(Tested on Ubuntu20, MacOS at 2024-06-25) Clone the repo including submodules
git clone --recurse-submodules git@github.com:F1Tenth-INI/f1tenth_development_gym.git
cd f1tenth_development_gym/
I highly recommend using Conda for virtual environments. First create a conda environment.
conda create -n f1t python=3.9 # Working environment with Apple Silicon
conda activate f1t
Then install the gym inside the environment. Don't omit the trailing / on gym.
There is a chance that yout setuptools is too new for the gym version. If that is the case, you need to downgrade it.
python -m pip install "pip<24.1"
pip install setuptools==65.5.0 "wheel<0.40.0"
And now you can install the gym environment.
pip install --user -e gym/
Check if the submodules are present. The folder SI_Toolkit and Control_Toolkit should not be empty. If they are empty, run:
git submodule update --init --recursive
And then install the SI_Toolkit
python -m pip install --user -e ./SI_Toolkit
Run the simulation
python run.py
If you are running from terminal, please run all python scripts from the project's root folder. You might want to export the Python Path env variable:
export PYTHONPATH=./
Have a look at the Settings file: Settings.py This file gives you an idea of what can be adjusted at the GYM.
Let's go through the most important ones:
Have a look at run_simulations.py. This file represents the world. You can add one or multiple instances of car_system classes to the drivers array:
drivers = [planner1,planner2]
Have a look at car_system.py. This is a representation of the physical car. A car system fetches information and sensor data from the environment and will deliver it to the Planner. The car system consists of everything that all cars (independent of the planner/controller) have in common. Features of the Car System are the following:
Note that every feature of the Car System is also implemented on the Physical car in the f1tenth_gym_bridge.
The next layer of abstraction is the planner. The planner is still system specific (resp. designed for the car/car environment) but it handles features that not all controllers have in common.
process_observation function that receives lidar data and returns a control command
(Optional) A controller
Everything else the controller needs ( fe. a cost function )
A controller is system agnostic. That means it does not know (and care) about which system is controlled. It will only try to fullfil the objective delivere by the planner. That's why Control Toolkit is a sub repository. In fact the same code will run to control the Car and also the CartPole f.e.. It you think of a PID controller, it only gets an objective (error) and will try to reach it (error -> 0) but has no information about the system.
We have implemented different car models. But within the environment_gym, we basically stick to the following definition for a car state. It is an array of 9 variables:
Check the TUM CommonRoad Vehiclemodels for further information. Attention: The state variable indices are not the same in our system, we sort the alphabetically!
Please access the state variables only by name, for example: pos_x = s[POSE_X_IDX] You can import the index names from utilities/state_utilities.py
A waypoint is defined as an array of the following properties:
Every waypoint describes a desired position, desired velocity and other features, that the car has to follow. The waypoints are saved in the map folder under map_name_wp.csv Please access the waypoint properties only by name, for example: pos_x = wp[WP_S_IDX]
You can import the index names from utilities/waypoint_utils.py
For a new map, you can either calculate the waypoints with "minimum curvature optimization" (fast-driving) or with "draw by hand" (uncompliated)
All maps are loceted at utilities/maps/ A map called [ExampleMap] consist of a folder at utilities/maps/ExampleMap/` containing the following files:
ExampleMap.yaml
- Contains meta information about the resolution etc.ExampleMap.pgm
- Original image of the map (from SLAM on physical car)ExampleMap.png
- Original image in .png format (used by localiyation stack on phcsical car, should not be changed!)ExampleMap_wp_min_curve.png
- Map that's used to calculate minimum curvature waypoints (can be editted to contain a closed contour)ExampleMap_wp_hand.png
- Is used to create waypoints by hand(only present after waypoint generation)
ExampleMap_wp.yaml
- List of waypoints in classic directionExampleMap_wp_reverse.yaml
- List of waypoints in reverfse directiondata/
- Containing image processing and other data of the mapPlease work on your own branches and do pull requests to the main branch. If possible, seperate your code into your own folders.
Every driver class must have the function process_observation, with the following arguments:
def process_observation(self, ranges=None, ego_odom=None):
"""
gives actuation given observation
@ranges: an array of 1080 distances (ranges) detected by the LiDAR scanner. As the LiDAR scanner takes readings for the full 360°, the angle between each range is 2π/1080 (in radians).
@ ego_odom: A dict with following indices:
{
'pose_x': float,
'pose_y': float,
'pose_theta': float,
'linear_vel_x': float,
'linear_vel_y': float,
'angular_vel_z': float,
}
"""
desired_speed = 0
desired_angle = 0
return desired_speed, desired_angle
The function should return the desired speed and the desired angle
Control Toolkit is a system agnostic sub-repository, which provides the cores of the most important controllers. It is used on multiple projects (f.e. CartPole).
In the gym we have implemented controllers from the Control Toolkit. Every Application Specific File (which are specifically meant for controlling the car in the GYM environment) are in the folder Control_Toolkit_ASF
The Control Toolkit's config files are called
Have a look at them and see how the controllers can be tuned.
The MPC controller is implemented in the GYM with two optimizers:
The cost functions are in Control_Toolkit_ASF/CostFunctions. The cost function properties are in cost function template: f1t_cost_function.py, lines 63-72.
Control Toolkit is a system agnostic sub-repository, which provides the cores for neural system identification and brunton plotting. Like Control Toolkit, is used on multiple projects (f.e. CartPole). Every Application Specific File related to the SI Toolkit is in the folder SI_Toolkit_ASF.
On the controller side, these structure are at SI_Toolkit_ASF/car_model.py, lines 113-190.
Collect experiment recordings with a controller of choise (fe. MPC - MPPI).
NOISE_LEVEL_TRANSLATIONAL_CONTROL = 0.5 NOISE_LEVEL_ANGULAR_CONTROL = 0.5
Tune the controller for robustness ( it needs to be able to complete laps reliably )
Delete all old experiment recordings in ExperimentRecordings/
Set EXPERIMENT_LENGTH such that the car completes more than 2 laps
set NUMBER_OF_EXPERIMENTS >= 10 depending on how much data you want to have
Run experiments
Create the following folders:
Distribute the experiment's CSV files into these 3 folders ( each 80%, 10%, 10% of the data points)
in config_training.yml set path_to_experiment to [Controller Name]
Create normalization file:
python SI_Toolkit_ASF/run/Create_normalization_file.py
python SI_Toolkit_ASF/run/Train_Network.py
CONTROLLER = 'neural'
...
PATH_TO_MODELS = 'SI_Toolkit_ASF/Experiments/[Controller Name]/Models/'
NET_NAME = '[Model Name]'
...
NOISE_LEVEL_TRANSLATIONAL_CONTROL = 0.0
NOISE_LEVEL_ANGULAR_CONTROL = 0.0
...
CONTROL_AVERAGE_WINDOW = (1, 1)
...
Check config_testting.yml:
python SI_Toolkit_ASF/run/Run_Brunton_Test.py
To generate data, the best and fastest way is to use the data generator:
DataGen/config_data_gen.yml
python3 -m SI_Toolkit_ASF.run.run_data_generator_for_ML_Pipeline
The provided settings are the ones that were found to work best for a time step of 0.04s. For other time steps, they might need to be adjusted. This creates a new folder in SI_Toolkit_ASF/Experiments
with the data split into a train, test and validation folder.
To remove outliers and add a derivative column, we need to preprocess the data.
SI_Toolkit_ASF/run/preprocess_data.py
)python3 -m SI_Toolkit_ASF.run.preprocess_data
To only add derivative columns to the dataset:
python3 -m SI_Toolkit_ASF.run.Add_derivative_to_csv
SI_Toolkit_ASF/run/Add_derivative_to_csv.py
To train, we first need to rename the columns of our training data. Use your IDE to rename all instances of [translational]/[angular]_control_applied
in your dataset to [translational]/[angular]_control
.
Then we need to create the normalization file:
SI_Toolkit_ASF/config_training.yml
and specify the desired path_to_experiments
python3 -m SI_Toolkit_ASF.run
Then set the desired model in config_training.yml
. Settings that worked well are:
NET_NAME: 'Dense-128H1-128H2'
, 20 epochs, batch size of 32, wash out length 0, post wash out length 1, shift_labels 1 (important!).NET_NAME: 'Dense-128H1-128H2'
, 20 epochs, batch size of 32, wash out length 10, post wash out length 1, shift_labels 1.Then run the training:
SI_Toolkit_ASF/config_training.yml
python3 -m SI_Toolkit_ASF.run.Train_Network
To check that your predictor works, run the Brunton test using:
SI_Toolkit_ASF/config_testing.py
python run/create_min_curve_waypoints.py
The waypoints (and additional data) will be saved in the map folder.
This is the repository of the F1TENTH Gym environment.
This project is still under heavy developement.
You can find the documentation of the environment here.
ImportError: Can't find framework /System/Library/Frameworks/OpenGL.framework.
You can fix the error by installing a newer version of pyglet:
$ pip3 install pyglet==1.5.11
And you might see an error similar to
gym 0.17.3 requires pyglet<=1.5.0,>=1.4.0, but you'll have pyglet 1.5.11 which is incompatible.
which could be ignored. The environment should still work without error.
If you find this Gym environment useful, please consider citing:
@inproceedings{okelly2020f1tenth,
title={F1TENTH: An Open-source Evaluation Environment for Continuous Control and Reinforcement Learning},
author={O’Kelly, Matthew and Zheng, Hongrui and Karthik, Dhruv and Mangharam, Rahul},
booktitle={NeurIPS 2019 Competition and Demonstration Track},
pages={77--89},
year={2020},
organization={PMLR}
}