use of org.opentripplanner.routing.core.RoutingRequest in project OpenTripPlanner by opentripplanner.
the class GraphPathFinder method createReversedTransitRequest.
private RoutingRequest createReversedTransitRequest(RoutingRequest originalReq, RoutingRequest options, Vertex fromVertex, Vertex toVertex, long arrDepTime, RemainingWeightHeuristic remainingWeightHeuristic) {
RoutingRequest request = createReversedRequest(originalReq, options, fromVertex, toVertex, arrDepTime, new EuclideanRemainingWeightHeuristic());
if ((originalReq.parkAndRide || originalReq.kissAndRide) && !originalReq.arriveBy) {
request.parkAndRide = false;
request.kissAndRide = false;
request.modes.setCar(false);
}
request.maxWalkDistance = CLAMP_MAX_WALK;
return request;
}
use of org.opentripplanner.routing.core.RoutingRequest in project OpenTripPlanner by opentripplanner.
the class GraphPathFinder method getPaths.
/**
* Repeatedly build shortest path trees, retaining the best path to the destination after each try.
* For search N, all trips used in itineraries retained from trips 0..(N-1) are "banned" to create variety.
* The goal direction heuristic is reused between tries, which means the later tries have more information to
* work with (in the case of the more sophisticated bidirectional heuristic, which improves over time).
*/
public List<GraphPath> getPaths(RoutingRequest options) {
RoutingRequest originalReq = options.clone();
if (options == null) {
LOG.error("PathService was passed a null routing request.");
return null;
}
// Reuse one instance of AStar for all N requests, which are carried out sequentially
AStar aStar = new AStar();
if (options.rctx == null) {
options.setRoutingContext(router.graph);
// The special long-distance heuristic should be sufficient to constrain the search to the right area.
}
// If this Router has a GraphVisualizer attached to it, set it as a callback for the AStar search
if (router.graphVisualizer != null) {
aStar.setTraverseVisitor(router.graphVisualizer.traverseVisitor);
// options.disableRemainingWeightHeuristic = true; // DEBUG
}
// Without transit, we'd just just return multiple copies of the same on-street itinerary.
if (!options.modes.isTransit()) {
options.numItineraries = 1;
}
// FORCING the dominance function to weight only
options.dominanceFunction = new DominanceFunction.MinimumWeight();
LOG.debug("rreq={}", options);
// Choose an appropriate heuristic for goal direction.
RemainingWeightHeuristic heuristic;
RemainingWeightHeuristic reversedSearchHeuristic;
if (options.disableRemainingWeightHeuristic) {
heuristic = new TrivialRemainingWeightHeuristic();
reversedSearchHeuristic = new TrivialRemainingWeightHeuristic();
} else if (options.modes.isTransit()) {
// Only use the BiDi heuristic for transit. It is not very useful for on-street modes.
// heuristic = new InterleavedBidirectionalHeuristic(options.rctx.graph);
// Use a simplistic heuristic until BiDi heuristic is improved, see #2153
heuristic = new InterleavedBidirectionalHeuristic();
reversedSearchHeuristic = new InterleavedBidirectionalHeuristic();
} else {
heuristic = new EuclideanRemainingWeightHeuristic();
reversedSearchHeuristic = new EuclideanRemainingWeightHeuristic();
}
options.rctx.remainingWeightHeuristic = heuristic;
/* In RoutingRequest, maxTransfers defaults to 2. Over long distances, we may see
* itineraries with far more transfers. We do not expect transfer limiting to improve
* search times on the LongDistancePathService, so we set it to the maximum we ever expect
* to see. Because people may use either the traditional path services or the
* LongDistancePathService, we do not change the global default but override it here. */
options.maxTransfers = 4;
// Now we always use what used to be called longDistance mode. Non-longDistance mode is no longer supported.
options.longDistance = true;
/* In long distance mode, maxWalk has a different meaning than it used to.
* It's the radius around the origin or destination within which you can walk on the streets.
* If no value is provided, max walk defaults to the largest double-precision float.
* This would cause long distance mode to do unbounded street searches and consider the whole graph walkable. */
if (options.maxWalkDistance == Double.MAX_VALUE)
options.maxWalkDistance = DEFAULT_MAX_WALK;
if (options.maxWalkDistance > CLAMP_MAX_WALK)
options.maxWalkDistance = CLAMP_MAX_WALK;
long searchBeginTime = System.currentTimeMillis();
LOG.debug("BEGIN SEARCH");
List<GraphPath> paths = Lists.newArrayList();
while (paths.size() < options.numItineraries) {
// TODO pull all this timeout logic into a function near org.opentripplanner.util.DateUtils.absoluteTimeout()
int timeoutIndex = paths.size();
if (timeoutIndex >= router.timeouts.length) {
timeoutIndex = router.timeouts.length - 1;
}
double timeout = searchBeginTime + (router.timeouts[timeoutIndex] * 1000);
// Convert from absolute to relative time
timeout -= System.currentTimeMillis();
// Convert milliseconds to seconds
timeout /= 1000;
if (timeout <= 0) {
// Catch the case where advancing to the next (lower) timeout value means the search is timed out
// before it even begins. Passing a negative relative timeout in the SPT call would mean "no timeout".
options.rctx.aborted = true;
break;
}
// Don't dig through the SPT object, just ask the A star algorithm for the states that reached the target.
aStar.getShortestPathTree(options, timeout);
if (options.rctx.aborted) {
// Search timed out or was gracefully aborted for some other reason.
break;
}
List<GraphPath> newPaths = aStar.getPathsToTarget();
if (newPaths.isEmpty()) {
break;
}
// Do a full reversed search to compact the legs
if (options.compactLegsByReversedSearch) {
newPaths = compactLegsByReversedSearch(aStar, originalReq, options, newPaths, timeout, reversedSearchHeuristic);
}
// Find all trips used in this path and ban them for the remaining searches
for (GraphPath path : newPaths) {
// path.dump();
List<AgencyAndId> tripIds = path.getTrips();
for (AgencyAndId tripId : tripIds) {
options.banTrip(tripId);
}
if (tripIds.isEmpty()) {
// This path does not use transit (is entirely on-street). Do not repeatedly find the same one.
options.onlyTransitTrips = true;
}
}
paths.addAll(newPaths.stream().filter(path -> {
double duration = options.useRequestedDateTimeInMaxHours ? options.arriveBy ? options.dateTime - path.getStartTime() : path.getEndTime() - options.dateTime : path.getDuration();
return duration < options.maxHours * 60 * 60;
}).collect(Collectors.toList()));
LOG.debug("we have {} paths", paths.size());
}
LOG.debug("END SEARCH ({} msec)", System.currentTimeMillis() - searchBeginTime);
Collections.sort(paths, new PathComparator(options.arriveBy));
return paths;
}
use of org.opentripplanner.routing.core.RoutingRequest in project OpenTripPlanner by opentripplanner.
the class StreetTransitLink method traverse.
public State traverse(State s0) {
// Forbid taking shortcuts composed of two street-transit links in a row. Also avoids spurious leg transitions.
if (s0.backEdge instanceof StreetTransitLink) {
return null;
}
// Do not re-enter the street network following a transfer.
if (s0.backEdge instanceof SimpleTransfer) {
return null;
}
RoutingRequest req = s0.getOptions();
if (s0.getOptions().wheelchairAccessible && !wheelchairAccessible) {
return null;
}
if (s0.getOptions().bikeParkAndRide && !s0.isBikeParked()) {
// Forbid taking your own bike in the station if bike P+R activated.
return null;
}
if (s0.isBikeRenting()) {
// TODO Check this condition, does this always make sense?
return null;
}
// Do not check here whether any transit modes are selected. A check for the presence of
// transit modes will instead be done in the following PreBoard edge.
// This allows searching for nearby transit stops using walk-only options.
StateEditor s1 = s0.edit(this);
/* Note that in arriveBy searches this is double-traversing link edges to fork the state into both WALK and CAR mode. This is an insane hack. */
if (s0.getNonTransitMode() == TraverseMode.CAR) {
if (req.kissAndRide && !s0.isCarParked()) {
s1.setCarParked(true);
} else {
return null;
}
}
s1.incrementTimeInSeconds(transitStop.getStreetToStopTime() + STL_TRAVERSE_COST);
s1.incrementWeight(STL_TRAVERSE_COST + transitStop.getStreetToStopTime());
s1.setBackMode(TraverseMode.LEG_SWITCH);
return s1.makeState();
}
use of org.opentripplanner.routing.core.RoutingRequest in project OpenTripPlanner by opentripplanner.
the class TripPattern method getResolvedTripTimes.
public TripTimes getResolvedTripTimes(int tripIndex, State state0) {
ServiceDay serviceDay = state0.getServiceDay();
RoutingRequest options = state0.getOptions();
Timetable timetable = getUpdatedTimetable(options, serviceDay);
return timetable.getTripTimes(tripIndex);
}
use of org.opentripplanner.routing.core.RoutingRequest in project OpenTripPlanner by opentripplanner.
the class PreBoardEdge 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) fromv).getStop())) {
return null;
}
}
if (!options.bannedStopsHard.isEmpty()) {
if (options.bannedStopsHard.matches(((TransitStop) fromv).getStop())) {
return null;
}
}
if (options.arriveBy) {
/* Traverse backward: not much to do */
StateEditor s1 = s0.edit(this);
TransitStop fromVertex = (TransitStop) getFromVertex();
// apply board slack
s1.incrementTimeInSeconds(options.boardSlack);
s1.alightTransit();
s1.setBackMode(getMode());
return s1.makeState();
} else {
// options can be used to find transit stops without boarding vehicles.
if (!options.modes.isTransit())
return null;
// 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.alightSlack;
} else {
slack = options.boardSlack;
}
long board_after = t0 + slack;
long 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(board_after);
long wait_cost = board_after - t0;
s1.incrementWeight(wait_cost + transfer_penalty);
s1.setBackMode(getMode());
return s1.makeState();
}
}
Aggregations