adjust testscases for collapse of use lane
This commit is contained in:
@@ -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"
|
||||
|
||||
+43
-28
@@ -47,6 +47,7 @@
|
||||
#include <iostream>
|
||||
#include <numeric> //partial_sum
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -56,6 +57,36 @@ namespace osrm
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
std::tuple<std::vector<std::uint32_t>, std::vector<guidance::TurnLaneType::Mask>>
|
||||
transformTurnLaneMapIntoArrays(const guidance::LaneDescriptionMap &turn_lane_map)
|
||||
{
|
||||
// could use some additional capacity? To avoid a copy during processing, though small data so
|
||||
// probably not that important.
|
||||
//
|
||||
// From the map, we construct an adjacency array that allows access from all IDs to the list of
|
||||
// associated Turn Lane Masks.
|
||||
//
|
||||
// turn lane offsets points into the locations of the turn_lane_masks array. We use a standard
|
||||
// adjacency array like structure to store the turn lane masks.
|
||||
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.size() + 2); // empty ID + sentinel
|
||||
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
|
||||
turn_lane_offsets[entry->second + 1] = entry->first.size();
|
||||
|
||||
// inplace prefix sum
|
||||
std::partial_sum(turn_lane_offsets.begin(), turn_lane_offsets.end(), turn_lane_offsets.begin());
|
||||
|
||||
// allocate the current masks
|
||||
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks(turn_lane_offsets.back());
|
||||
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
|
||||
std::copy(entry->first.begin(),
|
||||
entry->first.end(),
|
||||
turn_lane_masks.begin() + turn_lane_offsets[entry->second]);
|
||||
return std::make_tuple(std::move(turn_lane_offsets), std::move(turn_lane_masks));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* TODO: Refactor this function into smaller functions for better readability.
|
||||
*
|
||||
@@ -94,8 +125,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
||||
util::SimpleLogger().Write() << "Threads: " << number_of_threads;
|
||||
|
||||
ExtractionContainers extraction_containers;
|
||||
auto extractor_callbacks =
|
||||
util::make_unique<ExtractorCallbacks>(extraction_containers, turn_lane_map);
|
||||
auto extractor_callbacks = util::make_unique<ExtractorCallbacks>(extraction_containers);
|
||||
|
||||
const osmium::io::File input_file(config.input_path.string());
|
||||
osmium::io::Reader reader(input_file);
|
||||
@@ -185,6 +215,9 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
|
||||
<< number_of_ways << " ways, and " << number_of_relations
|
||||
<< " relations";
|
||||
|
||||
// take control over the turn lane map
|
||||
turn_lane_map = extractor_callbacks->moveOutLaneDescriptionMap();
|
||||
|
||||
extractor_callbacks.reset();
|
||||
|
||||
if (extraction_containers.all_edges_list.empty())
|
||||
@@ -447,19 +480,9 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
|
||||
// could use some additional capacity? To avoid a copy during processing, though small data so
|
||||
// probably not that important.
|
||||
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.size() + 2); // empty ID + sentinel
|
||||
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
|
||||
turn_lane_offsets[entry->second + 1] = entry->first.size();
|
||||
|
||||
// inplace prefix sum
|
||||
std::partial_sum(turn_lane_offsets.begin(), turn_lane_offsets.end(), turn_lane_offsets.begin());
|
||||
|
||||
// allocate the current masks
|
||||
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks(turn_lane_offsets.back());
|
||||
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
|
||||
std::copy(entry->first.begin(),
|
||||
entry->first.end(),
|
||||
turn_lane_masks.begin() + turn_lane_offsets[entry->second]);
|
||||
std::vector<std::uint32_t> turn_lane_offsets;
|
||||
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
|
||||
std::tie(turn_lane_offsets, turn_lane_masks) = transformTurnLaneMapIntoArrays(turn_lane_map);
|
||||
|
||||
EdgeBasedGraphFactory edge_based_graph_factory(
|
||||
node_based_graph,
|
||||
@@ -649,24 +672,16 @@ void Extractor::WriteIntersectionClassificationData(
|
||||
void Extractor::WriteTurnLaneData(const std::string &turn_lane_file) const
|
||||
{
|
||||
// Write the turn lane data to file
|
||||
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.size() + 2); // empty ID + sentinel
|
||||
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
|
||||
turn_lane_offsets[entry->second + 1] = entry->first.size();
|
||||
|
||||
// inplace prefix sum
|
||||
std::partial_sum(turn_lane_offsets.begin(), turn_lane_offsets.end(), turn_lane_offsets.begin());
|
||||
|
||||
// allocate the current masks
|
||||
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks(turn_lane_offsets.back());
|
||||
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
|
||||
std::copy(entry->first.begin(),
|
||||
entry->first.end(),
|
||||
turn_lane_masks.begin() + turn_lane_offsets[entry->second]);
|
||||
std::vector<std::uint32_t> turn_lane_offsets;
|
||||
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
|
||||
std::tie(turn_lane_offsets, turn_lane_masks) = transformTurnLaneMapIntoArrays(turn_lane_map);
|
||||
|
||||
util::SimpleLogger().Write() << "Writing turn lane masks...";
|
||||
TIMER_START(turn_lane_timer);
|
||||
|
||||
std::ofstream ofs(turn_lane_file, std::ios::binary);
|
||||
if (!ofs)
|
||||
throw osrm::util::exception("Failed to open " + turn_lane_file + " for writing.");
|
||||
|
||||
if (!util::serializeVector(ofs, turn_lane_offsets))
|
||||
{
|
||||
|
||||
@@ -31,15 +31,13 @@ namespace extractor
|
||||
using TurnLaneDescription = guidance::TurnLaneDescription;
|
||||
namespace TurnLaneType = guidance::TurnLaneType;
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers,
|
||||
guidance::LaneDescriptionMap &lane_description_map)
|
||||
: lane_description_map(lane_description_map), external_memory(extraction_containers)
|
||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers)
|
||||
: external_memory(extraction_containers)
|
||||
{
|
||||
// we reserved 0, 1, 2 for the empty case
|
||||
string_map[MapKey("", "")] = 0;
|
||||
|
||||
// The map should be empty before we start initializing it
|
||||
BOOST_ASSERT(lane_description_map.empty());
|
||||
lane_description_map[TurnLaneDescription()] = 0;
|
||||
}
|
||||
|
||||
@@ -395,5 +393,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
|
||||
}
|
||||
}
|
||||
|
||||
guidance::LaneDescriptionMap &&ExtractorCallbacks::moveOutLaneDescriptionMap()
|
||||
{
|
||||
return std::move(lane_description_map);
|
||||
}
|
||||
}
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/turn_discovery.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
||||
@@ -283,27 +283,18 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
|
||||
// we have to reduce it, assigning it to neighboring turns
|
||||
else if (connection_count < lane_data.size())
|
||||
{
|
||||
if( connection_count+1 < lane_data.size() ){
|
||||
std::cout << "[error] failed assignment" << std::endl;
|
||||
util::guidance::print(lane_data);
|
||||
std::cout << "Intersection:\n";
|
||||
for( auto road : intersection )
|
||||
std::cout << "\t" << toString(road) << std::endl;
|
||||
}
|
||||
// a pgerequisite is simple turns. Larger differences should not end up here
|
||||
// an additional line at the side is only reasonable if it is targeting public
|
||||
// service vehicles. Otherwise, we should not have it
|
||||
//
|
||||
// TODO(mokob): #2730 have a look please
|
||||
// BOOST_ASSERT(connection_count + 1 == lane_data.size());
|
||||
//
|
||||
if (connection_count + 1 != lane_data.size())
|
||||
if (connection_count + 1 == lane_data.size())
|
||||
{
|
||||
// skip broken intersections
|
||||
lane_data = mergeNoneTag(none_index, std::move(lane_data));
|
||||
}
|
||||
else
|
||||
{
|
||||
lane_data = mergeNoneTag(none_index, std::move(lane_data));
|
||||
// This represents a currently unhandled case. It should not even get here, but to be
|
||||
// sure we return nevertheless.
|
||||
return lane_data;
|
||||
}
|
||||
}
|
||||
// we have to rename and possibly augment existing ones. The pure count remains the
|
||||
|
||||
@@ -154,27 +154,6 @@ bool hasTag(const TurnLaneType::Mask tag, const LaneDataVector &data)
|
||||
return findTag(tag, data) != data.cend();
|
||||
}
|
||||
|
||||
bool isSubsetOf(const LaneDataVector &subset_candidate, const LaneDataVector &superset_candidate)
|
||||
{
|
||||
auto location = superset_candidate.begin();
|
||||
for (const auto entry : subset_candidate)
|
||||
{
|
||||
location = std::find_if(
|
||||
location, superset_candidate.end(), [entry](const TurnLaneData &lane_data) {
|
||||
return lane_data.tag == entry.tag;
|
||||
});
|
||||
|
||||
if (location == superset_candidate.end())
|
||||
return false;
|
||||
|
||||
// compare the number of lanes TODO this might have be to be revisited for situations where
|
||||
// a sliproad widens into multiple lanes
|
||||
if ((location->to - location->from) != (entry.to - entry.from))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace lanes
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "util/debug.hpp"
|
||||
|
||||
#include "extractor/guidance/turn_lane_handler.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/turn_discovery.hpp"
|
||||
#include "extractor/guidance/turn_lane_augmentation.hpp"
|
||||
#include "extractor/guidance/turn_lane_handler.hpp"
|
||||
#include "extractor/guidance/turn_lane_matcher.hpp"
|
||||
#include "util/simple_logger.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
@@ -33,8 +31,6 @@ std::size_t getNumberOfTurns(const Intersection &intersection)
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const constexpr char *TurnLaneHandler::scenario_names[TurnLaneScenario::NUM_SCENARIOS];
|
||||
|
||||
TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
std::vector<std::uint32_t> &turn_lane_offsets,
|
||||
std::vector<TurnLaneType::Mask> &turn_lane_masks,
|
||||
@@ -46,18 +42,12 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
|
||||
turn_lane_masks(turn_lane_masks), lane_description_map(lane_description_map),
|
||||
node_info_list(node_info_list), turn_analysis(turn_analysis), id_map(id_map)
|
||||
{
|
||||
count_handled = new unsigned;
|
||||
count_called = new unsigned;
|
||||
*count_handled = *count_called = 0;
|
||||
}
|
||||
|
||||
TurnLaneHandler::~TurnLaneHandler()
|
||||
{
|
||||
std::cout << "Handled: " << *count_handled << " of " << *count_called
|
||||
<< " lanes: " << (double)(*count_handled * 100) / (*count_called) << " %."
|
||||
<< std::endl;
|
||||
delete count_called;
|
||||
delete count_handled;
|
||||
std::cout << "Handled: " << count_handled << " of " << count_called
|
||||
<< " lanes: " << (double)(count_handled * 100) / (count_called) << " %." << std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -107,8 +97,8 @@ TurnLaneHandler::assignTurnLanes(const NodeID at, const EdgeID via_edge, Interse
|
||||
previous_lane_data,
|
||||
previous_description_id);
|
||||
|
||||
if (scenario != TurnLaneHandler::NONE)
|
||||
(*count_called)++;
|
||||
if (scenario != TurnLaneScenario::NONE)
|
||||
count_called++;
|
||||
|
||||
switch (scenario)
|
||||
{
|
||||
@@ -140,44 +130,26 @@ TurnLaneHandler::assignTurnLanes(const NodeID at, const EdgeID via_edge, Interse
|
||||
// case TurnLaneScenario::UNKNOWN:
|
||||
// case TurnLaneScenario::NONE:
|
||||
// case TurnLaneScenario::INVALID:
|
||||
{
|
||||
/*
|
||||
static int print_count = 0;
|
||||
if (TurnLaneScenario::NONE != scenario && print_count++ < 10)
|
||||
{
|
||||
std::cout << "[Unhandled] " << (int)lane_description_id << " -- "
|
||||
<< (int)previous_description_id << "\n"
|
||||
<< std::endl;
|
||||
util::guidance::printTurnAssignmentData(
|
||||
at, lane_data, intersection, node_info_list);
|
||||
|
||||
if (previous_node != SPECIAL_NODEID)
|
||||
util::guidance::printTurnAssignmentData(
|
||||
previous_node, previous_lane_data, previous_intersection, node_info_list);
|
||||
}
|
||||
*/
|
||||
}
|
||||
return intersection;
|
||||
}
|
||||
}
|
||||
|
||||
// Find out which scenario we have to handle
|
||||
TurnLaneHandler::TurnLaneScenario
|
||||
TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
const EdgeID via_edge,
|
||||
const Intersection &intersection,
|
||||
// Output Variables
|
||||
LaneDescriptionID &lane_description_id,
|
||||
LaneDataVector &lane_data,
|
||||
NodeID &previous_node,
|
||||
EdgeID &previous_via_edge,
|
||||
Intersection &previous_intersection,
|
||||
LaneDataVector &previous_lane_data,
|
||||
LaneDescriptionID &previous_description_id)
|
||||
TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
const EdgeID via_edge,
|
||||
const Intersection &intersection,
|
||||
// Output Variables
|
||||
LaneDescriptionID &lane_description_id,
|
||||
LaneDataVector &lane_data,
|
||||
NodeID &previous_node,
|
||||
EdgeID &previous_via_edge,
|
||||
Intersection &previous_intersection,
|
||||
LaneDataVector &previous_lane_data,
|
||||
LaneDescriptionID &previous_description_id)
|
||||
{
|
||||
// if only a uturn exists, there is nothing we can do
|
||||
if (intersection.size() == 1)
|
||||
return TurnLaneHandler::NONE;
|
||||
return TurnLaneScenario::NONE;
|
||||
|
||||
extractLaneData(via_edge, lane_description_id, lane_data);
|
||||
|
||||
@@ -199,7 +171,7 @@ TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE));
|
||||
|
||||
if (is_going_straight_and_turns_continue)
|
||||
return TurnLaneHandler::NONE;
|
||||
return TurnLaneScenario::NONE;
|
||||
|
||||
// if we see an invalid conversion, we stop immediately
|
||||
if (lane_description_id != INVALID_LANE_DESCRIPTIONID && lane_data.empty())
|
||||
@@ -694,7 +666,7 @@ Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection
|
||||
!hasTag(TurnLaneType::none | TurnLaneType::merge_to_left | TurnLaneType::merge_to_right,
|
||||
lane_data));
|
||||
|
||||
(*count_handled)++;
|
||||
count_handled++;
|
||||
|
||||
return triviallyMatchLanesToTurns(
|
||||
std::move(intersection), lane_data, node_based_graph, lane_description_id, id_map);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#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>
|
||||
@@ -102,11 +102,11 @@ bool isValidMatch(const TurnLaneType::Mask tag, const TurnInstruction instructio
|
||||
return false;
|
||||
}
|
||||
|
||||
double getMatchingQuality( const TurnLaneType::Mask tag, const ConnectedRoad &road)
|
||||
double getMatchingQuality(const TurnLaneType::Mask tag, const ConnectedRoad &road)
|
||||
{
|
||||
const constexpr double idealized_turn_angles[] = {0, 35, 90, 135, 180, 225, 270, 315};
|
||||
const auto idealized_angle = idealized_turn_angles[getMatchingModifier(tag)];
|
||||
return angularDeviation(idealized_angle,road.turn.angle);
|
||||
return angularDeviation(idealized_angle, road.turn.angle);
|
||||
}
|
||||
|
||||
// Every tag is somewhat idealized in form of the expected angle. A through lane should go straight
|
||||
@@ -116,21 +116,21 @@ double getMatchingQuality( const TurnLaneType::Mask tag, const ConnectedRoad &ro
|
||||
typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask tag,
|
||||
const Intersection &intersection)
|
||||
{
|
||||
return std::min_element(
|
||||
intersection.begin(),
|
||||
intersection.end(),
|
||||
[tag](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
// prefer valid matches
|
||||
if (isValidMatch(tag, lhs.turn.instruction) != isValidMatch(tag, rhs.turn.instruction))
|
||||
return isValidMatch(tag, lhs.turn.instruction);
|
||||
return std::min_element(intersection.begin(),
|
||||
intersection.end(),
|
||||
[tag](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
// prefer valid matches
|
||||
if (isValidMatch(tag, lhs.turn.instruction) !=
|
||||
isValidMatch(tag, rhs.turn.instruction))
|
||||
return isValidMatch(tag, lhs.turn.instruction);
|
||||
|
||||
// if the entry allowed flags don't match, we select the one with
|
||||
// entry allowed set to true
|
||||
if (lhs.entry_allowed != rhs.entry_allowed)
|
||||
return lhs.entry_allowed;
|
||||
// if the entry allowed flags don't match, we select the one with
|
||||
// entry allowed set to true
|
||||
if (lhs.entry_allowed != rhs.entry_allowed)
|
||||
return lhs.entry_allowed;
|
||||
|
||||
return getMatchingQuality(tag,lhs) < getMatchingQuality(tag,rhs);
|
||||
});
|
||||
return getMatchingQuality(tag, lhs) < getMatchingQuality(tag, rhs);
|
||||
});
|
||||
}
|
||||
|
||||
// Reverse is a special case, because it requires access to the leftmost tag. It has its own
|
||||
@@ -138,8 +138,8 @@ typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask tag
|
||||
// by default in OSRM. Therefor we cannot check whether a turn is allowed, since it could be
|
||||
// possible that it is forbidden. In addition, the best u-turn angle does not necessarily represent
|
||||
// the u-turn, since it could be a sharp-left turn instead on a road with a middle island.
|
||||
typename Intersection::const_iterator
|
||||
findBestMatchForReverse(const TurnLaneType::Mask neighbor_tag, const Intersection &intersection)
|
||||
typename Intersection::const_iterator findBestMatchForReverse(const TurnLaneType::Mask neighbor_tag,
|
||||
const Intersection &intersection)
|
||||
{
|
||||
const auto neighbor_itr = findBestMatch(neighbor_tag, intersection);
|
||||
if (neighbor_itr + 1 == intersection.cend())
|
||||
@@ -159,7 +159,7 @@ findBestMatchForReverse(const TurnLaneType::Mask neighbor_tag, const Intersectio
|
||||
if (lhs.entry_allowed != rhs.entry_allowed)
|
||||
return lhs.entry_allowed;
|
||||
|
||||
return getMatchingQuality(tag,lhs) < getMatchingQuality(tag,rhs);
|
||||
return getMatchingQuality(tag, lhs) < getMatchingQuality(tag, rhs);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user