50 mrpt::utils::COutputLogger(
"CGPSInterface"),
52 m_data_stream_cs(NULL),
53 m_data_stream_is_external(false),
55 m_rx_buffer (0x10000),
57 m_raw_dump_file_prefix(),
60 m_sensorLabelAppendMsgType (true),
61 m_GPS_comsWork (false),
63 m_custom_cmds_delay (0.1),
64 m_custom_cmds_append_CRLF(true),
66 m_JAVAD_rtk_src_port (),
67 m_JAVAD_rtk_src_baud (0),
68 m_JAVAD_rtk_format (
"cmr"),
69 m_topcon_useAIMMode ( false ),
70 m_topcon_AIMConfigured ( false ),
71 m_topcon_data_period ( 0.2 )
86 #ifdef MRPT_OS_WINDOWS
103 for (
int i=1;
true; i++)
113 for (
int i=1;
true; i++)
123 configSource.
read_float(iniSection,
"pose_x",0),
124 configSource.
read_float(iniSection,
"pose_y",0),
125 configSource.
read_float(iniSection,
"pose_z",0),
199 THROW_EXCEPTION(
"Cannot change serial port name: an external stream has been already bound manually.")
205 if (serial && serial->
isOpen())
206 THROW_EXCEPTION(
"Cannot change serial port name when it is already open")
257 catch (std::exception &e)
259 std::cerr <<
"[CGPSInterface::tryToOpenTheCOM] Error opening or configuring serial port:" << std::endl << e.what();
300 nRead = stream_tcpip->
readAsync( buf, to_read, 100, 10 );
302 else if (stream_serial) {
303 nRead = stream_serial->
Read(buf,to_read);
317 string sFilePostfix =
"_";
318 sFilePostfix +=
format(
"%04u-%02u-%02u_%02uh%02um%02us",(
unsigned int)parts.
year, (
unsigned int)parts.
month, (
unsigned int)parts.
day, (
unsigned int)parts.
hour, (
unsigned int)parts.
minute, (
unsigned int)parts.
second );
321 if (
m_verbose) std::cout <<
"[CGPSInterface] Creating RAW dump file: `" << sFileName <<
"`\n";
328 catch (std::exception &)
331 MRPT_LOG_ERROR(
"[CGPSInterface::doProcess] Error reading stream of data: Closing communications\n");
334 stream_serial->
close();
346 bool do_append_obs =
false;
358 if( tdif >= 0 && tdif < 7500 )
361 {
if (
m_verbose) cout <<
"[CGPSInterface] Warning: The initial timestamp seems to be wrong! : " << tdif << endl;}
366 if( time_diff < 0 || time_diff > 300 )
367 {
if (
m_verbose) cout <<
"[CGPSInterface ] Bad timestamp difference" << endl;
return; }
370 {
if (
m_verbose) cout <<
"[CGPSInterface] WARNING: According to the timestamps, we probably skipped one frame!" << endl; }
392 CObservationGPSPtr newObs = CObservationGPS::Create();
418 throw std::runtime_error(
"[CGPSInterface] Unknown parser!");
426 if (!(*this.*parser_ptr)(min_bytes))
439 size_t global_min_bytes_max=0;
442 bool all_parsers_want_to_skip =
true;
446 size_t this_parser_min_bytes;
447 if ((*this.*parser_ptr)(this_parser_min_bytes))
448 all_parsers_want_to_skip =
false;
452 if (all_parsers_want_to_skip)
467 const size_t len = strlen(str);
469 if (!stream_serial)
return;
475 written = stream_serial->
Write(str,
len);
479 std::cout <<
"[CGPSInterface] TX: " << str;
482 throw std::runtime_error(
format(
"Error sending command: '%s'",str).c_str());
485 if (!waitForAnswer)
return;
492 while(bad_counter < 10)
497 written = stream_serial->
Write(str,
len);
498 nRead = stream_serial->
Read(buf,
sizeof(buf));
502 std::cout <<
"[CGPSInterface] RX: " << buf << std::endl;
505 throw std::runtime_error(
format(
"ERROR: Invalid response '%s' for command '%s'",buf,str));
507 if (nRead>=3 && buf[0]==
'R' && buf[1]==
'E')
512 throw std::runtime_error(
format(
"ERROR: Invalid response '%s' for command '%s'",buf,str));
519 if (stream_serial && !stream_serial->
isOpen())
526 cout <<
"[CGPSInterface] TX shutdown command: `" <<
m_shutdown_cmds[i] <<
"`\n";
571 cout <<
"[CGPSInterface] TX setup command: `" <<
m_setup_cmds[i] <<
"`\n";
580 }
catch (std::exception &e) {
581 std::cerr <<
"[CGPSInterface::OnConnectionEstablished] Error sending setup cmds: " << e.what() << std::endl;
647 cout <<
"Unknown RTK corrections format. Only supported: CMR, RTCM or RTCM3" << endl;
685 cout <<
"[CGPSInterface] Configure RTK options" << endl;
689 const int elevation_mask = 5;
722 if (
m_verbose) cout <<
"[CGPSInterface] Using Advanced Input Mode";
724 if (
m_verbose) cout <<
"... done" << endl;
730 {
if (
m_verbose) cout <<
"[CGPSInterface::OnConnectionEstablished] JAVAD/TopCon commands sent successfully with AIM." << endl;}
732 {
if (
m_verbose) cout <<
"[CGPSInterface::OnConnectionEstablished] JAVAD/TopCon commands sent successfully." << endl;}
746 catch (std::exception &e)
748 std::cerr <<
"[CGPSInterface::sendCustomCommand] Error sending cmd: " << e.what() << std::endl;
#define IMPLEMENTS_GENERIC_SENSOR(class_name, NameSpace)
This must be inserted in all CGenericSensor classes implementation files:
#define MRPT_LOG_ERROR(_STRING)
A class capable of reading GPS/GNSS/GNSS+IMU receiver data, from a serial port or from any input stre...
bool isGPS_connected()
Returns true if communications work, i.e. if some message has been received.
void bindStream(mrpt::utils::CStream *external_stream, mrpt::synch::CCriticalSection *csOptionalExternalStream=NULL)
This enforces the use of a given user stream, instead of trying to open the serial port set in this c...
std::string m_last_GGA
Used in getLastGGA()
std::string m_JAVAD_rtk_format
Only used when "m_JAVAD_rtk_src_port" is not empty: format of RTK corrections: "cmr",...
bool OnConnectionEstablished()
Implements custom messages to be sent to the GPS unit just after connection and before normal use.
mrpt::utils::CFileOutputStream m_raw_output_file
unsigned int m_JAVAD_rtk_src_baud
Only used when "m_JAVAD_rtk_src_port" is not empty.
void setShutdownCommands(const std::vector< std::string > &cmds)
virtual ~CGPSInterface()
Dtor.
double m_topcon_data_period
The period in seconds which the data should be provided by the GPS.
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::vector< std::string > m_shutdown_cmds
bool sendCustomCommand(const void *data, const size_t datalen)
Send a custom data block to the GNSS device right now.
mrpt::system::TTimeStamp m_last_timestamp
void setSetupCommands(const std::vector< std::string > &cmds)
bool implement_parser_NMEA(size_t &out_minimum_rx_buf_to_decide)
void parseBuffer()
Process data in "m_buffer" to extract GPS messages, and remove them from the buffer.
bool setJAVAD_AIM_mode()
Set Advanced Input Mode for the primary port.
void setSerialPortName(const std::string &COM_port)
Set the serial port to use (COM1, ttyUSB0, etc).
bool implement_parser_NOVATEL_OEM6(size_t &out_minimum_rx_buf_to_decide)
mrpt::synch::CCriticalSection * m_data_stream_cs
std::string getSerialPortName() const
Get the serial port to use (COM1, ttyUSB0, etc).
mrpt::utils::CStream * m_data_stream
Typically a CSerialPort created by this class, but may be set externally.
bool(CGPSInterface::* ptr_parser_t)(size_t &out_minimum_rx_buf_to_decide)
CGPSInterface()
Default ctor.
poses::CPose3D m_sensorPose
bool isEnabledSetupCommandsAppendCRLF() const
bool tryToOpenTheCOM()
Returns true if the COM port is already open, or try to open it in other case.
void enableSetupCommandsAppendCRLF(const bool enable)
bool m_data_stream_is_external
mrpt::obs::CObservationGPS m_just_parsed_messages
A private copy of the last received gps datum.
PARSERS getParser() const
double getSetupCommandsDelay() const
bool m_sensorLabelAppendMsgType
bool m_topcon_AIMConfigured
Indicates if the AIM has been properly set up.
std::string m_JAVAD_rtk_src_port
If not empty, will send a cmd "set,/par/pos/pd/port,...". Example value: "/dev/ser/b".
void setSetupCommandsDelay(const double delay_secs)
bool m_custom_cmds_append_CRLF
void setParser(PARSERS parser)
Select the parser for incomming data, among the options enumerated in CGPSInterface.
void flushParsedMessagesNow()
Queue out now the messages in m_just_parsed_messages, leaving it empty.
bool m_topcon_useAIMMode
Use this mode for receive RTK corrections from a external source through the primary port.
void doProcess()
Queue out now the messages in m_just_parsed_messages, leaving it empty.
bool OnConnectionShutdown()
Like OnConnectionEstablished() for sending optional shutdown commands.
PARSERS
Read about parser selection in the documentation for CGPSInterface.
bool unsetJAVAD_AIM_mode()
Unset Advanced Input Mode for the primary port and use it only as a command port.
bool legacy_topcon_setup_commands()
double m_custom_cmds_delay
std::string m_raw_dump_file_prefix
void loadConfig_sensorSpecific(const mrpt::utils::CConfigFileBase &configSource, const std::string &iniSection)
See the class documentation at the top for expected parameters.
const std::vector< std::string > & getShutdownCommands() const
void JAVAD_sendMessage(const char *str, bool waitForAnswer=true)
Private auxiliary method. Raises exception on error.
mrpt::utils::circular_buffer< uint8_t > m_rx_buffer
Auxiliary buffer for readings.
const std::vector< std::string > & getSetupCommands() const
std::vector< std::string > m_setup_cmds
void appendObservation(const mrpt::utils::CSerializablePtr &obj)
Like appendObservations() but for just one observation.
std::string m_sensorLabel
See CGenericSensor.
A communications serial port built as an implementation of a utils::CStream.
bool isOpen() const
Returns if port has been correctly open.
void open()
Open the port.
void setConfig(int baudRate, int parity=0, int bits=8, int nStopBits=1, bool enableFlowControl=false)
Changes the configuration of the port.
size_t Write(const void *Buffer, size_t Count)
Implements the virtual method responsible for writing to the stream.
size_t Read(void *Buffer, size_t Count)
Implements the virtual method responsible for reading from the stream - Unlike CStream::ReadBuffer,...
void purgeBuffers()
Purge tx and rx buffers.
void close()
Close the port.
void setTimeouts(int ReadIntervalTimeout, int ReadTotalTimeoutMultiplier, int ReadTotalTimeoutConstant, int WriteTotalTimeoutMultiplier, int WriteTotalTimeoutConstant)
Changes the timeouts of the port, in milliseconds.
internal_msg_test_proxy< gnss::NMEA_RMC > has_RMC_datum
Evaluates as a bool; true if the corresponding field exists in messages.
mrpt::poses::CPose3D sensorPose
The sensor pose on the robot/vehicle.
void swap(CObservationGPS &o)
message_list_t messages
The main piece of data in this class: a list of GNNS messages.
void clear()
Empties this observation, clearing the container messages.
internal_msg_test_proxy< gnss::NMEA_GGA > has_GGA_datum
Evaluates as a bool; true if the corresponding field exists in messages.
std::string sensorLabel
An arbitrary label that can be used to identify the sensor.
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp. Where available, this should contain the accurate satellite-based time...
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...
This class provides simple critical sections functionality.
A class acquiring a CCriticalSection at its constructor, and releasing it at destructor.
A TCP socket that can be connected to a TCP server, implementing MRPT's CStream interface for passing...
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.
This class allows loading and storing values and vectors of different types from a configuration text...
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...
bool read_bool(const std::string §ion, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
double read_double(const std::string §ion, const std::string &name, double defaultValue, bool failIfNotFound=false) const
std::string read_string(const std::string §ion, const std::string &name, const std::string &defaultValue, bool failIfNotFound=false) const
int read_int(const std::string §ion, const std::string &name, int defaultValue, bool failIfNotFound=false) const
float read_float(const std::string §ion, const std::string &name, float defaultValue, bool failIfNotFound=false) const
bool fileOpenCorrectly()
Returns true if the file was open without errors.
bool open(const std::string &fileName, bool append=false)
Open the given file for write.
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
void WriteBuffer(const void *Buffer, size_t Count)
Writes a block of bytes to the stream from Buffer.
size_t ReadBuffer(void *Buffer, size_t Count)
Reads a block of bytes from the stream into Buffer.
size_t size() const
Return the number of elements available for read ("pop") in the buffer (this is NOT the maximum size ...
size_t available() const
The maximum number of elements that can be written ("push") without rising an overflow error.
T pop()
Retrieve an element from the buffer.
void push_many(T *array_elements, size_t count)
Insert an array of elements in the buffer.
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
const Scalar * const_iterator
GLsizei GLsizei GLenum GLenum const GLvoid * data
GLsizei const GLchar ** string
std::string BASE_IMPEXP fileNameStripInvalidChars(const std::string &filename, const char replacement_to_invalid_chars='_')
Replace invalid filename chars by underscores ('_') or any other user-given char.
int BASE_IMPEXP _strcmpi(const char *str1, const char *str2) MRPT_NO_THROWS
An OS-independent version of strcmpi.
void BASE_IMPEXP sleep(int time_ms) MRPT_NO_THROWS
An OS-independent method for sending the current thread to "sleep" for a given period of time.
std::string BASE_IMPEXP trim(const std::string &str)
Removes leading and trailing spaces.
bool BASE_IMPEXP strCmp(const std::string &s1, const std::string &s2)
Return true if the two strings are equal (case sensitive)
uint64_t TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1,...
std::string BASE_IMPEXP timeToString(const mrpt::system::TTimeStamp t)
Convert a timestamp into this textual form (UTC): HH:MM:SS.MMMMMM.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
double BASE_IMPEXP 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.
void BASE_IMPEXP 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.
int const JOCTET unsigned int datalen
#define THROW_EXCEPTION(msg)
Contains classes for various device interfaces.
This namespace contains representation of robot actions and observations.
This namespace provides multitask, synchronization utilities.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation,...
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
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.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
static const TParsersRegistry & getInstance()
std::list< CGPSInterface::ptr_parser_t > all_parsers
The parts of a date/time (it's like the standard 'tm' but with fractions of seconds).
uint8_t minute
Hour (0-23)
double second
Minute (0-59)