Search in sources :

Example 41 with TransitStop

use of org.opentripplanner.routing.vertextype.TransitStop in project OpenTripPlanner by opentripplanner.

the class RoundBasedProfileRouter method route.

public void route() {
    LOG.info("access modes: {}", request.accessModes);
    LOG.info("egress modes: {}", request.egressModes);
    LOG.info("direct modes: {}", request.directModes);
    // TimeWindow could constructed in the caller, which does have access to the graph index.
    this.window = new TimeWindow(request.fromTime, request.toTime, graph.index.servicesRunning(request.date));
    // Establish search timeouts
    long searchBeginTime = System.currentTimeMillis();
    long abortTime = searchBeginTime + TIMEOUT * 1000;
    LOG.info("Finding access/egress paths.");
    // Look for stops that are within a given time threshold of the origin and destination
    // Find the closest stop on each pattern near the origin and destination
    // TODO consider that some stops may be closer by one mode than another
    // and that some stops may be accessible by one mode but not another
    ProfileStateStore store = RETAIN_PATTERNS ? new MultiProfileStateStore() : new SingleProfileStateStore();
    for (ProfileState ps : findInitialStops(false)) {
        store.put(ps);
    }
    LOG.info("Found {} initial stops", store.size());
    // we don't want to generate trips that are artificially forced to go past a transit stop.
    ROUNDS: for (int round = 0; round < MAX_ROUNDS; round++) {
        long roundStart = System.currentTimeMillis();
        LOG.info("Begin round {}; {} stops to explore", round, store.size());
        ProfileStateStore previousStore = store;
        store = RETAIN_PATTERNS ? new MultiProfileStateStore((MultiProfileStateStore) store) : new SingleProfileStateStore((SingleProfileStateStore) store);
        Set<TripPattern> patternsToExplore = Sets.newHashSet();
        // explore all of the patterns at the stops visited on the previous round
        for (TransitStop tstop : previousStore.keys()) {
            Collection<TripPattern> patterns = graph.index.patternsForStop.get(tstop.getStop());
            patternsToExplore.addAll(patterns);
        }
        LOG.info("Exploring {} patterns", patternsToExplore.size());
        // propagate all of the bounds down each pattern
        PATTERNS: for (final TripPattern pattern : patternsToExplore) {
            STOPS: for (int i = 0; i < pattern.stopVertices.length; i++) {
                if (!previousStore.containsKey(pattern.stopVertices[i]))
                    continue STOPS;
                Collection<ProfileState> statesToPropagate;
                // only propagate nondominated states
                statesToPropagate = previousStore.get(pattern.stopVertices[i]);
                // don't propagate states that use the same pattern
                statesToPropagate = Collections2.filter(statesToPropagate, new Predicate<ProfileState>() {

                    @Override
                    public boolean apply(ProfileState input) {
                        // don't reboard same pattern, and don't board patterns that are better boarded elsewhere
                        return !input.containsPattern(pattern) && (input.targetPatterns == null || input.targetPatterns.contains(pattern));
                    }
                });
                if (statesToPropagate.isEmpty())
                    continue STOPS;
                int minWaitTime = Integer.MAX_VALUE;
                int maxWaitTime = Integer.MIN_VALUE;
                // (i.e. the transfer time is different for the initial boarding than transfers)
                for (FrequencyEntry freq : pattern.scheduledTimetable.frequencyEntries) {
                    if (freq.exactTimes) {
                        throw new IllegalStateException("Exact times not yet supported in profile routing.");
                    }
                    int overlap = window.overlap(freq.startTime, freq.endTime, freq.tripTimes.serviceCode);
                    if (overlap > 0) {
                        if (freq.headway > maxWaitTime)
                            maxWaitTime = freq.headway;
                        // if any frequency-based trips are running a wait of 0 is always possible, because it could come
                        // just as you show up at the stop.
                        minWaitTime = 0;
                    }
                }
                DESTSTOPS: for (int j = i + 1; j < pattern.stopVertices.length; j++) {
                    // how long does it take to ride this trip from i to j?
                    int minRideTime = Integer.MAX_VALUE;
                    int maxRideTime = Integer.MIN_VALUE;
                    // how long does it take to get to stop j from stop i?
                    for (TripTimes tripTimes : pattern.scheduledTimetable.tripTimes) {
                        int depart = tripTimes.getDepartureTime(i);
                        int arrive = tripTimes.getArrivalTime(j);
                        if (window.includes(depart) && window.includes(arrive) && window.servicesRunning.get(tripTimes.serviceCode)) {
                            int t = arrive - depart;
                            if (t < minRideTime)
                                minRideTime = t;
                            if (t > maxRideTime)
                                maxRideTime = t;
                        }
                    }
                    /* Do the same thing for any frequency-based trips. */
                    for (FrequencyEntry freq : pattern.scheduledTimetable.frequencyEntries) {
                        TripTimes tt = freq.tripTimes;
                        int overlap = window.overlap(freq.startTime, freq.endTime, tt.serviceCode);
                        if (overlap == 0)
                            continue;
                        int depart = tt.getDepartureTime(i);
                        int arrive = tt.getArrivalTime(j);
                        int t = arrive - depart;
                        if (t < minRideTime)
                            minRideTime = t;
                        if (t > maxRideTime)
                            maxRideTime = t;
                    }
                    if (minWaitTime == Integer.MAX_VALUE || maxWaitTime == Integer.MIN_VALUE || minRideTime == Integer.MAX_VALUE || maxRideTime == Integer.MIN_VALUE)
                        // no trips in window that arrive at stop
                        continue DESTSTOPS;
                    if (minRideTime < 0 || maxRideTime < 0) {
                        LOG.error("Pattern {} travels backwards in time between stop {} and {}", pattern, pattern.stopVertices[i].getStop(), pattern.stopVertices[j].getStop());
                        continue DESTSTOPS;
                    }
                    // we've already checked to ensure we're not reboarding the same pattern
                    for (ProfileState ps : statesToPropagate) {
                        ProfileState ps2 = ps.propagate(minWaitTime + minRideTime, maxWaitTime + maxRideTime);
                        if (ps2.upperBound > CUTOFF_SECONDS)
                            continue;
                        ps2.stop = pattern.stopVertices[j];
                        ps2.accessType = Type.TRANSIT;
                        if (RETAIN_PATTERNS)
                            ps2.patterns = new TripPattern[] { pattern };
                        store.put(ps2);
                    }
                }
            }
        }
        // merge states that came from the same stop.
        if (RETAIN_PATTERNS) {
            LOG.info("Round completed, merging similar states");
            ((MultiProfileStateStore) store).mergeStates();
        }
        for (ProfileState ps : store.getAll()) {
            retainedStates.put(ps.stop, ps);
        }
        if (round == MAX_ROUNDS - 1) {
            LOG.info("Finished round {} in {} seconds", round, (System.currentTimeMillis() - roundStart) / 1000);
            break ROUNDS;
        }
        // propagate states to nearby stops (transfers)
        LOG.info("Finding transfers . . .");
        // avoid concurrent modification
        Set<TransitStop> touchedStopKeys = new HashSet<TransitStop>(store.keys());
        for (TransitStop tstop : touchedStopKeys) {
            List<Tuple2<TransitStop, Integer>> accessTimes = Lists.newArrayList();
            // find transfers for the stop
            for (Edge e : tstop.getOutgoing()) {
                if (e instanceof SimpleTransfer) {
                    SimpleTransfer t = (SimpleTransfer) e;
                    int time = (int) (t.getDistance() / request.walkSpeed);
                    accessTimes.add(new Tuple2((TransitStop) e.getToVertex(), time));
                }
            }
            // only transfer from nondominated states. only transfer to each pattern once
            Collection<ProfileState> statesAtStop = store.get(tstop);
            TObjectIntHashMap<TripPattern> minBoardTime = new TObjectIntHashMap<TripPattern>(1000, .75f, Integer.MAX_VALUE);
            Map<TripPattern, ProfileState> optimalBoardState = Maps.newHashMap();
            List<ProfileState> xferStates = Lists.newArrayList();
            // make a hashset of the patterns that stop here, because we don't want to transfer to them at another stop
            HashSet<TripPattern> patternsAtSource = new HashSet<TripPattern>(graph.index.patternsForStop.get(tstop.getStop()));
            for (ProfileState ps : statesAtStop) {
                for (Tuple2<TransitStop, Integer> atime : accessTimes) {
                    ProfileState ps2 = ps.propagate(atime.b);
                    ps2.accessType = Type.TRANSFER;
                    ps2.stop = atime.a;
                    for (TripPattern patt : graph.index.patternsForStop.get(atime.a.getStop())) {
                        // don't transfer to patterns that we can board at this stop.
                        if (patternsAtSource.contains(patt))
                            continue;
                        if (atime.b < minBoardTime.get(patt)) {
                            minBoardTime.put(patt, atime.b);
                            optimalBoardState.put(patt, ps2);
                        }
                    }
                    xferStates.add(ps2);
                }
            }
            for (Entry<TripPattern, ProfileState> e : optimalBoardState.entrySet()) {
                ProfileState ps = e.getValue();
                if (ps.targetPatterns == null)
                    ps.targetPatterns = Sets.newHashSet();
                ps.targetPatterns.add(e.getKey());
            }
            for (ProfileState ps : xferStates) {
                if (ps.targetPatterns != null && !ps.targetPatterns.isEmpty()) {
                    store.put(ps);
                }
            }
        }
        LOG.info("Finished round {} in {} seconds", round, (System.currentTimeMillis() - roundStart) / 1000);
    }
    LOG.info("Finished profile routing in {} seconds", (System.currentTimeMillis() - searchBeginTime) / 1000);
    makeSurfaces();
    LOG.info("Finished analyst request in {} seconds total", (System.currentTimeMillis() - searchBeginTime) / 1000);
}
Also used : HashSet(java.util.HashSet) QualifiedModeSet(org.opentripplanner.api.parameter.QualifiedModeSet) Set(java.util.Set) RangeSet(org.opentripplanner.analyst.TimeSurface.RangeSet) TransitStop(org.opentripplanner.routing.vertextype.TransitStop) FrequencyEntry(org.opentripplanner.routing.trippattern.FrequencyEntry) FrequencyEntry(org.opentripplanner.routing.trippattern.FrequencyEntry) Entry(java.util.Map.Entry) TObjectIntHashMap(gnu.trove.map.hash.TObjectIntHashMap) TripTimes(org.opentripplanner.routing.trippattern.TripTimes) ArrayList(java.util.ArrayList) List(java.util.List) SimpleTransfer(org.opentripplanner.routing.edgetype.SimpleTransfer) HashSet(java.util.HashSet) TripPattern(org.opentripplanner.routing.edgetype.TripPattern) Tuple2(org.mapdb.Fun.Tuple2) Collection(java.util.Collection) Edge(org.opentripplanner.routing.graph.Edge) TObjectIntMap(gnu.trove.map.TObjectIntMap) Map(java.util.Map) TObjectIntHashMap(gnu.trove.map.hash.TObjectIntHashMap)

Example 42 with TransitStop

use of org.opentripplanner.routing.vertextype.TransitStop in project OpenTripPlanner by opentripplanner.

the class RoundBasedProfileRouter method findInitialStops.

/**
 * find the boarding stops
 */
private Collection<ProfileState> findInitialStops(boolean dest) {
    double lat = dest ? request.toLat : request.fromLat;
    double lon = dest ? request.toLon : request.fromLon;
    QualifiedModeSet modes = dest ? request.accessModes : request.egressModes;
    List<ProfileState> stops = Lists.newArrayList();
    RoutingRequest rr = new RoutingRequest(TraverseMode.WALK);
    rr.dominanceFunction = new DominanceFunction.EarliestArrival();
    rr.batch = true;
    rr.from = new GenericLocation(lat, lon);
    rr.walkSpeed = request.walkSpeed;
    rr.to = rr.from;
    rr.setRoutingContext(graph);
    // RoutingRequest dateTime defaults to currentTime.
    // If elapsed time is not capped, searches are very slow.
    rr.worstTime = (rr.dateTime + request.maxWalkTime * 60);
    AStar astar = new AStar();
    rr.longDistance = true;
    rr.setNumItineraries(1);
    // timeout in seconds
    ShortestPathTree spt = astar.getShortestPathTree(rr, 5);
    for (TransitStop tstop : graph.index.stopVertexForStop.values()) {
        State s = spt.getState(tstop);
        if (s != null) {
            ProfileState ps = new ProfileState();
            ps.lowerBound = ps.upperBound = (int) s.getElapsedTimeSeconds();
            ps.stop = tstop;
            ps.accessType = Type.STREET;
            stops.add(ps);
        }
    }
    Map<TripPattern, ProfileState> optimalBoardingLocation = Maps.newHashMap();
    TObjectIntMap<TripPattern> minBoardTime = new TObjectIntHashMap<TripPattern>(100, 0.75f, Integer.MAX_VALUE);
    // Only board patterns at the closest possible stop
    for (ProfileState ps : stops) {
        for (TripPattern pattern : graph.index.patternsForStop.get(ps.stop.getStop())) {
            if (ps.lowerBound < minBoardTime.get(pattern)) {
                optimalBoardingLocation.put(pattern, ps);
                minBoardTime.put(pattern, ps.lowerBound);
            }
        }
        ps.targetPatterns = Sets.newHashSet();
    }
    LOG.info("Found {} reachable stops, filtering to only board at closest stops", stops.size());
    for (Entry<TripPattern, ProfileState> e : optimalBoardingLocation.entrySet()) {
        e.getValue().targetPatterns.add(e.getKey());
    }
    for (Iterator<ProfileState> it = stops.iterator(); it.hasNext(); ) {
        if (it.next().targetPatterns.isEmpty())
            it.remove();
    }
    rr.cleanup();
    return stops;
}
Also used : TransitStop(org.opentripplanner.routing.vertextype.TransitStop) AStar(org.opentripplanner.routing.algorithm.AStar) QualifiedModeSet(org.opentripplanner.api.parameter.QualifiedModeSet) TripPattern(org.opentripplanner.routing.edgetype.TripPattern) ShortestPathTree(org.opentripplanner.routing.spt.ShortestPathTree) TObjectIntHashMap(gnu.trove.map.hash.TObjectIntHashMap) State(org.opentripplanner.routing.core.State) GenericLocation(org.opentripplanner.common.model.GenericLocation) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest) DominanceFunction(org.opentripplanner.routing.spt.DominanceFunction)

Example 43 with TransitStop

use of org.opentripplanner.routing.vertextype.TransitStop in project OpenTripPlanner by opentripplanner.

the class AlertPatch method apply.

public void apply(Graph graph) {
    Agency agency = null;
    if (feedId != null) {
        Map<String, Agency> agencies = graph.index.agenciesForFeedId.get(feedId);
        agency = this.agency != null ? agencies.get(this.agency) : null;
    }
    Route route = this.route != null ? graph.index.routeForId.get(this.route) : null;
    Stop stop = this.stop != null ? graph.index.stopForId.get(this.stop) : null;
    Trip trip = this.trip != null ? graph.index.tripForId.get(this.trip) : null;
    if (route != null || trip != null || agency != null) {
        Collection<TripPattern> tripPatterns = null;
        if (trip != null) {
            tripPatterns = new LinkedList<>();
            TripPattern tripPattern = graph.index.patternForTrip.get(trip);
            if (tripPattern != null) {
                tripPatterns.add(tripPattern);
            }
        } else if (route != null) {
            tripPatterns = graph.index.patternsForRoute.get(route);
        } else {
            // Find patterns for the feed.
            tripPatterns = graph.index.patternsForFeedId.get(feedId);
        }
        if (tripPatterns != null) {
            for (TripPattern tripPattern : tripPatterns) {
                if (direction != null && !direction.equals(tripPattern.getDirection())) {
                    continue;
                }
                if (directionId != -1 && directionId == tripPattern.directionId) {
                    continue;
                }
                for (int i = 0; i < tripPattern.stopPattern.stops.length; i++) {
                    if (stop == null || stop.equals(tripPattern.stopPattern.stops[i])) {
                        graph.addAlertPatch(tripPattern.boardEdges[i], this);
                        graph.addAlertPatch(tripPattern.alightEdges[i], this);
                    }
                }
            }
        }
    } else if (stop != null) {
        TransitStop transitStop = graph.index.stopVertexForStop.get(stop);
        for (Edge edge : transitStop.getOutgoing()) {
            if (edge instanceof PreBoardEdge) {
                graph.addAlertPatch(edge, this);
                break;
            }
        }
        for (Edge edge : transitStop.getIncoming()) {
            if (edge instanceof PreAlightEdge) {
                graph.addAlertPatch(edge, this);
                break;
            }
        }
    }
}
Also used : Trip(org.onebusaway.gtfs.model.Trip) PreBoardEdge(org.opentripplanner.routing.edgetype.PreBoardEdge) Agency(org.onebusaway.gtfs.model.Agency) TransitStop(org.opentripplanner.routing.vertextype.TransitStop) TransitStop(org.opentripplanner.routing.vertextype.TransitStop) Stop(org.onebusaway.gtfs.model.Stop) TripPattern(org.opentripplanner.routing.edgetype.TripPattern) PreAlightEdge(org.opentripplanner.routing.edgetype.PreAlightEdge) PreAlightEdge(org.opentripplanner.routing.edgetype.PreAlightEdge) PreBoardEdge(org.opentripplanner.routing.edgetype.PreBoardEdge) Edge(org.opentripplanner.routing.graph.Edge) Route(org.onebusaway.gtfs.model.Route)

Example 44 with TransitStop

use of org.opentripplanner.routing.vertextype.TransitStop in project OpenTripPlanner by opentripplanner.

the class PreAlightEdge method traverse.

@Override
public State traverse(State s0) {
    RoutingRequest options = s0.getOptions();
    // Ignore this edge if its stop is banned
    if (!options.bannedStops.isEmpty()) {
        if (options.bannedStops.matches(((TransitStop) tov).getStop())) {
            return null;
        }
    }
    if (!options.bannedStopsHard.isEmpty()) {
        if (options.bannedStopsHard.matches(((TransitStop) tov).getStop())) {
            return null;
        }
    }
    if (options.arriveBy) {
        // options can be used to find transit stops without boarding vehicles.
        if (!options.modes.isTransit())
            return null;
        TransitStop toVertex = (TransitStop) getToVertex();
        // If we've hit our transfer limit, don't go any further
        if (s0.getNumBoardings() > options.maxTransfers)
            return null;
        /* apply transfer rules */
        /*
             * look in the global transfer table for the rules from the previous stop to this stop.
             */
        long t0 = s0.getTimeSeconds();
        long slack;
        if (s0.isEverBoarded()) {
            slack = options.transferSlack - options.boardSlack;
        } else {
            slack = options.alightSlack;
        }
        long alight_before = t0 - slack;
        int transfer_penalty = 0;
        // penalize transfers more heavily if requested by the user
        if (s0.isEverBoarded()) {
            // this is not the first boarding, therefore we must have "transferred" -- whether
            // via a formal transfer or by walking.
            transfer_penalty += options.transferPenalty;
        }
        StateEditor s1 = s0.edit(this);
        s1.setTimeSeconds(alight_before);
        long wait_cost = t0 - alight_before;
        s1.incrementWeight(wait_cost + transfer_penalty);
        s1.setBackMode(getMode());
        return s1.makeState();
    } else {
        /* Forward traversal: not so much to do */
        StateEditor s1 = s0.edit(this);
        TransitStop toVertex = (TransitStop) getToVertex();
        s1.alightTransit();
        s1.incrementTimeInSeconds(options.alightSlack);
        s1.setBackMode(getMode());
        return s1.makeState();
    }
}
Also used : TransitStop(org.opentripplanner.routing.vertextype.TransitStop) StateEditor(org.opentripplanner.routing.core.StateEditor) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest)

Example 45 with TransitStop

use of org.opentripplanner.routing.vertextype.TransitStop in project OpenTripPlanner by opentripplanner.

the class StreetVertexIndexServiceImpl method getNearbyTransitStops.

/**
 * Get all transit stops within a given distance of a coordinate
 */
@Override
public List<TransitStop> getNearbyTransitStops(Coordinate coordinate, double radius) {
    Envelope env = new Envelope(coordinate);
    env.expandBy(SphericalDistanceLibrary.metersToLonDegrees(radius, coordinate.y), SphericalDistanceLibrary.metersToDegrees(radius));
    List<TransitStop> nearby = getTransitStopForEnvelope(env);
    List<TransitStop> results = new ArrayList<TransitStop>();
    for (TransitStop v : nearby) {
        if (SphericalDistanceLibrary.distance(v.getCoordinate(), coordinate) <= radius) {
            results.add(v);
        }
    }
    return results;
}
Also used : TransitStop(org.opentripplanner.routing.vertextype.TransitStop) Envelope(com.vividsolutions.jts.geom.Envelope)

Aggregations

TransitStop (org.opentripplanner.routing.vertextype.TransitStop)49 Stop (org.onebusaway.gtfs.model.Stop)20 Vertex (org.opentripplanner.routing.graph.Vertex)18 Edge (org.opentripplanner.routing.graph.Edge)15 AgencyAndId (org.onebusaway.gtfs.model.AgencyAndId)13 RoutingRequest (org.opentripplanner.routing.core.RoutingRequest)12 Coordinate (com.vividsolutions.jts.geom.Coordinate)11 TripPattern (org.opentripplanner.routing.edgetype.TripPattern)11 Graph (org.opentripplanner.routing.graph.Graph)10 Envelope (com.vividsolutions.jts.geom.Envelope)8 LineString (com.vividsolutions.jts.geom.LineString)8 ArrayList (java.util.ArrayList)8 State (org.opentripplanner.routing.core.State)8 StreetEdge (org.opentripplanner.routing.edgetype.StreetEdge)8 Agency (org.onebusaway.gtfs.model.Agency)7 Trip (org.onebusaway.gtfs.model.Trip)7 SimpleTransfer (org.opentripplanner.routing.edgetype.SimpleTransfer)7 ShortestPathTree (org.opentripplanner.routing.spt.ShortestPathTree)7 IntersectionVertex (org.opentripplanner.routing.vertextype.IntersectionVertex)7 Route (org.onebusaway.gtfs.model.Route)6