org.opentripplanner.transit.raptor.rangeraptor.multicriteria.McTransitWorker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
package org.opentripplanner.transit.raptor.rangeraptor.multicriteria;
import org.opentripplanner.transit.raptor.api.transit.CostCalculator;
import org.opentripplanner.transit.raptor.api.transit.RaptorTransfer;
import org.opentripplanner.transit.raptor.api.transit.RaptorTripPattern;
import org.opentripplanner.transit.raptor.api.transit.RaptorTripSchedule;
import org.opentripplanner.transit.raptor.rangeraptor.RoutingStrategy;
import org.opentripplanner.transit.raptor.rangeraptor.SlackProvider;
import org.opentripplanner.transit.raptor.rangeraptor.multicriteria.arrivals.AbstractStopArrival;
import org.opentripplanner.transit.raptor.rangeraptor.transit.TransitCalculator;
import org.opentripplanner.transit.raptor.rangeraptor.transit.TripScheduleSearch;
import org.opentripplanner.transit.raptor.util.paretoset.ParetoSet;
/**
* The purpose of this class is to implement the multi-criteria specific functionality of
* the worker.
*
* @param The TripSchedule type defined by the user of the raptor API.
*/
public final class McTransitWorker implements RoutingStrategy {
private final McRangeRaptorWorkerState state;
private final TransitCalculator calculator;
private final CostCalculator costCalculator;
private final SlackProvider slackProvider;
private final ParetoSet> patternRides = new ParetoSet<>(PatternRide.paretoComparatorRelativeCost());
private RaptorTripPattern pattern;
private TripScheduleSearch tripSearch;
public McTransitWorker(
McRangeRaptorWorkerState state,
SlackProvider slackProvider,
TransitCalculator calculator,
CostCalculator costCalculator
) {
this.state = state;
this.slackProvider = slackProvider;
this.calculator = calculator;
this.costCalculator = costCalculator;
}
@Override
public void prepareForTransitWith(RaptorTripPattern pattern, TripScheduleSearch tripSearch) {
this.pattern = pattern;
this.tripSearch = tripSearch;
this.patternRides.clear();
slackProvider.setCurrentPattern(pattern);
}
@Override
public void routeTransitAtStop(int stopPos) {
final int stopIndex = pattern.stopIndex(stopPos);
// Alight at boardStopPos
if (pattern.alightingPossibleAt(stopPos)) {
for (PatternRide ride : patternRides) {
state.transitToStop(
ride,
stopIndex,
ride.trip.arrival(stopPos),
slackProvider.alightSlack()
);
}
}
// If it is not possible to board the pattern at this stop, then return
if(!pattern.boardingPossibleAt(stopPos)) {
return;
}
// For each arrival at the current stop
for (AbstractStopArrival prevArrival : state.listStopArrivalsPreviousRound(stopIndex)) {
int earliestBoardTime = calculator.plusDuration(
prevArrival.arrivalTime(),
slackProvider.boardSlack()
);
boolean found = tripSearch.search(earliestBoardTime, stopPos);
if (found) {
final T trip = tripSearch.getCandidateTrip();
final int boardTime = trip.departure(stopPos);
// It the previous leg can
if(prevArrival.arrivedByAccessLeg()) {
prevArrival = prevArrival.timeShiftNewArrivalTime(boardTime - slackProvider.boardSlack());
}
// TODO OTP2 - Some access legs can be time-shifted towards the board time and
// - we need to account for this here, not in the calculator as done
// - now. If we don´t do that the alight slack of the first transit
// - is not added to the cost, giving the first transit leg a lower cost
// - than other transit legs.
// - See
final int boardWaitTime = boardTime - prevArrival.arrivalTime();
final int relativeBoardCost = calculateOnTripRelativeCost(
prevArrival,
boardTime,
boardWaitTime,
trip
);
patternRides.add(
new PatternRide<>(
prevArrival,
stopIndex,
stopPos,
boardTime,
boardWaitTime,
relativeBoardCost,
trip,
tripSearch.getCandidateTripIndex()
)
);
}
}
}
/**
* Calculate a cost for riding a trip. It should include the cost from the beginning of the
* journey all the way until a trip is boarded. The cost is used to compare trips boarding
* the same pattern with the same number of transfers. It is ok for the cost to be relative
* to any point in place or time - as long as it can be used to compare to paths that started
* at the origin in the same iteration, having used the same number-of-rounds to board the same
* trip.
*
* @param prevArrival The stop-arrival where the trip was boarded.
* @param boardTime the wait-time at the board stop before boarding.
* @param boardWaitTime the wait-time at the board stop before boarding.
* @param trip boarded trip
*/
private int calculateOnTripRelativeCost(
AbstractStopArrival prevArrival,
int boardTime,
int boardWaitTime,
T trip
) {
return costCalculator.onTripRidingCost(
prevArrival,
boardWaitTime,
boardTime,
trip
);
}
@Override
public void setInitialTimeForIteration(RaptorTransfer it, int iterationDepartureTime) {
// Earliest possible departure time from the origin, or latest possible arrival time at the
// destination if searching backwards, using this AccessEgress.
int departureTime = calculator.departureTime(it, iterationDepartureTime);
// This access is not available after the iteration departure time
if (departureTime == -1) { return; }
state.setInitialTimeForIteration(it, departureTime);
}
}