message_wrapper.cpp
Go to the documentation of this file.
1 // File header
2 #include "message_wrapper.h"
3 
4 // ROS headers
9 
10 // Project headers
11 #include <sbg_vector3.h>
12 
14 
18 //---------------------------------------------------------------------//
19 //- Constructor -//
20 //---------------------------------------------------------------------//
21 
22 MessageWrapper::MessageWrapper(void):
23 m_first_valid_utc_(false)
24 {
25  m_utm0_.easting = 0.0;
26  m_utm0_.northing = 0.0;
27  m_utm0_.altitude = 0.0;
28  m_utm0_.zone = 0;
29 }
30 
31 //---------------------------------------------------------------------//
32 //- Internal methods -//
33 //---------------------------------------------------------------------//
34 
35 float MessageWrapper::wrapAngle2Pi(float angle_rad) const
36 {
37  if ((angle_rad < -SBG_PI_F * 2.0f) || (angle_rad > SBG_PI_F * 2.0f))
38  {
39  angle_rad = fmodf(angle_rad, SBG_PI_F * 2.0f);
40  }
41 
42  if (angle_rad < 0.0f)
43  {
44  angle_rad = SBG_PI_F * 2.0f + angle_rad;
45  }
46 
47  return angle_rad;
48 }
49 
50 float MessageWrapper::wrapAngle360(float angle_deg) const
51 {
52  if ( (angle_deg < -360.0f) || (angle_deg > 360.0f) )
53  {
54  angle_deg = fmodf(angle_deg, 360.0f);
55  }
56 
57  if (angle_deg < 0.0f)
58  {
59  angle_deg = 360.0f + angle_deg;
60  }
61 
62  return angle_deg;
63 }
64 
65 double MessageWrapper::computeMeridian(int zone_number) const
66 {
67  return (zone_number == 0) ? 0.0 : (zone_number - 1) * 6.0 - 177.0;
68 }
69 
70 const std_msgs::Header MessageWrapper::createRosHeader(uint32_t device_timestamp) const
71 {
72  std_msgs::Header header;
73 
74  header.frame_id = m_frame_id_;
75 
77  {
78  header.stamp = convertInsTimeToUnix(device_timestamp);
79  }
80  else
81  {
82  header.stamp = ros::Time::now();
83  }
84 
85  return header;
86 }
87 
88 const ros::Time MessageWrapper::convertInsTimeToUnix(uint32_t device_timestamp) const
89 {
90  //
91  // Convert the UTC time to epoch from the last received message.
92  // Add the SBG timestamp difference (timestamp is in microsecond).
93  //
94  ros::Time utc_to_epoch;
95  uint32_t device_timestamp_diff;
96  uint64_t nanoseconds;
97 
98  utc_to_epoch = convertUtcToUnix(m_last_sbg_utc_);
99  device_timestamp_diff = device_timestamp - m_last_sbg_utc_.time_stamp;
100 
101  nanoseconds = utc_to_epoch.toNSec() + static_cast<uint64_t>(device_timestamp_diff) * 1000;
102 
103  utc_to_epoch.fromNSec(nanoseconds);
104 
105  return utc_to_epoch;
106 }
107 
108 const sbg_driver::SbgEkfStatus MessageWrapper::createEkfStatusMessage(uint32_t ekf_status) const
109 {
110  sbg_driver::SbgEkfStatus ekf_status_message;
111 
112  ekf_status_message.solution_mode = sbgEComLogEkfGetSolutionMode(ekf_status);
113  ekf_status_message.attitude_valid = (ekf_status & SBG_ECOM_SOL_ATTITUDE_VALID) != 0;
114  ekf_status_message.heading_valid = (ekf_status & SBG_ECOM_SOL_HEADING_VALID) != 0;
115  ekf_status_message.velocity_valid = (ekf_status & SBG_ECOM_SOL_VELOCITY_VALID) != 0;
116  ekf_status_message.position_valid = (ekf_status & SBG_ECOM_SOL_POSITION_VALID) != 0;
117 
118  ekf_status_message.vert_ref_used = (ekf_status & SBG_ECOM_SOL_VERT_REF_USED) != 0;
119  ekf_status_message.mag_ref_used = (ekf_status & SBG_ECOM_SOL_MAG_REF_USED) != 0;
120 
121  ekf_status_message.gps1_vel_used = (ekf_status & SBG_ECOM_SOL_GPS1_VEL_USED) != 0;
122  ekf_status_message.gps1_pos_used = (ekf_status & SBG_ECOM_SOL_GPS1_POS_USED) != 0;
123  ekf_status_message.gps1_course_used = (ekf_status & SBG_ECOM_SOL_GPS1_HDT_USED) != 0;
124  ekf_status_message.gps1_hdt_used = (ekf_status & SBG_ECOM_SOL_GPS1_HDT_USED) != 0;
125 
126  ekf_status_message.gps2_vel_used = (ekf_status & SBG_ECOM_SOL_GPS2_VEL_USED) != 0;
127  ekf_status_message.gps2_pos_used = (ekf_status & SBG_ECOM_SOL_GPS2_POS_USED) != 0;
128  ekf_status_message.gps2_course_used = (ekf_status & SBG_ECOM_SOL_GPS2_POS_USED) != 0;
129  ekf_status_message.gps2_hdt_used = (ekf_status & SBG_ECOM_SOL_GPS2_HDT_USED) != 0;
130 
131  ekf_status_message.odo_used = (ekf_status & SBG_ECOM_SOL_ODO_USED) != 0;
132 
133  return ekf_status_message;
134 }
135 
136 const sbg_driver::SbgGpsPosStatus MessageWrapper::createGpsPosStatusMessage(const SbgLogGpsPos& ref_log_gps_pos) const
137 {
138  sbg_driver::SbgGpsPosStatus gps_pos_status_message;
139 
140  gps_pos_status_message.status = sbgEComLogGpsPosGetStatus(ref_log_gps_pos.status);
141  gps_pos_status_message.type = sbgEComLogGpsPosGetType(ref_log_gps_pos.status);
142 
143  gps_pos_status_message.gps_l1_used = (ref_log_gps_pos.status & SBG_ECOM_GPS_POS_GPS_L1_USED) != 0;
144  gps_pos_status_message.gps_l2_used = (ref_log_gps_pos.status & SBG_ECOM_GPS_POS_GPS_L2_USED) != 0;
145  gps_pos_status_message.gps_l5_used = (ref_log_gps_pos.status & SBG_ECOM_GPS_POS_GPS_L5_USED) != 0;
146 
147  gps_pos_status_message.glo_l1_used = (ref_log_gps_pos.status & SBG_ECOM_GPS_POS_GLO_L1_USED) != 0;
148  gps_pos_status_message.glo_l2_used = (ref_log_gps_pos.status & SBG_ECOM_GPS_POS_GLO_L2_USED) != 0;
149 
150  return gps_pos_status_message;
151 }
152 
153 const sbg_driver::SbgGpsVelStatus MessageWrapper::createGpsVelStatusMessage(const SbgLogGpsVel& ref_log_gps_vel) const
154 {
155  sbg_driver::SbgGpsVelStatus gps_vel_status_message;
156 
157  gps_vel_status_message.vel_status = sbgEComLogGpsVelGetStatus(ref_log_gps_vel.status);
158  gps_vel_status_message.vel_type = sbgEComLogGpsVelGetType(ref_log_gps_vel.status);
159 
160  return gps_vel_status_message;
161 }
162 
163 const sbg_driver::SbgImuStatus MessageWrapper::createImuStatusMessage(uint16_t sbg_imu_status) const
164 {
165  sbg_driver::SbgImuStatus imu_status_message;
166 
167  imu_status_message.imu_com = (sbg_imu_status & SBG_ECOM_IMU_COM_OK) != 0;
168  imu_status_message.imu_status = (sbg_imu_status & SBG_ECOM_IMU_STATUS_BIT) != 0 ;
169  imu_status_message.imu_accels_in_range = (sbg_imu_status & SBG_ECOM_IMU_ACCELS_IN_RANGE) != 0;
170  imu_status_message.imu_gyros_in_range = (sbg_imu_status & SBG_ECOM_IMU_GYROS_IN_RANGE) != 0;
171 
172  imu_status_message.imu_accel_x = (sbg_imu_status & SBG_ECOM_IMU_ACCEL_X_BIT) != 0;
173  imu_status_message.imu_accel_y = (sbg_imu_status & SBG_ECOM_IMU_ACCEL_Y_BIT) != 0;
174  imu_status_message.imu_accel_z = (sbg_imu_status & SBG_ECOM_IMU_ACCEL_Z_BIT) != 0;
175 
176  imu_status_message.imu_gyro_x = (sbg_imu_status & SBG_ECOM_IMU_GYRO_X_BIT) != 0;
177  imu_status_message.imu_gyro_y = (sbg_imu_status & SBG_ECOM_IMU_GYRO_Y_BIT) != 0;
178  imu_status_message.imu_gyro_z = (sbg_imu_status & SBG_ECOM_IMU_GYRO_Z_BIT) != 0;
179 
180  return imu_status_message;
181 }
182 
183 const sbg_driver::SbgMagStatus MessageWrapper::createMagStatusMessage(const SbgLogMag& ref_log_mag) const
184 {
185  sbg_driver::SbgMagStatus mag_status_message;
186 
187  mag_status_message.mag_x = (ref_log_mag.status & SBG_ECOM_MAG_MAG_X_BIT) != 0;
188  mag_status_message.mag_y = (ref_log_mag.status & SBG_ECOM_MAG_MAG_Y_BIT) != 0;
189  mag_status_message.mag_z = (ref_log_mag.status & SBG_ECOM_MAG_MAG_Z_BIT) != 0;
190 
191  mag_status_message.accel_x = (ref_log_mag.status & SBG_ECOM_MAG_ACCEL_X_BIT) != 0;
192  mag_status_message.accel_y = (ref_log_mag.status & SBG_ECOM_MAG_ACCEL_Y_BIT) != 0;
193  mag_status_message.accel_z = (ref_log_mag.status & SBG_ECOM_MAG_ACCEL_Z_BIT) != 0;
194 
195  mag_status_message.mags_in_range = (ref_log_mag.status & SBG_ECOM_MAG_MAGS_IN_RANGE) != 0;
196  mag_status_message.accels_in_range = (ref_log_mag.status & SBG_ECOM_MAG_ACCELS_IN_RANGE) != 0;
197  mag_status_message.calibration = (ref_log_mag.status & SBG_ECOM_MAG_CALIBRATION_OK) != 0;
198 
199  return mag_status_message;
200 }
201 
202 const sbg_driver::SbgShipMotionStatus MessageWrapper::createShipMotionStatusMessage(const SbgLogShipMotionData& ref_log_ship_motion) const
203 {
204  sbg_driver::SbgShipMotionStatus ship_motion_status_message;
205 
206  ship_motion_status_message.heave_valid = (ref_log_ship_motion.status & SBG_ECOM_HEAVE_VALID) != 0;
207  ship_motion_status_message.heave_vel_aided = (ref_log_ship_motion.status & SBG_ECOM_HEAVE_VEL_AIDED) != 0;
208  ship_motion_status_message.period_available = (ref_log_ship_motion.status & SBG_ECOM_HEAVE_PERIOD_INCLUDED) != 0;
209  ship_motion_status_message.period_valid = (ref_log_ship_motion.status & SBG_ECOM_HEAVE_PERIOD_VALID) != 0;
210 
211  return ship_motion_status_message;
212 }
213 
214 const sbg_driver::SbgStatusAiding MessageWrapper::createStatusAidingMessage(const SbgLogStatusData& ref_log_status) const
215 {
216  sbg_driver::SbgStatusAiding status_aiding_message;
217 
218  status_aiding_message.gps1_pos_recv = (ref_log_status.aidingStatus & SBG_ECOM_AIDING_GPS1_POS_RECV) != 0;
219  status_aiding_message.gps1_vel_recv = (ref_log_status.aidingStatus & SBG_ECOM_AIDING_GPS1_VEL_RECV) != 0;
220  status_aiding_message.gps1_hdt_recv = (ref_log_status.aidingStatus & SBG_ECOM_AIDING_GPS1_HDT_RECV) != 0;
221  status_aiding_message.gps1_utc_recv = (ref_log_status.aidingStatus & SBG_ECOM_AIDING_GPS1_UTC_RECV) != 0;
222 
223  status_aiding_message.mag_recv = (ref_log_status.aidingStatus & SBG_ECOM_AIDING_MAG_RECV) != 0;
224  status_aiding_message.odo_recv = (ref_log_status.aidingStatus & SBG_ECOM_AIDING_ODO_RECV) != 0;
225  status_aiding_message.dvl_recv = (ref_log_status.aidingStatus & SBG_ECOM_AIDING_DVL_RECV) != 0;
226 
227  return status_aiding_message;
228 }
229 
230 const sbg_driver::SbgStatusCom MessageWrapper::createStatusComMessage(const SbgLogStatusData& ref_log_status) const
231 {
232  sbg_driver::SbgStatusCom status_com_message;
233 
234  status_com_message.port_a = (ref_log_status.comStatus & SBG_ECOM_PORTA_VALID) != 0;
235  status_com_message.port_b = (ref_log_status.comStatus & SBG_ECOM_PORTB_VALID) != 0;
236  status_com_message.port_c = (ref_log_status.comStatus & SBG_ECOM_PORTC_VALID) != 0;
237  status_com_message.port_d = (ref_log_status.comStatus & SBG_ECOM_PORTD_VALID) != 0;
238  status_com_message.port_e = (ref_log_status.comStatus & SBG_ECOM_PORTE_VALID) != 0;
239 
240  status_com_message.port_a_rx = (ref_log_status.comStatus & SBG_ECOM_PORTA_RX_OK) != 0;
241  status_com_message.port_a_tx = (ref_log_status.comStatus & SBG_ECOM_PORTA_TX_OK) != 0;
242  status_com_message.port_b_rx = (ref_log_status.comStatus & SBG_ECOM_PORTB_RX_OK) != 0;
243  status_com_message.port_b_tx = (ref_log_status.comStatus & SBG_ECOM_PORTB_TX_OK) != 0;
244  status_com_message.port_c_rx = (ref_log_status.comStatus & SBG_ECOM_PORTC_RX_OK) != 0;
245  status_com_message.port_c_tx = (ref_log_status.comStatus & SBG_ECOM_PORTC_TX_OK) != 0;
246  status_com_message.port_d_rx = (ref_log_status.comStatus & SBG_ECOM_PORTD_RX_OK) != 0;
247  status_com_message.port_d_tx = (ref_log_status.comStatus & SBG_ECOM_PORTD_TX_OK) != 0;
248  status_com_message.port_e_rx = (ref_log_status.comStatus & SBG_ECOM_PORTE_RX_OK) != 0;
249  status_com_message.port_e_tx = (ref_log_status.comStatus & SBG_ECOM_PORTE_TX_OK) != 0;
250 
251  status_com_message.can_rx = (ref_log_status.comStatus & SBG_ECOM_CAN_RX_OK) != 0;
252  status_com_message.can_tx = (ref_log_status.comStatus & SBG_ECOM_CAN_TX_OK) != 0;
253  status_com_message.can_status = (ref_log_status.comStatus & SBG_ECOM_CAN_VALID) != 0;
254 
255  return status_com_message;
256 }
257 
258 const sbg_driver::SbgStatusGeneral MessageWrapper::createStatusGeneralMessage(const SbgLogStatusData& ref_log_status) const
259 {
260  sbg_driver::SbgStatusGeneral status_general_message;
261 
262  status_general_message.main_power = (ref_log_status.generalStatus & SBG_ECOM_GENERAL_MAIN_POWER_OK) != 0;
263  status_general_message.imu_power = (ref_log_status.generalStatus & SBG_ECOM_GENERAL_IMU_POWER_OK) != 0;
264  status_general_message.gps_power = (ref_log_status.generalStatus & SBG_ECOM_GENERAL_GPS_POWER_OK) != 0;
265  status_general_message.settings = (ref_log_status.generalStatus & SBG_ECOM_GENERAL_SETTINGS_OK) != 0;
266  status_general_message.temperature = (ref_log_status.generalStatus & SBG_ECOM_GENERAL_TEMPERATURE_OK) != 0;
267 
268  return status_general_message;
269 }
270 
271 const sbg_driver::SbgUtcTimeStatus MessageWrapper::createUtcStatusMessage(const SbgLogUtcData& ref_log_utc) const
272 {
273  sbg_driver::SbgUtcTimeStatus utc_status_message;
274 
275  utc_status_message.clock_stable = (ref_log_utc.status & SBG_ECOM_CLOCK_STABLE_INPUT) != 0;
276  utc_status_message.clock_utc_sync = (ref_log_utc.status & SBG_ECOM_CLOCK_UTC_SYNC) != 0;
277 
278  utc_status_message.clock_status = static_cast<uint8_t>(sbgEComLogUtcGetClockStatus(ref_log_utc.status));
279  utc_status_message.clock_utc_status = static_cast<uint8_t>(sbgEComLogUtcGetClockUtcStatus(ref_log_utc.status));
280 
281  return utc_status_message;
282 }
283 
284 uint32_t MessageWrapper::getNumberOfDaysInYear(uint16_t year) const
285 {
286  if (isLeapYear(year))
287  {
288  return 366;
289  }
290  else
291  {
292  return 365;
293  }
294 }
295 
296 uint32_t MessageWrapper::getNumberOfDaysInMonth(uint16_t year, uint8_t month_index) const
297 {
298  if ((month_index == 4) || (month_index == 6) || (month_index == 9) || (month_index == 11))
299  {
300  return 30;
301  }
302  else if ((month_index == 2))
303  {
304  if (isLeapYear(year))
305  {
306  return 29;
307  }
308  else
309  {
310  return 28;
311  }
312  }
313  else
314  {
315  return 31;
316  }
317 }
318 
319 bool MessageWrapper::isLeapYear(uint16_t year) const
320 {
321  return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
322 }
323 
324 const ros::Time MessageWrapper::convertUtcToUnix(const sbg_driver::SbgUtcTime& ref_sbg_utc_msg) const
325 {
326  ros::Time utc_to_epoch;
327  uint32_t days;
328  uint64_t nanoseconds;
329 
330  //
331  // Convert the UTC time to Epoch(Unix) time, which is the elapsed seconds since 1 Jan 1970.
332  //
333  days = 0;
334  nanoseconds = 0;
335 
336  for (uint16_t yearIndex = 1970; yearIndex < ref_sbg_utc_msg.year; yearIndex++)
337  {
338  days += getNumberOfDaysInYear(yearIndex);
339  }
340 
341  for (uint8_t monthIndex = 1; monthIndex < ref_sbg_utc_msg.month; monthIndex++)
342  {
343  days += getNumberOfDaysInMonth(ref_sbg_utc_msg.year, monthIndex);
344  }
345 
346  days += ref_sbg_utc_msg.day - 1;
347 
348  nanoseconds = days * 24;
349  nanoseconds = (nanoseconds + ref_sbg_utc_msg.hour) * 60;
350  nanoseconds = (nanoseconds + ref_sbg_utc_msg.min) * 60;
351  nanoseconds = nanoseconds + ref_sbg_utc_msg.sec;
352  nanoseconds = nanoseconds * 1000000000 + ref_sbg_utc_msg.nanosec;
353 
354  utc_to_epoch.fromNSec(nanoseconds);
355 
356  return utc_to_epoch;
357 }
358 
359 const sbg_driver::SbgAirDataStatus MessageWrapper::createAirDataStatusMessage(const SbgLogAirData& ref_sbg_air_data) const
360 {
361  sbg_driver::SbgAirDataStatus air_data_status_message;
362 
363  air_data_status_message.is_delay_time = (ref_sbg_air_data.status & SBG_ECOM_AIR_DATA_TIME_IS_DELAY) != 0;
364  air_data_status_message.pressure_valid = (ref_sbg_air_data.status & SBG_ECOM_AIR_DATA_PRESSURE_ABS_VALID) != 0;
365  air_data_status_message.altitude_valid = (ref_sbg_air_data.status & SBG_ECOM_AIR_DATA_ALTITUDE_VALID) != 0;
366  air_data_status_message.pressure_diff_valid = (ref_sbg_air_data.status & SBG_ECOM_AIR_DATA_PRESSURE_DIFF_VALID) != 0;
367  air_data_status_message.air_speed_valid = (ref_sbg_air_data.status & SBG_ECOM_AIR_DATA_AIRPSEED_VALID) != 0;
368  air_data_status_message.air_temperature_valid = (ref_sbg_air_data.status & SBG_ECOM_AIR_DATA_TEMPERATURE_VALID) != 0;
369 
370  return air_data_status_message;
371 }
372 
381 {
382  char LetterDesignator;
383 
384  if ((84 >= Lat) && (Lat >= 72)) LetterDesignator = 'X';
385  else if ((72 > Lat) && (Lat >= 64)) LetterDesignator = 'W';
386  else if ((64 > Lat) && (Lat >= 56)) LetterDesignator = 'V';
387  else if ((56 > Lat) && (Lat >= 48)) LetterDesignator = 'U';
388  else if ((48 > Lat) && (Lat >= 40)) LetterDesignator = 'T';
389  else if ((40 > Lat) && (Lat >= 32)) LetterDesignator = 'S';
390  else if ((32 > Lat) && (Lat >= 24)) LetterDesignator = 'R';
391  else if ((24 > Lat) && (Lat >= 16)) LetterDesignator = 'Q';
392  else if ((16 > Lat) && (Lat >= 8)) LetterDesignator = 'P';
393  else if (( 8 > Lat) && (Lat >= 0)) LetterDesignator = 'N';
394  else if (( 0 > Lat) && (Lat >= -8)) LetterDesignator = 'M';
395  else if ((-8 > Lat) && (Lat >= -16)) LetterDesignator = 'L';
396  else if((-16 > Lat) && (Lat >= -24)) LetterDesignator = 'K';
397  else if((-24 > Lat) && (Lat >= -32)) LetterDesignator = 'J';
398  else if((-32 > Lat) && (Lat >= -40)) LetterDesignator = 'H';
399  else if((-40 > Lat) && (Lat >= -48)) LetterDesignator = 'G';
400  else if((-48 > Lat) && (Lat >= -56)) LetterDesignator = 'F';
401  else if((-56 > Lat) && (Lat >= -64)) LetterDesignator = 'E';
402  else if((-64 > Lat) && (Lat >= -72)) LetterDesignator = 'D';
403  else if((-72 > Lat) && (Lat >= -80)) LetterDesignator = 'C';
404  // 'Z' is an error flag, the Latitude is outside the UTM limits
405  else LetterDesignator = 'Z';
406  return LetterDesignator;
407 }
408 
409 void MessageWrapper::initUTM(double Lat, double Long, double altitude)
410 {
411  int zoneNumber;
412 
413  // Make sure the longitude is between -180.00 .. 179.9
414  double LongTemp = (Long+180)-int((Long+180)/360)*360-180;
415 
416  zoneNumber = int((LongTemp + 180)/6) + 1;
417 
418  if( Lat >= 56.0 && Lat < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0 )
419  {
420  zoneNumber = 32;
421  }
422 
423  // Special zones for Svalbard
424  if( Lat >= 72.0 && Lat < 84.0 )
425  {
426  if( LongTemp >= 0.0 && LongTemp < 9.0 ) zoneNumber = 31;
427  else if( LongTemp >= 9.0 && LongTemp < 21.0 ) zoneNumber = 33;
428  else if( LongTemp >= 21.0 && LongTemp < 33.0 ) zoneNumber = 35;
429  else if( LongTemp >= 33.0 && LongTemp < 42.0 ) zoneNumber = 37;
430  }
431 
432  m_utm0_.zone = zoneNumber;
433  m_utm0_.altitude = altitude;
435 
436  ROS_INFO("initialized from lat:%f long:%f UTM zone %d%c: easting:%fm (%dkm) northing:%fm (%dkm)"
437  , Lat, Long, m_utm0_.zone, UTMLetterDesignator(Lat)
438  , m_utm0_.easting, (int)(m_utm0_.easting)/1000
439  , m_utm0_.northing, (int)(m_utm0_.northing)/1000
440  );
441 }
442 
443 /*
444  * Modification of gps_common::LLtoUTM() to use a constant UTM zone.
445  *
446  * Convert lat/long to UTM coords. Equations from USGS Bulletin 1532
447  *
448  * East Longitudes are positive, West longitudes are negative.
449  * North latitudes are positive, South latitudes are negative
450  * Lat and Long are in fractional degrees
451  *
452  * Originally written by Chuck Gantz- chuck.gantz@globalstar.com.
453  */
454 void MessageWrapper::LLtoUTM(double Lat, double Long, int zoneNumber, double &UTMNorthing, double &UTMEasting) const
455 {
456  const double RADIANS_PER_DEGREE = M_PI/180.0;
457 
458  // WGS84 Parameters
459  const double WGS84_A = 6378137.0; // major axis
460  const double WGS84_E = 0.0818191908; // first eccentricity
461 
462  // UTM Parameters
463  const double UTM_K0 = 0.9996; // scale factor
464  const double UTM_E2 = (WGS84_E*WGS84_E); // e^2
465 
466  double a = WGS84_A;
467  double eccSquared = UTM_E2;
468  double k0 = UTM_K0;
469 
470  double LongOrigin;
471  double eccPrimeSquared;
472  double N, T, C, A, M;
473 
474  // Make sure the longitude is between -180.00 .. 179.9
475  double LongTemp = (Long+180)-int((Long+180)/360)*360-180;
476 
477  double LatRad = Lat*RADIANS_PER_DEGREE;
478  double LongRad = LongTemp*RADIANS_PER_DEGREE;
479  double LongOriginRad;
480 
481  // +3 puts origin in middle of zone
482  LongOrigin = (zoneNumber - 1)*6 - 180 + 3;
483  LongOriginRad = LongOrigin * RADIANS_PER_DEGREE;
484 
485  eccPrimeSquared = (eccSquared)/(1-eccSquared);
486 
487  N = a/sqrt(1-eccSquared*sin(LatRad)*sin(LatRad));
488  T = tan(LatRad)*tan(LatRad);
489  C = eccPrimeSquared*cos(LatRad)*cos(LatRad);
490  A = cos(LatRad)*(LongRad-LongOriginRad);
491 
492  M = a*((1 - eccSquared/4 - 3*eccSquared*eccSquared/64 - 5*eccSquared*eccSquared*eccSquared/256)*LatRad
493  - (3*eccSquared/8 + 3*eccSquared*eccSquared/32 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(2*LatRad)
494  + (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(4*LatRad)
495  - (35*eccSquared*eccSquared*eccSquared/3072)*sin(6*LatRad));
496 
497  UTMEasting = (double)(k0*N*(A+(1-T+C)*A*A*A/6
498  + (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120)
499  + 500000.0);
500 
501  UTMNorthing = (double)(k0*(M+N*tan(LatRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
502  + (61-58*T+T*T+600*C-330*eccPrimeSquared)*A*A*A*A*A*A/720)));
503 
504  if(Lat < 0)
505  {
506  UTMNorthing += 10000000.0; //10000000 meter offset for southern hemisphere
507  }
508 }
509 
510 //---------------------------------------------------------------------//
511 //- Parameters -//
512 //---------------------------------------------------------------------//
513 
515 {
516  m_time_reference_ = time_reference;
517 }
518 
519 void MessageWrapper::setFrameId(const std::string &frame_id)
520 {
521  m_frame_id_ = frame_id;
522 }
523 
525 {
526  m_use_enu_ = enu;
527 }
528 
529 void MessageWrapper::setOdomEnable(bool odom_enable)
530 {
531  m_odom_enable_ = odom_enable;
532 }
533 
534 void MessageWrapper::setOdomPublishTf(bool publish_tf)
535 {
536  m_odom_publish_tf_ = publish_tf;
537 }
538 
539 void MessageWrapper::setOdomFrameId(const std::string &ref_frame_id)
540 {
541  m_odom_frame_id_ = ref_frame_id;
542 }
543 
544 void MessageWrapper::setOdomBaseFrameId(const std::string &ref_frame_id)
545 {
546  m_odom_base_frame_id_ = ref_frame_id;
547 }
548 
549 void MessageWrapper::setOdomInitFrameId(const std::string &ref_frame_id)
550 {
551  m_odom_init_frame_id_ = ref_frame_id;
552 }
553 
554 //---------------------------------------------------------------------//
555 //- Operations -//
556 //---------------------------------------------------------------------//
557 
558 const sbg_driver::SbgEkfEuler MessageWrapper::createSbgEkfEulerMessage(const SbgLogEkfEulerData& ref_log_ekf_euler) const
559 {
560  sbg_driver::SbgEkfEuler ekf_euler_message;
561 
562  ekf_euler_message.header = createRosHeader(ref_log_ekf_euler.timeStamp);
563  ekf_euler_message.time_stamp = ref_log_ekf_euler.timeStamp;
564  ekf_euler_message.status = createEkfStatusMessage(ref_log_ekf_euler.status);
565 
566  if (m_use_enu_)
567  {
568  ekf_euler_message.angle.x = ref_log_ekf_euler.euler[0];
569  ekf_euler_message.angle.y = -ref_log_ekf_euler.euler[1];
570  ekf_euler_message.angle.z = wrapAngle2Pi((SBG_PI_F / 2.0f) - ref_log_ekf_euler.euler[2]);
571  }
572  else
573  {
574  ekf_euler_message.angle.x = ref_log_ekf_euler.euler[0];
575  ekf_euler_message.angle.y = ref_log_ekf_euler.euler[1];
576  ekf_euler_message.angle.z = ref_log_ekf_euler.euler[2];
577  }
578 
579  ekf_euler_message.accuracy.x = ref_log_ekf_euler.eulerStdDev[0];
580  ekf_euler_message.accuracy.y = ref_log_ekf_euler.eulerStdDev[1];
581  ekf_euler_message.accuracy.z = ref_log_ekf_euler.eulerStdDev[2];
582 
583  return ekf_euler_message;
584 }
585 
586 const sbg_driver::SbgEkfNav MessageWrapper::createSbgEkfNavMessage(const SbgLogEkfNavData& ref_log_ekf_nav) const
587 {
588  sbg_driver::SbgEkfNav ekf_nav_message;
589 
590  ekf_nav_message.header = createRosHeader(ref_log_ekf_nav.timeStamp);
591  ekf_nav_message.time_stamp = ref_log_ekf_nav.timeStamp;
592  ekf_nav_message.status = createEkfStatusMessage(ref_log_ekf_nav.status);
593  ekf_nav_message.undulation = ref_log_ekf_nav.undulation;
594 
595  ekf_nav_message.latitude = ref_log_ekf_nav.position[0];
596  ekf_nav_message.longitude = ref_log_ekf_nav.position[1];
597  ekf_nav_message.altitude = ref_log_ekf_nav.position[2];
598 
599  if (m_use_enu_)
600  {
601  ekf_nav_message.velocity.x = ref_log_ekf_nav.velocity[1];
602  ekf_nav_message.velocity.y = ref_log_ekf_nav.velocity[0];
603  ekf_nav_message.velocity.z = -ref_log_ekf_nav.velocity[2];
604 
605  ekf_nav_message.velocity_accuracy.x = ref_log_ekf_nav.velocityStdDev[1];
606  ekf_nav_message.velocity_accuracy.y = ref_log_ekf_nav.velocityStdDev[0];
607  ekf_nav_message.velocity_accuracy.z = ref_log_ekf_nav.velocityStdDev[2];
608 
609  ekf_nav_message.position_accuracy.x = ref_log_ekf_nav.positionStdDev[1];
610  ekf_nav_message.position_accuracy.y = ref_log_ekf_nav.positionStdDev[0];
611  ekf_nav_message.position_accuracy.z = ref_log_ekf_nav.positionStdDev[2];
612  }
613  else
614  {
615  ekf_nav_message.velocity.x = ref_log_ekf_nav.velocity[0];
616  ekf_nav_message.velocity.y = ref_log_ekf_nav.velocity[1];
617  ekf_nav_message.velocity.z = ref_log_ekf_nav.velocity[2];
618 
619  ekf_nav_message.velocity_accuracy.x = ref_log_ekf_nav.velocityStdDev[0];
620  ekf_nav_message.velocity_accuracy.y = ref_log_ekf_nav.velocityStdDev[1];
621  ekf_nav_message.velocity_accuracy.z = ref_log_ekf_nav.velocityStdDev[2];
622 
623  ekf_nav_message.position_accuracy.x = ref_log_ekf_nav.positionStdDev[0];
624  ekf_nav_message.position_accuracy.y = ref_log_ekf_nav.positionStdDev[1];
625  ekf_nav_message.position_accuracy.z = ref_log_ekf_nav.positionStdDev[2];
626  }
627 
628  return ekf_nav_message;
629 }
630 
631 const sbg_driver::SbgEkfQuat MessageWrapper::createSbgEkfQuatMessage(const SbgLogEkfQuatData& ref_log_ekf_quat) const
632 {
633  sbg_driver::SbgEkfQuat ekf_quat_message;
634 
635  ekf_quat_message.header = createRosHeader(ref_log_ekf_quat.timeStamp);
636  ekf_quat_message.time_stamp = ref_log_ekf_quat.timeStamp;
637  ekf_quat_message.status = createEkfStatusMessage(ref_log_ekf_quat.status);
638 
639  ekf_quat_message.accuracy.x = ref_log_ekf_quat.eulerStdDev[0];
640  ekf_quat_message.accuracy.y = ref_log_ekf_quat.eulerStdDev[1];
641  ekf_quat_message.accuracy.z = ref_log_ekf_quat.eulerStdDev[2];
642 
643  if (m_use_enu_)
644  {
645  ekf_quat_message.quaternion.x = ref_log_ekf_quat.quaternion[1];
646  ekf_quat_message.quaternion.y = -ref_log_ekf_quat.quaternion[2];
647  ekf_quat_message.quaternion.z = -ref_log_ekf_quat.quaternion[3];
648  ekf_quat_message.quaternion.w = ref_log_ekf_quat.quaternion[0];
649  }
650  else
651  {
652  ekf_quat_message.quaternion.x = ref_log_ekf_quat.quaternion[1];
653  ekf_quat_message.quaternion.y = ref_log_ekf_quat.quaternion[2];
654  ekf_quat_message.quaternion.z = ref_log_ekf_quat.quaternion[3];
655  ekf_quat_message.quaternion.w = ref_log_ekf_quat.quaternion[0];
656  }
657 
658  return ekf_quat_message;
659 }
660 
661 const sbg_driver::SbgEvent MessageWrapper::createSbgEventMessage(const SbgLogEvent& ref_log_event) const
662 {
663  sbg_driver::SbgEvent event_message;
664 
665  event_message.header = createRosHeader(ref_log_event.timeStamp);
666  event_message.time_stamp = ref_log_event.timeStamp;
667 
668  event_message.overflow = (ref_log_event.status & SBG_ECOM_EVENT_OVERFLOW) != 0;
669  event_message.offset_0_valid = (ref_log_event.status & SBG_ECOM_EVENT_OFFSET_0_VALID) != 0;
670  event_message.offset_1_valid = (ref_log_event.status & SBG_ECOM_EVENT_OFFSET_1_VALID) != 0;
671  event_message.offset_2_valid = (ref_log_event.status & SBG_ECOM_EVENT_OFFSET_2_VALID) != 0;
672  event_message.offset_3_valid = (ref_log_event.status & SBG_ECOM_EVENT_OFFSET_3_VALID) != 0;
673 
674  event_message.time_offset_0 = ref_log_event.timeOffset0;
675  event_message.time_offset_1 = ref_log_event.timeOffset1;
676  event_message.time_offset_2 = ref_log_event.timeOffset2;
677  event_message.time_offset_3 = ref_log_event.timeOffset3;
678 
679  return event_message;
680 }
681 
682 const sbg_driver::SbgGpsHdt MessageWrapper::createSbgGpsHdtMessage(const SbgLogGpsHdt& ref_log_gps_hdt) const
683 {
684  sbg_driver::SbgGpsHdt gps_hdt_message;
685 
686  gps_hdt_message.header = createRosHeader(ref_log_gps_hdt.timeStamp);
687  gps_hdt_message.time_stamp = ref_log_gps_hdt.timeStamp;
688  gps_hdt_message.status = ref_log_gps_hdt.status;
689  gps_hdt_message.tow = ref_log_gps_hdt.timeOfWeek;
690  gps_hdt_message.true_heading_acc = ref_log_gps_hdt.headingAccuracy;
691  gps_hdt_message.pitch_acc = ref_log_gps_hdt.pitchAccuracy;
692  gps_hdt_message.baseline = ref_log_gps_hdt.baseline;
693 
694  if (m_use_enu_)
695  {
696  gps_hdt_message.true_heading = wrapAngle360(90.0f - ref_log_gps_hdt.heading);
697  gps_hdt_message.pitch = -ref_log_gps_hdt.pitch;
698  }
699  else
700  {
701  gps_hdt_message.true_heading = ref_log_gps_hdt.heading;
702  gps_hdt_message.pitch = ref_log_gps_hdt.pitch;
703  }
704 
705  return gps_hdt_message;
706 }
707 
708 const sbg_driver::SbgGpsPos MessageWrapper::createSbgGpsPosMessage(const SbgLogGpsPos& ref_log_gps_pos) const
709 {
710  sbg_driver::SbgGpsPos gps_pos_message;
711 
712  gps_pos_message.header = createRosHeader(ref_log_gps_pos.timeStamp);
713  gps_pos_message.time_stamp = ref_log_gps_pos.timeStamp;
714 
715  gps_pos_message.status = createGpsPosStatusMessage(ref_log_gps_pos);
716  gps_pos_message.gps_tow = ref_log_gps_pos.timeOfWeek;
717  gps_pos_message.undulation = ref_log_gps_pos.undulation;
718  gps_pos_message.num_sv_used = ref_log_gps_pos.numSvUsed;
719  gps_pos_message.base_station_id = ref_log_gps_pos.baseStationId;
720  gps_pos_message.diff_age = ref_log_gps_pos.differentialAge;
721 
722  gps_pos_message.latitude = ref_log_gps_pos.latitude;
723  gps_pos_message.longitude = ref_log_gps_pos.longitude;
724  gps_pos_message.altitude = ref_log_gps_pos.altitude;
725 
726  if (m_use_enu_)
727  {
728  gps_pos_message.position_accuracy.x = ref_log_gps_pos.longitudeAccuracy;
729  gps_pos_message.position_accuracy.y = ref_log_gps_pos.latitudeAccuracy;
730  gps_pos_message.position_accuracy.z = ref_log_gps_pos.altitudeAccuracy;
731  }
732  else
733  {
734  gps_pos_message.position_accuracy.x = ref_log_gps_pos.latitudeAccuracy;
735  gps_pos_message.position_accuracy.y = ref_log_gps_pos.longitudeAccuracy;
736  gps_pos_message.position_accuracy.z = ref_log_gps_pos.altitudeAccuracy;
737  }
738 
739  return gps_pos_message;
740 }
741 
742 const sbg_driver::SbgGpsRaw MessageWrapper::createSbgGpsRawMessage(const SbgLogGpsRaw& ref_log_gps_raw) const
743 {
744  sbg_driver::SbgGpsRaw gps_raw_message;
745 
746  gps_raw_message.data.assign(ref_log_gps_raw.rawBuffer, ref_log_gps_raw.rawBuffer + ref_log_gps_raw.bufferSize);
747 
748  return gps_raw_message;
749 }
750 
751 const sbg_driver::SbgGpsVel MessageWrapper::createSbgGpsVelMessage(const SbgLogGpsVel& ref_log_gps_vel) const
752 {
753  sbg_driver::SbgGpsVel gps_vel_message;
754 
755  gps_vel_message.header = createRosHeader(ref_log_gps_vel.timeStamp);
756  gps_vel_message.time_stamp = ref_log_gps_vel.timeStamp;
757  gps_vel_message.status = createGpsVelStatusMessage(ref_log_gps_vel);
758  gps_vel_message.gps_tow = ref_log_gps_vel.timeOfWeek;
759  gps_vel_message.course_acc = ref_log_gps_vel.courseAcc;
760 
761  if (m_use_enu_)
762  {
763  gps_vel_message.velocity.x = ref_log_gps_vel.velocity[1];
764  gps_vel_message.velocity.y = ref_log_gps_vel.velocity[0];
765  gps_vel_message.velocity.z = -ref_log_gps_vel.velocity[2];
766 
767  gps_vel_message.velocity_accuracy.x = ref_log_gps_vel.velocityAcc[1];
768  gps_vel_message.velocity_accuracy.y = ref_log_gps_vel.velocityAcc[0];
769  gps_vel_message.velocity_accuracy.z = ref_log_gps_vel.velocityAcc[2];
770 
771  gps_vel_message.course = wrapAngle360(90.0f - ref_log_gps_vel.course);
772  }
773  else
774  {
775  gps_vel_message.velocity.x = ref_log_gps_vel.velocity[0];
776  gps_vel_message.velocity.y = ref_log_gps_vel.velocity[1];
777  gps_vel_message.velocity.z = ref_log_gps_vel.velocity[2];
778 
779  gps_vel_message.velocity_accuracy.x = ref_log_gps_vel.velocityAcc[0];
780  gps_vel_message.velocity_accuracy.y = ref_log_gps_vel.velocityAcc[1];
781  gps_vel_message.velocity_accuracy.z = ref_log_gps_vel.velocityAcc[2];
782 
783  gps_vel_message.course = ref_log_gps_vel.course;
784  }
785 
786  return gps_vel_message;
787 }
788 
789 const sbg_driver::SbgImuData MessageWrapper::createSbgImuDataMessage(const SbgLogImuData& ref_log_imu_data) const
790 {
791  sbg_driver::SbgImuData imu_data_message;
792 
793  imu_data_message.header = createRosHeader(ref_log_imu_data.timeStamp);
794  imu_data_message.time_stamp = ref_log_imu_data.timeStamp;
795  imu_data_message.imu_status = createImuStatusMessage(ref_log_imu_data.status);
796  imu_data_message.temp = ref_log_imu_data.temperature;
797 
798  if (m_use_enu_)
799  {
800  imu_data_message.accel.x = ref_log_imu_data.accelerometers[0];
801  imu_data_message.accel.y = -ref_log_imu_data.accelerometers[1];
802  imu_data_message.accel.z = -ref_log_imu_data.accelerometers[2];
803 
804  imu_data_message.gyro.x = ref_log_imu_data.gyroscopes[0];
805  imu_data_message.gyro.y = -ref_log_imu_data.gyroscopes[1];
806  imu_data_message.gyro.z = -ref_log_imu_data.gyroscopes[2];
807 
808  imu_data_message.delta_vel.x = ref_log_imu_data.deltaVelocity[0];
809  imu_data_message.delta_vel.y = -ref_log_imu_data.deltaVelocity[1];
810  imu_data_message.delta_vel.z = -ref_log_imu_data.deltaVelocity[2];
811 
812  imu_data_message.delta_angle.x = ref_log_imu_data.deltaAngle[0];
813  imu_data_message.delta_angle.y = -ref_log_imu_data.deltaAngle[1];
814  imu_data_message.delta_angle.z = -ref_log_imu_data.deltaAngle[2];
815  }
816  else
817  {
818  imu_data_message.accel.x = ref_log_imu_data.accelerometers[0];
819  imu_data_message.accel.y = ref_log_imu_data.accelerometers[1];
820  imu_data_message.accel.z = ref_log_imu_data.accelerometers[2];
821 
822  imu_data_message.gyro.x = ref_log_imu_data.gyroscopes[0];
823  imu_data_message.gyro.y = ref_log_imu_data.gyroscopes[1];
824  imu_data_message.gyro.z = ref_log_imu_data.gyroscopes[2];
825 
826  imu_data_message.delta_vel.x = ref_log_imu_data.deltaVelocity[0];
827  imu_data_message.delta_vel.y = ref_log_imu_data.deltaVelocity[1];
828  imu_data_message.delta_vel.z = ref_log_imu_data.deltaVelocity[2];
829 
830  imu_data_message.delta_angle.x = ref_log_imu_data.deltaAngle[0];
831  imu_data_message.delta_angle.y = ref_log_imu_data.deltaAngle[1];
832  imu_data_message.delta_angle.z = ref_log_imu_data.deltaAngle[2];
833  }
834 
835  return imu_data_message;
836 }
837 
838 const sbg_driver::SbgMag MessageWrapper::createSbgMagMessage(const SbgLogMag& ref_log_mag) const
839 {
840  sbg_driver::SbgMag mag_message;
841 
842  mag_message.header = createRosHeader(ref_log_mag.timeStamp);
843  mag_message.time_stamp = ref_log_mag.timeStamp;
844  mag_message.status = createMagStatusMessage(ref_log_mag);
845 
846  if (m_use_enu_)
847  {
848  mag_message.mag.x = ref_log_mag.magnetometers[0];
849  mag_message.mag.y = -ref_log_mag.magnetometers[1];
850  mag_message.mag.z = -ref_log_mag.magnetometers[2];
851 
852  mag_message.accel.x = ref_log_mag.accelerometers[0];
853  mag_message.accel.y = -ref_log_mag.accelerometers[1];
854  mag_message.accel.z = -ref_log_mag.accelerometers[2];
855  }
856  else
857  {
858  mag_message.mag.x = ref_log_mag.magnetometers[0];
859  mag_message.mag.y = ref_log_mag.magnetometers[1];
860  mag_message.mag.z = ref_log_mag.magnetometers[2];
861 
862  mag_message.accel.x = ref_log_mag.accelerometers[0];
863  mag_message.accel.y = ref_log_mag.accelerometers[1];
864  mag_message.accel.z = ref_log_mag.accelerometers[2];
865  }
866 
867  return mag_message;
868 }
869 
870 const sbg_driver::SbgMagCalib MessageWrapper::createSbgMagCalibMessage(const SbgLogMagCalib& ref_log_mag_calib) const
871 {
872  sbg_driver::SbgMagCalib mag_calib_message;
873 
874  // TODO. SbgMagCalib is not implemented.
875  mag_calib_message.header = createRosHeader(ref_log_mag_calib.timeStamp);
876 
877  return mag_calib_message;
878 }
879 
880 const sbg_driver::SbgOdoVel MessageWrapper::createSbgOdoVelMessage(const SbgLogOdometerData& ref_log_odo) const
881 {
882  sbg_driver::SbgOdoVel odo_vel_message;
883 
884  odo_vel_message.header = createRosHeader(ref_log_odo.timeStamp);
885  odo_vel_message.time_stamp = ref_log_odo.timeStamp;
886 
887  odo_vel_message.status = ref_log_odo.status;
888  odo_vel_message.vel = ref_log_odo.velocity;
889 
890  return odo_vel_message;
891 }
892 
893 const sbg_driver::SbgShipMotion MessageWrapper::createSbgShipMotionMessage(const SbgLogShipMotionData& ref_log_ship_motion) const
894 {
895  sbg_driver::SbgShipMotion ship_motion_message;
896 
897  ship_motion_message.header = createRosHeader(ref_log_ship_motion.timeStamp);
898  ship_motion_message.time_stamp = ref_log_ship_motion.timeStamp;
899  ship_motion_message.status = createShipMotionStatusMessage(ref_log_ship_motion);
900 
901  ship_motion_message.ship_motion.x = ref_log_ship_motion.shipMotion[0];
902  ship_motion_message.ship_motion.y = ref_log_ship_motion.shipMotion[1];
903  ship_motion_message.ship_motion.z = ref_log_ship_motion.shipMotion[2];
904 
905  ship_motion_message.acceleration.x = ref_log_ship_motion.shipAccel[0];
906  ship_motion_message.acceleration.y = ref_log_ship_motion.shipAccel[1];
907  ship_motion_message.acceleration.z = ref_log_ship_motion.shipAccel[2];
908 
909  ship_motion_message.velocity.x = ref_log_ship_motion.shipVel[0];
910  ship_motion_message.velocity.y = ref_log_ship_motion.shipVel[1];
911  ship_motion_message.velocity.z = ref_log_ship_motion.shipVel[2];
912 
913  return ship_motion_message;
914 }
915 
916 const sbg_driver::SbgStatus MessageWrapper::createSbgStatusMessage(const SbgLogStatusData& ref_log_status) const
917 {
918  sbg_driver::SbgStatus status_message;
919 
920  status_message.header = createRosHeader(ref_log_status.timeStamp);
921  status_message.time_stamp = ref_log_status.timeStamp;
922 
923  status_message.status_general = createStatusGeneralMessage(ref_log_status);
924  status_message.status_com = createStatusComMessage(ref_log_status);
925  status_message.status_aiding = createStatusAidingMessage(ref_log_status);
926 
927  return status_message;
928 }
929 
930 const sbg_driver::SbgUtcTime MessageWrapper::createSbgUtcTimeMessage(const SbgLogUtcData& ref_log_utc)
931 {
932  sbg_driver::SbgUtcTime utc_time_message;
933 
934  utc_time_message.header = createRosHeader(ref_log_utc.timeStamp);
935  utc_time_message.time_stamp = ref_log_utc.timeStamp;
936 
937  utc_time_message.clock_status = createUtcStatusMessage(ref_log_utc);
938  utc_time_message.year = ref_log_utc.year;
939  utc_time_message.month = ref_log_utc.month;
940  utc_time_message.day = ref_log_utc.day;
941  utc_time_message.hour = ref_log_utc.hour;
942  utc_time_message.min = ref_log_utc.minute;
943  utc_time_message.sec = ref_log_utc.second;
944  utc_time_message.nanosec = ref_log_utc.nanoSecond;
945  utc_time_message.gps_tow = ref_log_utc.gpsTimeOfWeek;
946 
947  if (!m_first_valid_utc_)
948  {
949  if (utc_time_message.clock_status.clock_stable && utc_time_message.clock_status.clock_utc_sync)
950  {
951  if (utc_time_message.clock_status.clock_status == SBG_ECOM_CLOCK_VALID)
952  {
953  m_first_valid_utc_ = true;
954  ROS_INFO("A full valid UTC log has been detected, timestamp will be synchronized with the UTC data.");
955  }
956  }
957  }
958 
959  //
960  // Store the last UTC message.
961  //
962  m_last_sbg_utc_ = utc_time_message;
963 
964  return utc_time_message;
965 }
966 
967 const sbg_driver::SbgAirData MessageWrapper::createSbgAirDataMessage(const SbgLogAirData& ref_air_data_log) const
968 {
969  sbg_driver::SbgAirData air_data_message;
970 
971  air_data_message.header = createRosHeader(ref_air_data_log.timeStamp);
972  air_data_message.time_stamp = ref_air_data_log.timeStamp;
973  air_data_message.status = createAirDataStatusMessage(ref_air_data_log);
974  air_data_message.pressure_abs = ref_air_data_log.pressureAbs;
975  air_data_message.altitude = ref_air_data_log.altitude;
976  air_data_message.pressure_diff = ref_air_data_log.pressureDiff;
977  air_data_message.true_air_speed = ref_air_data_log.trueAirspeed;
978  air_data_message.air_temperature = ref_air_data_log.airTemperature;
979 
980  return air_data_message;
981 }
982 
983 const sbg_driver::SbgImuShort MessageWrapper::createSbgImuShortMessage(const SbgLogImuShort& ref_short_imu_log) const
984 {
985  sbg_driver::SbgImuShort imu_short_message;
986 
987  imu_short_message.header = createRosHeader(ref_short_imu_log.timeStamp);
988  imu_short_message.time_stamp = ref_short_imu_log.timeStamp;
989  imu_short_message.imu_status = createImuStatusMessage(ref_short_imu_log.status);
990  imu_short_message.temperature = ref_short_imu_log.temperature;
991 
992  if (m_use_enu_)
993  {
994  imu_short_message.delta_velocity.x = ref_short_imu_log.deltaVelocity[0];
995  imu_short_message.delta_velocity.y = -ref_short_imu_log.deltaVelocity[1];
996  imu_short_message.delta_velocity.z = -ref_short_imu_log.deltaVelocity[2];
997 
998  imu_short_message.delta_angle.x = ref_short_imu_log.deltaAngle[0];
999  imu_short_message.delta_angle.y = -ref_short_imu_log.deltaAngle[1];
1000  imu_short_message.delta_angle.z = -ref_short_imu_log.deltaAngle[2];
1001  }
1002  else
1003  {
1004  imu_short_message.delta_velocity.x = ref_short_imu_log.deltaVelocity[0];
1005  imu_short_message.delta_velocity.y = ref_short_imu_log.deltaVelocity[1];
1006  imu_short_message.delta_velocity.z = ref_short_imu_log.deltaVelocity[2];
1007 
1008  imu_short_message.delta_angle.x = ref_short_imu_log.deltaAngle[0];
1009  imu_short_message.delta_angle.y = ref_short_imu_log.deltaAngle[1];
1010  imu_short_message.delta_angle.z = ref_short_imu_log.deltaAngle[2];
1011  }
1012 
1013  return imu_short_message;
1014 }
1015 
1016 const sensor_msgs::Imu MessageWrapper::createRosImuMessage(const sbg_driver::SbgImuData& ref_sbg_imu_msg, const sbg_driver::SbgEkfQuat& ref_sbg_quat_msg) const
1017 {
1018  sensor_msgs::Imu imu_ros_message;
1019 
1020  imu_ros_message.header = createRosHeader(ref_sbg_imu_msg.time_stamp);
1021 
1022  imu_ros_message.orientation = ref_sbg_quat_msg.quaternion;
1023  imu_ros_message.angular_velocity = ref_sbg_imu_msg.delta_angle;
1024  imu_ros_message.linear_acceleration = ref_sbg_imu_msg.delta_vel;
1025 
1026  imu_ros_message.orientation_covariance[0] = ref_sbg_quat_msg.accuracy.x * ref_sbg_quat_msg.accuracy.x;
1027  imu_ros_message.orientation_covariance[4] = ref_sbg_quat_msg.accuracy.y * ref_sbg_quat_msg.accuracy.y;
1028  imu_ros_message.orientation_covariance[8] = ref_sbg_quat_msg.accuracy.z * ref_sbg_quat_msg.accuracy.z;
1029 
1030  //
1031  // Angular velocity and linear acceleration covariances are not provided.
1032  //
1033  for (size_t i = 0; i < 9; i++)
1034  {
1035  imu_ros_message.angular_velocity_covariance[i] = 0.0;
1036  imu_ros_message.linear_acceleration_covariance[i] = 0.0;
1037  }
1038 
1039  return imu_ros_message;
1040 }
1041 
1042 void MessageWrapper::fillTransform(const std::string &ref_parent_frame_id, const std::string &ref_child_frame_id, const geometry_msgs::Pose &ref_pose, geometry_msgs::TransformStamped &refTransformStamped)
1043 {
1044  tf2::Quaternion q;
1045 
1046  refTransformStamped.header.stamp = ros::Time::now();
1047  refTransformStamped.header.frame_id = ref_parent_frame_id;
1048  refTransformStamped.child_frame_id = ref_child_frame_id;
1049 
1050  refTransformStamped.transform.translation.x = ref_pose.position.x;
1051  refTransformStamped.transform.translation.y = ref_pose.position.y;
1052  refTransformStamped.transform.translation.z = ref_pose.position.z;
1053  refTransformStamped.transform.rotation.x = ref_pose.orientation.x;
1054  refTransformStamped.transform.rotation.y = ref_pose.orientation.y;
1055  refTransformStamped.transform.rotation.z = ref_pose.orientation.z;
1056  refTransformStamped.transform.rotation.w = ref_pose.orientation.w;
1057 
1058  m_tf_broadcaster_.sendTransform(refTransformStamped);
1059 }
1060 
1061 const nav_msgs::Odometry MessageWrapper::createRosOdoMessage(const sbg_driver::SbgImuData &ref_sbg_imu_msg, const sbg_driver::SbgEkfNav &ref_ekf_nav_msg, const sbg_driver::SbgEkfQuat &ref_ekf_quat_msg, const sbg_driver::SbgEkfEuler &ref_ekf_euler_msg)
1062 {
1063  tf2::Quaternion orientation(ref_ekf_quat_msg.quaternion.x, ref_ekf_quat_msg.quaternion.y, ref_ekf_quat_msg.quaternion.z, ref_ekf_quat_msg.quaternion.w);
1064 
1065  return createRosOdoMessage(ref_sbg_imu_msg, ref_ekf_nav_msg, orientation, ref_ekf_euler_msg);
1066 }
1067 
1068 const nav_msgs::Odometry MessageWrapper::createRosOdoMessage(const sbg_driver::SbgImuData &ref_sbg_imu_msg, const sbg_driver::SbgEkfNav &ref_ekf_nav_msg, const sbg_driver::SbgEkfEuler &ref_ekf_euler_msg)
1069 {
1070  tf2::Quaternion orientation;
1071 
1072  // Compute orientation quaternion from euler angles (already converted from NED to ENU if needed).
1073  orientation.setRPY(ref_ekf_euler_msg.angle.x, ref_ekf_euler_msg.angle.y, ref_ekf_euler_msg.angle.z);
1074 
1075  return createRosOdoMessage(ref_sbg_imu_msg, ref_ekf_nav_msg, orientation, ref_ekf_euler_msg);
1076 }
1077 
1078 const nav_msgs::Odometry MessageWrapper::createRosOdoMessage(const sbg_driver::SbgImuData &ref_sbg_imu_msg, const sbg_driver::SbgEkfNav &ref_ekf_nav_msg, const tf2::Quaternion &ref_orientation, const sbg_driver::SbgEkfEuler &ref_ekf_euler_msg)
1079 {
1080  nav_msgs::Odometry odo_ros_msg;
1081  double utm_northing, utm_easting;
1082  std::string utm_zone;
1083  geometry_msgs::TransformStamped transform;
1084 
1085  // The pose message provides the position and orientation of the robot relative to the frame specified in header.frame_id
1086  odo_ros_msg.header = createRosHeader(ref_sbg_imu_msg.time_stamp);
1087  odo_ros_msg.header.frame_id = m_odom_frame_id_;
1088  tf2::convert(ref_orientation, odo_ros_msg.pose.pose.orientation);
1089 
1090  // Convert latitude and longitude to UTM coordinates.
1091  if (m_utm0_.zone == 0)
1092  {
1093  initUTM(ref_ekf_nav_msg.latitude, ref_ekf_nav_msg.longitude, ref_ekf_nav_msg.altitude);
1094 
1095  if (m_odom_publish_tf_)
1096  {
1097  // Publish UTM initial transformation.
1098  geometry_msgs::Pose pose;
1099  pose.position.x = m_utm0_.easting;
1100  pose.position.y = m_utm0_.northing;
1101  pose.position.z = m_utm0_.altitude;
1104  }
1105  }
1106 
1107  LLtoUTM(ref_ekf_nav_msg.latitude, ref_ekf_nav_msg.longitude, m_utm0_.zone, utm_easting, utm_northing);
1108  odo_ros_msg.pose.pose.position.x = utm_northing - m_utm0_.easting;
1109  odo_ros_msg.pose.pose.position.y = utm_easting - m_utm0_.northing;
1110  odo_ros_msg.pose.pose.position.z = ref_ekf_nav_msg.altitude - m_utm0_.altitude;
1111 
1112  // Compute convergence angle.
1113  double longitudeRad = sbgDegToRadD(ref_ekf_nav_msg.longitude);
1114  double latitudeRad = sbgDegToRadD(ref_ekf_nav_msg.latitude);
1115  double central_meridian = sbgDegToRadD(computeMeridian(m_utm0_.zone));
1116  double convergence_angle = atan(tan(longitudeRad - central_meridian) * sin(latitudeRad));
1117 
1118  // Convert position standard deviations to UTM frame.
1119  double std_east = ref_ekf_nav_msg.position_accuracy.x;
1120  double std_north = ref_ekf_nav_msg.position_accuracy.y;
1121  double std_x = std_north * cos(convergence_angle) - std_east * sin(convergence_angle);
1122  double std_y = std_north * sin(convergence_angle) + std_east * cos(convergence_angle);
1123  double std_z = ref_ekf_nav_msg.position_accuracy.z;
1124  odo_ros_msg.pose.covariance[0*6 + 0] = std_x * std_x;
1125  odo_ros_msg.pose.covariance[1*6 + 1] = std_y * std_y;
1126  odo_ros_msg.pose.covariance[2*6 + 2] = std_z * std_z;
1127  odo_ros_msg.pose.covariance[3*6 + 3] = ref_ekf_euler_msg.accuracy.x * ref_ekf_euler_msg.accuracy.x;
1128  odo_ros_msg.pose.covariance[4*6 + 4] = ref_ekf_euler_msg.accuracy.y * ref_ekf_euler_msg.accuracy.y;
1129  odo_ros_msg.pose.covariance[5*6 + 5] = ref_ekf_euler_msg.accuracy.z * ref_ekf_euler_msg.accuracy.z;
1130 
1131  // The twist message gives the linear and angular velocity relative to the frame defined in child_frame_id
1132  odo_ros_msg.child_frame_id = m_frame_id_;
1133  odo_ros_msg.twist.twist.linear.x = ref_ekf_nav_msg.velocity.x;
1134  odo_ros_msg.twist.twist.linear.y = ref_ekf_nav_msg.velocity.y;
1135  odo_ros_msg.twist.twist.linear.z = ref_ekf_nav_msg.velocity.z;
1136  odo_ros_msg.twist.twist.angular.x = ref_sbg_imu_msg.gyro.x;
1137  odo_ros_msg.twist.twist.angular.y = ref_sbg_imu_msg.gyro.y;
1138  odo_ros_msg.twist.twist.angular.z = ref_sbg_imu_msg.gyro.z;
1139  odo_ros_msg.twist.covariance[0*6 + 0] = ref_ekf_nav_msg.velocity_accuracy.x * ref_ekf_nav_msg.velocity_accuracy.x;
1140  odo_ros_msg.twist.covariance[1*6 + 1] = ref_ekf_nav_msg.velocity_accuracy.y * ref_ekf_nav_msg.velocity_accuracy.y;
1141  odo_ros_msg.twist.covariance[2*6 + 2] = ref_ekf_nav_msg.velocity_accuracy.z * ref_ekf_nav_msg.velocity_accuracy.z;
1142  odo_ros_msg.twist.covariance[3*6 + 3] = 0;
1143  odo_ros_msg.twist.covariance[4*6 + 4] = 0;
1144  odo_ros_msg.twist.covariance[5*6 + 5] = 0;
1145 
1146  if (m_odom_publish_tf_)
1147  {
1148  // Publish odom transformation.
1149  fillTransform(odo_ros_msg.header.frame_id, m_odom_base_frame_id_, odo_ros_msg.pose.pose, transform);
1150  m_tf_broadcaster_.sendTransform(transform);
1151  }
1152 
1153  return odo_ros_msg;
1154 }
1155 
1156 const sensor_msgs::Temperature MessageWrapper::createRosTemperatureMessage(const sbg_driver::SbgImuData& ref_sbg_imu_msg) const
1157 {
1158  sensor_msgs::Temperature temperature_message;
1159 
1160  temperature_message.header = createRosHeader(ref_sbg_imu_msg.time_stamp);
1161  temperature_message.temperature = ref_sbg_imu_msg.temp;
1162  temperature_message.variance = 0.0;
1163 
1164  return temperature_message;
1165 }
1166 
1167 const sensor_msgs::MagneticField MessageWrapper::createRosMagneticMessage(const sbg_driver::SbgMag& ref_sbg_mag_msg) const
1168 {
1169  sensor_msgs::MagneticField magnetic_message;
1170 
1171  magnetic_message.header = createRosHeader(ref_sbg_mag_msg.time_stamp);
1172  magnetic_message.magnetic_field = ref_sbg_mag_msg.mag;
1173 
1174  return magnetic_message;
1175 }
1176 
1177 const geometry_msgs::TwistStamped MessageWrapper::createRosTwistStampedMessage(const sbg_driver::SbgEkfEuler& ref_sbg_ekf_euler_msg, const sbg_driver::SbgEkfNav& ref_sbg_ekf_nav_msg, const sbg_driver::SbgImuData& ref_sbg_imu_msg) const
1178 {
1179  sbg::SbgMatrix3f tdcm;
1180  tdcm.makeDcm(sbg::SbgVector3f(ref_sbg_ekf_euler_msg.angle.x, ref_sbg_ekf_euler_msg.angle.y, ref_sbg_ekf_euler_msg.angle.z));
1181  tdcm.transpose();
1182 
1183  const sbg::SbgVector3f res = tdcm * sbg::SbgVector3f(ref_sbg_ekf_nav_msg.velocity.x, ref_sbg_ekf_nav_msg.velocity.y, ref_sbg_ekf_nav_msg.velocity.z);
1184 
1185  return createRosTwistStampedMessage(res, ref_sbg_imu_msg);
1186 }
1187 
1188 const geometry_msgs::TwistStamped MessageWrapper::createRosTwistStampedMessage(const sbg_driver::SbgEkfQuat& ref_sbg_ekf_quat_msg, const sbg_driver::SbgEkfNav& ref_sbg_ekf_nav_msg, const sbg_driver::SbgImuData& ref_sbg_imu_msg) const
1189 {
1190  sbg::SbgMatrix3f tdcm;
1191  tdcm.makeDcm(ref_sbg_ekf_quat_msg.quaternion.w, ref_sbg_ekf_quat_msg.quaternion.x, ref_sbg_ekf_quat_msg.quaternion.y, ref_sbg_ekf_quat_msg.quaternion.z);
1192  tdcm.transpose();
1193 
1194  const sbg::SbgVector3f res = tdcm * sbg::SbgVector3f(ref_sbg_ekf_nav_msg.velocity.x, ref_sbg_ekf_nav_msg.velocity.y, ref_sbg_ekf_nav_msg.velocity.z);
1195  return createRosTwistStampedMessage(res, ref_sbg_imu_msg);
1196 }
1197 
1198 const geometry_msgs::TwistStamped MessageWrapper::createRosTwistStampedMessage(const sbg::SbgVector3f& body_vel, const sbg_driver::SbgImuData& ref_sbg_imu_msg) const
1199 {
1200  geometry_msgs::TwistStamped twist_stamped_message;
1201 
1202  twist_stamped_message.header = createRosHeader(ref_sbg_imu_msg.time_stamp);
1203  twist_stamped_message.twist.angular = ref_sbg_imu_msg.delta_angle;
1204 
1205  twist_stamped_message.twist.linear.x = body_vel(0);
1206  twist_stamped_message.twist.linear.y = body_vel(1);
1207  twist_stamped_message.twist.linear.z = body_vel(2);
1208 
1209  return twist_stamped_message;
1210 }
1211 
1212 const geometry_msgs::PointStamped MessageWrapper::createRosPointStampedMessage(const sbg_driver::SbgEkfNav& ref_sbg_ekf_msg) const
1213 {
1214  geometry_msgs::PointStamped point_stamped_message;
1215 
1216  point_stamped_message.header = createRosHeader(ref_sbg_ekf_msg.time_stamp);
1217 
1218  //
1219  // Conversion from Geodetic coordinates to ECEF is based on World Geodetic System 1984 (WGS84).
1220  // Radius are expressed in meters, and latitude/longitude in radian.
1221  //
1222  double equatorial_radius;
1223  double polar_radius;
1224  double prime_vertical_radius;
1225  double eccentricity;
1226  double latitude;
1227  double longitude;
1228 
1229  equatorial_radius = 6378137.0;
1230  polar_radius = 6356752.314245;
1231  eccentricity = 1 - pow(polar_radius, 2) / pow(equatorial_radius, 2);
1232  latitude = sbgDegToRadD(ref_sbg_ekf_msg.latitude);
1233  longitude = sbgDegToRadD(ref_sbg_ekf_msg.longitude);
1234 
1235  prime_vertical_radius = equatorial_radius / sqrt(1.0 - pow(eccentricity, 2) * pow(sin(latitude), 2));
1236 
1237  point_stamped_message.point.x = (prime_vertical_radius + ref_sbg_ekf_msg.altitude) * cos(latitude) * cos(longitude);
1238  point_stamped_message.point.y = (prime_vertical_radius + ref_sbg_ekf_msg.altitude) * cos(latitude) * sin(longitude);
1239  point_stamped_message.point.z = ((pow(polar_radius, 2) / pow(equatorial_radius, 2)) * prime_vertical_radius + ref_sbg_ekf_msg.altitude) * sin(latitude);
1240 
1241  return point_stamped_message;
1242 }
1243 
1244 const sensor_msgs::TimeReference MessageWrapper::createRosUtcTimeReferenceMessage(const sbg_driver::SbgUtcTime& ref_sbg_utc_msg) const
1245 {
1246  sensor_msgs::TimeReference utc_reference_message;
1247 
1248  //
1249  // This message is defined to have comparison between the System time and the Utc reference.
1250  // Header of the ROS message will always be the System time, and the source is the computed time from Utc data.
1251  //
1252  utc_reference_message.header.stamp = ros::Time::now();
1253  utc_reference_message.time_ref = convertInsTimeToUnix(ref_sbg_utc_msg.time_stamp);
1254  utc_reference_message.source = "UTC time from device converted to Epoch";
1255 
1256  return utc_reference_message;
1257 }
1258 
1259 const sensor_msgs::NavSatFix MessageWrapper::createRosNavSatFixMessage(const sbg_driver::SbgGpsPos& ref_sbg_gps_msg) const
1260 {
1261  sensor_msgs::NavSatFix nav_sat_fix_message;
1262 
1263  nav_sat_fix_message.header = createRosHeader(ref_sbg_gps_msg.time_stamp);
1264 
1265  if (ref_sbg_gps_msg.status.type == SBG_ECOM_POS_NO_SOLUTION)
1266  {
1267  nav_sat_fix_message.status.status = nav_sat_fix_message.status.STATUS_NO_FIX;
1268  }
1269  else if (ref_sbg_gps_msg.status.type == SBG_ECOM_POS_SBAS)
1270  {
1271  nav_sat_fix_message.status.status = nav_sat_fix_message.status.STATUS_SBAS_FIX;
1272  }
1273  else
1274  {
1275  nav_sat_fix_message.status.status = nav_sat_fix_message.status.STATUS_FIX;
1276  }
1277 
1278  if (ref_sbg_gps_msg.status.glo_l1_used || ref_sbg_gps_msg.status.glo_l2_used)
1279  {
1280  nav_sat_fix_message.status.service = nav_sat_fix_message.status.SERVICE_GLONASS;
1281  }
1282  else
1283  {
1284  nav_sat_fix_message.status.service = nav_sat_fix_message.status.SERVICE_GPS;
1285  }
1286 
1287  nav_sat_fix_message.latitude = ref_sbg_gps_msg.latitude;
1288  nav_sat_fix_message.longitude = ref_sbg_gps_msg.longitude;
1289  nav_sat_fix_message.altitude = ref_sbg_gps_msg.altitude + ref_sbg_gps_msg.undulation;
1290 
1291  nav_sat_fix_message.position_covariance[0] = ref_sbg_gps_msg.position_accuracy.x * ref_sbg_gps_msg.position_accuracy.x;
1292  nav_sat_fix_message.position_covariance[4] = ref_sbg_gps_msg.position_accuracy.y * ref_sbg_gps_msg.position_accuracy.y;
1293  nav_sat_fix_message.position_covariance[8] = ref_sbg_gps_msg.position_accuracy.z * ref_sbg_gps_msg.position_accuracy.z;
1294 
1295  nav_sat_fix_message.position_covariance_type = nav_sat_fix_message.COVARIANCE_TYPE_DIAGONAL_KNOWN;
1296 
1297  return nav_sat_fix_message;
1298 }
1299 
1300 const sensor_msgs::FluidPressure MessageWrapper::createRosFluidPressureMessage(const sbg_driver::SbgAirData& ref_sbg_air_msg) const
1301 {
1302  sensor_msgs::FluidPressure fluid_pressure_message;
1303 
1304  fluid_pressure_message.header = createRosHeader(ref_sbg_air_msg.time_stamp);
1305  fluid_pressure_message.fluid_pressure = ref_sbg_air_msg.pressure_abs;
1306  fluid_pressure_message.variance = 0.0;
1307 
1308  return fluid_pressure_message;
1309 }
#define SBG_ECOM_PORTD_RX_OK
bool isLeapYear(uint16_t year) const
#define SBG_ECOM_AIDING_GPS1_VEL_RECV
#define SBG_ECOM_PORTD_TX_OK
#define SBG_ECOM_GPS_POS_GLO_L1_USED
#define SBG_ECOM_CLOCK_STABLE_INPUT
double easting
const sensor_msgs::NavSatFix createRosNavSatFixMessage(const sbg_driver::SbgGpsPos &ref_sbg_gps_msg) const
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
tf2_ros::TransformBroadcaster m_tf_broadcaster_
#define SBG_ECOM_GENERAL_MAIN_POWER_OK
const sbg_driver::SbgImuShort createSbgImuShortMessage(const SbgLogImuShort &ref_short_imu_log) const
SBG_INLINE SbgEComGpsVelType sbgEComLogGpsVelGetType(uint32_t status)
const std_msgs::Header createRosHeader(uint32_t device_timestamp) const
const nav_msgs::Odometry createRosOdoMessage(const sbg_driver::SbgImuData &ref_sbg_imu_msg, const sbg_driver::SbgEkfNav &ref_sbg_ekf_nav_msg, const sbg_driver::SbgEkfQuat &ref_sbg_ekf_quat_msg, const sbg_driver::SbgEkfEuler &ref_sbg_ekf_euler_msg)
void setOdomEnable(bool odom_enable)
#define SBG_ECOM_AIDING_MAG_RECV
uint32_t getNumberOfDaysInYear(uint16_t year) const
const sbg_driver::SbgEkfNav createSbgEkfNavMessage(const SbgLogEkfNavData &ref_log_ekf_nav) const
const sbg_driver::SbgAirData createSbgAirDataMessage(const SbgLogAirData &ref_air_data_log) const
#define SBG_ECOM_SOL_GPS1_POS_USED
#define SBG_ECOM_GPS_POS_GPS_L5_USED
#define SBG_ECOM_IMU_GYRO_Y_BIT
#define SBG_ECOM_EVENT_OFFSET_2_VALID
const sbg_driver::SbgStatusCom createStatusComMessage(const SbgLogStatusData &ref_log_status) const
const sensor_msgs::TimeReference createRosUtcTimeReferenceMessage(const sbg_driver::SbgUtcTime &ref_sbg_utc_msg) const
#define SBG_ECOM_AIR_DATA_PRESSURE_DIFF_VALID
#define SBG_ECOM_SOL_MAG_REF_USED
#define SBG_ECOM_PORTA_VALID
f
Time & fromNSec(uint64_t t)
#define SBG_ECOM_IMU_GYRO_Z_BIT
sbg_driver::SbgUtcTime m_last_sbg_utc_
#define SBG_ECOM_MAG_CALIBRATION_OK
#define SBG_ECOM_MAG_MAG_Z_BIT
#define SBG_ECOM_EVENT_OVERFLOW
#define SBG_ECOM_EVENT_OFFSET_1_VALID
uint64_t toNSec() const
void setOdomPublishTf(bool publish_tf)
#define SBG_ECOM_SOL_VERT_REF_USED
#define SBG_ECOM_SOL_HEADING_VALID
#define SBG_ECOM_SOL_GPS2_VEL_USED
SBG_INLINE SbgEComGpsPosStatus sbgEComLogGpsPosGetStatus(uint32_t status)
const sbg_driver::SbgImuStatus createImuStatusMessage(uint16_t sbg_imu_status) const
#define SBG_ECOM_SOL_GPS2_POS_USED
const sbg_driver::SbgAirDataStatus createAirDataStatusMessage(const SbgLogAirData &ref_sbg_air_data) const
#define SBG_ECOM_AIDING_DVL_RECV
const geometry_msgs::TwistStamped createRosTwistStampedMessage(const sbg::SbgVector3f &body_vel, const sbg_driver::SbgImuData &ref_sbg_imu_msg) const
const sbg_driver::SbgUtcTimeStatus createUtcStatusMessage(const SbgLogUtcData &ref_log_utc) const
const sbg_driver::SbgEkfStatus createEkfStatusMessage(uint32_t ekf_status) const
std::string m_odom_frame_id_
const ros::Time convertUtcToUnix(const sbg_driver::SbgUtcTime &ref_sbg_utc_msg) const
int32_t deltaVelocity[3]
#define SBG_ECOM_AIR_DATA_AIRPSEED_VALID
#define SBG_ECOM_MAG_ACCEL_Y_BIT
#define SBG_ECOM_PORTB_TX_OK
#define SBG_ECOM_PORTE_TX_OK
#define SBG_ECOM_PORTB_VALID
const sbg_driver::SbgStatusGeneral createStatusGeneralMessage(const SbgLogStatusData &ref_log_status) const
#define SBG_ECOM_SOL_POSITION_VALID
#define SBG_ECOM_PORTC_VALID
#define SBG_ECOM_PORTD_VALID
uint8_t rawBuffer[SBG_ECOM_GPS_RAW_MAX_BUFFER_SIZE]
#define SBG_ECOM_HEAVE_PERIOD_INCLUDED
Handle creation of messages.
double altitude
#define SBG_ECOM_SOL_ODO_USED
#define SBG_ECOM_GENERAL_IMU_POWER_OK
SBG_INLINE SbgEComGpsPosType sbgEComLogGpsPosGetType(uint32_t status)
#define SBG_ECOM_MAG_MAG_Y_BIT
#define SBG_ECOM_IMU_ACCEL_X_BIT
const sbg_driver::SbgEkfQuat createSbgEkfQuatMessage(const SbgLogEkfQuatData &ref_log_ekf_quat) const
SBG_INLINE SbgEComClockStatus sbgEComLogUtcGetClockStatus(uint16_t status)
const sbg_driver::SbgGpsPos createSbgGpsPosMessage(const SbgLogGpsPos &ref_log_gps_pos) const
#define SBG_ECOM_AIR_DATA_ALTITUDE_VALID
float wrapAngle360(float angle_deg) const
SBG_INLINE SbgEComSolutionMode sbgEComLogEkfGetSolutionMode(uint32_t status)
void setFrameId(const std::string &frame_id)
#define SBG_ECOM_GPS_POS_GPS_L2_USED
#define SBG_ECOM_AIDING_ODO_RECV
void transpose(void)
Definition: sbg_matrix3.h:176
void setTimeReference(TimeReference time_reference)
#define SBG_ECOM_MAG_MAG_X_BIT
#define SBG_ECOM_IMU_ACCELS_IN_RANGE
float accelerometers[3]
const sbg_driver::SbgUtcTime createSbgUtcTimeMessage(const SbgLogUtcData &ref_log_utc)
uint32_t getNumberOfDaysInMonth(uint16_t year, uint8_t month_index) const
const sensor_msgs::FluidPressure createRosFluidPressureMessage(const sbg_driver::SbgAirData &ref_sbg_air_msg) const
std::string m_frame_id_
#define SBG_ECOM_CAN_VALID
#define SBG_ECOM_MAG_ACCEL_X_BIT
#define SBG_ECOM_PORTC_TX_OK
#define SBG_ECOM_GPS_POS_GLO_L2_USED
double computeMeridian(int zone_number) const
float wrapAngle2Pi(float angle_rad) const
INLINE Rall1d< T, V, S > atan(const Rall1d< T, V, S > &x)
const sbg_driver::SbgShipMotion createSbgShipMotionMessage(const SbgLogShipMotionData &ref_log_ship_motion) const
#define SBG_ECOM_PORTB_RX_OK
#define SBG_ECOM_CLOCK_UTC_SYNC
#define SBG_ECOM_MAG_MAGS_IN_RANGE
#define ROS_INFO(...)
const sbg_driver::SbgMagCalib createSbgMagCalibMessage(const SbgLogMagCalib &ref_log_mag_calib) const
const sbg_driver::SbgEvent createSbgEventMessage(const SbgLogEvent &ref_log_event) const
const ros::Time convertInsTimeToUnix(uint32_t device_timestamp) const
SBG_INLINE SbgEComClockUtcStatus sbgEComLogUtcGetClockUtcStatus(uint16_t status)
#define SBG_ECOM_CAN_RX_OK
SbgVector3< float > SbgVector3f
Definition: sbg_vector3.h:178
TimeReference m_time_reference_
SBG_INLINE double sbgDegToRadD(double angle)
Definition: sbgDefines.h:361
float magnetometers[3]
#define SBG_ECOM_PORTE_VALID
std::string m_odom_init_frame_id_
#define SBG_ECOM_SOL_GPS1_VEL_USED
#define SBG_ECOM_GPS_POS_GPS_L1_USED
const sensor_msgs::Imu createRosImuMessage(const sbg_driver::SbgImuData &ref_sbg_imu_msg, const sbg_driver::SbgEkfQuat &ref_sbg_quat_msg) const
#define SBG_ECOM_SOL_VELOCITY_VALID
const sbg_driver::SbgStatus createSbgStatusMessage(const SbgLogStatusData &ref_log_status) const
#define SBG_ECOM_AIR_DATA_PRESSURE_ABS_VALID
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
SBG_INLINE SbgEComGpsVelStatus sbgEComLogGpsVelGetStatus(uint32_t status)
#define SBG_ECOM_MAG_ACCEL_Z_BIT
const sbg_driver::SbgMagStatus createMagStatusMessage(const SbgLogMag &ref_log_mag) const
#define SBG_ECOM_GENERAL_SETTINGS_OK
#define SBG_ECOM_SOL_GPS2_HDT_USED
const sbg_driver::SbgShipMotionStatus createShipMotionStatusMessage(const SbgLogShipMotionData &ref_log_ship_motion) const
double northing
#define SBG_ECOM_CAN_TX_OK
void sendTransform(const geometry_msgs::TransformStamped &transform)
void setOdomBaseFrameId(const std::string &ref_frame_id)
#define SBG_ECOM_HEAVE_PERIOD_VALID
#define SBG_ECOM_AIDING_GPS1_UTC_RECV
const geometry_msgs::PointStamped createRosPointStampedMessage(const sbg_driver::SbgEkfNav &ref_sbg_ekf_msg) const
#define SBG_ECOM_EVENT_OFFSET_0_VALID
#define SBG_ECOM_AIR_DATA_TIME_IS_DELAY
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
#define SBG_ECOM_MAG_ACCELS_IN_RANGE
#define SBG_ECOM_AIDING_GPS1_POS_RECV
const sbg_driver::SbgStatusAiding createStatusAidingMessage(const SbgLogStatusData &ref_log_status) const
#define SBG_ECOM_GENERAL_TEMPERATURE_OK
const sbg_driver::SbgImuData createSbgImuDataMessage(const SbgLogImuData &ref_log_imu_data) const
#define SBG_ECOM_PORTE_RX_OK
#define SBG_ECOM_HEAVE_VALID
char UTMLetterDesignator(double Lat)
const sbg_driver::SbgEkfEuler createSbgEkfEulerMessage(const SbgLogEkfEulerData &ref_log_ekf_euler) const
void setOdomFrameId(const std::string &ref_frame_id)
void fillTransform(const std::string &ref_parent_frame_id, const std::string &ref_child_frame_id, const geometry_msgs::Pose &ref_pose, geometry_msgs::TransformStamped &ref_transform_stamped)
void setUseEnu(bool enu)
#define SBG_ECOM_SOL_GPS1_HDT_USED
void makeDcm(const SbgVector3f &euler)
Definition: sbg_matrix3.h:199
const sbg_driver::SbgGpsVel createSbgGpsVelMessage(const SbgLogGpsVel &ref_log_gps_vel) const
#define SBG_ECOM_AIDING_GPS1_HDT_RECV
static Time now()
#define SBG_ECOM_IMU_ACCEL_Z_BIT
void convert(const A &a, B &b)
const sensor_msgs::Temperature createRosTemperatureMessage(const sbg_driver::SbgImuData &ref_sbg_imu_msg) const
#define SBG_ECOM_AIR_DATA_TEMPERATURE_VALID
const sbg_driver::SbgGpsVelStatus createGpsVelStatusMessage(const SbgLogGpsVel &ref_log_gps_vel) const
const sbg_driver::SbgMag createSbgMagMessage(const SbgLogMag &ref_log_mag) const
const std::string header
uint32_t timeStamp
#define SBG_ECOM_GENERAL_GPS_POWER_OK
#define SBG_ECOM_PORTA_RX_OK
const sensor_msgs::MagneticField createRosMagneticMessage(const sbg_driver::SbgMag &ref_sbg_mag_msg) const
#define SBG_ECOM_IMU_GYROS_IN_RANGE
#define SBG_ECOM_PORTC_RX_OK
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
INLINE Rall1d< T, V, S > tan(const Rall1d< T, V, S > &arg)
#define SBG_ECOM_PORTA_TX_OK
void setOdomInitFrameId(const std::string &ref_frame_id)
Handle a three components vector.
void sendTransform(const geometry_msgs::TransformStamped &transform)
void initUTM(double Lat, double Long, double altitude)
TimeReference
Definition: config_store.h:51
#define SBG_ECOM_SOL_ATTITUDE_VALID
#define SBG_ECOM_EVENT_OFFSET_3_VALID
void LLtoUTM(double Lat, double Long, int zoneNumber, double &UTMNorthing, double &UTMEasting) const
#define SBG_ECOM_IMU_GYRO_X_BIT
const sbg_driver::SbgGpsPosStatus createGpsPosStatusMessage(const SbgLogGpsPos &ref_log_gps_pos) const
const sbg_driver::SbgOdoVel createSbgOdoVelMessage(const SbgLogOdometerData &ref_log_odo) const
#define SBG_ECOM_IMU_COM_OK
#define SBG_PI_F
Definition: sbgDefines.h:293
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
#define SBG_ECOM_IMU_ACCEL_Y_BIT
const sbg_driver::SbgGpsHdt createSbgGpsHdtMessage(const SbgLogGpsHdt &ref_log_gps_hdt) const
std::string m_odom_base_frame_id_
tf2_ros::StaticTransformBroadcaster m_static_tf_broadcaster_
const sbg_driver::SbgGpsRaw createSbgGpsRawMessage(const SbgLogGpsRaw &ref_log_gps_raw) const
#define SBG_ECOM_IMU_STATUS_BIT
#define SBG_ECOM_HEAVE_VEL_AIDED


sbg_driver
Author(s): SBG Systems
autogenerated on Sat Sep 3 2022 02:53:35