diff --git a/integration_tests/routing_test_tools.cpp b/integration_tests/routing_test_tools.cpp index 8f12b391b4..80435c1427 100644 --- a/integration_tests/routing_test_tools.cpp +++ b/integration_tests/routing_test_tools.cpp @@ -98,7 +98,7 @@ namespace integration shared_ptr CreatePedestrianRouter(Index & index) { - unique_ptr router = CreatePedestrianAStarBidirectionalRouter(index, nullptr, nullptr); + unique_ptr router = CreatePedestrianAStarBidirectionalRouter(index, nullptr); return shared_ptr(move(router)); } @@ -197,7 +197,7 @@ namespace integration ASSERT(router, ()); shared_ptr route(new Route("mapsme")); IRouter::ResultCode result = - router->CalculateRoute(startPoint, startDirection, finalPoint, *route.get()); + router->CalculateRoute(startPoint, startDirection, finalPoint, nullptr, *route.get()); ASSERT(route, ()); return TRouteResult(route, result); } diff --git a/map/framework.cpp b/map/framework.cpp index 8f4b336348..0ea8c83495 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2125,7 +2125,7 @@ void Framework::BuildRoute(m2::PointD const & destination, uint32_t timeoutSec) RemoveRoute(); } CallRouteBuilded(code, absentCountries, absentRoutingIndexes); - }, timeoutSec); + }, m_progressCallback, timeoutSec); } void Framework::SetRouter(RouterType type) @@ -2176,7 +2176,7 @@ void Framework::SetRouterImpl(RouterType type) if (type == RouterType::Pedestrian) { router = - CreatePedestrianAStarBidirectionalRouter(m_model.GetIndex(), nullptr, routingVisualizerFn); + CreatePedestrianAStarBidirectionalRouter(m_model.GetIndex(), routingVisualizerFn); m_routingSession.SetRoutingSettings(routing::GetPedestrianRoutingSettings()); } else @@ -2259,7 +2259,7 @@ void Framework::CheckLocationForRouting(GpsInfo const & info) { if (code == IRouter::NoError) InsertRoute(route); - }, 0 /* timeoutSec */); + }, m_progressCallback, 0 /* timeoutSec */); } } diff --git a/map/framework.hpp b/map/framework.hpp index 13e5898b25..f4d1d7127c 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -564,7 +564,12 @@ public: void BuildRoute(m2::PointD const & destination, uint32_t timeoutSec); typedef function const &, vector const &)> TRouteBuildingCallback; - void SetRouteBuildingListener(TRouteBuildingCallback const & callback) { m_routingCallback = callback; } + typedef function TRouteProgressCallback; + void SetRouteBuildingListener(TRouteBuildingCallback const & buildingCallback, TRouteProgressCallback const & progressCallback) + { + m_routingCallback = buildingCallback; + m_progressCallback = progressCallback; + } void FollowRoute() { GetLocationState()->StartRouteFollow(); } void CloseRouting(); void GetRouteFollowingInfo(location::FollowingInfo & info) { m_routingSession.GetRouteFollowingInfo(info); } @@ -597,6 +602,7 @@ private: string GetRoutingErrorMessage(routing::IRouter::ResultCode code); TRouteBuildingCallback m_routingCallback; + TRouteProgressCallback m_progressCallback; routing::RouterType m_currentRouterType; //@} diff --git a/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp b/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp index 1e1f4e0e7b..48fb50bb6e 100644 --- a/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp +++ b/pedestrian_routing_benchmarks/pedestrian_routing_benchmarks.cpp @@ -97,7 +97,7 @@ void TestRouter(routing::IRouter & router, m2::PointD const & startPos, m2::Poin routing::Route route(""); my::Timer timer; routing::IRouter::ResultCode const resultCode = router.CalculateRoute(startPos, m2::PointD::Zero() /* startDirection */, - finalPos, route); + finalPos, nullptr, route); double const elapsedSec = timer.ElapsedSeconds(); TEST_EQUAL(routing::IRouter::NoError, resultCode, ()); LOG(LINFO, ("Route polyline size:", route.GetPoly().GetSize())); diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index bb85dd4af8..c121b24540 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -104,7 +104,7 @@ namespace qt m_framework->SetRouteBuildingListener([] (routing::IRouter::ResultCode, vector const &, vector const &) { - }); + }, nullptr); } DrawWidget::~DrawWidget() diff --git a/routing/async_router.cpp b/routing/async_router.cpp index 08728dc715..22f4b2a17d 100644 --- a/routing/async_router.cpp +++ b/routing/async_router.cpp @@ -66,7 +66,8 @@ AsyncRouter::AsyncRouter(unique_ptr && router, unique_ptr paramsGuard(m_paramsMutex); @@ -78,7 +79,7 @@ void AsyncRouter::CalculateRoute(m2::PointD const & startPoint, m2::PointD const m_router->Cancel(); } - GetPlatform().RunAsync(bind(&AsyncRouter::CalculateRouteImpl, this, callback)); + GetPlatform().RunAsync(bind(&AsyncRouter::CalculateRouteImpl, this, readyCallback, progressCallback)); } void AsyncRouter::ClearState() @@ -132,7 +133,7 @@ void AsyncRouter::LogCode(IRouter::ResultCode code, double const elapsedSec) } // TODO (ldragunov) write some tests to check this callback logic. -void AsyncRouter::CalculateRouteImpl(TReadyCallback const & callback) +void AsyncRouter::CalculateRouteImpl(TReadyCallback const & readyCallback, TProgressCallback const & progressCallback) { ASSERT(m_router, ()); if (m_isReadyThread.test_and_set()) @@ -167,7 +168,7 @@ void AsyncRouter::CalculateRouteImpl(TReadyCallback const & callback) m_absentFetcher->GenerateRequest(startPoint, finalPoint); // Run basic request. - code = m_router->CalculateRoute(startPoint, startDirection, finalPoint, route); + code = m_router->CalculateRoute(startPoint, startDirection, finalPoint, progressCallback, route); elapsedSec = timer.ElapsedSeconds(); // routing time LogCode(code, elapsedSec); @@ -183,7 +184,7 @@ void AsyncRouter::CalculateRouteImpl(TReadyCallback const & callback) //Draw route without waiting network latency. if (code == IRouter::NoError) - GetPlatform().RunOnGuiThread(bind(callback, route, code)); + GetPlatform().RunOnGuiThread(bind(readyCallback, route, code)); bool const needFetchAbsent = (code != IRouter::Cancelled); @@ -198,20 +199,25 @@ void AsyncRouter::CalculateRouteImpl(TReadyCallback const & callback) if (!absent.empty()) { - elapsedSec = timer.ElapsedSeconds(); // routing time + absents fetch time - - if (code == IRouter::NoError) - { - // Route has been found, but could be found a better route if were download absent files - code = IRouter::NeedMoreMaps; - } + if (code != IRouter::NoError) + GetPlatform().RunOnGuiThread(bind(readyCallback, route, code)); + return; } LogCode(code, elapsedSec); SendStatistics(startPoint, startDirection, finalPoint, code, route, elapsedSec); // Call callback only if we have some new data. if (code != IRouter::NoError) - GetPlatform().RunOnGuiThread(bind(callback, route, code)); + { + GetPlatform().RunOnGuiThread(bind(readyCallback, route, code)); + } + else + { + double const elapsedSec = timer.ElapsedSeconds(); + LogCode(IRouter::NeedMoreMaps, elapsedSec); + SendStatistics(startPoint, startDirection, finalPoint, IRouter::NeedMoreMaps, route, elapsedSec); + GetPlatform().RunOnGuiThread(bind(readyCallback, route, IRouter::NeedMoreMaps)); + } } void AsyncRouter::SendStatistics(m2::PointD const & startPoint, m2::PointD const & startDirection, diff --git a/routing/async_router.hpp b/routing/async_router.hpp index dda471887f..7a813749c2 100644 --- a/routing/async_router.hpp +++ b/routing/async_router.hpp @@ -19,6 +19,9 @@ public: /// Callback takes ownership of passed route. typedef function TReadyCallback; + /// Calback for updating state of the router progress. + typedef function TProgressCallback; + /// Callback on routing statistics typedef function const &)> TRoutingStatisticsCallback; @@ -36,16 +39,19 @@ public: /// @param startPoint point to start routing /// @param direction start direction for routers with high cost of the turnarounds /// @param finalPoint target point for route - /// @param callback function to return routing result + /// @param readyCallback function to return routing result + /// @param progressCallback function to update the router progress virtual void CalculateRoute(m2::PointD const & startPoint, m2::PointD const & direction, - m2::PointD const & finalPoint, TReadyCallback const & callback); + m2::PointD const & finalPoint, TReadyCallback const & readyCallback, + TProgressCallback const & progressCallback); /// Interrupt routing and clear buffers virtual void ClearState(); private: /// This function is called in async mode - void CalculateRouteImpl(TReadyCallback const & callback); + void CalculateRouteImpl(TReadyCallback const & readyCallback, + TProgressCallback const & progressCallback); /// These functions are called to send statistics about the routing void SendStatistics(m2::PointD const & startPoint, m2::PointD const & startDirection, diff --git a/routing/osrm_online_router.cpp b/routing/osrm_online_router.cpp index 3222de3535..bf625d9528 100644 --- a/routing/osrm_online_router.cpp +++ b/routing/osrm_online_router.cpp @@ -25,7 +25,8 @@ string OsrmOnlineRouter::GetName() const } void OsrmOnlineRouter::CalculateRoute(m2::PointD const & startPoint, m2::PointD const & /* direction */, - m2::PointD const & /* finalPoint */, TReadyCallback const & callback) + m2::PointD const & /* finalPoint */, TReadyCallback const & callback, + TProgressCallback const & /* progressCallback */) { // Construct OSRM url request to get the route string url = OSRM_CAR_ROUTING_URL; diff --git a/routing/osrm_online_router.hpp b/routing/osrm_online_router.hpp index 3bd928e78d..575664e9fc 100644 --- a/routing/osrm_online_router.hpp +++ b/routing/osrm_online_router.hpp @@ -20,7 +20,8 @@ public: virtual string GetName() const; // AsyncRouter overrides: void CalculateRoute(m2::PointD const & startPoint, m2::PointD const & /* direction */, - m2::PointD const & /* finalPoint */, TReadyCallback const & callback) override; + m2::PointD const & /* finalPoint */, TReadyCallback const & callback, + TProgressCallback const & /* progressCallback */) override; }; } // namespace routing diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp index 99aca205e6..53e646615e 100644 --- a/routing/osrm_router.cpp +++ b/routing/osrm_router.cpp @@ -519,7 +519,9 @@ OsrmRouter::ResultCode OsrmRouter::MakeRouteFromCrossesPath(TCheckedPath const & OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, m2::PointD const & startDirection, - m2::PointD const & finalPoint, Route & route) + m2::PointD const & finalPoint, + TRoutingProgressFn const & progressCallback, + Route & route) { my::HighResTimer timer(true); TRoutingMappingPtr startMapping = m_indexManager.GetMappingByPoint(startPoint); @@ -553,6 +555,8 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, UNUSED_VALUE(finalMappingGuard); LOG(LINFO, ("Duration of the MWM loading", timer.ElapsedNano())); timer.Reset(); + if (progressCallback) + progressCallback(10.f); // 3. Find start/end nodes. TFeatureGraphNodeVec startTask; @@ -578,6 +582,8 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, LOG(LINFO, ("Duration of the start/stop points lookup", timer.ElapsedNano())); timer.Reset(); + if (progressCallback) + progressCallback(15.f); // 4. Find route. RawRoutingResult routingResult; @@ -596,6 +602,8 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, return RouteNotFound; } INTERRUPT_WHEN_CANCELLED(); + if (progressCallback) + progressCallback(70.0f); // 5. Restore route. @@ -621,6 +629,8 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, ResultCode code = CalculateCrossMwmPath(startTask, m_cachedTargets, m_indexManager, cancellable, m_routingVisualization, finalPath); timer.Reset(); + if (progressCallback) + progressCallback(50.0f); // 5. Make generate answer if (code == NoError) diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp index 37811c26e3..ff9db6908b 100644 --- a/routing/osrm_router.hpp +++ b/routing/osrm_router.hpp @@ -41,7 +41,9 @@ public: virtual string GetName() const; ResultCode CalculateRoute(m2::PointD const & startPoint, m2::PointD const & startDirection, - m2::PointD const & finalPoint, Route & route) override; + m2::PointD const & finalPoint, + TRoutingProgressFn const & progressCallback, + Route & route) override; virtual void ClearState(); diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index f76b69b698..b665f3fed0 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -70,7 +70,9 @@ void RoadGraphRouter::ClearState() IRouter::ResultCode RoadGraphRouter::CalculateRoute(m2::PointD const & startPoint, m2::PointD const & /* startDirection */, - m2::PointD const & finalPoint, Route & route) + m2::PointD const & finalPoint, + TRoutingProgressFn const & progressFn, + Route & route) { vector> finalVicinity; m_roadGraph->FindClosestEdges(finalPoint, MAX_ROAD_CANDIDATES, finalVicinity); @@ -145,7 +147,7 @@ unique_ptr CreatePedestrianAStarRouter(Index & index, } unique_ptr CreatePedestrianAStarBidirectionalRouter( - Index & index, TRoutingProgressFn const & progressFn, TRoutingVisualizerFn const & visualizerFn) + Index & index, TRoutingVisualizerFn const & visualizerFn) { unique_ptr vehicleModelFactory(new PedestrianModelFactory()); unique_ptr algorithm(new AStarBidirectionalRoutingAlgorithm(visualizerFn)); diff --git a/routing/road_graph_router.hpp b/routing/road_graph_router.hpp index d652746893..6e7f098f28 100644 --- a/routing/road_graph_router.hpp +++ b/routing/road_graph_router.hpp @@ -33,7 +33,8 @@ public: string GetName() const override { return m_name; } void ClearState() override; ResultCode CalculateRoute(m2::PointD const & startPoint, m2::PointD const & startDirection, - m2::PointD const & finalPoint, Route & route) override; + m2::PointD const & finalPoint, TRoutingProgressFn const & progressFn, + Route & route) override; // my::Cancellable overrides: void Reset() override { m_algorithm->Reset(); } @@ -53,7 +54,7 @@ unique_ptr CreatePedestrianAStarRouter(Index & index, TRoutingVisualizerFn const & visualizerFn); unique_ptr CreatePedestrianAStarBidirectionalRouter( - Index & index, TRoutingProgressFn const & progressFn, + Index & index, TRoutingVisualizerFn const & visualizerFn); } // namespace routing diff --git a/routing/router.hpp b/routing/router.hpp index 6cfe82f97f..34cd7acea3 100644 --- a/routing/router.hpp +++ b/routing/router.hpp @@ -21,6 +21,11 @@ enum RouterType string ToString(RouterType type); +typedef function TRoutingVisualizerFn; + +/// Returns routing progress from 0 to 100. +typedef function TRoutingProgressFn; + class IRouter : public my::Cancellable { public: @@ -59,12 +64,9 @@ public: /// @see Cancellable virtual ResultCode CalculateRoute(m2::PointD const & startPoint, m2::PointD const & startDirection, - m2::PointD const & finalPoint, Route & route) = 0; + m2::PointD const & finalPoint, + TRoutingProgressFn const & progressCallback, + Route & route) = 0; }; -typedef function TRoutingVisualizerFn; - -/// Returns routing progress from 0 to 100. -typedef function TRoutingProgressFn; - } // namespace routing diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index bed78dd67d..85dc365898 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -35,18 +35,20 @@ RoutingSession::RoutingSession() } void RoutingSession::BuildRoute(m2::PointD const & startPoint, m2::PointD const & endPoint, - TReadyCallbackFn const & callback, + TReadyCallbackFn const & readyCallback, + TProgressCallbackFn const & progressCallback, uint32_t timeoutSec) { ASSERT(m_router != nullptr, ()); m_lastGoodPosition = startPoint; m_endPoint = endPoint; m_router->ClearState(); - RebuildRoute(startPoint, callback, timeoutSec); + RebuildRoute(startPoint, readyCallback, progressCallback, timeoutSec); } -void RoutingSession::RebuildRoute(m2::PointD const & startPoint, TReadyCallbackFn const & callback, - uint32_t timeoutSec) +void RoutingSession::RebuildRoute(m2::PointD const & startPoint, + TReadyCallbackFn const & readyCallback, + TProgressCallbackFn const & progressCallback, uint32_t timeoutSec) { ASSERT(m_router != nullptr, ()); ASSERT_NOT_EQUAL(m_endPoint, m2::PointD::Zero(), ("End point was not set")); @@ -58,7 +60,8 @@ void RoutingSession::RebuildRoute(m2::PointD const & startPoint, TReadyCallbackF // Use old-style callback construction, because lambda constructs buggy function on Android // (callback param isn't captured by value). m_router->CalculateRoute(startPoint, startPoint - m_lastGoodPosition, m_endPoint, - DoReadyCallback(*this, callback, m_routeSessionMutex)); + DoReadyCallback(*this, callback, m_routeSessionMutex), + progressCallback); if (timeoutSec != 0) InitRoutingWatchdogTimer(timeoutSec); diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index 3d4a4acb31..d9efb4f2cd 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -52,6 +52,7 @@ public: typedef function const &)> TRoutingStatisticsCallback; typedef function TReadyCallbackFn; + typedef function TProgressCallbackFn; RoutingSession(); @@ -61,10 +62,10 @@ public: /// @param[in] startPoint and endPoint in mercator /// @param[in] timeoutSec timeout in seconds, if zero then there is no timeout void BuildRoute(m2::PointD const & startPoint, m2::PointD const & endPoint, - TReadyCallbackFn const & callback, - uint32_t timeoutSec); - void RebuildRoute(m2::PointD const & startPoint, TReadyCallbackFn const & callback, - uint32_t timeoutSec); + TReadyCallbackFn const & readyCallback, + TProgressCallbackFn const & progressCallback, uint32_t timeoutSec); + void RebuildRoute(m2::PointD const & startPoint, TReadyCallbackFn const & readyCallback, + TProgressCallbackFn const & progressCallback, uint32_t timeoutSec); m2::PointD GetEndPoint() const { return m_endPoint; } bool IsActive() const { return (m_state != RoutingNotActive); } @@ -79,7 +80,6 @@ public: void MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const; - // TODO (Dragunov) Make activation of the pedestrian routing void ActivateAdditionalFeatures() {} void SetRoutingSettings(RoutingSettings const & routingSettings);