use of org.onebusaway.transit_data_federation.services.realtime.ArrivalAndDepartureInstance in project onebusaway-application-modules by camsys.
the class ArrivalAndDepartureServiceImplTest method testGetArrivalsAndDeparturesForStopInTimeRange17.
/**
* This method tests loops in the middle of routes (the same stop is visited more
* than once in the same trip) when stop_sequence is missing in the real-time feed.
* It attempts to apply the prediction if there is more than one prediction in the
* same trip (i.e., the stop_id can be disambiguated). However, there is a limitation for
* when the loop is in the middle of the trip (see FIXME below) - in this case, we can't disambiguate
* the time point prediction without stop_sequence. In other cases (and tests in this class),
* we are able to disambiguate the predictions for simple loop trips when the prediction is
* for the first or last stop in the trip and the first and last stop are the same, and we are able
* to infer this from the presence of more than one prediction (see #163). However, we can't
* currently make this same inference for loops that occur in middle of the route, as it would require
* us to look at a larger window of stops, which increases the computation time overhead. We would also
* need to add some bundle build-time attributes to identify which trips have loops within them,
* and which stops are the loop stops that appear more than once.
*
* NOTE: The "real" and simplest fix for this issue is for the real-time feed to include stop_sequence
* to disambiguate which real-time prediction should apply to which stop. This isn't currently a
* requirement in GTFS-rt, but we're trying to make it one (see https://github.com/google/transit/pull/20).
*
* Test configuration: There is one trip and this trip has 4 stops. But, in the middle of the route,
* same stop B visited twice. So, the route look like this: A->B->C->B->D, where the stop B visited twice
* in the middle of the route. Time point predictions do not have stop sequences,
* and therefore the update for Stop B is ambiguous. We currently do not have any mechanism to handle
* this case, and OBA cannot understand this is a loop route, because loop happens in
* the middle of the route. OBA will currently (and erroneously) apply the real-time update for both stop Bs.
* As a result, it will predict the arrival times wrong for stop b (sequence = 3) and stop D.
*
* Current time = 14:00
* Schedule time Real-time from feed GTFS stop_sequence trip_id
* Stop A 13:30 ----- 0 t1
* Stop B 13:45 13:50 1 t1
* Stop C 13:55 ----- 2 t1
* Stop B 14:05 ----- 3 t1
* Stop D 14:15 ----- 4 t1
*/
@Test
public void testGetArrivalsAndDeparturesForStopInTimeRange17() {
// Override the current time with a later time than the time point
// predictions
mCurrentTime = dateAsLong("2015-07-23 14:00");
// Set time point prediction for trip 1 stop B
TimepointPredictionRecord tpr1A = new TimepointPredictionRecord();
tpr1A.setTimepointId(mStopB.getId());
long tpr1ATime = createPredictedTime(time(13, 50));
tpr1A.setTimepointPredictedArrivalTime(tpr1ATime);
tpr1A.setTripId(mTrip1.getId());
// Call ArrivalsAndDeparturesForStopInTimeRange method in
// ArrivalAndDepartureServiceImpl
List<ArrivalAndDepartureInstance> arrivalsAndDepartures = getArrivalsAndDeparturesForLoopInTheMiddleOfRouteInTimeRangeByTimepointPredictionRecord(Arrays.asList(tpr1A));
// First trip in block
long predictedArrivalTimeStop1A = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), mTrip1.getId(), 0);
long predictedArrivalTimeStop1B = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopB.getId(), mTrip1.getId(), 1);
long predictedArrivalTimeStop1C = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopC.getId(), mTrip1.getId(), 2);
long predictedArrivalTimeStop1BB = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopB.getId(), mTrip1.getId(), 3);
long predictedArrivalTimeStop1D = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopD.getId(), mTrip1.getId(), 4);
/**
* Make sure no real-time info is applied to stop A
*/
assertEquals(predictedArrivalTimeStop1A, 0);
/**
* Check predictions for first stop B and stop C. We should have correct predictions for these stops.
*/
long scheduledArrivalTime1B = getScheduledArrivalTimeByStopId(mTrip1, mStopB.getId(), 1);
long scheduledArrivalTime1C = getScheduledArrivalTimeByStopId(mTrip1, mStopC.getId(), 2);
// Calculate the delay of the last stop A in trip B
long delta = TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStop1B) - scheduledArrivalTime1B;
assertEquals(predictedArrivalTimeStop1B, tpr1A.getTimepointPredictedArrivalTime());
assertEquals(scheduledArrivalTime1C + delta, TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStop1C));
/**
* FIXME: Properly apply real-time updates without stop_sequence to loop stops if they are in the middle of the trip
*
* In this test, we have a stop (stop B) and it is visited twice in the middle of the route.
* We have only one timePointPredicition without stop_sequence for the first stop B. OBA currently
* cannot determine this is a loop route. Therefore, it will apply the same timePointPrediction to
* two different stops (the first stop B and the second stop B). The proper behavior would be for the
* second visited stop B (stop_sequence = 3), we should have prediction propagated downstream from the
* first Stop B (stop_sequence = 1) (see below assertions for what should be happening).
*
* As a result, the following test cases should fail with the current configuration, and therefore are commented out.
* A simple fix to solve this problem is for the provider to add stop_squence in the GTFS-realtime feed.
*/
// long scheduledArrivalTime1BB = getScheduledArrivalTimeByStopId(mTrip1,
// mStopB.getId(), 3);
// long scheduledArrivalTime1D = getScheduledArrivalTimeByStopId(mTrip1,
// mStopD.getId(), 4);
//
// assertEquals(scheduledArrivalTime1BB + delta , TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStop1BB));
// assertEquals(scheduledArrivalTime1D + delta , TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStop1D));
}
use of org.onebusaway.transit_data_federation.services.realtime.ArrivalAndDepartureInstance in project onebusaway-application-modules by camsys.
the class ArrivalAndDepartureServiceImplTest method testGetArrivalsAndDeparturesForStopInTimeRange02.
/**
* This method tests upstream time point predictions for scheduled *arrival*
* times.
*
* Test configuration: Time point predictions are upstream of the current
* stop_id, which means that the bus hasn't passed the bus stop yet. A real
* time arrival time (time point prediction) is provided for only one bus stop
* (Stop A). In this case getArrivalsAndDeparturesForStopInTimeRange() should
* calculate a new arrival time for Stop B (based on the upstream prediction
* for Stop A), which is the scheduled arrival time + the upstream deviation.
*
* Current time = 13:00
* Schedule time Real-time from feed
* Stop A 13:30 13:35
* Stop B 13:40 ---
*
* We are requesting arrival time for Stop B, which should be propagated
* downstream from Stop A's prediction, which should be 13:45 (13:40 + 5 min
* deviation from Stop A). Stop A's predicted arrival and departure should
* also be the respective scheduled arrival and departure plus the 5 min
* deviation.
*/
@Test
public void testGetArrivalsAndDeparturesForStopInTimeRange02() {
// Set time point predictions for stop A
TimepointPredictionRecord tprA = new TimepointPredictionRecord();
tprA.setTimepointId(mStopA.getId());
long tprATime = createPredictedTime(time(13, 35));
tprA.setTimepointPredictedArrivalTime(tprATime);
tprA.setTripId(mTrip1.getId());
// Call ArrivalsAndDeparturesForStopInTimeRange method in
// ArrivalAndDepartureServiceImpl
List<ArrivalAndDepartureInstance> arrivalsAndDepartures = getArrivalsAndDeparturesForStopInTimeRangeByTimepointPredictionRecord(Arrays.asList(tprA));
long predictedArrivalTimeStopA = getPredictedArrivalTimeByStopId(arrivalsAndDepartures, mStopA.getId());
long predictedDepartureTimeStopA = getPredictedDepartureTimeByStopId(arrivalsAndDepartures, mStopA.getId());
long predictedArrivalTimeStopB = getPredictedArrivalTimeByStopId(arrivalsAndDepartures, mStopB.getId());
long predictedDepartureTimeStopB = getPredictedDepartureTimeByStopId(arrivalsAndDepartures, mStopB.getId());
long scheduledArrivalTimeStopA = getScheduledArrivalTimeByStopId(mTrip1, mStopA.getId());
long scheduledDepartureTimeStopA = getScheduledDepartureTimeByStopId(mTrip1, mStopA.getId());
long scheduledArrivalTimeStopB = getScheduledArrivalTimeByStopId(mTrip1, mStopB.getId());
long scheduledDepartureTimeStopB = getScheduledDepartureTimeByStopId(mTrip1, mStopB.getId());
// The time point prediction for Stop A was 5 min late, so this should be
// applied to Stop B scheduled arrival
long delta = TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStopA) - scheduledArrivalTimeStopA;
assertEquals(TimeUnit.MINUTES.toSeconds(5), delta);
// Check if the predictedArrivalTimes and predictedDepartureTimes is the
// same as the scheduledArrivalTime plus the delta
assertEquals(TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStopA), scheduledArrivalTimeStopA + delta);
assertEquals(TimeUnit.MILLISECONDS.toSeconds(predictedDepartureTimeStopA), scheduledDepartureTimeStopA + delta);
assertEquals(TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStopB), scheduledArrivalTimeStopB + delta);
assertEquals(TimeUnit.MILLISECONDS.toSeconds(predictedDepartureTimeStopB), scheduledDepartureTimeStopB + delta);
}
use of org.onebusaway.transit_data_federation.services.realtime.ArrivalAndDepartureInstance in project onebusaway-application-modules by camsys.
the class ArrivalAndDepartureServiceImplTest method testGetArrivalsAndDeparturesForStopInTimeRange11.
/**
* This method tests loop routes (the same stop is visited more
* than once in the same trip) when stop_sequence is missing in the real-time feed.
* It applies the prediction if there is more than one prediction in the same trip
* (i.e., the stop_id can be disambiguated).
*
* Test configuration: There are three different loop trips in the same block
* and each trip has 3 stops. Time point predictions do not have stop_sequences.
* Last 2 stops in middle trip have predictions.
*
* Current time = 14:00
* Schedule time Real-time from feed GTFS stop_sequence trip_id
* Stop A 13:30 ----- 0 t1
* Stop B 13:45 ----- 1 t1
* Stop A 13:55 ----- 2 t1
*
* Stop A 14:05 ----- 0 t2
* Stop B 14:15 14:25 1 t2
* Stop A 14:25 14:35 2 t2
*
* Stop A 14:30 ----- 0 t3
* Stop B 14:45 ----- 1 t3
* Stop A 14:55 ----- 2 t3
*/
@Test
public void testGetArrivalsAndDeparturesForStopInTimeRange11() {
// Override the current time with a later time than the time point
// predictions
mCurrentTime = dateAsLong("2015-07-23 14:00");
// Set time point predictions for trip 2 stop B
TimepointPredictionRecord tprB = new TimepointPredictionRecord();
tprB.setTimepointId(mStopB.getId());
long tprBTime = createPredictedTime(time(14, 25));
tprB.setTimepointPredictedArrivalTime(tprBTime);
tprB.setTripId(mTrip2.getId());
// Set time point predictions for trip 3 stop A (last instance)
TimepointPredictionRecord tprA = new TimepointPredictionRecord();
tprA.setTimepointId(mStopA.getId());
long tprATime = createPredictedTime(time(14, 35));
tprA.setTimepointPredictedArrivalTime(tprATime);
tprA.setTripId(mTrip2.getId());
// Call ArrivalsAndDeparturesForStopInTimeRange method in
// ArrivalAndDepartureServiceImpl
List<ArrivalAndDepartureInstance> arrivalsAndDepartures = getArrivalsAndDeparturesForLoopRouteInTimeRangeByTimepointPredictionRecordWithMultipleTrips(Arrays.asList(tprB, tprA), mStopB);
// First trip in block
long predictedArrivalTimeStop1A = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), mTrip1.getId(), 0);
long predictedArrivalTimeStop1B = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopB.getId(), mTrip1.getId(), 1);
long predictedArrivalTimeStop1C = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), mTrip1.getId(), 2);
assertEquals(predictedArrivalTimeStop1A, 0);
assertEquals(predictedArrivalTimeStop1B, 0);
assertEquals(predictedArrivalTimeStop1C, 0);
// Second trip in block
long predictedArrivalTimeStop2A = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), mTrip2.getId(), 0);
assertEquals(predictedArrivalTimeStop2A, 0);
/**
* Make sure the predictedArrivalTime for stop B and stop A (the last stop) in
* the trip B is exactly the same as TimepointPredictionRecords.
*/
long predictedArrivalTime2B = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopB.getId(), mTrip2.getId(), 1);
long predictedArrivalTime2C = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), mTrip2.getId(), 2);
assertEquals(tprB.getTimepointPredictedArrivalTime(), predictedArrivalTime2B);
assertEquals(tprA.getTimepointPredictedArrivalTime(), predictedArrivalTime2C);
/**
* Make sure the predictions happening downstream based on the last stop
* of the trip B
*/
long scheduledArrivalTime2C = getScheduledArrivalTimeByStopId(mTrip2, mStopA.getId(), 2);
// Calculate the delay of the last stop A in trip B
long delta = TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTime2C) - scheduledArrivalTime2C;
// Third trip in block
long scheduledArrivalTimeStop3A = getScheduledArrivalTimeByStopId(mTrip3, mStopA.getId(), 0);
long predictedArrivalTime3A = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), mTrip3.getId(), 0);
long scheduledArrivalTimeStop3B = getScheduledArrivalTimeByStopId(mTrip3, mStopB.getId(), 1);
long predictedArrivalTime3B = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopB.getId(), mTrip3.getId(), 1);
long scheduledArrivalTimeStop3C = getScheduledArrivalTimeByStopId(mTrip3, mStopA.getId(), 2);
long predictedArrivalTime3C = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), mTrip3.getId(), 2);
assertEquals(scheduledArrivalTimeStop3A + delta, TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTime3A));
assertEquals(scheduledArrivalTimeStop3B + delta, TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTime3B));
assertEquals(scheduledArrivalTimeStop3C + delta, TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTime3C));
}
use of org.onebusaway.transit_data_federation.services.realtime.ArrivalAndDepartureInstance in project onebusaway-application-modules by camsys.
the class ArrivalAndDepartureServiceImplTest method testGetArrivalsAndDeparturesForStopInTimeRange05.
/**
* This method tests a request for an arrival time for a stop, when the
* current time is greater than the arrival time prediction for that stop
* (Stop B). In other words, the bus is predicted to have already passed the
* stop (Stop B).
*
* Test configuration: There are 2 bus stops which have the real time arrival
* times (time point predictions) - Stop A and B. In this case
* getArrivalsAndDeparturesForStopInTimeRange() should return last received
* time point prediction for particular stop we're requesting information for.
*
* Current time = 14:00
* Schedule time Real-time from feed
* Stop A 13:30 13:30
* Stop B 13:40 13:50
*/
@Test
public void testGetArrivalsAndDeparturesForStopInTimeRange05() {
// Override the current time with a later time than the time point
// predictions
mCurrentTime = dateAsLong("2015-07-23 14:00");
// Set time point predictions for stop A
TimepointPredictionRecord tprA = new TimepointPredictionRecord();
tprA.setTimepointId(mStopA.getId());
long tprATime = createPredictedTime(time(13, 30));
tprA.setTimepointPredictedArrivalTime(tprATime);
tprA.setTripId(mTrip1.getId());
// Set time point predictions for stop B
TimepointPredictionRecord tprB = new TimepointPredictionRecord();
tprB.setTimepointId(mStopB.getId());
long tprBTime = createPredictedTime(time(13, 50));
tprB.setTimepointPredictedArrivalTime(tprBTime);
tprB.setTripId(mTrip1.getId());
// Call ArrivalsAndDeparturesForStopInTimeRange method in
// ArrivalAndDepartureServiceImpl
List<ArrivalAndDepartureInstance> arrivalsAndDepartures = getArrivalsAndDeparturesForStopInTimeRangeByTimepointPredictionRecord(Arrays.asList(tprA, tprB));
long predictedArrivalTimeStopA = getPredictedArrivalTimeByStopId(arrivalsAndDepartures, mStopA.getId());
long predictedArrivalTimeStopB = getPredictedArrivalTimeByStopId(arrivalsAndDepartures, mStopB.getId());
/**
* Check if the predictedArrivalTime is exactly the same as
* TimepointPrediction for both stops
*/
assertEquals(tprA.getTimepointPredictedArrivalTime(), predictedArrivalTimeStopA);
assertEquals(tprB.getTimepointPredictedArrivalTime(), predictedArrivalTimeStopB);
/**
* Check if the predictedDepartureTimes and scheduledDepartureTimes have the
* same delta as arrival predictions and scheduled arrival times for both
* stops
*/
long predictedDepartureTimeStopA = getPredictedDepartureTimeByStopId(arrivalsAndDepartures, mStopA.getId());
long predictedDepartureTimeStopB = getPredictedDepartureTimeByStopId(arrivalsAndDepartures, mStopB.getId());
long scheduledArrivalTimeForStopA = getScheduledArrivalTimeByStopId(mTrip1, mStopA.getId());
long scheduledArrivalTimeForStopB = getScheduledArrivalTimeByStopId(mTrip1, mStopB.getId());
long scheduledDepartureTimeForStopA = getScheduledDepartureTimeByStopId(mTrip1, mStopA.getId());
long scheduledDepartureTimeForStopB = getScheduledDepartureTimeByStopId(mTrip1, mStopB.getId());
long deltaA = TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStopA) - scheduledArrivalTimeForStopA;
assertEquals(scheduledDepartureTimeForStopA + deltaA, TimeUnit.MILLISECONDS.toSeconds(predictedDepartureTimeStopA));
long deltaB = TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStopB) - scheduledArrivalTimeForStopB;
assertEquals(scheduledDepartureTimeForStopB + deltaB, TimeUnit.MILLISECONDS.toSeconds(predictedDepartureTimeStopB));
}
use of org.onebusaway.transit_data_federation.services.realtime.ArrivalAndDepartureInstance in project onebusaway-application-modules by camsys.
the class ArrivalAndDepartureServiceImplTest method testGetArrivalsAndDeparturesForStopInTimeRange08.
/**
* This method tests loop routes (the same stop is visited more
* than once in the same trip) when stop_sequence is missing in the real-time feed.
* It applies the prediction if there is more than one prediction in the same trip
* (i.e., the stop_id can be disambiguated).
*
* Test configuration: There are two time point predictions, one for the first stop
* and one for second stop, and there is a single trip in the block. The time point
* predictions do not have stop_sequences. In this case, propagation should happen as normal.
* getArrivalsAndDeparturesForStopInTimeRange() the first Stop A and stop B predictions
* should match with time point predictions. The last Stop A should return a predicted
* arrival based on stop B (6 min delay).
*
* Current time = 14:00
* Schedule time Real-time from feed GTFS stop_sequence
* Stop A 13:30 13:35 0
* Stop B 13:45 13:51 1
* Stop A 13:55 ----- 2
*/
@Test
public void testGetArrivalsAndDeparturesForStopInTimeRange08() {
// Override the current time with a later time than the time point
// predictions
mCurrentTime = dateAsLong("2015-07-23 14:00");
// Set time point predictions for stop A
TimepointPredictionRecord tprA = new TimepointPredictionRecord();
tprA.setTimepointId(mStopA.getId());
long tprATime = createPredictedTime(time(13, 35));
tprA.setTimepointPredictedArrivalTime(tprATime);
tprA.setTripId(mTrip1.getId());
// Set time point predictions for stop B
TimepointPredictionRecord tprB = new TimepointPredictionRecord();
tprB.setTimepointId(mStopB.getId());
long tprBTime = createPredictedTime(time(13, 51));
tprB.setTimepointPredictedArrivalTime(tprBTime);
tprB.setTripId(mTrip1.getId());
// Call ArrivalsAndDeparturesForStopInTimeRange method in
// ArrivalAndDepartureServiceImpl
List<ArrivalAndDepartureInstance> arrivalsAndDepartures = getArrivalsAndDeparturesForLoopRouteInTimeRangeByTimepointPredictionRecord(Arrays.asList(tprA, tprB), mStopB);
long predictedArrivalTimeStopB = getPredictedArrivalTimeByStopId(arrivalsAndDepartures, mStopB.getId());
/**
* Check if the predictedArrivalTime for stop B is exactly the same as
* TimepointPredictionRecord.
*/
assertEquals(tprB.getTimepointPredictedArrivalTime(), predictedArrivalTimeStopB);
/**
* Make sure the predictedArrivalTime for stop A (the first stop) is exactly the same as
* TimepointPredictionRecord.
*/
long predictedArrivalTimeA = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), 0);
assertEquals(tprA.getTimepointPredictedArrivalTime(), predictedArrivalTimeA);
/**
* Make sure the predictedArrivalTime for stop A (the last stop) is propagated based on
* TimepointPredictionRecord of the stop B
*/
long scheduledArrivalTimeStopB = getScheduledArrivalTimeByStopId(mTrip1, mStopB.getId());
long scheduledArrivalTimeLastStopA = getScheduledArrivalTimeByStopId(mTrip1, mStopA.getId(), 2);
/**
* Calculate the delay of the previous stop(stop B)
*/
long delta = TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeStopB) - scheduledArrivalTimeStopB;
predictedArrivalTimeA = getPredictedArrivalTimeByStopIdAndSequence(arrivalsAndDepartures, mStopA.getId(), 2);
assertEquals(scheduledArrivalTimeLastStopA + delta, TimeUnit.MILLISECONDS.toSeconds(predictedArrivalTimeA));
}
Aggregations