MRPT  1.9.9
CObservationGPS.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "obs-precomp.h" // Precompiled headers
11 
14 #include <mrpt/math/matrix_serialization.h> // for << of matrices
15 #include <iomanip>
16 
17 using namespace std;
18 using namespace mrpt;
19 using namespace mrpt::obs;
20 using namespace mrpt::math;
21 
22 // This must be added to any CSerializable class implementation file.
24 
26 {
27  std::swap(timestamp, o.timestamp);
28  std::swap(originalReceivedTimestamp, o.originalReceivedTimestamp);
29  std::swap(has_satellite_timestamp, o.has_satellite_timestamp);
30  std::swap(sensorLabel, o.sensorLabel);
31  std::swap(sensorPose, o.sensorPose);
32  messages.swap(o.messages);
33 }
34 
35 uint8_t CObservationGPS::serializeGetVersion() const { return 11; }
36 void CObservationGPS::serializeTo(mrpt::serialization::CArchive& out) const
37 {
38  out << timestamp << originalReceivedTimestamp << sensorLabel << sensorPose;
39  out << has_satellite_timestamp; // v11
40 
41  const uint32_t nMsgs = messages.size();
42  out << nMsgs;
43  for (message_list_t::const_iterator it = messages.begin();
44  it != messages.end(); ++it)
45  it->second->writeToStream(out);
46 }
47 
48 void CObservationGPS::serializeFrom(
50 {
51  this->clear();
52 
53  switch (version)
54  {
55  case 10:
56  case 11:
57  {
58  in >> timestamp >> originalReceivedTimestamp >> sensorLabel >>
59  sensorPose;
60  if (version >= 11)
61  in >> has_satellite_timestamp; // v11
62  else
63  has_satellite_timestamp =
64  (this->timestamp != this->originalReceivedTimestamp);
65 
66  uint32_t nMsgs;
67  in >> nMsgs;
68  for (unsigned i = 0; i < nMsgs; i++)
69  {
70  gnss::gnss_message* msg =
71  gnss::gnss_message::readAndBuildFromStream(in);
72  messages[msg->message_type] = gnss::gnss_message_ptr(msg);
73  }
74  };
75  break;
76 
77  // OLD VERSIONS: Ensure we can load datasets from many years ago
78  // ==========
79  case 0:
80  {
81  bool has_GGA_datum_;
82  in >> has_GGA_datum_;
83  if (has_GGA_datum_)
84  {
86  in.ReadBuffer(&datum->fields, sizeof(datum->fields));
87  messages[gnss::NMEA_GGA] = gnss::gnss_message_ptr(datum);
88  }
89 
90  bool has_RMC_datum_;
91  in >> has_RMC_datum_;
92  if (has_RMC_datum_)
93  {
95  in.ReadBuffer(&datum->fields, sizeof(datum->fields));
96  messages[gnss::NMEA_RMC] = gnss::gnss_message_ptr(datum);
97  }
98  }
99  break;
100  case 1:
101  case 2:
102  case 3:
103  case 4:
104  case 5:
105  case 6:
106  case 7:
107  case 8:
108  case 9:
109  {
110  if (version >= 3)
111  in >> timestamp;
112  else
113  timestamp = INVALID_TIMESTAMP;
114 
115  bool has_GGA_datum_;
116  in >> has_GGA_datum_;
117  if (has_GGA_datum_)
118  {
120  gnss::Message_NMEA_GGA::content_t& GGA_datum = datum.fields;
121 
122  MRPT_READ_POD(in, GGA_datum.UTCTime.hour);
123  MRPT_READ_POD(in, GGA_datum.UTCTime.minute);
124  MRPT_READ_POD(in, GGA_datum.UTCTime.sec);
125  MRPT_READ_POD(in, GGA_datum.latitude_degrees);
126  MRPT_READ_POD(in, GGA_datum.longitude_degrees);
127  MRPT_READ_POD(in, GGA_datum.fix_quality);
128  MRPT_READ_POD(in, GGA_datum.altitude_meters);
129  if (version >= 9)
130  {
131  MRPT_READ_POD(in, GGA_datum.geoidal_distance);
134  }
135  else
136  {
137  GGA_datum.geoidal_distance = 0.0f;
138  GGA_datum.orthometric_altitude = 0.0f;
139  GGA_datum.corrected_orthometric_altitude = 0.0f;
140  }
141 
142  MRPT_READ_POD(in, GGA_datum.satellitesUsed);
143  MRPT_READ_POD(in, GGA_datum.thereis_HDOP);
144  MRPT_READ_POD(in, GGA_datum.HDOP);
145  this->setMsg(datum);
146  }
147 
148  bool has_RMC_datum_;
149  in >> has_RMC_datum_;
150  if (has_RMC_datum_)
151  {
153  gnss::Message_NMEA_RMC::content_t& RMC_datum = datum.fields;
154 
155  MRPT_READ_POD(in, RMC_datum.UTCTime.hour);
156  MRPT_READ_POD(in, RMC_datum.UTCTime.minute);
157  MRPT_READ_POD(in, RMC_datum.UTCTime.sec);
158  MRPT_READ_POD(in, RMC_datum.validity_char);
159  MRPT_READ_POD(in, RMC_datum.latitude_degrees);
160  MRPT_READ_POD(in, RMC_datum.longitude_degrees);
161  MRPT_READ_POD(in, RMC_datum.speed_knots);
162  MRPT_READ_POD(in, RMC_datum.direction_degrees);
163  this->setMsg(datum);
164  }
165  if (version > 1)
166  in >> sensorLabel;
167  else
168  sensorLabel = "";
169  if (version >= 4)
170  in >> sensorPose;
171  else
172  sensorPose.setFromValues(0, 0, 0, 0, 0, 0);
173  if (version >= 5)
174  {
175  bool has_PZS_datum_;
176  in >> has_PZS_datum_;
177  if (has_PZS_datum_)
178  {
179  gnss::Message_TOPCON_PZS* datum =
181  messages[gnss::TOPCON_PZS] = gnss::gnss_message_ptr(datum);
182  gnss::Message_TOPCON_PZS& PZS_datum = *datum;
183 
184  MRPT_READ_POD(in, PZS_datum.latitude_degrees);
185  MRPT_READ_POD(in, PZS_datum.longitude_degrees);
186  MRPT_READ_POD(in, PZS_datum.height_meters);
187  MRPT_READ_POD(in, PZS_datum.RTK_height_meters);
188  MRPT_READ_POD(in, PZS_datum.PSigma);
189  MRPT_READ_POD(in, PZS_datum.angle_transmitter);
190  MRPT_READ_POD(in, PZS_datum.nId);
191  MRPT_READ_POD(in, PZS_datum.Fix);
192  MRPT_READ_POD(in, PZS_datum.TXBattery);
193  MRPT_READ_POD(in, PZS_datum.RXBattery);
194  MRPT_READ_POD(in, PZS_datum.error);
195  // extra data?
196  if (version >= 6)
197  {
198  MRPT_READ_POD(in, PZS_datum.hasCartesianPosVel);
199  MRPT_READ_POD(in, PZS_datum.cartesian_x);
200  MRPT_READ_POD(in, PZS_datum.cartesian_y);
201  MRPT_READ_POD(in, PZS_datum.cartesian_z);
202  MRPT_READ_POD(in, PZS_datum.cartesian_vx);
203  MRPT_READ_POD(in, PZS_datum.cartesian_vy);
204  MRPT_READ_POD(in, PZS_datum.cartesian_vz);
205  MRPT_READ_POD(in, PZS_datum.hasPosCov);
206  MRPT_READ_POD(in, PZS_datum.pos_covariance);
207  MRPT_READ_POD(in, PZS_datum.hasVelCov);
208  MRPT_READ_POD(in, PZS_datum.vel_covariance);
209  MRPT_READ_POD(in, PZS_datum.hasStats);
212  if (version >= 8)
214  else
215  PZS_datum.stats_rtk_fix_progress = 0;
216  }
217  else
218  {
219  PZS_datum.hasCartesianPosVel = PZS_datum.hasPosCov =
220  PZS_datum.hasVelCov = PZS_datum.hasStats = false;
221  }
222  }
223  } // end version >=5
224 
225  // Added in V7:
226  if (version >= 7)
227  {
230  messages[gnss::TOPCON_SATS] = gnss::gnss_message_ptr(datum);
231  gnss::Message_TOPCON_SATS& SATS_datum = *datum;
232  bool has_SATS_datum_;
233  in >> has_SATS_datum_;
234  if (has_SATS_datum_)
235  {
236  MRPT_READ_POD(in, SATS_datum.USIs);
237  MRPT_READ_POD(in, SATS_datum.ELs);
238  MRPT_READ_POD(in, SATS_datum.AZs);
239  }
240  }
241  }
242  break;
243  default:
245  };
246 
247  if (originalReceivedTimestamp == INVALID_TIMESTAMP)
248  originalReceivedTimestamp = timestamp;
249 }
250 
251 void CObservationGPS::dumpToStream(std::ostream& out) const
252 {
253  out << "\n------------- [CObservationGPS] Dump of " << messages.size()
254  << " messages --------------------\n";
255  for (const auto& m : messages) m.second->dumpToStream(out);
256  out << "-------------- [CObservationGPS] End of dump -----------------\n\n";
257 }
258 
259 void CObservationGPS::dumpToConsole(std::ostream& o) const
260 {
261  this->dumpToStream(o);
262 }
263 
264 mrpt::system::TTimeStamp CObservationGPS::getOriginalReceivedTimeStamp() const
265 {
266  return originalReceivedTimestamp;
267 }
268 
270 {
271  messages.clear();
272  timestamp = INVALID_TIMESTAMP;
273  originalReceivedTimestamp = INVALID_TIMESTAMP;
274 }
275 void CObservationGPS::getDescriptionAsText(std::ostream& o) const
276 {
277  using namespace mrpt::system; // for the TTimeStamp << operator
278 
279  CObservation::getDescriptionAsText(o);
280 
281  o << "Timestamp (UTC) of reception at the computer: "
282  << mrpt::system::dateTimeToString(originalReceivedTimestamp) << std::endl;
283  o << " (as time_t): " << std::fixed << std::setprecision(5)
284  << mrpt::system::timestampTotime_t(originalReceivedTimestamp)
285  << std::endl;
286  o << " (as TTimestamp): " << originalReceivedTimestamp << std::endl;
287 
288  o << "Sensor position on the robot/vehicle: " << sensorPose << std::endl;
289 
290  this->dumpToConsole(o);
291 }
292 
293 bool CObservationGPS::hasMsgType(const gnss::gnss_message_type_t type_id) const
294 {
295  return messages.find(type_id) != messages.end();
296 }
297 
298 mrpt::obs::gnss::gnss_message* CObservationGPS::getMsgByType(
299  const gnss::gnss_message_type_t type_id)
300 {
301  message_list_t::iterator it = messages.find(type_id);
302  ASSERTMSG_(
303  it != messages.end(), mrpt::format(
304  "[CObservationGPS::getMsgByType] Cannot find "
305  "any observation of type `%u`",
306  static_cast<unsigned int>(type_id)));
307  return it->second.get();
308 }
309 /** \overload */
310 const mrpt::obs::gnss::gnss_message* CObservationGPS::getMsgByType(
311  const gnss::gnss_message_type_t type_id) const
312 {
313  message_list_t::const_iterator it = messages.find(type_id);
314  ASSERTMSG_(
315  it != messages.end(), mrpt::format(
316  "[CObservationGPS::getMsgByType] Cannot find "
317  "any observation of type `%u`",
318  static_cast<unsigned int>(type_id)));
319  return it->second.get();
320 }
321 
322 // From: http://gnsstk.sourceforge.net/time__conversion_8c-source.html
323 #define TIMECONV_JULIAN_DATE_START_OF_GPS_TIME (2444244.5) // [days]
325  const unsigned short gps_week, const double gps_tow,
326  const unsigned int utc_offset, double* julian_date)
327 {
328  if (gps_tow < 0.0 || gps_tow > 604800.0) return false;
329  // GPS time is ahead of UTC time and Julian time by the UTC offset
330  *julian_date = (gps_week + (gps_tow - utc_offset) / 604800.0) * 7.0 +
332  return true;
333 }
334 
335 bool TIMECONV_IsALeapYear(const unsigned short year)
336 {
337  bool is_a_leap_year = false;
338  if ((year % 4) == 0)
339  {
340  is_a_leap_year = true;
341  if ((year % 100) == 0)
342  {
343  if ((year % 400) == 0)
344  is_a_leap_year = true;
345  else
346  is_a_leap_year = false;
347  }
348  }
349  return is_a_leap_year;
350 }
351 
353  /** Universal Time Coordinated [year] */
354  const unsigned short year,
355  /** Universal Time Coordinated [1-12 months] */
356  const unsigned char month,
357  /** Days in the specified month [1-28|29|30|31 days] */
358  unsigned char* days_in_month)
359 {
360  unsigned char utmp = 0;
361  bool is_a_leapyear = TIMECONV_IsALeapYear(year);
362 
363  switch (month)
364  {
365  case 1:
366  utmp = 31;
367  break;
368  case 2:
369  if (is_a_leapyear)
370  {
371  utmp = 29;
372  }
373  else
374  {
375  utmp = 28;
376  }
377  break;
378  case 3:
379  utmp = 31;
380  break;
381  case 4:
382  utmp = 30;
383  break;
384  case 5:
385  utmp = 31;
386  break;
387  case 6:
388  utmp = 30;
389  break;
390  case 7:
391  utmp = 31;
392  break;
393  case 8:
394  utmp = 31;
395  break;
396  case 9:
397  utmp = 30;
398  break;
399  case 10:
400  utmp = 31;
401  break;
402  case 11:
403  utmp = 30;
404  break;
405  case 12:
406  utmp = 31;
407  break;
408  default:
409  return false;
410  break;
411  }
412  *days_in_month = utmp;
413  return true;
414 }
415 /** Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar)
416  * [days] */
418  const double julian_date, mrpt::system::TTimeParts& utc)
419 {
420  int a, b, c, d, e; // temporary values
421 
422  unsigned short year;
423  unsigned char month;
424  unsigned char day;
425  unsigned char hour;
426  unsigned char minute;
427  unsigned char days_in_month = 0;
428  double td; // temporary double
429  double seconds;
430  bool result;
431 
432  // Check the input.
433  if (julian_date < 0.0) return false;
434 
435  a = (int)(julian_date + 0.5);
436  b = a + 1537;
437  c = (int)(((double)b - 122.1) / 365.25);
438  d = (int)(365.25 * c);
439  e = (int)(((double)(b - d)) / 30.6001);
440 
441  td = b - d - (int)(30.6001 * e) + fmod(julian_date + 0.5, 1.0); // [days]
442  day = (unsigned char)td;
443  td -= day;
444  td *= 24.0; // [hours]
445  hour = (unsigned char)td;
446  td -= hour;
447  td *= 60.0; // [minutes]
448  minute = (unsigned char)td;
449  td -= minute;
450  td *= 60.0; // [s]
451  seconds = td;
452  month = (unsigned char)(e - 1 - 12 * (int)(e / 14));
453  year = (unsigned short)(c - 4715 - (int)((7.0 + (double)month) / 10.0));
454  // check for rollover issues
455  if (seconds >= 60.0)
456  {
457  seconds -= 60.0;
458  minute++;
459  if (minute >= 60)
460  {
461  minute -= 60;
462  hour++;
463  if (hour >= 24)
464  {
465  hour -= 24;
466  day++;
468  year, month, &days_in_month);
469  if (result == false) return false;
470  if (day > days_in_month)
471  {
472  day = 1;
473  month++;
474  if (month > 12)
475  {
476  month = 1;
477  year++;
478  }
479  }
480  }
481  }
482  }
483 
484  utc.year = year;
485  utc.month = month;
486  utc.day = day;
487  utc.hour = hour;
488  utc.minute = minute;
489  utc.second = seconds;
490  return true;
491 }
492 
493 bool CObservationGPS::GPS_time_to_UTC(
494  uint16_t gps_week, double gps_sec, const int leap_seconds_count,
495  mrpt::system::TTimeStamp& utc_out)
496 {
498  if (!GPS_time_to_UTC(gps_week, gps_sec, leap_seconds_count, tim))
499  return false;
501  return true;
502 }
503 
504 bool CObservationGPS::GPS_time_to_UTC(
505  uint16_t gps_week, double gps_sec, const int leap_seconds_count,
506  mrpt::system::TTimeParts& utc_out)
507 {
508  double julian_date = 0.0;
509  if (gps_sec < 0.0 || gps_sec > 604800.0) return false;
511  gps_week, gps_sec, leap_seconds_count, &julian_date))
512  return false;
513  if (!TIMECONV_GetUTCTimeFromJulianDate(julian_date, utc_out)) return false;
514  return true;
515 }
#define MRPT_READ_POD(_STREAM, _VARIABLE)
Definition: CArchive.h:412
bool TIMECONV_IsALeapYear(const unsigned short year)
bool TIMECONV_GetJulianDateFromGPSTime(const unsigned short gps_week, const double gps_tow, const unsigned int utc_offset, double *julian_date)
bool TIMECONV_GetNumberOfDaysInMonth(const unsigned short year, const unsigned char month, unsigned char *days_in_month)
bool TIMECONV_GetUTCTimeFromJulianDate(const double julian_date, mrpt::system::TTimeParts &utc)
Number of days since noon Universal Time Jan 1, 4713 BCE (Julian calendar) [days].
#define TIMECONV_JULIAN_DATE_START_OF_GPS_TIME
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
This class stores messages from GNSS or GNSS+IMU devices, from consumer-grade inexpensive GPS receive...
Declares a class that represents any robot's observation.
Definition: CObservation.h:44
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:53
Scalar * iterator
Definition: eigen_plugins.h:26
const Scalar * const_iterator
Definition: eigen_plugins.h:27
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: exceptions.h:90
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
Definition: exceptions.h:101
const GLubyte * c
Definition: glext.h:6313
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
GLubyte GLubyte b
Definition: glext.h:6279
GLuint in
Definition: glext.h:7274
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
Definition: datetime.h:43
mrpt::Clock::time_point TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1,...
Definition: datetime.h:40
std::string dateTimeToString(const mrpt::system::TTimeStamp t)
Convert a timestamp into this textual form (UTC time): YEAR/MONTH/DAY,HH:MM:SS.MMM.
Definition: datetime.cpp:147
mrpt::system::TTimeStamp buildTimestampFromParts(const mrpt::system::TTimeParts &p)
Builds a timestamp from the parts (Parts are in UTC)
Definition: datetime.cpp:85
double timestampTotime_t(const mrpt::system::TTimeStamp t)
Transform from TTimeStamp to standard "time_t" (actually a double number, it can contain fractions of...
Definition: datetime.cpp:50
This file implements matrix/vector text and binary serialization.
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:186
This base provides a set of functions for maths stuff.
gnss_message_type_t
List of all known GNSS message types.
This namespace contains representation of robot actions and observations.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
unsigned __int16 uint16_t
Definition: rptypes.h:44
unsigned __int32 uint32_t
Definition: rptypes.h:47
unsigned char uint8_t
Definition: rptypes.h:41
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
uint8_t fix_quality
NMEA standard values: 0 = invalid, 1 = GPS fix (SPS), 2 = DGPS fix, 3 = PPS fix, 4 = Real Time Kinema...
bool thereis_HDOP
This states whether to take into account the value in the HDOP field.
double orthometric_altitude
The measured orthometric altitude, in meters (A)+(B).
uint32_t satellitesUsed
The number of satelites used to compute this estimation.
double corrected_orthometric_altitude
The corrected (only for TopCon mmGPS) orthometric altitude, in meters mmGPS(A+B).
float HDOP
The HDOP (Horizontal Dilution of Precision) as returned by the sensor.
double altitude_meters
The measured altitude, in meters (A).
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
UTC_time UTCTime
The GPS sensor measured timestamp (in UTC time)
double geoidal_distance
Undulation: Difference between the measured altitude and the geoid, in meters (B).
content_t fields
Message content, accesible by individual fields.
double direction_degrees
Measured speed direction (in degrees)
int8_t validity_char
This will be: 'A'=OK or 'V'=void.
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
UTC_time UTCTime
The GPS sensor measured timestamp (in UTC time)
content_t fields
Message content, accesible by individual fields.
GPS datum for TopCon's mmGPS devices: PZS.
double angle_transmitter
Vertical angle of N-beam.
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
double cartesian_vx
Only if hasCartesianPosVel is true.
uint8_t stats_rtk_fix_progress
[0,100] %, only in modes other than RTK FIXED.
mrpt::math::CMatrixFloat44 vel_covariance
Only if hasPosCov is true.
uint8_t TXBattery
battery level on transmitter
double height_meters
ellipsoidal height from N-beam [m] perhaps weighted with regular gps
mrpt::math::CMatrixFloat44 pos_covariance
Only if hasPosCov is true.
bool hasCartesianPosVel
system error indicator
double RTK_height_meters
ellipsoidal height [m] without N-beam correction
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
uint8_t nId
ID of the transmitter [1-4], 0 if none.
double cartesian_x
Only if hasCartesianPosVel is true.
uint8_t RXBattery
battery level on receiver
TopCon mmGPS devices: SATS, a generic structure for statistics about tracked satelites and their posi...
std::vector< uint8_t > USIs
The list of USI (Universal Sat ID) for the detected sats (See GRIL Manual, pag 4-31).
std::vector< int8_t > ELs
Elevation (in degrees, 0-90) for each satellite in USIs.
std::vector< int16_t > AZs
Azimuth (in degrees, 0-360) for each satellite in USIs.
A smart pointer to a GNSS message.
Pure virtual base for all message types.
gnss_message_type_t message_type
Type of GNSS message.
The parts of a date/time (it's like the standard 'tm' but with fractions of seconds).
Definition: datetime.h:50
uint8_t hour
Day (1-31)
Definition: datetime.h:54
uint8_t day
Month (1-12)
Definition: datetime.h:53
uint8_t minute
Hour (0-23)
Definition: datetime.h:55
uint8_t month
The year.
Definition: datetime.h:52
double second
Minute (0-59)
Definition: datetime.h:56



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 814d80880 Fri Aug 24 01:51:28 2018 +0200 at mar 26 may 2026 12:30:59 CEST