realflight_bridge/
lib.rs

1//! [![github]](https://github.com/wboayue/realflight-bridge) [![crates-io]](https://crates.io/crates/realflight-bridge) [![license]](https://opensource.org/licenses/MIT)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [license]: https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge&labelColor=555555
6//!
7//! RealFlight is a leading RC flight simulator that provides a realistic, physics-based environment for flying fixed-wing aircraft, helicopters, and drones. Used by both hobbyists and professionals, it simulates aerodynamics, wind conditions, and control responses, making it an excellent tool for flight control algorithm validation.
8//!
9//! RealFlightBridge is a Rust library that interfaces with RealFlight Link, enabling external flight controllers to interact with the simulator. It allows developers to:
10//!
11//! * Send control commands to simulated aircraft.
12//! * Receive real-time simulated flight data for state estimation and control.
13//! * Test stabilization and autonomy algorithms in a controlled environment.
14//!
15//! See [README](https://github.com/wboayue/realflight-bridge) for examples and usage.
16
17use serde::Deserialize;
18use serde::Serialize;
19use thiserror::Error;
20
21/// Errors that can occur when interacting with the RealFlight simulator.
22#[derive(Debug, Error)]
23pub enum BridgeError {
24    /// Connection to the simulator failed
25    #[error("Connection failed: {0}")]
26    Connection(#[from] std::io::Error),
27
28    /// Initialization failed
29    #[error("Initialization failed: {0}")]
30    Initialization(String),
31
32    /// SOAP fault returned by the simulator
33    #[error("SOAP fault: {0}")]
34    SoapFault(String),
35
36    /// Failed to parse simulator response
37    #[error("Parse error for field '{field}': {message}")]
38    Parse { field: String, message: String },
39}
40
41/// Conditional type aliases for physical quantities.
42/// With `uom` feature: strongly-typed SI units
43/// Without `uom` feature: raw f32 values
44#[cfg(feature = "uom")]
45mod unit_types {
46    pub use uom::si::f32::{
47        Acceleration, Angle, AngularVelocity, ElectricCharge, ElectricCurrent, ElectricPotential,
48        Length, Time, Velocity, Volume,
49    };
50}
51
52#[cfg(not(feature = "uom"))]
53mod unit_types {
54    pub type Velocity = f32;
55    pub type Length = f32;
56    pub type AngularVelocity = f32;
57    pub type Angle = f32;
58    pub type Acceleration = f32;
59    pub type ElectricPotential = f32;
60    pub type ElectricCurrent = f32;
61    pub type ElectricCharge = f32;
62    pub type Volume = f32;
63    pub type Time = f32;
64}
65
66use unit_types::*;
67
68#[cfg(any(test, feature = "bench-internals"))]
69pub use decoders::decode_simulator_state;
70
71#[cfg(any(test, feature = "bench-internals"))]
72pub use decoders::extract_element;
73
74#[cfg(any(test, feature = "bench-internals"))]
75pub use encoders::encode_control_inputs;
76
77pub mod bridge;
78mod decoders;
79mod encoders;
80mod soap_client;
81mod statistics;
82
83pub use statistics::Statistics;
84pub(crate) use statistics::StatisticsEngine;
85
86/// Default RealFlight simulator address (localhost on standard port)
87pub const DEFAULT_SIMULATOR_HOST: &str = "127.0.0.1:18083";
88
89#[doc(inline)]
90pub use bridge::RealFlightBridge;
91#[doc(inline)]
92pub use bridge::local::Configuration;
93#[doc(inline)]
94pub use bridge::local::RealFlightLocalBridge;
95#[doc(inline)]
96pub use bridge::remote::RealFlightRemoteBridge;
97
98// Async exports (requires rt-tokio feature)
99#[cfg(feature = "rt-tokio")]
100#[doc(inline)]
101pub use bridge::AsyncBridge;
102#[cfg(feature = "rt-tokio")]
103#[doc(inline)]
104pub use bridge::local::{AsyncLocalBridge, AsyncLocalBridgeBuilder};
105#[cfg(feature = "rt-tokio")]
106#[doc(inline)]
107pub use bridge::remote::{AsyncRemoteBridge, AsyncRemoteBridgeBuilder};
108
109// Re-export for binary (not part of public API)
110#[cfg(feature = "rt-tokio")]
111#[doc(hidden)]
112pub use bridge::proxy::AsyncProxyServer;
113
114/// Control inputs for the RealFlight simulator using the standard RC channel mapping.
115/// Each channel value should be between 0.0 (minimum) and 1.0 (maximum).
116///
117/// # Standard RC Channel Mapping
118///
119/// The 12 available channels typically map to the following controls:
120///
121/// * Channel 1 (Aileron): Controls roll movement
122///   - 0.0: Full left roll
123///   - 0.5: Neutral
124///   - 1.0: Full right roll
125///
126/// * Channel 2 (Elevator): Controls pitch movement
127///   - 0.0: Full down pitch (nose down)
128///   - 0.5: Neutral
129///   - 1.0: Full up pitch (nose up)
130///
131/// * Channel 3 (Throttle): Controls engine power
132///   - 0.0: Zero throttle (engine off/idle)
133///   - 1.0: Full throttle
134///
135/// * Channel 4 (Rudder): Controls yaw movement
136///   - 0.0: Full left yaw
137///   - 0.5: Neutral
138///   - 1.0: Full right yaw
139///
140/// * Channel 5: Commonly used for flight modes
141///   - Often used as a 3-position switch (0.0, 0.5, 1.0)
142///   - Typical modes: Manual, Stabilized, Auto
143///
144/// * Channel 6: Commonly used for collective pitch (helicopters)
145///   - 0.0: Full negative pitch
146///   - 0.5: Zero pitch
147///   - 1.0: Full positive pitch
148///
149/// * Channels 7-12: Auxiliary channels
150///   - Can be mapped to various functions like:
151///     - Flaps
152///     - Landing gear
153///     - Camera gimbal
154///     - Lights
155///     - Custom functions
156#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
157pub struct ControlInputs {
158    /// Array of 12 channel values, each between 0.0 and 1.0
159    pub channels: [f32; 12],
160}
161
162/// Represents the complete state of the simulated aircraft in RealFlight.
163/// Physical quantities use metric units (strongly-typed with `uom` feature, raw f32 otherwise).
164#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
165pub struct SimulatorState {
166    /// Previous control inputs that led to this state
167    pub previous_inputs: ControlInputs,
168    /// Velocity relative to the air mass [meters/second]
169    pub airspeed: Velocity,
170    /// Altitude above sea level (m)
171    pub altitude_asl: Length,
172    /// Altitude above ground level (m)
173    pub altitude_agl: Length,
174    /// Velocity relative to the ground [meters/second]
175    pub groundspeed: Velocity,
176    /// Pitch rate around body Y axis [degrees/second]
177    pub pitch_rate: AngularVelocity,
178    /// Roll rate around body X axis [degrees/second]
179    pub roll_rate: AngularVelocity,
180    /// Yaw rate around body Z axis [degrees/second]
181    pub yaw_rate: AngularVelocity,
182    /// Heading angle (true north reference) (deg)
183    pub azimuth: Angle,
184    /// Pitch angle (nose up reference) (deg)
185    pub inclination: Angle,
186    /// Roll angle (right wing down reference) (deg)
187    pub roll: Angle,
188    /// Aircraft position along world X axis (North) (m)
189    pub aircraft_position_x: Length,
190    /// Aircraft position along world Y axis (East) (m)
191    pub aircraft_position_y: Length,
192    /// Velocity component along world X axis (North) [meters/second]
193    pub velocity_world_u: Velocity,
194    /// Velocity component along world Y axis (East) [meters/second]
195    pub velocity_world_v: Velocity,
196    /// Velocity component along world Z axis (Down) [meters/second]
197    pub velocity_world_w: Velocity,
198    /// Forward velocity in body frame [meters/second]
199    pub velocity_body_u: Velocity,
200    /// Lateral velocity in body frame [meters/second]
201    pub velocity_body_v: Velocity,
202    /// Vertical velocity in body frame [meters/second]
203    pub velocity_body_w: Velocity,
204    /// Acceleration along world X axis (North) [meters/second²]
205    pub acceleration_world_ax: Acceleration,
206    /// Acceleration along world Y axis (East) [meters/second²]
207    pub acceleration_world_ay: Acceleration,
208    /// Acceleration along world Z axis (Down) [meters/second²]
209    pub acceleration_world_az: Acceleration,
210    /// Acceleration along body X axis (Forward) [meters/second²]
211    pub acceleration_body_ax: Acceleration,
212    /// Acceleration along body Y axis (Right) [meters/second²]
213    pub acceleration_body_ay: Acceleration,
214    /// Acceleration along body Z axis (Down) [meters/second²]
215    pub acceleration_body_az: Acceleration,
216    /// Wind velocity along world X axis [meters/second]
217    pub wind_x: Velocity,
218    /// Wind velocity along world Y axis [meters/second]
219    pub wind_y: Velocity,
220    /// Wind velocity along world Z axis [meters/second]
221    pub wind_z: Velocity,
222    /// Propeller RPM for piston/electric aircraft [revolutions/minute]
223    pub prop_rpm: f32,
224    /// Main rotor RPM for helicopters [revolutions/minute]
225    pub heli_main_rotor_rpm: f32,
226    /// Battery voltage (V)
227    pub battery_voltage: ElectricPotential,
228    /// Current draw from battery (A)
229    pub battery_current_draw: ElectricCurrent,
230    /// Remaining battery capacity [milliamperes-hour]
231    pub battery_remaining_capacity: ElectricCharge,
232    /// Remaining fuel volume (oz)
233    pub fuel_remaining: Volume,
234    /// True if aircraft is in a frozen/paused state
235    pub is_locked: bool,
236    /// True if aircraft has lost components due to damage
237    pub has_lost_components: bool,
238    /// True if any engine is currently running
239    pub an_engine_is_running: bool,
240    /// True if aircraft is in contact with ground
241    pub is_touching_ground: bool,
242    /// Current status message from simulator
243    pub current_aircraft_status: String,
244    /// Current simulation time
245    pub current_physics_time: Time,
246    /// Current time acceleration factor
247    pub current_physics_speed_multiplier: f32,
248    /// Quaternion X component (scalar)
249    pub orientation_quaternion_x: f32,
250    /// Quaternion Y component (scalar)
251    pub orientation_quaternion_y: f32,
252    /// Quaternion Z component (scalar)
253    pub orientation_quaternion_z: f32,
254    /// Quaternion W component (scalar)
255    pub orientation_quaternion_w: f32,
256    /// True if external flight controller is active
257    pub flight_axis_controller_is_active: bool,
258    /// True if reset button was pressed
259    pub reset_button_has_been_pressed: bool,
260}
261
262#[cfg(test)]
263pub mod tests;