Search in sources :

Example 71 with Stop

use of org.opentripplanner.model.Stop in project OpenTripPlanner by opentripplanner.

the class TimetableSnapshotSource method checkNewStopTimeUpdatesAndFindStops.

/**
 * Check stop time updates of trip update that results in a new trip (ADDED or MODIFIED) and
 * find all stops of that trip.
 *
 * @param feedId feed id this trip update is intented for
 * @param tripUpdate trip update
 * @return stops when stop time updates are correct; null if there are errors
 */
private List<Stop> checkNewStopTimeUpdatesAndFindStops(final String feedId, final TripUpdate tripUpdate) {
    Integer previousStopSequence = null;
    Long previousTime = null;
    final List<StopTimeUpdate> stopTimeUpdates = tripUpdate.getStopTimeUpdateList();
    final List<Stop> stops = new ArrayList<>(stopTimeUpdates.size());
    for (int index = 0; index < stopTimeUpdates.size(); ++index) {
        final StopTimeUpdate stopTimeUpdate = stopTimeUpdates.get(index);
        // Determine whether stop is skipped
        final boolean skippedStop = isStopSkipped(stopTimeUpdate);
        // Check stop sequence
        if (stopTimeUpdate.hasStopSequence()) {
            final Integer stopSequence = stopTimeUpdate.getStopSequence();
            // Check non-negative
            if (stopSequence < 0) {
                LOG.warn("Trip update contains negative stop sequence, skipping.");
                return null;
            }
            // Check whether sequence is increasing
            if (previousStopSequence != null && previousStopSequence > stopSequence) {
                LOG.warn("Trip update contains decreasing stop sequence, skipping.");
                return null;
            }
            previousStopSequence = stopSequence;
        } else {
        // Allow missing stop sequences for ADDED and MODIFIED trips
        }
        // Find stops
        if (stopTimeUpdate.hasStopId()) {
            // Find stop
            final Stop stop = getStopForStopId(feedId, stopTimeUpdate.getStopId());
            if (stop != null) {
                // Remember stop
                stops.add(stop);
            } else if (skippedStop) {
                // Set a null value for a skipped stop
                stops.add(null);
            } else {
                LOG.warn("Graph doesn't contain stop id \"{}\" of trip update, skipping.", stopTimeUpdate.getStopId());
                return null;
            }
        } else {
            LOG.warn("Trip update misses some stop ids, skipping.");
            return null;
        }
        // Only check arrival and departure times for non-skipped stops
        if (!skippedStop) {
            // Check arrival time
            if (stopTimeUpdate.hasArrival() && stopTimeUpdate.getArrival().hasTime()) {
                // Check for increasing time
                final Long time = stopTimeUpdate.getArrival().getTime();
                if (previousTime != null && previousTime > time) {
                    LOG.warn("Trip update contains decreasing times, skipping.");
                    return null;
                }
                previousTime = time;
            } else {
                // TODO: should we support only requiring an arrival time on the last stop and interpolate?
                for (int earlierIndex = 0; earlierIndex < index; earlierIndex++) {
                    final StopTimeUpdate earlierStopTimeUpdate = stopTimeUpdates.get(earlierIndex);
                    // Determine whether earlier stop is skipped
                    final boolean earlierSkippedStop = isStopSkipped(earlierStopTimeUpdate);
                    if (!earlierSkippedStop) {
                        LOG.warn("Trip update misses arrival time, skipping.");
                        return null;
                    }
                }
            }
            // Check departure time
            if (stopTimeUpdate.hasDeparture() && stopTimeUpdate.getDeparture().hasTime()) {
                // Check for increasing time
                final Long time = stopTimeUpdate.getDeparture().getTime();
                if (previousTime != null && previousTime > time) {
                    LOG.warn("Trip update contains decreasing times, skipping.");
                    return null;
                }
                previousTime = time;
            } else {
                // TODO: should we support only requiring a departure time on the first stop and interpolate?
                for (int laterIndex = stopTimeUpdates.size() - 1; laterIndex > index; laterIndex--) {
                    final StopTimeUpdate laterStopTimeUpdate = stopTimeUpdates.get(laterIndex);
                    // Determine whether later stop is skipped
                    final boolean laterSkippedStop = isStopSkipped(laterStopTimeUpdate);
                    if (!laterSkippedStop) {
                        LOG.warn("Trip update misses departure time, skipping.");
                        return null;
                    }
                }
            }
        }
    }
    return stops;
}
Also used : Stop(org.opentripplanner.model.Stop) ArrayList(java.util.ArrayList) StopTimeUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate)

Example 72 with Stop

use of org.opentripplanner.model.Stop in project OpenTripPlanner by opentripplanner.

the class TimetableSnapshotSource method addTripToGraphAndBuffer.

/**
 * Add a (new) trip to the graph and the buffer
 *
 * @param graph graph
 * @param trip trip
 * @param tripUpdate trip update containing stop time updates
 * @param stops list of stops corresponding to stop time updates
 * @param serviceDate service date of trip
 * @param realTimeState real-time state of new trip
 * @return true iff successful
 */
private boolean addTripToGraphAndBuffer(final String feedId, final Graph graph, final Trip trip, final TripUpdate tripUpdate, final List<Stop> stops, final ServiceDate serviceDate, final RealTimeState realTimeState) {
    // Preconditions
    Preconditions.checkNotNull(stops);
    Preconditions.checkArgument(tripUpdate.getStopTimeUpdateCount() == stops.size(), "number of stop should match the number of stop time updates");
    // Calculate seconds since epoch on GTFS midnight (noon minus 12h) of service date
    final Calendar serviceCalendar = serviceDate.getAsCalendar(timeZone);
    final long midnightSecondsSinceEpoch = serviceCalendar.getTimeInMillis() / MILLIS_PER_SECOND;
    // Create StopTimes
    final List<StopTime> stopTimes = new ArrayList<>(tripUpdate.getStopTimeUpdateCount());
    for (int index = 0; index < tripUpdate.getStopTimeUpdateCount(); ++index) {
        final StopTimeUpdate stopTimeUpdate = tripUpdate.getStopTimeUpdate(index);
        final Stop stop = stops.get(index);
        // Determine whether stop is skipped
        final boolean skippedStop = isStopSkipped(stopTimeUpdate);
        // Only create stop time for non-skipped stops
        if (!skippedStop) {
            // Create stop time
            final StopTime stopTime = new StopTime();
            stopTime.setTrip(trip);
            stopTime.setStop(stop);
            // Set arrival time
            if (stopTimeUpdate.hasArrival() && stopTimeUpdate.getArrival().hasTime()) {
                final long arrivalTime = stopTimeUpdate.getArrival().getTime() - midnightSecondsSinceEpoch;
                if (arrivalTime < 0 || arrivalTime > MAX_ARRIVAL_DEPARTURE_TIME) {
                    LOG.warn("ADDED trip has invalid arrival time (compared to start date in " + "TripDescriptor), skipping.");
                    return false;
                }
                stopTime.setArrivalTime((int) arrivalTime);
            }
            // Set departure time
            if (stopTimeUpdate.hasDeparture() && stopTimeUpdate.getDeparture().hasTime()) {
                final long departureTime = stopTimeUpdate.getDeparture().getTime() - midnightSecondsSinceEpoch;
                if (departureTime < 0 || departureTime > MAX_ARRIVAL_DEPARTURE_TIME) {
                    LOG.warn("ADDED trip has invalid departure time (compared to start date in " + "TripDescriptor), skipping.");
                    return false;
                }
                stopTime.setDepartureTime((int) departureTime);
            }
            // Exact time
            stopTime.setTimepoint(1);
            if (stopTimeUpdate.hasStopSequence()) {
                stopTime.setStopSequence(stopTimeUpdate.getStopSequence());
            }
            // Set different pickup type for last stop
            if (index == tripUpdate.getStopTimeUpdateCount() - 1) {
                // No pickup available
                stopTime.setPickupType(1);
            } else {
                // Regularly scheduled pickup
                stopTime.setPickupType(0);
            }
            // Set different drop off type for first stop
            if (index == 0) {
                // No drop off available
                stopTime.setDropOffType(1);
            } else {
                // Regularly scheduled drop off
                stopTime.setDropOffType(0);
            }
            // Add stop time to list
            stopTimes.add(stopTime);
        }
    }
    // TODO: filter/interpolate stop times like in PatternHopFactory?
    // Create StopPattern
    final StopPattern stopPattern = new StopPattern(stopTimes);
    // Get cached trip pattern or create one if it doesn't exist yet
    final TripPattern pattern = tripPatternCache.getOrCreateTripPattern(stopPattern, trip, graph);
    // Add service code to bitset of pattern if needed (using copy on write)
    final int serviceCode = graph.getServiceCodes().get(trip.getServiceId());
    if (!pattern.getServices().get(serviceCode)) {
        final BitSet services = (BitSet) pattern.getServices().clone();
        services.set(serviceCode);
        pattern.setServices(services);
    }
    // Create new trip times
    final TripTimes newTripTimes = new TripTimes(trip, stopTimes, graph.deduplicator);
    // TODO: should we incorporate the delay field if present?
    for (int stopIndex = 0; stopIndex < newTripTimes.getNumStops(); stopIndex++) {
        newTripTimes.updateArrivalTime(stopIndex, newTripTimes.getScheduledArrivalTime(stopIndex));
        newTripTimes.updateDepartureTime(stopIndex, newTripTimes.getScheduledDepartureTime(stopIndex));
    }
    // Set service code of new trip times
    newTripTimes.serviceCode = serviceCode;
    // Make sure that updated trip times have the correct real time state
    newTripTimes.setRealTimeState(realTimeState);
    // Add new trip times to the buffer
    final boolean success = buffer.update(pattern, newTripTimes, serviceDate);
    return success;
}
Also used : StopPattern(org.opentripplanner.model.StopPattern) Stop(org.opentripplanner.model.Stop) Calendar(java.util.Calendar) ArrayList(java.util.ArrayList) BitSet(java.util.BitSet) TripPattern(org.opentripplanner.model.TripPattern) StopTimeUpdate(com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) StopTime(org.opentripplanner.model.StopTime)

Example 73 with Stop

use of org.opentripplanner.model.Stop in project OpenTripPlanner by opentripplanner.

the class TimetableSnapshotSource method validateAndHandleAddedTrip.

/**
 * Validate and handle GTFS-RT TripUpdate message containing an ADDED trip.
 *
 * @param graph graph to update
 * @param tripUpdate GTFS-RT TripUpdate message
 * @param feedId
 * @param serviceDate
 * @return true iff successful
 */
private boolean validateAndHandleAddedTrip(final Graph graph, final TripUpdate tripUpdate, final String feedId, final ServiceDate serviceDate) {
    // Preconditions
    Preconditions.checkNotNull(graph);
    Preconditions.checkNotNull(tripUpdate);
    Preconditions.checkNotNull(serviceDate);
    // 
    // Validate added trip
    // 
    // Check whether trip id of ADDED trip is available
    final TripDescriptor tripDescriptor = tripUpdate.getTrip();
    if (!tripDescriptor.hasTripId()) {
        LOG.warn("No trip id found for ADDED trip, skipping.");
        return false;
    }
    // Check whether trip id already exists in graph
    final String tripId = tripDescriptor.getTripId();
    final Trip trip = getTripForTripId(feedId, tripId);
    if (trip != null) {
        // TODO: should we support this and add a new instantiation of this trip (making it
        // frequency based)?
        LOG.warn("Graph already contains trip id of ADDED 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("ADDED trip doesn't have a start date in TripDescriptor, skipping.");
        return false;
    }
    // Check whether at least two stop updates exist
    if (tripUpdate.getStopTimeUpdateCount() < 2) {
        LOG.warn("ADDED trip has less then two stops, skipping.");
        return false;
    }
    // Check whether all stop times are available and all stops exist
    final List<Stop> stops = checkNewStopTimeUpdatesAndFindStops(feedId, tripUpdate);
    if (stops == null) {
        return false;
    }
    // 
    // Handle added trip
    // 
    final boolean success = handleAddedTrip(graph, tripUpdate, stops, feedId, serviceDate);
    return success;
}
Also used : Trip(org.opentripplanner.model.Trip) TripDescriptor(com.google.transit.realtime.GtfsRealtime.TripDescriptor) Stop(org.opentripplanner.model.Stop)

Aggregations

Stop (org.opentripplanner.model.Stop)73 FeedScopedId (org.opentripplanner.model.FeedScopedId)25 ArrayList (java.util.ArrayList)24 TripPattern (org.opentripplanner.model.TripPattern)24 Trip (org.opentripplanner.model.Trip)21 ServiceDate (org.opentripplanner.model.calendar.ServiceDate)13 RoutingService (org.opentripplanner.routing.RoutingService)13 TransitStopVertex (org.opentripplanner.routing.vertextype.TransitStopVertex)13 HashSet (java.util.HashSet)12 Station (org.opentripplanner.model.Station)12 TripTimes (org.opentripplanner.routing.trippattern.TripTimes)11 List (java.util.List)10 Test (org.junit.Test)8 Route (org.opentripplanner.model.Route)8 StopTime (org.opentripplanner.model.StopTime)8 Collectors (java.util.stream.Collectors)7 GET (javax.ws.rs.GET)7 Path (javax.ws.rs.Path)7 ApiStop (org.opentripplanner.api.model.ApiStop)7 TripTimeShort (org.opentripplanner.model.TripTimeShort)7