From: Marcin Masternak Date: Wed, 1 Jun 2016 18:14:15 +0000 (+0200) Subject: [my-place] Locations accuracy in visit and places fix. X-Git-Tag: submit/tizen/20160622.045445~1^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ac4dd936b26d64c47f4750d628d697e48130f453;p=platform%2Fcore%2Fcontext%2Fcontext-provider.git [my-place] Locations accuracy in visit and places fix. Change-Id: I5dbfb12cada1fdc93454fbeaee2014c8430cd70f Signed-off-by: Marcin Masternak --- diff --git a/src/my-place/place_recognition_types.h b/src/my-place/place_recognition_types.h index 0ecc8f1..b19777a 100644 --- a/src/my-place/place_recognition_types.h +++ b/src/my-place/place_recognition_types.h @@ -32,9 +32,10 @@ #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" @@ -45,12 +46,13 @@ #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" diff --git a/src/my-place/user_places/median.cpp b/src/my-place/user_places/median.cpp index 37c0793..8573761 100644 --- a/src/my-place/user_places/median.cpp +++ b/src/my-place/user_places/median.cpp @@ -18,19 +18,53 @@ #include #include "median.h" -ctx::num_t ctx::median(std::vector &v) +static bool compareFun(std::pair &i, std::pair &j) { + return (i.first < j.first); +} + +double ctx::median(std::vector &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> valuesTemp; + for (size_t i = 0; i < values.size(); i++) { + valuesTemp.push_back(std::pair(values[i], i)); + } + int n = valuesTemp.size() / 2; + std::nth_element(valuesTemp.begin(), valuesTemp.begin() + n, valuesTemp.end(), compareFun); + std::pair 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 &latitudes, std::vector &longitudes, std::vector &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; } diff --git a/src/my-place/user_places/median.h b/src/my-place/user_places/median.h index 84eaa34..90b6bdf 100644 --- a/src/my-place/user_places/median.h +++ b/src/my-place/user_places/median.h @@ -23,7 +23,8 @@ namespace ctx { - num_t median(std::vector &values); // caution: the input vector will be sorted + double median(std::vector &values, int &elemIdx, int &evenCaseElemIdx); + ctx::Location medianLocation(std::vector &latitudes, std::vector &longitudes, std::vector &accuracy); } /* namespace ctx */ diff --git a/src/my-place/user_places/place_categer.cpp b/src/my-place/user_places/place_categer.cpp index 3532ab6..05ebcfc 100644 --- a/src/my-place/user_places/place_categer.cpp +++ b/src/my-place/user_places/place_categer.cpp @@ -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 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; diff --git a/src/my-place/user_places/places_detector.cpp b/src/my-place/user_places/places_detector.cpp index d05647a..cb83db9 100644 --- a/src/my-place/user_places/places_detector.cpp +++ b/src/my-place/user_places/places_detector.cpp @@ -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 latitudes; std::vector longitudes; + std::vector 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 ap : place.wifiAps) { wifiAps.append(ap.first); diff --git a/src/my-place/user_places/visit_detector.cpp b/src/my-place/user_places/visit_detector.cpp index 9fc9264..662c700 100644 --- a/src/my-place/user_places/visit_detector.cpp +++ b/src/my-place/user_places/visit_detector.cpp @@ -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 latitudes; std::vector longitudes; + std::vector 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(visit.interval.start)); data.set(NULL, VISIT_COLUMN_END_TIME, static_cast(visit.interval.end));