Support OSM traffic signal directions (#6153)
Currently OSRM parses traffic signal nodes without consideration for the direction in which the signal applies. This can lead to duplicated routing penalties, especially when a forward and backward signal are in close proximity on a way. This commit adds support for directed signals to the extraction and graph creation. Signal penalties are only applied in the direction specified by the OSM tag. We add the assignment of traffic directions to the lua scripts, maintaining backwards compatibility with the existing boolean traffic states. As part of the changes to the internal structures used for tracking traffic signals during extraction, we stop serialising/deserialising signals to the `.osrm` file. The traffic signals are only used by `osrm-extract` so whilst this is a data format change, it will not break any existing user processes.
This commit is contained in:
parent
d8b358e810
commit
b17cbb4c47
@ -54,6 +54,7 @@
|
|||||||
- FIXED: Improvements to maneuver override processing [#6125](https://github.com/Project-OSRM/osrm-backend/pull/6125)
|
- FIXED: Improvements to maneuver override processing [#6125](https://github.com/Project-OSRM/osrm-backend/pull/6125)
|
||||||
- ADDED: Support snapping to multiple ways at an input location. [#5953](https://github.com/Project-OSRM/osrm-backend/pull/5953)
|
- ADDED: Support snapping to multiple ways at an input location. [#5953](https://github.com/Project-OSRM/osrm-backend/pull/5953)
|
||||||
- FIXED: Fix snapping target locations to ways used in turn restrictions. [#6339](https://github.com/Project-OSRM/osrm-backend/pull/6339)
|
- FIXED: Fix snapping target locations to ways used in turn restrictions. [#6339](https://github.com/Project-OSRM/osrm-backend/pull/6339)
|
||||||
|
- ADDED: Support OSM traffic signal directions. [#6153](https://github.com/Project-OSRM/osrm-backend/pull/6153)
|
||||||
|
|
||||||
# 5.26.0
|
# 5.26.0
|
||||||
- Changes from 5.25.0
|
- Changes from 5.25.0
|
||||||
|
@ -39,7 +39,113 @@ Feature: Car - Handle traffic lights
|
|||||||
| k | n | 20.7s | turn with traffic light |
|
| k | n | 20.7s | turn with traffic light |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Tarrif Signal Geometry
|
Scenario: Car - Traffic signal direction
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a-1-b-2-c
|
||||||
|
|
||||||
|
d-3-e-4-f
|
||||||
|
|
||||||
|
g-5-h-6-i
|
||||||
|
|
||||||
|
j-7-k-8-l
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | primary |
|
||||||
|
| def | primary |
|
||||||
|
| ghi | primary |
|
||||||
|
| jkl | primary |
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway | traffic_signals:direction |
|
||||||
|
| e | traffic_signals | |
|
||||||
|
| h | traffic_signals | forward |
|
||||||
|
| k | traffic_signals | backward |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | time | # |
|
||||||
|
| 1 | 2 | 11.1s | no turn with no traffic light |
|
||||||
|
| 2 | 1 | 11.1s | no turn with no traffic light |
|
||||||
|
| 3 | 4 | 13.1s | no turn with traffic light |
|
||||||
|
| 4 | 3 | 13.1s | no turn with traffic light |
|
||||||
|
| 5 | 6 | 13.1s | no turn with traffic light |
|
||||||
|
| 6 | 5 | 11.1s | no turn with no traffic light |
|
||||||
|
| 7 | 8 | 11.1s | no turn with no traffic light |
|
||||||
|
| 8 | 7 | 13.1s | no turn with traffic light |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Car - Encounters a traffic light
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a f k
|
||||||
|
| | |
|
||||||
|
b-c-d h-g-i l-m-n
|
||||||
|
| | |
|
||||||
|
e j o
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| bcd | primary |
|
||||||
|
| ace | primary |
|
||||||
|
| hgi | primary |
|
||||||
|
| fgj | primary |
|
||||||
|
| lmn | primary |
|
||||||
|
| kmo | primary |
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway | traffic_signals:direction |
|
||||||
|
| g | traffic_signals | forward |
|
||||||
|
| m | traffic_signals | backward |
|
||||||
|
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | time | # |
|
||||||
|
| a | d | 21.9s | no turn with no traffic light |
|
||||||
|
| a | e | 22.2s | no turn with traffic light |
|
||||||
|
| a | b | 18.7s | turn with no traffic light |
|
||||||
|
| e | b | 21.9s | no turn with no traffic light |
|
||||||
|
| e | a | 22.2s | no turn with traffic light |
|
||||||
|
| e | d | 18.7s | turn with no traffic light |
|
||||||
|
| d | e | 21.9s | no turn with no traffic light |
|
||||||
|
| d | b | 11s | no turn with traffic light |
|
||||||
|
| d | a | 18.7s | turn with no traffic light |
|
||||||
|
| b | a | 21.9s | no turn with no traffic light |
|
||||||
|
| b | d | 11s | no turn with traffic light |
|
||||||
|
| b | e | 18.7s | turn with no traffic light |
|
||||||
|
|
||||||
|
| f | i | 23.9s | no turn with no traffic light |
|
||||||
|
| f | j | 24.2s | no turn with traffic light |
|
||||||
|
| f | h | 20.7s | turn with no traffic light |
|
||||||
|
| j | h | 21.9s | no turn with no traffic light |
|
||||||
|
| j | f | 22.2s | no turn with traffic light |
|
||||||
|
| j | i | 18.7s | turn with no traffic light |
|
||||||
|
| i | j | 21.9s | no turn with no traffic light |
|
||||||
|
| i | h | 11s | no turn with traffic light |
|
||||||
|
| i | f | 18.7s | turn with no traffic light |
|
||||||
|
| h | f | 23.9s | no turn with no traffic light |
|
||||||
|
| h | i | 13s | no turn with traffic light |
|
||||||
|
| h | j | 20.7s | turn with no traffic light |
|
||||||
|
|
||||||
|
| k | n | 21.9s | no turn with no traffic light |
|
||||||
|
| k | o | 22.2s | no turn with traffic light |
|
||||||
|
| k | l | 18.7s | turn with no traffic light |
|
||||||
|
| o | l | 23.9s | no turn with no traffic light |
|
||||||
|
| o | k | 24.2s | no turn with traffic light |
|
||||||
|
| o | n | 20.7s | turn with no traffic light |
|
||||||
|
| n | o | 23.9s | no turn with no traffic light |
|
||||||
|
| n | l | 13s | no turn with traffic light |
|
||||||
|
| n | k | 20.7s | turn with no traffic light |
|
||||||
|
| l | k | 21.9s | no turn with no traffic light |
|
||||||
|
| l | n | 11s | no turn with traffic light |
|
||||||
|
| l | o | 18.7s | turn with no traffic light |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Traffic Signal Geometry
|
||||||
Given the query options
|
Given the query options
|
||||||
| overview | full |
|
| overview | full |
|
||||||
| geometries | polyline |
|
| geometries | polyline |
|
||||||
@ -61,6 +167,53 @@ Feature: Car - Handle traffic lights
|
|||||||
| from | to | route | geometry |
|
| from | to | route | geometry |
|
||||||
| a | c | abc,abc | _ibE_ibE?gJ?eJ |
|
| a | c | abc,abc | _ibE_ibE?gJ?eJ |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Traffic Signal Geometry - forward signal
|
||||||
|
Given the query options
|
||||||
|
| overview | full |
|
||||||
|
| geometries | polyline |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a - b - c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | primary |
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway | traffic_signals:direction |
|
||||||
|
| b | traffic_signals | forward |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | geometry |
|
||||||
|
| a | c | abc,abc | _ibE_ibE?gJ?eJ |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Traffic Signal Geometry - reverse signal
|
||||||
|
Given the query options
|
||||||
|
| overview | full |
|
||||||
|
| geometries | polyline |
|
||||||
|
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a - b - c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | primary |
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway | traffic_signals:direction |
|
||||||
|
| b | traffic_signals | reverse |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | geometry |
|
||||||
|
| a | c | abc,abc | _ibE_ibE?gJ?eJ |
|
||||||
|
|
||||||
|
|
||||||
@traffic
|
@traffic
|
||||||
Scenario: Traffic update on the edge with a traffic signal
|
Scenario: Traffic update on the edge with a traffic signal
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -91,3 +244,67 @@ Feature: Car - Handle traffic lights
|
|||||||
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
|
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
|
||||||
| a | c | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
|
| a | c | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
|
||||||
| c | a | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |
|
| c | a | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |
|
||||||
|
|
||||||
|
|
||||||
|
@traffic
|
||||||
|
Scenario: Traffic update on the edge with a traffic signal - forward
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a - b - c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | primary |
|
||||||
|
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway | traffic_signals:direction |
|
||||||
|
| b | traffic_signals | forward |
|
||||||
|
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
1,2,65
|
||||||
|
2,1,65
|
||||||
|
"""
|
||||||
|
And the query options
|
||||||
|
| annotations | datasources,nodes,speed,duration,weight |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
|
||||||
|
| a | c | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
|
||||||
|
| c | a | abc,abc | 65 km/h | 22.2,0 | 22.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |
|
||||||
|
|
||||||
|
|
||||||
|
@traffic
|
||||||
|
Scenario: Traffic update on the edge with a traffic signal - backward
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a - b - c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| abc | primary |
|
||||||
|
|
||||||
|
|
||||||
|
And the nodes
|
||||||
|
| node | highway | traffic_signals:direction |
|
||||||
|
| b | traffic_signals | backward |
|
||||||
|
|
||||||
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
And the speed file
|
||||||
|
"""
|
||||||
|
1,2,65
|
||||||
|
2,1,65
|
||||||
|
"""
|
||||||
|
And the query options
|
||||||
|
| annotations | datasources,nodes,speed,duration,weight |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
|
||||||
|
| a | c | abc,abc | 65 km/h | 22.2,0 | 22.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
|
||||||
|
| c | a | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
#include "storage/io.hpp"
|
||||||
|
#include "traffic_signals.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -68,7 +69,7 @@ class EdgeBasedGraphFactory
|
|||||||
EdgeBasedNodeDataContainer &node_data_container,
|
EdgeBasedNodeDataContainer &node_data_container,
|
||||||
const CompressedEdgeContainer &compressed_edge_container,
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const TrafficSignals &traffic_signals,
|
||||||
const std::vector<util::Coordinate> &coordinates,
|
const std::vector<util::Coordinate> &coordinates,
|
||||||
const NameTable &name_table,
|
const NameTable &name_table,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
@ -134,7 +135,7 @@ class EdgeBasedGraphFactory
|
|||||||
const util::NodeBasedDynamicGraph &m_node_based_graph;
|
const util::NodeBasedDynamicGraph &m_node_based_graph;
|
||||||
|
|
||||||
const std::unordered_set<NodeID> &m_barrier_nodes;
|
const std::unordered_set<NodeID> &m_barrier_nodes;
|
||||||
const std::unordered_set<NodeID> &m_traffic_lights;
|
const TrafficSignals &m_traffic_signals;
|
||||||
const CompressedEdgeContainer &m_compressed_edge_container;
|
const CompressedEdgeContainer &m_compressed_edge_container;
|
||||||
|
|
||||||
const NameTable &name_table;
|
const NameTable &name_table;
|
||||||
|
@ -8,8 +8,11 @@
|
|||||||
#include "extractor/scripting_environment.hpp"
|
#include "extractor/scripting_environment.hpp"
|
||||||
|
|
||||||
#include "storage/tar_fwd.hpp"
|
#include "storage/tar_fwd.hpp"
|
||||||
|
#include "traffic_lights.hpp"
|
||||||
|
#include "traffic_signals.hpp"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@ -25,15 +28,19 @@ namespace extractor
|
|||||||
class ExtractionContainers
|
class ExtractionContainers
|
||||||
{
|
{
|
||||||
using ReferencedWays = std::unordered_map<OSMWayID, NodesOfWay>;
|
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.
|
// The relationship between way and nodes is lost during node preparation.
|
||||||
// We identify the ways and nodes relevant to restrictions/overrides prior to
|
// We identify the ways and nodes relevant to restrictions/overrides/signals prior to
|
||||||
// node processing so that they can be referenced in the preparation phase.
|
// node processing so that they can be referenced in the preparation phase.
|
||||||
ReferencedWays IdentifyRestrictionWays();
|
ReferencedWays IdentifyRestrictionWays();
|
||||||
ReferencedWays IdentifyManeuverOverrideWays();
|
ReferencedWays IdentifyManeuverOverrideWays();
|
||||||
|
ReferencedTrafficSignals IdentifyTrafficSignals();
|
||||||
|
|
||||||
void PrepareNodes();
|
void PrepareNodes();
|
||||||
void PrepareManeuverOverrides(const ReferencedWays &maneuver_override_ways);
|
void PrepareManeuverOverrides(const ReferencedWays &maneuver_override_ways);
|
||||||
void PrepareRestrictions(const ReferencedWays &restriction_ways);
|
void PrepareRestrictions(const ReferencedWays &restriction_ways);
|
||||||
|
void PrepareTrafficSignals(const ReferencedTrafficSignals &referenced_traffic_signals);
|
||||||
void PrepareEdges(ScriptingEnvironment &scripting_environment);
|
void PrepareEdges(ScriptingEnvironment &scripting_environment);
|
||||||
|
|
||||||
void WriteNodes(storage::tar::FileWriter &file_out) const;
|
void WriteNodes(storage::tar::FileWriter &file_out) const;
|
||||||
@ -50,9 +57,9 @@ class ExtractionContainers
|
|||||||
using NameOffsets = std::vector<size_t>;
|
using NameOffsets = std::vector<size_t>;
|
||||||
using WayIDVector = std::vector<OSMWayID>;
|
using WayIDVector = std::vector<OSMWayID>;
|
||||||
using WayNodeIDOffsets = std::vector<size_t>;
|
using WayNodeIDOffsets = std::vector<size_t>;
|
||||||
|
using InputTrafficSignal = std::pair<OSMNodeID, TrafficLightClass::Direction>;
|
||||||
|
|
||||||
std::vector<OSMNodeID> barrier_nodes;
|
std::vector<OSMNodeID> barrier_nodes;
|
||||||
std::vector<OSMNodeID> traffic_signals;
|
|
||||||
NodeIDVector used_node_id_list;
|
NodeIDVector used_node_id_list;
|
||||||
NodeVector all_nodes_list;
|
NodeVector all_nodes_list;
|
||||||
EdgeVector all_edges_list;
|
EdgeVector all_edges_list;
|
||||||
@ -65,6 +72,9 @@ class ExtractionContainers
|
|||||||
|
|
||||||
unsigned max_internal_node_id;
|
unsigned max_internal_node_id;
|
||||||
|
|
||||||
|
std::vector<InputTrafficSignal> external_traffic_signals;
|
||||||
|
TrafficSignals internal_traffic_signals;
|
||||||
|
|
||||||
// List of restrictions (conditional and unconditional) before we transform them into the
|
// List of restrictions (conditional and unconditional) before we transform them into the
|
||||||
// output types. Input containers reference OSMNodeIDs. We can only transform them to the
|
// output types. Input containers reference OSMNodeIDs. We can only transform them to the
|
||||||
// correct internal IDs after we've read everything. Without a multi-parse approach,
|
// correct internal IDs after we've read everything. Without a multi-parse approach,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef EXTRACTION_NODE_HPP
|
#ifndef EXTRACTION_NODE_HPP
|
||||||
#define EXTRACTION_NODE_HPP
|
#define EXTRACTION_NODE_HPP
|
||||||
|
|
||||||
|
#include "traffic_lights.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace extractor
|
namespace extractor
|
||||||
@ -8,9 +10,13 @@ namespace extractor
|
|||||||
|
|
||||||
struct ExtractionNode
|
struct ExtractionNode
|
||||||
{
|
{
|
||||||
ExtractionNode() : traffic_lights(false), barrier(false) {}
|
ExtractionNode() : traffic_lights(TrafficLightClass::NONE), barrier(false) {}
|
||||||
void clear() { traffic_lights = barrier = false; }
|
void clear()
|
||||||
bool traffic_lights;
|
{
|
||||||
|
traffic_lights = TrafficLightClass::NONE;
|
||||||
|
barrier = false;
|
||||||
|
}
|
||||||
|
TrafficLightClass::Direction traffic_lights;
|
||||||
bool barrier;
|
bool barrier;
|
||||||
};
|
};
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
|
@ -43,6 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "util/guidance/turn_lanes.hpp"
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
|
|
||||||
#include "restriction_graph.hpp"
|
#include "restriction_graph.hpp"
|
||||||
|
#include "traffic_signals.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@ -64,7 +65,8 @@ class Extractor
|
|||||||
|
|
||||||
std::tuple<LaneDescriptionMap,
|
std::tuple<LaneDescriptionMap,
|
||||||
std::vector<TurnRestriction>,
|
std::vector<TurnRestriction>,
|
||||||
std::vector<UnresolvedManeuverOverride>>
|
std::vector<UnresolvedManeuverOverride>,
|
||||||
|
TrafficSignals>
|
||||||
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
|
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
|
||||||
|
|
||||||
EdgeID BuildEdgeExpandedGraph(
|
EdgeID BuildEdgeExpandedGraph(
|
||||||
@ -73,7 +75,7 @@ class Extractor
|
|||||||
const std::vector<util::Coordinate> &coordinates,
|
const std::vector<util::Coordinate> &coordinates,
|
||||||
const CompressedEdgeContainer &compressed_edge_container,
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const TrafficSignals &traffic_signals,
|
||||||
const RestrictionGraph &restriction_graph,
|
const RestrictionGraph &restriction_graph,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
const NameTable &name_table,
|
const NameTable &name_table,
|
||||||
|
@ -444,10 +444,9 @@ inline void readConditionalRestrictions(const boost::filesystem::path &path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reads .osrm file which is a temporary file of osrm-extract
|
// reads .osrm file which is a temporary file of osrm-extract
|
||||||
template <typename BarrierOutIter, typename TrafficSignalsOutIter, typename PackedOSMIDsT>
|
template <typename BarrierOutIter, typename PackedOSMIDsT>
|
||||||
void readRawNBGraph(const boost::filesystem::path &path,
|
void readRawNBGraph(const boost::filesystem::path &path,
|
||||||
BarrierOutIter barriers,
|
BarrierOutIter barriers,
|
||||||
TrafficSignalsOutIter traffic_signals,
|
|
||||||
std::vector<util::Coordinate> &coordinates,
|
std::vector<util::Coordinate> &coordinates,
|
||||||
PackedOSMIDsT &osm_node_ids,
|
PackedOSMIDsT &osm_node_ids,
|
||||||
std::vector<extractor::NodeBasedEdge> &edge_list,
|
std::vector<extractor::NodeBasedEdge> &edge_list,
|
||||||
@ -471,8 +470,6 @@ void readRawNBGraph(const boost::filesystem::path &path,
|
|||||||
|
|
||||||
reader.ReadStreaming<NodeID>("/extractor/barriers", barriers);
|
reader.ReadStreaming<NodeID>("/extractor/barriers", barriers);
|
||||||
|
|
||||||
reader.ReadStreaming<NodeID>("/extractor/traffic_lights", traffic_signals);
|
|
||||||
|
|
||||||
storage::serialization::read(reader, "/extractor/edges", edge_list);
|
storage::serialization::read(reader, "/extractor/edges", edge_list);
|
||||||
storage::serialization::read(reader, "/extractor/annotations", annotations);
|
storage::serialization::read(reader, "/extractor/annotations", annotations);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "extractor/scripting_environment.hpp"
|
#include "extractor/scripting_environment.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
|
#include "traffic_signals.hpp"
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -25,7 +26,7 @@ class GraphCompressor
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
void Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
void Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const TrafficSignals &traffic_signals,
|
||||||
ScriptingEnvironment &scripting_environment,
|
ScriptingEnvironment &scripting_environment,
|
||||||
std::vector<TurnRestriction> &turn_restrictions,
|
std::vector<TurnRestriction> &turn_restrictions,
|
||||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "extractor/packed_osm_ids.hpp"
|
#include "extractor/packed_osm_ids.hpp"
|
||||||
#include "extractor/scripting_environment.hpp"
|
#include "extractor/scripting_environment.hpp"
|
||||||
|
|
||||||
|
#include "traffic_signals.hpp"
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
|
|
||||||
@ -40,11 +41,11 @@ class NodeBasedGraphFactory
|
|||||||
NodeBasedGraphFactory(const boost::filesystem::path &input_file,
|
NodeBasedGraphFactory(const boost::filesystem::path &input_file,
|
||||||
ScriptingEnvironment &scripting_environment,
|
ScriptingEnvironment &scripting_environment,
|
||||||
std::vector<TurnRestriction> &turn_restrictions,
|
std::vector<TurnRestriction> &turn_restrictions,
|
||||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides);
|
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||||
|
const TrafficSignals &traffic_signals);
|
||||||
|
|
||||||
auto const &GetGraph() const { return compressed_output_graph; }
|
auto const &GetGraph() const { return compressed_output_graph; }
|
||||||
auto const &GetBarriers() const { return barriers; }
|
auto const &GetBarriers() const { return barriers; }
|
||||||
auto const &GetTrafficSignals() const { return traffic_signals; }
|
|
||||||
auto const &GetCompressedEdges() const { return compressed_edge_container; }
|
auto const &GetCompressedEdges() const { return compressed_edge_container; }
|
||||||
auto const &GetCoordinates() const { return coordinates; }
|
auto const &GetCoordinates() const { return coordinates; }
|
||||||
auto const &GetAnnotationData() const { return annotation_data; }
|
auto const &GetAnnotationData() const { return annotation_data; }
|
||||||
@ -68,7 +69,8 @@ class NodeBasedGraphFactory
|
|||||||
// edges into a single representative form
|
// edges into a single representative form
|
||||||
void Compress(ScriptingEnvironment &scripting_environment,
|
void Compress(ScriptingEnvironment &scripting_environment,
|
||||||
std::vector<TurnRestriction> &turn_restrictions,
|
std::vector<TurnRestriction> &turn_restrictions,
|
||||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides);
|
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||||
|
const TrafficSignals &traffic_signals);
|
||||||
|
|
||||||
// Most ways are bidirectional, making the geometry in forward and backward direction the same,
|
// 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
|
// except for reversal. We make use of this fact by keeping only one representation of the
|
||||||
@ -89,7 +91,6 @@ class NodeBasedGraphFactory
|
|||||||
|
|
||||||
// General Information about the graph, not used outside of extractor
|
// General Information about the graph, not used outside of extractor
|
||||||
std::unordered_set<NodeID> barriers;
|
std::unordered_set<NodeID> barriers;
|
||||||
std::unordered_set<NodeID> traffic_signals;
|
|
||||||
|
|
||||||
std::vector<util::Coordinate> coordinates;
|
std::vector<util::Coordinate> coordinates;
|
||||||
|
|
||||||
|
25
include/extractor/traffic_lights.hpp
Normal file
25
include/extractor/traffic_lights.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
|
||||||
|
#define OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace TrafficLightClass
|
||||||
|
{
|
||||||
|
// The traffic light annotation is extracted from node tags.
|
||||||
|
// The directions in which the traffic light applies are relative to the way containing the node.
|
||||||
|
enum Direction
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
DIRECTION_ALL = 1,
|
||||||
|
DIRECTION_FORWARD = 2,
|
||||||
|
DIRECTION_REVERSE = 3
|
||||||
|
};
|
||||||
|
} // namespace TrafficLightClass
|
||||||
|
|
||||||
|
} // namespace extractor
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
#endif // OSRM_EXTRACTOR_TRAFFIC_LIGHTS_DATA_HPP_
|
28
include/extractor/traffic_signals.hpp
Normal file
28
include/extractor/traffic_signals.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
|
||||||
|
#define OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
|
||||||
|
|
||||||
|
#include "util/typedefs.hpp"
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
|
||||||
|
struct TrafficSignals
|
||||||
|
{
|
||||||
|
std::unordered_set<NodeID> bidirectional_nodes;
|
||||||
|
std::unordered_set<std::pair<NodeID, NodeID>, boost::hash<std::pair<NodeID, NodeID>>>
|
||||||
|
unidirectional_segments;
|
||||||
|
|
||||||
|
inline bool HasSignal(NodeID from, NodeID to) const
|
||||||
|
{
|
||||||
|
return bidirectional_nodes.count(to) > 0 || unidirectional_segments.count({from, to}) > 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace extractor
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
#endif // OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP
|
@ -5,6 +5,7 @@ api_version = 4
|
|||||||
Set = require('lib/set')
|
Set = require('lib/set')
|
||||||
Sequence = require('lib/sequence')
|
Sequence = require('lib/sequence')
|
||||||
Handlers = require("lib/way_handlers")
|
Handlers = require("lib/way_handlers")
|
||||||
|
TrafficSignal = require("lib/traffic_signal")
|
||||||
find_access_tag = require("lib/access").find_access_tag
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
limit = require("lib/maxspeed").limit
|
limit = require("lib/maxspeed").limit
|
||||||
Measure = require("lib/measure")
|
Measure = require("lib/measure")
|
||||||
@ -235,10 +236,7 @@ function process_node(profile, node, result)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- check if node is a traffic light
|
-- check if node is a traffic light
|
||||||
local tag = node:get_value_by_key("highway")
|
result.traffic_lights = TrafficSignal.get_value(node)
|
||||||
if tag and "traffic_signals" == tag then
|
|
||||||
result.traffic_lights = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function handle_bicycle_tags(profile,way,result,data)
|
function handle_bicycle_tags(profile,way,result,data)
|
||||||
|
@ -6,6 +6,7 @@ Set = require('lib/set')
|
|||||||
Sequence = require('lib/sequence')
|
Sequence = require('lib/sequence')
|
||||||
Handlers = require("lib/way_handlers")
|
Handlers = require("lib/way_handlers")
|
||||||
Relations = require("lib/relations")
|
Relations = require("lib/relations")
|
||||||
|
TrafficSignal = require("lib/traffic_signal")
|
||||||
find_access_tag = require("lib/access").find_access_tag
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
limit = require("lib/maxspeed").limit
|
limit = require("lib/maxspeed").limit
|
||||||
Utils = require("lib/utils")
|
Utils = require("lib/utils")
|
||||||
@ -360,10 +361,7 @@ function process_node(profile, node, result, relations)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- check if node is a traffic light
|
-- check if node is a traffic light
|
||||||
local tag = node:get_value_by_key("highway")
|
result.traffic_lights = TrafficSignal.get_value(node)
|
||||||
if "traffic_signals" == tag then
|
|
||||||
result.traffic_lights = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_way(profile, way, result, relations)
|
function process_way(profile, way, result, relations)
|
||||||
|
@ -157,6 +157,7 @@ function process_node(profile, node, result)
|
|||||||
-- check if node is a traffic light
|
-- check if node is a traffic light
|
||||||
local tag = node:get_value_by_key("highway")
|
local tag = node:get_value_by_key("highway")
|
||||||
if "traffic_signals" == tag then
|
if "traffic_signals" == tag then
|
||||||
|
-- Direction should only apply to vehicles
|
||||||
result.traffic_lights = true
|
result.traffic_lights = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
26
profiles/lib/traffic_signal.lua
Normal file
26
profiles/lib/traffic_signal.lua
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
-- Assigns traffic light value to node as defined by
|
||||||
|
-- include/extractor/traffic_lights.hpp
|
||||||
|
|
||||||
|
local TrafficSignal = {}
|
||||||
|
|
||||||
|
function TrafficSignal.get_value(node)
|
||||||
|
local tag = node:get_value_by_key("highway")
|
||||||
|
if "traffic_signals" == tag then
|
||||||
|
local direction = node:get_value_by_key("traffic_signals:direction")
|
||||||
|
if direction then
|
||||||
|
if "forward" == direction then
|
||||||
|
return traffic_lights.direction_forward
|
||||||
|
end
|
||||||
|
if "backward" == direction then
|
||||||
|
return traffic_lights.direction_reverse
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- return traffic_lights.direction_all
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
-- return traffic_lights.none
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return TrafficSignal
|
||||||
|
|
@ -4,6 +4,7 @@
|
|||||||
-- Primary road: 36km/h = 36000m/3600s = 100m/10s
|
-- Primary road: 36km/h = 36000m/3600s = 100m/10s
|
||||||
-- Secondary road: 18km/h = 18000m/3600s = 100m/20s
|
-- Secondary road: 18km/h = 18000m/3600s = 100m/20s
|
||||||
-- Tertiary road: 12km/h = 12000m/3600s = 100m/30s
|
-- Tertiary road: 12km/h = 12000m/3600s = 100m/30s
|
||||||
|
TrafficSignal = require("lib/traffic_signal")
|
||||||
|
|
||||||
api_version = 4
|
api_version = 4
|
||||||
|
|
||||||
@ -38,12 +39,9 @@ function setup()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function process_node (profile, node, result)
|
function process_node (profile, node, result)
|
||||||
local traffic_signal = node:get_value_by_key("highway")
|
-- check if node is a traffic light
|
||||||
|
result.traffic_lights = TrafficSignal.get_value(node)
|
||||||
if traffic_signal and traffic_signal == "traffic_signals" then
|
-- TODO: a way to set the penalty value
|
||||||
result.traffic_lights = true
|
|
||||||
-- TODO: a way to set the penalty value
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function process_way (profile, way, result)
|
function process_way (profile, way, result)
|
||||||
|
@ -59,7 +59,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
EdgeBasedNodeDataContainer &node_data_container,
|
EdgeBasedNodeDataContainer &node_data_container,
|
||||||
const CompressedEdgeContainer &compressed_edge_container,
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_lights,
|
const TrafficSignals &traffic_signals,
|
||||||
const std::vector<util::Coordinate> &coordinates,
|
const std::vector<util::Coordinate> &coordinates,
|
||||||
const NameTable &name_table,
|
const NameTable &name_table,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
@ -67,7 +67,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
: m_edge_based_node_container(node_data_container), m_connectivity_checksum(0),
|
: m_edge_based_node_container(node_data_container), m_connectivity_checksum(0),
|
||||||
m_number_of_edge_based_nodes(0), m_coordinates(coordinates),
|
m_number_of_edge_based_nodes(0), m_coordinates(coordinates),
|
||||||
m_node_based_graph(node_based_graph), m_barrier_nodes(barrier_nodes),
|
m_node_based_graph(node_based_graph), m_barrier_nodes(barrier_nodes),
|
||||||
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
|
m_traffic_signals(traffic_signals), m_compressed_edge_container(compressed_edge_container),
|
||||||
name_table(name_table), segregated_edges(segregated_edges),
|
name_table(name_table), segregated_edges(segregated_edges),
|
||||||
lane_description_map(lane_description_map)
|
lane_description_map(lane_description_map)
|
||||||
{
|
{
|
||||||
@ -623,8 +623,26 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
BOOST_ASSERT(!edge_data1.reversed);
|
BOOST_ASSERT(!edge_data1.reversed);
|
||||||
BOOST_ASSERT(!edge_data2.reversed);
|
BOOST_ASSERT(!edge_data2.reversed);
|
||||||
|
|
||||||
|
// We write out the mapping between the edge-expanded edges and the original nodes.
|
||||||
|
// Since each edge represents a possible maneuver, external programs can use this to
|
||||||
|
// quickly perform updates to edge weights in order to penalize certain turns.
|
||||||
|
|
||||||
|
// If this edge is 'trivial' -- where the compressed edge corresponds exactly to an
|
||||||
|
// original OSM segment -- we can pull the turn's preceding node ID directly with
|
||||||
|
// `node_along_road_entering`;
|
||||||
|
// otherwise, we need to look up the node immediately preceding the turn from the
|
||||||
|
// compressed edge container.
|
||||||
|
const bool isTrivial = m_compressed_edge_container.IsTrivial(node_based_edge_from);
|
||||||
|
|
||||||
|
const auto &from_node =
|
||||||
|
isTrivial ? node_along_road_entering
|
||||||
|
: m_compressed_edge_container.GetLastEdgeSourceID(node_based_edge_from);
|
||||||
|
|
||||||
// compute weight and duration penalties
|
// compute weight and duration penalties
|
||||||
const auto is_traffic_light = m_traffic_lights.count(intersection_node);
|
// In theory we shouldn't get a directed traffic light on a turn, as it indicates that
|
||||||
|
// the traffic signal direction was potentially ambiguously annotated on the junction
|
||||||
|
// node But we'll check anyway.
|
||||||
|
const auto is_traffic_light = m_traffic_signals.HasSignal(from_node, intersection_node);
|
||||||
const auto is_uturn =
|
const auto is_uturn =
|
||||||
guidance::getTurnDirection(turn_angle) == guidance::DirectionModifier::UTurn;
|
guidance::getTurnDirection(turn_angle) == guidance::DirectionModifier::UTurn;
|
||||||
|
|
||||||
@ -690,20 +708,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
true,
|
true,
|
||||||
false};
|
false};
|
||||||
|
|
||||||
// We write out the mapping between the edge-expanded edges and the original nodes.
|
|
||||||
// Since each edge represents a possible maneuver, external programs can use this to
|
|
||||||
// quickly perform updates to edge weights in order to penalize certain turns.
|
|
||||||
|
|
||||||
// If this edge is 'trivial' -- where the compressed edge corresponds exactly to an
|
|
||||||
// original OSM segment -- we can pull the turn's preceding node ID directly with
|
|
||||||
// `node_along_road_entering`;
|
|
||||||
// otherwise, we need to look up the node immediately preceding the turn from the
|
|
||||||
// compressed edge container.
|
|
||||||
const bool isTrivial = m_compressed_edge_container.IsTrivial(node_based_edge_from);
|
|
||||||
|
|
||||||
const auto &from_node =
|
|
||||||
isTrivial ? node_along_road_entering
|
|
||||||
: m_compressed_edge_container.GetLastEdgeSourceID(node_based_edge_from);
|
|
||||||
const auto &to_node =
|
const auto &to_node =
|
||||||
m_compressed_edge_container.GetFirstEdgeTargetID(node_based_edge_to);
|
m_compressed_edge_container.GetFirstEdgeTargetID(node_based_edge_to);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/exception_utils.hpp"
|
#include "util/exception_utils.hpp"
|
||||||
#include "util/for_each_indexed.hpp"
|
#include "util/for_each_indexed.hpp"
|
||||||
|
#include "util/for_each_pair.hpp"
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
#include "util/timing_util.hpp"
|
#include "util/timing_util.hpp"
|
||||||
|
|
||||||
@ -413,6 +414,7 @@ void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environme
|
|||||||
|
|
||||||
const auto restriction_ways = IdentifyRestrictionWays();
|
const auto restriction_ways = IdentifyRestrictionWays();
|
||||||
const auto maneuver_override_ways = IdentifyManeuverOverrideWays();
|
const auto maneuver_override_ways = IdentifyManeuverOverrideWays();
|
||||||
|
const auto traffic_signals = IdentifyTrafficSignals();
|
||||||
|
|
||||||
PrepareNodes();
|
PrepareNodes();
|
||||||
WriteNodes(writer);
|
WriteNodes(writer);
|
||||||
@ -422,6 +424,7 @@ void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environme
|
|||||||
WriteEdges(writer);
|
WriteEdges(writer);
|
||||||
WriteMetadata(writer);
|
WriteMetadata(writer);
|
||||||
|
|
||||||
|
PrepareTrafficSignals(traffic_signals);
|
||||||
PrepareManeuverOverrides(maneuver_override_ways);
|
PrepareManeuverOverrides(maneuver_override_ways);
|
||||||
PrepareRestrictions(restriction_ways);
|
PrepareRestrictions(restriction_ways);
|
||||||
WriteCharData(name_file_name);
|
WriteCharData(name_file_name);
|
||||||
@ -911,25 +914,6 @@ void ExtractionContainers::WriteNodes(storage::tar::FileWriter &writer) const
|
|||||||
log << "ok, after " << TIMER_SEC(write_nodes) << "s";
|
log << "ok, after " << TIMER_SEC(write_nodes) << "s";
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
util::UnbufferedLog log;
|
|
||||||
log << "Writing traffic light nodes ... ";
|
|
||||||
TIMER_START(write_nodes);
|
|
||||||
std::vector<NodeID> internal_traffic_signals;
|
|
||||||
for (const auto osm_id : traffic_signals)
|
|
||||||
{
|
|
||||||
const auto node_id = mapExternalToInternalNodeID(
|
|
||||||
used_node_id_list.begin(), used_node_id_list.end(), osm_id);
|
|
||||||
if (node_id != SPECIAL_NODEID)
|
|
||||||
{
|
|
||||||
internal_traffic_signals.push_back(node_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storage::serialization::write(
|
|
||||||
writer, "/extractor/traffic_lights", internal_traffic_signals);
|
|
||||||
log << "ok, after " << TIMER_SEC(write_nodes) << "s";
|
|
||||||
}
|
|
||||||
|
|
||||||
util::Log() << "Processed " << max_internal_node_id << " nodes";
|
util::Log() << "Processed " << max_internal_node_id << " nodes";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,6 +967,50 @@ ExtractionContainers::ReferencedWays ExtractionContainers::IdentifyManeuverOverr
|
|||||||
return maneuver_override_ways;
|
return maneuver_override_ways;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExtractionContainers::PrepareTrafficSignals(
|
||||||
|
const ExtractionContainers::ReferencedTrafficSignals &referenced_traffic_signals)
|
||||||
|
{
|
||||||
|
const auto &bidirectional_signal_nodes = referenced_traffic_signals.first;
|
||||||
|
const auto &unidirectional_signal_segments = referenced_traffic_signals.second;
|
||||||
|
|
||||||
|
util::UnbufferedLog log;
|
||||||
|
log << "Preparing traffic light signals for " << bidirectional_signal_nodes.size()
|
||||||
|
<< " bidirectional, " << unidirectional_signal_segments.size()
|
||||||
|
<< " unidirectional nodes ...";
|
||||||
|
TIMER_START(prepare_traffic_signals);
|
||||||
|
|
||||||
|
std::unordered_set<NodeID> bidirectional;
|
||||||
|
std::unordered_set<std::pair<NodeID, NodeID>, boost::hash<std::pair<NodeID, NodeID>>>
|
||||||
|
unidirectional;
|
||||||
|
|
||||||
|
for (const auto &osm_node : bidirectional_signal_nodes)
|
||||||
|
{
|
||||||
|
const auto node_id = mapExternalToInternalNodeID(
|
||||||
|
used_node_id_list.begin(), used_node_id_list.end(), osm_node);
|
||||||
|
if (node_id != SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
bidirectional.insert(node_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &to_from : unidirectional_signal_segments)
|
||||||
|
{
|
||||||
|
const auto to_node_id = mapExternalToInternalNodeID(
|
||||||
|
used_node_id_list.begin(), used_node_id_list.end(), to_from.first);
|
||||||
|
const auto from_node_id = mapExternalToInternalNodeID(
|
||||||
|
used_node_id_list.begin(), used_node_id_list.end(), to_from.second);
|
||||||
|
if (from_node_id != SPECIAL_NODEID && to_node_id != SPECIAL_NODEID)
|
||||||
|
{
|
||||||
|
unidirectional.insert({from_node_id, to_node_id});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_traffic_signals.bidirectional_nodes = std::move(bidirectional);
|
||||||
|
internal_traffic_signals.unidirectional_segments = std::move(unidirectional);
|
||||||
|
|
||||||
|
TIMER_STOP(prepare_traffic_signals);
|
||||||
|
log << "ok, after " << TIMER_SEC(prepare_traffic_signals) << "s";
|
||||||
|
}
|
||||||
|
|
||||||
void ExtractionContainers::PrepareManeuverOverrides(const ReferencedWays &maneuver_override_ways)
|
void ExtractionContainers::PrepareManeuverOverrides(const ReferencedWays &maneuver_override_ways)
|
||||||
{
|
{
|
||||||
auto const osm_node_to_internal_nbn = [&](auto const osm_node) {
|
auto const osm_node_to_internal_nbn = [&](auto const osm_node) {
|
||||||
@ -1163,6 +1191,93 @@ ExtractionContainers::ReferencedWays ExtractionContainers::IdentifyRestrictionWa
|
|||||||
return restriction_ways;
|
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)
|
void ExtractionContainers::PrepareRestrictions(const ReferencedWays &restriction_ways)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ void SetClassNames(const std::vector<std::string> &class_names,
|
|||||||
if (!class_names.empty())
|
if (!class_names.empty())
|
||||||
{
|
{
|
||||||
// add class names that were never used explicitly on a way
|
// add class names that were never used explicitly on a way
|
||||||
// this makes sure we can correctly validate unkown class names later
|
// this makes sure we can correctly validate unknown class names later
|
||||||
for (const auto &name : class_names)
|
for (const auto &name : class_names)
|
||||||
{
|
{
|
||||||
if (!isValidClassName(name))
|
if (!isValidClassName(name))
|
||||||
@ -207,7 +207,8 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
LaneDescriptionMap turn_lane_map;
|
LaneDescriptionMap turn_lane_map;
|
||||||
std::vector<TurnRestriction> turn_restrictions;
|
std::vector<TurnRestriction> turn_restrictions;
|
||||||
std::vector<UnresolvedManeuverOverride> unresolved_maneuver_overrides;
|
std::vector<UnresolvedManeuverOverride> unresolved_maneuver_overrides;
|
||||||
std::tie(turn_lane_map, turn_restrictions, unresolved_maneuver_overrides) =
|
TrafficSignals traffic_signals;
|
||||||
|
std::tie(turn_lane_map, turn_restrictions, unresolved_maneuver_overrides, traffic_signals) =
|
||||||
ParseOSMData(scripting_environment, number_of_threads);
|
ParseOSMData(scripting_environment, number_of_threads);
|
||||||
|
|
||||||
// Transform the node-based graph that OSM is based on into an edge-based graph
|
// Transform the node-based graph that OSM is based on into an edge-based graph
|
||||||
@ -229,7 +230,8 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
NodeBasedGraphFactory node_based_graph_factory(config.GetPath(".osrm"),
|
NodeBasedGraphFactory node_based_graph_factory(config.GetPath(".osrm"),
|
||||||
scripting_environment,
|
scripting_environment,
|
||||||
turn_restrictions,
|
turn_restrictions,
|
||||||
unresolved_maneuver_overrides);
|
unresolved_maneuver_overrides,
|
||||||
|
traffic_signals);
|
||||||
|
|
||||||
NameTable name_table;
|
NameTable name_table;
|
||||||
files::readNames(config.GetPath(".osrm.names"), name_table);
|
files::readNames(config.GetPath(".osrm.names"), name_table);
|
||||||
@ -264,7 +266,6 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
node_based_graph_factory.GetCompressedEdges().PrintStatistics();
|
node_based_graph_factory.GetCompressedEdges().PrintStatistics();
|
||||||
|
|
||||||
const auto &barrier_nodes = node_based_graph_factory.GetBarriers();
|
const auto &barrier_nodes = node_based_graph_factory.GetBarriers();
|
||||||
const auto &traffic_signals = node_based_graph_factory.GetTrafficSignals();
|
|
||||||
// stealing the annotation data from the node-based graph
|
// stealing the annotation data from the node-based graph
|
||||||
edge_based_nodes_container =
|
edge_based_nodes_container =
|
||||||
EdgeBasedNodeDataContainer({}, std::move(node_based_graph_factory.GetAnnotationData()));
|
EdgeBasedNodeDataContainer({}, std::move(node_based_graph_factory.GetAnnotationData()));
|
||||||
@ -360,10 +361,12 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::
|
std::tuple<LaneDescriptionMap,
|
||||||
tuple<LaneDescriptionMap, std::vector<TurnRestriction>, std::vector<UnresolvedManeuverOverride>>
|
std::vector<TurnRestriction>,
|
||||||
Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
std::vector<UnresolvedManeuverOverride>,
|
||||||
const unsigned number_of_threads)
|
TrafficSignals>
|
||||||
|
Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
||||||
|
const unsigned number_of_threads)
|
||||||
{
|
{
|
||||||
TIMER_START(extracting);
|
TIMER_START(extracting);
|
||||||
|
|
||||||
@ -628,7 +631,8 @@ std::
|
|||||||
|
|
||||||
return std::make_tuple(std::move(turn_lane_map),
|
return std::make_tuple(std::move(turn_lane_map),
|
||||||
std::move(extraction_containers.turn_restrictions),
|
std::move(extraction_containers.turn_restrictions),
|
||||||
std::move(extraction_containers.internal_maneuver_overrides));
|
std::move(extraction_containers.internal_maneuver_overrides),
|
||||||
|
std::move(extraction_containers.internal_traffic_signals));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Extractor::FindComponents(unsigned number_of_edge_based_nodes,
|
void Extractor::FindComponents(unsigned number_of_edge_based_nodes,
|
||||||
@ -699,7 +703,7 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
|||||||
const std::vector<util::Coordinate> &coordinates,
|
const std::vector<util::Coordinate> &coordinates,
|
||||||
const CompressedEdgeContainer &compressed_edge_container,
|
const CompressedEdgeContainer &compressed_edge_container,
|
||||||
const std::unordered_set<NodeID> &barrier_nodes,
|
const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_signals,
|
const TrafficSignals &traffic_signals,
|
||||||
const RestrictionGraph &restriction_graph,
|
const RestrictionGraph &restriction_graph,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
const NameTable &name_table,
|
const NameTable &name_table,
|
||||||
|
@ -78,9 +78,9 @@ void ExtractorCallbacks::ProcessNode(const osmium::Node &input_node,
|
|||||||
{
|
{
|
||||||
external_memory.barrier_nodes.push_back(id);
|
external_memory.barrier_nodes.push_back(id);
|
||||||
}
|
}
|
||||||
if (result_node.traffic_lights)
|
if (result_node.traffic_lights != TrafficLightClass::NONE)
|
||||||
{
|
{
|
||||||
external_memory.traffic_signals.push_back(id);
|
external_memory.external_traffic_signals.push_back({id, result_node.traffic_lights});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,10 @@ namespace osrm
|
|||||||
namespace extractor
|
namespace extractor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static constexpr int SECOND_TO_DECISECOND = 10;
|
||||||
|
|
||||||
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
||||||
const std::unordered_set<NodeID> &traffic_signals,
|
const TrafficSignals &traffic_signals,
|
||||||
ScriptingEnvironment &scripting_environment,
|
ScriptingEnvironment &scripting_environment,
|
||||||
std::vector<TurnRestriction> &turn_restrictions,
|
std::vector<TurnRestriction> &turn_restrictions,
|
||||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||||
@ -207,16 +209,20 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
rev_edge_data2.annotation_data, rev_edge_data1.annotation_data);
|
rev_edge_data2.annotation_data, rev_edge_data1.annotation_data);
|
||||||
|
|
||||||
// Add node penalty when compress edge crosses a traffic signal
|
// Add node penalty when compress edge crosses a traffic signal
|
||||||
const bool has_node_penalty = traffic_signals.find(node_v) != traffic_signals.end();
|
const bool has_forward_signal = traffic_signals.HasSignal(node_u, node_v);
|
||||||
EdgeDuration node_duration_penalty = MAXIMAL_EDGE_DURATION;
|
const bool has_reverse_signal = traffic_signals.HasSignal(node_w, node_v);
|
||||||
EdgeWeight node_weight_penalty = INVALID_EDGE_WEIGHT;
|
|
||||||
if (has_node_penalty)
|
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
|
// we cannot handle this as node penalty, if it depends on turn direction
|
||||||
if (fwd_edge_data1.flags.restricted != fwd_edge_data2.flags.restricted)
|
if (fwd_edge_data1.flags.restricted != fwd_edge_data2.flags.restricted)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// generate an artifical turn for the turn penalty generation
|
// generate an artificial turn for the turn penalty generation
|
||||||
std::vector<ExtractionTurnLeg> roads_on_the_right;
|
std::vector<ExtractionTurnLeg> roads_on_the_right;
|
||||||
std::vector<ExtractionTurnLeg> roads_on_the_left;
|
std::vector<ExtractionTurnLeg> roads_on_the_left;
|
||||||
ExtractionTurn extraction_turn(0,
|
ExtractionTurn extraction_turn(0,
|
||||||
@ -245,8 +251,24 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
roads_on_the_right,
|
roads_on_the_right,
|
||||||
roads_on_the_left);
|
roads_on_the_left);
|
||||||
scripting_environment.ProcessTurn(extraction_turn);
|
scripting_environment.ProcessTurn(extraction_turn);
|
||||||
node_duration_penalty = extraction_turn.duration * 10;
|
|
||||||
node_weight_penalty = extraction_turn.weight * weight_multiplier;
|
auto update_direction_penalty =
|
||||||
|
[&extraction_turn, weight_multiplier](bool signal,
|
||||||
|
EdgeDuration &duration_penalty,
|
||||||
|
EdgeWeight &weight_penalty) {
|
||||||
|
if (signal)
|
||||||
|
{
|
||||||
|
duration_penalty = extraction_turn.duration * SECOND_TO_DECISECOND;
|
||||||
|
weight_penalty = extraction_turn.weight * weight_multiplier;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
update_direction_penalty(has_forward_signal,
|
||||||
|
forward_node_duration_penalty,
|
||||||
|
forward_node_weight_penalty);
|
||||||
|
update_direction_penalty(has_reverse_signal,
|
||||||
|
reverse_node_duration_penalty,
|
||||||
|
reverse_node_weight_penalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get weights before graph is modified
|
// Get weights before graph is modified
|
||||||
@ -278,27 +300,37 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
BOOST_ASSERT(0 != reverse_weight1);
|
BOOST_ASSERT(0 != reverse_weight1);
|
||||||
BOOST_ASSERT(0 != reverse_weight2);
|
BOOST_ASSERT(0 != reverse_weight2);
|
||||||
|
|
||||||
// add weight of e2's to e1
|
auto apply_e2_to_e1 = [&graph](EdgeID edge,
|
||||||
graph.GetEdgeData(forward_e1).weight += forward_weight2;
|
EdgeWeight weight,
|
||||||
graph.GetEdgeData(reverse_e1).weight += reverse_weight2;
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
|
EdgeDuration &duration_penalty,
|
||||||
|
EdgeWeight &weight_penalty) {
|
||||||
|
auto &edge_data = graph.GetEdgeData(edge);
|
||||||
|
edge_data.weight += weight;
|
||||||
|
edge_data.duration += duration;
|
||||||
|
edge_data.distance += distance;
|
||||||
|
if (weight_penalty != INVALID_EDGE_WEIGHT &&
|
||||||
|
duration_penalty != MAXIMAL_EDGE_DURATION)
|
||||||
|
{
|
||||||
|
edge_data.weight += weight_penalty;
|
||||||
|
edge_data.duration += duration_penalty;
|
||||||
|
// Note: no penalties for distances
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// add duration of e2's to e1
|
apply_e2_to_e1(forward_e1,
|
||||||
graph.GetEdgeData(forward_e1).duration += forward_duration2;
|
forward_weight2,
|
||||||
graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
|
forward_duration2,
|
||||||
|
forward_distance2,
|
||||||
// add distance of e2's to e1
|
forward_node_weight_penalty,
|
||||||
graph.GetEdgeData(forward_e1).distance += forward_distance2;
|
forward_node_duration_penalty);
|
||||||
graph.GetEdgeData(reverse_e1).distance += reverse_distance2;
|
apply_e2_to_e1(reverse_e1,
|
||||||
|
reverse_weight2,
|
||||||
if (node_weight_penalty != INVALID_EDGE_WEIGHT &&
|
reverse_duration2,
|
||||||
node_duration_penalty != MAXIMAL_EDGE_DURATION)
|
reverse_distance2,
|
||||||
{
|
reverse_node_weight_penalty,
|
||||||
graph.GetEdgeData(forward_e1).weight += node_weight_penalty;
|
reverse_node_duration_penalty);
|
||||||
graph.GetEdgeData(reverse_e1).weight += node_weight_penalty;
|
|
||||||
graph.GetEdgeData(forward_e1).duration += node_duration_penalty;
|
|
||||||
graph.GetEdgeData(reverse_e1).duration += node_duration_penalty;
|
|
||||||
// Note: no penalties for distances
|
|
||||||
}
|
|
||||||
|
|
||||||
// extend e1's to targets of e2's
|
// extend e1's to targets of e2's
|
||||||
graph.SetTarget(forward_e1, node_w);
|
graph.SetTarget(forward_e1, node_w);
|
||||||
@ -311,6 +343,25 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
// update any involved turn relations
|
// update any involved turn relations
|
||||||
turn_path_compressor.Compress(node_u, node_v, node_w);
|
turn_path_compressor.Compress(node_u, node_v, node_w);
|
||||||
|
|
||||||
|
// Forward and reversed compressed edge lengths need to match.
|
||||||
|
// Set a dummy empty penalty weight if opposite value exists.
|
||||||
|
auto set_dummy_penalty = [](EdgeWeight &weight_penalty,
|
||||||
|
EdgeDuration &duration_penalty,
|
||||||
|
EdgeWeight &other_weight_penalty) {
|
||||||
|
if (weight_penalty == INVALID_EDGE_WEIGHT &&
|
||||||
|
other_weight_penalty != INVALID_EDGE_WEIGHT)
|
||||||
|
{
|
||||||
|
weight_penalty = 0;
|
||||||
|
duration_penalty = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
set_dummy_penalty(forward_node_weight_penalty,
|
||||||
|
forward_node_duration_penalty,
|
||||||
|
reverse_node_weight_penalty);
|
||||||
|
set_dummy_penalty(reverse_node_weight_penalty,
|
||||||
|
reverse_node_duration_penalty,
|
||||||
|
forward_node_weight_penalty);
|
||||||
|
|
||||||
// store compressed geometry in container
|
// store compressed geometry in container
|
||||||
geometry_compressor.CompressEdge(forward_e1,
|
geometry_compressor.CompressEdge(forward_e1,
|
||||||
forward_e2,
|
forward_e2,
|
||||||
@ -320,8 +371,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
forward_weight2,
|
forward_weight2,
|
||||||
forward_duration1,
|
forward_duration1,
|
||||||
forward_duration2,
|
forward_duration2,
|
||||||
node_weight_penalty,
|
forward_node_weight_penalty,
|
||||||
node_duration_penalty);
|
forward_node_duration_penalty);
|
||||||
geometry_compressor.CompressEdge(reverse_e1,
|
geometry_compressor.CompressEdge(reverse_e1,
|
||||||
reverse_e2,
|
reverse_e2,
|
||||||
node_v,
|
node_v,
|
||||||
@ -330,8 +381,8 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
|
|||||||
reverse_weight2,
|
reverse_weight2,
|
||||||
reverse_duration1,
|
reverse_duration1,
|
||||||
reverse_duration2,
|
reverse_duration2,
|
||||||
node_weight_penalty,
|
reverse_node_weight_penalty,
|
||||||
node_duration_penalty);
|
reverse_node_duration_penalty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,11 @@ NodeBasedGraphFactory::NodeBasedGraphFactory(
|
|||||||
const boost::filesystem::path &input_file,
|
const boost::filesystem::path &input_file,
|
||||||
ScriptingEnvironment &scripting_environment,
|
ScriptingEnvironment &scripting_environment,
|
||||||
std::vector<TurnRestriction> &turn_restrictions,
|
std::vector<TurnRestriction> &turn_restrictions,
|
||||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides)
|
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||||
|
const TrafficSignals &traffic_signals)
|
||||||
{
|
{
|
||||||
LoadDataFromFile(input_file);
|
LoadDataFromFile(input_file);
|
||||||
Compress(scripting_environment, turn_restrictions, maneuver_overrides);
|
Compress(scripting_environment, turn_restrictions, maneuver_overrides, traffic_signals);
|
||||||
CompressGeometry();
|
CompressGeometry();
|
||||||
CompressAnnotationData();
|
CompressAnnotationData();
|
||||||
}
|
}
|
||||||
@ -31,16 +32,10 @@ NodeBasedGraphFactory::NodeBasedGraphFactory(
|
|||||||
void NodeBasedGraphFactory::LoadDataFromFile(const boost::filesystem::path &input_file)
|
void NodeBasedGraphFactory::LoadDataFromFile(const boost::filesystem::path &input_file)
|
||||||
{
|
{
|
||||||
auto barriers_iter = inserter(barriers, end(barriers));
|
auto barriers_iter = inserter(barriers, end(barriers));
|
||||||
auto traffic_signals_iter = inserter(traffic_signals, end(traffic_signals));
|
|
||||||
std::vector<NodeBasedEdge> edge_list;
|
std::vector<NodeBasedEdge> edge_list;
|
||||||
|
|
||||||
files::readRawNBGraph(input_file,
|
files::readRawNBGraph(
|
||||||
barriers_iter,
|
input_file, barriers_iter, coordinates, osm_node_ids, edge_list, annotation_data);
|
||||||
traffic_signals_iter,
|
|
||||||
coordinates,
|
|
||||||
osm_node_ids,
|
|
||||||
edge_list,
|
|
||||||
annotation_data);
|
|
||||||
|
|
||||||
const auto number_of_node_based_nodes = coordinates.size();
|
const auto number_of_node_based_nodes = coordinates.size();
|
||||||
if (edge_list.empty())
|
if (edge_list.empty())
|
||||||
@ -80,7 +75,8 @@ void NodeBasedGraphFactory::LoadDataFromFile(const boost::filesystem::path &inpu
|
|||||||
|
|
||||||
void NodeBasedGraphFactory::Compress(ScriptingEnvironment &scripting_environment,
|
void NodeBasedGraphFactory::Compress(ScriptingEnvironment &scripting_environment,
|
||||||
std::vector<TurnRestriction> &turn_restrictions,
|
std::vector<TurnRestriction> &turn_restrictions,
|
||||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides)
|
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||||
|
const TrafficSignals &traffic_signals)
|
||||||
{
|
{
|
||||||
GraphCompressor graph_compressor;
|
GraphCompressor graph_compressor;
|
||||||
graph_compressor.Compress(barriers,
|
graph_compressor.Compress(barriers,
|
||||||
|
@ -285,11 +285,41 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
return get_location_tag(context, node.location(), key);
|
return get_location_tag(context, node.location(), key);
|
||||||
});
|
});
|
||||||
|
|
||||||
context.state.new_usertype<ExtractionNode>("ResultNode",
|
context.state.new_enum("traffic_lights",
|
||||||
"traffic_lights",
|
"none",
|
||||||
&ExtractionNode::traffic_lights,
|
extractor::TrafficLightClass::NONE,
|
||||||
"barrier",
|
"direction_all",
|
||||||
&ExtractionNode::barrier);
|
extractor::TrafficLightClass::DIRECTION_ALL,
|
||||||
|
"direction_forward",
|
||||||
|
extractor::TrafficLightClass::DIRECTION_FORWARD,
|
||||||
|
"direction_reverse",
|
||||||
|
extractor::TrafficLightClass::DIRECTION_REVERSE);
|
||||||
|
|
||||||
|
context.state.new_usertype<ExtractionNode>(
|
||||||
|
"ResultNode",
|
||||||
|
"traffic_lights",
|
||||||
|
sol::property([](const ExtractionNode &node) { return node.traffic_lights; },
|
||||||
|
[](ExtractionNode &node, const sol::object &obj) {
|
||||||
|
if (obj.is<bool>())
|
||||||
|
{
|
||||||
|
// The old approach of assigning a boolean traffic light
|
||||||
|
// state to the node is converted to the class enum
|
||||||
|
// TODO: Make a breaking API change and remove this option.
|
||||||
|
bool val = obj.as<bool>();
|
||||||
|
node.traffic_lights = (val) ? TrafficLightClass::DIRECTION_ALL
|
||||||
|
: TrafficLightClass::NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(obj.is<TrafficLightClass::Direction>());
|
||||||
|
{
|
||||||
|
TrafficLightClass::Direction val =
|
||||||
|
obj.as<TrafficLightClass::Direction>();
|
||||||
|
node.traffic_lights = val;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
"barrier",
|
||||||
|
&ExtractionNode::barrier);
|
||||||
|
|
||||||
context.state.new_usertype<RoadClassification>(
|
context.state.new_usertype<RoadClassification>(
|
||||||
"RoadClassification",
|
"RoadClassification",
|
||||||
|
@ -44,7 +44,7 @@ std::size_t loadGraph(const std::string &path,
|
|||||||
auto nop = boost::make_function_output_iterator([](auto) {});
|
auto nop = boost::make_function_output_iterator([](auto) {});
|
||||||
|
|
||||||
extractor::files::readRawNBGraph(
|
extractor::files::readRawNBGraph(
|
||||||
path, nop, nop, coordinate_list, osm_node_ids, edge_list, annotation_data);
|
path, nop, coordinate_list, osm_node_ids, edge_list, annotation_data);
|
||||||
|
|
||||||
// Building a node-based graph
|
// Building a node-based graph
|
||||||
for (const auto &input_edge : edge_list)
|
for (const auto &input_edge : edge_list)
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -66,7 +65,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
|
|||||||
GraphCompressor compressor;
|
GraphCompressor compressor;
|
||||||
|
|
||||||
std::unordered_set<NodeID> barrier_nodes;
|
std::unordered_set<NodeID> barrier_nodes;
|
||||||
std::unordered_set<NodeID> traffic_lights;
|
TrafficSignals traffic_lights;
|
||||||
std::vector<TurnRestriction> restrictions;
|
std::vector<TurnRestriction> restrictions;
|
||||||
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
@ -112,7 +111,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
|
|||||||
GraphCompressor compressor;
|
GraphCompressor compressor;
|
||||||
|
|
||||||
std::unordered_set<NodeID> barrier_nodes;
|
std::unordered_set<NodeID> barrier_nodes;
|
||||||
std::unordered_set<NodeID> traffic_lights;
|
TrafficSignals traffic_lights;
|
||||||
std::vector<TurnRestriction> restrictions;
|
std::vector<TurnRestriction> restrictions;
|
||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
||||||
@ -175,7 +174,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
|
|||||||
GraphCompressor compressor;
|
GraphCompressor compressor;
|
||||||
|
|
||||||
std::unordered_set<NodeID> barrier_nodes;
|
std::unordered_set<NodeID> barrier_nodes;
|
||||||
std::unordered_set<NodeID> traffic_lights;
|
TrafficSignals traffic_lights;
|
||||||
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
||||||
std::vector<TurnRestriction> restrictions;
|
std::vector<TurnRestriction> restrictions;
|
||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
@ -218,7 +217,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
|
|||||||
GraphCompressor compressor;
|
GraphCompressor compressor;
|
||||||
|
|
||||||
std::unordered_set<NodeID> barrier_nodes;
|
std::unordered_set<NodeID> barrier_nodes;
|
||||||
std::unordered_set<NodeID> traffic_lights;
|
TrafficSignals traffic_lights;
|
||||||
std::vector<NodeBasedEdgeAnnotation> annotations(2);
|
std::vector<NodeBasedEdgeAnnotation> annotations(2);
|
||||||
std::vector<TurnRestriction> restrictions;
|
std::vector<TurnRestriction> restrictions;
|
||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
@ -256,7 +255,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
|
|||||||
GraphCompressor compressor;
|
GraphCompressor compressor;
|
||||||
|
|
||||||
std::unordered_set<NodeID> barrier_nodes;
|
std::unordered_set<NodeID> barrier_nodes;
|
||||||
std::unordered_set<NodeID> traffic_lights;
|
TrafficSignals traffic_lights;
|
||||||
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
||||||
std::vector<TurnRestriction> restrictions;
|
std::vector<TurnRestriction> restrictions;
|
||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
|
@ -19,7 +19,7 @@ using Graph = util::NodeBasedDynamicGraph;
|
|||||||
BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
|
BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
|
||||||
{
|
{
|
||||||
std::unordered_set<NodeID> barrier_nodes{6};
|
std::unordered_set<NodeID> barrier_nodes{6};
|
||||||
std::unordered_set<NodeID> traffic_lights;
|
TrafficSignals traffic_lights;
|
||||||
std::vector<NodeBasedEdgeAnnotation> annotations{
|
std::vector<NodeBasedEdgeAnnotation> annotations{
|
||||||
{EMPTY_NAMEID, 0, INAVLID_CLASS_DATA, TRAVEL_MODE_DRIVING, false},
|
{EMPTY_NAMEID, 0, INAVLID_CLASS_DATA, TRAVEL_MODE_DRIVING, false},
|
||||||
{EMPTY_NAMEID, 1, INAVLID_CLASS_DATA, TRAVEL_MODE_DRIVING, false}};
|
{EMPTY_NAMEID, 1, INAVLID_CLASS_DATA, TRAVEL_MODE_DRIVING, false}};
|
||||||
@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE(simple_intersection_connectivity)
|
|||||||
BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
|
BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
|
||||||
{
|
{
|
||||||
std::unordered_set<NodeID> barrier_nodes;
|
std::unordered_set<NodeID> barrier_nodes;
|
||||||
std::unordered_set<NodeID> traffic_lights;
|
TrafficSignals traffic_lights;
|
||||||
std::vector<NodeBasedEdgeAnnotation> annotations;
|
std::vector<NodeBasedEdgeAnnotation> annotations;
|
||||||
std::vector<TurnRestriction> restrictions;
|
std::vector<TurnRestriction> restrictions;
|
||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
@ -259,7 +259,7 @@ BOOST_AUTO_TEST_CASE(roundabout_intersection_connectivity)
|
|||||||
BOOST_AUTO_TEST_CASE(skip_degree_two_nodes)
|
BOOST_AUTO_TEST_CASE(skip_degree_two_nodes)
|
||||||
{
|
{
|
||||||
std::unordered_set<NodeID> barrier_nodes{1};
|
std::unordered_set<NodeID> barrier_nodes{1};
|
||||||
std::unordered_set<NodeID> traffic_lights{2};
|
TrafficSignals traffic_lights = {{2}, {}};
|
||||||
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
std::vector<NodeBasedEdgeAnnotation> annotations(1);
|
||||||
std::vector<TurnRestriction> restrictions;
|
std::vector<TurnRestriction> restrictions;
|
||||||
CompressedEdgeContainer container;
|
CompressedEdgeContainer container;
|
||||||
|
Loading…
Reference in New Issue
Block a user