diff --git a/generator/routing_index_generator.cpp b/generator/routing_index_generator.cpp index 1e293e2f39..a1c23ea8c5 100644 --- a/generator/routing_index_generator.cpp +++ b/generator/routing_index_generator.cpp @@ -286,7 +286,7 @@ void FillWeights(string const & path, string const & mwmFile, string const & cou EdgeEstimator::CreateForCar(nullptr /* trafficStash */, vehicleModel->GetMaxSpeed())); MwmValue mwmValue(LocalCountryFile(path, platform::CountryFile(country), 0 /* version */)); - DeserializeIndexGraph(mwmValue, graph); + DeserializeIndexGraph(mwmValue, kCarMask, graph); map> weights; auto const numEnters = connector.GetEnters().size(); diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index 2a5c78fc32..8935cb4b4e 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -40,6 +40,8 @@ #include +using namespace routing; + namespace { //#define SHOW_ROUTE_DEBUG_MARKS @@ -196,6 +198,18 @@ std::vector DeserializeRoutePoints(std::string const & data) return result; } + +routing::VehicleType GetVehicleType(RouterType routerType) +{ + switch (routerType) + { + case routing::RouterType::Pedestrian: return VehicleType::Pedestrian; + case RouterType::Bicycle: return VehicleType::Bicycle; + case RouterType::Vehicle: + case RouterType::Taxi: return VehicleType::Car; + case RouterType::Count: CHECK(false, ("Invalid type", routerType)); return VehicleType::Count; + } +} } // namespace namespace marketing @@ -203,8 +217,6 @@ namespace marketing char const * const kRoutingCalculatingRoute = "Routing_CalculatingRoute"; } // namespace marketing -using namespace routing; - RoutingManager::RoutingManager(Callbacks && callbacks, Delegate & delegate) : m_callbacks(std::move(callbacks)) , m_delegate(delegate) @@ -345,12 +357,12 @@ RouterType RoutingManager::GetLastUsedRouter() const } } -void RoutingManager::SetRouterImpl(routing::RouterType type) +void RoutingManager::SetRouterImpl(RouterType type) { auto const indexGetterFn = m_callbacks.m_featureIndexGetter; - ASSERT(indexGetterFn, ()); - std::unique_ptr router; - std::unique_ptr fetcher; + CHECK(indexGetterFn, ("type:", type)); + + VehicleType const vehicleType = GetVehicleType(type); auto const countryFileGetter = [this](m2::PointD const & p) -> std::string { // TODO (@gorshenin): fix CountryInfoGetter to return CountryFile @@ -361,40 +373,27 @@ void RoutingManager::SetRouterImpl(routing::RouterType type) auto numMwmIds = make_shared(); m_delegate.RegisterCountryFilesOnRoute(numMwmIds); - if (type == RouterType::Pedestrian) - { - router = CreatePedestrianAStarBidirectionalRouter(indexGetterFn(), countryFileGetter, numMwmIds); - m_routingSession.SetRoutingSettings(routing::GetPedestrianRoutingSettings()); - } - else if (type == RouterType::Bicycle) - { - router = CreateBicycleAStarBidirectionalRouter(indexGetterFn(), countryFileGetter, numMwmIds); - m_routingSession.SetRoutingSettings(routing::GetBicycleRoutingSettings()); - } - else - { - auto & index = m_callbacks.m_featureIndexGetter(); + auto & index = m_callbacks.m_featureIndexGetter(); - auto localFileChecker = [this](std::string const & countryFile) -> bool { - MwmSet::MwmId const mwmId = m_callbacks.m_featureIndexGetter().GetMwmIdByCountryFile( - platform::CountryFile(countryFile)); - if (!mwmId.IsAlive()) - return false; + auto localFileChecker = [this](std::string const & countryFile) -> bool { + MwmSet::MwmId const mwmId = m_callbacks.m_featureIndexGetter().GetMwmIdByCountryFile( + platform::CountryFile(countryFile)); + if (!mwmId.IsAlive()) + return false; - return version::MwmTraits(mwmId.GetInfo()->m_version).HasRoutingIndex(); - }; + return version::MwmTraits(mwmId.GetInfo()->m_version).HasRoutingIndex(); + }; - auto const getMwmRectByName = [this](std::string const & countryId) -> m2::RectD { - return m_callbacks.m_countryInfoGetter().GetLimitRectForLeaf(countryId); - }; + auto const getMwmRectByName = [this](std::string const & countryId) -> m2::RectD { + return m_callbacks.m_countryInfoGetter().GetLimitRectForLeaf(countryId); + }; - router = IndexRouter::CreateCarRouter( - countryFileGetter, getMwmRectByName, numMwmIds, - MakeNumMwmTree(*numMwmIds, m_callbacks.m_countryInfoGetter()), m_routingSession, index); - fetcher.reset(new OnlineAbsentCountriesFetcher(countryFileGetter, localFileChecker)); - m_routingSession.SetRoutingSettings(routing::GetCarRoutingSettings()); - } + auto fetcher = make_unique(countryFileGetter, localFileChecker); + auto router = IndexRouter::Create(vehicleType, countryFileGetter, getMwmRectByName, numMwmIds, + MakeNumMwmTree(*numMwmIds, m_callbacks.m_countryInfoGetter()), + m_routingSession, index); + m_routingSession.SetRoutingSettings(routing::GetRoutingSettings(vehicleType)); m_routingSession.SetRouter(std::move(router), std::move(fetcher)); m_currentRouterType = type; } diff --git a/routing/edge_estimator.cpp b/routing/edge_estimator.cpp index 6cc7f31f33..682f93c827 100644 --- a/routing/edge_estimator.cpp +++ b/routing/edge_estimator.cpp @@ -12,6 +12,17 @@ using namespace traffic; namespace { +double constexpr kKMPH2MPS = 1000.0 / (60 * 60); + +double TimeBetweenSec(m2::PointD const & from, m2::PointD const & to, double speedMPS) +{ + CHECK_GREATER(speedMPS, 0.0, + ("from:", MercatorBounds::ToLatLon(from), "to:", MercatorBounds::ToLatLon(to))); + + double const distanceM = MercatorBounds::DistanceOnEarth(from, to); + return distanceM / speedMPS; +} + double CalcTrafficFactor(SpeedGroup speedGroup) { double constexpr kImpossibleDrivingFactor = 1e4; @@ -27,54 +38,90 @@ double CalcTrafficFactor(SpeedGroup speedGroup) namespace routing { -double constexpr kKMPH2MPS = 1000.0 / (60 * 60); - -inline double TimeBetweenSec(m2::PointD const & from, m2::PointD const & to, double speedMPS) +// EdgeEstimator ----------------------------------------------------------------------------------- +EdgeEstimator::EdgeEstimator(double maxSpeedKMpH) : m_maxSpeedMPS(maxSpeedKMpH * kKMPH2MPS) { - CHECK_GREATER(speedMPS, 0.0, - ("from:", MercatorBounds::ToLatLon(from), "to:", MercatorBounds::ToLatLon(to))); - - double const distanceM = MercatorBounds::DistanceOnEarth(from, to); - return distanceM / speedMPS; + CHECK_GREATER(m_maxSpeedMPS, 0.0, ()); } -class CarEdgeEstimator : public EdgeEstimator +double EdgeEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry const & road) const +{ + ASSERT_LESS(segment.GetPointId(true /* front */), road.GetPointsCount(), ()); + ASSERT_LESS(segment.GetPointId(false /* front */), road.GetPointsCount(), ()); + + double const speedMPS = road.GetSpeed() * kKMPH2MPS; + double result = TimeBetweenSec(road.GetPoint(segment.GetPointId(false /* front */)), + road.GetPoint(segment.GetPointId(true /* front */)), speedMPS); + + return result; +} + +double EdgeEstimator::CalcHeuristic(m2::PointD const & from, m2::PointD const & to) const +{ + return TimeBetweenSec(from, to, m_maxSpeedMPS); +} + +double EdgeEstimator::CalcLeapWeight(m2::PointD const & from, m2::PointD const & to) const +{ + // Let us assume for the time being that + // leap edges will be added with a half of max speed. + // @TODO(bykoianko) It's necessary to gather statistics to calculate better factor(s) instead of + // one below. + return TimeBetweenSec(from, to, m_maxSpeedMPS / 2.0); +} + +// PedestrianEstimator ----------------------------------------------------------------------------- +class PedestrianEstimator final : public EdgeEstimator { public: - CarEdgeEstimator(shared_ptr trafficStash, double maxSpeedKMpH); + explicit PedestrianEstimator(double maxSpeedKMpH) : EdgeEstimator(maxSpeedKMpH) {} + + // EdgeEstimator overrides: + double GetUTurnPenalty() const override { return 0.0 /* seconds */; } + bool LeapIsAllowed(NumMwmId /* mwmId */) const override { return false; } +}; + +// BicycleEstimator -------------------------------------------------------------------------------- +class BicycleEstimator final : public EdgeEstimator +{ +public: + explicit BicycleEstimator(double maxSpeedKMpH) : EdgeEstimator(maxSpeedKMpH) {} + + // EdgeEstimator overrides: + double GetUTurnPenalty() const override { return 20.0 /* seconds */; } + bool LeapIsAllowed(NumMwmId /* mwmId */) const override { return false; } +}; + +// CarEstimator ------------------------------------------------------------------------------------ +class CarEstimator final : public EdgeEstimator +{ +public: + CarEstimator(shared_ptr trafficStash, double maxSpeedKMpH); // EdgeEstimator overrides: double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road) const override; - double CalcHeuristic(m2::PointD const & from, m2::PointD const & to) const override; - double CalcLeapWeight(m2::PointD const & from, m2::PointD const & to) const override; double GetUTurnPenalty() const override; bool LeapIsAllowed(NumMwmId mwmId) const override; private: shared_ptr m_trafficStash; - double const m_maxSpeedMPS; }; -CarEdgeEstimator::CarEdgeEstimator(shared_ptr trafficStash, double maxSpeedKMpH) - : m_trafficStash(trafficStash), m_maxSpeedMPS(maxSpeedKMpH * kKMPH2MPS) +CarEstimator::CarEstimator(shared_ptr trafficStash, double maxSpeedKMpH) + : EdgeEstimator(maxSpeedKMpH) + , m_trafficStash(move(trafficStash)) { - CHECK_GREATER(m_maxSpeedMPS, 0.0, ()); } -double CarEdgeEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry const & road) const +double CarEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry const & road) const { - ASSERT_LESS(segment.GetPointId(true /* front */), road.GetPointsCount(), ()); - ASSERT_LESS(segment.GetPointId(false /* front */), road.GetPointsCount(), ()); - // Current time estimation are too optimistic. // Need more accurate tuning: traffic lights, traffic jams, road models and so on. // Add some penalty to make estimation of a more realistic. // TODO: make accurate tuning, remove penalty. double constexpr kTimePenalty = 1.8; - double const speedMPS = road.GetSpeed() * kKMPH2MPS; - double result = TimeBetweenSec(road.GetPoint(segment.GetPointId(false /* front */)), - road.GetPoint(segment.GetPointId(true /* front */)), speedMPS); + double result = EdgeEstimator::CalcSegmentWeight(segment, road); if (m_trafficStash) { @@ -89,21 +136,7 @@ double CarEdgeEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry return result; } -double CarEdgeEstimator::CalcHeuristic(m2::PointD const & from, m2::PointD const & to) const -{ - return TimeBetweenSec(from, to, m_maxSpeedMPS); -} - -double CarEdgeEstimator::CalcLeapWeight(m2::PointD const & from, m2::PointD const & to) const -{ - // Let us assume for the time being that - // leap edges will be added with a half of max speed. - // @TODO(bykoianko) It's necessary to gather statistics to calculate better factor(s) instead of - // one below. - return TimeBetweenSec(from, to, m_maxSpeedMPS / 2.0); -} - -double CarEdgeEstimator::GetUTurnPenalty() const +double CarEstimator::GetUTurnPenalty() const { // Adds 2 minutes penalty for U-turn. The value is quite arbitrary // and needs to be properly selected after a number of real-world @@ -111,15 +144,21 @@ double CarEdgeEstimator::GetUTurnPenalty() const return 2 * 60; // seconds } -bool CarEdgeEstimator::LeapIsAllowed(NumMwmId mwmId) const { return !m_trafficStash->Has(mwmId); } -} // namespace +bool CarEstimator::LeapIsAllowed(NumMwmId mwmId) const { return !m_trafficStash->Has(mwmId); } -namespace routing -{ +// EdgeEstimator ----------------------------------------------------------------------------------- // static -shared_ptr EdgeEstimator::CreateForCar(shared_ptr trafficStash, - double maxSpeedKMpH) +shared_ptr EdgeEstimator::Create(VehicleType vehicleType, double maxSpeedKMpH, + shared_ptr trafficStash) { - return make_shared(trafficStash, maxSpeedKMpH); + switch (vehicleType) + { + case VehicleType::Pedestrian: return make_shared(maxSpeedKMpH); + case VehicleType::Bicycle: return make_shared(maxSpeedKMpH); + case VehicleType::Car: return make_shared(trafficStash, maxSpeedKMpH); + case VehicleType::Count: + CHECK(false, ("Can't create EdgeEstimator for", vehicleType)); + return nullptr; + } } } // namespace routing diff --git a/routing/edge_estimator.hpp b/routing/edge_estimator.hpp index a866c3e581..7c1c859e82 100644 --- a/routing/edge_estimator.hpp +++ b/routing/edge_estimator.hpp @@ -4,6 +4,7 @@ #include "routing/num_mwm_id.hpp" #include "routing/segment.hpp" #include "routing/traffic_stash.hpp" +#include "routing/vehicle_mask.hpp" #include "traffic/traffic_cache.hpp" @@ -20,25 +21,29 @@ namespace routing class EdgeEstimator { public: + explicit EdgeEstimator(double maxSpeedKMpH); virtual ~EdgeEstimator() = default; - virtual double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road) const = 0; - virtual double CalcHeuristic(m2::PointD const & from, m2::PointD const & to) const = 0; + double CalcHeuristic(m2::PointD const & from, m2::PointD const & to) const; // Returns time in seconds it takes to go from point |from| to point |to| along a leap (fake) // edge |from|-|to|. // Note 1. The result of the method should be used if it's necessary to add a leap (fake) edge // (|from|, |to|) in road graph. // Note 2. The result of the method should be less or equal to CalcHeuristic(|from|, |to|). // Note 3. It's assumed here that CalcLeapWeight(p1, p2) == CalcLeapWeight(p2, p1). - virtual double CalcLeapWeight(m2::PointD const & from, m2::PointD const & to) const = 0; + double CalcLeapWeight(m2::PointD const & from, m2::PointD const & to) const; + + virtual double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road) const; virtual double GetUTurnPenalty() const = 0; // The leap is the shortcut edge from mwm border enter to exit. // Router can't use leaps on some mwms: e.g. mwm with loaded traffic data. // Check wherether leap is allowed on specified mwm or not. virtual bool LeapIsAllowed(NumMwmId mwmId) const = 0; - // The estimator used in car routing. - static shared_ptr CreateForCar(shared_ptr trafficStash, - double maxSpeedKMpH); + static shared_ptr Create(VehicleType, double maxSpeedKMpH, + shared_ptr); + +private: + double const m_maxSpeedMPS; }; } // namespace routing diff --git a/routing/index_graph_loader.cpp b/routing/index_graph_loader.cpp index d0925f63a5..28ae24359a 100644 --- a/routing/index_graph_loader.cpp +++ b/routing/index_graph_loader.cpp @@ -18,7 +18,7 @@ using namespace std; class IndexGraphLoaderImpl final : public IndexGraphLoader { public: - IndexGraphLoaderImpl(shared_ptr numMwmIds, + IndexGraphLoaderImpl(VehicleType vehicleType, shared_ptr numMwmIds, shared_ptr vehicleModelFactory, shared_ptr estimator, Index & index); @@ -29,6 +29,7 @@ public: private: IndexGraph & Load(NumMwmId mwmId); + VehicleMask m_vehicleMask; Index & m_index; shared_ptr m_numMwmIds; shared_ptr m_vehicleModelFactory; @@ -36,10 +37,11 @@ private: unordered_map> m_graphs; }; -IndexGraphLoaderImpl::IndexGraphLoaderImpl(shared_ptr numMwmIds, +IndexGraphLoaderImpl::IndexGraphLoaderImpl(VehicleType vehicleType, shared_ptr numMwmIds, shared_ptr vehicleModelFactory, shared_ptr estimator, Index & index) - : m_index(index) + : m_vehicleMask(GetVehicleMask(vehicleType)) + , m_index(index) , m_numMwmIds(numMwmIds) , m_vehicleModelFactory(vehicleModelFactory) , m_estimator(estimator) @@ -75,7 +77,7 @@ IndexGraph & IndexGraphLoaderImpl::Load(NumMwmId numMwmId) my::Timer timer; MwmValue const & mwmValue = *handle.GetValue(); - DeserializeIndexGraph(mwmValue, graph); + DeserializeIndexGraph(mwmValue, m_vehicleMask, graph); m_graphs[numMwmId] = move(graphPtr); LOG(LINFO, (ROUTING_FILE_TAG, "section for", file.GetName(), "loaded in", timer.ElapsedSeconds(), "seconds")); @@ -109,17 +111,19 @@ namespace routing { // static unique_ptr IndexGraphLoader::Create( - shared_ptr numMwmIds, shared_ptr vehicleModelFactory, - shared_ptr estimator, Index & index) + VehicleType vehicleType, shared_ptr numMwmIds, + shared_ptr vehicleModelFactory, shared_ptr estimator, + Index & index) { - return make_unique(numMwmIds, vehicleModelFactory, estimator, index); + return make_unique(vehicleType, numMwmIds, vehicleModelFactory, estimator, + index); } -void DeserializeIndexGraph(MwmValue const & mwmValue, IndexGraph & graph) +void DeserializeIndexGraph(MwmValue const & mwmValue, VehicleMask vehicleMask, IndexGraph & graph) { FilesContainerR::TReader reader(mwmValue.m_cont.GetReader(ROUTING_FILE_TAG)); ReaderSource src(reader); - IndexGraphSerializer::Deserialize(graph, src, kCarMask); + IndexGraphSerializer::Deserialize(graph, src, vehicleMask); RestrictionLoader restrictionLoader(mwmValue, graph); if (restrictionLoader.HasRestrictions()) graph.SetRestrictions(restrictionLoader.StealRestrictions()); diff --git a/routing/index_graph_loader.hpp b/routing/index_graph_loader.hpp index 217cec4f6e..b1ba9c5de5 100644 --- a/routing/index_graph_loader.hpp +++ b/routing/index_graph_loader.hpp @@ -3,6 +3,7 @@ #include "routing/edge_estimator.hpp" #include "routing/index_graph.hpp" #include "routing/num_mwm_id.hpp" +#include "routing/vehicle_mask.hpp" #include "routing_common/vehicle_model.hpp" @@ -21,10 +22,10 @@ public: virtual void Clear() = 0; static std::unique_ptr Create( - std::shared_ptr numMwmIds, + VehicleType vehicleType, std::shared_ptr numMwmIds, std::shared_ptr vehicleModelFactory, std::shared_ptr estimator, Index & index); }; -void DeserializeIndexGraph(MwmValue const & mwmValue, IndexGraph & graph); +void DeserializeIndexGraph(MwmValue const & mwmValue, VehicleMask vehicleMask, IndexGraph & graph); } // namespace routing diff --git a/routing/index_router.cpp b/routing/index_router.cpp index f5763db8f7..c675a8cdff 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -8,6 +8,7 @@ #include "routing/index_graph_serialization.hpp" #include "routing/index_graph_starter.hpp" #include "routing/index_road_graph.hpp" +#include "routing/pedestrian_directions.hpp" #include "routing/restriction_loader.hpp" #include "routing/route.hpp" #include "routing/routing_helpers.hpp" @@ -49,6 +50,48 @@ double constexpr kMinDistanceToFinishM = 10000; // Limit of adjust in seconds. double constexpr kAdjustLimitSec = 5 * 60; +double CalcMaxSpeed(NumMwmIds const & numMwmIds, VehicleModelFactory const & vehicleModelFactory) +{ + double maxSpeed = 0.0; + numMwmIds.ForEachId([&](NumMwmId id) { + string const & country = numMwmIds.GetFile(id).GetName(); + double const mwmMaxSpeed = + vehicleModelFactory.GetVehicleModelForCountry(country)->GetMaxSpeed(); + maxSpeed = max(maxSpeed, mwmMaxSpeed); + }); + CHECK_GREATER(maxSpeed, 0.0, ()); + return maxSpeed; +} + +shared_ptr CreateVehicleModelFactory(VehicleType vehicleType) +{ + switch (vehicleType) + { + case VehicleType::Pedestrian: return make_shared(); + case VehicleType::Bicycle: return make_shared(); + case VehicleType::Car: return make_shared(); + case VehicleType::Count: + CHECK(false, ("Can't create VehicleModelFactory for", vehicleType)); + return nullptr; + } +} + +unique_ptr CreateDirectionsEngine(VehicleType vehicleType, + shared_ptr numMwmIds, Index & index) +{ + switch (vehicleType) + { + case VehicleType::Pedestrian: return make_unique(numMwmIds); + case VehicleType::Bicycle: + // @TODO Bicycle turn generation engine is used now. It's ok for the time being. + // But later a special car turn generation engine should be implemented. + case VehicleType::Car: return make_unique(index, numMwmIds); + case VehicleType::Count: + CHECK(false, ("Can't create DirectionsEngine for", vehicleType)); + return nullptr; + } +} + template IRouter::ResultCode ConvertResult(typename AStarAlgorithm::Result result) { @@ -199,6 +242,7 @@ IndexRouter::IndexRouter(string const & name, TCountryFileFn const & countryFile CourntryRectFn const & countryRectFn, shared_ptr numMwmIds, unique_ptr> numMwmTree, shared_ptr trafficStash, + VehicleType vehicleType, shared_ptr vehicleModelFactory, shared_ptr estimator, unique_ptr directionsEngine, Index & index) @@ -206,19 +250,19 @@ IndexRouter::IndexRouter(string const & name, TCountryFileFn const & countryFile , m_index(index) , m_countryFileFn(countryFileFn) , m_countryRectFn(countryRectFn) - , m_numMwmIds(numMwmIds) + , m_numMwmIds(move(numMwmIds)) , m_numMwmTree(move(numMwmTree)) - , m_trafficStash(trafficStash) + , m_trafficStash(move(trafficStash)) , m_indexManager(countryFileFn, m_index) , m_roadGraph(index, IRoadGraph::Mode::ObeyOnewayTag, vehicleModelFactory) + , m_vehicleType(vehicleType) , m_vehicleModelFactory(vehicleModelFactory) - , m_estimator(estimator) + , m_estimator(move(estimator)) , m_directionsEngine(move(directionsEngine)) { CHECK(!m_name.empty(), ()); CHECK(m_numMwmIds, ()); CHECK(m_numMwmTree, ()); - CHECK(m_trafficStash, ()); CHECK(m_vehicleModelFactory, ()); CHECK(m_estimator, ()); CHECK(m_directionsEngine, ()); @@ -289,7 +333,7 @@ IRouter::ResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoint if (!route.GetAbsentCountries().empty()) return IRouter::NeedMoreMaps; - TrafficStash::Guard guard(*m_trafficStash); + TrafficStash::Guard guard(m_trafficStash); WorldGraph graph = MakeWorldGraph(); vector segments; @@ -437,7 +481,7 @@ IRouter::ResultCode IndexRouter::AdjustRoute(Checkpoints const & checkpoints, RouterDelegate const & delegate, Route & route) { my::Timer timer; - TrafficStash::Guard guard(*m_trafficStash); + TrafficStash::Guard guard(m_trafficStash); WorldGraph graph = MakeWorldGraph(); graph.SetMode(WorldGraph::Mode::NoLeaps); @@ -538,7 +582,7 @@ WorldGraph IndexRouter::MakeWorldGraph() WorldGraph graph( make_unique(m_numMwmIds, m_numMwmTree, m_vehicleModelFactory, m_countryRectFn, m_index, m_indexManager), - IndexGraphLoader::Create(m_numMwmIds, m_vehicleModelFactory, m_estimator, m_index), + IndexGraphLoader::Create(m_vehicleType, m_numMwmIds, m_vehicleModelFactory, m_estimator, m_index), m_estimator); return graph; } @@ -700,7 +744,7 @@ bool IndexRouter::AreMwmsNear(NumMwmId startId, NumMwmId finishId) const } // static -unique_ptr IndexRouter::CreateCarRouter(TCountryFileFn const & countryFileFn, +unique_ptr IndexRouter::Create(VehicleType vehicleType,TCountryFileFn const & countryFileFn, CourntryRectFn const & coutryRectFn, shared_ptr numMwmIds, unique_ptr> numMwmTree, @@ -708,25 +752,17 @@ unique_ptr IndexRouter::CreateCarRouter(TCountryFileFn const & coun Index & index) { CHECK(numMwmIds, ()); - auto vehicleModelFactory = make_shared(); - // @TODO Bicycle turn generation engine is used now. It's ok for the time being. - // But later a special car turn generation engine should be implemented. - auto directionsEngine = make_unique(index, numMwmIds); - - double maxSpeed = 0.0; - numMwmIds->ForEachId([&](NumMwmId id) { - string const & country = numMwmIds->GetFile(id).GetName(); - double const mwmMaxSpeed = - vehicleModelFactory->GetVehicleModelForCountry(country)->GetMaxSpeed(); - maxSpeed = max(maxSpeed, mwmMaxSpeed); - }); - - auto trafficStash = make_shared(trafficCache, numMwmIds); - - auto estimator = EdgeEstimator::CreateForCar(trafficStash, maxSpeed); + CHECK(numMwmTree, ()); + auto vehicleModelFactory = CreateVehicleModelFactory(vehicleType); + auto directionsEngine = CreateDirectionsEngine(vehicleType, numMwmIds, index); + double const maxSpeed = CalcMaxSpeed(*numMwmIds, *vehicleModelFactory); + auto trafficStash = vehicleType == VehicleType::Car ? + make_shared(trafficCache, numMwmIds) : + nullptr; + auto estimator = EdgeEstimator::Create(vehicleType, maxSpeed, trafficStash); auto router = make_unique( - "astar-bidirectional-car", countryFileFn, coutryRectFn, numMwmIds, move(numMwmTree), - trafficStash, vehicleModelFactory, estimator, move(directionsEngine), index); + "astar-bidirectional-" + ToString(vehicleType), countryFileFn, coutryRectFn, numMwmIds, move(numMwmTree), + trafficStash,vehicleType, vehicleModelFactory, estimator, move(directionsEngine), index); return router; } } // namespace routing diff --git a/routing/index_router.hpp b/routing/index_router.hpp index 8297da53cb..d8cc34863c 100644 --- a/routing/index_router.hpp +++ b/routing/index_router.hpp @@ -54,23 +54,22 @@ public: IndexRouter(string const & name, TCountryFileFn const & countryFileFn, CourntryRectFn const & countryRectFn, shared_ptr numMwmIds, unique_ptr> numMwmTree, shared_ptr trafficStash, - shared_ptr vehicleModelFactory, + VehicleType vehicleType, shared_ptr vehicleModelFactory, shared_ptr estimator, unique_ptr directionsEngine, Index & index); // IRouter overrides: - virtual string GetName() const override { return m_name; } - virtual ResultCode CalculateRoute(Checkpoints const & checkpoints, - m2::PointD const & startDirection, bool adjustToPrevRoute, - RouterDelegate const & delegate, Route & route) override; + string GetName() const override { return m_name; } + ResultCode CalculateRoute(Checkpoints const & checkpoints, m2::PointD const & startDirection, + bool adjustToPrevRoute, RouterDelegate const & delegate, + Route & route) override; - /// \note |numMwmIds| should not be null. - static unique_ptr CreateCarRouter(TCountryFileFn const & countryFileFn, - CourntryRectFn const & coutryRectFn, - shared_ptr numMwmIds, - unique_ptr> numMwmTree, - traffic::TrafficCache const & trafficCache, - Index & index); + static unique_ptr Create(VehicleType vehicleType, + TCountryFileFn const & countryFileFn, + CourntryRectFn const & coutryRectFn, + shared_ptr numMwmIds, + unique_ptr> numMwmTree, + traffic::TrafficCache const & trafficCache, Index & index); private: IRouter::ResultCode DoCalculateRoute(Checkpoints const & checkpoints, @@ -116,6 +115,7 @@ private: shared_ptr m_trafficStash; RoutingIndexManager m_indexManager; FeaturesRoadGraph m_roadGraph; + VehicleType m_vehicleType; shared_ptr m_vehicleModelFactory; shared_ptr m_estimator; unique_ptr m_directionsEngine; diff --git a/routing/route.cpp b/routing/route.cpp index fccb1a1aa2..9d7c1cc299 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -42,7 +42,7 @@ bool IsNormalTurn(TurnItem const & turn) } // namespace Route::Route(string const & router, vector const & points, string const & name) - : m_router(router), m_routingSettings(GetCarRoutingSettings()), + : m_router(router), m_routingSettings(GetRoutingSettings(VehicleType::Car)), m_name(name), m_poly(points.begin(), points.end()) { } diff --git a/routing/route.hpp b/routing/route.hpp index df13be8680..fc1a7ce034 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -140,11 +140,11 @@ public: }; explicit Route(std::string const & router) - : m_router(router), m_routingSettings(GetCarRoutingSettings()) {} + : m_router(router), m_routingSettings(GetRoutingSettings(VehicleType::Car)) {} template Route(std::string const & router, TIter beg, TIter end) - : m_router(router), m_routingSettings(GetCarRoutingSettings()), m_poly(beg, end) + : m_router(router), m_routingSettings(GetRoutingSettings(VehicleType::Car)), m_poly(beg, end) { } diff --git a/routing/routing_settings.hpp b/routing/routing_settings.hpp index f0692a3466..4bd750e505 100644 --- a/routing/routing_settings.hpp +++ b/routing/routing_settings.hpp @@ -1,6 +1,8 @@ #pragma once -#include "std/utility.hpp" +#include "routing/vehicle_mask.hpp" + +#include "base/assert.hpp" namespace routing { @@ -37,24 +39,25 @@ struct RoutingSettings bool m_speedCameraWarning; }; -inline RoutingSettings GetPedestrianRoutingSettings() +inline RoutingSettings GetRoutingSettings(VehicleType vehicleType) { - return RoutingSettings({ true /* m_matchRoute */, false /* m_soundDirection */, - 20. /* m_matchingThresholdM */, true /* m_keepPedestrianInfo */, - false /* m_showTurnAfterNext */, false /* m_speedCameraWarning*/}); -} - -inline RoutingSettings GetCarRoutingSettings() -{ - return RoutingSettings({ true /* m_matchRoute */, true /* m_soundDirection */, - 50. /* m_matchingThresholdM */, false /* m_keepPedestrianInfo */, - true /* m_showTurnAfterNext */, true /* m_speedCameraWarning*/}); -} - -inline RoutingSettings GetBicycleRoutingSettings() -{ - return RoutingSettings({ true /* m_matchRoute */, true /* m_soundDirection */, - 30. /* m_matchingThresholdM */, false /* m_keepPedestrianInfo */, - false /* m_showTurnAfterNext */, false /* m_speedCameraWarning*/}); + switch (vehicleType) + { + case VehicleType::Pedestrian: + return {true /* m_matchRoute */, false /* m_soundDirection */, + 20. /* m_matchingThresholdM */, true /* m_keepPedestrianInfo */, + false /* m_showTurnAfterNext */, false /* m_speedCameraWarning*/}; + case VehicleType::Bicycle: + return {true /* m_matchRoute */, true /* m_soundDirection */, + 30. /* m_matchingThresholdM */, false /* m_keepPedestrianInfo */, + false /* m_showTurnAfterNext */, false /* m_speedCameraWarning*/}; + case VehicleType::Car: + return {true /* m_matchRoute */, true /* m_soundDirection */, + 50. /* m_matchingThresholdM */, false /* m_keepPedestrianInfo */, + true /* m_showTurnAfterNext */, true /* m_speedCameraWarning*/}; + case VehicleType::Count: + CHECK(false, ("Can't create GetRoutingSettings for", vehicleType)); + return {}; + } } } // namespace routing diff --git a/routing/routing_tests/index_graph_tools.cpp b/routing/routing_tests/index_graph_tools.cpp index 20fd44c99b..8700d7c869 100644 --- a/routing/routing_tests/index_graph_tools.cpp +++ b/routing/routing_tests/index_graph_tools.cpp @@ -62,18 +62,6 @@ double WeightedEdgeEstimator::CalcSegmentWeight(Segment const & segment, return it->second; } -double WeightedEdgeEstimator::CalcHeuristic(m2::PointD const & /* from */, - m2::PointD const & /* to */) const -{ - return 0.0; -} - -double WeightedEdgeEstimator::CalcLeapWeight(m2::PointD const & /* from */, - m2::PointD const & /* to */) const -{ - return 0.0; -} - double WeightedEdgeEstimator::GetUTurnPenalty() const { return 0.0; } bool WeightedEdgeEstimator::LeapIsAllowed(NumMwmId /* mwmId */) const { return false; } @@ -278,8 +266,8 @@ shared_ptr CreateEstimatorForCar(traffic::TrafficCache const & tr shared_ptr CreateEstimatorForCar(shared_ptr trafficStash) { - return EdgeEstimator::CreateForCar(trafficStash, - CarModelFactory().GetVehicleModel()->GetMaxSpeed()); + return EdgeEstimator::Create(VehicleType::Car, CarModelFactory().GetVehicleModel()->GetMaxSpeed(), + trafficStash); } AStarAlgorithm::Result CalculateRoute(IndexGraphStarter & starter, diff --git a/routing/routing_tests/index_graph_tools.hpp b/routing/routing_tests/index_graph_tools.hpp index 808e81b7a9..4e23de1c0f 100644 --- a/routing/routing_tests/index_graph_tools.hpp +++ b/routing/routing_tests/index_graph_tools.hpp @@ -94,16 +94,13 @@ private: class WeightedEdgeEstimator final : public EdgeEstimator { public: - WeightedEdgeEstimator(map const & segmentWeights) - : m_segmentWeights(segmentWeights) + explicit WeightedEdgeEstimator(map const & segmentWeights) + : EdgeEstimator(1e10 /* maxSpeedKMpH */), m_segmentWeights(segmentWeights) { } // EdgeEstimator overrides: double CalcSegmentWeight(Segment const & segment, RoadGeometry const & /* road */) const override; - double CalcHeuristic(m2::PointD const & /* from */, m2::PointD const & /* to */) const override; - double CalcLeapWeight(m2::PointD const & /* from */, - m2::PointD const & /* to */) const override; double GetUTurnPenalty() const override; bool LeapIsAllowed(NumMwmId /* mwmId */) const override; diff --git a/routing/traffic_stash.hpp b/routing/traffic_stash.hpp index 451e85e0cd..f16bd3d2bc 100644 --- a/routing/traffic_stash.hpp +++ b/routing/traffic_stash.hpp @@ -21,11 +21,20 @@ public: class Guard final { public: - Guard(TrafficStash & stash) : m_stash(stash) { m_stash.CopyTraffic(); } - ~Guard() { m_stash.Clear(); } + explicit Guard(std::shared_ptr stash) : m_stash(std::move(stash)) + { + if (m_stash) + m_stash->CopyTraffic(); + } + + ~Guard() + { + if (m_stash) + m_stash->Clear(); + } private: - TrafficStash & m_stash; + std::shared_ptr m_stash; }; TrafficStash(traffic::TrafficCache const & source, std::shared_ptr numMwmIds);