Search in sources :

Example 36 with TripTimes

use of org.opentripplanner.routing.trippattern.TripTimes in project OpenTripPlanner by opentripplanner.

the class OnBoardDepartServiceImplTest method testOnBoardDepartureTime.

@Test
public final void testOnBoardDepartureTime() {
    Coordinate[] coordinates = new Coordinate[5];
    coordinates[0] = new Coordinate(0.0, 0.0);
    coordinates[1] = new Coordinate(0.0, 1.0);
    coordinates[2] = new Coordinate(2.0, 1.0);
    coordinates[3] = new Coordinate(5.0, 1.0);
    coordinates[4] = new Coordinate(5.0, 5.0);
    PatternDepartVertex depart = mock(PatternDepartVertex.class);
    PatternArriveVertex dwell = mock(PatternArriveVertex.class);
    PatternArriveVertex arrive = mock(PatternArriveVertex.class);
    Graph graph = mock(Graph.class);
    RoutingRequest routingRequest = mock(RoutingRequest.class);
    ServiceDay serviceDay = mock(ServiceDay.class);
    // You're probably not supposed to do this to mocks (access their fields directly)
    // But I know of no other way to do this since the mock object has only action-free stub methods.
    routingRequest.modes = new TraverseModeSet("WALK,TRANSIT");
    when(graph.getTimeZone()).thenReturn(TimeZone.getTimeZone("GMT"));
    GeometryFactory geometryFactory = GeometryUtils.getGeometryFactory();
    CoordinateSequenceFactory coordinateSequenceFactory = geometryFactory.getCoordinateSequenceFactory();
    CoordinateSequence coordinateSequence = coordinateSequenceFactory.create(coordinates);
    LineString geometry = new LineString(coordinateSequence, geometryFactory);
    ArrayList<Edge> hops = new ArrayList<Edge>(2);
    RoutingContext routingContext = new RoutingContext(routingRequest, graph, null, arrive);
    AgencyAndId agencyAndId = new AgencyAndId("Agency", "ID");
    Agency agency = new Agency();
    Route route = new Route();
    ArrayList<StopTime> stopTimes = new ArrayList<StopTime>(3);
    StopTime stopDepartTime = new StopTime();
    StopTime stopDwellTime = new StopTime();
    StopTime stopArriveTime = new StopTime();
    Stop stopDepart = new Stop();
    Stop stopDwell = new Stop();
    Stop stopArrive = new Stop();
    Trip trip = new Trip();
    routingContext.serviceDays = new ArrayList<ServiceDay>(Collections.singletonList(serviceDay));
    agency.setId(agencyAndId.getAgencyId());
    route.setId(agencyAndId);
    route.setAgency(agency);
    stopDepart.setId(agencyAndId);
    stopDwell.setId(agencyAndId);
    stopArrive.setId(agencyAndId);
    stopDepartTime.setStop(stopDepart);
    stopDepartTime.setDepartureTime(0);
    stopDwellTime.setArrivalTime(20);
    stopDwellTime.setStop(stopDwell);
    stopDwellTime.setDepartureTime(40);
    stopArriveTime.setArrivalTime(60);
    stopArriveTime.setStop(stopArrive);
    stopTimes.add(stopDepartTime);
    stopTimes.add(stopDwellTime);
    stopTimes.add(stopArriveTime);
    trip.setId(agencyAndId);
    trip.setTripHeadsign("The right");
    trip.setRoute(route);
    TripTimes tripTimes = new TripTimes(trip, stopTimes, new Deduplicator());
    StopPattern stopPattern = new StopPattern(stopTimes);
    TripPattern tripPattern = new TripPattern(route, stopPattern);
    TripPattern.generateUniqueIds(Arrays.asList(tripPattern));
    when(depart.getTripPattern()).thenReturn(tripPattern);
    when(dwell.getTripPattern()).thenReturn(tripPattern);
    PatternHop patternHop0 = new PatternHop(depart, dwell, stopDepart, stopDwell, 0);
    PatternHop patternHop1 = new PatternHop(dwell, arrive, stopDwell, stopArrive, 1);
    hops.add(patternHop0);
    hops.add(patternHop1);
    when(graph.getEdges()).thenReturn(hops);
    when(depart.getCoordinate()).thenReturn(new Coordinate(0, 0));
    when(dwell.getCoordinate()).thenReturn(new Coordinate(0, 0));
    when(arrive.getCoordinate()).thenReturn(new Coordinate(0, 0));
    routingRequest.from = new GenericLocation();
    routingRequest.startingTransitTripId = agencyAndId;
    when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(9);
    patternHop0.setGeometry(geometry);
    tripPattern.add(tripTimes);
    graph.index = new GraphIndex(graph);
    coordinates = new Coordinate[3];
    coordinates[0] = new Coordinate(3.5, 1.0);
    coordinates[1] = new Coordinate(5.0, 1.0);
    coordinates[2] = new Coordinate(5.0, 5.0);
    coordinateSequence = coordinateSequenceFactory.create(coordinates);
    geometry = new LineString(coordinateSequence, geometryFactory);
    Vertex vertex = onBoardDepartServiceImpl.setupDepartOnBoard(routingContext);
    Edge edge = vertex.getOutgoing().toArray(new Edge[1])[0];
    assertEquals(vertex, edge.getFromVertex());
    assertEquals(dwell, edge.getToVertex());
    assertEquals("The right", edge.getDirection());
    assertEquals(geometry, edge.getGeometry());
    assertEquals(coordinates[0].x, vertex.getX(), 0.0);
    assertEquals(coordinates[0].y, vertex.getY(), 0.0);
}
Also used : CoordinateSequence(com.vividsolutions.jts.geom.CoordinateSequence) Vertex(org.opentripplanner.routing.graph.Vertex) PatternDepartVertex(org.opentripplanner.routing.vertextype.PatternDepartVertex) PatternArriveVertex(org.opentripplanner.routing.vertextype.PatternArriveVertex) GeometryFactory(com.vividsolutions.jts.geom.GeometryFactory) ServiceDay(org.opentripplanner.routing.core.ServiceDay) AgencyAndId(org.onebusaway.gtfs.model.AgencyAndId) TransitStop(org.opentripplanner.routing.vertextype.TransitStop) Stop(org.onebusaway.gtfs.model.Stop) ArrayList(java.util.ArrayList) Deduplicator(org.opentripplanner.routing.trippattern.Deduplicator) RoutingContext(org.opentripplanner.routing.core.RoutingContext) GraphIndex(org.opentripplanner.routing.graph.GraphIndex) PatternDepartVertex(org.opentripplanner.routing.vertextype.PatternDepartVertex) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) GenericLocation(org.opentripplanner.common.model.GenericLocation) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest) Route(org.onebusaway.gtfs.model.Route) StopTime(org.onebusaway.gtfs.model.StopTime) StopPattern(org.opentripplanner.model.StopPattern) Trip(org.onebusaway.gtfs.model.Trip) Agency(org.onebusaway.gtfs.model.Agency) TraverseModeSet(org.opentripplanner.routing.core.TraverseModeSet) TripPattern(org.opentripplanner.routing.edgetype.TripPattern) Graph(org.opentripplanner.routing.graph.Graph) Coordinate(com.vividsolutions.jts.geom.Coordinate) LineString(com.vividsolutions.jts.geom.LineString) CoordinateSequenceFactory(com.vividsolutions.jts.geom.CoordinateSequenceFactory) PatternHop(org.opentripplanner.routing.edgetype.PatternHop) PatternArriveVertex(org.opentripplanner.routing.vertextype.PatternArriveVertex) Edge(org.opentripplanner.routing.graph.Edge) Test(org.junit.Test)

Example 37 with TripTimes

use of org.opentripplanner.routing.trippattern.TripTimes in project OpenTripPlanner by opentripplanner.

the class AdjustDwellTime method apply.

@Override
public TripTimes apply(Trip trip, TripPattern tp, TripTimes tt) {
    if (!matches(trip))
        return tt;
    if (tt.getNumStops() == 0)
        return tt;
    // convert trip times to marginals
    int[] dwellTimes = new int[tt.getNumStops()];
    int[] hopTimes = new int[tt.getNumStops() - 1];
    int startTime = tt.getArrivalTime(0);
    for (int i = 0; i < tt.getNumStops(); i++) {
        // adjust dwell time in place as we loop over the stops
        if (stopId == null || stopId.contains(tp.stopPattern.stops[i].getId().getId()))
            dwellTimes[i] = dwellTime;
        else
            dwellTimes[i] = tt.getDepartureTime(i) - tt.getArrivalTime(i);
        if (i < hopTimes.length)
            hopTimes[i] = tt.getArrivalTime(i + 1) - tt.getDepartureTime(i);
    }
    // make a new triptimes
    // Note that this copies the original times, not ones that have been modified by other modifications
    // (suppose someone set the dwell time at some stops to one value because they have offboard fare collection
    // and at other stops to a different value because they don't - this exists, for example, in San Francisco's
    // Muni Metro, with offboard fare collection in the subway and onboard fare collection when running as a
    // streetcar)
    // However, this doesn't matter, because we've manually saved the modified times above.
    TripTimes ret = new TripTimes(tt);
    // Note: this requires us to use getArrivalTime not getScheduledArrivalTime when constructing the times
    // This also means that one should include real-time data in the analysis graphs at their own peril
    int cumulativeTime = startTime;
    for (int i = 0; i < dwellTimes.length; i++) {
        ret.updateArrivalTime(i, cumulativeTime);
        cumulativeTime += dwellTimes[i];
        ret.updateDepartureTime(i, cumulativeTime);
        if (i < hopTimes.length)
            cumulativeTime += hopTimes[i];
    }
    return ret;
}
Also used : TripTimes(org.opentripplanner.routing.trippattern.TripTimes)

Example 38 with TripTimes

use of org.opentripplanner.routing.trippattern.TripTimes in project OpenTripPlanner by opentripplanner.

the class ConvertToFrequency method apply.

public void apply(List<FrequencyEntry> frequencyEntries, List<TripTimes> scheduledTrips, Graph graph, BitSet servicesRunning, RaptorWorkerTimetable.BoardingAssumption assumption) {
    // preserve existing frequency entries
    this.frequencyEntries.addAll(frequencyEntries);
    Set<String> routeIds = new HashSet<>();
    if (routeId != null)
        Stream.of(routeId).forEach(routeIds::add);
    // loop over scheduled trips and figure out what to do with them
    for (TripTimes tt : scheduledTrips) {
        if (routeId == null || routeIds.contains(tt.trip.getRoute().getId().getId())) {
            // put this in the appropriate group for frequency conversion
            String key;
            switch(groupBy) {
                case ROUTE_DIRECTION:
                    key = tt.trip.getRoute().getId().getId() + "_" + tt.trip.getDirectionId();
                    break;
                case ROUTE:
                    key = tt.trip.getRoute().getId().getId();
                    break;
                case PATTERN:
                    key = graph.index.patternForTrip.get(tt.trip).getExemplar().getId().getId();
                    break;
                default:
                    throw new RuntimeException("Unrecognized group by value");
            }
            tripsToConvert.put(key, tt);
        } else {
            // don't touch this trip
            this.scheduledTrips.add(tt);
        }
    }
    // loop over all the groups and create frequency entries
    GROUPS: for (Map.Entry<String, Collection<TripTimes>> e : tripsToConvert.asMap().entrySet()) {
        // get just the running services
        List<TripTimes> group = e.getValue().stream().filter(tt -> servicesRunning.get(tt.serviceCode)).filter(tt -> windowStart < tt.getDepartureTime(0) && tt.getDepartureTime(0) < windowEnd).collect(Collectors.toList());
        if (group.isEmpty())
            continue GROUPS;
        if (group.size() == 1) {
            group.stream().forEach(scheduledTrips::add);
            continue GROUPS;
        }
        // find the dominant pattern
        TObjectIntMap<TripPattern> patternCount = new TObjectIntHashMap<>(5, 0.75f, 0);
        group.forEach(tt -> patternCount.adjustOrPutValue(graph.index.patternForTrip.get(tt.trip), 1, 1));
        int maxCount = 0;
        TripPattern tripPattern = null;
        for (TObjectIntIterator<TripPattern> it = patternCount.iterator(); it.hasNext(); ) {
            it.advance();
            if (it.value() > maxCount) {
                maxCount = it.value();
                tripPattern = it.key();
            }
        }
        // find a stop that is common to all trip patterns. Sort the list so that the same common stop is always returned
        NavigableSet<Stop> stops = new TreeSet<>((s1, s2) -> s1.getId().compareTo(s2.getId()));
        stops.addAll(tripPattern.getStops());
        patternCount.keySet().stream().forEach(p -> stops.retainAll(p.getStops()));
        if (stops.isEmpty()) {
            LOG.warn("Unable to find common stop for key {}, not converting to frequencies", e.getKey());
            scheduledTrips.addAll(e.getValue());
            continue GROUPS;
        }
        Stop stop = stops.stream().findFirst().get();
        // determine the median frequency at this stop
        // use a set to handle duplicated trips
        TIntSet arrivalTimes = new TIntHashSet();
        for (boolean filter : new boolean[] { true, false }) {
            for (TripTimes tt : group) {
                TripPattern tp = graph.index.patternForTrip.get(tt.trip);
                int arrivalTime = tt.getArrivalTime(tp.getStops().indexOf(stop));
                // however, if we apply the filter and end up with no trips at this stop, re-run with the filter disabled
                if (windowStart < arrivalTime && arrivalTime < windowEnd || !filter)
                    arrivalTimes.add(arrivalTime);
            }
            // if we didn't find stops, continue, which will turn off the filter
            if (arrivalTimes.size() > 1)
                break;
        }
        // now convert to elapsed times
        int[] arrivalTimeArray = arrivalTimes.toArray();
        Arrays.sort(arrivalTimeArray);
        int[] headway = new int[arrivalTimeArray.length - 1];
        for (int i = 1; i < arrivalTimeArray.length; i++) {
            headway[i - 1] = arrivalTimeArray[i] - arrivalTimeArray[i - 1];
        }
        Arrays.sort(headway);
        // the headway that we will use
        int aggregateHeadway;
        if (assumption == RaptorWorkerTimetable.BoardingAssumption.WORST_CASE)
            // simple: worst case analysis should use the worst case headway
            aggregateHeadway = Ints.max(headway);
        else {
            // we want the average headway, but we we want the average of the headways weighted
            // by themselves as if there is a two minute headway then a twenty-minute headway,
            // customers are ten times as likely to experience the twenty minute headway
            // (we want the average from the user's perspective, not the vehicle's perspective)
            // This is a weighted average where the weight is the same as the headway so it simplifies
            // to sum (headway^2) / sum(headway)
            aggregateHeadway = IntStream.of(headway).map(h -> h * h).sum() / IntStream.of(headway).sum();
        }
        LOG.info("Headway for route {} ({}) in direction {}: {}min", tripPattern.route.getShortName(), tripPattern.route.getId().getId(), tripPattern.directionId, aggregateHeadway / 60);
        // figure out running/dwell times based on the trips on this pattern
        final TripPattern chosenTp = tripPattern;
        List<TripTimes> candidates = group.stream().filter(tt -> graph.index.patternForTrip.get(tt.trip) == chosenTp).collect(Collectors.toList());
        // transposed from what you'd expect: stops on the rows
        int[][] hopTimes = new int[tripPattern.getStops().size() - 1][candidates.size()];
        int[][] dwellTimes = new int[tripPattern.getStops().size()][candidates.size()];
        int tripIndex = 0;
        for (TripTimes tt : candidates) {
            for (int stopIndex = 0; stopIndex < tripPattern.getStops().size(); stopIndex++) {
                dwellTimes[stopIndex][tripIndex] = tt.getDwellTime(stopIndex);
                if (stopIndex > 0)
                    hopTimes[stopIndex - 1][tripIndex] = tt.getArrivalTime(stopIndex) - tt.getDepartureTime(stopIndex - 1);
            }
            tripIndex++;
        }
        // collapse it down
        int[] meanHopTimes = new int[tripPattern.getStops().size() - 1];
        int hopIndex = 0;
        for (int[] hop : hopTimes) {
            meanHopTimes[hopIndex++] = IntStream.of(hop).sum() / hop.length;
        }
        int[] meanDwellTimes = new int[tripPattern.getStops().size()];
        int dwellIndex = 0;
        for (int[] dwell : dwellTimes) {
            meanDwellTimes[dwellIndex++] = IntStream.of(dwell).sum() / dwell.length;
        }
        // phew! now let's make a frequency entry
        TripTimes tt = new TripTimes(candidates.get(0));
        int cumulative = 0;
        for (int i = 0; i < tt.getNumStops(); i++) {
            tt.updateArrivalTime(i, cumulative);
            cumulative += meanDwellTimes[i];
            tt.updateDepartureTime(i, cumulative);
            if (i + 1 < tt.getNumStops())
                cumulative += meanHopTimes[i];
        }
        FrequencyEntry fe = new FrequencyEntry(windowStart - 60 * 60 * 3, windowEnd + 60 * 60 * 3, aggregateHeadway, false, tt);
        this.frequencyEntries.add(fe);
    }
}
Also used : IntStream(java.util.stream.IntStream) java.util(java.util) Logger(org.slf4j.Logger) FrequencyEntry(org.opentripplanner.routing.trippattern.FrequencyEntry) TObjectIntHashMap(gnu.trove.map.hash.TObjectIntHashMap) LoggerFactory(org.slf4j.LoggerFactory) Multimap(com.google.common.collect.Multimap) Ints(com.google.common.primitives.Ints) TripPattern(org.opentripplanner.routing.edgetype.TripPattern) Collectors(java.util.stream.Collectors) TObjectIntMap(gnu.trove.map.TObjectIntMap) TIntSet(gnu.trove.set.TIntSet) TIntHashSet(gnu.trove.set.hash.TIntHashSet) RaptorWorkerTimetable(org.opentripplanner.profile.RaptorWorkerTimetable) HashMultimap(com.google.common.collect.HashMultimap) TObjectIntIterator(gnu.trove.iterator.TObjectIntIterator) Stop(org.onebusaway.gtfs.model.Stop) Stream(java.util.stream.Stream) Graph(org.opentripplanner.routing.graph.Graph) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) TObjectIntMap(gnu.trove.map.TObjectIntMap) Stop(org.onebusaway.gtfs.model.Stop) TIntSet(gnu.trove.set.TIntSet) TObjectIntIterator(gnu.trove.iterator.TObjectIntIterator) FrequencyEntry(org.opentripplanner.routing.trippattern.FrequencyEntry) TripPattern(org.opentripplanner.routing.edgetype.TripPattern) TIntHashSet(gnu.trove.set.hash.TIntHashSet) FrequencyEntry(org.opentripplanner.routing.trippattern.FrequencyEntry) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) TIntHashSet(gnu.trove.set.hash.TIntHashSet)

Example 39 with TripTimes

use of org.opentripplanner.routing.trippattern.TripTimes in project OpenTripPlanner by opentripplanner.

the class TripPattern method semanticHashString.

/**
 * In most cases we want to use identity equality for Trips.
 * However, in some cases we want a way to consistently identify trips across versions of a GTFS feed, when the
 * feed publisher cannot ensure stable trip IDs. Therefore we define some additional hash functions.
 * Hash collisions are theoretically possible, so these identifiers should only be used to detect when two
 * trips are the same with a high degree of probability.
 * An example application is avoiding double-booking of a particular bus trip for school field trips.
 * Using Murmur hash function. see http://programmers.stackexchange.com/a/145633 for comparison.
 *
 * @param trip a trip object within this pattern, or null to hash the pattern itself independent any specific trip.
 * @return the semantic hash of a Trip in this pattern as a printable String.
 *
 * TODO deal with frequency-based trips
 */
public String semanticHashString(Trip trip) {
    HashFunction murmur = Hashing.murmur3_32();
    BaseEncoding encoder = BaseEncoding.base64Url().omitPadding();
    StringBuilder sb = new StringBuilder(50);
    sb.append(encoder.encode(stopPattern.semanticHash(murmur).asBytes()));
    if (trip != null) {
        TripTimes tripTimes = scheduledTimetable.getTripTimes(trip);
        if (tripTimes == null)
            return null;
        sb.append(':');
        sb.append(encoder.encode(tripTimes.semanticHash(murmur).asBytes()));
    }
    return sb.toString();
}
Also used : HashFunction(com.google.common.hash.HashFunction) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) BaseEncoding(com.google.common.io.BaseEncoding)

Example 40 with TripTimes

use of org.opentripplanner.routing.trippattern.TripTimes in project OpenTripPlanner by opentripplanner.

the class PatternInterlineDwell method traverse.

@Override
public State traverse(State state0) {
    RoutingRequest options = state0.getOptions();
    Trip oldTrip = state0.getBackTrip();
    Trip newTrip = options.arriveBy ? trips.inverse().get(oldTrip) : trips.get(oldTrip);
    if (newTrip == null)
        return null;
    TripPattern newPattern;
    TripTimes newTripTimes;
    TripTimes oldTripTimes = state0.getTripTimes();
    int arrivalTime;
    int departureTime;
    AgencyAndId tripId = state0.getTripId();
    if (options.arriveBy) {
        // traversing backward
        newPattern = ((OnboardVertex) fromv).getTripPattern();
        newTripTimes = newPattern.getResolvedTripTimes(newTrip, state0);
        // FIXME with getLastTime method
        arrivalTime = newTripTimes.getArrivalTime(newTripTimes.getNumStops() - 1);
        departureTime = oldTripTimes.getDepartureTime(0);
    } else {
        // traversing forward
        newPattern = ((OnboardVertex) tov).getTripPattern();
        newTripTimes = newPattern.getResolvedTripTimes(newTrip, state0);
        // FIXME with getLastTime method
        arrivalTime = oldTripTimes.getArrivalTime(oldTripTimes.getNumStops() - 1);
        departureTime = newTripTimes.getDepartureTime(0);
    }
    int boardStopIndex = options.arriveBy ? newPattern.stopPattern.size - 1 : 0;
    if (!newTripTimes.tripAcceptable(state0, boardStopIndex))
        return null;
    int dwellTime = departureTime - arrivalTime;
    if (dwellTime < 0)
        return null;
    StateEditor s1 = state0.edit(this);
    s1.incrementTimeInSeconds(dwellTime);
    // TODO check meaning
    s1.setTripId(newTrip.getId());
    // TODO check meaning
    s1.setPreviousTrip(oldTrip);
    s1.setTripTimes(newTripTimes);
    s1.incrementWeight(dwellTime);
    // Mode should not change.
    return s1.makeState();
}
Also used : Trip(org.onebusaway.gtfs.model.Trip) AgencyAndId(org.onebusaway.gtfs.model.AgencyAndId) StateEditor(org.opentripplanner.routing.core.StateEditor) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest)

Aggregations

TripTimes (org.opentripplanner.routing.trippattern.TripTimes)40 TripPattern (org.opentripplanner.routing.edgetype.TripPattern)19 Stop (org.onebusaway.gtfs.model.Stop)13 FrequencyEntry (org.opentripplanner.routing.trippattern.FrequencyEntry)12 TransitStop (org.opentripplanner.routing.vertextype.TransitStop)10 ArrayList (java.util.ArrayList)9 Trip (org.onebusaway.gtfs.model.Trip)9 RoutingRequest (org.opentripplanner.routing.core.RoutingRequest)9 Timetable (org.opentripplanner.routing.edgetype.Timetable)9 AgencyAndId (org.onebusaway.gtfs.model.AgencyAndId)8 StopTime (org.onebusaway.gtfs.model.StopTime)8 ServiceDay (org.opentripplanner.routing.core.ServiceDay)8 Test (org.junit.Test)7 StopPattern (org.opentripplanner.model.StopPattern)7 StopTimeUpdate (com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate)6 PatternHop (org.opentripplanner.routing.edgetype.PatternHop)6 TimetableSnapshot (org.opentripplanner.routing.edgetype.TimetableSnapshot)6 TripDescriptor (com.google.transit.realtime.GtfsRealtime.TripDescriptor)5 Coordinate (com.vividsolutions.jts.geom.Coordinate)5 RoutingContext (org.opentripplanner.routing.core.RoutingContext)5