Skip to content

Commit

Permalink
update basic usage,
Browse files Browse the repository at this point in the history
update random-track gen,
add files for usages,
remove unused reproduce.rst
  • Loading branch information
luigiberducci committed Mar 15, 2024
1 parent 97e6a24 commit 350bace
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 189 deletions.
Binary file added docs/src/assets/random_trackgen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions docs/src/usage/actions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _actions:

Actions
=====================

Work in progress on actions.
80 changes: 50 additions & 30 deletions docs/src/usage/basic_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,66 @@ Basic Usage Example

The environment can work out of the box without too much customization.

A gym env could be instantiated without any extra arguments. By default, it spawns two agents in the Vegas (IROS 2020) map. You can find the image of the map at ``gym/f110_gym/envs/maps/vegas.png``. At instantiation, the index of the ego agent in the list of agents is 0.
A gym env could be instantiated without any extra arguments using the ``gym.make()`` function.
By default, it spawns two agents in the Spielberg racetrack.

The agents can be reset by calling the ``reset()`` method using a numpy ndarray of size ``(num_agents, 2)``, where each row represents an agent, and the columns are the ``(x, y)`` coordinate of each agent.

The ``reset()`` and ``step()`` method returns:
- An *observation* dictionary
- A *step reward*, which in the current release is the physics timestep used.
- A *done* boolean indicator, flips to true when either a collision happens or the ego agent finishes 2 laps.
- An *info* dictionary. Empty in the current release.

The action taken by the ``step()`` function is a numpy ndarray of size ``(num_agents, 2)``, where each row represents an agent's action (indices corresponds to the list of agents), and the columns are control inputs (steering angle, velocity).
The simulation can be reset by calling the ``reset()`` method
and step forward in time by calling the ``step()`` method with a joint action for all agents.

A working example can be found in ``examples/waypoint_follow.py``.

The following pseudo code provides a skeleton for creating a simulation loop.

.. code:: python
Usage
-----

import gym
import numpy as np
from your_custom_policy import planner # the policy/motion planner that you create
.. code:: python
# instantiating the environment
racecar_env = gym.make('f110_gym:f110-v0')
obs, step_reward, done, info = racecar_env.reset(np.array([[0., 0., 0.], # pose of ego
[2., 0., 0.]])) # pose of 2nd agent
# instantiating your policy
planner = planner()
import gymnasium as gym
# simulation loop
lap_time = 0.
env = gym.make("f110_gym:f110-v0", render_mode="human")
obs, infos = env.reset()
# loops when env not done
while not done:
# get action based on the observation
actions = planner.plan(obs)
# stepping through the environment
# sample random action
actions = env.action_space.sample()
# step simulation
obs, step_reward, done, info = racecar_env.step(actions)
env.render()
Default configuration
---------------------

lap_time += step_reward
.. code:: python
For a more in-depth example that provides more customization to the environment, see :ref:`custom_usage`.
{
"seed": 12345,
"map": "Spielberg",
"params": {
"mu": 1.0489,
"C_Sf": 4.718,
"C_Sr": 5.4562,
"lf": 0.15875,
"lr": 0.17145,
"h": 0.074,
"m": 3.74,
"I": 0.04712,
"s_min": -0.4189,
"s_max": 0.4189,
"sv_min": -3.2,
"sv_max": 3.2,
"v_switch": 7.319,
"a_max": 9.51,
"v_min": -5.0,
"v_max": 20.0,
"width": 0.31,
"length": 0.58,
},
"num_agents": 2,
"timestep": 0.01,
"ego_idx": 0,
"integrator": "rk4",
"model": "st",
"control_input": ["speed", "steering_angle"],
"observation_config": {"type": None},
"reset_config": {"type": None},
}
159 changes: 17 additions & 142 deletions docs/src/usage/customized_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,157 +9,32 @@ The environment also provides options for customization.

Custom Map
------------
Work in progress on how to add a custom map.

The environment uses a convention that is similar to the ROS map convention. A map for the environment is created by two files: a ``yaml`` file containing the metadata of the map, and a single channel black and white image that represents the map, where black pixels are obstacles and white pixels are free space.
Random Track Generator
-----------------------

Map Metadata File (yaml)
~~~~~~~~~~~~~~~~~~~~~~~~~~
The script `examples/random_trackgen.py` allows to generate random tracks.

Only the ``resolution`` and the ``origin`` fields in the yaml files are used by the environment, and only the first two coordinates in the ``origin`` field are used. The unit of the resolution is *m/pixel*. The x and y (first two) numbers in the origin field are used to determine where the origin of the map frame is. Note that these two numbers follow the ROS convention. They represent the **bottom left** corner of the map image's coordinate in the world.
To use it, the following dependencies are required:

Map Image File
~~~~~~~~~~~~~~~~~~~~~~~~~~
::

A black and white, single channel image is used to represent free space and obstacles. For example, the Vegas map looks like this:
pip install cv2
pip install numpy
pip install shapely
pip install matplotlib

.. image:: ../gym/f110_gym/envs/maps/vegas.png
:width: 300
:align: center

Using a Custom Map
~~~~~~~~~~~~~~~~~~~~~~~~~~
The script can be run by specifying `seed`, number of maps to generate `n_maps` and the output directory `output_dir`.

The environment can be instantiated with arguments for a custom map. First, you can place your custom map files (.yaml and the image file) in the same directory, for example ``/your/path/to/map.yaml`` and ``/your/path/to/map.png``. Then you can create the environment with the absolute path to these files like this:
For example, to generate 3 random maps and store them in the directory `custom_maps`:

.. code:: python
::

env = gym.make('f110_gym:f110-v0',
map='/your/path/to/map',
map_ext='.png')
python examples/random_trackgen.py --seed 42 --n-maps 3 --outdir custom_maps

The ``map`` argument takes the absolute path to the map files **without** any extensions, and the ``map_ext`` argument takes the extension to the map image file. **Note** that it is assumed that the two files are in the **same directory**, and have the **same filename** (not including the extensions, for example map.png and map.yaml)

Random Track Generator (Beta)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A random track generator derived from the OpenAI CarRacing environment is also provided in ``gym/f110_gym/unittest/random_trackgen.py``. Note that it requires extra dependencies. ``OpenCV`` is required for image manipulation and IO operations, ``shapely`` and ``matplotlib`` are required for image generation. For OpenCV, you can follow the tutorial at https://docs.opencv.org/master/df/d65/tutorial_table_of_content_introduction.html for installation on different platforms. Then you can install ``shapely`` and ``matplotlib`` with: ``$ pip3 install shapely matplotlib``.

After you've installed the dependencies, you can run the track generator by:

.. code:: bash
$ python3 random_trackgen.py --seed 12345 --num_maps 1
where the ``--seed`` argument (int, default 123) is for reproducibility, and the ``--num_maps`` argument is for the number of maps you want to generate. By default, the script will create two directories in ``unittest``: ``unittest/maps`` and ``unittest/centerline``. The former contains all the map metadata and map image files, and the latter contains a csv file of the (x, y) coordinates of the points on the centerline of the track.

An example of a randomly generated track:

.. image:: ../examples/example_map.png
:width: 300
:align: center

Multiple Agents
-----------------

You can instantiate an environment with any number of agents (default is 2). For example:

.. code:: python
env = gym.make('f110_gym:f110-v0',
num_agents=3)
This will create an environment with 3 agents. Note that your call to the ``reset()`` and ``step()`` function will have to change accordingly:

.. code:: python
_, _, _, _ = env.reset(np.array([[ego_x, ego_y],
[opp1_x, opp1_y],
[opp2_x, opp2_y]]))
_, _, _, _ = env.step(np.array([[ego_steer, ego_speed],
[opp1_steer, opp1_speed],
[opp2_steer, opp2_speed]]))
Note that performance of the environment will start to degrade as more and more agents are added.

Changing Parameters in Vehicle Dynamics
------------------------------------------

The vehicle dynamic model used in the environment is the Single-Track Model from https://gitlab.lrz.de/tum-cps/commonroad-vehicle-models/.

You can change the default paramters (identified on concrete floor with the default configuration F1TENTH vehicle) used in the environment in two ways.

1. You could instantiate the environment with a parameter dictionary:

.. code:: python
params_dict = {'mu': 1.0489,
'C_Sf': 4.718,
'C_Sr': 5.4562,
'lf': 0.15875,
'lr': 0.17145,
'h': 0.074,
'm': 3.74,
'I': 0.04712,
's_min': -0.4189,
's_max': 0.4189,
'sv_min': -3.2,
'sv_max': 3.2,
'v_switch':7.319,
'a_max': 9.51,
'v_min':-5.0,
'v_max': 20.0,
'width': 0.31,
'length': 0.58}
env = gym.make('f110_gym:f110-v0', params=params_dict)
2. Or you could update the parameters of a specific vehicle in the list of vehicles (or all vehicles):

.. code:: python
# env with default params and 2 agents
env = gym.make('f110_gym:f110-v0')
# new params
params_dict = {'mu': 1.0489,
'C_Sf': 4.718,
'C_Sr': 5.4562,
'lf': 0.15875,
'lr': 0.17145,
'h': 0.074,
'm': 3.74,
'I': 0.04712,
's_min': -0.4189,
's_max': 0.4189,
'sv_min': -3.2,
'sv_max': 3.2,
'v_switch':7.319,
'a_max': 9.51,
'v_min':-5.0,
'v_max': 20.0,
'width': 0.31,
'length': 0.58}
# update params of only the 2nd vehicles
env.update_params(params_dict, index=1)
# update params of all vehicles
env.update_params(params_dict)
The dynamic model's physical parameters are:
- **mu**: surface friction coefficient *[-]*
- **C_Sf**: Cornering stiffness coefficient, front *[1/rad]*
- **C_Sr**: Cornering stiffness coefficient, rear *[1/rad]*
- **lf**: Distance from center of gravity to front axle *[m]*
- **lr**: Distance from center of gravity to rear axle *[m]*
- **h**: Height of center of gravity *[m]*
- **m**: Total mass of the vehicle *[kg]*
- **I**: Moment of inertial of the entire vehicle about the z axis *[kgm^2]*
- **s_min**: Minimum steering angle constraint *[rad]*
- **s_max**: Maximum steering angle constraint *[rad]*
- **sv_min**: Minimum steering velocity constraint *[rad/s]*
- **sv_max**: Maximum steering velocity constraint *[rad/s]*
- **v_switch**: Switching velocity (velocity at which the acceleration is no longer able to create wheel spin) *[m/s]*
- **a_max**: Maximum longitudinal acceleration *[m/s^2]*
- **v_min**: Minimum longitudinal velocity *[m/s]*
- **v_max**: Maximum longitudinal velocity *[m/s]*
- **width**: width of the vehicle *[m]*
- **length**: length of the vehicle *[m]*
.. image:: ../../../../src/assets/random_trackgen.png
:width: 800
:align: center
6 changes: 6 additions & 0 deletions docs/src/usage/dynamics.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
_dynamics:

Dynamics
=====================

Work in progress.
6 changes: 5 additions & 1 deletion docs/src/usage/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@ Usage
:maxdepth: 2

basic_usage
actions
observations
rewards
dynamics
customized_usage
reproduce
rendering
6 changes: 6 additions & 0 deletions docs/src/usage/observations.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _observations:

Observations
=====================

Work in progress.
6 changes: 6 additions & 0 deletions docs/src/usage/rendering.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _rendering:

Rendering
=====================

Work in progress.
6 changes: 0 additions & 6 deletions docs/src/usage/reproduce.rst

This file was deleted.

6 changes: 6 additions & 0 deletions docs/src/usage/rewards.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _rewards:

Rewards
=====================

Work in progress.
22 changes: 12 additions & 10 deletions examples/random_trackgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,17 @@ def main(args):
outdir.mkdir(parents=True, exist_ok=True)

for i in range(n_maps):
try:
print(f"[info] creating track {i}")
track, track_int, track_ext = create_track()
convert_track(track, track_int, track_ext, i, outdir)
print(f"[info] saved track {i} in {outdir}/")
except Exception as _: # noqa: F841
print("[error] failed to create track. Retrying...")
continue
print()
while True:
try:
print(f"[info] creating track {i}")
track, track_int, track_ext = create_track()
convert_track(track, track_int, track_ext, i, outdir)
print(f"[info] saved track {i} in {outdir}/")
break
except Exception as _: # noqa: F841
print("[error] failed to create track. Retrying...")
continue
print()


def create_track():
Expand Down Expand Up @@ -250,7 +252,7 @@ def convert_track(track, track_int, track_ext, track_id, outdir):
"--seed", type=int, default=123, help="The seed for the numpy rng"
)
parser.add_argument(
"--n_maps", type=int, default=3, help="Number of maps to create"
"--n-maps", type=int, default=3, help="Number of maps to create"
)
parser.add_argument(
"--outdir", type=pathlib.Path, default="./maps", help="Out directory"
Expand Down

0 comments on commit 350bace

Please sign in to comment.