Skip to content

Slicecam fine-acquire: don't move on noisy/duplicate frames; settle after moves; tune gains#452

Closed
cfremling wants to merge 1 commit into
mainfrom
fix/fineacquire-fixes
Closed

Slicecam fine-acquire: don't move on noisy/duplicate frames; settle after moves; tune gains#452
cfremling wants to merge 1 commit into
mainfrom
fix/fineacquire-fixes

Conversation

@cfremling

Copy link
Copy Markdown
Collaborator

Targeted robustness fixes to the slicecam fine-acquisition loop (do_fineacquire), addressing wrong/overshooting moves seen on main. Kept intentionally minimal: 5 files, +131/−13.

Changes

  • Apply the full offset (gain 1.0). FINE_ACQUIRE_GAIN 0.7 → 1.0. A fine-tune step should command the full measured offset; deliberately under-correcting a known offset is never beneficial here.
  • Never move on a noisy solution. Only command a correction when the per-axis MAD scatter is within FINE_ACQUIRE_PREC; otherwise discard the batch and re-gather. Previously a move was sent at max_samples regardless of scatter — i.e. acting on an untrustworthy median.
  • FINE_ACQUIRE_PREC 0.1 → 0.4″, now configurable. With the old hardcoded 0.1″ the scatter gate was rarely satisfied, so the loop fell through to the move-anyway path.
  • Post-move settle delay. Wait FINE_ACQUIRE_SETTLE_SEC (default 4 s) after a TCS move before evaluating the next frame. Time-based, independent of frame cadence — the move + CCD readout take time, and acting on a mid-move/mid-settle frame yields a wrong correction.
  • Reject duplicate frames. A commanded framegrab doesn't guarantee the image refreshed; processing the same frame twice double-counts samples and can command a second move from a pre-move image (overshoot). Skip a frame whose full-frame byte signature matches the previous one. (Full-frame hash, so it can't miss the small star region.)
  • Configurable centroid weighting σ (FINE_ACQUIRE_CENTROID_SIGMA, default 1.5 px), was hardcoded 2.0. 1.5 was the empirically most-robust value across SNR and seeing on real SCAM data (Commissioning/guiding_20260519, FWHM≈6 px), evaluated against a 2D-Moffat-fit ground truth. The optimum scales with PSF width, so it's tunable.

Verified

  • Offset sign/convention unchanged from the proven feature/acq-automation-clean engine: both measure (star − goal) with cos(dec) and apply ACAMD_OFFSETGOAL(star − goal). So this does not change which way the telescope moves — only when and whether a move is issued, plus the centroid weighting.

Out of scope (deliberately)

  • Moffat-fit centroiding. A bounded 2D Moffat fit is actually stable at low SNR and marginally more accurate in simulation, but it needs a nonlinear-least-squares fitter in C++ (new dependency) + a fallback, and real-PSF deviations/contamination need on-sky validation. Can be a later, flag-gated option.
  • The reference's larger adaptive faint/bright exposure engine (EWMA modes, frame-averaging) is not reproduced here.

Not compiled locally (no local build available).

🤖 Generated with Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cd07a1eb4a

ℹ️ 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".

Comment thread slicecamd/slicecam_interface.cpp Outdated
for ( size_t i = 0; i < nbytes; ++i ) {
sig = ( sig ^ static_cast<uint64_t>( bytes[i] ) ) * 1099511628211ULL;
}
if ( sig == this->fineacquire_state.last_frame_sig ) return; // identical frame; wait for a fresh one

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Count duplicate no-detection frames toward failure handling

When the repeated frame has no detectable centroid, this early return happens before calculate_centroid() and before consecutive_centroid_failures is incremented. In the stale-frame case this code is meant to handle, fine acquisition can now stay running forever on the same bad image instead of climbing the exposure ladder and eventually stopping; this is especially easy to hit with an unrefreshed camera frame or a fixed emulated image. Please either reset/age the signature on acquisition resets or let duplicate frames participate in the no-detection timeout path.

Useful? React with 👍 / 👎.

…fter moves; tune gains

Targeted robustness fixes to the slicecam fine-acquisition loop (do_fineacquire),
keeping the diff minimal:

- Gain 0.7 -> 1.0 (FINE_ACQUIRE_GAIN): a fine-tune step applies the full
  measured offset; deliberately under-correcting a known offset is never right.
- Refuse to move on a noisy solution: only command a correction when the
  per-axis MAD scatter is within FINE_ACQUIRE_PREC; otherwise discard the batch
  and re-gather. Previously a move was sent at max_samples regardless of scatter.
- FINE_ACQUIRE_PREC default 0.1 -> 0.4 arcsec and made configurable, so good
  data passes the scatter gate (with 0.1 it rarely did and fell through).
- Post-move settle: wait FINE_ACQUIRE_SETTLE_SEC (default 4s) after a TCS move
  before evaluating the next frame. Time-based, independent of frame cadence.
- Reject duplicate frames: a commanded framegrab does not guarantee the image
  refreshed; processing the same frame twice double-counts samples and can
  command a second move from a pre-move image (overshoot). Skip a frame whose
  full-frame byte signature matches the previous one. The signature is reset at
  acquisition start, and consecutive identical frames are bounded: if the camera
  is stuck on one frame (or a fixed emulated image) fine-acq stops instead of
  acquiring forever on a stale image (this early-skip otherwise bypasses the
  no-detection timeout below).
- Centroid Gaussian weighting sigma made configurable (FINE_ACQUIRE_CENTROID_SIGMA),
  default 1.5 px -- empirically the most robust across SNR and seeing on real
  SCAM data (was hardcoded 2.0). The optimum scales with PSF width, so it is tunable.

Offset measurement/application sign verified unchanged from the proven
auto-acq-clean engine (both apply ACAMD_OFFSETGOAL(star - goal)).
@cfremling

Copy link
Copy Markdown
Collaborator Author

Closing as superseded by #455. The minimal config + default tweaks there (FINE_ACQUIRE_GAIN=1.0, prec_arcsec=0.35, goal_arcsec=0.4, and a tunable time-based FINE_ACQUIRE_SETTLE_SEC) proved sufficient on-sky the night of 2026-06-16/17, so the heavier noisy/duplicate-frame + gain-scheduling changes here weren't needed.

@cfremling cfremling closed this Jun 18, 2026
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.

1 participant