Allow specifing a weight for routing that is independent of duration
This commit is contained in:
committed by
Patrick Niklaus
parent
e463733138
commit
279f8aabfb
@@ -4,6 +4,7 @@
|
||||
#include "extractor/extraction_node.hpp"
|
||||
#include "extractor/extraction_way.hpp"
|
||||
#include "extractor/guidance/road_classification.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/restriction.hpp"
|
||||
|
||||
#include "util/for_each_pair.hpp"
|
||||
@@ -18,6 +19,7 @@
|
||||
|
||||
#include "osrm/coordinate.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
@@ -31,8 +33,9 @@ namespace extractor
|
||||
using TurnLaneDescription = guidance::TurnLaneDescription;
|
||||
namespace TurnLaneType = guidance::TurnLaneType;
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers)
|
||||
: external_memory(extraction_containers)
|
||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers_,
|
||||
const ProfileProperties &properties)
|
||||
: external_memory(extraction_containers_), fallback_to_duration(properties.fallback_to_duration)
|
||||
{
|
||||
// we reserved 0, 1, 2, 3 for the empty case
|
||||
string_map[MapKey("", "", "", "")] = 0;
|
||||
@@ -80,16 +83,18 @@ void ExtractorCallbacks::ProcessRestriction(
|
||||
*/
|
||||
void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const ExtractionWay &parsed_way)
|
||||
{
|
||||
if (((0 >= parsed_way.forward_speed) ||
|
||||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode)) &&
|
||||
((0 >= parsed_way.backward_speed) ||
|
||||
(TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode)) &&
|
||||
(0 >= parsed_way.duration))
|
||||
if ((parsed_way.forward_travel_mode == TRAVEL_MODE_INACCESSIBLE &&
|
||||
parsed_way.backward_travel_mode == TRAVEL_MODE_INACCESSIBLE) ||
|
||||
(parsed_way.forward_speed <= 0 && parsed_way.backward_speed <= 0 &&
|
||||
parsed_way.duration <= 0) ||
|
||||
(!fallback_to_duration && parsed_way.forward_rate <= 0 && parsed_way.backward_rate <= 0 &&
|
||||
parsed_way.weight <= 0))
|
||||
{ // Only true if the way is specified by the speed profile
|
||||
return;
|
||||
}
|
||||
|
||||
if (input_way.nodes().size() <= 1)
|
||||
const auto &nodes = input_way.nodes();
|
||||
if (nodes.size() <= 1)
|
||||
{ // safe-guard against broken data
|
||||
return;
|
||||
}
|
||||
@@ -97,46 +102,63 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
if (std::numeric_limits<decltype(input_way.id())>::max() == input_way.id())
|
||||
{
|
||||
util::Log(logDEBUG) << "found bogus way with id: " << input_way.id() << " of size "
|
||||
<< input_way.nodes().size();
|
||||
<< nodes.size();
|
||||
return;
|
||||
}
|
||||
|
||||
InternalExtractorEdge::DurationData forward_duration_data;
|
||||
InternalExtractorEdge::DurationData backward_duration_data;
|
||||
InternalExtractorEdge::WeightData forward_weight_data;
|
||||
InternalExtractorEdge::WeightData backward_weight_data;
|
||||
|
||||
if (0 < parsed_way.duration)
|
||||
{
|
||||
const unsigned num_edges = (input_way.nodes().size() - 1);
|
||||
// FIXME We devide by the numer of nodes here, but should rather consider
|
||||
// the length of each segment. We would eigther have to compute the length
|
||||
// of the whole way here (we can't: no node coordinates) or push that back
|
||||
// to the container and keep a reference to the way.
|
||||
forward_weight_data.duration = parsed_way.duration / num_edges;
|
||||
forward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION;
|
||||
backward_weight_data.duration = parsed_way.duration / num_edges;
|
||||
backward_weight_data.type = InternalExtractorEdge::WeightType::WAY_DURATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parsed_way.forward_speed > 0 &&
|
||||
parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
||||
const auto toValueByEdgeOrByMeter =
|
||||
[&nodes](const double by_way, const double by_meter) -> detail::ByEdgeOrByMeterValue {
|
||||
if (by_way > 0)
|
||||
{
|
||||
forward_weight_data.speed = parsed_way.forward_speed;
|
||||
forward_weight_data.type = InternalExtractorEdge::WeightType::SPEED;
|
||||
// FIXME We divide by the number of edges here, but should rather consider
|
||||
// the length of each segment. We would either have to compute the length
|
||||
// of the whole way here (we can't: no node coordinates) or push that back
|
||||
// to the container and keep a reference to the way.
|
||||
const unsigned num_edges = (nodes.size() - 1);
|
||||
return detail::ValueByEdge{by_way / num_edges};
|
||||
}
|
||||
if (parsed_way.backward_speed > 0 &&
|
||||
parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
||||
else
|
||||
{
|
||||
backward_weight_data.speed = parsed_way.backward_speed;
|
||||
backward_weight_data.type = InternalExtractorEdge::WeightType::SPEED;
|
||||
return detail::ValueByMeter{by_meter};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (forward_weight_data.type == InternalExtractorEdge::WeightType::INVALID &&
|
||||
backward_weight_data.type == InternalExtractorEdge::WeightType::INVALID)
|
||||
if (parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
util::Log(logDEBUG) << "found way with bogus speed, id: " << input_way.id();
|
||||
return;
|
||||
BOOST_ASSERT(parsed_way.duration > 0 || parsed_way.forward_speed > 0);
|
||||
forward_duration_data =
|
||||
toValueByEdgeOrByMeter(parsed_way.duration, parsed_way.forward_speed / 3.6);
|
||||
// fallback to duration as weight
|
||||
if (parsed_way.weight > 0 || parsed_way.forward_rate > 0)
|
||||
{
|
||||
forward_weight_data =
|
||||
toValueByEdgeOrByMeter(parsed_way.weight, parsed_way.forward_rate);
|
||||
}
|
||||
else if (fallback_to_duration)
|
||||
{
|
||||
forward_weight_data = forward_duration_data;
|
||||
}
|
||||
}
|
||||
if (parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE)
|
||||
{
|
||||
BOOST_ASSERT(parsed_way.duration > 0 || parsed_way.backward_speed > 0);
|
||||
backward_duration_data =
|
||||
toValueByEdgeOrByMeter(parsed_way.duration, parsed_way.backward_speed / 3.6);
|
||||
// fallback to duration as weight
|
||||
if (parsed_way.weight > 0 || parsed_way.backward_rate > 0)
|
||||
{
|
||||
backward_weight_data =
|
||||
toValueByEdgeOrByMeter(parsed_way.weight, parsed_way.backward_rate);
|
||||
}
|
||||
else if (fallback_to_duration)
|
||||
{
|
||||
backward_weight_data = backward_duration_data;
|
||||
}
|
||||
}
|
||||
|
||||
const auto laneStringToDescription = [](const std::string &lane_string) -> TurnLaneDescription {
|
||||
@@ -237,27 +259,23 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
|
||||
const auto road_classification = parsed_way.road_classification;
|
||||
|
||||
const constexpr auto MAX_STRING_LENGTH = 255u;
|
||||
const constexpr std::size_t MAX_STRING_LENGTH = 255u;
|
||||
// Get the unique identifier for the street name, destination, and ref
|
||||
const auto name_iterator = string_map.find(
|
||||
MapKey(parsed_way.name, parsed_way.destinations, parsed_way.ref, parsed_way.pronunciation));
|
||||
unsigned name_id = EMPTY_NAMEID;
|
||||
auto name_id = EMPTY_NAMEID;
|
||||
if (string_map.end() == name_iterator)
|
||||
{
|
||||
const auto name_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.name.size());
|
||||
const auto name_length = std::min(MAX_STRING_LENGTH, parsed_way.name.size());
|
||||
const auto destinations_length =
|
||||
std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.destinations.size());
|
||||
std::min(MAX_STRING_LENGTH, parsed_way.destinations.size());
|
||||
const auto pronunciation_length =
|
||||
std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.pronunciation.size());
|
||||
const auto ref_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.ref.size());
|
||||
std::min(MAX_STRING_LENGTH, parsed_way.pronunciation.size());
|
||||
const auto ref_length = std::min(MAX_STRING_LENGTH, parsed_way.ref.size());
|
||||
|
||||
// name_offsets already has an offset of a new name, take the offset index as the name id
|
||||
name_id = external_memory.name_offsets.size() - 1;
|
||||
|
||||
external_memory.name_char_data.reserve(external_memory.name_char_data.size() + name_length +
|
||||
destinations_length + pronunciation_length +
|
||||
ref_length);
|
||||
|
||||
std::copy(parsed_way.name.c_str(),
|
||||
parsed_way.name.c_str() + name_length,
|
||||
std::back_inserter(external_memory.name_char_data));
|
||||
@@ -288,114 +306,85 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
||||
name_id = name_iterator->second;
|
||||
}
|
||||
|
||||
const bool split_edge = (parsed_way.forward_speed > 0) &&
|
||||
(TRAVEL_MODE_INACCESSIBLE != parsed_way.forward_travel_mode) &&
|
||||
(parsed_way.backward_speed > 0) &&
|
||||
(TRAVEL_MODE_INACCESSIBLE != parsed_way.backward_travel_mode) &&
|
||||
((parsed_way.forward_speed != parsed_way.backward_speed) ||
|
||||
const bool in_forward_direction =
|
||||
(parsed_way.forward_speed > 0 || parsed_way.forward_rate > 0 || parsed_way.duration > 0 ||
|
||||
parsed_way.weight > 0) &&
|
||||
(parsed_way.forward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
||||
|
||||
const bool in_backward_direction =
|
||||
(parsed_way.backward_speed > 0 || parsed_way.backward_rate > 0 || parsed_way.duration > 0 ||
|
||||
parsed_way.weight > 0) &&
|
||||
(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
||||
|
||||
const bool split_edge = in_forward_direction && in_backward_direction &&
|
||||
((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));
|
||||
|
||||
external_memory.used_node_id_list.reserve(external_memory.used_node_id_list.size() +
|
||||
input_way.nodes().size());
|
||||
|
||||
std::transform(input_way.nodes().begin(),
|
||||
input_way.nodes().end(),
|
||||
std::back_inserter(external_memory.used_node_id_list),
|
||||
[](const osmium::NodeRef &ref) {
|
||||
return OSMNodeID{static_cast<std::uint64_t>(ref.ref())};
|
||||
});
|
||||
|
||||
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
|
||||
|
||||
// traverse way in reverse in this case
|
||||
if (is_opposite_way)
|
||||
if (in_forward_direction)
|
||||
{
|
||||
BOOST_ASSERT(split_edge == false);
|
||||
BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
||||
util::for_each_pair(
|
||||
input_way.nodes().crbegin(),
|
||||
input_way.nodes().crend(),
|
||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
||||
external_memory.all_edges_list.push_back(
|
||||
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||
name_id,
|
||||
backward_weight_data,
|
||||
true,
|
||||
false,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.circular,
|
||||
parsed_way.is_startpoint,
|
||||
parsed_way.backward_travel_mode,
|
||||
false,
|
||||
turn_lane_id_backward,
|
||||
road_classification));
|
||||
});
|
||||
|
||||
external_memory.way_start_end_id_list.push_back(
|
||||
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes().back().ref())},
|
||||
OSMNodeID{
|
||||
static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[1].ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
|
||||
}
|
||||
else
|
||||
{
|
||||
const bool forward_only =
|
||||
split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode;
|
||||
util::for_each_pair(
|
||||
input_way.nodes().cbegin(),
|
||||
input_way.nodes().cend(),
|
||||
nodes.cbegin(),
|
||||
nodes.cend(),
|
||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
||||
external_memory.all_edges_list.push_back(
|
||||
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||
name_id,
|
||||
forward_weight_data,
|
||||
forward_duration_data,
|
||||
true,
|
||||
!forward_only,
|
||||
in_backward_direction && !split_edge,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.circular,
|
||||
parsed_way.is_startpoint,
|
||||
parsed_way.forward_travel_mode,
|
||||
split_edge,
|
||||
turn_lane_id_forward,
|
||||
road_classification));
|
||||
road_classification,
|
||||
{}));
|
||||
});
|
||||
if (split_edge)
|
||||
{
|
||||
BOOST_ASSERT(parsed_way.backward_travel_mode != TRAVEL_MODE_INACCESSIBLE);
|
||||
util::for_each_pair(
|
||||
input_way.nodes().cbegin(),
|
||||
input_way.nodes().cend(),
|
||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
||||
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||
OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||
name_id,
|
||||
backward_weight_data,
|
||||
false,
|
||||
true,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.circular,
|
||||
parsed_way.is_startpoint,
|
||||
parsed_way.backward_travel_mode,
|
||||
true,
|
||||
turn_lane_id_backward,
|
||||
road_classification));
|
||||
});
|
||||
}
|
||||
|
||||
external_memory.way_start_end_id_list.push_back(
|
||||
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes().back().ref())},
|
||||
OSMNodeID{
|
||||
static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[1].ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
|
||||
}
|
||||
|
||||
if (in_backward_direction || split_edge)
|
||||
{
|
||||
util::for_each_pair(
|
||||
nodes.cbegin(),
|
||||
nodes.cend(),
|
||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
||||
external_memory.all_edges_list.push_back(
|
||||
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||
name_id,
|
||||
backward_weight_data,
|
||||
backward_duration_data,
|
||||
false,
|
||||
true,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.circular,
|
||||
parsed_way.is_startpoint,
|
||||
parsed_way.backward_travel_mode,
|
||||
split_edge,
|
||||
turn_lane_id_backward,
|
||||
road_classification,
|
||||
{}));
|
||||
});
|
||||
}
|
||||
|
||||
std::transform(nodes.begin(),
|
||||
nodes.end(),
|
||||
std::back_inserter(external_memory.used_node_id_list),
|
||||
[](const osmium::NodeRef &ref) {
|
||||
return OSMNodeID{static_cast<std::uint64_t>(ref.ref())};
|
||||
});
|
||||
|
||||
external_memory.way_start_end_id_list.push_back(
|
||||
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(nodes[0].ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(nodes[1].ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(nodes[nodes.size() - 2].ref())},
|
||||
OSMNodeID{static_cast<std::uint64_t>(nodes.back().ref())}});
|
||||
}
|
||||
|
||||
guidance::LaneDescriptionMap &&ExtractorCallbacks::moveOutLaneDescriptionMap()
|
||||
|
||||
Reference in New Issue
Block a user