roundabout for segregated entry roads
This commit is contained in:
parent
be5b49e391
commit
e59a7926a2
@ -165,6 +165,84 @@ Feature: Basic Roundabout
|
||||
| j,f | jkl,def,def | depart,roundabout-exit-3,arrive |
|
||||
| j,c | jkl,abc,abc | depart,roundabout-exit-4,arrive |
|
||||
|
||||
Scenario: Mixed Entry and Exit - segregated roads
|
||||
Given the node map
|
||||
| | | a | | c | | |
|
||||
| | | | | | | |
|
||||
| l | | | b | | | d |
|
||||
| | | k | | e | | |
|
||||
| j | | | h | | | f |
|
||||
| | | | | | | |
|
||||
| | | i | | g | | |
|
||||
|
||||
And the ways
|
||||
| nodes | junction | oneway |
|
||||
| abc | | yes |
|
||||
| def | | yes |
|
||||
| ghi | | yes |
|
||||
| jkl | | yes |
|
||||
| bkheb | roundabout | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
|
||||
| a,l | abc,jkl,jkl | depart,roundabout-exit-1,arrive |
|
||||
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
|
||||
| a,f | abc,def,def | depart,roundabout-exit-3,arrive |
|
||||
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
|
||||
| d,c | def,abc,abc | depart,roundabout-exit-1,arrive |
|
||||
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
|
||||
| d,i | def,ghi,ghi | depart,roundabout-exit-3,arrive |
|
||||
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
|
||||
| g,f | ghi,def,def | depart,roundabout-exit-1,arrive |
|
||||
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
|
||||
| g,l | ghi,jkl,jkl | depart,roundabout-exit-3,arrive |
|
||||
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
|
||||
| j,i | jkl,ghi,ghi | depart,roundabout-exit-1,arrive |
|
||||
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
|
||||
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
|
||||
|
||||
Scenario: Mixed Entry and Exit - segregated roads, different names
|
||||
Given the node map
|
||||
| | | a | | c | | |
|
||||
| | | | | | | |
|
||||
| l | | | b | | | d |
|
||||
| | | k | | e | | |
|
||||
| j | | | h | | | f |
|
||||
| | | | | | | |
|
||||
| | | i | | g | | |
|
||||
|
||||
And the ways
|
||||
| nodes | junction | oneway |
|
||||
| ab | | yes |
|
||||
| bc | | yes |
|
||||
| de | | yes |
|
||||
| ef | | yes |
|
||||
| gh | | yes |
|
||||
| hi | | yes |
|
||||
| jk | | yes |
|
||||
| kl | | yes |
|
||||
| bkheb | roundabout | yes |
|
||||
|
||||
When I route I should get
|
||||
| waypoints | route | turns |
|
||||
| a,c | ab,bc,bc | depart,roundabout-exit-4,arrive |
|
||||
| a,l | ab,kl,kl | depart,roundabout-exit-1,arrive |
|
||||
| a,i | ab,hi,hi | depart,roundabout-exit-2,arrive |
|
||||
| a,f | ab,ef,ef | depart,roundabout-exit-3,arrive |
|
||||
| d,f | de,ef,ef | depart,roundabout-exit-4,arrive |
|
||||
| d,c | de,bc,bc | depart,roundabout-exit-1,arrive |
|
||||
| d,l | de,kl,kl | depart,roundabout-exit-2,arrive |
|
||||
| d,i | de,hi,hi | depart,roundabout-exit-3,arrive |
|
||||
| g,i | gh,hi,hi | depart,roundabout-exit-4,arrive |
|
||||
| g,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
|
||||
| g,c | gh,bc,bc | depart,roundabout-exit-2,arrive |
|
||||
| g,l | gh,kl,kl | depart,roundabout-exit-3,arrive |
|
||||
| j,l | jk,kl,kl | depart,roundabout-exit-4,arrive |
|
||||
| j,i | jk,hi,hi | depart,roundabout-exit-1,arrive |
|
||||
| j,f | jk,ef,ef | depart,roundabout-exit-2,arrive |
|
||||
| j,c | jk,bc,bc | depart,roundabout-exit-3,arrive |
|
||||
|
||||
Scenario: Collinear in X
|
||||
Given the node map
|
||||
| a | b | c | d | f |
|
||||
@ -184,11 +262,11 @@ Feature: Basic Roundabout
|
||||
|
||||
Scenario: Collinear in Y
|
||||
Given the node map
|
||||
| a | |
|
||||
| b | |
|
||||
| c | e |
|
||||
| d | |
|
||||
| f | |
|
||||
| | a |
|
||||
| | b |
|
||||
| e | c |
|
||||
| | d |
|
||||
| | f |
|
||||
|
||||
And the ways
|
||||
| nodes | junction |
|
||||
|
@ -56,6 +56,10 @@ class RoundaboutHandler : public IntersectionHandler
|
||||
const EdgeID via_eid,
|
||||
const Intersection &intersection) const;
|
||||
|
||||
void invalidateExitAgainstDirection(const NodeID from_nid,
|
||||
const EdgeID via_eid,
|
||||
Intersection &intersection) const;
|
||||
|
||||
// decide whether we lookk at a roundabout or a rotary
|
||||
bool isRotary(const NodeID nid) const;
|
||||
|
||||
|
@ -25,6 +25,28 @@ namespace engine
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
void print(const std::vector<RouteStep> &steps)
|
||||
{
|
||||
std::cout << "Path\n";
|
||||
int segment = 0;
|
||||
for (const auto &step : steps)
|
||||
{
|
||||
const auto type = static_cast<int>(step.maneuver.instruction.type);
|
||||
const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier);
|
||||
|
||||
std::cout << "\t[" << ++segment << "]: " << type << " " << modifier
|
||||
<< " Duration: " << step.duration << " Distance: " << step.distance
|
||||
<< " Geometry: " << step.geometry_begin << " " << step.geometry_end
|
||||
<< " exit: " << step.maneuver.exit
|
||||
<< " Intersections: " << step.maneuver.intersections.size() << " [";
|
||||
|
||||
for (const auto &intersection : step.maneuver.intersections)
|
||||
std::cout << "(" << intersection.duration << " " << intersection.distance << ")";
|
||||
|
||||
std::cout << "] name[" << step.name_id << "]: " << step.name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
bool canMergeTrivially(const RouteStep &destination, const RouteStep &source)
|
||||
@ -176,28 +198,6 @@ void closeOffRoundabout(const bool on_roundabout,
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
void print(const std::vector<RouteStep> &steps)
|
||||
{
|
||||
std::cout << "Path\n";
|
||||
int segment = 0;
|
||||
for (const auto &step : steps)
|
||||
{
|
||||
const auto type = static_cast<int>(step.maneuver.instruction.type);
|
||||
const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier);
|
||||
|
||||
std::cout << "\t[" << ++segment << "]: " << type << " " << modifier
|
||||
<< " Duration: " << step.duration << " Distance: " << step.distance
|
||||
<< " Geometry: " << step.geometry_begin << " " << step.geometry_end
|
||||
<< " exit: " << step.maneuver.exit
|
||||
<< " Intersections: " << step.maneuver.intersections.size() << " [";
|
||||
|
||||
for (auto intersection : step.maneuver.intersections)
|
||||
std::cout << "(" << intersection.duration << " " << intersection.distance << ")";
|
||||
|
||||
std::cout << "] name[" << step.name_id << "]: " << step.name << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Every Step Maneuver consists of the information until the turn.
|
||||
// This list contains a set of instructions, called silent, which should
|
||||
// not be part of the final output.
|
||||
|
@ -208,6 +208,15 @@ Intersection IntersectionGenerator::mergeSegregatedRoads(Intersection intersecti
|
||||
if (intersection.size() == 1)
|
||||
return intersection;
|
||||
|
||||
const bool is_connected_to_roundabout = [this,&intersection]() {
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
if (node_based_graph.GetEdgeData(road.turn.eid).roundabout)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
|
||||
// check for merges including the basic u-turn
|
||||
// these result in an adjustment of all other angles
|
||||
if (mergable(0, intersection.size() - 1))
|
||||
@ -216,8 +225,24 @@ Intersection IntersectionGenerator::mergeSegregatedRoads(Intersection intersecti
|
||||
(360 - intersection[intersection.size() - 1].turn.angle) / 2;
|
||||
for (std::size_t i = 1; i + 1 < intersection.size(); ++i)
|
||||
intersection[i].turn.angle += correction_factor;
|
||||
|
||||
// FIXME if we have a left-sided country, we need to switch this off and enable it below
|
||||
intersection[0] = merge(intersection.front(), intersection.back());
|
||||
intersection[0].turn.angle = 0;
|
||||
|
||||
if (is_connected_to_roundabout)
|
||||
{
|
||||
// We are merging a u-turn against the direction of a roundabout
|
||||
//
|
||||
// -----------> roundabout
|
||||
// / \
|
||||
// out in
|
||||
//
|
||||
// These cases have to be disabled, even if they are not forbidden specifically by a
|
||||
// relation
|
||||
intersection[0].entry_allowed = false;
|
||||
}
|
||||
|
||||
intersection.pop_back();
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ bool RoundaboutHandler::canProcess(const NodeID from_nid,
|
||||
Intersection RoundaboutHandler::
|
||||
operator()(const NodeID from_nid, const EdgeID via_eid, Intersection intersection) const
|
||||
{
|
||||
invalidateExitAgainstDirection(from_nid, via_eid, intersection);
|
||||
const auto flags = getRoundaboutFlags(from_nid, via_eid, intersection);
|
||||
const bool is_rotary = isRotary(node_based_graph.GetTarget(via_eid));
|
||||
// find the radius of the roundabout
|
||||
@ -55,7 +56,7 @@ detail::RoundaboutFlags RoundaboutHandler::getRoundaboutFlags(
|
||||
{
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
// only check actual outgoing edges
|
||||
if (edge_data.reversed)
|
||||
if (edge_data.reversed || !road.entry_allowed )
|
||||
continue;
|
||||
|
||||
if (edge_data.roundabout)
|
||||
@ -79,6 +80,42 @@ detail::RoundaboutFlags RoundaboutHandler::getRoundaboutFlags(
|
||||
return {on_roundabout, can_enter_roundabout, can_exit_roundabout_separately};
|
||||
}
|
||||
|
||||
void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
||||
const EdgeID via_eid,
|
||||
Intersection &intersection) const
|
||||
{
|
||||
const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid);
|
||||
if( in_edge_data.roundabout )
|
||||
return;
|
||||
|
||||
bool past_roundabout_angle = false;
|
||||
for (auto &road : intersection)
|
||||
{
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
// only check actual outgoing edges
|
||||
if (edge_data.reversed)
|
||||
{
|
||||
// remember whether we have seen the roundabout in-part
|
||||
if (edge_data.roundabout)
|
||||
past_roundabout_angle = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Exiting roundabouts at an entry point is technically a data-modelling issue.
|
||||
// This workaround handles cases in which an exit precedes and entry. The resulting
|
||||
// u-turn against the roundabout direction is invalidated.
|
||||
// The sorting of the angles represents a problem for left-sided driving, though.
|
||||
// FIXME in case of left-sided driving, we have to check whether we can enter the
|
||||
// roundabout later in the cycle, rather than prior.
|
||||
if (!edge_data.roundabout && node_based_graph.GetTarget(road.turn.eid) != from_nid &&
|
||||
past_roundabout_angle)
|
||||
{
|
||||
road.entry_allowed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RoundaboutHandler::isRotary(const NodeID nid) const
|
||||
{
|
||||
// translate a node ID into its respective coordinate stored in the node_info_list
|
||||
@ -191,7 +228,6 @@ Intersection RoundaboutHandler::handleRoundabouts(const bool is_rotary,
|
||||
const bool can_exit_roundabout_separately,
|
||||
Intersection intersection) const
|
||||
{
|
||||
// TODO requires differentiation between roundabouts and rotaries
|
||||
// detect via radius (get via circle through three vertices)
|
||||
NodeID node_v = node_based_graph.GetTarget(via_eid);
|
||||
if (on_roundabout)
|
||||
|
Loading…
Reference in New Issue
Block a user