Skip to content


Repository files navigation


Physics-based CartPole and Quadrotor Gym environments (using PyBullet) with symbolic a priori dynamics (using CasADi) for learning-based control, and model-free and model-based reinforcement learning (RL).

These environments include (and evaluate) symbolic safety constraints and implement input, parameter, and dynamics disturbances to test the robustness and generalizability of control approaches. [PDF]

problem illustration

         title={Safe Learning in Robotics: From Learning-Based Control to Safe Reinforcement Learning},
         author={Lukas Brunke and Melissa Greeff and Adam W. Hall and Zhaocong Yuan and Siqi Zhou and Jacopo Panerati and Angela P. Schoellig},
         journal = {Annual Review of Control, Robotics, and Autonomous Systems},
         url = {}}

To reproduce the results in the article, see branch ar.

      title={safe-control-gym: a Unified Benchmark Suite for Safe Learning-based Control and Reinforcement Learning},
      author={Zhaocong Yuan and Adam W. Hall and Siqi Zhou and Lukas Brunke and Melissa Greeff and Jacopo Panerati and Angela P. Schoellig},

To reproduce the results in the article, see branch submission.

Install on Ubuntu/macOS

Clone repo

git clone
cd safe-control-gym

(optional) Create a conda environment

Create and access a Python 3.10 environment using conda

conda create -n safe python=3.10
conda activate safe


Install the safe-control-gym repository

pip install --upgrade pip
pip install -e .


You may need to separately install gmp, a dependency of pycddlib:

conda install -c anaconda gmp


sudo apt-get install libgmp-dev


Overview of safe-control-gym's API:

block diagram



Getting Started

Familiarize with APIs and environments with the scripts in examples/

3D Quadrotor Lemniscate Trajectory Tracking with PID

cd ./examples/   # Navigate to the examples folder
python3 pid/ \
    --algo pid \
    --task quadrotor \
    --overrides \

systems trajectory

Cartpole Stabilization with LQR

cd ./examples/   # Navigate to the examples folder
python3 lqr/ \
    --algo lqr \
    --task cartpole \
    --overrides \
        ./lqr/config_overrides/cartpole/cartpole_stabilization.yaml \

2D Quadrotor Trajectory Tracking with PPO

cd ./examples/rl/   # Navigate to the RL examples folder
python3 \
    --algo ppo \
    --task quadrotor \
    --overrides \
        ./config_overrides/quadrotor_2D/quadrotor_2D_track.yaml \
        ./config_overrides/quadrotor_2D/ppo_quadrotor_2D.yaml \
    --kv_overrides \

Verbose API Example

cd ./examples/   # Navigate to the examples folder
python3 no_controller/ \
    --task cartpole \
    --overrides no_controller/verbose_api.yaml

List of Implemented Controllers

List of Implemented Safety Filters


We compare the sample efficiency of safe-control-gym with the original OpenAI Cartpole and PyBullet Gym's Inverted Pendulum, as well as gym-pybullet-drones. We choose the default physic simulation integration step of each project. We report performance results for open-loop, random action inputs. Note that the Bullet engine frequency reported for safe-control-gym is typically much finer grained for improved fidelity. safe-control-gym quadrotor environment is not as light-weight as gym-pybullet-drones but provides the same order of magnitude speed-up and several more safety features/symbolic models.

Environment GUI Control Freq. PyBullet Freq. Constraints & Disturbances^ Speed-Up^^
Gym cartpole True 50Hz N/A No 1.16x
InvPenPyBulletEnv False 60Hz 60Hz No 158.29x
cartpole True 50Hz 50Hz No 0.85x
cartpole False 50Hz 1000Hz No 24.73x
cartpole False 50Hz 1000Hz Yes 22.39x
gym-pyb-drones True 48Hz 240Hz No 2.43x
gym-pyb-drones False 50Hz 1000Hz No 21.50x
quadrotor True 60Hz 240Hz No 0.74x
quadrotor False 50Hz 1000Hz No 9.28x
quadrotor False 50Hz 1000Hz Yes 7.62x

^ Whether the environment includes a default set of constraints and disturbances

^^ Speed-up = Elapsed Simulation Time / Elapsed Wall Clock Time; on a 2.30GHz Quad-Core i7-1068NG7 with 32GB 3733MHz LPDDR4X; no GPU

Run Tests and Linting

Tests can be run locally by executing:

python3 -m pytest ./tests/  # Run all tests

Linting can be run locally with:

pre-commit install  # Install the pre-commit hooks
pre-commit autoupdate  # Auto-update the version of the hooks
pre-commit run --all  # Run the hooks on all files


Related Open-source Projects

University of Toronto's Dynamic Systems Lab / Vector Institute for Artificial Intelligence