A Functional Mock-up Unit (FMU) implementation for a rigid wing sail, compatible with FMI 3.0 standard. This FMU models the aerodynamic behavior and actuator dynamics of a sail wing and is designed to be integrated into a larger sail wing control system.
- FMI 3.0 Compliant: Co-simulation FMU with standard FMI interface
- Aerodynamic Modeling: 2D rigid wing model with bilinear interpolated Cx/Cy coefficients
- Actuator Dynamics: Rate-limited boom and flap control with position limits
- Cross-Platform: Supports Linux and Windows (x86_64)
- Rust Implementation: Using
fmu_from_structmacro for automatic FMU generation - Comprehensive Testing: Unit tests and visualization tools for force and coefficient analysis
wing_length_m(m): Wing span lengthwing_chord_m(m): Wing chord lengthboom_speed_deg_per_s(deg/s): Maximum boom rotation rateflap_speed_deg_per_s(deg/s): Maximum flap deflection rate
apparent_wind_speed_ms(m/s): Wind speed relative to the wingapparent_wind_angle_rad(rad): Wind direction relative to the wingboom_angle_order_rad(rad): Commanded boom angleflap_angle_order_rad(rad): Commanded flap deflection angle
boom_angle_rad(rad): Actual boom angleflap_angle_rad(rad): Actual flap deflection angleforce_x_N(N): Aerodynamic force in X direction (body frame)force_y_N(N): Aerodynamic force in Y direction (body frame)force_z_N(N): Aerodynamic force in Z direction (body frame, always 0)
cargo build --releaseGenerate cross-compiled FMU for Linux and Windows:
./build_fmu.shOutput: dist/SailWing.fmu
# Run all tests
cargo test
# Run specific test
cargo test test_sail_wing_do_step
# Generate aerodynamic coefficient plots (Cx/Cy vs. angle of attack)
cargo test test_aero_database_raw_plots -- --nocapture
# Generate force analysis plots (Forces vs. boom angle for different flap angles)
cargo test test_force_analysis_plots -- --nocaptureTest plots are saved to tests/output/:
raw_cx_coefficient_plot.png: Cx coefficients vs. angle of attackraw_cy_coefficient_plot.png: Cy coefficients vs. angle of attackforce_fx_analysis.png: X-forces vs. boom angleforce_fy_analysis.png: Y-forces vs. boom angle
A simple Python test script is available for testing the generated FMU:
# Run simple simulation test (requires fmpy)
python tests/simple_simulation.pyThe aerodynamic coefficients are hardcoded in src/aerodatabase.rs with data for:
- Flap angles: 0°, 10°, 20°, 30°
- Angle of attack: 0° to 360° (varying resolution)
- Coefficients: Cx (chord-aligned) and Cy (perpendicular to chord)
The database uses bilinear interpolation for intermediate values with proper wrapping at 360°/0°.
- Wing coordinates: X along chord, Y perpendicular to chord
- Body coordinates: X forward, Y starboard
- Forces are transformed from wing to body frame using the boom angle
- Boom: Unlimited rotation (wraps at 360°), rate-limited by
boom_speed_deg_per_s - Flap: Limited to ±30° (max defined in aerodynamic database), rate-limited by
flap_speed_deg_per_s - Both actuators use simple rate limiting with position clamping
.
├── src/
│ ├── lib.rs # Main FMU struct and physics implementation
│ └── aerodatabase.rs # Aerodynamic coefficient database and interpolation
├── tests/
│ ├── integration_tests.rs # Comprehensive test suite
│ └── simple_simulation.py # Python FMU validation script
├── build_fmu.sh # Cross-compilation script for FMU generation
├── Cargo.toml # Rust dependencies and build configuration
└── README.md # This file
fmu_from_struct: FMU macro generation for Rust structsserde,serde_json: Serialization support (for future config file support)
more-asserts: Enhanced test assertionsplotters: Plot generation for analysis and visualizationcross: Cross-compilation for Linux and Windows targets
See LICENSE.txt for details.