Skip to content

Commit

Permalink
Add Set of StreetModes to PathTransfer and other changes related to it.
Browse files Browse the repository at this point in the history
  • Loading branch information
VillePihlava committed Nov 26, 2024
1 parent 8951c60 commit 2215154
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import com.google.common.collect.Multimaps;
import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.opentripplanner.framework.application.OTPFeature;
import org.opentripplanner.graph_builder.issue.api.DataImportIssueStore;
Expand All @@ -17,6 +19,7 @@
import org.opentripplanner.graph_builder.module.nearbystops.StreetNearbyStopFinder;
import org.opentripplanner.model.PathTransfer;
import org.opentripplanner.routing.api.request.RouteRequest;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.graphfinder.NearbyStop;
import org.opentripplanner.street.model.edge.Edge;
Expand Down Expand Up @@ -102,6 +105,7 @@ public void buildGraph() {
LOG.debug("Linking stop '{}' {}", stop, ts0);

for (RouteRequest transferProfile : transferRequests) {
StreetMode mode = transferProfile.journey().transfer().mode();
for (NearbyStop sd : nearbyStopFinder.findNearbyStops(
ts0,
transferProfile,
Expand All @@ -115,12 +119,12 @@ public void buildGraph() {
if (sd.stop.transfersNotAllowed()) {
continue;
}
distinctTransfers.put(
new TransferKey(stop, sd.stop, sd.edges),
new PathTransfer(stop, sd.stop, sd.distance, sd.edges)
);
createPathTransfer(distinctTransfers, sd, stop, mode);
}
if (OTPFeature.FlexRouting.isOn()) {
}
if (OTPFeature.FlexRouting.isOn()) {
for (RouteRequest transferProfile : transferRequests) {
StreetMode mode = transferProfile.journey().transfer().mode();
// This code is for finding transfers from AreaStops to Stops, transfers
// from Stops to AreaStops and between Stops are already covered above.
for (NearbyStop sd : nearbyStopFinder.findNearbyStops(
Expand All @@ -136,10 +140,7 @@ public void buildGraph() {
if (sd.stop instanceof RegularStop) {
continue;
}
distinctTransfers.put(
new TransferKey(sd.stop, stop, sd.edges),
new PathTransfer(sd.stop, stop, sd.distance, sd.edges)
);
createPathTransfer(distinctTransfers, sd, stop, mode);
}
}
}
Expand Down Expand Up @@ -174,6 +175,32 @@ public void buildGraph() {
);
}

/**
* Factory method for creating a PathTransfer.
*/
private void createPathTransfer(
Map<TransferKey, PathTransfer> distinctTransfers,
NearbyStop sd,
RegularStop stop,
StreetMode mode
) {
TransferKey transferKey = new TransferKey(stop, sd.stop, sd.edges);
if (distinctTransfers.containsKey(transferKey)) {
PathTransfer oldTransfer = distinctTransfers.get(transferKey);
Set<StreetMode> newModes = new HashSet<>(oldTransfer.getModes());
newModes.add(mode);
distinctTransfers.put(
transferKey,
new PathTransfer(stop, sd.stop, sd.distance, sd.edges, newModes)
);
} else {
distinctTransfers.put(
transferKey,
new PathTransfer(stop, sd.stop, sd.distance, sd.edges, Set.of(mode))
);
}
}

/**
* Factory method for creating a NearbyStopFinder. Will create different finders depending on
* whether the graph has a street network and if ConsiderPatternsForDirectTransfers feature is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

import java.io.Serializable;
import java.util.List;
import java.util.Set;
import org.opentripplanner.model.transfer.ConstrainedTransfer;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.street.model.edge.Edge;
import org.opentripplanner.transit.model.site.StopLocation;
import org.opentripplanner.utils.tostring.ToStringBuilder;

/**
* Represents a transfer between stops with the street network path attatched to it.
* Represents a transfer for a set of modes between stops with the street network path attached to it.
* <p>
* Do not confuse this with {@link ConstrainedTransfer}.
*
* <p>
* TODO these should really have a set of valid modes in case bike vs. walk transfers are different
* TODO Should we just store the NearbyStop as a field here, or even switch to using it instead
* where this class is used
*/
Expand All @@ -27,11 +28,20 @@ public class PathTransfer implements Serializable {

private final List<Edge> edges;

public PathTransfer(StopLocation from, StopLocation to, double distanceMeters, List<Edge> edges) {
private final Set<StreetMode> modes;

public PathTransfer(
StopLocation from,
StopLocation to,
double distanceMeters,
List<Edge> edges,
Set<StreetMode> modes
) {
this.from = from;
this.to = to;
this.distanceMeters = distanceMeters;
this.edges = edges;
this.modes = modes;
}

public String getName() {
Expand All @@ -46,6 +56,10 @@ public List<Edge> getEdges() {
return this.edges;
}

public Set<StreetMode> getModes() {
return this.modes;
}

@Override
public String toString() {
return ToStringBuilder
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.opentripplanner.routing.algorithm.mapping;

import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.street.search.TraverseMode;

/**
* Maps street mode to transfer traverse mode.
*/
public class StreetModeToTransferTraverseModeMapper {

public static TraverseMode map(StreetMode mode) {
return switch (mode) {
case WALK -> TraverseMode.WALK;
case BIKE -> TraverseMode.BICYCLE;
case CAR -> TraverseMode.CAR;
default -> throw new IllegalArgumentException(
String.format("StreetMode %s can not be mapped to a TraverseMode for transfers.", mode)
);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.List;
import java.util.function.Function;
import org.opentripplanner.raptor.api.model.RaptorTransfer;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.street.search.request.StreetSearchRequest;

public class RaptorTransferIndex {
Expand All @@ -29,6 +30,7 @@ public static RaptorTransferIndex create(
) {
var forwardTransfers = new ArrayList<List<RaptorTransfer>>(transfersByStopIndex.size());
var reversedTransfers = new ArrayList<List<RaptorTransfer>>(transfersByStopIndex.size());
StreetMode mode = request.mode();

for (int i = 0; i < transfersByStopIndex.size(); i++) {
forwardTransfers.add(new ArrayList<>());
Expand All @@ -41,6 +43,7 @@ public static RaptorTransferIndex create(
var transfers = transfersByStopIndex
.get(fromStop)
.stream()
.filter(transfer -> transfer.getModes().contains(mode))
.flatMap(s -> s.asRaptorTransfer(request).stream())
.collect(
toMap(RaptorTransfer::stop, Function.identity(), (a, b) -> a.c1() < b.c1() ? a : b)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.locationtech.jts.geom.Coordinate;
import org.opentripplanner.raptor.api.model.RaptorCostConverter;
import org.opentripplanner.raptor.api.model.RaptorTransfer;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.routing.api.request.preference.WalkPreferences;
import org.opentripplanner.street.model.edge.Edge;
import org.opentripplanner.street.search.request.StreetSearchRequest;
Expand All @@ -31,16 +32,20 @@ public class Transfer {

private final List<Edge> edges;

public Transfer(int toStop, List<Edge> edges) {
private final Set<StreetMode> modes;

public Transfer(int toStop, List<Edge> edges, Set<StreetMode> modes) {
this.toStop = toStop;
this.edges = edges;
this.distanceMeters = (int) edges.stream().mapToDouble(Edge::getDistanceMeters).sum();
this.modes = modes;
}

public Transfer(int toStopIndex, int distanceMeters) {
public Transfer(int toStopIndex, int distanceMeters, Set<StreetMode> modes) {
this.toStop = toStopIndex;
this.distanceMeters = distanceMeters;
this.edges = null;
this.modes = modes;
}

public List<Coordinate> getCoordinates() {
Expand Down Expand Up @@ -68,6 +73,10 @@ public List<Edge> getEdges() {
return edges;
}

public Set<StreetMode> getModes() {
return modes;
}

public Optional<RaptorTransfer> asRaptorTransfer(StreetSearchRequest request) {
WalkPreferences walkPreferences = request.preferences().walk();
if (edges == null || edges.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,15 @@ static List<List<Transfer>> mapTransfers(
int toStopIndex = pathTransfer.to.getIndex();
Transfer newTransfer;
if (pathTransfer.getEdges() != null) {
newTransfer = new Transfer(toStopIndex, pathTransfer.getEdges());
newTransfer =
new Transfer(toStopIndex, pathTransfer.getEdges(), pathTransfer.getModes());
} else {
newTransfer =
new Transfer(toStopIndex, (int) Math.ceil(pathTransfer.getDistanceMeters()));
new Transfer(
toStopIndex,
(int) Math.ceil(pathTransfer.getDistanceMeters()),
pathTransfer.getModes()
);
}

list.add(newTransfer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -54,6 +55,7 @@
import org.opentripplanner.routing.algorithm.raptoradapter.transit.TransitLayer;
import org.opentripplanner.routing.algorithm.raptoradapter.transit.cost.DefaultCostCalculator;
import org.opentripplanner.routing.api.request.RouteRequest;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.street.search.state.State;
import org.opentripplanner.street.search.state.TestStateBuilder;
Expand Down Expand Up @@ -199,7 +201,7 @@ void createItineraryWithOnBoardFlexAccess() {
flexAccessEgress,
AccessEgressType.ACCESS
);
Transfer transfer = new Transfer(S2.getIndex(), 0);
Transfer transfer = new Transfer(S2.getIndex(), 0, Set.of(StreetMode.WALK));
RaptorTransfer raptorTransfer = new DefaultRaptorTransfer(S1.getIndex(), 0, 0, transfer);
RaptorAccessEgress egress = new DefaultAccessEgress(S2.getIndex(), state);
PathLeg<RaptorTripSchedule> egressLeg = new EgressPathLeg<>(egress, 0, 0, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.opentripplanner._support.geometry.Coordinates;
import org.opentripplanner.raptor.api.model.RaptorCostConverter;
import org.opentripplanner.raptor.api.model.RaptorTransfer;
import org.opentripplanner.routing.api.request.StreetMode;
import org.opentripplanner.street.model._data.StreetModelForTest;
import org.opentripplanner.street.model.vertex.IntersectionVertex;
import org.opentripplanner.street.search.request.StreetSearchRequest;
Expand All @@ -34,7 +36,7 @@ void limitMaxCost() {
// very long edge from Berlin to Boston that has of course a huge cost to traverse
var edge = StreetModelForTest.streetEdge(BERLIN_V, BOSTON_V);

var veryLongTransfer = new Transfer(0, List.of(edge));
var veryLongTransfer = new Transfer(0, List.of(edge), Set.of(StreetMode.WALK));
assertTrue(veryLongTransfer.getDistanceMeters() > 1_000_000);
// cost would be too high, so it should be capped to a maximum value
assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get());
Expand All @@ -43,7 +45,7 @@ void limitMaxCost() {
@Test
void allowLowCost() {
var edge = StreetModelForTest.streetEdge(BERLIN_V, BRANDENBURG_GATE_V);
var transfer = new Transfer(0, List.of(edge));
var transfer = new Transfer(0, List.of(edge), Set.of(StreetMode.WALK));
assertTrue(transfer.getDistanceMeters() < 4000);
final Optional<RaptorTransfer> raptorTransfer = transfer.asRaptorTransfer(
StreetSearchRequest.of().build()
Expand All @@ -58,26 +60,26 @@ class WithoutEdges {

@Test
void overflow() {
var veryLongTransfer = new Transfer(0, Integer.MAX_VALUE);
var veryLongTransfer = new Transfer(0, Integer.MAX_VALUE, Set.of(StreetMode.WALK));
assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get());
}

@Test
void negativeCost() {
var veryLongTransfer = new Transfer(0, -5);
var veryLongTransfer = new Transfer(0, -5, Set.of(StreetMode.WALK));
assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get());
}

@Test
void limitMaxCost() {
var veryLongTransfer = new Transfer(0, 8_000_000);
var veryLongTransfer = new Transfer(0, 8_000_000, Set.of(StreetMode.WALK));
// cost would be too high, so it will be capped before passing to RAPTOR
assertMaxCost(veryLongTransfer.asRaptorTransfer(StreetSearchRequest.of().build()).get());
}

@Test
void allowLowCost() {
var transfer = new Transfer(0, 200);
var transfer = new Transfer(0, 200, Set.of(StreetMode.WALK));
final Optional<RaptorTransfer> raptorTransfer = transfer.asRaptorTransfer(
StreetSearchRequest.of().build()
);
Expand Down

0 comments on commit 2215154

Please sign in to comment.