Visual Servoing Platform  version 3.6.1 under development (2024-07-18)
vpPylonGrabberGigE.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description: Implementation of vpPylonGrabberGigE class.
32  *
33  * Authors:
34  * Wenfeng CAI
35  *
36 *****************************************************************************/
37 
44 #include "vpPylonGrabberGigE.h"
45 
46 #ifdef VISP_HAVE_PYLON
47 
48 #include <visp3/core/vpException.h>
49 #include <visp3/core/vpTime.h>
50 
56 vpPylonGrabberGigE::vpPylonGrabberGigE() : m_camera(), m_index(0), m_numCameras(0), m_connected(false)
57 {
58  getNumCameras();
59 }
60 
65 
70 {
71  Pylon::CTlFactory &TlFactory = Pylon::CTlFactory::GetInstance();
72  Pylon::DeviceInfoList_t lstDevices;
73  Pylon::DeviceInfoList_t filter; // Filter for GigE cameras.
74  Pylon::CBaslerGigEDeviceInfo gige_devinfo;
75  filter.push_back(gige_devinfo);
76  TlFactory.EnumerateDevices(lstDevices, filter);
77 
78  m_numCameras = lstDevices.size();
79  return m_numCameras;
80 }
81 
87 std::ostream &vpPylonGrabberGigE::getCameraInfo(std::ostream &os)
88 {
89  connect();
90 
91  Pylon::CDeviceInfo deviceInfo = m_camera.GetDeviceInfo();
92  // Get the camera control object.
93  GenApi::INodeMap &control = m_camera.GetNodeMap();
94 
95  GenApi::CIntegerPtr widthMax = control.GetNode("WidthMax");
96  GenApi::CIntegerPtr heightMax = control.GetNode("HeightMax");
97 
98  os << "Camera information: " << std::endl;
99  os << " Serial number : " << deviceInfo.GetSerialNumber() << std::endl;
100  os << " Camera model : " << deviceInfo.GetModelName() << std::endl;
101  os << " Camera vendor : " << deviceInfo.GetVendorName() << std::endl;
102  os << " Resolution : " << widthMax->GetValue() << "x" << heightMax->GetValue() << std::endl;
103  os << " Firmware version : " << deviceInfo.GetDeviceVersion() << std::endl;
104 
105  return os;
106 }
107 
114 Pylon::CInstantCamera *vpPylonGrabberGigE::getCameraHandler()
115 {
116  connect();
117 
118  if (m_connected == true) {
119  return &m_camera;
120  }
121  else {
122  return nullptr;
123  }
124 }
125 
133 {
134  connect();
135 
136  float frame_rate = m_camera.AcquisitionFrameRateAbs.GetValue();
137  return frame_rate;
138 }
139 
147 {
148  connect();
149 
150  if (GenApi::IsReadable(m_camera.GainAbs))
151  return m_camera.GainAbs.GetValue();
152  else if (GenApi::IsReadable(m_camera.GainRaw))
153  return m_camera.GainRaw.GetValue();
154  else
155  throw vpException(vpException::notImplementedError, "Don't know how to get gain.");
156 }
157 
170 {
171  connect();
172 
173  if (GenApi::IsReadable(m_camera.BlackLevelAbs))
174  return m_camera.BlackLevelAbs.GetValue();
175  else if (GenApi::IsReadable(m_camera.BlackLevelRaw))
176  return m_camera.BlackLevelRaw.GetValue();
177  else
178  throw vpException(vpException::notImplementedError, "Don't know how to get blacklevel.");
179 }
180 
193 {
194  connect();
195 
196  if (GenApi::IsReadable(m_camera.ExposureTimeAbs))
197  return m_camera.ExposureTimeAbs.GetValue() * 0.001;
198  else if (GenApi::IsReadable(m_camera.ExposureTimeRaw))
199  return m_camera.ExposureTimeRaw.GetValue();
200  else
201  throw vpException(vpException::notImplementedError, "Don't know how to get exposure.");
202 }
203 
211 {
212  connect();
213 
214  float gamma = m_camera.Gamma.GetValue();
215  return gamma;
216 }
217 
224 std::string vpPylonGrabberGigE::getCameraSerial(unsigned int index)
225 {
226  getNumCameras();
227 
228  if (index >= m_numCameras) {
229  throw(vpException(vpException::badValue, "The camera with index %u is not present. Only %d cameras connected.",
230  index, m_numCameras));
231  }
232 
233  Pylon::CTlFactory &TlFactory = Pylon::CTlFactory::GetInstance();
234  Pylon::DeviceInfoList_t lstDevices; // List of connected cameras
235  Pylon::DeviceInfoList_t filter; // Filter for GigE cameras.
236  Pylon::CBaslerGigEDeviceInfo gige_devinfo;
237  filter.push_back(gige_devinfo);
238  TlFactory.EnumerateDevices(lstDevices, filter);
239 
240  std::ostringstream os;
241  os << lstDevices[index].GetSerialNumber();
242  return os.str();
243 }
244 
255 {
256  connect();
257 
258  bool success = selectUserSet(user_set);
259 
260  if (success) {
261  m_camera.UserSetLoad.Execute();
262  vpTime::wait(200); // How long you have to wait?
263  success = m_camera.UserSetLoad.IsDone();
264  }
265 
266  return success;
267 }
268 
276 {
277  connect();
278 
279  Basler_GigECamera::UserSetDefaultSelectorEnums user_set = m_camera.UserSetDefaultSelector.GetValue();
280 
281  switch (user_set) {
282  case Basler_GigECamera::UserSetDefaultSelector_Default:
283  return USERSET_DEFAULT;
284  break;
285  case Basler_GigECamera::UserSetDefaultSelector_UserSet1:
286  return USERSET_USERSET1;
287  break;
288  case Basler_GigECamera::UserSetDefaultSelector_UserSet2:
289  return USERSET_USERSET2;
290  break;
291  case Basler_GigECamera::UserSetDefaultSelector_UserSet3:
292  return USERSET_USERSET3;
293  break;
294  default:
295  return USERSET_UNKNOWN;
296  }
297 }
298 
315 void vpPylonGrabberGigE::setCameraIndex(unsigned int index)
316 {
317  if (index >= m_numCameras) {
318  throw(vpException(vpException::badValue, "The camera with index %u is not present. Only %d cameras connected.",
319  index, m_numCameras));
320  }
321 
322  m_index = index;
323 }
324 
331 void vpPylonGrabberGigE::setCameraSerial(const std::string &serial)
332 {
333  m_numCameras = getNumCameras();
334  for (unsigned int i = 0; i < m_numCameras; i++) {
335  if (getCameraSerial(i) == serial) {
336  m_index = i;
337  return;
338  }
339  }
340  throw(vpException(vpException::badValue, "The camera with serial id %s is not present.", serial.c_str()));
341 }
342 
350 float vpPylonGrabberGigE::setFrameRate(float frame_rate)
351 {
352  connect();
353 
354  m_camera.AcquisitionFrameRateAbs.SetValue(frame_rate);
355 
356  return m_camera.AcquisitionFrameRateAbs.GetValue();
357 }
358 
372 float vpPylonGrabberGigE::setGain(bool gain_auto, float gain_value)
373 {
374  connect();
375 
376  if (gain_auto)
377  m_camera.GainAuto.SetValue(Basler_GigECamera::GainAuto_Continuous);
378  else
379  m_camera.GainAuto.SetValue(Basler_GigECamera::GainAuto_Off);
380 
381  if (GenApi::IsWritable(m_camera.GainAbs)) {
382  m_camera.GainAbs.SetValue(gain_value);
383  return m_camera.GainAbs.GetValue();
384  }
385  else if (GenApi::IsWritable(m_camera.GainRaw)) {
386  m_camera.GainRaw.SetValue(gain_value);
387  return m_camera.GainRaw.GetValue();
388  }
389  else
390  throw vpException(vpException::notImplementedError, "Don't know how to set gain.");
391 }
392 
407 float vpPylonGrabberGigE::setBlackLevel(float blacklevel_value)
408 {
409  connect();
410 
411  if (GenApi::IsWritable(m_camera.BlackLevelAbs)) {
412  m_camera.BlackLevelAbs.SetValue(blacklevel_value);
413  return m_camera.BlackLevelAbs.GetValue();
414  }
415  else if (GenApi::IsWritable(m_camera.BlackLevelRaw)) {
416  m_camera.BlackLevelRaw.SetValue(blacklevel_value);
417  return m_camera.BlackLevelRaw.GetValue();
418  }
419  else
420  throw vpException(vpException::notImplementedError, "Don't know how to set blacklevel.");
421 }
422 
440 float vpPylonGrabberGigE::setExposure(bool exposure_on, bool exposure_auto, float exposure_value)
441 {
442  connect();
443 
444  if (exposure_on)
445  m_camera.ExposureMode.SetValue(Basler_GigECamera::ExposureMode_Timed);
446  else
447  m_camera.ExposureMode.SetValue(Basler_GigECamera::ExposureMode_Off);
448 
449  if (exposure_auto)
450  m_camera.ExposureAuto.SetValue(Basler_GigECamera::ExposureAuto_Continuous);
451  else
452  m_camera.ExposureAuto.SetValue(Basler_GigECamera::ExposureAuto_Off);
453 
454  if (GenApi::IsWritable(m_camera.ExposureTimeAbs)) {
455  m_camera.ExposureTimeAbs.SetValue(exposure_value * 1000);
456  return m_camera.ExposureTimeAbs.GetValue() * 0.001;
457  }
458  else if (GenApi::IsWritable(m_camera.ExposureTimeRaw)) {
459  m_camera.ExposureTimeRaw.SetValue(exposure_value);
460  return m_camera.ExposureTimeRaw.GetValue();
461  }
462  else
463  throw vpException(vpException::notImplementedError, "Don't know how to set exposure.");
464 }
465 
478 float vpPylonGrabberGigE::setGamma(bool gamma_on, float gamma_value)
479 {
480  connect();
481 
482  if (GenApi::IsWritable(m_camera.GammaEnable))
483  m_camera.GammaEnable.SetValue(gamma_on);
484 
485  if (GenApi::IsWritable(m_camera.Gamma)) {
486  m_camera.Gamma.SetValue(gamma_value);
487  return m_camera.Gamma.GetValue();
488  }
489  else
490  throw vpException(vpException::notImplementedError, "Don't know how to set gamma.");
491 }
492 
504 bool vpPylonGrabberGigE::saveUserSet(UserSetName user_set, bool set_default)
505 {
506  connect();
507 
508  bool success = selectUserSet(user_set);
509 
510  if (success) {
511  m_camera.UserSetSave.Execute();
512  vpTime::wait(200); // How long you have to wait?
513  success = m_camera.UserSetSave.IsDone();
514  }
515 
516  if (success && set_default)
517  success = setUserSetDefault(user_set);
518 
519  return success;
520 }
521 
532 {
533  connect();
534 
535  switch (user_set) {
536  case USERSET_DEFAULT:
537  m_camera.UserSetDefaultSelector.SetValue(Basler_GigECamera::UserSetDefaultSelector_Default);
538  return true;
539  break;
540  case USERSET_USERSET1:
541  m_camera.UserSetDefaultSelector.SetValue(Basler_GigECamera::UserSetDefaultSelector_UserSet1);
542  return true;
543  break;
544  case USERSET_USERSET2:
545  m_camera.UserSetDefaultSelector.SetValue(Basler_GigECamera::UserSetDefaultSelector_UserSet2);
546  return true;
547  break;
548  case USERSET_USERSET3:
549  m_camera.UserSetDefaultSelector.SetValue(Basler_GigECamera::UserSetDefaultSelector_UserSet3);
550  return true;
551  break;
552  default:
553  return false;
554  }
555 }
556 
563 {
564  connect();
565 
566  if (!m_camera.IsGrabbing()) {
567  m_camera.StartGrabbing(1);
568  }
569  if (m_connected && m_camera.IsGrabbing())
570  init = true;
571  else
572  init = false;
573 }
574 
581 {
582  if (m_camera.IsGrabbing()) {
583  m_camera.StopGrabbing();
584  }
585  if (m_connected && m_camera.IsGrabbing())
586  init = true;
587  else
588  init = false;
589 }
590 
597 {
598  if (m_connected == false) {
599  m_numCameras = getNumCameras();
600  if (m_numCameras == 0) {
601  throw(vpException(vpException::fatalError, "No camera found"));
602  }
603 
604  if (!m_camera.IsPylonDeviceAttached()) {
605  Pylon::CTlFactory &TlFactory = Pylon::CTlFactory::GetInstance();
606  Pylon::DeviceInfoList_t lstDevices;
607  Pylon::DeviceInfoList_t filter; // Filter for GigE cameras.
608  Pylon::CBaslerGigEDeviceInfo gige_devinfo;
609  filter.push_back(gige_devinfo);
610  TlFactory.EnumerateDevices(lstDevices, filter);
611 
612  m_camera.Attach(TlFactory.CreateDevice(lstDevices[m_index]));
613  }
614  // Connect to a camera
615  m_camera.Open();
616  m_connected = true;
617  }
618  if (m_connected && m_camera.IsGrabbing())
619  init = true;
620  else
621  init = false;
622 }
623 
630 {
631  if (m_connected == true) {
632  m_camera.Close();
633  m_connected = false;
634  }
635  if (m_connected && m_camera.IsGrabbing())
636  init = true;
637  else
638  init = false;
639 }
640 
650 {
651  stopCapture();
652  disconnect();
653 }
654 
661 {
662  open();
663 
664  Pylon::CGrabResultPtr grabResult;
665  // Retrieve an image
666  if (!m_camera.RetrieveResult(2000, grabResult)) {
667  throw(vpException(vpException::fatalError, "Cannot retrieve image from camera with serial %s",
668  getCameraSerial(m_index).c_str()));
669  }
670 
671  if (grabResult->GrabSucceeded()) {
672  height = grabResult->GetHeight();
673  width = grabResult->GetWidth();
674  I.resize(height, width);
675 
676  Pylon::CImageFormatConverter imageConvert;
677  imageConvert.OutputPixelFormat = Pylon::PixelType_Mono8;
678  imageConvert.OutputPaddingX = 0;
679  // Create a converted image
680  imageConvert.Convert(I.bitmap, sizeof(unsigned char) * width * height, (Pylon::IImage &)grabResult);
681  }
682 }
683 
690 {
691  open();
692 
693  Pylon::CGrabResultPtr grabResult;
694  // Retrieve an image
695  if (!m_camera.RetrieveResult(2000, grabResult)) {
696  throw(vpException(vpException::fatalError, "Cannot retrieve image from camera with serial %s",
697  getCameraSerial(m_index).c_str()));
698  }
699 
700  if (grabResult->GrabSucceeded()) {
701  height = grabResult->GetHeight();
702  width = grabResult->GetWidth();
703  I.resize(height, width);
704 
705  Pylon::CImageFormatConverter imageConvert;
706  imageConvert.OutputPixelFormat = Pylon::PixelType_BGRA8packed;
707  imageConvert.OutputPaddingX = 0;
708  // Create a converted image
709  Pylon::CPylonImage destImage;
710  imageConvert.Convert(destImage, (Pylon::IImage &)grabResult);
711  Pylon::SBGRA8Pixel *pixel = (Pylon::SBGRA8Pixel *)destImage.GetBuffer();
712  for (unsigned int i = 0; i < height; i++) {
713  for (unsigned int j = 0; j < width; j++) {
714  unsigned int p_index = i * width + j;
715  I[i][j].R = pixel[p_index].R;
716  I[i][j].G = pixel[p_index].G;
717  I[i][j].B = pixel[p_index].B;
718  I[i][j].A = pixel[p_index].A;
719  }
720  }
721  }
722 }
723 
729 {
730  open();
731  acquire(I);
732 }
733 
739 {
740  open();
741  acquire(I);
742 }
743 
756 {
757  connect();
758  startCapture();
759 }
760 
770 {
771  connect();
772 
773  switch (user_set) {
774  case USERSET_DEFAULT:
775  m_camera.UserSetSelector.SetValue(Basler_GigECamera::UserSetSelector_Default);
776  return true;
777  break;
778  case USERSET_USERSET1:
779  m_camera.UserSetSelector.SetValue(Basler_GigECamera::UserSetSelector_UserSet1);
780  return true;
781  break;
782  case USERSET_USERSET2:
783  m_camera.UserSetSelector.SetValue(Basler_GigECamera::UserSetSelector_UserSet2);
784  return true;
785  break;
786  case USERSET_USERSET3:
787  m_camera.UserSetSelector.SetValue(Basler_GigECamera::UserSetSelector_UserSet3);
788  return true;
789  break;
790  default:
791  return false;
792  }
793 }
794 
800 {
801  acquire(I);
802  return *this;
803 }
804 
810 {
811  acquire(I);
812  return *this;
813 }
814 END_VISP_NAMESPACE
815 #else
816 // Work around to avoid warning:
817 // libvisp_pylon.a(vpPylonGrabberGigE.cpp.o) has no symbols
818 void dummy_vpPylonGrabberGigE() { };
819 #endif // #ifdef VISP_HAVE_PYLON
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
@ notImplementedError
Not implemented.
Definition: vpException.h:69
@ fatalError
Fatal error.
Definition: vpException.h:72
unsigned int height
Number of rows in the image.
bool init
Set to true if the frame grabber has been initialized.
unsigned int width
Number of columns in the image.
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:538
Type * bitmap
points toward the bitmap
Definition: vpImage.h:135
void close()
Stop active camera capturing images and disconnect the active camera.
void setCameraIndex(unsigned int index)
bool loadUserSet(UserSetName user_set)
Loads the selected configuration into the camera's volatile memory and makes it the active configurat...
float setBlackLevel(float blacklevel_value=0)
std::string getCameraSerial(unsigned int index)
bool setUserSetDefault(UserSetName user_set)
Sets the configuration set to be used as the default startup set.
Pylon::CInstantCamera * getCameraHandler()
void acquire(vpImage< unsigned char > &I)
unsigned int getNumCameras()
float setExposure(bool exposure_on, bool exposure_auto, float exposure_value=0)
void setCameraSerial(const std::string &serial)
UserSetName getUserSetDefault()
Gets the configuration set being used as the default startup set.
float setGamma(bool gamma_on, float gamma_value=1)
float setFrameRate(float frame_rate)
bool selectUserSet(UserSetName user_set)
Selects the configuration set to load, save, or configure.
vpPylonGrabber & operator>>(vpImage< unsigned char > &I)
std::ostream & getCameraInfo(std::ostream &os)
float setGain(bool gain_auto, float gain_value=0)
bool saveUserSet(UserSetName user_set, bool set_default=false)
Saves the current active configuration set into the selected user set.
@ USERSET_DEFAULT
The default user set.
@ USERSET_UNKNOWN
User set not supported.
@ USERSET_USERSET1
User set 1.
@ USERSET_USERSET3
User set 3.
@ USERSET_USERSET2
User set 2.
VISP_EXPORT int wait(double t0, double t)