Skip to content

Conversation

@fouge
Copy link
Collaborator

@fouge fouge commented Jan 14, 2026

use polarizer state message as an indication of completion the message is sent on any new state & thus can be used to ensure the wheel moved successfully as per the request in the polarizer commands

@fouge fouge requested a review from a team as a code owner January 14, 2026 08:41
@fouge fouge requested a review from Copilot January 14, 2026 08:42
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances polarizer command reliability by waiting for polarizer state feedback messages to confirm successful wheel movement, rather than relying solely on command acknowledgment.

Changes:

  • Added wait_for_polarizer_wheel_state() method to wait for polarizer state feedback
  • Modified polarizer commands to wait for state confirmation after receiving ACK
  • Updated polarizer stress test to validate state changes with 1-second delays between commands

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 333 to 362
match tokio::time::timeout(
Duration::from_secs(2),
self.wait_for_polarizer_wheel_state(),
)
.await
{
Ok(Ok(state)) => {
info!("💈 Polarizer command {:?}: success", opts);
debug!("Polarizer wheel state: {:?}", state);
}
Ok(Err(e)) => {
return Err(eyre!(
"Error waiting for PolarizerWheelState for command {:?}: {:?}",
opts,
e
));
}
Err(_) => {
return Err(eyre!(
"Timeout waiting for PolarizerWheelState message for command {:?}",
opts
));
}
}
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code waits for any PolarizerWheelState message without validating that the state actually matches the requested command. For example, if the command was to move to "Horizontal" position, the code doesn't verify that the received state indicates the wheel is in the horizontal position. This means a command could be considered successful even if the wheel didn't actually move to the requested position. Consider adding validation to ensure the received state matches the expected state for the command that was sent.

Copilot generated this review using guidance from organization custom instructions.
Comment on lines +449 to +490
match tokio::time::timeout(
Duration::from_secs(2),
self.wait_for_polarizer_wheel_state(),
)
.await
{
Ok(Ok(state)) => {
success_count += 1;
debug!(
"[{}/{}] Polarizer -> {}: success [{:?}]",
i + 1,
repeat,
name,
state
);
}
Ok(Err(e)) => {
error_count += 1;
error!(
"[{}/{}] Polarizer -> {}: error waiting for state {:?}",
i + 1,
repeat,
name,
e
);
}
Err(_) => {
error_count += 1;
error!(
"[{}/{}] Polarizer -> {}: timeout waiting for state",
i + 1,
repeat,
name
);
}
}
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the polarizer method, this code waits for any PolarizerWheelState message without validating that the state actually corresponds to the requested position. The stress test should verify that the wheel actually reached the commanded position (passthrough, vertical, or horizontal) before counting it as a success. Otherwise, the test may report false successes when the wheel didn't actually move to the requested position.

Copilot generated this review using guidance from organization custom instructions.
Comment on lines +675 to +698
async fn wait_for_polarizer_wheel_state(
&mut self,
) -> Result<main_messaging::PolarizerWheelState> {
loop {
let Some(mcu_payload) = self.message_queue_rx.recv().await else {
return Err(eyre!("message queue closed"));
};
let McuPayload::FromMain(main_mcu_payload) = mcu_payload else {
continue;
};

if let main_messaging::mcu_to_jetson::Payload::PolarizerWheelState(state) =
main_mcu_payload
{
return Ok(state);
}
}
}
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wait_for_polarizer_wheel_state method consumes all messages from the message queue until it finds a PolarizerWheelState message, discarding any other messages that arrive (line 683 continues on non-matching messages). This could cause message loss if other important messages arrive during the wait period.

If a PolarizerWheelState message was already sent before this method is called (e.g., from a previous command), it will immediately consume that stale state instead of waiting for the new state corresponding to the current command. This creates a race condition where you might receive the state from a previous operation rather than the current one.

Consider one of these approaches:

  1. Clear any pending PolarizerWheelState messages before sending the command
  2. Add timestamp or sequence number validation to ensure the state corresponds to the current command
  3. Use a broadcast/watch channel pattern where state updates don't consume messages needed by other parts of the system

Copilot generated this review using guidance from organization custom instructions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In orb-mcu-util utility, command is run by the user, and during that command execution user doesn't care about other subsystems. So discarding other message types here is intended.
Correct @fouge ?

Comment on lines +413 to +420
// delay 1 second between commands
tokio::time::sleep(Duration::from_secs(1)).await;
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The delay has been moved to occur before waiting for the send result (line 414), which means it now delays before checking if the send was successful. This changes the timing semantics - previously, the delay occurred after a successful send. If the send fails, the delay still occurs, which adds unnecessary wait time when errors happen. Consider moving the delay to after the successful state verification (after line 484) to maintain the original semantics of delaying between successful operations.

Copilot uses AI. Check for mistakes.
Copy link
Member

@Qbicz Qbicz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, please check my question

Comment on lines +675 to +698
async fn wait_for_polarizer_wheel_state(
&mut self,
) -> Result<main_messaging::PolarizerWheelState> {
loop {
let Some(mcu_payload) = self.message_queue_rx.recv().await else {
return Err(eyre!("message queue closed"));
};
let McuPayload::FromMain(main_mcu_payload) = mcu_payload else {
continue;
};

if let main_messaging::mcu_to_jetson::Payload::PolarizerWheelState(state) =
main_mcu_payload
{
return Ok(state);
}
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In orb-mcu-util utility, command is run by the user, and during that command execution user doesn't care about other subsystems. So discarding other message types here is intended.
Correct @fouge ?

@fouge fouge force-pushed the fouge/mcu-util-polarizer-state branch from 32a999a to 3f81244 Compare January 20, 2026 10:17
use polarizer state message as an indication of completion
the message is sent on any new state & thus can be used
to ensure the wheel moved successfully as per the request
in the polarizer commands
@fouge fouge force-pushed the fouge/mcu-util-polarizer-state branch from 3f81244 to 677898f Compare January 20, 2026 10:22
@fouge fouge merged commit 08ff940 into main Jan 20, 2026
23 checks passed
@fouge fouge deleted the fouge/mcu-util-polarizer-state branch January 20, 2026 10:52
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