1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
//! Aircraft-level components: geometry and the core spawn bundle.
use crate*;
use Scalar;
use ;
use ;
/// Core bundle. Spawn on the aircraft root entity.
///
/// Mass, centre of gravity, and inertia are computed automatically by Avian
/// from child colliders' [`avian3d::prelude::ColliderDensity`] values.
///
/// Aerodynamic forces are accumulated each frame into the included
/// [`ConstantForce`] and [`ConstantTorque`] components, which Avian then
/// applies natively via `ForceSystems::ApplyConstantForces`.
///
/// [`LinearVelocity`] and [`AngularVelocity`] are present on a RigidBody::Dynamic
/// and included with zero defaults. Override them after spawning to set an
/// initial velocity.
///
/// # Collision filtering
///
/// Zone colliders are real physics colliders and will interact with terrain or
/// other objects in the scene by default. For aerodynamics-only simulation
/// (no collision response), use [`avian3d::prelude::CollisionLayers`] on each
/// zone child entity to prevent contact with world geometry. Do not use
/// [`avian3d::prelude::Sensor`] - it excludes the collider from mass computation.
///
/// # Optional components (add to the same entity after spawning)
///
/// - [`InducedDrag`], add for conventional lifting aircraft (most fixed-wing).
/// Omit for gliders with polar-based CDs, missiles, or LOD AI.
/// - [`LodDamping`], add only for sparse-zone aircraft where zone geometry
/// cannot produce realistic roll/pitch/yaw damping.
///
/// # Example
/// ```rust,no_run
/// # use avian_fdm::components::*;
/// # use bevy::prelude::*;
/// // Full-fidelity aircraft with induced drag, zone-based damping:
/// // commands.spawn((
/// // AircraftCoreBundle { geometry: AircraftGeometry { wing_area_m2: 16.2, wing_span_m: 10.6, chord_m: 1.53 }, ..default() },
/// // InducedDrag { oswald_factor: 0.85 },
/// // ));
/// ```
/// Wing and tail geometry constants used for converting forces to
/// dimensionless coefficients (non-dimensionalisation) and back.
///
/// Lives on the **aircraft root entity** as part of [`AircraftCoreBundle`].
///
/// Optional components (add separately to the root entity as needed):
/// - [`LodDamping`]: explicit damping for sparse-zone aircraft.
/// - [`InducedDrag`]: lift-induced drag for conventional aircraft.
/// Whole-aircraft angular-rate damping derivatives (LOD = Level of Detail
/// fallback).
///
/// Damping derivatives are coefficients that control how strongly the aircraft
/// resists rotation around each axis. Add this component to the aircraft root
/// when the zone layout is too sparse to produce realistic damping from
/// geometry alone (e.g. single-zone missiles, low-fidelity aircraft).
///
/// **Mutually exclusive with per-zone local alpha/beta**, when this component is
/// present, `compute_aero_forces`
/// evaluates all zones at the global alpha/beta (no rate corrections) and uses these
/// derivatives as the sole source of angular damping. When absent, per-zone
/// local angles run and damping emerges naturally from zone geometry.
///
/// # Non-dimensional form
///
/// **Damping moment = damping derivative × normalised angular rate × dynamic
/// pressure × wing area × reference length. The normalised rate (e.g. roll rate
/// × wingspan ÷ 2 × airspeed) is dimensionless, it compares rotational tip
/// speed to forward speed. Negative derivatives mean damping opposes motion.**
///
/// ```text
/// ΔL = Cl_p * (p * b / 2V) * q̄ * S * b roll damping (body X)
/// ΔM = Cm_q * (q * c̄ / 2V) * q̄ * S * c̄ pitch damping (body Y)
/// ΔN = Cn_r * (r * b / 2V) * q̄ * S * b yaw damping (body Z)
/// ```
///
/// All derivatives should be negative (damping opposes motion).
/// Typical light GA values (Nelson 1998, Table B1):
/// `Cl_p ≈ −0.45`, `Cm_q ≈ −12.0`, `Cn_r ≈ −0.12`.
/// Lift-induced drag model.
///
/// Induced drag is the extra drag caused by generating lift, because
/// wing-tip vortices redirect airflow downward behind the wing.
///
/// Add this component to the aircraft root entity to enable whole-aircraft
/// induced drag. See: induced drag, drag polar, Oswald efficiency.
///
/// **Omit this component** for:
/// - **Gliders**, induced drag is typically already embedded in the wing zone
/// CD tables from measured polar data.
/// - **Missiles and projectiles**, no significant spanwise lift distribution;
/// the bluff-body drag dominates.
/// - **Aircraft whose zone CD tables already include induced drag**, adding
/// this component would double-count.
///
/// **Include this component** for:
/// - Any conventional lifting aircraft whose zone CD comes from a 2-D profile
/// drag polar (JSBSim-style) that separates parasite and induced drag.
///
/// Induced drag coefficient = lift coefficient squared divided by
/// (pi * Oswald efficiency * aspect ratio):
///
/// ```text
/// CD_i = CL² / (π * e * AR), AR = b² / S
/// ```
///
/// Typical Oswald efficiency values: high-wing light aircraft 0.85-0.95,
/// low-wing monoplane 0.75-0.85, elliptical wing (ideal) 1.0,
/// delta/swept wing 0.6-0.75.