API
 
Loading...
Searching...
No Matches
kTracker.hpp
Go to the documentation of this file.
1/** \file kTracker.hpp
2 * \brief The MagAO-X K-mirror rotation tracker header file
3 *
4 * \ingroup kTracker_files
5 */
6
7#ifndef kTracker_hpp
8#define kTracker_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#include <cmath>
14
15#include <mx/math/gslInterpolation.hpp>
16#include <mx/ioutils/readColumns.hpp>
17
18/** \defgroup kTracker
19 * \brief The MagAO-X application to track pupil rotation with the k-mirror.
20 *
21 * <a href="../handbook/operating/software/apps/kTracker.html">Application Documentation</a>
22 *
23 * \ingroup apps
24 *
25 */
26
27/** \defgroup kTracker_files
28 * \ingroup kTracker
29 */
30
31namespace MagAOX
32{
33namespace app
34{
35
36/// The MagAO-X K-mirror tracker.
37/**
38 * \ingroup kTracker
39 */
40class kTracker : public MagAOXApp<true>
41{
42
43 // Give the test harness access.
44 friend class kTracker_test;
45
46 protected:
47 /** \name Configurable Parameters
48 *@{
49 */
50
51 float m_zero{ 0 }; ///< The starting point for the K-mirror at zd = 0.
52
53 int m_sign{ 1 }; ///< The sign to apply to the zenith distance to rotate the K-mirror.
54
55 std::string m_devName{ "stagek" }; ///< The device name of the K-mirror stage. Default is 'stagek'.
56 std::string m_tcsDevName{
57 "tcsi" }; ///< The device name of the TCS interface providing 'teldata.zd'. Default is 'tcsi'.
58
59 float m_updateInterval{ 10 }; ///< The interval at which to update positions, in seconds. Default is 10 secs.
60
61 ///@}
62
63 bool m_tracking{ false }; ///< True when automatic K-mirror updates are enabled.
64
65 float m_zd{ 0 }; ///< The most recent finite zenith distance received from the TCS interface.
66
67 bool m_haveZD{ false }; ///< True once at least one valid zenith distance has been received.
68
69 double m_lastUpdate{ 0 }; ///< Timestamp of the last stage command dispatched by the tracker.
70
71 public:
72 /// Default c'tor.
73 kTracker();
74
75 /// D'tor, declared and defined for noexcept.
77 {
78 }
79
80 /// Set up configuration entries.
81 virtual void setupConfig();
82
83 /// Implementation of loadConfig logic, separated for testing.
84 /** This is called by loadConfig().
85 */
87 mx::app::appConfigurator &_config /**< [in] an application configuration from which to load values*/ );
88
89 /// Load configuration values.
90 virtual void loadConfig();
91
92 /// Startup function
93 /**
94 *
95 */
96 virtual int appStartup();
97
98 /// Implementation of the FSM for kTracker.
99 /**
100 * \returns 0 on no critical error
101 * \returns -1 on an error requiring shutdown
102 */
103 virtual int appLogic();
104
105 /// Shutdown the app.
106 /**
107 *
108 */
109 virtual int appShutdown();
110
111 /** @name INDI
112 *
113 * @{
114 */
115 protected:
116 pcf::IndiProperty m_indiP_tracking; ///< The INDI toggle used to enable or disable tracking.
117
118 pcf::IndiProperty m_indiP_teldata; ///< The subscribed TCS property providing zenith distance updates.
119
120 pcf::IndiProperty m_indiP_kpos; ///< The outbound K-mirror stage position command property.
121
122 public:
123 /// Handle new tracking toggle requests.
125
126 /// Handle incoming telescope data updates.
128
129 ///@}
130};
131
132kTracker::kTracker() : MagAOXApp( MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED )
133{
134
135 return;
136}
137
139{
140 config.add( "k.zero",
141 "",
142 "k.zero",
143 argType::Required,
144 "k",
145 "zero",
146 false,
147 "float",
148 "The k-mirror zero position. Default is -40.0." );
149
150 config.add( "k.sign",
151 "",
152 "k.sign",
153 argType::Required,
154 "k",
155 "sign",
156 false,
157 "int",
158 "The k-mirror rotation sign. Default is +1." );
159
160 config.add( "k.devName",
161 "",
162 "k.devName",
163 argType::Required,
164 "k",
165 "devName",
166 false,
167 "string",
168 "The device name of the k-mirrorstage. Default is 'stagek'" );
169
170 config.add( "tcs.devName",
171 "",
172 "tcs.devName",
173 argType::Required,
174 "tcs",
175 "devName",
176 false,
177 "string",
178 "The device name of the TCS Interface providing 'teldata.zd'. Default is 'tcsi'" );
179
180 config.add( "tracking.updateInterval",
181 "",
182 "tracking.updateInterval",
183 argType::Required,
184 "tracking",
185 "updateInterval",
186 false,
187 "float",
188 "The interval at which to update positions, in seconds. Default is 10 secs." );
189}
190
191int kTracker::loadConfigImpl( mx::app::appConfigurator &_config )
192{
193 _config( m_zero, "k.zero" );
194 _config( m_sign, "k.sign" );
195 _config( m_devName, "k.devName" );
196
197 _config( m_tcsDevName, "tcs.devName" );
198
199 _config( m_updateInterval, "tracking.updateInterval" );
200
201 return 0;
202}
203
205{
206 loadConfigImpl( config );
207}
208
210{
211
214
216
217 m_indiP_kpos = pcf::IndiProperty( pcf::IndiProperty::Number );
218 m_indiP_kpos.setDevice( m_devName );
219 m_indiP_kpos.setName( "position" );
220 m_indiP_kpos.add( pcf::IndiElement( "target" ) );
221
223
224 return 0;
225}
226
228{
229 const double now = mx::sys::get_curr_time();
230
231 float k = 0;
232
233 { // mutex scope
234 std::unique_lock<std::mutex> lock( m_indiMutex, std::try_to_lock );
235
236 if( !lock.owns_lock() )
237 {
238 return 0;
239 }
240
241 if( !m_tracking )
242 {
243 m_lastUpdate = 0;
244 return 0;
245 }
246
248 {
249 return 0;
250 }
251
252 k = m_zero + m_sign * 0.5f * m_zd;
254 } // mutex scope
255
256 if( !std::isfinite( k ) )
257 {
258 log<software_error>( { __FILE__, __LINE__, "computed non-finite K-mirror target" } );
259 return 0;
260 }
261
262 std::cerr << "Sending k-mirror to: " << k << "\n";
263
264 if( sendNewProperty( m_indiP_kpos, "target", k ) < 0 )
265 {
266 log<software_error>( { __FILE__, __LINE__, "failed to send K-mirror target" } );
267 }
268
269 return 0;
270}
271
273{
274 return 0;
275}
276
277INDI_NEWCALLBACK_DEFN( kTracker, m_indiP_tracking )( const pcf::IndiProperty &ipRecv )
278{
279 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_tracking, ipRecv );
280
281 if( !ipRecv.find( "toggle" ) )
282 return 0;
283
284 if( ipRecv["toggle"].getSwitchState() == pcf::IndiElement::On )
285 {
286 updateSwitchIfChanged( m_indiP_tracking, "toggle", pcf::IndiElement::On, INDI_IDLE );
287
288 { // mutex scope
289 std::lock_guard<std::mutex> guard( m_indiMutex );
290 m_tracking = true;
291 m_lastUpdate = 0;
292 }
293
294 log<text_log>( "started K-mirror rotation tracking" );
295 }
296 else
297 {
298 updateSwitchIfChanged( m_indiP_tracking, "toggle", pcf::IndiElement::Off, INDI_IDLE );
299
300 { // mutex scope
301 std::lock_guard<std::mutex> guard( m_indiMutex );
302 m_tracking = false;
303 m_lastUpdate = 0;
304 }
305
306 log<text_log>( "stopped K-mirror rotation tracking" );
307 }
308
309 return 0;
310}
311
312INDI_SETCALLBACK_DEFN( kTracker, m_indiP_teldata )( const pcf::IndiProperty &ipRecv )
313{
314 INDI_VALIDATE_CALLBACK_PROPS( m_indiP_teldata, ipRecv );
315
316 if( !ipRecv.find( "zd" ) )
317 return 0;
318
319 float zd = 0;
320
321 try
322 {
323 zd = ipRecv["zd"].get<float>();
324 }
325 catch( const std::exception &e )
326 {
327 log<software_error>( { __FILE__, __LINE__, std::string( "exception reading teldata.zd: " ) + e.what() } );
328 return 0;
329 }
330 catch( ... )
331 {
332 log<software_error>( { __FILE__, __LINE__, "unknown exception reading teldata.zd" } );
333 return 0;
334 }
335
336 if( !std::isfinite( zd ) )
337 {
338 log<software_error>( { __FILE__, __LINE__, "received non-finite teldata.zd" } );
339 return 0;
340 }
341
342 { // mutex scope
343 std::lock_guard<std::mutex> guard( m_indiMutex );
344 m_zd = zd;
345 m_haveZD = true;
346 }
347
348 return 0;
349}
350
351} // namespace app
352} // namespace MagAOX
353
354#endif // kTracker_hpp
The base-class for XWCTk applications.
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.
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)
The MagAO-X K-mirror tracker.
Definition kTracker.hpp:41
pcf::IndiProperty m_indiP_tracking
The INDI toggle used to enable or disable tracking.
Definition kTracker.hpp:116
virtual void loadConfig()
Load configuration values.
Definition kTracker.hpp:204
kTracker()
Default c'tor.
Definition kTracker.hpp:132
pcf::IndiProperty m_indiP_teldata
The subscribed TCS property providing zenith distance updates.
Definition kTracker.hpp:118
~kTracker() noexcept
D'tor, declared and defined for noexcept.
Definition kTracker.hpp:76
bool m_haveZD
True once at least one valid zenith distance has been received.
Definition kTracker.hpp:67
float m_zero
The starting point for the K-mirror at zd = 0.
Definition kTracker.hpp:51
virtual int appShutdown()
Shutdown the app.
Definition kTracker.hpp:272
pcf::IndiProperty m_indiP_kpos
The outbound K-mirror stage position command property.
Definition kTracker.hpp:120
float m_zd
The most recent finite zenith distance received from the TCS interface.
Definition kTracker.hpp:65
virtual void setupConfig()
Set up configuration entries.
Definition kTracker.hpp:138
float m_updateInterval
The interval at which to update positions, in seconds. Default is 10 secs.
Definition kTracker.hpp:59
double m_lastUpdate
Timestamp of the last stage command dispatched by the tracker.
Definition kTracker.hpp:69
INDI_SETCALLBACK_DECL(kTracker, m_indiP_teldata)
Handle incoming telescope data updates.
INDI_NEWCALLBACK_DECL(kTracker, m_indiP_tracking)
Handle new tracking toggle requests.
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
Definition kTracker.hpp:191
friend class kTracker_test
Definition kTracker.hpp:44
virtual int appStartup()
Startup function.
Definition kTracker.hpp:209
int m_sign
The sign to apply to the zenith distance to rotate the K-mirror.
Definition kTracker.hpp:53
std::string m_tcsDevName
The device name of the TCS interface providing 'teldata.zd'. Default is 'tcsi'.
Definition kTracker.hpp:56
std::string m_devName
The device name of the K-mirror stage. Default is 'stagek'.
Definition kTracker.hpp:55
bool m_tracking
True when automatic K-mirror updates are enabled.
Definition kTracker.hpp:63
virtual int appLogic()
Implementation of the FSM for kTracker.
Definition kTracker.hpp:227
#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 INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2)
Standard check for matching INDI properties in a callback.
#define INDI_IDLE
Definition indiUtils.hpp:27
const pcf::IndiProperty & ipRecv
std::unique_lock< std::mutex > lock(m_indiMutex)
Definition dm.hpp:19
@ READY
The device is ready for operation, but is not operating.