From 2e01ae9ae0b8ed2d90986610479305a85f5ec879 Mon Sep 17 00:00:00 2001 From: Christoffer Fremling Date: Thu, 18 Jun 2026 14:30:35 -0700 Subject: [PATCH] slicecamd: fine-acquire tuning validated on-sky 2026-06-17 Bakes in the fine-acquire settings tuned and validated the night of 2026-06-16/17 (both bright offset-star and normal science targets; converging in 1-2 offsets, ~60-90 s slew-complete to lock): - FINE_ACQUIRE_GAIN 0.7 -> 1.0 (slicecamd.cfg.in + matching hardcoded default) - prec_arcsec 0.1 -> 0.35 (MAD scatter early-exit threshold) - goal_arcsec 0.3 -> 0.4 (convergence threshold) - new FINE_ACQUIRE_SETTLE_SEC (default 3.0): time-based settle after each move, on top of SETTLE_FRAMES. Autoexpose shortens the exposure on bright targets, which makes the frame-count settle elapse too fast in wall-clock for the TCS to physically settle; a time-based settle fixes that. Replaces a hardcoded test sleep and is tunable (0 disables) without a recompile. The slicecamd.cfg.in change is required: CONFIGURE_FILE regenerates Config/slicecamd.cfg from the template on build, so edits to the generated .cfg are lost on rebuild. Not compiled in this environment -- build on the instrument. Co-Authored-By: Claude Opus 4.8 (1M context) --- Config/slicecamd.cfg.in | 10 +++++++++- slicecamd/slicecam_interface.cpp | 21 +++++++++++++++++++++ slicecamd/slicecam_interface.h | 7 ++++--- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Config/slicecamd.cfg.in b/Config/slicecamd.cfg.in index 0e977379..17919d7f 100644 --- a/Config/slicecamd.cfg.in +++ b/Config/slicecamd.cfg.in @@ -90,11 +90,19 @@ FINE_ACQUIRE_MIN_SAMPLES=3 # FINE_ACQUIRE_SETTLE_FRAMES=2 +# FINE_ACQUIRE_SETTLE_SEC= +# Time-based settle applied after each move, in addition to SETTLE_FRAMES, +# to let the TCS physically finish the move before sampling resumes. This matters +# when autoexpose shortens the exposure (e.g. bright targets): the frame-count +# settle then elapses too quickly in wall-clock. Set to 0 to disable. +# +FINE_ACQUIRE_SETTLE_SEC=3.0 + # FINE_ACQUIRE_GAIN= # Proportional gain = {0..1} applied to the commanded offset when the residual # is at or below FINE_ACQUIRE_GAIN_THRESHOLD arcsec. # -FINE_ACQUIRE_GAIN=0.7 +FINE_ACQUIRE_GAIN=1.0 # FINE_ACQUIRE_GAIN_LARGE= # Proportional gain applied when the residual exceeds FINE_ACQUIRE_GAIN_THRESHOLD. diff --git a/slicecamd/slicecam_interface.cpp b/slicecamd/slicecam_interface.cpp index 01604a4b..3651aaa3 100644 --- a/slicecamd/slicecam_interface.cpp +++ b/slicecamd/slicecam_interface.cpp @@ -542,6 +542,14 @@ namespace Slicecam { return; } + // time-based settle: wait for the TCS to physically finish the move before + // sampling resumes. The frame-count settle (settle_frames) is too short in + // wall-clock when autoexpose shortens the exposure (e.g. bright targets), so + // apply a configurable time-based settle on top of it; settle_sec=0 disables. + if ( this->fineacquire_state.settle_sec > 0.0 ) { + std::this_thread::sleep_for( std::chrono::duration( this->fineacquire_state.settle_sec ) ); + } + // reset samples and discard settle_count frames for telescope settling this->fineacquire_state.reset(); this->fineacquire_state.settle_frames = this->fineacquire_state.settle_count; @@ -1332,6 +1340,19 @@ namespace Slicecam { applied++; } else + if ( config.param[entry] == "FINE_ACQUIRE_SETTLE_SEC" ) { + try { this->fineacquire_state.settle_sec = std::stod( config.arg[entry] ); } + catch ( const std::exception &e ) { + message.str(""); message << "ERROR invalid FINE_ACQUIRE_SETTLE_SEC " + << config.arg[entry] << ": " << e.what(); + logwrite( function, message.str() ); + return ERROR; + } + message.str(""); message << "SLICECAMD:config:" << config.param[entry] << "=" << config.arg[entry]; + logwrite( function, message.str() ); + applied++; + } + else if ( config.param[entry] == "FINE_ACQUIRE_GAIN" ) { try { this->fineacquire_state.gain = std::stod( config.arg[entry] ); } catch ( const std::exception &e ) { diff --git a/slicecamd/slicecam_interface.h b/slicecamd/slicecam_interface.h index f8d3920f..15023092 100644 --- a/slicecamd/slicecam_interface.h +++ b/slicecamd/slicecam_interface.h @@ -87,13 +87,14 @@ namespace Slicecam { std::vector ddec_samp; ///< dDEC samples, degrees int max_samples = 10; ///< samples before evaluating a move int min_samples = 3; ///< minimum samples before scatter-gated early exit - double prec_arcsec = 0.1; ///< MAD scatter threshold per axis for early exit (arcsec) - double goal_arcsec = 0.3; ///< convergence threshold, arcsec - double gain = 0.7; ///< gain applied when offset <= gain_threshold_arcsec + double prec_arcsec = 0.35; ///< MAD scatter threshold per axis for early exit (arcsec) + double goal_arcsec = 0.4; ///< convergence threshold, arcsec + double gain = 1.0; ///< gain applied when offset <= gain_threshold_arcsec double gain_large = 1.0; ///< gain applied when offset > gain_threshold_arcsec double gain_threshold_arcsec = 2.0; ///< offset above which gain_large is used int settle_frames = 0; ///< countdown of frames to discard while telescope settles int settle_count = 2; ///< configured: frames to discard after each move + double settle_sec = 3.0; ///< time-based settle (sec) after each move; 0 disables (needed when autoexpose shortens frames so the frame-count settle is too brief in wall-clock) int consecutive_centroid_failures = 0; ///< counts consecutive centroid failures // exposure compensation (shared by the reactive trim and, later, autoexpose) double exptime_min = 0.1; ///< clamp: minimum auto-adjusted exposure (sec)