diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 0eeaeced737..6ac7ccd97b8 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -181,7 +181,9 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod reverse_dist_prefix_sum[i], m_geometry_compressor.GetPositionForID(e1), i, - belongs_to_tiny_cc); + belongs_to_tiny_cc, + forward_data.travel_mode, + reverse_data.travel_mode); current_edge_source_coordinate_id = current_edge_target_coordinate_id; BOOST_ASSERT(m_edge_based_node_list.back().IsCompressed()); @@ -231,7 +233,9 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod 0, SPECIAL_EDGEID, 0, - belongs_to_tiny_cc); + belongs_to_tiny_cc, + forward_data.travel_mode, + reverse_data.travel_mode); BOOST_ASSERT(!m_edge_based_node_list.back().IsCompressed()); } } @@ -500,7 +504,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() } BOOST_ASSERT(u < v); - BOOST_ASSERT(edge_data.type != SHRT_MAX); // Note: edges that end on barrier nodes or on a turn restriction // may actually be in two distinct components. We choose the smallest @@ -648,7 +651,8 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(const std::string &original_edg (edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v), edge_data1.nameID, turn_instruction, - edge_is_compressed); + edge_is_compressed, + edge_data2.travel_mode); ++original_edges_counter; @@ -718,15 +722,6 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u, const EdgeData &data1 = m_node_based_graph->GetEdgeData(edge1); const EdgeData &data2 = m_node_based_graph->GetEdgeData(edge2); - if (!data1.contraFlow && data2.contraFlow) - { - return TurnInstruction::EnterAgainstAllowedDirection; - } - if (data1.contraFlow && !data2.contraFlow) - { - return TurnInstruction::LeaveAgainstAllowedDirection; - } - // roundabouts need to be handled explicitely if (data1.roundabout && data2.roundabout) { diff --git a/DataStructures/EdgeBasedNode.h b/DataStructures/EdgeBasedNode.h index 90f8b7c1177..c88a266d1a5 100644 --- a/DataStructures/EdgeBasedNode.h +++ b/DataStructures/EdgeBasedNode.h @@ -1,6 +1,7 @@ #ifndef EDGE_BASED_NODE_H #define EDGE_BASED_NODE_H +#include "../DataStructures/TravelMode.h" #include "../Util/SimpleLogger.h" #include "../typedefs.h" @@ -25,7 +26,9 @@ struct EdgeBasedNode reverse_offset(0), packed_geometry_id(SPECIAL_EDGEID), fwd_segment_position( std::numeric_limits::max() ), - is_in_tiny_cc(false) + is_in_tiny_cc(false), + forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), + backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) { } explicit EdgeBasedNode( @@ -40,7 +43,9 @@ struct EdgeBasedNode int reverse_offset, unsigned packed_geometry_id, unsigned short fwd_segment_position, - bool belongs_to_tiny_component + bool belongs_to_tiny_component, + TravelMode forward_travel_mode, + TravelMode backward_travel_mode ) : forward_edge_based_node_id(forward_edge_based_node_id), reverse_edge_based_node_id(reverse_edge_based_node_id), @@ -53,7 +58,9 @@ struct EdgeBasedNode reverse_offset(reverse_offset), packed_geometry_id(packed_geometry_id), fwd_segment_position(fwd_segment_position), - is_in_tiny_cc(belongs_to_tiny_component) + is_in_tiny_cc(belongs_to_tiny_component), + forward_travel_mode(forward_travel_mode), + backward_travel_mode(backward_travel_mode) { BOOST_ASSERT((forward_edge_based_node_id != SPECIAL_NODEID) || (reverse_edge_based_node_id != SPECIAL_NODEID)); @@ -85,6 +92,8 @@ struct EdgeBasedNode unsigned packed_geometry_id; // if set, then the edge represents a packed geometry unsigned short fwd_segment_position; // segment id in a compressed geometry bool is_in_tiny_cc; + TravelMode forward_travel_mode : 4; + TravelMode backward_travel_mode : 4; }; #endif //EDGE_BASED_NODE_H diff --git a/DataStructures/ImportEdge.cpp b/DataStructures/ImportEdge.cpp index 0d04b9fb0d9..b59d6149c66 100644 --- a/DataStructures/ImportEdge.cpp +++ b/DataStructures/ImportEdge.cpp @@ -52,17 +52,15 @@ NodeBasedEdge::NodeBasedEdge(NodeID source, EdgeWeight weight, bool forward, bool backward, - short type, bool roundabout, bool in_tiny_cc, bool access_restricted, - bool contra_flow, + TravelMode travel_mode, bool is_split) - : source(source), target(target), name_id(name_id), weight(weight), type(type), + : source(source), target(target), name_id(name_id), weight(weight), forward(forward), backward(backward), roundabout(roundabout), in_tiny_cc(in_tiny_cc), - access_restricted(access_restricted), contra_flow(contra_flow), is_split(is_split) + access_restricted(access_restricted), is_split(is_split), travel_mode(travel_mode) { - BOOST_ASSERT_MSG(type > 0, "negative edge type"); } bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index ecaffc97c0b..4ccbee6d91a 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef IMPORT_EDGE_H #define IMPORT_EDGE_H +#include "../DataStructures/TravelMode.h" #include "../typedefs.h" struct NodeBasedEdge @@ -40,25 +41,23 @@ struct NodeBasedEdge EdgeWeight weight, bool forward, bool backward, - short type, bool roundabout, bool in_tiny_cc, bool access_restricted, - bool contra_flow, + TravelMode travel_mode, bool is_split); NodeID source; NodeID target; NodeID name_id; EdgeWeight weight; - short type; bool forward : 1; bool backward : 1; bool roundabout : 1; bool in_tiny_cc : 1; bool access_restricted : 1; - bool contra_flow : 1; bool is_split : 1; + TravelMode travel_mode : 4; NodeBasedEdge() = delete; }; diff --git a/DataStructures/NodeBasedGraph.h b/DataStructures/NodeBasedGraph.h index 580c71d865c..14b5432d9ad 100644 --- a/DataStructures/NodeBasedGraph.h +++ b/DataStructures/NodeBasedGraph.h @@ -13,23 +13,22 @@ struct NodeBasedEdgeData { NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), - nameID(std::numeric_limits::max()), type(std::numeric_limits::max()), + nameID(std::numeric_limits::max()), isAccessRestricted(false), shortcut(false), forward(false), backward(false), - roundabout(false), ignore_in_grid(false), contraFlow(false) + roundabout(false), ignore_in_grid(false), travel_mode(TRAVEL_MODE_INACCESSIBLE) { } int distance; unsigned edgeBasedNodeID; unsigned nameID; - short type; bool isAccessRestricted : 1; bool shortcut : 1; bool forward : 1; bool backward : 1; bool roundabout : 1; bool ignore_in_grid : 1; - bool contraFlow : 1; + TravelMode travel_mode : 4; void SwapDirectionFlags() { @@ -42,7 +41,7 @@ struct NodeBasedEdgeData { return (forward == other.forward) && (backward == other.backward) && (nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) && - (contraFlow == other.contraFlow); + (travel_mode == other.travel_mode); } }; @@ -91,9 +90,9 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector @@ -38,16 +39,18 @@ struct OriginalEdgeData explicit OriginalEdgeData(NodeID via_node, unsigned name_id, TurnInstruction turn_instruction, - bool compressed_geometry) + bool compressed_geometry, + TravelMode travel_mode) : via_node(via_node), name_id(name_id), turn_instruction(turn_instruction), - compressed_geometry(compressed_geometry) + compressed_geometry(compressed_geometry), travel_mode(travel_mode) { } OriginalEdgeData() : via_node(std::numeric_limits::max()), name_id(std::numeric_limits::max()), - turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false) + turn_instruction(TurnInstruction::NoTurn), compressed_geometry(false), + travel_mode(TRAVEL_MODE_INACCESSIBLE) { } @@ -55,6 +58,7 @@ struct OriginalEdgeData unsigned name_id; TurnInstruction turn_instruction; bool compressed_geometry; + TravelMode travel_mode; }; #endif // ORIGINAL_EDGE_DATA_H diff --git a/DataStructures/PhantomNodes.h b/DataStructures/PhantomNodes.h index c46b1457346..ee9e66d5ff2 100644 --- a/DataStructures/PhantomNodes.h +++ b/DataStructures/PhantomNodes.h @@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define PHANTOM_NODES_H #include +#include "../DataStructures/TravelMode.h" #include "../Util/SimpleLogger.h" #include "../typedefs.h" @@ -39,7 +40,8 @@ struct PhantomNode PhantomNode(NodeID forward_node_id, NodeID reverse_node_id, unsigned name_id, int forward_weight, int reverse_weight, int forward_offset, int reverse_offset, unsigned packed_geometry_id, FixedPointCoordinate &location, - unsigned short fwd_segment_position) : + unsigned short fwd_segment_position, + TravelMode forward_travel_mode, TravelMode backward_travel_mode) : forward_node_id(forward_node_id), reverse_node_id(reverse_node_id), name_id(name_id), @@ -49,7 +51,9 @@ struct PhantomNode reverse_offset(reverse_offset), packed_geometry_id(packed_geometry_id), location(location), - fwd_segment_position(fwd_segment_position) + fwd_segment_position(fwd_segment_position), + forward_travel_mode(forward_travel_mode), + backward_travel_mode(backward_travel_mode) { } PhantomNode() : @@ -61,7 +65,9 @@ struct PhantomNode forward_offset(0), reverse_offset(0), packed_geometry_id(SPECIAL_EDGEID), - fwd_segment_position(0) + fwd_segment_position(0), + forward_travel_mode(TRAVEL_MODE_INACCESSIBLE), + backward_travel_mode(TRAVEL_MODE_INACCESSIBLE) { } NodeID forward_node_id; @@ -74,7 +80,9 @@ struct PhantomNode unsigned packed_geometry_id; FixedPointCoordinate location; unsigned short fwd_segment_position; - + TravelMode forward_travel_mode : 4; + TravelMode backward_travel_mode : 4; + int GetForwardWeightPlusOffset() const { if (SPECIAL_NODEID == forward_node_id) diff --git a/DataStructures/RawRouteData.h b/DataStructures/RawRouteData.h index f799841b2ff..d92242e7fa7 100644 --- a/DataStructures/RawRouteData.h +++ b/DataStructures/RawRouteData.h @@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define RAW_ROUTE_DATA_H #include "../DataStructures/PhantomNodes.h" +#include "../DataStructures/TravelMode.h" #include "../DataStructures/TurnInstructions.h" #include "../typedefs.h" @@ -41,18 +42,25 @@ struct PathData PathData() : node(SPECIAL_NODEID), name_id(INVALID_EDGE_WEIGHT), segment_duration(INVALID_EDGE_WEIGHT), - turn_instruction(TurnInstruction::NoTurn) + turn_instruction(TurnInstruction::NoTurn), + travel_mode(TRAVEL_MODE_INACCESSIBLE) { } - PathData(NodeID node, unsigned name_id, TurnInstruction turn_instruction, EdgeWeight segment_duration) - : node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction) + PathData(NodeID node, + unsigned name_id, + TurnInstruction turn_instruction, + EdgeWeight segment_duration, + TravelMode travel_mode) + : node(node), name_id(name_id), segment_duration(segment_duration), turn_instruction(turn_instruction), + travel_mode(travel_mode) { } NodeID node; unsigned name_id; EdgeWeight segment_duration; TurnInstruction turn_instruction; + TravelMode travel_mode : 4; }; struct RawRouteData diff --git a/DataStructures/SegmentInformation.h b/DataStructures/SegmentInformation.h index f145804491f..6e8d6839747 100644 --- a/DataStructures/SegmentInformation.h +++ b/DataStructures/SegmentInformation.h @@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "TurnInstructions.h" +#include "../DataStructures/TravelMode.h" #include "../typedefs.h" #include @@ -43,8 +44,9 @@ struct SegmentInformation float length; short bearing; // more than enough [0..3600] fits into 12 bits TurnInstruction turn_instruction; - bool necessary:1; - bool is_via_location:1; + TravelMode travel_mode; + bool necessary; + bool is_via_location; explicit SegmentInformation(const FixedPointCoordinate &location, const NodeID name_id, @@ -52,9 +54,11 @@ struct SegmentInformation const float length, const TurnInstruction turn_instruction, const bool necessary, - const bool is_via_location) + const bool is_via_location, + const TravelMode travel_mode) : location(location), name_id(name_id), duration(duration), length(length), bearing(0), - turn_instruction(turn_instruction), necessary(necessary), is_via_location(is_via_location) + turn_instruction(turn_instruction), travel_mode(travel_mode), necessary(necessary), + is_via_location(is_via_location) { } @@ -62,9 +66,11 @@ struct SegmentInformation const NodeID name_id, const EdgeWeight duration, const float length, - const TurnInstruction turn_instruction) + const TurnInstruction turn_instruction, + const TravelMode travel_mode) : location(location), name_id(name_id), duration(duration), length(length), bearing(0), - turn_instruction(turn_instruction), necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false) + turn_instruction(turn_instruction), travel_mode(travel_mode), + necessary(turn_instruction != TurnInstruction::NoTurn), is_via_location(false) { } }; diff --git a/DataStructures/StaticRTree.h b/DataStructures/StaticRTree.h index b17f61428f0..05e56045013 100644 --- a/DataStructures/StaticRTree.h +++ b/DataStructures/StaticRTree.h @@ -801,7 +801,9 @@ class StaticRTree current_segment.reverse_offset, current_segment.packed_geometry_id, foot_point_coordinate_on_segment, - current_segment.fwd_segment_position); + current_segment.fwd_segment_position, + current_segment.forward_travel_mode, + current_segment.backward_travel_mode); // Hack to fix rounding errors and wandering via nodes. FixUpRoundingIssue(input_coordinate, result_phantom_node_vector.back()); @@ -1077,7 +1079,9 @@ class StaticRTree current_edge.reverse_offset, current_edge.packed_geometry_id, nearest, - current_edge.fwd_segment_position}; + current_edge.fwd_segment_position, + current_edge.forward_travel_mode, + current_edge.backward_travel_mode}; nearest_edge = current_edge; } } diff --git a/DataStructures/TravelMode.h b/DataStructures/TravelMode.h new file mode 100644 index 00000000000..7ccc24d215e --- /dev/null +++ b/DataStructures/TravelMode.h @@ -0,0 +1,35 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TRAVEL_MODE_H +#define TRAVEL_MODE_H + +using TravelMode = unsigned char; +static const TravelMode TRAVEL_MODE_INACCESSIBLE = 0; +static const TravelMode TRAVEL_MODE_DEFAULT = 1; + +#endif /* TRAVEL_MODE_H */ diff --git a/Descriptors/DescriptionFactory.cpp b/Descriptors/DescriptionFactory.cpp index 38f2f32fe26..e8346fdcf09 100644 --- a/Descriptors/DescriptionFactory.cpp +++ b/Descriptors/DescriptionFactory.cpp @@ -45,8 +45,11 @@ void DescriptionFactory::SetStartSegment(const PhantomNode &source, const bool t start_phantom = source; const EdgeWeight segment_duration = (traversed_in_reverse ? source.reverse_weight : source.forward_weight); - AppendSegment(source.location, - PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration)); + const TravelMode travel_mode = + (traversed_in_reverse ? source.backward_travel_mode : source.forward_travel_mode); + AppendSegment( + source.location, + PathData(0, source.name_id, TurnInstruction::HeadOn, segment_duration, travel_mode)); BOOST_ASSERT(path_description.back().duration == segment_duration); } @@ -57,6 +60,8 @@ void DescriptionFactory::SetEndSegment(const PhantomNode &target, target_phantom = target; const EdgeWeight segment_duration = (traversed_in_reverse ? target.reverse_weight : target.forward_weight); + const TravelMode travel_mode = + (traversed_in_reverse ? target.backward_travel_mode : target.forward_travel_mode); path_description.emplace_back(target.location, target.name_id, segment_duration, @@ -64,24 +69,44 @@ void DescriptionFactory::SetEndSegment(const PhantomNode &target, is_via_location ? TurnInstruction::ReachViaLocation : TurnInstruction::NoTurn, true, - true); + true, + travel_mode); BOOST_ASSERT(path_description.back().duration == segment_duration); } void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate, const PathData &path_point) { - if ((1 == path_description.size()) && (path_description.back().location == coordinate)) + // if the start location is on top of a node, the first movement might be zero-length, + // in which case we dont' add a new description, but instead update the existing one + if ((1 == path_description.size()) && (path_description.front().location == coordinate)) { - path_description.back().name_id = path_point.name_id; + if (path_point.segment_duration > 0) + { + path_description.front().name_id = path_point.name_id; + path_description.front().travel_mode = path_point.travel_mode; + } return; } + // make sure mode changes are announced, even when there otherwise is no turn + const TurnInstruction turn = [&]() -> TurnInstruction + { + if (TurnInstruction::NoTurn == path_point.turn_instruction && + path_description.front().travel_mode != path_point.travel_mode && + path_point.segment_duration > 0) + { + return TurnInstruction::GoStraight; + } + return path_point.turn_instruction; + }(); + path_description.emplace_back(coordinate, path_point.name_id, path_point.segment_duration, 0.f, - path_point.turn_instruction); + turn, + path_point.travel_mode); } JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded) diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index c5e1becba7f..33728b7406a 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -356,6 +356,7 @@ template class JSONDescriptor : public BaseDescriptor(round(bearing_value))); + json_instruction_row.values.push_back(segment.travel_mode); route_segments_list.emplace_back( segment.name_id, diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp index 91981d66a00..3386446545b 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -330,7 +330,6 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, edge_iterator->source_coordinate.lon != std::numeric_limits::min()) { BOOST_ASSERT(edge_iterator->speed != -1); - BOOST_ASSERT(edge_iterator->type >= 0); edge_iterator->target_coordinate.lat = node_iterator->lat; edge_iterator->target_coordinate.lon = node_iterator->lon; @@ -371,12 +370,15 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name, } file_out_stream.write((char *)&integer_weight, sizeof(int)); - file_out_stream.write((char *)&edge_iterator->type, sizeof(short)); file_out_stream.write((char *)&edge_iterator->name_id, sizeof(unsigned)); file_out_stream.write((char *)&edge_iterator->is_roundabout, sizeof(bool)); file_out_stream.write((char *)&edge_iterator->is_in_tiny_cc, sizeof(bool)); file_out_stream.write((char *)&edge_iterator->is_access_restricted, sizeof(bool)); - file_out_stream.write((char *)&edge_iterator->is_contra_flow, sizeof(bool)); + + // cannot take adress of bit field, so use local + const TravelMode travel_mode = edge_iterator->travel_mode; + file_out_stream.write((char *)&travel_mode, sizeof(TravelMode)); + file_out_stream.write((char *)&edge_iterator->is_split, sizeof(bool)); ++number_of_used_edges; } diff --git a/Extractor/ExtractionWay.h b/Extractor/ExtractionWay.h index 6c3c93d63e2..36c138f8966 100644 --- a/Extractor/ExtractionWay.h +++ b/Extractor/ExtractionWay.h @@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define EXTRACTION_WAY_H #include "../DataStructures/HashTable.h" +#include "../DataStructures/TravelMode.h" #include "../typedefs.h" #include @@ -44,15 +45,15 @@ struct ExtractionWay nameID = INVALID_NAMEID; path.clear(); keyVals.Clear(); - direction = ExtractionWay::notSure; - speed = -1; + forward_speed = -1; backward_speed = -1; duration = -1; - type = -1; access = true; roundabout = false; isAccessRestricted = false; ignoreInGrid = false; + forward_travel_mode = TRAVEL_MODE_DEFAULT; + backward_travel_mode = TRAVEL_MODE_DEFAULT; } enum Directions @@ -60,20 +61,70 @@ struct ExtractionWay oneway, bidirectional, opposite }; + + // These accessor methods exists to support the depreciated "way.direction" access + // in LUA. Since the direction attribute was removed from ExtractionWay, the + // accessors translate to/from the mode attributes. + inline void set_direction(const Directions m) + { + if (Directions::oneway == m) + { + forward_travel_mode = TRAVEL_MODE_DEFAULT; + backward_travel_mode = TRAVEL_MODE_INACCESSIBLE; + } + else if (Directions::opposite == m) + { + forward_travel_mode = TRAVEL_MODE_INACCESSIBLE; + backward_travel_mode = TRAVEL_MODE_DEFAULT; + } + else if (Directions::bidirectional == m) + { + forward_travel_mode = TRAVEL_MODE_DEFAULT; + backward_travel_mode = TRAVEL_MODE_DEFAULT; + } + } + + inline const Directions get_direction() const + { + if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode && TRAVEL_MODE_INACCESSIBLE != backward_travel_mode) + { + return Directions::bidirectional; + } + else if (TRAVEL_MODE_INACCESSIBLE != forward_travel_mode) + { + return Directions::oneway; + } + else if (TRAVEL_MODE_INACCESSIBLE != backward_travel_mode) + { + return Directions::opposite; + } + else + { + return Directions::notSure; + } + } + + // These accessors exists because it's not possible to take the address of a bitfield, + // and LUA therefore cannot read/write the mode attributes directly. + inline void set_forward_mode(const TravelMode m) { forward_travel_mode = m; } + inline const TravelMode get_forward_mode() const { return forward_travel_mode; } + inline void set_backward_mode(const TravelMode m) { backward_travel_mode = m; } + inline const TravelMode get_backward_mode() const { return backward_travel_mode; } + unsigned id; unsigned nameID; - double speed; + double forward_speed; double backward_speed; double duration; - Directions direction; std::string name; - short type; bool access; bool roundabout; bool isAccessRestricted; bool ignoreInGrid; std::vector path; HashTable keyVals; + TravelMode forward_travel_mode : 4; + TravelMode backward_travel_mode : 4; }; #endif // EXTRACTION_WAY_H diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 5e27817c683..c2cc693c323 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -63,7 +63,11 @@ bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &res /** warning: caller needs to take care of synchronization! */ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way) { - if ((0 >= parsed_way.speed) && (0 >= parsed_way.duration)) + 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)) { // Only true if the way is specified by the speed profile return; } @@ -84,10 +88,10 @@ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way) { // TODO: iterate all way segments and set duration corresponding to the length of each // segment - parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1); + parsed_way.forward_speed = parsed_way.duration / (parsed_way.path.size() - 1); } - if (std::numeric_limits::epsilon() >= std::abs(-1. - parsed_way.speed)) + if (std::numeric_limits::epsilon() >= std::abs(-1. - parsed_way.forward_speed)) { SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id; return; @@ -106,29 +110,34 @@ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way) parsed_way.nameID = string_map_iterator->second; } - if (ExtractionWay::opposite == parsed_way.direction) + if (TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode) { std::reverse(parsed_way.path.begin(), parsed_way.path.end()); - parsed_way.direction = ExtractionWay::oneway; + parsed_way.forward_travel_mode = parsed_way.backward_travel_mode; + parsed_way.backward_travel_mode = TRAVEL_MODE_INACCESSIBLE; } const bool split_edge = - (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed); + (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) || + (parsed_way.forward_travel_mode != parsed_way.backward_travel_mode)); + BOOST_ASSERT(parsed_way.forward_travel_mode>0); for (unsigned n = 0; n < (parsed_way.path.size() - 1); ++n) { external_memory.all_edges_list.push_back(InternalExtractorEdge( parsed_way.path[n], parsed_way.path[n + 1], - parsed_way.type, - (split_edge ? ExtractionWay::oneway : parsed_way.direction), - parsed_way.speed, + ((split_edge || TRAVEL_MODE_INACCESSIBLE == parsed_way.backward_travel_mode) ? ExtractionWay::oneway + : ExtractionWay::bidirectional), + parsed_way.forward_speed, parsed_way.nameID, parsed_way.roundabout, parsed_way.ignoreInGrid, (0 < parsed_way.duration), parsed_way.isAccessRestricted, - false, + parsed_way.forward_travel_mode, split_edge)); external_memory.used_node_id_list.push_back(parsed_way.path[n]); } @@ -144,13 +153,13 @@ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way) if (split_edge) { // Only true if the way should be split + BOOST_ASSERT(parsed_way.backward_travel_mode>0); std::reverse(parsed_way.path.begin(), parsed_way.path.end()); for (std::vector::size_type n = 0; n < parsed_way.path.size() - 1; ++n) { external_memory.all_edges_list.push_back( InternalExtractorEdge(parsed_way.path[n], parsed_way.path[n + 1], - parsed_way.type, ExtractionWay::oneway, parsed_way.backward_speed, parsed_way.nameID, @@ -158,7 +167,7 @@ void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way) parsed_way.ignoreInGrid, (0 < parsed_way.duration), parsed_way.isAccessRestricted, - (ExtractionWay::oneway == parsed_way.direction), + parsed_way.backward_travel_mode, split_edge)); } external_memory.way_start_end_id_list.push_back( diff --git a/Extractor/InternalExtractorEdge.h b/Extractor/InternalExtractorEdge.h index 852f9f92943..848b24fb345 100644 --- a/Extractor/InternalExtractorEdge.h +++ b/Extractor/InternalExtractorEdge.h @@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INTERNAL_EXTRACTOR_EDGE_H #include "../typedefs.h" +#include "../DataStructures/TravelMode.h" #include #include @@ -36,15 +37,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct InternalExtractorEdge { InternalExtractorEdge() - : start(0), target(0), type(0), direction(0), speed(0), name_id(0), is_roundabout(false), + : start(0), target(0), direction(0), speed(0), name_id(0), is_roundabout(false), is_in_tiny_cc(false), is_duration_set(false), is_access_restricted(false), - is_contra_flow(false), is_split(false) + travel_mode(TRAVEL_MODE_INACCESSIBLE), is_split(false) { } explicit InternalExtractorEdge(NodeID start, NodeID target, - short type, short direction, double speed, unsigned name_id, @@ -52,30 +52,28 @@ struct InternalExtractorEdge bool is_in_tiny_cc, bool is_duration_set, bool is_access_restricted, - bool is_contra_flow, + TravelMode travel_mode, bool is_split) - : start(start), target(target), type(type), direction(direction), speed(speed), + : start(start), target(target), direction(direction), speed(speed), name_id(name_id), is_roundabout(is_roundabout), is_in_tiny_cc(is_in_tiny_cc), is_duration_set(is_duration_set), is_access_restricted(is_access_restricted), - is_contra_flow(is_contra_flow), is_split(is_split) + travel_mode(travel_mode), is_split(is_split) { - BOOST_ASSERT(0 <= type); } // necessary static util functions for stxxl's sorting static InternalExtractorEdge min_value() { - return InternalExtractorEdge(0, 0, 0, 0, 0, 0, false, false, false, false, false, false); + return InternalExtractorEdge(0, 0, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false); } static InternalExtractorEdge max_value() { return InternalExtractorEdge( - SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, 0, false, false, false, false, false, false); + SPECIAL_NODEID, SPECIAL_NODEID, 0, 0, 0, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false); } NodeID start; NodeID target; - short type; short direction; double speed; unsigned name_id; @@ -83,7 +81,7 @@ struct InternalExtractorEdge bool is_in_tiny_cc; bool is_duration_set; bool is_access_restricted; - bool is_contra_flow; + TravelMode travel_mode : 4; bool is_split; FixedPointCoordinate source_coordinate; diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index 660c35ca7fc..b9fd608e13b 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -76,16 +76,17 @@ void ScriptingEnvironment::initLuaState(lua_State* lua_state) // .def(luabind::constructor<>()) .def_readonly("id", &ExtractionWay::id) .def_readwrite("name", &ExtractionWay::name) - .def_readwrite("speed", &ExtractionWay::speed) + .def_readwrite("forward_speed", &ExtractionWay::forward_speed) .def_readwrite("backward_speed", &ExtractionWay::backward_speed) .def_readwrite("duration", &ExtractionWay::duration) - .def_readwrite("type", &ExtractionWay::type) .def_readwrite("access", &ExtractionWay::access) .def_readwrite("roundabout", &ExtractionWay::roundabout) .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted) .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid) .def_readwrite("tags", &ExtractionWay::keyVals) - .def_readwrite("direction", &ExtractionWay::direction) + .property("direction", &ExtractionWay::get_direction, &ExtractionWay::set_direction) + .property("forward_mode", &ExtractionWay::get_forward_mode, &ExtractionWay::set_forward_mode) + .property("backward_mode", &ExtractionWay::get_backward_mode, &ExtractionWay::set_backward_mode) .enum_("constants")[ luabind::value("notSure", 0), luabind::value("oneway", 1), diff --git a/Rakefile b/Rakefile index 1c2ce9ded80..21e95cfb230 100644 --- a/Rakefile +++ b/Rakefile @@ -6,7 +6,7 @@ require 'sys/proctable' BUILD_FOLDER = 'build' DATA_FOLDER = 'sandbox' -PROFILE = 'examples/postgis' +PROFILE = 'bicycle' OSRM_PORT = 5000 PROFILES_FOLDER = '../profiles' diff --git a/RoutingAlgorithms/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h index 807a8610ffb..1926e9e7729 100644 --- a/RoutingAlgorithms/BasicRoutingInterface.h +++ b/RoutingAlgorithms/BasicRoutingInterface.h @@ -227,6 +227,8 @@ template class BasicRoutingInterface BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut"); unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id); const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id); + const TravelMode travel_mode = facade->GetTravelModeForEdgeID(ed.id); + if (!facade->EdgeIsCompressed(ed.id)) { @@ -234,7 +236,8 @@ template class BasicRoutingInterface unpacked_path.emplace_back(facade->GetGeometryIndexForEdgeID(ed.id), name_index, turn_instruction, - ed.distance); + ed.distance, + travel_mode); } else { @@ -255,7 +258,7 @@ template class BasicRoutingInterface BOOST_ASSERT(start_index <= end_index); for (std::size_t i = start_index; i < end_index; ++i) { - unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0); + unpacked_path.emplace_back(id_vector[i], name_index, TurnInstruction::NoTurn, 0, travel_mode); } unpacked_path.back().turn_instruction = turn_instruction; unpacked_path.back().segment_duration = ed.distance; @@ -298,10 +301,12 @@ template class BasicRoutingInterface for (std::size_t i = start_index; i != end_index; (start_index < end_index ? ++i : --i)) { BOOST_ASSERT(i < id_vector.size()); + BOOST_ASSERT(phantom_node_pair.target_phantom.forward_travel_mode>0 ); unpacked_path.emplace_back(PathData{id_vector[i], - phantom_node_pair.target_phantom.name_id, - TurnInstruction::NoTurn, - 0}); + phantom_node_pair.target_phantom.name_id, + TurnInstruction::NoTurn, + 0, + phantom_node_pair.target_phantom.forward_travel_mode}); } } diff --git a/Server/DataStructures/BaseDataFacade.h b/Server/DataStructures/BaseDataFacade.h index 4f2ba544656..33695cbc850 100644 --- a/Server/DataStructures/BaseDataFacade.h +++ b/Server/DataStructures/BaseDataFacade.h @@ -92,6 +92,8 @@ template class BaseDataFacade virtual TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const = 0; + virtual TravelMode GetTravelModeForEdgeID(const unsigned id) const = 0; + virtual bool LocateClosestEndPointForCoordinate(const FixedPointCoordinate &input_coordinate, FixedPointCoordinate &result, const unsigned zoom_level = 18) = 0; diff --git a/Server/DataStructures/InternalDataFacade.h b/Server/DataStructures/InternalDataFacade.h index 3abab2aba93..5f0a2517bf4 100644 --- a/Server/DataStructures/InternalDataFacade.h +++ b/Server/DataStructures/InternalDataFacade.h @@ -66,6 +66,7 @@ template class InternalDataFacade : public BaseDataFacade::vector m_via_node_list; ShM::vector m_name_ID_list; ShM::vector m_turn_instruction_list; + ShM::vector m_travel_mode_list; ShM::vector m_names_char_list; ShM::vector m_egde_is_compressed; ShM::vector m_geometry_indices; @@ -145,6 +146,7 @@ template class InternalDataFacade : public BaseDataFacade class InternalDataFacade : public BaseDataFacade class InternalDataFacade : public BaseDataFacade class SharedDataFacade : public BaseDataFacade::vector m_via_node_list; ShM::vector m_name_ID_list; ShM::vector m_turn_instruction_list; + ShM::vector m_travel_mode_list; ShM::vector m_names_char_list; ShM::vector m_name_begin_indices; ShM::vector m_egde_is_compressed; @@ -346,6 +347,11 @@ template class SharedDataFacade : public BaseDataFacade 0, "loaded null length edge"); @@ -161,8 +159,6 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, forward = false; } - BOOST_ASSERT(type >= 0); - // translate the external NodeIDs to internal IDs auto internal_id_iter = ext_to_int_id_map.find(source); if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end()) @@ -196,11 +192,10 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, weight, forward, backward, - type, is_roundabout, ignore_in_grid, is_access_restricted, - is_contra_flow, + travel_mode, is_split); } @@ -303,10 +298,10 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, edge_list.reserve(m); EdgeWeight weight; - short type; NodeID nameID; int length; - bool is_roundabout, ignore_in_grid, is_access_restricted, is_contra_flow, is_split; + bool is_roundabout, ignore_in_grid, is_access_restricted, is_split; + TravelMode travel_mode; for (EdgeID i = 0; i < m; ++i) { @@ -315,20 +310,17 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &input_stream, input_stream.read((char *)&length, sizeof(int)); input_stream.read((char *)&dir, sizeof(short)); input_stream.read((char *)&weight, sizeof(int)); - input_stream.read((char *)&type, sizeof(short)); input_stream.read((char *)&nameID, sizeof(unsigned)); input_stream.read((char *)&is_roundabout, sizeof(bool)); input_stream.read((char *)&ignore_in_grid, sizeof(bool)); input_stream.read((char *)&is_access_restricted, sizeof(bool)); - input_stream.read((char *)&is_contra_flow, sizeof(bool)); + input_stream.read((char *)&travel_mode, sizeof(TravelMode)); input_stream.read((char *)&is_split, sizeof(bool)); BOOST_ASSERT_MSG(length > 0, "loaded null length edge"); BOOST_ASSERT_MSG(weight > 0, "loaded null weight"); BOOST_ASSERT_MSG(0 <= dir && dir <= 2, "loaded bogus direction"); - BOOST_ASSERT(type >= 0); - // translate the external NodeIDs to internal IDs auto internal_id_iter = ext_to_int_id_map.find(source); if (ext_to_int_id_map.find(source) == ext_to_int_id_map.end()) diff --git a/features/bicycle/mode.feature b/features/bicycle/mode.feature index eac04302c09..2bfa4de5b37 100644 --- a/features/bicycle/mode.feature +++ b/features/bicycle/mode.feature @@ -1,89 +1,177 @@ @routing @bicycle @mode Feature: Bike - Mode flag - Background: - Given the profile "bicycle" +# bicycle modes: +# 1 bike +# 2 pushing +# 3 ferry +# 4 train - @todo + Background: + Given the profile "bicycle" + Scenario: Bike - Mode when using a ferry - Given the node map - | a | b | | - | | c | d | + Given the node map + | a | b | | + | | c | d | - And the ways - | nodes | highway | route | duration | - | ab | primary | | | - | bc | | ferry | 0:01 | - | cd | primary | | | + And the ways + | nodes | highway | route | duration | + | ab | primary | | | + | bc | | ferry | 0:01 | + | cd | primary | | | - When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd | head,right,left, destination | bike,ferry,bike | - | d | a | cd,bc,ab | head,right,left, destination | bike,ferry,bike | - | c | a | bc,ab | head,left,destination | ferry,bike | - | d | b | cd,bc | head,right,destination | bike,ferry | - | a | c | ab,bc | head,right,destination | bike,ferry | - | b | d | bc,cd | head,left,destination | ferry,bike | - - @todo - Scenario: Bike - Mode when pushing bike against oneways - Given the node map - | a | b | | - | | c | d | + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,3,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,3,1 | + | c | a | bc,ab | head,left,destination | 3,1 | + | d | b | cd,bc | head,right,destination | 1,3 | + | a | c | ab,bc | head,right,destination | 1,3 | + | b | d | bc,cd | head,left,destination | 3,1 | - And the ways - | nodes | highway | oneway | - | ab | primary | | - | bc | primary | yes | - | cd | primary | | + Scenario: Bike - Mode when using a train + Given the node map + | a | b | | + | | c | d | - When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd | head,right,left,destination | bike,push,bike | - | d | a | cd,bc,ab | head,right,left,destination | bike,push,bike | - | c | a | bc,ab | head,left,destination | push,bike | - | d | b | cd,bc | head,right,destination | bike,push | - | a | c | ab,bc | head,right,destination | bike,push | - | b | d | bc,cd | head,left,destination | push,bike | - - @todo - Scenario: Bike - Mode when pushing on pedestrain streets + And the ways + | nodes | highway | railway | bicycle | + | ab | primary | | | + | bc | | train | yes | + | cd | primary | | | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,4,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,4,1 | + | c | a | bc,ab | head,left,destination | 4,1 | + | d | b | cd,bc | head,right,destination | 1,4 | + | a | c | ab,bc | head,right,destination | 1,4 | + | b | d | bc,cd | head,left,destination | 4,1 | + + Scenario: Bike - Mode when pushing bike against oneways + Given the node map + | a | b | | + | | c | d | + + And the ways + | nodes | highway | oneway | + | ab | primary | | + | bc | primary | yes | + | cd | primary | | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,1,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,1 | + | b | d | bc,cd | head,left,destination | 1,1 | + + Scenario: Bike - Mode when pushing on pedestrain streets + Given the node map + | a | b | | + | | c | d | + + And the ways + | nodes | highway | + | ab | primary | + | bc | pedestrian | + | cd | primary | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,2 | + | b | d | bc,cd | head,left,destination | 2,1 | + + Scenario: Bike - Mode when pushing on pedestrain areas + Given the node map + | a | b | | | + | | c | d | f | + + And the ways + | nodes | highway | area | + | ab | primary | | + | bcd | pedestrian | yes | + | df | primary | | + + When I route I should get + | from | to | route | modes | + | a | f | ab,bcd,df | 1,2,1 | + | f | a | df,bcd,ab | 1,2,1 | + | d | a | bcd,ab | 2,1 | + | f | b | df,bcd | 1,2 | + | a | d | ab,bcd | 1,2 | + | b | f | bcd,df | 2,1 | + + Scenario: Bike - Mode when pushing on steps + Given the node map + | a | b | | | + | | c | d | f | + + And the ways + | nodes | highway | + | ab | primary | + | bc | steps | + | cd | primary | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,2 | + | b | d | bc,cd | head,left,destination | 2,1 | + + Scenario: Bike - Mode when bicycle=dismount + Given the node map + | a | b | | | + | | c | d | f | + + And the ways + | nodes | highway | bicycle | + | ab | primary | | + | bc | primary | dismount | + | cd | primary | | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,2 | + | b | d | bc,cd | head,left,destination | 2,1 | + + Scenario: Bicycle - Modes when starting on forward oneway Given the node map - | a | b | | - | | c | d | + | a | b | And the ways - | nodes | highway | - | ab | primary | - | bc | pedestrian | - | cd | primary | + | nodes | oneway | + | ab | yes | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd | head,right,left,destination | bike,push,bike | - | d | a | cd,bc,ab | head,right,left,destination | bike,push,bike | - | c | a | bc,ab | head,left,destination | push,bike | - | d | b | cd,bc | head,right,destination | bike,push | - | a | c | ab,bc | head,right,destination | bike,push | - | b | d | bc,cd | head,left,destination | push,bike | - - @todo - Scenario: Bike - Mode when pushing on pedestrain areas + | from | to | route | modes | + | a | b | ab | 1 | + | b | a | ab | 2 | + + Scenario: Bicycle - Modes when starting on reverse oneway Given the node map - | a | b | | | - | | c | d | f | + | a | b | And the ways - | nodes | highway | area | - | ab | primary | | - | bcd | pedestrian | yes | - | df | primary | | + | nodes | oneway | + | ab | -1 | When I route I should get - | from | to | route | modes | - | a | f | ab,bcd,df | bike,push,bike | - | f | a | df,bcd,ab | bike,push,bike | - | d | a | bcd,ab | push,bike | - | f | b | df,bcd | bike,push | - | a | d | ab,bcd | bike,push | - | b | f | bcd,df | push,bike | + | from | to | route | modes | + | a | b | ab | 2 | + | b | a | ab | 1 | diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 2b238292a3f..5741fb1c0a0 100644 --- a/features/bicycle/pushing.feature +++ b/features/bicycle/pushing.feature @@ -4,9 +4,9 @@ Feature: Bike - Accessability of different way types Background: Given the profile "bicycle" Given the shortcuts - | key | value | - | bike | 49s ~20% | - | foot | 121s ~20% | + | key | value | + | bike | 15 km/h ~20% | + | foot | 5 km/h ~20% | Scenario: Bike - Pushing bikes on pedestrian-only ways Then routability should be @@ -98,11 +98,11 @@ Feature: Bike - Accessability of different way types | cd | primary | | When I route I should get - | from | to | route | turns | - | a | d | ab,bc,cd | head,right,left,destination | - | d | a | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination | - | c | a | bc,ab | head,leave_contraflow,destination | - | d | b | cd,bc | head,enter_contraflow,destination | + | from | to | route | turns | + | a | d | ab,bc,cd | head,right,left,destination | + | d | a | cd,bc,ab | head,right,left,destination | + | c | a | bc,ab | head,left,destination | + | d | b | cd,bc | head,right,destination | @todo Scenario: Bike - Instructions when pushing bike on footway/pedestrian, etc. @@ -117,8 +117,8 @@ Feature: Bike - Accessability of different way types | cd | primary | When I route I should get - | from | to | route | turns | - | a | d | ab,bc,cd | head,right,left,destination | - | d | a | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination | - | c | a | bc,ab | head,leave_contraflow,destination | - | d | b | cd,bc | head,enter_contraflow,destination | + | from | to | route | turns | + | a | d | ab,bc,cd | head,right,left,destination | + | d | a | cd,bc,ab | head,right,left,destination | + | c | a | bc,ab | head,left,destination | + | d | b | cd,bc | head,right,destination | diff --git a/features/car/ferry.feature b/features/car/ferry.feature index 3e90cf00539..7d16c2ed200 100644 --- a/features/car/ferry.feature +++ b/features/car/ferry.feature @@ -17,12 +17,12 @@ Feature: Car - Handle ferry routes | efg | primary | | | When I route I should get - | from | to | route | - | a | g | abc,cde,efg | - | b | f | abc,cde,efg | - | e | c | cde | - | e | b | cde,abc | - | e | a | cde,abc | - | c | e | cde | - | c | f | cde,efg | - | c | g | cde,efg | + | from | to | route | modes | + | a | g | abc,cde,efg | 1,2,1 | + | b | f | abc,cde,efg | 1,2,1 | + | e | c | cde | 2 | + | e | b | cde,abc | 2,1 | + | e | a | cde,abc | 2,1 | + | c | e | cde | 2 | + | c | f | cde,efg | 2,1 | + | c | g | cde,efg | 2,1 | diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 9e77cde74fb..7bb45809deb 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -38,14 +38,14 @@ OSRM will use 4/5 of the projected free-flow speed. Given a grid size of 100 meters Then routability should be - | highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | - | primary | | | | 51 km/h | 51 km/h | - | primary | 60 | | | 48 km/h | 48 km/h | - | primary | | 60 | | 48 km/h | 65 km/h | - | primary | | | 60 | 51 km/h | 48 km/h | - | primary | 15 | 60 | | 48 km/h | 15 km/h +- 1 | - | primary | 15 | | 60 | 12 km/h +- 1| 48 km/h | - | primary | 15 | 30 | 60 | 24 km/h | 48 km/h | + | highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | + | primary | | | | 51 km/h | 51 km/h | + | primary | 60 | | | 48 km/h | 48 km/h | + | primary | | 60 | | 48 km/h | 51 km/h | + | primary | | | 60 | 51 km/h | 48 km/h | + | primary | 15 | 60 | | 48 km/h | 12 km/h | + | primary | 15 | | 60 | 12 km/h | 48 km/h | + | primary | 15 | 30 | 60 | 24 km/h | 48 km/h | Scenario: Car - Maxspeed should not allow routing on unroutable ways Then routability should be diff --git a/features/foot/ferry.feature b/features/foot/ferry.feature index 43087565592..866644d26a7 100644 --- a/features/foot/ferry.feature +++ b/features/foot/ferry.feature @@ -17,15 +17,15 @@ Feature: Foot - Handle ferry routes | efg | primary | | | When I route I should get - | from | to | route | - | a | g | abc,cde,efg | - | b | f | abc,cde,efg | - | e | c | cde | - | e | b | cde,abc | - | e | a | cde,abc | - | c | e | cde | - | c | f | cde,efg | - | c | g | cde,efg | + | from | to | route | modes | + | a | g | abc,cde,efg | 1,2,1 | + | b | f | abc,cde,efg | 1,2,1 | + | e | c | cde | 2 | + | e | b | cde,abc | 2,1 | + | e | a | cde,abc | 2,1 | + | c | e | cde | 2 | + | c | f | cde,efg | 2,1 | + | c | g | cde,efg | 2,1 | Scenario: Foot - Ferry duration, single node Given the node map diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb index 03336e583d3..48f7f24de3c 100644 --- a/features/step_definitions/routability.rb +++ b/features/step_definitions/routability.rb @@ -54,11 +54,11 @@ def test_routability_row i want = shortcuts_hash[row[direction]] || row[direction] #expand shortcuts case want when '', 'x' - output_row[direction] = result[direction][:status].to_s + output_row[direction] = result[direction][:status] ? result[direction][:status].to_s : '' when /^\d+s/ - output_row[direction] = "#{result[direction][:time]}s" + output_row[direction] = result[direction][:time] ? "#{result[direction][:time]}s" : '' when /^\d+ km\/h/ - output_row[direction] = "#{result[direction][:speed]} km/h" + output_row[direction] = result[direction][:speed] ? "#{result[direction][:speed]} km/h" : '' else raise "*** Unknown expectation format: #{want}" end diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 73bd5381d12..4d944f32b3e 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -104,22 +104,22 @@ end end if table.headers.include? 'bearing' - got['bearing'] = bearings + got['bearing'] = instructions ? bearings : '' end if table.headers.include? 'compass' - got['compass'] = compasses + got['compass'] = instructions ? compasses : '' end if table.headers.include? 'turns' - got['turns'] = turns + got['turns'] = instructions ? turns : '' end if table.headers.include? 'modes' - got['modes'] = modes + got['modes'] = instructions ? modes : '' end if table.headers.include? 'times' - got['times'] = times + got['times'] = instructions ? times : '' end if table.headers.include? 'distances' - got['distances'] = distances + got['distances'] = instructions ? distances : '' end end end diff --git a/features/testbot/mode.feature b/features/testbot/mode.feature index bcc087ec44d..11fe83a4279 100644 --- a/features/testbot/mode.feature +++ b/features/testbot/mode.feature @@ -1,26 +1,227 @@ @routing @testbot @mode -Feature: Testbot - Mode flag +Feature: Testbot - Travel mode + +# testbot modes: +# 1 normal +# 2 route +# 3 river downstream +# 4 river upstream +# 5 steps down +# 6 steps up Background: - Given the profile "testbot" + Given the profile "testbot" + + Scenario: Testbot - Modes in each direction, different forward/backward speeds + Given the node map + | | 0 | 1 | | + | a | | | b | + + And the ways + | nodes | highway | oneway | + | ab | river | | + + When I route I should get + | from | to | route | modes | + | a | 0 | ab | 3 | + | a | b | ab | 3 | + | 0 | 1 | ab | 3 | + | 0 | b | ab | 3 | + | b | 1 | ab | 4 | + | b | a | ab | 4 | + | 1 | 0 | ab | 4 | + | 1 | a | ab | 4 | + + Scenario: Testbot - Modes in each direction, same forward/backward speeds + Given the node map + | | 0 | 1 | | + | a | | | b | + + And the ways + | nodes | highway | + | ab | steps | + + When I route I should get + | from | to | route | modes | time | + | 0 | 1 | ab | 5 | 60s +-1 | + | 1 | 0 | ab | 6 | 60s +-1 | + + @oneway + Scenario: Testbot - Modes for oneway, different forward/backward speeds + Given the node map + | a | b | - @todo - Scenario: Bike - Mode + And the ways + | nodes | highway | oneway | + | ab | river | yes | + + When I route I should get + | from | to | route | modes | + | a | b | ab | 3 | + | b | a | | | + + @oneway + Scenario: Testbot - Modes for oneway, same forward/backward speeds + Given the node map + | a | b | + + And the ways + | nodes | highway | oneway | + | ab | steps | yes | + + When I route I should get + | from | to | route | modes | + | a | b | ab | 5 | + | b | a | | | + + @oneway + Scenario: Testbot - Modes for reverse oneway, different forward/backward speeds Given the node map - | a | b | | - | | c | d | + | a | b | And the ways + | nodes | highway | oneway | + | ab | river | -1 | + + When I route I should get + | from | to | route | modes | + | a | b | | | + | b | a | ab | 4 | + + @oneway + Scenario: Testbot - Modes for reverse oneway, same forward/backward speeds + Given the node map + | a | b | + + And the ways + | nodes | highway | oneway | + | ab | steps | -1 | + + When I route I should get + | from | to | route | modes | + | a | b | | | + | b | a | ab | 6 | + + @via + Scenario: Testbot - Mode should be set at via points + Given the node map + | a | 1 | b | + + And the ways + | nodes | highway | + | ab | river | + + When I route I should get + | waypoints | route | modes | turns | + | a,1,b | ab,ab | 3,3 | head,via,destination | + | b,1,a | ab,ab | 4,4 | head,via,destination | + + Scenario: Testbot - Starting at a tricky node + Given the node map + | | a | | | | + | | | | b | c | + + And the ways + | nodes | highway | + | ab | river | + | bc | primary | + + When I route I should get + | from | to | route | modes | + | b | a | ab | 4 | + + Scenario: Testbot - Mode changes on straight way without name change + Given the node map + | a | 1 | b | 2 | c | + + And the ways + | nodes | highway | name | + | ab | primary | Avenue | + | bc | river | Avenue | + + When I route I should get + | from | to | route | modes | turns | + | a | c | Avenue,Avenue | 1,3 | head,straight,destination | + | c | a | Avenue,Avenue | 4,1 | head,straight,destination | + | 1 | 2 | Avenue,Avenue | 1,3 | head,straight,destination | + | 2 | 1 | Avenue,Avenue | 4,1 | head,straight,destination | + + Scenario: Testbot - Mode for routes + Given the node map + | a | b | | | | + | | c | d | e | f | + + And the ways | nodes | highway | route | duration | | ab | primary | | | | bc | | ferry | 0:01 | | cd | primary | | | + | de | primary | | | + | ef | primary | | | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,2 | + | b | d | bc,cd | head,left,destination | 2,1 | + | a | f | ab,bc,cd,de,ef | head,right,left,straight,straight,destination | 1,2,1,1,1 | + + Scenario: Testbot - Modes, triangle map + Given the node map + | | | | | | | d | + | | | | | | 2 | | + | | | | | 6 | | 5 | + | a | 0 | b | c | | | | + | | | | | 4 | | 1 | + | | | | | | 3 | | + | | | | | | | e | + + And the ways + | nodes | highway | oneway | + | abc | primary | | + | cd | primary | yes | + | ce | river | | + | de | primary | | + + When I route I should get + | from | to | route | modes | + | 0 | 1 | abc,ce,de | 1,3,1 | + | 1 | 0 | de,ce,abc | 1,4,1 | + | 0 | 2 | abc,cd | 1,1 | + | 2 | 0 | cd,de,ce,abc | 1,1,4,1 | + | 0 | 3 | abc,ce | 1,3 | + | 3 | 0 | ce,abc | 4,1 | + | 4 | 3 | ce | 3 | + | 3 | 4 | ce | 4 | + | 3 | 1 | ce,de | 3,1 | + | 1 | 3 | de,ce | 1,4 | + | a | e | abc,ce | 1,3 | + | e | a | ce,abc | 4,1 | + | a | d | abc,cd | 1,1 | + | d | a | de,ce,abc | 1,4,1 | + + Scenario: Testbot - River in the middle + Given the node map + | a | b | c | | | + | | | d | | | + | | | e | f | g | + + And the ways + | nodes | highway | + | abc | primary | + | cde | river | + | efg | primary | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd | head,right,left,destination | bot,ferry,bot | - | d | a | cd,bc,ab | head,right left,destination | bot,ferry,bot | - | c | a | bc,ab | head,left,destination | ferry,bot | - | d | b | cd,bc | head,right,destination | bot,ferry | - | a | c | ab,bc | head,right,destination | bot,ferry | - | b | d | bc,cd | head,left,destination | ferry,bot | + | from | to | route | modes | + | a | g | abc,cde,efg | 1,3,1 | + | b | f | abc,cde,efg | 1,3,1 | + | e | c | cde | 4 | + | e | b | cde,abc | 4,1 | + | e | a | cde,abc | 4,1 | + | c | e | cde | 3 | + | c | f | cde,efg | 3,1 | + | c | g | cde,efg | 3,1 | diff --git a/features/testbot/oneway.feature b/features/testbot/oneway.feature index c21d8b1cb6c..9b4693ddf58 100644 --- a/features/testbot/oneway.feature +++ b/features/testbot/oneway.feature @@ -42,3 +42,57 @@ Feature: Testbot - oneways | g | f | gh,ha,ab,bc,cd,de,ef | | h | g | ha,ab,bc,cd,de,ef,fg | | a | h | ab,bc,cd,de,ef,fg,gh | + + Scenario: Testbot - Simple oneway + Then routability should be + | highway | foot | oneway | forw | backw | + | primary | no | yes | x | | + + Scenario: Simple reverse oneway + Then routability should be + | highway | foot | oneway | forw | backw | + | primary | no | -1 | | x | + + Scenario: Testbot - Around the Block + Given the node map + | a | b | + | d | c | + + And the ways + | nodes | oneway | foot | + | ab | yes | no | + | bc | | no | + | cd | | no | + | da | | no | + + When I route I should get + | from | to | route | + | a | b | ab | + | b | a | bc,cd,da | + + Scenario: Testbot - Handle various oneway tag values + Then routability should be + | foot | oneway | forw | backw | + | no | | x | x | + | no | nonsense | x | x | + | no | no | x | x | + | no | false | x | x | + | no | 0 | x | x | + | no | yes | x | | + | no | true | x | | + | no | 1 | x | | + | no | -1 | | x | + + Scenario: Testbot - Two consecutive oneways + Given the node map + | a | b | c | + + And the ways + | nodes | oneway | + | ab | yes | + | bc | yes | + + + When I route I should get + | from | to | route | + | a | c | ab,bc | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 3efa3d025d3..4f567edc93e 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -1,4 +1,5 @@ require("lib/access") +require("lib/maxspeed") -- Begin of globals barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true } @@ -94,7 +95,13 @@ u_turn_penalty = 20 use_turn_restrictions = false turn_penalty = 60 turn_bias = 1.4 --- End of globals + + +--modes +mode_normal = 1 +mode_pushing = 2 +mode_ferry = 3 +mode_train = 4 local function parse_maxspeed(source) @@ -161,18 +168,18 @@ function way_function (way) (not man_made or man_made=='') and (not public_transport or public_transport=='') then - return 0 + return end -- don't route on ways or railways that are still under construction if highway=='construction' or railway=='construction' then - return 0 + return end -- access local access = Access.find_access_tag(way, access_tags_hierachy) if access_tag_blacklist[access] then - return 0 + return end -- other tags @@ -193,6 +200,7 @@ function way_function (way) local area = way.tags:Find("area") local foot = way.tags:Find("foot") local surface = way.tags:Find("surface") + local bicycle = way.tags:Find("bicycle") -- name if "" ~= ref and "" ~= name then @@ -215,126 +223,152 @@ function way_function (way) -- speed if route_speeds[route] then -- ferries (doesn't cover routes tagged using relations) - way.direction = Way.bidirectional + way.forward_mode = mode_ferry + way.backward_mode = mode_ferry way.ignore_in_grid = true if durationIsValid(duration) then way.duration = math.max( 1, parseDuration(duration) ) else - way.speed = route_speeds[route] + way.forward_speed = route_speeds[route] + way.backward_speed = route_speeds[route] end elseif railway and platform_speeds[railway] then -- railway platforms (old tagging scheme) - way.speed = platform_speeds[railway] + way.forward_speed = platform_speeds[railway] + way.backward_speed = platform_speeds[railway] elseif platform_speeds[public_transport] then -- public_transport platforms (new tagging platform) - way.speed = platform_speeds[public_transport] + way.forward_speed = platform_speeds[public_transport] + way.backward_speed = platform_speeds[public_transport] elseif railway and railway_speeds[railway] then + way.forward_mode = mode_train + way.backward_mode = mode_train -- railways if access and access_tag_whitelist[access] then - way.speed = railway_speeds[railway] - way.direction = Way.bidirectional + way.forward_speed = railway_speeds[railway] + way.backward_speed = railway_speeds[railway] end elseif amenity and amenity_speeds[amenity] then -- parking areas - way.speed = amenity_speeds[amenity] + way.forward_speed = amenity_speeds[amenity] + way.backward_speed = amenity_speeds[amenity] elseif bicycle_speeds[highway] then -- regular ways - way.speed = bicycle_speeds[highway] + way.forward_speed = bicycle_speeds[highway] + way.backward_speed = bicycle_speeds[highway] elseif access and access_tag_whitelist[access] then -- unknown way, but valid access tag - way.speed = default_speed + way.forward_speed = default_speed + way.backward_speed = default_speed else -- biking not allowed, maybe we can push our bike? -- essentially requires pedestrian profiling, for example foot=no mean we can't push a bike - -- TODO: if we can push, the way should be marked as pedestrion mode, but there's no way to do it yet from lua.. - if foot ~= 'no' then + if foot ~= 'no' and junction ~= "roundabout" then if pedestrian_speeds[highway] then -- pedestrian-only ways and areas - way.speed = pedestrian_speeds[highway] + way.forward_speed = pedestrian_speeds[highway] + way.backward_speed = pedestrian_speeds[highway] + way.forward_mode = mode_pushing + way.backward_mode = mode_pushing elseif man_made and man_made_speeds[man_made] then -- man made structures - way.speed = man_made_speeds[man_made] + way.forward_speed = man_made_speeds[man_made] + way.backward_speed = man_made_speeds[man_made] + way.forward_mode = mode_pushing + way.backward_mode = mode_pushing elseif foot == 'yes' then - way.speed = walking_speed + way.forward_speed = walking_speed + way.backward_speed = walking_speed + way.forward_mode = mode_pushing + way.backward_mode = mode_pushing + elseif foot_forward == 'yes' then + way.forward_speed = walking_speed + way.forward_mode = mode_pushing + way.backward_mode = 0 + elseif foot_backward == 'yes' then + way.forward_speed = walking_speed + way.forward_mode = 0 + way.backward_mode = mode_pushing end end end -- direction - way.direction = Way.bidirectional local impliedOneway = false if junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then - way.direction = Way.oneway impliedOneway = true end if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then - way.direction = Way.oneway + way.backward_mode = 0 elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then - way.direction = Way.bidirectional + -- prevent implied oneway elseif onewayClass == "-1" then - way.direction = Way.opposite + way.forward_mode = 0 elseif oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional + -- prevent implied oneway elseif cycleway and string.find(cycleway, "opposite") == 1 then if impliedOneway then - way.direction = Way.opposite - else - way.direction = Way.bidirectional + way.forward_mode = 0 + way.backward_mode = mode_normal + way.backward_speed = bicycle_speeds["cycleway"] end elseif cycleway_left and cycleway_tags[cycleway_left] and cycleway_right and cycleway_tags[cycleway_right] then - way.direction = Way.bidirectional + -- prevent implied elseif cycleway_left and cycleway_tags[cycleway_left] then if impliedOneway then - way.direction = Way.opposite - else - way.direction = Way.bidirectional + way.forward_mode = 0 + way.backward_mode = mode_normal + way.backward_speed = bicycle_speeds["cycleway"] end elseif cycleway_right and cycleway_tags[cycleway_right] then if impliedOneway then - way.direction = Way.oneway - else - way.direction = Way.bidirectional + way.forward_mode = mode_normal + way.backward_speed = bicycle_speeds["cycleway"] + way.backward_mode = 0 end elseif oneway == "-1" then - way.direction = Way.opposite - elseif oneway == "yes" or oneway == "1" or oneway == "true" then - way.direction = Way.oneway + way.forward_mode = 0 + elseif oneway == "yes" or oneway == "1" or oneway == "true" or impliedOneway then + way.backward_mode = 0 end - + -- pushing bikes if bicycle_speeds[highway] or pedestrian_speeds[highway] then - if foot ~= 'no' then - if junction ~= "roundabout" then - if way.direction == Way.oneway then - way.backward_speed = walking_speed - elseif way.direction == Way.opposite then - way.backward_speed = walking_speed - way.speed = way.speed - end + if foot ~= "no" and junction ~= "roundabout" then + if way.backward_mode == 0 then + way.backward_speed = walking_speed + way.backward_mode = mode_pushing + elseif way.forward_mode == 0 then + way.forward_speed = walking_speed + way.forward_mode = mode_pushing end end - if way.backward_speed == way.speed then - -- TODO: no way yet to mark a way as pedestrian mode if forward/backward speeds are equal - way.direction = Way.bidirectional - end end -- cycleways if cycleway and cycleway_tags[cycleway] then - way.speed = bicycle_speeds["cycleway"] + way.forward_speed = bicycle_speeds["cycleway"] elseif cycleway_left and cycleway_tags[cycleway_left] then - way.speed = bicycle_speeds["cycleway"] + way.forward_speed = bicycle_speeds["cycleway"] elseif cycleway_right and cycleway_tags[cycleway_right] then - way.speed = bicycle_speeds["cycleway"] + way.forward_speed = bicycle_speeds["cycleway"] + end + + -- dismount + if bicycle == "dismount" then + way.forward_mode = mode_pushing + way.backward_mode = mode_pushing + way.forward_speed = walking_speed + way.backward_speed = walking_speed end -- surfaces if surface then surface_speed = surface_speeds[surface] if surface_speed then - if way.speed > 0 then - way.speed = surface_speed + if way.forward_speed > 0 then + way.forward_speed = surface_speed end if way.backward_speed > 0 then way.backward_speed = surface_speed @@ -343,26 +377,7 @@ function way_function (way) end -- maxspeed - -- TODO: maxspeed of backward direction - if take_minimum_of_speeds then - if maxspeed and maxspeed>0 then - way.speed = math.min(way.speed, maxspeed) - end - end - - -- Override speed settings if explicit forward/backward maxspeeds are given - if way.speed > 0 and maxspeed_forward ~= nil and maxspeed_forward > 0 then - if Way.bidirectional == way.direction then - way.backward_speed = way.speed - end - way.speed = maxspeed_forward - end - if maxspeed_backward ~= nil and maxspeed_backward > 0 then - way.backward_speed = maxspeed_backward - end - - way.type = 1 - return 1 + MaxSpeed.limit( way, maxspeed, maxspeed_forward, maxspeed_backward ) end function turn_function (angle) diff --git a/profiles/car.lua b/profiles/car.lua old mode 100644 new mode 100755 index 8f8d1bcdde5..371740fe4bf --- a/profiles/car.lua +++ b/profiles/car.lua @@ -48,6 +48,11 @@ local max = math.max local speed_reduction = 0.8 +--modes +local mode_normal = 1 +local mode_ferry = 2 + + local function find_access_tag(source,access_tags_hierachy) for i,v in ipairs(access_tags_hierachy) do local has_tag = source.tags:Holds(v) @@ -169,8 +174,10 @@ function way_function (way) if durationIsValid(duration) then way.duration = max( parseDuration(duration), 1 ); end - way.direction = Way.bidirectional - way.speed = route_speed + way.forward_mode = mode_ferry + way.backward_mode = mode_ferry + way.forward_speed = route_speed + way.backward_speed = route_speed end -- leave early of this way is not accessible @@ -178,30 +185,34 @@ function way_function (way) return end - if way.speed == -1 then + if way.forward_speed == -1 then local highway_speed = speed_profile[highway] local max_speed = parse_maxspeed( way.tags:Find("maxspeed") ) -- Set the avg speed on the way if it is accessible by road class if highway_speed then if max_speed > highway_speed then - way.speed = max_speed + way.forward_speed = max_speed + way.backward_speed = max_speed -- max_speed = math.huge else - way.speed = highway_speed + way.forward_speed = highway_speed + way.backward_speed = highway_speed end else -- Set the avg speed on ways that are marked accessible if access_tag_whitelist[access] then - way.speed = speed_profile["default"] + way.forward_speed = speed_profile["default"] + way.backward_speed = speed_profile["default"] end end if 0 == max_speed then max_speed = math.huge end - way.speed = min(way.speed, max_speed) + way.forward_speed = min(way.forward_speed, max_speed) + way.backward_speed = min(way.backward_speed, max_speed) end - if -1 == way.speed then + if -1 == way.forward_speed and -1 == way.backward_speed then return end @@ -237,17 +248,16 @@ function way_function (way) end -- Set direction according to tags on way - way.direction = Way.bidirectional if obey_oneway then if oneway == "-1" then - way.direction = Way.opposite + way.forward_mode = 0 elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or (highway == "motorway_link" and oneway ~="no") or (highway == "motorway" and oneway ~= "no") then - way.direction = Way.oneway + way.backward_mode = 0 end end @@ -255,10 +265,10 @@ function way_function (way) local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward")) local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward")) if maxspeed_forward > 0 then - if Way.bidirectional == way.direction then - way.backward_speed = way.speed + if 0 ~= way.forward_mode and 0 ~= way.backward_mode then + way.backward_speed = way.forward_speed end - way.speed = maxspeed_forward + way.forward_speed = maxspeed_forward end if maxspeed_backward > 0 then way.backward_speed = maxspeed_backward @@ -268,14 +278,12 @@ function way_function (way) if ignore_in_grid[highway] then way.ignore_in_grid = true end - way.type = 1 -- scale speeds to get better avg driving times - way.speed = way.speed * speed_reduction - if maxspeed_backward > 0 then + way.forward_speed = way.forward_speed * speed_reduction + if way.backward_speed > 0 then way.backward_speed = way.backward_speed*speed_reduction end - return end -- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT diff --git a/profiles/examples/postgis.lua b/profiles/examples/postgis.lua index b101a2792f9..6e32e4c7f04 100644 --- a/profiles/examples/postgis.lua +++ b/profiles/examples/postgis.lua @@ -65,11 +65,11 @@ function way_function (way) local cursor = assert( sql_con:execute(sql_query) ) -- execute querty local row = cursor:fetch( {}, "a" ) -- fetch first (and only) row - way.speed = 20.0 -- default speed + way.forward_speed = 20.0 -- default speed if row then local val = tonumber(row.val) -- read 'val' from row if val > 10 then - way.speed = way.speed / math.log10( val ) -- reduce speed by amount of industry close by + way.forward_speed = way.forward_speed / math.log10( val ) -- reduce speed by amount of industry close by end end cursor:close() -- done with this query diff --git a/profiles/foot.lua b/profiles/foot.lua index ae0dd608317..1e7cd4ba076 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -63,6 +63,10 @@ traffic_signal_penalty = 2 u_turn_penalty = 2 use_turn_restrictions = false +--modes +local mode_normal = 1 +local mode_ferry = 2 + function get_exceptions(vector) for i,v in ipairs(restriction_exception_tags) do vector:Add(v) @@ -98,32 +102,32 @@ function node_function (node) end function way_function (way) - -- initial routability check, filters out buildings, boundaries, etc + -- initial routability check, filters out buildings, boundaries, etc local highway = way.tags:Find("highway") local route = way.tags:Find("route") local man_made = way.tags:Find("man_made") local railway = way.tags:Find("railway") local amenity = way.tags:Find("amenity") local public_transport = way.tags:Find("public_transport") - if (not highway or highway == '') and + if (not highway or highway == '') and (not route or route == '') and (not railway or railway=='') and (not amenity or amenity=='') and (not man_made or man_made=='') and - (not public_transport or public_transport=='') - then - return 0 + (not public_transport or public_transport=='') + then + return end -- don't route on ways that are still under construction if highway=='construction' then - return 0 + return end -- access local access = Access.find_access_tag(way, access_tags_hierachy) if access_tag_blacklist[access] then - return 0 + return end local name = way.tags:Find("name") @@ -156,50 +160,52 @@ function way_function (way) -- speed if route_speeds[route] then -- ferries (doesn't cover routes tagged using relations) - way.direction = Way.bidirectional way.ignore_in_grid = true if durationIsValid(duration) then way.duration = math.max( 1, parseDuration(duration) ) else - way.speed = route_speeds[route] + way.forward_speed = route_speeds[route] + way.backward_speed = route_speeds[route] end + way.forward_mode = mode_ferry + way.backward_mode = mode_ferry elseif railway and platform_speeds[railway] then -- railway platforms (old tagging scheme) - way.speed = platform_speeds[railway] + way.forward_speed = platform_speeds[railway] + way.backward_speed = platform_speeds[railway] elseif platform_speeds[public_transport] then -- public_transport platforms (new tagging platform) - way.speed = platform_speeds[public_transport] + way.forward_speed = platform_speeds[public_transport] + way.backward_speed = platform_speeds[public_transport] elseif amenity and amenity_speeds[amenity] then -- parking areas - way.speed = amenity_speeds[amenity] + way.forward_speed = amenity_speeds[amenity] + way.backward_speed = amenity_speeds[amenity] elseif speeds[highway] then -- regular ways - way.speed = speeds[highway] + way.forward_speed = speeds[highway] + way.backward_speed = speeds[highway] elseif access and access_tag_whitelist[access] then -- unknown way, but valid access tag - way.speed = walking_speed + way.forward_speed = walking_speed + way.backward_speed = walking_speed end -- oneway if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then - way.direction = Way.oneway + way.backward_mode = 0 elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then - way.direction = Way.bidirectional + -- nothing to do elseif onewayClass == "-1" then - way.direction = Way.opposite - else - way.direction = Way.bidirectional + way.forward_mode = 0 end -- surfaces if surface then surface_speed = surface_speeds[surface] if surface_speed then - way.speed = math.min(way.speed, surface_speed) + way.forward_speed = math.min(way.forward_speed, surface_speed) way.backward_speed = math.min(way.backward_speed, surface_speed) end end - - way.type = 1 - return 1 end diff --git a/profiles/lib/maxspeed.lua b/profiles/lib/maxspeed.lua new file mode 100644 index 00000000000..aca344a7962 --- /dev/null +++ b/profiles/lib/maxspeed.lua @@ -0,0 +1,17 @@ +local math = math + +module "MaxSpeed" + +function limit(way,max,maxf,maxb) + if maxf and maxf>0 then + way.forward_speed = math.min(way.forward_speed, maxf) + elseif max and max>0 then + way.forward_speed = math.min(way.forward_speed, max) + end + + if maxb and maxb>0 then + way.backward_speed = math.min(way.backward_speed, maxb) + elseif max and max>0 then + way.backward_speed = math.min(way.backward_speed, max) + end +end diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 66d65997408..a0b06f56d26 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -6,10 +6,19 @@ -- Secondary road: 18km/h = 18000m/3600s = 100m/20s -- Tertiary road: 12km/h = 12000m/3600s = 100m/30s +-- modes: +-- 1: normal +-- 2: route +-- 3: river downstream +-- 4: river upstream +-- 5: steps down +-- 6: steps up + speed_profile = { ["primary"] = 36, ["secondary"] = 18, ["tertiary"] = 12, + ["steps"] = 6, ["default"] = 24 } @@ -61,14 +70,21 @@ function way_function (way) if route ~= nil and durationIsValid(duration) then way.duration = math.max( 1, parseDuration(duration) ) + way.forward_mode = 2 + way.backward_mode = 2 else local speed_forw = speed_profile[highway] or speed_profile['default'] local speed_back = speed_forw if highway == "river" then local temp_speed = speed_forw; + way.forward_mode = 3 + way.backward_mode = 4 speed_forw = temp_speed*1.5 speed_back = temp_speed/1.5 + elseif highway == "steps" then + way.forward_mode = 5 + way.backward_mode = 6 end if maxspeed_forward ~= nil and maxspeed_forward > 0 then @@ -87,26 +103,19 @@ function way_function (way) end end - way.speed = speed_forw - if speed_back ~= way_forw then - way.backward_speed = speed_back - end + way.forward_speed = speed_forw + way.backward_speed = speed_back end if oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional + -- nothing to do elseif oneway == "-1" then - way.direction = Way.opposite + way.forward_mode = 0 elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" then - way.direction = Way.oneway - else - way.direction = Way.bidirectional + way.backward_mode = 0 end if junction == 'roundabout' then way.roundabout = true end - - way.type = 1 - return 1 end