Assessment schema
Every processed sortie produces assessment.json. The API returns it as assessment in GET /api/sorties/{sid}. Distances are meters, speeds m/s, angles degrees, times seconds from the first frame.
Top level#
| Field | Type | Description |
|---|---|---|
status | string | complete or rejected |
sortie_id | string | Sortie identifier |
meta | object | Upload metadata: pilot, receiver, tail, camera, date, data source, model release tag, marking |
platform | object | The allow-list decision: platform, template scores, when it was decided |
summary | object | Headline results (below) |
categories | object | One entry per scored category |
events | array | Detected events in time order |
inputs | object | How pilot inputs relate to the motion, when telemetry has them |
controls | object | Control surface and stick estimates per source, and their agreement |
series | object | Time series at the analysis rate |
tracking | object | Track quality and the 6-DoF track |
security | object | What the sanitizer did and the banner applied |
products | object | File names of the videos and charts |
processing_s, video_duration_s, version | number, number, string | Timing and software version |
A rejected sortie has only status, sortie_id, meta, decision, reason, processing_s and version. No imagery or derived product is kept.
summary#
{
"overall_score": 53.0,
"grade": "Debrief required", // Proficient | Needs refinement | Debrief required
"contacts": 1,
"contact_time_s": 30.2,
"phase_durations_s": {"approach": 12.4, "precontact": 1.8, "closing": 9.0, "contact": 30.2, ...},
"peak_closure_mps": 1.12
}
categories#
{
"closure": {"score": 0.0, "value": 1.12, "unit": "m/s peak closure near contact", "weight": 0.25},
"alignment": {"score": 89.4, "value": 2.2, "unit": "deg RMS from boom centerline", "weight": 0.2},
"stability": {"score": 20.8, "value": 0.74, "unit": "m RMS position scatter in contact", "weight": 0.2},
"envelope": {"score": 100, "value": 100.0,"unit": "% of contact time in ideal zone", "weight": 0.25},
"procedure": {"score": 60.0, "value": 1.8, "unit": "s stabilized at pre-contact", "weight": 0.1,
"notes": ["pre-contact stabilization 1.8 s < 3 s"]}
}
Values in these examples are illustrative. The unit string changes when no contact was made, so always display it with the value.
events#
[
{"t": 13.3, "type": "precontact_stabilized", "severity": "info", "detail": "Stabilized in the pre-contact position"},
{"t": 30.1, "type": "excessive_closure", "severity": "critical",
"detail": "Closure 1.30 m/s near contact (limit 1.20)", "closure_mps": 1.3}
]
type is one of precontact_stabilized, contact, disconnect, high_closure, excessive_closure, overshoot, envelope_warning, envelope_limit, vertical_oscillation, breakaway. severity is info, warning or critical. Some events carry extra measured fields.
series#
Parallel arrays at the analysis rate (10 Hz by default): t, phase, contact, moment_score (null outside scored phases), geometry such as closure rate and offsets from the contact point, envelope coordinates and margin, and roll_deg, pitch_deg, yaw_deg.
tracking#
| Field | Description |
|---|---|
analysis_hz, samples | Analysis rate and sample count |
valid_fraction | Share of samples with a trusted fit |
median_iou | Median silhouette fit quality |
pos_sigma_m_median | Median position uncertainty |
active_windows_s | Time windows where a receiver was present and analyzed |
boom_source | Where the boom geometry came from: image or telemetry |
pos, vel | The 6-DoF track's position and velocity per sample |
security#
sanitization counts frames processed, masked, blurred and written; metadata_stripped and frames_outside_presence_windows_discarded are always true; banner is the marking stamped on the frames; settings records the sanitizer configuration that produced the products. Release state and custody live in custody.json, served by the security routes.