← Blog
·6 min read·David Lampon

The GPS Data Gap: Why My Telemetry Was Out of Sync

developer-journalgpxdebuggingcyclingtechnical

Building SportsSync — Part 7

The Bug That Wouldn't Make Sense

The demo from last episode was 80% working. You could load a YouTube video, upload a GPX file, pick a synchronization point on the map, and see telemetry overlays update as the video played. But something was wrong: the data drifted.

At the sync point — the moment I crossed under a highway overpass — everything lined up perfectly. The map showed the right location, the speed matched the video. But as I scrubbed backward to where I was stopped at a traffic light, the speed showed 16 km/h. I was stationary in the video. The data said I was moving.

The further from the sync point, the worse the drift. Forward through the ride, the data would suddenly show impossible speeds on climbs. Backward, it showed movement during stops. The synchronization was broken, but only at a distance from the anchor point.

Following the Trail Into the GPX File

I opened the raw GPX file in VS Code. A GPX is just XML — verbose compared to JSON, but readable. Each track point contains latitude, longitude, elevation, timestamp, and Garmin-specific extensions like heart rate, cadence, and temperature.

The timestamps told the story. Scrolling through the data, most points were exactly one second apart: 07:08:53, 07:08:54, 07:08:55. Then suddenly: 07:10:10 jumped to 07:10:25. Fifteen seconds of data, gone.

The GPS Configuration Explains Everything

My cycling coach Edu provides a setup guide for all his athletes' GPS devices. Buried in the configuration instructions was the answer: cadence recording is set to exclude zeros.

When you stop pedaling — at a traffic light, during a descent, coasting — the GPS marks cadence as zero. With the "exclude zeros" setting, the device simply doesn't record those moments. No cadence data means no track point. Fifteen seconds at a red light becomes a gap in the timeline.

The device is optimized for training analysis, where idle time is irrelevant. But for video synchronization, every second matters. If the video shows you stopped at a light for 15 seconds but the GPS track has no data for those 15 seconds, the timeline compresses. Everything after the gap shifts earlier, and the drift compounds with each stop.

The Fix: Fill the Gaps

The solution was conceptually simple: after parsing the GPX file, scan for temporal gaps and fill them with interpolated data points.

For each pair of consecutive track points, if the time difference exceeds one second, generate intermediate points — one per second — copying the position, elevation, and other data from the last recorded point. The logic: if you're stopped, your position doesn't change, your elevation doesn't change, your speed is zero. Heart rate might drift, but we accept that approximation.

I explained this to Lovable in conversational terms, and it implemented the gap-filling algorithm in the GPX parser. After loading the same file, the timeline was now continuous — every second accounted for, gaps filled with stationary data points.

The Debugging Process With AI

What struck me about this debugging session was the process itself. With traditional development, I would have:

  1. Noticed the drift
  2. Added console.log statements throughout the sync logic
  3. Stepped through the code with a debugger
  4. Eventually traced it to the GPX parser
  5. Opened the raw file and spotted the gaps
  6. Written the fix

With Lovable, the process was different. I couldn't easily add breakpoints or step through code. Instead, I had a conversation:

"Can you show me how the GPX data is structured internally?" — Lovable explained the data model.

"I've noticed temporal gaps in the GPX file. Can you confirm this happens?" — Lovable confirmed and explained why.

"I need the internal data structure to have a point for every second. Can you fill the gaps?" — Lovable implemented it.

The conversational debugging was slower for this specific problem but more educational. I understood the why before writing the how. In traditional debugging, you often fix the symptom without fully understanding the cause.

What I Learned About GPS Data

Some technical details that matter for anyone working with GPX files:

Speed isn't stored in GPX. It's calculated from consecutive coordinates and timestamps. This means speed accuracy depends entirely on having consistent, frequent position data. Gaps in recording create artificial speed spikes — the device calculates distance over a longer time interval, producing an averaged (and wrong) speed.

The Haversine formula is used to calculate distance between GPS coordinates on a sphere. The GPX parser already had this implemented correctly. The issue wasn't calculation — it was missing input data.

GPS recording intervals vary. Most cycling computers default to one-second intervals, but the "smart recording" mode on some devices only records when something changes. For SportsSync, we need every-second recording. This will need to be a documented requirement for users.

Heart rate during gaps is approximate. When we fill gaps with the last recorded values, heart rate is the least accurate metric — it changes continuously even when stationary. For an MVP, this is acceptable. A more sophisticated solution would interpolate heart rate between known values.

UI Improvements Along the Way

Between episodes, I also refined the overlay design. The CSS gauges went from basic text spans to something closer to the Safa Brian aesthetic — speed prominently at the bottom, heart rate and cadence on the side, with smoother transitions between values (updating every 100ms instead of every second to reduce the robotic stepping effect).

The map blinking issue was also fixed — previously, every scrubber movement caused the entire map to reload. Now it smoothly pans to the new position without re-rendering the tile layer.

Fine-Tuning Controls

One practical UX issue became obvious during testing: the sliders are too imprecise for synchronization. With a 14-minute video and a 19,000-point GPS track, a tiny mouse movement jumps hundreds of data points. I need step buttons — plus and minus controls that advance by exactly one unit — for both the video timestamp and the GPS track position. This is the difference between "close enough" and "frame-perfect" synchronization.

Where We Are

The gap-filling fix should resolve the drift problem for most cases. There might be other sources of desynchronization — clock drift between the camera and GPS device, variable frame rates, or edge cases in the interpolation logic — but the biggest offender was the missing data points.

Next session: verify the fix works across the full ride, clean up the wizard UX into a single-page layout, and start thinking about how to present this demo on the landing page. The goal is still the same — let a visitor try it with their own data and understand the product in seconds.

Create cycling shorts with GPS telemetry

Upload your video, sync your GPX data, and generate ready-to-share shorts in minutes.

Try SportsSync — early access