From a2817d3c0765ed9e2bfc9226cea43701c9ec2a12 Mon Sep 17 00:00:00 2001 From: Quy Tonthat Date: Thu, 11 Oct 2007 08:53:11 +0000 Subject: [PATCH] Added new fields to trackpoints for data from GPS in realtime mode. - 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 --- ChangeLog | 1 + src/gpspoint.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++- src/gpx.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ src/vikgpslayer.c | 20 ++++++++++----- src/viktrack.c | 6 ++++- src/viktrack.h | 12 ++++++++- 6 files changed, 156 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 92872e02..63446a5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ Quy Tonthat : * 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 : diff --git a/src/gpspoint.c b/src/gpspoint.c index f6344a5e..7279b232 100644 --- a/src/gpspoint.c +++ b/src/gpspoint.c @@ -19,6 +19,7 @@ * */ +#include #include "viking.h" #include @@ -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" ); } diff --git a/src/gpx.c b/src/gpx.c index 53c08b88..ef1048c1 100644 --- 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, " \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, " %s\n", s_course ); + g_free(s_course); + } + if (!isnan(tp->speed)) { + gchar *s_speed = a_coords_dtostr(tp->speed); + fprintf ( f, " %s\n", s_speed ); + g_free(s_speed); + } + if (tp->fix_mode == VIK_GPS_MODE_2D) + fprintf ( f, " 2d\n"); + if (tp->fix_mode == VIK_GPS_MODE_3D) + fprintf ( f, " 3d\n"); + if (tp->nsats > 0) + fprintf ( f, " %d\n", tp->nsats ); + } + fprintf ( f, " \n" ); } diff --git a/src/vikgpslayer.c b/src/vikgpslayer.c index 973f9932..efcb4ec2 100644 --- a/src/vikgpslayer.c +++ b/src/vikgpslayer.c @@ -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) { diff --git a/src/viktrack.c b/src/viktrack.c index 1720724b..a5aa269e 100644 --- a/src/viktrack.c +++ b/src/viktrack.c @@ -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) diff --git a/src/viktrack.h b/src/viktrack.h index 047c59b1..0dc335e7 100644 --- a/src/viktrack.h +++ b/src/viktrack.h @@ -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; -- 2.39.5