-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Changed calculation of slope costs (#2579) #2580
Conversation
} | ||
/* | ||
* Here we divide by the *flat length* as the slope/work cost factors are multipliers of the | ||
* length of the street edge which is the flat one. | ||
*/ | ||
return new SlopeCosts(slopeSpeedEffectiveLength / flatLength, slopeWorkCost / flatLength, | ||
slopeSafetyCost, maxSlope, lengthMultiplier, flattened); | ||
slopeSafetyCost, maxSlope, lengthMultiplier, flattened, slopeWalkEffectiveLength * walkParA / flatLength); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is wrong. The slopeWalkEffectiveLength
should be used as is. There is no speed component in this any more. The * walkParA / flatLeng
can be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When this is ready (@t2gran approves it) I'll provide another review to allow merging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strictly I have participated in the development of this, so maybe someone else should review this in addition too @abyrd. @optionsome has done some testing on this in Finland, so maybe we can send an invitation to @tuukka and he can suggest some people that can be added to the list of reviewers. I believe adding people must be approved by the PLC.
…ctor `alkParA` from the calculation. - Cleanup names and comments. - Fix tests.
@optionsome I see that you were commenting on issue #2579 and have already done some testing of this new walk slope system. Can you provide a review of this pull request? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We observed issues with edge splitting in our fork. We fixed those and thought that they were not related to this pull request (which we have already merged into our fork). However, now that I started to review this again, I tested upstream's master with and without these changes and seems like these changes are causing the issue. The issue is that the walk time for first/last edge is not correct. The first picture is with these changes.
The second picture is without these changes.
We have already created a fix for this issue and it seems to work. It can be found here. The last commit there is not related to this issue.
Thank you @optionsome for taking the time to test this, and providing a fix. I was a puzzled by this, but the error is that the elevation data does not propagate into the TemporaryEdges when split. There is at least 3 ways to solve this.
I have reproduced the problem and tested that it works. |
The solution in the fix (option 2) has indeed this drawback but I don't think that it is that significant in majority of cases. in most cases edges are rather short and I don't think that it is that problematic, long edges in steep terrain would of course produce larger error. Option 3 is should be viable, although it has same shortcomings as option 2. |
@pailakka We do actually have the elevation data when routing. It is contained in StreetWithElevationEdge.packedElevationprofile. I think it could be a good idea to go with option 1, as I don't think it will cost much in terms of performance. |
I stand corrected, elevation data is indeed available when routing. Calculation needs to be done only twice with every RoutingRequest so it shouldn't be too bad performance wise. |
…it. This apply to biking and walking.
I have now fixed the elevation calculation for temporary edges. The fix calculate a new elevation profile for the partial section of the original edge. (Solution 1 above). This fix apply to both biking and walking. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't find problems while testing these changes but couple of comments should be slightly updated.
// make the edges | ||
// TODO this is using the StreetEdge implementation of split, which will discard elevation information | ||
// on edges that have it | ||
// make the edges on edges that have it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment already existed here earlier but I find it slightly hard to understand. Maybe it could be worded a bit better.
@@ -31,8 +32,13 @@ public PartialStreetEdge(StreetEdge parentEdge, StreetVertex v1, StreetVertex v2 | |||
super(v1, v2, geometry, name, length, parentEdge.getPermission(), false); | |||
setCarSpeed(parentEdge.getCarSpeed()); | |||
this.parentEdge = parentEdge; | |||
|
|||
// Initialize length_mm from Geometry | |||
if(getLength_mm() == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it could be a good idea to explain here in a comment why the length is sometimes 0 and why it needs to be calculated here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, also this is the only place length_mm
is used outside its StreetEdge
, I will move the logic to StreetEdge
to iImprove encapsulation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored this so we that there is one constructor in the TemporaryPartialStreetEdge with length and one without, and JavaDoc that explain the difference.
…n edge. - Push assigning 'wheelchairAccessible' into the 'TemporarySplitterVertex' constructor. - Create constructor for temporary street edge without a pre-calculated length, calculate length from the geometry in this case. - Update some comments
…ialStreetEdge, witch were the only place it was used except for tests. - Simplified the constructors a bit.
@optionsome I decided to refactor instead of explaining the implementation (fixing the documentation requested changes). Hopefully this become more clear. I have added som comments as well. @abyrd I removed the PartialStreetEdge - it was just simpler to refactor it into the TemporaryPartialStreetEdge(TPSE), then to describe the problem in a new issue. The TemporaryPartialStreetEdge had very specific constructors (5 of them); witch limited the type of edges we could link with a TemporaryEdge; I think it is the callers responsibility to enforce such thing, not the TPSE. If the types were used inside the TPSE; then it would be something else. If the intention was to ensure that at least one of the start/end Vertices is a Temporary vertex; then do it explicit in like an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, thanks @t2gran for the fixes to edge splitting. Only one request for changes, which is a spelling issue: I believe ToblersHickingFunction.java
should be "hiking" rather than "hicking". This spelling appears in about 13 places throughout the PR. With that simple spelling correction, I will approve it. So then just waiting for approval from @optionsome.
@t2gran about the many constructors with specific type parameters: this is from a time when we were trying to use language features to enforce graph structure. It was useful to know with certainty that types of edges were always assembled in the same way. It is indeed more concise and readable to do this with an assertion - I think the six constructors here are the result of someone seeing a pattern and taking it a step too far. In the ideal case, we'd enforce lots of things with language features at compile time and avoid instanceof
which is best avoided... but the reality is that OTP is still full of instanceof
so there's no reason not to use it here.
@abyrd I think restricting the types is a good thing, but only down to what is important/used - in this case is temporary or not - allowing new types to be created. The |
@abyrd this branch could be merged into dev-1.x soon after travis is done building. However, I just read from "Branches and Branch Protection" instructions that merges should be done with fast-forward. I think github merge uses --no-ff by default but has that been changed for this repository? |
@optionsome I think you are referring to a section of the OTP documentation at https://opentripplanner.readthedocs.io/en/latest/Developers-Guide/#contributing-to-the-project - there it does say "All other changes to master should result from fast-forward merges of a Github pull request from the dev-1.x branch". I was using the expression "fast forward" to mean that a merge is not necessary, that As you point out there is a distinction between a branch that can be fast-forwarded, and actually doing a fast-forward instead of a merge. We did not remove the I just need to reword the documentation to clarify the difference between "can be fast-forwarded" and "true fast-forward merge". |
This is an implementation we have had in production at Entur for about 6 months now. It is quite safe to use, as it caps the effective length factor for slopes between 1 and 3. We should probably come up with a more complete formula that accounts for steeper slopes and possible speed increases for downhill slopes. This will require more analysis, however, as some small street edges can be really steep and that does not play well with an exponential function.