Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
ae6fedd
Merge remote-tracking branch 'origin/main' into dev
N0OBSTUDENT Jan 22, 2026
674f981
Protptype for multi drone racing using a Barrier object to sync start
N0OBSTUDENT Jan 27, 2026
21d7b1e
Fixed dimension problem when trying to intialize a controller with mu…
N0OBSTUDENT Jan 27, 2026
2d59f68
Vibe coded 1st version of multi drone racing using Zenoh
N0OBSTUDENT Mar 2, 2026
74e8d27
Added real race client
N0OBSTUDENT Mar 3, 2026
5079284
Fixed all bugs to make it run
N0OBSTUDENT Mar 3, 2026
5764cad
Added latency calibration
N0OBSTUDENT Mar 3, 2026
f12bbf1
Make unknown observation nan instead of zero
N0OBSTUDENT Mar 3, 2026
6f4c80d
Merge branch 'zenoh_multidrone' of https://github.com/N0OBSTUDENT/lsy…
N0OBSTUDENT Mar 3, 2026
1e373f6
Switched to time.time() from perf_counter()
N0OBSTUDENT Mar 3, 2026
756c5aa
Made it work
N0OBSTUDENT Mar 17, 2026
b87f41a
Added rank to other controllers
N0OBSTUDENT Mar 17, 2026
df93e96
Made a demo for different controller, different frequency in differen…
N0OBSTUDENT Mar 17, 2026
d7f6654
Clean up codes
N0OBSTUDENT Mar 17, 2026
22f5aa3
Removed raw-zenoh and takeoff barrier related code
N0OBSTUDENT Mar 27, 2026
7d30658
Edit host, client and comm node code to make it look neater
N0OBSTUDENT Mar 27, 2026
4355b63
Resolve naming issues
N0OBSTUDENT Mar 27, 2026
c869263
Split the multi and single controllers
N0OBSTUDENT Mar 27, 2026
b4b790e
Pass ruff checks
N0OBSTUDENT Mar 27, 2026
03222bc
Added ROS2 package
N0OBSTUDENT Mar 27, 2026
36b925b
Removed take-off barrier configuration
N0OBSTUDENT Mar 27, 2026
8e310d7
Switch power cycle timeout to 2 second
N0OBSTUDENT Mar 28, 2026
9fe98bd
Restored real_race_env to latest commit of branch dev
N0OBSTUDENT Mar 28, 2026
ddcc4e4
Restore the controllers
N0OBSTUDENT Mar 28, 2026
4f2ae07
Close ros connector upon closing the client
N0OBSTUDENT Mar 28, 2026
029b2c5
Restore utils.py
N0OBSTUDENT Mar 28, 2026
f16ba56
Fixed the default config name in deploy_client.py
N0OBSTUDENT Mar 28, 2026
c3ba63c
Merge branch 'dev' into zenoh_ros2_multidrone
N0OBSTUDENT Mar 28, 2026
3c30975
-Resolve the pixi lock file again to make it compatible with later co…
N0OBSTUDENT Mar 28, 2026
39d8c46
Added gate pose update to clients
N0OBSTUDENT Mar 28, 2026
e4757da
Remove duplicate entreis in level config
N0OBSTUDENT Mar 28, 2026
07f0b69
Reorganized the functions.
N0OBSTUDENT Mar 28, 2026
46212bc
Organize imports, docstring and output format to pass ruff check
N0OBSTUDENT Mar 28, 2026
86dfcbf
Restored attitude rl to latest commit in dev and introduce wrapped at…
N0OBSTUDENT Mar 28, 2026
fec0381
Pass ruff check
N0OBSTUDENT Mar 28, 2026
fc5fa94
Replace events with barrier.
N0OBSTUDENT Apr 21, 2026
75d7c91
Add success/failure indicators in forks
ratheron Apr 22, 2026
767a622
keep only one example for multi-drone racing wrapping
N0OBSTUDENT Apr 26, 2026
0940e1c
Modified ros2 messages.
N0OBSTUDENT Apr 26, 2026
4a810db
Made a temporary repository to test the message
N0OBSTUDENT Apr 26, 2026
78c2965
Reused the EnvData from real_race_env.py
N0OBSTUDENT Apr 26, 2026
6fdd078
Merge the ROS connectors
N0OBSTUDENT Apr 26, 2026
c895bee
Fixed wrong docstring
N0OBSTUDENT Apr 26, 2026
eccd03c
Changed drone_rank check to assert, removed redundant deploy variable
N0OBSTUDENT Apr 26, 2026
9142d42
docstring in attitude_controller_multi.py is shorter now
N0OBSTUDENT Apr 26, 2026
287dab3
Fixed one ignored naming change
N0OBSTUDENT Apr 26, 2026
a3f5b94
Avoided the getter function naming
N0OBSTUDENT Apr 26, 2026
bf96661
Spreaded out the safety limit bound condition
N0OBSTUDENT Apr 26, 2026
a8dcf25
Removed the 0.1sec waiting and bare exception at shutdown of client
N0OBSTUDENT Apr 27, 2026
20919df
Split the ConfigDict argument in RealRaceHost
N0OBSTUDENT Apr 27, 2026
b671a74
Fixed bad docstring
N0OBSTUDENT Apr 27, 2026
bbd9c31
Replace the busy-wait loop with event blocking the thread
N0OBSTUDENT Apr 27, 2026
2ed0147
Remove the property and make the node externally accessible
N0OBSTUDENT Apr 27, 2026
2458860
Remove unnecessary imports
N0OBSTUDENT Apr 27, 2026
c4f8783
Modifies multi_sim to take in n controllers instead of one. Adds wrap…
rducrist Apr 10, 2026
25da75d
Changes flight times for demo attitude controllers to avoid collision
rducrist Apr 10, 2026
915aee7
Adapts documentation for wrappers
rducrist Apr 14, 2026
284ca13
Sets attitude controllers as default
rducrist Apr 14, 2026
6609914
Rewrites logging to be more readable. Now displays the stats as table
rducrist Apr 16, 2026
a11966e
Increases offset between drones to prevent collision
rducrist Apr 16, 2026
90ebded
Ruff formats
rducrist Apr 16, 2026
09ac56a
Ruff check again
rducrist Apr 16, 2026
933e4be
Avoids calling controllers if the respective drones are disabled
rducrist Apr 16, 2026
dc5c4b9
Adds start position of drones to waypoints
rducrist Apr 16, 2026
edcdc9e
Removes try block, simplyfies info rank logic.
rducrist Apr 20, 2026
1d59c53
Removes initial first waypoint from all controllers. Adds z offset to…
rducrist Apr 21, 2026
f8f386b
Update waypoints
ratheron Apr 23, 2026
aec6c33
Adds logic for running controllers at different frequencies
rducrist Apr 24, 2026
1201297
Move prediods
ratheron Apr 27, 2026
814cb04
Fix linting
ratheron Apr 27, 2026
b455d2d
Merge branch 'dev' into zenoh_ros2_multidrone
N0OBSTUDENT May 10, 2026
cd1b24b
Restored the attitude mpc implementation
N0OBSTUDENT May 10, 2026
dbecae6
Pinned the boost library version to 1.86. Otherwise the mocap package…
N0OBSTUDENT May 10, 2026
6fe9d1a
Pinned packaging to avoid conflicts
N0OBSTUDENT May 10, 2026
0287df9
Replace not-existing Error class with threading
N0OBSTUDENT May 10, 2026
c79a060
Fixed LD library path and mocap setup scripts
N0OBSTUDENT May 10, 2026
e2c15f6
Update lock file
N0OBSTUDENT May 10, 2026
0006ad4
Update ignore file
N0OBSTUDENT May 10, 2026
1c6ef11
Merge branch 'zenoh_ros2_multidrone' of https://github.com/N0OBSTUDEN…
N0OBSTUDENT May 10, 2026
fb33705
Add drone racing messages
ratheron Jun 9, 2026
992cd05
Fix ruff
ratheron Jun 9, 2026
98addb7
Fix tests
ratheron Jun 9, 2026
9ebb375
Add real race messages
ratheron Jun 9, 2026
df4fafe
Remove compute latency
ratheron Jun 9, 2026
f28bbad
Revert change
ratheron Jun 9, 2026
a415e49
Merge remote-tracking branch 'upstream/main' into zenoh_ros2_multidrone
ratheron Jun 9, 2026
fc421b5
Pin lark dependency
ratheron Jun 9, 2026
413ef07
Merge remote-tracking branch 'upstream/main' into zenoh_ros2_multidrone
ratheron Jun 10, 2026
6d626bd
Simplify PR by reverting changes
ratheron Jun 10, 2026
365d956
Rename files
ratheron Jun 10, 2026
0814a20
Fix create
ratheron Jun 16, 2026
1e45d95
Merge remote-tracking branch 'upstream/main' into zenoh_ros2_multidrone
ratheron Jun 16, 2026
71c0a5b
Fix lock file
ratheron Jun 16, 2026
a2e431b
Move to cflib2 deployment
ratheron Jun 16, 2026
12d1077
Adds return to start controller for each worker
rducrist Jun 23, 2026
ba8d0cd
Allocates the return controller height dynamically depending on the f…
rducrist Jun 25, 2026
d223bec
Reduces ROS topics to one ClientAction per drone and one HostState
rducrist Jun 26, 2026
5033cdc
Pulls drone estimators from git directly to run legacy estimator
rducrist Jun 26, 2026
03f93c0
Splits return home hand-off into height_ready_event and wait_for_retu…
rducrist Jun 26, 2026
73ddb0a
Wait for all client controller to init and then start the race
rducrist Jul 1, 2026
3ea4410
Merge remote-tracking branch 'upstream/main' into zenoh_ros2_multidrone
rducrist Jul 1, 2026
ee9a9ef
Adds first docs for maadr
rducrist Jul 1, 2026
35a66da
Fixes packaging version error prevening shell activation
rducrist Jul 1, 2026
589acc2
Removing unset check that was causing deploy activation failure
rducrist Jul 1, 2026
7810a05
Updates pixi.lock after getting corrupted during merge
rducrist Jul 1, 2026
72e4835
Adds testing deploy scripts for debugging
rducrist Jul 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@ site/
# pixi environments
.pixi/*
!.pixi/config.toml
ros_ws/
acados/
# ROS2 workspace build artifacts
ros_ws/src/motion_capture_tracking
ros_ws/build
ros_ws/install
ros_ws/log
acados/**
8 changes: 5 additions & 3 deletions config/multi_level0.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Level 0

# | Evaluation Scenario | Rand. Inertial Properties | Randomized Obstacles, Gates | Rand. Between Episodes | Notes |
# | :-----------------: | :-----------------------: | :-------------------------: | :--------------------: | :---------------: |
# | `level0.toml` | *No* | *No* | *No* | Perfect knowledge |
# | Evaluation Scenario | Randomized Inertial Properties | Randomized Obstacles, Gates | Randomized Tracks | Notes |
# | :-----------------: | :----------------------------: | :-------------------------: | :---------------: | :---------------: |
# | `level0.toml` | *No* | *No* | *No* | Perfect knowledge |
[[controller]]
file = "attitude_controller_multi.py" # Put your controller file name here. Specifying a controller as argument to scripts will override this setting. Controllers are located in `lsy_drone_racing/control/`
[[controller]] # Add the controller files for each drone
Expand All @@ -18,11 +18,13 @@ check_drone_start_pos = true
real_track_objects = true

[[deploy.drones]]
radio = 0
id = 10
channel = 100
drone_model = "cf21B_500" # Model of the drone, i.e., cf2x_L250, cf2x_P250, cf2x_T500, cf21B_500. For this course, we use cf21B_500

[[deploy.drones]]
radio = 0
id = 20
channel = 100
drone_model = "cf21B_500" # Model of the drone, i.e., cf2x_L250, cf2x_P250, cf2x_T500, cf21B_500. For this course, we use cf21B_500
Expand Down
16 changes: 9 additions & 7 deletions config/multi_level2.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Level 0
# Level 2

# | Evaluation Scenario | Rand. Inertial Properties | Randomized Obstacles, Gates | Rand. Between Episodes | Notes |
# | :-----------------: | :-----------------------: | :-------------------------: | :--------------------: | :---------------: |
# | `level0.toml` | *No* | *No* | *No* | Perfect knowledge |
# | Evaluation Scenario | Randomized Inertial Properties | Randomized Obstacles, Gates | Randomized Tracks | Notes |
# | :-----------------: | :----------------------------: | :-------------------------: | :---------------: | :-------------------: |
# | `level2.toml` | *Yes* | *Yes* | *No* | Learning, re-planning |
[[controller]]
file = "attitude_controller_multi.py" # Put your controller file name here. Specifying a controller as argument to scripts will override this setting. Controllers are located in `lsy_drone_racing/control/`
[[controller]]
Expand All @@ -18,11 +18,13 @@ check_drone_start_pos = true
real_track_objects = true

[[deploy.drones]]
radio = 0
id = 10
channel = 100
drone_model = "cf21B_500" # Model of the drone, i.e., cf2x_L250, cf2x_P250, cf2x_T500, cf21B_500. For this course, we use cf21B_500

[[deploy.drones]]
radio = 0
id = 20
channel = 100
drone_model = "cf21B_500" # Model of the drone, i.e., cf2x_L250, cf2x_P250, cf2x_T500, cf21B_500. For this course, we use cf21B_500
Expand Down Expand Up @@ -83,7 +85,7 @@ rpy = [0.0, 0.0, 0.0]
# Obstacle height: 1.52m + reflective marker on top. Height is measured from the ground to the top of the obstacle.
# Obstacles are cylinders with a diameter of 0.03m.
[[env.track.obstacles]]
pos = [-1.5, 0.55, 0.01]
pos = [0.0, 0.75, 1.55]
[[env.track.obstacles]]
pos = [1.0, 0.25, 1.55]
[[env.track.obstacles]]
Expand All @@ -92,12 +94,12 @@ pos = [-1.5, -0.25, 1.55]
pos = [-0.5, -0.75, 1.55]

[[env.track.drones]]
pos = [-1.5, 0.95, 0.01]
pos = [-1.5, 0.55, 0.01]
rpy = [0, 0, 0]
vel = [0, 0, 0]
ang_vel = [0, 0, 0]
[[env.track.drones]]
pos = [-1.3, 0.75, 0.01]
pos = [-1.5, 0.95, 0.01]
rpy = [0, 0, 0]
vel = [0, 0, 0]
ang_vel = [0, 0, 0]
Expand Down
168 changes: 168 additions & 0 deletions config/multi_test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# Level 2

# | Evaluation Scenario | Randomized Inertial Properties | Randomized Obstacles, Gates | Randomized Tracks | Notes |
# | :-----------------: | :----------------------------: | :-------------------------: | :---------------: | :-------------------: |
# | `level2.toml` | *Yes* | *Yes* | *No* | Learning, re-planning |
[[controller]]
file = "testing_race_slow.py" # Put your controller file name here. Specifying a controller as argument to scripts will override this setting. Controllers are located in `lsy_drone_racing/control/`
[[controller]]
file = "attitude_mpc_multi.py"

[deploy]
### Settings only relevant for deployment
# Whether to check if gate and obstacle positions observed by vicon are within the limits defined down below.
check_race_track = false
# Whether to check if the drone start position is within the limits specified down below.
check_drone_start_pos = false
# Lets you practice your controller without putting up gates & obstacles, assumes nominal positions given below.
real_track_objects = false

# Specify the minimal and maximal height for the return controller
return_height_min = 1.5
return_height_max = 1.75

[[deploy.drones]]
radio = 0
id = 52
channel = 80
drone_model = "cf21B_500" # Model of the drone, i.e., cf2x_L250, cf2x_P250, cf2x_T500, cf21B_500. For this course, we use cf21B_500

[[deploy.drones]]
radio = 1
id = 20
channel = 100
drone_model = "cf21B_500"


[sim]
# Physics options:
# "first_principles": first_principles (physics based) model
# "so_rpy": Simplified identified model.
# "so_rpy_rotor": Simplified identified model with rotor dynamics.
# "so_rpy_rotor_drag": Simplified identified model with rotor dynamics and drag.
physics = "first_principles"
drone_model = "cf21B_500" # Model of the drone, i.e., cf2x_L250, cf2x_P250, cf2x_T500, cf21B_500. For this course, we use cf21B_500
freq = 500 # Simulation frequency, in Hz
attitude_freq = 500 # Controller frequency, in Hz. This frequency is used to simulate the onboard controller, NOT for the environment's step function
render = true # Enable/disable Crazyflow's GUI
camera = -1 # camera id or name, i.e., drone cam ids start at 0, cam names are "fpv_cam:0" or "track_cam:0", where the number is the drone id
[[sim.cam_config]] # only used if camera == -1, i.e., world view is activated
distance = 5.0
azimuth = 180.0
elevation = -25.0
lookat = [0.0, 0.0, 0.0]


[env]
id = "MultiDroneRacing-v0"
seed = -1 # -1 for random seeds or a non-zero integer for reproducibility
[[env.kwargs]]
freq = 50 # Frequency of the environment's step function, in Hz
sensor_range = 0.7 # Range at which the exact location of gates and obstacles become visible to the drone. Objects that are not in the drone's sensor range report their nominal position.
control_mode = "attitude" # Control mode of the environment. Can be either "state" or "attitude"
[[env.kwargs]]
freq = 50 # Frequency of the environment's step function, in Hz
sensor_range = 0.7 # Range at which the exact location of gates and obstacles become visible to the drone. Objects that are not in the drone's sensor range report their nominal position.
control_mode = "attitude" # Control mode of the environment. Can be either "state" or "attitude"


[env.track]
# Full track radomization. When activated, the position (x & y) and orientation (yaw)
# of the below given gates, obstacles and drones is randomized inside the safety limits.
# Note: The order and therefore also height is not randomized!
randomize = false

# Tall gates: 1.195m height. Short gates: 0.695m height. Height is measured from the ground to the center of the gate.
# Gates are square. Gates are 0.72m wide (outer dimensions of the frame) with a 0.4m wide opening.
[[env.track.gates]]
pos = [0.5 , 0.25, 0.7]
rpy = [0.0, 0.0, -0.78]
[[env.track.gates]]
pos = [1.05, 0.75, 1.2]
rpy = [0.0, 0.0, 2.35]
[[env.track.gates]]
pos = [-1.0, -0.25, 0.7]
rpy = [0.0, 0.0, 3.14]
[[env.track.gates]]
pos = [0.0, -0.75, 1.2]
rpy = [0.0, 0.0, 0.0]

# Obstacle height: 1.52m + reflective marker on top. Height is measured from the ground to the top of the obstacle.
# Obstacles are cylinders with a diameter of 0.03m.
[[env.track.obstacles]]
pos = [0.0, 0.75, 1.55]
[[env.track.obstacles]]
pos = [1.0, 0.25, 1.55]
[[env.track.obstacles]]
pos = [-1.5, -0.25, 1.55]
[[env.track.obstacles]]
pos = [-0.5, -0.75, 1.55]

[[env.track.drones]]
pos = [-1.5, 0.50, 0.01]
rpy = [0, 0, 0]
vel = [0, 0, 0]
ang_vel = [0, 0, 0]
[[env.track.drones]]
pos = [-1.5, 1.0, 0.01]
rpy = [0, 0, 0]
vel = [0, 0, 0]
ang_vel = [0, 0, 0]

# If the drones exceed those bounds in real, the run will be stopped and the drone will safely be returned to the starting position
[env.track.safety_limits]
pos_limit_low = [-2.5, -1.5, -1e-3]
pos_limit_high = [2.5, 1.5, 2.0]

# We intentionally reduce the disturbances for the multi-drone scenario, so students can focus on the multi-drone aspect for now.
[env.disturbances.action]
fn = "normal"
scale = 0.001

[env.disturbances.dynamics]
fn = "uniform"
[env.disturbances.dynamics.kwargs]
minval = [-0.02, -0.02, -0.02]
maxval = [0.02, 0.02, 0.02]

[env.randomizations.drone_pos]
fn = "uniform"
[env.randomizations.drone_pos.kwargs]
minval = [-0.02, -0.02, 0.0]
maxval = [0.02, 0.02, 0.02]

[env.randomizations.drone_rpy]
fn = "uniform"
[env.randomizations.drone_rpy.kwargs]
minval = [-0.1, -0.1, -0.1]
maxval = [0.1, 0.1, 0.1]

[env.randomizations.drone_mass]
fn = "uniform"
[env.randomizations.drone_mass.kwargs]
minval = -0.002
maxval = 0.002

[env.randomizations.drone_inertia]
fn = "uniform"
[env.randomizations.drone_inertia.kwargs]
minval = [-0.000001, -0.000001, -0.000001]
maxval = [0.000001, 0.000001, 0.000001]

[env.randomizations.gate_pos]
fn = "uniform"
[env.randomizations.gate_pos.kwargs]
minval = [-0.02, -0.02, -0.01]
maxval = [0.02, 0.02, 0.01]

[env.randomizations.gate_rpy]
fn = "uniform"
[env.randomizations.gate_rpy.kwargs]
minval = [-0.01, -0.01, -0.01]
maxval = [0.01, 0.01, 0.01]

[env.randomizations.obstacle_pos]
fn = "uniform"
[env.randomizations.obstacle_pos.kwargs]
minval = [-0.02, -0.02, -0.01]
maxval = [0.02, 0.02, 0.01]
Loading
Loading