Conversation
Pid struct fields were pub(crate) but only accessed directly from main_state.rs for gain updates and integral reset. Replace with: - set_gains(kp, ki, kd) — updates gains and resets accumulated state - reset() — already existed, now used instead of direct integral = 0 Also make Commutation::intervals private — only accessed via record_interval() method.
Move stall/current-limit/speed PID logic from MainState::tick() into PidState methods: tick_stall(), tick_current_limit(), tick_speed_control(). All PidState fields are now private — access only through methods. MainState::tick() PID section shrinks from 30 lines to 15, calling 3 methods that each return a value to publish to SharedComm.
There was a problem hiding this comment.
Sorry @kaidokert, you have reached your weekly rate limit of 1500000 diff characters.
Please try again later or upgrade to continue using Sourcery
📝 WalkthroughWalkthroughMade PID and commutation internals private, added PidState constructors/setters and tick methods, updated MainState and harness to use the new Pid/PidState API, and added unit tests for PID behaviors; ISR now interacts via tick-returned values and commutation intervals are written via an interface instead of direct field access. Changes
Sequence Diagram(s)sequenceDiagram
participant Harness as "Harness (CLI)"
participant Main as "MainState"
participant Pid as "PidState"
participant ISR as "ISR / Commutation"
rect rgba(150,200,255,0.5)
Harness->>Main: set flag (use_current_limit / use_speed_control)
Main->>Pid: set_use_current_limit(v) / set_use_speed_control(v)
end
rect rgba(200,255,200,0.5)
ISR->>Pid: record_interval() / provide samples
Pid-->>ISR: tick_current_limit() -> duty_ceiling
Pid-->>ISR: tick_stall() -> boost_duty
Pid-->>ISR: tick_speed_control() -> Option<override>
end
rect rgba(255,230,150,0.5)
ISR->>Main: publish ISR-facing outputs (ceiling / boost / override)
Main->>Main: apply outputs to motor control
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Review rate limit: 3/5 reviews remaining, refill in 15 minutes and 18 seconds. Comment |
❌ 2 Tests Failed:
View the full list of 2 ❄️ flaky test(s)
To view more test analytics, go to the Test Analytics Dashboard |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0dab462b5d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@rm32/src/main_state.rs`:
- Around line 356-360: The call to pid.tick_speed_control(...) is using
shared.zero_crosses() directly which can change mid-tick; instead use the
tick-scoped snapshot captured earlier in MainState::tick() (the local zc
variable) so the PID sees a stable zero-crosses value for the whole tick; update
the pid.tick_speed_control call to pass zc (the variable captured at the top of
tick()) rather than calling shared.zero_crosses() directly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4e30031c-c2ee-47a1-8e32-1d9429be519a
📒 Files selected for processing (5)
rm32/src/bin/harness.rsrm32/src/commutation.rsrm32/src/control/state.rsrm32/src/main_state.rsrm32/src/pid.rs
There was a problem hiding this comment.
Code Review
This pull request refactors the PidState and Pid structures to improve encapsulation by making fields private and introducing dedicated methods for stall protection, current limiting, and speed control. The logic previously found in main_state.rs has been moved into these new methods. Feedback was provided regarding a behavioral change in the speed control logic where the entire PID state is reset instead of only the integral term, which may impact parity with the original implementation.
10 tests covering stall, current limit, and speed control PID ticks: - current_limit_pid_reduces_ceiling_when_over_target (mirrors C test) - current_limit_pid_clamps_to_min_duty - current_limit_pid_resets_when_inactive - stall_pid_boosts_when_interval_above_target (mirrors C test) - stall_pid_clamps_to_150 - stall_pid_clamps_to_zero - speed_control_inactive_returns_none - speed_control_not_running_returns_none - speed_control_active_returns_override - speed_control_works_during_startup
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@rm32/src/control/state.rs`:
- Around line 54-57: The target_e_com_time field is private but used by
tick_speed_control(), so add a public setter to allow updating the PID target
after default() initialization: implement pub fn set_target_e_com_time(&mut
self, target: u32) on the struct that contains target_e_com_time (the same type
that defines tick_speed_control()), and use that setter from callers that need
to change the speed control target; alternatively, make the field pub if you
prefer direct access, but prefer the setter for encapsulation. Ensure you update
any other similar struct instances referenced in the same file (the other
occurrence noted around the 114-126 region) to provide the same setter or public
access so both usages can change the target.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
…etter - Add Pid::clear_integral() that only zeros integral (matching C behavior). Speed control was using reset() which also cleared derivative state — behavioral change from C. - Pass captured zc snapshot to tick_speed_control instead of reading shared.zero_crosses() directly, which could change mid-tick via desync reset. - Add PidState::set_target_e_com_time() — field was private with no setter, leaving speed PID target stuck at 0.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@rm32/src/control/state.rs`:
- Around line 107-111: Normalize the lower clamp bound before using it: compute
a safe min_bound = min_duty.clamp(0, 2000) (ensure types match i16), then call
self.current_limit_adjust = self.current_limit_adjust.clamp(min_bound, 2000) so
the lower bound cannot exceed 2000 or be negative, and only then cast
self.current_limit_adjust as u16; adjust the code around current_limit_adjust,
min_duty and the clamp call to use min_bound.
- Around line 112-115: When tick_current_limit() or tick_speed_control() detect
the controller is inactive they currently suppress output but leave the PID
internal state intact; update both functions to reset their PID state when
returning inactive by clearing the integral accumulator,
last_error/previous_error and any derivative/history or timestamp fields so no
stale state remains. Locate the PID instances used by each function (e.g. fields
referenced in tick_current_limit and tick_speed_control such as current_limit_*
or speed_* controller/accumulator variables) and implement a reset method or
inline zeroing (integral = 0.0, previous_error = None/0.0, last_timestamp =
None, derivative_history.clear()) and call it before returning the inactive
value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 82c8d956-0c82-4a0d-b7c6-e061dc2e93c8
📒 Files selected for processing (3)
rm32/src/control/state.rsrm32/src/main_state.rsrm32/src/pid.rs
✅ Files skipped from review due to trivial changes (1)
- rm32/src/main_state.rs
Summary
Two encapsulation improvements:
Pid struct — all 10 fields now private (were pub(crate)). New
set_gains(kp, ki, kd)method replaces direct field writes + manual reset. Direct
integral = 0replacedwith existing
reset()method.PidState struct — all 10 fields now private (were pub/pub(crate)). PID tick logic
moved from MainState::tick() into 3 PidState methods:
tick_stall(ci) -> u16— stall boost for ISRtick_current_limit(current, target, min, running) -> u16— duty ceilingtick_speed_control(e_com, zc, running) -> Option<u16>— throttle overrideMainState::tick() PID section shrinks from 30 lines to 15.
Test plan
Summary by CodeRabbit