Skip to content

Commit

Permalink
Merge pull request opentripplanner#3386 from realCity/feature/time-de…
Browse files Browse the repository at this point in the history
…pendant-access-egress

RAPTOR: add tests for time restricted access
  • Loading branch information
t2gran authored Apr 22, 2021
2 parents 8adb559 + 9356f7f commit 4e17541
Show file tree
Hide file tree
Showing 7 changed files with 414 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ public final class RangeRaptorWorker<T extends RaptorTripSchedule> implements Wo

private boolean inFirstIteration = true;

private boolean hasTimeDependentAccess = false;

private int iterationDepartureTime;


Expand Down Expand Up @@ -232,7 +234,7 @@ private void transfersForRound() {
* This is protected to allow reverse search to override and create a alight search instead.
*/
private TripScheduleSearch<T> createTripSearch(RaptorTimeTable<T> timeTable) {
if(!inFirstIteration && roundTracker.isFirstRound()) {
if (!inFirstIteration && roundTracker.isFirstRound() && !hasTimeDependentAccess) {
// For the first round of every iteration(except the first) we restrict the first
// departure to happen within the time-window of the iteration. Another way to put this,
// is to say that we allow for the access path to be time-shifted to a later departure,
Expand Down Expand Up @@ -264,6 +266,13 @@ private void addAccessPaths(Collection<RaptorTransfer> accessPaths) {
// This access is not available after the iteration departure time
if (timeDependentDepartureTime == -1) { continue; }

// If the time differs from the iterationDepartureTime, than the access has time
// restrictions. If the difference between _any_ access between iterations is not a
// uniform iterationStep, than the exactTripSearch optimisation may not be used.
if (timeDependentDepartureTime != iterationDepartureTime) {
hasTimeDependentAccess = true;
}

transitWorker.setAccessToStop(it, iterationDepartureTime, timeDependentDepartureTime);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.opentripplanner.transit.raptor.rangeraptor.multicriteria;

import static org.opentripplanner.transit.raptor.rangeraptor.multicriteria.PatternRide.paretoComparatorRelativeCost;

import org.opentripplanner.transit.raptor.api.transit.CostCalculator;
import org.opentripplanner.transit.raptor.api.transit.RaptorTransfer;
import org.opentripplanner.transit.raptor.api.transit.RaptorTripPattern;
Expand All @@ -12,8 +14,6 @@
import org.opentripplanner.transit.raptor.rangeraptor.transit.TripScheduleSearch;
import org.opentripplanner.transit.raptor.util.paretoset.ParetoSet;

import static org.opentripplanner.transit.raptor.rangeraptor.multicriteria.PatternRide.paretoComparatorRelativeCost;


/**
* The purpose of this class is to implement the multi-criteria specific functionality of
Expand Down Expand Up @@ -101,15 +101,11 @@ public void routeTransitAtStop(int stopPos) {
final T trip = tripSearch.getCandidateTrip();
final int boardTime = trip.departure(stopPos);

if(prevArrival.arrivedByAccess()) {
if (prevArrival.arrivedByAccess()) {
prevArrival = prevArrival.timeShiftNewArrivalTime(boardTime - slackProvider.boardSlack());
}


final int boardWaitTimeForCostCalculation = timeShiftingAllowed(prevArrival)
? slackProvider.boardSlack()
: boardTime - prevArrival.arrivalTime();

final int boardWaitTimeForCostCalculation = boardTime - prevArrival.arrivalTime();
final int relativeBoardCost = calculateOnTripRelativeCost(
prevArrival,
boardTime,
Expand Down Expand Up @@ -151,14 +147,4 @@ private int calculateOnTripRelativeCost(
) {
return costCalculator.onTripRidingCost(prevArrival, boardWaitTime, boardTime);
}

/**
* Some access paths can be time-shifted towards the board time. This has to be taken into
* account when calculating the the correct wait-time. This can not be done in the calculator
* as done earlier. If we don´t do that the alight slack of the first transit is not added to
* the cost, giving the first transit path a lower cost than other transit paths.
*/
private static boolean timeShiftingAllowed(AbstractStopArrival<?> arrival) {
return arrival.arrivedByAccess() && !arrival.accessPath().access().hasRides();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ private AccessPathLeg<T> createAccessPathLeg(ArrivalView<T> from, PathLeg<T> nex

if(access.hasRides()) {
targetToTime -= slackProvider.transferSlack();
targetToTime = access.latestArrivalTime(targetToTime);
}

targetToTime = access.latestArrivalTime(targetToTime);

int targetFromTime = targetToTime - access.durationInSeconds();

return new AccessPathLeg<>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@ private EgressPathLeg<T> mapToEgressLeg(ArrivalView<T> accessArrival) {

if(egress.hasRides()) {
targetFromTime += slackProvider.transferSlack();
targetFromTime = egress.earliestDepartureTime(targetFromTime);
}

targetFromTime = egress.earliestDepartureTime(targetFromTime);

int targetToTime = targetFromTime + egress.durationInSeconds();

// No need to time-shift the egress leg, this is done when stopArrival is created
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public interface RaptorTestConstants {
int T00_04 = hm2time(0, 4);
int T00_10 = hm2time(0, 10);
int T00_30 = hm2time(0, 30);
int T01_00 = hm2time(1, 0);

// Stop indexes - Note! There is no stop defined for index 0(zero)! You must
// account for that in the test if you uses a stop index.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,40 @@
*/
public class TestTransfer implements RaptorTransfer {

public static final int SECONDS_IN_DAY = 24 * 3600;
public static final int DEFAULT_NUMBER_OF_LEGS = 0;
public static final boolean STOP_REACHED_ON_BOARD = true;
public static final boolean STOP_REACHED_ON_FOOT = false;
private final int stop;
private final int durationInSeconds;
private final int numberOfRides;
private final boolean stopReachedOnBoard;
private final Integer opening;
private final Integer closing;

private TestTransfer(
int stop,
int durationInSeconds,
int numberOfRides,
boolean stopReachedOnBoard
) {
this(stop, durationInSeconds, numberOfRides, stopReachedOnBoard, null, null);
}

private TestTransfer(
int stop,
int durationInSeconds,
int numberOfRides,
boolean stopReachedOnBoard,
Integer opening,
Integer closing
) {
this.stop = stop;
this.durationInSeconds = durationInSeconds;
this.numberOfRides = numberOfRides;
this.stopReachedOnBoard = stopReachedOnBoard;
this.opening = opening;
this.closing = closing;
}

/** Only use this to override this class, use factory methods to create instances. */
Expand All @@ -38,7 +54,17 @@ protected TestTransfer(int stop, int durationInSeconds) {
}

public static TestTransfer walk(int stop, int durationInSeconds) {
return new TestTransfer(stop, durationInSeconds, DEFAULT_NUMBER_OF_LEGS, STOP_REACHED_ON_FOOT);
return new TestTransfer(stop, durationInSeconds, DEFAULT_NUMBER_OF_LEGS, STOP_REACHED_ON_FOOT, null, null);
}

/**
* Creates a walk transfer with time restrictions. opening and closing may be specified as seconds
* since the start of "RAPTOR time" to limit the time periods that the access is traversable, which
* is repeatead every 24 hours. This allows the access to only be traversable between for example
* 08:00 and 16:00 every day.
*/
public static TestTransfer walk(int stop, int durationInSeconds, int opening, int closing) {
return new TestTransfer(stop, durationInSeconds, DEFAULT_NUMBER_OF_LEGS, STOP_REACHED_ON_FOOT, opening, closing);
}

/** Create a new flex access and arrive stop onBoard with 1 ride/extra transfer. */
Expand Down Expand Up @@ -91,6 +117,47 @@ public boolean stopReachedOnBoard() {
return stopReachedOnBoard;
}

@Override
public int earliestDepartureTime(int requestedDepartureTime) {
if (opening == null || closing == null) {
return requestedDepartureTime;
}

int days = Math.floorDiv(requestedDepartureTime, SECONDS_IN_DAY);
int specificOpening = days * SECONDS_IN_DAY + opening;
int specificClosing = days * SECONDS_IN_DAY + closing;
if (requestedDepartureTime < specificOpening) {
return specificOpening;
} else if (requestedDepartureTime > specificClosing) {
// return the opening time for the next day
return specificOpening + SECONDS_IN_DAY;
}
return requestedDepartureTime;
}

@Override
public int latestArrivalTime(int requestedArrivalTime) {
if (opening == null || closing == null) {
return requestedArrivalTime;
}

// opening & closing is relative to the departure
int requestedDepartureTime = requestedArrivalTime - durationInSeconds();
int days = Math.floorDiv(requestedDepartureTime, SECONDS_IN_DAY);
int specificOpening = days * SECONDS_IN_DAY + opening;
int specificClosing = days * SECONDS_IN_DAY + closing;
int closeAtArrival = specificClosing + durationInSeconds();

if (requestedDepartureTime < specificOpening) {
// return the closing for the previous day, offset with durationInSeconds()
return closeAtArrival - SECONDS_IN_DAY;
}
else if (requestedArrivalTime > closeAtArrival) {
return closeAtArrival;
}
return requestedArrivalTime;
}

@Override
public String toString() {
return asString();
Expand Down
Loading

0 comments on commit 4e17541

Please sign in to comment.