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(
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
328 , FrameSize(DEFAULT_FRAME_SIZE)
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)
350 , TransdSource(nullptr)
351 , PressedButton(NO_BUTTON_TAG)
354 , EnableAutoFocus(DEFAULT_ENABLE_AUTO_FOCUS)
359 void vtkPlusClariusOEM::vtkInternal::ListFn(
const char* list,
int sz)
363 std::vector<std::string> vec;
365 std::stringstream ss(list);
369 getline(ss, substr,
',');
370 vec.push_back(substr);
373 if (device->Internal->ExpectedList == EXPECTED_LIST::PROBES)
375 device->Internal->PromiseProbes.set_value(vec);
377 else if (device->Internal->ExpectedList == EXPECTED_LIST::APPLICATIONS)
379 device->Internal->PromiseApplications.set_value(vec);
384 void vtkPlusClariusOEM::vtkInternal::ConnectFn(CusConnection ret,
int port,
const char* status)
390 case ConnectionError:
391 LOG_ERROR(
"Connection status: error - " << status);
395 LOG_INFO(
"Connection status: probe connected - " << status);
397 case ProbeDisconnected:
398 LOG_INFO(
"Connection status: probe disconnected - " << status);
401 case ConnectionFailed:
402 LOG_ERROR(
"Connection status: connection failed - " << status);
405 case SwUpdateRequired:
406 LOG_INFO(
"Connection status: software update required - " << status);
411 if (ret == CusConnection::ProbeConnected)
414 device->Internal->ConnectionBarrier.set_value();
419 void vtkPlusClariusOEM::vtkInternal::CertFn(
int daysValid)
423 LOG_ERROR(
"Invalid or expired certificate provided for Clarius OEM device");
427 LOG_INFO(
"Clarius certificate is valid for " << daysValid <<
" more days");
432 void vtkPlusClariusOEM::vtkInternal::PowerDownFn(CusPowerDown ret,
int tm)
434 std::stringstream ss;
435 ss <<
"Clarius probe will power down ";
439 ss <<
"immediately as a result of ";
443 ss <<
"in " << tm <<
" seconds as a result of ";
446 if (ret == CusPowerDown::Idle)
448 ss <<
"being idle for an extended period of time. ";
450 else if (ret == CusPowerDown::TooHot)
452 ss <<
"overheating. ";
454 else if (ret == CusPowerDown::LowBattery)
456 ss <<
"running out of battery. ";
458 else if (ret == CusPowerDown::ButtonOff)
460 ss <<
"user holding the shutdown button. ";
464 ss <<
"an unspecified reason. ";
467 ss <<
"If Clarius probe has powered off please turn it back on and restart PLUS, if desired.";
472 void vtkPlusClariusOEM::vtkInternal::SwUpdateFn(CusSwUpdate ret)
474 LOG_ERROR(
"Clarius SwUpdateFn callback was called, but this feature is not supported by PLUS. Please update using the Clarius iOS/Android App");
478 void vtkPlusClariusOEM::vtkInternal::RawImageFn(
const void* newImage,
const CusRawImageInfo* nfo,
int npos,
const CusPosInfo* pos)
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");
484 void vtkPlusClariusOEM::vtkInternal::SpectralImageFn(
const void* newImage,
const CusSpectralImageInfo* nfo)
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");
490 void vtkPlusClariusOEM::vtkInternal::ImuDataFn(
const CusPosInfo* pos)
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");
500 LOG_ERROR(
"Failed to update probe status");
513 if (solumStatusInfo(&this->Internal->CurrentStatus) != 0)
515 LOG_ERROR(
"Failed to retrieve solumStatusInfo");
522 void vtkPlusClariusOEM::vtkInternal::ProcessedImageFn(
const void* oemImage,
const CusProcessedImageInfo* nfo,
int npos,
const CusPosInfo* pos)
527 LOG_ERROR(
"vtkPlusClariusOEM::vtkInternal::ProcessedImageFn called when Clarius instance was NULL!");
537 if (oemImage == NULL)
539 LOG_ERROR(
"NULL frame received by the Clarius OEM device");
544 if (!nfo->overlay && device->Internal->BModeSources.size() == 0)
548 else if (nfo->overlay && device->Internal->OverlaySources.size() == 0)
554 const double unfilteredTimestamp = vtkIGSIOAccurateTimer::GetSystemTime();
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);
562 std::vector<vtkPlusDataSource*> dataSources = device->Internal->BModeSources;
565 dataSources = device->Internal->OverlaySources;
568 for (
auto dataSource : dataSources)
570 if (dataSource->GetImageType() == US_IMG_RGB_COLOR)
572 vtkImage->AllocateScalars(VTK_UNSIGNED_CHAR, 3);
576 (
unsigned char*)oemImage,
577 (
unsigned char*)vtkImage->GetScalarPointer()
588 vtkImage->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
593 (
unsigned char*)oemImage,
594 (
unsigned char*)vtkImage->GetScalarPointer()
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);
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);
615 if (device->Internal->ButtonSentCount > 0)
617 --device->Internal->ButtonSentCount;
621 device->Internal->PressedButton = NO_BUTTON_TAG;
622 device->Internal->ButtonNumClicks = 0;
626 for (
auto dataSource : dataSources)
629 vtkImage->GetScalarPointer(),
630 dataSource->GetInputImageOrientation(),
631 dataSource->GetInputFrameSize(),
633 dataSource->GetImageType() == US_IMG_RGB_COLOR ? 3 : 1,
634 dataSource->GetImageType(),
646 if (device->Internal->TransdSource)
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++)
652 unsigned char imval = vtkImage->GetScalarComponentAsDouble(
i, j, 0, 0);
661 vtkSmartPointer<vtkMatrix4x4> tsfm = vtkSmartPointer<vtkMatrix4x4>::New();
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);
676 void vtkPlusClariusOEM::vtkInternal::ImagingFn(CusImagingState ready,
int imaging)
678 if (ready == CusImagingState::ImagingNotReady)
680 LOG_WARNING(
"Clarius imaging is not ready yet...");
682 else if (ready == CusImagingState::ImagingReady)
684 LOG_INFO(
"Clarius imaging is " << (imaging ?
"running" :
"stopped"));
686 else if (ready == CusImagingState::CertExpired)
688 LOG_ERROR(
"Clarius certificate needs to be updated prior to imaging");
690 else if (ready == CusImagingState::PoorWifi)
692 LOG_WARNING(
"Clarius imaging stopped as a result of a poor Wi-Fi connection");
694 else if (ready == CusImagingState::NoContact)
696 LOG_INFO(
"Clarius imaging stopped as a result of no patient contact for specified timeout duration");
698 else if (ready == CusImagingState::ChargingChanged)
700 LOG_WARNING(
"Clarius imaging " << (imaging ?
"started" :
"stopped") <<
" due to a change in charging status");
702 else if (ready == CusImagingState::LowBandwidth)
704 LOG_INFO(
"Clarius low bandwidth was detected, imaging parameters were adjusted");
706 else if (ready == CusImagingState::MotionSensor)
708 LOG_INFO(
"Clarius imaging " << (imaging ?
"started" :
"stopped") <<
" due to change in motion sensor");
712 LOG_ERROR(
"Clarius ImagingFn called with unknown 'ready' state");
720 void vtkPlusClariusOEM::vtkInternal::ButtonFn(CusButton btn,
int clicks)
725 LOG_ERROR(
"vtkPlusClariusOEM::vtkInternal::ButtonFn called when Clarius instance was NULL!");
732 LOG_ERROR(
"ClariusOEM device unexpectedly disconnected from Clarius Device. IpAddress = " << device->Internal->IpAddress
733 <<
" Port = " << device->Internal->TcpPort);
738 device->Internal->ButtonNumClicks = clicks;
739 if (btn == CusButton::ButtonDown)
741 device->Internal->PressedButton = DOWN_BUTTON_TAG;
743 else if (btn == CusButton::ButtonUp)
745 device->Internal->PressedButton = UP_BUTTON_TAG;
749 LOG_WARNING(
"Unexpected Clarius button value of " << btn <<
" received in vtkPlusClariusOEM::vtkInternal::ButtonFn");
753 device->Internal->ButtonSentCount = SEND_BUTTON_STATE_FOR_N_FRAMES;
759 void vtkPlusClariusOEM::vtkInternal::ProgressFn(
int progress)
761 LOG_INFO(
"Downloading: " << progress <<
"%");
768 void vtkPlusClariusOEM::vtkInternal::ErrorFn(
const char* err)
770 LOG_ERROR(
"A Clarius OEM error occurred. Error text was: " << err);
774 void vtkPlusClariusOEM::vtkInternal::LogUserSettings()
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;
801 LOG_INFO(std::endl <<
"User settings:" << std::endl << ss.str());
809 if (instance == NULL)
818 : Internal(new vtkInternal(this))
844 delete this->Internal;
845 this->Internal =
nullptr;
848 this->instance = NULL;
854 if (instance != NULL)
869 LOG_TRACE(
"vtkPlusClariusOEM::PrintSelf");
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;
898 LOG_TRACE(
"vtkPlusClariusOEM::ReadConfiguration");
903 XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
904 ProbeSerialNum, this->Internal->ProbeSerialNum, deviceConfig);
907 XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
908 PathToCert, this->Internal->PathToCert, deviceConfig);
911 XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
912 ProbeType, this->Internal->ProbeType, deviceConfig);
915 this->Internal->ProbeType.begin(),
916 this->Internal->ProbeType.end(),
917 this->Internal->ProbeType.begin(),
918 [](
unsigned char c) {
return std::toupper(c); }
922 XML_READ_STRING_ATTRIBUTE_NONMEMBER_REQUIRED(
923 ImagingApplication, this->Internal->ImagingApplication, deviceConfig);
926 this->Internal->ImagingApplication.begin(),
927 this->Internal->ImagingApplication.end(),
928 this->Internal->ImagingApplication.begin(),
929 [](
unsigned char c) {
return std::tolower(c); }
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))
936 if (rfs[0] < 0 || rfs[1] < 0)
938 LOG_ERROR(
"Negative frame size defined in config file. Please define a positive frame size.");
941 FrameSizeType fs = { static_cast<unsigned int>(rfs[0]), static_cast<unsigned int>(rfs[1]), 1 };
942 this->Internal->FrameSize = fs;
946 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnableAutoGain,
947 this->Internal->EnableAutoGain, deviceConfig);
950 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(Enable5v,
951 this->Internal->Enable5v, deviceConfig);
954 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(FreezeOnPoorWifiSignal,
955 this->Internal->FreezeOnPoorWifiSignal, deviceConfig);
958 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(KeepAwakeCharging,
959 this->Internal->KeepAwakeCharging, deviceConfig);
962 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(PowerButtonsEnabled,
963 this->Internal->PowerButtonsEnabled, deviceConfig);
966 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(SoundEnabled,
967 this->Internal->SoundEnabled, deviceConfig);
970 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, StationaryTimeoutSec,
971 this->Internal->StationaryTimeoutSec, deviceConfig);
974 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(WakeOnShake,
975 this->Internal->WakeOnShake, deviceConfig);
978 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(ForceLogSend,
979 this->Internal->ForceLogSend, deviceConfig);
982 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnablePenetrationMode,
983 this->Internal->EnablePenetrationMode, deviceConfig);
986 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, ContactDetectionTimeoutSec,
987 this->Internal->ContactDetectionTimeoutSec, deviceConfig);
990 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, AutoFreezeTimeoutSec,
991 this->Internal->AutoFreezeTimeoutSec, deviceConfig);
994 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, KeepAwakeTimeoutMin,
995 this->Internal->KeepAwakeTimeoutMin, deviceConfig);
998 XML_READ_SCALAR_ATTRIBUTE_NONMEMBER_OPTIONAL(
int, DeepSleepTimeoutHr,
999 this->Internal->DeepSleepTimeoutHr, deviceConfig);
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
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
1018 XML_READ_BOOL_ATTRIBUTE_NONMEMBER_OPTIONAL(EnableAutoFocus,
1019 this->Internal->EnableAutoFocus, deviceConfig);
1022 XML_READ_ENUM_ATTRIBUTE_NONMEMBER_OPTIONAL(ImagingMode, this->Internal->ImagingMode, deviceConfig, this->Internal->ImagingModeToString, 0, ImagingModeStrings.size());
1028 XML_FIND_NESTED_ELEMENT_REQUIRED(dataSourcesElement, deviceConfig,
"DataSources");
1029 int numSources = dataSourcesElement->GetNumberOfNestedElements();
1030 for (
int i = 0;
i < numSources; ++
i)
1032 vtkXMLDataElement* element = dataSourcesElement->GetNestedElement(
i);
1033 if (!igsioCommon::IsEqualInsensitive(element->GetName(),
"DataSource"))
1041 const char* type = element->GetAttribute(
"Type");
1042 if (type && igsioCommon::IsEqualInsensitive(type,
"Video"))
1044 const char* orientation = element->GetAttribute(
"PortUsImageOrientation");
1045 if (orientation && !igsioCommon::IsEqualInsensitive(orientation,
"UF"))
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'.");
1052 if (type && igsioCommon::IsEqualInsensitive(type,
"Tool"))
1054 const char* toolId = element->GetAttribute(
"Id");
1057 LOG_ERROR(
"Failed to initialize Clarius OEM transform: DataSource Id is missing");
1061 const char* portName = element->GetAttribute(
"PortName");
1062 if (portName && !igsioCommon::IsEqualInsensitive(portName, TRANSD_PORT_NAME))
1064 LOG_ERROR(
"Clarius OEM device only supports Tool items with PortName=\"" 1065 << TRANSD_PORT_NAME <<
"\"");
1071 std::string transdSourceId = transdTransformName.GetTransformName();
1072 if (this->
GetTool(transdSourceId, this->Internal->TransdSource) !=
PLUS_SUCCESS || this->Internal->TransdSource == NULL)
1074 LOG_ERROR(
"Failed to get ClariusOEM tool: " << transdSourceId);
1090 LOG_TRACE(
"vtkPlusClariusOEM::WriteConfiguration");
1102 LOG_TRACE(
"vtkPlusClariusOEM::NotifyConfigured");
1107 LOG_WARNING(
"vtkPlusClariusOEM is expecting one output channel and there are " <<
1108 this->
OutputChannels.size() <<
" channels. First output channel will be used.");
1113 LOG_ERROR(
"No output channels defined for vtkPlusClariusOEM. Cannot proceed.");
1118 std::vector<vtkPlusDataSource*> sources;
1120 if (sources.size() > 1)
1122 LOG_WARNING(
"More than one output video source found. First will be used");
1124 if (sources.size() == 0)
1126 LOG_ERROR(
"Video source required in configuration. Cannot proceed.");
1134 LOG_ERROR(
"Unable to retrieve the video source in the vtkPlusClariusOEM device.");
1144 LOG_TRACE(
"vtkPlusClariusOEM: Probe");
1145 LOG_ERROR(
"vtkPlusClariusOEM::Probe() is not implemented");
1153 LOG_TRACE(
"vtkPlusClariusOEM::GetSdkVersion");
1154 return "SDK version not available";
1160 LOG_TRACE(
"vtkPlusClariusOEM::InitializeBLE");
1163 if (!this->Internal->BleHelper.FindBySerial(this->Internal->ProbeSerialNum))
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.");
1169 std::vector<std::string> probes = this->Internal->BleHelper.RetrieveFoundProbeIds();
1174 LOG_ERROR(
"No active Clarius probes found within BLE range");
1179 std::stringstream ss;
1180 ss <<
"Clarius probes configured with Windows Bluetooth are:\n";
1181 for (
const std::string& probe : probes)
1183 ss <<
"\t" << probe <<
"\n";
1185 LOG_ERROR(ss.str());
1190 LOG_INFO(
"Connecting to BLE network of Clarius probe with SN: " << this->Internal->ProbeSerialNum);
1191 if (this->Internal->BleHelper.Connect() !=
PLUS_SUCCESS)
1193 LOG_ERROR(
"Failed to connect to Clarius probe. Last error was: " 1194 << this->Internal->BleHelper.GetLastError());
1199 if (!this->Internal->BleHelper.IsProbeConnected())
1201 LOG_ERROR(
"Failed to connect to Clarius probe. Last error was: " 1202 << this->Internal->BleHelper.GetLastError());
1213 LOG_TRACE(
"vtkPlusClariusOEM::InitializeProbe");
1216 if (this->Internal->BleHelper.RequestProbeOn() !=
PLUS_SUCCESS)
1218 LOG_ERROR(
"An error occurred during RequestProbeOn. Last error was: " 1219 << this->Internal->BleHelper.GetLastError());
1224 if (!this->Internal->BleHelper.AwaitWifiInfoReady())
1226 LOG_ERROR(
"Timeout occurred while waiting for Clarius probe to power on." 1227 <<
" Last error was: " << this->Internal->BleHelper.GetLastError());
1232 if (this->Internal->BleHelper.ConfigureWifiAP() !=
PLUS_SUCCESS)
1234 LOG_ERROR(
"An error occurred during ConfigureWifiAP. Last error was: " 1235 << this->Internal->BleHelper.GetLastError());
1240 std::pair<bool, ClariusWifiInfo> infoPair = this->Internal->BleHelper.GetWifiInfo();
1241 if (!infoPair.first)
1243 LOG_ERROR(
"An error occurred during GetWifiInfo. Last error was: " 1244 << this->Internal->BleHelper.GetLastError());
1251 LOG_ERROR(
"Wifi was not ready when connection info was requested");
1256 std::stringstream infoStream;
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";
1267 LOG_INFO(
"Clarius Wifi Info: " << std::endl << infoStream.str());
1269 this->Internal->Ssid = info.
SSID;
1270 this->Internal->Password = info.
Password;
1271 this->Internal->IpAddress = info.
IPv4;
1275 if (this->Internal->Ssid[0] ==
'"')
1277 this->Internal->Ssid = this->Internal->Ssid.substr(1, this->Internal->Ssid.size() - 2);
1280 if (this->Internal->Password[0] ==
'"')
1282 this->Internal->Password = this->Internal->Password.substr(1, this->Internal->Password.size() - 2);
1285 if (this->Internal->IpAddress[0] ==
'"')
1287 this->Internal->IpAddress = this->Internal->IpAddress.substr(1, this->Internal->IpAddress.size() - 2);
1298 LOG_TRACE(
"vtkPlusClariusOEM::InitializeWifi");
1300 if (this->Internal->WifiHelper.Initialize() !=
PLUS_SUCCESS)
1302 LOG_ERROR(
"Failed to initialize Clarius wifi helper");
1306 PlusStatus res = this->Internal->WifiHelper.ConnectToClariusWifi(
1307 this->Internal->Ssid,
1308 this->Internal->Password
1312 LOG_ERROR(
"Failed to connect to Clarius probe wifi");
1322 LOG_TRACE(
"vtkPlusClariusOEM::InitializeOEM");
1326 char** argv =
new char* [1];
1327 argv[0] =
new char[4];
1328 strcpy(argv[0],
"abc");
1329 const char* certPath =
"/Clarius";
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);
1347 std::vector<vtkPlusDataSource*> bModeSources;
1349 if (this->Internal->BModeSources.empty() && this->Internal->OverlaySources.empty())
1351 newProcessedImageFnPtr =
nullptr;
1355 std::vector<vtkPlusDataSource*> rfModeSources;
1357 if (rfModeSources.empty())
1359 newRawImageFnPtr =
nullptr;
1364 FrameSizeType fs = this->Internal->FrameSize;
1365 int result = solumInit(
1372 newProcessedImageFnPtr,
1374 newSpectralImageFnPtr,
1382 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1386 LOG_ERROR(
"Failed to initialize Clarius OEM library");
1390 catch (
const std::runtime_error& re)
1392 LOG_ERROR(
"Runtime error on solumInit. Error text: " << re.what());
1395 catch (
const std::exception& ex)
1397 LOG_ERROR(
"Exception on solumInit. Error text: " << ex.what());
1402 LOG_ERROR(
"Unknown failure occurred on solumInit");
1413 LOG_TRACE(
"vtkPlusClariusOEM::SetClariusCert");
1417 std::ifstream certFile(fullCertPath);
1418 if (!certFile.is_open())
1420 LOG_ERROR(
"Failed to open Clarius cert file from " << fullCertPath <<
". Please check the PathToCert path in your config.");
1424 std::ostringstream sstr;
1425 sstr << certFile.rdbuf();
1426 std::string certStr = sstr.str();
1429 if (solumSetCert(certStr.c_str()) != 0)
1431 LOG_ERROR(
"Failed to set Clarius OEM connection certificate");
1434 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
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:");
1446 std::future<void> connectionBarrierFuture = this->Internal->ConnectionBarrier.get_future();
1449 int result = solumConnect(ip,
port);
1450 if (result != CusConnection::ProbeConnected)
1452 LOG_ERROR(
"Failed to initiate connection to Clarius probe on " << ip <<
":" <<
port <<
1453 ". Return code: " << ConnectEnumToString[result]);
1457 catch (
const std::runtime_error& re)
1459 LOG_ERROR(
"Runtime error on solumConnect. Error text: " << re.what());
1462 catch (
const std::exception& ex)
1464 LOG_ERROR(
"Exception on solumConnect. Error text: " << ex.what());
1469 LOG_ERROR(
"Unknown failure occurred on solumConnect");
1474 if (connectionBarrierFuture.wait_for(std::chrono::seconds(25)) != std::future_status::ready)
1476 LOG_ERROR(
"Connection to Clarius device timed out");
1479 LOG_INFO(
"Connected to Clarius probe on " << ip <<
":" <<
port);
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)
1487 LOG_INFO(
"Failed to retrieve list of valid probe types");
1490 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1493 if (futureProbes.wait_for(std::chrono::seconds(5)) != std::future_status::ready)
1495 LOG_ERROR(
"Failed to retrieve list of valid Clarius probe names");
1498 std::vector<std::string> vProbes = futureProbes.get();
1501 std::string probeType = this->Internal->ProbeType;
1502 if (std::find(vProbes.begin(), vProbes.end(), probeType) == vProbes.end())
1504 std::string vProbesStr;
1505 for (
const auto& probe : vProbes)
1507 vProbesStr += probe +
", ";
1509 vProbesStr.pop_back(); vProbesStr.pop_back();
1510 LOG_ERROR(
"Invalid probe type (" << probeType <<
") provided, valid probe types are: " << vProbesStr);
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)
1519 LOG_ERROR(
"Failed to retrieve list of valid imaging applications");
1522 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1525 if (futureApplications.wait_for(std::chrono::seconds(5)) != std::future_status::ready)
1527 LOG_ERROR(
"Failed to retrieve list of valid Clarius application names");
1530 std::vector<std::string> vApps = futureApplications.get();
1533 std::string imagingApplication = this->Internal->ImagingApplication;
1534 if (std::find(vApps.begin(), vApps.end(), imagingApplication) == vApps.end())
1536 std::string vAppsStr;
1537 for (
const auto& app : vApps)
1539 vAppsStr += app +
", ";
1541 vAppsStr.pop_back(); vAppsStr.pop_back();
1542 LOG_ERROR(
"Invalid imaging application (" << imagingApplication <<
") provided, valid imaging applications are: " << vAppsStr);
1547 if (solumLoadApplication(probeType.c_str(), imagingApplication.c_str()) == 0)
1549 LOG_INFO(
"Loaded " << imagingApplication <<
" application on a " << probeType <<
" probe");
1553 LOG_ERROR(
"An error occured on call to solumLoadApplication");
1555 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1563 LOG_TRACE(
"vtkPlusClariusOEM::SetInitialUsParams");
1569 LOG_WARNING(
"Failed to set requested imaging depth (mm) in Clarius OEM device, unknown depth will be used");
1576 LOG_WARNING(
"Failed to set requested imaging gain (%) in Clarius OEM device, unknown gain will be used");
1583 LOG_WARNING(
"Failed to set requested imaging dynamic range in Clarius OEM device, unknown dynamic range will be used");
1590 LOG_WARNING(
"Failed to set requested imaging time gain compensation in Clarius OEM device, unknown time gain compensation will be used");
1595 LOG_WARNING(
"Failed to set auto focus");
1600 LOG_WARNING(
"Failed to set auto gain");
1605 LOG_WARNING(
"Failed to set penetration mode");
1614 LOG_TRACE(
"vtkPlusClariusOEM::InternalConnect");
1623 this->Internal->LogUserSettings();
1628 LOG_ERROR(
"Failed to initialize BLE in Clarius OEM device");
1636 LOG_ERROR(
"Failed to initialize probe (power, wifi settings) in Clarius OEM device");
1644 LOG_ERROR(
"Failed to initialize wifi in Clarius OEM device");
1652 LOG_ERROR(
"Failed to initialize OEM library in Clarius OEM device");
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");
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;
1675 settings.keepAwakeCharging = this->Internal->KeepAwakeCharging;
1676 settings.powerOn = this->Internal->PowerButtonsEnabled;
1677 settings.sounds = this->Internal->SoundEnabled;
1678 settings.wakeOnShake = this->Internal->WakeOnShake;
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)
1688 LOG_ERROR(
"Failed to set Clarius OEM probe settings");
1691 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1696 LOG_ERROR(
"Failed to configure Clarius probe application");
1703 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1705 CusProbeInfo probeInfo;
1706 if (solumProbeInfo(&probeInfo) != 0)
1708 LOG_WARNING(
"Failed to retrieve solumProbeInfo");
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());
1720 int enable5v = this->Internal->Enable5v ? 1 : 0;
1721 if (solumEnable5v(enable5v) < 0)
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);
1726 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1731 CusMode
mode = CusMode(this->Internal->ImagingMode);
1732 if (solumSetMode(
mode) != 0)
1734 LOG_ERROR(
"Failed to set Clarius OEM imaging mode");
1739 if (solumSeparateOverlays(1) != 0)
1741 LOG_ERROR(
"Failed to set Clarius separate overlays");
1751 LOG_TRACE(
"vtkPlusClariusOEM::DeInitializeOEM");
1753 int oemState = solumIsConnected();
1763 LOG_WARNING(
"Failed to disable Clarius 5v");
1766 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1769 LOG_WARNING(
"Failed to stop Clarius imaging");
1772 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1773 if (solumDisconnect() < 0)
1775 LOG_WARNING(
"Failed to disconnect from Clarius OEM library");
1779 if (solumDestroy() < 0)
1781 LOG_WARNING(
"Failed to destroy Clarius OEM library");
1788 LOG_TRACE(
"vtkPlusClariusOEM::DeInitializeWifi");
1790 if (!this->Internal->WifiHelper.DisconnectFromClariusWifi())
1792 LOG_WARNING(
"Failed to disconnect from Clarius wifi");
1794 if (!this->Internal->WifiHelper.DeInitialize())
1796 LOG_WARNING(
"Failed to de-initialize ClariusWifi");
1803 LOG_TRACE(
"vtkPlusClariusOEM::DeInitializeProbe");
1806 if (!this->Internal->BleHelper.IsProbeConnected())
1811 if (this->Internal->BleHelper.RequestProbeOff() !=
PLUS_SUCCESS)
1813 LOG_ERROR(
"An error occurred during RequestProbeOff. Last error was: " 1814 << this->Internal->BleHelper.GetLastError())
1821 LOG_TRACE(
"vtkPlusClariusOEM::DeInitializeBLE");
1824 if (this->Internal->BleHelper.Disconnect() !=
PLUS_SUCCESS)
1826 LOG_ERROR(
"An error occurred during Clarius BLE Disconnect. Last error was: " 1827 << this->Internal->BleHelper.GetLastError());
1834 LOG_TRACE(
"vtkPlusClariusOEM::InternalDisconnect");
1848 LOG_TRACE(
"vtkPlusClariusOEM::InternalStartRecording");
1852 bool running =
false;
1853 for (
int i = 0;
i < 10; ++
i)
1858 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1866 LOG_ERROR(
"Failed to start Clarius imaging");
1869 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1881 unsigned int numberOfScalarComponents = (videoSource->
GetImageType() == US_IMG_RGB_COLOR ? 3 : 1);
1889 LOG_TRACE(
"vtkPlusClariusOEM::InternalStopRecording");
1899 LOG_ERROR(
"Failed to stop Clarius imaging");
1902 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_LONG_DELAY_MS));
1910 LOG_TRACE(
"vtkPlusClariusOEM::InternalApplyImagingParameterChange");
1920 LOG_ERROR(
"Failed to set depth imaging parameter");
1932 LOG_ERROR(
"Failed to set gain imaging parameter");
1944 LOG_ERROR(
"Failed to set dynamic range imaging parameter");
1954 std::vector<double> tgcVec;
1958 LOG_ERROR(
"Failed to set time gain compensation imaging parameter");
1970 LOG_ERROR(
"Failed to set focus depth percent imaging parameter");
1988 double oemVal = solumGetParam(CusParam::ImageDepth);
1992 LOG_ERROR(
"Failed to get DepthMm parameter");
1995 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
1997 aDepthMm = oemVal * CM_TO_MM;
2012 LOG_INFO(
"Cached US parameter DepthMm = " << aDepthMm);
2017 double depthCm = aDepthMm * MM_TO_CM;
2018 if (solumSetParam(CusParam::ImageDepth, depthCm) < 0)
2020 LOG_ERROR(
"Failed to set DepthMm parameter");
2023 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2027 LOG_INFO(
"Set US parameter DepthMm to " << aDepthMm);
2040 double oemVal = solumGetParam(CusParam::Gain);
2044 LOG_ERROR(
"Failed to get GainPercent parameter");
2047 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2049 aGainPercent = oemVal;
2064 LOG_INFO(
"Cached US parameter GainPercent = " << aGainPercent);
2069 if (solumSetParam(CusParam::Gain, aGainPercent) < 0)
2071 LOG_ERROR(
"Failed to set GainPercent parameter");
2074 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2078 LOG_INFO(
"Set US parameter GainPercent to " << aGainPercent);
2091 double oemVal = solumGetParam(CusParam::DynamicRange);
2094 aDynRangePercent = -1;
2095 LOG_ERROR(
"Failed to get DynRange parameter");
2098 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2100 aDynRangePercent = oemVal;
2115 LOG_INFO(
"Cached US parameter DynRangePercent = " << aDynRangePercent);
2120 if (solumSetParam(CusParam::DynamicRange, aDynRangePercent) < 0)
2122 LOG_ERROR(
"Failed to set DynRange parameter");
2125 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2129 LOG_INFO(
"Set US parameter DynRangePercent to " << aDynRangePercent);
2143 if (solumGetTgc(&cTGC) < 0)
2145 LOG_ERROR(
"Failed to get time gain compensation parameter");
2148 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2154 aTGC[2] = cTGC.bottom;
2165 if (aTGC.size() != 3)
2167 LOG_ERROR(
"vtkPlusClariusOEM time gain compensation parameter must be provided a vector of exactly 3 doubles [top gain, mid gain, bottom gain]");
2175 LOG_INFO(
"Cached US parameter TGC = [" << aTGC[0] <<
", " << aTGC[1] <<
", " << aTGC[2] <<
"]");
2179 for (
int i = 0;
i < 3; ++
i)
2181 if (std::abs(aTGC[
i]) > 20)
2183 LOG_ERROR(
"Invalid time gain compensation parameter at index: " <<
i <<
" [" 2187 <<
"Valid range is [-20, 20]");
2195 cTGC.bottom = aTGC[2];
2196 if (solumSetTgc(&cTGC) < 0)
2198 LOG_ERROR(
"Failed to set time gain compensation parameter");
2201 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2205 LOG_INFO(
"Set US parameter TGC to [" << aTGC[0] <<
", " << aTGC[1] <<
", " << aTGC[2] <<
"]");
2212 int oemState = solumIsConnected();
2216 aEnableAutoFocus = this->Internal->EnableAutoFocus;
2220 aEnableAutoFocus = solumGetParam(CusParam::AutoFocus) > 0;
2227 this->Internal->EnableAutoFocus = aEnableAutoFocus;
2232 LOG_INFO(
"Cached US parameter AutoFocus = " << aEnableAutoFocus);
2239 LOG_ERROR(
"Failed to set AutoFocus parameter");
2242 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2253 aEnablePenetrationMode = this->Internal->EnablePenetrationMode;
2257 aEnablePenetrationMode = solumGetParam(PenetrationMode) > 0;
2264 LOG_TRACE(
"vtkPlusClariusOEM::SetEnablePenetrationMode");
2269 LOG_ERROR(
"Failed to set PenetrationMode parameter");
2272 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2286 double focusDepthCm = solumGetParam(CusParam::FocusDepth);
2287 if (focusDepthCm < 0)
2289 aFocusDepthPercent = -1;
2290 LOG_ERROR(
"Failed to get FocusDepthPercent parameter");
2293 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2309 LOG_INFO(
"Cached US parameter FocusDepthPercent = " << aFocusDepthPercent);
2313 if (aFocusDepthPercent < 0)
2323 if (solumSetParam(CusParam::FocusDepth, focusDepthCm) < 0)
2325 LOG_ERROR(
"Failed to set FocusDepthPercent parameter");
2328 std::this_thread::sleep_for(std::chrono::milliseconds(CLARIUS_SHORT_DELAY_MS));
2332 LOG_INFO(
"Set US parameter FocusDepthPercent to " << aFocusDepthPercent);
2339 double depthMm = 0.0;
2344 return 100.0 * depthMm / (aFocusDepthCm * CM_TO_MM);
2350 double depthMm = 0.0;
2355 return (depthMm * MM_TO_CM) * (aFocusDepthPercent / 100.0);
2364 aEnableAutoGain = this->Internal->EnableAutoGain;
2368 aEnableAutoGain = solumGetParam(CusParam::AutoGain) > 0;
2375 this->Internal->EnableAutoGain = aEnableAutoGain;
2380 LOG_INFO(
"Cached US parameter AutoGain = " << aEnableAutoGain);
2387 LOG_ERROR(
"Failed to set AutoGain parameter");
2390 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.