From ef34f9849b0158a67750fce154a92f322451f2d3 Mon Sep 17 00:00:00 2001 From: Ankit Date: Tue, 3 Mar 2015 02:18:50 +0530 Subject: [PATCH] Add property Heading to Location object Heading property tells the direction in which the device is headed to. This property will be helpful in implementating code for moving devices. It's also calculating the new direction on location change. https://bugs.freedesktop.org/show_bug.cgi?id=89395 --- src/gclue-location-source.c | 1 + src/gclue-locator.c | 5 ++ src/gclue-service-location.c | 3 ++ src/geocode-glib/geocode-location.c | 93 +++++++++++++++++++++++++++++++++++++ src/geocode-glib/geocode-location.h | 70 ++++++++++++++++++++++++++++ src/org.freedesktop.GeoClue2.xml | 7 +++ src/public-api/gclue-enums.h | 28 +++++++++++ 7 files changed, 207 insertions(+) diff --git a/src/gclue-location-source.c b/src/gclue-location-source.c index 17a4c87..5864a5d 100644 --- a/src/gclue-location-source.c +++ b/src/gclue-location-source.c @@ -276,6 +276,7 @@ gclue_location_source_set_location (GClueLocationSource *source, "accuracy", geocode_location_get_accuracy (location), "description", geocode_location_get_description (location), "speed", geocode_location_get_speed (location), + "heading", geocode_location_get_heading (location), NULL); g_object_notify (G_OBJECT (source), "location"); diff --git a/src/gclue-locator.c b/src/gclue-locator.c index a9185ca..277773c 100644 --- a/src/gclue-locator.c +++ b/src/gclue-locator.c @@ -77,6 +77,7 @@ set_location (GClueLocator *locator, guint64 cur_timestamp, timestamp; const gdouble ALPHA = 0.12; // This value can modulate noise in speed. gdouble cur_speed, speed; + guint heading; cur_location = gclue_location_source_get_location (GCLUE_LOCATION_SOURCE (locator)); @@ -99,6 +100,7 @@ set_location (GClueLocator *locator, if (cur_location == NULL) { // if it is the first location value speed = 0.0; + heading = GEOCODE_LOCATION_HEADING_NOWHERE; } else { cur_timestamp = geocode_location_get_timestamp (cur_location); timestamp = geocode_location_get_timestamp (location); @@ -108,9 +110,12 @@ set_location (GClueLocator *locator, speed = cur_speed * ALPHA + (1 - ALPHA) * geocode_location_get_distance_from (cur_location, location) * 1000.0 / (timestamp - cur_timestamp); + heading = geocode_location_get_heading_direction (cur_location, + location); } geocode_location_set_speed (location, speed); + geocode_location_set_heading (location, heading); gclue_location_source_set_location (GCLUE_LOCATION_SOURCE (locator), location); diff --git a/src/gclue-service-location.c b/src/gclue-service-location.c index d058faa..0163740 100644 --- a/src/gclue-service-location.c +++ b/src/gclue-service-location.c @@ -98,6 +98,7 @@ gclue_service_location_get_property (GObject *object, gclue_location_get_accuracy (location), gclue_location_get_description (location)); g_object_set (loc, "speed", gclue_location_get_speed (location), NULL); + g_object_set (loc, "heading", gclue_location_get_heading (location), NULL); altitude = gclue_location_get_altitude (location); if (altitude != GEOCODE_LOCATION_ALTITUDE_UNKNOWN) g_object_set (loc, "altitude", altitude, NULL); @@ -149,6 +150,8 @@ gclue_service_location_set_property (GObject *object, (location, geocode_location_get_description (loc)); gclue_location_set_speed (location, geocode_location_get_speed (loc)); + gclue_location_set_heading + (location, geocode_location_get_heading (loc)); altitude = geocode_location_get_altitude (loc); if (altitude != GEOCODE_LOCATION_ALTITUDE_UNKNOWN) gclue_location_set_altitude (location, altitude); diff --git a/src/geocode-glib/geocode-location.c b/src/geocode-glib/geocode-location.c index d0244e2..99e2f3e 100644 --- a/src/geocode-glib/geocode-location.c +++ b/src/geocode-glib/geocode-location.c @@ -44,6 +44,7 @@ struct _GeocodeLocationPrivate { gdouble altitude; gdouble accuracy; gdouble speed; + guint heading; guint64 timestamp; char *description; GeocodeLocationCRS crs; @@ -59,6 +60,7 @@ enum { PROP_TIMESTAMP, PROP_ALTITUDE, PROP_CRS, + PROP_HEADING, PROP_SPEED, }; @@ -113,6 +115,11 @@ geocode_location_get_property (GObject *object, geocode_location_get_speed (location)); break; + case PROP_HEADING: + g_value_set_uint (value, + geocode_location_get_heading (location)); + break; + default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -172,6 +179,15 @@ geocode_location_set_speed (GeocodeLocation *loc, loc->priv->speed = speed; } +void +geocode_location_set_heading(GeocodeLocation *loc, + guint heading) +{ + g_return_if_fail (GEOCODE_IS_LOCATION (loc)); + + loc->priv->heading = heading; +} + static void geocode_location_set_property(GObject *object, guint property_id, @@ -216,6 +232,11 @@ geocode_location_set_property(GObject *object, g_value_get_double (value)); break; + case PROP_HEADING: + geocode_location_set_heading (location, + g_value_get_uint (value)); + break; + default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -505,6 +526,21 @@ geocode_location_class_init (GeocodeLocationClass *klass) g_object_class_install_property (glocation_class, PROP_SPEED, pspec); /** + * GeocodeLocation:heading: + * + * The direction in which the device is heading to. + */ + pspec = g_param_spec_uint ("heading", + "Heading", + "The direction in which the device is heading to", + GEOCODE_LOCATION_HEADING_NOWHERE, + GEOCODE_LOCATION_HEADING_SOUTH_WEST, + GEOCODE_LOCATION_HEADING_NOWHERE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_property (glocation_class, PROP_HEADING, pspec); + + /** * GeocodeLocation:accuracy: * * The accuracy of this location in meters. @@ -787,6 +823,23 @@ geocode_location_get_speed (GeocodeLocation *loc) return loc->priv->speed; } +/** + * geocode_location_get_heading: + * @loc: a #GeocodeLocation + * + * Gets the direction towards which device is heading. + * i.e. 4 primary directions + 4 secondary directions + * + * Returns: The direction in which device is heading. + **/ +guint +geocode_location_get_heading (GeocodeLocation *loc) +{ + g_return_val_if_fail (GEOCODE_IS_LOCATION (loc), GEOCODE_LOCATION_HEADING_NOWHERE); + + return loc->priv->heading; +} + static char * geo_uri_from_location (GeocodeLocation *loc) { @@ -881,3 +934,43 @@ geocode_location_get_distance_from (GeocodeLocation *loca, c = 2 * atan2 (sqrt (a), sqrt (1-a)); return EARTH_RADIUS_KM * c; } + +guint +geocode_location_get_heading_direction (GeocodeLocation *loca, + GeocodeLocation *locb) +{ + const gdouble EPSILON = 0.05 / 1000.0 ; // 5 centimeters + gdouble dx, dy, angle; + gint dir; + + g_return_val_if_fail (GEOCODE_IS_LOCATION (loca), + GEOCODE_LOCATION_HEADING_NOWHERE); + g_return_val_if_fail (GEOCODE_IS_LOCATION (locb), + GEOCODE_LOCATION_HEADING_NOWHERE); + + dx = (locb->priv->latitude - loca->priv->latitude); + dy = (locb->priv->longitude - loca->priv->longitude); + + if (geocode_location_get_distance_from (loca, loca) < EPSILON){ + return GEOCODE_LOCATION_HEADING_NOWHERE; + } + // atan2 returns a value in range (-PI,PI] + angle = atan2 (dy, dx); + /* that value is divided into 8 segments and then + * rounded off, in order to snap to 8 directions */ + dir = (int) nearbyint (angle / M_PI * 4.0); + + switch(dir){ + case 0: return GEOCODE_LOCATION_HEADING_EAST; + case 1: return GEOCODE_LOCATION_HEADING_NORTH_EAST; + case 2: return GEOCODE_LOCATION_HEADING_NORTH; + case 3: return GEOCODE_LOCATION_HEADING_NORTH_WEST; + case 4: + case -4: return GEOCODE_LOCATION_HEADING_WEST; + case -3: return GEOCODE_LOCATION_HEADING_SOUTH_WEST; + case -2: return GEOCODE_LOCATION_HEADING_SOUTH; + case -1: return GEOCODE_LOCATION_HEADING_SOUTH_EAST; + } + + return GEOCODE_LOCATION_HEADING_NOWHERE; +} diff --git a/src/geocode-glib/geocode-location.h b/src/geocode-glib/geocode-location.h index 1703e2f..6101f0d 100644 --- a/src/geocode-glib/geocode-location.h +++ b/src/geocode-glib/geocode-location.h @@ -131,6 +131,69 @@ typedef enum { */ #define GEOCODE_LOCATION_ACCURACY_CONTINENT 3000000 /* 3000 km */ +/** + * GEOCODE_LOCATION_HEADING_NOWHERE: + * + * It specicifies that device is not moving + */ +#define GEOCODE_LOCATION_HEADING_NOWHERE 0 + +/** + * GEOCODE_LOCATION_HEADING_NORTH: + * + * It specicifies that device is moving towards North + */ +#define GEOCODE_LOCATION_HEADING_NORTH 1 + +/** + * GEOCODE_LOCATION_HEADING_EAST: + * + * It specicifies that device is moving towards East + */ +#define GEOCODE_LOCATION_HEADING_EAST 2 + +/** + * GEOCODE_LOCATION_HEADING_SOUTH: + * + * It specicifies that device is moving towards South + */ +#define GEOCODE_LOCATION_HEADING_SOUTH 4 + +/** + * GEOCODE_LOCATION_HEADING_WEST: + * + * It specicifies that device is moving towards West + */ +#define GEOCODE_LOCATION_HEADING_WEST 8 + +/** + * GEOCODE_LOCATION_HEADING_NORTH_EAST: + * + * It specicifies that device is moving towards North-East + */ +#define GEOCODE_LOCATION_HEADING_NORTH_EAST 3 + +/** + * GEOCODE_LOCATION_HEADING_NORTH_WEST: + * + * It specicifies that device is moving towards North-West + */ +#define GEOCODE_LOCATION_HEADING_NORTH_WEST 9 + +/** + * GEOCODE_LOCATION_HEADING_SOUTH_EAST: + * + * It specicifies that device is moving towards South-East + */ +#define GEOCODE_LOCATION_HEADING_SOUTH_EAST 6 + +/** + * GEOCODE_LOCATION_HEADING_SOUTH_WEST: + * + * It specicifies that device is moving towards South-West + */ +#define GEOCODE_LOCATION_HEADING_SOUTH_WEST 12 + #define GEOCODE_TYPE_LOCATION (geocode_location_get_type ()) GeocodeLocation *geocode_location_new (gdouble latitude, @@ -152,12 +215,18 @@ char * geocode_location_to_uri (GeocodeLocation *loc, double geocode_location_get_distance_from (GeocodeLocation *loca, GeocodeLocation *locb); +guint geocode_location_get_heading_direction (GeocodeLocation *loca, + GeocodeLocation *locb); + void geocode_location_set_description (GeocodeLocation *loc, const char *description); void geocode_location_set_speed (GeocodeLocation *loc, gdouble speed); +void geocode_location_set_heading (GeocodeLocation *loc, + guint heading); + const char *geocode_location_get_description (GeocodeLocation *loc); gdouble geocode_location_get_latitude (GeocodeLocation *loc); @@ -166,6 +235,7 @@ gdouble geocode_location_get_altitude (GeocodeLocation *loc); GeocodeLocationCRS geocode_location_get_crs (GeocodeLocation *loc); gdouble geocode_location_get_accuracy (GeocodeLocation *loc); gdouble geocode_location_get_speed (GeocodeLocation *loc); +guint geocode_location_get_heading (GeocodeLocation *loc); guint64 geocode_location_get_timestamp (GeocodeLocation *loc); G_END_DECLS diff --git a/src/org.freedesktop.GeoClue2.xml b/src/org.freedesktop.GeoClue2.xml index acd5f7e..a18703a 100644 --- a/src/org.freedesktop.GeoClue2.xml +++ b/src/org.freedesktop.GeoClue2.xml @@ -192,6 +192,13 @@ + + +