def __init__(self, bounding_box=BoundingBox(Position(0.0, 0), Position(100.0, 1)), outside=False, subrules=tuple(), subrule_operator=RuleOperator.ANY): ''' Initialisation :param bounding_box: BoundingBox, can be represented as a tuple, i.e. ((x1,y1),(x2,y2)) :param outside: True|False, apply to vehicles outside (or resp. inside) of the bounding box (default: False -> inside) :param subrules: List of sub-rules :param subrule_operator: Rule operator of RuleOperator enum for applying sub-rules ANY|ALL ''' SUMOPositionRule.__init__(self, bounding_box=bounding_box, outside=outside) ExtendableSUMORule.__init__(self, subrules=subrules, subrule_operator=subrule_operator)
def __init__(self, bounding_box=BoundingBox(Position(0.0, 0), Position(100.0, 1)), outside=False): ''' Initialisation. :param bounding_box: BoundingBox, can be represented as a tuple, i.e. ((x1,y1),(x2,y2)) :param outside: True|False, apply to vehicles outside (or resp. inside) of the bounding box (default: False -> inside) ''' super().__init__() assert BoundingBox(*bounding_box).p1.x <= BoundingBox(*bounding_box).p2.x assert BoundingBox(*bounding_box).p1.y <= BoundingBox(*bounding_box).p2.y self._bounding_box = BoundingBox(*bounding_box) self._outside = bool(outside)
def start_position(self, start_position: Position): ''' Include the initial position in calculations, as SUMO tends to put vehicles at positions > 0 in their 0th time step. :param start_position_x: start position on x axis ''' self._properties['start_position'] = Position(*start_position)
def start_position(self) -> Position: ''' Include the initial position in calculations, as SUMO tends to put vehicles at positions > 0 in their 0th time step. :return: start position ''' return Position(*self._properties.get('start_position'))
def test_basevehicle(self): ''' Test BaseVehicle class ''' # test default values l_basevehicle = colmto.environment.vehicle.BaseVehicle() self.assertEqual(l_basevehicle.speed, 0.0) self.assertEqual(l_basevehicle.position, Position(0.0, 0)) # test custom values l_basevehicle = colmto.environment.vehicle.BaseVehicle() l_basevehicle._properties['position'] = Position(23.0, 0) # pylint: disable=protected-access l_basevehicle._properties['speed'] = 12.1 # pylint: disable=protected-access self.assertEqual(l_basevehicle.speed, 12.1) self.assertEqual(l_basevehicle.position, Position(23.0, 0)) self.assertEqual(l_basevehicle.properties.get('position'), Position(23.0, 0)) self.assertEqual(l_basevehicle.properties.get('speed'), 12.1)
def test_update(self): '''Test update''' l_sumovehicle = colmto.environment.vehicle.SUMOVehicle( environment={ 'gridlength': 200, 'gridcellwidth': 4 }, speed_max=15, vtype_sumo_cfg={'dsat_threshold': 0.2}) self.assertEqual(l_sumovehicle.dsat_threshold, 0.2) self.assertEqual(l_sumovehicle.speed_max, 15) self.assertEqual(l_sumovehicle.dissatisfaction, 0.0) l_sumovehicle._properties['position'] = (0, 0) l_sumovehicle.start_time = 0 l_sumovehicle.update(position=Position(15000, 0), lane_index=1, speed=15, time_step=1000) self.assertAlmostEqual(l_sumovehicle.dissatisfaction, 0.0, places=4) self.assertEqual(l_sumovehicle.position, Position(15000, 0)) self.assertEqual( l_sumovehicle.speed, # pylint: disable=protected-access 15) self.assertEqual( l_sumovehicle.grid_position, # pylint: disable=protected-access GridPosition(round(15000 / 4) - 1, -1)) self.assertEqual( l_sumovehicle.time_step, # pylint: disable=protected-access 1000) l_sumovehicle.update(position=Position(12500, 0), lane_index=0, speed=12, time_step=1000) self.assertAlmostEqual(l_sumovehicle.dissatisfaction, .5, places=4)
def test_sumo_cse(self): ''' Test SumoCSE class ''' self.assertIsInstance( colmto.cse.cse.SumoCSE( SimpleNamespace(loglevel='debug', quiet=False, logfile='foo.log', writefulloccupancies=False)), colmto.cse.cse.SumoCSE) l_rule_speed = colmto.cse.rule.SUMOMinimalSpeedRule(80.) l_rule_outside_position = colmto.cse.rule.SUMOPositionRule( bounding_box=((0., 0), (64.0, 1)), outside=True) l_sumo_cse = colmto.cse.cse.SumoCSE().add_rule( l_rule_outside_position).add_rule(l_rule_speed) self.assertIsInstance(l_sumo_cse, colmto.cse.cse.SumoCSE) self.assertIsInstance(l_sumo_cse.rules, frozenset) self.assertIn(l_rule_speed, l_sumo_cse.rules) self.assertIn(l_rule_outside_position, l_sumo_cse.rules) self.assertIs(l_sumo_cse._traci, None) # pylint: disable=protected-access l_sumo_cse.traci('foo') self.assertEqual(l_sumo_cse._traci, 'foo') # pylint: disable=protected-access self.assertIs(l_sumo_cse.traci(None), l_sumo_cse) with self.assertRaises(TypeError): l_sumo_cse.add_rule('foo') l_vehicles = [ colmto.environment.vehicle.SUMOVehicle( environment={ 'gridlength': 200, 'gridcellwidth': 4 }, speed_max=numpy.random.randint(0, 250)) for _ in range(1000) ] for i_vehicle in l_vehicles: i_vehicle._properties['position'] = Position( numpy.random.randint(0, 120), numpy.random.randint(0, 1)) # pylint: disable=protected-access l_sumo_cse.apply(l_vehicles) for i_vehicle in l_vehicles: if 0 <= i_vehicle.position.x <= 64.0 and 0 <= i_vehicle.position.y <= 1 and \ i_vehicle.speed_max >= 80.0: self.assertEqual(i_vehicle.vehicle_class, colmto.cse.rule.SUMORule.allowed_class_name()) else: self.assertEqual( i_vehicle.vehicle_class, colmto.cse.rule.SUMORule.disallowed_class_name()) self.assertEqual( len(colmto.cse.cse.SumoCSE().add_rules_from_cfg({}).rules), 0) l_sumo_cse = colmto.cse.cse.SumoCSE().add_rules_from_cfg([{ 'type': 'ExtendableSUMOPositionRule', 'args': { 'bounding_box': ((1350., -2.), (2500., 2.)) }, 'subrule_operator': 'ANY', 'subrules': [{ 'type': 'SUMOMinimalSpeedRule', 'args': { 'minimal_speed': 85 / 3.6 }, }] }]) self.assertIsInstance( tuple(l_sumo_cse.rules)[0], colmto.cse.rule.ExtendableSUMOPositionRule) l_rule_speed = colmto.cse.rule.SUMOMinimalSpeedRule.from_configuration( { 'type': 'SUMOMinimalSpeedRule', 'args': { 'minimal_speed': 30 / 3.6 } }) l_sumo_cse.add_rule(l_rule_speed) self.assertIn(l_rule_speed, l_sumo_cse.rules)
def __init__(self, environment: dict, vehicle_type: str = None, vtype_sumo_cfg: dict = None, speed_deviation: float = 0.0, sigma: float = 0.0, speed_max: float = 0.0, cooperation_probability: typing.Union[None, float] = None): ''' Initialisation. :type environment: dict :param environment: environment :type vehicle_type: str :param vehicle_type: SUMO vehicle type :type vtype_sumo_cfg: dict :param vtype_sumo_cfg: (optional) SUMO config :type speed_deviation: float :param speed_deviation: speed deviation (Krauss driver model) :type sigma: float :param sigma: sigma (Krauss driver model) :type speed_max: float :param speed_max: maximum desired or capable speed of vehicle :type cooperation_probability: float :param cooperation_probability: disposition for cooperative driving with :math:`p\in [0,1]\cup \{None\}`. :math:`p=1` or `None` means always cooperative (default), :math:`p=0` always uncooperative ''' super().__init__() if isinstance(vtype_sumo_cfg, dict): self._properties.update(vtype_sumo_cfg) self._properties.update({ 'colour': Colour(red=255, green=255, blue=0, alpha=255), 'normal_colour': Colour(red=255, green=255, blue=0, alpha=255), 'start_time': 0.0, 'start_position': Position(x=0.0, y=0.0), 'speedDev': speed_deviation, 'sigma': sigma, 'maxSpeed': speed_max, 'vType': vehicle_type, 'vClass': colmto.cse.rule.SUMORule.allowed_class_name(), 'grid_position': Position(x=0, y=0), 'time_step': 0.0, 'travel_time': 0.0, 'dissatisfaction': 0.0, 'cooperation_disposition': VehicleDisposition.COOPERATIVE if not cooperation_probability else VehicleDisposition.choose(cooperation_probability) }) self._environment = environment # prepare grid-based series using OrderedDicts to maintain the order of keys self._grid_based_series_dict = { i_metric.value: OrderedDict() for i_metric in StatisticSeries.GRID.metrics() }
def __init__(self): '''Initialisation''' self._properties = {'position': Position(x=0.0, y=0.0), 'speed': 0.0}
def update(self, position: Position, lane_index: int, speed: float, time_step: float) -> BaseVehicle: ''' Update current properties of vehicle providing data acquired from TraCI call. For the grid cell the vehicle is in, take the global position in x-direction divided by grid cell size and int-rounded. For the y-coordinate take the lane index. :note: The cell width can be set via 'gridcellwidth' in the run config. :param position: tuple TraCI provided position :param lane_index: int TraCI provided lane index :param speed: float TraCI provided speed :param time_step: float TraCI provided time step :return: future Vehicle reference ''' # update current vehicle properties l_position = Position(*position) assert l_position.x >= 0 and l_position.y >= 0 self._properties['position'] = l_position self._properties['grid_position'] = l_position.gridified( width=self._environment.get('gridcellwidth')) assert float(speed) >= 0 self._properties['speed'] = float(speed) assert float(time_step) >= 0 self._properties['time_step'] = float(time_step) assert float(time_step) >= self.start_time self._properties['travel_time'] = float(time_step) - self.start_time assert int(lane_index) in (0, 1) self._properties['lane_index'] = int(lane_index) # vehicle/generic optimal travel time: round positions of division as SUMO reports positions with reduced # accuracy (2 significant figures) to avoid negative travel time losses. l_generic_optimal_travel_time = round(self.position.x / self.speed_max, 2) # Vehicle optimal travel time: include, i.e. substract the start_position as SUMO puts # vehicles at lane positions greater than 0 in their first active time step if they started # between the previous and current global (runtime) time step. l_vehicle_optimal_travel_time = round( (self.position.x - self.start_position.x) / self.speed_max, 2) l_vehicle_time_loss = self.travel_time - l_vehicle_optimal_travel_time assert l_vehicle_time_loss >= 0 self._properties[ 'dissatisfaction'] = colmto.common.model.dissatisfaction( time_loss=l_vehicle_time_loss, optimal_travel_time=l_generic_optimal_travel_time, time_loss_threshold=self.dsat_threshold) assert 0 <= self.dissatisfaction <= 1 # update data series based on grid cell self._grid_based_series_dict.get( Metric.TIME_STEP.value)[(Metric.TIME_STEP.value, self.grid_position.x)] = float(time_step) self._grid_based_series_dict.get( Metric.POSITION_Y.value)[(Metric.POSITION_Y.value, self.grid_position.x)] = self.position.y self._grid_based_series_dict.get(Metric.GRID_POSITION_Y.value)[( Metric.GRID_POSITION_Y.value, self.grid_position.x)] = self.grid_position.y self._grid_based_series_dict.get(Metric.DISSATISFACTION.value)[( Metric.DISSATISFACTION.value, self.grid_position.x)] = self.dissatisfaction self._grid_based_series_dict.get(Metric.TRAVEL_TIME.value)[( Metric.TRAVEL_TIME.value, self.grid_position.x)] = self.travel_time self._grid_based_series_dict.get(Metric.TIME_LOSS.value)[( Metric.TIME_LOSS.value, self.grid_position.x)] = l_vehicle_time_loss self._grid_based_series_dict.get(Metric.RELATIVE_TIME_LOSS.value)[( Metric.RELATIVE_TIME_LOSS.value, self.grid_position.x )] = l_vehicle_time_loss / l_generic_optimal_travel_time if l_generic_optimal_travel_time > 0 else 0 self._grid_based_series_dict.get( Metric.LANE_INDEX.value)[(Metric.LANE_INDEX.value, self.grid_position.x)] = self.lane return self
def test_sumovehicle(self): ''' Test SUMOVehicle class. ''' # test default values l_sumovehicle = colmto.environment.vehicle.SUMOVehicle( environment={ 'gridlength': 200, 'gridcellwidth': 4 }) self.assertEqual(l_sumovehicle.speed_max, 0.0) self.assertEqual(l_sumovehicle.speed, 0.0) # pylint: disable=protected-access self.assertEqual(l_sumovehicle.position, Position(0.0, 0)) self.assertEqual(l_sumovehicle.vehicle_type, VehicleType.UNDEFINED) self.assertEqual(l_sumovehicle.colour, Colour(255, 255, 0, 255)) self.assertEqual(l_sumovehicle.time_step, 0.0) l_sumovehicle._properties['time_step'] = 42.1 # pylint: disable=protected-access self.assertEqual(l_sumovehicle.time_step, 42.1) self.assertIsInstance( l_sumovehicle.properties.get('cooperation_disposition'), VehicleDisposition) self.assertIs(l_sumovehicle.properties.get('cooperation_disposition'), VehicleDisposition.COOPERATIVE) # test custom values l_sumovehicle = colmto.environment.vehicle.SUMOVehicle( speed_max=27.777, speed_deviation=1.2, environment={ 'gridlength': 200, 'gridcellwidth': 4 }, vehicle_type='passenger', vtype_sumo_cfg={ 'length': 3.00, 'minGap': 2.50 }) l_sumovehicle._properties['position'] = Position(42.0, 0) l_sumovehicle.normal_colour = (128, 64, 255, 255) l_sumovehicle.start_time = 13 self.assertEqual(l_sumovehicle.start_position, Position(0.0, 0.0)) l_sumovehicle.start_position = Position(1.2, 3.4) self.assertEqual(l_sumovehicle.start_position.x, 1.2) self.assertEqual(l_sumovehicle.start_position.y, 3.4) self.assertEqual(l_sumovehicle.start_position.gridified(2).x, 0) self.assertEqual(l_sumovehicle.start_position.gridified(2).y, 1) self.assertEqual(l_sumovehicle.start_position, Position(1.2, 3.4)) self.assertEqual(l_sumovehicle.speed_max, 27.777) self.assertEqual(l_sumovehicle.position, Position(42.0, 0)) self.assertEqual(l_sumovehicle.vehicle_type, VehicleType.PASSENGER) self.assertEqual(l_sumovehicle.normal_colour, Colour(128, 64, 255, 255)) self.assertEqual(l_sumovehicle.start_time, 13) self.assertEqual(l_sumovehicle.grid_position, GridPosition(0, 0)) l_sumovehicle._properties['grid_position'] = GridPosition(1, 2) # pylint: disable=protected-access self.assertEqual(l_sumovehicle.grid_position, GridPosition(1, 2)) self.assertEqual(l_sumovehicle.properties.get('grid_position'), GridPosition(1, 2)) self.assertEqual(l_sumovehicle.travel_time, 0.0)