PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusSpinnakerVideoSource.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 #include "PlusConfigure.h"
9 
10 // Local includes
11 #include "vtkPlusChannel.h"
12 #include "vtkPlusDataSource.h"
13 
14 // Spinnaker API includes
15 #include <Spinnaker.h>
16 #include <SpinGenApi/SpinnakerGenApi.h>
17 
18 // STL includes
19 #include <map>
20 #include <sstream>
21 
22 //----------------------------------------------------------------------------
24 
25 namespace
26 {
27  typedef vtkPlusSpinnakerVideoSource psvs;
28  const unsigned int DEFAULT_CAMERA_NUM(0);
29  const psvs::PIXEL_ENCODING DEFAULT_PIXEL_ENCODING(psvs::RGB24);
30  const FrameSizeType DEFAULT_FRAME_SIZE = { 640, 480, 1 };
31  const unsigned int DEFAULT_FRAME_RATE(30);
32  const psvs::EXPOSURE_MODE DEFAULT_EXPOSURE_MODE(psvs::EXPOSURE_AUTO_CONTINUOUS);
33  const float FLAG_EXPOSURE_MICROSEC(-1);
34  const psvs::GAIN_MODE DEFAULT_GAIN_MODE(psvs::GAIN_AUTO_CONTINUOUS);
35  const float FLAG_GAIN_DB(-1);
36  const psvs::WHITE_BALANCE_MODE DEFAULT_WHITE_BALANCE_MODE(psvs::WB_AUTO_CONTINUOUS);
37  const float FLAG_WHITE_BALANCE(-1);
38 
39  // xml attribute values
40  std::string EXPOSURE_TIMED_STRING = "TIMED";
41  std::string EXPOSURE_AUTO_ONCE_STRING = "AUTO_ONCE";
42  std::string EXPOSURE_AUTO_CONTINUOUS_STRING = "AUTO_CONTINUOUS";
43  std::string GAIN_MANUAL_STRING = "MANUAL";
44  std::string GAIN_AUTO_ONCE_STRING = "AUTO_ONCE";
45  std::string GAIN_AUTO_CONTINUOUS_STRING = "AUTO_CONTINUOUS";
46  std::string WB_MANUAL_STRING = "MANUAL";
47  std::string WB_AUTO_ONCE_STRING = "AUTO_ONCE";
48  std::string WB_AUTO_CONTINUOUS_STRING = "AUTO_CONTINUOUS";
49 }
50 
51 //----------------------------------------------------------------------------
52 class vtkPlusSpinnakerVideoSource::vtkInternal
53 {
54 public:
55  vtkPlusSpinnakerVideoSource * External;
56 
57  vtkInternal(vtkPlusSpinnakerVideoSource* external)
58  : External(external)
59  {
60  }
61 
62  virtual ~vtkInternal()
63  {
64  }
65 
66  // Singleton reference to system object
67  Spinnaker::SystemPtr SystemPtr;
68 
69  // list of connected cameras
70  Spinnaker::CameraList CameraList;
71 
72  // camera pointer
73  Spinnaker::CameraPtr CameraPtr;
74 };
75 
76 //----------------------------------------------------------------------------
78  : Internal(new vtkInternal(this)),
79  FrameNumber(0),
80  CameraNumber(DEFAULT_CAMERA_NUM),
81  PixelEncoding(DEFAULT_PIXEL_ENCODING),
82  FrameRate(DEFAULT_FRAME_RATE),
83  ExposureMode(DEFAULT_EXPOSURE_MODE),
84  ExposureMicroSec(FLAG_EXPOSURE_MICROSEC),
85  GainMode(DEFAULT_GAIN_MODE),
86  GainDB(FLAG_GAIN_DB),
87  WhiteBalanceMode(DEFAULT_WHITE_BALANCE_MODE),
88  WhiteBalanceRed(FLAG_WHITE_BALANCE),
89  WhiteBalanceBlue(FLAG_WHITE_BALANCE)
90 {
91  LOG_TRACE("vtkPlusSpinnakerVideoSource::vtkPlusSpinnakerVideoSource()");
93  this->StartThreadForInternalUpdates = true;
94  this->InternalUpdateRate = 3 * DEFAULT_FRAME_RATE;
95  this->AcquisitionRate = DEFAULT_FRAME_RATE;
96  this->FrameSize[0] = DEFAULT_FRAME_SIZE[0];
97  this->FrameSize[1] = DEFAULT_FRAME_SIZE[1];
98  this->FrameSize[2] = 1;
99 }
100 
101 //----------------------------------------------------------------------------
103 {
104  LOG_TRACE("vtkPlusSpinnakerVideoSource::~vtkPlusSpinnakerVideoSource()");
105 
106  delete Internal;
107  Internal = nullptr;
108 }
109 
110 //----------------------------------------------------------------------------
111 void vtkPlusSpinnakerVideoSource::PrintConfiguration(ostream& os, vtkIndent indent)
112 {
113  // define enum maps
114  std::map<EXPOSURE_MODE, std::string> ExposureModeToString;
115  ExposureModeToString[EXPOSURE_TIMED] = EXPOSURE_TIMED_STRING;
116  ExposureModeToString[EXPOSURE_AUTO_ONCE] = EXPOSURE_AUTO_ONCE_STRING;
117  ExposureModeToString[EXPOSURE_AUTO_CONTINUOUS] = EXPOSURE_AUTO_CONTINUOUS_STRING;
118 
119  std::map<GAIN_MODE, std::string> GainModeToString;
120  GainModeToString[GAIN_MANUAL] = GAIN_MANUAL_STRING;
121  GainModeToString[GAIN_AUTO_ONCE] = GAIN_AUTO_ONCE_STRING;
122  GainModeToString[GAIN_AUTO_CONTINUOUS] = GAIN_AUTO_CONTINUOUS_STRING;
123 
124  std::map<WHITE_BALANCE_MODE, std::string> WhiteBalanceModeToString;
125  WhiteBalanceModeToString[WB_MANUAL] = WB_MANUAL_STRING;
126  WhiteBalanceModeToString[WB_AUTO_ONCE] = WB_AUTO_ONCE_STRING;
127  WhiteBalanceModeToString[WB_AUTO_CONTINUOUS] = WB_AUTO_CONTINUOUS_STRING;
128 
129  // print device parameters
130  os << indent << "CameraNumber: " << this->CameraNumber << std::endl;
131  os << indent << "VideoFormat:" << this->PixelEncoding << std::endl;
132  os << indent << "FrameSize:" << "[" << this->FrameSize[0] << ", " << this->FrameSize[1] << "]" << std::endl;
133  os << indent << "FrameRate:" << this->FrameRate << std::endl;
134  os << indent << "ExposureMode:" << ExposureModeToString.find(this->ExposureMode)->second << std::endl;
135  if (this->ExposureMode == EXPOSURE_TIMED)
136  {
137  os << indent << "ExposureMicroSec:" << this->ExposureMicroSec << std::endl;
138  }
139  os << indent << "GainMode:" << GainModeToString.find(this->GainMode)->second << std::endl;
140  if (this->GainMode == GAIN_MANUAL)
141  {
142  os << indent << "GainDB:" << this->GainDB << std::endl;
143  }
144  os << indent << "WhiteBalanceMode:" << WhiteBalanceModeToString.find(this->WhiteBalanceMode)->second << std::endl;
145  if (this->WhiteBalanceMode == WB_MANUAL)
146  {
147  os << indent << "WhiteBalance(red):" << this->WhiteBalanceRed << std::endl;
148  os << indent << "WhiteBalance(blue):" << this->WhiteBalanceBlue << std::endl;
149  }
150 }
151 
152 //----------------------------------------------------------------------------
153 void vtkPlusSpinnakerVideoSource::PrintSelf(ostream& os, vtkIndent indent)
154 {
155  LOG_TRACE("vtkPlusSpinnakerVideoSource::PrintSelf(ostream& os, vtkIndent indent)");
156 
157  this->Superclass::PrintSelf(os, indent);
158  this->PrintConfiguration(os, indent);
159 }
160 
161 //----------------------------------------------------------------------------
163 {
164  if (frameRate < 1)
165  {
166  LOG_WARNING("Requested frame rate of " << frameRate << " (fps) is too low. Using default of " << DEFAULT_FRAME_RATE << ".");
167  this->FrameRate = DEFAULT_FRAME_RATE;
168  return PLUS_FAIL;
169  }
170  this->AcquisitionRate = frameRate;
171  this->InternalUpdateRate = frameRate;
172  this->FrameRate = frameRate;
173  return PLUS_SUCCESS;
174 }
175 
176 //----------------------------------------------------------------------------
178 {
179  this->ExposureMode = expMode;
180  return PLUS_SUCCESS;
181 }
182 
183 //----------------------------------------------------------------------------
185 {
186  if (exposureMicroSec < 11 || exposureMicroSec > 30000000)
187  {
188  LOG_WARNING("Requested invalid exposure time of " << exposureMicroSec << " (us). Using continuous auto-exposure.");
190  return PLUS_FAIL;
191  }
192  this->ExposureMicroSec = exposureMicroSec;
193  return PLUS_SUCCESS;
194 }
195 
196 //----------------------------------------------------------------------------
198 {
199  this->GainMode = gainMode;
200  return PLUS_SUCCESS;
201 }
202 
203 //----------------------------------------------------------------------------
205 {
206  if (gainDb < 0 || gainDb > 18)
207  {
208  LOG_WARNING("Requested invalid gain of " << gainDb << " (dB). Using continuous auto-gain.");
210  return PLUS_FAIL;
211  }
212  this->GainDB = gainDb;
213  return PLUS_SUCCESS;
214 }
215 
216 //----------------------------------------------------------------------------
218 {
219  this->WhiteBalanceMode = wbMode;
220  return PLUS_SUCCESS;
221 }
222 
223 //-----------------------------------------------------------------------------
224 // verify that if any manual settings are enabled then their corresponding values have also been set
226 {
227  PlusStatus retVal = PLUS_SUCCESS;
228 
229  // exposure
230  if (this->ExposureMode == EXPOSURE_TIMED && this->ExposureMicroSec == FLAG_EXPOSURE_MICROSEC)
231  {
232  LOG_ERROR("Failed to configure SpinnakerVideoSource: ExposureMode is set to \"TIMED\", but no ExposureMicroSec attribute is provided.");
233  retVal = PLUS_FAIL;
234  }
235 
236  // gain
237  if (this->GainMode == GAIN_MANUAL && this->GainDB == FLAG_GAIN_DB)
238  {
239  LOG_ERROR("Failed to configure SpinnakerVideoSource: GainMode is set to \"MANUAL\", but no GainDB attribute is provided.");
240  retVal = PLUS_FAIL;
241  }
242 
243  // white balance
244  if (this->WhiteBalanceMode == WB_MANUAL && this->WhiteBalanceRed == FLAG_WHITE_BALANCE)
245  {
246  LOG_ERROR("Failed to configure SpinnakerVideoSource: WhiteBalanceMode is set to \"MANUAL\", but no WhiteBalanceRed attribute is provided.");
247  retVal = PLUS_FAIL;
248  }
249  if (this->WhiteBalanceMode == WB_MANUAL && this->WhiteBalanceBlue == FLAG_WHITE_BALANCE)
250  {
251  LOG_ERROR("Failed to configure SpinnakerVideoSource: WhiteBalanceMode is set to \"MANUAL\", but no WhiteBalanceBlue attribute is provided.");
252  retVal = PLUS_FAIL;
253  }
254 
255  return retVal;
256 }
257 
258 //-----------------------------------------------------------------------------
259 PlusStatus vtkPlusSpinnakerVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
260 {
261  LOG_TRACE("vtkPlusSpinnakerVideoSource::ReadConfiguration(vtkXMLDataElement* rootConfigElement)");
262 
263  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
264 
265  // camera params
266  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, CameraNumber, deviceConfig);
267 
268  XML_READ_ENUM2_ATTRIBUTE_OPTIONAL(PixelEncoding, deviceConfig,
269  "RGB24", RGB24,
270  "MONO8", MONO8);
271 
272  // frame size
273  int requestedFrameSize[2] = { static_cast<int>(DEFAULT_FRAME_SIZE[0]), static_cast<int>(DEFAULT_FRAME_SIZE[1]) };
274  if (deviceConfig->GetVectorAttribute("FrameSize", 2, requestedFrameSize))
275  {
276  if (requestedFrameSize[0] < 0 || requestedFrameSize[1] < 0)
277  {
278  LOG_ERROR("Negative frame size defined in config file. Please define a positive frame size.");
279  return PLUS_FAIL;
280  }
281  this->FrameSize[0] = static_cast<unsigned int>(requestedFrameSize[0]);
282  this->FrameSize[1] = static_cast<unsigned int>(requestedFrameSize[1]);
283  this->FrameSize[2] = 1;
284  }
285 
286  // frame rate
287  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(int, FrameRate, deviceConfig);
288 
289  // exposure
290  XML_READ_ENUM3_ATTRIBUTE_OPTIONAL(ExposureMode, deviceConfig,
291  EXPOSURE_TIMED_STRING, EXPOSURE_TIMED,
292  EXPOSURE_AUTO_ONCE_STRING, EXPOSURE_AUTO_ONCE,
293  EXPOSURE_AUTO_CONTINUOUS_STRING, EXPOSURE_AUTO_CONTINUOUS);
294  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(float, ExposureMicroSec, deviceConfig);
295 
296  // gain
297  XML_READ_ENUM3_ATTRIBUTE_OPTIONAL(GainMode, deviceConfig,
298  GAIN_MANUAL_STRING, GAIN_MANUAL,
299  GAIN_AUTO_ONCE_STRING, GAIN_AUTO_ONCE,
300  GAIN_AUTO_CONTINUOUS_STRING, GAIN_AUTO_CONTINUOUS);
301  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(float, GainDB, deviceConfig);
302 
303  // white balance
304  XML_READ_ENUM3_ATTRIBUTE_OPTIONAL(WhiteBalanceMode, deviceConfig,
305  WB_MANUAL_STRING, WB_MANUAL,
306  WB_AUTO_ONCE_STRING, WB_AUTO_ONCE,
307  WB_AUTO_CONTINUOUS_STRING, WB_AUTO_CONTINUOUS);
308  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(float, WhiteBalanceRed, deviceConfig);
309  XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(float, WhiteBalanceBlue, deviceConfig);
310 
311  XML_FIND_NESTED_ELEMENT_REQUIRED(dataSourcesElement, deviceConfig, "DataSources");
312  for (int nestedElementIndex = 0; nestedElementIndex < dataSourcesElement->GetNumberOfNestedElements(); nestedElementIndex++)
313  {
314  vtkXMLDataElement* dataElement = dataSourcesElement->GetNestedElement(nestedElementIndex);
315  if (STRCASECMP(dataElement->GetName(), "DataSource") != 0)
316  {
317  // if this is not a data source element, skip it
318  continue;
319  }
320 
321  if (dataElement->GetAttribute("Type") != NULL && STRCASECMP(dataElement->GetAttribute("Type"), "Video") == 0)
322  {
323  // this is a video element
324  // get video ID
325  const char* toolId = dataElement->GetAttribute("Id");
326  if (toolId == NULL)
327  {
328  // tool doesn't have ID needed to generate transform
329  LOG_ERROR("Failed to initialize Spinnaker API VideoSource: Id is missing");
330  continue;
331  }
332  }
333  }
334 
335  // print configuration
336  std::ostringstream str;
337  this->PrintConfiguration(str, vtkIndent(0));
338  LOG_INFO(std::endl << "SpinnakerVideoSource configuration:" << std::endl << str.str());
339 
340  return this->CheckCameraParameterValidity();
341 }
342 
343 //-----------------------------------------------------------------------------
344 PlusStatus vtkPlusSpinnakerVideoSource::WriteConfiguration(vtkXMLDataElement* rootConfigElement)
345 {
346  LOG_TRACE("vtkPlusSpinnakerVideoSource::WriteConfiguration(vtkXMLDataElement* rootConfigElement)");
347 
348  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement);
349 
350  return PLUS_FAIL;
351 }
352 
353 //----------------------------------------------------------------------------
355 {
356  LOG_TRACE("vtkPlusSpinnakerVideoSource::InternalConnect()");
357 
358  // initialize system pointer
359  this->Internal->SystemPtr = Spinnaker::System::GetInstance();
360 
361  // Retrieve list of cameras from the system
362  this->Internal->CameraList = this->Internal->SystemPtr->GetCameras();
363 
364  // check CameraNumber parameter is valid
365  const int numConnectedCams = this->Internal->CameraList.GetSize();
366  if (numConnectedCams == 0)
367  {
368  this->Internal->CameraList.Clear();
369  LOG_ERROR("No Spinnaker compatible camera detected.");
370  return PLUS_FAIL;
371  }
372  else if (this->CameraNumber < 0 || this->CameraNumber > numConnectedCams)
373  {
374  LOG_ERROR("Invalid camera number (" << this->CameraNumber <<
375  "in config. Please verify your camera is connected and that your config contains the correct CameraNumber value.");
376  return PLUS_FAIL;
377  }
378 
379  // get camera pointer
380  this->Internal->CameraPtr = this->Internal->CameraList.GetByIndex(this->CameraNumber);
381 
382  // initialize camera
383  try
384  {
385  this->Internal->CameraPtr->Init();
386  }
387  catch (Spinnaker::Exception e)
388  {
389  LOG_ERROR("SpinnakerVideoSource: Error initializing camera. Exception text : " << e.what());
390  return PLUS_FAIL;
391  }
392 
393  // configure the camera with parameters specified in the config
394  try
395  {
396  // get camera nodemap pointer
397  Spinnaker::GenApi::INodeMap& nodeMap = this->Internal->CameraPtr->GetNodeMap();
398 
399  // map PIXEL_ENCODING to SpinnakerAPI pixel format
400  std::map<PIXEL_ENCODING, std::string> PixelEncodingToString;
401  PixelEncodingToString[RGB24] = "BayerRG8";
402  PixelEncodingToString[MONO8] = "Mono8";
403 
404  // set video encoding
405  Spinnaker::GenApi::CEnumerationPtr pfPtr = nodeMap.GetNode("PixelFormat");
406  if (Spinnaker::GenApi::IsAvailable(pfPtr) && Spinnaker::GenApi::IsWritable(pfPtr))
407  {
408  // Retrieve the desired entry node from the enumeration node
409  std::string spinnakerPixelFormat = PixelEncodingToString.find(this->PixelEncoding)->second;
410  Spinnaker::GenApi::CEnumEntryPtr pfEnumPtr = pfPtr->GetEntryByName(spinnakerPixelFormat.c_str());
411  if (Spinnaker::GenApi::IsAvailable(pfEnumPtr) && Spinnaker::GenApi::IsReadable(pfEnumPtr))
412  {
413  // Retrieve the integer value from the entry node
414  int64_t pixelFormat = pfEnumPtr->GetValue();
415  // Set integer as new value for enumeration node
416  pfPtr->SetIntValue(pixelFormat);
417  }
418  else
419  {
420  LOG_ERROR("Requested VideoFormat of \"" << this->PixelEncoding << "\" is not available...");
421  return PLUS_FAIL;
422  }
423  }
424  else
425  {
426  LOG_ERROR("Requested VideoFormat of \"" << this->PixelEncoding << "\" is not available...");
427  return PLUS_FAIL;
428  }
429 
430  // set frame width
431  Spinnaker::GenApi::CIntegerPtr WidthPtr = nodeMap.GetNode("Width");
432  if (Spinnaker::GenApi::IsAvailable(WidthPtr) && Spinnaker::GenApi::IsWritable(WidthPtr))
433  {
434  WidthPtr->SetValue(this->FrameSize[0]);
435  if (this->FrameSize[0] != WidthPtr->GetValue())
436  {
437  LOG_WARNING("Failed to set image width to requested value of " << this->FrameSize[0] <<
438  "(px). Setting width to default value of " << DEFAULT_FRAME_SIZE[0] << "(px).");
439  WidthPtr->SetValue(DEFAULT_FRAME_SIZE[0]);
440  this->FrameSize[0] = DEFAULT_FRAME_SIZE[0];
441  }
442  }
443  else
444  {
445  LOG_ERROR("Unable to set image width.");
446  return PLUS_FAIL;
447  }
448 
449  // set frame height
450  Spinnaker::GenApi::CIntegerPtr HeightPtr = nodeMap.GetNode("Height");
451  if (Spinnaker::GenApi::IsAvailable(HeightPtr) && Spinnaker::GenApi::IsWritable(HeightPtr))
452  {
453  HeightPtr->SetValue(this->FrameSize[1]);
454  if (this->FrameSize[1] != HeightPtr->GetValue())
455  {
456  LOG_WARNING("Failed to set image height to requested value of " << this->FrameSize[1] <<
457  "(px). Setting width to default value of " << DEFAULT_FRAME_SIZE[1] << "(px).");
458  WidthPtr->SetValue(DEFAULT_FRAME_SIZE[1]);
459  this->FrameSize[1] = DEFAULT_FRAME_SIZE[1];
460  }
461  }
462  else
463  {
464  LOG_ERROR("Unable to set image height.");
465  return PLUS_FAIL;
466  }
467 
468  // set acquisition mode to continuous
469  this->Internal->CameraPtr->AcquisitionMode.SetValue(Spinnaker::AcquisitionMode_Continuous);
470 
471  // enable manual frame rate control
472  Spinnaker::GenApi::CBooleanPtr FrameRateEnablePtr = nodeMap.GetNode("AcquisitionFrameRateEnable");
473  if (Spinnaker::GenApi::IsAvailable(FrameRateEnablePtr) && Spinnaker::GenApi::IsWritable(FrameRateEnablePtr))
474  {
475  FrameRateEnablePtr->SetValue(true);
476  }
477  else
478  {
479  LOG_ERROR("Unable to enable manual frame rate control.");
480  return PLUS_FAIL;
481  }
482 
483  // set frame rate
484  Spinnaker::GenApi::CFloatPtr FrameRatePtr = nodeMap.GetNode("AcquisitionFrameRate");
485  if (Spinnaker::GenApi::IsAvailable(FrameRatePtr) && Spinnaker::GenApi::IsWritable(FrameRatePtr))
486  {
487  FrameRatePtr->SetValue(this->FrameRate);
488  if (this->FrameRate != FrameRatePtr->GetValue())
489  {
490  LOG_WARNING("Failed to set frame rate to requested value of " << this->FrameRate <<
491  "(frames / sec). FrameRate set to default value of " << FrameRatePtr->GetValue() << " (frames / sec).");
492  }
493  }
494  else
495  {
496  LOG_ERROR("Unable to set frame rate.");
497  return PLUS_FAIL;
498  }
499 
500  // set exposure mode && exposure time (if manual exposure control enabled)
501  if (this->ExposureMode == EXPOSURE_TIMED)
502  {
503  this->Internal->CameraPtr->ExposureAuto.SetValue(Spinnaker::ExposureAuto_Off);
504  this->Internal->CameraPtr->ExposureMode.SetValue(Spinnaker::ExposureMode_Timed);
505  this->Internal->CameraPtr->ExposureTime.SetValue(this->ExposureMicroSec);
506  }
507  else if (this->ExposureMode == EXPOSURE_AUTO_ONCE)
508  {
509  this->Internal->CameraPtr->ExposureAuto.SetValue(Spinnaker::ExposureAuto_Once);
510  }
511  else if (this->ExposureMode == EXPOSURE_AUTO_CONTINUOUS)
512  {
513  this->Internal->CameraPtr->ExposureAuto.SetValue(Spinnaker::ExposureAuto_Continuous);
514  }
515 
516  // set gain mode && gain (if manual gain control enabled)
517  if (this->GainMode == GAIN_MANUAL)
518  {
519  this->Internal->CameraPtr->GainAuto.SetValue(Spinnaker::GainAuto_Off);
520  this->Internal->CameraPtr->Gain.SetValue(this->GainDB);
521  }
522  else if (this->GainMode == GAIN_AUTO_ONCE)
523  {
524  this->Internal->CameraPtr->GainAuto.SetValue(Spinnaker::GainAuto_Once);
525  }
526  else if (this->GainMode == GAIN_AUTO_CONTINUOUS)
527  {
528  this->Internal->CameraPtr->GainAuto.SetValue(Spinnaker::GainAuto_Continuous);
529  }
530 
531  // set white balance mode && wb (if manual wb control enabled)
532  if (this->WhiteBalanceMode == WB_MANUAL)
533  {
534  this->Internal->CameraPtr->BalanceWhiteAuto.SetValue(Spinnaker::BalanceWhiteAutoEnums::BalanceWhiteAuto_Off);
535  this->Internal->CameraPtr->BalanceRatioSelector.SetValue(Spinnaker::BalanceRatioSelectorEnums::BalanceRatioSelector_Blue);
536  Spinnaker::GenApi::CFloatPtr balanceRatioPtr = nodeMap.GetNode("BalanceRatio");
537  balanceRatioPtr->SetValue(this->WhiteBalanceBlue);
538  this->Internal->CameraPtr->BalanceRatioSelector.SetValue(Spinnaker::BalanceRatioSelectorEnums::BalanceRatioSelector_Red);
539  balanceRatioPtr->SetValue(this->WhiteBalanceRed);
540  }
541  else if (this->WhiteBalanceMode == WB_AUTO_ONCE)
542  {
543  this->Internal->CameraPtr->BalanceWhiteAuto.SetValue(Spinnaker::BalanceWhiteAutoEnums::BalanceWhiteAuto_Once);
544  }
545  else if (this->WhiteBalanceMode == WB_AUTO_CONTINUOUS)
546  {
547  this->Internal->CameraPtr->BalanceWhiteAuto.SetValue(Spinnaker::BalanceWhiteAutoEnums::BalanceWhiteAuto_Continuous);
548  }
549  }
550  catch (Spinnaker::Exception &e)
551  {
552  LOG_ERROR("SpinnakerVideoSource: Error configuring camera. Exception text: " << e.what());
553  return PLUS_FAIL;
554  }
555 
556  return PLUS_SUCCESS;
557 }
558 
559 //----------------------------------------------------------------------------
561 {
562  LOG_TRACE("vtkPlusSpinnakerVideoSource::InternalDisconnect()");
563 
564  try
565  {
566  this->Internal->CameraPtr->DeInit();
567  this->Internal->CameraPtr = NULL;
568  }
569  catch (Spinnaker::Exception &e)
570  {
571  LOG_ERROR("SpinnakerVideoSource: Failed to de-initialize camera. Exception text: " << e.what());
572  return PLUS_FAIL;
573  }
574 
575  try
576  {
577  this->Internal->CameraList.Clear();
578  }
579  catch (Spinnaker::Exception & e)
580  {
581  LOG_ERROR("SpinnakerVideoSource: Failed to clear camera list. Exception text: " << e.what());
582  return PLUS_FAIL;
583  }
584 
585  try
586  {
587  this->Internal->SystemPtr->ReleaseInstance();
588  }
589  catch (Spinnaker::Exception & e)
590  {
591  LOG_ERROR("SpinnakerVideoSource: Failed to release system pointer. Exception text: " << e.what());
592  return PLUS_FAIL;
593  }
594 
595  return PLUS_SUCCESS;
596 }
597 
598 //----------------------------------------------------------------------------
600 {
601  LOG_TRACE("vtkPlusSpinnakerVideoSource::InternalStartRecording()");
602 
603  // get camera nodemap pointer
604  try
605  {
606  Spinnaker::GenApi::INodeMap& nodeMapTLDevice = this->Internal->CameraPtr->GetTLDeviceNodeMap();
607  Spinnaker::GenApi::INodeMap& nodeMap = this->Internal->CameraPtr->GetNodeMap();
608 
609  // set acquisition mode to continuous
610 
611  Spinnaker::GenApi::CEnumerationPtr ptrAcquisitionMode = nodeMap.GetNode("AcquisitionMode");
612  if (!IsAvailable(ptrAcquisitionMode) || !IsWritable(ptrAcquisitionMode))
613  {
614  LOG_ERROR("Unable to set acquisition mode to continuous (node retrieval). Aborting...");
615  return PLUS_FAIL;
616  }
617  Spinnaker::GenApi::CEnumEntryPtr ptrAcquisitionModeContinuous = ptrAcquisitionMode->GetEntryByName("Continuous");
618  if (!IsAvailable(ptrAcquisitionModeContinuous) || !IsReadable(ptrAcquisitionModeContinuous))
619  {
620  LOG_ERROR("Unable to set acquisition mode to continuous (entry 'continuous' retrieval). Aborting...");
621  return PLUS_FAIL;
622  }
623  int64_t acquisitionModeContinuous = ptrAcquisitionModeContinuous->GetValue();
624  ptrAcquisitionMode->SetIntValue(acquisitionModeContinuous);
625  LOG_INFO("Acquisition mode set to continuous...");
626 
627  // begin acquiring images
628  this->Internal->CameraPtr->BeginAcquisition();
629 
630  std::string deviceSerialNumber("");
631  Spinnaker::GenApi::CStringPtr ptrStringSerial = nodeMapTLDevice.GetNode("DeviceSerialNumber");
632  if (IsAvailable(ptrStringSerial) && IsReadable(ptrStringSerial))
633  {
634  deviceSerialNumber = ptrStringSerial->GetValue();
635  LOG_INFO("Device serial number retrieved as " << deviceSerialNumber << ".");
636  }
637  }
638  catch (Spinnaker::Exception &e)
639  {
640  LOG_ERROR("SpinnakerVideoSource: Failed to start image acquisition. Exception text: " << e.what());
641  return PLUS_FAIL;
642  }
643 
644  return PLUS_SUCCESS;
645 }
646 
647 //----------------------------------------------------------------------------
649 {
650  LOG_TRACE("vtkPlusSpinnakerVideoSource::InternalStopRecording()");
651 
652  try
653  {
654  // End acquiring images
655  this->Internal->CameraPtr->EndAcquisition();
656  }
657  catch (Spinnaker::Exception &e)
658  {
659  LOG_ERROR("SpinnakerVideoSource: Failed to end recording. Exception text: " << e.what());
660  return PLUS_FAIL;
661  }
662 
663  return PLUS_SUCCESS;
664 }
665 
666 //----------------------------------------------------------------------------
668 {
669  // TODO: Implement some configuration checks here
670  LOG_TRACE("vtkPlusSpinnakerVideoSource::NotifyConfigured()");
671 
672  if (this->GetNumberOfVideoSources() < 1)
673  {
674  LOG_ERROR("Device must have at least one video source.");
675  return PLUS_FAIL;
676  }
677  if (this->OutputChannelCount() < 1)
678  {
679  LOG_ERROR("Device must have at least one output channel.");
680  return PLUS_FAIL;
681  }
682 
683  return PLUS_SUCCESS;
684 }
685 
686 //----------------------------------------------------------------------------
688 {
689  LOG_TRACE("vtkPlusSpinnakerVideoSource::InternalUpdate()");
690 
691  PlusStatus retVal = PLUS_FAIL;
692 
693  try
694  {
695  // Retrieve next received image and ensure image completion
696  Spinnaker::ImagePtr pResultImage = this->Internal->CameraPtr->GetNextImage();
697  if (pResultImage->IsIncomplete())
698  {
699  cout << "Image incomplete with image status " << pResultImage->GetImageStatus() << "..." << endl << endl;
700  }
701 
702  // Convert image from PointGrey to correct image type
703  Spinnaker::ImagePtr convertedImage;
704  if (this->PixelEncoding == RGB24)
705  {
706  convertedImage = pResultImage->Convert(Spinnaker::PixelFormat_RGB8, Spinnaker::HQ_LINEAR);
707  }
708  else if (this->PixelEncoding == MONO8)
709  {
710  convertedImage = pResultImage->Convert(Spinnaker::PixelFormat_Mono8, Spinnaker::HQ_LINEAR);
711  }
712  else
713  {
714  LOG_ERROR("Invalid image type selected.");
715  return PLUS_FAIL;
716  }
717 
718  // add image to PLUS buffer
719 
720  // get buffer
721  vtkPlusDataSource* videoSource(NULL);
722  if (this->GetFirstVideoSource(videoSource) != PLUS_SUCCESS)
723  {
724  LOG_WARNING("Failed to get video source in SpinnakerVideoSource");
725  return PLUS_FAIL;
726  }
727 
728  // initialize if buffer is empty
729  if (videoSource->GetNumberOfItems() == 0)
730  {
731  if (this->PixelEncoding == RGB24)
732  {
733  videoSource->SetImageType(US_IMG_RGB_COLOR);
734  videoSource->SetPixelType(VTK_UNSIGNED_CHAR);
735  videoSource->SetNumberOfScalarComponents(3);
736  videoSource->SetInputFrameSize(this->FrameSize);
737  }
738  else if (this->PixelEncoding == MONO8)
739  {
740  videoSource->SetImageType(US_IMG_BRIGHTNESS);
741  videoSource->SetPixelType(VTK_UNSIGNED_CHAR);
742  videoSource->SetNumberOfScalarComponents(1);
743  videoSource->SetInputFrameSize(this->FrameSize);
744  }
745  }
746 
747  // add frame to PLUS buffer
748  if (this->PixelEncoding == RGB24)
749  {
750  retVal = videoSource->AddItem(
751  convertedImage->GetData(),
752  US_IMG_ORIENT_MN,
753  this->FrameSize,
754  VTK_UNSIGNED_CHAR,
755  3,
756  US_IMG_RGB_COLOR,
757  0,
758  this->FrameNumber);
759  }
760  else if (this->PixelEncoding == MONO8)
761  {
762  retVal = videoSource->AddItem(
763  convertedImage->GetData(),
764  US_IMG_ORIENT_MN,
765  this->FrameSize,
766  VTK_UNSIGNED_CHAR,
767  1,
768  US_IMG_BRIGHTNESS,
769  0,
770  this->FrameNumber);
771  }
772 
773  // Release image
774  pResultImage->Release();
775  }
776  catch (Spinnaker::Exception &e)
777  {
778  LOG_ERROR("SpinnakerVideoSource: Failed in InternalUpdate(). Exception text: " << e.what());
779  return PLUS_FAIL;
780  }
781  this->FrameNumber++;
782  return retVal;
783 }
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
virtual int GetNumberOfVideoSources() const
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
igsioStatus PlusStatus
Definition: PlusCommon.h:40
PlusStatus SetInputFrameSize(unsigned int x, unsigned int y, unsigned int z)
virtual PlusStatus AddItem(vtkImageData *frame, US_IMAGE_ORIENTATION usImageOrientation, US_IMAGE_TYPE imageType, long frameNumber, double unfilteredTimestamp=UNDEFINED_TIMESTAMP, double filteredTimestamp=UNDEFINED_TIMESTAMP, const igsioFieldMapType *customFields=NULL)
PlusStatus SetGainMode(GAIN_MODE gainMode)
PlusStatus WriteConfiguration(vtkXMLDataElement *config)
bool RequireImageOrientationInConfiguration
PlusStatus SetImageType(US_IMAGE_TYPE imageType)
double AcquisitionRate
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
void PrintConfiguration(ostream &os, vtkIndent indent)
virtual void PrintSelf(ostream &os, vtkIndent indent)
PlusStatus GetFirstVideoSource(vtkPlusDataSource *&anImage)
PlusStatus SetExposureMicroSec(int exposureMicroSec)
PlusStatus SetExposureMode(EXPOSURE_MODE expMode)
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
double InternalUpdateRate
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
PlusStatus SetWhiteBalanceMode(WHITE_BALANCE_MODE wbMode)
vtkStandardNewMacro(vtkPlusSpinnakerVideoSource)
bool StartThreadForInternalUpdates
int32_t * deviceSerialNumber
Definition: phidget22.h:1317
PlusStatus SetNumberOfScalarComponents(unsigned int numberOfScalarComponents)
Interface class to Spinnaker API compatible Point Grey Cameras.
virtual int OutputChannelCount() const
virtual int GetNumberOfItems()
Interface to a 3D positioning tool, video source, or generalized data stream.