[my-place] Locations accuracy in visit and places fix. 02/72602/1
authorMarcin Masternak <m.masternak@samsung.com>
Wed, 1 Jun 2016 18:14:15 +0000 (20:14 +0200)
committerMarcin Masternak <m.masternak@samsung.com>
Wed, 1 Jun 2016 18:16:58 +0000 (20:16 +0200)
Change-Id: I5dbfb12cada1fdc93454fbeaee2014c8430cd70f
Signed-off-by: Marcin Masternak <m.masternak@samsung.com>
src/my-place/place_recognition_types.h
src/my-place/user_places/median.cpp
src/my-place/user_places/median.h
src/my-place/user_places/place_categer.cpp
src/my-place/user_places/places_detector.cpp
src/my-place/user_places/visit_detector.cpp

index 0ecc8f1..b19777a 100644 (file)
 #define VISIT_COLUMN_START_TIME_HUMAN          "start_time_human" // only for debug: human readable time data:
 #define VISIT_COLUMN_END_TIME_HUMAN            "end_time_human" // only for debug: human readable time data:
 #endif /* TIZEN_ENGINEER_MODE */
-#define VISIT_COLUMN_LOCATION_VALID            "geo_valid"
-#define VISIT_COLUMN_LOCATION_LATITUDE         "geo_latitude"
-#define VISIT_COLUMN_LOCATION_LONGITUDE        "geo_longitude"
+#define VISIT_COLUMN_LOCATION_VALID            "location_valid"
+#define VISIT_COLUMN_LOCATION_LATITUDE         "location_latitude"
+#define VISIT_COLUMN_LOCATION_LONGITUDE        "location_longitude"
+#define VISIT_COLUMN_LOCATION_ACCURACY         "location_accuracy"
 #define VISIT_COLUMN_CATEG_HOME                "categ_home"
 #define VISIT_COLUMN_CATEG_WORK                "categ_work"
 #define VISIT_COLUMN_CATEG_OTHER               "categ_other"
 #define WIFI_APS_MAP_COLUMN_INSERT_TIME        "insert_time"
 
 #define PLACE_TABLE                            "place_status_user_place"
-#define PLACE_COLUMN_CATEG_ID                  "type_id" // Name inconsistency: "cated_id" vs "type_id" TODO make it consistent
-#define PLACE_COLUMN_CATEG_CONFIDENCE          "type_confidence"
+#define PLACE_COLUMN_CATEG_ID                  "categ_id"
+#define PLACE_COLUMN_CATEG_CONFIDENCE          "categ_confidence"
 #define PLACE_COLUMN_NAME                      "name"
-#define PLACE_COLUMN_LOCATION_VALID            "geo_valid"
-#define PLACE_COLUMN_LOCATION_LATITUDE         "geo_latitude"
-#define PLACE_COLUMN_LOCATION_LONGITUDE        "geo_longitude"
+#define PLACE_COLUMN_LOCATION_VALID            "location_valid"
+#define PLACE_COLUMN_LOCATION_LATITUDE         "location_latitude"
+#define PLACE_COLUMN_LOCATION_LONGITUDE        "location_longitude"
+#define PLACE_COLUMN_LOCATION_ACCURACY         "location_accuracy"
 #define PLACE_COLUMN_WIFI_APS                  "wifi_aps"
 #define PLACE_COLUMN_CREATE_DATE               "create_date"
 
index 37c0793..8573761 100644 (file)
 #include <Types.h>
 #include "median.h"
 
-ctx::num_t ctx::median(std::vector<ctx::num_t> &v)
+static bool compareFun(std::pair<double, int> &i, std::pair<double, int> &j) {
+       return (i.first < j.first);
+}
+
+double ctx::median(std::vector<double> &values, int &elemIdx, int &evenCaseElemIdx)
 {
-       if (v.empty()) {
+       if (values.empty()) {
                _E("Median of empty set");
-               return 0; // this value does not make any sense
+               return -1;
+       }
+       std::vector<std::pair<double, int>> valuesTemp;
+       for (size_t i = 0; i < values.size(); i++) {
+               valuesTemp.push_back(std::pair<double, int>(values[i], i));
+       }
+       int n = valuesTemp.size() / 2;
+       std::nth_element(valuesTemp.begin(), valuesTemp.begin() + n, valuesTemp.end(), compareFun);
+       std::pair<double, int> valuesTempN = valuesTemp[n];
+       elemIdx = valuesTempN.second;
+       if (valuesTemp.size() % 2 == 1) { //odd size
+               evenCaseElemIdx = -1;
+               return valuesTempN.first;
+       } else { // even size
+               std::nth_element(valuesTemp.begin(), valuesTemp.begin() + n - 1, valuesTemp.end());
+               evenCaseElemIdx = valuesTemp[n - 1].second;
+               return 0.5 * (valuesTempN.first + valuesTemp[n - 1].first);
+       }
+}
+
+ctx::Location ctx::medianLocation(std::vector<double> &latitudes, std::vector<double> &longitudes, std::vector<double> &accuracy)
+{
+       ctx::Location location;
+       if (latitudes.empty() || latitudes.size() != longitudes.size() || latitudes.size() != accuracy.size()) {
+               _E("Incorrect input vectors size");
+               return location;
+       }
+       int idx;
+       int additionalIdx;
+       location.latitude = median(latitudes, idx, additionalIdx);
+       double latitudeAccuracy = accuracy[idx];
+       if (additionalIdx >= 0) {
+               latitudeAccuracy = 0.5 * (latitudeAccuracy + accuracy[additionalIdx]);
        }
-       size_t n = v.size() / 2;
-       std::nth_element(v.begin(), v.begin() + n, v.end());
-       num_t vn = v[n];
-       if (v.size() % 2 == 1) {
-               return vn;
-       } else {
-               std::nth_element(v.begin(), v.begin() + n - 1, v.end());
-               return 0.5 * (vn + v[n - 1]);
+       location.longitude = median(longitudes, idx, additionalIdx);
+       double longitudeAccuracy = accuracy[idx];
+       if (additionalIdx >= 0) {
+               longitudeAccuracy = 0.5 * (longitudeAccuracy + accuracy[additionalIdx]);
        }
+       location.accuracy = 0.5 * (latitudeAccuracy + longitudeAccuracy);
+       return location;
 }
index 84eaa34..90b6bdf 100644 (file)
@@ -23,7 +23,8 @@
 
 namespace ctx {
 
-       num_t median(std::vector<num_t> &values); // caution: the input vector will be sorted
+       double median(std::vector<double> &values, int &elemIdx, int &evenCaseElemIdx);
+       ctx::Location medianLocation(std::vector<double> &latitudes, std::vector<double> &longitudes, std::vector<double> &accuracy);
 
 } /* namespace ctx */
 
index 3532ab6..05ebcfc 100644 (file)
@@ -65,7 +65,8 @@ void ctx::PlaceCateger::categorize(ctx::Visits &visits, ctx::Place &place)
                num_t maxScore = 0.0;
                for (PlaceCategId categId : categIds) {
                        std::vector<num_t> categVector = __categVectorFromVisits(visits, categId);
-                       num_t score = median(categVector);
+                       int i, j;
+                       num_t score = median(categVector, i, j);
                        sumScore += score;
                        if (score > maxScore) {
                                maxScore = score;
index d05647a..cb83db9 100644 (file)
@@ -43,7 +43,8 @@
        VISIT_COLUMN_WIFI_APS ", "\
        VISIT_COLUMN_LOCATION_VALID ", "\
        VISIT_COLUMN_LOCATION_LATITUDE ", "\
-       VISIT_COLUMN_LOCATION_LONGITUDE ", " \
+       VISIT_COLUMN_LOCATION_LONGITUDE ", "\
+       VISIT_COLUMN_LOCATION_ACCURACY ", "\
        VISIT_COLUMN_CATEG_HOME ", "\
        VISIT_COLUMN_CATEG_WORK ", "\
        VISIT_COLUMN_CATEG_OTHER \
@@ -55,7 +56,8 @@
        PLACE_COLUMN_NAME ", "\
        PLACE_COLUMN_LOCATION_VALID ", "\
        PLACE_COLUMN_LOCATION_LATITUDE ", "\
-       PLACE_COLUMN_LOCATION_LONGITUDE ", " \
+       PLACE_COLUMN_LOCATION_LONGITUDE ", "\
+       PLACE_COLUMN_LOCATION_ACCURACY ", "\
        PLACE_COLUMN_WIFI_APS ", "\
        PLACE_COLUMN_CREATE_DATE \
        " FROM " PLACE_TABLE
@@ -72,6 +74,7 @@
        PLACE_COLUMN_LOCATION_VALID " INTEGER, "\
        PLACE_COLUMN_LOCATION_LATITUDE " REAL, "\
        PLACE_COLUMN_LOCATION_LONGITUDE " REAL, "\
+       PLACE_COLUMN_LOCATION_ACCURACY " REAL, "\
        PLACE_COLUMN_WIFI_APS " STRING, "\
        PLACE_COLUMN_CREATE_DATE " timestamp"
 
@@ -205,6 +208,7 @@ void ctx::PlacesDetector::__placeLocationFromJson(Json &row, ctx::Place &place)
        place.locationValid = (bool) locationValidInt;
        row.get(NULL, PLACE_COLUMN_LOCATION_LATITUDE, &(place.location.latitude));
        row.get(NULL, PLACE_COLUMN_LOCATION_LONGITUDE, &(place.location.longitude));
+       row.get(NULL, PLACE_COLUMN_LOCATION_ACCURACY, &(place.location.accuracy));
 }
 
 void ctx::PlacesDetector::__placeWifiAPsFromJson(Json &row, ctx::Place &place)
@@ -324,19 +328,26 @@ void ctx::PlacesDetector::__detectedPlacesUpdate(std::vector<std::shared_ptr<Pla
 
 void ctx::PlacesDetector::__mergeLocation(const Visits &visits, Place &place)
 {
-       place.locationValid = false;
        std::vector<double> latitudes;
        std::vector<double> longitudes;
+       std::vector<double> accuracy;
+       place.locationValid = false;
        for (const Visit& visit : visits) {
                if (visit.locationValid) {
                        latitudes.push_back(visit.location.latitude);
                        longitudes.push_back(visit.location.longitude);
+                       accuracy.push_back(visit.location.accuracy);
                        place.locationValid = true;
                }
        }
        if (place.locationValid) {
-               place.location.latitude = median(latitudes);
-               place.location.longitude = median(longitudes);
+               place.location = medianLocation(latitudes, longitudes, accuracy);
+               _D("place location set: lat=%.8f, lon=%.8f, acc=%.8f",
+                               place.location.latitude,
+                               place.location.longitude,
+                               place.location.accuracy);
+       } else {
+               _D("place location not set");
        }
 }
 
@@ -464,6 +475,7 @@ void ctx::PlacesDetector::__dbInsertPlace(const Place &place)
        data.set(NULL, PLACE_COLUMN_LOCATION_VALID, place.locationValid);
        data.set(NULL, PLACE_COLUMN_LOCATION_LATITUDE, place.location.latitude);
        data.set(NULL, PLACE_COLUMN_LOCATION_LONGITUDE, place.location.longitude);
+       data.set(NULL, PLACE_COLUMN_LOCATION_ACCURACY, place.location.accuracy);
        std::string wifiAps;
        for (std::pair<std::string, std::string> ap : place.wifiAps) {
                wifiAps.append(ap.first);
index 9fc9264..662c700 100644 (file)
@@ -38,6 +38,7 @@
        VISIT_COLUMN_LOCATION_VALID " INTEGER, "\
        VISIT_COLUMN_LOCATION_LATITUDE " REAL, "\
        VISIT_COLUMN_LOCATION_LONGITUDE " REAL, "\
+       VISIT_COLUMN_LOCATION_ACCURACY " REAL, "\
        VISIT_COLUMN_CATEG_HOME " REAL, "\
        VISIT_COLUMN_CATEG_WORK " REAL, "\
        VISIT_COLUMN_CATEG_OTHER " REAL"
@@ -49,6 +50,7 @@
        VISIT_COLUMN_LOCATION_VALID " INTEGER, "\
        VISIT_COLUMN_LOCATION_LATITUDE " REAL, "\
        VISIT_COLUMN_LOCATION_LONGITUDE " REAL, "\
+       VISIT_COLUMN_LOCATION_ACCURACY " REAL, "\
        VISIT_COLUMN_CATEG_HOME " REAL, "\
        VISIT_COLUMN_CATEG_WORK " REAL, "\
        VISIT_COLUMN_CATEG_OTHER " REAL"
@@ -241,21 +243,25 @@ void ctx::VisitDetector::__visitEndDetected()
 
 void ctx::VisitDetector::__putLocationToVisit(ctx::Visit &visit)
 {
-       // TODO: remove small accuracy locations from vectors?
+       // TODO: filter out small accuracy locations?
        std::vector<double> latitudes;
        std::vector<double> longitudes;
+       std::vector<double> accuracy;
        visit.locationValid = false;
-       for (LocationEvent location : __locationEvents) {
+       for (LocationEvent &location : __locationEvents) {
                if (location.timestamp >= __entranceTime && location.timestamp <= __departureTime) {
                        latitudes.push_back(location.coordinates.latitude);
                        longitudes.push_back(location.coordinates.longitude);
+                       accuracy.push_back(location.coordinates.accuracy);
                        visit.locationValid = true;
                }
        }
        if (visit.locationValid) {
-               visit.location.latitude = median(latitudes);
-               visit.location.longitude = median(longitudes);
-               _D("visit location set: lat=%.8f, lon=%.8f", visit.location.latitude, visit.location.longitude);
+               visit.location = medianLocation(latitudes, longitudes, accuracy);
+               _D("visit location set: lat=%.8f, lon=%.8f, acc=%.8f",
+                               visit.location.latitude,
+                               visit.location.longitude,
+                               visit.location.accuracy);
        } else {
                _D("visit location not set");
        }
@@ -405,6 +411,7 @@ int ctx::VisitDetector::__dbInsertVisit(Visit visit)
        data.set(NULL, VISIT_COLUMN_LOCATION_VALID, visit.locationValid);
        data.set(NULL, VISIT_COLUMN_LOCATION_LATITUDE, visit.location.latitude);
        data.set(NULL, VISIT_COLUMN_LOCATION_LONGITUDE, visit.location.longitude);
+       data.set(NULL, VISIT_COLUMN_LOCATION_ACCURACY, visit.location.accuracy);
 
        data.set(NULL, VISIT_COLUMN_START_TIME, static_cast<int>(visit.interval.start));
        data.set(NULL, VISIT_COLUMN_END_TIME, static_cast<int>(visit.interval.end));