52 :
mrpt::utils::COutputLogger(
"CGPSInterface"),
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 );
92 #ifdef MRPT_OS_WINDOWS 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")
263 if (serial->isOpen())
return true;
266 cout <<
"[CGPSInterface] Opening " <<
m_COMname <<
" @ " 274 serial->setTimeouts(1, 0, 1, 1, 1);
284 catch (std::exception& e)
286 std::cerr <<
"[CGPSInterface::tryToOpenTheCOM] Error opening or " 287 "configuring serial port:" 320 const size_t to_read =
330 nRead = stream_tcpip->
readAsync(buf, to_read, 100, 10);
332 else if (stream_serial)
334 nRead = stream_serial->
Read(buf, to_read);
351 string sFilePostfix =
"_";
353 "%04u-%02u-%02u_%02uh%02um%02us", (
unsigned int)parts.
year,
354 (
unsigned int)parts.
month, (
unsigned int)parts.
day,
355 (
unsigned int)parts.
hour, (
unsigned int)parts.
minute,
356 (
unsigned int)parts.
second);
357 const string sFileName =
363 std::cout <<
"[CGPSInterface] Creating RAW dump file: `" 364 << sFileName <<
"`\n";
372 catch (std::exception&)
376 "[CGPSInterface::doProcess] Error reading stream of data: Closing " 381 stream_serial->
close();
393 bool do_append_obs =
false;
403 cout <<
"[CGPSInterface] Initial timestamp: " 411 if (tdif >= 0 && tdif < 7500 )
416 cout <<
"[CGPSInterface] Warning: The initial timestamp " 417 "seems to be wrong! : " 425 if (time_diff < 0 || time_diff > 300)
432 cout <<
"[CGPSInterface ] Bad timestamp difference" << endl;
439 cout <<
"[CGPSInterface] WARNING: According to the " 440 "timestamps, we probably skipped one frame!" 498 throw std::runtime_error(
"[CGPSInterface] Unknown parser!");
506 if (!(*this.*parser_ptr)(min_bytes))
518 const std::list<CGPSInterface::ptr_parser_t>& all_parsers =
521 size_t global_min_bytes_max = 0;
524 bool all_parsers_want_to_skip =
true;
527 it != all_parsers.end(); ++it)
530 size_t this_parser_min_bytes;
531 if ((*this.*parser_ptr)(this_parser_min_bytes))
532 all_parsers_want_to_skip =
false;
534 global_min_bytes_max, this_parser_min_bytes);
537 if (all_parsers_want_to_skip)
553 const size_t len = strlen(str);
555 if (!stream_serial)
return;
561 written = stream_serial->
Write(str,
len);
564 if (
m_verbose) std::cout <<
"[CGPSInterface] TX: " << str;
567 throw std::runtime_error(
568 format(
"Error sending command: '%s'", str).c_str());
569 std::this_thread::sleep_for(5ms);
571 if (!waitForAnswer)
return;
573 std::this_thread::sleep_for(200ms);
578 while (bad_counter < 10)
583 written = stream_serial->
Write(str,
len);
584 nRead = stream_serial->
Read(buf,
sizeof(buf));
587 if (
m_verbose) std::cout <<
"[CGPSInterface] RX: " << buf << std::endl;
590 throw std::runtime_error(
592 "ERROR: Invalid response '%s' for command '%s'", buf, str));
594 if (nRead >= 3 && buf[0] ==
'R' && buf[1] ==
'E')
599 throw std::runtime_error(
600 format(
"ERROR: Invalid response '%s' for command '%s'", buf, str));
607 if (stream_serial && !stream_serial->
isOpen())
return false;
613 cout <<
"[CGPSInterface] TX shutdown command: `" 628 std::this_thread::sleep_for(
629 std::chrono::duration<double, std::milli>(
665 cout <<
"[CGPSInterface] TX setup command: `" <<
m_setup_cmds[i]
676 catch (std::exception& e)
678 std::cerr <<
"[CGPSInterface::OnConnectionEstablished] Error " 679 "sending setup cmds: " 680 << e.what() << std::endl;
683 std::this_thread::sleep_for(
684 std::chrono::duration<double, std::milli>(
687 std::this_thread::sleep_for(
700 std::this_thread::sleep_for(500ms);
702 std::this_thread::sleep_for(1000ms);
733 "%%set,/par/cur/term/jps/0,{nscmd,37,n,\"\"}\r\n");
746 "%%%%set,/par/cur/term/jps/1,{cmr,-1,y,%s}\r\n",
752 "%%%%set,/par%s/imode,cmr\r\n",
760 "%%%%set,/par/cur/term/jps/1,{rtcm,-1,y,%s}\r\n",
766 "%%%%set,/par%s/imode,rtcm\r\n",
774 "%%%%set,/par/cur/term/jps/1,{rtcm3,-1,y,%s}\r\n",
780 "%%%%set,/par%s/imode,rtcm3\r\n",
786 cout <<
"Unknown RTK corrections format. Only supported: CMR, RTCM " 814 std::this_thread::sleep_for(500ms);
816 std::this_thread::sleep_for(1000ms);
827 if (
m_verbose) cout <<
"[CGPSInterface] Configure RTK options" << endl;
831 const int elevation_mask = 5;
834 format(
"%%%%set,/par/lock/elm,%i\r\n", elevation_mask)
837 "%%set,/par/base/mode/,off\r\n");
847 "%%set,/par/pos/pd/qcheck,off\r\n");
849 "%%set,/par/pos/mode/cur,pd\r\n");
851 "%%set,/par/pos/pd/textr,10\r\n");
853 "%%set,/par/pos/pd/inuse,-1\r\n");
894 if (
m_verbose) cout <<
"[CGPSInterface] Using Advanced Input Mode";
896 if (
m_verbose) cout <<
"... done" << endl;
907 cout <<
"[CGPSInterface::OnConnectionEstablished] JAVAD/TopCon " 908 "commands sent successfully with AIM." 914 cout <<
"[CGPSInterface::OnConnectionEstablished] JAVAD/TopCon " 915 "commands sent successfully." 932 catch (std::exception& e)
934 std::cerr <<
"[CGPSInterface::sendCustomCommand] Error sending cmd: " 935 << e.what() << std::endl;
uint64_t TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
bool fileOpenCorrectly()
Returns true if the file was open without errors.
size_t Write(const void *Buffer, size_t Count)
Implements the virtual method responsible for writing to the stream.
PARSERS getParser() const
size_t ReadBuffer(void *Buffer, size_t Count)
Reads a block of bytes from the stream into Buffer.
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()
mrpt::utils::CStream * m_data_stream
Typically a CSerialPort created by this class, but may be set externally.
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
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
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)
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
A communications serial port built as an implementation of a utils::CStream.
poses::CPose3D m_sensorPose
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
float read_float(const std::string §ion, const std::string &name, float defaultValue, bool failIfNotFound=false) const
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.
size_t available() const
The maximum number of elements that can be written ("push") without rising an overflow error...
std::mutex * m_data_stream_cs
#define THROW_EXCEPTION(msg)
void swap(CObservationGPS &o)
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. ...
size_t size() const
Return the number of elements available for read ("pop") in the buffer (this is NOT the maximum size ...
void bindStream(mrpt::utils::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...
CGPSInterface()
Default ctor.
void WriteBuffer(const void *Buffer, size_t Count)
Writes a block of bytes to the stream from Buffer.
bool m_topcon_AIMConfigured
Indicates if the AIM has been properly set up.
bool open(const std::string &fileName, bool append=false)
Open the given file for write.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Contains classes for various device interfaces.
bool(CGPSInterface::* ptr_parser_t)(size_t &out_minimum_rx_buf_to_decide)
bool strCmp(const std::string &s1, const std::string &s2)
Return true if the two strings are equal (case sensitive)
std::string read_string(const std::string §ion, const std::string &name, const std::string &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.
const Scalar * const_iterator
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
bool isEnabledSetupCommandsAppendCRLF() const
This class allows loading and storing values and vectors of different types from a configuration text...
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
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)
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.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
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)
virtual ~CGPSInterface()
Dtor.
void purgeBuffers()
Purge tx and rx buffers.
mrpt::utils::circular_buffer< uint8_t > m_rx_buffer
Auxiliary buffer for readings.
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:
void close()
Close the port.
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...
std::vector< std::string > m_setup_cmds
void appendObservation(const mrpt::utils::CSerializable::Ptr &obj)
Like appendObservations() but for just one observation.
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
T pop()
Retrieve an element from the buffer.
void clear()
Empties this observation, clearing the container messages.
bool m_custom_cmds_append_CRLF
bool m_data_stream_is_external
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)
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.
bool setJAVAD_AIM_mode()
Set Advanced Input Mode for the primary port.
double read_double(const std::string §ion, const std::string &name, double defaultValue, bool failIfNotFound=false) const
mrpt::utils::CFileOutputStream m_raw_output_file
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...
std::shared_ptr< CObservationGPS > Ptr
void loadConfig_sensorSpecific(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
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.
#define MRPT_LOG_ERROR(_STRING)
double m_topcon_data_period
The period in seconds which the data should be provided by the GPS.
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
void push_many(T *array_elements, size_t count)
Insert an array of elements in the buffer.
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.
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...
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.