API
 
Loading...
Searching...
No Matches
alignLoop.hpp
Go to the documentation of this file.
1/** \file alignLoop.hpp
2 * \brief The MagAO-X alignment loop application header file.
3 *
4 * \ingroup alignLoop_files
5 */
6
7#ifndef alignLoop_hpp
8#define alignLoop_hpp
9
10#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
11#include "../../magaox_git_version.h"
12
13/** \defgroup alignLoop
14 * \brief The MagAO-X application for alignment-loop control.
15 *
16 * <a href="../handbook/operating/software/apps/XXXXXX.html">Application Documentation</a>
17 *
18 * \ingroup apps
19 *
20 */
21
22/** \defgroup alignLoop_files
23 * \ingroup alignLoop
24 */
25
26namespace MagAOX
27{
28namespace app
29{
30
31/// The MagAO-X alignment-loop controller.
32/**
33 * \ingroup alignLoop
34 */
35class alignLoop : public MagAOXApp<true>, public dev::shmimMonitor<alignLoop>
36{
37 // Give the test harness access.
38 friend class alignLoop_test;
39
40 friend class dev::shmimMonitor<alignLoop>;
41
42 public:
43 // The base shmimMonitor type
45
46 protected:
47 /** \name Configurable Parameters
48 *@{
49 */
50
51 std::vector<std::string> m_ctrlDevices; ///< Device names of the controlled axes.
52 std::vector<std::string> m_ctrlProperties; ///< INDI properties used to send loop commands.
53 std::vector<std::string> m_ctrlCurrents; ///< INDI elements holding the current controller values.
54 std::vector<std::string> m_ctrlTargets; ///< INDI elements to which updated commands are written.
55
56 std::vector<float> m_currents; ///< Most recently received controller values.
57
58 std::vector<pcf::IndiProperty> m_indiP_ctrl; ///< Registered controller properties for each axis.
59
60 std::string m_intMatFile; ///< Interaction matrix file name from configuration.
61
62 std::vector<float> m_defaultGains; ///< Default per-axis gains loaded from configuration.
63
64 std::string m_upstreamDevice; ///< Upstream loop device that this loop can follow.
65 std::string m_upstreamProperty{ "loop_state" }; ///< Toggle property on the upstream loop to monitor.
66 bool m_upstreamFollowClosed{ false }; ///< If true, this loop closes when the upstream loop closes.
67
68 ///@}
69
70 mx::improc::eigenImage<float> m_intMat; ///< Interaction matrix mapping measurements to commands.
71
72 mx::improc::eigenImage<float> m_measurements; ///< Most recent measured loop disturbance vector.
73 float m_delta0{ 0 }; ///< Latest first-axis residual.
74 float m_delta1{ 0 }; ///< Latest second-axis residual.
75
76 mx::improc::eigenImage<float> m_commands; ///< Most recent command delta vector.
77
78 float m_ggain{ 0 }; ///< Global loop gain applied to all axes.
79
80 std::vector<float> m_gains; ///< Active per-axis gains.
81
82 bool m_ctrlEnabled{ false }; ///< True when the loop is closed and may send controller commands.
83
84 public:
85 /// Default c'tor.
86 alignLoop();
87
88 /// D'tor, declared and defined for noexcept.
90 {
91 }
92
93 /// Set up the app configuration interface.
94 virtual void setupConfig();
95
96 /// Implementation of loadConfig logic, separated for testing.
97 /** This is called by loadConfig().
98 */
100 mx::app::appConfigurator &_config /**< [in] an application configuration from which to load values*/ );
101
102 /// Load the application configuration.
103 virtual void loadConfig();
104
105 /// Startup function
106 /**
107 *
108 */
109 virtual int appStartup();
110
111 /// Implementation of the FSM for alignLoop.
112 /**
113 * \returns 0 on no critical error
114 * \returns -1 on an error requiring shutdown
115 */
116 virtual int appLogic();
117
118 /// Shutdown the app.
119 /**
120 *
121 */
122 virtual int appShutdown();
123
124 /// Change the loop state.
125 int toggleLoop( bool onoff /**< [in] true to close the loop and false to open it */ );
126
127 // shmimMonitor interface:
128 /// Allocate working memory for the monitored image stream.
129 int allocate( const dev::shmimT &dummy /**< [in] ignored shmim descriptor */ );
130
131 /// Process a new measurement image from the monitored stream.
132 int processImage( void *curr_src /**< [in] pointer to the current image buffer */,
133 const dev::shmimT &dummy /**< [in] ignored shmim descriptor */
134 );
135
136 /// Send the newly computed commands to the controller devices.
137 int sendCommands( std::vector<float> &commands /**< [in] command values to transmit */ );
138
139 // INDI
140
141 pcf::IndiProperty m_indiP_deltas; ///< Published loop residual values.
142
143 pcf::IndiProperty m_indiP_ggain; ///< INDI property exposing the global loop gain.
144 pcf::IndiProperty m_indiP_ctrlEnabled; ///< INDI property exposing the loop open/closed state.
145
148
149 /// Route controller property updates into the instance callback.
150 static int st_setCallBack_ctrl( void *app /**< [in] application instance pointer */,
151 const pcf::IndiProperty &ipRecv /**< [in] controller property update */
152 )
153 {
154 return static_cast<alignLoop *>( app )->setCallBack_ctrl( ipRecv );
155 }
156
157 /// Update cached controller current values from an INDI property callback.
158 int setCallBack_ctrl( const pcf::IndiProperty &ipRecv /**< [in] controller property update */ );
159
160 int m_upstreamState{ 0 }; ///< Cached upstream state indicator.
161 pcf::IndiProperty m_indiP_upstream; ///< Property used to monitor the upstream loop state.
162
164};
165
166alignLoop::alignLoop() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
167{
168
169 return;
170}
171
173{
175
176 config.add( "ctrl.devices",
177 "",
178 "ctrl.devices",
179 argType::Required,
180 "ctrl",
181 "devices",
182 false,
183 "string",
184 "Device names of the controller(s) (one per element)." );
185 config.add( "ctrl.properties",
186 "",
187 "ctrl.properties",
188 argType::Required,
189 "ctrl",
190 "properties",
191 false,
192 "string",
193 "Properties of the ctrl devices to which to give the commands. One per element" );
194 config.add( "ctrl.currents",
195 "",
196 "ctrl.currents",
197 argType::Required,
198 "ctrl",
199 "currents",
200 false,
201 "vector<string>",
202 "current elements of the properties on which base the commands." );
203 config.add( "ctrl.targets",
204 "",
205 "ctrl.targets",
206 argType::Required,
207 "ctrl",
208 "targets",
209 false,
210 "vector<string>",
211 "target elements of the properties to which to send the commands." );
212
213 config.add(
214 "loop.gain", "", "loop.gain", argType::Required, "loop", "gain", false, "float", "default global loop gain." );
215 config.add( "loop.intMat",
216 "",
217 "loop.intMat",
218 argType::Required,
219 "loop",
220 "intMat",
221 false,
222 "string",
223 "file name of the interaction matrix." );
224 config.add( "loop.gains",
225 "",
226 "loop.gains",
227 argType::Required,
228 "loop",
229 "gains",
230 false,
231 "vector<float>",
232 "default loop gains. If single number, it is applied to all axes." );
233 config.add( "loop.upstream",
234 "",
235 "loop.upstream",
236 argType::Required,
237 "loop",
238 "upstream",
239 false,
240 "string",
241 "Upstream loop device name. This loop will open, and optionally close, with the upstream loop. "
242 "Default none." );
243 config.add( "loop.upstreamProperty",
244 "",
245 "loop.upstreamProperty",
246 argType::Required,
247 "loop",
248 "upstreamProperty",
249 false,
250 "string",
251 "Property of upstream loop device to follow. Must be a toggle. Default is loop_state." );
252 config.add( "loop.upstreamFollowClosed",
253 "",
254 "loop.upstreamFollowClosed",
255 argType::Required,
256 "loop",
257 "upstreamFollowClosed",
258 false,
259 "bool",
260 "If true, this loop also closes when the upstream loop closes. Default is false." );
261}
262
263int alignLoop::loadConfigImpl( mx::app::appConfigurator &_config )
264{
266
267 _config( m_ctrlDevices, "ctrl.devices" );
268 _config( m_ctrlProperties, "ctrl.properties" );
269 _config( m_ctrlCurrents, "ctrl.currents" );
270 _config( m_ctrlTargets, "ctrl.targets" );
271 _config( m_ggain, "loop.gain" );
272 _config( m_intMatFile, "loop.intMat" );
273 _config( m_defaultGains, "loop.gains" );
274 _config( m_upstreamDevice, "loop.upstream" );
275 _config( m_upstreamProperty, "loop.upstreamProperty" );
276 _config( m_upstreamFollowClosed, "loop.upstreamFollowClosed" );
277 return 0;
278}
279
281{
282 loadConfigImpl( config );
283}
284
286{
287 if( shmimMonitorT::appStartup() < 0 )
288 {
289 return log<software_error, -1>( { __FILE__, __LINE__ } );
290 }
291
292 if( m_ctrlTargets.size() != m_ctrlDevices.size() )
293 {
294 return log<software_error, -1>( { __FILE__, __LINE__, "ctrl.Targets and ctrl.devices are not the same size" } );
295 }
296
297 if( m_ctrlTargets.size() != m_ctrlProperties.size() )
298 {
299 return log<software_error, -1>(
300 { __FILE__, __LINE__, "ctrl.Targets and ctrl.properties are not the same size" } );
301 }
302
303 if( m_ctrlTargets.size() != m_ctrlCurrents.size() )
304 {
305 return log<software_error, -1>(
306 { __FILE__, __LINE__, "ctrl.Currents and ctrl.properties are not the same size" } );
307 }
308
309 if( m_ctrlTargets.size() != m_defaultGains.size() )
310 {
311 if( m_defaultGains.size() == 1 )
312 {
313 float g = m_defaultGains[0];
314 m_defaultGains.resize( m_ctrlTargets.size(), g );
315 log<text_log>( "Setting loop.gains gains to be same size as ctrl.Targets", logPrio::LOG_NOTICE );
316 }
317 else
318 {
319 return log<software_error, -1>(
320 { __FILE__, __LINE__, "ctrl.Targets and loop.gains are not the same size" } );
321 }
322 }
323
324 CREATE_REG_INDI_RO_NUMBER( m_indiP_deltas, "deltas", "Deltas", "Deltas" );
325 m_indiP_deltas.add( pcf::IndiElement( "delta0" ) );
326 m_indiP_deltas["delta0"] = 0;
327 m_indiP_deltas.add( pcf::IndiElement( "delta1" ) );
328 m_indiP_deltas["delta1"] = 0;
329
330 m_gains.resize( m_defaultGains.size() );
331 for( size_t n = 0; n < m_defaultGains.size(); ++n )
333
334 createStandardIndiNumber<unsigned>( m_indiP_ggain, "loop_gain", 0, 1, 0, "%0.2f" );
335 m_indiP_ggain["current"] = m_ggain;
336 m_indiP_ggain["target"] = m_ggain;
338 {
340 return -1;
341 }
342
345 {
347 return -1;
348 }
349
350 m_currents.resize( m_ctrlDevices.size(), -1e15 );
351
352 m_indiP_ctrl.resize( m_ctrlDevices.size() );
353
354 for( size_t n = 0; n < m_ctrlDevices.size(); ++n )
355 {
357 }
358
359 m_commands.resize( m_ctrlTargets.size(), m_ctrlTargets.size() );
360 m_commands.setZero();
361
362 m_intMat.resize( m_ctrlTargets.size(), m_ctrlTargets.size() );
363 m_intMat.setZero();
364 m_intMat( 1, 0 ) = 0.926;
365 m_intMat( 1, 1 ) = -0.370;
366 m_intMat( 0, 0 ) = 0.185;
367 m_intMat( 0, 1 ) = 0.926;
368
369 /*
370 std::string intMatPath = m_calibDir + "/" + m_intMatFile;
371
372 mx::fits::fitsFile<float> ff;
373 try
374 {
375 ff.read(m_intMat, intMatPath);
376 }
377 catch(...)
378 {
379 return log<software_error, -1>({__FILE__, __LINE__, "error reading loop.intMatFile. Does it exist?"});
380 }
381
382 if(m_intMat.rows() != m_ctrlTargets.size())
383 {
384 return log<software_error, -1>({__FILE__, __LINE__, "interaction matrix wrong size: rows do not match sensor
385 Targets"});
386 }
387
388 if(m_intMat.cols() != m_correctorTargets.size())
389 {
390 return log<software_error, -1>({__FILE__, __LINE__, "interaction matrix wrong size: cols do not match
391 corrector Targets"});
392 }
393 */
394
395 // Get the loop state for managing offloading
396 if( m_upstreamDevice != "" )
397 {
399 }
400
401 return 0;
402}
403
405{
406 if( shmimMonitorT::appLogic() < 0 )
407 {
408 return log<software_error, -1>( { __FILE__, __LINE__ } );
409 }
410
412
413 return 0;
414}
415
417{
419
420 return 0;
421}
422
423int alignLoop::toggleLoop( bool onoff )
424{
425 if( !m_ctrlEnabled && onoff ) // not enabled so change
426 {
427 m_ctrlEnabled = true;
429 updateSwitchIfChanged( m_indiP_ctrlEnabled, "toggle", pcf::IndiElement::On, INDI_OK );
430 return 0;
431 }
432
433 if( m_ctrlEnabled && !onoff )
434 {
435 m_ctrlEnabled = false;
437 updateSwitchIfChanged( m_indiP_ctrlEnabled, "toggle", pcf::IndiElement::Off, INDI_IDLE );
438
439 return 0;
440 }
441
442 return 0;
443}
444
445inline int alignLoop::allocate( const dev::shmimT &dummy )
446{
447 static_cast<void>( dummy );
448
449 std::lock_guard<std::mutex> guard( m_indiMutex );
450
451 std::cerr << shmimMonitorT::m_width << shmimMonitorT::m_height << "\n";
453
454 return 0;
455}
456
457inline int alignLoop::processImage( void *curr_src, const dev::shmimT &dummy )
458{
459 static_cast<void>( dummy );
460
461 for( unsigned nn = 0; nn < shmimMonitorT::m_width * shmimMonitorT::m_height; ++nn )
462 {
463 m_measurements.data()[nn] = ( static_cast<float *>( curr_src ) )[nn];
464 }
465
466 m_delta0 = m_measurements( 0, 0 );
467 m_delta1 = m_measurements( 1, 0 );
468
469 std::cout << "measurements: ";
470 for( int cc = 0; cc < m_measurements.rows(); ++cc )
471 {
472 std::cout << m_measurements( cc, 0 ) << " ";
473 }
474 std::cout << "\n";
475
476 if( m_currents[0] < -1e14 )
477 return 0;
478
479 m_commands.matrix() = m_intMat.matrix() * m_measurements.matrix();
480
481 std::cout << "delta commands: ";
482 for( int cc = 0; cc < m_measurements.rows(); ++cc )
483 {
484 std::cout << -m_commands( cc, 0 ) << " ";
485 }
486 std::cout << "\n";
487
488 std::vector<float> commands;
489 commands.resize( m_measurements.rows() );
490
491 std::cout << "commands: ";
492 for( int cc = 0; cc < m_measurements.rows(); ++cc )
493 {
495 std::cout << commands[cc] << " ";
496 }
497 std::cout << "\n";
498
499 // And send commands.
500 int rv;
501 if( m_ctrlEnabled )
502 {
504 }
505 else
506 {
507 rv = 0;
508 }
509
511 std::vector<std::string>( { "delta0", "delta1" } ),
512 std::vector<float>( { m_delta0, m_delta1 } ) );
513 return rv;
514}
515
516inline int alignLoop::sendCommands( std::vector<float> &commands )
517{
518 for( size_t n = 0; n < m_ctrlDevices.size(); ++n )
519 {
520 pcf::IndiProperty ip( pcf::IndiProperty::Number );
521
522 ip.setDevice( m_ctrlDevices[n] );
523 ip.setName( m_ctrlProperties[n] );
524 ip.add( pcf::IndiElement( m_ctrlTargets[n] ) );
526
528 }
529
530 return 0;
531}
532
533INDI_NEWCALLBACK_DEFN( alignLoop, m_indiP_ggain )( const pcf::IndiProperty &ipRecv )
534{
535 if( ipRecv.getName() != m_indiP_ggain.getName() )
536 {
537 log<software_error>( { __FILE__, __LINE__, "invalid indi property received" } );
538 return -1;
539 }
540
541 float target;
542
543 if( indiTargetUpdate( m_indiP_ggain, target, ipRecv, true ) < 0 )
544 {
545 log<software_error>( { __FILE__, __LINE__ } );
546 return -1;
547 }
548
549 m_ggain = target;
550
551 updateIfChanged( m_indiP_ggain, "current", m_ggain );
552 updateIfChanged( m_indiP_ggain, "target", m_ggain );
553
554 log<text_log>( "set global gain to " + std::to_string( m_ggain ), logPrio::LOG_NOTICE );
555
556 return 0;
557}
558
559INDI_NEWCALLBACK_DEFN( alignLoop, m_indiP_ctrlEnabled )( const pcf::IndiProperty &ipRecv )
560{
561 if( ipRecv.getName() != m_indiP_ctrlEnabled.getName() )
562 {
563 log<software_error>( { __FILE__, __LINE__, "invalid indi property received" } );
564 return -1;
565 }
566
567 // switch is toggled to on
568 if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
569 {
570 return toggleLoop( true );
571 }
572
573 // switch is toggle to off
574 if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off )
575 {
576 return toggleLoop( false );
577 }
578
579 return 0;
580}
581
582inline int alignLoop::setCallBack_ctrl( const pcf::IndiProperty &ipRecv )
583{
584 for( size_t n = 0; n < m_ctrlDevices.size(); ++n )
585 {
586 if( ipRecv.getDevice() == m_ctrlDevices[n] )
587 {
588 if( ipRecv.getName() == m_ctrlProperties[n] && ipRecv.find( m_ctrlCurrents[n] ) )
589 {
590 m_currents[n] = ipRecv[m_ctrlCurrents[n]].get<float>();
591 }
592 }
593 }
594
595 return 0;
596}
597
598INDI_SETCALLBACK_DEFN( alignLoop, m_indiP_upstream )( const pcf::IndiProperty &ipRecv )
599{
600 if( ipRecv.getName() != m_indiP_upstream.getName() )
601 {
602 return log<software_error>( { __FILE__, __LINE__, "wrong INDI property received" } );
603 }
604
605 if( !ipRecv.find( "toggle" ) )
606 return 0;
607
608 if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On && m_upstreamFollowClosed )
609 {
610 std::cerr << "upstream on\n";
611 return toggleLoop( true );
612 }
613 else if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::Off )
614 {
615 std::cerr << "upstream off\n";
616 return toggleLoop( false );
617 }
618
619 return 0;
620}
621
622} // namespace app
623} // namespace MagAOX
624
625#endif // alignLoop_hpp
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.
Definition alignLoop.hpp:36
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.
Definition alignLoop.hpp:66
std::vector< std::string > m_ctrlProperties
INDI properties used to send loop commands.
Definition alignLoop.hpp:52
mx::improc::eigenImage< float > m_commands
Most recent command delta vector.
Definition alignLoop.hpp:76
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.
Definition alignLoop.hpp:80
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.
Definition alignLoop.hpp:53
std::vector< std::string > m_ctrlTargets
INDI elements to which updated commands are written.
Definition alignLoop.hpp:54
INDI_SETCALLBACK_DECL(alignLoop, m_indiP_upstream)
float m_delta0
Latest first-axis residual.
Definition alignLoop.hpp:73
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.
Definition alignLoop.hpp:74
dev::shmimMonitor< alignLoop > shmimMonitorT
Definition alignLoop.hpp:44
mx::improc::eigenImage< float > m_intMat
Interaction matrix mapping measurements to commands.
Definition alignLoop.hpp:70
std::vector< std::string > m_ctrlDevices
Device names of the controlled axes.
Definition alignLoop.hpp:51
std::string m_upstreamDevice
Upstream loop device that this loop can follow.
Definition alignLoop.hpp:64
std::vector< float > m_defaultGains
Default per-axis gains loaded from configuration.
Definition alignLoop.hpp:62
std::string m_intMatFile
Interaction matrix file name from configuration.
Definition alignLoop.hpp:60
virtual int appLogic()
Implementation of the FSM for alignLoop.
std::string m_upstreamProperty
Toggle property on the upstream loop to monitor.
Definition alignLoop.hpp:65
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.
Definition alignLoop.hpp:56
~alignLoop() noexcept
D'tor, declared and defined for noexcept.
Definition alignLoop.hpp:89
float m_ggain
Global loop gain applied to all axes.
Definition alignLoop.hpp:78
alignLoop()
Default c'tor.
friend class alignLoop_test
Definition alignLoop.hpp:38
INDI_NEWCALLBACK_DECL(alignLoop, m_indiP_ggain)
std::vector< pcf::IndiProperty > m_indiP_ctrl
Registered controller properties for each axis.
Definition alignLoop.hpp:58
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.
Definition alignLoop.hpp:72
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.
Definition alignLoop.hpp:82
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.
#define INDI_IDLE
Definition indiUtils.hpp:27
#define INDI_OK
Definition indiUtils.hpp:28
const pcf::IndiProperty & ipRecv
updateIfChanged(m_indiP_angle, "target", m_angle)
Definition dm.hpp:19
static constexpr logPrioT LOG_NOTICE
A normal but significant condition.
@ OPERATING
The device is operating, other than homing.
Software ERR log entry.