Skip to content

Commit

Permalink
unpack path and get duration that way
Browse files Browse the repository at this point in the history
  • Loading branch information
ghoshkaj committed Mar 6, 2018
1 parent 60e9f98 commit 82eb4ae
Show file tree
Hide file tree
Showing 8 changed files with 382 additions and 96 deletions.
38 changes: 38 additions & 0 deletions include/engine/internal_route_result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ namespace osrm
namespace engine
{

struct DurationData
{
// duration that is traveled on the segment until the turn is reached,
// including a turn if the segment preceeds one.
EdgeWeight duration_until_turn;
// If this segment immediately preceeds a turn, then duration_of_turn
// will contain the duration of the turn. Otherwise it will be 0.
EdgeWeight duration_of_turn;
};

struct PathData
{
// from edge-based-node id
Expand Down Expand Up @@ -67,6 +77,34 @@ struct PathData
bool is_left_hand_driving;
};

struct InternalDurationsRouteResult
{
std::vector<std::vector<DurationData>> unpacked_path_segments;
std::vector<PhantomNodes> segment_end_coordinates;
std::vector<bool> source_traversed_in_reverse;
std::vector<bool> target_traversed_in_reverse;
EdgeWeight shortest_path_weight = INVALID_EDGE_WEIGHT;

bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_weight; }

bool is_via_leg(const std::size_t leg) const
{
return (leg != unpacked_path_segments.size() - 1);
}

// Note: includes duration for turns, except for at start and end node.
EdgeWeight duration() const
{
EdgeWeight ret{0};

for (const auto &leg : unpacked_path_segments)
for (const auto &segment : leg)
ret += segment.duration_until_turn;

return ret;
}
};

struct InternalRouteResult
{
std::vector<std::vector<PathData>> unpacked_path_segments;
Expand Down
177 changes: 174 additions & 3 deletions include/engine/routing_algorithms/routing_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,7 @@ void annotatePath(const FacadeT &facade,
{
id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id);
weight_vector = facade.GetUncompressedForwardWeights(geometry_index.id);
duration_vector = facade.GetUncompressedForwardDurations(
geometry_index.id); // DO WE WANT TO REMOVE ALL REFERENCES TO DURATION CALCS IN
// FACADE AS WELL LIKE THIS METHOD? AND USE THE
duration_vector = facade.GetUncompressedForwardDurations(geometry_index.id);
datasource_vector = facade.GetUncompressedForwardDatasources(geometry_index.id);
}
else
Expand Down Expand Up @@ -402,6 +400,179 @@ InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade,
return raw_route_data;
}

template <typename FacadeT>
void annotatePathWithDurations(const FacadeT &facade,
const PhantomNodes &phantom_node_pair,
const std::vector<NodeID> &unpacked_nodes,
const std::vector<EdgeID> &unpacked_edges,
std::vector<DurationData> &unpacked_path)
{
BOOST_ASSERT(!unpacked_nodes.empty());
BOOST_ASSERT(unpacked_nodes.size() == unpacked_edges.size() + 1);

const auto source_node_id = unpacked_nodes.front();
const auto target_node_id = unpacked_nodes.back();
const bool start_traversed_in_reverse =
phantom_node_pair.source_phantom.forward_segment_id.id != source_node_id;
const bool target_traversed_in_reverse =
phantom_node_pair.target_phantom.forward_segment_id.id != target_node_id;

BOOST_ASSERT(phantom_node_pair.source_phantom.forward_segment_id.id == source_node_id ||
phantom_node_pair.source_phantom.reverse_segment_id.id == source_node_id);
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_segment_id.id == target_node_id ||
phantom_node_pair.target_phantom.reverse_segment_id.id == target_node_id);

// datastructures to hold extracted data from geometry
std::vector<NodeID> id_vector;
std::vector<EdgeWeight> weight_vector;
std::vector<EdgeWeight> duration_vector;

const auto get_segment_geometry = [&](const auto geometry_index) {
if (geometry_index.forward)
{
id_vector = facade.GetUncompressedForwardGeometry(geometry_index.id);
weight_vector = facade.GetUncompressedForwardWeights(geometry_index.id);
duration_vector = facade.GetUncompressedForwardDurations(geometry_index.id);
}
else
{
id_vector = facade.GetUncompressedReverseGeometry(geometry_index.id);
weight_vector = facade.GetUncompressedReverseWeights(geometry_index.id);
duration_vector = facade.GetUncompressedReverseDurations(geometry_index.id);
}
};

auto node_from = unpacked_nodes.begin(), node_last = std::prev(unpacked_nodes.end());
for (auto edge = unpacked_edges.begin(); node_from != node_last; ++node_from, ++edge)
{
const auto &edge_data = facade.GetEdgeData(*edge);
const auto turn_id = edge_data.turn_id; // edge-based graph edge index
const auto node_id = *node_from; // edge-based graph node index

const auto geometry_index = facade.GetGeometryIndex(node_id);
get_segment_geometry(geometry_index);

BOOST_ASSERT(duration_vector.size() == id_vector.size() - 1);
const bool is_first_segment = unpacked_path.empty();

const std::size_t start_index =
(is_first_segment ? ((start_traversed_in_reverse)
? weight_vector.size() -
phantom_node_pair.source_phantom.fwd_segment_position - 1
: phantom_node_pair.source_phantom.fwd_segment_position)
: 0);
const std::size_t end_index = weight_vector.size();

BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index < end_index);
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
{
unpacked_path.push_back(DurationData{duration_vector[segment_idx], 0});
}
BOOST_ASSERT(unpacked_path.size() > 0);

const auto turn_duration = facade.GetDurationPenaltyForEdgeID(turn_id);

unpacked_path.back().duration_until_turn += turn_duration;
unpacked_path.back().duration_of_turn = turn_duration;
}

std::size_t start_index = 0, end_index = 0;
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
const auto target_geometry = facade.GetGeometryIndex(target_node_id);
const auto is_local_path = source_geometry_id == target_geometry.id && unpacked_path.empty();

get_segment_geometry(target_geometry);

if (target_traversed_in_reverse)
{
if (is_local_path)
{
start_index =
weight_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1;
}
end_index =
weight_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position - 1;
}
else
{
if (is_local_path)
{
start_index = phantom_node_pair.source_phantom.fwd_segment_position;
}
end_index = phantom_node_pair.target_phantom.fwd_segment_position;
}

// Given the following compressed geometry:
// U---v---w---x---y---Z
// s t
// s: fwd_segment 0
// t: fwd_segment 3
// -> (U, v), (v, w), (w, x)
// note that (x, t) is _not_ included but needs to be added later.
for (std::size_t segment_idx = start_index; segment_idx != end_index;
(start_index < end_index ? ++segment_idx : --segment_idx))
{
BOOST_ASSERT(segment_idx < id_vector.size() - 1);
BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0);
unpacked_path.push_back(DurationData{duration_vector[segment_idx], 0});
}

if (unpacked_path.size() > 0)
{
const auto source_duration = start_traversed_in_reverse
? phantom_node_pair.source_phantom.reverse_duration
: phantom_node_pair.source_phantom.forward_duration;
// The above code will create segments for (v, w), (w,x), (x, y) and (y, Z).
// However the first segment duration needs to be adjusted to the fact that the source
// phantom is in the middle of the segment. We do this by subtracting v--s from the
// duration.

// Since it's possible duration_until_turn can be less than source_weight here if
// a negative enough turn penalty is used to modify this edge weight during
// osrm-contract, we clamp to 0 here so as not to return a negative duration
// for this segment.

// TODO this creates a scenario where it's possible the duration from a phantom
// node to the first turn would be the same as from end to end of a segment,
// which is obviously incorrect and not ideal...
unpacked_path.front().duration_until_turn =
std::max(unpacked_path.front().duration_until_turn - source_duration, 0);
}
}

template <typename AlgorithmT>
InternalDurationsRouteResult extractDurations(const DataFacade<AlgorithmT> &facade,
const EdgeWeight weight,
const PhantomNodes &phantom_nodes,
const std::vector<NodeID> &unpacked_nodes,
const std::vector<EdgeID> &unpacked_edges)
{
InternalDurationsRouteResult raw_route_data;
raw_route_data.segment_end_coordinates = {phantom_nodes};

// No path found for both target nodes?
if (INVALID_EDGE_WEIGHT == weight)
{
return raw_route_data;
}

raw_route_data.shortest_path_weight = weight;
raw_route_data.unpacked_path_segments.resize(1);
raw_route_data.source_traversed_in_reverse.push_back(
(unpacked_nodes.front() != phantom_nodes.source_phantom.forward_segment_id.id));
raw_route_data.target_traversed_in_reverse.push_back(
(unpacked_nodes.back() != phantom_nodes.target_phantom.forward_segment_id.id));

annotatePathWithDurations(facade,
phantom_nodes,
unpacked_nodes,
unpacked_edges,
raw_route_data.unpacked_path_segments.front());

return raw_route_data;
}

} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
Expand Down
Loading

0 comments on commit 82eb4ae

Please sign in to comment.