Skip to content

Conditions

The Conditions panel is where you turn a measurement channel into a rule: “during the down phase, left_knee must be between 70° and 110°.”

The row UI

For each enabled channel × selected-phase combination, the Conditions panel renders one row:

┌─────────────────────────────────────────────────────────────┐
│ ● Left knee [angle] │
│ │
│ Current: 92° │
│ Min: [ 70 ]° Max: [ 110 ]° [Snap to current] │
│ │
│ ░░░░░░░██████████████████████████████░░░░░░░░░░░░░░░░░ │
│ ↑ │
│ live value (green/red ball) │
│ │
│ ⚙ Cue: "Bend your knees deeper" ⚠ warning onViolation │
│ ▸ Δ from phase entry | ▸ Bucket overrides │
└─────────────────────────────────────────────────────────────┘

Min/max number inputs

Numeric TextFields clamped to the channel’s slider bounds with decimal precision matched to the kind (whole degrees for angles, 2 decimals for ratios/distances/position, etc.).

Authoring is typically:

  • Type the numbers if you know the target range (“I want 70° to 110°”).
  • OR tap Snap to current to capture the live value as the centre + the kind’s default tolerance (e.g. angles snap with ±20°, ratios with ±0.10).
  • OR open the bucket overrides for per-angle variants.

Range bar + ball

The visual indicator. The bar shows the rule’s range (green when the live value is in, red when out). A 20px-diameter ball pins the live value on the bar so trainers can see compliance from across the room, sized intentionally large after trainer feedback (“can’t see it from 2m back”).

Snap to current

One-click shortcut that:

  1. Captures the current live value for this channel.
  2. Sets min = current - defaultTolerance, max = current + defaultTolerance, tolerance is kind-aware (AngleDefinitions defines per-channel defaults).

The fastest authoring flow:

  1. Get into the phase position.
  2. Hit Snap to current.
  3. Verify the ball is green at that position + red when you move away. Adjust if needed.

Cue editor

Per-condition feedback authoring:

  • Cue text: what the host UI surfaces when the rule fires. Free-form short string.
  • Trigger: when the cue fires:
    • onViolation (default), when compliance flips out-of-range.
    • onCompliance, when the user moves BACK into range (positive reinforcement).
    • always, every frame the condition evaluates.
  • Severity: info, warning, error. Drives the toast deck colour + filter.

Optional, leave blank and the condition still gates the phase transition + contributes to the form score, just without a trainer-authored cue.

Δ from phase entry toggle

For movements where what matters is the CHANGE from the start of the phase (e.g. “vertical hip displacement during a jump”), flip this on. The emitted TrackingPoint gets relativeToBaseline: true and the runtime emits current - baseline_at_phase_entry instead of the raw value.

The condition range then applies to the delta. So min: 0.1, max: 0.3 on a baseline-relative hip_center_y during the “jumped” phase means “hip moved 0.1 to 0.3 normalised units upward from the moment the jump phase started”.

Bucket overrides

For view-dependent measurements (camera-frame angles), the same condition can have DIFFERENT ranges per camera bucket. Expand the Bucket overrides section to author per-bucket bands.

The default range you set lives at the “authoring target” bucket (controlled by the Camera angles panel’s selected cell). Switch the authoring target to a different bucket, retune, the same condition row now stores two bands (one per bucket). At runtime the form service picks whichever bucket the live detector identifies. See camera buckets.

What the conditions produce

Each row maps to TWO entries in the .pose file:

  1. A PhaseCondition on the outgoing transition of the current phase. The condition gates the transition: when the live value is in range, the transition fires (along with any other conditions on the same transition).
  2. A FormRule with the same channel + range, scoped to appliesToPhase: currentPhaseId. The form rule drives feedback events + compliance scoring.

Multiple rows on the same phase contribute multiple PhaseConditions to the same transition (AND across them) and multiple FormRules (each evaluated independently).

Compliance dot vs feedback event

The live RAG dot on the row reflects the current compliance (red = out, green = in). The feedback event (cue → host UI) fires only when compliance FLIPS in the direction the trigger specifies, so a continuously-out-of-range condition doesn’t spam events, it fires once on each new violation.