metrics — the metric CATALOG (what is measured)
Purpose
The schema anchor-tree that defines, for every logged signal, what is measured: its
variable
name,deltamethod (how a raw signal becomes an error),unit, group label,reductions, and
includeflags. It is the what, not the judgment — the pass/fail gates live in
scoreboard. Single source of truth for what the pipeline catalogs and how it reduces each signal.
Structure
The file is one big YAML inheritance tree: a default_global anchor (&metric-default) seeds defaults
that nested anchors and leaf specs override via <<: merge. Top-level sections:
default_global— root defaults (continuous,log_desired,reductions,unit,find_norm,cc_frame, adeltasub-block,include).state— raw plant state (coord→x);find_norm: false.tracking_error— the error signals:com(p_c/v_c),base(z_b/omega_b),arm(p_e/z_e/nu_e). Anchors split position / lin_vel / pointing / ang_vel defaults.control_effort— actuator forces/torques/wrenches, each in a coordinated-control (cc_frame: true) and actuator (cc_frame: false) form.guidance— reference-side signals:comprogress/alpha,targetingmode + step-event counters + scorer score terms +tgt_x.inspection— coverage outcomes:area_coverage_frac,unique_triangles(reduced atfinal).diagnostics— guidance offsets/raw refs, controller demand, andconditioning(derate_fraction/s_min_J,gamma_scale,kappa_J,v_sat).
Key knobs/sections
Load-bearing fields (point at the YAML for the exhaustive leaf list):
| key path | what it controls | default / example | note |
|---|---|---|---|
default_global (&metric-default) | root defaults every leaf inherits via <<: | include: true, find_norm: true, reductions: null | YAML merge keys (<<:) build the whole tree; edit anchors, not leaves, to move a default |
<leaf>.variable | the logged signal key the spec binds to | p_e, z_b, s_min_J | a leaf missing variable: raises loudly in the loader (reject_missing_variable) |
<leaf>.reductions | scalar reductions cataloged for the signal | [max, rms, final, p95, p99] | drawn from the Reductions enum in data_analyzer; most reduce |x| (see footgun) |
<leaf>.delta.method | how a raw signal becomes a per-step error | step, angle_step, jump, change | step=finite diff; angle_step=angle-aware step for pointing; jump=raw jump; change=discrete-mode change count |
error.pointing (&z-default) | routes error through the versine 1 − cos θ | true for z_b/z_e | NOT the chord, NOT angle_between — see measurement contract |
<leaf>.include | whether the metric is cataloged on by default | anchors set false; arm p_e/z_e/nu_e override true | default_pointing is include: false at the anchor; arm/base pointing re-enable selectively |
<leaf>.unit | display/units string | m, m/s, Nm, normalized, null | unitless metrics must read "" not NaN downstream (pivot-drop footgun) |
cc_frame | coordinated-control vs actuator frame of a wrench | true (f_c, tau_b_oplus) / false (f_b, tau_b) | distinguishes the circumcentroidal reduced wrench from the actuator command (breve_controller) |
derate_fraction.threshold | frac_below floor on s_min_J for the throttle-share metric | 0.025 | mirrors controller.arm.null_space.freeze_floor — keep in sync when the controller floor is tuned |
Who reads it
- pre_run_loader —
MetricSpecLoader.walk_metric_specswalks the tree, inheriting parent context;default_globalseeds the defaults each leaf overrides. - metric_catalog — spec accessors +
catalog_by_key(lazy{variable: spec}index) over the loaded catalog. - data_analyzer —
SignalAnalysis/DataSummaryread fields off a spec object (theReductions/Deltasenums it drives by string). - logger — completeness is checked against scoreboard, not this full catalog (catalog metrics are config-conditional).
- parameter_loader — loads the raw YAML to a
RecursiveNamespace; dot-access, never raw-YAML reasoning.
Footguns
metrics.yaml ≠ scoreboard.yaml — separate concerns
This file is the variable catalog (what is measured). scoreboard is the judgment layer
(how it is judged: reduction, direction, gate, weight,after:startup window).MetricSpecLoader
andScoreboardSpecLoaderare their respective parsers — do not put a gate here.
(analysis/INSIGHTS.mdpre_run_loader [config])
One-in-one-out edit policy; no hardcoded strings
User-maintained to prevent cruft. Standing policy: retire at least one old metric for every new
addition. No hardcoded strings belong here. (YAMLs_by_domain/INSIGHTS.mdmetrics.yaml [config])
v_sat/v_maxis NOT a catalog threshold
v_sat(velocity-saturation flag) is derived per-step viadata_analyzer.saturation_series, NOT
stored at catalog level. The matchingv_maxthreshold lives on the run-spec sweep entry, not
here — adding it to the schema is a footgun. (YAMLs_by_domain/INSIGHTS.mdmetrics.yaml [io])
derate_fraction.thresholdmust track the controller floorIts
0.025mirrorscontroller.arm.null_space.freeze_floor(the speed-throttle floor). The two
values must stay in sync when the controller floor is tuned. (YAMLs_by_domain/INSIGHTS.mdmetrics.yaml [config])
Pointing is the versine; reductions abs-map
pointing: trueroutes through the versine1 − cos θ, not the raw vector difference. Separately,
every reduction EXCEPT theis_signedmembers reduces\|x\|— soMAX = max\|x\|butMINis a
signed minimum. (YAMLs_by_domain/INSIGHTS.mdmetrics.yaml [config]; data_analyzer magnitude footgun)
Related
scoreboard · pre_run_loader · metric_catalog · data_analyzer · logger · parameter_loader · breve_controller · robot · current_sota · terminology