]> git.street.me.uk Git - andy/viking.git/commitdiff
Added new fields to trackpoints for data from GPS in realtime mode.
authorQuy Tonthat <qtonthat@gmail.com>
Thu, 11 Oct 2007 08:53:11 +0000 (08:53 +0000)
committerQuy Tonthat <qtonthat@gmail.com>
Thu, 11 Oct 2007 08:53:11 +0000 (08:53 +0000)
- Speed, course, fix mode and number of satellites are now stored in trackpoint
  when received from GPS in realtime mode.

- There should be no backward compatibility problem. FIles saved by earlier
  version of viking can still be used.

- New data from files saved by viking from this change onward won't be
  recognised by earlier version of viking and will generate (lots of) warnings
  when read.

Signed-off-by: Quy Tonthat <qtonthat@gmail.com>
ChangeLog
src/gpspoint.c
src/gpx.c
src/vikgpslayer.c
src/viktrack.c
src/viktrack.h

index 92872e0260f2d3db26061fb06442eed20ee73641..63446a5cd7a533cbe3222b3c986e5b8cdbf72ecb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,7 @@ Quy Tonthat <qtonthat@gmail.com>:
        * Make Realtime Tracking a feature that can be disabled at configure
        time. Do not quietly disable it beacause libgps is not available
        at compiling time.
+       * Extra data from GPS in realtime mode are now stored in trackpoints.
 
 2007-10-10
 Quy Tonthat <qtonthat@gmail.com>:
index f6344a5ee89d8dc7b24f6f62ad68c9812cd539c5..7279b2326f3ecf3328313895dbb919f8b56564d2 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
+#include <math.h>
 #include "viking.h"
 
 #include <ctype.h>
@@ -70,6 +71,12 @@ static gboolean line_has_timestamp = FALSE;
 static time_t line_timestamp = 0;
 static gdouble line_altitude = VIK_DEFAULT_ALTITUDE;
 static gboolean line_visible = TRUE;
+
+static gboolean line_extended = FALSE;
+static gdouble line_speed = NAN;
+static gdouble line_course = NAN;
+static gint line_sat = 0;
+static gint line_fix = 0;
 /* other possible properties go here */
 
 
@@ -245,12 +252,22 @@ void a_gpspoint_read_file(VikTrwLayer *trw, FILE *f ) {
     }
     else if (line_type == GPSPOINT_TYPE_TRACKPOINT && current_track)
     {
-      VikTrackpoint *tp = g_malloc ( sizeof ( VikTrackpoint ) );
+      VikTrackpoint *tp = vik_trackpoint_new();
       vik_coord_load_from_latlon ( &(tp->coord), coord_mode, &line_latlon );
       tp->newsegment = line_newsegment;
       tp->has_timestamp = line_has_timestamp;
       tp->timestamp = line_timestamp;
       tp->altitude = line_altitude;
+      if (line_extended) {
+        tp->extended = TRUE;
+        tp->speed = line_speed;
+        tp->course = line_course;
+        tp->nsats = line_sat;
+        tp->fix_mode = line_fix;
+      }
+      else {
+        tp->extended = FALSE;
+      }
       current_track->trackpoints = g_list_append ( current_track->trackpoints, tp );
     }
 
@@ -273,6 +290,12 @@ void a_gpspoint_read_file(VikTrwLayer *trw, FILE *f ) {
     line_altitude = VIK_DEFAULT_ALTITUDE;
     line_visible = TRUE;
     line_symbol = NULL;
+
+    line_extended = FALSE;
+    line_speed = NAN;
+    line_course = NAN;
+    line_sat = 0;
+    line_fix = 0;
   }
 }
 
@@ -390,6 +413,26 @@ static void gpspoint_process_key_and_value ( const gchar *key, gint key_len, con
   {
     line_newsegment = TRUE;
   }
+  else if (key_len == 8 && strncasecmp( key, "extended", key_len ) == 0 && value != NULL)
+  {
+    line_extended = TRUE;
+  }
+  else if (key_len == 5 && strncasecmp( key, "speed", key_len ) == 0 && value != NULL)
+  {
+    line_speed = g_strtod(value, NULL);
+  }
+  else if (key_len == 6 && strncasecmp( key, "course", key_len ) == 0 && value != NULL)
+  {
+    line_course = g_strtod(value, NULL);
+  }
+  else if (key_len == 3 && strncasecmp( key, "sat", key_len ) == 0 && value != NULL)
+  {
+    line_sat = atoi(value);
+  }
+  else if (key_len == 3 && strncasecmp( key, "fix", key_len ) == 0 && value != NULL)
+  {
+    line_fix = atoi(value);
+  }
 }
 
 static void a_gpspoint_write_waypoint ( const gchar *name, VikWaypoint *wp, FILE *f )
@@ -435,6 +478,8 @@ static void a_gpspoint_write_trackpoint ( VikTrackpoint *tp, FILE *f )
   gchar *s_lat, *s_lon;
   vik_coord_to_latlon ( &(tp->coord), &ll );
 
+  /* TODO: modify a_coords_dtostr() to accept (optional) buffer
+   * instead of doing malloc/free everytime */
   s_lat = a_coords_dtostr(ll.lat);
   s_lon = a_coords_dtostr(ll.lon);
   fprintf ( f, "type=\"trackpoint\" latitude=\"%s\" longitude=\"%s\"", s_lat, s_lon );
@@ -450,6 +495,24 @@ static void a_gpspoint_write_trackpoint ( VikTrackpoint *tp, FILE *f )
     fprintf ( f, " unixtime=\"%ld\"", tp->timestamp );
   if ( tp->newsegment )
     fprintf ( f, " newsegment=\"yes\"" );
+
+  if (tp->extended) {
+    fprintf ( f, " extended=\"yes\"" );
+    if (!isnan(tp->speed)) {
+      gchar *s_speed = a_coords_dtostr(tp->speed);
+      fprintf ( f, " speed=\"%s\"", s_speed );
+      g_free(s_speed);
+    }
+    if (!isnan(tp->course)) {
+      gchar *s_course = a_coords_dtostr(tp->course);
+      fprintf ( f, " course=\"%s\"", s_course );
+      g_free(s_course);
+    }
+    if (tp->nsats > 0)
+      fprintf ( f, " sat=\"%d\"", tp->nsats );
+    if (tp->fix_mode > 0)
+      fprintf ( f, " fix=\"%d\"", tp->fix_mode );
+  }
   fprintf ( f, "\n" );
 }
 
index 53c08b88a17fd06eb273c961b80d2b536ae39a95..ef1048c19f43865c053e2dec9fcd84244a380c9e 100644 (file)
--- a/src/gpx.c
+++ b/src/gpx.c
@@ -54,6 +54,11 @@ typedef enum {
         tt_trk_trkseg_trkpt,
         tt_trk_trkseg_trkpt_ele,
         tt_trk_trkseg_trkpt_time,
+       /* extended */
+        tt_trk_trkseg_trkpt_course,
+        tt_trk_trkseg_trkpt_speed,
+        tt_trk_trkseg_trkpt_fix,
+        tt_trk_trkseg_trkpt_sat,
 
         tt_waypoint,
         tt_waypoint_coord,
@@ -95,6 +100,11 @@ tag_mapping tag_path_map[] = {
         { tt_trk_trkseg_trkpt, "/gpx/rte/rtept" },
         { tt_trk_trkseg_trkpt_ele, "/gpx/trk/trkseg/trkpt/ele" },
         { tt_trk_trkseg_trkpt_time, "/gpx/trk/trkseg/trkpt/time" },
+       /* extended */
+       { tt_trk_trkseg_trkpt_course, "/gpx/trk/trkseg/trkpt/course" },
+        { tt_trk_trkseg_trkpt_speed, "/gpx/trk/trkseg/trkpt/speed" },
+        { tt_trk_trkseg_trkpt_fix, "/gpx/trk/trkseg/trkpt/fix" },
+        { tt_trk_trkseg_trkpt_sat, "/gpx/trk/trkseg/trkpt/sat" },
 
         {0}
 };
@@ -314,6 +324,35 @@ static void gpx_end(VikTrwLayer *vtl, const char *el)
        g_string_erase ( c_cdata, 0, -1 );
        break;
 
+     case tt_trk_trkseg_trkpt_course:
+       c_tp->extended = TRUE;
+       c_tp->course = g_strtod ( c_cdata->str, NULL );
+       g_string_erase ( c_cdata, 0, -1 );
+       break;
+
+     case tt_trk_trkseg_trkpt_speed:
+       c_tp->extended = TRUE;
+       c_tp->speed = g_strtod ( c_cdata->str, NULL );
+       g_string_erase ( c_cdata, 0, -1 );
+       break;
+
+     case tt_trk_trkseg_trkpt_fix:
+       c_tp->extended = TRUE;
+       if (!strcmp("2d", c_cdata->str))
+         c_tp->fix_mode = VIK_GPS_MODE_2D;
+       else if (!strcmp("3d", c_cdata->str))
+         c_tp->fix_mode = VIK_GPS_MODE_3D;
+       else  /* TODO: more fix modes here */
+         c_tp->fix_mode = VIK_GPS_MODE_NOT_SEEN;
+       g_string_erase ( c_cdata, 0, -1 );
+       break;
+
+     case tt_trk_trkseg_trkpt_sat:
+       c_tp->extended = TRUE;
+       c_tp->nsats = atoi ( c_cdata->str );
+       g_string_erase ( c_cdata, 0, -1 );
+       break;
+
      default: break;
   }
 
@@ -332,6 +371,10 @@ static void gpx_cdata(void *dta, const XML_Char *s, int len)
     case tt_wpt_link:
     case tt_trk_desc:
     case tt_trk_trkseg_trkpt_time:
+    case tt_trk_trkseg_trkpt_course:
+    case tt_trk_trkseg_trkpt_speed:
+    case tt_trk_trkseg_trkpt_fix:
+    case tt_trk_trkseg_trkpt_sat:
     case tt_waypoint_name: /* .loc name is really description. */
       g_string_append_len ( c_cdata, s, len );
       break;
@@ -611,6 +654,25 @@ static void gpx_write_trackpoint ( VikTrackpoint *tp, FILE *f )
     time_buf [ strftime ( time_buf, sizeof(time_buf)-1, GPX_TIME_FORMAT, localtime(&(tp->timestamp)) ) ] = '\0';
     fprintf ( f, "    <time>%s</time>\n", time_buf );
   }
+  if (tp->extended && (tp->fix_mode >= VIK_GPS_MODE_2D)) {
+    if (!isnan(tp->course)) {
+      gchar *s_course = a_coords_dtostr(tp->course);
+      fprintf ( f, "    <course>%s</course>\n", s_course );
+      g_free(s_course);
+    }
+    if (!isnan(tp->speed)) {
+      gchar *s_speed = a_coords_dtostr(tp->speed);
+      fprintf ( f, "    <speed>%s</speed>\n", s_speed );
+      g_free(s_speed);
+    }
+    if (tp->fix_mode == VIK_GPS_MODE_2D)
+      fprintf ( f, "    <fix>2d</fix>\n");
+    if (tp->fix_mode == VIK_GPS_MODE_3D)
+      fprintf ( f, "    <fix>3d</fix>\n");
+    if (tp->nsats > 0)
+      fprintf ( f, "    <sat>%d</sat>\n", tp->nsats );
+  }
+
   fprintf ( f, "  </trkpt>\n" );
 }
 
index 973f993277fad3fa959d250e51e47e9417b56c75..efcb4ec2b7fbc17c9762b3e0a883bb48d12335b7 100644 (file)
@@ -187,6 +187,7 @@ typedef struct {
 
 typedef struct {
   struct gps_fix_t fix;
+  gint satellites_used;
   gboolean dirty;   /* needs to be saved */
 } GpsFix;
 #endif /* VIK_CONFIG_REALTIME_GPS_TRACKING */
@@ -1092,10 +1093,15 @@ static void create_realtime_trackpoint(VikGpsLayer *vgl, gboolean forced)
         /* TODO: check for new segments */
         VikTrackpoint *tp = vik_trackpoint_new();
         tp->newsegment = FALSE;
-        // tp->altitude = isnan(vgl->realtime_fix.fix.altitude) ? VIK_DEFAULT_ALTITUDE : vgl->realtime_fix.fix.altitude;
-        tp->altitude = alt;
         tp->has_timestamp = TRUE;
         tp->timestamp = vgl->realtime_fix.fix.time;
+        tp->altitude = alt;
+        /* speed only available for 3D fix. Check for NAN when use this speed */
+        tp->speed = vgl->realtime_fix.fix.speed;  
+        tp->course = vgl->realtime_fix.fix.track;
+        tp->nsats = vgl->realtime_fix.satellites_used;
+        tp->fix_mode = vgl->realtime_fix.fix.mode;
+        tp->extended = TRUE;
 
         ll.lat = vgl->realtime_fix.fix.latitude;
         ll.lon = vgl->realtime_fix.fix.longitude;
@@ -1104,6 +1110,7 @@ static void create_realtime_trackpoint(VikGpsLayer *vgl, gboolean forced)
 
         vgl->realtime_track->trackpoints = g_list_append(vgl->realtime_track->trackpoints, tp);
         vgl->realtime_fix.dirty = FALSE;
+        vgl->realtime_fix.satellites_used = 0;
         vgl->last_fix = vgl->realtime_fix;
       }
     }
@@ -1120,17 +1127,13 @@ void gpsd_raw_hook(VglGpsd *vgpsd, gchar *data)
     return;
   }
 
-#ifdef XXXXXXXXXXXXX
-  if ((time_t)vgl->realtime_fix.fix.time == (time_t)vgpsd->gpsd.fix.time)
-    return;
-#endif /*XXXXXXXXXXXX*/
-
   if ((vgpsd->gpsd.fix.mode >= MODE_2D) &&
       !isnan(vgpsd->gpsd.fix.latitude) &&
       !isnan(vgpsd->gpsd.fix.longitude) &&
       !isnan(vgpsd->gpsd.fix.track)) {
     g_mutex_lock(vgl->realtime_tracking_mutex);
     vgl->realtime_fix.fix = vgpsd->gpsd.fix;
+    vgl->realtime_fix.satellites_used = vgpsd->gpsd.satellites_used;
     vgl->realtime_fix.dirty = TRUE;
 
     if (vgl->realtime_keep_at_center ||
@@ -1183,6 +1186,9 @@ static void gps_start_stop_tracking_cb( gpointer layer_and_vlp[2])
   VikGpsLayer *vgl = (VikGpsLayer *)layer_and_vlp[0];
   vgl->realtime_tracking = (vgl->realtime_tracking == FALSE);
 
+  /* Make sure we are still in the boat with libgps */
+  g_assert((VIK_GPS_MODE_2D == MODE_2D) && (VIK_GPS_MODE_3D == MODE_3D));
+
   if (vgl->realtime_tracking) {
     struct gps_data_t *gpsd = gps_open(vgl->gpsd_host, vgl->gpsd_port);
     if (gpsd == NULL) {
index 1720724bf6957331b822dbe48b2781f96efe1f93..a5aa269e7238a79e097c52213c76fe290c0278ce 100644 (file)
@@ -94,7 +94,11 @@ VikTrack *vik_track_copy ( const VikTrack *tr )
 
 VikTrackpoint *vik_trackpoint_new()
 {
-  return g_malloc0(sizeof(VikTrackpoint));
+  VikTrackpoint *tp = g_malloc0(sizeof(VikTrackpoint));
+  tp->extended = FALSE;
+  tp->speed = NAN;
+  tp->course = NAN;
+  return tp;
 }
 
 void vik_trackpoint_free(VikTrackpoint *tp)
index 047c59b13b62fd64fb77c32931b7ed6046cfbe92..0dc335e742cd5700f488aff8c973301fa26bdcb2 100644 (file)
@@ -38,7 +38,17 @@ struct _VikTrackpoint {
   gboolean newsegment;
   gboolean has_timestamp;
   time_t timestamp;
-  gdouble altitude;
+  gdouble altitude;    /* only in 3D fixes */
+  /* Most GPSs provide this in realtime mode (NMEA) but not in data mode */
+  gboolean extended;
+  gdouble speed;       /* only in 3D fixes */
+  gdouble course;
+  guint nsats;         /* number of satellites used */
+#define VIK_GPS_MODE_NOT_SEEN  0       /* mode update not seen yet */
+#define VIK_GPS_MODE_NO_FIX    1       /* none */
+#define VIK_GPS_MODE_2D        2       /* good for latitude/longitude */
+#define VIK_GPS_MODE_3D        3       /* good for altitude/climb too */
+  gint fix_mode;
 };
 
 typedef struct _VikTrack VikTrack;