From 16bb9760784f8820a5e7ce20eec0d39e140884a3 Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 17:17:44 +0100 Subject: [PATCH 1/9] Update to support Gymnasium v1.0 --- .github/workflows/build.yml | 11 +-------- highway_env/__init__.py | 7 ++++-- setup.cfg | 10 ++++---- tests/envs/test_actions.py | 19 ++++++++------- tests/envs/test_env_preprocessors.py | 4 ++-- tests/envs/test_gym.py | 35 ++++++++++++++-------------- tests/envs/test_time.py | 2 +- tests/graphics/test_render.py | 11 ++++----- tests/vehicle/test_behavior.py | 3 +-- 9 files changed, 49 insertions(+), 53 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51745f86a..c073d75e0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v2 @@ -27,18 +27,9 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - sudo pip install pygame pip install -e .[deploy] - - name: Lint with flake8 - run: | - pip install flake8 - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test with pytest run: | pip install pytest pip install pytest-cov pytest --cov=./ --cov-report=xml - diff --git a/highway_env/__init__.py b/highway_env/__init__.py index 2493d128a..28fc83265 100644 --- a/highway_env/__init__.py +++ b/highway_env/__init__.py @@ -1,7 +1,7 @@ import os import sys -__version__ = "1.8.2" +__version__ = "1.9.0" try: from farama_notifications import notifications @@ -19,7 +19,7 @@ from highway_env.envs.common.abstract import MultiAgentWrapper -def register_highway_envs(): +def _register_highway_envs(): """Import the envs module so that envs register themselves.""" # exit_env.py @@ -108,3 +108,6 @@ def register_highway_envs(): # u_turn_env.py register(id="u-turn-v0", entry_point="highway_env.envs:UTurnEnv") + + +_register_highway_envs() diff --git a/setup.cfg b/setup.cfg index 6417bab87..fd2a62b7c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -8,9 +8,15 @@ long_description=file:README.md long_description_content_type=text/markdown url=https://github.com/eleurent/highway-env license=MIT +require-python= >= 3.8 classifiers= Development Status :: 5 - Production/Stable Programming Language :: Python :: 3 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 License :: OSI Approved :: MIT License @@ -38,9 +44,5 @@ exclude = docs scripts -[options.entry_points] -gymnasium.envs = - __root__ = highway_env.__init__:register_highway_envs - [aliases] test=pytest diff --git a/tests/envs/test_actions.py b/tests/envs/test_actions.py index 8cad31f2b..451b84550 100644 --- a/tests/envs/test_actions.py +++ b/tests/envs/test_actions.py @@ -3,18 +3,19 @@ import highway_env -highway_env.register_highway_envs() +gym.register_envs(highway_env) -action_configs = [ - {"type": "ContinuousAction"}, - {"type": "DiscreteAction"}, - {"type": "DiscreteMetaAction"}, -] - -@pytest.mark.parametrize("action_config", action_configs) +@pytest.mark.parametrize( + "action_config", + [ + {"type": "ContinuousAction"}, + {"type": "DiscreteAction"}, + {"type": "DiscreteMetaAction"}, + ], +) def test_action_type(action_config): - env = gym.make("highway-v0") + env = gym.make("highway-v0").unwrapped env.configure({"action": action_config}) env.reset() for _ in range(3): diff --git a/tests/envs/test_env_preprocessors.py b/tests/envs/test_env_preprocessors.py index 9db589196..4f78643fd 100644 --- a/tests/envs/test_env_preprocessors.py +++ b/tests/envs/test_env_preprocessors.py @@ -2,11 +2,11 @@ import highway_env -highway_env.register_highway_envs() +gym.register_envs(highway_env) def test_preprocessors(): - env = gym.make("highway-v0") + env = gym.make("highway-v0").unwrapped env = env.simplify() env = env.change_vehicles("highway_env.vehicle.behavior.IDMVehicle") env = env.set_preferred_lane(0) diff --git a/tests/envs/test_gym.py b/tests/envs/test_gym.py index 71cbb91e4..a478d8ed4 100644 --- a/tests/envs/test_gym.py +++ b/tests/envs/test_gym.py @@ -4,22 +4,23 @@ import highway_env from highway_env.envs.highway_env import HighwayEnv -highway_env.register_highway_envs() - -envs = [ - "highway-v0", - "merge-v0", - "roundabout-v0", - "intersection-v0", - "intersection-v1", - "parking-v0", - "two-way-v0", - "lane-keeping-v0", - "racetrack-v0", -] - - -@pytest.mark.parametrize("env_spec", envs) +gym.register_envs(highway_env) + + +@pytest.mark.parametrize( + "env_spec", + [ + "highway-v0", + "merge-v0", + "roundabout-v0", + "intersection-v0", + "intersection-v1", + "parking-v0", + "two-way-v0", + "lane-keeping-v0", + "racetrack-v0", + ], +) def test_env_step(env_spec): env = gym.make(env_spec) @@ -35,7 +36,7 @@ def test_env_step(env_spec): def test_env_reset_options(env_spec: str = "highway-v0"): - env = gym.make(env_spec) + env = gym.make(env_spec).unwrapped default_duration = HighwayEnv().default_config()["duration"] assert env.config["duration"] == default_duration diff --git a/tests/envs/test_time.py b/tests/envs/test_time.py index d2981890e..4de14aa75 100644 --- a/tests/envs/test_time.py +++ b/tests/envs/test_time.py @@ -4,7 +4,7 @@ import highway_env -highway_env.register_highway_envs() +gym.register_envs(highway_env) def wrapper(func, *args, **kwargs): diff --git a/tests/graphics/test_render.py b/tests/graphics/test_render.py index 8e8848a3c..f11062493 100644 --- a/tests/graphics/test_render.py +++ b/tests/graphics/test_render.py @@ -4,13 +4,12 @@ import highway_env -highway_env.register_highway_envs() -envs = ["highway-v0", "merge-v0"] +gym.register_envs(highway_env) -@pytest.mark.parametrize("env_spec", envs) +@pytest.mark.parametrize("env_spec", ["highway-v0", "merge-v0"]) def test_render(env_spec): - env = gym.make(env_spec, render_mode="rgb_array") + env = gym.make(env_spec, render_mode="rgb_array").unwrapped env.configure({"offscreen_rendering": True}) env.reset() img = env.render() @@ -23,9 +22,9 @@ def test_render(env_spec): ) # (H,W,C) -@pytest.mark.parametrize("env_spec", envs) +@pytest.mark.parametrize("env_spec", ["highway-v0", "merge-v0"]) def test_obs_grayscale(env_spec, stack_size=4): - env = gym.make(env_spec) + env = gym.make(env_spec).unwrapped env.configure( { "offscreen_rendering": True, diff --git a/tests/vehicle/test_behavior.py b/tests/vehicle/test_behavior.py index 4ae93f94b..e34e64b15 100644 --- a/tests/vehicle/test_behavior.py +++ b/tests/vehicle/test_behavior.py @@ -5,10 +5,9 @@ from highway_env.vehicle.objects import Obstacle FPS = 15 -vehicle_types = [IDMVehicle, LinearVehicle] -@pytest.mark.parametrize("vehicle_type", vehicle_types) +@pytest.mark.parametrize("vehicle_type", [IDMVehicle, LinearVehicle]) def test_stop_before_obstacle(vehicle_type): road = Road(RoadNetwork.straight_road_network(lanes=1)) vehicle = vehicle_type(road=road, position=[0, 0], speed=20, heading=0) From 5120cb60f37e210dd777595cb9e7d1d401233da8 Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 18:23:50 +0100 Subject: [PATCH 2/9] Add testing and fix issues --- highway_env/__init__.py | 70 +++++++++++++------------- highway_env/envs/__init__.py | 38 ++++++++++---- highway_env/envs/common/abstract.py | 11 ++-- highway_env/envs/common/observation.py | 2 +- highway_env/envs/exit_env.py | 14 +++--- highway_env/envs/intersection_env.py | 2 +- tests/envs/test_gym.py | 41 +++++++++++++++ 7 files changed, 123 insertions(+), 55 deletions(-) diff --git a/highway_env/__init__.py b/highway_env/__init__.py index 28fc83265..768f35943 100644 --- a/highway_env/__init__.py +++ b/highway_env/__init__.py @@ -1,6 +1,9 @@ import os import sys +import gymnasium as gym + + __version__ = "1.9.0" try: @@ -15,99 +18,98 @@ # Hide pygame support prompt os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "1" -from gymnasium.envs.registration import register -from highway_env.envs.common.abstract import MultiAgentWrapper - def _register_highway_envs(): """Import the envs module so that envs register themselves.""" + from highway_env.envs.common.abstract import MultiAgentWrapper + # exit_env.py - register( + gym.register( id="exit-v0", - entry_point="highway_env.envs:ExitEnv", + entry_point="highway_env.envs.exit_env:ExitEnv", ) # highway_env.py - register( + gym.register( id="highway-v0", - entry_point="highway_env.envs:HighwayEnv", + entry_point="highway_env.envs.highway_env:HighwayEnv", ) - register( + gym.register( id="highway-fast-v0", - entry_point="highway_env.envs:HighwayEnvFast", + entry_point="highway_env.envs.highway_env:HighwayEnvFast", ) # intersection_env.py - register( + gym.register( id="intersection-v0", - entry_point="highway_env.envs:IntersectionEnv", + entry_point="highway_env.envs.intersection_env:IntersectionEnv", ) - register( + gym.register( id="intersection-v1", - entry_point="highway_env.envs:ContinuousIntersectionEnv", + entry_point="highway_env.envs.intersection_env:ContinuousIntersectionEnv", ) - register( + gym.register( id="intersection-multi-agent-v0", - entry_point="highway_env.envs:MultiAgentIntersectionEnv", + entry_point="highway_env.envs.intersection_env:MultiAgentIntersectionEnv", ) - register( + gym.register( id="intersection-multi-agent-v1", - entry_point="highway_env.envs:MultiAgentIntersectionEnv", + entry_point="highway_env.envs.intersection_env:MultiAgentIntersectionEnv", additional_wrappers=(MultiAgentWrapper.wrapper_spec(),), ) # lane_keeping_env.py - register( + gym.register( id="lane-keeping-v0", - entry_point="highway_env.envs:LaneKeepingEnv", + entry_point="highway_env.envs.lane_keeping_env:LaneKeepingEnv", max_episode_steps=200, ) # merge_env.py - register( + gym.register( id="merge-v0", - entry_point="highway_env.envs:MergeEnv", + entry_point="highway_env.envs.merge_env:MergeEnv", ) # parking_env.py - register( + gym.register( id="parking-v0", - entry_point="highway_env.envs:ParkingEnv", + entry_point="highway_env.envs.parking_env:ParkingEnv", ) - register( + gym.register( id="parking-ActionRepeat-v0", - entry_point="highway_env.envs:ParkingEnvActionRepeat", + entry_point="highway_env.envs.parking_env:ParkingEnvActionRepeat", ) - register( - id="parking-parked-v0", entry_point="highway_env.envs:ParkingEnvParkedVehicles" + gym.register( + id="parking-parked-v0", entry_point="highway_env.envs.parking_env:ParkingEnvParkedVehicles" ) # racetrack_env.py - register( + gym.register( id="racetrack-v0", - entry_point="highway_env.envs:RacetrackEnv", + entry_point="highway_env.envs.racetrack_env:RacetrackEnv", ) # roundabout_env.py - register( + gym.register( id="roundabout-v0", - entry_point="highway_env.envs:RoundaboutEnv", + entry_point="highway_env.envs.roundabout_env:RoundaboutEnv", ) # two_way_env.py - register( - id="two-way-v0", entry_point="highway_env.envs:TwoWayEnv", max_episode_steps=15 + gym.register( + id="two-way-v0", entry_point="highway_env.envs.two_way_env:TwoWayEnv", max_episode_steps=15 ) # u_turn_env.py - register(id="u-turn-v0", entry_point="highway_env.envs:UTurnEnv") + gym.register(id="u-turn-v0", entry_point="highway_env.envs.u_turn_env:UTurnEnv") _register_highway_envs() diff --git a/highway_env/envs/__init__.py b/highway_env/envs/__init__.py index 6d6f5c9a7..0df23f8ed 100644 --- a/highway_env/envs/__init__.py +++ b/highway_env/envs/__init__.py @@ -1,10 +1,28 @@ -from highway_env.envs.highway_env import * -from highway_env.envs.merge_env import * -from highway_env.envs.parking_env import * -from highway_env.envs.roundabout_env import * -from highway_env.envs.two_way_env import * -from highway_env.envs.intersection_env import * -from highway_env.envs.lane_keeping_env import * -from highway_env.envs.u_turn_env import * -from highway_env.envs.exit_env import * -from highway_env.envs.racetrack_env import * +from highway_env.envs.exit_env import ExitEnv +from highway_env.envs.highway_env import HighwayEnv, HighwayEnvFast +from highway_env.envs.intersection_env import IntersectionEnv, ContinuousIntersectionEnv, MultiAgentIntersectionEnv +from highway_env.envs.lane_keeping_env import LaneKeepingEnv +from highway_env.envs.merge_env import MergeEnv +from highway_env.envs.parking_env import ParkingEnv, ParkingEnvActionRepeat, ParkingEnvParkedVehicles +from highway_env.envs.racetrack_env import RacetrackEnv +from highway_env.envs.roundabout_env import RoundaboutEnv +from highway_env.envs.two_way_env import TwoWayEnv +from highway_env.envs.u_turn_env import UTurnEnv + + +__all__ = [ + "ExitEnv", + "HighwayEnv", + "HighwayEnvFast", + "IntersectionEnv", + "ContinuousIntersectionEnv", + "MultiAgentIntersectionEnv", + "LaneKeepingEnv", + "MergeEnv", + "ParkingEnv", + "ParkingEnvActionRepeat", + "RacetrackEnv", + "RoundaboutEnv", + "TwoWayEnv", + "UTurnEnv", +] diff --git a/highway_env/envs/common/abstract.py b/highway_env/envs/common/abstract.py index 1c8b62e7a..59f316b1d 100644 --- a/highway_env/envs/common/abstract.py +++ b/highway_env/envs/common/abstract.py @@ -5,6 +5,7 @@ import gymnasium as gym import numpy as np from gymnasium import Wrapper +from gymnasium.utils import RecordConstructorArgs from gymnasium.wrappers import RecordVideo from highway_env import utils @@ -426,10 +427,14 @@ def __deepcopy__(self, memo): return result -class MultiAgentWrapper(Wrapper): +class MultiAgentWrapper(Wrapper, RecordConstructorArgs): + + def __init__(self, env): + Wrapper.__init__(self, env) + RecordConstructorArgs.__init__(self) + def step(self, action): - obs, reward, terminated, truncated, info = super().step(action) + obs, _, _, truncated, info = super().step(action) reward = info["agents_rewards"] terminated = info["agents_terminated"] - truncated = info["agents_truncated"] return obs, reward, terminated, truncated, info diff --git a/highway_env/envs/common/observation.py b/highway_env/envs/common/observation.py index 02f9de5a3..4806bf25d 100644 --- a/highway_env/envs/common/observation.py +++ b/highway_env/envs/common/observation.py @@ -674,7 +674,7 @@ def observe(self) -> np.ndarray: if self.order == "shuffled": self.env.np_random.shuffle(obs[1:]) # Flatten - return obs + return obs.astype(self.space().dtype) class LidarObservation(ObservationType): diff --git a/highway_env/envs/exit_env.py b/highway_env/envs/exit_env.py index f42067849..e9d40e66e 100644 --- a/highway_env/envs/exit_env.py +++ b/highway_env/envs/exit_env.py @@ -1,12 +1,14 @@ -from typing import Dict, Text, Tuple +from __future__ import annotations import numpy as np from highway_env import utils -from highway_env.envs import CircularLane, HighwayEnv, Vehicle +from highway_env.envs.highway_env import HighwayEnv from highway_env.envs.common.action import Action +from highway_env.road.lane import CircularLane from highway_env.road.road import Road, RoadNetwork from highway_env.vehicle.controller import ControlledVehicle +from highway_env.vehicle.kinematics import Vehicle class ExitEnv(HighwayEnv): @@ -44,10 +46,10 @@ def _reset(self) -> None: self._create_road() self._create_vehicles() - def step(self, action) -> Tuple[np.ndarray, float, bool, dict]: - obs, reward, terminal, info = super().step(action) + def step(self, action) -> tuple[np.ndarray, float, bool, bool, dict]: + obs, reward, terminated, truncated, info = super().step(action) info.update({"is_success": self._is_success()}) - return obs, reward, terminal, info + return obs, reward, terminated, truncated, info def _create_road( self, road_length=1000, exit_position=400, exit_length=100 @@ -154,7 +156,7 @@ def _reward(self, action: Action) -> float: reward = np.clip(reward, 0, 1) return reward - def _rewards(self, action: Action) -> Dict[Text, float]: + def _rewards(self, action: Action) -> dict[str, float]: lane_index = ( self.vehicle.target_lane_index if isinstance(self.vehicle, ControlledVehicle) diff --git a/highway_env/envs/intersection_env.py b/highway_env/envs/intersection_env.py index d55e32035..c290c3398 100644 --- a/highway_env/envs/intersection_env.py +++ b/highway_env/envs/intersection_env.py @@ -123,7 +123,7 @@ def _info(self, obs: np.ndarray, action: int) -> dict: info["agents_rewards"] = tuple( self._agent_reward(action, vehicle) for vehicle in self.controlled_vehicles ) - info["agents_dones"] = tuple( + info["agents_terminated"] = tuple( self._agent_is_terminal(vehicle) for vehicle in self.controlled_vehicles ) return info diff --git a/tests/envs/test_gym.py b/tests/envs/test_gym.py index a478d8ed4..9d43ad2b0 100644 --- a/tests/envs/test_gym.py +++ b/tests/envs/test_gym.py @@ -1,12 +1,53 @@ +import warnings + import gymnasium as gym import pytest +from gymnasium.utils.env_checker import check_env import highway_env +from highway_env.envs.common.abstract import MultiAgentWrapper from highway_env.envs.highway_env import HighwayEnv gym.register_envs(highway_env) +highway_env_ids = [ + env_id for env_id, env_spec in gym.registry.items() + if isinstance(env_spec.entry_point, str) and "highway_env" in env_spec.entry_point +] + + +CHECK_ENV_IGNORE_WARNINGS = [ + f"\x1b[33mWARN: {message}\x1b[0m" + for message in [ + "A Box observation space minimum value is -infinity. This is probably too low.", + "A Box observation space maximum value is infinity. This is probably too high.", + # "For Box action spaces, we recommend using a symmetric and normalized space (range=[-1, 1] or [0, 1]). See https://stable-baselines3.readthedocs.io/en/master/guide/rl_tips.html for more information.", + "The environment intersection-v0 is out of date. You should consider upgrading to version `v1`.", + "The environment intersection-multi-agent-v0 is out of date. You should consider upgrading to version `v1`." + ] +] + + +@pytest.mark.parametrize("env_id", highway_env_ids) +def test_highway_api(env_id): + """Check that all environments pass the environment checker with no warnings other than the expected.""" + with warnings.catch_warnings(record=True) as caught_warnings: + env = gym.make(env_id) + if isinstance(env, MultiAgentWrapper): + pytest.skip(f"Multi-Agent wrapper does not match api ({env}).") + + check_env(env, skip_render_check=True) + + env.close() + + for warning in caught_warnings: + if "is different from the unwrapped version" in warning.message.args[0]: + continue + if warning.message.args[0] not in CHECK_ENV_IGNORE_WARNINGS: + raise gym.error.Error(f"Unexpected warning: {warning.message}") + + @pytest.mark.parametrize( "env_spec", [ From 6a09d2d4beff6749c2f79b822b90202ad8d22be0 Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 18:27:18 +0100 Subject: [PATCH 3/9] pre-commit --- highway_env/__init__.py | 7 +++++-- highway_env/envs/__init__.py | 12 ++++++++++-- highway_env/envs/common/abstract.py | 1 - highway_env/envs/exit_env.py | 2 +- tests/envs/test_gym.py | 5 +++-- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/highway_env/__init__.py b/highway_env/__init__.py index 768f35943..ffcc0b53b 100644 --- a/highway_env/__init__.py +++ b/highway_env/__init__.py @@ -88,7 +88,8 @@ def _register_highway_envs(): ) gym.register( - id="parking-parked-v0", entry_point="highway_env.envs.parking_env:ParkingEnvParkedVehicles" + id="parking-parked-v0", + entry_point="highway_env.envs.parking_env:ParkingEnvParkedVehicles", ) # racetrack_env.py @@ -105,7 +106,9 @@ def _register_highway_envs(): # two_way_env.py gym.register( - id="two-way-v0", entry_point="highway_env.envs.two_way_env:TwoWayEnv", max_episode_steps=15 + id="two-way-v0", + entry_point="highway_env.envs.two_way_env:TwoWayEnv", + max_episode_steps=15, ) # u_turn_env.py diff --git a/highway_env/envs/__init__.py b/highway_env/envs/__init__.py index 0df23f8ed..552a8f5f8 100644 --- a/highway_env/envs/__init__.py +++ b/highway_env/envs/__init__.py @@ -1,9 +1,17 @@ from highway_env.envs.exit_env import ExitEnv from highway_env.envs.highway_env import HighwayEnv, HighwayEnvFast -from highway_env.envs.intersection_env import IntersectionEnv, ContinuousIntersectionEnv, MultiAgentIntersectionEnv +from highway_env.envs.intersection_env import ( + IntersectionEnv, + ContinuousIntersectionEnv, + MultiAgentIntersectionEnv, +) from highway_env.envs.lane_keeping_env import LaneKeepingEnv from highway_env.envs.merge_env import MergeEnv -from highway_env.envs.parking_env import ParkingEnv, ParkingEnvActionRepeat, ParkingEnvParkedVehicles +from highway_env.envs.parking_env import ( + ParkingEnv, + ParkingEnvActionRepeat, + ParkingEnvParkedVehicles, +) from highway_env.envs.racetrack_env import RacetrackEnv from highway_env.envs.roundabout_env import RoundaboutEnv from highway_env.envs.two_way_env import TwoWayEnv diff --git a/highway_env/envs/common/abstract.py b/highway_env/envs/common/abstract.py index 59f316b1d..454cf7345 100644 --- a/highway_env/envs/common/abstract.py +++ b/highway_env/envs/common/abstract.py @@ -428,7 +428,6 @@ def __deepcopy__(self, memo): class MultiAgentWrapper(Wrapper, RecordConstructorArgs): - def __init__(self, env): Wrapper.__init__(self, env) RecordConstructorArgs.__init__(self) diff --git a/highway_env/envs/exit_env.py b/highway_env/envs/exit_env.py index e9d40e66e..4f590c8b6 100644 --- a/highway_env/envs/exit_env.py +++ b/highway_env/envs/exit_env.py @@ -3,8 +3,8 @@ import numpy as np from highway_env import utils -from highway_env.envs.highway_env import HighwayEnv from highway_env.envs.common.action import Action +from highway_env.envs.highway_env import HighwayEnv from highway_env.road.lane import CircularLane from highway_env.road.road import Road, RoadNetwork from highway_env.vehicle.controller import ControlledVehicle diff --git a/tests/envs/test_gym.py b/tests/envs/test_gym.py index 9d43ad2b0..6246d8060 100644 --- a/tests/envs/test_gym.py +++ b/tests/envs/test_gym.py @@ -12,7 +12,8 @@ highway_env_ids = [ - env_id for env_id, env_spec in gym.registry.items() + env_id + for env_id, env_spec in gym.registry.items() if isinstance(env_spec.entry_point, str) and "highway_env" in env_spec.entry_point ] @@ -24,7 +25,7 @@ "A Box observation space maximum value is infinity. This is probably too high.", # "For Box action spaces, we recommend using a symmetric and normalized space (range=[-1, 1] or [0, 1]). See https://stable-baselines3.readthedocs.io/en/master/guide/rl_tips.html for more information.", "The environment intersection-v0 is out of date. You should consider upgrading to version `v1`.", - "The environment intersection-multi-agent-v0 is out of date. You should consider upgrading to version `v1`." + "The environment intersection-multi-agent-v0 is out of date. You should consider upgrading to version `v1`.", ] ] From 3ef5ad31c1065e6f3bd4f8c12108d55320ef8091 Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 18:37:00 +0100 Subject: [PATCH 4/9] Confirm in testing that Gymnasium v0.28 and v0.29.1 are pass the testing --- highway_env/__init__.py | 37 ++++++++++++++++++------------------- setup.cfg | 2 +- tests/envs/test_gym.py | 2 +- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/highway_env/__init__.py b/highway_env/__init__.py index ffcc0b53b..a1c1d9138 100644 --- a/highway_env/__init__.py +++ b/highway_env/__init__.py @@ -1,10 +1,9 @@ import os import sys -import gymnasium as gym +from gymnasium.envs.registration import register - -__version__ = "1.9.0" +__version__ = "2.0.0" try: from farama_notifications import notifications @@ -25,94 +24,94 @@ def _register_highway_envs(): from highway_env.envs.common.abstract import MultiAgentWrapper # exit_env.py - gym.register( + register( id="exit-v0", entry_point="highway_env.envs.exit_env:ExitEnv", ) # highway_env.py - gym.register( + register( id="highway-v0", entry_point="highway_env.envs.highway_env:HighwayEnv", ) - gym.register( + register( id="highway-fast-v0", entry_point="highway_env.envs.highway_env:HighwayEnvFast", ) # intersection_env.py - gym.register( + register( id="intersection-v0", entry_point="highway_env.envs.intersection_env:IntersectionEnv", ) - gym.register( + register( id="intersection-v1", entry_point="highway_env.envs.intersection_env:ContinuousIntersectionEnv", ) - gym.register( + register( id="intersection-multi-agent-v0", entry_point="highway_env.envs.intersection_env:MultiAgentIntersectionEnv", ) - gym.register( + register( id="intersection-multi-agent-v1", entry_point="highway_env.envs.intersection_env:MultiAgentIntersectionEnv", additional_wrappers=(MultiAgentWrapper.wrapper_spec(),), ) # lane_keeping_env.py - gym.register( + register( id="lane-keeping-v0", entry_point="highway_env.envs.lane_keeping_env:LaneKeepingEnv", max_episode_steps=200, ) # merge_env.py - gym.register( + register( id="merge-v0", entry_point="highway_env.envs.merge_env:MergeEnv", ) # parking_env.py - gym.register( + register( id="parking-v0", entry_point="highway_env.envs.parking_env:ParkingEnv", ) - gym.register( + register( id="parking-ActionRepeat-v0", entry_point="highway_env.envs.parking_env:ParkingEnvActionRepeat", ) - gym.register( + register( id="parking-parked-v0", entry_point="highway_env.envs.parking_env:ParkingEnvParkedVehicles", ) # racetrack_env.py - gym.register( + register( id="racetrack-v0", entry_point="highway_env.envs.racetrack_env:RacetrackEnv", ) # roundabout_env.py - gym.register( + register( id="roundabout-v0", entry_point="highway_env.envs.roundabout_env:RoundaboutEnv", ) # two_way_env.py - gym.register( + register( id="two-way-v0", entry_point="highway_env.envs.two_way_env:TwoWayEnv", max_episode_steps=15, ) # u_turn_env.py - gym.register(id="u-turn-v0", entry_point="highway_env.envs.u_turn_env:UTurnEnv") + register(id="u-turn-v0", entry_point="highway_env.envs.u_turn_env:UTurnEnv") _register_highway_envs() diff --git a/setup.cfg b/setup.cfg index fd2a62b7c..3c9a99bf5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -25,7 +25,7 @@ setup_requires= pytest-runner install_requires= farama-notifications - gymnasium>=0.27 + gymnasium>=0.28 numpy pygame>=2.0.2 matplotlib diff --git a/tests/envs/test_gym.py b/tests/envs/test_gym.py index 6246d8060..7514b6924 100644 --- a/tests/envs/test_gym.py +++ b/tests/envs/test_gym.py @@ -45,7 +45,7 @@ def test_highway_api(env_id): for warning in caught_warnings: if "is different from the unwrapped version" in warning.message.args[0]: continue - if warning.message.args[0] not in CHECK_ENV_IGNORE_WARNINGS: + elif warning.message.args[0] not in CHECK_ENV_IGNORE_WARNINGS: raise gym.error.Error(f"Unexpected warning: {warning.message}") From 838b1ae94dfc48e2744287eb46aa4bca8ddfc4d1 Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 18:42:33 +0100 Subject: [PATCH 5/9] Update CI to use Gymnasium v1.0 --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c073d75e0..47f3e2f9d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,6 +27,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip + pip install gymnasium>=1.0.0a2 pip install -e .[deploy] - name: Test with pytest run: | From 29a81b1da3b13472f9d39376ac4c1df504fbf77f Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 18:47:22 +0100 Subject: [PATCH 6/9] Update CI to use Gymnasium v1.0 --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 47f3e2f9d..0734c1133 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,9 +26,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip pip install gymnasium>=1.0.0a2 - pip install -e .[deploy] + pip install .[deploy] - name: Test with pytest run: | pip install pytest From 0d26a5cda3bce1dbbfc9adc911e6887028e58afc Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 18:51:25 +0100 Subject: [PATCH 7/9] Update CI to use Gymnasium v1.0 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 3c9a99bf5..1d4e4b325 100644 --- a/setup.cfg +++ b/setup.cfg @@ -25,7 +25,7 @@ setup_requires= pytest-runner install_requires= farama-notifications - gymnasium>=0.28 + gymnasium>=1.0.0a1 numpy pygame>=2.0.2 matplotlib From 7f9f4f6e7067634e23b2ff5e24d4b66122d14cf8 Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 22:57:21 +0100 Subject: [PATCH 8/9] Shift to using pyproject.toml rather than setup.cfg and setup.py --- .github/workflows/build.yml | 9 +- .github/workflows/release.yml | 2 +- .pre-commit-config.yaml | 1 - codecov.yml | 8 - highway_env/envs/__init__.py | 3 +- highway_env/envs/common/action.py | 6 +- highway_env/envs/common/observation.py | 8 +- highway_env/road/road.py | 2 +- pyproject.toml | 54 +++- scripts/highway_planning.ipynb | 194 +++++++------- scripts/intersection_social_dqn.ipynb | 352 ++++++++++++------------- scripts/sb3_highway_ppo_transformer.py | 4 +- setup.cfg | 48 ---- setup.py | 24 -- 14 files changed, 336 insertions(+), 379 deletions(-) delete mode 100644 codecov.yml delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0734c1133..9a7c288a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,11 +25,6 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Install dependencies - run: | - pip install gymnasium>=1.0.0a2 - pip install .[deploy] + run: pip install .[testing] - name: Test with pytest - run: | - pip install pytest - pip install pytest-cov - pytest --cov=./ --cov-report=xml + run: pytest --cov=./ --cov-report=xml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7a3123289..7f3721ccf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,4 +23,4 @@ jobs: uses: pypa/gh-action-pypi-publish@master with: user: __token__ - password: ${{ secrets.pypi_password }} \ No newline at end of file + password: ${{ secrets.pypi_password }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cc95bb980..789334631 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,6 @@ repos: hooks: - id: isort args: ["--profile", "black"] - exclude: "__init__.py" - repo: https://github.com/python/black rev: 23.3.0 hooks: diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index bfdc9877d..000000000 --- a/codecov.yml +++ /dev/null @@ -1,8 +0,0 @@ -coverage: - status: - project: - default: - informational: true - patch: - default: - informational: true diff --git a/highway_env/envs/__init__.py b/highway_env/envs/__init__.py index 552a8f5f8..e24fabbff 100644 --- a/highway_env/envs/__init__.py +++ b/highway_env/envs/__init__.py @@ -1,8 +1,8 @@ from highway_env.envs.exit_env import ExitEnv from highway_env.envs.highway_env import HighwayEnv, HighwayEnvFast from highway_env.envs.intersection_env import ( - IntersectionEnv, ContinuousIntersectionEnv, + IntersectionEnv, MultiAgentIntersectionEnv, ) from highway_env.envs.lane_keeping_env import LaneKeepingEnv @@ -17,7 +17,6 @@ from highway_env.envs.two_way_env import TwoWayEnv from highway_env.envs.u_turn_env import UTurnEnv - __all__ = [ "ExitEnv", "HighwayEnv", diff --git a/highway_env/envs/common/action.py b/highway_env/envs/common/action.py index e52d445bb..a82e00f1d 100644 --- a/highway_env/envs/common/action.py +++ b/highway_env/envs/common/action.py @@ -94,7 +94,7 @@ def __init__( lateral: bool = True, dynamical: bool = False, clip: bool = True, - **kwargs + **kwargs, ) -> None: """ Create a continuous action space. @@ -172,7 +172,7 @@ def __init__( dynamical: bool = False, clip: bool = True, actions_per_axis: int = 3, - **kwargs + **kwargs, ) -> None: super().__init__( env, @@ -216,7 +216,7 @@ def __init__( longitudinal: bool = True, lateral: bool = True, target_speeds: Optional[Vector] = None, - **kwargs + **kwargs, ) -> None: """ Create a discrete action space of meta-actions. diff --git a/highway_env/envs/common/observation.py b/highway_env/envs/common/observation.py index 4806bf25d..69f7a8547 100644 --- a/highway_env/envs/common/observation.py +++ b/highway_env/envs/common/observation.py @@ -70,7 +70,7 @@ def __init__( weights: List[float], scaling: Optional[float] = None, centering_position: Optional[List[float]] = None, - **kwargs + **kwargs, ) -> None: super().__init__(env) self.observation_shape = observation_shape @@ -168,7 +168,7 @@ def __init__( see_behind: bool = False, observe_intentions: bool = False, include_obstacles: bool = True, - **kwargs: dict + **kwargs: dict, ) -> None: """ :param env: The environment to observe @@ -293,7 +293,7 @@ def __init__( align_to_vehicle_axes: bool = False, clip: bool = True, as_image: bool = False, - **kwargs: dict + **kwargs: dict, ) -> None: """ :param env: The environment to observe @@ -687,7 +687,7 @@ def __init__( cells: int = 16, maximum_range: float = 60, normalize: bool = True, - **kwargs + **kwargs, ): super().__init__(env, **kwargs) self.cells = cells diff --git a/highway_env/road/road.py b/highway_env/road/road.py index 998eb017e..b88983abd 100644 --- a/highway_env/road/road.py +++ b/highway_env/road/road.py @@ -313,7 +313,7 @@ def straight_road_network( *nodes_str, StraightLane( origin, end, line_types=line_types, speed_limit=speed_limit - ) + ), ) return net diff --git a/pyproject.toml b/pyproject.toml index b5a3c468d..8a007fe90 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,50 @@ -[build-system] -requires = [ - "setuptools>=42", - "wheel" +[project] +name = "highway-env" +description = "An environment for simulated highway driving tasks." +readme = "README.md" +requires-python = ">= 3.8" +authors = [{ name = "Edouard Leurent", email = "eleurent@gmail.com" }] +license = { text = "MIT License" } +keywords = ["Reinforcement Learning", "car simulation", "RL", "AI"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "License :: OSI Approved :: MIT License", + 'Intended Audience :: Science/Research', + 'Topic :: Scientific/Engineering :: Artificial Intelligence', ] -build-backend = "setuptools.build_meta" \ No newline at end of file +dependencies = [ + "gymnasium >=0.28.0", + "farama-notifications >=0.0.1", + "numpy >=1.21.0", + "pygame >=2.0.2", + "matplotlib", + "pandas", + "scipy" +] +dynamic = ["version"] + +[project.optional-dependencies] +testing = [ + "pytest", + "pytest-cov" +] + +[project.urls] +Homepage = "https://farama.org" +Repository = "https://github.com/eleurent/highway-env" +Documentation = "https://highway-env.farama.org/" +"Bug Report" = "https://github.com/eleurent/highway-env/issues" + +[tool.setuptools] +include-package-data = true + +[tool.setuptools.packages.find] +include = ["highway_env", "highway_env.*"] + +[tool.setuptools.package-data] diff --git a/scripts/highway_planning.ipynb b/scripts/highway_planning.ipynb index 4fd9a87c0..b1722e1bb 100644 --- a/scripts/highway_planning.ipynb +++ b/scripts/highway_planning.ipynb @@ -1,100 +1,100 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "QKWvMXWMBEJA" - }, - "source": [ - "# Behavioural Planning for Autonomous Highway Driving\n", - "\n", - "We plan a trajectory using the _Optimistic Planning for Deterministic systems_ ([OPD](https://hal.inria.fr/hal-00830182)) algorithm.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "s-ghXis6A_md" - }, - "outputs": [], - "source": [ - "#@title Imports for env, agent, and visualisation.\n", - "# Environment\n", - "!pip install highway-env\n", - "import gymnasium as gym\n", - "import highway_env\n", - "\n", - "# Agent\n", - "!pip install git+https://github.com/eleurent/rl-agents#egg=rl-agents\n", - "from rl_agents.agents.common.factory import agent_factory\n", - "\n", - "# Visualisation\n", - "import sys\n", - "from tqdm.notebook import trange\n", - "!pip install moviepy -U\n", - "!pip install imageio_ffmpeg\n", - "!pip install pyvirtualdisplay\n", - "!apt-get install -y xvfb ffmpeg\n", - "!git clone https://github.com/Farama-Foundation/HighwayEnv.git\n", - "sys.path.insert(0, './highway-env/scripts/')\n", - "from utils import record_videos, show_videos\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "bgNDDWwqCj8l" - }, - "outputs": [], - "source": [ - "#@title Run an episode\n", - "\n", - "# Make environment\n", - "env = gym.make(\"highway-fast-v0\", render_mode=\"rgb_array\")\n", - "env = record_videos(env)\n", - "(obs, info), done = env.reset(), False\n", - "\n", - "# Make agent\n", - "agent_config = {\n", - " \"__class__\": \"\",\n", - " \"env_preprocessors\": [{\"method\":\"simplify\"}],\n", - " \"budget\": 50,\n", - " \"gamma\": 0.7,\n", - "}\n", - "agent = agent_factory(env, agent_config)\n", - "\n", - "# Run episode\n", - "for step in trange(env.unwrapped.config[\"duration\"], desc=\"Running...\"):\n", - " action = agent.act(obs)\n", - " obs, reward, done, truncated, info = env.step(action)\n", - " \n", - "env.close()\n", - "show_videos()" - ] - } - ], - "metadata": { - "colab": { - "name": "highway-planning.ipynb", - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "pycharm": { - "stem_cell": { - "cell_type": "raw", - "metadata": { - "collapsed": false - }, - "source": [] - } - } + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "QKWvMXWMBEJA" + }, + "source": [ + "# Behavioural Planning for Autonomous Highway Driving\n", + "\n", + "We plan a trajectory using the _Optimistic Planning for Deterministic systems_ ([OPD](https://hal.inria.fr/hal-00830182)) algorithm.\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "s-ghXis6A_md" + }, + "source": [ + "#@title Imports for env, agent, and visualisation.\n", + "# Environment\n", + "!pip install highway-env\n", + "import gymnasium as gym\n", + "import highway_env\n", + "\n", + "# Agent\n", + "!pip install git+https://github.com/eleurent/rl-agents#egg=rl-agents\n", + "from rl_agents.agents.common.factory import agent_factory\n", + "\n", + "# Visualisation\n", + "import sys\n", + "from tqdm.notebook import trange\n", + "!pip install moviepy -U\n", + "!pip install imageio_ffmpeg\n", + "!pip install pyvirtualdisplay\n", + "!apt-get install -y xvfb ffmpeg\n", + "!git clone https://github.com/Farama-Foundation/HighwayEnv.git\n", + "sys.path.insert(0, './highway-env/scripts/')\n", + "from utils import record_videos, show_videos\n" + ], + "outputs": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "bgNDDWwqCj8l" + }, + "source": [ + "#@title Run an episode\n", + "\n", + "# Make environment\n", + "env = gym.make(\"highway-fast-v0\", render_mode=\"rgb_array\")\n", + "env = record_videos(env)\n", + "(obs, info), done = env.reset(), False\n", + "\n", + "# Make agent\n", + "agent_config = {\n", + " \"__class__\": \"\",\n", + " \"env_preprocessors\": [{\"method\":\"simplify\"}],\n", + " \"budget\": 50,\n", + " \"gamma\": 0.7,\n", + "}\n", + "agent = agent_factory(env, agent_config)\n", + "\n", + "# Run episode\n", + "for step in trange(env.unwrapped.config[\"duration\"], desc=\"Running...\"):\n", + " action = agent.act(obs)\n", + " obs, reward, done, truncated, info = env.step(action)\n", + " \n", + "env.close()\n", + "show_videos()" + ], + "outputs": [] + } + ], + "metadata": { + "colab": { + "name": "highway-planning.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "pycharm": { + "stem_cell": { + "cell_type": "raw", + "metadata": { + "collapsed": false + }, + "source": [] + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 } diff --git a/scripts/intersection_social_dqn.ipynb b/scripts/intersection_social_dqn.ipynb index e29f32acb..bbfb2aaf2 100644 --- a/scripts/intersection_social_dqn.ipynb +++ b/scripts/intersection_social_dqn.ipynb @@ -1,179 +1,179 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "sepDWoBqdRMK" - }, - "source": [ - "# Training a DQN with social attention on `intersection-v0`\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Kx8X4s8krNWt" - }, - "outputs": [], - "source": [ - "#@title Import requirements\n", - "\n", - "# Environment\n", - "!pip install highway-env\n", - "import gymnasium as gym\n", - "\n", - "# Agent\n", - "!pip install git+https://github.com/eleurent/rl-agents#egg=rl-agents\n", - "\n", - "# Visualisation utils\n", - "!pip install moviepy\n", - "!pip install imageio_ffmpeg\n", - "import sys\n", - "%load_ext tensorboard\n", - "!pip install tensorboardx gym pyvirtualdisplay\n", - "!apt-get install -y xvfb ffmpeg\n", - "!git clone https://github.com/Farama-Foundation/HighwayEnv.git 2> /dev/null\n", - "sys.path.insert(0, '/content/HighwayEnv/scripts/')\n", - "from utils import show_videos" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "vvOEW00pdHrG" - }, - "source": [ - "## Training\n", - "\n", - "We use a policy architecture based on social attention, see [[Leurent and Mercat, 2019]](https://arxiv.org/abs/1911.12250).\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "QowKW3ix45ZW" - }, - "outputs": [], - "source": [ - "#@title Prepare environment, agent, and evaluation process.\n", - "\n", - "NUM_EPISODES = 3000 #@param {type: \"integer\"}\n", - "\n", - "from rl_agents.trainer.evaluation import Evaluation\n", - "from rl_agents.agents.common.factory import load_agent, load_environment\n", - "\n", - "# Get the environment and agent configurations from the rl-agents repository\n", - "!git clone https://github.com/eleurent/rl-agents.git 2> /dev/null\n", - "%cd /content/rl-agents/scripts/\n", - "env_config = 'configs/IntersectionEnv/env.json'\n", - "agent_config = 'configs/IntersectionEnv/agents/DQNAgent/ego_attention_2h.json'\n", - "\n", - "env = load_environment(env_config)\n", - "agent = load_agent(agent_config, env)\n", - "evaluation = Evaluation(env, agent, num_episodes=NUM_EPISODES, display_env=False, display_agent=False)\n", - "print(f\"Ready to train {agent} on {env}\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nqnGqW6jd1xN" - }, - "source": [ - "Run tensorboard locally to visualize training." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "q7QJY2wc4_1N" - }, - "outputs": [], - "source": [ - "%tensorboard --logdir \"{evaluation.directory}\"" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "BtK9dtfb0JMF" - }, - "source": [ - "Start training. This should take about an hour." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "sFVq1gFz42Eg" - }, - "outputs": [], - "source": [ - "evaluation.train()" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "-lNvWg42RWiw" - }, - "source": [ - "Progress can be visualised in the tensorboard cell above, which should update every 30s (or manually). You may need to click the *Fit domain to data* buttons below each graph." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "VKfvu5uhzCIU" - }, - "source": [ - "## Testing" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "gY0rpVYUtRpN" - }, - "outputs": [], - "source": [ - "#@title Run the learned policy for a few episodes.\n", - "env = load_environment(env_config)\n", - "env.config[\"offscreen_rendering\"] = True\n", - "agent = load_agent(agent_config, env)\n", - "evaluation = Evaluation(env, agent, num_episodes=20, training = False, recover = True)\n", - "evaluation.test()\n", - "show_videos(evaluation.run_directory)" - ] - } - ], - "metadata": { - "accelerator": "GPU", - "colab": { - "name": "SocialAttentionDQN", - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "pycharm": { - "stem_cell": { - "cell_type": "raw", - "metadata": { - "collapsed": false - }, - "source": [] - } - } + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "sepDWoBqdRMK" + }, + "source": [ + "# Training a DQN with social attention on `intersection-v0`\n", + "\n" + ] }, - "nbformat": 4, - "nbformat_minor": 0 + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Kx8X4s8krNWt" + }, + "source": [ + "#@title Import requirements\n", + "\n", + "# Environment\n", + "!pip install highway-env\n", + "import gymnasium as gym\n", + "\n", + "# Agent\n", + "!pip install git+https://github.com/eleurent/rl-agents#egg=rl-agents\n", + "\n", + "# Visualisation utils\n", + "!pip install moviepy\n", + "!pip install imageio_ffmpeg\n", + "import sys\n", + "%load_ext tensorboard\n", + "!pip install tensorboardx gym pyvirtualdisplay\n", + "!apt-get install -y xvfb ffmpeg\n", + "!git clone https://github.com/Farama-Foundation/HighwayEnv.git 2> /dev/null\n", + "sys.path.insert(0, '/content/HighwayEnv/scripts/')\n", + "from utils import show_videos" + ], + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "vvOEW00pdHrG" + }, + "source": [ + "## Training\n", + "\n", + "We use a policy architecture based on social attention, see [[Leurent and Mercat, 2019]](https://arxiv.org/abs/1911.12250).\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "QowKW3ix45ZW" + }, + "source": [ + "#@title Prepare environment, agent, and evaluation process.\n", + "\n", + "NUM_EPISODES = 3000 #@param {type: \"integer\"}\n", + "\n", + "from rl_agents.trainer.evaluation import Evaluation\n", + "from rl_agents.agents.common.factory import load_agent, load_environment\n", + "\n", + "# Get the environment and agent configurations from the rl-agents repository\n", + "!git clone https://github.com/eleurent/rl-agents.git 2> /dev/null\n", + "%cd /content/rl-agents/scripts/\n", + "env_config = 'configs/IntersectionEnv/env.json'\n", + "agent_config = 'configs/IntersectionEnv/agents/DQNAgent/ego_attention_2h.json'\n", + "\n", + "env = load_environment(env_config)\n", + "agent = load_agent(agent_config, env)\n", + "evaluation = Evaluation(env, agent, num_episodes=NUM_EPISODES, display_env=False, display_agent=False)\n", + "print(f\"Ready to train {agent} on {env}\")" + ], + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nqnGqW6jd1xN" + }, + "source": [ + "Run tensorboard locally to visualize training." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "q7QJY2wc4_1N" + }, + "source": [ + "%tensorboard --logdir \"{evaluation.directory}\"" + ], + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "BtK9dtfb0JMF" + }, + "source": [ + "Start training. This should take about an hour." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "sFVq1gFz42Eg" + }, + "source": [ + "evaluation.train()" + ], + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-lNvWg42RWiw" + }, + "source": [ + "Progress can be visualised in the tensorboard cell above, which should update every 30s (or manually). You may need to click the *Fit domain to data* buttons below each graph." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "VKfvu5uhzCIU" + }, + "source": [ + "## Testing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "gY0rpVYUtRpN" + }, + "source": [ + "#@title Run the learned policy for a few episodes.\n", + "env = load_environment(env_config)\n", + "env.config[\"offscreen_rendering\"] = True\n", + "agent = load_agent(agent_config, env)\n", + "evaluation = Evaluation(env, agent, num_episodes=20, training = False, recover = True)\n", + "evaluation.test()\n", + "show_videos(evaluation.run_directory)" + ], + "outputs": [] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "name": "SocialAttentionDQN", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "pycharm": { + "stem_cell": { + "cell_type": "raw", + "metadata": { + "collapsed": false + }, + "source": [] + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 } diff --git a/scripts/sb3_highway_ppo_transformer.py b/scripts/sb3_highway_ppo_transformer.py index aa234de3b..277374ad3 100644 --- a/scripts/sb3_highway_ppo_transformer.py +++ b/scripts/sb3_highway_ppo_transformer.py @@ -69,7 +69,7 @@ def __init__( out_size=None, activation="RELU", is_policy=False, - **kwargs + **kwargs, ): super().__init__(**kwargs) self.reshape = reshape @@ -170,7 +170,7 @@ def __init__( presence_feature_idx=0, embedding_layer_kwargs=None, attention_layer_kwargs=None, - **kwargs + **kwargs, ): super().__init__(**kwargs) self.out_size = out_size diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 1d4e4b325..000000000 --- a/setup.cfg +++ /dev/null @@ -1,48 +0,0 @@ -[metadata] -name=highway-env -version=attr: my_package.__version__ -author=Edouard Leurent -author_email=eleurent@gmail.com -description=An environment for simulated highway driving tasks. -long_description=file:README.md -long_description_content_type=text/markdown -url=https://github.com/eleurent/highway-env -license=MIT -require-python= >= 3.8 -classifiers= - Development Status :: 5 - Production/Stable - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - License :: OSI Approved :: MIT License - - -[options] -setup_requires= - pytest-runner -install_requires= - farama-notifications - gymnasium>=1.0.0a1 - numpy - pygame>=2.0.2 - matplotlib - pandas - scipy -packages=find: -tests_require= - pytest - -[options.extras_require] -deploy = pytest-runner; sphinx<1.7.3; sphinx_rtd_theme - -[options.packages.find] -exclude = - tests - docs - scripts - -[aliases] -test=pytest diff --git a/setup.py b/setup.py deleted file mode 100644 index e5e5d6041..000000000 --- a/setup.py +++ /dev/null @@ -1,24 +0,0 @@ -# Following PEP 517/518, this file should not not needed and replaced instead by the setup.cfg file and pyproject.toml. -# Unfortunately it is still required py the pip editable mode `pip install -e` -# See https://stackoverflow.com/a/60885212 - -import pathlib - -from setuptools import setup - -CWD = pathlib.Path(__file__).absolute().parent - - -def get_version(): - """Gets the gymnasium version.""" - path = CWD / "highway_env" / "__init__.py" - content = path.read_text() - - for line in content.splitlines(): - if line.startswith("__version__"): - return line.strip().split()[-1].strip().strip('"') - raise RuntimeError("bad version data in __init__.py") - - -if __name__ == "__main__": - setup(version=get_version()) From e9d823a3975c966ec61c21b962e745356b19fb3f Mon Sep 17 00:00:00 2001 From: pseudo-rnd-thoughts Date: Fri, 9 Aug 2024 23:07:08 +0100 Subject: [PATCH 9/9] Re-add setup.py and update gymnasium version to 1.0.0a2 --- pyproject.toml | 2 +- setup.py | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 setup.py diff --git a/pyproject.toml b/pyproject.toml index 8a007fe90..3818d26d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,7 @@ classifiers = [ 'Topic :: Scientific/Engineering :: Artificial Intelligence', ] dependencies = [ - "gymnasium >=0.28.0", + "gymnasium >=1.0.0a2", "farama-notifications >=0.0.1", "numpy >=1.21.0", "pygame >=2.0.2", diff --git a/setup.py b/setup.py new file mode 100644 index 000000000..7d8731597 --- /dev/null +++ b/setup.py @@ -0,0 +1,23 @@ +# Following PEP 517/518, this file should not not needed and replaced instead by the setup.cfg file and pyproject.toml. +# Unfortunately it is still required py the pip editable mode `pip install -e` +# See https://stackoverflow.com/a/60885212 + +import pathlib + +from setuptools import setup + +CWD = pathlib.Path(__file__).absolute().parent + + +def get_version(): + """Gets the gymnasium version.""" + path = CWD / "highway_env" / "__init__.py" + content = path.read_text() + + for line in content.splitlines(): + if line.startswith("__version__"): + return line.strip().split()[-1].strip().strip('"') + raise RuntimeError("bad version data in __init__.py") + + +setup(version=get_version())