From 7da94c140fa9e15a357f68462eb00a8fac9fe1cd Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Mon, 9 Nov 2015 13:38:42 +0300 Subject: [PATCH 1/6] Routing rebuilding fix. --- routing/routing_session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index 343462876b..a6cd019cab 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -195,7 +195,7 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const { // Distance from the last known projection on route // (check if we are moving far from the last known projection). - double const dist = m_route.GetCurrentSqDistance(position); + double const dist = MercatorBounds::DistanceOnEarth(m_route.GetFollowedPolyline().GetCurrentIter().m_pt, position); if (my::AlmostEqualAbs(dist, m_lastDistance, kRunawayDistanceSensitivityMeters)) return m_state; if (dist > m_lastDistance) From afa1d62d211edc5e1e87ebee6f06a6c60da8d776 Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Tue, 10 Nov 2015 11:11:30 +0300 Subject: [PATCH 2/6] Routing session tests. --- .../routing_tests/routing_session_test.cpp | 127 ++++++++++++++++++ routing/routing_tests/routing_tests.pro | 1 + 2 files changed, 128 insertions(+) create mode 100644 routing/routing_tests/routing_session_test.cpp diff --git a/routing/routing_tests/routing_session_test.cpp b/routing/routing_tests/routing_session_test.cpp new file mode 100644 index 0000000000..cd7c15a4e1 --- /dev/null +++ b/routing/routing_tests/routing_session_test.cpp @@ -0,0 +1,127 @@ +#include "testing/testing.hpp" + +#include "routing/route.hpp" +#include "routing/router.hpp" +#include "routing/routing_session.hpp" + +#include "geometry/point2d.hpp" + +#include "base/logging.hpp" + +#include "std/string.hpp" +#include "std/vector.hpp" + +namespace routing { +// Simple router. It returns route given to him on creation. +class DummyRouter : public IRouter +{ +private: + Route & m_route; + ResultCode m_code; + size_t & m_buildCount; + +public: + DummyRouter(Route & route, ResultCode code, size_t & buildCounter) + : m_route(route), m_code(code), m_buildCount(buildCounter) + { + } + string GetName() const override { return "dummy"; } + void ClearState() override {} + ResultCode CalculateRoute(m2::PointD const & /* startPoint */, + m2::PointD const & /* startDirection */, + m2::PointD const & /* finalPoint */, + RouterDelegate const & /* delegate */, Route & route) override + { + ++m_buildCount; + route = m_route; + return m_code; + } +}; + +static vector kTestRoute = {{0., 1.}, {0., 2.}, {0., 3.}, {0., 4.}}; + +UNIT_TEST(TestRouteBuilding) +{ + RoutingSession session; + session.Init(nullptr, nullptr); + vector routePoints = kTestRoute; + Route masterRoute("dummy", routePoints.begin(), routePoints.end()); + size_t counter = 0; + atomic routeBuilded(false); + unique_ptr router = make_unique(masterRoute, DummyRouter::NoError, counter); + session.SetRouter(move(router), nullptr); + session.BuildRoute(kTestRoute.front(), kTestRoute.back(), + [&routeBuilded](Route const &, IRouter::ResultCode) + { + routeBuilded = true; + }, + nullptr, 0); + while (!routeBuilded) + { + } + TEST_EQUAL(counter, 1, ()); +} + +UNIT_TEST(TestRouteRebuilding) +{ + Index index; + RoutingSession session; + session.Init(nullptr, nullptr); + vector routePoints = kTestRoute; + Route masterRoute("dummy", routePoints.begin(), routePoints.end()); + size_t counter = 0; + atomic routeBuilded(false); + unique_ptr router = make_unique(masterRoute, DummyRouter::NoError, counter); + session.SetRouter(move(router), nullptr); + + // Go along the route. + session.BuildRoute(kTestRoute.front(), kTestRoute.back(), + [&routeBuilded](Route const &, IRouter::ResultCode) + { + routeBuilded = true; + }, + nullptr, 0); + while (!routeBuilded) + { + } + + location::GpsInfo info; + info.m_horizontalAccuracy = 0.01; + info.m_verticalAccuracy = 0.01; + info.m_longitude = 0.; + info.m_latitude = 1.; + RoutingSession::State code = session.OnLocationPositionChanged( + MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), info, index); + while (info.m_latitude < kTestRoute.back().y) + { + code = session.OnLocationPositionChanged( + MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), info, index); + TEST_EQUAL(code, RoutingSession::State::OnRoute, ()); + info.m_latitude += 0.01; + } + TEST_EQUAL(counter, 1, ()); + + // Rebuild route and go in opposite direction. So initiate a route rebuilding flag. + counter = 0; + routeBuilded = false; + session.BuildRoute(kTestRoute.front(), kTestRoute.back(), + [&routeBuilded](Route const &, IRouter::ResultCode) + { + routeBuilded = true; + }, + nullptr, 0); + info.m_longitude = 0.; + info.m_latitude = 1.; + while (!routeBuilded) + { + } + + for (size_t i = 0; i < 10; ++i) + { + code = session.OnLocationPositionChanged( + MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), info, index); + info.m_latitude -= 0.1; + } + TEST_EQUAL(code, RoutingSession::State::RouteNeedRebuild, ()); +} +} // namespace routing diff --git a/routing/routing_tests/routing_tests.pro b/routing/routing_tests/routing_tests.pro index 6c46d3ae7b..f9cad6e63f 100644 --- a/routing/routing_tests/routing_tests.pro +++ b/routing/routing_tests/routing_tests.pro @@ -34,6 +34,7 @@ SOURCES += \ road_graph_nearest_edges_test.cpp \ route_tests.cpp \ routing_mapping_test.cpp \ + routing_session_test.cpp \ turns_generator_test.cpp \ turns_sound_test.cpp \ turns_tts_text_tests.cpp \ From 0c1817814860305f87edcd4d9701b65564c11849 Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Tue, 10 Nov 2015 11:16:27 +0300 Subject: [PATCH 3/6] Remove redundant route method. --- routing/route.cpp | 6 ------ routing/route.hpp | 2 -- 2 files changed, 8 deletions(-) diff --git a/routing/route.cpp b/routing/route.cpp index 602ff31dac..d144c70901 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -228,12 +228,6 @@ bool Route::MoveIterator(location::GpsInfo const & info) const return res.IsValid(); } -double Route::GetCurrentSqDistance(m2::PointD const & pt) const -{ - ASSERT(m_poly.IsValid(), ()); - return pt.SquareLength(m_poly.GetCurrentIter().m_pt); -} - double Route::GetPolySegAngle(size_t ind) const { size_t const polySz = m_poly.GetPolyline().GetSize(); diff --git a/routing/route.hpp b/routing/route.hpp index 86f199aedd..45bbe66caa 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -94,8 +94,6 @@ public: /// @return true If position was updated successfully (projection within gps error radius). bool MoveIterator(location::GpsInfo const & info) const; - /// Square distance to current projection in mercator. - double GetCurrentSqDistance(m2::PointD const & pt) const; void MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const; bool IsCurrentOnEnd() const; From 4ef24c1559d71c0f0339d38fac145e52510cc8f9 Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Tue, 10 Nov 2015 12:03:03 +0300 Subject: [PATCH 4/6] Using GPS corrdinates to calulate moving from projection distance. --- routing/routing_session.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index a6cd019cab..9f023a5422 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -195,7 +195,8 @@ RoutingSession::State RoutingSession::OnLocationPositionChanged(m2::PointD const { // Distance from the last known projection on route // (check if we are moving far from the last known projection). - double const dist = MercatorBounds::DistanceOnEarth(m_route.GetFollowedPolyline().GetCurrentIter().m_pt, position); + double const dist = MercatorBounds::DistanceOnEarth(m_route.GetFollowedPolyline().GetCurrentIter().m_pt, + MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude)); if (my::AlmostEqualAbs(dist, m_lastDistance, kRunawayDistanceSensitivityMeters)) return m_state; if (dist > m_lastDistance) From 6a1b36eb79bad5088c3e492ee38857d769d9a29e Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Tue, 10 Nov 2015 13:06:38 +0300 Subject: [PATCH 5/6] PR fixes. --- .../routing_tests/routing_session_test.cpp | 50 ++++++++----------- std/mutex.hpp | 1 + 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/routing/routing_tests/routing_session_test.cpp b/routing/routing_tests/routing_session_test.cpp index cd7c15a4e1..62ae8c2d0e 100644 --- a/routing/routing_tests/routing_session_test.cpp +++ b/routing/routing_tests/routing_session_test.cpp @@ -8,10 +8,13 @@ #include "base/logging.hpp" +#include "std/chrono.hpp" +#include "std/mutex.hpp" #include "std/string.hpp" #include "std/vector.hpp" -namespace routing { +namespace routing +{ // Simple router. It returns route given to him on creation. class DummyRouter : public IRouter { @@ -39,6 +42,7 @@ public: }; static vector kTestRoute = {{0., 1.}, {0., 2.}, {0., 3.}, {0., 4.}}; +static auto kRouteBuildingMaxDuration = seconds(30); UNIT_TEST(TestRouteBuilding) { @@ -47,18 +51,17 @@ UNIT_TEST(TestRouteBuilding) vector routePoints = kTestRoute; Route masterRoute("dummy", routePoints.begin(), routePoints.end()); size_t counter = 0; - atomic routeBuilded(false); + timed_mutex routeBuilded; + routeBuilded.lock(); unique_ptr router = make_unique(masterRoute, DummyRouter::NoError, counter); session.SetRouter(move(router), nullptr); session.BuildRoute(kTestRoute.front(), kTestRoute.back(), [&routeBuilded](Route const &, IRouter::ResultCode) { - routeBuilded = true; + routeBuilded.unlock(); }, nullptr, 0); - while (!routeBuilded) - { - } + TEST(routeBuilded.try_lock_for(kRouteBuildingMaxDuration), ()); TEST_EQUAL(counter, 1, ()); } @@ -70,28 +73,25 @@ UNIT_TEST(TestRouteRebuilding) vector routePoints = kTestRoute; Route masterRoute("dummy", routePoints.begin(), routePoints.end()); size_t counter = 0; - atomic routeBuilded(false); + timed_mutex routeBuilded; + auto fn = [&routeBuilded](Route const &, IRouter::ResultCode) + { + routeBuilded.unlock(); + }; + routeBuilded.lock(); unique_ptr router = make_unique(masterRoute, DummyRouter::NoError, counter); session.SetRouter(move(router), nullptr); // Go along the route. - session.BuildRoute(kTestRoute.front(), kTestRoute.back(), - [&routeBuilded](Route const &, IRouter::ResultCode) - { - routeBuilded = true; - }, - nullptr, 0); - while (!routeBuilded) - { - } + session.BuildRoute(kTestRoute.front(), kTestRoute.back(), fn, nullptr, 0); + TEST(routeBuilded.try_lock_for(kRouteBuildingMaxDuration), ()); location::GpsInfo info; info.m_horizontalAccuracy = 0.01; info.m_verticalAccuracy = 0.01; info.m_longitude = 0.; info.m_latitude = 1.; - RoutingSession::State code = session.OnLocationPositionChanged( - MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), info, index); + RoutingSession::State code; while (info.m_latitude < kTestRoute.back().y) { code = session.OnLocationPositionChanged( @@ -103,19 +103,11 @@ UNIT_TEST(TestRouteRebuilding) // Rebuild route and go in opposite direction. So initiate a route rebuilding flag. counter = 0; - routeBuilded = false; - session.BuildRoute(kTestRoute.front(), kTestRoute.back(), - [&routeBuilded](Route const &, IRouter::ResultCode) - { - routeBuilded = true; - }, - nullptr, 0); + session.BuildRoute(kTestRoute.front(), kTestRoute.back(), fn, nullptr, 0); + TEST(routeBuilded.try_lock_for(kRouteBuildingMaxDuration), ()); + info.m_longitude = 0.; info.m_latitude = 1.; - while (!routeBuilded) - { - } - for (size_t i = 0; i < 10; ++i) { code = session.OnLocationPositionChanged( diff --git a/std/mutex.hpp b/std/mutex.hpp index 47a7461fa7..ad184fe6cd 100644 --- a/std/mutex.hpp +++ b/std/mutex.hpp @@ -8,6 +8,7 @@ using std::lock_guard; using std::mutex; +using std::timed_mutex; using std::unique_lock; #ifdef DEBUG_NEW From 3d85ce745ae9aa8ceed5b28b3f47955d295a4956 Mon Sep 17 00:00:00 2001 From: Lev Dragunov Date: Tue, 10 Nov 2015 13:33:16 +0300 Subject: [PATCH 6/6] Rebuild route to current coordinate. --- map/framework.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/map/framework.cpp b/map/framework.cpp index 530cbcc67f..0cf375ef6c 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2303,7 +2303,8 @@ void Framework::CheckLocationForRouting(GpsInfo const & info) GetPlatform().RunOnGuiThread(bind(&Framework::InsertRoute, this, route)); }; - m_routingSession.RebuildRoute(position, readyCallback, m_progressCallback, 0 /* timeoutSec */); + m_routingSession.RebuildRoute(MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), + readyCallback, m_progressCallback, 0 /* timeoutSec */); } }