Skip to content

Commit

Permalink
Use realtime availability for vehicle parking
Browse files Browse the repository at this point in the history
  • Loading branch information
richardkoszegi authored and optionsome committed Dec 17, 2021
1 parent 2331f3c commit edeabda
Show file tree
Hide file tree
Showing 14 changed files with 306 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,9 @@ public abstract class RoutingResource {
@QueryParam("pathComparator")
private String pathComparator;

@QueryParam("useVehicleParkingAvailabilityInformation")
private Boolean useVehicleParkingAvailabilityInformation;

/**
* somewhat ugly bug fix: the graphService is only needed here for fetching per-graph time zones.
* this should ideally be done when setting the routing context, but at present departure/
Expand Down Expand Up @@ -924,6 +927,10 @@ protected RoutingRequest buildRequest() throws ParameterException {
request.itineraryFilters.debug = debugItineraryFilter;
}

if (useVehicleParkingAvailabilityInformation != null) {
request.useVehicleParkingAvailabilityInformation = useVehicleParkingAvailabilityInformation;
}

//getLocale function returns defaultLocale if locale is null
request.locale = ResourceBundleSingleton.INSTANCE.getLocale(locale);
return request;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ private ApiVehicleParkingWithEntrance mapVehicleParking(VehicleParkingWithEntran
.hasWheelchairAccessibleCarPlaces(vp.hasWheelchairAccessibleCarPlaces())
.availability(mapVehicleParkingSpaces(vp.getAvailability()))
.capacity(mapVehicleParkingSpaces(vp.getCapacity()))
.realtime(vehicleParkingWithEntrance.isRealtime())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ public class ApiVehicleParkingWithEntrance {
*/
public final ApiVehicleParkingSpaces availability;

/**
* True if realtime information is used for checking availability.
*/
public final boolean realtime;

ApiVehicleParkingWithEntrance(
String id,
String name,
Expand All @@ -92,7 +97,8 @@ public class ApiVehicleParkingWithEntrance {
boolean hasCarPlaces,
boolean hasWheelchairAccessibleCarPlaces,
ApiVehicleParkingSpaces capacity,
ApiVehicleParkingSpaces availability
ApiVehicleParkingSpaces availability,
boolean realtime
) {
this.id = id;
this.name = name;
Expand All @@ -108,6 +114,7 @@ public class ApiVehicleParkingWithEntrance {
this.hasWheelchairAccessibleCarPlaces = hasWheelchairAccessibleCarPlaces;
this.capacity = capacity;
this.availability = availability;
this.realtime = realtime;
}

public static ApiVehicleParkingWithEntranceBuilder builder() {
Expand All @@ -130,6 +137,7 @@ public static class ApiVehicleParkingWithEntranceBuilder {
private boolean hasWheelchairAccessibleCarPlaces;
private ApiVehicleParkingSpaces capacity;
private ApiVehicleParkingSpaces availability;
private boolean realtime;

ApiVehicleParkingWithEntranceBuilder() {}

Expand Down Expand Up @@ -213,11 +221,19 @@ public ApiVehicleParkingWithEntranceBuilder availability(
return this;
}


public ApiVehicleParkingWithEntranceBuilder realtime(
boolean realtime
) {
this.realtime = realtime;
return this;
}

public ApiVehicleParkingWithEntrance build() {
return new ApiVehicleParkingWithEntrance(
id, name, entranceId, entranceName, detailsUrl,
imageUrl, note, tags, hasBicyclePlaces, hasAnyCarPlaces, hasCarPlaces,
hasWheelchairAccessibleCarPlaces, capacity, availability
hasWheelchairAccessibleCarPlaces, capacity, availability, realtime
);
}
}
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/org/opentripplanner/model/plan/Place.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import org.opentripplanner.model.StopLocation;
import org.opentripplanner.model.WgsCoordinate;
import org.opentripplanner.model.base.ToStringBuilder;
import org.opentripplanner.routing.vehicle_rental.VehicleRentalPlace;
import org.opentripplanner.routing.api.request.RoutingRequest;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.graph.Vertex;
import org.opentripplanner.routing.vehicle_rental.VehicleRentalPlace;
import org.opentripplanner.routing.vertextype.TransitStopVertex;
import org.opentripplanner.routing.vertextype.VehicleParkingEntranceVertex;
import org.opentripplanner.routing.vertextype.VehicleRentalStationVertex;
Expand Down Expand Up @@ -204,7 +206,16 @@ public static Place forVehicleRentalPlace(VehicleRentalStationVertex vertex, Str
);
}

public static Place forVehicleParkingEntrance(VehicleParkingEntranceVertex vertex, String name) {
public static Place forVehicleParkingEntrance(VehicleParkingEntranceVertex vertex, String name, RoutingRequest request) {
TraverseMode traverseMode = null;
if (request.streetSubRequestModes.getCar()) {
traverseMode = TraverseMode.CAR;
} else if (request.streetSubRequestModes.getBicycle()) {
traverseMode = TraverseMode.BICYCLE;
}

boolean realTime = request.useVehicleParkingAvailabilityInformation
&& vertex.getVehicleParking().hasRealTimeDataForMode(traverseMode, request.wheelchairAccessible);
return new Place(
name,
null,
Expand All @@ -217,6 +228,7 @@ public static Place forVehicleParkingEntrance(VehicleParkingEntranceVertex verte
VehicleParkingWithEntrance.builder()
.vehicleParking(vertex.getVehicleParking())
.entrance(vertex.getParkingEntrance())
.realtime(realTime)
.build()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@ public class VehicleParkingWithEntrance {

private final VehicleParkingEntrance entrance;

/**
* Was realtime data used when parking at this VehicleParking.
*/
private final boolean realtime;

VehicleParkingWithEntrance(
VehicleParking vehicleParking,
VehicleParkingEntrance entrance
VehicleParkingEntrance entrance,
boolean realtime
) {
this.vehicleParking = vehicleParking;
this.entrance = entrance;
this.realtime = realtime;
}

public VehicleParking getVehicleParking() {
Expand All @@ -25,6 +32,10 @@ public VehicleParkingEntrance getEntrance() {
return this.entrance;
}

public boolean isRealtime() {
return realtime;
}

public static VehicleParkingWithEntranceBuilder builder() {
return new VehicleParkingWithEntranceBuilder();
}
Expand All @@ -33,6 +44,7 @@ public static class VehicleParkingWithEntranceBuilder {

private VehicleParking vehicleParking;
private VehicleParkingEntrance entrance;
private boolean realtime;

VehicleParkingWithEntranceBuilder() {}

Expand All @@ -50,8 +62,15 @@ public VehicleParkingWithEntranceBuilder entrance(
return this;
}

public VehicleParkingWithEntranceBuilder realtime(
boolean realtime
) {
this.realtime = realtime;
return this;
}

public VehicleParkingWithEntrance build() {
return new VehicleParkingWithEntrance(vehicleParking, entrance);
return new VehicleParkingWithEntrance(vehicleParking, entrance, realtime);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -476,21 +476,19 @@ private static void addStreetNotes(Graph graph, Leg leg, State[] states) {
* @param states The states that go with the leg
*/
private static void addPlaces(Leg leg, State[] states, Locale requestedLocale) {
Vertex firstVertex = states[0].getVertex();
Vertex lastVertex = states[states.length - 1].getVertex();

leg.from = makePlace(firstVertex, requestedLocale);
leg.to = makePlace(lastVertex, requestedLocale);
leg.from = makePlace(states[0], requestedLocale);
leg.to = makePlace(states[states.length - 1], requestedLocale);
}

/**
* Make a {@link Place} to add to a {@link Leg}.
*
* @param vertex The {@link Vertex} at the {@link State}.
* @param state The {@link State}.
* @param requestedLocale The locale to use for all text attributes.
* @return The resulting {@link Place} object.
*/
private static Place makePlace(Vertex vertex, Locale requestedLocale) {
private static Place makePlace(State state, Locale requestedLocale) {
Vertex vertex = state.getVertex();
String name = vertex.getName(requestedLocale);

//This gets nicer names instead of osm:node:id when changing mode of transport
Expand All @@ -505,7 +503,7 @@ private static Place makePlace(Vertex vertex, Locale requestedLocale) {
} else if(vertex instanceof VehicleRentalStationVertex) {
return Place.forVehicleRentalPlace((VehicleRentalStationVertex) vertex, name);
} else if (vertex instanceof VehicleParkingEntranceVertex) {
return Place.forVehicleParkingEntrance((VehicleParkingEntranceVertex) vertex, name);
return Place.forVehicleParkingEntrance((VehicleParkingEntranceVertex) vertex, name, state.getOptions());
} else {
return Place.normal(vertex, name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,11 @@ public class RoutingRequest implements AutoCloseable, Cloneable, Serializable {

public Set<FormFactor> allowedRentalFormFactors = new HashSet<>();

/**
* If true vehicle parking availability information will be used to plan park and ride trips where it exists.
*/
public boolean useVehicleParkingAvailabilityInformation = false;

/** The function that compares paths converging on the same vertex to decide which ones continue to be explored. */
public DominanceFunction dominanceFunction = new DominanceFunction.Pareto();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected State traverseUnPark(State s0) {

private State traverseUnPark(State s0, int parkingCost, int parkingTime, TraverseMode mode) {
RoutingRequest options = s0.getOptions();
if (!isSpacesAvailable(mode, options.wheelchairAccessible)) {
if (!vehicleParking.hasSpacesAvailable(mode, options.wheelchairAccessible, options.useVehicleParkingAvailabilityInformation)) {
return null;
}

Expand Down Expand Up @@ -100,7 +100,7 @@ private State traversePark(State s0) {
private State traversePark(State s0, int parkingCost, int parkingTime) {
RoutingRequest options = s0.getOptions();

if (!isSpacesAvailable(s0.getNonTransitMode(), options.wheelchairAccessible)) {
if (!vehicleParking.hasSpacesAvailable(s0.getNonTransitMode(), options.wheelchairAccessible, options.useVehicleParkingAvailabilityInformation)) {
return null;
}

Expand All @@ -111,17 +111,6 @@ private State traversePark(State s0, int parkingCost, int parkingTime) {
return s0e.makeState();
}

private boolean isSpacesAvailable(TraverseMode traverseMode, boolean wheelchairAccessible) {
switch (traverseMode) {
case BICYCLE:
return vehicleParking.hasBicyclePlaces();
case CAR:
return wheelchairAccessible ? vehicleParking.hasWheelchairAccessibleCarPlaces() : vehicleParking.hasCarPlaces();
default:
return false;
}
}

@Override
public double getDistanceMeters() {
return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Objects;
import java.util.Set;
import org.opentripplanner.model.FeedScopedId;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.util.I18NString;

/**
Expand Down Expand Up @@ -190,6 +191,51 @@ public boolean hasRealTimeData() {
return availability != null;
}

public boolean hasSpacesAvailable(TraverseMode traverseMode, boolean wheelchairAccessible, boolean useAvailability) {
switch (traverseMode) {
case BICYCLE:
if (useAvailability && hasRealTimeDataForMode(TraverseMode.BICYCLE, false)) {
return availability.getBicycleSpaces() > 0;
} else {
return bicyclePlaces;
}
case CAR:
if (wheelchairAccessible) {
if (useAvailability && hasRealTimeDataForMode(TraverseMode.CAR, true)) {
return availability.getWheelchairAccessibleCarSpaces() > 0;
} else {
return wheelchairAccessibleCarPlaces;
}
} else {
if (useAvailability && hasRealTimeDataForMode(TraverseMode.CAR, false)) {
return availability.getCarSpaces() > 0;
} else {
return carPlaces;
}
}
default:
return false;
}
}

public boolean hasRealTimeDataForMode(TraverseMode traverseMode, boolean wheelchairAccessibleCarPlaces) {
if (availability == null) {
return false;
}

switch (traverseMode) {
case BICYCLE:
return availability.getBicycleSpaces() != null;
case CAR:
var places = wheelchairAccessibleCarPlaces
? availability.getWheelchairAccessibleCarSpaces()
: availability.getCarSpaces();
return places != null;
default:
return false;
}
}

public void updateAvailability(VehicleParkingSpaces vehicleParkingSpaces) {
this.availability = vehicleParkingSpaces;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public static RoutingRequest mapRoutingRequest(NodeAdapter c) {
request.setTransitReluctanceForMode(c.asEnumMap("transitReluctanceForMode", TransitMode.class, NodeAdapter::asDouble));
request.turnReluctance = c.asDouble("turnReluctance", dft.turnReluctance);
request.useVehicleRentalAvailabilityInformation = c.asBoolean("useBikeRentalAvailabilityInformation", dft.useVehicleRentalAvailabilityInformation);
request.useVehicleParkingAvailabilityInformation = c.asBoolean("useVehicleParkingAvailabilityInformation", dft.useVehicleParkingAvailabilityInformation);
request.useUnpreferredRoutesPenalty = c.asInt("useUnpreferredRoutesPenalty", dft.useUnpreferredRoutesPenalty);
request.vehicleRental = c.asBoolean("allowBikeRental", dft.vehicleRental);
request.waitAtBeginningFactor = c.asDouble("waitAtBeginningFactor", dft.waitAtBeginningFactor);
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/org/opentripplanner/updater/DataSourceType.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ public enum DataSourceType {
GBFS,
SMOOVE,

// Vehicle Parking
KML,

// GTFS RT
GTFS_RT_HTTP,
GTFS_RT_FILE;
Expand Down
Loading

0 comments on commit edeabda

Please sign in to comment.