-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Consider availability of rental vehicles in routing #6697
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
base: dev-2.x
Are you sure you want to change the base?
Consider availability of rental vehicles in routing #6697
Conversation
|
Perhaps only use this for car rental as it's probably the only thing you are interested in? Could you join a developer meeting at some point to discuss this again? |
Yes I actually just interested in car rental, so I could do it just for the car rental. |
|
First of all draft. I continue with this pr later. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev-2.x #6697 +/- ##
=============================================
+ Coverage 72.18% 72.24% +0.05%
- Complexity 19840 19933 +93
=============================================
Files 2155 2163 +8
Lines 80051 80284 +233
Branches 8082 8113 +31
=============================================
+ Hits 57786 57998 +212
- Misses 19419 19422 +3
- Partials 2846 2864 +18 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
bbd6ddb to
3af25f0
Compare
3af25f0 to
f1b62aa
Compare
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 access/egress time-shifting support (as discussed in dev meeting) should be added in a follow up PR. Until then the API request parameter should be documented as experimental.
Implementing the Access/Egress opening hours can be done extending the DefaultAccessEgress and implementing: earliestDepartureTime(int requestedDepartureTime), latestArrivalTime(int requestedArrivalTime), numberOfRides()and hasOpeningHours()
Should the rentalDuration be relative to the requestTime or the pick-up-time, I am leaning towards requestTime using pick-up time may lead to very strange results (same problem as checking the time constraints during routing).
...c/main/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferences.java
Outdated
Show resolved
Hide resolved
...c/main/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferences.java
Outdated
Show resolved
Hide resolved
...c/main/java/org/opentripplanner/routing/api/request/preference/VehicleRentalPreferences.java
Outdated
Show resolved
Hide resolved
| this.pickupCost = builder.pickupCost; | ||
| this.dropOffTime = Duration.ofSeconds(Units.duration(builder.dropOffTime)); | ||
| this.dropOffCost = builder.dropOffCost; | ||
| this.rentalDuration = Duration.ofSeconds(Units.duration(builder.rentalDuration)); |
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.
You should validate the duration here by calling DurationUtils#requireNonNegative.
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.
added this validatio to ModePreferencesMapper
| Instant departureTime = s0.getTime().plus(preferences.pickupTime()); | ||
| OffsetDateTime rentalEndTime = OffsetDateTime.ofInstant( | ||
| departureTime, | ||
| ZoneId.systemDefault() | ||
| ).plus(preferences.rentalDuration()); |
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 the rental available period should be relative to the request time, not relative to the pickup-time. For depart after [request.dateTime, +rentalDuration] and for arrive by [-rentalDuration, request.dateTime]. This should be calculated and set in the StreetSearchRequest and checked here.
Unsure about the time-zone, using ZoneId.systemDefault() seams wrong. Also, I think the time calculations should use the internal AStar model time format.
@leonardehrenfried & @optionsome What happens if we traverse the graph in reverse - do we ever do that?
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.
What should we do if the journey can not be completed within the rentalDuration? I guess this should end up in a empty result. So I think there need to be a check that we have not exceeded the rentalDuration limit her as well.
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.
hmm I don't get what's the problem by using the pickup-time.
The pickup time seems to be more more precise to me as it really just considers the rental duration.
But if there is any experience with similar cases, I can change 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.
The problem using the pick-up time is that if you have two paths to walk to the rental A, and B. Then A takes 5 min and B 6 min. Then the rental is dropped for path A but accepted for path B. Then the returned result is not optimal. It is possible that path B i dropped in the "from" vertex state - if so this would be ok. Another problem is how to explain this to the end user. Let say there are 2 cars available from 12:00 to 15:00, you start walking 11:50. It takes 9 minutes to the first and 30 minutes to the second. rentalDuration is 1h. In this case the best option is to walk to the first car and WAIT 1 minute. Can you explain why we are not checking the "available from time"?
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 do not really have the "available from time" right now. The GBFS standard support currently available vehicles and the availableUntil fiel. So we do not have the informatin what is the start time, on which a vehicle is available.
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.
Thank you for the clarification. This was discussed shortly at todays developer meeting, and we decided:
- to use
departure-time + rentalDurationfor depart-after-search. For arrival search the vehicle need to be available at when the search start. An the search should be stopped when the time is less than thearrival-time - rentalDuration. - Any
rentalDurationvalue needs to be cleared before we do access/egress search since time-shifting is not supported. This can be implemented later - if someone needs it. - The following text should be added to the
rentalDurationdoc (domain model JavaDoc and API doc):
The
rentalDurationonly apply to direct search, support for transit search is not implemented.
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 changed the departure by using the start time of the StreetSearchRequest.
I also updated the behavior of arrival requests. I used the start time (arrival time) of the StreetSearchRequest to check, if the vehicle is available at this arrival time.
But I am not sure about "An the search should be stopped when the time is less than the arrival-time - rentalDuration" What exactly do you mean with "time". Maybe we can clarify that in the dev meeting.
I added the describing sentence to the GreaphQL parameter(schema) and as Java doc to the rentalDuration property in StreetRequest and StreetSearchRequest.
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 modelled the startTime and endTime of the rentalduration as RentalPeriod and get build in the StreetSearchRequestMapper.
|
I am unsure what we need to do to make this work with access/egress and regular transit. There are a few things that need investigation:
If this feature is not supported for access/egress then we need to make sure it is disabled in the access/egress search. Either of these two options needs to be implemented in this PR. |
| * An assumed duration of the rental trip, to make sure the vehicle is available during this time | ||
| */ | ||
| public Duration rentalDuration() { |
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.
| * An assumed duration of the rental trip, to make sure the vehicle is available during this time | |
| */ | |
| public Duration rentalDuration() { | |
| * An assumed duration of the rental trip, to make sure the vehicle is available during this time | |
| */ | |
| @Nullable | |
| public Duration rentalDuration() { |
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 added nullable annotation to the rentalDuration property of the streetRequest and streetSearchRequest
| Instant departureTime = s0.getTime().plus(preferences.pickupTime()); | ||
| OffsetDateTime rentalEndTime = OffsetDateTime.ofInstant( | ||
| departureTime, | ||
| ZoneId.systemDefault() | ||
| ).plus(preferences.rentalDuration()); |
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.
Thank you for the clarification. This was discussed shortly at todays developer meeting, and we decided:
- to use
departure-time + rentalDurationfor depart-after-search. For arrival search the vehicle need to be available at when the search start. An the search should be stopped when the time is less than thearrival-time - rentalDuration. - Any
rentalDurationvalue needs to be cleared before we do access/egress search since time-shifting is not supported. This can be implemented later - if someone needs it. - The following text should be added to the
rentalDurationdoc (domain model JavaDoc and API doc):
The
rentalDurationonly apply to direct search, support for transit search is not implemented.
2f5f8e1 to
f217651
Compare
|
Before merging this PR, I would like to squash the commits. There are now quite a few commits for just one feature. |
95b841a to
c0b9a69
Compare
|
@tobsesHub Can you go over the pending review comments. |
| return ToStringBuilder.ofEmbeddedType().addEnum("mode", mode, DEFAULT.mode).toString(); | ||
| return ToStringBuilder.ofEmbeddedType() | ||
| .addEnum("mode", mode, DEFAULT.mode) | ||
| .addObj("rentalDuration", rentalDuration, DEFAULT.rentalDuration) |
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.
| .addObj("rentalDuration", rentalDuration, DEFAULT.rentalDuration) | |
| .addDuration("rentalDuration", rentalDuration, DEFAULT.rentalDuration) |
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.
changed it.
| return mode; | ||
| } | ||
|
|
||
| public Duration rentalDuration() { |
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.
| public Duration rentalDuration() { | |
| @Nullable | |
| public Duration rentalDuration() { |
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.
changed 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.
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.
added nullable to rentalPeriod()
| boolean wheelchair; | ||
| GenericLocation from; | ||
| GenericLocation to; | ||
| Duration rentalDuration; |
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.
| Duration rentalDuration; | |
| @Nullable | |
| Duration rentalDuration; |
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.
changed it
| } | ||
| var streetModes = direct.stream().map(DirectModeMapper::map).toList(); | ||
| journey.withDirect(new StreetRequest(getStreetModeForRouting(streetModes))); | ||
|
|
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.
There is a lot of repetition in the code below, consider:
if(a != null) {
var b = a.b;
if(b != null) {
var c = b.c
if(c != null) {
...
}
}
}
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.
Actually I do not like both, because this solution has lots of nesting instead, but I think it is less error prone, so it should be better. I outsourced it to a static method. I hope makes the code more readable.
| } | ||
| StreetRequest that = (StreetRequest) o; | ||
| return mode == that.mode; | ||
| return (mode == that.mode && Objects.equals(rentalDuration, that.rentalDuration)); |
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.
| return (mode == that.mode && Objects.equals(rentalDuration, that.rentalDuration)); | |
| return (mode == that.mode) && Objects.equals(rentalDuration, that.rentalDuration); |
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.
changed it.
| public StreetRequest(StreetMode mode, Duration rentalDuration) { | ||
| this.mode = mode; | ||
| this.rentalDuration = rentalDuration; | ||
| } |
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 this is good enough, but the next time we add a new parameter to this class, we should make a builder.
| @Nonnull | ||
| private final Instant rentalEndTime; | ||
|
|
||
| public RentalPeriod(RentalPeriodBuilder rentalPeriodBuilder) { |
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.
Consider: pass in rentalStartTime and rentalEndTime here, not the builder.
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.
changed it.
| RentalPeriod rentalPeriod = new RentalPeriodBuilder() | ||
| .setRentalStartTime(rentalStart) | ||
| .setRentalEndTime(rentalEnd) | ||
| .build(); |
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 logic can be moved inside the RentalPeriodBuilder - then it become easy to unit-test. Instead
of the regular builder pattern it is better to create two builder methods:
var builder = RentalPeriod.of(time, rentalDuration);
var rentalPeriod = request.arriveBy()
? builder.buildFromLatestArrivalTime()
: builder.buildFromEarliestDepartureTime();
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.
good advice, thanks, I changed it that way.
I also was thinking, to add the arriveBy to the builder. Than the whole logic would be at one place at the RentalPeriodBuilder. But I was not sure, if it is a good idea.
| if (availableUntil != null && availableUntil.isBefore(rentalEndTime)) { | ||
| return State.empty(); | ||
| } | ||
| } |
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.
Why is there 2 identical code blocks 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.
Good point, there is no good reason. I added a isRentalVehicleAvailableDuringRentalPeriod method, to prevent the duplicate code blocks.
c0b9a69 to
0fec972
Compare
Summary
consider vehicles[].available_until field vehicle_status.json in direct routing
Issue
#6547
This is the implementation for two steps explained in this commend. #6547 (comment)
rentalDuration. rentalDuraton is zero by default. If it is negative or zero, it will not be considered. Therefore it should not change the previous behavior, if the new parameter was not used.Unit tests
Documentation