Skip to content

Commit

Permalink
Implements Alternatives for MLD
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-j-h committed Jul 5, 2017
1 parent 6d78c11 commit 8bc33ac
Show file tree
Hide file tree
Showing 28 changed files with 1,417 additions and 253 deletions.
11 changes: 9 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
# 5.9.0
- Changes from 5.8
- Algorithm:
- Multi-Level Dijkstra:
- Plugins supported: `table`
- Multi-Level Dijkstra:
- Plugins supported: `table`
- Adds alternative routes support (see [#4047](https://github.com/Project-OSRM/osrm-backend/pull/4047) and [3905](https://github.com/Project-OSRM/osrm-backend/issues/3905)): provides reasonably looking alternative routes (many, if possible) with reasonable query times.
- API:
- Exposes `alternatives=Number` parameter overload in addition to the boolean flag.
- Node.js Bindings:
- Exposes `alternatives=Number` parameter overload in addition to the boolean flag.
- Tools:
- Exposes engine limit on number of alternatives to generate `--max-alternatives` in `osrm-routed` (3 by default)

# 5.8.0
- Changes from 5.7
Expand Down
6 changes: 3 additions & 3 deletions docs/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,21 +165,21 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
Finds the fastest route between coordinates in the supplied order.

```endpoint
GET /route/v1/{profile}/{coordinates}?alternatives={true|false}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
GET /route/v1/{profile}/{coordinates}?alternatives={true|false|number}&steps={true|false}&geometries={polyline|polyline6|geojson}&overview={full|simplified|false}&annotations={true|false}
```

In addition to the [general options](#general-options) the following options are supported for this service:

|Option |Values |Description |
|------------|---------------------------------------------|-------------------------------------------------------------------------------|
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|alternatives|`true`, `false` (default), or Number |Search for alternative routes. Passing a number `alternatives=n` searches for up to `n` alternative routes.\* |
|steps |`true`, `false` (default) |Returned route steps for each route leg |
|annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. |

\* Please note that even if an alternative route is requested, a result cannot be guaranteed.
\* Please note that even if alternative routes are requested, a result cannot be guaranteed.

**Response**

Expand Down
20 changes: 10 additions & 10 deletions docs/profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ As you scroll down the file you'll see local variables, and then local functions

The following global properties can be set in your profile:

Attribute | Type | Notes
------------------------------|----------|----------------------------------------------------------------------------
weight_name | String | Name used in output for the routing weight property (default `'duration'`)
weight_precision | Unsigned | Decimal precision of edge weights (default `1`)
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance, default `false`)
use_turn_restrictions | Boolean | Are turn instructions followed? (default `false`)
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`)
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
max_turn_weight | Float | Maximum turn penalty weight
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `segment_function` will be called for all segments (default `false`)
Attribute | Type | Notes
-------------------------------------|----------|----------------------------------------------------------------------------
weight_name | String | Name used in output for the routing weight property (default `'duration'`)
weight_precision | Unsigned | Decimal precision of edge weights (default `1`)
left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance, default `false`)
use_turn_restrictions | Boolean | Are turn instructions followed? (default `false`)
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`)
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
max_turn_weight | Float | Maximum turn penalty weight
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `segment_function` will be called for all segments (default `false`)

## way_function

Expand Down
3 changes: 3 additions & 0 deletions include/engine/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ template <> struct HasGetTileTurns<corech::Algorithm> final : std::true_type
};

// Algorithms supported by Multi-Level Dijkstra
template <> struct HasAlternativePathSearch<mld::Algorithm> final : std::true_type
{
};
template <> struct HasDirectShortestPathSearch<mld::Algorithm> final : std::true_type
{
};
Expand Down
17 changes: 13 additions & 4 deletions include/engine/api/route_parameters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ struct RouteParameters : public BaseParameters
const boost::optional<bool> continue_straight_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
annotations{false}, annotations_type{AnnotationsType::None}, geometries{geometries_},
overview{overview_}, continue_straight{continue_straight_}
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{false},
annotations_type{AnnotationsType::None}, geometries{geometries_}, overview{overview_},
continue_straight{continue_straight_}
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one below.
{
}
Expand All @@ -105,7 +106,7 @@ struct RouteParameters : public BaseParameters
const boost::optional<bool> continue_straight_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
annotations{annotations_},
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{annotations_},
annotations_type{annotations_ ? AnnotationsType::All : AnnotationsType::None},
geometries{geometries_}, overview{overview_}, continue_straight{continue_straight_}
{
Expand All @@ -121,21 +122,29 @@ struct RouteParameters : public BaseParameters
const boost::optional<bool> continue_straight_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
number_of_alternatives{alternatives_ ? 1u : 0u},
annotations{annotations_ == AnnotationsType::None ? false : true},
annotations_type{annotations_}, geometries{geometries_}, overview{overview_},
continue_straight{continue_straight_}
{
}

bool steps = false;
// TODO: in v6 we should remove the boolean and only keep the number parameter; for compat.
bool alternatives = false;
unsigned number_of_alternatives = 0;
bool annotations = false;
AnnotationsType annotations_type = AnnotationsType::None;
GeometriesType geometries = GeometriesType::Polyline;
OverviewType overview = OverviewType::Simplified;
boost::optional<bool> continue_straight;

bool IsValid() const { return coordinates.size() >= 2 && BaseParameters::IsValid(); }
bool IsValid() const
{
const auto coordinates_ok = coordinates.size() >= 2;
const auto base_params_ok = BaseParameters::IsValid();
return coordinates_ok && base_params_ok;
}
};

inline bool operator&(RouteParameters::AnnotationsType lhs, RouteParameters::AnnotationsType rhs)
Expand Down
13 changes: 6 additions & 7 deletions include/engine/engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "engine/datafacade/contiguous_block_allocator.hpp"
#include "engine/datafacade_provider.hpp"
#include "engine/engine_config.hpp"
#include "engine/engine_config.hpp"
#include "engine/plugins/match.hpp"
#include "engine/plugins/nearest.hpp"
#include "engine/plugins/table.hpp"
Expand Down Expand Up @@ -54,12 +53,12 @@ template <typename Algorithm> class Engine final : public EngineInterface
{
public:
explicit Engine(const EngineConfig &config)
: route_plugin(config.max_locations_viaroute), //
table_plugin(config.max_locations_distance_table), //
nearest_plugin(config.max_results_nearest), //
trip_plugin(config.max_locations_trip), //
match_plugin(config.max_locations_map_matching), //
tile_plugin() //
: route_plugin(config.max_locations_viaroute, config.max_alternatives), //
table_plugin(config.max_locations_distance_table), //
nearest_plugin(config.max_results_nearest), //
trip_plugin(config.max_locations_trip), //
match_plugin(config.max_locations_map_matching), //
tile_plugin() //

{
if (config.use_shared_memory)
Expand Down
1 change: 1 addition & 0 deletions include/engine/engine_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ struct EngineConfig final
int max_locations_distance_table = -1;
int max_locations_map_matching = -1;
int max_results_nearest = -1;
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
bool use_shared_memory = true;
Algorithm algorithm = Algorithm::CH;
};
Expand Down
12 changes: 12 additions & 0 deletions include/engine/internal_route_result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ struct InternalRouteResult
{
return (leg != unpacked_path_segments.size() - 1);
}

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

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

return ret;
}
};

struct InternalManyRoutesResult
Expand Down
3 changes: 2 additions & 1 deletion include/engine/plugins/viaroute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ class ViaRoutePlugin final : public BasePlugin
{
private:
const int max_locations_viaroute;
const int max_alternatives;

public:
explicit ViaRoutePlugin(int max_locations_viaroute);
explicit ViaRoutePlugin(int max_locations_viaroute, int max_alternatives);

Status HandleRequest(const datafacade::ContiguousInternalMemoryDataFacadeBase &facade,
const RoutingAlgorithmsInterface &algorithms,
Expand Down
27 changes: 12 additions & 15 deletions include/engine/routing_algorithms.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class RoutingAlgorithmsInterface
{
public:
virtual InternalManyRoutesResult
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0;
AlternativePathSearch(const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives) const = 0;

virtual InternalRouteResult
ShortestPathSearch(const std::vector<PhantomNodes> &phantom_node_pair,
Expand Down Expand Up @@ -66,7 +67,8 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
virtual ~RoutingAlgorithms() = default;

InternalManyRoutesResult
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override;
AlternativePathSearch(const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives) const final override;

InternalRouteResult ShortestPathSearch(
const std::vector<PhantomNodes> &phantom_node_pair,
Expand Down Expand Up @@ -130,9 +132,11 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo

template <typename Algorithm>
InternalManyRoutesResult
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives) const
{
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
return routing_algorithms::alternativePathSearch(
heaps, facade, phantom_node_pair, number_of_alternatives);
}

template <typename Algorithm>
Expand Down Expand Up @@ -189,7 +193,8 @@ inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::G
// CoreCH overrides
template <>
InternalManyRoutesResult inline RoutingAlgorithms<
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &,
unsigned) const
{
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
}
Expand All @@ -203,15 +208,7 @@ RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
{
throw util::exception("ManyToManySearch is disabled due to performance reasons");
}

// MLD overrides for not implemented
template <>
InternalManyRoutesResult inline RoutingAlgorithms<
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
{
throw util::exception("AlternativePathSearch is not implemented");
}
}
}
} // ns engine
} // ns osrm

#endif
18 changes: 12 additions & 6 deletions include/engine/routing_algorithms/alternative_path.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ namespace engine
{
namespace routing_algorithms
{
namespace ch
{

InternalManyRoutesResult
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const PhantomNodes &phantom_node_pair);
} // namespace ch
alternativePathSearch(SearchEngineData<ch::Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<ch::Algorithm> &facade,
const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives);

InternalManyRoutesResult
alternativePathSearch(SearchEngineData<mld::Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<mld::Algorithm> &facade,
const PhantomNodes &phantom_node_pair,
unsigned number_of_alternatives);

} // namespace routing_algorithms
} // namespace engine
} // namespace osrm
Expand Down
38 changes: 37 additions & 1 deletion include/engine/routing_algorithms/routing_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "engine/algorithm.hpp"
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
#include "engine/internal_route_result.hpp"
#include "engine/phantom_node.hpp"
#include "engine/search_engine_data.hpp"

#include "util/coordinate_calculation.hpp"
Expand Down Expand Up @@ -38,9 +39,11 @@ static constexpr bool REVERSE_DIRECTION = false;
static constexpr bool DO_NOT_FORCE_LOOPS = false;

bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &target_phantom);

bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);

bool needsLoopForward(const PhantomNodes &phantoms);
bool needsLoopBackwards(const PhantomNodes &phantoms);

template <typename Heap>
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
{
Expand Down Expand Up @@ -366,6 +369,39 @@ double getPathDistance(const datafacade::ContiguousInternalMemoryDataFacade<Algo
return distance;
}

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

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

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

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

return raw_route_data;
}

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

0 comments on commit 8bc33ac

Please sign in to comment.