Problem 605034 · hard · Level 06 Heuristics & Optimization

Design the Drone's Altimeter Filter

Kalman filter · sensor fusion · outlier rejection · control input · tuning · estimation error

A delivery drone holds and changes altitude on the orders of its autopilot, and needs to know its height above the ground. Its barometric altimeter is noisy and, worse, now and then simply wrong. Your estimator turns its readings into an altitude estimate. Every 0.05 seconds the simulator calls

estimator(t, command, reading) -> altitude estimate (m)

with the time t in seconds (0, 0.05, ..., 19.95), the vertical acceleration command (m/s²) the autopilot asked for over the last interval (0 at t == 0), and the altimeter's reading (m), or None when it gave nothing.

The drone. It starts at rest at an unknown height between 8 and 15 m, and the autopilot keeps it roughly between 5 and 20 m. Between calls its vertical speed v and altitude h move on by one step of

v = v + 0.05 * (command + gust - 0.4 * v)        0.4 * v is air drag
h = h + 0.05 * v

where gust is an unknown wind push that changes slowly (it keeps 90 % of its value each step plus a random kick; typically about 0.3 m/s²). The commands come from a flight plan of hovers, climbs, drops and hops with accelerations of 1 to 3 m/s².

The altimeter. A good reading is the true altitude plus noise with standard deviation 0.5 m (variance 0.25), rounded to 0.01 m. About 5 % of the calls get None, and about 4 % get a faulty reading that is 3 to 15 m too high or too low.

The flight lasts 20 s (400 calls). Each test calls fly_drone(estimator, seed) (defined for you; try it with Run), which returns a summary such as

{"rms_error": 1.1769, "max_error": 6.038, "sensor_rms": 2.49, "faulty_readings": 21, "missing_readings": 23}

for the plain filter described under the scoring rules, on seed 1. Your function may keep state in global variables; t == 0 marks the start of a new flight.

How this problem is scored

  • The error of a flight is the RMS difference between your estimates and the true altitude over all 400 calls.
  • A test passes when that error is at most 0.75 times the RMS error of the readings themselves (sensor_rms, over the readings that were not None).
  • Its quality is 50 * log10(12 / error), kept between 0 and 100: an error of 1.2 m scores 50, and every halving of the error adds 15 points (0.12 m would score 100).
  • A plain one-number Kalman filter (a random walk with q = 0.05, r = 0.25) averages about 55. A filter that rejects faulty readings reaches the high 80s, and one that also uses the commands the low 90s.

Constraints

  • return a number every call; the result must not depend on the clock, and each call should take well under a millisecond
  • numpy is available but not needed

Goals

  • Build an altitude estimator that runs live, one reading at a time, and survives missing and faulty readings
  • Tune the balance between trusting the model and trusting the sensor by its measured error
  • Improve on a plain filter with an innovation gate and a model that uses the known commands
Starting Python…