initial version of intersection classification
This commit is contained in:
committed by
Patrick Niklaus
parent
6aa97048df
commit
ba074b0116
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "extractor/suffix_table.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
#include "extractor/guidance/turn_analysis.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
@@ -22,6 +23,7 @@
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -326,6 +328,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map,
|
||||
m_barrier_nodes, m_compressed_edge_container, name_table,
|
||||
street_name_suffix_table);
|
||||
|
||||
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
|
||||
std::numeric_limits<std::uint32_t>::max());
|
||||
|
||||
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
|
||||
{
|
||||
progress.PrintStatus(node_u);
|
||||
@@ -340,6 +346,40 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
auto possible_turns = turn_analysis.getTurns(node_u, edge_from_u);
|
||||
|
||||
const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);
|
||||
|
||||
// the entry class depends on the turn, so we have to classify the interesction for
|
||||
// every edge
|
||||
const auto turn_classification = classifyIntersection(
|
||||
node_v, turn_analysis.getIntersection(node_u, edge_from_u), *m_node_based_graph,
|
||||
m_compressed_edge_container, m_node_info_list);
|
||||
|
||||
const auto entry_class_id = [&](const util::guidance::EntryClass entry_class) {
|
||||
if (0 == entry_class_hash.count(entry_class))
|
||||
{
|
||||
const auto id = static_cast<std::uint16_t>(entry_class_hash.size());
|
||||
entry_class_hash[entry_class] = id;
|
||||
return id;
|
||||
}
|
||||
else
|
||||
{
|
||||
return entry_class_hash.find(entry_class)->second;
|
||||
}
|
||||
}(turn_classification.first);
|
||||
|
||||
const auto bearing_class_id = [&](const util::guidance::BearingClass bearing_class) {
|
||||
if (0 == bearing_class_hash.count(bearing_class))
|
||||
{
|
||||
const auto id = static_cast<std::uint32_t>(bearing_class_hash.size());
|
||||
bearing_class_hash[bearing_class] = id;
|
||||
return id;
|
||||
}
|
||||
else
|
||||
{
|
||||
return bearing_class_hash.find(bearing_class)->second;
|
||||
}
|
||||
}(turn_classification.second);
|
||||
bearing_class_by_node_based_node[node_v] = bearing_class_id;
|
||||
|
||||
for (const auto turn : possible_turns)
|
||||
{
|
||||
const double turn_angle = turn.angle;
|
||||
@@ -373,7 +413,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_from_u));
|
||||
original_edge_data_vector.emplace_back(
|
||||
m_compressed_edge_container.GetPositionForID(edge_from_u), edge_data1.name_id,
|
||||
turn_instruction, edge_data1.travel_mode);
|
||||
turn_instruction, entry_class_id, edge_data1.travel_mode);
|
||||
|
||||
++original_edges_counter;
|
||||
|
||||
@@ -469,6 +509,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
}
|
||||
}
|
||||
|
||||
util::SimpleLogger().Write() << "Created " << entry_class_hash.size() << " entry classes and "
|
||||
<< bearing_class_hash.size() << " Bearing Classes";
|
||||
|
||||
FlushVectorToStream(edge_data_file, original_edge_data_vector);
|
||||
|
||||
// Finally jump back to the empty space at the beginning and write length prefix
|
||||
@@ -493,6 +536,38 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
<< " turns over barriers";
|
||||
}
|
||||
|
||||
std::vector<util::guidance::BearingClass> EdgeBasedGraphFactory::GetBearingClasses() const
|
||||
{
|
||||
std::vector<util::guidance::BearingClass> result(bearing_class_hash.size());
|
||||
for (const auto &pair : bearing_class_hash)
|
||||
{
|
||||
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.size());
|
||||
for (const auto &pair : entry_class_hash)
|
||||
{
|
||||
BOOST_ASSERT(pair.second < result.size());
|
||||
result[pair.second] = pair.first;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int EdgeBasedGraphFactory::GetTurnPenalty(double angle, lua_State *lua_state) const
|
||||
{
|
||||
BOOST_ASSERT(lua_state != nullptr);
|
||||
|
||||
+54
-16
@@ -9,20 +9,18 @@
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
|
||||
#include "extractor/raster_source.hpp"
|
||||
#include "util/graph_loader.hpp"
|
||||
#include "util/io.hpp"
|
||||
#include "util/lua_util.hpp"
|
||||
#include "util/make_unique.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/timing_util.hpp"
|
||||
#include "util/lua_util.hpp"
|
||||
#include "util/graph_loader.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/static_rtree.hpp"
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/restriction_map.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/static_rtree.hpp"
|
||||
|
||||
#include "extractor/tarjan_scc.hpp"
|
||||
|
||||
@@ -41,14 +39,14 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
#include <chrono>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <chrono>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -159,8 +157,7 @@ int Extractor::run()
|
||||
// parse OSM entities in parallel, store in resulting vectors
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<std::size_t>(0, osm_elements.size()),
|
||||
[&](const tbb::blocked_range<std::size_t> &range)
|
||||
{
|
||||
[&](const tbb::blocked_range<std::size_t> &range) {
|
||||
ExtractionNode result_node;
|
||||
ExtractionWay result_way;
|
||||
auto &local_context = scripting_environment.GetContex();
|
||||
@@ -269,10 +266,10 @@ int Extractor::run()
|
||||
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(main_context.state, main_context.properties,
|
||||
internal_to_external_node_map,
|
||||
edge_based_node_list, node_is_startpoint,
|
||||
edge_based_node_weights, edge_based_edge_list);
|
||||
auto graph_size = BuildEdgeExpandedGraph(
|
||||
main_context.state, main_context.properties, internal_to_external_node_map,
|
||||
edge_based_node_list, node_is_startpoint, edge_based_node_weights, edge_based_edge_list,
|
||||
config.intersection_class_data_output_path);
|
||||
|
||||
auto number_of_node_based_nodes = graph_size.first;
|
||||
auto max_edge_id = graph_size.second;
|
||||
@@ -474,7 +471,8 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||
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)
|
||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||
const std::string &intersection_class_output_file)
|
||||
{
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> traffic_lights;
|
||||
@@ -508,6 +506,11 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
|
||||
auto max_edge_id = edge_based_graph_factory.GetHighestEdgeID();
|
||||
|
||||
const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();
|
||||
|
||||
WriteIntersectionClassificationData(
|
||||
intersection_class_output_file, edge_based_graph_factory.GetBearingClassIds(),
|
||||
edge_based_graph_factory.GetBearingClasses(), edge_based_graph_factory.GetEntryClasses());
|
||||
|
||||
return std::make_pair(number_of_node_based_nodes, max_edge_id);
|
||||
}
|
||||
|
||||
@@ -601,5 +604,40 @@ void Extractor::WriteEdgeBasedGraph(
|
||||
|
||||
util::SimpleLogger().Write() << "Processed " << number_of_used_edges << " edges";
|
||||
}
|
||||
|
||||
void Extractor::WriteIntersectionClassificationData(
|
||||
const std::string &output_file_name,
|
||||
const std::vector<BearingClassID> &node_based_intersection_classes,
|
||||
const std::vector<util::guidance::BearingClass> &bearing_classes,
|
||||
const std::vector<util::guidance::EntryClass> &entry_classes) const
|
||||
{
|
||||
std::ofstream file_out_stream(output_file_name.c_str(), std::ios::binary);
|
||||
if (!file_out_stream)
|
||||
{
|
||||
util::SimpleLogger().Write(logWARNING) << "Failed to open " << output_file_name
|
||||
<< " for writing";
|
||||
return;
|
||||
}
|
||||
|
||||
util::SimpleLogger().Write() << "Writing Intersection Classification Data";
|
||||
TIMER_START(write_edges);
|
||||
util::writeFingerprint(file_out_stream);
|
||||
util::serializeVector(file_out_stream, node_based_intersection_classes);
|
||||
|
||||
static_assert(std::is_trivially_copyable<util::guidance::BearingClass>::value,
|
||||
"BearingClass Serialization requires trivial copyable bearing classes");
|
||||
|
||||
util::serializeVector(file_out_stream, bearing_classes);
|
||||
|
||||
static_assert(std::is_trivially_copyable<util::guidance::EntryClass>::value,
|
||||
"EntryClass Serialization requires trivial copyable entry classes");
|
||||
|
||||
util::serializeVector(file_out_stream, entry_classes);
|
||||
TIMER_STOP(write_edges);
|
||||
util::SimpleLogger().Write() << "ok, after " << TIMER_SEC(write_edges) << "s for "
|
||||
<< node_based_intersection_classes.size() << " Indices into "
|
||||
<< bearing_classes.size() << " bearing classes and "
|
||||
<< entry_classes.size() << " entry classes";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
#include <cstddef>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
using osrm::util::guidance::getTurnDirection;
|
||||
|
||||
@@ -79,6 +81,11 @@ std::vector<TurnOperation> TurnAnalysis::getTurns(const NodeID from_nid, const E
|
||||
return turns;
|
||||
}
|
||||
|
||||
Intersection TurnAnalysis::getIntersection(const NodeID from_nid, const EdgeID via_eid) const
|
||||
{
|
||||
return intersection_generator(from_nid, via_eid);
|
||||
}
|
||||
|
||||
// Sets basic turn types as fallback for otherwise unhandled turns
|
||||
Intersection
|
||||
TurnAnalysis::setTurnTypes(const NodeID from_nid, const EdgeID, Intersection intersection) const
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "extractor/guidance/turn_classification.hpp"
|
||||
|
||||
#include "util/simple_logger.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
struct TurnPossibility
|
||||
{
|
||||
TurnPossibility(bool entry_allowed, double bearing)
|
||||
: entry_allowed(entry_allowed), bearing(std::move(bearing))
|
||||
{
|
||||
}
|
||||
|
||||
TurnPossibility() : entry_allowed(false), bearing(0) {}
|
||||
|
||||
bool entry_allowed;
|
||||
double bearing;
|
||||
};
|
||||
|
||||
std::pair<util::guidance::EntryClass, util::guidance::BearingClass>
|
||||
classifyIntersection(NodeID nid,
|
||||
const Intersection &intersection,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const extractor::CompressedEdgeContainer &compressed_geometries,
|
||||
const std::vector<extractor::QueryNode> &query_nodes)
|
||||
{
|
||||
|
||||
std::vector<TurnPossibility> turns;
|
||||
|
||||
const auto node_coordinate = util::Coordinate(query_nodes[nid].lon, query_nodes[nid].lat);
|
||||
|
||||
// generate a list of all turn angles between a base edge, the node and a current edge
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
const auto eid = road.turn.eid;
|
||||
const auto edge_coordinate = getRepresentativeCoordinate(
|
||||
nid, node_based_graph.GetTarget(eid), eid, false, compressed_geometries, query_nodes);
|
||||
|
||||
const double bearing =
|
||||
util::coordinate_calculation::bearing(node_coordinate, edge_coordinate);
|
||||
turns.push_back({road.entry_allowed, bearing});
|
||||
}
|
||||
|
||||
if (turns.empty())
|
||||
return {};
|
||||
|
||||
std::sort(turns.begin(), turns.end(),
|
||||
[](const TurnPossibility left, const TurnPossibility right) {
|
||||
return left.bearing < right.bearing;
|
||||
});
|
||||
|
||||
util::guidance::EntryClass entry_class;
|
||||
util::guidance::BearingClass bearing_class;
|
||||
|
||||
std::size_t turn_index = 0;
|
||||
for (std::size_t i = 0; i < turns.size(); ++i)
|
||||
{
|
||||
if (turns[i].entry_allowed)
|
||||
entry_class.activate(turn_index);
|
||||
if (bearing_class.addContinuous(turns[i].bearing))
|
||||
++turn_index;
|
||||
}
|
||||
|
||||
if (turn_index != turns.size())
|
||||
{
|
||||
util::SimpleLogger().Write(logDEBUG)
|
||||
<< "Failed to provide full turn list for intersection: " << turn_index << " roads of "
|
||||
<< turns.size() << " mapped.";
|
||||
for (auto turn : turns)
|
||||
std::cout << " " << (int)turn.bearing << " ("
|
||||
<< (int)util::guidance::BearingClass::discreteBearingID(turn.bearing) << ")";
|
||||
std::cout << std::endl;
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
const auto eid = road.turn.eid;
|
||||
const auto edge_coordinate =
|
||||
getRepresentativeCoordinate(nid, node_based_graph.GetTarget(eid), eid, false,
|
||||
compressed_geometries, query_nodes);
|
||||
|
||||
const double bearing =
|
||||
util::coordinate_calculation::bearing(node_coordinate, edge_coordinate);
|
||||
std::cout << " " << bearing;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
return std::make_pair(entry_class, bearing_class);
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
Reference in New Issue
Block a user