API
 
Loading...
Searching...
No Matches
baslerCtrl.hpp
Go to the documentation of this file.
1/** \file baslerCtrl.hpp
2 * \brief The MagAO-X basler camera controller.
3 *
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 * \ingroup baslerCtrl_files
7 */
8
9#ifndef baslerCtrl_hpp
10#define baslerCtrl_hpp
11
12
13
14#include <pylon/PylonIncludes.h>
15#include <pylon/PixelData.h>
16#include <pylon/GrabResultData.h>
17#include <pylon/usb/BaslerUsbInstantCamera.h>
18#include <pylon/usb/_BaslerUsbCameraParams.h>
19#include <GenApi/IFloat.h>
20
21typedef Pylon::CBaslerUsbInstantCamera Camera_t;
22typedef int16_t pixelT;
23
24using namespace Basler_UsbCameraParams;
25
26using namespace Pylon;
27
28//#include <ImageStruct.h>
29#include <ImageStreamIO/ImageStreamIO.h>
30
31#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
32#include "../../magaox_git_version.h"
33
34namespace MagAOX
35{
36namespace app
37{
38
39/** \defgroup baslerCtrl Basler USB3 Camera
40 * \brief Control of a Basler USB3 Camera
41 *
42 * <a href="../handbook/operating/software/apps/baslerCtrl.html">Application Documentation</a>
43 *
44 * \ingroup apps
45 *
46 */
47
48/** \defgroup baslerCtrl_files Basler USB3 Camera Files
49 * \ingroup baslerCtrl
50 */
51
52/** MagAO-X application to control a Basler USB3 Camera
53 *
54 * \ingroup baslerCtrl
55 *
56 */
57class baslerCtrl : public MagAOXApp<>, public dev::stdCamera<baslerCtrl>, public dev::frameGrabber<baslerCtrl>, public dev::telemeter<baslerCtrl>
58{
59
60 friend class dev::stdCamera<baslerCtrl>;
61 friend class dev::frameGrabber<baslerCtrl>;
62 friend class dev::telemeter<baslerCtrl>;
63
64public:
65 /** \name app::dev Configurations
66 *@{
67 */
68 static constexpr bool c_stdCamera_tempControl = false; ///< app::dev config to tell stdCamera to not expose temperature controls
69
70 static constexpr bool c_stdCamera_temp = true; ///< app::dev config to tell stdCamera to expose temperature
71
72 static constexpr bool c_stdCamera_readoutSpeed = false; ///< app::dev config to tell stdCamera not to expose readout speed controls
73
74 static constexpr bool c_stdCamera_vShiftSpeed = false; ///< app:dev config to tell stdCamera not to expose vertical shift speed control
75
76 static constexpr bool c_stdCamera_emGain = false; ///< app::dev config to tell stdCamera to not expose EM gain controls
77
78 static constexpr bool c_stdCamera_exptimeCtrl = true; ///< app::dev config to tell stdCamera to expose exposure time controls
79
80 static constexpr bool c_stdCamera_fpsCtrl = true; ///< app::dev config to tell stdCamera to expose FPS controls
81
82 static constexpr bool c_stdCamera_fps = true; ///< app::dev config to tell stdCamera not to expose FPS status (ignored since fpsCtrl=true)
83
84 static constexpr bool c_stdCamera_synchro = false; ///< app::dev config to tell stdCamera to not expose synchro mode controls
85
86 static constexpr bool c_stdCamera_usesModes = false; ///< app:dev config to tell stdCamera not to expose mode controls
87
88 static constexpr bool c_stdCamera_usesROI = true; ///< app:dev config to tell stdCamera to expose ROI controls
89
90 static constexpr bool c_stdCamera_cropMode = false; ///< app:dev config to tell stdCamera not to expose Crop Mode controls
91
92 static constexpr bool c_stdCamera_hasShutter = false; ///< app:dev config to tell stdCamera to expose shutter controls
93
94 static constexpr bool c_stdCamera_usesStateString = false; ///< app::dev confg to tell stdCamera to expose the state string property
95
96 static constexpr bool c_frameGrabber_flippable = true; ///< app:dev config to tell framegrabber that this camera can be flipped
97
98 ///@}
99
100protected:
101
102 /** \name configurable parameters
103 *@{
104 */
105 std::string m_serialNumber; ///< The camera's identifying serial number
106
107 int m_bits {10}; ///< The number of bits used by the camera.
108
109 ///@}
110
111 /** \name binning allowed values
112 * @{
113 */
114 std::vector<int> m_binXs; ///< The allowed values of binning in X (horizontal)
115 std::vector<int> m_binYs; ///< The allowed values of binning in Y (vertical)
116
117 std::vector<int> m_incXs; ///< The allowed increment in X for each X-binning
118
119 std::vector<int> m_minWs; ///< The minimum value of the width for each X-binning
120 std::vector<int> m_incWs; ///< The minimum value of the width for each X-binning
121 std::vector<int> m_maxWs; ///< The minimum value of the width for each X-binning
122
123 std::vector<int> m_incYs; ///< The allowed increment in Y for each Y-binning
124
125 std::vector<int> m_minHs; ///< The minimum value of the height for each Y-binning
126 std::vector<int> m_incHs; ///< The minimum value of the height for each Y-binning
127 std::vector<int> m_maxHs; ///< The minimum value of the height for each Y-binning
128
129 ///@}
130
131 CBaslerUsbInstantCamera * m_camera {nullptr}; ///< The library camera handle
132 CGrabResultPtr ptrGrabResult; ///< The result of an attempt to grab an image
133
134public:
135
136 ///Default c'tor
137 baslerCtrl();
138
139 ///Destructor
141
142 /// Setup the configuration system (called by MagAOXApp::setup())
143 virtual void setupConfig();
144
145 /// load the configuration system results (called by MagAOXApp::setup())
146 virtual void loadConfig();
147
148 /// Startup functions
149 /** Sets up the INDI vars.
150 *
151 */
152 virtual int appStartup();
153
154 /// Implementation of the FSM for the Siglent SDG
155 virtual int appLogic();
156
157 /// Do any needed shutdown tasks. Currently nothing in this app.
158 virtual int appShutdown();
159
160 int connect();
161
163 int startAcquisition();
165 int loadImageIntoStream(void * dest);
166 int reconfig();
167
169
170 /// Get the current detector temperature
171 /**
172 * \returns 0 on success
173 * \returns -1 on an error.
174 */
175 int getTemp();
176
177 /// Get the current exposure time
178 /**
179 * \returns 0 on success
180 * \returns -1 on an error.
181 */
182 int getExpTime();
183
184 /// Get the current framerate
185 /**
186 * \returns 0 on success
187 * \returns -1 on an error.
188 */
189 int getFPS();
190
191 float fps();
192
193 /** \name stdCamera Interface
194 *
195 * @{
196 */
197
198 /// Set defaults for a power on state.
199 /**
200 * \returns 0 on success
201 * \returns -1 on error
202 */
203 int powerOnDefaults();
204
205 /// Set the framerate.
206 /** This uses the acquistion framerate feature. If m_fpsSet is 0, acuisition framerate is disabled
207 * and the resultant framerate is based solely on exposure time and ROI. If non-zero, then the
208 * framerate will be set to m_fpsSet and the camera will maintain this (as long as exposure time
209 * and ROI allow).
210 *
211 * \returns 0 always
212 */
213 int setFPS();
214
215 /// Set the Exposure Time. [stdCamera interface]
216 /** Sets the frame rate to m_expTimeSet.
217 *
218 * \returns 0 on success
219 * \returns -1 on error
220 */
221 int setExpTime();
222
223 /// Check the next ROI
224 /** Checks if the target values are valid and adjusts them to the closest valid values if needed.
225 *
226 * \returns 0 always
227 */
228 int checkNextROI();
229
230 /// Set the next ROI
231 /**
232 * \returns 0 always
233 */
234 int setNextROI();
235
236 ///@}
237
238 /** \name Telemeter Interface
239 *
240 * @{
241 */
242
243 int checkRecordTimes();
244
246
247 ///@}
248
249};
250
251inline
258
259inline
261{
262 return;
263}
264
265inline
267{
269
271
272 config.add("camera.serialNumber", "", "camera.serialNumber", argType::Required, "camera", "serialNumber", false, "int", "The identifying serial number of the camera.");
273 config.add("camera.bits", "", "camera.bits", argType::Required, "camera", "bits", false, "int", "The number of bits used by the camera. Default is 10.");
274
276
277}
278
279inline
281{
283
284 config(m_serialNumber, "camera.serialNumber");
285 config(m_bits, "camera.bits");
286
288
290}
291
292
293inline
295{
296
297 //=================================
298 // Do camera configuration here
299
300 PylonInitialize(); // Initializes pylon runtime before using any pylon methods
301
302
304 {
306 }
307
309 {
311 }
312
313
315 {
316 return log<software_error,-1>({__FILE__,__LINE__});
317 }
318
320
321 return 0;
322
323}
324
325inline
327{
328 //and run stdCamera's appLogic
330 {
331 return log<software_error, -1>({__FILE__, __LINE__});
332 }
333
334 //and run frameGrabber's appLogic to see if the f.g. thread has exited.
336 {
337 return log<software_error, -1>({__FILE__, __LINE__});
338 }
339
340
342 {
343 std::unique_lock<std::mutex> lock(m_indiMutex);
344 if(connect() < 0)
345 {
347 }
348
349 if(state() != stateCodes::CONNECTED) return 0;
350 }
351
353 {
354 //Get a lock
355 std::unique_lock<std::mutex> lock(m_indiMutex);
356
358 }
359
361 {
362 //Get a lock if we can
363 std::unique_lock<std::mutex> lock(m_indiMutex, std::try_to_lock);
364
365 //but don't wait for it, just go back around.
366 if(!lock.owns_lock()) return 0;
367
368 if(getTemp() < 0)
369 {
371 return 0;
372 }
373
374 if(getExpTime() < 0)
375 {
377 return 0;
378 }
379
380 if(getFPS() < 0)
381 {
383 return 0;
384 }
385
387 {
390 return 0;
391 }
392
394 {
397 return 0;
398 }
399
401 {
403 return 0;
404 }
405 }
406
407 ///\todo Fall through check?
408
409 return 0;
410
411}
412
413
414inline
429
430
431inline
433{
435 //info.SetDeviceClass(Camera_t::DeviceClass());
436 info.SetSerialNumber(m_serialNumber.c_str());
437
438 try
439 {
440 if(m_camera)
441 {
442 m_camera->Close();
443 delete m_camera;
444 }
445 m_camera = nullptr;
446
447 m_camera = new CBaslerUsbInstantCamera( CTlFactory::GetInstance().CreateFirstDevice(info) );
448 }
449 catch(...)
450 {
451 if(m_camera)
452 {
453 m_camera->Close();
454 delete m_camera;
455 }
456 m_camera = nullptr;
457
459 if(!stateLogged())
460 {
461 log<text_log>("no camera with serial number " + m_serialNumber + " found.");
462 }
463 return 0;
464 }
465
466
467 try
468 {
469 if(m_shmimName == "")
470 {
471 m_shmimName = (std::string)m_camera->GetDeviceInfo().GetModelName() + "_" + (std::string)m_camera->GetDeviceInfo().GetSerialNumber(); // Gets m_camera model name and serial number
472 }
473
475
476 m_camera->Open(); // Opens camera parameters to grab images and set exposure time
477 }
478 catch(...)
479 {
480 if(m_camera)
481 {
482 m_camera->Close();
483 delete m_camera;
484 }
485 m_camera = nullptr;
486
488 if(!stateLogged())
489 {
490 log<text_log>("error opening camera " + m_serialNumber + ".");
491 }
492 return -1;
493 }
494
495 try
496 {
497 m_camera->ExposureAuto.SetValue(ExposureAuto_Off);
498 }
499 catch(...)
500 {
501 if(m_camera)
502 {
503 m_camera->Close();
504 delete m_camera;
505 }
506 m_camera = nullptr;
507
509 if(!stateLogged())
510 {
511 log<text_log>("failed to set exposure auto off for camera " + m_serialNumber);
512 }
513 return -1;
514 }
515
516 try
517 {
518 if(m_bits == 8)
519 {
520 m_camera->PixelFormat.SetValue(PixelFormat_Mono8);
521 }
522 else if(m_bits == 10)
523 {
524 m_camera->PixelFormat.SetValue(PixelFormat_Mono10); // Set to 10 bits
525 }
526 else if(m_bits == 12)
527 {
528 m_camera->PixelFormat.SetValue(PixelFormat_Mono12);
529 }
530 else
531 {
532 log<text_log>("unsupported bit depth for camera" + m_serialNumber + "");
533 }
534 }
535 catch(...)
536 {
537 if(m_camera)
538 {
539 m_camera->Close();
540 delete m_camera;
541 }
542 m_camera = nullptr;
543
545 if(!stateLogged())
546 {
547 log<text_log>("failed to set bit depth for camera" + m_serialNumber + "");
548 }
549 return -1;
550 }
551
553 if(!stateLogged())
554 {
555 log<text_log>("Found camera of type " + (std::string)m_camera->GetDeviceInfo().GetModelName() + " with serial number " + m_serialNumber + ".");
556 log<text_log>("Using shared memory name " + m_shmimName + ".");
557 }
558
559 m_camera->BinningHorizontalMode.SetValue(BinningHorizontalMode_Sum);
560 m_camera->BinningVerticalMode.SetValue(BinningVerticalMode_Sum);
561
562 // -- Here we interrogate the camera to find valid ROI settings -- //
563
564 // Stop the camera and cycle through settings to get limits for each binning
565 m_camera->StopGrabbing();
566 m_camera->OffsetX.SetValue(0); //ensure that all values are valid
567 m_camera->OffsetY.SetValue(0);
568
569 int minb = m_camera->BinningHorizontal.GetMin();
570 int incb = m_camera->BinningHorizontal.GetInc();
571 int maxb = m_camera->BinningHorizontal.GetMax();
572
573 m_binXs.clear();
574 for(int b = minb; b<=maxb; b+=incb) m_binXs.push_back(b);
575
576 minb = m_camera->BinningVertical.GetMin();
577 incb = m_camera->BinningVertical.GetInc();
578 maxb = m_camera->BinningVertical.GetMax();
579
580 m_binYs.clear();
581 for(int b = minb; b<=maxb; b+=incb) m_binYs.push_back(b);
582
583 m_incXs.clear();
584 m_minWs.clear();
585 m_incWs.clear();
586 m_maxWs.clear();
587 for(size_t b=0; b < m_binXs.size(); ++b)
588 {
589 m_camera->BinningHorizontal.SetValue(m_binXs[b]);
590 m_camera->BinningVertical.SetValue(m_binYs[0]);
591
592 m_incXs.push_back(m_camera->OffsetX.GetInc());
593 m_minWs.push_back(m_camera->Width.GetMin());
594 m_incWs.push_back(m_camera->Width.GetInc());
595 m_maxWs.push_back(m_camera->Width.GetMax());
596
597 /*//Leave for troubleshooting:
598 std::cerr << "--------------------\nH-binning: " << m_binXs[b] << "\n";
599 std::cerr << "OffsetX: " << 1 << " " << m_camera->OffsetX.GetInc() << " " << m_camera->Width.GetMax() - m_camera->Width.GetMin() << "\n";
600 std::cerr << "Width: " << m_camera->Width.GetMin() << " " << m_camera->Width.GetInc() << " " << m_camera->Width.GetMax() << "\n";
601 std::cerr << "OffsetY: " << 1 << " " << m_camera->OffsetY.GetInc() << " " << m_camera->Height.GetMax() - m_camera->Height.GetMin() << "\n";
602 std::cerr << "Height: " << m_camera->Height.GetMin() << " " << m_camera->Height.GetInc() << " " << m_camera->Height.GetMax() << "\n";
603 */
604 }
605
606 m_incYs.clear();
607 m_minHs.clear();
608 m_incHs.clear();
609 m_maxHs.clear();
610 for(size_t b=0; b < m_binYs.size(); ++b)
611 {
612 m_camera->BinningHorizontal.SetValue(m_binXs[0]);
613 m_camera->BinningVertical.SetValue(m_binYs[b]);
614
615 m_incYs.push_back(m_camera->OffsetX.GetInc());
616 m_minHs.push_back(m_camera->Height.GetMin());
617 m_incHs.push_back(m_camera->Height.GetInc());
618 m_maxHs.push_back(m_camera->Height.GetMax());
619
620 /*//Leave for troubleshooting:
621 std::cerr << "--------------------\nV-binning: " << m_binYs[b] << "\n";
622 std::cerr << "OffsetX: " << 1 << " " << m_camera->OffsetX.GetInc() << " " << m_camera->Width.GetMax() - m_camera->Width.GetMin() << "\n";
623 std::cerr << "Width: " << m_camera->Width.GetMin() << " " << m_camera->Width.GetInc() << " " << m_camera->Width.GetMax() << "\n";
624 std::cerr << "OffsetY: " << 1 << " " << m_camera->OffsetY.GetInc() << " " << m_camera->Height.GetMax() - m_camera->Height.GetMin() << "\n";
625 std::cerr << "Height: " << m_camera->Height.GetMin() << " " << m_camera->Height.GetInc() << " " << m_camera->Height.GetMax() << "\n";
626 */
627 }
628
629 m_full_w = m_camera->SensorWidth.GetValue();
630 m_full_h = m_camera->SensorHeight.GetValue();
631 m_full_x = 0.5*((float) m_full_w-1.0);
632 m_full_y = 0.5*((float) m_full_h-1.0);
633
638 if(m_default_bin_x == 0) m_binXs[0];
639 if(m_default_bin_y == 0) m_binYs[0];
640
647
648 return 0;
649}
650
651
653{
654 if(!m_camera) return -1;
655
656 try
657 {
658 recordCamera(true);
659 m_camera->StopGrabbing();
660 /*
661 The CenterX/Y has to be set to false otherwise the software tries to auto-center the frames.
662 See: https://docs.baslerweb.com/image-roi
663 */
664 m_camera->CenterX.SetValue(false);
665 m_camera->CenterY.SetValue(false);
666
667 //set offsets to 0 so any valid w/h will work.
668 m_camera->OffsetX.SetValue(0);
669 m_camera->OffsetY.SetValue(0);
670
671 if(checkNextROI() < 0)
672 {
673 log<software_error>({__FILE__, __LINE__, "error from checkNextROI()"});
674 return -1;
675 }
676
677 //Note: assuming checkNextROI has adjusted m_nextROI to valid values, so not doing any checks
678 //First find binning indices
679 size_t bx = 0;
680 for(size_t b =0; b < m_binXs.size(); ++b)
681 {
682 if(m_nextROI.bin_x == m_binXs[b])
683 {
684 bx = b;
685 break;
686 }
687 }
688
689 size_t by = 0;
690 for(size_t b =0; b < m_binYs.size(); ++b)
691 {
692 if(m_nextROI.bin_y == m_binYs[b])
693 {
694 by = b;
695 break;
696 }
697 }
698
699 //Set ROI.
700 int xoff;
701 int yoff;
703 {
704 xoff = (m_maxWs[bx] - 1 - m_nextROI.x) - 0.5*((float) m_nextROI.w - 1);
705 }
706 else
707 {
708 xoff = m_nextROI.x - 0.5*((float) m_nextROI.w - 1);
709 }
710
712 {
713 yoff = (m_maxHs[by] - 1 - m_nextROI.y) - 0.5*((float) m_nextROI.h - 1);
714 }
715 else
716 {
717 yoff = m_nextROI.y - 0.5*((float) m_nextROI.h - 1);
718 }
719
720 m_camera->BinningHorizontal.SetValue(m_nextROI.bin_x);
721 m_camera->BinningVertical.SetValue(m_nextROI.bin_y);
722 //Probably not necessary to do it every time, but just in case:
723 m_camera->BinningHorizontalMode.SetValue(BinningHorizontalMode_Sum);
724 m_camera->BinningVerticalMode.SetValue(BinningVerticalMode_Sum);
725
726 m_camera->Width.SetValue(m_nextROI.w);
727 m_camera->Height.SetValue(m_nextROI.h);
728
729 m_camera->OffsetX.SetValue(xoff);
730 m_camera->OffsetY.SetValue(yoff);
731
732 // Read the parameter from the camera to check if parameter change is successful
733 m_currentROI.bin_x = m_camera->BinningHorizontal.GetValue();
734 m_currentROI.bin_y = m_camera->BinningVertical.GetValue();
735
736 bx = 0;
737 for(size_t b =0; b < m_binXs.size(); ++b)
738 {
739 if(m_nextROI.bin_x == m_binXs[b])
740 {
741 bx = b;
742 break;
743 }
744 }
745
746 by = 0;
747 for(size_t b =0; b < m_binYs.size(); ++b)
748 {
749 if(m_nextROI.bin_y == m_binYs[b])
750 {
751 by = b;
752 break;
753 }
754 }
755
756 m_currentROI.w = m_camera->Width.GetValue();
757 m_currentROI.h = m_camera->Height.GetValue();
758
760 {
761 m_currentROI.x = m_maxWs[bx] - 1 - (m_camera->OffsetX.GetValue() + 0.5*((float) m_currentROI.w - 1));
762 }
763 else
764 {
765 m_currentROI.x = m_camera->OffsetX.GetValue() + 0.5*((float) m_currentROI.w - 1);
766 }
767
769 {
770 m_currentROI.y = m_maxHs[by] - 1 - (m_camera->OffsetY.GetValue() + 0.5*((float) m_currentROI.h - 1));
771 }
772 else
773 {
774 m_currentROI.y = m_camera->OffsetY.GetValue() + 0.5*((float) m_currentROI.h - 1);
775 }
776
777 //Set the full window for this binning
782
783 //Update binning
790
791 //We also update target to the settable values
796 m_nextROI.bin_x = m_currentROI.bin_x;
797 m_nextROI.bin_y = m_currentROI.bin_y;
798
805
809
810 getFPS();
811
812 recordCamera(true);
813 }
814 catch(...)
815 {
816 log<software_error>({__FILE__, __LINE__, "invalid ROI specifications"});
818 return -1;
819 }
820
821 return 0;
822}
823
825{
826 try
827 {
828 m_camera->StartGrabbing(GrabStrategy_LatestImageOnly ); // Start grabbing, and always grab just the last image.
829 }
830 catch(...)
831 {
833 return -1;
834 }
835
837
838 return 0;
839}
840
842{
843 try
844 {
846 }
847 catch(...)
848 {
850 return -1;
851 }
852
853 if (ptrGrabResult->GrabSucceeded()) // If image is grabbed successfully
854 {
856 return 0;
857 }
858 else
859 {
861 return -1;
862 }
863}
864
865
867{
868 pixelT * src = nullptr;
869 try
870 {
871 src = (pixelT *) ptrGrabResult->GetBuffer();
872 }
873 catch(...)
874 {
876 return -1;
877 }
878
879 if(src == nullptr) return -1;
880
882
883 return 0;
884}
885
887{
888
889
890 return 0;
891}
892
893
894inline
896{
897 if( m_camera == nullptr) return 0;
898
899 try
900 {
901 m_ccdTemp = (float)m_camera->DeviceTemperature.GetValue();
902 recordCamera();
903 }
904 catch(...)
905 {
906 m_ccdTemp = -999;
907 recordCamera();
909 return -1;
910 }
911
912 return 0;
913
914}
915
916inline
918{
919 if( m_camera == nullptr) return 0;
920
921 try
922 {
923 m_expTime = (float)m_camera->ExposureTime.GetValue()/1e6;
924 recordCamera();
925 }
926 catch(...)
927 {
928 m_expTime = -999;
929 recordCamera();
931 return -1;
932 }
933
934 return 0;
935
936}
937
938inline
940{
941 if( m_camera == nullptr) return 0;
942
943 try
944 {
945 m_fps = m_camera->ResultingFrameRate.GetValue();
946 recordCamera();
947 }
948 catch(...)
949 {
950 m_fps = -999;
951 recordCamera();
953 return -1;
954 }
955
956 return 0;
957
958}
959
960inline
962{
963 return m_fps;
964
965}
966
967inline
969{
976
977 return 0;
978}
979
980inline
982{
983 if( m_camera == nullptr) return 0;
984
985 recordCamera(true);
986
987 if(m_fpsSet == 0)
988 {
989 try
990 {
991 m_camera->AcquisitionFrameRateEnable.SetValue(false);
992 }
993 catch(...)
994 {
995 return log<software_error,-1>({__FILE__, __LINE__, "Error disabling frame rate limit."});
996 }
997 }
998 else
999 {
1000 try
1001 {
1002 m_camera->AcquisitionFrameRateEnable.SetValue(true);
1003 m_camera->AcquisitionFrameRate.SetValue(m_fpsSet);
1004 }
1005 catch(...)
1006 {
1007 return log<software_error,-1>({__FILE__, __LINE__, "Error setting frame rate limit."});
1008 }
1009 }
1010
1011 return 0;
1012}
1013
1014inline
1016{
1017 if( m_camera == nullptr) return 0;
1018
1019 try
1020 {
1021 recordCamera(true);
1022 m_camera->ExposureTime.SetValue(m_expTimeSet*1e6);
1023 }
1024 catch(...)
1025 {
1026 log<software_error>({__FILE__, __LINE__, "Error setting exposure time"});
1027 return -1;
1028 }
1029
1030 log<text_log>( "Set exposure time: " + std::to_string(m_expTimeSet) + " sec");
1031
1032 return 0;
1033}
1034
1035inline
1037{
1038 std::cerr << "checkNextROI!\n";
1039
1040 //First find binning indices
1041 size_t bx = 0;
1042 for(size_t b =0; b < m_binXs.size(); ++b)
1043 {
1044 if(m_nextROI.bin_x == m_binXs[b])
1045 {
1046 bx = b;
1047 break;
1048 }
1049 }
1050 std::cerr << "req bin_x: " << m_nextROI.bin_x << " " << "adj bin_x: " << m_binXs[bx] << "\n";
1051 m_nextROI.bin_x = m_binXs[bx]; //In case no valid value was found.
1052
1053 size_t by = 0;
1054 for(size_t b =0; b < m_binYs.size(); ++b)
1055 {
1056 if(m_nextROI.bin_y == m_binYs[b])
1057 {
1058 by = b;
1059 break;
1060 }
1061 }
1062 std::cerr << "req bin_y: " << m_nextROI.bin_y << " " << "adj bin_y: " << m_binYs[by] << "\n";
1063 m_nextROI.bin_y = m_binYs[by]; //In case no valid value was found.
1064
1065 //Next check width
1066 //-- round to nearest increment
1067 //-- check limits
1068 int w = m_nextROI.w;
1069 int rw = w % m_incWs[bx];
1070 if(rw < 0.5*m_incWs[bx]) w -= rw;
1071 else w += m_incWs[bx] - rw;
1072
1073 if(w < m_minWs[bx]) w = m_minWs[bx];
1074 else if(w > m_maxWs[bx]) w = m_maxWs[bx];
1075
1076 std::cerr << "req w: " << m_nextROI.w << " " << "adj w: " << w << "\n";
1077 m_nextROI.w = w;
1078
1079 //Now check x
1080 //-- calculate offset from center
1081 //-- round to nearest increment
1082 //-- recalculate center
1083 int x;
1085 {
1086 x = (m_maxWs[bx] - 1 - m_nextROI.x) - 0.5*((float) w - 1);
1087 }
1088 else
1089 {
1090 x = m_nextROI.x - 0.5*((float) w - 1);
1091 }
1092
1093 int rx = x % m_incXs[bx];
1094 if(rx < 0.5*m_incXs[bx]) x -= rx;
1095 else x += m_incXs[bx] - rx;
1096
1097 if(x < 0) x=0;
1098 else if(x > m_maxWs[bx] - w) x = m_maxWs[bx] - w;
1099
1100 std::cerr << "req x: " << m_nextROI.x;
1102 {
1103 m_nextROI.x = m_maxWs[bx] - 1 - (x + 0.5*((float) w - 1.0));
1104 }
1105 else
1106 {
1107 m_nextROI.x = x + 0.5*((float) w - 1.0);
1108 }
1109 std::cerr << " adj x: " << m_nextROI.x << "\n";
1110
1111 //Next check height
1112 //-- round to nearest increment
1113 //-- check limits
1114 int h = m_nextROI.h;
1115 int rh = h % m_incHs[by];
1116 if(rh < 0.5*m_incHs[by]) h -= rh;
1117 else h += m_incHs[by] - rh;
1118
1119 if(h < m_minHs[by]) h = m_minHs[by];
1120 else if(h > m_maxHs[by]) h = m_maxHs[by];
1121
1122 std::cerr << "req h: " << m_nextROI.h << " " << "adj h: " << h << "\n";
1123 m_nextROI.h = h;
1124
1125 //Now check y
1126 //-- calculate offset from center
1127 //-- round to nearest increment
1128 //-- recalculate center
1129 int y;
1131 {
1132 y = (m_maxHs[by] - 1 - m_nextROI.y) - 0.5*((float) h - 1);
1133 }
1134 else
1135 {
1136 y = m_nextROI.y - 0.5*((float) h - 1);
1137 }
1138
1139 int ry = y % m_incYs[by];
1140 if(ry < 0.5*m_incYs[by]) y -= ry;
1141 else y += m_incYs[by] - ry;
1142
1143 if(y < 0) y=0;
1144 else if(y > m_maxHs[by] - h) y = m_maxHs[by] - h;
1145
1146 std::cerr << "req y: " << m_nextROI.y;
1148 {
1149 m_nextROI.y = m_maxHs[by] - 1 - (y + 0.5*((float) h - 1));
1150 }
1151 else
1152 {
1153 m_nextROI.y = y + 0.5*((float) h - 1);
1154 }
1155 std::cerr << " adj y: " << m_nextROI.y << "\n";
1156
1163
1164 return 0;
1165}
1166
1167inline
1169{
1170 std::cerr << "setNextROI:\n";
1171 std::cerr << " m_nextROI.x = " << m_nextROI.x << "\n";
1172 std::cerr << " m_nextROI.y = " << m_nextROI.y << "\n";
1173 std::cerr << " m_nextROI.w = " << m_nextROI.w << "\n";
1174 std::cerr << " m_nextROI.h = " << m_nextROI.h << "\n";
1175 std::cerr << " m_nextROI.bin_x = " << m_nextROI.bin_x << "\n";
1176 std::cerr << " m_nextROI.bin_y = " << m_nextROI.bin_y << "\n";
1177
1178 m_reconfig = true;
1179
1180 updateSwitchIfChanged(m_indiP_roi_set, "request", pcf::IndiElement::Off, INDI_IDLE);
1181 updateSwitchIfChanged(m_indiP_roi_full, "request", pcf::IndiElement::Off, INDI_IDLE);
1182 updateSwitchIfChanged(m_indiP_roi_last, "request", pcf::IndiElement::Off, INDI_IDLE);
1183 updateSwitchIfChanged(m_indiP_roi_default, "request", pcf::IndiElement::Off, INDI_IDLE);
1184 return 0;
1185}
1186
1187inline
1192
1193inline
1195{
1196 return recordCamera(true);
1197}
1198
1199
1200}//namespace app
1201} //namespace MagAOX
1202#endif
Pylon::CBaslerUsbInstantCamera Camera_t
int16_t pixelT
The base-class for MagAO-X applications.
Definition MagAOXApp.hpp:73
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.
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.
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
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 setFPS()
Set the framerate.
~baslerCtrl() noexcept
Destructor.
virtual int appStartup()
Startup functions.
static constexpr bool c_stdCamera_exptimeCtrl
app::dev config to tell stdCamera to expose exposure time controls
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
baslerCtrl()
Default c'tor.
static constexpr bool c_stdCamera_cropMode
app:dev config to tell stdCamera not to expose Crop Mode controls
static constexpr bool c_stdCamera_emGain
app::dev config to tell stdCamera to not expose EM gain controls
static constexpr bool c_stdCamera_fpsCtrl
app::dev config to tell stdCamera to expose FPS controls
int m_bits
The number of bits used by the camera.
static constexpr bool c_stdCamera_readoutSpeed
app::dev config to tell stdCamera not to expose readout speed controls
std::vector< int > m_minWs
The minimum value of the width for each X-binning.
static constexpr bool c_stdCamera_fps
app::dev config to tell stdCamera not to expose FPS status (ignored since fpsCtrl=true)
static constexpr bool c_stdCamera_hasShutter
app:dev config to tell stdCamera to expose shutter controls
int setExpTime()
Set the Exposure Time. [stdCamera interface].
static constexpr bool c_stdCamera_usesStateString
app::dev confg to tell stdCamera to expose the state string property
static constexpr bool c_stdCamera_vShiftSpeed
app:dev config to tell stdCamera not to expose vertical shift speed control
std::vector< int > m_maxWs
The minimum value of the width for each X-binning.
int getTemp()
Get the current detector temperature.
static constexpr bool c_stdCamera_synchro
app::dev config to tell stdCamera to not expose synchro mode controls
static constexpr bool c_stdCamera_temp
app::dev config to tell stdCamera to expose temperature
int recordTelem(const telem_stdcam *)
static constexpr bool c_stdCamera_usesModes
app:dev config to tell stdCamera not to expose mode controls
static constexpr bool c_stdCamera_usesROI
app:dev config to tell stdCamera to expose ROI controls
int checkNextROI()
Check the next ROI.
CBaslerUsbInstantCamera * m_camera
The library camera handle.
CGrabResultPtr ptrGrabResult
The result of an attempt to grab an image.
std::vector< int > m_maxHs
The minimum value of the height for each Y-binning.
std::vector< int > m_incYs
The allowed increment in Y for each Y-binning.
std::vector< int > m_binXs
The allowed values of binning in X (horizontal)
int setNextROI()
Set the next ROI.
static constexpr bool c_frameGrabber_flippable
app:dev config to tell framegrabber that this camera can be flipped
static constexpr bool c_stdCamera_tempControl
app::dev config to tell stdCamera to not expose temperature controls
int getExpTime()
Get the current exposure time.
std::vector< int > m_incHs
The minimum value of the height for each Y-binning.
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
int getFPS()
Get the current framerate.
virtual int appLogic()
Implementation of the FSM for the Siglent SDG.
int loadImageIntoStream(void *dest)
std::vector< int > m_incWs
The minimum value of the width for each X-binning.
std::string m_serialNumber
The camera's identifying serial number.
std::vector< int > m_incXs
The allowed increment in X for each X-binning.
int powerOnDefaults()
Set defaults for a power on state.
std::vector< int > m_binYs
The allowed values of binning in Y (vertical)
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
std::vector< int > m_minHs
The minimum value of the height for each Y-binning.
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.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
std::string m_shmimName
The name of the shared memory image, is used in /tmp/<shmimName>.im.shm. Derived classes should set a...
uint8_t m_dataType
The ImageStreamIO type code.
bool m_reconfig
Flag to set if a camera reconfiguration requires a framegrabber reset.
uint32_t m_height
The height of the image, once deinterlaced etc.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
MagAO-X standard camera interface.
float m_fpsSet
The commanded fps, as set by user.
pcf::IndiProperty m_indiP_roi_y
Property used to set the ROI x center coordinate.
int m_full_currbin_w
The current-binning full ROI width.
float m_default_x
Power-on ROI center x coordinate.
float m_full_currbin_x
The current-binning full ROI center x coordinate.
float m_expTime
The current exposure time, in seconds.
int m_default_bin_x
Power-on ROI x binning.
pcf::IndiProperty m_indiP_roi_last
Property used to trigger setting the last ROI.
float m_expTimeSet
The exposure time, in seconds, as set by user.
pcf::IndiProperty m_indiP_roi_h
Property used to set the ROI height.
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
float m_full_y
The full ROI center y coordinate.
pcf::IndiProperty m_indiP_roi_w
Property used to set the ROI width.
pcf::IndiProperty m_indiP_roi_default
Property used to trigger setting the default and startup ROI.
pcf::IndiProperty m_indiP_roi_bin_x
Property used to set the ROI x binning.
float m_full_x
The full ROI center x coordinate.
int m_full_currbin_h
The current-binning full ROI height.
float m_ccdTemp
The current temperature, in C.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
float m_full_currbin_y
The current-binning full ROI center y coordinate.
pcf::IndiProperty m_indiP_roi_full
Property used to trigger setting the full ROI.
pcf::IndiProperty m_indiP_roi_set
Property used to trigger setting the ROI.
int appShutdown()
Application shutdown.
float m_default_y
Power-on ROI center y coordinate.
pcf::IndiProperty m_indiP_roi_bin_y
Property used to set the ROI y binning.
pcf::IndiProperty m_indiP_roi_x
Property used to set the ROI x center coordinate.
int m_default_bin_y
Power-on ROI y binning.
@ OPERATING
The device is operating, other than homing.
@ NODEVICE
No device exists for the application to control.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ READY
The device is ready for operation, but is not operating.
@ CONNECTED
The application has connected to the device or service.
@ NOTCONNECTED
The application is not connected to the device or service.
@ info
For information only.
#define INDI_IDLE
Definition indiUtils.hpp:28
#define INDI_OK
Definition indiUtils.hpp:29
std::unique_lock< std::mutex > lock(m_indiMutex)
Definition dm.hpp:24
A device base class which saves telemetry.
Definition telemeter.hpp:69
int appShutdown()
Perform telemeter application shutdown.
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
Software CRITICAL log entry.
Software ERR log entry.
Log entry recording stdcam stage specific status.