Skip to content

Commit

Permalink
Merge pull request #2932 from entur/otp2_support_for_automatic_search…
Browse files Browse the repository at this point in the history
…_window

SW_1 - Implement dynamic computation of EDT, LAT and SearchWindow.
  • Loading branch information
t2gran committed Feb 5, 2020
2 parents 718d6ca + 8c829c6 commit 1c28caf
Show file tree
Hide file tree
Showing 38 changed files with 1,382 additions and 311 deletions.
1 change: 1 addition & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- Ability to switch off the fare service(#2912).
- Limit the transit service period(#2925).
- Removed unwanted cost added for wait time between access and transit with RangeRaptor (#2927)
- Dynamic search parameters, calculate raptor search-window when needed. (#2931)

## Ported over from the 1.x
- Add application/x-protobuf to accepted protobuf content-types (#2839)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ private RoutingRequest createRequest(DataFetchingEnvironment environment) {
// callWith.argument("preTransitReluctance", (Double v) -> request.setPreTransitReluctance(v));
// callWith.argument("maxPreTransitWalkDistance", (Double v) -> request.setMaxPreTransitWalkDistance(v));
callWith.argument("walkBoardCost", request::setWalkBoardCost);
callWith.argument("walkReluctance", (Double v) -> request.setWalkReluctance(v));
callWith.argument("waitReluctance", (Double v) -> request.setWaitReluctance(v));
callWith.argument("walkReluctance", request::setWalkReluctance);
callWith.argument("waitReluctance", request::setWaitReluctance);
callWith.argument("walkBoardCost", request::setWalkBoardCost);
// callWith.argument("walkOnStreetReluctance", request::setWalkOnStreetReluctance);
callWith.argument("waitReluctance", request::setWaitReluctance);
Expand Down Expand Up @@ -230,23 +230,23 @@ private RoutingRequest createRequest(DataFetchingEnvironment environment) {
// callWith.argument("preferred.lines", lines -> request.setPreferredRoutes(mappingUtil.prepareListOfFeedScopedId((List<String>) lines, "__")));
callWith.argument("preferred.otherThanPreferredLinesPenalty", request::setOtherThanPreferredRoutesPenalty);
// Deprecated organisations -> authorities
callWith.argument("preferred.organisations", organisations -> request.setPreferredAgencies(mappingUtil.mapCollectionOfValues((Collection<String>) organisations, in -> in)));
callWith.argument("preferred.authorities", authorities -> request.setPreferredAgencies(mappingUtil.mapCollectionOfValues((Collection<String>) authorities, in -> in)));
callWith.argument("preferred.organisations", (Collection<String> organisations) -> request.setPreferredAgencies(mappingUtil.mapCollectionOfValues(organisations, in -> in)));
callWith.argument("preferred.authorities", (Collection<String> authorities) -> request.setPreferredAgencies(mappingUtil.mapCollectionOfValues(authorities, in -> in)));
// callWith.argument("unpreferred.lines", lines -> request.setUnpreferredRoutes(mappingUtil.prepareListOfFeedScopedId((List<String>) lines, "__")));
callWith.argument("unpreferred.organisations", organisations -> request.setUnpreferredAgencies(mappingUtil.mapCollectionOfValues((Collection<String>) organisations, in -> in)));
callWith.argument("unpreferred.authorities", authorities -> request.setUnpreferredAgencies(mappingUtil.mapCollectionOfValues((Collection<String>) authorities, in -> in)));
callWith.argument("unpreferred.organisations", (Collection<String> organisations) -> request.setUnpreferredAgencies(mappingUtil.mapCollectionOfValues(organisations, in -> in)));
callWith.argument("unpreferred.authorities", (Collection<String> authorities) -> request.setUnpreferredAgencies(mappingUtil.mapCollectionOfValues(authorities, in -> in)));

// callWith.argument("banned.lines", lines -> request.setBannedRoutes(mappingUtil.prepareListOfFeedScopedId((List<String>) lines, "__")));
callWith.argument("banned.organisations", organisations -> request.setBannedAgencies(mappingUtil.mapCollectionOfValues((Collection<String>) organisations, in -> in)));
callWith.argument("banned.authorities", authorities -> request.setBannedAgencies(mappingUtil.mapCollectionOfValues((Collection<String>) authorities, in -> in)));
callWith.argument("banned.serviceJourneys", serviceJourneys -> request.bannedTrips = toBannedTrips((Collection<String>) serviceJourneys));
callWith.argument("banned.organisations", (Collection<String> organisations) -> request.setBannedAgencies(mappingUtil.mapCollectionOfValues(organisations, in -> in)));
callWith.argument("banned.authorities", (Collection<String> authorities) -> request.setBannedAgencies(mappingUtil.mapCollectionOfValues(authorities, in -> in)));
callWith.argument("banned.serviceJourneys", (Collection<String> serviceJourneys) -> request.bannedTrips = toBannedTrips(serviceJourneys));

// callWith.argument("banned.quays", quays -> request.setBannedStops(mappingUtil.prepareListOfFeedScopedId((List<String>) quays)));
// callWith.argument("banned.quaysHard", quaysHard -> request.setBannedStopsHard(mappingUtil.prepareListOfFeedScopedId((List<String>) quaysHard)));

callWith.argument("whiteListed.lines", lines -> request.setWhiteListedRoutes(mappingUtil.prepareListOfFeedScopedId((List<String>) lines, "__")));
callWith.argument("whiteListed.organisations", organisations -> request.setWhiteListedAgencies(mappingUtil.mapCollectionOfValues((Collection<String>) organisations, in -> in)));
callWith.argument("whiteListed.authorities", authorities -> request.setWhiteListedAgencies(mappingUtil.mapCollectionOfValues((Collection<String>) authorities, in -> in)));
callWith.argument("whiteListed.lines", (List<String> lines) -> request.setWhiteListedRoutes(mappingUtil.prepareListOfFeedScopedId((List<String>) lines, "__")));
callWith.argument("whiteListed.organisations", (Collection<String> organisations) -> request.setWhiteListedAgencies(mappingUtil.mapCollectionOfValues(organisations, in -> in)));
callWith.argument("whiteListed.authorities", (Collection<String> authorities) -> request.setWhiteListedAgencies(mappingUtil.mapCollectionOfValues(authorities, in -> in)));

//callWith.argument("heuristicStepsPerMainStep", (Integer v) -> request.heuristicStepsPerMainStep = v);
// callWith.argument("compactLegsByReversedSearch", (Boolean v) -> { /* not used any more */ });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
import org.opentripplanner.routing.services.FareService;
import org.opentripplanner.transit.raptor.RaptorService;
import org.opentripplanner.transit.raptor.api.path.Path;
import org.opentripplanner.transit.raptor.api.request.Optimization;
import org.opentripplanner.transit.raptor.api.request.RaptorProfile;
import org.opentripplanner.transit.raptor.api.request.RaptorRequest;
import org.opentripplanner.transit.raptor.api.request.RaptorRequestBuilder;
import org.opentripplanner.transit.raptor.api.request.RaptorTuningParameters;
import org.opentripplanner.transit.raptor.api.response.RaptorResponse;
import org.opentripplanner.transit.raptor.api.transit.TransferLeg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -40,7 +42,7 @@ public class RaptorRouter {
private static final RaptorService<TripSchedule> raptorService = new RaptorService<>(
// TODO OTP2 - Load turning parameters from config file
new RaptorTuningParameters() {}
);
);

private final RaptorRoutingRequestTransitData requestTransitDataProvider;
private final TransitLayer transitLayer;
Expand All @@ -50,8 +52,8 @@ public class RaptorRouter {
public RaptorRouter(RoutingRequest request, TransitLayer transitLayer) {
double startTime = System.currentTimeMillis();

this.requestTransitDataProvider = new RaptorRoutingRequestTransitData(
transitLayer,
this.requestTransitDataProvider = new RaptorRoutingRequestTransitData(
transitLayer,
request.getDateTime().toInstant(),
TRANSIT_SEARCH_RANGE_IN_DAYS,
request.modes,
Expand Down Expand Up @@ -93,34 +95,41 @@ public Collection<Itinerary> route() {

double startTimeRouting = System.currentTimeMillis();

int departureTime = DateMapper.secondsSinceStartOfTime(
RaptorRequestBuilder<TripSchedule> builder = new RaptorRequestBuilder<>();

int time = DateMapper.secondsSinceStartOfTime(
requestTransitDataProvider.getStartOfTime(),
request.getDateTime().toInstant()
);

if(request.arriveBy) {
builder.searchParams().latestArrivalTime(time);
}
else {
builder.searchParams().earliestDepartureTime(time);
}

// TODO Expose parameters
// TODO Remove parameters from API
RaptorRequest<TripSchedule> raptorRequest = new RaptorRequestBuilder<TripSchedule>()
.profile(RaptorProfile.STANDARD)
//TODO Check in combination with timetableEnabled
//.enableOptimization(Optimization.PARETO_CHECK_AGAINST_DESTINATION)
builder.profile(RaptorProfile.MULTI_CRITERIA)
.enableOptimization(Optimization.PARETO_CHECK_AGAINST_DESTINATION)
.searchParams()
.earliestDepartureTime(departureTime)
.searchWindowInSeconds(request.raptorSearchWindow)
.searchWindow(request.searchWindow)
.addAccessStops(accessTimes)
.addEgressStops(egressTimes)
.boardSlackInSeconds(request.boardSlack)
.timetableEnabled(true)
.build();
.allowWaitingBetweenAccessAndTransit(false)
.timetableEnabled(true);

/* Route transit */
RaptorRequest<TripSchedule> raptorRequest = builder.build();

Collection<Path<TripSchedule>> paths = raptorService.route(
// Route transit
RaptorResponse<TripSchedule> response = raptorService.route(
raptorRequest,
this.requestTransitDataProvider
);

LOG.info("Found {} itineraries", paths.size());
LOG.info("Found {} itineraries", response.paths().size());

LOG.info("Main routing took {} ms", System.currentTimeMillis() - startTimeRouting);

Expand All @@ -138,7 +147,7 @@ public Collection<Itinerary> route() {
FareService fareService = request.getRoutingContext().graph.getService(FareService.class);

List<Itinerary> itineraries = new ArrayList<>();
for (Path<TripSchedule> path : paths) {
for (Path<TripSchedule> path : response.paths()) {
// Convert the Raptor/Astar paths to OTP API Itineraries
Itinerary itinerary = itineraryMapper.createItinerary(path);
// Decorate the Itineraries with fare information.
Expand Down
44 changes: 26 additions & 18 deletions src/main/java/org/opentripplanner/routing/core/RoutingRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
Expand All @@ -37,11 +38,13 @@
import java.util.TimeZone;

/**
* A trip planning request. Some parameters may not be honored by the trip planner for some or all itineraries.
* For example, maxWalkDistance may be relaxed if the alternative is to not provide a route.
* A trip planning request. Some parameters may not be honored by the trip planner for some or all
* itineraries. For example, maxWalkDistance may be relaxed if the alternative is to not provide a
* route.
*
* All defaults should be specified here in the RoutingRequest, NOT as annotations on query parameters in web services
* that create RoutingRequests. This establishes a priority chain for default values:
* All defaults should be specified here in the RoutingRequest, NOT as annotations on query
* parameters in web services that create RoutingRequests. This establishes a priority chain for
* default values:
* RoutingRequest field initializers, then JSON router config, then query parameters.
*
* @Deprecated tag is added to all parameters that are not currently functional in either the Raptor router or other
Expand Down Expand Up @@ -189,13 +192,28 @@ public class RoutingRequest implements Cloneable, Serializable {
/** The epoch date/time that the trip should depart (or arrive, for requests where arriveBy is true) */
public long dateTime = new Date().getTime() / 1000;

/**
* This is the time/duration in seconds from the earliest-departure-time(EDT) to
* latest-departure-time(LDT). In case of a reverse search it will be the time from earliest
* to latest arrival time (LAT - EAT).
* <p>
* All optimal travels that depart within the search window is guarantied to be found.
* <p>
* This is sometimes referred to as the Range Raptor Search Window - but could be used in a none
* Transit search as well; Hence this is named search-window and not raptor-search-window. Do
* not confuse this with the travel-window, which is the time between EDT to LAT.
* <p>
* Use {@code null} to unset, and {@link Duration#ZERO} to do one Raptor iteration. The value is
* dynamically assigned a suitable value, if not set. In a small to medium size operation
* you may use a fixed value, like 60 minutes. If you have a mixture of high frequency cities
* routes and infrequent long distant journeys, the best option is normally to use the dynamic
* auto assignment.
*/
public Duration searchWindow;

/**
* Whether the trip should depart at dateTime (false, the default), or arrive at dateTime.
*
* @deprecated TODO OTP2 Regression. Needs to be implemented in Raptor.
* @see https://github.com/opentripplanner/OpenTripPlanner/issues/2885
*/
@Deprecated
public boolean arriveBy = false;

/**
Expand Down Expand Up @@ -488,15 +506,6 @@ public class RoutingRequest implements Cloneable, Serializable {
@Deprecated
public int maxTransfers = 2;

/**
* Raptor search window in seconds.
*
* TODO OTP2 This needs to be exposed on the API, maybe not as is. There are
* a few possibilities. Other alternatives are:
* {@code earliest/latest departure/arrival time}
*/
public int raptorSearchWindow = 40 * 60;

/**
* For the bike triangle, how important time is.
* triangleTimeFactor+triangleSlopeFactor+triangleSafetyFactor == 1
Expand Down Expand Up @@ -1340,5 +1349,4 @@ public Comparator<GraphPath> getPathComparator(boolean compareStartTimes) {
}
return new PathComparator(compareStartTimes);
}

}

0 comments on commit 1c28caf

Please sign in to comment.