Skip to content

Commit

Permalink
Initial support for origMode and destMode. #1042 #865.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Conway committed Apr 11, 2013
1 parent c350cd7 commit 6d02b74
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 12 deletions.
Expand Up @@ -26,6 +26,7 @@ the License, or (at your option) any later version.
import org.onebusaway.gtfs.model.AgencyAndId;
import org.opentripplanner.routing.core.OptimizeType;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.request.BannedStopSet;
import org.opentripplanner.routing.services.GraphService;
Expand Down Expand Up @@ -100,6 +101,16 @@ public abstract class RoutingResource {

/** The set of modes that a user is willing to use. */
@DefaultValue("TRANSIT,WALK") @QueryParam("mode") protected List<TraverseModeSet> modes;

// no default values for these two, they should be null if not specified (they're then
// reconstructed in RoutingRequest)
/** The mode at the origin, filled in automatically from modeset if not specified */
@QueryParam("origMode") protected List<TraverseMode> origMode;

/** The mode at the destination, filled in automatically based on overall modeset
* if not specified */
@QueryParam("destMode") protected List<TraverseMode> destMode;


/** The minimum time, in seconds, between successive trips on different vehicles.
* This is designed to allow for imperfect schedule adherence. This is a minimum;
Expand Down Expand Up @@ -318,6 +329,9 @@ protected RoutingRequest buildRequest(int n) throws ParameterException {
request.setOptimize(opt);
TraverseModeSet modeSet = get(modes, n, request.getModes());
request.setModes(modeSet);
request.setOrigMode(get(origMode, n, request.getOrigMode()));
request.setDestMode(get(destMode, n, request.getDestMode()));

if (modeSet.getBicycle() && modeSet.getWalk() && bikeSpeedParam == -1) {
//slower bike speed for bike sharing, based on empirical evidence from DC.
request.setBikeSpeed(4.3);
Expand Down
Expand Up @@ -101,6 +101,12 @@ public class RoutingRequest implements Cloneable, Serializable {
/** The set of TraverseModes that a user is willing to use. Defaults to WALK | TRANSIT. */
public TraverseModeSet modes = new TraverseModeSet("TRANSIT,WALK"); // defaults in constructor

/** The mode at the origin of the trip */
public TraverseMode origMode = null;

/** The mode at the destination of the trip */
public TraverseMode destMode = null;

/** The set of characteristics that the user wants to optimize for -- defaults to QUICK, or optimize for transit time. */
public OptimizeType optimize = OptimizeType.QUICK;

Expand Down Expand Up @@ -387,6 +393,8 @@ public void setMode(TraverseMode mode) {

public void setModes(TraverseModeSet modes) {
this.modes = modes;

// TODO: how do origin and destination modes affect walking bikes?
if (modes.getBicycle()) {
bikeWalkingOptions = new RoutingRequest();
bikeWalkingOptions.setArriveBy(this.isArriveBy());
Expand All @@ -398,14 +406,42 @@ public void setModes(TraverseModeSet modes) {
bikeWalkingOptions.modes.setBicycle(false);
bikeWalkingOptions.modes.setWalk(true);
bikeWalkingOptions.walkingBike = true;
bikeWalkingOptions.guessModes();
} else if (modes.getDriving()) {
bikeWalkingOptions = new RoutingRequest();
bikeWalkingOptions.setArriveBy(this.isArriveBy());
bikeWalkingOptions.maxWalkDistance = maxWalkDistance;
bikeWalkingOptions.modes = modes.clone();
bikeWalkingOptions.modes.setBicycle(false);
bikeWalkingOptions.modes.setWalk(true);
bikeWalkingOptions.guessModes();
}

this.guessModes();
}

/** Guess the origMode and destMode, if not specified */
public void guessModes() {
TraverseMode nonTransitMode;
// This code used to be in the constructor for StateData
if (modes.getCar())
nonTransitMode = TraverseMode.CAR;
else if (modes.getCustomMotorVehicle())
nonTransitMode = TraverseMode.CUSTOM_MOTOR_VEHICLE;
else if (modes.getWalk())
nonTransitMode = TraverseMode.WALK;
else if (modes.getBicycle())
nonTransitMode = TraverseMode.BICYCLE;
else
nonTransitMode = null;

if (this.origMode == null)
this.origMode = nonTransitMode;

if (this.destMode == null)
this.destMode = nonTransitMode;

return;
}

public void setOptimize(OptimizeType optimize) {
Expand Down
Expand Up @@ -236,10 +236,12 @@ public boolean isBikeRenting() {
}

/**
* Check to make sure that a) any rented bikes have been returned and b) the mode is correct
* for the destination
* @return True if the state at vertex can be the end of path.
*/
public boolean isFinal() {
return !isBikeRenting();
return (!isBikeRenting() && stateData.nonTransitMode.equals(stateData.lastMode));
}

public Vertex getPreviousStop() {
Expand Down
Expand Up @@ -94,21 +94,20 @@ public class StateData implements Cloneable {
* The mode that was used to traverse the backEdge
*/
protected TraverseMode backMode;

/**
* The mode that should be in use at the end of this SPT (already corrected for arriveBy, so
* a value of WALK indicates that the user should be walking at the edges of the SPT,
* regardless of whether that represents the origin or the destination)
*/
protected TraverseMode lastMode;

public Set<String> bikeRentalNetworks;

public StateData(RoutingRequest options) {
TraverseModeSet modes = options.getModes();
if (modes.getCar())
nonTransitMode = TraverseMode.CAR;
else if (modes.getCustomMotorVehicle())
nonTransitMode = TraverseMode.CUSTOM_MOTOR_VEHICLE;
else if (modes.getWalk())
nonTransitMode = TraverseMode.WALK;
else if (modes.getBicycle())
nonTransitMode = TraverseMode.BICYCLE;
else
nonTransitMode = null;
// Set the non-transit mode to the mode at the proper vertex
nonTransitMode = options.arriveBy ? options.destMode : options.origMode;
lastMode = options.arriveBy ? options.origMode : options.destMode;
}

protected StateData clone() {
Expand Down
Expand Up @@ -560,4 +560,15 @@ public void setBikeRentalNetwork(Set<String> networks) {
cloneStateDataAsNeeded();
child.stateData.bikeRentalNetworks = networks;
}

/**
* Set the non-transit mode for this state and its children.
* @param mode
*/
public void setNonTransitMode(TraverseMode mode) {
// TODO: should we have a check to make sure the mode is in the allowed modes, or assume
// that anyone who changes the mode knows what they're doing?
cloneStateDataAsNeeded();
child.stateData.nonTransitMode = mode;
}
}
@@ -0,0 +1,103 @@
/* This program is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */

package org.opentripplanner.routing.edgetype;

import lombok.Getter;

import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.core.State;
import org.opentripplanner.routing.core.StateEditor;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.graph.Edge;
import org.opentripplanner.routing.graph.Vertex;

/**
* An edge that allows switching modes, e.g. parking, renting or returning a bike or automobile.
* @author mattwigway
*/
public class ModeSwitchEdge extends Edge {
private static final long serialVersionUID = 20130410L;

/** The modes that this edge switches from and to */
@Getter
private TraverseMode fromMode, toMode;

/** The cost of switching */
@Getter
private float traverseWeight;

/** The time, in seconds, to switch modes */
@Getter
private int traverseTime;

/**
* Create a new mode switching edge
* @param v The vertex to which to attach (ModeSwitchEdges are loop edges)
* @param fromMode The mode that the edge switches from
* @param toMode The mode that the edge switches to
* @param traverseCost The traversal cost of the edge
* @param traverseTime The traversal time of the edge, in seconds
*/
public ModeSwitchEdge(Vertex v, TraverseMode fromMode, TraverseMode toMode, float traverseWeight, int traverseTime) {
super(v, v);
this.fromMode = fromMode;
this.toMode = toMode;
this.traverseWeight = traverseWeight;
this.traverseTime = traverseTime;
}

@Override
public State traverse(State s0) {
// we use non-transit mode because this is never called when the user is on transit
TraverseMode mode = s0.getNonTransitMode();
RoutingRequest options = s0.getOptions();
TraverseModeSet modes = options.getModes();
boolean arriveBy = options.isArriveBy();

// Checks: Make sure that the mode we are switching to (the toMode in a forward search)
// is in the allowed modes, and that the current mode matches the mode we are switching
// (the fromMode in a forward search). Everything is backwards in a reverse search.
if (!arriveBy) {
if (!this.fromMode.equals(mode) || !modes.contains(toMode)) {
return null;
}
}

if (arriveBy) {
if (!this.toMode.equals(mode) || !modes.contains(fromMode)) {
return null;
}
}

StateEditor s1 = s0.edit(this);

if (arriveBy)
s1.setNonTransitMode(fromMode);
else
s1.setNonTransitMode(toMode);

s1.incrementWeight(traverseWeight);
s1.incrementTimeInSeconds(traverseTime);

return s1.makeState();

}

@Override
public String getName() {
return "ModeSwitchEdge<" + fromMode + " to " + toMode + ">";
}

}

0 comments on commit 6d02b74

Please sign in to comment.