* 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>:
*
*/
+#include <math.h>
#include "viking.h"
#include <ctype.h>
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 */
}
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 );
}
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;
}
}
{
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 )
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 );
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" );
}
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,
{ 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}
};
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;
}
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;
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" );
}
typedef struct {
struct gps_fix_t fix;
+ gint satellites_used;
gboolean dirty; /* needs to be saved */
} GpsFix;
#endif /* VIK_CONFIG_REALTIME_GPS_TRACKING */
/* 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;
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;
}
}
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 ||
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) {
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)
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;