Main:
This major update refactors the entire application from a single monolithic HTML file into a modern, modular JavaScript architecture for improved maintainability, performance, and future extensibility.
Alongside the refactoring, this commit introduces a completely overhauled synchronization engine and several quality-of-life improvements.
Key changes and new features include:
- **Modular Architecture**: The application is now split into distinct, decoupled modules for state management (`state.js`), DOM manipulation (`dom.js`), synchronization (`sync.js`), file parsing (`fileParsers.js`), and UI components (`p5/radarSketch.js`, `modal.js`, etc.).
- **Robust Synchronization Engine**:
- The core playback loop in `sync.js` now correctly applies the manual time offset, ensuring accurate synchronization between the video and radar data during playback.
- Fixed a bug where fast scrubbing with the timeline slider could leave a persistent drift while paused. The fix uses the video's `seeked` event for a reliable, event-driven UI update.
- **Enhanced User Experience**:
- Added a new feature allowing users to press 'Enter' in the offset input box to instantly resync the video to the current radar frame, which significantly streamlines the manual calibration process.
- **Improved Debugging Tools**:
- The advanced debug overlay's drift calculation is now "offset-aware," providing an accurate representation of the true synchronization status during both playback and seeking.
2.) feat(visualization): Add advanced overlays and robust large-file streaming
This commit introduces several major features and critical bug fixes to the visualizer, significantly enhancing its analytical capabilities and performance.
The primary focus was on adding more detailed visualization overlays from the Kalman filter and implementing a robust solution for handling very large JSON files that were previously crashing the application.
### New Features
- **Covariance Ellipse Overlay:**
- A "Show Covariance" checkbox has been added to the UI.
- When enabled, the visualizer now draws the 95% confidence ellipse for each track's predicted position, derived from the `covarianceP` matrix. This provides a real-time view of the Kalman filter's positional uncertainty.
- **Predicted vs. Corrected Position Markers:**
- A "Show Predicted Position" checkbox has been added.
- This feature displays the filter's raw prediction (red cross) alongside the final corrected position (blue cross), making it easy to visualize the predict-correct cycle and analyze the filter's behavior during object acceleration or maneuvers.
### Bug Fixes & Performance Enhancements
- **Fix: Marker for Lost Tracks:**
- The main track marker (blue cross) now correctly disappears if its `correctedPosition` is null for a given frame. This provides a clear and intuitive visual cue that a track has been temporarily "lost" and is coasting on predictions alone.
- **Fix: Large JSON File Parsing (Streaming & Web Worker):**
- Resolved a critical "Maximum call stack size exceeded" error that occurred when loading JSON files larger than ~30MB.
- The entire file loading and parsing pipeline has been refactored to use a Web Worker. This moves the CPU-intensive parsing off the main UI thread, preventing the page from freezing.
- The worker streams the file and uses a lightweight parser (Clarinet.js) to build the data object, ensuring low memory usage and a responsive interface.
- **feat: Add Progress Bar for File Loading:**
- To provide feedback during the new streaming process, a progress bar is now displayed in the modal, showing the real-time progress of the file parsing operation.
Body:
This commit introduces a new advanced debugging overlay to help diagnose synchronization issues and fixes three core timing bugs that caused data streams to be misaligned.
Advanced Debug Overlay:
A new "Show Advanced Debug" toggle has been added to the UI. When enabled, it displays critical synchronization diagnostics in real-time, including:
Video vs. Target Radar timestamps
The calculated "Drift" in milliseconds between the two
Absolute start times for video and radar recordings
The currently applied offset
This provides a precise tool for manually calibrating the offset and verifying sync accuracy.
Synchronization Fixes:
The previous implementation suffered from several race conditions and logical errors in its time management:
Speed Graph Misalignment: The ego speed line on the graph was plotted using raw radar timestamps, ignoring the video offset. This has been corrected to use the offset-adjusted timestampMs, aligning it with the CAN data.
Playback Drift: The main animation loop was incorrectly applying the time offset a second time during playback, causing the radar visualization to lead or lag the video. The redundant offset calculation has been removed from the animationLoop.
Seeking Inaccuracy: When scrubbing the timeline, the UI would update the CAN speed using a stale videoPlayer.currentTime value due to the asynchronous nature of video seeking. The logic in updateFrame now uses the precise, calculated target time for the update, ensuring the EGO and CAN speed indicators match perfectly during seeks.
These changes result in a significantly more robust and verifiable synchronization between the video and radar data feeds.
Moves the main animationLoop function from index.html into a dedicated src/sync.js module.
This change isolates the core playback, clock management, and video resynchronization logic into a single, focused file.
The main script in index.html now imports and calls this function, simplifying its responsibilities and preparing for the final wiring step.
This commit resolves three persistent bugs that were identified during the refactoring of the file parsers and UI modules.
1. Fixed Cache Loading Race Condition
Problem: On page load, the application would try to process cached JSON data immediately. If the cached video file hadn't finished loading its metadata yet, the videoStartDate would be null, causing a getTime of null error in the JSON parser and preventing the visualization from loading.
Solution: The application's startup logic in DOMContentLoaded has been rewritten. A new processAllData function now contains all the data parsing logic. This function is now called exclusively as a callback to the video player's onloadedmetadata event. This guarantees that all data processing (for JSON and CAN logs) only happens after the video is ready and a valid videoStartDate is available.
2. Fixed Speed Graph Theme Not Updating
Problem: The speed graph's background, grid, and data lines are drawn to a static buffer for performance. When the theme was changed, the setTheme function would call .redraw() on the sketch, but this would only re-display the old buffer with the old theme's colors. The buffer itself was not being regenerated.
Solution:
The drawStaticGraphToBuffer function within the speedGraphSketch was made public by attaching it to the p5 instance (p.drawStaticGraphToBuffer).
The setTheme function in src/theme.js was updated to explicitly call this new public function. It now forces the speed graph to generate a new static buffer with the correct theme colors before redrawing.
Imported the videoPlayer element into theme.js to prevent a ReferenceError when checking its properties.
3. Fixed p5.js Canvas Resizing Error
Problem: When the browser window was resized, both p5 sketches would throw a TypeError because the code was attempting to call .resize() on the static graphics buffers (staticBackgroundBuffer and staticBuffer), which is not a valid function.
Solution: The windowResized functions in both sketches were corrected. Instead of trying to resize the existing buffer, the code now creates a brand new, correctly-sized buffer using p.createGraphics() and immediately redraws the static content (axes, gridlines, etc.) onto it.
Refactored the modal and theme-switching functionality out of the main script.
- Created src/modal.js to handle all logic for the confirmation modal.
- Created src/theme.js to manage the dark/light theme and canvas redraws.
- The main script now imports and initializes these modules, cleaning up the global scope.