Skip to content

Commit

Permalink
Release version 1.0.2 (#1819)
Browse files Browse the repository at this point in the history
See CHANGELOG.md

Co-authored-by: Qianyi Sun <[email protected]>
Co-authored-by: adai <[email protected]>
Co-authored-by: Saul Field <[email protected]>
  • Loading branch information
4 people authored Jan 28, 2023
1 parent e1c7fa7 commit 9281a8e
Show file tree
Hide file tree
Showing 38 changed files with 1,198 additions and 1,058 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ Copy and pasting the git commit messages is __NOT__ enough.
### Removed
### Security

## [1.0.2] 2023-01-27
### Added
- The `hiway-v1` environment can now be configured to provide an "unformatted" observation.
### Changed
- Scenario paths is no longer manually supplied to Envision server while setup. Scenario paths are automatically sent to Envision server from SMARTS during simulation startup phase.
- Updated "hiway-v1" with `gymnasium` action spaces using new `ActionsSpaceFormatter` utility.
### Fixed
- Fixed an issue where a sensor detach call when a bubble vehicle exits a bubble could cause a program crash.
- Fixed issue with "hiway-v0" where "agent_interfaces" was not populated.
- Add missing `distance_travelled` to the `hiway-v1` observations.

## [1.0.1] 2023-01-24
### Fixed
- Fixed issue where Driving SMARTS benchmark only did 2 evaluations per scenario instead of 50.
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (C) 2022. Huawei Technologies Co., Ltd. All rights reserved.
Copyright (C) 2023. Huawei Technologies Co., Ltd. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ sanity-test: build-sanity-scenarios
./smarts/core/tests/test_dynamics_backend.py::test_set_pose \
./smarts/core/tests/test_sensors.py::test_waypoints_sensor \
./smarts/core/tests/test_smarts.py::test_smarts_doesnt_leak_tasks_after_reset \
./examples/tests/test_examples.py::test_examples[hiway_v1] \
./examples/tests/test_examples.py::test_examples[laner] \
./smarts/env/tests/test_social_agent.py::test_social_agents

Expand Down
11 changes: 2 additions & 9 deletions cli/envision.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,6 @@ def envision_cli():

@envision_cli.command(name="start", help="Start an Envision server.")
@click.option("-p", "--port", help="Port Envision will run on.", default=8081)
@click.option(
"-s",
"--scenarios",
help="A list of directories where scenarios are stored.",
multiple=True,
default=["scenarios"],
)
@click.option(
"-c",
"--max_capacity",
Expand All @@ -49,8 +42,8 @@ def envision_cli():
default=500,
type=float,
)
def start_server(port, scenarios, max_capacity):
run(scenario_dirs=scenarios, max_capacity_mb=max_capacity, port=port)
def start_server(port, max_capacity):
run(max_capacity_mb=max_capacity, port=port)


envision_cli.add_command(start_server)
2 changes: 0 additions & 2 deletions cli/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ def run_experiment(envision, envision_port, script_path, script_args):
"scl",
"envision",
"start",
"-s",
"./scenarios",
"-p",
str(envision_port),
],
Expand Down
2 changes: 1 addition & 1 deletion docs/resources/containers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ SMARTS docker images are hosted at `dockerhub <https://hub.docker.com/u/huaweino
# E.g. docker run --rm -it -v $PWD:/src -p 8081:8081 huaweinoah/smarts:v0.5.1
# If visualization is needed, run Envision server in the background.
$ scl envision start -s ./scenarios -p 8081 &
$ scl envision start -p 8081 &
# Build the scenario.
# This step is required on the first time, and whenever the scenario is modified.
Expand Down
4 changes: 2 additions & 2 deletions docs/sim/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ Examples of common usage are as follows.

.. code-block:: bash
# Start envision and serve scenario assets out of ./scenarios
$ scl envision start --scenarios ./scenarios
# Start envision server
$ scl envision start
# Build all scenarios under given directories
$ scl scenario build-all ./scenarios
Expand Down
4 changes: 3 additions & 1 deletion envision/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ def default(self, obj):
return bool(obj)
elif isinstance(obj, np.ndarray):
return [self.default(x) for x in obj]
elif isinstance(obj, Path):
return str(obj)

return super().default(obj)

Expand Down Expand Up @@ -292,7 +294,7 @@ def run_socket(endpoint, wait_between_retries):

run_socket(endpoint, wait_between_retries)

def send(self, state: types.State):
def send(self, state: Union[types.State, types.Preamble]):
"""Send the given envision state to the remote as the most recent state."""
if not self._headless and self._process.is_alive():
self._state_queue.put(state)
Expand Down
79 changes: 42 additions & 37 deletions envision/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
from tornado.websocket import WebSocketClosedError

import smarts.core.models
from envision.types import State
from envision.web import dist as web_dist
from smarts.core.utils.file import path2hash

Expand All @@ -55,6 +54,9 @@
# Mapping of simulation ID to the Frames data store
FRAMES = {}

# Mapping of path to map geometry files
MAPS = {}


class AllowCORSMixin:
"""A mixin that adds CORS headers to the page."""
Expand Down Expand Up @@ -318,14 +320,24 @@ def on_close(self):
async def on_message(self, message):
"""Asynchronously receive messages from the Envision client."""
it = ijson.parse(message)
frame_time = None
# Find the first number value, which will be the frame time.
for prefix, event, value in it:
if prefix and event == "number":
frame_time = float(value)
break
assert isinstance(frame_time, float)
self._frames.append(Frame(timestamp=frame_time, data=message))
next(it) # Discard first entry: prefix="", event="start_array", value=None
prefix, event, value = next(it)
if prefix == "item" and event == "number":
# If the second event is a `number`, it is a payload message.
frame_time = float(value)
assert isinstance(frame_time, float)
self._frames.append(Frame(timestamp=frame_time, data=message))
elif prefix == "item" and event == "start_map":
# If the second event is a `start_map`, it is a preamble.
scenarios = [
value
for prefix, event, value in it
if prefix == "item.scenarios.item" and event == "string"
]
path_map = _index_map(scenarios)
MAPS.update(path_map)
else:
raise tornado.web.HTTPError(400, f"Bad request message.")


class StateWebSocket(tornado.websocket.WebSocketHandler):
Expand All @@ -346,9 +358,9 @@ def get_compression_options(self):
return {"compression_level": 6, "mem_level": 5}

async def open(self, simulation_id):
"""Open this socket to listen for webclient playback requests."""
"""Open this socket to listen for webclient playback requests."""
if simulation_id not in WEB_CLIENT_RUN_LOOPS:
raise tornado.web.HTTPError(404, f"Simuation `{simulation_id}` not found.")
raise tornado.web.HTTPError(404, f"Simulation `{simulation_id}` not found.")

frequency = 10
message_frame_volume = 100
Expand Down Expand Up @@ -422,20 +434,9 @@ async def serve_chunked(self, path: Path, chunk_size: int = 1024 * 1024):
class MapFileHandler(FileHandler):
"""This handler serves map geometry to the given endpoint."""

def initialize(self, scenario_dirs: Sequence):
"""Setup this handler. Finds and indexes all map geometry files in the given scenario
directories.
"""
path_map = {}
for dir_ in scenario_dirs:
path_map.update(
{
f"{path2hash(str(glb.parents[2].resolve()))}.glb": glb
for glb in Path(dir_).rglob("build/map/*.glb")
}
)

super().initialize(path_map)
def initialize(self):
"""Setup this handler."""
super().initialize(path_map=MAPS)


class SimulationListHandler(AllowCORSMixin, tornado.web.RequestHandler):
Expand Down Expand Up @@ -487,7 +488,7 @@ def get(self):
self.render(str(index_path))


def make_app(scenario_dirs: Sequence, max_capacity_mb: float, debug: bool):
def make_app(max_capacity_mb: float, debug: bool):
"""Create the envision web server application through composition of services."""

dist_path = Path(os.path.dirname(web_dist.__file__)).absolute()
Expand All @@ -505,7 +506,6 @@ def make_app(scenario_dirs: Sequence, max_capacity_mb: float, debug: bool):
(
r"/assets/maps/(.*)",
MapFileHandler,
dict(scenario_dirs=scenario_dirs),
),
(r"/assets/models/(.*)", ModelFileHandler),
(r"/(.*)", tornado.web.StaticFileHandler, dict(path=str(dist_path))),
Expand All @@ -514,20 +514,33 @@ def make_app(scenario_dirs: Sequence, max_capacity_mb: float, debug: bool):
)


def _index_map(scenario_dirs: Sequence[str]) -> Dict[str, Path]:
"""Finds and indexes all map geometry files in the given scenario directories."""
path_map = {}
for dir_ in scenario_dirs:
path_map.update(
{
f"{path2hash(str(glb.parents[2].resolve()))}.glb": glb
for glb in Path(dir_).rglob("build/map/map.glb")
}
)

return path_map


def on_shutdown():
"""Callback on shutdown of the envision server."""
logging.debug("Shutting down Envision")
tornado.ioloop.IOLoop.current().stop()


def run(
scenario_dirs: List[str],
max_capacity_mb: int = 500,
port: int = 8081,
debug: bool = False,
):
"""Create and run an envision web server."""
app = make_app(scenario_dirs, max_capacity_mb, debug=debug)
app = make_app(max_capacity_mb, debug=debug)
app.listen(port)
logging.debug("Envision listening on port=%s", port)

Expand All @@ -548,13 +561,6 @@ def main():
description="The Envision server broadcasts SMARTS state to Envision web "
"clients for visualization.",
)
parser.add_argument(
"--scenarios",
help="A list of directories where scenarios are stored.",
default=["./scenarios"],
type=str,
nargs="+",
)
parser.add_argument(
"--port",
help="Port Envision will run on.",
Expand All @@ -576,7 +582,6 @@ def main():
args = parser.parse_args()

run(
scenario_dirs=args.scenarios,
max_capacity_mb=args.max_capacity,
port=args.port,
debug=args.debug,
Expand Down
7 changes: 7 additions & 0 deletions envision/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ class State(NamedTuple):
frame_time: float


class Preamble(NamedTuple):
"""Information for startup and synchronisation between client and server."""

scenarios: Sequence[str]
"""Directories of simulated scenarios."""


def format_actor_id(actor_id: str, vehicle_id: str, is_multi: bool):
"""A conversion utility to ensure that an actor id conforms to envision's actor id standard.
Args:
Expand Down
9 changes: 8 additions & 1 deletion examples/control/laner.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ def main(scenarios, headless, num_episodes, max_episode_steps=None):

if not args.scenarios:
args.scenarios = [
str(Path(__file__).absolute().parents[2] / "scenarios" / "sumo" / "loop")
str(Path(__file__).absolute().parents[2] / "scenarios" / "sumo" / "loop"),
str(
Path(__file__).absolute().parents[2]
/ "scenarios"
/ "sumo"
/ "figure_eight"
),
]

build_scenarios(
Expand All @@ -81,4 +87,5 @@ def main(scenarios, headless, num_episodes, max_episode_steps=None):
scenarios=args.scenarios,
headless=args.headless,
num_episodes=args.episodes,
max_episode_steps=args.max_episode_steps,
)
6 changes: 6 additions & 0 deletions examples/tools/argument_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ def default_argument_parser(program: Optional[str] = None):
parser.add_argument(
"--headless", help="Run the simulation in headless mode.", action="store_true"
)
parser.add_argument(
"--max_episode_steps",
help="Maximum number of steps to run each episode for.",
type=int,
default=100,
)
parser.add_argument("--seed", type=int, default=42)
parser.add_argument(
"--sim-name",
Expand Down
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ cloudpickle==1.6.0
colorama==0.4.6
colorful==0.5.5
constantly==15.1.0
coverage==7.0.5
coverage==7.1.0
cycler==0.11.0
dm-tree==0.1.8
eclipse-sumo==1.15.0
Expand Down Expand Up @@ -83,7 +83,7 @@ pandas==1.3.5
Pillow==9.4.0
pkgutil_resolve_name==1.3.10
pluggy==1.0.0
prometheus-client==0.15.0
prometheus-client==0.16.0
protobuf==3.19.6
psutil==5.9.4
py==1.11.0
Expand All @@ -107,7 +107,7 @@ ray==1.0.1.post1
redis==3.4.1
requests==2.28.2
requests-oauthlib==1.3.1
rich==13.2.0
rich==13.3.0
rsa==4.9
Rtree==1.0.1
scipy==1.7.3
Expand Down Expand Up @@ -136,10 +136,10 @@ typing_extensions==4.4.0
urllib3==1.26.14
visdom==0.2.3
wcwidth==0.2.6
websocket-client==1.4.2
websocket-client==1.5.0
Werkzeug==2.2.2
wrapt==1.14.1
yarl==1.8.2
yattag==1.15.0
zipp==3.11.0
zipp==3.12.0
zope.interface==5.5.2
3 changes: 2 additions & 1 deletion scenarios/sumo/intersections/2lane/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@
scenario=Scenario(
traffic=traffic,
map_spec=MapSpec(
source=Path(__file__).parent,
source=Path(__file__).parent.absolute(),
shift_to_origin=True,
lanepoint_spacing=1.0,
),
),
output_dir=Path(__file__).parent,
Expand Down
3 changes: 2 additions & 1 deletion scenarios/sumo/intersections/4lane/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@
},
ego_missions=ego_missions,
map_spec=MapSpec(
source=Path(__file__).parent,
source=Path(__file__).parent.absolute(),
shift_to_origin=True,
lanepoint_spacing=1.0,
),
)

Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = smarts
version = 1.0.1
version = 1.0.2
url = https://github.com/huawei-noah/SMARTS
long_description = file:utils/setup/README.pypi.md
long_description_content_type = text/markdown
Expand Down
Loading

0 comments on commit 9281a8e

Please sign in to comment.