10#include "../../libMagAOX/libMagAOX.hpp"
11#include "../../magaox_git_version.h"
100 mx::app::appConfigurator &
_config );
151 const pcf::IndiProperty &
ipRecv
176 config.add(
"ctrl.devices",
184 "Device names of the controller(s) (one per element)." );
185 config.add(
"ctrl.properties",
193 "Properties of the ctrl devices to which to give the commands. One per element" );
194 config.add(
"ctrl.currents",
202 "current elements of the properties on which base the commands." );
203 config.add(
"ctrl.targets",
211 "target elements of the properties to which to send the commands." );
214 "loop.gain",
"",
"loop.gain", argType::Required,
"loop",
"gain",
false,
"float",
"default global loop gain." );
215 config.add(
"loop.intMat",
223 "file name of the interaction matrix." );
224 config.add(
"loop.gains",
232 "default loop gains. If single number, it is applied to all axes." );
233 config.add(
"loop.upstream",
241 "Upstream loop device name. This loop will open, and optionally close, with the upstream loop. "
243 config.add(
"loop.upstreamProperty",
245 "loop.upstreamProperty",
251 "Property of upstream loop device to follow. Must be a toggle. Default is loop_state." );
252 config.add(
"loop.upstreamFollowClosed",
254 "loop.upstreamFollowClosed",
257 "upstreamFollowClosed",
260 "If true, this loop also closes when the upstream loop closes. Default is false." );
300 {
__FILE__,
__LINE__,
"ctrl.Targets and ctrl.properties are not the same size" } );
306 {
__FILE__,
__LINE__,
"ctrl.Currents and ctrl.properties are not the same size" } );
320 {
__FILE__,
__LINE__,
"ctrl.Targets and loop.gains are not the same size" } );
447 static_cast<void>(
dummy );
459 static_cast<void>(
dummy );
469 std::cout <<
"measurements: ";
481 std::cout <<
"delta commands: ";
491 std::cout <<
"commands: ";
511 std::vector<std::string>( {
"delta0",
"delta1" } ),
520 pcf::IndiProperty
ip( pcf::IndiProperty::Number );
535 if(
ipRecv.getName() != m_indiP_ggain.getName() )
537 log<software_error>( { __FILE__, __LINE__,
"invalid indi property received" } );
543 if( indiTargetUpdate( m_indiP_ggain,
target,
ipRecv,
true ) < 0 )
545 log<software_error>( { __FILE__, __LINE__ } );
561 if(
ipRecv.getName() != m_indiP_ctrlEnabled.getName() )
563 log<software_error>( { __FILE__, __LINE__,
"invalid indi property received" } );
568 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On )
570 return toggleLoop(
true );
574 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off )
576 return toggleLoop(
false );
600 if(
ipRecv.getName() != m_indiP_upstream.getName() )
602 return log<software_error>( { __FILE__, __LINE__,
"wrong INDI property received" } );
605 if( !
ipRecv.find(
"toggle" ) )
608 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On && m_upstreamFollowClosed )
610 std::cerr <<
"upstream on\n";
611 return toggleLoop(
true );
613 else if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off )
615 std::cerr <<
"upstream off\n";
616 return toggleLoop(
false );
The base-class for XWCTk applications.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
stateCodes::stateCodeT state()
Get the current state code.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
int createStandardIndiToggleSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single toggle element.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
std::mutex m_indiMutex
Mutex for locking INDI communications.
int sendNewProperty(const pcf::IndiProperty &ipSend, const std::string &el, const T &newVal)
Send a newProperty command to another device (using the INDI Client interface)
int registerIndiPropertySet(pcf::IndiProperty &prop, const std::string &devName, const std::string &propName, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is monitored for updates from others.
The MagAO-X alignment-loop controller.
pcf::IndiProperty m_indiP_ctrlEnabled
INDI property exposing the loop open/closed state.
bool m_upstreamFollowClosed
If true, this loop closes when the upstream loop closes.
std::vector< std::string > m_ctrlProperties
INDI properties used to send loop commands.
mx::improc::eigenImage< float > m_commands
Most recent command delta vector.
static int st_setCallBack_ctrl(void *app, const pcf::IndiProperty &ipRecv)
Route controller property updates into the instance callback.
int toggleLoop(bool onoff)
Change the loop state.
int allocate(const dev::shmimT &dummy)
Allocate working memory for the monitored image stream.
std::vector< float > m_gains
Active per-axis gains.
virtual int appStartup()
Startup function.
INDI_NEWCALLBACK_DECL(alignLoop, m_indiP_ctrlEnabled)
std::vector< std::string > m_ctrlCurrents
INDI elements holding the current controller values.
std::vector< std::string > m_ctrlTargets
INDI elements to which updated commands are written.
INDI_SETCALLBACK_DECL(alignLoop, m_indiP_upstream)
float m_delta0
Latest first-axis residual.
int processImage(void *curr_src, const dev::shmimT &dummy)
Process a new measurement image from the monitored stream.
pcf::IndiProperty m_indiP_deltas
Published loop residual values.
float m_delta1
Latest second-axis residual.
dev::shmimMonitor< alignLoop > shmimMonitorT
mx::improc::eigenImage< float > m_intMat
Interaction matrix mapping measurements to commands.
std::vector< std::string > m_ctrlDevices
Device names of the controlled axes.
std::string m_upstreamDevice
Upstream loop device that this loop can follow.
std::vector< float > m_defaultGains
Default per-axis gains loaded from configuration.
std::string m_intMatFile
Interaction matrix file name from configuration.
virtual int appLogic()
Implementation of the FSM for alignLoop.
std::string m_upstreamProperty
Toggle property on the upstream loop to monitor.
int setCallBack_ctrl(const pcf::IndiProperty &ipRecv)
Update cached controller current values from an INDI property callback.
virtual int appShutdown()
Shutdown the app.
pcf::IndiProperty m_indiP_ggain
INDI property exposing the global loop gain.
std::vector< float > m_currents
Most recently received controller values.
~alignLoop() noexcept
D'tor, declared and defined for noexcept.
float m_ggain
Global loop gain applied to all axes.
alignLoop()
Default c'tor.
friend class alignLoop_test
INDI_NEWCALLBACK_DECL(alignLoop, m_indiP_ggain)
std::vector< pcf::IndiProperty > m_indiP_ctrl
Registered controller properties for each axis.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
int m_upstreamState
Cached upstream state indicator.
mx::improc::eigenImage< float > m_measurements
Most recent measured loop disturbance vector.
pcf::IndiProperty m_indiP_upstream
Property used to monitor the upstream loop state.
virtual void setupConfig()
Set up the app configuration interface.
int sendCommands(std::vector< float > &commands)
Send the newly computed commands to the controller devices.
virtual void loadConfig()
Load the application configuration.
bool m_ctrlEnabled
True when the loop is closed and may send controller commands.
int appStartup()
Startup function.
uint32_t m_width
The width of the images in the stream.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int appLogic()
Checks the shmimMonitor thread.
uint32_t m_height
The height of the images in the stream.
int appShutdown()
Shuts down the shmimMonitor thread.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
#define INDI_SETCALLBACK_DEFN(class, prop)
Define the callback for a set property request.
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
#define CREATE_REG_INDI_RO_NUMBER(prop, name, label, group)
Create and register a RO INDI property as a number, using the standard callback name.
const pcf::IndiProperty & ipRecv
updateIfChanged(m_indiP_angle, "target", m_angle)
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
@ OPERATING
The device is operating, other than homing.