diff --git a/map/framework.cpp b/map/framework.cpp index 253f22d53b..c28edbd6ab 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2325,7 +2325,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 */); } } 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; diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index 8dadcc1a20..85ea2d175e 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -200,7 +200,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 = m_route.GetCurrentSqDistance(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) diff --git a/routing/routing_tests/routing_session_test.cpp b/routing/routing_tests/routing_session_test.cpp new file mode 100644 index 0000000000..62ae8c2d0e --- /dev/null +++ b/routing/routing_tests/routing_session_test.cpp @@ -0,0 +1,119 @@ +#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/chrono.hpp" +#include "std/mutex.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.}}; +static auto kRouteBuildingMaxDuration = seconds(30); + +UNIT_TEST(TestRouteBuilding) +{ + RoutingSession session; + session.Init(nullptr, nullptr); + vector routePoints = kTestRoute; + Route masterRoute("dummy", routePoints.begin(), routePoints.end()); + size_t counter = 0; + 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.unlock(); + }, + nullptr, 0); + TEST(routeBuilded.try_lock_for(kRouteBuildingMaxDuration), ()); + 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; + 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(), 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; + 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; + session.BuildRoute(kTestRoute.front(), kTestRoute.back(), fn, nullptr, 0); + TEST(routeBuilded.try_lock_for(kRouteBuildingMaxDuration), ()); + + info.m_longitude = 0.; + info.m_latitude = 1.; + 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 \ 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