diff --git a/CHANGELOG.md b/CHANGELOG.md
index fddc909d92c..3f36b733ab0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
# Unreleased
- Changes from 5.27.1
- Features
+ - ADDED: Add generic support for obstacles [#7130](https://github.com/Project-OSRM/osrm-backend/pull/7130)
- ADDED: Route pedestrians over highway=platform [#6993](https://github.com/Project-OSRM/osrm-backend/pull/6993)
- REMOVED: Remove all core-CH left-overs [#6920](https://github.com/Project-OSRM/osrm-backend/pull/6920)
- ADDED: Add support for a keepalive_timeout flag. [#6674](https://github.com/Project-OSRM/osrm-backend/pull/6674)
diff --git a/docs/profiles.md b/docs/profiles.md
index c66eb81c299..b6c29056899 100644
--- a/docs/profiles.md
+++ b/docs/profiles.md
@@ -1,7 +1,7 @@
# OSRM profiles
OSRM supports "profiles". Profiles representing routing behavior for different transport modes like car, bike and foot. You can also create profiles for variations like a fastest/shortest car profile or fastest/safest/greenest bicycles profile.
- A profile describes whether or not it's possible to route along a particular type of way, whether we can pass a particular node, and how quickly we'll be traveling when we do. This feeds into the way the routing graph is created and thus influences the output routes.
+A profile describes whether or not it's possible to route along a particular type of way, whether we can pass a particular node, and how quickly we'll be traveling when we do. This feeds into the way the routing graph is created and thus influences the output routes.
## Available profiles
Out-of-the-box OSRM comes with profiles for car, bicycle and foot. You can easily modify these or create new ones if you like.
@@ -116,7 +116,7 @@ suffix_list | Set | List of name suffixes
relation_types | Sequence | Determines which relations should be cached for processing in this profile. It contains relations types
### process_node(profile, node, result, relations)
-Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay.
+Process an OSM node to determine whether this node is an obstacle, if it can be passed at all and whether passing it incurs a delay.
Argument | Description
---------|-------------------------------------------------------
@@ -126,12 +126,177 @@ result | The output that you will modify.
relations| Storage of relations to access relations, where `node` is a member.
The following attributes can be set on `result`:
+(Note: for new code use the `obstacle_map`.
Attribute | Type | Notes
----------------|---------|---------------------------------------------------------
barrier | Boolean | Is it an impassable barrier?
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?
+### Obstacle
+A user type that represents an obstacle on the road or a place where you can turn
+around.
+
+This may be a completely impassable obstacle like a barrier, a temporary obstacle like a
+traffic light or a stop sign, or an obstacle that just slows you down like a
+traffic_calming. The obstacle may be present in both directions or in one direction
+only.
+
+This also represents a good turning point like a mini_roundabout, turning_loop, or
+turning_circle.
+
+An object of this type is immutable once constructed.
+
+```lua
+local obs = Obstacle.new(
+ obstacle_type.traffic_signals,
+ obstacle_direction.forward,
+ 2.5,
+ 0
+)
+assert(obs.duration == 2.5)
+```
+
+Member | Mode | Type | Notes
+----------|-----------|--------------------|----------------------------------
+type | read-only | obstacle_type | eg. `obstacle_type.barrier`
+direction | read-only | obstacle_direction | eg. `obstacle_direction.forward`
+duration | read-only | float | The expected delay in seconds
+weight | read-only | float | The weight
+
+#### obstacle_type
+An enum with the following keys:
+
+Keys |
+----------------|
+none |
+barrier |
+traffic_signals |
+stop |
+give_way |
+crossing |
+traffic_calming |
+mini_roundabout |
+turning_loop |
+turning_circle |
+
+#### obstacle_direction
+An enum with the following keys:
+
+Keys |
+---------|
+none |
+forward |
+backward |
+both |
+
+### obstacle_map
+A global user type. It stores obstacles.
+
+The canonical workflow is: to store obstacles in `process_node()` and retrieve them in
+`process_turn()`.
+
+Note: In the course of processing, between the `process_node()` stage and the
+`process_turn()` stage, the extractor switches from using OSM nodes to using
+internal nodes. Both types have different ids. You can only store OSM nodes and only
+retrieve internal nodes. This implies that, in `process_node()`, you cannot retrieve an
+obstacle you have just stored.
+
+#### obstacle_map:add(node, obstacle)
+Call this function inside `process_node()` to register an obstacle on a node. You can
+register as many different obstacles as you wish on any given node. It is your
+responsibility to register the same obstacle only once.
+
+In a following step -- likely in `process_turn()` -- you can retrieve all obstacles
+registered at any given node. This function works with OSM nodes.
+
+Argument | Type | Notes
+---------|----------|--------------------------------------------
+node | OSMNode | The same node as passed to `process_node`.
+obstacle | Obstacle | The obstacle
+
+Usage example:
+
+```lua
+function process_node(profile, node, result, relations)
+ ...
+ obstacle_map:add(node,
+ Obstacle.new(
+ obstacle_type.traffic_signal,
+ obstacle_direction.forward,
+ 2, 0))
+end
+```
+
+#### obstacle_map:any(from, to, type)
+Return true if there are any obstacles at node `to` when coming from node
+`from` and having the type `type`.
+
+You will likely call this function inside `process_turn()`.
+Note that this works only with internal nodes, not with OSM nodes.
+
+```lua
+bool obstacle_map:any(to)
+bool obstacle_map:any(from, to)
+bool obstacle_map:any(from, to, type)
+```
+
+Argument | Type | Notes
+---------|---------------|-------------------------------------------------------------------------------------
+from | Node | The leading node. Optional.
+to | Node | The node with the obstacle.
+type | obstacle_type | The obstacle type. Defaults to all types. May be a bitwise-or combination of types.
+returns | bool | True if there are any obstacles satisfiying the given criteria.
+
+Usage examples:
+
+```lua
+function process_turn(profile, turn)
+ if obstacle_map:any(turn.via) then
+ ...
+ end
+ if obstacle_map:any(turn.from, turn.via, obstacle_type.traffic_signal) then
+ turn.duration = turn.duration + 2
+ end
+end
+```
+
+#### obstacle_map:get(from, to, type)
+This function retrieves all registered obstacles at node `to` when coming from the node
+`from` and having the type `type`.
+
+You will likely call this function inside `process_turn()`.
+Note that this works only with internal nodes, not with OSM nodes.
+
+```lua
+obstacle_map:get(to)
+obstacle_map:get(from, to)
+obstacle_map:get(from, to, type)
+```
+
+Argument | Type | Notes
+---------|---------------|-------------------------------------------------------------------------------------
+from | Node | The leading node. Optional.
+to | Node | The node with the obstacle.
+type | obstacle_type | The obstacle type. Defaults to all types. May be a bitwise-or combination of types.
+returns | table | A table of `Obstacle`s.
+
+Usage examples:
+
+```lua
+function process_turn(profile, turn)
+ for _, obs in pairs(obstacle_map:get(turn.via)) do
+ if obs.type == obstacle_type.barrier then
+ turn.duration = turn.duration + obs.duration
+ end
+ end
+ for _, obs in pairs(obstacle_map:get(
+ turn.from, turn.via, obstacle_type.traffic_signal)) do
+ turn.duration = turn.duration + obs.duration
+ end
+end
+```
+
### process_way(profile, way, result, relations)
Given an OpenStreetMap way, the `process_way` function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash.
@@ -233,14 +398,24 @@ target_highway_turn_classification | Read | Integer |
target_access_turn_classification | Read | Integer | Classification based on access tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15))
target_speed | Read | Integer | Speed on this target road in km/h
target_priority_class | Read | Enum | The type of road priority class of the target. Defined in `include/extractor/road_classification.hpp`
+from | Read | NodeID | The leading node
+via | Read | NodeID | The intersection node
+to | Read | NodeID | The trailing node
+source_road | Read | ExtractionTurnLeg | The incoming road
+target_road | Read | ExtractionTurnLeg | The outgoing road
roads_on_the_right | Read | Vector<ExtractionTurnLeg> | Vector with information about other roads on the right of the turn that are also connected at the intersection
roads_on_the_left | Read | Vector<ExtractionTurnLeg> | Vector with information about other roads on the left of the turn that are also connected at the intersection. If turn is a u turn, this is empty.
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
-#### `roads_on_the_right` and `roads_on_the_left`
-The information of `roads_on_the_right` and `roads_on_the_left` that can be read are as follows:
+#### `from`, `via`, and `to`
+Use these node IDs to retrieve obstacles. See: `obstacle_map:get`.
+
+#### `source_road`, `target_road`, `roads_on_the_right`, and `roads_on_the_left`
+
+The information of `source_road`, `target_road`, `roads_on_the_right`, and
+`roads_on_the_left` that can be read are as follows:
Attribute | Read/write? | Type | Notes
--------------------- | ------------- | --------- | ------------------------------------------------------
@@ -252,6 +427,7 @@ number_of_lanes | Read | Integer | How many lanes does th
highway_turn_classification | Read | Integer | Classification based on highway tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15)
access_turn_classification | Read | Integer | Classification based on access tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15)
speed | Read | Integer | Speed on this road in km/h
+distance | Read | Double | The length of the road edge
priority_class | Read | Enum | The type of road priority class of the leg. Defined in `include/extractor/road_classification.hpp`
is_incoming | Read | Boolean | Is the road an incoming road of the intersection
is_outgoing | Read | Boolean | Is the road an outgoing road of the intersection
diff --git a/docs/src/content.js b/docs/src/content.js
index 6e7844e1a29..c3eaf359d36 100644
--- a/docs/src/content.js
+++ b/docs/src/content.js
@@ -11,6 +11,4 @@ var fs = require('fs');
*/
module.exports =
'# HTTP API\n' +
- fs.readFileSync('./content/http.md', 'utf8') + '\n'+
- '# libosrm C++ API\n' +
- fs.readFileSync('./content/libosrm.md', 'utf8') + '\n';
+ fs.readFileSync('./content/http.md', 'utf8') + '\n';
diff --git a/features/car/obstacle_penalties.feature b/features/car/obstacle_penalties.feature
new file mode 100644
index 00000000000..1b733933004
--- /dev/null
+++ b/features/car/obstacle_penalties.feature
@@ -0,0 +1,227 @@
+@routing @car @obstacle
+Feature: Car - Handle obstacle penalties
+
+ Background:
+ Given the profile "car"
+
+ Scenario: Car - Give-Way signs
+ Given the node map
+ """
+ a-b-c d-e-f g-h-i j-k-l m-n-o
+
+ """
+
+ And the ways
+ | nodes | highway |
+ | abc | primary |
+ | def | primary |
+ | ghi | primary |
+ | jkl | primary |
+ | mno | primary |
+
+ And the nodes
+ | node | highway | direction |
+ | e | give_way | |
+ | h | give_way | forward |
+ | k | give_way | backward |
+ | n | give_way | both |
+
+ When I route I should get
+ | from | to | time | # |
+ | a | c | 11s | |
+ | c | a | 11s | |
+ | d | f | 12s | give-way sign |
+ | f | d | 12s | give-way sign |
+ | g | i | 12s | give-way sign |
+ | i | g | 11s | |
+ | j | l | 11s | |
+ | l | j | 12s | give-way sign |
+ | m | o | 12s | give-way sign |
+ | o | m | 12s | give-way sign |
+
+
+ Scenario: Car - Stop signs
+ Given the node map
+ """
+ a-b-c d-e-f g-h-i j-k-l m-n-o
+
+ """
+
+ And the ways
+ | nodes | highway |
+ | abc | primary |
+ | def | primary |
+ | ghi | primary |
+ | jkl | primary |
+ | mno | primary |
+
+ And the nodes
+ | node | highway | direction |
+ | e | stop | |
+ | h | stop | forward |
+ | k | stop | backward |
+ | n | stop | both |
+
+ When I route I should get
+ | from | to | time | # |
+ | a | c | 11s | |
+ | c | a | 11s | |
+ | d | f | 13s | stop sign |
+ | f | d | 13s | stop sign |
+ | g | i | 13s | stop sign |
+ | i | g | 11s | |
+ | j | l | 11s | |
+ | l | j | 13s | stop sign |
+ | m | o | 13s | stop sign |
+ | o | m | 13s | stop sign |
+
+
+ Scenario: Car - Stop sign on intersection node
+ 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 | secondary |
+ | hgi | primary |
+ | fgj | secondary |
+ | lmn | primary |
+ | kmo | secondary |
+
+ And the nodes
+ | node | highway | stop |
+ | g | stop | |
+ | m | stop | minor |
+
+
+ When I route I should get
+
+ # No road has stop signs
+ | from | to | time | # |
+ | a | b | 14s +-1 | turn |
+ | a | e | 13s +-1 | no turn |
+ | a | d | 17s +-1 | turn |
+ | e | d | 14s +-1 | turn |
+ | e | a | 13s +-1 | no turn |
+ | e | b | 17s +-1 | turn |
+ | d | a | 14s +-1 | turn |
+ | d | b | 11s +-1 | no turn |
+ | d | e | 17s +-1 | turn |
+ | b | e | 14s +-1 | turn |
+ | b | d | 11s +-1 | no turn |
+ | b | a | 17s +-1 | turn |
+
+ # All roads have stop signs - 2s penalty
+ | f | h | 16s +-1 | turn with stop |
+ | f | j | 15s +-1 | no turn with stop |
+ | f | i | 19s +-1 | turn with stop |
+ | j | i | 16s +-1 | turn with stop |
+ | j | f | 15s +-1 | no turn with stop |
+ | j | h | 19s +-1 | turn with stop |
+ | i | f | 16s +-1 | turn with stop |
+ | i | h | 13s +-1 | no turn with stop |
+ | i | j | 19s +-1 | turn with stop |
+ | h | j | 16s +-1 | turn with stop |
+ | h | i | 13s +-1 | no turn with stop |
+ | h | f | 19s +-1 | turn with stop |
+
+ # Minor roads have stop signs - 2s penalty
+ | k | l | 16s +-1 | turn with minor stop |
+ | k | o | 15s +-1 | no turn with minor stop |
+ | k | n | 19s +-1 | turn with minor stop |
+ | o | n | 16s +-1 | turn with minor stop |
+ | o | k | 15s +-1 | no turn with minor stop |
+ | o | l | 19s +-1 | turn with minor stop |
+ | n | k | 14s +-1 | turn |
+ | n | l | 11s +-1 | no turn |
+ | n | o | 17s +-1 | turn |
+ | l | o | 14s +-1 | turn |
+ | l | n | 11s +-1 | no turn |
+ | l | k | 17s +-1 | turn |
+
+
+ Scenario: Car - Infer stop sign direction
+ Given a grid size of 5 meters
+
+ Given the node map
+ """
+ a---------sb
+
+ c---------td
+
+ e---------uf
+
+ g---------vh
+
+ """
+
+ And the ways
+ | nodes | highway |
+ | asb | primary |
+ | ctd | primary |
+ | euf | primary |
+ | gvh | primary |
+
+ And the nodes
+ | node | highway | direction |
+ | s | stop | |
+ | t | stop | forward |
+ | u | stop | backward |
+ | v | stop | both |
+
+ When I route I should get
+ | from | to | time | # |
+ | a | b | 3.5s | stop |
+ | b | a | 1.5s | |
+ | c | d | 3.5s | stop |
+ | d | c | 1.5s | |
+ | e | f | 1.5s | |
+ | f | e | 3.5s | stop |
+ | g | h | 3.5s | stop |
+ | h | g | 3.5s | stop |
+
+
+ Scenario: Car - Infer stop sign direction 2
+ Given a grid size of 5 meters
+
+ Given the node map
+ """
+
+ d
+ |
+ a---------sbt---------c
+ |
+ e
+
+ """
+
+ And the ways
+ | nodes | highway |
+ | asbtc | primary |
+ | dbe | primary |
+
+ And the nodes
+ | node | highway |
+ | s | stop |
+ | t | stop |
+
+ When I route I should get
+ | from | to | time | # |
+ | a | d | 9s +- 1 | stop |
+ | a | c | 5s +- 1 | stop |
+ | a | e | 6s +- 1 | stop |
+ | c | e | 9s +- 1 | stop |
+ | c | a | 5s +- 1 | stop |
+ | c | d | 6s +- 1 | stop |
+ | d | c | 7s +- 1 | |
+ | d | e | 1s +- 1 | |
+ | d | a | 4s +- 1 | |
+ | e | a | 7s +- 1 | |
+ | e | d | 1s +- 1 | |
+ | e | c | 4s +- 1 | |
diff --git a/features/car/traffic_light_penalties.feature b/features/car/traffic_light_penalties.feature
index 2a5ded5f02e..5311599b6df 100644
--- a/features/car/traffic_light_penalties.feature
+++ b/features/car/traffic_light_penalties.feature
@@ -81,7 +81,7 @@ Feature: Car - Handle traffic lights
Given the profile file "car" initialized with
"""
profile.properties.weight_name = 'distance'
- profile.properties.traffic_light_penalty = 100000
+ profile.properties.traffic_signal_penalty = 1000
"""
Given the node map
@@ -107,8 +107,8 @@ Feature: Car - Handle traffic lights
| b | traffic_signals |
When I route I should get
- | from | to | time | distances | weight | # |
- | 1 | 2 | 100033.2s | 599.9m,0m | 599.8 | goes via the expensive traffic signal |
+ | from | to | time | distances | weight | # |
+ | 1 | 2 | 1033.2s | 599.9m,0m | 599.8 | goes via the expensive traffic signal |
@@ -243,7 +243,7 @@ Feature: Car - Handle traffic lights
| a | c | abc,abc | _ibE_ibE?gJ?eJ |
- Scenario: Traffic Signal Geometry - reverse signal
+ Scenario: Traffic Signal Geometry - backward signal
Given the query options
| overview | full |
| geometries | polyline |
@@ -259,7 +259,7 @@ Feature: Car - Handle traffic lights
And the nodes
| node | highway | traffic_signals:direction |
- | b | traffic_signals | reverse |
+ | b | traffic_signals | backward |
When I route I should get
| from | to | route | geometry |
diff --git a/features/car/turning_loop.feature b/features/car/turning_loop.feature
new file mode 100644
index 00000000000..1c4d8bb0d54
--- /dev/null
+++ b/features/car/turning_loop.feature
@@ -0,0 +1,32 @@
+@routing @car @turning_loop
+Feature: Car - Handle turning loop
+
+ Background:
+ Given the profile "car"
+
+ Scenario: Car - Must turn around at the first good opportunity
+ Given the node map
+ """
+ a-b-c-d-e-f-g
+ """
+
+ And the ways
+ | nodes | highway |
+ | ab | primary |
+ | bc | primary |
+ | cd | primary |
+ | de | primary |
+ | ef | primary |
+ | fg | primary |
+
+ And the nodes
+ | node | highway |
+ | b | turning_loop |
+ | d | turning_circle |
+ | f | mini_roundabout |
+
+ When I route I should get
+ | waypoints | bearings | route | turns |
+ | a,a | 90,10 270,10 | ab,ab,ab | depart,continue uturn,arrive |
+ | c,a | 90,10 270,10 | cd,cd,ab | depart,continue uturn,arrive |
+ | e,a | 90,10 270,10 | ef,ef,ab | depart,continue uturn,arrive |
diff --git a/include/extractor/edge_based_graph_factory.hpp b/include/extractor/edge_based_graph_factory.hpp
index 56aec7392c7..dd5454f519a 100644
--- a/include/extractor/edge_based_graph_factory.hpp
+++ b/include/extractor/edge_based_graph_factory.hpp
@@ -23,7 +23,6 @@
#include "util/typedefs.hpp"
#include "storage/io.hpp"
-#include "traffic_signals.hpp"
#include <cstdint>
#include <string>
@@ -60,8 +59,6 @@ class EdgeBasedGraphFactory
explicit EdgeBasedGraphFactory(const util::NodeBasedDynamicGraph &node_based_graph,
EdgeBasedNodeDataContainer &node_data_container,
const CompressedEdgeContainer &compressed_edge_container,
- const std::unordered_set<NodeID> &barrier_nodes,
- const TrafficSignals &traffic_signals,
const std::vector<util::Coordinate> &coordinates,
const NameTable &name_table,
const std::unordered_set<EdgeID> &segregated_edges,
@@ -126,8 +123,6 @@ class EdgeBasedGraphFactory
const std::vector<util::Coordinate> &m_coordinates;
const util::NodeBasedDynamicGraph &m_node_based_graph;
- const std::unordered_set<NodeID> &m_barrier_nodes;
- 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 1711e7cb241..60b9cf64656 100644
--- a/include/extractor/extraction_containers.hpp
+++ b/include/extractor/extraction_containers.hpp
@@ -8,8 +8,6 @@
#include "extractor/scripting_environment.hpp"
#include "storage/tar_fwd.hpp"
-#include "traffic_lights.hpp"
-#include "traffic_signals.hpp"
#include <unordered_map>
#include <unordered_set>
@@ -26,19 +24,15 @@ namespace osrm::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/signals prior to
+ // We identify the ways and nodes relevant to restrictions/overrides/obstacles 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 WriteCharData(const std::string &file_name);
@@ -52,9 +46,7 @@ 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;
NodeIDVector used_node_id_list;
NodeVector all_nodes_list;
EdgeVector all_edges_list;
@@ -67,9 +59,6 @@ class ExtractionContainers
unsigned max_internal_node_id;
- std::vector<InputTrafficSignal> external_traffic_signals;
- TrafficSignals internal_traffic_signals;
-
std::vector<NodeBasedEdge> used_edges;
// List of restrictions (conditional and unconditional) before we transform them into the
@@ -81,7 +70,6 @@ class ExtractionContainers
std::vector<InputManeuverOverride> external_maneuver_overrides_list;
std::vector<UnresolvedManeuverOverride> internal_maneuver_overrides;
- std::unordered_set<NodeID> used_barrier_nodes;
NodeVector used_nodes;
ExtractionContainers();
diff --git a/include/extractor/extraction_node.hpp b/include/extractor/extraction_node.hpp
index ad46e9bcefc..189e37c7e3b 100644
--- a/include/extractor/extraction_node.hpp
+++ b/include/extractor/extraction_node.hpp
@@ -1,21 +1,17 @@
#ifndef EXTRACTION_NODE_HPP
#define EXTRACTION_NODE_HPP
-#include "traffic_lights.hpp"
+#include <osmium/osm/node.hpp>
namespace osrm::extractor
{
struct ExtractionNode
{
- ExtractionNode() : traffic_lights(TrafficLightClass::NONE), barrier(false) {}
- void clear()
- {
- traffic_lights = TrafficLightClass::NONE;
- barrier = false;
- }
- TrafficLightClass::Direction traffic_lights;
- bool barrier;
+ ExtractionNode() {}
+
+ // the current node
+ const osmium::Node *node;
};
} // namespace osrm::extractor
diff --git a/include/extractor/extraction_turn.hpp b/include/extractor/extraction_turn.hpp
index 4dafd823cb9..a779c920ed0 100644
--- a/include/extractor/extraction_turn.hpp
+++ b/include/extractor/extraction_turn.hpp
@@ -1,8 +1,10 @@
#ifndef OSRM_EXTRACTION_TURN_HPP
#define OSRM_EXTRACTION_TURN_HPP
+#include "extractor/graph_compressor.hpp"
#include "extractor/road_classification.hpp"
#include "extractor/travel_mode.hpp"
+#include "util/typedefs.hpp"
#include <boost/numeric/conversion/cast.hpp>
@@ -13,6 +15,8 @@ namespace osrm::extractor
struct ExtractionTurnLeg
{
+ using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
+
ExtractionTurnLeg(bool is_restricted,
bool is_motorway,
bool is_link,
@@ -20,17 +24,34 @@ struct ExtractionTurnLeg
int highway_turn_classification,
int access_turn_classification,
int speed,
+ double distance,
RoadPriorityClass::Enum priority_class,
bool is_incoming,
bool is_outgoing)
: is_restricted(is_restricted), is_motorway(is_motorway), is_link(is_link),
number_of_lanes(number_of_lanes),
highway_turn_classification(highway_turn_classification),
- access_turn_classification(access_turn_classification), speed(speed),
+ access_turn_classification(access_turn_classification), speed(speed), distance(distance),
priority_class(priority_class), is_incoming(is_incoming), is_outgoing(is_outgoing)
{
}
+ ExtractionTurnLeg(EdgeData edge_data, bool is_incoming, bool is_outgoing)
+ : ExtractionTurnLeg(edge_data.flags.restricted,
+ edge_data.flags.road_classification.IsMotorwayClass(),
+ edge_data.flags.road_classification.IsLinkClass(),
+ edge_data.flags.road_classification.GetNumberOfLanes(),
+ edge_data.flags.highway_turn_classification,
+ edge_data.flags.access_turn_classification,
+ 36.0 * from_alias<double>(edge_data.distance) /
+ from_alias<double>(edge_data.duration),
+ from_alias<double>(edge_data.distance),
+ edge_data.flags.road_classification.GetPriority(),
+ is_incoming,
+ is_outgoing)
+ {
+ }
+
bool is_restricted;
bool is_motorway;
bool is_link;
@@ -38,11 +59,25 @@ struct ExtractionTurnLeg
int highway_turn_classification;
int access_turn_classification;
int speed;
+ double distance;
RoadPriorityClass::Enum priority_class;
bool is_incoming;
bool is_outgoing;
};
+// Structure reflected into LUA scripting
+//
+// This structure backs the `turn` parameter in the LUA `process_turn` function.
+// That function is called:
+//
+// 1. from graph_compressor.cpp when compressing nodes with obstacles. A fake turn with
+// just one incoming and one outgoing edge will be generated. `number_of_roads` will
+// be 2. The returned penalties will be added to the compressed edge.
+//
+// 2. from edge_based_graph_factory.cpp during generation of edge-expanded edges. In
+// this stage real turns will be modelled. The returned penalties will be added to
+// the edge-expanded edge.
+
struct ExtractionTurn
{
ExtractionTurn(double angle,
@@ -50,6 +85,7 @@ struct ExtractionTurn
bool is_u_turn,
bool has_traffic_light,
bool is_left_hand_driving,
+
bool source_restricted,
TravelMode source_mode,
bool source_is_motorway,
@@ -70,8 +106,13 @@ struct ExtractionTurn
int target_speed,
RoadPriorityClass::Enum target_priority_class,
+ const ExtractionTurnLeg &source_road,
+ const ExtractionTurnLeg &target_road,
const std::vector<ExtractionTurnLeg> &roads_on_the_right,
- const std::vector<ExtractionTurnLeg> &roads_on_the_left)
+ const std::vector<ExtractionTurnLeg> &roads_on_the_left,
+ const NodeID from,
+ const NodeID via,
+ const NodeID to)
: angle(180. - angle), number_of_roads(number_of_roads), is_u_turn(is_u_turn),
has_traffic_light(has_traffic_light), is_left_hand_driving(is_left_hand_driving),
@@ -89,11 +130,60 @@ struct ExtractionTurn
target_access_turn_classification(target_access_turn_classification),
target_speed(target_speed), target_priority_class(target_priority_class),
- roads_on_the_right(roads_on_the_right), roads_on_the_left(roads_on_the_left), weight(0.),
- duration(0.)
+ from(from), via(via), to(to),
+
+ source_road(source_road), target_road(target_road),
+ roads_on_the_right(roads_on_the_right), roads_on_the_left(roads_on_the_left),
+ weight(0.), duration(0.)
{
}
+
+ // to construct a "fake" turn while compressing obstacle nodes
+ // in graph_compressor.cpp
+ ExtractionTurn(NodeID from,
+ NodeID via,
+ NodeID to,
+ const ExtractionTurnLeg::EdgeData &source_edge,
+ const ExtractionTurnLeg::EdgeData &target_edge,
+ const std::vector<ExtractionTurnLeg> &roads_on_the_right,
+ const std::vector<ExtractionTurnLeg> &roads_on_the_left)
+ : ExtractionTurn{0,
+ 2,
+ false,
+ true,
+ false,
+ // source
+ false,
+ TRAVEL_MODE_DRIVING,
+ false,
+ false,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ // target
+ false,
+ TRAVEL_MODE_DRIVING,
+ false,
+ false,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ // other
+ ExtractionTurnLeg{source_edge, true, false},
+ ExtractionTurnLeg{target_edge, false, true},
+ roads_on_the_right,
+ roads_on_the_left,
+ from,
+ via,
+ to}
+ {
+ }
+
const double angle;
const int number_of_roads;
const bool is_u_turn;
@@ -122,6 +212,12 @@ struct ExtractionTurn
const int target_speed;
const RoadPriorityClass::Enum target_priority_class;
+ const NodeID from;
+ const NodeID via;
+ const NodeID to;
+
+ const ExtractionTurnLeg source_road;
+ const ExtractionTurnLeg target_road;
const std::vector<ExtractionTurnLeg> roads_on_the_right;
const std::vector<ExtractionTurnLeg> roads_on_the_left;
diff --git a/include/extractor/extractor.hpp b/include/extractor/extractor.hpp
index 1d36418aab2..4d30eb7e4b1 100644
--- a/include/extractor/extractor.hpp
+++ b/include/extractor/extractor.hpp
@@ -43,7 +43,6 @@ 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::extractor
@@ -64,8 +63,6 @@ class Extractor
LaneDescriptionMap turn_lane_map;
std::vector<TurnRestriction> turn_restrictions;
std::vector<UnresolvedManeuverOverride> unresolved_maneuver_overrides;
- TrafficSignals traffic_signals;
- std::unordered_set<NodeID> barriers;
std::vector<util::Coordinate> osm_coordinates;
extractor::PackedOSMIDs osm_node_ids;
std::vector<NodeBasedEdge> edge_list;
@@ -83,8 +80,6 @@ class Extractor
const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container,
- const std::unordered_set<NodeID> &barrier_nodes,
- const TrafficSignals &traffic_signals,
const RestrictionGraph &restriction_graph,
const std::unordered_set<EdgeID> &segregated_edges,
const NameTable &name_table,
@@ -112,7 +107,6 @@ class Extractor
const EdgeBasedNodeDataContainer &edge_based_node_container,
const std::vector<util::Coordinate> &node_coordinates,
const CompressedEdgeContainer &compressed_edge_container,
- const std::unordered_set<NodeID> &barrier_nodes,
const RestrictionGraph &restriction_graph,
const NameTable &name_table,
LaneDescriptionMap lane_description_map,
diff --git a/include/extractor/extractor_callbacks.hpp b/include/extractor/extractor_callbacks.hpp
index 83672f54977..9a493e27409 100644
--- a/include/extractor/extractor_callbacks.hpp
+++ b/include/extractor/extractor_callbacks.hpp
@@ -43,13 +43,13 @@ class ExtractorCallbacks
using MapVal = unsigned;
using StringMap = std::unordered_map<MapKey, MapVal>;
StringMap string_map;
- ExtractionContainers &external_memory;
std::unordered_map<std::string, ClassData> &classes_map;
LaneDescriptionMap &lane_description_map;
bool fallback_to_duration;
bool force_split_edges;
public:
+ ExtractionContainers &external_memory;
using ClassesMap = std::unordered_map<std::string, ClassData>;
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers,
diff --git a/include/extractor/graph_compressor.hpp b/include/extractor/graph_compressor.hpp
index 0e9a1070570..3af6662779d 100644
--- a/include/extractor/graph_compressor.hpp
+++ b/include/extractor/graph_compressor.hpp
@@ -2,10 +2,8 @@
#define GEOMETRY_COMPRESSOR_HPP
#include "extractor/scripting_environment.hpp"
-#include "util/typedefs.hpp"
-
-#include "traffic_signals.hpp"
#include "util/node_based_graph.hpp"
+#include "util/typedefs.hpp"
#include <unordered_set>
#include <vector>
@@ -19,12 +17,10 @@ struct UnresolvedManeuverOverride;
class GraphCompressor
{
+ public:
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
- public:
- void Compress(const std::unordered_set<NodeID> &barrier_nodes,
- TrafficSignals &traffic_signals,
- ScriptingEnvironment &scripting_environment,
+ void Compress(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
util::NodeBasedDynamicGraph &graph,
diff --git a/include/extractor/intersection/intersection_analysis.hpp b/include/extractor/intersection/intersection_analysis.hpp
index 9e0878df5d7..6765b5b52d5 100644
--- a/include/extractor/intersection/intersection_analysis.hpp
+++ b/include/extractor/intersection/intersection_analysis.hpp
@@ -6,6 +6,7 @@
#include "extractor/intersection/intersection_view.hpp"
#include "extractor/intersection/mergable_road_detector.hpp"
#include "extractor/node_restriction_map.hpp"
+#include "extractor/obstacles.hpp"
#include "extractor/turn_lane_types.hpp"
#include "util/coordinate.hpp"
@@ -26,7 +27,7 @@ IntersectionEdges getOutgoingEdges(const util::NodeBasedDynamicGraph &graph,
bool isTurnAllowed(const util::NodeBasedDynamicGraph &graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const IntersectionEdgeGeometries &geometries,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &from,
@@ -46,14 +47,14 @@ getIntersectionGeometries(const util::NodeBasedDynamicGraph &graph,
IntersectionView convertToIntersectionView(const util::NodeBasedDynamicGraph &graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const IntersectionEdgeGeometries &edge_geometries,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge,
const IntersectionEdges &outgoing_edges,
const std::unordered_set<EdgeID> &merged_edges);
-// Check for restrictions/barriers and generate a list of valid and invalid turns present at
+// Check for restrictions/obstacles and generate a list of valid and invalid turns present at
// the node reached from `incoming_edge`. The resulting candidates have to be analyzed
// for their actual instructions later on.
template <bool USE_CLOSE_COORDINATE>
@@ -62,7 +63,7 @@ IntersectionView getConnectedRoads(const util::NodeBasedDynamicGraph &graph,
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge);
@@ -70,15 +71,15 @@ IntersectionView
getConnectedRoadsForEdgeGeometries(const util::NodeBasedDynamicGraph &graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge,
const IntersectionEdgeGeometries &edge_geometries,
const std::unordered_set<EdgeID> &merged_edge_ids);
-// Graph Compression cannot compress every setting. For example any barrier/traffic light cannot
+// Graph Compression cannot compress every setting. For example nodes with obstacles cannot
// be compressed. As a result, a simple road of the form `a ----- b` might end up as having an
-// intermediate intersection, if there is a traffic light in between. If we want to look farther
+// intermediate intersection, if there is an obstacle in between. If we want to look farther
// down a road, finding the next actual decision requires the look at multiple intersections.
// Here we follow the road until we either reach a dead end or find the next intersection with
// more than a single next road. This function skips over degree two nodes to find correct input
diff --git a/include/extractor/intersection/intersection_view.hpp b/include/extractor/intersection/intersection_view.hpp
index 4eb60585602..6cb721b1275 100644
--- a/include/extractor/intersection/intersection_view.hpp
+++ b/include/extractor/intersection/intersection_view.hpp
@@ -166,7 +166,7 @@ template <typename Self> struct EnableIntersectionOps
}
// Can this be skipped over?
- auto isTrafficSignalOrBarrier() const { return self()->size() == 2; }
+ auto isObstacle() const { return self()->size() == 2; }
// Checks if there is at least one road available (except UTurn road) on which to continue.
auto isDeadEnd() const
diff --git a/include/extractor/intersection/mergable_road_detector.hpp b/include/extractor/intersection/mergable_road_detector.hpp
index 1f02afb5675..2686196a264 100644
--- a/include/extractor/intersection/mergable_road_detector.hpp
+++ b/include/extractor/intersection/mergable_road_detector.hpp
@@ -6,6 +6,7 @@
#include "extractor/intersection/have_identical_names.hpp"
#include "extractor/name_table.hpp"
#include "extractor/node_restriction_map.hpp"
+#include "extractor/obstacles.hpp"
#include "extractor/turn_lane_types.hpp"
#include "guidance/intersection.hpp"
@@ -47,7 +48,7 @@ class MergableRoadDetector
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
@@ -164,7 +165,7 @@ class MergableRoadDetector
const std::vector<util::Coordinate> &node_coordinates;
const extractor::CompressedEdgeContainer &compressed_geometries;
const RestrictionMap &node_restriction_map;
- const std::unordered_set<NodeID> &barrier_nodes;
+ const ObstacleMap &obstacle_nodes;
const TurnLanesIndexedArray &turn_lanes_data;
// name detection
diff --git a/include/extractor/intersection/node_based_graph_walker.hpp b/include/extractor/intersection/node_based_graph_walker.hpp
index f3915ee9f1e..bafd662121f 100644
--- a/include/extractor/intersection/node_based_graph_walker.hpp
+++ b/include/extractor/intersection/node_based_graph_walker.hpp
@@ -30,7 +30,7 @@ class NodeBasedGraphWalker
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data);
/*
@@ -53,7 +53,7 @@ class NodeBasedGraphWalker
const std::vector<util::Coordinate> &node_coordinates;
const extractor::CompressedEdgeContainer &compressed_geometries;
const RestrictionMap &node_restriction_map;
- const std::unordered_set<NodeID> &barrier_nodes;
+ const ObstacleMap &obstacle_nodes;
const TurnLanesIndexedArray &turn_lanes_data;
};
@@ -160,7 +160,7 @@ struct IntersectionFinderAccumulator
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data);
// true if the path has traversed enough distance
bool terminate();
@@ -182,7 +182,7 @@ struct IntersectionFinderAccumulator
const std::vector<util::Coordinate> &node_coordinates;
const extractor::CompressedEdgeContainer &compressed_geometries;
const RestrictionMap &node_restriction_map;
- const std::unordered_set<NodeID> &barrier_nodes;
+ const ObstacleMap &obstacle_nodes;
const TurnLanesIndexedArray &turn_lanes_data;
};
@@ -223,7 +223,7 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
{current_node_id, current_edge_id});
@@ -252,7 +252,7 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
return {};
}
-struct SkipTrafficSignalBarrierRoadSelector
+struct SkipObstacleRoadSelector
{
std::optional<EdgeID> operator()(const NodeID,
const EdgeID,
@@ -260,7 +260,7 @@ struct SkipTrafficSignalBarrierRoadSelector
const util::NodeBasedDynamicGraph &,
const EdgeBasedNodeDataContainer &) const
{
- if (intersection.isTrafficSignalOrBarrier())
+ if (intersection.isObstacle())
{
return std::make_optional(intersection[1].eid);
}
diff --git a/include/extractor/node_based_edge.hpp b/include/extractor/node_based_edge.hpp
index 2abb98b205c..d98e2283e64 100644
--- a/include/extractor/node_based_edge.hpp
+++ b/include/extractor/node_based_edge.hpp
@@ -48,6 +48,8 @@ struct NodeBasedEdgeClassification
{
}
+ bool IsRestricted() const { return restricted; }
+
bool operator==(const NodeBasedEdgeClassification &other) const
{
return (road_classification == other.road_classification) && (forward == other.forward) &&
diff --git a/include/extractor/node_based_graph_factory.hpp b/include/extractor/node_based_graph_factory.hpp
index 79b4b45cd34..8c08e78bd33 100644
--- a/include/extractor/node_based_graph_factory.hpp
+++ b/include/extractor/node_based_graph_factory.hpp
@@ -8,7 +8,6 @@
#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"
@@ -23,7 +22,7 @@ namespace osrm::extractor
// edge-based graph and is also the basic concept for annotating paths. All information from ways
// that is transferred into the API response is connected to the edges of the node-based graph.
//
-// The input to the graph creation is the set of edges, traffic signals, barriers, meta-data,...
+// The input to the graph creation is the set of edges, obstacles, meta-data,...
// which is generated during extraction and stored within the extraction containers.
class NodeBasedGraphFactory
{
@@ -35,15 +34,12 @@ class NodeBasedGraphFactory
NodeBasedGraphFactory(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
- TrafficSignals &traffic_signals,
- std::unordered_set<NodeID> &&barriers,
std::vector<util::Coordinate> &&coordinates,
extractor::PackedOSMIDs &&osm_node_ids,
const std::vector<NodeBasedEdge> &edge_list,
std::vector<NodeBasedEdgeAnnotation> &&annotation_data);
auto const &GetGraph() const { return compressed_output_graph; }
- auto const &GetBarriers() const { return barriers; }
auto const &GetCompressedEdges() const { return compressed_edge_container; }
auto const &GetCoordinates() const { return coordinates; }
auto const &GetAnnotationData() const { return annotation_data; }
@@ -66,8 +62,7 @@ class NodeBasedGraphFactory
// edges into a single representative form
void Compress(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
- std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
- TrafficSignals &traffic_signals);
+ std::vector<UnresolvedManeuverOverride> &maneuver_overrides);
// 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
@@ -87,8 +82,6 @@ class NodeBasedGraphFactory
std::vector<NodeBasedEdgeAnnotation> annotation_data;
// General Information about the graph, not used outside of extractor
- std::unordered_set<NodeID> barriers;
-
std::vector<util::Coordinate> coordinates;
// data to keep in sync with the node-based graph
diff --git a/include/extractor/obstacles.hpp b/include/extractor/obstacles.hpp
new file mode 100644
index 00000000000..b2ca3039172
--- /dev/null
+++ b/include/extractor/obstacles.hpp
@@ -0,0 +1,211 @@
+/*
+
+Copyright (c) 2025, Project OSRM contributors
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef OSRM_EXTRACTOR_OBSTACLES_DATA_HPP_
+#define OSRM_EXTRACTOR_OBSTACLES_DATA_HPP_
+
+#include "util/typedefs.hpp"
+
+#include <osmium/osm/node.hpp>
+#include <tbb/concurrent_vector.h>
+
+#include <ranges>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace osrm::extractor
+{
+// A class that represents an obstacle on the road or a place where you can turn around.
+//
+// This may be a completely impassable obstacle like a barrier, a temporary obstacle
+// like a traffic light or a stop sign, or an obstacle that just slows you down like a
+// traffic calming bump. The obstacle may be present in both directions or in one
+// direction only.
+//
+// This also represents a good turning point like a mini_roundabout, turning_loop, or
+// turning_circle.
+//
+// Note: A better name would have been 'WayPoint', but that name is ambiguous in the
+// OSRM-context.
+//
+struct Obstacle
+{
+ // The type of an obstacle
+ // Note: must be kept in sync with the initializer_list in obstacles.cpp
+ enum class Type : uint16_t
+ {
+ None = 0x0000,
+ Barrier = 0x0001,
+ TrafficSignals = 0x0002,
+ Stop = 0x0004,
+ GiveWay = 0x0008,
+ Crossing = 0x0010,
+ TrafficCalming = 0x0020,
+ MiniRoundabout = 0x0040,
+ TurningLoop = 0x0080,
+ TurningCircle = 0x0100,
+ StopMinor = 0x0200,
+
+ Turning = MiniRoundabout | TurningLoop | TurningCircle,
+ Incompressible = Barrier | Turning,
+ All = 0xFFFF
+ };
+
+ static const std::initializer_list<std::pair<std::string_view, Type>>
+ enum_type_initializer_list;
+
+ // The directions in which an obstacle applies.
+ // Note: must be kept in sync with the initializer_list in obstacles.cpp
+ enum class Direction : uint8_t
+ {
+ None = 0x0,
+ Forward = 0x1,
+ Backward = 0x2,
+ Both = 0x3
+ };
+
+ static const std::initializer_list<std::pair<std::string_view, Direction>>
+ enum_direction_initializer_list;
+
+ // use overloading instead of default arguments for sol::constructors
+ Obstacle(Type t_type) : type{t_type} {};
+ Obstacle(Type t_type, Direction t_direction) : type{t_type}, direction{t_direction} {};
+ Obstacle(Type t_type, Direction t_direction, float t_duration_penalty, float t_weight_penalty)
+ : type{t_type}, direction{t_direction}, duration{t_duration_penalty},
+ weight{t_weight_penalty} {};
+
+ Type type;
+ Direction direction{Direction::None};
+ float duration{0}; // in seconds
+ float weight{0}; // unit: profile.weight_multiplier
+};
+
+// A class that holds all known nodes with obstacles.
+//
+// This class holds all obstacles, bidirectional and unidirectional ones. For
+// unidirectional obstacle nodes it also stores the node leading to it.
+//
+// Notes:
+//
+// Before fixupNodes() it uses the external node id (aka. OSMNodeID).
+// After fixupNodes() it uses the internal node id (aka. NodeID).
+//
+class ObstacleMap
+{
+ using NodeIDVector = std::vector<OSMNodeID>;
+ using WayNodeIDOffsets = std::vector<size_t>;
+
+ using OsmFromToObstacle = std::tuple<OSMNodeID, OSMNodeID, Obstacle>;
+ using FromToObstacle = std::tuple<NodeID, NodeID, Obstacle>;
+
+ public:
+ ObstacleMap() = default;
+
+ // Insert an obstacle using the OSM node id.
+ //
+ // This function is thread-safe.
+ void emplace(OSMNodeID osm_node_id, const Obstacle &obstacle)
+ {
+ osm_obstacles.emplace_back(SPECIAL_OSM_NODEID, osm_node_id, obstacle);
+ };
+
+ // Insert an obstacle using internal node ids.
+ //
+ // The obstacle is at 'to'. For bidirectional obstacles set 'from' to SPECIAL_NODEID.
+ // Convenient for testing.
+ void emplace(NodeID from, NodeID to, const Obstacle &obstacle)
+ {
+ obstacles.emplace(to, std::make_tuple(from, to, obstacle));
+ };
+
+ // get all obstacles at node 'to' when coming from node 'from'
+ // pass SPECIAL_NODEID as 'from' to get all obstacles at 'to'
+ // 'type' can be a bitwise-or combination of Obstacle::Type
+ std::vector<Obstacle>
+ get(NodeID from, NodeID to, Obstacle::Type type = Obstacle::Type::All) const
+ {
+ std::vector<Obstacle> result;
+
+ auto [begin, end] = obstacles.equal_range(to);
+ for (auto &[key, value] : std::ranges::subrange(begin, end))
+ {
+ auto &[from_id, to_id, obstacle] = value;
+ if ((from_id == SPECIAL_NODEID || from_id == from) &&
+ (static_cast<uint16_t>(obstacle.type) & static_cast<uint16_t>(type)))
+ {
+ result.push_back(obstacle);
+ }
+ }
+ return result; // vector has move semantics
+ }
+
+ std::vector<Obstacle> get(NodeID to) const
+ {
+ return get(SPECIAL_NODEID, to, Obstacle::Type::All);
+ }
+
+ // is there any obstacle at node 'to'?
+ // inexpensive general test
+ bool any(NodeID to) const { return obstacles.contains(to); }
+
+ // is there any obstacle of type 'type' at node 'to' when coming from node 'from'?
+ // pass SPECIAL_NODEID as 'from' to query all obstacles at 'to'
+ // 'type' can be a bitwise-or combination of Obstacle::Type
+ bool any(NodeID from, NodeID to, Obstacle::Type type = Obstacle::Type::All) const
+ {
+ return any(to) && !get(from, to, type).empty();
+ }
+
+ // Preprocess the obstacles
+ //
+ // For all unidirectional obstacles find the node that leads up to them. This
+ // function must be called while the vector 'node_ids' is still unsorted /
+ // uncompressed.
+ void preProcess(const NodeIDVector &, const WayNodeIDOffsets &);
+
+ // Convert all external OSMNodeIDs into internal NodeIDs.
+ //
+ // This function must be called when the vector 'node_ids' is already sorted and
+ // compressed. Call this function once only.
+ void fixupNodes(const NodeIDVector &);
+
+ // Replace a leading node that is going to be deleted during graph
+ // compression with the leading node of the leading node.
+ void compress(NodeID from, NodeID delendus, NodeID to);
+
+ private:
+ // obstacles according to external id
+ tbb::concurrent_vector<OsmFromToObstacle> osm_obstacles;
+
+ // obstacles according to internal id, with a leading node if unidirectional
+ // bidirectional obstacles are stored with a leading node id == SPECIAL_NODE_ID
+ std::unordered_multimap<NodeID, FromToObstacle> obstacles;
+};
+
+} // namespace osrm::extractor
+#endif // OSRM_EXTRACTOR_OBSTACLES_DATA_HPP_
diff --git a/include/extractor/road_classification.hpp b/include/extractor/road_classification.hpp
index 679e1d1f6ca..875e9036dad 100644
--- a/include/extractor/road_classification.hpp
+++ b/include/extractor/road_classification.hpp
@@ -99,7 +99,7 @@ class RoadClassification
std::uint8_t GetNumberOfLanes() const { return number_of_lanes; }
void SetNumberOfLanes(const std::uint8_t new_value) { number_of_lanes = new_value; }
- std::uint32_t GetPriority() const { return static_cast<std::uint32_t>(road_priority_class); }
+ RoadPriorityClass::Enum GetPriority() const { return road_priority_class; }
RoadPriorityClass::Enum GetClass() const { return road_priority_class; }
void SetClass(const RoadPriorityClass::Enum new_value) { road_priority_class = new_value; }
diff --git a/include/extractor/scripting_environment.hpp b/include/extractor/scripting_environment.hpp
index 2a11afc33d1..662aea23527 100644
--- a/include/extractor/scripting_environment.hpp
+++ b/include/extractor/scripting_environment.hpp
@@ -3,6 +3,7 @@
#include "extractor/internal_extractor_edge.hpp"
#include "extractor/maneuver_override.hpp"
+#include "extractor/obstacles.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/restriction.hpp"
@@ -72,6 +73,8 @@ class ScriptingEnvironment
std::vector<InputManeuverOverride> &resulting_maneuver_overrides) = 0;
virtual bool HasLocationDependentData() const = 0;
+
+ ObstacleMap m_obstacle_map; // The obstacle map shared by all threads.
};
} // namespace extractor
} // namespace osrm
diff --git a/include/extractor/traffic_lights.hpp b/include/extractor/traffic_lights.hpp
deleted file mode 100644
index 1bb54bd91c3..00000000000
--- a/include/extractor/traffic_lights.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
-#define OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
-
-namespace osrm::extractor::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 osrm::extractor::TrafficLightClass
-
-#endif // OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
diff --git a/include/extractor/traffic_signals.hpp b/include/extractor/traffic_signals.hpp
deleted file mode 100644
index af0d3daeb19..00000000000
--- a/include/extractor/traffic_signals.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
-#define OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
-
-#include "util/std_hash.hpp"
-#include "util/typedefs.hpp"
-
-#include <unordered_set>
-#include <utility>
-
-namespace osrm::extractor
-{
-
-struct TrafficSignals
-{
- std::unordered_set<NodeID> bidirectional_nodes;
- std::unordered_set<std::pair<NodeID, NodeID>> unidirectional_segments;
-
- inline bool HasSignal(NodeID from, NodeID to) const
- {
- return bidirectional_nodes.contains(to) || unidirectional_segments.contains({from, to});
- }
-
- void Compress(NodeID from, NodeID via, NodeID to)
- {
- bidirectional_nodes.erase(via);
- if (unidirectional_segments.contains({via, to}))
- {
- unidirectional_segments.erase({via, to});
- unidirectional_segments.insert({from, to});
- }
- if (unidirectional_segments.contains({via, from}))
- {
- unidirectional_segments.erase({via, from});
- unidirectional_segments.insert({to, from});
- }
- }
-};
-} // namespace osrm::extractor
-
-#endif // OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
diff --git a/include/extractor/turn_path_compressor.hpp b/include/extractor/turn_path_compressor.hpp
index 4a6bbea8987..e4e7f4da175 100644
--- a/include/extractor/turn_path_compressor.hpp
+++ b/include/extractor/turn_path_compressor.hpp
@@ -16,7 +16,7 @@ struct UnresolvedManeuverOverride;
// OSRM stores turn paths as node -> [node] -> node instead of way -> node -> way (or
// way->[way]->way) as it is done in OSM. These paths need to match the state of graph
// compression which we perform in the graph compressor that removes certain degree two nodes from
-// the graph (all but the ones with penalties/barriers, as of the state of writing).
+// the graph (all but the ones with obstacles, as of the state of writing).
// Since this graph compression is performed after creating the turn paths in the extraction
// phase, we need to update the involved nodes whenever one of the nodes is compressed.
//
diff --git a/include/guidance/driveway_handler.hpp b/include/guidance/driveway_handler.hpp
index a33cab9a863..81cc9a0daeb 100644
--- a/include/guidance/driveway_handler.hpp
+++ b/include/guidance/driveway_handler.hpp
@@ -15,7 +15,7 @@ class DrivewayHandler final : public IntersectionHandler
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table);
diff --git a/include/guidance/guidance_processing.hpp b/include/guidance/guidance_processing.hpp
index e0aea1d5423..a95554120ac 100644
--- a/include/guidance/guidance_processing.hpp
+++ b/include/guidance/guidance_processing.hpp
@@ -7,6 +7,7 @@
#include "extractor/name_table.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/node_restriction_map.hpp"
+#include "extractor/obstacles.hpp"
#include "extractor/suffix_table.hpp"
#include "extractor/turn_lane_types.hpp"
#include "extractor/way_restriction_map.hpp"
@@ -29,7 +30,7 @@ void annotateTurns(const util::NodeBasedDynamicGraph &node_based_graph,
const extractor::EdgeBasedNodeDataContainer &edge_based_node_container,
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_edge_container,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::RestrictionMap &node_restriction_map,
const extractor::WayRestrictionMap &way_restriction_map,
const extractor::NameTable &name_table,
diff --git a/include/guidance/intersection_handler.hpp b/include/guidance/intersection_handler.hpp
index 2f657ee05ed..9cd130634fc 100644
--- a/include/guidance/intersection_handler.hpp
+++ b/include/guidance/intersection_handler.hpp
@@ -32,7 +32,7 @@ class IntersectionHandler
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table);
@@ -53,7 +53,7 @@ class IntersectionHandler
const std::vector<util::Coordinate> &node_coordinates;
const extractor::CompressedEdgeContainer &compressed_geometries;
const extractor::RestrictionMap &node_restriction_map;
- const std::unordered_set<NodeID> &barrier_nodes;
+ const extractor::ObstacleMap &obstacle_nodes;
const extractor::TurnLanesIndexedArray &turn_lanes_data;
const extractor::NameTable &name_table;
const extractor::SuffixTable &street_name_suffix_table;
@@ -114,8 +114,8 @@ class IntersectionHandler
NodeID node; // < node at this intersection
};
- // Skips over artificial intersections i.e. traffic lights, barriers etc.
- // Returns the next non-artificial intersection and its node in the node based
+ // Skips over a string of edges that could not be compressed because of obstacles.
+ // Returns the next intersection and its node in the node based
// graph if an intersection could be found or none otherwise.
//
// a ... tl ... b .. c
diff --git a/include/guidance/motorway_handler.hpp b/include/guidance/motorway_handler.hpp
index 8f399156de1..bda5ffc71ce 100644
--- a/include/guidance/motorway_handler.hpp
+++ b/include/guidance/motorway_handler.hpp
@@ -23,7 +23,7 @@ class MotorwayHandler final : public IntersectionHandler
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table);
diff --git a/include/guidance/roundabout_handler.hpp b/include/guidance/roundabout_handler.hpp
index 29fda3786f7..150f182226e 100644
--- a/include/guidance/roundabout_handler.hpp
+++ b/include/guidance/roundabout_handler.hpp
@@ -41,7 +41,7 @@ class RoundaboutHandler final : public IntersectionHandler
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table);
diff --git a/include/guidance/sliproad_handler.hpp b/include/guidance/sliproad_handler.hpp
index 533ac4dcfb2..a7e43f3c66e 100644
--- a/include/guidance/sliproad_handler.hpp
+++ b/include/guidance/sliproad_handler.hpp
@@ -24,7 +24,7 @@ class SliproadHandler final : public IntersectionHandler
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table);
diff --git a/include/guidance/statistics_handler.hpp b/include/guidance/statistics_handler.hpp
index f0e3401c70a..3e4123754fa 100644
--- a/include/guidance/statistics_handler.hpp
+++ b/include/guidance/statistics_handler.hpp
@@ -28,7 +28,7 @@ class StatisticsHandler final : public IntersectionHandler
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
@@ -37,7 +37,7 @@ class StatisticsHandler final : public IntersectionHandler
coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table)
diff --git a/include/guidance/suppress_mode_handler.hpp b/include/guidance/suppress_mode_handler.hpp
index 447a3fdb3b0..cf9acde18b9 100644
--- a/include/guidance/suppress_mode_handler.hpp
+++ b/include/guidance/suppress_mode_handler.hpp
@@ -22,7 +22,7 @@ class SuppressModeHandler final : public IntersectionHandler
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table);
diff --git a/include/guidance/turn_analysis.hpp b/include/guidance/turn_analysis.hpp
index 56a3e5804bc..704ef007dce 100644
--- a/include/guidance/turn_analysis.hpp
+++ b/include/guidance/turn_analysis.hpp
@@ -33,7 +33,7 @@ class TurnAnalysis
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_edge_container,
const extractor::RestrictionMap &restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table);
diff --git a/include/guidance/turn_discovery.hpp b/include/guidance/turn_discovery.hpp
index 67aaa1259c2..d354e5ee9b8 100644
--- a/include/guidance/turn_discovery.hpp
+++ b/include/guidance/turn_discovery.hpp
@@ -2,6 +2,7 @@
#define OSRM_GUIDANCE_TURN_DISCOVERY_HPP_
#include "extractor/node_restriction_map.hpp"
+#include "extractor/obstacles.hpp"
#include "guidance/intersection.hpp"
#include "guidance/turn_lane_data.hpp"
#include "util/typedefs.hpp"
@@ -35,7 +36,7 @@ bool findPreviousIntersection(
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
// output parameters, will be in an arbitrary state on failure
NodeID &result_node,
diff --git a/include/guidance/turn_handler.hpp b/include/guidance/turn_handler.hpp
index 5d4348cab4a..e2ac0564e25 100644
--- a/include/guidance/turn_handler.hpp
+++ b/include/guidance/turn_handler.hpp
@@ -26,7 +26,7 @@ class TurnHandler final : public IntersectionHandler
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table);
diff --git a/include/guidance/turn_lane_handler.hpp b/include/guidance/turn_lane_handler.hpp
index b7c9e1a042b..53791a02f98 100644
--- a/include/guidance/turn_lane_handler.hpp
+++ b/include/guidance/turn_lane_handler.hpp
@@ -57,7 +57,7 @@ class TurnLaneHandler
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
extractor::LaneDescriptionMap &lane_description_map,
const TurnAnalysis &turn_analysis,
@@ -78,7 +78,7 @@ class TurnLaneHandler
const std::vector<util::Coordinate> &node_coordinates;
const extractor::CompressedEdgeContainer &compressed_geometries;
const extractor::RestrictionMap &node_restriction_map;
- const std::unordered_set<NodeID> &barrier_nodes;
+ const extractor::ObstacleMap &obstacle_nodes;
const extractor::TurnLanesIndexedArray &turn_lanes_data;
std::vector<std::uint32_t> turn_lane_offsets;
diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua
index 2c701e218b3..76335155365 100644
--- a/profiles/bicycle.lua
+++ b/profiles/bicycle.lua
@@ -17,7 +17,7 @@ function setup()
return {
properties = {
u_turn_penalty = 20,
- traffic_light_penalty = 2,
+ traffic_signal_penalty = 2,
--weight_name = 'cyclability',
weight_name = 'duration',
process_call_tagless_node = false,
@@ -706,7 +706,7 @@ function process_turn(profile, turn)
end
if turn.has_traffic_light then
- turn.duration = turn.duration + profile.properties.traffic_light_penalty
+ turn.duration = turn.duration + profile.properties.traffic_signal_penalty
end
if profile.properties.weight_name == 'cyclability' then
turn.weight = turn.duration
diff --git a/profiles/car.lua b/profiles/car.lua
index 24079bfaae0..35b4178d9cd 100644
--- a/profiles/car.lua
+++ b/profiles/car.lua
@@ -6,7 +6,7 @@ Set = require('lib/set')
Sequence = require('lib/sequence')
Handlers = require("lib/way_handlers")
Relations = require("lib/relations")
-TrafficSignal = require("lib/traffic_signal")
+Obstacles = require("lib/obstacles")
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
Utils = require("lib/utils")
@@ -27,7 +27,6 @@ function setup()
continue_straight_at_waypoint = true,
use_turn_restrictions = true,
left_hand_driving = false,
- traffic_light_penalty = 2,
},
default_mode = mode.driving,
@@ -333,7 +332,7 @@ function process_node(profile, node, result, relations)
local access = find_access_tag(node, profile.access_tags_hierarchy)
if access then
if profile.access_tag_blacklist[access] and not profile.restricted_access_tag_list[access] then
- result.barrier = true
+ obstacle_map:add(node, Obstacle.new(obstacle_type.barrier))
end
else
local barrier = node:get_value_by_key("barrier")
@@ -361,13 +360,12 @@ function process_node(profile, node, result, relations)
and not flat_kerb
and not highway_crossing_kerb
or restricted_by_height then
- result.barrier = true
+ obstacle_map:add(node, Obstacle.new(obstacle_type.barrier))
end
end
end
- -- check if node is a traffic light
- result.traffic_lights = TrafficSignal.get_value(node)
+ Obstacles.process_node(profile, node)
end
function process_way(profile, way, result, relations)
@@ -476,8 +474,24 @@ function process_turn(profile, turn)
local turn_penalty = profile.turn_penalty
local turn_bias = turn.is_left_hand_driving and 1. / profile.turn_bias or profile.turn_bias
- if turn.has_traffic_light then
- turn.duration = profile.properties.traffic_light_penalty
+ for _, obs in pairs(obstacle_map:get(turn.from, turn.via)) do
+ -- disregard a minor stop if entering by the major road
+ -- rationale: if a stop sign is tagged at the center of the intersection with stop=minor
+ -- it should only penalize the minor roads entering the intersection
+ if obs.type == obstacle_type.stop_minor and not Obstacles.entering_by_minor_road(turn) then
+ goto skip
+ end
+ -- heuristic to infer the direction of a stop without an explicit direction tag
+ -- rationale: a stop sign should not be placed farther than 20m from the intersection
+ if turn.number_of_roads == 2
+ and obs.type == obstacle_type.stop
+ and obs.direction == obstacle_direction.none
+ and turn.source_road.distance < 20
+ and turn.target_road.distance > 20 then
+ goto skip
+ end
+ turn.duration = turn.duration + obs.duration
+ ::skip::
end
if turn.number_of_roads > 2 or turn.source_mode ~= turn.target_mode or turn.is_u_turn then
diff --git a/profiles/foot.lua b/profiles/foot.lua
index fa5f8b6634f..b0a97127210 100644
--- a/profiles/foot.lua
+++ b/profiles/foot.lua
@@ -14,7 +14,7 @@ function setup()
weight_name = 'duration',
max_speed_for_map_matching = 40/3.6, -- kmph -> m/s
call_tagless_node_function = false,
- traffic_light_penalty = 2,
+ traffic_signal_penalty = 2,
u_turn_penalty = 2,
continue_straight_at_waypoint = false,
use_turn_restrictions = false,
@@ -252,7 +252,7 @@ function process_turn (profile, turn)
end
if turn.has_traffic_light then
- turn.duration = profile.properties.traffic_light_penalty
+ turn.duration = profile.properties.traffic_signal_penalty
end
if profile.properties.weight_name == 'routability' then
-- penalize turns from non-local access only segments onto local access only tags
diff --git a/profiles/lib/obstacles.lua b/profiles/lib/obstacles.lua
new file mode 100644
index 00000000000..a2ba2ca4aa7
--- /dev/null
+++ b/profiles/lib/obstacles.lua
@@ -0,0 +1,53 @@
+-- Assigns obstacle value to nodes as defined by
+-- include/extractor/obstacles.hpp
+
+local Obstacles = {}
+
+-- process the obstacles at the given node
+-- note: does not process barriers
+function Obstacles.process_node(profile, node)
+ local highway = node:get_value_by_key("highway")
+ if highway then
+ local type = obstacle_type[highway]
+ -- barriers already handled in car.lua
+ if type and type ~= obstacle_type.barrier then
+ local direction = node:get_value_by_key("direction")
+ local weight = 0
+ local duration = 0
+ local minor = false
+
+ if type == obstacle_type.traffic_signals then
+ -- traffic_signals:direction trumps direction
+ direction = node:get_value_by_key("traffic_signals:direction") or direction
+ -- traffic_signal_penalty is deprecated
+ -- but there's still unit_tests using it
+ duration = profile.properties.traffic_signal_penalty or 2
+ end
+ if type == obstacle_type.stop then
+ if node:get_value_by_key("stop") == "minor" then
+ type = obstacle_type.stop_minor
+ end
+ duration = 2
+ end
+ if type == obstacle_type.give_way then
+ duration = 1
+ end
+ obstacle_map:add(node, Obstacle.new(type, obstacle_direction[direction] or obstacle_direction.none, duration, weight))
+ end
+ end
+end
+
+-- return true if the source road of this turn is a minor road at the intersection
+function Obstacles.entering_by_minor_road(turn)
+ -- implementation: comparing road speeds (anybody has a better idea?)
+ local max_speed = turn.target_speed
+ for _, turn_leg in pairs(turn.roads_on_the_right) do
+ max_speed = math.max(max_speed, turn_leg.speed)
+ end
+ for _, turn_leg in pairs(turn.roads_on_the_left) do
+ max_speed = math.max(max_speed, turn_leg.speed)
+ end
+ return max_speed > turn.source_speed
+end
+
+return Obstacles
diff --git a/profiles/testbot.lua b/profiles/testbot.lua
index a796be21ff5..aabc028a46c 100644
--- a/profiles/testbot.lua
+++ b/profiles/testbot.lua
@@ -15,8 +15,8 @@ function setup()
max_speed_for_map_matching = 30/3.6, --km -> m/s
weight_name = 'duration',
process_call_tagless_node = false,
- u_turn_penalty = 20,
- traffic_light_penalty = 7, -- seconds
+ u_turn_penalty = 20,
+ traffic_signal_penalty = 7, -- seconds
use_turn_restrictions = true
},
@@ -131,7 +131,7 @@ function process_turn (profile, turn)
turn.weight = turn.weight + profile.properties.u_turn_penalty
end
if turn.has_traffic_light then
- turn.duration = turn.duration + profile.properties.traffic_light_penalty
+ turn.duration = turn.duration + profile.properties.traffic_signal_penalty
end
end
diff --git a/scripts/check_taginfo.py b/scripts/check_taginfo.py
index c71b46882e3..2e664799f40 100755
--- a/scripts/check_taginfo.py
+++ b/scripts/check_taginfo.py
@@ -19,10 +19,12 @@
valid_strings = [t["key"] for t in taginfo["tags"]]
valid_strings += [t["value"] for t in taginfo["tags"] if "value" in t]
-valid_strings += [t["value"].lower() for t in taginfo["tags"] if "value" in t] # lower is for max speed
+valid_strings += [
+ t["value"].lower() for t in taginfo["tags"] if "value" in t
+] # lower is for max speed
valid_strings = set(valid_strings)
-string_regxp = re.compile("\"([\d\w\_:]+)\"")
+string_regxp = re.compile(r"\"([\d\w\_:]+)\"")
profile = None
with open(profile_path) as f:
@@ -40,7 +42,7 @@
errors = []
for token in tokens:
if token not in WHITELIST and token not in valid_strings:
- idx = line.find("\""+token+"\"")
+ idx = line.find('"' + token + '"')
errors.append((idx, token))
errors = sorted(errors)
n_errors += len(errors)
@@ -49,7 +51,7 @@
offset = len(prefix)
for idx, token in errors:
sys.stdout.write(prefix + line)
- marker = " "*(idx+offset) + "~"*(len(token)+2)
+ marker = " " * (idx + offset) + "~" * (len(token) + 2)
print(marker)
if n_errors > 0:
diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp
index b5ab53e25c7..2a447a2741f 100644
--- a/src/extractor/edge_based_graph_factory.cpp
+++ b/src/extractor/edge_based_graph_factory.cpp
@@ -39,16 +39,13 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const util::NodeBasedDynamicGraph &node_based_graph,
EdgeBasedNodeDataContainer &node_data_container,
const CompressedEdgeContainer &compressed_edge_container,
- const std::unordered_set<NodeID> &barrier_nodes,
- const TrafficSignals &traffic_signals,
const std::vector<util::Coordinate> &coordinates,
const NameTable &name_table,
const std::unordered_set<EdgeID> &segregated_edges,
const extractor::LaneDescriptionMap &lane_description_map)
: 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_signals(traffic_signals), m_compressed_edge_container(compressed_edge_container),
+ m_node_based_graph(node_based_graph), m_compressed_edge_container(compressed_edge_container),
name_table(name_table), segregated_edges(segregated_edges),
lane_description_map(lane_description_map)
{
@@ -492,7 +489,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
m_coordinates,
m_compressed_edge_container,
unconditional_node_restriction_map,
- m_barrier_nodes,
+ scripting_environment.m_obstacle_map,
turn_lanes_data,
name_table,
street_name_suffix_table);
@@ -585,76 +582,88 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
}
});
+ // connected_roads.begin()
+ // turn
// Generate edges for either artificial nodes or the main graph
- const auto generate_edge = [this, &scripting_environment, weight_multiplier](
- // what nodes will be used? In most cases this will be the id
- // stored in the edge_data. In case of duplicated nodes (e.g.
- // due to via-way restrictions), one/both of these might
- // refer to a newly added edge based node
- const auto edge_based_node_from,
- const auto edge_based_node_to,
- // the situation of the turn
- const auto node_along_road_entering,
- const auto node_based_edge_from,
- const auto intersection_node,
- const auto node_based_edge_to,
- const auto &turn_angle,
- const auto &road_legs_on_the_right,
- const auto &road_legs_on_the_left,
- const auto &edge_geometries)
+ const auto generate_edge =
+ [this, &scripting_environment, weight_multiplier](
+ // what nodes will be used? In most cases this will be the id
+ // stored in the edge_data. In case of duplicated nodes (e.g.
+ // due to via-way restrictions), one/both of these might
+ // refer to a newly added edge based node
+ const NodeID edge_based_node_from,
+ const NodeID edge_based_node_to,
+ // the situation of the turn
+ const NodeID node_along_road_entering,
+ const EdgeID node_based_edge_from,
+ const NodeID intersection_node,
+ const EdgeID node_based_edge_to,
+ const double &turn_angle,
+ const ExtractionTurnLeg &incoming_road_leg,
+ const ExtractionTurnLeg &outgoing_road_leg,
+ const std::vector<ExtractionTurnLeg> &road_legs_on_the_right,
+ const std::vector<ExtractionTurnLeg> &road_legs_on_the_left,
+ const intersection::IntersectionEdgeGeometries &edge_geometries) -> EdgeWithData
{
const auto &edge_data1 = m_node_based_graph.GetEdgeData(node_based_edge_from);
const auto &edge_data2 = m_node_based_graph.GetEdgeData(node_based_edge_to);
+ const NodeID node_along_road_exiting = m_node_based_graph.GetTarget(node_based_edge_to);
+
BOOST_ASSERT(nbe_to_ebn_mapping[node_based_edge_from] !=
nbe_to_ebn_mapping[node_based_edge_to]);
BOOST_ASSERT(!edge_data1.reversed);
BOOST_ASSERT(!edge_data2.reversed);
// compute weight and duration penalties
- // 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(node_along_road_entering, intersection_node);
- const auto is_uturn =
+ // In theory we shouldn't get a directed obstacle on a turn, as it indicates that
+ // the obstacle direction was potentially ambiguously annotated on the junction
+ // node. But we'll check anyway.
+ const bool is_traffic_light = scripting_environment.m_obstacle_map.any(
+ node_along_road_entering, intersection_node, Obstacle::Type::TrafficSignals);
+ const bool is_uturn =
guidance::getTurnDirection(turn_angle) == guidance::DirectionModifier::UTurn;
- ExtractionTurn extracted_turn(
+ ExtractionTurn extracted_turn{
// general info
turn_angle,
- road_legs_on_the_right.size() + road_legs_on_the_left.size() + 2 - is_uturn,
+ static_cast<int>(road_legs_on_the_right.size() + road_legs_on_the_left.size() + 2 -
+ is_uturn),
is_uturn,
is_traffic_light,
m_edge_based_node_container.GetAnnotation(edge_data1.annotation_data)
.is_left_hand_driving,
// source info
- edge_data1.flags.restricted,
+ edge_data1.flags.IsRestricted(),
m_edge_based_node_container.GetAnnotation(edge_data1.annotation_data).travel_mode,
edge_data1.flags.road_classification.IsMotorwayClass(),
edge_data1.flags.road_classification.IsLinkClass(),
edge_data1.flags.road_classification.GetNumberOfLanes(),
edge_data1.flags.highway_turn_classification,
edge_data1.flags.access_turn_classification,
- ((double)intersection::findEdgeLength(edge_geometries, node_based_edge_from) /
- from_alias<double>(edge_data1.duration)) *
- 36,
+ static_cast<int>(
+ intersection::findEdgeLength(edge_geometries, node_based_edge_from) /
+ from_alias<double>(edge_data1.duration) * 36.0),
edge_data1.flags.road_classification.GetPriority(),
// target info
- edge_data2.flags.restricted,
+ edge_data2.flags.IsRestricted(),
m_edge_based_node_container.GetAnnotation(edge_data2.annotation_data).travel_mode,
edge_data2.flags.road_classification.IsMotorwayClass(),
edge_data2.flags.road_classification.IsLinkClass(),
edge_data2.flags.road_classification.GetNumberOfLanes(),
edge_data2.flags.highway_turn_classification,
edge_data2.flags.access_turn_classification,
- ((double)intersection::findEdgeLength(edge_geometries, node_based_edge_to) /
- from_alias<double>(edge_data2.duration)) *
- 36,
+ static_cast<int>(intersection::findEdgeLength(edge_geometries, node_based_edge_to) /
+ from_alias<double>(edge_data2.duration) * 36.0),
edge_data2.flags.road_classification.GetPriority(),
// connected roads
+ incoming_road_leg,
+ outgoing_road_leg,
road_legs_on_the_right,
- road_legs_on_the_left);
+ road_legs_on_the_left,
+ node_along_road_entering,
+ intersection_node,
+ node_along_road_exiting};
scripting_environment.ProcessTurn(extracted_turn);
@@ -718,8 +727,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
auto buffer = std::make_shared<EdgesPipelineBuffer>();
buffer->nodes_processed = intersection_node_range.size();
- for (auto intersection_node = intersection_node_range.begin(),
- end = intersection_node_range.end();
+ for (NodeID intersection_node = intersection_node_range.begin(),
+ end = intersection_node_range.end();
intersection_node < end;
++intersection_node)
{
@@ -761,32 +770,32 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// an outgoing edge. Therefore, we have to search all connected edges for edges
// entering `b`
- for (const auto &incoming_edge : incoming_edges)
+ for (const intersection::IntersectionEdge &incoming_edge : incoming_edges)
{
++node_based_edge_counter;
- const auto connected_roads =
- extractor::intersection::getConnectedRoadsForEdgeGeometries(
+ const intersection::IntersectionView connected_roads =
+ intersection::getConnectedRoadsForEdgeGeometries(
m_node_based_graph,
m_edge_based_node_container,
unconditional_node_restriction_map,
- m_barrier_nodes,
+ scripting_environment.m_obstacle_map,
turn_lanes_data,
incoming_edge,
edge_geometries,
merged_edge_ids);
// check if this edge is part of a restriction via-way
- const auto is_restriction_via_edge =
+ const bool is_restriction_via_edge =
way_restriction_map.IsViaWayEdge(incoming_edge.node, intersection_node);
- for (const auto &outgoing_edge : outgoing_edges)
+ for (const intersection::IntersectionEdge &outgoing_edge : outgoing_edges)
{
- auto is_turn_allowed =
+ const bool is_turn_allowed =
intersection::isTurnAllowed(m_node_based_graph,
m_edge_based_node_container,
unconditional_node_restriction_map,
- m_barrier_nodes,
+ scripting_environment.m_obstacle_map,
edge_geometries,
turn_lanes_data,
incoming_edge,
@@ -804,10 +813,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
OSRM_ASSERT(turn != connected_roads.end(),
m_coordinates[intersection_node]);
- std::vector<ExtractionTurnLeg> road_legs_on_the_right;
- std::vector<ExtractionTurnLeg> road_legs_on_the_left;
-
- auto get_connected_road_info = [&](const auto &connected_edge)
+ auto get_connected_road_info =
+ [&](const auto &connected_edge) -> ExtractionTurnLeg
{
const auto &edge_data =
m_node_based_graph.GetEdgeData(connected_edge.eid);
@@ -841,23 +848,30 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
is_outgoing = true;
}
+ double distance = intersection::findEdgeLength(edge_geometries,
+ connected_edge.eid);
- return ExtractionTurnLeg(
- edge_data.flags.restricted,
+ return ExtractionTurnLeg{
+ edge_data.flags.IsRestricted(),
edge_data.flags.road_classification.IsMotorwayClass(),
edge_data.flags.road_classification.IsLinkClass(),
edge_data.flags.road_classification.GetNumberOfLanes(),
edge_data.flags.highway_turn_classification,
edge_data.flags.access_turn_classification,
- ((double)intersection::findEdgeLength(edge_geometries,
- connected_edge.eid) /
- from_alias<double>(edge_data.duration)) *
- 36,
+ static_cast<int>(36.0 * distance /
+ from_alias<double>(edge_data.duration)),
+ distance,
edge_data.flags.road_classification.GetPriority(),
is_incoming,
- is_outgoing);
+ is_outgoing};
};
+ ExtractionTurnLeg incoming_road_leg =
+ get_connected_road_info(connected_roads[0]);
+ ExtractionTurnLeg outgoing_road_leg = get_connected_road_info(*turn);
+ std::vector<ExtractionTurnLeg> road_legs_on_the_right;
+ std::vector<ExtractionTurnLeg> road_legs_on_the_left;
+
// all connected roads on the right of a u turn
const auto is_uturn = guidance::getTurnDirection(turn->angle) ==
guidance::DirectionModifier::UTurn;
@@ -959,6 +973,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
outgoing_edge.node,
outgoing_edge.edge,
turn->angle,
+ incoming_road_leg,
+ outgoing_road_leg,
road_legs_on_the_right,
road_legs_on_the_left,
edge_geometries);
@@ -1039,6 +1055,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
outgoing_edge.node,
outgoing_edge.edge,
turn->angle,
+ incoming_road_leg,
+ outgoing_road_leg,
road_legs_on_the_right,
road_legs_on_the_left,
edge_geometries);
@@ -1090,6 +1108,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
outgoing_edge.node,
outgoing_edge.edge,
turn->angle,
+ incoming_road_leg,
+ outgoing_road_leg,
road_legs_on_the_right,
road_legs_on_the_left,
edge_geometries);
diff --git a/src/extractor/extraction_containers.cpp b/src/extractor/extraction_containers.cpp
index 9445c7c252b..879bb1bebea 100644
--- a/src/extractor/extraction_containers.cpp
+++ b/src/extractor/extraction_containers.cpp
@@ -395,7 +395,9 @@ ExtractionContainers::ExtractionContainers()
/**
* Processes the collected data and serializes it.
- * At this point nodes are still referenced by their OSM id.
+ *
+ * In this function the nodes will eventually be converted from their 64bit OSM id to the
+ * internal 32bit OSRM id.
*
* - Identify nodes of ways used in restrictions and maneuver overrides
* - Filter nodes list to nodes that are referenced by ways
@@ -408,12 +410,12 @@ void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environme
{
const auto restriction_ways = IdentifyRestrictionWays();
const auto maneuver_override_ways = IdentifyManeuverOverrideWays();
- const auto traffic_signals = IdentifyTrafficSignals();
+ scripting_environment.m_obstacle_map.preProcess(used_node_id_list, way_node_id_offsets);
PrepareNodes();
PrepareEdges(scripting_environment);
+ scripting_environment.m_obstacle_map.fixupNodes(used_node_id_list);
- PrepareTrafficSignals(traffic_signals);
PrepareManeuverOverrides(maneuver_override_ways);
PrepareRestrictions(restriction_ways);
WriteCharData(name_file_name);
@@ -545,22 +547,6 @@ void ExtractionContainers::PrepareNodes()
log << "ok, after " << TIMER_SEC(write_nodes) << "s";
}
- {
- util::UnbufferedLog log;
- log << "Writing barrier nodes ... ";
- TIMER_START(write_nodes);
- for (const auto osm_id : barrier_nodes)
- {
- const auto node_id = mapExternalToInternalNodeID(
- used_node_id_list.begin(), used_node_id_list.end(), osm_id);
- if (node_id != SPECIAL_NODEID)
- {
- used_barrier_nodes.emplace(node_id);
- }
- }
- log << "ok, after " << TIMER_SEC(write_nodes) << "s";
- }
-
util::Log() << "Processed " << max_internal_node_id << " nodes";
}
@@ -940,49 +926,6 @@ 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>> 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)
@@ -1169,97 +1112,6 @@ 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)
{
diff --git a/src/extractor/extractor.cpp b/src/extractor/extractor.cpp
index 80b327e7179..389d22bcae4 100644
--- a/src/extractor/extractor.cpp
+++ b/src/extractor/extractor.cpp
@@ -176,7 +176,7 @@ std::vector<CompressedNodeBasedGraphEdge> toEdgeList(const util::NodeBasedDynami
* That includes:
* - extracting turn restrictions
* - splitting ways into (directional!) edge segments
- * - checking if nodes are barriers or traffic signal
+ * - checking if nodes are obstacles, that must be kept
* - discarding all tag information: All relevant type information for nodes/ways
* is extracted at this point.
*
@@ -218,8 +218,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
NodeBasedGraphFactory node_based_graph_factory(scripting_environment,
parsed_osm_data.turn_restrictions,
parsed_osm_data.unresolved_maneuver_overrides,
- parsed_osm_data.traffic_signals,
- std::move(parsed_osm_data.barriers),
std::move(parsed_osm_data.osm_coordinates),
std::move(parsed_osm_data.osm_node_ids),
parsed_osm_data.edge_list,
@@ -257,7 +255,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
node_based_graph_factory.GetCompressedEdges().PrintStatistics();
- const auto &barrier_nodes = node_based_graph_factory.GetBarriers();
// stealing the annotation data from the node-based graph
edge_based_nodes_container =
EdgeBasedNodeDataContainer({}, std::move(node_based_graph_factory.GetAnnotationData()));
@@ -274,8 +271,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
BuildEdgeExpandedGraph(node_based_graph,
coordinates,
node_based_graph_factory.GetCompressedEdges(),
- barrier_nodes,
- parsed_osm_data.traffic_signals,
restriction_graph,
segregated_edges,
name_table,
@@ -294,7 +289,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
edge_based_nodes_container,
coordinates,
node_based_graph_factory.GetCompressedEdges(),
- barrier_nodes,
restriction_graph,
name_table,
std::move(parsed_osm_data.turn_lane_map),
@@ -505,6 +499,7 @@ Extractor::ParsedOSMData Extractor::ParseOSMData(ScriptingEnvironment &scripting
{
extractor_callbacks->ProcessNode(result.first, result.second);
}
+
number_of_ways += parsed_buffer.resulting_ways.size();
for (const auto &result : parsed_buffer.resulting_ways)
{
@@ -651,8 +646,6 @@ Extractor::ParsedOSMData Extractor::ParseOSMData(ScriptingEnvironment &scripting
return ParsedOSMData{std::move(turn_lane_map),
std::move(extraction_containers.turn_restrictions),
std::move(extraction_containers.internal_maneuver_overrides),
- std::move(extraction_containers.internal_traffic_signals),
- std::move(extraction_containers.used_barrier_nodes),
std::move(osm_coordinates),
std::move(osm_node_ids),
std::move(extraction_containers.used_edges),
@@ -726,8 +719,6 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container,
- const std::unordered_set<NodeID> &barrier_nodes,
- const TrafficSignals &traffic_signals,
const RestrictionGraph &restriction_graph,
const std::unordered_set<EdgeID> &segregated_edges,
const NameTable &name_table,
@@ -747,8 +738,6 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph,
edge_based_nodes_container,
compressed_edge_container,
- barrier_nodes,
- traffic_signals,
coordinates,
name_table,
segregated_edges,
@@ -836,7 +825,6 @@ void Extractor::ProcessGuidanceTurns(
const extractor::EdgeBasedNodeDataContainer &edge_based_node_container,
const std::vector<util::Coordinate> &node_coordinates,
const CompressedEdgeContainer &compressed_edge_container,
- const std::unordered_set<NodeID> &barrier_nodes,
const RestrictionGraph &restriction_graph,
const NameTable &name_table,
LaneDescriptionMap lane_description_map,
@@ -863,7 +851,7 @@ void Extractor::ProcessGuidanceTurns(
edge_based_node_container,
node_coordinates,
compressed_edge_container,
- barrier_nodes,
+ scripting_environment.m_obstacle_map,
unconditional_node_restriction_map,
way_restriction_map,
name_table,
diff --git a/src/extractor/extractor_callbacks.cpp b/src/extractor/extractor_callbacks.cpp
index 5e47f15e3c6..b89ce671040 100644
--- a/src/extractor/extractor_callbacks.cpp
+++ b/src/extractor/extractor_callbacks.cpp
@@ -41,10 +41,9 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containe
std::unordered_map<std::string, ClassData> &classes_map,
LaneDescriptionMap &lane_description_map,
const ProfileProperties &properties)
- : external_memory(extraction_containers_), classes_map(classes_map),
- lane_description_map(lane_description_map),
+ : classes_map(classes_map), lane_description_map(lane_description_map),
fallback_to_duration(properties.fallback_to_duration),
- force_split_edges(properties.force_split_edges)
+ force_split_edges(properties.force_split_edges), external_memory(extraction_containers_)
{
// we reserved 0, 1, 2, 3, 4 for the empty case
string_map[MapKey("", "", "", "", "")] = 0;
@@ -57,24 +56,13 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containe
*
* warning: caller needs to take care of synchronization!
*/
-void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
- const ExtractionNode &result_node)
+void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node, const ExtractionNode &)
{
- const auto id = OSMNodeID{static_cast<std::uint64_t>(input_node.id())};
-
+ const auto id = to_alias<OSMNodeID>(input_node.id());
external_memory.all_nodes_list.push_back(
QueryNode{util::toFixed(util::UnsafeFloatLongitude{input_node.location().lon()}),
util::toFixed(util::UnsafeFloatLatitude{input_node.location().lat()}),
id});
-
- if (result_node.barrier)
- {
- external_memory.barrier_nodes.push_back(id);
- }
- if (result_node.traffic_lights != TrafficLightClass::NONE)
- {
- external_memory.external_traffic_signals.push_back({id, result_node.traffic_lights});
- }
}
void ExtractorCallbacks::ProcessRestriction(const InputTurnRestriction &restriction)
diff --git a/src/extractor/graph_compressor.cpp b/src/extractor/graph_compressor.cpp
index 931668f2676..b410b4ab3e2 100644
--- a/src/extractor/graph_compressor.cpp
+++ b/src/extractor/graph_compressor.cpp
@@ -19,9 +19,7 @@ namespace osrm::extractor
static constexpr int SECOND_TO_DECISECOND = 10;
-void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
- TrafficSignals &traffic_signals,
- ScriptingEnvironment &scripting_environment,
+void GraphCompressor::Compress(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
util::NodeBasedDynamicGraph &graph,
@@ -30,6 +28,7 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
{
const unsigned original_number_of_nodes = graph.GetNumberOfNodes();
const unsigned original_number_of_edges = graph.GetNumberOfEdges();
+ const std::vector<ExtractionTurnLeg> no_other_roads;
TurnPathCompressor turn_path_compressor(turn_restrictions, maneuver_overrides);
@@ -76,8 +75,9 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
continue;
}
- // don't contract barrier node
- if (barrier_nodes.end() != barrier_nodes.find(node_v))
+ // don't compress nodes with these obstacle types
+ if (scripting_environment.m_obstacle_map.any(
+ SPECIAL_NODEID, node_v, Obstacle::Type::Incompressible))
{
continue;
}
@@ -160,8 +160,7 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
graph.GetEdgeData(reverse_e1).reversed));
/*
* Remember Lane Data for compressed parts. This handles scenarios where lane-data
- * is
- * only kept up until a traffic light.
+ * is only kept up until a traffic light.
*
* | |
* ---------------- |
@@ -173,17 +172,14 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
*
* u ------- v ---- w
*
- * Since the edge is compressable, we can transfer:
- * "left|right" (uv) and "" (uw) into a string with "left|right" (uw) for the
- * compressed
- * edge.
- * Doing so, we might mess up the point from where the lanes are shown. It should be
- * reasonable, since the announcements have to come early anyhow. So there is a
- * potential danger in here, but it saves us from adding a lot of additional edges
- * for
- * turn-lanes. Without this, we would have to treat any turn-lane beginning/ending
- * just
- * like a barrier.
+ * Since the edge is compressible, we can transfer: "left|right" (uv)
+ * and "" (uw) into a string with "left|right" (uw) for the compressed
+ * edge. Doing so, we might mess up the point from where the lanes are
+ * shown. It should be reasonable, since the announcements have to come
+ * early anyhow. So there is a potential danger in here, but it saves us
+ * from adding a lot of additional edges for turn-lanes. Without this,
+ * we would have to treat any turn-lane beginning or ending just like an
+ * obstacle.
*/
const auto selectAnnotation =
[&node_data_container](const AnnotationID front_annotation,
@@ -208,70 +204,9 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
graph.GetEdgeData(reverse_e2).annotation_data = selectAnnotation(
rev_edge_data2.annotation_data, rev_edge_data1.annotation_data);
- // Add node penalty when compress edge crosses a traffic signal
- 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 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,
- 2,
- false,
- true,
- false,
- false,
- TRAVEL_MODE_DRIVING,
- false,
- false,
- 1,
- 0,
- 0,
- 0,
- 0,
- false,
- TRAVEL_MODE_DRIVING,
- false,
- false,
- 1,
- 0,
- 0,
- 0,
- 0,
- roads_on_the_right,
- roads_on_the_left);
- scripting_environment.ProcessTurn(extraction_turn);
-
- auto update_direction_penalty =
- [&extraction_turn, weight_multiplier](
- bool signal, EdgeDuration &duration_penalty, EdgeWeight &weight_penalty)
- {
- if (signal)
- {
- duration_penalty = to_alias<EdgeDuration>(extraction_turn.duration *
- SECOND_TO_DECISECOND);
- weight_penalty =
- to_alias<EdgeWeight>(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);
- }
+ // 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;
// Get weights before graph is modified
const auto forward_weight1 = fwd_edge_data1.weight;
@@ -302,33 +237,60 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
BOOST_ASSERT(EdgeWeight{0} != reverse_weight1);
BOOST_ASSERT(EdgeWeight{0} != reverse_weight2);
- auto apply_e2_to_e1 = [&graph](EdgeID edge1,
- EdgeID edge2,
- EdgeWeight &weight_penalty,
- EdgeDuration &duration_penalty)
+ struct EdgePenalties
{
- auto &edge1_data = graph.GetEdgeData(edge1);
- const auto &edge2_data = graph.GetEdgeData(edge2);
- edge1_data.weight += edge2_data.weight;
- edge1_data.duration += edge2_data.duration;
- edge1_data.distance += edge2_data.distance;
- if (weight_penalty != INVALID_EDGE_WEIGHT &&
- duration_penalty != MAXIMAL_EDGE_DURATION)
- {
- edge1_data.weight += weight_penalty;
- edge1_data.duration += duration_penalty;
- // Note: no penalties for distances
- }
+ EdgeDuration duration;
+ EdgeWeight weight;
+ };
+
+ auto update_edge =
+ [](EdgeData &to, const EdgeData &from, const EdgePenalties &penalties)
+ {
+ to.weight += from.weight;
+ to.duration += from.duration;
+ to.distance += from.distance;
+ to.weight += penalties.weight;
+ to.duration += penalties.duration;
+ };
+
+ // Add the obstacle's penalties to the edge when compressing an edge with
+ // an obstacle
+ auto get_obstacle_penalty = [&scripting_environment,
+ weight_multiplier,
+ no_other_roads](const NodeID from,
+ const NodeID via,
+ const NodeID to,
+ const EdgeData &from_edge,
+ const EdgeData &to_edge,
+ EdgePenalties &penalties)
+ {
+ // generate an artificial turn for the turn penalty generation
+ ExtractionTurn fake_turn{
+ from, via, to, from_edge, to_edge, no_other_roads, no_other_roads};
+ scripting_environment.ProcessTurn(fake_turn);
+ penalties.duration +=
+ to_alias<EdgeDuration>(fake_turn.duration * SECOND_TO_DECISECOND);
+ penalties.weight += to_alias<EdgeWeight>(fake_turn.weight * weight_multiplier);
};
- apply_e2_to_e1(forward_e1,
- forward_e2,
- forward_node_weight_penalty,
- forward_node_duration_penalty);
- apply_e2_to_e1(reverse_e1,
- reverse_e2,
- reverse_node_weight_penalty,
- reverse_node_duration_penalty);
+ auto &f1_data = graph.GetEdgeData(forward_e1);
+ auto &b1_data = graph.GetEdgeData(reverse_e1);
+ const auto &f2_data = graph.GetEdgeData(forward_e2);
+ const auto &b2_data = graph.GetEdgeData(reverse_e2);
+
+ EdgePenalties forward_penalties{{0}, {0}};
+ EdgePenalties backward_penalties{{0}, {0}};
+
+ if (scripting_environment.m_obstacle_map.any(node_v))
+ {
+ get_obstacle_penalty(
+ node_u, node_v, node_w, f1_data, f2_data, forward_penalties);
+ get_obstacle_penalty(
+ node_w, node_v, node_u, b1_data, b2_data, backward_penalties);
+ }
+
+ update_edge(f1_data, f2_data, forward_penalties);
+ update_edge(b1_data, b2_data, backward_penalties);
// extend e1's to targets of e2's
graph.SetTarget(forward_e1, node_w);
@@ -341,28 +303,20 @@ 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);
- // Update traffic signal paths containing compressed node.
- traffic_signals.Compress(node_u, node_v, node_w);
+ // Update obstacle paths containing the compressed node.
+ scripting_environment.m_obstacle_map.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)
+ // Forward and backward penalties must both be valid or both be invalid.
+ auto set_dummy_penalty = [](EdgePenalties &f, EdgePenalties &b)
{
- if (weight_penalty == INVALID_EDGE_WEIGHT &&
- other_weight_penalty != INVALID_EDGE_WEIGHT)
+ if (f.weight == INVALID_EDGE_WEIGHT && b.weight != INVALID_EDGE_WEIGHT)
{
- weight_penalty = {0};
- duration_penalty = {0};
+ f.weight = {0};
+ f.duration = {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);
+ set_dummy_penalty(forward_penalties, backward_penalties);
+ set_dummy_penalty(backward_penalties, forward_penalties);
// store compressed geometry in container
geometry_compressor.CompressEdge(forward_e1,
@@ -373,8 +327,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
forward_weight2,
forward_duration1,
forward_duration2,
- forward_node_weight_penalty,
- forward_node_duration_penalty);
+ forward_penalties.weight,
+ forward_penalties.duration);
geometry_compressor.CompressEdge(reverse_e1,
reverse_e2,
node_v,
@@ -383,8 +337,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
reverse_weight2,
reverse_duration1,
reverse_duration2,
- reverse_node_weight_penalty,
- reverse_node_duration_penalty);
+ backward_penalties.weight,
+ backward_penalties.duration);
}
}
}
diff --git a/src/extractor/intersection/intersection_analysis.cpp b/src/extractor/intersection/intersection_analysis.cpp
index 2850e06235a..d8b68c644db 100644
--- a/src/extractor/intersection/intersection_analysis.cpp
+++ b/src/extractor/intersection/intersection_analysis.cpp
@@ -434,7 +434,7 @@ bool isTurnRestricted(RestrictionsRange restrictions, const NodeID to)
bool isTurnAllowed(const util::NodeBasedDynamicGraph &graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const IntersectionEdgeGeometries &geometries,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &from,
@@ -506,14 +506,18 @@ bool isTurnAllowed(const util::NodeBasedDynamicGraph &graph,
}
}
- // 3) if the intersection has a barrier
- const bool is_barrier_node = barrier_nodes.find(intersection_node) != barrier_nodes.end();
+ // 3) if the intersection has an obstacle or is a designated turning place
+
+ bool is_barrier_node =
+ obstacle_nodes.any(SPECIAL_NODEID, intersection_node, Obstacle::Type::Barrier);
+ bool is_turning_node =
+ obstacle_nodes.any(SPECIAL_NODEID, intersection_node, Obstacle::Type::Turning);
// Check a U-turn
if (from.node == destination_node)
{
- // Allow U-turns before barrier nodes
- if (is_barrier_node)
+ // Allow U-turns before barrier nodes or at designated turning places
+ if (is_barrier_node || is_turning_node)
return true;
// Allow U-turns at dead-ends
@@ -597,7 +601,7 @@ bool isTurnAllowed(const util::NodeBasedDynamicGraph &graph,
IntersectionView convertToIntersectionView(const util::NodeBasedDynamicGraph &graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const IntersectionEdgeGeometries &edge_geometries,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge,
@@ -625,7 +629,7 @@ IntersectionView convertToIntersectionView(const util::NodeBasedDynamicGraph &gr
const auto is_turn_allowed = intersection::isTurnAllowed(graph,
node_data_container,
restriction_map,
- barrier_nodes,
+ obstacle_nodes,
edge_geometries,
turn_lanes_data,
incoming_edge,
@@ -748,7 +752,7 @@ IntersectionView getConnectedRoads(const util::NodeBasedDynamicGraph &graph,
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge)
{
@@ -760,7 +764,7 @@ IntersectionView getConnectedRoads(const util::NodeBasedDynamicGraph &graph,
return getConnectedRoadsForEdgeGeometries(graph,
node_data_container,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
incoming_edge,
edge_geometries,
@@ -771,7 +775,7 @@ IntersectionView
getConnectedRoadsForEdgeGeometries(const util::NodeBasedDynamicGraph &graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge,
const IntersectionEdgeGeometries &edge_geometries,
@@ -802,7 +806,7 @@ getConnectedRoadsForEdgeGeometries(const util::NodeBasedDynamicGraph &graph,
return convertToIntersectionView(graph,
node_data_container,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
processed_edge_geometries,
turn_lanes_data,
incoming_edge,
@@ -816,7 +820,7 @@ getConnectedRoads<false>(const util::NodeBasedDynamicGraph &graph,
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge);
@@ -826,7 +830,7 @@ getConnectedRoads<true>(const util::NodeBasedDynamicGraph &graph,
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data,
const IntersectionEdge &incoming_edge);
diff --git a/src/extractor/intersection/mergable_road_detector.cpp b/src/extractor/intersection/mergable_road_detector.cpp
index adfb601cb44..69d93d80af3 100644
--- a/src/extractor/intersection/mergable_road_detector.cpp
+++ b/src/extractor/intersection/mergable_road_detector.cpp
@@ -54,13 +54,13 @@ MergableRoadDetector::MergableRoadDetector(
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const NameTable &name_table,
const SuffixTable &street_name_suffix_table)
: node_based_graph(node_based_graph), node_data_container(node_data_container),
node_coordinates(node_coordinates), compressed_geometries(compressed_geometries),
- node_restriction_map(node_restriction_map), barrier_nodes(barrier_nodes),
+ node_restriction_map(node_restriction_map), obstacle_nodes(obstacle_nodes),
turn_lanes_data(turn_lanes_data), name_table(name_table),
street_name_suffix_table(street_name_suffix_table),
coordinate_extractor(node_based_graph, compressed_geometries, node_coordinates)
@@ -180,7 +180,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data),
right_accumulator(SMALL_RANDOM_HOPLIMIT,
node_based_graph,
@@ -188,7 +188,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data);
/* Standard following the straightmost road
@@ -206,7 +206,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data);
graph_walker.TraverseRoad(intersection_node, lhs.eid, left_accumulator, selector);
/* if the intersection does not have a right turn, we continue onto the next one once
@@ -286,7 +286,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data);
graph_walker.TraverseRoad(node_based_graph.GetTarget(left_accumulator.via_edge_id),
connector_turn->eid,
@@ -307,7 +307,7 @@ bool MergableRoadDetector::IsCircularShape(const NodeID intersection_node,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data);
const auto getCoordinatesAlongWay = [&](const EdgeID edge_id, const double max_length)
{
@@ -351,7 +351,7 @@ bool MergableRoadDetector::IsCircularShape(const NodeID intersection_node,
// ---- ----
// \ /
// -------
- const auto constexpr CIRCULAR_POLYGON_ISOPERIMETRIC_LOWER_BOUND = 0.85 / (4 * std::numbers::pi);
+ const auto CIRCULAR_POLYGON_ISOPERIMETRIC_LOWER_BOUND = 0.85 / (4 * std::numbers::pi);
if (connect_again && coordinates_to_the_left.front() == coordinates_to_the_left.back())
{ // if the left and right roads connect again and are closed polygons ...
const auto area = util::coordinate_calculation::computeArea(coordinates_to_the_left);
@@ -380,7 +380,7 @@ bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data);
const auto getCoordinatesAlongWay = [&](const EdgeID edge_id, const double max_length)
{
@@ -565,7 +565,7 @@ bool MergableRoadDetector::IsLinkRoad(const NodeID intersection_node,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
next_intersection_parameters);
const auto extract_name_id = [this](const MergableRoadData &road)
diff --git a/src/extractor/intersection/node_based_graph_walker.cpp b/src/extractor/intersection/node_based_graph_walker.cpp
index c1ee0fc642e..3f9414a2502 100644
--- a/src/extractor/intersection/node_based_graph_walker.cpp
+++ b/src/extractor/intersection/node_based_graph_walker.cpp
@@ -17,11 +17,11 @@ NodeBasedGraphWalker::NodeBasedGraphWalker(
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data)
: node_based_graph(node_based_graph), node_data_container(node_data_container),
node_coordinates(node_coordinates), compressed_geometries(compressed_geometries),
- node_restriction_map(node_restriction_map), barrier_nodes(barrier_nodes),
+ node_restriction_map(node_restriction_map), obstacle_nodes(obstacle_nodes),
turn_lanes_data(turn_lanes_data)
{
}
@@ -252,12 +252,12 @@ IntersectionFinderAccumulator::IntersectionFinderAccumulator(
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const ObstacleMap &obstacle_nodes,
const TurnLanesIndexedArray &turn_lanes_data)
: hops(0), hop_limit(hop_limit), node_based_graph(node_based_graph),
node_data_container(node_data_container), node_coordinates(node_coordinates),
compressed_geometries(compressed_geometries), node_restriction_map(node_restriction_map),
- barrier_nodes(barrier_nodes), turn_lanes_data(turn_lanes_data)
+ obstacle_nodes(obstacle_nodes), turn_lanes_data(turn_lanes_data)
{
}
@@ -287,7 +287,7 @@ void IntersectionFinderAccumulator::update(const NodeID from_node,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
{from_node, via_edge});
}
diff --git a/src/extractor/node_based_graph_factory.cpp b/src/extractor/node_based_graph_factory.cpp
index 9fb50149d4d..b11d39f1a9b 100644
--- a/src/extractor/node_based_graph_factory.cpp
+++ b/src/extractor/node_based_graph_factory.cpp
@@ -17,17 +17,15 @@ NodeBasedGraphFactory::NodeBasedGraphFactory(
ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
- TrafficSignals &traffic_signals,
- std::unordered_set<NodeID> &&barriers,
std::vector<util::Coordinate> &&coordinates,
extractor::PackedOSMIDs &&osm_node_ids,
const std::vector<NodeBasedEdge> &edge_list,
std::vector<NodeBasedEdgeAnnotation> &&annotation_data)
- : annotation_data(std::move(annotation_data)), barriers(std::move(barriers)),
- coordinates(std::move(coordinates)), osm_node_ids(std::move(osm_node_ids))
+ : annotation_data(std::move(annotation_data)), coordinates(std::move(coordinates)),
+ osm_node_ids(std::move(osm_node_ids))
{
BuildCompressedOutputGraph(edge_list);
- Compress(scripting_environment, turn_restrictions, maneuver_overrides, traffic_signals);
+ Compress(scripting_environment, turn_restrictions, maneuver_overrides);
CompressGeometry();
CompressAnnotationData();
}
@@ -75,13 +73,10 @@ void NodeBasedGraphFactory::BuildCompressedOutputGraph(const std::vector<NodeBas
void NodeBasedGraphFactory::Compress(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
- std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
- TrafficSignals &traffic_signals)
+ std::vector<UnresolvedManeuverOverride> &maneuver_overrides)
{
GraphCompressor graph_compressor;
- graph_compressor.Compress(barriers,
- traffic_signals,
- scripting_environment,
+ graph_compressor.Compress(scripting_environment,
turn_restrictions,
maneuver_overrides,
compressed_output_graph,
diff --git a/src/extractor/obstacles.cpp b/src/extractor/obstacles.cpp
new file mode 100644
index 00000000000..b4ca86617f5
--- /dev/null
+++ b/src/extractor/obstacles.cpp
@@ -0,0 +1,159 @@
+/*
+
+Copyright (c) 2025, Project OSRM contributors
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "extractor/obstacles.hpp"
+
+#include "util/log.hpp"
+#include "util/timing_util.hpp"
+
+namespace osrm::extractor
+{
+
+const std::initializer_list<std::pair<std::string_view, Obstacle::Type>>
+ Obstacle::enum_type_initializer_list{{"none", Obstacle::Type::None},
+ {"barrier", Obstacle::Type::Barrier},
+ {"traffic_signals", Obstacle::Type::TrafficSignals},
+ {"stop", Obstacle::Type::Stop},
+ {"stop_minor", Obstacle::Type::StopMinor},
+ {"give_way", Obstacle::Type::GiveWay},
+ {"crossing", Obstacle::Type::Crossing},
+ {"traffic_calming", Obstacle::Type::TrafficCalming},
+ {"mini_roundabout", Obstacle::Type::MiniRoundabout},
+ {"turning_loop", Obstacle::Type::TurningLoop},
+ {"turning_circle", Obstacle::Type::TurningCircle}};
+
+const std::initializer_list<std::pair<std::string_view, Obstacle::Direction>>
+ Obstacle::enum_direction_initializer_list{{"none", Obstacle::Direction::None},
+ {"forward", Obstacle::Direction::Forward},
+ {"backward", Obstacle::Direction::Backward},
+ {"both", Obstacle::Direction::Both}};
+
+void ObstacleMap::preProcess(const NodeIDVector &node_ids, const WayNodeIDOffsets &way_node_offsets)
+{
+ util::UnbufferedLog log;
+ log << "Collecting information on " << osm_obstacles.size() << " obstacles...";
+ TIMER_START(preProcess);
+
+ // build a map to speed up the next step
+ // multimap of OSMNodeId to index into way_node_offsets
+ std::unordered_multimap<OSMNodeID, size_t> node2start_index;
+
+ for (size_t i = 0, j = 1; j < way_node_offsets.size(); ++i, ++j)
+ {
+ for (size_t k = way_node_offsets[i]; k < way_node_offsets[j]; ++k)
+ {
+ node2start_index.emplace(node_ids[k], i);
+ }
+ }
+
+ // for each unidirectional obstacle
+ // for each way that crosses the obstacle
+ // for each node of the crossing way
+ // find the node immediately before or after the obstacle
+ // add the unidirectional obstacle
+ // note that we don't remove the bidirectional obstacle here,
+ // but in fixupNodes()
+
+ for (auto &[from_id, to_id, obstacle] : osm_obstacles)
+ {
+ if (obstacle.direction == Obstacle::Direction::Forward ||
+ obstacle.direction == Obstacle::Direction::Backward)
+ {
+ bool forward = obstacle.direction == Obstacle::Direction::Forward;
+ auto [wno_begin, wno_end] = node2start_index.equal_range(to_id);
+ // for each way that crosses the obstacle
+ for (auto wno_iter = wno_begin; wno_iter != wno_end; ++wno_iter)
+ {
+ using NodeIdIterator = NodeIDVector::const_iterator;
+
+ NodeIdIterator begin = node_ids.cbegin() + way_node_offsets[wno_iter->second];
+ NodeIdIterator end = node_ids.cbegin() + way_node_offsets[wno_iter->second + 1];
+ if (forward)
+ ++begin;
+ else
+ --end;
+
+ NodeIdIterator node_iter = find(begin, end, to_id);
+ if (node_iter != end)
+ {
+ osm_obstacles.emplace_back(*(node_iter + (forward ? -1 : 1)), to_id, obstacle);
+ }
+ }
+ }
+ }
+
+ TIMER_STOP(preProcess);
+ log << "ok, after " << TIMER_SEC(preProcess) << "s";
+}
+
+void ObstacleMap::fixupNodes(const NodeIDVector &node_ids)
+{
+ const auto begin = node_ids.cbegin();
+ const auto end = node_ids.cend();
+
+ auto osm_to_internal = [&](const OSMNodeID &osm_node) -> NodeID
+ {
+ if (osm_node == SPECIAL_OSM_NODEID)
+ {
+ return SPECIAL_NODEID;
+ }
+ const auto it = std::lower_bound(begin, end, osm_node);
+ return (it == end || osm_node < *it) ? SPECIAL_NODEID
+ : static_cast<NodeID>(std::distance(begin, it));
+ };
+
+ for (const auto &[osm_from, osm_to, obstacle] : osm_obstacles)
+ {
+ if ((obstacle.direction == Obstacle::Direction::Forward ||
+ obstacle.direction == Obstacle::Direction::Backward) &&
+ osm_from == SPECIAL_OSM_NODEID)
+ // drop these bidirectional entries because we have generated an
+ // unidirectional copy of them
+ continue;
+ emplace(osm_to_internal(osm_from), osm_to_internal(osm_to), obstacle);
+ }
+ osm_obstacles.clear();
+}
+
+void ObstacleMap::compress(NodeID node1, NodeID delendus, NodeID node2)
+{
+ auto comp = [this, delendus](NodeID first, NodeID last)
+ {
+ const auto &[begin, end] = obstacles.equal_range(last);
+ for (auto i = begin; i != end; ++i)
+ {
+ auto &[from, to, obstacle] = i->second;
+ if (from == delendus)
+ from = first;
+ }
+ };
+
+ comp(node1, node2);
+ comp(node2, node1);
+}
+
+} // namespace osrm::extractor
diff --git a/src/extractor/scripting_environment_lua.cpp b/src/extractor/scripting_environment_lua.cpp
index 9aaf7977812..ca565751c80 100644
--- a/src/extractor/scripting_environment_lua.cpp
+++ b/src/extractor/scripting_environment_lua.cpp
@@ -6,11 +6,11 @@
#include "extractor/extraction_segment.hpp"
#include "extractor/extraction_turn.hpp"
#include "extractor/extraction_way.hpp"
+#include "extractor/graph_compressor.hpp"
#include "extractor/internal_extractor_edge.hpp"
#include "extractor/maneuver_override_relation_parser.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
-#include "extractor/raster_source.hpp"
#include "extractor/restriction_parser.hpp"
#include "guidance/turn_instruction.hpp"
@@ -99,11 +99,12 @@ void handle_lua_error(const sol::protected_function_result &luares)
const auto msg = luaerr.what();
if (msg != nullptr)
{
- std::cerr << msg << "\n";
+ // util::Log is thread-safe
+ util::UnbufferedLog(logERROR) << msg << "\n";
}
else
{
- std::cerr << "unknown error\n";
+ util::UnbufferedLog(logERROR) << "unknown error\n";
}
throw util::exception("Lua error (see stderr for traceback)");
}
@@ -303,40 +304,96 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
context.state.new_enum("traffic_lights",
"none",
- extractor::TrafficLightClass::NONE,
+ Obstacle::Direction::None,
"direction_all",
- extractor::TrafficLightClass::DIRECTION_ALL,
+ Obstacle::Direction::Both,
"direction_forward",
- extractor::TrafficLightClass::DIRECTION_FORWARD,
+ Obstacle::Direction::Forward,
"direction_reverse",
- extractor::TrafficLightClass::DIRECTION_REVERSE);
+ Obstacle::Direction::Backward);
+
+ context.state.new_enum("obstacle_type", Obstacle::enum_type_initializer_list);
+ context.state.new_enum("obstacle_direction", Obstacle::enum_direction_initializer_list);
+
+ context.state.new_usertype<Obstacle>(
+ "Obstacle",
+ sol::constructors<Obstacle(Obstacle::Type),
+ Obstacle(Obstacle::Type, Obstacle::Direction),
+ Obstacle(Obstacle::Type, Obstacle::Direction, float, float)>(),
+ "type",
+ sol::readonly(&Obstacle::type),
+ "direction",
+ sol::readonly(&Obstacle::direction),
+ "duration",
+ sol::readonly(&Obstacle::duration),
+ "weight",
+ sol::readonly(&Obstacle::weight));
+
+ context.state.new_usertype<ObstacleMap>(
+ "ObstacleMap",
+ "add",
+ [](ObstacleMap &obstacles, const osmium::Node &from, Obstacle obstacle)
+ {
+ OSMNodeID id = to_alias<OSMNodeID>(from.id());
+ obstacles.emplace(id, obstacle);
+ },
+ "get",
+ sol::overload([](const ObstacleMap &om, NodeID to) { return om.get(to); },
+ [](const ObstacleMap &om, NodeID from, NodeID to)
+ { return om.get(from, to); },
+ [](const ObstacleMap &om, NodeID from, NodeID to, Obstacle::Type type)
+ { return om.get(from, to, type); }),
+ "any",
+ sol::overload([](const ObstacleMap &om, NodeID to) { return om.any(to); },
+ [](const ObstacleMap &om, NodeID from, NodeID to)
+ { return om.any(from, to, Obstacle::Type::All); },
+ [](const ObstacleMap &om, NodeID from, NodeID to, Obstacle::Type type)
+ { return om.any(from, to, type); }));
+
+ context.state["obstacle_map"] = std::ref(m_obstacle_map);
context.state.new_usertype<ExtractionNode>(
"ResultNode",
+ // for API compatibility only
"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;
- }
- }),
+ sol::property(
+ [&context, this](ExtractionNode &node, const sol::object &obj)
+ {
+ if (obj.is<Obstacle::Direction>())
+ {
+ m_obstacle_map.emplace(
+ to_alias<OSMNodeID>(node.node->id()),
+ Obstacle{Obstacle::Type::TrafficSignals,
+ obj.as<Obstacle::Direction>(),
+ static_cast<float>(context.properties.GetTrafficSignalPenalty()),
+ 0});
+ return;
+ }
+ if (obj.is<bool>() && obj.as<bool>())
+ {
+ // The old approach of assigning a boolean traffic light
+ // state to the node
+ // TODO: Make a breaking API change and remove this option.
+ m_obstacle_map.emplace(
+ to_alias<OSMNodeID>(node.node->id()),
+ Obstacle{Obstacle::Type::TrafficSignals,
+ Obstacle::Direction::Both,
+ static_cast<float>(context.properties.GetTrafficSignalPenalty()),
+ 0});
+ }
+ }),
+ // for API compatibility only
"barrier",
- &ExtractionNode::barrier);
+ sol::property(
+ [this](ExtractionNode &node, const sol::object &obj)
+ {
+ if (obj.is<bool>() && obj.as<bool>())
+ {
+ m_obstacle_map.emplace(
+ to_alias<OSMNodeID>(node.node->id()),
+ Obstacle{Obstacle::Type::Barrier, Obstacle::Direction::Both});
+ }
+ }));
context.state.new_usertype<RoadClassification>(
"RoadClassification",
@@ -807,6 +864,8 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
&ExtractionTurnLeg::access_turn_classification,
"speed",
&ExtractionTurnLeg::speed,
+ "distance",
+ &ExtractionTurnLeg::distance,
"priority_class",
&ExtractionTurnLeg::priority_class,
"is_incoming",
@@ -865,10 +924,21 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"target_priority_class",
&ExtractionTurn::target_priority_class,
+ "from",
+ &ExtractionTurn::from,
+ "via",
+ &ExtractionTurn::via,
+ "to",
+ &ExtractionTurn::to,
+ "source_road",
+ &ExtractionTurn::source_road,
+ "target_road",
+ &ExtractionTurn::target_road,
"roads_on_the_right",
&ExtractionTurn::roads_on_the_right,
"roads_on_the_left",
&ExtractionTurn::roads_on_the_left,
+
"weight",
&ExtractionTurn::weight,
"duration",
@@ -975,13 +1045,13 @@ void Sol2ScriptingEnvironment::ProcessElements(
case osmium::item_type::node:
{
const auto &node = static_cast<const osmium::Node &>(*entity);
- // NOLINTNEXTLINE(bugprone-use-after-move)
- result_node.clear();
+ result_node.node = &node;
if (local_context.has_node_function &&
(!node.tags().empty() || local_context.properties.call_tagless_node_function))
{
local_context.ProcessNode(node, result_node, relations);
}
+ result_node.node = nullptr;
resulting_nodes.push_back({node, result_node});
}
break;
diff --git a/src/guidance/driveway_handler.cpp b/src/guidance/driveway_handler.cpp
index 5e781a9bb30..20cdf25ef5c 100644
--- a/src/guidance/driveway_handler.cpp
+++ b/src/guidance/driveway_handler.cpp
@@ -10,7 +10,7 @@ DrivewayHandler::DrivewayHandler(const util::NodeBasedDynamicGraph &node_based_g
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
@@ -19,7 +19,7 @@ DrivewayHandler::DrivewayHandler(const util::NodeBasedDynamicGraph &node_based_g
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table)
diff --git a/src/guidance/guidance_processing.cpp b/src/guidance/guidance_processing.cpp
index 2debabb04f8..d26ba8928f2 100644
--- a/src/guidance/guidance_processing.cpp
+++ b/src/guidance/guidance_processing.cpp
@@ -20,7 +20,7 @@ void annotateTurns(const util::NodeBasedDynamicGraph &node_based_graph,
const extractor::EdgeBasedNodeDataContainer &edge_based_node_container,
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_edge_container,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::RestrictionMap &node_restriction_map,
const extractor::WayRestrictionMap &way_restriction_map,
const extractor::NameTable &name_table,
@@ -41,7 +41,7 @@ void annotateTurns(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
suffix_table);
@@ -51,7 +51,7 @@ void annotateTurns(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
suffix_table);
@@ -61,7 +61,7 @@ void annotateTurns(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
lane_description_map,
turn_analysis,
@@ -173,7 +173,7 @@ void annotateTurns(const util::NodeBasedDynamicGraph &node_based_graph,
node_based_graph,
edge_based_node_container,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
edge_geometries,
turn_lanes_data,
incoming_edge,
@@ -213,7 +213,7 @@ void annotateTurns(const util::NodeBasedDynamicGraph &node_based_graph,
extractor::intersection::isTurnAllowed(node_based_graph,
edge_based_node_container,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
edge_geometries,
turn_lanes_data,
incoming_edge,
diff --git a/src/guidance/intersection_handler.cpp b/src/guidance/intersection_handler.cpp
index b11597d5f46..5f839e97a13 100644
--- a/src/guidance/intersection_handler.cpp
+++ b/src/guidance/intersection_handler.cpp
@@ -46,20 +46,20 @@ IntersectionHandler::IntersectionHandler(
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
: node_based_graph(node_based_graph), node_data_container(node_data_container),
node_coordinates(node_coordinates), compressed_geometries(compressed_geometries),
- node_restriction_map(node_restriction_map), barrier_nodes(barrier_nodes),
+ node_restriction_map(node_restriction_map), obstacle_nodes(obstacle_nodes),
turn_lanes_data(turn_lanes_data), name_table(name_table),
street_name_suffix_table(street_name_suffix_table), graph_walker(node_based_graph,
node_data_container,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data)
{
}
@@ -430,7 +430,7 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid,
std::optional<IntersectionHandler::IntersectionViewAndNode>
IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) const
{
- // We use the intersection generator to jump over traffic signals, barriers. The intersection
+ // We use the intersection generator to jump over obstacles. The intersection
// generater takes a starting node and a corresponding edge starting at this node. It returns
// the next non-artificial intersection writing as out param. the source node and the edge
// for which the target is the next intersection.
@@ -458,12 +458,12 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
intersection_parameters);
auto intersection_node = node_based_graph.GetTarget(intersection_parameters.edge);
- if (intersection.size() <= 2 || intersection.isTrafficSignalOrBarrier())
+ if (intersection.size() <= 2 || intersection.isObstacle())
{
return std::nullopt;
}
diff --git a/src/guidance/motorway_handler.cpp b/src/guidance/motorway_handler.cpp
index 5c85e2edf5f..258124d9963 100644
--- a/src/guidance/motorway_handler.cpp
+++ b/src/guidance/motorway_handler.cpp
@@ -44,7 +44,7 @@ MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_g
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
@@ -53,7 +53,7 @@ MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_g
coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table)
diff --git a/src/guidance/roundabout_handler.cpp b/src/guidance/roundabout_handler.cpp
index 451ebf7bf5c..a1390b5c2c0 100644
--- a/src/guidance/roundabout_handler.cpp
+++ b/src/guidance/roundabout_handler.cpp
@@ -24,7 +24,7 @@ RoundaboutHandler::RoundaboutHandler(
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
@@ -33,7 +33,7 @@ RoundaboutHandler::RoundaboutHandler(
coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table),
diff --git a/src/guidance/sliproad_handler.cpp b/src/guidance/sliproad_handler.cpp
index 90a92801f53..d5686632a0b 100644
--- a/src/guidance/sliproad_handler.cpp
+++ b/src/guidance/sliproad_handler.cpp
@@ -22,7 +22,7 @@ SliproadHandler::SliproadHandler(const util::NodeBasedDynamicGraph &node_based_g
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
@@ -31,7 +31,7 @@ SliproadHandler::SliproadHandler(const util::NodeBasedDynamicGraph &node_based_g
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table),
@@ -255,9 +255,9 @@ Intersection SliproadHandler::operator()(const NodeID /*nid*/,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data};
- const extractor::intersection::SkipTrafficSignalBarrierRoadSelector road_selector{};
+ const extractor::intersection::SkipObstacleRoadSelector road_selector{};
(void)graph_walker.TraverseRoad(intersection_node_id, // start node
sliproad_edge, // onto edge
intersection_finder, // accumulator
@@ -585,10 +585,10 @@ Intersection SliproadHandler::operator()(const NodeID /*nid*/,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
{node_based_graph.GetTarget(sliproad_edge), candidate_road.eid});
- if (skip_traffic_light_intersection.isTrafficSignalOrBarrier() &&
+ if (skip_traffic_light_intersection.isObstacle() &&
node_based_graph.GetTarget(skip_traffic_light_intersection[1].eid) ==
main_road_intersection->node)
{
@@ -703,7 +703,7 @@ bool SliproadHandler::nextIntersectionIsTooFarAway(const NodeID start, const Edg
extractor::intersection::DistanceToNextIntersectionAccumulator accumulator{
coordinate_extractor, node_based_graph, threshold};
- const extractor::intersection::SkipTrafficSignalBarrierRoadSelector selector{};
+ const extractor::intersection::SkipObstacleRoadSelector selector{};
(void)graph_walker.TraverseRoad(start, onto, accumulator, selector);
diff --git a/src/guidance/suppress_mode_handler.cpp b/src/guidance/suppress_mode_handler.cpp
index e1356de6b9f..c910732fa6d 100644
--- a/src/guidance/suppress_mode_handler.cpp
+++ b/src/guidance/suppress_mode_handler.cpp
@@ -13,7 +13,7 @@ SuppressModeHandler::SuppressModeHandler(
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
@@ -22,7 +22,7 @@ SuppressModeHandler::SuppressModeHandler(
coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table)
diff --git a/src/guidance/turn_analysis.cpp b/src/guidance/turn_analysis.cpp
index 5e51a5cbe27..08b419d361a 100644
--- a/src/guidance/turn_analysis.cpp
+++ b/src/guidance/turn_analysis.cpp
@@ -19,7 +19,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_edge_container,
const extractor::RestrictionMap &restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
@@ -28,7 +28,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table),
@@ -37,7 +37,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table),
@@ -46,7 +46,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table),
@@ -55,7 +55,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table),
@@ -64,7 +64,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table),
@@ -73,7 +73,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table),
@@ -82,7 +82,7 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
node_coordinates,
compressed_edge_container,
restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table)
diff --git a/src/guidance/turn_discovery.cpp b/src/guidance/turn_discovery.cpp
index 57b66f8a75c..0911a5f22f0 100644
--- a/src/guidance/turn_discovery.cpp
+++ b/src/guidance/turn_discovery.cpp
@@ -18,7 +18,7 @@ bool findPreviousIntersection(const NodeID node_v,
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
// output parameters
NodeID &result_node,
@@ -74,7 +74,7 @@ bool findPreviousIntersection(const NodeID node_v,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
{node_w, u_turn_at_node_w});
// Continue along the straightmost turn. If there is no straight turn, we cannot find a valid
@@ -94,7 +94,7 @@ bool findPreviousIntersection(const NodeID node_v,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
{node_v, straightmost_at_v_in_reverse->eid});
@@ -120,7 +120,7 @@ bool findPreviousIntersection(const NodeID node_v,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
{node_u, result_via_edge});
const auto check_via_edge =
diff --git a/src/guidance/turn_handler.cpp b/src/guidance/turn_handler.cpp
index 0a77243604f..5672f62c7b5 100644
--- a/src/guidance/turn_handler.cpp
+++ b/src/guidance/turn_handler.cpp
@@ -110,7 +110,7 @@ TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<util::Coordinate> &coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
const extractor::NameTable &name_table,
const extractor::SuffixTable &street_name_suffix_table)
@@ -119,7 +119,7 @@ TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
name_table,
street_name_suffix_table)
diff --git a/src/guidance/turn_lane_handler.cpp b/src/guidance/turn_lane_handler.cpp
index 19d246bc24e..8622d696cf0 100644
--- a/src/guidance/turn_lane_handler.cpp
+++ b/src/guidance/turn_lane_handler.cpp
@@ -34,14 +34,14 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
const std::vector<util::Coordinate> &node_coordinates,
const extractor::CompressedEdgeContainer &compressed_geometries,
const extractor::RestrictionMap &node_restriction_map,
- const std::unordered_set<NodeID> &barrier_nodes,
+ const extractor::ObstacleMap &obstacle_nodes,
const extractor::TurnLanesIndexedArray &turn_lanes_data,
extractor::LaneDescriptionMap &lane_description_map,
const TurnAnalysis &turn_analysis,
util::guidance::LaneDataIdMap &id_map)
: node_based_graph(node_based_graph), node_data_container(node_data_container),
node_coordinates(node_coordinates), compressed_geometries(compressed_geometries),
- node_restriction_map(node_restriction_map), barrier_nodes(barrier_nodes),
+ node_restriction_map(node_restriction_map), obstacle_nodes(obstacle_nodes),
turn_lanes_data(turn_lanes_data), lane_description_map(lane_description_map),
turn_analysis(turn_analysis), id_map(id_map)
{
@@ -213,7 +213,7 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
previous_node,
previous_via_edge,
@@ -268,7 +268,7 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
return TurnLaneScenario::MERGE;
// Dead end streets that don't have any left-tag. This can happen due to the fallbacks for
- // broken data/barriers.
+ // broken data or obstacles.
const bool has_non_usable_u_turn = (intersection[0].entry_allowed &&
!hasTag(TurnLaneType::none | TurnLaneType::left |
TurnLaneType::sharp_left | TurnLaneType::uturn,
@@ -579,7 +579,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
node_coordinates,
compressed_geometries,
node_restriction_map,
- barrier_nodes,
+ obstacle_nodes,
turn_lanes_data,
{at, straightmost->eid}));
diff --git a/taginfo.json b/taginfo.json
index dfe48f96a6f..c2bb0367d30 100644
--- a/taginfo.json
+++ b/taginfo.json
@@ -124,8 +124,21 @@
{"key": "side_road", "value": "yes", "description": "gets speed penalty"},
{"key": "side_road", "value": "rotary", "description": "gets speed penalty"},
{"key": "route", "object_types": ["way"]},
- {"key": "highway", "value": "traffic_signals", "object_types": ["node"]},
{"key": "highway", "value": "crossing", "object_types": ["node"]},
+ {"key": "highway", "value": "give_way", "object_types": ["node"]},
+ {"key": "highway", "value": "mini_roundabout", "object_types": ["node"]},
+ {"key": "highway", "value": "stop", "object_types": ["node"]},
+ {"key": "highway", "value": "traffic_calming", "object_types": ["node"]},
+ {"key": "highway", "value": "traffic_signals", "object_types": ["node"]},
+ {"key": "highway", "value": "turning_circle", "object_types": ["node"]},
+ {"key": "highway", "value": "turning_loop", "object_types": ["node"]},
+ {"key": "direction", "value": "forward", "object_types": ["node"]},
+ {"key": "direction", "value": "backward", "object_types": ["node"]},
+ {"key": "direction", "value": "both", "object_types": ["node"]},
+ {"key": "traffic_signals:direction", "value": "forward", "object_types": ["node"]},
+ {"key": "traffic_signals:direction", "value": "backward", "object_types": ["node"]},
+ {"key": "traffic_signals:direction", "value": "both", "object_types": ["node"]},
+ {"key": "stop", "value": "minor", "object_types": ["node"]},
{"key": "access", "value": "yes"},
{"key": "access", "value": "motorcar"},
{"key": "access", "value": "motor_vehicle"},
diff --git a/test/data/profiles/bad_node.lua b/test/data/profiles/bad_node.lua
index 74c730587bc..fd974799841 100644
--- a/test/data/profiles/bad_node.lua
+++ b/test/data/profiles/bad_node.lua
@@ -9,8 +9,8 @@ function setup()
max_speed_for_map_matching = 30/3.6, --km -> m/s
weight_name = 'duration',
process_call_tagless_node = false,
- u_turn_penalty = 20,
- traffic_light_penalty = 7, -- seconds
+ u_turn_penalty = 20,
+ traffic_signal_penalty = 7, -- seconds
use_turn_restrictions = true
},
@@ -128,7 +128,7 @@ function process_turn (profile, turn)
turn.weight = turn.weight + profile.properties.u_turn_penalty
end
if turn.has_traffic_light then
- turn.duration = turn.duration + profile.properties.traffic_light_penalty
+ turn.duration = turn.duration + profile.properties.traffic_signal_penalty
end
end
diff --git a/test/data/profiles/bad_segment.lua b/test/data/profiles/bad_segment.lua
index cbb5bac1932..3c33bb542c8 100644
--- a/test/data/profiles/bad_segment.lua
+++ b/test/data/profiles/bad_segment.lua
@@ -9,8 +9,8 @@ function setup()
max_speed_for_map_matching = 30/3.6, --km -> m/s
weight_name = 'duration',
process_call_tagless_node = false,
- u_turn_penalty = 20,
- traffic_light_penalty = 7, -- seconds
+ u_turn_penalty = 20,
+ traffic_signal_penalty = 7, -- seconds
use_turn_restrictions = true
},
@@ -124,7 +124,7 @@ function process_turn (profile, turn)
turn.weight = turn.weight + profile.properties.u_turn_penalty
end
if turn.has_traffic_light then
- turn.duration = turn.duration + profile.properties.traffic_light_penalty
+ turn.duration = turn.duration + profile.properties.traffic_signal_penalty
end
end
diff --git a/test/data/profiles/bad_setup.lua b/test/data/profiles/bad_setup.lua
index 72e32cc40ce..2604ca85f03 100644
--- a/test/data/profiles/bad_setup.lua
+++ b/test/data/profiles/bad_setup.lua
@@ -13,8 +13,8 @@ function setup()
max_speed_for_map_matching = 30/3.6, --km -> m/s
weight_name = 'duration',
process_call_tagless_node = false,
- u_turn_penalty = 20,
- traffic_light_penalty = 7, -- seconds
+ u_turn_penalty = 20,
+ traffic_signal_penalty = 7, -- seconds
use_turn_restrictions = true
},
@@ -128,7 +128,7 @@ function process_turn (profile, turn)
turn.weight = turn.weight + profile.properties.u_turn_penalty
end
if turn.has_traffic_light then
- turn.duration = turn.duration + profile.properties.traffic_light_penalty
+ turn.duration = turn.duration + profile.properties.traffic_signal_penalty
end
end
diff --git a/test/data/profiles/bad_turn.lua b/test/data/profiles/bad_turn.lua
index 0fecb7d2d07..79e25b29587 100644
--- a/test/data/profiles/bad_turn.lua
+++ b/test/data/profiles/bad_turn.lua
@@ -9,8 +9,8 @@ function setup()
max_speed_for_map_matching = 30/3.6, --km -> m/s
weight_name = 'duration',
process_call_tagless_node = false,
- u_turn_penalty = 20,
- traffic_light_penalty = 7, -- seconds
+ u_turn_penalty = 20,
+ traffic_signal_penalty = 7, -- seconds
use_turn_restrictions = true
},
@@ -128,7 +128,7 @@ function process_turn (profile, turn)
turn.weight = turn.weight + profile.properties.u_turn_penalty
end
if turn.has_traffic_light then
- turn.duration = turn.duration + profile.properties.traffic_light_penalty
+ turn.duration = turn.duration + profile.properties.traffic_signal_penalty
end
end
diff --git a/test/data/profiles/bad_way.lua b/test/data/profiles/bad_way.lua
index cb0a3eb7206..f3cc6804ab4 100644
--- a/test/data/profiles/bad_way.lua
+++ b/test/data/profiles/bad_way.lua
@@ -9,8 +9,8 @@ function setup()
max_speed_for_map_matching = 30/3.6, --km -> m/s
weight_name = 'duration',
process_call_tagless_node = false,
- u_turn_penalty = 20,
- traffic_light_penalty = 7, -- seconds
+ u_turn_penalty = 20,
+ traffic_signal_penalty = 7, -- seconds
use_turn_restrictions = true
},
@@ -128,7 +128,7 @@ function process_turn (profile, turn)
turn.weight = turn.weight + profile.properties.u_turn_penalty
end
if turn.has_traffic_light then
- turn.duration = turn.duration + profile.properties.traffic_light_penalty
+ turn.duration = turn.duration + profile.properties.traffic_signal_penalty
end
end
diff --git a/unit_tests/extractor/graph_compressor.cpp b/unit_tests/extractor/graph_compressor.cpp
index f70d71b4f91..c12b48a3646 100644
--- a/unit_tests/extractor/graph_compressor.cpp
+++ b/unit_tests/extractor/graph_compressor.cpp
@@ -64,8 +64,6 @@ BOOST_AUTO_TEST_CASE(long_road_test)
//
GraphCompressor compressor;
- std::unordered_set<NodeID> barrier_nodes;
- TrafficSignals traffic_lights;
std::vector<TurnRestriction> restrictions;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
CompressedEdgeContainer container;
@@ -86,14 +84,8 @@ BOOST_AUTO_TEST_CASE(long_road_test)
BOOST_CHECK(compatible(graph, annotations, 2, 4));
BOOST_CHECK(compatible(graph, annotations, 4, 6));
- compressor.Compress(barrier_nodes,
- traffic_lights,
- scripting_environment,
- restrictions,
- maneuver_overrides,
- graph,
- annotations,
- container);
+ compressor.Compress(
+ scripting_environment, restrictions, maneuver_overrides, graph, annotations, container);
BOOST_CHECK_EQUAL(graph.FindEdge(0, 1), SPECIAL_EDGEID);
BOOST_CHECK_EQUAL(graph.FindEdge(1, 2), SPECIAL_EDGEID);
BOOST_CHECK_EQUAL(graph.FindEdge(2, 3), SPECIAL_EDGEID);
@@ -110,8 +102,6 @@ BOOST_AUTO_TEST_CASE(loop_test)
//
GraphCompressor compressor;
- std::unordered_set<NodeID> barrier_nodes;
- TrafficSignals traffic_lights;
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
@@ -146,14 +136,8 @@ BOOST_AUTO_TEST_CASE(loop_test)
BOOST_CHECK(compatible(graph, annotations, 10, 11));
BOOST_CHECK(compatible(graph, annotations, 11, 0));
- compressor.Compress(barrier_nodes,
- traffic_lights,
- scripting_environment,
- restrictions,
- maneuver_overrides,
- graph,
- annotations,
- container);
+ compressor.Compress(
+ scripting_environment, restrictions, maneuver_overrides, graph, annotations, container);
BOOST_CHECK_EQUAL(graph.FindEdge(5, 0), SPECIAL_EDGEID);
BOOST_CHECK_EQUAL(graph.FindEdge(0, 1), SPECIAL_EDGEID);
@@ -173,8 +157,6 @@ BOOST_AUTO_TEST_CASE(t_intersection)
//
GraphCompressor compressor;
- std::unordered_set<NodeID> barrier_nodes;
- TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
@@ -195,14 +177,8 @@ BOOST_AUTO_TEST_CASE(t_intersection)
BOOST_CHECK(compatible(graph, annotations, 3, 4));
BOOST_CHECK(compatible(graph, annotations, 4, 5));
- compressor.Compress(barrier_nodes,
- traffic_lights,
- scripting_environment,
- restrictions,
- maneuver_overrides,
- graph,
- annotations,
- container);
+ compressor.Compress(
+ scripting_environment, restrictions, maneuver_overrides, graph, annotations, container);
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);
BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID);
@@ -216,8 +192,6 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
//
GraphCompressor compressor;
- std::unordered_set<NodeID> barrier_nodes;
- TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(2);
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
@@ -234,14 +208,8 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
BOOST_CHECK(compatible(graph, annotations, 0, 1));
BOOST_CHECK(compatible(graph, annotations, 2, 3));
- compressor.Compress(barrier_nodes,
- traffic_lights,
- scripting_environment,
- restrictions,
- maneuver_overrides,
- graph,
- annotations,
- container);
+ compressor.Compress(
+ scripting_environment, restrictions, maneuver_overrides, graph, annotations, container);
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);
BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID);
@@ -254,8 +222,6 @@ BOOST_AUTO_TEST_CASE(direction_changes)
//
GraphCompressor compressor;
- std::unordered_set<NodeID> barrier_nodes;
- TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
@@ -268,14 +234,8 @@ BOOST_AUTO_TEST_CASE(direction_changes)
edges[1].data.reversed = true;
Graph graph(5, edges);
- compressor.Compress(barrier_nodes,
- traffic_lights,
- scripting_environment,
- restrictions,
- maneuver_overrides,
- graph,
- annotations,
- container);
+ compressor.Compress(
+ scripting_environment, restrictions, maneuver_overrides, graph, annotations, container);
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);
BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID);
diff --git a/unit_tests/extractor/intersection_analysis_tests.cpp b/unit_tests/extractor/intersection_analysis_tests.cpp
index 947359c598a..79b261ac74c 100644
--- a/unit_tests/extractor/intersection_analysis_tests.cpp
+++ b/unit_tests/extractor/intersection_analysis_tests.cpp
@@ -18,8 +18,6 @@ using Graph = util::NodeBasedDynamicGraph;
BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
{
- std::unordered_set<NodeID> barrier_nodes{6};
- 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}};
@@ -27,6 +25,7 @@ BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
CompressedEdgeContainer container;
test::MockScriptingEnvironment scripting_environment;
std::vector<UnresolvedManeuverOverride> maneuver_overrides;
+ scripting_environment.m_obstacle_map.emplace(SPECIAL_NODEID, 6, {Obstacle::Type::Barrier});
TurnLanesIndexedArray turn_lanes_data{{0, 0, 3},
{TurnLaneType::uturn | TurnLaneType::left,
@@ -86,14 +85,8 @@ BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
Graph graph(8, edges);
- GraphCompressor().Compress(barrier_nodes,
- traffic_lights,
- scripting_environment,
- restrictions,
- maneuver_overrides,
- graph,
- annotations,
- container);
+ GraphCompressor().Compress(
+ scripting_environment, restrictions, maneuver_overrides, graph, annotations, container);
REQUIRE_SIZE_RANGE(getIncomingEdges(graph, 2), 3);
REQUIRE_SIZE_RANGE(getOutgoingEdges(graph, 2), 4);
@@ -115,7 +108,7 @@ BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
result.push_back(isTurnAllowed(graph,
node_data_container,
restriction_map,
- barrier_nodes,
+ scripting_environment.m_obstacle_map,
edge_geometries,
turn_lanes_data,
incoming_edge,
@@ -153,8 +146,6 @@ BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
{
- std::unordered_set<NodeID> barrier_nodes;
- TrafficSignals traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations;
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
@@ -211,14 +202,8 @@ BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
Graph graph(7, edges);
- GraphCompressor().Compress(barrier_nodes,
- traffic_lights,
- scripting_environment,
- restrictions,
- maneuver_overrides,
- graph,
- annotations,
- container);
+ GraphCompressor().Compress(
+ scripting_environment, restrictions, maneuver_overrides, graph, annotations, container);
REQUIRE_SIZE_RANGE(getIncomingEdges(graph, 0), 3);
REQUIRE_SIZE_RANGE(getOutgoingEdges(graph, 0), 6);
@@ -241,7 +226,7 @@ BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
result.push_back(isTurnAllowed(graph,
node_data_container,
restriction_map,
- barrier_nodes,
+ scripting_environment.m_obstacle_map,
edge_geometries,
turn_lanes_data,
incoming_edge,
@@ -262,13 +247,14 @@ BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
BOOST_AUTO_TEST_CASE(skip_degree_two_nodes)
{
- std::unordered_set<NodeID> barrier_nodes{1};
- TrafficSignals traffic_lights = {{2}, {}};
std::vector<NodeBasedEdgeAnnotation> annotations(1);
std::vector<TurnRestriction> restrictions;
CompressedEdgeContainer container;
test::MockScriptingEnvironment scripting_environment;
std::vector<UnresolvedManeuverOverride> maneuver_overrides;
+ scripting_environment.m_obstacle_map.emplace(SPECIAL_NODEID, 1, {Obstacle::Type::Barrier});
+ scripting_environment.m_obstacle_map.emplace(
+ SPECIAL_NODEID, 2, {Obstacle::Type::TrafficSignals});
TurnLanesIndexedArray turn_lanes_data;
@@ -312,14 +298,8 @@ BOOST_AUTO_TEST_CASE(skip_degree_two_nodes)
Graph graph(10, edges);
- GraphCompressor().Compress(barrier_nodes,
- traffic_lights,
- scripting_environment,
- restrictions,
- maneuver_overrides,
- graph,
- annotations,
- container);
+ GraphCompressor().Compress(
+ scripting_environment, restrictions, maneuver_overrides, graph, annotations, container);
BOOST_CHECK_EQUAL(graph.GetTarget(skipDegreeTwoNodes(graph, {0, 0}).edge), 4);
BOOST_CHECK_EQUAL(graph.GetTarget(skipDegreeTwoNodes(graph, {4, 7}).edge), 0);
diff --git a/unit_tests/library/extract.cpp b/unit_tests/library/extract.cpp
index 768331c1c22..c4f1f0354f8 100644
--- a/unit_tests/library/extract.cpp
+++ b/unit_tests/library/extract.cpp
@@ -135,28 +135,24 @@ BOOST_AUTO_TEST_CASE(test_segment_runtime_error)
BOOST_CHECK(boost::algorithm::contains(
output.str(), "bad_segment.lua:132: attempt to compare number with nil"));
}
-// NOTE: THIS TEST IS COMMENTED OUT BECAUSE IT FAILS
-// BOOST_AUTO_TEST_CASE(test_turn_runtime_error)
-// {
-// osrm::ExtractorConfig config;
-// config.input_path = OSRM_TEST_DATA_DIR "/monaco.osm.pbf";
-// config.UseDefaultOutputNames(OSRM_TEST_DATA_DIR "/monaco.osm.pbf");
-// config.profile_path = OSRM_TEST_DATA_DIR "/profiles/bad_turn.lua";
-// config.small_component_size = 1000;
-// config.requested_num_threads = std::thread::hardware_concurrency();
-
-// std::stringstream output;
-
-// {
-// redirect_stderr redir(output.rdbuf());
-// BOOST_CHECK_THROW(osrm::extract(config), osrm::util::exception);
-// }
-
-// // We just look for the line number, file name, and error message. This avoids portability
-// // issues since the output contains the full path to the file, which may change between
-// systems BOOST_CHECK(boost::algorithm::contains(output.str(),
-// "bad_turn.lua:122: attempt to compare number with
-// nil"));
-// }
+
+BOOST_AUTO_TEST_CASE(test_turn_runtime_error)
+{
+ osrm::ExtractorConfig config;
+ config.input_path = OSRM_TEST_DATA_DIR "/monaco.osm.pbf";
+ config.UseDefaultOutputNames(OSRM_TEST_DATA_DIR "/monaco.osm.pbf");
+ config.profile_path = OSRM_TEST_DATA_DIR "/profiles/bad_turn.lua";
+ config.small_component_size = 1000;
+ config.requested_num_threads = std::thread::hardware_concurrency();
+ std::stringstream output;
+ {
+ redirect_stderr redir(output.rdbuf());
+ BOOST_CHECK_THROW(osrm::extract(config), osrm::util::exception);
+ }
+ // We just look for the line number, file name, and error message. This avoids portability
+ // issues since the output contains the full path to the file, which may change between systems
+ BOOST_CHECK(boost::algorithm::contains(output.str(),
+ "bad_turn.lua:122: attempt to compare number with nil"));
+}
BOOST_AUTO_TEST_SUITE_END()