motion_result.hpp¶
MotionResult — the per-motion result line, as data + one formatter.
This header declares 2 types (15 members) and 2 free functions.
Extracted from include/shulib/diag/motion_result.hpp — this page is that header's documentation, reformatted, so it cannot disagree with the code. Prose about how to think about the API lives in the user guide; worked recipes live in the cookbook; this page is the complete, mechanical list of what exists.
Contents¶
enum class MotionOutcomeSettledTimedOutCancelledFaultAbortSupersededUnsetmotionOutcomeName— free functionstruct MotionResultidnameoutcomeabortFaultdurationhasPathDatafinalPoseovershootdriftemitResultLine— free function
enum class MotionOutcome¶
§18.4's motion exit-reason codes, at the BOUNDARY level (header note). WIRE-STABLE: explicit values, append-only, pinned by test.
enum class, declared at include/shulib/diag/motion_result.hpp:57.
MotionOutcome::Settled¶
arrived within tolerances — the ✓ case
enumerator, declared at include/shulib/diag/motion_result.hpp:58.
MotionOutcome::TimedOut¶
the watchdog fired first
enumerator, declared at include/shulib/diag/motion_result.hpp:59.
MotionOutcome::Cancelled¶
stopped by the caller (user cancel / panic stop)
enumerator, declared at include/shulib/diag/motion_result.hpp:60.
MotionOutcome::FaultAbort¶
the scheduler's fault policy forced the stop (causal code attached)
enumerator, declared at include/shulib/diag/motion_result.hpp:61.
MotionOutcome::Superseded¶
pre-empted: a newer motion took the slot
enumerator, declared at include/shulib/diag/motion_result.hpp:62.
MotionOutcome::Unset¶
No producer has written this field yet. APPENDED (value 5, append-only per the enum rule above) and made the DEFAULT, because the previous default was Settled — the one value meaning success — so a result line whose producer forgot the field rendered "✓ SETTLED" for a motion that never happened. That is the opposite polarity to this same struct's hasPathData, which defaults false precisely so over/drift render "n/a" rather than a fabricated 0.00. There was no value to give the field until this one.
enumerator, declared at include/shulib/diag/motion_result.hpp:69.
motionOutcomeName¶
§18.4 spelling for the line. Never null; out-of-range renders, never crashes.
free function, declared at include/shulib/diag/motion_result.hpp:73.
struct MotionResult¶
One finished motion's result, as the boundary saw it (a value type; the motion-layer glue builds it from CompletedMotion — motion/run_reporter.hpp).
struct, declared at include/shulib/diag/motion_result.hpp:87.
MotionResult::id¶
the command id it ran under
field, declared at include/shulib/diag/motion_result.hpp:88.
MotionResult::name¶
IMotion::name() (stable literal)
field, declared at include/shulib/diag/motion_result.hpp:89.
MotionResult::outcome¶
How the motion ended. Drives the glanceable pass/fail column — only Settled renders ✓ — and decides whether abortFault is meaningful (it is rendered iff this is FaultAbort). Defaults to Unset, the pessimistic value: a record whose producer forgot this field renders "✗ UNSET" rather than the checkmark and SETTLED it used to claim.
field, declared at include/shulib/diag/motion_result.hpp:94.
MotionResult::abortFault¶
causal code iff FaultAbort
field, declared at include/shulib/diag/motion_result.hpp:95.
MotionResult::duration¶
end − start
field, declared at include/shulib/diag/motion_result.hpp:96.
MotionResult::hasPathData¶
record stream flowed (header note)
field, declared at include/shulib/diag/motion_result.hpp:97.
MotionResult::finalPose¶
estimate at the boundary (always real)
field, declared at include/shulib/diag/motion_result.hpp:98.
MotionResult::overshoot¶
see header; valid iff hasPathData
field, declared at include/shulib/diag/motion_result.hpp:99.
MotionResult::drift¶
|final heading error|; valid iff hasPathData
field, declared at include/shulib/diag/motion_result.hpp:100.
emitResultLine¶
Format + log the §18.3 result line (one [MOT] Info line; byte shape pinned by test). ✓ marks SETTLED; every other outcome is ✗ — a glanceable pass/fail column. FAULT_ABORT carries its causal code: "✗FAULT_ABORT=ODO_STUCK".
free function, declared at include/shulib/diag/motion_result.hpp:106.
Design commentary, from the header¶
The header opens with the reasoning behind these shapes. It is reproduced here in full because a reference that only lists signatures teaches nobody why.
The header’s own reasoning — 40 lines
MotionResult — the per-motion result line, as data + one formatter (§18.3/§18.4;
WS13, chunk C5). The second idea salvaged from the legacy "logging extreme" code,
rebuilt the §18 way: STRUCTURED FIELDS a formatter renders, never an essay
emitted from a motion loop.
Target shape (§18.3, byte-pinned by test/motion_result_test.cpp):
[t= 12.50] [MOT] MoveToPose#7 ✓SETTLED final( 24.1, 36.0, 90.1°) over 0.20" drift 0.1° 1.16s
The line rides log() as [MOT]-tagged Info text (the FaultLatch precedent), so it
lands in the tick stream exactly where the motion ended, in exact §18.3 shape.
── The outcome vocabulary is §18.4's, verbatim ─────────────────────────────────────
§18.4 names the motion exit-reason codes: SETTLED / TIMEOUT / CANCELLED /
FAULT_ABORT / SUPERSEDED. control::ExitReason deliberately carries only the first
three verbs plus Running — the scheduler's BOUNDARY knows more than the motion
does (a Cancelled exit whose cause was the fault policy is FAULT_ABORT; one whose
cause was pre-emption is SUPERSEDED). This enum is that boundary vocabulary,
wire-stable like FaultCode's (explicit values, append-only, pinned by test).
diag/ cannot name motion-layer types (dependency leaf), which is exactly why the
RESULT vocabulary — not the motion vocabulary — lives here.
── Numbers must be TRUE (the brief's constraint 3) ─────────────────────────────────
hasPathData says whether the record stream actually flowed for this motion (it
does not with NullSink, and a motion cancelled in the boot window never had a
live estimate). When false, over/drift render "n/a" — the line NEVER fabricates
a 0.00 it has no data behind. finalPose is always real (the scheduler reads the
estimate at the boundary). The reported values are the ESTIMATE's story; the C5
tests bound estimate-vs-truth divergence across all three drivetrains so "what
the motion believed" provably tracks "what the motion did".
Semantics of the two derived quantities (computed by the scheduler's stats sink):
* over (inches): how far the robot pushed PAST its target — max projection of
(measured − target) onto the start→target direction, floored at 0. For a
stationary-target motion (turn/hold: |target − start| < ~0.1"), the direction
is undefined, so it degrades to max |measured − target| (worst wander from
the point) — the honest analogue.
* drift (degrees): |final heading error| — how far the heading ended from the
target heading (the §18.3 sample's "drift 0.1°").
Last updated 2026-08-15 — published from the main release branch, commit fa545ff. This site tracks releases, so between them it can lag the repository — that lag is deliberate, and it is what keeps the development log off the public site. For the current state of the code, see the repository.