Skip to content

Commit

Permalink
fix: architecture and use currentRangeMeters via State
Browse files Browse the repository at this point in the history
  • Loading branch information
UserX20 committed Jul 9, 2024
1 parent 954c3d8 commit 758ffe8
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package org.opentripplanner.astar.strategy;

import java.util.Optional;
import java.util.function.Predicate;
import org.opentripplanner.astar.spi.AStarEdge;
import org.opentripplanner.astar.spi.AStarState;
import org.opentripplanner.astar.spi.SkipEdgeStrategy;
import org.opentripplanner.service.vehiclerental.street.StreetVehicleRentalLink;

/**
* Skips Edges when the available battery distance of a vehicle is less than the accumulated driving
Expand All @@ -15,19 +14,14 @@ public class BatteryDistanceSkipEdgeStrategy<
>
implements SkipEdgeStrategy<State, Edge> {

private final Predicate<State> shouldSkip;

public BatteryDistanceSkipEdgeStrategy(Predicate<State> shouldSkip) {
this.shouldSkip = shouldSkip;
}

@Override
public boolean shouldSkipEdge(State current, Edge edge) {
if (edge instanceof StreetVehicleRentalLink) {
Optional<Double> currentRangeMeters =
((StreetVehicleRentalLink) edge).getCurrentRangeMeters();

if (currentRangeMeters.isEmpty()) {
return false;
}
double batteryDistance =
((org.opentripplanner.street.search.state.State) current).batteryDistance;
return currentRangeMeters.get() < batteryDistance;
}
return false;
return shouldSkip.test(current);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.opentripplanner.routing.impl;

import java.util.Optional;
import org.opentripplanner.street.search.state.State;

public class BatteryValidator {

public static boolean wouldBatteryRunOut(Object current) {
double drivenBatteryMeters =
((org.opentripplanner.street.search.state.State) current).drivenBatteryMeters;
Optional<Double> currentRangeMeters = ((State) current).currentRangeMeters;
if (currentRangeMeters.isEmpty()) {
return false;
}
return currentRangeMeters.get() < drivenBatteryMeters;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public List<GraphPath<State, Edge, Vertex>> getPaths(
new DurationSkipEdgeStrategy(
preferences.maxDirectDuration().valueOf(request.journey().direct().mode())
),
new BatteryDistanceSkipEdgeStrategy()
new BatteryDistanceSkipEdgeStrategy(BatteryValidator::wouldBatteryRunOut)
)
)
// FORCING the dominance function to weight only
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package org.opentripplanner.service.vehiclerental.street;

import java.util.Optional;
import javax.annotation.Nonnull;
import org.opentripplanner.framework.i18n.I18NString;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle;
import org.opentripplanner.street.model.edge.Edge;
import org.opentripplanner.street.model.vertex.StreetVertex;
import org.opentripplanner.street.search.state.State;
import org.opentripplanner.street.search.state.StateEditor;
import org.opentripplanner.transit.model.framework.FeedScopedId;

/**
* This represents the connection between a street vertex and a bike rental station vertex.
Expand Down Expand Up @@ -74,11 +71,4 @@ public State[] traverse(State s0) {
public I18NString getName() {
return vehicleRentalPlaceVertex.getName();
}

public Optional<Double> getCurrentRangeMeters() {
if (vehicleRentalPlaceVertex.getStation() instanceof VehicleRentalVehicle) {
return ((VehicleRentalVehicle) vehicleRentalPlaceVertex.getStation()).getCurrentRangeMeters();
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package org.opentripplanner.service.vehiclerental.street;

import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nonnull;
import org.opentripplanner.framework.i18n.I18NString;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalPlace;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle;
import org.opentripplanner.street.model.RentalFormFactor;
import org.opentripplanner.street.model.edge.Edge;
import org.opentripplanner.street.search.state.State;
Expand All @@ -19,10 +21,12 @@
public class VehicleRentalEdge extends Edge {

public final RentalFormFactor formFactor;
private final VehicleRentalPlaceVertex vertex;

private VehicleRentalEdge(VehicleRentalPlaceVertex vertex, RentalFormFactor formFactor) {
super(vertex, vertex);
this.formFactor = formFactor;
this.vertex = vertex;
}

public static VehicleRentalEdge createVehicleRentalEdge(
Expand Down Expand Up @@ -169,6 +173,7 @@ public State[] traverse(State s0) {
? (int) preferences.pickupTime().toSeconds()
: (int) preferences.dropOffTime().toSeconds()
);
s1.setCurrentRangeMeters(getCurrentRangeMeters());
s1.setBackMode(null);
return s1.makeStateArray();
}
Expand Down Expand Up @@ -206,4 +211,11 @@ private static Set<RentalFormFactor> allowedModes(StreetMode streetMode) {
default -> Set.of();
};
}

public Optional<Double> getCurrentRangeMeters() {
if (vertex.getStation() instanceof VehicleRentalVehicle) {
return ((VehicleRentalVehicle) vertex.getStation()).getCurrentRangeMeters();
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@ private StateEditor doTraverse(State s0, TraverseMode traverseMode, boolean walk
}

if (traverseMode.isCyclingIsh() && s1.isVehicleRentable()) {
s1.incrementBatteryDistance(getDistanceWithElevation());
s1.incrementDrivenBatteryMeters(getDistanceWithElevation());
}

if (costExtension != null) {
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/org/opentripplanner/street/search/state/State.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
Expand Down Expand Up @@ -52,8 +53,11 @@ public class State implements AStarState<State, Edge, Vertex>, Cloneable {
// we should DEFINITELY rename this variable and the associated methods.
public double walkDistance;

// how far a vehicle powered by battery has driven
public double batteryDistance;
// how far a sharing vehicle powered by battery has driven
public double drivenBatteryMeters;

//the available battery distance of a currently selected sharing vehicle
public Optional<Double> currentRangeMeters;

/* CONSTRUCTORS */

Expand Down Expand Up @@ -85,7 +89,8 @@ public State(
vertex.rentalRestrictions().noDropOffNetworks();
}
this.walkDistance = 0;
this.batteryDistance = 0;
this.drivenBatteryMeters = 0;
this.currentRangeMeters = Optional.empty();
this.time = startTime.getEpochSecond();
}

Expand Down Expand Up @@ -364,7 +369,8 @@ public State reverse() {
editor.incrementTimeInSeconds(orig.getAbsTimeDeltaSeconds());
editor.incrementWeight(orig.getWeightDelta());
editor.incrementWalkDistance(orig.getWalkDistanceDelta());
editor.incrementBatteryDistance(orig.getBatteryDistanceDelta());
editor.incrementDrivenBatteryMeters(orig.getBatteryDistanceDelta());
editor.setCurrentRangeMeters(orig.getCurrentRangeMeters());

// propagate the modes through to the reversed edge
editor.setBackMode(orig.getBackMode());
Expand Down Expand Up @@ -510,12 +516,20 @@ private double getWalkDistanceDelta() {

private double getBatteryDistanceDelta() {
if (backState != null) {
return Math.abs(this.batteryDistance - backState.batteryDistance);
return Math.abs(this.drivenBatteryMeters - backState.drivenBatteryMeters);
} else {
return 0.0;
}
}

private Optional<Double> getCurrentRangeMeters() {
if (backState != null) {
return backState.currentRangeMeters;
} else {
return Optional.empty();
}
}

private State reversedClone() {
StreetSearchRequest reversedRequest = request
.copyOfReversed(getTime())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.opentripplanner.street.search.state;

import java.util.Optional;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -196,13 +197,17 @@ public void incrementWalkDistance(double length) {
child.walkDistance += length;
}

public void incrementBatteryDistance(double length) {
public void incrementDrivenBatteryMeters(double length) {
if (length < 0) {
LOG.warn("A state's battery distance is being incremented by a negative amount.");
defectiveTraversal = true;
return;
}
child.batteryDistance += length;
child.drivenBatteryMeters += length;
}

public void setCurrentRangeMeters(Optional<Double> currentRangeMeters) {
child.currentRangeMeters = currentRangeMeters;
}

/* Basic Setters */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.locationtech.jts.geom.Coordinate;
import org.opentripplanner.routing.algorithm.GraphRoutingTest;
import org.opentripplanner.service.vehiclerental.model.VehicleRentalVehicle;
import org.opentripplanner.service.vehiclerental.street.StreetVehicleRentalLink;
import org.opentripplanner.service.vehiclerental.street.VehicleRentalPlaceVertex;
import org.opentripplanner.street.model.edge.FreeEdge;
import org.opentripplanner.street.model.vertex.SimpleVertex;
import org.opentripplanner.street.model.vertex.StreetLocation;
import org.opentripplanner.routing.impl.BatteryValidator;
import org.opentripplanner.street.search.state.State;
import org.opentripplanner.street.search.state.TestStateBuilder;

Expand All @@ -23,15 +18,13 @@ public class BatteryDistanceSkipEdgeStrategyTest extends GraphRoutingTest {
*/
@Test
void batteryIsNotEnough() {
var vertex = new SimpleVertex(null, -74.01, 40.01);

var edge = getStreetVehicleRentalLink(0.0, vertex);

var state = getState(100.0);

var strategy = new BatteryDistanceSkipEdgeStrategy();
state.currentRangeMeters = Optional.of(0.0);

var strategy = new BatteryDistanceSkipEdgeStrategy(BatteryValidator::wouldBatteryRunOut);

assertTrue(strategy.shouldSkipEdge(state, edge));
assertTrue(strategy.shouldSkipEdge(state, null));
}

/**
Expand All @@ -40,14 +33,11 @@ void batteryIsNotEnough() {
*/
@Test
void batteryIsEnough() {
var vertex = new SimpleVertex(null, -74.01, 40.01);

var edge = getStreetVehicleRentalLink(4000.0, vertex);

var state = getState(100.0);
state.currentRangeMeters = Optional.of(4000.0);

var strategy = new BatteryDistanceSkipEdgeStrategy();
assertFalse(strategy.shouldSkipEdge(state, edge));
var strategy = new BatteryDistanceSkipEdgeStrategy(BatteryValidator::wouldBatteryRunOut);
assertFalse(strategy.shouldSkipEdge(state, null));
}

/**
Expand All @@ -56,14 +46,12 @@ void batteryIsEnough() {
*/
@Test
void batteryDiesAtFinalLocation() {
var vertex = new SimpleVertex(null, -74.01, 40.01);

var edge = getStreetVehicleRentalLink(100.0, vertex);

var state = getState(100.0);

var strategy = new BatteryDistanceSkipEdgeStrategy();
assertFalse(strategy.shouldSkipEdge(state, edge));
state.currentRangeMeters = Optional.of(100.0);

var strategy = new BatteryDistanceSkipEdgeStrategy(BatteryValidator::wouldBatteryRunOut);
assertFalse(strategy.shouldSkipEdge(state, null));
}

/**
Expand All @@ -72,28 +60,11 @@ void batteryDiesAtFinalLocation() {
*/
@Test
void noDrivenMeters() {
var vertex = new SimpleVertex(null, -74.01, 40.01);

var edge = getStreetVehicleRentalLink(100.0, vertex);

var state = getState(0.0);
state.currentRangeMeters = Optional.of(100.0);

var strategy = new BatteryDistanceSkipEdgeStrategy();
assertFalse(strategy.shouldSkipEdge(state, edge));
}

/**
* Edge is of wrong Type (not StreetVehicleLink) -> does not skip Edge
* edge is no StreetVehicleRentalLink => false
*/
@Test
void edgeIsOfWrongType() {
var from = new StreetLocation(null, new Coordinate(0.0, 0.0), null);
var to = new StreetLocation(null, new Coordinate(1.0, 1.0), null);
var edge = FreeEdge.createFreeEdge(from, to);
var state = TestStateBuilder.ofScooterRental().build();
var strategy = new BatteryDistanceSkipEdgeStrategy();
assertFalse(strategy.shouldSkipEdge(state, edge));
var strategy = new BatteryDistanceSkipEdgeStrategy(BatteryValidator::wouldBatteryRunOut);
assertFalse(strategy.shouldSkipEdge(state, null));
}

/**
Expand All @@ -102,35 +73,16 @@ void edgeIsOfWrongType() {
*/
@Test
void batteryHasNoValue() {
var vertex = new SimpleVertex(null, -74.01, 40.01);

var vehicle = new VehicleRentalVehicle();
vehicle.currentRangeMeters = null;

var rentalVertex = new VehicleRentalPlaceVertex(vehicle);

var edge = StreetVehicleRentalLink.createStreetVehicleRentalLink(vertex, rentalVertex);

var state = TestStateBuilder.ofScooterRental().build();
state.currentRangeMeters = Optional.empty();

var strategy = new BatteryDistanceSkipEdgeStrategy();
assertFalse(strategy.shouldSkipEdge(state, edge));
}

private static StreetVehicleRentalLink getStreetVehicleRentalLink(
double currentRangeMeters,
SimpleVertex vertex
) {
var vehicle = new VehicleRentalVehicle();
vehicle.currentRangeMeters = currentRangeMeters;
var rentalVertex = new VehicleRentalPlaceVertex(vehicle);
var edge = StreetVehicleRentalLink.createStreetVehicleRentalLink(vertex, rentalVertex);
return edge;
var strategy = new BatteryDistanceSkipEdgeStrategy(BatteryValidator::wouldBatteryRunOut);
assertFalse(strategy.shouldSkipEdge(state, null));
}

private static State getState(double batteryDistance) {
private static State getState(double drivenBatteryMetters) {
var state = TestStateBuilder.ofScooterRental().build();
state.batteryDistance = batteryDistance;
state.drivenBatteryMeters = drivenBatteryMetters;
return state;
}
}

0 comments on commit 758ffe8

Please sign in to comment.