diff --git a/CHANGELOG.md b/CHANGELOG.md index 0241464a0..ecb4109c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/features/car/traffic_light_penalties.feature b/features/car/traffic_light_penalties.feature index e8961abb1..37bbad3a7 100644 --- a/features/car/traffic_light_penalties.feature +++ b/features/car/traffic_light_penalties.feature @@ -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 | diff --git a/include/extractor/edge_based_graph_factory.hpp b/include/extractor/edge_based_graph_factory.hpp index 01a3122ea..9dc0cadf2 100644 --- a/include/extractor/edge_based_graph_factory.hpp +++ b/include/extractor/edge_based_graph_factory.hpp @@ -23,6 +23,7 @@ #include "util/typedefs.hpp" #include "storage/io.hpp" +#include "traffic_signals.hpp" #include #include @@ -68,7 +69,7 @@ class EdgeBasedGraphFactory EdgeBasedNodeDataContainer &node_data_container, const CompressedEdgeContainer &compressed_edge_container, const std::unordered_set &barrier_nodes, - const std::unordered_set &traffic_lights, + const TrafficSignals &traffic_signals, const std::vector &coordinates, const NameTable &name_table, const std::unordered_set &segregated_edges, @@ -134,7 +135,7 @@ class EdgeBasedGraphFactory const util::NodeBasedDynamicGraph &m_node_based_graph; const std::unordered_set &m_barrier_nodes; - const std::unordered_set &m_traffic_lights; + const TrafficSignals &m_traffic_signals; const CompressedEdgeContainer &m_compressed_edge_container; const NameTable &name_table; diff --git a/include/extractor/extraction_containers.hpp b/include/extractor/extraction_containers.hpp index a8b8f7767..b630763fb 100644 --- a/include/extractor/extraction_containers.hpp +++ b/include/extractor/extraction_containers.hpp @@ -8,8 +8,11 @@ #include "extractor/scripting_environment.hpp" #include "storage/tar_fwd.hpp" +#include "traffic_lights.hpp" +#include "traffic_signals.hpp" #include +#include namespace osrm { @@ -25,15 +28,19 @@ namespace extractor class ExtractionContainers { using ReferencedWays = std::unordered_map; + using ReferencedTrafficSignals = + std::pair, std::unordered_multimap>; // 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; using WayIDVector = std::vector; using WayNodeIDOffsets = std::vector; + using InputTrafficSignal = std::pair; std::vector barrier_nodes; - std::vector 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 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, diff --git a/include/extractor/extraction_node.hpp b/include/extractor/extraction_node.hpp index 065ff4a3f..9a146d4d3 100644 --- a/include/extractor/extraction_node.hpp +++ b/include/extractor/extraction_node.hpp @@ -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 diff --git a/include/extractor/extractor.hpp b/include/extractor/extractor.hpp index 070a3b4ef..fc103fe69 100644 --- a/include/extractor/extractor.hpp +++ b/include/extractor/extractor.hpp @@ -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, - std::vector> + std::vector, + TrafficSignals> ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads); EdgeID BuildEdgeExpandedGraph( @@ -73,7 +75,7 @@ class Extractor const std::vector &coordinates, const CompressedEdgeContainer &compressed_edge_container, const std::unordered_set &barrier_nodes, - const std::unordered_set &traffic_lights, + const TrafficSignals &traffic_signals, const RestrictionGraph &restriction_graph, const std::unordered_set &segregated_edges, const NameTable &name_table, diff --git a/include/extractor/files.hpp b/include/extractor/files.hpp index 6c0445e9b..5c71e9de9 100644 --- a/include/extractor/files.hpp +++ b/include/extractor/files.hpp @@ -444,10 +444,9 @@ inline void readConditionalRestrictions(const boost::filesystem::path &path, } // reads .osrm file which is a temporary file of osrm-extract -template +template void readRawNBGraph(const boost::filesystem::path &path, BarrierOutIter barriers, - TrafficSignalsOutIter traffic_signals, std::vector &coordinates, PackedOSMIDsT &osm_node_ids, std::vector &edge_list, @@ -471,8 +470,6 @@ void readRawNBGraph(const boost::filesystem::path &path, reader.ReadStreaming("/extractor/barriers", barriers); - reader.ReadStreaming("/extractor/traffic_lights", traffic_signals); - storage::serialization::read(reader, "/extractor/edges", edge_list); storage::serialization::read(reader, "/extractor/annotations", annotations); } diff --git a/include/extractor/graph_compressor.hpp b/include/extractor/graph_compressor.hpp index 9e9ddd036..1b6d8159a 100644 --- a/include/extractor/graph_compressor.hpp +++ b/include/extractor/graph_compressor.hpp @@ -4,6 +4,7 @@ #include "extractor/scripting_environment.hpp" #include "util/typedefs.hpp" +#include "traffic_signals.hpp" #include "util/node_based_graph.hpp" #include @@ -25,7 +26,7 @@ class GraphCompressor public: void Compress(const std::unordered_set &barrier_nodes, - const std::unordered_set &traffic_lights, + const TrafficSignals &traffic_signals, ScriptingEnvironment &scripting_environment, std::vector &turn_restrictions, std::vector &maneuver_overrides, diff --git a/include/extractor/node_based_graph_factory.hpp b/include/extractor/node_based_graph_factory.hpp index e3fc39583..9e07513c2 100644 --- a/include/extractor/node_based_graph_factory.hpp +++ b/include/extractor/node_based_graph_factory.hpp @@ -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 &turn_restrictions, - std::vector &maneuver_overrides); + std::vector &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 &turn_restrictions, - std::vector &maneuver_overrides); + std::vector &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 barriers; - std::unordered_set traffic_signals; std::vector coordinates; diff --git a/include/extractor/traffic_lights.hpp b/include/extractor/traffic_lights.hpp new file mode 100644 index 000000000..0c8aa6d00 --- /dev/null +++ b/include/extractor/traffic_lights.hpp @@ -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_ diff --git a/include/extractor/traffic_signals.hpp b/include/extractor/traffic_signals.hpp new file mode 100644 index 000000000..36913092c --- /dev/null +++ b/include/extractor/traffic_signals.hpp @@ -0,0 +1,28 @@ +#ifndef OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP +#define OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP + +#include "util/typedefs.hpp" +#include + +#include + +namespace osrm +{ +namespace extractor +{ + +struct TrafficSignals +{ + std::unordered_set bidirectional_nodes; + std::unordered_set, boost::hash>> + 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 diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 58740db48..07032206e 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -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) diff --git a/profiles/car.lua b/profiles/car.lua index fddae14d7..770805962 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -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) diff --git a/profiles/foot.lua b/profiles/foot.lua index ea24706c8..978648954 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -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 diff --git a/profiles/lib/traffic_signal.lua b/profiles/lib/traffic_signal.lua new file mode 100644 index 000000000..8356e3500 --- /dev/null +++ b/profiles/lib/traffic_signal.lua @@ -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 + diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 691e57617..a796be21f 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -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 - -- TODO: a way to set the penalty value - end + -- check if node is a traffic light + result.traffic_lights = TrafficSignal.get_value(node) + -- TODO: a way to set the penalty value end function process_way (profile, way, result) diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index 6e15d15e9..a0a8561b7 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -59,7 +59,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( EdgeBasedNodeDataContainer &node_data_container, const CompressedEdgeContainer &compressed_edge_container, const std::unordered_set &barrier_nodes, - const std::unordered_set &traffic_lights, + const TrafficSignals &traffic_signals, const std::vector &coordinates, const NameTable &name_table, const std::unordered_set &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); diff --git a/src/extractor/extraction_containers.cpp b/src/extractor/extraction_containers.cpp index 9ec1b2887..4730441b1 100644 --- a/src/extractor/extraction_containers.cpp +++ b/src/extractor/extraction_containers.cpp @@ -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 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 bidirectional; + std::unordered_set, boost::hash>> + 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 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 signal_segments; + + std::unordered_set 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) { diff --git a/src/extractor/extractor.cpp b/src/extractor/extractor.cpp index 8e94344c1..388ee866d 100644 --- a/src/extractor/extractor.cpp +++ b/src/extractor/extractor.cpp @@ -75,7 +75,7 @@ void SetClassNames(const std::vector &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 turn_restrictions; std::vector 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,10 +361,12 @@ int Extractor::run(ScriptingEnvironment &scripting_environment) return 0; } -std:: - tuple, std::vector> - Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment, - const unsigned number_of_threads) +std::tuple, + std::vector, + 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 &coordinates, const CompressedEdgeContainer &compressed_edge_container, const std::unordered_set &barrier_nodes, - const std::unordered_set &traffic_signals, + const TrafficSignals &traffic_signals, const RestrictionGraph &restriction_graph, const std::unordered_set &segregated_edges, const NameTable &name_table, diff --git a/src/extractor/extractor_callbacks.cpp b/src/extractor/extractor_callbacks.cpp index 6ecfe83e5..7cecd763e 100644 --- a/src/extractor/extractor_callbacks.cpp +++ b/src/extractor/extractor_callbacks.cpp @@ -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}); } } diff --git a/src/extractor/graph_compressor.cpp b/src/extractor/graph_compressor.cpp index d38266bd0..000985564 100644 --- a/src/extractor/graph_compressor.cpp +++ b/src/extractor/graph_compressor.cpp @@ -19,8 +19,10 @@ namespace osrm namespace extractor { +static constexpr int SECOND_TO_DECISECOND = 10; + void GraphCompressor::Compress(const std::unordered_set &barrier_nodes, - const std::unordered_set &traffic_signals, + const TrafficSignals &traffic_signals, ScriptingEnvironment &scripting_environment, std::vector &turn_restrictions, std::vector &maneuver_overrides, @@ -207,16 +209,20 @@ void GraphCompressor::Compress(const std::unordered_set &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 roads_on_the_right; std::vector roads_on_the_left; ExtractionTurn extraction_turn(0, @@ -245,8 +251,24 @@ void GraphCompressor::Compress(const std::unordered_set &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 &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; + 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) + { + edge_data.weight += weight_penalty; + edge_data.duration += duration_penalty; + // Note: no penalties for distances + } + }; - // 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) - { - 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; - // 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 &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 &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 &barrier_nodes, reverse_weight2, reverse_duration1, reverse_duration2, - node_weight_penalty, - node_duration_penalty); + reverse_node_weight_penalty, + reverse_node_duration_penalty); } } } diff --git a/src/extractor/node_based_graph_factory.cpp b/src/extractor/node_based_graph_factory.cpp index 51473797d..887523de9 100644 --- a/src/extractor/node_based_graph_factory.cpp +++ b/src/extractor/node_based_graph_factory.cpp @@ -19,10 +19,11 @@ NodeBasedGraphFactory::NodeBasedGraphFactory( const boost::filesystem::path &input_file, ScriptingEnvironment &scripting_environment, std::vector &turn_restrictions, - std::vector &maneuver_overrides) + std::vector &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 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 &turn_restrictions, - std::vector &maneuver_overrides) + std::vector &maneuver_overrides, + const TrafficSignals &traffic_signals) { GraphCompressor graph_compressor; graph_compressor.Compress(barriers, diff --git a/src/extractor/scripting_environment_lua.cpp b/src/extractor/scripting_environment_lua.cpp index 744140022..dca80fc44 100644 --- a/src/extractor/scripting_environment_lua.cpp +++ b/src/extractor/scripting_environment_lua.cpp @@ -285,11 +285,41 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context) return get_location_tag(context, node.location(), key); }); - context.state.new_usertype("ResultNode", - "traffic_lights", - &ExtractionNode::traffic_lights, - "barrier", - &ExtractionNode::barrier); + 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( + "ResultNode", + "traffic_lights", + sol::property([](const ExtractionNode &node) { return node.traffic_lights; }, + [](ExtractionNode &node, const sol::object &obj) { + if (obj.is()) + { + // 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(); + node.traffic_lights = (val) ? TrafficLightClass::DIRECTION_ALL + : TrafficLightClass::NONE; + return; + } + + BOOST_ASSERT(obj.is()); + { + TrafficLightClass::Direction val = + obj.as(); + node.traffic_lights = val; + } + }), + "barrier", + &ExtractionNode::barrier); context.state.new_usertype( "RoadClassification", diff --git a/src/tools/components.cpp b/src/tools/components.cpp index dcd051518..1b43cc215 100644 --- a/src/tools/components.cpp +++ b/src/tools/components.cpp @@ -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) diff --git a/unit_tests/extractor/graph_compressor.cpp b/unit_tests/extractor/graph_compressor.cpp index e49932afb..559bde7d6 100644 --- a/unit_tests/extractor/graph_compressor.cpp +++ b/unit_tests/extractor/graph_compressor.cpp @@ -9,7 +9,6 @@ #include -#include #include #include @@ -66,7 +65,7 @@ BOOST_AUTO_TEST_CASE(long_road_test) GraphCompressor compressor; std::unordered_set barrier_nodes; - std::unordered_set traffic_lights; + TrafficSignals traffic_lights; std::vector restrictions; std::vector annotations(1); CompressedEdgeContainer container; @@ -112,7 +111,7 @@ BOOST_AUTO_TEST_CASE(loop_test) GraphCompressor compressor; std::unordered_set barrier_nodes; - std::unordered_set traffic_lights; + TrafficSignals traffic_lights; std::vector restrictions; CompressedEdgeContainer container; std::vector annotations(1); @@ -175,7 +174,7 @@ BOOST_AUTO_TEST_CASE(t_intersection) GraphCompressor compressor; std::unordered_set barrier_nodes; - std::unordered_set traffic_lights; + TrafficSignals traffic_lights; std::vector annotations(1); std::vector restrictions; CompressedEdgeContainer container; @@ -218,7 +217,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes) GraphCompressor compressor; std::unordered_set barrier_nodes; - std::unordered_set traffic_lights; + TrafficSignals traffic_lights; std::vector annotations(2); std::vector restrictions; CompressedEdgeContainer container; @@ -256,7 +255,7 @@ BOOST_AUTO_TEST_CASE(direction_changes) GraphCompressor compressor; std::unordered_set barrier_nodes; - std::unordered_set traffic_lights; + TrafficSignals traffic_lights; std::vector annotations(1); std::vector restrictions; CompressedEdgeContainer container; diff --git a/unit_tests/extractor/intersection_analysis_tests.cpp b/unit_tests/extractor/intersection_analysis_tests.cpp index 979f60ddd..40cdece81 100644 --- a/unit_tests/extractor/intersection_analysis_tests.cpp +++ b/unit_tests/extractor/intersection_analysis_tests.cpp @@ -19,7 +19,7 @@ using Graph = util::NodeBasedDynamicGraph; BOOST_AUTO_TEST_CASE(simple_intersection_connectivity) { std::unordered_set barrier_nodes{6}; - std::unordered_set traffic_lights; + TrafficSignals traffic_lights; std::vector 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 barrier_nodes; - std::unordered_set traffic_lights; + TrafficSignals traffic_lights; std::vector annotations; std::vector 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 barrier_nodes{1}; - std::unordered_set traffic_lights{2}; + TrafficSignals traffic_lights = {{2}, {}}; std::vector annotations(1); std::vector restrictions; CompressedEdgeContainer container;