last_year_project: The Fitness Coach That Thinks in Angles, States, and Timers

A deep dive into an AI exercise system that keeps pose tracking local, turns motion into finite-state logic, and uses simple math to do surprisingly disciplined coaching.

8 to 10 min read View on GitHub More from Pritipaudel

A user sits in front of a laptop camera while pose landmarks and angle arcs are overlaid on their body. On the other side of the composition, the motion is translated into a clean chain of exercise states, showing how raw movement becomes a counted rep.
The project’s core idea is not recognition alone. It turns live motion into a rule-based coaching pipeline that can decide when a rep starts, peaks, and ends.
Key Takeaways

A workout coach that never guesses

The most interesting thing about last_year_project is not that it sees a body. It decides what that body is doing, frame by frame, with a chain of explicit rules. A curl only counts when the angle, the timing, and the posture all agree.

That makes the system feel less like an AI demo and more like a control loop. Webcam motion comes in noisy. The software smooths it, measures it, classifies it, and only then decides whether to speak, count, or warn.

The project’s pipeline is simple in the best way. Landmarks feed angles, angles feed smoothing, smoothing feeds thresholds, and thresholds trigger state transitions.

Why the math matters more than the model

The geometry choice is the first clue that this repo values stability over spectacle. Instead of relying on a more fragile angle trick, it uses vector dot products and arccos to keep joint angles in a predictable 0 to 180 degree range. That matters when an elbow flexion curve should not suddenly flip because a webcam frame jitters.

// Stable joint angle calculation
function calculateAngle(a: Point, b: Point, c: Point): number {
  const ab = { x: a.x - b.x, y: a.y - b.y };
  const cb = { x: c.x - b.x, y: c.y - b.y };

  const dot = ab.x * cb.x + ab.y * cb.y;
  const magAB = Math.hypot(ab.x, ab.y);
  const magCB = Math.hypot(cb.x, cb.y);

  const cosine = dot / (magAB * magCB);
  const angle = Math.acos(Math.min(1, Math.max(-1, cosine)));

  return angle * (180 / Math.PI);
}

// EMA smoothing reduces frame-to-frame jitter
smoothed = alpha * current + (1 - alpha) * previous;

That math gets paired with exponential moving average smoothing, which is doing more work here than a casual reader might expect. Webcam pose estimates wobble. A rep counter cannot afford to wobble with them. Smoothing turns raw signal noise into something the thresholds can trust.

A close-up mechanical drawing shows two bone-like segments forming an elbow with a clean measured arc between them. A jittery waveform in the background is being flattened into a smoother line, illustrating how noisy pose data is stabilized before it becomes a coaching decision.
This is the real foundation of the app. Stable angle math and smoothing turn noisy webcam input into a signal that can be judged reliably.

Movement becomes a state machine

This is where the repo stops being a pose tracker and becomes a rule engine. The curl tracker does not ask whether the model thinks the arm looks like a curl in some vague sense. It waits for a sequence: extended, curling_up, peak, lowering_down. That sequence is what makes the rep count feel disciplined instead of approximate.

The same pattern appears in the other trackers. Tree pose is not just a snapshot of balance. It is a progression through phases, with timers, leg switching, and completion logic that make the exercise legible to the machine.

QuestionState-machine approachTypical opaque fitness AI
How a rep is representedA named sequence of thresholds and phasesA learned score or confidence output
When feedback happensAt explicit transitions and timer gatesWhenever the model emits a response
How cheating is handledRules such as body swing or incomplete extensionOften folded into a single confidence drop
What the user can inspectThe state and the trigger are visibleThe decision is harder to explain
Where it works bestConstrained movements with clear form criteriaBroader scenarios with less deterministic motion

That difference is subtle but important. A state machine is narrower than a model, but it is also more honest. If the exercise has clear phases, the software can say exactly why a rep counted or failed.

The browser is the backend for feedback

The architecture keeps the hard part local. The frontend owns the camera, pose model, smoothing, and rep logic. The backend handles the things that benefit from persistence: accounts, schedules, exercise records, and doctor-patient coordination. In practice, that means the user gets immediate feedback without shipping every frame to a server first.

DimensionBrowser-side exercise engineCloud-heavy fitness AI
LatencyImmediate local feedbackDepends on network and server round trips
PrivacyVideo can stay on deviceVideo often traverses a remote service
CostMore device work, less server loadMore backend infrastructure and inference cost
Failure modeNarrow, deterministic, explainableBroader, but harder to debug
User trustEasier to reason about what happens locallyRequires more confidence in the service pipeline

What it gets right, and what it gives up

The tradeoff is obvious once you look at the architecture honestly. A deterministic system is strong when the movement is constrained and the rules are well chosen. It is weaker when the motion is messy, the camera is poor, or the exercise does not fit the predefined state machine.

That is not a flaw so much as a boundary. The project is choosing repeatability over generality. It will almost always be better at a narrow exercise than a vague all-purpose coach, because it knows exactly what kind of motion it is trying to measure.

That last point is easy to miss. The project is not just counting. It is curating feedback. Prioritized cues, calibration frames, and distance-normalized checks all point to the same design instinct: reduce noise until the user can actually act on what the system says.

Why this architecture feels durable

The repo’s strongest quality is not novelty. It is discipline. Angle math instead of guesswork. Smoothing instead of jitter. Thresholds instead of vibes. Those choices add up to software that can explain itself, which is rare in fitness products and even rarer in AI products.

That is why last_year_project feels more durable than a flashy demo. It treats human movement as something that can be modeled, checked, and improved in software without pretending the model has magic intuition. The result is a coach that feels specific enough to trust.