mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-21 05:43:37 +00:00
[traffxml] Add router-based decoder, still crude, ugly and buggy
To use it, redefine DefaultTraffDecoder in traffxml/traff_decoder.hpp Signed-off-by: mvglasow <michael -at- vonglasow.com>
This commit is contained in:
@@ -296,6 +296,7 @@ Framework::Framework(FrameworkParams const & params, bool loadMaps)
|
||||
[this]() -> power_management::PowerManager const & { return m_powerManager; }),
|
||||
static_cast<RoutingManager::Delegate &>(*this))
|
||||
, m_trafficManager(m_featuresFetcher.GetDataSource(),
|
||||
[this]() -> storage::CountryInfoGetter const & { return GetCountryInfoGetter(); },
|
||||
[this](string const & id) -> string { return m_storage.GetParentIdFor(id); },
|
||||
bind(&Framework::GetMwmsByRect, this, _1, false /* rough */),
|
||||
kMaxTrafficCacheSizeBytes, m_routingManager.RoutingSession())
|
||||
@@ -388,6 +389,8 @@ Framework::Framework(FrameworkParams const & params, bool loadMaps)
|
||||
|
||||
if (loadMaps)
|
||||
LoadMapsSync();
|
||||
|
||||
m_trafficManager.Start();
|
||||
}
|
||||
|
||||
Framework::~Framework()
|
||||
|
||||
@@ -56,13 +56,13 @@ TrafficManager::CacheEntry::CacheEntry(time_point<steady_clock> const & requestT
|
||||
, m_lastAvailability(traffic::TrafficInfo::Availability::Unknown)
|
||||
{}
|
||||
|
||||
TrafficManager::TrafficManager(DataSource & dataSource,
|
||||
TrafficManager::TrafficManager(DataSource & dataSource, CountryInfoGetterFn countryInfoGetter,
|
||||
const CountryParentNameGetterFn &countryParentNameGetter,
|
||||
GetMwmsByRectFn const & getMwmsByRectFn, size_t maxCacheSizeBytes,
|
||||
traffic::TrafficObserver & observer)
|
||||
: m_dataSource(dataSource)
|
||||
, m_countryInfoGetterFn(countryInfoGetter)
|
||||
, m_countryParentNameGetterFn(countryParentNameGetter)
|
||||
, m_traffDecoder(dataSource, countryParentNameGetter, m_messageCache)
|
||||
, m_getMwmsByRectFn(getMwmsByRectFn)
|
||||
, m_observer(observer)
|
||||
, m_currentDataVersion(0)
|
||||
@@ -129,6 +129,13 @@ void TrafficManager::SetEnabled(bool enabled)
|
||||
m_observer.OnTrafficInfoClear();
|
||||
}
|
||||
|
||||
void TrafficManager::Start()
|
||||
{
|
||||
m_traffDecoder = make_unique<traffxml::DefaultTraffDecoder>(m_dataSource, m_countryInfoGetterFn,
|
||||
m_countryParentNameGetterFn, m_messageCache);
|
||||
m_isStarted = true;
|
||||
}
|
||||
|
||||
void TrafficManager::Clear()
|
||||
{
|
||||
// TODO no longer needed
|
||||
@@ -211,7 +218,6 @@ void TrafficManager::UpdateActiveMwms(m2::RectD const & rect,
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_isStarted = true;
|
||||
m_activeMwmsChanged = true;
|
||||
activeMwms.clear();
|
||||
for (auto const & mwm : mwms)
|
||||
@@ -462,7 +468,7 @@ void TrafficManager::DecodeFirstMessage()
|
||||
}
|
||||
|
||||
LOG(LINFO, (" ", message.m_id, ":", message));
|
||||
m_traffDecoder.DecodeMessage(message);
|
||||
m_traffDecoder->DecodeMessage(message);
|
||||
// store message in cache
|
||||
m_messageCache.insert_or_assign(message.m_id, message);
|
||||
// store message coloring in AllMwmColoring
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "indexer/mwm_set.hpp"
|
||||
|
||||
#include "storage/country_info_getter.hpp"
|
||||
|
||||
#include "traffxml/traff_decoder.hpp"
|
||||
#include "traffxml/traff_model.hpp"
|
||||
|
||||
@@ -34,6 +36,7 @@
|
||||
class TrafficManager final
|
||||
{
|
||||
public:
|
||||
using CountryInfoGetterFn = std::function<storage::CountryInfoGetter const &()>;
|
||||
using CountryParentNameGetterFn = std::function<std::string(std::string const &)>;
|
||||
|
||||
/**
|
||||
@@ -75,6 +78,7 @@ public:
|
||||
using GetMwmsByRectFn = std::function<std::vector<MwmSet::MwmId>(m2::RectD const &)>;
|
||||
|
||||
TrafficManager(DataSource & dataSource,
|
||||
CountryInfoGetterFn countryInfoGetter,
|
||||
CountryParentNameGetterFn const & countryParentNameGetter,
|
||||
GetMwmsByRectFn const & getMwmsByRectFn, size_t maxCacheSizeBytes,
|
||||
traffic::TrafficObserver & observer);
|
||||
@@ -109,6 +113,26 @@ public:
|
||||
*/
|
||||
bool IsEnabled() const;
|
||||
|
||||
/**
|
||||
* @brief Starts the traffic manager.
|
||||
*
|
||||
* After creation, the traffic manager will not poll any sources or process any feeds until it is
|
||||
* started. Feeds received through `Push()` will be added to the queue before the traffic manager
|
||||
* is started, but will not be processed any further until the traffic manager is started.
|
||||
*
|
||||
* MWMs must be loaded before starting the traffic manager.
|
||||
*
|
||||
* @todo Currently, all MWMs must be loaded before calling `Start()`, as MWMs loaded after that
|
||||
* will not get picked up. We need to extend `TrafficManager` to react to MWMs being added (and
|
||||
* removed) – note that this affects the data source, not the set of active MWMs.
|
||||
*
|
||||
* @todo Start is currently not integrated with state or pause/resume logic (all of which might
|
||||
* not be fully implemented ATM). If the traffic manager is not started, no message processing
|
||||
* (other than filling the queue and deduplication) will take place, regardless of state. Starting
|
||||
* the traffic manager will not change the state it reports.
|
||||
*/
|
||||
void Start();
|
||||
|
||||
void UpdateViewport(ScreenBase const & screen);
|
||||
void UpdateMyPosition(MyPosition const & myPosition);
|
||||
|
||||
@@ -400,6 +424,7 @@ private:
|
||||
}
|
||||
|
||||
DataSource & m_dataSource;
|
||||
CountryInfoGetterFn m_countryInfoGetterFn;
|
||||
CountryParentNameGetterFn m_countryParentNameGetterFn;
|
||||
GetMwmsByRectFn m_getMwmsByRectFn;
|
||||
traffic::TrafficObserver & m_observer;
|
||||
@@ -535,7 +560,7 @@ private:
|
||||
*
|
||||
* Used to decode TraFF locations into road segments on the map.
|
||||
*/
|
||||
traffxml::DefaultTraffDecoder m_traffDecoder;
|
||||
std::unique_ptr<traffxml::DefaultTraffDecoder> m_traffDecoder;
|
||||
|
||||
/**
|
||||
* @brief Map between MWM IDs and their colorings.
|
||||
|
||||
@@ -276,6 +276,40 @@ IndexRouter::IndexRouter(VehicleType vehicleType, bool loadAltitudes,
|
||||
CHECK(m_directionsEngine, ());
|
||||
}
|
||||
|
||||
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)
|
||||
: m_vehicleType(vehicleType)
|
||||
, m_loadAltitudes(loadAltitudes)
|
||||
, m_name("astar-bidirectional-" + ToString(m_vehicleType))
|
||||
, m_dataSource(dataSource, numMwmIds)
|
||||
, m_vehicleModelFactory(CreateVehicleModelFactory(m_vehicleType, countryParentNameGetterFn))
|
||||
, m_countryFileFn(countryFileFn)
|
||||
, m_countryRectFn(countryRectFn)
|
||||
, m_numMwmIds(std::move(numMwmIds))
|
||||
, m_numMwmTree(std::move(numMwmTree))
|
||||
, m_trafficStash(nullptr)
|
||||
, m_roadGraph(m_dataSource,
|
||||
vehicleType == VehicleType::Pedestrian || vehicleType == VehicleType::Transit
|
||||
? 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_directionsEngine(CreateDirectionsEngine(m_vehicleType, m_numMwmIds, m_dataSource))
|
||||
, m_countryParentNameGetterFn(countryParentNameGetterFn)
|
||||
{
|
||||
CHECK(!m_name.empty(), ());
|
||||
CHECK(m_numMwmIds, ());
|
||||
CHECK(m_numMwmTree, ());
|
||||
CHECK(m_estimator, ());
|
||||
CHECK(m_directionsEngine, ());
|
||||
}
|
||||
|
||||
unique_ptr<WorldGraph> IndexRouter::MakeSingleMwmWorldGraph()
|
||||
{
|
||||
auto worldGraph = MakeWorldGraph();
|
||||
|
||||
@@ -65,6 +65,23 @@ public:
|
||||
m2::PointD const m_direction;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new `IndexRouter` instance.
|
||||
*
|
||||
* This is the constructor intended for normal routing. It requires a `TrafficCache` argument,
|
||||
* from which it may create a traffic stash so the traffic situation can be considered for the
|
||||
* route, depending on the vehicle type.
|
||||
*
|
||||
* @param vehicleType The vehichle type
|
||||
* @param loadAltitudes Whether to load altitudes
|
||||
* @param countryParentNameGetterFn Function which converts a country name into the name of its parent country)
|
||||
* @param countryFileFn Function which converts a pointer to its country name
|
||||
* @param countryRectFn Function which returns the rect for a country
|
||||
* @param numMwmIds
|
||||
* @param numMwmTree
|
||||
* @param trafficCache The traffic cache (used only if `vehicleType` is `VehicleType::Car`)
|
||||
* @param dataSource The MWM data source
|
||||
*/
|
||||
IndexRouter(VehicleType vehicleType, bool loadAltitudes,
|
||||
CountryParentNameGetterFn const & countryParentNameGetterFn,
|
||||
TCountryFileFn const & countryFileFn, CountryRectFn const & countryRectFn,
|
||||
@@ -89,6 +106,29 @@ public:
|
||||
|
||||
VehicleType GetVehicleType() const { return m_vehicleType; }
|
||||
|
||||
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.
|
||||
*
|
||||
* @param vehicleType The vehichle type
|
||||
* @param loadAltitudes Whether to load altitudes
|
||||
* @param countryParentNameGetterFn Function which converts a country name into the name of its parent country)
|
||||
* @param countryFileFn Function which converts a pointer to its country name
|
||||
* @param countryRectFn Function which returns the rect for a country
|
||||
* @param numMwmIds
|
||||
* @param numMwmTree
|
||||
* @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);
|
||||
|
||||
private:
|
||||
RouterResultCode CalculateSubrouteJointsMode(IndexGraphStarter & starter,
|
||||
RouterDelegate const & delegate,
|
||||
|
||||
@@ -6,10 +6,18 @@
|
||||
#include "openlr/openlr_decoder.hpp"
|
||||
#include "openlr/openlr_model.hpp"
|
||||
|
||||
#include "routing/async_router.hpp"
|
||||
#include "routing/checkpoints.hpp"
|
||||
#include "routing/maxspeeds.hpp"
|
||||
#include "routing/route.hpp"
|
||||
#include "routing/router_delegate.hpp"
|
||||
|
||||
#include "routing_common/maxspeed_conversion.hpp"
|
||||
|
||||
#include "storage/routing_helpers.hpp"
|
||||
|
||||
#include "traffic/traffic_cache.hpp"
|
||||
|
||||
namespace traffxml
|
||||
{
|
||||
// Number of worker threads for the OpenLR decoder
|
||||
@@ -21,10 +29,15 @@ namespace traffxml
|
||||
*/
|
||||
auto constexpr kNumDecoderThreads = 1;
|
||||
|
||||
TraffDecoder::TraffDecoder(DataSource & dataSource,
|
||||
// Timeout for the router in seconds, used by RoutingTraffDecoder
|
||||
// TODO set to a sensible value
|
||||
auto constexpr kRouterTimeoutSec = 30;
|
||||
|
||||
TraffDecoder::TraffDecoder(DataSource & dataSource, CountryInfoGetterFn countryInfoGetter,
|
||||
const CountryParentNameGetterFn & countryParentNameGetter,
|
||||
std::map<std::string, TraffMessage> & messageCache)
|
||||
: m_dataSource(dataSource)
|
||||
, m_countryInfoGetterFn(countryInfoGetter)
|
||||
, m_countryParentNameGetterFn(countryParentNameGetter)
|
||||
, m_messageCache(messageCache)
|
||||
{}
|
||||
@@ -121,10 +134,10 @@ void TraffDecoder::DecodeMessage(traffxml::TraffMessage & message)
|
||||
}
|
||||
}
|
||||
|
||||
OpenLrV3TraffDecoder::OpenLrV3TraffDecoder(DataSource & dataSource,
|
||||
OpenLrV3TraffDecoder::OpenLrV3TraffDecoder(DataSource & dataSource, CountryInfoGetterFn countryInfoGetter,
|
||||
const CountryParentNameGetterFn & countryParentNameGetter,
|
||||
std::map<std::string, TraffMessage> & messageCache)
|
||||
: TraffDecoder(dataSource, countryParentNameGetter, messageCache)
|
||||
: TraffDecoder(dataSource, countryInfoGetter, countryParentNameGetter, messageCache)
|
||||
, m_openLrDecoder(dataSource, countryParentNameGetter)
|
||||
{}
|
||||
|
||||
@@ -336,4 +349,263 @@ void OpenLrV3TraffDecoder::DecodeLocation(traffxml::TraffMessage & message, traf
|
||||
decoded[paths[i].m_path[j].GetFeatureId().m_mwmId][traffic::TrafficInfo::RoadSegmentId(fid, segment, direction)] = traffic::SpeedGroup::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
RoutingTraffDecoder::DecoderRouter::DecoderRouter(CountryParentNameGetterFn const & countryParentNameGetterFn,
|
||||
routing::TCountryFileFn const & countryFileFn,
|
||||
routing::CountryRectFn const & countryRectFn,
|
||||
std::shared_ptr<routing::NumMwmIds> numMwmIds,
|
||||
std::unique_ptr<m4::Tree<routing::NumMwmId>> numMwmTree,
|
||||
DataSource & dataSource)
|
||||
: routing::IndexRouter(routing::VehicleType::Car /* VehicleType vehicleType */,
|
||||
false /* bool loadAltitudes */,
|
||||
countryParentNameGetterFn,
|
||||
countryFileFn,
|
||||
countryRectFn,
|
||||
std::move(numMwmIds),
|
||||
std::move(numMwmTree),
|
||||
//std::nullopt /* std::optional<traffic::TrafficCache> const & trafficCache */,
|
||||
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?
|
||||
{}
|
||||
|
||||
RoutingTraffDecoder::RoutingTraffDecoder(DataSource & dataSource, CountryInfoGetterFn countryInfoGetter,
|
||||
const CountryParentNameGetterFn & countryParentNameGetter,
|
||||
std::map<std::string, TraffMessage> & messageCache)
|
||||
: TraffDecoder(dataSource, countryInfoGetter, countryParentNameGetter, messageCache)
|
||||
{
|
||||
InitRouter();
|
||||
}
|
||||
|
||||
bool RoutingTraffDecoder::InitRouter()
|
||||
{
|
||||
if (m_router)
|
||||
return true;
|
||||
|
||||
// code mostly from RoutingManager::SetRouterImpl(RouterType)
|
||||
/*
|
||||
* RoutingManager::SetRouterImpl(RouterType) calls m_delegate.RegisterCountryFilesOnRoute(numMwmIds).
|
||||
* m_delegate is the framework, and the routine cycles through the countries in storage.
|
||||
* As we don’t have access to storage, we get our country files from the data source.
|
||||
*/
|
||||
std::vector<std::shared_ptr<MwmInfo>> mwmsInfo;
|
||||
m_dataSource.GetMwmsInfo(mwmsInfo);
|
||||
for (auto mwmInfo : mwmsInfo)
|
||||
m_numMwmIds->RegisterFile(mwmInfo->GetLocalFile().GetCountryFile());
|
||||
|
||||
if (m_numMwmIds->IsEmpty())
|
||||
return false;
|
||||
|
||||
auto const countryFileGetter = [this](m2::PointD const & p) -> std::string {
|
||||
// TODO (@gorshenin): fix CountryInfoGetter to return CountryFile
|
||||
// instances instead of plain strings.
|
||||
return m_countryInfoGetterFn().GetRegionCountryId(p);
|
||||
};
|
||||
|
||||
auto const getMwmRectByName = [this](std::string const & countryId) -> m2::RectD {
|
||||
return m_countryInfoGetterFn().GetLimitRectForLeaf(countryId);
|
||||
};
|
||||
|
||||
m_router =
|
||||
make_unique<RoutingTraffDecoder::DecoderRouter>(m_countryParentNameGetterFn,
|
||||
countryFileGetter, getMwmRectByName, m_numMwmIds,
|
||||
routing::MakeNumMwmTree(*m_numMwmIds, m_countryInfoGetterFn()),
|
||||
m_dataSource);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copied from AsyncRouter
|
||||
// static
|
||||
void RoutingTraffDecoder::LogCode(routing::RouterResultCode code, double const elapsedSec)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case routing::RouterResultCode::StartPointNotFound:
|
||||
LOG(LWARNING, ("Can't find start or end node"));
|
||||
break;
|
||||
case routing::RouterResultCode::EndPointNotFound:
|
||||
LOG(LWARNING, ("Can't find end point node"));
|
||||
break;
|
||||
case routing::RouterResultCode::PointsInDifferentMWM:
|
||||
LOG(LWARNING, ("Points are in different MWMs"));
|
||||
break;
|
||||
case routing::RouterResultCode::RouteNotFound:
|
||||
LOG(LWARNING, ("Route not found"));
|
||||
break;
|
||||
case routing::RouterResultCode::RouteFileNotExist:
|
||||
LOG(LWARNING, ("There is no routing file"));
|
||||
break;
|
||||
case routing::RouterResultCode::NeedMoreMaps:
|
||||
LOG(LINFO,
|
||||
("Routing can find a better way with additional maps, elapsed seconds:", elapsedSec));
|
||||
break;
|
||||
case routing::RouterResultCode::Cancelled:
|
||||
LOG(LINFO, ("Route calculation cancelled, elapsed seconds:", elapsedSec));
|
||||
break;
|
||||
case routing::RouterResultCode::NoError:
|
||||
LOG(LINFO, ("Route found, elapsed seconds:", elapsedSec));
|
||||
break;
|
||||
case routing::RouterResultCode::NoCurrentPosition:
|
||||
LOG(LINFO, ("No current position"));
|
||||
break;
|
||||
case routing::RouterResultCode::InconsistentMWMandRoute:
|
||||
LOG(LINFO, ("Inconsistent mwm and route"));
|
||||
break;
|
||||
case routing::RouterResultCode::InternalError:
|
||||
LOG(LINFO, ("Internal error"));
|
||||
break;
|
||||
case routing::RouterResultCode::FileTooOld:
|
||||
LOG(LINFO, ("File too old"));
|
||||
break;
|
||||
case routing::RouterResultCode::IntermediatePointNotFound:
|
||||
LOG(LWARNING, ("Can't find intermediate point node"));
|
||||
break;
|
||||
case routing::RouterResultCode::TransitRouteNotFoundNoNetwork:
|
||||
LOG(LWARNING, ("No transit route is found because there's no transit network in the mwm of "
|
||||
"the route point"));
|
||||
break;
|
||||
case routing::RouterResultCode::TransitRouteNotFoundTooLongPedestrian:
|
||||
LOG(LWARNING, ("No transit route is found because pedestrian way is too long"));
|
||||
break;
|
||||
case routing::RouterResultCode::RouteNotFoundRedressRouteError:
|
||||
LOG(LWARNING, ("Route not found because of a redress route error"));
|
||||
break;
|
||||
case routing::RouterResultCode::HasWarnings:
|
||||
LOG(LINFO, ("Route has warnings, elapsed seconds:", elapsedSec));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RoutingTraffDecoder::DecodeLocationDirection(traffxml::TraffMessage & message,
|
||||
traffxml::MultiMwmColoring & decoded, bool backwards)
|
||||
{
|
||||
bool adjustToPrevRoute = false; // calculate a fresh route, no adjustments to previous one
|
||||
uint64_t routeId = 0; // used in callbacks to identify the route, we might not need it at all
|
||||
std::string routerName; // set later
|
||||
|
||||
std::vector<m2::PointD> points;
|
||||
if (message.m_location.value().m_from)
|
||||
points.push_back(mercator::FromLatLon(message.m_location.value().m_from.value().m_coordinates));
|
||||
if (message.m_location.value().m_at)
|
||||
points.push_back(mercator::FromLatLon(message.m_location.value().m_at.value().m_coordinates));
|
||||
else if (message.m_location.value().m_via)
|
||||
points.push_back(mercator::FromLatLon(message.m_location.value().m_via.value().m_coordinates));
|
||||
if (message.m_location.value().m_to)
|
||||
points.push_back(mercator::FromLatLon(message.m_location.value().m_to.value().m_coordinates));
|
||||
if (backwards)
|
||||
std::reverse(points.begin(), points.end());
|
||||
// m_notVia is ignored as OpenLR does not support this functionality.
|
||||
CHECK_GREATER(points.size(), 1, ("At least two reference points must be given"));
|
||||
|
||||
/*
|
||||
* startDirection is the direction of travel at start. Can be m2::PointD::Zero() to ignore
|
||||
* direction, or PositionAccumulator::GetDirection(), which basically returns the difference
|
||||
* between the last position and an earlier one (offset between two points from which the
|
||||
* direction of travel can be inferred).
|
||||
*
|
||||
* For our purposes, points[1] - points[0] would be as close as we could get to a start direction.
|
||||
* This would be accurate on very straight roads, less accurate on not-so-straight ones. However,
|
||||
* even on a near-straight road, the standard router (with the default EdgeEstimator) seemed quite
|
||||
* unimpressed by the direction and insisted on starting off on the carriageway closest to the
|
||||
* start point and sending us on a huge detour, instead of taking the direct route on the opposite
|
||||
* carriageway.
|
||||
*/
|
||||
m2::PointD startDirection = m2::PointD::Zero();
|
||||
|
||||
routing::Checkpoints checkpoints(std::move(points));
|
||||
|
||||
/*
|
||||
* This code is mostly lifted from:
|
||||
* - AsyncRouter::CalculateRoute(Checkpoints const &, m2::PointD const &, bool, ReadyCallbackOwnership const &,
|
||||
* NeedMoreMapsCallback const &, RemoveRouteCallback const &, ProgressCallback, uint32_t)
|
||||
* - AsyncRouter::CalculateRoute()
|
||||
*/
|
||||
|
||||
// AsyncRouter::CalculateRoute(with args)
|
||||
/*
|
||||
* AsyncRouter::CalculateRoute() has a `DelegateProxy`, which is private. We just need the return
|
||||
* value of GetDelegate(), which is a `routing::RouterDelegate`, so use that instead. We don’t
|
||||
* nedd any of the callbacks, therefore we don’t set them.
|
||||
*/
|
||||
routing::RouterDelegate delegate;
|
||||
delegate.SetTimeout(kRouterTimeoutSec);
|
||||
|
||||
// AsyncRouter::CalculateRoute()
|
||||
if (!m_router && !InitRouter())
|
||||
return;
|
||||
|
||||
routerName = m_router->GetName();
|
||||
// TODO is that for following a track? If so, can we use that with just 2–3 reference points?
|
||||
//router->SetGuides(std::move(m_guides));
|
||||
//m_guides.clear();
|
||||
|
||||
auto route = std::make_shared<routing::Route>(m_router->GetName(), routeId);
|
||||
routing::RouterResultCode code;
|
||||
|
||||
base::Timer timer;
|
||||
double elapsedSec = 0.0;
|
||||
|
||||
try
|
||||
{
|
||||
LOG(LINFO, ("Calculating the route of direct length", checkpoints.GetSummaryLengthBetweenPointsMeters(),
|
||||
"m. checkpoints:", checkpoints, "startDirection:", startDirection, "router name:", m_router->GetName()));
|
||||
|
||||
// Run basic request.
|
||||
code = m_router->CalculateRoute(checkpoints, startDirection, adjustToPrevRoute,
|
||||
delegate, *route);
|
||||
m_router->SetGuides({});
|
||||
elapsedSec = timer.ElapsedSeconds(); // routing time
|
||||
LogCode(code, elapsedSec);
|
||||
LOG(LINFO, ("ETA:", route->GetTotalTimeSec(), "sec."));
|
||||
}
|
||||
catch (RootException const & e)
|
||||
{
|
||||
code = routing::RouterResultCode::InternalError;
|
||||
LOG(LERROR, ("Exception happened while calculating route:", e.Msg()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == routing::RouterResultCode::NoError)
|
||||
{
|
||||
LOG(LINFO, ("Decoded route:"));
|
||||
for (auto rsegment : route->GetRouteSegments())
|
||||
{
|
||||
routing::Segment segment = rsegment.GetSegment();
|
||||
if (segment.GetMwmId() == routing::kFakeNumMwmId)
|
||||
{
|
||||
LOG(LINFO, (" Fake segment:", segment));
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(LINFO, (" segment:", segment));
|
||||
|
||||
auto const countryFile = m_numMwmIds->GetFile(segment.GetMwmId());
|
||||
MwmSet::MwmId mwmId = m_dataSource.GetMwmIdByCountryFile(countryFile);
|
||||
|
||||
auto const fid = segment.GetFeatureId();
|
||||
auto const sid = segment.GetSegmentIdx();
|
||||
uint8_t direction = segment.IsForward() ?
|
||||
traffic::TrafficInfo::RoadSegmentId::kForwardDirection :
|
||||
traffic::TrafficInfo::RoadSegmentId::kReverseDirection;
|
||||
|
||||
decoded[mwmId][traffic::TrafficInfo::RoadSegmentId(fid, sid, direction)] = traffic::SpeedGroup::Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RoutingTraffDecoder::DecodeLocation(traffxml::TraffMessage & message, traffxml::MultiMwmColoring & decoded)
|
||||
{
|
||||
ASSERT(message.m_location, ("Message has no location"));
|
||||
decoded.clear();
|
||||
|
||||
int dirs = (message.m_location.value().m_directionality == Directionality::BothDirections) ? 2 : 1;
|
||||
for (int dir = 0; dir < dirs; dir++)
|
||||
DecodeLocationDirection(message, decoded, dir == 0 ? false : true /* backwards */);
|
||||
}
|
||||
} // namespace traffxml
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
#include "openlr/openlr_decoder.hpp"
|
||||
#include "openlr/openlr_model.hpp"
|
||||
|
||||
#include "routing/index_router.hpp"
|
||||
#include "routing/regions_decl.hpp"
|
||||
#include "routing/router.hpp"
|
||||
|
||||
#include "routing_common/num_mwm_id.hpp"
|
||||
|
||||
#include "storage/country_info_getter.hpp"
|
||||
|
||||
namespace traffxml
|
||||
{
|
||||
/**
|
||||
@@ -15,9 +23,10 @@ namespace traffxml
|
||||
class TraffDecoder
|
||||
{
|
||||
public:
|
||||
using CountryInfoGetterFn = std::function<storage::CountryInfoGetter const &()>;
|
||||
using CountryParentNameGetterFn = std::function<std::string(std::string const &)>;
|
||||
|
||||
TraffDecoder(DataSource & dataSource,
|
||||
TraffDecoder(DataSource & dataSource, CountryInfoGetterFn countryInfoGetter,
|
||||
const CountryParentNameGetterFn & countryParentNameGetter,
|
||||
std::map<std::string, traffxml::TraffMessage> & messageCache);
|
||||
|
||||
@@ -53,6 +62,7 @@ protected:
|
||||
void ApplyTrafficImpact(traffxml::TrafficImpact & impact, traffxml::MultiMwmColoring & decoded);
|
||||
|
||||
DataSource & m_dataSource;
|
||||
CountryInfoGetterFn m_countryInfoGetterFn;
|
||||
CountryParentNameGetterFn m_countryParentNameGetterFn;
|
||||
|
||||
/**
|
||||
@@ -71,7 +81,7 @@ private:
|
||||
class OpenLrV3TraffDecoder : public TraffDecoder
|
||||
{
|
||||
public:
|
||||
OpenLrV3TraffDecoder(DataSource & dataSource,
|
||||
OpenLrV3TraffDecoder(DataSource & dataSource, CountryInfoGetterFn countryInfoGetter,
|
||||
const CountryParentNameGetterFn & countryParentNameGetter,
|
||||
std::map<std::string, traffxml::TraffMessage> & messageCache);
|
||||
|
||||
@@ -151,6 +161,80 @@ private:
|
||||
openlr::OpenLRDecoder m_openLrDecoder;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A `TraffDecoder` implementation which internally uses the routing engine.
|
||||
*/
|
||||
class RoutingTraffDecoder : public TraffDecoder
|
||||
{
|
||||
public:
|
||||
class DecoderRouter : public routing::IndexRouter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a new `DecoderRouter` instance.
|
||||
*
|
||||
* @param countryParentNameGetterFn Function which converts a country name into the name of its parent country)
|
||||
* @param countryFileFn Function which converts a pointer to its country name
|
||||
* @param countryRectFn Function which returns the rect for a country
|
||||
* @param numMwmIds
|
||||
* @param numMwmTree
|
||||
* @param trafficCache Tre traffic cache (used only if `vehicleType` is `VehicleType::Car`)
|
||||
* @param dataSource The MWM data source
|
||||
*/
|
||||
DecoderRouter(CountryParentNameGetterFn const & countryParentNameGetterFn,
|
||||
routing::TCountryFileFn const & countryFileFn,
|
||||
routing::CountryRectFn const & countryRectFn,
|
||||
std::shared_ptr<routing::NumMwmIds> numMwmIds,
|
||||
std::unique_ptr<m4::Tree<routing::NumMwmId>> numMwmTree,
|
||||
DataSource & dataSource);
|
||||
protected:
|
||||
private:
|
||||
};
|
||||
|
||||
RoutingTraffDecoder(DataSource & dataSource, CountryInfoGetterFn countryInfoGetter,
|
||||
const CountryParentNameGetterFn & countryParentNameGetter,
|
||||
std::map<std::string, traffxml::TraffMessage> & messageCache);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Initializes the router.
|
||||
*
|
||||
* This is usually done in the constructor but fails if no maps are loaded (attempting to
|
||||
* construct a router without maps results in a crash, hence we check for maps and exit with an
|
||||
* error if we have none). It can be repeated any time.
|
||||
*
|
||||
* Attempting to initialize a router which has already been succesfully initialized is a no-op. It
|
||||
* will be reported as success.
|
||||
*
|
||||
* @return true if successful, false if not.
|
||||
*/
|
||||
bool InitRouter();
|
||||
|
||||
/**
|
||||
* @brief Decodes one direction of a TraFF location.
|
||||
*
|
||||
* @param message The message to decode.
|
||||
* @param decoded Receives the decoded segments. The speed group will be `Unknown`.
|
||||
* @param backwards If true, decode the backward direction, else the forward direction.
|
||||
*/
|
||||
void DecodeLocationDirection(traffxml::TraffMessage & message,
|
||||
traffxml::MultiMwmColoring & decoded, bool backwards);
|
||||
|
||||
/**
|
||||
* @brief Decodes a TraFF location.
|
||||
*
|
||||
* @param message The message to decode.
|
||||
* @param decoded Receives the decoded segments. The speed group will be `Unknown`.
|
||||
*/
|
||||
void DecodeLocation(traffxml::TraffMessage & message, traffxml::MultiMwmColoring & decoded);
|
||||
|
||||
private:
|
||||
static void LogCode(routing::RouterResultCode code, double const elapsedSec);
|
||||
|
||||
std::shared_ptr<routing::NumMwmIds> m_numMwmIds = std::make_shared<routing::NumMwmIds>();
|
||||
std::unique_ptr<routing::IRouter> m_router;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The default TraFF decoder implementation, recommended for production use.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user