correct handling of travel modes

This commit is contained in:
Moritz Kobitzsch 2016-02-13 19:17:30 +01:00
parent 65183e94c6
commit 2679c1cf0a
5 changed files with 72 additions and 42 deletions

View File

@ -25,6 +25,22 @@ Feature: Testbot - Travel mode
When I route I should get When I route I should get
| from | to | route | modes | | from | to | route | modes |
| a | d | foo,foo,foo | 1,3,1 | | a | d | foo,foo,foo | 1,3,1 |
| b | d | foo,foo | 3,1 |
Scenario: Testbot - Compressed Modes
Given the node map
| a | b | c | d | e | f | g |
And the ways
| nodes | highway | name |
| abc | residential | road |
| cde | river | liquid |
| efg | residential | solid |
When I route I should get
| from | to | route | modes | turns |
| a | g | road,liquid,solid | 1,3,1 | head,straight,straight,destination |
| c | g | liquid,solid | 3,1 | head,straight,destination |
Scenario: Testbot - Modes in each direction, different forward/backward speeds Scenario: Testbot - Modes in each direction, different forward/backward speeds
Given the node map Given the node map

View File

@ -154,7 +154,7 @@ void SegmentList<DataFacadeT>::AddLeg(const std::vector<PathData> &leg_data,
const bool is_via_leg, const bool is_via_leg,
const DataFacade *facade) const DataFacade *facade)
{ {
for (const PathData &path_data : leg_data) for (const auto &path_data : leg_data)
{ {
AppendSegment(facade->GetCoordinateOfNode(path_data.node), path_data); AppendSegment(facade->GetCoordinateOfNode(path_data.node), path_data);
} }
@ -196,32 +196,7 @@ template <typename DataFacadeT>
void SegmentList<DataFacadeT>::AppendSegment(const FixedPointCoordinate coordinate, void SegmentList<DataFacadeT>::AppendSegment(const FixedPointCoordinate coordinate,
const PathData &path_point) const PathData &path_point)
{ {
// if the start location is on top of a node, the first movement might be zero-length, const auto turn = path_point.turn_instruction;
// in which case we dont' add a new description, but instead update the existing one
if ((1 == segments.size()) && (segments.front().location == coordinate))
{
if (path_point.segment_duration > 0)
{
segments.front().name_id = path_point.name_id;
segments.front().travel_mode = path_point.travel_mode;
}
return;
}
// make sure mode changes are announced, even when there otherwise is no turn
const auto getTurn = [](const PathData &path_point, const extractor::TravelMode previous_mode)
{
if (extractor::TurnInstruction::NoTurn == path_point.turn_instruction &&
previous_mode != path_point.travel_mode && path_point.segment_duration > 0)
{
return extractor::TurnInstruction::GoStraight;
}
return path_point.turn_instruction;
};
// TODO check why we require .front() here
const auto turn = segments.size() ? getTurn(path_point, segments.front().travel_mode)
: path_point.turn_instruction;
segments.emplace_back(coordinate, path_point.name_id, path_point.segment_duration, 0.f, turn, segments.emplace_back(coordinate, path_point.name_id, path_point.segment_duration, 0.f, turn,
path_point.travel_mode); path_point.travel_mode);
@ -236,6 +211,30 @@ void SegmentList<DataFacadeT>::Finalize(const bool extract_alternative,
if (segments.empty()) if (segments.empty())
return; return;
// check if first two segments can be merged
BOOST_ASSERT(segments.size() >= 2);
if (segments[0].location == segments[1].location &&
segments[1].turn_instruction == extractor::TurnInstruction::NoTurn)
{
segments[0].travel_mode = segments[1].travel_mode;
segments[0].name_id = segments[1].name_id;
// Other data??
segments.erase(segments.begin() + 1);
}
// announce mode changes
for (std::size_t i = 0; i + 1 < segments.size(); ++i)
{
auto &segment = segments[i];
const auto next_mode = segments[i + 1].travel_mode;
if (segment.travel_mode != next_mode &&
segment.turn_instruction == extractor::TurnInstruction::NoTurn)
{
segment.turn_instruction = extractor::TurnInstruction::GoStraight;
segment.necessary = true;
}
}
segments[0].length = 0.f; segments[0].length = 0.f;
for (const auto i : util::irange<std::size_t>(1, segments.size())) for (const auto i : util::irange<std::size_t>(1, segments.size()))
{ {

View File

@ -44,8 +44,9 @@ inline util::json::Array AnnotateRoute(const std::vector<SegmentInformation> &ro
extractor::TravelMode last_travel_mode = TRAVEL_MODE_DEFAULT; extractor::TravelMode last_travel_mode = TRAVEL_MODE_DEFAULT;
// Generate annotations for every segment // Generate annotations for every segment
for (const SegmentInformation &segment : route_segments) for (std::size_t i = 0; i < route_segments.size(); ++i)
{ {
const auto &segment = route_segments[i];
util::json::Array json_instruction_row; util::json::Array json_instruction_row;
extractor::TurnInstruction current_instruction = segment.turn_instruction; extractor::TurnInstruction current_instruction = segment.turn_instruction;
if (extractor::isTurnNecessary(current_instruction)) if (extractor::isTurnNecessary(current_instruction))
@ -89,8 +90,17 @@ inline util::json::Array AnnotateRoute(const std::vector<SegmentInformation> &ro
json_instruction_row.values.push_back( json_instruction_row.values.push_back(
static_cast<std::uint32_t>(std::round(post_turn_bearing_value))); static_cast<std::uint32_t>(std::round(post_turn_bearing_value)));
json_instruction_row.values.push_back(segment.travel_mode); if (i + 1 < route_segments.size())
last_travel_mode = segment.travel_mode; {
// anounce next travel mode with turn
json_instruction_row.values.push_back(route_segments[i + 1].travel_mode);
last_travel_mode = segment.travel_mode;
}
else
{
json_instruction_row.values.push_back(segment.travel_mode);
last_travel_mode = segment.travel_mode;
}
// pre turn bearing // pre turn bearing
const double pre_turn_bearing_value = (segment.pre_turn_bearing / 10.); const double pre_turn_bearing_value = (segment.pre_turn_bearing / 10.);

View File

@ -99,8 +99,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
(!force_loop_forward || (!force_loop_forward ||
forward_heap.GetData(node).parent != forward_heap.GetData(node).parent !=
node) // if loops are forced, they are so at the source node) // if loops are forced, they are so at the source
&& && (!force_loop_reverse || reverse_heap.GetData(node).parent != node))
(!force_loop_reverse || reverse_heap.GetData(node).parent != node))
{ {
middle_node_id = node; middle_node_id = node;
upper_bound = new_distance; upper_bound = new_distance;
@ -290,7 +289,10 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id); unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id);
const extractor::TurnInstruction turn_instruction = const extractor::TurnInstruction turn_instruction =
facade->GetTurnInstructionForEdgeID(ed.id); facade->GetTurnInstructionForEdgeID(ed.id);
const extractor::TravelMode travel_mode = facade->GetTravelModeForEdgeID(ed.id); const extractor::TravelMode travel_mode =
(unpacked_path.empty() && start_traversed_in_reverse)
? phantom_node_pair.source_phantom.backward_travel_mode
: facade->GetTravelModeForEdgeID(ed.id);
if (!facade->EdgeIsCompressed(ed.id)) if (!facade->EdgeIsCompressed(ed.id))
{ {
@ -364,11 +366,11 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
BOOST_ASSERT(i < id_vector.size()); BOOST_ASSERT(i < id_vector.size());
BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0); BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode > 0);
unpacked_path.emplace_back( unpacked_path.emplace_back(
PathData{id_vector[i], PathData{id_vector[i], phantom_node_pair.target_phantom.name_id,
phantom_node_pair.target_phantom.name_id, extractor::TurnInstruction::NoTurn, 0,
extractor::TurnInstruction::NoTurn, target_traversed_in_reverse
0, ? phantom_node_pair.target_phantom.backward_travel_mode
phantom_node_pair.target_phantom.forward_travel_mode}); : phantom_node_pair.target_phantom.forward_travel_mode});
} }
} }
@ -560,6 +562,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
const bool force_loop_reverse) const const bool force_loop_reverse) const
{ {
NodeID middle = SPECIAL_NODEID; NodeID middle = SPECIAL_NODEID;
distance = INVALID_EDGE_WEIGHT;
std::vector<std::pair<NodeID, EdgeWeight>> forward_entry_points; std::vector<std::pair<NodeID, EdgeWeight>> forward_entry_points;
std::vector<std::pair<NodeID, EdgeWeight>> reverse_entry_points; std::vector<std::pair<NodeID, EdgeWeight>> reverse_entry_points;
@ -602,11 +605,10 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
} }
} }
} }
// TODO check if unordered_set might be faster // TODO check if unordered_set might be faster
// sort by id and increasing by distance // sort by id and increasing by distance
auto entry_point_comparator = auto entry_point_comparator = [](const std::pair<NodeID, EdgeWeight> &lhs,
[](const std::pair<NodeID, EdgeWeight> &lhs, const std::pair<NodeID, EdgeWeight> &rhs) const std::pair<NodeID, EdgeWeight> &rhs)
{ {
return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second); return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second);
}; };
@ -614,6 +616,8 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
std::sort(reverse_entry_points.begin(), reverse_entry_points.end(), entry_point_comparator); std::sort(reverse_entry_points.begin(), reverse_entry_points.end(), entry_point_comparator);
NodeID last_id = SPECIAL_NODEID; NodeID last_id = SPECIAL_NODEID;
forward_core_heap.Clear();
reverse_core_heap.Clear();
for (const auto p : forward_entry_points) for (const auto p : forward_entry_points)
{ {
if (p.first == last_id) if (p.first == last_id)

View File

@ -180,6 +180,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeI
reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i], reverse_geometry[geometry_size - 1 - i].second, forward_dist_prefix_sum[i],
reverse_dist_prefix_sum[i], m_compressed_edge_container.GetPositionForID(edge_id_1), reverse_dist_prefix_sum[i], m_compressed_edge_container.GetPositionForID(edge_id_1),
false, INVALID_COMPONENTID, i, forward_data.travel_mode, reverse_data.travel_mode); false, INVALID_COMPONENTID, i, forward_data.travel_mode, reverse_data.travel_mode);
m_edge_based_node_is_startpoint.push_back(forward_data.startpoint || m_edge_based_node_is_startpoint.push_back(forward_data.startpoint ||
reverse_data.startpoint); reverse_data.startpoint);
current_edge_source_coordinate_id = current_edge_target_coordinate_id; current_edge_source_coordinate_id = current_edge_target_coordinate_id;
@ -483,7 +484,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
(edge_is_compressed ? m_compressed_edge_container.GetPositionForID(edge_form_u) (edge_is_compressed ? m_compressed_edge_container.GetPositionForID(edge_form_u)
: node_v), : node_v),
edge_data1.name_id, turn_instruction, edge_is_compressed, edge_data1.name_id, turn_instruction, edge_is_compressed,
edge_data2.travel_mode); edge_data1.travel_mode);
++original_edges_counter; ++original_edges_counter;