What ArduPilot SITL catches, and where it stops telling the truth
This post is also available in Korean.
A bug found on a laptop costs an afternoon. The same bug found in the air costs an aircraft. Here is what ArduPilot SITL actually proves, and the four places where a green simulation run means nothing.
SITL runs the firmware, not a model of it
This is the part that makes SITL worth the setup, and the part most people skip past.
Software In The Loop does not simulate an approximation of your flight controller. It compiles the real ArduPilot source for a sitl target and runs it as a native process. The same scheduler, the same EKF, the same mode transitions, the same failsafe logic that will run on the flight controller runs on your desktop. What gets replaced is the physics and the sensor drivers, not the code under test.
So when a mode transition misbehaves in SITL, that is your bug. Not a modelling artifact.
Getting a vehicle flying takes one command after the initial setup:
git clone --recurse-submodules https://github.com/ArduPilot/ardupilot
cd ardupilot
./Tools/environment_install/install-prereqs-ubuntu.sh -y
./Tools/autotest/sim_vehicle.py -v ArduCopter --console --map
The first run builds the firmware with waf and takes a few minutes. Every run after that starts in seconds. You get a MAVProxy console, a map, and a copter sitting armed-and-ready at the default location.
Talk to it the way the companion computer will
MAVProxy is convenient, but it is not the point. The point is that the companion computer — in my case a Jetson — should talk to the simulated vehicle over exactly the interface it will use on the real airframe.
SITL exposes the flight controller's serial ports as TCP sockets:
| Port | Maps to | Typical use |
|---|---|---|
| 5760 | SERIAL0 | console, MAVProxy attaches here |
| 5762 | SERIAL1 | companion computer |
| 5763 | SERIAL2 | second link |
Point pymavlink, MAVSDK, or your own MAVLink code at tcp:127.0.0.1:5762 and it speaks the same protocol it will speak over a UART later. The offboard control logic you write against SITL is the offboard control logic you fly.
For multiple vehicles, -I 1 shifts the whole port block by ten, so instance 1 lands on 5770 and up. That is how you get a swarm on one laptop without a second machine.
Break things on purpose
This is what SITL is actually for. Not watching a copter fly a mission — it will fly the mission — but watching what it does when something goes wrong at the worst moment.
ArduPilot exposes a family of SIM_* parameters that inject faults at runtime. You set them from the MAVProxy console while the vehicle is flying:
param set SIM_WIND_SPD 12
param set SIM_WIND_DIR 270
param set SIM_RC_FAIL 1
Wind, GPS loss, RC failsafe, battery sag, individual motor failure, barometer dropout — each one is a parameter you can toggle mid-flight and watch the response. Failure handling is the part of a flight stack that never gets exercised in normal testing, and it is the part that decides whether you get the aircraft back.
Check the names against your own build. The
SIM_*parameter set moves between ArduPilot releases — the GPS simulation parameters in particular were reworked, and older tutorials reference names that no longer exist. Runparam show SIM_*on the version you are actually running rather than trusting any blog post, this one included.
Faster than real time, and headless
SITL runs the firmware in lockstep with the physics model, which means the vehicle's clock is driven by the simulation rather than by wall time. Speeding the whole thing up does not corrupt the timing the code sees:
./Tools/autotest/sim_vehicle.py -v ArduCopter --speedup 10 --no-mavproxy
A mission that takes twenty minutes of flight takes two. Drop MAVProxy and it runs headless, which is the shape you want for CI. ArduPilot's own test suites run this way:
./Tools/autotest/autotest.py
Once your control logic runs unattended against a scripted scenario, regression testing a flight stack becomes an ordinary software problem.
Where SITL stops telling the truth
Now the part that matters more than everything above, because a green SITL run is easy to over-read.
1. The sensors are too polite. A real IMU on a real airframe sees frame resonance, motor harmonics, and aliasing from a badly placed flight controller. SITL's default noise model does not reproduce any of that. You cannot tune a notch filter in simulation, and vibration problems — one of the most common causes of a bad flight — are invisible here.
2. The timing is desktop timing. A laptop core running one process is not an H7 running the full sensor, logging, and telemetry load. Scheduler overruns that show up on real hardware under real load may never appear in SITL.
3. The EKF gets clean data. GPS multipath near buildings, magnetic interference from power wiring routed too close to the compass, a barometer that drifts when the sun hits it — these are the failure modes that actually bring aircraft down, and by default they are not in the model. You can inject a GPS outage. Injecting a plausible bad GPS fix is much harder.
4. Nothing is loose. No connector backs out under vibration. No ESC desyncs. No propeller is out of balance. No solder joint cracks on the third flight of the day.
So the honest summary is this: SITL proves your logic. It does not prove your aircraft. A clean simulation run is permission to do a tethered hover test, not a flight-readiness certificate. What it buys you is that by the time you are standing in a field, the bugs you are looking for are physical ones — and those are the only kind you cannot find at a desk.
Summary
- SITL runs the actual ArduPilot firmware, so bugs it finds are real bugs.
- Connect your companion computer to
tcp:127.0.0.1:5762and develop offboard control against the same MAVLink interface you will fly. SIM_*parameters inject wind, GPS loss, RC failsafe, and motor failure at runtime — verify the names on your own build.--speedupplus--no-mavproxymakes flight-stack regression testing a normal CI job.- Vibration, real-hardware timing, dirty sensor data, and mechanical failure are all outside the model. Do not read a green run as more than it is.
SITL's built-in physics is enough for control logic. It is not enough the moment the perception stack needs something to actually look at — which is where an external simulator comes in. That is the next post.
Comments
Post a Comment