diff --git a/map/routing_session.cpp b/map/routing_session.cpp index 9e52e2b099..5da1c53b6a 100644 --- a/map/routing_session.cpp +++ b/map/routing_session.cpp @@ -21,6 +21,7 @@ RoutingSession::RoutingSession() : m_router(nullptr) , m_route(string()) , m_state(RoutingNotActive) + , m_endPoint(m2::PointD::Zero()) { } @@ -29,19 +30,20 @@ void RoutingSession::BuildRoute(m2::PointD const & startPoint, m2::PointD const { ASSERT(m_router != nullptr, ()); m_lastGoodPosition = startPoint; - m_router->SetFinalPoint(endPoint); + m_endPoint = endPoint; RebuildRoute(startPoint, callback); } void RoutingSession::RebuildRoute(m2::PointD const & startPoint, TReadyCallbackFn const & callback) { ASSERT(m_router != nullptr, ()); + ASSERT_NOT_EQUAL(m_endPoint, m2::PointD::Zero(), ("End point was not set")); Reset(); m_state = RouteBuilding; // Use old-style callback constraction, because lambda constructs buggy function on Android // (callback param isn't captured by value). - m_router->CalculateRoute(startPoint, DoReadyCallback(*this, callback, m_routeSessionMutex), startPoint - m_lastGoodPosition); + m_router->CalculateRoute(startPoint, startPoint - m_lastGoodPosition, m_endPoint, DoReadyCallback(*this, callback, m_routeSessionMutex)); } void RoutingSession::DoReadyCallback::operator() (Route & route, IRouter::ResultCode e) diff --git a/map/routing_session.hpp b/map/routing_session.hpp index 3b4dcbd033..11c5855e67 100644 --- a/map/routing_session.hpp +++ b/map/routing_session.hpp @@ -86,6 +86,7 @@ private: unique_ptr m_router; Route m_route; State m_state; + m2::PointD m_endPoint; mutable threads::Mutex m_routeSessionMutex; diff --git a/pedestrian_routing_benchmarks/pedestrian_routing_test.cpp b/pedestrian_routing_benchmarks/pedestrian_routing_test.cpp index 960c91eb93..4e96901d3d 100644 --- a/pedestrian_routing_benchmarks/pedestrian_routing_test.cpp +++ b/pedestrian_routing_benchmarks/pedestrian_routing_test.cpp @@ -51,13 +51,12 @@ void TestTwoPoints(uint32_t featureIdStart, uint32_t segIdStart, uint32_t featur GetPointsAroundSeg(index, id, featureIdStart, segIdStart); vector finalPos = {{featureIdFinal, true, segIdFinal, finalBounds.second}, {featureIdFinal, false, segIdFinal, finalBounds.first}}; - router.SetFinalRoadPos(finalPos); vector route; my::Timer timer; LOG(LINFO, ("Calculating routing...")); - router.CalculateRoute(startPos, route); + router.CalculateRouteOnMwm(startPos, finalPos, route); LOG(LINFO, ("Route length:", route.size())); LOG(LINFO, ("Elapsed:", timer.ElapsedSeconds(), "seconds")); } diff --git a/routing/astar_router.cpp b/routing/astar_router.cpp index dcbafa298d..d64dc7b87b 100644 --- a/routing/astar_router.cpp +++ b/routing/astar_router.cpp @@ -10,22 +10,7 @@ namespace routing { -static double const kMaxSpeedMPS = 5000.0 / 3600; // m/s - -void AStarRouter::SetFinalRoadPos(vector const & finalPos) -{ -#if defined(DEBUG) - for (auto const & roadPos : finalPos) - LOG(LDEBUG, ("AStarRouter::SetFinalRoadPos(): finalPos:", roadPos)); -#endif // defined(DEBUG) - - ASSERT_GREATER(finalPos.size(), 0, ()); - m_bestDistance.clear(); - for (auto const & roadPos : finalPos) - { - VERIFY(m_bestDistance.insert({roadPos, 0.0}).second, ()); - } -} +static double const kMaxSpeedMPS = 5000.0 / 3600; // This implementation is based on the view that the A* algorithm // is equivalent to Dijkstra's algorithm that is run on a reweighted @@ -39,11 +24,23 @@ void AStarRouter::SetFinalRoadPos(vector const & finalPos) // // The vertices of the graph are of type RoadPos. // The edges of the graph are of type PossibleTurn. -void AStarRouter::CalculateRoute(vector const & startPos, vector & route) +void AStarRouter::CalculateRouteOnMwm(vector const & startPos, vector const & finalPos, vector & route) { +#if defined(DEBUG) + for (auto const & roadPos : finalPos) + LOG(LDEBUG, ("AStarRouter::CalculateRouteOnMwm(): finalPos:", roadPos)); +#endif // defined(DEBUG) + + ASSERT_GREATER(finalPos.size(), 0, ()); + m_bestDistance.clear(); + for (auto const & roadPos : finalPos) + { + VERIFY(m_bestDistance.insert({roadPos, 0.0}).second, ()); + } + #if defined(DEBUG) for (auto const & roadPos : startPos) - LOG(LDEBUG, ("AStarRouter::CalculateRoute(): startPos:", roadPos)); + LOG(LDEBUG, ("AStarRouter::CalculateRouteOnMwm(): startPos:", roadPos)); #endif // defined(DEBUG) route.clear(); diff --git a/routing/astar_router.hpp b/routing/astar_router.hpp index 694a6e342d..9f1af09819 100644 --- a/routing/astar_router.hpp +++ b/routing/astar_router.hpp @@ -14,9 +14,8 @@ class AStarRouter : public RoadGraphRouter public: AStarRouter(Index const * pIndex = 0) : BaseT(pIndex) {} - virtual string GetName() const { return "routeme"; } - virtual void SetFinalRoadPos(vector const & finalPos); - virtual void CalculateRoute(vector const & startPos, vector & route); + virtual string GetName() const { return "pedestrian"; } + void CalculateRouteOnMwm(vector const & startPos, vector const & finalPos, vector & route) override; protected: diff --git a/routing/async_router.cpp b/routing/async_router.cpp new file mode 100644 index 0000000000..f4457eff81 --- /dev/null +++ b/routing/async_router.cpp @@ -0,0 +1,103 @@ +#include "async_router.hpp" + +#include "../base/macros.hpp" +#include "../platform/platform.hpp" +#include "../base/logging.hpp" + +namespace routing +{ + +AsyncRouter::AsyncRouter() +{ + m_requestCancel = false; + m_isReadyThread.clear(); +} + +void AsyncRouter::CalculateRoute( + m2::PointD const & startPt, + m2::PointD const & direction, + m2::PointD const & finalPt, + ReadyCallback const & callback) +{ + { + threads::MutexGuard guard(m_paramsMutex); + UNUSED_VALUE(guard); + + m_startPt = startPt; + m_startDr = direction; + m_finalPt = finalPt; + + m_requestCancel = true; + } + + GetPlatform().RunAsync(bind(&AsyncRouter::CalculateRouteAsync, this, callback)); +} + +void AsyncRouter::ClearState() +{ + m_requestCancel = true; + + threads::MutexGuard guard(m_routeMutex); + UNUSED_VALUE(guard); +} + +void AsyncRouter::CalculateRouteAsync(ReadyCallback const & callback) +{ + if (m_isReadyThread.test_and_set()) + return; + + Route route(GetName()); + ResultCode code; + + threads::MutexGuard guard(m_routeMutex); + UNUSED_VALUE(guard); + + m_isReadyThread.clear(); + + m2::PointD startPt, finalPt, startDr; + { + threads::MutexGuard params(m_paramsMutex); + UNUSED_VALUE(params); + + startPt = m_startPt; + finalPt = m_finalPt; + startDr = m_startDr; + + m_requestCancel = false; + } + + try + { + code = CalculateRouteImpl(startPt, startDr, finalPt, m_requestCancel, route); + switch (code) + { + case StartPointNotFound: + LOG(LWARNING, ("Can't find start or end node")); + break; + case EndPointNotFound: + LOG(LWARNING, ("Can't find end point node")); + break; + case PointsInDifferentMWM: + LOG(LWARNING, ("Points are in different MWMs")); + break; + case RouteNotFound: + LOG(LWARNING, ("Route not found")); + break; + case RouteFileNotExist: + LOG(LWARNING, ("There are no routing file")); + break; + + default: + break; + } + } + catch (Reader::Exception const & e) + { + LOG(LERROR, ("Routing index is absent or incorrect. Error while loading routing index:", e.Msg())); + code = InternalError; + } + + GetPlatform().RunOnGuiThread(bind(callback, route, code)); +} + +} diff --git a/routing/async_router.hpp b/routing/async_router.hpp new file mode 100644 index 0000000000..e87e84593a --- /dev/null +++ b/routing/async_router.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "route.hpp" +#include "router.hpp" + +#include "../std/atomic.hpp" +#include "../base/mutex.hpp" + +namespace routing +{ + +class AsyncRouter : public IRouter +{ +public: + /// AsyncRouter is a wrapper class to run routing routines in the different thread + AsyncRouter(); + + typedef atomic CancelFlagT; + + /// Main method to calulate new route from startPt to finalPt with start direction + /// Processed result will be passed to callback + /// + /// @param startPt point to start routing + /// @param direction start direction for routers with high cost of the turnarounds + /// @param finalPt target point for route + /// @param callback function to return routing result + void CalculateRoute( + m2::PointD const & startPt, + m2::PointD const & direction, + m2::PointD const & finalPt, + ReadyCallback const & callback) override; + + /// Interrupt routing and clear buffers + virtual void ClearState(); + + /// Override this function with routing implementation. + /// It will be called in separate thread and only one function will processed in same time. + /// All locks implemented in AsyncRouter wrapper. + /// + /// @param startPt point to start routing + /// @param direction start direction for routers with high cost of the turnarounds + /// @param finalPt target point for route + /// @param requestCancel interruption flag. You must stop processing when it is true. + /// @param callback function to return routing result + virtual ResultCode CalculateRouteImpl(m2::PointD const & startPt, + m2::PointD const & startDr, + m2::PointD const & finalPt, + CancelFlagT const & requestCancel, + Route & route) = 0; + +private: + void CalculateRouteAsync(ReadyCallback const & callback); + + threads::Mutex m_paramsMutex; + threads::Mutex m_routeMutex; + atomic_flag m_isReadyThread; + atomic m_requestCancel; + + m2::PointD m_startPt, m_finalPt, m_startDr; +}; + +} diff --git a/routing/dijkstra_router.cpp b/routing/dijkstra_router.cpp index 7655bee8ae..c0b3da6655 100644 --- a/routing/dijkstra_router.cpp +++ b/routing/dijkstra_router.cpp @@ -9,7 +9,7 @@ namespace routing DijkstraRouter::ShortestPath const * const DijkstraRouter::ShortestPath::FINAL_POS = reinterpret_cast(1); -void DijkstraRouter::SetFinalRoadPos(vector const & finalPos) +void DijkstraRouter::CalculateRouteOnMwm(vector const & startPos, vector const & finalPos, vector & route) { m_entries = PathSet(); m_queue = PossiblePathQueue(); @@ -20,10 +20,6 @@ void DijkstraRouter::SetFinalRoadPos(vector const & finalPos) ASSERT(t.second, ()); m_queue.push(PossiblePath(0.0, &*t.first, ShortestPath::FINAL_POS)); } -} - -void DijkstraRouter::CalculateRoute(vector const & startPos, vector & route) -{ route.clear(); set startSet(startPos.begin(), startPos.end()); set startFeatureSet; diff --git a/routing/dijkstra_router.hpp b/routing/dijkstra_router.hpp index 6312873e58..e82c2c46fc 100644 --- a/routing/dijkstra_router.hpp +++ b/routing/dijkstra_router.hpp @@ -20,8 +20,9 @@ public: DijkstraRouter(Index const * pIndex = 0) : BaseT(pIndex) {} virtual string GetName() const { return "routeme"; } - virtual void SetFinalRoadPos(vector const & finalPos); - virtual void CalculateRoute(vector const & startPos, vector & route); + virtual void CalculateRouteOnMwm(vector const & startPos, vector const & finalPos, + vector & route); + private: class ShortestPath diff --git a/routing/osrm2feature_map.cpp b/routing/osrm2feature_map.cpp index 7216205799..4324945a88 100644 --- a/routing/osrm2feature_map.cpp +++ b/routing/osrm2feature_map.cpp @@ -164,7 +164,7 @@ void OsrmFtSegMapping::DumpSegmentByNode(TOsrmNodeId nodeId) const } -void OsrmFtSegMapping::GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res, volatile bool const & requestCancel) const +void OsrmFtSegMapping::GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res, atomic const & requestCancel) const { auto addResFn = [&] (uint64_t seg, size_t idx, bool forward) { diff --git a/routing/osrm2feature_map.hpp b/routing/osrm2feature_map.hpp index 741e6e8aca..67edbbfc72 100644 --- a/routing/osrm2feature_map.hpp +++ b/routing/osrm2feature_map.hpp @@ -142,7 +142,7 @@ public: } typedef unordered_map > OsrmNodesT; - void GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res, volatile bool const & requestCancel) const; + void GetOsrmNodes(FtSegSetT & segments, OsrmNodesT & res, atomic const & requestCancel) const; void GetSegmentByIndex(size_t idx, OsrmMappingTypes::FtSeg & seg) const; diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp index 4e762fb9bf..245290ba90 100644 --- a/routing/osrm_router.cpp +++ b/routing/osrm_router.cpp @@ -258,7 +258,7 @@ public: node.m_node.reverse_weight = 0; } - void MakeResult(FeatureGraphNodeVecT & res, size_t maxCount,volatile bool const & requestCancel) + void MakeResult(FeatureGraphNodeVecT & res, size_t maxCount,AsyncRouter::CancelFlagT const & requestCancel) { if (m_mwmId == numeric_limits::max()) return; @@ -364,10 +364,9 @@ RoutingMappingPtrT RoutingIndexManager::GetMappingByName(string const & fName, I OsrmRouter::OsrmRouter(Index const * index, CountryFileFnT const & fn) - : m_pIndex(index), m_indexManager(fn), m_isFinalChanged(false), - m_requestCancel(false), m_additionalFeatures(false) + : m_pIndex(index), m_indexManager(fn), + m_additionalFeatures(false) { - m_isReadyThread.clear(); #ifdef DEBUG m_additionalFeatures = true; #endif @@ -375,112 +374,7 @@ OsrmRouter::OsrmRouter(Index const * index, CountryFileFnT const & fn) string OsrmRouter::GetName() const { - return "mapsme"; -} - -void OsrmRouter::ClearState() -{ - m_requestCancel = true; - - threads::MutexGuard guard(m_routeMutex); - UNUSED_VALUE(guard); - - m_cachedFinalNodes.clear(); - - m_indexManager.Clear(); -} - -void OsrmRouter::SetFinalPoint(m2::PointD const & finalPt) -{ - { - threads::MutexGuard guard(m_paramsMutex); - UNUSED_VALUE(guard); - - m_finalPt = finalPt; - m_isFinalChanged = true; - - m_requestCancel = true; - } -} - -void OsrmRouter::CalculateRoute(m2::PointD const & startPt, ReadyCallback const & callback, m2::PointD const & direction) -{ - { - threads::MutexGuard guard(m_paramsMutex); - UNUSED_VALUE(guard); - - m_startPt = startPt; - m_startDr = direction; - - m_requestCancel = true; - } - - GetPlatform().RunAsync(bind(&OsrmRouter::CalculateRouteAsync, this, callback)); -} - -void OsrmRouter::CalculateRouteAsync(ReadyCallback const & callback) -{ - if (m_isReadyThread.test_and_set()) - return; - - Route route(GetName()); - ResultCode code; - - threads::MutexGuard guard(m_routeMutex); - UNUSED_VALUE(guard); - - m_isReadyThread.clear(); - - m2::PointD startPt, finalPt, startDr; - { - threads::MutexGuard params(m_paramsMutex); - UNUSED_VALUE(params); - - startPt = m_startPt; - finalPt = m_finalPt; - startDr = m_startDr; - - if (m_isFinalChanged) - m_cachedFinalNodes.clear(); - m_isFinalChanged = false; - - m_requestCancel = false; - } - - try - { - code = CalculateRouteImpl(startPt, startDr, finalPt, route); - switch (code) - { - case StartPointNotFound: - LOG(LWARNING, ("Can't find start or end node")); - break; - case EndPointNotFound: - LOG(LWARNING, ("Can't find end point node")); - break; - case PointsInDifferentMWM: - LOG(LWARNING, ("Points are in different MWMs")); - break; - case RouteNotFound: - LOG(LWARNING, ("Route not found")); - break; - case RouteFileNotExist: - LOG(LWARNING, ("There are no routing file")); - break; - - default: - break; - } - } - catch (Reader::Exception const & e) - { - LOG(LERROR, ("Routing index is absent or incorrect. Error while loading routing index:", e.Msg())); - code = InternalError; - - m_indexManager.Clear(); - } - - GetPlatform().RunOnGuiThread(bind(callback, route, code)); + return "vehicle"; } namespace @@ -589,7 +483,7 @@ size_t OsrmRouter::FindNextMwmNode(OutgoingCrossNode const & startNode, RoutingM return INVALID_NODE_ID; } -OsrmRouter::ResultCode OsrmRouter::MakeRouteFromCrossesPath(CheckedPathT const & path, Route & route) +OsrmRouter::ResultCode OsrmRouter::MakeRouteFromCrossesPath(CheckedPathT const & path, CancelFlagT const & requestCancel, Route & route) { Route::TurnsT TurnsDir; Route::TimesT Times; @@ -623,7 +517,7 @@ OsrmRouter::ResultCode OsrmRouter::MakeRouteFromCrossesPath(CheckedPathT const & Route::TimesT mwmTimes; vector mwmPoints; turns::TurnsGeomT mwmTurnsGeom; - MakeTurnAnnotation(routingResult, mwmMapping, mwmPoints, mwmTurnsDir, mwmTimes, mwmTurnsGeom); + MakeTurnAnnotation(routingResult, mwmMapping, mwmPoints, requestCancel, mwmTurnsDir, mwmTimes, mwmTurnsGeom); // And connect it to result route for (auto turn : mwmTurnsDir) @@ -722,12 +616,14 @@ public: } }; -OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt, Route & route) +OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt, CancelFlagT const & requestCancel, Route & route) { my::HighResTimer timer(true); RoutingMappingPtrT startMapping = m_indexManager.GetMappingByPoint(startPt, m_pIndex); RoutingMappingPtrT targetMapping = m_indexManager.GetMappingByPoint(finalPt, m_pIndex); + m_indexManager.Clear(); // TODO (Dragunov) make proper index manager cleaning + if (!startMapping->IsValid()) { route.AddAbsentCountry(startMapping->GetName()); @@ -763,7 +659,8 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt startDr, startTask, MAX_NODE_CANDIDATES, - startMapping); + startMapping, + requestCancel); if (code != NoError) return code; } @@ -775,13 +672,14 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt m2::PointD::Zero(), m_CachedTargetTask, MAX_NODE_CANDIDATES, - targetMapping); + targetMapping, + requestCancel); if (code != NoError) return code; m_CachedTargetPoint = finalPt; } } - if (m_requestCancel) + if (requestCancel) return Cancelled; LOG(LINFO, ("Duration of the start/stop points lookup", timer.ElapsedNano())); @@ -802,7 +700,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt { return RouteNotFound; } - if (m_requestCancel) + if (requestCancel) { return Cancelled; } @@ -814,7 +712,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt vector points; turns::TurnsGeomT turnsGeom; - MakeTurnAnnotation(routingResult, startMapping, points, turnsDir, times, turnsGeom); + MakeTurnAnnotation(routingResult, startMapping, points, requestCancel, turnsDir, times, turnsGeom); route.SetGeometry(points.begin(), points.end()); route.SetTurnInstructions(turnsDir); @@ -893,7 +791,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt if (weights.empty()) return StartPointNotFound; - if (m_requestCancel) + if (requestCancel) return Cancelled; // Load target data @@ -921,7 +819,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt { if (weights[j] == INVALID_EDGE_WEIGHT) continue; - if (m_requestCancel) + if (requestCancel) return Cancelled; string const & nextMwm = startMapping->m_crossContext.getOutgoingMwmName((mwmOutsIter.first + j)->m_outgoingIndex); @@ -966,7 +864,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt { while (getPathWeight(crossTasks.top())= finalWeight) continue; - if (m_requestCancel) + if (requestCancel) return Cancelled; string const & nextMwm = currentContext.getOutgoingMwmName(oit->m_outgoingIndex); @@ -1067,7 +965,7 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRouteImpl(m2::PointD const & startPt { indexPair.second->FreeCrossContext(); }); - auto code = MakeRouteFromCrossesPath(finalPath, route); + auto code = MakeRouteFromCrossesPath(finalPath, requestCancel, route); LOG(LINFO, ("Make final route", timer.ElapsedNano())); timer.Reset(); return code; @@ -1102,7 +1000,13 @@ m2::PointD OsrmRouter::GetPointForTurnAngle(OsrmMappingTypes::FtSeg const & seg, return nextPnt; } -OsrmRouter::ResultCode OsrmRouter::MakeTurnAnnotation(RawRoutingResultT const & routingResult, RoutingMappingPtrT const & mapping, vector & points, Route::TurnsT & turnsDir,Route::TimesT & times, turns::TurnsGeomT & turnsGeom) +OsrmRouter::ResultCode OsrmRouter::MakeTurnAnnotation(RawRoutingResultT const & routingResult, + RoutingMappingPtrT const & mapping, + vector & points, + CancelFlagT const & requestCancel, + Route::TurnsT & turnsDir, + Route::TimesT & times, + turns::TurnsGeomT & turnsGeom) { typedef OsrmMappingTypes::FtSeg SegT; SegT const & segBegin = routingResult.m_sourceEdge.m_seg; @@ -1119,7 +1023,7 @@ OsrmRouter::ResultCode OsrmRouter::MakeTurnAnnotation(RawRoutingResultT const & #endif for (auto i : osrm::irange(0, routingResult.m_routePath.unpacked_path_segments.size())) { - if (m_requestCancel) + if (requestCancel) return Cancelled; // Get all the coordinates for the computed route @@ -1694,7 +1598,7 @@ void OsrmRouter::FixupTurns(vector const & points, Route::TurnsT & t } IRouter::ResultCode OsrmRouter::FindPhantomNodes(string const & fName, m2::PointD const & point, m2::PointD const & direction, - FeatureGraphNodeVecT & res, size_t maxCount, RoutingMappingPtrT const & mapping) + FeatureGraphNodeVecT & res, size_t maxCount, RoutingMappingPtrT const & mapping, CancelFlagT const & requestCancel) { Point2PhantomNode getter(mapping->m_segMapping, m_pIndex, direction); getter.SetPoint(point); @@ -1706,7 +1610,7 @@ IRouter::ResultCode OsrmRouter::FindPhantomNodes(string const & fName, m2::Point if (!getter.HasCandidates()) return StartPointNotFound; - getter.MakeResult(res, maxCount, m_requestCancel); + getter.MakeResult(res, maxCount, requestCancel); return NoError; } diff --git a/routing/osrm_router.hpp b/routing/osrm_router.hpp index ad18c048f9..c251fa7d4f 100644 --- a/routing/osrm_router.hpp +++ b/routing/osrm_router.hpp @@ -87,7 +87,7 @@ public: } }; -class OsrmRouter : public IRouter +class OsrmRouter : public AsyncRouter { public: @@ -110,9 +110,6 @@ public: OsrmRouter(Index const * index, CountryFileFnT const & fn); virtual string GetName() const; - virtual void ClearState(); - virtual void SetFinalPoint(m2::PointD const & finalPt); - virtual void CalculateRoute(m2::PointD const & startPt, ReadyCallback const & callback, m2::PointD const & direction = m2::PointD::Zero()); /*! Find single shortest path in a single MWM between 2 sets of edges * \param source: vector of source edges to make path @@ -148,7 +145,8 @@ public: protected: IRouter::ResultCode FindPhantomNodes(string const & fName, m2::PointD const & point, m2::PointD const & direction, - FeatureGraphNodeVecT & res, size_t maxCount, RoutingMappingPtrT const & mapping); + FeatureGraphNodeVecT & res, size_t maxCount, RoutingMappingPtrT const & mapping, + CancelFlagT const & requestCancel); size_t FindNextMwmNode(OutgoingCrossNode const & startNode, RoutingMappingPtrT const & targetMapping); @@ -158,16 +156,17 @@ protected: * \param routingResult OSRM routing result structure to annotate * \param mapping Feature mappings * \param points Unpacked point pathes + * \param requestCancel flag to stop calculation * \param turnsDir output turns annotation storage * \param times output times annotation storage * \param turnsGeom output turns geometry * \return OSRM routing errors if any */ - ResultCode MakeTurnAnnotation(RawRoutingResultT const & routingResult, RoutingMappingPtrT const & mapping, - vector & points, Route::TurnsT & turnsDir,Route::TimesT & times, turns::TurnsGeomT & turnsGeom); + ResultCode MakeTurnAnnotation(RawRoutingResultT const & routingResult, RoutingMappingPtrT const & mapping, vector & points, + CancelFlagT const & requestCancel, Route::TurnsT & turnsDir,Route::TimesT & times, turns::TurnsGeomT & turnsGeom); void CalculateRouteAsync(ReadyCallback const & callback); - ResultCode CalculateRouteImpl(m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt, Route & route); + ResultCode CalculateRouteImpl(m2::PointD const & startPt, m2::PointD const & startDr, m2::PointD const & finalPt,CancelFlagT const & requestCancel, Route & route) override; private: typedef pair MwmOutT; @@ -201,10 +200,11 @@ private: /*! * \brief Makes route (points turns and other annotations) and submits it to @route class * \param path vector of pathes through mwms + * \param requestCancel flag to terminate processing * \param route class to render final route * \return NoError or error code */ - ResultCode MakeRouteFromCrossesPath(CheckedPathT const & path, Route & route); + ResultCode MakeRouteFromCrossesPath(CheckedPathT const & path, CancelFlagT const & requestCancel, Route & route); NodeID GetTurnTargetNode(NodeID src, NodeID trg, QueryEdge::EdgeData const & edgeData, RoutingMappingPtrT const & routingMapping); void GetPossibleTurns(NodeID node, m2::PointD const & p1, @@ -241,16 +241,9 @@ private: RoutingIndexManager m_indexManager; - bool m_isFinalChanged; m2::PointD m_startPt, m_finalPt, m_startDr; FeatureGraphNodeVecT m_cachedFinalNodes; - threads::Mutex m_paramsMutex; - threads::Mutex m_routeMutex; - atomic_flag m_isReadyThread; - - volatile bool m_requestCancel; - // Additional features unlocking engine bool m_additionalFeatures; }; diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index 67c46ddea0..209b211dff 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -107,43 +107,41 @@ bool RoadGraphRouter::IsMyMWM(size_t mwmID) const return (m_pRoadGraph && dynamic_cast(m_pRoadGraph.get())->GetMwmID() == mwmID); } -void RoadGraphRouter::SetFinalPoint(m2::PointD const & finalPt) +AsyncRouter::ResultCode RoadGraphRouter::CalculateRouteImpl(m2::PointD const & startPt, + m2::PointD const & startDr, + m2::PointD const & finalPt, + CancelFlagT const & requestCancel, + Route & route) { + // We can make easy turnaround when walking. So we will not use direction for route calculation + UNUSED_VALUE(startDr); + vector finalPos; - size_t const mwmID = GetRoadPos(finalPt, finalPos); + size_t mwmID = GetRoadPos(finalPt, finalPos); - if (!finalPos.empty()) - { - if (!IsMyMWM(mwmID)) - m_pRoadGraph.reset(new FeaturesRoadGraph(m_pIndex, mwmID)); + if (!finalPos.empty() && !IsMyMWM(mwmID)) + m_pRoadGraph.reset(new FeaturesRoadGraph(m_pIndex, mwmID)); - SetFinalRoadPos(finalPos); - } -} - -//void RoadGraphRouter::CalculateRoute(m2::PointD const & startPt, ReadyCallback const & callback) -void RoadGraphRouter::CalculateRoute(m2::PointD const & startingPt, ReadyCallback const & callback, m2::PointD const & direction) -{ if (!m_pRoadGraph) - return; + return EndPointNotFound; vector startPos; - size_t const mwmID = GetRoadPos(startingPt, startPos); + mwmID = GetRoadPos(startPt, startPos); if (startPos.empty() || !IsMyMWM(mwmID)) - return; + return StartPointNotFound; my::Timer timer; timer.Reset(); vector routePos; - CalculateRoute(startPos, routePos); + + CalculateRouteOnMwm(startPos, finalPos, routePos); LOG(LINFO, ("Route calculation time: ", timer.ElapsedSeconds())); - Route route(GetName()); m_pRoadGraph->ReconstructPath(routePos, route); - callback(route, NoError); + return NoError; } } // namespace routing diff --git a/routing/road_graph_router.hpp b/routing/road_graph_router.hpp index c5089518e0..ed7400e000 100644 --- a/routing/road_graph_router.hpp +++ b/routing/road_graph_router.hpp @@ -1,6 +1,6 @@ #pragma once -#include "router.hpp" +#include "async_router.hpp" #include "road_graph.hpp" #include "../geometry/point2d.hpp" @@ -16,21 +16,21 @@ namespace routing class IVehicleModel; -class RoadGraphRouter : public IRouter +class RoadGraphRouter : public AsyncRouter { public: RoadGraphRouter(Index const * pIndex); ~RoadGraphRouter(); - virtual void SetFinalPoint(m2::PointD const & finalPt); - //virtual void CalculateRoute(m2::PointD const & startPt, ReadyCallback const & callback); - virtual void CalculateRoute(m2::PointD const & startingPt, ReadyCallback const & callback, m2::PointD const & direction = m2::PointD::Zero()); - - - virtual void SetFinalRoadPos(vector const & finalPos) = 0; - virtual void CalculateRoute(vector const & startPos, vector & route) = 0; + virtual void CalculateRouteOnMwm(vector const & startPos, vector const & finalPos, vector & route) = 0; virtual void SetRoadGraph(IRoadGraph * pRoadGraph) { m_pRoadGraph.reset(pRoadGraph); } + virtual ResultCode CalculateRouteImpl(m2::PointD const & startPt, + m2::PointD const & startDr, + m2::PointD const & finalPt, + CancelFlagT const & requestCancel, + Route & route); + protected: size_t GetRoadPos(m2::PointD const & pt, vector & pos); bool IsMyMWM(size_t mwmID) const; diff --git a/routing/router.hpp b/routing/router.hpp index e4a4682a4f..efa8853f2e 100644 --- a/routing/router.hpp +++ b/routing/router.hpp @@ -38,8 +38,11 @@ public: virtual void ClearState() {} virtual void ActivateAdditionalFeatures() {} - virtual void SetFinalPoint(m2::PointD const & finalPt) = 0; - virtual void CalculateRoute(m2::PointD const & startingPt, ReadyCallback const & callback, m2::PointD const & direction = m2::PointD::Zero()) = 0; + virtual void CalculateRoute( + m2::PointD const & startingPt, + m2::PointD const & direction, + m2::PointD const & finalPt, + ReadyCallback const & callback) = 0; }; } diff --git a/routing/routing.pro b/routing/routing.pro index fe430a8f35..2f24757419 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -24,7 +24,8 @@ SOURCES += \ dijkstra_router.cpp \ features_road_graph.cpp \ road_graph_router.cpp \ - road_graph.cpp + road_graph.cpp \ + async_router.cpp \ HEADERS += \ cross_routing_context.hpp \ @@ -41,4 +42,5 @@ HEADERS += \ dijkstra_router.hpp \ features_road_graph.hpp \ road_graph_router.hpp \ - road_graph.hpp + road_graph.hpp \ + async_router.hpp \ diff --git a/routing/routing_tests/astar_router_test.cpp b/routing/routing_tests/astar_router_test.cpp index a77878e341..5941b206c6 100644 --- a/routing/routing_tests/astar_router_test.cpp +++ b/routing/routing_tests/astar_router_test.cpp @@ -28,9 +28,10 @@ void TestAStarRouterMock(RoadPos (&finalPos)[finalPosSize], AStarRouter router; router.SetRoadGraph(graph); - router.SetFinalRoadPos(vector(&finalPos[0], &finalPos[0] + ARRAY_SIZE(finalPos))); vector result; - router.CalculateRoute(vector(&startPos[0], &startPos[0] + ARRAY_SIZE(startPos)), result); + router.CalculateRouteOnMwm(vector(&startPos[0], &startPos[0] + ARRAY_SIZE(startPos)), + vector(&finalPos[0], &finalPos[0] + ARRAY_SIZE(finalPos)), + result); TEST_EQUAL(vector(&expected[0], &expected[0] + ARRAY_SIZE(expected)), result, ()); } @@ -48,13 +49,12 @@ void TestAStarRouterMWM(RoadPos (&finalPos)[finalPosSize], vector finalV(&finalPos[0], &finalPos[0] + ARRAY_SIZE(finalPos)); tester.Name2FeatureID(finalV); - router.SetFinalRoadPos(finalV); vector startV(&startPos[0], &startPos[0] + ARRAY_SIZE(startPos)); tester.Name2FeatureID(startV); vector result; - router.CalculateRoute(startV, result); + router.CalculateRouteOnMwm(startV, finalV, result); LOG(LDEBUG, (result)); Route route(router.GetName()); diff --git a/routing/routing_tests/dijkstra_router_test.cpp b/routing/routing_tests/dijkstra_router_test.cpp index 710d49a712..a0161b58cc 100644 --- a/routing/routing_tests/dijkstra_router_test.cpp +++ b/routing/routing_tests/dijkstra_router_test.cpp @@ -30,9 +30,9 @@ void TestDijkstraRouterMock(RoadPos (&finalPos)[finalPosSize], router.SetRoadGraph(graph); - router.SetFinalRoadPos(vector(&finalPos[0], &finalPos[0] + ARRAY_SIZE(finalPos))); vector result; - router.CalculateRoute(vector(&startPos[0], &startPos[0] + ARRAY_SIZE(startPos)), result); + router.CalculateRouteOnMwm(vector(&startPos[0], &startPos[0] + ARRAY_SIZE(startPos)), + vector(&finalPos[0], &finalPos[0] + ARRAY_SIZE(finalPos)), result); TEST_EQUAL(vector(&expected[0], &expected[0] + ARRAY_SIZE(expected)), result, ()); } @@ -50,13 +50,12 @@ void TestDijkstraRouterMWM(RoadPos (&finalPos)[finalPosSize], vector finalV(&finalPos[0], &finalPos[0] + ARRAY_SIZE(finalPos)); tester.Name2FeatureID(finalV); - router.SetFinalRoadPos(finalV); vector startV(&startPos[0], &startPos[0] + ARRAY_SIZE(startPos)); tester.Name2FeatureID(startV); vector result; - router.CalculateRoute(startV, result); + router.CalculateRouteOnMwm(startV, finalV, result); LOG(LDEBUG, (result)); Route route(router.GetName());