From 60368d2b9119f57a0fe493e7ca49231d209d0e9a Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 19 Jul 2024 14:05:29 +0200 Subject: [PATCH 1/9] add prebooking support for drt shifts some minor shift cleanups possibility to assign requests to shifts that are assigned bot not started yet --- .../edrt/run/EDrtControlerCreator.java | 8 +- .../DrtOperationsControlerCreator.java | 21 +- .../EDrtOperationsControlerCreator.java | 18 +- .../EDrtAssignShiftToVehicleLogic.java | 6 +- .../dispatcher/EDrtShiftDispatcherImpl.java | 10 +- .../dispatcher/EDrtShiftStartLogic.java | 6 +- .../run/ShiftEDrtModeOptimizerQSimModule.java | 4 +- ...tayTask.java => EDrtWaitForShiftTask.java} | 10 +- .../schedule/ShiftEDrtActionCreator.java | 4 +- .../schedule/ShiftEDrtTaskFactoryImpl.java | 20 +- .../scheduler/EShiftTaskScheduler.java | 32 +- .../shifts/config/ShiftsParams.java | 14 +- .../dispatcher/DefaultShiftStartLogic.java | 6 +- .../dispatcher/DrtShiftDispatcherImpl.java | 37 +-- .../ShiftVehicleDataEntryFactory.java | 37 ++- .../ShiftInsertionCostCalculator.java | 17 +- .../shifts/run/ShiftDrtModeModule.java | 6 +- .../run/ShiftDrtModeOptimizerQSimModule.java | 4 +- .../schedule/ShiftDrtActionCreator.java | 2 +- .../ShiftDrtStayTaskEndTimeCalculator.java | 18 +- .../shifts/schedule/ShiftDrtTaskFactory.java | 4 +- .../schedule/ShiftDrtTaskFactoryImpl.java | 8 +- .../shifts/schedule/WaitForShiftStayTask.java | 29 -- .../shifts/schedule/WaitForShiftTask.java | 65 ++++ .../scheduler/ShiftDrtScheduleInquiry.java | 4 +- .../shifts/scheduler/ShiftTaskScheduler.java | 4 + .../scheduler/ShiftTaskSchedulerImpl.java | 32 +- .../run/RunPrebookingShiftDrtScenarioIT.java | 298 ++++++++++++++++++ .../contrib/drt/run/DrtControlerCreator.java | 17 +- 29 files changed, 590 insertions(+), 151 deletions(-) rename contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/{EDrtWaitForShiftStayTask.java => EDrtWaitForShiftTask.java} (69%) delete mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/WaitForShiftStayTask.java create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/WaitForShiftTask.java create mode 100644 contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtControlerCreator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtControlerCreator.java index 1db60059c37..3d54738d88e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtControlerCreator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtControlerCreator.java @@ -41,11 +41,13 @@ public class EDrtControlerCreator { public static Controler createControler(Config config, boolean otfvis) { - MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config); - DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtConfig, config.scoring(), config.routing()); - Scenario scenario = DrtControlerCreator.createScenarioWithDrtRouteFactory(config); ScenarioUtils.loadScenario(scenario); + return createControler(config, scenario, otfvis); + } + public static Controler createControler(Config config, Scenario scenario, boolean otfvis) { + MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config); + DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtConfig, config.scoring(), config.routing()); Controler controler = new Controler(scenario); controler.addOverridingModule(new MultiModeEDrtModule()); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/DrtOperationsControlerCreator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/DrtOperationsControlerCreator.java index 835cc77e9e2..ccc1576a348 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/DrtOperationsControlerCreator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/DrtOperationsControlerCreator.java @@ -1,5 +1,6 @@ package org.matsim.contrib.drt.extension.operations; +import org.matsim.api.core.v01.Scenario; import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesModeModule; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilitiesQSimModule; @@ -27,10 +28,25 @@ public class DrtOperationsControlerCreator { * @return */ public static Controler createControler(Config config, boolean otfvis) { - MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config); - Controler controler = DrtControlerCreator.createControler(config, otfvis); + return prepareController(config, controler); + } + + /** + * Creates a controller in one step. + * + * @param config + * @param scenario + * @param otfvis + * @return + */ + public static Controler createControler(Config config, Scenario scenario, boolean otfvis) { + Controler controler = DrtControlerCreator.createControler(config, scenario, otfvis); + return prepareController(config, controler); + } + private static Controler prepareController(Config config, Controler controler) { + MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config); for (DrtConfigGroup drtCfg : multiModeDrtConfig.getModalElements()) { controler.addOverridingModule(new ShiftDrtModeModule(drtCfg)); controler.addOverridingQSimModule(new DrtModeQSimModule(drtCfg, new ShiftDrtModeOptimizerQSimModule(drtCfg))); @@ -40,7 +56,6 @@ public static Controler createControler(Config config, boolean otfvis) { } controler.configureQSimComponents(DvrpQSimComponents.activateAllModes(multiModeDrtConfig)); - return controler; } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/EDrtOperationsControlerCreator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/EDrtOperationsControlerCreator.java index da76f73772d..855cba7f143 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/EDrtOperationsControlerCreator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/EDrtOperationsControlerCreator.java @@ -1,5 +1,6 @@ package org.matsim.contrib.drt.extension.operations; +import org.matsim.api.core.v01.Scenario; import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; import org.matsim.contrib.drt.extension.edrt.run.EDrtControlerCreator; import org.matsim.contrib.drt.extension.operations.eshifts.charging.ShiftOperatingVehicleProvider; @@ -24,11 +25,19 @@ public class EDrtOperationsControlerCreator { public static Controler createControler(Config config, boolean otfvis) { - - MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config); - Controler controler = EDrtControlerCreator.createControler(config, otfvis); + prepareController(config, controler); + return controler; + } + + public static Controler createControler(Config config, Scenario scenario, boolean otfvis) { + Controler controler = EDrtControlerCreator.createControler(config, scenario, otfvis); + prepareController(config, controler); + return controler; + } + private static void prepareController(Config config, Controler controler) { + MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config); for (DrtConfigGroup drtCfg : multiModeDrtConfig.getModalElements()) { controler.addOverridingModule(new ShiftDrtModeModule(drtCfg)); controler.addOverridingQSimModule(new DrtModeQSimModule(drtCfg, new ShiftDrtModeOptimizerQSimModule(drtCfg))); @@ -39,14 +48,11 @@ public static Controler createControler(Config config, boolean otfvis) { controler.addOverridingModule(new DrtShiftEfficiencyModeModule(drtCfg)); } - controler.addOverridingQSimModule(new AbstractQSimModule() { @Override protected void configureQSim() { this.bind(IdleDischargingHandler.VehicleProvider.class).to(ShiftOperatingVehicleProvider.class); } }); - - return controler; } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtAssignShiftToVehicleLogic.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtAssignShiftToVehicleLogic.java index 32f74d1196c..0c2d4fd79c8 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtAssignShiftToVehicleLogic.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtAssignShiftToVehicleLogic.java @@ -9,7 +9,7 @@ package org.matsim.contrib.drt.extension.operations.eshifts.dispatcher; import org.matsim.contrib.drt.extension.operations.eshifts.fleet.EvShiftDvrpVehicle; -import org.matsim.contrib.drt.extension.operations.eshifts.schedule.EDrtWaitForShiftStayTask; +import org.matsim.contrib.drt.extension.operations.eshifts.schedule.EDrtWaitForShiftTask; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.AssignShiftToVehicleLogic; import org.matsim.contrib.drt.extension.operations.shifts.fleet.ShiftDvrpVehicle; @@ -37,8 +37,8 @@ public boolean canAssignVehicleToShift(ShiftDvrpVehicle vehicle, DrtShift shift) // no, if charging if(vehicle.getSchedule().getStatus() == Schedule.ScheduleStatus.STARTED) { final Task currentTask = vehicle.getSchedule().getCurrentTask(); - if (currentTask instanceof EDrtWaitForShiftStayTask) { - if (((EDrtWaitForShiftStayTask) currentTask).getChargingTask() != null) { + if (currentTask instanceof EDrtWaitForShiftTask) { + if (((EDrtWaitForShiftTask) currentTask).getChargingTask() != null) { if (currentTask.getEndTime() > shift.getStartTime()) { return false; } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftDispatcherImpl.java index e18008e4ce5..ace6e8d66e0 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftDispatcherImpl.java @@ -3,7 +3,7 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.network.Link; import org.matsim.contrib.drt.extension.operations.eshifts.fleet.EvShiftDvrpVehicle; -import org.matsim.contrib.drt.extension.operations.eshifts.schedule.EDrtWaitForShiftStayTask; +import org.matsim.contrib.drt.extension.operations.eshifts.schedule.EDrtWaitForShiftTask; import org.matsim.contrib.drt.extension.operations.eshifts.scheduler.EShiftTaskScheduler; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcher; @@ -11,7 +11,7 @@ import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacilities; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTask; -import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftStayTask; +import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftTask; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.schedule.Schedule; @@ -96,8 +96,8 @@ private void checkChargingAtHub(double timeStep) { final ElectricVehicle electricVehicle = eShiftVehicle.getElectricVehicle(); if (electricVehicle.getBattery().getCharge() / electricVehicle.getBattery().getCapacity() < drtShiftParams.chargeAtHubThreshold) { final Task currentTask = eShiftVehicle.getSchedule().getCurrentTask(); - if (currentTask instanceof EDrtWaitForShiftStayTask - && ((EDrtWaitForShiftStayTask) currentTask).getChargingTask() == null) { + if (currentTask instanceof EDrtWaitForShiftTask + && ((EDrtWaitForShiftTask) currentTask).getChargingTask() == null) { Optional selectedCharger = chargerIds .stream() .map(id -> chargingInfrastructure.getChargers().get(id)) @@ -122,7 +122,7 @@ private void checkChargingAtHub(double timeStep) { .calcRemainingEnergyToCharge(electricVehicle); final double endTime = timeStep + waitTime + chargingTime; if (endTime < currentTask.getEndTime()) { - shiftTaskScheduler.chargeAtHub((WaitForShiftStayTask) currentTask, eShiftVehicle, + shiftTaskScheduler.chargeAtHub((WaitForShiftTask) currentTask, eShiftVehicle, electricVehicle, selectedChargerImpl, timeStep, endTime, energy); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftStartLogic.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftStartLogic.java index ad3c83ca0f7..97ceadbb433 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftStartLogic.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/dispatcher/EDrtShiftStartLogic.java @@ -8,7 +8,7 @@ */ package org.matsim.contrib.drt.extension.operations.eshifts.dispatcher; -import org.matsim.contrib.drt.extension.operations.eshifts.schedule.EDrtWaitForShiftStayTask; +import org.matsim.contrib.drt.extension.operations.eshifts.schedule.EDrtWaitForShiftTask; import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.DrtShiftDispatcher; import org.matsim.contrib.drt.extension.operations.shifts.dispatcher.ShiftStartLogic; import org.matsim.contrib.dvrp.schedule.Schedule; @@ -29,9 +29,9 @@ public EDrtShiftStartLogic(ShiftStartLogic delegate) { public boolean shiftStarts(DrtShiftDispatcher.ShiftEntry shiftEntry) { Schedule schedule = shiftEntry.vehicle().getSchedule(); Task currentTask = schedule.getCurrentTask(); - if (currentTask instanceof EDrtWaitForShiftStayTask) { + if (currentTask instanceof EDrtWaitForShiftTask) { //check whether vehicle still needs to complete charging task - if(((EDrtWaitForShiftStayTask) currentTask).getChargingTask() == null) { + if(((EDrtWaitForShiftTask) currentTask).getChargingTask() == null) { return delegate.shiftStarts(shiftEntry); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java index ab4bf41c938..aefdfeb5e6c 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/run/ShiftEDrtModeOptimizerQSimModule.java @@ -76,7 +76,9 @@ drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()), new EDrtAssignShiftToVehicleLogic(new DefaultAssignShiftToVehicleLogic(drtShiftParams), drtShiftParams)), getter.getModal(Fleet.class)))).asEagerSingleton(); - bindModal(VehicleEntry.EntryFactory.class).toProvider(modalProvider(getter -> new ShiftVehicleDataEntryFactory(new EDrtVehicleDataEntryFactory(0)))).asEagerSingleton(); + bindModal(VehicleEntry.EntryFactory.class).toProvider(modalProvider(getter -> + new ShiftVehicleDataEntryFactory(new EDrtVehicleDataEntryFactory(0), + drtShiftParams.considerUpcomingShiftsForInsertion))).asEagerSingleton(); bindModal(DrtTaskFactory.class).toProvider(modalProvider(getter -> new ShiftEDrtTaskFactoryImpl(new EDrtTaskFactoryImpl(), getter.getModal(OperationFacilities.class)))).in(Singleton.class); bindModal(ShiftDrtTaskFactory.class).toProvider(modalProvider(getter -> ((ShiftDrtTaskFactory) getter.getModal(DrtTaskFactory.class)))); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/EDrtWaitForShiftStayTask.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/EDrtWaitForShiftTask.java similarity index 69% rename from contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/EDrtWaitForShiftStayTask.java rename to contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/EDrtWaitForShiftTask.java index c60e0214f1d..546b4e6b770 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/EDrtWaitForShiftStayTask.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/EDrtWaitForShiftTask.java @@ -1,23 +1,23 @@ package org.matsim.contrib.drt.extension.operations.eshifts.schedule; import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftTask; import org.matsim.contrib.evrp.ChargingTask; import org.matsim.contrib.evrp.ETask; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; -import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftStayTask; /** * @author nkuehnel / MOIA */ -public class EDrtWaitForShiftStayTask extends WaitForShiftStayTask implements ETask { +public class EDrtWaitForShiftTask extends WaitForShiftTask implements ETask { private final double consumedEnergy; private final ChargingTask chargingTask; - public EDrtWaitForShiftStayTask(double beginTime, double endTime, Link link, - double consumedEnergy, OperationFacility facility, - ChargingTask chargingTask) { + public EDrtWaitForShiftTask(double beginTime, double endTime, Link link, + double consumedEnergy, OperationFacility facility, + ChargingTask chargingTask) { super(beginTime, endTime, link, facility); this.consumedEnergy = consumedEnergy; this.chargingTask = chargingTask; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtActionCreator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtActionCreator.java index 4604771bed9..6092021974c 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtActionCreator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtActionCreator.java @@ -42,9 +42,9 @@ public DynAction createAction(DynAgent dynAgent, DvrpVehicle vehicle, double now task.initTaskTracker(new OfflineETaskTracker((EvDvrpVehicle) vehicle, timer)); DrtStopTask t = (DrtStopTask) task; return new ChargingChangeoverActivity(((EDrtShiftChangeoverTaskImpl) task).getChargingTask(), passengerHandler, dynAgent, t, t.getDropoffRequests(), t.getPickupRequests()); - } else if (task instanceof EDrtWaitForShiftStayTask && ((EDrtWaitForShiftStayTask) task).getChargingTask() != null) { + } else if (task instanceof EDrtWaitForShiftTask && ((EDrtWaitForShiftTask) task).getChargingTask() != null) { task.initTaskTracker(new OfflineETaskTracker((EvDvrpVehicle) vehicle, timer)); - return new ChargingWaitForShiftActivity(((EDrtWaitForShiftStayTask) task).getChargingTask()); + return new ChargingWaitForShiftActivity(((EDrtWaitForShiftTask) task).getChargingTask()); } DynAction dynAction = delegate.createAction(dynAgent, vehicle, now); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtTaskFactoryImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtTaskFactoryImpl.java index 5e0c085c1bb..b7c2657f1bf 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtTaskFactoryImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/schedule/ShiftEDrtTaskFactoryImpl.java @@ -9,7 +9,7 @@ import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTask; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftChangeOverTask; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftDrtTaskFactory; -import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftStayTask; +import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftTask; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreak; import org.matsim.contrib.drt.schedule.DrtDriveTask; @@ -69,14 +69,14 @@ public DefaultStayTask createInitialTask(DvrpVehicle vehicle, double beginTime, } catch (Throwable e) { throw new RuntimeException(e); } - WaitForShiftStayTask waitForShiftStayTask = createWaitForShiftStayTask(vehicle, vehicle.getServiceBeginTime(), vehicle.getServiceEndTime(), + WaitForShiftTask waitForShiftTask = createWaitForShiftStayTask(vehicle, vehicle.getServiceBeginTime(), vehicle.getServiceEndTime(), vehicle.getStartLink(), operationFacility); boolean success = operationFacility.register(vehicle.getId()); if (!success) { throw new RuntimeException(String.format("Cannot register vehicle %s at facility %s at start-up. Please check" + "facility capacity and initial fleet distribution.", vehicle.getId().toString(), operationFacility.getId().toString())); } - return waitForShiftStayTask; + return waitForShiftTask; } @Override @@ -92,16 +92,16 @@ public ShiftChangeOverTask createShiftChangeoverTask(DvrpVehicle vehicle, double } @Override - public WaitForShiftStayTask createWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link, - OperationFacility facility) { - return new EDrtWaitForShiftStayTask(beginTime, endTime, link, 0, facility, null); + public WaitForShiftTask createWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link, + OperationFacility facility) { + return new EDrtWaitForShiftTask(beginTime, endTime, link, 0, facility, null); } - public WaitForShiftStayTask createChargingWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime, - double endTime, Link link, OperationFacility facility, - double totalEnergy, Charger charger) { + public WaitForShiftTask createChargingWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime, + double endTime, Link link, OperationFacility facility, + double totalEnergy, Charger charger) { ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy); - return new EDrtWaitForShiftStayTask(beginTime, endTime, link, totalEnergy, facility, chargingTask); + return new EDrtWaitForShiftTask(beginTime, endTime, link, totalEnergy, facility, chargingTask); } public EDrtShiftBreakTaskImpl createChargingShiftBreakTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link, diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java index 7352f32c261..dc053728a40 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/eshifts/scheduler/EShiftTaskScheduler.java @@ -351,8 +351,8 @@ private void appendShiftChange(DvrpVehicle vehicle, DrtShift shift, OperationFac public void startShift(ShiftDvrpVehicle vehicle, double now, DrtShift shift) { Schedule schedule = vehicle.getSchedule(); StayTask stayTask = (StayTask) schedule.getCurrentTask(); - if (stayTask instanceof WaitForShiftStayTask) { - ((WaitForShiftStayTask) stayTask).getFacility().deregisterVehicle(vehicle.getId()); + if (stayTask instanceof WaitForShiftTask) { + ((WaitForShiftTask) stayTask).getFacility().deregisterVehicle(vehicle.getId()); stayTask.setEndTime(now); schedule.addTask(taskFactory.createStayTask(vehicle, now, shift.getEndTime(), stayTask.getLink())); } else { @@ -375,6 +375,24 @@ public boolean updateShiftChange(ShiftDvrpVehicle vehicle, Link link, DrtShift s return false; } + @Override + public void planAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShift shift) { + Schedule schedule = vehicle.getSchedule(); + StayTask stayTask = (StayTask) schedule.getCurrentTask(); + if (stayTask instanceof WaitForShiftTask) { + stayTask.setEndTime(Math.max(timeStep, shift.getStartTime())); + } + } + + @Override + public void cancelAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShift shift) { + Schedule schedule = vehicle.getSchedule(); + StayTask stayTask = (StayTask) schedule.getCurrentTask(); + if (stayTask instanceof WaitForShiftTask) { + stayTask.setEndTime(vehicle.getServiceEndTime()); + } + } + private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vrpPath, DrtShift shift, OperationFacility facility, Task lastTask) { Schedule schedule = vehicle.getSchedule(); @@ -413,19 +431,19 @@ private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vr vrpPath.getToLink(), facility)); } - public void chargeAtHub(WaitForShiftStayTask currentTask, ShiftDvrpVehicle vehicle, + public void chargeAtHub(WaitForShiftTask currentTask, ShiftDvrpVehicle vehicle, ElectricVehicle electricVehicle, Charger charger, double beginTime, double endTime, double energy) { final double initialEndTime = currentTask.getEndTime(); currentTask.setEndTime(beginTime); ((ChargingWithAssignmentLogic) charger.getLogic()).assignVehicle(electricVehicle); - final WaitForShiftStayTask chargingWaitForShiftStayTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingWaitForShiftStayTask(vehicle, + final WaitForShiftTask chargingWaitForShiftTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingWaitForShiftStayTask(vehicle, beginTime, endTime, currentTask.getLink(), currentTask.getFacility(), energy, charger); - final WaitForShiftStayTask waitForShiftStayTask = taskFactory.createWaitForShiftStayTask(vehicle, endTime, + final WaitForShiftTask waitForShiftTask = taskFactory.createWaitForShiftStayTask(vehicle, endTime, initialEndTime, currentTask.getLink(), currentTask.getFacility()); - vehicle.getSchedule().addTask(currentTask.getTaskIdx() + 1, chargingWaitForShiftStayTask); - vehicle.getSchedule().addTask(currentTask.getTaskIdx() + 2, waitForShiftStayTask); + vehicle.getSchedule().addTask(currentTask.getTaskIdx() + 1, chargingWaitForShiftTask); + vehicle.getSchedule().addTask(currentTask.getTaskIdx() + 2, waitForShiftTask); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java index 4d76cbddfc0..e61e5541896 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/config/ShiftsParams.java @@ -8,8 +8,8 @@ */ package org.matsim.contrib.drt.extension.operations.shifts.config; -import org.matsim.contrib.ev.infrastructure.ChargerSpecification; import org.matsim.contrib.common.util.ReflectiveConfigGroupWithConfigurableParameterSets; +import org.matsim.contrib.ev.infrastructure.ChargerSpecification; import org.matsim.core.config.ConfigGroup; import java.net.URL; @@ -43,7 +43,7 @@ public class ShiftsParams extends ReflectiveConfigGroupWithConfigurableParameter @Parameter @Comment("Time of shift end rescheduling (i.e. check whether shift should end" + - " at a different facillity) before end of shift in [seconds]") + " at a different facility) before end of shift in [seconds]") public double shiftEndRescheduleLookAhead = 1800; @Parameter @@ -53,7 +53,7 @@ public class ShiftsParams extends ReflectiveConfigGroupWithConfigurableParameter @Parameter @Comment("set to true if shifts can start and end at in field operational facilities," + - " false if changerover is only allowed at hubs") + " false if changeover is only allowed at hubs") public boolean allowInFieldChangeover = true; //electric shifts @@ -91,7 +91,13 @@ public class ShiftsParams extends ReflectiveConfigGroupWithConfigurableParameter @Comment("defines the logging interval in [seconds]") public double loggingInterval = 600; - public ShiftsParams() { + @Parameter + @Comment("Defines whether vehicles should be eligible for insertion when they have a shift assigned which has not yet started. " + + "Defaults to false. Should be set to true if used together with prebookings that are inserted before shift starts. " + + "In this case, make sure that 'shiftScheduleLookAhead' is larger than the prebboking slack.") + public boolean considerUpcomingShiftsForInsertion = false; + + public ShiftsParams() { super(SET_NAME); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftStartLogic.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftStartLogic.java index cb9e5d76a9f..f2b006cbae7 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftStartLogic.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DefaultShiftStartLogic.java @@ -11,7 +11,7 @@ import com.google.common.base.Verify; import org.matsim.api.core.v01.Id; import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; -import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftStayTask; +import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftTask; import org.matsim.contrib.dvrp.schedule.Schedule; import org.matsim.contrib.dvrp.schedule.Task; @@ -34,11 +34,11 @@ public boolean shiftStarts(DrtShiftDispatcher.ShiftEntry peek) { // current task is WaitForShiftTask Task currentTask = schedule.getCurrentTask(); - if(currentTask instanceof WaitForShiftStayTask) { + if(currentTask instanceof WaitForShiftTask) { //check if optional location requirement is met if(peek.shift().getOperationFacilityId().isPresent()) { Id operationFacilityId = peek.shift().getOperationFacilityId().get(); - Verify.verify((operationFacilityId.equals(((WaitForShiftStayTask) currentTask).getFacility().getId())), + Verify.verify((operationFacilityId.equals(((WaitForShiftTask) currentTask).getFacility().getId())), "Vehicle and shift start locations do not match."); } return true; diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index c32b5d1b12b..7cfa4579612 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -152,28 +152,30 @@ private void checkBreaks() { } private void startShifts(double timeStep) { - // Start shifts final Iterator iterator = this.assignedShifts.iterator(); while (iterator.hasNext()) { - final ShiftEntry next = iterator.next(); - if (next.shift().getStartTime() > timeStep) { + final ShiftEntry assignedShiftEntry = iterator.next(); + if (assignedShiftEntry.shift().getStartTime() > timeStep) { + shiftTaskScheduler.planAssignedShift(assignedShiftEntry.vehicle(), timeStep, assignedShiftEntry.shift()); break; - } else if (next.shift().getEndTime() < timeStep) { - logger.warn("Too late to start shift " + next.shift().getId()); - next.vehicle().getShifts().remove(next.shift()); + } else if (assignedShiftEntry.shift().getEndTime() < timeStep) { + logger.warn("Too late to start shift " + assignedShiftEntry.shift().getId()); + assignedShiftEntry.vehicle().getShifts().remove(assignedShiftEntry.shift()); iterator.remove(); continue; } - if (shiftStartLogic.shiftStarts(next)) { - next.shift().start(); - shiftTaskScheduler.startShift(next.vehicle(), timeStep, next.shift()); - activeShifts.add(next); + if (shiftStartLogic.shiftStarts(assignedShiftEntry)) { + assignedShiftEntry.shift().start(); + shiftTaskScheduler.startShift(assignedShiftEntry.vehicle(), timeStep, assignedShiftEntry.shift()); + activeShifts.add(assignedShiftEntry); iterator.remove(); - logger.debug("Started shift " + next.shift()); - StayTask currentTask = (StayTask) next.vehicle().getSchedule().getCurrentTask(); - eventsManager.processEvent(new DrtShiftStartedEvent(timeStep, mode, next.shift().getId(), next.vehicle().getId(), + logger.debug("Started shift " + assignedShiftEntry.shift()); + StayTask currentTask = (StayTask) assignedShiftEntry.vehicle().getSchedule().getCurrentTask(); + eventsManager.processEvent(new DrtShiftStartedEvent(timeStep, mode, assignedShiftEntry.shift().getId(), assignedShiftEntry.vehicle().getId(), currentTask.getLink().getId())); + } else { + shiftTaskScheduler.planAssignedShift(assignedShiftEntry.vehicle(), timeStep, assignedShiftEntry.shift()); } } } @@ -264,6 +266,7 @@ private void assignShifts(double timeStep) { private void assignShiftToVehicle(DrtShift shift, ShiftDvrpVehicle vehicle) { Gbl.assertNotNull(vehicle); vehicle.addShift(shift); + shiftTaskScheduler.planAssignedShift(vehicle, timer.getTimeOfDay(), shift); assignedShifts.add(new ShiftEntry(shift, vehicle)); eventsManager.processEvent(new DrtShiftAssignedEvent(timer.getTimeOfDay(), mode, shift.getId(), vehicle.getId())); } @@ -438,7 +441,7 @@ private void scheduleShiftEnd(ShiftEntry endingShift) { private OperationFacility decideOnBreak(ShiftEntry activeShift) { if (activeShift.shift() != null) { - if (shiftNeedsBreak(activeShift.shift(), timer.getTimeOfDay())) { + if (hasSchedulableBreak(activeShift.shift(), timer.getTimeOfDay())) { final Schedule schedule = activeShift.vehicle().getSchedule(); Task currentTask = schedule.getCurrentTask(); Link lastLink; @@ -500,12 +503,10 @@ public void startBreak(ShiftDvrpVehicle vehicle, Id linkId) { } private boolean isSchedulable(DrtShift shift, double timeStep) { - return shift.getStartTime() <= timeStep + drtShiftParams.shiftScheduleLookAhead; // && shift.getEndTime() > timeStep; + return shift.getStartTime() <= timeStep + drtShiftParams.shiftScheduleLookAhead; } - - - private boolean shiftNeedsBreak(DrtShift shift, double timeStep) { + private boolean hasSchedulableBreak(DrtShift shift, double timeStep) { return shift.getBreak().isPresent() && shift.getBreak().get().getEarliestBreakStartTime() == timeStep && !shift.getBreak().get().isScheduled(); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/ShiftVehicleDataEntryFactory.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/ShiftVehicleDataEntryFactory.java index 3262fe787fc..66a3470ddbe 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/ShiftVehicleDataEntryFactory.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/ShiftVehicleDataEntryFactory.java @@ -1,16 +1,11 @@ package org.matsim.contrib.drt.extension.operations.shifts.optimizer; -import com.google.inject.Provider; import org.matsim.contrib.drt.extension.operations.shifts.fleet.ShiftDvrpVehicle; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; import org.matsim.contrib.drt.extension.operations.shifts.schedule.OperationalStop; -import org.matsim.contrib.drt.optimizer.VehicleDataEntryFactoryImpl; +import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftTask; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; import org.matsim.contrib.drt.optimizer.VehicleEntry; -import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; -import org.matsim.core.config.Config; - -import jakarta.inject.Inject; /** * @author nkuehnel / MOIA @@ -19,10 +14,13 @@ public class ShiftVehicleDataEntryFactory implements VehicleEntry.EntryFactory { private final VehicleEntry.EntryFactory entryFactory; + private final boolean considerUpcomingShifts; + - public ShiftVehicleDataEntryFactory(VehicleEntry.EntryFactory delegate) { + public ShiftVehicleDataEntryFactory(VehicleEntry.EntryFactory delegate, boolean considerUpcomingShifts) { entryFactory = delegate; - } + this.considerUpcomingShifts = considerUpcomingShifts; + } @Override public VehicleEntry create(DvrpVehicle vehicle, double currentTime) { @@ -36,12 +34,21 @@ public VehicleEntry create(DvrpVehicle vehicle, double currentTime) { public boolean isEligibleForRequestInsertion(DvrpVehicle dvrpVehicle, double currentTime) { final DrtShift currentShift = ((ShiftDvrpVehicle) dvrpVehicle).getShifts().peek(); - if(currentShift == null || - currentTime > currentShift.getEndTime() || - !currentShift.isStarted() || - currentShift.isEnded()) { - return false; + + // no shift assigned + if (currentShift == null) { + return false; + } + + if(currentShift.isStarted()) { + if(currentTime > currentShift.getEndTime()) { + return false; + } + // do not insert into operational stops such as breaks + return !(dvrpVehicle.getSchedule().getCurrentTask() instanceof OperationalStop); + } else { + // upcoming shift assigned but not started yet. Only consider vehicles already waiting for shift start + return considerUpcomingShifts && dvrpVehicle.getSchedule().getCurrentTask() instanceof WaitForShiftTask; } - return !(dvrpVehicle.getSchedule().getCurrentTask() instanceof OperationalStop); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/insertion/ShiftInsertionCostCalculator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/insertion/ShiftInsertionCostCalculator.java index db74fcd4d85..7055e4569be 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/insertion/ShiftInsertionCostCalculator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/insertion/ShiftInsertionCostCalculator.java @@ -1,5 +1,6 @@ package org.matsim.contrib.drt.extension.operations.shifts.optimizer.insertion; +import org.matsim.contrib.drt.extension.operations.shifts.fleet.ShiftDvrpVehicle; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTask; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftChangeOverTask; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreak; @@ -32,19 +33,23 @@ public ShiftInsertionCostCalculator(MobsimTimer timer, @Override public double calculate(DrtRequest drtRequest, Insertion insertion, DetourTimeInfo detourTimeInfo) { - if (!checkShiftTimeConstraintsForScheduledRequests(insertion, - detourTimeInfo.pickupDetourInfo.pickupTimeLoss, detourTimeInfo.getTotalTimeLoss())) { + if (!checkShiftTimeConstraintsForScheduledRequests(insertion, detourTimeInfo)) { return INFEASIBLE_SOLUTION_COST; } return delegate.calculate(drtRequest, insertion, detourTimeInfo); } - boolean checkShiftTimeConstraintsForScheduledRequests(Insertion insertion, double pickupDetourTimeLoss, - double totalTimeLoss) { + boolean checkShiftTimeConstraintsForScheduledRequests(Insertion insertion, DetourTimeInfo detourTimeInfo) { VehicleEntry vEntry = insertion.vehicleEntry; final int pickupIdx = insertion.pickup.index; final int dropoffIdx = insertion.dropoff.index; + double shiftEndTime = ((ShiftDvrpVehicle) vEntry.vehicle).getShifts().peek().getEndTime(); + if(shiftEndTime < detourTimeInfo.dropoffDetourInfo.arrivalTime) { + // fast fail which also captures requests that are prebooked for times outside of the shift. + return false; + } + for (int s = 0; s < pickupIdx; s++) { Waypoint.Stop stop = vEntry.stops.get(s); if (stop.task instanceof ShiftChangeOverTask) { @@ -53,6 +58,8 @@ boolean checkShiftTimeConstraintsForScheduledRequests(Insertion insertion, doubl } } + double pickupDetourTimeLoss = detourTimeInfo.pickupDetourInfo.pickupTimeLoss; + // each existing stop has 2 time constraints: latestArrivalTime and latestDepartureTime (see: Waypoint.Stop) // we are looking only at the time constraints of the scheduled requests (the new request is checked separately) @@ -73,6 +80,8 @@ boolean checkShiftTimeConstraintsForScheduledRequests(Insertion insertion, doubl } } + double totalTimeLoss = detourTimeInfo.getTotalTimeLoss(); + // all stops after the new (potential) dropoff are delayed by totalTimeLoss // check if this delay satisfies the time constraints at these stops for (int s = dropoffIdx; s < vEntry.stops.size(); s++) { diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java index 7df2d885723..8b52ca88951 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeModule.java @@ -14,7 +14,7 @@ import org.matsim.contrib.drt.extension.operations.shifts.io.DrtShiftsReader; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTaskImpl; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftChangeoverTaskImpl; -import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftStayTask; +import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftTask; import org.matsim.contrib.drt.extension.operations.shifts.scheduler.ShiftTaskScheduler; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecificationImpl; @@ -57,7 +57,7 @@ public ShiftDrtModeModule(DrtConfigGroup drtCfg) { private static final Comparator taskTypeComparator = Comparator.comparing((Task.TaskType type) -> { //we want the following order on the plot: STAY, RELOCATE, other - if (type.equals(WaitForShiftStayTask.TYPE)) { + if (type.equals(WaitForShiftTask.TYPE)) { return "F"; } else if (type.equals(ShiftChangeoverTaskImpl.TYPE)) { return "E"; @@ -73,7 +73,7 @@ public ShiftDrtModeModule(DrtConfigGroup drtCfg) { }).reversed(); private static final Map taskTypePaints = ImmutableMap.of( - WaitForShiftStayTask.TYPE, Color.WHITE, + WaitForShiftTask.TYPE, Color.WHITE, ShiftChangeoverTaskImpl.TYPE, Color.GRAY, ShiftBreakTaskImpl.TYPE, Color.DARK_GRAY, DrtStayTask.TYPE, Color.LIGHT_GRAY); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java index a6398faf3b3..a65de06b2c4 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/run/ShiftDrtModeOptimizerQSimModule.java @@ -124,7 +124,9 @@ shiftsParams, new DefaultShiftStartLogic(), new DefaultAssignShiftToVehicleLogic new DefaultInsertionCostCalculator(getter.getModal(CostCalculationStrategy.class), drtCfg.addOrGetDrtOptimizationConstraintsParams().addOrGetDefaultDrtOptimizationConstraintsSet())))); - bindModal(VehicleEntry.EntryFactory.class).toInstance(new ShiftVehicleDataEntryFactory(new VehicleDataEntryFactoryImpl())); + bindModal(VehicleEntry.EntryFactory.class).toInstance( + new ShiftVehicleDataEntryFactory(new VehicleDataEntryFactoryImpl(), shiftsParams.considerUpcomingShiftsForInsertion) + ); bindModal(DrtTaskFactory.class).toProvider(modalProvider(getter -> new ShiftDrtTaskFactoryImpl(new DrtTaskFactoryImpl(), getter.getModal(OperationFacilities.class)))); bindModal(ShiftDrtTaskFactory.class).toProvider(modalProvider(getter -> ((ShiftDrtTaskFactory) getter.getModal(DrtTaskFactory.class)))); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtActionCreator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtActionCreator.java index 0f65e1208f0..5deb47eba47 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtActionCreator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtActionCreator.java @@ -38,7 +38,7 @@ public DynAction createAction(DynAgent dynAgent, DvrpVehicle vehicle, double now DrtStopTask t = (DrtStopTask) task; return new DrtStopActivity(passengerHandler, dynAgent, t::getEndTime, t.getDropoffRequests(), t.getPickupRequests(), DRT_SHIFT_CHANGEOVER_NAME); - } else if (task instanceof WaitForShiftStayTask) { + } else if (task instanceof WaitForShiftTask) { return new IdleDynActivity(DRT_SHIFT_WAIT_FOR_SHIFT_NAME, task::getEndTime); } else { return dynActionCreator.createAction(dynAgent, vehicle, now); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtStayTaskEndTimeCalculator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtStayTaskEndTimeCalculator.java index ddeaf4ffb9e..546f0843673 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtStayTaskEndTimeCalculator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtStayTaskEndTimeCalculator.java @@ -1,8 +1,8 @@ package org.matsim.contrib.drt.extension.operations.shifts.schedule; +import com.google.common.base.Verify; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreak; import org.matsim.contrib.drt.schedule.DrtStayTaskEndTimeCalculator; @@ -31,17 +31,21 @@ public ShiftDrtStayTaskEndTimeCalculator(ShiftsParams drtShiftParams, DrtStayTas @Override public double calcNewEndTime(DvrpVehicle vehicle, StayTask task, double newBeginTime) { - if(task instanceof ShiftBreakTask) { + if (task instanceof WaitForShiftTask) { + Verify.verify(newBeginTime <= task.getEndTime(), "WaitForShiftTasks should not be delayed"); + return task.getEndTime(); + } + if (task instanceof ShiftBreakTask) { final DrtShiftBreak shiftBreak = ((ShiftBreakTask) task).getShiftBreak(); return newBeginTime + shiftBreak.getDuration(); - } else if(task instanceof ShiftChangeOverTask) { + } else if (task instanceof ShiftChangeOverTask) { return Math.max(newBeginTime, ((ShiftChangeOverTask) task).getShift().getEndTime()) + drtShiftParams.changeoverDuration; - } else if(DrtTaskBaseType.getBaseTypeOrElseThrow(task).equals(DrtTaskBaseType.STAY)) { + } else if (DrtTaskBaseType.getBaseTypeOrElseThrow(task).equals(DrtTaskBaseType.STAY)) { final List tasks = vehicle.getSchedule().getTasks(); final int taskIdx = tasks.indexOf(task); - if(tasks.size() > taskIdx+1) { - final Task nextTask = tasks.get(taskIdx +1); - if(nextTask instanceof ShiftChangeOverTask) { + if (tasks.size() > taskIdx + 1) { + final Task nextTask = tasks.get(taskIdx + 1); + if (nextTask instanceof ShiftChangeOverTask) { return Math.max(newBeginTime, ((ShiftChangeOverTask) nextTask).getShift().getEndTime()); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtTaskFactory.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtTaskFactory.java index 9de610a8b84..eaaf5c371ef 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtTaskFactory.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtTaskFactory.java @@ -18,6 +18,6 @@ ShiftBreakTask createShiftBreakTask(DvrpVehicle vehicle, double beginTime, doubl ShiftChangeOverTask createShiftChangeoverTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link, DrtShift shift, OperationFacility facility); - WaitForShiftStayTask createWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link, - OperationFacility facility); + WaitForShiftTask createWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link, + OperationFacility facility); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtTaskFactoryImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtTaskFactoryImpl.java index 57460d2bee6..e59d40dbac6 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtTaskFactoryImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/ShiftDrtTaskFactoryImpl.java @@ -58,9 +58,9 @@ public ShiftChangeOverTask createShiftChangeoverTask(DvrpVehicle vehicle, double } @Override - public WaitForShiftStayTask createWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime, double endTime, - Link link, OperationFacility facility) { - return new WaitForShiftStayTask(beginTime, endTime, link, facility); + public WaitForShiftTask createWaitForShiftStayTask(DvrpVehicle vehicle, double beginTime, double endTime, + Link link, OperationFacility facility) { + return new WaitForShiftTask(beginTime, endTime, link, facility); } public DefaultStayTask createInitialTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link) { @@ -71,7 +71,7 @@ public DefaultStayTask createInitialTask(DvrpVehicle vehicle, double beginTime, } catch (Throwable e) { throw new RuntimeException(e); } - WaitForShiftStayTask waitForShiftStayTask = createWaitForShiftStayTask(vehicle, vehicle.getServiceBeginTime(), vehicle.getServiceEndTime(), + WaitForShiftTask waitForShiftStayTask = createWaitForShiftStayTask(vehicle, vehicle.getServiceBeginTime(), vehicle.getServiceEndTime(), vehicle.getStartLink(), operationFacility); boolean success = operationFacility.register(vehicle.getId()); if (!success) { diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/WaitForShiftStayTask.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/WaitForShiftStayTask.java deleted file mode 100644 index 25556e16db7..00000000000 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/WaitForShiftStayTask.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.matsim.contrib.drt.extension.operations.shifts.schedule; - -import org.matsim.api.core.v01.network.Link; -import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; -import org.matsim.contrib.drt.schedule.DrtTaskType; -import org.matsim.contrib.dvrp.schedule.DefaultStayTask; - -import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.STAY; - -/** - * @author nkuehnel / MOIA - */ -public class WaitForShiftStayTask extends DefaultStayTask implements OperationalStop { - - public static final DrtTaskType TYPE = new DrtTaskType("WAIT_FOR_SHIFT", STAY); - - private final OperationFacility facility; - - public WaitForShiftStayTask(double beginTime, double endTime, Link link, OperationFacility facility) { - super(TYPE, beginTime, endTime, link); - this.facility = facility; - } - - @Override - public OperationFacility getFacility() { - return facility; - } - -} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/WaitForShiftTask.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/WaitForShiftTask.java new file mode 100644 index 00000000000..dcb0e9a1927 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/schedule/WaitForShiftTask.java @@ -0,0 +1,65 @@ +package org.matsim.contrib.drt.extension.operations.shifts.schedule; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; +import org.matsim.contrib.drt.passenger.AcceptedDrtRequest; +import org.matsim.contrib.drt.schedule.DrtStopTask; +import org.matsim.contrib.drt.schedule.DrtTaskType; +import org.matsim.contrib.dvrp.optimizer.Request; +import org.matsim.contrib.dvrp.schedule.DefaultStayTask; + +import java.util.Collections; +import java.util.Map; + +import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.STOP; + +/** + * @author nkuehnel / MOIA + */ +public class WaitForShiftTask extends DefaultStayTask implements DrtStopTask, OperationalStop { + + public static final DrtTaskType TYPE = new DrtTaskType("WAIT_FOR_SHIFT", STOP); + + private final OperationFacility facility; + + public WaitForShiftTask(double beginTime, double endTime, Link link, OperationFacility facility) { + super(TYPE, beginTime, endTime, link); + this.facility = facility; + } + + @Override + public OperationFacility getFacility() { + return facility; + } + + @Override + public Map, AcceptedDrtRequest> getDropoffRequests() { + return Collections.emptyMap(); + } + + @Override + public Map, AcceptedDrtRequest> getPickupRequests() { + return Collections.emptyMap(); + } + + @Override + public void addDropoffRequest(AcceptedDrtRequest request) { + throw new RuntimeException("Not supported"); + } + + @Override + public void addPickupRequest(AcceptedDrtRequest request) { + throw new RuntimeException("Not supported"); + } + + @Override + public void removePickupRequest(Id requestId) { + throw new RuntimeException("Not supported"); + } + + @Override + public void removeDropoffRequest(Id requestId) { + throw new RuntimeException("Not supported"); + } +} diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftDrtScheduleInquiry.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftDrtScheduleInquiry.java index 7fb582caea6..d598bb29b13 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftDrtScheduleInquiry.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftDrtScheduleInquiry.java @@ -2,13 +2,13 @@ import com.google.inject.Inject; import org.matsim.contrib.drt.extension.operations.shifts.fleet.ShiftDvrpVehicle; +import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftTask; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; import org.matsim.contrib.drt.scheduler.DrtScheduleInquiry; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.schedule.Schedule; import org.matsim.contrib.dvrp.schedule.ScheduleInquiry; import org.matsim.contrib.dvrp.schedule.Task; -import org.matsim.contrib.drt.extension.operations.shifts.schedule.WaitForShiftStayTask; import org.matsim.core.mobsim.framework.MobsimTimer; import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.STAY; @@ -42,7 +42,7 @@ public boolean isIdle(DvrpVehicle vehicle) { } } Task currentTask = schedule.getCurrentTask(); - if(currentTask instanceof WaitForShiftStayTask) { + if(currentTask instanceof WaitForShiftTask) { return false; } return currentTask.getTaskIdx() == schedule.getTaskCount() - 1 diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskScheduler.java index 2b9b3415d5c..dc8187c0fce 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskScheduler.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskScheduler.java @@ -23,4 +23,8 @@ public interface ShiftTaskScheduler { boolean updateShiftChange(ShiftDvrpVehicle vehicle, Link link, DrtShift shift, LinkTimePair start, OperationFacility facility, Task lastTask); + + void planAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShift shift); + + void cancelAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShift shift); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java index d6d272371e9..0cb820990b2 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java @@ -18,10 +18,7 @@ import org.matsim.contrib.dvrp.fleet.Fleet; import org.matsim.contrib.dvrp.path.VrpPathWithTravelData; import org.matsim.contrib.dvrp.path.VrpPaths; -import org.matsim.contrib.dvrp.schedule.DriveTask; -import org.matsim.contrib.dvrp.schedule.Schedule; -import org.matsim.contrib.dvrp.schedule.StayTask; -import org.matsim.contrib.dvrp.schedule.Task; +import org.matsim.contrib.dvrp.schedule.*; import org.matsim.contrib.dvrp.tracker.OnlineDriveTaskTracker; import org.matsim.contrib.dvrp.util.LinkTimePair; import org.matsim.core.mobsim.framework.MobsimTimer; @@ -266,10 +263,13 @@ private void appendShiftChange(DvrpVehicle vehicle, DrtShift shift, OperationFac public void startShift(ShiftDvrpVehicle vehicle, double now, DrtShift shift) { Schedule schedule = vehicle.getSchedule(); StayTask stayTask = (StayTask) schedule.getCurrentTask(); - if (stayTask instanceof WaitForShiftStayTask) { - ((WaitForShiftStayTask) stayTask).getFacility().deregisterVehicle(vehicle.getId()); + if (stayTask instanceof WaitForShiftTask) { + ((WaitForShiftTask) stayTask).getFacility().deregisterVehicle(vehicle.getId()); stayTask.setEndTime(now); - schedule.addTask(taskFactory.createStayTask(vehicle, now, shift.getEndTime(), stayTask.getLink())); + if(Schedules.getLastTask(schedule).equals(stayTask)) { + //nothing planned yet. + schedule.addTask(taskFactory.createStayTask(vehicle, now, shift.getEndTime(), stayTask.getLink())); + } } else { throw new IllegalStateException("Vehicle cannot start shift during task:" + stayTask.getTaskType().name()); } @@ -291,6 +291,24 @@ public boolean updateShiftChange(ShiftDvrpVehicle vehicle, Link link, DrtShift s return false; } + @Override + public void planAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShift shift) { + Schedule schedule = vehicle.getSchedule(); + StayTask stayTask = (StayTask) schedule.getCurrentTask(); + if (stayTask instanceof WaitForShiftTask) { + stayTask.setEndTime(Math.max(timeStep, shift.getStartTime())); + } + } + + @Override + public void cancelAssignedShift(ShiftDvrpVehicle vehicle, double timeStep, DrtShift shift) { + Schedule schedule = vehicle.getSchedule(); + StayTask stayTask = (StayTask) schedule.getCurrentTask(); + if (stayTask instanceof WaitForShiftTask) { + stayTask.setEndTime(vehicle.getServiceEndTime()); + } + } + private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vrpPath, DrtShift shift, OperationFacility facility, Task lastTask) { Schedule schedule = vehicle.getSchedule(); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java new file mode 100644 index 00000000000..fa6ad3cb0ce --- /dev/null +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java @@ -0,0 +1,298 @@ +package org.matsim.contrib.drt.extension.operations.shifts.run; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.matsim.api.core.v01.Coord; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.api.core.v01.population.*; +import org.matsim.contrib.common.zones.systems.grid.square.SquareGridZoneSystemParams; +import org.matsim.contrib.drt.analysis.zonal.DrtZoneSystemParams; +import org.matsim.contrib.drt.extension.DrtWithExtensionsConfigGroup; +import org.matsim.contrib.drt.extension.operations.DrtOperationsControlerCreator; +import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; +import org.matsim.contrib.drt.extension.operations.operationFacilities.*; +import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftSpecificationImpl; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecificationImpl; +import org.matsim.contrib.drt.optimizer.constraints.DefaultDrtOptimizationConstraintsSet; +import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams; +import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; +import org.matsim.contrib.drt.optimizer.rebalancing.mincostflow.MinCostFlowRebalancingStrategyParams; +import org.matsim.contrib.drt.prebooking.PrebookingModeQSimModule; +import org.matsim.contrib.drt.prebooking.PrebookingParams; +import org.matsim.contrib.drt.prebooking.logic.AttributeBasedPrebookingLogic; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.DrtControlerCreator; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import org.matsim.contrib.dvrp.fleet.FleetSpecification; +import org.matsim.contrib.dvrp.fleet.FleetSpecificationImpl; +import org.matsim.contrib.dvrp.fleet.ImmutableDvrpVehicleSpecification; +import org.matsim.contrib.dvrp.passenger.PassengerRequestRejectedEventHandler; +import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.zone.skims.DvrpTravelTimeMatrixParams; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.ReplanningConfigGroup; +import org.matsim.core.config.groups.ScoringConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.Controler; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.population.PopulationUtils; +import org.matsim.core.utils.geometry.CoordUtils; + +import java.util.HashSet; +import java.util.Set; + + + +/** + * @author nkuehnel / MOIA + */ +public class RunPrebookingShiftDrtScenarioIT { + + + @Test + void test() { + + MultiModeDrtConfigGroup multiModeDrtConfigGroup = new MultiModeDrtConfigGroup(DrtWithExtensionsConfigGroup::new); + + DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup = (DrtWithExtensionsConfigGroup) multiModeDrtConfigGroup.createParameterSet("drt"); + drtWithShiftsConfigGroup.mode = TransportMode.drt; + DefaultDrtOptimizationConstraintsSet defaultConstraintsSet = + (DefaultDrtOptimizationConstraintsSet) drtWithShiftsConfigGroup.addOrGetDrtOptimizationConstraintsParams() + .addOrGetDefaultDrtOptimizationConstraintsSet(); + drtWithShiftsConfigGroup.stopDuration = 30.; + defaultConstraintsSet.maxTravelTimeAlpha = 1.5; + defaultConstraintsSet.maxTravelTimeBeta = 10. * 60.; + defaultConstraintsSet.maxWaitTime = 600.; + defaultConstraintsSet.rejectRequestIfMaxWaitOrTravelTimeViolated = true; + defaultConstraintsSet.maxWalkDistance = 1000.; + drtWithShiftsConfigGroup.operationalScheme = DrtConfigGroup.OperationalScheme.door2door; + + drtWithShiftsConfigGroup.addParameterSet(new ExtensiveInsertionSearchParams()); + + ConfigGroup rebalancing = drtWithShiftsConfigGroup.createParameterSet("rebalancing"); + drtWithShiftsConfigGroup.addParameterSet(rebalancing); + ((RebalancingParams) rebalancing).interval = 600; + + MinCostFlowRebalancingStrategyParams strategyParams = new MinCostFlowRebalancingStrategyParams(); + strategyParams.targetAlpha = 0.3; + strategyParams.targetBeta = 0.3; + + drtWithShiftsConfigGroup.getRebalancingParams().get().addParameterSet(strategyParams); + + SquareGridZoneSystemParams zoneParams = new SquareGridZoneSystemParams(); + zoneParams.cellSize = 500.; + + DrtZoneSystemParams drtZoneSystemParams = new DrtZoneSystemParams(); + drtZoneSystemParams.addParameterSet(zoneParams); + drtWithShiftsConfigGroup.addParameterSet(drtZoneSystemParams); + + DvrpConfigGroup dvrpConfigGroup = new DvrpConfigGroup(); + DvrpTravelTimeMatrixParams matrixParams = dvrpConfigGroup.getTravelTimeMatrixParams(); + matrixParams.addParameterSet(zoneParams); + + multiModeDrtConfigGroup.addParameterSet(drtWithShiftsConfigGroup); + + final Config config = ConfigUtils.createConfig(multiModeDrtConfigGroup, + dvrpConfigGroup); + + Set modes = new HashSet<>(); + modes.add("drt"); + config.travelTimeCalculator().setAnalyzedModes(modes); + + ScoringConfigGroup.ModeParams scoreParams = new ScoringConfigGroup.ModeParams("drt"); + config.scoring().addModeParams(scoreParams); + ScoringConfigGroup.ModeParams scoreParams2 = new ScoringConfigGroup.ModeParams("walk"); + config.scoring().addModeParams(scoreParams2); + + final ScoringConfigGroup.ActivityParams start = new ScoringConfigGroup.ActivityParams("start"); + start.setScoringThisActivityAtAll(false); + final ScoringConfigGroup.ActivityParams end = new ScoringConfigGroup.ActivityParams("end"); + end.setScoringThisActivityAtAll(false); + + config.scoring().addActivityParams(start); + config.scoring().addActivityParams(end); + + config.qsim().setSimStarttimeInterpretation(QSimConfigGroup.StarttimeInterpretation.onlyUseStarttime); + config.qsim().setSimEndtimeInterpretation(QSimConfigGroup.EndtimeInterpretation.minOfEndtimeAndMobsimFinished); + + final ReplanningConfigGroup.StrategySettings stratSets = new ReplanningConfigGroup.StrategySettings(); + stratSets.setWeight(1); + stratSets.setStrategyName("ChangeExpBeta"); + config.replanning().addStrategySettings(stratSets); + + config.controller().setLastIteration(0); + config.controller().setWriteEventsInterval(1); + + config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); + config.controller().setOutputDirectory("test/output/prebooking_shifts"); + + DrtOperationsParams operationsParams = (DrtOperationsParams) drtWithShiftsConfigGroup.createParameterSet(DrtOperationsParams.SET_NAME); + ShiftsParams shiftsParams = (ShiftsParams) operationsParams.createParameterSet(ShiftsParams.SET_NAME); + OperationFacilitiesParams operationFacilitiesParams = (OperationFacilitiesParams) operationsParams.createParameterSet(OperationFacilitiesParams.SET_NAME); + operationsParams.addParameterSet(shiftsParams); + operationsParams.addParameterSet(operationFacilitiesParams); + + shiftsParams.considerUpcomingShiftsForInsertion = true; + drtWithShiftsConfigGroup.addParameterSet(operationsParams); + + PrebookingParams prebookingParams = new PrebookingParams(); + prebookingParams.maximumPassengerDelay = 600; + prebookingParams.unschedulingMode = PrebookingParams.UnschedulingMode.Routing; + prebookingParams.scheduleWaitBeforeDrive = true; + drtWithShiftsConfigGroup.addParameterSet(prebookingParams); + + Scenario scenario = DrtControlerCreator.createScenarioWithDrtRouteFactory(config); + prepareNetwork(scenario); + preparePopulation(scenario); + + final Controler run = DrtOperationsControlerCreator.createControler(config, scenario, false); + prepareOperations(run, drtWithShiftsConfigGroup); + + run.addOverridingQSimModule(new PrebookingModeQSimModule(drtWithShiftsConfigGroup.getMode(), + prebookingParams)); + AttributeBasedPrebookingLogic.install(run, drtWithShiftsConfigGroup); + + Set> rejectedPersons = new HashSet<>(); + run.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addEventHandlerBinding().toInstance((PassengerRequestRejectedEventHandler) event -> rejectedPersons.addAll(event.getPersonIds())); + } + }); + + run.run(); + + + Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(1))); + Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(2))); + Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(3))); + Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(4))); + } + + private void preparePopulation(Scenario scenario) { + Population population = scenario.getPopulation(); + PopulationFactory factory = PopulationUtils.getFactory(); + + //person 1 - prebooking submitted once shift is assigned (but not started) for time when shift should be active - ok + { + Person person = factory.createPerson(Id.createPersonId(1)); + Plan plan = factory.createPlan(); + Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); + start.setEndTime(5000); + start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 1800.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.); + plan.addActivity(start); + plan.addLeg(factory.createLeg("drt")); + plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); + person.addPlan(plan); + population.addPerson(person); + } + + //person 2 - prebooking submitted before shift is assigned for time when shift should be active - rejected + { + Person person = factory.createPerson(Id.createPersonId(2)); + Plan plan = factory.createPlan(); + Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); + start.setEndTime(5000); + start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 900.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.); + plan.addActivity(start); + plan.addLeg(factory.createLeg("drt")); + plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); + person.addPlan(plan); + population.addPerson(person); + } + + //person 3 - prebooking submitted during shift for time when shift should be active - ok + { + Person person = factory.createPerson(Id.createPersonId(3)); + Plan plan = factory.createPlan(); + Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); + start.setEndTime(5000); + start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 5000.); + plan.addActivity(start); + plan.addLeg(factory.createLeg("drt")); + plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); + person.addPlan(plan); + population.addPerson(person); + } + + //person 4 - prebooking submitted during shift for time when shift should be ended - rejected + { + Person person = factory.createPerson(Id.createPersonId(4)); + Plan plan = factory.createPlan(); + Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); + start.setEndTime(8000); + start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 8000.); + plan.addActivity(start); + plan.addLeg(factory.createLeg("drt")); + plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); + person.addPlan(plan); + population.addPerson(person); + } + } + + private static void prepareOperations(Controler run, DrtWithExtensionsConfigGroup drtWithShiftsConfigGroup) { + FleetSpecification fleetSpecification = new FleetSpecificationImpl(); + fleetSpecification.addVehicleSpecification(ImmutableDvrpVehicleSpecification.newBuilder() // + .id(Id.create("v1", DvrpVehicle.class)) // + .capacity(1) // + .serviceBeginTime(0.0) // + .serviceEndTime(24 * 3600) // + .startLinkId(Id.createLinkId(1)) // + .build()); + + OperationFacilitiesSpecification opFasSpecification = new OperationFacilitiesSpecificationImpl(); + opFasSpecification.addOperationFacilitySpecification(OperationFacilitySpecificationImpl + .newBuilder() + .capacity(1) + .type(OperationFacilityType.hub) + .coord(new Coord(1000, 1000)) + .linkId(Id.createLinkId(1)) + .id(Id.create(1, OperationFacility.class)) + .build()); + + DrtShiftsSpecification shiftsSpecification = new DrtShiftsSpecificationImpl(); + shiftsSpecification.addShiftSpecification(DrtShiftSpecificationImpl.newBuilder() + .start(3600) + .end(7200) + .id(Id.create(1, DrtShift.class)) + .operationFacility(Id.create(1, OperationFacility.class)) + .build() + ); + run.addOverridingModule(new AbstractDvrpModeModule(drtWithShiftsConfigGroup.getMode()) { + @Override + public void install() { + bindModal(FleetSpecification.class).toInstance(fleetSpecification); + bindModal(OperationFacilitiesSpecification.class).toInstance(opFasSpecification); + bindModal(DrtShiftsSpecification.class).toInstance(shiftsSpecification); + } + }); + + } + + private void prepareNetwork(Scenario scenario) { + Network network = scenario.getNetwork(); + Node node1 = NetworkUtils.createAndAddNode(network, Id.createNodeId(1), new Coord(0, 0)); + Node node2 = NetworkUtils.createAndAddNode(network, Id.createNodeId(2), new Coord(1000, 1000)); + + NetworkUtils.createAndAddLink(network, Id.createLinkId(1), node1, node2, CoordUtils.length(node2.getCoord()), 50 / 3.6, 100, 1, null, null); + NetworkUtils.createAndAddLink(network, Id.createLinkId(2), node2, node1, CoordUtils.length(node2.getCoord()), 50 / 3.6, 100, 1, null, null); + } + +} diff --git a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtControlerCreator.java b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtControlerCreator.java index ab438acc805..1b4435829f1 100644 --- a/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtControlerCreator.java +++ b/contribs/drt/src/main/java/org/matsim/contrib/drt/run/DrtControlerCreator.java @@ -60,11 +60,22 @@ public static Scenario createScenarioWithDrtRouteFactory(Config config) { * @return */ public static Controler createControler(Config config, boolean otfvis) { - MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config); - DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtConfig, config.scoring(), config.routing()); - Scenario scenario = createScenarioWithDrtRouteFactory(config); ScenarioUtils.loadScenario(scenario); + return createControler(config, scenario, otfvis); + } + + /** + * Creates a controller in one step. + * + * @param config + * @param scenario + * @param otfvis + * @return + */ + public static Controler createControler(Config config, Scenario scenario, boolean otfvis) { + MultiModeDrtConfigGroup multiModeDrtConfig = MultiModeDrtConfigGroup.get(config); + DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtConfig, config.scoring(), config.routing()); Controler controler = new Controler(scenario); controler.addOverridingModule(new DvrpModule()); From 4a5ad3fa7a3c1e41a442556ad524806d25bc9745 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 19 Jul 2024 15:05:48 +0200 Subject: [PATCH 2/9] cancel assigned shifts --- .../operations/shifts/dispatcher/DrtShiftDispatcherImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index 7cfa4579612..aeda75ba862 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -160,6 +160,7 @@ private void startShifts(double timeStep) { break; } else if (assignedShiftEntry.shift().getEndTime() < timeStep) { logger.warn("Too late to start shift " + assignedShiftEntry.shift().getId()); + shiftTaskScheduler.cancelAssignedShift(assignedShiftEntry.vehicle(), timeStep, assignedShiftEntry.shift()); assignedShiftEntry.vehicle().getShifts().remove(assignedShiftEntry.shift()); iterator.remove(); continue; @@ -185,7 +186,7 @@ private void assignShifts(double timeStep) { unscheduledShifts.removeIf(shift -> { if (shift.getStartTime() + drtShiftParams.maxUnscheduledShiftDelay < timeStep ) { logger.warn("Shift with ID " + shift.getId() + " could not be assigned and is being removed as start time is longer in the past than defined by maxUnscheduledShiftDelay."); - return true; + return true; } return false; }); From 7c2f4d213b8f0058a5d83a1048b0267e8cc7ae3e Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 19 Jul 2024 17:35:38 +0200 Subject: [PATCH 3/9] add some documentation --- .../drt/extension/operations/README.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/README.md diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/README.md b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/README.md new file mode 100644 index 00000000000..9f7200cc257 --- /dev/null +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/README.md @@ -0,0 +1,72 @@ +# DRT Operations + +Provides functionality to realistically simulate operational aspects, +designed for, bot not limited to, non-autonomous services. + +Initially developed for MOIA GmbH + +If used, please cite: + +Felix Zwick, Nico Kuehnel, Sebastian Hörl. +Shifts in perspective: Operational aspects in (non-)autonomous +ride-pooling simulations. +Transportation Research Part A: Policy and Practice, +Volume 165, 2022, Pages 300-320. +https://doi.org/10.1016/j.tra.2022.09.001. + + +## Core features: + +- Operation facilities +- (Driver) shifts + + +The entry point for setting up a simulation are the specific control(l)er creators: +- DrtOperationsControlerCreator + - or +- EDrtOperationsControlerCreator + - in the electric vehicles case + +## Operation Facilities +Operation facilities are meant to represent hubs and in-field break locations. +The facilities have a capacity that cannot be exceeded and may be linked to +existing chargers via the id. + +(Driver) shifts may only start or end at operation facilities in the default setup. +Vehicles will route to operation facilities to end a shift or for scheduling a break. + +Operational facilities may be described with an xml file like this: +``` + + + + + + + + +``` + +## Shifts +Shifts define periods in which vehicles may be active serving passengers. +Shifts are dynamically assigned to vehicles. + +In autonomous settings, shifts may be used to model up- and down-time and/or cleaning +cycles. + +Shifts have a start and end time and can optionally have a break which is defined +by earliest start and latest end as well as a duration. Optionally, as operation +facility id may be defined to control the location of the start/end of the shift. + +Shifts may be described in an xml file likes this: +``` + + + + + + + + +``` + From 106766a42a240d268d02ba5bfb3536426b329b1b Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 19 Jul 2024 17:37:06 +0200 Subject: [PATCH 4/9] shift drt maintenance --- .../dispatcher/DrtShiftDispatcherImpl.java | 68 +++++++++---------- .../scheduler/ShiftTaskSchedulerImpl.java | 6 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index aeda75ba862..27bdeb5125d 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -140,12 +140,21 @@ private void checkBreaks() { for (ShiftEntry activeShift : activeShifts) { final DrtShift shift = activeShift.shift(); if (shift != null && shift.isStarted()) { - OperationFacility breakFacility = decideOnBreak(activeShift); - if (breakFacility != null) { - shiftTaskScheduler.relocateForBreak(activeShift.vehicle(), breakFacility, shift); - eventsManager.processEvent(new DrtShiftBreakScheduledEvent(timer.getTimeOfDay(), mode, shift.getId(), - activeShift.vehicle().getId(), breakFacility.getLinkId(), - shift.getBreak().orElseThrow().getScheduledLatestArrival())); + if (hasSchedulableBreak(shift, timer.getTimeOfDay())) { + Optional breakFacility = findBreakFacility(activeShift); + if (breakFacility.isPresent()) { + OperationFacility facility = breakFacility.get(); + if (facility.register(activeShift.vehicle().getId())) { + eventsManager.processEvent(new ShiftFacilityRegistrationEvent( + timer.getTimeOfDay(), mode, activeShift.vehicle().getId(), facility.getId())); + shiftTaskScheduler.relocateForBreak(activeShift.vehicle(), facility, shift); + eventsManager.processEvent(new DrtShiftBreakScheduledEvent(timer.getTimeOfDay(), mode, shift.getId(), + activeShift.vehicle().getId(), facility.getLinkId(), + shift.getBreak().orElseThrow().getScheduledLatestArrival())); + return; + } + } + throw new RuntimeException("Could not schedule break!"); } } } @@ -188,7 +197,7 @@ private void assignShifts(double timeStep) { logger.warn("Shift with ID " + shift.getId() + " could not be assigned and is being removed as start time is longer in the past than defined by maxUnscheduledShiftDelay."); return true; } - return false; + return false; }); // Assign shifts @@ -440,37 +449,28 @@ private void scheduleShiftEnd(ShiftEntry endingShift) { } } - private OperationFacility decideOnBreak(ShiftEntry activeShift) { + private Optional findBreakFacility(ShiftEntry activeShift) { if (activeShift.shift() != null) { - if (hasSchedulableBreak(activeShift.shift(), timer.getTimeOfDay())) { - final Schedule schedule = activeShift.vehicle().getSchedule(); - Task currentTask = schedule.getCurrentTask(); - Link lastLink; - if (currentTask instanceof DriveTask - && currentTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE) - && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount()-2))) { - LinkTimePair start = ((OnlineDriveTaskTracker) currentTask.getTaskTracker()).getDiversionPoint(); - if(start != null) { - lastLink = start.link; - } else { - lastLink = ((DriveTask) currentTask).getPath().getToLink(); - } - } else { - lastLink = ((DrtStayTask) schedule.getTasks() - .get(schedule.getTaskCount() - 1)).getLink(); - } - final OperationFacility shiftBreakFacility = breakFacilityFinder.findFacility(lastLink.getCoord()); - if (shiftBreakFacility == null) { - throw new RuntimeException("Could not schedule break!"); - } - if (shiftBreakFacility.register(activeShift.vehicle().getId())) { - eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), - mode, activeShift.vehicle().getId(), shiftBreakFacility.getId())); - return shiftBreakFacility; + final Schedule schedule = activeShift.vehicle().getSchedule(); + Task currentTask = schedule.getCurrentTask(); + Link lastLink; + if (currentTask instanceof DriveTask + && currentTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE) + && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount()-2))) { + LinkTimePair start = ((OnlineDriveTaskTracker) currentTask.getTaskTracker()).getDiversionPoint(); + if(start != null) { + lastLink = start.link; + } else { + lastLink = ((DriveTask) currentTask).getPath().getToLink(); } + } else { + lastLink = ((DrtStayTask) schedule.getTasks() + .get(schedule.getTaskCount() - 1)).getLink(); } + final OperationFacility shiftBreakFacility = breakFacilityFinder.findFacility(lastLink.getCoord()); + return Optional.of(shiftBreakFacility); } - return null; + return Optional.empty(); } @Override diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java index 0cb820990b2..94b5c3d0fed 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/scheduler/ShiftTaskSchedulerImpl.java @@ -92,7 +92,7 @@ public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFa double startTime = path.getArrivalTime(); double endTime = startTime + shift.getBreak().orElseThrow().getDuration(); - double latestDetourArrival = path.getDepartureTime() + path.getTravelTime() + 1.5; + double latestDetourArrival = path.getDepartureTime() + path.getTravelTime() * 1.5; relocateForBreakImpl(vehicle, startTime, endTime, latestDetourArrival, toLink, shift, breakFacility); } else { @@ -153,10 +153,10 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do // append SHIFT_BREAK task DrtShiftBreak shiftBreak = shift.getBreak().orElseThrow(); - ShiftBreakTask dropoffStopTask = taskFactory.createShiftBreakTask(vehicle, startTime, + ShiftBreakTask shiftBreakTask = taskFactory.createShiftBreakTask(vehicle, startTime, endTime, link, shiftBreak, breakFacility); - schedule.addTask(dropoffStopTask); + schedule.addTask(shiftBreakTask); schedule.addTask(taskFactory.createStayTask(vehicle, endTime, shift.getEndTime(), link)); From c7a9904df8156dfc88481610bd909f2605f6aaff Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 19 Jul 2024 17:55:32 +0200 Subject: [PATCH 5/9] some more drt shift maintenance --- ...stOperationFacilityWithCapacityFinder.java | 9 ++- .../OperationFacilityFinder.java | 6 +- .../dispatcher/DrtShiftDispatcherImpl.java | 78 +++++++++---------- 3 files changed, 46 insertions(+), 47 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/operationFacilities/NearestOperationFacilityWithCapacityFinder.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/operationFacilities/NearestOperationFacilityWithCapacityFinder.java index 1df98354824..7d41752548e 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/operationFacilities/NearestOperationFacilityWithCapacityFinder.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/operationFacilities/NearestOperationFacilityWithCapacityFinder.java @@ -4,6 +4,7 @@ import org.matsim.contrib.common.util.DistanceUtils; import java.util.Comparator; +import java.util.Optional; import java.util.function.Predicate; /** @@ -21,7 +22,7 @@ public NearestOperationFacilityWithCapacityFinder(OperationFacilities operationF } @Override - public OperationFacility findFacilityOfType(Coord coord, OperationFacilityType type) { + public Optional findFacilityOfType(Coord coord, OperationFacilityType type) { Predicate filter; switch (type) { case hub: @@ -37,15 +38,15 @@ public OperationFacility findFacilityOfType(Coord coord, OperationFacilityType t .filter(filter) .filter(OperationFacility::hasCapacity) .min(Comparator.comparing( - f -> DistanceUtils.calculateSquaredDistance(coord, f.getCoord()))).orElse(null); + f -> DistanceUtils.calculateSquaredDistance(coord, f.getCoord()))); } @Override - public OperationFacility findFacility(Coord coord) { + public Optional findFacility(Coord coord) { return operationFacilities.getDrtOperationFacilities().values().stream() .filter(OperationFacility::hasCapacity) .min(Comparator.comparing( - f -> DistanceUtils.calculateSquaredDistance(coord, f.getCoord()))).orElse(null); + f -> DistanceUtils.calculateSquaredDistance(coord, f.getCoord()))); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/operationFacilities/OperationFacilityFinder.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/operationFacilities/OperationFacilityFinder.java index 8262f5938f5..469f7f3703b 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/operationFacilities/OperationFacilityFinder.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/operationFacilities/OperationFacilityFinder.java @@ -2,12 +2,14 @@ import org.matsim.api.core.v01.Coord; +import java.util.Optional; + /** * @author nkuehnel / MOIA */ public interface OperationFacilityFinder { - OperationFacility findFacilityOfType(Coord coord, OperationFacilityType type); + Optional findFacilityOfType(Coord coord, OperationFacilityType type); - OperationFacility findFacility(Coord coord); + Optional findFacility(Coord coord); } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java index 27bdeb5125d..5d983e81f05 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/dispatcher/DrtShiftDispatcherImpl.java @@ -370,23 +370,25 @@ private void updateShiftEnd(ShiftEntry next) { } } - final OperationFacility shiftChangeFacility; + final Optional maybeFacility; if (drtShiftParams.allowInFieldChangeover) { - shiftChangeFacility = breakFacilityFinder.findFacility(start.link.getCoord()); + maybeFacility = breakFacilityFinder.findFacility(start.link.getCoord()); } else { - shiftChangeFacility = breakFacilityFinder.findFacilityOfType(start.link.getCoord(), + maybeFacility = breakFacilityFinder.findFacilityOfType(start.link.getCoord(), OperationFacilityType.hub); } - if (shiftChangeFacility != null && changeOverTask != null - && !(shiftChangeFacility.getId().equals(changeOverTask.getFacility().getId()))) { - if (shiftChangeFacility.hasCapacity()) { - if (shiftTaskScheduler.updateShiftChange(next.vehicle(), - network.getLinks().get(shiftChangeFacility.getLinkId()), next.shift(), start, - shiftChangeFacility, lastTask)) { - shiftChangeFacility.register(next.vehicle().getId()); - changeOverTask.getFacility().deregisterVehicle(next.vehicle().getId()); - eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), - mode, next.vehicle().getId(), shiftChangeFacility.getId())); + if (maybeFacility.isPresent()) { + OperationFacility shiftChangeFacility = maybeFacility.get(); + if(changeOverTask != null && !(shiftChangeFacility.getId().equals(changeOverTask.getFacility().getId()))) { + if (shiftChangeFacility.hasCapacity()) { + if (shiftTaskScheduler.updateShiftChange(next.vehicle(), + network.getLinks().get(shiftChangeFacility.getLinkId()), next.shift(), start, + shiftChangeFacility, lastTask)) { + shiftChangeFacility.register(next.vehicle().getId()); + changeOverTask.getFacility().deregisterVehicle(next.vehicle().getId()); + eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), + mode, next.vehicle().getId(), shiftChangeFacility.getId())); + } } } } @@ -436,41 +438,35 @@ private void scheduleShiftEnd(ShiftEntry endingShift) { if(shiftChangeoverFacility == null) { shiftChangeoverFacility = breakFacilityFinder.findFacilityOfType(coord, - OperationFacilityType.hub); + OperationFacilityType.hub).orElseThrow(() -> new RuntimeException("Could not find shift end location!")); } - if (shiftChangeoverFacility != null && shiftChangeoverFacility.register(endingShift.vehicle().getId())) { - shiftTaskScheduler.relocateForShiftChange(endingShift.vehicle(), - network.getLinks().get(shiftChangeoverFacility.getLinkId()), endingShift.shift(), shiftChangeoverFacility); - eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), mode, endingShift.vehicle().getId(), - shiftChangeoverFacility.getId())); - } else { - throw new RuntimeException("Could not find shift end location!"); - } + Verify.verify(shiftChangeoverFacility.register(endingShift.vehicle().getId()), "Could not register vehicle at facility."); + + shiftTaskScheduler.relocateForShiftChange(endingShift.vehicle(), + network.getLinks().get(shiftChangeoverFacility.getLinkId()), endingShift.shift(), shiftChangeoverFacility); + eventsManager.processEvent(new ShiftFacilityRegistrationEvent(timer.getTimeOfDay(), mode, endingShift.vehicle().getId(), + shiftChangeoverFacility.getId())); } private Optional findBreakFacility(ShiftEntry activeShift) { - if (activeShift.shift() != null) { - final Schedule schedule = activeShift.vehicle().getSchedule(); - Task currentTask = schedule.getCurrentTask(); - Link lastLink; - if (currentTask instanceof DriveTask - && currentTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE) - && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount()-2))) { - LinkTimePair start = ((OnlineDriveTaskTracker) currentTask.getTaskTracker()).getDiversionPoint(); - if(start != null) { - lastLink = start.link; - } else { - lastLink = ((DriveTask) currentTask).getPath().getToLink(); - } - } else { - lastLink = ((DrtStayTask) schedule.getTasks() - .get(schedule.getTaskCount() - 1)).getLink(); + final Schedule schedule = activeShift.vehicle().getSchedule(); + Task currentTask = schedule.getCurrentTask(); + Link lastLink; + if (currentTask instanceof DriveTask + && currentTask.getTaskType().equals(EmptyVehicleRelocator.RELOCATE_VEHICLE_TASK_TYPE) + && currentTask.equals(schedule.getTasks().get(schedule.getTaskCount()-2))) { + LinkTimePair start = ((OnlineDriveTaskTracker) currentTask.getTaskTracker()).getDiversionPoint(); + if(start != null) { + lastLink = start.link; + } else { + lastLink = ((DriveTask) currentTask).getPath().getToLink(); } - final OperationFacility shiftBreakFacility = breakFacilityFinder.findFacility(lastLink.getCoord()); - return Optional.of(shiftBreakFacility); + } else { + lastLink = ((DrtStayTask) schedule.getTasks() + .get(schedule.getTaskCount() - 1)).getLink(); } - return Optional.empty(); + return breakFacilityFinder.findFacility(lastLink.getCoord()); } @Override From 6dc04214fed5b5b2d8e09e84dea63c2ed47cd8c2 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 19 Jul 2024 19:30:22 +0200 Subject: [PATCH 6/9] consider break corridors for (pre)bookings --- .../ShiftInsertionCostCalculator.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/insertion/ShiftInsertionCostCalculator.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/insertion/ShiftInsertionCostCalculator.java index 7055e4569be..d6b3c978146 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/insertion/ShiftInsertionCostCalculator.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/optimizer/insertion/ShiftInsertionCostCalculator.java @@ -3,6 +3,7 @@ import org.matsim.contrib.drt.extension.operations.shifts.fleet.ShiftDvrpVehicle; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftBreakTask; import org.matsim.contrib.drt.extension.operations.shifts.schedule.ShiftChangeOverTask; +import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreak; import org.matsim.contrib.drt.optimizer.VehicleEntry; import org.matsim.contrib.drt.optimizer.Waypoint; @@ -44,7 +45,8 @@ boolean checkShiftTimeConstraintsForScheduledRequests(Insertion insertion, Detou final int pickupIdx = insertion.pickup.index; final int dropoffIdx = insertion.dropoff.index; - double shiftEndTime = ((ShiftDvrpVehicle) vEntry.vehicle).getShifts().peek().getEndTime(); + DrtShift currentShift = ((ShiftDvrpVehicle) vEntry.vehicle).getShifts().peek(); + double shiftEndTime = currentShift.getEndTime(); if(shiftEndTime < detourTimeInfo.dropoffDetourInfo.arrivalTime) { // fast fail which also captures requests that are prebooked for times outside of the shift. return false; @@ -118,6 +120,31 @@ boolean checkShiftTimeConstraintsForScheduledRequests(Insertion insertion, Detou return false; } } + + + // avoid shrinking break corridor too much (rather coarse for now) + if(currentShift.getBreak().isPresent()) { + DrtShiftBreak drtShiftBreak = currentShift.getBreak().get(); + if(!drtShiftBreak.isScheduled()) { + + + if(detourTimeInfo.dropoffDetourInfo.arrivalTime < drtShiftBreak.getEarliestBreakStartTime()) { + // insertion finished before break corridor + //ok + } else if(detourTimeInfo.pickupDetourInfo.departureTime > drtShiftBreak.getLatestBreakEndTime()) { + // insertion start after break corridor + //ok + } else { + double remainingTime = drtShiftBreak.getLatestBreakEndTime() - detourTimeInfo.dropoffDetourInfo.arrivalTime; + if (remainingTime < drtShiftBreak.getDuration()) { + // no meaningful break possible after insertion + // (there could still be enough time before a prebooking though) + return false; + } + } + } + } + return true; //all time constraints of all stops are satisfied } } From 6f8d84143ffc936023c51359d773ace983e8699a Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 19 Jul 2024 19:30:40 +0200 Subject: [PATCH 7/9] consider break corridors for (pre)bookings --- .../run/RunPrebookingShiftDrtScenarioIT.java | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java index fa6ad3cb0ce..5babef611b3 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/shifts/run/RunPrebookingShiftDrtScenarioIT.java @@ -16,10 +16,7 @@ import org.matsim.contrib.drt.extension.operations.DrtOperationsParams; import org.matsim.contrib.drt.extension.operations.operationFacilities.*; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShift; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftSpecificationImpl; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecification; -import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftsSpecificationImpl; +import org.matsim.contrib.drt.extension.operations.shifts.shift.*; import org.matsim.contrib.drt.optimizer.constraints.DefaultDrtOptimizationConstraintsSet; import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams; import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; @@ -146,6 +143,7 @@ void test() { operationsParams.addParameterSet(operationFacilitiesParams); shiftsParams.considerUpcomingShiftsForInsertion = true; + shiftsParams.shiftEndLookAhead = 900.; drtWithShiftsConfigGroup.addParameterSet(operationsParams); PrebookingParams prebookingParams = new PrebookingParams(); @@ -180,6 +178,8 @@ public void install() { Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(2))); Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(3))); Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(4))); + Assertions.assertFalse(rejectedPersons.contains(Id.createPersonId(5))); + Assertions.assertTrue(rejectedPersons.contains(Id.createPersonId(6))); } private void preparePopulation(Scenario scenario) { @@ -238,7 +238,37 @@ private void preparePopulation(Scenario scenario) { Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); start.setEndTime(8000); start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.); - start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 8000.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 11000.); + plan.addActivity(start); + plan.addLeg(factory.createLeg("drt")); + plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); + person.addPlan(plan); + population.addPerson(person); + } + + //person 5 - prebooking submitted during shift for time which falls into break beginning of break corridor with enough remaining time - ok + { + Person person = factory.createPerson(Id.createPersonId(5)); + Plan plan = factory.createPlan(); + Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); + start.setEndTime(6000.); + start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 6000.); + plan.addActivity(start); + plan.addLeg(factory.createLeg("drt")); + plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); + person.addPlan(plan); + population.addPerson(person); + } + + //person 6 - prebooking submitted during shift for time which would preclude meaningful break - rejected + { + Person person = factory.createPerson(Id.createPersonId(6)); + Plan plan = factory.createPlan(); + Activity start = factory.createActivityFromLinkId("start", Id.createLinkId(1)); + start.setEndTime(6500.); + start.getAttributes().putAttribute("prebooking:submissionTime" + "drt", 4000.); + start.getAttributes().putAttribute("prebooking:plannedDepartureTime" + "drt", 6500.); plan.addActivity(start); plan.addLeg(factory.createLeg("drt")); plan.addActivity(factory.createActivityFromLinkId("end", Id.createLinkId(2))); @@ -270,8 +300,9 @@ private static void prepareOperations(Controler run, DrtWithExtensionsConfigGrou DrtShiftsSpecification shiftsSpecification = new DrtShiftsSpecificationImpl(); shiftsSpecification.addShiftSpecification(DrtShiftSpecificationImpl.newBuilder() .start(3600) - .end(7200) + .end(10800) .id(Id.create(1, DrtShift.class)) + .shiftBreak(DrtShiftBreakSpecificationImpl.newBuilder().duration(600.).earliestStart(6000.).latestEnd(7000.).build()) .operationFacility(Id.create(1, OperationFacility.class)) .build() ); From ef5de1771ba18773455e8702e0c7c73241d39721 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Fri, 19 Jul 2024 19:31:04 +0200 Subject: [PATCH 8/9] clean up obsolete method --- .../operations/shifts/shift/DefaultShiftBreakImpl.java | 5 ----- .../drt/extension/operations/shifts/shift/DrtShiftBreak.java | 2 -- 2 files changed, 7 deletions(-) diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DefaultShiftBreakImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DefaultShiftBreakImpl.java index 07b094f3dc0..10f36a1d387 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DefaultShiftBreakImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DefaultShiftBreakImpl.java @@ -54,9 +54,4 @@ public boolean isScheduled() { public double getScheduledLatestArrival() { return latestArrivalTime; } - - @Override - public void reset() { - this.latestArrivalTime = UNSCHEDULED_ARRIVAL_TIME; - } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftBreak.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftBreak.java index 2009dcd02f6..86e5500401a 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftBreak.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/operations/shifts/shift/DrtShiftBreak.java @@ -16,6 +16,4 @@ public interface DrtShiftBreak { boolean isScheduled(); double getScheduledLatestArrival(); - - void reset(); } From 2d4f1d7f540fece86cdd7f5e544e6da30050d5a3 Mon Sep 17 00:00:00 2001 From: nkuehnel Date: Tue, 23 Jul 2024 10:59:16 +0200 Subject: [PATCH 9/9] update FISS test, reduce iterations to reduce runtime --- .../contrib/drt/extension/fiss/RunFissDrtScenarioIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/fiss/RunFissDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/fiss/RunFissDrtScenarioIT.java index 2da1b30b225..fc58f3b3b63 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/fiss/RunFissDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/fiss/RunFissDrtScenarioIT.java @@ -135,7 +135,7 @@ void test() { stratSets.setStrategyName("ChangeExpBeta"); config.replanning().addStrategySettings(stratSets); - config.controller().setLastIteration(2); + config.controller().setLastIteration(1); config.controller().setWriteEventsInterval(1); config.controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); @@ -184,7 +184,7 @@ public void install() { } run.run(); - Assertions.assertEquals(23817, linkCounter.getLinkLeaveCount()); + Assertions.assertEquals(20842, linkCounter.getLinkLeaveCount()); } static class LinkCounter implements LinkLeaveEventHandler {