Line data Source code
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 0 : static std::string configSection()
27 : {
28 0 : return "darkShmim";
29 : };
30 :
31 0 : static std::string indiPrefix()
32 : {
33 0 : 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>;
63 : friend class dev::shmimMonitor<pwfsSlopeCalc,darkShmimT>;
64 : friend class dev::frameGrabber<pwfsSlopeCalc>;
65 : friend class dev::telemeter<pwfsSlopeCalc>;
66 :
67 : //The base shmimMonitor type
68 : typedef dev::shmimMonitor<pwfsSlopeCalc> shmimMonitorT;
69 :
70 : //The dark shmimMonitor type
71 : typedef dev::shmimMonitor<pwfsSlopeCalc, darkShmimT> darkMonitorT;
72 :
73 : //The base frameGrabber type
74 : typedef dev::frameGrabber<pwfsSlopeCalc> frameGrabberT;
75 :
76 : //The base telemeter type
77 : typedef dev::telemeter<pwfsSlopeCalc> telemeterT;
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 0 : ~pwfsSlopeCalc() noexcept
145 0 : {}
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 0 : float fps()
188 : {
189 0 : 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:
242 0 : INDI_SETCALLBACK_DECL(pwfsSlopeCalc, m_indiP_quad1);
243 0 : INDI_SETCALLBACK_DECL(pwfsSlopeCalc, m_indiP_quad2);
244 0 : INDI_SETCALLBACK_DECL(pwfsSlopeCalc, m_indiP_quad3);
245 0 : INDI_SETCALLBACK_DECL(pwfsSlopeCalc, m_indiP_quad4);
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 : {
262 : darkMonitorT::m_getExistingFirst = true;
263 : return;
264 : }
265 :
266 : inline
267 0 : void pwfsSlopeCalc::setupConfig()
268 : {
269 0 : shmimMonitorT::setupConfig(config);
270 0 : darkMonitorT::setupConfig(config);
271 :
272 0 : frameGrabberT::setupConfig(config);
273 0 : telemeterT::setupConfig(config);
274 :
275 0 : 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 0 : config.add("pupil.D", "", "pupil.D", argType::Required, "pupil", "D", false, "int", "The diameter of the pupils, fixed. Default is 56.");
278 :
279 0 : config.add("pupil.buffer", "", "pupil.buffer", argType::Required, "pupil", "buffer", false, "int", "The edge buffer for the pupils. Default is 1.");
280 :
281 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : }
297 :
298 : inline
299 0 : int pwfsSlopeCalc::loadConfigImpl( mx::app::appConfigurator & _config )
300 : {
301 :
302 0 : shmimMonitorT::loadConfig(_config);
303 0 : darkMonitorT::loadConfig(_config);
304 0 : frameGrabberT::loadConfig(_config);
305 0 : telemeterT::loadConfig(_config);
306 :
307 0 : config(m_fitter, "pupil.fitter");
308 0 : config(m_numPupils, "pupil.numPupils");
309 0 : config(m_pupil_D, "pupil.D");
310 0 : config(m_pupil_buffer, "pupil.buffer");
311 0 : config(m_pupil_cx_1, "pupil.cx_1");
312 0 : config(m_pupil_cy_1, "pupil.cy_1");
313 0 : config(m_pupil_cx_2, "pupil.cx_2");
314 0 : config(m_pupil_cy_2, "pupil.cy_2");
315 0 : config(m_pupil_cx_3, "pupil.cx_3");
316 0 : config(m_pupil_cy_3, "pupil.cy_3");
317 0 : config(m_pupil_cx_4, "pupil.cx_4");
318 0 : config(m_pupil_cy_4, "pupil.cy_4");
319 0 : return 0;
320 : }
321 :
322 : inline
323 0 : void pwfsSlopeCalc::loadConfig()
324 : {
325 0 : loadConfigImpl(config);
326 0 : }
327 :
328 : inline
329 0 : int pwfsSlopeCalc::appStartup()
330 : {
331 0 : if(sem_init(&m_smSemaphore, 0,0) < 0)
332 : {
333 0 : log<software_critical>({__FILE__, __LINE__, errno,0, "Initializing S.M. semaphore"});
334 0 : return -1;
335 : }
336 :
337 0 : if(shmimMonitorT::appStartup() < 0)
338 : {
339 0 : return log<software_error,-1>({__FILE__, __LINE__});
340 : }
341 :
342 0 : if(darkMonitorT::appStartup() < 0)
343 : {
344 0 : return log<software_error,-1>({__FILE__, __LINE__});
345 : }
346 :
347 0 : if(frameGrabberT::appStartup() < 0)
348 : {
349 0 : return log<software_error,-1>({__FILE__, __LINE__});
350 : }
351 :
352 0 : if(telemeterT::appStartup() < 0)
353 : {
354 0 : return log<software_error,-1>({__FILE__, __LINE__});
355 : }
356 :
357 0 : if(m_fitter != "")
358 : {
359 0 : REG_INDI_SETPROP(m_indiP_quad1, m_fitter, "quadrant1");
360 0 : REG_INDI_SETPROP(m_indiP_quad2, m_fitter, "quadrant2");
361 0 : REG_INDI_SETPROP(m_indiP_quad3, m_fitter, "quadrant3");
362 0 : if(m_numPupils == 4)
363 : {
364 0 : REG_INDI_SETPROP(m_indiP_quad4, m_fitter, "quadrant4");
365 : }
366 : }
367 :
368 0 : state(stateCodes::OPERATING);
369 :
370 0 : return 0;
371 : }
372 :
373 : inline
374 0 : int pwfsSlopeCalc::appLogic()
375 : {
376 0 : if( shmimMonitorT::appLogic() < 0)
377 : {
378 0 : return log<software_error,-1>({__FILE__,__LINE__});
379 : }
380 :
381 0 : if( darkMonitorT::appLogic() < 0)
382 : {
383 0 : return log<software_error,-1>({__FILE__,__LINE__});
384 : }
385 :
386 :
387 0 : if( frameGrabberT::appLogic() < 0)
388 : {
389 0 : return log<software_error,-1>({__FILE__,__LINE__});
390 : }
391 :
392 0 : if( telemeterT::appLogic() < 0)
393 : {
394 0 : return log<software_error,-1>({__FILE__,__LINE__});
395 : }
396 :
397 0 : std::unique_lock<std::mutex> lock(m_indiMutex);
398 :
399 0 : if(shmimMonitorT::updateINDI() < 0)
400 : {
401 0 : log<software_error>({__FILE__, __LINE__});
402 : }
403 :
404 0 : if(darkMonitorT::updateINDI() < 0)
405 : {
406 0 : log<software_error>({__FILE__, __LINE__});
407 : }
408 :
409 0 : if(frameGrabberT::updateINDI() < 0)
410 : {
411 0 : log<software_error>({__FILE__, __LINE__});
412 : }
413 :
414 :
415 :
416 :
417 0 : return 0;
418 0 : }
419 :
420 : inline
421 0 : int pwfsSlopeCalc::appShutdown()
422 : {
423 0 : shmimMonitorT::appShutdown();
424 :
425 0 : darkMonitorT::appShutdown();
426 :
427 0 : frameGrabberT::appShutdown();
428 :
429 0 : telemeterT::appShutdown();
430 :
431 0 : return 0;
432 : }
433 :
434 : inline
435 0 : int pwfsSlopeCalc::allocate(const dev::shmimT & dummy)
436 : {
437 : static_cast<void>(dummy); //be unused
438 :
439 : //Initialize dark image if not correct size.
440 0 : if(darkMonitorT::m_width != shmimMonitorT::m_width || darkMonitorT::m_height != shmimMonitorT::m_height)
441 : {
442 0 : m_darkImage.resize(shmimMonitorT::m_width,shmimMonitorT::m_height);
443 0 : m_darkImage.setZero();
444 0 : m_darkSet = false;
445 : }
446 :
447 0 : m_reconfig = true;
448 :
449 0 : return 0;
450 : }
451 :
452 : inline
453 0 : int pwfsSlopeCalc::processImage( void * curr_src,
454 : const dev::shmimT & dummy
455 : )
456 : {
457 : static_cast<void>(dummy); //be unused
458 :
459 0 : m_curr_src = curr_src;
460 :
461 : //Now tell the f.g. to get going
462 0 : if(sem_post(&m_smSemaphore) < 0)
463 : {
464 0 : log<software_critical>({__FILE__, __LINE__, errno, 0, "Error posting to semaphore"});
465 0 : return -1;
466 : }
467 :
468 0 : return 0;
469 : }
470 :
471 : inline
472 0 : int pwfsSlopeCalc::allocate(const darkShmimT & dummy)
473 : {
474 : static_cast<void>(dummy); //be unused
475 :
476 0 : 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 :
483 0 : m_darkImage.resize(darkMonitorT::m_width, darkMonitorT::m_height);
484 0 : dark_pixget = getPixPointer<realT>(darkMonitorT::m_dataType);
485 :
486 0 : if(dark_pixget == nullptr)
487 : {
488 0 : log<software_error>({__FILE__, __LINE__, "bad data type"});
489 0 : return -1;
490 : }
491 :
492 0 : return 0;
493 : }
494 :
495 : inline
496 0 : int pwfsSlopeCalc::processImage( void * curr_src,
497 : const darkShmimT & dummy
498 : )
499 : {
500 : static_cast<void>(dummy); //be unused
501 :
502 0 : realT * data = m_darkImage.data();
503 :
504 0 : 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 0 : data[nn] = dark_pixget(curr_src, nn);
508 : }
509 :
510 0 : m_darkSet = true;
511 :
512 0 : return 0;
513 : }
514 :
515 : inline
516 0 : int pwfsSlopeCalc::configureAcquisition()
517 : {
518 0 : std::unique_lock<std::mutex> lock(m_indiMutex);
519 :
520 0 : if(shmimMonitorT::m_width==0 || shmimMonitorT::m_height==0 || shmimMonitorT::m_dataType == 0)
521 : {
522 : //This means we haven't connected to the stream to average. so wait.
523 0 : sleep(1);
524 0 : return -1;
525 : }
526 :
527 0 : m_quadSize = m_pupil_D + 2*m_pupil_buffer;
528 :
529 0 : m_pupil_sx_1 = m_pupil_cx_1 - 0.5*m_quadSize;
530 0 : m_pupil_sy_1 = m_pupil_cy_1 - 0.5*m_quadSize;
531 :
532 0 : m_pupil_sx_2 = m_pupil_cx_2 - 0.5*m_quadSize;
533 0 : m_pupil_sy_2 = m_pupil_cy_2 - 0.5*m_quadSize;
534 :
535 0 : m_pupil_sx_3 = m_pupil_cx_3 - 0.5*m_quadSize;
536 0 : m_pupil_sy_3 = m_pupil_cy_3 - 0.5*m_quadSize;
537 :
538 0 : m_pupil_sx_4 = m_pupil_cx_4 - 0.5*m_quadSize;
539 0 : m_pupil_sy_4 = m_pupil_cy_4 - 0.5*m_quadSize;
540 :
541 : //m_quadSize = shmimMonitorT::m_width/2;
542 0 : frameGrabberT::m_width = m_quadSize;
543 0 : frameGrabberT::m_height = 2*m_quadSize;
544 0 : frameGrabberT::m_dataType = _DATATYPE_FLOAT;
545 :
546 0 : return 0;
547 0 : }
548 :
549 : inline
550 0 : int pwfsSlopeCalc::startAcquisition()
551 : {
552 0 : return 0;
553 : }
554 :
555 : inline
556 0 : int pwfsSlopeCalc::acquireAndCheckValid()
557 : {
558 : timespec ts;
559 :
560 0 : if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
561 : {
562 0 : log<software_critical>({__FILE__,__LINE__,errno,0,"clock_gettime"});
563 0 : return -1;
564 : }
565 :
566 0 : ts.tv_sec += 1;
567 :
568 0 : if(sem_timedwait(&m_smSemaphore, &ts) == 0)
569 : {
570 0 : clock_gettime(CLOCK_REALTIME, &m_currImageTimestamp);
571 0 : return 0;
572 : }
573 : else
574 : {
575 0 : return 1;
576 : }
577 : }
578 :
579 : inline
580 0 : int pwfsSlopeCalc::loadImageIntoStream(void * dest)
581 : {
582 : //Here is where we do it.
583 0 : Eigen::Map<eigenImage<unsigned short>> pwfsIm( static_cast<unsigned short *>(m_curr_src), shmimMonitorT::m_width, shmimMonitorT::m_height );
584 0 : 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 0 : float norm = 0;
589 0 : int N = 0;
590 0 : if(m_numPupils == 3)
591 : {
592 0 : for(int rr=0; rr< m_quadSize; ++rr)
593 : {
594 0 : for(int cc=0; cc< m_quadSize; ++cc)
595 : {
596 0 : 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 0 : 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 0 : 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 0 : norm += I1+I2+I3;
601 0 : ++N;
602 :
603 0 : slopesIm(rr,cc) = sqrt32*(I2-I3);///norm;
604 0 : slopesIm(rr,cc+m_quadSize) = (I1-0.5*(I2+I3));///norm;
605 : }
606 : }
607 : }
608 : else
609 : {
610 :
611 0 : for(int rr=0; rr< m_quadSize; ++rr)
612 : {
613 0 : for(int cc=0; cc< m_quadSize; ++cc)
614 : {
615 0 : 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 0 : 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 0 : 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 0 : 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 0 : norm += I1+I2+I3+I4;
621 0 : ++N;
622 :
623 0 : slopesIm(rr,cc) = ((I1+I3) - (I2+I4));///norm;
624 0 : slopesIm(rr,cc+m_quadSize) = ((I1+I2)-(I3+I4));///norm;
625 : }
626 : }
627 : }
628 :
629 0 : norm /= N;
630 0 : for(size_t ii=0; ii< frameGrabberT::m_height; ++ii)
631 : {
632 0 : for(size_t jj=0; jj < frameGrabberT::m_width; ++jj)
633 : {
634 0 : slopesIm(jj,ii)/=norm;
635 : }
636 : }
637 :
638 0 : return 0;
639 : }
640 :
641 : inline
642 0 : int pwfsSlopeCalc::reconfig()
643 : {
644 0 : return 0;
645 : }
646 :
647 0 : INDI_SETCALLBACK_DEFN(pwfsSlopeCalc, m_indiP_quad1)(const pcf::IndiProperty &ipRecv)
648 : {
649 0 : if(ipRecv.getName() != m_indiP_quad1.getName())
650 : {
651 0 : log<software_error>({__FILE__,__LINE__,"wrong INDI property received"});
652 :
653 0 : return -1;
654 : }
655 :
656 0 : if(ipRecv.find("set-x"))
657 : {
658 0 : float newval = ipRecv["set-x"].get<float>();
659 0 : if(newval != m_pupil_cx_1)
660 : {
661 0 : m_pupil_cx_1 = newval;
662 0 : m_reconfig = true;
663 : }
664 : }
665 :
666 0 : if(ipRecv.find("set-y"))
667 : {
668 0 : float newval = ipRecv["set-y"].get<float>();
669 0 : if(newval != m_pupil_cy_1)
670 : {
671 0 : m_pupil_cy_1 = newval;
672 0 : m_reconfig = true;
673 : }
674 : }
675 :
676 0 : if(ipRecv.find("set-D"))
677 : {
678 0 : float newval = ipRecv["set-D"].get<float>();
679 0 : if(newval != m_pupil_D_1)
680 : {
681 0 : m_pupil_D_1 = newval;
682 0 : m_reconfig = true;
683 : }
684 : }
685 :
686 :
687 0 : return 0;
688 : }
689 :
690 0 : INDI_SETCALLBACK_DEFN(pwfsSlopeCalc, m_indiP_quad2)(const pcf::IndiProperty &ipRecv)
691 : {
692 0 : if(ipRecv.getName() != m_indiP_quad2.getName())
693 : {
694 0 : log<software_error>({__FILE__,__LINE__,"wrong INDI property received"});
695 :
696 0 : return -2;
697 : }
698 :
699 0 : if(ipRecv.find("set-x"))
700 : {
701 0 : float newval = ipRecv["set-x"].get<float>();
702 0 : if(newval != m_pupil_cx_2)
703 : {
704 0 : m_pupil_cx_2 = newval;
705 0 : m_reconfig = true;
706 : }
707 : }
708 :
709 0 : if(ipRecv.find("set-y"))
710 : {
711 0 : float newval = ipRecv["set-y"].get<float>();
712 0 : if(newval != m_pupil_cy_2)
713 : {
714 0 : m_pupil_cy_2 = newval;
715 0 : m_reconfig = true;
716 : }
717 : }
718 0 : if(ipRecv.find("set-D"))
719 : {
720 0 : float newval = ipRecv["set-D"].get<float>();
721 0 : if(newval != m_pupil_D_2)
722 : {
723 0 : m_pupil_D_2 = newval;
724 0 : m_reconfig = true;
725 : }
726 : }
727 :
728 :
729 0 : return 0;
730 : }
731 :
732 0 : INDI_SETCALLBACK_DEFN(pwfsSlopeCalc, m_indiP_quad3)(const pcf::IndiProperty &ipRecv)
733 : {
734 0 : if(ipRecv.getName() != m_indiP_quad3.getName())
735 : {
736 0 : log<software_error>({__FILE__,__LINE__,"wrong INDI property received"});
737 :
738 0 : return -3;
739 : }
740 :
741 0 : if(ipRecv.find("set-x"))
742 : {
743 0 : float newval = ipRecv["set-x"].get<float>();
744 0 : if(newval != m_pupil_cx_3)
745 : {
746 0 : m_pupil_cx_3 = newval;
747 0 : m_reconfig = true;
748 : }
749 : }
750 0 : if(ipRecv.find("set-y"))
751 : {
752 0 : float newval = ipRecv["set-y"].get<float>();
753 0 : if(newval != m_pupil_cy_3)
754 : {
755 0 : m_pupil_cy_3 = newval;
756 0 : m_reconfig = true;
757 : }
758 : }
759 0 : if(ipRecv.find("set-D"))
760 : {
761 0 : float newval = ipRecv["set-D"].get<float>();
762 0 : if(newval != m_pupil_D_3)
763 : {
764 0 : m_pupil_D_3 = newval;
765 0 : m_reconfig = true;
766 : }
767 : }
768 :
769 :
770 0 : return 0;
771 : }
772 :
773 0 : INDI_SETCALLBACK_DEFN(pwfsSlopeCalc, m_indiP_quad4)(const pcf::IndiProperty &ipRecv)
774 : {
775 0 : if(ipRecv.getName() != m_indiP_quad4.getName())
776 : {
777 0 : log<software_error>({__FILE__,__LINE__,"wrong INDI property received"});
778 :
779 0 : return -4;
780 : }
781 :
782 0 : if(ipRecv.find("set-x"))
783 : {
784 0 : float newval = ipRecv["set-x"].get<float>();
785 0 : if(newval != m_pupil_cx_4)
786 : {
787 0 : m_pupil_cx_4 = newval;
788 0 : m_reconfig = true;
789 : }
790 : }
791 0 : if(ipRecv.find("set-y"))
792 : {
793 0 : float newval = ipRecv["set-y"].get<float>();
794 0 : if(newval != m_pupil_cy_4)
795 : {
796 0 : m_pupil_cy_4 = newval;
797 0 : m_reconfig = true;
798 : }
799 : }
800 0 : if(ipRecv.find("set-D"))
801 : {
802 0 : float newval = ipRecv["set-D"].get<float>();
803 0 : if(newval != m_pupil_D_4)
804 : {
805 0 : m_pupil_D_4 = newval;
806 0 : m_reconfig = true;
807 : }
808 : }
809 :
810 :
811 0 : return 0;
812 : }
813 :
814 : inline
815 0 : int pwfsSlopeCalc::checkRecordTimes()
816 : {
817 0 : return telemeterT::checkRecordTimes(telem_fgtimings());
818 : }
819 :
820 : inline
821 0 : int pwfsSlopeCalc::recordTelem( const telem_fgtimings * )
822 : {
823 0 : return recordFGTimings(true);
824 : }
825 :
826 : } //namespace app
827 : } //namespace MagAOX
828 :
829 : #endif //pwfsSlopeCalc_hpp
|