diff --git a/simba/rotation.py b/simba/rotation.py index 2e821af..8320625 100644 --- a/simba/rotation.py +++ b/simba/rotation.py @@ -11,6 +11,7 @@ def __init__(self, id, vehicle_type, schedule) -> None: self.trips = [] self.schedule = schedule + self.allow_opp_charging_for_oppb: bool = True self.vehicle_type = vehicle_type self.vehicle_id = None self.charging_type = None diff --git a/simba/schedule.py b/simba/schedule.py index a53757e..25b8312 100644 --- a/simba/schedule.py +++ b/simba/schedule.py @@ -920,8 +920,11 @@ def generate_scenario(self, args): # assume electrified station station = self.stations[gc_name] station_type = station["type"] - if station_type == 'opps' and trip.rotation.charging_type == 'depb': - # a depot bus cannot charge at an opp station + if (station_type == 'opps' and + (trip.rotation.charging_type == 'depb' or + not trip.rotation.allow_opp_charging_for_oppb)): + # a depot bus cannot charge at an opp station. + # a bus cannot charge at opps if it's not allowed station_type = None else: # get desired soc by station type and trip diff --git a/tests/test_schedule.py b/tests/test_schedule.py index 56385f2..507926a 100644 --- a/tests/test_schedule.py +++ b/tests/test_schedule.py @@ -60,6 +60,32 @@ def basic_run(self): class TestSchedule(BasicSchedule): + def test_allow_opp_charging(self): + # test if the schedule properly skips charging events if the rotation is not allowed + # to opportunity charge + sched, scen, args = BasicSchedule().basic_run() + oppb_rotations = [rot for rot in sched.rotations.values() if rot.charging_type == "oppb"] + assert len(oppb_rotations) >= 1 + oppb_rotation = oppb_rotations[0] + vehicle = oppb_rotation.vehicle_id + assert oppb_rotation.allow_opp_charging_for_oppb is True + index = list(scen.components.vehicles.keys()).index(vehicle) + min_soc = min(s[index] for s in scen.socs if s[index] is not None) + vehicle_event = [e for e in scen.events.vehicle_events if e.vehicle_id == vehicle] + charge_events = 0 + for e in vehicle_event: + if vars(e).get("update", {}).get("connected_charging_station") is not None: + charge_events += 1 + + assert charge_events > 0, \ + "Rotation has no charge events to check if allow_opp_charging_for_oppb works" + for rot in oppb_rotations: + rot.allow_opp_charging_for_oppb = False + scen2 = sched.run(args) + + index = list(scen2.components.vehicles.keys()).index(vehicle) + min_soc_charging_not_allowed = min(s[index] for s in scen2.socs if s[index] is not None) + assert min_soc_charging_not_allowed < min_soc def test_timestep(self): # Get the parser from util. This way the test is directly coupled to the parser arguments