mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 13:03:36 +00:00
[routing] OSM tag based time and turn penalties
Signed-off-by: Henry Sternberg <dev@bluelightmaps.com> Co-Authored-By: eisa01 <eisa01@gmail.com> Co-Authored-By: x7z4w <x7z4w@noreply.codeberg.org> Co-Authored-By: Yannik Bloscheck <git@yannikbloscheck.com>
This commit is contained in:
@@ -42,6 +42,7 @@
|
|||||||
#define METADATA_FILE_TAG "meta"
|
#define METADATA_FILE_TAG "meta"
|
||||||
#define ALTITUDES_FILE_TAG "altitudes"
|
#define ALTITUDES_FILE_TAG "altitudes"
|
||||||
#define ROAD_ACCESS_FILE_TAG "roadaccess"
|
#define ROAD_ACCESS_FILE_TAG "roadaccess"
|
||||||
|
#define ROAD_PENALTY_FILE_TAG "roadpenalty"
|
||||||
#define RESTRICTIONS_FILE_TAG "restrictions"
|
#define RESTRICTIONS_FILE_TAG "restrictions"
|
||||||
#define ROUTING_FILE_TAG "routing"
|
#define ROUTING_FILE_TAG "routing"
|
||||||
#define CROSS_MWM_FILE_TAG "cross_mwm"
|
#define CROSS_MWM_FILE_TAG "cross_mwm"
|
||||||
@@ -90,6 +91,7 @@
|
|||||||
#define GPS_TRACK_FILENAME "gps_track.dat"
|
#define GPS_TRACK_FILENAME "gps_track.dat"
|
||||||
#define RESTRICTIONS_FILENAME "restrictions.csv"
|
#define RESTRICTIONS_FILENAME "restrictions.csv"
|
||||||
#define ROAD_ACCESS_FILENAME "road_access.bin"
|
#define ROAD_ACCESS_FILENAME "road_access.bin"
|
||||||
|
#define ROAD_PENALTY_FILENAME "road_penalty.bin"
|
||||||
|
|
||||||
#define METALINES_FILENAME "metalines.bin"
|
#define METALINES_FILENAME "metalines.bin"
|
||||||
#define CAMERAS_TO_WAYS_FILENAME "cameras_to_ways.bin"
|
#define CAMERAS_TO_WAYS_FILENAME "cameras_to_ways.bin"
|
||||||
|
|||||||
@@ -186,6 +186,8 @@ set(SRC
|
|||||||
restriction_writer.hpp
|
restriction_writer.hpp
|
||||||
road_access_generator.cpp
|
road_access_generator.cpp
|
||||||
road_access_generator.hpp
|
road_access_generator.hpp
|
||||||
|
road_penalty_generator.cpp
|
||||||
|
road_penalty_generator.hpp
|
||||||
routing_city_boundaries_processor.cpp
|
routing_city_boundaries_processor.cpp
|
||||||
routing_city_boundaries_processor.hpp
|
routing_city_boundaries_processor.hpp
|
||||||
routing_helpers.cpp
|
routing_helpers.cpp
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "generator/raw_generator.hpp"
|
#include "generator/raw_generator.hpp"
|
||||||
#include "generator/restriction_generator.hpp"
|
#include "generator/restriction_generator.hpp"
|
||||||
#include "generator/road_access_generator.hpp"
|
#include "generator/road_access_generator.hpp"
|
||||||
|
#include "generator/road_penalty_generator.hpp"
|
||||||
#include "generator/routing_index_generator.hpp"
|
#include "generator/routing_index_generator.hpp"
|
||||||
#include "generator/routing_world_roads_generator.hpp"
|
#include "generator/routing_world_roads_generator.hpp"
|
||||||
#include "generator/search_index_builder.hpp"
|
#include "generator/search_index_builder.hpp"
|
||||||
@@ -466,6 +467,7 @@ MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
|
|||||||
|
|
||||||
string const restrictionsFilename = genInfo.GetIntermediateFileName(RESTRICTIONS_FILENAME);
|
string const restrictionsFilename = genInfo.GetIntermediateFileName(RESTRICTIONS_FILENAME);
|
||||||
string const roadAccessFilename = genInfo.GetIntermediateFileName(ROAD_ACCESS_FILENAME);
|
string const roadAccessFilename = genInfo.GetIntermediateFileName(ROAD_ACCESS_FILENAME);
|
||||||
|
string const roadPenaltyFilename = genInfo.GetIntermediateFileName(ROAD_PENALTY_FILENAME);
|
||||||
|
|
||||||
BuildRoutingIndex(dataFile, country, *countryParentGetter);
|
BuildRoutingIndex(dataFile, country, *countryParentGetter);
|
||||||
auto routingGraph = CreateIndexGraph(dataFile, country, *countryParentGetter);
|
auto routingGraph = CreateIndexGraph(dataFile, country, *countryParentGetter);
|
||||||
@@ -475,7 +477,8 @@ MAIN_WITH_ERROR_HANDLING([](int argc, char ** argv)
|
|||||||
|
|
||||||
/// @todo CHECK return result doesn't work now for some small countries like Somalie.
|
/// @todo CHECK return result doesn't work now for some small countries like Somalie.
|
||||||
if (!BuildRoadRestrictions(*routingGraph, dataFile, restrictionsFilename, osmToFeatureFilename) ||
|
if (!BuildRoadRestrictions(*routingGraph, dataFile, restrictionsFilename, osmToFeatureFilename) ||
|
||||||
!BuildRoadAccessInfo(dataFile, roadAccessFilename, *osm2feature))
|
!BuildRoadAccessInfo(dataFile, roadAccessFilename, *osm2feature) ||
|
||||||
|
!BuildRoadPenalty(dataFile, roadPenaltyFilename, *osm2feature))
|
||||||
{
|
{
|
||||||
LOG(LERROR, ("Routing build failed for", dataFile));
|
LOG(LERROR, ("Routing build failed for", dataFile));
|
||||||
}
|
}
|
||||||
|
|||||||
253
generator/road_penalty_generator.cpp
Normal file
253
generator/road_penalty_generator.cpp
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
#include "generator/road_penalty_generator.hpp"
|
||||||
|
|
||||||
|
#include "generator/feature_builder.hpp"
|
||||||
|
#include "generator/intermediate_data.hpp"
|
||||||
|
#include "generator/osm_element.hpp"
|
||||||
|
#include "generator/routing_helpers.hpp"
|
||||||
|
|
||||||
|
#include "routing/road_penalty_serialization.hpp"
|
||||||
|
#include "routing/routing_helpers.hpp"
|
||||||
|
#include "routing/vehicle_mask.hpp"
|
||||||
|
|
||||||
|
#include "coding/file_reader.hpp"
|
||||||
|
#include "coding/file_writer.hpp"
|
||||||
|
#include "coding/files_container.hpp"
|
||||||
|
#include "coding/internal/file_data.hpp"
|
||||||
|
#include "coding/varint.hpp"
|
||||||
|
#include "coding/write_to_sink.hpp"
|
||||||
|
|
||||||
|
#include "base/assert.hpp"
|
||||||
|
#include "base/logging.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace routing_builder
|
||||||
|
{
|
||||||
|
using namespace feature;
|
||||||
|
using namespace generator;
|
||||||
|
using namespace routing;
|
||||||
|
using std::string, std::vector;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// Unified penalty mapping for all OSM tags that create road penalties
|
||||||
|
std::map<OsmElement::Tag, RoadPenalty::Type> const kUnifiedPenaltyMapping = {
|
||||||
|
// Traffic calming measures
|
||||||
|
|
||||||
|
{OsmElement::Tag("traffic_calming", "rumble_strip"), RoadPenalty::Type::SmallCalming},
|
||||||
|
{OsmElement::Tag("traffic_calming", "island"), RoadPenalty::Type::SmallCalming},
|
||||||
|
|
||||||
|
{OsmElement::Tag("traffic_calming", "cushion"), RoadPenalty::Type::MediumCalming},
|
||||||
|
{OsmElement::Tag("traffic_calming", "chicane"), RoadPenalty::Type::MediumCalming},
|
||||||
|
{OsmElement::Tag("traffic_calming", "choker"), RoadPenalty::Type::MediumCalming},
|
||||||
|
{OsmElement::Tag("traffic_calming", "table"), RoadPenalty::Type::MediumCalming},
|
||||||
|
|
||||||
|
{OsmElement::Tag("traffic_calming", "bump"), RoadPenalty::Type::LargeCalming},
|
||||||
|
{OsmElement::Tag("traffic_calming", "hump"), RoadPenalty::Type::LargeCalming},
|
||||||
|
|
||||||
|
{OsmElement::Tag("crossing", "unmarked"), RoadPenalty::Type::LargeCalming},
|
||||||
|
|
||||||
|
// Barrier penalties
|
||||||
|
{OsmElement::Tag("barrier", "gate"), RoadPenalty::Type::Gate},
|
||||||
|
{OsmElement::Tag("barrier", "lift_gate"), RoadPenalty::Type::Gate},
|
||||||
|
{OsmElement::Tag("barrier", "swing_gate"), RoadPenalty::Type::Gate},
|
||||||
|
|
||||||
|
// Junction penalties
|
||||||
|
{OsmElement::Tag("highway", "stop"), RoadPenalty::Type::UncontrolledJunction},
|
||||||
|
{OsmElement::Tag("highway", "give_way"), RoadPenalty::Type::UncontrolledJunction},
|
||||||
|
{OsmElement::Tag("crossing", "uncontrolled"), RoadPenalty::Type::UncontrolledJunction},
|
||||||
|
{OsmElement::Tag("crossing", "marked"), RoadPenalty::Type::UncontrolledJunction},
|
||||||
|
// highway=crossing ommitted as often accompanied by traffic_signals
|
||||||
|
|
||||||
|
{OsmElement::Tag("highway", "traffic_signals"), RoadPenalty::Type::ControlledJunction},
|
||||||
|
{OsmElement::Tag("railway", "crossing"), RoadPenalty::Type::ControlledJunction},
|
||||||
|
{OsmElement::Tag("railway", "level_crossing"), RoadPenalty::Type::ControlledJunction},
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<RoadPenalty::Type> GetPenaltyByMapping(OsmElement const & elem)
|
||||||
|
{
|
||||||
|
for (auto const & tag : elem.m_tags)
|
||||||
|
{
|
||||||
|
auto const it = kUnifiedPenaltyMapping.find(tag);
|
||||||
|
if (it != kUnifiedPenaltyMapping.cend())
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadRoadPenalty(std::string const & penaltyPath, routing::OsmWay2FeaturePoint & way2Feature,
|
||||||
|
RoadPenaltyByVehicleType & penalties)
|
||||||
|
{
|
||||||
|
FileReader reader(penaltyPath);
|
||||||
|
ReaderSource src(reader);
|
||||||
|
|
||||||
|
// Read node penalties grouped by way
|
||||||
|
uint64_t nodeWayCount = ReadPrimitiveFromSource<uint64_t>(src);
|
||||||
|
while (nodeWayCount-- > 0)
|
||||||
|
{
|
||||||
|
uint64_t wayID = ReadPrimitiveFromSource<uint64_t>(src);
|
||||||
|
uint32_t nodeCount = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < nodeCount; ++i)
|
||||||
|
{
|
||||||
|
uint32_t nodeIdx = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
m2::PointU coord;
|
||||||
|
coord.x = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
coord.y = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
VehicleMask vehicleMask = ReadPrimitiveFromSource<VehicleMask>(src);
|
||||||
|
|
||||||
|
// Read penalty type and derive time based on vehicle type
|
||||||
|
RoadPenalty::Type type;
|
||||||
|
routing::Load(src, type);
|
||||||
|
|
||||||
|
// For each vehicle type, create penalty with vehicle-specific time
|
||||||
|
for (uint8_t vType = 0; vType < static_cast<uint8_t>(VehicleType::Count); ++vType)
|
||||||
|
{
|
||||||
|
if (vehicleMask & (1 << vType))
|
||||||
|
{
|
||||||
|
// Create penalty with time specific to this vehicle type
|
||||||
|
auto vehicleSpecificPenalty = RoadPenalty::Penalty(type, static_cast<VehicleType>(vType));
|
||||||
|
|
||||||
|
// Process this location only once
|
||||||
|
RoadPenalty::PointToPenalty pointToPenalty;
|
||||||
|
way2Feature.ForEachNodeIdx(wayID, nodeIdx, coord, [&](uint32_t featureID, uint32_t nodeIdx)
|
||||||
|
{ pointToPenalty[RoadPoint(featureID, nodeIdx)] = vehicleSpecificPenalty; });
|
||||||
|
|
||||||
|
if (!pointToPenalty.empty())
|
||||||
|
{
|
||||||
|
auto existingPenalties = penalties[vType].GetPointToPenalty();
|
||||||
|
existingPenalties.insert(pointToPenalty.begin(), pointToPenalty.end());
|
||||||
|
penalties[vType].SetPointPenalties(std::move(existingPenalties));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// RoadPenaltyCollector implementation
|
||||||
|
RoadPenaltyCollector::RoadPenaltyCollector(string const & filename, IDRInterfacePtr cache)
|
||||||
|
: generator::CollectorInterface(filename)
|
||||||
|
, m_cache(std::move(cache))
|
||||||
|
{
|
||||||
|
// Empty - initialization handled in member initializer list
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<CollectorInterface> RoadPenaltyCollector::Clone(IDRInterfacePtr const & cache) const
|
||||||
|
{
|
||||||
|
return std::make_shared<RoadPenaltyCollector>(GetFilename(), cache ? cache : m_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoadPenaltyCollector::CollectFeature(feature::FeatureBuilder const & fb, OsmElement const & elem)
|
||||||
|
{
|
||||||
|
// Track roads for barrier processing
|
||||||
|
if (elem.IsWay() && routing::IsCarRoad(fb.GetTypes()))
|
||||||
|
m_roads.AddWay(elem);
|
||||||
|
|
||||||
|
// Process only nodes for penalty types
|
||||||
|
if (elem.IsNode())
|
||||||
|
{
|
||||||
|
auto penaltyType = GetPenaltyByMapping(elem);
|
||||||
|
if (penaltyType)
|
||||||
|
m_nodesWithType.Add(elem.m_id, ms::LatLon(elem.m_lat, elem.m_lon), *penaltyType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoadPenaltyCollector::MergeInto(RoadPenaltyCollector & collector) const
|
||||||
|
{
|
||||||
|
m_nodesWithType.MergeInto(collector.m_nodesWithType);
|
||||||
|
m_roads.MergeInto(collector.m_roads);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RoadPenaltyCollector::Save()
|
||||||
|
{
|
||||||
|
auto const fileName = GetFilename();
|
||||||
|
LOG(LINFO, ("Saving road penalty values to", fileName));
|
||||||
|
FileWriter writer(fileName);
|
||||||
|
|
||||||
|
// All vehicles use the same penalty types
|
||||||
|
|
||||||
|
// Group node penalties by way
|
||||||
|
struct NodePenaltyEntry
|
||||||
|
{
|
||||||
|
uint32_t nodeIdx = 0;
|
||||||
|
m2::PointU coord;
|
||||||
|
RoadPenalty::Type type = RoadPenalty::Type::None;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<uint64_t, std::vector<NodePenaltyEntry>> penaltiesByWay;
|
||||||
|
|
||||||
|
m_roads.ForEachWayWithIndex([&](uint64_t wayID, std::vector<uint64_t> const & nodes, size_t idx)
|
||||||
|
{
|
||||||
|
std::vector<NodePenaltyEntry> wayNodePenalties;
|
||||||
|
|
||||||
|
for (uint32_t nodeIdx = 0; nodeIdx < nodes.size(); ++nodeIdx)
|
||||||
|
{
|
||||||
|
uint64_t const nodeID = nodes[nodeIdx];
|
||||||
|
auto const * barrierEntry = m_nodesWithType.Find(nodeID);
|
||||||
|
if (barrierEntry == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
NodePenaltyEntry entry;
|
||||||
|
entry.nodeIdx = nodeIdx;
|
||||||
|
entry.coord = barrierEntry->m_coord;
|
||||||
|
entry.type = barrierEntry->m_t;
|
||||||
|
wayNodePenalties.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wayNodePenalties.empty())
|
||||||
|
penaltiesByWay[wayID] = std::move(wayNodePenalties);
|
||||||
|
}, m_cache);
|
||||||
|
|
||||||
|
// Write node penalties grouped by way
|
||||||
|
uint64_t const wayCount = penaltiesByWay.size();
|
||||||
|
WriteToSink(writer, wayCount);
|
||||||
|
for (auto const & [wayID, entries] : penaltiesByWay)
|
||||||
|
{
|
||||||
|
WriteToSink(writer, wayID);
|
||||||
|
WriteToSink(writer, static_cast<uint32_t>(entries.size()));
|
||||||
|
|
||||||
|
for (auto const & entry : entries)
|
||||||
|
{
|
||||||
|
WriteToSink(writer, entry.nodeIdx);
|
||||||
|
WriteToSink(writer, entry.coord.x);
|
||||||
|
WriteToSink(writer, entry.coord.y);
|
||||||
|
WriteToSink(writer, kAllVehiclesMask);
|
||||||
|
|
||||||
|
// Store only penalty type (time derived from vehicle type when loading)
|
||||||
|
routing::Save(writer, entry.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BuildRoadPenalty(string const & dataFilePath, string const & roadPenaltyPath,
|
||||||
|
routing::OsmWay2FeaturePoint & way2feature)
|
||||||
|
{
|
||||||
|
LOG(LINFO, ("Generating road penalty info for", dataFilePath));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RoadPenaltyByVehicleType penalties;
|
||||||
|
ReadRoadPenalty(roadPenaltyPath, way2feature, penalties);
|
||||||
|
|
||||||
|
FilesContainerW cont(dataFilePath, FileWriter::OP_WRITE_EXISTING);
|
||||||
|
auto writer = cont.GetWriter(ROAD_PENALTY_FILE_TAG);
|
||||||
|
|
||||||
|
// Write number of vehicle types
|
||||||
|
uint32_t const vehicleTypeCount = penalties.size();
|
||||||
|
WriteToSink(*writer, vehicleTypeCount);
|
||||||
|
|
||||||
|
// Write penalty data for each vehicle type
|
||||||
|
for (size_t i = 0; i < penalties.size(); ++i)
|
||||||
|
RoadPenaltySerializer::Serialize(*writer, penalties[i]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (RootException const & ex)
|
||||||
|
{
|
||||||
|
LOG(LWARNING, ("No road penalty created:", ex.Msg()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace routing_builder
|
||||||
70
generator/road_penalty_generator.hpp
Normal file
70
generator/road_penalty_generator.hpp
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "generator/collector_interface.hpp"
|
||||||
|
#include "generator/feature_builder.hpp"
|
||||||
|
#include "generator/osm_element.hpp"
|
||||||
|
#include "generator/way_nodes_mapper.hpp"
|
||||||
|
|
||||||
|
#include "routing/road_penalty.hpp"
|
||||||
|
#include "routing/vehicle_mask.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace routing
|
||||||
|
{
|
||||||
|
class OsmWay2FeaturePoint;
|
||||||
|
|
||||||
|
template <class Sink>
|
||||||
|
void Save(Sink & sink, RoadPenalty::Type const & type)
|
||||||
|
{
|
||||||
|
WriteToSink(sink, static_cast<uint8_t>(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Source>
|
||||||
|
void Load(Source & src, RoadPenalty::Type & type)
|
||||||
|
{
|
||||||
|
uint8_t const res = ReadPrimitiveFromSource<uint8_t>(src);
|
||||||
|
CHECK_LESS(res, static_cast<uint8_t>(RoadPenalty::Type::Count), ());
|
||||||
|
type = static_cast<RoadPenalty::Type>(res);
|
||||||
|
}
|
||||||
|
} // namespace routing
|
||||||
|
|
||||||
|
namespace routing_builder
|
||||||
|
{
|
||||||
|
using RoadPenalty = routing::RoadPenalty;
|
||||||
|
using VehicleType = routing::VehicleType;
|
||||||
|
|
||||||
|
using RoadPenaltyByVehicleType = std::array<RoadPenalty, static_cast<size_t>(VehicleType::Count)>;
|
||||||
|
|
||||||
|
class RoadPenaltyCollector : public generator::CollectorInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RoadPenaltyCollector(std::string const & filename, IDRInterfacePtr cache);
|
||||||
|
|
||||||
|
std::shared_ptr<CollectorInterface> Clone(IDRInterfacePtr const & cache = {}) const override;
|
||||||
|
|
||||||
|
void CollectFeature(feature::FeatureBuilder const & fb, OsmElement const & elem) override;
|
||||||
|
|
||||||
|
IMPLEMENT_COLLECTOR_IFACE(RoadPenaltyCollector);
|
||||||
|
void MergeInto(RoadPenaltyCollector & collector) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void Save() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
IDRInterfacePtr m_cache;
|
||||||
|
|
||||||
|
// Store only penalty types during collection phase
|
||||||
|
generator::WayNodesMapper<RoadPenalty::Type> m_nodesWithType;
|
||||||
|
generator::WaysIDHolder m_roads;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool BuildRoadPenalty(std::string const & dataFilePath, std::string const & roadPenaltyPath,
|
||||||
|
routing::OsmWay2FeaturePoint & way2feature);
|
||||||
|
} // namespace routing_builder
|
||||||
@@ -88,9 +88,16 @@ public:
|
|||||||
{
|
{
|
||||||
auto ft = m_featureGetter.GetFeatureByIndex(featureID);
|
auto ft = m_featureGetter.GetFeatureByIndex(featureID);
|
||||||
CHECK(ft, (featureID));
|
CHECK(ft, (featureID));
|
||||||
CHECK(ft->GetGeomType() == feature::GeomType::Line, (featureID));
|
|
||||||
|
|
||||||
// Converison should work with the same logic as in WayNodesMapper::EncodePoint.
|
// Skip non-line features (e.g., barriers on area boundaries)
|
||||||
|
if (ft->GetGeomType() != feature::GeomType::Line)
|
||||||
|
{
|
||||||
|
// Use LDEBUG to reduce log spam for features processed multiple times per vehicle type
|
||||||
|
LOG(LDEBUG, ("Skipping non-line feature", featureID, "for node penalty mapping"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conversion should work with the same logic as in WayNodesMapper::EncodePoint.
|
||||||
auto const mercatorPt = PointUToPointD(pt, kPointCoordBits, fullRect);
|
auto const mercatorPt = PointUToPointD(pt, kPointCoordBits, fullRect);
|
||||||
double minSquareDist = 1.0E6;
|
double minSquareDist = 1.0E6;
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
// #include "generator/node_mixer.hpp"
|
// #include "generator/node_mixer.hpp"
|
||||||
#include "generator/restriction_writer.hpp"
|
#include "generator/restriction_writer.hpp"
|
||||||
#include "generator/road_access_generator.hpp"
|
#include "generator/road_access_generator.hpp"
|
||||||
|
#include "generator/road_penalty_generator.hpp"
|
||||||
|
|
||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
|
|
||||||
@@ -107,6 +108,8 @@ TranslatorCountry::TranslatorCountry(std::shared_ptr<FeatureProcessorInterface>
|
|||||||
info.GetIntermediateFileName(RESTRICTIONS_FILENAME), cache->GetCache()));
|
info.GetIntermediateFileName(RESTRICTIONS_FILENAME), cache->GetCache()));
|
||||||
collectors->Append(std::make_shared<routing_builder::RoadAccessCollector>(
|
collectors->Append(std::make_shared<routing_builder::RoadAccessCollector>(
|
||||||
info.GetIntermediateFileName(ROAD_ACCESS_FILENAME), cache->GetCache()));
|
info.GetIntermediateFileName(ROAD_ACCESS_FILENAME), cache->GetCache()));
|
||||||
|
collectors->Append(std::make_shared<routing_builder::RoadPenaltyCollector>(
|
||||||
|
info.GetIntermediateFileName(ROAD_PENALTY_FILENAME), cache->GetCache()));
|
||||||
collectors->Append(std::make_shared<routing_builder::CameraCollector>(
|
collectors->Append(std::make_shared<routing_builder::CameraCollector>(
|
||||||
info.GetIntermediateFileName(CAMERAS_TO_WAYS_FILENAME), cache->GetCache()));
|
info.GetIntermediateFileName(CAMERAS_TO_WAYS_FILENAME), cache->GetCache()));
|
||||||
collectors->Append(std::make_shared<MiniRoundaboutCollector>(info.GetIntermediateFileName(MINI_ROUNDABOUTS_FILENAME),
|
collectors->Append(std::make_shared<MiniRoundaboutCollector>(info.GetIntermediateFileName(MINI_ROUNDABOUTS_FILENAME),
|
||||||
|
|||||||
@@ -146,6 +146,13 @@ public:
|
|||||||
|
|
||||||
void MergeInto(WaysMapper & mapper) const { mapper.m_ways.insert(m_ways.begin(), m_ways.end()); }
|
void MergeInto(WaysMapper & mapper) const { mapper.m_ways.insert(m_ways.begin(), m_ways.end()); }
|
||||||
|
|
||||||
|
template <class Fn>
|
||||||
|
void ForEach(Fn && fn) const
|
||||||
|
{
|
||||||
|
for (auto const & [id, value] : m_ways)
|
||||||
|
fn(id, value);
|
||||||
|
}
|
||||||
|
|
||||||
template <class Sink>
|
template <class Sink>
|
||||||
void Serialize(Sink & sink) const
|
void Serialize(Sink & sink) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,4 +26,13 @@ double DistanceOnEarth(LatLon const & ll1, LatLon const & ll2)
|
|||||||
{
|
{
|
||||||
return DistanceOnEarth(ll1.m_lat, ll1.m_lon, ll2.m_lat, ll2.m_lon);
|
return DistanceOnEarth(ll1.m_lat, ll1.m_lon, ll2.m_lat, ll2.m_lon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m3::Point<double> ToVector(LatLon const & ll)
|
||||||
|
{
|
||||||
|
double const lat = math::DegToRad(ll.m_lat);
|
||||||
|
double const lon = math::DegToRad(ll.m_lon);
|
||||||
|
return {kEarthRadiusMeters * cos(lat) * cos(lon), kEarthRadiusMeters * cos(lat) * sin(lon),
|
||||||
|
kEarthRadiusMeters * sin(lat)};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ms
|
} // namespace ms
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "geometry/latlon.hpp"
|
#include "geometry/latlon.hpp"
|
||||||
|
#include "geometry/point3d.hpp"
|
||||||
|
|
||||||
// namespace ms - "math on sphere", similar to namespace m2.
|
// namespace ms - "math on sphere", similar to namespace m2.
|
||||||
namespace ms
|
namespace ms
|
||||||
@@ -14,4 +15,5 @@ double DistanceOnSphere(double lat1Deg, double lon1Deg, double lat2Deg, double l
|
|||||||
// lat1, lat2, lon1, lon2 - in degrees.
|
// lat1, lat2, lon1, lon2 - in degrees.
|
||||||
double DistanceOnEarth(double lat1Deg, double lon1Deg, double lat2Deg, double lon2Deg);
|
double DistanceOnEarth(double lat1Deg, double lon1Deg, double lat2Deg, double lon2Deg);
|
||||||
double DistanceOnEarth(LatLon const & ll1, LatLon const & ll2);
|
double DistanceOnEarth(LatLon const & ll1, LatLon const & ll2);
|
||||||
|
m3::Point<double> ToVector(LatLon const & ll);
|
||||||
} // namespace ms
|
} // namespace ms
|
||||||
|
|||||||
@@ -14,6 +14,12 @@ class Point
|
|||||||
public:
|
public:
|
||||||
Point() = default;
|
Point() = default;
|
||||||
constexpr Point(T x_, T y_, T z_) : x(x_), y(y_), z(z_) {}
|
constexpr Point(T x_, T y_, T z_) : x(x_), y(y_), z(z_) {}
|
||||||
|
Point<T> operator+(Point<T> const & obj) { return {x + obj.x, y + obj.y, z + obj.z}; }
|
||||||
|
Point<T> operator-(Point<T> const & obj) { return {x - obj.x, y - obj.y, z - obj.z}; }
|
||||||
|
|
||||||
|
Point<T> operator*(T const & obj) { return {x * obj, y * obj, z * obj}; }
|
||||||
|
|
||||||
|
Point<T> operator/(T const & obj) { return {x / obj, y / obj, z / obj}; }
|
||||||
|
|
||||||
T Length() const { return std::sqrt(x * x + y * y + z * z); }
|
T Length() const { return std::sqrt(x * x + y * y + z * z); }
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,9 @@ set(SRC
|
|||||||
road_access.hpp
|
road_access.hpp
|
||||||
road_access_serialization.cpp
|
road_access_serialization.cpp
|
||||||
road_access_serialization.hpp
|
road_access_serialization.hpp
|
||||||
|
road_penalty.cpp
|
||||||
|
road_penalty.hpp
|
||||||
|
road_penalty_serialization.hpp
|
||||||
road_graph.cpp
|
road_graph.cpp
|
||||||
road_graph.hpp
|
road_graph.hpp
|
||||||
road_index.cpp
|
road_index.cpp
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "routing/edge_estimator.hpp"
|
#include "routing/edge_estimator.hpp"
|
||||||
|
|
||||||
#include "routing/geometry.hpp"
|
#include "routing/geometry.hpp"
|
||||||
#include "routing/latlon_with_altitude.hpp"
|
#include "routing/latlon_with_altitude.hpp"
|
||||||
#include "routing/routing_helpers.hpp"
|
#include "routing/routing_helpers.hpp"
|
||||||
@@ -10,10 +9,11 @@
|
|||||||
#include "geometry/distance_on_sphere.hpp"
|
#include "geometry/distance_on_sphere.hpp"
|
||||||
#include "geometry/point_with_altitude.hpp"
|
#include "geometry/point_with_altitude.hpp"
|
||||||
|
|
||||||
#include "base/assert.hpp"
|
#include "coding/csv_reader.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include "base/assert.hpp"
|
||||||
#include <unordered_map>
|
#include "base/logging.hpp"
|
||||||
|
#include "platform/platform.hpp"
|
||||||
|
|
||||||
namespace routing
|
namespace routing
|
||||||
{
|
{
|
||||||
@@ -166,10 +166,12 @@ double GetCarClimbPenalty(EdgeEstimator::Purpose, double, geometry::Altitude)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EdgeEstimator -----------------------------------------------------------------------------------
|
// EdgeEstimator -----------------------------------------------------------------------------------
|
||||||
EdgeEstimator::EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH,
|
EdgeEstimator::EdgeEstimator(VehicleType vehicleType, double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH,
|
||||||
DataSource * /*dataSourcePtr*/, std::shared_ptr<NumMwmIds> /*numMwmIds*/)
|
DataSource * /*dataSourcePtr*/, std::shared_ptr<NumMwmIds> /*numMwmIds*/)
|
||||||
: m_maxWeightSpeedMpS(KmphToMps(maxWeightSpeedKMpH))
|
: m_vehicleType(vehicleType)
|
||||||
|
, m_maxWeightSpeedMpS(KmphToMps(maxWeightSpeedKMpH))
|
||||||
, m_offroadSpeedKMpH(offroadSpeedKMpH)
|
, m_offroadSpeedKMpH(offroadSpeedKMpH)
|
||||||
|
|
||||||
//, m_dataSourcePtr(dataSourcePtr)
|
//, m_dataSourcePtr(dataSourcePtr)
|
||||||
//, m_numMwmIds(numMwmIds)
|
//, m_numMwmIds(numMwmIds)
|
||||||
{
|
{
|
||||||
@@ -179,6 +181,204 @@ EdgeEstimator::EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroa
|
|||||||
|
|
||||||
if (m_offroadSpeedKMpH.m_eta != kNotUsed)
|
if (m_offroadSpeedKMpH.m_eta != kNotUsed)
|
||||||
CHECK_GREATER_OR_EQUAL(m_maxWeightSpeedMpS, KmphToMps(m_offroadSpeedKMpH.m_eta), ());
|
CHECK_GREATER_OR_EQUAL(m_maxWeightSpeedMpS, KmphToMps(m_offroadSpeedKMpH.m_eta), ());
|
||||||
|
|
||||||
|
LOG(LINFO, ("Loading turn penalties for vehicle type:", static_cast<int>(vehicleType)));
|
||||||
|
|
||||||
|
struct TurnPenaltyMatrix
|
||||||
|
{
|
||||||
|
int road;
|
||||||
|
VehicleType vehicleType;
|
||||||
|
double penalty;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TurnPenalty
|
||||||
|
{
|
||||||
|
HighwayType fromRoadType;
|
||||||
|
HighwayType toRoadType;
|
||||||
|
VehicleType vehicleType;
|
||||||
|
double penalty;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define N 144
|
||||||
|
|
||||||
|
static auto constexpr kTurnPenaltyMatrix = []
|
||||||
|
{
|
||||||
|
array<TurnPenalty, N> constexpr kTable = {{
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayPrimary, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTrunk, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayLivingStreet, HighwayType::HighwayUnclassified, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.11},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayPrimary, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayResidential, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwaySecondary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayService, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTertiary, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTrunk, VehicleType::Car, 0.04},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.04},
|
||||||
|
{HighwayType::HighwayPrimary, HighwayType::HighwayUnclassified, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayPrimary, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayResidential, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwaySecondary, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayService, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTertiary, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayPrimaryLink, HighwayType::HighwayUnclassified, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayPrimary, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayResidential, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayTrunk, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayResidential, HighwayType::HighwayUnclassified, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayPrimary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayResidential, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayService, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwaySecondary, HighwayType::HighwayUnclassified, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayPrimary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwaySecondary, VehicleType::Car, 0.05},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.05},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayService, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTertiary, VehicleType::Car, 0.05},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.05},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTrunk, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwaySecondaryLink, HighwayType::HighwayUnclassified, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayPrimary, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwaySecondary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayService, HighwayType::HighwayUnclassified, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayPrimary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayResidential, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwaySecondary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiary, HighwayType::HighwayUnclassified, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayPrimary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwaySecondary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTertiaryLink, HighwayType::HighwayUnclassified, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayPrimary, VehicleType::Car, 0.05},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.03},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayResidential, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayService, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTertiary, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTrunk, VehicleType::Car, 0.01},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.01},
|
||||||
|
{HighwayType::HighwayTrunk, HighwayType::HighwayUnclassified, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.11},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayPrimary, VehicleType::Car, 0.04},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.04},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayResidential, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwaySecondary, VehicleType::Car, 0.04},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.04},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayService, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTertiary, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.06},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTrunk, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.02},
|
||||||
|
{HighwayType::HighwayTrunkLink, HighwayType::HighwayUnclassified, VehicleType::Car, 0.1},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayLivingStreet, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayPrimary, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayPrimaryLink, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayResidential, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwaySecondary, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwaySecondaryLink, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayService, VehicleType::Car, 0.08},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTertiary, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTertiaryLink, VehicleType::Car, 0.07},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTrunk, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayTrunkLink, VehicleType::Car, 0.09},
|
||||||
|
{HighwayType::HighwayUnclassified, HighwayType::HighwayUnclassified, VehicleType::Car, 0.08},
|
||||||
|
}};
|
||||||
|
|
||||||
|
array<TurnPenaltyMatrix, N> result{};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N; ++i)
|
||||||
|
result[i] = {static_cast<int>(kTable[i].fromRoadType) * 65535 + static_cast<int>(kTable[i].toRoadType),
|
||||||
|
kTable[i].vehicleType, kTable[i].penalty};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}();
|
||||||
|
|
||||||
|
double totalPenalty = 0;
|
||||||
|
|
||||||
|
for (TurnPenaltyMatrix const & row : kTurnPenaltyMatrix)
|
||||||
|
{
|
||||||
|
if (row.vehicleType != vehicleType)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_turnPenaltyMap[row.road] += row.penalty;
|
||||||
|
totalPenalty += row.penalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_turnPenaltyMap.empty())
|
||||||
|
{
|
||||||
|
m_defaultPenalty = totalPenalty / m_turnPenaltyMap.size();
|
||||||
|
LOG(LINFO, ("Loaded", m_turnPenaltyMap.size(), "turn penalties with default:", m_defaultPenalty));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(LWARNING, ("No turn penalties loaded for vehicle type:", static_cast<int>(vehicleType)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double EdgeEstimator::CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const
|
double EdgeEstimator::CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const
|
||||||
@@ -265,11 +465,18 @@ class PedestrianEstimator final : public EdgeEstimator
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PedestrianEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
PedestrianEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
||||||
: EdgeEstimator(maxWeightSpeedKMpH, offroadSpeedKMpH)
|
: EdgeEstimator(VehicleType::Pedestrian, maxWeightSpeedKMpH, offroadSpeedKMpH)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// EdgeEstimator overrides:
|
// EdgeEstimator overrides:
|
||||||
double GetUTurnPenalty(Purpose /* purpose */) const override { return 0.0 /* seconds */; }
|
double GetUTurnPenalty(Purpose /* purpose */) const override { return 0.0 /* seconds */; }
|
||||||
|
|
||||||
|
double GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road, RoadGeometry const & to_road,
|
||||||
|
bool is_left_hand_traffic = false) const override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
double GetFerryLandingPenalty(Purpose purpose) const override
|
double GetFerryLandingPenalty(Purpose purpose) const override
|
||||||
{
|
{
|
||||||
switch (purpose)
|
switch (purpose)
|
||||||
@@ -293,11 +500,18 @@ class BicycleEstimator final : public EdgeEstimator
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BicycleEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
BicycleEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
||||||
: EdgeEstimator(maxWeightSpeedKMpH, offroadSpeedKMpH)
|
: EdgeEstimator(VehicleType::Bicycle, maxWeightSpeedKMpH, offroadSpeedKMpH)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// EdgeEstimator overrides:
|
// EdgeEstimator overrides:
|
||||||
double GetUTurnPenalty(Purpose /* purpose */) const override { return 20.0 /* seconds */; }
|
double GetUTurnPenalty(Purpose /* purpose */) const override { return 20.0 /* seconds */; }
|
||||||
|
|
||||||
|
double GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road, RoadGeometry const & to_road,
|
||||||
|
bool is_left_hand_traffic = false) const override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
double GetFerryLandingPenalty(Purpose purpose) const override
|
double GetFerryLandingPenalty(Purpose purpose) const override
|
||||||
{
|
{
|
||||||
switch (purpose)
|
switch (purpose)
|
||||||
@@ -349,20 +563,15 @@ class CarEstimator final : public EdgeEstimator
|
|||||||
public:
|
public:
|
||||||
CarEstimator(DataSource * dataSourcePtr, std::shared_ptr<NumMwmIds> numMwmIds, shared_ptr<TrafficStash> trafficStash,
|
CarEstimator(DataSource * dataSourcePtr, std::shared_ptr<NumMwmIds> numMwmIds, shared_ptr<TrafficStash> trafficStash,
|
||||||
double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH)
|
||||||
: EdgeEstimator(maxWeightSpeedKMpH, offroadSpeedKMpH, dataSourcePtr, numMwmIds)
|
: EdgeEstimator(VehicleType::Car, maxWeightSpeedKMpH, offroadSpeedKMpH, dataSourcePtr, numMwmIds)
|
||||||
, m_trafficStash(std::move(trafficStash))
|
, m_trafficStash(std::move(trafficStash))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// EdgeEstimator overrides:
|
// EdgeEstimator overrides:
|
||||||
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override;
|
double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const override;
|
||||||
double GetUTurnPenalty(Purpose /* purpose */) const override
|
double GetUTurnPenalty(Purpose /* purpose */) const override;
|
||||||
{
|
double GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road, RoadGeometry const & to_road,
|
||||||
// Adds 2 minutes penalty for U-turn. The value is quite arbitrary
|
bool is_left_hand_traffic = false) const override;
|
||||||
// and needs to be properly selected after a number of real-world
|
|
||||||
// experiments.
|
|
||||||
return 2 * 60; // seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
double GetFerryLandingPenalty(Purpose purpose) const override
|
double GetFerryLandingPenalty(Purpose purpose) const override
|
||||||
{
|
{
|
||||||
switch (purpose)
|
switch (purpose)
|
||||||
@@ -374,9 +583,47 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
shared_ptr<TrafficStash> m_trafficStash;
|
std::shared_ptr<TrafficStash> m_trafficStash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
double CarEstimator::GetUTurnPenalty(Purpose /* purpose */) 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
|
||||||
|
// experiments.
|
||||||
|
return 2 * 60; // seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
double CarEstimator::GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road,
|
||||||
|
RoadGeometry const & to_road, bool is_left_hand_traffic) const
|
||||||
|
{
|
||||||
|
auto penalty = m_defaultPenalty;
|
||||||
|
|
||||||
|
if (from_road.GetHighwayType().has_value() && to_road.GetHighwayType().has_value())
|
||||||
|
{
|
||||||
|
int const from_road_idx = static_cast<int>(from_road.GetHighwayType().value());
|
||||||
|
int const to_road_idx = static_cast<int>(to_road.GetHighwayType().value());
|
||||||
|
auto const pen = m_turnPenaltyMap.find(from_road_idx * 65535 + to_road_idx);
|
||||||
|
if (pen != m_turnPenaltyMap.end())
|
||||||
|
penalty = pen->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if turn crosses traffic based on driving side
|
||||||
|
// @TODO We should really account for oneway roads etc.
|
||||||
|
|
||||||
|
bool turn_crosses_traffic;
|
||||||
|
if (is_left_hand_traffic)
|
||||||
|
turn_crosses_traffic = angle < 0;
|
||||||
|
else
|
||||||
|
turn_crosses_traffic = angle > 0;
|
||||||
|
|
||||||
|
// Twice as long to turn across traffic than not to
|
||||||
|
auto const extra_penalty = turn_crosses_traffic ? 2.0 : 1.0;
|
||||||
|
auto const result = fabs(angle) * penalty * extra_penalty;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
double CarEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const
|
double CarEstimator::CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const
|
||||||
{
|
{
|
||||||
double result = road.GetDistance(segment.GetSegmentIdx()) / GetSpeedMpS(purpose, segment, road);
|
double result = road.GetDistance(segment.GetSegmentIdx()) / GetSpeedMpS(purpose, segment, road);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "geometry/point_with_altitude.hpp"
|
#include "geometry/point_with_altitude.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
class DataSource;
|
class DataSource;
|
||||||
|
|
||||||
@@ -27,8 +28,8 @@ public:
|
|||||||
ETA
|
ETA
|
||||||
};
|
};
|
||||||
|
|
||||||
EdgeEstimator(double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH, DataSource * dataSourcePtr = nullptr,
|
EdgeEstimator(VehicleType vehicleType, double maxWeightSpeedKMpH, SpeedKMpH const & offroadSpeedKMpH,
|
||||||
std::shared_ptr<NumMwmIds> numMwmIds = nullptr);
|
DataSource * dataSourcePtr = nullptr, std::shared_ptr<NumMwmIds> numMwmIds = nullptr);
|
||||||
virtual ~EdgeEstimator() = default;
|
virtual ~EdgeEstimator() = default;
|
||||||
|
|
||||||
double CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const;
|
double CalcHeuristic(ms::LatLon const & from, ms::LatLon const & to) const;
|
||||||
@@ -47,6 +48,8 @@ public:
|
|||||||
|
|
||||||
virtual double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const = 0;
|
virtual double CalcSegmentWeight(Segment const & segment, RoadGeometry const & road, Purpose purpose) const = 0;
|
||||||
virtual double GetUTurnPenalty(Purpose purpose) const = 0;
|
virtual double GetUTurnPenalty(Purpose purpose) const = 0;
|
||||||
|
virtual double GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road,
|
||||||
|
RoadGeometry const & to_road, bool is_left_hand_traffic = false) const = 0;
|
||||||
virtual double GetFerryLandingPenalty(Purpose purpose) const = 0;
|
virtual double GetFerryLandingPenalty(Purpose purpose) const = 0;
|
||||||
|
|
||||||
static std::shared_ptr<EdgeEstimator> Create(VehicleType vehicleType, double maxWeighSpeedKMpH,
|
static std::shared_ptr<EdgeEstimator> Create(VehicleType vehicleType, double maxWeighSpeedKMpH,
|
||||||
@@ -58,6 +61,11 @@ public:
|
|||||||
std::shared_ptr<TrafficStash> trafficStash, DataSource * dataSourcePtr,
|
std::shared_ptr<TrafficStash> trafficStash, DataSource * dataSourcePtr,
|
||||||
std::shared_ptr<NumMwmIds> numMwmIds);
|
std::shared_ptr<NumMwmIds> numMwmIds);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
VehicleType const m_vehicleType;
|
||||||
|
double m_defaultPenalty = 0.0;
|
||||||
|
std::unordered_map<int, double> m_turnPenaltyMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double const m_maxWeightSpeedMpS;
|
double const m_maxWeightSpeedMpS;
|
||||||
SpeedKMpH const m_offroadSpeedKMpH;
|
SpeedKMpH const m_offroadSpeedKMpH;
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
#include "base/exception.hpp"
|
#include "base/exception.hpp"
|
||||||
#include "base/timer.hpp"
|
#include "base/timer.hpp"
|
||||||
|
|
||||||
|
#include "geometry/distance_on_sphere.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
|
||||||
#include <iterator>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -34,13 +34,22 @@ bool IsBoarding(bool prevIsFerry, bool nextIsFerry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
IndexGraph::IndexGraph(shared_ptr<Geometry> geometry, shared_ptr<EdgeEstimator> estimator,
|
IndexGraph::IndexGraph(shared_ptr<Geometry> geometry, shared_ptr<EdgeEstimator> estimator,
|
||||||
RoutingOptions routingOptions)
|
RoutingOptions routingOptions, feature::RegionData const * regionData)
|
||||||
: m_geometry(std::move(geometry))
|
: m_geometry(std::move(geometry))
|
||||||
, m_estimator(std::move(estimator))
|
, m_estimator(std::move(estimator))
|
||||||
, m_avoidRoutingOptions(routingOptions)
|
, m_avoidRoutingOptions(routingOptions)
|
||||||
{
|
{
|
||||||
CHECK(m_geometry, ());
|
CHECK(m_geometry, ());
|
||||||
CHECK(m_estimator, ());
|
CHECK(m_estimator, ());
|
||||||
|
if (regionData)
|
||||||
|
{
|
||||||
|
auto const driving_side = regionData->Get(feature::RegionData::RD_DRIVING);
|
||||||
|
m_isLeftHandTraffic = (driving_side == "l");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_isLeftHandTraffic = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IndexGraph::IsJoint(RoadPoint const & roadPoint) const
|
bool IndexGraph::IsJoint(RoadPoint const & roadPoint) const
|
||||||
@@ -229,6 +238,11 @@ void IndexGraph::SetRoadAccess(RoadAccess && roadAccess)
|
|||||||
m_roadAccess.SetCurrentTimeGetter(m_currentTimeGetter);
|
m_roadAccess.SetCurrentTimeGetter(m_currentTimeGetter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IndexGraph::SetRoadPenalty(RoadPenalty && roadPenalty)
|
||||||
|
{
|
||||||
|
m_roadPenalty = std::move(roadPenalty);
|
||||||
|
}
|
||||||
|
|
||||||
void IndexGraph::GetNeighboringEdges(astar::VertexData<Segment, RouteWeight> const & fromVertexData,
|
void IndexGraph::GetNeighboringEdges(astar::VertexData<Segment, RouteWeight> const & fromVertexData,
|
||||||
RoadPoint const & rp, bool isOutgoing, bool useRoutingOptions,
|
RoadPoint const & rp, bool isOutgoing, bool useRoutingOptions,
|
||||||
SegmentEdgeListT & edges, Parents<Segment> const & parents,
|
SegmentEdgeListT & edges, Parents<Segment> const & parents,
|
||||||
@@ -340,7 +354,7 @@ void IndexGraph::ReconstructJointSegment(astar::VertexData<JointSegment, RouteWe
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
// This is optimization: we calculate accesses of road points before calculating weight of
|
// This is optimization: we calculate accesses of road points before calculating weight of
|
||||||
// segments between these road points. Because of that we make less calculations when some
|
// segments between these road points. Because of that we make fewer calculations when some
|
||||||
// points have RoadAccess::Type::No.
|
// points have RoadAccess::Type::No.
|
||||||
// And using |weightTimeToParent| is not fair in fact, because we should calculate weight
|
// And using |weightTimeToParent| is not fair in fact, because we should calculate weight
|
||||||
// until this |rp|. But we assume that segments have small length and inaccuracy will not
|
// until this |rp|. But we assume that segments have small length and inaccuracy will not
|
||||||
@@ -456,6 +470,12 @@ RouteWeight IndexGraph::GetPenalties(EdgeEstimator::Purpose purpose, Segment con
|
|||||||
auto const rp = u.GetRoadPoint(true /* front */);
|
auto const rp = u.GetRoadPoint(true /* front */);
|
||||||
auto const [rpAccessType, rpConfidence] =
|
auto const [rpAccessType, rpConfidence] =
|
||||||
prevWeight ? m_roadAccess.GetAccess(rp, *prevWeight) : m_roadAccess.GetAccessWithoutConditional(rp);
|
prevWeight ? m_roadAccess.GetAccess(rp, *prevWeight) : m_roadAccess.GetAccessWithoutConditional(rp);
|
||||||
|
// Get penalty from new penalty system if MWM supports it
|
||||||
|
auto penalty = m_roadPenalty.GetPenalty(rp);
|
||||||
|
uint16_t penaltyTime = 0;
|
||||||
|
if (penalty)
|
||||||
|
penaltyTime = penalty->m_timeSeconds;
|
||||||
|
|
||||||
switch (rpConfidence)
|
switch (rpConfidence)
|
||||||
{
|
{
|
||||||
case RoadAccess::Confidence::Sure:
|
case RoadAccess::Confidence::Sure:
|
||||||
@@ -478,7 +498,7 @@ RouteWeight IndexGraph::GetPenalties(EdgeEstimator::Purpose purpose, Segment con
|
|||||||
if (IsBoarding(fromPenaltyData.m_isFerry, toPenaltyData.m_isFerry))
|
if (IsBoarding(fromPenaltyData.m_isFerry, toPenaltyData.m_isFerry))
|
||||||
weightPenalty += m_estimator->GetFerryLandingPenalty(purpose);
|
weightPenalty += m_estimator->GetFerryLandingPenalty(purpose);
|
||||||
|
|
||||||
return {weightPenalty /* weight */, passThroughPenalty, accessPenalty, accessConditionalPenalties,
|
return {penaltyTime + weightPenalty /* weight */, passThroughPenalty, accessPenalty, accessConditionalPenalties,
|
||||||
0.0 /* transitTime */};
|
0.0 /* transitTime */};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,12 +536,30 @@ RouteWeight IndexGraph::CalculateEdgeWeight(EdgeEstimator::Purpose purpose, bool
|
|||||||
Segment const & to,
|
Segment const & to,
|
||||||
std::optional<RouteWeight const> const & prevWeight) const
|
std::optional<RouteWeight const> const & prevWeight) const
|
||||||
{
|
{
|
||||||
auto const & segment = isOutgoing ? to : from;
|
auto const & to_segment = isOutgoing ? to : from;
|
||||||
auto const & road = GetRoadGeometry(segment.GetFeatureId());
|
auto const & from_segment = isOutgoing ? from : to;
|
||||||
|
auto const & to_road = GetRoadGeometry(to_segment.GetFeatureId());
|
||||||
auto const weight = RouteWeight(m_estimator->CalcSegmentWeight(segment, road, purpose));
|
auto const weight = RouteWeight(m_estimator->CalcSegmentWeight(to_segment, to_road, purpose));
|
||||||
auto const penalties = GetPenalties(purpose, isOutgoing ? from : to, isOutgoing ? to : from, prevWeight);
|
auto const penalties = GetPenalties(purpose, isOutgoing ? from : to, isOutgoing ? to : from, prevWeight);
|
||||||
|
auto const turn_penalty = getTurnPenalty(purpose, from_segment, to_segment);
|
||||||
|
return weight + penalties + turn_penalty;
|
||||||
|
}
|
||||||
|
|
||||||
return weight + penalties;
|
RouteWeight IndexGraph::getTurnPenalty(EdgeEstimator::Purpose purpose, Segment const & from, Segment const & to) const
|
||||||
|
{
|
||||||
|
if (from.GetFeatureId() == to.GetFeatureId())
|
||||||
|
return {0, 0, 0, 0, 0};
|
||||||
|
auto const & to_road = GetRoadGeometry(to.GetFeatureId());
|
||||||
|
auto const & from_road = GetRoadGeometry(from.GetFeatureId());
|
||||||
|
auto v1 = ms::ToVector(GetPoint(from, true)) - ms::ToVector(GetPoint(from, false));
|
||||||
|
auto v2 = ms::ToVector(GetPoint(to, true)) - ms::ToVector(GetPoint(to, false));
|
||||||
|
auto const dotLen = v1.Length() * v2.Length();
|
||||||
|
if (dotLen == 0)
|
||||||
|
return {0, 0, 0, 0, 0};
|
||||||
|
auto normal = ms::ToVector(GetPoint(from, true)) + ms::ToVector(GetPoint(to, false));
|
||||||
|
normal = normal / normal.Length();
|
||||||
|
auto const signed_angle =
|
||||||
|
math::RadToDeg(atan2(m3::DotProduct(m3::CrossProduct(v1, v2), normal), m3::DotProduct(v1, v2)));
|
||||||
|
return {m_estimator->GetTurnPenalty(purpose, signed_angle, from_road, to_road, m_isLeftHandTraffic), 0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
} // namespace routing
|
} // namespace routing
|
||||||
|
|||||||
@@ -11,10 +11,13 @@
|
|||||||
#include "routing/restrictions_serialization.hpp"
|
#include "routing/restrictions_serialization.hpp"
|
||||||
#include "routing/road_access.hpp"
|
#include "routing/road_access.hpp"
|
||||||
#include "routing/road_index.hpp"
|
#include "routing/road_index.hpp"
|
||||||
|
#include "routing/road_penalty.hpp"
|
||||||
#include "routing/road_point.hpp"
|
#include "routing/road_point.hpp"
|
||||||
#include "routing/routing_options.hpp"
|
#include "routing/routing_options.hpp"
|
||||||
#include "routing/segment.hpp"
|
#include "routing/segment.hpp"
|
||||||
|
|
||||||
|
#include "indexer/feature_meta.hpp"
|
||||||
|
|
||||||
#include "geometry/point2d.hpp"
|
#include "geometry/point2d.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -49,7 +52,7 @@ public:
|
|||||||
|
|
||||||
IndexGraph() = default;
|
IndexGraph() = default;
|
||||||
IndexGraph(std::shared_ptr<Geometry> geometry, std::shared_ptr<EdgeEstimator> estimator,
|
IndexGraph(std::shared_ptr<Geometry> geometry, std::shared_ptr<EdgeEstimator> estimator,
|
||||||
RoutingOptions routingOptions = RoutingOptions());
|
RoutingOptions routingOptions = RoutingOptions(), feature::RegionData const * regionData = nullptr);
|
||||||
|
|
||||||
// Put outgoing (or ingoing) egdes for segment to the 'edges' vector.
|
// Put outgoing (or ingoing) egdes for segment to the 'edges' vector.
|
||||||
void GetEdgeList(astar::VertexData<Segment, RouteWeight> const & vertexData, bool isOutgoing, bool useRoutingOptions,
|
void GetEdgeList(astar::VertexData<Segment, RouteWeight> const & vertexData, bool isOutgoing, bool useRoutingOptions,
|
||||||
@@ -89,6 +92,7 @@ public:
|
|||||||
void SetRestrictions(RestrictionVec && restrictions);
|
void SetRestrictions(RestrictionVec && restrictions);
|
||||||
void SetUTurnRestrictions(std::vector<RestrictionUTurn> && noUTurnRestrictions);
|
void SetUTurnRestrictions(std::vector<RestrictionUTurn> && noUTurnRestrictions);
|
||||||
void SetRoadAccess(RoadAccess && roadAccess);
|
void SetRoadAccess(RoadAccess && roadAccess);
|
||||||
|
void SetRoadPenalty(RoadPenalty && roadPenalty);
|
||||||
|
|
||||||
void PushFromSerializer(Joint::Id jointId, RoadPoint const & rp) { m_roadIndex.PushFromSerializer(jointId, rp); }
|
void PushFromSerializer(Joint::Id jointId, RoadPoint const & rp) { m_roadIndex.PushFromSerializer(jointId, rp); }
|
||||||
|
|
||||||
@@ -186,10 +190,8 @@ private:
|
|||||||
std::shared_ptr<EdgeEstimator> m_estimator;
|
std::shared_ptr<EdgeEstimator> m_estimator;
|
||||||
RoadIndex m_roadIndex;
|
RoadIndex m_roadIndex;
|
||||||
JointIndex m_jointIndex;
|
JointIndex m_jointIndex;
|
||||||
|
|
||||||
Restrictions m_restrictionsForward;
|
Restrictions m_restrictionsForward;
|
||||||
Restrictions m_restrictionsBackward;
|
Restrictions m_restrictionsBackward;
|
||||||
|
|
||||||
// u_turn can be in both sides of feature.
|
// u_turn can be in both sides of feature.
|
||||||
struct UTurnEnding
|
struct UTurnEnding
|
||||||
{
|
{
|
||||||
@@ -202,11 +204,13 @@ private:
|
|||||||
// If m_noUTurnRestrictions.count(featureId) == 0, that means, that there are no any
|
// If m_noUTurnRestrictions.count(featureId) == 0, that means, that there are no any
|
||||||
// no_u_turn restriction at the feature with id = featureId.
|
// no_u_turn restriction at the feature with id = featureId.
|
||||||
std::unordered_map<uint32_t, UTurnEnding> m_noUTurnRestrictions;
|
std::unordered_map<uint32_t, UTurnEnding> m_noUTurnRestrictions;
|
||||||
|
|
||||||
RoadAccess m_roadAccess;
|
RoadAccess m_roadAccess;
|
||||||
|
RoadPenalty m_roadPenalty;
|
||||||
RoutingOptions m_avoidRoutingOptions;
|
RoutingOptions m_avoidRoutingOptions;
|
||||||
|
bool m_isLeftHandTraffic;
|
||||||
|
|
||||||
std::function<time_t()> m_currentTimeGetter = []() { return GetCurrentTimestamp(); };
|
std::function<time_t()> m_currentTimeGetter = []() { return GetCurrentTimestamp(); };
|
||||||
|
RouteWeight getTurnPenalty(EdgeEstimator::Purpose purpose, Segment const & from, Segment const & to) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename AccessPositionType>
|
template <typename AccessPositionType>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "routing/restriction_loader.hpp"
|
#include "routing/restriction_loader.hpp"
|
||||||
#include "routing/road_access.hpp"
|
#include "routing/road_access.hpp"
|
||||||
#include "routing/road_access_serialization.hpp"
|
#include "routing/road_access_serialization.hpp"
|
||||||
|
#include "routing/road_penalty.hpp"
|
||||||
|
#include "routing/road_penalty_serialization.hpp"
|
||||||
#include "routing/route.hpp"
|
#include "routing/route.hpp"
|
||||||
#include "routing/speed_camera_ser_des.hpp"
|
#include "routing/speed_camera_ser_des.hpp"
|
||||||
|
|
||||||
@@ -138,7 +140,7 @@ IndexGraphLoaderImpl::GraphPtrT IndexGraphLoaderImpl::CreateIndexGraph(NumMwmId
|
|||||||
geometry = make_shared<Geometry>(GeometryLoader::Create(handle, std::move(vehicleModel), m_loadAltitudes));
|
geometry = make_shared<Geometry>(GeometryLoader::Create(handle, std::move(vehicleModel), m_loadAltitudes));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto graph = make_unique<IndexGraph>(geometry, m_estimator, m_avoidRoutingOptions);
|
auto graph = make_unique<IndexGraph>(geometry, m_estimator, m_avoidRoutingOptions, &value->GetRegionData());
|
||||||
graph->SetCurrentTimeGetter(m_currentTimeGetter);
|
graph->SetCurrentTimeGetter(m_currentTimeGetter);
|
||||||
DeserializeIndexGraph(*value, m_vehicleType, *graph);
|
DeserializeIndexGraph(*value, m_vehicleType, *graph);
|
||||||
|
|
||||||
@@ -209,6 +211,40 @@ bool ReadRoadAccessFromMwm(MwmValue const & mwmValue, VehicleType vehicleType, R
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ReadRoadPenaltyFromMwm(MwmValue const & mwmValue, VehicleType vehicleType, RoadPenalty & roadPenalty)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto const reader = mwmValue.m_cont.GetReader(ROAD_PENALTY_FILE_TAG);
|
||||||
|
ReaderSource src(reader);
|
||||||
|
|
||||||
|
// Read number of vehicle types
|
||||||
|
uint32_t numVehicleTypes = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
CHECK_EQUAL(numVehicleTypes, static_cast<uint32_t>(VehicleType::Count), ());
|
||||||
|
|
||||||
|
// Skip to the correct vehicle type
|
||||||
|
for (uint32_t i = 0; i < static_cast<uint32_t>(vehicleType); ++i)
|
||||||
|
{
|
||||||
|
RoadPenalty dummy;
|
||||||
|
RoadPenaltySerializer::Deserialize(src, dummy, static_cast<VehicleType>(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the penalty data for this vehicle type
|
||||||
|
RoadPenaltySerializer::Deserialize(src, roadPenalty, vehicleType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Reader::OpenException const &)
|
||||||
|
{
|
||||||
|
// This is expected for older mwm files - not an error
|
||||||
|
LOG(LDEBUG, (ROAD_PENALTY_FILE_TAG, "section not found - using legacy penalty system"));
|
||||||
|
}
|
||||||
|
catch (Reader::Exception const & e)
|
||||||
|
{
|
||||||
|
LOG(LERROR, ("Error while reading", ROAD_PENALTY_FILE_TAG, "section.", e.Msg()));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
unique_ptr<IndexGraphLoader> IndexGraphLoader::Create(VehicleType vehicleType, bool loadAltitudes,
|
unique_ptr<IndexGraphLoader> IndexGraphLoader::Create(VehicleType vehicleType, bool loadAltitudes,
|
||||||
shared_ptr<VehicleModelFactoryInterface> vehicleModelFactory,
|
shared_ptr<VehicleModelFactoryInterface> vehicleModelFactory,
|
||||||
@@ -244,6 +280,10 @@ void DeserializeIndexGraph(MwmValue const & mwmValue, VehicleType vehicleType, I
|
|||||||
RoadAccess roadAccess;
|
RoadAccess roadAccess;
|
||||||
if (ReadRoadAccessFromMwm(mwmValue, vehicleType, roadAccess))
|
if (ReadRoadAccessFromMwm(mwmValue, vehicleType, roadAccess))
|
||||||
graph.SetRoadAccess(std::move(roadAccess));
|
graph.SetRoadAccess(std::move(roadAccess));
|
||||||
|
|
||||||
|
RoadPenalty roadPenalty;
|
||||||
|
if (ReadRoadPenaltyFromMwm(mwmValue, vehicleType, roadPenalty))
|
||||||
|
graph.SetRoadPenalty(std::move(roadPenalty));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DeserializeIndexGraphNumRoads(MwmValue const & mwmValue, VehicleType vehicleType)
|
uint32_t DeserializeIndexGraphNumRoads(MwmValue const & mwmValue, VehicleType vehicleType)
|
||||||
|
|||||||
82
libs/routing/road_penalty.cpp
Normal file
82
libs/routing/road_penalty.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#include "routing/road_penalty.hpp"
|
||||||
|
|
||||||
|
#include "base/assert.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace routing
|
||||||
|
{
|
||||||
|
namespace penalty_impl
|
||||||
|
{
|
||||||
|
// Array of strings must be in the same order as RoadPenalty::Type enum
|
||||||
|
std::string const kNames[] = {"None", "SmallCalming", "MediumCalming", "LargeCalming",
|
||||||
|
"Gate", "UncontrolledJunction", "ControlledJunction", "Count"};
|
||||||
|
} // namespace penalty_impl
|
||||||
|
|
||||||
|
std::optional<RoadPenalty::Penalty> RoadPenalty::GetPenalty(RoadPoint const & point) const
|
||||||
|
{
|
||||||
|
auto const it = m_pointToPenalty.find(point);
|
||||||
|
if (it != m_pointToPenalty.end())
|
||||||
|
return it->second;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RoadPenalty::operator==(RoadPenalty const & rhs) const
|
||||||
|
{
|
||||||
|
return m_pointToPenalty == rhs.m_pointToPenalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToString(RoadPenalty::Type type)
|
||||||
|
{
|
||||||
|
if (type <= RoadPenalty::Type::Count)
|
||||||
|
return penalty_impl::kNames[static_cast<size_t>(type)];
|
||||||
|
ASSERT(false, ("Bad RoadPenalty::Type", static_cast<size_t>(type)));
|
||||||
|
return "Bad RoadPenalty::Type";
|
||||||
|
}
|
||||||
|
|
||||||
|
void FromString(std::string_view s, RoadPenalty::Type & result)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i <= static_cast<size_t>(RoadPenalty::Type::Count); ++i)
|
||||||
|
{
|
||||||
|
if (s == penalty_impl::kNames[i])
|
||||||
|
{
|
||||||
|
result = static_cast<RoadPenalty::Type>(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT(false, ("Could not read RoadPenalty::Type from string", s));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DebugPrint(RoadPenalty::Type type)
|
||||||
|
{
|
||||||
|
return ToString(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DebugPrint(RoadPenalty::Penalty const & penalty)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Penalty(" << DebugPrint(penalty.m_type) << ", " << penalty.m_timeSeconds << "s)";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DebugPrint(RoadPenalty const & roadPenalty)
|
||||||
|
{
|
||||||
|
size_t constexpr kMaxKV = 10;
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "RoadPenalty { PointToPenalty: [";
|
||||||
|
size_t i = 0;
|
||||||
|
for (auto const & kv : roadPenalty.GetPointToPenalty())
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
oss << ", ";
|
||||||
|
oss << "(" << DebugPrint(kv.first) << ", " << DebugPrint(kv.second) << ")";
|
||||||
|
++i;
|
||||||
|
if (i == kMaxKV)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (roadPenalty.GetPointToPenalty().size() > kMaxKV)
|
||||||
|
oss << ", ...";
|
||||||
|
oss << "] }";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
} // namespace routing
|
||||||
127
libs/routing/road_penalty.hpp
Normal file
127
libs/routing/road_penalty.hpp
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "routing/road_point.hpp"
|
||||||
|
#include "routing/vehicle_mask.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "3party/skarupke/flat_hash_map.hpp"
|
||||||
|
|
||||||
|
namespace routing
|
||||||
|
{
|
||||||
|
// This class provides information about road penalties (time delays)
|
||||||
|
// that are separate from access restrictions. Examples include:
|
||||||
|
// - Speed bumps and traffic calming measures
|
||||||
|
// - Traffic signals
|
||||||
|
// - Gates that take time to open
|
||||||
|
// One instance of RoadPenalty holds information about one mwm.
|
||||||
|
//
|
||||||
|
// FILE FORMATS:
|
||||||
|
//
|
||||||
|
// 1. Intermediate file (from RoadPenaltyCollector::Save()):
|
||||||
|
// [uint64_t] Number of ways with penalties
|
||||||
|
// For each way:
|
||||||
|
// [uint64_t] Way ID
|
||||||
|
// [uint32_t] Number of nodes with penalties
|
||||||
|
// For each node:
|
||||||
|
// [uint32_t] Node index within way
|
||||||
|
// [uint32_t] Coordinate X
|
||||||
|
// [uint32_t] Coordinate Y
|
||||||
|
// [VehicleMask] Vehicle mask (uint32_t)
|
||||||
|
// [uint8_t] Penalty type
|
||||||
|
//
|
||||||
|
// 2. Final MWM file:
|
||||||
|
// [uint32_t] Number of vehicle types (4)
|
||||||
|
// For each vehicle type:
|
||||||
|
// [uint32_t] Number of point penalties
|
||||||
|
// For each penalty:
|
||||||
|
// [uint32_t] Feature ID
|
||||||
|
// [uint32_t] Point ID
|
||||||
|
// [uint8_t] Penalty type (time derived from type + vehicle)
|
||||||
|
class RoadPenalty final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Types of penalties that can be applied to roads/nodes
|
||||||
|
enum class Type : uint8_t
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
// Traffic calming devices with different severities
|
||||||
|
SmallCalming, // Traffic islands
|
||||||
|
MediumCalming, // Cushions, chicanes, tables, choker
|
||||||
|
LargeCalming, // Humps, bumps
|
||||||
|
|
||||||
|
// Gates and barriers
|
||||||
|
Gate, // Emergency gates, barrier gates
|
||||||
|
|
||||||
|
// Traffic control
|
||||||
|
UncontrolledJunction,
|
||||||
|
ControlledJunction,
|
||||||
|
|
||||||
|
// The number of different penalty types
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Penalty
|
||||||
|
{
|
||||||
|
Type m_type = Type::None;
|
||||||
|
uint16_t m_timeSeconds = 0; // Time penalty in seconds (0-65535)
|
||||||
|
|
||||||
|
Penalty() = default;
|
||||||
|
|
||||||
|
// Constructor that derives time from type and vehicle
|
||||||
|
Penalty(Type type, VehicleType vehicleType) : m_type(type), m_timeSeconds(GetTimePenalty(type, vehicleType)) {}
|
||||||
|
|
||||||
|
bool operator==(Penalty const & rhs) const { return m_type == rhs.m_type && m_timeSeconds == rhs.m_timeSeconds; }
|
||||||
|
|
||||||
|
bool operator!=(Penalty const & rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
// Get default time penalty for a given type and vehicle
|
||||||
|
static uint16_t GetTimePenalty(Type type, VehicleType vehicleType)
|
||||||
|
{
|
||||||
|
// Penalty times lookup table [Type][VehicleType]
|
||||||
|
// Rows: penalty types (None, SmallCalming, MediumCalming, LargeCalming, Gate, Uncontrolled, Controlled)
|
||||||
|
// Columns: vehicle types (Pedestrian, Bicycle, Car, Transit)
|
||||||
|
static constexpr uint16_t kPenaltyTimes[7][4] = {
|
||||||
|
// Ped, Bic, Car, Tran
|
||||||
|
{0, 0, 0, 0}, // None
|
||||||
|
{0, 0, 3, 0}, // SmallCalming
|
||||||
|
{0, 0, 5, 0}, // MediumCalming
|
||||||
|
{0, 0, 7, 0}, // LargeCalming
|
||||||
|
{10, 10, 30, 0}, // Gate
|
||||||
|
{0, 10, 5, 0}, // Uncontrolled Junction
|
||||||
|
{0, 15, 10, 0}, // Controlled Junction
|
||||||
|
};
|
||||||
|
|
||||||
|
if (type >= Type::Count || vehicleType >= VehicleType::Count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return kPenaltyTimes[static_cast<size_t>(type)][static_cast<size_t>(vehicleType)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using PointToPenalty = ska::flat_hash_map<RoadPoint, Penalty, RoadPoint::Hash>;
|
||||||
|
|
||||||
|
RoadPenalty() = default;
|
||||||
|
|
||||||
|
PointToPenalty const & GetPointToPenalty() const { return m_pointToPenalty; }
|
||||||
|
|
||||||
|
std::optional<Penalty> GetPenalty(RoadPoint const & point) const;
|
||||||
|
|
||||||
|
void SetPointPenalties(PointToPenalty && penalties) { m_pointToPenalty = std::move(penalties); }
|
||||||
|
|
||||||
|
bool operator==(RoadPenalty const & rhs) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PointToPenalty m_pointToPenalty;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string ToString(RoadPenalty::Type type);
|
||||||
|
void FromString(std::string_view s, RoadPenalty::Type & result);
|
||||||
|
|
||||||
|
std::string DebugPrint(RoadPenalty::Type type);
|
||||||
|
std::string DebugPrint(RoadPenalty::Penalty const & penalty);
|
||||||
|
std::string DebugPrint(RoadPenalty const & roadPenalty);
|
||||||
|
} // namespace routing
|
||||||
110
libs/routing/road_penalty_serialization.hpp
Normal file
110
libs/routing/road_penalty_serialization.hpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "routing/road_penalty.hpp"
|
||||||
|
#include "routing/road_point.hpp"
|
||||||
|
|
||||||
|
#include "coding/reader.hpp"
|
||||||
|
#include "coding/write_to_sink.hpp"
|
||||||
|
|
||||||
|
#include "base/assert.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace routing
|
||||||
|
{
|
||||||
|
class RoadPenaltySerializer final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using PointToPenalty = RoadPenalty::PointToPenalty;
|
||||||
|
using Penalty = RoadPenalty::Penalty;
|
||||||
|
|
||||||
|
RoadPenaltySerializer() = delete;
|
||||||
|
|
||||||
|
template <typename Sink>
|
||||||
|
static void Serialize(Sink & sink, RoadPenalty const & roadPenalty)
|
||||||
|
{
|
||||||
|
SerializePenalties(sink, roadPenalty.GetPointToPenalty());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
static void Deserialize(Source & src, RoadPenalty & roadPenalty, VehicleType vehicleType)
|
||||||
|
{
|
||||||
|
PointToPenalty pointToPenalty;
|
||||||
|
DeserializePenalties(src, pointToPenalty, vehicleType);
|
||||||
|
|
||||||
|
roadPenalty.SetPointPenalties(std::move(pointToPenalty));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename Sink>
|
||||||
|
static void SerializePenalty(Sink & sink, Penalty const & penalty)
|
||||||
|
{
|
||||||
|
WriteToSink(sink, static_cast<uint8_t>(penalty.m_type));
|
||||||
|
// Time is derived from type + vehicle when loading
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
static void DeserializePenalty(Source & src, Penalty & penalty, VehicleType vehicleType)
|
||||||
|
{
|
||||||
|
penalty.m_type = static_cast<RoadPenalty::Type>(ReadPrimitiveFromSource<uint8_t>(src));
|
||||||
|
penalty.m_timeSeconds = Penalty::GetTimePenalty(penalty.m_type, vehicleType);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Sink, typename PenaltyMap>
|
||||||
|
static void SerializePenalties(Sink & sink, PenaltyMap const & penalties)
|
||||||
|
{
|
||||||
|
WriteToSink(sink, static_cast<uint32_t>(penalties.size()));
|
||||||
|
for (auto const & [key, penalty] : penalties)
|
||||||
|
{
|
||||||
|
SerializeKey(sink, key);
|
||||||
|
SerializePenalty(sink, penalty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Source, typename PenaltyMap>
|
||||||
|
static void DeserializePenalties(Source & src, PenaltyMap & penalties, VehicleType vehicleType)
|
||||||
|
{
|
||||||
|
uint32_t const size = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
penalties.reserve(size);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
typename PenaltyMap::key_type key;
|
||||||
|
DeserializeKey(src, key);
|
||||||
|
|
||||||
|
Penalty penalty;
|
||||||
|
DeserializePenalty(src, penalty, vehicleType);
|
||||||
|
|
||||||
|
penalties[key] = penalty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Sink>
|
||||||
|
static void SerializeKey(Sink & sink, uint32_t key)
|
||||||
|
{
|
||||||
|
WriteToSink(sink, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
static void DeserializeKey(Source & src, uint32_t & key)
|
||||||
|
{
|
||||||
|
key = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Sink>
|
||||||
|
static void SerializeKey(Sink & sink, RoadPoint const & key)
|
||||||
|
{
|
||||||
|
WriteToSink(sink, key.GetFeatureId());
|
||||||
|
WriteToSink(sink, key.GetPointId());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Source>
|
||||||
|
static void DeserializeKey(Source & src, RoadPoint & key)
|
||||||
|
{
|
||||||
|
uint32_t featureId = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
uint32_t pointId = ReadPrimitiveFromSource<uint32_t>(src);
|
||||||
|
key = RoadPoint(featureId, pointId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace routing
|
||||||
@@ -26,6 +26,7 @@ set(SRC
|
|||||||
position_accumulator_tests.cpp
|
position_accumulator_tests.cpp
|
||||||
restriction_test.cpp
|
restriction_test.cpp
|
||||||
road_access_test.cpp
|
road_access_test.cpp
|
||||||
|
road_penalty_test.cpp
|
||||||
road_graph_builder.cpp
|
road_graph_builder.cpp
|
||||||
road_graph_builder.hpp
|
road_graph_builder.hpp
|
||||||
road_graph_nearest_edges_test.cpp
|
road_graph_nearest_edges_test.cpp
|
||||||
|
|||||||
@@ -150,6 +150,11 @@ double WeightedEdgeEstimator::GetUTurnPenalty(Purpose purpose) const
|
|||||||
{
|
{
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
double WeightedEdgeEstimator::GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road,
|
||||||
|
RoadGeometry const & to_road, bool is_left_hand_traffic) const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
double WeightedEdgeEstimator::GetFerryLandingPenalty(Purpose purpose) const
|
double WeightedEdgeEstimator::GetFerryLandingPenalty(Purpose purpose) const
|
||||||
{
|
{
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ public:
|
|||||||
// maxSpeedKMpH doesn't matter, but should be greater then any road speed in all tests.
|
// maxSpeedKMpH doesn't matter, but should be greater then any road speed in all tests.
|
||||||
// offroadSpeedKMpH doesn't matter, but should be > 0 and <= maxSpeedKMpH.
|
// offroadSpeedKMpH doesn't matter, but should be > 0 and <= maxSpeedKMpH.
|
||||||
explicit WeightedEdgeEstimator(std::map<Segment, double> const & segmentWeights)
|
explicit WeightedEdgeEstimator(std::map<Segment, double> const & segmentWeights)
|
||||||
: EdgeEstimator(1e10 /* maxSpeedKMpH */, 1.0 /* offroadSpeedKMpH */)
|
: EdgeEstimator(VehicleType::Count, 1e10 /* maxSpeedKMpH */, 1.0 /* offroadSpeedKMpH */)
|
||||||
, m_segmentWeights(segmentWeights)
|
, m_segmentWeights(segmentWeights)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -174,6 +174,8 @@ public:
|
|||||||
EdgeEstimator::Purpose purpose) const override;
|
EdgeEstimator::Purpose purpose) const override;
|
||||||
|
|
||||||
double GetUTurnPenalty(Purpose purpose) const override;
|
double GetUTurnPenalty(Purpose purpose) const override;
|
||||||
|
double GetTurnPenalty(Purpose purpose, double angle, RoadGeometry const & from_road, RoadGeometry const & to_road,
|
||||||
|
bool is_left_hand_traffic = false) const override;
|
||||||
double GetFerryLandingPenalty(Purpose purpose) const override;
|
double GetFerryLandingPenalty(Purpose purpose) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
169
libs/routing/routing_tests/road_penalty_test.cpp
Normal file
169
libs/routing/routing_tests/road_penalty_test.cpp
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
#include "testing/testing.hpp"
|
||||||
|
|
||||||
|
#include "routing/road_penalty.hpp"
|
||||||
|
#include "routing/road_point.hpp"
|
||||||
|
#include "routing/vehicle_mask.hpp"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace road_penalty_test
|
||||||
|
{
|
||||||
|
using namespace routing;
|
||||||
|
|
||||||
|
UNIT_TEST(RoadPenalty_Basic)
|
||||||
|
{
|
||||||
|
RoadPenalty penalty;
|
||||||
|
|
||||||
|
// Test empty penalty
|
||||||
|
TEST(!penalty.GetPenalty(RoadPoint(1, 0)).has_value(), ());
|
||||||
|
TEST(!penalty.GetPenalty(RoadPoint(2, 1)).has_value(), ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(RoadPenalty_PointPenalties)
|
||||||
|
{
|
||||||
|
RoadPenalty penalty;
|
||||||
|
|
||||||
|
// Test point penalties
|
||||||
|
RoadPenalty::PointToPenalty pointPenalties;
|
||||||
|
pointPenalties[RoadPoint(1, 0)] = RoadPenalty::Penalty(RoadPenalty::Type::MediumCalming, VehicleType::Car);
|
||||||
|
pointPenalties[RoadPoint(2, 3)] = RoadPenalty::Penalty(RoadPenalty::Type::Gate, VehicleType::Car);
|
||||||
|
penalty.SetPointPenalties(std::move(pointPenalties));
|
||||||
|
|
||||||
|
auto p1 = penalty.GetPenalty(RoadPoint(1, 0));
|
||||||
|
TEST(p1.has_value(), ());
|
||||||
|
TEST_EQUAL(p1->m_type, RoadPenalty::Type::MediumCalming, ());
|
||||||
|
TEST_EQUAL(p1->m_timeSeconds, 5, ());
|
||||||
|
|
||||||
|
auto p2 = penalty.GetPenalty(RoadPoint(2, 3));
|
||||||
|
TEST(p2.has_value(), ());
|
||||||
|
TEST_EQUAL(p2->m_type, RoadPenalty::Type::Gate, ());
|
||||||
|
TEST_EQUAL(p2->m_timeSeconds, 30, ());
|
||||||
|
|
||||||
|
TEST(!penalty.GetPenalty(RoadPoint(1, 1)).has_value(), ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(RoadPenalty_TypeConversion)
|
||||||
|
{
|
||||||
|
// Test ToString/FromString
|
||||||
|
TEST_EQUAL(ToString(RoadPenalty::Type::None), "None", ());
|
||||||
|
TEST_EQUAL(ToString(RoadPenalty::Type::SmallCalming), "SmallCalming", ());
|
||||||
|
TEST_EQUAL(ToString(RoadPenalty::Type::MediumCalming), "MediumCalming", ());
|
||||||
|
TEST_EQUAL(ToString(RoadPenalty::Type::LargeCalming), "LargeCalming", ());
|
||||||
|
TEST_EQUAL(ToString(RoadPenalty::Type::Gate), "Gate", ());
|
||||||
|
TEST_EQUAL(ToString(RoadPenalty::Type::UncontrolledJunction), "UncontrolledJunction", ());
|
||||||
|
TEST_EQUAL(ToString(RoadPenalty::Type::ControlledJunction), "ControlledJunction", ());
|
||||||
|
|
||||||
|
RoadPenalty::Type type;
|
||||||
|
FromString("SmallCalming", type);
|
||||||
|
TEST_EQUAL(type, RoadPenalty::Type::SmallCalming, ());
|
||||||
|
|
||||||
|
FromString("Gate", type);
|
||||||
|
TEST_EQUAL(type, RoadPenalty::Type::Gate, ());
|
||||||
|
|
||||||
|
FromString("UncontrolledJunction", type);
|
||||||
|
TEST_EQUAL(type, RoadPenalty::Type::UncontrolledJunction, ());
|
||||||
|
|
||||||
|
FromString("ControlledJunction", type);
|
||||||
|
TEST_EQUAL(type, RoadPenalty::Type::ControlledJunction, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
UNIT_TEST(RoadPenalty_Equality)
|
||||||
|
{
|
||||||
|
RoadPenalty penalty1, penalty2;
|
||||||
|
TEST(penalty1 == penalty2, ());
|
||||||
|
|
||||||
|
RoadPenalty::PointToPenalty pointPenalties;
|
||||||
|
pointPenalties[RoadPoint(1, 0)] = RoadPenalty::Penalty(RoadPenalty::Type::SmallCalming, VehicleType::Car);
|
||||||
|
penalty1.SetPointPenalties(std::move(pointPenalties));
|
||||||
|
|
||||||
|
TEST(!(penalty1 == penalty2), ());
|
||||||
|
|
||||||
|
pointPenalties.clear();
|
||||||
|
pointPenalties[RoadPoint(1, 0)] = RoadPenalty::Penalty(RoadPenalty::Type::SmallCalming, VehicleType::Car);
|
||||||
|
penalty2.SetPointPenalties(std::move(pointPenalties));
|
||||||
|
|
||||||
|
TEST(penalty1 == penalty2, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test vehicle mask functionality
|
||||||
|
UNIT_TEST(RoadPenalty_VehicleMask)
|
||||||
|
{
|
||||||
|
// Test basic mask operations
|
||||||
|
VehicleMask mask = 0;
|
||||||
|
|
||||||
|
// Set bit for Car (VehicleType::Car = 2)
|
||||||
|
mask |= (1 << 2);
|
||||||
|
TEST((mask & (1 << 2)) != 0, ());
|
||||||
|
TEST((mask & (1 << 1)) == 0, ());
|
||||||
|
|
||||||
|
// Test mask with multiple vehicle types
|
||||||
|
VehicleMask multiMask = 0;
|
||||||
|
multiMask |= (1 << 0); // Pedestrian
|
||||||
|
multiMask |= (1 << 1); // Bicycle
|
||||||
|
multiMask |= (1 << 2); // Car
|
||||||
|
|
||||||
|
// Verify multiple bits are set
|
||||||
|
TEST_EQUAL(__builtin_popcount(multiMask), 3, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test default time penalties
|
||||||
|
UNIT_TEST(RoadPenalty_DefaultTimes)
|
||||||
|
{
|
||||||
|
// Test GetTimePenalty with Car as default
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::None, VehicleType::Car), 0, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::SmallCalming, VehicleType::Car), 3, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::MediumCalming, VehicleType::Car), 5, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::LargeCalming, VehicleType::Car), 7, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::Gate, VehicleType::Car), 30, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::UncontrolledJunction, VehicleType::Car), 15, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::ControlledJunction, VehicleType::Car), 30, ());
|
||||||
|
|
||||||
|
// Test constructor with vehicle type
|
||||||
|
RoadPenalty::Penalty smallCalming(RoadPenalty::Type::SmallCalming, VehicleType::Car);
|
||||||
|
TEST_EQUAL(smallCalming.m_type, RoadPenalty::Type::SmallCalming, ());
|
||||||
|
TEST_EQUAL(smallCalming.m_timeSeconds, 3, ());
|
||||||
|
|
||||||
|
RoadPenalty::Penalty gate(RoadPenalty::Type::Gate, VehicleType::Car);
|
||||||
|
TEST_EQUAL(gate.m_type, RoadPenalty::Type::Gate, ());
|
||||||
|
TEST_EQUAL(gate.m_timeSeconds, 30, ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test vehicle-specific time penalties
|
||||||
|
UNIT_TEST(RoadPenalty_VehicleSpecificTimes)
|
||||||
|
{
|
||||||
|
// Test GetTimePenalty with different vehicle types
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::Gate, VehicleType::Car), 30, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::Gate, VehicleType::Bicycle), 10, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::Gate, VehicleType::Pedestrian), 10, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::Gate, VehicleType::Transit), 5, ());
|
||||||
|
|
||||||
|
// Test constructor with vehicle type
|
||||||
|
RoadPenalty::Penalty carGate(RoadPenalty::Type::Gate, VehicleType::Car);
|
||||||
|
TEST_EQUAL(carGate.m_type, RoadPenalty::Type::Gate, ());
|
||||||
|
TEST_EQUAL(carGate.m_timeSeconds, 30, ());
|
||||||
|
|
||||||
|
RoadPenalty::Penalty bicycleGate(RoadPenalty::Type::Gate, VehicleType::Bicycle);
|
||||||
|
TEST_EQUAL(bicycleGate.m_type, RoadPenalty::Type::Gate, ());
|
||||||
|
TEST_EQUAL(bicycleGate.m_timeSeconds, 10, ());
|
||||||
|
|
||||||
|
// Test traffic calming with different vehicles
|
||||||
|
RoadPenalty::Penalty carCalming(RoadPenalty::Type::SmallCalming, VehicleType::Car);
|
||||||
|
TEST_EQUAL(carCalming.m_type, RoadPenalty::Type::SmallCalming, ());
|
||||||
|
TEST_EQUAL(carCalming.m_timeSeconds, 3, ());
|
||||||
|
|
||||||
|
RoadPenalty::Penalty bicycleCalming(RoadPenalty::Type::SmallCalming, VehicleType::Bicycle);
|
||||||
|
TEST_EQUAL(bicycleCalming.m_type, RoadPenalty::Type::SmallCalming, ());
|
||||||
|
TEST_EQUAL(bicycleCalming.m_timeSeconds, 0, ());
|
||||||
|
|
||||||
|
// Test junction penalties with different vehicles
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::UncontrolledJunction, VehicleType::Bicycle), 10,
|
||||||
|
());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::ControlledJunction, VehicleType::Bicycle), 30, ());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::UncontrolledJunction, VehicleType::Pedestrian), 0,
|
||||||
|
());
|
||||||
|
TEST_EQUAL(RoadPenalty::Penalty::GetTimePenalty(RoadPenalty::Type::ControlledJunction, VehicleType::Pedestrian), 0,
|
||||||
|
());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace road_penalty_test
|
||||||
@@ -18,7 +18,7 @@ HighwayBasedFactors const kHighwayBasedFactors = {
|
|||||||
|
|
||||||
// Tier 2:
|
// Tier 2:
|
||||||
{HighwayType::HighwayPrimary,
|
{HighwayType::HighwayPrimary,
|
||||||
InOutCityFactor(SpeedFactor{0.85 /* weight */, 0.80 /* eta */} /* in city */, 0.85 /* out city */)},
|
InOutCityFactor(SpeedFactor{0.95 /* weight */, 0.90 /* eta */} /* in city */, 0.85 /* out city */)},
|
||||||
{HighwayType::HighwayPrimaryLink, InOutCityFactor(0.70 /* in city */, 0.75 /* out city */)}, // 0.10 less
|
{HighwayType::HighwayPrimaryLink, InOutCityFactor(0.70 /* in city */, 0.75 /* out city */)}, // 0.10 less
|
||||||
{HighwayType::HighwaySecondary, InOutCityFactor(0.80 /* in city */, 0.85 /* out city */)},
|
{HighwayType::HighwaySecondary, InOutCityFactor(0.80 /* in city */, 0.85 /* out city */)},
|
||||||
{HighwayType::HighwaySecondaryLink, InOutCityFactor(0.70 /* in city */, 0.75 /* out city */)}, // 0.10 less
|
{HighwayType::HighwaySecondaryLink, InOutCityFactor(0.70 /* in city */, 0.75 /* out city */)}, // 0.10 less
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace routing
|
namespace routing
|
||||||
{
|
{
|
||||||
@@ -378,4 +379,41 @@ string DebugPrint(HighwayType type)
|
|||||||
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FromString(std::string_view s, HighwayType & highwayType)
|
||||||
|
{
|
||||||
|
// Build reverse lookup from DebugPrint function
|
||||||
|
static std::unordered_map<std::string, HighwayType> const stringToEnum = []()
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, HighwayType> map;
|
||||||
|
|
||||||
|
// All possible HighwayType values
|
||||||
|
constexpr HighwayType allTypes[] = {
|
||||||
|
HighwayType::HighwayResidential, HighwayType::HighwayService, HighwayType::HighwayUnclassified,
|
||||||
|
HighwayType::HighwayFootway, HighwayType::HighwayTrack, HighwayType::HighwayTertiary,
|
||||||
|
HighwayType::HighwaySecondary, HighwayType::HighwayPath, HighwayType::HighwayPrimary,
|
||||||
|
HighwayType::HighwayRoad, HighwayType::HighwayCycleway, HighwayType::HighwayMotorwayLink,
|
||||||
|
HighwayType::HighwayLivingStreet, HighwayType::HighwayMotorway, HighwayType::HighwaySteps,
|
||||||
|
HighwayType::HighwayTrunk, HighwayType::HighwayPedestrian, HighwayType::HighwayTrunkLink,
|
||||||
|
HighwayType::HighwayPrimaryLink, HighwayType::ManMadePier, HighwayType::HighwayBridleway,
|
||||||
|
HighwayType::HighwaySecondaryLink, HighwayType::RouteFerry, HighwayType::HighwayTertiaryLink,
|
||||||
|
HighwayType::HighwayBusway, HighwayType::RouteShuttleTrain};
|
||||||
|
|
||||||
|
for (auto type : allTypes)
|
||||||
|
map[DebugPrint(type)] = type;
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}();
|
||||||
|
|
||||||
|
auto it = stringToEnum.find(std::string(s));
|
||||||
|
if (it != stringToEnum.end())
|
||||||
|
{
|
||||||
|
highwayType = it->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(false, ("Could not read HighwayType from string", s));
|
||||||
|
highwayType = HighwayType::HighwayResidential; // default fallback
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace routing
|
} // namespace routing
|
||||||
|
|||||||
@@ -366,4 +366,5 @@ std::string DebugPrint(SpeedFactor const & speedFactor);
|
|||||||
std::string DebugPrint(InOutCitySpeedKMpH const & speed);
|
std::string DebugPrint(InOutCitySpeedKMpH const & speed);
|
||||||
std::string DebugPrint(InOutCityFactor const & speedFactor);
|
std::string DebugPrint(InOutCityFactor const & speedFactor);
|
||||||
std::string DebugPrint(HighwayType type);
|
std::string DebugPrint(HighwayType type);
|
||||||
|
void FromString(std::string_view s, HighwayType & highwayType);
|
||||||
} // namespace routing
|
} // namespace routing
|
||||||
|
|||||||
@@ -212,6 +212,10 @@
|
|||||||
67C79BA21E2CEE1400C40034 /* restriction_loader.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 67C79BA01E2CEE1400C40034 /* restriction_loader.hpp */; };
|
67C79BA21E2CEE1400C40034 /* restriction_loader.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 67C79BA01E2CEE1400C40034 /* restriction_loader.hpp */; };
|
||||||
67C7D42D1B4EB48F00FE41AA /* turns_sound_settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 67C7D4251B4EB48F00FE41AA /* turns_sound_settings.cpp */; };
|
67C7D42D1B4EB48F00FE41AA /* turns_sound_settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 67C7D4251B4EB48F00FE41AA /* turns_sound_settings.cpp */; };
|
||||||
67C7D42E1B4EB48F00FE41AA /* turns_sound_settings.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 67C7D4261B4EB48F00FE41AA /* turns_sound_settings.hpp */; };
|
67C7D42E1B4EB48F00FE41AA /* turns_sound_settings.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 67C7D4261B4EB48F00FE41AA /* turns_sound_settings.hpp */; };
|
||||||
|
833F71FA2E48DF27008F7617 /* road_penalty.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 833F71F82E48DF27008F7617 /* road_penalty.hpp */; };
|
||||||
|
833F71FB2E48DF27008F7617 /* road_penalty.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 833F71F92E48DF27008F7617 /* road_penalty.cpp */; };
|
||||||
|
833F71FD2E48E011008F7617 /* road_penalty_serialization.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 833F71FC2E48E010008F7617 /* road_penalty_serialization.hpp */; };
|
||||||
|
833F71FF2E48E02E008F7617 /* road_penalty_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 833F71FE2E48E02E008F7617 /* road_penalty_test.cpp */; };
|
||||||
A120B3531B4A7C1C002F3808 /* astar_algorithm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A120B3521B4A7C1C002F3808 /* astar_algorithm.hpp */; };
|
A120B3531B4A7C1C002F3808 /* astar_algorithm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A120B3521B4A7C1C002F3808 /* astar_algorithm.hpp */; };
|
||||||
A1616E2B1B6B60AB003F078E /* router_delegate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1616E291B6B60AB003F078E /* router_delegate.cpp */; };
|
A1616E2B1B6B60AB003F078E /* router_delegate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1616E291B6B60AB003F078E /* router_delegate.cpp */; };
|
||||||
A1616E2C1B6B60AB003F078E /* router_delegate.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A1616E2A1B6B60AB003F078E /* router_delegate.hpp */; };
|
A1616E2C1B6B60AB003F078E /* router_delegate.hpp in Headers */ = {isa = PBXBuildFile; fileRef = A1616E2A1B6B60AB003F078E /* router_delegate.hpp */; };
|
||||||
@@ -498,6 +502,10 @@
|
|||||||
67C79BA01E2CEE1400C40034 /* restriction_loader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = restriction_loader.hpp; sourceTree = "<group>"; };
|
67C79BA01E2CEE1400C40034 /* restriction_loader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = restriction_loader.hpp; sourceTree = "<group>"; };
|
||||||
67C7D4251B4EB48F00FE41AA /* turns_sound_settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = turns_sound_settings.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
67C7D4251B4EB48F00FE41AA /* turns_sound_settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = turns_sound_settings.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||||
67C7D4261B4EB48F00FE41AA /* turns_sound_settings.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = turns_sound_settings.hpp; sourceTree = "<group>"; };
|
67C7D4261B4EB48F00FE41AA /* turns_sound_settings.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = turns_sound_settings.hpp; sourceTree = "<group>"; };
|
||||||
|
833F71F82E48DF27008F7617 /* road_penalty.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = road_penalty.hpp; sourceTree = "<group>"; };
|
||||||
|
833F71F92E48DF27008F7617 /* road_penalty.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = road_penalty.cpp; sourceTree = "<group>"; };
|
||||||
|
833F71FC2E48E010008F7617 /* road_penalty_serialization.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = road_penalty_serialization.hpp; sourceTree = "<group>"; };
|
||||||
|
833F71FE2E48E02E008F7617 /* road_penalty_test.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = road_penalty_test.cpp; sourceTree = "<group>"; };
|
||||||
A120B3521B4A7C1C002F3808 /* astar_algorithm.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = astar_algorithm.hpp; sourceTree = "<group>"; };
|
A120B3521B4A7C1C002F3808 /* astar_algorithm.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = astar_algorithm.hpp; sourceTree = "<group>"; };
|
||||||
A1616E291B6B60AB003F078E /* router_delegate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = router_delegate.cpp; sourceTree = "<group>"; };
|
A1616E291B6B60AB003F078E /* router_delegate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = router_delegate.cpp; sourceTree = "<group>"; };
|
||||||
A1616E2A1B6B60AB003F078E /* router_delegate.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = router_delegate.hpp; sourceTree = "<group>"; };
|
A1616E2A1B6B60AB003F078E /* router_delegate.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = router_delegate.hpp; sourceTree = "<group>"; };
|
||||||
@@ -618,6 +626,7 @@
|
|||||||
6742ACAF1C68A0B1009CB89E /* road_graph_builder.cpp */,
|
6742ACAF1C68A0B1009CB89E /* road_graph_builder.cpp */,
|
||||||
6742ACB01C68A0B1009CB89E /* road_graph_builder.hpp */,
|
6742ACB01C68A0B1009CB89E /* road_graph_builder.hpp */,
|
||||||
6742ACB11C68A0B1009CB89E /* road_graph_nearest_edges_test.cpp */,
|
6742ACB11C68A0B1009CB89E /* road_graph_nearest_edges_test.cpp */,
|
||||||
|
833F71FE2E48E02E008F7617 /* road_penalty_test.cpp */,
|
||||||
6742ACB21C68A0B1009CB89E /* route_tests.cpp */,
|
6742ACB21C68A0B1009CB89E /* route_tests.cpp */,
|
||||||
56290B85206A3231003892E0 /* routing_algorithm.cpp */,
|
56290B85206A3231003892E0 /* routing_algorithm.cpp */,
|
||||||
56290B86206A3231003892E0 /* routing_algorithm.hpp */,
|
56290B86206A3231003892E0 /* routing_algorithm.hpp */,
|
||||||
@@ -694,6 +703,7 @@
|
|||||||
671F58BA1B874EA20032311E /* base */,
|
671F58BA1B874EA20032311E /* base */,
|
||||||
5694723F2418C8220013CD21 /* car_directions.hpp */,
|
5694723F2418C8220013CD21 /* car_directions.hpp */,
|
||||||
569472402418C8220013CD21 /* car_directions.cpp */,
|
569472402418C8220013CD21 /* car_directions.cpp */,
|
||||||
|
5670595B1F3AF97F0062672D /* checkpoint_predictor.cpp */,
|
||||||
5670595C1F3AF97F0062672D /* checkpoint_predictor.hpp */,
|
5670595C1F3AF97F0062672D /* checkpoint_predictor.hpp */,
|
||||||
5670595B1F3AF97F0062672D /* checkpoint_predictor.cpp */,
|
5670595B1F3AF97F0062672D /* checkpoint_predictor.cpp */,
|
||||||
0C15B8011F02A61B0058E253 /* checkpoints.hpp */,
|
0C15B8011F02A61B0058E253 /* checkpoints.hpp */,
|
||||||
@@ -792,6 +802,9 @@
|
|||||||
674F9BC41B0A580E00704FFA /* road_graph.cpp */,
|
674F9BC41B0A580E00704FFA /* road_graph.cpp */,
|
||||||
0C5FEC671DDE193F0017688C /* road_index.hpp */,
|
0C5FEC671DDE193F0017688C /* road_index.hpp */,
|
||||||
0C5FEC661DDE193F0017688C /* road_index.cpp */,
|
0C5FEC661DDE193F0017688C /* road_index.cpp */,
|
||||||
|
833F71F82E48DF27008F7617 /* road_penalty.hpp */,
|
||||||
|
833F71F92E48DF27008F7617 /* road_penalty.cpp */,
|
||||||
|
833F71FC2E48E010008F7617 /* road_penalty_serialization.hpp */,
|
||||||
0C5FEC681DDE193F0017688C /* road_point.hpp */,
|
0C5FEC681DDE193F0017688C /* road_point.hpp */,
|
||||||
6753440E1A3F644F00A0A8C3 /* route.hpp */,
|
6753440E1A3F644F00A0A8C3 /* route.hpp */,
|
||||||
6753440D1A3F644F00A0A8C3 /* route.cpp */,
|
6753440D1A3F644F00A0A8C3 /* route.cpp */,
|
||||||
@@ -941,6 +954,7 @@
|
|||||||
44642D2D29CDA44700F8813A /* ruler_router.hpp in Headers */,
|
44642D2D29CDA44700F8813A /* ruler_router.hpp in Headers */,
|
||||||
56CBED5522E9CE2600D51AF7 /* position_accumulator.hpp in Headers */,
|
56CBED5522E9CE2600D51AF7 /* position_accumulator.hpp in Headers */,
|
||||||
5694CECB1EBA25F7004576D3 /* road_access_serialization.hpp in Headers */,
|
5694CECB1EBA25F7004576D3 /* road_access_serialization.hpp in Headers */,
|
||||||
|
833F71FA2E48DF27008F7617 /* road_penalty.hpp in Headers */,
|
||||||
0C08AA371DF8324D004195DD /* vehicle_mask.hpp in Headers */,
|
0C08AA371DF8324D004195DD /* vehicle_mask.hpp in Headers */,
|
||||||
6753441D1A3F644F00A0A8C3 /* router.hpp in Headers */,
|
6753441D1A3F644F00A0A8C3 /* router.hpp in Headers */,
|
||||||
A1616E2E1B6B60B3003F078E /* astar_progress.hpp in Headers */,
|
A1616E2E1B6B60B3003F078E /* astar_progress.hpp in Headers */,
|
||||||
@@ -972,6 +986,7 @@
|
|||||||
4443DC3822789793000C8E32 /* leaps_postprocessor.hpp in Headers */,
|
4443DC3822789793000C8E32 /* leaps_postprocessor.hpp in Headers */,
|
||||||
0C62BFE61E8ADC3100055A79 /* coding.hpp in Headers */,
|
0C62BFE61E8ADC3100055A79 /* coding.hpp in Headers */,
|
||||||
674F9BD51B0A580E00704FFA /* road_graph.hpp in Headers */,
|
674F9BD51B0A580E00704FFA /* road_graph.hpp in Headers */,
|
||||||
|
833F71FD2E48E011008F7617 /* road_penalty_serialization.hpp in Headers */,
|
||||||
562BDE2020D14860008EFF6F /* routing_callbacks.hpp in Headers */,
|
562BDE2020D14860008EFF6F /* routing_callbacks.hpp in Headers */,
|
||||||
567F81952154D6FF0093C25B /* city_roads.hpp in Headers */,
|
567F81952154D6FF0093C25B /* city_roads.hpp in Headers */,
|
||||||
D5C9497C2525C855001E45E2 /* directions_engine_helpers.hpp in Headers */,
|
D5C9497C2525C855001E45E2 /* directions_engine_helpers.hpp in Headers */,
|
||||||
@@ -1179,6 +1194,7 @@
|
|||||||
6742AD371C68A9DF009CB89E /* turns_tts_text_tests.cpp in Sources */,
|
6742AD371C68A9DF009CB89E /* turns_tts_text_tests.cpp in Sources */,
|
||||||
6742AD2C1C68A9DF009CB89E /* followed_polyline_test.cpp in Sources */,
|
6742AD2C1C68A9DF009CB89E /* followed_polyline_test.cpp in Sources */,
|
||||||
FAA838AC26BB4B3D002E54C6 /* coding_test.cpp in Sources */,
|
FAA838AC26BB4B3D002E54C6 /* coding_test.cpp in Sources */,
|
||||||
|
833F71FF2E48E02E008F7617 /* road_penalty_test.cpp in Sources */,
|
||||||
FAA8389D26BB4ADD002E54C6 /* guides_tests.cpp in Sources */,
|
FAA8389D26BB4ADD002E54C6 /* guides_tests.cpp in Sources */,
|
||||||
56CBED5822E9CFB600D51AF7 /* position_accumulator_tests.cpp in Sources */,
|
56CBED5822E9CFB600D51AF7 /* position_accumulator_tests.cpp in Sources */,
|
||||||
FAA838A826BB4B21002E54C6 /* routing_helpers_tests.cpp in Sources */,
|
FAA838A826BB4B21002E54C6 /* routing_helpers_tests.cpp in Sources */,
|
||||||
@@ -1233,6 +1249,7 @@
|
|||||||
6741AA9C1BF35331002C974C /* turns_notification_manager.cpp in Sources */,
|
6741AA9C1BF35331002C974C /* turns_notification_manager.cpp in Sources */,
|
||||||
0C0DF9211DE898B70055A22F /* index_graph_starter.cpp in Sources */,
|
0C0DF9211DE898B70055A22F /* index_graph_starter.cpp in Sources */,
|
||||||
56C439281E93BF8C00998E29 /* cross_mwm_graph.cpp in Sources */,
|
56C439281E93BF8C00998E29 /* cross_mwm_graph.cpp in Sources */,
|
||||||
|
833F71FB2E48DF27008F7617 /* road_penalty.cpp in Sources */,
|
||||||
670EE5731B664796001E8064 /* pedestrian_directions.cpp in Sources */,
|
670EE5731B664796001E8064 /* pedestrian_directions.cpp in Sources */,
|
||||||
567F81942154D6FF0093C25B /* city_roads.cpp in Sources */,
|
567F81942154D6FF0093C25B /* city_roads.cpp in Sources */,
|
||||||
6753441B1A3F644F00A0A8C3 /* route.cpp in Sources */,
|
6753441B1A3F644F00A0A8C3 /* route.cpp in Sources */,
|
||||||
|
|||||||
Reference in New Issue
Block a user