Improving Spleeft’s Barbell Velocity Algorithm with Real Data

Apple Watch attached to a bar during a field test with a linear encoder

To improve Spleeft’s bar velocity measurements, I collected recordings alongside a linear encoder during training with the Spanish BMX team in Paris. I rebuilt the iOS algorithm in Python and focused on detecting real rest periods and complete repetitions, where sensor noise could otherwise distort the result.

I started building Spleeft as a personal project while working in physical preparation. Programming helped me turn ideas from coaching into a tool for measuring bar velocity, and gave me a way to show what I could do beyond the gym.

As AI made programming more accessible, I began asking where I could make the greatest contribution. The answer was in the part that code alone could not solve: understanding the sensor data and making the measurements more reliable in real training. That question led to the algorithm project I want to share here.

Try Spleeft: Download Spleeft on the App Store to track barbell velocity with your iPhone or Apple Watch.

The bar velocity problem: drift and false pauses

The previous optimisation of Spleeft, which I described in the original data science article, was smaller in scope. I mainly focused on adjusting parameters of an existing algorithm and finding combinations that improved its performance.

That work was valuable, but after spending more time testing Spleeft in real training environments, I started to see a deeper problem.

The main difficulty was not simply calculating velocity.

It was knowing when a movement started, when it ended and when the device was genuinely still.

Spleeft uses accelerometer data. To calculate velocity, acceleration has to be integrated over time. This is mathematically elegant, but it also creates an unavoidable problem: even a small bias or error in the acceleration signal accumulates during integration and becomes velocity drift.

That drift can come from several sources:

  • sensor noise;
  • small changes in device orientation;
  • changes in the plane of movement;
  • integration error;
  • imperfect filtering;
  • vibrations from the athlete or the bar;
  • periods of low acceleration while the bar is still moving.

The last point is particularly important. Acceleration close to zero does not always mean that velocity is zero. It can also mean that the bar is moving at a relatively constant velocity.

Therefore, the real challenge was not simply to find “more zeros”.

It was to find better zeros.

A zero is a moment that can be used to recalibrate the integrated velocity signal. If the zero before a repetition is wrong, the integration starts from the wrong point. If a false zero appears inside a repetition, the movement can be cut or recalibrated too early.

Vertical velocity across four deadlift repetitions, showing the original recording in grey and the drift-corrected signal in teal
Four deadlift repetitions: the grey trace drifts away from zero between movements, while the corrected trace returns closer to zero during pauses.

This led to a new principle for the project:

First improve the quality of the rest-state detection and repetition segmentation. Then evaluate velocity.

Collecting bar velocity data in Paris

The first step was to obtain a reference device that could be used alongside Spleeft.

A recognised linear encoder had released a device capable of providing not only velocity, but also raw data that could be collected in a real training context. This was exactly what I needed.

During a concentration with the Spanish BMX team in Paris, I collected a large dataset while performing different exercises:

  • squats;
  • deadlifts;
  • power cleans;
  • squat jumps;
  • other mixed strength exercises.
Strength training data collection during the Spanish BMX team concentration in Paris
Collecting strength-training data during the Spanish BMX team’s concentration in Paris.

The measurements were collected simultaneously:

  • Spleeft recorded high-frequency accelerometer data, including sessions at up to 800 Hz;
  • the linear encoder recorded at approximately 100 Hz.

This was not a laboratory dataset collected under perfectly controlled conditions. That was intentional.

I wanted to understand what happened when the system was used in the environments where coaches would actually use it: with different exercises, different loads, different pauses, different movement strategies and different sources of noise.

The dataset also allowed me to compare two very different types of measurement.

The encoder measures movement along a more defined mechanical path. The Apple Watch or iPhone measures the forces acting on the device, the bar and, indirectly, the athlete. They do not see exactly the same signal.

That difference became one of the most important lessons of the project.

Rebuilding Spleeft in Python

Before optimising anything, I had to reproduce the existing iOS algorithm outside the application.

This sounds simple, but it was one of the most important parts of the whole process.

The production algorithm runs in Swift on iPhone and Apple Watch. The optimisation work, however, was much easier to perform in Python, where I could process large datasets, generate plots and test thousands or millions of parameter combinations.

The problem was that a Python approximation would not be enough.

If the Python version behaved differently from the Swift version, I would not be optimising Spleeft. I would be optimising a different algorithm.

So I developed a Python simulator that reproduced the main processing stages of the iOS implementation:

  1. reading the accelerometer and motion data;
  2. reconstructing velocity;
  3. detecting zero-velocity updates;
  4. compensating signal drift;
  5. segmenting repetitions;
  6. calculating mean velocity and other metrics.

I then validated the simulator against the Swift output. The objective was not to obtain a similar result, but to make sure that the same raw signal produced the same repetitions and practically the same metrics.

Only after this step could the optimisation become meaningful.

Looking beyond the original zero detector

The first version of the algorithm already included zero-velocity recalibration, but its logic was relatively simple.

It worked well in controlled situations. However, certain exercises exposed its weaknesses. Bench press and deadlift were particularly challenging because the device can experience additional movement while the athlete stabilises the bar.

I began investigating alternative zero-velocity detection approaches from the scientific literature and from related inertial-navigation applications.

Some of the ideas included:

  • filtered acceleration across multiple axes;
  • gyroscope information;
  • persistence requirements over consecutive samples;
  • movement energy;
  • drift-based checks;
  • conservative statistical detectors;
  • different thresholds for different states of the movement.

Not every idea worked.

For example, I explored a decision-tree-based inertial state classifier. It was a useful data science experiment, but its performance was not reliable enough to become a hard veto in the production algorithm.

This was an important distinction.

The project involved machine learning experiments and data science methods, but the final production solution was not a black-box model that simply classified every sample. The data science process helped me understand the signal, identify failure modes and design a more robust causal state machine.

The final system remained interpretable.

Searching through millions of possibilities

Once the simulator and the candidate detectors were available, I started running systematic parameter searches.

For each candidate configuration, the same raw signals were processed again. The parameters controlled aspects such as:

  • acceleration thresholds;
  • the minimum number of consecutive samples;
  • filtering behaviour;
  • movement-entry rules;
  • movement-exit rules;
  • the amount of evidence required before recalibration;
  • how the system handled transitions between movement and rest.

The search was not designed to find the configuration with the lowest velocity error against the encoder.

That would have been too narrow.

The first objective was to identify the combination that best detected genuine zero-velocity periods while avoiding false zeros during active movement.

The evaluation followed a cascade:

  1. Were the effective zeros detected correctly?
  2. Were repetitions segmented and counted correctly?
  3. Once the first two conditions were acceptable, how close were the velocity metrics to the external reference?

This order matters.

A repetition with a velocity close to the encoder is not necessarily a correctly measured repetition if its start or end was defined by a false zero.

The numbers were only part of how I judged each experiment. I kept the raw recordings and the resulting velocity traces visible, then inspected them against movements I had seen in my own training and in tests with my athletes. When there was an obvious pause, I could see whether the algorithm brought velocity back to zero. When a repetition was still moving, I could spot a false correction. Those simple visual checks often told me more about the next change to make than another error score.

A state machine for movement

One of the main architectural improvements was adding a state machine to complement zero detection.

The algorithm now reasons about the movement as a sequence of states rather than treating every sample independently.

In simplified terms, it moves through states such as:

  • searching for the beginning of movement;
  • movement detected;
  • searching for the end of movement;
  • confirming a real post-movement rest;
  • recalibrating the signal.

This structure helps prevent isolated sensor events from immediately changing the interpretation of the repetition.

For example, a short period of low acceleration during a moving bar should not automatically be interpreted as rest. The system needs additional evidence: the direction of the signal, the persistence of the event and the broader movement context.

The state machine also allowed me to separate two ideas that had previously been too closely connected:

  • detecting whether the bar is moving;
  • deciding whether the integrated velocity can be recalibrated.

This was especially useful because a movement state can remain active even when acceleration is temporarily close to zero.

What the encoder could—and could not—tell me

I used the encoder as an external reference, but not as an unquestionable ground truth.

For every repetition, I processed the encoder data using a comparable methodology rather than simply copying the metrics exported by its proprietary algorithm. This reduced the influence of differences between the encoder’s internal processing and Spleeft’s processing.

Even then, the encoder was treated as a reference, not an absolute standard.

Different devices have different filters, delays, detection rules and mechanical constraints. The exported signal may also not be exactly the same signal used internally to calculate every metric.

This is why I decided not to define success simply as:

“The Spleeft value is close to the encoder value.”

Instead, I looked for an algorithm that was internally consistent, detected repetitions correctly and behaved robustly across different exercises and recording conditions.

The encoder helped me identify errors and investigate difficult cases. It did not replace critical thinking.

Testing the algorithm with real user data

After the laboratory experiments, I went back to data collected outside the controlled sessions.

Some of the most useful files came from Spleeft users who had shared examples of cases where the application had produced an unexpected result.

These files were valuable because they contained the problems that appear in real life:

  • imperfect pauses;
  • unexpected bar vibrations;
  • slow repetitions;
  • different attachment positions;
  • changes in technique;
  • noise before or after the repetition;
  • exercises that do not behave like a squat.

I ran the new algorithm over these historical datasets and compared its behaviour with the previous implementation.

This stage helped reveal an important principle: improving the algorithm does not mean making it more complicated at any cost. It means making the logic better adapted to the physical reality of the sensor and the exercise.

That experience also shaped the latest Spleeft update. Accelerometer measurements have limitations, even after careful optimisation, so I wanted coaches to be able to inspect the underlying recordings and judge whether a result is trustworthy in their own setting.

Testing on a €40 Apple Watch SE

I also wanted to test the new algorithm on an actual Apple Watch rather than relying only on Python simulations.

To keep the project aligned with Spleeft’s original philosophy, I bought a second-hand Apple Watch SE for approximately €40. It was one of the least expensive models capable of running the application and processing the signal in real time.

Apple Watch attached to a bar during a field test with a linear encoder
Apple Watch mounted on the bar alongside the encoder during a field test.

This was more than a practical test.

Spleeft has always been built around the idea that velocity-based training should be accessible. If a new algorithm only worked on the most expensive device or in a perfect laboratory environment, it would not fit the purpose of the project.

During the field testing, I compared two placements:

  • the watch on the athlete’s wrist;
  • the watch attached directly to the bar.

This showed how important sensor placement can be.

In deadlifts and bench press, the movement of the athlete’s wrist can introduce additional noise. The athlete is holding and stabilising the bar, so the sensor is not only measuring the bar’s vertical movement. It is also measuring small movements from the hand, wrist and body.

Placing the watch directly on the bar reduced some of this noise.

This does not mean that the bar position is always the best option, or that the wrist position is incorrect. It means that the best algorithm also needs to respect the limitations of the hardware and the way the device is being used.

No amount of data science can completely compensate for a poor measurement setup.

What changed in Spleeft’s algorithm

The new algorithm has moved beyond beta. Its real test is how consistently it works across different exercises, devices and training environments. I want coaches to be able to judge that for themselves.

I also want to be clear about what happens behind the number: Spleeft uses detected rest periods to limit velocity drift and a state machine to identify repetitions. We tested those decisions against recorded sessions and external devices. I am sharing the approach while keeping the exact parameters private.

What I learned

This project taught me that a useful velocity metric depends on more than a clever algorithm. It depends on the sensor, the exercise, the quality of the data and the decisions made at every step. AI helped me explore and build faster, but coaching experience was essential for deciding which problems mattered.

Spleeft is still a personal project shaped by that curiosity. I will keep testing it in real training and sharing what I learn.

 

share this post:

Leave a Comment

Your email address will not be published. Required fields are marked *

You may also be interested in

en_GB