Move guidance turn generation out of EBGF
This commit is contained in:
parent
988b6e3311
commit
10de243556
@ -126,7 +126,7 @@ configure_file(
|
|||||||
)
|
)
|
||||||
file(GLOB UtilGlob src/util/*.cpp src/util/*/*.cpp)
|
file(GLOB UtilGlob src/util/*.cpp src/util/*/*.cpp)
|
||||||
file(GLOB ExtractorGlob src/extractor/*.cpp src/extractor/*/*.cpp)
|
file(GLOB ExtractorGlob src/extractor/*.cpp src/extractor/*/*.cpp)
|
||||||
file(GLOB GuidanceGlob src/guidance/*.cpp)
|
file(GLOB GuidanceGlob src/guidance/*.cpp src/extractor/intersection/*.cpp)
|
||||||
file(GLOB PartitionerGlob src/partitioner/*.cpp)
|
file(GLOB PartitionerGlob src/partitioner/*.cpp)
|
||||||
file(GLOB CustomizerGlob src/customize/*.cpp)
|
file(GLOB CustomizerGlob src/customize/*.cpp)
|
||||||
file(GLOB ContractorGlob src/contractor/*.cpp)
|
file(GLOB ContractorGlob src/contractor/*.cpp)
|
||||||
|
@ -115,6 +115,7 @@ module.exports = function() {
|
|||||||
this.OSRM_EXTRACT_PATH,
|
this.OSRM_EXTRACT_PATH,
|
||||||
this.OSRM_CONTRACT_PATH,
|
this.OSRM_CONTRACT_PATH,
|
||||||
this.LIB_OSRM_EXTRACT_PATH,
|
this.LIB_OSRM_EXTRACT_PATH,
|
||||||
|
this.LIB_OSRM_GUIDANCE_PATH,
|
||||||
this.LIB_OSRM_CONTRACT_PATH
|
this.LIB_OSRM_CONTRACT_PATH
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ module.exports = function () {
|
|||||||
this.OSRM_CONTRACT_PATH = path.resolve(util.format('%s/%s%s', this.BIN_PATH, 'osrm-contract', this.EXE));
|
this.OSRM_CONTRACT_PATH = path.resolve(util.format('%s/%s%s', this.BIN_PATH, 'osrm-contract', this.EXE));
|
||||||
this.OSRM_ROUTED_PATH = path.resolve(util.format('%s/%s%s', this.BIN_PATH, 'osrm-routed', this.EXE));
|
this.OSRM_ROUTED_PATH = path.resolve(util.format('%s/%s%s', this.BIN_PATH, 'osrm-routed', this.EXE));
|
||||||
this.LIB_OSRM_EXTRACT_PATH = util.format('%s/' + this.LIB, this.BIN_PATH, 'osrm_extract'),
|
this.LIB_OSRM_EXTRACT_PATH = util.format('%s/' + this.LIB, this.BIN_PATH, 'osrm_extract'),
|
||||||
|
this.LIB_OSRM_GUIDANCE_PATH = util.format('%s/' + this.LIB, this.BIN_PATH, 'osrm_guidance'),
|
||||||
this.LIB_OSRM_CONTRACT_PATH = util.format('%s/' + this.LIB, this.BIN_PATH, 'osrm_contract'),
|
this.LIB_OSRM_CONTRACT_PATH = util.format('%s/' + this.LIB, this.BIN_PATH, 'osrm_contract'),
|
||||||
this.LIB_OSRM_PATH = util.format('%s/' + this.LIB, this.BIN_PATH, 'osrm');
|
this.LIB_OSRM_PATH = util.format('%s/' + this.LIB, this.BIN_PATH, 'osrm');
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include "extractor/profile_properties.hpp"
|
#include "extractor/profile_properties.hpp"
|
||||||
#include "extractor/segment_data_container.hpp"
|
#include "extractor/segment_data_container.hpp"
|
||||||
#include "extractor/turn_lane_types.hpp"
|
#include "extractor/turn_lane_types.hpp"
|
||||||
|
|
||||||
|
#include "guidance/turn_bearing.hpp"
|
||||||
#include "guidance/turn_data_container.hpp"
|
#include "guidance/turn_data_container.hpp"
|
||||||
#include "guidance/turn_instruction.hpp"
|
#include "guidance/turn_instruction.hpp"
|
||||||
|
|
||||||
@ -35,7 +37,6 @@
|
|||||||
#include "util/filtered_graph.hpp"
|
#include "util/filtered_graph.hpp"
|
||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
#include "util/guidance/turn_lanes.hpp"
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
#include "util/name_table.hpp"
|
#include "util/name_table.hpp"
|
||||||
@ -328,14 +329,14 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
util::vector_view<EntryClassID> entry_class_ids(
|
util::vector_view<EntryClassID> entry_class_ids(
|
||||||
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
||||||
|
|
||||||
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
|
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<guidance::TurnBearing>(
|
||||||
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
|
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
|
||||||
util::vector_view<util::guidance::TurnBearing> pre_turn_bearings(
|
util::vector_view<guidance::TurnBearing> pre_turn_bearings(
|
||||||
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
||||||
|
|
||||||
const auto post_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing>(
|
const auto post_turn_bearing_ptr = layout.GetBlockPtr<guidance::TurnBearing>(
|
||||||
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
|
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
|
||||||
util::vector_view<util::guidance::TurnBearing> post_turn_bearings(
|
util::vector_view<guidance::TurnBearing> post_turn_bearings(
|
||||||
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
||||||
|
|
||||||
turn_data = guidance::TurnDataView(std::move(turn_instructions),
|
turn_data = guidance::TurnDataView(std::move(turn_instructions),
|
||||||
@ -844,11 +845,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
return intersection_bearings_view.GetBearingClass(node);
|
return intersection_bearings_view.GetBearingClass(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
|
guidance::TurnBearing PreTurnBearing(const EdgeID eid) const override final
|
||||||
{
|
{
|
||||||
return turn_data.GetPreTurnBearing(eid);
|
return turn_data.GetPreTurnBearing(eid);
|
||||||
}
|
}
|
||||||
util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
|
guidance::TurnBearing PostTurnBearing(const EdgeID eid) const override final
|
||||||
{
|
{
|
||||||
return turn_data.GetPostTurnBearing(eid);
|
return turn_data.GetPostTurnBearing(eid);
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,13 @@
|
|||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
#include "extractor/turn_lane_types.hpp"
|
#include "extractor/turn_lane_types.hpp"
|
||||||
|
|
||||||
|
#include "guidance/turn_bearing.hpp"
|
||||||
#include "guidance/turn_instruction.hpp"
|
#include "guidance/turn_instruction.hpp"
|
||||||
|
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
#include "util/guidance/turn_lanes.hpp"
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
#include "util/string_util.hpp"
|
#include "util/string_util.hpp"
|
||||||
@ -181,8 +182,8 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual double GetWeightMultiplier() const = 0;
|
virtual double GetWeightMultiplier() const = 0;
|
||||||
|
|
||||||
virtual util::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0;
|
virtual osrm::guidance::TurnBearing PreTurnBearing(const EdgeID eid) const = 0;
|
||||||
virtual util::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const = 0;
|
virtual osrm::guidance::TurnBearing PostTurnBearing(const EdgeID eid) const = 0;
|
||||||
|
|
||||||
virtual util::guidance::BearingClass GetBearingClass(const NodeID node) const = 0;
|
virtual util::guidance::BearingClass GetBearingClass(const NodeID node) const = 0;
|
||||||
|
|
||||||
|
@ -3,13 +3,14 @@
|
|||||||
|
|
||||||
#include "extractor/class_data.hpp"
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
|
|
||||||
|
#include "guidance/turn_bearing.hpp"
|
||||||
#include "guidance/turn_instruction.hpp"
|
#include "guidance/turn_instruction.hpp"
|
||||||
|
|
||||||
#include "engine/phantom_node.hpp"
|
#include "engine/phantom_node.hpp"
|
||||||
|
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
#include "util/guidance/turn_lanes.hpp"
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
@ -56,9 +57,9 @@ struct PathData
|
|||||||
DatasourceID datasource_id;
|
DatasourceID datasource_id;
|
||||||
|
|
||||||
// bearing (as seen from the intersection) pre-turn
|
// bearing (as seen from the intersection) pre-turn
|
||||||
util::guidance::TurnBearing pre_turn_bearing;
|
osrm::guidance::TurnBearing pre_turn_bearing;
|
||||||
// bearing (as seen from the intersection) post-turn
|
// bearing (as seen from the intersection) post-turn
|
||||||
util::guidance::TurnBearing post_turn_bearing;
|
osrm::guidance::TurnBearing post_turn_bearing;
|
||||||
|
|
||||||
// Driving side of the turn
|
// Driving side of the turn
|
||||||
bool is_left_hand_driving;
|
bool is_left_hand_driving;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef OSRM_ENGINE_ROUTING_BASE_HPP
|
#ifndef OSRM_ENGINE_ROUTING_BASE_HPP
|
||||||
#define OSRM_ENGINE_ROUTING_BASE_HPP
|
#define OSRM_ENGINE_ROUTING_BASE_HPP
|
||||||
|
|
||||||
|
#include "guidance/turn_bearing.hpp"
|
||||||
#include "guidance/turn_instruction.hpp"
|
#include "guidance/turn_instruction.hpp"
|
||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
@ -10,7 +11,6 @@
|
|||||||
#include "engine/search_engine_data.hpp"
|
#include "engine/search_engine_data.hpp"
|
||||||
|
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
@ -205,8 +205,8 @@ void annotatePath(const FacadeT &facade,
|
|||||||
classes,
|
classes,
|
||||||
EMPTY_ENTRY_CLASS,
|
EMPTY_ENTRY_CLASS,
|
||||||
datasource_vector[segment_idx],
|
datasource_vector[segment_idx],
|
||||||
util::guidance::TurnBearing(0),
|
osrm::guidance::TurnBearing(0),
|
||||||
util::guidance::TurnBearing(0),
|
osrm::guidance::TurnBearing(0),
|
||||||
is_left_hand_driving});
|
is_left_hand_driving});
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||||
@ -279,8 +279,8 @@ void annotatePath(const FacadeT &facade,
|
|||||||
facade.GetClassData(target_node_id),
|
facade.GetClassData(target_node_id),
|
||||||
EMPTY_ENTRY_CLASS,
|
EMPTY_ENTRY_CLASS,
|
||||||
datasource_vector[segment_idx],
|
datasource_vector[segment_idx],
|
||||||
util::guidance::TurnBearing(0),
|
guidance::TurnBearing(0),
|
||||||
util::guidance::TurnBearing(0),
|
guidance::TurnBearing(0),
|
||||||
is_target_left_hand_driving});
|
is_target_left_hand_driving});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,11 +75,9 @@ class EdgeBasedGraphFactory
|
|||||||
const std::vector<util::Coordinate> &coordinates,
|
const std::vector<util::Coordinate> &coordinates,
|
||||||
const util::NameTable &name_table,
|
const util::NameTable &name_table,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
LaneDescriptionMap &lane_description_map);
|
const LaneDescriptionMap &lane_description_map);
|
||||||
|
|
||||||
void Run(ScriptingEnvironment &scripting_environment,
|
void Run(ScriptingEnvironment &scripting_environment,
|
||||||
const std::string &turn_data_filename,
|
|
||||||
const std::string &turn_lane_data_filename,
|
|
||||||
const std::string &turn_weight_penalties_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
const std::string &turn_duration_penalties_filename,
|
const std::string &turn_duration_penalties_filename,
|
||||||
const std::string &turn_penalties_index_filename,
|
const std::string &turn_penalties_index_filename,
|
||||||
@ -95,12 +93,6 @@ class EdgeBasedGraphFactory
|
|||||||
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
||||||
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
||||||
|
|
||||||
// These access functions don't destroy the content
|
|
||||||
const std::vector<BearingClassID> &GetBearingClassIds() const;
|
|
||||||
std::vector<BearingClassID> &GetBearingClassIds();
|
|
||||||
std::vector<util::guidance::BearingClass> GetBearingClasses() const;
|
|
||||||
std::vector<util::guidance::EntryClass> GetEntryClasses() const;
|
|
||||||
|
|
||||||
std::uint64_t GetNumberOfEdgeBasedNodes() const;
|
std::uint64_t GetNumberOfEdgeBasedNodes() const;
|
||||||
|
|
||||||
// Basic analysis of a turn (u --(e1)-- v --(e2)-- w)
|
// Basic analysis of a turn (u --(e1)-- v --(e2)-- w)
|
||||||
@ -158,7 +150,7 @@ class EdgeBasedGraphFactory
|
|||||||
|
|
||||||
const util::NameTable &name_table;
|
const util::NameTable &name_table;
|
||||||
const std::unordered_set<EdgeID> &segregated_edges;
|
const std::unordered_set<EdgeID> &segregated_edges;
|
||||||
LaneDescriptionMap &lane_description_map;
|
const LaneDescriptionMap &lane_description_map;
|
||||||
|
|
||||||
// In the edge based graph, any traversable (non reversed) edge of the node-based graph forms a
|
// In the edge based graph, any traversable (non reversed) edge of the node-based graph forms a
|
||||||
// node of the edge-based graph. To be able to name these nodes, we loop over the node-based
|
// node of the edge-based graph. To be able to name these nodes, we loop over the node-based
|
||||||
@ -175,8 +167,6 @@ class EdgeBasedGraphFactory
|
|||||||
// Edge-expanded edges are generate for all valid turns. The validity can be checked via the
|
// Edge-expanded edges are generate for all valid turns. The validity can be checked via the
|
||||||
// restriction maps
|
// restriction maps
|
||||||
void GenerateEdgeExpandedEdges(ScriptingEnvironment &scripting_environment,
|
void GenerateEdgeExpandedEdges(ScriptingEnvironment &scripting_environment,
|
||||||
const std::string &original_edge_data_filename,
|
|
||||||
const std::string &turn_lane_data_filename,
|
|
||||||
const std::string &turn_weight_penalties_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
const std::string &turn_duration_penalties_filename,
|
const std::string &turn_duration_penalties_filename,
|
||||||
const std::string &turn_penalties_index_filename,
|
const std::string &turn_penalties_index_filename,
|
||||||
@ -187,15 +177,8 @@ class EdgeBasedGraphFactory
|
|||||||
|
|
||||||
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
|
||||||
|
|
||||||
std::size_t restricted_turns_counter;
|
|
||||||
std::size_t skipped_uturns_counter;
|
|
||||||
std::size_t skipped_barrier_turns_counter;
|
|
||||||
|
|
||||||
// mapping of node-based edges to edge-based nodes
|
// mapping of node-based edges to edge-based nodes
|
||||||
std::vector<NodeID> nbe_to_ebn_mapping;
|
std::vector<NodeID> nbe_to_ebn_mapping;
|
||||||
util::ConcurrentIDMap<util::guidance::BearingClass, BearingClassID> bearing_class_hash;
|
|
||||||
std::vector<BearingClassID> bearing_class_by_node_based_node;
|
|
||||||
util::ConcurrentIDMap<util::guidance::EntryClass, EntryClassID> entry_class_hash;
|
|
||||||
};
|
};
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -34,6 +34,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "extractor/graph_compressor.hpp"
|
#include "extractor/graph_compressor.hpp"
|
||||||
#include "extractor/packed_osm_ids.hpp"
|
#include "extractor/packed_osm_ids.hpp"
|
||||||
|
|
||||||
|
#include "guidance/guidance_processing.hpp"
|
||||||
|
#include "guidance/turn_data_container.hpp"
|
||||||
|
|
||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
#include "util/guidance/turn_lanes.hpp"
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
@ -72,8 +75,8 @@ class Extractor
|
|||||||
const std::vector<TurnRestriction> &turn_restrictions,
|
const std::vector<TurnRestriction> &turn_restrictions,
|
||||||
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
// might have to be updated to add new lane combinations
|
const util::NameTable &name_table,
|
||||||
LaneDescriptionMap &turn_lane_map,
|
const LaneDescriptionMap &turn_lane_map,
|
||||||
// for calculating turn penalties
|
// for calculating turn penalties
|
||||||
ScriptingEnvironment &scripting_environment,
|
ScriptingEnvironment &scripting_environment,
|
||||||
// output data
|
// output data
|
||||||
@ -81,8 +84,7 @@ class Extractor
|
|||||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||||
std::vector<bool> &node_is_startpoint,
|
std::vector<bool> &node_is_startpoint,
|
||||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list);
|
||||||
const std::string &intersection_class_output_file);
|
|
||||||
|
|
||||||
void FindComponents(unsigned max_edge_id,
|
void FindComponents(unsigned max_edge_id,
|
||||||
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
|
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
|
||||||
@ -101,6 +103,18 @@ class Extractor
|
|||||||
void WriteConditionalRestrictions(
|
void WriteConditionalRestrictions(
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
||||||
|
|
||||||
|
void ProcessGuidanceTurns(
|
||||||
|
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
|
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 std::vector<TurnRestriction> &turn_restrictions,
|
||||||
|
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||||
|
const util::NameTable &name_table,
|
||||||
|
LaneDescriptionMap lane_description_map,
|
||||||
|
ScriptingEnvironment &scripting_environment);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ class MergableRoadDetector
|
|||||||
const static double constexpr distance_to_extract = 120;
|
const static double constexpr distance_to_extract = 120;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace intersection
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ struct DistanceToNextIntersectionAccumulator
|
|||||||
double distance = 0.;
|
double distance = 0.;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace intersection
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
#ifndef OSRM_EXTRACTOR_TURN_DATA_CONTAINER_HPP
|
|
||||||
#define OSRM_EXTRACTOR_TURN_DATA_CONTAINER_HPP
|
|
||||||
|
|
||||||
#include "extractor/travel_mode.hpp"
|
|
||||||
#include "guidance/turn_instruction.hpp"
|
|
||||||
|
|
||||||
#include "storage/io_fwd.hpp"
|
|
||||||
#include "storage/shared_memory_ownership.hpp"
|
|
||||||
|
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
#include "util/vector_view.hpp"
|
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template <storage::Ownership Ownership> class TurnDataContainerImpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace serialization
|
|
||||||
{
|
|
||||||
template <storage::Ownership Ownership>
|
|
||||||
void read(storage::io::FileReader &reader, detail::TurnDataContainerImpl<Ownership> &turn_data);
|
|
||||||
|
|
||||||
template <storage::Ownership Ownership>
|
|
||||||
void write(storage::io::FileWriter &writer,
|
|
||||||
const detail::TurnDataContainerImpl<Ownership> &turn_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct TurnData
|
|
||||||
{
|
|
||||||
extractor::guidance::TurnInstruction turn_instruction;
|
|
||||||
LaneDataID lane_data_id;
|
|
||||||
EntryClassID entry_class_id;
|
|
||||||
util::guidance::TurnBearing pre_turn_bearing;
|
|
||||||
util::guidance::TurnBearing post_turn_bearing;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template <storage::Ownership Ownership> class TurnDataContainerImpl
|
|
||||||
{
|
|
||||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
|
||||||
|
|
||||||
public:
|
|
||||||
TurnDataContainerImpl() = default;
|
|
||||||
|
|
||||||
TurnDataContainerImpl(Vector<extractor::guidance::TurnInstruction> turn_instructions,
|
|
||||||
Vector<LaneDataID> lane_data_ids,
|
|
||||||
Vector<EntryClassID> entry_class_ids,
|
|
||||||
Vector<util::guidance::TurnBearing> pre_turn_bearings,
|
|
||||||
Vector<util::guidance::TurnBearing> post_turn_bearings)
|
|
||||||
: turn_instructions(std::move(turn_instructions)), lane_data_ids(std::move(lane_data_ids)),
|
|
||||||
entry_class_ids(std::move(entry_class_ids)),
|
|
||||||
pre_turn_bearings(std::move(pre_turn_bearings)),
|
|
||||||
post_turn_bearings(std::move(post_turn_bearings))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EntryClassID GetEntryClassID(const EdgeID id) const { return entry_class_ids[id]; }
|
|
||||||
|
|
||||||
util::guidance::TurnBearing GetPreTurnBearing(const EdgeID id) const
|
|
||||||
{
|
|
||||||
return pre_turn_bearings[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
util::guidance::TurnBearing GetPostTurnBearing(const EdgeID id) const
|
|
||||||
{
|
|
||||||
return post_turn_bearings[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
LaneDataID GetLaneDataID(const EdgeID id) const { return lane_data_ids[id]; }
|
|
||||||
|
|
||||||
bool HasLaneData(const EdgeID id) const { return INVALID_LANE_DATAID != lane_data_ids[id]; }
|
|
||||||
|
|
||||||
extractor::guidance::TurnInstruction GetTurnInstruction(const EdgeID id) const
|
|
||||||
{
|
|
||||||
return turn_instructions[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used by EdgeBasedGraphFactory to fill data structure
|
|
||||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
|
||||||
void push_back(const TurnData &data)
|
|
||||||
{
|
|
||||||
turn_instructions.push_back(data.turn_instruction);
|
|
||||||
lane_data_ids.push_back(data.lane_data_id);
|
|
||||||
entry_class_ids.push_back(data.entry_class_id);
|
|
||||||
pre_turn_bearings.push_back(data.pre_turn_bearing);
|
|
||||||
post_turn_bearings.push_back(data.post_turn_bearing);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
|
||||||
void append(const std::vector<TurnData> &others)
|
|
||||||
{
|
|
||||||
std::for_each(
|
|
||||||
others.begin(), others.end(), [this](const TurnData &other) { push_back(other); });
|
|
||||||
}
|
|
||||||
|
|
||||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
|
||||||
TurnDataContainerImpl &turn_data_container);
|
|
||||||
friend void serialization::write<Ownership>(storage::io::FileWriter &writer,
|
|
||||||
const TurnDataContainerImpl &turn_data_container);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vector<extractor::guidance::TurnInstruction> turn_instructions;
|
|
||||||
Vector<LaneDataID> lane_data_ids;
|
|
||||||
Vector<EntryClassID> entry_class_ids;
|
|
||||||
Vector<util::guidance::TurnBearing> pre_turn_bearings;
|
|
||||||
Vector<util::guidance::TurnBearing> post_turn_bearings;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
using TurnDataExternalContainer = detail::TurnDataContainerImpl<storage::Ownership::External>;
|
|
||||||
using TurnDataContainer = detail::TurnDataContainerImpl<storage::Ownership::Container>;
|
|
||||||
using TurnDataView = detail::TurnDataContainerImpl<storage::Ownership::View>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
49
include/guidance/guidance_processing.hpp
Normal file
49
include/guidance/guidance_processing.hpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef OSRM_GUIDANCE_GUIDANCE_RUNNER_HPP
|
||||||
|
#define OSRM_GUIDANCE_GUIDANCE_RUNNER_HPP
|
||||||
|
|
||||||
|
#include "guidance/turn_data_container.hpp"
|
||||||
|
|
||||||
|
#include "extractor/compressed_edge_container.hpp"
|
||||||
|
#include "extractor/node_data_container.hpp"
|
||||||
|
#include "extractor/suffix_table.hpp"
|
||||||
|
#include "extractor/turn_lane_types.hpp"
|
||||||
|
#include "extractor/way_restriction_map.hpp"
|
||||||
|
|
||||||
|
#include "util/coordinate.hpp"
|
||||||
|
#include "util/guidance/bearing_class.hpp"
|
||||||
|
#include "util/guidance/entry_class.hpp"
|
||||||
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
|
#include "util/name_table.hpp"
|
||||||
|
#include "util/node_based_graph.hpp"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace guidance
|
||||||
|
{
|
||||||
|
using BearingClassesVector = std::vector<BearingClassID>;
|
||||||
|
using BearingClassesMap = util::ConcurrentIDMap<util::guidance::BearingClass, BearingClassID>;
|
||||||
|
using EntryClassesMap = util::ConcurrentIDMap<util::guidance::EntryClass, EntryClassID>;
|
||||||
|
|
||||||
|
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::RestrictionMap &node_restriction_map,
|
||||||
|
const extractor::WayRestrictionMap &way_restriction_map,
|
||||||
|
const util::NameTable &name_table,
|
||||||
|
const extractor::SuffixTable &suffix_table,
|
||||||
|
const extractor::TurnLanesIndexedArray &turn_lanes_data,
|
||||||
|
extractor::LaneDescriptionMap &lane_description_map,
|
||||||
|
util::guidance::LaneDataIdMap &lane_data_map,
|
||||||
|
guidance::TurnDataExternalContainer &turn_data_container,
|
||||||
|
BearingClassesVector &bearing_class_by_node_based_node,
|
||||||
|
BearingClassesMap &bearing_class_hash,
|
||||||
|
EntryClassesMap &entry_class_hash);
|
||||||
|
|
||||||
|
} // namespace customizer
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
#endif
|
@ -12,6 +12,7 @@ class NameTable;
|
|||||||
namespace extractor
|
namespace extractor
|
||||||
{
|
{
|
||||||
class NodeBasedGraphFactory;
|
class NodeBasedGraphFactory;
|
||||||
|
}
|
||||||
|
|
||||||
namespace guidance
|
namespace guidance
|
||||||
{
|
{
|
||||||
@ -20,8 +21,7 @@ namespace guidance
|
|||||||
// - middle edges between two osm ways in one logic road (U-turn)
|
// - middle edges between two osm ways in one logic road (U-turn)
|
||||||
// - staggered intersections (X-cross)
|
// - staggered intersections (X-cross)
|
||||||
// - square/circle intersections
|
// - square/circle intersections
|
||||||
std::unordered_set<EdgeID> findSegregatedNodes(const NodeBasedGraphFactory &factory,
|
std::unordered_set<EdgeID> findSegregatedNodes(const extractor::NodeBasedGraphFactory &factory,
|
||||||
const util::NameTable &names);
|
const util::NameTable &names);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
38
include/guidance/turn_bearing.hpp
Normal file
38
include/guidance/turn_bearing.hpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef OSRM_INCLUDE_GUIDANCE_TURN_BEARING_HPP_
|
||||||
|
#define OSRM_INCLUDE_GUIDANCE_TURN_BEARING_HPP_
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace guidance
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const double bearing_scale = 360.0 / 256.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
class TurnBearing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// discretizes a bearing into distinct units of 1.4 degrees
|
||||||
|
TurnBearing(const double value = 0) : bearing(value / bearing_scale)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(value >= 0 && value < 360.0,
|
||||||
|
"Bearing value needs to be between 0 and 360 (exclusive)");
|
||||||
|
}
|
||||||
|
|
||||||
|
double Get() const { return bearing * bearing_scale; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::uint8_t bearing;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
} // namespace guidance
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
|
#endif /* OSRM_INCLUDE_GUIDANCE_TURN_BEARING_HPP_ */
|
@ -2,12 +2,12 @@
|
|||||||
#define OSRM_GUIDANCE_TURN_DATA_CONTAINER_HPP
|
#define OSRM_GUIDANCE_TURN_DATA_CONTAINER_HPP
|
||||||
|
|
||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
|
#include "guidance/turn_bearing.hpp"
|
||||||
#include "guidance/turn_instruction.hpp"
|
#include "guidance/turn_instruction.hpp"
|
||||||
|
|
||||||
#include "storage/io_fwd.hpp"
|
#include "storage/io_fwd.hpp"
|
||||||
#include "storage/shared_memory_ownership.hpp"
|
#include "storage/shared_memory_ownership.hpp"
|
||||||
|
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
#include "util/vector_view.hpp"
|
#include "util/vector_view.hpp"
|
||||||
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
@ -33,11 +33,11 @@ void write(storage::io::FileWriter &writer,
|
|||||||
|
|
||||||
struct TurnData
|
struct TurnData
|
||||||
{
|
{
|
||||||
guidance::TurnInstruction turn_instruction;
|
TurnInstruction turn_instruction;
|
||||||
LaneDataID lane_data_id;
|
LaneDataID lane_data_id;
|
||||||
EntryClassID entry_class_id;
|
EntryClassID entry_class_id;
|
||||||
util::guidance::TurnBearing pre_turn_bearing;
|
TurnBearing pre_turn_bearing;
|
||||||
util::guidance::TurnBearing post_turn_bearing;
|
TurnBearing post_turn_bearing;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -49,11 +49,11 @@ template <storage::Ownership Ownership> class TurnDataContainerImpl
|
|||||||
public:
|
public:
|
||||||
TurnDataContainerImpl() = default;
|
TurnDataContainerImpl() = default;
|
||||||
|
|
||||||
TurnDataContainerImpl(Vector<guidance::TurnInstruction> turn_instructions,
|
TurnDataContainerImpl(Vector<TurnInstruction> turn_instructions,
|
||||||
Vector<LaneDataID> lane_data_ids,
|
Vector<LaneDataID> lane_data_ids,
|
||||||
Vector<EntryClassID> entry_class_ids,
|
Vector<EntryClassID> entry_class_ids,
|
||||||
Vector<util::guidance::TurnBearing> pre_turn_bearings,
|
Vector<TurnBearing> pre_turn_bearings,
|
||||||
Vector<util::guidance::TurnBearing> post_turn_bearings)
|
Vector<TurnBearing> post_turn_bearings)
|
||||||
: turn_instructions(std::move(turn_instructions)), lane_data_ids(std::move(lane_data_ids)),
|
: turn_instructions(std::move(turn_instructions)), lane_data_ids(std::move(lane_data_ids)),
|
||||||
entry_class_ids(std::move(entry_class_ids)),
|
entry_class_ids(std::move(entry_class_ids)),
|
||||||
pre_turn_bearings(std::move(pre_turn_bearings)),
|
pre_turn_bearings(std::move(pre_turn_bearings)),
|
||||||
@ -63,15 +63,9 @@ template <storage::Ownership Ownership> class TurnDataContainerImpl
|
|||||||
|
|
||||||
EntryClassID GetEntryClassID(const EdgeID id) const { return entry_class_ids[id]; }
|
EntryClassID GetEntryClassID(const EdgeID id) const { return entry_class_ids[id]; }
|
||||||
|
|
||||||
util::guidance::TurnBearing GetPreTurnBearing(const EdgeID id) const
|
TurnBearing GetPreTurnBearing(const EdgeID id) const { return pre_turn_bearings[id]; }
|
||||||
{
|
|
||||||
return pre_turn_bearings[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
util::guidance::TurnBearing GetPostTurnBearing(const EdgeID id) const
|
TurnBearing GetPostTurnBearing(const EdgeID id) const { return post_turn_bearings[id]; }
|
||||||
{
|
|
||||||
return post_turn_bearings[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
LaneDataID GetLaneDataID(const EdgeID id) const { return lane_data_ids[id]; }
|
LaneDataID GetLaneDataID(const EdgeID id) const { return lane_data_ids[id]; }
|
||||||
|
|
||||||
@ -106,11 +100,11 @@ template <storage::Ownership Ownership> class TurnDataContainerImpl
|
|||||||
const TurnDataContainerImpl &turn_data_container);
|
const TurnDataContainerImpl &turn_data_container);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<guidance::TurnInstruction> turn_instructions;
|
Vector<TurnInstruction> turn_instructions;
|
||||||
Vector<LaneDataID> lane_data_ids;
|
Vector<LaneDataID> lane_data_ids;
|
||||||
Vector<EntryClassID> entry_class_ids;
|
Vector<EntryClassID> entry_class_ids;
|
||||||
Vector<util::guidance::TurnBearing> pre_turn_bearings;
|
Vector<TurnBearing> pre_turn_bearings;
|
||||||
Vector<util::guidance::TurnBearing> post_turn_bearings;
|
Vector<TurnBearing> post_turn_bearings;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
#ifndef OSRM_INCLUDE_UTIL_TURN_BEARING_HPP_
|
|
||||||
#define OSRM_INCLUDE_UTIL_TURN_BEARING_HPP_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
namespace guidance
|
|
||||||
{
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
class TurnBearing
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TurnBearing(const double value = 0);
|
|
||||||
|
|
||||||
double Get() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::uint8_t bearing;
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
} // namespace guidance
|
|
||||||
} // namespace util
|
|
||||||
} // namespace osrm
|
|
||||||
|
|
||||||
#endif /* OSRM_INCLUDE_UTIL_TURN_BEARING_HPP_ */
|
|
@ -7,11 +7,6 @@
|
|||||||
#include "extractor/serialization.hpp"
|
#include "extractor/serialization.hpp"
|
||||||
#include "extractor/suffix_table.hpp"
|
#include "extractor/suffix_table.hpp"
|
||||||
|
|
||||||
#include "guidance/files.hpp"
|
|
||||||
#include "guidance/turn_analysis.hpp"
|
|
||||||
#include "guidance/turn_data_container.hpp"
|
|
||||||
#include "guidance/turn_lane_handler.hpp"
|
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
#include "storage/io.hpp"
|
||||||
|
|
||||||
#include "util/assert.hpp"
|
#include "util/assert.hpp"
|
||||||
@ -19,7 +14,6 @@
|
|||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/exception.hpp"
|
#include "util/exception.hpp"
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
#include "util/integer_range.hpp"
|
#include "util/integer_range.hpp"
|
||||||
#include "util/log.hpp"
|
#include "util/log.hpp"
|
||||||
#include "util/percent.hpp"
|
#include "util/percent.hpp"
|
||||||
@ -75,7 +69,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
|||||||
const std::vector<util::Coordinate> &coordinates,
|
const std::vector<util::Coordinate> &coordinates,
|
||||||
const util::NameTable &name_table,
|
const util::NameTable &name_table,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
extractor::LaneDescriptionMap &lane_description_map)
|
const extractor::LaneDescriptionMap &lane_description_map)
|
||||||
: m_edge_based_node_container(node_data_container), m_number_of_edge_based_nodes(0),
|
: m_edge_based_node_container(node_data_container), m_number_of_edge_based_nodes(0),
|
||||||
m_coordinates(coordinates), m_node_based_graph(std::move(node_based_graph)),
|
m_coordinates(coordinates), m_node_based_graph(std::move(node_based_graph)),
|
||||||
m_barrier_nodes(barrier_nodes), m_traffic_lights(traffic_lights),
|
m_barrier_nodes(barrier_nodes), m_traffic_lights(traffic_lights),
|
||||||
@ -219,8 +213,6 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
|
void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
|
||||||
const std::string &turn_data_filename,
|
|
||||||
const std::string &turn_lane_data_filename,
|
|
||||||
const std::string &turn_weight_penalties_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
const std::string &turn_duration_penalties_filename,
|
const std::string &turn_duration_penalties_filename,
|
||||||
const std::string &turn_penalties_index_filename,
|
const std::string &turn_penalties_index_filename,
|
||||||
@ -249,8 +241,6 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
|
|||||||
|
|
||||||
TIMER_START(generate_edges);
|
TIMER_START(generate_edges);
|
||||||
GenerateEdgeExpandedEdges(scripting_environment,
|
GenerateEdgeExpandedEdges(scripting_environment,
|
||||||
turn_data_filename,
|
|
||||||
turn_lane_data_filename,
|
|
||||||
turn_weight_penalties_filename,
|
turn_weight_penalties_filename,
|
||||||
turn_duration_penalties_filename,
|
turn_duration_penalties_filename,
|
||||||
turn_penalties_index_filename,
|
turn_penalties_index_filename,
|
||||||
@ -406,8 +396,6 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
|
|||||||
/// Actually it also generates turn data and serializes them...
|
/// Actually it also generates turn data and serializes them...
|
||||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||||
ScriptingEnvironment &scripting_environment,
|
ScriptingEnvironment &scripting_environment,
|
||||||
const std::string &turn_data_filename,
|
|
||||||
const std::string &turn_lane_data_filename,
|
|
||||||
const std::string &turn_weight_penalties_filename,
|
const std::string &turn_weight_penalties_filename,
|
||||||
const std::string &turn_duration_penalties_filename,
|
const std::string &turn_duration_penalties_filename,
|
||||||
const std::string &turn_penalties_index_filename,
|
const std::string &turn_penalties_index_filename,
|
||||||
@ -419,15 +407,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
util::Log() << "Generating edge-expanded edges ";
|
util::Log() << "Generating edge-expanded edges ";
|
||||||
|
|
||||||
std::size_t node_based_edge_counter = 0;
|
std::size_t node_based_edge_counter = 0;
|
||||||
restricted_turns_counter = 0;
|
|
||||||
skipped_uturns_counter = 0;
|
|
||||||
skipped_barrier_turns_counter = 0;
|
|
||||||
|
|
||||||
storage::io::FileWriter turn_penalties_index_file(turn_penalties_index_filename,
|
storage::io::FileWriter turn_penalties_index_file(turn_penalties_index_filename,
|
||||||
storage::io::FileWriter::HasNoFingerprint);
|
storage::io::FileWriter::HasNoFingerprint);
|
||||||
|
|
||||||
guidance::TurnDataExternalContainer turn_data_container;
|
|
||||||
|
|
||||||
SuffixTable street_name_suffix_table(scripting_environment);
|
SuffixTable street_name_suffix_table(scripting_environment);
|
||||||
const auto &turn_lanes_data = transformTurnLaneMapIntoArrays(lane_description_map);
|
const auto &turn_lanes_data = transformTurnLaneMapIntoArrays(lane_description_map);
|
||||||
intersection::MergableRoadDetector mergable_road_detector(m_node_based_graph,
|
intersection::MergableRoadDetector mergable_road_detector(m_node_based_graph,
|
||||||
@ -440,34 +423,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
name_table,
|
name_table,
|
||||||
street_name_suffix_table);
|
street_name_suffix_table);
|
||||||
|
|
||||||
// Loop over all turns and generate new set of edges.
|
|
||||||
// Three nested loop look super-linear, but we are dealing with a (kind of)
|
|
||||||
// linear number of turns only.
|
|
||||||
guidance::TurnAnalysis turn_analysis(m_node_based_graph,
|
|
||||||
m_edge_based_node_container,
|
|
||||||
m_coordinates,
|
|
||||||
m_compressed_edge_container,
|
|
||||||
node_restriction_map,
|
|
||||||
m_barrier_nodes,
|
|
||||||
turn_lanes_data,
|
|
||||||
name_table,
|
|
||||||
street_name_suffix_table);
|
|
||||||
|
|
||||||
util::guidance::LaneDataIdMap lane_data_map;
|
|
||||||
guidance::lanes::TurnLaneHandler turn_lane_handler(m_node_based_graph,
|
|
||||||
m_edge_based_node_container,
|
|
||||||
m_coordinates,
|
|
||||||
m_compressed_edge_container,
|
|
||||||
node_restriction_map,
|
|
||||||
m_barrier_nodes,
|
|
||||||
turn_lanes_data,
|
|
||||||
lane_description_map,
|
|
||||||
turn_analysis,
|
|
||||||
lane_data_map);
|
|
||||||
|
|
||||||
bearing_class_by_node_based_node.resize(m_node_based_graph.GetNumberOfNodes(),
|
|
||||||
std::numeric_limits<std::uint32_t>::max());
|
|
||||||
|
|
||||||
// FIXME these need to be tuned in pre-allocated size
|
// FIXME these need to be tuned in pre-allocated size
|
||||||
std::vector<TurnPenalty> turn_weight_penalties;
|
std::vector<TurnPenalty> turn_weight_penalties;
|
||||||
std::vector<TurnPenalty> turn_duration_penalties;
|
std::vector<TurnPenalty> turn_duration_penalties;
|
||||||
@ -484,8 +439,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
// created them in (tbb::filter::serial_in_order creates this guarantee). The order needs to be
|
// created them in (tbb::filter::serial_in_order creates this guarantee). The order needs to be
|
||||||
// maintained because we depend on it later in the processing pipeline.
|
// maintained because we depend on it later in the processing pipeline.
|
||||||
{
|
{
|
||||||
util::UnbufferedLog log;
|
|
||||||
|
|
||||||
const NodeID node_count = m_node_based_graph.GetNumberOfNodes();
|
const NodeID node_count = m_node_based_graph.GetNumberOfNodes();
|
||||||
|
|
||||||
// Because we write TurnIndexBlock data as we go, we'll
|
// Because we write TurnIndexBlock data as we go, we'll
|
||||||
@ -524,18 +477,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
};
|
};
|
||||||
using EdgesPipelineBufferPtr = std::shared_ptr<EdgesPipelineBuffer>;
|
using EdgesPipelineBufferPtr = std::shared_ptr<EdgesPipelineBuffer>;
|
||||||
|
|
||||||
struct TurnsPipelineBuffer
|
|
||||||
{
|
|
||||||
std::size_t nodes_processed = 0;
|
|
||||||
|
|
||||||
std::vector<guidance::TurnData> continuous_turn_data; // populate answers from guidance
|
|
||||||
std::vector<guidance::TurnData> delayed_turn_data; // populate answers from guidance
|
|
||||||
};
|
|
||||||
using TurnsPipelineBufferPtr = std::shared_ptr<TurnsPipelineBuffer>;
|
|
||||||
|
|
||||||
// going over all nodes (which form the center of an intersection), we compute all possible
|
// going over all nodes (which form the center of an intersection), we compute all possible
|
||||||
// turns along these intersections.
|
// turns along these intersections.
|
||||||
|
|
||||||
NodeID current_node = 0;
|
NodeID current_node = 0;
|
||||||
|
|
||||||
// Handle intersections in sets of 100. The pipeline below has a serial bottleneck during
|
// Handle intersections in sets of 100. The pipeline below has a serial bottleneck during
|
||||||
@ -764,10 +707,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
const auto turning_off_via_way =
|
const auto turning_off_via_way =
|
||||||
way_restriction_map.IsViaWay(incoming_edge.node, intersection_node);
|
way_restriction_map.IsViaWay(incoming_edge.node, intersection_node);
|
||||||
|
|
||||||
// Save reversed incoming bearing to compute turn angles
|
|
||||||
const auto incoming_bearing =
|
|
||||||
findEdgeBearing(edge_geometries, incoming_edge.edge);
|
|
||||||
|
|
||||||
for (const auto &outgoing_edge : outgoing_edges)
|
for (const auto &outgoing_edge : outgoing_edges)
|
||||||
{
|
{
|
||||||
if (!intersection::isTurnAllowed(m_node_based_graph,
|
if (!intersection::isTurnAllowed(m_node_based_graph,
|
||||||
@ -1006,177 +945,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
return buffer;
|
return buffer;
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
|
||||||
// Guidance stage
|
|
||||||
//
|
|
||||||
tbb::filter_t<tbb::blocked_range<NodeID>, TurnsPipelineBufferPtr> guidance_stage(
|
|
||||||
tbb::filter::parallel, [&](const tbb::blocked_range<NodeID> &intersection_node_range) {
|
|
||||||
|
|
||||||
auto buffer = std::make_shared<TurnsPipelineBuffer>();
|
|
||||||
buffer->nodes_processed = intersection_node_range.size();
|
|
||||||
|
|
||||||
for (auto intersection_node = intersection_node_range.begin(),
|
|
||||||
end = intersection_node_range.end();
|
|
||||||
intersection_node < end;
|
|
||||||
++intersection_node)
|
|
||||||
{
|
|
||||||
// We capture the thread-local work in these objects, then flush
|
|
||||||
// them in a controlled manner at the end of the parallel range
|
|
||||||
const auto &incoming_edges =
|
|
||||||
intersection::getIncomingEdges(m_node_based_graph, intersection_node);
|
|
||||||
const auto &outgoing_edges =
|
|
||||||
intersection::getOutgoingEdges(m_node_based_graph, intersection_node);
|
|
||||||
const auto &edge_geometries_and_merged_edges =
|
|
||||||
intersection::getIntersectionGeometries(m_node_based_graph,
|
|
||||||
m_compressed_edge_container,
|
|
||||||
m_coordinates,
|
|
||||||
mergable_road_detector,
|
|
||||||
intersection_node);
|
|
||||||
const auto &edge_geometries = edge_geometries_and_merged_edges.first;
|
|
||||||
const auto &merged_edge_ids = edge_geometries_and_merged_edges.second;
|
|
||||||
|
|
||||||
// all nodes in the graph are connected in both directions. We check all
|
|
||||||
// outgoing nodes to find the incoming edge. This is a larger search overhead,
|
|
||||||
// but the cost we need to pay to generate edges here is worth the additional
|
|
||||||
// search overhead.
|
|
||||||
//
|
|
||||||
// a -> b <-> c
|
|
||||||
// |
|
|
||||||
// v
|
|
||||||
// d
|
|
||||||
//
|
|
||||||
// will have:
|
|
||||||
// a: b,rev=0
|
|
||||||
// b: a,rev=1 c,rev=0 d,rev=0
|
|
||||||
// c: b,rev=0
|
|
||||||
//
|
|
||||||
// From the flags alone, we cannot determine which nodes are connected to
|
|
||||||
// `b` by an outgoing edge. Therefore, we have to search all connected edges for
|
|
||||||
// edges entering `b`
|
|
||||||
|
|
||||||
for (const auto &incoming_edge : incoming_edges)
|
|
||||||
{
|
|
||||||
const auto intersection_view =
|
|
||||||
convertToIntersectionView(m_node_based_graph,
|
|
||||||
m_edge_based_node_container,
|
|
||||||
node_restriction_map,
|
|
||||||
m_barrier_nodes,
|
|
||||||
edge_geometries,
|
|
||||||
turn_lanes_data,
|
|
||||||
incoming_edge,
|
|
||||||
outgoing_edges,
|
|
||||||
merged_edge_ids);
|
|
||||||
|
|
||||||
auto intersection = turn_analysis.AssignTurnTypes(
|
|
||||||
incoming_edge.node, incoming_edge.edge, intersection_view);
|
|
||||||
|
|
||||||
OSRM_ASSERT(intersection.valid(), m_coordinates[intersection_node]);
|
|
||||||
intersection = turn_lane_handler.assignTurnLanes(
|
|
||||||
incoming_edge.node, incoming_edge.edge, std::move(intersection));
|
|
||||||
|
|
||||||
// the entry class depends on the turn, so we have to classify the
|
|
||||||
// interesction for every edge
|
|
||||||
const auto turn_classification =
|
|
||||||
classifyIntersection(intersection, m_coordinates[intersection_node]);
|
|
||||||
|
|
||||||
const auto entry_class_id =
|
|
||||||
entry_class_hash.ConcurrentFindOrAdd(turn_classification.first);
|
|
||||||
|
|
||||||
const auto bearing_class_id =
|
|
||||||
bearing_class_hash.ConcurrentFindOrAdd(turn_classification.second);
|
|
||||||
|
|
||||||
// Note - this is strictly speaking not thread safe, but we know we
|
|
||||||
// should never be touching the same element twice, so we should
|
|
||||||
// be fine.
|
|
||||||
bearing_class_by_node_based_node[intersection_node] = bearing_class_id;
|
|
||||||
|
|
||||||
// check if we are turning off a via way
|
|
||||||
const auto turning_off_via_way =
|
|
||||||
way_restriction_map.IsViaWay(incoming_edge.node, intersection_node);
|
|
||||||
|
|
||||||
for (const auto &outgoing_edge : outgoing_edges)
|
|
||||||
{
|
|
||||||
if (!intersection::isTurnAllowed(m_node_based_graph,
|
|
||||||
m_edge_based_node_container,
|
|
||||||
node_restriction_map,
|
|
||||||
m_barrier_nodes,
|
|
||||||
edge_geometries,
|
|
||||||
turn_lanes_data,
|
|
||||||
incoming_edge,
|
|
||||||
outgoing_edge))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto turn =
|
|
||||||
std::find_if(intersection.begin(),
|
|
||||||
intersection.end(),
|
|
||||||
[edge = outgoing_edge.edge](const auto &road) {
|
|
||||||
return road.eid == edge;
|
|
||||||
});
|
|
||||||
|
|
||||||
OSRM_ASSERT(turn != intersection.end(),
|
|
||||||
m_coordinates[intersection_node]);
|
|
||||||
|
|
||||||
buffer->continuous_turn_data.push_back(guidance::TurnData{
|
|
||||||
turn->instruction,
|
|
||||||
turn->lane_data_id,
|
|
||||||
entry_class_id,
|
|
||||||
util::guidance::TurnBearing(intersection[0].bearing),
|
|
||||||
util::guidance::TurnBearing(turn->bearing)});
|
|
||||||
|
|
||||||
// when turning off a a via-way turn restriction, we need to not only
|
|
||||||
// handle the normal edges for the way, but also add turns for every
|
|
||||||
// duplicated node. This process is integrated here to avoid doing the
|
|
||||||
// turn analysis multiple times.
|
|
||||||
if (turning_off_via_way)
|
|
||||||
{
|
|
||||||
const auto duplicated_nodes = way_restriction_map.DuplicatedNodeIDs(
|
|
||||||
incoming_edge.node, intersection_node);
|
|
||||||
|
|
||||||
// next to the normal restrictions tracked in `entry_allowed`, via
|
|
||||||
// ways might introduce additional restrictions. These are handled
|
|
||||||
// here when turning off a via-way
|
|
||||||
for (auto duplicated_node_id : duplicated_nodes)
|
|
||||||
{
|
|
||||||
auto const node_at_end_of_turn =
|
|
||||||
m_node_based_graph.GetTarget(outgoing_edge.edge);
|
|
||||||
|
|
||||||
const auto is_way_restricted = way_restriction_map.IsRestricted(
|
|
||||||
duplicated_node_id, node_at_end_of_turn);
|
|
||||||
|
|
||||||
if (is_way_restricted)
|
|
||||||
{
|
|
||||||
auto const restriction = way_restriction_map.GetRestriction(
|
|
||||||
duplicated_node_id, node_at_end_of_turn);
|
|
||||||
|
|
||||||
if (restriction.condition.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
buffer->delayed_turn_data.push_back(guidance::TurnData{
|
|
||||||
turn->instruction,
|
|
||||||
turn->lane_data_id,
|
|
||||||
entry_class_id,
|
|
||||||
util::guidance::TurnBearing(intersection[0].bearing),
|
|
||||||
util::guidance::TurnBearing(turn->bearing)});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer->delayed_turn_data.push_back(guidance::TurnData{
|
|
||||||
turn->instruction,
|
|
||||||
turn->lane_data_id,
|
|
||||||
entry_class_id,
|
|
||||||
util::guidance::TurnBearing(intersection[0].bearing),
|
|
||||||
util::guidance::TurnBearing(turn->bearing)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Last part of the pipeline puts all the calculated data into the serial buffers
|
// Last part of the pipeline puts all the calculated data into the serial buffers
|
||||||
|
util::UnbufferedLog log;
|
||||||
util::Percent routing_progress(log, node_count);
|
util::Percent routing_progress(log, node_count);
|
||||||
std::vector<EdgeWithData> delayed_data;
|
std::vector<EdgeWithData> delayed_data;
|
||||||
tbb::filter_t<EdgesPipelineBufferPtr, void> output_stage(
|
tbb::filter_t<EdgesPipelineBufferPtr, void> output_stage(
|
||||||
@ -1206,51 +976,16 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
delayed_data.end(), buffer->delayed_data.begin(), buffer->delayed_data.end());
|
delayed_data.end(), buffer->delayed_data.begin(), buffer->delayed_data.end());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Last part of the pipeline puts all the calculated data into the serial buffers
|
|
||||||
util::Percent guidance_progress(log, node_count);
|
|
||||||
std::vector<guidance::TurnData> delayed_turn_data;
|
|
||||||
|
|
||||||
tbb::filter_t<TurnsPipelineBufferPtr, void> guidance_output_stage(
|
|
||||||
tbb::filter::serial_in_order, [&](auto buffer) {
|
|
||||||
|
|
||||||
guidance_progress.PrintAddition(buffer->nodes_processed);
|
|
||||||
|
|
||||||
// Guidance data
|
|
||||||
std::for_each(buffer->continuous_turn_data.begin(),
|
|
||||||
buffer->continuous_turn_data.end(),
|
|
||||||
[&turn_data_container](const auto &turn_data) {
|
|
||||||
turn_data_container.push_back(turn_data);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Copy via-way restrictions delayed data
|
|
||||||
delayed_turn_data.insert(delayed_turn_data.end(),
|
|
||||||
buffer->delayed_turn_data.begin(),
|
|
||||||
buffer->delayed_turn_data.end());
|
|
||||||
});
|
|
||||||
|
|
||||||
// Now, execute the pipeline. The value of "5" here was chosen by experimentation
|
// Now, execute the pipeline. The value of "5" here was chosen by experimentation
|
||||||
// on a 16-CPU machine and seemed to give the best performance. This value needs
|
// on a 16-CPU machine and seemed to give the best performance. This value needs
|
||||||
// to be balanced with the GRAINSIZE above - ideally, the pipeline puts as much work
|
// to be balanced with the GRAINSIZE above - ideally, the pipeline puts as much work
|
||||||
// as possible in the `intersection_handler` step so that those parallel workers don't
|
// as possible in the `intersection_handler` step so that those parallel workers don't
|
||||||
// get blocked too much by the slower (io-performing) `buffer_storage`
|
// get blocked too much by the slower (io-performing) `buffer_storage`
|
||||||
util::Log() << "Generating edge-expanded edges ";
|
|
||||||
current_node = 0;
|
|
||||||
tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 5,
|
tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 5,
|
||||||
generator_stage & processor_stage & output_stage);
|
generator_stage & processor_stage & output_stage);
|
||||||
log << std::endl;
|
|
||||||
|
|
||||||
util::Log() << "Generating guidance turns ";
|
|
||||||
current_node = 0;
|
|
||||||
tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 5,
|
|
||||||
generator_stage & guidance_stage & guidance_output_stage);
|
|
||||||
|
|
||||||
// NOTE: buffer.delayed_data and buffer.delayed_turn_data have the same index
|
// NOTE: buffer.delayed_data and buffer.delayed_turn_data have the same index
|
||||||
std::for_each(delayed_data.begin(), delayed_data.end(), transfer_data);
|
std::for_each(delayed_data.begin(), delayed_data.end(), transfer_data);
|
||||||
std::for_each(delayed_turn_data.begin(),
|
|
||||||
delayed_turn_data.end(),
|
|
||||||
[&turn_data_container](const auto &turn_data) {
|
|
||||||
turn_data_container.push_back(turn_data);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Flush the turn_indexes_write_buffer if it's not empty
|
// Flush the turn_indexes_write_buffer if it's not empty
|
||||||
if (!turn_indexes_write_buffer.empty())
|
if (!turn_indexes_write_buffer.empty())
|
||||||
@ -1261,7 +996,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Log() << "Reunmbering turns";
|
util::Log() << "done.";
|
||||||
|
util::Log() << "Renumbering turns";
|
||||||
// Now, update the turn_id property on every EdgeBasedEdge - it will equal the position in the
|
// Now, update the turn_id property on every EdgeBasedEdge - it will equal the position in the
|
||||||
// m_edge_based_edge_list array for each object.
|
// m_edge_based_edge_list array for each object.
|
||||||
tbb::parallel_for(tbb::blocked_range<NodeID>(0, m_edge_based_edge_list.size()),
|
tbb::parallel_for(tbb::blocked_range<NodeID>(0, m_edge_based_edge_list.size()),
|
||||||
@ -1272,7 +1008,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// re-hash conditionals to ocnnect to their respective edge-based edges. Due to the ordering, we
|
// re-hash conditionals to connect to their respective edge-based edges. Due to the ordering, we
|
||||||
// do not really have a choice but to index the conditional penalties and walk over all
|
// do not really have a choice but to index the conditional penalties and walk over all
|
||||||
// edge-based-edges to find the ID of the edge
|
// edge-based-edges to find the ID of the edge
|
||||||
auto const indexed_conditionals = IndexConditionals(std::move(conditionals));
|
auto const indexed_conditionals = IndexConditionals(std::move(conditionals));
|
||||||
@ -1299,34 +1035,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
storage::serialization::write(writer, turn_duration_penalties);
|
storage::serialization::write(writer, turn_duration_penalties);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::Log() << "Created " << entry_class_hash.data.size() << " entry classes and "
|
|
||||||
<< bearing_class_hash.data.size() << " Bearing Classes";
|
|
||||||
|
|
||||||
util::Log() << "Writing Turn Lane Data to File...";
|
|
||||||
{
|
|
||||||
storage::io::FileWriter writer(turn_lane_data_filename,
|
|
||||||
storage::io::FileWriter::GenerateFingerprint);
|
|
||||||
|
|
||||||
std::vector<util::guidance::LaneTupleIdPair> lane_data(lane_data_map.data.size());
|
|
||||||
// extract lane data sorted by ID
|
|
||||||
for (auto itr : lane_data_map.data)
|
|
||||||
lane_data[itr.second] = itr.first;
|
|
||||||
|
|
||||||
storage::serialization::write(writer, lane_data);
|
|
||||||
}
|
|
||||||
util::Log() << "done.";
|
|
||||||
|
|
||||||
guidance::files::writeTurnData(turn_data_filename, turn_data_container);
|
|
||||||
|
|
||||||
util::Log() << "Generated " << m_edge_based_node_segments.size() << " edge based node segments";
|
util::Log() << "Generated " << m_edge_based_node_segments.size() << " edge based node segments";
|
||||||
util::Log() << "Node-based graph contains " << node_based_edge_counter << " edges";
|
util::Log() << "Node-based graph contains " << node_based_edge_counter << " edges";
|
||||||
util::Log() << "Edge-expanded graph ...";
|
util::Log() << "Edge-expanded graph ...";
|
||||||
util::Log() << " contains " << m_edge_based_edge_list.size() << " edges";
|
util::Log() << " contains " << m_edge_based_edge_list.size() << " edges";
|
||||||
util::Log() << " skips " << restricted_turns_counter << " turns, "
|
|
||||||
"defined by "
|
|
||||||
<< node_restriction_map.Size() << " restrictions";
|
|
||||||
util::Log() << " skips " << skipped_uturns_counter << " U turns";
|
|
||||||
util::Log() << " skips " << skipped_barrier_turns_counter << " turns over barriers";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ConditionalTurnPenalty>
|
std::vector<ConditionalTurnPenalty>
|
||||||
@ -1354,37 +1066,5 @@ EdgeBasedGraphFactory::IndexConditionals(std::vector<Conditional> &&conditionals
|
|||||||
return indexed_restrictions;
|
return indexed_restrictions;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<util::guidance::BearingClass> EdgeBasedGraphFactory::GetBearingClasses() const
|
|
||||||
{
|
|
||||||
std::vector<util::guidance::BearingClass> result(bearing_class_hash.data.size());
|
|
||||||
for (const auto &pair : bearing_class_hash.data)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(pair.second < result.size());
|
|
||||||
result[pair.second] = pair.first;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<BearingClassID> &EdgeBasedGraphFactory::GetBearingClassIds() const
|
|
||||||
{
|
|
||||||
return bearing_class_by_node_based_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<BearingClassID> &EdgeBasedGraphFactory::GetBearingClassIds()
|
|
||||||
{
|
|
||||||
return bearing_class_by_node_based_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<util::guidance::EntryClass> EdgeBasedGraphFactory::GetEntryClasses() const
|
|
||||||
{
|
|
||||||
std::vector<util::guidance::EntryClass> result(entry_class_hash.data.size());
|
|
||||||
for (const auto &pair : entry_class_hash.data)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(pair.second < result.size());
|
|
||||||
result[pair.second] = pair.first;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -13,7 +13,10 @@
|
|||||||
#include "extractor/restriction_parser.hpp"
|
#include "extractor/restriction_parser.hpp"
|
||||||
#include "extractor/scripting_environment.hpp"
|
#include "extractor/scripting_environment.hpp"
|
||||||
|
|
||||||
|
#include "guidance/files.hpp"
|
||||||
|
#include "guidance/guidance_processing.hpp"
|
||||||
#include "guidance/segregated_intersection_classification.hpp"
|
#include "guidance/segregated_intersection_classification.hpp"
|
||||||
|
#include "guidance/turn_data_container.hpp"
|
||||||
|
|
||||||
#include "storage/io.hpp"
|
#include "storage/io.hpp"
|
||||||
|
|
||||||
@ -274,6 +277,8 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
|
|
||||||
const auto number_of_node_based_nodes = node_based_graph.GetNumberOfNodes();
|
const auto number_of_node_based_nodes = node_based_graph.GetNumberOfNodes();
|
||||||
|
|
||||||
|
const util::NameTable name_table(config.GetPath(".osrm.names").string());
|
||||||
|
|
||||||
const auto number_of_edge_based_nodes =
|
const auto number_of_edge_based_nodes =
|
||||||
BuildEdgeExpandedGraph(node_based_graph,
|
BuildEdgeExpandedGraph(node_based_graph,
|
||||||
coordinates,
|
coordinates,
|
||||||
@ -283,14 +288,25 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
|||||||
turn_restrictions,
|
turn_restrictions,
|
||||||
conditional_turn_restrictions,
|
conditional_turn_restrictions,
|
||||||
segregated_edges,
|
segregated_edges,
|
||||||
|
name_table,
|
||||||
turn_lane_map,
|
turn_lane_map,
|
||||||
scripting_environment,
|
scripting_environment,
|
||||||
edge_based_nodes_container,
|
edge_based_nodes_container,
|
||||||
edge_based_node_segments,
|
edge_based_node_segments,
|
||||||
node_is_startpoint,
|
node_is_startpoint,
|
||||||
edge_based_node_weights,
|
edge_based_node_weights,
|
||||||
edge_based_edge_list,
|
edge_based_edge_list);
|
||||||
config.GetPath(".osrm.icd").string());
|
|
||||||
|
ProcessGuidanceTurns(node_based_graph,
|
||||||
|
edge_based_nodes_container,
|
||||||
|
coordinates,
|
||||||
|
node_based_graph_factory.GetCompressedEdges(),
|
||||||
|
barrier_nodes,
|
||||||
|
turn_restrictions,
|
||||||
|
conditional_turn_restrictions,
|
||||||
|
name_table,
|
||||||
|
std::move(turn_lane_map),
|
||||||
|
scripting_environment);
|
||||||
|
|
||||||
TIMER_STOP(expansion);
|
TIMER_STOP(expansion);
|
||||||
|
|
||||||
@ -672,8 +688,8 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
|||||||
const std::vector<TurnRestriction> &turn_restrictions,
|
const std::vector<TurnRestriction> &turn_restrictions,
|
||||||
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||||
const std::unordered_set<EdgeID> &segregated_edges,
|
const std::unordered_set<EdgeID> &segregated_edges,
|
||||||
// might have to be updated to add new lane combinations
|
const util::NameTable &name_table,
|
||||||
LaneDescriptionMap &turn_lane_map,
|
const LaneDescriptionMap &turn_lane_map,
|
||||||
// for calculating turn penalties
|
// for calculating turn penalties
|
||||||
ScriptingEnvironment &scripting_environment,
|
ScriptingEnvironment &scripting_environment,
|
||||||
// output data
|
// output data
|
||||||
@ -681,11 +697,8 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
|||||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||||
std::vector<bool> &node_is_startpoint,
|
std::vector<bool> &node_is_startpoint,
|
||||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list)
|
||||||
const std::string &intersection_class_output_file)
|
|
||||||
{
|
{
|
||||||
util::NameTable name_table(config.GetPath(".osrm.names").string());
|
|
||||||
|
|
||||||
EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph,
|
EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph,
|
||||||
edge_based_nodes_container,
|
edge_based_nodes_container,
|
||||||
compressed_edge_container,
|
compressed_edge_container,
|
||||||
@ -712,10 +725,7 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
|||||||
WayRestrictionMap via_way_restriction_map(conditional_turn_restrictions);
|
WayRestrictionMap via_way_restriction_map(conditional_turn_restrictions);
|
||||||
ConditionalRestrictionMap conditional_node_restriction_map(conditional_node_restrictions,
|
ConditionalRestrictionMap conditional_node_restriction_map(conditional_node_restrictions,
|
||||||
IndexNodeByFromAndVia());
|
IndexNodeByFromAndVia());
|
||||||
|
|
||||||
edge_based_graph_factory.Run(scripting_environment,
|
edge_based_graph_factory.Run(scripting_environment,
|
||||||
config.GetPath(".osrm.edges").string(),
|
|
||||||
config.GetPath(".osrm.tld").string(),
|
|
||||||
config.GetPath(".osrm.turn_weight_penalties").string(),
|
config.GetPath(".osrm.turn_weight_penalties").string(),
|
||||||
config.GetPath(".osrm.turn_duration_penalties").string(),
|
config.GetPath(".osrm.turn_duration_penalties").string(),
|
||||||
config.GetPath(".osrm.turn_penalties_index").string(),
|
config.GetPath(".osrm.turn_penalties_index").string(),
|
||||||
@ -729,30 +739,11 @@ EdgeID Extractor::BuildEdgeExpandedGraph(
|
|||||||
|
|
||||||
const auto number_of_edge_based_nodes = create_edge_based_edges();
|
const auto number_of_edge_based_nodes = create_edge_based_edges();
|
||||||
|
|
||||||
{
|
|
||||||
std::vector<std::uint32_t> turn_lane_offsets;
|
|
||||||
std::vector<TurnLaneType::Mask> turn_lane_masks;
|
|
||||||
std::tie(turn_lane_offsets, turn_lane_masks) =
|
|
||||||
transformTurnLaneMapIntoArrays(turn_lane_map);
|
|
||||||
files::writeTurnLaneDescriptions(
|
|
||||||
config.GetPath(".osrm.tls"), turn_lane_offsets, turn_lane_masks);
|
|
||||||
}
|
|
||||||
|
|
||||||
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
|
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
|
||||||
edge_based_graph_factory.GetEdgeBasedNodeSegments(edge_based_node_segments);
|
edge_based_graph_factory.GetEdgeBasedNodeSegments(edge_based_node_segments);
|
||||||
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
|
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
|
||||||
edge_based_graph_factory.GetEdgeBasedNodeWeights(edge_based_node_weights);
|
edge_based_graph_factory.GetEdgeBasedNodeWeights(edge_based_node_weights);
|
||||||
|
|
||||||
util::Log() << "Writing Intersection Classification Data";
|
|
||||||
TIMER_START(write_intersections);
|
|
||||||
files::writeIntersections(
|
|
||||||
intersection_class_output_file,
|
|
||||||
IntersectionBearingsContainer{edge_based_graph_factory.GetBearingClassIds(),
|
|
||||||
edge_based_graph_factory.GetBearingClasses()},
|
|
||||||
edge_based_graph_factory.GetEntryClasses());
|
|
||||||
TIMER_STOP(write_intersections);
|
|
||||||
util::Log() << "ok, after " << TIMER_SEC(write_intersections) << "s";
|
|
||||||
|
|
||||||
return number_of_edge_based_nodes;
|
return number_of_edge_based_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,5 +835,101 @@ void Extractor::WriteCompressedNodeBasedGraph(const std::string &path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Map> auto convertIDMapToVector(const Map &map)
|
||||||
|
{
|
||||||
|
std::vector<typename Map::key_type> result(map.size());
|
||||||
|
for (const auto &pair : map)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(pair.second < map.size());
|
||||||
|
result[pair.second] = pair.first;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Extractor::ProcessGuidanceTurns(
|
||||||
|
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
|
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 std::vector<TurnRestriction> &turn_restrictions,
|
||||||
|
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||||
|
const util::NameTable &name_table,
|
||||||
|
LaneDescriptionMap lane_description_map,
|
||||||
|
ScriptingEnvironment &scripting_environment)
|
||||||
|
{
|
||||||
|
// Output data
|
||||||
|
osrm::guidance::TurnDataExternalContainer turn_data_container;
|
||||||
|
util::guidance::LaneDataIdMap lane_data_map;
|
||||||
|
osrm::guidance::BearingClassesVector bearing_class_by_node_based_node;
|
||||||
|
osrm::guidance::BearingClassesMap bearing_class_hash;
|
||||||
|
osrm::guidance::EntryClassesMap entry_class_hash;
|
||||||
|
|
||||||
|
TIMER_START(turn_annotations);
|
||||||
|
|
||||||
|
{
|
||||||
|
SuffixTable street_name_suffix_table(scripting_environment);
|
||||||
|
const auto &turn_lanes_data = transformTurnLaneMapIntoArrays(lane_description_map);
|
||||||
|
|
||||||
|
std::vector<TurnRestriction> node_restrictions;
|
||||||
|
for (auto const &t : turn_restrictions)
|
||||||
|
if (t.Type() == RestrictionType::NODE_RESTRICTION)
|
||||||
|
node_restrictions.push_back(t);
|
||||||
|
|
||||||
|
RestrictionMap node_restriction_map(node_restrictions, IndexNodeByFromAndVia());
|
||||||
|
WayRestrictionMap way_restriction_map(conditional_turn_restrictions);
|
||||||
|
|
||||||
|
osrm::guidance::annotateTurns(node_based_graph,
|
||||||
|
edge_based_node_container,
|
||||||
|
node_coordinates,
|
||||||
|
compressed_edge_container,
|
||||||
|
barrier_nodes,
|
||||||
|
node_restriction_map,
|
||||||
|
way_restriction_map,
|
||||||
|
name_table,
|
||||||
|
street_name_suffix_table,
|
||||||
|
turn_lanes_data,
|
||||||
|
lane_description_map,
|
||||||
|
lane_data_map,
|
||||||
|
turn_data_container,
|
||||||
|
bearing_class_by_node_based_node,
|
||||||
|
bearing_class_hash,
|
||||||
|
entry_class_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMER_STOP(turn_annotations);
|
||||||
|
util::Log() << "Guidance turn annotations took " << TIMER_SEC(turn_annotations) << "s";
|
||||||
|
|
||||||
|
util::Log() << "Writing Intersection Classification Data";
|
||||||
|
TIMER_START(write_intersections);
|
||||||
|
files::writeIntersections(
|
||||||
|
config.GetPath(".osrm.icd").string(),
|
||||||
|
IntersectionBearingsContainer{bearing_class_by_node_based_node,
|
||||||
|
convertIDMapToVector(bearing_class_hash.data)},
|
||||||
|
convertIDMapToVector(entry_class_hash.data));
|
||||||
|
TIMER_STOP(write_intersections);
|
||||||
|
util::Log() << "ok, after " << TIMER_SEC(write_intersections) << "s";
|
||||||
|
|
||||||
|
util::Log() << "Writing Turns and Lane Data...";
|
||||||
|
TIMER_START(write_guidance_data);
|
||||||
|
storage::io::FileWriter writer(config.GetPath(".osrm.tld").string(),
|
||||||
|
storage::io::FileWriter::GenerateFingerprint);
|
||||||
|
storage::serialization::write(writer, convertIDMapToVector(lane_data_map.data));
|
||||||
|
|
||||||
|
{ // Turn lanes handler modifies lane_description_map, so another transformation is needed
|
||||||
|
std::vector<std::uint32_t> turn_lane_offsets;
|
||||||
|
std::vector<TurnLaneType::Mask> turn_lane_masks;
|
||||||
|
std::tie(turn_lane_offsets, turn_lane_masks) =
|
||||||
|
transformTurnLaneMapIntoArrays(lane_description_map);
|
||||||
|
files::writeTurnLaneDescriptions(
|
||||||
|
config.GetPath(".osrm.tls"), turn_lane_offsets, turn_lane_masks);
|
||||||
|
}
|
||||||
|
|
||||||
|
osrm::guidance::files::writeTurnData(config.GetPath(".osrm.edges").string(),
|
||||||
|
turn_data_container);
|
||||||
|
TIMER_STOP(write_guidance_data);
|
||||||
|
util::Log() << "ok, after " << TIMER_SEC(write_guidance_data) << "s";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -1174,6 +1174,6 @@ CoordinateExtractor::RegressionLine(const std::vector<util::Coordinate> &coordin
|
|||||||
return {coord_between_front, coord_between_back};
|
return {coord_between_front, coord_between_back};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace intersection
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -615,6 +615,6 @@ bool MergableRoadDetector::IsLinkRoad(const NodeID intersection_node,
|
|||||||
.annotation_data));
|
.annotation_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace intersection
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
330
src/guidance/guidance_processing.cpp
Normal file
330
src/guidance/guidance_processing.cpp
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
#include "guidance/guidance_processing.hpp"
|
||||||
|
#include "guidance/turn_analysis.hpp"
|
||||||
|
#include "guidance/turn_lane_handler.hpp"
|
||||||
|
|
||||||
|
#include "extractor/intersection/intersection_analysis.hpp"
|
||||||
|
|
||||||
|
#include "util/assert.hpp"
|
||||||
|
#include "util/percent.hpp"
|
||||||
|
|
||||||
|
#include <tbb/blocked_range.h>
|
||||||
|
#include <tbb/pipeline.h>
|
||||||
|
#include <tbb/task_scheduler_init.h>
|
||||||
|
|
||||||
|
namespace osrm
|
||||||
|
{
|
||||||
|
namespace guidance
|
||||||
|
{
|
||||||
|
|
||||||
|
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::RestrictionMap &node_restriction_map,
|
||||||
|
const extractor::WayRestrictionMap &way_restriction_map,
|
||||||
|
const util::NameTable &name_table,
|
||||||
|
const extractor::SuffixTable &suffix_table,
|
||||||
|
const extractor::TurnLanesIndexedArray &turn_lanes_data,
|
||||||
|
extractor::LaneDescriptionMap &lane_description_map,
|
||||||
|
util::guidance::LaneDataIdMap &lane_data_map,
|
||||||
|
guidance::TurnDataExternalContainer &turn_data_container,
|
||||||
|
BearingClassesVector &bearing_class_by_node_based_node,
|
||||||
|
BearingClassesMap &bearing_class_hash,
|
||||||
|
EntryClassesMap &entry_class_hash)
|
||||||
|
{
|
||||||
|
util::Log() << "Generating guidance turns ";
|
||||||
|
|
||||||
|
extractor::intersection::MergableRoadDetector mergable_road_detector(node_based_graph,
|
||||||
|
edge_based_node_container,
|
||||||
|
node_coordinates,
|
||||||
|
compressed_edge_container,
|
||||||
|
node_restriction_map,
|
||||||
|
barrier_nodes,
|
||||||
|
turn_lanes_data,
|
||||||
|
name_table,
|
||||||
|
suffix_table);
|
||||||
|
|
||||||
|
guidance::TurnAnalysis turn_analysis(node_based_graph,
|
||||||
|
edge_based_node_container,
|
||||||
|
node_coordinates,
|
||||||
|
compressed_edge_container,
|
||||||
|
node_restriction_map,
|
||||||
|
barrier_nodes,
|
||||||
|
turn_lanes_data,
|
||||||
|
name_table,
|
||||||
|
suffix_table);
|
||||||
|
|
||||||
|
guidance::lanes::TurnLaneHandler turn_lane_handler(node_based_graph,
|
||||||
|
edge_based_node_container,
|
||||||
|
node_coordinates,
|
||||||
|
compressed_edge_container,
|
||||||
|
node_restriction_map,
|
||||||
|
barrier_nodes,
|
||||||
|
turn_lanes_data,
|
||||||
|
lane_description_map,
|
||||||
|
turn_analysis,
|
||||||
|
lane_data_map);
|
||||||
|
|
||||||
|
bearing_class_by_node_based_node.resize(node_based_graph.GetNumberOfNodes(),
|
||||||
|
std::numeric_limits<std::uint32_t>::max());
|
||||||
|
|
||||||
|
struct TurnsPipelineBuffer
|
||||||
|
{
|
||||||
|
std::size_t nodes_processed = 0;
|
||||||
|
|
||||||
|
std::vector<guidance::TurnData> continuous_turn_data; // populate answers from guidance
|
||||||
|
std::vector<guidance::TurnData> delayed_turn_data; // populate answers from guidance
|
||||||
|
};
|
||||||
|
using TurnsPipelineBufferPtr = std::shared_ptr<TurnsPipelineBuffer>;
|
||||||
|
|
||||||
|
// going over all nodes (which form the center of an intersection), we compute all
|
||||||
|
// possible turns along these intersections.
|
||||||
|
{
|
||||||
|
const NodeID node_count = node_based_graph.GetNumberOfNodes();
|
||||||
|
NodeID current_node = 0;
|
||||||
|
|
||||||
|
// Handle intersections in sets of 100. The pipeline below has a serial bottleneck
|
||||||
|
// during the writing phase, so we want to make the parallel workers do more work
|
||||||
|
// to give the serial final stage time to complete its tasks.
|
||||||
|
const constexpr unsigned GRAINSIZE = 100;
|
||||||
|
|
||||||
|
// First part of the pipeline generates iterator ranges of IDs in sets of GRAINSIZE
|
||||||
|
tbb::filter_t<void, tbb::blocked_range<NodeID>> generator_stage(
|
||||||
|
tbb::filter::serial_in_order, [&](tbb::flow_control &fc) {
|
||||||
|
if (current_node < node_count)
|
||||||
|
{
|
||||||
|
auto next_node = std::min(current_node + GRAINSIZE, node_count);
|
||||||
|
auto result = tbb::blocked_range<NodeID>(current_node, next_node);
|
||||||
|
current_node = next_node;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fc.stop();
|
||||||
|
return tbb::blocked_range<NodeID>(node_count, node_count);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// Guidance stage
|
||||||
|
//
|
||||||
|
tbb::filter_t<tbb::blocked_range<NodeID>, TurnsPipelineBufferPtr> guidance_stage(
|
||||||
|
tbb::filter::parallel, [&](const tbb::blocked_range<NodeID> &intersection_node_range) {
|
||||||
|
|
||||||
|
auto buffer = std::make_shared<TurnsPipelineBuffer>();
|
||||||
|
buffer->nodes_processed = intersection_node_range.size();
|
||||||
|
|
||||||
|
for (auto intersection_node = intersection_node_range.begin(),
|
||||||
|
end = intersection_node_range.end();
|
||||||
|
intersection_node < end;
|
||||||
|
++intersection_node)
|
||||||
|
{
|
||||||
|
// We capture the thread-local work in these objects, then flush
|
||||||
|
// them in a controlled manner at the end of the parallel range
|
||||||
|
const auto &incoming_edges = extractor::intersection::getIncomingEdges(
|
||||||
|
node_based_graph, intersection_node);
|
||||||
|
const auto &outgoing_edges = extractor::intersection::getOutgoingEdges(
|
||||||
|
node_based_graph, intersection_node);
|
||||||
|
const auto &edge_geometries_and_merged_edges =
|
||||||
|
extractor::intersection::getIntersectionGeometries(
|
||||||
|
node_based_graph,
|
||||||
|
compressed_edge_container,
|
||||||
|
node_coordinates,
|
||||||
|
mergable_road_detector,
|
||||||
|
intersection_node);
|
||||||
|
const auto &edge_geometries = edge_geometries_and_merged_edges.first;
|
||||||
|
const auto &merged_edge_ids = edge_geometries_and_merged_edges.second;
|
||||||
|
|
||||||
|
// all nodes in the graph are connected in both directions. We check all
|
||||||
|
// outgoing nodes to find the incoming edge. This is a larger search overhead,
|
||||||
|
// but the cost we need to pay to generate edges here is worth the additional
|
||||||
|
// search overhead.
|
||||||
|
//
|
||||||
|
// a -> b <-> c
|
||||||
|
// |
|
||||||
|
// v
|
||||||
|
// d
|
||||||
|
//
|
||||||
|
// will have:
|
||||||
|
// a: b,rev=0
|
||||||
|
// b: a,rev=1 c,rev=0 d,rev=0
|
||||||
|
// c: b,rev=0
|
||||||
|
//
|
||||||
|
// From the flags alone, we cannot determine which nodes are connected to
|
||||||
|
// `b` by an outgoing edge. Therefore, we have to search all connected edges for
|
||||||
|
// edges entering `b`
|
||||||
|
|
||||||
|
for (const auto &incoming_edge : incoming_edges)
|
||||||
|
{
|
||||||
|
const auto intersection_view =
|
||||||
|
extractor::intersection::convertToIntersectionView(
|
||||||
|
node_based_graph,
|
||||||
|
edge_based_node_container,
|
||||||
|
node_restriction_map,
|
||||||
|
barrier_nodes,
|
||||||
|
edge_geometries,
|
||||||
|
turn_lanes_data,
|
||||||
|
incoming_edge,
|
||||||
|
outgoing_edges,
|
||||||
|
merged_edge_ids);
|
||||||
|
|
||||||
|
auto intersection = turn_analysis.AssignTurnTypes(
|
||||||
|
incoming_edge.node, incoming_edge.edge, intersection_view);
|
||||||
|
|
||||||
|
OSRM_ASSERT(intersection.valid(), node_coordinates[intersection_node]);
|
||||||
|
intersection = turn_lane_handler.assignTurnLanes(
|
||||||
|
incoming_edge.node, incoming_edge.edge, std::move(intersection));
|
||||||
|
|
||||||
|
// the entry class depends on the turn, so we have to classify the
|
||||||
|
// interesction for every edge
|
||||||
|
const auto turn_classification =
|
||||||
|
classifyIntersection(intersection, node_coordinates[intersection_node]);
|
||||||
|
|
||||||
|
const auto entry_class_id =
|
||||||
|
entry_class_hash.ConcurrentFindOrAdd(turn_classification.first);
|
||||||
|
|
||||||
|
const auto bearing_class_id =
|
||||||
|
bearing_class_hash.ConcurrentFindOrAdd(turn_classification.second);
|
||||||
|
|
||||||
|
// Note - this is strictly speaking not thread safe, but we know we
|
||||||
|
// should never be touching the same element twice, so we should
|
||||||
|
// be fine.
|
||||||
|
bearing_class_by_node_based_node[intersection_node] = bearing_class_id;
|
||||||
|
|
||||||
|
// check if we are turning off a via way
|
||||||
|
const auto turning_off_via_way =
|
||||||
|
way_restriction_map.IsViaWay(incoming_edge.node, intersection_node);
|
||||||
|
|
||||||
|
for (const auto &outgoing_edge : outgoing_edges)
|
||||||
|
{
|
||||||
|
auto is_turn_allowed =
|
||||||
|
extractor::intersection::isTurnAllowed(node_based_graph,
|
||||||
|
edge_based_node_container,
|
||||||
|
node_restriction_map,
|
||||||
|
barrier_nodes,
|
||||||
|
edge_geometries,
|
||||||
|
turn_lanes_data,
|
||||||
|
incoming_edge,
|
||||||
|
outgoing_edge);
|
||||||
|
|
||||||
|
if (!is_turn_allowed)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto turn =
|
||||||
|
std::find_if(intersection.begin(),
|
||||||
|
intersection.end(),
|
||||||
|
[edge = outgoing_edge.edge](const auto &road) {
|
||||||
|
return road.eid == edge;
|
||||||
|
});
|
||||||
|
|
||||||
|
OSRM_ASSERT(turn != intersection.end(),
|
||||||
|
node_coordinates[intersection_node]);
|
||||||
|
|
||||||
|
buffer->continuous_turn_data.push_back(
|
||||||
|
guidance::TurnData{turn->instruction,
|
||||||
|
turn->lane_data_id,
|
||||||
|
entry_class_id,
|
||||||
|
guidance::TurnBearing(intersection[0].bearing),
|
||||||
|
guidance::TurnBearing(turn->bearing)});
|
||||||
|
|
||||||
|
// when turning off a a via-way turn restriction, we need to not only
|
||||||
|
// handle the normal edges for the way, but also add turns for every
|
||||||
|
// duplicated node. This process is integrated here to avoid doing the
|
||||||
|
// turn analysis multiple times.
|
||||||
|
if (turning_off_via_way)
|
||||||
|
{
|
||||||
|
const auto duplicated_nodes = way_restriction_map.DuplicatedNodeIDs(
|
||||||
|
incoming_edge.node, intersection_node);
|
||||||
|
|
||||||
|
// next to the normal restrictions tracked in `entry_allowed`, via
|
||||||
|
// ways might introduce additional restrictions. These are handled
|
||||||
|
// here when turning off a via-way
|
||||||
|
for (auto duplicated_node_id : duplicated_nodes)
|
||||||
|
{
|
||||||
|
auto const node_at_end_of_turn =
|
||||||
|
node_based_graph.GetTarget(outgoing_edge.edge);
|
||||||
|
|
||||||
|
const auto is_way_restricted = way_restriction_map.IsRestricted(
|
||||||
|
duplicated_node_id, node_at_end_of_turn);
|
||||||
|
|
||||||
|
if (is_way_restricted)
|
||||||
|
{
|
||||||
|
auto const restriction = way_restriction_map.GetRestriction(
|
||||||
|
duplicated_node_id, node_at_end_of_turn);
|
||||||
|
|
||||||
|
if (restriction.condition.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buffer->delayed_turn_data.push_back(guidance::TurnData{
|
||||||
|
turn->instruction,
|
||||||
|
turn->lane_data_id,
|
||||||
|
entry_class_id,
|
||||||
|
guidance::TurnBearing(intersection[0].bearing),
|
||||||
|
guidance::TurnBearing(turn->bearing)});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer->delayed_turn_data.push_back(guidance::TurnData{
|
||||||
|
turn->instruction,
|
||||||
|
turn->lane_data_id,
|
||||||
|
entry_class_id,
|
||||||
|
guidance::TurnBearing(intersection[0].bearing),
|
||||||
|
guidance::TurnBearing(turn->bearing)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Last part of the pipeline puts all the calculated data into the serial buffers
|
||||||
|
util::UnbufferedLog log;
|
||||||
|
util::Percent guidance_progress(log, node_count);
|
||||||
|
std::vector<guidance::TurnData> delayed_turn_data;
|
||||||
|
|
||||||
|
tbb::filter_t<TurnsPipelineBufferPtr, void> guidance_output_stage(
|
||||||
|
tbb::filter::serial_in_order, [&](auto buffer) {
|
||||||
|
|
||||||
|
guidance_progress.PrintAddition(buffer->nodes_processed);
|
||||||
|
|
||||||
|
// Guidance data
|
||||||
|
std::for_each(buffer->continuous_turn_data.begin(),
|
||||||
|
buffer->continuous_turn_data.end(),
|
||||||
|
[&turn_data_container](const auto &turn_data) {
|
||||||
|
turn_data_container.push_back(turn_data);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Copy via-way restrictions delayed data
|
||||||
|
delayed_turn_data.insert(delayed_turn_data.end(),
|
||||||
|
buffer->delayed_turn_data.begin(),
|
||||||
|
buffer->delayed_turn_data.end());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now, execute the pipeline. The value of "5" here was chosen by experimentation
|
||||||
|
// on a 16-CPU machine and seemed to give the best performance. This value needs
|
||||||
|
// to be balanced with the GRAINSIZE above - ideally, the pipeline puts as much work
|
||||||
|
// as possible in the `intersection_handler` step so that those parallel workers don't
|
||||||
|
// get blocked too much by the slower (io-performing) `buffer_storage`
|
||||||
|
tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 5,
|
||||||
|
generator_stage & guidance_stage & guidance_output_stage);
|
||||||
|
|
||||||
|
// NOTE: EBG edges delayed_data and turns delayed_turn_data have the same index
|
||||||
|
std::for_each(delayed_turn_data.begin(),
|
||||||
|
delayed_turn_data.end(),
|
||||||
|
[&turn_data_container](const auto &turn_data) {
|
||||||
|
turn_data_container.push_back(turn_data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
util::Log() << "done.";
|
||||||
|
|
||||||
|
util::Log() << "Created " << entry_class_hash.data.size() << " entry classes and "
|
||||||
|
<< bearing_class_hash.data.size() << " Bearing Classes";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace guidance
|
||||||
|
} // namespace osrm
|
@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
namespace extractor
|
|
||||||
{
|
|
||||||
namespace guidance
|
namespace guidance
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace RoadPriorityClass = extractor::RoadPriorityClass;
|
||||||
|
|
||||||
struct EdgeInfo
|
struct EdgeInfo
|
||||||
{
|
{
|
||||||
NodeID node;
|
NodeID node;
|
||||||
@ -21,7 +21,7 @@ struct EdgeInfo
|
|||||||
// 0 - outgoing (forward), 1 - incoming (reverse), 2 - both outgoing and incoming
|
// 0 - outgoing (forward), 1 - incoming (reverse), 2 - both outgoing and incoming
|
||||||
int direction;
|
int direction;
|
||||||
|
|
||||||
ClassData road_class;
|
extractor::ClassData road_class;
|
||||||
|
|
||||||
RoadPriorityClass::Enum road_priority_class;
|
RoadPriorityClass::Enum road_priority_class;
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ bool IsSegregated(std::vector<EdgeInfo> v1,
|
|||||||
return edgeLength <= threshold;
|
return edgeLength <= threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_set<EdgeID> findSegregatedNodes(const NodeBasedGraphFactory &factory,
|
std::unordered_set<EdgeID> findSegregatedNodes(const extractor::NodeBasedGraphFactory &factory,
|
||||||
const util::NameTable &names)
|
const util::NameTable &names)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -238,6 +238,6 @@ std::unordered_set<EdgeID> findSegregatedNodes(const NodeBasedGraphFactory &fact
|
|||||||
|
|
||||||
return segregated_edges;
|
return segregated_edges;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
} // namespace guidance
|
||||||
}
|
} // namespace osrm
|
||||||
|
@ -241,9 +241,9 @@ void Storage::PopulateLayout(DataLayout &layout)
|
|||||||
const auto number_of_original_edges = edges_file.ReadElementCount64();
|
const auto number_of_original_edges = edges_file.ReadElementCount64();
|
||||||
|
|
||||||
// note: settings this all to the same size is correct, we extract them from the same struct
|
// note: settings this all to the same size is correct, we extract them from the same struct
|
||||||
layout.SetBlockSize<util::guidance::TurnBearing>(DataLayout::PRE_TURN_BEARING,
|
layout.SetBlockSize<guidance::TurnBearing>(DataLayout::PRE_TURN_BEARING,
|
||||||
number_of_original_edges);
|
number_of_original_edges);
|
||||||
layout.SetBlockSize<util::guidance::TurnBearing>(DataLayout::POST_TURN_BEARING,
|
layout.SetBlockSize<guidance::TurnBearing>(DataLayout::POST_TURN_BEARING,
|
||||||
number_of_original_edges);
|
number_of_original_edges);
|
||||||
layout.SetBlockSize<guidance::TurnInstruction>(DataLayout::TURN_INSTRUCTION,
|
layout.SetBlockSize<guidance::TurnInstruction>(DataLayout::TURN_INSTRUCTION,
|
||||||
number_of_original_edges);
|
number_of_original_edges);
|
||||||
@ -708,14 +708,14 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
|
|||||||
util::vector_view<EntryClassID> entry_class_ids(
|
util::vector_view<EntryClassID> entry_class_ids(
|
||||||
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
|
||||||
|
|
||||||
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing, true>(
|
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<guidance::TurnBearing, true>(
|
||||||
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
|
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
|
||||||
util::vector_view<util::guidance::TurnBearing> pre_turn_bearings(
|
util::vector_view<guidance::TurnBearing> pre_turn_bearings(
|
||||||
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
|
||||||
|
|
||||||
const auto post_turn_bearing_ptr = layout.GetBlockPtr<util::guidance::TurnBearing, true>(
|
const auto post_turn_bearing_ptr = layout.GetBlockPtr<guidance::TurnBearing, true>(
|
||||||
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
|
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
|
||||||
util::vector_view<util::guidance::TurnBearing> post_turn_bearings(
|
util::vector_view<guidance::TurnBearing> post_turn_bearings(
|
||||||
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
|
||||||
|
|
||||||
guidance::TurnDataView turn_data(std::move(turn_instructions),
|
guidance::TurnDataView turn_data(std::move(turn_instructions),
|
||||||
|
@ -78,5 +78,5 @@ std::size_t BearingClass::findMatchingBearing(const double bearing) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace extractor
|
} // namespace util
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -37,5 +37,5 @@ bool EntryClass::operator<(const EntryClass &other) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace extractor
|
} // namespace util
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
namespace osrm
|
|
||||||
{
|
|
||||||
namespace util
|
|
||||||
{
|
|
||||||
namespace guidance
|
|
||||||
{
|
|
||||||
|
|
||||||
constexpr double bearing_scale = 360.0 / 256.0;
|
|
||||||
|
|
||||||
// discretizes a bearing into distinct units of 1.4 degrees
|
|
||||||
TurnBearing::TurnBearing(const double value) : bearing(value / bearing_scale)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT_MSG(value >= 0 && value < 360.0,
|
|
||||||
"Bearing value needs to be between 0 and 360 (exclusive)");
|
|
||||||
}
|
|
||||||
|
|
||||||
double TurnBearing::Get() const { return bearing * bearing_scale; }
|
|
||||||
|
|
||||||
} // namespace guidance
|
|
||||||
} // namespace util
|
|
||||||
} // namespace osrm
|
|
@ -341,14 +341,14 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
|||||||
ComponentID GetComponentID(NodeID) const override { return ComponentID{}; }
|
ComponentID GetComponentID(NodeID) const override { return ComponentID{}; }
|
||||||
bool ExcludeNode(const NodeID) const override { return false; }
|
bool ExcludeNode(const NodeID) const override { return false; }
|
||||||
|
|
||||||
util::guidance::TurnBearing PreTurnBearing(const EdgeID /*eid*/) const override
|
guidance::TurnBearing PreTurnBearing(const EdgeID /*eid*/) const override
|
||||||
{
|
{
|
||||||
return util::guidance::TurnBearing(0);
|
return guidance::TurnBearing(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::guidance::TurnBearing PostTurnBearing(const EdgeID /*eid*/) const override
|
guidance::TurnBearing PostTurnBearing(const EdgeID /*eid*/) const override
|
||||||
{
|
{
|
||||||
return util::guidance::TurnBearing(0);
|
return guidance::TurnBearing(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::guidance::BearingClass
|
util::guidance::BearingClass
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "extractor/class_data.hpp"
|
#include "extractor/class_data.hpp"
|
||||||
#include "extractor/travel_mode.hpp"
|
#include "extractor/travel_mode.hpp"
|
||||||
#include "extractor/turn_lane_types.hpp"
|
#include "extractor/turn_lane_types.hpp"
|
||||||
|
#include "guidance/turn_bearing.hpp"
|
||||||
#include "guidance/turn_instruction.hpp"
|
#include "guidance/turn_instruction.hpp"
|
||||||
|
|
||||||
#include "engine/algorithm.hpp"
|
#include "engine/algorithm.hpp"
|
||||||
@ -15,7 +16,6 @@
|
|||||||
|
|
||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
#include "util/guidance/turn_bearing.hpp"
|
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@ -226,13 +226,13 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
|||||||
bool IsLeftHandDriving(const NodeID /*id*/) const override { return false; }
|
bool IsLeftHandDriving(const NodeID /*id*/) const override { return false; }
|
||||||
bool IsSegregated(const NodeID /*id*/) const override { return false; }
|
bool IsSegregated(const NodeID /*id*/) const override { return false; }
|
||||||
|
|
||||||
util::guidance::TurnBearing PreTurnBearing(const EdgeID /*eid*/) const override final
|
guidance::TurnBearing PreTurnBearing(const EdgeID /*eid*/) const override final
|
||||||
{
|
{
|
||||||
return util::guidance::TurnBearing{0.0};
|
return guidance::TurnBearing{0.0};
|
||||||
}
|
}
|
||||||
util::guidance::TurnBearing PostTurnBearing(const EdgeID /*eid*/) const override final
|
guidance::TurnBearing PostTurnBearing(const EdgeID /*eid*/) const override final
|
||||||
{
|
{
|
||||||
return util::guidance::TurnBearing{0.0};
|
return guidance::TurnBearing{0.0};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasLaneData(const EdgeID /*id*/) const override final { return true; };
|
bool HasLaneData(const EdgeID /*id*/) const override final { return true; };
|
||||||
|
Loading…
Reference in New Issue
Block a user