Skip to content

Commit

Permalink
Merge branch 'feat/prebooking' into feat/canceling
Browse files Browse the repository at this point in the history
  • Loading branch information
sebhoerl committed Nov 16, 2023
2 parents 9e8e15d + 809024d commit 82e17fd
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@

package org.matsim.contrib.ev.discharging;

import com.google.inject.Singleton;
import org.matsim.contrib.ev.EvModule;
import org.matsim.contrib.ev.temperature.TemperatureService;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.mobsim.qsim.AbstractQSimModule;

import com.google.inject.Singleton;

/**
* @author Michal Maciejewski (michalm)
*/
Expand All @@ -34,16 +35,17 @@ public final class DischargingModule extends AbstractModule {
public void install() {
bind(DriveEnergyConsumption.Factory.class).toInstance(ev -> new OhdeSlaskiDriveEnergyConsumption());
bind(TemperatureService.class).toInstance(linkId -> 15);// XXX fixed temperature 15 oC
bind(AuxEnergyConsumption.Factory.class).to(OhdeSlaskiAuxEnergyConsumption.Factory.class).in( Singleton.class );
bind(AuxEnergyConsumption.Factory.class).to(OhdeSlaskiAuxEnergyConsumption.Factory.class).in(Singleton.class);

installQSimModule(new AbstractQSimModule() {
@Override
protected void configureQSim() {
this.bind(DriveDischargingHandler.class).in( Singleton.class );
this.bind(DriveDischargingHandler.class).in(Singleton.class);
addMobsimScopeEventHandlerBinding().to(DriveDischargingHandler.class);
this.addQSimComponentBinding(EvModule.EV_COMPONENT).to(DriveDischargingHandler.class);
// event handlers are not qsim components

this.bind(IdleDischargingHandler.class).in( Singleton.class );
this.bind(IdleDischargingHandler.class).in(Singleton.class);
addMobsimScopeEventHandlerBinding().to(IdleDischargingHandler.class);
this.addQSimComponentBinding(EvModule.EV_COMPONENT).to(IdleDischargingHandler.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

package org.matsim.contrib.ev.discharging;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.matsim.api.core.v01.Id;
Expand All @@ -35,6 +37,8 @@
import org.matsim.contrib.ev.fleet.ElectricVehicle;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.events.MobsimScopeEventHandler;
import org.matsim.core.mobsim.framework.events.MobsimAfterSimStepEvent;
import org.matsim.core.mobsim.framework.listeners.MobsimAfterSimStepListener;
import org.matsim.vehicles.Vehicle;

import com.google.inject.Inject;
Expand All @@ -45,7 +49,9 @@
* idle discharge process (see {@link IdleDischargingHandler}).
*/
public final class DriveDischargingHandler
implements LinkLeaveEventHandler, VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler, MobsimScopeEventHandler {
implements LinkLeaveEventHandler, VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler, MobsimScopeEventHandler,
MobsimAfterSimStepListener {

private static class EvDrive {
private final Id<Vehicle> vehicleId;
private final ElectricVehicle ev;
Expand All @@ -67,6 +73,9 @@ private boolean isOnFirstLink() {
private final Map<Id<Vehicle>, ? extends ElectricVehicle> eVehicles;
private final Map<Id<Vehicle>, EvDrive> evDrives;

private final List<LinkLeaveEvent> linkLeaveEvents = new ArrayList<>();
private final List<VehicleLeavesTrafficEvent> trafficLeaveEvents = new ArrayList<>();

@Inject
DriveDischargingHandler(ElectricFleet data, Network network, EventsManager eventsManager) {
this.network = network;
Expand All @@ -86,36 +95,47 @@ public void handleEvent(VehicleEntersTrafficEvent event) {

@Override
public void handleEvent(LinkLeaveEvent event) {
EvDrive evDrive = dischargeVehicle(event.getVehicleId(), event.getLinkId(), event.getTime());
if (evDrive != null) {
evDrive.movedOverNodeTime = event.getTime();
}
linkLeaveEvents.add(event);
}

@Override
public void handleEvent(VehicleLeavesTrafficEvent event) {
EvDrive evDrive = dischargeVehicle(event.getVehicleId(), event.getLinkId(), event.getTime());
if (evDrive != null) {
evDrives.remove(evDrive.vehicleId);
trafficLeaveEvents.add(event);
}

@Override
public void notifyMobsimAfterSimStep(MobsimAfterSimStepEvent e) {
// We want to process events in the main thread (instead of the event handling threads).
// This is to eliminate race conditions, where the battery is read/modified by many threads without proper synchronisation
for (var event : linkLeaveEvents) {
EvDrive evDrive = dischargeVehicle(event.getVehicleId(), event.getLinkId(), event.getTime());
if (evDrive != null) {
evDrive.movedOverNodeTime = event.getTime();
}
}
linkLeaveEvents.clear();

for (var event : trafficLeaveEvents) {
EvDrive evDrive = dischargeVehicle(event.getVehicleId(), event.getLinkId(), event.getTime());
if (evDrive != null) {
evDrives.remove(evDrive.vehicleId);
}
}
trafficLeaveEvents.clear();
}

//XXX The current implementation is thread-safe because no other EventHandler modifies battery charge
// (for instance, AUX discharging and battery charging modifies charge outside event handling
// (as MobsimAfterSimStepListeners)
//TODO In the long term, it will be safer to move the discharging procedure to a MobsimAfterSimStepListener
private EvDrive dischargeVehicle(Id<Vehicle> vehicleId, Id<Link> linkId, double eventTime) {
EvDrive evDrive = evDrives.get(vehicleId);
if (evDrive != null && !evDrive.isOnFirstLink()) {// handle only our EVs, except for the first link
Link link = network.getLinks().get(linkId);
double tt = eventTime - evDrive.movedOverNodeTime;
ElectricVehicle ev = evDrive.ev;
double energy = ev.getDriveEnergyConsumption().calcEnergyConsumption(link, tt, eventTime - tt) + ev.getAuxEnergyConsumption()
.calcEnergyConsumption(eventTime - tt, tt, linkId);
.calcEnergyConsumption(eventTime - tt, tt, linkId);
//Energy consumption may be negative on links with negative slope
ev.getBattery()
.dischargeEnergy(energy,
missingEnergy -> eventsManager.processEvent(new MissingEnergyEvent(eventTime, ev.getId(), link.getId(), missingEnergy)));
.dischargeEnergy(energy,
missingEnergy -> eventsManager.processEvent(new MissingEnergyEvent(eventTime, ev.getId(), link.getId(), missingEnergy)));
eventsManager.processEvent(new DrivingEnergyConsumptionEvent(eventTime, vehicleId, linkId, energy, ev.getBattery().getCharge()));
}
return evDrive;
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 82e17fd

Please sign in to comment.