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

Move ProfileResolver out of GraphHopper class #1958

Merged
merged 38 commits into from Mar 23, 2020
Merged

Conversation

easbar
Copy link
Member

@easbar easbar commented Mar 17, 2020

In this PR I moved the ProfileResolver out of GraphHopper and into the Route/Isochrone/SPTResource. This means:

  • GraphHopper#route only considers the profile parameter (instead of vehicle,weighting,edge_based). At the moment it even throws an error if these parameters are set. Is that ok or should we go for a 'softer' migration and change this to an error log only? A missing profile parameter is definitely an error, I just wonder if its too strict to throw an error in case there is also vehicle/weighting (which are not used anyway).

  • To make use of the profile parameter we now have to add routing profiles also for non-prepared (no CH or LM) algorithms. GH configs without profiles lead to an error with this PR!

  • ProfileResolver does the conversion of the vehicle/weighting/edge_based parameters and the profile name is passed to GraphHopper. Therefore the actual behavior of the GH server should not be changed (unless there is a bug).

Another change that is done here is that we no longer use the first flag encoder as default vehicle. We already did this for CH before, but now its the same for CH/LM/flex. If the vehicle parameter is not set (and ch.disable=true) we are trying to find a matching profile based on the other parameters. If there are multiple matches there will now be an error (previously we would have used the first encoder as default vehicle).

I think it might be useful to merge these changes before in #1859 we:

  1. Actually expose the new profile parameter via the web api. We probably also want to adjust the integration tests then and only keep a few that test the parameter conversion (profile selection). The good thing with this PR is that we can check if the conversion works before changing the tests etc.

  2. Implement the merging rules between profile parameters and hints (e.g. take distance factor for short_fastest weighting from profile, but overwrite if given in request hints and not CH etc.)

Current todos for this PR:

  • adjust config-example.yml
  • add integration tests for edge_based/turn_costs parameter (and the corresponding conversion)/what about turn_cost=true/false cross querying for LM?
  • merge profile and request hints

@easbar easbar added this to the 1.0 milestone Mar 17, 2020
@@ -34,6 +34,9 @@
*/
public class GHRequest {
private List<GHPoint> points;
// todonow: keep this here or put it into hints, and even more important: can we remove vehicle+weighting from
// hints?
private String profile = "";
Copy link
Member Author

Choose a reason for hiding this comment

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

I think we discussed this in #1859 already: We'll def. remove vehicle+weighting from the HintsMap, but maybe in a follow-up PR? Since the profile parameter will be required it makes sense to keep it as a separate field?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I would also use it here and remove weighting and vehicle in a later PR

@@ -824,6 +809,9 @@ public boolean load(String graphHopperFolder) {
}

private void checkProfilesConsistency() {
if (profilesByName.isEmpty()) {
Copy link
Member Author

Choose a reason for hiding this comment

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

There are a few odd cases where we do not use GraphHopper for routing (like NearestResource) so these do not necessarily require profiles. Not sure, to me this seems rather the exception so I am checking the existence of at least one profile here. Once we do #1901 we can move this check into GraphHopperRouter's constructor for example.

// todonow: maybe still allow something like running a (non CH) profile edge-based or not (if no turn costs or something)?, also see traversal mode below
if (!request.getHints().get(Routing.EDGE_BASED, "").isEmpty())
throw new IllegalArgumentException("GHRequest may no longer contain the edge_based=true/false parameter, use the profile parameter instead, see #todonow");
// todonow: do not allow things like short_fastest.distance_factor or u_turn_costs unless CH is disabled and only under certain conditions for LM
Copy link
Member Author

Choose a reason for hiding this comment

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

This is about the 'merging' feature where some properties are set right in the profile (like distance_factor), but they might be overwritten per request. The problem is that this does not work with CH (and only some special cases work for LM), so I am a bit unsure where to put these checks. They cannot really go into createWeighting (where the merging will happen?!), because in this method we do not 'know' whether the weighting is created for CH or not...

Copy link
Member Author

Choose a reason for hiding this comment

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

for now we are just blindly merging the hints, later we will add these kind of checks here to be more strict

if (!profile.isTurnCosts() && !request.getCurbsides().isEmpty())
throw new IllegalArgumentException("To make use of the " + CURBSIDE + " parameter you need to use a profile that supports turn costs");

// todonow: should we be able to control this using the edge_based parameter?
Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe we can do this later, see #1702.

Boolean edgeBased = getEdgeBased(hintsMap);
Integer uTurnCosts = getUTurnCosts(hintsMap);
return (edgeBased == null || p.isTurnCosts() == edgeBased) &&
(uTurnCosts == null || uTurnCosts.equals(getUTurnCosts(p.getHints()))) &&
Copy link
Member Author

Choose a reason for hiding this comment

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

Since we are now selecting a CHProfileConfig instead of a CHProfile we can deal with the case of multiple edge-based profiles with different u_turn_costs again (c.f. #1949). This should also help to get rid of Weighting#getFlagEncoder in the long run.

@@ -71,6 +71,7 @@ empty list for `profiles_ch`.
Parameter | Default | Description
:----------------|:-----------|:-----------
ch.disable | `false` | Use this parameter in combination with one or more parameters of this table
# todonow: update docs regarding profile etc.
Copy link
Member Author

Choose a reason for hiding this comment

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

This file is supposed to describe the web-api, but this documentation also is available on the directions-api documentation website. Does it make sense to keep this updated here? Or should this be rather about the documentation of the parameters of the open source server?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, definitely this is different. This doc should should show all the features, e.g. including public transit and mvt endpoint etc that we do not have in the GraphHopper Directions API.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok so this file is actually the documentation of the open source server then? I will try to make this a bit more clear and for the hosted service point to the online docs then?

Copy link
Member

@karussell karussell Mar 18, 2020

Choose a reason for hiding this comment

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

I wanted to avoid doing "advertisements" here, but probably you are right and this would be more clear.

@@ -73,6 +75,7 @@
private final Map<String, Object> properties = new TreeMap<>();
private long seed;
private int maxNode;
private String vehicle;
Copy link
Member Author

Choose a reason for hiding this comment

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

Here I thought the measurements are running only for one vehicle anyway (and if we want to test others we might as well start the measurement again for the other vehicle), so it makes sense to keep the vehicle as a class variable (just like weighting) rather than pass it with every querysetting?

Copy link
Member

Choose a reason for hiding this comment

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

In the CustomWeighting branch I already use profile and then I do not want the vehicle in the request: https://github.com/graphhopper/graphhopper/pull/1841/files#diff-cd749cc545f8b84137c2b75b2d174b72 but probably this can be still done somehow.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok yes vehicle and weihgting should be mostly removed from measurement and only profile should be left then?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, but let's do this later :)

Copy link
Member Author

Choose a reason for hiding this comment

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

There isn't really anything to do. vehicle&weighting are only used to create the profile initially.

# Conflicts:
#	core/src/main/java/com/graphhopper/routing/ProfileResolver.java
#	core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java
#	reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java
#	reader-osm/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java
#	tools/src/main/java/com/graphhopper/tools/CHMeasurement.java
#	tools/src/main/java/com/graphhopper/tools/Measurement.java
#	web-bundle/src/main/java/com/graphhopper/resources/IsochroneResource.java
#	web-bundle/src/main/java/com/graphhopper/resources/SPTResource.java
@easbar easbar mentioned this pull request Mar 19, 2020
# Conflicts:
#	core/src/main/java/com/graphhopper/routing/ProfileResolver.java
#	reader-gtfs/src/test/java/com/graphhopper/AnotherAgencyIT.java
#	reader-gtfs/src/test/java/com/graphhopper/ExtendedRouteTypeIT.java
#	reader-gtfs/src/test/java/com/graphhopper/GraphHopperGtfsIT.java
#	reader-gtfs/src/test/java/com/graphhopper/GraphHopperMultimodalIT.java
#	reader-gtfs/src/test/java/com/graphhopper/RealtimeIT.java
#	reader-osm/src/test/java/com/graphhopper/GraphHopperIT.java
#	reader-osm/src/test/java/com/graphhopper/reader/osm/GraphHopperOSMTest.java
#	web/src/test/java/com/graphhopper/http/SpatialRulesTest.java
#	web/src/test/java/com/graphhopper/http/resources/ChangeGraphResourceTest.java
#	web/src/test/java/com/graphhopper/http/resources/GtfsTest.java
#	web/src/test/java/com/graphhopper/http/resources/I18nResourceTest.java
#	web/src/test/java/com/graphhopper/http/resources/IsochroneResourceTest.java
#	web/src/test/java/com/graphhopper/http/resources/MvtResourceTest.java
#	web/src/test/java/com/graphhopper/http/resources/NearestResourceTest.java
#	web/src/test/java/com/graphhopper/http/resources/NearestResourceWithEleTest.java
#	web/src/test/java/com/graphhopper/http/resources/PtIsochroneTest.java
#	web/src/test/java/com/graphhopper/http/resources/RouteResourceWithEleTest.java
#	web/src/test/java/com/graphhopper/http/resources/SPTResourceTest.java
Comment on lines 1353 to 1358
// Merge profile hints with request hints, the request hints take precedence.
// Note that so far we do not check if overwriting the profile hints actually works with the preparation
// for LM/CH. Later we should also limit the number of parameters that can be used to modify the profile.
PMap hints = new PMap();
hints.putAll(profile.getHints());
hints.putAll(requestHints);
Copy link
Member Author

@easbar easbar Mar 20, 2020

Choose a reason for hiding this comment

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

These are (the very simple) rules how we merge the profile hints with the request hints. The only thing I am wondering now is how we do this for block_area? Shall we do this in a similar way (use hints from profile and overwrite with request hints)? Do we need this here or is it ok to only create block areas from request hints (not the profile) here, and add this in #1776? Its still a bit unfortunate that we do not do the block_area stuff inside createWeighting. Now it looks all we are missing to do this in createWeighting are the points?

Copy link
Member

Choose a reason for hiding this comment

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

The only thing I am wondering now is how we do this for block_area?

Hmmh, we would need to add it to the list of shapes

Do we need this here or is it ok to only create block areas from request hints (not the profile) here

I would postpone this and properly support this in CustomWeighting.

Now it looks all we are missing to do this in createWeighting are the points

Yeah, although we only need this because of the is-in-area check which we could keep out of the Weighting creation somehow.

# Conflicts:
#	core/src/main/java/com/graphhopper/routing/ProfileResolver.java
#	tools/src/main/java/com/graphhopper/tools/Measurement.java
# Conflicts:
#	core/src/main/java/com/graphhopper/routing/ProfileResolver.java
#	web/src/test/java/com/graphhopper/http/resources/RouteResourceProfileSelectionTest.java
@easbar easbar merged commit 6daf068 into master Mar 23, 2020
@easbar easbar deleted the profile_parameter2 branch March 23, 2020 20:45
@easbar easbar mentioned this pull request Mar 26, 2020
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants