Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drt: attempt to handle waiting time explicitly when teleporting #3095

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading