Skip to content

Telemetry recording and replay with pointing math refactor#411

Open
mrosseel wants to merge 14 commits into
brickbots:mainfrom
mrosseel:telemetry
Open

Telemetry recording and replay with pointing math refactor#411
mrosseel wants to merge 14 commits into
brickbots:mainfrom
mrosseel:telemetry

Conversation

@mrosseel
Copy link
Copy Markdown
Collaborator

Summary

  • Add telemetry recording and replay system (telemetry.py, telemetry_list.py UI, menu entries)
  • Extract pointing math and telemetry into separate modules from integrator.py (slims integrator from ~600 lines to ~335)
  • Enhance telemetry with raw IMU data, target tracking, replay fixes
  • Add integrator drift integration tests and telemetry unit tests

Test plan

  • nox -s unit_tests passes (includes new test_telemetry.py and test_integrator_drift.py)
  • nox -s lint passes
  • nox -s type_hints passes
  • Record a telemetry session on real hardware and verify replay produces matching pointing output
  • Verify integrator behavior unchanged against a known session (regression check after pointing extraction)

🤖 Generated with Claude Code

mrosseel and others added 12 commits March 5, 2026 16:29
Replays synthetic telemetry through real ImuDeadReckoning and
integrator wrapper functions, measuring dead-reckoning error vs
ground truth. Three tests: stationary drift, slew tracking, and
solve correction reset.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Telemetry recorder captures solve and IMU events with timestamps
- Menu entries for telemetry start/stop/replay
- Integrator wired to record solves and IMU readings
- UI list screen for telemetry sessions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split integrator.py into three focused modules:
- pointing.py: coordinate math (IMU dead-reckoning, plate-solve
  integration, roll/constellation/altaz finalization)
- telemetry.py: TelemetryManager facade (recording, replay,
  command dispatch, image saving, replay event handling)
- integrator.py: main loop and queue plumbing only

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 55 unit tests covering TelemetryRecorder, TelemetryPlayer,
  TelemetryManager, and pointing.py functions
- Fix test_integrator_drift.py import from PiFinder.integrator
  to PiFinder.pointing after refactor

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…and analysis tools

- Record raw gyro and accelerometer readings in IMU events
- Record target changes (name, RA/Dec, Alt/Az) for time-to-target analysis
- Fix replay: solve_time, solve_source, imu_pos, failed solves, mount_type header
- Reset integrator state after replay ends
- Move location to separate .location sidecar file for privacy
- Reduce file size with stationary IMU decimation (10x) and float rounding
- Add telemetry analysis scripts: session visualizer, drift analysis,
  truss flex analysis, IMU free-run drift visualization
- Include sample recording (session_20260309.jsonl, location scrubbed)
- 67 unit tests covering all new functionality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single conflict in python/PiFinder/integrator.py: telemetry already
refactored the helper functions (update_plate_solve_and_imu, update_imu,
set_cam2scope_alignment, get_roll_by_mount_type) into pointing.py.

Kept telemetry's refactor; dropped the duplicate helpers that upstream
modified in place. Upstream-only additions (get_alt_az, get_constellation,
pointing_updated flag) and the imu_time tweak in update_imu are NOT
incorporated here — apply them to pointing.py as a follow-up if wanted.
Upstream's astro_coords refactor (brickbots#420) moved RaDecRoll from
pointing_model/astro_coords.py to types/coordinates.py and reworked the
API: constructor now takes (ra, dec, roll, deg=...) and replaces
set_from_deg/get_deg with set(...) and get(deg=True).

Resolution:
- integrator.py: kept HEAD; dropped duplicate helpers (now in pointing.py)
- pointing.py: updated import path and ported all RaDecRoll calls to the
  new API (set_from_deg/get_deg → constructor / get(deg=True))
- integrator_classic.py: accepted upstream deletion (brickbots#421 dropped classic
  integrator); telemetry's only change was a trivial **kwargs signature
The clear-on-failure block in solver() reset solved["RA"]/Dec/Matches
but left camera_center and camera_solve pinned to the last successful
solve across every failure path.

Integrator-side downstream is unaffected (integrator.py:96 only merges
new position data when RA is not None), but stale camera_center leaks
into anything reading 'solved' from the solver's perspective. Completes
the existing 'otherwise old values persist' clearing block.
mrosseel added 2 commits May 22, 2026 03:42
solver.py imports tetra3 at module scope, which transitively pulled the
submodule into any caller of get_initialized_solved_dict — including
integrator.py and the integration-drift tests. CI's checkout step does
not init submodules, so tests/test_integrator_drift.py failed to collect:

  PiFinder/solver.py:28: ModuleNotFoundError: No module named 'tetra3'

Move the pure-data dict factory to a tiny new module PiFinder/solved.py.
Update solver.py, integrator.py, and test_integrator_drift.py to import
from there. No runtime behavior change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant