API
pwfsSlopeCalc.hpp
Go to the documentation of this file.
1 /** \file pwfsSlopeCalc.hpp
2  * \brief The MagAO-X PWFS Slope Calculator
3  *
4  * \ingroup app_files
5  */
6 
7 #ifndef pwfsSlopeCalc_hpp
8 #define pwfsSlopeCalc_hpp
9 
10 #include <limits>
11 
12 #include <mx/improc/eigenCube.hpp>
13 #include <mx/improc/eigenImage.hpp>
14 using namespace mx::improc;
15 
16 #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
17 #include "../../magaox_git_version.h"
18 
19 namespace MagAOX
20 {
21 namespace app
22 {
23 
24 struct darkShmimT
25 {
26  static std::string configSection()
27  {
28  return "darkShmim";
29  };
30 
31  static std::string indiPrefix()
32  {
33  return "dark";
34  };
35 };
36 
37 
38 /** \defgroup pwfsSlopeCalc PWFS Slope Calculator
39  * \brief Calculates slopes from a PWFS image.
40  *
41  * <a href="../handbook/operating/software/apps/pwfsSlopeCalc.html">Application Documentation</a>
42  *
43  * \ingroup apps
44  *
45  */
46 
47 /** \defgroup pwfsSlopeCalc_files PWFS Slope Calculator Files
48  * \ingroup pwfsSlopeCalc
49  */
50 
51 /** MagAO-X application to calculate slopes from PWFS images.
52  *
53  * \ingroup pwfsSlopeCalc
54  *
55  */
56 class pwfsSlopeCalc : public MagAOXApp<true>, public dev::shmimMonitor<pwfsSlopeCalc>, public dev::shmimMonitor<pwfsSlopeCalc,darkShmimT>, public dev::frameGrabber<pwfsSlopeCalc>, public dev::telemeter<pwfsSlopeCalc>
57 {
58 
59  //Give the test harness access.
60  friend class pwfsSlopeCalc_test;
61 
62  friend class dev::shmimMonitor<pwfsSlopeCalc>;
64  friend class dev::frameGrabber<pwfsSlopeCalc>;
65  friend class dev::telemeter<pwfsSlopeCalc>;
66 
67  //The base shmimMonitor type
69 
70  //The dark shmimMonitor type
72 
73  //The base frameGrabber type
75 
76  //The base telemeter type
78 
79  ///Floating point type in which to do all calculations.
80  typedef float realT;
81 
82  static constexpr bool c_frameGrabber_flippable = false; ///< app:dev config to tell framegrabber these images can not be flipped
83 
84 protected:
85 
86  /** \name Configurable Parameters
87  *@{
88  */
89 
90  std::string m_fitter; ///< Device name of the pupil fitter process. If set, the number of pupils
91  int m_numPupils {4};
92 
93  float m_pupil_cx_1; ///< the center x coordinate of pupil 1
94  float m_pupil_cy_1; ///< the center y coordinate of pupil 1
95  float m_pupil_D_1 {0}; ///< the diameter of pupil 1, used only for averaging the fitter output
96 
97  float m_pupil_cx_2; ///< the center x coordinate of pupil 2
98  float m_pupil_cy_2; ///< the center y coordinate of pupil 2
99  float m_pupil_D_2 {0}; ///< the diameter of pupil 2, used only for averaging the fitter output
100 
101  float m_pupil_cx_3; ///< the center x coordinate of pupil 3
102  float m_pupil_cy_3; ///< the center y coordinate of pupil 3
103  float m_pupil_D_3 {0}; ///< the diameter of pupil 3, used only for averaging the fitter output
104 
105  float m_pupil_cx_4; ///< the center x coordinate of pupil 4
106  float m_pupil_cy_4; ///< the center y coordinate of pupil 4
107  float m_pupil_D_4 {0}; ///< the diameter of pupil 4, used only for averaging the fitter output
108 
109  int m_pupil_D {56}; ///< the pupil diameter, just one applied to all pupils.
110 
111  int m_pupil_buffer {1}; ///< the edge buffer for the pupils, just one applied to all pupils. Default is 1.
112 
113  ///@}
114 
115  sem_t m_smSemaphore; ///< Semaphore used to synchronize the fg thread and the sm thread.
116 
117  realT (*pixget)(void *, size_t) {nullptr}; ///< Pointer to a function to extract the image data as our desired type realT.
118 
119  void * m_curr_src {nullptr};
120 
121  int m_quadSize {60};
122 
123  mx::improc::eigenImage<realT> m_darkImage;
124  realT (*dark_pixget)(void *, size_t) {nullptr}; ///< Pointer to a function to extract the image data as our desired type realT.
125  bool m_darkSet {false};
126 
127  int m_pupil_sx_1; ///< the starting x-coordinate of pupil 1 quadrant, calculated from the pupil center, diameter, and buffer.
128  int m_pupil_sy_1; ///< the starting y-coordinate of pupil 1 quadrant, calculated from the pupil center, diameter, and buffer.
129 
130  int m_pupil_sx_2; ///< the starting x-coordinate of pupil 2 quadrant, calculated from the pupil center, diameter, and buffer.
131  int m_pupil_sy_2; ///< the starting y-coordinate of pupil 2 quadrant, calculated from the pupil center, diameter, and buffer.
132 
133  int m_pupil_sx_3; ///< the starting x-coordinate of pupil 3 quadrant, calculated from the pupil center, diameter, and buffer.
134  int m_pupil_sy_3; ///< the starting y-coordinate of pupil 3 quadrant, calculated from the pupil center, diameter, and buffer.
135 
136  int m_pupil_sx_4; ///< the starting x-coordinate of pupil 4 quadrant, calculated from the pupil center, diameter, and buffer.
137  int m_pupil_sy_4; ///< the starting y-coordinate of pupil 4 quadrant, calculated from the pupil center, diameter, and buffer.
138 
139 public:
140  /// Default c'tor.
141  pwfsSlopeCalc();
142 
143  /// D'tor, declared and defined for noexcept.
144  ~pwfsSlopeCalc() noexcept
145  {}
146 
147  virtual void setupConfig();
148 
149  /// Implementation of loadConfig logic, separated for testing.
150  /** This is called by loadConfig().
151  */
152  int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
153 
154  virtual void loadConfig();
155 
156  /// Startup function
157  /**
158  *
159  */
160  virtual int appStartup();
161 
162  /// Implementation of the FSM for pwfsSlopeCalc.
163  /**
164  * \returns 0 on no critical error
165  * \returns -1 on an error requiring shutdown
166  */
167  virtual int appLogic();
168 
169  /// Shutdown the app.
170  /**
171  *
172  */
173  virtual int appShutdown();
174 
175  int allocate( const dev::shmimT & dummy /**< [in] tag to differentiate shmimMonitor parents.*/);
176 
177  int processImage( void * curr_src, ///< [in] pointer to start of current frame.
178  const dev::shmimT & dummy ///< [in] tag to differentiate shmimMonitor parents.
179  );
180 
181  int allocate( const darkShmimT & dummy /**< [in] tag to differentiate shmimMonitor parents.*/);
182 
183  int processImage( void * curr_src, ///< [in] pointer to start of current frame.
184  const darkShmimT & dummy ///< [in] tag to differentiate shmimMonitor parents.
185  );
186 
187  float fps()
188  {
189  return 250;
190  }
191 
192 protected:
193 
194  /** \name dev::frameGrabber interface
195  *
196  * @{
197  */
198 
199  /// Implementation of the framegrabber configureAcquisition interface
200  /**
201  * \returns 0 on success
202  * \returns -1 on error
203  */
204  int configureAcquisition();
205 
206  /// Implementation of the framegrabber startAcquisition interface
207  /**
208  * \returns 0 on success
209  * \returns -1 on error
210  */
211  int startAcquisition();
212 
213  /// Implementation of the framegrabber acquireAndCheckValid interface
214  /**
215  * \returns 0 on success
216  * \returns -1 on error
217  */
218  int acquireAndCheckValid();
219 
220  /// Implementation of the framegrabber loadImageIntoStream interface
221  /**
222  * \returns 0 on success
223  * \returns -1 on error
224  */
225  int loadImageIntoStream( void * dest /**< [in] */);
226 
227  /// Implementation of the framegrabber reconfig interface
228  /**
229  * \returns 0 on success
230  * \returns -1 on error
231  */
232  int reconfig();
233 
234  ///@}
235 
236  pcf::IndiProperty m_indiP_quad1;
237  pcf::IndiProperty m_indiP_quad2;
238  pcf::IndiProperty m_indiP_quad3;
239  pcf::IndiProperty m_indiP_quad4;
240 
241 public:
246 
247  /** \name Telemeter Interface
248  *
249  * @{
250  */
251  int checkRecordTimes();
252 
253  int recordTelem( const telem_fgtimings * );
254 
255  ///@}
256 };
257 
258 
259 inline
260 pwfsSlopeCalc::pwfsSlopeCalc() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
261 {
263  return;
264 }
265 
266 inline
268 {
271 
273  telemeterT::setupConfig(config);
274 
275  config.add("pupil.fitter", "", "pupil.fitter", argType::Required, "pupil", "fitter", false, "int", "The device name of the pupil fitter. If set, then pupil position is set by the fitter reference.");
276 
277  config.add("pupil.D", "", "pupil.D", argType::Required, "pupil", "D", false, "int", "The diameter of the pupils, fixed. Default is 56.");
278 
279  config.add("pupil.buffer", "", "pupil.buffer", argType::Required, "pupil", "buffer", false, "int", "The edge buffer for the pupils. Default is 1.");
280 
281  config.add("pupil.numPupils", "", "pupil.numPupils", argType::Required, "pupil", "numPupils", false, "int", "The number of pupils. Default is 4. 3 is also supported.");
282 
283 
284 
285  config.add("pupil.cx_1", "", "pupil.cx_1", argType::Required, "pupil", "cx_1", false, "int", "The default x-coordinate of pupil 1 (LL). Can be updated from real-time fitter.");
286  config.add("pupil.cy_1", "", "pupil.cy_1", argType::Required, "pupil", "cy_1", false, "int", "The default y-coordinate of pupil 1 (LL). Can be updated from real-time fitter.");
287 
288  config.add("pupil.cx_2", "", "pupil.cx_2", argType::Required, "pupil", "cx_2", false, "int", "The default x-coordinate of pupil 2 (LL). Can be updated from real-time fitter.");
289  config.add("pupil.cy_2", "", "pupil.cy_2", argType::Required, "pupil", "cy_2", false, "int", "The default y-coordinate of pupil 2 (LL). Can be updated from real-time fitter.");
290 
291  config.add("pupil.cx_3", "", "pupil.cx_3", argType::Required, "pupil", "cx_3", false, "int", "The default x-coordinate of pupil 3 (LL). Can be updated from real-time fitter.");
292  config.add("pupil.cy_3", "", "pupil.cy_3", argType::Required, "pupil", "cy_3", false, "int", "The default y-coordinate of pupil 3 (LL). Can be updated from real-time fitter.");
293 
294  config.add("pupil.cx_4", "", "pupil.cx_4", argType::Required, "pupil", "cx_4", false, "int", "The default x-coordinate of pupil 4 (LL). Can be updated from real-time fitter.");
295  config.add("pupil.cy_4", "", "pupil.cy_4", argType::Required, "pupil", "cy_4", false, "int", "The default y-coordinate of pupil 4 (LL). Can be updated from real-time fitter.");
296 }
297 
298 inline
299 int pwfsSlopeCalc::loadConfigImpl( mx::app::appConfigurator & _config )
300 {
301 
302  shmimMonitorT::loadConfig(_config);
303  darkMonitorT::loadConfig(_config);
304  frameGrabberT::loadConfig(_config);
305  telemeterT::loadConfig(_config);
306 
307  config(m_fitter, "pupil.fitter");
308  config(m_numPupils, "pupil.numPupils");
309  config(m_pupil_D, "pupil.D");
310  config(m_pupil_buffer, "pupil.buffer");
311  config(m_pupil_cx_1, "pupil.cx_1");
312  config(m_pupil_cy_1, "pupil.cy_1");
313  config(m_pupil_cx_2, "pupil.cx_2");
314  config(m_pupil_cy_2, "pupil.cy_2");
315  config(m_pupil_cx_3, "pupil.cx_3");
316  config(m_pupil_cy_3, "pupil.cy_3");
317  config(m_pupil_cx_4, "pupil.cx_4");
318  config(m_pupil_cy_4, "pupil.cy_4");
319  return 0;
320 }
321 
322 inline
324 {
325  loadConfigImpl(config);
326 }
327 
328 inline
330 {
331  if(sem_init(&m_smSemaphore, 0,0) < 0)
332  {
333  log<software_critical>({__FILE__, __LINE__, errno,0, "Initializing S.M. semaphore"});
334  return -1;
335  }
336 
337  if(shmimMonitorT::appStartup() < 0)
338  {
339  return log<software_error,-1>({__FILE__, __LINE__});
340  }
341 
342  if(darkMonitorT::appStartup() < 0)
343  {
344  return log<software_error,-1>({__FILE__, __LINE__});
345  }
346 
347  if(frameGrabberT::appStartup() < 0)
348  {
349  return log<software_error,-1>({__FILE__, __LINE__});
350  }
351 
352  if(telemeterT::appStartup() < 0)
353  {
354  return log<software_error,-1>({__FILE__, __LINE__});
355  }
356 
357  if(m_fitter != "")
358  {
359  REG_INDI_SETPROP(m_indiP_quad1, m_fitter, "quadrant1");
360  REG_INDI_SETPROP(m_indiP_quad2, m_fitter, "quadrant2");
361  REG_INDI_SETPROP(m_indiP_quad3, m_fitter, "quadrant3");
362  if(m_numPupils == 4)
363  {
364  REG_INDI_SETPROP(m_indiP_quad4, m_fitter, "quadrant4");
365  }
366  }
367 
369 
370  return 0;
371 }
372 
373 inline
375 {
376  if( shmimMonitorT::appLogic() < 0)
377  {
378  return log<software_error,-1>({__FILE__,__LINE__});
379  }
380 
381  if( darkMonitorT::appLogic() < 0)
382  {
383  return log<software_error,-1>({__FILE__,__LINE__});
384  }
385 
386 
387  if( frameGrabberT::appLogic() < 0)
388  {
389  return log<software_error,-1>({__FILE__,__LINE__});
390  }
391 
392  if( telemeterT::appLogic() < 0)
393  {
394  return log<software_error,-1>({__FILE__,__LINE__});
395  }
396 
397  std::unique_lock<std::mutex> lock(m_indiMutex);
398 
399  if(shmimMonitorT::updateINDI() < 0)
400  {
401  log<software_error>({__FILE__, __LINE__});
402  }
403 
404  if(darkMonitorT::updateINDI() < 0)
405  {
406  log<software_error>({__FILE__, __LINE__});
407  }
408 
409  if(frameGrabberT::updateINDI() < 0)
410  {
411  log<software_error>({__FILE__, __LINE__});
412  }
413 
414 
415 
416 
417  return 0;
418 }
419 
420 inline
422 {
424 
426 
428 
430 
431  return 0;
432 }
433 
434 inline
436 {
437  static_cast<void>(dummy); //be unused
438 
439  //Initialize dark image if not correct size.
441  {
443  m_darkImage.setZero();
444  m_darkSet = false;
445  }
446 
447  m_reconfig = true;
448 
449  return 0;
450 }
451 
452 inline
453 int pwfsSlopeCalc::processImage( void * curr_src,
454  const dev::shmimT & dummy
455  )
456 {
457  static_cast<void>(dummy); //be unused
458 
459  m_curr_src = curr_src;
460 
461  //Now tell the f.g. to get going
462  if(sem_post(&m_smSemaphore) < 0)
463  {
464  log<software_critical>({__FILE__, __LINE__, errno, 0, "Error posting to semaphore"});
465  return -1;
466  }
467 
468  return 0;
469 }
470 
471 inline
473 {
474  static_cast<void>(dummy); //be unused
475 
476  m_darkSet = false;
477 
478 // if(darkMonitorT::m_width != shmimMonitorT::m_width || darkMonitorT::m_height != shmimMonitorT::m_height)
479 // {
480 // darkMonitorT::m_restart = true;
481 // }
482 
484  dark_pixget = getPixPointer<realT>(darkMonitorT::m_dataType);
485 
486  if(dark_pixget == nullptr)
487  {
488  log<software_error>({__FILE__, __LINE__, "bad data type"});
489  return -1;
490  }
491 
492  return 0;
493 }
494 
495 inline
496 int pwfsSlopeCalc::processImage( void * curr_src,
497  const darkShmimT & dummy
498  )
499 {
500  static_cast<void>(dummy); //be unused
501 
502  realT * data = m_darkImage.data();
503 
504  for(unsigned nn=0; nn < darkMonitorT::m_width*darkMonitorT::m_height; ++nn)
505  {
506  //data[nn] = *( (int16_t * ) (curr_src + nn*shmimMonitorT::m_typeSize));
507  data[nn] = dark_pixget(curr_src, nn);
508  }
509 
510  m_darkSet = true;
511 
512  return 0;
513 }
514 
515 inline
517 {
518  std::unique_lock<std::mutex> lock(m_indiMutex);
519 
521  {
522  //This means we haven't connected to the stream to average. so wait.
523  sleep(1);
524  return -1;
525  }
526 
528 
531 
534 
537 
540 
541  //m_quadSize = shmimMonitorT::m_width/2;
544  frameGrabberT::m_dataType = _DATATYPE_FLOAT;
545 
546  return 0;
547 }
548 
549 inline
551 {
552  return 0;
553 }
554 
555 inline
557 {
558  timespec ts;
559 
560  if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
561  {
562  log<software_critical>({__FILE__,__LINE__,errno,0,"clock_gettime"});
563  return -1;
564  }
565 
566  ts.tv_sec += 1;
567 
568  if(sem_timedwait(&m_smSemaphore, &ts) == 0)
569  {
570  clock_gettime(CLOCK_REALTIME, &m_currImageTimestamp);
571  return 0;
572  }
573  else
574  {
575  return 1;
576  }
577 }
578 
579 inline
581 {
582  //Here is where we do it.
583  Eigen::Map<eigenImage<unsigned short>> pwfsIm( static_cast<unsigned short *>(m_curr_src), shmimMonitorT::m_width, shmimMonitorT::m_height );
584  Eigen::Map<eigenImage<float>> slopesIm(static_cast<float*>(dest), frameGrabberT::m_width, frameGrabberT::m_height );
585 
586  static float sqrt32 = sqrt(3.0)/2;
587 
588  float norm = 0;
589  int N = 0;
590  if(m_numPupils == 3)
591  {
592  for(int rr=0; rr< m_quadSize; ++rr)
593  {
594  for(int cc=0; cc< m_quadSize; ++cc)
595  {
596  float I2 = pwfsIm(rr+m_pupil_sx_1,cc+m_pupil_sy_1) - m_darkImage(rr+m_pupil_sx_1,cc+m_pupil_sy_1);
597  float I3 = pwfsIm(rr+m_pupil_sx_2,cc+m_pupil_sy_2) - m_darkImage(rr+m_pupil_sx_2,cc+m_pupil_sy_2);
598  float I1 = pwfsIm(rr+m_pupil_sx_3,cc+m_pupil_sy_3) - m_darkImage(rr+m_pupil_sx_3,cc+m_pupil_sy_3);
599 
600  norm += I1+I2+I3;
601  ++N;
602 
603  slopesIm(rr,cc) = sqrt32*(I2-I3);///norm;
604  slopesIm(rr,cc+m_quadSize) = (I1-0.5*(I2+I3));///norm;
605  }
606  }
607  }
608  else
609  {
610 
611  for(int rr=0; rr< m_quadSize; ++rr)
612  {
613  for(int cc=0; cc< m_quadSize; ++cc)
614  {
615  float I1 = pwfsIm(rr+m_pupil_sx_1,cc+m_pupil_sy_1) - m_darkImage(rr+m_pupil_sx_1,cc+m_pupil_sy_1);
616  float I2 = pwfsIm(rr+m_pupil_sx_2,cc+m_pupil_sy_2) - m_darkImage(rr+m_pupil_sx_2,cc+m_pupil_sy_2);
617  float I3 = pwfsIm(rr+m_pupil_sx_3,cc+m_pupil_sy_3) - m_darkImage(rr+m_pupil_sx_3,cc+m_pupil_sy_3);
618  float I4 = pwfsIm(rr+m_pupil_sx_4,cc+m_pupil_sy_4) - m_darkImage(rr+m_pupil_sx_4,cc+m_pupil_sy_4);
619 
620  norm += I1+I2+I3+I4;
621  ++N;
622 
623  slopesIm(rr,cc) = ((I1+I3) - (I2+I4));///norm;
624  slopesIm(rr,cc+m_quadSize) = ((I1+I2)-(I3+I4));///norm;
625  }
626  }
627  }
628 
629  norm /= N;
630  for(size_t ii=0; ii< frameGrabberT::m_height; ++ii)
631  {
632  for(size_t jj=0; jj < frameGrabberT::m_width; ++jj)
633  {
634  slopesIm(jj,ii)/=norm;
635  }
636  }
637 
638  return 0;
639 }
640 
641 inline
643 {
644  return 0;
645 }
646 
647 INDI_SETCALLBACK_DEFN(pwfsSlopeCalc, m_indiP_quad1)(const pcf::IndiProperty &ipRecv)
648 {
649  if(ipRecv.getName() != m_indiP_quad1.getName())
650  {
651  log<software_error>({__FILE__,__LINE__,"wrong INDI property received"});
652 
653  return -1;
654  }
655 
656  if(ipRecv.find("set-x"))
657  {
658  float newval = ipRecv["set-x"].get<float>();
659  if(newval != m_pupil_cx_1)
660  {
661  m_pupil_cx_1 = newval;
662  m_reconfig = true;
663  }
664  }
665 
666  if(ipRecv.find("set-y"))
667  {
668  float newval = ipRecv["set-y"].get<float>();
669  if(newval != m_pupil_cy_1)
670  {
671  m_pupil_cy_1 = newval;
672  m_reconfig = true;
673  }
674  }
675 
676  if(ipRecv.find("set-D"))
677  {
678  float newval = ipRecv["set-D"].get<float>();
679  if(newval != m_pupil_D_1)
680  {
681  m_pupil_D_1 = newval;
682  m_reconfig = true;
683  }
684  }
685 
686 
687  return 0;
688 }
689 
690 INDI_SETCALLBACK_DEFN(pwfsSlopeCalc, m_indiP_quad2)(const pcf::IndiProperty &ipRecv)
691 {
692  if(ipRecv.getName() != m_indiP_quad2.getName())
693  {
694  log<software_error>({__FILE__,__LINE__,"wrong INDI property received"});
695 
696  return -2;
697  }
698 
699  if(ipRecv.find("set-x"))
700  {
701  float newval = ipRecv["set-x"].get<float>();
702  if(newval != m_pupil_cx_2)
703  {
704  m_pupil_cx_2 = newval;
705  m_reconfig = true;
706  }
707  }
708 
709  if(ipRecv.find("set-y"))
710  {
711  float newval = ipRecv["set-y"].get<float>();
712  if(newval != m_pupil_cy_2)
713  {
714  m_pupil_cy_2 = newval;
715  m_reconfig = true;
716  }
717  }
718  if(ipRecv.find("set-D"))
719  {
720  float newval = ipRecv["set-D"].get<float>();
721  if(newval != m_pupil_D_2)
722  {
723  m_pupil_D_2 = newval;
724  m_reconfig = true;
725  }
726  }
727 
728 
729  return 0;
730 }
731 
732 INDI_SETCALLBACK_DEFN(pwfsSlopeCalc, m_indiP_quad3)(const pcf::IndiProperty &ipRecv)
733 {
734  if(ipRecv.getName() != m_indiP_quad3.getName())
735  {
736  log<software_error>({__FILE__,__LINE__,"wrong INDI property received"});
737 
738  return -3;
739  }
740 
741  if(ipRecv.find("set-x"))
742  {
743  float newval = ipRecv["set-x"].get<float>();
744  if(newval != m_pupil_cx_3)
745  {
746  m_pupil_cx_3 = newval;
747  m_reconfig = true;
748  }
749  }
750  if(ipRecv.find("set-y"))
751  {
752  float newval = ipRecv["set-y"].get<float>();
753  if(newval != m_pupil_cy_3)
754  {
755  m_pupil_cy_3 = newval;
756  m_reconfig = true;
757  }
758  }
759  if(ipRecv.find("set-D"))
760  {
761  float newval = ipRecv["set-D"].get<float>();
762  if(newval != m_pupil_D_3)
763  {
764  m_pupil_D_3 = newval;
765  m_reconfig = true;
766  }
767  }
768 
769 
770  return 0;
771 }
772 
773 INDI_SETCALLBACK_DEFN(pwfsSlopeCalc, m_indiP_quad4)(const pcf::IndiProperty &ipRecv)
774 {
775  if(ipRecv.getName() != m_indiP_quad4.getName())
776  {
777  log<software_error>({__FILE__,__LINE__,"wrong INDI property received"});
778 
779  return -4;
780  }
781 
782  if(ipRecv.find("set-x"))
783  {
784  float newval = ipRecv["set-x"].get<float>();
785  if(newval != m_pupil_cx_4)
786  {
787  m_pupil_cx_4 = newval;
788  m_reconfig = true;
789  }
790  }
791  if(ipRecv.find("set-y"))
792  {
793  float newval = ipRecv["set-y"].get<float>();
794  if(newval != m_pupil_cy_4)
795  {
796  m_pupil_cy_4 = newval;
797  m_reconfig = true;
798  }
799  }
800  if(ipRecv.find("set-D"))
801  {
802  float newval = ipRecv["set-D"].get<float>();
803  if(newval != m_pupil_D_4)
804  {
805  m_pupil_D_4 = newval;
806  m_reconfig = true;
807  }
808  }
809 
810 
811  return 0;
812 }
813 
814 inline
816 {
818 }
819 
820 inline
822 {
823  return recordFGTimings(true);
824 }
825 
826 } //namespace app
827 } //namespace MagAOX
828 
829 #endif //pwfsSlopeCalc_hpp
The base-class for MagAO-X applications.
Definition: MagAOXApp.hpp:75
stateCodes::stateCodeT state()
Get the current state code.
Definition: MagAOXApp.hpp:2082
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
Definition: MagAOXApp.hpp:1590
std::mutex m_indiMutex
Mutex for locking INDI communications.
Definition: MagAOXApp.hpp:540
timespec m_currImageTimestamp
The timestamp of the current image.
uint32_t m_width
The width of the image, once deinterlaced etc.
int appShutdown()
Shuts down the framegrabber thread.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int updateINDI()
Update the INDI properties for this device controller.
uint8_t m_dataType
The ImageStreamIO type code.
bool m_reconfig
Flag to set if a camera reconfiguration requires a framegrabber reset.
int appLogic()
Checks the framegrabber thread.
uint32_t m_height
The height of the image, once deinterlaced etc.
uint32_t m_width
The width of the images in the stream.
int updateINDI()
Update the INDI properties for this device controller.
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.
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
bool m_getExistingFirst
If set to true by derivedT, any existing image will be grabbed and sent to processImage before waitin...
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
std::string m_fitter
Device name of the pupil fitter process. If set, the number of pupils.
float m_pupil_cy_1
the center y coordinate of pupil 1
void * m_curr_src
Pointer to a function to extract the image data as our desired type realT.
int m_pupil_sy_1
the starting y-coordinate of pupil 1 quadrant, calculated from the pupil center, diameter,...
pcf::IndiProperty m_indiP_quad2
float m_pupil_cx_2
the center x coordinate of pupil 2
int configureAcquisition()
Implementation of the framegrabber configureAcquisition interface.
pcf::IndiProperty m_indiP_quad1
virtual int appShutdown()
Shutdown the app.
pcf::IndiProperty m_indiP_quad4
float m_pupil_cx_1
the center x coordinate of pupil 1
INDI_SETCALLBACK_DECL(pwfsSlopeCalc, m_indiP_quad4)
virtual int appStartup()
Startup function.
float m_pupil_cx_3
the center x coordinate of pupil 3
float realT
Floating point type in which to do all calculations.
dev::frameGrabber< pwfsSlopeCalc > frameGrabberT
INDI_SETCALLBACK_DECL(pwfsSlopeCalc, m_indiP_quad1)
int m_pupil_sx_4
the starting x-coordinate of pupil 4 quadrant, calculated from the pupil center, diameter,...
float m_pupil_cy_3
the center y coordinate of pupil 3
int m_pupil_D
the pupil diameter, just one applied to all pupils.
int m_pupil_sx_3
the starting x-coordinate of pupil 3 quadrant, calculated from the pupil center, diameter,...
realT(* dark_pixget)(void *, size_t)
virtual int appLogic()
Implementation of the FSM for pwfsSlopeCalc.
INDI_SETCALLBACK_DECL(pwfsSlopeCalc, m_indiP_quad3)
int acquireAndCheckValid()
Implementation of the framegrabber acquireAndCheckValid interface.
dev::shmimMonitor< pwfsSlopeCalc, darkShmimT > darkMonitorT
int loadImageIntoStream(void *dest)
Implementation of the framegrabber loadImageIntoStream interface.
int m_pupil_sy_2
the starting y-coordinate of pupil 2 quadrant, calculated from the pupil center, diameter,...
int allocate(const dev::shmimT &dummy)
int m_pupil_sx_2
the starting x-coordinate of pupil 2 quadrant, calculated from the pupil center, diameter,...
int m_pupil_sx_1
the starting x-coordinate of pupil 1 quadrant, calculated from the pupil center, diameter,...
int m_pupil_sy_3
the starting y-coordinate of pupil 3 quadrant, calculated from the pupil center, diameter,...
INDI_SETCALLBACK_DECL(pwfsSlopeCalc, m_indiP_quad2)
dev::telemeter< pwfsSlopeCalc > telemeterT
~pwfsSlopeCalc() noexcept
D'tor, declared and defined for noexcept.
bool m_darkSet
Pointer to a function to extract the image data as our desired type realT.
int m_pupil_sy_4
the starting y-coordinate of pupil 4 quadrant, calculated from the pupil center, diameter,...
int startAcquisition()
Implementation of the framegrabber startAcquisition interface.
pcf::IndiProperty m_indiP_quad3
float m_pupil_cx_4
the center x coordinate of pupil 4
sem_t m_smSemaphore
Semaphore used to synchronize the fg thread and the sm thread.
dev::shmimMonitor< pwfsSlopeCalc > shmimMonitorT
int reconfig()
Implementation of the framegrabber reconfig interface.
float m_pupil_cy_2
the center y coordinate of pupil 2
float m_pupil_cy_4
the center y coordinate of pupil 4
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
int recordTelem(const telem_fgtimings *)
int m_pupil_buffer
the edge buffer for the pupils, just one applied to all pupils. Default is 1.
mx::improc::eigenImage< realT > m_darkImage
int processImage(void *curr_src, const dev::shmimT &dummy)
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
Definition: indiMacros.hpp:264
@ OPERATING
The device is operating, other than homing.
Definition: stateCodes.hpp:50
const pcf::IndiProperty & ipRecv
INDI_SETCALLBACK_DEFN(MagAOXApp< _useINDI >, m_indiP_powerChannel)(const pcf
Definition: MagAOXApp.hpp:3195
Definition: dm.hpp:24
static std::string configSection()
static std::string indiPrefix()
A device which saves telemetry.
Definition: telemeter.hpp:52
int appShutdown()
Perform telemeter application shutdown.
Definition: telemeter.hpp:259
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
Definition: telemeter.hpp:208
int appLogic()
Perform telemeter application logic.
Definition: telemeter.hpp:253
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
Definition: telemeter.hpp:195
int appStartup()
Starts the telemetry log thread.
Definition: telemeter.hpp:226
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Definition: telemeter.hpp:266
Software ERR log entry.
Log entry recording framegrabber timings.