diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java index 00dabefc585..90773153294 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/EDrtModeOptimizerQSimModule.java @@ -59,6 +59,7 @@ import org.matsim.contrib.dvrp.schedule.ScheduleTimingUpdater; import org.matsim.contrib.dvrp.vrpagent.VrpAgentLogic; import org.matsim.contrib.dvrp.vrpagent.VrpLegFactory; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureUtils; import org.matsim.core.api.experimental.events.EventsManager; @@ -116,7 +117,8 @@ protected void configureQSim() { public EmptyVehicleChargingScheduler get() { var taskFactory = getModalInstance(DrtTaskFactory.class); var chargingInfrastructure = getModalInstance(ChargingInfrastructure.class); - return new EmptyVehicleChargingScheduler(timer, taskFactory, chargingInfrastructure); + ChargingStrategy.Factory chargingStrategyFactory = getModalInstance(ChargingStrategy.Factory.class); + return new EmptyVehicleChargingScheduler(timer, taskFactory, chargingInfrastructure, chargingStrategyFactory); } }).asEagerSingleton(); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenario.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenario.java index 741c4047786..915c5efa220 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenario.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/run/RunEDrtScenario.java @@ -22,15 +22,17 @@ import java.net.URL; +import org.matsim.contrib.drt.extension.edrt.optimizer.EDrtVehicleDataEntryFactory.EDrtVehicleDataEntryFactoryProvider; import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; -import org.matsim.contrib.drt.extension.edrt.optimizer.EDrtVehicleDataEntryFactory.EDrtVehicleDataEntryFactoryProvider; +import org.matsim.contrib.dvrp.run.DvrpModes; import org.matsim.contrib.ev.EvConfigGroup; import org.matsim.contrib.ev.charging.ChargeUpToMaxSocStrategy; import org.matsim.contrib.ev.charging.ChargingLogic; import org.matsim.contrib.ev.charging.ChargingPower; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.charging.ChargingWithQueueingAndAssignmentLogic; import org.matsim.contrib.ev.charging.FixedSpeedCharging; import org.matsim.contrib.ev.temperature.TemperatureService; @@ -40,6 +42,8 @@ import org.matsim.core.controler.Controler; import org.matsim.vis.otfvis.OTFVisConfigGroup; +import com.google.inject.Key; + /** * @author Michal Maciejewski (michalm) */ @@ -69,10 +73,13 @@ public void install() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - bind(ChargingLogic.Factory.class).toProvider(new ChargingWithQueueingAndAssignmentLogic.FactoryProvider( - charger -> new ChargeUpToMaxSocStrategy(charger, MAX_RELATIVE_SOC))); + bind(ChargingLogic.Factory.class).to(ChargingWithQueueingAndAssignmentLogic.Factory.class); bind(ChargingPower.Factory.class).toInstance(ev -> new FixedSpeedCharging(ev, CHARGING_SPEED_FACTOR)); bind(TemperatureService.class).toInstance(linkId -> TEMPERATURE); + + for (DrtConfigGroup drtCfg : MultiModeDrtConfigGroup.get(config).getModalElements()) { + bind(Key.get(ChargingStrategy.Factory.class, DvrpModes.mode(drtCfg.mode))).toInstance(new ChargeUpToMaxSocStrategy.Factory(MAX_RELATIVE_SOC)); + } } }); diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtChargingTask.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtChargingTask.java index e2dcfdba751..95b36f65889 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtChargingTask.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtChargingTask.java @@ -20,6 +20,7 @@ package org.matsim.contrib.drt.extension.edrt.schedule; import org.matsim.contrib.drt.schedule.DrtTaskType; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.contrib.evrp.ChargingTaskImpl; @@ -27,7 +28,7 @@ public class EDrtChargingTask extends ChargingTaskImpl { public static final DrtTaskType TYPE = new DrtTaskType("CHARGING"); - public EDrtChargingTask(double beginTime, double endTime, Charger charger, ElectricVehicle ev, double totalEnergy) { - super(TYPE, beginTime, endTime, charger, ev, totalEnergy); + public EDrtChargingTask(double beginTime, double endTime, Charger charger, ElectricVehicle ev, double totalEnergy, ChargingStrategy chargingStrategy) { + super(TYPE, beginTime, endTime, charger, ev, totalEnergy, chargingStrategy); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtTaskFactoryImpl.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtTaskFactoryImpl.java index 4ec83dc7a15..d99fdc6fbfe 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtTaskFactoryImpl.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/schedule/EDrtTaskFactoryImpl.java @@ -26,6 +26,7 @@ import org.matsim.contrib.dvrp.schedule.DefaultStayTask; import org.matsim.contrib.evrp.EvDvrpVehicle; import org.matsim.contrib.evrp.VrpPathEnergyConsumptions; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.Charger; @@ -59,8 +60,8 @@ public DefaultStayTask createInitialTask(DvrpVehicle vehicle, double beginTime, } public EDrtChargingTask createChargingTask(DvrpVehicle vehicle, double beginTime, double endTime, Charger charger, - double totalEnergy) { + double totalEnergy, ChargingStrategy chargingStrategy) { return new EDrtChargingTask(beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), - totalEnergy); + totalEnergy, chargingStrategy); } } diff --git a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/scheduler/EmptyVehicleChargingScheduler.java b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/scheduler/EmptyVehicleChargingScheduler.java index eea29745e80..2df2ed57028 100644 --- a/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/scheduler/EmptyVehicleChargingScheduler.java +++ b/contribs/drt-extensions/src/main/java/org/matsim/contrib/drt/extension/edrt/scheduler/EmptyVehicleChargingScheduler.java @@ -47,10 +47,12 @@ public class EmptyVehicleChargingScheduler { private final MobsimTimer timer; private final EDrtTaskFactoryImpl taskFactory; private final Map, List> linkToChargersMap; + private final ChargingStrategy.Factory chargingStrategyFactory; public EmptyVehicleChargingScheduler(MobsimTimer timer, DrtTaskFactory taskFactory, - ChargingInfrastructure chargingInfrastructure) { + ChargingInfrastructure chargingInfrastructure, ChargingStrategy.Factory chargingStrategyFactory) { this.timer = timer; + this.chargingStrategyFactory = chargingStrategyFactory; this.taskFactory = (EDrtTaskFactoryImpl)taskFactory; linkToChargersMap = chargingInfrastructure.getChargers() .values() @@ -68,15 +70,16 @@ public void chargeVehicle(DvrpVehicle vehicle) { // Empty charger or at least smallest queue charger Charger charger = freeCharger.orElseGet(() -> chargers.stream().min(Comparator.comparingInt(e -> e.getLogic().getQueuedVehicles().size())).orElseThrow()); ElectricVehicle ev = ((EvDvrpVehicle)vehicle).getElectricVehicle(); - if (!charger.getLogic().getChargingStrategy().isChargingCompleted(ev)) { - chargeVehicleImpl(vehicle, charger); + ChargingStrategy strategy = chargingStrategyFactory.createStrategy(charger.getSpecification(), ev); + if (!strategy.isChargingCompleted()) { + chargeVehicleImpl(vehicle, ev, charger, strategy); } } } - private void chargeVehicleImpl(DvrpVehicle vehicle, Charger charger) { + private void chargeVehicleImpl(DvrpVehicle vehicle, ElectricVehicle ev, Charger charger, ChargingStrategy strategy) { Schedule schedule = vehicle.getSchedule(); DrtStayTask stayTask = (DrtStayTask)schedule.getCurrentTask(); if (stayTask.getTaskIdx() != schedule.getTaskCount() - 1) { @@ -86,19 +89,17 @@ private void chargeVehicleImpl(DvrpVehicle vehicle, Charger charger) { // add CHARGING TASK double beginTime = stayTask.getEndTime(); - ChargingStrategy strategy = charger.getLogic().getChargingStrategy(); - ElectricVehicle ev = ((EvDvrpVehicle)vehicle).getElectricVehicle(); - double totalEnergy = -strategy.calcRemainingEnergyToCharge(ev); + double totalEnergy = -strategy.calcRemainingEnergyToCharge(); - double chargingDuration = Math.min(strategy.calcRemainingTimeToCharge(ev), + double chargingDuration = Math.min(strategy.calcRemainingTimeToCharge(), vehicle.getServiceEndTime() - beginTime); if (chargingDuration <= 0) { return;// no charging } double endTime = beginTime + chargingDuration; - schedule.addTask(taskFactory.createChargingTask(vehicle, beginTime, endTime, charger, totalEnergy)); - ((ChargingWithAssignmentLogic)charger.getLogic()).assignVehicle(ev); + schedule.addTask(taskFactory.createChargingTask(vehicle, beginTime, endTime, charger, totalEnergy, strategy)); + ((ChargingWithAssignmentLogic)charger.getLogic()).assignVehicle(ev, strategy); // append STAY schedule.addTask(taskFactory.createStayTask(vehicle, endTime, vehicle.getServiceEndTime(), charger.getLink())); 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 ace6e8d66e0..b3469edbc2e 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 @@ -42,15 +42,18 @@ public class EDrtShiftDispatcherImpl implements DrtShiftDispatcher { private final Fleet fleet; + private final ChargingStrategy.Factory chargingStrategyFactory; + public EDrtShiftDispatcherImpl(EShiftTaskScheduler shiftTaskScheduler, ChargingInfrastructure chargingInfrastructure, ShiftsParams drtShiftParams, OperationFacilities operationFacilities, - DrtShiftDispatcher delegate, Fleet fleet) { + DrtShiftDispatcher delegate, Fleet fleet, ChargingStrategy.Factory chargingStrategyFactory) { this.shiftTaskScheduler = shiftTaskScheduler; this.chargingInfrastructure = chargingInfrastructure; this.drtShiftParams = drtShiftParams; this.operationFacilities = operationFacilities; this.delegate = delegate; this.fleet = fleet; + this.chargingStrategyFactory = chargingStrategyFactory; } @Override @@ -112,18 +115,18 @@ private void checkChargingAtHub(double timeStep) { if (selectedCharger.isPresent()) { Charger selectedChargerImpl = selectedCharger.get(); - ChargingStrategy chargingStrategy = selectedChargerImpl.getLogic().getChargingStrategy(); - if (!chargingStrategy.isChargingCompleted(electricVehicle)) { + ChargingStrategy chargingStrategy = chargingStrategyFactory.createStrategy(selectedChargerImpl.getSpecification(), electricVehicle); + if (!chargingStrategy.isChargingCompleted()) { final double waitTime = ChargingEstimations .estimateMaxWaitTimeForNextVehicle(selectedChargerImpl); final double chargingTime = chargingStrategy - .calcRemainingTimeToCharge(electricVehicle); + .calcRemainingTimeToCharge(); double energy = -chargingStrategy - .calcRemainingEnergyToCharge(electricVehicle); + .calcRemainingEnergyToCharge(); final double endTime = timeStep + waitTime + chargingTime; if (endTime < currentTask.getEndTime()) { shiftTaskScheduler.chargeAtHub((WaitForShiftTask) currentTask, eShiftVehicle, - electricVehicle, selectedChargerImpl, timeStep, endTime, energy); + electricVehicle, selectedChargerImpl, timeStep, endTime, energy, chargingStrategy); } } } 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 32bf96909bf..95b6feb85e3 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 @@ -34,6 +34,7 @@ import org.matsim.contrib.dvrp.run.DvrpConfigGroup; import org.matsim.contrib.dvrp.vrpagent.VrpAgentLogic; import org.matsim.contrib.dvrp.vrpagent.VrpLegFactory; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.mobsim.framework.MobsimTimer; @@ -72,7 +73,7 @@ protected void configureQSim() { drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()), new EDrtAssignShiftToVehicleLogic(new DefaultAssignShiftToVehicleLogic(drtShiftParams), drtShiftParams), getter.getModal(ShiftScheduler.class)), - getter.getModal(Fleet.class))) + getter.getModal(Fleet.class), getter.getModal(ChargingStrategy.Factory.class))) ).asEagerSingleton(); bindModal(VehicleEntry.EntryFactory.class).toProvider(modalProvider(getter -> @@ -87,7 +88,8 @@ drtShiftParams, new EDrtShiftStartLogic(new DefaultShiftStartLogic()), getter -> new EShiftTaskScheduler(getter.getModal(Network.class), getter.getModal(TravelTime.class), getter.getModal(TravelDisutilityFactory.class).createTravelDisutility(getter.getModal(TravelTime.class)), getter.get(MobsimTimer.class), getter.getModal(ShiftDrtTaskFactory.class), drtShiftParams, getter.getModal(ChargingInfrastructure.class), - getter.getModal(OperationFacilities.class), getter.getModal(Fleet.class)) + getter.getModal(OperationFacilities.class), getter.getModal(Fleet.class), + getter.getModal(ChargingStrategy.Factory.class)) )).asEagerSingleton(); // See EDrtModeOptimizerQSimModule 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 b7c2657f1bf..c74713d9f73 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 @@ -19,6 +19,7 @@ import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.path.VrpPathWithTravelData; import org.matsim.contrib.dvrp.schedule.DefaultStayTask; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.contrib.evrp.ChargingTask; import org.matsim.contrib.evrp.ChargingTaskImpl; @@ -99,21 +100,21 @@ public WaitForShiftTask createWaitForShiftStayTask(DvrpVehicle vehicle, double b 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); + double totalEnergy, Charger charger, ChargingStrategy strategy) { + ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy, strategy); return new EDrtWaitForShiftTask(beginTime, endTime, link, totalEnergy, facility, chargingTask); } public EDrtShiftBreakTaskImpl createChargingShiftBreakTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link, - DrtShiftBreak shiftBreak, Charger charger, double totalEnergy, OperationFacility facility) { - ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy); + DrtShiftBreak shiftBreak, Charger charger, double totalEnergy, OperationFacility facility, ChargingStrategy strategy) { + ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy, strategy); return new EDrtShiftBreakTaskImpl(beginTime, endTime, link, shiftBreak, totalEnergy, chargingTask, facility); } public ShiftChangeOverTask createChargingShiftChangeoverTask(DvrpVehicle vehicle, double beginTime, double endTime, Link link, Charger charger, double totalEnergy, - DrtShift shift, OperationFacility facility) { - ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy); + DrtShift shift, OperationFacility facility, ChargingStrategy strategy) { + ChargingTask chargingTask = new ChargingTaskImpl(EDrtChargingTask.TYPE, beginTime, endTime, charger, ((EvDvrpVehicle)vehicle).getElectricVehicle(), totalEnergy, strategy); return new EDrtShiftChangeoverTaskImpl(beginTime, endTime, link, shift, totalEnergy, chargingTask, facility); } } 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 9c5a7172282..2bc42cc1925 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 @@ -1,5 +1,11 @@ package org.matsim.contrib.drt.extension.operations.eshifts.scheduler; +import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.DRIVE; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.matsim.api.core.v01.Id; @@ -12,7 +18,11 @@ import org.matsim.contrib.drt.extension.operations.operationFacilities.OperationFacility; import org.matsim.contrib.drt.extension.operations.shifts.config.ShiftsParams; import org.matsim.contrib.drt.extension.operations.shifts.fleet.ShiftDvrpVehicle; -import org.matsim.contrib.drt.extension.operations.shifts.schedule.*; +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.ShiftSchedules; +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.DrtShift; import org.matsim.contrib.drt.extension.operations.shifts.shift.DrtShiftBreak; @@ -23,11 +33,16 @@ 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.*; +import org.matsim.contrib.dvrp.schedule.DriveTask; +import org.matsim.contrib.dvrp.schedule.Schedule; +import org.matsim.contrib.dvrp.schedule.Schedules; +import org.matsim.contrib.dvrp.schedule.StayTask; +import org.matsim.contrib.dvrp.schedule.Task; import org.matsim.contrib.dvrp.tracker.OnlineDriveTaskTracker; import org.matsim.contrib.dvrp.util.LinkTimePair; import org.matsim.contrib.ev.charging.BatteryCharging; import org.matsim.contrib.ev.charging.ChargingEstimations; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic; import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.Charger; @@ -38,12 +53,7 @@ import org.matsim.core.router.util.LeastCostPathCalculator; import org.matsim.core.router.util.TravelDisutility; import org.matsim.core.router.util.TravelTime; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import static org.matsim.contrib.drt.schedule.DrtTaskBaseType.DRIVE; +import org.matsim.core.utils.collections.Tuple; /** * @author nkuehnel / MOIA @@ -61,10 +71,12 @@ public class EShiftTaskScheduler implements ShiftTaskScheduler { private final Network network; private final ChargingInfrastructure chargingInfrastructure; + private final ChargingStrategy.Factory chargingStrategyFactory; public EShiftTaskScheduler(Network network, TravelTime travelTime, TravelDisutility travelDisutility, MobsimTimer timer, ShiftDrtTaskFactory taskFactory, ShiftsParams shiftsParams, - ChargingInfrastructure chargingInfrastructure, OperationFacilities operationFacilities, Fleet fleet) { + ChargingInfrastructure chargingInfrastructure, OperationFacilities operationFacilities, Fleet fleet, + ChargingStrategy.Factory chargingStrategyFactory) { this.travelTime = travelTime; this.timer = timer; this.taskFactory = taskFactory; @@ -72,6 +84,7 @@ public EShiftTaskScheduler(Network network, TravelTime travelTime, TravelDisutil this.shiftsParams = shiftsParams; this.router = new SpeedyALTFactory().createPathCalculator(network, travelDisutility, travelTime); this.chargingInfrastructure = chargingInfrastructure; + this.chargingStrategyFactory = chargingStrategyFactory; } public void relocateForBreak(ShiftDvrpVehicle vehicle, OperationFacility breakFacility, DrtShift shift) { @@ -169,23 +182,25 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do ShiftBreakTask dropoffStopTask; ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); - Optional charger = charge(breakFacility, ev); + Optional charger = charge(breakFacility, ev); if (charger.isPresent()) { - final Charger chargerImpl = charger.get(); + final ChargerWithStrategy chargerImpl = charger.get(); final double waitTime = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(chargerImpl); + .estimateMaxWaitTimeForNextVehicle(chargerImpl.charger); if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() > shiftsParams.chargeDuringBreakThreshold || waitTime > 0) { dropoffStopTask = taskFactory.createShiftBreakTask(vehicle, startTime, endTime, link, shiftBreak, breakFacility); } else { - double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargerImpl.getSpecification(), endTime - startTime); + ChargingStrategy strategy = chargingStrategyFactory.createStrategy(chargerImpl.charger.getSpecification(), ev); + + double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargerImpl.charger.getSpecification(), endTime - startTime); double totalEnergy = -energyCharge; - ((ChargingWithAssignmentLogic) chargerImpl.getLogic()).assignVehicle(ev); + ((ChargingWithAssignmentLogic) chargerImpl.charger.getLogic()).assignVehicle(ev, strategy); dropoffStopTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingShiftBreakTask(vehicle, - startTime, endTime, link, shiftBreak, chargerImpl, totalEnergy, breakFacility); + startTime, endTime, link, shiftBreak, chargerImpl.charger, totalEnergy, breakFacility, chargerImpl.strategy); } } else { dropoffStopTask = taskFactory.createShiftBreakTask(vehicle, startTime, @@ -202,7 +217,7 @@ private void relocateForBreakImpl(ShiftDvrpVehicle vehicle, double startTime, do shiftBreak.schedule(Math.min(latestDetourArrival, latestTimeConstraintArrival)); } - private Optional charge(OperationFacility breakFacility, ElectricVehicle electricVehicle) { + private Optional charge(OperationFacility breakFacility, ElectricVehicle electricVehicle) { if (chargingInfrastructure != null) { List> chargerIds = breakFacility.getChargers(); if (!chargerIds.isEmpty()) { @@ -218,16 +233,19 @@ private Optional charge(OperationFacility breakFacility, ElectricVehicl return Double.compare(waitTime, waitTime2); }); if (selectedCharger.isPresent()) { - if (selectedCharger.get().getLogic().getChargingStrategy().isChargingCompleted(electricVehicle)) { + ChargingStrategy strategy = chargingStrategyFactory.createStrategy(selectedCharger.get().getSpecification(), electricVehicle); + if (strategy.isChargingCompleted()) { return Optional.empty(); } + return Optional.of(new ChargerWithStrategy(selectedCharger.get(), strategy)); } - return selectedCharger; } } return Optional.empty(); } + private record ChargerWithStrategy(Charger charger, ChargingStrategy strategy) {} + public void relocateForShiftChange(DvrpVehicle vehicle, Link link, DrtShift shift, OperationFacility breakFacility) { final Schedule schedule = vehicle.getSchedule(); @@ -318,24 +336,24 @@ private void appendShiftChange(DvrpVehicle vehicle, DrtShift shift, OperationFac // append SHIFT_CHANGEOVER task ElectricVehicle ev = ((EvDvrpVehicle) vehicle).getElectricVehicle(); - Optional charger = charge(breakFacility, ev); + Optional charger = charge(breakFacility, ev); if (charger.isPresent()) { - Charger chargingImpl = charger.get(); - + ChargerWithStrategy chargingImpl = charger.get(); + final double waitTime = ChargingEstimations - .estimateMaxWaitTimeForNextVehicle(chargingImpl); + .estimateMaxWaitTimeForNextVehicle(chargingImpl.charger); if (ev.getBattery().getCharge() / ev.getBattery().getCapacity() < shiftsParams.chargeDuringBreakThreshold - || ((ChargingWithAssignmentLogic) chargingImpl.getLogic()).getAssignedVehicles().contains(ev) + || ((ChargingWithAssignmentLogic) chargingImpl.charger.getLogic()).isAssigned(ev) || waitTime > 0) { dropoffStopTask = taskFactory.createShiftChangeoverTask(vehicle, startTime, endTime, link, shift, breakFacility); } else { - double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargingImpl.getSpecification(), endTime - startTime); + double energyCharge = ((BatteryCharging) ev.getChargingPower()).calcEnergyCharged(chargingImpl.charger.getSpecification(), endTime - startTime); double totalEnergy = -energyCharge; - ((ChargingWithAssignmentLogic) chargingImpl.getLogic()).assignVehicle(ev); + ((ChargingWithAssignmentLogic) chargingImpl.charger.getLogic()).assignVehicle(ev, chargingImpl.strategy); dropoffStopTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingShiftChangeoverTask(vehicle, - startTime, endTime, link, chargingImpl, totalEnergy, shift, breakFacility); + startTime, endTime, link, chargingImpl.charger, totalEnergy, shift, breakFacility, chargingImpl.strategy); } } else { dropoffStopTask = taskFactory.createShiftChangeoverTask(vehicle, startTime, @@ -470,12 +488,12 @@ private void updateShiftChangeImpl(DvrpVehicle vehicle, VrpPathWithTravelData vr public void chargeAtHub(WaitForShiftTask currentTask, ShiftDvrpVehicle vehicle, ElectricVehicle electricVehicle, Charger charger, double beginTime, - double endTime, double energy) { + double endTime, double energy, ChargingStrategy strategy) { final double initialEndTime = currentTask.getEndTime(); currentTask.setEndTime(beginTime); - ((ChargingWithAssignmentLogic) charger.getLogic()).assignVehicle(electricVehicle); + ((ChargingWithAssignmentLogic) charger.getLogic()).assignVehicle(electricVehicle, strategy); final WaitForShiftTask chargingWaitForShiftTask = ((ShiftEDrtTaskFactoryImpl) taskFactory).createChargingWaitForShiftStayTask(vehicle, - beginTime, endTime, currentTask.getLink(), currentTask.getFacility(), energy, charger); + beginTime, endTime, currentTask.getLink(), currentTask.getFacility(), energy, charger, strategy); final WaitForShiftTask waitForShiftTask = taskFactory.createWaitForShiftStayTask(vehicle, endTime, initialEndTime, currentTask.getLink(), currentTask.getFacility()); diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/eshifts/run/RunEShiftDrtScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/eshifts/run/RunEShiftDrtScenarioIT.java index a137d932fe5..a65091c6102 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/eshifts/run/RunEShiftDrtScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/operations/eshifts/run/RunEShiftDrtScenarioIT.java @@ -17,6 +17,7 @@ import org.matsim.contrib.drt.run.DrtConfigGroup; import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.dvrp.run.DvrpModes; import org.matsim.contrib.ev.EvConfigGroup; import org.matsim.contrib.ev.charging.*; import org.matsim.contrib.ev.temperature.TemperatureService; @@ -32,6 +33,8 @@ import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.examples.ExamplesUtils; +import com.google.inject.Key; + import java.util.HashSet; import java.util.Set; @@ -177,8 +180,8 @@ void test() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - bind(ChargingLogic.Factory.class).toProvider(new ChargingWithQueueingAndAssignmentLogic.FactoryProvider( - charger -> new ChargeUpToMaxSocStrategy(charger, MAX_RELATIVE_SOC))); + bind(ChargingLogic.Factory.class).to(ChargingWithQueueingAndAssignmentLogic.Factory.class); + bind(Key.get(ChargingStrategy.Factory.class, DvrpModes.mode(drtConfigGroup.mode))).toInstance(new ChargeUpToMaxSocStrategy.Factory(MAX_RELATIVE_SOC)); bind(ChargingPower.Factory.class).toInstance(FastThenSlowCharging::new); bind(TemperatureService.class).toInstance(linkId -> TEMPERATURE); } diff --git a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/services/RunEDrtWithServicesScenarioIT.java b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/services/RunEDrtWithServicesScenarioIT.java index b16dca56807..da8b28c6c82 100644 --- a/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/services/RunEDrtWithServicesScenarioIT.java +++ b/contribs/drt-extensions/src/test/java/org/matsim/contrib/drt/extension/services/RunEDrtWithServicesScenarioIT.java @@ -14,6 +14,7 @@ import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; import org.matsim.contrib.dvrp.fleet.DvrpVehicle; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; +import org.matsim.contrib.dvrp.run.DvrpModes; import org.matsim.contrib.ev.charging.*; import org.matsim.contrib.ev.temperature.TemperatureService; import org.matsim.core.config.Config; @@ -22,6 +23,8 @@ import org.matsim.core.controler.Controler; import org.matsim.testcases.MatsimTestUtils; +import com.google.inject.Key; + public class RunEDrtWithServicesScenarioIT { public static final double MINIMUM_RELATIVE_SOC = 0.2; public static final double MAX_SOC = 1.0; @@ -77,7 +80,8 @@ public void install() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - bind(ChargingLogic.Factory.class).toProvider(new ChargingWithQueueingAndAssignmentLogic.FactoryProvider(charger -> new ChargeUpToMaxSocStrategy(charger, MAX_SOC))); + bind(ChargingLogic.Factory.class).to(ChargingWithQueueingAndAssignmentLogic.Factory.class); + bind(Key.get(ChargingStrategy.Factory.class, DvrpModes.mode(drtConfigGroup.mode))).toInstance(new ChargeUpToMaxSocStrategy.Factory(MAX_SOC)); bind(ChargingPower.Factory.class).toInstance(ev -> new FixedSpeedCharging(ev, RELATIVE_SPEED)); bind(TemperatureService.class).toInstance(linkId -> TEMPERATURE); } diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingActivity.java b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingActivity.java index 05217bf940e..8c1cb0adee3 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingActivity.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingActivity.java @@ -21,6 +21,7 @@ package org.matsim.contrib.evrp; import org.matsim.contrib.dynagent.DynActivity; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic; import org.matsim.contrib.ev.fleet.ElectricVehicle; @@ -64,7 +65,7 @@ private void initialize(double now) { ChargingWithAssignmentLogic logic = chargingTask.getChargingLogic(); ElectricVehicle ev = chargingTask.getElectricVehicle(); logic.unassignVehicle(ev); - logic.addVehicle(ev, new DvrpChargingListener(this), now); + logic.addVehicle(ev, chargingTask.getChargingStrategy(), new DvrpChargingListener(this), now); state = State.added; } diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTask.java b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTask.java index 21ad8303ae5..7326e1bedd9 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTask.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTask.java @@ -20,6 +20,7 @@ package org.matsim.contrib.evrp; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic; import org.matsim.contrib.ev.fleet.ElectricVehicle; @@ -29,6 +30,8 @@ public interface ChargingTask extends ETask { ChargingWithAssignmentLogic getChargingLogic(); + ChargingStrategy getChargingStrategy(); + ElectricVehicle getElectricVehicle(); double getChargingStartedTime(); diff --git a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTaskImpl.java b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTaskImpl.java index 969fa50da00..8cbd525cbea 100644 --- a/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTaskImpl.java +++ b/contribs/dvrp/src/main/java/org/matsim/contrib/evrp/ChargingTaskImpl.java @@ -24,6 +24,7 @@ import com.google.common.base.Preconditions; import org.matsim.contrib.dvrp.schedule.DefaultStayTask; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic; import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.Charger; @@ -33,18 +34,20 @@ */ public class ChargingTaskImpl extends DefaultStayTask implements ChargingTask { private final ChargingWithAssignmentLogic chargingLogic; + private final ChargingStrategy chargingStrategy; private final ElectricVehicle ev; private Double chargingStartedTime; private final double totalEnergy; public ChargingTaskImpl(TaskType taskType, double beginTime, double endTime, Charger charger, ElectricVehicle ev, - double totalEnergy) { + double totalEnergy, ChargingStrategy chargingStrategy) { super(taskType, beginTime, endTime, charger.getLink()); Preconditions.checkArgument(totalEnergy < 0, "Total energy consumption is not negative: %s", totalEnergy); this.chargingLogic = (ChargingWithAssignmentLogic)charger.getLogic(); this.ev = ev; this.totalEnergy = totalEnergy; + this.chargingStrategy = chargingStrategy; } @Override @@ -57,6 +60,11 @@ public ChargingWithAssignmentLogic getChargingLogic() { return chargingLogic; } + @Override + public ChargingStrategy getChargingStrategy() { + return chargingStrategy; + } + @Override public ElectricVehicle getElectricVehicle() { return ev; @@ -76,6 +84,7 @@ public double getChargingStartedTime() { public String toString() { return MoreObjects.toStringHelper(this) .add("chargingLogic", chargingLogic) + .add("chargingStrategy", chargingStrategy) .add("ev", ev) .add("chargingStartedTime", chargingStartedTime) .add("totalEnergy", totalEnergy) diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargeUpToMaxSocStrategy.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargeUpToMaxSocStrategy.java index 85760aabefc..3703a7b0794 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargeUpToMaxSocStrategy.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargeUpToMaxSocStrategy.java @@ -23,30 +23,65 @@ import org.matsim.contrib.ev.fleet.Battery; import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; +import org.matsim.vehicles.Vehicle; /** * @author Michal Maciejewski (michalm) + * @author Sebastian Hörl (sebhoerl), IRT SystemX */ public class ChargeUpToMaxSocStrategy implements ChargingStrategy { + static public final String MAXIMUM_SOC_VEHICLE_ATTRIBUTE = "maximumSoc"; + + private final ElectricVehicle ev; private final ChargerSpecification charger; private final double maxSoc; - public ChargeUpToMaxSocStrategy(ChargerSpecification charger, double maxSoc) { + public ChargeUpToMaxSocStrategy(ChargerSpecification charger, ElectricVehicle ev, double maxSoc) { if (maxSoc < 0 || maxSoc > 1) { throw new IllegalArgumentException(); } this.charger = charger; this.maxSoc = maxSoc; + this.ev = ev; } @Override - public double calcRemainingEnergyToCharge(ElectricVehicle ev) { + public double calcRemainingEnergyToCharge() { Battery battery = ev.getBattery(); return maxSoc * battery.getCapacity() - battery.getCharge(); } @Override - public double calcRemainingTimeToCharge(ElectricVehicle ev) { - return ((BatteryCharging)ev.getChargingPower()).calcChargingTime(charger, calcRemainingEnergyToCharge(ev)); + public double calcRemainingTimeToCharge() { + return ((BatteryCharging)ev.getChargingPower()).calcChargingTime(charger, calcRemainingEnergyToCharge()); + } + + @Override + public boolean isChargingCompleted() { + return calcRemainingEnergyToCharge() <= 0; + } + + static public class Factory implements ChargingStrategy.Factory { + private final double maxSoc; + + public Factory(double maxSoc) { + this.maxSoc = maxSoc; + } + + @Override + public ChargingStrategy createStrategy(ChargerSpecification charger, ElectricVehicle ev) { + double vehicleMaximumSoc = maxSoc; + + Vehicle vehicle = ev.getVehicleSpecification().getMatsimVehicle(); + if (vehicle != null) { + Double value = (Double) vehicle.getAttributes().getAttribute(MAXIMUM_SOC_VEHICLE_ATTRIBUTE); + + if (value != null) { + vehicleMaximumSoc = value; + } + } + + return new ChargeUpToMaxSocStrategy(charger, ev, vehicleMaximumSoc); + } } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEstimations.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEstimations.java index 5c0499f3bbf..502573d8bb2 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEstimations.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingEstimations.java @@ -20,7 +20,7 @@ import java.util.stream.Stream; -import org.matsim.contrib.ev.fleet.ElectricVehicle; +import org.matsim.contrib.ev.charging.ChargingLogic.ChargingVehicle; import org.matsim.contrib.ev.infrastructure.Charger; /** @@ -38,20 +38,18 @@ public static double estimateMaxWaitTimeForNextVehicle(Charger charger) { } public static double estimateTotalTimeToCharge(ChargingLogic logic) { - return estimateTotalTimeToCharge(logic.getChargingStrategy(), - Stream.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream())); + return estimateTotalTimeToCharge(Stream.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream())); } public static double estimateTotalEnergyToCharge(ChargingLogic logic) { - return estimateTotalEnergyToCharge(logic.getChargingStrategy(), - Stream.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream())); + return estimateTotalEnergyToCharge(Stream.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream())); } - public static double estimateTotalTimeToCharge(ChargingStrategy strategy, Stream vehicles) { - return vehicles.mapToDouble(strategy::calcRemainingTimeToCharge).sum(); + public static double estimateTotalTimeToCharge(Stream vehicles) { + return vehicles.map(ChargingVehicle::strategy).mapToDouble(ChargingStrategy::calcRemainingTimeToCharge).sum(); } - public static double estimateTotalEnergyToCharge(ChargingStrategy strategy, Stream vehicles) { - return vehicles.mapToDouble(strategy::calcRemainingEnergyToCharge).sum(); + public static double estimateTotalEnergyToCharge(Stream vehicles) { + return vehicles.map(ChargingVehicle::strategy).mapToDouble(ChargingStrategy::calcRemainingEnergyToCharge).sum(); } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingLogic.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingLogic.java index 854947741e0..de274606326 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingLogic.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingLogic.java @@ -29,17 +29,17 @@ interface Factory { ChargingLogic create(ChargerSpecification charger); } - void addVehicle(ElectricVehicle ev, double now); + void addVehicle(ElectricVehicle ev, ChargingStrategy strategy, double now); - void addVehicle(ElectricVehicle ev, ChargingListener chargingListener, double now); + void addVehicle(ElectricVehicle ev, ChargingStrategy strategy, ChargingListener chargingListener, double now); void removeVehicle(ElectricVehicle ev, double now); void chargeVehicles(double chargePeriod, double now); - Collection getPluggedVehicles(); + Collection getPluggedVehicles(); - Collection getQueuedVehicles(); + Collection getQueuedVehicles(); - ChargingStrategy getChargingStrategy(); + record ChargingVehicle(ElectricVehicle ev, ChargingStrategy strategy) {} } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingModule.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingModule.java index 7b42877507d..430484e4943 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingModule.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingModule.java @@ -20,14 +20,13 @@ package org.matsim.contrib.ev.charging; -import com.google.inject.Singleton; import org.matsim.contrib.ev.EvModule; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.controler.AbstractModule; import org.matsim.core.mobsim.qsim.AbstractQSimModule; -import com.google.inject.Inject; -import com.google.inject.Provider; +import com.google.inject.Provides; +import com.google.inject.Singleton; /** * @author Michal Maciejewski (michalm) @@ -35,13 +34,11 @@ public class ChargingModule extends AbstractModule { @Override public void install() { - // The following returns a charging logic for a given charger specification. Needs to be a provider, since the eventsManager needs to be inserted. - bind(ChargingLogic.Factory.class).toProvider(new Provider<>() { - @Inject private EventsManager eventsManager; - @Override public ChargingLogic.Factory get() { - return charger -> new ChargingWithQueueingLogic(charger, new ChargeUpToMaxSocStrategy(charger, 1.), eventsManager); - } - }); + // By default, charging logic with queue is used + bind(ChargingLogic.Factory.class).to(ChargingWithQueueingLogic.Factory.class); + + // By default, charging strategy that chargers to 100% is used + bind(ChargingStrategy.Factory.class).toInstance(new ChargeUpToMaxSocStrategy.Factory(1.0)); // The following returns the charging power/speed for a vehicle: bind(ChargingPower.Factory.class).toInstance(ev -> new FixedSpeedCharging(ev, 1)); @@ -58,4 +55,14 @@ public void install() { // this.addMobsimListenerBinding().to( ChargingHandler.class ).in( Singleton.class ); // does not work since ChargingInfrastructure is not available. } + + @Provides @Singleton + ChargingWithQueueingLogic.Factory provideChargingWithQueueingLogicFactory(EventsManager eventsManager) { + return new ChargingWithQueueingLogic.Factory(eventsManager); + } + + @Provides @Singleton + ChargingWithQueueingAndAssignmentLogic.Factory provideChargingWithQueueingAndAssignmentLogicFactory(EventsManager eventsManager) { + return new ChargingWithQueueingAndAssignmentLogic.Factory(eventsManager); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStrategy.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStrategy.java index 87b76bf1303..bb5717b3cc2 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStrategy.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingStrategy.java @@ -19,17 +19,21 @@ package org.matsim.contrib.ev.charging; import org.matsim.contrib.ev.fleet.ElectricVehicle; +import org.matsim.contrib.ev.infrastructure.ChargerSpecification; /** * @author michalm + * @author Sebastian Hörl (sebhoerl), IRT SystemX */ public interface ChargingStrategy { - default boolean isChargingCompleted(ElectricVehicle ev) { - return calcRemainingEnergyToCharge(ev) <= 0; - } + boolean isChargingCompleted(); - double calcRemainingEnergyToCharge(ElectricVehicle ev); + double calcRemainingEnergyToCharge(); //XXX should include potentially longer charging if AUX remains turned on - double calcRemainingTimeToCharge(ElectricVehicle ev); + double calcRemainingTimeToCharge(); + + static public interface Factory { + ChargingStrategy createStrategy(ChargerSpecification charger, ElectricVehicle ev); + } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithAssignmentLogic.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithAssignmentLogic.java index ceaabad797e..cd7333d9411 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithAssignmentLogic.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithAssignmentLogic.java @@ -5,9 +5,11 @@ import java.util.Collection; public interface ChargingWithAssignmentLogic extends ChargingLogic { - void assignVehicle(ElectricVehicle ev); + void assignVehicle(ElectricVehicle ev, ChargingStrategy strategy); void unassignVehicle(ElectricVehicle ev); - Collection getAssignedVehicles(); + Collection getAssignedVehicles(); + + boolean isAssigned(ElectricVehicle ev); } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingAndAssignmentLogic.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingAndAssignmentLogic.java index 5fb5cc0ae6d..a21fde69f40 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingAndAssignmentLogic.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingAndAssignmentLogic.java @@ -23,7 +23,6 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import java.util.function.Function; import org.matsim.api.core.v01.Id; import org.matsim.contrib.ev.fleet.ElectricVehicle; @@ -31,21 +30,18 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.vehicles.Vehicle; -import com.google.inject.Inject; -import com.google.inject.Provider; - public class ChargingWithQueueingAndAssignmentLogic extends ChargingWithQueueingLogic implements ChargingWithAssignmentLogic { - private final Map, ElectricVehicle> assignedVehicles = new LinkedHashMap<>(); + private final Map, ChargingVehicle> assignedVehicles = new LinkedHashMap<>(); - public ChargingWithQueueingAndAssignmentLogic(ChargerSpecification charger, ChargingStrategy chargingStrategy, - EventsManager eventsManager) { - super(charger, chargingStrategy, eventsManager); + public ChargingWithQueueingAndAssignmentLogic(ChargerSpecification charger, EventsManager eventsManager) { + super(charger, eventsManager); } @Override - public void assignVehicle(ElectricVehicle ev) { - if (assignedVehicles.put(ev.getId(), ev) != null) { + public void assignVehicle(ElectricVehicle ev, ChargingStrategy strategy) { + ChargingVehicle cv = new ChargingVehicle(ev, strategy); + if (assignedVehicles.put(ev.getId(), cv) != null) { throw new IllegalArgumentException("Vehicle is already assigned: " + ev.getId()); } } @@ -57,28 +53,29 @@ public void unassignVehicle(ElectricVehicle ev) { } } - private final Collection unmodifiableAssignedVehicles = Collections.unmodifiableCollection( + @Override + public boolean isAssigned(ElectricVehicle ev) { + return assignedVehicles.containsKey(ev.getId()); + } + + private final Collection unmodifiableAssignedVehicles = Collections.unmodifiableCollection( assignedVehicles.values()); @Override - public Collection getAssignedVehicles() { + public Collection getAssignedVehicles() { return unmodifiableAssignedVehicles; } - public static class FactoryProvider implements Provider { - @Inject - private EventsManager eventsManager; - - private final Function chargingStrategyCreator; + static public class Factory implements ChargingLogic.Factory { + private final EventsManager eventsManager; - public FactoryProvider(Function chargingStrategyCreator) { - this.chargingStrategyCreator = chargingStrategyCreator; + public Factory(EventsManager eventsManager) { + this.eventsManager = eventsManager; } @Override - public ChargingLogic.Factory get() { - return charger -> new ChargingWithQueueingAndAssignmentLogic(charger, - chargingStrategyCreator.apply(charger), eventsManager); + public ChargingLogic create(ChargerSpecification charger) { + return new ChargingWithQueueingAndAssignmentLogic(charger, eventsManager); } } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingLogic.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingLogic.java index 8cf57733532..515a586a4c2 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingLogic.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingWithQueueingLogic.java @@ -19,49 +19,55 @@ package org.matsim.contrib.ev.charging; -import com.google.common.base.Preconditions; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Objects; +import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; + import org.matsim.api.core.v01.Id; import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.ChargerSpecification; import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.vehicles.Vehicle; -import java.util.*; -import java.util.concurrent.LinkedBlockingQueue; +import com.google.common.base.Preconditions; public class ChargingWithQueueingLogic implements ChargingLogic { protected final ChargerSpecification charger; - private final ChargingStrategy chargingStrategy; private final EventsManager eventsManager; - private final Map, ElectricVehicle> pluggedVehicles = new LinkedHashMap<>(); - private final Queue queuedVehicles = new LinkedList<>(); - private final Queue arrivingVehicles = new LinkedBlockingQueue<>(); + private final Map, ChargingVehicle> pluggedVehicles = new LinkedHashMap<>(); + private final Queue queuedVehicles = new LinkedList<>(); + private final Queue arrivingVehicles = new LinkedBlockingQueue<>(); private final Map, ChargingListener> listeners = new LinkedHashMap<>(); - public ChargingWithQueueingLogic(ChargerSpecification charger, ChargingStrategy chargingStrategy, EventsManager eventsManager) { - this.chargingStrategy = Objects.requireNonNull(chargingStrategy); + public ChargingWithQueueingLogic(ChargerSpecification charger, EventsManager eventsManager) { this.charger = Objects.requireNonNull(charger); this.eventsManager = Objects.requireNonNull(eventsManager); } @Override public void chargeVehicles(double chargePeriod, double now) { - Iterator evIter = pluggedVehicles.values().iterator(); - while (evIter.hasNext()) { - ElectricVehicle ev = evIter.next(); + Iterator cvIter = pluggedVehicles.values().iterator(); + while (cvIter.hasNext()) { + ChargingVehicle cv = cvIter.next(); // with fast charging, we charge around 4% of SOC per minute, // so when updating SOC every 10 seconds, SOC increases by less then 1% - double oldCharge = ev.getBattery().getCharge(); - double energy = ev.getChargingPower().calcChargingPower(charger) * chargePeriod; - double newCharge = Math.min(oldCharge + energy, ev.getBattery().getCapacity()); - ev.getBattery().setCharge(newCharge); - eventsManager.processEvent(new EnergyChargedEvent(now, charger.getId(), ev.getId(), newCharge - oldCharge, newCharge)); - - if (chargingStrategy.isChargingCompleted(ev)) { - evIter.remove(); - eventsManager.processEvent(new ChargingEndEvent(now, charger.getId(), ev.getId(), ev.getBattery().getCharge())); - listeners.remove(ev.getId()).notifyChargingEnded(ev, now); + double oldCharge = cv.ev().getBattery().getCharge(); + double energy = cv.ev().getChargingPower().calcChargingPower(charger) * chargePeriod; + double newCharge = Math.min(oldCharge + energy, cv.ev().getBattery().getCapacity()); + cv.ev().getBattery().setCharge(newCharge); + eventsManager.processEvent(new EnergyChargedEvent(now, charger.getId(), cv.ev().getId(), newCharge - oldCharge, newCharge)); + + if (cv.strategy().isChargingCompleted()) { + cvIter.remove(); + eventsManager.processEvent(new ChargingEndEvent(now, charger.getId(), cv.ev().getId(), cv.ev().getBattery().getCharge())); + listeners.remove(cv.ev().getId()).notifyChargingEnded(cv.ev(), now); } } @@ -72,25 +78,25 @@ public void chargeVehicles(double chargePeriod, double now) { var arrivingVehiclesIter = arrivingVehicles.iterator(); while (arrivingVehiclesIter.hasNext()) { - var ev = arrivingVehiclesIter.next(); + var cv = arrivingVehiclesIter.next(); if (pluggedVehicles.size() < charger.getPlugCount()) { - plugVehicle(ev, now); + plugVehicle(cv, now); } else { - queueVehicle(ev, now); + queueVehicle(cv, now); } arrivingVehiclesIter.remove(); } } @Override - public void addVehicle(ElectricVehicle ev, double now) { - addVehicle(ev, new ChargingListener() { + public void addVehicle(ElectricVehicle ev, ChargingStrategy strategy, double now) { + addVehicle(ev, strategy, new ChargingListener() { }, now); } @Override - public void addVehicle(ElectricVehicle ev, ChargingListener chargingListener, double now) { - arrivingVehicles.add(ev); + public void addVehicle(ElectricVehicle ev, ChargingStrategy strategy, ChargingListener chargingListener, double now) { + arrivingVehicles.add(new ChargingVehicle(ev, strategy)); listeners.put(ev.getId(), chargingListener); } @@ -111,36 +117,44 @@ public void removeVehicle(ElectricVehicle ev, double now) { } } - private void queueVehicle(ElectricVehicle ev, double now) { - queuedVehicles.add(ev); - eventsManager.processEvent(new QueuedAtChargerEvent(now, charger.getId(), ev.getId())); - listeners.get(ev.getId()).notifyVehicleQueued(ev, now); + private void queueVehicle(ChargingVehicle cv, double now) { + queuedVehicles.add(cv); + eventsManager.processEvent(new QueuedAtChargerEvent(now, charger.getId(), cv.ev().getId())); + listeners.get(cv.ev().getId()).notifyVehicleQueued(cv.ev(), now); } - private void plugVehicle(ElectricVehicle ev, double now) { - if (pluggedVehicles.put(ev.getId(), ev) != null) { + private void plugVehicle(ChargingVehicle cv, double now) { + if (pluggedVehicles.put(cv.ev().getId(), cv) != null) { throw new IllegalArgumentException(); } - eventsManager.processEvent(new ChargingStartEvent(now, charger.getId(), ev.getId(), ev.getBattery().getCharge())); - listeners.get(ev.getId()).notifyChargingStarted(ev, now); + eventsManager.processEvent(new ChargingStartEvent(now, charger.getId(), cv.ev().getId(), cv.ev().getBattery().getCharge())); + listeners.get(cv.ev().getId()).notifyChargingStarted(cv.ev(), now); } - private final Collection unmodifiablePluggedVehicles = Collections.unmodifiableCollection(pluggedVehicles.values()); + private final Collection unmodifiablePluggedVehicles = Collections.unmodifiableCollection(pluggedVehicles.values()); @Override - public Collection getPluggedVehicles() { + public Collection getPluggedVehicles() { return unmodifiablePluggedVehicles; } - private final Collection unmodifiableQueuedVehicles = Collections.unmodifiableCollection(queuedVehicles); + private final Collection unmodifiableQueuedVehicles = Collections.unmodifiableCollection(queuedVehicles); @Override - public Collection getQueuedVehicles() { + public Collection getQueuedVehicles() { return unmodifiableQueuedVehicles; } - @Override - public ChargingStrategy getChargingStrategy() { - return chargingStrategy; + static public class Factory implements ChargingLogic.Factory { + private final EventsManager eventsManager; + + public Factory(EventsManager eventsManager) { + this.eventsManager = eventsManager; + } + + @Override + public ChargingLogic create(ChargerSpecification charger) { + return new ChargingWithQueueingLogic(charger, eventsManager); + } } } diff --git a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java index d206a50c875..15431cea1fe 100644 --- a/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java +++ b/contribs/ev/src/main/java/org/matsim/contrib/ev/charging/VehicleChargingHandler.java @@ -86,11 +86,14 @@ public class VehicleChargingHandler private final ImmutableListMultimap, Charger> chargersAtLinks; private final EvConfigGroup evCfg; + private final ChargingStrategy.Factory strategyFactory; + @Inject - VehicleChargingHandler(ChargingInfrastructure chargingInfrastructure, ElectricFleet electricFleet, EvConfigGroup evConfigGroup) { + VehicleChargingHandler(ChargingInfrastructure chargingInfrastructure, ElectricFleet electricFleet, EvConfigGroup evConfigGroup, ChargingStrategy.Factory strategyFactory) { this.chargingInfrastructure = chargingInfrastructure; this.electricFleet = electricFleet; this.evCfg = evConfigGroup; + this.strategyFactory = strategyFactory; chargersAtLinks = ChargingInfrastructureUtils.getChargersAtLinks(chargingInfrastructure ); } @@ -112,7 +115,7 @@ public void handleEvent(ActivityStartEvent event) { .filter(ch -> ev.getChargerTypes().contains(ch.getChargerType())) .findAny() .get(); - c.getLogic().addVehicle(ev, event.getTime()); + c.getLogic().addVehicle(ev, strategyFactory.createStrategy(c.getSpecification(), ev), event.getTime()); vehiclesAtChargers.put(evId, c.getId()); } } diff --git a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/ETaxiChargingTask.java b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/ETaxiChargingTask.java index 8f7f9b018ca..afb1b839bd5 100644 --- a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/ETaxiChargingTask.java +++ b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/ETaxiChargingTask.java @@ -20,6 +20,7 @@ package org.matsim.contrib.etaxi; import org.matsim.contrib.evrp.ChargingTaskImpl; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.Charger; import org.matsim.contrib.taxi.schedule.TaxiTaskType; @@ -28,7 +29,7 @@ public class ETaxiChargingTask extends ChargingTaskImpl { public static final TaxiTaskType TYPE = new TaxiTaskType("CHARGING"); public ETaxiChargingTask(double beginTime, double endTime, Charger charger, ElectricVehicle ev, - double totalEnergy) { - super(TYPE, beginTime, endTime, charger, ev, totalEnergy); + double totalEnergy, ChargingStrategy chargingStrategy) { + super(TYPE, beginTime, endTime, charger, ev, totalEnergy, chargingStrategy); } } diff --git a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/ETaxiScheduler.java b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/ETaxiScheduler.java index 79999d4b140..16850cf1004 100644 --- a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/ETaxiScheduler.java +++ b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/ETaxiScheduler.java @@ -34,6 +34,7 @@ import org.matsim.contrib.dvrp.schedule.Schedules; import org.matsim.contrib.dvrp.schedule.Task; import org.matsim.contrib.ev.charging.ChargingEstimations; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.charging.ChargingWithAssignmentLogic; import org.matsim.contrib.ev.fleet.ElectricVehicle; import org.matsim.contrib.ev.infrastructure.Charger; @@ -50,10 +51,13 @@ public class ETaxiScheduler extends TaxiScheduler { public static final TaxiTaskType DRIVE_TO_CHARGER = new TaxiTaskType("DRIVE_TO_CHARGER", EMPTY_DRIVE); + private final ChargingStrategy.Factory chargingStrategyFactory; + public ETaxiScheduler(TaxiConfigGroup taxiCfg, Fleet fleet, TaxiScheduleInquiry taxiScheduleInquiry, TravelTime travelTime, Supplier routerCreator, EventsManager eventsManager, - MobsimTimer mobsimTimer) { + MobsimTimer mobsimTimer, ChargingStrategy.Factory chargingStrategyFactory) { super(taxiCfg, fleet, taxiScheduleInquiry, travelTime, routerCreator, eventsManager, mobsimTimer); + this.chargingStrategyFactory = chargingStrategyFactory; } // FIXME underestimated due to the ongoing AUX/drive consumption @@ -65,12 +69,13 @@ public void scheduleCharging(DvrpVehicle vehicle, ElectricVehicle ev, Charger ch divertOrAppendDrive(schedule, vrpPath, DRIVE_TO_CHARGER); ChargingWithAssignmentLogic logic = (ChargingWithAssignmentLogic)charger.getLogic(); + ChargingStrategy strategy = chargingStrategyFactory.createStrategy(charger.getSpecification(), ev); double chargingEndTime = vrpPath.getArrivalTime() + ChargingEstimations.estimateMaxWaitTimeForNextVehicle( charger)// TODO not precise!!! - + logic.getChargingStrategy().calcRemainingTimeToCharge(ev);// TODO not precise !!! (SOC will be lower) + + strategy.calcRemainingTimeToCharge();// TODO not precise !!! (SOC will be lower) schedule.addTask(new ETaxiChargingTask(vrpPath.getArrivalTime(), chargingEndTime, charger, ev, - -logic.getChargingStrategy().calcRemainingEnergyToCharge(ev)));// TODO not precise !!! (ditto) - logic.assignVehicle(ev); + -strategy.calcRemainingEnergyToCharge(), strategy));// TODO not precise !!! (ditto) + logic.assignVehicle(ev, strategy); appendStayTask(vehicle); } diff --git a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/ETaxiModeOptimizerQSimModule.java b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/ETaxiModeOptimizerQSimModule.java index 5860bea3890..a713f20796c 100644 --- a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/ETaxiModeOptimizerQSimModule.java +++ b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/ETaxiModeOptimizerQSimModule.java @@ -34,6 +34,7 @@ import org.matsim.contrib.etaxi.ETaxiActionCreator; import org.matsim.contrib.etaxi.ETaxiScheduler; import org.matsim.contrib.etaxi.util.ETaxiStayTaskEndTimeCalculator; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructure; import org.matsim.contrib.ev.infrastructure.ChargingInfrastructureUtils; import org.matsim.contrib.taxi.analysis.TaxiEventSequenceCollector; @@ -113,8 +114,9 @@ public ETaxiScheduler get() { var speedyALTFactory = new SpeedyALTFactory(); Supplier routerCreator = () -> speedyALTFactory.createPathCalculator( network, travelDisutility, travelTime); + ChargingStrategy.Factory chargingStrategyFactory = getModalInstance(ChargingStrategy.Factory.class); return new ETaxiScheduler(taxiCfg, fleet, taxiScheduleInquiry, travelTime, routerCreator, - events, timer); + events, timer, chargingStrategyFactory); } }); diff --git a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/assignment/AssignmentChargerPlugData.java b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/assignment/AssignmentChargerPlugData.java index 6f3a1105fc3..3d3e4b720e8 100644 --- a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/assignment/AssignmentChargerPlugData.java +++ b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/optimizer/assignment/AssignmentChargerPlugData.java @@ -71,7 +71,7 @@ static AssignmentDestinationData create(double currentTime, Iterabl } // does not include AUX+driving for assigned vehs - double assignedWorkload = ChargingEstimations.estimateTotalTimeToCharge(logic.getChargingStrategy(), + double assignedWorkload = ChargingEstimations.estimateTotalTimeToCharge( Streams.concat(logic.getPluggedVehicles().stream(), logic.getQueuedVehicles().stream(), logic.getAssignedVehicles().stream())); diff --git a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/run/RunETaxiBenchmark.java b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/run/RunETaxiBenchmark.java index 5e67a5e2105..68d20b5263b 100644 --- a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/run/RunETaxiBenchmark.java +++ b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/run/RunETaxiBenchmark.java @@ -27,6 +27,7 @@ import org.matsim.contrib.dvrp.fleet.FleetSpecification; import org.matsim.contrib.dvrp.run.AbstractDvrpModeModule; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.dvrp.run.DvrpModes; import org.matsim.contrib.dvrp.run.DvrpQSimComponents; import org.matsim.contrib.ev.EvConfigGroup; import org.matsim.contrib.ev.EvModule; @@ -34,6 +35,7 @@ import org.matsim.contrib.ev.charging.ChargingEventSequenceCollector; import org.matsim.contrib.ev.charging.ChargingLogic; import org.matsim.contrib.ev.charging.ChargingPower; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.charging.ChargingWithQueueingAndAssignmentLogic; import org.matsim.contrib.ev.charging.FixedSpeedCharging; import org.matsim.contrib.ev.discharging.IdleDischargingHandler; @@ -53,6 +55,8 @@ import org.matsim.core.mobsim.qsim.AbstractQSimModule; import org.matsim.core.scenario.ScenarioUtils; +import com.google.inject.Key; + /** * For a fair and consistent benchmarking of taxi dispatching algorithms we assume that link travel times are * deterministic. To simulate this property, we remove (1) all other traffic, and (2) link capacity constraints (e.g. by @@ -111,8 +115,8 @@ protected void configureQSim() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - bind(ChargingLogic.Factory.class).toProvider(new ChargingWithQueueingAndAssignmentLogic.FactoryProvider( - charger -> new ChargeUpToMaxSocStrategy(charger, MAX_SOC))); + bind(ChargingLogic.Factory.class).to(ChargingWithQueueingAndAssignmentLogic.Factory.class); + bind(Key.get(ChargingStrategy.Factory.class, DvrpModes.mode(mode))).toInstance(new ChargeUpToMaxSocStrategy.Factory(MAX_SOC)); //TODO switch to VariableSpeedCharging for Nissan bind(ChargingPower.Factory.class).toInstance(ev -> new FixedSpeedCharging(ev, CHARGING_SPEED_FACTOR)); bind(TemperatureService.class).toInstance(linkId -> TEMPERATURE); diff --git a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/run/RunETaxiScenario.java b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/run/RunETaxiScenario.java index f5598174103..bd266b4b0f2 100644 --- a/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/run/RunETaxiScenario.java +++ b/contribs/taxi/src/main/java/org/matsim/contrib/etaxi/run/RunETaxiScenario.java @@ -23,6 +23,7 @@ import org.matsim.api.core.v01.Scenario; import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contrib.dvrp.run.DvrpModes; import org.matsim.contrib.dvrp.run.DvrpModule; import org.matsim.contrib.dvrp.run.DvrpQSimComponents; import org.matsim.contrib.ev.EvConfigGroup; @@ -30,12 +31,13 @@ import org.matsim.contrib.ev.charging.ChargeUpToMaxSocStrategy; import org.matsim.contrib.ev.charging.ChargingLogic; import org.matsim.contrib.ev.charging.ChargingPower; +import org.matsim.contrib.ev.charging.ChargingStrategy; import org.matsim.contrib.ev.charging.ChargingWithQueueingAndAssignmentLogic; import org.matsim.contrib.ev.charging.FixedSpeedCharging; import org.matsim.contrib.ev.discharging.IdleDischargingHandler; +import org.matsim.contrib.ev.temperature.TemperatureService; import org.matsim.contrib.evrp.EvDvrpFleetQSimModule; import org.matsim.contrib.evrp.OperatingVehicleProvider; -import org.matsim.contrib.ev.temperature.TemperatureService; import org.matsim.contrib.otfvis.OTFVisLiveModule; import org.matsim.contrib.taxi.run.MultiModeTaxiConfigGroup; import org.matsim.contrib.taxi.run.TaxiConfigGroup; @@ -48,6 +50,8 @@ import org.matsim.core.scenario.ScenarioUtils; import org.matsim.vis.otfvis.OTFVisConfigGroup; +import com.google.inject.Key; + public class RunETaxiScenario { private static final double CHARGING_SPEED_FACTOR = 1.5; // > 1 in this example private static final double MAX_SOC = 0.8; // charge up to 80% SOC @@ -91,11 +95,14 @@ protected void configureQSim() { controler.addOverridingModule(new AbstractModule() { @Override public void install() { - bind(ChargingLogic.Factory.class).toProvider(new ChargingWithQueueingAndAssignmentLogic.FactoryProvider( - charger -> new ChargeUpToMaxSocStrategy(charger, MAX_SOC))); + bind(ChargingLogic.Factory.class).to(ChargingWithQueueingAndAssignmentLogic.Factory.class); //TODO switch to VariableSpeedCharging for Nissan bind(ChargingPower.Factory.class).toInstance(ev -> new FixedSpeedCharging(ev, CHARGING_SPEED_FACTOR)); bind(TemperatureService.class).toInstance(linkId -> TEMPERATURE); + + for (TaxiConfigGroup taxiCfg : multiModeTaxiConfig.getModalElements()) { + bind(Key.get(ChargingStrategy.Factory.class, DvrpModes.mode(taxiCfg.getMode()))).toInstance(new ChargeUpToMaxSocStrategy.Factory(MAX_SOC)); + } } }); diff --git a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanVehicleChargingHandler.java b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanVehicleChargingHandler.java index 592722998fe..8e40eb18120 100644 --- a/contribs/vsp/src/main/java/playground/vsp/ev/UrbanVehicleChargingHandler.java +++ b/contribs/vsp/src/main/java/playground/vsp/ev/UrbanVehicleChargingHandler.java @@ -61,13 +61,16 @@ class UrbanVehicleChargingHandler private final ElectricFleet electricFleet; private final ImmutableListMultimap, Charger> chargersAtLinks; + private final ChargingStrategy.Factory chargingStrategyFactory; + private Map, Map, Tuple, Id>>> chargingProcedures = new HashMap<>(); @Inject - UrbanVehicleChargingHandler(ChargingInfrastructure chargingInfrastructure, ElectricFleet electricFleet) { + UrbanVehicleChargingHandler(ChargingInfrastructure chargingInfrastructure, ElectricFleet electricFleet, ChargingStrategy.Factory chargingStrategyFactory) { this.chargingInfrastructure = chargingInfrastructure; this.electricFleet = electricFleet; this.chargersAtLinks = ChargingInfrastructureUtils.getChargersAtLinks(chargingInfrastructure ); + this.chargingStrategyFactory = chargingStrategyFactory; } /** @@ -89,7 +92,8 @@ public void handleEvent(ActivityStartEvent event) { .findAny() .get(); - charger.getLogic().addVehicle(ev, event.getTime()); + ChargingStrategy strategy = chargingStrategyFactory.createStrategy(charger.getSpecification(), ev); + charger.getLogic().addVehicle(ev, strategy, event.getTime()); Map, Tuple, Id>> proceduresOnLink = this.chargingProcedures.get(event.getLinkId()); if(proceduresOnLink != null && proceduresOnLink.containsKey(event.getPersonId())){ throw new RuntimeException("person " + event.getPersonId() + " tries to charge 2 vehicles at the same time on link " + event.getLinkId() +