Skip to the content
FixTheRobot Explore Robotics / UAV / Module 8 / M8-T4

UAV Systems Engineering · Module 8

M8-T4: SIL, HIL and ground testing

Find each defect at the cheapest level that can expose it, and gate the move upward on evidence.

  • Lesson 4 of 18
  • Safety, Verification and Flight Testing
  • Established engineering
  • About 6 minutes to read

Flight tests are expensive, risky and slow; SIL runs are free. A good test strategy puts each class of defect where it is cheapest to find, and uses entry criteria so that a vehicle only leaves the bench when the bench has nothing more to say. The matrix of defects against levels also shows what only flight can reveal.

Learning objectives

After this lesson, you should be able to:

  • Describe the purpose and limits of each test level.
  • Define entry criteria for moving from one level to the next.
  • Design fault-injection tests per level and know where each fault can be injected.
  • Build a defect-class by test-level coverage matrix and find what only flight can test.

Conceptual explanation

Established The staged approach is standard in aerospace and robotics testing. Details (which levels exist, which gates apply) depend on the programme; the table is a typical pattern, not a prescription.

undefined
LevelWhat runs for realGood at findingCannot find
Unit / componentOne function or moduleLogic errors, numerical bugs, edge casesIntegration and timing issues
SIL (software-in-the-loop)Full software stack, simulated worldSystem logic, failsafe sequences, regressions, statistics over many runsHardware, timing on target, sensor realism not modelled
HIL (hardware-in-the-loop)Flight controller and companion hardware, simulated worldTiming and load, drivers, wiring, boot, integrationReal sensors, vibration, aerodynamics
Ground testWhole vehicle, props off or restrainedCalibration, sensor health, power, thermal, link range, kill switch, vibration spectraFlight dynamics, real navigation performance
Tethered / constrained flightWhole vehicle, mechanically limitedController stability, first estimator behaviour, thrust marginLarge excursions, failsafe outcomes
Free flightEverything in the real environmentReal performance, environment-specific failuresNothing is hidden, but failures are costly

Fault injection belongs at every level: at SIL and HIL by altering the simulated sensor stream or the message flow (dropouts, freezes, biases, noise bursts); on the ground by disconnecting sensors or links; in flight only for faults whose consequences are bounded by the safety design (a pilot ready to take over, a geofence).

Test levels and gatesEvidence is gathered at progressively more realistic levels: unit, software-in-the-loop, hardware-in-the-loop, ground tests with the real vehicle, tethered flight, free flight. Each level has entry criteria from the previous one and a stated purpose.Unit / componentlogic, mathSILclosed loop, modelsHILreal targetGroundreal sensors, props offFlighttether, then freeEntry criteria prevent expensive failures: do not go up a level with a defect the lower level can find.
Levels and gates. Each gate is a list of evidence, not a date.
Animation of one hundred defects passing through four test stages, software in the loop, hardware in the loop, ground test and flight test. The defects are coloured by class: logic, timing, sensor interface and environment. Each stage has a different chance of detecting each class, so the defects caught by software-in-the-loop are mostly logic errors, timing errors appear with hardware in the loop and environmental ones only on the ground or in flight. A counter shows the defects remaining after each stage.
Detection probabilities per class and stage are illustrative; the point is that no single environment finds everything, so the stages are complementary, and each defect escaping a stage is more expensive to fix in the next. Seeded random draws against the table shown. (Looping, about 5 seconds; drawn and computed for this course with illustrative values.)

Engineering intuition

The cost of finding a defect rises by about an order of magnitude per level. A sign error found in a unit test costs minutes; the same error found in HIL costs hours; on the ground days; in flight, possibly the vehicle. So the discipline is to ask, for every flight test: could this have been found lower? If yes, add the missing lower-level test before flying.

The reverse is also true: some things only flight reveals (vibration coupling into the IMU at specific throttle, wind gust response, lighting changes). The matrix tells you which defect classes have no cheaper level, so you plan flight time for them deliberately instead of hoping to meet them.

Mathematical formulation

A simple expected-cost model chooses how much to test at each level. If a defect class has occurrence probability qq, and test level ll detects it with probability dld_{l} at cost clc_{l} (incurred whether or not it is found), and an escape to the next level costs more by a factor of flf_{l}, then the expected cost of finding and fixing at the first detecting level is

Expected cost over a sequence of test levels
E[cost]=q∑l(∏j<l(1−dj))dl Fl+∑lclE[\text{cost}] = q\sum_l\left(\prod_{j<l}(1 - d_j)\right) d_l\,F_l + \sum_l c_l
Fl is the cost of fixing a defect found at level l.

With dld_{l} typically high at lower levels for logic defects and zero for environment-specific ones. The cumulative detection probability after levels 1…LL is 1−Π(1−dl)1-\Pi (1-d_{l}); with independent detection probabilities of 0.9, 0.6 and 0.5 it is 1 − 0.1·0.4·0.5 = 0.98. Escapes that reach flight are the product of the non-detections, which is why raising the lowest-cost level’s detection rate has the biggest effect on the total. Treat the probabilities as engineering judgement informed by history; they are prioritisation aids, not measurements.

dld_{l}
probability that level ll detects the defect class.
clc_{l}
cost of executing level ll.
FlF_{l}
cost of fixing a defect found at level ll.

Architecture and data flow

Code change → unit tests in CI → SIL regression (many seeded scenarios) in CI → HIL bench test on a rig (nightly or per release) → ground test checklist on the vehicle → tethered flight → free flight per test card. At each level the result is stored with the baseline ID; the entry criteria for the next level read those results automatically (all required tests pass on this baseline, no open critical defects, traceability coverage complete).

Real-world UAV applications

  • Planning the test campaign for a new navigation algorithm.
  • Deciding what must be verified before the first outdoor flight.
  • Defining the SIL regression suite that gates merges.
  • Organising fault-injection tests across levels.

Implementation example

This runs as shown. A defect-class by level matrix with detection probabilities (illustrative judgement values), the cumulative detection, the classes that only flight can find, and a gate checker for entry criteria.

import numpy as np
levels = ['unit', 'SIL', 'HIL', 'ground', 'tether', 'flight']
detect = {  # defect class -> probability of detection at each level (illustrative engineering judgement)
 'frame / unit error':           [0.50, 0.90, 0.60, 0.50, 0.80, 0.90],
 'failsafe logic error':         [0.20, 0.85, 0.80, 0.60, 0.30, 0.80],
 'timing / overload on target':  [0.00, 0.00, 0.90, 0.40, 0.50, 0.70],
 'sensor driver / wiring fault': [0.00, 0.00, 0.70, 0.90, 0.80, 0.80],
 'vibration coupling into IMU':  [0.00, 0.00, 0.00, 0.60, 0.70, 0.90],
 'wind / aerodynamic limit':     [0.00, 0.10, 0.00, 0.00, 0.30, 0.90]}
for k, d in detect.items():
    cum = 1 - np.cumprod(1 - np.array(d)); first_cheap = next((levels[i] for i, c in enumerate(d) if c >= 0.5), 'never')
    print(f"{k:>28}: first level with detection >= 0.5: {first_cheap:>6}; cumulative before flight {cum[-2]:.2f}, after flight {cum[-1]:.2f}")
flight_only = [k for k, d in detect.items() if max(d[:-1]) < 0.5]
print("classes with no pre-flight level at >= 0.5 (plan flight time for these):", flight_only)
assert flight_only == ['wind / aerodynamic limit']
results = {'unit': 'pass', 'SIL': 'pass', 'HIL': 'pass', 'ground': 'fail', 'tether': 'not run'}
def gate(next_level):
    need = levels[:levels.index(next_level)]; blockers = [l for l in need if results.get(l) != 'pass']
    return ('OPEN', []) if not blockers else ('CLOSED', blockers)
print("gate to tether:", gate('tether'), "| gate to HIL:", gate('HIL'))
assert gate('HIL')[0] == 'OPEN' and gate('tether') == ('CLOSED', ['ground'])
Detection probabilities by level and a gate checker. The probabilities are illustrative judgements, not data.

Common engineering mistakes

Skipping levels under schedule pressure

A defect SIL would have found now costs a vehicle.

SIL with ideal sensors only

Inject noise, bias, dropouts and latency that match real data.

Treating HIL as a flight rehearsal

It tests the target and integration, not sensors and dynamics.

Entry criteria as dates

Gate on evidence: tests passed on this baseline, defects closed.

No fault injection on the ground

Pull the sensor connector in a safe test and see what happens before it happens in the air.

Failure modes

Failure modes, symptoms and causes
Failure modeHow it shows upLikely cause
First flight crashes from a logic errorA defect that SIL could exposeNo SIL scenario for the failure case
Timing overruns only appear in flightLoad differs from the benchHIL load unrepresentative; test with full sensors and logging
Calibration surprises outdoorsCompass or camera mismatchGround test not done in representative conditions
Regression after a minor changePreviously working behaviour brokeNo automated SIL regression suite

Debugging approach

  1. For every flight defect, ask which level should have caught it and add the test there.
  2. Keep a defect log with the level of discovery and the level it should have been found.
  3. Check HIL timing with the full flight load.
  4. Review the gate results before each move up.

Practical exercises

  1. Fill the defect-by-level matrix for your project with probabilities and justify two entries.
  2. Define the entry criteria list for the first free flight of your navigation system.
  3. Design five SIL fault-injection scenarios for GNSS loss and VO failure.
  4. Compute the cumulative detection before flight for a defect class with detection probabilities 0.7, 0.5, 0.4 at SIL, HIL and ground.

Interview questions

Write an answer in your own words, then reveal the model answer. Nothing is sent anywhere.

Question 1

Why test at several levels?

Model answer

Cost to find a defect rises steeply with each level; lower levels find logic and integration defects cheaply, while only flight reveals some environment-dependent ones. The staging puts each defect class where it is cheapest to find.

Question 2

What is the purpose of an entry criterion?

Model answer

To require evidence that the lower level has nothing more to find (tests passed on this baseline, defects closed) before taking the risk and cost of the next level.

Question 3

What can HIL not find?

Model answer

Real sensor performance, vibration, magnetic and optical environment effects and flight dynamics: those need ground and flight tests.

References and further reading

Primary papers, official documentation and standards. Each claim above that is specific to a tool or version points here.

What’s next

Mark this lesson

Saved in this browser and synced to your account when you are signed in.

Next lesson

M8-T5: Flight-test planning

Plan staged flight tests with test cards, entry and abort criteria, instrumentation and safety measures.