Search in sources :

Example 1 with TripDescriptor

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

the class TripUpdateConvertor method readFeedEntity.

@Override
public TripUpdateModel readFeedEntity(FeedEntity entity, long timestamp) {
    if (entity.hasTripUpdate()) {
        TripUpdateModel tu = new TripUpdateModel();
        TripDescriptor t = entity.getTripUpdate().getTrip();
        if (entity.getTripUpdate().hasTimestamp()) {
            timestamp = entity.getTripUpdate().getTimestamp() * 1000;
        }
        tu.setTimestamp(new Date(timestamp));
        if (entity.getTripUpdate().hasDelay()) {
            tu.setDelay(entity.getTripUpdate().getDelay());
        }
        if (t.hasTripId())
            tu.setTripId(t.getTripId());
        if (t.hasRouteId()) {
            tu.setRouteId(t.getRouteId());
        }
        if (t.hasStartDate() && t.hasStartTime()) {
            tu.setTripStart(GtfsRealtimeConversionLibrary.parseDate(t.getStartDate(), t.getStartTime()));
        }
        tu.setScheduleRelationship(findRelationship(t));
        VehicleDescriptor vehicle = entity.getTripUpdate().getVehicle();
        if (vehicle != null) {
            tu.setVehicleId(vehicle.getId());
            tu.setVehicleLabel(vehicle.getLabel());
            tu.setVehicleLicensePlate(vehicle.getLicensePlate());
        }
        for (StopTimeUpdate stu : entity.getTripUpdate().getStopTimeUpdateList()) {
            StopTimeUpdateModel stopTimeUpdate = readStopTimeUpdate(stu, tu.getScheduleRelationship());
            if (stopTimeUpdate != null) {
                stopTimeUpdate.setTripUpdateModel(tu);
                tu.addStopTimeUpdateModel(stopTimeUpdate);
            }
        }
        return tu;
    }
    return null;
}
Also used : StopTimeUpdateModel(org.onebusaway.gtfs_realtime.model.StopTimeUpdateModel) TripDescriptor(com.google.transit.realtime.GtfsRealtime.TripDescriptor) StopTimeUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate) VehicleDescriptor(com.google.transit.realtime.GtfsRealtime.VehicleDescriptor) Date(java.util.Date) TripUpdateModel(org.onebusaway.gtfs_realtime.model.TripUpdateModel)

Example 2 with TripDescriptor

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

the class VehiclePositionConvertor method readFeedEntity.

@Override
public VehiclePositionModel readFeedEntity(FeedEntity entity, long timestamp) {
    if (entity == null)
        return null;
    VehiclePositionModel vpm = new VehiclePositionModel();
    if (entity.hasVehicle()) {
        if (entity.getVehicle().hasTimestamp()) {
            timestamp = entity.getVehicle().getTimestamp() * 1000;
        }
        if (entity.getVehicle().hasTrip()) {
            TripDescriptor td = entity.getVehicle().getTrip();
            if (td.hasTripId()) {
                vpm.setTripId(td.getTripId());
            }
            if (td.hasRouteId()) {
                vpm.setRouteId(td.getRouteId());
            }
            if (td.hasStartDate() && td.hasStartTime()) {
                vpm.setTripStart(GtfsRealtimeConversionLibrary.parseDate(td.getStartDate(), td.getStartTime()));
            }
        }
        if (entity.getVehicle().hasVehicle()) {
            VehicleDescriptor vd = entity.getVehicle().getVehicle();
            if (vd.hasId()) {
                vpm.setVehicleId(vd.getId());
            }
            if (vd.hasLabel()) {
                vpm.setVehicleLabel(vd.getLabel());
            }
            if (vd.hasLicensePlate()) {
                vpm.setVehicleLicensePlate(vd.getLicensePlate());
            }
        }
        if (entity.getVehicle().hasPosition()) {
            Position p = entity.getVehicle().getPosition();
            vpm.setLat(p.getLatitude());
            vpm.setLon(p.getLongitude());
            if (p.hasBearing()) {
                vpm.setBearing(p.getBearing());
            }
            if (p.hasSpeed()) {
                vpm.setSpeed(p.getSpeed());
            }
        }
        if (entity.getVehicle().hasTrip()) {
            if (vpm.getTripId() == null) {
                if (entity.getVehicle().getTrip().hasTripId()) {
                    vpm.setTripId(entity.getVehicle().getTrip().getTripId());
                }
            }
            if (vpm.getRouteId() == null) {
                if (entity.getVehicle().getTrip().hasRouteId()) {
                    vpm.setRouteId(entity.getVehicle().getTrip().getRouteId());
                }
            }
        }
    }
    if (entity.getVehicle().hasStopId()) {
        vpm.setStopId(entity.getVehicle().getStopId());
    }
    vpm.setTimestamp(new Date(timestamp));
    return vpm;
}
Also used : TripDescriptor(com.google.transit.realtime.GtfsRealtime.TripDescriptor) Position(com.google.transit.realtime.GtfsRealtime.Position) VehiclePositionModel(org.onebusaway.gtfs_realtime.model.VehiclePositionModel) VehicleDescriptor(com.google.transit.realtime.GtfsRealtime.VehicleDescriptor) Date(java.util.Date)

Example 3 with TripDescriptor

use of com.google.transit.realtime.GtfsRealtime.TripDescriptor 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 4 with TripDescriptor

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

the class TimetableSnapshotSource method validateAndHandleModifiedTrip.

/**
 * Validate and handle GTFS-RT TripUpdate message containing a MODIFIED trip.
 *
 * @param graph graph to update
 * @param tripUpdate GTFS-RT TripUpdate message
 * @param feedId
 * @param serviceDate
 * @return true iff successful
 */
private boolean validateAndHandleModifiedTrip(final Graph graph, final TripUpdate tripUpdate, final String feedId, final ServiceDate serviceDate) {
    // Preconditions
    Preconditions.checkNotNull(graph);
    Preconditions.checkNotNull(tripUpdate);
    Preconditions.checkNotNull(serviceDate);
    // 
    // Validate modified trip
    // 
    // Check whether trip id of MODIFIED trip is available
    final TripDescriptor tripDescriptor = tripUpdate.getTrip();
    if (!tripDescriptor.hasTripId()) {
        LOG.warn("No trip id found for MODIFIED trip, skipping.");
        return false;
    }
    // Check whether trip id already exists in graph
    String tripId = tripDescriptor.getTripId();
    Trip trip = getTripForTripId(feedId, tripId);
    if (trip == null) {
        // TODO: should we support this and consider it an ADDED trip?
        LOG.warn("Graph does not contain trip id of MODIFIED trip, skipping.");
        return false;
    }
    // Check whether a start date exists
    if (!tripDescriptor.hasStartDate()) {
        // TODO: should we support this and apply update to all days?
        LOG.warn("MODIFIED trip doesn't have a start date in TripDescriptor, skipping.");
        return false;
    } else {
        // Check whether service date is served by trip
        final Set<AgencyAndId> serviceIds = graph.getCalendarService().getServiceIdsOnDate(serviceDate);
        if (!serviceIds.contains(trip.getServiceId())) {
            // TODO: should we support this and change service id of trip?
            LOG.warn("MODIFIED trip has a service date that is not served by trip, skipping.");
            return false;
        }
    }
    // Check whether at least two stop updates exist
    if (tripUpdate.getStopTimeUpdateCount() < 2) {
        LOG.warn("MODIFIED trip has less then two stops, skipping.");
        return false;
    }
    // Check whether all stop times are available and all stops exist
    List<Stop> stops = checkNewStopTimeUpdatesAndFindStops(feedId, tripUpdate);
    if (stops == null) {
        return false;
    }
    // 
    // Handle modified trip
    // 
    final boolean success = handleModifiedTrip(graph, trip, tripUpdate, stops, feedId, serviceDate);
    return success;
}
Also used : Trip(org.onebusaway.gtfs.model.Trip) TripDescriptor(com.google.transit.realtime.GtfsRealtime.TripDescriptor) AgencyAndId(org.onebusaway.gtfs.model.AgencyAndId) Stop(org.onebusaway.gtfs.model.Stop)

Example 5 with TripDescriptor

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

the class TimetableSnapshotSource method applyTripUpdates.

/**
 * Method to apply a trip update list to the most recent version of the timetable snapshot. A
 * GTFS-RT feed is always applied against a single static feed (indicated by feedId).
 *<<<<<<< HEAD
 *
 *=======
 *
 * However, multi-feed support is not completed and we currently assume there is only one static
 * feed when matching IDs.
 *
 *>>>>>>> 7296be8ffd532a13afb0bec263a9f436ab787022
 * @param graph graph to update (needed for adding/changing stop patterns)
 * @param fullDataset true iff the list with updates represent all updates that are active right
 *        now, i.e. all previous updates should be disregarded
 * @param updates GTFS-RT TripUpdate's that should be applied atomically
 * @param feedId
 */
public void applyTripUpdates(final Graph graph, final boolean fullDataset, final List<TripUpdate> updates, final String feedId) {
    if (updates == null) {
        LOG.warn("updates is null");
        return;
    }
    // Acquire lock on buffer
    bufferLock.lock();
    try {
        if (fullDataset) {
            // Remove all updates from the buffer
            buffer.clear(feedId);
        }
        LOG.debug("message contains {} trip updates", updates.size());
        int uIndex = 0;
        for (TripUpdate tripUpdate : updates) {
            if (fuzzyTripMatcher != null && tripUpdate.hasTrip()) {
                final TripDescriptor trip = fuzzyTripMatcher.match(feedId, tripUpdate.getTrip());
                tripUpdate = tripUpdate.toBuilder().setTrip(trip).build();
            }
            if (!tripUpdate.hasTrip()) {
                LOG.warn("Missing TripDescriptor in gtfs-rt trip update: \n{}", tripUpdate);
                continue;
            }
            ServiceDate serviceDate = new ServiceDate();
            final TripDescriptor tripDescriptor = tripUpdate.getTrip();
            if (tripDescriptor.hasStartDate()) {
                try {
                    serviceDate = ServiceDate.parseString(tripDescriptor.getStartDate());
                } catch (final ParseException e) {
                    LOG.warn("Failed to parse start date in gtfs-rt trip update: \n{}", tripUpdate);
                    continue;
                }
            } else {
            // TODO: figure out the correct service date. For the special case that a trip
            // starts for example at 40:00, yesterday would probably be a better guess.
            }
            uIndex += 1;
            LOG.debug("trip update #{} ({} updates) :", uIndex, tripUpdate.getStopTimeUpdateCount());
            LOG.trace("{}", tripUpdate);
            // Determine what kind of trip update this is
            boolean applied = false;
            final TripDescriptor.ScheduleRelationship tripScheduleRelationship = determineTripScheduleRelationship(tripUpdate);
            switch(tripScheduleRelationship) {
                case SCHEDULED:
                    applied = handleScheduledTrip(tripUpdate, feedId, serviceDate);
                    break;
                case ADDED:
                    applied = validateAndHandleAddedTrip(graph, tripUpdate, feedId, serviceDate);
                    break;
                case UNSCHEDULED:
                    applied = handleUnscheduledTrip(tripUpdate, feedId, serviceDate);
                    break;
                case CANCELED:
                    applied = handleCanceledTrip(tripUpdate, feedId, serviceDate);
                    break;
                case MODIFIED:
                    applied = validateAndHandleModifiedTrip(graph, tripUpdate, feedId, serviceDate);
                    break;
            }
            if (applied) {
                appliedBlockCount++;
            } else {
                LOG.warn("Failed to apply TripUpdate.");
                LOG.trace(" Contents: {}", tripUpdate);
            }
            if (appliedBlockCount % logFrequency == 0) {
                LOG.info("Applied {} trip updates.", appliedBlockCount);
            }
        }
        LOG.debug("end of update message");
        // Make sure that the public (locking) getTimetableSnapshot function is not called.
        if (purgeExpiredData) {
            final boolean modified = purgeExpiredData();
            getTimetableSnapshot(modified);
        } else {
            getTimetableSnapshot(false);
        }
    } finally {
        // Always release lock
        bufferLock.unlock();
    }
}
Also used : ServiceDate(org.onebusaway.gtfs.model.calendar.ServiceDate) TripUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate) TripDescriptor(com.google.transit.realtime.GtfsRealtime.TripDescriptor) ParseException(java.text.ParseException)

Aggregations

TripDescriptor (com.google.transit.realtime.GtfsRealtime.TripDescriptor)12 AgencyAndId (org.onebusaway.gtfs.model.AgencyAndId)4 EntitySelector (com.google.transit.realtime.GtfsRealtime.EntitySelector)2 TripUpdate (com.google.transit.realtime.GtfsRealtime.TripUpdate)2 StopTimeUpdate (com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate)2 VehicleDescriptor (com.google.transit.realtime.GtfsRealtime.VehicleDescriptor)2 Date (java.util.Date)2 Stop (org.onebusaway.gtfs.model.Stop)2 Trip (org.onebusaway.gtfs.model.Trip)2 Affects (org.onebusaway.transit_data_federation.services.service_alerts.ServiceAlerts.Affects)2 Id (org.onebusaway.transit_data_federation.services.service_alerts.ServiceAlerts.Id)2 TripTimes (org.opentripplanner.routing.trippattern.TripTimes)2 Alert (com.google.transit.realtime.GtfsRealtime.Alert)1 FeedEntity (com.google.transit.realtime.GtfsRealtime.FeedEntity)1 Position (com.google.transit.realtime.GtfsRealtime.Position)1 TimeRange (com.google.transit.realtime.GtfsRealtime.TimeRange)1 TranslatedString (com.google.transit.realtime.GtfsRealtime.TranslatedString)1 Translation (com.google.transit.realtime.GtfsRealtime.TranslatedString.Translation)1 StopTimeEvent (com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeEvent)1 VehiclePosition (com.google.transit.realtime.GtfsRealtime.VehiclePosition)1