sl-controls created pull request seb/saltylab-firmware#127

sl-controls
Mon, 02 Mar 2026 09:16:03 -0500

127#feat(tank): SaltyTank tracked-vehicle ESC driver (Issue #122)#

Summary

kinematics.py — tank_speeds with slip compensation (angular_cmd = angular_z / (1-slip_factor)), skid_steer_speeds, speed_to_pwm, compute_track_speeds (2wd|4wd|tracked + ±max clip), expand_to_4ch, odometry_from_track_speeds (angular × (1-slip_factor))

tank_driver_node.py — 50 Hz ROS2 node; serial P<ch1>,<ch2>,<ch3>,<ch4>\n; H\n heartbeat; dual stop paths: watchdog 0.3 s + /saltybot/e_stop Bool topic (latching, cleared by new cmd_vel); runtime drive_mode + slip_factor live param switch; slip-compensated dead-reckoning; /saltybot/tank_pwm JSON + /saltybot/tank_odom

config/tank_params.yaml, launch/tank_driver.launch.py, package.xml, setup.py/cfg

test/test_tank_kinematics.py — 71/71 unit tests passing (parametric round-trip over slip {0.0, 0.1, 0.3, 0.5})

Slip compensation model

Command path: angular_cmd = angular_z / (1 - slip_factor)
Odometry path: angular_odom = (v_right - v_left) / B x (1 - slip_factor)

The corrections are complementary — consistent dead-reckoning at any slip value. Tune live: ros2 param set /tank_driver slip_factor 0.1

Test plan

71 unit tests pass

Deploy: ros2 launch saltybot_tank_driver tank_driver.launch.py

Verify neutral PWM at rest

Zero-radius pivot via /cmd_vel (linear=0, angular!=0)

E-stop: ros2 topic pub /saltybot/e_stop std_msgs/Bool '{data: true}' --once

Live mode switch: ros2 param set /tank_driver drive_mode 4wd

Confirm /saltybot/tank_odom tracks motion

Closes #122

🤖 Generated with Claude Code