-
Notifications
You must be signed in to change notification settings - Fork 0
Phoenix6SignalsUpdate #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughSignal handling logic in Phoenix6 was made conditional on signal-array lengths. In Phoenix6Inputs.java, 🚥 Pre-merge checks | ❌ 3❌ Failed checks (1 warning, 2 inconclusive)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
hardware/phoenix6/Phoenix6SignalThread.java (1)
46-53: Thread is started even whenUSE_CANIVOREis false.When
USE_CANIVOREis false, the thread starts, waits 5 seconds, then immediately exits without doing any work. Consider gatingstart()on the flag:private Phoenix6SignalThread() { super("Phoenix6SignalThread"); - if (RobotHardwareStats.isReplay()) + if (RobotHardwareStats.isReplay() || !RobotConstants.USE_CANIVORE) return; setName("Phoenix6SignalThread"); setDaemon(true); start(); }This also allows restoring the simpler
while (true)loop since the thread won't exist when CANivore is disabled.Also applies to: 74-79
hardware/phoenix6/Phoenix6Inputs.java (1)
110-118: Critical: Array lookup uses wrong condition whenisCanivore=truebutUSE_CANIVORE=false.When an instance has
isCanivore=truebut the globalUSE_CANIVOREisfalse, signals are added toRIO_SIGNALS(line 94-97) andfirstInputIndexis set relative toRIO_SIGNALS. However, line 115 checks onlyisCanivoreto select the array, causing it to read fromCANIVORE_SIGNALSwith an index meant forRIO_SIGNALS.This will cause
ArrayIndexOutOfBoundsExceptionor return wrong signals.🐛 Suggested fix
private void updateSignalsToTable(LogTable table) { if (firstInputIndex == -1 || numberOfInputs == 0) return; + final boolean useCanivoreArray = isCanivore && RobotConstants.USE_CANIVORE; for (int i = firstInputIndex; i < firstInputIndex + numberOfInputs; i++) { - final BaseStatusSignal signal = isCanivore ? CANIVORE_SIGNALS[i] : RIO_SIGNALS[i]; + final BaseStatusSignal signal = useCanivoreArray ? CANIVORE_SIGNALS[i] : RIO_SIGNALS[i]; table.put(signal.getName(), signal.getValueAsDouble()); } }hardware/InputsBase.java (1)
66-75: CallgetDouble()instead ofgetDoubleArray()whenUSE_CANIVOREis false.When
USE_CANIVOREis false, threaded signals are stored as scalardoublevalues, not arrays. CallinggetDoubleArray()on a scalar violates the AdvantageKit API contract and will return incorrect results. Fetch the single value withvalue.getDouble()whenUSE_CANIVOREis false, or ensure threaded signals are always logged as arrays when registering them.
♻️ Duplicate comments (1)
hardware/phoenix6/Phoenix6Inputs.java (1)
65-69: Magic number100should be a named constant.As noted in a previous review, this hardcoded frequency should be extracted. Also, consider adding a brief comment explaining why threaded signals fall back to non-threaded registration when CANivore is disabled.
levyishai
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Don't make this a boolean, make it auto detectable
- You shouldn't reference normal code from lib
- Just add an
ifbefore the while that checks whether there are values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
| import edu.wpi.first.wpilibj.Timer; | ||
| import frc.trigon.lib.hardware.RobotHardwareStats; | ||
| import frc.trigon.lib.hardware.SignalThreadBase; | ||
| import frc.trigon.robot.constants.RobotConstants; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Unused import.
RobotConstants is imported but never used in this file.
🧹 Remove unused import
-import frc.trigon.robot.constants.RobotConstants;| public void run() { | ||
| Timer.delay(5); | ||
|
|
||
| while (true) | ||
| while (signals.length > 0) | ||
| updateValues(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thread exits permanently if no signals registered within 5 seconds.
The loop condition while (signals.length > 0) is evaluated once after the initial delay. If no signals have been registered by then, the thread terminates and any signals registered later will never be processed.
If signal registration is guaranteed to complete during robot initialization (within 5 seconds), this is acceptable. Otherwise, consider a different approach:
🔧 Option 1: Block until signals exist
`@Override`
public void run() {
Timer.delay(5);
-
- while (signals.length > 0)
+
+ while (true) {
+ if (signals.length == 0) {
+ Timer.delay(0.1);
+ continue;
+ }
updateValues();
+ }
}🔧 Option 2: Exit early with explicit no-op (if intentional)
`@Override`
public void run() {
Timer.delay(5);
-
- while (signals.length > 0)
- updateValues();
+
+ if (signals.length == 0)
+ return; // No signals registered - thread not needed
+
+ while (true)
+ updateValues();
}Option 2 makes the intent clearer if early exit is deliberate, but still prevents late registrations from being processed.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public void run() { | |
| Timer.delay(5); | |
| while (true) | |
| while (signals.length > 0) | |
| updateValues(); | |
| } | |
| `@Override` | |
| public void run() { | |
| Timer.delay(5); | |
| while (true) { | |
| if (signals.length == 0) { | |
| Timer.delay(0.1); | |
| continue; | |
| } | |
| updateValues(); | |
| } | |
| } |
| public void run() { | |
| Timer.delay(5); | |
| while (true) | |
| while (signals.length > 0) | |
| updateValues(); | |
| } | |
| `@Override` | |
| public void run() { | |
| Timer.delay(5); | |
| if (signals.length == 0) | |
| return; // No signals registered - thread not needed | |
| while (true) | |
| updateValues(); | |
| } |
| if (!signalToThreadedQueue.isEmpty()) | ||
| updateThreadedSignalsToTable(table); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this if really needed?
|
|
||
| while (true) | ||
| while (signals.length > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add an if before this while, don't use it as the condition of the while.
No description provided.