Merge pull request #1766 from Project-OSRM/feature/bearing_selection

Add bearing support to all plugins, add optional range to bearing parameter.
This commit is contained in:
Daniel Patterson 2015-11-17 16:41:34 -05:00
commit 13ceeb191c
11 changed files with 326 additions and 282 deletions

View File

@ -118,16 +118,17 @@ void RouteParameters::addTimestamp(const unsigned timestamp)
} }
} }
void RouteParameters::addBearing(const int bearing, boost::spirit::qi::unused_type unused, bool& pass) void RouteParameters::addBearing(
const boost::fusion::vector<int, boost::optional<int>> &received_bearing,
boost::spirit::qi::unused_type /* unused */, bool& pass)
{ {
bearings.resize(coordinates.size());
pass = false; pass = false;
const int bearing = boost::fusion::at_c<0>(received_bearing);
const boost::optional<int> range = boost::fusion::at_c<1>(received_bearing);
if (bearing < 0 || bearing > 359) return; if (bearing < 0 || bearing > 359) return;
if (!bearings.empty()) if (range && (*range < 0 || *range > 180)) return;
{ bearings.emplace_back(std::make_pair(bearing,range));
bearings.back() = bearing; pass = true;
pass = true;
}
} }
void RouteParameters::setLanguage(const std::string &language_string) void RouteParameters::setLanguage(const std::string &language_string)

View File

@ -8,6 +8,17 @@ When /^I match I should get$/ do |table|
response = request_url row['request'] response = request_url row['request']
else else
params = @query_params params = @query_params
got = {}
row.each_pair do |k,v|
if k =~ /param:(.*)/
if v=='(nil)'
params[$1]=nil
elsif v!=nil
params[$1]=v
end
got[k]=v
end
end
trace = [] trace = []
timestamps = [] timestamps = []
if row['trace'] if row['trace']
@ -19,24 +30,13 @@ When /^I match I should get$/ do |table|
if row['timestamps'] if row['timestamps']
timestamps = row['timestamps'].split(" ").compact.map { |t| t.to_i} timestamps = row['timestamps'].split(" ").compact.map { |t| t.to_i}
end end
got = {'trace' => row['trace'] } got = got.merge({'trace' => row['trace'] })
response = request_matching trace, timestamps, params response = request_matching trace, timestamps, params
else else
raise "*** no trace" raise "*** no trace"
end end
end end
row.each_pair do |k,v|
if k =~ /param:(.*)/
if v=='(nil)'
params[$1]=nil
elsif v!=nil
params[$1]=v
end
got[k]=v
end
end
if response.body.empty? == false if response.body.empty? == false
json = JSON.parse response.body json = JSON.parse response.body
end end

View File

@ -8,6 +8,17 @@ When /^I route I should get$/ do |table|
response = request_url row['request'] response = request_url row['request']
else else
params = @query_params params = @query_params
got = {}
row.each_pair do |k,v|
if k =~ /param:(.*)/
if v=='(nil)'
params[$1]=nil
elsif v!=nil
params[$1]=v
end
got[k]=v
end
end
waypoints = [] waypoints = []
if row['from'] and row['to'] if row['from'] and row['to']
node = find_node_by_name(row['from']) node = find_node_by_name(row['from'])
@ -18,7 +29,7 @@ When /^I route I should get$/ do |table|
raise "*** unknown to-node '#{row['to']}" unless node raise "*** unknown to-node '#{row['to']}" unless node
waypoints << node waypoints << node
got = {'from' => row['from'], 'to' => row['to'] } got = got.merge({'from' => row['from'], 'to' => row['to'] })
response = request_route waypoints, params response = request_route waypoints, params
elsif row['waypoints'] elsif row['waypoints']
row['waypoints'].split(',').each do |n| row['waypoints'].split(',').each do |n|
@ -26,24 +37,13 @@ When /^I route I should get$/ do |table|
raise "*** unknown waypoint node '#{n.strip}" unless node raise "*** unknown waypoint node '#{n.strip}" unless node
waypoints << node waypoints << node
end end
got = {'waypoints' => row['waypoints'] } got = got.merge({'waypoints' => row['waypoints'] })
response = request_route waypoints, params response = request_route waypoints, params
else else
raise "*** no waypoints" raise "*** no waypoints"
end end
end end
row.each_pair do |k,v|
if k =~ /param:(.*)/
if v=='(nil)'
params[$1]=nil
elsif v!=nil
params[$1]=v
end
got[k]=v
end
end
if response.body.empty? == false if response.body.empty? == false
json = JSON.parse response.body json = JSON.parse response.body
end end

View File

@ -1,10 +1,26 @@
@routing @bearing_param @todo @testbot @routing @bearing_param @testbot
Feature: Bearing parameter Feature: Bearing parameter
Background: Background:
Given the profile "testbot" Given the profile "testbot"
And a grid size of 10 meters And a grid size of 10 meters
Scenario: Testbot - Intial bearing in simple case
Given the node map
| a | b | c | d |
And the ways
| nodes |
| ad |
When I route I should get
| from | to | param:b | route | bearing |
| b | c | 90&b=90 | ad | 90 |
| b | c | 180&b=90 | | |
| b | c | 80&b=100 | ad | 90 |
| b | c | 79&b=100 | | |
| b | c | 79,11&b=100 | ad | 90 |
Scenario: Testbot - Intial bearing in simple case Scenario: Testbot - Intial bearing in simple case
Given the node map Given the node map
| a | | | a | |
@ -17,13 +33,13 @@ Feature: Bearing parameter
| bc | | bc |
When I route I should get When I route I should get
| from | to | param:bearing | route | bearing | | from | to | param:b | route | bearing |
| 0 | c | 0 | bc | 45 | | 0 | c | 0&b=0 | | |
| 0 | c | 45 | bc | 45 | | 0 | c | 45&b=45 | bc | 45 ~3% |
| 0 | c | 85 | bc | 45 | | 0 | c | 85&b=85 | | |
| 0 | c | 95 | ac | 135 | | 0 | c | 95&b=95 | | |
| 0 | c | 135 | ac | 135 | | 0 | c | 135&b=135 | ac | 135 ~1% |
| 0 | c | 180 | ac | 135 | | 0 | c | 180&b=180 | | |
Scenario: Testbot - Initial bearing on split way Scenario: Testbot - Initial bearing on split way
Given the node map Given the node map
@ -38,23 +54,21 @@ Feature: Bearing parameter
| da | yes | | da | yes |
When I route I should get When I route I should get
| from | to | param:bearing | route | bearing | | from | to | param:b | route | bearing |
| 0 | b | 10 | ab | 90 | | 0 | b | 10&b=10 | | |
| 0 | b | 90 | ab | 90 | | 0 | b | 90&b=90 | ab | 90 |
| 0 | b | 170 | ab | 90 | | 0 | b | 170&b=170 | | |
| 0 | b | 190 | cd,da,ab | 270 | | 0 | b | 190&b=190 | | |
| 0 | b | 270 | cd,da,ab | 270 | | 0 | 1 | 90&b=270 | ab,bc,cd | 90,0,270 |
| 0 | b | 350 | cd,da,ab | 270 | | 1 | d | 10&b=10 | | |
| 1 | d | 10 | cd | 90 | | 1 | d | 90&b=90 | | |
| 1 | d | 90 | cd | 90 | | 1 | 0 | 190&b=190 | | |
| 1 | d | 170 | cd | 90 | | 1 | d | 270&b=270 | cd | 270 |
| 1 | d | 190 | ab,bc,cd | 270 | | 1 | d | 350&b=350 | | |
| 1 | d | 270 | ab,bc,cd | 270 |
| 1 | d | 350 | ab,bc,cd | 270 |
Scenario: Testbot - Initial bearing in all direction Scenario: Testbot - Initial bearing in all direction
Given the node map Given the node map
| h | | | a | | | b | | h | | q | a | | | b |
| | | | | | | | | | | | | | | |
| | | p | i | j | | | | | | p | i | j | | |
| g | | o | 0 | k | | c | | g | | o | 0 | k | | c |
@ -82,12 +96,12 @@ Feature: Bearing parameter
| ha | yes | | ha | yes |
When I route I should get When I route I should get
| from | to | param:bearing | route | bearing | | from | to | param:b | route | bearing |
| 0 | a | 0 | ia | 0 | | i | q | 0&b=90 | ia,ab,bc,cd,de,ef,fg,gh,ha | 0,90,180,180,270,270,0,0,90 |
| 0 | a | 45 | jb,bc,cd,de,ef,fg,gh,ha | 45 | | 0 | a | 45&b=90 | jb,bc,cd,de,ef,fg,gh,ha | 45,180,180,270,270,0,0,90 |
| 0 | a | 90 | kc,cd,de,ef,fg,gh,ha | 90 | | j | q | 90&b=90 | kc,cd,de,ef,fg,gh,ha | 90,180,270,270,0,0,90 |
| 0 | a | 135 | ld,de,ef,fg,gh,ha | 135 | | k | a | 135&b=90 | ld,de,ef,fg,gh,ha | 135,270,270,0,0,90 |
| 0 | a | 180 | me,de,ef,fg,gh,ha | 180 | | 0 | a | 180&b=90 | me,ef,fg,gh,ha | 180,270,0,0,90 |
| 0 | a | 225 | nf,ef,fg,gh,ha | 225 | | m | a | 225&b=90 | nf,fg,gh,ha | 225,0,0,90 |
| 0 | a | 270 | og,gh,ha | 270 | | 0 | a | 270&b=90 | og,gh,ha | 270,0,90 |
| 0 | a | 315 | pn,ha | 315 | | 0 | a | 315&b=90 | ph,ha | 315,90 |

View File

@ -72,7 +72,7 @@ struct RouteParameters
void addTimestamp(const unsigned timestamp); void addTimestamp(const unsigned timestamp);
void addBearing(const int timestamp, boost::spirit::qi::unused_type unused, bool& pass); void addBearing(const boost::fusion::vector<int, boost::optional<int>> &received_bearing, boost::spirit::qi::unused_type unused, bool& pass);
void setLanguage(const std::string &language); void setLanguage(const std::string &language);
@ -102,7 +102,7 @@ struct RouteParameters
std::string language; std::string language;
std::vector<std::string> hints; std::vector<std::string> hints;
std::vector<unsigned> timestamps; std::vector<unsigned> timestamps;
std::vector<int> bearings; std::vector<std::pair<const int,const boost::optional<int>>> bearings;
std::vector<bool> uturns; std::vector<bool> uturns;
std::vector<FixedPointCoordinate> coordinates; std::vector<FixedPointCoordinate> coordinates;
}; };

View File

@ -75,6 +75,13 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
return 400; return 400;
} }
const auto &input_bearings = route_parameters.bearings;
if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size())
{
json_result.values["status"] = "Number of bearings does not match number of coordinates .";
return 400;
}
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
unsigned max_locations = unsigned max_locations =
std::min(static_cast<unsigned>(max_locations_distance_table), std::min(static_cast<unsigned>(max_locations_distance_table),
@ -94,8 +101,10 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
continue; continue;
} }
} }
const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0;
const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180;
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
phantom_node_vector[i], 1); phantom_node_vector[i], 1, bearing, range);
BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes())); BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
} }

View File

@ -94,7 +94,7 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
} }
bool getCandidates(const std::vector<FixedPointCoordinate> &input_coords, bool getCandidates(const std::vector<FixedPointCoordinate> &input_coords,
const std::vector<int> &input_bearings, const std::vector<std::pair<const int,const boost::optional<int>>> &input_bearings,
const double gps_precision, const double gps_precision,
std::vector<double> &sub_trace_lengths, std::vector<double> &sub_trace_lengths,
osrm::matching::CandidateLists &candidates_lists) osrm::matching::CandidateLists &candidates_lists)
@ -130,8 +130,8 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
std::vector<std::pair<PhantomNode, double>> candidates; std::vector<std::pair<PhantomNode, double>> candidates;
// Use bearing values if supplied, otherwise fallback to 0,180 defaults // Use bearing values if supplied, otherwise fallback to 0,180 defaults
auto bearing = input_bearings.size() > 0 ? input_bearings[current_coordinate] : 0; auto bearing = input_bearings.size() > 0 ? input_bearings[current_coordinate].first : 0;
auto range = input_bearings.size() > 0 ? 10 : 180; auto range = input_bearings.size() > 0 ? (input_bearings[current_coordinate].second ? *input_bearings[current_coordinate].second : 10 ) : 180;
facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance( facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
input_coords[current_coordinate], candidates, query_radius, input_coords[current_coordinate], candidates, query_radius,
bearing, range); bearing, range);

View File

@ -58,11 +58,21 @@ template <class DataFacadeT> class NearestPlugin final : public BasePlugin
{ {
return 400; return 400;
} }
const auto &input_bearings = route_parameters.bearings;
if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size())
{
json_result.values["status"] = "Number of bearings does not match number of coordinates .";
return 400;
}
auto number_of_results = static_cast<std::size_t>(route_parameters.num_results); auto number_of_results = static_cast<std::size_t>(route_parameters.num_results);
std::vector<PhantomNode> phantom_node_vector; std::vector<PhantomNode> phantom_node_vector;
const int bearing = input_bearings.size() > 0 ? input_bearings.front().first : 0;
const int range = input_bearings.size() > 0 ? (input_bearings.front().second?*input_bearings.front().second:10) : 180;
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(), facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
phantom_node_vector, phantom_node_vector,
static_cast<int>(number_of_results)); static_cast<int>(number_of_results), bearing, range);
if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid()) if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid())
{ {

View File

@ -76,6 +76,7 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
PhantomNodeArray &phantom_node_vector) PhantomNodeArray &phantom_node_vector)
{ {
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum()); const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
const auto &input_bearings = route_parameters.bearings;
// find phantom nodes for all input coords // find phantom nodes for all input coords
for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size())) for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size()))
@ -92,8 +93,10 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
continue; continue;
} }
} }
const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0;
const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180;
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
phantom_node_vector[i], 1); phantom_node_vector[i], 1, bearing, range);
if (phantom_node_vector[i].size() > 1) if (phantom_node_vector[i].size() > 1)
{ {
phantom_node_vector[i].erase(std::begin(phantom_node_vector[i])); phantom_node_vector[i].erase(std::begin(phantom_node_vector[i]));
@ -239,6 +242,13 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
return 400; return 400;
} }
const auto &input_bearings = route_parameters.bearings;
if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size())
{
json_result.values["status"] = "Number of bearings does not match number of coordinates .";
return 400;
}
// get phantom nodes // get phantom nodes
PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size()); PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
GetPhantomNodes(route_parameters, phantom_node_vector); GetPhantomNodes(route_parameters, phantom_node_vector);

View File

@ -103,8 +103,8 @@ template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
} }
} }
std::vector<PhantomNode> phantom_node_vector; std::vector<PhantomNode> phantom_node_vector;
int bearing = input_bearings.size() > 0 ? input_bearings[i] : 0; const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0;
int range = input_bearings.size() > 0 ? 8 : 180; const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180;
if (facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i], if (facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
phantom_node_vector, 1, bearing, range)) phantom_node_vector, 1, bearing, range))
{ {

View File

@ -66,7 +66,7 @@ template <typename Iterator, class HandlerT> struct APIGrammar : qi::grammar<Ite
timestamp = (-qi::lit('&')) >> qi::lit("t") >> '=' >> timestamp = (-qi::lit('&')) >> qi::lit("t") >> '=' >>
qi::uint_[boost::bind(&HandlerT::addTimestamp, handler, ::_1)]; qi::uint_[boost::bind(&HandlerT::addTimestamp, handler, ::_1)];
bearing = (-qi::lit('&')) >> qi::lit("b") >> '=' >> bearing = (-qi::lit('&')) >> qi::lit("b") >> '=' >>
qi::int_[boost::bind(&HandlerT::addBearing, handler, ::_1, ::_2, ::_3)]; (qi::int_ >> -(qi::lit(',') >> qi::int_ | qi::attr(10)))[boost::bind(&HandlerT::addBearing, handler, ::_1, ::_2, ::_3)];
u = (-qi::lit('&')) >> qi::lit("u") >> '=' >> u = (-qi::lit('&')) >> qi::lit("u") >> '=' >>
qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)]; qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)];
uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >> uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >>