Skip to content

Refactor arcade heading hold, reverse steering - #115

Open
SaintSampo wants to merge 6 commits into
mainfrom
driveArcadeRefactor
Open

Refactor arcade heading hold, reverse steering#115
SaintSampo wants to merge 6 commits into
mainfrom
driveArcadeRefactor

Conversation

@SaintSampo

@SaintSampo SaintSampo commented Aug 6, 2026

Copy link
Copy Markdown
Member

Summary

Cleans up arcade() and its IMU heading-hold, and fixes two teleop feel issues. Single file, differential_drive.py.

Changes

  • Per-board heading gains. The single kp=0.075, kd=0.001 is replaced with tuned values: non-Nano kp=0.064, kd=0.0045, Nano kp=0.014, kd=0.001.

  • Reverse steering fix. Pushing back-and-left used to curve the robot right (the turn kept the same rotation direction as forward). Turn is now flipped when reversing, so the robot steers toward the stick either way.

  • Collapsed the heading-hold state machine. The two flags turning + reset_heading are replaced by one _holding_heading. Same behavior across every transition, far less to reason about. arcade() is flattened to early returns instead of 3-deep nesting, and the misnamed left_speed/right_speed (they're efforts) become left/right.

  • Stop forgets the held heading. A neutral (0, 0) clears _holding_heading, so resuming straight recaptures the current heading rather than steering back toward the pre-stop one.

  • Fresh PID per straight segment. heading_pid.clear_history() on entering straight prevents a prior turn's elapsed time from leaking into the controller's first derivative/integral step.

Replace reset_heading/turning flags with a single _holding_heading flag and simplify arcade mixing logic. Use early returns, keep wheel-mixing/scaling behavior, and centralize IMU-assisted straight driving: capture heading on entry, hold it while straight, and clear the hold when turning. Improves readability and fixes heading recapture behavior when transitioning between turning and straight driving.
When driving backward the turn input is inverted so the robot steers toward the joystick the same way as when driving forward. Adds a check in DifferentialDrive to negate `turn` if `straight` is negative before mixing, preserving the existing mixing and scaling logic and preventing reversed steering behavior.
@fgrossman

fgrossman commented Aug 7, 2026 via email

Copy link
Copy Markdown
Collaborator

@SaintSampo

Copy link
Copy Markdown
Member Author

My thinking was that without a deadband, there is not much point of having a control loop maintain heading. A stick will almost never be at exactly zero. Very few users are going to know to add a deadband. But I can remove it, if it is technically more correct.

Future idea: I think a drivetrain class like this should make it easy for users to set and tune a min_input, max_input, deadband, and input exponential. Low priority but I want to revisit this at some point.

@SaintSampo SaintSampo changed the title Refactor arcade heading hold. Add deadband and reverse steering Refactor arcade heading hold, reverse steering Aug 7, 2026
@SaintSampo
SaintSampo requested a review from KalticCodes August 10, 2026 22:45
@KalticCodes

KalticCodes commented Aug 12, 2026

Copy link
Copy Markdown
Member

The arcade function, in its original inception, was just meant to be an alternate version of set_effort, where you send a forward/back effort and a turning effort (which makes it really easy to program a line-follower and such). I think the changes that were made prior to this PR (adding the heading_pid) are not ideal. I think a better change for improving this function is to make a different version of this that uses speed control (including angular velocity control), which will result in the level of control without obfuscating the behavior in the default version of the function.

Since XRPLib is a learning platform, I think hiding elements such as angular drift feels a little silly (which is why this is not the right place for a deadband)

@SaintSampo

Copy link
Copy Markdown
Member Author

@KalticCodes I agree, I removed deadband from this PR. I'm with you in that I don't really think having heading_pid as part of arcade drive is ideal but it is outside the scope of this PR.

The main purpose of this PR is the lib needs the per-board heading gains. I believe the reverse steering fix is a good improvement too, everything is else is just cleaning up the existing function/improving readability now.

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.

3 participants