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 }
double angle_transmitter
Vertical angle of N-beam.
std::vector< int16_t > AZs
Azimuth (in degrees, 0-360) for each satellite in USIs.
Scalar * iterator
Definition: eigen_plugins.h:26
uint8_t stats_rtk_fix_progress
[0,100] %, only in modes other than RTK FIXED.
uint8_t fix_quality
NMEA standard values: 0 = invalid, 1 = GPS fix (SPS), 2 = DGPS fix, 3 = PPS fix, 4 = Real Time Kinema...
double height_meters
ellipsoidal height from N-beam [m] perhaps weighted with regular gps
content_t fields
Message content, accesible by individual fields.
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
unsigned __int16 uint16_t
Definition: rptypes.h:44
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
TopCon mmGPS devices: SATS, a generic structure for statistics about tracked satelites and their posi...
mrpt::math::CMatrixFloat44 vel_covariance
Only if hasPosCov is true.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
gnss_message_type_t
List of all known GNSS message types.
mrpt::system::TTimeStamp buildTimestampFromParts(const mrpt::system::TTimeParts &p)
Builds a timestamp from the parts (Parts are in UTC)
Definition: datetime.cpp:85
uint32_t satellitesUsed
The number of satelites used to compute this estimation.
STL namespace.
bool TIMECONV_GetJulianDateFromGPSTime(const unsigned short gps_week, const double gps_tow, const unsigned int utc_offset, double *julian_date)
bool TIMECONV_IsALeapYear(const unsigned short year)
GPS datum for TopCon&#39;s mmGPS devices: PZS.
int8_t validity_char
This will be: &#39;A&#39;=OK or &#39;V&#39;=void.
UTC_time UTCTime
The GPS sensor measured timestamp (in UTC time)
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
uint8_t nId
ID of the transmitter [1-4], 0 if none.
double orthometric_altitude
The measured orthometric altitude, in meters (A)+(B).
bool hasCartesianPosVel
system error indicator
unsigned char uint8_t
Definition: rptypes.h:41
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: exceptions.h:90
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
double altitude_meters
The measured altitude, in meters (A).
bool thereis_HDOP
This states whether to take into account the value in the HDOP field.
This base provides a set of functions for maths stuff.
double corrected_orthometric_altitude
The corrected (only for TopCon mmGPS) orthometric altitude, in meters mmGPS(A+B). ...
#define MRPT_READ_POD(_STREAM, _VARIABLE)
Definition: CArchive.h:412
mrpt::math::CMatrixFloat44 pos_covariance
Only if hasPosCov is true.
bool TIMECONV_GetNumberOfDaysInMonth(const unsigned short year, const unsigned char month, unsigned char *days_in_month)
const GLubyte * c
Definition: glext.h:6313
The parts of a date/time (it&#39;s like the standard &#39;tm&#39; but with fractions of seconds).
Definition: datetime.h:49
float HDOP
The HDOP (Horizontal Dilution of Precision) as returned by the sensor.
uint8_t day
Month (1-12)
Definition: datetime.h:53
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
This namespace contains representation of robot actions and observations.
GLubyte GLubyte b
Definition: glext.h:6279
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
Definition: exceptions.h:101
gnss_message_type_t message_type
Type of GNSS message.
uint8_t RXBattery
battery level on receiver
double second
Minute (0-59)
Definition: datetime.h:56
double cartesian_x
Only if hasCartesianPosVel is true.
double geoidal_distance
Undulation: Difference between the measured altitude and the geoid, in meters (B).
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].
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::vector< uint8_t > USIs
The list of USI (Universal Sat ID) for the detected sats (See GRIL Manual, pag 4-31).
uint8_t minute
Hour (0-23)
Definition: datetime.h:55
Virtual base class for "archives": classes abstracting I/O streams.
Definition: CArchive.h:52
Declares a class that represents any robot&#39;s observation.
Definition: CObservation.h:43
Pure virtual base for all message types.
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
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
This file implements matrix/vector text and binary serialization.
double direction_degrees
Measured speed direction (in degrees)
GLuint in
Definition: glext.h:7274
content_t fields
Message content, accesible by individual fields.
uint8_t month
The year.
Definition: datetime.h:52
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
uint8_t hour
Day (1-31)
Definition: datetime.h:54
#define TIMECONV_JULIAN_DATE_START_OF_GPS_TIME
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
uint8_t TXBattery
battery level on transmitter
double cartesian_vx
Only if hasCartesianPosVel is true.
This class stores messages from GNSS or GNSS+IMU devices, from consumer-grade inexpensive GPS receive...
unsigned __int32 uint32_t
Definition: rptypes.h:47
double RTK_height_meters
ellipsoidal height [m] without N-beam correction
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
void clear()
Clear the contents of this container.
Definition: ts_hash_map.h:186
const Scalar * const_iterator
Definition: eigen_plugins.h:27
std::vector< int8_t > ELs
Elevation (in degrees, 0-90) for each satellite in USIs.
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
Definition: datetime.h:43
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
UTC_time UTCTime
The GPS sensor measured timestamp (in UTC time)
A smart pointer to a GNSS message.
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020