Skip to content

Share one control loop between straight() and turn(), compensate for battery voltage#104

Open
SaintSampo wants to merge 3 commits into
mainfrom
improvedDrivetrainPID
Open

Share one control loop between straight() and turn(), compensate for battery voltage#104
SaintSampo wants to merge 3 commits into
mainfrom
improvedDrivetrainPID

Conversation

@SaintSampo

Copy link
Copy Markdown
Collaborator

Summary

straight() and turn() were near-duplicate loops solving the same problem on different axes. Both now delegate to a shared _move() that controls translation and rotation together.

_move() runs translation and rotation through their own controllers and mixes them as left = translation - rotation, right = translation + rotation. straight() passes heading_target = 0, turn() passes distance_target = 0, so each move drives one axis and actively holds the other at zero. A zero goal doesn't gate the exit, so both functions still exit on the same axis they did before.

Changes

  • Effort limits apply to the mixed wheel efforts, not the main PID's raw output. Both wheels scale by a common factor, so heading correction survives saturation instead of being clipped. min_effort is a new optional argument on both functions.
  • The floor only engages while an axis is outside tolerance. Otherwise a settled axis lets a tiny correction on the other get scaled up to min_effort, spinning the robot in place over a fraction of a degree.
  • Battery voltage compensation. Effort is raw PWM duty, so a gain set tuned on a fresh pack is 30-40% weaker near cutoff. __init__ averages 8 readings into voltage_scale, applied in _move. max_effort now means fraction of nominal power, so duty can exceed it on a weak pack. arcade() unchanged.
  • Retuned both boards. Integral terms dropped on the XRP; tolerance_count 3 → 10 on both, since at the measured 11.2 ms loop period 3 was a 34 ms dwell — short enough to latch "done" while still moving through the band.
XRP Nano
min_effort 0.14 0.10
distance kp / kd 3.5 / 0.1 0.32 / 0.0184
distance tolerance / count 0.1 cm / 10 0.2 cm / 10
heading kp / kd 0.064 / 0.0045 0.014 / 0.001
heading tolerance / count 0.5° / 10 1° / 10

Extract shared movement logic from straight() and turn() into a unified _move() controller to reduce code duplication. Add voltage compensation that scales motor effort based on battery voltage to maintain consistent performance across different battery states. Add min_effort parameter to both movement methods for better control tuning.
Add optional distance_controller and heading_controller parameters to DifferentialDrive._move and use provided controllers if passed. Preserve existing default PID construction when controllers are None. Fix effort-floor logic by reading controller tolerances with getattr (avoids errors for controllers without tolerance). Update straight() and turn() callers to pass main/secondary controllers (turn swaps order so main/secondary map to heading/distance appropriately). No behavior change when controllers are omitted.
Adjust PID controller gains, tolerances, and minimum effort for the NanoXRP differential drive implementation. Increases min_effort from 0.05 to 0.10, refines distance and heading controller parameters, and increases tolerance_count from 3 to 10 for more stable control performance.
@SaintSampo
SaintSampo requested a review from KalticCodes July 22, 2026 21:25
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.

2 participants