From da4f700f80c01115ed4af07732bf325060b200b7 Mon Sep 17 00:00:00 2001 From: Daniel Patterson Date: Thu, 3 Jan 2019 11:59:28 -0800 Subject: [PATCH] Add flag to edges that transition into restricted areas. --- include/contractor/contractor_graph.hpp | 13 +- .../contractor/graph_contractor_adaptors.hpp | 9 +- include/contractor/query_edge.hpp | 19 ++- include/extractor/edge_based_edge.hpp | 16 +- .../partitioner/edge_based_graph_reader.hpp | 2 + include/storage/view_factory.hpp | 39 +++++ profiles/car.lua | 6 +- src/contractor/graph_contractor.cpp | 13 ++ src/extractor/edge_based_graph_factory.cpp | 6 + src/tools/dump.cpp | 143 ++++++++++++++++++ 10 files changed, 245 insertions(+), 21 deletions(-) create mode 100644 src/tools/dump.cpp diff --git a/include/contractor/contractor_graph.hpp b/include/contractor/contractor_graph.hpp index 02cad2e08..bf32c9169 100644 --- a/include/contractor/contractor_graph.hpp +++ b/include/contractor/contractor_graph.hpp @@ -12,27 +12,30 @@ namespace contractor struct ContractorEdgeData { ContractorEdgeData() - : weight(0), duration(0), distance(0), id(0), originalEdges(0), shortcut(0), forward(0), - backward(0) + : weight(0), duration(0), distance(0), id(0), maneuver_restricted(false), originalEdges(0), + shortcut(0), forward(0), backward(0) { } ContractorEdgeData(EdgeWeight weight, - EdgeWeight duration, + EdgeDuration duration, EdgeDistance distance, unsigned original_edges, unsigned id, + bool maneuver_restricted, bool shortcut, bool forward, bool backward) : weight(weight), duration(duration), distance(distance), id(id), + maneuver_restricted(maneuver_restricted), originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut), forward(forward), backward(backward) { } EdgeWeight weight; - EdgeWeight duration; + EdgeDuration duration; EdgeDistance distance; - unsigned id; + unsigned id : 31; + bool maneuver_restricted : 1; unsigned originalEdges : 29; bool shortcut : 1; bool forward : 1; diff --git a/include/contractor/graph_contractor_adaptors.hpp b/include/contractor/graph_contractor_adaptors.hpp index 94dc7e62b..158da96d4 100644 --- a/include/contractor/graph_contractor_adaptors.hpp +++ b/include/contractor/graph_contractor_adaptors.hpp @@ -44,6 +44,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp input_edge.data.distance, 1, input_edge.data.turn_id, + input_edge.data.maneuver_restricted, false, input_edge.data.forward ? true : false, input_edge.data.backward ? true : false); @@ -55,6 +56,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp input_edge.data.distance, 1, input_edge.data.turn_id, + input_edge.data.maneuver_restricted, // Note: inverted false, input_edge.data.backward ? true : false, input_edge.data.forward ? true : false); @@ -85,6 +87,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT; forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION; forward_edge.data.distance = reverse_edge.data.distance = MAXIMAL_EDGE_DISTANCE; + forward_edge.data.maneuver_restricted = reverse_edge.data.maneuver_restricted = false; // remove parallel edges while (i < edges.size() && edges[i].source == source && edges[i].target == target) { @@ -95,6 +98,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp std::min(edges[i].data.duration, forward_edge.data.duration); forward_edge.data.distance = std::min(edges[i].data.distance, forward_edge.data.distance); + forward_edge.data.maneuver_restricted = edges[i].data.maneuver_restricted; } if (edges[i].data.backward) { @@ -103,11 +107,13 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp std::min(edges[i].data.duration, reverse_edge.data.duration); reverse_edge.data.distance = std::min(edges[i].data.distance, reverse_edge.data.distance); + reverse_edge.data.maneuver_restricted = edges[i].data.maneuver_restricted; } ++i; } // merge edges (s,t) and (t,s) into bidirectional edge - if (forward_edge.data.weight == reverse_edge.data.weight) + if (forward_edge.data.weight == reverse_edge.data.weight && + forward_edge.data.maneuver_restricted == reverse_edge.data.maneuver_restricted) { if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT) { @@ -165,6 +171,7 @@ template inline std::vector toEdges(GraphT g "edge id invalid"); new_edge.data.forward = data.forward; new_edge.data.backward = data.backward; + new_edge.data.maneuver_restricted = data.maneuver_restricted; } } BOOST_ASSERT(edge_index == edges.size()); diff --git a/include/contractor/query_edge.hpp b/include/contractor/query_edge.hpp index 74d38e79e..e3a3463cc 100644 --- a/include/contractor/query_edge.hpp +++ b/include/contractor/query_edge.hpp @@ -17,8 +17,8 @@ struct QueryEdge struct EdgeData { explicit EdgeData() - : turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false), - distance(0) + : turn_id(0), shortcut(false), maneuver_restricted(false), weight(0), duration(0), + forward(false), backward(false), distance(0) { } @@ -28,9 +28,11 @@ struct QueryEdge const EdgeWeight duration, const EdgeDistance distance, const bool forward, - const bool backward) - : turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration), - forward(forward), backward(backward), distance(distance) + const bool backward, + const bool maneuver_restricted) + : turn_id(turn_id), shortcut(shortcut), maneuver_restricted(maneuver_restricted), + weight(weight), duration(duration), forward(forward), backward(backward), + distance(distance) { } @@ -43,12 +45,14 @@ struct QueryEdge forward = other.forward; backward = other.backward; distance = other.distance; + maneuver_restricted = other.maneuver_restricted; } // this ID is either the middle node of the shortcut, or the ID of the edge based node (node // based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle // node. Otherwise we see the edge based node to access node data. - NodeID turn_id : 31; + NodeID turn_id : 30; bool shortcut : 1; + bool maneuver_restricted : 1; EdgeWeight weight; EdgeWeight duration : 30; std::uint32_t forward : 1; @@ -74,7 +78,8 @@ struct QueryEdge data.weight == right.data.weight && data.duration == right.data.duration && data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward && data.turn_id == right.data.turn_id && - data.distance == right.data.distance); + data.distance == right.data.distance && + data.maneuver_restricted == data.maneuver_restricted); } }; } diff --git a/include/extractor/edge_based_edge.hpp b/include/extractor/edge_based_edge.hpp index 28ebf934a..501b4a3c9 100644 --- a/include/extractor/edge_based_edge.hpp +++ b/include/extractor/edge_based_edge.hpp @@ -16,22 +16,25 @@ struct EdgeBasedEdge struct EdgeData { EdgeData() - : turn_id(0), weight(0), distance(0), duration(0), forward(false), backward(false) + : turn_id(0), maneuver_restricted(false), weight(0), distance(0), duration(0), + forward(false), backward(false) { } EdgeData(const NodeID turn_id, + const bool maneuver_restricted, const EdgeWeight weight, const EdgeDistance distance, const EdgeWeight duration, const bool forward, const bool backward) - : turn_id(turn_id), weight(weight), distance(distance), duration(duration), - forward(forward), backward(backward) + : turn_id(turn_id), maneuver_restricted(maneuver_restricted), weight(weight), + distance(distance), duration(duration), forward(forward), backward(backward) { } - NodeID turn_id; // ID of the edge based node (node based edge) + NodeID turn_id : 31; // ID of the edge based node (node based edge) + bool maneuver_restricted : 1; EdgeWeight weight; EdgeDistance distance; EdgeWeight duration : 30; @@ -46,6 +49,7 @@ struct EdgeBasedEdge EdgeBasedEdge(const NodeID source, const NodeID target, const NodeID edge_id, + const bool maneuver_restricted, const EdgeWeight weight, const EdgeWeight duration, const EdgeDistance distance, @@ -71,12 +75,14 @@ inline EdgeBasedEdge::EdgeBasedEdge() : source(0), target(0) {} inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source, const NodeID target, const NodeID turn_id, + const bool maneuver_restricted, const EdgeWeight weight, const EdgeWeight duration, const EdgeDistance distance, const bool forward, const bool backward) - : source(source), target(target), data{turn_id, weight, distance, duration, forward, backward} + : source(source), target(target), + data{turn_id, maneuver_restricted, weight, distance, duration, forward, backward} { } diff --git a/include/partitioner/edge_based_graph_reader.hpp b/include/partitioner/edge_based_graph_reader.hpp index bc5ba8b96..a02649574 100644 --- a/include/partitioner/edge_based_graph_reader.hpp +++ b/include/partitioner/edge_based_graph_reader.hpp @@ -41,6 +41,7 @@ splitBidirectionalEdges(const std::vector &edges) directed.emplace_back(edge.source, edge.target, edge.data.turn_id, + edge.data.maneuver_restricted, std::max(edge.data.weight, 1), edge.data.duration, edge.data.distance, @@ -50,6 +51,7 @@ splitBidirectionalEdges(const std::vector &edges) directed.emplace_back(edge.target, edge.source, edge.data.turn_id, + edge.data.maneuver_restricted, std::max(edge.data.weight, 1), edge.data.duration, edge.data.distance, diff --git a/include/storage/view_factory.hpp b/include/storage/view_factory.hpp index b04e3026e..b38223157 100644 --- a/include/storage/view_factory.hpp +++ b/include/storage/view_factory.hpp @@ -372,6 +372,45 @@ inline auto make_filtered_graph_view(const SharedDataIndex &index, auto edge_list = make_vector_view( index, name + "/contracted_graph/edge_array"); + // DEBUG - dump CH + std::cout << "digraph {" << std::endl; + for (std::size_t i = 0; i < node_list.size(); i++) + { + for (auto edge = node_list[i].first_edge; + edge < (i == node_list.size() - 1 ? edge_list.size() : node_list[i + 1].first_edge); + edge++) + { + const auto &e = edge_list[edge]; + if (e.data.forward) + { + std::cout << i << " -> " << e.target; + std::cout << "["; + std::cout << "label=\"↑" << e.data.weight << "\",weight=\"" << e.data.weight + << "\""; + if (e.data.maneuver_restricted) + { + std::cout << ",color=red,penwidth=3.0"; + } + std::cout << "];"; + std::cout << std::endl; + } + if (e.data.backward) + { + std::cout << e.target << " -> " << i; + std::cout << "["; + std::cout << "label=\"↓" << e.data.weight << "\",weight=\"" << e.data.weight + << "\""; + if (e.data.maneuver_restricted) + { + std::cout << ",color=red,penwidth=3.0"; + } + std::cout << "];"; + std::cout << std::endl; + } + } + } + std::cout << "}" << std::endl; + return util::FilteredGraphView({node_list, edge_list}, edge_filter); } } diff --git a/profiles/car.lua b/profiles/car.lua index 02f185abb..3e0496c5a 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -483,9 +483,9 @@ function process_turn(profile, turn) if profile.properties.weight_name == 'routability' then -- penalize turns from non-local access only segments onto local access only tags - if not turn.source_restricted and turn.target_restricted then - turn.weight = constants.max_turn_weight - end + -- if not turn.source_restricted and turn.target_restricted then + -- turn.weight = constants.max_turn_weight + -- end end end diff --git a/src/contractor/graph_contractor.cpp b/src/contractor/graph_contractor.cpp index 8615156dd..d960e4a6a 100644 --- a/src/contractor/graph_contractor.cpp +++ b/src/contractor/graph_contractor.cpp @@ -218,6 +218,8 @@ void ContractNode(ContractorThreadData *data, in_data.distance + out_data.distance, out_data.originalEdges + in_data.originalEdges, node, + in_data.maneuver_restricted || + out_data.maneuver_restricted, SHORTCUT_ARC, FORWARD_DIRECTION_ENABLED, REVERSE_DIRECTION_DISABLED); @@ -229,6 +231,8 @@ void ContractNode(ContractorThreadData *data, in_data.distance + out_data.distance, out_data.originalEdges + in_data.originalEdges, node, + in_data.maneuver_restricted || + out_data.maneuver_restricted, SHORTCUT_ARC, FORWARD_DIRECTION_DISABLED, REVERSE_DIRECTION_ENABLED); @@ -285,6 +289,8 @@ void ContractNode(ContractorThreadData *data, in_data.distance + out_data.distance, out_data.originalEdges + in_data.originalEdges, node, + in_data.maneuver_restricted || + out_data.maneuver_restricted, SHORTCUT_ARC, FORWARD_DIRECTION_ENABLED, REVERSE_DIRECTION_DISABLED); @@ -296,6 +302,8 @@ void ContractNode(ContractorThreadData *data, in_data.distance + out_data.distance, out_data.originalEdges + in_data.originalEdges, node, + in_data.maneuver_restricted || + out_data.maneuver_restricted, SHORTCUT_ARC, FORWARD_DIRECTION_DISABLED, REVERSE_DIRECTION_ENABLED); @@ -329,6 +337,11 @@ void ContractNode(ContractorThreadData *data, { continue; } + if (inserted_edges[other].data.maneuver_restricted != + inserted_edges[i].data.maneuver_restricted) + { + continue; + } inserted_edges[other].data.forward |= inserted_edges[i].data.forward; inserted_edges[other].data.backward |= inserted_edges[i].data.backward; found = true; diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index 0d4023877..03fb14220 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -656,6 +656,11 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( BOOST_ASSERT(SPECIAL_NODEID != nbe_to_ebn_mapping[node_based_edge_from]); BOOST_ASSERT(SPECIAL_NODEID != nbe_to_ebn_mapping[node_based_edge_to]); + // If a source is not restricted, and the target is restricted, then we + // call this a "restricted maneuver" + const bool restricted_maneuver = + !edge_data1.flags.restricted && edge_data2.flags.restricted; + // auto turn_id = m_edge_based_edge_list.size(); auto weight = boost::numeric_cast(edge_data1.weight + weight_penalty); auto duration = boost::numeric_cast(edge_data1.duration + duration_penalty); @@ -665,6 +670,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( edge_based_node_to, SPECIAL_NODEID, // This will be updated once the main // loop completes! + restricted_maneuver, weight, duration, distance, diff --git a/src/tools/dump.cpp b/src/tools/dump.cpp new file mode 100644 index 000000000..0ba4adc75 --- /dev/null +++ b/src/tools/dump.cpp @@ -0,0 +1,143 @@ +#include "storage/serialization.hpp" +#include "storage/shared_memory.hpp" +#include "storage/shared_monitor.hpp" +#include "storage/storage.hpp" + +#include "osrm/exception.hpp" +#include "util/log.hpp" +#include "util/meminfo.hpp" +#include "util/typedefs.hpp" +#include "util/version.hpp" + +#include +#include + +#include +#include + +using namespace osrm; + +// generate boost::program_options object for the routing part +bool generateDataStoreOptions(const int argc, + const char *argv[], + std::string &verbosity, + boost::filesystem::path &base_path, + int &max_wait, + std::string &dataset_name, + bool &list_datasets, + bool &list_blocks, + bool &only_metric) +{ + // declare a group of options that will be allowed only on command line + boost::program_options::options_description generic_options("Options"); + generic_options.add_options() // + ("contraction-heirarchy,ch", "Dump CH graph")("cells,c", "Dump partition structure"); + + try + { + boost::program_options::store( + boost::program_options::command_line_parser(argc, argv, generic_options), + option_variables); + } + catch (const boost::program_options::error &e) + { + util::Log(logERROR) << e.what(); + return false; + } + + if (option_variables.count("version")) + { + util::Log() << OSRM_VERSION; + return false; + } + + if (option_variables.count("help")) + { + util::Log() << visible_options; + return false; + } + + if (option_variables.count("remove-locks")) + { + removeLocks(); + return false; + } + + if (option_variables.count("spring-clean")) + { + springClean(); + return false; + } + + boost::program_options::notify(option_variables); + + return true; +} + +[[noreturn]] void CleanupSharedBarriers(int signum) +{ // Here the lock state of named mutexes is unknown, make a hard cleanup + removeLocks(); + std::_Exit(128 + signum); +} + +int main(const int argc, const char *argv[]) try +{ + int signals[] = {SIGTERM, SIGSEGV, SIGINT, SIGILL, SIGABRT, SIGFPE}; + for (auto sig : signals) + { + std::signal(sig, CleanupSharedBarriers); + } + + util::LogPolicy::GetInstance().Unmute(); + + std::string verbosity; + boost::filesystem::path base_path; + int max_wait = -1; + std::string dataset_name; + bool list_datasets = false; + bool list_blocks = false; + bool only_metric = false; + if (!generateDataStoreOptions(argc, + argv, + verbosity, + base_path, + max_wait, + dataset_name, + list_datasets, + list_blocks, + only_metric)) + { + return EXIT_SUCCESS; + } + + util::LogPolicy::GetInstance().SetLevel(verbosity); + + if (list_datasets || list_blocks) + { + listRegions(list_blocks); + return EXIT_SUCCESS; + } + + storage::StorageConfig config(base_path); + if (!config.IsValid()) + { + util::Log(logERROR) << "Config contains invalid file paths. Exiting!"; + return EXIT_FAILURE; + } + storage::Storage storage(std::move(config)); + + return storage.Run(max_wait, dataset_name, only_metric); +} +catch (const osrm::RuntimeError &e) +{ + util::Log(logERROR) << e.what(); + return e.GetCode(); +} +catch (const std::bad_alloc &e) +{ + util::DumpMemoryStats(); + util::Log(logERROR) << "[exception] " << e.what(); + util::Log(logERROR) << "Please provide more memory or disable locking the virtual " + "address space (note: this makes OSRM swap, i.e. slow)"; + return EXIT_FAILURE; +}