53 m_data_stream(nullptr),
55 m_data_stream_cs(nullptr),
56 m_data_stream_is_external(false),
60 m_raw_dump_file_prefix(),
63 m_sensorLabelAppendMsgType(true),
64 m_GPS_comsWork(false),
66 m_custom_cmds_delay(0.1),
67 m_custom_cmds_append_CRLF(true),
69 m_JAVAD_rtk_src_port(),
70 m_JAVAD_rtk_src_baud(0),
71 m_JAVAD_rtk_format(
"cmr"),
72 m_topcon_useAIMMode(false),
73 m_topcon_AIMConfigured(false),
74 m_topcon_data_period(0.2)
87 iniSection,
"parser",
m_parser,
false );
116 for (
int i = 1;
true; i++)
121 if (sLine.empty())
break;
126 for (
int i = 1;
true; i++)
131 if (sLine.empty())
break;
136 configSource.
read_float(iniSection,
"pose_x", 0),
137 configSource.
read_float(iniSection,
"pose_y", 0),
138 configSource.
read_float(iniSection,
"pose_z", 0),
227 "Cannot change serial port name: an external stream has been " 228 "already bound manually.")
234 if (serial && serial->isOpen())
236 "Cannot change serial port name when it is already open")
265 if (serial->isOpen())
return true;
268 cout <<
"[CGPSInterface] Opening " <<
m_COMname <<
" @ " 276 serial->setTimeouts(1, 0, 1, 1, 1);
286 catch (std::exception& e)
288 std::cerr <<
"[CGPSInterface::tryToOpenTheCOM] Error opening or " 289 "configuring serial port:" 322 const size_t to_read =
332 nRead = stream_tcpip->
readAsync(buf, to_read, 100, 10);
334 else if (stream_serial)
336 nRead = stream_serial->
Read(buf, to_read);
353 string sFilePostfix =
"_";
355 "%04u-%02u-%02u_%02uh%02um%02us", (
unsigned int)parts.
year,
356 (
unsigned int)parts.
month, (
unsigned int)parts.
day,
357 (
unsigned int)parts.
hour, (
unsigned int)parts.
minute,
358 (
unsigned int)parts.
second);
359 const string sFileName =
365 std::cout <<
"[CGPSInterface] Creating RAW dump file: `" 366 << sFileName <<
"`\n";
374 catch (std::exception&)
378 "[CGPSInterface::doProcess] Error reading stream of data: Closing " 383 stream_serial->
close();
395 bool do_append_obs =
false;
405 cout <<
"[CGPSInterface] Initial timestamp: " 413 if (tdif >= 0 && tdif < 7500 )
418 cout <<
"[CGPSInterface] Warning: The initial timestamp " 419 "seems to be wrong! : " 427 if (time_diff < 0 || time_diff > 300)
434 cout <<
"[CGPSInterface ] Bad timestamp difference" << endl;
441 cout <<
"[CGPSInterface] WARNING: According to the " 442 "timestamps, we probably skipped one frame!" 500 throw std::runtime_error(
"[CGPSInterface] Unknown parser!");
508 if (!(*this.*parser_ptr)(min_bytes))
521 const std::list<CGPSInterface::ptr_parser_t>& all_parsers =
524 size_t global_min_bytes_max = 0;
527 bool all_parsers_want_to_skip =
true;
530 it != all_parsers.end(); ++it)
533 size_t this_parser_min_bytes;
534 if ((*this.*parser_ptr)(this_parser_min_bytes))
535 all_parsers_want_to_skip =
false;
555 const size_t len = strlen(str);
557 if (!stream_serial)
return;
563 written = stream_serial->
Write(str,
len);
566 if (
m_verbose) std::cout <<
"[CGPSInterface] TX: " << str;
569 throw std::runtime_error(
570 format(
"Error sending command: '%s'", str).c_str());
571 std::this_thread::sleep_for(5ms);
573 if (!waitForAnswer)
return;
575 std::this_thread::sleep_for(200ms);
580 while (bad_counter < 10)
585 written = stream_serial->
Write(str,
len);
586 nRead = stream_serial->
Read(buf,
sizeof(buf));
589 if (
m_verbose) std::cout <<
"[CGPSInterface] RX: " << buf << std::endl;
592 throw std::runtime_error(
594 "ERROR: Invalid response '%s' for command '%s'", buf, str));
596 if (nRead >= 3 && buf[0] ==
'R' && buf[1] ==
'E')
601 throw std::runtime_error(
602 format(
"ERROR: Invalid response '%s' for command '%s'", buf, str));
609 if (stream_serial && !stream_serial->
isOpen())
return false;
615 cout <<
"[CGPSInterface] TX shutdown command: `" 630 std::this_thread::sleep_for(
631 std::chrono::duration<double, std::milli>(
667 cout <<
"[CGPSInterface] TX setup command: `" <<
m_setup_cmds[i]
678 catch (std::exception& e)
680 std::cerr <<
"[CGPSInterface::OnConnectionEstablished] Error " 681 "sending setup cmds: " 682 << e.what() << std::endl;
685 std::this_thread::sleep_for(
686 std::chrono::duration<double, std::milli>(
689 std::this_thread::sleep_for(
702 std::this_thread::sleep_for(500ms);
704 std::this_thread::sleep_for(1000ms);
735 "%%set,/par/cur/term/jps/0,{nscmd,37,n,\"\"}\r\n");
748 "%%%%set,/par/cur/term/jps/1,{cmr,-1,y,%s}\r\n",
754 "%%%%set,/par%s/imode,cmr\r\n",
762 "%%%%set,/par/cur/term/jps/1,{rtcm,-1,y,%s}\r\n",
768 "%%%%set,/par%s/imode,rtcm\r\n",
776 "%%%%set,/par/cur/term/jps/1,{rtcm3,-1,y,%s}\r\n",
782 "%%%%set,/par%s/imode,rtcm3\r\n",
788 cout <<
"Unknown RTK corrections format. Only supported: CMR, RTCM " 816 std::this_thread::sleep_for(500ms);
818 std::this_thread::sleep_for(1000ms);
829 if (
m_verbose) cout <<
"[CGPSInterface] Configure RTK options" << endl;
833 const int elevation_mask = 5;
836 format(
"%%%%set,/par/lock/elm,%i\r\n", elevation_mask)
839 "%%set,/par/base/mode/,off\r\n");
849 "%%set,/par/pos/pd/qcheck,off\r\n");
851 "%%set,/par/pos/mode/cur,pd\r\n");
853 "%%set,/par/pos/pd/textr,10\r\n");
855 "%%set,/par/pos/pd/inuse,-1\r\n");
896 if (
m_verbose) cout <<
"[CGPSInterface] Using Advanced Input Mode";
898 if (
m_verbose) cout <<
"... done" << endl;
909 cout <<
"[CGPSInterface::OnConnectionEstablished] JAVAD/TopCon " 910 "commands sent successfully with AIM." 916 cout <<
"[CGPSInterface::OnConnectionEstablished] JAVAD/TopCon " 917 "commands sent successfully." 934 catch (std::exception& e)
936 std::cerr <<
"[CGPSInterface::sendCustomCommand] Error sending cmd: " 937 << e.what() << std::endl;
PARSERS getParser() const
size_t available() const
The maximum number of elements that can be written ("push") without rising an overflow error...
void timestampToParts(TTimeStamp t, TTimeParts &p, bool localTime=false)
Gets the individual parts of a date/time (days, hours, minutes, seconds) - UTC time or local time...
static const TParsersRegistry & getInstance()
PARSERS
Read about parser selection in the documentation for CGPSInterface.
A class capable of reading GPS/GNSS/GNSS+IMU receiver data, from a serial port or from any input stre...
double m_custom_cmds_delay
void JAVAD_sendMessage(const char *str, bool waitForAnswer=true)
Private auxiliary method.
void doProcess()
This method will be invoked at a minimum rate of "process_rate" (Hz)
void bindStream(mrpt::io::CStream *external_stream, std::mutex *csOptionalExternalStream=nullptr)
This enforces the use of a given user stream, instead of trying to open the serial port set in this c...
void appendObservation(const mrpt::serialization::CSerializable::Ptr &obj)
Like appendObservations() but for just one observation.
std::string read_string(const std::string §ion, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
A communications serial port built as an implementation of a utils::CStream.
poses::CPose3D m_sensorPose
#define THROW_EXCEPTION(msg)
bool isGPS_connected()
Returns true if communications work, i.e.
mrpt::obs::CObservationGPS m_just_parsed_messages
A private copy of the last received gps datum.
const std::vector< std::string > & getSetupCommands() const
bool m_sensorLabelAppendMsgType
bool OnConnectionShutdown()
Like OnConnectionEstablished() for sending optional shutdown commands.
std::string m_sensorLabel
See CGenericSensor.
double DEG2RAD(const double x)
Degrees to radians.
std::mutex * m_data_stream_cs
void swap(CObservationGPS &o)
virtual size_t Read(void *Buffer, size_t Count)=0
Introduces a pure virtual method responsible for reading from the stream.
message_list_t messages
The main piece of data in this class: a list of GNNS messages.
bool unsetJAVAD_AIM_mode()
Unset Advanced Input Mode for the primary port and use it only as a command port. ...
CGPSInterface()
Default ctor.
bool m_topcon_AIMConfigured
Indicates if the AIM has been properly set up.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Contains classes for various device interfaces.
bool(CGPSInterface::*)(size_t &out_minimum_rx_buf_to_decide) ptr_parser_t
bool strCmp(const std::string &s1, const std::string &s2)
Return true if the two strings are equal (case sensitive)
float read_float(const std::string §ion, const std::string &name, float defaultValue, bool failIfNotFound=false) const
void enableSetupCommandsAppendCRLF(const bool enable)
std::string timeToString(const mrpt::system::TTimeStamp t)
Convert a timestamp into this textual form (UTC): HH:MM:SS.MMMMMM.
void parseBuffer()
Process data in "m_buffer" to extract GPS messages, and remove them from the buffer.
std::string fileNameStripInvalidChars(const std::string &filename, const char replacement_to_invalid_chars='_')
Replace invalid filename chars by underscores ('_') or any other user-given char. ...
bool sendCustomCommand(const void *data, const size_t datalen)
Send a custom data block to the GNSS device right now.
std::string m_raw_dump_file_prefix
bool tryToOpenTheCOM()
Returns true if the COM port is already open, or try to open it in other case.
unsigned int m_JAVAD_rtk_src_baud
Only used when "m_JAVAD_rtk_src_port" is not empty.
std::string m_JAVAD_rtk_src_port
If not empty, will send a cmd "set,/par/pos/pd/port,...".
std::list< CGPSInterface::ptr_parser_t > all_parsers
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
bool isEnabledSetupCommandsAppendCRLF() const
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
ENUMTYPE read_enum(const std::string §ion, const std::string &name, const ENUMTYPE &defaultValue, bool failIfNotFound=false) const
Reads an "enum" value, where the value in the config file can be either a numerical value or the symb...
#define ASSERT_(f)
Defines an assertion mechanism.
mrpt::Clock::time_point TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
This class allows loading and storing values and vectors of different types from a configuration text...
T pop()
Retrieve an element from the buffer.
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
internal_msg_test_proxy< gnss::NMEA_RMC > has_RMC_datum
Evaluates as a bool; true if the corresponding field exists in messages.
bool implement_parser_NMEA(size_t &out_minimum_rx_buf_to_decide)
Versatile class for consistent logging and management of output messages.
The parts of a date/time (it's like the standard 'tm' but with fractions of seconds).
void setSetupCommands(const std::vector< std::string > &cmds)
bool isOpen() const
Returns if port has been correctly open.
void setSetupCommandsDelay(const double delay_secs)
This namespace contains representation of robot actions and observations.
size_t Write(const void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for writing to the stream.
std::string m_JAVAD_rtk_format
Only used when "m_JAVAD_rtk_src_port" is not empty: format of RTK corrections: "cmr", "rtcm", "rtcm3", etc.
bool implement_parser_NOVATEL_OEM6(size_t &out_minimum_rx_buf_to_decide)
void loadConfig_sensorSpecific(const mrpt::config::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
double read_double(const std::string §ion, const std::string &name, double defaultValue, bool failIfNotFound=false) const
virtual ~CGPSInterface()
Dtor.
void purgeBuffers()
Purge tx and rx buffers.
GLsizei const GLchar ** string
bool OnConnectionEstablished()
Implements custom messages to be sent to the GPS unit just after connection and before normal use...
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
size_t size() const
Return the number of elements available for read ("pop") in the buffer (this is NOT the maximum size ...
void close()
Close the port.
std::vector< std::string > m_setup_cmds
void clear()
Empties this observation, clearing the container messages.
bool fileOpenCorrectly() const
Returns true if the file was open without errors.
bool m_custom_cmds_append_CRLF
bool m_data_stream_is_external
bool open(const std::string &fileName, bool append=false)
Open the given file for write.
double second
Minute (0-59)
std::string getSerialPortName() const
Get the serial port to use (COM1, ttyUSB0, etc).
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp.
uint8_t minute
Hour (0-23)
mrpt::io::CFileOutputStream m_raw_output_file
internal_msg_test_proxy< gnss::NMEA_GGA > has_GGA_datum
Evaluates as a bool; true if the corresponding field exists in messages.
mrpt::poses::CPose3D sensorPose
The sensor pose on the robot/vehicle.
#define MRPT_LOG_ERROR(_STRING)
virtual size_t Write(const void *Buffer, size_t Count)=0
Introduces a pure virtual method responsible for writing to the stream.
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
bool setJAVAD_AIM_mode()
Set Advanced Input Mode for the primary port.
size_t Write(const void *Buffer, size_t Count) override
Introduces a pure virtual method responsible for writing to the stream.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
void setFromValues(const double x0, const double y0, const double z0, const double yaw=0, const double pitch=0, const double roll=0)
Set the pose from a 3D position (meters) and yaw/pitch/roll angles (radians) - This method recomputes...
bool legacy_topcon_setup_commands()
A TCP socket that can be connected to a TCP server, implementing MRPT's CStream interface for passing...
mrpt::io::CStream * m_data_stream
Typically a CSerialPort created by this class, but may be set externally.
std::mutex m_data_stream_mine_cs
std::string getLastGGA(bool reset=true)
Gets the latest GGA command or an empty string if no newer GGA command was received since the last ca...
std::string trim(const std::string &str)
Removes leading and trailing spaces.
void push_many(T *array_elements, size_t count)
Insert an array of elements in the buffer.
double m_topcon_data_period
The period in seconds which the data should be provided by the GPS.
mrpt::containers::circular_buffer< uint8_t > m_rx_buffer
Auxiliary buffer for readings.
double timeDifference(const mrpt::system::TTimeStamp t_first, const mrpt::system::TTimeStamp t_later)
Returns the time difference from t1 to t2 (positive if t2 is posterior to t1), in seconds...
Serial and networking devices and utilities.
mrpt::system::TTimeStamp m_last_timestamp
size_t readAsync(void *Buffer, const size_t Count, const int timeoutStart_ms=-1, const int timeoutBetween_ms=-1)
A method for reading from the socket with an optional timeout.
std::vector< std::string > m_shutdown_cmds
GLsizei GLsizei GLenum GLenum const GLvoid * data
std::string m_last_GGA
Used in getLastGGA()
size_t Read(void *Buffer, size_t Count)
Implements the virtual method responsible for reading from the stream - Unlike CStream::ReadBuffer, this method will not raise an exception on zero bytes read, as long as there is not any fatal error in the communications.
bool m_topcon_useAIMMode
Use this mode for receive RTK corrections from a external source through the primary port...
void flushParsedMessagesNow()
Queue out now the messages in m_just_parsed_messages, leaving it empty.
const Scalar * const_iterator
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
void setSerialPortName(const std::string &COM_port)
Set the serial port to use (COM1, ttyUSB0, etc).
void setParser(PARSERS parser)
Select the parser for incomming data, among the options enumerated in CGPSInterface.
const std::vector< std::string > & getShutdownCommands() const
double getSetupCommandsDelay() const
void setShutdownCommands(const std::vector< std::string > &cmds)
int _strcmpi(const char *str1, const char *str2) noexcept
An OS-independent version of strcmpi.