Feedforward speed control with shared battery compensation - #118
Draft
SaintSampo wants to merge 4 commits into
Draft
Feedforward speed control with shared battery compensation#118SaintSampo wants to merge 4 commits into
SaintSampo wants to merge 4 commits into
Conversation
Centralize and clarify encoder timing and unit conversions. In encoded_motor.py introduce _UPDATE_PERIOD_MS/_UPDATE_HZ, conversion helpers (_counts_per_update_to_rpm, _rpm_to_counts_per_update), and store counts-per-update instead of ambiguous `speed`. Use the update period constant for the virtual timer and for rpm<->counts conversions. Update set_speed/get_speed/inner update logic to use the new helpers and names. In differential_drive.py rename cmpsToRPM to snake_case cmps_to_rpm for naming consistency. Improves readability and correctness of rpm/count calculations.
Move battery voltage measurement/compensation onto Board (nominal voltage per platform, update_voltage_compensation(), voltage_scale measured at init). DifferentialDrive now reads board.voltage_scale (removed its own redundant voltage logic). EncodedMotor switched to feedforward+P velocity control (kS/kV per platform), holds Board reference, applies voltage_scale to motor effort, and clamps effort to [-1,1]. Minor PID/integral changes to match the new feedforward approach.
Update EncodedMotor defaults: NanoXRP now uses zeroed feedforward (kS/kV = 0.00) with a P-only PID (kp=0.015). Other platforms use kS=0.12, kV=0.02 and a stronger P-only PID (kp=0.1). Also clear prev_speed (set to 0) when stopping so direction is forgotten when the controller is cleared.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reworks the motor speed loop from a pure PI controller into feedforward + P with battery compensation, and cleans up the speed math along the way. Feedforward (kS to break stiction, kV per unit speed) does the bulk of the work.
Changes
Speed control law (
encoded_motor.py)kS·sign(target) + kV·target + kP·error, scaled by batteryvoltage_scale. Integral dropped (with feedforward carrying the load, the residual is small and voltage comp absorbs droop).kS/kVare per-motor attributes;kPis the injectable controller'skp(set_speed_controllerstill works).kS=0.12, kV=0.02, kp=0.1; NanokS=0.1, kV=0.00122, kpsmall (Nano's high gear ratio/resolution makes the P loop go unstable above ~0.03).Battery compensation centralized on Board (
board.py)voltage_scale+update_voltage_compensation()now live onBoard, measured once at construction and shared by every consumer. Removes the duplicate copies the drivetrain and motors each held.Speed-math cleanup (
encoded_motor.py,differential_drive.py)_UPDATE_PERIOD_MS/_UPDATE_HZconstants replace the magicperiod=20/60*50that had to agree by hand._rpm_to_counts_per_update/_counts_per_update_to_rpmhold the conversion in one place (get_speed/set_speedcall them).self.speed(counts-per-tick) toself._counts_per_update.set_speed(0/None)now resetsprev_speedso the direction-change reset can't key off a stale value.API notes
DifferentialDrive.update_voltage_compensation()removed — callBoard.get_default_board().update_voltage_compensation()instead (e.g. after a battery swap).Boardnow measures the battery once at construction (one 8-sample read); on the Nano this leaves the shared VIN/RM2 pin restored to output, which is friendlier to BLE than before.