use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class TestPatternHopFactory method testTransfers.
public void testTransfers() throws Exception {
TransferTable transferTable = graph.getTransferTable();
// create dummy routes and trips
// In tests we don't patch entities with the feed id, only default agency id is used.
Route fromRoute = new Route();
fromRoute.setId(new AgencyAndId("agency", "1"));
Trip fromTrip = new Trip();
fromTrip.setId(new AgencyAndId("agency", "1.1"));
fromTrip.setRoute(fromRoute);
Route toRoute = new Route();
toRoute.setId(new AgencyAndId("agency", "2"));
Trip toTrip = new Trip();
toTrip.setId(new AgencyAndId("agency", "2.1"));
toTrip.setRoute(toRoute);
Trip toTrip2 = new Trip();
toTrip2.setId(new AgencyAndId("agency", "2.2"));
toTrip2.setRoute(toRoute);
// find stops
Stop stopK = ((TransitStopArrive) graph.getVertex(feedId + ":K_arrive")).getStop();
Stop stopN = ((TransitStopDepart) graph.getVertex(feedId + ":N_depart")).getStop();
Stop stopM = ((TransitStopDepart) graph.getVertex(feedId + ":M_depart")).getStop();
assertTrue(transferTable.hasPreferredTransfers());
assertEquals(StopTransfer.UNKNOWN_TRANSFER, transferTable.getTransferTime(stopN, stopM, fromTrip, toTrip, true));
assertEquals(StopTransfer.FORBIDDEN_TRANSFER, transferTable.getTransferTime(stopK, stopM, fromTrip, toTrip, true));
assertEquals(StopTransfer.PREFERRED_TRANSFER, transferTable.getTransferTime(stopN, stopK, toTrip, toTrip2, true));
assertEquals(StopTransfer.TIMED_TRANSFER, transferTable.getTransferTime(stopN, stopK, fromTrip, toTrip, true));
assertEquals(15, transferTable.getTransferTime(stopN, stopK, fromTrip, toTrip2, true));
TransitStop e_arrive = (TransitStop) graph.getVertex(feedId + ":E");
TransitStop f_depart = (TransitStop) graph.getVertex(feedId + ":F");
Edge edge = new TransferEdge(e_arrive, f_depart, 10000, 10000);
long startTime = TestUtils.dateInSeconds("America/New_York", 2009, 8, 18, 0, 50, 0);
Vertex stop_b = graph.getVertex(feedId + ":B_depart");
Vertex stop_g = graph.getVertex(feedId + ":G_arrive");
RoutingRequest options = new RoutingRequest();
options.dateTime = startTime;
options.setRoutingContext(graph, stop_b, stop_g);
ShortestPathTree spt = aStar.getShortestPathTree(options);
GraphPath path = spt.getPath(stop_g, false);
assertNotNull(path);
assertTrue("expected to use much later trip due to min transfer time", path.getEndTime() - startTime > 4.5 * 60 * 60);
/* cleanup */
e_arrive.removeOutgoing(edge);
f_depart.removeIncoming(edge);
}
use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class OnBoardDepartServiceImplTest method testOnBoardAtStation.
@Test
public final void testOnBoardAtStation() {
TransitStop station0 = mock(TransitStop.class);
TransitStop station1 = mock(TransitStop.class);
TransitStop station2 = mock(TransitStop.class);
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"));
ArrayList<Edge> hops = new ArrayList<Edge>(2);
RoutingContext routingContext = new RoutingContext(routingRequest, graph, null, arrive);
Agency agency = new Agency();
AgencyAndId agencyAndId = new AgencyAndId("Agency", "ID");
Route route = new Route();
ArrayList<StopTime> stopTimes = new ArrayList<StopTime>(2);
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(new AgencyAndId("Station", "0"));
stopDwell.setId(new AgencyAndId("Station", "1"));
stopArrive.setId(new AgencyAndId("Station", "2"));
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.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(graph.getVertex("Station_0")).thenReturn(station0);
when(graph.getVertex("Station_1")).thenReturn(station1);
when(graph.getVertex("Station_2")).thenReturn(station2);
tripPattern.add(tripTimes);
graph.index = new GraphIndex(graph);
when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(0);
assertEquals(station0, onBoardDepartServiceImpl.setupDepartOnBoard(routingContext));
when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(20);
assertEquals(station1, onBoardDepartServiceImpl.setupDepartOnBoard(routingContext));
when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(30);
assertEquals(station1, onBoardDepartServiceImpl.setupDepartOnBoard(routingContext));
when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(40);
assertEquals(station1, onBoardDepartServiceImpl.setupDepartOnBoard(routingContext));
when(serviceDay.secondsSinceMidnight(anyInt())).thenReturn(60);
assertEquals(station2, onBoardDepartServiceImpl.setupDepartOnBoard(routingContext));
}
use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class OnBoardDepartServiceImplTest method testOnBoardDepartureAtArrivalTime.
@Test
public final void testOnBoardDepartureAtArrivalTime() {
Coordinate[] coordinates = new Coordinate[2];
coordinates[0] = new Coordinate(0.0, 0.0);
coordinates[1] = new Coordinate(0.0, 1.0);
TransitStop station0 = mock(TransitStop.class);
TransitStop station1 = mock(TransitStop.class);
PatternDepartVertex depart = mock(PatternDepartVertex.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"));
when(station0.getX()).thenReturn(coordinates[0].x);
when(station0.getY()).thenReturn(coordinates[0].y);
when(station1.getX()).thenReturn(coordinates[1].x);
when(station1.getY()).thenReturn(coordinates[1].y);
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>(2);
StopTime stopDepartTime = new StopTime();
StopTime stopArriveTime = new StopTime();
Stop stopDepart = 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(new AgencyAndId("Station", "0"));
stopArrive.setId(new AgencyAndId("Station", "1"));
stopDepartTime.setStop(stopDepart);
stopDepartTime.setDepartureTime(0);
stopArriveTime.setArrivalTime(10);
stopArriveTime.setStop(stopArrive);
stopTimes.add(stopDepartTime);
stopTimes.add(stopArriveTime);
trip.setId(agencyAndId);
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);
PatternHop patternHop = new PatternHop(depart, arrive, stopDepart, stopArrive, 0);
when(graph.getEdges()).thenReturn(Collections.<Edge>singletonList(patternHop));
when(depart.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(10);
when(graph.getVertex("Station_0")).thenReturn(station0);
when(graph.getVertex("Station_1")).thenReturn(station1);
tripPattern.add(tripTimes);
graph.index = new GraphIndex(graph);
Vertex vertex = onBoardDepartServiceImpl.setupDepartOnBoard(routingContext);
assertEquals(coordinates[1].x, vertex.getX(), 0.0);
assertEquals(coordinates[1].y, vertex.getY(), 0.0);
}
use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class TransitBoardAlight method traverse.
/**
* NOTE: We do not need to check the pickup/drop off type. TransitBoardAlight edges are simply
* not created for pick/drop type 1 (no pick/drop).
*
* @param arrivalTimeAtStop TODO: clarify what this is.
*/
public State traverse(State s0, long arrivalTimeAtStop) {
RoutingContext rctx = s0.getContext();
RoutingRequest options = s0.getOptions();
// Forbid taking shortcuts composed of two board-alight edges in a row. Also avoids spurious leg transitions.
if (s0.backEdge instanceof TransitBoardAlight) {
return null;
}
/* If the user requested a wheelchair accessible trip, check whether and this stop is not accessible. */
if (options.wheelchairAccessible && !getPattern().wheelchairAccessible(stopIndex)) {
return null;
}
;
/*
* Determine whether we are going onto or off of transit. Entering and leaving transit is
* not the same thing as boarding and alighting. When arriveBy == true, we are entering
* transit when traversing an alight edge backward.
*/
boolean leavingTransit = (boarding && options.arriveBy) || (!boarding && !options.arriveBy);
/* TODO pull on/off transit out into two functions. */
if (leavingTransit) {
// Perhaps this should be handled by PathParser.
if (s0.getBackEdge() instanceof TransitBoardAlight) {
return null;
}
StateEditor s1 = s0.edit(this);
s1.setTripId(null);
s1.setLastAlightedTimeSeconds(s0.getTimeSeconds());
// Store the stop we are alighting at, for computing stop-to-stop transfer times,
// preferences, and permissions.
// The vertices in the transfer table are stop arrives/departs, not pattern
// arrives/departs, so previousStop is direction-dependent.
s1.setPreviousStop(getStop());
s1.setLastPattern(this.getPattern());
if (boarding) {
int boardingTime = options.getBoardTime(this.getPattern().mode);
if (boardingTime != 0) {
// When traveling backwards the time travels also backwards
s1.incrementTimeInSeconds(boardingTime);
s1.incrementWeight(boardingTime * options.waitReluctance);
}
} else {
int alightTime = options.getAlightTime(this.getPattern().mode);
if (alightTime != 0) {
s1.incrementTimeInSeconds(alightTime);
s1.incrementWeight(alightTime * options.waitReluctance);
// TODO: should we have different cost for alighting and boarding compared to regular waiting?
}
}
/* Determine the wait. */
if (arrivalTimeAtStop > 0) {
// FIXME what is this arrivalTimeAtStop?
int wait = (int) Math.abs(s0.getTimeSeconds() - arrivalTimeAtStop);
s1.incrementTimeInSeconds(wait);
// this should only occur at the beginning
s1.incrementWeight(wait * options.waitAtBeginningFactor);
s1.setInitialWaitTimeSeconds(wait);
// LOG.debug("Initial wait time set to {} in PatternBoard", wait);
}
// so that comparable trip plans result (comparable to non-optimized plans)
if (options.reverseOptimizing)
s1.incrementWeight(options.getBoardCost(s0.getNonTransitMode()));
if (options.reverseOptimizeOnTheFly) {
TripPattern pattern = getPattern();
int thisDeparture = s0.getTripTimes().getDepartureTime(stopIndex);
int numTrips = getPattern().getNumScheduledTrips();
int nextDeparture;
s1.setLastNextArrivalDelta(Integer.MAX_VALUE);
for (int tripIndex = 0; tripIndex < numTrips; tripIndex++) {
Timetable timetable = pattern.getUpdatedTimetable(options, s0.getServiceDay());
nextDeparture = timetable.getTripTimes(tripIndex).getDepartureTime(stopIndex);
if (nextDeparture > thisDeparture) {
s1.setLastNextArrivalDelta(nextDeparture - thisDeparture);
break;
}
}
}
s1.setBackMode(getMode());
return s1.makeState();
} else {
/* Disallow ever re-boarding the same trip pattern. */
if (s0.getLastPattern() == this.getPattern()) {
return null;
}
/* Check this pattern's mode against those allowed in the request. */
if (!options.modes.get(modeMask)) {
return null;
}
/* We assume all trips in a pattern are on the same route. Check if that route is banned. */
if (options.bannedRoutes != null && options.bannedRoutes.matches(getPattern().route)) {
// TODO: remove route checks in/after the trip search
return null;
}
/*
* Find the next boarding/alighting time relative to the current State. Check lists of
* transit serviceIds running yesterday, today, and tomorrow relative to the initial
* state. Choose the closest board/alight time among trips starting yesterday, today, or
* tomorrow. Note that we cannot skip searching on service days that have not started
* yet: Imagine a state at 23:59 Sunday, that should take a bus departing at 00:01
* Monday (and coded on Monday in the GTFS); disallowing Monday's departures would
* produce a strange plan. We also can't break off the search after we find trips today.
* Imagine a trip on a pattern at 25:00 today and another trip on the same pattern at
* 00:30 tommorrow. The 00:30 trip should be taken, but if we stopped the search after
* finding today's 25:00 trip we would never find tomorrow's 00:30 trip.
*/
TripPattern tripPattern = this.getPattern();
int bestWait = -1;
TripTimes bestTripTimes = null;
ServiceDay bestServiceDay = null;
for (ServiceDay sd : rctx.serviceDays) {
/* Find the proper timetable (updated or original) if there is a realtime snapshot. */
Timetable timetable = tripPattern.getUpdatedTimetable(options, sd);
/* Skip this day/timetable if no trip in it could possibly be useful. */
// TODO disabled until frequency representation is stable, and min/max timetable times are set from frequencies
// However, experiments seem to show very little measurable improvement here (due to cache locality?)
// if ( ! timetable.temporallyViable(sd, s0.getTimeSeconds(), bestWait, boarding)) continue;
/* Find the next or prev departure depending on final boolean parameter. */
TripTimes tripTimes = timetable.getNextTrip(s0, sd, stopIndex, boarding);
if (tripTimes != null) {
/* Wait is relative to departures on board and arrivals on alight. */
int wait = boarding ? (int) (sd.time(tripTimes.getDepartureTime(stopIndex)) - s0.getTimeSeconds()) : (int) (s0.getTimeSeconds() - sd.time(tripTimes.getArrivalTime(stopIndex)));
/* A trip was found. The wait should be non-negative. */
if (wait < 0)
LOG.error("Negative wait time when boarding.");
/* Track the soonest departure over all relevant schedules. */
if (bestWait < 0 || wait < bestWait) {
bestWait = wait;
bestServiceDay = sd;
bestTripTimes = tripTimes;
}
}
}
// no appropriate trip was found
if (bestWait < 0)
return null;
Trip trip = bestTripTimes.trip;
// FIXME this should be done WHILE searching for a trip.
if (options.tripIsBanned(trip))
return null;
/* Check if route is preferred by the user. */
long preferences_penalty = options.preferencesPenaltyForRoute(getPattern().route);
/* Compute penalty for non-preferred transfers. */
int transferPenalty = 0;
/* If this is not the first boarding, then we are transferring. */
if (s0.isEverBoarded()) {
TransferTable transferTable = options.getRoutingContext().transferTable;
int transferTime = transferTable.getTransferTime(s0.getPreviousStop(), getStop(), s0.getPreviousTrip(), trip, boarding);
transferPenalty = transferTable.determineTransferPenalty(transferTime, options.nonpreferredTransferPenalty);
}
/* Found a trip to board. Now make the child state. */
StateEditor s1 = s0.edit(this);
s1.setBackMode(getMode());
s1.setServiceDay(bestServiceDay);
// Save the trip times in the State to ensure that router has a consistent view
// and constant-time access to them.
s1.setTripTimes(bestTripTimes);
s1.incrementTimeInSeconds(bestWait);
s1.incrementNumBoardings();
s1.setTripId(trip.getId());
s1.setPreviousTrip(trip);
s1.setZone(getPattern().getZone(stopIndex));
s1.setRoute(trip.getRoute().getId());
double wait_cost = bestWait;
if (!s0.isEverBoarded() && !options.reverseOptimizing) {
wait_cost *= options.waitAtBeginningFactor;
s1.setInitialWaitTimeSeconds(bestWait);
} else {
wait_cost *= options.waitReluctance;
}
s1.incrementWeight(preferences_penalty);
s1.incrementWeight(transferPenalty);
// alight to prevent state domination due to free alights
if (options.reverseOptimizing) {
s1.incrementWeight(wait_cost);
} else {
s1.incrementWeight(wait_cost + options.getBoardCost(s0.getNonTransitMode()));
}
// impacting the possibility of this trip
if (options.reverseOptimizeOnTheFly && !options.reverseOptimizing && s0.isEverBoarded() && s0.getLastNextArrivalDelta() <= bestWait && s0.getLastNextArrivalDelta() > -1) {
// it is re-reversed by optimize, so this still yields a forward tree
State optimized = s1.makeState().optimizeOrReverse(true, true);
if (optimized == null)
LOG.error("Null optimized state. This shouldn't happen.");
return optimized;
}
/* If we didn't return an optimized path, return an unoptimized one. */
return s1.makeState();
}
}
use of org.onebusaway.gtfs.model.Trip in project OpenTripPlanner by opentripplanner.
the class GTFSPatternHopFactory method interline.
/**
* Identify interlined trips (where a physical vehicle continues on to another logical trip)
* and update the TripPatterns accordingly. This must be called after all the pattern edges and vertices
* are already created, because it creates interline dwell edges between existing pattern arrive/depart vertices.
*/
private void interline(Collection<TripPattern> tripPatterns, Graph graph) {
/* Record which Pattern each interlined TripTimes belongs to. */
Map<TripTimes, TripPattern> patternForTripTimes = Maps.newHashMap();
/* TripTimes grouped by the block ID and service ID of their trips. Must be a ListMultimap to allow sorting. */
ListMultimap<BlockIdAndServiceId, TripTimes> tripTimesForBlock = ArrayListMultimap.create();
LOG.info("Finding interlining trips based on block IDs.");
for (TripPattern pattern : tripPatterns) {
Timetable timetable = pattern.scheduledTimetable;
/* TODO: Block semantics seem undefined for frequency trips, so skip them? */
for (TripTimes tripTimes : timetable.tripTimes) {
Trip trip = tripTimes.trip;
if (!Strings.isNullOrEmpty(trip.getBlockId())) {
tripTimesForBlock.put(new BlockIdAndServiceId(trip), tripTimes);
// For space efficiency, only record times that are part of a block.
patternForTripTimes.put(tripTimes, pattern);
}
}
}
/* Associate pairs of TripPatterns with lists of trips that continue from one pattern to the other. */
Multimap<P2<TripPattern>, P2<Trip>> interlines = ArrayListMultimap.create();
/*
Sort trips within each block by first departure time, then iterate over trips in this block and service,
linking them. Has no effect on single-trip blocks.
*/
SERVICE_BLOCK: for (BlockIdAndServiceId block : tripTimesForBlock.keySet()) {
List<TripTimes> blockTripTimes = tripTimesForBlock.get(block);
Collections.sort(blockTripTimes);
TripTimes prev = null;
for (TripTimes curr : blockTripTimes) {
if (prev != null) {
if (prev.getDepartureTime(prev.getNumStops() - 1) > curr.getArrivalTime(0)) {
LOG.error("Trip times within block {} are not increasing on service {} after trip {}.", block.blockId, block.serviceId, prev.trip.getId());
continue SERVICE_BLOCK;
}
TripPattern prevPattern = patternForTripTimes.get(prev);
TripPattern currPattern = patternForTripTimes.get(curr);
Stop fromStop = prevPattern.getStop(prevPattern.getStops().size() - 1);
Stop toStop = currPattern.getStop(0);
double teleportationDistance = SphericalDistanceLibrary.fastDistance(fromStop.getLat(), fromStop.getLon(), toStop.getLat(), toStop.getLon());
if (teleportationDistance > maxInterlineDistance) {
// FIXME Trimet data contains a lot of these -- in their data, two trips sharing a block ID just
// means that they are served by the same vehicle, not that interlining is automatically allowed.
// see #1654
// LOG.error(graph.addBuilderAnnotation(new InterliningTeleport(prev.trip, block.blockId, (int)teleportationDistance)));
// Only skip this particular interline edge; there may be other valid ones in the block.
} else {
interlines.put(new P2<TripPattern>(prevPattern, currPattern), new P2<Trip>(prev.trip, curr.trip));
}
}
prev = curr;
}
}
/*
Create the PatternInterlineDwell edges linking together TripPatterns.
All the pattern vertices and edges must already have been created.
*/
for (P2<TripPattern> patterns : interlines.keySet()) {
TripPattern prevPattern = patterns.first;
TripPattern nextPattern = patterns.second;
// This is a single (uni-directional) edge which may be traversed forward and backward.
PatternInterlineDwell edge = new PatternInterlineDwell(prevPattern, nextPattern);
for (P2<Trip> trips : interlines.get(patterns)) {
edge.add(trips.first, trips.second);
}
}
LOG.info("Done finding interlining trips and creating the corresponding edges.");
}
Aggregations