diff --git a/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.cpp b/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.cpp index 335c1fd11f..2d5b96caa7 100644 --- a/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.cpp +++ b/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.cpp @@ -1,73 +1,138 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataDisplacementFilter.h" #include "mitkPropertyList.h" #include "mitkProperties.h" mitk::NavigationDataDisplacementFilter::NavigationDataDisplacementFilter() -: mitk::NavigationDataToNavigationDataFilter() +: mitk::NavigationDataToNavigationDataFilter(), m_Transform6DOF(false) { m_Offset[0] = 0.0; m_Offset[1] = 0.0; m_Offset[2] = 0.0; + + m_Transformation = mitk::NavigationData::New(); + } mitk::NavigationDataDisplacementFilter::~NavigationDataDisplacementFilter() { } void mitk::NavigationDataDisplacementFilter::GenerateData() { /* update outputs with tracking data from tools */ - for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) + if( !m_Transform6DOF ) + { + for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) + { + mitk::NavigationData* output = this->GetOutput(i); + assert(output); + const mitk::NavigationData* input = this->GetInput(i); + assert(input); + + if (input->IsDataValid() == false) + { + output->SetDataValid(false); + continue; + } + output->Graft(input); // First, copy all information from input to output + output->SetPosition(input->GetPosition() + m_Offset); // Then change the member(s): add offset to position of navigation data + output->SetDataValid(true); // operation was successful, therefore data of output is valid. + // don't change anything else here + } + } + else { - mitk::NavigationData* output = this->GetOutput(i); - assert(output); - const mitk::NavigationData* input = this->GetInput(i); - assert(input); + if( this->GetNumberOfOutputs() < 2 ) + { + MITK_WARN << "TrackedUltrasound not possible. The number of tracked devices must be at least 2."; + return; + } + + //important: First device = Needle | Second device = US-Tracker + + mitk::NavigationData::Pointer needleOut = this->GetOutput(0); + const mitk::NavigationData* needleIn = this->GetInput(0); + + mitk::NavigationData::Pointer usTrackerOut = this->GetOutput(1); + const mitk::NavigationData* usTrackerIn = this->GetInput(1); - if (input->IsDataValid() == false) + if(needleIn->IsDataValid() == false ) { - output->SetDataValid(false); - continue; + needleOut->SetDataValid(false); + } + else + needleOut->Graft(needleIn); + + if (usTrackerIn->IsDataValid() == false) + { + usTrackerOut->SetDataValid(false); + } + else + usTrackerOut->Graft(usTrackerIn); + + needleOut->Compose( usTrackerOut->GetInverse(), false ); + needleOut->Compose( m_Transformation->GetInverse() ); + + usTrackerOut->SetDataValid(true); + needleOut->SetDataValid(true); + + if( this->GetNumberOfOutputs() > 2 ) + { + for( unsigned int i = 2; i < this->GetNumberOfOutputs(); ++i ) + { + mitk::NavigationData* output = this->GetOutput(i); + const mitk::NavigationData* input = this->GetInput(i); + + if (input->IsDataValid() == false) + { + output->SetDataValid(false); + continue; + } + output->Graft(input); + output->SetDataValid(true); + } } - output->Graft(input); // First, copy all information from input to output - output->SetPosition(input->GetPosition() + m_Offset); // Then change the member(s): add offset to position of navigation data - output->SetDataValid(true); // operation was successful, therefore data of output is valid. - // don't change anything else here } } +void mitk::NavigationDataDisplacementFilter::SetTransformation(mitk::AffineTransform3D::Pointer transform) +{ + mitk::NavigationData::Pointer transformation = mitk::NavigationData::New(transform); + m_Transformation = transformation; +} + void mitk::NavigationDataDisplacementFilter::SetParameters( const mitk::PropertyList* p ) { if (p == nullptr) return; mitk::Vector3D v; if (p->GetPropertyValue("NavigationDataDisplacementFilter_Offset", v) == true) // search for Offset parameter this->SetOffset(v); // apply if found; } mitk::PropertyList::ConstPointer mitk::NavigationDataDisplacementFilter::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); p->SetProperty("NavigationDataDisplacementFilter_Offset", mitk::Vector3DProperty::New(this->GetOffset())); // store Offset parameter return mitk::PropertyList::ConstPointer(p); } diff --git a/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.h b/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.h index 0cbfa23854..91786cc5d1 100644 --- a/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.h +++ b/Modules/IGT/Algorithms/mitkNavigationDataDisplacementFilter.h @@ -1,76 +1,85 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataDisplacementFilter_H_HEADER_INCLUDED_ #define MITKNavigationDataDisplacementFilter_H_HEADER_INCLUDED_ #include namespace mitk { /**Documentation * \brief NavigationDataDisplacementFilter adds an offset to navigation data objects * * Example class that shows how to write a navigation filter. This filter * adds a offset that can be specified as a parameter to each input navigation data. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationDataDisplacementFilter : public NavigationDataToNavigationDataFilter { public: mitkClassMacro(NavigationDataDisplacementFilter, NavigationDataToNavigationDataFilter); itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkSetVectorMacro(Offset, mitk::Vector3D); ///< Get Offset parameter mitkGetVectorMacro(Offset, mitk::Vector3D); ///< Set Offset parameter + itkSetMacro(Transform6DOF, bool); + itkGetMacro(Transform6DOF, bool); + + void SetTransformation( mitk::AffineTransform3D::Pointer transform ); /** *\brief Set all filter parameters (Offset) as the PropertyList p * * This method reads the following properties from the PropertyList (name : data type): * - "NavigationDataDisplacementFilter_Offset" : mitk::Vector3DProperty */ virtual void SetParameters(const mitk::PropertyList* p) override; /** *\brief Get all filter parameters (offset) as a PropertyList * * This method returns a PropertyList containing the following * properties (name : data type): * - "NavigationDataDisplacementFilter_Offset" : mitk::Vector3DProperty * The returned PropertyList must be assigned to a * SmartPointer immediately, or else it will get destroyed. */ mitk::PropertyList::ConstPointer GetParameters() const override; protected: NavigationDataDisplacementFilter(); virtual ~NavigationDataDisplacementFilter(); /**Documentation * \brief filter execute method * * adds the offset m_Offset to all inputs */ virtual void GenerateData() override; mitk::Vector3D m_Offset; ///< offset that is added to all inputs + + bool m_Transform6DOF; + + mitk::NavigationData::Pointer m_Transformation; + }; } // namespace mitk #endif /* MITKNAVIGATIONDATATONAVIGATIONDATAFILTER_H_HEADER_INCLUDED_ */ diff --git a/Modules/US/USNavigation/files.cmake b/Modules/US/USNavigation/files.cmake index 8d3a527324..0b77d91b58 100644 --- a/Modules/US/USNavigation/files.cmake +++ b/Modules/US/USNavigation/files.cmake @@ -1,6 +1,7 @@ SET(CPP_FILES mitkUSCombinedModality.cpp + mitkTrackedUltrasound.cpp mitkAbstractUltrasoundTrackerDevice.cpp Filter/mitkNodeDisplacementFilter.cpp ) diff --git a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp index 1afd8b41a6..9f118bf7c0 100644 --- a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp +++ b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.cpp @@ -1,478 +1,485 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkAbstractUltrasoundTrackerDevice.h" #include "mitkImageReadAccessor.h" #include "mitkNavigationDataSmoothingFilter.h" #include "mitkNavigationDataDelayFilter.h" +#include "mitkNavigationDataDisplacementFilter.h" #include "mitkTrackingDeviceSource.h" // US Control Interfaces #include "mitkUSControlInterfaceProbes.h" #include "mitkUSControlInterfaceBMode.h" #include "mitkUSControlInterfaceDoppler.h" //Microservices #include #include #include #include #include //TempIncludes #include -//___ -//Microservices - const std::string mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier = "org.mitk.modules.us.AbstractUltrasoundTrackerDevice"; const char* mitk::AbstractUltrasoundTrackerDevice::DefaultProbeIdentifier = "default"; const char* mitk::AbstractUltrasoundTrackerDevice::ProbeAndDepthSeperator = "_"; const std::string mitk::AbstractUltrasoundTrackerDevice::US_INTERFACE_NAME = "org.mitk.services.AbstractUltrasoundTrackerDevice"; const std::string mitk::AbstractUltrasoundTrackerDevice::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::AbstractUltrasoundTrackerDevice::US_PROPKEY_CLASS = US_INTERFACE_NAME + ".class"; const std::string mitk::AbstractUltrasoundTrackerDevice::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; //____ mitk::AbstractUltrasoundTrackerDevice::AbstractUltrasoundTrackerDevice( USDevice::Pointer usDevice, NavigationDataSource::Pointer trackingDevice, bool trackedUltrasoundActive ) : m_UltrasoundDevice(usDevice), m_TrackingDeviceDataSource(trackingDevice), m_SmoothingFilter(mitk::NavigationDataSmoothingFilter::New()), m_DelayFilter(mitk::NavigationDataDelayFilter::New(0)), + m_DisplacementFilter(mitk::NavigationDataDisplacementFilter::New()), m_NumberOfSmoothingValues(0), m_DelayCount(0), m_IsTrackedUltrasoundActive( trackedUltrasoundActive ) { + m_DisplacementFilter->SetTransform6DOF(true); + this->RebuildFilterPipeline(); //create a new output (for the image data) mitk::Image::Pointer newOutput = mitk::Image::New(); this->SetNthOutput(0, newOutput); // Combined Modality should not spawn an own acquire thread, because // image acquiring is done by the included us device m_UltrasoundDevice->SetSpawnAcquireThread(false); } mitk::AbstractUltrasoundTrackerDevice::~AbstractUltrasoundTrackerDevice() { if (m_ServiceRegistration != nullptr) { m_ServiceRegistration.Unregister(); } m_ServiceRegistration = 0; } mitk::AffineTransform3D::Pointer mitk::AbstractUltrasoundTrackerDevice::GetCalibration() { return this->GetCalibration( this->GetCurrentDepthValue(), this->GetIdentifierForCurrentProbe() ); } mitk::AffineTransform3D::Pointer mitk::AbstractUltrasoundTrackerDevice::GetCalibration(std::string depth) { return this->GetCalibration(depth, this->GetIdentifierForCurrentProbe()); } mitk::AffineTransform3D::Pointer mitk::AbstractUltrasoundTrackerDevice::GetCalibration( std::string depth, std::string probe ) { // make sure that there is no '/' which would cause problems for TinyXML std::replace(probe.begin(), probe.end(), '/', '-'); // create identifier for calibration from probe and depth std::string calibrationKey = probe + mitk::AbstractUltrasoundTrackerDevice::ProbeAndDepthSeperator + depth; // find calibration for combination of probe identifier and depth std::map::iterator calibrationIterator = m_Calibrations.find(calibrationKey); if (calibrationIterator == m_Calibrations.end()) { return 0; } return calibrationIterator->second; } void mitk::AbstractUltrasoundTrackerDevice::SetCalibration( mitk::AffineTransform3D::Pointer calibration ) { if( calibration.IsNull() ) { MITK_WARN << "Null pointer passed to SetCalibration of mitk::USDevice. Ignoring call."; return; } std::string calibrationKey = this->GetIdentifierForCurrentCalibration(); if( calibrationKey.empty() ) { MITK_WARN << "Could not get a key for the calibration -> Calibration cannot be set."; return; } m_Calibrations[calibrationKey] = calibration; } bool mitk::AbstractUltrasoundTrackerDevice::RemoveCalibration() { return this->RemoveCalibration( this->GetCurrentDepthValue(), this->GetIdentifierForCurrentProbe() ); } bool mitk::AbstractUltrasoundTrackerDevice::RemoveCalibration(std::string depth) { return this->RemoveCalibration( depth, this->GetIdentifierForCurrentProbe() ); } bool mitk::AbstractUltrasoundTrackerDevice::RemoveCalibration( std::string depth, std::string probe ) { // make sure that there is no '/' which would cause problems for TinyXML std::replace(probe.begin(), probe.end(), '/', '-'); // create identifier for calibration from probe and depth std::string calibrationKey = probe + mitk::AbstractUltrasoundTrackerDevice::ProbeAndDepthSeperator + depth; return m_Calibrations.erase(calibrationKey) > 0; } std::string mitk::AbstractUltrasoundTrackerDevice::GetDeviceClass() { return DeviceClassIdentifier; } mitk::USImageSource::Pointer mitk::AbstractUltrasoundTrackerDevice::GetUSImageSource() { if (m_UltrasoundDevice.IsNull()) { MITK_ERROR("AbstractUltrasoundTrackerDevice")("USDevice") << "UltrasoundDevice must not be null."; mitkThrow() << "UltrasoundDevice must not be null."; } return m_UltrasoundDevice->GetUSImageSource(); } mitk::NavigationDataSource::Pointer mitk::AbstractUltrasoundTrackerDevice::GetNavigationDataSource() { return this->RebuildFilterPipeline(); } bool mitk::AbstractUltrasoundTrackerDevice::GetIsCalibratedForCurrentStatus() { return m_Calibrations.find(this->GetIdentifierForCurrentCalibration()) != m_Calibrations.end(); } bool mitk::AbstractUltrasoundTrackerDevice::GetContainsAtLeastOneCalibration() { return !m_Calibrations.empty(); } std::string mitk::AbstractUltrasoundTrackerDevice::SerializeCalibration() { std::stringstream result; result << "" << std::endl; // For each calibration in the set for( std::map::iterator it = m_Calibrations.begin(); it != m_Calibrations.end(); it++ ) { mitk::AffineTransform3D::MatrixType matrix = it->second->GetMatrix(); mitk::AffineTransform3D::TranslationType translation = it->second->GetTranslation(); TiXmlElement elem(it->first); // Serialize Matrix elem.SetDoubleAttribute("M00", matrix[0][0]); elem.SetDoubleAttribute("M01", matrix[0][1]); elem.SetDoubleAttribute("M02", matrix[0][2]); elem.SetDoubleAttribute("M10", matrix[1][0]); elem.SetDoubleAttribute("M11", matrix[1][1]); elem.SetDoubleAttribute("M12", matrix[1][2]); elem.SetDoubleAttribute("M20", matrix[2][0]); elem.SetDoubleAttribute("M21", matrix[2][1]); elem.SetDoubleAttribute("M22", matrix[2][2]); // Serialize Offset elem.SetDoubleAttribute("T0", translation[0]); elem.SetDoubleAttribute("T1", translation[1]); elem.SetDoubleAttribute("T2", translation[2]); result << elem << std::endl; } result << "" << std::endl; return result.str(); } void mitk::AbstractUltrasoundTrackerDevice::DeserializeCalibration( const std::string& xmlString, bool clearPreviousCalibrations ) { // Sanitize Input if (xmlString == "") { MITK_ERROR << "Empty string passed to Deserialize() method of CombinedModality. Aborting..."; mitkThrow() << "Empty string passed to Deserialize() method of CombinedModality. Aborting..."; return; } // Clear previous calibrations if necessary if (clearPreviousCalibrations) m_Calibrations.clear(); // Parse Input TiXmlDocument doc; if (!doc.Parse(xmlString.c_str())) { MITK_ERROR << "Unable to deserialize calibrations in CombinedModality. Error was: " << doc.ErrorDesc(); mitkThrow() << "Unable to deserialize calibrations in CombinedModality. Error was: " << doc.ErrorDesc(); return; } TiXmlElement* root = doc.FirstChildElement(); if (root == nullptr) { MITK_ERROR << "Unable to deserialize calibrations in CombinedModality. String contained no root element."; mitkThrow() << "Unable to deserialize calibrations in CombinedModality. String contained no root element."; return; } // Read Calibrations for (TiXmlElement* elem = root->FirstChildElement(); elem != nullptr; elem = elem->NextSiblingElement()) { mitk::AffineTransform3D::MatrixType matrix; mitk::AffineTransform3D::OffsetType translation; std::string calibName = elem->Value(); // Deserialize Matrix elem->QueryDoubleAttribute("M00", &matrix[0][0]); elem->QueryDoubleAttribute("M01", &matrix[0][1]); elem->QueryDoubleAttribute("M02", &matrix[0][2]); elem->QueryDoubleAttribute("M10", &matrix[1][0]); elem->QueryDoubleAttribute("M11", &matrix[1][1]); elem->QueryDoubleAttribute("M12", &matrix[1][2]); elem->QueryDoubleAttribute("M20", &matrix[2][0]); elem->QueryDoubleAttribute("M21", &matrix[2][1]); elem->QueryDoubleAttribute("M22", &matrix[2][2]); // Deserialize Offset elem->QueryDoubleAttribute("T0", &translation[0]); elem->QueryDoubleAttribute("T1", &translation[1]); elem->QueryDoubleAttribute("T2", &translation[2]); mitk::AffineTransform3D::Pointer calibration = mitk::AffineTransform3D::New(); calibration->SetMatrix(matrix); calibration->SetTranslation(translation); m_Calibrations[calibName] = calibration; } } void mitk::AbstractUltrasoundTrackerDevice::SetNumberOfSmoothingValues( unsigned int numberOfSmoothingValues ) { unsigned int oldNumber = m_NumberOfSmoothingValues; m_NumberOfSmoothingValues = numberOfSmoothingValues; // if filter should be activated or deactivated if ((oldNumber == 0 && numberOfSmoothingValues != 0) || (oldNumber != 0 && numberOfSmoothingValues == 0)) { this->RebuildFilterPipeline(); } m_SmoothingFilter->SetNumerOfValues(numberOfSmoothingValues); } void mitk::AbstractUltrasoundTrackerDevice::SetDelayCount( unsigned int delayCount ) { unsigned int oldCount = m_DelayCount; m_DelayCount = delayCount; // if filter should be activated or deactivated if ((oldCount == 0 && delayCount != 0) || (oldCount != 0 && delayCount == 0)) { this->RebuildFilterPipeline(); } m_DelayFilter->SetDelay(delayCount); } itk::SmartPointer mitk::AbstractUltrasoundTrackerDevice::GetControlInterfaceCustom() { return itk::SmartPointer(); } itk::SmartPointer mitk::AbstractUltrasoundTrackerDevice::GetControlInterfaceBMode() { return itk::SmartPointer(); } itk::SmartPointer mitk::AbstractUltrasoundTrackerDevice::GetControlInterfaceProbes() { return itk::SmartPointer(); } itk::SmartPointer mitk::AbstractUltrasoundTrackerDevice::GetControlInterfaceDoppler() { return itk::SmartPointer(); } /*void mitk::AbstractUltrasoundTrackerDevice::UnregisterOnService() { if( m_UltrasoundDevice->GetDeviceState() == USDevice::State_Activated ) { m_UltrasoundDevice->Deactivate(); } if( m_UltrasoundDevice->GetDeviceState() == USDevice::State_Connected ) { m_UltrasoundDevice->Disconnect(); } if( m_ServiceRegistration != nullptr ) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } void mitk::AbstractUltrasoundTrackerDevice::RegisterAsMicroservice() { //Get Context us::ModuleContext* context = us::GetModuleContext(); //Define ServiceProps //us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator("TEST", 16); m_ServiceProperties[US_PROPKEY_ID] = uidGen.GetUID(); m_ServiceProperties[US_PROPKEY_DEVICENAME] = m_UltrasoundDevice->GetName(); m_ServiceProperties[US_PROPKEY_CLASS] = mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier; m_ServiceRegistration = context->RegisterService(this, m_ServiceProperties); }*/ void mitk::AbstractUltrasoundTrackerDevice::GenerateData() { } std::string mitk::AbstractUltrasoundTrackerDevice::GetIdentifierForCurrentCalibration() { return this->GetIdentifierForCurrentProbe() + mitk::AbstractUltrasoundTrackerDevice::ProbeAndDepthSeperator + this->GetCurrentDepthValue(); } std::string mitk::AbstractUltrasoundTrackerDevice::GetIdentifierForCurrentProbe() { us::ServiceProperties usdeviceProperties = m_UltrasoundDevice->GetServiceProperties(); us::ServiceProperties::const_iterator probeIt = usdeviceProperties.find( mitk::USDevice::GetPropertyKeys().US_PROPKEY_PROBES_SELECTED); // get probe identifier from control interface for probes std::string probeName = mitk::AbstractUltrasoundTrackerDevice::DefaultProbeIdentifier; if (probeIt != usdeviceProperties.end()) { probeName = (probeIt->second).ToString(); } // make sure that there is no '/' which would cause problems for TinyXML std::replace(probeName.begin(), probeName.end(), '/', '-'); return probeName; } std::string mitk::AbstractUltrasoundTrackerDevice::GetCurrentDepthValue() { us::ServiceProperties usdeviceProperties = m_UltrasoundDevice->GetServiceProperties(); // get string for depth value from the micro service properties std::string depth; us::ServiceProperties::iterator depthIterator = usdeviceProperties.find( mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH); if (depthIterator != usdeviceProperties.end()) { depth = depthIterator->second.ToString(); } else { depth = "0"; } return depth; } mitk::NavigationDataSource::Pointer mitk::AbstractUltrasoundTrackerDevice::RebuildFilterPipeline() { itk::SmartPointer filter = m_TrackingDeviceDataSource; if( m_NumberOfSmoothingValues > 0 ) { for (unsigned int i = 0; i < m_TrackingDeviceDataSource->GetNumberOfOutputs(); i++) { m_SmoothingFilter->SetInput(i, filter->GetOutput(i)); } filter = m_SmoothingFilter; } if( m_DelayCount > 0 ) { for( unsigned int i = 0; i < m_TrackingDeviceDataSource->GetNumberOfOutputs(); i++ ) { m_DelayFilter->SetInput(i, filter->GetOutput(i)); } filter = m_DelayFilter; } + if( m_IsTrackedUltrasoundActive ) + { + m_DisplacementFilter->ConnectTo(filter.GetPointer()); + filter = m_DisplacementFilter; + } + return filter.GetPointer(); } void mitk::AbstractUltrasoundTrackerDevice::UnregisterOnService() { if (m_UltrasoundDevice->GetDeviceState() == USDevice::State_Activated) { m_UltrasoundDevice->Deactivate(); } if (m_UltrasoundDevice->GetDeviceState() == USDevice::State_Connected) { m_UltrasoundDevice->Disconnect(); } if (m_ServiceRegistration != nullptr) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } void mitk::AbstractUltrasoundTrackerDevice::RegisterAsMicroservice() { //Get Context us::ModuleContext* context = us::GetModuleContext(); //Define ServiceProps //us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator("org.mitk.services.AbstractUltrasoundTrackerDevice", 16); m_ServiceProperties[US_PROPKEY_ID] = uidGen.GetUID(); m_ServiceProperties[US_PROPKEY_DEVICENAME] = m_UltrasoundDevice->GetName(); m_ServiceProperties[US_PROPKEY_CLASS] = mitk::AbstractUltrasoundTrackerDevice::DeviceClassIdentifier; m_ServiceRegistration = context->RegisterService(this, m_ServiceProperties); } diff --git a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h index e8bc035359..0b3ab32ee6 100644 --- a/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h +++ b/Modules/US/USNavigation/mitkAbstractUltrasoundTrackerDevice.h @@ -1,261 +1,263 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkAbstractUltrasoundTrackerDevice_h #define __mitkAbstractUltrasoundTrackerDevice_h #include #include "mitkUSDevice.h" #include "mitkImageSource.h" #include "mitkNavigationDataSource.h" // Microservices #include #include #include #include #include #include namespace itk { template class SmartPointer; } namespace mitk { class NavigationDataSmoothingFilter; class NavigationDataDelayFilter; + class NavigationDataDisplacementFilter; /** * \brief Abstract class for an easy handling of a combination of an USDevice and * a NavigationDataSource. * This class can be used as an ImageSource subclass. Additionally tracking data be * retrieved from the NavigationDataSource returned by GetTrackingDevice(). * * A calibration of the ultrasound image stream to the navigation datas can be set * for the currently active zoom level (of the ultrasound device) by SetCalibration() * The ultrasound images are transformed according to this calibration in the * GenerateData() method. */ class MITKUSNAVIGATION_EXPORT AbstractUltrasoundTrackerDevice : public mitk::ImageSource { public: static const std::string DeviceClassIdentifier; static const char* DefaultProbeIdentifier; static const char* ProbeAndDepthSeperator; static const std::string US_INTERFACE_NAME; static const std::string US_PROPKEY_DEVICENAME; static const std::string US_PROPKEY_CLASS; static const std::string US_PROPKEY_ID; mitkClassMacro(AbstractUltrasoundTrackerDevice, mitk::ImageSource); mitkNewMacro3Param(AbstractUltrasoundTrackerDevice, USDevice::Pointer, itk::SmartPointer, bool); itkGetMacro(UltrasoundDevice, itk::SmartPointer); itkSetMacro(UltrasoundDevice, itk::SmartPointer); itkGetMacro(TrackingDeviceDataSource, itk::SmartPointer); itkSetMacro(TrackingDeviceDataSource, itk::SmartPointer); /** * \brief Getter for calibration data of the currently active depth and probe. * * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(); /** * \brief Getter for calibration data of the given depth and the currently active probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be returned * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(std::string depth); /** * \brief Getter for calibration data of the given depth and probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be returned * \param probe probe of the ultrasound device for which the calibration should be returned * \return Transformation for calibration or null if no calibration is available. */ AffineTransform3D::Pointer GetCalibration(std::string depth, std::string probe); /** * \brief Sets a transformation as calibration data. * Calibration data is set for the currently activated probe and their current * zoom factor. It also marks the device as calibrated. */ void SetCalibration(AffineTransform3D::Pointer calibration); /** * \brief Removes the calibration data of the currently active depth and probe. * \return true on success, false if there was no calibration */ bool RemoveCalibration(); /** * \brief Removes the calibration data of the given depth and the currently active probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be removed * \return true on success, false if there was no calibration */ bool RemoveCalibration(std::string depth); /** * \brief Removes the calibration data of the given depth and probe. * * \param depth depth of the b mode ultrasound image for which the calibration should be removed * \param probe probe of the ultrasound device for which the calibration should be removed * \return true on success, false if there was no calibration */ bool RemoveCalibration(std::string depth, std::string probe); /** * \brief Returns the Class of the Device. */ std::string GetDeviceClass(); /** * \brief Wrapper for returning USImageSource of the UltrasoundDevice. */ USImageSource::Pointer GetUSImageSource(); itk::SmartPointer GetNavigationDataSource(); /** * \return true if the device is calibrated for the currently selected probe with the current zoom level */ bool GetIsCalibratedForCurrentStatus(); /** * \return true if a calibration was loaded for at least one probe and depth */ bool GetContainsAtLeastOneCalibration(); /** * \brief Serializes all contained calibrations into an xml fragment. * * The returned string contains one parent node named "calibrations" and several * subnodes, one for each calibration that is present. */ std::string SerializeCalibration(); /** * \brief Deserializes a string provided by a prior call to Serialize(). * If the bool flag is true, all prior calibrations will be deleted. * If the flag is set to false, prior calibrations will be retained, but overwritten * if one of equal name is present. * * \throws mitk::Exception if the given string could not be parsed correctly. */ void DeserializeCalibration(const std::string &xmlString, bool clearPreviousCalibrations = true); void SetNumberOfSmoothingValues(unsigned int numberOfSmoothingValues); void SetDelayCount(unsigned int delayCount); /** * \brief Remove this device from the micro service. * This method is public for mitk::USCombinedModality, because this devices * can be completly removed. This is not possible for API devices, which * should be available while their sub module is loaded. */ void UnregisterOnService(); virtual void RegisterAsMicroservice(); /** * \brief Wrapper for returning custom control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceCustom(); /** * \brief Wrapper for returning B mode control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceBMode(); /** * \brief Wrapper for returning probes control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceProbes(); /** * \brief Wrapper for returning doppler control interface of the UltrasoundDevice. */ virtual itk::SmartPointer GetControlInterfaceDoppler(); /** *\brief These Constants are used in conjunction with Microservices */ /*static const std::string US_INTERFACE_NAME; static const std::string US_PROPKEY_DEVICENAME; static const std::string US_PROPKEY_CLASS; static const std::string US_PROPKEY_ID;*/ protected: AbstractUltrasoundTrackerDevice( USDevice::Pointer usDevice, itk::SmartPointer trackingDevice, bool trackedUltrasoundActive ); virtual ~AbstractUltrasoundTrackerDevice(); itkGetMacro(IsTrackedUltrasoundActive, bool); /** * \brief Grabs the next frame from the input. * Must be implemented by the derived class. * This method is called internally, whenever Update() is invoked by an Output. */ virtual void GenerateData() override; std::string GetIdentifierForCurrentCalibration(); std::string GetIdentifierForCurrentProbe(); std::string GetCurrentDepthValue(); itk::SmartPointer RebuildFilterPipeline(); USDevice::Pointer m_UltrasoundDevice; itk::SmartPointer m_TrackingDeviceDataSource; std::map m_Calibrations; itk::SmartPointer m_SmoothingFilter; itk::SmartPointer m_DelayFilter; + itk::SmartPointer m_DisplacementFilter; unsigned int m_NumberOfSmoothingValues; unsigned int m_DelayCount; /** * \brief The device's ServiceRegistration object that allows to modify it's Microservice registraton details. */ us::ServiceRegistration m_ServiceRegistration; /** * \brief Properties of the device's Microservice. */ us::ServiceProperties m_ServiceProperties; private: bool m_IsTrackedUltrasoundActive; }; } // namespace mitk MITK_DECLARE_SERVICE_INTERFACE(mitk::AbstractUltrasoundTrackerDevice, "org.mitk.services.AbstractUltrasoundTrackerDevice") #endif diff --git a/Modules/US/USNavigation/mitkTrackedUltrasound.cpp b/Modules/US/USNavigation/mitkTrackedUltrasound.cpp new file mode 100644 index 0000000000..ee9a316421 --- /dev/null +++ b/Modules/US/USNavigation/mitkTrackedUltrasound.cpp @@ -0,0 +1,124 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTrackedUltrasound.h" +#include "mitkImageReadAccessor.h" +#include +#include +#include "mitkNavigationDataDisplacementFilter.h" +#include "mitkTrackingDeviceSource.h" + +// US Control Interfaces +#include "mitkUSControlInterfaceProbes.h" +#include "mitkUSControlInterfaceBMode.h" +#include "mitkUSControlInterfaceDoppler.h" + + +mitk::TrackedUltrasound::TrackedUltrasound( USDevice::Pointer usDevice, + NavigationDataSource::Pointer trackingDevice, + bool trackedUltrasoundActive ) + : AbstractUltrasoundTrackerDevice( usDevice, trackingDevice, trackedUltrasoundActive ) +{ +} + +mitk::TrackedUltrasound::~TrackedUltrasound() +{ +} + + + + +mitk::USAbstractControlInterface::Pointer mitk::TrackedUltrasound::GetControlInterfaceCustom() +{ + if (m_UltrasoundDevice.IsNull()) + { + MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; + mitkThrow() << "UltrasoundDevice must not be null."; + } + + return m_UltrasoundDevice->GetControlInterfaceCustom(); +} + +mitk::USControlInterfaceBMode::Pointer mitk::TrackedUltrasound::GetControlInterfaceBMode() +{ + if (m_UltrasoundDevice.IsNull()) + { + MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; + mitkThrow() << "UltrasoundDevice must not be null."; + } + + return m_UltrasoundDevice->GetControlInterfaceBMode(); +} + +mitk::USControlInterfaceProbes::Pointer mitk::TrackedUltrasound::GetControlInterfaceProbes() +{ + if (m_UltrasoundDevice.IsNull()) + { + MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; + mitkThrow() << "UltrasoundDevice must not be null."; + } + + return m_UltrasoundDevice->GetControlInterfaceProbes(); +} + +mitk::USControlInterfaceDoppler::Pointer mitk::TrackedUltrasound::GetControlInterfaceDoppler() +{ + if (m_UltrasoundDevice.IsNull()) + { + MITK_ERROR("USCombinedModality")("USDevice") << "UltrasoundDevice must not be null."; + mitkThrow() << "UltrasoundDevice must not be null."; + } + + return m_UltrasoundDevice->GetControlInterfaceDoppler(); +} + + +void mitk::TrackedUltrasound::GenerateData() +{ + if (m_UltrasoundDevice->GetIsFreezed()) { return; } //if the image is freezed: do nothing + + //get next image from ultrasound image source + mitk::Image::Pointer image = m_UltrasoundDevice->GetUSImageSource()->GetNextImage(); + + if (image.IsNull() || !image->IsInitialized()) //check the image + { + MITK_WARN << "Invalid image in USCombinedModality, aborting!"; + return; + } + + //get output and initialize it if it wasn't initialized before + mitk::Image::Pointer output = this->GetOutput(); + if (!output->IsInitialized()) { output->Initialize(image); } + + //now update image data + mitk::ImageReadAccessor inputReadAccessor(image, image->GetSliceData(0, 0, 0)); + output->SetSlice(inputReadAccessor.GetData()); //copy image data + output->GetGeometry()->SetSpacing(image->GetGeometry()->GetSpacing()); //copy spacing because this might also change + + //and update calibration (= transformation of the image) + std::string calibrationKey = this->GetIdentifierForCurrentCalibration(); + if (!calibrationKey.empty()) + { + std::map::iterator calibrationIterator + = m_Calibrations.find(calibrationKey); + if (calibrationIterator != m_Calibrations.end()) + { + // transform image according to callibration if one is set + // for current configuration of probe and depth + m_DisplacementFilter->SetTransformation(calibrationIterator->second); + } + } +} diff --git a/Modules/US/USNavigation/mitkTrackedUltrasound.h b/Modules/US/USNavigation/mitkTrackedUltrasound.h new file mode 100644 index 0000000000..0a99629c91 --- /dev/null +++ b/Modules/US/USNavigation/mitkTrackedUltrasound.h @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef __mitkTrackedUltrasound_h +#define __mitkTrackedUltrasound_h + +#include +#include "mitkUSDevice.h" +#include "mitkImageSource.h" +#include "mitkAbstractUltrasoundTrackerDevice.h" +#include "mitkNavigationDataSource.h" + +namespace itk { + template class SmartPointer; +} + +namespace mitk { + class USControlInterfaceBMode; + class USControlInterfaceProbes; + class USControlInterfaceDoppler; + + /** + * \brief Combination of USDevice and NavigationDataSource. + * This class can be used as an ImageSource subclass. Additionally tracking data be + * retrieved from the NavigationDataSource returned by GetTrackingDevice(). + * + * A calibration of the ultrasound image stream to the navigation datas can be set + * for the currently active zoom level (of the ultrasound device) by SetCalibration(). + * The ultrasound images are transformed according to this calibration in the + * GenerateData() method. + */ + class MITKUSNAVIGATION_EXPORT TrackedUltrasound : public mitk::AbstractUltrasoundTrackerDevice + { + public: + + mitkClassMacro(TrackedUltrasound, mitk::AbstractUltrasoundTrackerDevice); + mitkNewMacro3Param(TrackedUltrasound, USDevice::Pointer, itk::SmartPointer, bool); + + + /** + * \brief Wrapper for returning custom control interface of the UltrasoundDevice. + */ + virtual itk::SmartPointer GetControlInterfaceCustom() override; + + /** + * \brief Wrapper for returning B mode control interface of the UltrasoundDevice. + */ + virtual itk::SmartPointer GetControlInterfaceBMode() override; + + /** + * \brief Wrapper for returning probes control interface of the UltrasoundDevice. + */ + virtual itk::SmartPointer GetControlInterfaceProbes() override; + + /** + * \brief Wrapper for returning doppler control interface of the UltrasoundDevice. + */ + virtual itk::SmartPointer GetControlInterfaceDoppler() override; + + protected: + TrackedUltrasound( USDevice::Pointer usDevice, + itk::SmartPointer trackingDevice, + bool trackedUltrasoundActive = true ); + virtual ~TrackedUltrasound(); + + /** + * \brief Grabs the next frame from the input. + * This method is called internally, whenever Update() is invoked by an Output. + */ + void GenerateData() override; + + }; +} // namespace mitk +#endif // __mitkTrackedUltrasound_h diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp index 19b7efb0f3..f93de764c0 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.cpp @@ -1,81 +1,92 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkUSCombinedModalityCreationWidget.h" #include "ui_QmitkUSCombinedModalityCreationWidget.h" +#include "mitkTrackedUltrasound.h" + QmitkUSCombinedModalityCreationWidget::QmitkUSCombinedModalityCreationWidget(QWidget *parent) : QWidget(parent), ui(new Ui::QmitkUSCombinedModalityCreationWidget) { ui->setupUi(this); std::string filterExcludeCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(!(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + ")))"; connect(ui->usDevicesServiceList, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnSelectedUltrasoundOrTrackingDevice())); connect(ui->trackingDevicesServiceList, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnSelectedUltrasoundOrTrackingDevice())); ui->usDevicesServiceList->SetAutomaticallySelectFirstEntry(true); ui->trackingDevicesServiceList->SetAutomaticallySelectFirstEntry(true); ui->usDevicesServiceList->Initialize(mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL, filterExcludeCombinedModalities); ui->trackingDevicesServiceList->Initialize(mitk::NavigationDataSource::US_PROPKEY_DEVICENAME); connect(ui->createButton, SIGNAL(clicked()), this, SLOT(OnCreation())); connect(ui->cancelButton, SIGNAL(clicked()), this, SIGNAL(SignalAborted())); } QmitkUSCombinedModalityCreationWidget::~QmitkUSCombinedModalityCreationWidget() { delete ui; } void QmitkUSCombinedModalityCreationWidget::OnCreation() { mitk::USDevice::Pointer usDevice = ui->usDevicesServiceList->GetSelectedService(); if (usDevice.IsNull()) { MITK_WARN << "No Ultrasound Device selected for creation of Combined Modality."; return; } mitk::NavigationDataSource::Pointer trackingDevice = ui->trackingDevicesServiceList->GetSelectedService(); if (trackingDevice.IsNull()) { MITK_WARN << "No Traccking Device selected for creation of Combined Modality."; return; } QString vendor = ui->vendorLineEdit->text(); QString name = ui->nameLineEdit->text(); - if (name.isEmpty()) { name = "Combined Modality"; } + if (name.isEmpty()) { name = "Ultrasound Tracker Device"; } - m_CombinedModality = mitk::USCombinedModality::New(usDevice, trackingDevice, false); + if( ui->activateTrackedUSCheckbox->isChecked() ) + { + m_CombinedModality = mitk::TrackedUltrasound::New(usDevice, trackingDevice, true); + MITK_INFO << "Created TrackedUltrasound device"; + } + else + { + m_CombinedModality = mitk::USCombinedModality::New(usDevice, trackingDevice, false); + MITK_INFO << "Created CombinedModality device"; + } m_CombinedModality->GetUltrasoundDevice()->Initialize(); m_CombinedModality->RegisterAsMicroservice(); // register as micro service emit SignalCreated(); //emit SignalCreated(m_CombinedModality); } void QmitkUSCombinedModalityCreationWidget::OnSelectedUltrasoundOrTrackingDevice() { // create button is enabled only if an ultrasound // and a tracking device is selected ui->createButton->setEnabled( ui->usDevicesServiceList->GetIsServiceSelected() && ui->trackingDevicesServiceList->GetIsServiceSelected()); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui index 8454199a6b..fddd41ad6f 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSCombinedModalityCreationWidget.ui @@ -1,167 +1,174 @@ QmitkUSCombinedModalityCreationWidget 0 0 323 350 0 350 Form 75 true Ultrasound Devices: 0 0 0 0 75 true Tracking Devices: 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Please select an ultrasound device and a tracking device from the lists above. These devices will be used to create a combined modality. Additionally, you may specifiy a vendor and a name.</span></p></body></html> true - - + + - Name + Vendor - - + + - Combined Modality + MBI - - + + - Vendor + Name - - + + - MBI + Combined Modality + + + + Activate Tracked Ultrasound + + + false Create Combined Modality :/USNavigation/accept.png:/USNavigation/accept.png Cancel :/USNavigation/restart.png:/USNavigation/restart.png QmitkServiceListWidget QWidget
QmitkServiceListWidget.h
1
SignalAborted()