Implement Turn Lane Api

This commit is contained in:
Moritz Kobitzsch
2016-06-15 14:38:24 +02:00
parent ec0a1a4ab1
commit 5d91b759d1
59 changed files with 1274 additions and 439 deletions
+24 -3
View File
@@ -1,5 +1,5 @@
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_graph_factory.hpp"
#include "extractor/edge_based_edge.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/exception.hpp"
@@ -182,6 +182,7 @@ void EdgeBasedGraphFactory::FlushVectorToStream(
}
void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state,
const std::string &edge_segment_lookup_filename,
const std::string &edge_penalty_filename,
@@ -198,6 +199,7 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
TIMER_START(generate_edges);
GenerateEdgeExpandedEdges(original_edge_data_filename,
turn_lane_data_filename,
lua_state,
edge_segment_lookup_filename,
edge_penalty_filename,
@@ -296,6 +298,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
/// Actually it also generates OriginalEdgeData and serializes them...
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state,
const std::string &edge_segment_lookup_filename,
const std::string &edge_fixed_penalties_filename,
@@ -348,6 +351,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
std::numeric_limits<std::uint32_t>::max());
guidance::LaneDataIdMap lane_data_map;
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
progress.PrintStatus(node_u);
@@ -364,8 +368,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
intersection =
turn_analysis.assignTurnTypes(node_u, edge_from_u, std::move(intersection));
intersection =
turn_lane_handler.assignTurnLanes(node_u, edge_from_u, std::move(intersection));
intersection = turn_lane_handler.assignTurnLanes(
node_u, edge_from_u, std::move(intersection), lane_data_map);
const auto possible_turns = turn_analysis.transformIntersectionIntoTurns(intersection);
// the entry class depends on the turn, so we have to classify the interesction for
@@ -437,6 +441,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
original_edge_data_vector.emplace_back(
m_compressed_edge_container.GetPositionForID(edge_from_u),
edge_data1.name_id,
turn.lane_data_id,
turn_instruction,
entry_class_id,
edge_data1.travel_mode);
@@ -541,6 +546,22 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
util::SimpleLogger().Write() << "Created " << entry_class_hash.size() << " entry classes and "
<< bearing_class_hash.size() << " Bearing Classes";
util::SimpleLogger().Write() << "Writing Turn Lane Data to File...";
std::ofstream turn_lane_data_file(turn_lane_data_filename.c_str(), std::ios::binary);
std::vector<util::guidance::LaneTupelIdPair> lane_data(lane_data_map.size());
// extract lane data sorted by ID
for (auto itr : lane_data_map)
lane_data[itr.second] = itr.first;
std::uint64_t size = lane_data.size();
turn_lane_data_file.write(reinterpret_cast<const char *>(&size), sizeof(size));
if (!lane_data.empty())
turn_lane_data_file.write(reinterpret_cast<const char *>(&lane_data[0]),
sizeof(util::guidance::LaneTupelIdPair) * lane_data.size());
util::SimpleLogger().Write() << "done.";
FlushVectorToStream(edge_data_file, original_edge_data_vector);
// Finally jump back to the empty space at the beginning and write length prefix
+2 -4
View File
@@ -51,8 +51,6 @@ ExtractionContainers::ExtractionContainers()
name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
turn_lane_lengths.push_back(0);
}
@@ -87,8 +85,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
PrepareRestrictions();
WriteRestrictions(restrictions_file_name);
WriteCharData(name_file_name,name_lengths,name_char_data);
WriteCharData(turn_lane_file_name,turn_lane_lengths,turn_lane_char_data);
WriteCharData(name_file_name, name_lengths, name_char_data);
WriteCharData(turn_lane_file_name, turn_lane_lengths, turn_lane_char_data);
}
catch (const std::exception &e)
{
+3 -2
View File
@@ -239,7 +239,7 @@ int Extractor::run()
extraction_containers.PrepareData(config.output_file_name,
config.restriction_file_name,
config.names_file_name,
config.turn_lane_file_name,
config.turn_lane_strings_file_name,
main_context.state);
WriteProfileProperties(config.profile_properties_output_path, main_context.properties);
@@ -504,7 +504,7 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
util::NameTable name_table(config.names_file_name);
util::NameTable turn_lanes(config.turn_lane_file_name);
util::NameTable turn_lanes(config.turn_lane_strings_file_name);
EdgeBasedGraphFactory edge_based_graph_factory(
node_based_graph,
@@ -518,6 +518,7 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
turn_lanes);
edge_based_graph_factory.Run(config.edge_output_path,
config.turn_lane_data_file_name,
lua_state,
config.edge_segment_lookup_path,
config.edge_penalty_path,
+11 -3
View File
@@ -1,7 +1,7 @@
#include "extractor/extractor_callbacks.hpp"
#include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/extractor_callbacks.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/restriction.hpp"
@@ -149,9 +149,17 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
// Otherwise fetches the id based on the name and returns it without insertion.
const constexpr auto MAX_STRING_LENGTH = 255u;
const auto requestId = [this,MAX_STRING_LENGTH](const std::string turn_lane_string) {
if( turn_lane_string == "" )
const auto requestId = [this, MAX_STRING_LENGTH](const std::string &turn_lane_string_) {
if (turn_lane_string_ == "")
return INVALID_LANE_STRINGID;
// requires https://github.com/cucumber/cucumber-js/issues/417
// remove this handling when the issue is contained
std::string turn_lane_string = turn_lane_string_;
for (auto &val : turn_lane_string)
if (val == '&')
val = '|';
const auto &lane_map_iterator = lane_map.find(turn_lane_string);
if (lane_map.end() == lane_map_iterator)
{
+5 -5
View File
@@ -113,7 +113,7 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
// traffic signals in the `traffic_lights` list, which EdgeData
// doesn't have access to.
const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end();
if( has_node_penalty )
if (has_node_penalty)
continue;
// Get distances before graph is modified
@@ -168,10 +168,10 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
return front;
return back;
};
graph.GetEdgeData(forward_e1).lane_string_id =
selectLaneID(graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id);
graph.GetEdgeData(reverse_e1).lane_string_id =
selectLaneID(graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id);
graph.GetEdgeData(forward_e1).lane_string_id = selectLaneID(
graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id);
graph.GetEdgeData(reverse_e1).lane_string_id = selectLaneID(
graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id);
// remove e2's (if bidir, otherwise only one)
graph.DeleteEdge(node_v, forward_e2);
+3 -6
View File
@@ -22,12 +22,9 @@ std::string toString(const ConnectedRoad &road)
result += " angle: ";
result += std::to_string(road.turn.angle);
result += " instruction: ";
result +=
std::to_string(static_cast<std::int32_t>(road.turn.instruction.type)) + " " +
std::to_string(static_cast<std::int32_t>(road.turn.instruction.direction_modifier)) + " " +
std::to_string(static_cast<std::int32_t>(road.turn.instruction.lane_tupel.lanes_in_turn)) +
" " + std::to_string(static_cast<std::int32_t>(
road.turn.instruction.lane_tupel.first_lane_from_the_right));
result += std::to_string(static_cast<std::int32_t>(road.turn.instruction.type)) + " " +
std::to_string(static_cast<std::int32_t>(road.turn.instruction.direction_modifier)) +
" " + std::to_string(static_cast<std::int32_t>(road.turn.lane_data_id));
return result;
}
@@ -1,5 +1,5 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/toolkit.hpp"
#include <algorithm>
@@ -114,9 +114,12 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
has_uturn_edge = true;
}
intersection.push_back(ConnectedRoad(
TurnOperation{onto_edge, angle, {TurnType::Invalid, DirectionModifier::UTurn}},
turn_is_valid));
intersection.push_back(
ConnectedRoad(TurnOperation{onto_edge,
angle,
{TurnType::Invalid, DirectionModifier::UTurn},
INVALID_LANE_DATAID},
turn_is_valid));
}
// We hit the case of a street leading into nothing-ness. Since the code here assumes that this
@@ -124,7 +127,9 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
if (!has_uturn_edge)
{
intersection.push_back(
{TurnOperation{via_eid, 0., {TurnType::Invalid, DirectionModifier::UTurn}}, false});
{TurnOperation{
via_eid, 0., {TurnType::Invalid, DirectionModifier::UTurn}, INVALID_LANE_DATAID},
false});
}
const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) {
@@ -373,11 +373,12 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
if (1 == node_based_graph.GetDirectedOutDegree(node_v))
{
// No turn possible.
if( intersection.size() == 2 )
if (intersection.size() == 2)
turn.instruction = TurnInstruction::NO_TURN();
else
{
turn.instruction.type = TurnType::Suppressed; //make sure to report intersection
turn.instruction.type =
TurnType::Suppressed; // make sure to report intersection
turn.instruction.direction_modifier = getTurnDirection(turn.angle);
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_discovery.hpp"
#include "extractor/guidance/constants.hpp"
namespace osrm
{
@@ -2,9 +2,9 @@
#include "util/simple_logger.hpp"
#include <algorithm>
#include <boost/assert.hpp>
#include <cstddef>
#include <utility>
#include <boost/assert.hpp>
namespace osrm
{
@@ -171,7 +171,6 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
has_left |= modifier == DirectionModifier::SharpLeft;
}
// find missing tag and augment neighboring, if possible
if (none_index == 0)
{
+5 -5
View File
@@ -52,8 +52,7 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
// count the number of lanes
const auto num_lanes = [](const std::string &turn_lane_string) {
return boost::numeric_cast<LaneID>(
std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1 +
std::count(turn_lane_string.begin(), turn_lane_string.end(), '&'));
std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1);
}(turn_lane_string);
const auto getNextTag = [](std::string &string, const char *separators) {
@@ -103,7 +102,7 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
// FIXME this is a cucumber workaround, since escaping does not work properly in
// cucumber.js (see https://github.com/cucumber/cucumber-js/issues/417). Needs to be
// changed to "|" only, when the bug is fixed
auto lane = getNextTag(turn_lane_string, "|&");
auto lane = getNextTag(turn_lane_string, "|");
setLaneData(lane_map, lane, lane_nr);
++lane_nr;
} while (lane_nr < num_lanes);
@@ -135,8 +134,9 @@ LaneDataVector::const_iterator findTag(const std::string &tag, const LaneDataVec
});
}
bool hasTag(const std::string &tag, const LaneDataVector &data){
return findTag(tag,data) != data.cend();
bool hasTag(const std::string &tag, const LaneDataVector &data)
{
return findTag(tag, data) != data.cend();
}
} // namespace lanes
+29 -24
View File
@@ -1,8 +1,8 @@
#include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_discovery.hpp"
#include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "extractor/guidance/turn_lane_augmentation.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "util/simple_logger.hpp"
#include "util/typedefs.hpp"
@@ -40,7 +40,7 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
}
/*
Turn lanes are given in the form of strings that closely correspond to the direction modifiers
Turn lanes are given in the form of strings that closely correspond to the direction modifiers
we use for our turn types. However, we still cannot simply perform a 1:1 assignment.
This function parses the turn_lane_strings of a format that describes an intersection as:
@@ -58,11 +58,9 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
*/
Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
const EdgeID via_edge,
Intersection intersection) const
Intersection intersection,
LaneDataIdMap &id_map) const
{
// initialize to invalid
for (auto &road : intersection)
road.turn.instruction.lane_tupel = {0, INVALID_LANEID};
const auto &data = node_based_graph.GetEdgeData(via_edge);
const auto turn_lane_string = data.lane_string_id != INVALID_LANE_STRINGID
? turn_lane_strings.GetNameForID(data.lane_string_id)
@@ -89,17 +87,15 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
const std::size_t possible_entries = getNumberOfTurns(intersection);
// merge does not justify an instruction
const bool has_merge_lane = (hasTag("merge_to_left", lane_data) ||
hasTag("merge_to_right", lane_data));
const bool has_merge_lane =
(hasTag("merge_to_left", lane_data) || hasTag("merge_to_right", lane_data));
// Dead end streets that don't have any left-tag. This can happen due to the fallbacks for
// broken data/barriers.
const bool has_non_usable_u_turn =
(intersection[0].entry_allowed && !hasTag("none", lane_data) &&
!hasTag("left", lane_data) &&
!hasTag("sharp_left", lane_data) &&
!hasTag("reverse", lane_data) &&
lane_data.size() + 1 == possible_entries);
!hasTag("left", lane_data) && !hasTag("sharp_left", lane_data) &&
!hasTag("reverse", lane_data) && lane_data.size() + 1 == possible_entries);
if (has_merge_lane || has_non_usable_u_turn)
return std::move(intersection);
@@ -118,7 +114,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
if (is_simple)
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, data.lane_string_id, id_map);
}
// if the intersection is not simple but we have lane data, we check for intersections with
// middle islands. We have two cases. The first one is providing lane data on the current
@@ -138,7 +135,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
isSimpleIntersection(lane_data, intersection))
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, data.lane_string_id, id_map);
}
}
}
@@ -148,7 +146,7 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
{
// acquire the lane data of a previous segment and, if possible, use it for the current
// intersection.
return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection));
return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection), id_map);
}
return std::move(intersection);
@@ -158,7 +156,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
// actually take the turn, we need to look back to the edge we drove onto the intersection with.
Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
const EdgeID via_edge,
Intersection intersection) const
Intersection intersection,
LaneDataIdMap &id_map) const
{
NodeID previous_node = SPECIAL_NODEID;
Intersection previous_intersection;
@@ -176,6 +175,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
previous_id,
previous_intersection))
return "";
BOOST_ASSERT(previous_id != SPECIAL_EDGEID);
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
auto previous_string = previous_data.lane_string_id != INVALID_LANE_STRINGID
@@ -204,11 +204,13 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
if (lane_data.empty())
return std::move(intersection);
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
const auto is_simple = isSimpleIntersection(lane_data, intersection);
if (is_simple)
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
}
else
{
@@ -227,14 +229,14 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
isSimpleIntersection(lane_data, intersection))
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
}
}
}
return std::move(intersection);
}
/* A simple intersection does not depend on the next intersection coming up. This is important
* for turn lanes, since traffic signals and/or segregated a intersection can influence the
* interpretation of turn-lanes at a given turn.
@@ -296,7 +298,7 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
}
if (num_turns > lane_data.size() && intersection[0].entry_allowed &&
!( hasTag("reverse", lane_data) ||
!(hasTag("reverse", lane_data) ||
(lane_data.back().tag != "left" && lane_data.back().tag != "sharp_left")))
{
return false;
@@ -417,7 +419,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
return {turn_lane_data, {}};
}
std::size_t none_index = std::distance(turn_lane_data.begin(),findTag("none", turn_lane_data));
std::size_t none_index = std::distance(turn_lane_data.begin(), findTag("none", turn_lane_data));
// if the turn lanes are pull forward, we might have to add an additional straight tag
// did we find something that matches against the straightmost road?
@@ -486,7 +488,9 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
}
Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data) const
const LaneDataVector &lane_data,
const LaneStringID lane_string_id,
LaneDataIdMap &id_map) const
{
if (lane_data.empty() || !canMatchTrivially(intersection, lane_data))
return std::move(intersection);
@@ -496,7 +500,8 @@ Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection
return boost::starts_with(data.tag, "merge");
}) == 0);
return triviallyMatchLanesToTurns(std::move(intersection), lane_data, node_based_graph);
return triviallyMatchLanesToTurns(
std::move(intersection), lane_data, node_based_graph, lane_string_id, id_map);
}
} // namespace lanes
+26 -6
View File
@@ -1,8 +1,11 @@
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/guidance/toolkit.hpp"
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <functional>
namespace osrm
{
@@ -169,9 +172,27 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph)
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneStringID lane_string_id,
LaneDataIdMap &lane_data_to_id)
{
std::size_t road_index = 1, lane = 0;
const auto matchRoad = [&](ConnectedRoad &road, const TurnLaneData &data) {
LaneTupelIdPair key{{LaneID(data.to - data.from + 1), data.from}, lane_string_id};
auto lane_data_id = boost::numeric_cast<LaneDataID>(lane_data_to_id.size());
const auto it = lane_data_to_id.find(key);
if (it == lane_data_to_id.end())
lane_data_to_id.insert({key, lane_data_id});
else
lane_data_id = it->second;
// set lane id instead after the switch:
road.turn.lane_data_id = lane_data_id;
};
for (; road_index < intersection.size() && lane < lane_data.size(); ++road_index)
{
if (intersection[road_index].entry_allowed)
@@ -185,8 +206,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
if (TurnType::Suppressed == intersection[road_index].turn.instruction.type)
intersection[road_index].turn.instruction.type = TurnType::UseLane;
intersection[road_index].turn.instruction.lane_tupel = {
LaneID(lane_data[lane].to - lane_data[lane].from + 1), lane_data[lane].from};
matchRoad(intersection[road_index], lane_data[lane]);
++lane;
}
}
@@ -209,8 +229,8 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
intersection[u_turn].entry_allowed = true;
intersection[u_turn].turn.instruction.type = TurnType::Turn;
intersection[u_turn].turn.instruction.direction_modifier = DirectionModifier::UTurn;
intersection[u_turn].turn.instruction.lane_tupel = {
LaneID(lane_data.back().to - lane_data.back().from + 1), lane_data.back().from};
matchRoad(intersection[u_turn], lane_data.back());
}
return std::move(intersection);
}