Fix routing when start and target are on the same segment

Fixes issue #1864. Given the simple set-up:

a --> b --> c
^-----------|

This would translate into an edge based graph (ab) -> (bc),
(bc) -> (ca), (ca) -> (ab).

Starting at the end of the one-way street (ab) and going to
the beginning, the query has to find a self-loop within the
graph (ab) -> (bc) -> (ca) -> (ab), as both nodes map to the
same segment (ab).
This commit is contained in:
Moritz Kobitzsch
2016-01-07 10:33:47 +01:00
committed by Patrick Niklaus
parent 238e77d959
commit 1c1bfd7541
22 changed files with 744 additions and 287 deletions
+32 -10
View File
@@ -7,6 +7,7 @@
#include "contractor/crc32_processor.hpp"
#include "util/graph_loader.hpp"
#include "util/io.hpp"
#include "util/integer_range.hpp"
#include "util/lua_util.hpp"
#include "util/osrm_exception.hpp"
@@ -22,6 +23,9 @@
#include <tbb/parallel_sort.h>
#include <cstddef>
#include <cstdint>
#include <bitset>
#include <chrono>
#include <memory>
#include <string>
@@ -73,7 +77,7 @@ int Prepare::Run()
util::DeallocatingVector<extractor::EdgeBasedEdge> edge_based_edge_list;
size_t max_edge_id = LoadEdgeExpandedGraph(
std::size_t max_edge_id = LoadEdgeExpandedGraph(
config.edge_based_graph_path, edge_based_edge_list, config.edge_segment_lookup_path,
config.edge_penalty_path, config.segment_speed_lookup_path);
@@ -86,9 +90,18 @@ int Prepare::Run()
{
ReadNodeLevels(node_levels);
}
util::SimpleLogger().Write() << "Reading node weights.";
std::vector<EdgeWeight> node_weights;
std::string node_file_name = config.osrm_input_path.string() + ".enw";
if (util::deserializeVector(node_file_name, node_weights))
util::SimpleLogger().Write() << "Done reading node weights.";
else
util::SimpleLogger().Write() << "Failed reading node weights.";
util::DeallocatingVector<QueryEdge> contracted_edge_list;
ContractGraph(max_edge_id, edge_based_edge_list, contracted_edge_list, is_core_node,
node_levels);
ContractGraph(max_edge_id, edge_based_edge_list, contracted_edge_list, std::move(node_weights),
is_core_node, node_levels);
TIMER_STOP(contraction);
util::SimpleLogger().Write() << "Contraction took " << TIMER_SEC(contraction) << " sec";
@@ -143,10 +156,12 @@ std::size_t Prepare::LoadEdgeExpandedGraph(
input_stream.read((char *)&fingerprint_loaded, sizeof(util::FingerPrint));
fingerprint_loaded.TestPrepare(fingerprint_valid);
size_t number_of_edges = 0;
size_t max_edge_id = SPECIAL_EDGEID;
input_stream.read((char *)&number_of_edges, sizeof(size_t));
input_stream.read((char *)&max_edge_id, sizeof(size_t));
// TODO std::size_t can vary on systems. Our files are not transferable, but we might want to
// consider using a fixed size type for I/O
std::size_t number_of_edges = 0;
std::size_t max_edge_id = SPECIAL_EDGEID;
input_stream.read((char *)&number_of_edges, sizeof(std::size_t));
input_stream.read((char *)&max_edge_id, sizeof(std::size_t));
edge_based_edge_list.resize(number_of_edges);
util::SimpleLogger().Write() << "Reading " << number_of_edges
@@ -179,7 +194,6 @@ std::size_t Prepare::LoadEdgeExpandedGraph(
{
extractor::EdgeBasedEdge inbuffer;
input_stream.read((char *)&inbuffer, sizeof(extractor::EdgeBasedEdge));
if (update_edge_weights)
{
// Processing-time edge updates
@@ -370,8 +384,11 @@ Prepare::WriteContractedGraph(unsigned max_node_id,
util::StaticGraph<EdgeData>::EdgeArrayEntry current_edge;
for (const auto edge : util::irange<std::size_t>(0, contracted_edge_list.size()))
{
// some self-loops are required for oneway handling. Need to assertthat we only keep these
// (TODO)
// no eigen loops
BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target);
// BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target ||
// node_represents_oneway[contracted_edge_list[edge].source]);
current_edge.target = contracted_edge_list[edge].target;
current_edge.data = contracted_edge_list[edge].data;
@@ -407,17 +424,22 @@ void Prepare::ContractGraph(
const unsigned max_edge_id,
util::DeallocatingVector<extractor::EdgeBasedEdge> &edge_based_edge_list,
util::DeallocatingVector<QueryEdge> &contracted_edge_list,
std::vector<EdgeWeight> &&node_weights,
std::vector<bool> &is_core_node,
std::vector<float> &inout_node_levels) const
{
std::vector<float> node_levels;
node_levels.swap(inout_node_levels);
Contractor contractor(max_edge_id + 1, edge_based_edge_list, std::move(node_levels));
Contractor contractor(max_edge_id + 1, edge_based_edge_list, std::move(node_levels),
std::move(node_weights));
contractor.Run(config.core_factor);
contractor.GetEdges(contracted_edge_list);
contractor.GetCoreMarker(is_core_node);
contractor.GetNodeLevels(inout_node_levels);
std::cout << "Levels: " << inout_node_levels.size() << " Core: " << is_core_node.size()
<< " MEID: " << max_edge_id << std::endl;
}
}
}
@@ -67,6 +67,12 @@ void EdgeBasedGraphFactory::GetStartPointMarkers(std::vector<bool> &node_is_star
swap(m_edge_based_node_is_startpoint, node_is_startpoint);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights)
{
using std::swap; // Koenig swap
swap(m_edge_based_node_weights, output_node_weights);
}
unsigned EdgeBasedGraphFactory::GetHighestEdgeID() { return m_max_edge_id; }
void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID node_v)
@@ -92,6 +98,9 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
return;
}
if (forward_data.edge_id != SPECIAL_NODEID && reverse_data.edge_id == SPECIAL_NODEID)
m_edge_based_node_weights[forward_data.edge_id] = INVALID_EDGE_WEIGHT;
BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_id_1) ==
m_compressed_edge_container.HasEntryForID(edge_id_2));
if (m_compressed_edge_container.HasEntryForID(edge_id_1))
@@ -231,6 +240,7 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
TIMER_STOP(renumber);
TIMER_START(generate_nodes);
m_edge_based_node_weights.reserve(m_max_edge_id + 1);
GenerateEdgeExpandedNodes();
TIMER_STOP(generate_nodes);
@@ -270,6 +280,11 @@ unsigned EdgeBasedGraphFactory::RenumberEdges()
continue;
}
// oneway streets always require this self-loop. Other streets only if a u-turn plus
// traversal
// of the street takes longer than the loop
m_edge_based_node_weights.push_back(edge_data.distance + speed_profile.u_turn_penalty);
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges());
edge_data.edge_id = numbered_edges_count;
++numbered_edges_count;
@@ -321,6 +336,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
}
BOOST_ASSERT(m_edge_based_node_list.size() == m_edge_based_node_is_startpoint.size());
BOOST_ASSERT(m_max_edge_id+1 == m_edge_based_node_weights.size());
util::SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size()
<< " nodes in edge-expanded graph";
+28 -14
View File
@@ -9,6 +9,7 @@
#include "extractor/scripting_environment.hpp"
#include "extractor/raster_source.hpp"
#include "util/io.hpp"
#include "util/make_unique.hpp"
#include "util/simple_logger.hpp"
#include "util/timing_util.hpp"
@@ -46,6 +47,7 @@
#include <thread>
#include <unordered_map>
#include <vector>
#include <bitset>
namespace osrm
{
@@ -71,7 +73,7 @@ namespace extractor
* graph
*
*/
int extractor::run()
int Extractor::run()
{
try
{
@@ -265,16 +267,25 @@ int extractor::run()
std::vector<EdgeBasedNode> node_based_edge_list;
util::DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
std::vector<bool> node_is_startpoint;
std::vector<EdgeWeight> edge_based_node_weights;
std::vector<QueryNode> internal_to_external_node_map;
auto graph_size =
BuildEdgeExpandedGraph(internal_to_external_node_map, node_based_edge_list,
node_is_startpoint, edge_based_edge_list);
auto graph_size = BuildEdgeExpandedGraph(internal_to_external_node_map,
node_based_edge_list, node_is_startpoint,
edge_based_node_weights, edge_based_edge_list);
auto number_of_node_based_nodes = graph_size.first;
auto max_edge_id = graph_size.second;
TIMER_STOP(expansion);
util::SimpleLogger().Write() << "Saving edge-based node weights to file.";
TIMER_START(timer_write_node_weights);
util::serializeVector(config.edge_based_node_weights_output_path,
edge_based_node_weights);
TIMER_STOP(timer_write_node_weights);
util::SimpleLogger().Write() << "Done writing. (" << TIMER_SEC(timer_write_node_weights)
<< ")";
util::SimpleLogger().Write() << "building r-tree ...";
TIMER_START(rtree);
@@ -309,7 +320,7 @@ int extractor::run()
\brief Setups scripting environment (lua-scripting)
Also initializes speed profile.
*/
void extractor::SetupScriptingEnvironment(lua_State *lua_state,
void Extractor::SetupScriptingEnvironment(lua_State *lua_state,
SpeedProfileProperties &speed_profile)
{
// open utility libraries string library;
@@ -347,7 +358,7 @@ void extractor::SetupScriptingEnvironment(lua_State *lua_state,
speed_profile.has_turn_penalty_function = util::lua_function_exists(lua_state, "turn_function");
}
void extractor::FindComponents(unsigned max_edge_id,
void Extractor::FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
std::vector<EdgeBasedNode> &input_nodes) const
{
@@ -425,7 +436,7 @@ void extractor::FindComponents(unsigned max_edge_id,
/**
\brief Build load restrictions from .restriction file
*/
std::shared_ptr<RestrictionMap> extractor::LoadRestrictionMap()
std::shared_ptr<RestrictionMap> Extractor::LoadRestrictionMap()
{
boost::filesystem::ifstream input_stream(config.restriction_file_name,
std::ios::in | std::ios::binary);
@@ -442,7 +453,7 @@ std::shared_ptr<RestrictionMap> extractor::LoadRestrictionMap()
\brief Load node based graph from .osrm file
*/
std::shared_ptr<util::NodeBasedDynamicGraph>
extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
Extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
std::unordered_set<NodeID> &traffic_lights,
std::vector<QueryNode> &internal_to_external_node_map)
{
@@ -483,9 +494,10 @@ extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
\brief Building an edge-expanded graph from node-based input and turn restrictions
*/
std::pair<std::size_t, std::size_t>
extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
Extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
std::vector<EdgeBasedNode> &node_based_edge_list,
std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list)
{
lua_State *lua_state = luaL_newstate();
@@ -526,6 +538,7 @@ extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_n
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list);
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
edge_based_graph_factory.GetEdgeBasedNodeWeights(edge_based_node_weights);
auto max_edge_id = edge_based_graph_factory.GetHighestEdgeID();
const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();
@@ -535,7 +548,7 @@ extractor::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_n
/**
\brief Writing info on original (node-based) nodes
*/
void extractor::WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map)
void Extractor::WriteNodeMapping(const std::vector<QueryNode> &internal_to_external_node_map)
{
boost::filesystem::ofstream node_stream(config.node_output_path, std::ios::binary);
const unsigned size_of_mapping = internal_to_external_node_map.size();
@@ -553,7 +566,7 @@ void extractor::WriteNodeMapping(const std::vector<QueryNode> &internal_to_exter
Saves tree into '.ramIndex' and leaves into '.fileIndex'.
*/
void extractor::BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
void Extractor::BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
std::vector<bool> node_is_startpoint,
const std::vector<QueryNode> &internal_to_external_node_map)
{
@@ -589,7 +602,7 @@ void extractor::BuildRTree(std::vector<EdgeBasedNode> node_based_edge_list,
<< " seconds";
}
void extractor::WriteEdgeBasedGraph(
void Extractor::WriteEdgeBasedGraph(
std::string const &output_file_filename,
size_t const max_edge_id,
util::DeallocatingVector<EdgeBasedEdge> const &edge_based_edge_list)
@@ -600,7 +613,8 @@ void extractor::WriteEdgeBasedGraph(
const util::FingerPrint fingerprint = util::FingerPrint::GetValid();
file_out_stream.write((char *)&fingerprint, sizeof(util::FingerPrint));
std::cout << "[extractor] Writing edge-based-graph egdes ... " << std::flush;
util::SimpleLogger().Write() << "[extractor] Writing edge-based-graph egdes ... "
<< std::flush;
TIMER_START(write_edges);
size_t number_of_used_edges = edge_based_edge_list.size();
@@ -613,7 +627,7 @@ void extractor::WriteEdgeBasedGraph(
}
TIMER_STOP(write_edges);
std::cout << "ok, after " << TIMER_SEC(write_edges) << "s" << std::endl;
util::SimpleLogger().Write() << "ok, after " << TIMER_SEC(write_edges) << "s" << std::endl;
util::SimpleLogger().Write() << "Processed " << number_of_used_edges << " edges";
file_out_stream.close();
+4
View File
@@ -142,6 +142,7 @@ void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_confi
extractor_config.geometry_output_path = input_path.string();
extractor_config.edge_output_path = input_path.string();
extractor_config.edge_graph_output_path = input_path.string();
extractor_config.edge_based_node_weights_output_path = input_path.string();
extractor_config.node_output_path = input_path.string();
extractor_config.rtree_nodes_output_path = input_path.string();
extractor_config.rtree_leafs_output_path = input_path.string();
@@ -173,6 +174,7 @@ void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_confi
extractor_config.node_output_path.append(".osrm.nodes");
extractor_config.edge_output_path.append(".osrm.edges");
extractor_config.edge_graph_output_path.append(".osrm.ebg");
extractor_config.edge_based_node_weights_output_path.append(".osrm.enw");
extractor_config.rtree_nodes_output_path.append(".osrm.ramIndex");
extractor_config.rtree_leafs_output_path.append(".osrm.fileIndex");
extractor_config.edge_segment_lookup_path.append(".osrm.edge_segment_lookup");
@@ -188,6 +190,7 @@ void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_confi
extractor_config.node_output_path.replace(pos, 5, ".osrm.nodes");
extractor_config.edge_output_path.replace(pos, 5, ".osrm.edges");
extractor_config.edge_graph_output_path.replace(pos, 5, ".osrm.ebg");
extractor_config.edge_based_node_weights_output_path.replace(pos, 5, ".osrm.enw");
extractor_config.rtree_nodes_output_path.replace(pos, 5, ".osrm.ramIndex");
extractor_config.rtree_leafs_output_path.replace(pos, 5, ".osrm.fileIndex");
extractor_config.edge_segment_lookup_path.replace(pos, 5, ".osrm.edge_segment_lookup");
@@ -204,6 +207,7 @@ void ExtractorOptions::GenerateOutputFilesNames(ExtractorConfig &extractor_confi
extractor_config.node_output_path.replace(pos, 8, ".osrm.nodes");
extractor_config.edge_output_path.replace(pos, 8, ".osrm.edges");
extractor_config.edge_graph_output_path.replace(pos, 8, ".osrm.ebg");
extractor_config.edge_based_node_weights_output_path.replace(pos, 8, ".osrm.enw");
extractor_config.rtree_nodes_output_path.replace(pos, 8, ".osrm.ramIndex");
extractor_config.rtree_leafs_output_path.replace(pos, 8, ".osrm.fileIndex");
extractor_config.edge_segment_lookup_path.replace(pos, 8, ".osrm.edge_segment_lookup");
+1 -1
View File
@@ -49,7 +49,7 @@ int main(int argc, char *argv[]) try
<< "Profile " << extractor_config.profile_path.string() << " not found!";
return EXIT_FAILURE;
}
return extractor::extractor(extractor_config).run();
return extractor::Extractor(extractor_config).run();
}
catch (const std::bad_alloc &e)
{