diff --git a/docs/sim/env.rst b/docs/sim/env.rst index ad167b34d8..5c984612d1 100644 --- a/docs/sim/env.rst +++ b/docs/sim/env.rst @@ -50,7 +50,7 @@ HiwayEnvV1 ``HiwayEnvV1`` inherits class ``gymnasium.Env`` and supports gym APIs like ``reset``, ``step``, ``close``. An usage example is shown below. This version has two configurations of observation output: `ObservationOptions.full` which provides padded agents in the observations which exactly matches the `env.observation_space`, and `ObservationOptions.multi_agent` which provides only agents as are currently active. Refer to - :class:`~smarts.env.gymnasium.hiway_env_v1.HiWayEnvV1` for more details. +:class:`~smarts.env.gymnasium.hiway_env_v1.HiWayEnvV1` for more details. .. code-block:: python diff --git a/docs/sim/obs_action_reward.rst b/docs/sim/obs_action_reward.rst index eab1671a1e..43721de82d 100644 --- a/docs/sim/obs_action_reward.rst +++ b/docs/sim/obs_action_reward.rst @@ -17,7 +17,7 @@ The complete set of possible :class:`~smarts.core.sensors.Observation` returned +------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------+ | steps_completed | int | Number of steps this agent has taken within SMARTS. | +------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------+ -| elapsed_sim_time | float | Amount of simulation time elapsed for the current scenario. | +| elapsed_sim_time | float | Amount of simulation time elapsed for the current scenario. | +------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------+ | events | :class:`~smarts.core.events.Events` | Classified observations that can trigger agent done status. | +------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------+ @@ -25,7 +25,7 @@ The complete set of possible :class:`~smarts.core.sensors.Observation` returned +------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------+ | under_this_agent_control | bool | Whether this agent currently has control of the vehicle. | +------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------+ -| neighborhood_vehicle_states | Optional[List[:class:`~smarts.core.sensors.VehicleObservation`]] | List of neighborhood vehicle states. | +| neighborhood_vehicle_states | Optional[List[:class:`~smarts.core.sensors.VehicleObservation`]] | List of neighborhood vehicle states. | +------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------+ | waypoint_paths | Optional[List[List[:class:`~smarts.core.road_map.Waypoint`]]] | Dynamic evenly-spaced points on the road ahead of the vehicle. | +------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------+ diff --git a/requirements.txt b/requirements.txt index 9c92bc969b..c9f0e213c6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ Automat==22.10.0 beautifulsoup4==4.11.1 blessed==1.19.1 cached-property==1.5.2 -cachetools==5.2.1 +cachetools==5.3.0 certifi==2022.12.7 charset-normalizer==2.1.1 click==8.1.3 @@ -43,7 +43,7 @@ grpcio==1.51.1 gym==0.19.0 gymnasium==0.27.0 gymnasium-notices==0.0.1 -h5py==3.7.0 +h5py==3.8.0 hyperlink==21.0.0 idna==3.4 ijson==3.2.0.post0 diff --git a/smarts/env/gymnasium/hiway_env_v1.py b/smarts/env/gymnasium/hiway_env_v1.py index c10bc55740..a2fd9572af 100644 --- a/smarts/env/gymnasium/hiway_env_v1.py +++ b/smarts/env/gymnasium/hiway_env_v1.py @@ -89,17 +89,15 @@ class SumoOptions(NamedTuple): ) -# TODO: Could not help the double layer joke here: highway-lowway huawei-laowei. Add a real name. class HiWayEnvV1(gym.Env): """A generic environment for various driving tasks simulated by SMARTS. Args: - scenarios (Sequence[str]): A list of scenario directories that + scenarios (Sequence[str]): A list of scenario directories that will be simulated. agent_interfaces (Dict[str, AgentInterface]): Specification of the agents needs that will be used to configure the environment. - sim_name (str, optional): Simulation name. Defaults to - None. + sim_name (str, optional): Simulation name. Defaults to None. scenarios_order (ScenarioOrder, optional): Configures the order that scenarios will provided over successive resets. headless (bool, optional): If True, disables visualization in @@ -119,14 +117,14 @@ class HiWayEnvV1(gym.Env): zoo_addrs (str, optional): List of (ip, port) tuples of zoo server, used to instantiate remote social agents. Defaults to None. - observation_options (ObservationOptions | string): Defines the options + observation_options (ObservationOptions, string): Defines the options for how the formatting matches the observation space. String version can be used instead. See :class:`ObservationOptions`. Defaults to - `ObservationOptions.default`. + :attr:`ObservationOptions.default`. """ metadata = {"render.modes": ["human"]} - """Metadata for gym's use""" + """Metadata for gym's use.""" # define render_mode if your environment supports rendering render_mode: Optional[str] = None @@ -233,15 +231,20 @@ def step( ], ]: """Run one timestep of the environment's dynamics using the agent actions. + When the end of an episode is reached (``terminated or truncated``), it is necessary to call :meth:`reset` to reset this environment's state for the next episode. Args: action (ActType): an action provided by the agent to update the environment state. + Returns: - observation (dict): An element of the environment's :attr:`observation_space` as the next observation due to the agent actions. - This observation will change based on the provided :attr:`agent_interfaces`. Check :attr:`observation_space after initialization. - reward (SupportsFloat): The reward as a result of taking the action. + observation (dict): An element of the environment's :attr:`observation_space` as the + next observation due to the agent actions. This observation will change based on + the provided :attr:`agent_interfaces`. Check :attr:` observation_space after + initialization. + reward (SupportsFloat): The reward as a result of taking the + action. terminated (bool): Whether the agent reaches the terminal state (as defined under the MDP of the task) which can be positive or negative. An example is reaching the goal state. If true, the user needs to call :meth:`reset`. truncated (bool): Whether the truncation condition outside the scope of the MDP is satisfied. @@ -320,10 +323,11 @@ def reset( Usually, you want to pass an integer *right after the environment has been initialized and then never again*. options (optional dict): Additional information to specify how the environment is reset (optional, depending on the specific environment) + Returns: observation (dict): Observation of the initial state. This will be an element of :attr:`observation_space` and is analogous to the observation returned by :meth:`step`. - info (dictionary): This dictionary contains auxiliary information complementing ``observation``. It should be analogous to + info (dict): This dictionary contains auxiliary information complementing ``observation``. It should be analogous to the ``info`` returned by :meth:`step`. """ super().reset(seed=seed, options=options) @@ -347,20 +351,27 @@ def render( The environment's :attr:`metadata` render modes (`env.metadata["render_modes"]`) should contain the possible ways to implement the render modes. In addition, list versions for most render modes is achieved through `gymnasium.make` which automatically applies a wrapper to collect rendered frames. + Note: As the :attr:`render_mode` is known during ``__init__``, the objects used to render the environment state should be initialised in ``__init__``. + By convention, if the :attr:`render_mode` is: - - None (default): no render is computed. - - "human": The environment is continuously rendered in the current display or terminal, usually for human consumption. - This rendering should occur during :meth:`step` and :meth:`render` doesn't need to be called. Returns ``None``. - - "rgb_array": Return a single frame representing the current state of the environment. - A frame is a ``np.ndarray`` with shape ``(x, y, 3)`` representing RGB values for an x-by-y pixel image. - - "ansi": Return a strings (``str``) or ``StringIO.StringIO`` containing a terminal-style text representation - for each time step. The text can include newlines and ANSI escape sequences (e.g. for colors). - - "rgb_array_list" and "ansi_list": List based version of render modes are possible (except Human) through the - wrapper, :py:class:`gymnasium.wrappers.RenderCollection` that is automatically applied during ``gymnasium.make(..., render_mode="rgb_array_list")``. - The frames collected are popped after :meth:`render` is called or :meth:`reset`. + - None (default): no render is computed. + - "human": The environment is continuously rendered in the current display or terminal, + usually for human consumption. This rendering should occur during :meth:`step` and + :meth:`render` doesn't need to be called. Returns ``None``. + - "rgb_array": Return a single frame representing the current state of the environment. + A frame is a ``np.ndarray`` with shape ``(x, y, 3)`` representing RGB values for + an x-by-y pixel image. + - "ansi": Return a strings (``str``) or ``StringIO.StringIO`` containing a + terminal-style text representation for each time step. The text can include + newlines and ANSI escape sequences (e.g. for colors). + - "rgb_array_list" and "ansi_list": List based version of render modes are possible + (except Human) through the wrapper, :py:class:`gymnasium.wrappers.RenderCollection` + that is automatically applied during ``gymnasium.make(..., render_mode="rgb_array_list")``. + The frames collected are popped after :meth:`render` is called or :meth:`reset`. + Note: Make sure that your class's :attr:`metadata` ``"render_modes"`` key includes the list of supported modes. """ @@ -382,6 +393,7 @@ def close(self): @property def unwrapped(self) -> gym.Env[ObsType, ActType]: """Returns the base non-wrapped environment. + Returns: Env: The base non-wrapped :class:`gymnasium.Env` instance """ @@ -390,8 +402,9 @@ def unwrapped(self) -> gym.Env[ObsType, ActType]: @property def np_random(self) -> np.random.Generator: """Returns the environment's internal :attr:`_np_random` that if not set will initialise with a random seed. + Returns: - Instances of `np.random.Generator` + Instances of `np.random.Generator`. """ return super().np_random @@ -400,9 +413,10 @@ def np_random(self, value: np.random.Generator): self._np_random = value def __str__(self): - """Returns a string of the environment with :attr:`spec` id's if :attr:`spec. + """Returns a string of the environment with :attr:`spec` id's if :attr:`spec`. + Returns: - A string identifying the environment + A string identifying the environment. """ if self.spec is None: return f"<{type(self).__name__} instance>" @@ -422,6 +436,7 @@ def __exit__(self, *args: Any): @property def agent_ids(self) -> Set[str]: """Agent ids of all agents that potentially will be in the environment. + Returns: (Set[str]): Agent ids. """ @@ -430,6 +445,7 @@ def agent_ids(self) -> Set[str]: @property def agent_interfaces(self) -> Dict[str, AgentInterface]: """Agent interfaces used for the environment. + Returns: (Dict[str, AgentInterface]): Agent interface defining the agents affect on the observation and action spaces @@ -440,8 +456,9 @@ def agent_interfaces(self) -> Dict[str, AgentInterface]: @property def scenario_log(self) -> Dict[str, Union[float, str]]: """Simulation steps log. + Returns: - Dict[str, Union[float,str]]: A dictionary with the following keys. + (Dict[str, Union[float,str]]): A dictionary with the following keys. fixed_timestep_sec - Simulation timestep. scenario_map - Name of the current scenario. scenario_traffic - Traffic spec(s) used. @@ -459,7 +476,8 @@ def scenario_log(self) -> Dict[str, Union[float, str]]: @property def scenario(self) -> Scenario: """Returns underlying scenario. + Returns: - Scenario: Current simulated scenario. + scenario.Scenario: Current simulated scenario. """ return self._smarts.scenario diff --git a/smarts/env/gymnasium/utils/observation_conversion.py b/smarts/env/gymnasium/utils/observation_conversion.py index c70c4b9702..515e25b974 100644 --- a/smarts/env/gymnasium/utils/observation_conversion.py +++ b/smarts/env/gymnasium/utils/observation_conversion.py @@ -79,7 +79,7 @@ class BaseSpaceFormat: """Defines the base interface for an observation formatter.""" def format(self, obs: Observation): - """Selects and formats the given observation to get a value that matches :attr:`space`.""" + """Selects and formats the given observation to get a value that matches the :attr:`space`.""" raise NotImplementedError() def active(self, agent_interface: AgentInterface) -> bool: @@ -1130,165 +1130,170 @@ def name(self): class ObservationsSpaceFormat: """Formats a smarts observation to fixed sized object. - Observations in numpy array format, suitable for vectorized processing. - - For each agent id: - obs = dict({ - If the agent is active. - "active": 1 if agent is active in smarts, else 0 - - Total distance travelled in meters. - "distance_travelled": np.float32 - - Ego vehicle state, with the following attributes. - "ego_vehicle_state": dict({ - "angular_acceleration": - Angular acceleration vector. Requires `accelerometer` attribute - enabled in AgentInterface, else absent. shape=(3,). dtype=np.float32. - "angular_jerk": - Angular jerk vector. Requires `accelerometer` attribute enabled in - AgentInterface, else absent. shape=(3,). dtype=np.float32. - "angular_velocity": - Angular velocity vector. shape=(3,). dtype=np.float32). - "box": - Length, width, and height of the vehicle bounding box. shape=(3,). - dtype=np.float32. - "heading": - Vehicle heading in radians [-pi, pi]. dtype=np.float32. - "lane_index": - Vehicle's lane number. Rightmost lane has index 0 and increases - towards left. dtype=np.int8. - "linear_acceleration": - Vehicle acceleration in x, y, and z axes. Requires `accelerometer` - attribute enabled in AgentInterface, else absent. shape=(3,). - dtype=np.float32. - "linear_jerk": - Linear jerk vector. Requires `accelerometer` attribute enabled in - AgentInterface, else absent. shape=(3,). dtype=np.float32. - "linear_velocity": - Vehicle velocity in x, y, and z axes. shape=(3,). dtype=np.float32. - "pos": - Coordinate of the center of the vehicle bounding box's bottom plane. - shape=(3,). dtype=np.float64. - "speed": - Vehicle speed in m/s. dtype=np.float32. - "steering": - Angle of front wheels in radians [-pi, pi]. dtype=np.float32. - "yaw_rate": - Rotation speed around vertical axis in rad/s [0, 2pi]. - dtype=np.float32. - )} - - A dictionary of event markers. - "events": dict({ - "agents_alive_done": - 1 if `DoneCriteria.agents_alive` is triggered, else 0. - "collisions": - 1 if any collisions occurred with ego vehicle, else 0. - "not_moving": - 1 if `DoneCriteria.not_moving` is triggered, else 0. - "off_road": - 1 if ego vehicle drives off road, else 0. - "off_route": - 1 if ego vehicle drives off mission route, else 0. - "on_shoulder": - 1 if ego vehicle drives on road shoulder, else 0. - "reached_goal": - 1 if ego vehicle reaches its goal, else 0. - "reached_max_episode_steps": - 1 if maximum episode steps reached, else 0. - "wrong_way": - 1 if ego vehicle drives in the wrong traffic direction, else 0. - }) - - Drivable area grid map. Map is binary, with 255 if a cell contains a road, - else 0. dtype=np.uint8. - "drivable_area_grid_map": np.ndarray - - Lidar point cloud, with the following attributes. - "lidar_point_cloud": dict({ - "hit": - Binary array. 1 if an object is hit, else 0. shape(300,). - "point_cloud": - Coordinates of lidar point cloud. shape=(300,3). dtype=np.float64. - "ray_origin": - Ray origin coordinates. shape=(300,3). dtype=np.float64. - "ray_vector": - Ray vectors. shape=(300,3). dtype=np.float64. - }) - Mission details for the ego agent. - "mission": dict({ - "goal_pos": - Achieve goal by reaching the end position. Defaults to np.array([0,0,0]) - for no mission. shape=(3,). dtype=np.float64. - }) + Observations in numpy array format, suitable for vectorized processing. - Feature array of 10 nearest neighborhood vehicles. If nearest neighbor - vehicles are insufficient, default feature values are padded. - "neighborhood_vehicle_states": dict({ - "box": - Bounding box of neighbor vehicles. Defaults to np.array([0,0,0]) per - vehicle. shape=(10,3). dtype=np.float32. - "heading": - Heading of neighbor vehicles in radians [-pi, pi]. Defaults to - np.array([0]) per vehicle. shape=(10,). dtype=np.float32. - "lane_index": - Lane number of neighbor vehicles. Defaults to np.array([0]) per - vehicle. shape=(10,). dtype=np.int8. - "pos": - Coordinate of the center of neighbor vehicles' bounding box's bottom - plane. Defaults to np.array([0,0,0]) per vehicle. shape=(10,3). - dtype=np.float64. - "speed": - Speed of neighbor vehicles in m/s. Defaults to np.array([0]) per - vehicle. shape=(10,). dtype=np.float32. - }) + For each agent id:: + + obs = dict({ + + If the agent is active. + "active": 1 if agent is active in smarts, else 0 + + Total distance travelled in meters. + "distance_travelled": np.float32 + + Ego vehicle state, with the following attributes. + "ego_vehicle_state": dict({ + "angular_acceleration": + Angular acceleration vector. Requires `accelerometer` attribute + enabled in AgentInterface, else absent. shape=(3,). dtype=np.float32. + "angular_jerk": + Angular jerk vector. Requires `accelerometer` attribute enabled in + AgentInterface, else absent. shape=(3,). dtype=np.float32. + "angular_velocity": + Angular velocity vector. shape=(3,). dtype=np.float32). + "box": + Length, width, and height of the vehicle bounding box. shape=(3,). + dtype=np.float32. + "heading": + Vehicle heading in radians [-pi, pi]. dtype=np.float32. + "lane_index": + Vehicle's lane number. Rightmost lane has index 0 and increases + towards left. dtype=np.int8. + "linear_acceleration": + Vehicle acceleration in x, y, and z axes. Requires `accelerometer` + attribute enabled in AgentInterface, else absent. shape=(3,). + dtype=np.float32. + "linear_jerk": + Linear jerk vector. Requires `accelerometer` attribute enabled in + AgentInterface, else absent. shape=(3,). dtype=np.float32. + "linear_velocity": + Vehicle velocity in x, y, and z axes. shape=(3,). dtype=np.float32. + "pos": + Coordinate of the center of the vehicle bounding box's bottom plane. + shape=(3,). dtype=np.float64. + "speed": + Vehicle speed in m/s. dtype=np.float32. + "steering": + Angle of front wheels in radians [-pi, pi]. dtype=np.float32. + "yaw_rate": + Rotation speed around vertical axis in rad/s [0, 2pi]. + dtype=np.float32. + )} + + A dictionary of event markers. + "events": dict({ + "agents_alive_done": + 1 if `DoneCriteria.agents_alive` is triggered, else 0. + "collisions": + 1 if any collisions occurred with ego vehicle, else 0. + "not_moving": + 1 if `DoneCriteria.not_moving` is triggered, else 0. + "off_road": + 1 if ego vehicle drives off road, else 0. + "off_route": + 1 if ego vehicle drives off mission route, else 0. + "on_shoulder": + 1 if ego vehicle drives on road shoulder, else 0. + "reached_goal": + 1 if ego vehicle reaches its goal, else 0. + "reached_max_episode_steps": + 1 if maximum episode steps reached, else 0. + "wrong_way": + 1 if ego vehicle drives in the wrong traffic direction, else 0. + }) + + Drivable area grid map. Map is binary, with 255 if a cell contains a road, + else 0. dtype=np.uint8. + "drivable_area_grid_map": np.ndarray + + Lidar point cloud, with the following attributes. + "lidar_point_cloud": dict({ + "hit": + Binary array. 1 if an object is hit, else 0. shape(300,). + "point_cloud": + Coordinates of lidar point cloud. shape=(300,3). dtype=np.float64. + "ray_origin": + Ray origin coordinates. shape=(300,3). dtype=np.float64. + "ray_vector": + Ray vectors. shape=(300,3). dtype=np.float64. + }) + + Mission details for the ego agent. + "mission": dict({ + "goal_pos": + Achieve goal by reaching the end position. Defaults to np.array([0,0,0]) + for no mission. shape=(3,). dtype=np.float64. + }) + + Feature array of 10 nearest neighborhood vehicles. If nearest neighbor + vehicles are insufficient, default feature values are padded. + "neighborhood_vehicle_states": dict({ + "box": + Bounding box of neighbor vehicles. Defaults to np.array([0,0,0]) per + vehicle. shape=(10,3). dtype=np.float32. + "heading": + Heading of neighbor vehicles in radians [-pi, pi]. Defaults to + np.array([0]) per vehicle. shape=(10,). dtype=np.float32. + "lane_index": + Lane number of neighbor vehicles. Defaults to np.array([0]) per + vehicle. shape=(10,). dtype=np.int8. + "pos": + Coordinate of the center of neighbor vehicles' bounding box's bottom + plane. Defaults to np.array([0,0,0]) per vehicle. shape=(10,3). + dtype=np.float64. + "speed": + Speed of neighbor vehicles in m/s. Defaults to np.array([0]) per + vehicle. shape=(10,). dtype=np.float32. + }) + + Occupancy grid map. Map is binary, with 255 if a cell is occupied, else 0. + dtype=np.uint8. + "occupancy_grid_map": np.ndarray + + RGB image, from the top view, with ego vehicle at the center. + shape=(height, width, 3). dtype=np.uint8. + "top_down_rgb": np.ndarray + + Feature array of 20 waypoints ahead or in the mission route, from the + nearest 4 lanes. If lanes or waypoints ahead are insufficient, default + values are padded. + "waypoint_paths": dict({ + "heading": + Lane heading angle at a waypoint in radians [-pi, pi]. Defaults to + np.array([0]) per waypoint. shape=(4,20). dtype=np.float32. + "lane_index": + Lane number at a waypoint. Defaults to np.array([0]) per waypoint. + shape=(4,20). dtype=np.int8. + "lane_width": + Lane width at a waypoint in meters. Defaults to np.array([0]) per + waypoint. shape=(4,20). dtype=np.float32. + "pos": + Coordinate of a waypoint. Defaults to np.array([0,0,0]). + shape=(4,20,3). dtype=np.float64. + "speed_limit": + Lane speed limit at a waypoint in m/s. shape=(4,20). dtype=np.float32. + }) + + Feature array of 3 upcoming signals. If there aren't this many signals ahead, + default values are padded. + "signals": dict({ + "state": + The state of the traffic signal. + See smarts.core.signal_provider.SignalLightState for interpretation. + Defaults to np.array([0]) per signal. shape=(3,), dtype=np.int8. + "stop_point": + The stopping point for traffic controlled by the signal, i.e., the + point where actors should stop when the signal is in a stop state. + Defaults to np.array([0, 0]) per signal. shape=(3,2), dtype=np.float64. + "last_changed": + If known, the simulation time this signal last changed its state. + Defaults to np.array([0]) per signal. shape=(3,), dtype=np.float32. + }) - Occupancy grid map. Map is binary, with 255 if a cell is occupied, else 0. - dtype=np.uint8. - "occupancy_grid_map": np.ndarray - - RGB image, from the top view, with ego vehicle at the center. - shape=(height, width, 3). dtype=np.uint8. - "top_down_rgb": np.ndarray - - Feature array of 20 waypoints ahead or in the mission route, from the - nearest 4 lanes. If lanes or waypoints ahead are insufficient, default - values are padded. - "waypoint_paths": dict({ - "heading": - Lane heading angle at a waypoint in radians [-pi, pi]. Defaults to - np.array([0]) per waypoint. shape=(4,20). dtype=np.float32. - "lane_index": - Lane number at a waypoint. Defaults to np.array([0]) per waypoint. - shape=(4,20). dtype=np.int8. - "lane_width": - Lane width at a waypoint in meters. Defaults to np.array([0]) per - waypoint. shape=(4,20). dtype=np.float32. - "pos": - Coordinate of a waypoint. Defaults to np.array([0,0,0]). - shape=(4,20,3). dtype=np.float64. - "speed_limit": - Lane speed limit at a waypoint in m/s. shape=(4,20). dtype=np.float32. }) - Feature array of 3 upcoming signals. If there aren't this many signals ahead, - default values are padded. - "signals": dict({ - "state": - The state of the traffic signal. - See smarts.core.signal_provider.SignalLightState for interpretation. - Defaults to np.array([0]) per signal. shape=(3,), dtype=np.int8. - "stop_point": - The stopping point for traffic controlled by the signal, i.e., the - point where actors should stop when the signal is in a stop state. - Defaults to np.array([0, 0]) per signal. shape=(3,2), dtype=np.float64. - "last_changed": - If known, the simulation time this signal last changed its state. - Defaults to np.array([0]) per signal. shape=(3,), dtype=np.float32. - }) - }) """ def __init__( diff --git a/smarts/env/gymnasium/wrappers/metrics.py b/smarts/env/gymnasium/wrappers/metrics.py index d3d6424c5a..6463eafa83 100644 --- a/smarts/env/gymnasium/wrappers/metrics.py +++ b/smarts/env/gymnasium/wrappers/metrics.py @@ -214,7 +214,9 @@ def reset(self, **kwargs): def records(self) -> Dict[str, Dict[str, Record]]: """ Fine grained performance metric for each agent in each scenario. + .. code-block:: bash + $ env.records() $ { scen1: { @@ -225,6 +227,7 @@ def records(self) -> Dict[str, Dict[str, Record]]: agent1: Record(completion, costs, counts), }, } + Returns: Dict[str, Dict[str, Record]]: Performance record in a nested dictionary for each agent in each scenario.