From cef145f355f2c83f38bd274236cad7e51edfca71 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Tue, 5 Jun 2018 15:36:01 +0300 Subject: [PATCH] Calling ExtrapolatedLocationUpdate() on background thread immediately after OnLocationUpdate() was called. extrapolation_benchmark result: LOG TID(1) INFO 3.5842e-05 extrapolation_benchmark/extrapolation_benchmark.cpp:227 main() General tracks statistics. Number of tracks: 886 Number of track points: 567362 Average points per track: 640 Average track length: 15325.8 meters LOG TID(1) INFO 91.914 extrapolation_benchmark/extrapolation_benchmark.cpp:318 main() Processed 153443 points. 767215 extrapolations is calculated. Projection is calculated for 767215 extrapolations. LOG TID(1) INFO 91.914 extrapolation_benchmark/extrapolation_benchmark.cpp:320 main() Expected value for each extrapolation: LOG TID(1) INFO 91.914 extrapolation_benchmark/extrapolation_benchmark.cpp:326 main() Extrapolation 1 , 200 seconds after point two. Expected value = 0.705745 meters. Variance = 1.29414 . Standard deviation = 1.1376 LOG TID(1) INFO 91.9141 extrapolation_benchmark/extrapolation_benchmark.cpp:326 main() Extrapolation 2 , 400 seconds after point two. Expected value = 1.39173 meters. Variance = 4.76746 . Standard deviation = 2.18345 LOG TID(1) INFO 91.9141 extrapolation_benchmark/extrapolation_benchmark.cpp:326 main() Extrapolation 3 , 600 seconds after point two. Expected value = 2.04523 meters. Variance = 9.80405 . Standard deviation = 3.13114 LOG TID(1) INFO 91.9141 extrapolation_benchmark/extrapolation_benchmark.cpp:326 main() Extrapolation 4 , 800 seconds after point two. Expected value = 2.63355 meters. Variance = 15.9907 . Standard deviation = 3.99883 LOG TID(1) INFO 91.9141 extrapolation_benchmark/extrapolation_benchmark.cpp:326 main() Extrapolation 5 , 1000 seconds after point two. Expected value = 3.13071 meters. Variance = 22.8244 . Standard deviation = 4.77749 --- map/extrapolation/extrapolator.cpp | 53 +++++++++++++------ map/extrapolation/extrapolator.hpp | 9 +++- .../extrapolation_benchmark.cpp | 8 ++- 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/map/extrapolation/extrapolator.cpp b/map/extrapolation/extrapolator.cpp index cd4e7178f2..b70f412cbb 100644 --- a/map/extrapolation/extrapolator.cpp +++ b/map/extrapolation/extrapolator.cpp @@ -100,20 +100,20 @@ bool AreCoordsGoodForExtrapolation(location::GpsInfo const & beforeLastGpsInfo, Extrapolator::Extrapolator(ExtrapolatedLocationUpdateFn const & update) : m_isEnabled(false), m_extrapolatedLocationUpdate(update) { - GetPlatform().RunTask(Platform::Thread::Background, [this] - { - ExtrapolatedLocationUpdate(); - }); + RunTaskOnBackgroundThread(false /* delayed */); } void Extrapolator::OnLocationUpdate(location::GpsInfo const & gpsInfo) { - // @TODO Consider calling ExtrapolatedLocationUpdate() on background thread immediately - // after OnLocationUpdate() was called. - lock_guard guard(m_mutex); - m_beforeLastGpsInfo = m_lastGpsInfo; - m_lastGpsInfo = gpsInfo; - m_extrapolationCounter = 0; + { + lock_guard guard(m_mutex); + m_beforeLastGpsInfo = m_lastGpsInfo; + m_lastGpsInfo = gpsInfo; + m_extrapolationCounter = 0; + // Canceling all background tasks which are put to the queue before the task run in this method. + m_extrapolatedUpdateMinValid = m_extrapolatedUpdateCounter + 1; + } + RunTaskOnBackgroundThread(false /* delayed */); } void Extrapolator::Enable(bool enabled) @@ -122,11 +122,15 @@ void Extrapolator::Enable(bool enabled) m_isEnabled = enabled; } -void Extrapolator::ExtrapolatedLocationUpdate() +void Extrapolator::ExtrapolatedLocationUpdate(uint64_t extrapolatedUpdateCounter) { location::GpsInfo gpsInfo; { lock_guard guard(m_mutex); + // Canceling all calls of the method which were activated before |m_extrapolatedUpdateMinValid|. + if (extrapolatedUpdateCounter < m_extrapolatedUpdateMinValid) + return; + uint64_t const extrapolationTimeMs = kExtrapolationPeriodMs * m_extrapolationCounter; if (extrapolationTimeMs < kMaxExtrapolationTimeMs && m_lastGpsInfo.IsValid()) { @@ -154,11 +158,30 @@ void Extrapolator::ExtrapolatedLocationUpdate() ++m_extrapolationCounter; } - // Call ExtrapolatedLocationUpdate() every |kExtrapolationPeriodMs| milliseconds. - auto constexpr kSExtrapolationPeriod = std::chrono::milliseconds(kExtrapolationPeriodMs); - GetPlatform().RunDelayedTask(Platform::Thread::Background, kSExtrapolationPeriod, [this] + // Calling ExtrapolatedLocationUpdate() in |kExtrapolationPeriodMs| milliseconds. + RunTaskOnBackgroundThread(true /* delayed */); +} + +void Extrapolator::RunTaskOnBackgroundThread(bool delayed) +{ { - ExtrapolatedLocationUpdate(); + lock_guard guard(m_mutex); + ++m_extrapolatedUpdateCounter; + } + + auto const extrapolatedUpdateCounter = m_extrapolatedUpdateCounter; + if (delayed) + { + auto constexpr kSExtrapolationPeriod = std::chrono::milliseconds(kExtrapolationPeriodMs); + GetPlatform().RunDelayedTask(Platform::Thread::Background, kSExtrapolationPeriod, + [this, extrapolatedUpdateCounter] { + ExtrapolatedLocationUpdate(extrapolatedUpdateCounter); + }); + return; + } + + GetPlatform().RunTask(Platform::Thread::Background, [this, extrapolatedUpdateCounter] { + ExtrapolatedLocationUpdate(extrapolatedUpdateCounter); }); } diff --git a/map/extrapolation/extrapolator.hpp b/map/extrapolation/extrapolator.hpp index d0a71d6ff0..70cd6556af 100644 --- a/map/extrapolation/extrapolator.hpp +++ b/map/extrapolation/extrapolator.hpp @@ -48,7 +48,8 @@ private: /// \returns true if there's enough information for extrapolation and extrapolation is enabled. /// \note This method should be called only when |m_mutex| is locked. bool DoesExtrapolationWork() const; - void ExtrapolatedLocationUpdate(); + void ExtrapolatedLocationUpdate(uint64_t extrapolatedUpdateCounter); + void RunTaskOnBackgroundThread(bool delayed); bool m_isEnabled; @@ -57,5 +58,11 @@ private: location::GpsInfo m_lastGpsInfo; location::GpsInfo m_beforeLastGpsInfo; uint64_t m_extrapolationCounter = kExtrapolationCounterUndefined; + // Number of calls Extrapolator::RunTaskOnBackgroundThread() method. + uint64_t m_extrapolatedUpdateCounter = 0; + // If |m_extrapolatedUpdateCounter| < |m_extrapolatedUpdateMinValid| when + // ExtrapolatedLocationUpdate() is called (on background thread) + // ExtrapolatedLocationUpdate() cancels its execution. + uint64_t m_extrapolatedUpdateMinValid = 0; }; } // namespace extrapolation diff --git a/map/extrapolation_benchmark/extrapolation_benchmark.cpp b/map/extrapolation_benchmark/extrapolation_benchmark.cpp index d9fd187e56..0c83aaebb4 100644 --- a/map/extrapolation_benchmark/extrapolation_benchmark.cpp +++ b/map/extrapolation_benchmark/extrapolation_benchmark.cpp @@ -173,6 +173,7 @@ bool Parse(string const & pathToCsv, Tracks & tracks) void GpsPointToGpsInfo(GpsPoint const gpsPoint, GpsInfo & gpsInfo) { + gpsInfo = {}; gpsInfo.m_source = TLocationSource::EAppleNative; gpsInfo.m_timestamp = gpsPoint.m_timestampS; gpsInfo.m_latitude = gpsPoint.m_lat; @@ -268,14 +269,17 @@ int main(int argc, char * argv[]) GpsInfo const extrapolated = LinearExtrapolation(info1, info2, timeMs); m2::PointD const extrapolatedMerc = MercatorBounds::FromLatLon(extrapolated.m_latitude, extrapolated.m_longitude); - m2::RectD const posRect = MercatorBounds::MetresToXY( + // To generate |posSquare| the method below requires the size of half square in meters. + // This constant is chosen based on maximum value of GpsInfo::m_horizontalAccuracy + // which is used calculation of projection in production code. + m2::RectD const posSquare = MercatorBounds::MetresToXY( extrapolated.m_longitude, extrapolated.m_latitude, 100.0 /* half square in meters */); // Note 1. One is deducted from polyline size because in GetClosestProjectionInInterval() // is used segment indices but not point indices. // Note 2. Calculating projection of the center of |posRect| to polyline segments which // are inside of |posRect|. auto const & iter = followedPoly.GetClosestProjectionInInterval( - posRect, + posSquare, [&extrapolatedMerc](FollowedPolyline::Iter const & it) { return MercatorBounds::DistanceOnEarth(it.m_pt, extrapolatedMerc); },