[traffxml] Use custom EdgeEstimator for decoding

Signed-off-by: mvglasow <michael -at- vonglasow.com>
This commit is contained in:
mvglasow
2025-05-26 19:49:36 +03:00
parent 9afb28aaa1
commit f566f6f0ef
3 changed files with 64 additions and 16 deletions

View File

@@ -280,7 +280,7 @@ IndexRouter::IndexRouter(VehicleType vehicleType, bool loadAltitudes,
CountryParentNameGetterFn const & countryParentNameGetterFn,
TCountryFileFn const & countryFileFn, CountryRectFn const & countryRectFn,
shared_ptr<NumMwmIds> numMwmIds, unique_ptr<m4::Tree<NumMwmId>> numMwmTree,
DataSource & dataSource)
std::shared_ptr<EdgeEstimator> 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)
{

View File

@@ -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> numMwmIds, std::unique_ptr<m4::Tree<NumMwmId>> numMwmTree,
DataSource & dataSource);
std::shared_ptr<EdgeEstimator> estimator, DataSource & dataSource);
private:
RouterResultCode CalculateSubrouteJointsMode(IndexGraphStarter & starter,

View File

@@ -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<routing::NumMwmIds> 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<traffic::TrafficCache> const & trafficCache */,
std::make_shared<TraffEstimator>(&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 dont need directions, can we disable that?
{}