LCOV - code coverage report
Current view: top level - SITL - SIM_GPS_NMEA.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 38 52 73.1 %
Date: 2026-09-09 11:02:08 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "SIM_config.h"
       2             : 
       3             : #if AP_SIM_GPS_NMEA_ENABLED
       4             : 
       5             : #include "SIM_GPS_NMEA.h"
       6             : 
       7             : #include <SITL/SITL.h>
       8             : #include <AP_Common/NMEA.h>
       9             : #include <AP_HAL/AP_HAL.h>
      10             : 
      11             : #include <time.h>
      12             : #include <sys/time.h>
      13             : 
      14             : extern const AP_HAL::HAL& hal;
      15             : 
      16             : using namespace SITL;
      17             : 
      18             : /*
      19             :   formatted print of NMEA message, with checksum appended
      20             :  */
      21        1538 : void GPS_NMEA::nmea_printf(const char *fmt, ...)
      22             : {
      23             :     va_list ap;
      24             : 
      25        1538 :     va_start(ap, fmt);
      26        1538 :     char *s = nmea_vaprintf(fmt, ap);
      27        1538 :     va_end(ap);
      28        1538 :     if (s != nullptr) {
      29        1538 :         write_to_autopilot((const char*)s, strlen(s));
      30        1538 :         free(s);
      31             :     }
      32        1538 : }
      33             : 
      34             : 
      35             : /*
      36             :   send a new GPS NMEA packet
      37             :  */
      38         406 : void GPS_NMEA::publish(const GPS_Data *d)
      39             : {
      40             :     struct timeval tv;
      41             :     struct tm *tm;
      42             :     char tstring[20];
      43             :     char dstring[20];
      44             :     char lat_string[20];
      45             :     char lng_string[20];
      46             : 
      47         406 :     simulation_timeval(&tv);
      48             : 
      49         406 :     struct tm tvd {};
      50         406 :     tm = gmtime_r(&tv.tv_sec, &tvd);
      51             : 
      52             :     // format time string
      53         406 :     hal.util->snprintf(tstring, sizeof(tstring), "%02u%02u%06.3f", tm->tm_hour, tm->tm_min, tm->tm_sec + tv.tv_usec*1.0e-6);
      54             : 
      55             :     // format date string
      56         406 :     hal.util->snprintf(dstring, sizeof(dstring), "%02u%02u%02u", tm->tm_mday, tm->tm_mon+1, tm->tm_year % 100);
      57             : 
      58             :     // format latitude
      59         406 :     double deg = fabs(d->latitude);
      60         406 :     hal.util->snprintf(lat_string, sizeof(lat_string), "%02u%08.5f,%c",
      61             :              (unsigned)deg,
      62         406 :              (deg - int(deg))*60,
      63         406 :              d->latitude<0?'S':'N');
      64             : 
      65             :     // format longitude
      66         406 :     deg = fabs(d->longitude);
      67         406 :     hal.util->snprintf(lng_string, sizeof(lng_string), "%03u%08.5f,%c",
      68             :              (unsigned)deg,
      69         406 :              (deg - int(deg))*60,
      70         406 :              d->longitude<0?'W':'E');
      71             : 
      72         412 :     nmea_printf("$GPGGA,%s,%s,%s,%01d,%02d,%04.1f,%07.2f,M,0.0,M,,",
      73             :                      tstring,
      74             :                      lat_string,
      75             :                      lng_string,
      76         406 :                      d->have_lock?1:0,
      77         400 :                      d->have_lock?d->num_sats:3,
      78             :                      1.2,
      79         406 :                      d->altitude);
      80             : 
      81         406 :     const float speed_mps = d->speed_2d();
      82         406 :     const float speed_knots = speed_mps * M_PER_SEC_TO_KNOTS;
      83         406 :     const auto ground_track_deg = degrees(d->ground_track_rad());
      84             : 
      85             :     //$GPVTG,133.18,T,120.79,M,0.11,N,0.20,K,A*24
      86         406 :     nmea_printf("$GPVTG,%.2f,T,%.2f,M,%.2f,N,%.2f,K,A",
      87             :                      tstring,
      88             :                      ground_track_deg,
      89             :                      ground_track_deg,
      90             :                      speed_knots,
      91         406 :                      speed_knots * KNOTS_TO_METERS_PER_SECOND * 3.6);
      92             : 
      93         406 :     nmea_printf("$GPRMC,%s,%c,%s,%s,%.2f,%.2f,%s,,",
      94             :                      tstring,
      95         406 :                      d->have_lock?'A':'V',
      96             :                      lat_string,
      97             :                      lng_string,
      98             :                      speed_knots,
      99             :                      ground_track_deg,
     100             :                      dstring);
     101             : 
     102         406 :     if (_sitl->gps[instance].hdg_enabled == SITL::SIM::GPS_HEADING_HDT) {
     103         320 :         nmea_printf("$GPHDT,%.2f,T", d->yaw_deg);
     104             :     }
     105          86 :     else if (_sitl->gps[instance].hdg_enabled == SITL::SIM::GPS_HEADING_THS) {
     106           0 :         nmea_printf("$GPTHS,%.2f,%c,T", d->yaw_deg, d->have_lock ? 'A' : 'V');
     107          86 :     } else if (_sitl->gps[instance].hdg_enabled == SITL::SIM::GPS_HEADING_KSXT) {
     108             :         // Unicore support
     109             :         // $KSXT,20211016083433.00,116.31296102,39.95817066,49.4911,223.57,-11.32,330.19,0.024,,1,3,28,27,,,,-0.012,0.021,0.020,,*2D
     110           0 :         nmea_printf("$KSXT,%04u%02u%02u%02u%02u%02u.%02u,%.8f,%.8f,%.4f,%.2f,%.2f,%.2f,%.2f,%.3f,%u,%u,%u,%u,,,,%.3f,%.3f,%.3f,,",
     111           0 :                     tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, unsigned(tv.tv_usec*1.e-4),
     112           0 :                     d->longitude, d->latitude,
     113           0 :                     d->altitude,
     114           0 :                     wrap_360(d->yaw_deg),
     115           0 :                     d->pitch_deg,
     116             :                     ground_track_deg,
     117             :                     speed_mps,
     118           0 :                     d->roll_deg,
     119           0 :                     d->have_lock?1:0, // 2=rtkfloat 3=rtkfixed,
     120             :                     3, // fixed rtk yaw solution,
     121           0 :                     d->have_lock?d->num_sats:3,
     122           0 :                     d->have_lock?d->num_sats:3,
     123           0 :                     d->speedE * 3.6,
     124           0 :                     d->speedN * 3.6,
     125           0 :                     -d->speedD * 3.6);
     126             :     }
     127         406 : }
     128             : 
     129             : #endif  // AP_SIM_GPS_NMEA_ENABLED

Generated by: LCOV version 1.14