Skip to content

Commit

Permalink
drt: attempt to handle waiting time explicitly when teleporting
Browse files Browse the repository at this point in the history
  • Loading branch information
tschlenther committed Feb 7, 2024
1 parent d0b2d66 commit 5b3c4f1
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,17 @@ public Route calculateRoute(PassengerRequest request) {
final Coord toActCoord = endLink.getToNode().getCoord();
double dist = CoordUtils.calcEuclideanDistance(fromActCoord, toActCoord);
Route route = new GenericRouteImpl(startLink.getId(), endLink.getId());
//TODO move wait time outside the route (handle it explicitly by the TeleportingPassengerEngine)
//wait time has to be included in route travel time because TeleportingPassengerEngine delegates to DefaulTeleportationEngine for the TeleportationArrivalEvent
//but TeleportingPassengerEngine then accounts for the waiting time separataly
int travTime = (int)(averageWaitingTime + (dist / averageInVehicleBeelineSpeed));
route.setTravelTime(travTime);
route.setDistance(dist);
return route;
}

@Override
public double getAverageWaitingTime() {
return averageWaitingTime;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@

package org.matsim.contrib.dvrp.passenger;

import java.util.*;

import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import jakarta.inject.Inject;
import jakarta.inject.Provider;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.matsim.api.core.v01.Id;
Expand All @@ -37,11 +36,7 @@
import org.matsim.contrib.dvrp.optimizer.Request;
import org.matsim.contrib.dvrp.run.DvrpModes;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.mobsim.framework.MobsimAgent;
import org.matsim.core.mobsim.framework.MobsimDriverAgent;
import org.matsim.core.mobsim.framework.MobsimPassengerAgent;
import org.matsim.core.mobsim.framework.MobsimTimer;
import org.matsim.core.mobsim.framework.PlanAgent;
import org.matsim.core.mobsim.framework.*;
import org.matsim.core.mobsim.qsim.DefaultTeleportationEngine;
import org.matsim.core.mobsim.qsim.InternalInterface;
import org.matsim.core.mobsim.qsim.TeleportationEngine;
Expand All @@ -50,17 +45,18 @@
import org.matsim.vis.snapshotwriters.AgentSnapshotInfo;
import org.matsim.vis.snapshotwriters.VisData;

import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import java.util.*;

/**
* @author Michal Maciejewski (michalm)
*/
public class TeleportingPassengerEngine implements PassengerEngine, VisData {
public static final String ORIGINAL_ROUTE_ATTRIBUTE = "originalRoute";

public interface TeleportedRouteCalculator {

Route calculateRoute(PassengerRequest request);
double getAverageWaitingTime();

}

private final String mode;
Expand All @@ -76,6 +72,8 @@ public interface TeleportedRouteCalculator {
private final TeleportationEngine teleportationEngine;
private final Queue<Pair<Double, PassengerRequest>> teleportedRequests = new PriorityQueue<>(
Comparator.comparingDouble(Pair::getLeft));
private final Queue<Pair<Double, PassengerRequest>> waitingRequests = new PriorityQueue<>(
Comparator.comparingDouble(Pair::getLeft));

private InternalInterface internalInterface;

Expand Down Expand Up @@ -115,7 +113,16 @@ public void onPrepareSim() {

@Override
public void doSimStep(double time) {
//first process passenger dropoff events
//first process passenger pickup events
while (!waitingRequests.isEmpty() && waitingRequests.peek().getLeft() <= time) {
PassengerRequest request = waitingRequests.poll().getRight();
for (Id<Person> passenger : request.getPassengerIds()) {
//TODO: check whether to use first passenger Id
eventsManager.processEvent(new PassengerPickedUpEvent(time, mode, request.getId(), request.getPassengerIds().get(0), null));
}
}

//then process passenger dropoff events
while (!teleportedRequests.isEmpty() && teleportedRequests.peek().getLeft() <= time) {
PassengerRequest request = teleportedRequests.poll().getRight();
for (Id<Person> passenger : request.getPassengerIds()) {
Expand Down Expand Up @@ -149,8 +156,10 @@ public boolean handleDeparture(double now, MobsimAgent agent, Id<Link> fromLinkI

if (internalPassengerHandling.validateRequest(request, requestValidator, now)) {
Route teleportedRoute = adaptLegRouteForTeleportation(List.of(passenger), request, now);
eventsManager.processEvent(new PassengerPickedUpEvent(now, mode, request.getId(), passenger.getId(), null));
teleportationEngine.handleDeparture(now, passenger, fromLinkId);
double waitingEnd = now + teleportedRouteCalculator.getAverageWaitingTime();
waitingRequests.add(ImmutablePair.of(waitingEnd, request));
//the teleportedRoute travel time already includes the waiting time - it has to because otherwise the delegation to teleportationEngine.doSimStep does not work properly
teleportedRequests.add(ImmutablePair.of(now + teleportedRoute.getTravelTime().seconds(), request));
} else {
//not much else can be done for immediate requests
Expand All @@ -177,7 +186,7 @@ private Route adaptLegRouteForTeleportation(List<MobsimPassengerAgent> passenger
}

eventsManager.processEvent(new PassengerRequestScheduledEvent(mobsimTimer.getTimeOfDay(), mode, request.getId(),
request.getPassengerIds(), null, now, now + teleportedRoute.getTravelTime().seconds()));
request.getPassengerIds(), null, now, now + teleportedRouteCalculator.getAverageWaitingTime() + teleportedRoute.getTravelTime().seconds()));
return teleportedRoute;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,35 @@ void test_valid_teleported() {
fixture.addPersonWithLeg(fixture.linkAB, fixture.linkBA, departureTime, fixture.PERSON_ID);

double travelTime = 999;
double waitTime = 1;
double travelDistance = 555;
TeleportedRouteCalculator teleportedRouteCalculator = request -> {
Route route = new GenericRouteImpl(request.getFromLink().getId(), request.getToLink().getId());
route.setTravelTime(travelTime);
route.setDistance(travelDistance);
return route;
TeleportedRouteCalculator teleportedRouteCalculator = new TeleportedRouteCalculator() {
@Override
public Route calculateRoute(PassengerRequest request) {
Route route = new GenericRouteImpl(request.getFromLink().getId(), request.getToLink().getId());
route.setTravelTime(travelTime);
route.setDistance(travelDistance);
return route;
}

@Override
public double getAverageWaitingTime() {
return waitTime;
}
};
PassengerRequestValidator requestValidator = request -> Set.of();//valid
createQSim(teleportedRouteCalculator, requestValidator).run();

double arrivalTime = departureTime + travelTime;
double arrivalTime = departureTime + waitTime + travelTime;
var requestId = Id.create("taxi_0", Request.class);
fixture.assertPassengerEvents(
Collections.singleton(fixture.PERSON_ID),
new ActivityEndEvent(departureTime, fixture.PERSON_ID, fixture.linkAB.getId(), null, START_ACTIVITY),
new PersonDepartureEvent(departureTime, fixture.PERSON_ID, fixture.linkAB.getId(), MODE, MODE),
new PassengerWaitingEvent(departureTime, MODE, requestId, List.of(fixture.PERSON_ID)),
new PassengerRequestScheduledEvent(departureTime, MODE, requestId, List.of(fixture.PERSON_ID), null, departureTime,
arrivalTime), new PassengerPickedUpEvent(departureTime, MODE, requestId, fixture.PERSON_ID, null),
arrivalTime),
new PassengerPickedUpEvent(departureTime + waitTime, MODE, requestId, fixture.PERSON_ID, null),
new PassengerDroppedOffEvent(arrivalTime, MODE, requestId, fixture.PERSON_ID, null),
new TeleportationArrivalEvent(arrivalTime, fixture.PERSON_ID, travelDistance, MODE),
new PersonArrivalEvent(arrivalTime, fixture.PERSON_ID, fixture.linkBA.getId(), MODE),
Expand All @@ -85,7 +95,18 @@ void test_invalid_rejected() {
double departureTime = 0;
fixture.addPersonWithLeg(fixture.linkAB, fixture.linkBA, departureTime, fixture.PERSON_ID);

TeleportedRouteCalculator teleportedRouteCalculator = request -> null; // unused
TeleportedRouteCalculator teleportedRouteCalculator = new TeleportedRouteCalculator() {
// unused
@Override
public Route calculateRoute(PassengerRequest request) {
return null;
}

@Override
public double getAverageWaitingTime() {
return 0;
}
};
PassengerRequestValidator requestValidator = request -> Set.of("invalid");
createQSim(teleportedRouteCalculator, requestValidator).run();

Expand Down

0 comments on commit 5b3c4f1

Please sign in to comment.