From f566f6f0efa2d430eda58d197c831b1e3ef2bed0 Mon Sep 17 00:00:00 2001 From: mvglasow Date: Mon, 26 May 2025 19:49:36 +0300 Subject: [PATCH] [traffxml] Use custom EdgeEstimator for decoding Signed-off-by: mvglasow --- routing/index_router.cpp | 7 ++--- routing/index_router.hpp | 15 +++++++--- traffxml/traff_decoder.cpp | 58 +++++++++++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 7f30fe0bd..1ece94437 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -280,7 +280,7 @@ IndexRouter::IndexRouter(VehicleType vehicleType, bool loadAltitudes, CountryParentNameGetterFn const & countryParentNameGetterFn, TCountryFileFn const & countryFileFn, CountryRectFn const & countryRectFn, shared_ptr numMwmIds, unique_ptr> numMwmTree, - DataSource & dataSource) + std::shared_ptr estimator, DataSource & dataSource) : m_vehicleType(vehicleType) , m_loadAltitudes(loadAltitudes) , m_name("astar-bidirectional-" + ToString(m_vehicleType)) @@ -296,10 +296,7 @@ IndexRouter::IndexRouter(VehicleType vehicleType, bool loadAltitudes, ? IRoadGraph::Mode::IgnoreOnewayTag : IRoadGraph::Mode::ObeyOnewayTag, m_vehicleModelFactory) - , m_estimator(EdgeEstimator::Create( - m_vehicleType, CalcMaxSpeed(*m_numMwmIds, *m_vehicleModelFactory, m_vehicleType), - CalcOffroadSpeed(*m_vehicleModelFactory), m_trafficStash, - &dataSource, m_numMwmIds)) + , m_estimator(estimator) , m_directionsEngine(CreateDirectionsEngine(m_vehicleType, m_numMwmIds, m_dataSource)) , m_countryParentNameGetterFn(countryParentNameGetterFn) { diff --git a/routing/index_router.hpp b/routing/index_router.hpp index 4d433584f..dae5a530b 100644 --- a/routing/index_router.hpp +++ b/routing/index_router.hpp @@ -110,9 +110,15 @@ protected: /** * @brief Creates a new `IndexRouter` instance. * - * This constructor is intended for use by the TraFF decoder, not for normal routing. It lacks the - * `TrafficCache` argument and never creates a traffic stash. This creates a router instance which - * ignores the traffic situation, regardless of the vehicle type. + * This constructor is intended for use by the TraFF decoder, not for normal routing. It differs + * from the general-purpose constructor in two ways. + * + * It takes an explicit `EdgeEstimator` argument, instance, which gives the caller fine-grained + * control over the cost calculations used for routing by supplying an `EdgeEstimator` of their + * choice. + * + * It also lacks the `TrafficCache` argument and never creates a traffic stash. This creates a + * router instance which ignores the traffic situation, regardless of the vehicle type. * * @param vehicleType The vehichle type * @param loadAltitudes Whether to load altitudes @@ -121,13 +127,14 @@ protected: * @param countryRectFn Function which returns the rect for a country * @param numMwmIds * @param numMwmTree + * @param estimator An edge estimator * @param dataSource The MWM data source */ IndexRouter(VehicleType vehicleType, bool loadAltitudes, CountryParentNameGetterFn const & countryParentNameGetterFn, TCountryFileFn const & countryFileFn, CountryRectFn const & countryRectFn, std::shared_ptr numMwmIds, std::unique_ptr> numMwmTree, - DataSource & dataSource); + std::shared_ptr estimator, DataSource & dataSource); private: RouterResultCode CalculateSubrouteJointsMode(IndexGraphStarter & starter, diff --git a/traffxml/traff_decoder.cpp b/traffxml/traff_decoder.cpp index 4b8557217..fa8d1e601 100644 --- a/traffxml/traff_decoder.cpp +++ b/traffxml/traff_decoder.cpp @@ -8,6 +8,7 @@ #include "routing/async_router.hpp" #include "routing/checkpoints.hpp" +#include "routing/edge_estimator.hpp" #include "routing/maxspeeds.hpp" #include "routing/route.hpp" #include "routing/router_delegate.hpp" @@ -350,6 +351,53 @@ void OpenLrV3TraffDecoder::DecodeLocation(traffxml::TraffMessage & message, traf } } +class TraffEstimator final : public routing::EdgeEstimator +{ +public: + TraffEstimator(DataSource * dataSourcePtr, std::shared_ptr numMwmIds, + double maxWeightSpeedKMpH, + routing::SpeedKMpH const & offroadSpeedKMpH) + : EdgeEstimator(maxWeightSpeedKMpH, offroadSpeedKMpH, dataSourcePtr, numMwmIds) + { + } + + // EdgeEstimator overrides: + double CalcSegmentWeight(routing::Segment const & segment, routing::RoadGeometry const & road, Purpose purpose) const override; + double GetUTurnPenalty(Purpose /* purpose */) const override + { + // Adds 2 minutes penalty for U-turn. The value is quite arbitrary + // and needs to be properly selected after a number of real-world + // experiments. + return 2 * 60; // seconds + } + + double GetFerryLandingPenalty(Purpose purpose) const override + { + switch (purpose) + { + case Purpose::Weight: return 20 * 60; // seconds + case Purpose::ETA: return 20 * 60; // seconds + } + UNREACHABLE(); + } +}; + +// TODO only needed temporarily +double GetSpeedMpS(routing::EdgeEstimator::Purpose purpose, routing::Segment const & segment, routing::RoadGeometry const & road) +{ + routing::SpeedKMpH const & speed = road.GetSpeed(segment.IsForward()); + double const speedMpS = measurement_utils::KmphToMps(purpose == routing::EdgeEstimator::Purpose::Weight ? speed.m_weight : speed.m_eta); + ASSERT_GREATER(speedMpS, 0.0, (segment)); + return speedMpS; +} + +double TraffEstimator::CalcSegmentWeight(routing::Segment const & segment, routing::RoadGeometry const & road, Purpose purpose) const +{ + double result = road.GetDistance(segment.GetSegmentIdx()) / GetSpeedMpS(purpose, segment, road); + + return result; +} + RoutingTraffDecoder::DecoderRouter::DecoderRouter(CountryParentNameGetterFn const & countryParentNameGetterFn, routing::TCountryFileFn const & countryFileFn, routing::CountryRectFn const & countryRectFn, @@ -361,16 +409,12 @@ RoutingTraffDecoder::DecoderRouter::DecoderRouter(CountryParentNameGetterFn cons countryParentNameGetterFn, countryFileFn, countryRectFn, - std::move(numMwmIds), + numMwmIds, std::move(numMwmTree), //std::nullopt /* std::optional const & trafficCache */, + std::make_shared(&dataSource, numMwmIds, 120.0f /* maxWeighSpeedKMpH */, + routing::SpeedKMpH(0.01 /* weight */, routing::kNotUsed /* eta */) /* offroadSpeedKMpH */), dataSource) - /* TODO build our own edge estimator for TraFF decoding purposes - , m_estimator(EdgeEstimator::Create( - VehicleType::Car, CalcMaxSpeed(*m_numMwmIds, *m_vehicleModelFactory, m_vehicleType), - CalcOffroadSpeed(*m_vehicleModelFactory), m_trafficStash, - &dataSource, m_numMwmIds)) - */ //, m_directionsEngine(CreateDirectionsEngine(m_vehicleType, m_numMwmIds, m_dataSource)) // TODO we don’t need directions, can we disable that? {}