Introduction
Developing flight control software is inherently risky. Uploading an untested stabilization loop to a real quadcopter can mean instant hardware destruction. What developers need is a way to validate control logic in a realistic environment before the first flight.
This is exactly what RealFlight Bridge provides: a Rust interface to the RealFlight simulator that enables both Software-in-the-Loop (SITL) and Hardware-in-the-Loop (HITL, sometimes written HIL) testing. It lets you run your flight controller against a high-fidelity physics simulation built for RC aircraft.
Why RealFlight?
Before diving into the technical details, you might wonder: why RealFlight specifically?
Simulator Comparison
| Simulator | Strengths | Limitations | Best For |
|---|---|---|---|
| Microsoft Flight Simulator | Stunning visuals, massive world, realistic full-scale aircraft | Poor multirotor modeling, low update rate (<100 Hz), limited drone customization | General aviation, fixed-wing |
| Gazebo / Ignition | Open-source, ROS integration, configurable physics | Heavy setup, requires tuning for realistic multirotor behavior | Robotics research, ROS-based systems |
| X-Plane | Accurate aerodynamics, professional-grade flight model | Expensive, limited multirotor support | Fixed-wing training & development |
| RealFlight | Built for RC aircraft & drones, high-fidelity small-scale physics, supports custom models, achieves 200+ Hz | Windows-only, proprietary | Multirotor & RC aircraft development (SITL/HITL) |
For drone flight controller development, RealFlight’s focus on small-scale aircraft, custom model support, and high update rates makes it an ideal choice. It understands the unique dynamics of quadcopters, helicopters, and fixed-wing RC aircraft in a way that general aviation simulators don’t.
What is RealFlight Bridge?
With the right simulator selected, the next challenge is connecting your flight controller code to it. That’s where RealFlight Bridge comes in.
RealFlight Bridge is a Rust library that interfaces with RealFlight’s Link API, allowing external flight controllers to send control inputs and receive simulated sensor data. It acts as a communication bridge between your flight control code and the simulator’s physics engine.
flowchart LR
FC[Flight Controller<br/>Rust Code] -->|Control Inputs<br/>12 RC Channels| RFB[RealFlight Bridge<br/>Local or Remote]
RFB -->|SOAP Request<br/>HTTP/XML| RF[RealFlight<br/>Simulator]
RF -->|Sensor Data| RFB
RFB -->|Aircraft State<br/>Position, Velocity,<br/>Orientation, IMU| FC
subgraph Your Code
FC
end
subgraph Bridge Layer
RFB
end
subgraph Simulation
RF
end
The library handles the complexity of RealFlight’s SOAP-based API, providing a clean, idiomatic Rust interface. Physical quantities use type-safe SI units via the uom crate by default, or you can disable the uom feature for raw floating-point values with minimal dependencies.
Key Capabilities
Control Input: Send 12-channel RC control commands to the simulated aircraft
- Standard RC channels: aileron, elevator, throttle, rudder
- Auxiliary channels: flight mode, collective pitch, flaps, landing gear, etc.
Sensor Data: Receive comprehensive flight state information including:
- Position and orientation (quaternions and Euler angles)
- Velocities (airspeed, groundspeed, body/world frame)
- Angular rates (roll, pitch, yaw rates)
- Accelerations (body and world frame)
- Altitude (above sea level and above ground)
- Environmental data (wind vectors)
- Power systems (battery voltage, current, capacity)
- Engine status (RPM, fuel remaining)
Connection Modes:
- Local Bridge: Direct connection for development on the same machine
- Remote Bridge: Network connection for testing hardware flight controllers or from remote machine
Getting Started
Let’s set up your development environment and get your first connection working.
Prerequisites
RealFlight simulator (RealFlight Evolution recommended)
- Note: RealFlight requires Windows, but runs well in VMs (Parallels, VMware) on Mac/Linux
Enable RealFlight Link:
- Open RealFlight
- Navigate to Settings → Physics → Quality
- Check “RealFlight Link Enabled”
- Restart RealFlight
Rust toolchain (install from rustup.rs)
Installation
Add to your Cargo.toml:
[dependencies]
realflight-bridge = "0.4.2"
For minimal dependencies on embedded targets, disable the default uom feature:
[dependencies]
realflight-bridge = { version = "0.4.2", default-features = false }
This uses raw f64 values instead of type-safe SI units.
Verifying Your Connection
Here’s a minimal example to verify your setup:
use realflight_bridge::{RealFlightLocalBridge, ControlInputs};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let bridge = RealFlightLocalBridge::new()?;
// Read current aircraft state
let controls = ControlInputs::default();
let state = bridge.exchange_data(&controls)?;
println!("Connected to RealFlight!");
println!("Altitude AGL: {:.2} m",
state.altitude_agl.get::<uom::si::length::meter>());
println!("Airspeed: {:.2} m/s",
state.airspeed.get::<uom::si::velocity::meter_per_second>());
Ok(())
}
Run with cargo run. You should see the current aircraft state printed to your console, confirming the connection is working.
Use Cases
RealFlight Bridge supports two primary development workflows:
Software-in-the-Loop (SITL) Development
Develop and test flight control algorithms entirely in software before touching hardware. Using RealFlightLocalBridge, you can iterate rapidly on control logic with instant feedback. No physical drone required. This is ideal for:
- Initial algorithm development and prototyping
- Parameter tuning (PID gains, filter constants)
- Testing control modes and state machines
- Debugging logic errors safely
Hardware-in-the-Loop (HITL) Testing
Once your algorithms work in software, validate them on actual embedded hardware using RealFlightRemoteBridge. Your flight controller runs on real hardware with actual timing constraints and computational limits, but the aircraft is simulated. This catches:
- Real-time performance issues
- Hardware-specific bugs (floating point, memory constraints)
- Sensor integration problems
- Communication timing issues
The Remote Bridge connects over the network to a proxy server running on the simulator machine, allowing your embedded hardware to interact with RealFlight as if it were flying a real aircraft.
Control Loop Structure
The core pattern for any flight controller using RealFlight Bridge is straightforward: read sensor data, compute control outputs, send commands. Here’s the basic structure:
use realflight_bridge::{RealFlightLocalBridge, ControlInputs};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let bridge = RealFlightLocalBridge::new()?;
bridge.reset_aircraft()?;
bridge.disable_rc()?;
let mut controls = ControlInputs::default();
loop {
// Get current aircraft state
let state = bridge.exchange_data(&controls)?;
// Your control logic here - this will vary based on:
// - Aircraft type (quadcopter, helicopter, fixed-wing)
// - Control objectives (altitude hold, attitude control, waypoint navigation)
// - Your specific tuning parameters
// Example: access sensor data
let altitude = state.altitude_agl.get::<uom::si::length::meter>();
let roll_rate = state.roll_rate.get::<uom::si::angular_velocity::radian_per_second>();
let airspeed = state.airspeed.get::<uom::si::velocity::meter_per_second>();
// Compute and apply control outputs (-1.0..1.0 or 0.0..1.0 depending on mapping)
// Channel assignments depend on your aircraft configuration
controls.channels[0] = /* aileron/roll */;
controls.channels[1] = /* elevator/pitch */;
controls.channels[2] = /* throttle */;
controls.channels[3] = /* rudder/yaw */;
}
}
For Hardware-in-the-Loop (HITL) testing, use RealFlightRemoteBridge instead, which connects over the network to a proxy server running on the simulator machine:
# On simulator machine
cargo install realflight-bridge
# Proxy binary name may appear as either of the following depending on platform/build
realflight-bridge-proxy
# or
realflight_bridge_proxy
The Remote Bridge provides the same API as the Local Bridge, so your control logic remains unchanged.
Performance Tuning
For real-time control, you need at least 200 Hz update rate. The library achieves this with:
Connection pooling for local bridges:
use realflight_bridge::Configuration;
use std::time::Duration;
let config = Configuration {
simulator_host: "127.0.0.1:18083".to_string(),
connect_timeout: Duration::from_millis(25),
pool_size: 5, // Multiple connections for throughput
};
let bridge = RealFlightLocalBridge::with_configuration(&config)?;
Network requirements for remote bridges:
- Use wired Ethernet (WiFi cannot reliably achieve 200 Hz)
- Minimize network latency
- Works well with Parallels VMs on Mac
Real-World Development Experience
I’ve been using RealFlight Bridge extensively while developing my Rust-based flight controller. Here’s how it fits into my actual workflow:
Algorithm development: I write control algorithms on my Mac, testing them with
RealFlightRemoteBridgeconnecting to RealFlight running on Parallels VM. I can iterate in seconds, tweaking PID gains and logic without leaving my IDE.Custom models: I imported the model I’m developing control logic for (a tail sitter) into RealFlight, so the simulation matches my hardware closely.
Edge case testing: I can easily test failure modes (motor failures, sensor dropouts, extreme wind) that would be dangerous or impossible to reproduce in flight.
The result? When I finally take my drone out for its first flight, I already know the control algorithms work. The simulation doesn’t eliminate all risks, but it catches the obvious bugs and gives me confidence the fundamentals are solid.
Conclusion
RealFlight Bridge solves a critical problem in flight controller development: safely testing your code before flight. By providing a clean Rust interface to RealFlight’s physics simulation, it enables both software-in-the-loop development and hardware-in-the-loop testing.
Whether you’re building a custom autopilot, experimenting with novel control algorithms, or just learning about flight dynamics, simulation-based testing is invaluable. RealFlight’s focus on RC aircraft and drones, combined with support for custom models and high update rates, makes it an excellent choice for this work.
The library is open source and available on GitHub and crates.io. If you’re working on flight control systems in Rust, give it a try and let me know how it works for you!
Additional Resources
- GitHub Repository
- Documentation
- RealFlight Simulator
- ArduPilot SITL (uses similar concepts)