Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion acamd/acam_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3644,7 +3644,10 @@ logwrite( function, message.str() );
// and is unaffected.
//
double maxoffset = this->tcs_max_offset;
if ( this->acquire_mode == Acam::TARGET_GUIDE && this->allow_large_offset.load() ) {
if ( this->allow_large_offset.load() ) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep large-offset permission synchronized with guide state

When offsetgoal races with acquire stop or a new acquisition, allow_large_offset can remain true after acquire_mode leaves TARGET_GUIDE: stopping does not clear the flag, and a new acquisition clears it before changing the mode, allowing another command thread to re-arm it in between. Since acamd processes multiple connections concurrently with the frame-grab loop, removing this predicate lets an in-flight do_acquire() accept up to the 300-arcsec limit and then bypass the guide median filter, sending the correction immediately after a stop or as an acquisition correction rather than enforcing tcs_max_offset. Synchronize the allowance with the associated goal/mode transition instead of honoring the bare flag in every mode.

Useful? React with 👍 / 👎.

@cfremling cfremling Aug 26, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The scenarios described are not failure modes of this change — they are the intended behavior, and none of them are relevant to the defect this fixes.

allow_large_offset is armed by exactly one thing: a deliberate offsetgoal command from the sequencer or an operator. Whatever mode the loop happens to be in when the next correction lands — mid-transition, after a stop, during re-acquisition — executing that deliberate offset is the commanded behavior. "Sending the correction immediately" and "bypassing the guide median filter" for that one correction are both exactly right: a deliberate 72″ science move must not be vetoed by a mode race (measured on sky 2026-08-26: a 6 ms loss exposed 900 s of the wrong object) nor median-filtered against sub-arcsecond guide samples (which would veto it just as silently).

The blast radius of any flag race is already bounded by the existing design: the allowance is one-shot (consumed on use or rejection), ordinary guide corrections remain capped at ACQUIRE_TCS_MAX_OFFSET in every mode because nothing else ever arms the flag, and the absolute 300″ backstop still applies to the consuming correction. The removed predicate provided no protection/it protected against executing exactly what was asked, which is the bug.

If a stricter arm/consume lifecycle (e.g., clearing on acquire stop) is wanted, that is a reasonable, separate hardening change. This PR is the urgent one-line restoration of the correct semantic.

🤖 Generated with Claude Code

// A deliberate goal offset is correct by construction and must not
// be capped as a guide correction, whatever mode the loop is in
// when the correction lands.
maxoffset = this->tcs_max_putonslit_offset;
}

Expand Down
Loading