The plan assumed no code existed yet, but the 2.5D-map autonomy stack
(URDF, terrain-aware speed control, Nav2 global/local costmaps +
collision monitor) is already built and running in the separate
fori_ws workspace. Reframes the doc around what's actually there and
the concrete gaps found (AMCL correction not wired into the nav TF
tree, skid-steer calibration not ported from xbox_motor_control.cpp).
IMU integration (WitMotion HWT905-RS232, doc/06-imu-integration-plan.md):
- Phase 1: raw accel/gyro/angle observation, power-on-relative yaw offset
- Phase 2: x,y odometry + wheel-vs-IMU omega residual, using a self-fused
heading (wheel encoder omega + raw gyro_z average) instead of the IMU's
own onboard fused yaw, which field logs showed disagreeing with its own
raw gyro sign ~30% of the time during turns
- Phase 3: straight-line heading-hold PI trim, active only when steering
is centered and no lidar dodge is in progress, capped and field-tuned
- Phase 4: whole-body slip detection (commanded vs IMU-measured omega
ratio) that temporarily scales down v_x/omega, independent of the
per-wheel current-based diagnostics
- Phase 5a: k_skid/effective_w replaced with values fitted from real
wheel-vs-IMU logs (0.406->0.51, 0.684->0.87) instead of the geometric
formula, which field data showed under-driving every turn
RC receiver: switched from ttyUSB* guessing to udev-stable device names
(ttyMOTOR/ttyRC/ttyIMU), wired through run_4wd.sh and set_low_latency.sh.
Motor driver: read motor/driver temperature registers (0x20A4/0x20B0)
for proactive overheat visibility in the HUD/CSV.
Control fixes:
- Airborne-wheel zeroing no longer applies during spin turns, where
reaction-torque-driven diagonal load transfer was misclassified as
wheels leaving the ground and cutting spin torque in half
- jerkLimitedStep's instant-acceleration path now only fires for
same-direction speed increases; sign reversals (RC noise/deadzone
jitter near a stop, or a genuine direction change) go through the
jerk-limited path instead of snapping across zero
Auto CSV logging (logs/, gitignored) extended with encoder ticks, IMU,
odometry, heading-hold, slip, and temperature columns for field analysis.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Steering (CH1): omega was computed with the opposite sign from the
convention used everywhere else in this file (+omega=left,
-omega=right, per the LiDAR avoidance comments and the prior Xbox
joystick code), so pushing the stick left steered the robot right
and vice versa. Flipped the sign at the single point omega is
derived from the stick so curve-turn and spin-turn both inherit the
fix.
Throttle/steer anti-corruption filter: once a reading was rejected
for exceeding max_slew_per_tick, last_raw_throttle/last_raw_steer
never updated, so every subsequent real reading kept failing the
same slew check against that now-permanently-stale reference —
a livelock. Symptom: CH2 showing neutral (1500) on the HUD while the
robot kept driving forward regardless of stick input. Added a
max_reject_streak escape hatch: after a few consecutive rejections
in a row, treat it as a real fast stick movement rather than a
one-off corrupted frame and resync to the latest value.
Verified working on hardware.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Migrates the 4WD control input from SDL2/Xbox gamepad to a serial RC
receiver per doc/joystick.md's functional spec: CH1 steering, CH2
throttle, CH5 emergency brake (highest priority), CH7 speed mode
(0.3/0.6 m/s), with a 200ms fail-safe that forces an immediate stop
on signal loss. Channel mapping, deadzones, port, and baudrate are
all configurable via --rc_* CLI flags. LiDAR avoidance, jerk-limited
motion profile, and wheel-fault detection are unchanged.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Documents the ZLAC8015D V4 dual-channel driver (hardware spec, RS485
Modbus register map, 4WD skid-steer system architecture, the
xbox_motor_control.cpp control loop, and error/troubleshooting) under
doc/, plus a phased plan for adding IMU-based heading/slip feedback
(doc/06) informed by Clearpath Husky's sensor fusion stack and
skid-steer ICR literature. QnA/ records the Q&A that refined that plan.
Also adds the underlying manual PDFs and reference links under
resource/ that the docs cite.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Previously, once a wheel's airborne flag cleared, its target reverted
to the normal drive command but the actual RPM still had to ramp up
through the gentle standstill-launch accel_rate/jerk profile. Since
the chassis is already moving at that point (unlike a stop-start),
the wheel spent several hundred ms unable to match ground speed,
dragging/grinding against the surface and occasionally landing on a
momentarily negative curve-turn target, making it spin backward.
Track the airborne->grounded transition per wheel and, on the tick it
clears, snap cmd directly to target and reset the jerk accel state
instead of ramping, so the wheel rejoins the other three immediately.
Verified working on hardware.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Steering angular velocity (omega) was scaled by the constant max
speed (max_v) instead of the actual current forward speed (v_x).
This decoupled turn tightness from throttle position: at low/medium
throttle, a moderate left-stick steering input already produced an
omega large enough to flip the inner wheel's commanded velocity
negative, causing the robot to spin/reverse/lurch forward instead of
smoothly curving. Scaling by abs(v_x) keeps turn radius proportional
to speed as intended, matching prior full-throttle behavior while
fixing the reversal at partial throttle.
Also drops the stale committed x86-64 binary (built before this fix,
so its behavior no longer matched source). Build fresh on an x86
machine via `make`; run_4wd.sh already rebuilds automatically when
the binary is missing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reads 0x20A5/0x20A6 error codes alongside existing feedback poll to
diagnose overcurrent/overload alarms, and adds rated/max current
query and max current write helpers.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds jerk-limited S-curve motion profiles, robust median-based
odometry to reject wheel-lift encoder spikes, per-wheel current-based
airborne/stall detection with pair-wise comparison to avoid false
positives during normal curve turns, curved-turn blending for spin
turns, and optional CSV telemetry logging. Fixes a bug where any
right-stick input while driving forward would override left-stick
curve steering. Raises max speed from 0.3 to 0.4 m/s.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>