Python SDK for QuadSim drone simulation
Project description
QuadSim Python SDK
Research-oriented drone simulation control for Python.
High-level flight commands, raw low-level control, deterministic stepping, and live visualization.
Getting Started • Quick Example • Control Modes • Lockstep Control • Coordinate Frame • API Overview • Project Structure
What is QuadSim?
QuadSim is a research-oriented quadrotor simulation platform built in Unity for controls research, autonomy development, and sim-to-real workflows.
This package is the Python SDK. It connects to a running QuadSim Unity scene over ZeroMQ and lets Python code command drones, read sensors, switch control modes, step the simulator deterministically, and stream live visualization data.
The Unity runtime is installed separately:
- Unity plugin: github.com/ninonick0607/Unity-QuadSim-Plugin
The SDK exposes two layers through one simple object model:
QuadSim ← sim/world entry point, owns the connection
└─ Drone ← high-level flight, raw commands, sensors, telemetry, stepping
You can move from takeoff() to raw send_command() or lockstep step_with_*() calls without changing objects.
Getting Started
Requirements
- Python 3.8+
- A running QuadSim Unity scene or headless build
- RPC enabled in Unity through
ExternalRpcAdapter - Unity command port, default
5555 - Unity telemetry port, default
5556
Install
From PyPI:
pip install quadsim-sdk
From source:
git clone https://github.com/ninonick0607/QuadSimLib.git
cd QuadSimLib
pip install -e .
This installs the Python dependencies, including pyzmq and msgpack.
Verify Connection
Start the Unity scene or headless build first, then run:
from quadsim import QuadSim
with QuadSim() as sim:
print(sim.get_status())
If it prints status information, the SDK is connected.
Quick Example
from quadsim import QuadSim
with QuadSim() as sim:
drone = sim.drone()
drone.takeoff(altitude=3.0)
drone.fly_to(x=5, y=0, z=3)
drone.hover(duration=2.0)
drone.yaw_to(heading_deg=180)
drone.fly_path([(5, 5, 3), (0, 5, 3), (0, 0, 3)])
drone.land()
Control Modes
QuadSim supports high-level scripted flight, cascaded controller modes, motor passthrough, allocated wrench control, and direct wrench control.
The detailed control-mode documentation lives in:
That page covers:
- When to use each mode.
- Exact
send_command(...)layouts. - How to call
set_mode(...). - How to use one-shot commands versus lockstep
step_with_*commands. - Difference between position, velocity, angle, rate, passthrough, allocated wrench, direct wrench, and acceleration helper APIs.
- How to read sensors and telemetry after each command.
Minimal raw example:
import time
from quadsim import QuadSim
with QuadSim() as sim:
drone = sim.drone()
drone.takeoff(3.0)
drone.set_mode("velocity")
for _ in range(100):
drone.send_command(vx=1.0, vy=0.0, vz=0.0, yaw_rate=10.0)
time.sleep(0.02)
drone.hover(duration=2.0)
drone.land()
Lockstep Control
For tuning, learning, and deterministic experiments, pause the simulator and advance it one control tick at a time.
from quadsim import QuadSim
CONTROL_HZ = 50.0
with QuadSim() as sim:
drone = sim.drone()
sim.pause()
status = sim.get_status()
steps_per_tick = max(1, round((1.0 / CONTROL_HZ) / status.fixed_dt))
sensors = drone.get_sensors()
for _ in range(2500):
tx, ty, tz, thrust = my_controller(sensors)
sensors = drone.step_with_wrench(
tx=tx,
ty=ty,
tz=tz,
thrust=thrust,
count=steps_per_tick,
)
sim.resume()
A composite step call applies a command, advances Unity physics, and returns the post-step sensor snapshot in one RPC round trip.
At the default Unity physics rate of 250 Hz, count=5 gives one 50 Hz controller update.
Async Flight with Polling
High-level methods also have _async variants that return a future-like handle:
import time
from quadsim import QuadSim
with QuadSim() as sim:
drone = sim.drone()
drone.takeoff(3.0)
future = drone.fly_to_async(x=10, y=0, z=3, speed=2.0)
while not future.done:
pos = drone.get_position()
print(f"Position: ({pos[0]:.1f}, {pos[1]:.1f}, {pos[2]:.1f})")
time.sleep(0.5)
drone.land()
Coordinate Frame
Everything the Python SDK exposes uses FLU unless an advanced bridge explicitly documents another frame:
| Axis | Direction | Example |
|---|---|---|
X |
Forward | fly_to(x=5, ...) moves forward |
Y |
Left | fly_to(y=3, ...) moves left |
Z |
Up | fly_to(z=3, ...) means 3 meters altitude |
Z is altitude for positions and vertical commands.
Common conventions:
| Data | Frame |
|---|---|
gps_position |
World FLU |
imu_vel |
Body FLU |
imu_ang_vel |
Body FLU |
imu_accel |
Body FLU |
wrench torques |
Body FLU |
position commands |
World FLU |
velocity commands |
SDK FLU command convention |
passthrough motors |
Motor order: FL, FR, BL, BR |
The Unity adapter handles Unity-frame conversion internally.
Environment / Disturbance
Toggle the scene wind/disturbance field from Python:
drone.set_wind(enabled=True)
drone.set_wind(enabled=True, wind_speed=8.0)
drone.set_wind(enabled=False)
With no wind_speed, each Unity WindModule keeps its scene-configured speed.
Headless Visualization
The SDK includes UdpViz, a fire-and-forget UDP sender for live headless visualization.
from quadsim import UdpViz
viz = UdpViz(source="my-run")
viz.path(planned_points)
# inside the loop
viz.sample(t, pos, target=target_pos, err=err, speed=speed, trial=trial_id)
Run the viewer separately:
python live_viewer.py --port 14660
Positions are FLU [x, y, z], z-up. If no viewer is listening, packets are dropped and the run continues.
API Overview
QuadSim — Sim / World
| Method | Description |
|---|---|
connect() |
Connect to Unity server |
disconnect() |
Clean disconnect |
drone() |
Get a Drone handle |
get_status() |
Sim time, fixed dt, pause state, authority |
pause() / resume() |
Pause/resume simulation |
step(count) |
Advance N physics steps |
set_time_scale(scale) |
Speed up / slow down free-run mode |
reset() |
Reset entire simulation |
Drone — Flight / Control
| Method | Description |
|---|---|
takeoff(altitude, speed) |
Climb and stabilize |
land(speed) |
Descend to ground |
hover(duration) |
Hold position |
fly_to(x, y, z, speed, yaw) |
Fly to a position |
fly_path(waypoints, speed) |
Follow a waypoint sequence |
yaw_to(heading_deg) |
Rotate to heading |
set_mode(mode) |
Set raw goal mode |
set_controller(controller) |
Switch controller kind |
send_command(...) |
Send raw Axis4 command |
send_motors(...) |
Send motor passthrough command |
send_wrench(...) |
Send allocated wrench command |
send_wrench_bypass(...) |
Send direct Rigidbody wrench |
step_with_* |
Apply command + step + return sensors |
get_sensors() |
Full sensor snapshot |
get_telemetry() |
Controller state and motor outputs |
reset_pose(...) |
Teleport pose |
reset_physics() |
Zero velocities |
reset_controller() |
Clear controller state |
Streaming
| Method | Description |
|---|---|
subscribe_sensors(callback, hz) |
Push-based sensor data |
subscribe_telemetry(callback, hz) |
Push-based telemetry |
subscribe(callback, topics, hz) |
Raw topic subscription |
unsubscribe() |
Stop streaming |
API Reference
SensorData Fields
sensors = drone.get_sensors()
sensors.gps_position
sensors.imu_attitude
sensors.imu_vel
sensors.imu_accel
sensors.imu_ang_vel
sensors.imu_orientation
sensors.gps_lat
sensors.gps_lon
sensors.gps_alt
sensors.gps_vel_ned
sensors.baro_pressure_hpa
sensors.baro_temperature_c
sensors.mag_field
Telemetry Fields
telem = drone.get_telemetry()
telem.drone_id
telem.mode
telem.controller
telem.motors
telem.motor_thrusts
telem.desired_rates_deg
telem.desired_angles_deg
telem.desired_vel
telem.external_cmd
SimStatus Fields
status = sim.get_status()
status.is_paused
status.time_scale
status.sim_time
status.fixed_dt
status.authority
status.client_connected
Tuning Parameters
Set these on the Drone object before or during high-level flight:
drone.position_tolerance = 0.5
drone.altitude_tolerance = 0.3
drone.landing_altitude = 0.15
drone.default_speed = 2.0
drone.control_loop_hz = 50.0
drone.default_leg_timeout = 30.0
drone.use_velocity_mode_navigation = False
Exceptions
from quadsim import QuadSimError, ConnectionError, CommandError, TimeoutError, ProtocolError
| Exception | When |
|---|---|
ConnectionError |
Not connected or connection denied |
CommandError |
Authority rejected, invalid drone, invalid mode |
TimeoutError |
RPC timeout or flight command timeout |
ProtocolError |
Wire-level serialization issue |
All inherit from QuadSimError.
How It Works
The SDK communicates with QuadSim's Unity runtime over ZeroMQ:
| Socket | Default port | Purpose |
|---|---|---|
| REQ/REP | 5555 |
Commands, queries, mode changes, composite steps |
| PUB/SUB | 5556 |
Streaming telemetry |
Messages are serialized with MessagePack. A background heartbeat keeps the connection alive. Socket handling is internal to _transport.py.
Project Structure
QuadSimLib/
├── quadsim/
│ ├── __init__.py
│ ├── sim.py
│ ├── drone.py
│ ├── viz.py
│ ├── _transport.py
│ ├── _control_loops.py
│ ├── types.py
│ ├── exceptions.py
│ └── future.py
├── docs/
│ └── control_modes.md
├── live_viewer.py
├── Examples/
│ ├── flight_demo.py
│ └── async_demo.py
├── Testing/
│ ├── quadsim_test_client.py
│ ├── quadsim_test_commands.py
│ └── test_high_level.py
└── pyproject.toml
Related
- Unity runtime/plugin: github.com/ninonick0607/Unity-QuadSim-Plugin
- Main Unity development repo: github.com/ninonick0607/Unity_QuadSim
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file quadsim_sdk-0.13.0.tar.gz.
File metadata
- Download URL: quadsim_sdk-0.13.0.tar.gz
- Upload date:
- Size: 33.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
401262bf223145f6620d027d1c28a18ddd518b55d07d8343fbca6346a003383b
|
|
| MD5 |
03bf7905468737296be3b4711cfa5cb1
|
|
| BLAKE2b-256 |
a0dbfb9f216e1fe164e568d3d05044903620809086179ffa70340a88b9ee1283
|
File details
Details for the file quadsim_sdk-0.13.0-py3-none-any.whl.
File metadata
- Download URL: quadsim_sdk-0.13.0-py3-none-any.whl
- Upload date:
- Size: 34.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9790f04a7ce56f5b0edeab7668b44f12d6e3fd8252f59322d4b464e97500d761
|
|
| MD5 |
9af36a9320812b8a93d91935c999d61d
|
|
| BLAKE2b-256 |
ea6028478b7c3d7b1575571344b40196b2deceeee7360b3ead763c0ca253e568
|