Skip to content

Commit

Permalink
Update AgentInterface with vehicle class.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gamenot committed Jan 4, 2024
1 parent e936588 commit 1d3e58b
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 58 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ Copy and pasting the git commit messages is __NOT__ enough.
- Renamed `MACOS` `pybullet` gui utility from `smarts.core.utils.bullet.BulletClient` to `smarts.core.utils.pybullet.BulletClientMACOS`.
- `Vehicle.build_agent_vehicle()` and `Vehicle.build_social_vehicle()` moved to `VehicleIndex`.
- `smarts.core.configuration.Configuration.get_settings()` now uses the `PyYAML` default instead of forcefully casting to `str`.
- Added `AgentInterface.vehicle_class` which allows selection of a dynamics vehicle from the vehicle definitions list file.
### Deprecated
- Module `smarts.core.models` is now deprecated in favour of `smarts.assets`.
- Deprecated a few things related to vehicles in the `Scenario` class, including the `vehicle_filepath`, `tire_parameters_filepath`, and `controller_parameters_filepath`. The functionality is now handled through the vehicle definitions.
- `AgentInterface.vehicle_type` is now deprecated with potential to be restored.
### Fixed
- `SumoTrafficSimulation` gives clearer reasons as to why it failed to connect to the TraCI server.
- Suppressed an issue where `pybullet_utils.pybullet.BulletClient` would cause an error because it was catching a non `BaseException` type.
Expand Down
6 changes: 3 additions & 3 deletions smarts/assets/vehicles/vehicle_definitions_list.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
bus: ${SMARTS_ASSETS_PATH}/vehicles/definitions/bus.yaml
moving_truck_empty: ${SMARTS_ASSETS_PATH}/vehicles/definitions/moving_truck_empty.yaml
moving_truck_loaded: ${SMARTS_ASSETS_PATH}/vehicles/definitions/moving_truck_loaded.yaml
sedan: &SEDAN ${SMARTS_ASSETS_PATH}/vehicles/definitions/sedan.yaml
truck: ${SMARTS_ASSETS_PATH}/vehicles/definitions/moving_truck_empty.yaml
passenger: *SEDAN
generic_sedan: &GENERIC_SEDAN ${SMARTS_ASSETS_PATH}/vehicles/definitions/sedan.yaml
sedan: *GENERIC_SEDAN
truck: ${SMARTS_ASSETS_PATH}/vehicles/definitions/moving_truck_empty.yaml
29 changes: 17 additions & 12 deletions smarts/core/agent_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,16 @@ class AgentInterface:
The choice of action space; this also decides the controller that will be enabled and the chassis type that will be used.
"""

vehicle_type: Literal[
"bus", "coach", "motorcycle", "pedestrian", "sedan", "trailer", "truck"
] = "sedan"
vehicle_type: str = ""
"""
The choice of vehicle type.
"""

vehicle_class: str = "generic_sedan"
"""
The choice of vehicle classes from the vehicle definition list.
"""

accelerometer: Union[Accelerometer, bool] = True
"""
Enable acceleration and jerk observations.
Expand Down Expand Up @@ -369,15 +372,17 @@ def __post_init__(self):
self.lane_positions, LanePositions
)
self.signals = AgentInterface._resolve_config(self.signals, Signals)
assert self.vehicle_type in {
"bus",
"coach",
"motorcycle",
"pedestrian",
"sedan",
"trailer",
"truck",
}
if self.vehicle_type != "":
warnings.warn(
"`vehicle_type` is now deprecated. Instead use `vehicle_class`.",
category=DeprecationWarning,
)
assert self.vehicle_type in (
"sedan",
"bus",
), "Only these values were supported at deprecation."
self.vehicle_class = self.vehicle_type
assert isinstance(self.vehicle_class, str)

@staticmethod
def from_type(requested_type: AgentType, **kwargs):
Expand Down
1 change: 0 additions & 1 deletion smarts/core/agents_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ def perform_agent_actions(self, agent_actions: Dict[str, Any]):
controller_state,
sensor_state,
agent_interface.action,
agent_interface.vehicle_type,
)

@property
Expand Down
4 changes: 2 additions & 2 deletions smarts/core/chassis.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ def __init__(
self,
pose: Pose,
bullet_client: bc.BulletClient,
vehicle_filepath=DEFAULT_VEHICLE_FILEPATH,
vehicle_dynamics_filepath=DEFAULT_VEHICLE_FILEPATH,
tire_parameters_filepath=None,
friction_map=None,
controller_parameters=DEFAULT_CONTROLLER_PARAMETERS,
Expand Down Expand Up @@ -381,7 +381,7 @@ def __init__(
self._road_wheel_frictions = None

self._bullet_id = self._client.loadURDF(
vehicle_filepath,
vehicle_dynamics_filepath,
[0, 0, 0],
[0, 0, 0, 1],
useFixedBase=False,
Expand Down
5 changes: 0 additions & 5 deletions smarts/core/controllers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ def perform_action(
controller_state,
sensor_state,
action_space,
vehicle_type,
):
"""Calls control for the given vehicle based on a given action space and action.
Expand All @@ -89,13 +88,9 @@ def perform_action(
The state of a vehicle sensor as relates to vehicle sensors.
action_space:
The action space of the provided action.
vehicle_type:
Vehicle type information about the given vehicle.
"""
if action is None:
return
if vehicle_type == "bus":
assert action_space == ActionSpaceType.Trajectory
if action_space == ActionSpaceType.Continuous:
vehicle.control(
throttle=np.clip(action[0], 0.0, 1.0),
Expand Down
10 changes: 6 additions & 4 deletions smarts/core/tests/test_trajectory_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from smarts.core.utils import pybullet
from smarts.core.utils.pybullet import SafeBulletClient
from smarts.core.utils.resources import (
VehicleDefinitions,
load_vehicle_definitions_list,
load_yaml_config_with_substitution,
)
Expand All @@ -45,13 +46,14 @@


@pytest.fixture
def vehicle_definitions_list():
def vehicle_definitions_list() -> VehicleDefinitions:
return load_vehicle_definitions_list(None)


@pytest.fixture(params=["bus", "sedan", "truck"])
def vehicle_definition(vehicle_definitions_list, request: pytest.FixtureRequest):

def vehicle_definition(
vehicle_definitions_list: VehicleDefinitions, request: pytest.FixtureRequest
):
return vehicle_definitions_list.load_vehicle_definition(request.param)


Expand Down Expand Up @@ -79,7 +81,7 @@ def vehicle(bullet_client, vehicle_definition, fixed_timestep_sec=time_step):
chassis=AckermannChassis(
pose=pose,
bullet_client=bullet_client,
vehicle_filepath=vehicle_definition["dynamics_model"],
vehicle_dynamics_filepath=vehicle_definition["dynamics_model"],
controller_parameters=load_yaml_config_with_substitution(
vehicle_definition["controller_params"]
),
Expand Down
18 changes: 9 additions & 9 deletions smarts/core/utils/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def load_vehicle_definitions_list(vehicle_list_filepath: Optional[str]):
vehicle_list_filepath = config()("assets", "default_vehicle_definitions_list")
vehicle_list_filepath = Path(vehicle_list_filepath).absolute()

return VehicleDefintions(
return VehicleDefinitions(
data=load_yaml_config_with_substitution(vehicle_list_filepath),
filepath=vehicle_list_filepath,
)
Expand Down Expand Up @@ -96,7 +96,7 @@ def load_yaml_config_with_substitution(


@dataclass(frozen=True)
class VehicleDefintions:
class VehicleDefinitions:
"""This defines a set of vehicle definitions and loading utilities."""

data: Dict[str, Any]
Expand All @@ -105,25 +105,25 @@ class VehicleDefintions:
"""The path to the vehicle definitions file."""

@lru_cache(maxsize=20)
def load_vehicle_definition(self, vehicle_type: str):
def load_vehicle_definition(self, vehicle_class: str):
"""Loads in a particular vehicle definition."""
if vehicle_definition_filepath := self.data.get(vehicle_type):
if vehicle_definition_filepath := self.data.get(vehicle_class):
return load_yaml_config_with_substitution(Path(vehicle_definition_filepath))
raise OSError(
f"Vehicle '{vehicle_type}' is not defined in {list(self.data.keys())}"
f"Vehicle '{vehicle_class}' is not defined in {list(self.data.keys())}"
)

@lru_cache(maxsize=20)
def controller_params_for_vehicle_type(self, vehicle_type: str):
def controller_params_for_vehicle_class(self, vehicle_class: str):
"""Get the controller parameters for the given vehicle type"""
vehicle_definition = self.load_vehicle_definition(vehicle_type)
vehicle_definition = self.load_vehicle_definition(vehicle_class)
controller_params = Path(vehicle_definition["controller_params"])
return load_yaml_config_with_substitution(controller_params)

@lru_cache(maxsize=20)
def chassis_params_for_vehicle_type(self, vehicle_type: str):
def chassis_params_for_vehicle_class(self, vehicle_class: str):
"""Get the controller parameters for the given vehicle type"""
vehicle_definition = self.load_vehicle_definition(vehicle_type)
vehicle_definition = self.load_vehicle_definition(vehicle_class)
chassis_parms = Path(vehicle_definition["chassis_params"])
return load_yaml_config_with_substitution(chassis_parms)

Expand Down
17 changes: 15 additions & 2 deletions smarts/core/vehicle.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ def __init__(
id: str,
chassis: Chassis,
visual_model_filepath: Optional[str],
vehicle_config_type: str = "passenger",
vehicle_config_type: str = "sedan",
vehicle_class: str = "generic_sedan",
color: Optional[SceneColors] = None,
action_space=None,
):
Expand All @@ -80,6 +81,7 @@ def __init__(
if vehicle_config_type == "sedan":
vehicle_config_type = "passenger"
self._vehicle_config_type = vehicle_config_type
self._vehicle_class = vehicle_class
self._action_space = action_space

self._meta_create_sensor_functions()
Expand Down Expand Up @@ -115,6 +117,7 @@ def __repr__(self):
pose={self.pose},
speed={self.speed},
type={self.vehicle_type},
class={self.vehicle_class},
w={self.width},
l={self.length},
h={self.height}
Expand Down Expand Up @@ -250,9 +253,19 @@ def bounding_box(self) -> List[np.ndarray]:

@property
def vehicle_type(self) -> str:
"""Get the vehicle type identifier."""
"""Get the vehicle type name as recognized by SMARTS. (e.g. 'car')"""
return VEHICLE_CONFIGS[self._vehicle_config_type].vehicle_type

@property
def vehicle_config_type(self) -> str:
"""Get the vehicle type identifier. (e.g. 'sedan')"""
return self._vehicle_config_type

@property
def vehicle_class(self) -> str:
"""Get the custom class of vehicle this is. (e.g. 'ford_f150')"""
return self._vehicle_class

@property
def valid(self) -> bool:
"""Check if the vehicle still `exists` and is still operable."""
Expand Down
41 changes: 21 additions & 20 deletions smarts/core/vehicle_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def __init__(self):
self._controller_states = {}

# Loaded from yaml file on scenario reset
self._vehicle_definitions: resources.VehicleDefintions = {}
self._vehicle_definitions: resources.VehicleDefinitions = {}

@classmethod
def identity(cls):
Expand Down Expand Up @@ -477,23 +477,20 @@ def switch_control_to_agent(
vehicle = self._vehicles[vehicle_id]
chassis = None
if agent_interface and agent_interface.action in sim.dynamic_action_spaces:
vehicle_definition = self._vehicle_definitions.load_vehicle_definition(
agent_interface.vehicle_class
)
chassis = AckermannChassis(
pose=vehicle.pose,
bullet_client=sim.bc,
vehicle_filepath=self._vehicle_definitions.load_vehicle_definition(
agent_interface.vehicle_type
).get("dynamics_model"),
tire_parameters_filepath=self._vehicle_definitions.load_vehicle_definition(
agent_interface.vehicle_type
).get(
"tire_params"
),
vehicle_dynamics_filepath=vehicle_definition.get("dynamics_model"),
tire_parameters_filepath=vehicle_definition.get("tire_params"),
friction_map=sim.scenario.surface_patches,
controller_parameters=self._vehicle_definitions.controller_params_for_vehicle_type(
agent_interface.vehicle_type
controller_parameters=self._vehicle_definitions.controller_params_for_vehicle_class(
agent_interface.vehicle_class
),
chassis_parameters=self._vehicle_definitions.chassis_params_for_vehicle_type(
agent_interface.vehicle_type
chassis_parameters=self._vehicle_definitions.chassis_params_for_vehicle_class(
agent_interface.vehicle_class
),
initial_speed=vehicle.speed,
)
Expand Down Expand Up @@ -646,14 +643,15 @@ def _switch_control_to_agent_recreate(
plan = sensor_state.get_plan(sim.road_map)

vehicle_definition = self._vehicle_definitions.load_vehicle_definition(
agent_interface.vehicle_type
agent_interface.vehicle_class
)
# Create a new vehicle to replace the old one
new_vehicle = VehicleIndex._build_agent_vehicle(
sim,
vehicle.id,
agent_interface.action,
vehicle_definition.get("type"),
agent_interface.vehicle_class,
plan,
vehicle_definition.get("dynamics_model"),
vehicle_definition.get("tire_params"),
Expand Down Expand Up @@ -705,6 +703,7 @@ def _build_agent_vehicle(
vehicle_id: str,
action: Optional[ActionSpaceType],
vehicle_type: str,
vehicle_class: str,
plan: Plan,
vehicle_dynamics_filepath: Optional[str],
tire_filepath: str,
Expand All @@ -731,13 +730,13 @@ def _build_agent_vehicle(

vehicle_color = SceneColors.Agent if trainable else SceneColors.SocialAgent
controller_parameters = (
sim.vehicle_index._vehicle_definitions.controller_params_for_vehicle_type(
vehicle_type
sim.vehicle_index._vehicle_definitions.controller_params_for_vehicle_class(
vehicle_class
)
)
chassis_parameters = (
sim.vehicle_index._vehicle_definitions.chassis_params_for_vehicle_type(
vehicle_type
sim.vehicle_index._vehicle_definitions.chassis_params_for_vehicle_class(
vehicle_class
)
)

Expand All @@ -751,7 +750,7 @@ def _build_agent_vehicle(
chassis = AckermannChassis(
pose=start_pose,
bullet_client=sim.bc,
vehicle_filepath=vehicle_dynamics_filepath,
vehicle_dynamics_filepath=vehicle_dynamics_filepath,
tire_parameters_filepath=tire_filepath,
friction_map=surface_patches,
controller_parameters=controller_parameters,
Expand All @@ -771,6 +770,7 @@ def _build_agent_vehicle(
chassis=chassis,
color=vehicle_color,
vehicle_config_type=vehicle_type,
vehicle_class=vehicle_class,
visual_model_filepath=visual_model_filepath,
)

Expand All @@ -790,13 +790,14 @@ def build_agent_vehicle(
):
"""Build an entirely new vehicle for an agent."""
vehicle_definition = self._vehicle_definitions.load_vehicle_definition(
agent_interface.vehicle_type
agent_interface.vehicle_class
)
vehicle = VehicleIndex._build_agent_vehicle(
sim=sim,
vehicle_id=vehicle_id or agent_id,
action=agent_interface.action,
vehicle_type=vehicle_definition.get("type"),
vehicle_class=agent_interface.vehicle_class,
plan=plan,
vehicle_dynamics_filepath=vehicle_definition.get("dynamics_model"),
tire_filepath=vehicle_definition.get("tire_params"),
Expand Down

0 comments on commit 1d3e58b

Please sign in to comment.