-
Notifications
You must be signed in to change notification settings - Fork 456
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ev): add charging priorities and reservations (#3632)
- Loading branch information
Showing
10 changed files
with
281 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
contribs/ev/src/main/java/org/matsim/contrib/ev/charging/ChargingPriority.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.matsim.contrib.ev.charging; | ||
|
||
import org.matsim.contrib.ev.charging.ChargingLogic.ChargingVehicle; | ||
import org.matsim.contrib.ev.infrastructure.ChargerSpecification; | ||
|
||
/** | ||
* This interface is supposed to decide if a vehicle can be plugged right now or | ||
* if it needs to go to / remain in the queue. While the condition whether | ||
* enough of empty plugs are available is *always* checked, the presented method | ||
* allows to define a more complex logic beyond that. | ||
* | ||
* @author Sebastian Hörl (sebhoerl), IRT SystemX | ||
*/ | ||
public interface ChargingPriority { | ||
/** | ||
* The vehicle can start charging if the method returns true, otherwise it stays | ||
* in the queue. | ||
*/ | ||
boolean requestPlugNext(ChargingVehicle cv, double now); | ||
|
||
public interface Factory { | ||
ChargingPriority create(ChargerSpecification charger); | ||
} | ||
|
||
/** | ||
* The default charging priority: first-in first-out. | ||
*/ | ||
static public final Factory FIFO = charger -> (ev, now) -> true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
106 changes: 106 additions & 0 deletions
106
contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ChargerReservationManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package org.matsim.contrib.ev.reservation; | ||
|
||
import java.util.LinkedList; | ||
import java.util.List; | ||
|
||
import org.matsim.api.core.v01.IdMap; | ||
import org.matsim.contrib.ev.fleet.ElectricVehicle; | ||
import org.matsim.contrib.ev.infrastructure.Charger; | ||
import org.matsim.contrib.ev.infrastructure.ChargerSpecification; | ||
import org.matsim.core.controler.events.IterationStartsEvent; | ||
import org.matsim.core.controler.listener.IterationStartsListener; | ||
|
||
/** | ||
* This class is a singleton service that keeps a list of reservations for | ||
* chargers. It can be used in combination with the | ||
* ReservationBasedChargingPriority to let vehicle pass on to charging only if | ||
* they have a proper reservation. | ||
* | ||
* @author Sebastian Hörl (sebhoerl), IRT SystemX | ||
*/ | ||
public class ChargerReservationManager implements IterationStartsListener { | ||
private final IdMap<Charger, List<Reservation>> reservations = new IdMap<>(Charger.class); | ||
|
||
public boolean isAvailable(ChargerSpecification charger, ElectricVehicle vehicle, double startTile, | ||
double endTime) { | ||
if (charger.getPlugCount() == 0) { | ||
return false; | ||
} | ||
|
||
if (!reservations.containsKey(charger.getId())) { | ||
return true; | ||
} | ||
|
||
int remaining = charger.getPlugCount(); | ||
for (Reservation reservation : reservations.get(charger.getId())) { | ||
if (reservation.vehicle != vehicle && isOverlapping(reservation, startTile, endTime)) { | ||
remaining--; | ||
} | ||
} | ||
|
||
return remaining > 0; | ||
} | ||
|
||
private boolean isOverlapping(Reservation reservation, double startTime, double endTime) { | ||
if (startTime >= reservation.startTime && startTime <= reservation.endTime) { | ||
return true; // start time within existing range | ||
} else if (endTime >= reservation.startTime && endTime <= reservation.endTime) { | ||
return true; // end time within existing range | ||
} else if (startTime <= reservation.startTime && endTime >= reservation.endTime) { | ||
return true; // new range covers existing range | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
public Reservation addReservation(ChargerSpecification charger, ElectricVehicle vehicle, double startTime, | ||
double endTime) { | ||
if (isAvailable(charger, vehicle, startTime, endTime)) { | ||
List<Reservation> chargerReservations = reservations.get(charger.getId()); | ||
|
||
if (chargerReservations == null) { | ||
chargerReservations = new LinkedList<>(); | ||
reservations.put(charger.getId(), chargerReservations); | ||
} | ||
|
||
Reservation reservation = new Reservation(charger, vehicle, startTime, endTime); | ||
chargerReservations.add(reservation); | ||
|
||
return reservation; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
public boolean removeReservation(Reservation reservation) { | ||
List<Reservation> chargerReservations = reservations.get(reservation.charger.getId()); | ||
|
||
if (chargerReservations != null) { | ||
return chargerReservations.remove(reservation); | ||
} | ||
|
||
return false; | ||
} | ||
|
||
public Reservation findReservation(ChargerSpecification charger, ElectricVehicle vehicle, double now) { | ||
List<Reservation> chargerReservations = reservations.get(charger.getId()); | ||
|
||
if (chargerReservations != null) { | ||
for (Reservation reservation : chargerReservations) { | ||
if (reservation.vehicle == vehicle && now >= reservation.startTime && now <= reservation.endTime) { | ||
return reservation; | ||
} | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
public record Reservation(ChargerSpecification charger, ElectricVehicle vehicle, double startTime, double endTime) { | ||
} | ||
|
||
@Override | ||
public void notifyIterationStarts(IterationStartsEvent event) { | ||
reservations.clear(); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
contribs/ev/src/main/java/org/matsim/contrib/ev/reservation/ChargerReservationModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.matsim.contrib.ev.reservation; | ||
|
||
import org.matsim.contrib.ev.charging.ChargingPriority; | ||
import org.matsim.core.controler.AbstractModule; | ||
|
||
import com.google.inject.Provides; | ||
import com.google.inject.Singleton; | ||
|
||
/** | ||
* This module enables the reservation-based charging logic that requires | ||
* vehicles to have or make a reservation when attempting to charge at a | ||
* charger. | ||
* | ||
* @author Sebastian Hörl (sebhoerl), IRT SystemX | ||
*/ | ||
public class ChargerReservationModule extends AbstractModule { | ||
@Override | ||
public void install() { | ||
addControlerListenerBinding().to(ChargerReservationManager.class); | ||
bind(ChargingPriority.Factory.class).to(ReservationBasedChargingPriority.Factory.class); | ||
} | ||
|
||
@Provides | ||
@Singleton | ||
ReservationBasedChargingPriority.Factory provideReservationBasedChargingPriorityFactory( | ||
ChargerReservationManager reservationManager) { | ||
return new ReservationBasedChargingPriority.Factory(reservationManager); | ||
} | ||
|
||
@Provides | ||
@Singleton | ||
ChargerReservationManager provideChargerReservationManager() { | ||
return new ChargerReservationManager(); | ||
} | ||
} |
Oops, something went wrong.