Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Per location search filters for functional road class and forms of way #2289

Merged
merged 15 commits into from
Apr 3, 2020

Conversation

danpaz
Copy link
Collaborator

@danpaz danpaz commented Mar 26, 2020

Issue

This PR enables excluding edge candidates from Loki's search results with a new per-location parameter search_filter. Unlike heading and preferred_side filters, search_filter removes edges from the set of candidates entirely. The idea is to customize snapping behavior for routing: in some cases you don't want to snap to a highway or tunnel if you know your destination is a building centroid, even if that building is closer to the highway than the nearest navigable road.

Supports filtering on the following parameters:

  • min_road_class (string, default "service_other"): min functional road class allowed, options are from highest to lowest: "motorway","trunk","primary","secondary","tertiary","unclassified","residential","service_other"
  • max_road_class (string, default "motorway"): max functional road class allowed, options are from highest to lowest: "motorway","trunk","primary","secondary","tertiary","unclassified","residential","service_other"
  • exclude_tunnel (boolean, default false) exclude roads with tunnel attribution
  • exclude_bridge (boolean, default false) exclude roads with bridge attribution
  • exclude_ramp (boolean, default false) exclude roads with ramp use (includes links and turn channels)

Tasklist

  • Add tests
  • Add #fixes with the issue number that this PR addresses
  • Generally use squash merge to rebase and clean comments before merging
  • Update the changelog

Requirements / Relations

Link any requirements here. Other pull requests this PR is based on?

@@ -122,3 +133,14 @@ message TurnLane {
optional uint32 directions_mask = 1;
optional bool is_active = 2;
}

enum RoadClass {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored this enum out of TripLeg and into the top level namespace in 99998bd so I could use it in the Location SearchFilter message. Actually much of the diff in this PR is that one refactor commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have any concerns about backward compatibility here? This will break any existing users of the protobuf definitions unless they too refactor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be wrong but AFAIK the proto definitions are only used within Valhalla, and I'm not aware of a situation where valhalla processes of different versions would be communicating with each other.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was my understanding as well, the external API of Valhalla doesn't include protobuf definitions.

Copy link
Member

@kevinkreiser kevinkreiser Mar 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct we have not yet exposed the protobuf API externally so we are ok to do things like this until we cross that barrier

@@ -22,6 +23,22 @@ template <typename T> inline T square(T v) {
return v * v;
}

bool search_filter(const DirectedEdge* edge, const Location::SearchFilter& search_filter) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual edge filtering happens in this function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A highly subjective idea, take it or leave it :)

The function name I think could be something that reflects that it is a bool and what the outcome is without the user having to check the implementation. Something like is_search_filter_triggered or similar would convey to the reader in other parts of the code what it is doing and returning.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, generally any function that returns bool is clearer to prefix with is_ or has_.

@@ -582,6 +582,11 @@ route(const map& map, const std::string& from, const std::string& to, const std:
return route(map, {from, to}, costing);
}

valhalla::Api route(const map& map, const std::string& request_json) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @danpat I added this for convenience of writing tests with additional parameters in the request. If you have a neater pattern in mind for custom request parameters let me know.

/**
* Optional filters supplied in the request.
*/
struct SearchFilter {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This struct is a mirror of the protobuf message, per @kevinkreiser there's a larger refactor to be done here for Loki to use the proto generated valhalla::Location directly. I didn't tackle that refactor in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a HUGE TODO and CAUTION to the docstring with what your comment just said?

@mandeepsandhu
Copy link
Contributor

Issue

This PR enables excluding edge candidates from Loki's search results with a new per-location parameter search_filter. Unlike heading and preferred_side filters, search_filter removes edges from the set of candidates entirely. The idea is to customize snapping behavior for routing: in some cases you don't want to snap to a highway or tunnel if you know your destination is a building centroid, even if that building is closer to the highway than the nearest navigable road.

Supports filtering on the following parameters:

  • min_road_class (string, default "service_other"): min functional road class allowed, options are from highest to lowest: "motorway","trunk","primary","secondary","tertiary","unclassified","residential","service_other"
  • max_road_class (string, default "motorway"): max functional road class allowed, options are from highest to lowest: "motorway","trunk","primary","secondary","tertiary","unclassified","residential","service_other"
  • exclude_tunnel (boolean, default false) exclude roads with tunnel attribution
  • exclude_bridge (boolean, default false) exclude roads with bridge attribution
  • exclude_ramp (boolean, default false) exclude roads with ramp use (includes links and turn channels)

Tasklist

  • Add tests
  • Add #fixes with the issue number that this PR addresses
  • Generally use squash merge to rebase and clean comments before merging
  • Update the changelog

Requirements / Relations

Link any requirements here. Other pull requests this PR is based on?

Is this filtering applied only when its searching for the destination node? Eg if exclude_bridge is set and the destination is a bridge itself, then does it result in a "no route"?

if (!c_itr->prefiltered) {
all_prefiltered = false;
}
// all_prefiltered = all_prefiltered || !c_itr->prefiltered;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stray comment?

{"BC", {{"highway", "primary"}}},
{"CD", {{"highway", "primary"}}},
{"AD", {{"highway", "primary"}}}};
map = gurka::buildtiles(layout, ways, {}, {}, "test/data/search_filter_heading");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does buildtiles do nothing if invoked again with the same tileset? If not, this pattern may result in several runs of the tile baking process. (Maybe it's lightning quick given the small graph).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'll rebuild tiles on every run, and can be a bit slow (on the order of 5-10 seconds per build). We should try to group test maps together to minimize build times, so I simplified the tests to that end in a73ed02.

auto result_filtered = gurka::route(map, request_filtered);

gurka::assert::osrm::expect_route(result_filtered, {"ABE", "BC", "CD"});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are a joy to read, great work @danpaz & @danpat

Copy link
Contributor

@purew purew left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me overall, only added a comment to move your github comment into the code comment for the struct mirroring protobuf.

@@ -87,6 +105,7 @@ struct candidate_t {
double sq_distance;
PointLL point;
size_t index;
bool prefiltered;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used?

src/loki/search.cc Outdated Show resolved Hide resolved
@danpaz danpaz merged commit ac22924 into master Apr 3, 2020
@danpaz danpaz deleted the search_filters branch April 3, 2020 14:58
yuzheyan added a commit that referenced this pull request Apr 16, 2020
* master:
  Refactor some functions for easier re-use. (#2302)
  typo in bitfield struct directededge (#2301)
  Re-enables changelog validation (#2294)
  ref and directional fixes (#2298)
  Add resample_distance (#2261)
  Fix Some ASAN Bugs (#2296)
  Update codecov ignore directory to third_party (#2297)
  Per location search filters for functional road class and forms of way (#2289)
  Adds traffic::Tile accessor function to GraphTile (#2295)
  Properly set the not_thru_pruning flag on the destination edge (just as (#2291)
  Range updates for datetime and emergency updates.  (#2290)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants