Gusts
What the server computes
Section titled “What the server computes”With gusts: "dryden", the server runs a gust model of its own and sends SITL the result. Every SYSTEM_TIME message, 20 times a sim second, it advances three random processes from the current height and airspeed, adds the gust to the mean wind, and sets SITL’s SIM_WIND_SPD, SIM_WIND_DIR and SIM_WIND_DIR_Z. SITL’s own turbulence, SIM_WIND_TURB, is set to zero.
The model is the low-altitude form of the Dryden turbulence model in MIL-F-8785C. Three gust components, along the mean wind (u), across it (v) and vertical (w, up positive), are each a first-order random process with a strength σ and a length scale L. With h the height in feet, held between 3 m and 1000 ft:
| Strength | Length | |
|---|---|---|
| w | σw = 0.1 × mean wind | Lw = h |
| u | σu = σw / (0.177 + 0.000823 h)0.4 | Lu = h / (0.177 + 0.000823 h)1.2 |
| v | σv = σu | Lv = Lu / 2 |
Near the ground the horizontal gusts are stronger and much longer than the vertical one, and every length grows with height. Each length becomes a time constant at the current speed, τ = L / V with V the larger of airspeed and mean wind (frozen turbulence: the aircraft flies through a fixed pattern of air). The model is Dryden-type rather than Dryden exactly: the true v and w filters are second order, and here all three are first order.
wind_history from a hover near 10 m in an 8 m/s mean wind, gusts: "dryden", seed 7. The gust is what the server adds to the mean wind before sending SITL itsSIM_WIND_* values every tick.The other two settings are simpler. "off" sends a steady wind once. "sitl" hands turbulence to SITL’s own SIM_WIND_TURB, set to 0.1 × mean wind × scale, which is close to white noise at SITL’s physics rate, with no length scales and no dependence on height.
Why the exact update
Section titled “Why the exact update”A first-order random process with time constant τ and strength σ (an Ornstein-Uhlenbeck process) has an update that is exact at any step size. With a = Δt / τ and φ = e−a:
xk+1 = φ xk + σ √(1 − φ²) nk, nk ~ N(0, 1)
Its stationary variance is σ² whatever Δt is. That matters here because Δt is not small next to τ near the ground: Lw equals the height, so at 3 m and 15 m/s the vertical time constant is a fifth of a second, against ticks a twentieth of a second apart.
The gust model this package inherited used the forward Euler form instead:
xk+1 = (1 − a) xk + σ √(2a) nk
Its stationary variance V satisfies V = (1 − a)² V + 2a σ², which gives
V = σ² / (1 − a/2)
So the Euler gusts are too strong by a factor that depends on the step, and the update diverges outright once a passes 2, where |1 − a| > 1. For the vertical channel at 3 m:
| Speed | Δt | a | Euler σ / target |
|---|---|---|---|
| 5 m/s | 0.05 s | 0.083 | 1.022 |
| 5 m/s | 0.10 s | 0.167 | 1.044 |
| 15 m/s | 0.05 s | 0.25 | 1.069 |
| 15 m/s | 0.10 s | 0.50 | 1.155 |
| 15 m/s | 0.50 s | 2.50 | diverges |
At the server’s 20 Hz ticks that is 2 to 7 % too much vertical gust near the ground, more for a fast aircraft, and the u and v channels, with lengths several times longer, much less. A simulation of 400 000 steps of each form agreed with the formula within one percent. The exact form costs the same arithmetic, so it is the default.
method: "euler" keeps the old form. It draws the same random numbers in the same order as the code it came from, so a harness can move onto this model, reproduce its earlier runs number for number, and re-baseline on exact when it chooses.
Repeating the same air
Section titled “Repeating the same air”A seed seeds the model’s random number generator. Real SITL delivers SYSTEM_TIME on an exact 20 Hz sim clock, so two flights with the same seed see the same tick times, draw the same numbers and meet the same gusts. That is what makes a gusty A/B test fair: change one parameter, fly the same seed, and the air is identical. The gusts still depend on height and airspeed, so two flights that diverge in altitude feel the same random sequence scaled to where each one is.
scale multiplies the gust (not the mean wind), up to 5, for a rougher day without changing its character. The step size is capped at half a second, so a long gap between ticks cannot produce one enormous jump.
Seeing what was flown
Section titled “Seeing what was flown”Every snapshot carries the gust now and the SIM_WIND_* values SITL was last given, and wind_history returns up to two minutes of both at whatever resolution you ask. Because the model runs in the server rather than inside SITL, the record of what the aircraft flew through exists without digging it out of the dataflash log.