PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusClariusOEM.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2  Program: Plus
3  Copyright (c) Verdure Imaging Inc, Stockton, California. All rights reserved.
4  See License.txt for details.
5 
6  We would like to acknowledge Verdure Imaging Inc for generously open-sourcing
7  this support for the Clarius OEM interface to the PLUS & Slicer communities.
8 =========================================================Plus=header=end*/
9 
10 // Local includes
11 #include "PlusConfigure.h"
12 #include "vtkPlusChannel.h"
13 #include "vtkPlusClariusOEM.h"
14 #include "PixelCodec.h"
15 #include "vtkPlusDataSource.h"
17 
18 // Wifi & BLE helpers
19 #include "ClariusBLE.h"
20 #include "ClariusWifi.h"
21 
22 // Clarius Includes
23 #include <solum.h>
24 #include <solum_def.h>
25 
26 // VTK includes
27 #include <vtkImageData.h>
28 #include <vtkInformation.h>
29 #include <vtkMatrix4x4.h>
30 #include <vtkNew.h>
31 #include <vtkSmartPointer.h>
32 
33 // STL includes
34 #include <algorithm>
35 #include <cctype>
36 #include <chrono>
37 #include <future>
38 #include <map>
39 #include <sstream>
40 #include <string>
41 
42 // Clarius enable / disable values
43 #define CLARIUS_TRUE 1
44 #define CLARIUS_FALSE 0
45 #define CLARIUS_RUN 1
46 #define CLARIUS_STOP 0
47 
48 // Clarius connection state values
49 #define CLARIUS_STATE_NOT_INITIALIZED -1
50 #define CLARIUS_STATE_NOT_CONNECTED 0
51 #define CLARIUS_STATE_CONNECTED 1
52 
53 const std::string vtkPlusClariusOEM::OVERLAY_PORT_NAME = "Overlay";
54 
55 //-------------------------------------------------------------------------------------------------
56 // instance memory
57 vtkPlusClariusOEM* vtkPlusClariusOEM::instance;
58 
59 //-------------------------------------------------------------------------------------------------
60 // free helper functions
61 //-------------------------------------------------------------------------------------------------
62 std::string to_string(ClariusAvailability avail)
63 {
64  switch (avail)
65  {
67  return "Available";
69  return "Listen";
71  return "Not Available";
72  default:
73  return "Unknown ClariusAvailability";
74  }
75 }
76 
77 //-------------------------------------------------------------------------------------------------
79 {
80  switch (mode)
81  {
83  return "Access Point";
85  return "Local Area Network";
86  default:
87  return "Unknown ClariusWifiMode";
88  }
89 }
90 
91 //-------------------------------------------------------------------------------------------------
92 namespace
93 {
94  enum class BUTTON_MODE
95  {
96  DISABLED = CusButtonSetting::ButtonDisabled,
97  FREEZE = CusButtonSetting::ButtonFreeze,
98  USER = CusButtonSetting::ButtonUser
99  };
100 
101  static std::map<BUTTON_MODE, std::string> ButtonModeEnumToString{
102  {BUTTON_MODE::FREEZE, "FREEZE"},
103  {BUTTON_MODE::USER, "USER"},
104  {BUTTON_MODE::DISABLED, "DISABLED"}
105  };
106 
107  static std::map<int, std::string> ImagingModeStrings{
108  {CusMode::BMode, "BMode"},
109  {CusMode::Compounding, "Compounding"},
110  {CusMode::MMode, "MMode"},
111  {CusMode::ColorMode, "ColorMode"},
112  {CusMode::PowerMode, "PowerMode"},
113  {CusMode::PwMode, "PwMode"},
114  {CusMode::NeedleEnhance, "NeedleEnhance"},
115  {CusMode::Strain, "Strain"},
116  {CusMode::RfMode, "RfMode"},
117  };
118 
119  static const double CM_TO_MM = 10.0;
120  static const double MM_TO_CM = 0.1;
121  static const double UM_TO_MM = 0.001;
122 
123  static const int CLARIUS_SHORT_DELAY_MS = 10;
124  static const int CLARIUS_LONG_DELAY_MS = 1000;
125 
126  static const std::string BATTERY_FIELD_TAG = "ClariusBattery";
127  static const std::string TEMP_FIELD_TAG = "ClariusTemp";
128  static const std::string FRAME_RATE_FIELD_TAG = "ClariusFrameRate";
129  static const std::string BUTTON_FIELD_TAG = "ClariusButton";
130  static const std::string UP_BUTTON_TAG = "Up";
131  static const std::string DOWN_BUTTON_TAG = "Down";
132  static const std::string NO_BUTTON_TAG = "None";
133  static const std::string NUM_CLICKS_FIELD_TAG = "ClariusNumClicks";
134  static const int SEND_BUTTON_STATE_FOR_N_FRAMES = 20;
135 
136  static const FrameSizeType DEFAULT_FRAME_SIZE = { 512, 512, 1 };
137 
138  static const bool DEFAULT_ENABLE_AUTO_GAIN = false;
139 
140  static const bool DEFAULT_ENABLE_5V_RAIL = false;
141 
142  static const bool DEFAULT_FREEZE_ON_POOR_WIFI_SIGNAL = true;
143 
144  static const bool DEFAULT_KEEP_AWAKE_CHARGING = true;
145 
146  static const bool DEFAULT_POWER_BUTTONS_ENABLED = true;
147 
148  static const bool DEFAULT_SOUND_ENABLED = true;
149 
150  static const int DEFAULT_STATIONARY_TIMEOUT_SEC = 0;
151 
152  static const bool DEFAULT_WAKE_ON_SHAKE = false;
153 
154  static const bool DEFAULT_FORCE_LOG_SEND = false;
155 
156  static const bool DEFAULT_PENETRATION_MODE_ENABLED = false;
157 
158  static const int DEFAULT_CONTACT_DETECTION_TIMEOUT_SEC = 15;
159 
160  static const int DEFAULT_AUTO_FREEZE_TIMEOUT_SEC = 60;
161 
162  static const int DEFAULT_KEEP_AWAKE_TIMEOUT_SEC = 60;
163 
164  static const int DEFAULT_DEEP_SLEEP_TIMEOUT_HR = 0;
165 
166  static const BUTTON_MODE DEFAULT_UP_BUTTON_MODE = BUTTON_MODE::DISABLED;
167 
168  static const BUTTON_MODE DEFAULT_DOWN_BUTTON_MODE = BUTTON_MODE::FREEZE;
169 
170  static const double DEFAULT_DEPTH_MM = 100.0;
171 
172  static const double DEFAULT_GAIN_PERCENT = 80.0;
173 
174  static const double DEFAULT_DYNRANGE_PERCENT = 80.0;
175 
176  static const std::vector<double> DEFAULT_TGC_DB = { 5, 5, 5 };
177 
178  static const bool DEFAULT_ENABLE_AUTO_FOCUS = false;
179 
180  static std::map<int, std::string> ConnectEnumToString{
181  {CusConnection::ProbeConnected, "CONNECT_SUCCESS"},
182  {CusConnection::ProbeDisconnected, "CONNECT_DISCONNECT"},
183  {CusConnection::ConnectionFailed, "CONNECT_FAILED"},
184  {CusConnection::SwUpdateRequired, "CONNECT_SWUPDATE"},
185  {CusConnection::ConnectionError, "CONNECT_ERROR"},
186  };
187 
188  static const std::string TRANSD_PORT_NAME = "Transd";
189 }
190 
191 //-------------------------------------------------------------------------------------------------
192 // vtkInternal
193 //-------------------------------------------------------------------------------------------------
194 
195 class vtkPlusClariusOEM::vtkInternal
196 {
197 public:
198 
199  vtkInternal(vtkPlusClariusOEM* ext);
200 
201  virtual ~vtkInternal()
202  {
203  }
204 
205 protected:
206 
207  friend class vtkPlusClariusOEM;
208 
209  // Clarius callbacks
210  static void ListFn(const char* list, int sz);
211 
212  static void ConnectFn(CusConnection ret, int port, const char* status);
213 
214  static void CertFn(int daysValid);
215 
216  static void PowerDownFn(CusPowerDown ret, int tm);
217 
218  static void SwUpdateFn(CusSwUpdate ret);
219 
220  static void RawImageFn(const void* newImage, const CusRawImageInfo* nfo, int npos, const CusPosInfo* pos);
221 
222  static void ProcessedImageFn(const void* newImage, const CusProcessedImageInfo* nfo, int npos, const CusPosInfo* pos);
223 
224  static void SpectralImageFn(const void* newImage, const CusSpectralImageInfo* nfo);
225 
226  static void ImuDataFn(const CusPosInfo* pos);
227 
228  static void ImagingFn(CusImagingState ready, int imaging);
229 
230  static void ButtonFn(CusButton btn, int clicks);
231 
232  static void ProgressFn(int progress);
233 
234  static void ErrorFn(const char* msg);
235 
236  std::string ImagingModeToString(int mode)
237  {
238  if (ImagingModeStrings.find(mode) != ImagingModeStrings.end())
239  {
240  return ImagingModeStrings[mode];
241  }
242  else
243  {
244  return "Unknown Imaging Mode";
245  }
246  }
247 
248  // log user settings to console
249  void LogUserSettings();
250 
251  //
252  // members
253  //
254 
255  // user configurable params
256  std::string ProbeSerialNum;
257  std::string PathToCert;
258  FrameSizeType FrameSize;
259  std::string ProbeType;
260  std::string ImagingApplication;
261  bool EnableAutoGain;
262  bool Enable5v;
263  bool FreezeOnPoorWifiSignal;
264  bool KeepAwakeCharging;
265  bool PowerButtonsEnabled;
266  bool SoundEnabled;
267  int StationaryTimeoutSec;
268  bool WakeOnShake;
269  bool ForceLogSend;
270  bool EnablePenetrationMode;
271  int ContactDetectionTimeoutSec;
272  int AutoFreezeTimeoutSec;
273  int KeepAwakeTimeoutMin;
274  int DeepSleepTimeoutHr;
275  BUTTON_MODE UpButtonMode;
276  BUTTON_MODE DownButtonMode;
277  int ImagingMode;
278 
279  // parameters retrieved from the probe over BLE
280  std::string Ssid;
281  std::string Password;
282  std::string IpAddress;
283  int TcpPort;
284 
285  // parameters retrieved from the probe using the OEM API
286  std::promise<std::vector<std::string>> PromiseProbes;
287  std::promise<std::vector<std::string>> PromiseApplications;
288  std::promise<void> ConnectionBarrier;
289 
290  // pointers to DataSources
291  std::vector<vtkPlusDataSource*> BModeSources;
292  std::vector<vtkPlusDataSource*> OverlaySources;
293  vtkPlusDataSource* TransdSource;
294 
295  // button press info
296  std::string PressedButton;
297  int ButtonNumClicks;
298  int ButtonSentCount; // button state is sent for SEND_BUTTON_STATE_FOR_N_FRAMES
299  // frames after button is clicked to ensure user can process
300  // it in Slicer even if a frame is skipped
301 
302  CusStatusInfo CurrentStatus;
303 
304  bool EnableAutoFocus;
305 
306  enum class EXPECTED_LIST
307  {
308  PROBES,
309  APPLICATIONS,
310  UNKNOWN
311  } ExpectedList;
312 
313 private:
314  vtkPlusClariusOEM* External;
315 
316  // BLE interface
317  ClariusBLE BleHelper;
318 
319  // Wifi helper class
320  ClariusWifi WifiHelper;
321 };
322 
323 //-------------------------------------------------------------------------------------------------
324 vtkPlusClariusOEM::vtkInternal::vtkInternal(vtkPlusClariusOEM* ext)
325  : External(ext)
326  , ProbeSerialNum("")
327  , PathToCert("")
328  , FrameSize(DEFAULT_FRAME_SIZE)
329  , ProbeType("")
330  , ImagingApplication("")
331  , EnableAutoGain(DEFAULT_ENABLE_AUTO_GAIN)
332  , Enable5v(DEFAULT_ENABLE_5V_RAIL)
333  , FreezeOnPoorWifiSignal(DEFAULT_FREEZE_ON_POOR_WIFI_SIGNAL)
334  , KeepAwakeCharging(DEFAULT_KEEP_AWAKE_CHARGING)
335  , PowerButtonsEnabled(DEFAULT_POWER_BUTTONS_ENABLED)
336  , SoundEnabled(DEFAULT_SOUND_ENABLED)
337  , StationaryTimeoutSec(DEFAULT_STATIONARY_TIMEOUT_SEC)
338  , WakeOnShake(DEFAULT_WAKE_ON_SHAKE)
339  , ForceLogSend(DEFAULT_FORCE_LOG_SEND)
340  , EnablePenetrationMode(DEFAULT_PENETRATION_MODE_ENABLED)
341  , ContactDetectionTimeoutSec(DEFAULT_CONTACT_DETECTION_TIMEOUT_SEC)
342  , AutoFreezeTimeoutSec(DEFAULT_AUTO_FREEZE_TIMEOUT_SEC)
343  , KeepAwakeTimeoutMin(DEFAULT_KEEP_AWAKE_TIMEOUT_SEC)
344  , DeepSleepTimeoutHr(DEFAULT_DEEP_SLEEP_TIMEOUT_HR)
345  , UpButtonMode(DEFAULT_UP_BUTTON_MODE)
346  , DownButtonMode(DEFAULT_DOWN_BUTTON_MODE)
347  , ImagingMode(CusMode::BMode)
348  , IpAddress("")
349  , TcpPort(-1)
350  , TransdSource(nullptr)
351  , PressedButton(NO_BUTTON_TAG)
352  , ButtonNumClicks(0)
353  , ButtonSentCount(0)
354  , EnableAutoFocus(DEFAULT_ENABLE_AUTO_FOCUS)
355 {
356 }
357 
358 //-------------------------------------------------------------------------------------------------
359 void vtkPlusClariusOEM::vtkInternal::ListFn(const char* list, int sz)
360 {
362 
363  std::vector<std::string> vec;
364 
365  std::stringstream ss(list);
366  while (ss.good())
367  {
368  std::string substr;
369  getline(ss, substr, ',');
370  vec.push_back(substr);
371  }
372 
373  if (device->Internal->ExpectedList == EXPECTED_LIST::PROBES)
374  {
375  device->Internal->PromiseProbes.set_value(vec);
376  }
377  else if (device->Internal->ExpectedList == EXPECTED_LIST::APPLICATIONS)
378  {
379  device->Internal->PromiseApplications.set_value(vec);
380  }
381 }
382 
383 //-------------------------------------------------------------------------------------------------
384 void vtkPlusClariusOEM::vtkInternal::ConnectFn(CusConnection ret, int port, const char* status)
385 {
387 
388  switch (ret)
389  {
390  case ConnectionError:
391  LOG_ERROR("Connection status: error - " << status);
392  device->Disconnect();
393  break;
394  case ProbeConnected:
395  LOG_INFO("Connection status: probe connected - " << status);
396  break;
397  case ProbeDisconnected:
398  LOG_INFO("Connection status: probe disconnected - " << status);
399  device->Disconnect();
400  break;
401  case ConnectionFailed:
402  LOG_ERROR("Connection status: connection failed - " << status);
403  device->Disconnect();
404  break;
405  case SwUpdateRequired:
406  LOG_INFO("Connection status: software update required - " << status);
407  device->Disconnect();
408  break;
409  }
410 
411  if (ret == CusConnection::ProbeConnected)
412  {
413  // connection succeeded, set Internal->Connected variable to end busy wait in InternalConnect
414  device->Internal->ConnectionBarrier.set_value();
415  }
416 }
417 
418 //-------------------------------------------------------------------------------------------------
419 void vtkPlusClariusOEM::vtkInternal::CertFn(int daysValid)
420 {
421  if (daysValid <= 0)
422  {
423  LOG_ERROR("Invalid or expired certificate provided for Clarius OEM device");
424  }
425  else
426  {
427  LOG_INFO("Clarius certificate is valid for " << daysValid << " more days");
428  }
429 }
430 
431 //-------------------------------------------------------------------------------------------------
432 void vtkPlusClariusOEM::vtkInternal::PowerDownFn(CusPowerDown ret, int tm)
433 {
434  std::stringstream ss;
435  ss << "Clarius probe will power down ";
436 
437  if (tm == 0)
438  {
439  ss << "immediately as a result of ";
440  }
441  else
442  {
443  ss << "in " << tm << " seconds as a result of ";
444  }
445 
446  if (ret == CusPowerDown::Idle)
447  {
448  ss << "being idle for an extended period of time. ";
449  }
450  else if (ret == CusPowerDown::TooHot)
451  {
452  ss << "overheating. ";
453  }
454  else if (ret == CusPowerDown::LowBattery)
455  {
456  ss << "running out of battery. ";
457  }
458  else if (ret == CusPowerDown::ButtonOff)
459  {
460  ss << "user holding the shutdown button. ";
461  }
462  else
463  {
464  ss << "an unspecified reason. ";
465  }
466 
467  ss << "If Clarius probe has powered off please turn it back on and restart PLUS, if desired.";
468  LOG_ERROR(ss.str());
469 }
470 
471 //-------------------------------------------------------------------------------------------------
472 void vtkPlusClariusOEM::vtkInternal::SwUpdateFn(CusSwUpdate ret)
473 {
474  LOG_ERROR("Clarius SwUpdateFn callback was called, but this feature is not supported by PLUS. Please update using the Clarius iOS/Android App");
475 }
476 
477 //-------------------------------------------------------------------------------------------------
478 void vtkPlusClariusOEM::vtkInternal::RawImageFn(const void* newImage, const CusRawImageInfo* nfo, int npos, const CusPosInfo* pos)
479 {
480  LOG_ERROR("Support for Clarius OEM raw images has not been implemented. If you desire this feature please submit an issue to request it on the PlusToolkit/PlusLib GitHub repository");
481 }
482 
483 //-------------------------------------------------------------------------------------------------
484 void vtkPlusClariusOEM::vtkInternal::SpectralImageFn(const void* newImage, const CusSpectralImageInfo* nfo)
485 {
486  LOG_ERROR("Support for Clarius OEM spectral images has not been implemented. If you desire this feature please submit an issue to request it on the PlusToolkit/PlusLib GitHub repository");
487 }
488 
489 //-------------------------------------------------------------------------------------------------
490 void vtkPlusClariusOEM::vtkInternal::ImuDataFn(const CusPosInfo* pos)
491 {
492  LOG_ERROR("Support for Clarius OEM IMU data has not been implemented. If you desire this feature please submit an issue to request it on the PlusToolkit/PlusLib GitHub repository");
493 }
494 
495 //-------------------------------------------------------------------------------------------------
497 {
498  if (this->UpdateProbeStatus() != PLUS_SUCCESS)
499  {
500  LOG_ERROR("Failed to update probe status");
501  }
502  return PLUS_SUCCESS;
503 }
504 
505 //-------------------------------------------------------------------------------------------------
507 {
508  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
509  {
510  return PLUS_SUCCESS;
511  }
512 
513  if (solumStatusInfo(&this->Internal->CurrentStatus) != 0)
514  {
515  LOG_ERROR("Failed to retrieve solumStatusInfo");
516  return PLUS_FAIL;
517  }
518  return PLUS_SUCCESS;
519 }
520 
521 //-------------------------------------------------------------------------------------------------
522 void vtkPlusClariusOEM::vtkInternal::ProcessedImageFn(const void* oemImage, const CusProcessedImageInfo* nfo, int npos, const CusPosInfo* pos)
523 {
525  if (device == NULL)
526  {
527  LOG_ERROR("vtkPlusClariusOEM::vtkInternal::ProcessedImageFn called when Clarius instance was NULL!");
528  return;
529  }
530 
531  // check if still connected
532  if (!device->Connected)
533  {
534  return;
535  }
536 
537  if (oemImage == NULL)
538  {
539  LOG_ERROR("NULL frame received by the Clarius OEM device");
540  return;
541  }
542 
543  // check if source is valid, if not - nothing to do
544  if (!nfo->overlay && device->Internal->BModeSources.size() == 0)
545  {
546  return;
547  }
548  else if (nfo->overlay && device->Internal->OverlaySources.size() == 0)
549  {
550  return;
551  }
552 
553  // setup source
554  const double unfilteredTimestamp = vtkIGSIOAccurateTimer::GetSystemTime();
555 
556  vtkSmartPointer<vtkImageData> vtkImage = vtkSmartPointer<vtkImageData>::New();
557  vtkNew<vtkInformation> info;
558  vtkImage->SetExtent(0, nfo->width - 1, 0, nfo->height - 1, 0, 1);
559  vtkImage->SetOrigin(0.0, 0.0, 0.0);
560  vtkImage->SetSpacing(1.0, 1.0, 1.0);
561 
562  std::vector<vtkPlusDataSource*> dataSources = device->Internal->BModeSources;
563  if (nfo->overlay)
564  {
565  dataSources = device->Internal->OverlaySources;
566  }
567 
568  for (auto dataSource : dataSources)
569  {
570  if (dataSource->GetImageType() == US_IMG_RGB_COLOR)
571  {
572  vtkImage->AllocateScalars(VTK_UNSIGNED_CHAR, 3);
574  nfo->width,
575  nfo->height,
576  (unsigned char*)oemImage,
577  (unsigned char*)vtkImage->GetScalarPointer()
578  );
579  }
580  else
581  {
582  // convert Clarius RGBA to grayscale
583  // format is:
584  // B = ultrasound value
585  // G = ultrasound value
586  // R = ultrasound value
587  // A = 255
588  vtkImage->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
591  nfo->width,
592  nfo->height,
593  (unsigned char*)oemImage,
594  (unsigned char*)vtkImage->GetScalarPointer()
595  );
596  }
597  }
598 
599 
600  // custom fields (battery & button clicks)
601  igsioFieldMapType customFields;
602  customFields[BATTERY_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
603  customFields[BATTERY_FIELD_TAG].second = std::to_string(device->Internal->CurrentStatus.battery);
604  customFields[TEMP_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
605  customFields[TEMP_FIELD_TAG].second = std::to_string(device->Internal->CurrentStatus.temperature);
606  customFields[FRAME_RATE_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
607  customFields[FRAME_RATE_FIELD_TAG].second = std::to_string(device->Internal->CurrentStatus.frameRate);
608 
609  customFields[BUTTON_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
610  customFields[BUTTON_FIELD_TAG].second = device->Internal->PressedButton;
611  customFields[NUM_CLICKS_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
612  customFields[NUM_CLICKS_FIELD_TAG].second = std::to_string(device->Internal->ButtonNumClicks);
613 
614  // reset button state if sent SEND_BUTTON_STATE_FOR_N_FRAMES times
615  if (device->Internal->ButtonSentCount > 0)
616  {
617  --device->Internal->ButtonSentCount;
618  }
619  else
620  {
621  device->Internal->PressedButton = NO_BUTTON_TAG;
622  device->Internal->ButtonNumClicks = 0;
623  }
624 
625  // update the image
626  for (auto dataSource : dataSources)
627  {
628  dataSource->AddItem(
629  vtkImage->GetScalarPointer(),
630  dataSource->GetInputImageOrientation(),
631  dataSource->GetInputFrameSize(),
632  VTK_UNSIGNED_CHAR,
633  dataSource->GetImageType() == US_IMG_RGB_COLOR ? 3 : 1,
634  dataSource->GetImageType(),
635  0,
636  device->FrameNumber,
637  unfilteredTimestamp,
638  unfilteredTimestamp,
639  &customFields
640  );
641  }
642 
643  // if transd source is valid, update the ImageToTransd (or similarly named)
644  // transform which localizes the image to the center of the transducer
645  // and correctly sizes the image
646  if (device->Internal->TransdSource)
647  {
648  int i = nfo->width / 2;
649  double transd[2] = { static_cast<double>(i), 0.0 };
650  for (int j = 0; j < nfo->height; j++)
651  {
652  unsigned char imval = vtkImage->GetScalarComponentAsDouble(i, j, 0, 0);
653  if (imval != 0)
654  {
655  transd[0] = i;
656  transd[1] = j;
657  break;
658  }
659  }
660 
661  vtkSmartPointer<vtkMatrix4x4> tsfm = vtkSmartPointer<vtkMatrix4x4>::New();
662  tsfm->Identity();
663  double mmPerPixel = nfo->micronsPerPixel * UM_TO_MM;
664  tsfm->SetElement(0, 0, mmPerPixel);
665  tsfm->SetElement(1, 1, mmPerPixel);
666  tsfm->SetElement(2, 2, mmPerPixel);
667  tsfm->SetElement(0, 3, -transd[0] * mmPerPixel);
668  tsfm->SetElement(1, 3, -transd[1] * mmPerPixel);
669  device->Internal->TransdSource->AddTimeStampedItem(tsfm, TOOL_OK, device->FrameNumber, unfilteredTimestamp, unfilteredTimestamp, &customFields);
670  }
671 
672  device->FrameNumber++;
673 }
674 
675 //-------------------------------------------------------------------------------------------------
676 void vtkPlusClariusOEM::vtkInternal::ImagingFn(CusImagingState ready, int imaging)
677 {
678  if (ready == CusImagingState::ImagingNotReady)
679  {
680  LOG_WARNING("Clarius imaging is not ready yet...");
681  }
682  else if (ready == CusImagingState::ImagingReady)
683  {
684  LOG_INFO("Clarius imaging is " << (imaging ? "running" : "stopped"));
685  }
686  else if (ready == CusImagingState::CertExpired)
687  {
688  LOG_ERROR("Clarius certificate needs to be updated prior to imaging");
689  }
690  else if (ready == CusImagingState::PoorWifi)
691  {
692  LOG_WARNING("Clarius imaging stopped as a result of a poor Wi-Fi connection");
693  }
694  else if (ready == CusImagingState::NoContact)
695  {
696  LOG_INFO("Clarius imaging stopped as a result of no patient contact for specified timeout duration");
697  }
698  else if (ready == CusImagingState::ChargingChanged)
699  {
700  LOG_WARNING("Clarius imaging " << (imaging ? "started" : "stopped") << " due to a change in charging status");
701  }
702  else if (ready == CusImagingState::LowBandwidth)
703  {
704  LOG_INFO("Clarius low bandwidth was detected, imaging parameters were adjusted");
705  }
706  else if (ready == CusImagingState::MotionSensor)
707  {
708  LOG_INFO("Clarius imaging " << (imaging ? "started" : "stopped") << " due to change in motion sensor");
709  }
710  else
711  {
712  LOG_ERROR("Clarius ImagingFn called with unknown 'ready' state");
713  }
714 }
715 
716 //-------------------------------------------------------------------------------------------------
720 void vtkPlusClariusOEM::vtkInternal::ButtonFn(CusButton btn, int clicks)
721 {
723  if (device == NULL)
724  {
725  LOG_ERROR("vtkPlusClariusOEM::vtkInternal::ButtonFn called when Clarius instance was NULL!");
726  return;
727  }
728 
729  // check if still connected
730  if (!device->Connected)
731  {
732  LOG_ERROR("ClariusOEM device unexpectedly disconnected from Clarius Device. IpAddress = " << device->Internal->IpAddress
733  << " Port = " << device->Internal->TcpPort);
734  return;
735  }
736 
737  // set button state
738  device->Internal->ButtonNumClicks = clicks;
739  if (btn == CusButton::ButtonDown)
740  {
741  device->Internal->PressedButton = DOWN_BUTTON_TAG;
742  }
743  else if (btn == CusButton::ButtonUp)
744  {
745  device->Internal->PressedButton = UP_BUTTON_TAG;
746  }
747  else
748  {
749  LOG_WARNING("Unexpected Clarius button value of " << btn << " received in vtkPlusClariusOEM::vtkInternal::ButtonFn");
750  }
751 
752  // reset number of frames to send new button state for
753  device->Internal->ButtonSentCount = SEND_BUTTON_STATE_FOR_N_FRAMES;
754 }
755 
756 //-------------------------------------------------------------------------------------------------
759 void vtkPlusClariusOEM::vtkInternal::ProgressFn(int progress)
760 {
761  LOG_INFO("Downloading: " << progress << "%");
762 }
763 
764 //-------------------------------------------------------------------------------------------------
768 void vtkPlusClariusOEM::vtkInternal::ErrorFn(const char* err)
769 {
770  LOG_ERROR("A Clarius OEM error occurred. Error text was: " << err);
771 }
772 
773 //-------------------------------------------------------------------------------------------------
774 void vtkPlusClariusOEM::vtkInternal::LogUserSettings()
775 {
776  std::stringstream ss;
777  ss << "ProbeSerialNum: " << this->ProbeSerialNum << std::endl;
778  ss << "PathToCert: " << this->PathToCert << std::endl;
779  ss << "ProbeType: " << this->ProbeType << std::endl;
780  ss << "ImagingApplication: " << this->ImagingApplication << std::endl;
781  ss << "FrameSize: [" << this->FrameSize[0] << ", " << this->FrameSize[1] << ", " << this->FrameSize[2] << "]" << std::endl;
782  ss << "EnableAutoGain: " << (this->EnableAutoGain ? "TRUE" : "FALSE") << std::endl;
783  ss << "EnableAutoFocus: " << (this->EnableAutoFocus ? "TRUE" : "FALSE") << std::endl;
784  ss << "Enable5v: " << (this->Enable5v ? "TRUE" : "FALSE") << std::endl;
785  ss << "EnablePenetrationMode: " << (this->EnablePenetrationMode ? "TRUE" : "FALSE") << std::endl;
786  ss << "FreezeOnPoorWifiSignal: " << (this->FreezeOnPoorWifiSignal ? "TRUE" : "FALSE") << std::endl;
787  ss << "KeepAwakeCharging: " << (this->KeepAwakeCharging ? "TRUE" : "FALSE") << std::endl;
788  ss << "PowerButtonsEnabled: " << (this->PowerButtonsEnabled ? "TRUE" : "FALSE") << std::endl;
789  ss << "SoundEnabled: " << (this->SoundEnabled ? "TRUE" : "FALSE") << std::endl;
790  ss << "StationaryTimeoutSec: " << this->StationaryTimeoutSec << std::endl;
791  ss << "WakeOnShake: " << (this->WakeOnShake ? "TRUE" : "FALSE") << std::endl;
792  ss << "ForceLogSend: " << (this->ForceLogSend ? "TRUE" : "FALSE") << std::endl;
793  ss << "EnablePenetrationMode: " << (this->EnablePenetrationMode ? "TRUE" : "FALSE") << std::endl;
794  ss << "ContactDetectionTimeoutSec: " << this->ContactDetectionTimeoutSec << std::endl;
795  ss << "AutoFreezeTimeoutSec: " << this->AutoFreezeTimeoutSec << std::endl;
796  ss << "KeepAwakeTimeoutMin: " << this->KeepAwakeTimeoutMin << std::endl;
797  ss << "UpButtonMode: " << ButtonModeEnumToString[this->UpButtonMode] << std::endl;
798  ss << "DownButtonMode: " << ButtonModeEnumToString[this->DownButtonMode] << std::endl;
799  ss << "ImagingMode: " << this->ImagingModeToString(this->ImagingMode) << std::endl;
800 
801  LOG_INFO(std::endl << "User settings:" << std::endl << ss.str());
802 }
803 
804 //-------------------------------------------------------------------------------------------------
805 // vtkPlusClariusOEM definitions
806 //-------------------------------------------------------------------------------------------------
808 {
809  if (instance == NULL)
810  {
811  instance = new vtkPlusClariusOEM();
812  }
813  return instance;
814 }
815 
816 //-------------------------------------------------------------------------------------------------
818  : Internal(new vtkInternal(this))
819 {
820  this->StartThreadForInternalUpdates = true;
822 
823  this->ImagingParameters->SetDepthMm(DEFAULT_DEPTH_MM);
824  this->ImagingParameters->SetGainPercent(DEFAULT_GAIN_PERCENT);
825  this->ImagingParameters->SetDynRangeDb(DEFAULT_DYNRANGE_PERCENT);
826  this->ImagingParameters->SetTimeGainCompensation(DEFAULT_TGC_DB);
827 
828  // set dummy values to avoid endless error messages when using SlicerOpenIGTLink US Remote Control
829  this->ImagingParameters->SetPowerDb(-1);
832 
833  instance = this;
834 }
835 
836 //-------------------------------------------------------------------------------------------------
838 {
839  // ensure resources released
840  this->InternalDisconnect();
841 
842  if (this->Internal)
843  {
844  delete this->Internal;
845  this->Internal = nullptr;
846  }
847 
848  this->instance = NULL;
849 }
850 
851 //-------------------------------------------------------------------------------------------------
853 {
854  if (instance != NULL)
855  {
856  return instance;
857  }
858  else
859  {
860  // Instance is null, creating new instance
861  instance = new vtkPlusClariusOEM();
862  return instance;
863  }
864 }
865 
866 //-------------------------------------------------------------------------------------------------
867 void vtkPlusClariusOEM::PrintSelf(ostream& os, vtkIndent indent)
868 {
869  LOG_TRACE("vtkPlusClariusOEM::PrintSelf");
870 
871  this->Superclass::PrintSelf(os, indent);
872  os << indent << "ProbeSerialNum: " << this->Internal->ProbeSerialNum << std::endl;
873  os << indent << "PathToCert: " << this->Internal->PathToCert << std::endl;
874  os << indent << "ProbeType: " << this->Internal->ProbeType << std::endl;
875  os << indent << "ImagingApplication: " << this->Internal->ImagingApplication << std::endl;
876  os << indent << "FrameSize: [" << this->Internal->FrameSize[0] << ", " << this->Internal->FrameSize[1] << ", " << this->Internal->FrameSize[2] << "]" << std::endl;
877  os << indent << "EnableAutoGain: " << (this->Internal->EnableAutoGain ? "TRUE" : "FALSE") << std::endl;
878  os << indent << "Enable5v: " << (this->Internal->Enable5v ? "TRUE" : "FALSE") << std::endl;
879  os << indent << "FreezeOnPoorWifiSignal: " << (this->Internal->FreezeOnPoorWifiSignal ? "TRUE" : "FALSE") << std::endl;
880  os << indent << "KeepAwakeCharging: " << (this->Internal->KeepAwakeCharging ? "TRUE" : "FALSE") << std::endl;
881  os << indent << "PowerButtonsEnabled: " << (this->Internal->PowerButtonsEnabled ? "TRUE" : "FALSE") << std::endl;
882  os << indent << "SoundEnabled: " << (this->Internal->SoundEnabled ? "TRUE" : "FALSE") << std::endl;
883  os << indent << "StationaryTimeoutSec: " << this->Internal->StationaryTimeoutSec << std::endl;
884  os << indent << "WakeOnShake: " << (this->Internal->WakeOnShake ? "TRUE" : "FALSE") << std::endl;
885  os << indent << "ForceLogSend: " << (this->Internal->ForceLogSend ? "TRUE" : "FALSE") << std::endl;
886  os << indent << "EnablePenetrationMode: " << (this->Internal->EnablePenetrationMode ? "TRUE" : "FALSE") << std::endl;
887  os << indent << "ContactDetectionTimeoutSec: " << this->Internal->ContactDetectionTimeoutSec << std::endl;
888  os << indent << "AutoFreezeTimeoutSec: " << this->Internal->AutoFreezeTimeoutSec << std::endl;
889  os << indent << "KeepAwakeTimeoutMin: " << this->Internal->KeepAwakeTimeoutMin << std::endl;
890  os << indent << "UpButtonMode: " << ButtonModeEnumToString[this->Internal->UpButtonMode] << std::endl;
891  os << indent << "DownButtonMode: " << ButtonModeEnumToString[this->Internal->DownButtonMode] << std::endl;
892  os << indent << "ImagingMode: " << this->Internal->ImagingModeToString(this->Internal->ImagingMode) << std::endl;
893 }
894 
895 //-------------------------------------------------------------------------------------------------
896 PlusStatus vtkPlusClariusOEM::ReadConfiguration(vtkXMLDataElement* rootConfigElement)
897 {
898  LOG_TRACE("vtkPlusClariusOEM::ReadConfiguration");
899 
900  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement);
901 
902  // probe serial number
903  XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
904  ProbeSerialNum, this->Internal->ProbeSerialNum, deviceConfig);
905 
906  // path to Clarius certificate
907  XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
908  PathToCert, this->Internal->PathToCert, deviceConfig);
909 
910  // probe type
911  XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
912  ProbeType, this->Internal->ProbeType, deviceConfig);
913  // force probe type string to be entirely uppercase
914  std::transform(
915  this->Internal->ProbeType.begin(),
916  this->Internal->ProbeType.end(),
917  this->Internal->ProbeType.begin(),
918  [](unsigned char c) { return std::toupper(c); }
919  );
920 
921  // imaging application (msk, abdomen, etc.)
922  XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
923  ImagingApplication, this->Internal->ImagingApplication, deviceConfig);
924  // force imaging application string to be entirely lowercase
925  std::transform(
926  this->Internal->ImagingApplication.begin(),
927  this->Internal->ImagingApplication.end(),
928  this->Internal->ImagingApplication.begin(),
929  [](unsigned char c) { return std::tolower(c); }
930  );
931 
932  // frame size
933  int rfs[2] = { static_cast<int>(DEFAULT_FRAME_SIZE[0]), static_cast<int>(DEFAULT_FRAME_SIZE[1]) };
934  if (deviceConfig->GetVectorAttribute("FrameSize", 2, rfs))
935  {
936  if (rfs[0] < 0 || rfs[1] < 0)
937  {
938  LOG_ERROR("Negative frame size defined in config file. Please define a positive frame size.");
939  return PLUS_FAIL;
940  }
941  FrameSizeType fs = { static_cast<unsigned int>(rfs[0]), static_cast<unsigned int>(rfs[1]), 1 };
942  this->Internal->FrameSize = fs;
943  }
944 
945  // enable auto gain
946  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnableAutoGain,
947  this->Internal->EnableAutoGain, deviceConfig);
948 
949  // enable 5v rail
950  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(Enable5v,
951  this->Internal->Enable5v, deviceConfig);
952 
953  // freeze on poor wifi signal
954  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(FreezeOnPoorWifiSignal,
955  this->Internal->FreezeOnPoorWifiSignal, deviceConfig);
956 
957  // keep awake when charging
958  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(KeepAwakeCharging,
959  this->Internal->KeepAwakeCharging, deviceConfig);
960 
961  // power buttons enabled
962  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(PowerButtonsEnabled,
963  this->Internal->PowerButtonsEnabled, deviceConfig);
964 
965  // sound enabled
966  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(SoundEnabled,
967  this->Internal->SoundEnabled, deviceConfig);
968 
969  // freeze when probe is stationary for a specified duration
970  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, StationaryTimeoutSec,
971  this->Internal->StationaryTimeoutSec, deviceConfig);
972 
973  // wake on shake
974  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(WakeOnShake,
975  this->Internal->WakeOnShake, deviceConfig);
976 
977  // force log send
978  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(ForceLogSend,
979  this->Internal->ForceLogSend, deviceConfig);
980 
981  // penetration mode enabled
982  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnablePenetrationMode,
983  this->Internal->EnablePenetrationMode, deviceConfig);
984 
985  // contact detection timeout (seconds)
986  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, ContactDetectionTimeoutSec,
987  this->Internal->ContactDetectionTimeoutSec, deviceConfig);
988 
989  // auto freeze timeout (seconds)
990  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, AutoFreezeTimeoutSec,
991  this->Internal->AutoFreezeTimeoutSec, deviceConfig);
992 
993  // keep awake timeout (seconds)
994  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, KeepAwakeTimeoutMin,
995  this->Internal->KeepAwakeTimeoutMin, deviceConfig);
996 
997  // deep sleep timeout (hours)
998  XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(int, DeepSleepTimeoutHr,
999  this->Internal->DeepSleepTimeoutHr, deviceConfig);
1000 
1001  // up button mode
1002  XML_READ_ENUM3_ATTRIBUTE_NONMEMBER_OPTIONAL(UpButtonMode,
1003  this->Internal->UpButtonMode, deviceConfig,
1004  "FREEZE", BUTTON_MODE::FREEZE,
1005  "USER", BUTTON_MODE::USER,
1006  "DISABLED", BUTTON_MODE::DISABLED
1007  );
1008 
1009  // down button mode
1010  XML_READ_ENUM3_ATTRIBUTE_NONMEMBER_OPTIONAL(DownButtonMode,
1011  this->Internal->DownButtonMode, deviceConfig,
1012  "FREEZE", BUTTON_MODE::FREEZE,
1013  "USER", BUTTON_MODE::USER,
1014  "DISABLED", BUTTON_MODE::DISABLED
1015  );
1016 
1017  // enable auto focus
1018  XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnableAutoFocus,
1019  this->Internal->EnableAutoFocus, deviceConfig);
1020 
1021  // imaging mode
1022  XML_READ_ENUM_ATTRIBUTE_NONMEMBER_OPTIONAL(ImagingMode, this->Internal->ImagingMode, deviceConfig, this->Internal->ImagingModeToString, 0, ImagingModeStrings.size());
1023 
1024  // read imaging parameters
1025  this->ImagingParameters->ReadConfiguration(deviceConfig);
1026 
1027  // validate data sources
1028  XML_FIND_NESTED_ELEMENT_REQUIRED(dataSourcesElement, deviceConfig, "DataSources");
1029  int numSources = dataSourcesElement->GetNumberOfNestedElements();
1030  for (int i = 0; i < numSources; ++i)
1031  {
1032  vtkXMLDataElement* element = dataSourcesElement->GetNestedElement(i);
1033  if (!igsioCommon::IsEqualInsensitive(element->GetName(), "DataSource"))
1034  {
1035  // if this is not a data source element, skip it
1036  continue;
1037  }
1038 
1039  // if video source, verify correct orientation (MF) to place the (0, 0) voxel
1040  // of the image in the marked corner adjacent to the probe
1041  const char* type = element->GetAttribute("Type");
1042  if (type && igsioCommon::IsEqualInsensitive(type, "Video"))
1043  {
1044  const char* orientation = element->GetAttribute("PortUsImageOrientation");
1045  if (orientation && !igsioCommon::IsEqualInsensitive(orientation, "UF"))
1046  {
1047  LOG_WARNING("Clarius image source has unexpected value '" << orientation << "' for PortUsImageOrientation. Please confirm your image orientation, expected value for most Clarius probes is 'UF'.");
1048  }
1049  }
1050 
1051  // if tool, verify port name is a valid option for Clarius OEM
1052  if (type && igsioCommon::IsEqualInsensitive(type, "Tool"))
1053  {
1054  const char* toolId = element->GetAttribute("Id");
1055  if (toolId == NULL)
1056  {
1057  LOG_ERROR("Failed to initialize Clarius OEM transform: DataSource Id is missing");
1058  return PLUS_FAIL;
1059  }
1060 
1061  const char* portName = element->GetAttribute("PortName");
1062  if (portName && !igsioCommon::IsEqualInsensitive(portName, TRANSD_PORT_NAME))
1063  {
1064  LOG_ERROR("Clarius OEM device only supports Tool items with PortName=\""
1065  << TRANSD_PORT_NAME << "\"");
1066  return PLUS_FAIL;
1067  }
1068 
1069  // set vtkInternal pointer to transd transform source
1070  igsioTransformName transdTransformName(toolId, this->GetToolReferenceFrameName());
1071  std::string transdSourceId = transdTransformName.GetTransformName();
1072  if (this->GetTool(transdSourceId, this->Internal->TransdSource) != PLUS_SUCCESS || this->Internal->TransdSource == NULL)
1073  {
1074  LOG_ERROR("Failed to get ClariusOEM tool: " << transdSourceId);
1075  return PLUS_FAIL;
1076  }
1077  }
1078  }
1079 
1080  // set vtkInternal pointer to b-mode data source
1081  this->GetVideoSourcesByPortName(vtkPlusDevice::BMODE_PORT_NAME, this->Internal->BModeSources);
1082  this->GetVideoSourcesByPortName(vtkPlusClariusOEM::OVERLAY_PORT_NAME, this->Internal->OverlaySources);
1083 
1084  return PLUS_SUCCESS;
1085 }
1086 
1087 //-------------------------------------------------------------------------------------------------
1088 PlusStatus vtkPlusClariusOEM::WriteConfiguration(vtkXMLDataElement* rootConfigElement)
1089 {
1090  LOG_TRACE("vtkPlusClariusOEM::WriteConfiguration");
1091 
1092  XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement);
1093 
1094  this->ImagingParameters->WriteConfiguration(deviceConfig);
1095 
1096  return PLUS_SUCCESS;
1097 }
1098 
1099 //-------------------------------------------------------------------------------------------------
1101 {
1102  LOG_TRACE("vtkPlusClariusOEM::NotifyConfigured");
1103 
1105  if (device->OutputChannels.size() > 1)
1106  {
1107  LOG_WARNING("vtkPlusClariusOEM is expecting one output channel and there are " <<
1108  this->OutputChannels.size() << " channels. First output channel will be used.");
1109  }
1110 
1111  if (device->OutputChannels.empty())
1112  {
1113  LOG_ERROR("No output channels defined for vtkPlusClariusOEM. Cannot proceed.");
1114  this->CorrectlyConfigured = false;
1115  return PLUS_FAIL;
1116  }
1117 
1118  std::vector<vtkPlusDataSource*> sources;
1119  sources = device->GetVideoSources();
1120  if (sources.size() > 1)
1121  {
1122  LOG_WARNING("More than one output video source found. First will be used");
1123  }
1124  if (sources.size() == 0)
1125  {
1126  LOG_ERROR("Video source required in configuration. Cannot proceed.");
1127  return PLUS_FAIL;
1128  }
1129 
1130  // Check if output channel has data source
1131  vtkPlusDataSource* aSource(NULL);
1132  if (device->OutputChannels[0]->GetVideoSource(aSource) != PLUS_SUCCESS)
1133  {
1134  LOG_ERROR("Unable to retrieve the video source in the vtkPlusClariusOEM device.");
1135  return PLUS_FAIL;
1136  }
1137 
1138  return PLUS_SUCCESS;
1139 }
1140 
1141 //-------------------------------------------------------------------------------------------------
1143 {
1144  LOG_TRACE("vtkPlusClariusOEM: Probe");
1145  LOG_ERROR("vtkPlusClariusOEM::Probe() is not implemented");
1146 
1147  return PLUS_SUCCESS;
1148 };
1149 
1150 //-------------------------------------------------------------------------------------------------
1152 {
1153  LOG_TRACE("vtkPlusClariusOEM::GetSdkVersion");
1154  return "SDK version not available";
1155 }
1156 
1157 //-------------------------------------------------------------------------------------------------
1159 {
1160  LOG_TRACE("vtkPlusClariusOEM::InitializeBLE");
1161 
1162  // find probe by serial number
1163  if (!this->Internal->BleHelper.FindBySerial(this->Internal->ProbeSerialNum))
1164  {
1165  LOG_ERROR("Failed to find BLE connection for Clarius probe with serial number "
1166  << this->Internal->ProbeSerialNum << ". Please make sure the probe is charged"
1167  ", paired, and in range for BLE.");
1168 
1169  std::vector<std::string> probes = this->Internal->BleHelper.RetrieveFoundProbeIds();
1170 
1171  if (!probes.size())
1172  {
1173  // failed to connect to probe by serial number, no active probes found in BLE range
1174  LOG_ERROR("No active Clarius probes found within BLE range");
1175  return PLUS_FAIL;
1176  }
1177 
1178  // print list of nearby active probes
1179  std::stringstream ss;
1180  ss << "Clarius probes configured with Windows Bluetooth are:\n";
1181  for (const std::string& probe : probes)
1182  {
1183  ss << "\t" << probe << "\n";
1184  }
1185  LOG_ERROR(ss.str());
1186  return PLUS_FAIL;
1187  }
1188 
1189  // attempt to connect to probe ble network
1190  LOG_INFO("Connecting to BLE network of Clarius probe with SN: " << this->Internal->ProbeSerialNum);
1191  if (this->Internal->BleHelper.Connect() != PLUS_SUCCESS)
1192  {
1193  LOG_ERROR("Failed to connect to Clarius probe. Last error was: "
1194  << this->Internal->BleHelper.GetLastError());
1195  return PLUS_FAIL;
1196  }
1197 
1198  // double check probe is connected
1199  if (!this->Internal->BleHelper.IsProbeConnected())
1200  {
1201  LOG_ERROR("Failed to connect to Clarius probe. Last error was: "
1202  << this->Internal->BleHelper.GetLastError());
1203  return PLUS_FAIL;
1204  }
1205 
1206  // BLE connection succeeded
1207  return PLUS_SUCCESS;
1208 }
1209 
1210 //-------------------------------------------------------------------------------------------------
1212 {
1213  LOG_TRACE("vtkPlusClariusOEM::InitializeProbe");
1214 
1215  // power on the probe
1216  if (this->Internal->BleHelper.RequestProbeOn() != PLUS_SUCCESS)
1217  {
1218  LOG_ERROR("An error occurred during RequestProbeOn. Last error was: "
1219  << this->Internal->BleHelper.GetLastError());
1220  return PLUS_FAIL;
1221  }
1222 
1223  // wait for probe to fully power on
1224  if (!this->Internal->BleHelper.AwaitWifiInfoReady())
1225  {
1226  LOG_ERROR("Timeout occurred while waiting for Clarius probe to power on."
1227  << " Last error was: " << this->Internal->BleHelper.GetLastError());
1228  return PLUS_FAIL;
1229  }
1230 
1231  // force wifi into AP mode
1232  if (this->Internal->BleHelper.ConfigureWifiAP() != PLUS_SUCCESS)
1233  {
1234  LOG_ERROR("An error occurred during ConfigureWifiAP. Last error was: "
1235  << this->Internal->BleHelper.GetLastError());
1236  return PLUS_FAIL;
1237  }
1238 
1239  // get & print wifi info
1240  std::pair<bool, ClariusWifiInfo> infoPair = this->Internal->BleHelper.GetWifiInfo();
1241  if (!infoPair.first)
1242  {
1243  LOG_ERROR("An error occurred during GetWifiInfo. Last error was: "
1244  << this->Internal->BleHelper.GetLastError());
1245  return PLUS_FAIL;
1246  }
1247 
1248  ClariusWifiInfo info = infoPair.second;
1249  if (!info.Ready)
1250  {
1251  LOG_ERROR("Wifi was not ready when connection info was requested");
1252  return PLUS_FAIL;
1253  }
1254  else
1255  {
1256  std::stringstream infoStream;
1257  infoStream << "\tAvailable: " << to_string(info.Available) << "\n";
1258  infoStream << "\tWifi Mode: " << to_string(info.WifiMode) << "\n";
1259  infoStream << "\tSSID: " << info.SSID << "\n";
1260  infoStream << "\tPassword: " << info.Password << "\n";
1261  infoStream << "\tIPv4: " << info.IPv4 << "\n";
1262  infoStream << "\tMac Address: " << info.MacAddress << "\n";
1263  infoStream << "\tControl Port: " << info.ControlPort << "\n";
1264  infoStream << "\tCast Port: " << info.CastPort << "\n";
1265  infoStream << "\tChannel: " << info.Channel << "\n";
1266 
1267  LOG_INFO("Clarius Wifi Info: " << std::endl << infoStream.str());
1268 
1269  this->Internal->Ssid = info.SSID;
1270  this->Internal->Password = info.Password;
1271  this->Internal->IpAddress = info.IPv4;
1272  this->Internal->TcpPort = info.ControlPort;
1273 
1274  // Remove leading/trailing quotes from SSID
1275  if (this->Internal->Ssid[0] == '"')
1276  {
1277  this->Internal->Ssid = this->Internal->Ssid.substr(1, this->Internal->Ssid.size() - 2);
1278  }
1279  // Remove leading/trailing quotes from password
1280  if (this->Internal->Password[0] == '"')
1281  {
1282  this->Internal->Password = this->Internal->Password.substr(1, this->Internal->Password.size() - 2);
1283  }
1284  // Remove leading/trailing quotes from IP address
1285  if (this->Internal->IpAddress[0] == '"')
1286  {
1287  this->Internal->IpAddress = this->Internal->IpAddress.substr(1, this->Internal->IpAddress.size() - 2);
1288  }
1289 
1290  }
1291 
1292  return PLUS_SUCCESS;
1293 }
1294 
1295 //-------------------------------------------------------------------------------------------------
1297 {
1298  LOG_TRACE("vtkPlusClariusOEM::InitializeWifi");
1299 
1300  if (this->Internal->WifiHelper.Initialize() != PLUS_SUCCESS)
1301  {
1302  LOG_ERROR("Failed to initialize Clarius wifi helper");
1303  return PLUS_FAIL;
1304  }
1305 
1306  PlusStatus res = this->Internal->WifiHelper.ConnectToClariusWifi(
1307  this->Internal->Ssid,
1308  this->Internal->Password
1309  );
1310  if (res != PLUS_SUCCESS)
1311  {
1312  LOG_ERROR("Failed to connect to Clarius probe wifi");
1313  return PLUS_FAIL;
1314  }
1315 
1316  return PLUS_SUCCESS;
1317 }
1318 
1319 //-------------------------------------------------------------------------------------------------
1321 {
1322  LOG_TRACE("vtkPlusClariusOEM::InitializeOEM");
1323 
1324  // placeholder argc / argv arguments
1325  int argc = 1;
1326  char** argv = new char* [1];
1327  argv[0] = new char[4];
1328  strcpy(argv[0], "abc");
1329  const char* certPath = "/Clarius";
1330 
1331  // api callback functions
1332  CusListFn listFnPtr = static_cast<CusListFn>(&vtkPlusClariusOEM::vtkInternal::ListFn);
1333  CusConnectFn connectFnPtr = static_cast<CusConnectFn>(&vtkPlusClariusOEM::vtkInternal::ConnectFn);
1334  CusCertFn certFnPtr = static_cast<CusCertFn>(&vtkPlusClariusOEM::vtkInternal::CertFn);
1335  CusPowerDownFn powerDownFnPtr = static_cast<CusPowerDownFn>(&vtkPlusClariusOEM::vtkInternal::PowerDownFn);
1336  CusSwUpdateFn swUpdateFnPtr = static_cast<CusSwUpdateFn>(&vtkPlusClariusOEM::vtkInternal::SwUpdateFn);
1337  CusNewRawImageFn newRawImageFnPtr = static_cast<CusNewRawImageFn>(&vtkPlusClariusOEM::vtkInternal::RawImageFn);
1338  CusNewProcessedImageFn newProcessedImageFnPtr = static_cast<CusNewProcessedImageFn>(&vtkPlusClariusOEM::vtkInternal::ProcessedImageFn);
1339  CusNewSpectralImageFn newSpectralImageFnPtr = static_cast<CusNewSpectralImageFn>(&vtkPlusClariusOEM::vtkInternal::SpectralImageFn);
1340  CusNewImuDataFn newImuDataFnPtr = static_cast<CusNewImuDataFn>(&vtkPlusClariusOEM::vtkInternal::ImuDataFn);
1341  CusImagingFn imagingFnPtr = static_cast<CusImagingFn>(&vtkPlusClariusOEM::vtkInternal::ImagingFn);
1342  CusButtonFn buttonFnPtr = static_cast<CusButtonFn>(&vtkPlusClariusOEM::vtkInternal::ButtonFn);
1343  CusProgressFn progressFnPtr = static_cast<CusProgressFn>(&vtkPlusClariusOEM::vtkInternal::ProgressFn);
1344  CusErrorFn errorFnPtr = static_cast<CusErrorFn>(&vtkPlusClariusOEM::vtkInternal::ErrorFn);
1345 
1346  // no b-mode data sources, disable b mode callback
1347  std::vector<vtkPlusDataSource*> bModeSources;
1349  if (this->Internal->BModeSources.empty() && this->Internal->OverlaySources.empty())
1350  {
1351  newProcessedImageFnPtr = nullptr;
1352  }
1353 
1354  // no RF-mode data sources, disable RF-mode callback
1355  std::vector<vtkPlusDataSource*> rfModeSources;
1357  if (rfModeSources.empty())
1358  {
1359  newRawImageFnPtr = nullptr;
1360  }
1361 
1362  try
1363  {
1364  FrameSizeType fs = this->Internal->FrameSize;
1365  int result = solumInit(
1366  argc,
1367  argv,
1368  certPath,
1369  connectFnPtr,
1370  certFnPtr,
1371  powerDownFnPtr,
1372  newProcessedImageFnPtr,
1373  newRawImageFnPtr,
1374  newSpectralImageFnPtr,
1375  newImuDataFnPtr,
1376  imagingFnPtr,
1377  buttonFnPtr,
1378  errorFnPtr,
1379  fs[0],
1380  fs[1]
1381  );
1382  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1383 
1384  if (result < 0)
1385  {
1386  LOG_ERROR("Failed to initialize Clarius OEM library");
1387  return PLUS_FAIL;
1388  }
1389  }
1390  catch (const std::runtime_error& re)
1391  {
1392  LOG_ERROR("Runtime error on solumInit. Error text: " << re.what());
1393  return PLUS_FAIL;
1394  }
1395  catch (const std::exception& ex)
1396  {
1397  LOG_ERROR("Exception on solumInit. Error text: " << ex.what());
1398  return PLUS_FAIL;
1399  }
1400  catch (...)
1401  {
1402  LOG_ERROR("Unknown failure occurred on solumInit");
1403  return PLUS_FAIL;
1404  }
1405 
1406  return PLUS_SUCCESS;
1407 
1408 }
1409 
1410 //-------------------------------------------------------------------------------------------------
1412 {
1413  LOG_TRACE("vtkPlusClariusOEM::SetClariusCert");
1414 
1415  // load the cert file
1416  std::string fullCertPath = vtkPlusConfig::GetInstance()->GetDeviceSetConfigurationPath(this->Internal->PathToCert);
1417  std::ifstream certFile(fullCertPath);
1418  if (!certFile.is_open())
1419  {
1420  LOG_ERROR("Failed to open Clarius cert file from " << fullCertPath << ". Please check the PathToCert path in your config.");
1421  return PLUS_FAIL;
1422  }
1423 
1424  std::ostringstream sstr;
1425  sstr << certFile.rdbuf();
1426  std::string certStr = sstr.str();
1427 
1428  // set cert in OEM API
1429  if (solumSetCert(certStr.c_str()) != 0)
1430  {
1431  LOG_ERROR("Failed to set Clarius OEM connection certificate");
1432  return PLUS_FAIL;
1433  }
1434  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1435 
1436  return PLUS_SUCCESS;
1437 }
1438 
1439 //-------------------------------------------------------------------------------------------------
1441 {
1442  const char* ip = this->Internal->IpAddress.c_str();
1443  unsigned int port = this->Internal->TcpPort;
1444  LOG_INFO("Attempting connection to Clarius ultrasound on " << ip << ":" << port << " for 25 seconds:");
1445 
1446  std::future<void> connectionBarrierFuture = this->Internal->ConnectionBarrier.get_future();
1447  try
1448  {
1449  int result = solumConnect(ip, port);
1450  if (result != CusConnection::ProbeConnected)
1451  {
1452  LOG_ERROR("Failed to initiate connection to Clarius probe on " << ip << ":" << port <<
1453  ". Return code: " << ConnectEnumToString[result]);
1454  return PLUS_FAIL;
1455  }
1456  }
1457  catch (const std::runtime_error& re)
1458  {
1459  LOG_ERROR("Runtime error on solumConnect. Error text: " << re.what());
1460  return PLUS_FAIL;
1461  }
1462  catch (const std::exception& ex)
1463  {
1464  LOG_ERROR("Exception on solumConnect. Error text: " << ex.what());
1465  return PLUS_FAIL;
1466  }
1467  catch (...)
1468  {
1469  LOG_ERROR("Unknown failure occurred on solumConnect");
1470  return PLUS_FAIL;
1471  }
1472 
1473  // wait for solumConnected call to complete
1474  if (connectionBarrierFuture.wait_for(std::chrono::seconds(25)) != std::future_status::ready)
1475  {
1476  LOG_ERROR("Connection to Clarius device timed out");
1477  return PLUS_FAIL;
1478  }
1479  LOG_INFO("Connected to Clarius probe on " << ip << ":" << port);
1480 
1481  // get list of available probes
1482  CusListFn listFnPtr = static_cast<CusListFn>(&vtkPlusClariusOEM::vtkInternal::ListFn);
1483  this->Internal->ExpectedList = vtkPlusClariusOEM::vtkInternal::EXPECTED_LIST::PROBES;
1484  std::future<std::vector<std::string>> futureProbes = this->Internal->PromiseProbes.get_future();
1485  if (solumProbes(listFnPtr) != 0)
1486  {
1487  LOG_INFO("Failed to retrieve list of valid probe types");
1488  return PLUS_FAIL;
1489  }
1490  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1491 
1492  // wait for probes list to be populated
1493  if (futureProbes.wait_for(std::chrono::seconds(5)) != std::future_status::ready)
1494  {
1495  LOG_ERROR("Failed to retrieve list of valid Clarius probe names");
1496  return PLUS_FAIL;
1497  }
1498  std::vector<std::string> vProbes = futureProbes.get();
1499 
1500  // validate provided probe type
1501  std::string probeType = this->Internal->ProbeType;
1502  if (std::find(vProbes.begin(), vProbes.end(), probeType) == vProbes.end())
1503  {
1504  std::string vProbesStr;
1505  for (const auto& probe : vProbes)
1506  {
1507  vProbesStr += probe + ", ";
1508  }
1509  vProbesStr.pop_back(); vProbesStr.pop_back(); // remove trailing comma and space
1510  LOG_ERROR("Invalid probe type (" << probeType << ") provided, valid probe types are: " << vProbesStr);
1511  return PLUS_FAIL;
1512  }
1513 
1514  // list available imaging applications
1515  this->Internal->ExpectedList = vtkPlusClariusOEM::vtkInternal::EXPECTED_LIST::APPLICATIONS;
1516  std::future<std::vector<std::string>> futureApplications = this->Internal->PromiseApplications.get_future();
1517  if (solumApplications(probeType.c_str(), listFnPtr) != 0)
1518  {
1519  LOG_ERROR("Failed to retrieve list of valid imaging applications");
1520  return PLUS_FAIL;
1521  }
1522  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1523 
1524  // wait for applications list to be populated
1525  if (futureApplications.wait_for(std::chrono::seconds(5)) != std::future_status::ready)
1526  {
1527  LOG_ERROR("Failed to retrieve list of valid Clarius application names");
1528  return PLUS_FAIL;
1529  }
1530  std::vector<std::string> vApps = futureApplications.get();
1531 
1532  // validate provided imaging application
1533  std::string imagingApplication = this->Internal->ImagingApplication;
1534  if (std::find(vApps.begin(), vApps.end(), imagingApplication) == vApps.end())
1535  {
1536  std::string vAppsStr;
1537  for (const auto& app : vApps)
1538  {
1539  vAppsStr += app + ", ";
1540  }
1541  vAppsStr.pop_back(); vAppsStr.pop_back(); // remove trailing comma and space
1542  LOG_ERROR("Invalid imaging application (" << imagingApplication << ") provided, valid imaging applications are: " << vAppsStr);
1543  return PLUS_FAIL;
1544  }
1545 
1546  // configure probe mode
1547  if (solumLoadApplication(probeType.c_str(), imagingApplication.c_str()) == 0)
1548  {
1549  LOG_INFO("Loaded " << imagingApplication << " application on a " << probeType << " probe");
1550  }
1551  else
1552  {
1553  LOG_ERROR("An error occured on call to solumLoadApplication");
1554  }
1555  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1556 
1557  return PLUS_SUCCESS;
1558 }
1559 
1560 //-------------------------------------------------------------------------------------------------
1562 {
1563  LOG_TRACE("vtkPlusClariusOEM::SetInitialUsParams");
1564 
1565  // set imaging depth (mm)
1566  double depthMm = this->ImagingParameters->GetDepthMm();
1567  if (this->SetDepthMm(depthMm) != PLUS_SUCCESS)
1568  {
1569  LOG_WARNING("Failed to set requested imaging depth (mm) in Clarius OEM device, unknown depth will be used");
1570  }
1571 
1572  // set gain (%)
1573  double gainPercent = this->ImagingParameters->GetGainPercent();
1574  if (this->SetGainPercent(gainPercent) != PLUS_SUCCESS)
1575  {
1576  LOG_WARNING("Failed to set requested imaging gain (%) in Clarius OEM device, unknown gain will be used");
1577  }
1578 
1579  // set dynamic range (%)
1580  double dynRangePercent = this->ImagingParameters->GetDynRangeDb();
1581  if (this->SetDynRangePercent(dynRangePercent) != PLUS_SUCCESS)
1582  {
1583  LOG_WARNING("Failed to set requested imaging dynamic range in Clarius OEM device, unknown dynamic range will be used");
1584  }
1585 
1586  // set time gain compensation
1587  std::vector<double> tgcDb = this->ImagingParameters->GetTimeGainCompensation();
1588  if (this->SetTimeGainCompensationDb(tgcDb) != PLUS_SUCCESS)
1589  {
1590  LOG_WARNING("Failed to set requested imaging time gain compensation in Clarius OEM device, unknown time gain compensation will be used");
1591  }
1592 
1593  if (this->SetEnableAutoFocus(this->Internal->EnableAutoFocus) != PLUS_SUCCESS)
1594  {
1595  LOG_WARNING("Failed to set auto focus");
1596  }
1597 
1598  if (this->SetEnableAutoGain(this->Internal->EnableAutoGain) != PLUS_SUCCESS)
1599  {
1600  LOG_WARNING("Failed to set auto gain");
1601  }
1602 
1603  if (this->SetEnablePenetrationMode(this->Internal->EnablePenetrationMode) != PLUS_SUCCESS)
1604  {
1605  LOG_WARNING("Failed to set penetration mode");
1606  }
1607 
1608  return PLUS_SUCCESS;
1609 }
1610 
1611 //-------------------------------------------------------------------------------------------------
1613 {
1614  LOG_TRACE("vtkPlusClariusOEM::InternalConnect");
1615 
1616  if (this->Connected)
1617  {
1618  // Internal connect already called and completed successfully
1619  return PLUS_SUCCESS;
1620  }
1621 
1622  // log user settings for debugging
1623  this->Internal->LogUserSettings();
1624 
1625  // BLE
1626  if (this->InitializeBLE() != PLUS_SUCCESS)
1627  {
1628  LOG_ERROR("Failed to initialize BLE in Clarius OEM device");
1629  this->InternalDisconnect();
1630  return PLUS_FAIL;
1631  }
1632 
1633  // PROBE (power, etc.)
1634  if (this->InitializeProbe() != PLUS_SUCCESS)
1635  {
1636  LOG_ERROR("Failed to initialize probe (power, wifi settings) in Clarius OEM device");
1637  this->InternalDisconnect();
1638  return PLUS_FAIL;
1639  }
1640 
1641  // WIFI
1642  if (this->InitializeWifi() != PLUS_SUCCESS)
1643  {
1644  LOG_ERROR("Failed to initialize wifi in Clarius OEM device");
1645  this->InternalDisconnect();
1646  return PLUS_FAIL;
1647  }
1648 
1649  // OEM library
1650  if (this->InitializeOEM() != PLUS_SUCCESS)
1651  {
1652  LOG_ERROR("Failed to initialize OEM library in Clarius OEM device");
1653  this->InternalDisconnect();
1654  return PLUS_FAIL;
1655  }
1656 
1657  // SET CERTIFICATE
1658  if (this->SetClariusCert() != PLUS_SUCCESS)
1659  {
1660  LOG_ERROR("Failed to set Clarius certificate. Please check your PathToCert is valid, and contains the correct cert for the probe you're connecting to");
1661  this->InternalDisconnect();
1662  return PLUS_FAIL;
1663  }
1664 
1665  // CONFIGURE PROBE SETTINGS
1666  CusProbeSettings settings;
1667  settings.contactDetection = this->Internal->ContactDetectionTimeoutSec;
1668  settings.autoFreeze = this->Internal->AutoFreezeTimeoutSec;
1669  settings.keepAwake = this->Internal->KeepAwakeTimeoutMin;
1670  settings.deepSleep = this->Internal->DeepSleepTimeoutHr;
1671  settings.stationary = this->Internal->StationaryTimeoutSec;
1672  settings.wifiOptimization = this->Internal->FreezeOnPoorWifiSignal;
1673  // settings.wifiSearch
1674  // settings.htWifi
1675  settings.keepAwakeCharging = this->Internal->KeepAwakeCharging;
1676  settings.powerOn = this->Internal->PowerButtonsEnabled;
1677  settings.sounds = this->Internal->SoundEnabled;
1678  settings.wakeOnShake = this->Internal->WakeOnShake;
1679  // settings.bandwidthOptimization
1680  settings.forceLogSend = this->Internal->ForceLogSend;
1681  settings.up = static_cast<CusButtonSetting>(this->Internal->UpButtonMode);
1682  settings.down = static_cast<CusButtonSetting>(this->Internal->DownButtonMode);
1683  settings.handle = CusButtonSetting::ButtonDisabled;
1684  settings.upHold = CusButtonHoldSetting::ButtonHoldDisabled;
1685  settings.downHold = CusButtonHoldSetting::ButtonHoldShutdown;
1686  if (solumSetProbeSettings(&settings) != 0)
1687  {
1688  LOG_ERROR("Failed to set Clarius OEM probe settings");
1689  return PLUS_FAIL;
1690  }
1691  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1692 
1693  // CONFIGURE PROBE MODE
1694  if (this->ConfigureProbeApplication() != PLUS_SUCCESS)
1695  {
1696  LOG_ERROR("Failed to configure Clarius probe application");
1697  this->InternalDisconnect();
1698  return PLUS_FAIL;
1699  }
1700 
1701  // PRINT DEVICE STATS AND PROBE INFO
1702  this->UpdateProbeStatus();
1703  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1704 
1705  CusProbeInfo probeInfo;
1706  if (solumProbeInfo(&probeInfo) != 0)
1707  {
1708  LOG_WARNING("Failed to retrieve solumProbeInfo");
1709  }
1710  std::stringstream ss;
1711  ss << "Version: " << probeInfo.version << std::endl;
1712  ss << "Battery: " << this->Internal->CurrentStatus.battery << "%" << std::endl;
1713  ss << "Temperature: " << this->Internal->CurrentStatus.temperature << "%" << std::endl;
1714  ss << "Elements: " << probeInfo.elements << std::endl;
1715  ss << "Pitch: " << probeInfo.pitch << std::endl;
1716  ss << "Radius: " << probeInfo.radius << "mm" << std::endl;
1717  LOG_INFO(std::endl << "Probe info: " << std::endl << ss.str());
1718 
1719  // enable the 5v rail on the top of the Clarius probe
1720  int enable5v = this->Internal->Enable5v ? 1 : 0;
1721  if (solumEnable5v(enable5v) < 0)
1722  {
1723  std::string enstr = (enable5v ? "TRUE" : "FALSE");
1724  LOG_WARNING("Failed to set the state of the Clarius probe 5v rail, provided enable value was: " << enstr);
1725  }
1726  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1727 
1728  // set imaging parameters
1729  this->SetInitialUsParams();
1730 
1731  CusMode mode = CusMode(this->Internal->ImagingMode);
1732  if (solumSetMode(mode) != 0)
1733  {
1734  LOG_ERROR("Failed to set Clarius OEM imaging mode");
1735  return PLUS_FAIL;
1736  }
1737 
1738  // set separate overlays
1739  if (solumSeparateOverlays(1) != 0)
1740  {
1741  LOG_ERROR("Failed to set Clarius separate overlays");
1742  return PLUS_FAIL;
1743  }
1744 
1745  return PLUS_SUCCESS;
1746 };
1747 
1748 //-------------------------------------------------------------------------------------------------
1750 {
1751  LOG_TRACE("vtkPlusClariusOEM::DeInitializeOEM");
1752 
1753  int oemState = solumIsConnected();
1754  if (oemState == CLARIUS_STATE_NOT_INITIALIZED)
1755  {
1756  return;
1757  }
1758 
1759  if (oemState == CLARIUS_STATE_CONNECTED)
1760  {
1761  if (solumEnable5v(CLARIUS_FALSE) < 0)
1762  {
1763  LOG_WARNING("Failed to disable Clarius 5v");
1764  }
1765 
1766  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1767  if (solumRun(CLARIUS_STOP) < 0)
1768  {
1769  LOG_WARNING("Failed to stop Clarius imaging");
1770  }
1771 
1772  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1773  if (solumDisconnect() < 0)
1774  {
1775  LOG_WARNING("Failed to disconnect from Clarius OEM library");
1776  }
1777  }
1778 
1779  if (solumDestroy() < 0)
1780  {
1781  LOG_WARNING("Failed to destroy Clarius OEM library");
1782  }
1783 }
1784 
1785 //-------------------------------------------------------------------------------------------------
1787 {
1788  LOG_TRACE("vtkPlusClariusOEM::DeInitializeWifi");
1789 
1790  if (!this->Internal->WifiHelper.DisconnectFromClariusWifi())
1791  {
1792  LOG_WARNING("Failed to disconnect from Clarius wifi");
1793  }
1794  if (!this->Internal->WifiHelper.DeInitialize())
1795  {
1796  LOG_WARNING("Failed to de-initialize ClariusWifi");
1797  }
1798 }
1799 
1800 //-------------------------------------------------------------------------------------------------
1802 {
1803  LOG_TRACE("vtkPlusClariusOEM::DeInitializeProbe");
1804 
1805  // power off the probe if powered / connected over BLE
1806  if (!this->Internal->BleHelper.IsProbeConnected())
1807  {
1808  return;
1809  }
1810 
1811  if (this->Internal->BleHelper.RequestProbeOff() != PLUS_SUCCESS)
1812  {
1813  LOG_ERROR("An error occurred during RequestProbeOff. Last error was: "
1814  << this->Internal->BleHelper.GetLastError())
1815  }
1816 }
1817 
1818 //-------------------------------------------------------------------------------------------------
1820 {
1821  LOG_TRACE("vtkPlusClariusOEM::DeInitializeBLE");
1822 
1823  // disconnect from probe BLE
1824  if (this->Internal->BleHelper.Disconnect() != PLUS_SUCCESS)
1825  {
1826  LOG_ERROR("An error occurred during Clarius BLE Disconnect. Last error was: "
1827  << this->Internal->BleHelper.GetLastError());
1828  }
1829 }
1830 
1831 //-------------------------------------------------------------------------------------------------
1833 {
1834  LOG_TRACE("vtkPlusClariusOEM::InternalDisconnect");
1835 
1836  // inverse order to initialization
1837  this->DeInitializeOEM();
1838  this->DeInitializeWifi();
1839  this->DeInitializeProbe();
1840  this->DeInitializeBLE();
1841 
1842  return PLUS_SUCCESS;
1843 };
1844 
1845 //-------------------------------------------------------------------------------------------------
1847 {
1848  LOG_TRACE("vtkPlusClariusOEM::InternalStartRecording");
1849 
1850  this->UpdateFrameSize();
1851 
1852  bool running = false;
1853  for (int i = 0; i < 10; ++i)
1854  {
1855  // Attempt to connect. solumRun may not succeed the first time.
1856  if (solumRun(CLARIUS_RUN) < 0)
1857  {
1858  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1859  continue;
1860  }
1861  running = true;
1862  }
1863 
1864  if (!running)
1865  {
1866  LOG_ERROR("Failed to start Clarius imaging");
1867  return PLUS_FAIL;
1868  }
1869  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1870 
1871  return PLUS_SUCCESS;
1872 }
1873 
1874 //----------------------------------------------------------------------------
1876 {
1877  vtkPlusDataSource* videoSource(NULL);
1878  this->GetFirstVideoSource(videoSource);
1879  videoSource->SetInputFrameSize(this->Internal->FrameSize);
1880  videoSource->SetPixelType(VTK_UNSIGNED_CHAR);
1881  unsigned int numberOfScalarComponents = (videoSource->GetImageType() == US_IMG_RGB_COLOR ? 3 : 1);
1882  videoSource->SetNumberOfScalarComponents(numberOfScalarComponents);
1883  return PLUS_SUCCESS;
1884 }
1885 
1886 //-------------------------------------------------------------------------------------------------
1888 {
1889  LOG_TRACE("vtkPlusClariusOEM::InternalStopRecording");
1890 
1891  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
1892  {
1893  // Not connected, so recording is already stopped.
1894  return PLUS_SUCCESS;
1895  }
1896 
1897  if (solumRun(CLARIUS_STOP) < 0)
1898  {
1899  LOG_ERROR("Failed to stop Clarius imaging");
1900  return PLUS_FAIL;
1901  }
1902  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1903 
1904  return PLUS_SUCCESS;
1905 }
1906 
1907 //-------------------------------------------------------------------------------------------------
1909 {
1910  LOG_TRACE("vtkPlusClariusOEM::InternalApplyImagingParameterChange");
1911 
1912  PlusStatus status = PLUS_SUCCESS;
1913 
1914  // depth (mm), note: Clarius uses cm
1917  {
1918  if (this->SetDepthMm(this->ImagingParameters->GetDepthMm()) != PLUS_SUCCESS)
1919  {
1920  LOG_ERROR("Failed to set depth imaging parameter");
1921  status = PLUS_FAIL;
1922  }
1924  }
1925 
1926  // gain (percent)
1929  {
1931  {
1932  LOG_ERROR("Failed to set gain imaging parameter");
1933  status = PLUS_FAIL;
1934  }
1936  }
1937 
1938  // dynamic range (percent)
1941  {
1943  {
1944  LOG_ERROR("Failed to set dynamic range imaging parameter");
1945  status = PLUS_FAIL;
1946  }
1948  }
1949 
1950  // TGC (time gain compensation)
1953  {
1954  std::vector<double> tgcVec;
1956  if (this->SetTimeGainCompensationDb(tgcVec) != PLUS_SUCCESS)
1957  {
1958  LOG_ERROR("Failed to set time gain compensation imaging parameter");
1959  status = PLUS_FAIL;
1960  }
1962  }
1963 
1964  // FOCUS DEPTH
1967  {
1969  {
1970  LOG_ERROR("Failed to set focus depth percent imaging parameter");
1971  status = PLUS_FAIL;
1972  }
1974  }
1975 
1976  return status;
1977 }
1978 
1979 //-------------------------------------------------------------------------------------------------
1981 {
1982  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
1983  {
1984  // Connection has not been established yet, return cached parameter value
1985  return this->ImagingParameters->GetDepthMm(aDepthMm);
1986  }
1987 
1988  double oemVal = solumGetParam(CusParam::ImageDepth);
1989  if (oemVal < 0)
1990  {
1991  aDepthMm = -1;
1992  LOG_ERROR("Failed to get DepthMm parameter");
1993  return PLUS_FAIL;
1994  }
1995  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
1996 
1997  aDepthMm = oemVal * CM_TO_MM;
1998 
1999  // ensure ImagingParameters is up to date
2000  this->ImagingParameters->SetDepthMm(aDepthMm);
2001 
2002  return PLUS_SUCCESS;
2003 }
2004 
2005 //-------------------------------------------------------------------------------------------------
2007 {
2008  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2009  {
2010  // Connection has not been established yet, parameter value will be set upon connection
2011  this->ImagingParameters->SetDepthMm(aDepthMm);
2012  LOG_INFO("Cached US parameter DepthMm = " << aDepthMm);
2013  return PLUS_SUCCESS;
2014  }
2015 
2016  // attempt to set parameter value
2017  double depthCm = aDepthMm * MM_TO_CM;
2018  if (solumSetParam(CusParam::ImageDepth, depthCm) < 0)
2019  {
2020  LOG_ERROR("Failed to set DepthMm parameter");
2021  return PLUS_FAIL;
2022  }
2023  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2024 
2025  // update imaging parameters & return successfully
2026  this->ImagingParameters->SetDepthMm(aDepthMm);
2027  LOG_INFO("Set US parameter DepthMm to " << aDepthMm);
2028  return PLUS_SUCCESS;
2029 }
2030 
2031 //-------------------------------------------------------------------------------------------------
2033 {
2034  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2035  {
2036  // Connection has not been established yet, return cached parameter value
2037  return this->ImagingParameters->GetGainPercent(aGainPercent);
2038  }
2039 
2040  double oemVal = solumGetParam(CusParam::Gain);
2041  if (oemVal < 0)
2042  {
2043  aGainPercent = -1;
2044  LOG_ERROR("Failed to get GainPercent parameter");
2045  return PLUS_FAIL;
2046  }
2047  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2048 
2049  aGainPercent = oemVal;
2050 
2051  // ensure ImagingParameters is up to date
2052  this->ImagingParameters->SetGainPercent(aGainPercent);
2053 
2054  return PLUS_SUCCESS;
2055 }
2056 
2057 //-------------------------------------------------------------------------------------------------
2059 {
2060  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2061  {
2062  // Connection has not been established yet, parameter value will be set upon connection
2063  this->ImagingParameters->SetGainPercent(aGainPercent);
2064  LOG_INFO("Cached US parameter GainPercent = " << aGainPercent);
2065  return PLUS_SUCCESS;
2066  }
2067 
2068  // attempt to set parameter value
2069  if (solumSetParam(CusParam::Gain, aGainPercent) < 0)
2070  {
2071  LOG_ERROR("Failed to set GainPercent parameter");
2072  return PLUS_FAIL;
2073  }
2074  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2075 
2076  // update imaging parameters & return successfully
2077  this->ImagingParameters->SetGainPercent(aGainPercent);
2078  LOG_INFO("Set US parameter GainPercent to " << aGainPercent);
2079  return PLUS_SUCCESS;
2080 }
2081 
2082 //-------------------------------------------------------------------------------------------------
2084 {
2085  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2086  {
2087  // Connection has not been established yet, return cached parameter value
2088  return this->ImagingParameters->GetDynRangeDb(aDynRangePercent);
2089  }
2090 
2091  double oemVal = solumGetParam(CusParam::DynamicRange);
2092  if (oemVal < 0)
2093  {
2094  aDynRangePercent = -1;
2095  LOG_ERROR("Failed to get DynRange parameter");
2096  return PLUS_FAIL;
2097  }
2098  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2099 
2100  aDynRangePercent = oemVal;
2101 
2102  // ensure ImagingParameters is up to date
2103  this->ImagingParameters->SetDynRangeDb(aDynRangePercent);
2104 
2105  return PLUS_SUCCESS;
2106 }
2107 
2108 //-------------------------------------------------------------------------------------------------
2110 {
2111  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2112  {
2113  // Connection has not been established yet, parameter value will be set upon connection
2114  this->ImagingParameters->SetDynRangeDb(aDynRangePercent);
2115  LOG_INFO("Cached US parameter DynRangePercent = " << aDynRangePercent);
2116  return PLUS_SUCCESS;
2117  }
2118 
2119  // attempt to set parameter value
2120  if (solumSetParam(CusParam::DynamicRange, aDynRangePercent) < 0)
2121  {
2122  LOG_ERROR("Failed to set DynRange parameter");
2123  return PLUS_FAIL;
2124  }
2125  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2126 
2127  // update imaging parameters & return successfully
2128  this->ImagingParameters->SetDynRangeDb(aDynRangePercent);
2129  LOG_INFO("Set US parameter DynRangePercent to " << aDynRangePercent);
2130  return PLUS_SUCCESS;
2131 }
2132 
2133 //-------------------------------------------------------------------------------------------------
2135 {
2136  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2137  {
2138  // Connection has not been established yet, return cached parameter value
2139  return this->ImagingParameters->GetTimeGainCompensation(aTGC);
2140  }
2141 
2142  CusTgc cTGC;
2143  if (solumGetTgc(&cTGC) < 0)
2144  {
2145  LOG_ERROR("Failed to get time gain compensation parameter");
2146  return PLUS_FAIL;
2147  }
2148  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2149 
2150  aTGC.clear();
2151  aTGC.resize(3);
2152  aTGC[0] = cTGC.top;
2153  aTGC[1] = cTGC.mid;
2154  aTGC[2] = cTGC.bottom;
2155 
2156  // ensure imaging parameters are up to date
2158 
2159  return PLUS_SUCCESS;
2160 }
2161 
2162 //-------------------------------------------------------------------------------------------------
2164 {
2165  if (aTGC.size() != 3)
2166  {
2167  LOG_ERROR("vtkPlusClariusOEM time gain compensation parameter must be provided a vector of exactly 3 doubles [top gain, mid gain, bottom gain]");
2168  return PLUS_FAIL;
2169  }
2170 
2171  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2172  {
2173  // Connection has not been established yet, parameter value will be set upon connection
2175  LOG_INFO("Cached US parameter TGC = [" << aTGC[0] << ", " << aTGC[1] << ", " << aTGC[2] << "]");
2176  return PLUS_SUCCESS;
2177  }
2178 
2179  for (int i = 0; i < 3; ++i)
2180  {
2181  if (std::abs(aTGC[i]) > 20)
2182  {
2183  LOG_ERROR("Invalid time gain compensation parameter at index: " << i << " ["
2184  << aTGC[0] << ", "
2185  << aTGC[1] << ", "
2186  << aTGC[2] << "]. "
2187  << "Valid range is [-20, 20]");
2188  return PLUS_FAIL;
2189  }
2190  }
2191 
2192  CusTgc cTGC;
2193  cTGC.top = aTGC[0];
2194  cTGC.mid = aTGC[1];
2195  cTGC.bottom = aTGC[2];
2196  if (solumSetTgc(&cTGC) < 0)
2197  {
2198  LOG_ERROR("Failed to set time gain compensation parameter");
2199  return PLUS_FAIL;
2200  }
2201  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2202 
2203  // update imaging parameters & return successfully
2205  LOG_INFO("Set US parameter TGC to [" << aTGC[0] << ", " << aTGC[1] << ", " << aTGC[2] << "]");
2206  return PLUS_SUCCESS;
2207 }
2208 
2209 //-------------------------------------------------------------------------------------------------
2211 {
2212  int oemState = solumIsConnected();
2213  if (oemState != CLARIUS_STATE_CONNECTED)
2214  {
2215  // Connection has not been established yet, return cached parameter value
2216  aEnableAutoFocus = this->Internal->EnableAutoFocus;
2217  return PLUS_SUCCESS;
2218  }
2219 
2220  aEnableAutoFocus = solumGetParam(CusParam::AutoFocus) > 0;
2221  return PLUS_SUCCESS;
2222 }
2223 
2224 //-------------------------------------------------------------------------------------------------
2226 {
2227  this->Internal->EnableAutoFocus = aEnableAutoFocus;
2228 
2229  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2230  {
2231  // Connection has not been established yet, parameter value will be set upon connection
2232  LOG_INFO("Cached US parameter AutoFocus = " << aEnableAutoFocus);
2233  return PLUS_SUCCESS;
2234  }
2235 
2236  // attempt to set parameter value
2237  if (solumSetParam(AutoFocus, aEnableAutoFocus ? CLARIUS_TRUE : CLARIUS_FALSE))
2238  {
2239  LOG_ERROR("Failed to set AutoFocus parameter");
2240  return PLUS_FAIL;
2241  }
2242  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2243 
2244  return PLUS_SUCCESS;
2245 }
2246 
2247 //-------------------------------------------------------------------------------------------------
2249 {
2250  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2251  {
2252  // Connection has not been established yet, return cached parameter value
2253  aEnablePenetrationMode = this->Internal->EnablePenetrationMode;
2254  return PLUS_SUCCESS;
2255  }
2256 
2257  aEnablePenetrationMode = solumGetParam(PenetrationMode) > 0;
2258  return PLUS_SUCCESS;
2259 }
2260 
2261 //-------------------------------------------------------------------------------------------------
2263 {
2264  LOG_TRACE("vtkPlusClariusOEM::SetEnablePenetrationMode");
2265 
2266  // attempt to set parameter value
2267  if (solumSetParam(PenetrationMode, aEnablePenetrationMode ? CLARIUS_TRUE : CLARIUS_FALSE))
2268  {
2269  LOG_ERROR("Failed to set PenetrationMode parameter");
2270  return PLUS_FAIL;
2271  }
2272  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2273 
2274  return PLUS_SUCCESS;
2275 }
2276 
2277 //-------------------------------------------------------------------------------------------------
2279 {
2280  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2281  {
2282  // Connection has not been established yet, return cached parameter value
2283  return this->ImagingParameters->GetFocusDepthPercent(aFocusDepthPercent);
2284  }
2285 
2286  double focusDepthCm = solumGetParam(CusParam::FocusDepth);
2287  if (focusDepthCm < 0)
2288  {
2289  aFocusDepthPercent = -1;
2290  LOG_ERROR("Failed to get FocusDepthPercent parameter");
2291  return PLUS_FAIL;
2292  }
2293  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2294 
2295  // ensure ImagingParameters is up to date
2298 
2299  return PLUS_SUCCESS;
2300 }
2301 
2302 //-------------------------------------------------------------------------------------------------
2304 {
2305  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2306  {
2307  // Connection has not been established yet, parameter value will be set upon connection
2308  this->ImagingParameters->SetFocusDepthPercent(aFocusDepthPercent);
2309  LOG_INFO("Cached US parameter FocusDepthPercent = " << aFocusDepthPercent);
2310  return PLUS_SUCCESS;
2311  }
2312 
2313  if (aFocusDepthPercent < 0)
2314  {
2315  this->SetEnableAutoFocus(true);
2316  return PLUS_SUCCESS;
2317  }
2318  this->SetEnableAutoFocus(false);
2319 
2320  double focusDepthCm = this->ConvertDepthPercentToCm(aFocusDepthPercent);
2321 
2322  // attempt to set parameter value
2323  if (solumSetParam(CusParam::FocusDepth, focusDepthCm) < 0)
2324  {
2325  LOG_ERROR("Failed to set FocusDepthPercent parameter");
2326  return PLUS_FAIL;
2327  }
2328  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2329 
2330  // update imaging parameters & return successfully
2331  this->ImagingParameters->SetFocusDepthPercent(aFocusDepthPercent);
2332  LOG_INFO("Set US parameter FocusDepthPercent to " << aFocusDepthPercent);
2333  return PLUS_SUCCESS;
2334 }
2335 
2336 //-------------------------------------------------------------------------------------------------
2338 {
2339  double depthMm = 0.0;
2340  if (this->GetDepthMm(depthMm) != PLUS_SUCCESS)
2341  {
2342  return 0.0;
2343  }
2344  return 100.0 * depthMm / (aFocusDepthCm * CM_TO_MM);
2345 }
2346 
2347 //-------------------------------------------------------------------------------------------------
2348 double vtkPlusClariusOEM::ConvertDepthPercentToCm(double aFocusDepthPercent)
2349 {
2350  double depthMm = 0.0;
2351  if (this->GetDepthMm(depthMm) != PLUS_SUCCESS)
2352  {
2353  return 0.0;
2354  }
2355  return (depthMm * MM_TO_CM) * (aFocusDepthPercent / 100.0);
2356 }
2357 
2358 //-------------------------------------------------------------------------------------------------
2360 {
2361  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2362  {
2363  // Connection has not been established yet, return cached parameter value
2364  aEnableAutoGain = this->Internal->EnableAutoGain;
2365  return PLUS_SUCCESS;
2366  }
2367 
2368  aEnableAutoGain = solumGetParam(CusParam::AutoGain) > 0;
2369  return PLUS_SUCCESS;
2370 }
2371 
2372 //-------------------------------------------------------------------------------------------------
2374 {
2375  this->Internal->EnableAutoGain = aEnableAutoGain;
2376 
2377  if (solumIsConnected() != CLARIUS_STATE_CONNECTED)
2378  {
2379  // Connection has not been established yet, parameter value will be set upon connection
2380  LOG_INFO("Cached US parameter AutoGain = " << aEnableAutoGain);
2381  return PLUS_SUCCESS;
2382  }
2383 
2384  // attempt to set parameter value
2385  if (solumSetParam(AutoGain, aEnableAutoGain ? CLARIUS_TRUE : CLARIUS_FALSE))
2386  {
2387  LOG_ERROR("Failed to set AutoGain parameter");
2388  return PLUS_FAIL;
2389  }
2390  std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2391 
2392  return PLUS_SUCCESS;
2393 }
PlusStatus ConfigureProbeApplication()
PlusStatus GetEnablePenetrationMode(bool &aEnablePenetrationMode)
static const std::string RFMODE_PORT_NAME
Definition: vtkPlusDevice.h:68
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *deviceConfig)
#define CLARIUS_RUN
bool IsPending(const std::string &paramName) const
double ConvertDepthCmToPercent(double aFocusDepthMm)
static void BGRA32ToRGB24(int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:260
US_IMAGE_TYPE GetImageType()
PlusStatus UpdateFrameSize()
PlusStatus SetGainPercent(double aGainPercent)
std::string Password
Definition: ClariusBLE.h:46
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
#define CLARIUS_TRUE
PlusStatus InitializeProbe()
Phidget_MeshMode mode
Definition: phidget22.h:1332
igsioStatus PlusStatus
Definition: PlusCommon.h:40
PlusStatus GetFocusDepthPercent(double &aFocusDepthPercent) const
static const std::string BMODE_PORT_NAME
Definition: vtkPlusDevice.h:67
PlusStatus GetDepthMm(double &aDepthMm) const
std::string IPv4
Definition: ClariusBLE.h:47
PlusStatus SetEnableAutoGain(bool aEnableAutoGain)
PlusStatus SetInputFrameSize(unsigned int x, unsigned int y, unsigned int z)
std::vector< vtkPlusDataSource * > GetVideoSources() const
#define CLARIUS_STATE_CONNECTED
bool RequirePortNameInDeviceSetConfiguration
std::string to_string(ClariusAvailability avail)
std::string MacAddress
Definition: ClariusBLE.h:48
PlusStatus UpdateProbeStatus()
vtkPlusUsImagingParameters * ImagingParameters
Store the current imaging parameters.
ClariusAvailability
Definition: ClariusBLE.h:24
for i
PlusStatus SetPending(const std::string &paramName, bool pending)
PlusStatus InternalStartRecording() override
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus GetGainPercent(double &aGainPercent)
void PrintSelf(ostream &os, vtkIndent indent) override
PlusStatus GetVideoSourcesByPortName(const char *aPortName, std::vector< vtkPlusDataSource * > &sources)
static vtkPlusClariusOEM * New()
PlusStatus NotifyConfigured() override
int port
Definition: phidget22.h:2454
PlusStatus SetPixelType(igsioCommon::VTKScalarPixelType pixelType)
PlusStatus SetTimeGainCompensation(const std::vector< double > &tgc)
#define CLARIUS_STATE_NOT_INITIALIZED
static vtkPlusConfig * GetInstance()
PlusStatus GetGainPercent(double aGainPercent) const
ClariusWifiMode
Definition: ClariusBLE.h:32
PlusStatus GetFirstVideoSource(vtkPlusDataSource *&anImage)
virtual PlusStatus Disconnect()
PlusStatus GetTimeGainCompensation(std::vector< double > &tgc) const
PlusStatus SetPowerDb(double aPower)
PlusStatus SetEnablePenetrationMode(bool aEnablePenetrationMode)
PlusStatus WriteConfiguration(vtkXMLDataElement *config) override
unsigned long FrameNumber
PlusStatus GetDepthMm(double &aDepthMm)
virtual void PrintSelf(ostream &os, vtkIndent indent) VTK_OVERRIDE
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
static const std::string OVERLAY_PORT_NAME
PlusStatus SetFocusDepthPercent(double aFocusDepthPercent)
PlusStatus GetFocusDepthPercent(double &aFocusDepthPercent)
PlusStatus GetDynRangePercent(double &aDynamicRangePercent)
PlusStatus GetDynRangeDb(double &aDynRangeDb) const
PlusStatus SetGainPercent(double aGainPercent)
PlusStatus SetDynRangePercent(double aDynamicRangePercent)
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_READING(deviceConfig, rootConfigElement)
PlusStatus SetDynRangeDb(double aDynRangeDb)
ClariusAvailability Available
Definition: ClariusBLE.h:43
PlusStatus ReadConfiguration(vtkXMLDataElement *config) override
PlusStatus GetTimeGainCompensationDb(std::vector< double > &aTGC)
#define CLARIUS_FALSE
PlusStatus InternalUpdate() override
PlusStatus GetEnableAutoGain(bool &aEnableAutoGain)
PlusStatus Probe() override
ClariusWifiMode WifiMode
Definition: ClariusBLE.h:44
std::string GetSdkVersion() override
bool StartThreadForInternalUpdates
#define CLARIUS_STOP
static PlusStatus ConvertToGray(int inputCompression, int width, int height, unsigned char *s, unsigned char *d)
Definition: PixelCodec.h:146
PlusStatus SetDepthMm(double aDepthMm)
PlusStatus SetEnableAutoFocus(bool aEnableAutoFocus)
PlusStatus InternalDisconnect() override
PlusStatus SetFrequencyMhz(double aFrequencyMhz)
ChannelContainer OutputChannels
PlusStatus SetNumberOfScalarComponents(unsigned int numberOfScalarComponents)
PlusStatus SetFocusDepthPercent(double aFocusDepthPercent)
std::string GetDeviceSetConfigurationPath(const std::string &subPath)
PlusStatus SetInitialUsParams()
PlusStatus InternalConnect() override
PlusStatus GetEnableAutoFocus(bool &aEnableAutoFocus)
std::string GetToolReferenceFrameName() const
bool IsSet(const std::string &paramName) const
PlusStatus InternalStopRecording() override
PlusStatus GetTool(const char *aToolSourceId, vtkPlusDataSource *&aTool) const
static vtkPlusClariusOEM * GetInstance()
PlusStatus SetDepthMm(double aDepthMm)
PlusStatus SetTimeGainCompensationDb(const std::vector< double > &aTGC)
Interface to Clarius Ultrasound Devices This class talks with a Clarius US Scanner over the Clarius O...
PlusStatus InternalApplyImagingParameterChange() override
std::string SSID
Definition: ClariusBLE.h:45
double ConvertDepthPercentToCm(double aFocusDepthPercent)
bool CorrectlyConfigured
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *deviceConfig)
Interface to a 3D positioning tool, video source, or generalized data stream.