Support OSM traffic signal directions (#6153)
Currently OSRM parses traffic signal nodes without consideration for the direction in which the signal applies. This can lead to duplicated routing penalties, especially when a forward and backward signal are in close proximity on a way. This commit adds support for directed signals to the extraction and graph creation. Signal penalties are only applied in the direction specified by the OSM tag. We add the assignment of traffic directions to the lua scripts, maintaining backwards compatibility with the existing boolean traffic states. As part of the changes to the internal structures used for tracking traffic signals during extraction, we stop serialising/deserialising signals to the `.osrm` file. The traffic signals are only used by `osrm-extract` so whilst this is a data format change, it will not break any existing user processes.
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
#include "traffic_signals.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@@ -68,7 +69,7 @@ class EdgeBasedGraphFactory
|
||||
EdgeBasedNodeDataContainer &node_data_container,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
const TrafficSignals &traffic_signals,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const NameTable &name_table,
|
||||
const std::unordered_set<EdgeID> &segregated_edges,
|
||||
@@ -134,7 +135,7 @@ class EdgeBasedGraphFactory
|
||||
const util::NodeBasedDynamicGraph &m_node_based_graph;
|
||||
|
||||
const std::unordered_set<NodeID> &m_barrier_nodes;
|
||||
const std::unordered_set<NodeID> &m_traffic_lights;
|
||||
const TrafficSignals &m_traffic_signals;
|
||||
const CompressedEdgeContainer &m_compressed_edge_container;
|
||||
|
||||
const NameTable &name_table;
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
|
||||
#include "storage/tar_fwd.hpp"
|
||||
#include "traffic_lights.hpp"
|
||||
#include "traffic_signals.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -25,15 +28,19 @@ namespace extractor
|
||||
class ExtractionContainers
|
||||
{
|
||||
using ReferencedWays = std::unordered_map<OSMWayID, NodesOfWay>;
|
||||
using ReferencedTrafficSignals =
|
||||
std::pair<std::unordered_set<OSMNodeID>, std::unordered_multimap<OSMNodeID, OSMNodeID>>;
|
||||
// The relationship between way and nodes is lost during node preparation.
|
||||
// We identify the ways and nodes relevant to restrictions/overrides prior to
|
||||
// We identify the ways and nodes relevant to restrictions/overrides/signals prior to
|
||||
// node processing so that they can be referenced in the preparation phase.
|
||||
ReferencedWays IdentifyRestrictionWays();
|
||||
ReferencedWays IdentifyManeuverOverrideWays();
|
||||
ReferencedTrafficSignals IdentifyTrafficSignals();
|
||||
|
||||
void PrepareNodes();
|
||||
void PrepareManeuverOverrides(const ReferencedWays &maneuver_override_ways);
|
||||
void PrepareRestrictions(const ReferencedWays &restriction_ways);
|
||||
void PrepareTrafficSignals(const ReferencedTrafficSignals &referenced_traffic_signals);
|
||||
void PrepareEdges(ScriptingEnvironment &scripting_environment);
|
||||
|
||||
void WriteNodes(storage::tar::FileWriter &file_out) const;
|
||||
@@ -50,9 +57,9 @@ class ExtractionContainers
|
||||
using NameOffsets = std::vector<size_t>;
|
||||
using WayIDVector = std::vector<OSMWayID>;
|
||||
using WayNodeIDOffsets = std::vector<size_t>;
|
||||
using InputTrafficSignal = std::pair<OSMNodeID, TrafficLightClass::Direction>;
|
||||
|
||||
std::vector<OSMNodeID> barrier_nodes;
|
||||
std::vector<OSMNodeID> traffic_signals;
|
||||
NodeIDVector used_node_id_list;
|
||||
NodeVector all_nodes_list;
|
||||
EdgeVector all_edges_list;
|
||||
@@ -65,6 +72,9 @@ class ExtractionContainers
|
||||
|
||||
unsigned max_internal_node_id;
|
||||
|
||||
std::vector<InputTrafficSignal> external_traffic_signals;
|
||||
TrafficSignals internal_traffic_signals;
|
||||
|
||||
// List of restrictions (conditional and unconditional) before we transform them into the
|
||||
// output types. Input containers reference OSMNodeIDs. We can only transform them to the
|
||||
// correct internal IDs after we've read everything. Without a multi-parse approach,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef EXTRACTION_NODE_HPP
|
||||
#define EXTRACTION_NODE_HPP
|
||||
|
||||
#include "traffic_lights.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
@@ -8,9 +10,13 @@ namespace extractor
|
||||
|
||||
struct ExtractionNode
|
||||
{
|
||||
ExtractionNode() : traffic_lights(false), barrier(false) {}
|
||||
void clear() { traffic_lights = barrier = false; }
|
||||
bool traffic_lights;
|
||||
ExtractionNode() : traffic_lights(TrafficLightClass::NONE), barrier(false) {}
|
||||
void clear()
|
||||
{
|
||||
traffic_lights = TrafficLightClass::NONE;
|
||||
barrier = false;
|
||||
}
|
||||
TrafficLightClass::Direction traffic_lights;
|
||||
bool barrier;
|
||||
};
|
||||
} // namespace extractor
|
||||
|
||||
@@ -43,6 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "util/guidance/turn_lanes.hpp"
|
||||
|
||||
#include "restriction_graph.hpp"
|
||||
#include "traffic_signals.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
@@ -64,7 +65,8 @@ class Extractor
|
||||
|
||||
std::tuple<LaneDescriptionMap,
|
||||
std::vector<TurnRestriction>,
|
||||
std::vector<UnresolvedManeuverOverride>>
|
||||
std::vector<UnresolvedManeuverOverride>,
|
||||
TrafficSignals>
|
||||
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
|
||||
|
||||
EdgeID BuildEdgeExpandedGraph(
|
||||
@@ -73,7 +75,7 @@ class Extractor
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
const TrafficSignals &traffic_signals,
|
||||
const RestrictionGraph &restriction_graph,
|
||||
const std::unordered_set<EdgeID> &segregated_edges,
|
||||
const NameTable &name_table,
|
||||
|
||||
@@ -444,10 +444,9 @@ inline void readConditionalRestrictions(const boost::filesystem::path &path,
|
||||
}
|
||||
|
||||
// reads .osrm file which is a temporary file of osrm-extract
|
||||
template <typename BarrierOutIter, typename TrafficSignalsOutIter, typename PackedOSMIDsT>
|
||||
template <typename BarrierOutIter, typename PackedOSMIDsT>
|
||||
void readRawNBGraph(const boost::filesystem::path &path,
|
||||
BarrierOutIter barriers,
|
||||
TrafficSignalsOutIter traffic_signals,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
PackedOSMIDsT &osm_node_ids,
|
||||
std::vector<extractor::NodeBasedEdge> &edge_list,
|
||||
@@ -471,8 +470,6 @@ void readRawNBGraph(const boost::filesystem::path &path,
|
||||
|
||||
reader.ReadStreaming<NodeID>("/extractor/barriers", barriers);
|
||||
|
||||
reader.ReadStreaming<NodeID>("/extractor/traffic_lights", traffic_signals);
|
||||
|
||||
storage::serialization::read(reader, "/extractor/edges", edge_list);
|
||||
storage::serialization::read(reader, "/extractor/annotations", annotations);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "traffic_signals.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
|
||||
#include <memory>
|
||||
@@ -25,7 +26,7 @@ class GraphCompressor
|
||||
|
||||
public:
|
||||
void Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
const TrafficSignals &traffic_signals,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
|
||||
#include "traffic_signals.hpp"
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
|
||||
@@ -40,11 +41,11 @@ class NodeBasedGraphFactory
|
||||
NodeBasedGraphFactory(const boost::filesystem::path &input_file,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides);
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||
const TrafficSignals &traffic_signals);
|
||||
|
||||
auto const &GetGraph() const { return compressed_output_graph; }
|
||||
auto const &GetBarriers() const { return barriers; }
|
||||
auto const &GetTrafficSignals() const { return traffic_signals; }
|
||||
auto const &GetCompressedEdges() const { return compressed_edge_container; }
|
||||
auto const &GetCoordinates() const { return coordinates; }
|
||||
auto const &GetAnnotationData() const { return annotation_data; }
|
||||
@@ -68,7 +69,8 @@ class NodeBasedGraphFactory
|
||||
// edges into a single representative form
|
||||
void Compress(ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides);
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||
const TrafficSignals &traffic_signals);
|
||||
|
||||
// Most ways are bidirectional, making the geometry in forward and backward direction the same,
|
||||
// except for reversal. We make use of this fact by keeping only one representation of the
|
||||
@@ -89,7 +91,6 @@ class NodeBasedGraphFactory
|
||||
|
||||
// General Information about the graph, not used outside of extractor
|
||||
std::unordered_set<NodeID> barriers;
|
||||
std::unordered_set<NodeID> traffic_signals;
|
||||
|
||||
std::vector<util::Coordinate> coordinates;
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
|
||||
#define OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
namespace TrafficLightClass
|
||||
{
|
||||
// The traffic light annotation is extracted from node tags.
|
||||
// The directions in which the traffic light applies are relative to the way containing the node.
|
||||
enum Direction
|
||||
{
|
||||
NONE = 0,
|
||||
DIRECTION_ALL = 1,
|
||||
DIRECTION_FORWARD = 2,
|
||||
DIRECTION_REVERSE = 3
|
||||
};
|
||||
} // namespace TrafficLightClass
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
|
||||
#define OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
#include <unordered_set>
|
||||
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
struct TrafficSignals
|
||||
{
|
||||
std::unordered_set<NodeID> bidirectional_nodes;
|
||||
std::unordered_set<std::pair<NodeID, NodeID>, boost::hash<std::pair<NodeID, NodeID>>>
|
||||
unidirectional_segments;
|
||||
|
||||
inline bool HasSignal(NodeID from, NodeID to) const
|
||||
{
|
||||
return bidirectional_nodes.count(to) > 0 || unidirectional_segments.count({from, to}) > 0;
|
||||
}
|
||||
};
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
|
||||
Reference in New Issue
Block a user