Search in sources :

Example 1 with StopTimeEvent

use of com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent in project OpenTripPlanner by opentripplanner.

the class Timetable method createUpdatedTripTimes.

/**
 * Apply the TripUpdate to the appropriate TripTimes from this Timetable. The existing TripTimes
 * must not be modified directly because they may be shared with the underlying
 * scheduledTimetable, or other updated Timetables. The {@link TimetableSnapshot} performs the
 * protective copying of this Timetable. It is not done in this update method to avoid
 * repeatedly cloning the same Timetable when several updates are applied to it at once. We
 * assume here that all trips in a timetable are from the same feed, which should always be the
 * case.
 *
 * @param tripUpdate GTFS-RT trip update
 * @param timeZone time zone of trip update
 * @param updateServiceDate service date of trip update
 * @return new copy of updated TripTimes after TripUpdate has been applied on TripTimes of trip
 *         with the id specified in the trip descriptor of the TripUpdate; null if something
 *         went wrong
 */
public TripTimes createUpdatedTripTimes(TripUpdate tripUpdate, TimeZone timeZone, ServiceDate updateServiceDate) {
    if (tripUpdate == null) {
        LOG.error("A null TripUpdate pointer was passed to the Timetable class update method.");
        return null;
    }
    // However, we want to apply trip updates on top of *scheduled* times
    if (!tripUpdate.hasTrip()) {
        LOG.error("TripUpdate object has no TripDescriptor field.");
        return null;
    }
    TripDescriptor tripDescriptor = tripUpdate.getTrip();
    if (!tripDescriptor.hasTripId()) {
        LOG.error("TripDescriptor object has no TripId field");
        return null;
    }
    String tripId = tripDescriptor.getTripId();
    int tripIndex = getTripIndex(tripId);
    if (tripIndex == -1) {
        LOG.info("tripId {} not found in pattern.", tripId);
        return null;
    } else {
        LOG.trace("tripId {} found at index {} in timetable.", tripId, tripIndex);
    }
    TripTimes newTimes = new TripTimes(getTripTimes(tripIndex));
    if (tripDescriptor.hasScheduleRelationship() && tripDescriptor.getScheduleRelationship() == TripDescriptor.ScheduleRelationship.CANCELED) {
        newTimes.cancel();
    } else {
        // The GTFS-RT reference specifies that StopTimeUpdates are sorted by stop_sequence.
        Iterator<StopTimeUpdate> updates = tripUpdate.getStopTimeUpdateList().iterator();
        if (!updates.hasNext()) {
            LOG.warn("Won't apply zero-length trip update to trip {}.", tripId);
            return null;
        }
        StopTimeUpdate update = updates.next();
        int numStops = newTimes.getNumStops();
        Integer delay = null;
        for (int i = 0; i < numStops; i++) {
            boolean match = false;
            if (update != null) {
                if (update.hasStopSequence()) {
                    match = update.getStopSequence() == newTimes.getStopSequence(i);
                } else if (update.hasStopId()) {
                    match = pattern.getStop(i).getId().getId().equals(update.getStopId());
                }
            }
            if (match) {
                StopTimeUpdate.ScheduleRelationship scheduleRelationship = update.hasScheduleRelationship() ? update.getScheduleRelationship() : StopTimeUpdate.ScheduleRelationship.SCHEDULED;
                if (scheduleRelationship == StopTimeUpdate.ScheduleRelationship.SKIPPED) {
                    LOG.warn("Partially canceled trips are unsupported by this method." + " Skipping TripUpdate.");
                    return null;
                } else if (scheduleRelationship == StopTimeUpdate.ScheduleRelationship.NO_DATA) {
                    newTimes.updateArrivalDelay(i, 0);
                    newTimes.updateDepartureDelay(i, 0);
                    delay = 0;
                } else {
                    long today = updateServiceDate.getAsDate(timeZone).getTime() / 1000;
                    if (update.hasArrival()) {
                        StopTimeEvent arrival = update.getArrival();
                        if (arrival.hasDelay()) {
                            delay = arrival.getDelay();
                            if (arrival.hasTime()) {
                                newTimes.updateArrivalTime(i, (int) (arrival.getTime() - today));
                            } else {
                                newTimes.updateArrivalDelay(i, delay);
                            }
                        } else if (arrival.hasTime()) {
                            newTimes.updateArrivalTime(i, (int) (arrival.getTime() - today));
                            delay = newTimes.getArrivalDelay(i);
                        } else {
                            LOG.error("Arrival time at index {} is erroneous.", i);
                            return null;
                        }
                    } else {
                        if (delay == null) {
                            newTimes.updateArrivalTime(i, TripTimes.UNAVAILABLE);
                        } else {
                            newTimes.updateArrivalDelay(i, delay);
                        }
                    }
                    if (update.hasDeparture()) {
                        StopTimeEvent departure = update.getDeparture();
                        if (departure.hasDelay()) {
                            delay = departure.getDelay();
                            if (departure.hasTime()) {
                                newTimes.updateDepartureTime(i, (int) (departure.getTime() - today));
                            } else {
                                newTimes.updateDepartureDelay(i, delay);
                            }
                        } else if (departure.hasTime()) {
                            newTimes.updateDepartureTime(i, (int) (departure.getTime() - today));
                            delay = newTimes.getDepartureDelay(i);
                        } else {
                            LOG.error("Departure time at index {} is erroneous.", i);
                            return null;
                        }
                    } else {
                        if (delay == null) {
                            newTimes.updateDepartureTime(i, TripTimes.UNAVAILABLE);
                        } else {
                            newTimes.updateDepartureDelay(i, delay);
                        }
                    }
                }
                if (updates.hasNext()) {
                    update = updates.next();
                } else {
                    update = null;
                }
            } else {
                if (delay == null) {
                    newTimes.updateArrivalTime(i, TripTimes.UNAVAILABLE);
                    newTimes.updateDepartureTime(i, TripTimes.UNAVAILABLE);
                } else {
                    newTimes.updateArrivalDelay(i, delay);
                    newTimes.updateDepartureDelay(i, delay);
                }
            }
        }
        if (update != null) {
            LOG.error("Part of a TripUpdate object could not be applied successfully to trip {}.", tripId);
            return null;
        }
    }
    if (!newTimes.timesIncreasing()) {
        LOG.error("TripTimes are non-increasing after applying GTFS-RT delay propagation to trip {}.", tripId);
        return null;
    }
    LOG.debug("A valid TripUpdate object was applied to trip {} using the Timetable class update method.", tripId);
    return newTimes;
}
Also used : StopTimeEvent(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent) TripDescriptor(com.google.transit.realtime.GtfsRealtime.TripDescriptor) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) StopTimeUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate)

Example 2 with StopTimeEvent

use of com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent in project onebusaway-application-modules by camsys.

the class GtfsRealtimeServiceImpl method getTripUpdates.

@Override
public FeedMessage getTripUpdates() {
    FeedMessage.Builder feedMessage = createFeedWithDefaultHeader();
    List<BlockLocation> activeBlocks = _blockStatusService.getAllActiveBlocks(SystemTime.currentTimeMillis());
    for (BlockLocation activeBlock : activeBlocks) {
        // Only interested in blocks with real-time data
        if (!activeBlock.isPredicted())
            continue;
        // Only interested in blocks with a next stop
        BlockStopTimeEntry nextBlockStop = activeBlock.getNextStop();
        if (nextBlockStop == null)
            continue;
        // Only interested in blocks with a schedule deviation set
        if (!activeBlock.isScheduleDeviationSet())
            continue;
        TripUpdate.Builder tripUpdate = TripUpdate.newBuilder();
        BlockTripEntry activeBlockTrip = nextBlockStop.getTrip();
        TripEntry activeTrip = activeBlockTrip.getTrip();
        if (activeBlock.getTimepointPredictions() != null && activeBlock.getTimepointPredictions().size() > 0) {
            // If multiple stoptime predictions were originally obtained,
            // pass them through as received
            List<TimepointPredictionRecord> timepointPredictions = activeBlock.getTimepointPredictions();
            for (TimepointPredictionRecord tpr : timepointPredictions) {
                StopTimeUpdate.Builder stopTimeUpdate = StopTimeUpdate.newBuilder();
                stopTimeUpdate.setStopId(AgencyAndId.convertToString(tpr.getTimepointId()));
                stopTimeUpdate.setScheduleRelationship(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship.SCHEDULED);
                if (tpr.getTimepointPredictedArrivalTime() != -1) {
                    StopTimeEvent.Builder arrivalStopTimeEvent = StopTimeEvent.newBuilder();
                    arrivalStopTimeEvent.setTime(tpr.getTimepointPredictedArrivalTime());
                    stopTimeUpdate.setArrival(arrivalStopTimeEvent);
                }
                if (tpr.getTimepointPredictedDepartureTime() != -1) {
                    StopTimeEvent.Builder departureStopTimeEvent = StopTimeEvent.newBuilder();
                    departureStopTimeEvent.setTime(tpr.getTimepointPredictedDepartureTime());
                    stopTimeUpdate.setDeparture(departureStopTimeEvent);
                }
                tripUpdate.addStopTimeUpdate(stopTimeUpdate);
            }
        } else {
            // No matter what our active trip is, we let our current trip be the the
            // trip of our next stop
            StopTimeEntry nextStopTime = nextBlockStop.getStopTime();
            StopEntry stop = nextStopTime.getStop();
            StopTimeUpdate.Builder stopTimeUpdate = StopTimeUpdate.newBuilder();
            stopTimeUpdate.setStopId(AgencyAndId.convertToString(stop.getId()));
            stopTimeUpdate.setStopSequence(nextStopTime.getSequence());
            stopTimeUpdate.setScheduleRelationship(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship.SCHEDULED);
            StopTimeEvent.Builder stopTimeEvent = StopTimeEvent.newBuilder();
            stopTimeEvent.setDelay((int) activeBlock.getScheduleDeviation());
            stopTimeUpdate.setDeparture(stopTimeEvent);
            tripUpdate.addStopTimeUpdate(stopTimeUpdate);
        }
        AgencyAndId routeId = activeTrip.getRouteCollection().getId();
        AgencyAndId tripId = activeTrip.getId();
        BlockInstance blockInstance = activeBlock.getBlockInstance();
        String startDate = String.format("%1$ty%1$tm%1$td", new Date(blockInstance.getServiceDate()));
        TripDescriptor.Builder tripDescriptor = TripDescriptor.newBuilder();
        tripDescriptor.setRouteId(AgencyAndId.convertToString(routeId));
        tripDescriptor.setScheduleRelationship(ScheduleRelationship.SCHEDULED);
        tripDescriptor.setStartDate(startDate);
        tripDescriptor.setTripId(AgencyAndId.convertToString(tripId));
        tripUpdate.setTrip(tripDescriptor);
        AgencyAndId vehicleId = activeBlock.getVehicleId();
        VehicleDescriptor.Builder vehicleDescriptor = VehicleDescriptor.newBuilder();
        vehicleDescriptor.setId(AgencyAndId.convertToString(vehicleId));
        tripUpdate.setVehicle(vehicleDescriptor);
        FeedEntity.Builder feedEntity = FeedEntity.newBuilder();
        feedEntity.setTripUpdate(tripUpdate);
        feedEntity.setId(vehicleDescriptor.getId());
        feedMessage.addEntity(feedEntity);
    }
    return feedMessage.build();
}
Also used : AgencyAndId(org.onebusaway.gtfs.model.AgencyAndId) ServiceAlertLocalizedString(org.onebusaway.transit_data_federation.impl.service_alerts.ServiceAlertLocalizedString) BlockLocation(org.onebusaway.transit_data_federation.services.realtime.BlockLocation) StopTimeUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate) Date(java.util.Date) StopTimeEvent(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent) BlockInstance(org.onebusaway.transit_data_federation.services.blocks.BlockInstance) TimepointPredictionRecord(org.onebusaway.realtime.api.TimepointPredictionRecord)

Example 3 with StopTimeEvent

use of com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent in project onebusaway-application-modules by camsys.

the class GtfsRealtimeTripLibraryTest method testStopRewriting.

@Test
public void testStopRewriting() {
    StopTimeUpdate.Builder stopTimeUpdate = StopTimeUpdate.newBuilder();
    stopTimeUpdate.setStopId("replaceA");
    StopTimeEvent.Builder stopTimeEvent = StopTimeEvent.newBuilder();
    stopTimeEvent.setDelay(180);
    stopTimeUpdate.setDeparture(stopTimeEvent);
    stopTimeUpdate.setStopSequence(0);
    TripUpdate tripUpdate = TripUpdate.newBuilder().setTrip(TripDescriptor.newBuilder().setTripId("tripA")).setDelay(120).setTimestamp(123456789).addStopTimeUpdate(stopTimeUpdate).build();
    TripEntryImpl tripA = trip("tripA");
    stopTime(0, stop("stopA", 0, 0), tripA, time(7, 30), 0.0);
    BlockEntryImpl blockA = block("blockA");
    BlockConfigurationEntry blockConfigA = blockConfiguration(blockA, serviceIds("s1"), tripA);
    BlockInstance blockInstanceA = new BlockInstance(blockConfigA, 0L);
    Mockito.when(_blockCalendarService.getActiveBlocks(Mockito.eq(blockA.getId()), Mockito.anyLong(), Mockito.anyLong())).thenReturn(Collections.singletonList(blockInstanceA));
    CombinedTripUpdatesAndVehiclePosition update = new CombinedTripUpdatesAndVehiclePosition();
    update.block = new BlockDescriptor();
    update.block.setBlockInstance(blockInstanceA);
    update.tripUpdates = Collections.singletonList(tripUpdate);
    StopModificationStrategy strategy = Mockito.mock(StopModificationStrategy.class);
    Mockito.when(strategy.convertStopId("replaceA")).thenReturn("stopA");
    _library.setStopModificationStrategy(strategy);
    VehicleLocationRecord record = _library.createVehicleLocationRecordForUpdate(update);
    assertEquals(123456789000L, record.getTimeOfRecord());
    assertEquals(120, record.getScheduleDeviation(), 0.0);
    TimepointPredictionRecord tpr = record.getTimepointPredictions().get(0);
    long departure = tpr.getTimepointPredictedDepartureTime();
    assertEquals(departure, time(7, 33) * 1000);
}
Also used : TripUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate) TripEntryImpl(org.onebusaway.transit_data_federation.impl.transit_graph.TripEntryImpl) StopTimeEvent(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent) BlockInstance(org.onebusaway.transit_data_federation.services.blocks.BlockInstance) StopTimeUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate) VehicleLocationRecord(org.onebusaway.realtime.api.VehicleLocationRecord) TimepointPredictionRecord(org.onebusaway.realtime.api.TimepointPredictionRecord) BlockEntryImpl(org.onebusaway.transit_data_federation.impl.transit_graph.BlockEntryImpl) BlockConfigurationEntry(org.onebusaway.transit_data_federation.services.transit_graph.BlockConfigurationEntry) Test(org.junit.Test)

Example 4 with StopTimeEvent

use of com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent in project onebusaway-application-modules by camsys.

the class GtfsRealtimeTripLibraryTest method testCreateVehicleLocationRecordForUpdate_WithStopTimeUpdates.

@Test
public void testCreateVehicleLocationRecordForUpdate_WithStopTimeUpdates() {
    StopTimeUpdate.Builder stopTimeUpdate = StopTimeUpdate.newBuilder();
    stopTimeUpdate.setStopId("stopA");
    StopTimeEvent.Builder stopTimeEvent = StopTimeEvent.newBuilder();
    stopTimeEvent.setDelay(180);
    stopTimeUpdate.setDeparture(stopTimeEvent);
    TripUpdate tripUpdate = TripUpdate.newBuilder().setTrip(TripDescriptor.newBuilder().setTripId("tripA")).setDelay(120).setTimestamp(123456789).addStopTimeUpdate(stopTimeUpdate).build();
    TripEntryImpl tripA = trip("tripA");
    stopTime(0, stop("stopA", 0, 0), tripA, time(7, 30), 0.0);
    BlockEntryImpl blockA = block("blockA");
    BlockConfigurationEntry blockConfigA = blockConfiguration(blockA, serviceIds("s1"), tripA);
    BlockInstance blockInstanceA = new BlockInstance(blockConfigA, 0L);
    Mockito.when(_blockCalendarService.getActiveBlocks(Mockito.eq(blockA.getId()), Mockito.anyLong(), Mockito.anyLong())).thenReturn(Arrays.asList(blockInstanceA));
    CombinedTripUpdatesAndVehiclePosition update = new CombinedTripUpdatesAndVehiclePosition();
    update.block = new BlockDescriptor();
    update.block.setBlockInstance(blockInstanceA);
    update.tripUpdates = Arrays.asList(tripUpdate);
    VehicleLocationRecord record = _library.createVehicleLocationRecordForUpdate(update);
    TimepointPredictionRecord tpr = record.getTimepointPredictions().get(0);
    long departure = tpr.getTimepointPredictedDepartureTime();
    // 7:30 plus 3 min delay, + now we are in ms.
    assertEquals(departure, time(7, 33) * 1000);
}
Also used : TripUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate) TripEntryImpl(org.onebusaway.transit_data_federation.impl.transit_graph.TripEntryImpl) StopTimeEvent(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent) BlockInstance(org.onebusaway.transit_data_federation.services.blocks.BlockInstance) StopTimeUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate) VehicleLocationRecord(org.onebusaway.realtime.api.VehicleLocationRecord) TimepointPredictionRecord(org.onebusaway.realtime.api.TimepointPredictionRecord) BlockEntryImpl(org.onebusaway.transit_data_federation.impl.transit_graph.BlockEntryImpl) BlockConfigurationEntry(org.onebusaway.transit_data_federation.services.transit_graph.BlockConfigurationEntry) Test(org.junit.Test)

Example 5 with StopTimeEvent

use of com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent in project onebusaway-application-modules by camsys.

the class GtfsRealtimeRetrieverImpl method writeStopTimeUpdate.

private StopTimeUpdate writeStopTimeUpdate(StopTimeUpdateModel stum) {
    if (stum == null)
        return null;
    StopTimeUpdate.Builder stu = StopTimeUpdate.newBuilder();
    if (stum.getStopSequence() != null) {
        stu.setStopSequence(stum.getStopSequence().intValue());
    }
    if (stum.getStopId() != null) {
        String parsedStopId = parseId(stum.getStopId());
        if (parsedStopId != null) {
            stu.setStopId(parseId(stum.getStopId()));
        } else {
            // parsing failed (invalid agency-and-id) but pass along as is
            stu.setStopId(stum.getStopId());
        }
    }
    if (stum.getArrivalDelay() != null || stum.getArrivalTime() != null) {
        StopTimeEvent arrival = writeStopTimeEvent(stum.getArrivalDelay(), stum.getArrivalTime(), stum.getArrivalUncertainty());
        stu.setArrival(arrival);
    }
    if (stum.getDepartureDelay() != null || stum.getDepartureTime() != null) {
        StopTimeEvent dept = writeStopTimeEvent(stum.getDepartureDelay(), stum.getDepartureTime(), stum.getDepartureUncertainty());
        stu.setDeparture(dept);
    }
    StopTimeUpdate.ScheduleRelationship sr = StopTimeUpdate.ScheduleRelationship.valueOf(stum.getScheduleRelationship());
    if (sr != null) {
        stu.setScheduleRelationship(sr);
    }
    return stu.build();
}
Also used : StopTimeEvent(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent) StopTimeUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate)

Aggregations

StopTimeEvent (com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent)6 StopTimeUpdate (com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate)5 TimepointPredictionRecord (org.onebusaway.realtime.api.TimepointPredictionRecord)3 BlockInstance (org.onebusaway.transit_data_federation.services.blocks.BlockInstance)3 TripUpdate (com.google.transit.realtime.GtfsRealtime.TripUpdate)2 Test (org.junit.Test)2 VehicleLocationRecord (org.onebusaway.realtime.api.VehicleLocationRecord)2 BlockEntryImpl (org.onebusaway.transit_data_federation.impl.transit_graph.BlockEntryImpl)2 TripEntryImpl (org.onebusaway.transit_data_federation.impl.transit_graph.TripEntryImpl)2 BlockConfigurationEntry (org.onebusaway.transit_data_federation.services.transit_graph.BlockConfigurationEntry)2 TripDescriptor (com.google.transit.realtime.GtfsRealtime.TripDescriptor)1 Date (java.util.Date)1 AgencyAndId (org.onebusaway.gtfs.model.AgencyAndId)1 ServiceAlertLocalizedString (org.onebusaway.transit_data_federation.impl.service_alerts.ServiceAlertLocalizedString)1 BlockLocation (org.onebusaway.transit_data_federation.services.realtime.BlockLocation)1 TripTimes (org.opentripplanner.routing.trippattern.TripTimes)1