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:
Michael Bell 2022-08-30 10:36:49 +01:00 committed by GitHub
parent d8b358e810
commit b17cbb4c47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 648 additions and 139 deletions

View File

@ -54,6 +54,7 @@
- FIXED: Improvements to maneuver override processing [#6125](https://github.com/Project-OSRM/osrm-backend/pull/6125)
- ADDED: Support snapping to multiple ways at an input location. [#5953](https://github.com/Project-OSRM/osrm-backend/pull/5953)
- FIXED: Fix snapping target locations to ways used in turn restrictions. [#6339](https://github.com/Project-OSRM/osrm-backend/pull/6339)
- ADDED: Support OSM traffic signal directions. [#6153](https://github.com/Project-OSRM/osrm-backend/pull/6153)
# 5.26.0
- Changes from 5.25.0

View File

@ -39,7 +39,113 @@ Feature: Car - Handle traffic lights
| k | n | 20.7s | turn with traffic light |
Scenario: Tarrif Signal Geometry
Scenario: Car - Traffic signal direction
Given the node map
"""
a-1-b-2-c
d-3-e-4-f
g-5-h-6-i
j-7-k-8-l
"""
And the ways
| nodes | highway |
| abc | primary |
| def | primary |
| ghi | primary |
| jkl | primary |
And the nodes
| node | highway | traffic_signals:direction |
| e | traffic_signals | |
| h | traffic_signals | forward |
| k | traffic_signals | backward |
When I route I should get
| from | to | time | # |
| 1 | 2 | 11.1s | no turn with no traffic light |
| 2 | 1 | 11.1s | no turn with no traffic light |
| 3 | 4 | 13.1s | no turn with traffic light |
| 4 | 3 | 13.1s | no turn with traffic light |
| 5 | 6 | 13.1s | no turn with traffic light |
| 6 | 5 | 11.1s | no turn with no traffic light |
| 7 | 8 | 11.1s | no turn with no traffic light |
| 8 | 7 | 13.1s | no turn with traffic light |
Scenario: Car - Encounters a traffic light
Given the node map
"""
a f k
| | |
b-c-d h-g-i l-m-n
| | |
e j o
"""
And the ways
| nodes | highway |
| bcd | primary |
| ace | primary |
| hgi | primary |
| fgj | primary |
| lmn | primary |
| kmo | primary |
And the nodes
| node | highway | traffic_signals:direction |
| g | traffic_signals | forward |
| m | traffic_signals | backward |
When I route I should get
| from | to | time | # |
| a | d | 21.9s | no turn with no traffic light |
| a | e | 22.2s | no turn with traffic light |
| a | b | 18.7s | turn with no traffic light |
| e | b | 21.9s | no turn with no traffic light |
| e | a | 22.2s | no turn with traffic light |
| e | d | 18.7s | turn with no traffic light |
| d | e | 21.9s | no turn with no traffic light |
| d | b | 11s | no turn with traffic light |
| d | a | 18.7s | turn with no traffic light |
| b | a | 21.9s | no turn with no traffic light |
| b | d | 11s | no turn with traffic light |
| b | e | 18.7s | turn with no traffic light |
| f | i | 23.9s | no turn with no traffic light |
| f | j | 24.2s | no turn with traffic light |
| f | h | 20.7s | turn with no traffic light |
| j | h | 21.9s | no turn with no traffic light |
| j | f | 22.2s | no turn with traffic light |
| j | i | 18.7s | turn with no traffic light |
| i | j | 21.9s | no turn with no traffic light |
| i | h | 11s | no turn with traffic light |
| i | f | 18.7s | turn with no traffic light |
| h | f | 23.9s | no turn with no traffic light |
| h | i | 13s | no turn with traffic light |
| h | j | 20.7s | turn with no traffic light |
| k | n | 21.9s | no turn with no traffic light |
| k | o | 22.2s | no turn with traffic light |
| k | l | 18.7s | turn with no traffic light |
| o | l | 23.9s | no turn with no traffic light |
| o | k | 24.2s | no turn with traffic light |
| o | n | 20.7s | turn with no traffic light |
| n | o | 23.9s | no turn with no traffic light |
| n | l | 13s | no turn with traffic light |
| n | k | 20.7s | turn with no traffic light |
| l | k | 21.9s | no turn with no traffic light |
| l | n | 11s | no turn with traffic light |
| l | o | 18.7s | turn with no traffic light |
Scenario: Traffic Signal Geometry
Given the query options
| overview | full |
| geometries | polyline |
@ -61,6 +167,53 @@ Feature: Car - Handle traffic lights
| from | to | route | geometry |
| a | c | abc,abc | _ibE_ibE?gJ?eJ |
Scenario: Traffic Signal Geometry - forward signal
Given the query options
| overview | full |
| geometries | polyline |
Given the node map
"""
a - b - c
"""
And the ways
| nodes | highway |
| abc | primary |
And the nodes
| node | highway | traffic_signals:direction |
| b | traffic_signals | forward |
When I route I should get
| from | to | route | geometry |
| a | c | abc,abc | _ibE_ibE?gJ?eJ |
Scenario: Traffic Signal Geometry - reverse signal
Given the query options
| overview | full |
| geometries | polyline |
Given the node map
"""
a - b - c
"""
And the ways
| nodes | highway |
| abc | primary |
And the nodes
| node | highway | traffic_signals:direction |
| b | traffic_signals | reverse |
When I route I should get
| from | to | route | geometry |
| a | c | abc,abc | _ibE_ibE?gJ?eJ |
@traffic
Scenario: Traffic update on the edge with a traffic signal
Given the node map
@ -91,3 +244,67 @@ Feature: Car - Handle traffic lights
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
| a | c | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
| c | a | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |
@traffic
Scenario: Traffic update on the edge with a traffic signal - forward
Given the node map
"""
a - b - c
"""
And the ways
| nodes | highway |
| abc | primary |
And the nodes
| node | highway | traffic_signals:direction |
| b | traffic_signals | forward |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,65
2,1,65
"""
And the query options
| annotations | datasources,nodes,speed,duration,weight |
When I route I should get
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
| a | c | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
| c | a | abc,abc | 65 km/h | 22.2,0 | 22.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |
@traffic
Scenario: Traffic update on the edge with a traffic signal - backward
Given the node map
"""
a - b - c
"""
And the ways
| nodes | highway |
| abc | primary |
And the nodes
| node | highway | traffic_signals:direction |
| b | traffic_signals | backward |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,65
2,1,65
"""
And the query options
| annotations | datasources,nodes,speed,duration,weight |
When I route I should get
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
| a | c | abc,abc | 65 km/h | 22.2,0 | 22.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
| c | a | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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);
}

View File

@ -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,

View File

@ -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;

View File

@ -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_

View File

@ -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

View File

@ -5,6 +5,7 @@ api_version = 4
Set = require('lib/set')
Sequence = require('lib/sequence')
Handlers = require("lib/way_handlers")
TrafficSignal = require("lib/traffic_signal")
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
Measure = require("lib/measure")
@ -235,10 +236,7 @@ function process_node(profile, node, result)
end
-- check if node is a traffic light
local tag = node:get_value_by_key("highway")
if tag and "traffic_signals" == tag then
result.traffic_lights = true
end
result.traffic_lights = TrafficSignal.get_value(node)
end
function handle_bicycle_tags(profile,way,result,data)

View File

@ -6,6 +6,7 @@ Set = require('lib/set')
Sequence = require('lib/sequence')
Handlers = require("lib/way_handlers")
Relations = require("lib/relations")
TrafficSignal = require("lib/traffic_signal")
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
Utils = require("lib/utils")
@ -360,10 +361,7 @@ function process_node(profile, node, result, relations)
end
-- check if node is a traffic light
local tag = node:get_value_by_key("highway")
if "traffic_signals" == tag then
result.traffic_lights = true
end
result.traffic_lights = TrafficSignal.get_value(node)
end
function process_way(profile, way, result, relations)

View File

@ -157,6 +157,7 @@ function process_node(profile, node, result)
-- check if node is a traffic light
local tag = node:get_value_by_key("highway")
if "traffic_signals" == tag then
-- Direction should only apply to vehicles
result.traffic_lights = true
end
end

View File

@ -0,0 +1,26 @@
-- Assigns traffic light value to node as defined by
-- include/extractor/traffic_lights.hpp
local TrafficSignal = {}
function TrafficSignal.get_value(node)
local tag = node:get_value_by_key("highway")
if "traffic_signals" == tag then
local direction = node:get_value_by_key("traffic_signals:direction")
if direction then
if "forward" == direction then
return traffic_lights.direction_forward
end
if "backward" == direction then
return traffic_lights.direction_reverse
end
end
-- return traffic_lights.direction_all
return true
end
-- return traffic_lights.none
return false
end
return TrafficSignal

View File

@ -4,6 +4,7 @@
-- Primary road: 36km/h = 36000m/3600s = 100m/10s
-- Secondary road: 18km/h = 18000m/3600s = 100m/20s
-- Tertiary road: 12km/h = 12000m/3600s = 100m/30s
TrafficSignal = require("lib/traffic_signal")
api_version = 4
@ -38,12 +39,9 @@ function setup()
end
function process_node (profile, node, result)
local traffic_signal = node:get_value_by_key("highway")
if traffic_signal and traffic_signal == "traffic_signals" then
result.traffic_lights = true
-- check if node is a traffic light
result.traffic_lights = TrafficSignal.get_value(node)
-- TODO: a way to set the penalty value
end
end
function process_way (profile, way, result)

View File

@ -59,7 +59,7 @@ EdgeBasedGraphFactory::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,
@ -67,7 +67,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
: m_edge_based_node_container(node_data_container), m_connectivity_checksum(0),
m_number_of_edge_based_nodes(0), m_coordinates(coordinates),
m_node_based_graph(node_based_graph), m_barrier_nodes(barrier_nodes),
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
m_traffic_signals(traffic_signals), m_compressed_edge_container(compressed_edge_container),
name_table(name_table), segregated_edges(segregated_edges),
lane_description_map(lane_description_map)
{
@ -623,8 +623,26 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
BOOST_ASSERT(!edge_data1.reversed);
BOOST_ASSERT(!edge_data2.reversed);
// We write out the mapping between the edge-expanded edges and the original nodes.
// Since each edge represents a possible maneuver, external programs can use this to
// quickly perform updates to edge weights in order to penalize certain turns.
// If this edge is 'trivial' -- where the compressed edge corresponds exactly to an
// original OSM segment -- we can pull the turn's preceding node ID directly with
// `node_along_road_entering`;
// otherwise, we need to look up the node immediately preceding the turn from the
// compressed edge container.
const bool isTrivial = m_compressed_edge_container.IsTrivial(node_based_edge_from);
const auto &from_node =
isTrivial ? node_along_road_entering
: m_compressed_edge_container.GetLastEdgeSourceID(node_based_edge_from);
// compute weight and duration penalties
const auto is_traffic_light = m_traffic_lights.count(intersection_node);
// In theory we shouldn't get a directed traffic light on a turn, as it indicates that
// the traffic signal direction was potentially ambiguously annotated on the junction
// node But we'll check anyway.
const auto is_traffic_light = m_traffic_signals.HasSignal(from_node, intersection_node);
const auto is_uturn =
guidance::getTurnDirection(turn_angle) == guidance::DirectionModifier::UTurn;
@ -690,20 +708,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
true,
false};
// We write out the mapping between the edge-expanded edges and the original nodes.
// Since each edge represents a possible maneuver, external programs can use this to
// quickly perform updates to edge weights in order to penalize certain turns.
// If this edge is 'trivial' -- where the compressed edge corresponds exactly to an
// original OSM segment -- we can pull the turn's preceding node ID directly with
// `node_along_road_entering`;
// otherwise, we need to look up the node immediately preceding the turn from the
// compressed edge container.
const bool isTrivial = m_compressed_edge_container.IsTrivial(node_based_edge_from);
const auto &from_node =
isTrivial ? node_along_road_entering
: m_compressed_edge_container.GetLastEdgeSourceID(node_based_edge_from);
const auto &to_node =
m_compressed_edge_container.GetFirstEdgeTargetID(node_based_edge_to);

View File

@ -11,6 +11,7 @@
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
#include "util/for_each_indexed.hpp"
#include "util/for_each_pair.hpp"
#include "util/log.hpp"
#include "util/timing_util.hpp"
@ -413,6 +414,7 @@ void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environme
const auto restriction_ways = IdentifyRestrictionWays();
const auto maneuver_override_ways = IdentifyManeuverOverrideWays();
const auto traffic_signals = IdentifyTrafficSignals();
PrepareNodes();
WriteNodes(writer);
@ -422,6 +424,7 @@ void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environme
WriteEdges(writer);
WriteMetadata(writer);
PrepareTrafficSignals(traffic_signals);
PrepareManeuverOverrides(maneuver_override_ways);
PrepareRestrictions(restriction_ways);
WriteCharData(name_file_name);
@ -911,25 +914,6 @@ void ExtractionContainers::WriteNodes(storage::tar::FileWriter &writer) const
log << "ok, after " << TIMER_SEC(write_nodes) << "s";
}
{
util::UnbufferedLog log;
log << "Writing traffic light nodes ... ";
TIMER_START(write_nodes);
std::vector<NodeID> internal_traffic_signals;
for (const auto osm_id : traffic_signals)
{
const auto node_id = mapExternalToInternalNodeID(
used_node_id_list.begin(), used_node_id_list.end(), osm_id);
if (node_id != SPECIAL_NODEID)
{
internal_traffic_signals.push_back(node_id);
}
}
storage::serialization::write(
writer, "/extractor/traffic_lights", internal_traffic_signals);
log << "ok, after " << TIMER_SEC(write_nodes) << "s";
}
util::Log() << "Processed " << max_internal_node_id << " nodes";
}
@ -983,6 +967,50 @@ ExtractionContainers::ReferencedWays ExtractionContainers::IdentifyManeuverOverr
return maneuver_override_ways;
}
void ExtractionContainers::PrepareTrafficSignals(
const ExtractionContainers::ReferencedTrafficSignals &referenced_traffic_signals)
{
const auto &bidirectional_signal_nodes = referenced_traffic_signals.first;
const auto &unidirectional_signal_segments = referenced_traffic_signals.second;
util::UnbufferedLog log;
log << "Preparing traffic light signals for " << bidirectional_signal_nodes.size()
<< " bidirectional, " << unidirectional_signal_segments.size()
<< " unidirectional nodes ...";
TIMER_START(prepare_traffic_signals);
std::unordered_set<NodeID> bidirectional;
std::unordered_set<std::pair<NodeID, NodeID>, boost::hash<std::pair<NodeID, NodeID>>>
unidirectional;
for (const auto &osm_node : bidirectional_signal_nodes)
{
const auto node_id = mapExternalToInternalNodeID(
used_node_id_list.begin(), used_node_id_list.end(), osm_node);
if (node_id != SPECIAL_NODEID)
{
bidirectional.insert(node_id);
}
}
for (const auto &to_from : unidirectional_signal_segments)
{
const auto to_node_id = mapExternalToInternalNodeID(
used_node_id_list.begin(), used_node_id_list.end(), to_from.first);
const auto from_node_id = mapExternalToInternalNodeID(
used_node_id_list.begin(), used_node_id_list.end(), to_from.second);
if (from_node_id != SPECIAL_NODEID && to_node_id != SPECIAL_NODEID)
{
unidirectional.insert({from_node_id, to_node_id});
}
}
internal_traffic_signals.bidirectional_nodes = std::move(bidirectional);
internal_traffic_signals.unidirectional_segments = std::move(unidirectional);
TIMER_STOP(prepare_traffic_signals);
log << "ok, after " << TIMER_SEC(prepare_traffic_signals) << "s";
}
void ExtractionContainers::PrepareManeuverOverrides(const ReferencedWays &maneuver_override_ways)
{
auto const osm_node_to_internal_nbn = [&](auto const osm_node) {
@ -1163,6 +1191,93 @@ ExtractionContainers::ReferencedWays ExtractionContainers::IdentifyRestrictionWa
return restriction_ways;
}
ExtractionContainers::ReferencedTrafficSignals ExtractionContainers::IdentifyTrafficSignals()
{
util::UnbufferedLog log;
log << "Collecting traffic signal information on " << external_traffic_signals.size()
<< " signals...";
TIMER_START(identify_traffic_signals);
// Temporary store for nodes containing a unidirectional signal.
std::unordered_map<OSMNodeID, TrafficLightClass::Direction> unidirectional_signals;
// For each node that has a unidirectional traffic signal, we store the node(s)
// that lead up to the signal.
std::unordered_multimap<OSMNodeID, OSMNodeID> signal_segments;
std::unordered_set<OSMNodeID> bidirectional_signals;
const auto mark_signals = [&](auto const &traffic_signal) {
if (traffic_signal.second == TrafficLightClass::DIRECTION_FORWARD ||
traffic_signal.second == TrafficLightClass::DIRECTION_REVERSE)
{
unidirectional_signals.insert({traffic_signal.first, traffic_signal.second});
}
else
{
BOOST_ASSERT(traffic_signal.second == TrafficLightClass::DIRECTION_ALL);
bidirectional_signals.insert(traffic_signal.first);
}
};
std::for_each(external_traffic_signals.begin(), external_traffic_signals.end(), mark_signals);
// Extract all the segments that lead up to unidirectional traffic signals.
const auto set_segments = [&](const size_t way_list_idx, auto const & /*unused*/) {
const auto node_start_offset =
used_node_id_list.begin() + way_node_id_offsets[way_list_idx];
const auto node_end_offset =
used_node_id_list.begin() + way_node_id_offsets[way_list_idx + 1];
for (auto node_it = node_start_offset; node_it < node_end_offset; node_it++)
{
const auto sig = unidirectional_signals.find(*node_it);
if (sig != unidirectional_signals.end())
{
if (sig->second == TrafficLightClass::DIRECTION_FORWARD)
{
if (node_it != node_start_offset)
{
// Previous node leads to signal
signal_segments.insert({*node_it, *(node_it - 1)});
}
}
else
{
BOOST_ASSERT(sig->second == TrafficLightClass::DIRECTION_REVERSE);
if (node_it + 1 != node_end_offset)
{
// Next node leads to signal
signal_segments.insert({*node_it, *(node_it + 1)});
}
}
}
}
};
util::for_each_indexed(ways_list.cbegin(), ways_list.cend(), set_segments);
util::for_each_pair(
signal_segments, [](const auto pair_a, const auto pair_b) {
if (pair_a.first == pair_b.first)
{
// If a node is appearing multiple times in this map, then it's ambiguous.
// The node is an intersection and the traffic direction is being use for multiple
// ways. We can't be certain of the original intent. See:
// https://wiki.openstreetmap.org/wiki/Key:traffic_signals:direction
// OSRM will include the signal for all intersecting ways in the specified
// direction, but let's flag this as a concern.
util::Log(logWARNING)
<< "OSM node " << pair_a.first
<< " has a unidirectional traffic signal ambiguously applied to multiple ways";
}
});
TIMER_STOP(identify_traffic_signals);
log << "ok, after " << TIMER_SEC(identify_traffic_signals) << "s";
return {std::move(bidirectional_signals), std::move(signal_segments)};
}
void ExtractionContainers::PrepareRestrictions(const ReferencedWays &restriction_ways)
{

View File

@ -75,7 +75,7 @@ void SetClassNames(const std::vector<std::string> &class_names,
if (!class_names.empty())
{
// add class names that were never used explicitly on a way
// this makes sure we can correctly validate unkown class names later
// this makes sure we can correctly validate unknown class names later
for (const auto &name : class_names)
{
if (!isValidClassName(name))
@ -207,7 +207,8 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
LaneDescriptionMap turn_lane_map;
std::vector<TurnRestriction> turn_restrictions;
std::vector<UnresolvedManeuverOverride> unresolved_maneuver_overrides;
std::tie(turn_lane_map, turn_restrictions, unresolved_maneuver_overrides) =
TrafficSignals traffic_signals;
std::tie(turn_lane_map, turn_restrictions, unresolved_maneuver_overrides, traffic_signals) =
ParseOSMData(scripting_environment, number_of_threads);
// Transform the node-based graph that OSM is based on into an edge-based graph
@ -229,7 +230,8 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
NodeBasedGraphFactory node_based_graph_factory(config.GetPath(".osrm"),
scripting_environment,
turn_restrictions,
unresolved_maneuver_overrides);
unresolved_maneuver_overrides,
traffic_signals);
NameTable name_table;
files::readNames(config.GetPath(".osrm.names"), name_table);
@ -264,7 +266,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
node_based_graph_factory.GetCompressedEdges().PrintStatistics();
const auto &barrier_nodes = node_based_graph_factory.GetBarriers();
const auto &traffic_signals = node_based_graph_factory.GetTrafficSignals();
// stealing the annotation data from the node-based graph
edge_based_nodes_container =
EdgeBasedNodeDataContainer({}, std::move(node_based_graph_factory.GetAnnotationData()));
@ -360,9 +361,11 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
return 0;
}
std::
tuple<LaneDescriptionMap, std::vector<TurnRestriction>, std::vector<UnresolvedManeuverOverride>>
Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
std::tuple<LaneDescriptionMap,
std::vector<TurnRestriction>,
std::vector<UnresolvedManeuverOverride>,
TrafficSignals>
Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
const unsigned number_of_threads)
{
TIMER_START(extracting);
@ -628,7 +631,8 @@ std::
return std::make_tuple(std::move(turn_lane_map),
std::move(extraction_containers.turn_restrictions),
std::move(extraction_containers.internal_maneuver_overrides));
std::move(extraction_containers.internal_maneuver_overrides),
std::move(extraction_containers.internal_traffic_signals));
}
void Extractor::FindComponents(unsigned number_of_edge_based_nodes,
@ -699,7 +703,7 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_signals,
const TrafficSignals &traffic_signals,
const RestrictionGraph &restriction_graph,
const std::unordered_set<EdgeID> &segregated_edges,
const NameTable &name_table,

View File

@ -78,9 +78,9 @@ void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
{
external_memory.barrier_nodes.push_back(id);
}
if (result_node.traffic_lights)
if (result_node.traffic_lights != TrafficLightClass::NONE)
{
external_memory.traffic_signals.push_back(id);
external_memory.external_traffic_signals.push_back({id, result_node.traffic_lights});
}
}

View File

@ -19,8 +19,10 @@ namespace osrm
namespace extractor
{
static constexpr int SECOND_TO_DECISECOND = 10;
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_signals,
const TrafficSignals &traffic_signals,
ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
@ -207,16 +209,20 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
rev_edge_data2.annotation_data, rev_edge_data1.annotation_data);
// Add node penalty when compress edge crosses a traffic signal
const bool has_node_penalty = traffic_signals.find(node_v) != traffic_signals.end();
EdgeDuration node_duration_penalty = MAXIMAL_EDGE_DURATION;
EdgeWeight node_weight_penalty = INVALID_EDGE_WEIGHT;
if (has_node_penalty)
const bool has_forward_signal = traffic_signals.HasSignal(node_u, node_v);
const bool has_reverse_signal = traffic_signals.HasSignal(node_w, node_v);
EdgeDuration forward_node_duration_penalty = MAXIMAL_EDGE_DURATION;
EdgeWeight forward_node_weight_penalty = INVALID_EDGE_WEIGHT;
EdgeDuration reverse_node_duration_penalty = MAXIMAL_EDGE_DURATION;
EdgeWeight reverse_node_weight_penalty = INVALID_EDGE_WEIGHT;
if (has_forward_signal || has_reverse_signal)
{
// we cannot handle this as node penalty, if it depends on turn direction
if (fwd_edge_data1.flags.restricted != fwd_edge_data2.flags.restricted)
continue;
// generate an artifical turn for the turn penalty generation
// generate an artificial turn for the turn penalty generation
std::vector<ExtractionTurnLeg> roads_on_the_right;
std::vector<ExtractionTurnLeg> roads_on_the_left;
ExtractionTurn extraction_turn(0,
@ -245,8 +251,24 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
roads_on_the_right,
roads_on_the_left);
scripting_environment.ProcessTurn(extraction_turn);
node_duration_penalty = extraction_turn.duration * 10;
node_weight_penalty = extraction_turn.weight * weight_multiplier;
auto update_direction_penalty =
[&extraction_turn, weight_multiplier](bool signal,
EdgeDuration &duration_penalty,
EdgeWeight &weight_penalty) {
if (signal)
{
duration_penalty = extraction_turn.duration * SECOND_TO_DECISECOND;
weight_penalty = extraction_turn.weight * weight_multiplier;
}
};
update_direction_penalty(has_forward_signal,
forward_node_duration_penalty,
forward_node_weight_penalty);
update_direction_penalty(has_reverse_signal,
reverse_node_duration_penalty,
reverse_node_weight_penalty);
}
// Get weights before graph is modified
@ -278,27 +300,37 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
BOOST_ASSERT(0 != reverse_weight1);
BOOST_ASSERT(0 != reverse_weight2);
// add weight of e2's to e1
graph.GetEdgeData(forward_e1).weight += forward_weight2;
graph.GetEdgeData(reverse_e1).weight += reverse_weight2;
// add duration of e2's to e1
graph.GetEdgeData(forward_e1).duration += forward_duration2;
graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
// add distance of e2's to e1
graph.GetEdgeData(forward_e1).distance += forward_distance2;
graph.GetEdgeData(reverse_e1).distance += reverse_distance2;
if (node_weight_penalty != INVALID_EDGE_WEIGHT &&
node_duration_penalty != MAXIMAL_EDGE_DURATION)
auto apply_e2_to_e1 = [&graph](EdgeID edge,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance,
EdgeDuration &duration_penalty,
EdgeWeight &weight_penalty) {
auto &edge_data = graph.GetEdgeData(edge);
edge_data.weight += weight;
edge_data.duration += duration;
edge_data.distance += distance;
if (weight_penalty != INVALID_EDGE_WEIGHT &&
duration_penalty != MAXIMAL_EDGE_DURATION)
{
graph.GetEdgeData(forward_e1).weight += node_weight_penalty;
graph.GetEdgeData(reverse_e1).weight += node_weight_penalty;
graph.GetEdgeData(forward_e1).duration += node_duration_penalty;
graph.GetEdgeData(reverse_e1).duration += node_duration_penalty;
edge_data.weight += weight_penalty;
edge_data.duration += duration_penalty;
// Note: no penalties for distances
}
};
apply_e2_to_e1(forward_e1,
forward_weight2,
forward_duration2,
forward_distance2,
forward_node_weight_penalty,
forward_node_duration_penalty);
apply_e2_to_e1(reverse_e1,
reverse_weight2,
reverse_duration2,
reverse_distance2,
reverse_node_weight_penalty,
reverse_node_duration_penalty);
// extend e1's to targets of e2's
graph.SetTarget(forward_e1, node_w);
@ -311,6 +343,25 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
// update any involved turn relations
turn_path_compressor.Compress(node_u, node_v, node_w);
// Forward and reversed compressed edge lengths need to match.
// Set a dummy empty penalty weight if opposite value exists.
auto set_dummy_penalty = [](EdgeWeight &weight_penalty,
EdgeDuration &duration_penalty,
EdgeWeight &other_weight_penalty) {
if (weight_penalty == INVALID_EDGE_WEIGHT &&
other_weight_penalty != INVALID_EDGE_WEIGHT)
{
weight_penalty = 0;
duration_penalty = 0;
}
};
set_dummy_penalty(forward_node_weight_penalty,
forward_node_duration_penalty,
reverse_node_weight_penalty);
set_dummy_penalty(reverse_node_weight_penalty,
reverse_node_duration_penalty,
forward_node_weight_penalty);
// store compressed geometry in container
geometry_compressor.CompressEdge(forward_e1,
forward_e2,
@ -320,8 +371,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
forward_weight2,
forward_duration1,
forward_duration2,
node_weight_penalty,
node_duration_penalty);
forward_node_weight_penalty,
forward_node_duration_penalty);
geometry_compressor.CompressEdge(reverse_e1,
reverse_e2,
node_v,
@ -330,8 +381,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
reverse_weight2,
reverse_duration1,
reverse_duration2,
node_weight_penalty,
node_duration_penalty);
reverse_node_weight_penalty,
reverse_node_duration_penalty);
}
}
}

View File

@ -19,10 +19,11 @@ 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)
{
LoadDataFromFile(input_file);
Compress(scripting_environment, turn_restrictions, maneuver_overrides);
Compress(scripting_environment, turn_restrictions, maneuver_overrides, traffic_signals);
CompressGeometry();
CompressAnnotationData();
}
@ -31,16 +32,10 @@ NodeBasedGraphFactory::NodeBasedGraphFactory(
void NodeBasedGraphFactory::LoadDataFromFile(const boost::filesystem::path &input_file)
{
auto barriers_iter = inserter(barriers, end(barriers));
auto traffic_signals_iter = inserter(traffic_signals, end(traffic_signals));
std::vector<NodeBasedEdge> edge_list;
files::readRawNBGraph(input_file,
barriers_iter,
traffic_signals_iter,
coordinates,
osm_node_ids,
edge_list,
annotation_data);
files::readRawNBGraph(
input_file, barriers_iter, coordinates, osm_node_ids, edge_list, annotation_data);
const auto number_of_node_based_nodes = coordinates.size();
if (edge_list.empty())
@ -80,7 +75,8 @@ void NodeBasedGraphFactory::LoadDataFromFile(const boost::filesystem::path &inpu
void NodeBasedGraphFactory::Compress(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides)
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
const TrafficSignals &traffic_signals)
{
GraphCompressor graph_compressor;
graph_compressor.Compress(barriers,

View File

@ -285,9 +285,39 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
return get_location_tag(context, node.location(), key);
});
context.state.new_usertype<ExtractionNode>("ResultNode",
context.state.new_enum("traffic_lights",
"none",
extractor::TrafficLightClass::NONE,
"direction_all",
extractor::TrafficLightClass::DIRECTION_ALL,
"direction_forward",
extractor::TrafficLightClass::DIRECTION_FORWARD,
"direction_reverse",
extractor::TrafficLightClass::DIRECTION_REVERSE);
context.state.new_usertype<ExtractionNode>(
"ResultNode",
"traffic_lights",
&ExtractionNode::traffic_lights,
sol::property([](const ExtractionNode &node) { return node.traffic_lights; },
[](ExtractionNode &node, const sol::object &obj) {
if (obj.is<bool>())
{
// The old approach of assigning a boolean traffic light
// state to the node is converted to the class enum
// TODO: Make a breaking API change and remove this option.
bool val = obj.as<bool>();
node.traffic_lights = (val) ? TrafficLightClass::DIRECTION_ALL
: TrafficLightClass::NONE;
return;
}
BOOST_ASSERT(obj.is<TrafficLightClass::Direction>());
{
TrafficLightClass::Direction val =
obj.as<TrafficLightClass::Direction>();
node.traffic_lights = val;
}
}),
"barrier",
&ExtractionNode::barrier);

View File

@ -44,7 +44,7 @@ std::size_t loadGraph(const std::string &path,
auto nop = boost::make_function_output_iterator([](auto) {});
extractor::files::readRawNBGraph(
path, nop, nop, coordinate_list, osm_node_ids, edge_list, annotation_data);
path, nop, coordinate_list, osm_node_ids, edge_list, annotation_data);
// Building a node-based graph
for (const auto &input_edge : edge_list)

View File

@ -9,7 +9,6 @@
#include <boost/test/unit_test.hpp>
#include <iostream>
#include <unordered_set>
#include <vector>
@ -66,7 +65,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
GraphCompressor compressor;
std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights;
TrafficSignals traffic_lights;
std::vector<TurnRestriction> restrictions;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
CompressedEdgeContainer container;
@ -112,7 +111,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
GraphCompressor compressor;
std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights;
TrafficSignals traffic_lights;
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
@ -175,7 +174,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
GraphCompressor compressor;
std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights;
TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
@ -218,7 +217,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
GraphCompressor compressor;
std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights;
TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(2);
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
@ -256,7 +255,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
GraphCompressor compressor;
std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights;
TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;

View File

@ -19,7 +19,7 @@ using Graph = util::NodeBasedDynamicGraph;
BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
{
std::unordered_set<NodeID> barrier_nodes{6};
std::unordered_set<NodeID> traffic_lights;
TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations{
{EMPTY_NAMEID, 0, INAVLID_CLASS_DATA, TRAVEL_MODE_DRIVING, false},
{EMPTY_NAMEID, 1, INAVLID_CLASS_DATA, TRAVEL_MODE_DRIVING, false}};
@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
{
std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights;
TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations;
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
@ -259,7 +259,7 @@ BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
BOOST_AUTO_TEST_CASE(skip_degree_two_nodes)
{
std::unordered_set<NodeID> barrier_nodes{1};
std::unordered_set<NodeID> traffic_lights{2};
TrafficSignals traffic_lights = {{2}, {}};
std::vector<NodeBasedEdgeAnnotation> annotations(1);
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;