diff --git a/common/message_keys.h b/common/message_keys.h index 30181591..0888bc52 100644 --- a/common/message_keys.h +++ b/common/message_keys.h @@ -68,6 +68,7 @@ namespace Key { namespace Sequencer { inline const std::string SEQSTATE = "seqstate"; inline const std::string SHOULD_FINEACQUIRE = "should_fineacquire"; + inline const std::string SHOULD_FLEXCOMP = "should_flexcomp"; ///< does the sequencer invoke flexure compensation? } namespace TargetInfo { diff --git a/common/sequencerd_commands.h b/common/sequencerd_commands.h index b69dce30..79ab0f59 100644 --- a/common/sequencerd_commands.h +++ b/common/sequencerd_commands.h @@ -12,6 +12,7 @@ const std::string SEQUENCERD_CONFIG = "config"; const std::string SEQUENCERD_DOTYPE = "do"; const std::string SEQUENCERD_EXIT = "exit"; const std::string SEQUENCERD_FINEACQUIRE= "fineacquire"; +const std::string SEQUENCERD_FLEXCOMP = "flexcomp"; const std::string SEQUENCERD_GETONETARGET = "getone"; const std::string SEQUENCERD_GUIDE = "guide"; const std::string SEQUENCERD_MODEXPTIME = "modexptime"; @@ -52,6 +53,7 @@ const std::vector SEQUENCERD_SYNTAX = { SEQUENCERD_DOTYPE+" [ one | all ]", SEQUENCERD_EXIT, SEQUENCERD_FINEACQUIRE+" [ enable | disable ]", + SEQUENCERD_FLEXCOMP+" [ enable | disable ]", SEQUENCERD_GETONETARGET, SEQUENCERD_GUIDE, SEQUENCERD_MODEXPTIME+" ", diff --git a/sequencerd/sequence.cpp b/sequencerd/sequence.cpp index 00e1b2b6..8384f948 100644 --- a/sequencerd/sequence.cpp +++ b/sequencerd/sequence.cpp @@ -259,6 +259,9 @@ namespace Sequencer { // user-settable: should automatic fine acquisition run? jmessage_out[Key::Sequencer::SHOULD_FINEACQUIRE] = this->should_fineacquire.load(); + // user-settable: should flexure compensation be applied? + jmessage_out[Key::Sequencer::SHOULD_FLEXCOMP] = this->should_flexcomp.load(); + try { this->publisher->publish( jmessage_out, Topic::SEQ_SEQSTATE ); } @@ -2417,6 +2420,11 @@ namespace Sequencer { /***** Sequencer::Sequence::flexure_set *************************************/ /** * @brief compensate for flexure + * @details When compensation is user-disabled the actuators are instead moved + * to their configured default positions. The defaults are the + * compensation origin (flexured adds the computed delta to defpos), + * so this is the neutral state; it prevents a previous target's + * compensation from being left applied to every subsequent target. * @return NO_ERROR * */ @@ -2426,6 +2434,23 @@ namespace Sequencer { ScopedState thr_state( thread_state_manager, Sequencer::THR_FLEXURE_SET ); ScopedState wait_state( wait_state_manager, Sequencer::SEQ_WAIT_FLEXURE ); + // Compensation can be user-disabled, in which case neutralize the compensator + // by moving the actuators to their defaults, once. Failure here is not fatal + // but warn and let the next target retry. + // + if ( !this->should_flexcomp.load() ) { + if ( !this->cancel_flag.load() && !this->is_flexure_default.load() ) { + if ( this->flexured.command( FLEXURED_DEFAULTPOS ) != NO_ERROR ) { + this->broadcast.warning( function, "flexure compensation disabled: ERROR moving actuators to default" ); + } + else { + this->is_flexure_default.store(true); + this->broadcast.notice( function, "flexure compensation disabled: actuators moved to default" ); + } + } + return NO_ERROR; + } + // build up list of activate chans std::ostringstream activechans; const std::string calname = std::string(this->target.iscal ? this->target.name : "SCIENCE"); @@ -2444,7 +2469,9 @@ namespace Sequencer { throw std::runtime_error("setting flexure compensator"); } - this->broadcast.notice( function, "set flexure compensator for "+activechans.str()); + this->is_flexure_default.store(false); + + this->broadcast.notice( function, "flexure compensator set for "+activechans.str()); return NO_ERROR; } @@ -4190,7 +4217,7 @@ namespace Sequencer { */ long Sequence::fine_acquire(std::string args, std::string &retstring) { if (args=="help"||args=="?") { - retstring = SLICECAMD_FINEACQUIRE; + retstring = SEQUENCERD_FINEACQUIRE; retstring.append( " [ enable | disable ]\n" ); retstring.append( " enables or disables the automatic fine acquisition step\n" ); retstring.append( " no arg returns state only\n" ); @@ -4221,6 +4248,47 @@ namespace Sequencer { /***** Sequencer::Sequence::fine_acquire ************************************/ + /***** Sequencer::Sequence::flexure_compensate ******************************/ + /** + * @brief enable or disable flexure compensation + * @param[in] args enable|disable + * @param[out] retstring state {enabled|disabled} + * @return ERROR|NO_ERROR|HELP + * + */ + long Sequence::flexure_compensate(std::string args, std::string &retstring) { + if (args=="help"||args=="?") { + retstring = SEQUENCERD_FLEXCOMP; + retstring.append( " [ enable | disable ]\n" ); + retstring.append( " enables or disables the flexure compensation step\n" ); + retstring.append( " no arg returns state only\n" ); + return HELP; + } + + const bool prev = this->should_flexcomp.load(); + + if (args=="enable") this->should_flexcomp.store(true); + else + if (args=="disable") this->should_flexcomp.store(false); + else + if (!args.empty()) { + logwrite("Sequencer::Sequence::flexure_compensate", + "ERROR invalid '"+args+"' expected enable|disable"); + return ERROR; + } + + retstring = this->should_flexcomp.load() ? "enabled" : "disabled"; + + // publish on change + if ( this->should_flexcomp.load() != prev ) { + this->publish_seqstate(); + } + + return NO_ERROR; + } + /***** Sequencer::Sequence::flexure_compensate ******************************/ + + /***** Sequencer::Sequence::test ********************************************/ /** * @brief test routines diff --git a/sequencerd/sequence.h b/sequencerd/sequence.h index a64601f2..7342d369 100644 --- a/sequencerd/sequence.h +++ b/sequencerd/sequence.h @@ -289,6 +289,8 @@ namespace Sequencer { private: zmqpp::context context; bool ready_to_start; ///< set on nightly startup success, used to return seqstate to READY after an abort + std::atomic should_flexcomp{true}; ///< should flexure compensation be applied? + std::atomic is_flexure_default{false}; ///< are flexure actuators at their default (uncompensated) positions? std::atomic can_expose; std::atomic is_science_frame_transfer; ///< is frame transfer enabled for science cameras std::atomic notify_tcs_next_target; ///< notify TCS of next target when remaining time within TCS_PREAUTH_TIME @@ -562,6 +564,7 @@ namespace Sequencer { long parse_state( std::string whoami, std::string reply, bool &state ); ///< parse true|false state from reply string void dothread_test_fpoffset(); ///< for testing, calls Python function from thread long fine_acquire( std::string args, std::string &retstring ); ///< enable|disable fineacquisition step + long flexure_compensate( std::string args, std::string &retstring ); ///< enable|disable flexure compensation long test( std::string args, std::string &retstring ); ///< handles test commands long extract_tcs_value( std::string reply, int &value ); ///< extract value returned by the TCS via tcsd long parse_tcs_generic( int value ); ///< parse generic TCS reply diff --git a/sequencerd/sequencer_server.cpp b/sequencerd/sequencer_server.cpp index f3b5d9f6..405b43f3 100644 --- a/sequencerd/sequencer_server.cpp +++ b/sequencerd/sequencer_server.cpp @@ -1204,7 +1204,11 @@ namespace Sequencer { } else if ( cmd == SEQUENCERD_FINEACQUIRE ) { - this->sequence.fine_acquire(args, retstring); + ret = this->sequence.fine_acquire(args, retstring); + } + else + if ( cmd == SEQUENCERD_FLEXCOMP ) { + ret = this->sequence.flexure_compensate(args, retstring); } else