11 #include "PlusConfigure.h" 24 #include <solum_def.h> 27 #include <vtkImageData.h> 28 #include <vtkInformation.h> 29 #include <vtkMatrix4x4.h> 31 #include <vtkSmartPointer.h> 43 #define CLARIUS_TRUE 1 44 #define CLARIUS_FALSE 0 46 #define CLARIUS_STOP 0 49 #define CLARIUS_STATE_NOT_INITIALIZED -1 50 #define CLARIUS_STATE_NOT_CONNECTED 0 51 #define CLARIUS_STATE_CONNECTED 1 71 return "Not Available";
73 return "Unknown ClariusAvailability";
83 return "Access Point";
85 return "Local Area Network";
87 return "Unknown ClariusWifiMode";
96 DISABLED = CusButtonSetting::ButtonDisabled,
97 FREEZE = CusButtonSetting::ButtonFreeze,
98 USER = CusButtonSetting::ButtonUser
101 static std::map<BUTTON_MODE, std::string> ButtonModeEnumToString{
102 {BUTTON_MODE::FREEZE,
"FREEZE"},
103 {BUTTON_MODE::USER,
"USER"},
104 {BUTTON_MODE::DISABLED,
"DISABLED"}
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"},
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;
123 static const int CLARIUS_SHORT_DELAY_MS = 10;
124 static const int CLARIUS_LONG_DELAY_MS = 1000;
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;
136 static const FrameSizeType DEFAULT_FRAME_SIZE = { 512, 512, 1 };
138 static const bool DEFAULT_ENABLE_AUTO_GAIN =
false;
140 static const bool DEFAULT_ENABLE_5V_RAIL =
false;
142 static const bool DEFAULT_FREEZE_ON_POOR_WIFI_SIGNAL =
true;
144 static const bool DEFAULT_KEEP_AWAKE_CHARGING =
true;
146 static const bool DEFAULT_POWER_BUTTONS_ENABLED =
true;
148 static const bool DEFAULT_SOUND_ENABLED =
true;
150 static const int DEFAULT_STATIONARY_TIMEOUT_SEC = 0;
152 static const bool DEFAULT_WAKE_ON_SHAKE =
false;
154 static const bool DEFAULT_FORCE_LOG_SEND =
false;
156 static const bool DEFAULT_PENETRATION_MODE_ENABLED =
false;
158 static const int DEFAULT_CONTACT_DETECTION_TIMEOUT_SEC = 15;
160 static const int DEFAULT_AUTO_FREEZE_TIMEOUT_SEC = 60;
162 static const int DEFAULT_KEEP_AWAKE_TIMEOUT_SEC = 60;
164 static const int DEFAULT_DEEP_SLEEP_TIMEOUT_HR = 0;
166 static const BUTTON_MODE DEFAULT_UP_BUTTON_MODE = BUTTON_MODE::DISABLED;
168 static const BUTTON_MODE DEFAULT_DOWN_BUTTON_MODE = BUTTON_MODE::FREEZE;
170 static const double DEFAULT_DEPTH_MM = 100.0;
172 static const double DEFAULT_GAIN_PERCENT = 80.0;
174 static const double DEFAULT_DYNRANGE_PERCENT = 80.0;
176 static const std::vector<double> DEFAULT_TGC_DB = { 5, 5, 5 };
178 static const bool DEFAULT_ENABLE_AUTO_FOCUS =
false;
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"},
188 static const std::string TRANSD_PORT_NAME =
"Transd";
195 class vtkPlusClariusOEM::vtkInternal
201 virtual ~vtkInternal()
210 static void ListFn(
const char* list,
int sz);
212 static void ConnectFn(CusConnection ret,
int port,
const char* status);
214 static void CertFn(
int daysValid);
216 static void PowerDownFn(CusPowerDown ret,
int tm);
218 static void SwUpdateFn(CusSwUpdate ret);
220 static void RawImageFn(
const void* newImage,
const CusRawImageInfo* nfo,
int npos,
const CusPosInfo* pos);
222 static void ProcessedImageFn(
const void* newImage,
const CusProcessedImageInfo* nfo,
int npos,
const CusPosInfo* pos);
224 static void SpectralImageFn(
const void* newImage,
const CusSpectralImageInfo* nfo);
226 static void ImuDataFn(
const CusPosInfo* pos);
228 static void ImagingFn(CusImagingState ready,
int imaging);
230 static void ButtonFn(CusButton btn,
int clicks);
232 static void ProgressFn(
int progress);
234 static void ErrorFn(CusErrorCode errorCode,
const char* msg);
236 std::string ImagingModeToString(
int mode)
238 if (ImagingModeStrings.find(
mode) != ImagingModeStrings.end())
240 return ImagingModeStrings[
mode];
244 return "Unknown Imaging Mode";
249 void LogUserSettings();
256 std::string ProbeSerialNum;
257 std::string PathToCert;
258 FrameSizeType FrameSize;
259 std::string ProbeType;
260 std::string ImagingApplication;
263 bool FreezeOnPoorWifiSignal;
264 bool KeepAwakeCharging;
265 bool PowerButtonsEnabled;
267 int StationaryTimeoutSec;
270 bool EnablePenetrationMode;
271 int ContactDetectionTimeoutSec;
272 int AutoFreezeTimeoutSec;
273 int KeepAwakeTimeoutMin;
274 int DeepSleepTimeoutHr;
281 std::string Password;
282 std::string IpAddress;
286 std::promise<std::vector<std::string>> PromiseProbes;
287 std::promise<std::vector<std::string>> PromiseApplications;
288 std::promise<void> ConnectionBarrier;
291 std::vector<vtkPlusDataSource*> BModeSources;
292 std::vector<vtkPlusDataSource*> OverlaySources;
296 std::string PressedButton;
302 CusStatusInfo CurrentStatus;
304 bool EnableAutoFocus;
306 enum class EXPECTED_LIST
313 std::string SoftwareUpdateFilename;
314 int SoftwareUpdateHardwareVersion{ 0 };
331 , FrameSize(DEFAULT_FRAME_SIZE)
333 , ImagingApplication(
"")
334 , EnableAutoGain(DEFAULT_ENABLE_AUTO_GAIN)
335 , Enable5v(DEFAULT_ENABLE_5V_RAIL)
336 , FreezeOnPoorWifiSignal(DEFAULT_FREEZE_ON_POOR_WIFI_SIGNAL)
337 , KeepAwakeCharging(DEFAULT_KEEP_AWAKE_CHARGING)
338 , PowerButtonsEnabled(DEFAULT_POWER_BUTTONS_ENABLED)
339 , SoundEnabled(DEFAULT_SOUND_ENABLED)
340 , StationaryTimeoutSec(DEFAULT_STATIONARY_TIMEOUT_SEC)
341 , WakeOnShake(DEFAULT_WAKE_ON_SHAKE)
342 , ForceLogSend(DEFAULT_FORCE_LOG_SEND)
343 , EnablePenetrationMode(DEFAULT_PENETRATION_MODE_ENABLED)
344 , ContactDetectionTimeoutSec(DEFAULT_CONTACT_DETECTION_TIMEOUT_SEC)
345 , AutoFreezeTimeoutSec(DEFAULT_AUTO_FREEZE_TIMEOUT_SEC)
346 , KeepAwakeTimeoutMin(DEFAULT_KEEP_AWAKE_TIMEOUT_SEC)
347 , DeepSleepTimeoutHr(DEFAULT_DEEP_SLEEP_TIMEOUT_HR)
348 , UpButtonMode(DEFAULT_UP_BUTTON_MODE)
349 , DownButtonMode(DEFAULT_DOWN_BUTTON_MODE)
350 , ImagingMode(CusMode::BMode)
353 , TransdSource(nullptr)
354 , PressedButton(NO_BUTTON_TAG)
357 , EnableAutoFocus(DEFAULT_ENABLE_AUTO_FOCUS)
362 void vtkPlusClariusOEM::vtkInternal::ListFn(
const char* list,
int sz)
366 std::vector<std::string> vec;
368 std::stringstream ss(list);
372 getline(ss, substr,
',');
373 vec.push_back(substr);
376 if (device->Internal->ExpectedList == EXPECTED_LIST::PROBES)
378 device->Internal->PromiseProbes.set_value(vec);
380 else if (device->Internal->ExpectedList == EXPECTED_LIST::APPLICATIONS)
382 device->Internal->PromiseApplications.set_value(vec);
387 void vtkPlusClariusOEM::vtkInternal::ConnectFn(CusConnection ret,
int port,
const char* status)
393 case ConnectionError:
394 LOG_ERROR(
"Connection status: error - " << status);
398 LOG_INFO(
"Connection status: probe connected - " << status);
400 case ProbeDisconnected:
401 LOG_INFO(
"Connection status: probe disconnected - " << status);
404 case ConnectionFailed:
405 LOG_ERROR(
"Connection status: connection failed - " << status);
408 case SwUpdateRequired:
409 LOG_INFO(
"Connection status: software update required - " << status);
414 if (ret == CusConnection::ProbeConnected)
417 device->Internal->ConnectionBarrier.set_value();
422 void vtkPlusClariusOEM::vtkInternal::CertFn(
int daysValid)
426 LOG_ERROR(
"Invalid or expired certificate provided for Clarius OEM device");
430 LOG_INFO(
"Clarius certificate is valid for " << daysValid <<
" more days");
435 void vtkPlusClariusOEM::vtkInternal::PowerDownFn(CusPowerDown ret,
int tm)
437 std::stringstream ss;
438 ss <<
"Clarius probe will power down ";
442 ss <<
"immediately as a result of ";
446 ss <<
"in " << tm <<
" seconds as a result of ";
449 if (ret == CusPowerDown::Idle)
451 ss <<
"being idle for an extended period of time. ";
453 else if (ret == CusPowerDown::TooHot)
455 ss <<
"overheating. ";
457 else if (ret == CusPowerDown::LowBattery)
459 ss <<
"running out of battery. ";
461 else if (ret == CusPowerDown::ButtonOff)
463 ss <<
"user holding the shutdown button. ";
467 ss <<
"an unspecified reason. ";
470 ss <<
"If Clarius probe has powered off please turn it back on and restart PLUS, if desired.";
475 void vtkPlusClariusOEM::vtkInternal::SwUpdateFn(CusSwUpdate ret)
482 LOG_ERROR(
"Clarius software update failed");
484 case SwUpdateSuccess:
485 LOG_INFO(
"Clarius software update was successful");
487 case SwUpdateCurrent:
488 LOG_INFO(
"Clarius software is current, no update required");
490 case SwUpdateBattery:
491 LOG_WARNING(
"Clarius software update failed due to low battery, please charge the probe and try again");
493 case SwUpdateUnsupported:
494 LOG_ERROR(
"Clarius software update failed because the firmware being sent is not longer supported by the probe");
496 case SwUpdateCorrupt:
497 LOG_ERROR(
"Clarius software update failed because the probe file system may be corrupt, please contact Clarius support for assistance");
500 LOG_ERROR(
"Clarius software update callback received an unknown status: " << ret);
507 void vtkPlusClariusOEM::vtkInternal::RawImageFn(
const void* newImage,
const CusRawImageInfo* nfo,
int npos,
const CusPosInfo* pos)
509 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");
513 void vtkPlusClariusOEM::vtkInternal::SpectralImageFn(
const void* newImage,
const CusSpectralImageInfo* nfo)
515 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");
519 void vtkPlusClariusOEM::vtkInternal::ImuDataFn(
const CusPosInfo* pos)
521 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");
529 LOG_ERROR(
"Failed to update probe status");
542 if (solumStatusInfo(&this->Internal->CurrentStatus) != 0)
544 LOG_ERROR(
"Failed to retrieve solumStatusInfo");
551 void vtkPlusClariusOEM::vtkInternal::ProcessedImageFn(
const void* oemImage,
const CusProcessedImageInfo* nfo,
int npos,
const CusPosInfo* pos)
556 LOG_ERROR(
"vtkPlusClariusOEM::vtkInternal::ProcessedImageFn called when Clarius instance was NULL!");
566 if (oemImage == NULL)
568 LOG_ERROR(
"NULL frame received by the Clarius OEM device");
573 if (!nfo->overlay && device->Internal->BModeSources.size() == 0)
577 else if (nfo->overlay && device->Internal->OverlaySources.size() == 0)
583 const double unfilteredTimestamp = vtkIGSIOAccurateTimer::GetSystemTime();
585 vtkSmartPointer<vtkImageData> vtkImage = vtkSmartPointer<vtkImageData>::New();
586 vtkNew<vtkInformation> info;
587 vtkImage->SetExtent(0, nfo->width - 1, 0, nfo->height - 1, 0, 1);
588 vtkImage->SetOrigin(0.0, 0.0, 0.0);
589 vtkImage->SetSpacing(1.0, 1.0, 1.0);
591 std::vector<vtkPlusDataSource*> dataSources = device->Internal->BModeSources;
594 dataSources = device->Internal->OverlaySources;
597 for (
auto dataSource : dataSources)
599 if (dataSource->GetImageType() == US_IMG_RGB_COLOR)
601 vtkImage->AllocateScalars(VTK_UNSIGNED_CHAR, 3);
605 (
unsigned char*)oemImage,
606 (
unsigned char*)vtkImage->GetScalarPointer()
617 vtkImage->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
622 (
unsigned char*)oemImage,
623 (
unsigned char*)vtkImage->GetScalarPointer()
630 igsioFieldMapType customFields;
631 customFields[BATTERY_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
632 customFields[BATTERY_FIELD_TAG].second =
std::to_string(device->Internal->CurrentStatus.battery);
633 customFields[TEMP_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
634 customFields[TEMP_FIELD_TAG].second =
std::to_string(device->Internal->CurrentStatus.temperature);
635 customFields[FRAME_RATE_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
636 customFields[FRAME_RATE_FIELD_TAG].second =
std::to_string(device->Internal->CurrentStatus.frameRate);
638 customFields[BUTTON_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
639 customFields[BUTTON_FIELD_TAG].second = device->Internal->PressedButton;
640 customFields[NUM_CLICKS_FIELD_TAG].first = FRAMEFIELD_FORCE_SERVER_SEND;
641 customFields[NUM_CLICKS_FIELD_TAG].second =
std::to_string(device->Internal->ButtonNumClicks);
644 if (device->Internal->ButtonSentCount > 0)
646 --device->Internal->ButtonSentCount;
650 device->Internal->PressedButton = NO_BUTTON_TAG;
651 device->Internal->ButtonNumClicks = 0;
655 for (
auto dataSource : dataSources)
658 vtkImage->GetScalarPointer(),
659 dataSource->GetInputImageOrientation(),
660 dataSource->GetInputFrameSize(),
662 dataSource->GetImageType() == US_IMG_RGB_COLOR ? 3 : 1,
663 dataSource->GetImageType(),
675 if (device->Internal->TransdSource)
677 int i = nfo->width / 2;
678 double transd[2] = { static_cast<double>(
i), 0.0 };
679 for (
int j = 0; j < nfo->height; j++)
681 unsigned char imval = vtkImage->GetScalarComponentAsDouble(
i, j, 0, 0);
690 vtkSmartPointer<vtkMatrix4x4> tsfm = vtkSmartPointer<vtkMatrix4x4>::New();
692 double mmPerPixel = nfo->micronsPerPixel * UM_TO_MM;
693 tsfm->SetElement(0, 0, mmPerPixel);
694 tsfm->SetElement(1, 1, mmPerPixel);
695 tsfm->SetElement(2, 2, mmPerPixel);
696 tsfm->SetElement(0, 3, -transd[0] * mmPerPixel);
697 tsfm->SetElement(1, 3, -transd[1] * mmPerPixel);
698 device->Internal->TransdSource->AddTimeStampedItem(tsfm, TOOL_OK, device->
FrameNumber, unfilteredTimestamp, unfilteredTimestamp, &customFields);
705 void vtkPlusClariusOEM::vtkInternal::ImagingFn(CusImagingState ready,
int imaging)
707 if (ready == CusImagingState::ImagingNotReady)
709 LOG_WARNING(
"Clarius imaging is not ready yet...");
711 else if (ready == CusImagingState::ImagingReady)
713 LOG_INFO(
"Clarius imaging is " << (imaging ?
"running" :
"stopped"));
715 else if (ready == CusImagingState::CertExpired)
717 LOG_ERROR(
"Clarius certificate needs to be updated prior to imaging");
719 else if (ready == CusImagingState::PoorWifi)
721 LOG_WARNING(
"Clarius imaging stopped as a result of a poor Wi-Fi connection");
723 else if (ready == CusImagingState::NoContact)
725 LOG_INFO(
"Clarius imaging stopped as a result of no patient contact for specified timeout duration");
727 else if (ready == CusImagingState::ChargingChanged)
729 LOG_WARNING(
"Clarius imaging " << (imaging ?
"started" :
"stopped") <<
" due to a change in charging status");
731 else if (ready == CusImagingState::LowBandwidth)
733 LOG_INFO(
"Clarius low bandwidth was detected, imaging parameters were adjusted");
735 else if (ready == CusImagingState::MotionSensor)
737 LOG_INFO(
"Clarius imaging " << (imaging ?
"started" :
"stopped") <<
" due to change in motion sensor");
741 LOG_ERROR(
"Clarius ImagingFn called with unknown 'ready' state");
749 void vtkPlusClariusOEM::vtkInternal::ButtonFn(CusButton btn,
int clicks)
754 LOG_ERROR(
"vtkPlusClariusOEM::vtkInternal::ButtonFn called when Clarius instance was NULL!");
761 LOG_ERROR(
"ClariusOEM device unexpectedly disconnected from Clarius Device. IpAddress = " << device->Internal->IpAddress
762 <<
" Port = " << device->Internal->TcpPort);
767 device->Internal->ButtonNumClicks = clicks;
768 if (btn == CusButton::ButtonDown)
770 device->Internal->PressedButton = DOWN_BUTTON_TAG;
772 else if (btn == CusButton::ButtonUp)
774 device->Internal->PressedButton = UP_BUTTON_TAG;
778 LOG_WARNING(
"Unexpected Clarius button value of " << btn <<
" received in vtkPlusClariusOEM::vtkInternal::ButtonFn");
782 device->Internal->ButtonSentCount = SEND_BUTTON_STATE_FOR_N_FRAMES;
788 void vtkPlusClariusOEM::vtkInternal::ProgressFn(
int progress)
790 LOG_INFO(
"Updating: " << progress <<
"%");
797 void vtkPlusClariusOEM::vtkInternal::ErrorFn(CusErrorCode errorCode,
const char* err)
799 std::stringstream errorSS;
800 errorSS <<
"Clarius OEM ";
804 errorSS <<
"generic error";
807 errorSS <<
"setup error";
810 errorSS <<
"probe error";
812 case ErrorApplication:
813 errorSS <<
"application load error";
816 errorSS <<
"software update error";
819 errorSS <<
"GL error";
822 errorSS <<
"raw data error";
825 errorSS <<
"unknown error code" << errorCode;
828 errorSS <<
": " << err;
829 LOG_ERROR(errorSS.str());
833 void vtkPlusClariusOEM::vtkInternal::LogUserSettings()
835 std::stringstream ss;
836 ss <<
"ProbeSerialNum: " << this->ProbeSerialNum << std::endl;
837 ss <<
"PathToCert: " << this->PathToCert << std::endl;
838 ss <<
"ProbeType: " << this->ProbeType << std::endl;
839 ss <<
"ImagingApplication: " << this->ImagingApplication << std::endl;
840 ss <<
"FrameSize: [" << this->FrameSize[0] <<
", " << this->FrameSize[1] <<
", " << this->FrameSize[2] <<
"]" << std::endl;
841 ss <<
"EnableAutoGain: " << (this->EnableAutoGain ?
"TRUE" :
"FALSE") << std::endl;
842 ss <<
"EnableAutoFocus: " << (this->EnableAutoFocus ?
"TRUE" :
"FALSE") << std::endl;
843 ss <<
"Enable5v: " << (this->Enable5v ?
"TRUE" :
"FALSE") << std::endl;
844 ss <<
"EnablePenetrationMode: " << (this->EnablePenetrationMode ?
"TRUE" :
"FALSE") << std::endl;
845 ss <<
"FreezeOnPoorWifiSignal: " << (this->FreezeOnPoorWifiSignal ?
"TRUE" :
"FALSE") << std::endl;
846 ss <<
"KeepAwakeCharging: " << (this->KeepAwakeCharging ?
"TRUE" :
"FALSE") << std::endl;
847 ss <<
"PowerButtonsEnabled: " << (this->PowerButtonsEnabled ?
"TRUE" :
"FALSE") << std::endl;
848 ss <<
"SoundEnabled: " << (this->SoundEnabled ?
"TRUE" :
"FALSE") << std::endl;
849 ss <<
"StationaryTimeoutSec: " << this->StationaryTimeoutSec << std::endl;
850 ss <<
"WakeOnShake: " << (this->WakeOnShake ?
"TRUE" :
"FALSE") << std::endl;
851 ss <<
"ForceLogSend: " << (this->ForceLogSend ?
"TRUE" :
"FALSE") << std::endl;
852 ss <<
"EnablePenetrationMode: " << (this->EnablePenetrationMode ?
"TRUE" :
"FALSE") << std::endl;
853 ss <<
"ContactDetectionTimeoutSec: " << this->ContactDetectionTimeoutSec << std::endl;
854 ss <<
"AutoFreezeTimeoutSec: " << this->AutoFreezeTimeoutSec << std::endl;
855 ss <<
"KeepAwakeTimeoutMin: " << this->KeepAwakeTimeoutMin << std::endl;
856 ss <<
"UpButtonMode: " << ButtonModeEnumToString[this->UpButtonMode] << std::endl;
857 ss <<
"DownButtonMode: " << ButtonModeEnumToString[this->DownButtonMode] << std::endl;
858 ss <<
"ImagingMode: " << this->ImagingModeToString(this->ImagingMode) << std::endl;
860 LOG_INFO(std::endl <<
"User settings:" << std::endl << ss.str());
868 if (instance == NULL)
877 : Internal(new vtkInternal(this))
903 delete this->Internal;
904 this->Internal =
nullptr;
907 this->instance = NULL;
913 if (instance != NULL)
928 LOG_TRACE(
"vtkPlusClariusOEM::PrintSelf");
931 os << indent <<
"ProbeSerialNum: " << this->Internal->ProbeSerialNum << std::endl;
932 os << indent <<
"PathToCert: " << this->Internal->PathToCert << std::endl;
933 os << indent <<
"ProbeType: " << this->Internal->ProbeType << std::endl;
934 os << indent <<
"ImagingApplication: " << this->Internal->ImagingApplication << std::endl;
935 os << indent <<
"FrameSize: [" << this->Internal->FrameSize[0] <<
", " << this->Internal->FrameSize[1] <<
", " << this->Internal->FrameSize[2] <<
"]" << std::endl;
936 os << indent <<
"EnableAutoGain: " << (this->Internal->EnableAutoGain ?
"TRUE" :
"FALSE") << std::endl;
937 os << indent <<
"Enable5v: " << (this->Internal->Enable5v ?
"TRUE" :
"FALSE") << std::endl;
938 os << indent <<
"FreezeOnPoorWifiSignal: " << (this->Internal->FreezeOnPoorWifiSignal ?
"TRUE" :
"FALSE") << std::endl;
939 os << indent <<
"KeepAwakeCharging: " << (this->Internal->KeepAwakeCharging ?
"TRUE" :
"FALSE") << std::endl;
940 os << indent <<
"PowerButtonsEnabled: " << (this->Internal->PowerButtonsEnabled ?
"TRUE" :
"FALSE") << std::endl;
941 os << indent <<
"SoundEnabled: " << (this->Internal->SoundEnabled ?
"TRUE" :
"FALSE") << std::endl;
942 os << indent <<
"StationaryTimeoutSec: " << this->Internal->StationaryTimeoutSec << std::endl;
943 os << indent <<
"WakeOnShake: " << (this->Internal->WakeOnShake ?
"TRUE" :
"FALSE") << std::endl;
944 os << indent <<
"ForceLogSend: " << (this->Internal->ForceLogSend ?
"TRUE" :
"FALSE") << std::endl;
945 os << indent <<
"EnablePenetrationMode: " << (this->Internal->EnablePenetrationMode ?
"TRUE" :
"FALSE") << std::endl;
946 os << indent <<
"ContactDetectionTimeoutSec: " << this->Internal->ContactDetectionTimeoutSec << std::endl;
947 os << indent <<
"AutoFreezeTimeoutSec: " << this->Internal->AutoFreezeTimeoutSec << std::endl;
948 os << indent <<
"KeepAwakeTimeoutMin: " << this->Internal->KeepAwakeTimeoutMin << std::endl;
949 os << indent <<
"UpButtonMode: " << ButtonModeEnumToString[this->Internal->UpButtonMode] << std::endl;
950 os << indent <<
"DownButtonMode: " << ButtonModeEnumToString[this->Internal->DownButtonMode] << std::endl;
951 os << indent <<
"ImagingMode: " << this->Internal->ImagingModeToString(this->Internal->ImagingMode) << std::endl;
957 LOG_TRACE(
"vtkPlusClariusOEM::ReadConfiguration");
962 XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
963 ProbeSerialNum, this->Internal->ProbeSerialNum, deviceConfig);
966 XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
967 PathToCert, this->Internal->PathToCert, deviceConfig);
970 XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
971 ProbeType, this->Internal->ProbeType, deviceConfig);
974 this->Internal->ProbeType.begin(),
975 this->Internal->ProbeType.end(),
976 this->Internal->ProbeType.begin(),
977 [](
unsigned char c) {
return std::toupper(c); }
981 XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
982 ImagingApplication, this->Internal->ImagingApplication, deviceConfig);
985 this->Internal->ImagingApplication.begin(),
986 this->Internal->ImagingApplication.end(),
987 this->Internal->ImagingApplication.begin(),
988 [](
unsigned char c) {
return std::tolower(c); }
992 int rfs[2] = { static_cast<int>(DEFAULT_FRAME_SIZE[0]), static_cast<int>(DEFAULT_FRAME_SIZE[1]) };
993 if (deviceConfig->GetVectorAttribute(
"FrameSize", 2, rfs))
995 if (rfs[0] < 0 || rfs[1] < 0)
997 LOG_ERROR(
"Negative frame size defined in config file. Please define a positive frame size.");
1000 FrameSizeType fs = { static_cast<unsigned int>(rfs[0]), static_cast<unsigned int>(rfs[1]), 1 };
1001 this->Internal->FrameSize = fs;
1005 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnableAutoGain,
1006 this->Internal->EnableAutoGain, deviceConfig);
1009 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(Enable5v,
1010 this->Internal->Enable5v, deviceConfig);
1013 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(FreezeOnPoorWifiSignal,
1014 this->Internal->FreezeOnPoorWifiSignal, deviceConfig);
1017 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(KeepAwakeCharging,
1018 this->Internal->KeepAwakeCharging, deviceConfig);
1021 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(PowerButtonsEnabled,
1022 this->Internal->PowerButtonsEnabled, deviceConfig);
1025 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(SoundEnabled,
1026 this->Internal->SoundEnabled, deviceConfig);
1029 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, StationaryTimeoutSec,
1030 this->Internal->StationaryTimeoutSec, deviceConfig);
1033 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(WakeOnShake,
1034 this->Internal->WakeOnShake, deviceConfig);
1037 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(ForceLogSend,
1038 this->Internal->ForceLogSend, deviceConfig);
1041 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnablePenetrationMode,
1042 this->Internal->EnablePenetrationMode, deviceConfig);
1045 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, ContactDetectionTimeoutSec,
1046 this->Internal->ContactDetectionTimeoutSec, deviceConfig);
1049 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, AutoFreezeTimeoutSec,
1050 this->Internal->AutoFreezeTimeoutSec, deviceConfig);
1053 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, KeepAwakeTimeoutMin,
1054 this->Internal->KeepAwakeTimeoutMin, deviceConfig);
1057 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, DeepSleepTimeoutHr,
1058 this->Internal->DeepSleepTimeoutHr, deviceConfig);
1061 XML_READ_ENUM3_ATTRIBUTE_NONMEMBER_OPTIONAL(UpButtonMode,
1062 this->Internal->UpButtonMode, deviceConfig,
1063 "FREEZE", BUTTON_MODE::FREEZE,
1064 "USER", BUTTON_MODE::USER,
1065 "DISABLED", BUTTON_MODE::DISABLED
1069 XML_READ_ENUM3_ATTRIBUTE_NONMEMBER_OPTIONAL(DownButtonMode,
1070 this->Internal->DownButtonMode, deviceConfig,
1071 "FREEZE", BUTTON_MODE::FREEZE,
1072 "USER", BUTTON_MODE::USER,
1073 "DISABLED", BUTTON_MODE::DISABLED
1077 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnableAutoFocus,
1078 this->Internal->EnableAutoFocus, deviceConfig);
1081 XML_READ_ENUM_ATTRIBUTE_NONMEMBER_OPTIONAL(ImagingMode, this->Internal->ImagingMode, deviceConfig, this->Internal->ImagingModeToString, 0, ImagingModeStrings.size());
1087 XML_FIND_NESTED_ELEMENT_REQUIRED(dataSourcesElement, deviceConfig,
"DataSources");
1088 int numSources = dataSourcesElement->GetNumberOfNestedElements();
1089 for (
int i = 0;
i < numSources; ++
i)
1091 vtkXMLDataElement* element = dataSourcesElement->GetNestedElement(
i);
1092 if (!igsioCommon::IsEqualInsensitive(element->GetName(),
"DataSource"))
1100 const char* type = element->GetAttribute(
"Type");
1101 if (type && igsioCommon::IsEqualInsensitive(type,
"Video"))
1103 const char* orientation = element->GetAttribute(
"PortUsImageOrientation");
1104 if (orientation && !igsioCommon::IsEqualInsensitive(orientation,
"UF"))
1106 LOG_WARNING(
"Clarius image source has unexpected value '" << orientation <<
"' for PortUsImageOrientation. Please confirm your image orientation, expected value for most Clarius probes is 'UF'.");
1111 if (type && igsioCommon::IsEqualInsensitive(type,
"Tool"))
1113 const char* toolId = element->GetAttribute(
"Id");
1116 LOG_ERROR(
"Failed to initialize Clarius OEM transform: DataSource Id is missing");
1120 const char* portName = element->GetAttribute(
"PortName");
1121 if (portName && !igsioCommon::IsEqualInsensitive(portName, TRANSD_PORT_NAME))
1123 LOG_ERROR(
"Clarius OEM device only supports Tool items with PortName=\"" 1124 << TRANSD_PORT_NAME <<
"\"");
1130 std::string transdSourceId = transdTransformName.GetTransformName();
1131 if (this->
GetTool(transdSourceId, this->Internal->TransdSource) !=
PLUS_SUCCESS || this->Internal->TransdSource == NULL)
1133 LOG_ERROR(
"Failed to get ClariusOEM tool: " << transdSourceId);
1139 XML_READ_STRING_ATTRIBUTE_NONMEMBER_OPTIONAL(
1140 SoftwareUpdateFilename, this->Internal->SoftwareUpdateFilename, deviceConfig);
1141 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
1142 int, SoftwareUpdateHardwareVersion, this->Internal->SoftwareUpdateHardwareVersion, deviceConfig);
1154 LOG_TRACE(
"vtkPlusClariusOEM::WriteConfiguration");
1166 LOG_TRACE(
"vtkPlusClariusOEM::NotifyConfigured");
1171 LOG_WARNING(
"vtkPlusClariusOEM is expecting one output channel and there are " <<
1172 this->
OutputChannels.size() <<
" channels. First output channel will be used.");
1177 LOG_ERROR(
"No output channels defined for vtkPlusClariusOEM. Cannot proceed.");
1182 std::vector<vtkPlusDataSource*> sources;
1184 if (sources.size() > 1)
1186 LOG_WARNING(
"More than one output video source found. First will be used");
1188 if (sources.size() == 0)
1190 LOG_ERROR(
"Video source required in configuration. Cannot proceed.");
1198 LOG_ERROR(
"Unable to retrieve the video source in the vtkPlusClariusOEM device.");
1208 LOG_TRACE(
"vtkPlusClariusOEM: Probe");
1209 LOG_ERROR(
"vtkPlusClariusOEM::Probe() is not implemented");
1217 LOG_TRACE(
"vtkPlusClariusOEM::GetSdkVersion");
1218 return "SDK version not available";
1224 LOG_TRACE(
"vtkPlusClariusOEM::InitializeBLE");
1227 if (!this->Internal->BleHelper.FindBySerial(this->Internal->ProbeSerialNum))
1229 LOG_ERROR(
"Failed to find BLE connection for Clarius probe with serial number " 1230 << this->Internal->ProbeSerialNum <<
". Please make sure the probe is charged" 1231 ", paired, and in range for BLE.");
1233 std::vector<std::string> probes = this->Internal->BleHelper.RetrieveFoundProbeIds();
1238 LOG_ERROR(
"No active Clarius probes found within BLE range");
1243 std::stringstream ss;
1244 ss <<
"Clarius probes configured with Windows Bluetooth are:" << std::endl;
1245 for (
const std::string& probe : probes)
1247 ss <<
"\t" << probe << std::endl;
1249 LOG_ERROR(ss.str());
1254 LOG_INFO(
"Connecting to BLE network of Clarius probe with SN: " << this->Internal->ProbeSerialNum);
1255 if (this->Internal->BleHelper.Connect() !=
PLUS_SUCCESS)
1257 LOG_ERROR(
"Failed to connect to Clarius probe. Last error was: " 1258 << this->Internal->BleHelper.GetLastError());
1263 if (!this->Internal->BleHelper.IsProbeConnected())
1265 LOG_ERROR(
"Failed to connect to Clarius probe. Last error was: " 1266 << this->Internal->BleHelper.GetLastError());
1277 LOG_TRACE(
"vtkPlusClariusOEM::InitializeProbe");
1280 if (this->Internal->BleHelper.RequestProbeOn() !=
PLUS_SUCCESS)
1282 LOG_ERROR(
"An error occurred during RequestProbeOn. Last error was: " 1283 << this->Internal->BleHelper.GetLastError());
1288 if (!this->Internal->BleHelper.AwaitWifiInfoReady())
1290 LOG_ERROR(
"Timeout occurred while waiting for Clarius probe to power on." 1291 <<
" Last error was: " << this->Internal->BleHelper.GetLastError());
1296 if (this->Internal->BleHelper.ConfigureWifiAP() !=
PLUS_SUCCESS)
1298 LOG_ERROR(
"An error occurred during ConfigureWifiAP. Last error was: " 1299 << this->Internal->BleHelper.GetLastError());
1304 std::pair<bool, ClariusWifiInfo> infoPair = this->Internal->BleHelper.GetWifiInfo();
1305 if (!infoPair.first)
1307 LOG_ERROR(
"An error occurred during GetWifiInfo. Last error was: " 1308 << this->Internal->BleHelper.GetLastError());
1315 LOG_ERROR(
"Wifi was not ready when connection info was requested");
1320 std::stringstream infoStream;
1323 infoStream <<
"\tSSID: " << info.
SSID << std::endl;
1324 infoStream <<
"\tPassword: " << info.
Password << std::endl;
1325 infoStream <<
"\tIPv4: " << info.
IPv4 << std::endl;
1326 infoStream <<
"\tMac Address: " << info.
MacAddress << std::endl;
1327 infoStream <<
"\tControl Port: " << info.
ControlPort << std::endl;
1328 infoStream <<
"\tCast Port: " << info.
CastPort << std::endl;
1329 infoStream <<
"\tChannel: " << info.
Channel << std::endl;
1331 LOG_INFO(
"Clarius Wifi Info: " << std::endl << infoStream.str());
1333 this->Internal->Ssid = info.
SSID;
1334 this->Internal->Password = info.
Password;
1335 this->Internal->IpAddress = info.
IPv4;
1339 if (this->Internal->Ssid[0] ==
'"')
1341 this->Internal->Ssid = this->Internal->Ssid.substr(1, this->Internal->Ssid.size() - 2);
1344 if (this->Internal->Password[0] ==
'"')
1346 this->Internal->Password = this->Internal->Password.substr(1, this->Internal->Password.size() - 2);
1349 if (this->Internal->IpAddress[0] ==
'"')
1351 this->Internal->IpAddress = this->Internal->IpAddress.substr(1, this->Internal->IpAddress.size() - 2);
1362 LOG_TRACE(
"vtkPlusClariusOEM::InitializeWifi");
1364 if (this->Internal->WifiHelper.Initialize() !=
PLUS_SUCCESS)
1366 LOG_ERROR(
"Failed to initialize Clarius wifi helper");
1370 PlusStatus res = this->Internal->WifiHelper.ConnectToClariusWifi(
1371 this->Internal->Ssid,
1372 this->Internal->Password
1376 LOG_ERROR(
"Failed to connect to Clarius probe wifi");
1386 LOG_TRACE(
"vtkPlusClariusOEM::InitializeOEM");
1390 char** argv =
new char* [1];
1391 argv[0] =
new char[4];
1392 strcpy(argv[0],
"abc");
1393 const char* certPath =
"/Clarius";
1396 CusListFn listFnPtr = static_cast<CusListFn>(&vtkPlusClariusOEM::vtkInternal::ListFn);
1397 CusConnectFn connectFnPtr = static_cast<CusConnectFn>(&vtkPlusClariusOEM::vtkInternal::ConnectFn);
1398 CusCertFn certFnPtr = static_cast<CusCertFn>(&vtkPlusClariusOEM::vtkInternal::CertFn);
1399 CusPowerDownFn powerDownFnPtr = static_cast<CusPowerDownFn>(&vtkPlusClariusOEM::vtkInternal::PowerDownFn);
1400 CusNewRawImageFn newRawImageFnPtr = static_cast<CusNewRawImageFn>(&vtkPlusClariusOEM::vtkInternal::RawImageFn);
1401 CusNewProcessedImageFn newProcessedImageFnPtr = static_cast<CusNewProcessedImageFn>(&vtkPlusClariusOEM::vtkInternal::ProcessedImageFn);
1402 CusNewSpectralImageFn newSpectralImageFnPtr = static_cast<CusNewSpectralImageFn>(&vtkPlusClariusOEM::vtkInternal::SpectralImageFn);
1403 CusNewImuDataFn newImuDataFnPtr = static_cast<CusNewImuDataFn>(&vtkPlusClariusOEM::vtkInternal::ImuDataFn);
1404 CusImagingFn imagingFnPtr = static_cast<CusImagingFn>(&vtkPlusClariusOEM::vtkInternal::ImagingFn);
1405 CusButtonFn buttonFnPtr = static_cast<CusButtonFn>(&vtkPlusClariusOEM::vtkInternal::ButtonFn);
1406 CusErrorFn errorFnPtr = static_cast<CusErrorFn>(&vtkPlusClariusOEM::vtkInternal::ErrorFn);
1409 std::vector<vtkPlusDataSource*> bModeSources;
1411 if (this->Internal->BModeSources.empty() && this->Internal->OverlaySources.empty())
1413 newProcessedImageFnPtr =
nullptr;
1417 std::vector<vtkPlusDataSource*> rfModeSources;
1419 if (rfModeSources.empty())
1421 newRawImageFnPtr =
nullptr;
1426 FrameSizeType fs = this->Internal->FrameSize;
1427 CusInitParams initParams;
1428 initParams.storeDir = certPath;
1429 initParams.connectFn = connectFnPtr;
1430 initParams.certFn = certFnPtr;
1431 initParams.powerDownFn = powerDownFnPtr;
1432 initParams.newRawImageFn = newRawImageFnPtr;
1433 initParams.newProcessedImageFn = newProcessedImageFnPtr;
1434 initParams.newSpectralImageFn = newSpectralImageFnPtr;
1435 initParams.newImuDataFn = newImuDataFnPtr;
1436 initParams.imagingFn = imagingFnPtr;
1437 initParams.buttonFn = buttonFnPtr;
1438 initParams.errorFn = errorFnPtr;
1439 initParams.newImuPortFn =
nullptr;
1440 initParams.newImuDataFn =
nullptr;
1441 initParams.width = fs[0];
1442 initParams.height = fs[1];
1444 CusInitParams::Args initArgs;
1445 initArgs.argc = argc;
1446 initArgs.argv = argv;
1447 initParams.args = initArgs;
1449 int result = solumInit(&initParams);
1451 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1455 LOG_ERROR(
"Failed to initialize Clarius OEM library");
1459 catch (
const std::runtime_error& re)
1461 LOG_ERROR(
"Runtime error on solumInit. Error text: " << re.what());
1464 catch (
const std::exception& ex)
1466 LOG_ERROR(
"Exception on solumInit. Error text: " << ex.what());
1471 LOG_ERROR(
"Unknown failure occurred on solumInit");
1482 LOG_TRACE(
"vtkPlusClariusOEM::SetClariusCert");
1486 std::ifstream certFile(fullCertPath);
1487 if (!certFile.is_open())
1489 LOG_ERROR(
"Failed to open Clarius cert file from " << fullCertPath <<
". Please check the PathToCert path in your config.");
1493 std::ostringstream sstr;
1494 sstr << certFile.rdbuf();
1495 std::string certStr = sstr.str();
1498 if (solumSetCert(certStr.c_str()) != 0)
1500 LOG_ERROR(
"Failed to set Clarius OEM connection certificate");
1503 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1511 const char* ip = this->Internal->IpAddress.c_str();
1512 unsigned int port = this->Internal->TcpPort;
1513 LOG_INFO(
"Attempting connection to Clarius ultrasound on " << ip <<
":" <<
port <<
" for 25 seconds:");
1515 std::future<void> connectionBarrierFuture = this->Internal->ConnectionBarrier.get_future();
1518 CusConnectionParams connParams;
1519 connParams.ipAddress = ip;
1520 connParams.port =
port;
1521 int result = solumConnect(&connParams);
1522 if (result != CusConnection::ProbeConnected)
1524 LOG_ERROR(
"Failed to initiate connection to Clarius probe on " << ip <<
":" <<
port <<
1525 ". Return code: " << ConnectEnumToString[result]);
1529 catch (
const std::runtime_error& re)
1531 LOG_ERROR(
"Runtime error on solumConnect. Error text: " << re.what());
1534 catch (
const std::exception& ex)
1536 LOG_ERROR(
"Exception on solumConnect. Error text: " << ex.what());
1541 LOG_ERROR(
"Unknown failure occurred on solumConnect");
1546 if (connectionBarrierFuture.wait_for(std::chrono::seconds(25)) != std::future_status::ready)
1548 LOG_ERROR(
"Connection to Clarius device timed out");
1551 LOG_INFO(
"Connected to Clarius probe on " << ip <<
":" <<
port);
1554 CusListFn listFnPtr = static_cast<CusListFn>(&vtkPlusClariusOEM::vtkInternal::ListFn);
1555 this->Internal->ExpectedList = vtkPlusClariusOEM::vtkInternal::EXPECTED_LIST::PROBES;
1556 std::future<std::vector<std::string>> futureProbes = this->Internal->PromiseProbes.get_future();
1557 if (solumProbes(listFnPtr) != 0)
1559 LOG_INFO(
"Failed to retrieve list of valid probe types");
1562 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1565 if (futureProbes.wait_for(std::chrono::seconds(5)) != std::future_status::ready)
1567 LOG_ERROR(
"Failed to retrieve list of valid Clarius probe names");
1570 std::vector<std::string> vProbes = futureProbes.get();
1573 std::string probeType = this->Internal->ProbeType;
1574 if (std::find(vProbes.begin(), vProbes.end(), probeType) == vProbes.end())
1576 std::string vProbesStr;
1577 for (
const auto& probe : vProbes)
1579 vProbesStr += probe +
", ";
1581 vProbesStr.pop_back(); vProbesStr.pop_back();
1582 LOG_ERROR(
"Invalid probe type (" << probeType <<
") provided, valid probe types are: " << vProbesStr);
1587 this->Internal->ExpectedList = vtkPlusClariusOEM::vtkInternal::EXPECTED_LIST::APPLICATIONS;
1588 std::future<std::vector<std::string>> futureApplications = this->Internal->PromiseApplications.get_future();
1589 if (solumApplications(probeType.c_str(), listFnPtr) != 0)
1591 LOG_ERROR(
"Failed to retrieve list of valid imaging applications");
1594 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1597 if (futureApplications.wait_for(std::chrono::seconds(5)) != std::future_status::ready)
1599 LOG_ERROR(
"Failed to retrieve list of valid Clarius application names");
1602 std::vector<std::string> vApps = futureApplications.get();
1605 std::string imagingApplication = this->Internal->ImagingApplication;
1606 if (std::find(vApps.begin(), vApps.end(), imagingApplication) == vApps.end())
1608 std::string vAppsStr;
1609 for (
const auto& app : vApps)
1611 vAppsStr += app +
", ";
1613 vAppsStr.pop_back(); vAppsStr.pop_back();
1614 LOG_ERROR(
"Invalid imaging application (" << imagingApplication <<
") provided, valid imaging applications are: " << vAppsStr);
1619 if (solumLoadApplication(probeType.c_str(), imagingApplication.c_str()) == 0)
1621 LOG_INFO(
"Loaded " << imagingApplication <<
" application on a " << probeType <<
" probe");
1625 LOG_ERROR(
"An error occured on call to solumLoadApplication");
1627 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1635 LOG_TRACE(
"vtkPlusClariusOEM::SetInitialUsParams");
1641 LOG_WARNING(
"Failed to set requested imaging depth (mm) in Clarius OEM device, unknown depth will be used");
1648 LOG_WARNING(
"Failed to set requested imaging gain (%) in Clarius OEM device, unknown gain will be used");
1655 LOG_WARNING(
"Failed to set requested imaging dynamic range in Clarius OEM device, unknown dynamic range will be used");
1662 LOG_WARNING(
"Failed to set requested imaging time gain compensation in Clarius OEM device, unknown time gain compensation will be used");
1667 LOG_WARNING(
"Failed to set auto focus");
1672 LOG_WARNING(
"Failed to set auto gain");
1677 LOG_WARNING(
"Failed to set penetration mode");
1686 LOG_TRACE(
"vtkPlusClariusOEM::InternalConnect");
1695 this->Internal->LogUserSettings();
1700 LOG_ERROR(
"Failed to initialize BLE in Clarius OEM device");
1708 LOG_ERROR(
"Failed to initialize probe (power, wifi settings) in Clarius OEM device");
1716 LOG_ERROR(
"Failed to initialize wifi in Clarius OEM device");
1724 LOG_ERROR(
"Failed to initialize OEM library in Clarius OEM device");
1732 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");
1738 CusProbeSettings settings;
1739 settings.contactDetection = this->Internal->ContactDetectionTimeoutSec;
1740 settings.autoFreeze = this->Internal->AutoFreezeTimeoutSec;
1741 settings.keepAwake = this->Internal->KeepAwakeTimeoutMin;
1742 settings.deepSleep = this->Internal->DeepSleepTimeoutHr;
1743 settings.stationary = this->Internal->StationaryTimeoutSec;
1744 settings.wifiOptimization = this->Internal->FreezeOnPoorWifiSignal;
1747 settings.keepAwakeCharging = this->Internal->KeepAwakeCharging;
1748 settings.powerOn = this->Internal->PowerButtonsEnabled;
1749 settings.sounds = this->Internal->SoundEnabled;
1750 settings.wakeOnShake = this->Internal->WakeOnShake;
1752 settings.forceLogSend = this->Internal->ForceLogSend;
1753 settings.up = static_cast<CusButtonSetting>(this->Internal->UpButtonMode);
1754 settings.down = static_cast<CusButtonSetting>(this->Internal->DownButtonMode);
1755 settings.handle = CusButtonSetting::ButtonDisabled;
1756 settings.upHold = CusButtonHoldSetting::ButtonHoldDisabled;
1757 settings.downHold = CusButtonHoldSetting::ButtonHoldShutdown;
1758 if (solumSetProbeSettings(&settings) != 0)
1760 LOG_ERROR(
"Failed to set Clarius OEM probe settings");
1763 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1768 LOG_ERROR(
"Failed to configure Clarius probe application");
1775 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1777 CusProbeInfo probeInfo;
1778 if (solumProbeInfo(&probeInfo) != 0)
1780 LOG_WARNING(
"Failed to retrieve solumProbeInfo");
1782 std::stringstream ss;
1783 ss <<
"Version: " << probeInfo.version << std::endl;
1784 ss <<
"Battery: " << this->Internal->CurrentStatus.battery <<
"%" << std::endl;
1785 ss <<
"Temperature: " << this->Internal->CurrentStatus.temperature <<
"%" << std::endl;
1786 ss <<
"Elements: " << probeInfo.elements << std::endl;
1787 ss <<
"Pitch: " << probeInfo.pitch << std::endl;
1788 ss <<
"Radius: " << probeInfo.radius <<
"mm" << std::endl;
1789 LOG_INFO(std::endl <<
"Probe info: " << std::endl << ss.str());
1791 char versionStringV1[128] = {};
1792 solumFwVersion(CusPlatform::V1, versionStringV1, 128);
1793 LOG_DEBUG(
"Current Clarius V1 firmware version:\t" << versionStringV1);
1794 char versionStringHD[128] = {};
1795 solumFwVersion(CusPlatform::HD, versionStringHD, 128);
1796 LOG_DEBUG(
"Current Clarius HD firmware version:\t" << versionStringHD);
1797 char versionStringHD3[128] = {};
1798 solumFwVersion(CusPlatform::HD3, versionStringHD3, 128);
1799 LOG_DEBUG(
"Current Clarius HD3 firmware version:\t" << versionStringHD3);
1801 if (this->Internal->SoftwareUpdateFilename !=
"")
1803 CusSwUpdateFn swUpdateFnPtr = static_cast<CusSwUpdateFn>(&vtkPlusClariusOEM::vtkInternal::SwUpdateFn);
1804 CusProgressFn progressFnPtr = static_cast<CusProgressFn>(&vtkPlusClariusOEM::vtkInternal::ProgressFn);
1807 if (solumSoftwareUpdate(this->Internal->SoftwareUpdateFilename.c_str(),
1808 swUpdateFnPtr, progressFnPtr, this->Internal->SoftwareUpdateHardwareVersion) != 0)
1810 LOG_ERROR(
"Failed to update Clarius firmware");
1811 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1819 int enable5v = this->Internal->Enable5v ? 1 : 0;
1820 if (solumEnable5v(enable5v) < 0)
1822 std::string enstr = (enable5v ?
"TRUE" :
"FALSE");
1823 LOG_WARNING(
"Failed to set the state of the Clarius probe 5v rail, provided enable value was: " << enstr);
1825 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1830 CusMode
mode = CusMode(this->Internal->ImagingMode);
1831 if (solumSetMode(
mode) != 0)
1833 LOG_ERROR(
"Failed to set Clarius OEM imaging mode");
1838 if (solumSeparateOverlays(1) != 0)
1840 LOG_ERROR(
"Failed to set Clarius separate overlays");
1850 LOG_TRACE(
"vtkPlusClariusOEM::DeInitializeOEM");
1852 int oemState = solumIsConnected();
1862 LOG_WARNING(
"Failed to disable Clarius 5v");
1865 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1868 LOG_WARNING(
"Failed to stop Clarius imaging");
1871 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1872 if (solumDisconnect() < 0)
1874 LOG_WARNING(
"Failed to disconnect from Clarius OEM library");
1878 if (solumDestroy() < 0)
1880 LOG_WARNING(
"Failed to destroy Clarius OEM library");
1887 LOG_TRACE(
"vtkPlusClariusOEM::DeInitializeWifi");
1889 if (!this->Internal->WifiHelper.DisconnectFromClariusWifi())
1891 LOG_WARNING(
"Failed to disconnect from Clarius wifi");
1893 if (!this->Internal->WifiHelper.DeInitialize())
1895 LOG_WARNING(
"Failed to de-initialize ClariusWifi");
1902 LOG_TRACE(
"vtkPlusClariusOEM::DeInitializeProbe");
1905 if (!this->Internal->BleHelper.IsProbeConnected())
1910 if (this->Internal->BleHelper.RequestProbeOff() !=
PLUS_SUCCESS)
1912 LOG_ERROR(
"An error occurred during RequestProbeOff. Last error was: " 1913 << this->Internal->BleHelper.GetLastError())
1920 LOG_TRACE(
"vtkPlusClariusOEM::DeInitializeBLE");
1923 if (this->Internal->BleHelper.Disconnect() !=
PLUS_SUCCESS)
1925 LOG_ERROR(
"An error occurred during Clarius BLE Disconnect. Last error was: " 1926 << this->Internal->BleHelper.GetLastError());
1933 LOG_TRACE(
"vtkPlusClariusOEM::InternalDisconnect");
1947 LOG_TRACE(
"vtkPlusClariusOEM::InternalStartRecording");
1951 bool running =
false;
1952 for (
int i = 0;
i < 10; ++
i)
1957 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1965 LOG_ERROR(
"Failed to start Clarius imaging");
1968 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1980 unsigned int numberOfScalarComponents = (videoSource->
GetImageType() == US_IMG_RGB_COLOR ? 3 : 1);
1988 LOG_TRACE(
"vtkPlusClariusOEM::InternalStopRecording");
1998 LOG_ERROR(
"Failed to stop Clarius imaging");
2001 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
2009 LOG_TRACE(
"vtkPlusClariusOEM::InternalApplyImagingParameterChange");
2019 LOG_ERROR(
"Failed to set depth imaging parameter");
2031 LOG_ERROR(
"Failed to set gain imaging parameter");
2043 LOG_ERROR(
"Failed to set dynamic range imaging parameter");
2053 std::vector<double> tgcVec;
2057 LOG_ERROR(
"Failed to set time gain compensation imaging parameter");
2069 LOG_ERROR(
"Failed to set focus depth percent imaging parameter");
2087 double oemVal = solumGetParam(CusParam::ImageDepth);
2091 LOG_ERROR(
"Failed to get DepthMm parameter");
2094 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2096 aDepthMm = oemVal * CM_TO_MM;
2111 LOG_INFO(
"Cached US parameter DepthMm = " << aDepthMm);
2116 double depthCm = aDepthMm * MM_TO_CM;
2117 if (solumSetParam(CusParam::ImageDepth, depthCm) < 0)
2119 LOG_ERROR(
"Failed to set DepthMm parameter");
2122 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2126 LOG_INFO(
"Set US parameter DepthMm to " << aDepthMm);
2139 double oemVal = solumGetParam(CusParam::Gain);
2143 LOG_ERROR(
"Failed to get GainPercent parameter");
2146 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2148 aGainPercent = oemVal;
2163 LOG_INFO(
"Cached US parameter GainPercent = " << aGainPercent);
2168 if (solumSetParam(CusParam::Gain, aGainPercent) < 0)
2170 LOG_ERROR(
"Failed to set GainPercent parameter");
2173 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2177 LOG_INFO(
"Set US parameter GainPercent to " << aGainPercent);
2190 double oemVal = solumGetParam(CusParam::DynamicRange);
2193 aDynRangePercent = -1;
2194 LOG_ERROR(
"Failed to get DynRange parameter");
2197 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2199 aDynRangePercent = oemVal;
2214 LOG_INFO(
"Cached US parameter DynRangePercent = " << aDynRangePercent);
2219 if (solumSetParam(CusParam::DynamicRange, aDynRangePercent) < 0)
2221 LOG_ERROR(
"Failed to set DynRange parameter");
2224 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2228 LOG_INFO(
"Set US parameter DynRangePercent to " << aDynRangePercent);
2242 if (solumGetTgc(&cTGC) < 0)
2244 LOG_ERROR(
"Failed to get time gain compensation parameter");
2247 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2253 aTGC[2] = cTGC.bottom;
2264 if (aTGC.size() != 3)
2266 LOG_ERROR(
"vtkPlusClariusOEM time gain compensation parameter must be provided a vector of exactly 3 doubles [top gain, mid gain, bottom gain]");
2274 LOG_INFO(
"Cached US parameter TGC = [" << aTGC[0] <<
", " << aTGC[1] <<
", " << aTGC[2] <<
"]");
2278 for (
int i = 0;
i < 3; ++
i)
2280 if (std::abs(aTGC[
i]) > 20)
2282 LOG_ERROR(
"Invalid time gain compensation parameter at index: " <<
i <<
" [" 2286 <<
"Valid range is [-20, 20]");
2294 cTGC.bottom = aTGC[2];
2295 if (solumSetTgc(&cTGC) < 0)
2297 LOG_ERROR(
"Failed to set time gain compensation parameter");
2300 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2304 LOG_INFO(
"Set US parameter TGC to [" << aTGC[0] <<
", " << aTGC[1] <<
", " << aTGC[2] <<
"]");
2311 int oemState = solumIsConnected();
2315 aEnableAutoFocus = this->Internal->EnableAutoFocus;
2319 aEnableAutoFocus = solumGetParam(CusParam::AutoFocus) > 0;
2326 this->Internal->EnableAutoFocus = aEnableAutoFocus;
2331 LOG_INFO(
"Cached US parameter AutoFocus = " << aEnableAutoFocus);
2338 LOG_ERROR(
"Failed to set AutoFocus parameter");
2341 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2352 aEnablePenetrationMode = this->Internal->EnablePenetrationMode;
2356 aEnablePenetrationMode = solumGetParam(PenetrationMode) > 0;
2363 LOG_TRACE(
"vtkPlusClariusOEM::SetEnablePenetrationMode");
2368 LOG_ERROR(
"Failed to set PenetrationMode parameter");
2371 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2385 double focusDepthCm = solumGetParam(CusParam::FocusDepth);
2386 if (focusDepthCm < 0)
2388 aFocusDepthPercent = -1;
2389 LOG_ERROR(
"Failed to get FocusDepthPercent parameter");
2392 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2408 LOG_INFO(
"Cached US parameter FocusDepthPercent = " << aFocusDepthPercent);
2412 if (aFocusDepthPercent < 0)
2422 if (solumSetParam(CusParam::FocusDepth, focusDepthCm) < 0)
2424 LOG_ERROR(
"Failed to set FocusDepthPercent parameter");
2427 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2431 LOG_INFO(
"Set US parameter FocusDepthPercent to " << aFocusDepthPercent);
2438 double depthMm = 0.0;
2443 return 100.0 * depthMm / (aFocusDepthCm * CM_TO_MM);
2449 double depthMm = 0.0;
2454 return (depthMm * MM_TO_CM) * (aFocusDepthPercent / 100.0);
2463 aEnableAutoGain = this->Internal->EnableAutoGain;
2467 aEnableAutoGain = solumGetParam(CusParam::AutoGain) > 0;
2474 this->Internal->EnableAutoGain = aEnableAutoGain;
2479 LOG_INFO(
"Cached US parameter AutoGain = " << aEnableAutoGain);
2486 LOG_ERROR(
"Failed to set AutoGain parameter");
2489 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
static const char * KEY_DYNRANGE
PlusStatus ConfigureProbeApplication()
PlusStatus GetEnablePenetrationMode(bool &aEnablePenetrationMode)
static const std::string RFMODE_PORT_NAME
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *deviceConfig)
bool IsPending(const std::string ¶mName) const
PlusStatus InitializeBLE()
double ConvertDepthCmToPercent(double aFocusDepthMm)
static void BGRA32ToRGB24(int width, int height, unsigned char *s, unsigned char *d)
US_IMAGE_TYPE GetImageType()
PlusStatus UpdateFrameSize()
PlusStatus SetGainPercent(double aGainPercent)
static const char * KEY_DEPTH
PlusStatus SetClariusCert()
#define XML_FIND_DEVICE_ELEMENT_REQUIRED_FOR_WRITING(deviceConfig, rootConfigElement)
PlusStatus InitializeProbe()
PlusStatus InitializeWifi()
static const char * KEY_FOCUS_DEPTH
PlusStatus GetFocusDepthPercent(double &aFocusDepthPercent) const
static const std::string BMODE_PORT_NAME
PlusStatus GetDepthMm(double &aDepthMm) const
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)
PlusStatus UpdateProbeStatus()
vtkPlusUsImagingParameters * ImagingParameters
Store the current imaging parameters.
PlusStatus SetPending(const std::string ¶mName, bool pending)
static const char * KEY_GAIN
PlusStatus InternalStartRecording() override
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
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
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
static const std::string OVERLAY_PORT_NAME
PlusStatus SetFocusDepthPercent(double aFocusDepthPercent)
PlusStatus GetFocusDepthPercent(double &aFocusDepthPercent)
PlusStatus InitializeOEM()
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
PlusStatus ReadConfiguration(vtkXMLDataElement *config) override
PlusStatus GetTimeGainCompensationDb(std::vector< double > &aTGC)
PlusStatus InternalUpdate() override
PlusStatus GetEnableAutoGain(bool &aEnableAutoGain)
PlusStatus Probe() override
std::string GetSdkVersion() override
bool StartThreadForInternalUpdates
static PlusStatus ConvertToGray(int inputCompression, int width, int height, unsigned char *s, unsigned char *d)
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 ¶mName) 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
double ConvertDepthPercentToCm(double aFocusDepthPercent)
static const char * KEY_TGC
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *deviceConfig)
Interface to a 3D positioning tool, video source, or generalized data stream.