`PhaseConfig`
One phase of an movement + its outgoing transitions. The atom of the rule-based rep counting path.
class PhaseConfig { final String id; final String name; final PhaseType type; final List<String> trackingPoints; final PhaseDuration duration; final List<PhaseTransition> transitions;}Example
A squat’s down phase, transitioning back to up:
const downPhase = PhaseConfig( id: 'down', name: 'Down', type: PhaseType.transition, trackingPoints: ['left_knee', 'right_knee'], duration: PhaseDuration(min: 0, max: 5000), transitions: [ PhaseTransition( toPhase: 'up', conditions: [ PhaseCondition( trackingPoint: 'left_knee', operator: ConditionOperator.gt, value: 160, ), PhaseCondition( trackingPoint: 'right_knee', operator: ConditionOperator.gt, value: 160, ), ], ), ],);The phase enters when the previous phase’s transition fires. While
the user is in this phase, the runtime evaluates every transition’s
conditions per frame. When all conditions of ANY transition are
satisfied (AND across conditions, OR across transitions), the
machine moves to that transition’s toPhase.
Fields
id
Stable identifier, unique within the movement. Referenced from
repDetection.phases, phaseAlternatives, formRules.appliesToPhase,
and the Studio’s selected-phase state.
name
Display name for the Studio + consumer UIs.
type
PhaseType.transition, most phases. The user is expected to move through this phase as part of the cycle.PhaseType.rep, marks the boundary phase (used by some rep detectors).PhaseType.hold, the user is expected to PAUSE in this phase. Drives theholdrep-detection strategy.
trackingPoints
IDs of channels relevant to this phase. The Studio uses this as a UI hint (“which measurements affect this phase?”) and doesn’t affect runtime evaluation (the form service references rules directly).
duration
class PhaseDuration { final int min; // milliseconds final int max; // milliseconds}min, minimum hold time before any transition can fire. Useful forholdphases (“hold the plank for 5 seconds”).max, force a transition when exceeded. Prevents the user from getting stuck in a phase if they pause mid-rep.
Defaults to (min: 0, max: 5000).
PhaseTransition
class PhaseTransition { final String toPhase; final List<PhaseCondition> conditions;}A transition fires when ALL conditions are satisfied. To express OR logic, add multiple transitions with disjoint condition sets, the phase machine picks the first one whose conditions match.
PhaseCondition
class PhaseCondition { final String trackingPoint; final ConditionOperator operator; final dynamic value; // number or [min, max] for `between` final int? holdTime; // optional ms}Operators
| Operator | Compares | value shape |
|---|---|---|
gt | tracking value > threshold | number |
lt | tracking value < threshold | number |
eq | tracking value ≈ threshold (±2°) | number |
between | tracking value ∈ [min, max] | [number, number] |
holdTime
When set, the condition must remain satisfied for this many milliseconds before the transition fires. Use to prevent flicker on noisy frames or to require the user to actually pause at the position.
The phase state machine
PhaseStateMachine is the runtime
that walks phaseConfigs. Initialised once per loaded movement,
ticked once per frame:
machine.initialize(movementConfig);
for (final frame in frames) { machine.update(trackingValues);}
machine.currentPhaseId; // stringmachine.completedReps; // intmachine.onPhaseChanged.listen(…); // PhaseChangeEvent streammachine.onRepCompleted.listen(…); // RepCompletedEvent streamMovementTracker owns the state machine, you don’t need to drive
it yourself unless you’re writing a non-tracker consumer.
Studio authoring
In PoseFlow Studio, phases are the first thing a trainer adds.
See the Studio phases page for the
authoring workflow + the _PhaseTile UI (border highlights when
a phase is the live-detected one + when a sequence is in progress
through it).
Read next
MovementTrackingPoint, the channels phase conditions reference.RepDetectionConfig, how phases compose into rep counting.- Rep counting, the two paths.
- Phase config spec.