enter and exit roundabout feature - currently not showing turn
This commit is contained in:
		
							parent
							
								
									28d878ed23
								
							
						
					
					
						commit
						f12bb2fa2f
					
				| @ -152,7 +152,6 @@ class RouteAPI : public BaseAPI | ||||
|                         leg_geometry.locations.begin() + step.geometry_end)); | ||||
|                 }); | ||||
|         } | ||||
| 
 | ||||
|         return json::makeRoute(route, | ||||
|                                json::makeRouteLegs(std::move(legs), std::move(step_geometries)), | ||||
|                                std::move(json_overview)); | ||||
|  | ||||
| @ -171,13 +171,17 @@ inline bool entersRoundabout(const TurnInstruction instruction) | ||||
|     return (instruction.type == TurnType::EnterRoundabout || | ||||
|             instruction.type == TurnType::EnterRotary || | ||||
|             instruction.type == TurnType::EnterRoundaboutAtExit || | ||||
|             instruction.type == TurnType::EnterRotaryAtExit); | ||||
|             instruction.type == TurnType::EnterRotaryAtExit || | ||||
|             instruction.type == TurnType::EnterAndExitRoundabout || | ||||
|             instruction.type == TurnType::EnterAndExitRotary); | ||||
| } | ||||
| 
 | ||||
| inline bool leavesRoundabout(const TurnInstruction instruction) | ||||
| { | ||||
|     return (instruction.type == TurnType::ExitRoundabout || | ||||
|             instruction.type == TurnType::ExitRotary); | ||||
|             instruction.type == TurnType::ExitRotary || | ||||
|             instruction.type == TurnType::EnterAndExitRoundabout || | ||||
|             instruction.type == TurnType::EnterAndExitRotary); | ||||
| } | ||||
| 
 | ||||
| inline bool staysOnRoundabout(const TurnInstruction instruction) | ||||
| @ -384,7 +388,7 @@ inline DirectionModifier bearingToDirectionModifier(const std::string &bearing) | ||||
| 
 | ||||
| inline DirectionModifier bearingToDirectionModifier(const double angle) | ||||
| { | ||||
|     return bearingToDirectionModifier( util::bearing::get(angle) ); | ||||
|     return bearingToDirectionModifier(util::bearing::get(angle)); | ||||
| } | ||||
| 
 | ||||
| inline bool isHighway(FunctionalRoadClass road_class) | ||||
|  | ||||
| @ -1,243 +0,0 @@ | ||||
| #ifndef OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP | ||||
| #define OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP | ||||
| 
 | ||||
| #include "guidance/turn_instruction.hpp" | ||||
| #include "guidance/guidance_toolkit.hpp" | ||||
| 
 | ||||
| #include "util/simple_logger.hpp" | ||||
| 
 | ||||
| namespace osrm | ||||
| { | ||||
| namespace engine | ||||
| { | ||||
| namespace guidance | ||||
| { | ||||
| 
 | ||||
| enum class InstructionSymbol : unsigned char | ||||
| { | ||||
|     NoTurn = 0, | ||||
|     GoStraight, | ||||
|     TurnSlightRight, | ||||
|     TurnRight, | ||||
|     TurnSharpRight, | ||||
|     UTurn, | ||||
|     TurnSharpLeft, | ||||
|     TurnLeft, | ||||
|     TurnSlightLeft, | ||||
|     ReachViaLocation, | ||||
|     HeadOn, | ||||
|     EnterRoundAbout, | ||||
|     LeaveRoundAbout, | ||||
|     StayOnRoundAbout, | ||||
|     StartAtEndOfStreet, | ||||
|     ReachedYourDestination, | ||||
|     NameChanges, | ||||
|     EnterAgainstAllowedDirection, | ||||
|     LeaveAgainstAllowedDirection, | ||||
|     InverseAccessRestrictionFlag = 127, | ||||
|     AccessRestrictionFlag = 128, | ||||
|     AccessRestrictionPenalty = 129 | ||||
| }; | ||||
| 
 | ||||
| inline InstructionSymbol directTranslation(const DirectionModifier direction_modifier) | ||||
| { | ||||
|     const constexpr InstructionSymbol translation[] = { | ||||
|         InstructionSymbol::UTurn,      InstructionSymbol::TurnSharpRight, | ||||
|         InstructionSymbol::TurnRight,  InstructionSymbol::TurnSlightRight, | ||||
|         InstructionSymbol::GoStraight, InstructionSymbol::TurnSlightLeft, | ||||
|         InstructionSymbol::TurnLeft,   InstructionSymbol::TurnSharpLeft}; | ||||
|     return translation[direction_modifier]; | ||||
| } | ||||
| 
 | ||||
| inline bool canTranslateDirectly(const TurnType type) | ||||
| { | ||||
|     return type == TurnType::Continue   // remain on a street
 | ||||
|            || type == TurnType::NewName // no turn, but name changes
 | ||||
|            || type == TurnType::Turn    // basic turn
 | ||||
|            || type == TurnType::Ramp    // special turn (highway ramp exits)
 | ||||
|            || type == TurnType::Fork    // fork road splitting up
 | ||||
|            || type == TurnType::EndOfRoad || type == TurnType::Restriction || | ||||
|            type == TurnType::Merge || type == TurnType::Notification; | ||||
| } | ||||
| 
 | ||||
| inline InstructionSymbol getSymbol(const TurnInstruction instruction) | ||||
| { | ||||
|     if (canTranslateDirectly(instruction.type)) | ||||
|     { | ||||
|         return directTranslation(instruction.direction_modifier); | ||||
|     } | ||||
|     else if (instruction.type == TurnType::EnterRoundabout || | ||||
|              instruction.type == TurnType::EnterRotary) | ||||
|     { | ||||
|         return InstructionSymbol::EnterRoundAbout; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         util::SimpleLogger().Write(logDEBUG) | ||||
|             << "Unreasonable request for symbol: " | ||||
|             << std::to_string(static_cast<int>(instruction.type)) << " " | ||||
|             << std::to_string(static_cast<int>(instruction.direction_modifier)); | ||||
|         return InstructionSymbol::NoTurn; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline InstructionSymbol getLocationSymbol(const LocationType type) | ||||
| { | ||||
|     if (type == LocationType::Start) | ||||
|         return InstructionSymbol::HeadOn; | ||||
|     if (type == LocationType::Intermediate) | ||||
|         return InstructionSymbol::ReachViaLocation; | ||||
|     if (type == LocationType::Destination) | ||||
|         return InstructionSymbol::ReachedYourDestination; | ||||
|     return InstructionSymbol::NoTurn; | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| // shiftable turns to left and right
 | ||||
| const constexpr bool shiftable_left[] = {false, false, true, true, true, false, false, true, true}; | ||||
| const constexpr bool shiftable_right[] = {false, false, true, true, false, false, true, true, true}; | ||||
| 
 | ||||
| inline TurnInstruction shiftTurnToLeft(TurnInstruction turn) | ||||
| { | ||||
|     BOOST_ASSERT_MSG(static_cast<int>(turn) < 9, | ||||
|                      "Shift turn only supports basic turn instructions"); | ||||
|     if (turn > TurnInstruction::TurnSlightLeft) | ||||
|         return turn; | ||||
|     else | ||||
|         return shiftable_left[static_cast<int>(turn)] | ||||
|                    ? (static_cast<TurnInstruction>(static_cast<int>(turn) - 1)) | ||||
|                    : turn; | ||||
| } | ||||
| 
 | ||||
| inline TurnInstruction shiftTurnToRight(TurnInstruction turn) | ||||
| { | ||||
|     BOOST_ASSERT_MSG(static_cast<int>(turn) < 9, | ||||
|                      "Shift turn only supports basic turn instructions"); | ||||
|     if (turn > TurnInstruction::TurnSlightLeft) | ||||
|         return turn; | ||||
|     else | ||||
|         return shiftable_right[static_cast<int>(turn)] | ||||
|                    ? (static_cast<TurnInstruction>(static_cast<int>(turn) + 1)) | ||||
|                    : turn; | ||||
| } | ||||
| 
 | ||||
| inline double angularDeviation(const double angle, const double from) | ||||
| { | ||||
|     const double deviation = std::abs(angle - from); | ||||
|     return std::min(360 - deviation, deviation); | ||||
| } | ||||
| 
 | ||||
| inline double getAngularPenalty(const double angle, TurnInstruction instruction) | ||||
| { | ||||
|     BOOST_ASSERT_MSG(static_cast<int>(instruction) < 9, | ||||
|                      "Angular penalty only supports basic turn instructions"); | ||||
|     const double center[] = {180, 180, 135, 90, 45, | ||||
|                              0,   315, 270, 225}; // centers of turns from getTurnDirection
 | ||||
|     return angularDeviation(center[static_cast<int>(instruction)], angle); | ||||
| } | ||||
| 
 | ||||
| inline double getTurnConfidence(const double angle, TurnInstruction instruction) | ||||
| { | ||||
| 
 | ||||
|     // special handling of U-Turns and Roundabout
 | ||||
|     if (instruction >= TurnInstruction::HeadOn || instruction == TurnInstruction::UTurn || | ||||
|         instruction == TurnInstruction::NoTurn || instruction == TurnInstruction::EnterRoundAbout || | ||||
|         instruction == TurnInstruction::StayOnRoundAbout || instruction == TurnInstruction::LeaveRoundAbout ) | ||||
|         return 1.0; | ||||
| 
 | ||||
|     BOOST_ASSERT_MSG(static_cast<int>(instruction) < 9, | ||||
|                      "Turn confidence only supports basic turn instructions"); | ||||
|     const double deviations[] = {10, 10, 35, 50, 45, 0, 45, 50, 35}; | ||||
|     const double difference = getAngularPenalty(angle, instruction); | ||||
|     const double max_deviation = deviations[static_cast<int>(instruction)]; | ||||
|     return 1.0 - (difference / max_deviation) * (difference / max_deviation); | ||||
| } | ||||
| 
 | ||||
| // Translates between angles and their human-friendly directional representation
 | ||||
| inline TurnInstruction getTurnDirection(const double angle) | ||||
| { | ||||
|     // An angle of zero is a u-turn
 | ||||
|     // 180 goes perfectly straight
 | ||||
|     // 0-180 are right turns
 | ||||
|     // 180-360 are left turns
 | ||||
|     if (angle > 0 && angle < 60) | ||||
|         return TurnInstruction::TurnSharpRight; | ||||
|     if (angle >= 60 && angle < 140) | ||||
|         return TurnInstruction::TurnRight; | ||||
|     if (angle >= 140 && angle < 170) | ||||
|         return TurnInstruction::TurnSlightRight; | ||||
|     if (angle >= 170 && angle <= 190) | ||||
|         return TurnInstruction::GoStraight; | ||||
|     if (angle > 190 && angle <= 220) | ||||
|         return TurnInstruction::TurnSlightLeft; | ||||
|     if (angle > 220 && angle <= 300) | ||||
|         return TurnInstruction::TurnLeft; | ||||
|     if (angle > 300 && angle < 360) | ||||
|         return TurnInstruction::TurnSharpLeft; | ||||
|     return TurnInstruction::UTurn; | ||||
| } | ||||
| 
 | ||||
| // Decides if a turn is needed to be done for the current instruction
 | ||||
| inline bool isTurnNecessary(const TurnInstruction turn_instruction) | ||||
| { | ||||
|     if (TurnInstruction::NoTurn == turn_instruction || | ||||
|         TurnInstruction::StayOnRoundAbout == turn_instruction) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| inline bool resolve(TurnInstruction &to_resolve, const TurnInstruction neighbor, bool resolve_right) | ||||
| { | ||||
|     const auto shifted_turn = | ||||
|         resolve_right ? shiftTurnToRight(to_resolve) : shiftTurnToLeft(to_resolve); | ||||
|     if (shifted_turn == neighbor || shifted_turn == to_resolve) | ||||
|         return false; | ||||
| 
 | ||||
|     to_resolve = shifted_turn; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| inline bool resolveTransitive(TurnInstruction &first, | ||||
|                               TurnInstruction &second, | ||||
|                               const TurnInstruction third, | ||||
|                               bool resolve_right) | ||||
| { | ||||
|     if (resolve(second, third, resolve_right)) | ||||
|     { | ||||
|         first = resolve_right ? shiftTurnToRight(first) : shiftTurnToLeft(first); | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| inline bool isSlightTurn(const TurnInstruction turn) | ||||
| { | ||||
|     return turn == TurnInstruction::GoStraight || turn == TurnInstruction::TurnSlightRight || | ||||
|            turn == TurnInstruction::TurnSlightLeft || turn == TurnInstruction::NoTurn; | ||||
| } | ||||
| 
 | ||||
| inline bool isSharpTurn(const TurnInstruction turn) | ||||
| { | ||||
|     return turn == TurnInstruction::TurnSharpLeft || turn == TurnInstruction::TurnSharpRight; | ||||
| } | ||||
| 
 | ||||
| inline bool isStraight(const TurnInstruction turn) | ||||
| { | ||||
|     return turn == TurnInstruction::GoStraight || turn == TurnInstruction::NoTurn; | ||||
| } | ||||
| 
 | ||||
| inline bool isConflict(const TurnInstruction first, const TurnInstruction second) | ||||
| { | ||||
|     return first == second || (isStraight(first) && isStraight(second)); | ||||
| } | ||||
| } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| } // namespace guidance
 | ||||
| } // namespace engine
 | ||||
| } // namespace osrm
 | ||||
| 
 | ||||
| #endif /* OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP */ | ||||
| @ -60,9 +60,11 @@ enum TurnType // at the moment we can support 32 turn types, without increasing | ||||
|     EndOfRoad,              // T intersection
 | ||||
|     EnterRoundabout,        // Entering a small Roundabout
 | ||||
|     EnterRoundaboutAtExit,  // Entering a small Roundabout at a countable exit
 | ||||
|     EnterAndExitRoundabout, // Touching a roundabout
 | ||||
|     ExitRoundabout,         // Exiting a small Roundabout
 | ||||
|     EnterRotary,            // Enter a rotary
 | ||||
|     EnterRotaryAtExit,      // Enter A Rotary at a countable exit
 | ||||
|     EnterAndExitRotary,     // Touching a rotary
 | ||||
|     ExitRotary,             // Exit a rotary
 | ||||
|     StayOnRoundabout,       // Continue on Either a small or a large Roundabout
 | ||||
|     Restriction,            // Cross a Barrier, requires barrier penalties instead of full block
 | ||||
| @ -82,7 +84,7 @@ inline bool isValidModifier( const TurnType type, const DirectionModifier modifi | ||||
| const constexpr char *turn_type_names[] = {"invalid", | ||||
|                                            "no turn", | ||||
|                                            "waypoint", | ||||
|                                            "passing intersection", | ||||
|                                            "invalid", | ||||
|                                            "new name", | ||||
|                                            "continue", | ||||
|                                            "turn", | ||||
| @ -91,10 +93,12 @@ const constexpr char *turn_type_names[] = {"invalid", | ||||
|                                            "fork", | ||||
|                                            "end of road", | ||||
|                                            "roundabout", | ||||
|                                            "invalid" | ||||
|                                            "invalid", | ||||
|                                            "roundabout", | ||||
|                                            "invalid", | ||||
|                                            "traffic circle", | ||||
|                                            "invalid", | ||||
|                                            "traffic circle", | ||||
|                                            "invalid", | ||||
|                                            "invalid", | ||||
|                                            "restriction", | ||||
|  | ||||
| @ -267,6 +267,7 @@ class BasePlugin | ||||
|             // we didn't found a fitting node, return error
 | ||||
|             if (!phantom_node_pairs[i].first.IsValid(facade.GetNumberOfNodes())) | ||||
|             { | ||||
|                 //TODO document why?
 | ||||
|                 phantom_node_pairs.pop_back(); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
| @ -41,6 +41,7 @@ struct TurnCandidate | ||||
| namespace turn_analysis | ||||
| { | ||||
| 
 | ||||
| // the entry into the turn analysis
 | ||||
| std::vector<TurnCandidate> | ||||
| getTurns(const NodeID from_node, | ||||
|          const EdgeID via_eid, | ||||
| @ -50,6 +51,34 @@ getTurns(const NodeID from_node, | ||||
|          const std::unordered_set<NodeID> &barrier_nodes, | ||||
|          const CompressedEdgeContainer &compressed_edge_container); | ||||
| 
 | ||||
| namespace detail | ||||
| { | ||||
| 
 | ||||
| // Check for restrictions/barriers and generate a list of valid and invalid turns present at the
 | ||||
| // node reached
 | ||||
| // from `from_node` via `via_eid`
 | ||||
| std::vector<TurnCandidate> | ||||
| getTurnCandidates(const NodeID from_node, | ||||
|                   const EdgeID via_eid, | ||||
|                   const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph, | ||||
|                   const std::vector<QueryNode> &node_info_list, | ||||
|                   const std::shared_ptr<RestrictionMap const> restriction_map, | ||||
|                   const std::unordered_set<NodeID> &barrier_nodes, | ||||
|                   const CompressedEdgeContainer &compressed_edge_container); | ||||
| 
 | ||||
| // handle roundabouts
 | ||||
| // TODO distinguish roundabouts and rotaries
 | ||||
| std::vector<TurnCandidate> | ||||
| handleRoundabouts(const NodeID from, | ||||
|                   const EdgeID via_edge, | ||||
|                   const bool on_roundabout, | ||||
|                   const bool can_enter_roundabout, | ||||
|                   const bool can_exit_roundabout, | ||||
|                   std::vector<TurnCandidate> turn_candidates, | ||||
|                   const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph); | ||||
| 
 | ||||
| // handle intersections
 | ||||
| 
 | ||||
| std::vector<TurnCandidate> | ||||
| setTurnTypes(const NodeID from, | ||||
|              const EdgeID via_edge, | ||||
| @ -84,15 +113,6 @@ suppressTurns(const EdgeID via_eid, | ||||
|               std::vector<TurnCandidate> turn_candidates, | ||||
|               const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph); | ||||
| 
 | ||||
| std::vector<TurnCandidate> | ||||
| getTurnCandidates(const NodeID from_node, | ||||
|                   const EdgeID via_eid, | ||||
|                   const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph, | ||||
|                   const std::vector<QueryNode> &node_info_list, | ||||
|                   const std::shared_ptr<RestrictionMap const> restriction_map, | ||||
|                   const std::unordered_set<NodeID> &barrier_nodes, | ||||
|                   const CompressedEdgeContainer &compressed_edge_container); | ||||
| 
 | ||||
| // node_u -- (edge_1) --> node_v -- (edge_2) --> node_w
 | ||||
| engine::guidance::TurnInstruction | ||||
| AnalyzeTurn(const NodeID node_u, | ||||
| @ -102,6 +122,7 @@ AnalyzeTurn(const NodeID node_u, | ||||
|             const NodeID node_w, | ||||
|             const double angle, | ||||
|             const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph); | ||||
| } // namespace detail
 | ||||
| } // namespace turn_analysis
 | ||||
| } // namespace extractor
 | ||||
| } // namespace osrm
 | ||||
|  | ||||
| @ -3,11 +3,8 @@ | ||||
| 
 | ||||
| #include "util/coordinate.hpp" | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <utility> | ||||
| 
 | ||||
| #include <boost/assert.hpp> | ||||
| 
 | ||||
| namespace osrm | ||||
| { | ||||
| namespace util | ||||
|  | ||||
| @ -85,7 +85,7 @@ std::string modeToString(const extractor::TravelMode mode) | ||||
|         token = "river downstream"; | ||||
|         break; | ||||
|     case TRAVEL_MODE_ROUTE: | ||||
|         token = "rout"; | ||||
|         token = "route"; | ||||
|         break; | ||||
|     default: | ||||
|         token = "other"; | ||||
| @ -106,8 +106,8 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver) | ||||
|     step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location); | ||||
|     step_maneuver.values["bearing_before"] = maneuver.bearing_before; | ||||
|     step_maneuver.values["bearing_after"] = maneuver.bearing_after; | ||||
|     if( maneuver.exit != 0 ) | ||||
|       step_maneuver.values["exit"] = maneuver.exit; | ||||
|     if (maneuver.exit != 0) | ||||
|         step_maneuver.values["exit"] = maneuver.exit; | ||||
|     return step_maneuver; | ||||
| } | ||||
| 
 | ||||
| @ -178,7 +178,7 @@ util::json::Array makeRouteLegs(std::vector<guidance::RouteLeg> legs, | ||||
| 
 | ||||
|     return json_legs; | ||||
| } | ||||
| } | ||||
| } | ||||
| } // namespace json
 | ||||
| } // namespace api
 | ||||
| } // namespace engine
 | ||||
| } // namespace osrm
 | ||||
|  | ||||
| @ -84,8 +84,8 @@ void print(const std::vector<std::vector<PathData>> &leg_data) | ||||
| 
 | ||||
| std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> leg_data) | ||||
| { | ||||
|     if( leg_data.empty() ) | ||||
|       return leg_data; | ||||
|     if (leg_data.empty()) | ||||
|         return leg_data; | ||||
| 
 | ||||
| #define PRINT_DEBUG 0 | ||||
|     unsigned carry_exit = 0; | ||||
| @ -98,19 +98,19 @@ std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData> | ||||
|     bool on_roundabout = false; | ||||
|     for (auto &path_data : leg_data) | ||||
|     { | ||||
|         if( not path_data.empty() ) | ||||
|           path_data[0].exit = carry_exit; | ||||
|         if (not path_data.empty()) | ||||
|             path_data[0].exit = carry_exit; | ||||
| 
 | ||||
|         for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index) | ||||
|         { | ||||
|             if (entersRoundabout(path_data[data_index].turn_instruction) ) | ||||
|             if (entersRoundabout(path_data[data_index].turn_instruction)) | ||||
|             { | ||||
|                 path_data[data_index].exit += 1; | ||||
|                 on_roundabout = true; | ||||
|             } | ||||
| 
 | ||||
|             if (isSilent(path_data[data_index].turn_instruction) && | ||||
|                  path_data[data_index].turn_instruction != TurnInstruction::NO_TURN()) | ||||
|                 path_data[data_index].turn_instruction != TurnInstruction::NO_TURN()) | ||||
|             { | ||||
|                 path_data[data_index].exit += 1; | ||||
|             } | ||||
| @ -118,7 +118,7 @@ std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData> | ||||
|             { | ||||
|                 if (!on_roundabout) | ||||
|                 { | ||||
|                     BOOST_ASSERT(leg_data[0][0].turn_instruction.type == TurnType::NO_TURN() ); | ||||
|                     BOOST_ASSERT(leg_data[0][0].turn_instruction.type == TurnType::NO_TURN()); | ||||
|                     if (path_data[data_index].turn_instruction.type == ExitRoundabout) | ||||
|                         leg_data[0][0].turn_instruction.type = TurnType::EnterRoundabout; | ||||
|                     if (path_data[data_index].turn_instruction.type == ExitRotary) | ||||
| @ -160,15 +160,16 @@ std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData> | ||||
|         { | ||||
|             if (entersRoundabout(path_data[data_index - 1].turn_instruction)) | ||||
|             { | ||||
|                 if( !on_roundabout ) | ||||
|                   path_data[data_index-1].exit = 0; | ||||
|                 if (!on_roundabout && !leavesRoundabout(path_data[data_index - 1].turn_instruction)) | ||||
|                     path_data[data_index - 1].exit = 0; | ||||
|                 on_roundabout = false; | ||||
|             } | ||||
|             if (on_roundabout) | ||||
|             { | ||||
|                 path_data[data_index - 2].exit = path_data[data_index - 1].exit; | ||||
|             } | ||||
|             if (leavesRoundabout(path_data[data_index - 1].turn_instruction)) | ||||
|             if (leavesRoundabout(path_data[data_index - 1].turn_instruction) && | ||||
|                 !entersRoundabout(path_data[data_index - 1].turn_instruction)) | ||||
|             { | ||||
|                 path_data[data_index - 2].exit = path_data[data_index - 1].exit; | ||||
|                 on_roundabout = true; | ||||
| @ -191,7 +192,8 @@ std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData> | ||||
|     { | ||||
|         for (auto &data : path_data) | ||||
|         { | ||||
|             if (isSilent(data.turn_instruction) || leavesRoundabout(data.turn_instruction)) | ||||
|             if (isSilent(data.turn_instruction) || (leavesRoundabout(data.turn_instruction) && | ||||
|                                                     !entersRoundabout(data.turn_instruction))) | ||||
|             { | ||||
|                 data.turn_instruction = TurnInstruction::NO_TURN(); | ||||
|                 data.exit = 0; | ||||
|  | ||||
| @ -43,6 +43,7 @@ using engine::guidance::isSlightTurn; | ||||
| using engine::guidance::isSlightModifier; | ||||
| using engine::guidance::mirrorDirectionModifier; | ||||
| 
 | ||||
| #define PRINT_DEBUG_CANDIDATES 0 | ||||
| std::vector<TurnCandidate> | ||||
| getTurns(const NodeID from, | ||||
|          const EdgeID via_edge, | ||||
| @ -52,12 +53,36 @@ getTurns(const NodeID from, | ||||
|          const std::unordered_set<NodeID> &barrier_nodes, | ||||
|          const CompressedEdgeContainer &compressed_edge_container) | ||||
| { | ||||
|     auto turn_candidates = turn_analysis::getTurnCandidates( | ||||
|         from, via_edge, node_based_graph, node_info_list, restriction_map, barrier_nodes, | ||||
|         compressed_edge_container); | ||||
|     auto turn_candidates = | ||||
|         detail::getTurnCandidates(from, via_edge, node_based_graph, node_info_list, restriction_map, | ||||
|                                   barrier_nodes, compressed_edge_container); | ||||
| 
 | ||||
|     // main priority: roundabouts
 | ||||
|     const auto &in_edge_data = node_based_graph->GetEdgeData(via_edge); | ||||
|     bool on_roundabout = in_edge_data.roundabout; | ||||
|     bool can_enter_roundabout = false; | ||||
|     bool can_exit_roundabout = false; | ||||
|     for (const auto &candidate : turn_candidates) | ||||
|     { | ||||
|         if (node_based_graph->GetEdgeData(candidate.eid).roundabout) | ||||
|         { | ||||
|             can_enter_roundabout = true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             can_exit_roundabout = true; | ||||
|         } | ||||
|     } | ||||
|     if (on_roundabout || can_enter_roundabout) | ||||
|     { | ||||
|         return detail::handleRoundabouts(from, via_edge, on_roundabout, can_enter_roundabout, | ||||
|                                          can_exit_roundabout, std::move(turn_candidates), | ||||
|                                          node_based_graph); | ||||
|     } | ||||
| 
 | ||||
|     turn_candidates = | ||||
|         turn_analysis::setTurnTypes(from, via_edge, std::move(turn_candidates), node_based_graph); | ||||
| #define PRINT_DEBUG_CANDIDATES 0 | ||||
|         detail::setTurnTypes(from, via_edge, std::move(turn_candidates), node_based_graph); | ||||
| 
 | ||||
| #if PRINT_DEBUG_CANDIDATES | ||||
|     std::cout << "Initial Candidates:\n"; | ||||
|     for (auto tc : turn_candidates) | ||||
| @ -65,8 +90,8 @@ getTurns(const NodeID from, | ||||
|                   << (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class | ||||
|                   << std::endl; | ||||
| #endif | ||||
|     turn_candidates = turn_analysis::optimizeCandidates(via_edge, std::move(turn_candidates), | ||||
|                                                         node_based_graph, node_info_list); | ||||
|     turn_candidates = detail::optimizeCandidates(via_edge, std::move(turn_candidates), | ||||
|                                                  node_based_graph, node_info_list); | ||||
| #if PRINT_DEBUG_CANDIDATES | ||||
|     std::cout << "Optimized Candidates:\n"; | ||||
|     for (auto tc : turn_candidates) | ||||
| @ -74,8 +99,7 @@ getTurns(const NodeID from, | ||||
|                   << (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class | ||||
|                   << std::endl; | ||||
| #endif | ||||
|     turn_candidates = | ||||
|         turn_analysis::suppressTurns(via_edge, std::move(turn_candidates), node_based_graph); | ||||
|     turn_candidates = detail::suppressTurns(via_edge, std::move(turn_candidates), node_based_graph); | ||||
| #if PRINT_DEBUG_CANDIDATES | ||||
|     std::cout << "Suppressed Candidates:\n"; | ||||
|     for (auto tc : turn_candidates) | ||||
| @ -86,6 +110,93 @@ getTurns(const NodeID from, | ||||
|     return turn_candidates; | ||||
| } | ||||
| 
 | ||||
| namespace detail | ||||
| { | ||||
| 
 | ||||
| std::vector<TurnCandidate> | ||||
| handleRoundabouts(const NodeID from, | ||||
|                   const EdgeID via_edge, | ||||
|                   const bool on_roundabout, | ||||
|                   const bool can_enter_roundabout, | ||||
|                   const bool can_exit_roundabout, | ||||
|                   std::vector<TurnCandidate> turn_candidates, | ||||
|                   const std::shared_ptr<const util::NodeBasedDynamicGraph> node_based_graph) | ||||
| { | ||||
|     (void)from; | ||||
|     // TODO requires differentiation between roundabouts and rotaries
 | ||||
|     NodeID node_v = node_based_graph->GetTarget(via_edge); | ||||
|     if (on_roundabout) | ||||
|     { | ||||
|         // Shoule hopefully have only a single exit and continue
 | ||||
|         // at least for cars. How about bikes?
 | ||||
|         for (auto &candidate : turn_candidates) | ||||
|         { | ||||
|             const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); | ||||
|             if (out_data.roundabout) | ||||
|             { | ||||
|                 // TODO can forks happen in roundabouts? E.g. required lane changes
 | ||||
|                 if (1 == node_based_graph->GetDirectedOutDegree(node_v)) | ||||
|                 { | ||||
|                     // No turn possible.
 | ||||
|                     candidate.instruction = TurnInstruction::NO_TURN(); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     candidate.instruction = | ||||
|                         TurnInstruction::REMAIN_ROUNDABOUT(getTurnDirection(candidate.angle)); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 candidate.instruction = | ||||
|                     TurnInstruction::EXIT_ROUNDABOUT(getTurnDirection(candidate.angle)); | ||||
|             } | ||||
|         } | ||||
| #if PRINT_DEBUG_CANDIDATES | ||||
|         std::cout << "On Roundabout Candidates:\n"; | ||||
|         for (auto tc : turn_candidates) | ||||
|             std::cout << "\t" << tc.toString() << " " | ||||
|                       << (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class | ||||
|                       << std::endl; | ||||
| #endif | ||||
|         return turn_candidates; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         (void)can_enter_roundabout; | ||||
|         BOOST_ASSERT(can_enter_roundabout); | ||||
|         for (auto &candidate : turn_candidates) | ||||
|         { | ||||
|             const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); | ||||
|             if (out_data.roundabout) | ||||
|             { | ||||
|                 candidate.instruction = | ||||
|                     TurnInstruction::ENTER_ROUNDABOUT(getTurnDirection(candidate.angle)); | ||||
|                 if (can_exit_roundabout) | ||||
|                 { | ||||
|                     if (candidate.instruction.type == TurnType::EnterRotary) | ||||
|                         candidate.instruction.type = TurnType::EnterRotaryAtExit; | ||||
|                     if (candidate.instruction.type == TurnType::EnterRoundabout) | ||||
|                         candidate.instruction.type = TurnType::EnterRoundaboutAtExit; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 candidate.instruction = {TurnType::EnterAndExitRoundabout, | ||||
|                                          getTurnDirection(candidate.angle)}; | ||||
|             } | ||||
|         } | ||||
| #if PRINT_DEBUG_CANDIDATES | ||||
|         std::cout << "Into Roundabout Candidates:\n"; | ||||
|         for (auto tc : turn_candidates) | ||||
|             std::cout << "\t" << tc.toString() << " " | ||||
|                       << (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class | ||||
|                       << std::endl; | ||||
| #endif | ||||
|         return turn_candidates; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| std::vector<TurnCandidate> | ||||
| setTurnTypes(const NodeID from, | ||||
|              const EdgeID via_edge, | ||||
| @ -839,6 +950,7 @@ AnalyzeTurn(const NodeID node_u, | ||||
|     return {TurnType::Turn, getTurnDirection(angle)}; | ||||
| } | ||||
| 
 | ||||
| } // anemspace detail
 | ||||
| } // namespace turn_analysis
 | ||||
| } // namespace extractor
 | ||||
| } // namespace osrm
 | ||||
| } // nameNspace osrm
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user