Allow users to specify a class for each way

This adds the ability to mark ways with a user-defined
class in the profile. This class information will be included
in the response as property of the RouteStep object.
This commit is contained in:
Patrick Niklaus
2017-06-27 22:01:05 +00:00
committed by Patrick Niklaus
parent d52d530cbe
commit 44739f2dc3
39 changed files with 614 additions and 57 deletions
+12
View File
@@ -265,6 +265,18 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver));
route_step.values["geometry"] = std::move(geometry);
if (!step.classes.empty())
{
util::json::Array classes;
classes.values.reserve(step.classes.size());
std::transform(
step.classes.begin(),
step.classes.end(),
std::back_inserter(classes.values),
[](const std::string &class_name) { return util::json::String{class_name}; });
route_step.values["classes"] = std::move(classes);
}
util::json::Array intersections;
intersections.values.reserve(step.intersections.size());
std::transform(step.intersections.begin(),
+1
View File
@@ -486,6 +486,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
auto &new_next_to_last = *(steps.end() - 2);
next_to_last_step.AdaptStepSignage(new_next_to_last);
next_to_last_step.mode = new_next_to_last.mode;
next_to_last_step.classes = new_next_to_last.classes;
// the geometry indices of the last step are already correct;
}
else if (util::coordinate_calculation::haversineDistance(
+4 -2
View File
@@ -148,13 +148,15 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
m_edge_based_node_container.SetData(forward_data.edge_id,
GeometryID{packed_geometry_id, true},
forward_data.name_id,
forward_data.travel_mode);
forward_data.travel_mode,
forward_data.classes);
if (reverse_data.edge_id != SPECIAL_EDGEID)
{
m_edge_based_node_container.SetData(reverse_data.edge_id,
GeometryID{packed_geometry_id, false},
reverse_data.name_id,
reverse_data.travel_mode);
reverse_data.travel_mode,
reverse_data.classes);
}
// Add segments of edge-based nodes
+25 -8
View File
@@ -63,6 +63,21 @@ namespace osrm
namespace extractor
{
namespace
{
// Converts the class name map into a fixed mapping of index to name
void SetClassNames(const ExtractorCallbacks::ClassesMap &classes_map,
ProfileProperties &profile_properties)
{
for (const auto &pair : classes_map)
{
auto range = getClassIndexes(pair.second);
BOOST_ASSERT(range.size() == 1);
profile_properties.SetClassName(range.front(), pair.first);
}
}
}
/**
* TODO: Refactor this function into smaller functions for better readability.
*
@@ -201,8 +216,13 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
TIMER_START(parsing);
ExtractionContainers extraction_containers;
auto extractor_callbacks = std::make_unique<ExtractorCallbacks>(
extraction_containers, scripting_environment.GetProfileProperties());
ExtractorCallbacks::ClassesMap classes_map;
guidance::LaneDescriptionMap turn_lane_map;
auto extractor_callbacks =
std::make_unique<ExtractorCallbacks>(extraction_containers,
classes_map,
turn_lane_map,
scripting_environment.GetProfileProperties());
// setup raster sources
scripting_environment.SetupSources();
@@ -304,10 +324,6 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
util::Log() << "Raw input contains " << number_of_nodes << " nodes, " << number_of_ways
<< " ways, and " << number_of_relations << " relations";
// take control over the turn lane map
guidance::LaneDescriptionMap turn_lane_map;
turn_lane_map.data = extractor_callbacks->moveOutLaneDescriptionMap().data;
extractor_callbacks.reset();
if (extraction_containers.all_edges_list.empty())
@@ -321,8 +337,9 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
config.restriction_file_name,
config.names_file_name);
files::writeProfileProperties(config.profile_properties_output_path,
scripting_environment.GetProfileProperties());
auto profile_properties = scripting_environment.GetProfileProperties();
SetClassNames(classes_map, profile_properties);
files::writeProfileProperties(config.profile_properties_output_path, profile_properties);
TIMER_STOP(extracting);
util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s";
+39 -6
View File
@@ -34,8 +34,11 @@ using TurnLaneDescription = guidance::TurnLaneDescription;
namespace TurnLaneType = guidance::TurnLaneType;
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers_,
std::unordered_map<std::string, ClassData> &classes_map,
guidance::LaneDescriptionMap &lane_description_map,
const ProfileProperties &properties)
: external_memory(extraction_containers_),
: external_memory(extraction_containers_), classes_map(classes_map),
lane_description_map(lane_description_map),
fallback_to_duration(properties.fallback_to_duration),
force_split_edges(properties.force_split_edges)
{
@@ -175,6 +178,38 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
}
}
const auto classStringToMask = [this](const std::string &class_name) {
auto iter = classes_map.find(class_name);
if (iter == classes_map.end())
{
if (classes_map.size() > MAX_CLASS_INDEX)
{
throw util::exception("Maximum number of classes if " +
std::to_string(MAX_CLASS_INDEX + 1));
}
ClassData class_mask = 1u << classes_map.size();
classes_map[class_name] = class_mask;
return class_mask;
}
else
{
return iter->second;
}
};
const auto classesToMask = [&](const auto &classes) {
ClassData mask = 0;
for (const auto &name_and_flag : classes)
{
if (name_and_flag.second)
{
mask |= classStringToMask(name_and_flag.first);
}
}
return mask;
};
const ClassData forward_classes = classesToMask(parsed_way.forward_classes);
const ClassData backward_classes = classesToMask(parsed_way.backward_classes);
const auto laneStringToDescription = [](const std::string &lane_string) -> TurnLaneDescription {
if (lane_string.empty())
return {};
@@ -330,7 +365,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
(force_split_edges || (parsed_way.forward_rate != parsed_way.backward_rate) ||
(parsed_way.forward_speed != parsed_way.backward_speed) ||
(parsed_way.forward_travel_mode != parsed_way.backward_travel_mode) ||
(turn_lane_id_forward != turn_lane_id_backward));
(turn_lane_id_forward != turn_lane_id_backward) || (forward_classes != backward_classes));
if (in_forward_direction)
{ // add (forward) segments or (forward,backward) for non-split edges in backward direction
@@ -352,6 +387,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.forward_restricted,
split_edge,
parsed_way.forward_travel_mode,
forward_classes,
turn_lane_id_forward,
road_classification,
{}));
@@ -378,6 +414,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
parsed_way.backward_restricted,
split_edge,
parsed_way.backward_travel_mode,
backward_classes,
turn_lane_id_backward,
road_classification,
{}));
@@ -399,9 +436,5 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
OSMNodeID{static_cast<std::uint64_t>(nodes.back().ref())}});
}
guidance::LaneDescriptionMap &&ExtractorCallbacks::moveOutLaneDescriptionMap()
{
return std::move(lane_description_map);
}
} // namespace extractor
} // namespace osrm
@@ -75,9 +75,6 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
const ConnectedRoad &road) const
{
const auto type = findBasicTurnType(via_edge, road);
// handle travel modes:
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode;
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode;
if (type == TurnType::OnRamp)
{
return {TurnType::OnRamp, getTurnDirection(road.angle)};
@@ -87,6 +84,15 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
{
return {TurnType::Continue, DirectionModifier::UTurn};
}
// handle travel modes:
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode;
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode;
const auto in_classes = node_based_graph.GetEdgeData(via_edge).classes;
const auto out_classes = node_based_graph.GetEdgeData(road.eid).classes;
// if we just lose class flags we don't want to notify
const auto needs_notification = in_mode != out_mode || !isSubset(out_classes, in_classes);
if (type == TurnType::Turn)
{
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
@@ -141,14 +147,14 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
}
else
{
return {in_mode == out_mode ? TurnType::NewName : TurnType::Notification,
return {needs_notification ? TurnType::Notification : TurnType::NewName,
getTurnDirection(road.angle)};
}
}
// name has not changed, suppress a turn here or indicate mode change
else
{
if (in_mode != out_mode)
if (needs_notification)
return {TurnType::Notification, getTurnDirection(road.angle)};
else
return {num_roads == 2 ? TurnType::NoTurn : TurnType::Suppressed,
@@ -156,7 +162,7 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
}
}
BOOST_ASSERT(type == TurnType::Continue);
if (in_mode != out_mode)
if (needs_notification)
{
return {TurnType::Notification, getTurnDirection(road.angle)};
}
@@ -342,6 +342,10 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
&ExtractionWay::weight,
"road_classification",
&ExtractionWay::road_classification,
"forward_classes",
&ExtractionWay::forward_classes,
"backward_classes",
&ExtractionWay::backward_classes,
"forward_mode",
sol::property([](const ExtractionWay &way) { return way.forward_travel_mode; },
[](ExtractionWay &way, TravelMode mode) { way.forward_travel_mode = mode; }),
+9 -1
View File
@@ -11,6 +11,7 @@
#include "customizer/edge_based_graph.hpp"
#include "extractor/class_data.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/edge_based_edge.hpp"
#include "extractor/files.hpp"
@@ -253,6 +254,7 @@ void Storage::PopulateLayout(DataLayout &layout)
layout.SetBlockSize<NameID>(DataLayout::NAME_ID_LIST, nodes_number);
layout.SetBlockSize<ComponentID>(DataLayout::COMPONENT_ID_LIST, nodes_number);
layout.SetBlockSize<extractor::TravelMode>(DataLayout::TRAVEL_MODE_LIST, nodes_number);
layout.SetBlockSize<extractor::ClassData>(DataLayout::CLASSES_LIST, nodes_number);
}
if (boost::filesystem::exists(config.hsgr_data_path))
@@ -614,10 +616,16 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
util::vector_view<extractor::TravelMode> travel_modes(
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
auto classes_list_ptr = layout.GetBlockPtr<extractor::ClassData, true>(
memory_ptr, storage::DataLayout::CLASSES_LIST);
util::vector_view<extractor::ClassData> classes(
classes_list_ptr, layout.num_entries[storage::DataLayout::CLASSES_LIST]);
extractor::EdgeBasedNodeDataView node_data(std::move(geometry_ids),
std::move(name_ids),
std::move(component_ids),
std::move(travel_modes));
std::move(travel_modes),
std::move(classes));
extractor::files::readNodeData(config.edge_based_nodes_data_path, node_data);
}