Compare commits
18 Commits
master
...
v5.21.0-cu
Author | SHA1 | Date | |
---|---|---|---|
|
986252c4f9 | ||
|
aed7df6173 | ||
|
e3b09875c6 | ||
|
52ceea429b | ||
|
3d4d51d6b7 | ||
|
23c69f4c3d | ||
|
9d044bf388 | ||
|
823d7e45e7 | ||
|
6b961dccfc | ||
|
44d4903985 | ||
|
55e05b70ac | ||
|
210908dbe6 | ||
|
6b9006f6e7 | ||
|
ca55521c87 | ||
|
67e99c9809 | ||
|
05647adcc6 | ||
|
6c37b71046 | ||
|
cb2a46b8d9 |
@ -35,3 +35,28 @@ Feature: Car - Allowed start/end modes
|
|||||||
| from | to | route | modes |
|
| from | to | route | modes |
|
||||||
| 1 | 2 | ab,ab | driving,driving |
|
| 1 | 2 | ab,ab | driving,driving |
|
||||||
| 2 | 1 | ab,ab | driving,driving |
|
| 2 | 1 | ab,ab | driving,driving |
|
||||||
|
|
||||||
|
Scenario: Car - URL override of non-startpoints
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 b c 2 d
|
||||||
|
"""
|
||||||
|
|
||||||
|
Given the query options
|
||||||
|
| snapping | any |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | access |
|
||||||
|
| ab | service | private |
|
||||||
|
| bc | primary | |
|
||||||
|
| cd | service | private |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | 2 | c |
|
||||||
|
| 1 | 59.1 | 35.1 |
|
||||||
|
| b | 35.1 | 11.1 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| 1 | 2 | ab,bc,cd |
|
||||||
|
| 2 | 1 | cd,bc,ab |
|
||||||
|
168
features/testbot/stoppage.feature
Normal file
168
features/testbot/stoppage.feature
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
@routing @maxspeed @testbot
|
||||||
|
Feature: Testbot - Acceleration profiles
|
||||||
|
|
||||||
|
Background: Use specific speeds
|
||||||
|
Given the profile "testbot"
|
||||||
|
|
||||||
|
Scenario: Testbot - No stoppage penalties
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | time | distance |
|
||||||
|
| a | b | ab,ab | 3.6s | 59.9m |
|
||||||
|
| a | 1 | ab,ab | 0.6s | 10m |
|
||||||
|
| a | 2 | ab,ab | 1.2s | 20m |
|
||||||
|
| a | 3 | ab,ab | 1.8s | 30m |
|
||||||
|
| a | 4 | ab,ab | 2.4s | 40m |
|
||||||
|
| a | 5 | ab,ab | 3s | 50m |
|
||||||
|
| 5 | b | ab,ab | 0.6s | 9.9m |
|
||||||
|
| 4 | b | ab,ab | 1.2s | 19.9m |
|
||||||
|
| 3 | b | ab,ab | 1.8s | 29.9m |
|
||||||
|
| 2 | b | ab,ab | 2.4s | 39.9m |
|
||||||
|
| 1 | b | ab,ab | 3s | 49.9m |
|
||||||
|
| 1 | 2 | ab,ab | 0.6s | 10m |
|
||||||
|
| 1 | 3 | ab,ab | 1.2s | 20m |
|
||||||
|
| 1 | 4 | ab,ab | 1.8s | 30m |
|
||||||
|
| 1 | 5 | ab,ab | 2.4s | 40m |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||||
|
| a | 0 | 0.6 | 1.2 | 1.8 | 2.4 | 3 | 3.6 |
|
||||||
|
| 1 | 0.8 | 0 | 0.6 | 1.2 | 1.8 | 2.4 | 3 |
|
||||||
|
| 2 | 1.6 | 0.8 | 0 | 0.6 | 1.2 | 1.8 | 2.4 |
|
||||||
|
| 3 | 2.4 | 1.6 | 0.8 | 0 | 0.6 | 1.2 | 1.8 |
|
||||||
|
| 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 | 0.6 | 1.2 |
|
||||||
|
| 5 | 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 | 0.6 |
|
||||||
|
| b | 4.8 | 4 | 3.2 | 2.4 | 1.6 | 0.8 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - No stoppage points, tiny grid size
|
||||||
|
Given a grid size of 1 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 6 7 8 9 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b |
|
||||||
|
| a | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 | 0.3 | 0.4 | 0.4 | 0.5 | 0.6 |
|
||||||
|
| 1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 | 0.3 | 0.4 | 0.4 | 0.5 | 0.6 |
|
||||||
|
| 2 | 0.1 | 0.1 | 0 | 0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.3 | 0.4 | 0.5 |
|
||||||
|
| 3 | 0.2 | 0.2 | 0.1 | 0 | 0.1 | 0.2 | 0.2 | 0.3 | 0.3 | 0.4 | 0.5 |
|
||||||
|
| 4 | 0.3 | 0.3 | 0.2 | 0.1 | 0 | 0.1 | 0.1 | 0.2 | 0.2 | 0.3 | 0.4 |
|
||||||
|
| 5 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 |
|
||||||
|
| 6 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 | 0 | 0.1 | 0.1 | 0.2 | 0.3 |
|
||||||
|
| 7 | 0.5 | 0.5 | 0.4 | 0.3 | 0.2 | 0.1 | 0.1 | 0 | 0 | 0.1 | 0.2 |
|
||||||
|
| 8 | 0.6 | 0.6 | 0.5 | 0.4 | 0.3 | 0.2 | 0.2 | 0.1 | 0 | 0.1 | 0.2 |
|
||||||
|
| 9 | 0.7 | 0.7 | 0.6 | 0.5 | 0.4 | 0.3 | 0.3 | 0.2 | 0.1 | 0 | 0.1 |
|
||||||
|
| b | 0.8 | 0.8 | 0.7 | 0.6 | 0.5 | 0.4 | 0.4 | 0.3 | 0.2 | 0.1 | 0 |
|
||||||
|
|
||||||
|
Scenario: Testbot - With stoppage points, tiny grid size
|
||||||
|
Given a grid size of 1 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 6 7 8 9 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| acceleration_profile | car |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b |
|
||||||
|
| a | 0 | 1.1 | 1.7 | 2.1 | 2.4 | 2.6 | 2.9 | 3.1 | 3.4 | 3.5 | 3.7 |
|
||||||
|
| 1 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.3 | 2.6 | 2.8 | 3.1 | 3.3 | 3.5 |
|
||||||
|
| 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.4 | 2.6 | 2.9 | 3.1 | 3.3 |
|
||||||
|
| 3 | 2 | 1.5 | 1.1 | 0 | 1.1 | 1.5 | 2 | 2.3 | 2.6 | 2.8 | 3 |
|
||||||
|
| 4 | 2.3 | 1.9 | 1.5 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.4 | 2.6 | 2.8 |
|
||||||
|
| 5 | 2.5 | 2.2 | 1.9 | 1.5 | 1.1 | 0 | 1.1 | 1.7 | 2.1 | 2.4 | 2.6 |
|
||||||
|
| 6 | 2.8 | 2.5 | 2.3 | 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 | 2.3 |
|
||||||
|
| 7 | 3 | 2.8 | 2.5 | 2.3 | 2 | 1.7 | 1.1 | 0 | 1.1 | 1.7 | 2 |
|
||||||
|
| 8 | 3.2 | 3 | 2.8 | 2.5 | 2.3 | 2 | 1.5 | 1.1 | 0 | 1.1 | 1.5 |
|
||||||
|
| 9 | 3.4 | 3.2 | 3 | 2.8 | 2.5 | 2.3 | 1.9 | 1.5 | 1.1 | 0 | 1.1 |
|
||||||
|
| b | 3.6 | 3.4 | 3.2 | 3 | 2.8 | 2.5 | 2.2 | 1.9 | 1.5 | 1.1 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Testbot - Use stoppage penalty at waypoints
|
||||||
|
Given a grid size of 10 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| acceleration_profile | car |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||||
|
| a | 0 | 3.7 | 5.3 | 6.5 | 7.5 | 8.4 | 9.1 |
|
||||||
|
| 1 | 3.6 | 0 | 3.7 | 5.3 | 6.5 | 7.5 | 8.3 |
|
||||||
|
| 2 | 5.1 | 3.6 | 0 | 3.7 | 5.3 | 6.5 | 7.5 |
|
||||||
|
| 3 | 6.3 | 5.1 | 3.6 | 0 | 3.7 | 5.3 | 6.4 |
|
||||||
|
| 4 | 7.2 | 6.3 | 5.1 | 3.6 | 0 | 3.7 | 5.2 |
|
||||||
|
| 5 | 8.1 | 7.2 | 6.3 | 5.1 | 3.6 | 0 | 3.7 |
|
||||||
|
| b | 8.9 | 8.1 | 7.2 | 6.2 | 5.1 | 3.6 | 0 |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Long distance grid with no penalty
|
||||||
|
Given a grid size of 1000 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||||
|
| a | 0 | 59.9 | 119.9 | 179.9 | 239.9 | 299.9 | 359.9 |
|
||||||
|
| 1 | 79.9 | 0 | 60 | 120 | 180 | 240 | 300 |
|
||||||
|
| 2 | 159.9 | 80 | 0 | 60 | 120 | 180 | 240 |
|
||||||
|
| 3 | 239.9 | 160 | 80 | 0 | 60 | 120 | 180 |
|
||||||
|
| 4 | 319.9 | 240 | 160 | 80 | 0 | 60 | 120 |
|
||||||
|
| 5 | 399.9 | 320 | 240 | 160 | 80 | 0 | 60 |
|
||||||
|
| b | 479.9 | 400 | 320 | 240 | 160 | 80 | 0 |
|
||||||
|
|
||||||
|
Scenario: Long distance grid
|
||||||
|
Given a grid size of 1000 meters
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a 1 2 3 4 5 b
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | maxspeed:forward | maxspeed:backward |
|
||||||
|
| ab | trunk | 60 | 45 |
|
||||||
|
|
||||||
|
And the query options
|
||||||
|
| acceleration_profile | car |
|
||||||
|
|
||||||
|
When I request a travel time matrix I should get
|
||||||
|
| | a | 1 | 2 | 3 | 4 | 5 | b |
|
||||||
|
| a | 0 | 65.1 | 125.1 | 185.1 | 245.1 | 305.1 | 365.1 |
|
||||||
|
| 1 | 83.7 | 0 | 65.2 | 125.2 | 185.2 | 245.2 | 305.2 |
|
||||||
|
| 2 | 163.7 | 83.8 | 0 | 65.2 | 125.2 | 185.2 | 245.2 |
|
||||||
|
| 3 | 243.7 | 163.8 | 83.8 | 0 | 65.2 | 125.2 | 185.2 |
|
||||||
|
| 4 | 323.7 | 243.8 | 163.8 | 83.8 | 0 | 65.2 | 125.2 |
|
||||||
|
| 5 | 403.7 | 323.8 | 243.8 | 163.8 | 83.8 | 0 | 65.2 |
|
||||||
|
| b | 483.7 | 403.8 | 323.8 | 243.8 | 163.8 | 83.8 | 0 |
|
@ -63,6 +63,13 @@ namespace api
|
|||||||
*/
|
*/
|
||||||
struct BaseParameters
|
struct BaseParameters
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum class SnappingType
|
||||||
|
{
|
||||||
|
Default,
|
||||||
|
Any
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<util::Coordinate> coordinates;
|
std::vector<util::Coordinate> coordinates;
|
||||||
std::vector<boost::optional<Hint>> hints;
|
std::vector<boost::optional<Hint>> hints;
|
||||||
std::vector<boost::optional<double>> radiuses;
|
std::vector<boost::optional<double>> radiuses;
|
||||||
@ -73,15 +80,22 @@ struct BaseParameters
|
|||||||
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
||||||
bool generate_hints = true;
|
bool generate_hints = true;
|
||||||
|
|
||||||
|
SnappingType snapping = SnappingType::Default;
|
||||||
|
// Whether or not to add acceleration/decelleration penalties at waypoints
|
||||||
|
double waypoint_acceleration_factor = 0.;
|
||||||
|
|
||||||
BaseParameters(const std::vector<util::Coordinate> coordinates_ = {},
|
BaseParameters(const std::vector<util::Coordinate> coordinates_ = {},
|
||||||
const std::vector<boost::optional<Hint>> hints_ = {},
|
const std::vector<boost::optional<Hint>> hints_ = {},
|
||||||
std::vector<boost::optional<double>> radiuses_ = {},
|
std::vector<boost::optional<double>> radiuses_ = {},
|
||||||
std::vector<boost::optional<Bearing>> bearings_ = {},
|
std::vector<boost::optional<Bearing>> bearings_ = {},
|
||||||
std::vector<boost::optional<Approach>> approaches_ = {},
|
std::vector<boost::optional<Approach>> approaches_ = {},
|
||||||
bool generate_hints_ = true,
|
bool generate_hints_ = true,
|
||||||
std::vector<std::string> exclude = {})
|
std::vector<std::string> exclude = {},
|
||||||
|
const SnappingType snapping_ = SnappingType::Default,
|
||||||
|
bool waypoint_acceleration_factor_ = 0.)
|
||||||
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
||||||
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_)
|
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_),
|
||||||
|
snapping(snapping_), waypoint_acceleration_factor(waypoint_acceleration_factor_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,23 +386,25 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const Approach approach) const override final
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
input_coordinate, approach);
|
input_coordinate, approach, use_all_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const double max_distance,
|
const double max_distance,
|
||||||
const Approach approach) const override final
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
input_coordinate, max_distance, approach);
|
input_coordinate, max_distance, approach, use_all_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
@ -410,24 +412,26 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
|||||||
const double max_distance,
|
const double max_distance,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const override final
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
input_coordinate, max_distance, bearing, bearing_range, approach);
|
input_coordinate, max_distance, bearing, bearing_range, approach, use_all_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const override final
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const override final
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_geospatial_query.get());
|
BOOST_ASSERT(m_geospatial_query.get());
|
||||||
|
|
||||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
input_coordinate, bearing, bearing_range, approach);
|
input_coordinate, bearing, bearing_range, approach, use_all_edges);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
|
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
|
||||||
|
@ -159,22 +159,26 @@ class BaseDataFacade
|
|||||||
|
|
||||||
virtual std::pair<PhantomNode, PhantomNode>
|
virtual std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const Approach approach) const = 0;
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const = 0;
|
||||||
virtual std::pair<PhantomNode, PhantomNode>
|
virtual std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const double max_distance,
|
const double max_distance,
|
||||||
const Approach approach) const = 0;
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const = 0;
|
||||||
virtual std::pair<PhantomNode, PhantomNode>
|
virtual std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const double max_distance,
|
const double max_distance,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const = 0;
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const = 0;
|
||||||
virtual std::pair<PhantomNode, PhantomNode>
|
virtual std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const = 0;
|
const Approach approach,
|
||||||
|
const bool use_all_edges = false) const = 0;
|
||||||
|
|
||||||
virtual bool HasLaneData(const EdgeID id) const = 0;
|
virtual bool HasLaneData(const EdgeID id) const = 0;
|
||||||
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
||||||
|
@ -205,18 +205,23 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const double max_distance,
|
const double max_distance,
|
||||||
const Approach approach) const
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const
|
||||||
{
|
{
|
||||||
bool has_small_component = false;
|
bool has_small_component = false;
|
||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
[this,
|
||||||
const CandidateSegment &segment) {
|
approach,
|
||||||
|
&input_coordinate,
|
||||||
|
&has_big_component,
|
||||||
|
&has_small_component,
|
||||||
|
&use_all_edges](const CandidateSegment &segment) {
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
const auto valid_edges = HasValidEdge(segment);
|
const auto valid_edges = HasValidEdge(segment, use_all_edges);
|
||||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, admissible_segments);
|
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||||
@ -251,19 +256,24 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const Approach approach) const
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const
|
||||||
{
|
{
|
||||||
bool has_small_component = false;
|
bool has_small_component = false;
|
||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
auto results = rtree.Nearest(
|
auto results = rtree.Nearest(
|
||||||
input_coordinate,
|
input_coordinate,
|
||||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
[this,
|
||||||
const CandidateSegment &segment) {
|
approach,
|
||||||
|
&input_coordinate,
|
||||||
|
&has_big_component,
|
||||||
|
&has_small_component,
|
||||||
|
&use_all_edges](const CandidateSegment &segment) {
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
|
|
||||||
const auto valid_edges = HasValidEdge(segment);
|
const auto valid_edges = HasValidEdge(segment, use_all_edges);
|
||||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, admissible_segments);
|
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||||
@ -298,7 +308,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const
|
||||||
{
|
{
|
||||||
bool has_small_component = false;
|
bool has_small_component = false;
|
||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
@ -310,12 +321,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
bearing,
|
bearing,
|
||||||
bearing_range,
|
bearing_range,
|
||||||
&has_big_component,
|
&has_big_component,
|
||||||
&has_small_component](const CandidateSegment &segment) {
|
&has_small_component,
|
||||||
|
&use_all_edges](const CandidateSegment &segment) {
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
|
||||||
|
|
||||||
if (use_segment)
|
if (use_segment)
|
||||||
{
|
{
|
||||||
@ -356,7 +368,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
const double max_distance,
|
const double max_distance,
|
||||||
const int bearing,
|
const int bearing,
|
||||||
const int bearing_range,
|
const int bearing_range,
|
||||||
const Approach approach) const
|
const Approach approach,
|
||||||
|
const bool use_all_edges) const
|
||||||
{
|
{
|
||||||
bool has_small_component = false;
|
bool has_small_component = false;
|
||||||
bool has_big_component = false;
|
bool has_big_component = false;
|
||||||
@ -368,12 +381,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
bearing,
|
bearing,
|
||||||
bearing_range,
|
bearing_range,
|
||||||
&has_big_component,
|
&has_big_component,
|
||||||
&has_small_component](const CandidateSegment &segment) {
|
&has_small_component,
|
||||||
|
&use_all_edges](const CandidateSegment &segment) {
|
||||||
auto use_segment =
|
auto use_segment =
|
||||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
|
||||||
|
|
||||||
if (use_segment)
|
if (use_segment)
|
||||||
{
|
{
|
||||||
|
@ -270,6 +270,7 @@ class BasePlugin
|
|||||||
const bool use_bearings = !parameters.bearings.empty();
|
const bool use_bearings = !parameters.bearings.empty();
|
||||||
const bool use_radiuses = !parameters.radiuses.empty();
|
const bool use_radiuses = !parameters.radiuses.empty();
|
||||||
const bool use_approaches = !parameters.approaches.empty();
|
const bool use_approaches = !parameters.approaches.empty();
|
||||||
|
const bool use_all_edges = parameters.snapping == api::BaseParameters::SnappingType::Any;
|
||||||
|
|
||||||
BOOST_ASSERT(parameters.IsValid());
|
BOOST_ASSERT(parameters.IsValid());
|
||||||
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||||
@ -296,7 +297,8 @@ class BasePlugin
|
|||||||
*parameters.radiuses[i],
|
*parameters.radiuses[i],
|
||||||
parameters.bearings[i]->bearing,
|
parameters.bearings[i]->bearing,
|
||||||
parameters.bearings[i]->range,
|
parameters.bearings[i]->range,
|
||||||
approach);
|
approach,
|
||||||
|
use_all_edges);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -305,7 +307,8 @@ class BasePlugin
|
|||||||
parameters.coordinates[i],
|
parameters.coordinates[i],
|
||||||
parameters.bearings[i]->bearing,
|
parameters.bearings[i]->bearing,
|
||||||
parameters.bearings[i]->range,
|
parameters.bearings[i]->range,
|
||||||
approach);
|
approach,
|
||||||
|
use_all_edges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -314,13 +317,16 @@ class BasePlugin
|
|||||||
{
|
{
|
||||||
phantom_node_pairs[i] =
|
phantom_node_pairs[i] =
|
||||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
parameters.coordinates[i], *parameters.radiuses[i], approach);
|
parameters.coordinates[i],
|
||||||
|
*parameters.radiuses[i],
|
||||||
|
approach,
|
||||||
|
use_all_edges);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
phantom_node_pairs[i] =
|
phantom_node_pairs[i] =
|
||||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||||
parameters.coordinates[i], approach);
|
parameters.coordinates[i], approach, use_all_edges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -692,6 +692,77 @@ inline bool argumentsToParameter(const Nan::FunctionCallbackInfo<v8::Value> &arg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->Has(Nan::New("snapping").ToLocalChecked()))
|
||||||
|
{
|
||||||
|
v8::Local<v8::Value> snapping = obj->Get(Nan::New("snapping").ToLocalChecked());
|
||||||
|
if (snapping.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!snapping->IsString())
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Snapping must be a string: [default, any]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const Nan::Utf8String snapping_utf8str(snapping);
|
||||||
|
std::string snapping_str{*snapping_utf8str, *snapping_utf8str + snapping_utf8str.length()};
|
||||||
|
|
||||||
|
if (snapping_str == "default")
|
||||||
|
{
|
||||||
|
params->snapping = osrm::RouteParameters::SnappingType::Default;
|
||||||
|
}
|
||||||
|
else if (snapping_str == "any")
|
||||||
|
{
|
||||||
|
params->snapping = osrm::RouteParameters::SnappingType::Any;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Nan::ThrowError("'snapping' param must be one of [default, any]");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj->Has(Nan::New("acceleration_profile").ToLocalChecked()))
|
||||||
|
{
|
||||||
|
v8::Local<v8::Value> acceleration_profile =
|
||||||
|
obj->Get(Nan::New("acceleration_profile").ToLocalChecked());
|
||||||
|
if (acceleration_profile.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!acceleration_profile->IsNumber() || !acceleration_profile->IsString())
|
||||||
|
{
|
||||||
|
Nan::ThrowError("acceleration_profile must be a decimal number or one of 'car', 'fast_car', 'slow_car', 'truck', or 'tractor_trailer'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acceleration_profile->IsString()) {
|
||||||
|
std::string ssaf = *v8::String::Utf8Value(acceleration_profile);
|
||||||
|
// If they say 'yes', they get the default
|
||||||
|
if (ssaf == "car") {
|
||||||
|
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_CAR;
|
||||||
|
} else if (ssaf == "fast_car") {
|
||||||
|
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_FAST_CAR;
|
||||||
|
} else if (ssaf == "slow_car") {
|
||||||
|
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_SLOW_CAR;
|
||||||
|
} else if (ssaf == "truck") {
|
||||||
|
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_TRUCK;
|
||||||
|
} else if (ssaf == "tractor_trailer") {
|
||||||
|
params->waypoint_acceleration_factor = ACCELERATION_ALPHA_TRACTOR_TRAILER;
|
||||||
|
} else {
|
||||||
|
Nan::ThrowError("acceleration_profile must be a decimal number or one of 'car', 'fast_car', 'slow_car', 'truck', or 'tractor_trailer'");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto value = acceleration_profile->NumberValue();
|
||||||
|
if (value < 0) {
|
||||||
|
Nan::ThrowError("acceleration_profile cannot be negative");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
params->waypoint_acceleration_factor = value;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,19 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
},
|
},
|
||||||
qi::_1)];
|
qi::_1)];
|
||||||
|
|
||||||
|
acceleration_alpha_defaults_rule =
|
||||||
|
qi::lit("car")[qi::_val = ACCELERATION_ALPHA_CAR] |
|
||||||
|
qi::lit("fast_car")[qi::_val = ACCELERATION_ALPHA_FAST_CAR] |
|
||||||
|
qi::lit("slow_car")[qi::_val = ACCELERATION_ALPHA_SLOW_CAR] |
|
||||||
|
qi::lit("truck")[qi::_val = ACCELERATION_ALPHA_TRUCK] |
|
||||||
|
qi::lit("tractor_trailer")[qi::_val = ACCELERATION_ALPHA_TRACTOR_TRAILER];
|
||||||
|
|
||||||
|
acceleration_profile_rule =
|
||||||
|
qi::lit("acceleration_profile=") >
|
||||||
|
(qi::double_ | acceleration_alpha_defaults_rule)
|
||||||
|
[ph::bind(&engine::api::BaseParameters::waypoint_acceleration_factor, qi::_r1) =
|
||||||
|
qi::_1];
|
||||||
|
|
||||||
query_rule =
|
query_rule =
|
||||||
((location_rule % ';') | polyline_rule |
|
((location_rule % ';') | polyline_rule |
|
||||||
polyline6_rule)[ph::bind(&engine::api::BaseParameters::coordinates, qi::_r1) = qi::_1];
|
polyline6_rule)[ph::bind(&engine::api::BaseParameters::coordinates, qi::_r1) = qi::_1];
|
||||||
@ -162,6 +175,13 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
(-approach_type %
|
(-approach_type %
|
||||||
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
|
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
|
||||||
|
|
||||||
|
snapping_type.add("default", engine::api::BaseParameters::SnappingType::Default)(
|
||||||
|
"any", engine::api::BaseParameters::SnappingType::Any);
|
||||||
|
|
||||||
|
snapping_rule =
|
||||||
|
qi::lit("snapping=") >
|
||||||
|
snapping_type[ph::bind(&engine::api::BaseParameters::snapping, qi::_r1) = qi::_1];
|
||||||
|
|
||||||
exclude_rule = qi::lit("exclude=") >
|
exclude_rule = qi::lit("exclude=") >
|
||||||
(qi::as_string[+qi::char_("a-zA-Z0-9")] %
|
(qi::as_string[+qi::char_("a-zA-Z0-9")] %
|
||||||
',')[ph::bind(&engine::api::BaseParameters::exclude, qi::_r1) = qi::_1];
|
',')[ph::bind(&engine::api::BaseParameters::exclude, qi::_r1) = qi::_1];
|
||||||
@ -171,7 +191,9 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
| bearings_rule(qi::_r1) //
|
| bearings_rule(qi::_r1) //
|
||||||
| generate_hints_rule(qi::_r1) //
|
| generate_hints_rule(qi::_r1) //
|
||||||
| approach_rule(qi::_r1) //
|
| approach_rule(qi::_r1) //
|
||||||
| exclude_rule(qi::_r1);
|
| exclude_rule(qi::_r1) //
|
||||||
|
| snapping_rule(qi::_r1) //
|
||||||
|
| acceleration_profile_rule(qi::_r1);//
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -188,6 +210,7 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
qi::rule<Iterator, Signature> generate_hints_rule;
|
qi::rule<Iterator, Signature> generate_hints_rule;
|
||||||
qi::rule<Iterator, Signature> approach_rule;
|
qi::rule<Iterator, Signature> approach_rule;
|
||||||
qi::rule<Iterator, Signature> exclude_rule;
|
qi::rule<Iterator, Signature> exclude_rule;
|
||||||
|
qi::rule<Iterator, Signature> acceleration_profile_rule;
|
||||||
|
|
||||||
qi::rule<Iterator, osrm::engine::Bearing()> bearing_rule;
|
qi::rule<Iterator, osrm::engine::Bearing()> bearing_rule;
|
||||||
qi::rule<Iterator, osrm::util::Coordinate()> location_rule;
|
qi::rule<Iterator, osrm::util::Coordinate()> location_rule;
|
||||||
@ -197,8 +220,12 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
|||||||
qi::rule<Iterator, unsigned char()> base64_char;
|
qi::rule<Iterator, unsigned char()> base64_char;
|
||||||
qi::rule<Iterator, std::string()> polyline_chars;
|
qi::rule<Iterator, std::string()> polyline_chars;
|
||||||
qi::rule<Iterator, double()> unlimited_rule;
|
qi::rule<Iterator, double()> unlimited_rule;
|
||||||
|
qi::rule<Iterator, Signature> snapping_rule;
|
||||||
|
|
||||||
|
qi::rule<Iterator, double()> acceleration_alpha_defaults_rule;
|
||||||
|
|
||||||
qi::symbols<char, engine::Approach> approach_type;
|
qi::symbols<char, engine::Approach> approach_type;
|
||||||
|
qi::symbols<char, engine::api::BaseParameters::SnappingType> snapping_type;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,8 +488,8 @@ inline void Prettify(char *buffer, int length, int k)
|
|||||||
inline void dtoa_milo(double value, char *buffer)
|
inline void dtoa_milo(double value, char *buffer)
|
||||||
{
|
{
|
||||||
// Not handling NaN and inf
|
// Not handling NaN and inf
|
||||||
assert(!isnan(value));
|
assert(!std::isnan(value));
|
||||||
assert(!isinf(value));
|
assert(!std::isinf(value));
|
||||||
|
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
{
|
{
|
||||||
|
@ -118,6 +118,14 @@ static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>
|
|||||||
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||||
static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<double>::max();
|
static const EdgeDistance INVALID_FALLBACK_SPEED = std::numeric_limits<double>::max();
|
||||||
|
|
||||||
|
// Recommended value for passenger vehicles from
|
||||||
|
// https://fdotwww.blob.core.windows.net/sitefinity/docs/default-source/content/rail/publications/studies/safety/accelerationresearch.pdf?sfvrsn=716a4bb1_0
|
||||||
|
static const double ACCELERATION_ALPHA_CAR = 6.0;
|
||||||
|
static const double ACCELERATION_ALPHA_FAST_CAR = 18;
|
||||||
|
static const double ACCELERATION_ALPHA_SLOW_CAR = 2;
|
||||||
|
static const double ACCELERATION_ALPHA_TRUCK = 1.5;
|
||||||
|
static const double ACCELERATION_ALPHA_TRACTOR_TRAILER = 0.5;
|
||||||
|
|
||||||
// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent
|
// FIXME the bitfields we use require a reduced maximal duration, this should be kept consistent
|
||||||
// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any
|
// within the code base. For now we have to ensure that we don't case 30 bit to -1 and break any
|
||||||
// min() / operator< checks due to the invalid truncation. In addition, using signed and unsigned
|
// min() / operator< checks due to the invalid truncation. In addition, using signed and unsigned
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.21.0",
|
"version": "5.21.0-customsnapping.9",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -86,8 +86,11 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
bool request_distance = params.annotations & api::TableParameters::AnnotationsType::Distance;
|
bool request_distance = params.annotations & api::TableParameters::AnnotationsType::Distance;
|
||||||
bool request_duration = params.annotations & api::TableParameters::AnnotationsType::Duration;
|
bool request_duration = params.annotations & api::TableParameters::AnnotationsType::Duration;
|
||||||
|
|
||||||
|
// Because of the Short Trip ETA adjustments below, we need distances every time
|
||||||
|
const bool distances_required = request_distance || params.waypoint_acceleration_factor > 0.;
|
||||||
|
|
||||||
auto result_tables_pair = algorithms.ManyToManySearch(
|
auto result_tables_pair = algorithms.ManyToManySearch(
|
||||||
snapped_phantoms, params.sources, params.destinations, request_distance);
|
snapped_phantoms, params.sources, params.destinations, distances_required);
|
||||||
|
|
||||||
if ((request_duration && result_tables_pair.first.empty()) ||
|
if ((request_duration && result_tables_pair.first.empty()) ||
|
||||||
(request_distance && result_tables_pair.second.empty()))
|
(request_distance && result_tables_pair.second.empty()))
|
||||||
@ -97,8 +100,71 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
|
|
||||||
std::vector<api::TableAPI::TableCellRef> estimated_pairs;
|
std::vector<api::TableAPI::TableCellRef> estimated_pairs;
|
||||||
|
|
||||||
|
// Adds some time to adjust for getting up to speed and slowing down to a stop
|
||||||
|
// Returns a new `duration`
|
||||||
|
auto adjust_for_startstop = [&](const double &acceleration_alpha,
|
||||||
|
const EdgeDuration &duration,
|
||||||
|
const EdgeDistance &distance) -> EdgeDuration {
|
||||||
|
|
||||||
|
// Very short paths can end up with 0 duration. That'll lead to a divide
|
||||||
|
// by zero, so instead, we'll assume the travel speed is 10m/s (36km/h).
|
||||||
|
// Typically, the distance is also short, so we're quibbling at tiny numbers
|
||||||
|
// here, but tiny numbers is what this adjustment lambda is all about,
|
||||||
|
// so we do try to be reasonable.
|
||||||
|
const auto average_speed =
|
||||||
|
duration == 0 ? 10 : std::abs(distance) /
|
||||||
|
(duration / 10.); // duration is in deciseconds, we need m/sec
|
||||||
|
|
||||||
|
// The following reference has a nice model (equations 9 through 12)
|
||||||
|
// for vehicle acceleration
|
||||||
|
// https://fdotwww.blob.core.windows.net/sitefinity/docs/default-source/content/rail/publications/studies/safety/accelerationresearch.pdf?sfvrsn=716a4bb1_0
|
||||||
|
// We solve euqation 10 for time to figure out how long it'll take
|
||||||
|
// to get up to the desired speed
|
||||||
|
|
||||||
|
// Because Equation 10 is asymptotic on v_des, we need to pick a target speed
|
||||||
|
// that's slighly less so the equation can actually get there. 1m/s less than
|
||||||
|
// target seems like a reasonable value to aim for
|
||||||
|
const auto target_speed = std::max(average_speed - 1, 0.1);
|
||||||
|
const auto initial_speed = 0.;
|
||||||
|
|
||||||
|
// Equation 9
|
||||||
|
const auto beta = acceleration_alpha / average_speed;
|
||||||
|
|
||||||
|
// Equation 10 solved for time
|
||||||
|
const auto time_to_full_speed = std::log( (average_speed - initial_speed) / (average_speed - target_speed) ) / beta;
|
||||||
|
BOOST_ASSERT(time_to_full_speed >= 0);
|
||||||
|
|
||||||
|
// Equation 11
|
||||||
|
const auto distance_to_full_speed =
|
||||||
|
average_speed * time_to_full_speed -
|
||||||
|
average_speed * (1 - std::exp(-1 * beta * time_to_full_speed)) / beta;
|
||||||
|
|
||||||
|
BOOST_ASSERT(distance_to_full_speed >= 0);
|
||||||
|
|
||||||
|
if (distance_to_full_speed > std::abs(distance) / 2)
|
||||||
|
{
|
||||||
|
// Because equation 12 requires velocity at halfway, and
|
||||||
|
// solving equation 11 for t requires a Lambert W function,
|
||||||
|
// we'll approximate here by assuming constant acceleration
|
||||||
|
// over distance_to_full_speed using s = ut + 1/2at^2
|
||||||
|
const auto average_acceleration =
|
||||||
|
2 * distance_to_full_speed / (time_to_full_speed * time_to_full_speed);
|
||||||
|
const auto time_to_halfway = std::sqrt(std::abs(distance) / average_acceleration);
|
||||||
|
BOOST_ASSERT(time_to_halfway >= 0);
|
||||||
|
return (2 * time_to_halfway) * 10; // result is in deciseconds
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto cruising_distance = std::abs(distance) - 2 * distance_to_full_speed;
|
||||||
|
const auto cruising_time = cruising_distance / average_speed;
|
||||||
|
BOOST_ASSERT(cruising_time >= 0);
|
||||||
|
return (cruising_time + 2 * time_to_full_speed) * 10; // result is in deciseconds
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Scan table for null results - if any exist, replace with distance estimates
|
// Scan table for null results - if any exist, replace with distance estimates
|
||||||
if (params.fallback_speed != INVALID_FALLBACK_SPEED || params.scale_factor != 1)
|
if (params.fallback_speed != INVALID_FALLBACK_SPEED || params.scale_factor != 1 ||
|
||||||
|
params.waypoint_acceleration_factor != 0.)
|
||||||
{
|
{
|
||||||
for (std::size_t row = 0; row < num_sources; row++)
|
for (std::size_t row = 0; row < num_sources; row++)
|
||||||
{
|
{
|
||||||
@ -106,6 +172,16 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
{
|
{
|
||||||
const auto &table_index = row * num_destinations + column;
|
const auto &table_index = row * num_destinations + column;
|
||||||
BOOST_ASSERT(table_index < result_tables_pair.first.size());
|
BOOST_ASSERT(table_index < result_tables_pair.first.size());
|
||||||
|
// apply an accel/deceleration penalty to the duration
|
||||||
|
if (result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
|
||||||
|
row != column && params.waypoint_acceleration_factor != 0.)
|
||||||
|
{
|
||||||
|
result_tables_pair.first[table_index] =
|
||||||
|
adjust_for_startstop(params.waypoint_acceleration_factor,
|
||||||
|
result_tables_pair.first[table_index],
|
||||||
|
result_tables_pair.second[table_index]);
|
||||||
|
}
|
||||||
|
// Estimate null results based on fallback_speed (if valid) and distance
|
||||||
if (params.fallback_speed != INVALID_FALLBACK_SPEED && params.fallback_speed > 0 &&
|
if (params.fallback_speed != INVALID_FALLBACK_SPEED && params.fallback_speed > 0 &&
|
||||||
result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION)
|
result_tables_pair.first[table_index] == MAXIMAL_EDGE_DURATION)
|
||||||
{
|
{
|
||||||
@ -132,6 +208,7 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
|
|
||||||
estimated_pairs.emplace_back(row, column);
|
estimated_pairs.emplace_back(row, column);
|
||||||
}
|
}
|
||||||
|
// Apply a scale factor to non-null result if requested
|
||||||
if (params.scale_factor > 0 && params.scale_factor != 1 &&
|
if (params.scale_factor > 0 && params.scale_factor != 1 &&
|
||||||
result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
|
result_tables_pair.first[table_index] != MAXIMAL_EDGE_DURATION &&
|
||||||
result_tables_pair.first[table_index] != 0)
|
result_tables_pair.first[table_index] != 0)
|
||||||
@ -153,6 +230,14 @@ Status TablePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If distances weren't requested, delete them from the result so they don't
|
||||||
|
// get rendered.
|
||||||
|
if (!request_distance)
|
||||||
|
{
|
||||||
|
std::vector<EdgeDistance> empty;
|
||||||
|
result_tables_pair.second.swap(empty);
|
||||||
|
}
|
||||||
|
|
||||||
api::TableAPI table_api{facade, params};
|
api::TableAPI table_api{facade, params};
|
||||||
table_api.MakeResponse(result_tables_pair, snapped_phantoms, estimated_pairs, result);
|
table_api.MakeResponse(result_tables_pair, snapped_phantoms, estimated_pairs, result);
|
||||||
|
|
||||||
|
@ -143,7 +143,8 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration))
|
else if (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration) &&
|
||||||
|
new_distance >= 0)
|
||||||
{
|
{
|
||||||
current_weight = new_weight;
|
current_weight = new_weight;
|
||||||
current_duration = new_duration;
|
current_duration = new_duration;
|
||||||
|
@ -606,3 +606,23 @@ test('route: route in Monaco without motorways', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('route: throws on invalid snapping values', function (assert) {
|
||||||
|
assert.plan(1);
|
||||||
|
var osrm = new OSRM(monaco_path);
|
||||||
|
var options = {
|
||||||
|
steps: true,
|
||||||
|
coordinates: three_test_coordinates.concat(three_test_coordinates),
|
||||||
|
snapping: "zing"
|
||||||
|
};
|
||||||
|
assert.throws(function () { osrm.route(options, function (err, response) { console.error(`response: ${response}`); console.error(`error: ${err}`); }); },
|
||||||
|
/'snapping' param must be one of \[default, any\]/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('route: snapping parameter passed through OK', function(assert) {
|
||||||
|
assert.plan(2);
|
||||||
|
var osrm = new OSRM(monaco_path);
|
||||||
|
osrm.route({snapping: "any", coordinates: [[7.448205209414596,43.754001097311544],[7.447122039202185,43.75306156811368]]}, function(err, route) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(Math.round(route.routes[0].distance * 10), 1314); // Round it to nearest 0.1m to eliminate floating point comparison error
|
||||||
|
});
|
||||||
|
});
|
@ -48,6 +48,21 @@ test('table: test annotations paramater combination', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('table: snapping parameter passed through OK', function(assert) {
|
||||||
|
assert.plan(2);
|
||||||
|
var osrm = new OSRM(data_path);
|
||||||
|
var options = {
|
||||||
|
coordinates: [[7.448205209414596,43.754001097311544],[7.447122039202185,43.75306156811368]],
|
||||||
|
annotations: ['duration', 'distance'],
|
||||||
|
snapping: 'any'
|
||||||
|
};
|
||||||
|
console.log(options);
|
||||||
|
osrm.table(options, function(err, result) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(Math.round(result.distances[0][1] * 10), 1315); // Round it to nearest 0.1m to eliminate floating point comparison error
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('table: returns buffer', function(assert) {
|
test('table: returns buffer', function(assert) {
|
||||||
assert.plan(3);
|
assert.plan(3);
|
||||||
var osrm = new OSRM(data_path);
|
var osrm = new OSRM(data_path);
|
||||||
@ -303,5 +318,46 @@ tables.forEach(function(annotation) {
|
|||||||
assert.throws(()=>osrm.table(options, (err, res) => {}), /scale_factor must be > 0/, "should throw on invalid scale_factor value");
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /scale_factor must be > 0/, "should throw on invalid scale_factor value");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('table: ' + annotation + ' table in Monaco with start_stop_acceleration_factor values', function(assert) {
|
||||||
|
assert.plan(12);
|
||||||
|
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
||||||
|
var options = {
|
||||||
|
coordinates: two_test_coordinates,
|
||||||
|
annotations: [annotation.slice(0,-1)],
|
||||||
|
acceleration_profile: []
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on empty array");
|
||||||
|
|
||||||
|
options.start_stop_acceleration_factor = 'a';
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on non-numeric value");
|
||||||
|
|
||||||
|
options.start_stop_acceleration_factor = [1];
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on non-numeric value");
|
||||||
|
|
||||||
|
options.start_stop_acceleration_factor = -0.1;
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on non-numeric value");
|
||||||
|
|
||||||
|
options.start_stop_acceleration_factor = 0.;
|
||||||
|
assert.ok(()=>osrm.table(options, (err, res) => {}), "should work with zero");
|
||||||
|
|
||||||
|
options.start_stop_acceleration_factor = 2.0;
|
||||||
|
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with positive numeric values");
|
||||||
|
options.start_stop_acceleration_factor = 'car';
|
||||||
|
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with car defaults");
|
||||||
|
options.start_stop_acceleration_factor = 'fast_car';
|
||||||
|
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with fast car defaults");
|
||||||
|
options.start_stop_acceleration_factor = 'slow_car';
|
||||||
|
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with slow car defaults");
|
||||||
|
options.start_stop_acceleration_factor = 'truck';
|
||||||
|
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with truck defaults");
|
||||||
|
options.start_stop_acceleration_factor = 'tractor_trailer';
|
||||||
|
assert.ok(()=>osrm.table(options, (err, res) => {}), "Should work with tractor trailer defaults");
|
||||||
|
|
||||||
|
options.start_stop_acceleration_factor = 'yes';
|
||||||
|
assert.throws(()=>osrm.table(options, (err, res) => {}), /acceleration_profile must be a decimal number or one of/, "should throw on non-recognized string");
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -284,7 +284,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
|||||||
|
|
||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||||
const Approach /*approach*/) const override
|
const Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -292,7 +293,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
|||||||
std::pair<PhantomNode, PhantomNode>
|
std::pair<PhantomNode, PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||||
const double /*max_distance*/,
|
const double /*max_distance*/,
|
||||||
const Approach /*approach*/) const override
|
const Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -302,7 +304,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
|||||||
const double /*max_distance*/,
|
const double /*max_distance*/,
|
||||||
const int /*bearing*/,
|
const int /*bearing*/,
|
||||||
const int /*bearing_range*/,
|
const int /*bearing_range*/,
|
||||||
const Approach /*approach*/) const override
|
const Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -311,7 +314,8 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
|||||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||||
const int /*bearing*/,
|
const int /*bearing*/,
|
||||||
const int /*bearing_range*/,
|
const int /*bearing_range*/,
|
||||||
const Approach /*approach*/) const override
|
const Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -167,39 +167,39 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||||
const util::Coordinate /*input_coordinate*/,
|
const engine::Approach /*approach*/,
|
||||||
const engine::Approach /*approach*/) const override
|
const bool /* use_all_edges */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||||
const util::Coordinate /*input_coordinate*/,
|
|
||||||
const double /*max_distance*/,
|
const double /*max_distance*/,
|
||||||
const engine::Approach /*approach*/) const override
|
const engine::Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||||
const util::Coordinate /*input_coordinate*/,
|
|
||||||
const double /*max_distance*/,
|
const double /*max_distance*/,
|
||||||
const int /*bearing*/,
|
const int /*bearing*/,
|
||||||
const int /*bearing_range*/,
|
const int /*bearing_range*/,
|
||||||
const engine::Approach /*approach*/) const override
|
const engine::Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<engine::PhantomNode, engine::PhantomNode>
|
std::pair<engine::PhantomNode, engine::PhantomNode>
|
||||||
NearestPhantomNodeWithAlternativeFromBigComponent(
|
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||||
const util::Coordinate /*input_coordinate*/,
|
|
||||||
const int /*bearing*/,
|
const int /*bearing*/,
|
||||||
const int /*bearing_range*/,
|
const int /*bearing_range*/,
|
||||||
const engine::Approach /*approach*/) const override
|
const engine::Approach /*approach*/,
|
||||||
|
const bool /* use_all_edges */) const override
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user