Battery health
The drone agent watches every battery pack the flight controller reports and turns the rawBATTERY_STATUS stream into a health view: per-cell
voltages with the weakest cell called out, pack voltage and current,
consumed capacity and energy, temperature, a time-to-reserve estimate
and a set of anomaly rules. The engine runs inside ados-control on
the drone, so the same result reaches Mission Control, the on-box
dashboard and the REST API.
Battery health is a drone profile feature. It needs a flight controller
that sends BATTERY_STATUS (ArduPilot and PX4 both do). The agent
advertises it with the battery.health capability.
How it works
Every 500 ms the engine reads the latest vehicle state. A new sample is ingested only when the state actually changed, and nothing is ingested while the flight controller link is down. Each pack is tracked by its MAVLink batteryid. Up to 8 distinct packs
are tracked; a ninth new id is ignored. When the flight controller sends
no BATTERY_STATUS at all, the engine builds pack 0 from the
SYS_STATUS battery fields.
For each pack the engine keeps up to 300 seconds of samples (600 at
2 Hz), the live anomaly set and the last 100 raise and clear events.
Cells and pack voltage
A cell array is plausible when it is non-empty and every value is between 2.5 V and 4.5 V. Some flight controllers put the whole pack voltage into the first cell slot (a 4S pack shows up as a single 16.8 V “cell”). That array is implausible, so for that sample:- no cell rule runs (
cell_critical,cell_low,cell_divergence); - the pack reports
cells_plausible: false; min_cell_v,max_cell_v,divergence_mvandweakest_cell_indexarenull.
voltage_v) is chosen in this order:
- The sum of the cells, when the cells are plausible.
- The single reported value, when exactly one value is present.
- For pack
0only, theSYS_STATUSbattery voltage.
voltage_v is null. For pack 0,
remaining_pct falls back to the SYS_STATUS remaining value when the
pack itself does not report one.
Anomaly rules
The rules run on every new sample, in this order.dt is the time
since the previous sample of the same pack.
Each anomaly carries the measured
value and the threshold it was
compared with, in the same unit:
Clearing
An anomaly clears with a 5 second hold. When a rule stops firing, the anomaly stays in the live list withcleared_at_ms set. If the rule
fires again inside 5 seconds the stamp is removed and the anomaly
carries on as the same event. If 5 seconds pass with no re-fire, the
anomaly is removed and a cleared entry is added to the history. This
stops a pack that sits right on a threshold from flapping.
Time to reserve
The prediction uses the samples inside the lastpredictive_window_s
seconds. It needs at least 2 samples spanning at least 1 second;
otherwise the state is idle with every number null.
The engine computes the drop rate in percent per second from the
remaining-capacity change across the window:
eta_s is (remaining - reserve) / drop rate, rounded to whole
seconds. mean_current_a is the mean absolute current over the same
window.
Configuration
Thebattery: block in /etc/ados/config.yaml holds the thresholds.
Every value is an integer. A value outside its range, or a
critical_cell_mv that is not below low_cell_mv, falls back to its
default and the agent logs a warning.
The engine checks the config file every tick and reloads the block when
the file changes, so a threshold edit takes effect without a restart.
Where to see it
Mission Control
Open the drone, switch to the Agent tab, and pick Battery under the Node section. The page has two views:- Live: one card per pack with the cell bar (weakest cell highlighted), voltage, current, consumed mAh and Wh, temperature, the time-to-reserve strip, active anomalies and recent history. A pack with implausible cells shows “Per-cell data not reported by the FC” in place of the cell bar.
- Setup: the threshold fields from the table above.
On-box dashboard
On the drone’s own web dashboard, open Settings and pick Battery (listed under System and safety, drone profile only). It shows the same live pack cards and the threshold fields, and saves to the samebattery: block.
REST API
200. Example response:
Pack fields:
Log events
Every raise and final clear is written to the node log as abattery.anomaly event from ados-control, with the fields rule,
pack_id, state (raised or cleared), value and threshold. A
raised critical anomaly logs at error, a raised warning at warn, and
a clear at info.
With the Black Box store turned on, query them
with: