feat: Encoder odometry and wheel speed feedback (Issue #632) #642

Merged
sl-jetson merged 1 commits from sl-controls/issue-632-encoder-odom into main 2026-03-15 17:29:55 -04:00
Collaborator

Summary

  • TIM2 (32-bit) left encoder / TIM3 (16-bit) right encoder in quadrature mode 3 (×4 resolution)
  • RPM computation with int16 saturation; 16-bit counter wrap handled correctly via signed delta cast
  • Differential-drive odometry: x/y (mm) and theta (rad, wrapped ±π) via Euler-forward integration
  • Flash config at sector 7 (0x0807FF00, 64 bytes) stores ticks_per_rev, wheel_diam_mm, wheel_base_mm with magic validation and default fallback
  • JLINK_TLM_ODOM (0x8C) 22-byte frame at 50 Hz: rpm_left, rpm_right, x_mm, y_mm, theta_cdeg, speed_mmps
  • 75/75 unit tests passing (TEST_HOST build, gcc -I include -I src -DTEST_HOST -lm)

Files changed

  • include/encoder_odom.h — API, flash struct, state struct, defaults
  • src/encoder_odom.c — TIM2/TIM3 init, tick/RPM/odometry, flash load/save, TLM send
  • test/test_encoder_odom.c — 75 unit tests
  • include/jlink.h — JLINK_TLM_ODOM 0x8C, jlink_tlm_odom_t (16 bytes), declaration
  • src/jlink.c — jlink_send_odom_tlm() 22-byte frame implementation
  • include/config.h — ENC_LEFT_TIM/ENC_RIGHT_TIM pin/AF constants

Closes #632

## Summary - TIM2 (32-bit) left encoder / TIM3 (16-bit) right encoder in quadrature mode 3 (×4 resolution) - RPM computation with int16 saturation; 16-bit counter wrap handled correctly via signed delta cast - Differential-drive odometry: x/y (mm) and theta (rad, wrapped ±π) via Euler-forward integration - Flash config at sector 7 (0x0807FF00, 64 bytes) stores ticks_per_rev, wheel_diam_mm, wheel_base_mm with magic validation and default fallback - JLINK_TLM_ODOM (0x8C) 22-byte frame at 50 Hz: rpm_left, rpm_right, x_mm, y_mm, theta_cdeg, speed_mmps - 75/75 unit tests passing (TEST_HOST build, gcc -I include -I src -DTEST_HOST -lm) ## Files changed - `include/encoder_odom.h` — API, flash struct, state struct, defaults - `src/encoder_odom.c` — TIM2/TIM3 init, tick/RPM/odometry, flash load/save, TLM send - `test/test_encoder_odom.c` — 75 unit tests - `include/jlink.h` — JLINK_TLM_ODOM 0x8C, jlink_tlm_odom_t (16 bytes), declaration - `src/jlink.c` — jlink_send_odom_tlm() 22-byte frame implementation - `include/config.h` — ENC_LEFT_TIM/ENC_RIGHT_TIM pin/AF constants Closes #632
sl-perception added 1 commit 2026-03-15 14:50:29 -04:00
- TIM2 (32-bit) left encoder, TIM3 (16-bit) right encoder in mode 3
- RPM calculation with int16 clamp; 16-bit wrap handled via signed delta
- Differential-drive odometry: x/y/theta Euler-forward integration
- Flash config (sector 7, 0x0807FF00) for ticks_per_rev/wheel_diam/base
- JLINK_TLM_ODOM (0x8C) at 50 Hz: rpm_l/r, x_mm, y_mm, theta_cdeg, speed_mmps
- 75/75 unit tests passing (TEST_HOST build)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sl-jetson force-pushed sl-controls/issue-632-encoder-odom from ebfc8ec468 to 779f9d00e2 2026-03-15 16:34:45 -04:00 Compare
sl-jetson merged commit 0fcad75cb4 into main 2026-03-15 17:29:55 -04:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: seb/saltylab-firmware#642
No description provided.