diff --git a/CMake/BuildConfigurations/mitkNavigationModules.cmake b/CMake/BuildConfigurations/mitkNavigationModules.cmake index ee7b528cc9..456c1c877c 100644 --- a/CMake/BuildConfigurations/mitkNavigationModules.cmake +++ b/CMake/BuildConfigurations/mitkNavigationModules.cmake @@ -1,37 +1,38 @@ message(STATUS "Configuring MITK Navigation Modules Build") set(MITK_CONFIG_PACKAGES ACVD Qt5 BLUEBERRY ) # Enable open cv and open igt link, which is a necessary configuration set(MITK_USE_OpenCV ON CACHE BOOL "MITK Use OpenCV Library" FORCE) set(MITK_USE_OpenIGTLink ON CACHE BOOL "MITK Use OpenIGTLink Library" FORCE) # Enable default plugins and the navigation modules set(MITK_CONFIG_PLUGINS org.mitk.gui.qt.datamanager org.mitk.gui.qt.stdmultiwidgeteditor org.mitk.gui.qt.dicom org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.properties org.mitk.gui.qt.segmentation org.mitk.gui.qt.volumevisualization org.mitk.planarfigure org.mitk.gui.qt.moviemaker org.mitk.gui.qt.pointsetinteraction org.mitk.gui.qt.registration org.mitk.gui.qt.remeshing org.mitk.gui.qt.viewnavigator org.mitk.gui.qt.imagecropper org.mitk.gui.qt.igtexamples org.mitk.gui.qt.igttracking org.mitk.gui.qt.igtlplugin + org.mitk.gui.qt.openigtlink org.mitk.gui.qt.ultrasound org.mitk.gui.qt.toftutorial org.mitk.gui.qt.tofutil ) diff --git a/CMake/MITK.vcxproj.user.in b/CMake/MITK.vcxproj.user.in index 48fc5df678..7d974043e4 100644 --- a/CMake/MITK.vcxproj.user.in +++ b/CMake/MITK.vcxproj.user.in @@ -1,15 +1,28 @@ PATH=@MITK_RUNTIME_PATH_REL@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_REL@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_REL@;%PATH% WindowsLocalDebugger PATH=@MITK_RUNTIME_PATH_RELDEB@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_RELDEB@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_RELDEB@;%PATH% WindowsLocalDebugger PATH=@MITK_RUNTIME_PATH_DEB@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_DEB@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_DEB@;%PATH% WindowsLocalDebugger + + + PATH=@MITK_RUNTIME_PATH_REL@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_REL@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_REL@;%PATH% + WindowsLocalDebugger + + + PATH=@MITK_RUNTIME_PATH_RELDEB@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_RELDEB@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_RELDEB@;%PATH% + WindowsLocalDebugger + + + PATH=@MITK_RUNTIME_PATH_DEB@;@CUSTOM_RUNTIME_PATH@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\@VS_BUILD_TYPE_DEB@;@CMAKE_RUNTIME_OUTPUT_DIRECTORY@\plugins\@VS_BUILD_TYPE_DEB@;%PATH% + WindowsLocalDebugger + \ No newline at end of file diff --git a/Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.cpp b/Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.cpp similarity index 100% rename from Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.cpp rename to Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.cpp diff --git a/Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.h b/Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.h similarity index 91% rename from Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.h rename to Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.h index da5563a0c3..42579317f2 100644 --- a/Modules/US/USNavigation/Filter/mitkNavigationDataPassThroughFilter.h +++ b/Modules/IGT/Algorithms/mitkNavigationDataPassThroughFilter.h @@ -1,52 +1,52 @@ /*=================================================================== 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 NAVIGATIONDATAPASSTHROUGHFILTER_H #define NAVIGATIONDATAPASSTHROUGHFILTER_H #include "mitkNavigationDataToNavigationDataFilter.h" -#include "MitkUSNavigationExports.h" +#include "MitkIGTExports.h" namespace mitk { /** * \brief Basis for filters that want to leave the navigation data untouched. * * Subclasses can call the mitk::NavigationDataToNavigationDataFilter::GenerateData() * method in their own GenerateData() implementation to pass through navigation data * from all inputs to the outputs. */ -class MITKUSNAVIGATION_EXPORT NavigationDataPassThroughFilter : public NavigationDataToNavigationDataFilter +class MITKIGT_EXPORT NavigationDataPassThroughFilter : public NavigationDataToNavigationDataFilter { public: mitkClassMacro(NavigationDataPassThroughFilter, NavigationDataToNavigationDataFilter) itkNewMacro(Self) protected: NavigationDataPassThroughFilter(); virtual ~NavigationDataPassThroughFilter(); /** * \brief Passes navigation data from all inputs to all outputs. * If a subclass wants to implement its own version of the GenerateData() * method it should call this method inside its implementation. */ virtual void GenerateData() override; }; } // namespace mitk #endif // NAVIGATIONDATAPASSTHROUGHFILTER_H diff --git a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp b/Modules/IGT/Algorithms/mitkNeedleProjectionFilter.cpp similarity index 75% rename from Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp rename to Modules/IGT/Algorithms/mitkNeedleProjectionFilter.cpp index 4b4065d024..6854335767 100644 --- a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.cpp +++ b/Modules/IGT/Algorithms/mitkNeedleProjectionFilter.cpp @@ -1,169 +1,198 @@ /*=================================================================== 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. ===================================================================*/ // MITK #include "mitkNeedleProjectionFilter.h" #include -#include "mitkUSCombinedModality.h" +// Vermutung - wird nicht benötigt: #include "mitkUSCombinedModality.h" // VTK #include - - mitk::NeedleProjectionFilter::NeedleProjectionFilter() : m_Projection(mitk::PointSet::New()), m_OriginalPoints(mitk::PointSet::New()), + m_ShowToolAxis(false), m_SelectedInput(-1) { // Tool Coordinates:x axis is chosen as default axis when no axis is specified - for (int i = 0; i < 2; i++) + + MITK_DEBUG << "Constructor called"; + + mitk::Point3D toolAxis; + mitk::FillVector3D(toolAxis, 1, 0, 0); + m_ToolAxis = toolAxis; + InitializeOriginalPoints(toolAxis, m_ShowToolAxis); + + MITK_DEBUG << "orginal point 0 set constructor" << m_OriginalPoints->GetPoint(0); + MITK_DEBUG << "orginal point 1 set constructor" << m_OriginalPoints->GetPoint(1); +} + +void mitk::NeedleProjectionFilter::InitializeOriginalPoints(mitk::Point3D toolAxis, bool showToolAxis) +{ + m_OriginalPoints = mitk::PointSet::New(); + + mitk::Point3D projectionPoint; + projectionPoint.SetElement(0, toolAxis.GetElement(0) * 400); + projectionPoint.SetElement(1, toolAxis.GetElement(1) * 400); + projectionPoint.SetElement(2, toolAxis.GetElement(2) * 400); + m_OriginalPoints->InsertPoint(projectionPoint); + + mitk::Point3D toolOrigin; + toolOrigin.SetElement(0, 0); + toolOrigin.SetElement(1, 0); + toolOrigin.SetElement(2, 0); + m_OriginalPoints->InsertPoint(toolOrigin); + + if (showToolAxis) { - mitk::Point3D point; - point.SetElement(0, i * 400); - point.SetElement(1, 0); - point.SetElement(2, 0); - m_OriginalPoints->InsertPoint(i, point); + mitk::Point3D axisPoint; + axisPoint.SetElement(0, toolAxis.GetElement(0) * -400); + axisPoint.SetElement(1, toolAxis.GetElement(1) * -400); + axisPoint.SetElement(2, toolAxis.GetElement(2) * -400); + m_OriginalPoints->InsertPoint(axisPoint); } + +} + +void mitk::NeedleProjectionFilter::ShowToolAxis(bool enabled) +{ + m_ShowToolAxis = enabled; + InitializeOriginalPoints(m_ToolAxis,m_ShowToolAxis); } void mitk::NeedleProjectionFilter::SetToolAxisForFilter(mitk::Point3D point) { - // Tool Coordinates: First point - Tip of Needle, Second Point - 40 cm distance from needle - mitk::Point3D originPoint; - originPoint.SetElement(0, 0); - originPoint.SetElement(1, 0); - originPoint.SetElement(2, 0); - m_OriginalPoints->SetPoint(0, originPoint); - - mitk::Point3D endPoint; - endPoint.SetElement(0, point.GetElement(0) * 400); - endPoint.SetElement(1, point.GetElement(1) * 400); - endPoint.SetElement(2, point.GetElement(2) * 400); - MITK_INFO << "Tool axis in project filter:"; - MITK_INFO << endPoint; - m_OriginalPoints->SetPoint(1, endPoint); + m_ToolAxis = point; + InitializeOriginalPoints(m_ToolAxis, m_ShowToolAxis); + + MITK_DEBUG << "orginal point 1 set mutator" << m_OriginalPoints->GetPoint(1); + MITK_DEBUG << "orginal point 0 set mutator" << m_OriginalPoints->GetPoint(0); } mitk::NeedleProjectionFilter::~NeedleProjectionFilter() { } void mitk::NeedleProjectionFilter::SelectInput(int i) { if (i < 0) mitkThrow() << "Negative Input selected in NeedleProjectionFilter"; if (! (static_cast(i) < this->GetInputs().size())) mitkThrow() << "Selected input index is larger than actual number of inputs in NeedleProjectionFilter"; m_SelectedInput = i; } void mitk::NeedleProjectionFilter::GenerateData() { // copy the navigation data from the inputs to the outputs mitk::NavigationDataPassThroughFilter::GenerateData(); // If no reference has been set yet, warn and abort if (m_SelectedInput == -1) { MITK_INFO << "No input has been selected in NeedleProjection Filter. Only forwarding NavigationData..."; return; } // Cancel, if selected tool is currently not being tracked if (! GetInput(m_SelectedInput)->IsDataValid()) return; // Outputs have been updated, now to calculate the Projection // 1) Generate Pseudo-Geometry for Input mitk::AffineTransform3D::Pointer refTrans = this->NavigationDataToTransform(this->GetInput(m_SelectedInput)); mitk::Geometry3D::Pointer refGeom = this->TransformToGeometry(refTrans); + // 2) Transform Original Pointset m_OriginalPoints->SetGeometry(refGeom); // Update Projection (We do not clone, since we want to keep properties alive) m_Projection->SetPoint(0, m_OriginalPoints->GetPoint(0)); m_Projection->SetPoint(1, m_OriginalPoints->GetPoint(1)); + if (m_ShowToolAxis) { m_Projection->SetPoint(2, m_OriginalPoints->GetPoint(2)); } + // 3a) If no target Plane has been set, then leave it at that if (this->m_TargetPlane.IsNull()) return; // 3b) else, calculate intersection with plane mitk::PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); plane->SetIndexToWorldTransform(m_TargetPlane); //plane->TransferItkToVtkTransform(); //included in SetIndexToWorldTransform double t; double x[3]; // Points that define the needle vector double p1[3] = {m_OriginalPoints->GetPoint(0)[0], m_OriginalPoints->GetPoint(0)[1], m_OriginalPoints->GetPoint(0)[2]}; double p2[3] = {m_OriginalPoints->GetPoint(1)[0], m_OriginalPoints->GetPoint(1)[1], m_OriginalPoints->GetPoint(1)[2]}; // Center of image plane and it's normal double center[3] = {plane->GetCenter()[0], plane->GetCenter()[1], plane->GetCenter()[2]}; double normal[3] = {plane->GetNormal()[0], plane->GetNormal()[1], plane->GetNormal()[2]}; vtkPlane::IntersectWithLine(p1, p2, normal, center, t, x); // change (cut) needle path only if the needle points to the image plane; // otherwise the needle path direction would be changed pointing to the image plane if ( t >= 0 ) { // Convert vtk to itk mitk::Point3D intersection; intersection[0] = x[0]; intersection[1] = x[1]; intersection[2] = x[2]; // Replace distant point with image intersection - m_Projection->SetPoint(1, intersection); + m_Projection->SetPoint(0, intersection); + } } mitk::AffineTransform3D::Pointer mitk::NeedleProjectionFilter::NavigationDataToTransform(const mitk::NavigationData * nd) { mitk::AffineTransform3D::Pointer affineTransform = mitk::AffineTransform3D::New(); affineTransform->SetIdentity(); //calculate the transform from the quaternions static itk::QuaternionRigidTransform::Pointer quatTransform = itk::QuaternionRigidTransform::New(); mitk::NavigationData::OrientationType orientation = nd->GetOrientation(); // convert mitk::ScalarType quaternion to double quaternion because of itk bug vnl_quaternion doubleQuaternion(orientation.x(), orientation.y(), orientation.z(), orientation.r()); quatTransform->SetIdentity(); quatTransform->SetRotation(doubleQuaternion); quatTransform->Modified(); /* because of an itk bug, the transform can not be calculated with float data type. To use it in the mitk geometry classes, it has to be transfered to mitk::ScalarType which is float */ static AffineTransform3D::MatrixType m; mitk::TransferMatrix(quatTransform->GetMatrix(), m); affineTransform->SetMatrix(m); /*set the offset by convert from itkPoint to itkVector and setting offset of transform*/ mitk::Vector3D pos; pos.SetVnlVector(nd->GetPosition().GetVnlVector()); affineTransform->SetOffset(pos); affineTransform->Modified(); return affineTransform; } mitk::Geometry3D::Pointer mitk::NeedleProjectionFilter::TransformToGeometry(mitk::AffineTransform3D::Pointer transform){ mitk::Geometry3D::Pointer g3d = mitk::Geometry3D::New(); mitk::ScalarType scale[] = {1.0, 1.0, 1.0}; g3d->SetSpacing(scale); g3d->SetIndexToWorldTransform(transform); //g3d->TransferItkToVtkTransform(); // update VTK Transform for rendering too //included in SetIndexToWorldTransform g3d->Modified(); return g3d; } diff --git a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.h b/Modules/IGT/Algorithms/mitkNeedleProjectionFilter.h similarity index 78% rename from Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.h rename to Modules/IGT/Algorithms/mitkNeedleProjectionFilter.h index 1b03ffd6ea..845a2a9b48 100644 --- a/Modules/US/USNavigation/Filter/mitkNeedleProjectionFilter.h +++ b/Modules/IGT/Algorithms/mitkNeedleProjectionFilter.h @@ -1,86 +1,97 @@ /*=================================================================== 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 NEEDLEPROJECTIONFILTER_H_INCLUDED #define NEEDLEPROJECTIONFILTER_H_INCLUDED -#include +#include "MitkIGTExports.h" // MITK #include #include #include #include namespace mitk { /** * \brief This filter projects a needle's path onto a plane. * * To use it, hook it up to a NavigationDataStream, * select an input and set an AffineTransform 3D that represents the target plane. * You can then call GetProjection to retrieve a pointset that represents the projected path. * You may change the PointSet's properties, these changes will not be overwritten. * If no Input is selected, the target Pointset will not update * If no Target Plane is selected, The projection line will always be 40 cm long * Any points you add to the pointSet will be overwritten during the next Update. * The point with index zero is the Tip of the Needle. * The Point with index one is the projection onto the plane. * * Projection will happen onto an extension of the plane as well - the filter does not regard boundaries * This Filter currently only supports projection of one needle. Extension to multiple needles / planes should be easy. * - * \ingroup US + * \ingroup IGT */ - class MITKUSNAVIGATION_EXPORT NeedleProjectionFilter : public NavigationDataPassThroughFilter + class MITKIGT_EXPORT NeedleProjectionFilter : public NavigationDataPassThroughFilter { public: mitkClassMacro(NeedleProjectionFilter, NavigationDataPassThroughFilter); itkNewMacro(Self); virtual void SelectInput(int i); itkGetMacro(TargetPlane, mitk::AffineTransform3D::Pointer); itkSetMacro(TargetPlane, mitk::AffineTransform3D::Pointer); itkGetMacro(Projection, mitk::PointSet::Pointer); + /** Sets the tool axis for this filter. The default tool axis is along the x-axis in + * tool coordinates. */ void SetToolAxisForFilter(mitk::Point3D point); + /** Sets whether the tool axis should be visualized. This is required if no surface is available. + * If disabled only the projection and not the axis is shown. It's disabled by default. */ + void ShowToolAxis(bool enabled); protected: NeedleProjectionFilter(); virtual ~NeedleProjectionFilter(); virtual void GenerateData() override; mitk::AffineTransform3D::Pointer m_TargetPlane; mitk::PointSet::Pointer m_Projection; mitk::PointSet::Pointer m_OriginalPoints; + bool m_ShowToolAxis; + mitk::Point3D m_ToolAxis; int m_SelectedInput; + /** Internal method for initialization of the projection / tool axis representation + * by the point set m_OriginalPoints. */ + void InitializeOriginalPoints(mitk::Point3D toolAxis, bool showToolAxis); + /** * \brief Creates an Affine Transformation from a Navigation Data Object. */ mitk::AffineTransform3D::Pointer NavigationDataToTransform(const mitk::NavigationData * nd); /** * \brief Creates an Geometry 3D Object from an AffineTransformation. */ mitk::Geometry3D::Pointer TransformToGeometry(mitk::AffineTransform3D::Pointer transform); }; } // namespace mitk #endif diff --git a/Modules/IGT/Common/mitkTrackingTypes.h b/Modules/IGT/Common/mitkTrackingTypes.h index 7cf0a0250b..dbb7c5db5e 100644 --- a/Modules/IGT/Common/mitkTrackingTypes.h +++ b/Modules/IGT/Common/mitkTrackingTypes.h @@ -1,93 +1,94 @@ /*=================================================================== 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 MITKTRACKINGTYPES_H_HEADER_INCLUDED_ #define MITKTRACKINGTYPES_H_HEADER_INCLUDED_ #include #include #include namespace mitk { typedef std::string TrackingDeviceType; /** * /brief This structure defines key variables of a device model and type. + * Line is (usually) identical with the TrackingDeviceName and can be used to compare TrackingDevices (string). * It is specifically used to find out which models belong to which vendor, and what volume * to use for a specific Model. Leaving VolumeModelLocation set to null will instruct the Generator * to generate a field to the best of his ability. HardwareCode stands for a hexadecimal string, * that represents the tracking volume. "X" stands for "hardwarecode is not known" or "tracking device has * no hardware code". For NDI devices it is used in the SetVolume() Method in mitkNDITrackingDevice.cpp. * The Pyramid Volume has the hardwarecode "4", but it is not supported yet. */ struct TrackingDeviceData { TrackingDeviceType Line; std::string Model; std::string VolumeModelLocation; std::string HardwareCode; }; /**Documentation * \brief Error codes of NDI tracking devices */ enum OperationMode { ToolTracking6D, ToolTracking5D, MarkerTracking3D, HybridTracking }; /**Documentation * \brief activation rate of IR illuminator for NDI Polaris tracking device */ enum IlluminationActivationRate { Hz20 = 20, Hz30 = 30, Hz60 = 60 }; /**Documentation * \brief Data transfer mode for NDI tracking devices */ enum DataTransferMode { TX = 0, BX = 1 }; /**Documentation * \brief Query mode for NDI tracking devices */ enum PHSRQueryType { ALL = 0x00, FREED = 0x01, OCCUPIED = 0x02, INITIALIZED = 0x03, ENABLED = 0x04 }; typedef itk::Point MarkerPointType; typedef std::vector MarkerPointContainerType; /** definition of colors for IGT */ static mitk::Color IGTColor_WARNING = mitk::ColorProperty::New(1.0f, 0.0f, 0.0f)->GetColor(); static mitk::Color IGTColor_VALID = mitk::ColorProperty::New(0.0f, 1.0f, 0.0f)->GetColor(); } // namespace mitk #endif /* MITKTRACKINGTYPES_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/DataManagement/mitkNavigationTool.cpp b/Modules/IGT/DataManagement/mitkNavigationTool.cpp index 02e48810a0..1763aeecfe 100644 --- a/Modules/IGT/DataManagement/mitkNavigationTool.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationTool.cpp @@ -1,134 +1,336 @@ /*=================================================================== 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 "mitkNavigationTool.h" #include "mitkIGTException.h" #include "mitkNavigationData.h" #include "Poco/File.h" #include "mitkUnspecifiedTrackingTypeInformation.h" +#include "mitkInternalTrackingTool.h" + +#include "vtkSphereSource.h" +#include "vtkConeSource.h" +#include "vtkLineSource.h" +#include "vtkCylinderSource.h" +#include "vtkTransformPolyDataFilter.h" +#include +#include "mitkTextAnnotation3D.h" +#include "mitkManualPlacementAnnotationRenderer.h" +#include "mitkBaseRenderer.h" mitk::NavigationTool::NavigationTool() : m_Identifier("None"), - m_Type(mitk::NavigationTool::Unknown), - m_CalibrationFile("none"), - m_SerialNumber(""), - m_TrackingDeviceType(mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()), - m_ToolRegistrationLandmarks(mitk::PointSet::New()), - m_ToolCalibrationLandmarks(mitk::PointSet::New()), - m_ToolTipOrientation(mitk::Quaternion(0,0,0,1)) - { - m_ToolTipPosition[0] = 0; - m_ToolTipPosition[1] = 0; - m_ToolTipPosition[2] = 0; +m_Type(mitk::NavigationTool::Unknown), +m_CalibrationFile("none"), +m_SerialNumber(""), +m_TrackingDeviceType(mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()), +m_ToolRegistrationLandmarks(mitk::PointSet::New()), +m_ToolCalibrationLandmarks(mitk::PointSet::New()), +m_ToolTipOrientation(mitk::Quaternion(0, 0, 0, 1)) +{ + m_ToolTipPosition[0] = 0; + m_ToolTipPosition[1] = 0; + m_ToolTipPosition[2] = 0; - m_ToolAxis[0] = 1; - m_ToolAxis[1] = 0; - m_ToolAxis[2] = 0; - } + m_ToolAxis[0] = 1; + m_ToolAxis[1] = 0; + m_ToolAxis[2] = 0; -mitk::NavigationTool::~NavigationTool() - { + SetDefaultSurface(); +} + +itk::LightObject::Pointer mitk::NavigationTool::InternalClone() const +{ + Self::Pointer tool = new Self(*this); + tool->UnRegister(); + return tool.GetPointer(); +} +mitk::NavigationTool::NavigationTool(const NavigationTool &other) + : Superclass() +{ + this->m_Identifier = other.m_Identifier; + this->m_Type = other.m_Type; + if (other.m_DataNode.IsNotNull()) + { + this->m_DataNode = other.m_DataNode->Clone(); + this->m_DataNode->SetName(other.m_DataNode->GetName()); + if (other.m_DataNode->GetData()) + { + this->m_DataNode->SetData(dynamic_cast(other.m_DataNode->GetData()->Clone().GetPointer())); + } } + if (other.m_SpatialObject.IsNotNull()) + this->m_SpatialObject = other.m_SpatialObject->Clone(); + this->m_CalibrationFile = other.m_CalibrationFile; + this->m_SerialNumber = other.m_SerialNumber; + this->m_TrackingDeviceType = other.m_TrackingDeviceType; + if (other.m_ToolRegistrationLandmarks.IsNotNull()) + this->m_ToolRegistrationLandmarks = other.m_ToolRegistrationLandmarks->Clone(); + if (other.m_ToolCalibrationLandmarks.IsNotNull()) + this->m_ToolCalibrationLandmarks = other.m_ToolCalibrationLandmarks->Clone(); + this->m_ToolTipPosition = other.m_ToolTipPosition; + this->m_ToolTipOrientation = other.m_ToolTipOrientation; + this->m_ToolAxis = other.m_ToolAxis; +} + +mitk::NavigationTool::~NavigationTool() +{ +} + mitk::AffineTransform3D::Pointer mitk::NavigationTool::GetToolTipTransform() - { - mitk::NavigationData::Pointer returnValue = mitk::NavigationData::New(); - returnValue->SetPosition(this->m_ToolTipPosition); - returnValue->SetOrientation(this->m_ToolTipOrientation); - return returnValue->GetAffineTransform3D(); - } - -void mitk::NavigationTool::Graft( const DataObject *data ) +{ + mitk::NavigationData::Pointer returnValue = mitk::NavigationData::New(); + returnValue->SetPosition(this->m_ToolTipPosition); + returnValue->SetOrientation(this->m_ToolTipOrientation); + return returnValue->GetAffineTransform3D(); +} + +void mitk::NavigationTool::Graft(const DataObject *data) { // Attempt to cast data to an NavigationData const Self* nd; try { - nd = dynamic_cast( data ); + nd = dynamic_cast(data); } - catch( ... ) + catch (...) { mitkThrowException(mitk::IGTException) << "mitk::NavigationData::Graft cannot cast " << typeid(data).name() << " to " - << typeid(const Self *).name() ; + << typeid(const Self *).name(); } if (!nd) { // pointer could not be cast back down mitkThrowException(mitk::IGTException) << "mitk::NavigationData::Graft cannot cast " << typeid(data).name() << " to " - << typeid(const Self *).name() ; + << typeid(const Self *).name(); } // Now copy anything that is needed m_Identifier = nd->GetIdentifier(); m_Type = nd->GetType(); m_DataNode->SetName(nd->GetDataNode()->GetName()); m_DataNode->SetData(nd->GetDataNode()->GetData()); m_SpatialObject = nd->GetSpatialObject(); - m_TrackingTool = nd->GetTrackingTool(); m_CalibrationFile = nd->GetCalibrationFile(); m_SerialNumber = nd->GetSerialNumber(); m_TrackingDeviceType = nd->GetTrackingDeviceType(); m_ToolRegistrationLandmarks = nd->GetToolRegistrationLandmarks(); m_ToolCalibrationLandmarks = nd->GetToolCalibrationLandmarks(); m_ToolTipPosition = nd->GetToolTipPosition(); m_ToolTipOrientation = nd->GetToolTipOrientation(); m_ToolAxis = nd->GetToolAxis(); - } bool mitk::NavigationTool::IsToolTipSet() - { - if( (m_ToolTipPosition[0] == 0) && +{ + if ((m_ToolTipPosition[0] == 0) && (m_ToolTipPosition[1] == 0) && (m_ToolTipPosition[2] == 0) && (m_ToolTipOrientation.x() == 0) && (m_ToolTipOrientation.y() == 0) && (m_ToolTipOrientation.z() == 0) && (m_ToolTipOrientation.r() == 1)) - return false; + return false; else return true; - } +} void mitk::NavigationTool::SetCalibrationFile(const std::string filename) - { +{ //check if file does exist: - if (filename=="") - { + if (filename == "") + { m_CalibrationFile = "none"; - } + } else - { + { Poco::File myFile(filename); if (myFile.exists()) m_CalibrationFile = filename; else m_CalibrationFile = "none"; - } } +} std::string mitk::NavigationTool::GetToolName() - { - if (this->m_DataNode.IsNull()) {return "";} - else {return m_DataNode->GetName();} - } +{ + if (this->m_DataNode.IsNull()) { return ""; } + else { return m_DataNode->GetName(); } +} mitk::Surface::Pointer mitk::NavigationTool::GetToolSurface() - { - if (this->m_DataNode.IsNull()) {return nullptr;} - else if (this->m_DataNode->GetData() == nullptr) {return nullptr;} - else {return dynamic_cast(m_DataNode->GetData());} - } +{ + if (this->m_DataNode.IsNull()) { return nullptr; } + else if (this->m_DataNode->GetData() == nullptr) { return nullptr; } + else { return dynamic_cast(m_DataNode->GetData()); } +} + +void mitk::NavigationTool::SetDefaultSurface() +{ + if (m_DataNode.IsNull()) + m_DataNode = mitk::DataNode::New(); + + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + + double axisLength = 5.; + + vtkSphereSource *vtkSphere = vtkSphereSource::New(); + vtkConeSource *vtkCone = vtkConeSource::New(); + vtkCylinderSource *vtkCylinder = vtkCylinderSource::New(); + vtkPolyData* axis = vtkPolyData::New(); + vtkLineSource *vtkLine = vtkLineSource::New(); + vtkLineSource *vtkLine2 = vtkLineSource::New(); + vtkLineSource *vtkLine3 = vtkLineSource::New(); + + vtkAppendPolyData* appendPolyData = vtkAppendPolyData::New(); + vtkPolyData* surface = vtkPolyData::New(); + + //Y-Axis (start with y, cause cylinder is oriented in y by vtk default...) + vtkCone->SetDirection(0, 1, 0); + vtkCone->SetHeight(1.0); + vtkCone->SetRadius(0.4f); + vtkCone->SetResolution(16); + vtkCone->SetCenter(0.0, axisLength, 0.0); + vtkCone->Update(); + + vtkCylinder->SetRadius(0.05); + vtkCylinder->SetHeight(axisLength); + vtkCylinder->SetCenter(0.0, 0.5*axisLength, 0.0); + vtkCylinder->Update(); + + appendPolyData->AddInputData(vtkCone->GetOutput()); + appendPolyData->AddInputData(vtkCylinder->GetOutput()); + appendPolyData->Update(); + axis->DeepCopy(appendPolyData->GetOutput()); + + //y symbol + vtkLine->SetPoint1(-0.5, axisLength + 2., 0.0); + vtkLine->SetPoint2(0.0, axisLength + 1.5, 0.0); + vtkLine->Update(); + + vtkLine2->SetPoint1(0.5, axisLength + 2., 0.0); + vtkLine2->SetPoint2(-0.5, axisLength + 1., 0.0); + vtkLine2->Update(); + + appendPolyData->AddInputData(vtkLine->GetOutput()); + appendPolyData->AddInputData(vtkLine2->GetOutput()); + appendPolyData->AddInputData(axis); + appendPolyData->Update(); + surface->DeepCopy(appendPolyData->GetOutput()); + + //X-axis + vtkTransform *XTransform = vtkTransform::New(); + XTransform->RotateZ(-90); + vtkTransformPolyDataFilter *TrafoFilter = vtkTransformPolyDataFilter::New(); + TrafoFilter->SetTransform(XTransform); + TrafoFilter->SetInputData(axis); + TrafoFilter->Update(); + + //x symbol + vtkLine->SetPoint1(axisLength + 2., -0.5, 0.0); + vtkLine->SetPoint2(axisLength + 1., 0.5, 0.0); + vtkLine->Update(); + + vtkLine2->SetPoint1(axisLength + 2., 0.5, 0.0); + vtkLine2->SetPoint2(axisLength + 1., -0.5, 0.0); + vtkLine2->Update(); + + appendPolyData->AddInputData(vtkLine->GetOutput()); + appendPolyData->AddInputData(vtkLine2->GetOutput()); + appendPolyData->AddInputData(TrafoFilter->GetOutput()); + appendPolyData->AddInputData(surface); + appendPolyData->Update(); + surface->DeepCopy(appendPolyData->GetOutput()); + + //Z-axis + vtkTransform *ZTransform = vtkTransform::New(); + ZTransform->RotateX(90); + TrafoFilter->SetTransform(ZTransform); + TrafoFilter->SetInputData(axis); + TrafoFilter->Update(); + + //z symbol + vtkLine->SetPoint1(-0.5, 0.0, axisLength + 2.); + vtkLine->SetPoint2(0.5, 0.0, axisLength + 2.); + vtkLine->Update(); + + vtkLine2->SetPoint1(-0.5, 0.0, axisLength + 2.); + vtkLine2->SetPoint2(0.5, 0.0, axisLength + 1.); + vtkLine2->Update(); + + vtkLine3->SetPoint1(0.5, 0.0, axisLength + 1.); + vtkLine3->SetPoint2(-0.5, 0.0, axisLength + 1.); + vtkLine3->Update(); + + appendPolyData->AddInputData(vtkLine->GetOutput()); + appendPolyData->AddInputData(vtkLine2->GetOutput()); + appendPolyData->AddInputData(vtkLine3->GetOutput()); + appendPolyData->AddInputData(TrafoFilter->GetOutput()); + appendPolyData->AddInputData(surface); + appendPolyData->Update(); + surface->DeepCopy(appendPolyData->GetOutput()); + + //Center + vtkSphere->SetRadius(0.5f); + vtkSphere->SetCenter(0.0, 0.0, 0.0); + vtkSphere->Update(); + + appendPolyData->AddInputData(vtkSphere->GetOutput()); + appendPolyData->AddInputData(surface); + appendPolyData->Update(); + surface->DeepCopy(appendPolyData->GetOutput()); + + //Scale + vtkTransform *ScaleTransform = vtkTransform::New(); + ScaleTransform->Scale(20., 20., 20.); + + TrafoFilter->SetTransform(ScaleTransform); + TrafoFilter->SetInputData(surface); + TrafoFilter->Update(); + + mySphere->SetVtkPolyData(TrafoFilter->GetOutput()); + + vtkCone->Delete(); + vtkSphere->Delete(); + vtkLine->Delete(); + vtkLine2->Delete(); + vtkLine3->Delete(); + vtkCylinder->Delete(); + ZTransform->Delete(); + XTransform->Delete(); + ScaleTransform->Delete(); + TrafoFilter->Delete(); + appendPolyData->Delete(); + surface->Delete(); + + this->GetDataNode()->SetData(mySphere); +} + +std::string mitk::NavigationTool::GetStringWithAllToolInformation() const +{ + std::stringstream _info; + _info << " Identifier: " << this->m_Identifier << "\n" + << " NavigationToolType: " << m_Type << "\n" + << " Calibration file: " << m_CalibrationFile << "\n" + << " Serial number: " << m_SerialNumber << "\n" + << " TrackingDeviceType: " << m_TrackingDeviceType << "\n" + << " ToolTip Position: " << m_ToolTipPosition << "\n" + << " ToolTip Orientation: " << m_ToolTipOrientation << "\n" + << " ToolTip Axis: " << m_ToolAxis; + + return _info.str(); +} \ No newline at end of file diff --git a/Modules/IGT/DataManagement/mitkNavigationTool.h b/Modules/IGT/DataManagement/mitkNavigationTool.h index 04ce577314..d77d3ea8de 100644 --- a/Modules/IGT/DataManagement/mitkNavigationTool.h +++ b/Modules/IGT/DataManagement/mitkNavigationTool.h @@ -1,206 +1,212 @@ /*=================================================================== 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 NAVIGATIONTOOL_H_INCLUDED #define NAVIGATIONTOOL_H_INCLUDED //itk headers #include #include #include //mitk headers #include #include #include #include #include #include #include namespace mitk { /**Documentation * \brief An object of this class represents a navigation tool in the view of the software. * A few informations like an identifier, a toolname, a surface and a itk spatial * object are stored in such an object. The classes NavigationToolReader and * are availiable to write/read tools to/from the harddisc. If you need a collection * of navigation tools the class NavigationToolStorage could be used. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationTool : public itk::DataObject { public: mitkClassMacroItkParent(NavigationTool,itk::DataObject); itkFactorylessNewMacro(Self) itkCloneMacro(Self) enum NavigationToolType {Instrument, Fiducial, Skinmarker, Unknown}; //## getter and setter ## //NavigationToolType: itkGetConstMacro(Type,NavigationToolType); itkSetMacro(Type,NavigationToolType); //Identifier: itkGetConstMacro(Identifier,std::string); itkSetMacro(Identifier,std::string); //Datatreenode: itkGetConstMacro(DataNode,mitk::DataNode::Pointer); itkSetMacro(DataNode,mitk::DataNode::Pointer); //SpatialObject: itkGetConstMacro(SpatialObject,itk::SpatialObject<3>::Pointer); itkSetMacro(SpatialObject,itk::SpatialObject<3>::Pointer); - //TrackingTool: - itkGetConstMacro(TrackingTool,mitk::TrackingTool::Pointer); - itkSetMacro(TrackingTool,mitk::TrackingTool::Pointer); - //CalibrationFile: itkGetConstMacro(CalibrationFile,std::string); void SetCalibrationFile(const std::string filename); //Tool tip definition: itkGetConstMacro(ToolTipPosition,mitk::Point3D); itkSetMacro(ToolTipPosition,mitk::Point3D); itkGetConstMacro(ToolTipOrientation,mitk::Quaternion); itkSetMacro(ToolTipOrientation,mitk::Quaternion); //Tool Axis definition: //default tool axis is along x axis, the tool axis must be normalized itkGetConstMacro(ToolAxis, mitk::Point3D); itkSetMacro(ToolAxis, mitk::Point3D); /** @return Returns the tooltip as transform object. */ mitk::AffineTransform3D::Pointer GetToolTipTransform(); /** @return Returns true if a tooltip is set, false if not. */ bool IsToolTipSet(); //Tool Landmarks: /** For overview, here are descriptons of the two types of tool landmarks: * * tool calibration landmarks: These landmarks may be used clearly define the tools pose only by * using landmarks in the tool coordinate system. E.g., two landmarks for a 5DoF tool and three * landmarks for a 6DoF tool. These landmarks may be used, e.g., for a point based registration * of a tool from image space to tracking space. * * tool registration landmarks: These landmarks are designed for representing defined landmarks * on a tools surface. The number of these landmarks might exeed the number of tool calibration * landmarks for reasons of redundancy and averaging. They are used for, e.g., manually registering * the pose of a tool by visual markers in a CT scan. If you would use these landmarks to do a * point based registration from image space to tracking space later, you might overweight the * tool because of two many landmarks compared to other markers. * * @return Returns the tool registration landmarks which represent markers / special points on a * tool that can be used for registration. The landmarks should be given in tool coordinates. * If there are no landmarks defined for this tool the method returns an empty point set. */ itkGetConstMacro(ToolRegistrationLandmarks,mitk::PointSet::Pointer); /** @brief Sets the tool registration landmarks which represent markers / special points on a * tool that can be used for registration. The landmarks should be given in tool coordinates. */ itkSetMacro(ToolRegistrationLandmarks,mitk::PointSet::Pointer); /** @return Returns the tool calibration landmarks for calibration of the defined points in the * tool coordinate system, e.g. 2 landmarks for a 5DoF tool and 3 landmarks for a 6DoF tool. */ itkGetConstMacro(ToolCalibrationLandmarks,mitk::PointSet::Pointer); /** @brief Sets the tool calibration landmarks for calibration of defined points in the * tool coordinate system, e.g. 2 landmarks for a 5DoF tool and 3 landmarks for a 6DoF tool. */ itkSetMacro(ToolCalibrationLandmarks,mitk::PointSet::Pointer); //SerialNumber: itkGetConstMacro(SerialNumber,std::string); itkSetMacro(SerialNumber,std::string); //TrackingDeviceType: itkGetConstMacro(TrackingDeviceType,mitk::TrackingDeviceType); itkSetMacro(TrackingDeviceType,mitk::TrackingDeviceType); //ToolName (only getter): /** @return Returns the name of this navigation tool. Returns an empty string if there is * no name (for example because the data node has not been set yet). * * Note: There is no setter for the name, * because the name of the corresponding data node is used as tool name. So if you * want to modify the name of this navigation tool only get the data node and modify * its name. */ std::string GetToolName(); //ToolSurface (only getter): /** @return Returns the surface of this navigation tool. Returns nullptr if there is * no surface (for example because the data node has not been set yet). * * Note: There is no setter for the surface, * because the surface is the data of the corresponding data node. So if you * want to set a new surface only get the data node and modify its data. */ mitk::Surface::Pointer GetToolSurface(); /** * \brief Graft the data and information from one NavigationTool to another. * * Copies the content of data into this object. * This is a convenience method to setup a second NavigationTool object with all the meta * information of another NavigationTool object. * Note that this method is different than just using two * SmartPointers to the same NavigationTool object since separate DataObjects are * still maintained. */ virtual void Graft(const DataObject *data) override; + + + /** + * Return all relevant information as string, e.g. to display all tool information + */ + std::string GetStringWithAllToolInformation() const; + + + void SetDefaultSurface(); + //####################### protected: NavigationTool(); + NavigationTool(const NavigationTool &other); ~NavigationTool(); + virtual itk::LightObject::Pointer InternalClone() const override; //## data structure of a navigation tool object ## std::string m_Identifier; NavigationToolType m_Type; /** @brief This DataNode holds a toolname and a tool surface */ mitk::DataNode::Pointer m_DataNode; /** @brief This member variable holds a mathamatical description of the tool */ itk::SpatialObject<3>::Pointer m_SpatialObject; - /** @brief This member variable holds a pointer to the corresponding tracking tool in the hardware. */ - mitk::TrackingTool::Pointer m_TrackingTool; /** @brief The path to the calibration file of the tool. */ std::string m_CalibrationFile; /** @brief A unique serial number of the tool which is needed to identify the tool correctly. This is very important * in case of the NDI Aurora System. */ std::string m_SerialNumber; /** @brief This member holds the tracking device type of the tool. */ mitk::TrackingDeviceType m_TrackingDeviceType; /** @brief Holds landmarks for tool registration. */ mitk::PointSet::Pointer m_ToolRegistrationLandmarks; /** @brief Holds landmarks for calibration of the defined points in the tool coordinate system, * e.g. 2 landmarks for a 5DoF tool and 3 landmarks for a 6DoF tool. */ mitk::PointSet::Pointer m_ToolCalibrationLandmarks; /** @brief Holds the position of the tool tip. */ mitk::Point3D m_ToolTipPosition; /** @brief Holds the orientation of the tool tip. */ mitk::Quaternion m_ToolTipOrientation; /** @brief Holds the axis of the tool. */ mitk::Point3D m_ToolAxis; //################################################# }; } // namespace mitk #endif //NAVIGATIONTOOL diff --git a/Modules/IGT/DataManagement/mitkNavigationToolStorage.cpp b/Modules/IGT/DataManagement/mitkNavigationToolStorage.cpp index 399d800e5c..85b8e27465 100644 --- a/Modules/IGT/DataManagement/mitkNavigationToolStorage.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationToolStorage.cpp @@ -1,219 +1,239 @@ /*=================================================================== 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 "mitkNavigationToolStorage.h" //Microservices #include #include #include const std::string mitk::NavigationToolStorage::US_INTERFACE_NAME = "org.mitk.services.NavigationToolStorage"; // Name of the interface const std::string mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID = US_INTERFACE_NAME + ".sourceID"; const std::string mitk::NavigationToolStorage::US_PROPKEY_STORAGE_NAME = US_INTERFACE_NAME + ".name"; mitk::NavigationToolStorage::NavigationToolStorage() : m_ToolCollection(std::vector()), m_DataStorage(nullptr), - m_storageLocked(false) - { + m_storageLocked(false) +{ this->SetName("ToolStorage (no name given)"); - } +} -mitk::NavigationToolStorage::NavigationToolStorage(mitk::DataStorage::Pointer ds) : m_storageLocked(false) - { +mitk::NavigationToolStorage::NavigationToolStorage(mitk::DataStorage::Pointer ds) + : m_storageLocked(false) +{ m_ToolCollection = std::vector(); this->m_DataStorage = ds; - } + this->SetName("Tool Storage (no name given)"); +} void mitk::NavigationToolStorage::SetName(std::string n) - { +{ m_Name = n; - m_props[ US_PROPKEY_STORAGE_NAME ] = m_Name; - } + m_props[US_PROPKEY_STORAGE_NAME] = m_Name; +} - void mitk::NavigationToolStorage::UpdateMicroservice() - { - if (m_ServiceRegistration) {m_ServiceRegistration.SetProperties(m_props);} - } +std::string mitk::NavigationToolStorage::GetName() const +{ + return m_Name; +} +void mitk::NavigationToolStorage::UpdateMicroservice() +{ + if (m_ServiceRegistration) { m_ServiceRegistration.SetProperties(m_props); } +} mitk::NavigationToolStorage::~NavigationToolStorage() - { +{ if (m_DataStorage.IsNotNull()) //remove all nodes from the data storage - { - for(std::vector::iterator it = m_ToolCollection.begin(); it != m_ToolCollection.end(); it++) - m_DataStorage->Remove((*it)->GetDataNode()); - } + { + for (std::vector::iterator it = m_ToolCollection.begin(); it != m_ToolCollection.end(); it++) + m_DataStorage->Remove((*it)->GetDataNode()); } +} - -void mitk::NavigationToolStorage::RegisterAsMicroservice(std::string sourceID){ - - if ( sourceID.empty() ) mitkThrow() << "Empty or null string passed to NavigationToolStorage::registerAsMicroservice()."; - +void mitk::NavigationToolStorage::RegisterAsMicroservice(){ // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps - m_props[ US_PROPKEY_SOURCE_ID ] = sourceID; m_ServiceRegistration = context->RegisterService(this, m_props); + //Tell all widgets, that there is a new toolStorage registered, e.g. the old one might have changed. + UpdateMicroservice(); } - void mitk::NavigationToolStorage::UnRegisterMicroservice(){ - if ( ! m_ServiceRegistration ) + if (!m_ServiceRegistration) { MITK_WARN("NavigationToolStorage") - << "Cannot unregister microservice as it wasn't registered before."; + << "Cannot unregister microservice as it wasn't registered before."; return; } m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } - bool mitk::NavigationToolStorage::DeleteTool(int number) +{ + if (m_storageLocked) { - if (m_storageLocked) - { - MITK_WARN << "Storage is locked, cannot modify it!"; - return false; - } - - else if ((unsigned int)number > m_ToolCollection.size()) - { - MITK_WARN << "Tool no " << number << "doesn't exist, can't delete it!"; - return false; - } - std::vector::iterator it = m_ToolCollection.begin() + number; - if(m_DataStorage.IsNotNull()) - m_DataStorage->Remove((*it)->GetDataNode()); - m_ToolCollection.erase(it); + MITK_WARN << "Storage is locked, cannot modify it!"; + return false; + } - return true; + else if ((unsigned int)number > m_ToolCollection.size()) + { + MITK_WARN << "Tool no " << number << "doesn't exist, can't delete it!"; + return false; } + std::vector::iterator it = m_ToolCollection.begin() + number; + if (m_DataStorage.IsNotNull()) + m_DataStorage->Remove((*it)->GetDataNode()); + m_ToolCollection.erase(it); + + //This line is important so that other widgets can get a notice that the toolStorage has changed! + this->UpdateMicroservice(); + return true; +} bool mitk::NavigationToolStorage::DeleteAllTools() +{ + if (m_storageLocked) { - if (m_storageLocked) - { MITK_WARN << "Storage is locked, cannot modify it!"; return false; - } + } - while(m_ToolCollection.size() > 0) if (!DeleteTool(0)) return false; + while (m_ToolCollection.size() > 0) if (!DeleteTool(0)) return false; return true; - } +} bool mitk::NavigationToolStorage::AddTool(mitk::NavigationTool::Pointer tool) - { +{ if (m_storageLocked) - { + { MITK_WARN << "Storage is locked, cannot modify it!"; return false; - } + } else if (GetTool(tool->GetIdentifier()).IsNotNull()) - { + { MITK_WARN << "Tool ID already exists in storage, can't add!"; return false; - } + } else - { + { m_ToolCollection.push_back(tool); - if(m_DataStorage.IsNotNull()) - { + if (m_DataStorage.IsNotNull()) + { if (!m_DataStorage->Exists(tool->GetDataNode())) m_DataStorage->Add(tool->GetDataNode()); - } - return true; } + //This line is important so that other widgets can get a notice that the toolStorage has changed! + this->UpdateMicroservice(); + return true; } +} mitk::NavigationTool::Pointer mitk::NavigationToolStorage::GetTool(int number) - { +{ return m_ToolCollection.at(number); - } +} mitk::NavigationTool::Pointer mitk::NavigationToolStorage::GetTool(std::string identifier) - { - for (int i=0; iGetIdentifier())==identifier) return GetTool(i); +{ + for (unsigned int i = 0; i < GetToolCount(); i++) if ((GetTool(i)->GetIdentifier()) == identifier) return GetTool(i); return nullptr; - } +} mitk::NavigationTool::Pointer mitk::NavigationToolStorage::GetToolByName(std::string name) - { - for (int i=0; iGetToolName())==name) return GetTool(i); +{ + for (unsigned int i = 0; i < GetToolCount(); i++) if ((GetTool(i)->GetToolName()) == name) return GetTool(i); return nullptr; - } +} -int mitk::NavigationToolStorage::GetToolCount() - { +unsigned int mitk::NavigationToolStorage::GetToolCount() +{ return m_ToolCollection.size(); - } +} bool mitk::NavigationToolStorage::isEmpty() - { +{ return m_ToolCollection.empty(); - } +} void mitk::NavigationToolStorage::LockStorage() - { +{ m_storageLocked = true; - } +} void mitk::NavigationToolStorage::UnLockStorage() - { +{ m_storageLocked = false; - } +} bool mitk::NavigationToolStorage::isLocked() - { +{ return m_storageLocked; - } +} bool mitk::NavigationToolStorage::AssignToolNumber(std::string identifier1, int number2) - { +{ if (this->GetTool(identifier1).IsNull()) - { + { MITK_WARN << "Identifier does not exist, cannot assign new number"; return false; - } + } if ((number2 >= static_cast(m_ToolCollection.size())) || (number2 < 0)) - { + { MITK_WARN << "Invalid number, cannot assign new number"; return false; - } + } mitk::NavigationTool::Pointer tool2 = m_ToolCollection.at(number2); int number1 = -1; for(int i = 0; i(m_ToolCollection.size()); i++) - { - if (m_ToolCollection.at(i)->GetIdentifier() == identifier1) {number1=i;} - } + { + if (m_ToolCollection.at(i)->GetIdentifier() == identifier1) { number1 = i; } + } m_ToolCollection[number2] = m_ToolCollection.at(number1); m_ToolCollection[number1] = tool2; MITK_DEBUG << "Swapped tool " << number2 << " with tool " << number1; + //This line is important so that other widgets can get a notice that the toolStorage has changed! + this->UpdateMicroservice(); + return true; } + +void mitk::NavigationToolStorage::SetSourceID(std::string _id) +{ + m_SourceID = _id; + m_props[US_PROPKEY_SOURCE_ID] = m_SourceID; +} + +/** @return Returns the name of this storage. */ +std::string mitk::NavigationToolStorage::GetSourceID() const +{ + return m_SourceID; +} diff --git a/Modules/IGT/DataManagement/mitkNavigationToolStorage.h b/Modules/IGT/DataManagement/mitkNavigationToolStorage.h index 80785a3c98..74fcbef42b 100644 --- a/Modules/IGT/DataManagement/mitkNavigationToolStorage.h +++ b/Modules/IGT/DataManagement/mitkNavigationToolStorage.h @@ -1,186 +1,201 @@ /*=================================================================== 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 NAVIGATIONTOOLSTORAGE_H_INCLUDED #define NAVIGATIONTOOLSTORAGE_H_INCLUDED //itk headers #include //mitk headers #include #include #include "mitkNavigationTool.h" #include // Microservices #include #include #include namespace mitk { /**Documentation * \brief An object of this class represents a collection of navigation tools. * You may add/delete navigation tools or store/load the whole collection * to/from the harddisc by using the class NavigationToolStorageSerializer * and NavigationToolStorageDeserializer. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationToolStorage : public itk::Object { public: mitkClassMacroItkParent(NavigationToolStorage,itk::Object); /** @brief Constructs a NavigationToolStorage without reference to a DataStorage. The Data Nodes of tools have to be added and removed to a data storage outside this class. * Normaly the other constructor should be used. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** @brief Constructs a NavigationToolStorage with reference to a DataStorage. The Data Nodes of tools are added and removed automatically to this data storage. */ mitkNewMacro1Param(Self,mitk::DataStorage::Pointer); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. * To unregister, call UnregisterMicroservice(). Make sure to pass the id of the Device that this tool is connected to. */ - virtual void RegisterAsMicroservice(std::string sourceID); + virtual void RegisterAsMicroservice(); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. */ virtual void UnRegisterMicroservice(); /** *\brief Returns the id that this device is registered with. The id will only be valid, if the * NavigationDataSource has been registered using RegisterAsMicroservice(). */ std::string GetMicroserviceID(); /** *\brief These constants are used in conjunction with Microservices */ - static const std::string US_INTERFACE_NAME; // Name of the interface - static const std::string US_PROPKEY_SOURCE_ID; // ID of the device this ToolStorage is associated with - static const std::string US_PROPKEY_STORAGE_NAME; // name of the storage + // Name of the interface + static const std::string US_INTERFACE_NAME; + // ID of the NavigationDataSource this ToolStorage is associated with. Can be empty ("") and changed with SetSourceID(). + static const std::string US_PROPKEY_SOURCE_ID; + // name of the storage + static const std::string US_PROPKEY_STORAGE_NAME; /** * @brief Adds a tool to the storage. Be sure that the tool has a unique * identifier which is not already part of this storage. * @return Returns true if the tool was added to the storage, false if not * (false can be returned if the identifier already exists in this storage * for example). */ bool AddTool(mitk::NavigationTool::Pointer tool); /** * @return Returns the tracking tool at the position "number" * in the storage. Returns nullptr if there is no * tracking tool at this position. */ mitk::NavigationTool::Pointer GetTool(int number); /** * @return Returns the tracking tool with the given identifier. * Returns nullptr if there is no * tracking tool with this identifier in the storage. */ mitk::NavigationTool::Pointer GetTool(std::string identifier); /** * @return Returns the tracking tool with the given name. * Returns nullptr if there is no * tracking tool with this name in the storage. */ mitk::NavigationTool::Pointer GetToolByName(std::string name); /** Assigns the given number to the tool with the given identifier. This means the tool is swapped with another tool in the internal tool vector. * @return Returns true if the assignment was successfull. Returns false if assignment is not possible, e.g. because the identifier does not exist or if the given number is not available. **/ bool AssignToolNumber(std::string identifier1, int number2); /** * @brief Deletes a tool from the collection. * Warning, this method operates on the data storage and is not thread save. Calling it from outside the main thread may cause crashes. */ bool DeleteTool(int number); /** * @brief Deletes all tools from the collection. * Warning, this method operates on the data storage and is not thread save. Calling it from outside the main thread may cause crashes. */ bool DeleteAllTools(); /** * @return Returns the number of tools stored in the storage. */ - int GetToolCount(); + unsigned int GetToolCount(); /** * @return Returns true if the storage is empty, false if not. */ bool isEmpty(); /** * @return Returns the corresponding data storage if one is set to this NavigationToolStorage. * Returns nullptr if none is set. */ itkGetMacro(DataStorage,mitk::DataStorage::Pointer); /** Sets the name of this storage. The name should be understandable for the user. * Something like "NDI Aurora Tool Storage". If a storage is loaded from the harddisk * the name might be the filename. */ void SetName(std::string); /** @return Returns the name of this storage. */ - itkGetConstMacro(Name,std::string); + std::string GetName() const; + + /** Sets the name of this storage. The name should be understandable for the user. + * Something like "NDI Aurora Tool Storage". If a storage is loaded from the harddisk + * the name might be the filename. + * @warning: if your microservice is already registered, you need to call UpdateMicroservice after changing the ID. + * This can't be done inside this functions, as we might use different threads. + */ + void SetSourceID(std::string); + + /** @return Returns the name of this storage. */ + std::string GetSourceID() const; /** Locks the storage. A logged storage may not be modified. * If a method tries to modify the storage anyway a waring message is given. * The storage is unlocked by default. A Storage might be locked when a * tracking device is active and needs the storage to stay consistent. */ void LockStorage(); /** Unlocks the storage again. */ void UnLockStorage(); /** @return Returns true if the storage is locked at the moment, false if not. */ bool isLocked(); /** Sets the properties which causes the microservice to emit an update signal. */ void UpdateMicroservice(); protected: NavigationToolStorage(); NavigationToolStorage(mitk::DataStorage::Pointer); ~NavigationToolStorage(); std::vector m_ToolCollection; mitk::DataStorage::Pointer m_DataStorage; std::string m_Name; + std::string m_SourceID; bool m_storageLocked; private: us::ServiceRegistration m_ServiceRegistration; us::ServiceProperties m_props; }; } // namespace mitk MITK_DECLARE_SERVICE_INTERFACE(mitk::NavigationToolStorage, "org.mitk.services.NavigationToolStorage") #endif //NAVIGATIONTOOLSTORAGE diff --git a/Modules/IGT/DataManagement/mitkTrackingDeviceSource.cpp b/Modules/IGT/DataManagement/mitkTrackingDeviceSource.cpp index ee1298389b..40d33caa07 100644 --- a/Modules/IGT/DataManagement/mitkTrackingDeviceSource.cpp +++ b/Modules/IGT/DataManagement/mitkTrackingDeviceSource.cpp @@ -1,213 +1,216 @@ /*=================================================================== 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 "mitkTrackingDeviceSource.h" #include "mitkTrackingDevice.h" #include "mitkTrackingTool.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTException.h" +#include "mitkIGTHardwareException.h" mitk::TrackingDeviceSource::TrackingDeviceSource() : mitk::NavigationDataSource(), m_TrackingDevice(nullptr) { } mitk::TrackingDeviceSource::~TrackingDeviceSource() { if (m_TrackingDevice.IsNotNull()) { if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking) { this->StopTracking(); } if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Ready) { this->Disconnect(); } m_TrackingDevice = nullptr; } } void mitk::TrackingDeviceSource::GenerateData() { if (m_IsFrozen) {return;} //no update at all if device is frozen else if (m_TrackingDevice.IsNull()) {return;} if (m_TrackingDevice->GetToolCount() < 1) return; if (this->GetNumberOfIndexedOutputs() != m_TrackingDevice->GetToolCount()) // mismatch between tools and outputs. What should we do? Were tools added to the tracking device after SetTrackingDevice() was called? { //check this: TODO: ////this might happen if a tool is plugged into an aurora during tracking. //this->CreateOutputs(); std::stringstream ss; ss << "mitk::TrackingDeviceSource: not enough outputs available for all tools. " << this->GetNumberOfOutputs() << " outputs available, but " << m_TrackingDevice->GetToolCount() << " tools available in the tracking device."; throw std::out_of_range(ss.str()); } /* update outputs with tracking data from tools */ unsigned int toolCount = m_TrackingDevice->GetToolCount(); for (unsigned int i = 0; i < toolCount; ++i) { mitk::NavigationData* nd = this->GetOutput(i); assert(nd); mitk::TrackingTool* t = m_TrackingDevice->GetTool(i); assert(t); if ((t->IsEnabled() == false) || (t->IsDataValid() == false)) { nd->SetDataValid(false); continue; } nd->SetDataValid(true); mitk::NavigationData::PositionType p; t->GetPosition(p); nd->SetPosition(p); mitk::NavigationData::OrientationType o; t->GetOrientation(o); nd->SetOrientation(o); nd->SetOrientationAccuracy(t->GetTrackingError()); nd->SetPositionAccuracy(t->GetTrackingError()); nd->SetIGTTimeStamp(t->GetIGTTimeStamp()); //for backward compatibility: check if the timestamp was set, if not create a default timestamp if (nd->GetIGTTimeStamp()==0) nd->SetIGTTimeStamp(mitk::IGTTimeStamp::GetInstance()->GetElapsed()); } } void mitk::TrackingDeviceSource::SetTrackingDevice( mitk::TrackingDevice* td ) { MITK_DEBUG << "Setting TrackingDevice to " << td; if (this->m_TrackingDevice.GetPointer() != td) { this->m_TrackingDevice = td; this->CreateOutputs(); std::stringstream name; // create a human readable name for the source name << td->GetData().Model << " Tracking Source"; this->SetName(name.str()); } } void mitk::TrackingDeviceSource::CreateOutputs(){ //if outputs are set then delete them if (this->GetNumberOfOutputs() > 0) { for (int numOP = this->GetNumberOfOutputs() -1; numOP >= 0; numOP--) this->RemoveOutput(numOP); this->Modified(); } //fill the outputs if a valid tracking device is set if (m_TrackingDevice.IsNull()) return; this->SetNumberOfIndexedOutputs(m_TrackingDevice->GetToolCount()); // create outputs for all tools unsigned int numberOfOutputs = this->GetNumberOfIndexedOutputs(); MITK_DEBUG << "Number of tools at start of method CreateOutputs(): " << m_TrackingDevice->GetToolCount(); MITK_DEBUG << "Number of outputs at start of method CreateOutputs(): " << numberOfOutputs; for (unsigned int idx = 0; idx < m_TrackingDevice->GetToolCount(); ++idx) { if (this->GetOutput(idx) == nullptr) { DataObjectPointer newOutput = this->MakeOutput(idx); static_cast(newOutput.GetPointer())->SetName(m_TrackingDevice->GetTool(idx)->GetToolName()); // set NavigationData name to ToolName this->SetNthOutput(idx, newOutput); this->Modified(); } } } void mitk::TrackingDeviceSource::Connect() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (this->IsConnected()) return; - try {m_TrackingDevice->OpenConnection();} + try + { + //Try to open the connection. If it didn't work (fals is returned from OpenConnection by the tracking device), throw an exception. + if (!m_TrackingDevice->OpenConnection()) + { + mitkThrowException(mitk::IGTHardwareException) << "Could not open connection."; + } + } catch (mitk::IGTException &e) { throw std::runtime_error(std::string("mitk::TrackingDeviceSource: Could not open connection to tracking device. Error: ") + e.GetDescription()); } - - /* NDI Aurora needs a connection to discover tools that are connected to it. - Therefore we need to create outputs for these tools now */ - //if (m_TrackingDevice->GetType() == mitk::NDIAurora) - //this->CreateOutputs(); } void mitk::TrackingDeviceSource::StartTracking() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking) return; if (m_TrackingDevice->StartTracking() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not start tracking"); } void mitk::TrackingDeviceSource::Disconnect() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->CloseConnection() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not close connection to tracking device"); } void mitk::TrackingDeviceSource::StopTracking() { if (m_TrackingDevice.IsNull()) throw std::invalid_argument("mitk::TrackingDeviceSource: No tracking device set"); if (m_TrackingDevice->StopTracking() == false) throw std::runtime_error("mitk::TrackingDeviceSource: Could not stop tracking"); } void mitk::TrackingDeviceSource::UpdateOutputInformation() { if(this->GetTrackingDevice()->GetToolCount() != this->GetNumberOfIndexedOutputs()) this->CreateOutputs(); this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } //unsigned int mitk::TrackingDeviceSource::GetToolCount() //{ // if (m_TrackingDevice) // return m_TrackingDevice->GetToolCount(); // return 0; //} bool mitk::TrackingDeviceSource::IsConnected() { if (m_TrackingDevice.IsNull()) return false; return (m_TrackingDevice->GetState() == mitk::TrackingDevice::Ready) || (m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking); } bool mitk::TrackingDeviceSource::IsTracking() { if (m_TrackingDevice.IsNull()) return false; return m_TrackingDevice->GetState() == mitk::TrackingDevice::Tracking; } diff --git a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp index dec53c3505..43d5eb3dd2 100644 --- a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp +++ b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp @@ -1,175 +1,175 @@ /*=================================================================== 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 "mitkTrackingDeviceSourceConfigurator.h" #include "mitkNDITrackingDevice.h" #include "mitkClaronTrackingDevice.h" #include "mitkOptitrackTrackingDevice.h" #include "mitkOpenIGTLinkTrackingDevice.h" #include "mitkVirtualTrackingDevice.h" #include #include #include #include #include #include #include mitk::TrackingDeviceSourceConfigurator::TrackingDeviceSourceConfigurator(mitk::NavigationToolStorage::Pointer NavigationTools, mitk::TrackingDevice::Pointer TrackingDevice) { //make a copy of the navigation tool storage because we will modify the storage if (NavigationTools.IsNotNull()) { m_NavigationTools = mitk::NavigationToolStorage::New(); - for (int i=0; iGetToolCount(); i++) + for (unsigned int i=0; iGetToolCount(); i++) { m_NavigationTools->AddTool(NavigationTools->GetTool(i)); } } m_TrackingDevice = TrackingDevice; m_ToolCorrespondencesInToolStorage = std::vector(); m_ErrorMessage = ""; } mitk::NavigationToolStorage::Pointer mitk::TrackingDeviceSourceConfigurator::GetUpdatedNavigationToolStorage() { return m_NavigationTools; } mitk::TrackingDeviceSourceConfigurator::~TrackingDeviceSourceConfigurator() { } bool mitk::TrackingDeviceSourceConfigurator::IsCreateTrackingDeviceSourcePossible() { if (m_NavigationTools.IsNull()) { m_ErrorMessage = "NavigationToolStorage is nullptr!"; return false; } else if (m_TrackingDevice.IsNull()) { m_ErrorMessage = "TrackingDevice is nullptr!"; return false; } else { - for (int i=0; iGetToolCount(); i++) + for (unsigned int i=0; iGetToolCount(); i++) { if (m_NavigationTools->GetTool(i)->GetTrackingDeviceType() != m_TrackingDevice->GetType()) { m_ErrorMessage = "At least one tool is not of the same type like the tracking device."; return false; } } //TODO in case of Aurora: check if the tools are automatically detected by comparing the serial number return true; } } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateTrackingDeviceSource() { mitk::NavigationDataObjectVisualizationFilter::Pointer dummy; //this dummy is lost directly after creating the device return this->CreateTrackingDeviceSource(dummy); } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateTrackingDeviceSource(mitk::NavigationDataObjectVisualizationFilter::Pointer &visualizationFilter) { if (!this->IsCreateTrackingDeviceSourcePossible()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return nullptr;} mitk::TrackingDeviceSource::Pointer returnValue; us::ModuleContext* context = us::GetModuleContext(); std::vector > refs = context->GetServiceReferences(); if (refs.empty()) { MITK_ERROR << "No tracking device service found!"; } mitk::TrackingDeviceTypeCollection* deviceTypeCollection = context->GetService(refs.front()); //create tracking device source returnValue = deviceTypeCollection->GetTrackingDeviceTypeInformation(m_TrackingDevice->GetType())-> CreateTrackingDeviceSource(m_TrackingDevice,m_NavigationTools, &m_ErrorMessage, &m_ToolCorrespondencesInToolStorage); //TODO: insert other tracking systems? if (returnValue.IsNull()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return nullptr;} //create visualization filter visualizationFilter = CreateNavigationDataObjectVisualizationFilter(returnValue,m_NavigationTools); if (visualizationFilter.IsNull()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return nullptr;} return returnValue; } std::string mitk::TrackingDeviceSourceConfigurator::GetErrorMessage() { return this->m_ErrorMessage; } //############################ internal help methods ######################################## mitk::NavigationDataObjectVisualizationFilter::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNavigationDataObjectVisualizationFilter(mitk::TrackingDeviceSource::Pointer trackingDeviceSource, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::NavigationDataObjectVisualizationFilter::Pointer returnValue = mitk::NavigationDataObjectVisualizationFilter::New(); for (unsigned int i=0; iGetNumberOfIndexedOutputs(); i++) { // Note: If all tools have the same name only the first tool will always be returned and // the others won't be updated during rendering.This could potentially lead to inconstencies mitk::NavigationTool::Pointer currentTool = navigationTools->GetToolByName(trackingDeviceSource->GetOutput(i)->GetName()); if (currentTool.IsNull()) { this->m_ErrorMessage = "Error: did not find corresponding tool in tracking device after initialization."; return nullptr; } returnValue->SetInput(i,trackingDeviceSource->GetOutput(i)); returnValue->SetRepresentationObject(i,currentTool->GetDataNode()->GetData()); } return returnValue; } int mitk::TrackingDeviceSourceConfigurator::GetToolNumberInToolStorage(unsigned int outputID) { if (outputID < m_ToolCorrespondencesInToolStorage.size()) return m_ToolCorrespondencesInToolStorage.at(outputID); else return -1; } std::string mitk::TrackingDeviceSourceConfigurator::GetToolIdentifierInToolStorage(unsigned int outputID) { if (outputID < m_ToolCorrespondencesInToolStorage.size()) return m_NavigationTools->GetTool(m_ToolCorrespondencesInToolStorage.at(outputID))->GetIdentifier(); else return ""; } std::vector mitk::TrackingDeviceSourceConfigurator::GetToolNumbersInToolStorage() { return m_ToolCorrespondencesInToolStorage; } std::vector mitk::TrackingDeviceSourceConfigurator::GetToolIdentifiersInToolStorage() { std::vector returnValue = std::vector(); for (unsigned int i=0; iGetTool(m_ToolCorrespondencesInToolStorage.at(i))->GetIdentifier());} return returnValue; } diff --git a/Modules/IGT/IO/mitkNavigationToolStorageSerializer.cpp b/Modules/IGT/IO/mitkNavigationToolStorageSerializer.cpp index 1d4b2cf7d3..236db1c301 100644 --- a/Modules/IGT/IO/mitkNavigationToolStorageSerializer.cpp +++ b/Modules/IGT/IO/mitkNavigationToolStorageSerializer.cpp @@ -1,99 +1,99 @@ /*=================================================================== 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. ===================================================================*/ //Poco headers #include #include #include #include "mitkNavigationToolStorageSerializer.h" #include "mitkNavigationToolWriter.h" #include "mitkIGTException.h" #include "mitkIGTIOException.h" #include #include #include #include mitk::NavigationToolStorageSerializer::NavigationToolStorageSerializer() { //create temp directory m_tempDirectory = mitk::IOUtil::CreateTemporaryDirectory("NavigationToolStorageSerializerTmp_XXXXXX",mitk::IOUtil::GetProgramPath()); } mitk::NavigationToolStorageSerializer::~NavigationToolStorageSerializer() { //remove temp directory Poco::File myFile(m_tempDirectory); try { if (myFile.exists()) myFile.remove(true); } catch(...) { MITK_ERROR << "Can't remove temp directory " << m_tempDirectory << "!"; } } bool mitk::NavigationToolStorageSerializer::Serialize(std::string filename, mitk::NavigationToolStorage::Pointer storage) { //save every tool to temp directory mitk::NavigationToolWriter::Pointer myToolWriter = mitk::NavigationToolWriter::New(); - for(int i=0; iGetToolCount();i++) + for(unsigned int i=0; iGetToolCount();i++) { std::string tempFileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; if (!myToolWriter->DoWrite(tempFileName,storage->GetTool(i))) { mitkThrowException(mitk::IGTIOException) << "Could not write tool to tempory directory: " << tempFileName; } } //add all files to zip archive std::ofstream file( filename.c_str(), std::ios::binary | std::ios::out); if (!file.good()) //test if the zip archive is ready for writing { //first: clean up - for (int i=0; iGetToolCount();i++) + for (unsigned int i=0; iGetToolCount();i++) { std::string tempFileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; std::remove(tempFileName.c_str()); } //then: throw an exception mitkThrowException(mitk::IGTIOException) << "Could not open a file for writing: " << filename; } Poco::Zip::Compress zipper( file, true ); - for (int i=0; iGetToolCount();i++) + for (unsigned int i=0; iGetToolCount();i++) { std::string fileName = m_tempDirectory + Poco::Path::separator() + "NavigationTool" + convertIntToString(i) + ".tool"; zipper.addFile(fileName,myToolWriter->GetFileWithoutPath(fileName)); std::remove(fileName.c_str()); //delete file } zipper.close(); file.close(); return true; } std::string mitk::NavigationToolStorageSerializer::convertIntToString(int i) { std::string s; std::stringstream out; out << i; s = out.str(); return s; } diff --git a/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.cpp b/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.cpp index d9676fca30..128eabfc47 100644 --- a/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.cpp +++ b/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.cpp @@ -1,270 +1,279 @@ /*=================================================================== 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 "mitkInternalTrackingTool.h" #include typedef itk::MutexLockHolder MutexLockHolder; mitk::InternalTrackingTool::InternalTrackingTool() : TrackingTool(), m_TrackingError(0.0f), m_Enabled(true), m_DataValid(false), m_ToolTipSet(false) { m_Position[0] = 0.0f; m_Position[1] = 0.0f; m_Position[2] = 0.0f; m_Orientation[0] = 0.0f; m_Orientation[1] = 0.0f; m_Orientation[2] = 0.0f; m_Orientation[3] = 0.0f; // this should not be necessary as the tools bring their own tooltip transformation m_ToolTip[0] = 0.0f; m_ToolTip[1] = 0.0f; m_ToolTip[2] = 0.0f; m_ToolTipRotation[0] = 0.0f; m_ToolTipRotation[1] = 0.0f; m_ToolTipRotation[2] = 0.0f; m_ToolTipRotation[3] = 1.0f; } mitk::InternalTrackingTool::~InternalTrackingTool() { } void mitk::InternalTrackingTool::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Position: " << m_Position << std::endl; os << indent << "Orientation: " << m_Orientation << std::endl; os << indent << "TrackingError: " << m_TrackingError << std::endl; os << indent << "Enabled: " << m_Enabled << std::endl; os << indent << "DataValid: " << m_DataValid << std::endl; os << indent << "ToolTip: " << m_ToolTip << std::endl; os << indent << "ToolTipRotation: " << m_ToolTipRotation << std::endl; os << indent << "ToolTipSet: " << m_ToolTipSet << std::endl; } void mitk::InternalTrackingTool::SetToolName(const char* _arg) { itkDebugMacro("setting m_ToolName to " << _arg); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if ( _arg && (_arg == this->m_ToolName) ) { return; } if (_arg) { this->m_ToolName= _arg; } else { this->m_ToolName= ""; } this->Modified(); } void mitk::InternalTrackingTool::SetToolName( const std::string _arg ) { this->SetToolName(_arg.c_str()); } void mitk::InternalTrackingTool::GetPosition(mitk::Point3D& position) const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (m_ToolTipSet) { // Compute the position of tool tip in the coordinate frame of the // tracking device: Rotate the position of the tip into the tracking // device coordinate frame then add to the position of the tracking // sensor vnl_vector pos_vnl = m_Position.GetVnlVector() + m_Orientation.rotate( m_ToolTip.GetVnlVector() ) ; position[0] = pos_vnl[0]; position[1] = pos_vnl[1]; position[2] = pos_vnl[2]; } else { position[0] = m_Position[0]; position[1] = m_Position[1]; position[2] = m_Position[2]; } this->Modified(); } void mitk::InternalTrackingTool::SetPosition(mitk::Point3D position) { itkDebugMacro("setting m_Position to " << position); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex m_Position = position; this->Modified(); } void mitk::InternalTrackingTool::GetOrientation(mitk::Quaternion& orientation) const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (m_ToolTipSet) { // Compute the orientation of the tool tip in the coordinate frame of // the tracking device. // // * m_Orientation is the orientation of the sensor relative to the transmitter // * m_ToolTipRotation is the orientation of the tool tip relative to the sensor orientation = m_Orientation * m_ToolTipRotation; } else { orientation = m_Orientation; } } void mitk::InternalTrackingTool::SetToolTip(mitk::Point3D toolTipPosition, mitk::Quaternion orientation, mitk::ScalarType eps) { if ( !Equal(m_ToolTip, toolTipPosition, eps) || !Equal(m_ToolTipRotation, orientation, eps) ) { if( (toolTipPosition[0] == 0) && (toolTipPosition[1] == 0) && (toolTipPosition[2] == 0) && (orientation.x() == 0) && (orientation.y() == 0) && (orientation.z() == 0) && (orientation.r() == 1)) { m_ToolTipSet = false; } else { m_ToolTipSet = true; } m_ToolTip = toolTipPosition; m_ToolTipRotation = orientation; this->Modified(); } } +mitk::Point3D mitk::InternalTrackingTool::GetToolTip() const +{ + return m_ToolTip; +} +mitk::Quaternion mitk::InternalTrackingTool::GetToolTipOrientation() const +{ + return m_ToolTipRotation; +} + void mitk::InternalTrackingTool::SetOrientation(mitk::Quaternion orientation) { itkDebugMacro("setting m_Orientation to " << orientation); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex m_Orientation = orientation; this->Modified(); } void mitk::InternalTrackingTool::SetTrackingError(float error) { itkDebugMacro("setting m_TrackingError to " << error); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (error == m_TrackingError) { return; } m_TrackingError = error; this->Modified(); } float mitk::InternalTrackingTool::GetTrackingError() const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex float r = m_TrackingError; return r; } bool mitk::InternalTrackingTool::Enable() { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (m_Enabled == false) { this->m_Enabled = true; this->Modified(); } return true; } bool mitk::InternalTrackingTool::Disable() { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if (m_Enabled == true) { this->m_Enabled = false; this->Modified(); } return true; } bool mitk::InternalTrackingTool::IsEnabled() const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex return m_Enabled; } bool mitk::InternalTrackingTool::IsTooltipSet() const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex return m_ToolTipSet; } bool mitk::InternalTrackingTool::IsDataValid() const { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex return m_DataValid; } void mitk::InternalTrackingTool::SetDataValid(bool _arg) { itkDebugMacro("setting m_DataValid to " << _arg); if (this->m_DataValid != _arg) { MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex this->m_DataValid = _arg; this->Modified(); } } void mitk::InternalTrackingTool::SetErrorMessage(const char* _arg) { itkDebugMacro("setting m_ErrorMessage to " << _arg); MutexLockHolder lock(*m_MyMutex); // lock and unlock the mutex if ((_arg == nullptr) || (_arg == this->m_ErrorMessage)) return; if (_arg != nullptr) this->m_ErrorMessage = _arg; else this->m_ErrorMessage = ""; this->Modified(); } diff --git a/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.h b/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.h index de952cf0b8..d0a34cc476 100644 --- a/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.h +++ b/Modules/IGT/TrackingDevices/mitkInternalTrackingTool.h @@ -1,80 +1,82 @@ /*=================================================================== 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 MITKINTERNALTRACKINGTOOL_H_HEADER_INCLUDED_ #define MITKINTERNALTRACKINGTOOL_H_HEADER_INCLUDED_ #include #include #include #include namespace mitk { /**Documentation * \brief implements TrackingTool interface * * This class is a complete TrackingTool implementation. It can either be used directly by * TrackingDevices, or be subclassed for more specific implementations. * mitk::MicroBirdTrackingDevice uses this class to manage its tools. Other tracking devices * uses specialized versions of this class (e.g. mitk::NDITrackingTool) * * \ingroup IGT */ class MITKIGT_EXPORT InternalTrackingTool : public TrackingTool { friend class MicroBirdTrackingDevice; // Add all TrackingDevice subclasses that use InternalTrackingDevice directly public: mitkClassMacro(InternalTrackingTool, TrackingTool); virtual void PrintSelf(std::ostream& os, itk::Indent indent) const override; virtual void GetPosition(Point3D& position) const override; ///< returns the current position of the tool as an array of three floats (in the tracking device coordinate system) virtual void GetOrientation(Quaternion& orientation) const override; ///< returns the current orientation of the tool as a quaternion (in the tracking device coordinate system) virtual bool Enable() override; ///< enablea the tool, so that it will be tracked. Returns true if enabling was successfull virtual bool Disable() override; ///< disables the tool, so that it will not be tracked anymore. Returns true if disabling was successfull virtual bool IsEnabled() const override; ///< returns whether the tool is enabled or disabled virtual bool IsDataValid() const override; ///< returns true if the current position data is valid (no error during tracking, tracking error below threshold, ...) virtual float GetTrackingError() const override; ///< return one value that corresponds to the overall tracking error. The dimension of this value is specific to each tracking device virtual bool IsTooltipSet() const; ///< returns true if a tooltip is set, false if not virtual void SetToolName(const std::string _arg); ///< Sets the name of the tool virtual void SetToolName(const char* _arg); ///< Sets the name of the tool virtual void SetPosition(Point3D position); ///< sets the position virtual void SetOrientation(Quaternion orientation); ///< sets the orientation as a quaternion virtual void SetTrackingError(float error); ///< sets the tracking error virtual void SetDataValid(bool _arg); ///< sets if the tracking data (position & Orientation) is valid virtual void SetErrorMessage(const char* _arg); ///< sets the error message virtual void SetToolTip(Point3D toolTipPosition, Quaternion orientation = Quaternion(0,0,0,1), ScalarType eps=0.0) override; ///< defines a tool tip for this tool in tool coordinates. GetPosition() and GetOrientation() return the data of the tool tip if it is defined. By default no tooltip is defined. + Point3D GetToolTip() const; //Returns the tool tip in tool coordinates, which where set by SetToolTip + Quaternion GetToolTipOrientation() const;//Returns the tool tip orientation in tool coordinates, which where set by SetToolTip protected: itkFactorylessNewMacro(Self) itkCloneMacro(Self) InternalTrackingTool(); virtual ~InternalTrackingTool(); Point3D m_Position; ///< holds the position of the tool Quaternion m_Orientation; ///< holds the orientation of the tool float m_TrackingError; ///< holds the tracking error of the tool bool m_Enabled; ///< if true, tool is enabled and should receive tracking updates from the tracking device bool m_DataValid; ///< if true, data in m_Position and m_Orientation is valid, e.g. true tracking data Point3D m_ToolTip; Quaternion m_ToolTipRotation; bool m_ToolTipSet; }; } // namespace mitk #endif /* MITKINTERNALTRACKINGTOOL_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/TrackingDevices/mitkMicronTrackerTypeInformation.cpp b/Modules/IGT/TrackingDevices/mitkMicronTrackerTypeInformation.cpp index eb75123bf4..3edfdf7dcd 100644 --- a/Modules/IGT/TrackingDevices/mitkMicronTrackerTypeInformation.cpp +++ b/Modules/IGT/TrackingDevices/mitkMicronTrackerTypeInformation.cpp @@ -1,70 +1,70 @@ /*=================================================================== 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 "mitkMicronTrackerTypeInformation.h" #include "mitkClaronTrackingDevice.h" namespace mitk { std::string MicronTrackerTypeInformation::GetTrackingDeviceName() { return "Claron Micron"; } TrackingDeviceData MicronTrackerTypeInformation::GetDeviceDataMicronTrackerH40() { TrackingDeviceData data = { MicronTrackerTypeInformation::GetTrackingDeviceName(), "Micron Tracker H40", "ClaronMicron.stl", "X" }; return data; } MicronTrackerTypeInformation::MicronTrackerTypeInformation() { m_DeviceName = MicronTrackerTypeInformation::GetTrackingDeviceName(); m_TrackingDeviceData.push_back(GetDeviceDataMicronTrackerH40()); } MicronTrackerTypeInformation::~MicronTrackerTypeInformation() { } mitk::TrackingDeviceSource::Pointer MicronTrackerTypeInformation::CreateTrackingDeviceSource( mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools, std::string* errorMessage, std::vector* toolCorrespondencesInToolStorage) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::ClaronTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); *toolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device - for (int i = 0; i < navigationTools->GetToolCount(); i++) + for (unsigned int i = 0; i < navigationTools->GetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = navigationTools->GetTool(i); toolCorrespondencesInToolStorage->push_back(i); bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str(), thisNavigationTool->GetCalibrationFile().c_str()); if (!toolAddSuccess) { //todo error handling errorMessage->append("Can't add tool, is the toolfile valid?"); return nullptr; } thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(), thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } } diff --git a/Modules/IGT/TrackingDevices/mitkNDIAuroraTypeInformation.cpp b/Modules/IGT/TrackingDevices/mitkNDIAuroraTypeInformation.cpp index 16ce24fc58..77b0e70b23 100644 --- a/Modules/IGT/TrackingDevices/mitkNDIAuroraTypeInformation.cpp +++ b/Modules/IGT/TrackingDevices/mitkNDIAuroraTypeInformation.cpp @@ -1,149 +1,153 @@ /*=================================================================== 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 "mitkNDIAuroraTypeInformation.h" #include "mitkIGTHardwareException.h" #include "mitkNDITrackingDevice.h" namespace mitk { std::string NDIAuroraTypeInformation::GetTrackingDeviceName() { return "NDI Aurora"; } TrackingDeviceData NDIAuroraTypeInformation::GetDeviceDataAuroraCompact() { TrackingDeviceData data = { NDIAuroraTypeInformation::GetTrackingDeviceName(), "Aurora Compact", "NDIAuroraCompactFG_Dome.stl", "A" }; return data; } TrackingDeviceData NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube() { TrackingDeviceData data = { NDIAuroraTypeInformation::GetTrackingDeviceName(), "Aurora Planar (Cube)", "NDIAurora.stl", "9" }; return data; } TrackingDeviceData NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome() { TrackingDeviceData data = { NDIAuroraTypeInformation::GetTrackingDeviceName(), "Aurora Planar (Dome)", "NDIAuroraPlanarFG_Dome.stl", "A" }; return data; } TrackingDeviceData NDIAuroraTypeInformation::GetDeviceDataAuroraTabletop() { TrackingDeviceData data = { NDIAuroraTypeInformation::GetTrackingDeviceName(), "Aurora Tabletop", "NDIAuroraTabletopFG_Dome.stl", "A" }; return data; } NDIAuroraTypeInformation::NDIAuroraTypeInformation() { m_DeviceName = NDIAuroraTypeInformation::GetTrackingDeviceName(); m_TrackingDeviceData.push_back(GetDeviceDataAuroraCompact()); m_TrackingDeviceData.push_back(GetDeviceDataAuroraPlanarCube()); m_TrackingDeviceData.push_back(GetDeviceDataAuroraPlanarDome()); m_TrackingDeviceData.push_back(GetDeviceDataAuroraTabletop()); } NDIAuroraTypeInformation::~NDIAuroraTypeInformation() { } mitk::TrackingDeviceSource::Pointer NDIAuroraTypeInformation::CreateTrackingDeviceSource( mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools, std::string* errorMessage, std::vector* toolCorrespondencesInToolStorage) { MITK_DEBUG << "Creating Aurora tracking device."; mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::NDITrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); try { //connect to aurora to dectect tools automatically thisDevice->OpenConnection(); } catch (mitk::IGTHardwareException& e) { errorMessage->append("Hardware error on opening the connection ("); errorMessage->append(e.GetDescription()); errorMessage->append(")"); return nullptr; } catch (mitk::IGTException& e) { errorMessage->append("Error on opening the connection ("); errorMessage->append(e.GetDescription()); errorMessage->append(")"); return nullptr; } //now search for automatically detected tools in the tool storage and save them mitk::NavigationToolStorage::Pointer newToolStorageInRightOrder = mitk::NavigationToolStorage::New(); - std::vector alreadyFoundTools = std::vector(); + std::vector alreadyFoundTools = std::vector(); *toolCorrespondencesInToolStorage = std::vector(); for (unsigned int i = 0; i < thisDevice->GetToolCount(); i++) { bool toolFound = false; - for (int j = 0; j < navigationTools->GetToolCount(); j++) + for (unsigned int j = 0; j < navigationTools->GetToolCount(); j++) { //check if the serial number is the same to identify the tool if ((dynamic_cast(thisDevice->GetTool(i)))->GetSerialNumber() == navigationTools->GetTool(j)->GetSerialNumber()) { //check if this tool was already added to make sure that every tool is only added once (in case of same serial numbers) bool toolAlreadyAdded = false; - for (unsigned int k = 0; k < alreadyFoundTools.size(); k++) if (alreadyFoundTools.at(k) == j) toolAlreadyAdded = true; + for (unsigned int k = 0; k < alreadyFoundTools.size(); k++) + { + if (alreadyFoundTools.at(k) == j) + { + toolAlreadyAdded = true; + } + } if (!toolAlreadyAdded) { //add tool in right order newToolStorageInRightOrder->AddTool(navigationTools->GetTool(j)); toolCorrespondencesInToolStorage->push_back(j); //adapt name of tool dynamic_cast(thisDevice->GetTool(i))->SetToolName(navigationTools->GetTool(j)->GetToolName()); //set tip of tool dynamic_cast(thisDevice->GetTool(i))->SetToolTip(navigationTools->GetTool(j)->GetToolTipPosition(), navigationTools->GetTool(j)->GetToolTipOrientation()); //rember that this tool was already found alreadyFoundTools.push_back(j); toolFound = true; break; } } } if (!toolFound) { errorMessage->append("Error: did not find every automatically detected tool in the loaded tool storage: aborting initialization."); return nullptr; } } - //delete all tools from the tool storage - navigationTools->DeleteAllTools(); - - //and add only the detected tools in the right order - for (int i = 0; i < newToolStorageInRightOrder->GetToolCount(); i++) + //And resort them (this was done in TrackingToolBoxWorker before). + for (unsigned int i = 0; i < newToolStorageInRightOrder->GetToolCount(); i++) { - navigationTools->AddTool(newToolStorageInRightOrder->GetTool(i)); + navigationTools->AssignToolNumber(newToolStorageInRightOrder->GetTool(i)->GetIdentifier(), i); } + returnValue->SetTrackingDevice(thisDevice); MITK_DEBUG << "Number of tools of created tracking device: " << thisDevice->GetToolCount(); MITK_DEBUG << "Number of outputs of created source: " << returnValue->GetNumberOfOutputs(); return returnValue; } } diff --git a/Modules/IGT/TrackingDevices/mitkNDIPolarisTypeInformation.cpp b/Modules/IGT/TrackingDevices/mitkNDIPolarisTypeInformation.cpp index 2fd22e6bd0..025f26d535 100644 --- a/Modules/IGT/TrackingDevices/mitkNDIPolarisTypeInformation.cpp +++ b/Modules/IGT/TrackingDevices/mitkNDIPolarisTypeInformation.cpp @@ -1,90 +1,90 @@ /*=================================================================== 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 "mitkNDIPolarisTypeInformation.h" #include "mitkNDITrackingDevice.h" namespace mitk { std::string NDIPolarisTypeInformation::GetTrackingDeviceName() { return "NDI Polaris"; ///< Polaris: optical Tracker from NDI; } TrackingDeviceData NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel() { TrackingDeviceData data = { NDIPolarisTypeInformation::GetTrackingDeviceName(), "Polaris (Old Model)", "NDIPolarisOldModel.stl", "0" }; return data; } TrackingDeviceData NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra() { //full hardware code of polaris spectra: 5-240000-153200-095000+057200+039800+056946+024303+029773+999999+99999924 TrackingDeviceData data = { NDIPolarisTypeInformation::GetTrackingDeviceName(), "Polaris Spectra", "NDIPolarisSpectra.stl", "5-2" }; return data; } TrackingDeviceData NDIPolarisTypeInformation::GetDeviceDataSpectraExtendedPyramid() { //full hardware code of polaris spectra (extended pyramid): 5-300000-153200-095000+057200+039800+056946+024303+029773+999999+07350024 TrackingDeviceData data = { NDIPolarisTypeInformation::GetTrackingDeviceName(), "Polaris Spectra (Extended Pyramid)", "NDIPolarisSpectraExtendedPyramid.stl", "5-3" }; return data; } TrackingDeviceData NDIPolarisTypeInformation::GetDeviceDataPolarisVicra() { TrackingDeviceData data = { NDIPolarisTypeInformation::GetTrackingDeviceName(), "Polaris Vicra", "NDIPolarisVicra.stl", "7" }; return data; } NDIPolarisTypeInformation::NDIPolarisTypeInformation() { m_DeviceName = NDIPolarisTypeInformation::GetTrackingDeviceName(); m_TrackingDeviceData.push_back(GetDeviceDataPolarisOldModel()); m_TrackingDeviceData.push_back(GetDeviceDataSpectraExtendedPyramid()); m_TrackingDeviceData.push_back(GetDeviceDataPolarisSpectra()); m_TrackingDeviceData.push_back(GetDeviceDataPolarisVicra()); } NDIPolarisTypeInformation::~NDIPolarisTypeInformation() { } mitk::TrackingDeviceSource::Pointer NDIPolarisTypeInformation::CreateTrackingDeviceSource( mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools, std::string* errorMessage, std::vector* toolCorrespondencesInToolStorage) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::NDITrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); *toolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device - for (int i = 0; i < navigationTools->GetToolCount(); i++) + for (unsigned int i = 0; i < navigationTools->GetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = navigationTools->GetTool(i); toolCorrespondencesInToolStorage->push_back(i); bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str(), thisNavigationTool->GetCalibrationFile().c_str()); if (!toolAddSuccess) { //todo: error handling errorMessage->append("Can't add tool, is the SROM-file valid?"); return nullptr; } thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(), thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } } diff --git a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp index 04a190ddaa..9f3e895a38 100644 --- a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.cpp @@ -1,1335 +1,1314 @@ /*=================================================================== 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 "mitkNDITrackingDevice.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTHardwareException.h" #include #include #include #include #include #include // vtk #include typedef itk::MutexLockHolder MutexLockHolder; - const unsigned char CR = 0xD; // == '\r' - carriage return const unsigned char LF = 0xA; // == '\n' - line feed - mitk::NDITrackingDevice::NDITrackingDevice() : -TrackingDevice(),m_DeviceName(""), m_PortNumber(mitk::SerialCommunication::COM5), m_BaudRate(mitk::SerialCommunication::BaudRate9600), +TrackingDevice(), m_DeviceName(""), m_PortNumber(mitk::SerialCommunication::COM5), m_BaudRate(mitk::SerialCommunication::BaudRate9600), m_DataBits(mitk::SerialCommunication::DataBits8), m_Parity(mitk::SerialCommunication::None), m_StopBits(mitk::SerialCommunication::StopBits1), m_HardwareHandshake(mitk::SerialCommunication::HardwareHandshakeOff), m_IlluminationActivationRate(Hz20), m_DataTransferMode(TX), m_6DTools(), m_ToolsMutex(nullptr), m_SerialCommunication(nullptr), m_SerialCommunicationMutex(nullptr), m_DeviceProtocol(nullptr), m_MultiThreader(nullptr), m_ThreadID(0), m_OperationMode(ToolTracking6D), m_MarkerPointsMutex(nullptr), m_MarkerPoints() { m_Data = mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified(); m_6DTools.clear(); m_SerialCommunicationMutex = itk::FastMutexLock::New(); m_DeviceProtocol = NDIProtocol::New(); m_DeviceProtocol->SetTrackingDevice(this); m_DeviceProtocol->UseCRCOn(); m_MultiThreader = itk::MultiThreader::New(); m_ToolsMutex = itk::FastMutexLock::New(); m_MarkerPointsMutex = itk::FastMutexLock::New(); m_MarkerPoints.reserve(50); // a maximum of 50 marker positions can be reported by the tracking device } - bool mitk::NDITrackingDevice::UpdateTool(mitk::TrackingTool* tool) { if (this->GetState() != Setup) { mitk::NDIPassiveTool* ndiTool = dynamic_cast(tool); if (ndiTool == nullptr) return false; std::string portHandle = ndiTool->GetPortHandle(); //return false if the SROM Data has not been set if (ndiTool->GetSROMData() == nullptr) return false; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PVWR(&portHandle, ndiTool->GetSROMData(), ndiTool->GetSROMDataLength()); if (returnvalue != NDIOKAY) return false; returnvalue = m_DeviceProtocol->PINIT(&portHandle); if (returnvalue != NDIOKAY) return false; returnvalue = m_DeviceProtocol->PENA(&portHandle, ndiTool->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) return false; return true; } else { return false; } } void mitk::NDITrackingDevice::SetRotationMode(RotationMode r) { m_RotationMode = r; } mitk::NDITrackingDevice::~NDITrackingDevice() { /* stop tracking and disconnect from tracking device */ if (GetState() == Tracking) { this->StopTracking(); } if (GetState() == Ready) { this->CloseConnection(); } /* cleanup tracking thread */ if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull())) { m_MultiThreader->TerminateThread(m_ThreadID); } m_MultiThreader = nullptr; /* free serial communication interface */ if (m_SerialCommunication.IsNotNull()) { m_SerialCommunication->ClearReceiveBuffer(); m_SerialCommunication->ClearSendBuffer(); m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; } } - void mitk::NDITrackingDevice::SetPortNumber(const PortNumber _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting PortNumber to " << _arg); if (this->m_PortNumber != _arg) { this->m_PortNumber = _arg; this->Modified(); } } - void mitk::NDITrackingDevice::SetDeviceName(std::string _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting eviceName to " << _arg); if (this->m_DeviceName != _arg) { this->m_DeviceName = _arg; this->Modified(); } } - void mitk::NDITrackingDevice::SetBaudRate(const BaudRate _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting BaudRate to " << _arg); if (this->m_BaudRate != _arg) { this->m_BaudRate = _arg; this->Modified(); } } - void mitk::NDITrackingDevice::SetDataBits(const DataBits _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting DataBits to " << _arg); if (this->m_DataBits != _arg) { this->m_DataBits = _arg; this->Modified(); } } - void mitk::NDITrackingDevice::SetParity(const Parity _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting Parity to " << _arg); if (this->m_Parity != _arg) { this->m_Parity = _arg; this->Modified(); } } - void mitk::NDITrackingDevice::SetStopBits(const StopBits _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting StopBits to " << _arg); if (this->m_StopBits != _arg) { this->m_StopBits = _arg; this->Modified(); } } - void mitk::NDITrackingDevice::SetHardwareHandshake(const HardwareHandshake _arg) { if (this->GetState() != Setup) return; itkDebugMacro("setting HardwareHandshake to " << _arg); if (this->m_HardwareHandshake != _arg) { this->m_HardwareHandshake = _arg; this->Modified(); } } - void mitk::NDITrackingDevice::SetIlluminationActivationRate(const IlluminationActivationRate _arg) { if (this->GetState() == Tracking) return; itkDebugMacro("setting IlluminationActivationRate to " << _arg); if (this->m_IlluminationActivationRate != _arg) { this->m_IlluminationActivationRate = _arg; this->Modified(); if (this->GetState() == Ready) // if the connection to the tracking system is established, send the new rate to the tracking device too m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate); } } - void mitk::NDITrackingDevice::SetDataTransferMode(const DataTransferMode _arg) { itkDebugMacro("setting DataTransferMode to " << _arg); if (this->m_DataTransferMode != _arg) { this->m_DataTransferMode = _arg; this->Modified(); } } - mitk::NDIErrorCode mitk::NDITrackingDevice::Send(const std::string* input, bool addCRC) { if (input == nullptr) return SERIALSENDERROR; std::string message; if (addCRC == true) message = *input + CalcCRC(input) + std::string(1, CR); else message = *input + std::string(1, CR); //unsigned int messageLength = message.length() + 1; // +1 for CR // Clear send buffer this->ClearSendBuffer(); // Send the date to the device MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Send(message); if (returnvalue == 0) return SERIALSENDERROR; else return NDIOKAY; } - mitk::NDIErrorCode mitk::NDITrackingDevice::Receive(std::string* answer, unsigned int numberOfBytes) { if (answer == nullptr) return SERIALRECEIVEERROR; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Receive(*answer, numberOfBytes); // never read more bytes than the device has send, the function will block until enough bytes are send... if (returnvalue == 0) return SERIALRECEIVEERROR; else return NDIOKAY; } - mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveByte(char* answer) { if (answer == nullptr) return SERIALRECEIVEERROR; std::string m; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex long returnvalue = m_SerialCommunication->Receive(m, 1); - if ((returnvalue == 0) ||(m.size() != 1)) + if ((returnvalue == 0) || (m.size() != 1)) return SERIALRECEIVEERROR; *answer = m.at(0); return NDIOKAY; } - mitk::NDIErrorCode mitk::NDITrackingDevice::ReceiveLine(std::string* answer) { if (answer == nullptr) return SERIALRECEIVEERROR; std::string m; MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex do { long returnvalue = m_SerialCommunication->Receive(m, 1); - if ((returnvalue == 0) ||(m.size() != 1)) + if ((returnvalue == 0) || (m.size() != 1)) return SERIALRECEIVEERROR; *answer += m; } while (m.at(0) != LF); return NDIOKAY; } - void mitk::NDITrackingDevice::ClearSendBuffer() { MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex m_SerialCommunication->ClearSendBuffer(); } - void mitk::NDITrackingDevice::ClearReceiveBuffer() { MutexLockHolder lock(*m_SerialCommunicationMutex); // lock and unlock the mutex m_SerialCommunication->ClearReceiveBuffer(); } - const std::string mitk::NDITrackingDevice::CalcCRC(const std::string* input) { - if (input == nullptr) return ""; /* the crc16 calculation code is taken from the NDI API guide example code section */ - static int oddparity[16] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0}; + static int oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; unsigned int data; // copy of the input string's current character unsigned int crcValue = 0; // the crc value is stored here unsigned int* puCRC16 = &crcValue; // the algorithm uses a pointer to crcValue, so it's easier to provide that than to change the algorithm for (unsigned int i = 0; i < input->length(); i++) { data = (*input)[i]; - data = (data ^ (*(puCRC16) & 0xff)) & 0xff; + data = (data ^ (*(puCRC16)& 0xff)) & 0xff; *puCRC16 >>= 8; if (oddparity[data & 0x0f] ^ oddparity[data >> 4]) { *(puCRC16) ^= 0xc001; } data <<= 6; *puCRC16 ^= data; data <<= 1; *puCRC16 ^= data; } // crcValue contains now the CRC16 value. Convert it to a string and return it char returnvalue[13]; - sprintf(returnvalue,"%04X", crcValue); // 4 hexadecimal digit with uppercase format + sprintf(returnvalue, "%04X", crcValue); // 4 hexadecimal digit with uppercase format return std::string(returnvalue); } bool mitk::NDITrackingDevice::OpenConnection() { - //this->m_ModeMutex->Lock(); if (this->GetState() != Setup) - {mitkThrowException(mitk::IGTException) << "Can only try to open the connection if in setup mode";} + { + mitkThrowException(mitk::IGTException) << "Can only try to open the connection if in setup mode"; + } m_SerialCommunication = mitk::SerialCommunication::New(); /* init local com port to standard com settings for a NDI tracking device: 9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake */ if (m_DeviceName.empty()) m_SerialCommunication->SetPortNumber(m_PortNumber); else m_SerialCommunication->SetDeviceName(m_DeviceName); m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600); m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8); m_SerialCommunication->SetParity(mitk::SerialCommunication::None); m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); if (m_SerialCommunication->OpenConnection() == 0) // 0 == ERROR_VALUE { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; mitkThrowException(mitk::IGTHardwareException) << "Can not open serial port"; } /* Reset Tracking device by sending a serial break for 500ms */ m_SerialCommunication->SendBreak(400); /* Read answer from tracking device (RESETBE6F) */ static const std::string reset("RESETBE6F\r"); std::string answer = ""; this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F) this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset if (reset.compare(answer) != 0) // check for RESETBE6F { if (m_SerialCommunication.IsNotNull()) { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; } mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work"; } /* Now the tracking device isSetData reset, start initialization */ NDIErrorCode returnvalue; /* set device com settings to new values and wait for the device to change them */ returnvalue = m_DeviceProtocol->COMM(m_BaudRate, m_DataBits, m_Parity, m_StopBits, m_HardwareHandshake); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << "Could not set comm settings in trackingdevice";} + { + mitkThrowException(mitk::IGTHardwareException) << "Could not set comm settings in trackingdevice"; + } //after changing COMM wait at least 100ms according to NDI Api documentation page 31 itksys::SystemTools::Delay(500); /* now change local com settings accordingly */ m_SerialCommunication->CloseConnection(); m_SerialCommunication->SetBaudRate(m_BaudRate); m_SerialCommunication->SetDataBits(m_DataBits); m_SerialCommunication->SetParity(m_Parity); m_SerialCommunication->SetStopBits(m_StopBits); m_SerialCommunication->SetHardwareHandshake(m_HardwareHandshake); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); m_SerialCommunication->OpenConnection(); - /* initialize the tracking device */ returnvalue = m_DeviceProtocol->INIT(); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << "Could not initialize the tracking device";} + { + mitkThrowException(mitk::IGTHardwareException) << "Could not initialize the tracking device"; + } if (this->GetType() == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName()) // if the type of tracking device is not specified, try to query the connected device { mitk::TrackingDeviceType deviceType; returnvalue = m_DeviceProtocol->VER(deviceType); if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName())) - {mitkThrowException(mitk::IGTHardwareException) << "Could not determine tracking device type. Please set manually and try again.";} + { + mitkThrowException(mitk::IGTHardwareException) << "Could not determine tracking device type. Please set manually and try again."; + } this->SetType(deviceType); } /**** Optional Polaris specific code, Work in progress // start diagnostic mode returnvalue = m_DeviceProtocol->DSTART(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not start diagnostic mode"); return false; } else // we are in diagnostic mode { // initialize extensive IR checking returnvalue = m_DeviceProtocol->IRINIT(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not initialize intense infrared light checking"); return false; } bool intenseIR = false; returnvalue = m_DeviceProtocol->IRCHK(&intenseIR); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not execute intense infrared light checking"); return false; } if (intenseIR == true) // do something - warn the user, raise exception, write to protocol or similar std::cout << "Warning: Intense infrared light detected. Accurate tracking will probably not be possible.\n"; // stop diagnictic mode returnvalue = m_DeviceProtocol->DSTOP(); if (returnvalue != NDIOKAY) { this->SetErrorMessage("Could not stop diagnostic mode"); return false; } } *** end of optional polaris code ***/ /** * now add tools to the tracking system **/ /* First, check if the tracking device has port handles that need to be freed and free them */ returnvalue = FreePortHandles(); // non-critical, therefore no error handling /** * POLARIS: initialize the tools that were added manually **/ { - MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex std::string portHandle; auto endIt = m_6DTools.end(); - for(auto it = m_6DTools.begin(); it != endIt; ++it) + for (auto it = m_6DTools.begin(); it != endIt; ++it) { /* get a port handle for the tool */ returnvalue = m_DeviceProtocol->PHRQ(&portHandle); if (returnvalue == NDIOKAY) { (*it)->SetPortHandle(portHandle.c_str()); /* now write the SROM file of the tool to the tracking system using PVWR */ - if (this->m_Data.Line == mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()) + if (this->m_Data.Line == mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()) { returnvalue = m_DeviceProtocol->PVWR(&portHandle, (*it)->GetSROMData(), (*it)->GetSROMDataLength()); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + (*it)->GetToolName() + std::string("' to tracking device")).c_str();} + { + mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + (*it)->GetToolName() + std::string("' to tracking device")).c_str(); + } returnvalue = m_DeviceProtocol->PINIT(&portHandle); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + (*it)->GetToolName()).c_str();} + { + mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + (*it)->GetToolName()).c_str(); + } if ((*it)->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&portHandle, (*it)->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + portHandle + - std::string("' for tool '")+ (*it)->GetToolName() + std::string("'")).c_str(); + std::string("' for tool '") + (*it)->GetToolName() + std::string("'")).c_str(); } } } } } } // end of toolsmutexlockholder scope /* check for wired tools and add them too */ if (this->DiscoverWiredTools() == false) // query the tracking device for wired tools and add them to our tool list return false; // \TODO: could we continue anyways? - /*POLARIS: set the illuminator activation rate */ if (this->m_Data.Line == mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()) { returnvalue = m_DeviceProtocol->IRATE(this->m_IlluminationActivationRate); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << "Could not set the illuminator activation rate";} + { + mitkThrowException(mitk::IGTHardwareException) << "Could not set the illuminator activation rate"; + } } /* finish - now all tools should be added, initialized and enabled, so that tracking can be started */ this->SetState(Ready); try { SetVolume(this->m_Data); } catch (mitk::IGTHardwareException e) { - MITK_WARN<PHSR(OCCUPIED, &portHandle); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected";} + { + mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected"; + } /* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */ std::string ph; for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); mitk::NDIPassiveTool* pt = this->GetInternalTool(ph); - if ( pt == nullptr) // if we don't have a tool, something is wrong. Tools should be discovered first by calling DiscoverWiredTools() + if (pt == nullptr) // if we don't have a tool, something is wrong. Tools should be discovered first by calling DiscoverWiredTools() continue; if (pt->GetSROMData() == nullptr) continue; returnvalue = m_DeviceProtocol->PVWR(&ph, pt->GetSROMData(), pt->GetSROMDataLength()); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + pt->GetToolName() + std::string("' to tracking device")).c_str();} + { + mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + pt->GetToolName() + std::string("' to tracking device")).c_str(); + } returnvalue = m_DeviceProtocol->PINIT(&ph); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + pt->GetToolName()).c_str();} + { + mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize tool '") + pt->GetToolName()).c_str(); + } if (pt->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&ph, pt->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + portHandle + - std::string("' for tool '")+ pt->GetToolName() + std::string("'")).c_str(); + std::string("' for tool '") + pt->GetToolName() + std::string("'")).c_str(); } } } return true; } - mitk::TrackingDeviceType mitk::NDITrackingDevice::TestConnection() { if (this->GetState() != Setup) { return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); } m_SerialCommunication = mitk::SerialCommunication::New(); //m_DeviceProtocol = mitk::NDIProtocol::New(); //m_DeviceProtocol->SetTrackingDevice(this); //m_DeviceProtocol->UseCRCOn(); /* init local com port to standard com settings for a NDI tracking device: 9600 baud, 8 data bits, no parity, 1 stop bit, no hardware handshake */ if (m_DeviceName.empty()) m_SerialCommunication->SetPortNumber(m_PortNumber); else m_SerialCommunication->SetDeviceName(m_DeviceName); m_SerialCommunication->SetBaudRate(mitk::SerialCommunication::BaudRate9600); m_SerialCommunication->SetDataBits(mitk::SerialCommunication::DataBits8); m_SerialCommunication->SetParity(mitk::SerialCommunication::None); m_SerialCommunication->SetStopBits(mitk::SerialCommunication::StopBits1); m_SerialCommunication->SetSendTimeout(5000); m_SerialCommunication->SetReceiveTimeout(5000); if (m_SerialCommunication->OpenConnection() == 0) // error { m_SerialCommunication = nullptr; return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); } /* Reset Tracking device by sending a serial break for 500ms */ m_SerialCommunication->SendBreak(400); /* Read answer from tracking device (RESETBE6F) */ static const std::string reset("RESETBE6F\r"); std::string answer = ""; this->Receive(&answer, reset.length()); // read answer (should be RESETBE6F) this->ClearReceiveBuffer(); // flush the receive buffer of all remaining data (carriage return, strings other than reset if (reset.compare(answer) != 0) // check for RESETBE6F { m_SerialCommunication->CloseConnection(); m_SerialCommunication = nullptr; mitkThrowException(mitk::IGTHardwareException) << "Hardware Reset of tracking device did not work"; } /* Now the tracking device is reset, start initialization */ NDIErrorCode returnvalue; /* initialize the tracking device */ //returnvalue = m_DeviceProtocol->INIT(); //if (returnvalue != NDIOKAY) //{ // this->SetErrorMessage("Could not initialize the tracking device"); // return mitk::TrackingSystemNotSpecified; //} - - mitk::TrackingDeviceType deviceType; - returnvalue = m_DeviceProtocol->VER(deviceType); - if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName())) - { - m_SerialCommunication = nullptr; - return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); - } + mitk::TrackingDeviceType deviceType; + returnvalue = m_DeviceProtocol->VER(deviceType); + if ((returnvalue != NDIOKAY) || (deviceType == mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName())) + { m_SerialCommunication = nullptr; - return deviceType; + return mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); + } + m_SerialCommunication = nullptr; + return deviceType; } - bool mitk::NDITrackingDevice::CloseConnection() { if (this->GetState() != Setup) { //init before closing to force the field generator from aurora to switch itself off m_DeviceProtocol->INIT(); /* close the serial connection */ m_SerialCommunication->CloseConnection(); /* invalidate all tools */ this->InvalidateAll(); /* return to setup mode */ this->SetState(Setup); m_SerialCommunication = nullptr; } return true; } - ITK_THREAD_RETURN_TYPE mitk::NDITrackingDevice::ThreadStartTracking(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } NDITrackingDevice *trackingDevice = (NDITrackingDevice*)pInfo->UserData; if (trackingDevice != nullptr) { if (trackingDevice->GetOperationMode() == ToolTracking6D) trackingDevice->TrackTools(); // call TrackTools() from the original object else if (trackingDevice->GetOperationMode() == MarkerTracking3D) trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object else if (trackingDevice->GetOperationMode() == ToolTracking5D) trackingDevice->TrackMarkerPositions(); // call TrackMarkerPositions() from the original object else if (trackingDevice->GetOperationMode() == HybridTracking) { trackingDevice->TrackToolsAndMarkers(); } } trackingDevice->m_ThreadID = 0; // erase thread id, now that this thread will end. return ITK_THREAD_RETURN_VALUE; } - bool mitk::NDITrackingDevice::StartTracking() { if (this->GetState() != Ready) return false; this->SetState(Tracking); // go to mode Tracking this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking this->m_StopTracking = false; this->m_StopTrackingMutex->Unlock(); m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method mitk::IGTTimeStamp::GetInstance()->Start(this); return true; } - void mitk::NDITrackingDevice::TrackTools() { /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */ MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (this->GetState() != Tracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->TSTART(); if (returnvalue != NDIOKAY) return; - - bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { if (this->m_DataTransferMode == TX) { returnvalue = this->m_DeviceProtocol->TX(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors break; } else { returnvalue = this->m_DeviceProtocol->BX(); if (returnvalue != NDIOKAY) break; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->TSTOP(); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << "An error occured while tracking tools.";} + { + mitkThrowException(mitk::IGTHardwareException) << "An error occured while tracking tools."; + } return; // returning from this function (and ThreadStartTracking()) this will end the thread and transfer control back to main thread by releasing trackingFinishedLockHolder } - void mitk::NDITrackingDevice::TrackMarkerPositions() { MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (m_OperationMode == ToolTracking6D) return; if (this->GetState() != Tracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->DSTART(); // Start Diagnostic Mode if (returnvalue != NDIOKAY) return; bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { m_MarkerPointsMutex->Lock(); // lock points data structure returnvalue = this->m_DeviceProtocol->POS3D(&m_MarkerPoints); // update points data structure with new position data from tracking device m_MarkerPointsMutex->Unlock(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors { std::cout << "Error in POS3D: could not read data. Possibly no markers present." << std::endl; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); itksys::SystemTools::Delay(1); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->DSTOP(); if (returnvalue != NDIOKAY) return; // how can this thread tell the application, that an error has occured? this->SetState(Ready); return; // returning from this function (and ThreadStartTracking()) this will end the thread } - void mitk::NDITrackingDevice::TrackToolsAndMarkers() { - MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope if (m_OperationMode != HybridTracking) return; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->TSTART(); // Start Diagnostic Mode if (returnvalue != NDIOKAY) return; bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); while ((this->GetState() == Tracking) && (localStopTracking == false)) { m_MarkerPointsMutex->Lock(); // lock points data structure returnvalue = this->m_DeviceProtocol->TX(true, &m_MarkerPoints); // update points data structure with new position data from tracking device m_MarkerPointsMutex->Unlock(); if (!((returnvalue == NDIOKAY) || (returnvalue == NDICRCERROR) || (returnvalue == NDICRCDOESNOTMATCH))) // right now, do not stop on crc errors { std::cout << "Error in TX: could not read data. Possibly no markers present." << std::endl; } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } /* StopTracking was called, thus the mode should be changed back to Ready now that the tracking loop has ended. */ returnvalue = m_DeviceProtocol->TSTOP(); if (returnvalue != NDIOKAY) return; // how can this thread tell the application, that an error has occurred? this->SetState(Ready); return; // returning from this function (and ThreadStartTracking()) this will end the thread } - mitk::TrackingTool* mitk::NDITrackingDevice::GetTool(unsigned int toolNumber) const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex if (toolNumber < m_6DTools.size()) return m_6DTools.at(toolNumber); return nullptr; } - mitk::TrackingTool* mitk::NDITrackingDevice::GetToolByName(std::string name) const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) if (name.compare((*iterator)->GetToolName()) == 0) return *iterator; return nullptr; } - mitk::NDIPassiveTool* mitk::NDITrackingDevice::GetInternalTool(std::string portHandle) { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) if (portHandle.compare((*iterator)->GetPortHandle()) == 0) return *iterator; return nullptr; } - unsigned int mitk::NDITrackingDevice::GetToolCount() const { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex return m_6DTools.size(); } - bool mitk::NDITrackingDevice::Beep(unsigned char count) { if (this->GetState() != Setup) { return (m_DeviceProtocol->BEEP(count) == NDIOKAY); } else { return false; } } -mitk::TrackingTool* mitk::NDITrackingDevice::AddTool( const char* toolName, const char* fileName, TrackingPriority p /*= NDIPassiveTool::Dynamic*/ ) +mitk::TrackingTool* mitk::NDITrackingDevice::AddTool(const char* toolName, const char* fileName, TrackingPriority p /*= NDIPassiveTool::Dynamic*/) { mitk::NDIPassiveTool::Pointer t = mitk::NDIPassiveTool::New(); if (t->LoadSROMFile(fileName) == false) return nullptr; t->SetToolName(toolName); t->SetTrackingPriority(p); if (this->InternalAddTool(t) == false) return nullptr; return t.GetPointer(); } - bool mitk::NDITrackingDevice::InternalAddTool(mitk::NDIPassiveTool* tool) { if (tool == nullptr) return false; NDIPassiveTool::Pointer p = tool; /* if the connection to the tracking device is already established, add the new tool to the device now */ if (this->GetState() == Ready) { /* get a port handle for the tool */ std::string newPortHandle; NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PHRQ(&newPortHandle); if (returnvalue == NDIOKAY) { p->SetPortHandle(newPortHandle.c_str()); /* now write the SROM file of the tool to the tracking system using PVWR */ returnvalue = m_DeviceProtocol->PVWR(&newPortHandle, p->GetSROMData(), p->GetSROMDataLength()); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + p->GetToolName() + std::string("' to tracking device")).c_str();} + { + mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not write SROM file for tool '") + p->GetToolName() + std::string("' to tracking device")).c_str(); + } /* initialize the port handle */ returnvalue = m_DeviceProtocol->PINIT(&newPortHandle); if (returnvalue != NDIOKAY) - { - mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + newPortHandle + - std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str(); - } + { + mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + newPortHandle + + std::string("' for tool '") + p->GetToolName() + std::string("'")).c_str(); + } /* enable the port handle */ if (p->IsEnabled() == true) { returnvalue = m_DeviceProtocol->PENA(&newPortHandle, p->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + newPortHandle + - std::string("' for tool '")+ p->GetToolName() + std::string("'")).c_str(); + std::string("' for tool '") + p->GetToolName() + std::string("'")).c_str(); } } } /* now that the tool is added to the device, add it to list too */ m_ToolsMutex->Lock(); this->m_6DTools.push_back(p); m_ToolsMutex->Unlock(); this->Modified(); return true; } else if (this->GetState() == Setup) { /* In Setup mode, we only add it to the list, so that OpenConnection() can add it later */ m_ToolsMutex->Lock(); this->m_6DTools.push_back(p); m_ToolsMutex->Unlock(); this->Modified(); return true; } else // in Tracking mode, no tools can be added return false; } - bool mitk::NDITrackingDevice::RemoveTool(mitk::TrackingTool* tool) { mitk::NDIPassiveTool* ndiTool = dynamic_cast(tool); if (ndiTool == nullptr) return false; std::string portHandle = ndiTool->GetPortHandle(); /* a valid portHandle has length 2. If a valid handle exists, the tool is already added to the tracking device, so we have to remove it there if the connection to the tracking device has already been established. */ if ((portHandle.length() == 2) && (this->GetState() == Ready)) // do not remove a tool in tracking mode { NDIErrorCode returnvalue; returnvalue = m_DeviceProtocol->PHF(&portHandle); if (returnvalue != NDIOKAY) return false; /* Now that the tool is removed from the tracking device, remove it from our tool list too */ MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex (scope is inside the if-block auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) { if (iterator->GetPointer() == ndiTool) { m_6DTools.erase(iterator); this->Modified(); return true; } } return false; } else if (this->GetState() == Setup) // in Setup Mode, we are not connected to the tracking device, so we can just remove the tool from the tool list { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) { if ((*iterator).GetPointer() == ndiTool) { m_6DTools.erase(iterator); this->Modified(); return true; } } return false; } return false; } - void mitk::NDITrackingDevice::InvalidateAll() { MutexLockHolder toolsMutexLockHolder(*m_ToolsMutex); // lock and unlock the mutex auto end = m_6DTools.end(); for (auto iterator = m_6DTools.begin(); iterator != end; ++iterator) (*iterator)->SetDataValid(false); } - bool mitk::NDITrackingDevice::SetOperationMode(OperationMode mode) { if (GetState() == Tracking) return false; m_OperationMode = mode; return true; } - mitk::OperationMode mitk::NDITrackingDevice::GetOperationMode() { return m_OperationMode; } - bool mitk::NDITrackingDevice::GetMarkerPositions(MarkerPointContainerType* markerpositions) { m_MarkerPointsMutex->Lock(); *markerpositions = m_MarkerPoints; // copy the internal vector to the one provided m_MarkerPointsMutex->Unlock(); - return (markerpositions->size() != 0) ; + return (markerpositions->size() != 0); } - bool mitk::NDITrackingDevice::DiscoverWiredTools() { /* First, check for disconnected tools and remove them */ this->FreePortHandles(); /* check for new tools, add and initialize them */ NDIErrorCode returnvalue; std::string portHandle; returnvalue = m_DeviceProtocol->PHSR(OCCUPIED, &portHandle); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected";} + { + mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that are connected"; + } /* if there are port handles that need to be initialized, initialize them. Furthermore instantiate tools for each handle that has no tool yet. */ std::string ph; /* we need to remember the ports which are occupied to be able to readout the serial numbers of the connected tools later */ std::vector occupiedPorts = std::vector(); int numberOfToolsAtStart = this->GetToolCount(); //also remember the number of tools at start to identify the automatically detected tools later for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); if (this->GetInternalTool(ph) != nullptr) // if we already have a tool with this handle continue; // then skip the initialization //instantiate an object for each tool that is connected mitk::NDIPassiveTool::Pointer newTool = mitk::NDIPassiveTool::New(); newTool->SetPortHandle(ph.c_str()); newTool->SetTrackingPriority(mitk::NDIPassiveTool::Dynamic); //set a name for identification newTool->SetToolName((std::string("Port ") + ph).c_str()); returnvalue = m_DeviceProtocol->PINIT(&ph); if (returnvalue != NDIINITIALIZATIONFAILED) //if the initialization failed (AURORA) it can not be enabled. A srom file will have to be specified manually first. Still return true to be able to continue { if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not initialize port '") + ph + - std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str(); + std::string("' for tool '") + newTool->GetToolName() + std::string("'")).c_str(); } /* enable the port handle */ returnvalue = m_DeviceProtocol->PENA(&ph, newTool->GetTrackingPriority()); // Enable tool if (returnvalue != NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << (std::string("Could not enable port '") + ph + - std::string("' for tool '")+ newTool->GetToolName() + std::string("'")).c_str(); + std::string("' for tool '") + newTool->GetToolName() + std::string("'")).c_str(); } } //we have to temporarily unlock m_ModeMutex here to avoid a deadlock with another lock inside InternalAddTool() if (this->InternalAddTool(newTool) == false) - {mitkThrowException(mitk::IGTException) << "Error while adding new tool";} + { + mitkThrowException(mitk::IGTException) << "Error while adding new tool"; + } else occupiedPorts.push_back(i); } - // after initialization readout serial numbers of automatically detected tools for (unsigned int i = 0; i < occupiedPorts.size(); i++) - { + { ph = portHandle.substr(occupiedPorts.at(i), 2); std::string portInfo; NDIErrorCode returnvaluePort = m_DeviceProtocol->PHINF(ph, &portInfo); - if ((returnvaluePort==NDIOKAY) && (portInfo.size()>31)) dynamic_cast(this->GetTool(i+numberOfToolsAtStart))->SetSerialNumber(portInfo.substr(23,8)); + if ((returnvaluePort == NDIOKAY) && (portInfo.size()>31)) dynamic_cast(this->GetTool(i + numberOfToolsAtStart))->SetSerialNumber(portInfo.substr(23, 8)); itksys::SystemTools::Delay(10); - } + } return true; } - mitk::NDIErrorCode mitk::NDITrackingDevice::FreePortHandles() { /* first search for port handles that need to be freed: e.g. because of a reset of the tracking system */ NDIErrorCode returnvalue = NDIOKAY; std::string portHandle; returnvalue = m_DeviceProtocol->PHSR(FREED, &portHandle); if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that need to be freed";} + { + mitkThrowException(mitk::IGTHardwareException) << "Could not obtain a list of port handles that need to be freed"; + } /* if there are port handles that need to be freed, free them */ if (portHandle.empty() == true) return returnvalue; std::string ph; for (unsigned int i = 0; i < portHandle.size(); i += 2) { ph = portHandle.substr(i, 2); mitk::NDIPassiveTool* t = this->GetInternalTool(ph); if (t != nullptr) // if we have a tool for the port handle that needs to be freed { if (this->RemoveTool(t) == false) // remove it (this will free the port too) returnvalue = NDIERROR; } else // we don't have a tool, the port handle exists only in the tracking device { returnvalue = m_DeviceProtocol->PHF(&ph); // free it there // What to do if port handle could not be freed? This seems to be a non critical error if (returnvalue != NDIOKAY) - {mitkThrowException(mitk::IGTHardwareException) << "Could not free all port handles";} + { + mitkThrowException(mitk::IGTHardwareException) << "Could not free all port handles"; + } } } return returnvalue; } - int mitk::NDITrackingDevice::GetMajorFirmwareRevisionNumber() { std::string revision; - if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) ) + if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9)) { MITK_ERROR << "Could not receive firmware revision number!"; return 0; } - const std::string majrevno = revision.substr(2,3); //cut out "004" from "D.004.001" + const std::string majrevno = revision.substr(2, 3); //cut out "004" from "D.004.001" return std::atoi(majrevno.c_str()); } const char* mitk::NDITrackingDevice::GetFirmwareRevisionNumber() { static std::string revision; - if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9) ) + if (m_DeviceProtocol->APIREV(&revision) != mitk::NDIOKAY || revision.empty() || (revision.size() != 9)) { MITK_ERROR << "Could not receive firmware revision number!"; revision = ""; return revision.c_str(); } return revision.c_str(); } bool mitk::NDITrackingDevice::AutoDetectToolsAvailable() { if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { return true; } else { return false; } } +bool mitk::NDITrackingDevice::AddSingleToolIsAvailable() +{ + //For Aurora, only AutoDetecion or loading of toolStorage should be used. It is not possible to add a single tool. + if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { return false; } + //For Polaris, a single tool can be added, there is no autoDetection. + else { return true; } +} + mitk::NavigationToolStorage::Pointer mitk::NDITrackingDevice::AutoDetectTools() { mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(); if (this->GetType() == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) { try { this->OpenConnection(); this->StartTracking(); } catch (mitk::Exception& e) { MITK_WARN << "Warning, can not auto-detect tools! (" << e.GetDescription() << ")"; return autoDetectedStorage; } for (unsigned int i = 0; i < this->GetToolCount(); i++) { //create a navigation tool with sphere as surface std::stringstream toolname; toolname << "AutoDetectedTool" << i; mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); newTool->SetSerialNumber(dynamic_cast(this->GetTool(i))->GetSerialNumber()); newTool->SetIdentifier(toolname.str()); newTool->SetTrackingDeviceType(mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()); - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - mitk::Surface::Pointer mySphere = mitk::Surface::New(); - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(3.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - mySphere->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(mySphere); - newNode->SetName(toolname.str()); - newTool->SetDataNode(newNode); + newTool->GetDataNode()->SetName(toolname.str()); autoDetectedStorage->AddTool(newTool); } this->StopTracking(); this->CloseConnection(); } return autoDetectedStorage; } bool mitk::NDITrackingDevice::GetSupportedVolumes(unsigned int* numberOfVolumes, mitk::NDITrackingDevice::NDITrackingVolumeContainerType* volumes, mitk::NDITrackingDevice::TrackingVolumeDimensionType* volumesDimensions) { if (numberOfVolumes == nullptr || volumes == nullptr || volumesDimensions == nullptr) return false; static std::string info; if (m_DeviceProtocol->SFLIST(&info) != mitk::NDIOKAY || info.empty()) { MITK_ERROR << "Could not receive tracking volume information of tracking system!"; return false; } /*info contains the following: (+n times:) */ - (*numberOfVolumes) = (unsigned int) std::atoi(info.substr(0,1).c_str()); + (*numberOfVolumes) = (unsigned int)std::atoi(info.substr(0, 1).c_str()); - for (unsigned int i=0; i<(*numberOfVolumes); i++) + for (unsigned int i = 0; i < (*numberOfVolumes); i++) { //e.g. for cube: "9-025000+025000-025000+025000-055000-005000+000000+000000+000000+00000011" //for dome: "A+005000+048000+005000+066000+000000+000000+000000+000000+000000+00000011" std::string::size_type offset, end; - offset = (i*73)+1; - end = 73+(i*73); + offset = (i * 73) + 1; + end = 73 + (i * 73); std::string currentVolume = info.substr(offset, end);//i=0: from 1 to 73 characters; i=1: from 75 to 148 char; // if i>0 then we have a return statement infront - if (i>0) + if (i > 0) currentVolume = currentVolume.substr(1, currentVolume.size()); if (currentVolume.compare(0, 1, NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisOldModel().Model); if (currentVolume.compare(0, 3, NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisSpectra().Model); if (currentVolume.compare(1, 3, NDIPolarisTypeInformation::GetDeviceDataSpectraExtendedPyramid().HardwareCode) == 0) { - currentVolume = currentVolume.substr(1,currentVolume.size()); + currentVolume = currentVolume.substr(1, currentVolume.size()); volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataSpectraExtendedPyramid().Model); } if (currentVolume.compare(0, 1, NDIPolarisTypeInformation::GetDeviceDataPolarisVicra().HardwareCode) == 0) volumes->push_back(NDIPolarisTypeInformation::GetDeviceDataPolarisVicra().Model); else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().HardwareCode) == 0) volumes->push_back(mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarCube().Model);//alias cube else if (currentVolume.compare(0, 1, mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome().HardwareCode) == 0) volumes->push_back(mitk::NDIAuroraTypeInformation::GetDeviceDataAuroraPlanarDome().Model); //fill volumesDimensions for (unsigned int index = 0; index < 10; index++) { std::string::size_type offD, endD; - offD = 1+(index*7); //7 digits per dimension and the first is the type of volume - endD = offD+7; + offD = 1 + (index * 7); //7 digits per dimension and the first is the type of volume + endD = offD + 7; int dimension = std::atoi(currentVolume.substr(offD, endD).c_str()); dimension /= 100; //given in mm. 7 digits are xxxx.xx according to NDI //strange, the last two digits (11) also for the metal flag get read also... volumesDimensions->push_back(dimension); } } return true; } bool mitk::NDITrackingDevice::SetVolume(mitk::TrackingDeviceData volume) { if (m_DeviceProtocol->VSEL(volume) != mitk::NDIOKAY) { mitkThrowException(mitk::IGTHardwareException) << "Could not set volume!"; } return true; -} - +} \ No newline at end of file diff --git a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.h b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.h index 9895aa12fe..e7dcfd2226 100644 --- a/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.h +++ b/Modules/IGT/TrackingDevices/mitkNDITrackingDevice.h @@ -1,331 +1,334 @@ /*=================================================================== 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 MITKNDITRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 #define MITKNDITRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 #include "mitkTrackingDevice.h" #include #include #include "itkFastMutexLock.h" #include #include "mitkNDIProtocol.h" #include "mitkNDIPassiveTool.h" #include "mitkSerialCommunication.h" namespace mitk { class NDIProtocol; /** Documentation * \brief superclass for specific NDI tracking Devices that use serial communication. * * implements the TrackingDevice interface for NDI tracking devices (POLARIS, AURORA) * * \ingroup IGT */ class MITKIGT_EXPORT NDITrackingDevice : public TrackingDevice { friend class NDIProtocol; public: typedef std::vector Tool6DContainerType; ///< List of 6D tools of the correct type for this tracking device typedef mitk::TrackingDeviceType NDITrackingDeviceType; ///< This enumeration includes the two types of NDI tracking devices (Polaris, Aurora). typedef mitk::SerialCommunication::PortNumber PortNumber; ///< Port number of the serial connection typedef mitk::SerialCommunication::BaudRate BaudRate; ///< Baud rate of the serial connection typedef mitk::SerialCommunication::DataBits DataBits; ///< Number of data bits used in the serial connection typedef mitk::SerialCommunication::Parity Parity; ///< Parity mode used in the serial connection typedef mitk::SerialCommunication::StopBits StopBits; ///< Number of stop bits used in the serial connection typedef mitk::SerialCommunication::HardwareHandshake HardwareHandshake; ///< Hardware handshake mode of the serial connection typedef mitk::NDIPassiveTool::TrackingPriority TrackingPriority; ///< Tracking priority used for tracking a tool mitkClassMacro(NDITrackingDevice, TrackingDevice); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** * \brief Set the type of the NDI Tracking Device because it can not jet handle this itself */ //itkSetMacro(Type, TrackingDeviceType); /** * \brief initialize the connection to the tracking device * * OpenConnection() establishes the connection to the tracking device by: * - initializing the serial port with the given parameters (port number, baud rate, ...) * - connection to the tracking device * - initializing the device * - initializing all manually added passive tools (user supplied srom file) * - initializing active tools that are connected to the tracking device * @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. * @throw mitk::IGTException Throws a normal IGT exception if an error occures which is not related to the hardware. */ virtual bool OpenConnection() override; /** * \brief Closes the connection * * CloseConnection() resets the tracking device, invalidates all tools and then closes the serial port. */ virtual bool CloseConnection() override; /** @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. */ bool InitializeWiredTools(); /** Sets the rotation mode of this class. See documentation of enum RotationMode for details * on the different modes. */ virtual void SetRotationMode(RotationMode r) override; /** * \brief TestConnection() tries to connect to a NDI tracking device on the current port/device and returns which device it has found * * TestConnection() tries to connect to a NDI tracking device on the current port/device. * \return It returns the type of the device that answers at the port/device. Throws an exception if no device is available on that port. * @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. */ virtual mitk::TrackingDeviceType TestConnection(); /** * \brief retrieves all wired tools from the tracking device * * This method queries the tracking device for all wired tools, initializes them and creates TrackingTool representation objects * for them * \return True if the method was executed successful. * @throw mitk::IGTHardwareException Throws an exception if there are errors while connecting to the device. * @throw mitk::IGTException Throws a normal IGT exception if an error occures which is not related to the hardware. */ bool DiscoverWiredTools(); /** * \brief Start the tracking. * * A new thread is created, which continuously reads the position and orientation information of each tool and stores them inside the tools. * Depending on the current operation mode (see SetOperationMode()), either the 6D tools (ToolTracking6D), 5D tools (ToolTracking5D), * 3D marker positions (MarkerTracking3D) or both 6D tools and 3D markers (HybridTracking) are updated. * Call StopTracking() to stop the tracking thread. */ virtual bool StartTracking() override; /** * \brief return the tool with index toolNumber */ virtual TrackingTool* GetTool(unsigned int toolNumber) const override; virtual mitk::TrackingTool* GetToolByName(std::string name) const override; /** * \brief return current number of tools */ virtual unsigned int GetToolCount() const override; /** * \brief Create a passive 6D tool with toolName and fileName and add it to the list of tools * * This method will create a new NDIPassiveTool object, load the SROM file fileName, * set the tool name toolName and the tracking priority p and then add * it to the list of tools. It returns a pointer of type mitk::TrackingTool to the tool * that can be used to read tracking data from it. * This is the only way to add tools to NDITrackingDevice. * @throw mitk::IGTHardwareException Throws an exception if there are errors while adding the tool. * * \warning adding tools is not possible in tracking mode, only in setup and ready. */ mitk::TrackingTool* AddTool(const char* toolName, const char* fileName, TrackingPriority p = NDIPassiveTool::Dynamic); /** * \brief Remove a passive 6D tool from the list of tracked tools. * * \warning removing tools is not possible in tracking mode, only in setup and ready modes. */ virtual bool RemoveTool(TrackingTool* tool); /** * \brief reloads the srom file and reinitializes the tool */ virtual bool UpdateTool(mitk::TrackingTool* tool); virtual void SetPortNumber(const PortNumber _arg); ///< set port number for serial communication itkGetConstMacro(PortNumber, PortNumber); ///< returns the port number for serial communication virtual void SetDeviceName(std::string _arg); ///< set device name (e.g. COM1, /dev/ttyUSB0). If this is set, PortNumber will be ignored itkGetStringMacro(DeviceName); ///< returns the device name for serial communication virtual void SetBaudRate(const BaudRate _arg); ///< set baud rate for serial communication itkGetConstMacro(BaudRate, BaudRate); ///< returns the baud rate for serial communication virtual void SetDataBits(const DataBits _arg); ///< set number of data bits itkGetConstMacro(DataBits, DataBits); ///< returns the data bits for serial communication virtual void SetParity(const Parity _arg); ///< set parity mode itkGetConstMacro(Parity, Parity); ///< returns the parity mode virtual void SetStopBits(const StopBits _arg); ///< set number of stop bits itkGetConstMacro(StopBits, StopBits); ///< returns the number of stop bits virtual void SetHardwareHandshake(const HardwareHandshake _arg); ///< set use hardware handshake for serial communication itkGetConstMacro(HardwareHandshake, HardwareHandshake); ///< returns the hardware handshake setting virtual void SetIlluminationActivationRate(const IlluminationActivationRate _arg); ///< set activation rate of IR illumator for polaris itkGetConstMacro(IlluminationActivationRate, IlluminationActivationRate); ///< returns the activation rate of IR illumator for polaris virtual void SetDataTransferMode(const DataTransferMode _arg); ///< set data transfer mode to text (TX) or binary (BX). \warning: only TX is supportet at the moment itkGetConstMacro(DataTransferMode, DataTransferMode); ///< returns the data transfer mode virtual bool Beep(unsigned char count); ///< Beep the tracking device 1 to 9 times NDIErrorCode GetErrorCode(const std::string* input); ///< returns the error code for a string that contains an error code in hexadecimal format virtual bool SetOperationMode(OperationMode mode); ///< set operation mode to 6D tool tracking, 3D marker tracking or 6D&3D hybrid tracking (see OperationMode) virtual OperationMode GetOperationMode(); ///< get current operation mode /** * \brief Get 3D marker positions (operation mode must be set to MarkerTracking3D or HybridTracking) */ virtual bool GetMarkerPositions(MarkerPointContainerType* markerpositions); /** * \brief Get major revision number from tracking device * should not be called directly after starting to track **/ virtual int GetMajorFirmwareRevisionNumber(); /** * \brief Get revision number from tracking device as string * should not be called directly after starting to track **/ virtual const char* GetFirmwareRevisionNumber(); /** @return Returns true if this device can autodetects its tools. */ virtual bool AutoDetectToolsAvailable(); + /** @return Returns true if it is possible to add a single tool. True for Polaris, false for Aurora.*/ + virtual bool AddSingleToolIsAvailable(); + /** Autodetects tools from this device and returns them as a navigation tool storage. * @return Returns the detected tools. Returns an empty storage if no tools are present * or if detection is not possible */ virtual mitk::NavigationToolStorage::Pointer AutoDetectTools(); protected: typedef std::vector NDITrackingVolumeContainerType; ///< vector of tracking volumes typedef std::vector TrackingVolumeDimensionType; ///< List of the supported tracking volume dimensions. /** * \brief Get number of supported tracking volumes, a vector containing the supported volumes and * a vector containing the signed dimensions in mm. For each volume 10 boundaries are stored in the order of * the supported volumes (see AURORA API GUIDE: SFLIST p.54). **/ virtual bool GetSupportedVolumes(unsigned int* numberOfVolumes, NDITrackingVolumeContainerType* volumes, TrackingVolumeDimensionType* volumesDimensions); /** * \brief Sets the desired tracking volume. Returns true if the volume type could be set. It is set in the OpenConnection() Method and sets the tracking volume out of m_Data. * @throw mitk::IGTHardwareException Throws an IGT hardware exception if the volume could not be set. **/ virtual bool SetVolume(mitk::TrackingDeviceData volume); /** * \brief Add a passive 6D tool to the list of tracked tools. This method is used by AddTool * @throw mitk::IGTHardwareException Throws an exception if there are errors while adding the tool. * \warning adding tools is not possible in tracking mode, only in setup and ready. */ virtual bool InternalAddTool(NDIPassiveTool* tool); /* Methods for NDIProtocol friend class */ virtual void InvalidateAll(); ///< invalidate all tools NDIPassiveTool* GetInternalTool(std::string portHandle); ///< returns the tool object that has been assigned the port handle or nullptr if no tool can be found /** * \brief free all port handles that need to be freed * * This method retrieves a list of all port handles that need to be freed (e.g. tool got disconnected) * and frees the handles at the tracking device and it removes the tools from the internal tool list * \warning This method can remove TrackingTools from the tool list! After calling this method, GetTool(i) could return * a different tool, because tool indices could have changed. * @throw mitk::IGTHardwareException Throws an exception if there are errors while communicating with the device. * \return returns NDIOKAY if everything was sucessfull, returns an error code otherwise */ NDIErrorCode FreePortHandles(); NDIErrorCode Send(const std::string* message, bool addCRC = true); ///< Send message to tracking device NDIErrorCode Receive(std::string* answer, unsigned int numberOfBytes); ///< receive numberOfBytes bytes from tracking device NDIErrorCode ReceiveByte(char* answer); ///< lightweight receive function, that reads just one byte NDIErrorCode ReceiveLine(std::string* answer); ///< receive characters until the first LF (The LF is included in the answer string) void ClearSendBuffer(); ///< empty send buffer of serial communication interface void ClearReceiveBuffer(); ///< empty receive buffer of serial communication interface const std::string CalcCRC(const std::string* input); ///< returns the CRC16 for input as a std::string public: /** * \brief TrackTools() continuously polls serial interface for new 6d tool positions until StopTracking is called. * * Continuously tracks the 6D position of all tools until StopTracking() is called. * This function is executed by the tracking thread (through StartTracking() and ThreadStartTracking()). * It should not be called directly. * @throw mitk::IGTHardwareException Throws an exception if there are errors while tracking the tools. */ virtual void TrackTools(); /** * \brief continuously polls serial interface for new 3D marker positions until StopTracking is called. * * Continuously tracks the 3D position of all markers until StopTracking() is called. * This function is executed by the tracking thread (through StartTracking() and ThreadStartTracking()). * It should not be called directly. */ virtual void TrackMarkerPositions(); /** * \brief continuously polls serial interface for new 3D marker positions and 6D tool positions until StopTracking is called. * * Continuously tracks the 3D position of all markers and the 6D position of all tools until StopTracking() is called. * This function is executed by the tracking thread (through StartTracking() and ThreadStartTracking()). * It should not be called directly. */ virtual void TrackToolsAndMarkers(); /** * \brief static start method for the tracking thread. */ static ITK_THREAD_RETURN_TYPE ThreadStartTracking(void* data); protected: NDITrackingDevice(); ///< Constructor virtual ~NDITrackingDevice(); ///< Destructor std::string m_DeviceName;///< Device Name PortNumber m_PortNumber; ///< COM Port Number BaudRate m_BaudRate; ///< COM Port Baud Rate DataBits m_DataBits; ///< Number of Data Bits per token Parity m_Parity; ///< Parity mode for communication StopBits m_StopBits; ///< number of stop bits per token HardwareHandshake m_HardwareHandshake; ///< use hardware handshake for serial port connection ///< which tracking volume is currently used (if device supports multiple volumes) (\warning This parameter is not used yet) IlluminationActivationRate m_IlluminationActivationRate; ///< update rate of IR illuminator for Polaris DataTransferMode m_DataTransferMode; ///< use TX (text) or BX (binary) (\warning currently, only TX mode is supported) Tool6DContainerType m_6DTools; ///< list of 6D tools itk::FastMutexLock::Pointer m_ToolsMutex; ///< mutex for coordinated access of tool container mitk::SerialCommunication::Pointer m_SerialCommunication; ///< serial communication interface itk::FastMutexLock::Pointer m_SerialCommunicationMutex; ///< mutex for coordinated access of serial communication interface NDIProtocol::Pointer m_DeviceProtocol; ///< create and parse NDI protocol strings itk::MultiThreader::Pointer m_MultiThreader; ///< creates tracking thread that continuously polls serial interface for new tracking data int m_ThreadID; ///< ID of tracking thread OperationMode m_OperationMode; ///< tracking mode (6D tool tracking, 3D marker tracking,...) itk::FastMutexLock::Pointer m_MarkerPointsMutex; ///< mutex for marker point data container MarkerPointContainerType m_MarkerPoints; ///< container for markers (3D point tracking mode) }; } // namespace mitk #endif /* MITKNDITRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 */ diff --git a/Modules/IGT/TrackingDevices/mitkNPOptitrackTrackingTypeInformation.cpp b/Modules/IGT/TrackingDevices/mitkNPOptitrackTrackingTypeInformation.cpp index e16418f2ed..7b56482453 100644 --- a/Modules/IGT/TrackingDevices/mitkNPOptitrackTrackingTypeInformation.cpp +++ b/Modules/IGT/TrackingDevices/mitkNPOptitrackTrackingTypeInformation.cpp @@ -1,75 +1,75 @@ /*=================================================================== 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 "mitkNPOptitrackTrackingTypeInformation.h" #include "mitkOptitrackTrackingDevice.h" namespace mitk { std::string NPOptitrackTrackingTypeInformation::GetTrackingDeviceName() { return "NP Optitrack"; } TrackingDeviceData NPOptitrackTrackingTypeInformation::GetDeviceDataNPOptitrack() { TrackingDeviceData data = { NPOptitrackTrackingTypeInformation::GetTrackingDeviceName(), "Optitrack", "cube", "X" }; return data; } NPOptitrackTrackingTypeInformation::NPOptitrackTrackingTypeInformation() { m_DeviceName = NPOptitrackTrackingTypeInformation::GetTrackingDeviceName(); m_TrackingDeviceData.push_back(GetDeviceDataNPOptitrack()); } NPOptitrackTrackingTypeInformation::~NPOptitrackTrackingTypeInformation() { } TrackingDeviceSource::Pointer NPOptitrackTrackingTypeInformation::CreateTrackingDeviceSource( TrackingDevice::Pointer trackingDevice, NavigationToolStorage::Pointer navigationTools, std::string* errorMessage, std::vector* toolCorrespondencesInToolStorage) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::OptitrackTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); *toolCorrespondencesInToolStorage = std::vector(); //OpenConnection with Optitrack thisDevice->OpenConnection(); //add the tools to the tracking device - for (int i = 0; i < navigationTools->GetToolCount(); i++) + for (unsigned int i = 0; i < navigationTools->GetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = navigationTools->GetTool(i); toolCorrespondencesInToolStorage->push_back(i); bool toolAddSuccess = thisDevice->AddToolByDefinitionFile(thisNavigationTool->GetCalibrationFile()); thisDevice->GetOptitrackTool(i)->SetToolName(thisNavigationTool->GetToolName().c_str()); if (!toolAddSuccess) { //todo error handling errorMessage->append("Can't add tool, is the toolfile valid?"); return nullptr; } //thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(),thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } } diff --git a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp index 954ec5487f..0ea2bd84e4 100644 --- a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp @@ -1,524 +1,508 @@ /*=================================================================== 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 "mitkOpenIGTLinkTrackingDevice.h" #include "mitkOpenIGTLinkTrackingTool.h" #include "mitkIGTConfig.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTHardwareException.h" #include "mitkTrackingTypes.h" #include #include #include #include #include #include //sleep headers #include #include typedef itk::MutexLockHolder MutexLockHolder; mitk::OpenIGTLinkTrackingDevice::OpenIGTLinkTrackingDevice() : mitk::TrackingDevice(), m_UpdateRate(60) { //set the type of this tracking device this->m_Data = mitk::OpenIGTLinkTypeInformation::GetDeviceDataOpenIGTLinkTrackingDeviceConnection(); m_OpenIGTLinkClient = mitk::IGTLClient::New(true); m_OpenIGTLinkClient->SetName("OpenIGTLink Tracking Device"); m_OpenIGTLinkClient->EnableNoBufferingMode(false); m_IGTLDeviceSource = mitk::IGTLTrackingDataDeviceSource::New(); m_IGTLDeviceSource->SetIGTLDevice(m_OpenIGTLinkClient); } mitk::OpenIGTLinkTrackingDevice::~OpenIGTLinkTrackingDevice() { } int mitk::OpenIGTLinkTrackingDevice::GetPortNumber() { return m_OpenIGTLinkClient->GetPortNumber(); } bool mitk::OpenIGTLinkTrackingDevice::AutoDetectToolsAvailable() { return true; } mitk::NavigationToolStorage::Pointer mitk::OpenIGTLinkTrackingDevice::AutoDetectTools() { mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(); if (m_OpenIGTLinkClient->GetPortNumber() == -1) { MITK_WARN << "Connection not initialized, aborting (invalid port number)."; return mitk::NavigationToolStorage::New(); } //open connection try { m_IGTLDeviceSource->Connect(); m_IGTLDeviceSource->StartCommunication(); } catch (std::runtime_error &e) { MITK_WARN << "AutoDetection: Open IGT Link device retruned an error while trying to connect: " << e.what(); return mitk::NavigationToolStorage::New(); } //get a message to find out type m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::UNKNOWN); mitk::IGTLMessage::Pointer receivedMessage = ReceiveMessage(100); const char* msgType = receivedMessage->GetIGTLMessageType(); if (std::string(msgType).empty()) { MITK_INFO << "Did not receive a message. Do you have to start the stream manually at the server?"; MITK_INFO << "Waiting for 10 seconds ..."; receivedMessage = ReceiveMessage(10000); msgType = receivedMessage->GetIGTLMessageType(); } MITK_INFO << "################# got message type: " << msgType; mitk::OpenIGTLinkTrackingDevice::TrackingMessageType type = GetMessageTypeFromString(msgType); switch (type) { case UNKNOWN: m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::UNKNOWN); break; case TDATA: m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::TDATA); break; case QTDATA: m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::QTDATA); break; case TRANSFORM: m_IGTLDeviceSource->SettrackingDataType(mitk::IGTLTrackingDataDeviceSource::TRANSFORM); break; } returnValue = DiscoverToolsAndConvertToNavigationTools(type); //close connection try { m_IGTLDeviceSource->StopCommunication(); m_IGTLDeviceSource->Disconnect(); } catch (std::runtime_error &e) { MITK_WARN << "AutoDetection: Open IGT Link device retruned an error while trying to disconnect: " << e.what(); return mitk::NavigationToolStorage::New(); } return returnValue; } mitk::NavigationToolStorage::Pointer mitk::OpenIGTLinkTrackingDevice::DiscoverToolsAndConvertToNavigationTools(mitk::OpenIGTLinkTrackingDevice::TrackingMessageType type, int NumberOfMessagesToWait) { MITK_INFO << "Start discovering tools by " << type << " messages"; mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(); std::map toolNameMap; for (int j = 0; jUpdate(); switch (type) { case TRANSFORM: { igtl::TransformMessage::Pointer msg = dynamic_cast(m_IGTLDeviceSource->GetOutput()->GetMessage().GetPointer()); if (msg == nullptr || msg.IsNull()) { MITK_INFO << "Received message is invalid / null. Skipping.."; continue; } int count = toolNameMap[msg->GetDeviceName()]; if (count == 0) { toolNameMap[msg->GetDeviceName()] = 1; } else { toolNameMap[msg->GetDeviceName()]++; } } break; case TDATA: { igtl::TrackingDataMessage::Pointer msg = dynamic_cast(m_IGTLDeviceSource->GetOutput()->GetMessage().GetPointer()); if (msg == nullptr || msg.IsNull()) { MITK_INFO << "Received message is invalid / null. Skipping.."; continue; } for (int k = 0; k < msg->GetNumberOfTrackingDataElements(); k++) { igtl::TrackingDataElement::Pointer tde; msg->GetTrackingDataElement(k, tde); if (tde.IsNotNull()) { int count = toolNameMap[tde->GetName()]; if (count == 0) { toolNameMap[tde->GetName()] = 1; } else { toolNameMap[tde->GetName()]++; } } } } break; default: MITK_WARN << "Only TRANSFORM and TDATA is currently supported, skipping!"; break; } } int i = 0; for (std::map::iterator it = toolNameMap.begin(); it != toolNameMap.end(); ++it) { MITK_INFO << "Found tool: " << it->first; std::stringstream name; name << it->first; std::stringstream identifier; identifier << "AutoDetectedTool-" << i; i++; mitk::NavigationTool::Pointer newTool = ConstructDefaultOpenIGTLinkTool(name.str(), identifier.str()); returnValue->AddTool(newTool); } return returnValue; } std::string mitk::OpenIGTLinkTrackingDevice::GetHostname() { return m_OpenIGTLinkClient->GetHostname(); } void mitk::OpenIGTLinkTrackingDevice::SetPortNumber(int portNumber) { m_OpenIGTLinkClient->SetPortNumber(portNumber); } void mitk::OpenIGTLinkTrackingDevice::SetHostname(std::string hostname) { m_OpenIGTLinkClient->SetHostname(hostname); } bool mitk::OpenIGTLinkTrackingDevice::IsDeviceInstalled() { return true; } mitk::TrackingTool* mitk::OpenIGTLinkTrackingDevice::AddTool(const char*, const char*) { mitk::OpenIGTLinkTrackingTool::Pointer t;// = mitk::OpenIGTLinkTrackingTool::New(); //TODO: Implement if (this->InternalAddTool(t) == false) return nullptr; return t.GetPointer(); } bool mitk::OpenIGTLinkTrackingDevice::InternalAddTool(OpenIGTLinkTrackingTool::Pointer tool) { m_AllTools.push_back(tool); return true; } bool mitk::OpenIGTLinkTrackingDevice::DiscoverTools(int waitingTime) { if (m_OpenIGTLinkClient->GetPortNumber() == -1) { MITK_WARN << "Connection not initialized, aborting (invalid port number)."; return false; } try { m_IGTLDeviceSource->Connect(); m_IGTLDeviceSource->StartCommunication(); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while trying to connect: " << e.what(); return false; } mitk::IGTLMessage::Pointer receivedMessage = ReceiveMessage(waitingTime); //check the tracking stream for the number and type of tools //igtl::MessageBase::Pointer receivedMessage = m_OpenIGTLinkClient->GetNextMessage(); if (receivedMessage.IsNull()) { MITK_WARN << "No message was received. Is there really a server?"; return false; } else if (!receivedMessage->IsDataValid()) { MITK_WARN << "Received invalid message."; return false; } const char* msgType = receivedMessage->GetIGTLMessageType(); mitk::OpenIGTLinkTrackingDevice::TrackingMessageType type = GetMessageTypeFromString(msgType); mitk::NavigationToolStorage::Pointer foundTools = this->DiscoverToolsAndConvertToNavigationTools(type); if (foundTools.IsNull() || (foundTools->GetToolCount() == 0)) { return false; } - for (int i = 0; i < foundTools->GetToolCount(); i++) { AddNewToolForName(foundTools->GetTool(i)->GetToolName(), i); } + for (unsigned int i = 0; i < foundTools->GetToolCount(); i++) { AddNewToolForName(foundTools->GetTool(i)->GetToolName(), i); } MITK_INFO << "Found tools: " << foundTools->GetToolCount(); return true; } mitk::IGTLMessage::Pointer mitk::OpenIGTLinkTrackingDevice::ReceiveMessage(int waitingTime) { mitk::IGTLMessage::Pointer receivedMessage; //send a message to the server: start tracking stream mitk::IGTLMessageFactory::Pointer msgFactory = m_OpenIGTLinkClient->GetMessageFactory(); std::string message[2] = {"STT_QTDATA","STT_TDATA"}; for (int i = 0; i < 2; i++) { igtl::MessageBase::Pointer sttMsg = msgFactory->CreateInstance(message[i]); //TODO: Fix this to dynamically get this from GUI ((igtl::StartTrackingDataMessage*)sttMsg.GetPointer())->SetResolution(m_UpdateRate); m_OpenIGTLinkClient->SendMessage(mitk::IGTLMessage::New(sttMsg)); } std::chrono::high_resolution_clock::time_point time = std::chrono::high_resolution_clock::now(); std::chrono::milliseconds d = std::chrono::milliseconds(waitingTime); while (!(receivedMessage.IsNotNull() && receivedMessage->IsDataValid())) { m_IGTLDeviceSource->Update(); receivedMessage = m_IGTLDeviceSource->GetOutput(); if ((time + d) < std::chrono::high_resolution_clock::now()) break; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } return receivedMessage; } void mitk::OpenIGTLinkTrackingDevice::AddNewToolForName(std::string name, int i) { mitk::OpenIGTLinkTrackingTool::Pointer newTool = mitk::OpenIGTLinkTrackingTool::New(); if (name == "") //if no name was given create a default name { std::stringstream defaultName; defaultName << "OpenIGTLinkTool#" << i; name = defaultName.str(); } MITK_INFO << "Added tool " << name << " to tracking device."; newTool->SetToolName(name); InternalAddTool(newTool); } mitk::NavigationTool::Pointer mitk::OpenIGTLinkTrackingDevice::ConstructDefaultOpenIGTLinkTool(std::string name, std::string identifier) { - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - - newNode->SetName(name); - - mitk::Surface::Pointer myCone = mitk::Surface::New(); - vtkConeSource *vtkData = vtkConeSource::New(); - vtkData->SetAngle(5.0); - vtkData->SetResolution(50); - vtkData->SetHeight(6.0f); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - myCone->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(myCone); - mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); - newTool->SetDataNode(newNode); + newTool->GetDataNode()->SetName(name); newTool->SetIdentifier(identifier); newTool->SetTrackingDeviceType(mitk::OpenIGTLinkTypeInformation::GetDeviceDataOpenIGTLinkTrackingDeviceConnection().Line); return newTool; } void mitk::OpenIGTLinkTrackingDevice::UpdateTools() { if (this->GetState() != Tracking) { MITK_ERROR << "Method was called in the wrong state, something went wrong!"; return; } m_IGTLMsgToNavDataFilter->Update(); for (std::size_t j = 0; j < m_IGTLMsgToNavDataFilter->GetNumberOfIndexedOutputs(); ++j) { mitk::NavigationData::Pointer currentNavData = m_IGTLMsgToNavDataFilter->GetOutput(j); const char* name = currentNavData->GetName(); for (std::size_t i = 0; i < m_AllTools.size(); i++) { if (strcmp(m_AllTools.at(i)->GetToolName(), name) == 0) { m_AllTools.at(i)->SetDataValid(currentNavData->IsDataValid()); m_AllTools.at(i)->SetPosition(currentNavData->GetPosition()); m_AllTools.at(i)->SetOrientation(currentNavData->GetOrientation()); m_AllTools.at(i)->SetIGTTimeStamp(currentNavData->GetIGTTimeStamp()); } } } } bool mitk::OpenIGTLinkTrackingDevice::StartTracking() { //check tracking state if (this->GetState() != Ready) { MITK_WARN << "Cannot start tracking, device is not ready!"; return false; } try { m_IGTLDeviceSource->StartCommunication(); //send a message to the server: start tracking stream mitk::IGTLMessageFactory::Pointer msgFactory = m_OpenIGTLinkClient->GetMessageFactory(); std::string message = "STT_TDATA"; //m_OpenIGTLinkClient->SendMessage(msgFactory->CreateInstance(message)); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while starting communication: " << e.what(); return false; } //create internal igtl pipeline m_IGTLMsgToNavDataFilter = mitk::IGTLMessageToNavigationDataFilter::New(); m_IGTLMsgToNavDataFilter->SetNumberOfExpectedOutputs(this->GetToolCount()); m_IGTLMsgToNavDataFilter->ConnectTo(m_IGTLDeviceSource); //connect itk events typedef itk::SimpleMemberCommand< mitk::OpenIGTLinkTrackingDevice > CurCommandType; CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); messageReceivedCommand->SetCallbackFunction(this, &mitk::OpenIGTLinkTrackingDevice::UpdateTools); m_MessageReceivedObserverTag = m_OpenIGTLinkClient->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); m_OpenIGTLinkClient->EnableNoBufferingMode(true); this->SetState(Tracking); return true; } bool mitk::OpenIGTLinkTrackingDevice::StopTracking() { //check tracking state if (this->GetState() != Tracking) { MITK_WARN << "Cannot open connection, device is already connected!"; return false; } m_OpenIGTLinkClient->RemoveObserver(m_MessageReceivedObserverTag); //disconnect itk events try { m_IGTLDeviceSource->StopCommunication(); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while stopping communication: " << e.what(); return false; } m_OpenIGTLinkClient->EnableNoBufferingMode(false); this->SetState(Ready); return true; } unsigned int mitk::OpenIGTLinkTrackingDevice::GetToolCount() const { return (unsigned int)this->m_AllTools.size(); } mitk::TrackingTool* mitk::OpenIGTLinkTrackingDevice::GetTool(unsigned int toolNumber) const { if (toolNumber >= this->GetToolCount()) return nullptr; else return this->m_AllTools[toolNumber]; } bool mitk::OpenIGTLinkTrackingDevice::OpenConnection() { //check tracking state if (this->GetState() != Setup) { MITK_WARN << "Cannot open connection, device is already connected!"; return false; } try { m_IGTLDeviceSource->Connect(); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while trying to connect: " << e.what(); return false; } this->SetState(Ready); return true; } bool mitk::OpenIGTLinkTrackingDevice::CloseConnection() { //check tracking state if (this->GetState() != Ready) { MITK_WARN << "Cannot close connection, device is in the wrong state!"; return false; } try { m_IGTLDeviceSource->Disconnect(); } catch (std::runtime_error &e) { MITK_WARN << "Open IGT Link device retruned an error while trying to disconnect: " << e.what(); return false; } this->SetState(Setup); return true; } std::vector mitk::OpenIGTLinkTrackingDevice::GetAllTools() { return this->m_AllTools; } mitk::OpenIGTLinkTrackingDevice::TrackingMessageType mitk::OpenIGTLinkTrackingDevice::GetMessageTypeFromString(const char* messageTypeString) { if (strcmp(messageTypeString, "TDATA") == 0) { return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::TDATA; } else if (strcmp(messageTypeString, "QTDATA") == 0) { return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::QTDATA; } else if (strcmp(messageTypeString, "TRANSFORM") == 0) { return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::TRANSFORM; } else { return mitk::OpenIGTLinkTrackingDevice::TrackingMessageType::UNKNOWN; } } diff --git a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTypeInformation.cpp b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTypeInformation.cpp index 428e1e043c..aacdeea343 100644 --- a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTypeInformation.cpp +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTypeInformation.cpp @@ -1,60 +1,60 @@ /*=================================================================== 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 "mitkOpenIGTLinkTypeInformation.h" #include "mitkOpenIGTLinkTrackingDevice.h" namespace mitk { std::string OpenIGTLinkTypeInformation::GetTrackingDeviceName() { return "Open IGT Link Connection"; } TrackingDeviceData OpenIGTLinkTypeInformation::GetDeviceDataOpenIGTLinkTrackingDeviceConnection(){ TrackingDeviceData data = { OpenIGTLinkTypeInformation::GetTrackingDeviceName(), "OpenIGTLink Tracking Device", "cube", "X" }; return data; } OpenIGTLinkTypeInformation::OpenIGTLinkTypeInformation() { m_DeviceName = OpenIGTLinkTypeInformation::GetTrackingDeviceName(); m_TrackingDeviceData.push_back(GetDeviceDataOpenIGTLinkTrackingDeviceConnection()); } OpenIGTLinkTypeInformation::~OpenIGTLinkTypeInformation() { } mitk::TrackingDeviceSource::Pointer OpenIGTLinkTypeInformation::CreateTrackingDeviceSource( mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools, std::string* errorMessage, std::vector* /*toolCorrespondencesInToolStorage*/) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::OpenIGTLinkTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); thisDevice->DiscoverTools(); - if (static_cast(thisDevice->GetToolCount()) != navigationTools->GetToolCount()) + if (thisDevice->GetToolCount() != navigationTools->GetToolCount()) { errorMessage->append("The number of tools in the connected device differs from the tool storage, cannot add tools."); return nullptr; } returnValue->SetTrackingDevice(thisDevice); return returnValue; } } diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusInterface.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusInterface.cpp index 7e4af215c8..b7b8f0cf85 100644 --- a/Modules/IGT/TrackingDevices/mitkPolhemusInterface.cpp +++ b/Modules/IGT/TrackingDevices/mitkPolhemusInterface.cpp @@ -1,207 +1,469 @@ /*=================================================================== 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 #define _USE_MATH_DEFINES #include #include BYTE MotionBuf[0x1FA400]; mitk::PolhemusInterface::PolhemusInterface() : m_continousTracking(false) { - m_pdiDev = new CPDIdev(); - + m_pdiDev = new CPDIdev(); + m_numberOfTools = 0; } mitk::PolhemusInterface::~PolhemusInterface() { - delete m_pdiDev; + delete m_pdiDev; } bool mitk::PolhemusInterface::InitializeDevice() { m_pdiDev->ResetTracker(); m_pdiDev->ResetSAlignment(-1); m_pdiDev->Trace(TRUE, 7); m_continousTracking = false; return true; } bool mitk::PolhemusInterface::SetupDevice() { m_pdiDev->SetPnoBuffer(MotionBuf, 0x1FA400); m_pdiDev->SetMetric(true); //use cm instead of inches m_pdiDev->StartPipeExport(); CPDImdat pdiMDat; pdiMDat.Empty(); pdiMDat.Append(PDI_MODATA_FRAMECOUNT); pdiMDat.Append(PDI_MODATA_POS); pdiMDat.Append(PDI_MODATA_ORI); m_pdiDev->SetSDataList(-1, pdiMDat); CPDIbiterr cBE; m_pdiDev->GetBITErrs(cBE); - if (!(cBE.IsClear())) {m_pdiDev->ClearBITErrs();} - - if (this->m_HemisphereTrackingEnabled) { m_pdiDev->SetSHemiTrack(-1); } - else { m_pdiDev->SetSHemisphere(-1, { (float)2.54,0,0 }); } + if (!(cBE.IsClear())) { m_pdiDev->ClearBITErrs(); } return true; } bool mitk::PolhemusInterface::StartTracking() { - LPCTSTR szWindowClass = _T("PDIconsoleWinClass"); - HINSTANCE hInst = GetModuleHandle(0); - HWND hwnd = CreateWindowEx( - WS_EX_NOACTIVATE,//WS_EX_STATICEDGE, // - szWindowClass, - _T("MyWindowName"), - WS_POPUP, - 0, 0, 1, 1, - HWND_MESSAGE, - 0, - hInst, - 0); - m_continousTracking = true; - return m_pdiDev->StartContPno(hwnd); + return m_pdiDev->StartContPno(0); } bool mitk::PolhemusInterface::StopTracking() { m_continousTracking = false; + m_pdiDev->StopContPno(); return true; } +bool mitk::PolhemusInterface::OpenConnection() +{ + bool returnValue; + //Initialize, and if it is not successful, return false. + if (!InitializeDevice()) + { + returnValue = false; + } + //Connect + else if (m_pdiDev->CnxReady()) + { + returnValue = true; + } + //If it is not successful, search for connections. + else + { + CPDIser pdiSer; + m_pdiDev->SetSerialIF(&pdiSer); + + ePiCommType eType = m_pdiDev->DiscoverCnx(); + switch (eType) + { + case PI_CNX_USB: + MITK_INFO << "USB Connection: " << m_pdiDev->GetLastResultStr(); + break; + case PI_CNX_SERIAL: + MITK_INFO << "Serial Connection: " << m_pdiDev->GetLastResultStr(); + break; + default: + MITK_INFO << "DiscoverCnx result: " << m_pdiDev->GetLastResultStr(); + break; + } + + //Setup device + if (!SetupDevice()) + { + returnValue = false; + } + else + { + returnValue = m_pdiDev->CnxReady(); + } + } + return returnValue; +} + bool mitk::PolhemusInterface::Connect() { - if (!InitializeDevice()) { return false; } + bool returnValue = OpenConnection(); - if (m_pdiDev->CnxReady()) { return true; } - CPDIser pdiSer; - m_pdiDev->SetSerialIF(&pdiSer); + if (!returnValue) + { + return returnValue; + } + + m_numberOfTools = this->GetNumberOfTools(); + + //Get the tracking data to find out which tools are available. + std::vector _trackingData = GetFrame(); + + //if we have more/less tools than before, reset all data. + //check with toolStorage changes is nto enough, 'cause a sensor could just have been unplugged. + if (m_ToolPorts.size() != _trackingData.size()) + { + m_ToolPorts.clear(); + m_Hemispheres.clear(); + m_HemisphereTracking.clear(); + } - ePiCommType eType = m_pdiDev->DiscoverCnx(); - switch (eType) + //if we have the same number of tools as before, check if they are still the same. + if (m_ToolPorts.size() == _trackingData.size()) { - case PI_CNX_USB: - MITK_INFO << "USB Connection: " << m_pdiDev->GetLastResultStr(); - break; - case PI_CNX_SERIAL: - MITK_INFO << "Serial Connection: " << m_pdiDev->GetLastResultStr(); - break; - default: - MITK_INFO << "DiscoverCnx result: " << m_pdiDev->GetLastResultStr(); - break; + for (int i = 0; i < _trackingData.size(); ++i) + { + //if they are not the same, clear hemispheres and toolNames and break. + if (m_ToolPorts[i] != _trackingData.at(i).id) + { + m_ToolPorts.clear(); + m_Hemispheres.clear(); + m_HemisphereTracking.clear(); + break; + } + } } - if (!SetupDevice()) { return false; } + //if we don't have old tool names or if the old ones don't match any more, assign them again. + if (m_ToolPorts.size() == 0) + { + for (int i = 0; i < _trackingData.size(); ++i) + { + m_ToolPorts.push_back(_trackingData.at(i).id); + } + //and reset the hemisphere parameters + m_Hemispheres.clear(); + m_HemisphereTracking.clear(); + mitk::Vector3D temp; + mitk::FillVector3D(temp, 1, 0, 0); + m_Hemispheres.assign(m_numberOfTools, temp); + m_HemisphereTracking.assign(m_numberOfTools, false); + } - return m_pdiDev->CnxReady(); + return returnValue; } bool mitk::PolhemusInterface::Disconnect() { + bool returnValue = true; + //If Tracking is running, stop tracking first if (m_continousTracking) { - m_continousTracking = false; - if (!m_pdiDev->Disconnect()) return false; + this->StopTracking(); } - return true; + + returnValue = m_pdiDev->Disconnect(); + MITK_INFO << "Disconnect: " << m_pdiDev->GetLastResultStr(); + return returnValue; +} + +std::vector mitk::PolhemusInterface::AutoDetectTools() +{ + OpenConnection(); + std::vector frame = GetSingleFrame(); + m_pdiDev->Disconnect(); + return frame; +} + +unsigned int mitk::PolhemusInterface::GetNumberOfTools() +{ + std::vector _trackingData = GetFrame(); + return _trackingData.size(); +} + +std::vector mitk::PolhemusInterface::GetFrame() +{ + if (m_continousTracking) + return this->GetLastFrame(); + else + return this->GetSingleFrame(); } std::vector mitk::PolhemusInterface::GetLastFrame() { PBYTE pBuf; DWORD dwSize; //read one frame - if (!m_pdiDev->LastPnoPtr(pBuf, dwSize)) {MITK_WARN << m_pdiDev->GetLastResultStr();} + if (!m_pdiDev->LastPnoPtr(pBuf, dwSize)) { MITK_WARN << m_pdiDev->GetLastResultStr(); } std::vector returnValue = ParsePolhemusRawData(pBuf, dwSize); - if (returnValue.empty()) { MITK_WARN << "Cannot parse data / no tools present"; } + if (returnValue.empty()) + { + MITK_WARN << "Cannot parse data / no tools present"; + } return returnValue; } -unsigned int mitk::PolhemusInterface::GetNumberOfTools() -{ - if (m_continousTracking) return GetLastFrame().size(); - else return GetSingleFrame().size(); -} - std::vector mitk::PolhemusInterface::GetSingleFrame() { if (m_continousTracking) { - MITK_WARN << "Cannot get tool count when continously tracking"; + MITK_WARN << "Cannot get a single frame when continuous tracking is on!"; return std::vector(); } PBYTE pBuf; DWORD dwSize; //read one frame if (!m_pdiDev->ReadSinglePnoBuf(pBuf, dwSize)) { MITK_WARN << m_pdiDev->GetLastResultStr(); return std::vector(); } return ParsePolhemusRawData(pBuf, dwSize); } std::vector mitk::PolhemusInterface::ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize) { std::vector returnValue; DWORD i = 0; - while (i eulerQuat(rollAngle, elevationAngle, azimuthAngle); currentTrackingData.rot = eulerQuat; returnValue.push_back(currentTrackingData); i += shSize; } return returnValue; } + +void mitk::PolhemusInterface::SetHemisphereTrackingEnabled(bool _HeisphereTrackingEnabeled, int _tool) +{ + //only if connection is ready! + if (!this->m_pdiDev->CnxReady()) + return; + + if (m_Hemispheres.empty()) + { + MITK_ERROR << "No Hemispheres. This should never happen when connected. Check your code!"; + } + + //HemisphereTracking is switched on by SetSHemiTrack(-1). "-1" means for all sensors. + //To switch heisphere tracking of, you need to set a hemisphere vector e.g. by calling SetSHemisphere(-1, { (float)1,0,0 }) + if (_HeisphereTrackingEnabeled) + { + m_pdiDev->SetSHemiTrack(_tool); + if (_tool != -1) + { + m_HemisphereTracking.at(GetToolIndex(_tool)) = true; + } + else + { + m_HemisphereTracking.assign(m_numberOfTools, true); + } + } + + //switch HemiTracking OFF + else + { + //Get Tool Position. ToDo, this should not be the tool tip but the sensor position. Any chance, to get that from Polhemus interface?! + std::vector _position = GetFrame(); + + for (int index : GetToolIterator(_tool)) + { + //Scalar product between mitk::point and mitk::vector + double _scalarProduct = _position.at(index).pos.GetVectorFromOrigin() * m_Hemispheres.at(index); + //if scalar product is negative, then the tool is in the opposite sphere then when we started to track. + //Hence, we have to set the inverted hemisphere. + //For default (1|0|0) this means, if x is negative, we have to set (-1|0|0). But we want to keep it generic if user sets different hemisphere... + if (_scalarProduct < 0) + { + m_Hemispheres.at(index) = -1. * m_Hemispheres.at(index); + } + else if (_scalarProduct == 0) + MITK_ERROR << "Something went wrong. Hemisphere or Position should not be zero."; + + SetHemisphere(m_ToolPorts[index], m_Hemispheres.at(index)); + } + } +} + +void mitk::PolhemusInterface::ToggleHemisphere(int _tool) +{ + //only if connection is ready! + if (!this->m_pdiDev->CnxReady()) + return; + + //toggle. + for (int index : GetToolIterator(_tool)) + { + if (m_HemisphereTracking.at(index)) + { + SetHemisphereTrackingEnabled(false, m_ToolPorts[index]); + this->SetHemisphere(m_ToolPorts[index], -1.*m_Hemispheres.at(index)); + SetHemisphereTrackingEnabled(true, m_ToolPorts[index]); + } + else + { + this->SetHemisphere(m_ToolPorts[index], -1.*m_Hemispheres.at(index)); + } + } +} + +void mitk::PolhemusInterface::AdjustHemisphere(int _tool) +{ + //only if connection is ready! + if (!this->m_pdiDev->CnxReady()) + return; + + mitk::Vector3D _hemisphere; + mitk::FillVector3D(_hemisphere, 1, 0, 0); + + for (int index : GetToolIterator(_tool)) + { + if (m_HemisphereTracking.at(index)) + { + SetHemisphereTrackingEnabled(false, m_ToolPorts[index]); + this->SetHemisphere(m_ToolPorts[index], _hemisphere); + SetHemisphereTrackingEnabled(true, m_ToolPorts[index]); + } + else + { + this->SetHemisphere(m_ToolPorts[index], _hemisphere); + } + } +} + +void mitk::PolhemusInterface::SetHemisphere(int _tool, mitk::Vector3D _hemisphere) +{ + //only if connection is ready! + if (!this->m_pdiDev->CnxReady()) + return; + + m_pdiDev->SetSHemisphere(_tool, { (float)_hemisphere[0], (float)_hemisphere[1], (float)_hemisphere[2] }); + + for (int index : GetToolIterator(_tool)) + { + if (_hemisphere.GetNorm() != 0) + { + m_HemisphereTracking.at(index) = false; + m_Hemispheres.at(index) = _hemisphere; + } + else + { + m_HemisphereTracking.at(index) = true; + //don't set the Hemisphere to (0|0|0), as we want to remember the old one. + } + } +} + +mitk::Vector3D mitk::PolhemusInterface::GetHemisphere(int _tool) +{ + if (_tool == -1) + { + MITK_WARN << "Can't return hemisphere for all tools. Returning Hemisphere of first tool " << m_ToolPorts[0]; + return m_Hemispheres.at(0); + } + return m_Hemispheres.at(GetToolIndex(_tool)); +} + +bool mitk::PolhemusInterface::GetHemisphereTrackingEnabled(int _tool) +{ + //if tool is -1, this means "All Tools". We return true if HemiTracking is enabled for all tools, and false if it is off for at least one tool. + if (_tool == -1) + { + bool _returnValue = true; + for (bool currentValue : m_HemisphereTracking) + _returnValue = _returnValue && currentValue; + return _returnValue; + } + else + return m_HemisphereTracking.at(GetToolIndex(_tool)); +} + +std::vector mitk::PolhemusInterface::GetToolPorts() +{ + return m_ToolPorts; +} + +int mitk::PolhemusInterface::GetToolIndex(int _tool) +{ + if (_tool == -1) + return -1; + else + return std::find(m_ToolPorts.begin(), m_ToolPorts.end(), _tool) - m_ToolPorts.begin(); +} + +std::vector mitk::PolhemusInterface::GetToolIterator(int _tool) +{ + std::vector _iterator; + if (_tool == -1) + { + for (int i = 0; i < static_cast(m_numberOfTools); ++i) + _iterator.push_back(i); + } + else + { + _iterator.push_back(GetToolIndex(_tool)); + } + return _iterator; +} + +void mitk::PolhemusInterface::PrintStatus() +{ + MITK_INFO << "Polhemus status: " << this->m_pdiDev->CnxReady(); +} \ No newline at end of file diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusInterface.h b/Modules/IGT/TrackingDevices/mitkPolhemusInterface.h index 28eea88760..4123d66038 100644 --- a/Modules/IGT/TrackingDevices/mitkPolhemusInterface.h +++ b/Modules/IGT/TrackingDevices/mitkPolhemusInterface.h @@ -1,117 +1,174 @@ /*=================================================================== 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 MITKPolhemusINTERFACE_H_HEADER_INCLUDED_ #define MITKPolhemusINTERFACE_H_HEADER_INCLUDED_ - #include #include #include #include "mitkCommon.h" #include #include #include #include #include #include class CPDIdev; namespace mitk { - /** Documentation: * \brief An object of this class represents the interface to Polhemus trackers. + * All variables with the name "tool" start with index 1, which is the station number of Polhemus. + * Make sure to call functions in this class with parameter "1" if you want to loop over all tools. + * If you need to access an array (e.g. m_Hemisphere), you need to use "_tool -1" and adapt your index for loops... * \ingroup IGT */ class MITKIGT_EXPORT PolhemusInterface : public itk::Object { public: - mitkClassMacroItkParent(PolhemusInterface,itk::Object); + mitkClassMacroItkParent(PolhemusInterface, itk::Object); itkFactorylessNewMacro(Self); itkCloneMacro(Self); struct trackingData { mitk::Point3D pos; mitk::Quaternion rot; BYTE id; }; /** * \brief Opens the connection to the device and makes it ready to track tools. * \return Returns true if there is a connection to the device and the device is ready to track tools, false if not. */ bool StartTracking(); /** * \brief Clears all resources. After this method have been called the system isn't ready to track any longer. * \return Returns true if the operation was succesful, false if not. */ bool StopTracking(); bool Connect(); bool Disconnect(); + /** @return Returns the number of tools. Returns 0 if no information is avialable.*/ + unsigned int GetNumberOfTools(); + + /** Enables/disables hemisphere tracking for all stations/tools. */ + void SetHemisphereTrackingEnabled(bool _HeisphereTrackingEnabeled, int _tool = -1); + + /** Toggles the current hemisphere. Parameter _tool describes, for which tool the hemisphere should change. Default -1 toggles all tools. + Index starts at "1" for the first tool (i.e. station number of Polhemus). Not 0! + */ + void ToggleHemisphere(int _tool = -1); + + /** Convenient method to print the status of the tracking device (true/false) if connection is established. For debugging...*/ + void PrintStatus(); + + /** Sets the Hemisphere of tool _tool to the vector _hemisphere. "-1" sets all tools. + Index starts at "1" for the first tool (i.e. station number of Polhemus). Not 0! + */ + void SetHemisphere(int _tool, mitk::Vector3D _hemisphere); + + /** Get the Hemisphere for _tool as mitk vector. -1 ("all tools") returns hemisphere of first tool. + Index starts at "1" for the first tool (i.e. station number of Polhemus). Not 0! + */ + mitk::Vector3D GetHemisphere(int _tool); + + /** Get the ports on which tools are connected. Returns empty vector if device is not connected! + */ + std::vector GetToolPorts(); + + /** Is Hemisphere Tracking Enabled for this tool? + * if tool is -1, this means "All Tools". We return true if HemiTracking is enabled for all tools, and false if it is off for at least one tool.*/ + bool GetHemisphereTrackingEnabled(int _tool); + + /** Adjust the Hemisphere for this tool. User needs to make sure, that the tool is located in hemisphere (1|0|0) when calling this function. + In contrast to SetHemisphere(1,0,0), this method restores the original HemisphereTracking settings at the end. */ + void AdjustHemisphere(int _tool); + /** @return Returns a single frame. Only works if the tracking device is not in continous tracking mode. Returns an empty vector in case of an error.*/ std::vector GetSingleFrame(); + /** @return Returns a single frame with all tools, which could be auto detected.*/ + std::vector AutoDetectTools(); + /** @return Returns the last frame when the tracking device is in continous tracking mode. Returns an empty vector in case of an error.*/ std::vector GetLastFrame(); - /** @return Returns the number of tools. Returns 0 if no information is avialable.*/ - unsigned int GetNumberOfTools(); - - /** Enables/disables hemisphere tracking for all sensors. */ - itkSetMacro(HemisphereTrackingEnabled, bool); - protected: /** * \brief standard constructor */ PolhemusInterface(); /** * \brief standard destructor */ ~PolhemusInterface(); - /** Polhemus liberty/patriot tracker object*/ + /** Polhemus liberty/patriot tracker object*/ CPDIdev* m_pdiDev; - - /** Parses polhemus raw data to a collection of tracking data of single tools. */ - std::vector ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize); - - unsigned int m_numberOfTools; - bool m_continousTracking; + /** Parses polhemus raw data to a collection of tracking data of single tools. */ + std::vector ParsePolhemusRawData(PBYTE pBuf, DWORD dwSize); bool InitializeDevice(); bool SetupDevice(); - bool m_HemisphereTrackingEnabled; + //returns the index in the arrays of tool _tool. Eg. sensor 3 (_tool = 3) is the second tool --> index 1 in m_Hemispheres etc. + int GetToolIndex(int _tool); + + /** @brief Convenient method to get a frame from the tracking device. + * @return Returns a single OR the last frame depending on m_continuousTracking. + * @warning Don't use this function if you use different threads. You need to make sure, that you are still in the right mode! */ + std::vector GetFrame(); + private: + //returns vector with tool index as only element if tool != -1, else returns vector from 0 to numberOfTools + std::vector GetToolIterator(int _tool); + //helper method to open connection + bool OpenConnection(); + + + private: + //Stores the hemispheres for all sensors. Default is (1|0|0). + std::vector m_Hemispheres; + + //Stores, if hemisphereTracking is on for this Sensor. + std::vector m_HemisphereTracking; + + //This vector stores the order of tools, which are available. + //E.g. only Sensor 1 and 3 are attached, then this vector maps the first tool (0) to Polhemus identifier 1 and the second tool (1) to Polhemus 3. + std::vector m_ToolPorts; + + unsigned int m_numberOfTools; + + bool m_continousTracking; }; }//mitk #endif diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTool.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusTool.cpp index dfa34e5769..5131f608ae 100644 --- a/Modules/IGT/TrackingDevices/mitkPolhemusTool.cpp +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTool.cpp @@ -1,25 +1,35 @@ /*=================================================================== 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 "mitkPolhemusTool.h" mitk::PolhemusTool::PolhemusTool() :InternalTrackingTool() { } mitk::PolhemusTool::~PolhemusTool(void) { } + +void mitk::PolhemusTool::SetToolPort(int _ToolPort) +{ + this->m_ToolPort = _ToolPort; +} + +int mitk::PolhemusTool::GetToolPort() +{ + return this->m_ToolPort; +} diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTool.h b/Modules/IGT/TrackingDevices/mitkPolhemusTool.h index 0d16bebb10..1f23d2ece5 100644 --- a/Modules/IGT/TrackingDevices/mitkPolhemusTool.h +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTool.h @@ -1,46 +1,60 @@ /*=================================================================== 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 MITKPolhemusTOOL_H_HEADER_INCLUDED_ #define MITKPolhemusTOOL_H_HEADER_INCLUDED_ #include #include #include namespace mitk { class PolhemusTrackingDevice; /** Documentation: * \brief An object of this class represents a tool of a Polhemus tracking device. * A tool has to be added to a tracking device which will then * continuously update the tool coordinates. * \ingroup IGT */ class MITKIGT_EXPORT PolhemusTool : public InternalTrackingTool { public: friend class PolhemusTrackingDevice; mitkClassMacro(PolhemusTool, InternalTrackingTool); + /** + * \brief Sets the port of the tool. (e.g. 1 for port "SENS 1" etc.) + */ + virtual void SetToolPort(int _ToolPort); + + /** + * \brief Sets the port of the tool. (e.g. 1 for port "SENS 1" etc.) + */ + virtual int GetToolPort(); + protected: itkFactorylessNewMacro(Self) itkCloneMacro(Self) PolhemusTool(); virtual ~PolhemusTool(); + + //This is the port, on which the tool is connected. It is identical with the "ToolIdentifier" set on NavigationDataTools. + //If tool is connected on port "SENS 2", the m_ToolPort is 2 etc. + int m_ToolPort; }; }//mitk #endif // MITKPolhemusTOOL_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp index a4e7bed526..4efd7f2596 100644 --- a/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp @@ -1,70 +1,70 @@ /*=================================================================== 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 "mitkPolhemusTrackerTypeInformation.h" #include "mitkPolhemusTrackingDevice.h" namespace mitk { std::string PolhemusTrackerTypeInformation::GetTrackingDeviceName() { return "Polhemus tracker"; } TrackingDeviceData PolhemusTrackerTypeInformation::GetDeviceDataPolhemusTrackerLiberty() { TrackingDeviceData data = { PolhemusTrackerTypeInformation::GetTrackingDeviceName(), "Polhemus Liberty Tracker", "cube", "X" }; return data; } PolhemusTrackerTypeInformation::PolhemusTrackerTypeInformation() { m_DeviceName = PolhemusTrackerTypeInformation::GetTrackingDeviceName(); m_TrackingDeviceData.push_back(GetDeviceDataPolhemusTrackerLiberty()); } PolhemusTrackerTypeInformation::~PolhemusTrackerTypeInformation() { } mitk::TrackingDeviceSource::Pointer PolhemusTrackerTypeInformation::CreateTrackingDeviceSource( mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools, std::string* errorMessage, std::vector* toolCorrespondencesInToolStorage) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::PolhemusTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); *toolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device for (int i = 0; i < navigationTools->GetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = navigationTools->GetTool(i); toolCorrespondencesInToolStorage->push_back(i); - bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str()); + bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str(), std::stoi(thisNavigationTool->GetIdentifier())); if (!toolAddSuccess) { //todo error handling errorMessage->append("Can't add tool, is the toolfile valid?"); return NULL; } thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(), thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } } diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp index 98bd67f4f7..7121391bfe 100644 --- a/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.cpp @@ -1,250 +1,317 @@ /*=================================================================== 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 "mitkPolhemusTrackingDevice.h" #include "mitkPolhemusTool.h" #include "mitkIGTConfig.h" #include "mitkIGTTimeStamp.h" #include "mitkIGTHardwareException.h" #include #include #include #include "mitkPolhemusTrackerTypeInformation.h" -#include typedef itk::MutexLockHolder MutexLockHolder; - -mitk::PolhemusTrackingDevice::PolhemusTrackingDevice(): mitk::TrackingDevice() +mitk::PolhemusTrackingDevice::PolhemusTrackingDevice() : mitk::TrackingDevice() { //set the type of this tracking device this->m_Data = mitk::PolhemusTrackerTypeInformation::GetDeviceDataPolhemusTrackerLiberty(); this->m_MultiThreader = itk::MultiThreader::New(); m_ThreadID = 0; m_Device = mitk::PolhemusInterface::New(); } mitk::PolhemusTrackingDevice::~PolhemusTrackingDevice() { } bool mitk::PolhemusTrackingDevice::IsDeviceInstalled() { return true; } -mitk::TrackingTool* mitk::PolhemusTrackingDevice::AddTool( const char* toolName) +mitk::TrackingTool* mitk::PolhemusTrackingDevice::AddTool(const char* toolName, int toolPort) { + //Only add tool if port isn't already used. + for (auto _tool : m_AllTools) + { + if (_tool->GetToolPort() == toolPort) + { + MITK_DEBUG << "There is already a tool connected to this port. Returning existing tool"; + return _tool; + } + } + mitk::PolhemusTool::Pointer t = mitk::PolhemusTool::New(); t->SetToolName(toolName); + t->SetToolPort(toolPort); if (this->InternalAddTool(t) == false) return nullptr; return t.GetPointer(); } bool mitk::PolhemusTrackingDevice::InternalAddTool(PolhemusTool::Pointer tool) { m_AllTools.push_back(tool); return true; } bool mitk::PolhemusTrackingDevice::StartTracking() { bool success = m_Device->StartTracking(); if (success) { mitk::IGTTimeStamp::GetInstance()->Start(this); this->SetState(Tracking); + this->m_StopTrackingMutex->Lock(); + this->m_StopTracking = false; + this->m_StopTrackingMutex->Unlock(); m_ThreadID = m_MultiThreader->SpawnThread(this->ThreadStartTracking, this); // start a new thread that executes the TrackTools() method return true; } else { this->SetState(Ready); mitkThrowException(mitk::IGTHardwareException) << "Error while trying to start the device!"; } return success; } bool mitk::PolhemusTrackingDevice::StopTracking() { + m_Device->StopTracking(); return Superclass::StopTracking(); } - unsigned int mitk::PolhemusTrackingDevice::GetToolCount() const { return (unsigned int)this->m_AllTools.size(); } - mitk::TrackingTool* mitk::PolhemusTrackingDevice::GetTool(unsigned int toolNumber) const { - if ( toolNumber >= this->GetToolCount()) + if (toolNumber >= this->GetToolCount()) return nullptr; else return this->m_AllTools[toolNumber]; } - bool mitk::PolhemusTrackingDevice::OpenConnection() { //reset everything - if (m_Device.IsNull()) {m_Device = mitk::PolhemusInterface::New();} - m_Device->SetHemisphereTrackingEnabled(m_HemisphereTrackingEnabled); - m_Device->Connect(); + if (m_Device.IsNull()) { m_Device = mitk::PolhemusInterface::New(); } + if (!m_Device->Connect()) //Connect the device, if it fails, throw an error. + { + MITK_ERROR << "Cannot connect Polhemus device!"; + CloseConnection(); + return false; + } + + //Ready must be set here, 'cause if tools don't match we need to be able to disconnect. this->SetState(Ready); + + //check if connected ports of Polhemus matches the tools in the toolStorage. + std::vector toolPorts = m_Device->GetToolPorts(); + + //first, check size. + if (this->GetToolCount() != toolPorts.size()) + { + MITK_ERROR << "Cannot connect device, number of tools in toolstorage doesn't match the number of tools connected to Polhemus device!"; + CloseConnection(); + return false; + } + + //second, check if toolStorage identifier is included in this port. + for (auto _tool : m_AllTools) + { + if (std::find(toolPorts.begin(), toolPorts.end(), _tool->GetToolPort()) == toolPorts.end()) + { + MITK_ERROR << "Cannot connect device, tool " << _tool->GetToolPort() << " is not connected to its port."; + CloseConnection(); + return false; + } + else + { + //erase this port to avoid that two tools want to connect to the same port. + toolPorts.erase(std::find(toolPorts.begin(), toolPorts.end(), _tool->GetToolPort())); + } + } + + m_Device->SetHemisphereTrackingEnabled(m_HemisphereTrackingEnabled); + return true; } bool mitk::PolhemusTrackingDevice::CloseConnection() { bool returnValue = true; if (this->GetState() == Setup) return true; returnValue = m_Device->Disconnect(); this->SetState(Setup); return returnValue; } - mitk::PolhemusInterface* mitk::PolhemusTrackingDevice::GetDevice() { return m_Device; } - std::vector mitk::PolhemusTrackingDevice::GetAllTools() { return this->m_AllTools; } - void mitk::PolhemusTrackingDevice::TrackTools() { try { /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */ MutexLockHolder trackingFinishedLockHolder(*m_TrackingFinishedMutex); // keep lock until end of scope bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here this->m_StopTrackingMutex->Lock(); // update the local copy of m_StopTracking localStopTracking = this->m_StopTracking; this->m_StopTrackingMutex->Unlock(); Sleep(100);//Wait a bit until the tracker is ready... while ((this->GetState() == Tracking) && (localStopTracking == false)) { std::vector lastData = this->GetDevice()->GetLastFrame(); if (lastData.size() != m_AllTools.size()) { - MITK_WARN << "Tool count is corrupt. Aborting!"; + MITK_WARN << "Tool count is corrupt. Hardware gives " << lastData.size() << " tools, MITK expects " << m_AllTools.size() << " tools. Aborting!"; } else { std::vector allTools = this->GetAllTools(); for (int i = 0; i < allTools.size(); i++) { mitk::PolhemusTool::Pointer currentTool = allTools.at(i); currentTool->SetDataValid(true); currentTool->SetPosition(lastData.at(i).pos); currentTool->SetOrientation(lastData.at(i).rot); currentTool->SetIGTTimeStamp(mitk::IGTTimeStamp::GetInstance()->GetElapsed()); } } /* Update the local copy of m_StopTracking */ this->m_StopTrackingMutex->Lock(); localStopTracking = m_StopTracking; this->m_StopTrackingMutex->Unlock(); } } - catch(...) + catch (...) { this->StopTracking(); mitkThrowException(mitk::IGTHardwareException) << "Error while trying to track tools. Thread stopped."; } } ITK_THREAD_RETURN_TYPE mitk::PolhemusTrackingDevice::ThreadStartTracking(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } PolhemusTrackingDevice *trackingDevice = (PolhemusTrackingDevice*)pInfo->UserData; if (trackingDevice != nullptr) trackingDevice->TrackTools(); return ITK_THREAD_RETURN_VALUE; } bool mitk::PolhemusTrackingDevice::AutoDetectToolsAvailable() { return true; } mitk::NavigationToolStorage::Pointer mitk::PolhemusTrackingDevice::AutoDetectTools() { - this->OpenConnection(); - std::vector singeFrameData = this->m_Device->GetSingleFrame(); + std::vector singeFrameData = this->m_Device->AutoDetectTools(); MITK_INFO << "Found " << singeFrameData.size() << " tools."; - this->CloseConnection(); mitk::NavigationToolStorage::Pointer returnValue = mitk::NavigationToolStorage::New(); for each (mitk::PolhemusInterface::trackingData t in singeFrameData) { + mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); std::stringstream name; name << "Sensor-" << ((int)t.id); - newNode->SetName(name.str()); - - mitk::Surface::Pointer myCone = mitk::Surface::New(); - vtkConeSource *vtkData = vtkConeSource::New(); - vtkData->SetAngle(5.0); - vtkData->SetResolution(50); - vtkData->SetHeight(6.0f); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - myCone->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(myCone); - - mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); - newTool->SetDataNode(newNode); + newTool->GetDataNode()->SetName(name.str()); + //The identifier defines, which plug is used (e.g. "Sens 2" --> 2). std::stringstream identifier; - identifier << "AutoDetectedTool-" << ((int)t.id); + identifier << ((int)t.id); newTool->SetIdentifier(identifier.str()); newTool->SetTrackingDeviceType(mitk::PolhemusTrackerTypeInformation::GetDeviceDataPolhemusTrackerLiberty().Line); returnValue->AddTool(newTool); } return returnValue; +} + +void mitk::PolhemusTrackingDevice::SetHemisphereTrackingEnabled(bool _HemisphereTrackingEnabled) +{ + //We need to remember if HemisphereTracking is switch on for this reason: + /* m_Device->SetHemi works only if the device is connected. However, GUI can also change if it is not connected. + In this case, we remember it in the m_HemisphereTrackingEnabled variable. And when connecting, we know, which + status is wanted from the user by GUI. + */ + m_HemisphereTrackingEnabled = _HemisphereTrackingEnabled; + this->m_Device->SetHemisphereTrackingEnabled(_HemisphereTrackingEnabled); +} +void mitk::PolhemusTrackingDevice::ToggleHemisphere(int _tool) +{ + this->m_Device->ToggleHemisphere(_tool); } + +void mitk::PolhemusTrackingDevice::SetHemisphere(int _tool, mitk::Vector3D _hemisphere) +{ + //If you set a hemisphere vector which is unequal (0|0|0), this means, that there is no hemisphere tracking any more + //disable the option, so that it can be reactivated... Also if it is just a single tool. + if (_hemisphere.GetNorm() != 0) + m_HemisphereTrackingEnabled = false; + + this->m_Device->SetHemisphere(_tool, _hemisphere); +} + +mitk::Vector3D mitk::PolhemusTrackingDevice::GetHemisphere(int _tool) +{ + return this->m_Device->GetHemisphere(_tool); +} + +bool mitk::PolhemusTrackingDevice::GetHemisphereTrackingEnabled(int _tool) +{ + return this->m_Device->GetHemisphereTrackingEnabled(_tool); +} + +void mitk::PolhemusTrackingDevice::AdjustHemisphere(int _tool) +{ + return this->m_Device->AdjustHemisphere(_tool); +} \ No newline at end of file diff --git a/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.h b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.h index 0d02827f2f..1d50ec8f75 100644 --- a/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.h +++ b/Modules/IGT/TrackingDevices/mitkPolhemusTrackingDevice.h @@ -1,145 +1,165 @@ /*=================================================================== 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 MITKPolhemusTRACKINGDEVICE_H_HEADER_INCLUDED_ #define MITKPolhemusTRACKINGDEVICE_H_HEADER_INCLUDED_ #include #include #include #include #include namespace mitk { /** Documentation: * \brief An object of this class represents Polhemus tracking device. You can add tools to this * device, then open the connection and start tracking. The tracking device will then * continuously update the tool coordinates. + * The tools which are used by Polhemus need to be connected to the correct port. + * The port of the tool is stored as m_ToolPort in PolhemusTool AND as identifier in the NavigationTool (ToolStorage). * \ingroup IGT */ class MITKIGT_EXPORT PolhemusTrackingDevice : public TrackingDevice { public: mitkClassMacro(PolhemusTrackingDevice, TrackingDevice); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** * \brief Starts the tracking. * \return Returns true if the tracking is started. Throws an exception if an error occures. * @throw mitk::IGTHardwareException Throws an exception if there is an error during start tracking. */ virtual bool StartTracking() override; /** * \brief Stops the tracking. * \return Returns true if the tracking is stopped. */ virtual bool StopTracking() override; /** * \brief Opens the connection to the device. This have to be done before the tracking is started. * @throw mitk::IGTHardwareException Throws an exception if there is an error during open connection. */ virtual bool OpenConnection() override; /** * \brief Closes the connection and clears all resources. */ virtual bool CloseConnection() override; /** * \return Returns the number of tools which have been added to the device. */ virtual unsigned int GetToolCount() const override; /** * \param toolNumber The number of the tool which should be given back. * \return Returns the tool which the number "toolNumber". Returns NULL, if there is * no tool with this number. */ TrackingTool* GetTool(unsigned int toolNumber) const override; /** * \brief Create a new Polhemus tool with toolName and add it to the list of tools * * This method will create a new PolhemusTool object, * set the tool name toolName and then add it to the list of tools. * It returns a pointer of type mitk::TrackingTool to the tool * that can be used to read tracking data from it. * This is the only way to add tools to PolhemusTrackingDevice. * * \warning adding tools is not possible in tracking mode, only in setup and ready. */ - mitk::TrackingTool* AddTool(const char* toolName); + mitk::TrackingTool* AddTool(const char* toolName, int toolPort); + + bool IsDeviceInstalled(); /** @return Returns true if this device can autodetects its tools. */ virtual bool AutoDetectToolsAvailable(); /** Autodetects tools from this device and returns them as a navigation tool storage. * @return Returns the detected tools. Returns an empty storage if no tools are present * or if detection is not possible */ virtual mitk::NavigationToolStorage::Pointer AutoDetectTools(); /** Enables/disables hemisphere tracking for all sensors. */ - itkSetMacro(HemisphereTrackingEnabled, bool); + void SetHemisphereTrackingEnabled(bool _HemisphereTrackingEnabled); + + /** Is Hemisphere Tracking Enabled for this tool? */ + bool GetHemisphereTrackingEnabled(int _tool); + + /** Toggles the current hemisphere. Parameter _tool describes, for which tool the hemisphere should change. Default -1 toggles all tools.*/ + void ToggleHemisphere(int _tool = -1); + + /** Sets the Hemisphere of tool _tool to the vector _hemisphere */ + void SetHemisphere(int _tool, mitk::Vector3D _hemisphere); + + /** Get the Hemisphere for _tool as mitk vector */ + mitk::Vector3D GetHemisphere(int _tool); + + /** Adjust the Hemisphere for this tool. User needs to make sure, that the tool is located in hemisphere (1|0|0) when calling this function. + In contrast to SetHemisphere(1,0,0), this method restores the original HemisphereTracking settings at the end. */ + void AdjustHemisphere(int _tool); protected: PolhemusTrackingDevice(); ~PolhemusTrackingDevice(); /** * \brief Adds a tool to the tracking device. * * \param tool The tool which will be added. * \return Returns true if the tool has been added, false otherwise. */ bool InternalAddTool(PolhemusTool::Pointer tool); /** * \brief This method tracks tools as long as the variable m_Mode is set to "Tracking". * Tracking tools means grabbing frames from the camera an updating the tools. * @throw mitk::IGTHardwareException Throws an exception if there is an error during tracking of tools. */ void TrackTools(); /** * \return Returns all tools of the tracking device. */ std::vector GetAllTools(); /** * \return Gives back the device which is represented by an object of the class PolhemusInterface. */ PolhemusInterface* GetDevice(); static ITK_THREAD_RETURN_TYPE ThreadStartTracking(void* data); std::vector m_AllTools; ///< vector holding all tools PolhemusInterface::Pointer m_Device; ///< represents the interface to the tracking hardware itk::MultiThreader::Pointer m_MultiThreader; int m_ThreadID; bool m_HemisphereTrackingEnabled; }; }//mitk #endif /* MITKPolhemusTRACKINGDEVICE_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/TrackingDevices/mitkTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkTrackingDevice.cpp index 8393c21d4f..f3585d0ee1 100644 --- a/Modules/IGT/TrackingDevices/mitkTrackingDevice.cpp +++ b/Modules/IGT/TrackingDevices/mitkTrackingDevice.cpp @@ -1,148 +1,157 @@ /*=================================================================== 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 "mitkTrackingDevice.h" #include "mitkIGTTimeStamp.h" #include "mitkTrackingTool.h" #include #include #include #include "mitkUnspecifiedTrackingTypeInformation.h" #include "mitkTrackingDeviceTypeCollection.h" typedef itk::MutexLockHolder MutexLockHolder; mitk::TrackingDevice::TrackingDevice() : m_State(mitk::TrackingDevice::Setup), m_Data(mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified()), m_StopTracking(false), m_RotationMode(mitk::TrackingDevice::RotationStandard) { m_StopTrackingMutex = itk::FastMutexLock::New(); m_StateMutex = itk::FastMutexLock::New(); m_TrackingFinishedMutex = itk::FastMutexLock::New(); } mitk::TrackingDevice::~TrackingDevice() { } bool mitk::TrackingDevice::IsDeviceInstalled() { return true; //this is the default for all tracking device //If a device needs installation please reimplement //this method in the subclass. } bool mitk::TrackingDevice::AutoDetectToolsAvailable() { return false; } +bool mitk::TrackingDevice::AddSingleToolIsAvailable() +{ + return true; +} + mitk::NavigationToolStorage::Pointer mitk::TrackingDevice::AutoDetectTools() { return mitk::NavigationToolStorage::New(); } mitk::TrackingDevice::TrackingDeviceState mitk::TrackingDevice::GetState() const { MutexLockHolder lock(*m_StateMutex); return m_State; } void mitk::TrackingDevice::SetState( TrackingDeviceState state ) { itkDebugMacro("setting m_State to " << state); MutexLockHolder lock(*m_StateMutex); // lock and unlock the mutex if (m_State == state) { return; } m_State = state; this->Modified(); } void mitk::TrackingDevice::SetRotationMode(RotationMode) { MITK_WARN << "Rotation mode switching is not implemented for this device. Leaving it at mitk::TrackingDevice::RotationStandard"; } mitk::TrackingDeviceType mitk::TrackingDevice::GetType() const{ return m_Data.Line; } void mitk::TrackingDevice::SetType(mitk::TrackingDeviceType deviceType){ us::ModuleContext* context = us::GetModuleContext(); std::vector > refs = context->GetServiceReferences(); if (refs.empty()) { MITK_ERROR << "No tracking device service found!"; } mitk::TrackingDeviceTypeCollection* deviceTypeCollection = context->GetService(refs.front()); m_Data = deviceTypeCollection->GetFirstCompatibleDeviceDataForLine(deviceType); } mitk::TrackingDeviceData mitk::TrackingDevice::GetData() const{ return m_Data; } void mitk::TrackingDevice::SetData(mitk::TrackingDeviceData data){ m_Data = data; } bool mitk::TrackingDevice::StopTracking() { if (this->GetState() == Tracking) // Only if the object is in the correct state { m_StopTrackingMutex->Lock(); // m_StopTracking is used by two threads, so we have to ensure correct thread handling m_StopTracking = true; m_StopTrackingMutex->Unlock(); //we have to wait here that the other thread recognizes the STOP-command and executes it m_TrackingFinishedMutex->Lock(); mitk::IGTTimeStamp::GetInstance()->Stop(this); // notify realtime clock // StopTracking was called, thus the mode should be changed back // to Ready now that the tracking loop has ended. this->SetState(Ready); m_TrackingFinishedMutex->Unlock(); } return true; } mitk::TrackingTool* mitk::TrackingDevice::GetToolByName( std::string name ) const { unsigned int toolCount = this->GetToolCount(); for (unsigned int i = 0; i < toolCount; ++i) if (name == this->GetTool(i)->GetToolName()) return this->GetTool(i); return nullptr; } +std::string mitk::TrackingDevice::GetTrackingDeviceName() +{ + return this->GetData().Line; +} diff --git a/Modules/IGT/TrackingDevices/mitkTrackingDevice.h b/Modules/IGT/TrackingDevices/mitkTrackingDevice.h index 1cadb52701..c731ee7419 100644 --- a/Modules/IGT/TrackingDevices/mitkTrackingDevice.h +++ b/Modules/IGT/TrackingDevices/mitkTrackingDevice.h @@ -1,199 +1,209 @@ /*=================================================================== 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 MITKTRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 #define MITKTRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 #include #include "itkObject.h" #include "mitkCommon.h" #include "mitkTrackingTypes.h" #include "itkFastMutexLock.h" #include "mitkNavigationToolStorage.h" namespace mitk { class TrackingTool; // interface for a tool that can be tracked by the TrackingDevice /**Documentation * \brief Interface for all Tracking Devices * * Defines the methods that are common for all tracking devices. * * \ingroup IGT */ class MITKIGT_EXPORT TrackingDevice : public itk::Object { public: mitkClassMacroItkParent(TrackingDevice, itk::Object); /** Defines the rotation modes of this tracking device which results in different representations * of quaternions. * * - Standard: normal representation, rawdata from the device is not changed (DEFAULT) * * - Transposed: the rotation is stored transposed, which is (by mistake!) expected by some older MITK classes due * to an ambigious method naming in VNL. * * CAUTION: The rotation mode can only be changed for backward compatibility of old WRONG code. * PLEASE DO NOT CHANGE THE ROTATION MODE UNLESS YOU ARE KNOWING EXACTLY WHAT YOU ARE DOING! * * use SetRotationMode to change the mode. */ enum RotationMode {RotationStandard, RotationTransposed}; enum TrackingDeviceState {Setup, Ready, Tracking}; ///< Type for state variable. The trackingdevice is always in one of these states /** * \brief Opens a connection to the device * * This may only be called if there is currently no connection to the device. * If OpenConnection() is successful, the object will change from Setup state to Ready state */ virtual bool OpenConnection() = 0; /** * \brief Closes the connection to the device * * This may only be called if there is currently a connection to the device, but tracking is * not running (e.g. object is in Ready state) */ virtual bool CloseConnection() = 0; ///< Closes the connection with the device /** * \brief start retrieving tracking data from the device. * * This may only be called after the connection to the device has been established * with a call to OpenConnection() (E.g. object is in Ready mode). This will change the * object state from Ready to Tracking */ virtual bool StartTracking() = 0; /** * \brief stop retrieving tracking data from the device. * stop retrieving tracking data from the device. * This may only be called after StartTracking was called * (e.g. the object is in Tracking mode). * This will change the object state from Tracking to Ready. */ virtual bool StopTracking(); /** * \brief Return tool with index toolNumber * * tools are numbered from 0 to GetToolCount() - 1. */ virtual TrackingTool* GetTool(unsigned int toolNumber) const = 0; /** * \brief Returns the tool with the given tool name * * Note: subclasses can and should implement optimized versions of this method * \return the given tool or nullptr if no tool with that name exists */ virtual mitk::TrackingTool* GetToolByName(std::string name) const; /** * \brief Returns number of tracking tools */ virtual unsigned int GetToolCount() const = 0; /** Sets the rotation mode of this class. See documentation of enum RotationMode for details * on the different modes. This method has to be implemented in a deriving class to become * functional / if different rotation modes should be supported. * CAUTION: The rotation mode can only be changed for backward compatibility of old WRONG code. * PLEASE DO NOT CHANGE THE ROTATION MODE UNLESS YOU ARE KNOWING EXACTLY WHAT YOU ARE DOING! */ virtual void SetRotationMode(RotationMode r); /** @return Returns the rotation mode of this class. See documentation of enum * RotationMode for details on the different modes. */ itkGetConstMacro(RotationMode,RotationMode); /** * \brief return current object state (Setup, Ready or Tracking) */ TrackingDeviceState GetState() const; /** - * \brief Deprecated! Use the more specific getDeviceData instead. return device type identifier + * \brief Deprecated! Use the more specific getData or GetTrackingDeviceName instead. return device type identifier */ TrackingDeviceType GetType() const; /** * \brief Deprecated! Use the more specific setDeviceData instead. set device type */ void SetType(TrackingDeviceType type); + /** + * \brief Convenient Method to get the Name of the Tracking Device. + * This is identical with GetData().Line and can be used to compare with TrackingDeviceTypeInformation::GetTrackingDeviceName() + * to check if you have a specific device. + */ + std::string GetTrackingDeviceName(); + /** * \brief return device data */ TrackingDeviceData GetData() const; /** * \brief set device type */ void SetData(TrackingDeviceData data); /** * @return Returns true if the device is installed on this system an can be used. * Installed means activated in MITK, in some cases this means the MITK * installation / build has to know the installation path of the device * libraries on this system. This path is usually given as cmake variable * during the build configuration in devellopers mode. If the device should * be available for end users with an installer the libraries can be included * into the installer or the installer has to be adapted such that it asks * for the path. * Returns fals if the device is not installed. It cannot be used on this build * in this case. * * Note that some tracking systems communicate via a standard interface (e.g., serial * port) and don't need any library or installation. These devices are always "installed". */ virtual bool IsDeviceInstalled(); /** @return Returns true if this device can autodetects its tools. */ virtual bool AutoDetectToolsAvailable(); + /** @return Returns true if it is possible to add a single tool. Default return is true.*/ + virtual bool AddSingleToolIsAvailable(); + /** Autodetects tools from this device and returns them as a navigation tool storage. * @return Returns the detected tools. Returns an empty storage if no tools are present * or if detection is not possible */ virtual mitk::NavigationToolStorage::Pointer AutoDetectTools(); private: TrackingDeviceState m_State; ///< current object state (Setup, Ready or Tracking) protected: /** * \brief change object state */ void SetState(TrackingDeviceState state); TrackingDevice(); virtual ~TrackingDevice(); TrackingDeviceData m_Data; ///< current device Data bool m_StopTracking; ///< signal stop to tracking thread itk::FastMutexLock::Pointer m_StopTrackingMutex; ///< mutex to control access to m_StopTracking itk::FastMutexLock::Pointer m_TrackingFinishedMutex; ///< mutex to manage control flow of StopTracking() itk::FastMutexLock::Pointer m_StateMutex; ///< mutex to control access to m_State RotationMode m_RotationMode; ///< defines the rotation mode Standard or Transposed, Standard is default }; } // namespace mitk #endif /* MITKTRACKINGDEVICE_H_HEADER_INCLUDED_C1C2FCD2 */ diff --git a/Modules/IGT/TrackingDevices/mitkVirtualTrackerTypeInformation.cpp b/Modules/IGT/TrackingDevices/mitkVirtualTrackerTypeInformation.cpp index 2bcc5fa600..eae7f126b7 100644 --- a/Modules/IGT/TrackingDevices/mitkVirtualTrackerTypeInformation.cpp +++ b/Modules/IGT/TrackingDevices/mitkVirtualTrackerTypeInformation.cpp @@ -1,70 +1,70 @@ /*=================================================================== 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 "mitkVirtualTrackerTypeInformation.h" #include "mitkVirtualTrackingDevice.h" namespace mitk { std::string VirtualTrackerTypeInformation::GetTrackingDeviceName() { return "Virtual Tracker"; } TrackingDeviceData VirtualTrackerTypeInformation::GetDeviceDataVirtualTracker() { TrackingDeviceData data = { VirtualTrackerTypeInformation::GetTrackingDeviceName(), "Virtual Tracker", "cube", "X" }; return data; } VirtualTrackerTypeInformation::VirtualTrackerTypeInformation() { m_DeviceName = VirtualTrackerTypeInformation::GetTrackingDeviceName(); m_TrackingDeviceData.push_back(GetDeviceDataVirtualTracker()); } VirtualTrackerTypeInformation::~VirtualTrackerTypeInformation() { } mitk::TrackingDeviceSource::Pointer VirtualTrackerTypeInformation::CreateTrackingDeviceSource( mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools, std::string* errorMessage, std::vector* toolCorrespondencesInToolStorage) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::VirtualTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); *toolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device - for (int i = 0; i < navigationTools->GetToolCount(); i++) + for (unsigned int i = 0; i < navigationTools->GetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = navigationTools->GetTool(i); toolCorrespondencesInToolStorage->push_back(i); bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str()); if (!toolAddSuccess) { //todo error handling errorMessage->append("Can't add tool, is the toolfile valid?"); return nullptr; } } returnValue->SetTrackingDevice(thisDevice); return returnValue; } } diff --git a/Modules/IGT/files.cmake b/Modules/IGT/files.cmake index 8d9ec0bc9e..f9b80c1194 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,113 +1,115 @@ set(CPP_FILES TestingHelper/mitkNavigationToolStorageTestHelper.cpp Algorithms/mitkNavigationDataDelayFilter.cpp Algorithms/mitkNavigationDataDisplacementFilter.cpp Algorithms/mitkNavigationDataEvaluationFilter.cpp Algorithms/mitkNavigationDataLandmarkTransformFilter.cpp + Algorithms/mitkNavigationDataPassThroughFilter.cpp Algorithms/mitkNavigationDataReferenceTransformFilter.cpp Algorithms/mitkNavigationDataSmoothingFilter.cpp Algorithms/mitkNavigationDataToMessageFilter.cpp Algorithms/mitkNavigationDataToNavigationDataFilter.cpp Algorithms/mitkNavigationDataToPointSetFilter.cpp Algorithms/mitkNavigationDataTransformFilter.cpp Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp Algorithms/mitkIGTLMessageToNavigationDataFilter.cpp + Algorithms/mitkNeedleProjectionFilter.cpp Algorithms/mitkPivotCalibration.cpp Common/mitkIGTTimeStamp.cpp Common/mitkSerialCommunication.cpp DataManagement/mitkNavigationDataSource.cpp DataManagement/mitkNavigationTool.cpp DataManagement/mitkNavigationToolStorage.cpp DataManagement/mitkTrackingDeviceSourceConfigurator.cpp DataManagement/mitkTrackingDeviceSource.cpp DataManagement/mitkTrackingDeviceTypeCollection.cpp ExceptionHandling/mitkIGTException.cpp ExceptionHandling/mitkIGTHardwareException.cpp ExceptionHandling/mitkIGTIOException.cpp IO/mitkNavigationDataPlayer.cpp IO/mitkNavigationDataPlayerBase.cpp IO/mitkNavigationDataRecorder.cpp IO/mitkNavigationDataRecorderDeprecated.cpp IO/mitkNavigationDataSequentialPlayer.cpp IO/mitkNavigationToolReader.cpp IO/mitkNavigationToolStorageSerializer.cpp IO/mitkNavigationToolStorageDeserializer.cpp IO/mitkNavigationToolWriter.cpp IO/mitkNavigationDataReaderInterface.cpp Rendering/mitkCameraVisualization.cpp Rendering/mitkNavigationDataObjectVisualizationFilter.cpp Rendering/mitkNavigationDataSliceVisualization.cpp TrackingDevices/mitkClaronTool.cpp TrackingDevices/mitkClaronTrackingDevice.cpp TrackingDevices/mitkInternalTrackingTool.cpp TrackingDevices/mitkNDIPassiveTool.cpp TrackingDevices/mitkNDIProtocol.cpp TrackingDevices/mitkNDITrackingDevice.cpp TrackingDevices/mitkTrackingDevice.cpp TrackingDevices/mitkTrackingTool.cpp TrackingDevices/mitkTrackingVolumeGenerator.cpp TrackingDevices/mitkVirtualTrackingDevice.cpp TrackingDevices/mitkVirtualTrackingTool.cpp TrackingDevices/mitkOptitrackErrorMessages.cpp TrackingDevices/mitkOptitrackTrackingDevice.cpp TrackingDevices/mitkOptitrackTrackingTool.cpp TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp TrackingDevices/mitkNDIAuroraTypeInformation.cpp TrackingDevices/mitkNDIPolarisTypeInformation.cpp TrackingDevices/mitkNPOptitrackTrackingTypeInformation.cpp TrackingDevices/mitkVirtualTrackerTypeInformation.cpp TrackingDevices/mitkMicronTrackerTypeInformation.cpp TrackingDevices/mitkOpenIGTLinkTypeInformation.cpp TrackingDevices/mitkUnspecifiedTrackingTypeInformation.cpp # TrackingDevices/mitkPolhemusTrackingDevice.cpp # TrackingDevices/mitkPolhemusTool.cpp # TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp ) set(H_FILES DataManagement/mitkTrackingDeviceTypeInformation.h Common/mitkTrackingTypes.h ) set(RESOURCE_FILES ClaronMicron.stl IntuitiveDaVinci.stl NDIAurora.stl NDIAurora_Dome.stl NDIAuroraCompactFG_Dome.stl NDIAuroraPlanarFG_Dome.stl NDIAuroraTabletopFG_Dome.stl NDIAuroraTabletopFG_Prototype_Dome.stl NDIPolarisOldModel.stl NDIPolarisSpectra.stl NDIPolarisSpectraExtendedPyramid.stl NDIPolarisVicra.stl ) if(MITK_USE_MICRON_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterface.cpp) else() set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterfaceStub.cpp) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkMicroBirdTrackingDevice.cpp) endif(MITK_USE_MICROBIRD_TRACKER) if(MITK_USE_POLHEMUS_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkPolhemusInterface.cpp TrackingDevices/mitkPolhemusTrackingDevice.cpp TrackingDevices/mitkPolhemusTool.cpp TrackingDevices/mitkPolhemusTrackerTypeInformation.cpp ) endif(MITK_USE_POLHEMUS_TRACKER) diff --git a/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.cpp b/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.cpp index d337d2d393..f84d1676a5 100644 --- a/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.cpp @@ -1,77 +1,77 @@ /*=================================================================== 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 "QmitkAbstractTrackingDeviceWidget.h" #include QmitkAbstractTrackingDeviceWidget::QmitkAbstractTrackingDeviceWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) , m_TestConnectionWorker(nullptr) , m_TestConnectionWorkerThread(nullptr) , m_ErrorMessage("") , isInitialized(false) { } void QmitkAbstractTrackingDeviceWidget::InitializeSuperclassWidget() { m_TestConnectionWorkerThread = new QThread(); m_TestConnectionWorker = new QmitkTrackingDeviceConfigurationWidgetConnectionWorker(); CreateConnections(); m_ErrorMessage = ""; isInitialized = true; } QmitkAbstractTrackingDeviceWidget::~QmitkAbstractTrackingDeviceWidget(){ if (m_TestConnectionWorker) delete m_TestConnectionWorker; if (m_TestConnectionWorkerThread) delete m_TestConnectionWorkerThread; } void QmitkAbstractTrackingDeviceWidget::TestConnectionFinished(bool connected, QString output) { m_TestConnectionWorkerThread->quit(); AddOutput(output.toStdString()); MITK_INFO << "Test connection: " << connected; this->setEnabled(true); } void QmitkAbstractTrackingDeviceWidget::TestConnection() { this->setEnabled(false); //construct a tracking device: - mitk::TrackingDevice::Pointer testTrackingDevice = ConstructTrackingDevice(); + mitk::TrackingDevice::Pointer testTrackingDevice = GetTrackingDevice(); m_TestConnectionWorker->SetTrackingDevice(testTrackingDevice); m_TestConnectionWorkerThread->start(); } void QmitkAbstractTrackingDeviceWidget::CreateConnections() { connect(m_TestConnectionWorker, SIGNAL(ConnectionTested(bool, QString)), this, SLOT(TestConnectionFinished(bool, QString))); connect(m_TestConnectionWorkerThread, SIGNAL(started()), m_TestConnectionWorker, SLOT(TestConnectionThreadFunc())); //move the worker to the thread m_TestConnectionWorker->moveToThread(m_TestConnectionWorkerThread); } QmitkAbstractTrackingDeviceWidget* QmitkAbstractTrackingDeviceWidget::CloneForQt(QWidget* parent) const { QmitkAbstractTrackingDeviceWidget* clonedWidget = this->Clone(parent); if (!clonedWidget->IsInitialized()) MITK_ERROR << "Your cloned widget is not initialized!"; clonedWidget->create(); return clonedWidget; } diff --git a/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.h b/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.h index 2948a8c06c..74f1aeaec6 100644 --- a/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkAbstractTrackingDeviceWidget.h @@ -1,143 +1,175 @@ /*=================================================================== 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 QmitkAbstractTrackingDeviceWidget_H #define QmitkAbstractTrackingDeviceWidget_H #include #include "MitkIGTUIExports.h" #include "mitkTrackingDevice.h" #include #include "QmitkTrackingDeviceConfigurationWidgetConnectionWorker.h" //itk headers /** Documentation: * \brief Abstract class to configure a tracking device. * Inherited widgets should be registered in the Microservice (TrackingDeviceCollectionWidget), * If done so, they will be included in the QmitkTrackingDeviceConfigurationWidget of the Tracking Toolbox. * - * - Each implementation of this class must have a method to construct a tracking Device (ConstructTrackingDevice). + * - Each implementation of this class must have a method to get a TrackingDevice + * - Each implementation handles itself, if a new TrackingDevice needs to be constructed. + * Attention: In former MITK versions, there was no pure virtual GetTrackingDevice function but a pure virtual ConstructTrackingDevice function. + * You can simply rename these, but you should give it a thought, if each time "Construct" was called, a new device needs to be constructed, + * or if you can store your TrackingDevice in a member variable and return this. Up to you. * - Please create the UI elements in a function like CreateQtPartControl (e.g. see QmitkVitrualTrackerWidget). * - You might want to use own buttons etc., please connect them in a private CreateConnections (e.g. see QmitkVitrualTrackerWidget). * - Due to initialization of qt during autoloading of the IGT module, you constructor should be as slim as possible and only contain a call * of the QmitkAbstractTrackingDeviceWidget constructor and simple variable initialization. * - For the initialization, you must write an Iniltialize() function, which must include a call of InitializeSuperclassWidget() and should contain * calls of your private CreateConnections / CreateQtPartControl (if you implemented these). * - For integration into the TrackingToolbox, a clone function is needed. Here, a new widget should be created, Initialize() needs to be called, * and all settings of your widget should be copied. * * You can Load and Store previous settings of your GUI elements (e.g. see QmitkNDIPolarisWidget). * Also, you can add an output textbox to your widget to display information about your device status. It's optional, see e.g. QmitkNDIAuroraWidget. * Some Devices need the information if drivers are installed on your computer. If this is necessary for your device to avoid crashes, * please override IsDeviceInstalled. The default return value is true otherwise. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkAbstractTrackingDeviceWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; QmitkAbstractTrackingDeviceWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkAbstractTrackingDeviceWidget() override; /** * \brief Return pointer to copy of the object. * Internally use of QmitkUSAbstractCustomWidget::Clone() with additionaly * setting an internal flag that the object was really cloned. */ QmitkAbstractTrackingDeviceWidget* CloneForQt(QWidget* parent = 0) const; /** * \brief Subclass must implement this method to return a pointer to a copy of the object. * Please don't forget to call InitializeSuperclassWidget(), CreateQtPartControl and optionally CreateConnections during this function. */ virtual void Initialize() = 0; bool IsInitialized() const { return isInitialized; } signals: void ConnectionTested(bool connected, QString output); protected slots: void TestConnectionFinished(bool connected, QString output); /* @brief This method is called when the user presses the button "test connection". The method will then create a temporary tracking device, * try to open a connection and start tracking. The user can see the result of the connection test on the small output window. */ void TestConnection(); private: /// \brief Creation of the connections. You might implement the same function again in your inherited widget. void CreateConnections(); protected: PERSISTENCE_GET_SERVICE_METHOD_MACRO void InitializeSuperclassWidget(); QmitkTrackingDeviceConfigurationWidgetConnectionWorker* m_TestConnectionWorker; QThread* m_TestConnectionWorkerThread; /** * \brief Subclass must implement this method to return a pointer to a copy of the object. * Please don't forget to call Initialize() during this function and copy all of your settings. */ virtual QmitkAbstractTrackingDeviceWidget* Clone(QWidget* parent = 0) const = 0; public: /** * \brief Optional method to add output to a small screen in the trackingToolbox (see QmitkNDIPolarisWidget) */ virtual void ResetOutput() {} /** * \brief Optional method to add output to a small screen in the trackingToolbox (see QmitkNDIPolarisWidget) */ virtual void AddOutput(std::string) {} - virtual mitk::TrackingDevice::Pointer ConstructTrackingDevice() = 0; + virtual mitk::TrackingDevice::Pointer GetTrackingDevice() = 0; /** * \brief Optional method to store and load settings of your widget (see QmitkNDIPolarisWidget) */ virtual void StoreUISettings() {} /** * \brief Optional method to store and load settings of your widget (see QmitkNDIPolarisWidget) */ virtual void LoadUISettings() {} /** * \brief Optional method to investigate if drivers etc for your device are installed. * The default value is "true" as most devices don't need this information. * Others however migth crash, and for these you might implement this function (see QmitkMicronTrackerWidget) */ virtual bool IsDeviceInstalled() { return true; } + /** + * \brief This function is called, when in the TrackingToolboxView "Connect" was clicked and the device is successful connected. + * Can e.g. be used to activate options of a tracking device only when it is connected. + */ + virtual void OnConnected(bool) {} + /** + * \brief This function is called, when in the TrackingToolboxView "Disconnect" was clicked and the device is successful disconnected. + * Can e.g. be used to activate/disactivate options of a tracking device. + */ + virtual void OnDisconnected(bool) {} + + /** + * \brief This function is called, when in the TrackingToolboxView "Start Tracking" was clicked and the device successfully started tracking. + * Can e.g. be used to activate options of a tracking device only when tracking is started. + */ + virtual void OnStartTracking(bool) {} + /** + * \brief This function is called, when in the TrackingToolboxView "Stop Tracking" was clicked and the device successful stopped tracking. + * Can e.g. be used to activate/disactivate options when device is not tracking. + */ + virtual void OnStopTracking(bool) {} + /** + * \brief This function is called, when anything in the ToolStorage changed, e.g. AddTool or EditTool. + * ServiceListener is connected in the QmitkMITKIGTTrackingToolboxView. + */ + virtual void OnToolStorageChanged() {} + + std::string m_ErrorMessage; ///< current problem description private: /** * \warning Don't touch this variable if you don't know what you are doing! */ bool isInitialized; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkIGTConnectionWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTConnectionWidget.cpp index d86c9516d2..099873b754 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTConnectionWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTConnectionWidget.cpp @@ -1,215 +1,215 @@ /*=================================================================== 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 "QmitkIGTConnectionWidget.h" #include "QmitkTrackingDeviceConfigurationWidget.h" #include "mitkClaronTrackingDevice.h" #include "mitkNDITrackingDevice.h" #include "mitkOptitrackTrackingDevice.h" #include "mitkNavigationToolStorageDeserializer.h" #include "mitkTrackingDeviceSourceConfigurator.h" #include "QmitkIGTCommonHelper.h" #include #include const std::string QmitkIGTConnectionWidget::VIEW_ID = "org.mitk.views.igtconnectionwidget"; QmitkIGTConnectionWidget::QmitkIGTConnectionWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); CreateConnections(); m_TrackingDevice = nullptr; m_TrackingDeviceSource = nullptr; m_NavigationToolStorage = nullptr; m_DataStorage = nullptr; m_ErrorMessage = ""; } QmitkIGTConnectionWidget::~QmitkIGTConnectionWidget() { } void QmitkIGTConnectionWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTConnectionWidgetControls; m_Controls->setupUi(parent); } } void QmitkIGTConnectionWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->connectButton), SIGNAL(clicked()), this, SLOT(OnConnect()) ); } } void QmitkIGTConnectionWidget::OnConnect() { if (m_Controls->connectButton->isChecked()) // Load tools and connect tracking device { m_Controls->connectButton->setChecked(false); // create TrackingDevice m_TrackingDevice = m_Controls->trackingDeviceConfigurationWidget->GetTrackingDevice(); if (m_TrackingDevice.IsNotNull()) { QString fileName = QFileDialog::getOpenFileName(nullptr,tr("Open Navigation tool storage"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("Toolfile (*.tfl)")); QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(fileName); if (LoadToolfile(fileName)) { // Create TrackingDeviceSource and add tools mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(this->m_NavigationToolStorage,m_TrackingDevice); m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(); m_TrackingDeviceSource->Connect(); m_TrackingDeviceSource->StartTracking(); // change button text m_Controls->connectButton->setText("Disconnect"); m_Controls->connectButton->setChecked(true); // disable configuration widget m_Controls->trackingDeviceConfigurationWidget->setEnabled(false); // emit connected signal emit TrackingDeviceConnected(); } else { QString error(m_ErrorMessage.c_str()); QMessageBox::warning(nullptr,"Warning",error); // reset button to unchecked m_Controls->connectButton->setChecked(false); // remove tool nodes from DataStorage this->RemoveToolNodes(); // reset NavigationToolStorage m_NavigationToolStorage = nullptr; } } else { // reset button to unchecked m_Controls->connectButton->setChecked(false); MITK_ERROR<<"Could not create TrackingDevice"; } } else // Disconnect tracking device { // disconnect TrackingDeviceSource if (m_TrackingDeviceSource.IsNotNull()) { m_TrackingDeviceSource->StopTracking(); m_TrackingDeviceSource->Disconnect(); } // remove tool nodes from DataStorage this->RemoveToolNodes(); // reset members m_NavigationToolStorage = nullptr; m_TrackingDevice = nullptr; m_TrackingDeviceSource = nullptr; // change button text m_Controls->connectButton->setText("Connect"); // enable configuration widget m_Controls->trackingDeviceConfigurationWidget->setEnabled(true); // emit disconnected signal emit TrackingDeviceDisconnected(); } } bool QmitkIGTConnectionWidget::LoadToolfile(QString qFilename) { if (m_DataStorage.IsNotNull()) { std::string filename = qFilename.toStdString(); mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(this->m_DataStorage); mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); m_NavigationToolStorage = tempStorage; if (tempStorage.IsNull()) { m_ErrorMessage = myDeserializer->GetErrorMessage(); return false; } // check if there are tools in the storage mitk::TrackingDeviceType lastDevice; if (tempStorage->GetToolCount()>0) { lastDevice = tempStorage->GetTool(0)->GetTrackingDeviceType(); } else { m_ErrorMessage = "Error: Didn't find a tool in the storage. Do you want to navigate without even an instrument?"; return false; } //check if all tools are from the same device - for (int i=1; iGetToolCount(); i++) + for (unsigned int i=1; iGetToolCount(); i++) { if (lastDevice!=tempStorage->GetTool(i)->GetTrackingDeviceType()) { m_ErrorMessage = "Error: Toolfile contains tools of different tracking devices which is not acceptable for this application."; return false; } else lastDevice = tempStorage->GetTool(i)->GetTrackingDeviceType(); } // check if tracking device typ of tools corresponds with chosen tracking device if (m_TrackingDevice->GetType()!=tempStorage->GetTool(0)->GetTrackingDeviceType()) { m_ErrorMessage = "Tools are not compliant with this tracking device. Please use correct toolfile for specified device."; return false; } m_NavigationToolStorage = tempStorage; return true; } else { m_ErrorMessage = "Error: No DataStorage available! Make sure the widget is initialized with a DataStorage"; return false; } } void QmitkIGTConnectionWidget::RemoveToolNodes() { - for (int i=0; iGetToolCount(); i++) + for (unsigned int i=0; iGetToolCount(); i++) { mitk::DataNode::Pointer currentNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); if (currentNode.IsNotNull()) { m_DataStorage->Remove(currentNode); } } } mitk::TrackingDeviceSource::Pointer QmitkIGTConnectionWidget::GetTrackingDeviceSource() { return m_TrackingDeviceSource; } void QmitkIGTConnectionWidget::SetDataStorage( mitk::DataStorage::Pointer dataStorage ) { m_DataStorage = dataStorage; } mitk::NavigationToolStorage::Pointer QmitkIGTConnectionWidget::GetNavigationToolStorage() { return m_NavigationToolStorage; } diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp index ce2de57c70..f994bf2fdc 100644 --- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.cpp @@ -1,287 +1,300 @@ /*=================================================================== 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 "QmitkInteractiveTransformationWidget.h" // mitk includes #include "mitkRenderingManager.h" +#include "mitkBaseRenderer.h" #include "mitkNavigationData.h" // vtk includes #include "vtkMatrix4x4.h" #include "vtkLinearTransform.h" const std::string QmitkInteractiveTransformationWidget::VIEW_ID = "org.mitk.views.interactivetransformationwidget"; QmitkInteractiveTransformationWidget::QmitkInteractiveTransformationWidget(QWidget* parent, Qt::WindowFlags f) -: QWidget(parent, f), m_Controls(nullptr), m_Geometry(nullptr), m_ResetGeometry(nullptr) + : QDialog(parent, f), m_Controls(nullptr), m_Geometry(nullptr) { CreateQtPartControl(this); CreateConnections(); - m_TranslationVector.Fill(0.0f); - m_RotateSliderPos.Fill(0.0f); + + m_ResetGeometry = mitk::Geometry3D::New(); + + + this->setWindowTitle("Edit Tool Tip and Tool Orientation"); } QmitkInteractiveTransformationWidget::~QmitkInteractiveTransformationWidget() { } void QmitkInteractiveTransformationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkInteractiveTransformationWidgetControls; m_Controls->setupUi(parent); } } void QmitkInteractiveTransformationWidget::CreateConnections() { - if ( m_Controls ) + if (m_Controls) { // translations - connect( (QObject*)(m_Controls->m_XTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnXTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_XTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnXTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_YTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnYTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_YTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnYTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_ZTransSlider), SIGNAL(valueChanged(int)), this, SLOT(OnZTranslationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_ZTransSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnZTranslationValueChanged(int)) ); + connect(m_Controls->m_XTransSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnXTranslationValueChanged); + connect(m_Controls->m_XTransSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnXTranslationValueChanged); + + connect(m_Controls->m_YTransSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnYTranslationValueChanged); + connect(m_Controls->m_YTransSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnYTranslationValueChanged); + + connect(m_Controls->m_ZTransSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnZTranslationValueChanged); + connect(m_Controls->m_ZTransSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnZTranslationValueChanged); // rotations - connect( (QObject*)(m_Controls->m_XRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnXRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_XRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnXRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_YRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnYRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_YRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnYRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_ZRotSlider), SIGNAL(valueChanged(int)), this, SLOT(OnZRotationValueChanged(int)) ); - connect( (QObject*)(m_Controls->m_ZRotSpinBox), SIGNAL(valueChanged(int)), this, SLOT(OnZRotationValueChanged(int)) ); - - connect( (QObject*)(m_Controls->m_ResetPB), SIGNAL(clicked()), this, SLOT(OnResetGeometry()) ); - connect( (QObject*)(m_Controls->m_UseManipulatedToolTipPB), SIGNAL(clicked()), this, SLOT(OnApplyManipulatedToolTip()) ); + connect(m_Controls->m_XRotSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnXRotationValueChanged); + connect(m_Controls->m_XRotSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnXRotationValueChanged); + + connect(m_Controls->m_YRotSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnYRotationValueChanged); + connect(m_Controls->m_YRotSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnYRotationValueChanged); + + connect(m_Controls->m_ZRotSpinBox, static_cast(&QDoubleSpinBox::valueChanged), this, &QmitkInteractiveTransformationWidget::OnZRotationValueChanged); + connect(m_Controls->m_ZRotSlider, &QSlider::valueChanged, this, &QmitkInteractiveTransformationWidget::OnZRotationValueChanged); + + connect((QObject*)(m_Controls->m_ResetPB), SIGNAL(clicked()), this, SLOT(OnResetGeometryToIdentity())); + connect((QObject*)(m_Controls->m_RevertChanges), SIGNAL(clicked()), this, SLOT(OnRevertChanges())); + connect((QObject*)(m_Controls->m_UseManipulatedToolTipPB), SIGNAL(clicked()), this, SLOT(OnApplyManipulatedToolTip())); + connect((QObject*)(m_Controls->m_Cancel), SIGNAL(clicked()), this, SLOT(OnCancel())); } } -void QmitkInteractiveTransformationWidget::SetGeometry( mitk::BaseGeometry::Pointer geometry, mitk::BaseGeometry::Pointer defaultValues ) +void QmitkInteractiveTransformationWidget::SetToolToEdit(const mitk::NavigationTool::Pointer _tool) { - m_Geometry = geometry; - m_ResetGeometry = geometry->Clone(); - - //set default values - if (defaultValues.IsNotNull()) - { - //first: some conversion - mitk::NavigationData::Pointer transformConversionHelper = mitk::NavigationData::New(defaultValues->GetIndexToWorldTransform()); - double eulerAlphaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[0] / vnl_math::pi * 180; - double eulerBetaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[1] / vnl_math::pi * 180; - double eulerGammaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[2] / vnl_math::pi * 180; - - //set translation - OnXTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[0]); - OnYTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[1]); - OnZTranslationValueChanged(defaultValues->GetIndexToWorldTransform()->GetOffset()[2]); - - //set rotation - OnXRotationValueChanged(eulerAlphaDegrees); - OnYRotationValueChanged(eulerBetaDegrees); - OnZRotationValueChanged(eulerGammaDegrees); - } - else - { - //reset everything - OnXTranslationValueChanged(0); - OnYTranslationValueChanged(0); - OnZTranslationValueChanged(0); - OnXRotationValueChanged(0); - OnYRotationValueChanged(0); - OnZRotationValueChanged(0); - } + //If there is already a tool, remove it's node first. + if (m_ToolToEdit) + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage() + ->Remove(m_ToolToEdit->GetDataNode()); + + m_ToolToEdit = _tool->Clone(); + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage() + ->Add(m_ToolToEdit->GetDataNode()); + m_ToolToEdit->GetDataNode()->SetName("Tool Tip to be edited"); + + //change color to red + m_ToolToEdit->GetDataNode()->SetProperty("color", mitk::ColorProperty::New(1, 0, 0)); + + //use the set-fuction via vtk matrix, 'cause this garantees a deep copy and not just sharing a pointer. + m_Geometry = m_ToolToEdit->GetDataNode()->GetData()->GetGeometry(); + m_ResetGeometry->SetIndexToWorldTransformByVtkMatrix(m_Geometry->GetVtkMatrix()); //Remember the original values to be able to reset and abort everything } -mitk::BaseGeometry::Pointer QmitkInteractiveTransformationWidget::GetGeometry() +void QmitkInteractiveTransformationWidget::SetDefaultOffset(const mitk::Point3D _defaultValues) { - return m_Geometry; + m_Geometry->SetOrigin(_defaultValues); + m_ResetGeometry->SetOrigin(_defaultValues); //Remember the original values to be able to reset and abort everything + SetValuesToGUI(m_Geometry->GetIndexToWorldTransform()); } +void QmitkInteractiveTransformationWidget::SetDefaultRotation(const mitk::Quaternion _defaultValues) +{ + // Conversion to navigation data / transform + mitk::NavigationData::Pointer rotationTransform = mitk::NavigationData::New(m_Geometry->GetIndexToWorldTransform()); + rotationTransform->SetOrientation(_defaultValues); + m_Geometry->SetIndexToWorldTransform(rotationTransform->GetAffineTransform3D()); + //For ResetGeometry, use the set-fuction via vtk matrix, 'cause this garantees a deep copy and not just sharing a pointer. + m_ResetGeometry->SetIndexToWorldTransformByVtkMatrix(m_Geometry->GetVtkMatrix()); //Remember the original values to be able to reset and abort everything + SetValuesToGUI(m_Geometry->GetIndexToWorldTransform()); +} +void QmitkInteractiveTransformationWidget::SetValuesToGUI(const mitk::AffineTransform3D::Pointer _defaultValues) +{ + //Set toolTip values in gui + m_Controls->m_XTransSlider->setValue(_defaultValues->GetOffset()[0]); + m_Controls->m_YTransSlider->setValue(_defaultValues->GetOffset()[1]); + m_Controls->m_ZTransSlider->setValue(_defaultValues->GetOffset()[2]); -///////////////////////////////////////////////////////////////////////////////////////////// -// Section to allow interactive positioning of the moving surface -///////////////////////////////////////////////////////////////////////////////////////////// + //first: some conversion + mitk::NavigationData::Pointer transformConversionHelper = mitk::NavigationData::New(_defaultValues); + double eulerAlphaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[0] / vnl_math::pi * 180; + double eulerBetaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[1] / vnl_math::pi * 180; + double eulerGammaDegrees = transformConversionHelper->GetOrientation().rotation_euler_angles()[2] / vnl_math::pi * 180; -void QmitkInteractiveTransformationWidget::OnXTranslationValueChanged( int v ) -{ - mitk::Vector3D translationParams; - translationParams[0] = v; - translationParams[1] = m_Controls->m_YTransSlider->value(); - translationParams[2] = m_Controls->m_ZTransSlider->value(); - SetSliderX(v); - this->Translate(translationParams); -} + m_Controls->m_XRotSpinBox->setValue(eulerAlphaDegrees); + m_Controls->m_YRotSpinBox->setValue(eulerBetaDegrees); + m_Controls->m_ZRotSpinBox->setValue(eulerGammaDegrees); -void QmitkInteractiveTransformationWidget::SetSliderX(int v) -{ - m_Controls->m_XTransSlider->setValue(v); - m_Controls->m_XTransSpinBox->setValue(v); + //Update view + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkInteractiveTransformationWidget::OnYTranslationValueChanged( int v ) +void QmitkInteractiveTransformationWidget::SetSynchronizedVauesToSliderAndSpinbox(QDoubleSpinBox* _spinbox, QSlider* _slider, double _value) { - mitk::Vector3D translationParams; - translationParams[0] = m_Controls->m_XTransSlider->value(); - translationParams[1] = v; - translationParams[2] = m_Controls->m_ZTransSlider->value(); - SetSliderY(v); - this->Translate(translationParams); +//block signals to avoid loop between slider and spinbox. Unblock at the end of the function! + _spinbox->blockSignals(true); + _slider->blockSignals(true); + _spinbox->setValue(_value); + _slider->setValue(_value); +//unblock signals. See above, don't remove this line. Unblock at the end of the function! + _spinbox->blockSignals(false);// + _slider->blockSignals(false);// } -void QmitkInteractiveTransformationWidget::SetSliderY(int v) +void QmitkInteractiveTransformationWidget::OnXTranslationValueChanged(double v) { - m_Controls->m_YTransSlider->setValue(v); - m_Controls->m_YTransSpinBox->setValue(v); -} + //Set values to member variable + mitk::Point3D translationParams = m_Geometry->GetOrigin(); + translationParams[0] = v; + m_Geometry->SetOrigin(translationParams); + + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_XTransSpinBox, m_Controls->m_XTransSlider, v); + + //Update view + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -void QmitkInteractiveTransformationWidget::OnZTranslationValueChanged( int v ) -{ - mitk::Vector3D translationParams; - translationParams[0] = m_Controls->m_XTransSlider->value(); - translationParams[1] = m_Controls->m_YTransSlider->value(); - translationParams[2] = v; - SetSliderZ(v); - this->Translate(translationParams); } -void QmitkInteractiveTransformationWidget::SetSliderZ(int v) +void QmitkInteractiveTransformationWidget::OnYTranslationValueChanged(double v) { - m_Controls->m_ZTransSlider->setValue(v); - m_Controls->m_ZTransSpinBox->setValue(v); + //Set values to member variable + mitk::Point3D translationParams = m_Geometry->GetOrigin(); + translationParams[1] = v; + m_Geometry->SetOrigin(translationParams); + + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_YTransSpinBox, m_Controls->m_YTransSlider, v); + + //Update view + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkInteractiveTransformationWidget::Translate( mitk::Vector3D translateVector) +void QmitkInteractiveTransformationWidget::OnZTranslationValueChanged(double v) { - mitk::Vector3D translateVec; - - // transform the translation vector - translateVec[0] = translateVector[0] - m_TranslationVector[0]; - translateVec[1] = translateVector[1] - m_TranslationVector[1]; - translateVec[2] = translateVector[2] - m_TranslationVector[2]; + //Set values to member variable + mitk::Point3D translationParams = m_Geometry->GetOrigin(); + translationParams[2] = v; + m_Geometry->SetOrigin(translationParams); - // set the new translation vector to member variable - m_TranslationVector[0] = translateVector[0]; - m_TranslationVector[1] = translateVector[1]; - m_TranslationVector[2] = translateVector[2]; + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_ZTransSpinBox, m_Controls->m_ZTransSlider, v); - m_Geometry->Translate( translateVec ); - qApp->processEvents(); + //Update view mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkInteractiveTransformationWidget::OnXRotationValueChanged( int v ) +void QmitkInteractiveTransformationWidget::OnXRotationValueChanged(double v) { mitk::Vector3D rotationParams; rotationParams[0] = v; - rotationParams[1] = m_Controls->m_YRotSlider->value(); - rotationParams[2] = m_Controls->m_ZRotSlider->value(); + rotationParams[1] = m_Controls->m_YRotSpinBox->value(); + rotationParams[2] = m_Controls->m_ZRotSpinBox->value(); - m_Controls->m_XRotSlider->setValue(v); - m_Controls->m_XRotSpinBox->setValue(v); + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_XRotSpinBox, m_Controls->m_XRotSlider, v); this->Rotate(rotationParams); } -void QmitkInteractiveTransformationWidget::OnYRotationValueChanged( int v ) +void QmitkInteractiveTransformationWidget::OnYRotationValueChanged(double v) { mitk::Vector3D rotationParams; - rotationParams[0] = m_Controls->m_XRotSlider->value(); + rotationParams[0] = m_Controls->m_XRotSpinBox->value(); rotationParams[1] = v; - rotationParams[2] = m_Controls->m_ZRotSlider->value(); + rotationParams[2] = m_Controls->m_ZRotSpinBox->value(); - m_Controls->m_YRotSlider->setValue(v); - m_Controls->m_YRotSpinBox->setValue(v); + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_YRotSpinBox, m_Controls->m_YRotSlider, v); this->Rotate(rotationParams); } -void QmitkInteractiveTransformationWidget::OnZRotationValueChanged( int v ) +void QmitkInteractiveTransformationWidget::OnZRotationValueChanged(double v) { mitk::Vector3D rotationParams; - rotationParams[0]=m_Controls->m_XRotSlider->value(); - rotationParams[1]=m_Controls->m_YRotSlider->value(); - rotationParams[2]=v; - m_Controls->m_ZRotSlider->setValue(v); - m_Controls->m_ZRotSpinBox->setValue(v); + rotationParams[0] = m_Controls->m_XRotSpinBox->value(); + rotationParams[1] = m_Controls->m_YRotSpinBox->value(); + rotationParams[2] = v; + + SetSynchronizedVauesToSliderAndSpinbox(m_Controls->m_ZRotSpinBox, m_Controls->m_ZRotSlider, v); this->Rotate(rotationParams); } void QmitkInteractiveTransformationWidget::Rotate(mitk::Vector3D rotateVector) { //0: from degrees to radians double radianX = rotateVector[0] * vnl_math::pi / 180; double radianY = rotateVector[1] * vnl_math::pi / 180; double radianZ = rotateVector[2] * vnl_math::pi / 180; //1: from euler angles to quaternion - mitk::Quaternion rotation(radianX,radianY,radianZ); + mitk::Quaternion rotation(radianX, radianY, radianZ); //2: Conversion to navigation data / transform - mitk::NavigationData::Pointer rotationTransform = mitk::NavigationData::New(); + mitk::NavigationData::Pointer rotationTransform = mitk::NavigationData::New(m_Geometry->GetIndexToWorldTransform()); rotationTransform->SetOrientation(rotation); - //3: Apply transform + m_Geometry->SetIndexToWorldTransform(rotationTransform->GetAffineTransform3D()); - //also remember old transform, but without rotation, because rotation is completely stored in the sliders - mitk::NavigationData::Pointer oldTransform = mitk::NavigationData::New(m_Geometry->GetIndexToWorldTransform()); - mitk::Quaternion identity(0,0,0,1); - oldTransform->SetOrientation(identity); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} - //compose old transform with the new one - rotationTransform->Compose(oldTransform); +void QmitkInteractiveTransformationWidget::OnResetGeometryToIdentity() +{ + // reset the input to its initial state. + m_Geometry->SetIdentity(); - //and apply it... - m_Geometry->SetIndexToWorldTransform(rotationTransform->GetAffineTransform3D()); - qApp->processEvents(); + //Update Sliders + this->SetValuesToGUI(m_Geometry->GetIndexToWorldTransform()); + //Refresh view mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void QmitkInteractiveTransformationWidget::OnResetGeometry() +void QmitkInteractiveTransformationWidget::OnRevertChanges() { - m_Controls->m_XRotSlider->setValue(0); - m_Controls->m_YRotSlider->setValue(0); - m_Controls->m_ZRotSlider->setValue(0); - m_Controls->m_XRotSpinBox->setValue(0); - m_Controls->m_YRotSpinBox->setValue(0); - m_Controls->m_ZRotSpinBox->setValue(0); - - m_Controls->m_XTransSlider->setValue(0); - m_Controls->m_YTransSlider->setValue(0); - m_Controls->m_ZTransSlider->setValue(0); - m_Controls->m_XTransSpinBox->setValue(0); - m_Controls->m_YTransSpinBox->setValue(0); - m_Controls->m_ZTransSpinBox->setValue(0); - qApp->processEvents(); - // reset the input to its initial state. - m_Geometry->SetIdentity(); - m_Geometry->Compose(m_ResetGeometry->GetVtkTransform()->GetMatrix()); + m_Geometry->SetIndexToWorldTransformByVtkMatrix(m_ResetGeometry->GetVtkMatrix()); + + //Update Sliders + this->SetValuesToGUI(m_Geometry->GetIndexToWorldTransform()); + //Refresh view mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkInteractiveTransformationWidget::OnApplyManipulatedToolTip() { - emit ApplyManipulatedToolTip(); + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage() + ->Remove(m_ToolToEdit->GetDataNode()); + + mitk::AffineTransform3D::Pointer toolTip = m_Geometry->GetIndexToWorldTransform(); + emit EditToolTipFinished(toolTip); + this->close(); +} + +void QmitkInteractiveTransformationWidget::reject() +{ + OnCancel(); } + +void QmitkInteractiveTransformationWidget::OnCancel() +{ + QDialog::reject(); + + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage() + ->Remove(m_ToolToEdit->GetDataNode()); + + emit EditToolTipFinished(nullptr); +} \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h index f4a93e5f95..bbab6d819d 100644 --- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidget.h @@ -1,94 +1,102 @@ /*=================================================================== 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 QmitkInteractiveTransformationWidget_H #define QmitkInteractiveTransformationWidget_H //QT headers -#include +#include //Mitk headers #include "MitkIGTUIExports.h" #include "mitkVector.h" #include "mitkGeometry3D.h" +#include "mitkNavigationTool.h" //ui header #include "ui_QmitkInteractiveTransformationWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to create a widget to access the advance tool creation options. * * * \ingroup IGTUI */ -class MITKIGTUI_EXPORT QmitkInteractiveTransformationWidget : public QWidget +class MITKIGTUI_EXPORT QmitkInteractiveTransformationWidget : public QDialog { Q_OBJECT public: static const std::string VIEW_ID; QmitkInteractiveTransformationWidget(QWidget* parent = nullptr, Qt::WindowFlags f = nullptr); ~QmitkInteractiveTransformationWidget() override; - /** Sets the geometry which will be modified by this widget. Default values may be - * provided by the second variable. These values will be applied to the geometry - * in the beginning and the UI will also hold these values. + /** This tool will be copied to m_ToolToEdit. It will not be changed. + To apply any changes made by this widget, you will need to connect to the signal + EditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip) and set this transfrom + as calibrated tool tip. + We do not directly modify the tool to allow to cancel/exit this widget without doing + any harm. */ - void SetGeometry(mitk::BaseGeometry::Pointer geometry, mitk::BaseGeometry::Pointer defaultValues = nullptr); + void SetToolToEdit(const mitk::NavigationTool::Pointer _tool); - mitk::BaseGeometry::Pointer GetGeometry(); + /** The sliders and spinboxes will be set to these values. + When clicking "Revert Changes", sliders will be reseted to these values. + */ + void SetDefaultOffset(const mitk::Point3D _defaultValues); + void SetDefaultRotation(const mitk::Quaternion _defaultValues); protected slots: - void OnZTranslationValueChanged( int v ); - void OnYTranslationValueChanged( int v ); - void OnXTranslationValueChanged( int v ); - void OnZRotationValueChanged( int v ); - void OnYRotationValueChanged( int v ); - void OnXRotationValueChanged( int v ); - void OnResetGeometry(); + void OnZTranslationValueChanged( double v ); + void OnYTranslationValueChanged(double v); + void OnXTranslationValueChanged(double v); + void OnZRotationValueChanged(double v); + void OnYRotationValueChanged(double v); + void OnXRotationValueChanged(double v); + void OnResetGeometryToIdentity(); + void OnRevertChanges(); void OnApplyManipulatedToolTip(); + void OnCancel(); signals: - void ApplyManipulatedToolTip(); + void EditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip); protected: + void reject(); + virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); - void SetSliderX(int v); - void SetSliderY(int v); - void SetSliderZ(int v); - - /*! \brief Method performs the translation. - \params translateVector New translation to be combine with geometry. */ - void Translate( mitk::Vector3D translateVector); - /*! \brief Method performs the rotation. \params rotateVector New rotation to be combined with geometry. */ void Rotate(mitk::Vector3D rotateVector); // Member variables Ui::QmitkInteractiveTransformationWidgetControls* m_Controls; - mitk::BaseGeometry::Pointer m_Geometry; ///< \brief Initial geometry that is manipulated - mitk::BaseGeometry::Pointer m_ResetGeometry; ///< \brief Lifeline to reset to the initial geometry - mitk::Vector3D m_TranslationVector; ///< \brief Accumulated translation vector - mitk::Vector3D m_RotateSliderPos; ///< \brief Accumulated rotation vector (holds degree around x,y,z direction) + mitk::NavigationTool::Pointer m_ToolToEdit; ///< \brief this mamber holds a copy of the tool that should be edited for visualization + mitk::BaseGeometry::Pointer m_Geometry; ///< \brief The geometry that is manipulated + mitk::BaseGeometry::Pointer m_ResetGeometry; ///< \brief Lifeline to reset to the original geometry + +private: + void SetValuesToGUI(const mitk::AffineTransform3D::Pointer _defaultValues); + void SetSynchronizedVauesToSliderAndSpinbox(QDoubleSpinBox* _spinbox, QSlider* _slider, double _value); + }; #endif // QmitkInteractiveTransformationWidget_H diff --git a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui index 62f0938a91..6daf485458 100644 --- a/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkInteractiveTransformationWidgetControls.ui @@ -1,433 +1,463 @@ QmitkInteractiveTransformationWidgetControls 0 0 - 374 - 380 + 435 + 381 Form - + Interactive Translation 50 false x-Direction (Frontal): false 0 0 ArrowCursor -500 500 1 Qt::Horizontal - true + false false QSlider::TicksAbove 100 - + + + 1 + - -500 + -500.000000000000000 - 500 + 500.000000000000000 50 false y-Direction (Sagittal): false 0 0 -500 500 Qt::Horizontal - true + false QSlider::TicksAbove 100 - + + + 1 + - -500 + -500.000000000000000 - 500 - - - 0 + 500.000000000000000 50 false z-Direction (Transversal): false 0 0 -500 500 0 Qt::Horizontal - true + false QSlider::TicksAbove 100 - + + + 1 + - -500 + -500.000000000000000 - 500 - - - 1 + 500.000000000000000 - + Interactive Rotation 50 false x-Axis (Frontal): false 0 0 ArrowCursor -180 180 Qt::Horizontal QSlider::TicksAbove 45 - + + + 1 + - -180 + -180.000000000000000 - 180 + 180.000000000000000 50 false y-Axis (Sagittal): false 0 0 -180 180 Qt::Horizontal QSlider::TicksAbove 45 - + + + 1 + - -180 + -180.000000000000000 - 180 + 180.000000000000000 50 false z-Axis (Transversal): false 0 0 -180 180 Qt::Horizontal QSlider::TicksAbove 45 - + + + 1 + - -180 + -180.000000000000000 - 180 + 180.000000000000000 + + + + + + Use Manipulated ToolTip + + + + + + + Reset To Identity + + + + + + + Revert Changes + + + + + + + Cancel + + + + + - - - - Reset To Identity - - - - - - - Use Manipulated ToolTip - - - diff --git a/Modules/IGTUI/Qmitk/QmitkMicronTrackerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkMicronTrackerWidget.cpp index 953b1c1ed0..c1d1401646 100644 --- a/Modules/IGTUI/Qmitk/QmitkMicronTrackerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkMicronTrackerWidget.cpp @@ -1,171 +1,171 @@ /*=================================================================== 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 "QmitkMicronTrackerWidget.h" #include #include #include #include #include #include #include const std::string QmitkMicronTrackerWidget::VIEW_ID = "org.mitk.views.NDIMicronTrackerWidget"; QmitkMicronTrackerWidget::QmitkMicronTrackerWidget(QWidget* parent, Qt::WindowFlags f) : QmitkAbstractTrackingDeviceWidget(parent, f) , m_Controls(nullptr) { } void QmitkMicronTrackerWidget::Initialize() { InitializeSuperclassWidget(); CreateQtPartControl(this); CreateConnections(); m_MTCalibrationFile = ""; } QmitkMicronTrackerWidget::~QmitkMicronTrackerWidget() { delete m_Controls; } void QmitkMicronTrackerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkMicronTrackerWidget; m_Controls->setupUi(parent); } } void QmitkMicronTrackerWidget::CreateConnections() { if (m_Controls) { connect((QObject*)(m_Controls->m_testConnectionMicronTracker), SIGNAL(clicked()), this, SLOT(TestConnection())); connect((QObject*)(m_Controls->m_SetMTCalibrationFile), SIGNAL(clicked()), this, SLOT(SetMTCalibrationFileClicked())); } } void QmitkMicronTrackerWidget::ResetOutput() { m_Controls->m_outputTextMicronTracker->setHtml("output:"); } void QmitkMicronTrackerWidget::AddOutput(std::string s) { m_Controls->m_outputTextMicronTracker->setHtml(QString(s.c_str())); m_Controls->m_outputTextMicronTracker->verticalScrollBar()->setValue(m_Controls->m_outputTextMicronTracker->verticalScrollBar()->maximum()); } -mitk::TrackingDevice::Pointer QmitkMicronTrackerWidget::ConstructTrackingDevice() +mitk::TrackingDevice::Pointer QmitkMicronTrackerWidget::GetTrackingDevice() { mitk::ClaronTrackingDevice::Pointer newDevice = mitk::ClaronTrackingDevice::New(); if (this->m_MTCalibrationFile.empty()) //if configuration file for MicronTracker is empty: load default { mitk::ClaronTrackingDevice::Pointer tempDevice = mitk::ClaronTrackingDevice::New(); m_MTCalibrationFile = tempDevice->GetCalibrationDir(); Poco::Path myPath = Poco::Path(m_MTCalibrationFile.c_str()); m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } if (!this->m_MTCalibrationFile.empty()) { //extract path from calibration file and set the calibration dir of the device std::string path = itksys::SystemTools::GetFilenamePath(m_MTCalibrationFile); newDevice->SetCalibrationDir(path); } else AddOutput("
Warning: Calibration file is not set!"); return static_cast(newDevice); } void QmitkMicronTrackerWidget::StoreUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; if (this->GetPersistenceService()) // now save the settings using the persistence service { mitk::PropertyList::Pointer propList = this->GetPersistenceService()->GetPropertyList(id); propList->Set("MTCalibrationFile", m_MTCalibrationFile); } else // QSettings as a fallback if the persistence service is not available { QSettings settings; settings.beginGroup(QString::fromStdString(id)); settings.setValue("mTCalibrationFile", QVariant(QString::fromStdString(m_MTCalibrationFile))); settings.endGroup(); } } void QmitkMicronTrackerWidget::LoadUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; if (this->GetPersistenceService()) { mitk::PropertyList::Pointer propList = this->GetPersistenceService()->GetPropertyList(id); if (propList.IsNull()) { MITK_ERROR << "Property list for this UI (" << id << ") is not available, could not load UI settings!"; return; } propList->Get("MTCalibrationFile", m_MTCalibrationFile); } else { // QSettings as a fallback if the persistence service is not available QSettings settings; settings.beginGroup(QString::fromStdString(id)); m_MTCalibrationFile = settings.value("mTCalibrationFile", "").toString().toStdString(); settings.endGroup(); } m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString::fromStdString(m_MTCalibrationFile)); } bool QmitkMicronTrackerWidget::IsDeviceInstalled() { return mitk::ClaronTrackingDevice::New()->IsDeviceInstalled(); } void QmitkMicronTrackerWidget::SetMTCalibrationFileClicked() { std::string filename = QFileDialog::getOpenFileName(nullptr, tr("Open Calibration File"), QmitkIGTCommonHelper::GetLastFileLoadPath(), "*.*").toLatin1().data(); if (filename == "") { return; } else { QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); m_MTCalibrationFile = filename; Poco::Path myPath = Poco::Path(m_MTCalibrationFile.c_str()); m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } } QmitkMicronTrackerWidget* QmitkMicronTrackerWidget::Clone(QWidget* parent) const { QmitkMicronTrackerWidget* clonedWidget = new QmitkMicronTrackerWidget(parent); clonedWidget->Initialize(); clonedWidget->m_MTCalibrationFile = m_MTCalibrationFile; m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString::fromStdString(m_MTCalibrationFile)); return clonedWidget; } diff --git a/Modules/IGTUI/Qmitk/QmitkMicronTrackerWidget.h b/Modules/IGTUI/Qmitk/QmitkMicronTrackerWidget.h index 1eabead4e2..d411761eba 100644 --- a/Modules/IGTUI/Qmitk/QmitkMicronTrackerWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkMicronTrackerWidget.h @@ -1,71 +1,71 @@ /*=================================================================== 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 QmitkMicronTrackerWidget_H #define QmitkMicronTrackerWidget_H #include "ui_QmitkMicronTrackerWidget.h" #include "QmitkAbstractTrackingDeviceWidget.h" /** Documentation: * \brief Implementation of a configuration widget for Micron Tracking Devices. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkMicronTrackerWidget : public QmitkAbstractTrackingDeviceWidget { Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) public: static const std::string VIEW_ID; QmitkMicronTrackerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkMicronTrackerWidget() override; void Initialize() override; signals: protected slots : /* @brief Opens a file dialog. The users sets the calibration file which location is then stored in the member m_MTCalibrationFile.*/ void SetMTCalibrationFileClicked(); private: /// \brief Creation of the connections void CreateConnections(); void CreateQtPartControl(QWidget *parent); protected: QmitkMicronTrackerWidget* Clone(QWidget* parent) const override; std::string m_MTCalibrationFile; Ui::QmitkMicronTrackerWidget* m_Controls; public: void ResetOutput() override; void AddOutput(std::string s) override; - mitk::TrackingDevice::Pointer ConstructTrackingDevice() override; + virtual mitk::TrackingDevice::Pointer GetTrackingDevice() override; void StoreUISettings() override; void LoadUISettings() override; bool IsDeviceInstalled() override; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.cpp index a91be96fa8..e225eab219 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.cpp @@ -1,174 +1,174 @@ /*=================================================================== 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 "QmitkNDIAuroraWidget.h" #include "mitkNDITrackingDevice.h" #include "mitkNDIAuroraTypeInformation.h" #include #include const std::string QmitkNDIAuroraWidget::VIEW_ID = "org.mitk.views.NDIAuroraWidget"; QmitkNDIAuroraWidget::QmitkNDIAuroraWidget(QWidget* parent, Qt::WindowFlags f) : QmitkNDIAbstractDeviceWidget(parent, f) , m_Controls(nullptr) { } void QmitkNDIAuroraWidget::Initialize() { InitializeNDIWidget(); CreateQtPartControl(this); CreateConnections(); } QmitkNDIAuroraWidget::~QmitkNDIAuroraWidget() { delete m_Controls; } void QmitkNDIAuroraWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNDIAuroraWidget; m_Controls->setupUi(parent); } } void QmitkNDIAuroraWidget::CreateConnections() { if (m_Controls) { connect((QObject*)(m_Controls->m_testConnectionAurora), SIGNAL(clicked()), this, SLOT(TestConnection())); connect((QObject*)(m_Controls->m_AutoScanAurora), SIGNAL(clicked()), this, SLOT(AutoScanPorts())); //set a few UI components depending on Windows / Linux #ifdef WIN32 m_Controls->portTypeLabelAurora->setVisible(false); m_Controls->portTypeAurora->setVisible(false); #else m_Controls->comPortLabelAurora->setText("Port Nr:"); m_Controls->m_portSpinBoxAurora->setPrefix(""); #endif } } void QmitkNDIAuroraWidget::ResetOutput() { m_Controls->m_outputTextAurora->setHtml("output:"); } void QmitkNDIAuroraWidget::AddOutput(std::string s) { m_Controls->m_outputTextAurora->setHtml(QString(s.c_str())); m_Controls->m_outputTextAurora->verticalScrollBar()->setValue(m_Controls->m_outputTextAurora->verticalScrollBar()->maximum()); } -mitk::TrackingDevice::Pointer QmitkNDIAuroraWidget::ConstructTrackingDevice() +mitk::TrackingDevice::Pointer QmitkNDIAuroraWidget::GetTrackingDevice() { mitk::NDITrackingDevice::Pointer tempTrackingDevice = mitk::NDITrackingDevice::New(); //get port int port = 0; port = m_Controls->m_portSpinBoxAurora->value(); //build prefix (depends on linux/win) QString prefix = ""; #ifdef WIN32 prefix = "COM"; tempTrackingDevice->SetPortNumber(static_cast(port)); //also set the com port for compatibility #else prefix = m_Controls->portTypeAurora->currentText(); #endif //build port name string QString portName = prefix + QString::number(port); tempTrackingDevice->SetDeviceName(portName.toStdString()); //set the port name tempTrackingDevice->SetBaudRate(mitk::SerialCommunication::BaudRate115200);//set baud rate tempTrackingDevice->SetType(mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()); return static_cast(tempTrackingDevice); } void QmitkNDIAuroraWidget::StoreUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; if (this->GetPersistenceService()) // now save the settings using the persistence service { mitk::PropertyList::Pointer propList = this->GetPersistenceService()->GetPropertyList(id); propList->Set("AuroraPortWin", m_Controls->m_portSpinBoxAurora->value()); propList->Set("PortTypeAurora", m_Controls->portTypeAurora->currentIndex()); } else // QSettings as a fallback if the persistence service is not available { QSettings settings; settings.beginGroup(QString::fromStdString(id)); settings.setValue("portSpinBoxAurora", QVariant(m_Controls->m_portSpinBoxAurora->value())); settings.setValue("portTypeAurora", QVariant(m_Controls->portTypeAurora->currentIndex())); settings.endGroup(); } } void QmitkNDIAuroraWidget::LoadUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; if (this->GetPersistenceService()) { int port = 0; int portType = 0; mitk::PropertyList::Pointer propList = this->GetPersistenceService()->GetPropertyList(id); if (propList.IsNull()) { MITK_ERROR << "Property list for this UI (" << id << ") is not available, could not load UI settings!"; return; } propList->Get("AuroraPortWin", port); propList->Get("PortTypeAurora", portType); this->SetPortTypeToGUI(portType); this->SetPortValueToGUI(port); } else { // QSettings as a fallback if the persistence service is not available QSettings settings; settings.beginGroup(QString::fromStdString(id)); m_Controls->m_portSpinBoxAurora->setValue(settings.value("portSpinBoxAurora", 0).toInt()); m_Controls->portTypeAurora->setCurrentIndex(settings.value("portTypeAurora", 0).toInt()); settings.endGroup(); } } void QmitkNDIAuroraWidget::SetPortValueToGUI(int portValue){ m_Controls->m_portSpinBoxAurora->setValue(portValue); } void QmitkNDIAuroraWidget::SetPortTypeToGUI(int portType){ m_Controls->portTypeAurora->setCurrentIndex(portType); } QmitkNDIAuroraWidget* QmitkNDIAuroraWidget::Clone(QWidget* parent) const { QmitkNDIAuroraWidget* clonedWidget = new QmitkNDIAuroraWidget(parent); clonedWidget->Initialize(); clonedWidget->SetPortTypeToGUI(m_Controls->portTypeAurora->currentIndex()); clonedWidget->SetPortValueToGUI(m_Controls->m_portSpinBoxAurora->value()); return clonedWidget; } diff --git a/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.h b/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.h index 5d4b0951c6..55d47d8e16 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.h @@ -1,62 +1,62 @@ /*=================================================================== 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 QmitkNDIAuroraWidget_H #define QmitkNDIAuroraWidget_H #include "ui_QmitkNDIAuroraWidget.h" #include "QmitkNDIAbstractDeviceWidget.h" /** Documentation: * \brief Implementation of a configuration widget for NDI Aurora Devices. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkNDIAuroraWidget : public QmitkNDIAbstractDeviceWidget { Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) public: static const std::string VIEW_ID; QmitkNDIAuroraWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkNDIAuroraWidget() override; void Initialize() override; private: /// \brief Creation of the connections void CreateConnections(); void CreateQtPartControl(QWidget *parent); protected: void ResetOutput() override; void AddOutput(std::string s) override; - mitk::TrackingDevice::Pointer ConstructTrackingDevice() override; + virtual mitk::TrackingDevice::Pointer GetTrackingDevice() override; void StoreUISettings() override; void LoadUISettings() override; void SetPortValueToGUI(int portValue) override; void SetPortTypeToGUI(int portType) override; QmitkNDIAuroraWidget* Clone(QWidget* parent) const override; Ui::QmitkNDIAuroraWidget* m_Controls; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.ui b/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.ui index e0dd4013c3..24cc19d363 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNDIAuroraWidget.ui @@ -1,190 +1,177 @@ QmitkNDIAuroraWidget 0 0 400 153 <!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:'MS Shell Dlg 2'; font-size:8pt; 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=" text-decoration: underline;">Aurora</span></p></body></html> Com Port: COM Auto Scan Qt::Horizontal 40 20 Port Type: /dev/ttyUSB /dev/ttyS Qt::Horizontal 40 20 Qt::Vertical 20 40 120 50 120 80 <!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:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 Test Connection - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.cpp index 13cce48813..78ee14ea62 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.cpp @@ -1,197 +1,197 @@ /*=================================================================== 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 "QmitkNDIPolarisWidget.h" #include "mitkNDITrackingDevice.h" #include "mitkNDIPolarisTypeInformation.h" #include #include const std::string QmitkNDIPolarisWidget::VIEW_ID = "org.mitk.views.NDIPolarisWidget"; QmitkNDIPolarisWidget::QmitkNDIPolarisWidget(QWidget* parent, Qt::WindowFlags f) : QmitkNDIAbstractDeviceWidget(parent, f) , m_Controls(nullptr) { } void QmitkNDIPolarisWidget::Initialize() { InitializeNDIWidget(); CreateQtPartControl(this); CreateConnections(); } QmitkNDIPolarisWidget::~QmitkNDIPolarisWidget() { delete m_Controls; } void QmitkNDIPolarisWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNDIPolarisWidget; m_Controls->setupUi(parent); } } void QmitkNDIPolarisWidget::CreateConnections() { if (m_Controls) { connect((QObject*)(m_Controls->m_testConnectionPolaris), SIGNAL(clicked()), this, SLOT(TestConnection())); connect((QObject*)(m_Controls->m_AutoScanPolaris), SIGNAL(clicked()), this, SLOT(AutoScanPorts())); //set a few UI components depending on Windows / Linux #ifdef WIN32 m_Controls->portTypeLabelPolaris->setVisible(false); m_Controls->portTypePolaris->setVisible(false); #else m_Controls->m_comPortLabelPolaris->setText("Port Nr:"); m_Controls->m_portSpinBoxPolaris->setPrefix(""); #endif } } void QmitkNDIPolarisWidget::ResetOutput() { m_Controls->m_outputTextPolaris->setHtml("output:"); } void QmitkNDIPolarisWidget::AddOutput(std::string s) { m_Controls->m_outputTextPolaris->setHtml(QString(s.c_str())); m_Controls->m_outputTextPolaris->verticalScrollBar()->setValue(m_Controls->m_outputTextPolaris->verticalScrollBar()->maximum()); } -mitk::TrackingDevice::Pointer QmitkNDIPolarisWidget::ConstructTrackingDevice() +mitk::TrackingDevice::Pointer QmitkNDIPolarisWidget::GetTrackingDevice() { mitk::NDITrackingDevice::Pointer tempTrackingDevice = mitk::NDITrackingDevice::New(); //get port int port = 0; port = m_Controls->m_portSpinBoxPolaris->value(); //build prefix (depends on linux/win) QString prefix = ""; #ifdef WIN32 prefix = "COM"; tempTrackingDevice->SetPortNumber(static_cast(port)); //also set the com port for compatibility tempTrackingDevice->SetIlluminationActivationRate(GetPolarisFrameRate()); #else prefix = m_Controls->portTypePolaris->currentText(); tempTrackingDevice->SetIlluminationActivationRate(GetPolarisFrameRate()); #endif //build port name string QString portName = prefix + QString::number(port); tempTrackingDevice->SetDeviceName(portName.toStdString()); //set the port name tempTrackingDevice->SetBaudRate(mitk::SerialCommunication::BaudRate115200);//set baud rate tempTrackingDevice->SetType(mitk::NDIPolarisTypeInformation::GetTrackingDeviceName()); return static_cast(tempTrackingDevice); } void QmitkNDIPolarisWidget::StoreUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; if (this->GetPersistenceService()) // now save the settings using the persistence service { mitk::PropertyList::Pointer propList = this->GetPersistenceService()->GetPropertyList(id); propList->Set("PolarisPortWin", m_Controls->m_portSpinBoxPolaris->value()); propList->Set("PortTypePolaris", m_Controls->portTypePolaris->currentIndex()); propList->Set("PolarisFrameRate", GetPolarisFrameRate()); } else // QSettings as a fallback if the persistence service is not available { QSettings settings; settings.beginGroup(QString::fromStdString(id)); settings.setValue("portSpinBoxPolaris", QVariant(m_Controls->m_portSpinBoxPolaris->value())); settings.setValue("portTypePolaris", QVariant(m_Controls->portTypePolaris->currentIndex())); settings.setValue("PolarisFrameRate", QVariant(GetPolarisFrameRate())); settings.endGroup(); } } void QmitkNDIPolarisWidget::LoadUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; if (this->GetPersistenceService()) { int port = 0; int portType = 0; int polarisFrameRate = 0; mitk::PropertyList::Pointer propList = this->GetPersistenceService()->GetPropertyList(id); if (propList.IsNull()) { MITK_ERROR << "Property list for this UI (" << id << ") is not available, could not load UI settings!"; return; } propList->Get("PolarisPortWin", port); propList->Get("PortTypePolaris", portType); propList->Get("PolarisFrameRate", polarisFrameRate); this->SetPortTypeToGUI(portType); this->SetPortValueToGUI(port); m_Controls->m_frameRateComboBoxPolaris->setCurrentIndex((int)(polarisFrameRate / 30)); } else { // QSettings as a fallback if the persistence service is not available QSettings settings; settings.beginGroup(QString::fromStdString(id)); m_Controls->m_portSpinBoxPolaris->setValue(settings.value("portSpinBoxPolaris", 0).toInt()); m_Controls->portTypePolaris->setCurrentIndex(settings.value("portTypePolaris", 0).toInt()); //framerates 20,30,60 --> divided by 30 = 0,1,2 --> index of combobox m_Controls->m_frameRateComboBoxPolaris->setCurrentIndex((int)(settings.value("PolarisFrameRate", 0).toInt() / 30)); settings.endGroup(); } } mitk::IlluminationActivationRate QmitkNDIPolarisWidget::GetPolarisFrameRate() { mitk::IlluminationActivationRate frameRate = mitk::Hz20; QString comboBox = m_Controls->m_frameRateComboBoxPolaris->currentText(); if (comboBox == "20 Hz") frameRate = mitk::Hz20; else if (comboBox == "30 Hz") frameRate = mitk::Hz30; else if (comboBox == "60 Hz") frameRate = mitk::Hz60; return frameRate; } void QmitkNDIPolarisWidget::SetPortValueToGUI(int portValue){ m_Controls->m_portSpinBoxPolaris->setValue(portValue); } void QmitkNDIPolarisWidget::SetPortTypeToGUI(int portType){ m_Controls->portTypePolaris->setCurrentIndex(portType); } QmitkNDIPolarisWidget* QmitkNDIPolarisWidget::Clone(QWidget* parent) const { QmitkNDIPolarisWidget* clonedWidget = new QmitkNDIPolarisWidget(parent); clonedWidget->Initialize(); clonedWidget->SetPortTypeToGUI(m_Controls->portTypePolaris->currentIndex()); clonedWidget->SetPortValueToGUI(m_Controls->m_portSpinBoxPolaris->value()); clonedWidget->m_Controls->m_frameRateComboBoxPolaris->setCurrentIndex(m_Controls->m_frameRateComboBoxPolaris->currentIndex()); return clonedWidget; } diff --git a/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.h b/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.h index 891308aa1b..1c78105bc7 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.h @@ -1,71 +1,71 @@ /*=================================================================== 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 QmitkNDIPolarisWidget_H #define QmitkNDIPolarisWidget_H #include "ui_QmitkNDIPolarisWidget.h" #include "QmitkNDIAbstractDeviceWidget.h" /** Documentation: * \brief Implementation of a configuration widget for NDI Polaris Devices. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkNDIPolarisWidget : public QmitkNDIAbstractDeviceWidget { Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) public: static const std::string VIEW_ID; QmitkNDIPolarisWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkNDIPolarisWidget() override; void Initialize() override; signals: protected slots : private: /// \brief Creation of the connections void CreateConnections(); void CreateQtPartControl(QWidget *parent); protected: /** @return Returns the frame rate set in the m_frameRatePolaris ComboBox */ mitk::IlluminationActivationRate GetPolarisFrameRate(); Ui::QmitkNDIPolarisWidget* m_Controls; void SetPortValueToGUI(int portValue) override; void SetPortTypeToGUI(int portType) override; QmitkNDIPolarisWidget* Clone(QWidget* parent) const override; public: void ResetOutput() override; void AddOutput(std::string s) override; - mitk::TrackingDevice::Pointer ConstructTrackingDevice() override; + virtual mitk::TrackingDevice::Pointer GetTrackingDevice() override; void StoreUISettings() override; void LoadUISettings() override; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.ui b/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.ui index 44dc177df1..6b05398793 100644 --- a/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNDIPolarisWidget.ui @@ -1,243 +1,230 @@ QmitkNDIPolarisWidget 0 0 408 191 <!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:'MS Shell Dlg 2'; font-size:8pt; 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=" text-decoration: underline;">Polaris</span></p></body></html> Com Port: COM Auto Scan Qt::Horizontal 40 20 Port Type: /dev/ttyUSB /dev/ttyS Qt::Horizontal 40 20 Frame Rate: 20 Hz 30 Hz 60 Hz Qt::Horizontal 40 20 Qt::Vertical 20 40 120 50 120 80 120 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:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; color:#ffffff;">NDI Polaris selected</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 Test Connection - - - - Qt::Vertical - - - - 20 - 40 - - - - diff --git a/Modules/IGTUI/Qmitk/QmitkNPOptitrackWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNPOptitrackWidget.cpp index 47f43dbd0e..cc690ce35c 100644 --- a/Modules/IGTUI/Qmitk/QmitkNPOptitrackWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNPOptitrackWidget.cpp @@ -1,122 +1,122 @@ /*=================================================================== 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 "QmitkNPOptitrackWidget.h" #include "mitkOptitrackTrackingDevice.h" #include "mitkNPOptitrackTrackingTypeInformation.h" #include "QmitkIGTCommonHelper.h" #include #include #include const std::string QmitkNPOptitrackWidget::VIEW_ID = "org.mitk.views.NPOptitrackWidget"; QmitkNPOptitrackWidget::QmitkNPOptitrackWidget(QWidget* parent, Qt::WindowFlags f) : QmitkAbstractTrackingDeviceWidget(parent, f) , m_Controls(nullptr) { } void QmitkNPOptitrackWidget::Initialize() { InitializeSuperclassWidget(); CreateQtPartControl(this); CreateConnections(); } QmitkNPOptitrackWidget::~QmitkNPOptitrackWidget() { delete m_Controls; } void QmitkNPOptitrackWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNPOptitrackWidget; m_Controls->setupUi(parent); } } void QmitkNPOptitrackWidget::CreateConnections() { if (m_Controls) { connect((QObject*)(m_Controls->m_testConnectionOptitrack), SIGNAL(clicked()), this, SLOT(TestConnection())); connect((QObject*)(m_Controls->m_SetOptitrackCalibrationFile), SIGNAL(clicked()), this, SLOT(SetOptitrackCalibrationFileClicked())); } } void QmitkNPOptitrackWidget::ResetOutput() { m_Controls->m_outputTextOptitrack->setHtml("output:"); } void QmitkNPOptitrackWidget::AddOutput(std::string s) { m_Controls->m_outputTextOptitrack->setHtml(QString(s.c_str())); m_Controls->m_outputTextOptitrack->verticalScrollBar()->setValue(m_Controls->m_outputTextOptitrack->verticalScrollBar()->maximum()); } -mitk::TrackingDevice::Pointer QmitkNPOptitrackWidget::ConstructTrackingDevice() +mitk::TrackingDevice::Pointer QmitkNPOptitrackWidget::GetTrackingDevice() { // Create the Tracking Device mitk::OptitrackTrackingDevice::Pointer tempTrackingDevice = mitk::OptitrackTrackingDevice::New(); // Set the calibration File tempTrackingDevice->SetCalibrationPath(m_OptitrackCalibrationFile); //Set the camera parameters tempTrackingDevice->SetExp(m_Controls->m_OptitrackExp->value()); tempTrackingDevice->SetLed(m_Controls->m_OptitrackLed->value()); tempTrackingDevice->SetThr(m_Controls->m_OptitrackThr->value()); tempTrackingDevice->SetType(mitk::NPOptitrackTrackingTypeInformation::GetTrackingDeviceName()); return static_cast(tempTrackingDevice); } bool QmitkNPOptitrackWidget::IsDeviceInstalled() { return mitk::OptitrackTrackingDevice::New()->IsDeviceInstalled(); } void QmitkNPOptitrackWidget::SetOptitrackCalibrationFileClicked() { std::string filename = QFileDialog::getOpenFileName(nullptr, tr("Open Calibration File"), QmitkIGTCommonHelper::GetLastFileLoadPath(), "*.*").toLatin1().data(); if (filename == "") { return; } else { QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); m_OptitrackCalibrationFile = filename; Poco::Path myPath = Poco::Path(m_OptitrackCalibrationFile.c_str()); m_Controls->m_OptitrackCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } } QmitkNPOptitrackWidget* QmitkNPOptitrackWidget::Clone(QWidget* parent) const { QmitkNPOptitrackWidget* clonedWidget = new QmitkNPOptitrackWidget(parent); clonedWidget->Initialize(); clonedWidget->m_OptitrackCalibrationFile = this->m_OptitrackCalibrationFile; clonedWidget->m_Controls->m_OptitrackCalibrationFile->setText(m_Controls->m_OptitrackCalibrationFile->text()); clonedWidget->m_Controls->m_OptitrackExp->setValue(m_Controls->m_OptitrackExp->value()); clonedWidget->m_Controls->m_OptitrackLed->setValue(m_Controls->m_OptitrackLed->value()); clonedWidget->m_Controls->m_OptitrackThr->setValue(m_Controls->m_OptitrackThr->value()); return clonedWidget; } diff --git a/Modules/IGTUI/Qmitk/QmitkNPOptitrackWidget.h b/Modules/IGTUI/Qmitk/QmitkNPOptitrackWidget.h index 409c2cde51..5bd2f0e64a 100644 --- a/Modules/IGTUI/Qmitk/QmitkNPOptitrackWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkNPOptitrackWidget.h @@ -1,68 +1,68 @@ /*=================================================================== 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 QmitkNPOptitrackWidget_H #define QmitkNPOptitrackWidget_H #include "ui_QmitkNPOptitrackWidget.h" #include "QmitkAbstractTrackingDeviceWidget.h" /** Documentation: * \brief Implementation of a configuration widget for NP Optitrack Tracking Devices. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkNPOptitrackWidget : public QmitkAbstractTrackingDeviceWidget { Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) public: static const std::string VIEW_ID; QmitkNPOptitrackWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkNPOptitrackWidget() override; void Initialize() override; signals: protected slots : /* @brief Opens a file dialog. The users sets the calibration file which location is then stored in the member m_OptitrackCalibrationFile.*/ void SetOptitrackCalibrationFileClicked(); private: /// \brief Creation of the connections void CreateConnections(); void CreateQtPartControl(QWidget *parent); protected: QmitkNPOptitrackWidget* Clone(QWidget* parent) const override; std::string m_OptitrackCalibrationFile; Ui::QmitkNPOptitrackWidget* m_Controls; public: void ResetOutput() override; void AddOutput(std::string s) override; - mitk::TrackingDevice::Pointer ConstructTrackingDevice() override; + mitk::TrackingDevice::Pointer GetTrackingDevice() override; bool IsDeviceInstalled() override; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp index 4eb7d3b3b5..0419e4ca9e 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp @@ -1,140 +1,137 @@ /*=================================================================== 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 "QmitkNavigationDataSourceSelectionWidget.h" //mitk headers #include #include #include QmitkNavigationDataSourceSelectionWidget::QmitkNavigationDataSourceSelectionWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); CreateConnections(); } QmitkNavigationDataSourceSelectionWidget::~QmitkNavigationDataSourceSelectionWidget() { } void QmitkNavigationDataSourceSelectionWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationDataSourceSelectionWidgetControls; m_Controls->setupUi(parent); std::string empty = ""; m_Controls->m_NavigationDataSourceWidget->Initialize(mitk::NavigationDataSource::US_PROPKEY_DEVICENAME,empty); } } void QmitkNavigationDataSourceSelectionWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_NavigationDataSourceWidget), SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(NavigationDataSourceSelected(us::ServiceReferenceU)) ); connect((QObject*)(m_Controls->m_ToolView), SIGNAL(currentRowChanged(int)), this, SLOT(NavigationToolSelected(int))); } } void QmitkNavigationDataSourceSelectionWidget::NavigationToolSelected(int selection) { emit NavigationToolSelected(this->m_CurrentStorage->GetTool(selection)); } void QmitkNavigationDataSourceSelectionWidget::NavigationDataSourceSelected(us::ServiceReferenceU s) { if (!s) //no device selected { //reset everything m_CurrentSource = nullptr; m_CurrentStorage = nullptr; emit NavigationDataSourceSelected(m_CurrentSource); return; } // Get Source us::ModuleContext* context = us::GetModuleContext(); m_CurrentSource = context->GetService(s); - std::string id = s.GetProperty(mitk::NavigationDataSource::US_PROPKEY_ID).ToString(); // clear tool list before filling it m_Controls->m_ToolView->clear(); //Fill tool list MITK_INFO<<"no outputs: "<GetNumberOfOutputs(); for(std::size_t i = 0; i < m_CurrentSource->GetNumberOfOutputs(); i++) { new QListWidgetItem(tr(m_CurrentSource->GetOutput(i)->GetName()), m_Controls->m_ToolView); } - - // Create Filter for ToolStorage - std::string filter = "("+ mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")"; - // Get Storage + std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + m_CurrentSource->GetMicroserviceID() + ")"; std::vector > refs = context->GetServiceReferences(filter); if (refs.empty()) return; //no storage was found m_CurrentStorage = context->GetService(refs.front()); + if (m_CurrentStorage.IsNull()) { MITK_WARN << "Found an invalid storage object!"; return; } - if (m_CurrentStorage->GetToolCount() != static_cast(m_CurrentSource->GetNumberOfOutputs())) //there is something wrong with the storage + if (m_CurrentStorage->GetToolCount() != m_CurrentSource->GetNumberOfOutputs()) //there is something wrong with the storage { MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This storage won't be used because it isn't the right one."; m_CurrentStorage = nullptr; } emit NavigationDataSourceSelected(m_CurrentSource); } mitk::NavigationDataSource::Pointer QmitkNavigationDataSourceSelectionWidget::GetSelectedNavigationDataSource() { return this->m_CurrentSource; } int QmitkNavigationDataSourceSelectionWidget::GetSelectedToolID() { return this->m_Controls->m_ToolView->currentIndex().row(); } mitk::NavigationTool::Pointer QmitkNavigationDataSourceSelectionWidget::GetSelectedNavigationTool() { if (this->m_CurrentStorage.IsNull()) return nullptr; - if (m_Controls->m_ToolView->currentIndex().row() >= m_CurrentStorage->GetToolCount()) return nullptr; + if ((m_Controls->m_ToolView->currentIndex().row() < 0) || (static_cast(m_Controls->m_ToolView->currentIndex().row()) >= m_CurrentStorage->GetToolCount())) return nullptr; return this->m_CurrentStorage->GetTool(m_Controls->m_ToolView->currentIndex().row()); } mitk::NavigationToolStorage::Pointer QmitkNavigationDataSourceSelectionWidget::GetNavigationToolStorageOfSource() { return this->m_CurrentStorage; } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp deleted file mode 100644 index c39a795386..0000000000 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/*=================================================================== - -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 "QmitkNavigationToolCreationAdvancedWidget.h" -#include "QmitkNavigationToolCreationWidget.h" - -// mitk includes -#include -#include -#include - -// vtk includes -#include -#include - -const std::string QmitkNavigationToolCreationAdvancedWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationadvancedwidget"; - -QmitkNavigationToolCreationAdvancedWidget::QmitkNavigationToolCreationAdvancedWidget(QWidget* parent, Qt::WindowFlags f) - : QDialog(parent, f), m_Controls(nullptr), m_DataStorage(nullptr), m_ToolTipSurface(nullptr), m_ManipulatedToolTip(nullptr), - m_SurfaceNodeName("") -{ - CreateQtPartControl(this); - CreateConnections(); -} - -QmitkNavigationToolCreationAdvancedWidget::~QmitkNavigationToolCreationAdvancedWidget() -{ -} - -void QmitkNavigationToolCreationAdvancedWidget::CreateQtPartControl(QWidget *parent) - { - if (!m_Controls) - { - // create GUI widgets - m_Controls = new Ui::QmitkNavigationToolCreationAdvancedWidgetControls; - m_Controls->setupUi(parent); - } - } - -void QmitkNavigationToolCreationAdvancedWidget::CreateConnections() - { - if ( m_Controls ) - { - connect( (QObject*)(this), SIGNAL(finished(int)), this, SLOT(OnClose())); - connect( (QObject*)(m_Controls->m_InteractiveTransformation), SIGNAL(ApplyManipulatedToolTip()), this, SLOT(OnApplyManipulatedToolTip())); - } - } - -void QmitkNavigationToolCreationAdvancedWidget::OnClose() -{ - //clean the data storage - if(m_DataStorage->Exists(m_DataStorage->GetNamedNode("StandardToolTip"))) - { - m_DataStorage->Remove(m_DataStorage->GetNamedNode("StandardToolTip")); - } - - if(m_DataStorage.IsNotNull() && m_DataStorage->Exists(m_DataStorage->GetNamedNode("ManipulatedToolTip"))) - { - m_DataStorage->Remove(m_DataStorage->GetNamedNode("ManipulatedToolTip")); - } - - emit DialogCloseRequested(); -} - -void QmitkNavigationToolCreationAdvancedWidget::SetDataStorage( mitk::DataStorage::Pointer dataStorage ) -{ - m_DataStorage = dataStorage; -} - -void QmitkNavigationToolCreationAdvancedWidget::ReInitialize() -{ - if (m_DataStorage.IsNull()) return; - - //reset some variables - m_ManipulatedToolTip = nullptr; - m_ToolTipSurface = nullptr; - m_SurfaceNodeName = ""; - mitk::Geometry3D::Pointer geo3d = mitk::Geometry3D::New(); - mitk::BaseGeometry::Pointer emptyGeo = dynamic_cast(geo3d.GetPointer()); - m_Controls->m_InteractiveTransformation->SetGeometry(emptyGeo,emptyGeo); - - //call initialization method - this->RetrieveAndInitializeDataForTooltipManipulation(); - - //care for new data nodes - mitk::DataNode::Pointer manipulatedTipNode = nullptr; - if(!m_DataStorage->Exists(m_DataStorage->GetNamedNode("ManipulatedToolTip"))) - { - manipulatedTipNode = mitk::DataNode::New(); - manipulatedTipNode->SetData(m_ManipulatedToolTip); - manipulatedTipNode->SetName("ManipulatedToolTip"); - manipulatedTipNode->SetColor(1.0, 0.0, 0.0); - manipulatedTipNode->SetOpacity(0.5); - m_DataStorage->Add(manipulatedTipNode); - } - else - { - manipulatedTipNode = m_DataStorage->GetNamedNode("ManipulatedToolTip"); - manipulatedTipNode->SetData(m_ManipulatedToolTip); - } - - // reinit the views with the new nodes - mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); -} - -void QmitkNavigationToolCreationAdvancedWidget::RetrieveAndInitializeDataForTooltipManipulation() -{ - // we need the tooltip surface (point or stl) - emit RetrieveDataForManualToolTipManipulation(); - - if(m_ToolTipSurface.IsNotNull()) - { - mitk::DataNode::Pointer toolTipNode = nullptr; - - if(m_SurfaceNodeName.empty()) - { - m_SurfaceNodeName = "StandardToolTip"; - } - - if(!m_DataStorage->Exists(m_DataStorage->GetNamedNode(m_SurfaceNodeName))) - { - toolTipNode = mitk::DataNode::New(); - toolTipNode->SetName(m_SurfaceNodeName); - toolTipNode->SetData(m_ToolTipSurface); - m_DataStorage->Add(toolTipNode); - - } - else - { - toolTipNode = m_DataStorage->GetNamedNode(m_SurfaceNodeName); - toolTipNode->SetData(m_ToolTipSurface); - } - - m_ManipulatedToolTip = m_ToolTipSurface->Clone(); - - mitk::BaseGeometry::Pointer defaultGeo = dynamic_cast (mitk::Geometry3D::New().GetPointer()); - defaultGeo->SetIndexToWorldTransform(m_DefaultToolTip); - - m_Controls->m_InteractiveTransformation->SetGeometry(m_ManipulatedToolTip->GetGeometry(),defaultGeo); - } - else - { - mitkThrow() << "No tooltip surface specified, operation aborted"; - } -} - -void QmitkNavigationToolCreationAdvancedWidget::SetDefaultTooltip(mitk::AffineTransform3D::Pointer defaultToolTip) -{ - m_DefaultToolTip = defaultToolTip; -} - -void QmitkNavigationToolCreationAdvancedWidget::SetToolTipSurface( bool cone, mitk::DataNode::Pointer node /*= nullptr*/ ) -{ - m_ToolTipSurface = nullptr; - if(cone) - { - m_ToolTipSurface = mitk::Surface::New(); - vtkConeSource *vtkData = vtkConeSource::New(); - vtkData->SetAngle(5.0); - vtkData->SetResolution(50); - vtkData->SetHeight(6.0f); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - - vtkData->Update(); - m_ToolTipSurface->SetVtkPolyData(vtkData->GetOutput()); - - vtkData->Delete(); - m_SurfaceNodeName =""; - } - else if(!cone && node.IsNotNull()) - { - m_ToolTipSurface = dynamic_cast(node->GetData()); - m_SurfaceNodeName = node->GetName(); - } -} - -void QmitkNavigationToolCreationAdvancedWidget::OnApplyManipulatedToolTip() -{ - //save manipulated surface object, which holds the tooltip as geometry - m_ManipulatedToolTip = dynamic_cast(m_DataStorage->GetNamedNode("ManipulatedToolTip")->GetData()->Clone().GetPointer()); - //then close the window - OnClose(); -} - -mitk::AffineTransform3D::Pointer QmitkNavigationToolCreationAdvancedWidget::GetManipulatedToolTip() -{ - mitk::AffineTransform3D::Pointer returnValue = mitk::AffineTransform3D::New(); - if (m_ManipulatedToolTip.IsNotNull()) returnValue = m_ManipulatedToolTip->GetGeometry()->GetIndexToWorldTransform(); - else returnValue->SetIdentity(); - return returnValue; -} diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.h deleted file mode 100644 index d770553b75..0000000000 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidget.h +++ /dev/null @@ -1,109 +0,0 @@ -/*=================================================================== - -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 QmitkNavigationToolCreationAdvancedWidget_H -#define QmitkNavigationToolCreationAdvancedWidget_H - -//QT headers -#include - -//Mitk headers -#include "MitkIGTUIExports.h" -#include "mitkDataStorage.h" -#include "mitkSurface.h" - -// Qmitk headers -#include "QmitkInteractiveTransformationWidget.h" - -//ui header -#include "ui_QmitkNavigationToolCreationAdvancedWidgetControls.h" - - /** Documentation: - * \brief An object of this class offers an UI to modify a tooltip of an IGT navigation tool. - * - * The user can modify translation and orientation of the tooltip. The current tooltip - * might be provided as default data, then the widget starts with the given values for - * translation and orientation. - * - * As long as the UI is open, there will also be a (temporary) preview data node, so - * the user can see the effect of his manipulations. - * - * Please call the method SetDataStorage to initialize the UI with the data storage - * of the current application. - * - * \ingroup IGTUI - */ -class MITKIGTUI_EXPORT QmitkNavigationToolCreationAdvancedWidget : public QDialog -{ - Q_OBJECT - - public: - static const std::string VIEW_ID; - - QmitkNavigationToolCreationAdvancedWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); - ~QmitkNavigationToolCreationAdvancedWidget() override; - - /** Initializes the view with the a data storage. This data storage is needed for the - * preview node during tooltip manipulation. - */ - void SetDataStorage(mitk::DataStorage::Pointer dataStorage); - - /** Sets the current tooltip surface, also for preview purposes (the preview node - * will be a clone of this surface). If there is no surface, a simple cone can be used. - * Please set cone to true in this case. - */ - void SetToolTipSurface(bool cone, mitk::DataNode::Pointer node = nullptr); - - /** Sets a default tooltip transform, which will shown in the beginning. - * If the windows is already open, the transform will be set to default - * immediately. - */ - void SetDefaultTooltip(mitk::AffineTransform3D::Pointer defaultToolTip); - - /** @return Returns the manipulated tip transform. Returns an identity transform if - * nothing was manipulated. - */ - mitk::AffineTransform3D::Pointer GetManipulatedToolTip(); - - /** Reinitializes the view, e.g. after it was closed. - */ - void ReInitialize(); - -signals: - void DialogCloseRequested(); - void RetrieveDataForManualToolTipManipulation(); - - protected slots: - void OnClose(); - void OnApplyManipulatedToolTip(); - - protected: - - virtual void CreateConnections(); - - virtual void CreateQtPartControl(QWidget *parent); - void RetrieveAndInitializeDataForTooltipManipulation(); - // Member variables - Ui::QmitkNavigationToolCreationAdvancedWidgetControls* m_Controls; - - mitk::AffineTransform3D::Pointer m_DefaultToolTip; - - mitk::DataStorage::Pointer m_DataStorage; - mitk::Surface::Pointer m_ToolTipSurface; - mitk::Surface::Pointer m_ManipulatedToolTip; ///< manipulated surface object, which holds the tooltip as geometry - std::string m_SurfaceNodeName; -}; -#endif // QmitkNavigationToolCreationAdvancedWidget_H diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui deleted file mode 100644 index d3db69929f..0000000000 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui +++ /dev/null @@ -1,52 +0,0 @@ - - - QmitkNavigationToolCreationAdvancedWidgetControls - - - - 0 - 0 - 462 - 429 - - - - Form - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 400 - - - - - - - - - QmitkInteractiveTransformationWidget - QWidget -
QmitkInteractiveTransformationWidget.h
- 1 -
-
- - -
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp index ceae19d863..545095bfa5 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp @@ -1,347 +1,400 @@ /*=================================================================== 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 "QmitkNavigationToolCreationWidget.h" //mitk headers #include #include #include #include #include "mitkTrackingDeviceTypeCollection.h" //qt headers #include #include -#include #include #include +#include //poco headers #include -// vtk -#include -#include - const std::string QmitkNavigationToolCreationWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationwizardwidget"; QmitkNavigationToolCreationWidget::QmitkNavigationToolCreationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { + m_Controls = NULL; + m_ToolToBeEdited = mitk::NavigationTool::New(); + m_FinalTool = mitk::NavigationTool::New(); + m_ToolTransformationWidget = new QmitkInteractiveTransformationWidget(); m_Controls = nullptr; - m_AdvancedWidget = new QmitkNavigationToolCreationAdvancedWidget(this); - m_AdvancedWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - m_AdvancedWidget->setWindowTitle("Tool Creation Advanced Options"); - m_AdvancedWidget->setModal(false); + CreateQtPartControl(this); CreateConnections(); -RefreshTrackingDeviceCollection(); + this->InitializeUIToolLandmarkLists(); + Initialize(nullptr, ""); + + //Default values, which are not stored in tool + m_Controls->m_CalibrationFileName->setText("none"); + m_Controls->m_Surface_Use_Sphere->setChecked(true); + + m_Controls->m_CalibrationLandmarksList->EnableEditButton(false); + m_Controls->m_RegistrationLandmarksList->EnableEditButton(false); + + RefreshTrackingDeviceCollection(); + + OnSurfaceUseToggled(); } QmitkNavigationToolCreationWidget::~QmitkNavigationToolCreationWidget() { m_Controls->m_CalibrationLandmarksList->SetPointSetNode(nullptr); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(nullptr); - delete m_AdvancedWidget; + delete m_ToolTransformationWidget; } void QmitkNavigationToolCreationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolCreationWidgetControls; m_Controls->setupUi(parent); } } void QmitkNavigationToolCreationWidget::CreateConnections() { - if ( m_Controls ) + if (m_Controls) { - connect( (QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel()) ); - connect( (QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished()) ); - connect( (QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface()) ); - connect( (QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile()) ); - connect( (QObject*)(m_Controls->m_ShowAdvancedOptionsPB), SIGNAL(toggled(bool)), this, SLOT(OnShowAdvancedOptions(bool)) ); - connect( (QObject*)(m_AdvancedWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessDialogCloseRequest()) ); - connect( (QObject*)(m_AdvancedWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation()) ); - - connect( m_Controls->m_Surface_Use_Other, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceUseOtherToggled(bool))); + connect((QObject*)(m_Controls->m_TrackingDeviceTypeChooser), SIGNAL(currentIndexChanged(int)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolNameEdit), SIGNAL(textChanged(const QString)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolTypeChooser), SIGNAL(currentIndexChanged(int)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_IdentifierEdit), SIGNAL(textChanged(const QString)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_SerialNumberEdit), SIGNAL(textChanged(const QString)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolAxisX), SIGNAL(valueChanged(int)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolAxisY), SIGNAL(valueChanged(int)), this, SLOT(GetValuesFromGuiElements())); + connect((QObject*)(m_Controls->m_ToolAxisZ), SIGNAL(valueChanged(int)), this, SLOT(GetValuesFromGuiElements())); + + //Buttons + connect((QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile())); + connect(m_Controls->m_Surface_Use_Other, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceUseToggled())); + connect(m_Controls->m_Surface_Load_File, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceUseToggled())); + connect((QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface())); + connect((QObject*)(m_Controls->m_EditToolTip), SIGNAL(clicked()), this, SLOT(OnEditToolTip())); + + connect((QObject*)(m_ToolTransformationWidget), SIGNAL(EditToolTipFinished(mitk::AffineTransform3D::Pointer)), this, + SLOT(OnEditToolTipFinished(mitk::AffineTransform3D::Pointer))); + + connect((QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel())); + connect((QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished())); } } void QmitkNavigationToolCreationWidget::Initialize(mitk::DataStorage* dataStorage, const std::string& supposedIdentifier, const std::string& supposedName) { m_DataStorage = dataStorage; - //initialize UI components m_Controls->m_SurfaceChooser->SetDataStorage(m_DataStorage); m_Controls->m_SurfaceChooser->SetAutoSelectNewItems(true); m_Controls->m_SurfaceChooser->SetPredicate(mitk::NodePredicateDataType::New("Surface")); - //set default data - m_Controls->m_ToolNameEdit->setText(supposedName.c_str()); - m_Controls->m_CalibrationFileName->setText("none"); - m_Controls->m_Surface_Use_Sphere->setChecked(true); - m_AdvancedWidget->SetDataStorage(m_DataStorage); - m_Controls->m_IdentifierEdit->setText(supposedIdentifier.c_str()); - this->InitializeUIToolLandmarkLists(); - m_Controls->m_CalibrationLandmarksList->EnableEditButton(false); - m_Controls->m_RegistrationLandmarksList->EnableEditButton(false); + //Create new tool, which should be edited/created + m_ToolToBeEdited = nullptr;//Reset + m_ToolToBeEdited = mitk::NavigationTool::New();//Reinitialize + m_ToolToBeEdited->SetIdentifier(supposedIdentifier); + + m_ToolToBeEdited->GetDataNode()->SetName(supposedName); + + this->SetDefaultData(m_ToolToBeEdited); } -void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool) +void QmitkNavigationToolCreationWidget::ShowToolPreview(std::string _name) { - int index = m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(type)); + m_DataStorage->Add(m_ToolToBeEdited->GetDataNode()); + m_ToolToBeEdited->GetDataNode()->SetName(_name); - if (index >= 0) - { - m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(index); - } -} + //change color to blue + m_ToolToBeEdited->GetDataNode()->SetProperty("color", mitk::ColorProperty::New(0, 0, 1)); + //Global Reinit to show new tool + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); +} -mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool() +void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool) { - return m_CreatedTool; -} + //Set Members. This can either be the new initialized tool from call of Initialize() or a tool which already exists in the toolStorage + m_ToolToBeEdited = DefaultTool->Clone(); -//################################################################################## -//############################## slots ############################ -//################################################################################## + //Set all gui variables + SetGuiElements(); +} -void QmitkNavigationToolCreationWidget::OnFinished() +void QmitkNavigationToolCreationWidget::SetGuiElements() { - //here we create a new tool - m_CreatedTool = mitk::NavigationTool::New(); - - //create DataNode... - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - if(m_Controls->m_Surface_Use_Sphere->isChecked()) - { - //create small sphere and use it as surface - mitk::Surface::Pointer mySphere = mitk::Surface::New(); - vtkConeSource *vtkData = vtkConeSource::New(); - vtkData->SetAngle(5.0); - vtkData->SetResolution(50); - vtkData->SetHeight(6.0f); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - mySphere->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - newNode->SetData(mySphere); - } - else + //Block signals, so that we don't call SetGuiElements again. This is undone at the end of this function! + m_Controls->m_TrackingDeviceTypeChooser->blockSignals(true); + m_Controls->m_ToolNameEdit->blockSignals(true); + m_Controls->m_ToolTypeChooser->blockSignals(true); + m_Controls->m_IdentifierEdit->blockSignals(true); + m_Controls->m_SerialNumberEdit->blockSignals(true); + m_Controls->m_ToolAxisX->blockSignals(true); + m_Controls->m_ToolAxisY->blockSignals(true); + m_Controls->m_ToolAxisZ->blockSignals(true); + + //DeviceType + int index = m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(m_ToolToBeEdited->GetTrackingDeviceType())); + if (index >= 0) { - newNode->SetData(m_Controls->m_SurfaceChooser->GetSelectedNode()->GetData()); + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(index); } - newNode->SetName(m_Controls->m_ToolNameEdit->text().toLatin1()); - m_CreatedTool->SetDataNode(newNode); + m_Controls->m_ToolNameEdit->setText(QString(m_ToolToBeEdited->GetToolName().c_str())); + m_Controls->m_CalibrationFileName->setText(QString(m_ToolToBeEdited->GetCalibrationFile().c_str())); - //fill NavigationTool object - m_CreatedTool->SetCalibrationFile(m_Controls->m_CalibrationFileName->text().toLatin1().data()); - m_CreatedTool->SetIdentifier(m_Controls->m_IdentifierEdit->text().toLatin1().data()); - m_CreatedTool->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toLatin1().data()); + FillUIToolLandmarkLists(m_ToolToBeEdited->GetToolCalibrationLandmarks(), m_ToolToBeEdited->GetToolRegistrationLandmarks()); -//Tracking Device -m_CreatedTool->SetTrackingDeviceType(m_Controls->m_TrackingDeviceTypeChooser->currentText().toStdString()); - - //ToolType - if (m_Controls->m_ToolTypeChooser->currentText()=="Instrument") m_CreatedTool->SetType(mitk::NavigationTool::Instrument); - else if (m_Controls->m_ToolTypeChooser->currentText()=="Fiducial") m_CreatedTool->SetType(mitk::NavigationTool::Fiducial); - else if (m_Controls->m_ToolTypeChooser->currentText()=="Skinmarker") m_CreatedTool->SetType(mitk::NavigationTool::Skinmarker); - else m_CreatedTool->SetType(mitk::NavigationTool::Unknown); - - //Tool Tip - mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_AdvancedWidget->GetManipulatedToolTip()); - m_CreatedTool->SetToolTipOrientation(tempND->GetOrientation()); - m_CreatedTool->SetToolTipPosition(tempND->GetPosition()); - - //Tool Landmarks - mitk::PointSet::Pointer toolCalLandmarks, toolRegLandmarks; - GetUIToolLandmarksLists(toolCalLandmarks,toolRegLandmarks); - m_CreatedTool->SetToolCalibrationLandmarks(toolCalLandmarks); - m_CreatedTool->SetToolRegistrationLandmarks(toolRegLandmarks); - - //Tool Axis - mitk::Point3D toolAxis; - toolAxis.SetElement(0, (m_Controls->m_ToolAxisX->value())); - toolAxis.SetElement(1, (m_Controls->m_ToolAxisY->value())); - toolAxis.SetElement(2, (m_Controls->m_ToolAxisZ->value())); - m_CreatedTool->SetToolAxis(toolAxis); + switch (m_ToolToBeEdited->GetType()) + { + case mitk::NavigationTool::Instrument: + m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break; + case mitk::NavigationTool::Fiducial: + m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break; + case mitk::NavigationTool::Skinmarker: + m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break; + case mitk::NavigationTool::Unknown: + m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break; + } - emit NavigationToolFinished(); + m_Controls->m_IdentifierEdit->setText(QString(m_ToolToBeEdited->GetIdentifier().c_str())); + m_Controls->m_SerialNumberEdit->setText(QString(m_ToolToBeEdited->GetSerialNumber().c_str())); + + m_Controls->m_ToolAxisX->setValue(m_ToolToBeEdited->GetToolAxis()[0]); + m_Controls->m_ToolAxisY->setValue(m_ToolToBeEdited->GetToolAxis()[1]); + m_Controls->m_ToolAxisZ->setValue(m_ToolToBeEdited->GetToolAxis()[2]); + QString _label = "(" + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[0], 'f', 1) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[1], 'f', 1) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[2], 'f', 1) + "), quat: [" + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[0], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[1], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[2], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[3], 'f', 2) + "]"; + m_Controls->m_ToolTipLabel->setText(_label); + + //Undo block signals. Don't remove it, if signals are still blocked at the beginning of this function! + m_Controls->m_TrackingDeviceTypeChooser->blockSignals(false); + m_Controls->m_ToolNameEdit->blockSignals(false); + m_Controls->m_ToolTypeChooser->blockSignals(false); + m_Controls->m_IdentifierEdit->blockSignals(false); + m_Controls->m_SerialNumberEdit->blockSignals(false); + m_Controls->m_ToolAxisX->blockSignals(false); + m_Controls->m_ToolAxisY->blockSignals(false); + m_Controls->m_ToolAxisZ->blockSignals(false); } -void QmitkNavigationToolCreationWidget::OnCancel() +void QmitkNavigationToolCreationWidget::OnSurfaceUseToggled() { - m_CreatedTool = nullptr; + if (m_Controls->m_Surface_Use_Sphere->isChecked()) m_ToolToBeEdited->SetDefaultSurface(); + m_Controls->m_SurfaceChooser->setEnabled(m_Controls->m_Surface_Use_Other->isChecked()); + m_Controls->m_LoadSurface->setEnabled(m_Controls->m_Surface_Load_File->isChecked()); - emit Canceled(); + //Global Reinit to show tool surface preview + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); } void QmitkNavigationToolCreationWidget::OnLoadSurface() { - std::string filename = QFileDialog::getOpenFileName(nullptr,tr("Open Surface"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("STL (*.stl)")).toLatin1().data(); + std::string filename = QFileDialog::getOpenFileName(nullptr, tr("Open Surface"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("STL (*.stl)")).toLatin1().data(); QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); + mitk::Surface::Pointer surface; try { - mitk::IOUtil::Load(filename.c_str(), *m_DataStorage); + surface = mitk::IOUtil::LoadSurface(filename.c_str()); } catch (mitk::Exception &e) { MITK_ERROR << "Exception occured: " << e.what(); + return; } + + m_ToolToBeEdited->GetDataNode()->SetData(surface); + + //Global Reinit to show tool surface or preview + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); } void QmitkNavigationToolCreationWidget::OnLoadCalibrationFile() { - QString fileName = QFileDialog::getOpenFileName(nullptr,tr("Open Calibration File"), QmitkIGTCommonHelper::GetLastFileLoadPath(), "*.*"); + QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open Calibration File"), QmitkIGTCommonHelper::GetLastFileLoadPath(), "*.*"); QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(fileName); m_Controls->m_CalibrationFileName->setText(fileName); + m_ToolToBeEdited->SetCalibrationFile(fileName.toStdString()); } - -void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool) +void QmitkNavigationToolCreationWidget::GetValuesFromGuiElements() { -m_Controls->m_ToolNameEdit->setText(QString(DefaultTool->GetDataNode()->GetName().c_str())); -m_Controls->m_IdentifierEdit->setText(QString(DefaultTool->GetIdentifier().c_str())); -m_Controls->m_SerialNumberEdit->setText(QString(DefaultTool->GetSerialNumber().c_str())); -m_AdvancedWidget->SetDefaultTooltip( DefaultTool->GetToolTipTransform() ); -int index = m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(DefaultTool->GetTrackingDeviceType())); + //Tracking Device + m_ToolToBeEdited->SetTrackingDeviceType(m_Controls->m_TrackingDeviceTypeChooser->currentText().toStdString()); + m_ToolToBeEdited->GetDataNode()->SetName(m_Controls->m_ToolNameEdit->text().toStdString()); + + //Tool Landmarks + mitk::PointSet::Pointer toolCalLandmarks, toolRegLandmarks; + GetUIToolLandmarksLists(toolCalLandmarks, toolRegLandmarks); + m_ToolToBeEdited->SetToolCalibrationLandmarks(toolCalLandmarks); + m_ToolToBeEdited->SetToolRegistrationLandmarks(toolRegLandmarks); + + //Advanced + if (m_Controls->m_ToolTypeChooser->currentText() == "Instrument") m_ToolToBeEdited->SetType(mitk::NavigationTool::Instrument); + else if (m_Controls->m_ToolTypeChooser->currentText() == "Fiducial") m_ToolToBeEdited->SetType(mitk::NavigationTool::Fiducial); + else if (m_Controls->m_ToolTypeChooser->currentText() == "Skinmarker") m_ToolToBeEdited->SetType(mitk::NavigationTool::Skinmarker); + else m_FinalTool->SetType(mitk::NavigationTool::Unknown); + + m_ToolToBeEdited->SetIdentifier(m_Controls->m_IdentifierEdit->text().toLatin1().data()); + m_ToolToBeEdited->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toLatin1().data()); -if (index >= 0) + //Tool Axis + mitk::Point3D toolAxis; + toolAxis.SetElement(0, (m_Controls->m_ToolAxisX->value())); + toolAxis.SetElement(1, (m_Controls->m_ToolAxisY->value())); + toolAxis.SetElement(2, (m_Controls->m_ToolAxisZ->value())); + m_ToolToBeEdited->SetToolAxis(toolAxis); +} + +mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool() { - m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(index); + return m_FinalTool; } -m_Controls->m_CalibrationFileName->setText(QString(DefaultTool->GetCalibrationFile().c_str())); -m_Controls->m_Surface_Use_Other->setChecked(true); -switch(DefaultTool->GetType()) +void QmitkNavigationToolCreationWidget::OnFinished() { -case mitk::NavigationTool::Instrument: -m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break; -case mitk::NavigationTool::Fiducial: -m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break; -case mitk::NavigationTool::Skinmarker: -m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break; -case mitk::NavigationTool::Unknown: -m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break; + if (m_Controls->m_Surface_Use_Other->isChecked()) + m_ToolToBeEdited->GetDataNode()->SetData(m_Controls->m_SurfaceChooser->GetSelectedNode()->GetData()); + + //here we create a new tool + m_FinalTool = m_ToolToBeEdited->Clone(); + //Set the correct name of data node, cause the m_ToolToBeEdited was called "Tool preview" + m_FinalTool->GetDataNode()->SetName(m_Controls->m_ToolNameEdit->text().toStdString()); + + emit NavigationToolFinished(); } - m_Controls->m_SurfaceChooser->SetSelectedNode(DefaultTool->GetDataNode()); - FillUIToolLandmarkLists(DefaultTool->GetToolCalibrationLandmarks(),DefaultTool->GetToolRegistrationLandmarks()); +void QmitkNavigationToolCreationWidget::OnCancel() +{ + Initialize(nullptr, "");//Reset everything to a fresh tool, like it was done in the constructor + emit Canceled(); } +void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable /*= true*/) +{ + //Adapt Gui + int index = m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(type)); + + if (index >= 0) + { + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(index); + } + + m_Controls->m_TrackingDeviceTypeChooser->setEditable(changeable); + + //Set data to member + m_ToolToBeEdited->SetTrackingDeviceType(type); +} //################################################################################## //############################## internal help methods ############################# //################################################################################## void QmitkNavigationToolCreationWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } -void QmitkNavigationToolCreationWidget::OnShowAdvancedOptions(bool state) +void QmitkNavigationToolCreationWidget::OnEditToolTip() { - if(state) - { - m_AdvancedWidget->show(); - m_AdvancedWidget->SetDefaultTooltip(m_AdvancedWidget->GetManipulatedToolTip()); //use the last one, if there is one - m_AdvancedWidget->ReInitialize(); - - // reinit the views with the new nodes - mitk::DataStorage::SetOfObjects::ConstPointer rs = m_DataStorage->GetAll(); - mitk::TimeGeometry::Pointer bounds = m_DataStorage->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry - mitk::RenderingManager::GetInstance()->InitializeViews(bounds); - } - else - { - m_AdvancedWidget->hide(); - } -} + m_ToolTransformationWidget->SetToolToEdit(m_ToolToBeEdited); + m_ToolTransformationWidget->SetDefaultRotation(m_ToolToBeEdited->GetToolTipOrientation()); + m_ToolTransformationWidget->SetDefaultOffset(m_ToolToBeEdited->GetToolTipPosition()); -void QmitkNavigationToolCreationWidget::OnProcessDialogCloseRequest() -{ - m_AdvancedWidget->hide(); - m_Controls->m_ShowAdvancedOptionsPB->setChecked(false); + m_ToolTransformationWidget->open(); } -void QmitkNavigationToolCreationWidget::OnRetrieveDataForManualTooltipManipulation() +void QmitkNavigationToolCreationWidget::OnEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip) { - if(m_Controls->m_Surface_Use_Sphere->isChecked()) + //if user pressed cancle, nullptr is returned. Do nothing. Else, set values. + if (toolTip) { - m_AdvancedWidget->SetToolTipSurface(true); + m_ToolToBeEdited->SetToolTipPosition(toolTip->GetOffset()); + mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(toolTip);//Convert to Navigation data for simple transversion to quaternion + m_ToolToBeEdited->SetToolTipOrientation(tempND->GetOrientation()); + + //Update Label + QString _label = "(" + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[0], 'f', 1) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[1], 'f', 1) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipPosition()[2], 'f', 1) + "), quat: [" + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[0], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[1], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[2], 'f', 2) + ", " + + QString::number(m_ToolToBeEdited->GetToolTipOrientation()[3], 'f', 2) + "]"; + m_Controls->m_ToolTipLabel->setText(_label); } - else - { - m_AdvancedWidget->SetToolTipSurface(false, - dynamic_cast(m_Controls->m_SurfaceChooser->GetSelectedNode().GetPointer())); - } -} - -void QmitkNavigationToolCreationWidget::OnSurfaceUseOtherToggled(bool checked) -{ - m_Controls->m_LoadSurface->setEnabled(checked); } void QmitkNavigationToolCreationWidget::FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks) { m_calLandmarkNode->SetData(calLandmarks); m_regLandmarkNode->SetData(regLandmarks); m_Controls->m_CalibrationLandmarksList->SetPointSetNode(m_calLandmarkNode); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(m_regLandmarkNode); } void QmitkNavigationToolCreationWidget::GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks) { calLandmarks = dynamic_cast(m_calLandmarkNode->GetData()); regLandmarks = dynamic_cast(m_regLandmarkNode->GetData()); } void QmitkNavigationToolCreationWidget::InitializeUIToolLandmarkLists() { m_calLandmarkNode = mitk::DataNode::New(); m_regLandmarkNode = mitk::DataNode::New(); - FillUIToolLandmarkLists(mitk::PointSet::New(),mitk::PointSet::New()); + FillUIToolLandmarkLists(mitk::PointSet::New(), mitk::PointSet::New()); } void QmitkNavigationToolCreationWidget::RefreshTrackingDeviceCollection() { us::ModuleContext* context = us::GetModuleContext(); std::vector > refs = context->GetServiceReferences(); if (refs.empty()) { MITK_WARN << "No tracking device service found!"; return; } mitk::TrackingDeviceTypeCollection* _DeviceTypeCollection = context->GetService(refs.front()); for (auto name : _DeviceTypeCollection->GetTrackingDeviceTypeNames()) { //if the device is not included yet, add name to comboBox and widget to stackedWidget if (m_Controls->m_TrackingDeviceTypeChooser->findText(QString::fromStdString(name)) == -1) { m_Controls->m_TrackingDeviceTypeChooser->addItem(QString::fromStdString(name)); } } -} +} \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.h index 8be1dfc25b..4579b13f8c 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.h @@ -1,132 +1,145 @@ /*=================================================================== 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 QmitkNavigationToolCreationWidget_H #define QmitkNavigationToolCreationWidget_H //QT headers #include //mitk headers #include "MitkIGTUIExports.h" #include #include #include +#include "QmitkInteractiveTransformationWidget.h" + +#include //Microservices #include #include #include #include -// Qmitk headers -#include "QmitkNavigationToolCreationAdvancedWidget.h" - //ui header #include "ui_QmitkNavigationToolCreationWidget.h" - /** Documentation: - * \brief An object of this class offers an UI to create or modify NavigationTools. - * - * Be sure to call the initialize method before you start the widget - * otherwise some errors might occure. - * - * \ingroup IGTUI - */ +/** Documentation: + * \brief An object of this class offers an UI to create or modify NavigationTools. + * + * Be sure to call the initialize method before you start the widget + * otherwise some errors might occure. + * + * \ingroup IGTUI + */ class MITKIGTUI_EXPORT QmitkNavigationToolCreationWidget : public QWidget { Q_OBJECT - public: - static const std::string VIEW_ID; +public: + static const std::string VIEW_ID; - /** @brief Initializes the widget. - * @param dataStorage The data storage is needed to offer the possibility to choose surfaces from the data storage for tool visualization. - * @param supposedIdentifier This Identifier is supposed for the user. It is needed because every identifier in a navigation tool storage must be unique and we don't know the others. - */ - void Initialize(mitk::DataStorage* dataStorage, const std::string &supposedIdentifier, const std::string &supposedName = "NewTool"); + /** @brief Initializes the widget. + * @param dataStorage The data storage is needed to offer the possibility to choose surfaces from the data storage for tool visualization. + * @param supposedIdentifier This Identifier is supposed for the user. It is needed because every identifier in a navigation tool storage must be unique and we don't know the others. + */ + void Initialize(mitk::DataStorage* dataStorage, const std::string &supposedIdentifier, const std::string &supposedName = "NewTool"); - /** @brief Sets the default tracking device type. You may also define if it is changeable or not.*/ - void SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable = true); + /** @brief This Function will add a new node to the Data Manager with given name to enable a preview of the m_ToolToBeEdited + */ + void ShowToolPreview(std::string _name); - /** @brief Sets the default data of all input fields. The default data is used from the default tool which is given as parameter. */ - void SetDefaultData(mitk::NavigationTool::Pointer DefaultTool); + /** @brief Sets the default tracking device type. You may also define if it is changeable or not.*/ + void SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable = true); QmitkNavigationToolCreationWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkNavigationToolCreationWidget() override; + /** @brief Sets the default data of all input fields. The default data is used from the default tool which is given as parameter. */ + void SetDefaultData(mitk::NavigationTool::Pointer DefaultTool); /** @return Returns the created tool. Returns nullptr if no tool was created yet. */ mitk::NavigationTool::Pointer GetCreatedTool(); - signals: +signals: - /** @brief This signal is emitted if the user finished the creation of the tool. */ - void NavigationToolFinished(); + /** @brief This signal is emitted if the user finished the creation of the tool. */ + void NavigationToolFinished(); - /** @brief This signal is emitted if the user canceled the creation of the tool. */ - void Canceled(); + /** @brief This signal is emitted if the user canceled the creation of the tool. */ + void Canceled(); protected slots: - void OnCancel(); - void OnFinished(); - void OnLoadSurface(); - void OnLoadCalibrationFile(); - void OnShowAdvancedOptions(bool state); - void OnProcessDialogCloseRequest(); - void OnRetrieveDataForManualTooltipManipulation(); - void OnSurfaceUseOtherToggled(bool checked); - protected: + void OnLoadCalibrationFile(); + void OnSurfaceUseToggled(); + void OnLoadSurface(); + void OnEditToolTip(); + void OnEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip); + + void OnCancel(); + void OnFinished(); - /// \brief Creation of the connections - virtual void CreateConnections(); + void GetValuesFromGuiElements(); + +private: + + //############## private help methods ####################### + /** Shows a message box with the given message s. */ + void MessageBox(std::string s); + + /** Set the tool landmark lists in the UI.*/ + void FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks); + + /** Returns the tool landmark lists from the UI. + * @param[out] calLandmarks Returns a pointer to the calibration landmarks point set. + * @param[out] regLandmarks Returns a pointer to the registration landmarks point set. + */ + void GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks); - virtual void CreateQtPartControl(QWidget *parent); + /** Initializes the tool landmark lists in the UI. */ + void InitializeUIToolLandmarkLists(); + void RefreshTrackingDeviceCollection(); - Ui::QmitkNavigationToolCreationWidgetControls* m_Controls; + void SetGuiElements(); - QmitkNavigationToolCreationAdvancedWidget* m_AdvancedWidget; +protected: + /// \brief Creation of the connections + virtual void CreateConnections(); - /** @brief holds the DataStorage */ - mitk::DataStorage* m_DataStorage; + virtual void CreateQtPartControl(QWidget *parent); - /** @brief this pointer holds the tool which is created */ - mitk::NavigationTool::Pointer m_CreatedTool; + Ui::QmitkNavigationToolCreationWidgetControls* m_Controls; - //############## private help methods ####################### - /** Shows a message box with the given message s. */ - void MessageBox(std::string s); + /** @brief this pointer holds the tool which is edited. If finished is clicked, it will be copied to the final tool, if it is cancled, it is reseted and not used. + This can be regarded as the clipboard for all changes. */ + mitk::NavigationTool::Pointer m_ToolToBeEdited; - /** Hold the data nodes which are needed for the landmark widgets. */ - mitk::DataNode::Pointer m_calLandmarkNode, m_regLandmarkNode; + /** @brief this pointer holds the tool which is created and returned */ + mitk::NavigationTool::Pointer m_FinalTool; - /** Set the tool landmark lists in the UI.*/ - void FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks); + QmitkInteractiveTransformationWidget* m_ToolTransformationWidget; - /** Returns the tool landmark lists from the UI. - * @param[out] calLandmarks Returns a pointer to the calibration landmarks point set. - * @param[out] regLandmarks Returns a pointer to the registration landmarks point set. - */ - void GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks); + /** @brief holds the DataStorage */ + mitk::DataStorage* m_DataStorage; - /** Initializes the tool landmark lists in the UI. */ - void InitializeUIToolLandmarkLists(); - void RefreshTrackingDeviceCollection(); + /** Hold the data nodes which are needed for the landmark widgets. */ + mitk::DataNode::Pointer m_calLandmarkNode, m_regLandmarkNode; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui index d65184df95..5db33c91e0 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui @@ -1,571 +1,586 @@ QmitkNavigationToolCreationWidgetControls 0 0 - 255 - 309 + 357 + 405 Form Device Type: 150 0 150 16777215 0 0 0 - 236 - 90 + 339 + 211 Basic Information 100 0 Name: NewTool 100 0 Calibration File: none 40 16777215 Load Qt::Vertical 20 40 0 0 - 310 - 113 + 339 + 211 Tool Visualization - Use Simple Cone + Default representation (shows tool coordinates) true - Use Surface: + Use surface from data storage - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 25 - 20 - - - - 200 0 150 16777215 + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Load surface from file + + + + + false 40 16777215 Load Qt::Horizontal 40 20 Qt::Vertical 20 8 0 0 - 157 - 84 + 145 + 73 Tool Landmarks 1 Calibration Landmarks Registration Landmarks 0 0 - 286 - 183 + 276 + 161 Advanced 100 0 Tool Type: 150 0 150 16777215 Instrument Fiducial Skinmarker Unkown 100 0 Identifier: <not given> 100 0 Serial Number: <not given> Tooltip: + + + + + + + Qt::Horizontal 40 20 - + Edit Tooltip true Qt::Vertical 20 40 Tool Axis: Qt::Horizontal 40 20 QAbstractSpinBox::CorrectToPreviousValue -9999 9999 1 -9999 9999 -9999 9999 Qt::Horizontal Qt::Horizontal 40 20 Cancel Finished QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
1
QmitkPointListWidget QWidget
QmitkPointListWidget.h
1
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp index acdeae0ceb..7de0a427ca 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp @@ -1,419 +1,442 @@ /*=================================================================== 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 "QmitkNavigationToolManagementWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include //qt headers #include #include #include #include //poco headers #include const std::string QmitkNavigationToolManagementWidget::VIEW_ID = "org.mitk.views.navigationtoolmanagementwidget"; QmitkNavigationToolManagementWidget::QmitkNavigationToolManagementWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; CreateQtPartControl(this); CreateConnections(); } QmitkNavigationToolManagementWidget::~QmitkNavigationToolManagementWidget() { } void QmitkNavigationToolManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolManagementWidgetControls; m_Controls->setupUi(parent); } //Disable StorageControls in the beginning, because there is no storage to edit DisableStorageControls(); } void QmitkNavigationToolManagementWidget::OnLoadTool() { if (m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); std::string filename = QFileDialog::getOpenFileName(nullptr,tr("Add Navigation Tool"), QmitkIGTCommonHelper::GetLastFileLoadPath(), "*.IGTTool").toLatin1().data(); QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); if (filename == "") return; mitk::NavigationTool::Pointer readTool = myReader->DoRead(filename); if (readTool.IsNull()) MessageBox("Error: " + myReader->GetErrorMessage()); else { if (!m_NavigationToolStorage->AddTool(readTool)) { MessageBox("Error: Can't add tool!"); m_DataStorage->Remove(readTool->GetDataNode()); } UpdateToolTable(); - m_NavigationToolStorage->UpdateMicroservice(); - } +} } void QmitkNavigationToolManagementWidget::OnSaveTool() { //if no item is selected, show error message: if (m_Controls->m_ToolList->currentItem() == nullptr) { MessageBox("Error: Please select tool first!"); return; } mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = QFileDialog::getSaveFileName(nullptr,tr("Save Navigation Tool"), QmitkIGTCommonHelper::GetLastFileSavePath(), "*.IGTTool").toLatin1().data(); QmitkIGTCommonHelper::SetLastFileSavePathByFileName(QString::fromStdString(filename)); if (filename == "") return; std::string fileExt = Poco::Path(filename).getExtension(); if (fileExt == "") { filename.append(".IGTTool"); } if (!myWriter->DoWrite(filename,m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()))) MessageBox("Error: "+ myWriter->GetErrorMessage()); } void QmitkNavigationToolManagementWidget::CreateConnections() { if (m_Controls) { //main widget page: connect((QObject*)(m_Controls->m_AddTool), SIGNAL(clicked()), this, SLOT(OnAddTool())); connect((QObject*)(m_Controls->m_DeleteTool), SIGNAL(clicked()), this, SLOT(OnDeleteTool())); connect((QObject*)(m_Controls->m_EditTool), SIGNAL(clicked()), this, SLOT(OnEditTool())); connect((QObject*)(m_Controls->m_MoveToolUp), SIGNAL(clicked()), this, SLOT(OnMoveToolUp())); connect((QObject*)(m_Controls->m_MoveToolDown), SIGNAL(clicked()), this, SLOT(OnMoveToolDown())); connect((QObject*)(m_Controls->m_LoadStorage), SIGNAL(clicked()), this, SLOT(OnLoadStorage())); connect((QObject*)(m_Controls->m_SaveStorage), SIGNAL(clicked()), this, SLOT(OnSaveStorage())); connect((QObject*)(m_Controls->m_LoadTool), SIGNAL(clicked()), this, SLOT(OnLoadTool())); connect((QObject*)(m_Controls->m_SaveTool), SIGNAL(clicked()), this, SLOT(OnSaveTool())); connect((QObject*)(m_Controls->m_CreateNewStorage), SIGNAL(clicked()), this, SLOT(OnCreateStorage())); + connect((QObject*)(m_Controls->m_ToolList), SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(OnToolSelected())); + //widget page "add tool": connect((QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(Canceled()), this, SLOT(OnAddToolCancel())); connect((QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(NavigationToolFinished()), this, SLOT(OnAddToolSave())); } } void QmitkNavigationToolManagementWidget::Initialize(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage, "Tool0"); } void QmitkNavigationToolManagementWidget::LoadStorage(mitk::NavigationToolStorage::Pointer storageToLoad) { if (storageToLoad.IsNotNull()) { m_NavigationToolStorage = storageToLoad; m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); } else { m_NavigationToolStorage = nullptr; DisableStorageControls(); } UpdateToolTable(); - m_NavigationToolStorage->UpdateMicroservice(); } //################################################################################## //############################## slots: main widget ################################ //################################################################################## void QmitkNavigationToolManagementWidget::OnMoveToolUp() { if (m_NavigationToolStorage.IsNotNull()) { + //Proof, if the NavigationToolStorage is locked. If it is locked, show MessageBox to user. + if( m_NavigationToolStorage->isLocked() ) + { + MessageBox("The storage is locked and it cannot be modified. Maybe the tracking device which " \ + "uses this storage is connected. If you want to modify the storage please " \ + "disconnect the device first."); + return; + } int toolIndex = m_Controls->m_ToolList->currentIndex().row(); if (toolIndex >= 0) { mitk::NavigationTool::Pointer currentNavigationTool = m_NavigationToolStorage->GetTool(toolIndex); if (currentNavigationTool.IsNotNull()) { std::string currentIdentifier = currentNavigationTool->GetIdentifier(); int NewNumber = m_Controls->m_ToolList->currentIndex().row() - 1; if (NewNumber < 0) { MITK_WARN << "Cannot move tool up because it is on the top!"; } else { m_NavigationToolStorage->AssignToolNumber(currentIdentifier, NewNumber); } UpdateToolTable(); - m_NavigationToolStorage->UpdateMicroservice(); } } } } void QmitkNavigationToolManagementWidget::OnMoveToolDown() { if (m_NavigationToolStorage.IsNotNull()) { + //Proof, if the NavigationToolStorage is locked. If it is locked, show MessageBox to user. + if( m_NavigationToolStorage->isLocked() ) + { + MessageBox("The storage is locked and it cannot be modified. Maybe the tracking device which " \ + "uses this storage is connected. If you want to modify the storage please " \ + "disconnect the device first."); + return; + } int toolIndex = m_Controls->m_ToolList->currentIndex().row(); if (toolIndex >= 0) { mitk::NavigationTool::Pointer currentNavigationTool = m_NavigationToolStorage->GetTool(toolIndex); if (currentNavigationTool.IsNotNull()) { std::string currentIdentifier = currentNavigationTool->GetIdentifier(); - int NewNumber = m_Controls->m_ToolList->currentIndex().row() + 1; + unsigned int NewNumber = m_Controls->m_ToolList->currentIndex().row() + 1; if (NewNumber >= m_NavigationToolStorage->GetToolCount()) { MITK_WARN << "Cannot move tool down because it is the last tool in this storage!"; } else { m_NavigationToolStorage->AssignToolNumber(currentIdentifier, NewNumber); } UpdateToolTable(); - m_NavigationToolStorage->UpdateMicroservice(); } } } } void QmitkNavigationToolManagementWidget::OnAddTool() { if (m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } QString defaultIdentifier = "NavigationTool#" + QString::number(m_NavigationToolStorage->GetToolCount()); QString defaultName = "NavigationTool" + QString::number(m_NavigationToolStorage->GetToolCount()); m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage, defaultIdentifier.toStdString(), defaultName.toStdString()); + m_Controls->m_ToolCreationWidget->ShowToolPreview("Tool preview"); m_edit = false; m_Controls->m_MainWidgets->setCurrentIndex(1); - m_NavigationToolStorage->UpdateMicroservice(); } void QmitkNavigationToolManagementWidget::OnDeleteTool() { //first: some checks if (m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == nullptr) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } m_DataStorage->Remove(m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetDataNode()); m_NavigationToolStorage->DeleteTool(m_Controls->m_ToolList->currentIndex().row()); UpdateToolTable(); - m_NavigationToolStorage->UpdateMicroservice(); } void QmitkNavigationToolManagementWidget::OnEditTool() { if (m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == nullptr) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } mitk::NavigationTool::Pointer selectedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); + m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage, "", ""); //Initialize once again, might be called here for the first time after autodetection m_Controls->m_ToolCreationWidget->SetDefaultData(selectedTool); - m_NavigationToolStorage->SetName("test"); + m_Controls->m_ToolCreationWidget->ShowToolPreview("Tool preview"); m_edit = true; m_Controls->m_MainWidgets->setCurrentIndex(1); - m_NavigationToolStorage->UpdateMicroservice(); } void QmitkNavigationToolManagementWidget::OnCreateStorage() { QString storageName = QInputDialog::getText(nullptr, "Storage Name", "Name of the new tool storage:"); if (storageName.isNull()) return; m_NavigationToolStorage = mitk::NavigationToolStorage::New(this->m_DataStorage); m_NavigationToolStorage->SetName(storageName.toStdString()); m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); emit NewStorageAdded(m_NavigationToolStorage, storageName.toStdString()); } void QmitkNavigationToolManagementWidget::OnLoadStorage() { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); - std::string filename = QFileDialog::getOpenFileName(nullptr, tr("Open Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); + std::string filename = QFileDialog::getOpenFileName(nullptr, tr("Open Navigation Tool Storage"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); if (filename == "") return; + QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); try { - mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); - std::string filename = QFileDialog::getOpenFileName(NULL, tr("Open Navigation Tool Storage"), QmitkIGTCommonHelper::GetLastFileLoadPath(), tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); - if (filename == "") return; - - QmitkIGTCommonHelper::SetLastFileLoadPathByFileName(QString::fromStdString(filename)); - - try - { - mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); + mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); - if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); - else - { - Poco::Path myPath = Poco::Path(filename.c_str()); - tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it - this->LoadStorage(tempStorage); - emit NewStorageAdded(m_NavigationToolStorage,myPath.getFileName()); - m_NavigationToolStorage->UpdateMicroservice(); - } - } - catch (const mitk::Exception& exception) + if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); + else { - MessageBox(exception.GetDescription()); + Poco::Path myPath = Poco::Path(filename.c_str()); + tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it + this->LoadStorage(tempStorage); + emit NewStorageAdded(m_NavigationToolStorage,myPath.getFileName()); } } catch (const mitk::Exception& exception) { MessageBox(exception.GetDescription()); } - m_NavigationToolStorage->UpdateMicroservice(); } void QmitkNavigationToolManagementWidget::OnSaveStorage() { QFileDialog *fileDialog = new QFileDialog; fileDialog->setDefaultSuffix("IGTToolStorage"); QString suffix = "IGT Tool Storage (*.IGTToolStorage)"; QString filename = fileDialog->getSaveFileName(nullptr, tr("Save Navigation Tool Storage"), QmitkIGTCommonHelper::GetLastFileSavePath(), suffix, &suffix); if (filename.isEmpty()) return; //canceled by the user // check file suffix QFileInfo file(filename); if(file.suffix().isEmpty()) filename += ".IGTToolStorage"; //serialize tool storage mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); if (!mySerializer->Serialize(filename.toStdString(), m_NavigationToolStorage)) { MessageBox("Error: " + mySerializer->GetErrorMessage()); return; QmitkIGTCommonHelper::SetLastFileSavePath(file.absolutePath()); } Poco::Path myPath = Poco::Path(filename.toStdString()); m_Controls->m_StorageName->setText(QString::fromStdString(myPath.getFileName())); } //################################################################################## //############################## slots: add tool widget ############################ //################################################################################## void QmitkNavigationToolManagementWidget::OnAddToolSave() { + //Proof, if the NavigationToolStorage is locked. If it is locked, show MessageBox to user. + if( m_NavigationToolStorage->isLocked() ) + { + MessageBox( "The storage is locked and it cannot be modified. Maybe the tracking device which " \ + "uses this storage is connected. If you want to modify the storage please " \ + "disconnect the device first."); + return; + } + mitk::NavigationTool::Pointer newTool = m_Controls->m_ToolCreationWidget->GetCreatedTool(); if (m_edit) //here we edit a existing tool { mitk::NavigationTool::Pointer editedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); editedTool->Graft(newTool); + //Keep this line, 'cause otherwise, the NavigationToolStorage wouldn't notice, that the toolStorage changed. + m_NavigationToolStorage->UpdateMicroservice(); } else //here we create a new tool { m_NavigationToolStorage->AddTool(newTool); } + //Remove tool preview + m_DataStorage->Remove(m_DataStorage->GetNamedNode("Tool preview")); + UpdateToolTable(); m_Controls->m_MainWidgets->setCurrentIndex(0); - m_NavigationToolStorage->UpdateMicroservice(); + + m_Controls->m_ToolInformation->setText(""); } void QmitkNavigationToolManagementWidget::OnAddToolCancel() { m_Controls->m_MainWidgets->setCurrentIndex(0); + //Remove tool preview + m_DataStorage->Remove(m_DataStorage->GetNamedNode("Tool preview")); +} + +void QmitkNavigationToolManagementWidget::OnToolSelected() +{ + QString _label = "Information for tool " + m_Controls->m_ToolList->currentItem()->text() + "\n"; + _label.append(QString(m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetStringWithAllToolInformation().c_str())); + m_Controls->m_ToolInformation->setText(_label); } //################################################################################## //############################## private help methods ############################## //################################################################################## void QmitkNavigationToolManagementWidget::UpdateToolTable() { m_Controls->m_ToolList->clear(); if (m_NavigationToolStorage.IsNull()) return; - for (int i = 0; i < m_NavigationToolStorage->GetToolCount(); i++) + for (unsigned int i = 0; i < m_NavigationToolStorage->GetToolCount(); i++) { - QString currentTool = "Tool" + QString::number(i) + ": " + QString(m_NavigationToolStorage->GetTool(i)->GetDataNode()->GetName().c_str()) + " "; + QString currentTool = "Tool" + QString::number(i) + ": " + QString(m_NavigationToolStorage->GetTool(i)->GetToolName().c_str()) + " "; currentTool += "(" + QString::fromStdString(m_NavigationToolStorage->GetTool(i)->GetTrackingDeviceType()) + "/"; switch (m_NavigationToolStorage->GetTool(i)->GetType()) { case mitk::NavigationTool::Instrument: currentTool += "Instrument)"; break; case mitk::NavigationTool::Fiducial: currentTool += "Fiducial)"; break; case mitk::NavigationTool::Skinmarker: currentTool += "Skinmarker)"; break; default: currentTool += "Unknown)"; } m_Controls->m_ToolList->addItem(currentTool); } } void QmitkNavigationToolManagementWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkNavigationToolManagementWidget::DisableStorageControls() { m_Controls->m_StorageName->setText(""); m_Controls->m_AddTool->setEnabled(false); m_Controls->m_LoadTool->setEnabled(false); m_Controls->m_MoveToolUp->setEnabled(false); m_Controls->m_MoveToolDown->setEnabled(false); m_Controls->m_selectedLabel->setEnabled(false); m_Controls->m_DeleteTool->setEnabled(false); m_Controls->m_EditTool->setEnabled(false); m_Controls->m_SaveTool->setEnabled(false); m_Controls->m_ToolList->setEnabled(false); m_Controls->m_SaveStorage->setEnabled(false); m_Controls->m_ToolLabel->setEnabled(false); } void QmitkNavigationToolManagementWidget::EnableStorageControls() { m_Controls->m_AddTool->setEnabled(true); m_Controls->m_LoadTool->setEnabled(true); m_Controls->m_MoveToolUp->setEnabled(true); m_Controls->m_MoveToolDown->setEnabled(true); m_Controls->m_selectedLabel->setEnabled(true); m_Controls->m_DeleteTool->setEnabled(true); m_Controls->m_EditTool->setEnabled(true); m_Controls->m_SaveTool->setEnabled(true); m_Controls->m_ToolList->setEnabled(true); m_Controls->m_SaveStorage->setEnabled(true); m_Controls->m_ToolLabel->setEnabled(true); } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h index c8bef65e8a..260a9eece9 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h @@ -1,112 +1,113 @@ /*=================================================================== 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 QMITKNAVIGATIONTOOLMANAGEMENTWIDGET_H #define QMITKNAVIGATIONTOOLMANAGEMENTWIDGET_H //QT headers #include //mitk headers #include "MitkIGTUIExports.h" #include "mitkNavigationTool.h" #include //ui header #include "ui_QmitkNavigationToolManagementWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to manage NavigationTools and * NavigationToolStorages. This means a user may create, save and load * single NavigationTools and/or NavigationToolStorages with this widget. * * Be sure to call the Initialize-methode before you start the widget * otherwise some errors might occure. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkNavigationToolManagementWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** Initializes the widget. Has to be called before any action, otherwise errors might occur. */ void Initialize(mitk::DataStorage* dataStorage); /** Loads a storage to the widget. The old storage storage is dropped, so be careful, if the * storage is not saved somewhere else it might be lost. You might want to ask the user if he * wants to save the storage to the harddisk before calling this method. * @param storageToLoad This storage will be loaded and might be modified by the user. */ void LoadStorage(mitk::NavigationToolStorage::Pointer storageToLoad); QmitkNavigationToolManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkNavigationToolManagementWidget() override; signals: /** This signal is emmited if a new storage was added by the widget itself, e.g. because * a storage was loaded from the harddisk. * @param newStorage Holds the new storage which was added. * @param storageName Name of the new storage (e.g. filename) */ void NewStorageAdded(mitk::NavigationToolStorage::Pointer newStorage, std::string storageName); protected slots: //main widget page: void OnAddTool(); void OnDeleteTool(); void OnEditTool(); void OnLoadTool(); void OnSaveTool(); void OnMoveToolUp(); void OnMoveToolDown(); void OnLoadStorage(); void OnSaveStorage(); void OnCreateStorage(); + void OnToolSelected(); //widget page "add tool": void OnAddToolCancel(); void OnAddToolSave(); protected: /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkNavigationToolManagementWidgetControls* m_Controls; /** @brief holds the DataStorage */ mitk::DataStorage* m_DataStorage; /** @brief holds the NavigationToolStorage we are working with. */ mitk::NavigationToolStorage::Pointer m_NavigationToolStorage; /** @brief shows if we are in edit mode, if not we create new navigation tool objects. */ bool m_edit; //############## private help methods ####################### void MessageBox(std::string s); void UpdateToolTable(); void DisableStorageControls(); void EnableStorageControls(); }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui index a80055349a..b246da95c5 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui @@ -1,308 +1,315 @@ QmitkNavigationToolManagementWidgetControls 0 0 443 781 Form Qt::Horizontal 40 20 Whole Storage: Create New Load Save Qt::Horizontal 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:'MS Shell Dlg 2'; font-size:7.8pt; 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-size:8pt; font-weight:600;">Storage Name:</span></p></body></html> <none> Qt::Horizontal 40 20 <!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:'MS Shell Dlg 2'; font-size:8.25pt; 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-size:8pt; font-weight:600;">Tools:</span></p></body></html> Qt::Horizontal 40 20 50 16777215 Add 50 16777215 Load <!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:'MS Shell Dlg 2'; font-size:7.8pt; 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-size:8pt;">Selected:</span></p></body></html> 50 16777215 Up 50 16777215 Down 50 16777215 Delete 50 16777215 Edit 50 16777215 Save Qt::Vertical 20 40 0 150 Qt::Vertical 20 40 + + + + + + + QmitkNavigationToolCreationWidget QWidget
QmitkNavigationToolCreationWidget.h
1
diff --git a/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.cpp b/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.cpp index 0a8c3a1ffc..317575e58d 100644 --- a/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.cpp @@ -1,69 +1,69 @@ /*=================================================================== 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 "QmitkOpenIGTLinkWidget.h" #include "mitkOpenIGTLinkTrackingDevice.h" const std::string QmitkOpenIGTLinkWidget::VIEW_ID = "org.mitk.views.OpenIGTLinkWidget"; QmitkOpenIGTLinkWidget::QmitkOpenIGTLinkWidget(QWidget* parent, Qt::WindowFlags f) : QmitkAbstractTrackingDeviceWidget(parent, f) , m_Controls(nullptr) { } void QmitkOpenIGTLinkWidget::Initialize() { InitializeSuperclassWidget(); CreateQtPartControl(this); } QmitkOpenIGTLinkWidget::~QmitkOpenIGTLinkWidget() { delete m_Controls; } void QmitkOpenIGTLinkWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkOpenIGTLinkWidget; m_Controls->setupUi(parent); } } -mitk::TrackingDevice::Pointer QmitkOpenIGTLinkWidget::ConstructTrackingDevice() +mitk::TrackingDevice::Pointer QmitkOpenIGTLinkWidget::GetTrackingDevice() { // Create the Virtual Tracking Device mitk::OpenIGTLinkTrackingDevice::Pointer OIGTLDevice = mitk::OpenIGTLinkTrackingDevice::New(); OIGTLDevice->SetPortNumber(m_Controls->m_OpenIGTLinkPort->text().toInt()); OIGTLDevice->SetHostname(m_Controls->m_OpenIGTLinkHostname->text().toStdString()); OIGTLDevice->SetUpdateRate(m_Controls->m_UpdateRate->value()); return static_cast(OIGTLDevice); } QmitkOpenIGTLinkWidget* QmitkOpenIGTLinkWidget::Clone(QWidget* parent) const { QmitkOpenIGTLinkWidget* clonedWidget = new QmitkOpenIGTLinkWidget(parent); clonedWidget->Initialize(); clonedWidget->m_Controls->m_OpenIGTLinkPort->setText(m_Controls->m_OpenIGTLinkPort->text()); clonedWidget->m_Controls->m_OpenIGTLinkHostname->setText(m_Controls->m_OpenIGTLinkHostname->text()); return clonedWidget; } diff --git a/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.h b/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.h index 0f170762c8..b53c143e3d 100644 --- a/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.h @@ -1,54 +1,54 @@ /*=================================================================== 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 QmitkOpenIGTLinkWidget_H #define QmitkOpenIGTLinkWidget_H #include "ui_QmitkOpenIGTLinkWidget.h" #include "QmitkAbstractTrackingDeviceWidget.h" /** Documentation: * \brief Implementation of a configuration widget to use an Open IGT Link connection to track any device. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkOpenIGTLinkWidget : public QmitkAbstractTrackingDeviceWidget { Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) public: static const std::string VIEW_ID; QmitkOpenIGTLinkWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkOpenIGTLinkWidget() override; void Initialize() override; signals: protected slots : private: void CreateQtPartControl(QWidget *parent); protected: QmitkOpenIGTLinkWidget* Clone(QWidget* parent) const override; Ui::QmitkOpenIGTLinkWidget* m_Controls; public: - mitk::TrackingDevice::Pointer ConstructTrackingDevice() override; + virtual mitk::TrackingDevice::Pointer GetTrackingDevice() override; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.ui b/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.ui index a587c5fa52..d79cfdb81f 100644 --- a/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkOpenIGTLinkWidget.ui @@ -1,129 +1,133 @@ QmitkOpenIGTLinkWidget 0 0 294 - 169 + 140 <html><head/><body><p><span style=" text-decoration: underline;">Open IGT Link Connection</span></p></body></html> - - - Hostname: - - - - - - - 127.0.0.1 - - - - - + - + - Port: + Hostname: - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 50 - 16777215 - - + - 18944 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + 127.0.0.1 - - - - - - - Update Rate: - - + + + + + Port: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 16777215 + + + + 18944 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Update Rate: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 999 + + + 60 + + + + - + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - - - 1 - - - 999 - - - 60 - - - - - - - Qt::Vertical - - - - 20 - 66 - - - - diff --git a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.cpp index c1add0dd7a..3ef829be6d 100644 --- a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.cpp @@ -1,85 +1,299 @@ /*=================================================================== 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 "QmitkPolhemusTrackerWidget.h" #include #include - -#include +#include #include #include #include +#include +#include +#include "vtkRenderer.h" +#include "vtkCamera.h" + const std::string QmitkPolhemusTrackerWidget::VIEW_ID = "org.mitk.views.PolhemusTrackerWidget"; QmitkPolhemusTrackerWidget::QmitkPolhemusTrackerWidget(QWidget* parent, Qt::WindowFlags f) : QmitkAbstractTrackingDeviceWidget(parent, f) , m_Controls(nullptr) { } void QmitkPolhemusTrackerWidget::Initialize() { InitializeSuperclassWidget(); CreateQtPartControl(this); + + SetAdvancedSettingsEnabled(false); + on_m_AdvancedSettings_clicked(); //hide advanced settings on setup } QmitkPolhemusTrackerWidget::~QmitkPolhemusTrackerWidget() { delete m_Controls; } void QmitkPolhemusTrackerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPolhemusTrackerWidget; m_Controls->setupUi(parent); } } +void QmitkPolhemusTrackerWidget::OnToolStorageChanged() +{ + this->m_TrackingDevice = nullptr; + MITK_DEBUG<<"Resetting Polhemus Tracking Device, because tool storage changed."; +} + void QmitkPolhemusTrackerWidget::CreateConnections() { if (m_Controls) { - + connect((QObject*)(m_Controls->m_hemisphereTracking), SIGNAL(clicked()), this, SLOT(on_m_hemisphereTracking_clicked())); + connect((QObject*)(m_Controls->m_ToggleHemisphere), SIGNAL(clicked()), this, SLOT(on_m_ToggleHemisphere_clicked())); + connect((QObject*)(m_Controls->m_SetHemisphere), SIGNAL(clicked()), this, SLOT(on_m_SetHemisphere_clicked())); + connect((QObject*)(m_Controls->m_GetHemisphere), SIGNAL(clicked()), this, SLOT(on_m_GetHemisphere_clicked())); + connect((QObject*)(m_Controls->m_AdjustHemisphere), SIGNAL(clicked()), this, SLOT(on_m_AdjustHemisphere_clicked())); + connect((QObject*)(m_Controls->m_AdvancedSettings), SIGNAL(clicked()), this, SLOT(on_m_AdvancedSettings_clicked())); + connect((QObject*)(m_Controls->m_ToggleToolTipCalibration), SIGNAL(clicked()), this, SLOT(on_m_ToggleToolTipCalibration_clicked())); } } mitk::TrackingDevice::Pointer QmitkPolhemusTrackerWidget::GetTrackingDevice() { - if (m_TrackingDevice.IsNull()) m_TrackingDevice = ConstructTrackingDevice(); - return m_TrackingDevice; + if (m_TrackingDevice.IsNull()) + { + m_TrackingDevice = mitk::PolhemusTrackingDevice::New(); + m_TrackingDevice->SetHemisphereTrackingEnabled(m_Controls->m_hemisphereTracking->isChecked()); + } + + return static_cast(m_TrackingDevice); } +QmitkPolhemusTrackerWidget* QmitkPolhemusTrackerWidget::Clone(QWidget* parent) const +{ + QmitkPolhemusTrackerWidget* clonedWidget = new QmitkPolhemusTrackerWidget(parent); + clonedWidget->Initialize(); + return clonedWidget; +} -mitk::TrackingDevice::Pointer QmitkPolhemusTrackerWidget::ConstructTrackingDevice() +void QmitkPolhemusTrackerWidget::on_m_hemisphereTracking_clicked() { - mitk::PolhemusTrackingDevice::Pointer newDevice = mitk::PolhemusTrackingDevice::New(); - newDevice->SetHemisphereTrackingEnabled(m_Controls->m_hemisphereTracking->isChecked()); - return static_cast(newDevice); + m_TrackingDevice->SetHemisphereTrackingEnabled(m_Controls->m_hemisphereTracking->isChecked()); } +void QmitkPolhemusTrackerWidget::on_m_ToggleHemisphere_clicked() +{ + // Index 0 == All Tools == -1 for Polhemus interface; Index 2 == Tool 2 == 1 for Polhemus; etc... + m_TrackingDevice->ToggleHemisphere(GetSelectedToolIndex()); + MITK_INFO << "Toggle Hemisphere for tool " << m_Controls->m_ToolSelection->currentText().toStdString(); +} -QmitkPolhemusTrackerWidget* QmitkPolhemusTrackerWidget::Clone(QWidget* parent) const +void QmitkPolhemusTrackerWidget::on_m_SetHemisphere_clicked() { - QmitkPolhemusTrackerWidget* clonedWidget = new QmitkPolhemusTrackerWidget(parent); - clonedWidget->Initialize(); - return clonedWidget; + mitk::Vector3D _hemisphere; + mitk::FillVector3D(_hemisphere, m_Controls->m_Hemisphere_X->value(), m_Controls->m_Hemisphere_Y->value(), m_Controls->m_Hemisphere_Z->value()); + m_TrackingDevice->SetHemisphere(GetSelectedToolIndex(), _hemisphere); + + //If you set a hemisphere vector which is unequal (0|0|0), this means, that there is no hemisphere tracking any more + //disable the checkbox in case it was on before, so that it can be reactivated... + if (_hemisphere.GetNorm() != 0) + m_Controls->m_hemisphereTracking->setChecked(false); + + MITK_INFO << "Hemisphere set for tool " << m_Controls->m_ToolSelection->currentText().toStdString(); +} + +void QmitkPolhemusTrackerWidget::on_m_GetHemisphere_clicked() +{ + mitk::Vector3D _hemisphere = m_TrackingDevice->GetHemisphere(GetSelectedToolIndex()); + m_Controls->m_Hemisphere_X->setValue(_hemisphere[0]); + m_Controls->m_Hemisphere_Y->setValue(_hemisphere[1]); + m_Controls->m_Hemisphere_Z->setValue(_hemisphere[2]); + + QString label; + + if (m_TrackingDevice->GetHemisphereTrackingEnabled(GetSelectedToolIndex())) + { + label = "HemisphereTracking is ON for tool "; + label.append(m_Controls->m_ToolSelection->currentText()); + } + else if (GetSelectedToolIndex() == -1) + { + label = "HemisphereTracking is OFF for at least one tool."; + } + else + { + label = "HemisphereTracking is OFF for tool "; + label.append(m_Controls->m_ToolSelection->currentText()); + } + + m_Controls->m_StatusLabelHemisphereTracking->setText(label); + + MITK_INFO << "Updated SpinBox for Hemisphere of tool " << m_Controls->m_ToolSelection->currentText().toStdString(); +} + +void QmitkPolhemusTrackerWidget::on_m_AdjustHemisphere_clicked() +{ + int _tool = GetSelectedToolIndex(); + QMessageBox msgBox; + QString _text; + if (_tool == -1) + { + _text.append("Adjusting hemisphere for all tools."); + msgBox.setText(_text); + _text.clear(); + _text = tr("Please make sure, that the entire tools (including tool tip AND sensor) are placed in the positive x hemisphere. Press 'Adjust hemisphere' if you are ready."); + msgBox.setInformativeText(_text); + } + else + { + _text.append("Adjusting hemisphere for tool '"); + _text.append(m_Controls->m_ToolSelection->currentText()); + _text.append(tr("' at port %2.").arg(_tool)); + msgBox.setText(_text); + _text.clear(); + _text = tr("Please make sure, that the entire tool (including tool tip AND sensor) is placed in the positive x hemisphere. Press 'Adjust hemisphere' if you are ready."); + msgBox.setInformativeText(_text); + } + + QPushButton *adjustButton = msgBox.addButton(tr("Adjust hemisphere"), QMessageBox::ActionRole); + QPushButton *cancelButton = msgBox.addButton(QMessageBox::Cancel); + msgBox.exec(); + if (msgBox.clickedButton() == adjustButton) { + // adjust + m_TrackingDevice->AdjustHemisphere(_tool); + MITK_INFO << "Adjusting Hemisphere for tool " << m_Controls->m_ToolSelection->currentText().toStdString(); + } + else if (msgBox.clickedButton() == cancelButton) { + // abort + MITK_INFO << "Cancel 'Adjust hemisphere'. No harm done..."; + } } + +void QmitkPolhemusTrackerWidget::on_m_ToggleToolTipCalibration_clicked() +{ + if (m_Controls->m_ToolSelection->currentIndex() != 0) + { + mitk::PolhemusTool* _tool = dynamic_cast (this->m_TrackingDevice->GetToolByName(m_Controls->m_ToolSelection->currentText().toStdString())); + mitk::Point3D tip = _tool->GetToolTip().GetVectorFromOrigin()*(-1.); + mitk::Quaternion quat = _tool->GetToolTipOrientation().inverse(); + _tool->SetToolTip(tip, quat); + } + else + { + for (int i = 0; i < m_TrackingDevice->GetToolCount(); ++i) + { + mitk::PolhemusTool* _tool = dynamic_cast (this->m_TrackingDevice->GetTool(i)); + mitk::Point3D tip = _tool->GetToolTip().GetVectorFromOrigin()*(-1.); + mitk::Quaternion quat = _tool->GetToolTipOrientation().inverse(); + _tool->SetToolTip(tip, quat); + } + } +} + +void QmitkPolhemusTrackerWidget::OnConnected(bool _success) +{ + if (!_success) + { + this->m_TrackingDevice = nullptr; + return; + } + + SetAdvancedSettingsEnabled(true); + + if (m_TrackingDevice->GetToolCount() != m_Controls->m_ToolSelection->count()) + { + m_Controls->m_ToolSelection->clear(); + + m_Controls->m_ToolSelection->addItem("All Tools"); + + for (int i = 0; i < m_TrackingDevice->GetToolCount(); ++i) + { + m_Controls->m_ToolSelection->addItem(m_TrackingDevice->GetTool(i)->GetToolName()); + } + } +} + +void QmitkPolhemusTrackerWidget::OnStartTracking(bool _success) +{ + if (!_success) + return; + //Rotate mitk standard multi widget, so that the view matches the sensor. Positive x == right, y == front, z == down; + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToPosterior(); + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetVtkRenderer()->GetActiveCamera()->SetViewUp(0, 0, -1); + +} + +void QmitkPolhemusTrackerWidget::OnDisconnected(bool _success) +{ + if (!_success) + return; + SetAdvancedSettingsEnabled(false); +} + +void QmitkPolhemusTrackerWidget::SetAdvancedSettingsEnabled(bool _enable) +{ + m_Controls->m_ToolSelection->setEnabled(_enable); + m_Controls->label_toolsToChange->setEnabled(_enable); + m_Controls->label_UpdateOnRequest->setEnabled(_enable); + m_Controls->m_GetHemisphere->setEnabled(_enable); + m_Controls->m_Hemisphere_X->setEnabled(_enable); + m_Controls->m_Hemisphere_Y->setEnabled(_enable); + m_Controls->m_Hemisphere_Z->setEnabled(_enable); + m_Controls->m_SetHemisphere->setEnabled(_enable); + m_Controls->m_ToggleHemisphere->setEnabled(_enable); + m_Controls->m_AdjustHemisphere->setEnabled(_enable); + m_Controls->m_ToggleToolTipCalibration->setEnabled(_enable); +} + +void QmitkPolhemusTrackerWidget::on_m_AdvancedSettings_clicked() +{ + bool _enable = m_Controls->m_AdvancedSettings->isChecked(); + m_Controls->m_ToolSelection->setVisible(_enable); + m_Controls->label_toolsToChange->setVisible(_enable); + m_Controls->label_UpdateOnRequest->setVisible(_enable); + m_Controls->m_GetHemisphere->setVisible(_enable); + m_Controls->m_Hemisphere_X->setVisible(_enable); + m_Controls->m_Hemisphere_Y->setVisible(_enable); + m_Controls->m_Hemisphere_Z->setVisible(_enable); + m_Controls->m_SetHemisphere->setVisible(_enable); + m_Controls->m_ToggleHemisphere->setVisible(_enable); + m_Controls->m_AdjustHemisphere->setVisible(_enable); + m_Controls->m_ToggleToolTipCalibration->setVisible(_enable); + m_Controls->m_StatusLabelHemisphereTracking->setVisible(_enable); +} + +int QmitkPolhemusTrackerWidget::GetSelectedToolIndex() +{ + // Index 0 == All Tools == -1 for Polhemus interface; Index 1 == Tool 1 == 1 for Polhemus Interface; etc... + int _index = m_Controls->m_ToolSelection->currentIndex() - 1; + if (_index != -1) + { + //we need to find the internal Polhemus index for this tool. This is stored in the identifier of a navigation tool or as Port in PolhemusTool. + mitk::PolhemusTool* _tool = dynamic_cast(m_TrackingDevice->GetToolByName(m_Controls->m_ToolSelection->currentText().toStdString())); + _index = _tool->GetToolPort(); + } + return _index; +} \ No newline at end of file diff --git a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h index dfd41ec261..56c0595f3d 100644 --- a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.h @@ -1,65 +1,96 @@ /*=================================================================== 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 QmitkPolhemusTrackerWidget_H #define QmitkPolhemusTrackerWidget_H #include "ui_QmitkPolhemusTrackerWidget.h" #include "QmitkAbstractTrackingDeviceWidget.h" +#include /** Documentation: * \brief Implementation of a configuration widget for Polhemus Tracking Devices. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkPolhemusTrackerWidget : public QmitkAbstractTrackingDeviceWidget { Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) public: static const std::string VIEW_ID; QmitkPolhemusTrackerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkPolhemusTrackerWidget(); - mitk::TrackingDevice::Pointer GetTrackingDevice(); - virtual void Initialize(); signals: -protected slots : + protected slots : + void on_m_hemisphereTracking_clicked(); + void on_m_ToggleHemisphere_clicked(); + void on_m_SetHemisphere_clicked(); + void on_m_GetHemisphere_clicked(); + void on_m_AdjustHemisphere_clicked(); + void on_m_AdvancedSettings_clicked(); + void on_m_ToggleToolTipCalibration_clicked(); private: /// \brief Creation of the connections void CreateConnections(); void CreateQtPartControl(QWidget *parent); + void SetAdvancedSettingsEnabled(bool _enable); + + int GetSelectedToolIndex(); + protected: virtual QmitkPolhemusTrackerWidget* Clone(QWidget* parent) const; Ui::QmitkPolhemusTrackerWidget* m_Controls; - mitk::TrackingDevice::Pointer m_TrackingDevice; + mitk::PolhemusTrackingDevice::Pointer m_TrackingDevice; public: - virtual mitk::TrackingDevice::Pointer ConstructTrackingDevice(); + virtual mitk::TrackingDevice::Pointer GetTrackingDevice(); + /** + * \brief This function is called, when in the TrackingToolboxView "Connect" was clicked and the device is successful connected. + * Can e.g. be used to activate options of a tracking device only when it is connected. + */ + virtual void OnConnected( bool _success); + /** + * \brief This function is called, when in the TrackingToolboxView "Disconnect" was clicked and the device is successful disconnected. + * Can e.g. be used to activate/disactivate options of a tracking device. + */ + virtual void OnDisconnected(bool _success); + /** + * \brief This function is called, when in the TrackingToolboxView "Start Tracking" was clicked and the device successfully started tracking. + * Can e.g. be used to activate options of a tracking device only when tracking is started. + */ + virtual void OnStartTracking(bool _success); + /** + * \brief This function is called, when anything in the ToolStorage changed, e.g. AddTool or EditTool. + * ServiceListener is connected in the QmitkMITKIGTTrackingToolboxView. + */ + virtual void OnToolStorageChanged(); + }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui index 9dee4ebd75..eca4075ca9 100644 --- a/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkPolhemusTrackerWidget.ui @@ -1,52 +1,174 @@ QmitkPolhemusTrackerWidget 0 0 475 - 181 + 324 <!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:'MS Shell Dlg 2'; font-size:8pt; 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=" text-decoration: underline;">Polhemus Tracker</span></p></body></html> - + + + + + Enable hemisphere tracking (for all tools) + + + true + + + + + + + Show Advanced Settings + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + Tools to change: + + + + + + + - Enable hemisphere tracking + Spinbox values and label are only updated on request (click 'Get Hemisphere'). - - true + + + + + + + + Get Hemisphere + + + + + + + -10 + + + 10 + + + + + + + -10 + + + 10 + + + + + + + -10 + + + 10 + + + + + + + Set Hemisphere + + + + + + + + + + + + + + + + + + Toggle Hemisphere + + + + + + + Adjust Hemisphere + + + + + + + Toggle Tool Tip Calibration + + + + + Qt::Vertical 20 40 diff --git a/Modules/IGTUI/Qmitk/QmitkToolTrackingStatusWidget.cpp b/Modules/IGTUI/Qmitk/QmitkToolTrackingStatusWidget.cpp index 8e188a48d3..a46f603f9c 100644 --- a/Modules/IGTUI/Qmitk/QmitkToolTrackingStatusWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkToolTrackingStatusWidget.cpp @@ -1,272 +1,273 @@ /*=================================================================== 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 "QmitkToolTrackingStatusWidget.h" #include QmitkToolTrackingStatusWidget::QmitkToolTrackingStatusWidget(QWidget* parent) : QWidget(parent), m_Controls(nullptr), m_StatusLabels(nullptr), m_NavigationDatas(nullptr), m_NavDatasNewFlag(false) { m_ShowPositions = false; m_ShowQuaternions = false; m_Alignment = Qt::AlignHCenter; m_Style = QmitkToolTrackingStatusWidget::VerticalUpperStyle; CreateQtPartControl( this ); } void QmitkToolTrackingStatusWidget::SetStyle(QmitkToolTrackingStatusWidget::Style newStyle) { //set new style m_Style = newStyle; //update current labels to show them in the new style Refresh(); } void QmitkToolTrackingStatusWidget::SetShowPositions(bool enable) { m_ShowPositions = enable; //update current labels Refresh(); } void QmitkToolTrackingStatusWidget::SetShowQuaternions(bool enable) { m_ShowQuaternions = enable; //update current labels Refresh(); } void QmitkToolTrackingStatusWidget::SetTextAlignment(Qt::AlignmentFlag alignment) { m_Alignment = alignment; //update current labels Refresh(); } QmitkToolTrackingStatusWidget::~QmitkToolTrackingStatusWidget() { //m_Controls = nullptr; if (m_StatusLabels!=nullptr) {delete m_StatusLabels;} if (m_NavigationDatas != nullptr) { m_NavigationDatas->clear(); if (m_NavDatasNewFlag) { delete m_NavigationDatas; } } } void QmitkToolTrackingStatusWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToolTrackingStatusWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); //add empty label AddEmptyLabel(); } m_Context = us::GetModuleContext(); std::string m_Filter = "(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.NavigationToolStorage" + ")"; m_Context->AddServiceListener(this, &QmitkToolTrackingStatusWidget::OnServiceEvent, m_Filter); } void QmitkToolTrackingStatusWidget::OnServiceEvent(const us::ServiceEvent event) { if ((event.GetType() == us::ServiceEvent::MODIFIED) && (m_previewToolStorage.IsNotNull())) {this->PreShowTools(m_previewToolStorage);} } void QmitkToolTrackingStatusWidget::CreateConnections() { } void QmitkToolTrackingStatusWidget::SetNavigationDatas(std::vector* navDatas) { m_NavigationDatas = navDatas; m_previewToolStorage = nullptr; } void QmitkToolTrackingStatusWidget::AddNavigationData(mitk::NavigationData::Pointer nd) { if(m_NavigationDatas == nullptr) { m_NavigationDatas = new std::vector(); m_NavDatasNewFlag = true; m_previewToolStorage = nullptr; } m_NavigationDatas->push_back(nd); } void QmitkToolTrackingStatusWidget::Refresh(int posPrecision, int quatPrecision) { if(m_NavigationDatas == nullptr || m_NavigationDatas->size() <= 0) { RemoveGuiLabels(); AddEmptyLabel(); return; } mitk::NavigationData* navData; for(unsigned int i = 0; i < m_NavigationDatas->size(); i++) { navData = m_NavigationDatas->at(i).GetPointer(); QString name(navData->GetName()); QString pos = ""; QString quat = ""; if (m_ShowPositions) { mitk::Point3D position = navData->GetPosition(); pos = " [" + QString::number(position[0],'f',posPrecision) + ";" + QString::number(position[1],'f',posPrecision) + ";" + QString::number(position[2],'f',posPrecision) + "]"; } if (m_ShowQuaternions) { mitk::Quaternion quaternion = navData->GetOrientation(); quat = " / [qx:" + QString::number(quaternion.x(),'f',quatPrecision) + ";qy:" + QString::number(quaternion.y(),'f',quatPrecision) + ";qz:" + QString::number(quaternion.z(),'f',quatPrecision) + ";qr:" + QString::number(quaternion.r()) + "]"; } if(!(m_StatusLabels->at(i)->text() == name+pos+quat)) m_StatusLabels->at(i)->setText(name+pos+quat); if(navData->IsDataValid()) m_StatusLabels->at(i)->setStyleSheet("QLabel{background-color: #8bff8b }"); else m_StatusLabels->at(i)->setStyleSheet("QLabel{background-color: #ff7878 }"); } } void QmitkToolTrackingStatusWidget::ShowStatusLabels() { RemoveGuiLabels(); if(m_NavigationDatas == nullptr || m_NavigationDatas->size() <= 0) { RemoveGuiLabels(); AddEmptyLabel(); return; } m_StatusLabels = new QVector(); mitk::NavigationData* navData; QLabel* label; for(unsigned int i = 0; i < m_NavigationDatas->size(); i++) { navData = m_NavigationDatas->at(i).GetPointer(); QString name(navData->GetName()); label = new QLabel(name, this); label->setObjectName(name); label->setAlignment(m_Alignment | Qt::AlignVCenter); label->setFrameStyle(QFrame::Panel | QFrame::Sunken); m_StatusLabels->append(label); - if (m_Style == QmitkToolTrackingStatusWidget::VerticalUpperStyle) m_Controls->m_VerticalLayout->addWidget(m_StatusLabels->at(i)); - else m_Controls->m_GridLayout->addWidget(m_StatusLabels->at(i),0,i); + if (m_Style == QmitkToolTrackingStatusWidget::VerticalUpperStyle) + m_Controls->m_VerticalLayout->addWidget(m_StatusLabels->at(i)); + else m_Controls->m_GridLayout->addWidget(m_StatusLabels->at(i),i,0); } } void QmitkToolTrackingStatusWidget::PreShowTools(mitk::NavigationToolStorage::Pointer toolStorage) { RemoveGuiLabels(); QLabel* label; - for(int i = 0; i < toolStorage->GetToolCount(); i++) + for(unsigned int i = 0; i < toolStorage->GetToolCount(); i++) { QString name(toolStorage->GetTool(i)->GetToolName().c_str()); label = new QLabel(name, this); label->setObjectName(name); label->setAlignment(m_Alignment | Qt::AlignVCenter); label->setFrameStyle(QFrame::Panel | QFrame::Sunken); label->setStyleSheet("QLabel{background-color: #dddddd }"); if (m_Style == QmitkToolTrackingStatusWidget::VerticalUpperStyle) m_Controls->m_VerticalLayout->addWidget(label); else m_Controls->m_GridLayout->addWidget(label); } m_previewToolStorage = toolStorage; } void QmitkToolTrackingStatusWidget::RemoveStatusLabels() { //remove GUI elements RemoveGuiLabels(); //clear members if(m_StatusLabels != nullptr && m_StatusLabels->size() > 0) { delete m_StatusLabels; m_StatusLabels = new QVector< QLabel* >(); } if(m_NavigationDatas != nullptr && m_NavigationDatas->size() > 0) { if (m_NavDatasNewFlag) { delete m_NavigationDatas; m_NavDatasNewFlag = false; } m_NavigationDatas = new std::vector(); m_NavDatasNewFlag = true; } //add empty label AddEmptyLabel(); } void QmitkToolTrackingStatusWidget::RemoveGuiLabels() { while(m_Controls->m_GridLayout->count() > 0 || m_Controls->m_VerticalLayout->count() > 0) { if (m_Controls->m_GridLayout->count() > 0) { QWidget* actWidget = m_Controls->m_GridLayout->itemAt(0)->widget(); m_Controls->m_GridLayout->removeWidget(actWidget); delete actWidget; } else if (m_Controls->m_VerticalLayout->count() > 0) { QWidget* actWidget = m_Controls->m_VerticalLayout->itemAt(0)->widget(); m_Controls->m_VerticalLayout->removeWidget(actWidget); delete actWidget; } } } void QmitkToolTrackingStatusWidget::AddEmptyLabel() { //add a label which tells that no tools are loaded yet QLabel* label = new QLabel("No tools loaded yet.", this); label->setObjectName("No tools loaded yet."); label->setAlignment(m_Alignment | Qt::AlignVCenter); label->setFrameStyle(QFrame::Panel | QFrame::Sunken); label->setStyleSheet("QLabel{background-color: #dddddd }"); if (m_Style == QmitkToolTrackingStatusWidget::VerticalUpperStyle) m_Controls->m_VerticalLayout->addWidget(label); else m_Controls->m_GridLayout->addWidget(label); } diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp index 6ae2c4dbb5..8f1f07205e 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp @@ -1,347 +1,362 @@ /*=================================================================== 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 "QmitkTrackingDeviceConfigurationWidget.h" #include "mitkNDIPolarisTypeInformation.h" +#include "mitkNDIAuroraTypeInformation.h" #include const std::string QmitkTrackingDeviceConfigurationWidget::VIEW_ID = "org.mitk.views.trackingdeviceconfigurationwidget"; QmitkTrackingDeviceConfigurationWidget::QmitkTrackingDeviceConfigurationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) , m_Controls(nullptr) - , m_TrackingDevice(nullptr) , m_DeviceToWidgetIndexMap() { //initializations CreateQtPartControl(this); CreateConnections(); RefreshTrackingDeviceCollection(); //initialize a few UI elements AddOutput("
First Element selected"); //Order from Collection List //reset a few things ResetOutput(); //restore old UI settings LoadUISettings(); } QmitkTrackingDeviceConfigurationWidget::~QmitkTrackingDeviceConfigurationWidget() { StoreUISettings(); delete m_Controls; - m_TrackingDevice = nullptr; } void QmitkTrackingDeviceConfigurationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkTrackingDeviceConfigurationWidgetControls; m_Controls->setupUi(parent); } } void QmitkTrackingDeviceConfigurationWidget::CreateConnections() { if (m_Controls) { connect((QObject*)(m_Controls->m_TrackingDeviceChooser), SIGNAL(currentIndexChanged(int)), this, SLOT(TrackingDeviceChanged())); } } void QmitkTrackingDeviceConfigurationWidget::TrackingDeviceChanged() { const std::string currentDevice = this->GetCurrentDeviceName(); //show the correspondig widget m_Controls->m_TrackingSystemWidget->setCurrentIndex(m_DeviceToWidgetIndexMap[currentDevice]); //reset output ResetOutput(); AddOutput("
"); AddOutput(currentDevice); AddOutput(" selected"); QmitkAbstractTrackingDeviceWidget* widget = GetWidget(currentDevice); if (widget == nullptr || !widget->IsDeviceInstalled()) { AddOutput("
ERROR: not installed!"); } emit TrackingDeviceSelectionChanged(); } void QmitkTrackingDeviceConfigurationWidget::RefreshTrackingDeviceCollection() { // clean-up of stacked widget, drop-down box and map for (auto& item : m_DeviceToWidgetIndexMap) { m_Controls->m_TrackingSystemWidget->removeWidget(m_Controls->m_TrackingSystemWidget->widget(item.second)); MITK_INFO << "removing widget for device '" << item.first << "'"; } m_Controls->m_TrackingDeviceChooser->clear(); m_DeviceToWidgetIndexMap.clear(); // get tracking device type service references us::ModuleContext* context = us::GetModuleContext(); std::vector > deviceRefs = context->GetServiceReferences(); if (deviceRefs.empty()) { MITK_ERROR << "No tracking device type service found!"; return; } // get tracking device configuration widget service references std::vector > widgetRefs = context->GetServiceReferences(); if (widgetRefs.empty()) { MITK_ERROR << "No tracking device configuration widget service found!"; return; } const us::ServiceReference& deviceServiceReference = deviceRefs.front(); const us::ServiceReference& widgetServiceReference = widgetRefs.front(); mitk::TrackingDeviceTypeCollection* deviceTypeCollection = context->GetService(deviceServiceReference); mitk::TrackingDeviceWidgetCollection* deviceWidgetCollection = context->GetService(widgetServiceReference); for (auto name : deviceTypeCollection->GetTrackingDeviceTypeNames()) { // if the device is not included yet, add name to comboBox and widget to stackedWidget if (m_Controls->m_TrackingDeviceChooser->findText(QString::fromStdString(name)) == -1) { m_Controls->m_TrackingDeviceChooser->addItem(QString::fromStdString(name)); QWidget* current = deviceWidgetCollection->GetTrackingDeviceWidgetClone(name); if (current == nullptr) { MITK_WARN << "No widget for tracking device type " << name << " available. Please implement and register it!"; current = new QWidget(); } m_DeviceToWidgetIndexMap[name] = m_Controls->m_TrackingSystemWidget->addWidget(current); } } if (!m_DeviceToWidgetIndexMap.empty()) { m_Controls->m_TrackingDeviceChooser->setCurrentIndex(0); m_Controls->m_TrackingSystemWidget->setCurrentIndex(0); } context->UngetService(deviceServiceReference); context->UngetService(widgetServiceReference); } //######################### internal help methods ####################################### void QmitkTrackingDeviceConfigurationWidget::ResetOutput() { QmitkAbstractTrackingDeviceWidget* currentWidget = this->GetWidget(this->GetCurrentDeviceName()); if (currentWidget == nullptr) { return; } currentWidget->ResetOutput(); currentWidget->repaint(); } void QmitkTrackingDeviceConfigurationWidget::AddOutput(std::string s) { QmitkAbstractTrackingDeviceWidget* currentWidget = this->GetWidget(this->GetCurrentDeviceName()); if (currentWidget == nullptr) { return; } currentWidget->AddOutput(s); currentWidget->repaint(); } -mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConstructTrackingDevice() +mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::GetTrackingDevice() { QmitkAbstractTrackingDeviceWidget* currentWidget = this->GetWidget(this->GetCurrentDeviceName()); - if (currentWidget == nullptr) + if (currentWidget == nullptr || !currentWidget->IsDeviceInstalled()) { return nullptr; } - return currentWidget->ConstructTrackingDevice(); -} - -mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::GetTrackingDevice() -{ - m_TrackingDevice = ConstructTrackingDevice(); - if (m_TrackingDevice.IsNull() || !m_TrackingDevice->IsDeviceInstalled()) return nullptr; - else return this->m_TrackingDevice; + return currentWidget->GetTrackingDevice(); } void QmitkTrackingDeviceConfigurationWidget::StoreUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; std::string selectedDevice = this->GetCurrentDeviceName(); //Save settings for every widget //Don't use m_DeviceTypeCollection here, it's already unregistered, when deconstructor is called... for (int index = 0; index < m_Controls->m_TrackingSystemWidget->count(); index++) { QmitkAbstractTrackingDeviceWidget* widget = dynamic_cast(m_Controls->m_TrackingSystemWidget->widget(index)); if (widget != nullptr) { widget->StoreUISettings(); } } if (this->GetPersistenceService()) // now save the settings using the persistence service { mitk::PropertyList::Pointer propList = this->GetPersistenceService()->GetPropertyList(id); propList->Set("SelectedDevice", selectedDevice); } else // QSettings as a fallback if the persistence service is not available { QSettings settings; settings.beginGroup(QString::fromStdString(id)); settings.setValue("trackingDeviceChooser", QVariant(QString::fromStdString(selectedDevice))); settings.endGroup(); } } /** * @brief QmitkTrackingDeviceConfigurationWidget::LoadUISettings * * Precondition: * Make sure that QStackedWidget is already initialized, * e.g. by calling RefreshTrackingDeviceCollection() before. */ void QmitkTrackingDeviceConfigurationWidget::LoadUISettings() { //Load settings for every widget for (int index = 0; index < m_Controls->m_TrackingSystemWidget->count(); index++) { QmitkAbstractTrackingDeviceWidget* widget = dynamic_cast(m_Controls->m_TrackingSystemWidget->widget(index)); if (widget != nullptr) { widget->LoadUISettings(); } } std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; std::string selectedDevice; if (this->GetPersistenceService()) { mitk::PropertyList::Pointer propList = this->GetPersistenceService()->GetPropertyList(id); if (propList.IsNull()) { MITK_ERROR << "Property list for this UI (" << id << ") is not available, could not load UI settings!"; return; } propList->Get("SelectedDevice", selectedDevice); if (selectedDevice.empty()) { MITK_ERROR << "Loaded data from persistence service is invalid (SelectedDevice:" << selectedDevice << "): aborted to restore data!"; return; } MITK_INFO << "Successfully restored UI settings"; } else { // QSettings as a fallback if the persistence service is not available QSettings settings; settings.beginGroup(QString::fromStdString(id)); selectedDevice = settings.value("trackingDeviceChooser", "").toString().toStdString(); settings.endGroup(); } // The selected device requires some checks because a device that is not installed should not be restored to avoid bugs. // Use NDI Polaris as default if there's no widget registered for selected device or there's a widget for it but no device installed. const auto& deviceIterator = m_DeviceToWidgetIndexMap.find(selectedDevice); if (deviceIterator != m_DeviceToWidgetIndexMap.end()) { QmitkAbstractTrackingDeviceWidget* widget = dynamic_cast(m_Controls->m_TrackingSystemWidget->widget(deviceIterator->second)); if (widget == nullptr || (widget != nullptr && !widget->IsDeviceInstalled())) { selectedDevice = mitk::NDIPolarisTypeInformation::GetTrackingDeviceName(); } } else { selectedDevice = mitk::NDIPolarisTypeInformation::GetTrackingDeviceName(); } const int index = m_Controls->m_TrackingDeviceChooser->findText(QString::fromStdString(selectedDevice)); if (index >= 0) { m_Controls->m_TrackingDeviceChooser->setCurrentIndex(index); } else { MITK_ERROR << "Failed to load UI setting for tracking device configuration"; return; } m_Controls->m_TrackingSystemWidget->setCurrentIndex(m_DeviceToWidgetIndexMap[selectedDevice]); } std::string QmitkTrackingDeviceConfigurationWidget::GetCurrentDeviceName(void) const { return m_Controls->m_TrackingDeviceChooser->currentText().toStdString(); } QmitkAbstractTrackingDeviceWidget* QmitkTrackingDeviceConfigurationWidget::GetWidget(const std::string& deviceName) const { const auto& deviceIterator = m_DeviceToWidgetIndexMap.find(deviceName); if (deviceIterator != m_DeviceToWidgetIndexMap.end()) { QWidget* widget = m_Controls->m_TrackingSystemWidget->widget(deviceIterator->second); return dynamic_cast(widget); } return nullptr; } + +void QmitkTrackingDeviceConfigurationWidget::OnConnected(bool _success) +{ + this->GetWidget(this->GetCurrentDeviceName())->OnConnected(_success); +} +void QmitkTrackingDeviceConfigurationWidget::OnDisconnected(bool _success) +{ + this->GetWidget(this->GetCurrentDeviceName())->OnDisconnected(_success); +} + +void QmitkTrackingDeviceConfigurationWidget::OnStartTracking(bool _success) +{ + this->GetWidget(this->GetCurrentDeviceName())->OnStartTracking(_success); +} +void QmitkTrackingDeviceConfigurationWidget::OnStopTracking(bool _success) +{ + this->GetWidget(this->GetCurrentDeviceName())->OnStopTracking(_success); +} + +void QmitkTrackingDeviceConfigurationWidget::OnToolStorageChanged() +{ + this->GetWidget(this->GetCurrentDeviceName())->OnToolStorageChanged(); +} diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.h b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.h index a833054112..158a5dd2c3 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.h @@ -1,108 +1,135 @@ /*=================================================================== 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 QMITKTRACKINGDEVICECONFIGURATIONWIDGET_H #define QMITKTRACKINGDEVICECONFIGURATIONWIDGET_H #include #include #include "MitkIGTUIExports.h" #include "ui_QmitkTrackingDeviceConfigurationWidgetControls.h" #include "mitkTrackingDeviceTypeCollection.h" #include "mitkTrackingDeviceWidgetCollection.h" + /** Documentation: * \brief An object of this class offers an UI to configurate * a tracking device. If the user finished the configuration process and * a fully configurated tracking device is availiabe the object emits a * signal "TrackingDeviceConfigurationFinished()". You can then get the * tracking device by calling the method GetTrackingDevice(). * * Once the tracking device is configurated there are two ways to reset * the UI to allow the user for configuring a new device. The method Reset() * can be called and there is also a button "reset" which can be pressed by * the user. In both cases a signal "TrackingDeviceConfigurationReseted()" * is emitted and you may wait for a new configurated tracking device. * * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkTrackingDeviceConfigurationWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; QmitkTrackingDeviceConfigurationWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkTrackingDeviceConfigurationWidget() override; /* @return Returns the current configurated tracking device. If the user didn't finished the * configuration process or if there is an error during configuration nullptr is returned. */ mitk::TrackingDevice::Pointer GetTrackingDevice(); + /** + * \brief This function is called, when anything in the ToolStorage changed, e.g. AddTool or EditTool. + * ServiceListener is connected in the QmitkMITKIGTTrackingToolboxView. + */ + void OnToolStorageChanged(); + signals: /* @brief This signal is sent if the tracking device was changed. */ void TrackingDeviceSelectionChanged(); +public slots: +/** +* \brief This function is called, when in the TrackingToolboxView "Connect" was clicked and the device is successful connected. +* Can e.g. be used to activate options of a tracking device only when it is connected. +*/ + void OnConnected(bool _success); + /** + * \brief This function is called, when in the TrackingToolboxView "Disconnect" was clicked and the device is successful disconnected. + * Can e.g. be used to activate/disactivate options of a tracking device. + */ + void OnDisconnected(bool _success); + + /** + * \brief This function is called, when in the TrackingToolboxView "Start Tracking" was clicked and the device successfully started tracking. + * Can e.g. be used to activate options of a tracking device only when tracking is started. + */ + void OnStartTracking(bool _success); + /** + * \brief This function is called, when in the TrackingToolboxView "Stop Tracking" was clicked and the device successful stopped tracking. + * Can e.g. be used to activate/disactivate options when device is not tracking. + */ + void OnStopTracking(bool _success); + protected: /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkTrackingDeviceConfigurationWidgetControls* m_Controls; - mitk::TrackingDevice::Pointer m_TrackingDevice; - // key is port name (e.g. "COM1", "/dev/ttyS0"), value will be filled with the type of tracking device at this port typedef QMap PortDeviceMap; //######################### internal help methods ####################################### void ResetOutput(); void AddOutput(std::string s); - mitk::TrackingDevice::Pointer ConstructTrackingDevice(); void StoreUISettings(); void LoadUISettings(); /* @brief This method is called when the user clicks on "Refresh Selection" (m_RefreshTrackingDeviceCollection). It then sets the correct widget for the selected tracking device.*/ void RefreshTrackingDeviceCollection(); protected slots: /* @brief This method is called when the user changes the selection of the trackingdevice (m_trackingDeviceChooser). It then sets the correct widget for the selected tracking device.*/ void TrackingDeviceChanged(); private: PERSISTENCE_GET_SERVICE_METHOD_MACRO std::string GetCurrentDeviceName(void) const; QmitkAbstractTrackingDeviceWidget* GetWidget(const std::string& deviceName) const; /** * @brief Mapping of device type identifier and index of the configuration widget in QStackedWidget. */ std::map m_DeviceToWidgetIndexMap; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui index 2ea0ff23ac..31c9b7103b 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui @@ -1,218 +1,74 @@ QmitkTrackingDeviceConfigurationWidgetControls 0 0 - 366 - 536 + 446 + 603 0 0 Form - - - 0 - - - 0 - - - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + + + + + <!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:'MS Shell Dlg 2'; font-size:7.8pt; 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-size:10pt; font-weight:600;">Tracking Device Configuration</span></p></body></html> - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Qt::Horizontal - - - - 128 - 20 - - - - - - - - - 0 - 0 - - - - - - - - - - Qt::Horizontal - - - - - - - true - - - -1 - - - - - - - Qt::Vertical - - - - 20 - 50 - - - - - - - - - - - - - - 0 - + - - - - Qt::Vertical + + + + + 0 + 0 + - - - 20 - 289 - - - - - - - - - - - - true - - - - - 0 - 0 - 98 - 31 - - - - - - - - - - Qt::Vertical - - - - 20 - 269 - - - - - - - - - - - - - - 16777215 - 0 - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - + + + + + Qt::Horizontal + + + + + + + true + + + -1 + + + + diff --git a/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.cpp index 4b4a3db625..257b3fe1bc 100644 --- a/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.cpp @@ -1,94 +1,94 @@ /*=================================================================== 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 "QmitkVirtualTrackerWidget.h" #include "mitkVirtualTrackingDevice.h" const std::string QmitkVirtualTrackerWidget::VIEW_ID = "org.mitk.views.VirtualTrackerWidget"; QmitkVirtualTrackerWidget::QmitkVirtualTrackerWidget(QWidget* parent, Qt::WindowFlags f) : QmitkAbstractTrackingDeviceWidget(parent, f) , m_Controls(nullptr) { } void QmitkVirtualTrackerWidget::Initialize() { InitializeSuperclassWidget(); CreateQtPartControl(this); CreateConnections(); } QmitkVirtualTrackerWidget::~QmitkVirtualTrackerWidget() { delete m_Controls; } void QmitkVirtualTrackerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkVirtualTrackerWidget; m_Controls->setupUi(parent); } } void QmitkVirtualTrackerWidget::CreateConnections() { if (m_Controls) { connect((QObject*)(m_Controls->m_EnableGaussianNoise), SIGNAL(clicked()), this, SLOT(EnableGaussianNoise())); } } -mitk::TrackingDevice::Pointer QmitkVirtualTrackerWidget::ConstructTrackingDevice() +mitk::TrackingDevice::Pointer QmitkVirtualTrackerWidget::GetTrackingDevice() { // Create the Virtual Tracking Device mitk::VirtualTrackingDevice::Pointer returnValue = mitk::VirtualTrackingDevice::New(); if (m_Controls->m_EnableGaussianNoise->isChecked()) { returnValue->EnableGaussianNoise(); returnValue->SetParamsForGaussianNoise(m_Controls->m_MeanDistributionParam->value(), m_Controls->m_DeviationDistributionParam->value()); } return static_cast(returnValue); //static_cast necessary for compiling with Linux } void QmitkVirtualTrackerWidget::EnableGaussianNoise() { if (m_Controls->m_EnableGaussianNoise->isChecked()) { m_Controls->m_MeanDistributionParam->setEnabled(true); m_Controls->m_DeviationDistributionParam->setEnabled(true); } else { m_Controls->m_MeanDistributionParam->setEnabled(false); m_Controls->m_DeviationDistributionParam->setEnabled(false); } } QmitkVirtualTrackerWidget* QmitkVirtualTrackerWidget::Clone(QWidget* parent) const { QmitkVirtualTrackerWidget* clonedWidget = new QmitkVirtualTrackerWidget(parent); clonedWidget->Initialize(); clonedWidget->m_Controls->m_EnableGaussianNoise->setEnabled(m_Controls->m_EnableGaussianNoise->isEnabled()); clonedWidget->m_Controls->m_MeanDistributionParam->setValue(m_Controls->m_MeanDistributionParam->value()); clonedWidget->m_Controls->m_DeviationDistributionParam->setValue(m_Controls->m_DeviationDistributionParam->value()); return clonedWidget; } diff --git a/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.h b/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.h index d1cb353dfd..1a1913f4e6 100644 --- a/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.h @@ -1,61 +1,61 @@ /*=================================================================== 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 QmitkVirtualTrackerWidget_H #define QmitkVirtualTrackerWidget_H #include "ui_QmitkVirtualTrackerWidget.h" #include "QmitkAbstractTrackingDeviceWidget.h" /** Documentation: * \brief Implementation of a configuration widget for a Vitrual Tracking Device. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkVirtualTrackerWidget : public QmitkAbstractTrackingDeviceWidget { Q_OBJECT // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) public: static const std::string VIEW_ID; QmitkVirtualTrackerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkVirtualTrackerWidget() override; void Initialize() override; signals: protected slots : /* @brief Enables or disables the Gaussian Noise for the VirtualTrackingDevice dependent on the State of the according Checkbox */ void EnableGaussianNoise(); private: /// \brief Creation of the connections void CreateConnections(); void CreateQtPartControl(QWidget *parent); protected: QmitkVirtualTrackerWidget* Clone(QWidget* parent) const override; Ui::QmitkVirtualTrackerWidget* m_Controls; public: - mitk::TrackingDevice::Pointer ConstructTrackingDevice() override; + virtual mitk::TrackingDevice::Pointer GetTrackingDevice() override; }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.ui b/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.ui index 38a69d6c0a..df33c99c8d 100644 --- a/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkVirtualTrackerWidget.ui @@ -1,117 +1,121 @@ QmitkVirtualTrackerWidget 0 0 - 320 - 220 + 294 + 143 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:'MS Shell Dlg 2'; font-size:8pt; 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=" text-decoration: underline;">Virtual Tracker</span></p></body></html> - - - Simulate Jitter - - - - - + - + - Mean Distribution Parameter + Simulate Jitter - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - + + + + + Mean Distribution Parameter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + - - - - - - - Deviation Distribution Parameter - - + + + + + Deviation Distribution Parameter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + - + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 - - - - false - - - - - - - Qt::Vertical - - - - 20 - 81 - - - - diff --git a/Modules/IGTUI/files.cmake b/Modules/IGTUI/files.cmake index df2e5e6088..5773331a13 100644 --- a/Modules/IGTUI/files.cmake +++ b/Modules/IGTUI/files.cmake @@ -1,116 +1,113 @@ set(CPP_FILES Qmitk/QmitkTrackingDeviceWidget.cpp Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp Qmitk/QmitkNDIConfigurationWidget.cpp Qmitk/QmitkFiducialRegistrationWidget.cpp Qmitk/QmitkNDIToolDelegate.cpp Qmitk/QmitkNavigationToolManagementWidget.cpp Qmitk/QmitkIGTLoggerWidget.cpp Qmitk/QmitkUpdateTimerWidget.cpp Qmitk/QmitkToolDistanceWidget.cpp Qmitk/QmitkToolTrackingStatusWidget.cpp Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.cpp Qmitk/QmitkIGTPlayerWidget.cpp Qmitk/QmitkIGTConnectionWidget.cpp Qmitk/QmitkToolSelectionWidget.cpp Qmitk/QmitkNavigationToolCreationWidget.cpp - Qmitk/QmitkNavigationToolCreationAdvancedWidget.cpp Qmitk/QmitkNavigationDataSourceSelectionWidget.cpp Qmitk/QmitkInteractiveTransformationWidget.cpp Qmitk/QmitkNavigationToolStorageSelectionWidget.cpp Qmitk/QmitkNavigationDataPlayerControlWidget.cpp Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.cpp Qmitk/QmitkNDIAuroraWidget.cpp Qmitk/QmitkNDIPolarisWidget.cpp Qmitk/QmitkMicronTrackerWidget.cpp Qmitk/QmitkNPOptitrackWidget.cpp Qmitk/QmitkVirtualTrackerWidget.cpp Qmitk/QmitkOpenIGTLinkWidget.cpp Qmitk/mitkTrackingDeviceWidgetCollection.cpp Qmitk/QmitkTrackingDeviceConfigurationWidgetScanPortsWorker.cpp Qmitk/QmitkTrackingDeviceConfigurationWidgetConnectionWorker.cpp Qmitk/QmitkNDIAbstractDeviceWidget.cpp Qmitk/QmitkAbstractTrackingDeviceWidget.cpp Qmitk/QmitkIGTCommonHelper.cpp ) set(UI_FILES Qmitk/QmitkNavigationToolManagementWidgetControls.ui Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui Qmitk/QmitkNDIConfigurationWidget.ui Qmitk/QmitkFiducialRegistrationWidget.ui Qmitk/QmitkIGTLoggerWidgetControls.ui Qmitk/QmitkUpdateTimerWidgetControls.ui Qmitk/QmitkToolDistanceWidgetControls.ui Qmitk/QmitkToolTrackingStatusWidgetControls.ui Qmitk/QmitkTrackingSourcesCheckBoxPanelWidgetControls.ui Qmitk/QmitkIGTPlayerWidgetControls.ui Qmitk/QmitkIGTConnectionWidgetControls.ui Qmitk/QmitkToolSelectionWidgetControls.ui Qmitk/QmitkNavigationToolCreationWidget.ui - Qmitk/QmitkNavigationToolCreationAdvancedWidgetControls.ui Qmitk/QmitkNavigationDataSourceSelectionWidgetControls.ui Qmitk/QmitkInteractiveTransformationWidgetControls.ui Qmitk/QmitkNavigationToolStorageSelectionWidgetControls.ui Qmitk/QmitkNavigationDataPlayerControlWidget.ui Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.ui Qmitk/QmitkNDIAuroraWidget.ui Qmitk/QmitkNDIPolarisWidget.ui Qmitk/QmitkMicronTrackerWidget.ui Qmitk/QmitkNPOptitrackWidget.ui Qmitk/QmitkVirtualTrackerWidget.ui Qmitk/QmitkOpenIGTLinkWidget.ui ) set(MOC_H_FILES Qmitk/QmitkNavigationToolManagementWidget.h Qmitk/QmitkTrackingDeviceWidget.h Qmitk/QmitkTrackingDeviceConfigurationWidget.h Qmitk/QmitkNDIConfigurationWidget.h Qmitk/QmitkFiducialRegistrationWidget.h Qmitk/QmitkNDIToolDelegate.h Qmitk/QmitkIGTLoggerWidget.h Qmitk/QmitkUpdateTimerWidget.h Qmitk/QmitkToolDistanceWidget.h Qmitk/QmitkToolTrackingStatusWidget.h Qmitk/QmitkTrackingSourcesCheckBoxPanelWidget.h Qmitk/QmitkIGTPlayerWidget.h Qmitk/QmitkIGTConnectionWidget.h Qmitk/QmitkToolSelectionWidget.h Qmitk/QmitkNavigationToolCreationWidget.h - Qmitk/QmitkNavigationToolCreationAdvancedWidget.h Qmitk/QmitkNavigationDataSourceSelectionWidget.h Qmitk/QmitkInteractiveTransformationWidget.h Qmitk/QmitkNavigationToolStorageSelectionWidget.h Qmitk/QmitkNavigationDataPlayerControlWidget.h Qmitk/QmitkNavigationDataSequentialPlayerControlWidget.h Qmitk/QmitkNDIAuroraWidget.h Qmitk/QmitkNDIPolarisWidget.h Qmitk/QmitkMicronTrackerWidget.h Qmitk/QmitkNPOptitrackWidget.h Qmitk/QmitkVirtualTrackerWidget.h Qmitk/QmitkOpenIGTLinkWidget.h Qmitk/QmitkTrackingDeviceConfigurationWidgetScanPortsWorker.h Qmitk/QmitkTrackingDeviceConfigurationWidgetConnectionWorker.h Qmitk/QmitkNDIAbstractDeviceWidget.h Qmitk/QmitkAbstractTrackingDeviceWidget.h Qmitk/QmitkIGTCommonHelper.h ) if(MITK_USE_POLHEMUS_TRACKER) set(CPP_FILES ${CPP_FILES} Qmitk/QmitkPolhemusTrackerWidget.cpp) set(UI_FILES ${UI_FILES} Qmitk/QmitkPolhemusTrackerWidget.ui) set(MOC_H_FILES ${MOC_H_FILES} Qmitk/QmitkPolhemusTrackerWidget.h) endif(MITK_USE_POLHEMUS_TRACKER) set(QRC_FILES resources/IGTUI.qrc ) diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.cpp b/Modules/OpenIGTLink/mitkIGTLDevice.cpp index e8e38e7119..d5427bde0a 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.cpp +++ b/Modules/OpenIGTLink/mitkIGTLDevice.cpp @@ -1,562 +1,563 @@ /*=================================================================== 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 "mitkIGTLDevice.h" //#include "mitkIGTException.h" //#include "mitkIGTTimeStamp.h" #include #include #include #include #include #include //remove later #include //TODO: Which timeout is acceptable and also needed to transmit image data? Is there a maximum data limit? static const int SOCKET_SEND_RECEIVE_TIMEOUT_MSEC = 100; typedef itk::MutexLockHolder MutexLockHolder; mitk::IGTLDevice::IGTLDevice(bool ReadFully) : // m_Data(mitk::DeviceDataUnspecified), m_State(mitk::IGTLDevice::Setup), m_Name("Unspecified Device"), m_StopCommunication(false), m_Hostname("127.0.0.1"), m_PortNumber(-1), +m_LogMessages(false), m_MultiThreader(nullptr), m_SendThreadID(0), m_ReceiveThreadID(0), m_ConnectThreadID(0) { m_ReadFully = ReadFully; m_StopCommunicationMutex = itk::FastMutexLock::New(); m_StateMutex = itk::FastMutexLock::New(); // m_LatestMessageMutex = itk::FastMutexLock::New(); m_SendingFinishedMutex = itk::FastMutexLock::New(); m_ReceivingFinishedMutex = itk::FastMutexLock::New(); m_ConnectingFinishedMutex = itk::FastMutexLock::New(); // execution rights are owned by the application thread at the beginning m_SendingFinishedMutex->Lock(); m_ReceivingFinishedMutex->Lock(); m_ConnectingFinishedMutex->Lock(); m_MultiThreader = itk::MultiThreader::New(); // m_Data = mitk::DeviceDataUnspecified; // m_LatestMessage = igtl::MessageBase::New(); m_MessageFactory = mitk::IGTLMessageFactory::New(); m_MessageQueue = mitk::IGTLMessageQueue::New(); } mitk::IGTLDevice::~IGTLDevice() { /* stop communication and disconnect from igtl device */ if (GetState() == Running) { this->StopCommunication(); this->CloseConnection(); } else if (GetState() == Ready) { this->CloseConnection(); } /* cleanup tracking thread */ if (m_MultiThreader.IsNotNull()) { if ((m_SendThreadID != 0)) { m_MultiThreader->TerminateThread(m_SendThreadID); } if ((m_ReceiveThreadID != 0)) { m_MultiThreader->TerminateThread(m_ReceiveThreadID); } if ((m_ConnectThreadID != 0)) { m_MultiThreader->TerminateThread(m_ConnectThreadID); } } m_MultiThreader = nullptr; } mitk::IGTLDevice::IGTLDeviceState mitk::IGTLDevice::GetState() const { MutexLockHolder lock(*m_StateMutex); return m_State; } void mitk::IGTLDevice::SetState(IGTLDeviceState state) { itkDebugMacro("setting m_State to " << state); m_StateMutex->Lock(); // MutexLockHolder lock(*m_StateMutex); // lock and unlock the mutex if (m_State == state) { m_StateMutex->Unlock(); return; } m_State = state; m_StateMutex->Unlock(); this->Modified(); } bool mitk::IGTLDevice::TestConnection() { return true; } unsigned int mitk::IGTLDevice::ReceivePrivate(igtl::Socket* socket) { // Create a message buffer to receive header igtl::MessageHeader::Pointer headerMsg; headerMsg = igtl::MessageHeader::New(); // Initialize receive buffer headerMsg->InitPack(); // Receive generic header from the socket int r = socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), 0); //MITK_INFO << "Server received r = " << r; //MITK_INFO << "Received r = " << r; if (r == 0) //connection error { // an error was received, therefore the communication with this socket // must be stoppedy return IGTL_STATUS_NOT_PRESENT; } else if (r == -1) //timeout { // a timeout was received, this is no error state, thus, do nothing return IGTL_STATUS_TIME_OUT; } else if (r == headerMsg->GetPackSize()) { // Deserialize the header and check the CRC // ERROR HERE: This probably means the header data is corrupted... int crcCheck = headerMsg->Unpack(1); if (crcCheck & igtl::MessageHeader::UNPACK_HEADER) { // Allocate a time stamp igtl::TimeStamp::Pointer ts; ts = igtl::TimeStamp::New(); // Get time stamp igtlUint32 sec; igtlUint32 nanosec; headerMsg->GetTimeStamp(ts); ts->GetTimeStamp(&sec, &nanosec); // std::cerr << "Time stamp: " // << sec << "." // << nanosec << std::endl; // std::cerr << "Dev type and name: " << headerMsg->GetDeviceType() << " " // << headerMsg->GetDeviceName() << std::endl; // headerMsg->Print(std::cout); //check the type of the received message //if it is a GET_, STP_ or RTS_ command push it into the command queue //otherwise continue reading the whole message from the socket const char* curDevType = headerMsg->GetDeviceType(); if (std::strstr(curDevType, "GET_") != nullptr || std::strstr(curDevType, "STP_") != nullptr || std::strstr(curDevType, "RTS_") != nullptr) { this->m_MessageQueue->PushCommandMessage(headerMsg); this->InvokeEvent(CommandReceivedEvent()); return IGTL_STATUS_OK; } //Create a message according to the header message igtl::MessageBase::Pointer curMessage; curMessage = m_MessageFactory->CreateInstance(headerMsg); //check if the curMessage is created properly, if not the message type is //not supported and the message has to be skipped if (curMessage.IsNull()) { socket->Skip(headerMsg->GetBodySizeToRead(), 0); // MITK_ERROR("IGTLDevice") << "The received type is not supported. Please " // "add it to the message factory."; return IGTL_STATUS_NOT_FOUND; } //insert the header to the message and allocate the pack curMessage->SetMessageHeader(headerMsg); curMessage->AllocatePack(); // Receive transform data from the socket int receiveCheck = 0; receiveCheck = socket->Receive(curMessage->GetPackBodyPointer(), curMessage->GetPackBodySize(), m_ReadFully); if (receiveCheck > 0) { int c = curMessage->Unpack(1); if (!(c & igtl::MessageHeader::UNPACK_BODY)) { return IGTL_STATUS_CHECKSUM_ERROR; } //check the type of the received message //if it is a command push it into the command queue //otherwise into the normal receive queue //STP_ commands are handled here because they implemented additional //member variables that are not stored in the header message if (std::strstr(curDevType, "STT_") != nullptr) { this->m_MessageQueue->PushCommandMessage(curMessage); this->InvokeEvent(CommandReceivedEvent()); } else { if(m_LogMessages) MITK_INFO << "Received Message: " << mitk::IGTLMessage::New(curMessage)->ToString(); this->m_MessageQueue->PushMessage(curMessage); this->InvokeEvent(MessageReceivedEvent()); } return IGTL_STATUS_OK; } else { MITK_WARN("IGTLDevice") << "Received a valid header but could not " << "read the whole message."; return IGTL_STATUS_UNKNOWN_ERROR; } } else { //CRC check failed MITK_WARN << "CRC Check failed"; return IGTL_STATUS_CHECKSUM_ERROR; } } else { //Message size information and actual data size don't match. //this state is not suppossed to be reached, return unknown error MITK_WARN << "IGTL status unknown"; return IGTL_STATUS_UNKNOWN_ERROR; } } void mitk::IGTLDevice::SendMessage(mitk::IGTLMessage::Pointer msg) { m_MessageQueue->PushSendMessage(msg); } unsigned int mitk::IGTLDevice::SendMessagePrivate(mitk::IGTLMessage::Pointer msg, igtl::Socket::Pointer socket) { //check the input message if (msg.IsNull()) { MITK_ERROR("IGTLDevice") << "Could not send message because message is not " "valid. Please check."; return false; } igtl::MessageBase* sendMessage = msg->GetMessage(); // Pack (serialize) and send sendMessage->Pack(); int sendSuccess = socket->Send(sendMessage->GetPackPointer(), sendMessage->GetPackSize()); if (sendSuccess) { if (m_LogMessages) { MITK_INFO << "Send IGTL message: " << msg->ToString(); } this->InvokeEvent(MessageSentEvent()); return IGTL_STATUS_OK; } else { return IGTL_STATUS_UNKNOWN_ERROR; } } void mitk::IGTLDevice::RunCommunication(void (IGTLDevice::*ComFunction)(void), itk::FastMutexLock* mutex) { if (this->GetState() != Running) return; try { // keep lock until end of scope MutexLockHolder communicationFinishedLockHolder(*mutex); // Because m_StopCommunication is used by two threads, access has to be guarded // by a mutex. To minimize thread locking, a local copy is used here bool localStopCommunication; // update the local copy of m_StopCommunication this->m_StopCommunicationMutex->Lock(); localStopCommunication = this->m_StopCommunication; this->m_StopCommunicationMutex->Unlock(); while ((this->GetState() == Running) && (localStopCommunication == false)) { (this->*ComFunction)(); /* Update the local copy of m_StopCommunication */ this->m_StopCommunicationMutex->Lock(); localStopCommunication = m_StopCommunication; this->m_StopCommunicationMutex->Unlock(); // time to relax, this sets the maximum ever possible framerate to 1000 Hz itksys::SystemTools::Delay(1); } } catch (...) { mutex->Unlock(); this->StopCommunication(); MITK_ERROR("IGTLDevice::RunCommunication") << "Error while communicating. Thread stopped."; //mitkThrowException(mitk::IGTException) << "Error while communicating. Thread stopped."; } // StopCommunication was called, thus the mode should be changed back to Ready now // that the tracking loop has ended. //this->SetState(Ready); //this is done elsewhere MITK_DEBUG("IGTLDevice::RunCommunication") << "Reached end of communication."; // returning from this function (and ThreadStartCommunication()) // this will end the thread return; } bool mitk::IGTLDevice::StartCommunication() { if (this->GetState() != Ready) return false; // go to mode Running this->SetState(Running); // set a timeout for the sending and receiving this->m_Socket->SetTimeout(SOCKET_SEND_RECEIVE_TIMEOUT_MSEC); // update the local copy of m_StopCommunication this->m_StopCommunicationMutex->Lock(); this->m_StopCommunication = false; this->m_StopCommunicationMutex->Unlock(); // transfer the execution rights to tracking thread m_SendingFinishedMutex->Unlock(); m_ReceivingFinishedMutex->Unlock(); m_ConnectingFinishedMutex->Unlock(); // start new threads that execute the communication m_SendThreadID = m_MultiThreader->SpawnThread(this->ThreadStartSending, this); m_ReceiveThreadID = m_MultiThreader->SpawnThread(this->ThreadStartReceiving, this); m_ConnectThreadID = m_MultiThreader->SpawnThread(this->ThreadStartConnecting, this); // mitk::IGTTimeStamp::GetInstance()->Start(this); return true; } bool mitk::IGTLDevice::StopCommunication() { if (this->GetState() == Running) // Only if the object is in the correct state { // m_StopCommunication is used by two threads, so we have to ensure correct // thread handling m_StopCommunicationMutex->Lock(); m_StopCommunication = true; m_StopCommunicationMutex->Unlock(); // we have to wait here that the other thread recognizes the STOP-command // and executes it m_SendingFinishedMutex->Lock(); m_ReceivingFinishedMutex->Lock(); m_ConnectingFinishedMutex->Lock(); // mitk::IGTTimeStamp::GetInstance()->Stop(this); // notify realtime clock // StopCommunication was called, thus the mode should be changed back // to Ready now that the tracking loop has ended. this->SetState(Ready); } return true; } bool mitk::IGTLDevice::CloseConnection() { if (this->GetState() == Setup) { return true; } else if (this->GetState() == Running) { this->StopCommunication(); } m_Socket->CloseSocket(); /* return to setup mode */ this->SetState(Setup); // this->InvokeEvent(mitk::LostConnectionEvent()); return true; } bool mitk::IGTLDevice::SendRTSMessage(const char* type) { //construct the device type for the return message, it starts with RTS_ and //continues with the requested type std::string returnType("RTS_"); returnType.append(type); //create a return message igtl::MessageBase::Pointer rtsMsg = this->m_MessageFactory->CreateInstance(returnType); //if retMsg is nullptr there is no return message defined and thus it is not //necessary to send one back if (rtsMsg.IsNotNull()) { this->SendMessage(mitk::IGTLMessage::New(rtsMsg)); return true; } else { return false; } } void mitk::IGTLDevice::Connect() { MITK_DEBUG << "mitk::IGTLDevice::Connect();"; } igtl::ImageMessage::Pointer mitk::IGTLDevice::GetNextImage2dMessage() { return this->m_MessageQueue->PullImage2dMessage(); } igtl::ImageMessage::Pointer mitk::IGTLDevice::GetNextImage3dMessage() { return this->m_MessageQueue->PullImage3dMessage(); } igtl::TransformMessage::Pointer mitk::IGTLDevice::GetNextTransformMessage() { return this->m_MessageQueue->PullTransformMessage(); } igtl::TrackingDataMessage::Pointer mitk::IGTLDevice::GetNextTrackingDataMessage() { igtl::TrackingDataMessage::Pointer msg = this->m_MessageQueue->PullTrackingMessage(); return msg; } igtl::StringMessage::Pointer mitk::IGTLDevice::GetNextStringMessage() { return this->m_MessageQueue->PullStringMessage(); } igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextMiscMessage() { return this->m_MessageQueue->PullMiscMessage(); } igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextCommand() { return m_MessageQueue->PullCommandMessage(); } void mitk::IGTLDevice::EnableNoBufferingMode(bool enable) { m_MessageQueue->EnableNoBufferingMode(enable); } void mitk::IGTLDevice::EnableNoBufferingMode( mitk::IGTLMessageQueue::Pointer queue, bool enable) { queue->EnableNoBufferingMode(enable); } ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartSending(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; if (igtlDevice != nullptr) { igtlDevice->RunCommunication(&mitk::IGTLDevice::Send, igtlDevice->m_SendingFinishedMutex); } igtlDevice->m_SendThreadID = 0; // erase thread id because thread will end. return ITK_THREAD_RETURN_VALUE; } ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartReceiving(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; if (igtlDevice != nullptr) { igtlDevice->RunCommunication(&mitk::IGTLDevice::Receive, igtlDevice->m_ReceivingFinishedMutex); } igtlDevice->m_ReceiveThreadID = 0; // erase thread id because thread will end. return ITK_THREAD_RETURN_VALUE; } ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartConnecting(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; if (igtlDevice != nullptr) { igtlDevice->RunCommunication(&mitk::IGTLDevice::Connect, igtlDevice->m_ConnectingFinishedMutex); } igtlDevice->m_ConnectThreadID = 0; // erase thread id because thread will end. return ITK_THREAD_RETURN_VALUE; } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp index 7e4801aebc..984a97a282 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp @@ -1,410 +1,438 @@ /*=================================================================== 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 "QmitkIGTLDeviceSetupConnectionWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include #include #include #include //poco headers #include const std::string QmitkIGTLDeviceSetupConnectionWidget::VIEW_ID = "org.mitk.views.igtldevicesetupconnectionwidget"; QmitkIGTLDeviceSetupConnectionWidget::QmitkIGTLDeviceSetupConnectionWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_IsClient(false) { m_Controls = nullptr; this->m_IGTLDevice = nullptr; CreateQtPartControl(this); m_NumSentFramesSinceLastUpdate = 0; m_NumReceivedFramesSinceLastUpdate = 0; } QmitkIGTLDeviceSetupConnectionWidget::~QmitkIGTLDeviceSetupConnectionWidget() { this->RemoveObserver(); } void QmitkIGTLDeviceSetupConnectionWidget::RemoveObserver() { if (this->m_IGTLDevice.IsNotNull()) { this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); this->m_IGTLDevice->RemoveObserver(m_MessageSentObserverTag); this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); } } void QmitkIGTLDeviceSetupConnectionWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLDeviceSetupConnectionWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } // set the validator for the ip edit box (values must be between 0 and 255 and // there are four of them, seperated with a point QRegExpValidator *v = new QRegExpValidator(this); QRegExp rx("((1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})\\.){3,3}(1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})"); v->setRegExp(rx); m_Controls->editIP->setValidator(v); // set the validator for the port edit box (values must be between 1 and 65535) m_Controls->editPort->setValidator(new QIntValidator(1, 65535, this)); m_FPSCalculationTimer.start(1000); //connect slots with signals CreateConnections(); } void QmitkIGTLDeviceSetupConnectionWidget::CreateConnections() { if (m_Controls) { // connect the widget items with the methods connect(m_Controls->butConnect, SIGNAL(clicked()), this, SLOT(OnConnect())); connect(m_Controls->editPort, SIGNAL(editingFinished()), this, SLOT(OnPortChanged())); connect(m_Controls->editIP, SIGNAL(editingFinished()), this, SLOT(OnHostnameChanged())); connect(m_Controls->bufferInMsgCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnBufferIncomingMessages(int))); connect(m_Controls->bufferOutMsgCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnBufferOutgoingMessages(int))); connect(&m_FPSCalculationTimer, SIGNAL(timeout()), this, SLOT(OnUpdateFPSLabel())); + connect(m_Controls->logMessageDetailsCheckBox, SIGNAL(clicked()), + this, SLOT(OnLogMessageDetailsCheckBoxClicked())); } //this is used for thread seperation, otherwise the worker thread would change the ui elements //which would cause an exception connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState())); } void QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged() { emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceSetupConnectionWidget::AdaptGUIToState() { //check the validity of the device if (this->m_IGTLDevice.IsNull()) { return; } //check the state of the device mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); switch (state) { case mitk::IGTLDevice::Setup: if (!m_IsClient) { m_Controls->butConnect->setText("Go Online"); this->m_Controls->editIP->setEnabled(false); } else { m_Controls->butConnect->setText("Connect"); this->m_Controls->editIP->setEnabled(true); } this->m_Controls->editPort->setEnabled(true); - this->m_Controls->logIncomingMsg->setEnabled(false); - this->m_Controls->logOutgoingMsg->setEnabled(false); + this->m_Controls->logMessageStatusCheckBox->setChecked(false); + this->m_Controls->logMessageDetailsCheckBox->setChecked(false); + this->m_Controls->logMessageStatusCheckBox->setEnabled(false); + this->m_Controls->logMessageDetailsCheckBox->setEnabled(false); this->m_Controls->bufferInMsgCheckBox->setEnabled(false); this->m_Controls->bufferOutMsgCheckBox->setEnabled(false); this->m_Controls->butConnect->setEnabled(true); this->m_Controls->fpsInLabel->setEnabled(false); this->m_Controls->fpsOutLabel->setEnabled(false); this->m_Controls->fpsInDescrLabel->setEnabled(false); this->m_Controls->fpsOutDescrLabel->setEnabled(false); + + if( this->m_IGTLDevice.IsNotNull() ) + { + this->m_IGTLDevice->SetLogMessages(false); + } + break; case mitk::IGTLDevice::Ready: if (m_IsClient) { this->m_Controls->butConnect->setText("Disconnect"); } else { this->m_Controls->butConnect->setText("Go Offline"); } this->m_Controls->editIP->setEnabled(false); this->m_Controls->editPort->setEnabled(false); - this->m_Controls->logIncomingMsg->setEnabled(true); - this->m_Controls->logOutgoingMsg->setEnabled(true); + this->m_Controls->logMessageStatusCheckBox->setEnabled(true); + this->m_Controls->logMessageDetailsCheckBox->setEnabled(true); this->m_Controls->bufferInMsgCheckBox->setEnabled(true); this->m_Controls->bufferOutMsgCheckBox->setEnabled(true); this->m_Controls->butConnect->setEnabled(true); this->m_Controls->fpsInLabel->setEnabled(true); this->m_Controls->fpsOutLabel->setEnabled(true); this->m_Controls->fpsInDescrLabel->setEnabled(true); this->m_Controls->fpsOutDescrLabel->setEnabled(true); break; case mitk::IGTLDevice::Running: if (m_IsClient) { this->m_Controls->butConnect->setText("Disconnect"); } else { this->m_Controls->butConnect->setText("Go Offline"); } this->m_Controls->editIP->setEnabled(false); this->m_Controls->editPort->setEnabled(false); - this->m_Controls->logIncomingMsg->setEnabled(true); - this->m_Controls->logOutgoingMsg->setEnabled(true); + this->m_Controls->logMessageStatusCheckBox->setEnabled(true); + this->m_Controls->logMessageDetailsCheckBox->setEnabled(true); this->m_Controls->bufferInMsgCheckBox->setEnabled(true); this->m_Controls->bufferOutMsgCheckBox->setEnabled(true); this->m_Controls->butConnect->setEnabled(true); this->m_Controls->fpsInLabel->setEnabled(true); this->m_Controls->fpsOutLabel->setEnabled(true); this->m_Controls->fpsInDescrLabel->setEnabled(true); this->m_Controls->fpsOutDescrLabel->setEnabled(true); break; default: mitkThrow() << "Invalid Device State"; break; } } void QmitkIGTLDeviceSetupConnectionWidget::Initialize( mitk::IGTLDevice::Pointer device) { //reset the GUI DisableSourceControls(); //reset the observers this->RemoveObserver(); if (device.IsNotNull()) { this->m_IGTLDevice = device; //check if the device is a server or a client if (dynamic_cast( this->m_IGTLDevice.GetPointer()) == nullptr) { m_IsClient = false; } else { m_IsClient = true; } this->AdaptGUIToState(); typedef itk::SimpleMemberCommand< QmitkIGTLDeviceSetupConnectionWidget > CurCommandType; CurCommandType::Pointer messageSentCommand = CurCommandType::New(); messageSentCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageSent); this->m_MessageSentObserverTag = this->m_IGTLDevice->AddObserver( mitk::MessageSentEvent(), messageSentCommand); CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); messageReceivedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived); this->m_MessageReceivedObserverTag = this->m_IGTLDevice->AddObserver( mitk::MessageReceivedEvent(), messageReceivedCommand); CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); commandReceivedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived); this->m_CommandReceivedObserverTag = this->m_IGTLDevice->AddObserver( mitk::CommandReceivedEvent(), commandReceivedCommand); CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); connectionLostCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection); this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::LostConnectionEvent(), connectionLostCommand); CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection); this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); stateModifiedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged); this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( itk::ModifiedEvent(), stateModifiedCommand); OnBufferIncomingMessages(m_Controls->bufferInMsgCheckBox->isChecked()); OnBufferOutgoingMessages(m_Controls->bufferOutMsgCheckBox->isChecked()); } else { m_IGTLDevice = nullptr; } } void QmitkIGTLDeviceSetupConnectionWidget::DisableSourceControls() { m_Controls->editIP->setEnabled(false); m_Controls->editPort->setEnabled(false); m_Controls->butConnect->setEnabled(false); m_Controls->bufferInMsgCheckBox->setEnabled(false); m_Controls->bufferOutMsgCheckBox->setEnabled(false); - m_Controls->logIncomingMsg->setEnabled(false); - m_Controls->logOutgoingMsg->setEnabled(false); + this->m_Controls->logMessageStatusCheckBox->setChecked(false); + this->m_Controls->logMessageDetailsCheckBox->setChecked(false); + this->m_Controls->logMessageStatusCheckBox->setEnabled(false); + this->m_Controls->logMessageDetailsCheckBox->setEnabled(false); + + if( this->m_IGTLDevice.IsNotNull() ) + { + this->m_IGTLDevice->SetLogMessages(false); + } } void QmitkIGTLDeviceSetupConnectionWidget::OnConnect() { if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Setup) { QString port = m_Controls->editPort->text(); m_IGTLDevice->SetPortNumber(port.toInt()); std::string hostname = m_Controls->editIP->text().toStdString(); m_IGTLDevice->SetHostname(hostname); //connect with the other OpenIGTLink device => changes the state from Setup //to Ready if (m_IGTLDevice->OpenConnection()) { //starts the communication thread => changes the state from Ready to //Running if (m_IGTLDevice->StartCommunication()) { if (this->m_IsClient) { MITK_INFO("IGTLDeviceSourceManagementWidget") << "Successfully connected to " << hostname << " on port " << port.toStdString(); } } else { MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") << "Could not start a communication with the" "server because the client is in the wrong state"; } } else { MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") << "Could not connect to the server. " "Please check the hostname and port."; } } else if (m_IGTLDevice->GetState() == mitk::IGTLDevice::Ready || m_IGTLDevice->GetState() == mitk::IGTLDevice::Running) { m_IGTLDevice->CloseConnection(); MITK_INFO("QmitkIGTLDeviceSetupConnectionWidget") << "Closed connection"; } else { mitkThrow() << "Invalid state of IGTLDevice"; } this->AdaptGUIToState(); } void QmitkIGTLDeviceSetupConnectionWidget::OnPortChanged() { } void QmitkIGTLDeviceSetupConnectionWidget::OnHostnameChanged() { } void QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection() { emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection() { emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived() { - if (this->m_Controls->logIncomingMsg->isChecked()) + if( this->m_Controls->logMessageStatusCheckBox->isChecked() ) { - MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a message: " - << this->m_IGTLDevice->GetMessageQueue()->GetLatestMsgInformationString(); + MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a message."; } m_NumReceivedFramesSinceLastUpdate++; } void QmitkIGTLDeviceSetupConnectionWidget::OnMessageSent() { - if (this->m_Controls->logOutgoingMsg->isChecked()) + if( this->m_Controls->logMessageStatusCheckBox->isChecked() ) { MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Sent a message."; } m_NumSentFramesSinceLastUpdate++; } void QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived() { - if (this->m_Controls->logIncomingMsg->isChecked()) + if( this->m_Controls->logMessageStatusCheckBox->isChecked() ) { - MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a command: " - << this->m_IGTLDevice->GetMessageQueue()->GetLatestMsgInformationString(); + MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a command."; } } void QmitkIGTLDeviceSetupConnectionWidget::OnBufferIncomingMessages(int state) { if (this->m_IGTLDevice.IsNotNull()) { this->m_IGTLDevice->EnableNoBufferingMode( this->m_IGTLDevice->GetMessageQueue(), (bool)state); } } void QmitkIGTLDeviceSetupConnectionWidget::OnBufferOutgoingMessages(int state) { if (this->m_IGTLDevice.IsNotNull()) { this->m_IGTLDevice->EnableNoBufferingMode( this->m_IGTLDevice->GetMessageQueue(), (bool)state); } } void QmitkIGTLDeviceSetupConnectionWidget::OnUpdateFPSLabel() { double fpsIn = m_NumReceivedFramesSinceLastUpdate / 1.0; double fpsOut = m_NumSentFramesSinceLastUpdate / 1.0; this->m_Controls->fpsInLabel->setText(QString::number(fpsIn)); this->m_Controls->fpsOutLabel->setText(QString::number(fpsOut)); m_NumReceivedFramesSinceLastUpdate = 0; m_NumSentFramesSinceLastUpdate = 0; } + +void QmitkIGTLDeviceSetupConnectionWidget::OnLogMessageDetailsCheckBoxClicked() +{ + if( this->m_IGTLDevice.IsNull() ) + { + MITK_WARN << "Logging information not passed down to Message Provider."; + return; + } + else + { + this->m_IGTLDevice->SetLogMessages( this->m_Controls->logMessageDetailsCheckBox->isChecked() ); + } +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h index dab9020c04..b1dacabfa5 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h @@ -1,180 +1,185 @@ /*=================================================================== 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 QmitkIGTLDeviceSetupConnectionWidget_H #define QmitkIGTLDeviceSetupConnectionWidget_H //QT headers #include #include //mitk headers #include "MitkOpenIGTLinkUIExports.h" #include "mitkIGTLDeviceSource.h" #include "mitkIGTLClient.h" #include "mitkDataStorage.h" //itk #include //ui header #include "ui_QmitkIGTLDeviceSetupConnectionWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to setup the connection of an * OpenIGTLink device. * * * \ingroup OpenIGTLinkUI */ class MITKOPENIGTLINKUI_EXPORT QmitkIGTLDeviceSetupConnectionWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** * \brief Initializes the widget with the given device. * * The old device is * dropped, so be careful, if the source is not saved somewhere else it might * be lost. You might want to ask the user if he wants to save the changes * before calling this method. * \param device The widget will be initialized corresponding to the state of * this device. */ void Initialize(mitk::IGTLDevice::Pointer device); QmitkIGTLDeviceSetupConnectionWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkIGTLDeviceSetupConnectionWidget() override; // /** // * \brief Is called when the current device received a message // */ // void OnMessageReceived(itk::Object* caller, const itk::EventObject&); // /** // * \brief Is called when the current device received a command // */ // void OnCommandReceived(itk::Object* caller, const itk::EventObject&); /** * \brief Is called when the current device lost a connection to one of its * sockets */ void OnLostConnection(); /** * \brief Is called when the current device connected to another device */ void OnNewConnection(); /** * \brief Is called when the current device received a message */ void OnMessageReceived(); /** * \brief Is called when the current device received a message */ void OnMessageSent(); /** * \brief Is called when the current device received a command */ void OnCommandReceived(); protected slots: void OnConnect(); void OnPortChanged(); void OnHostnameChanged(); void OnUpdateFPSLabel(); + /** + * \brief Enables/Disables the detailed logging of incoming/outgoing messages + */ + void OnLogMessageDetailsCheckBoxClicked(); + /** * \brief Enables/Disables the buffering of incoming messages */ void OnBufferIncomingMessages(int state); /** * \brief Enables/Disables the buffering of outgoing messages * * This can be necessary when the data is faster produced then sent */ void OnBufferOutgoingMessages(int state); /** * \brief Adapts the GUI to the state of the device */ void AdaptGUIToState(); signals: /** * \brief used for thread seperation, the worker thread must not call AdaptGUIToState directly. * QT signals are thread safe and seperate the threads */ void AdaptGUIToStateSignal(); protected: /** * \brief Calls AdaptGUIToState() */ void OnDeviceStateChanged(); /** \brief Creation of the connections */ virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkIGTLDeviceSetupConnectionWidgetControls* m_Controls; /** @brief holds the OpenIGTLink device */ mitk::IGTLDevice::Pointer m_IGTLDevice; /** @brief flag to indicate if the IGTL device is a client or a server */ bool m_IsClient; unsigned long m_MessageSentObserverTag; unsigned long m_MessageReceivedObserverTag; unsigned long m_CommandReceivedObserverTag; unsigned long m_LostConnectionObserverTag; unsigned long m_NewConnectionObserverTag; unsigned long m_StateModifiedObserverTag; /** @brief the number of received frames (messages) since the last fps calculation update * * This counter is incremented every time a message is received. When the timer * m_FPSCalculationTimer is fired it is reset to 0 and the number is used to calculate the FPS */ unsigned int m_NumReceivedFramesSinceLastUpdate; /** @brief the number of sent frames (messages) since the last fps calculation update * * This counter is incremented every time a message is sent. When the timer * m_FPSCalculationTimer is fired it is reset to 0 and the number is used to calculate the FPS */ unsigned int m_NumSentFramesSinceLastUpdate; /** @brief the timer used to calculate the frames per second */ QTimer m_FPSCalculationTimer; //############## private help methods ####################### void DisableSourceControls(); // void EnableSourceControls(); void RemoveObserver(); }; #endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui index c976d33c47..ad460f826f 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui @@ -1,209 +1,212 @@ QmitkIGTLDeviceSetupConnectionWidgetControls 0 0 443 169 Form false Connect with the host/Start server Connect false false false false false Port Server-IP false Enter the port number of the host 18944 5 true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Port false Enter the IP address of the host 127.0.0.1 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + false - Enable this checkbox to log the send and receive message events + Enable/Disable the logging of incoming and outgoing messages in detail - Log Incoming Messages + Log Message Details false Incoming FPS: false 0 - + false + + Enable/Disable the logging of short status messages (i.e.: Sent/received message). + - Log Outgoing Messages + Log Short Status Messages false Buffer Outgoing Messages false If this checkbox is set the device stores all incoming messages in the queue. If it is not set it always overwrites the current value. Buffer Incoming Messages false false Outgoing FPS: false 0 diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp index 672254735e..171543d499 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp @@ -1,87 +1,106 @@ /*=================================================================== 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 "QmitkIGTLMessageSourceSelectionWidget.h" //mitk headers #include #include QmitkIGTLMessageSourceSelectionWidget::QmitkIGTLMessageSourceSelectionWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = nullptr; m_CurrentIGTLMessageSource = nullptr; CreateQtPartControl(this); } QmitkIGTLMessageSourceSelectionWidget::~QmitkIGTLMessageSourceSelectionWidget() { } void QmitkIGTLMessageSourceSelectionWidget::CreateQtPartControl(QWidget *parent) { if ( !m_Controls ) { // create GUI widgets m_Controls = new Ui::QmitkIGTLMessageSourceSelectionWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } CreateConnections(); } void QmitkIGTLMessageSourceSelectionWidget::CreateConnections() { if ( m_Controls ) { connect( m_Controls->m_ServiceListWidget, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(IGTLMessageSourceSelected(us::ServiceReferenceU)) ); //initialize service list widget std::string empty = ""; m_Controls->m_ServiceListWidget->Initialize( mitk::IGTLMessageSource::US_PROPKEY_DEVICENAME, empty); } } void QmitkIGTLMessageSourceSelectionWidget::IGTLMessageSourceSelected(us::ServiceReferenceU s) { if (!s) //nothing selected { //reset everything this->m_CurrentIGTLMessageSource = nullptr; emit IGTLMessageSourceSelected(this->m_CurrentIGTLMessageSource); return; } // Get storage us::ModuleContext* context = us::GetModuleContext(); this->m_CurrentIGTLMessageSource = context->GetService(s); emit IGTLMessageSourceSelected(this->m_CurrentIGTLMessageSource); } mitk::IGTLMessageSource::Pointer QmitkIGTLMessageSourceSelectionWidget::GetSelectedIGTLMessageSource() { return this->m_CurrentIGTLMessageSource; } + +mitk::IGTLMessageSource::Pointer QmitkIGTLMessageSourceSelectionWidget::AutoSelectFirstIGTLMessageSource() +{ + if( m_Controls->m_ServiceListWidget->GetAllServiceReferences().size() != 0 ) + { + us::ModuleContext* context = us::GetModuleContext(); + this->m_CurrentIGTLMessageSource = + context->GetService( + m_Controls->m_ServiceListWidget->GetAllServiceReferences().at(0) ); + } + else + { + this->m_CurrentIGTLMessageSource = nullptr; + MITK_WARN("CurrentIGTLMessageSource") << "There was no OpenIGTLink message source to select." + << "The OpenIGTLink message source must be selected manually."; + } + + return this->m_CurrentIGTLMessageSource; +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.h index 6ad1080bc2..0b98a6d68d 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.h +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.h @@ -1,87 +1,101 @@ /*=================================================================== 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 QmitkIGTLMessageSourceSelectionWidget_H #define QmitkIGTLMessageSourceSelectionWidget_H //QT headers #include //mitk headers #include "MitkOpenIGTLinkUIExports.h" #include "mitkIGTLMessageSource.h" //us #include //ui header #include "ui_QmitkIGTLMessageSourceSelectionWidgetControls.h" /** Documentation: * \brief This widget allows the user to select a OpenIGTLink message source. * * The widget lists all OpenIGTLink message sources which are available * as microservice via the module context. * * A signal is emmited whenever the selection changes. * * \ingroup OpenIGTLinkUI */ class MITKOPENIGTLINKUI_EXPORT QmitkIGTLMessageSourceSelectionWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; QmitkIGTLMessageSourceSelectionWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkIGTLMessageSourceSelectionWidget() override; /** @return Returns the currently selected OpenIGTLink message source. * Returns null if no source is selected at the moment. */ mitk::IGTLMessageSource::Pointer GetSelectedIGTLMessageSource(); + /** @brief Automatically selects the first available OpenIGTLink message source + * of the messageSourceSelectionWidget as message source and assigns it to the + * class member m_CurrentIGTLMessageSource. + * If there is no OpenIGTLink message source available, a nullptr will be assigned + * to the m_CurrentIGTLMessageSource. It is important to call this method whenever + * a new OpenIGTLink client connects to the active OpenIGTLink server. Otherwise, + * the connection between PLUS and MITK or between Slicer and MITK won't work + * automatically. + * + * @return The pointer to the automatically selected message source. This might + * be a nullptr, if there is no message source available. + */ + mitk::IGTLMessageSource::Pointer AutoSelectFirstIGTLMessageSource(); + signals: /** @brief This signal is emitted when a new OpenIGTLink message source is * selected. * @param source Holds the new selected OpenIGTLink device source. Is null * if the old source is deselected and no new source is selected. */ void IGTLMessageSourceSelected(mitk::IGTLMessageSource::Pointer source); protected slots: void IGTLMessageSourceSelected(us::ServiceReferenceU s); protected: /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkIGTLMessageSourceSelectionWidgetControls* m_Controls; mitk::IGTLMessageSource::Pointer m_CurrentIGTLMessageSource; }; #endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp index 4e9342e25d..7f7ea77605 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp @@ -1,375 +1,383 @@ /*=================================================================== 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 "QmitkIGTLStreamingManagementWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include #include #include #include //poco headers #include const std::string QmitkIGTLStreamingManagementWidget::VIEW_ID = "org.mitk.views.igtldevicesourcemanagementwidget"; QmitkIGTLStreamingManagementWidget::QmitkIGTLStreamingManagementWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_IsClient(false) { m_Controls = nullptr; this->m_IGTLDevice = nullptr; CreateQtPartControl(this); } QmitkIGTLStreamingManagementWidget::~QmitkIGTLStreamingManagementWidget() { this->RemoveObserver(); } void QmitkIGTLStreamingManagementWidget::RemoveObserver() { if (this->m_IGTLDevice.IsNotNull()) { this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); } if (this->m_IGTLMsgProvider.IsNotNull()) { this->m_IGTLMsgProvider->RemoveObserver(m_StartStreamingTimerObserverTag); this->m_IGTLMsgProvider->RemoveObserver(m_StopStreamingTimerObserverTag); } } void QmitkIGTLStreamingManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLStreamingManagementWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } //connect slots with signals CreateConnections(); } void QmitkIGTLStreamingManagementWidget::CreateConnections() { if (m_Controls) { connect((QObject*)(m_Controls->messageSourceSelectionWidget), SIGNAL(IGTLMessageSourceSelected(mitk::IGTLMessageSource::Pointer)), this, SLOT(SourceSelected(mitk::IGTLMessageSource::Pointer))); connect(m_Controls->startStreamPushButton, SIGNAL(clicked()), this, SLOT(OnStartStreaming())); connect(m_Controls->stopStreamPushButton, SIGNAL(clicked()), this, SLOT(OnStopStreaming())); } //this is used for thread seperation, otherwise the worker thread would change the ui elements //which would cause an exception connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState())); connect(this, SIGNAL(SelectSourceAndAdaptGUISignal()), this, SLOT(SelectSourceAndAdaptGUI())); } void QmitkIGTLStreamingManagementWidget::AdaptGUIToState() { if (this->m_IGTLMsgProvider.IsNotNull()) { //get the state of the device mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); switch (state) { case mitk::IGTLDevice::Setup: case mitk::IGTLDevice::Ready: m_Controls->messageSourceSelectionWidget->setEnabled(false); m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); break; case mitk::IGTLDevice::Running: //check the number of connections of the device, a server can be in //the running state even if there is no connected device, this part of //the GUI shall just be available when there is a connection if (this->m_IGTLDevice->GetNumberOfConnections() == 0) { m_Controls->messageSourceSelectionWidget->setEnabled(false); m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); } else //there is a connection { //check if the user already selected a source to stream if (this->m_IGTLMsgSource.IsNull()) // he did not so far { m_Controls->messageSourceSelectionWidget->setEnabled(true); m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); } else //user already selected a source { QString nameOfSource = QString::fromStdString(m_IGTLMsgSource->GetName()); m_Controls->messageSourceSelectionWidget->setEnabled(true); m_Controls->selectedSourceLabel->setText(nameOfSource); m_Controls->selectedSourceLabel->setEnabled(true); m_Controls->label->setEnabled(true); //check if the streaming is already running if (this->m_IGTLMsgProvider->IsStreaming()) { m_Controls->startStreamPushButton->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(true); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); } else { m_Controls->startStreamPushButton->setEnabled(true); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(true); m_Controls->fpsSpinBox->setEnabled(true); } } } break; default: mitkThrow() << "Invalid Device State"; break; } } else { this->DisableSourceControls(); } } void QmitkIGTLStreamingManagementWidget::LoadSource( mitk::IGTLMessageProvider::Pointer provider) { //reset the GUI DisableSourceControls(); if (provider.IsNull()) return; //reset the observers this->RemoveObserver(); //disconnect the timer disconnect(&this->m_StreamingTimer); this->m_IGTLMsgProvider = provider; //get the device this->m_IGTLDevice = this->m_IGTLMsgProvider->GetIGTLDevice(); //check if the device is a server or a client if (dynamic_cast( this->m_IGTLDevice.GetPointer()) == nullptr) { m_IsClient = false; } else { m_IsClient = true; } typedef itk::SimpleMemberCommand< QmitkIGTLStreamingManagementWidget > CurCommandType; // CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); // messageReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLStreamingManagementWidget::OnMessageReceived ); // this->m_MessageReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); // CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); // commandReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLStreamingManagementWidget::OnCommandReceived ); // this->m_CommandReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); connectionLostCommand->SetCallbackFunction( this, &QmitkIGTLStreamingManagementWidget::OnLostConnection); this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::LostConnectionEvent(), connectionLostCommand); CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkIGTLStreamingManagementWidget::OnNewConnection); this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); stateModifiedCommand->SetCallbackFunction( this, &QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged); this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( itk::ModifiedEvent(), stateModifiedCommand); CurCommandType::Pointer startStreamingTimerCommand = CurCommandType::New(); startStreamingTimerCommand->SetCallbackFunction( this, &QmitkIGTLStreamingManagementWidget::OnStartStreamingTimer); this->m_StartStreamingTimerObserverTag = this->m_IGTLMsgProvider->AddObserver( mitk::StreamingStartRequiredEvent(), startStreamingTimerCommand); CurCommandType::Pointer stopStreamingTimerCommand = CurCommandType::New(); stopStreamingTimerCommand->SetCallbackFunction( this, &QmitkIGTLStreamingManagementWidget::OnStopStreamingTimer); this->m_StopStreamingTimerObserverTag = this->m_IGTLMsgProvider->AddObserver( mitk::StreamingStopRequiredEvent(), stopStreamingTimerCommand); this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::DisableSourceControls() { m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->messageSourceSelectionWidget->setEnabled(false); } void QmitkIGTLStreamingManagementWidget::SourceSelected( mitk::IGTLMessageSource::Pointer source) { //reset everything this->DisableSourceControls(); if (source.IsNotNull()) //no source selected { this->m_IGTLMsgSource = source; m_Controls->selectedSourceLabel->setText(source->GetName().c_str()); m_Controls->selectedSourceLabel->setEnabled(true); } this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::OnStartStreaming() { unsigned int fps = this->m_Controls->fpsSpinBox->value(); this->m_IGTLMsgProvider->StartStreamingOfSource(this->m_IGTLMsgSource, fps); this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::OnStopStreaming() { this->m_IGTLMsgProvider->StopStreamingOfSource(this->m_IGTLMsgSource); this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::OnMessageReceived() { } void QmitkIGTLStreamingManagementWidget::OnCommandReceived() { } void QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged() { emit AdaptGUIToStateSignal(); } void QmitkIGTLStreamingManagementWidget::OnLostConnection() { emit AdaptGUIToStateSignal(); } void QmitkIGTLStreamingManagementWidget::OnNewConnection() { emit SelectSourceAndAdaptGUISignal(); } void QmitkIGTLStreamingManagementWidget::OnStartStreamingTimer() { if (this->m_IGTLMsgProvider.IsNotNull()) { //get the frame rate unsigned int interval = this->m_IGTLMsgProvider->GetStreamingTime(); //connect the update method connect(&m_StreamingTimer, SIGNAL(timeout()), this, SLOT(OnStreamingTimerTimeout())); //start the timer this->m_StreamingTimer.start(interval); } emit AdaptGUIToStateSignal(); } void QmitkIGTLStreamingManagementWidget::OnStopStreamingTimer() { //stop the timer this->m_StreamingTimer.stop(); //if the provider is still valid disconnect from it if (this->m_IGTLMsgProvider.IsNotNull()) { //disconnect the update method disconnect(&m_StreamingTimer, SIGNAL(timeout()), this, SLOT(OnStreamingTimerTimeout())); } emit AdaptGUIToStateSignal(); } void QmitkIGTLStreamingManagementWidget::OnStreamingTimerTimeout() { if (this->m_IGTLMsgSource.IsNotNull()) { this->m_IGTLMsgProvider->Update(); } } void QmitkIGTLStreamingManagementWidget::SelectSourceAndAdaptGUI() { - //get the current selection and call SourceSelected which will call AdaptGUI + //get the current selection (the auto-selected message source) and call + //SourceSelected which will call AdaptGUI mitk::IGTLMessageSource::Pointer curSelSrc = - m_Controls->messageSourceSelectionWidget->GetSelectedIGTLMessageSource(); + m_Controls->messageSourceSelectionWidget->AutoSelectFirstIGTLMessageSource(); SourceSelected(curSelSrc); + + if( curSelSrc.IsNotNull() ) + { + //automatically start streaming for better support and handling when using + //e.g. the US-module. + this->OnStartStreaming(); + } } diff --git a/Modules/ToFHardware/KinectV2/mitkKinectV2Device.cpp b/Modules/ToFHardware/KinectV2/mitkKinectV2Device.cpp index 8e85f6c9be..c2fcb0c689 100644 --- a/Modules/ToFHardware/KinectV2/mitkKinectV2Device.cpp +++ b/Modules/ToFHardware/KinectV2/mitkKinectV2Device.cpp @@ -1,354 +1,357 @@ /*=================================================================== 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 "mitkKinectV2Device.h" #include #include #include #include #include namespace mitk { + bool KinectV2Device::m_PrintFrameRate = false; KinectV2Device::KinectV2Device(): m_DistanceDataBuffer(nullptr), m_AmplitudeDataBuffer(nullptr), m_RGBDataBuffer(nullptr), m_DepthBufferSize(sizeof(float)*512*424), m_RGBBufferSize(3*1920*1080) { m_Controller = mitk::KinectV2Controller::New(); m_PolyData = vtkSmartPointer::New(); } KinectV2Device::~KinectV2Device() { } std::string GetDeviceName() { return "Microsoft Kinect 2 Device "; } bool KinectV2Device::OnConnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetDepthCaptureWidth(); this->m_CaptureHeight = m_Controller->GetDepthCaptureHeight(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; this->m_RGBImageWidth = m_Controller->GetRGBCaptureWidth(); this->m_RGBImageHeight = m_Controller->GetRGBCaptureHeight(); this->m_RGBPixelNumber = this->m_RGBImageWidth * this->m_RGBImageHeight; // allocate buffer this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_RGBDataBuffer = new unsigned char*[this->m_MaxBufferSize]; for (int i=0; im_MaxBufferSize; i++) { this->m_RGBDataBuffer[i] = new unsigned char[this->m_RGBPixelNumber*3]; } m_CameraConnected = true; } } return ok; } bool KinectV2Device::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); // clean-up only if camera was connected if (m_CameraConnected) { delete [] m_DistanceArray; delete [] m_AmplitudeArray; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_DistanceDataBuffer[i]; delete[] this->m_AmplitudeDataBuffer[i]; delete[] this->m_RGBDataBuffer[i]; } delete[] this->m_DistanceDataBuffer; delete[] this->m_AmplitudeDataBuffer; delete[] this->m_RGBDataBuffer; m_CameraConnected = false; } } return ok; } void KinectV2Device::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); this->m_Controller->GetAllData(this->m_DistanceDataBuffer[this->m_FreePos],this->m_AmplitudeDataBuffer[this->m_FreePos],this->m_RGBDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_WARN << "Camera not connected"; } } void KinectV2Device::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(10); } bool KinectV2Device::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } void KinectV2Device::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } ITK_THREAD_RETURN_TYPE KinectV2Device::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == nullptr) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == nullptr) { return ITK_THREAD_RETURN_VALUE; } KinectV2Device* toFCameraDevice = (KinectV2Device*)pInfo->UserData; if (toFCameraDevice!=nullptr) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the image data from the camera and write it at the next free position in the buffer toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetAllData(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_RGBDataBuffer[toFCameraDevice->m_FreePos]); //Here we get also the PolyData, because the kinect V2 SDK offers an excellent //default calibration and generates very nice, textured surfaces. The method //GetAllData of MITK-ToF does not allow for passing the surface. toFCameraDevice->m_PolyData = toFCameraDevice->m_Controller->GetVtkPolyData(); toFCameraDevice->m_ImageMutex->Unlock(); // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); bool generateTriangularMesh = false; toFCameraDevice->GetBoolProperty("GenerateTriangularMesh", generateTriangularMesh); toFCameraDevice->m_Controller->SetGenerateTriangularMesh(generateTriangularMesh); float triangulationThreshold = static_cast(toFCameraDevice->GetProperty("TriangulationThreshold"))->GetValue(); toFCameraDevice->m_Controller->SetTriangulationThreshold(triangulationThreshold); toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { overflow = true; } - if (toFCameraDevice->m_ImageSequence % n == 0) - { - printStatus = true; - } + if (overflow) { overflow = false; } - // print current framerate - if (printStatus) + if(m_PrintFrameRate) { - t2 = realTimeClock->GetCurrentStamp() - t1; - MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; - t1 = realTimeClock->GetCurrentStamp(); - printStatus = false; + if (toFCameraDevice->m_ImageSequence % n == 0) + { + printStatus = true; + } + // print current framerate + if (printStatus) + { + t2 = realTimeClock->GetCurrentStamp() - t1; + MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; + t1 = realTimeClock->GetCurrentStamp(); + printStatus = false; + } } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } void KinectV2Device::GetAmplitudes(float* amplitudeArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { memcpy(amplitudeArray, this->m_AmplitudeDataBuffer[this->m_CurrentPos], this->m_DepthBufferSize); imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void KinectV2Device::GetIntensities(float*, int&) { } void KinectV2Device::GetDistances(float* distanceArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { memcpy(distanceArray, this->m_DistanceDataBuffer[this->m_CurrentPos], this->m_DepthBufferSize); imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void KinectV2Device::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_WARN << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } // write image data to arrays m_ImageMutex->Lock(); memcpy(distanceArray, this->m_DistanceDataBuffer[pos], this->m_DepthBufferSize); memcpy(amplitudeArray, this->m_AmplitudeDataBuffer[pos], this->m_DepthBufferSize); memcpy(rgbDataArray, this->m_RGBDataBuffer[pos], this->m_RGBBufferSize); - vtkSmartPointer deepCopyOfPoly = vtkSmartPointer::New(); - deepCopyOfPoly->DeepCopy(this->m_PolyData); m_ImageMutex->Unlock(); //Since the standard method GetAllImages does not allow transfering a surface, //we use a property to pass the surface to the workbench. mitk::Surface::Pointer surface = mitk::Surface::New(); - surface->SetVtkPolyData( deepCopyOfPoly ); + surface->SetVtkPolyData(this->m_PolyData); this->SetProperty("ToFSurface", mitk::SmartPointerProperty::New( surface )); this->Modified(); } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } KinectV2Controller::Pointer KinectV2Device::GetController() { return this->m_Controller; } int KinectV2Device::GetRGBCaptureWidth() { return this->m_RGBImageWidth; } int KinectV2Device::GetRGBCaptureHeight() { return this->m_RGBImageHeight; } } diff --git a/Modules/ToFHardware/KinectV2/mitkKinectV2Device.h b/Modules/ToFHardware/KinectV2/mitkKinectV2Device.h index 26d1729f48..1cd03a0a69 100644 --- a/Modules/ToFHardware/KinectV2/mitkKinectV2Device.h +++ b/Modules/ToFHardware/KinectV2/mitkKinectV2Device.h @@ -1,148 +1,157 @@ /*=================================================================== 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 __mitkKinectV2Device_h #define __mitkKinectV2Device_h #include #include #include "mitkToFCameraDevice.h" #include "mitkKinectV2Controller.h" #include #include #include #include #include #include namespace mitk { /** * @brief Interface for all representations of Microsoft Kinect V2 devices. * Kinect2Device internally holds an instance of Kinect2Controller and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * * \throws mitkException In case of no connection, an exception is thrown! * * @ingroup ToFHardware */ class MITKKINECTV2_EXPORT KinectV2Device : public ToFCameraDevice { public: mitkClassMacro( KinectV2Device , ToFCameraDevice ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) + /** Prints the framerate to the console every 100 frames. + * Mainly for debugging, deactivated by default. + * Refers to a static variable, means it is acivated/deactivated + * for all instances. + */ + itkSetMacro(PrintFrameRate, bool); /*! \brief opens a connection to the ToF camera \throws mitkException In case of no connection, an exception is thrown! */ virtual bool OnConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates \throws mitkException In case of no connection, an exception is thrown! */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief updates the camera for image acquisition \throws mitkException In case of no connection, an exception is thrown! */ virtual void UpdateCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief Does nothing for Kinect V2 as there is no intensity data provided by the device. * * The method is an empty implementation, because the interface (ToFCameraDevice) requires it. */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray Contains the distance data as an array. \param amplitudeArray Contains the infrared image. \param intensityArray Does nothing for Kinect V2. \param sourceDataArray Does nothing for Kinect V2. \param requiredImageSequence The required image sequence number. \param capturedImageSequence Does nothing for Kinect V2. */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=nullptr); /*! \brief returns the corresponding camera controller */ KinectV2Controller::Pointer GetController(); /*! \brief returns the width of the RGB image */ int GetRGBCaptureWidth(); /*! \brief returns the height of the RGB image */ int GetRGBCaptureHeight(); protected: KinectV2Device(); ~KinectV2Device(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); + static bool m_PrintFrameRate; ///< prints the framerate to the console every 100 frames, deactivated by default KinectV2Controller::Pointer m_Controller; ///< corresponding CameraController float** m_DistanceDataBuffer; ///< buffer holding the last distance images float** m_AmplitudeDataBuffer; ///< buffer holding the last amplitude images unsigned char** m_RGBDataBuffer; ///< buffer holding the last RGB image + + size_t m_DepthBufferSize; ///< Size of depth buffer (i.e. memory size of depth and infrared image) size_t m_RGBBufferSize; ///< Size of RGB buffer (i.e. memory size of RGB image) vtkSmartPointer m_PolyData; ///< Surface generated via the Kinect V2 SDK with default/unknown calibration. }; } //END mitk namespace #endif diff --git a/Modules/US/USNavigation/files.cmake b/Modules/US/USNavigation/files.cmake index 7fdc9ef27f..b240daaede 100644 --- a/Modules/US/USNavigation/files.cmake +++ b/Modules/US/USNavigation/files.cmake @@ -1,7 +1,5 @@ SET(CPP_FILES mitkUSCombinedModality.cpp - Filter/mitkNavigationDataPassThroughFilter.cpp - Filter/mitkNeedleProjectionFilter.cpp Filter/mitkNodeDisplacementFilter.cpp ) diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp index 2cf1445a20..0266b86fee 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.cpp @@ -1,415 +1,427 @@ /*=================================================================== 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 "QmitkUSNavigationStepCombinedModality.h" #include "ui_QmitkUSNavigationStepCombinedModality.h" #include "mitkUSCombinedModality.h" #include "../Widgets/QmitkUSCombinedModalityEditWidget.h" #include #include #include +#include "mitkBaseRenderer.h" + QmitkUSNavigationStepCombinedModality::QmitkUSNavigationStepCombinedModality(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_LastCalibrationFilename(""), m_CalibrationLoadedNecessary(true), m_ListenerDeviceChanged(this, &QmitkUSNavigationStepCombinedModality::OnDevicePropertyChanged), ui(new Ui::QmitkUSNavigationStepCombinedModality) { ui->setupUi(this); // combined modality create widget should only be visible after button press ui->combinedModalityCreateWidget->setVisible(false); ui->combinedModalityEditWidget->setVisible(false); connect(ui->combinedModalityListWidget, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnDeviceSelectionChanged())); connect(ui->combinedModalityListWidget, SIGNAL(ServiceModified(us::ServiceReferenceU)), this, SLOT(OnDeviceSelectionChanged())); connect(ui->combinedModalityCreateWidget, SIGNAL(SignalAborted()), this, SLOT(OnCombinedModalityCreationExit())); connect(ui->combinedModalityCreateWidget, SIGNAL(SignalCreated()), this, SLOT(OnCombinedModalityCreationExit())); connect(ui->combinedModalityEditWidget, SIGNAL(SignalAborted()), this, SLOT(OnCombinedModalityEditExit())); connect(ui->combinedModalityEditWidget, SIGNAL(SignalSaved()), this, SLOT(OnCombinedModalityEditExit())); std::string filterOnlyCombinedModalities = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.USCombinedModality)(" + mitk::USCombinedModality::GetPropertyKeys().US_PROPKEY_CLASS + "=" + mitk::USCombinedModality::DeviceClassIdentifier + "))"; //std::string filter = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice))"; ui->combinedModalityListWidget->Initialize(mitk::USCombinedModality::US_PROPKEY_DEVICENAME); ui->combinedModalityListWidget->SetAutomaticallySelectFirstEntry(true); //try to load UI settings QSettings settings; settings.beginGroup(QString::fromStdString("QmitkUSNavigationStepCombinedModality")); m_LastCalibrationFilename = settings.value("LastCalibrationFilename", QVariant("")).toString().toStdString(); MITK_DEBUG << "PERSISTENCE load: " << m_LastCalibrationFilename; settings.endGroup(); } QmitkUSNavigationStepCombinedModality::~QmitkUSNavigationStepCombinedModality() { ui->combinedModalityListWidget->blockSignals(true); //save UI settings QSettings settings; settings.beginGroup(QString::fromStdString("QmitkUSNavigationStepCombinedModality")); settings.setValue("LastCalibrationFilename", QVariant(m_LastCalibrationFilename.c_str())); settings.endGroup(); MITK_DEBUG << "PERSISTENCE save: " << m_LastCalibrationFilename; //delete UI delete ui; } void QmitkUSNavigationStepCombinedModality::OnDeviceSelectionChanged() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); bool combinedModalitySelected = combinedModality.IsNotNull(); ui->calibrationGroupBox->setEnabled(combinedModalitySelected); ui->combinedModalityDeleteButton->setEnabled(combinedModalitySelected); ui->combinedModalitEditButton->setEnabled(combinedModalitySelected); if (!combinedModalitySelected || m_CombinedModality != combinedModality) { emit SignalNoLongerReadyForNextStep(); if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } if (combinedModalitySelected && combinedModality->GetUltrasoundDevice().IsNotNull()) { combinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } } m_CombinedModality = combinedModality; if (combinedModalitySelected) { bool calibrated = this->UpdateCalibrationState(); if (!m_CalibrationLoadedNecessary) { emit SignalReadyForNextStep(); } else { if (calibrated) { emit SignalReadyForNextStep(); } else { emit SignalNoLongerReadyForNextStep(); } } // enable disconnect button only if combined modality is connected or active ui->combinedModalityDistconnectButton->setEnabled(combinedModality->GetDeviceState() >= mitk::USCombinedModality::State_Connected); ui->combinedModalityActivateButton->setEnabled(combinedModality->GetDeviceState() < mitk::USCombinedModality::State_Activated); this->UpdateTrackingToolNames(); } else { ui->combinedModalityDistconnectButton->setEnabled(false); ui->combinedModalityActivateButton->setEnabled(false); } } void QmitkUSNavigationStepCombinedModality::OnLoadCalibration() { QString filename = QFileDialog::getOpenFileName(QApplication::activeWindow(), "Load Calibration", m_LastCalibrationFilename.c_str(), "Calibration files *.cal"); m_LastCalibrationFilename = filename.toStdString(); mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNull()) { ui->calibrationLoadStateLabel->setText("Selected device is no USCombinedModality."); emit SignalNoLongerReadyForNextStep(); return; } if (filename.isEmpty()) { bool calibrated = this->UpdateCalibrationState(); if (!calibrated) { emit SignalNoLongerReadyForNextStep(); } return; } QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { MITK_WARN << "Cannot open file '" << filename.toStdString() << "' for reading."; ui->calibrationLoadStateLabel->setText("Cannot open file '" + filename + "' for reading."); emit SignalNoLongerReadyForNextStep(); return; } QTextStream inStream(&file); m_LoadedCalibration = inStream.readAll().toStdString(); if (m_LoadedCalibration.empty()) { MITK_WARN << "Failed to load file. Unsupported format?"; ui->calibrationLoadStateLabel->setText("Failed to load file. Unsupported format?"); emit SignalNoLongerReadyForNextStep(); return; } try { combinedModality->DeserializeCalibration(m_LoadedCalibration); } catch (const mitk::Exception& /*exception*/) { MITK_WARN << "Failed to deserialize calibration. Unsuppoerted format?"; ui->calibrationLoadStateLabel->setText("Failed to deserialize calibration. Unsuppoerted format?"); emit SignalNoLongerReadyForNextStep(); return; } ui->calibrationLoadStateLabel->setText("Loaded calibration : " + filename); m_CombinedModality = combinedModality; emit SignalReadyForNextStep(); } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityCreateNewButtonClicked() { this->SetCombinedModalityCreateWidgetEnabled(true); } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityCreationExit() { this->SetCombinedModalityCreateWidgetEnabled(false); + try + { + mitk::RenderingManager::GetInstance()->InitializeViews(//Reinit + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetDataStorage()//GetDataStorage + ->GetNamedNode("US Support Viewing Stream")->GetData()->GetTimeGeometry());//GetNode + } + catch (...) + { + MITK_DEBUG << "No reinit possible"; + } } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityEditExit() { this->SetCombinedModalityEditWidgetEnabled(false); ui->combinedModalityEditWidget->SetCombinedModality(0); } void QmitkUSNavigationStepCombinedModality::OnDeleteButtonClicked() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { combinedModality->RemoveAllObservers(); combinedModality->UnregisterOnService(); } } void QmitkUSNavigationStepCombinedModality::OnCombinedModalityEditButtonClicked() { ui->combinedModalityEditWidget->SetCombinedModality(m_CombinedModality); this->SetCombinedModalityEditWidgetEnabled(true); } void QmitkUSNavigationStepCombinedModality::OnActivateButtonClicked() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { if (!combinedModality->GetIsConnected()) { combinedModality->Connect(); } if (!combinedModality->GetIsActive()) { combinedModality->Activate(); } } } void QmitkUSNavigationStepCombinedModality::OnDisconnectButtonClicked() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { if (combinedModality->GetIsActive()) { combinedModality->Deactivate(); } if (combinedModality->GetIsConnected()) { combinedModality->Disconnect(); } } } bool QmitkUSNavigationStepCombinedModality::OnStartStep() { return true; } bool QmitkUSNavigationStepCombinedModality::OnRestartStep() { return true; } bool QmitkUSNavigationStepCombinedModality::OnFinishStep() { mitk::USCombinedModality::Pointer combinedModality = this->GetSelectedCombinedModality(); if (combinedModality.IsNotNull()) { QApplication::setOverrideCursor(Qt::WaitCursor); // make sure that the combined modality is in connected state before using it if (combinedModality->GetDeviceState() < mitk::USDevice::State_Connected) { combinedModality->Connect(); } if (combinedModality->GetDeviceState() < mitk::USDevice::State_Activated) { combinedModality->Activate(); } QApplication::restoreOverrideCursor(); } emit SignalCombinedModalityChanged(combinedModality); this->CreateCombinedModalityResultAndSignalIt(); return true; } bool QmitkUSNavigationStepCombinedModality::OnActivateStep() { // make sure that device selection status is up-to-date this->OnDeviceSelectionChanged(); return true; } void QmitkUSNavigationStepCombinedModality::OnUpdate() { } QString QmitkUSNavigationStepCombinedModality::GetTitle() { return "Selection of Combined Modality"; } bool QmitkUSNavigationStepCombinedModality::GetIsRestartable() { return false; } void QmitkUSNavigationStepCombinedModality::SetCombinedModalityCreateWidgetEnabled(bool enabled) { ui->combinedModalityLabel->setVisible(!enabled); ui->combinedModalityListWidget->setVisible(!enabled); ui->combinedModalityCreateButton->setVisible(!enabled); ui->combinedModalityDeleteButton->setVisible(!enabled); ui->combinedModalitEditButton->setVisible(!enabled); ui->combinedModalityActivateButton->setVisible(!enabled); ui->combinedModalityDistconnectButton->setVisible(!enabled); ui->helpLabel->setVisible(!enabled); ui->calibrationGroupBox->setVisible(!enabled); ui->combinedModalityCreateWidget->setVisible(enabled); } void QmitkUSNavigationStepCombinedModality::SetCombinedModalityEditWidgetEnabled(bool enabled) { ui->combinedModalityLabel->setVisible(!enabled); ui->combinedModalityListWidget->setVisible(!enabled); ui->combinedModalityCreateButton->setVisible(!enabled); ui->combinedModalityDeleteButton->setVisible(!enabled); ui->combinedModalitEditButton->setVisible(!enabled); ui->combinedModalityActivateButton->setVisible(!enabled); ui->combinedModalityDistconnectButton->setVisible(!enabled); ui->helpLabel->setVisible(!enabled); ui->calibrationGroupBox->setVisible(!enabled); ui->combinedModalityEditWidget->setVisible(enabled); } void QmitkUSNavigationStepCombinedModality::CreateCombinedModalityResultAndSignalIt() { mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(); mitk::USDevice::Pointer usDevice = combinedModality->GetUltrasoundDevice(); // save identifiers and calibration to a result object mitk::DataNode::Pointer combinedModalityResult = mitk::DataNode::New(); combinedModalityResult->SetName("CombinedModalityResult"); combinedModalityResult->SetStringProperty("USNavigation::CombinedModality", std::string(combinedModality->GetManufacturer() + ": " + combinedModality->GetName() + " (" + combinedModality->GetComment() + ")").c_str()); combinedModalityResult->SetStringProperty("USNavigation::UltrasoundDevice", std::string(usDevice->GetManufacturer() + ": " + usDevice->GetName() + " (" + usDevice->GetComment() + ")").c_str()); combinedModalityResult->SetStringProperty("USNavigation::TrackingDevice", combinedModality->GetNavigationDataSource()->GetName().c_str()); combinedModalityResult->SetStringProperty("USNavigation::Calibration", combinedModality->SerializeCalibration().c_str()); emit SignalIntermediateResult(combinedModalityResult); } bool QmitkUSNavigationStepCombinedModality::UpdateCalibrationState() { if (m_CombinedModality.IsNull()) { return false; } bool calibrated = m_CombinedModality->GetContainsAtLeastOneCalibration(); if (calibrated) { ui->calibrationLoadStateLabel->setText("Selected device contains at least one calibration."); } else { ui->calibrationLoadStateLabel->setText("Selected device is not calibrated."); } return calibrated; } mitk::USCombinedModality::Pointer QmitkUSNavigationStepCombinedModality::GetSelectedCombinedModality() { // nothing more to do if no device is selected at the moment if (!ui->combinedModalityListWidget->GetIsServiceSelected()) { return 0; } mitk::USCombinedModality::Pointer combinedModality = ui->combinedModalityListWidget->GetSelectedService(); if (combinedModality.IsNull()) { MITK_WARN << "Selected device is no USCombinedModality."; } return combinedModality; } void QmitkUSNavigationStepCombinedModality::SetCalibrationLoadedNecessary(bool necessary) { m_CalibrationLoadedNecessary = necessary; } void QmitkUSNavigationStepCombinedModality::OnDevicePropertyChanged(const std::string& key, const std::string&) { // property changes only matter if the navigation step is currently active // (being sensitive to them in other states may even be dangerous) if (this->GetNavigationStepState() < QmitkUSAbstractNavigationStep::State_Active) { return; } // calibration state could have changed if the depth was changed if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) { bool calibrated = this->UpdateCalibrationState(); if (calibrated) { emit SignalReadyForNextStep(); } else { emit SignalNoLongerReadyForNextStep(); } } } void QmitkUSNavigationStepCombinedModality::UpdateTrackingToolNames() { //check if everything is initialized if (m_CombinedModality.IsNull()) { return; } mitk::NavigationDataSource::Pointer navigationDataSource = m_CombinedModality->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { return; } if (GetDataStorage(false).IsNull()) { return; } // get the settings node mitk::DataNode::Pointer settingsNode = this->GetNamedDerivedNode(DATANAME_SETTINGS, DATANAME_BASENODE); std::string needleNames; itk::ProcessObject::DataObjectPointerArray outputs = navigationDataSource->GetOutputs(); for (itk::ProcessObject::DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) { needleNames += std::string((static_cast(it->GetPointer()))->GetName()) + ";"; } // change the settings node only if the settings changed std::string oldProperty; if (!settingsNode->GetStringProperty("settings.needle-names", oldProperty) || oldProperty != needleNames || !settingsNode->GetStringProperty("settings.reference-names", oldProperty) || oldProperty != needleNames) { settingsNode->SetStringProperty("settings.needle-names", needleNames.c_str()); settingsNode->SetStringProperty("settings.reference-names", needleNames.c_str()); emit SignalSettingsNodeChanged(settingsNode); } } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp index fe43a0e31d..61c7b2e42d 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.cpp @@ -1,1020 +1,1017 @@ /*=================================================================== 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 "QmitkUSNavigationStepMarkerIntervention.h" #include "ui_QmitkUSNavigationStepMarkerIntervention.h" #include "mitkBaseRenderer.h" #include "mitkContourModel.h" #include "mitkNeedleProjectionFilter.h" #include "mitkNodeDisplacementFilter.h" #include "mitkSurface.h" #include "mitkTextAnnotation2D.h" #include #include #include "../Filter/mitkUSNavigationTargetIntersectionFilter.h" #include "../Filter/mitkUSNavigationTargetOcclusionFilter.h" #include "../Filter/mitkUSNavigationTargetUpdateFilter.h" #include "../USNavigationMarkerPlacement.h" #include "../Widgets/QmitkZoneProgressBar.h" #include "../mitkUSTargetPlacementQualityCalculator.h" #include "../Interactors/mitkUSPointMarkInteractor.h" #include "usModuleRegistry.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkSurface.h" // VTK #include "vtkCellLocator.h" #include "vtkDataSet.h" #include "vtkDoubleArray.h" #include "vtkFloatArray.h" #include "vtkIdList.h" #include "vtkLinearTransform.h" #include "vtkLookupTable.h" #include "vtkMath.h" #include "vtkOBBTree.h" #include "vtkPointData.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkSelectEnclosedPoints.h" #include "vtkSmartPointer.h" #include "vtkSphereSource.h" #include "vtkTransformPolyDataFilter.h" #include "vtkWarpScalar.h" QmitkUSNavigationStepMarkerIntervention::QmitkUSNavigationStepMarkerIntervention(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_NumberOfTargets(0), - m_TargetProgressBar(0), - m_PlannedTargetProgressBar(0), + m_PlannedTargetsNodes(), + m_ReachedTargetsNodes(), + m_TargetProgressBar(new QmitkZoneProgressBar(QString::fromStdString("Target: %1 mm"), 200, 0, this)), + m_PlannedTargetProgressBar(nullptr), m_CurrentTargetIndex(0), m_CurrentTargetReached(false), m_ShowPlanningColors(false), + m_PointMarkInteractor(mitk::USPointMarkInteractor::New()), + m_TargetNode(nullptr), + m_TargetColorLookupTableProperty(nullptr), + m_TargetSurface(nullptr), m_NeedleProjectionFilter(mitk::NeedleProjectionFilter::New()), m_NodeDisplacementFilter(mitk::NodeDisplacementFilter::New()), m_TargetUpdateFilter(mitk::USNavigationTargetUpdateFilter::New()), m_TargetOcclusionFilter(mitk::USNavigationTargetOcclusionFilter::New()), m_TargetIntersectionFilter(mitk::USNavigationTargetIntersectionFilter::New()), m_PlacementQualityCalculator(mitk::USTargetPlacementQualityCalculator::New()), m_TargetStructureWarnOverlay(mitk::TextAnnotation2D::New()), + m_ReferenceSensorName(), + m_NeedleSensorName(), m_ReferenceSensorIndex(1), m_NeedleSensorIndex(0), m_ListenerTargetCoordinatesChanged(this, &QmitkUSNavigationStepMarkerIntervention::UpdateTargetCoordinates), ui(new Ui::QmitkUSNavigationStepMarkerIntervention) { m_ActiveTargetColor[0] = 1; m_ActiveTargetColor[1] = 1; m_ActiveTargetColor[2] = 0; m_InactiveTargetColor[0] = 1; m_InactiveTargetColor[1] = 1; m_InactiveTargetColor[2] = 0.5; m_ReachedTargetColor[0] = 0.6; m_ReachedTargetColor[1] = 1; m_ReachedTargetColor[2] = 0.6; ui->setupUi(this); connect(ui->freezeImageButton, SIGNAL(SignalFreezed(bool)), this, SLOT(OnFreeze(bool))); connect(ui->backToLastTargetButton, SIGNAL(clicked()), this, SLOT(OnBackToLastTargetClicked())); connect(ui->targetReachedButton, SIGNAL(clicked()), this, SLOT(OnTargetLeft())); connect(this, SIGNAL(TargetReached(int)), this, SLOT(OnTargetReached())); connect(this, SIGNAL(TargetLeft(int)), this, SLOT(OnTargetLeft())); connect(ui->riskStructuresRangeWidget, SIGNAL(SignalZoneViolated(const mitk::DataNode *, mitk::Point3D)), this, SLOT(OnRiskZoneViolated(const mitk::DataNode *, mitk::Point3D))); - m_PointMarkInteractor = mitk::USPointMarkInteractor::New(); m_PointMarkInteractor->CoordinatesChangedEvent.AddListener(m_ListenerTargetCoordinatesChanged); this->GenerateTargetColorLookupTable(); - m_TargetProgressBar = new QmitkZoneProgressBar(QString::fromStdString("Target: %1 mm"), 200, 0, this); m_TargetProgressBar->SetTextFormatInvalid("Target is not on Needle Path"); ui->targetStructuresRangeLayout->addWidget(m_TargetProgressBar); m_TargetUpdateFilter->SetScalarArrayIdentifier("USNavigation::ReachedTargetScores"); } QmitkUSNavigationStepMarkerIntervention::~QmitkUSNavigationStepMarkerIntervention() { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(false); if (dataStorage.IsNotNull()) { // remove the node for the needle path mitk::DataNode::Pointer node = this->GetNamedDerivedNode("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if (node.IsNotNull()) { dataStorage->Remove(node); } } - if (m_SegmentationNode.IsNotNull()) - { - this->GetDataStorage()->Remove(m_SegmentationNode); - } - if (m_ForegroundModelPointsNode.IsNotNull()) - { - this->GetDataStorage()->Remove(m_ForegroundModelPointsNode); - } - delete ui; m_PointMarkInteractor->CoordinatesChangedEvent.RemoveListener(m_ListenerTargetCoordinatesChanged); } bool QmitkUSNavigationStepMarkerIntervention::OnStartStep() { m_NeedleProjectionFilter->SelectInput(m_NeedleSensorIndex); // create node for Needle Projection mitk::DataNode::Pointer node = this->GetNamedDerivedNodeAndCreate("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); node->SetData(m_NeedleProjectionFilter->GetProjection()); node->SetBoolProperty("show contour", true); // initialize warning overlay (and do not display it, yet) m_TargetStructureWarnOverlay->SetText("Warning: Needle is Inside the Target Structure."); m_TargetStructureWarnOverlay->SetVisibility(false); // set position and font size for the text overlay mitk::Point2D overlayPosition; overlayPosition.SetElement(0, 10.0f); overlayPosition.SetElement(1, 10.0f); m_TargetStructureWarnOverlay->SetPosition2D(overlayPosition); m_TargetStructureWarnOverlay->SetFontSize(18); // overlay should be red mitk::Color color; color[0] = 1; color[1] = 0; color[2] = 0; m_TargetStructureWarnOverlay->SetColor(color); mitk::ManualPlacementAnnotationRenderer::AddAnnotation(m_TargetStructureWarnOverlay.GetPointer(), "stdmulti.widget4"); return true; } bool QmitkUSNavigationStepMarkerIntervention::OnStopStep() { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); // remove all reached nodes from the data storage for (QVector>::iterator it = m_ReachedTargetsNodes.begin(); it != m_ReachedTargetsNodes.end(); ++it) { dataStorage->Remove(*it); } m_ReachedTargetsNodes.clear(); m_CurrentTargetIndex = 0; // reset button states ui->freezeImageButton->setEnabled(false); ui->backToLastTargetButton->setEnabled(false); ui->targetReachedButton->setEnabled(true); // make sure that it is unfreezed after stopping the step ui->freezeImageButton->Unfreeze(); // remove base node for reached targets from the data storage mitk::DataNode::Pointer reachedTargetsNode = this->GetNamedDerivedNode( QmitkUSAbstractNavigationStep::DATANAME_BASENODE, USNavigationMarkerPlacement::DATANAME_REACHED_TARGETS); if (reachedTargetsNode.IsNotNull()) { dataStorage->Remove(reachedTargetsNode); } return true; } bool QmitkUSNavigationStepMarkerIntervention::OnFinishStep() { return true; } bool QmitkUSNavigationStepMarkerIntervention::OnActivateStep() { this->ClearZones(); // clear risk zones before adding new ones // get target node from data storage and make sure that it contains data m_TargetNode = this->GetNamedDerivedNode(USNavigationMarkerPlacement::DATANAME_TARGETSURFACE, USNavigationMarkerPlacement::DATANAME_TUMOUR); if (m_TargetNode.IsNull() || m_TargetNode->GetData() == 0) { mitkThrow() << "Target node (" << USNavigationMarkerPlacement::DATANAME_TARGETSURFACE << ") must not be null."; } // get target data and make sure that it is a surface m_TargetSurface = dynamic_cast(m_TargetNode->GetData()); if (m_TargetSurface.IsNull()) { mitkThrow() << "Target node (" << USNavigationMarkerPlacement::DATANAME_TARGETSURFACE << ") data must be of type mitk::Surface"; } // delete progress bars for reinitializing them again afterwards if (m_PlannedTargetProgressBar) { ui->targetStructuresRangeLayout->removeWidget(m_PlannedTargetProgressBar); delete m_PlannedTargetProgressBar; m_PlannedTargetProgressBar = 0; } m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); this->UpdateTargetProgressDisplay(); mitk::DataNode::Pointer tumourNode = this->GetNamedDerivedNode(USNavigationMarkerPlacement::DATANAME_TUMOUR, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if (tumourNode.IsNotNull()) { // do not show tumour node during intervention (target surface is shown) tumourNode->SetBoolProperty("visible", false); // add tumour as a risk structure ui->riskStructuresRangeWidget->AddZone(tumourNode); } // set target structure for target update filter m_TargetUpdateFilter->SetTargetStructure(m_TargetNode); m_TargetOcclusionFilter->SetTargetStructure(m_TargetNode); // set lookup table of tumour node m_TargetNode->SetProperty("LookupTable", m_TargetColorLookupTableProperty); // mitk::DataNode::Pointer targetsBaseNode = this->GetNamedDerivedNode(USNavigationMarkerPlacement::DATANAME_TARGETS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); mitk::DataStorage::SetOfObjects::ConstPointer plannedTargetNodes; if (targetsBaseNode.IsNotNull()) { plannedTargetNodes = this->GetDataStorage()->GetDerivations(targetsBaseNode); } if (plannedTargetNodes.IsNotNull() && plannedTargetNodes->Size() > 0) { for (mitk::DataStorage::SetOfObjects::ConstIterator it = plannedTargetNodes->Begin(); it != plannedTargetNodes->End(); ++it) { m_PlannedTargetsNodes.push_back(it->Value()); } m_PlannedTargetProgressBar = new QmitkZoneProgressBar(QString::fromStdString("Planned Target"), 200, 0); ui->targetStructuresRangeLayout->addWidget(m_PlannedTargetProgressBar); } // add progress bars for risk zone nodes mitk::DataNode::Pointer zonesBaseNode = this->GetNamedDerivedNode(USNavigationMarkerPlacement::DATANAME_ZONES, QmitkUSAbstractNavigationStep::DATANAME_BASENODE); // only add progress bars if the base node for zones was created if (zonesBaseNode.IsNotNull()) { mitk::DataStorage::SetOfObjects::ConstPointer zoneNodes = this->GetDataStorage()->GetDerivations(zonesBaseNode); for (mitk::DataStorage::SetOfObjects::ConstIterator it = zoneNodes->Begin(); it != zoneNodes->End(); ++it) { ui->riskStructuresRangeWidget->AddZone(it->Value()); } m_TargetOcclusionFilter->SelectStartPositionInput(m_NeedleSensorIndex); m_TargetOcclusionFilter->SetObstacleStructures(zoneNodes); } return true; } bool QmitkUSNavigationStepMarkerIntervention::OnDeactivateStep() { ui->freezeImageButton->Unfreeze(); return true; } void QmitkUSNavigationStepMarkerIntervention::OnUpdate() { // get navigation data source and make sure that it is not null mitk::NavigationDataSource::Pointer navigationDataSource = this->GetCombinedModality()->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { MITK_ERROR("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Navigation Data Source of Combined Modality must not be null."; mitkThrow() << "Navigation Data Source of Combined Modality must not be null."; } ui->riskStructuresRangeWidget->UpdateDistancesToNeedlePosition(navigationDataSource->GetOutput(m_NeedleSensorIndex)); this->UpdateBodyMarkerStatus(navigationDataSource->GetOutput(m_ReferenceSensorIndex)); this->UpdateTargetColors(); this->UpdateTargetScore(); this->UpdateTargetViolationStatus(); } void QmitkUSNavigationStepMarkerIntervention::OnSettingsChanged(const itk::SmartPointer settingsNode) { if (settingsNode.IsNull()) { return; } int numberOfTargets; if (settingsNode->GetIntProperty("settings.number-of-targets", numberOfTargets)) { m_NumberOfTargets = numberOfTargets; m_TargetUpdateFilter->SetNumberOfTargets(numberOfTargets); m_PlacementQualityCalculator->SetOptimalAngle(m_TargetUpdateFilter->GetOptimalAngle()); } std::string referenceSensorName; if (settingsNode->GetStringProperty("settings.reference-name-selected", referenceSensorName)) { m_ReferenceSensorName = referenceSensorName; } std::string needleSensorName; if (settingsNode->GetStringProperty("settings.needle-name-selected", needleSensorName)) { m_NeedleSensorName = needleSensorName; } this->UpdateSensorsNames(); } QString QmitkUSNavigationStepMarkerIntervention::GetTitle() { return "Computer-assisted Intervention"; } bool QmitkUSNavigationStepMarkerIntervention::GetIsRestartable() { return true; } QmitkUSAbstractNavigationStep::FilterVector QmitkUSNavigationStepMarkerIntervention::GetFilter() { FilterVector filter; filter.push_back(m_NeedleProjectionFilter.GetPointer()); filter.push_back(m_NodeDisplacementFilter.GetPointer()); filter.push_back(m_TargetOcclusionFilter.GetPointer()); return filter; } void QmitkUSNavigationStepMarkerIntervention::OnSetCombinedModality() { mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNotNull()) { mitk::AffineTransform3D::Pointer calibration = combinedModality->GetCalibration(); if (calibration.IsNotNull()) { m_NeedleProjectionFilter->SetTargetPlane(calibration); } } ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); this->UpdateSensorsNames(); } void QmitkUSNavigationStepMarkerIntervention::OnTargetReached() { m_CurrentTargetReached = true; } void QmitkUSNavigationStepMarkerIntervention::OnTargetLeft() { m_CurrentTargetReached = false; m_CurrentTargetIndex++; if (m_CurrentTargetIndex >= 0 && static_cast(m_CurrentTargetIndex) >= m_NumberOfTargets) { ui->targetReachedButton->setDisabled(true); } ui->backToLastTargetButton->setEnabled(true); ui->freezeImageButton->setEnabled(true); this->UpdateTargetProgressDisplay(); if (m_ReachedTargetsNodes.size() < m_CurrentTargetIndex) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetName( (QString("Target ") + QString("%1").arg(m_CurrentTargetIndex, 2, 10, QLatin1Char('0'))).toStdString()); this->GetDataStorage()->Add( node, this->GetNamedDerivedNodeAndCreate(USNavigationMarkerPlacement::DATANAME_REACHED_TARGETS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE)); m_ReachedTargetsNodes.push_back(node); } mitk::DataNode::Pointer node = m_ReachedTargetsNodes.at(m_CurrentTargetIndex - 1); mitk::Surface::Pointer zone = mitk::Surface::New(); // create a vtk sphere with given radius vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(5); vtkData->SetCenter(0, 0, 0); vtkData->Update(); zone->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); // set vtk sphere and origin to data node node->SetData(zone); node->GetData()->GetGeometry()->SetOrigin( this->GetCombinedModality()->GetNavigationDataSource()->GetOutput(m_NeedleSensorIndex)->GetPosition()); node->SetColor(0.2, 0.9, 0.2); this->UpdateTargetCoordinates(node); } void QmitkUSNavigationStepMarkerIntervention::OnBackToLastTargetClicked() { if (m_CurrentTargetIndex < 1) { MITK_WARN << "Cannot go back to last target as there is no last target."; return; } m_CurrentTargetIndex--; if (m_ReachedTargetsNodes.size() > m_CurrentTargetIndex) { this->GetDataStorage()->Remove(m_ReachedTargetsNodes.last()); MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Removed Target " << m_ReachedTargetsNodes.size(); m_ReachedTargetsNodes.pop_back(); } if (m_CurrentTargetIndex == 0) { ui->backToLastTargetButton->setDisabled(true); } if (m_CurrentTargetIndex >= 0 && static_cast(m_CurrentTargetIndex) < m_NumberOfTargets) { ui->targetReachedButton->setEnabled(true); } ui->freezeImageButton->setEnabled(false); ui->freezeImageButton->Unfreeze(); this->UpdateTargetProgressDisplay(); m_TargetUpdateFilter->RemovePositionOfTarget(m_CurrentTargetIndex); } void QmitkUSNavigationStepMarkerIntervention::OnFreeze(bool freezed) { if (freezed) { this->GetCombinedModality()->SetIsFreezed(true); // load state machine and event config for data interactor m_PointMarkInteractor->LoadStateMachine("USPointMarkInteractions.xml", us::ModuleRegistry::GetModule("MitkUS")); m_PointMarkInteractor->SetEventConfig("globalConfig.xml"); if (m_CurrentTargetIndex < 1) { mitkThrow() << "Current target index has to be greater zero when freeze button is clicked."; } if (m_ReachedTargetsNodes.size() < m_CurrentTargetIndex) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetName( (QString("Target ") + QString("%1").arg(m_CurrentTargetIndex, 2, 10, QLatin1Char('0'))).toStdString()); this->GetDataStorage()->Add( node, this->GetNamedDerivedNodeAndCreate(USNavigationMarkerPlacement::DATANAME_REACHED_TARGETS, QmitkUSAbstractNavigationStep::DATANAME_BASENODE)); m_ReachedTargetsNodes.push_back(node); } m_PointMarkInteractor->SetDataNode(m_ReachedTargetsNodes.last()); } else { m_PointMarkInteractor->SetDataNode(0); this->GetCombinedModality()->SetIsFreezed(false); } } void QmitkUSNavigationStepMarkerIntervention::OnShowPlanningView(bool show) { m_ShowPlanningColors = show; } void QmitkUSNavigationStepMarkerIntervention::OnRiskZoneViolated(const mitk::DataNode *node, mitk::Point3D position) { MITK_INFO << "Risk zone (" << node->GetName() << ") violated at position " << position << "."; } void QmitkUSNavigationStepMarkerIntervention::ClearZones() { ui->riskStructuresRangeWidget->ClearZones(); // remove all reached target nodes from the data storage and clear the list mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); for (QVector::iterator it = m_ReachedTargetsNodes.begin(); it != m_ReachedTargetsNodes.end(); ++it) { if (it->IsNotNull()) { dataStorage->Remove(*it); } } m_ReachedTargetsNodes.clear(); } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetCoordinates(mitk::DataNode *dataNode) { m_NodeDisplacementFilter->ResetNodes(); for (QVector>::iterator it = m_ReachedTargetsNodes.begin(); it != m_ReachedTargetsNodes.end(); ++it) { if (it->IsNotNull() && (*it)->GetData() != 0) { m_NodeDisplacementFilter->AddNode(*it); } } mitk::BaseData *baseData = dataNode->GetData(); if (!baseData) { mitkThrow() << "Data of the data node must not be null."; } mitk::BaseGeometry::Pointer geometry = baseData->GetGeometry(); if (geometry.IsNull()) { mitkThrow() << "Geometry of the data node must not be null."; } m_TargetUpdateFilter->SetControlNode(m_CurrentTargetIndex - 1, dataNode); if (m_PlannedTargetsNodes.size() > m_CurrentTargetIndex - 1) { m_PlannedTargetsNodes.at(m_CurrentTargetIndex - 1)->SetVisibility(false); } MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Target " << m_CurrentTargetIndex << " reached at position " << geometry->GetOrigin(); this->CalculateTargetPlacementQuality(); } void QmitkUSNavigationStepMarkerIntervention::UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker) { if (bodyMarker.IsNull()) { MITK_ERROR("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Current Navigation Data for body marker of Combined Modality must not be null."; mitkThrow() << "Current Navigation Data for body marker of Combined Modality must not be null."; } bool valid = bodyMarker->IsDataValid(); // update body marker status label if (valid) { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume."); } else { ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume."); } ui->targetStructuresRangeGroupBox->setEnabled(valid); ui->riskStructuresRangeGroupBox->setEnabled(valid); } void QmitkUSNavigationStepMarkerIntervention::GenerateTargetColorLookupTable() { vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetHueRange(0.0, 0.33); lookupTable->SetSaturationRange(1.0, 1.0); lookupTable->SetValueRange(1.0, 1.0); lookupTable->SetTableRange(0.0, 1.0); lookupTable->Build(); mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); lut->SetVtkLookupTable(lookupTable); m_TargetColorLookupTableProperty = mitk::LookupTableProperty::New(lut); } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetColors() { if (m_TargetNode.IsNull()) { return; } m_TargetNode->SetColor(1, 1, 1); mitk::BaseData *targetNodeData = m_TargetNode->GetData(); if (targetNodeData == 0) { return; } mitk::Surface::Pointer targetNodeSurface = dynamic_cast(targetNodeData); vtkSmartPointer targetNodeSurfaceVtk = targetNodeSurface->GetVtkPolyData(); vtkPointData *targetPointData = targetNodeSurface->GetVtkPolyData()->GetPointData(); vtkFloatArray *scalars = dynamic_cast(targetPointData->GetScalars("USNavigation::Occlusion")); vtkFloatArray *targetScoreScalars; if (m_ShowPlanningColors) { targetScoreScalars = dynamic_cast(targetPointData->GetScalars("USNavigation::PlanningScalars")); } else { targetScoreScalars = dynamic_cast(targetPointData->GetScalars("USNavigation::ReachedTargetScores")); } if (!scalars || !targetScoreScalars) { return; } unsigned int numberOfTupels = scalars->GetNumberOfTuples(); vtkSmartPointer colors = vtkSmartPointer::New(); colors->SetNumberOfComponents(1); colors->SetNumberOfTuples(numberOfTupels); colors->SetName("Colors"); double color, intersection, markerScore; for (unsigned int n = 0; n < numberOfTupels; n++) { scalars->GetTuple(n, &intersection); targetScoreScalars->GetTuple(n, &markerScore); if (intersection > 0) { color = 0; } else { color = markerScore; } colors->SetTuple(n, &color); } if (numberOfTupels > 0) { targetNodeSurfaceVtk->GetPointData()->SetScalars(colors); targetNodeSurfaceVtk->GetPointData()->Update(); } } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetScore() { if (m_NeedleProjectionFilter->GetProjection()->GetSize() != 2) { return; } vtkSmartPointer targetSurfaceVtk = m_TargetSurface->GetVtkPolyData(); m_TargetIntersectionFilter->SetTargetSurface(m_TargetSurface); m_TargetIntersectionFilter->SetLine(m_NeedleProjectionFilter->GetProjection()); m_TargetIntersectionFilter->CalculateIntersection(); if (m_TargetIntersectionFilter->GetIsIntersecting()) { vtkFloatArray *scalars = dynamic_cast(targetSurfaceVtk->GetPointData()->GetScalars("USNavigation::ReachedTargetScores")); double score; scalars->GetTuple(m_TargetIntersectionFilter->GetIntersectionNearestSurfacePointId(), &score); double color[3]; m_TargetColorLookupTableProperty->GetLookupTable()->GetVtkLookupTable()->GetColor(score, color); float colorF[3]; colorF[0] = color[0]; colorF[1] = color[1]; colorF[2] = color[2]; m_TargetProgressBar->SetColor(colorF); m_TargetProgressBar->SetBorderColor(colorF); m_TargetProgressBar->setValue(m_TargetIntersectionFilter->GetDistanceToIntersection()); if (m_PlannedTargetProgressBar) { vtkFloatArray *scalars = dynamic_cast(targetSurfaceVtk->GetPointData()->GetScalars("USNavigation::PlanningScalars")); if (scalars) { double score; scalars->GetTuple(m_TargetIntersectionFilter->GetIntersectionNearestSurfacePointId(), &score); double color[3]; m_TargetColorLookupTableProperty->GetLookupTable()->GetVtkLookupTable()->GetColor(score, color); float colorF[3]; colorF[0] = color[0]; colorF[1] = color[1]; colorF[2] = color[2]; m_PlannedTargetProgressBar->SetColor(colorF); m_PlannedTargetProgressBar->SetBorderColor(colorF); m_PlannedTargetProgressBar->SetTextFormatValid("Planned Target: %1 mm"); mitk::Point3D intersectionPoint = m_TargetIntersectionFilter->GetIntersectionPoint(); mitk::ScalarType minDistance = -1; for (QVector>::iterator it = m_PlannedTargetsNodes.begin(); it != m_PlannedTargetsNodes.end(); ++it) { mitk::ScalarType distance = intersectionPoint.EuclideanDistanceTo((*it)->GetData()->GetGeometry()->GetOrigin()); if (minDistance < 0 || distance < minDistance) { minDistance = distance; } } m_PlannedTargetProgressBar->setValue(minDistance); } } } else { m_TargetProgressBar->setValueInvalid(); } } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetProgressDisplay() { QString description; if (m_CurrentTargetIndex >= static_cast(m_NumberOfTargets)) { description = "All Targets Reached"; if (m_TargetProgressBar) { m_TargetProgressBar->hide(); } } else { description = QString("Distance to Target ") + QString::number(m_CurrentTargetIndex + 1) + QString(" of ") + QString::number(m_NumberOfTargets); if (m_TargetProgressBar) { m_TargetProgressBar->show(); } } ui->targetStructuresRangeGroupBox->setTitle(description); } void QmitkUSNavigationStepMarkerIntervention::UpdatePlannedTargetProgressDisplay() { // make sure that the needle projection consists of two points if (m_NeedleProjectionFilter->GetProjection()->GetSize() != 2) { return; } vtkSmartPointer targetSurfaceVtk = m_TargetSurface->GetVtkPolyData(); m_TargetIntersectionFilter->SetTargetSurface(m_TargetSurface); m_TargetIntersectionFilter->SetLine(m_NeedleProjectionFilter->GetProjection()); m_TargetIntersectionFilter->CalculateIntersection(); // update target progress bar according to the color of the intersection // point on the target surface and the distance to the intersection if (m_TargetIntersectionFilter->GetIsIntersecting()) { vtkFloatArray *scalars = dynamic_cast(targetSurfaceVtk->GetPointData()->GetScalars("Colors")); double score; scalars->GetTuple(m_TargetIntersectionFilter->GetIntersectionNearestSurfacePointId(), &score); double color[3]; m_TargetColorLookupTableProperty->GetLookupTable()->GetVtkLookupTable()->GetColor(score, color); float colorF[3]; colorF[0] = color[0]; colorF[1] = color[1]; colorF[2] = color[2]; m_TargetProgressBar->SetColor(colorF); m_TargetProgressBar->SetBorderColor(colorF); m_TargetProgressBar->setValue(m_TargetIntersectionFilter->GetDistanceToIntersection()); } else { float red[3] = {0.6f, 0.0f, 0.0f}; m_TargetProgressBar->SetBorderColor(red); m_TargetProgressBar->setValueInvalid(); } } void QmitkUSNavigationStepMarkerIntervention::UpdateTargetViolationStatus() { // transform vtk polydata according to mitk geometry vtkSmartPointer transformFilter = vtkSmartPointer::New(); transformFilter->SetInputData(0, m_TargetSurface->GetVtkPolyData()); transformFilter->SetTransform(m_TargetSurface->GetGeometry()->GetVtkTransform()); transformFilter->Update(); vtkSmartPointer enclosedPoints = vtkSmartPointer::New(); enclosedPoints->Initialize(transformFilter->GetOutput()); mitk::Point3D needleTip = m_NeedleProjectionFilter->GetProjection()->GetPoint(0); // show warning if the needle tip is inside the target surface if (enclosedPoints->IsInsideSurface(needleTip[0], needleTip[1], needleTip[2])) { if (!m_TargetStructureWarnOverlay->IsVisible(NULL)) { m_TargetStructureWarnOverlay->SetVisibility(true); mitk::DataNode::Pointer targetViolationResult = mitk::DataNode::New(); targetViolationResult->SetName("TargetViolation"); targetViolationResult->SetProperty("USNavigation::TargetViolationPoint", mitk::Point3dProperty::New(needleTip)); emit SignalIntermediateResult(targetViolationResult); } MITK_INFO("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepMarkerIntervention") << "Target surface violated at " << needleTip << "."; } else { m_TargetStructureWarnOverlay->SetVisibility(false); } } void QmitkUSNavigationStepMarkerIntervention::CalculateTargetPlacementQuality() { // clear quality display if there aren't all targets reached if (m_ReachedTargetsNodes.size() != static_cast(m_NumberOfTargets)) { ui->placementQualityGroupBox->setEnabled(false); ui->angleDifferenceValue->setText(""); ui->centersOfMassValue->setText(""); return; } ui->placementQualityGroupBox->setEnabled(true); mitk::Surface::Pointer targetSurface = dynamic_cast(m_TargetNode->GetData()); if (targetSurface.IsNull()) { mitkThrow() << "Target surface must not be null."; } m_PlacementQualityCalculator->SetTargetSurface(targetSurface); mitk::PointSet::Pointer targetPointSet = mitk::PointSet::New(); // copy the origins of all reached target nodes into a point set // for the quality calculator mitk::PointSet::PointIdentifier n = 0; for (QVector>::iterator it = m_ReachedTargetsNodes.begin(); it != m_ReachedTargetsNodes.end(); ++it) { targetPointSet->InsertPoint(n++, (*it)->GetData()->GetGeometry()->GetOrigin()); } m_PlacementQualityCalculator->SetTargetPoints(targetPointSet); m_PlacementQualityCalculator->Update(); double centersOfMassDistance = m_PlacementQualityCalculator->GetCentersOfMassDistance(); ui->centersOfMassValue->setText(QString::number(centersOfMassDistance, 103, 2) + " mm"); double meanAnglesDifference = m_PlacementQualityCalculator->GetMeanAngleDifference(); - ui->angleDifferenceValue->setText(QString::number(meanAnglesDifference, 103, 2) + QString::fromLatin1(" °")); + ui->angleDifferenceValue->setText(QString::number(meanAnglesDifference, 103, 2) + QString::fromLatin1(" °")); // create an intermediate result of the placement quality mitk::DataNode::Pointer placementQualityResult = mitk::DataNode::New(); placementQualityResult->SetName("PlacementQuality"); placementQualityResult->SetFloatProperty("USNavigation::CentersOfMassDistance", centersOfMassDistance); placementQualityResult->SetFloatProperty("USNavigation::MeanAngleDifference", meanAnglesDifference); placementQualityResult->SetProperty( "USNavigation::AngleDifferences", mitk::GenericProperty::New(m_PlacementQualityCalculator->GetAngleDifferences())); if (m_PlannedTargetsNodes.size() == static_cast(m_NumberOfTargets)) { mitk::VnlVector reachedPlannedDifferences; double reachedPlannedDifferencesSum = 0; double reachedPlannedDifferencesMax = 0; reachedPlannedDifferences.set_size(m_NumberOfTargets); // get sum and maximum of the planning / reality differences for (unsigned int n = 0; n < m_NumberOfTargets; ++n) { mitk::ScalarType distance = m_PlannedTargetsNodes.at(n)->GetData()->GetGeometry()->GetOrigin().EuclideanDistanceTo( m_ReachedTargetsNodes.at(n)->GetData()->GetGeometry()->GetOrigin()); reachedPlannedDifferences.put(n, distance); reachedPlannedDifferencesSum += distance; if (distance > reachedPlannedDifferencesMax) { reachedPlannedDifferencesMax = distance; } } // add distances between planning and reality to the quality intermediate result placementQualityResult->SetProperty("USNavigation::PlanningRealityDistances", mitk::GenericProperty::New(reachedPlannedDifferences)); placementQualityResult->SetProperty( "USNavigation::MeanPlanningRealityDistance", mitk::DoubleProperty::New(reachedPlannedDifferencesSum / static_cast(m_NumberOfTargets))); placementQualityResult->SetProperty("USNavigation::MaximumPlanningRealityDistance", mitk::DoubleProperty::New(reachedPlannedDifferencesMax)); } emit SignalIntermediateResult(placementQualityResult); } void QmitkUSNavigationStepMarkerIntervention::UpdateSensorsNames() { mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); if (combinedModality.IsNull()) { return; } mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); if (navigationDataSource.IsNull()) { return; } if (!m_NeedleSensorName.empty()) { try { m_NeedleSensorIndex = navigationDataSource->GetOutputIndex(m_NeedleSensorName); } catch (const std::exception &e) { MITK_WARN("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Cannot get index for needle sensor name: " << e.what(); } } if (this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active) { m_NeedleProjectionFilter->SelectInput(m_NeedleSensorIndex); } if (!m_ReferenceSensorName.empty()) { try { m_ReferenceSensorIndex = navigationDataSource->GetOutputIndex(m_ReferenceSensorName); } catch (const std::exception &e) { MITK_WARN("QmitkUSAbstractNavigationStep") ("QmitkUSNavigationStepPlacementPlanning") << "Cannot get index for reference sensor name: " << e.what(); } } if (this->GetNavigationStepState() >= QmitkUSAbstractNavigationStep::State_Active) { m_NodeDisplacementFilter->SelectInput(m_ReferenceSensorIndex); } ui->freezeImageButton->SetCombinedModality(combinedModality, m_ReferenceSensorIndex); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h index 2f54e50fc5..dc94ab612c 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h @@ -1,171 +1,167 @@ /*=================================================================== 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 QMITKUSNAVIGATIONSTEPMARKERINTERVENTION_H #define QMITKUSNAVIGATIONSTEPMARKERINTERVENTION_H #include "QmitkUSAbstractNavigationStep.h" namespace mitk { class DataNode; class NeedleProjectionFilter; class NodeDisplacementFilter; class USNavigationGrabCutSegmentationUpdateFilter; class USNavigationTargetUpdateFilter; class USNavigationTargetOcclusionFilter; class USNavigationTargetIntersectionFilter; class USPointMarkInteractor; class LookupTableProperty; class Surface; class TextAnnotation2D; class USTargetPlacementQualityCalculator; } namespace Ui { class QmitkUSNavigationStepMarkerIntervention; } class QmitkZoneProgressBar; /** * \brief Navigation step for the actual marker placement. */ class QmitkUSNavigationStepMarkerIntervention : public QmitkUSAbstractNavigationStep { Q_OBJECT signals: void TargetReached(int); void TargetLeft(int); protected slots: void OnTargetReached(); void OnTargetLeft(); void OnBackToLastTargetClicked(); void OnFreeze(bool); void OnShowPlanningView(bool); void OnRiskZoneViolated(const mitk::DataNode *, mitk::Point3D); public: explicit QmitkUSNavigationStepMarkerIntervention(QWidget *parent = 0); ~QmitkUSNavigationStepMarkerIntervention(); virtual bool OnStartStep(); virtual bool OnStopStep(); virtual bool OnFinishStep(); virtual bool OnActivateStep(); virtual bool OnDeactivateStep(); virtual void OnUpdate(); virtual void OnSettingsChanged(const itk::SmartPointer settingsNode); virtual QString GetTitle(); virtual bool GetIsRestartable(); virtual FilterVector GetFilter(); protected: virtual void OnSetCombinedModality(); void ClearZones(); void UpdateTargetCoordinates(mitk::DataNode *); void UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker); void GenerateTargetColorLookupTable(); void UpdateTargetColors(); /** * \brief */ void UpdateTargetScore(); /** * \brief Updates display showing the number of the currently active target. */ void UpdateTargetProgressDisplay(); /** * \brief Updates color and distance of the progress bar for the planned target. * The intersection between needle path and target surface is calculated and * the color is got from the intersection point. */ void UpdatePlannedTargetProgressDisplay(); /** * \brief Tests for target violation and updates the display accordingly. * This method tests if the needle tip is inside the target surface. */ void UpdateTargetViolationStatus(); /** * \brief Calculates and display quality metrics if all three markers are placed. */ void CalculateTargetPlacementQuality(); void UpdateSensorsNames(); unsigned int m_NumberOfTargets; - QVector> m_ZoneNodes; QVector> m_PlannedTargetsNodes; QVector> m_ReachedTargetsNodes; - itk::SmartPointer m_SegmentationNode; - itk::SmartPointer m_ForegroundModelPointsNode; - QmitkZoneProgressBar *m_TargetProgressBar; QmitkZoneProgressBar *m_PlannedTargetProgressBar; int m_CurrentTargetIndex; bool m_CurrentTargetReached; mitk::ScalarType m_ActiveTargetColor[3]; mitk::ScalarType m_InactiveTargetColor[3]; mitk::ScalarType m_ReachedTargetColor[3]; bool m_ShowPlanningColors; itk::SmartPointer m_PointMarkInteractor; itk::SmartPointer m_TargetNode; itk::SmartPointer m_TargetColorLookupTableProperty; itk::SmartPointer m_TargetSurface; itk::SmartPointer m_NeedleProjectionFilter; itk::SmartPointer m_NodeDisplacementFilter; itk::SmartPointer m_TargetUpdateFilter; itk::SmartPointer m_TargetOcclusionFilter; itk::SmartPointer m_TargetIntersectionFilter; itk::SmartPointer m_PlacementQualityCalculator; itk::SmartPointer m_TargetStructureWarnOverlay; std::string m_ReferenceSensorName; std::string m_NeedleSensorName; unsigned int m_ReferenceSensorIndex; unsigned int m_NeedleSensorIndex; private: mitk::MessageDelegate1 m_ListenerTargetCoordinatesChanged; Ui::QmitkUSNavigationStepMarkerIntervention *ui; }; #endif // QMITKUSNAVIGATIONSTEPMARKERINTERVENTION_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp index a582d7a530..1e0fcbba77 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.cpp @@ -1,286 +1,283 @@ /*=================================================================== 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 "QmitkUSNavigationStepPunctuationIntervention.h" #include "ui_QmitkUSNavigationStepPunctuationIntervention.h" #include "mitkNeedleProjectionFilter.h" #include "../Widgets/QmitkZoneProgressBar.h" #include "../USNavigationMarkerPlacement.h" #include "usModuleRegistry.h" #include QmitkUSNavigationStepPunctuationIntervention::QmitkUSNavigationStepPunctuationIntervention(QWidget *parent) : QmitkUSAbstractNavigationStep(parent), m_Ui(new Ui::QmitkUSNavigationStepPunctuationIntervention), + m_ZoneNodes(nullptr), m_NeedleProjectionFilter(mitk::NeedleProjectionFilter::New()), + m_NeedleNavigationTool(mitk::NavigationTool::New()), + m_OldColors(), m_SphereSource(vtkSmartPointer::New()), m_OBBTree(vtkSmartPointer::New()), m_IntersectPoints(vtkSmartPointer::New()) { m_Ui->setupUi(this); connect(m_Ui->m_AddNewAblationZone, SIGNAL(clicked()), this, SLOT(OnAddAblationZoneClicked())); + connect(m_Ui->m_ShowToolAxisN, SIGNAL(stateChanged(int)), this, SLOT(OnShowToolAxisEnabled(int))); connect(m_Ui->m_EnableAblationMarking, SIGNAL(clicked()), this, SLOT(OnEnableAblationZoneMarkingClicked())); connect(m_Ui->m_AblationZoneSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnAblationZoneSizeSliderChanged(int))); m_Ui->m_AblationZonesBox->setVisible(false); } -QmitkUSNavigationStepPunctuationIntervention::QmitkUSNavigationStepPunctuationIntervention(mitk::Point3D toolAxis, QWidget *parent) : -QmitkUSAbstractNavigationStep(parent), - m_Ui(new Ui::QmitkUSNavigationStepPunctuationIntervention), - m_NeedleProjectionFilter(mitk::NeedleProjectionFilter::New()), - m_SphereSource(vtkSmartPointer::New()), - m_OBBTree(vtkSmartPointer::New()), - m_IntersectPoints(vtkSmartPointer::New()) +void QmitkUSNavigationStepPunctuationIntervention::SetNeedleMetaData(mitk::NavigationTool::Pointer needleNavigationTool) + { - m_ToolAxis.SetElement(0, (toolAxis.GetElement(0))); - m_ToolAxis.SetElement(1, (toolAxis.GetElement(1))); - m_ToolAxis.SetElement(2, (toolAxis.GetElement(2))); - m_NeedleProjectionFilter->SetToolAxisForFilter(m_ToolAxis); - m_Ui->setupUi(this); - connect(m_Ui->m_AddNewAblationZone, SIGNAL(clicked()), this, SLOT(OnAddAblationZoneClicked())); - connect(m_Ui->m_EnableAblationMarking, SIGNAL(clicked()), this, SLOT(OnEnableAblationZoneMarkingClicked())); - connect(m_Ui->m_AblationZoneSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(OnAblationZoneSizeSliderChanged(int))); - m_Ui->m_AblationZonesBox->setVisible(false); + this->m_NeedleNavigationTool = needleNavigationTool; } void QmitkUSNavigationStepPunctuationIntervention::OnEnableAblationZoneMarkingClicked() { if(m_Ui->m_EnableAblationMarking->isChecked()) m_Ui->m_AblationZonesBox->setVisible(true); else m_Ui->m_AblationZonesBox->setVisible(false); } void QmitkUSNavigationStepPunctuationIntervention::OnAblationZoneSizeSliderChanged(int size) { int id = m_Ui->m_AblationZonesList->currentRow(); if (id!=-1) {emit AblationZoneChanged(id,size);} }// void QmitkUSNavigationStepPunctuationIntervention::OnAddAblationZoneClicked() { QListWidgetItem* newItem = new QListWidgetItem("Ablation Zone (initial size: " + QString::number(m_Ui->m_AblationZoneSizeSlider->value()) + " mm)", m_Ui->m_AblationZonesList); newItem->setSelected(true); emit AddAblationZoneClicked(m_Ui->m_AblationZoneSizeSlider->value()); } QmitkUSNavigationStepPunctuationIntervention::~QmitkUSNavigationStepPunctuationIntervention() { mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(false); if ( dataStorage.IsNotNull() ) { // remove needle path from data storage if it is there mitk::DataNode::Pointer node = this->GetNamedDerivedNode ("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if ( node.IsNotNull() ) { dataStorage->Remove(node); } } delete m_Ui; } bool QmitkUSNavigationStepPunctuationIntervention::OnStartStep() { // create node for Needle Projection mitk::DataNode::Pointer node = this->GetNamedDerivedNodeAndCreate ("Needle Path", QmitkUSAbstractNavigationStep::DATANAME_BASENODE); node->SetData(m_NeedleProjectionFilter->GetProjection()); node->SetBoolProperty("show contour", true); - + m_NeedleProjectionFilter->SetToolAxisForFilter(m_NeedleNavigationTool->GetToolAxis()); return true; } bool QmitkUSNavigationStepPunctuationIntervention::OnRestartStep() { return this->OnActivateStep(); } bool QmitkUSNavigationStepPunctuationIntervention::OnFinishStep() { mitk::DataNode::Pointer finishPunctionResult = mitk::DataNode::New(); finishPunctionResult->SetName("PunctionResult"); mitk::Point3D needlePos = m_NeedleProjectionFilter->GetOutput(0)->GetPosition(); mitk::Quaternion needleRot = m_NeedleProjectionFilter->GetOutput(0)->GetOrientation(); finishPunctionResult->SetProperty("USNavigation::TipPositionEnd", mitk::Point3dProperty::New(needlePos)); MITK_INFO("USNavigationLogging") << "Instrument tip at end: " <ClearZones(); mitk::DataStorage::Pointer dataStorage = this->GetDataStorage(); // add progress bars for risk zone nodes m_ZoneNodes = dataStorage->GetDerivations(dataStorage->GetNamedNode(USNavigationMarkerPlacement::DATANAME_ZONES)); // add zones to the widgets for risk structures for (mitk::DataStorage::SetOfObjects::ConstIterator it = m_ZoneNodes->Begin(); it != m_ZoneNodes->End(); ++it) { m_Ui->riskStructuresRangeWidget->AddZone(it->Value()); float rgb[3]; it->Value()->GetColor(rgb); mitk::Color color; color.SetRed(rgb[0]); color.SetGreen(rgb[1]); color.SetBlue(rgb[2]); m_OldColors[it->Value()] = color; } m_NeedleProjectionFilter->SelectInput(0); return true; } +void QmitkUSNavigationStepPunctuationIntervention::OnShowToolAxisEnabled(int enabled) +{ + if (enabled == 0) { m_NeedleProjectionFilter->ShowToolAxis(false); } + else { m_NeedleProjectionFilter->ShowToolAxis(true); } +} + void QmitkUSNavigationStepPunctuationIntervention::OnUpdate() { // get navigation data source and make sure that it is not null mitk::NavigationDataSource::Pointer navigationDataSource = this->GetCombinedModality()->GetNavigationDataSource(); if ( navigationDataSource.IsNull() ) { MITK_ERROR("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepPunctuationIntervention") << "Navigation Data Source of Combined Modality must not be null."; mitkThrow() << "Navigation Data Source of Combined Modality must not be null."; } // update body marker this->UpdateBodyMarkerStatus(navigationDataSource->GetOutput(1)); // update critical structures this->UpdateCriticalStructures(navigationDataSource->GetOutput(0),m_NeedleProjectionFilter->GetProjection()); //Update Distance to US image mitk::Point3D point1 = m_NeedleProjectionFilter->GetProjection()->GetPoint(0); mitk::Point3D point2 = m_NeedleProjectionFilter->GetProjection()->GetPoint(1); double distance = point1.EuclideanDistanceTo(point2); m_Ui->m_DistanceToUSPlane->setText(QString::number(distance) + " mm"); } void QmitkUSNavigationStepPunctuationIntervention::OnSettingsChanged(const itk::SmartPointer settingsNode) { if ( settingsNode.IsNull() ) { return; } } QString QmitkUSNavigationStepPunctuationIntervention::GetTitle() { return "Computer-assisted Intervention"; } bool QmitkUSNavigationStepPunctuationIntervention::GetIsRestartable() { return false; } QmitkUSNavigationStepPunctuationIntervention::FilterVector QmitkUSNavigationStepPunctuationIntervention::GetFilter() { return FilterVector(1, m_NeedleProjectionFilter.GetPointer()); } void QmitkUSNavigationStepPunctuationIntervention::OnSetCombinedModality() { mitk::USCombinedModality::Pointer combinedModality = this->GetCombinedModality(false); if ( combinedModality.IsNotNull() ) { // set calibration of the combined modality to the needle projection filter mitk::AffineTransform3D::Pointer calibration = combinedModality->GetCalibration(); if ( calibration.IsNotNull() ) { m_NeedleProjectionFilter->SetTargetPlane(calibration); } } } void QmitkUSNavigationStepPunctuationIntervention::ClearZones() { m_Ui->riskStructuresRangeWidget->ClearZones(); } void QmitkUSNavigationStepPunctuationIntervention::UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker) { if ( bodyMarker.IsNull() ) { MITK_ERROR("QmitkUSAbstractNavigationStep")("QmitkUSNavigationStepPunctuationIntervention") << "Current Navigation Data for body marker of Combined Modality must not be null."; mitkThrow() << "Current Navigation Data for body marker of Combined Modality must not be null."; } bool valid = bodyMarker->IsDataValid(); // update body marker status label if (valid) { m_Ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #8bff8b; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); m_Ui->bodyMarkerTrackingStatusLabel->setText("Body marker is inside the tracking volume."); } else { m_Ui->bodyMarkerTrackingStatusLabel->setStyleSheet( "background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey"); m_Ui->bodyMarkerTrackingStatusLabel->setText("Body marker is not inside the tracking volume."); } m_Ui->riskStructuresRangeGroupBox->setEnabled(valid); } void QmitkUSNavigationStepPunctuationIntervention::UpdateCriticalStructures(mitk::NavigationData::Pointer needle, mitk::PointSet::Pointer path) { // update the distances for the risk structures widget m_Ui->riskStructuresRangeWidget->UpdateDistancesToNeedlePosition(needle); //iterate through all zones for (mitk::DataStorage::SetOfObjects::ConstIterator it = m_ZoneNodes->Begin(); it != m_ZoneNodes->End(); ++it) { mitk::DataNode::Pointer currentNode = it->Value(); //get center point and radius float radius = -1; mitk::Point3D center; currentNode->GetFloatProperty("zone.size", radius); center = currentNode->GetData()->GetGeometry()->GetIndexToWorldTransform()->GetTranslation(); mitk::Point3D point0 = path->GetPoint(0); mitk::Point3D point1 = path->GetPoint(1); if (CheckSphereLineIntersection(center,radius,point0,point1)) {currentNode->SetColor(mitk::IGTColor_WARNING);} else {currentNode->SetColor(m_OldColors[currentNode]);} } } bool QmitkUSNavigationStepPunctuationIntervention::CheckSphereLineIntersection(mitk::Point3D& sphereOrigin, float& sphereRadius, mitk::Point3D& lineStart, mitk::Point3D& lineEnd) { double center[3] = {sphereOrigin[0],sphereOrigin[1],sphereOrigin[2]}; m_SphereSource->SetCenter(center); m_SphereSource->SetRadius(sphereRadius); m_SphereSource->Update(); m_OBBTree->SetDataSet(m_SphereSource->GetOutput()); m_OBBTree->BuildLocator(); double lineP0[3] = {lineStart[0], lineStart[1], lineStart[2]}; double lineP1[3] = {lineEnd[0], lineEnd[1], lineEnd[2]}; m_OBBTree->IntersectWithLine(lineP0, lineP1, m_IntersectPoints, nullptr); if (m_IntersectPoints->GetNumberOfPoints() > 0) {return true;} else {return false;} } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h index a41339d019..c7e30d322a 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h @@ -1,119 +1,123 @@ /*=================================================================== 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 QMITKUSNAVIGATIONSTEPPUNCTUATIONINTERVENTION_H #define QMITKUSNAVIGATIONSTEPPUNCTUATIONINTERVENTION_H #include "QmitkUSAbstractNavigationStep.h" #include +#include #include #include #include #include namespace mitk { class DataNode; class NeedleProjectionFilter; class NodeDisplacementFilter; class USNavigationGrabCutSegmentationUpdateFilter; class USNavigationTargetUpdateFilter; class USNavigationTargetOcclusionFilter; class USPointMarkInteractor; class LookupTableProperty; class Surface; } namespace Ui { class QmitkUSNavigationStepPunctuationIntervention; } class QmitkZoneProgressBar; /** * \brief Navigations step for the actual punctuation intervention. * The needle path is projected onto the image plane and the distances to all * risk structures are displayed in the widget. * * The risk structures are expected to be in the data storage under * DATANAME_BASENODE -> DATANAME_ZONES. They should contain a property named * "zone.size" and it is assumed that they are spherical. */ class QmitkUSNavigationStepPunctuationIntervention : public QmitkUSAbstractNavigationStep { Q_OBJECT public: + + /** Sets the navigation tool of the needle for the meta data (tool axis etc.)*/ + void SetNeedleMetaData(mitk::NavigationTool::Pointer needleNavigationTool); explicit QmitkUSNavigationStepPunctuationIntervention(QWidget *parent = 0); - explicit QmitkUSNavigationStepPunctuationIntervention(mitk::Point3D toolAxis, QWidget *parent = 0); ~QmitkUSNavigationStepPunctuationIntervention(); virtual bool OnStartStep(); virtual bool OnRestartStep(); virtual bool OnFinishStep(); virtual bool OnActivateStep(); virtual void OnUpdate(); virtual void OnSettingsChanged(const itk::SmartPointer); virtual QString GetTitle(); virtual bool GetIsRestartable(); virtual FilterVector GetFilter(); signals: void AddAblationZoneClicked(int); void AblationZoneChanged(int,int); protected slots: void OnAddAblationZoneClicked(); void OnEnableAblationZoneMarkingClicked(); void OnAblationZoneSizeSliderChanged(int size); + void OnShowToolAxisEnabled(int enabled); protected: virtual void OnSetCombinedModality(); void ClearZones(); void UpdateBodyMarkerStatus(mitk::NavigationData::Pointer bodyMarker); /** Updates the critical structures which means that the distance to the needle tip is updated and also the color changes to red if the path projection intersects the critical structure. */ void UpdateCriticalStructures(mitk::NavigationData::Pointer needle, mitk::PointSet::Pointer path); /** Checks if the given line intersects the given sphere. */ bool CheckSphereLineIntersection(mitk::Point3D& sphereOrigin, float& sphereRadius, mitk::Point3D& lineStart, mitk::Point3D& lineEnd); private: Ui::QmitkUSNavigationStepPunctuationIntervention *m_Ui; mitk::DataStorage::SetOfObjects::ConstPointer m_ZoneNodes; - /** - * \brief Creates a Pointset that projects the needle's path - */ + /** \brief Creates a Pointset that projects the needle's path */ itk::SmartPointer m_NeedleProjectionFilter; - mitk::Point3D m_ToolAxis; + + /** holds the navigation tool of the needle for the meta data (tool axis etc.)*/ + mitk::NavigationTool::Pointer m_NeedleNavigationTool; std::map m_OldColors; //stores the original color of the critical structrue nodes //some help variables for the CheckSphereLineIntersection()-Method vtkSmartPointer m_SphereSource; vtkSmartPointer m_OBBTree; vtkSmartPointer m_IntersectPoints; }; #endif // QMITKUSNAVIGATIONSTEPPUNCTUATIONINTERVENTION_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui index a3b454f70a..4a176396d5 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.ui @@ -1,222 +1,229 @@ QmitkUSNavigationStepPunctuationIntervention 0 0 317 - 393 + 420 Form background-color: #ff7878; margin-right: 1em; margin-left: 1em; border: 1px solid grey Body marker is not inside the tracking volume. Qt::AlignCenter true Distance Needle to US plane: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter <not available> Distances to Critical Structures + + + + Show Tool Axis + + + Enable Manual Ablation Zone Marking true Ablation Zones Size: Qt::Vertical 20 40 100 10 Qt::Horizontal QSlider::TicksBelow 10 0 cm Qt::Horizontal 40 20 10 cm Qt::Horizontal 40 20 Add New Ablation Zone Qt::Vertical 20 40 QmitkUSNavigationZoneDistancesWidget QWidget
src/internal/Widgets/QmitkUSNavigationZoneDistancesWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp index 9fc49abbf6..61500be8af 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.cpp @@ -1,809 +1,875 @@ /*=================================================================== 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 "USNavigationMarkerPlacement.h" #include "ui_USNavigationMarkerPlacement.h" #include "NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h" #include "NavigationStepWidgets/QmitkUSNavigationStepMarkerIntervention.h" #include "NavigationStepWidgets/QmitkUSNavigationStepPlacementPlanning.h" #include "NavigationStepWidgets/QmitkUSNavigationStepPunctuationIntervention.h" #include "NavigationStepWidgets/QmitkUSNavigationStepTumourSelection.h" #include "NavigationStepWidgets/QmitkUSNavigationStepZoneMarking.h" #include "SettingsWidgets/QmitkUSNavigationCombinedSettingsWidget.h" #include "mitkIRenderingManager.h" #include "mitkNodeDisplacementFilter.h" #include "mitkUSCombinedModality.h" #include #include "IO/mitkUSNavigationExperimentLogging.h" #include "IO/mitkUSNavigationStepTimer.h" #include #include #include #include #include #include #include "QmitkRenderWindow.h" #include "QmitkStdMultiWidget.h" #include "QmitkStdMultiWidgetEditor.h" #include "mitkLayoutAnnotationRenderer.h" +#include "mitkCameraController.h" // scene serialization #include #include #include #include #include const std::string USNavigationMarkerPlacement::VIEW_ID = "org.mitk.views.usmarkerplacement"; const char *USNavigationMarkerPlacement::DATANAME_TUMOUR = "Tumour"; const char *USNavigationMarkerPlacement::DATANAME_TARGETSURFACE = "Target Surface"; const char *USNavigationMarkerPlacement::DATANAME_ZONES = "Zones"; const char *USNavigationMarkerPlacement::DATANAME_TARGETS = "Targets"; const char *USNavigationMarkerPlacement::DATANAME_TARGETS_PATHS = "Target Paths"; const char *USNavigationMarkerPlacement::DATANAME_REACHED_TARGETS = "Reached Targets"; USNavigationMarkerPlacement::USNavigationMarkerPlacement() - : m_Parent(nullptr), - m_UpdateTimer(new QTimer(this)), - m_ImageAndNavigationDataLoggingTimer(new QTimer(this)), - m_StdMultiWidget(nullptr), - m_ReinitAlreadyDone(false), - m_IsExperimentRunning(false), - m_NavigationStepTimer(mitk::USNavigationStepTimer::New()), - m_ExperimentLogging(mitk::USNavigationExperimentLogging::New()), - m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()), - m_IconRunning(QPixmap(":/USNavigation/record.png")), - m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")), - m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()), - m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()), - m_SceneNumber(1), - m_WarnOverlay(mitk::TextAnnotation2D::New()), - m_NeedleIndex(0), - m_MarkerIndex(1), - m_ListenerDeviceChanged(this, &USNavigationMarkerPlacement::OnCombinedModalityPropertyChanged), - ui(new Ui::USNavigationMarkerPlacement) + : m_Parent(nullptr), + m_NavigationSteps(), + m_UpdateTimer(new QTimer(this)), + m_ImageAndNavigationDataLoggingTimer(new QTimer(this)), + m_StdMultiWidget(nullptr), + m_CombinedModality(nullptr), + m_ReinitAlreadyDone(false), + m_IsExperimentRunning(false), + m_CurrentApplicationName(), + m_NavigationStepTimer(mitk::USNavigationStepTimer::New()), + m_ExperimentLogging(mitk::USNavigationExperimentLogging::New()), + m_IconRunning(QPixmap(":/USNavigation/record.png")), + m_IconNotRunning(QPixmap(":/USNavigation/record-gray.png")), + m_ResultsDirectory(), + m_ExperimentName(), + m_ExperimentResultsSubDirectory(), + m_NavigationStepNames(), + m_LoggingBackend(), + m_USImageLoggingFilter(mitk::USImageLoggingFilter::New()), + m_NavigationDataRecorder(mitk::NavigationDataRecorder::New()), + m_TargetNodeDisplacementFilter(nullptr), + m_AblationZonesDisplacementFilter(mitk::NodeDisplacementFilter::New()), + m_AblationZonesVector(), + m_NeedleIndex(0), + m_MarkerIndex(1), + m_SceneNumber(1), + m_WarnOverlay(mitk::TextAnnotation2D::New()), + m_NavigationDataSource(nullptr), + m_CurrentStorage(nullptr), + m_ListenerDeviceChanged(this, &USNavigationMarkerPlacement::OnCombinedModalityPropertyChanged), + ui(new Ui::USNavigationMarkerPlacement) { - connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout())); - connect( - m_ImageAndNavigationDataLoggingTimer, SIGNAL(timeout()), this, SLOT(OnImageAndNavigationDataLoggingTimeout())); + connect(m_UpdateTimer, SIGNAL(timeout()), this, SLOT(OnTimeout())); + connect( + m_ImageAndNavigationDataLoggingTimer, SIGNAL(timeout()), this, SLOT(OnImageAndNavigationDataLoggingTimeout())); - // scale running (and not running) icon the specific height - m_IconRunning = m_IconRunning.scaledToHeight(20, Qt::SmoothTransformation); - m_IconNotRunning = m_IconNotRunning.scaledToHeight(20, Qt::SmoothTransformation); + // scale running (and not running) icon the specific height + m_IconRunning = m_IconRunning.scaledToHeight(20, Qt::SmoothTransformation); + m_IconNotRunning = m_IconNotRunning.scaledToHeight(20, Qt::SmoothTransformation); - // set prefix for experiment logging (only keys with this prefix are taken - // into consideration - m_ExperimentLogging->SetKeyPrefix("USNavigation::"); + // set prefix for experiment logging (only keys with this prefix are taken + // into consideration + m_ExperimentLogging->SetKeyPrefix("USNavigation::"); - m_UpdateTimer->start(33); // every 33 Milliseconds = 30 Frames/Second + m_UpdateTimer->start(33); // every 33 Milliseconds = 30 Frames/Second } USNavigationMarkerPlacement::~USNavigationMarkerPlacement() { - - // remove listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); - } - + // remove listener for ultrasound device changes + if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) + { + m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); + } // remove listener for ultrasound device changes if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) { m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); } delete ui; - - } void USNavigationMarkerPlacement::OnChangeAblationZone(int id, int newSize) { if ((static_cast(m_AblationZonesVector.size()) < id) || (id < 0)) { return; } - MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize; + MITK_INFO << "Ablation Zone " << id << " changed, new size: " << newSize; - // create a vtk sphere with given radius - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(newSize / 2); - vtkData->SetCenter(0, 0, 0); - vtkData->SetPhiResolution(20); - vtkData->SetThetaResolution(20); - vtkData->Update(); + // create a vtk sphere with given radius + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(newSize / 2); + vtkData->SetCenter(0, 0, 0); + vtkData->SetPhiResolution(20); + vtkData->SetThetaResolution(20); + vtkData->Update(); - mitk::Surface::Pointer zoneSurface = dynamic_cast(m_AblationZonesVector.at(id)->GetData()); - zoneSurface->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); + mitk::Surface::Pointer zoneSurface = dynamic_cast(m_AblationZonesVector.at(id)->GetData()); + zoneSurface->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); } void USNavigationMarkerPlacement::OnAddAblationZone(int size) { - m_AblationZonesDisplacementFilter->SetInitialReferencePose( - m_CombinedModality->GetNavigationDataSource()->GetOutput(m_MarkerIndex)); - mitk::DataNode::Pointer NewAblationZone = mitk::DataNode::New(); - - mitk::Point3D origin = m_CombinedModality->GetNavigationDataSource()->GetOutput(m_NeedleIndex)->GetPosition(); - - MITK_INFO("USNavigationLogging") << "Ablation Zone Added, initial size: " << size << ", origin: " << origin; - - mitk::Surface::Pointer zone = mitk::Surface::New(); - - // create a vtk sphere with given radius - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(size / 2); - vtkData->SetCenter(0, 0, 0); - vtkData->SetPhiResolution(20); - vtkData->SetThetaResolution(20); - vtkData->Update(); - zone->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - - // set vtk sphere and origin to data node (origin must be set - // again, because of the new sphere set as data) - NewAblationZone->SetData(zone); - NewAblationZone->GetData()->GetGeometry()->SetOrigin(origin); - mitk::Color SphereColor = mitk::Color(); - // default color - SphereColor[0] = 102; - SphereColor[1] = 0; - SphereColor[2] = 204; - NewAblationZone->SetColor(SphereColor); - NewAblationZone->SetOpacity(0.3); - - // set name of zone - std::stringstream name; - name << "Ablation Zone" << m_AblationZonesVector.size(); - NewAblationZone->SetName(name.str()); - - // add zone to filter - m_AblationZonesDisplacementFilter->AddNode(NewAblationZone); - m_AblationZonesVector.push_back(NewAblationZone); - this->GetDataStorage()->Add(NewAblationZone); + m_AblationZonesDisplacementFilter->SetInitialReferencePose( + m_CombinedModality->GetNavigationDataSource()->GetOutput(m_MarkerIndex)); + mitk::DataNode::Pointer NewAblationZone = mitk::DataNode::New(); + + mitk::Point3D origin = m_CombinedModality->GetNavigationDataSource()->GetOutput(m_NeedleIndex)->GetPosition(); + + MITK_INFO("USNavigationLogging") << "Ablation Zone Added, initial size: " << size << ", origin: " << origin; + + mitk::Surface::Pointer zone = mitk::Surface::New(); + + // create a vtk sphere with given radius + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(size / 2); + vtkData->SetCenter(0, 0, 0); + vtkData->SetPhiResolution(20); + vtkData->SetThetaResolution(20); + vtkData->Update(); + zone->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + + // set vtk sphere and origin to data node (origin must be set + // again, because of the new sphere set as data) + NewAblationZone->SetData(zone); + NewAblationZone->GetData()->GetGeometry()->SetOrigin(origin); + mitk::Color SphereColor = mitk::Color(); + // default color + SphereColor[0] = 102; + SphereColor[1] = 0; + SphereColor[2] = 204; + NewAblationZone->SetColor(SphereColor); + NewAblationZone->SetOpacity(0.3); + + // set name of zone + std::stringstream name; + name << "Ablation Zone" << m_AblationZonesVector.size(); + NewAblationZone->SetName(name.str()); + + // add zone to filter + m_AblationZonesDisplacementFilter->AddNode(NewAblationZone); + m_AblationZonesVector.push_back(NewAblationZone); + this->GetDataStorage()->Add(NewAblationZone); } void USNavigationMarkerPlacement::CreateQtPartControl(QWidget *parent) { - m_Parent = parent; - ui->setupUi(parent); - - connect(ui->navigationProcessWidget, - SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), - this, - SLOT(OnCombinedModalityChanged(itk::SmartPointer))); - - connect(ui->navigationProcessWidget, - SIGNAL(SignalSettingsChanged(itk::SmartPointer)), - this, - SLOT(OnSettingsChanged(itk::SmartPointer))); - - connect(ui->navigationProcessWidget, - SIGNAL(SignalActiveNavigationStepChanged(int)), - this, - SLOT(OnActiveNavigationStepChanged(int))); - - connect(ui->startExperimentButton, SIGNAL(clicked()), this, SLOT(OnStartExperiment())); - connect(ui->finishExperimentButton, SIGNAL(clicked()), this, SLOT(OnFinishExperiment())); + m_Parent = parent; + ui->setupUi(parent); + + connect(ui->navigationProcessWidget, + SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), + this, + SLOT(OnCombinedModalityChanged(itk::SmartPointer))); + + connect(ui->navigationProcessWidget, + SIGNAL(SignalSettingsChanged(itk::SmartPointer)), + this, + SLOT(OnSettingsChanged(itk::SmartPointer))); + + connect(ui->navigationProcessWidget, + SIGNAL(SignalActiveNavigationStepChanged(int)), + this, + SLOT(OnActiveNavigationStepChanged(int))); + + connect(ui->navigationProcessWidget, + SIGNAL(SignalActiveNavigationStepChangeRequested(int)), + this, + SLOT(OnNextNavigationStepInitialization(int))); + + connect(ui->startExperimentButton, SIGNAL(clicked()), this, SLOT(OnStartExperiment())); + connect(ui->finishExperimentButton, SIGNAL(clicked()), this, SLOT(OnFinishExperiment())); connect(ui->m_enableNavigationLayout, SIGNAL(clicked()), this, SLOT(OnChangeLayoutClicked())); + connect(ui->m_RenderWindowSelection, SIGNAL(valueChanged(int)), this, SLOT(OnRenderWindowSelection())); + connect(ui->m_RefreshView, SIGNAL(clicked()), this, SLOT(OnRefreshView())); - connect(ui->navigationProcessWidget, - SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), - this, - SLOT(OnIntermediateResultProduced(const itk::SmartPointer))); + connect(ui->navigationProcessWidget, + SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), + this, + SLOT(OnIntermediateResultProduced(const itk::SmartPointer))); - ui->navigationProcessWidget->SetDataStorage(this->GetDataStorage()); + ui->navigationProcessWidget->SetDataStorage(this->GetDataStorage()); - // indicate that no experiment is running at start - ui->runningLabel->setPixmap(m_IconNotRunning); + // indicate that no experiment is running at start + ui->runningLabel->setPixmap(m_IconNotRunning); - ui->navigationProcessWidget->SetSettingsWidget(new QmitkUSNavigationCombinedSettingsWidget(m_Parent)); + ui->navigationProcessWidget->SetSettingsWidget(new QmitkUSNavigationCombinedSettingsWidget(m_Parent)); } void USNavigationMarkerPlacement::OnCombinedModalityPropertyChanged(const std::string &key, const std::string &) { - if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) - { - m_ReinitAlreadyDone = false; - this->ReinitOnImage(); - - if (m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsCalibratedForCurrentStatus()) - { - mitk::LayoutAnnotationRenderer::AddAnnotation( - m_WarnOverlay.GetPointer(), "stdmulti.widget1", mitk::LayoutAnnotationRenderer::TopLeft); - MITK_WARN << "No calibration available for the selected ultrasound image depth."; - } - } -} - - -void USNavigationMarkerPlacement::SetToolAxisMarkerPlacement() -{ - m_NavigationDataSource = m_CombinedModality->GetNavigationDataSource(); - m_ToolAxis.SetElement(0, 0); - m_ToolAxis.SetElement(1, 0); - m_ToolAxis.SetElement(2, 1); - if (m_NavigationDataSource.IsNull()) + if (key == mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DEPTH) { - MITK_WARN << "Cannot retrieve tool axis as tracking source is null."; - } - else - { - us::ModuleContext* context = us::GetModuleContext(); - std::string id = m_NavigationDataSource->US_PROPKEY_ID; - std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")"; - // Get Storage - std::vector > refs = context->GetServiceReferences(); - m_CurrentStorage = context->GetService(refs.front()); - if (m_CurrentStorage.IsNull()) - { - MITK_WARN << "Found an invalid storage object!"; - } - if (m_CurrentStorage->GetToolCount() != static_cast(m_NavigationDataSource->GetNumberOfOutputs())) //there is something wrong with the storage + m_ReinitAlreadyDone = false; + this->ReinitOnImage(); + + if (m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsCalibratedForCurrentStatus()) { - MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This storage won't be used because it isn't the right one."; - m_CurrentStorage = NULL; + mitk::LayoutAnnotationRenderer::AddAnnotation( + m_WarnOverlay.GetPointer(), "stdmulti.widget1", mitk::LayoutAnnotationRenderer::TopLeft); + MITK_WARN << "No calibration available for the selected ultrasound image depth."; } - - //getting the first tool in the tool storage, assuming this is the needle - mitk::NavigationTool::Pointer needle; - needle = m_CurrentStorage->GetTool(0); - - m_ToolAxis.SetElement(0, (needle->GetToolAxis().GetElement(0))); - m_ToolAxis.SetElement(1, (needle->GetToolAxis().GetElement(1))); - m_ToolAxis.SetElement(2, (needle->GetToolAxis().GetElement(2))); } } - void USNavigationMarkerPlacement::SetFocus() { - this->ReinitOnImage(); + this->ReinitOnImage(); } void USNavigationMarkerPlacement::OnTimeout() { - if (!m_StdMultiWidget) + if (!m_StdMultiWidget) + { + // try to get the standard multi widget if it couldn't be got before + mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); + + QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); + + // if there is a standard multi widget now, disable the level window and + // change the layout to 2D up and 3d down + if (multiWidgetEditor) { - // try to get the standard multi widget if it couldn't be got before - mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); - - QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); - - // if there is a standard multi widget now, disable the level window and - // change the layout to 2D up and 3d down - if (multiWidgetEditor) - { - m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); - if (m_StdMultiWidget) - { - m_StdMultiWidget->DisableStandardLevelWindow(); - m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(); - } - } - - this->CreateOverlays(); + m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); + SetTwoWindowView(); } - if (m_CombinedModality.IsNotNull() && - !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing - { - ui->navigationProcessWidget->UpdateNavigationProgress(); - m_AblationZonesDisplacementFilter->Update(); + this->CreateOverlays(); + } + + if (m_CombinedModality.IsNotNull() && + !this->m_CombinedModality->GetIsFreezed()) // if the combined modality is freezed: do nothing + { + ui->navigationProcessWidget->UpdateNavigationProgress(); + m_AblationZonesDisplacementFilter->Update(); - // update the 3D window only every fourth time to speed up the rendering (at least in 2D) - this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); + // update the 3D window only every fourth time to speed up the rendering (at least in 2D) + this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); - // make sure that a reinit was performed on the image - this->ReinitOnImage(); - } + // make sure that a reinit was performed on the image + this->ReinitOnImage(); + } } void USNavigationMarkerPlacement::OnEnableNavigationLayout() { MITK_INFO << "Navigation Layout"; // try to get the standard multi widget if it couldn't be got before mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); QmitkStdMultiWidgetEditor *multiWidgetEditor = dynamic_cast(renderWindow); // if there is a standard multi widget now, disable the level window and // change the layout to 2D up and 3d down if (multiWidgetEditor) { m_StdMultiWidget = multiWidgetEditor->GetStdMultiWidget(); - if (m_StdMultiWidget) + SetTwoWindowView(); + } +} + +void USNavigationMarkerPlacement::OnRenderWindowSelection() +{ + SetTwoWindowView(); +} + +void USNavigationMarkerPlacement::OnRefreshView() +{ + if (!ui->m_enableNavigationLayout->isChecked()) + OnResetStandardLayout(); + else + { + //Reinit the US Image Stream (this might be broken if there was a global reinit somewhere...) + try + { + mitk::RenderingManager::GetInstance()->InitializeViews(//Reinit + this->GetDataStorage()//GetDataStorage + ->GetNamedNode("US Support Viewing Stream")->GetData()->GetTimeGeometry());//GetNode + } + catch (...) { - m_StdMultiWidget->DisableStandardLevelWindow(); - m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(); - this->GetDataStorage()->GetNamedNode("stdmulti.widget1.plane")->SetVisibility(false); - this->GetDataStorage()->GetNamedNode("stdmulti.widget3.plane")->SetVisibility(false); + MITK_DEBUG << "No reinit possible"; } + SetTwoWindowView(); + } +} + +void USNavigationMarkerPlacement::SetTwoWindowView() +{ + if (m_StdMultiWidget) + { + m_StdMultiWidget->DisableStandardLevelWindow(); + int i, j, k; + switch (this->ui->m_RenderWindowSelection->value()) + { + case 1: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToCaudal(); + i = 2; j = 3; //other windows + k = 1; + break; + case 2: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToSinister(); + i = 1; j = 3; + k = 2; + break; + case 3: + mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))->GetCameraController()->SetViewToAnterior(); + i = 2; j = 1; + k = 3; + break; + default: + return; + } + m_StdMultiWidget->changeLayoutTo2DUpAnd3DDown(k); + ////Crosshair invisible in 3D view + this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane")-> + SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane")-> + SetBoolProperty("visible", false, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(k) + ".plane")-> + SetBoolProperty("visible", true, mitk::BaseRenderer::GetInstance(mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(i) + ".plane")-> + SetIntProperty("Crosshair.Gap Size", 0); + this->GetDataStorage()->GetNamedNode("stdmulti.widget" + std::to_string(j) + ".plane")-> + SetIntProperty("Crosshair.Gap Size", 0); } } void USNavigationMarkerPlacement::OnResetStandardLayout() { //reset render windows mitk::DataNode::Pointer widget1 = this->GetDataStorage()->GetNamedNode("stdmulti.widget1.plane"); if (widget1.IsNotNull()) { widget1->SetVisibility(true); } + mitk::DataNode::Pointer widget2 = this->GetDataStorage()->GetNamedNode("stdmulti.widget2.plane"); + if (widget2.IsNotNull()) { widget2->SetVisibility(true); } mitk::DataNode::Pointer widget3 = this->GetDataStorage()->GetNamedNode("stdmulti.widget3.plane"); if (widget3.IsNotNull()) { widget3->SetVisibility(true); } m_StdMultiWidget->changeLayoutToDefault(); } void USNavigationMarkerPlacement::OnChangeLayoutClicked() { if (ui->m_enableNavigationLayout->isChecked()) OnEnableNavigationLayout(); else OnResetStandardLayout(); } void USNavigationMarkerPlacement::OnImageAndNavigationDataLoggingTimeout() { // update filter for logging navigation data and ultrasound images if (m_CombinedModality.IsNotNull()) { m_NavigationDataRecorder->Update(); // get last messages for logging filer and store them std::vector messages = m_LoggingBackend.GetNavigationMessages(); std::string composedMessage = ""; for (std::size_t i = 0; i < messages.size(); i++) { composedMessage += messages.at(i); } m_USImageLoggingFilter->AddMessageToCurrentImage(composedMessage); m_LoggingBackend.ClearNavigationMessages(); // update logging filter m_USImageLoggingFilter->Update(); } } void USNavigationMarkerPlacement::OnStartExperiment() { - // get name for the experiment by a QInputDialog - bool ok; - if (m_ExperimentName.isEmpty()) - { // default: current date - m_ExperimentName = QString::number(QDateTime::currentDateTime().date().year()) + "_" + - QString::number(QDateTime::currentDateTime().date().month()) + "_" + - QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" + - QString::number(QDateTime::currentDateTime().time().hour()) + "." + - QString::number(QDateTime::currentDateTime().time().minute()); + // get name for the experiment by a QInputDialog + bool ok; + if (m_ExperimentName.isEmpty()) + { // default: current date + m_ExperimentName = QString::number(QDateTime::currentDateTime().date().year()) + "_" + + QString::number(QDateTime::currentDateTime().date().month()) + "_" + + QString::number(QDateTime::currentDateTime().date().day()) + "_experiment_" + + QString::number(QDateTime::currentDateTime().time().hour()) + "." + + QString::number(QDateTime::currentDateTime().time().minute()); + } + m_ExperimentName = QInputDialog::getText( + m_Parent, QString("Experiment Name"), QString("Name of the Experiment"), QLineEdit::Normal, m_ExperimentName, &ok); + MITK_INFO("USNavigationLogging") << "Experiment started: " << m_ExperimentName.toStdString(); + if (ok && !m_ExperimentName.isEmpty()) + { + // display error message and call the function recursivly if a directory + // with the given name already exists + QDir experimentResultsDir(m_ResultsDirectory + QDir::separator() + m_ExperimentName); + if (experimentResultsDir.exists()) + { + QMessageBox::critical( + m_Parent, "Results Directory Exists", "The result directory already exists.\nPlease choose an other name."); + this->OnStartExperiment(); } - m_ExperimentName = QInputDialog::getText( - m_Parent, QString("Experiment Name"), QString("Name of the Experiment"), QLineEdit::Normal, m_ExperimentName, &ok); - MITK_INFO("USNavigationLogging") << "Experiment started: " << m_ExperimentName.toStdString(); - if (ok && !m_ExperimentName.isEmpty()) + else { - // display error message and call the function recursivly if a directory - // with the given name already exists - QDir experimentResultsDir(m_ResultsDirectory + QDir::separator() + m_ExperimentName); - if (experimentResultsDir.exists()) - { - QMessageBox::critical( - m_Parent, "Results Directory Exists", "The result directory already exists.\nPlease choose an other name."); - this->OnStartExperiment(); - } - else - { - QDir(m_ResultsDirectory).mkdir(m_ExperimentName); - m_ExperimentResultsSubDirectory = m_ResultsDirectory + QDir::separator() + m_ExperimentName; - - // experiment is running now - ui->runningLabel->setPixmap(m_IconRunning); - ui->navigationProcessWidget->EnableInteraction(true); - - // (re)start timer for navigation step durations - m_NavigationStepTimer->Reset(); - m_NavigationStepTimer->SetOutputFileName( - QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("durations.cvs")).toStdString()); - m_NavigationStepTimer->SetActiveIndex(0, m_NavigationSteps.at(0)->GetTitle().toStdString()); - - ui->finishExperimentButton->setEnabled(true); - ui->startExperimentButton->setDisabled(true); - - // initialize and register logging backend - QString loggingFilename = m_ExperimentResultsSubDirectory + QDir::separator() + "logging.txt"; - m_LoggingBackend.SetOutputFileName(loggingFilename.toStdString()); - mbilog::RegisterBackend(&m_LoggingBackend); - - // initialize and start navigation data recorder form xml recording - m_NavigationDataRecorder->StartRecording(); - - m_IsExperimentRunning = true; - - m_ImageAndNavigationDataLoggingTimer->start(1000); - - // (re)start experiment logging and set output file name - m_ExperimentLogging->Reset(); - m_ExperimentLogging->SetFileName( - QString(m_ExperimentResultsSubDirectory + QDir::separator() + "experiment-logging.xml").toStdString()); - } + QDir(m_ResultsDirectory).mkdir(m_ExperimentName); + m_ExperimentResultsSubDirectory = m_ResultsDirectory + QDir::separator() + m_ExperimentName; + + // experiment is running now + ui->runningLabel->setPixmap(m_IconRunning); + ui->navigationProcessWidget->EnableInteraction(true); + + // (re)start timer for navigation step durations + m_NavigationStepTimer->Reset(); + m_NavigationStepTimer->SetOutputFileName( + QString(m_ExperimentResultsSubDirectory + QDir::separator() + QString("durations.cvs")).toStdString()); + m_NavigationStepTimer->SetActiveIndex(0, m_NavigationSteps.at(0)->GetTitle().toStdString()); + + ui->finishExperimentButton->setEnabled(true); + ui->startExperimentButton->setDisabled(true); + + // initialize and register logging backend + QString loggingFilename = m_ExperimentResultsSubDirectory + QDir::separator() + "logging.txt"; + m_LoggingBackend.SetOutputFileName(loggingFilename.toStdString()); + mbilog::RegisterBackend(&m_LoggingBackend); + + // initialize and start navigation data recorder form xml recording + m_NavigationDataRecorder->StartRecording(); + + m_IsExperimentRunning = true; + + m_ImageAndNavigationDataLoggingTimer->start(1000); + + // (re)start experiment logging and set output file name + m_ExperimentLogging->Reset(); + m_ExperimentLogging->SetFileName( + QString(m_ExperimentResultsSubDirectory + QDir::separator() + "experiment-logging.xml").toStdString()); } + } } void USNavigationMarkerPlacement::OnFinishExperiment() { - this->WaitCursorOn(); + this->WaitCursorOn(); - MITK_INFO("USNavigationLogging") << "Experiment finished!"; - MITK_INFO("USNavigationLogging") - << "Position/Orientation of needle tip: " - << (dynamic_cast(m_CombinedModality->GetTrackingDevice()->GetOutput(0)))->GetPosition(); - MITK_INFO("USNavigationLogging") - << "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition(); - MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration(); + MITK_INFO("USNavigationLogging") << "Experiment finished!"; + MITK_INFO("USNavigationLogging") + << "Position/Orientation of needle tip: " + << (dynamic_cast(m_CombinedModality->GetTrackingDevice()->GetOutput(0)))->GetPosition(); + MITK_INFO("USNavigationLogging") + << "Position of target: " << m_TargetNodeDisplacementFilter->GetRawDisplacementNavigationData(0)->GetPosition(); + MITK_INFO("USNavigationLogging") << "Total duration: " << m_NavigationStepTimer->GetTotalDuration(); - ui->navigationProcessWidget->FinishCurrentNavigationStep(); - m_ImageAndNavigationDataLoggingTimer->stop(); + ui->navigationProcessWidget->FinishCurrentNavigationStep(); + m_ImageAndNavigationDataLoggingTimer->stop(); - ui->runningLabel->setPixmap(m_IconNotRunning); - ui->navigationProcessWidget->EnableInteraction(false); + ui->runningLabel->setPixmap(m_IconNotRunning); + ui->navigationProcessWidget->EnableInteraction(false); - m_NavigationStepTimer->Stop(); + m_NavigationStepTimer->Stop(); - // make sure that the navigation process will be start from beginning at the - // next experiment - ui->navigationProcessWidget->ResetNavigationProcess(); + // make sure that the navigation process will be start from beginning at the + // next experiment + ui->navigationProcessWidget->ResetNavigationProcess(); - ui->finishExperimentButton->setDisabled(true); - ui->startExperimentButton->setEnabled(true); + ui->finishExperimentButton->setDisabled(true); + ui->startExperimentButton->setEnabled(true); - MITK_INFO("USNavigationLogging") << "Writing logging data to " << m_ExperimentResultsSubDirectory.toStdString(); - // save ultrasound images to the file system - QDir(m_ExperimentResultsSubDirectory).mkdir("ImageStream"); - m_USImageLoggingFilter->Update(); - m_USImageLoggingFilter->SetImageFilesExtension(".jpg"); - m_USImageLoggingFilter->SaveImages( - QString(m_ExperimentResultsSubDirectory + QDir::separator() + "ImageStream" + QDir::separator()).toStdString()); - m_USImageLoggingFilter = mitk::USImageLoggingFilter::New(); + MITK_INFO("USNavigationLogging") << "Writing logging data to " << m_ExperimentResultsSubDirectory.toStdString(); + // save ultrasound images to the file system + QDir(m_ExperimentResultsSubDirectory).mkdir("ImageStream"); + m_USImageLoggingFilter->Update(); + m_USImageLoggingFilter->SetImageFilesExtension(".jpg"); + m_USImageLoggingFilter->SaveImages( + QString(m_ExperimentResultsSubDirectory + QDir::separator() + "ImageStream" + QDir::separator()).toStdString()); + m_USImageLoggingFilter = mitk::USImageLoggingFilter::New(); - m_NavigationDataRecorder->StopRecording(); + m_NavigationDataRecorder->StopRecording(); // Write data to csv and xml file mitk::IOUtil::Save( m_NavigationDataRecorder->GetNavigationDataSet(), (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.xml").toStdString().c_str())); mitk::IOUtil::Save( m_NavigationDataRecorder->GetNavigationDataSet(), (QString(m_ExperimentResultsSubDirectory + QDir::separator() + "navigation-data.csv").toStdString().c_str())); - // write logged navigation data messages to separate file - std::stringstream csvNavigationMessagesFilename; - csvNavigationMessagesFilename << m_ExperimentResultsSubDirectory.toStdString() << QDir::separator().toLatin1() - << "CSVNavigationMessagesLogFile.csv"; - MITK_INFO("USNavigationLogging") << "Writing logged navigation messages to separate csv file: " - << csvNavigationMessagesFilename.str(); - m_LoggingBackend.WriteCSVFileWithNavigationMessages(csvNavigationMessagesFilename.str()); + // write logged navigation data messages to separate file + std::stringstream csvNavigationMessagesFilename; + csvNavigationMessagesFilename << m_ExperimentResultsSubDirectory.toStdString() << QDir::separator().toLatin1() + << "CSVNavigationMessagesLogFile.csv"; + MITK_INFO("USNavigationLogging") << "Writing logged navigation messages to separate csv file: " + << csvNavigationMessagesFilename.str(); + m_LoggingBackend.WriteCSVFileWithNavigationMessages(csvNavigationMessagesFilename.str()); - mbilog::UnregisterBackend(&m_LoggingBackend); + mbilog::UnregisterBackend(&m_LoggingBackend); - m_IsExperimentRunning = false; + m_IsExperimentRunning = false; - m_ImageAndNavigationDataLoggingTimer->stop(); - m_CombinedModality = 0; + m_ImageAndNavigationDataLoggingTimer->stop(); + m_CombinedModality = nullptr; - // reset scene number for next experiment - m_SceneNumber = 1; + // reset scene number for next experiment + m_SceneNumber = 1; - this->WaitCursorOff(); - MITK_INFO("USNavigationLogging") << "Finished!"; + this->WaitCursorOff(); + MITK_INFO("USNavigationLogging") << "Finished!"; } void USNavigationMarkerPlacement::OnCombinedModalityChanged( - itk::SmartPointer combinedModality) + itk::SmartPointer combinedModality) { - // remove old listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); - } + // remove old listener for ultrasound device changes + if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) + { + m_CombinedModality->GetUltrasoundDevice()->RemovePropertyChangedListener(m_ListenerDeviceChanged); + } - m_CombinedModality = combinedModality; - m_ReinitAlreadyDone = false; + m_CombinedModality = combinedModality; + m_ReinitAlreadyDone = false; - // add a listener for ultrasound device changes - if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) - { - m_CombinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_ListenerDeviceChanged); - } + // add a listener for ultrasound device changes + if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetUltrasoundDevice().IsNotNull()) + { + m_CombinedModality->GetUltrasoundDevice()->AddPropertyChangedListener(m_ListenerDeviceChanged); + } - // update navigation data recorder for using the new combined modality - mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); - m_NavigationDataRecorder->ConnectTo(navigationDataSource); - m_NavigationDataRecorder->ResetRecording(); - - //upate stored tool axis for current tool - this->SetToolAxisMarkerPlacement(); - //store new tool axis - QmitkUSNavigationStepPunctuationIntervention* stepIntervention = - new QmitkUSNavigationStepPunctuationIntervention(m_ToolAxis, m_Parent); - m_NavigationSteps.pop_back(); - m_NavigationSteps.push_back(stepIntervention); - - // TODO check for correct connection - // for (unsigned int n = 0; n < navigationDataSource->GetNumberOfIndexedOutputs(); ++n) - // { - // m_NavigationDataRecorder->AddNavigationData(navigationDataSource->GetOutput(n)); - // } + // update navigation data recorder for using the new combined modality + mitk::NavigationDataSource::Pointer navigationDataSource = combinedModality->GetNavigationDataSource(); + m_NavigationDataRecorder->ConnectTo(navigationDataSource); + m_NavigationDataRecorder->ResetRecording(); // update ultrasound image logging filter for using the new combined modality mitk::USDevice::Pointer ultrasoundImageSource = combinedModality->GetUltrasoundDevice(); for (unsigned int n = 0; n < ultrasoundImageSource->GetNumberOfIndexedOutputs(); ++n) { m_USImageLoggingFilter->SetInput(n, ultrasoundImageSource->GetOutput(n)); } // update ablation zone filter for using the new combined modality for (unsigned int n = 0; n < navigationDataSource->GetNumberOfIndexedOutputs(); ++n) { m_AblationZonesDisplacementFilter->SetInput(n, navigationDataSource->GetOutput(n)); } m_AblationZonesDisplacementFilter->SelectInput(m_MarkerIndex); // make sure that a reinit is done for the new images this->ReinitOnImage(); } void USNavigationMarkerPlacement::OnSettingsChanged(itk::SmartPointer settings) { - std::string applicationName; - if (!settings->GetStringProperty("settings.application", applicationName)) - { - // set default application if the string property is not available - applicationName = "Marker Placement"; - } + std::string applicationName; + if (!settings->GetStringProperty("settings.application", applicationName)) + { + // set default application if the string property is not available + applicationName = "Marker Placement"; + } - // create navigation step widgets according to the selected application - if (applicationName != m_CurrentApplicationName) - { - m_CurrentApplicationName = applicationName; + // create navigation step widgets according to the selected application + if (applicationName != m_CurrentApplicationName) + { + m_CurrentApplicationName = applicationName; QmitkUSNavigationProcessWidget::NavigationStepVector navigationSteps; if (applicationName == "Puncture") { QmitkUSNavigationStepCombinedModality* stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); QmitkUSNavigationStepTumourSelection* stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); stepTumourSelection->SetTargetSelectionOptional(true); m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); QmitkUSNavigationStepZoneMarking* stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); QmitkUSNavigationStepPunctuationIntervention* stepIntervention = new QmitkUSNavigationStepPunctuationIntervention(m_Parent); - connect(stepIntervention, SIGNAL(AddAblationZoneClicked(int)), this, SLOT(OnAddAblationZone(int))); - connect(stepIntervention, SIGNAL(AblationZoneChanged(int, int)), this, SLOT(OnChangeAblationZone(int, int))); - - m_NavigationStepNames = std::vector(); - navigationSteps.push_back(stepCombinedModality); - m_NavigationStepNames.push_back("Combined Modality Initialization"); - navigationSteps.push_back(stepTumourSelection); - m_NavigationStepNames.push_back("Target Selection"); - navigationSteps.push_back(stepZoneMarking); - m_NavigationStepNames.push_back("Critical Structure Marking"); - navigationSteps.push_back(stepIntervention); - m_NavigationStepNames.push_back("Intervention"); - } - else if (applicationName == "Marker Placement") - { - QmitkUSNavigationStepCombinedModality *stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); - QmitkUSNavigationStepTumourSelection *stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); - m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); - QmitkUSNavigationStepZoneMarking *stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); - QmitkUSNavigationStepPlacementPlanning *stepPlacementPlanning = - new QmitkUSNavigationStepPlacementPlanning(m_Parent); - QmitkUSNavigationStepMarkerIntervention *stepMarkerIntervention = - new QmitkUSNavigationStepMarkerIntervention(m_Parent); - - m_NavigationStepNames = std::vector(); - navigationSteps.push_back(stepCombinedModality); - m_NavigationStepNames.push_back("Combined Modality Initialization"); - navigationSteps.push_back(stepTumourSelection); - m_NavigationStepNames.push_back("Target Selection"); - navigationSteps.push_back(stepZoneMarking); - m_NavigationStepNames.push_back("Critical Structure Marking"); - navigationSteps.push_back(stepPlacementPlanning); - m_NavigationStepNames.push_back("Placement Planning"); - navigationSteps.push_back(stepMarkerIntervention); - m_NavigationStepNames.push_back("Marker Intervention"); - } - - // set navigation step widgets to the process widget - ui->navigationProcessWidget->SetNavigationSteps(navigationSteps); - - for (QmitkUSNavigationProcessWidget::NavigationStepIterator it = m_NavigationSteps.begin(); - it != m_NavigationSteps.end(); - ++it) - { - delete *it; - } - m_NavigationSteps.clear(); - m_NavigationSteps = navigationSteps; + connect(stepIntervention, SIGNAL(AddAblationZoneClicked(int)), this, SLOT(OnAddAblationZone(int))); + connect(stepIntervention, SIGNAL(AblationZoneChanged(int, int)), this, SLOT(OnChangeAblationZone(int, int))); + + m_NavigationStepNames = std::vector(); + navigationSteps.push_back(stepCombinedModality); + m_NavigationStepNames.push_back("Combined Modality Initialization"); + navigationSteps.push_back(stepTumourSelection); + m_NavigationStepNames.push_back("Target Selection"); + navigationSteps.push_back(stepZoneMarking); + m_NavigationStepNames.push_back("Critical Structure Marking"); + navigationSteps.push_back(stepIntervention); + m_NavigationStepNames.push_back("Intervention"); } - - // initialize gui according to the experiment mode setting - bool experimentMode = false; - settings->GetBoolProperty("settings.experiment-mode", experimentMode); - ui->startExperimentButton->setVisible(experimentMode); - ui->finishExperimentButton->setVisible(experimentMode); - ui->runningLabel->setVisible(experimentMode); - if (experimentMode && !m_IsExperimentRunning) + else if (applicationName == "Marker Placement") { - ui->navigationProcessWidget->ResetNavigationProcess(); - ui->navigationProcessWidget->EnableInteraction(false); - ui->runningLabel->setPixmap(m_IconNotRunning); - } - else if (!experimentMode) - { - if (m_IsExperimentRunning) - { - this->OnFinishExperiment(); - } - ui->navigationProcessWidget->EnableInteraction(true); + QmitkUSNavigationStepCombinedModality *stepCombinedModality = new QmitkUSNavigationStepCombinedModality(m_Parent); + QmitkUSNavigationStepTumourSelection *stepTumourSelection = new QmitkUSNavigationStepTumourSelection(m_Parent); + m_TargetNodeDisplacementFilter = stepTumourSelection->GetTumourNodeDisplacementFilter(); + QmitkUSNavigationStepZoneMarking *stepZoneMarking = new QmitkUSNavigationStepZoneMarking(m_Parent); + QmitkUSNavigationStepPlacementPlanning *stepPlacementPlanning = + new QmitkUSNavigationStepPlacementPlanning(m_Parent); + QmitkUSNavigationStepMarkerIntervention *stepMarkerIntervention = + new QmitkUSNavigationStepMarkerIntervention(m_Parent); + + m_NavigationStepNames = std::vector(); + navigationSteps.push_back(stepCombinedModality); + m_NavigationStepNames.push_back("Combined Modality Initialization"); + navigationSteps.push_back(stepTumourSelection); + m_NavigationStepNames.push_back("Target Selection"); + navigationSteps.push_back(stepZoneMarking); + m_NavigationStepNames.push_back("Critical Structure Marking"); + navigationSteps.push_back(stepPlacementPlanning); + m_NavigationStepNames.push_back("Placement Planning"); + navigationSteps.push_back(stepMarkerIntervention); + m_NavigationStepNames.push_back("Marker Intervention"); } - // get the results directory from the settings and use home directory if - // there is no results directory configured - std::string resultsDirectory; - if (settings->GetStringProperty("settings.experiment-results-directory", resultsDirectory)) - { - m_ResultsDirectory = QString::fromStdString(resultsDirectory); - } - else + // set navigation step widgets to the process widget + ui->navigationProcessWidget->SetNavigationSteps(navigationSteps); + + for (QmitkUSNavigationProcessWidget::NavigationStepIterator it = m_NavigationSteps.begin(); + it != m_NavigationSteps.end(); + ++it) { - m_ResultsDirectory = QDir::homePath(); + delete *it; } + m_NavigationSteps.clear(); + m_NavigationSteps = navigationSteps; + } - // make sure that the results directory exists - QDir resultsDirectoryQDir = QDir(m_ResultsDirectory); - if (!resultsDirectoryQDir.exists()) + // initialize gui according to the experiment mode setting + bool experimentMode = false; + settings->GetBoolProperty("settings.experiment-mode", experimentMode); + ui->startExperimentButton->setVisible(experimentMode); + ui->finishExperimentButton->setVisible(experimentMode); + ui->runningLabel->setVisible(experimentMode); + if (experimentMode && !m_IsExperimentRunning) + { + ui->navigationProcessWidget->ResetNavigationProcess(); + ui->navigationProcessWidget->EnableInteraction(false); + ui->runningLabel->setPixmap(m_IconNotRunning); + } + else if (!experimentMode) + { + if (m_IsExperimentRunning) { - resultsDirectoryQDir.mkpath(m_ResultsDirectory); + this->OnFinishExperiment(); } + ui->navigationProcessWidget->EnableInteraction(true); + } - MITK_INFO << "Results Directory: " << m_ResultsDirectory.toStdString(); + // get the results directory from the settings and use home directory if + // there is no results directory configured + std::string resultsDirectory; + if (settings->GetStringProperty("settings.experiment-results-directory", resultsDirectory)) + { + m_ResultsDirectory = QString::fromStdString(resultsDirectory); + } + else + { + m_ResultsDirectory = QDir::homePath(); + } + + // make sure that the results directory exists + QDir resultsDirectoryQDir = QDir(m_ResultsDirectory); + if (!resultsDirectoryQDir.exists()) + { + resultsDirectoryQDir.mkpath(m_ResultsDirectory); + } + + MITK_INFO("USNavigation") << "Results Directory: " << m_ResultsDirectory.toStdString(); } void USNavigationMarkerPlacement::OnActiveNavigationStepChanged(int index) { // update navigation step timer each time the active navigation step changes m_NavigationStepTimer->SetActiveIndex(index, m_NavigationSteps.at(index)->GetTitle().toStdString()); if (static_cast(m_NavigationStepNames.size()) <= index) { MITK_INFO("USNavigationLogging") << "Someting went wrong: unknown navigation step!"; } else { MITK_INFO("USNavigationLogging") << "Navigation step finished/changed, next step: " - << this->m_NavigationStepNames.at(index).toStdString() - << "; duration until now: " << m_NavigationStepTimer->GetTotalDuration(); + << this->m_NavigationStepNames.at(index).toStdString() + << "; duration until now: " << m_NavigationStepTimer->GetTotalDuration(); } } -void USNavigationMarkerPlacement::OnIntermediateResultProduced(const itk::SmartPointer resultsNode) +void USNavigationMarkerPlacement::OnNextNavigationStepInitialization(int index) { - // intermediate results only matter during an experiment - if (!m_IsExperimentRunning) + MITK_DEBUG << "Next Step: " << m_NavigationSteps.at(index)->GetTitle().toStdString(); + + if (m_NavigationSteps.at(index)->GetTitle().toStdString() == "Computer-assisted Intervention") + { + QmitkUSNavigationStepPunctuationIntervention* navigationStepPunctuationIntervention = static_cast(m_NavigationSteps.at(index)); + if (navigationStepPunctuationIntervention != nullptr) { - return; + if (m_CurrentStorage.IsNull()) { this->UpdateToolStorage(); } + if (m_CurrentStorage.IsNull() || (m_CurrentStorage->GetTool(m_NeedleIndex).IsNull())) + { + MITK_WARN << "Found null pointer when setting the tool axis, aborting"; + } + else + { + navigationStepPunctuationIntervention->SetNeedleMetaData(m_CurrentStorage->GetTool(m_NeedleIndex)); + MITK_DEBUG << "Needle axis vector: " << m_CurrentStorage->GetTool(m_NeedleIndex)->GetToolAxis(); + } } + } +} + +void USNavigationMarkerPlacement::OnIntermediateResultProduced(const itk::SmartPointer resultsNode) +{ + // intermediate results only matter during an experiment + if (!m_IsExperimentRunning) + { + return; + } - this->WaitCursorOn(); + this->WaitCursorOn(); - // set results node to the experiment logging (for saving contents to the - // file system) - m_ExperimentLogging->SetResult(resultsNode); + // set results node to the experiment logging (for saving contents to the + // file system) + m_ExperimentLogging->SetResult(resultsNode); - std::string resultsName; - if (!resultsNode->GetName(resultsName)) - { - MITK_WARN << "Could not get name of current results node."; - return; - } + std::string resultsName; + if (!resultsNode->GetName(resultsName)) + { + MITK_WARN << "Could not get name of current results node."; + return; + } - // save the mitk scene - std::string scenefile = QString(m_ExperimentResultsSubDirectory + QDir::separator() + - QString("Scene %1 - ").arg(m_SceneNumber++, 2, 10, QChar('0')) + - QString::fromStdString(resultsName).replace(":", "_") + ".mitk") - .toStdString(); - MITK_INFO << "Saving Scene File: " << scenefile; + // save the mitk scene + std::string scenefile = QString(m_ExperimentResultsSubDirectory + QDir::separator() + + QString("Scene %1 - ").arg(m_SceneNumber++, 2, 10, QChar('0')) + + QString::fromStdString(resultsName).replace(":", "_") + ".mitk") + .toStdString(); + MITK_INFO << "Saving Scene File: " << scenefile; - mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); - mitk::NodePredicateNot::Pointer isNotHelperObject = - mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); - mitk::DataStorage::SetOfObjects::ConstPointer nodesToBeSaved = this->GetDataStorage()->GetSubset(isNotHelperObject); + mitk::SceneIO::Pointer sceneIO = mitk::SceneIO::New(); + mitk::NodePredicateNot::Pointer isNotHelperObject = + mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true))); + mitk::DataStorage::SetOfObjects::ConstPointer nodesToBeSaved = this->GetDataStorage()->GetSubset(isNotHelperObject); - this->Convert2DImagesTo3D(nodesToBeSaved); + this->Convert2DImagesTo3D(nodesToBeSaved); - sceneIO->SaveScene(nodesToBeSaved, this->GetDataStorage(), scenefile); + sceneIO->SaveScene(nodesToBeSaved, this->GetDataStorage(), scenefile); - this->WaitCursorOff(); + this->WaitCursorOff(); } void USNavigationMarkerPlacement::ReinitOnImage() { - if (!m_ReinitAlreadyDone && m_CombinedModality.IsNotNull()) + if (!m_ReinitAlreadyDone && m_CombinedModality.IsNotNull()) + { + // make sure that the output is already calibrated correctly + // (if the zoom level was changed recently) + m_CombinedModality->Modified(); + m_CombinedModality->Update(); + + mitk::Image::Pointer image = m_CombinedModality->GetOutput(); + if (image.IsNotNull() && image->IsInitialized()) { - // make sure that the output is already calibrated correctly - // (if the zoom level was changed recently) - m_CombinedModality->Modified(); - m_CombinedModality->Update(); - - mitk::Image::Pointer image = m_CombinedModality->GetOutput(); - if (image.IsNotNull() && image->IsInitialized()) - { - // make a reinit on the ultrasound image - mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); - if (renderWindow != NULL && image->GetTimeGeometry()->IsValid()) - { - renderWindow->GetRenderingManager()->InitializeViews( - image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); - renderWindow->GetRenderingManager()->RequestUpdateAll(); - } - - this->RequestRenderWindowUpdate(); - - m_ReinitAlreadyDone = true; - } + // make a reinit on the ultrasound image + mitk::IRenderWindowPart *renderWindow = this->GetRenderWindowPart(); + if (renderWindow != NULL && image->GetTimeGeometry()->IsValid()) + { + renderWindow->GetRenderingManager()->InitializeViews( + image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); + renderWindow->GetRenderingManager()->RequestUpdateAll(); + } + + this->RequestRenderWindowUpdate(); + + m_ReinitAlreadyDone = true; } + } } void USNavigationMarkerPlacement::Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes) { - for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); ++it) + for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); ++it) + { + if (it->Value()->GetData() && strcmp(it->Value()->GetData()->GetNameOfClass(), "Image") == 0) { - if (it->Value()->GetData() && strcmp(it->Value()->GetData()->GetNameOfClass(), "Image") == 0) - { - // convert image to 3d image if it is 2d at the moment - mitk::Image::Pointer image = dynamic_cast(it->Value()->GetData()); - if (image.IsNotNull() && image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) - { - mitk::Convert2Dto3DImageFilter::Pointer convert2DTo3DImageFilter = mitk::Convert2Dto3DImageFilter::New(); - convert2DTo3DImageFilter->SetInput(image); - convert2DTo3DImageFilter->Update(); - it->Value()->SetData(convert2DTo3DImageFilter->GetOutput()); - } - } + // convert image to 3d image if it is 2d at the moment + mitk::Image::Pointer image = dynamic_cast(it->Value()->GetData()); + if (image.IsNotNull() && image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) + { + mitk::Convert2Dto3DImageFilter::Pointer convert2DTo3DImageFilter = mitk::Convert2Dto3DImageFilter::New(); + convert2DTo3DImageFilter->SetInput(image); + convert2DTo3DImageFilter->Update(); + it->Value()->SetData(convert2DTo3DImageFilter->GetOutput()); + } } + } } void USNavigationMarkerPlacement::CreateOverlays() { - // initialize warning overlay (and do not display it, yet) - m_WarnOverlay->SetText("Warning: No calibration available for current depth."); - - // set position and font size for the text overlay - // (nonesense postition as a layouter is used, but it ignored - // the overlay without setting a position here) - mitk::Point2D overlayPosition; - overlayPosition.SetElement(0, -50.0f); - overlayPosition.SetElement(1, -50.0f); - m_WarnOverlay->SetPosition2D(overlayPosition); - m_WarnOverlay->SetFontSize(22); - m_WarnOverlay->SetColor(1, 0, 0); // overlay should be red + // initialize warning overlay (and do not display it, yet) + m_WarnOverlay->SetText("Warning: No calibration available for current depth."); + + // set position and font size for the text overlay + // (nonesense postition as a layouter is used, but it ignored + // the overlay without setting a position here) + mitk::Point2D overlayPosition; + overlayPosition.SetElement(0, -50.0f); + overlayPosition.SetElement(1, -50.0f); + m_WarnOverlay->SetPosition2D(overlayPosition); + m_WarnOverlay->SetFontSize(22); + m_WarnOverlay->SetColor(1, 0, 0); // overlay should be red +} + +void USNavigationMarkerPlacement::UpdateToolStorage() +{ + if (m_NavigationDataSource.IsNull()) { m_NavigationDataSource = m_CombinedModality->GetNavigationDataSource(); } + if (m_NavigationDataSource.IsNull()) { MITK_WARN << "Found an invalid navigation data source object!"; } + us::ModuleContext* context = us::GetModuleContext(); + std::string id = m_NavigationDataSource->US_PROPKEY_ID; + std::string filter = "(" + mitk::NavigationToolStorage::US_PROPKEY_SOURCE_ID + "=" + id + ")"; + // Get Storage + std::vector > refs = context->GetServiceReferences(); + m_CurrentStorage = context->GetService(refs.front()); + + if (m_CurrentStorage.IsNull()) + { + MITK_WARN << "Found an invalid storage object!"; + } + else if (m_CurrentStorage->GetToolCount() != m_NavigationDataSource->GetNumberOfOutputs()) //there is something wrong with the storage + { + MITK_WARN << "Found a tool storage, but it has not the same number of tools like the NavigationDataSource. This storage won't be used because it isn't the right one."; + m_CurrentStorage = NULL; + } } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.h index 3fe0f4156c..6dd2b585ea 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.h @@ -1,198 +1,216 @@ /*=================================================================== 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 USNAVIGATIONMARKERPLACEMENT_H #define USNAVIGATIONMARKERPLACEMENT_H #include #include "IO/mitkUSNavigationLoggingBackend.h" #include "Widgets/QmitkUSNavigationProcessWidget.h" #include "mitkNavigationDataRecorder.h" #include "mitkNodeDisplacementFilter.h" #include "mitkUSImageLoggingFilter.h" #include #include #include #include namespace itk { template class SmartPointer; } namespace mitk { class USNavigationStepTimer; class USNavigationExperimentLogging; } namespace Ui { class USNavigationMarkerPlacement; } class QmitkUSAbstractNavigationStep; +class QmitkUSNavigationStepPunctuationIntervention; class QmitkStdMultiWidget; class QTimer; class QSignalMapper; /** * \brief View for navigated marker placement using the combined modality. * This view utilizes the QmitkUSNavigationProcessWidget to do the navigation * process. It can be switched between widgets for marker placement and widgets * for punctuation. * * An experiment mode allows for logging results, durations and the ultrasound * images. */ class USNavigationMarkerPlacement : public QmitkAbstractView { Q_OBJECT protected slots: /** * \brief Called periodically to update the rendering. * The standard multi widget is changed to fit the navigation process once it * is available and a reinit on the ultrasound image is done for a new image * node. */ void OnTimeout(); /** * \brief Called periodically during an experiment for logging the ultrasound images. */ void OnImageAndNavigationDataLoggingTimeout(); /** * \brief Initializes anything neccessary for an experiment. * The user is asked for a directory for storing the results and the logging * is started. */ void OnStartExperiment(); /** * \brief Stops logging and saves everything to the file system. */ void OnFinishExperiment(); void OnCombinedModalityChanged(itk::SmartPointer); /** * \brief Switches the navigation step widgets if the navigation application was changed. */ void OnSettingsChanged(itk::SmartPointer); /** * \brief Updates the timer for the navigation steps durations every time the active navigation step changes. */ void OnActiveNavigationStepChanged(int); + /** Initializes the next navigation step */ + void OnNextNavigationStepInitialization(int); + /** * \brief The data node is given to the experiment logging and scene is saved to the file system. */ void OnIntermediateResultProduced(const itk::SmartPointer); void OnAddAblationZone(int size); void OnEnableNavigationLayout(); void OnResetStandardLayout(); void OnChangeLayoutClicked(); void OnChangeAblationZone(int id, int newSize); + void OnRenderWindowSelection(); + + void OnRefreshView(); + public: static const char *DATANAME_TUMOUR; static const char *DATANAME_TARGETSURFACE; static const char *DATANAME_ZONES; static const char *DATANAME_TARGETS; static const char *DATANAME_TARGETS_PATHS; static const char *DATANAME_REACHED_TARGETS; explicit USNavigationMarkerPlacement(); ~USNavigationMarkerPlacement(); virtual void CreateQtPartControl(QWidget *parent); static const std::string VIEW_ID; void OnCombinedModalityPropertyChanged(const std::string &, const std::string &); - /** - * \returns the point defining the needle axis in the tool storage - */ - void SetToolAxisMarkerPlacement(); - mitk::Point3D m_ToolAxis; protected: /** * \brief A reinit on the ultrasound image is performed every time the view gets the focus. */ virtual void SetFocus(); /** * \brief Helper function which performs a reinit on the ultrasound image. */ void ReinitOnImage(); + /** + * \brief Sets the multiwidget to two windows, axial on top and 3D render window on the bottom. + */ + virtual void SetTwoWindowView(); + /** * \brief Helper function for being able to serialize the 2d ultrasound image. */ void Convert2DImagesTo3D(mitk::DataStorage::SetOfObjects::ConstPointer nodes); - void CreateOverlays(); + void UpdateToolStorage(); - QmitkUSNavigationProcessWidget::NavigationStepVector m_NavigationSteps; - itk::SmartPointer m_CombinedModality; - std::string m_CurrentApplicationName; - QString m_ResultsDirectory; - QString m_ExperimentName; - QString m_ExperimentResultsSubDirectory; - std::vector m_NavigationStepNames; // stores the names of the navigation steps which are currently used (for logging purposes) - mitk::USNavigationLoggingBackend m_LoggingBackend; - mitk::NodeDisplacementFilter::Pointer m_TargetNodeDisplacementFilter; - std::vector m_AblationZonesVector; - //To get tool storage - mitk::NavigationDataSource::Pointer m_NavigationDataSource; - mitk::NavigationToolStorage::Pointer m_CurrentStorage; + void CreateOverlays(); QWidget *m_Parent; + QmitkUSNavigationProcessWidget::NavigationStepVector m_NavigationSteps; QTimer *m_UpdateTimer; QTimer *m_ImageAndNavigationDataLoggingTimer; QmitkStdMultiWidget *m_StdMultiWidget; + itk::SmartPointer m_CombinedModality; bool m_ReinitAlreadyDone; bool m_IsExperimentRunning; + std::string m_CurrentApplicationName; + itk::SmartPointer m_NavigationStepTimer; itk::SmartPointer m_ExperimentLogging; - mitk::NodeDisplacementFilter::Pointer m_AblationZonesDisplacementFilter; + QPixmap m_IconRunning; QPixmap m_IconNotRunning; + + QString m_ResultsDirectory; + QString m_ExperimentName; + QString m_ExperimentResultsSubDirectory; + std::vector + m_NavigationStepNames; // stores the names of the navigation steps which are currently used (for logging purposes) + + mitk::USNavigationLoggingBackend m_LoggingBackend; mitk::USImageLoggingFilter::Pointer m_USImageLoggingFilter; mitk::NavigationDataRecorder::Pointer m_NavigationDataRecorder; // records navigation data files - int m_SceneNumber; - itk::SmartPointer m_WarnOverlay; + mitk::NodeDisplacementFilter::Pointer m_TargetNodeDisplacementFilter; + mitk::NodeDisplacementFilter::Pointer m_AblationZonesDisplacementFilter; + std::vector m_AblationZonesVector; + int m_NeedleIndex; int m_MarkerIndex; + int m_SceneNumber; + + itk::SmartPointer m_WarnOverlay; + + //To get tool storage + mitk::NavigationDataSource::Pointer m_NavigationDataSource; + mitk::NavigationToolStorage::Pointer m_CurrentStorage; + private: mitk::MessageDelegate2 m_ListenerDeviceChanged; Ui::USNavigationMarkerPlacement *ui; }; #endif // USNAVIGATIONMARKERPLACEMENT_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui index eb816e0225..a181fe0767 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/USNavigationMarkerPlacement.ui @@ -1,102 +1,123 @@ USNavigationMarkerPlacement 0 0 400 146 Form 0 0 0 0 0 Qt::Horizontal - - - Enable Navigation Render Window Layout - - - true - - + + + + + Enable Navigation Render Window Layout with RenderWindow + + + true + + + + + + + 1 + + + 3 + + + + + + + Refresh view + + + + Start New Experiment false Finish Experiment 20 20 QmitkUSNavigationProcessWidget QWidget
src/internal/Widgets/QmitkUSNavigationProcessWidget.h
1
OnStartExperiment() OnFinishExperiment()
diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/UltrasoundCalibrationControls.ui b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/UltrasoundCalibrationControls.ui index 55ea3f8943..59289dd670 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/UltrasoundCalibrationControls.ui +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/UltrasoundCalibrationControls.ui @@ -1,1162 +1,1163 @@ UltrasoundCalibrationControls true 0 0 374 923 0 0 QmitkTemplate 0 0 1 0 0 - 356 - 824 + 200 + 57 Config false Start Calibration for Selected Device 0 0 356 824 Spatial Calibration 0 10 351 831 - 2 + 1 Spacing 10 150 281 41 Add Point Qt::Horizontal QSizePolicy::Expanding 40 20 false Freeze 10 10 281 131 <html><head/><body><p>1. Freeze the US-Image.</p><p>2. Mark two points in the US-Image of which you know <br/>they are exactly 30mm apart in horizontal direction.</p><p>3. Marktwo more points in the US-Image of which you <br/>know they are exactly 20mm apart vertical direction.</p><p>4. Now you can click the &quot;Calculate Spacing&quot;-Button. <br/>The spacing is calculated and applied to the US-Image.</p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 10 200 281 192 20 400 261 23 Calculate Spacing Point Based 10 10 221 16 <!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:'MS Shell Dlg 2'; font-size:8.25pt; 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-size:8pt; font-weight:600; text-decoration: underline;">Step 1: Collect Points</span></p></body></html> 10 30 - 231 + 261 91 <!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:'MS Shell Dlg 2'; font-size:8.25pt; 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-size:8pt;">Slowly move a tracking tool into the image plane of the ultrasound. As soon as it becomes visible, click &quot;freeze&quot; and mark the point on the screen. Do this with as many points as necessary, then click calibrate to perform calibration.</span></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; 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;">Slowly move a tracking tool into the image plane of the ultrasound. As soon as it becomes visible, click &quot;freeze&quot; and mark the point on the screen by moving the Crosshair to the pont in the US image (best: click in 2D Axial view).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Do this with as many points as necessary, then click calibrate to perform calibration.</p></body></html>
true 10 120 291 31 75 true <!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:'MS Shell Dlg 2'; font-size:8.25pt; 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-size:8pt;">Tracking Status:</span></p></body></html> false 10 620 301 23 Save Calibration 10 550 291 16 Qt::Horizontal 10 200 301 225 10 450 571 16 <!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:'MS Shell Dlg 2'; font-size:8.25pt; 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-size:8pt; font-weight:600; text-decoration: underline;">Step 2: Calibrate (perform landmark transformation)</span></p></body></html> 10 160 301 25 Freeze Qt::Horizontal 40 20 false Add Point 10 430 301 21 Qt::Horizontal 10 510 301 23 Calibrate 10 590 584 17 Save additional logging information (MITK scene, etc.) true 10 480 584 17 Activate Scaling during Calibration Transform 10 570 291 16 <!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:'MS Shell Dlg 2'; font-size:8.25pt; 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-size:8pt; font-weight:600; text-decoration: underline;">Step 3: Save calibration to hard disc</span></p></body></html> 10 680 301 23 Stop Calibration Process 10 710 301 23 Restart Current Calibration 100 120 211 31 0 40 10 650 301 20 Qt::Horizontal PLUS Connection 10 10 301 241 <!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:'MS Shell Dlg 2'; font-size:8pt; 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-weight:600; text-decoration: underline;">Step 1: Calibrate using fCal</span></p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop <!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:'MS Shell Dlg 2'; font-size:8pt; 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;">1. Setup the Connection to PLUS</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2. Start fCal with the EchoTrackCalibration Config file</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3. Connect fcal to MITK, once it connected successfully you can click the &quot;Start Streaming&quot; Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">4. Now follow the steps in fCal and don't forget to save the Calibration in the end</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">5. Finish fCal</p></body></html> true <!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:'MS Shell Dlg 2'; font-size:8pt; 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-weight:600; text-decoration: underline;">Step 2: Get the calibration back from PLUS</span></p></body></html> <!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:'MS Shell Dlg 2'; font-size:8pt; 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;">1. Start a PLUS Server with the configfile you saved in the final step of fCal</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">2. Once the Server connected to MITK click the &quot;Start Streaming&quot; Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3. Now Click the &quot;Get Calibration from PLUS&quot;Button below</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">4. You can now save the calibration</p></body></html> true 10 270 301 281 false 0 90 299 23 Start Streaming false 0 140 299 23 Get Calibration from PLUS false 0 180 299 23 Save PLUS Calibration 0 220 299 23 Stop Calibration with PLUS false 0 60 291 21 0 120 281 16 false 0 30 301 23 Setup PLUS Connection false 0 10 291 21 0 0 - 356 - 824 + 100 + 30 Evaluation 0 0 311 821 1 Point Based Evaluation 10 130 301 16 Mark the visible needle tip with the crosshair 10 10 301 31 <!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:'MS Shell Dlg 2'; font-size:8.25pt; 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-size:8pt;">Bring the needle into the tracking volume, so the projection can be calculated</span></p></body></html> true 10 70 291 31 Push the needle forward until it becomes visible in the Image true 10 150 291 23 Step 3: Add Target Points 10 100 291 23 Step 2: Freeze Image 10 440 291 108 When done, save results Run Next Round Prefix: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Save Results Path: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 10 180 291 247 Control QFormLayout::AllNonFixedFieldsGrow Tracking Status: # Projection Points: # Target Points: 0 Evaluation TRE: 0 Projection TRE: 0 Calibration FRE: 0 0 10 50 291 23 Step 1: Save Needle Projection Reference Device 10 10 281 16 Choose pointer: 10 30 281 50 0 50 10 90 281 366 1 0 0 179 82 Create Reference Current reference points: Add Current Pointer Tip Position Qt::Vertical 20 111 0 0 281 312 Quick Verification Start Verification Current Point: Qt::Horizontal 40 20 <none> Add current pointer tip Result: QmitkToolTrackingStatusWidget QWidget
QmitkToolTrackingStatusWidget.h
1
QmitkUSNavigationStepCombinedModality QWidget
src/internal/NavigationStepWidgets/QmitkUSNavigationStepCombinedModality.h
1
QmitkPointListWidget QWidget
QmitkPointListWidget.h
1
QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
QmitkNavigationDataSourceSelectionWidget QWidget
QmitkNavigationDataSourceSelectionWidget.h
1
OnStartCalibrationProcess() OnReset() OnStopCalibrationProcess() diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp index 02b1f4064f..0ef68154c7 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.cpp @@ -1,556 +1,557 @@ /*=================================================================== 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 "QmitkUSNavigationProcessWidget.h" #include "ui_QmitkUSNavigationProcessWidget.h" #include "../NavigationStepWidgets/QmitkUSAbstractNavigationStep.h" #include "../SettingsWidgets/QmitkUSNavigationAbstractSettingsWidget.h" #include "mitkDataNode.h" #include "mitkNavigationDataToNavigationDataFilter.h" #include #include #include QmitkUSNavigationProcessWidget::QmitkUSNavigationProcessWidget(QWidget* parent) : QWidget(parent), m_SettingsWidget(0), m_BaseNode(mitk::DataNode::New()), m_CurrentTabIndex(0), m_CurrentMaxStep(0), m_ImageAlreadySetToNode(false), m_ReadySignalMapper(new QSignalMapper(this)), m_NoLongerReadySignalMapper(new QSignalMapper(this)), m_StdMultiWidget(0), m_UsePlanningStepWidget(false), ui(new Ui::QmitkUSNavigationProcessWidget) { m_Parent = parent; ui->setupUi(this); // remove the default page ui->stepsToolBox->setCurrentIndex(1);// ->removeItem(0); //set shortcuts QShortcut *nextShortcut = new QShortcut(QKeySequence("F10"), parent); QShortcut *prevShortcut = new QShortcut(QKeySequence("F11"), parent); connect(nextShortcut, SIGNAL(activated()), this, SLOT(OnNextButtonClicked())); connect(prevShortcut, SIGNAL(activated()), this, SLOT(OnPreviousButtonClicked())); //connect other slots connect( ui->restartStepButton, SIGNAL(clicked()), this, SLOT(OnRestartStepButtonClicked()) ); connect( ui->previousButton, SIGNAL(clicked()), this, SLOT(OnPreviousButtonClicked()) ); connect( ui->nextButton, SIGNAL(clicked()), this, SLOT(OnNextButtonClicked()) ); connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); connect (ui->settingsButton, SIGNAL(clicked()), this, SLOT(OnSettingsButtonClicked()) ); connect( m_ReadySignalMapper, SIGNAL(mapped(int)), this, SLOT(OnStepReady(int)) ); connect( m_NoLongerReadySignalMapper, SIGNAL(mapped(int)), this, SLOT(OnStepNoLongerReady(int)) ); ui->settingsFrameWidget->setHidden(true); } QmitkUSNavigationProcessWidget::~QmitkUSNavigationProcessWidget() { ui->stepsToolBox->blockSignals(true); for ( NavigationStepVector::iterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it ) { if ( (*it)->GetNavigationStepState() > QmitkUSAbstractNavigationStep::State_Stopped ) { (*it)->StopStep(); } delete *it; } m_NavigationSteps.clear(); if ( m_SettingsNode.IsNotNull() && m_DataStorage.IsNotNull() ) { m_DataStorage->Remove(m_SettingsNode); } delete ui; } void QmitkUSNavigationProcessWidget::EnableInteraction(bool enable) { if (enable) { ui->restartStepButton->setEnabled(true); ui->previousButton->setEnabled(true); ui->nextButton->setEnabled(true); ui->stepsToolBox->setEnabled(true); } else { ui->restartStepButton->setEnabled(false); ui->previousButton->setEnabled(false); ui->nextButton->setEnabled(false); ui->stepsToolBox->setEnabled(false); } } void QmitkUSNavigationProcessWidget::SetDataStorage(itk::SmartPointer dataStorage) { m_DataStorage = dataStorage; if ( dataStorage.IsNull() ) { mitkThrow() << "Data Storage must not be null for QmitkUSNavigationProcessWidget."; } // test if base node is already in the data storage and add it if not m_BaseNode = dataStorage->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); if ( m_BaseNode.IsNull() ) { m_BaseNode = mitk::DataNode::New(); m_BaseNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_BASENODE); dataStorage->Add(m_BaseNode); } // base node and image stream node may be the same node if ( strcmp(QmitkUSAbstractNavigationStep::DATANAME_BASENODE, QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM) != 0) { m_ImageStreamNode = dataStorage->GetNamedNode(QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM); if (m_ImageStreamNode.IsNull()) { // Create Node for US Stream m_ImageStreamNode = mitk::DataNode::New(); m_ImageStreamNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_IMAGESTREAM); dataStorage->Add(m_ImageStreamNode); } } else { m_ImageStreamNode = m_BaseNode; } m_SettingsNode = dataStorage->GetNamedDerivedNode(QmitkUSAbstractNavigationStep::DATANAME_SETTINGS, m_BaseNode); if ( m_SettingsNode.IsNull() ) { m_SettingsNode = mitk::DataNode::New(); m_SettingsNode->SetName(QmitkUSAbstractNavigationStep::DATANAME_SETTINGS); dataStorage->Add(m_SettingsNode, m_BaseNode); } if (m_SettingsWidget) { m_SettingsWidget->SetSettingsNode(m_SettingsNode); } } void QmitkUSNavigationProcessWidget::SetSettingsWidget(QmitkUSNavigationAbstractSettingsWidget* settingsWidget) { // disconnect slots to settings widget if there was a widget before if ( m_SettingsWidget ) { disconnect( ui->settingsSaveButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnSave()) ); disconnect( ui->settingsCancelButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnCancel()) ); disconnect (m_SettingsWidget, SIGNAL(Saved()), this, SLOT(OnSettingsWidgetReturned()) ); disconnect (m_SettingsWidget, SIGNAL(Canceled()), this, SLOT(OnSettingsWidgetReturned()) ); disconnect (m_SettingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer)), this, SLOT(OnSettingsChanged(itk::SmartPointer)) ); ui->settingsWidget->removeWidget(m_SettingsWidget); } m_SettingsWidget = settingsWidget; if ( m_SettingsWidget ) { m_SettingsWidget->LoadSettings(); connect( ui->settingsSaveButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnSave()) ); connect( ui->settingsCancelButton, SIGNAL(clicked()), m_SettingsWidget, SLOT(OnCancel()) ); connect (m_SettingsWidget, SIGNAL(Saved()), this, SLOT(OnSettingsWidgetReturned()) ); connect (m_SettingsWidget, SIGNAL(Canceled()), this, SLOT(OnSettingsWidgetReturned()) ); connect (m_SettingsWidget, SIGNAL(SettingsChanged(itk::SmartPointer)), this, SLOT(OnSettingsChanged(itk::SmartPointer)) ); if ( m_SettingsNode.IsNotNull() ) { m_SettingsWidget->SetSettingsNode(m_SettingsNode, true); } ui->settingsWidget->addWidget(m_SettingsWidget); } ui->settingsButton->setEnabled(m_SettingsWidget != 0); } void QmitkUSNavigationProcessWidget::SetNavigationSteps(NavigationStepVector navigationSteps) { disconnect( this, SLOT(OnTabChanged(int)) ); for ( int n = ui->stepsToolBox->count()-1; n >= 0; --n ) { //ui->stepsToolBox->removeItem(n); } connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); m_NavigationSteps.clear(); m_NavigationSteps = navigationSteps; this->InitializeNavigationStepWidgets(); // notify all navigation step widgets about the current settings for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->OnSettingsChanged(m_SettingsNode); } } void QmitkUSNavigationProcessWidget::ResetNavigationProcess() { MITK_INFO("QmitkUSNavigationProcessWidget") << "Resetting navigation process."; ui->stepsToolBox->blockSignals(true); for ( int n = 0; n <= m_CurrentMaxStep; ++n ) { m_NavigationSteps.at(n)->StopStep(); //if ( n > 0 ) { ui->stepsToolBox->setItemEnabled(n, false); } } ui->stepsToolBox->blockSignals(false); m_CurrentMaxStep = 0; ui->stepsToolBox->setCurrentIndex(0); if ( m_NavigationSteps.size() > 0 ) { m_NavigationSteps.at(0)->ActivateStep(); } this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::UpdateNavigationProgress() { if ( m_CombinedModality.IsNotNull() && !m_CombinedModality->GetIsFreezed() ) { m_CombinedModality->Modified(); m_CombinedModality->Update(); if ( m_LastNavigationDataFilter.IsNotNull() ) { m_LastNavigationDataFilter->Update(); } mitk::Image::Pointer image = m_CombinedModality->GetOutput(); // make sure that always the current image is set to the data node if ( image.IsNotNull() && m_ImageStreamNode->GetData() != image.GetPointer() && image->IsInitialized() ) { m_ImageStreamNode->SetData(image); m_ImageAlreadySetToNode = true; } } if ( m_CurrentTabIndex > 0 && static_cast(m_CurrentTabIndex) < m_NavigationSteps.size() ) { m_NavigationSteps.at(m_CurrentTabIndex)->Update(); } } void QmitkUSNavigationProcessWidget::OnNextButtonClicked() { if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetIsFreezed()) {return;} //no moving through steps when the modality is nullptr or frozen int currentIndex = ui->stepsToolBox->currentIndex(); if (currentIndex >= m_CurrentMaxStep) { MITK_WARN << "Next button clicked though no next tab widget is available."; return; } ui->stepsToolBox->setCurrentIndex(++currentIndex); this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::OnPreviousButtonClicked() { if (m_CombinedModality.IsNotNull() && m_CombinedModality->GetIsFreezed()) {return;} //no moving through steps when the modality is nullptr or frozen int currentIndex = ui->stepsToolBox->currentIndex(); if (currentIndex <= 0) { MITK_WARN << "Previous button clicked though no previous tab widget is available."; return; } ui->stepsToolBox->setCurrentIndex(--currentIndex); this->UpdatePrevNextButtons(); } void QmitkUSNavigationProcessWidget::OnRestartStepButtonClicked() { - MITK_INFO("QmitkUSNavigationProcessWidget") << "Restarting step " + MITK_DEBUG("QmitkUSNavigationProcessWidget") << "Restarting step " << m_CurrentTabIndex << " (" << m_NavigationSteps.at(m_CurrentTabIndex)->GetTitle().toStdString() << ")."; m_NavigationSteps.at(ui->stepsToolBox->currentIndex())->RestartStep(); m_NavigationSteps.at(ui->stepsToolBox->currentIndex())->ActivateStep(); } void QmitkUSNavigationProcessWidget::OnTabChanged(int index) { + emit SignalActiveNavigationStepChangeRequested(index); if ( index < 0 || index >= static_cast(m_NavigationSteps.size()) ) { return; } else if ( m_CurrentTabIndex == index ) { // just activate the step if it is the same step againg m_NavigationSteps.at(index)->ActivateStep(); return; } - MITK_INFO("QmitkUSNavigationProcessWidget") << "Activating navigation step " + MITK_DEBUG("QmitkUSNavigationProcessWidget") << "Activating navigation step " << index << " (" << m_NavigationSteps.at(index)->GetTitle().toStdString() <<")."; if (index > m_CurrentTabIndex) { this->UpdateFilterPipeline(); // finish all previous steps to make sure that all data is valid for (int n = m_CurrentTabIndex; n < index; ++n) { m_NavigationSteps.at(n)->FinishStep(); } } // deactivate the previously active step if ( m_CurrentTabIndex > 0 && m_NavigationSteps.size() > static_cast(m_CurrentTabIndex) ) { m_NavigationSteps.at(m_CurrentTabIndex)->DeactivateStep(); } // start step of the current tab if it wasn't started before if ( m_NavigationSteps.at(index)->GetNavigationStepState() == QmitkUSAbstractNavigationStep::State_Stopped ) { m_NavigationSteps.at(index)->StartStep(); } m_NavigationSteps.at(index)->ActivateStep(); if (static_cast(index) < m_NavigationSteps.size()) ui->restartStepButton->setEnabled(m_NavigationSteps.at(index)->GetIsRestartable()); this->UpdatePrevNextButtons(); m_CurrentTabIndex = index; emit SignalActiveNavigationStepChanged(index); } void QmitkUSNavigationProcessWidget::OnSettingsButtonClicked() { this->SetSettingsWidgetVisible(true); } void QmitkUSNavigationProcessWidget::OnSettingsWidgetReturned() { this->SetSettingsWidgetVisible(false); } void QmitkUSNavigationProcessWidget::OnSettingsNodeChanged(itk::SmartPointer dataNode) { if ( m_SettingsWidget ) m_SettingsWidget->SetSettingsNode(dataNode); } void QmitkUSNavigationProcessWidget::OnStepReady(int index) { if (m_CurrentMaxStep <= index) { m_CurrentMaxStep = index + 1; this->UpdatePrevNextButtons(); for (int n = 0; n <= m_CurrentMaxStep; ++n) { //ui->stepsToolBox->setItemEnabled(n, true); } } emit SignalNavigationStepFinished(index, true); } void QmitkUSNavigationProcessWidget::OnStepNoLongerReady(int index) { if (m_CurrentMaxStep > index) { m_CurrentMaxStep = index; this->UpdatePrevNextButtons(); this->UpdateFilterPipeline(); for (int n = m_CurrentMaxStep+1; n < ui->stepsToolBox->count(); ++n) { //ui->stepsToolBox->setItemEnabled(n, false); m_NavigationSteps.at(n)->StopStep(); } } emit SignalNavigationStepFinished(index, false); } void QmitkUSNavigationProcessWidget::OnCombinedModalityChanged(itk::SmartPointer combinedModality) { m_CombinedModality = combinedModality; m_ImageAlreadySetToNode = false; if ( combinedModality.IsNotNull() ) { if ( combinedModality->GetNavigationDataSource().IsNull() ) { MITK_WARN << "There is no navigation data source set for the given combined modality."; return; } this->UpdateFilterPipeline(); } for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->SetCombinedModality(combinedModality); } emit SignalCombinedModalityChanged(combinedModality); } void QmitkUSNavigationProcessWidget::OnSettingsChanged(const mitk::DataNode::Pointer dataNode) { static bool methodEntered = false; if ( methodEntered ) { MITK_WARN("QmitkUSNavigationProcessWidget") << "Ignoring recursive call to 'OnSettingsChanged()'. " << "Make sure to no emit 'SignalSettingsNodeChanged' in an 'OnSettingsChanged()' method."; return; } methodEntered = true; std::string application; if ( dataNode->GetStringProperty("settings.application", application) ) { QString applicationQString = QString::fromStdString(application); if ( applicationQString != ui->titleLabel->text() ) { ui->titleLabel->setText(applicationQString); } } // notify all navigation step widgets about the changed settings for (NavigationStepIterator it = m_NavigationSteps.begin(); it != m_NavigationSteps.end(); ++it) { (*it)->OnSettingsChanged(dataNode); } emit SignalSettingsChanged(dataNode); methodEntered = false; } void QmitkUSNavigationProcessWidget::InitializeNavigationStepWidgets() { // do not listen for steps tool box signal during insertion of items into tool box disconnect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); m_CurrentMaxStep = 0; mitk::DataStorage::Pointer dataStorage = m_DataStorage; for (unsigned int n = 0; n < m_NavigationSteps.size(); ++n) { QmitkUSAbstractNavigationStep* curNavigationStep = m_NavigationSteps.at(n); curNavigationStep->SetDataStorage(dataStorage); connect( curNavigationStep, SIGNAL(SignalReadyForNextStep()), m_ReadySignalMapper, SLOT(map())); connect( curNavigationStep, SIGNAL(SignalNoLongerReadyForNextStep()), m_NoLongerReadySignalMapper, SLOT(map()) ); connect( curNavigationStep, SIGNAL(SignalCombinedModalityChanged(itk::SmartPointer)), this, SLOT(OnCombinedModalityChanged(itk::SmartPointer)) ); connect( curNavigationStep, SIGNAL(SignalIntermediateResult(const itk::SmartPointer)), this, SIGNAL(SignalIntermediateResult(const itk::SmartPointer)) ); connect( curNavigationStep, SIGNAL(SignalSettingsNodeChanged(itk::SmartPointer)), this, SLOT(OnSettingsNodeChanged(itk::SmartPointer)) ); m_ReadySignalMapper->setMapping(curNavigationStep, n); m_NoLongerReadySignalMapper->setMapping(curNavigationStep, n); ui->stepsToolBox->insertWidget(n, curNavigationStep); //if ( n > 0 ) { ui->stepsToolBox->get(n, false); } } ui->restartStepButton->setEnabled(m_NavigationSteps.at(0)->GetIsRestartable()); ui->stepsToolBox->setCurrentIndex(0); // activate the first navigation step widgets if ( ! m_NavigationSteps.empty() ) { m_NavigationSteps.at(0)->ActivateStep(); } // after filling the steps tool box the signal is interesting again connect( ui->stepsToolBox, SIGNAL(currentChanged(int)), this, SLOT(OnTabChanged(int)) ); this->UpdateFilterPipeline(); } void QmitkUSNavigationProcessWidget::UpdatePrevNextButtons() { int currentIndex = ui->stepsToolBox->currentIndex(); ui->previousButton->setEnabled(currentIndex > 0); ui->nextButton->setEnabled(currentIndex < m_CurrentMaxStep); } void QmitkUSNavigationProcessWidget::UpdateFilterPipeline() { if ( m_CombinedModality.IsNull() ) { return; } std::vector filterList; mitk::NavigationDataSource::Pointer navigationDataSource = m_CombinedModality->GetNavigationDataSource(); for (unsigned int n = 0; n <= static_cast(m_CurrentMaxStep) && n < m_NavigationSteps.size(); ++n) { QmitkUSAbstractNavigationStep::FilterVector filter = m_NavigationSteps.at(n)->GetFilter(); if ( ! filter.empty() ) { filterList.insert(filterList.end(), filter.begin(), filter.end()); } } if ( ! filterList.empty() ) { for (unsigned int n = 0; n < navigationDataSource->GetNumberOfOutputs(); ++n) { filterList.at(0)->SetInput(n, navigationDataSource->GetOutput(n)); } for (std::vector::iterator it = filterList.begin()+1; it != filterList.end(); ++it) { std::vector::iterator prevIt = it-1; for (unsigned int n = 0; n < (*prevIt)->GetNumberOfOutputs(); ++n) { (*it)->SetInput(n, (*prevIt)->GetOutput(n)); } } m_LastNavigationDataFilter = filterList.at(filterList.size()-1); } else { m_LastNavigationDataFilter = navigationDataSource.GetPointer(); } } void QmitkUSNavigationProcessWidget::SetSettingsWidgetVisible(bool visible) { ui->settingsFrameWidget->setVisible(visible); ui->stepsToolBox->setHidden(visible); ui->settingsButton->setHidden(visible); ui->restartStepButton->setHidden(visible); ui->previousButton->setHidden(visible); ui->nextButton->setHidden(visible); } void QmitkUSNavigationProcessWidget::FinishCurrentNavigationStep() { int currentIndex = ui->stepsToolBox->currentIndex(); QmitkUSAbstractNavigationStep* curNavigationStep = m_NavigationSteps.at(currentIndex); curNavigationStep->FinishStep(); } diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h index 44e6c3f967..1a78fd3998 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/Widgets/QmitkUSNavigationProcessWidget.h @@ -1,174 +1,179 @@ /*=================================================================== 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 USNAVIGATIONPROCESSWIDGET_H #define USNAVIGATIONPROCESSWIDGET_H #include #include #include #include namespace itk { template class SmartPointer; } namespace mitk { class NodeDisplacementFilter; } namespace Ui { class QmitkUSNavigationProcessWidget; } class QmitkUSAbstractNavigationStep; class QmitkUSNavigationAbstractSettingsWidget; class QmitkUSNavigationStepCombinedModality; class QmitkStdMultiWidget; class QTimer; class QSignalMapper; /** * \brief Widget for handling navigation steps. * The navigation steps (subclasses of QmitkUSAbstractNavigationStep) can be set * in a vector. The coordination of this steps is done by this widget then. */ class QmitkUSNavigationProcessWidget : public QWidget { Q_OBJECT signals: /** * \brief Signals a replacement of the combined modality by one of the navigation steps. */ void SignalCombinedModalityChanged(itk::SmartPointer); /** * \brief Signals a change of the navigation settings. */ void SignalSettingsChanged(itk::SmartPointer); /** - * \brief Signals a change of the currently active navigation step. + * \brief Signals if a change of the currently active navigation step is requested. Gives the index of the new step. + */ + void SignalActiveNavigationStepChangeRequested(int); + + /** + * \brief Signals a change of the currently active navigation step after the step was changed. */ void SignalActiveNavigationStepChanged(int); /** * \brief Signals that the navigation step with the given id was finished. */ void SignalNavigationStepFinished(int, bool); /** * \brief Signals the creation of an intermediate result. * The result data is given as properties of the data node. */ void SignalIntermediateResult(const itk::SmartPointer); protected slots: void OnNextButtonClicked(); void OnPreviousButtonClicked(); void OnRestartStepButtonClicked(); void OnTabChanged(int index); void OnSettingsButtonClicked(); void OnSettingsWidgetReturned(); void OnSettingsNodeChanged(itk::SmartPointer); void OnStepReady(int); void OnStepNoLongerReady(int); void OnCombinedModalityChanged(itk::SmartPointer); void OnSettingsChanged(const itk::SmartPointer); public: typedef std::vector NavigationStepVector; typedef NavigationStepVector::iterator NavigationStepIterator; explicit QmitkUSNavigationProcessWidget(QWidget* parent = 0); ~QmitkUSNavigationProcessWidget(); /** * \brief Setter for the data storage used for storing the navigation progress. */ void SetDataStorage(itk::SmartPointer dataStorage); void SetSettingsWidget(QmitkUSNavigationAbstractSettingsWidget*); /** * \brief Setter for a vector of navigation step widgets. * These widgets are used for the navigation process in the order of their * appearance in this vector. */ void SetNavigationSteps(NavigationStepVector navigationSteps); /** * \brief Forget the current progress of the navigation process. * The process will then start again at the beginning. */ void ResetNavigationProcess(); /** Enables/disables the (navigation step) interaction with this widget. * The settings button is not affected by this flag. */ void EnableInteraction(bool enable); /** Finishes the current navigation step. */ void FinishCurrentNavigationStep(); /** Updates the navigation process widget, which includes updating the * navigation pipeline. Has to be called from outside this class with * a given update rate. So no additional internal timer is needed. */ void UpdateNavigationProgress(); protected: void InitializeNavigationStepWidgets(); void UpdatePrevNextButtons(); void UpdateFilterPipeline(); void SetSettingsWidgetVisible(bool visible); itk::SmartPointer m_DataStorage; NavigationStepVector m_NavigationSteps; QmitkUSNavigationAbstractSettingsWidget* m_SettingsWidget; itk::SmartPointer m_BaseNode; itk::SmartPointer m_SettingsNode; int m_CurrentTabIndex; int m_CurrentMaxStep; itk::SmartPointer m_ImageStreamNode; bool m_ImageAlreadySetToNode; itk::SmartPointer m_CombinedModality; itk::SmartPointer m_LastNavigationDataFilter; QWidget* m_Parent; QSignalMapper* m_ReadySignalMapper; QSignalMapper* m_NoLongerReadySignalMapper; QmitkStdMultiWidget* m_StdMultiWidget; bool m_UsePlanningStepWidget; private: Ui::QmitkUSNavigationProcessWidget *ui; }; #endif // USNAVIGATIONPROCESSWIDGET_H diff --git a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/org_mbi_gui_qt_usnavigation_Activator.cpp b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/org_mbi_gui_qt_usnavigation_Activator.cpp index f8a17098f1..fb1eaf8361 100644 --- a/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/org_mbi_gui_qt_usnavigation_Activator.cpp +++ b/Plugins/org.mitk.gui.qt.igt.app.echotrack/src/internal/org_mbi_gui_qt_usnavigation_Activator.cpp @@ -1,67 +1,67 @@ /*=================================================================== 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 "org_mbi_gui_qt_usnavigation_Activator.h" #include #include //#include "USNavigation.h" #include "UltrasoundCalibration.h" #include "USNavigationMarkerPlacement.h" #include "QmitkUSNavigationPerspective.h" #include "mitkVirtualTrackingDevice.h" namespace mitk { ctkPluginContext* org_mbi_gui_qt_usnavigation_Activator::m_Context = 0; void org_mbi_gui_qt_usnavigation_Activator::start(ctkPluginContext* context) { m_Context = context; //BERRY_REGISTER_EXTENSION_CLASS(USNavigation, context) BERRY_REGISTER_EXTENSION_CLASS(UltrasoundCalibration, context) BERRY_REGISTER_EXTENSION_CLASS(USNavigationMarkerPlacement, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkUSNavigationPerspective, context) - // create a combined modality persitence object for loading and storing + // create a combined modality persistence object for loading and storing // combined modality objects persistently m_USCombinedModalityPersistence = mitk::USNavigationCombinedModalityPersistence::New(); } void org_mbi_gui_qt_usnavigation_Activator::stop(ctkPluginContext* context) { m_USCombinedModalityPersistence = 0; m_Context = 0; Q_UNUSED(context) } ctkPluginContext *org_mbi_gui_qt_usnavigation_Activator::GetContext() { return m_Context; } } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) Q_EXPORT_PLUGIN2(org_mitk_gui_qt_igt_app_echotrack, mitk::org_mbi_gui_qt_usnavigation_Activator) #endif // necessary for us::GetModuleContext() in USNavigationCombinedModalityPersistence // (see: https://www.mail-archive.com/mitk-users@lists.sourceforge.net/msg04421.html) US_INITIALIZE_MODULE diff --git a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp index 8ed8cb6862..0c651095d4 100644 --- a/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp +++ b/Plugins/org.mitk.gui.qt.igtexamples/src/internal/QmitkIGTTrackingLabView.cpp @@ -1,734 +1,731 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkIGTTrackingLabView.h" #include #include #include #include #include #include - -#include #include #include #include #include #include -#include #include #include #include #include // Qt #include #include #include // vtk #include const std::string QmitkIGTTrackingLabView::VIEW_ID = "org.mitk.views.igttrackinglab"; QmitkIGTTrackingLabView::QmitkIGTTrackingLabView() : QmitkAbstractView() ,m_Source(nullptr) ,m_PermanentRegistrationFilter(nullptr) ,m_Visualizer(nullptr) ,m_VirtualView(nullptr) ,m_PSRecordingPointSet(nullptr) ,m_PointSetRecording(false) ,m_PermanentRegistration(false) ,m_CameraView(false) ,m_ImageFiducialsDataNode(nullptr) ,m_TrackerFiducialsDataNode(nullptr) ,m_PermanentRegistrationSourcePoints(nullptr) { } //############################################################################################### //############################################################################################### //############################## Timer method for IGT pipeline updating ######################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::UpdateTimer() { if (m_PermanentRegistration && m_PermanentRegistrationFilter.IsNotNull()) { if(IsTransformDifferenceHigh(m_ObjectmarkerNavigationData, m_ObjectmarkerNavigationDataLastUpdate)) { m_ObjectmarkerNavigationDataLastUpdate->Graft(m_ObjectmarkerNavigationData); m_PermanentRegistrationFilter->Update(); } } if (m_CameraView && m_VirtualView.IsNotNull()) {m_VirtualView->Update();} if(m_PointSetRecording && m_PSRecordingPointSet.IsNotNull()) { int size = m_PSRecordingPointSet->GetSize(); mitk::NavigationData::Pointer nd = m_PointSetRecordingNavigationData; if(size > 0) { mitk::Point3D p = m_PSRecordingPointSet->GetPoint(size-1); if(p.EuclideanDistanceTo(nd->GetPosition()) > (double) m_Controls.m_PSRecordingSpinBox->value()) m_PSRecordingPointSet->InsertPoint(size, nd->GetPosition()); } else m_PSRecordingPointSet->InsertPoint(size, nd->GetPosition()); } } //############################################################################################### //############################################################################################### //############################## Slots of CONFIGURATION step #################################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnSetupNavigation() { if(m_Source.IsNotNull()) if(m_Source->IsTracking()) return; mitk::DataStorage* ds = this->GetDataStorage(); if(ds == nullptr) { MITK_WARN << "IGTSurfaceTracker: Error. Cannot access DataStorage. Navigation not possible"; return; } //Building up the filter pipeline try { this->InitializeRegistration(); } catch(mitk::IGTException& e) { MITK_WARN << "Error while building the IGT-Pipeline: " << e.GetDescription(); this->DestroyIGTPipeline(); // destroy the pipeline if building is incomplete return; } catch(...) { MITK_WARN << "Unexpected error while building the IGT-Pipeline"; this->DestroyIGTPipeline(); return; } } void QmitkIGTTrackingLabView::OnInstrumentSelected() { if (m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource().IsNotNull()) { m_InstrumentNavigationData = m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedToolID()); } else { m_Controls.m_PointerNameLabel->setText(""); return; } if (m_InstrumentNavigationData.IsNotNull()) { m_Controls.m_PointerNameLabel->setText(m_InstrumentNavigationData->GetName()); } else { m_Controls.m_PointerNameLabel->setText(""); } } void QmitkIGTTrackingLabView::OnObjectmarkerSelected() { if (m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource().IsNotNull()) { m_ObjectmarkerNavigationData = m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedToolID()); MITK_INFO << "Objectmarker rotation: " << m_ObjectmarkerNavigationData->GetOrientation(); } else { m_Controls.m_ObjectmarkerNameLabel->setText(""); return; } if (m_ObjectmarkerNavigationData.IsNotNull()) { m_Controls.m_ObjectmarkerNameLabel->setText(m_ObjectmarkerNavigationData->GetName()); } else { m_Controls.m_ObjectmarkerNameLabel->setText(""); } } //############################################################################################### //############################################################################################### //####################### Slots of INITIAL REGISTRATION step #################################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnInitialRegistration() { //Check for initialization if (!CheckRegistrationInitialization()) return; mitk::PointSet::Pointer imageFiducials = dynamic_cast(m_ImageFiducialsDataNode->GetData()); mitk::PointSet::Pointer trackerFiducials = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); //############### conversion to vtk data types (we will use the vtk landmark based transform) ########################## //convert point sets to vtk poly data vtkSmartPointer sourcePoints = vtkSmartPointer::New(); vtkSmartPointer targetPoints = vtkSmartPointer::New(); for (int i=0; iGetSize(); i++) { double point[3] = {imageFiducials->GetPoint(i)[0],imageFiducials->GetPoint(i)[1],imageFiducials->GetPoint(i)[2]}; sourcePoints->InsertNextPoint(point); double point_targets[3] = {trackerFiducials->GetPoint(i)[0],trackerFiducials->GetPoint(i)[1],trackerFiducials->GetPoint(i)[2]}; targetPoints->InsertNextPoint(point_targets); } //########################### here, the actual transform is computed ########################## //compute transform vtkSmartPointer transform = vtkSmartPointer::New(); transform->SetSourceLandmarks(sourcePoints); transform->SetTargetLandmarks(targetPoints); transform->SetModeToRigidBody(); transform->Modified(); transform->Update(); //compute FRE of transform double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(imageFiducials, trackerFiducials, transform); m_Controls.m_RegistrationWidget->SetQualityDisplayText("FRE: " + QString::number(FRE) + " mm"); //############################################################################################# //############### conversion back to itk/mitk data types ########################## //convert from vtk to itk data types itk::Matrix rotationFloat = itk::Matrix(); itk::Vector translationFloat = itk::Vector(); itk::Matrix rotationDouble = itk::Matrix(); itk::Vector translationDouble = itk::Vector(); vtkSmartPointer m = transform->GetMatrix(); for(int k=0; k<3; k++) for(int l=0; l<3; l++) { rotationFloat[k][l] = m->GetElement(k,l); rotationDouble[k][l] = m->GetElement(k,l); } for(int k=0; k<3; k++) { translationFloat[k] = m->GetElement(k,3); translationDouble[k] = m->GetElement(k,3); } //create affine transform 3D surface mitk::AffineTransform3D::Pointer mitkTransform = mitk::AffineTransform3D::New(); mitkTransform->SetMatrix(rotationDouble); mitkTransform->SetOffset(translationDouble); //############################################################################################# //############### object is transformed ########################## //save transform m_T_ObjectReg = mitk::NavigationData::New(mitkTransform); // this is stored in a member because it is needed for permanent registration later on //transform surface if(m_Controls.m_SurfaceActive->isChecked() && m_Controls.m_ObjectComboBox->GetSelectedNode().IsNotNull()) { m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(mitkTransform); } //################################################################ //############### if activated: ct image is also transformed ########################## //transform ct image //todo: Erklären, dass hier AffineTransform3D verwendet wird, weil NavigationData kein Spacing unterstützt! if(m_Controls.m_ImageActive->isChecked() && m_Controls.m_ImageComboBox->GetSelectedNode().IsNotNull()) { //first we have to store the original ct image transform to compose it with the new transform later mitk::AffineTransform3D::Pointer imageTransform = m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform(); m_T_ImageGeo = mitk::AffineTransform3D::New(); // this is also stored in a member because it is needed for permanent registration later on //now the new transform of the ct image is computed m_T_ImageGeo->Compose(imageTransform); imageTransform->Compose(mitkTransform); mitk::AffineTransform3D::Pointer newImageTransform = mitk::AffineTransform3D::New(); //create new image transform... setting the composed directly leads to an error itk::Matrix rotationFloatNew = imageTransform->GetMatrix(); itk::Vector translationFloatNew = imageTransform->GetOffset(); newImageTransform->SetMatrix(rotationFloatNew); newImageTransform->SetOffset(translationFloatNew); m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(newImageTransform); m_T_ImageReg = m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform(); } //################################################################ } void QmitkIGTTrackingLabView::OnAddRegistrationTrackingFiducial() { mitk::NavigationData::Pointer nd = m_InstrumentNavigationData; if( nd.IsNull() || !nd->IsDataValid()) { QMessageBox::warning( 0, "Invalid tracking data", "Navigation data is not available or invalid!", QMessageBox::Ok ); return; } if(m_TrackerFiducialsDataNode.IsNotNull() && m_TrackerFiducialsDataNode->GetData() != nullptr) { mitk::PointSet::Pointer ps = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); ps->InsertPoint(ps->GetSize(), nd->GetPosition()); } else QMessageBox::warning(nullptr, "IGTSurfaceTracker: Error", "Can not access Tracker Fiducials. Adding fiducial not possible!"); } void QmitkIGTTrackingLabView::InitializeRegistration() { mitk::DataStorage* ds = this->GetDataStorage(); if( ds == nullptr ) return; // let the registration widget know about the slice navigation controllers // in the active render window part (crosshair updates) foreach(QmitkRenderWindow* renderWindow, this->GetRenderWindowPart()->GetQmitkRenderWindows().values()) { m_Controls.m_RegistrationWidget->AddSliceNavigationController(renderWindow->GetSliceNavigationController()); } if(m_ImageFiducialsDataNode.IsNull()) { m_ImageFiducialsDataNode = mitk::DataNode::New(); mitk::PointSet::Pointer ifPS = mitk::PointSet::New(); m_ImageFiducialsDataNode->SetData(ifPS); mitk::Color color; color.Set(1.0f, 0.0f, 0.0f); m_ImageFiducialsDataNode->SetName("Image Fiducials"); m_ImageFiducialsDataNode->SetColor(color); m_ImageFiducialsDataNode->SetBoolProperty( "updateDataOnRender", false ); ds->Add(m_ImageFiducialsDataNode); } m_Controls.m_RegistrationWidget->SetImageFiducialsNode(m_ImageFiducialsDataNode); if(m_TrackerFiducialsDataNode.IsNull()) { m_TrackerFiducialsDataNode = mitk::DataNode::New(); mitk::PointSet::Pointer tfPS = mitk::PointSet::New(); m_TrackerFiducialsDataNode->SetData(tfPS); mitk::Color color; color.Set(0.0f, 1.0f, 0.0f); m_TrackerFiducialsDataNode->SetName("Tracking Fiducials"); m_TrackerFiducialsDataNode->SetColor(color); m_TrackerFiducialsDataNode->SetBoolProperty( "updateDataOnRender", false ); ds->Add(m_TrackerFiducialsDataNode); } m_Controls.m_RegistrationWidget->SetTrackerFiducialsNode(m_TrackerFiducialsDataNode); } //############################################################################################### //############################################################################################### //####################### Slots of PERMANENT REGISTRATION step ################################## //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnPermanentRegistration(bool on) { if(on) { //###################################################################### //######################## inititalization ############################# //###################################################################### //some initial checks if(!CheckRegistrationInitialization()) { m_Controls.m_UsePermanentRegistrationToggle->setChecked(false); return; } //remember initial object transform to calculate the object to marker transform later on and convert it to navigation data mitk::AffineTransform3D::Pointer transform = this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform(); mitk::NavigationData::Pointer T_Object = mitk::NavigationData::New(transform,false); //TODO: catch exception during conversion? //then reset the transform because we will now start to calculate the permanent registration this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIdentity(); if(m_Controls.m_ImageActive->isChecked()) {this->m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ImageGeo);} //create the permanent registration filter m_PermanentRegistrationFilter = mitk::NavigationDataObjectVisualizationFilter::New(); //###################################################################### //first: initialize permanent registration of surface (always activated) //###################################################################### //connect filter to source m_PermanentRegistrationFilter->SetInput(0,this->m_ObjectmarkerNavigationData); //set representation object m_PermanentRegistrationFilter->SetRepresentationObject(0,this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()); //get the marker transform out of the navigation data mitk::NavigationData::Pointer T_Marker = m_ObjectmarkerNavigationData; //compute transform from object to marker (T_MarkerRel = T_Object * T_Marker^-1) mitk::NavigationData::Pointer T_MarkerRel = mitk::NavigationData::New(); T_MarkerRel->Compose(T_Object); T_MarkerRel->Compose(T_Marker->GetInverse()); m_T_MarkerRel = T_MarkerRel; m_PermanentRegistrationFilter->SetOffset(0,m_T_MarkerRel->GetAffineTransform3D()); //###################################################################### //second: initialize permanent registration of image (if activated) //###################################################################### if (m_Controls.m_ImageActive->isChecked() && (m_Controls.m_ImageComboBox->GetSelectedNode().IsNotNull())) { mitk::DataNode::Pointer imageNode = this->m_Controls.m_ImageComboBox->GetSelectedNode(); imageNode->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_LINEAR) ); m_PermanentRegistrationFilter->SetInput(1,this->m_ObjectmarkerNavigationData); m_PermanentRegistrationFilter->SetRepresentationObject(1,imageNode->GetData()); //for the image we can't use NavigationData objects as transforms because an image needs additional geometry information, e.g., spacing //thus we use mitk::AffineTransform3D objects //computer transform from image to marker (T_ImageRel = T_ImageGeo * T_MarkerRel) mitk::AffineTransform3D::Pointer T_ImageRel = mitk::AffineTransform3D::New(); T_ImageRel->SetIdentity(); T_ImageRel->Compose(m_T_ImageGeo); T_ImageRel->Compose(m_T_MarkerRel->GetAffineTransform3D()); m_PermanentRegistrationFilter->SetOffset(1,T_ImageRel); } //some general stuff m_PermanentRegistration = true; m_ObjectmarkerNavigationDataLastUpdate = mitk::NavigationData::New(); } else //if off = disable the permanent registration { //stop permanent registration m_PermanentRegistration = false; //restore old registration if(m_T_ObjectReg.IsNotNull()) {this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ObjectReg->GetAffineTransform3D());} if(m_T_ImageReg.IsNotNull()) {this->m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ImageReg);} //delete filter m_PermanentRegistrationFilter = nullptr; } } //############################################################################################### //############################################################################################### //####################### Slots of POINT SET RECORDING step ##################################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnPointSetRecording(bool record) { mitk::DataStorage* ds = this->GetDataStorage(); if(record) { if (m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedToolID() == -1) { QMessageBox::warning(nullptr, "Error", "No tool selected for point set recording!"); m_Controls.m_PointSetRecordCheckBox->setChecked(false); return; } m_PointSetRecordingNavigationData = m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedToolID()); //initialize point set mitk::DataNode::Pointer psRecND = ds->GetNamedNode("Recorded Points"); if(m_PSRecordingPointSet.IsNull() || psRecND.IsNull()) { m_PSRecordingPointSet = nullptr; m_PSRecordingPointSet = mitk::PointSet::New(); mitk::DataNode::Pointer dn = mitk::DataNode::New(); dn->SetName("Recorded Points"); dn->SetColor(0.,1.,0.); dn->SetData(m_PSRecordingPointSet); ds->Add(dn); } else { m_PSRecordingPointSet->Clear(); } m_PointSetRecording = true; } else { m_PointSetRecording = false; } } //############################################################################################### //############################################################################################### //####################### Slots of VIRTUAL CAMERA VIEW step ##################################### //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::OnVirtualCamera(bool on) { if (m_Controls.m_CameraViewSelection->GetSelectedToolID() == -1) { m_Controls.m_ActivateNeedleView->setChecked(false); QMessageBox::warning(nullptr, "Error", "No tool selected for camera view!"); return; } if(on) { m_VirtualView = mitk::CameraVisualization::New(); m_VirtualView->SetInput(m_Controls.m_CameraViewSelection->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_CameraViewSelection->GetSelectedToolID())); mitk::Vector3D viewDirection; viewDirection[0] = (int)(m_Controls.m_NeedleViewX->isChecked()); viewDirection[1] = (int)(m_Controls.m_NeedleViewY->isChecked()); viewDirection[2] = (int)(m_Controls.m_NeedleViewZ->isChecked()); if (m_Controls.m_NeedleViewInvert->isChecked()) viewDirection *= -1; m_VirtualView->SetDirectionOfProjectionInToolCoordinates(viewDirection); mitk::Vector3D viewUpVector; viewUpVector[0] = (int)(m_Controls.m_NeedleUpX->isChecked()); viewUpVector[1] = (int)(m_Controls.m_NeedleUpY->isChecked()); viewUpVector[2] = (int)(m_Controls.m_NeedleUpZ->isChecked()); if (m_Controls.m_NeedleUpInvert->isChecked()) viewUpVector *= -1; m_VirtualView->SetViewUpInToolCoordinates(viewUpVector); m_VirtualView->SetRenderer(this->GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderer()); //next line: better code when this plugin is migrated to mitk::abstractview //m_VirtualView->SetRenderer(mitk::BaseRenderer::GetInstance(this->GetRenderWindowPart()->GetRenderWindow("3d")->GetRenderWindow())); m_CameraView = true; //make pointer itself invisible m_Controls.m_CameraViewSelection->GetSelectedNavigationTool()->GetDataNode()->SetBoolProperty("visible",false); //disable UI elements m_Controls.m_ViewDirectionBox->setEnabled(false); m_Controls.m_ViewUpBox->setEnabled(false); } else { m_VirtualView = nullptr; m_CameraView = false; m_Controls.m_CameraViewSelection->GetSelectedNavigationTool()->GetDataNode()->SetBoolProperty("visible",true); m_Controls.m_ViewDirectionBox->setEnabled(true); m_Controls.m_ViewUpBox->setEnabled(true); } } //############################################################################################### //############################################################################################### //############################## some general UI methods, always needed ######################### //############################################################################################### //############################################################################################### QmitkIGTTrackingLabView::~QmitkIGTTrackingLabView() { if (m_Timer->isActive()) m_Timer->stop(); } void QmitkIGTTrackingLabView::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); this->CreateBundleWidgets(); this->CreateConnections(); } void QmitkIGTTrackingLabView::CreateBundleWidgets() { //initialize registration widget m_Controls.m_RegistrationWidget->HideStaticRegistrationRadioButton(true); m_Controls.m_RegistrationWidget->HideContinousRegistrationRadioButton(true); m_Controls.m_RegistrationWidget->HideUseICPRegistrationCheckbox(true); } void QmitkIGTTrackingLabView::CreateConnections() { //initialize timer m_Timer = new QTimer(this); //create connections connect(m_Timer, SIGNAL(timeout()), this, SLOT(UpdateTimer())); connect( m_Controls.m_UsePermanentRegistrationToggle, SIGNAL(toggled(bool)), this, SLOT(OnPermanentRegistration(bool)) ); connect( m_Controls.m_TrackingDeviceSelectionWidget, SIGNAL(NavigationDataSourceSelected(mitk::NavigationDataSource::Pointer)), this, SLOT(OnSetupNavigation()) ); connect( m_Controls.m_UseAsPointerButton, SIGNAL(clicked()), this, SLOT(OnInstrumentSelected()) ); connect( m_Controls.m_UseAsObjectmarkerButton, SIGNAL(clicked()), this, SLOT(OnObjectmarkerSelected()) ); connect( m_Controls.m_RegistrationWidget, SIGNAL(AddedTrackingFiducial()), this, SLOT(OnAddRegistrationTrackingFiducial()) ); connect( m_Controls.m_RegistrationWidget, SIGNAL(PerformFiducialRegistration()), this, SLOT(OnInitialRegistration()) ); connect( m_Controls.m_PointSetRecordCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnPointSetRecording(bool)) ); connect( m_Controls.m_ActivateNeedleView, SIGNAL(toggled(bool)), this, SLOT(OnVirtualCamera(bool)) ); //start timer m_Timer->start(30); //initialize Combo Boxes m_Controls.m_ObjectComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.m_ObjectComboBox->SetAutoSelectNewItems(false); m_Controls.m_ObjectComboBox->SetPredicate(mitk::NodePredicateDataType::New("Surface")); m_Controls.m_ImageComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.m_ImageComboBox->SetAutoSelectNewItems(false); m_Controls.m_ImageComboBox->SetPredicate(mitk::NodePredicateDataType::New("Image")); } void QmitkIGTTrackingLabView::SetFocus() { m_Controls.m_UseAsPointerButton->setFocus(); } //############################################################################################### //############################################################################################### //####################### some additional slots and help methods ################################ //####################### for cleaner code - not that important ################################ //####################### to understand the basic functions ################################ //############################################################################################### //############################################################################################### void QmitkIGTTrackingLabView::DestroyIGTPipeline() { if(m_Source.IsNotNull()) { m_Source->StopTracking(); m_Source->Disconnect(); m_Source = nullptr; } m_PermanentRegistrationFilter = nullptr; m_Visualizer = nullptr; m_VirtualView = nullptr; } bool QmitkIGTTrackingLabView::CheckRegistrationInitialization() { // a couple of variables which we need in this method std::string warningMessage = ""; bool initializationErrorDetected = false; mitk::PointSet::Pointer imageFiducials,trackerFiducials; // check some initialization stuff if (m_ImageFiducialsDataNode.IsNull() || m_TrackerFiducialsDataNode.IsNull()) { warningMessage = "Initialization not finished!"; MITK_WARN << warningMessage; QMessageBox::warning(nullptr, "Registration not possible", warningMessage.c_str()); return false; } else { imageFiducials = dynamic_cast(m_ImageFiducialsDataNode->GetData()); trackerFiducials = dynamic_cast(m_TrackerFiducialsDataNode->GetData()); } // now, do a lot of other checks... if (m_Controls.m_SurfaceActive->isChecked() && m_Controls.m_ObjectComboBox->GetSelectedNode().IsNull()) { warningMessage = "No surface selected for registration.\nRegistration is not possible"; initializationErrorDetected = true; } else if (m_Controls.m_ImageActive->isChecked() && m_Controls.m_ImageComboBox->GetSelectedNode().IsNull()) { warningMessage = "No image selected for registration.\nRegistration is not possible"; initializationErrorDetected = true; } else if (imageFiducials.IsNull() || trackerFiducials.IsNull()) { warningMessage = "Fiducial data objects not found. \n" "Please set 3 or more fiducials in the image and with the tracking system.\n\n" "Registration is not possible"; initializationErrorDetected = true; } else if ((imageFiducials->GetSize() < 3) || (trackerFiducials->GetSize() < 3) || (imageFiducials->GetSize() != trackerFiducials->GetSize())) { warningMessage = "Not enough fiducial pairs found. At least 3 fiducial must exist for the image and the tracking system respectively."; initializationErrorDetected = true; } // finaly: if an err was detected, give a warning and an error popup, then return false if(initializationErrorDetected) { MITK_WARN << warningMessage; QMessageBox::warning(nullptr, "Registration not possible", warningMessage.c_str()); return false; } //if no error was detected simply return true else {return true;} } bool QmitkIGTTrackingLabView::IsTransformDifferenceHigh(mitk::NavigationData::Pointer transformA, mitk::NavigationData::Pointer transformB, double euclideanDistanceThreshold, double angularDifferenceThreshold) { if(transformA.IsNull() || transformA.IsNull()) {return false;} mitk::Point3D posA,posB; posA = transformA->GetPosition(); posB = transformB->GetPosition(); if(posA.EuclideanDistanceTo(posB) > euclideanDistanceThreshold) {return true;} double returnValue; mitk::Quaternion rotA,rotB; rotA = transformA->GetOrientation(); rotB = transformB->GetOrientation(); itk::Vector point; //caution 5D-Tools: Vector must lie in the YZ-plane for a correct result. point[0] = 0.0; point[1] = 0.0; point[2] = 100000.0; rotA.normalize(); rotB.normalize(); itk::Matrix rotMatrixA; for(int i=0; i<3; i++) for(int j=0; j<3; j++) rotMatrixA[i][j] = rotA.rotation_matrix_transpose().transpose()[i][j]; itk::Matrix rotMatrixB; for(int i=0; i<3; i++) for(int j=0; j<3; j++) rotMatrixB[i][j] = rotB.rotation_matrix_transpose().transpose()[i][j]; itk::Vector pt1 = rotMatrixA * point; itk::Vector pt2 = rotMatrixB * point; returnValue = (pt1[0]*pt2[0]+pt1[1]*pt2[1]+pt1[2]*pt2[2]) / ( sqrt(pow(pt1[0],2.0)+pow(pt1[1],2.0)+pow(pt1[2],2.0)) * sqrt(pow(pt2[0],2.0)+pow(pt2[1],2.0)+pow(pt2[2],2.0))); returnValue = acos(returnValue); if(returnValue*57.3 > angularDifferenceThreshold){return true;} return false; } diff --git a/Plugins/org.mitk.gui.qt.igttracking/files.cmake b/Plugins/org.mitk.gui.qt.igttracking/files.cmake index 73f51d7e22..cbb54f9284 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/files.cmake +++ b/Plugins/org.mitk.gui.qt.igttracking/files.cmake @@ -1,58 +1,59 @@ set(SRC_CPP_FILES - + internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkMITKIGTNavigationToolManagerView.cpp QmitkMITKIGTTrackingToolboxView.cpp QmitkNavigationDataPlayerView.cpp IGTFiducialRegistration.cpp IGTNavigationToolCalibration.cpp ) set(UI_FILES src/internal/QmitkMITKIGTNavigationToolManagerViewControls.ui src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui src/internal/QmitkNavigationDataPlayerViewControls.ui src/internal/IGTNavigationToolCalibrationControls.ui src/internal/IGTFiducialRegistrationControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkMITKIGTNavigationToolManagerView.h src/internal/QmitkMITKIGTTrackingToolboxView.h + src/internal/QmitkMITKIGTTrackingToolboxViewWorker.h src/internal/QmitkNavigationDataPlayerView.h src/internal/IGTNavigationToolCalibration.h src/internal/IGTFiducialRegistration.h ) # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench set(CACHED_RESOURCE_FILES resources/iconTrackingDataPlayer.svg resources/iconTrackingRegistration.svg resources/iconTrackingToolbox.svg resources/iconTrackingToolCalibration.svg resources/iconTrackingToolManager.svg plugin.xml ) # list of Qt .qrc files which contain additional resources # specific to this plugin set(QRC_FILES resources/IGTNavigationToolCalibration.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp index 4b8e801196..3e16d95952 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp @@ -1,635 +1,735 @@ /*=================================================================== 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 // Blueberry #include #include // Qmitk #include "IGTNavigationToolCalibration.h" // mitk #include #include #include #include #include #include #include // Qt #include #include //vtk #include const std::string IGTNavigationToolCalibration::VIEW_ID = "org.mitk.views.igtnavigationtoolcalibration"; IGTNavigationToolCalibration::IGTNavigationToolCalibration() -{} +{ + m_ToolTransformationWidget = new QmitkInteractiveTransformationWidget(); +} IGTNavigationToolCalibration::~IGTNavigationToolCalibration() { //The following code is required due to a bug in the point list widget. //If this is removed, MITK crashes when closing the view: m_Controls.m_RegistrationLandmarkWidget->SetPointSetNode(nullptr); m_Controls.m_CalibrationLandmarkWidget->SetPointSetNode(nullptr); + + //clean up data storage + this->GetDataStorage()->Remove(m_ToolTipPointPreview); + + + delete m_ToolTransformationWidget; } void IGTNavigationToolCalibration::SetFocus() { } void IGTNavigationToolCalibration::OnToolCalibrationMethodChanged(int index) { //if pivot calibration (3) or manual(0) is chosen only calibration pointer is needed if (index == 0 || index == 3) { if (!CheckInitialization(false)) { return; } } else{ if (!CheckInitialization()) { return; } } UpdateManualToolTipCalibrationView(); m_Controls.m_CalibrationMethodsWidget->setCurrentIndex(index); m_IndexCurrentCalibrationMethod = index; } void IGTNavigationToolCalibration::CreateQtPartControl(QWidget *parent) { - //initialize manual tool editing widget - m_ManualToolTipEditWidget = new QmitkNavigationToolCreationAdvancedWidget(parent); - m_ManualToolTipEditWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - m_ManualToolTipEditWidget->setWindowTitle("Edit Tool Tip Manually"); - m_ManualToolTipEditWidget->setModal(false); - m_ManualToolTipEditWidget->SetDataStorage(this->GetDataStorage()); - m_TrackingTimer = new QTimer(this); // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); connect(m_Controls.m_SetToolToCalibrate, SIGNAL(clicked()), this, SLOT(SetToolToCalibrate())); connect(m_Controls.m_SetPointer, SIGNAL(clicked()), this, SLOT(SetCalibrationPointer())); connect(m_TrackingTimer, SIGNAL(timeout()), this, SLOT(UpdateTrackingTimer())); connect(m_Controls.m_AddLandmark, SIGNAL(clicked()), this, SLOT(AddLandmark())); connect(m_Controls.m_SaveCalibratedTool, SIGNAL(clicked()), this, SLOT(SaveCalibratedTool())); connect(m_Controls.m_AddPivotPose, SIGNAL(clicked()), this, SLOT(OnAddPivotPose())); connect(m_Controls.m_ComputePivot, SIGNAL(clicked()), this, SLOT(OnComputePivot())); connect(m_Controls.m_UseComputedPivotPoint, SIGNAL(clicked()), this, SLOT(OnUseComputedPivotPoint())); connect(m_Controls.m_StartEditTooltipManually, SIGNAL(clicked()), this, SLOT(OnStartManualToolTipCalibration())); - connect((QObject*)(m_ManualToolTipEditWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation())); - connect((QObject*)(m_ManualToolTipEditWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessManualTooltipEditDialogCloseRequest())); + connect(m_Controls.m_GetPositions, SIGNAL(clicked()), this, SLOT(OnGetPositions())); + connect(m_Controls.m_ToolAxis_X, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged())); + connect(m_Controls.m_ToolAxis_Y, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged())); + connect(m_Controls.m_ToolAxis_Z, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged())); + connect(m_Controls.m_CalibrateToolAxis, SIGNAL(clicked()), this, SLOT(OnCalibrateToolAxis())); + connect((QObject*)(m_ToolTransformationWidget), SIGNAL(EditToolTipFinished(mitk::AffineTransform3D::Pointer)), this, + SLOT(OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer))); connect(m_Controls.m_CalibrationMethodComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnToolCalibrationMethodChanged(int))); connect((QObject*)(m_Controls.m_RunCalibrationButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnRunSingleRefToolCalibrationClicked())); connect((QObject*)(m_Controls.m_CollectNavigationDataButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnLoginSingleRefToolNavigationDataClicked())); connect((QObject*)(m_Controls.m_SetNewToolTipPosButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnSetNewToolTipPosButtonClicked())); m_IDToolToCalibrate = -1; m_IDCalibrationPointer = -1; m_IndexCurrentCalibrationMethod = -1; m_OnLoginSingleRefToolNavigationDataClicked = false; m_NumberOfNavigationDataCounter = 0; m_NumberOfNavigationData = -1; //for pivot calibration m_OnAddPivotPoseClicked = false; PivotCount = 0; m_PivotPoses = std::vector(); m_CalibrationLandmarks = mitk::PointSet::New(); m_CalibrationLandmarksNode = mitk::DataNode::New(); m_CalibrationLandmarksNode->SetData(m_CalibrationLandmarks); m_Controls.m_CalibrationLandmarkWidget->SetPointSetNode(m_CalibrationLandmarksNode); m_RegistrationLandmarks = mitk::PointSet::New(); m_RegistrationLandmarksNode = mitk::DataNode::New(); m_RegistrationLandmarksNode->SetData(m_RegistrationLandmarks); m_Controls.m_RegistrationLandmarkWidget->SetPointSetNode(m_RegistrationLandmarksNode); m_ToolSurfaceInToolCoordinatesDataNode = mitk::DataNode::New(); m_ToolSurfaceInToolCoordinatesDataNode->SetName("ToolSurface(ToolCoordinates)"); m_LoggedNavigationDataDifferences = std::vector< mitk::NavigationData::Pointer >(); } void IGTNavigationToolCalibration::OnRunSingleRefToolCalibrationClicked() { if (!CheckInitialization()) { return; } mitk::NavigationData::Pointer ToolTipTransform = mitk::NavigationData::New(); if (m_Controls.m_CalibratePosition->isChecked()) { //1: Compute mean translational offset vector m_ResultOffsetVector.Fill(0); for (std::vector::iterator vecIter = m_LoggedNavigationDataOffsets.begin(); vecIter != m_LoggedNavigationDataOffsets.end(); vecIter++) { m_ResultOffsetVector[0] = m_ResultOffsetVector[0] + (*vecIter)[0]; m_ResultOffsetVector[1] = m_ResultOffsetVector[1] + (*vecIter)[1]; m_ResultOffsetVector[2] = m_ResultOffsetVector[2] + (*vecIter)[2]; } m_ResultOffsetVector[0] = m_ResultOffsetVector[0] / m_LoggedNavigationDataOffsets.size(); m_ResultOffsetVector[1] = m_ResultOffsetVector[1] / m_LoggedNavigationDataOffsets.size(); m_ResultOffsetVector[2] = m_ResultOffsetVector[2] / m_LoggedNavigationDataOffsets.size(); this->m_Controls.m_ResultOfCalibration->setText( QString("x: ") + QString(QString::number(m_ResultOffsetVector[0], 103, 3)) + QString("; y: ") + (QString::number(m_ResultOffsetVector[1], 103, 3)) + QString("; z: ") + (QString::number(m_ResultOffsetVector[2], 103, 3))); ToolTipTransform->SetPosition(m_ResultOffsetVector); } if (m_Controls.m_CalibrateOrientation->isChecked()) { //2: Compute mean orientation mitk::Quaternion meanOrientation; std::vector allOrientations = std::vector (); for (std::size_t i = 0; i < m_LoggedNavigationDataDifferences.size(); i++) { allOrientations.push_back(m_LoggedNavigationDataDifferences.at(i)->GetOrientation()); } meanOrientation = mitk::QuaternionAveraging::CalcAverage(allOrientations); this->m_Controls.m_ResultOfCalibrationOrientation->setText( QString("qx: ") + QString(QString::number(meanOrientation.x(), 103, 3)) + QString("; qy: ") + (QString::number(meanOrientation.y(), 103, 3)) + QString("; qz: ") + (QString::number(meanOrientation.z(), 103, 3)) + QString("; qr: ") + (QString::number(meanOrientation.r(), 103, 3))); ToolTipTransform->SetOrientation(meanOrientation); } MITK_INFO << "Computed calibration: "; MITK_INFO << "Translation Vector: " << ToolTipTransform->GetPosition(); MITK_INFO << "Quaternion: (" << ToolTipTransform->GetOrientation() << ")"; MITK_INFO << "Euler Angles [rad]: (" << ToolTipTransform->GetOrientation().rotation_euler_angles() << ")"; MITK_INFO << "Matrix:"; vnl_matrix_fixed rotMatrix = ToolTipTransform->GetOrientation().rotation_matrix_transpose(); MITK_INFO << rotMatrix[0][0] << " " << rotMatrix[0][1] << " " << rotMatrix[0][2] << std::endl; MITK_INFO << rotMatrix[1][0] << " " << rotMatrix[1][1] << " " << rotMatrix[1][2] << std::endl; MITK_INFO << rotMatrix[2][0] << " " << rotMatrix[2][1] << " " << rotMatrix[2][2] << std::endl; //3: write everything into the final tool tip transform and save it as member (it will be written to the tool later on) mitk::NavigationData::Pointer ToolTipInTrackingCoordinates = mitk::NavigationData::New(); ToolTipInTrackingCoordinates->Compose(ToolTipTransform); ToolTipInTrackingCoordinates->Compose(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); ShowToolTipPreview(ToolTipInTrackingCoordinates); m_Controls.m_SetNewToolTipPosButton->setEnabled(true); m_ComputedToolTipTransformation = ToolTipTransform; } void IGTNavigationToolCalibration::OnLoginSingleRefToolNavigationDataClicked() { + if (!CheckInitialization()) { return; } + + //reset old data + m_LoggedNavigationDataOffsets.clear(); + m_LoggedNavigationDataDifferences.clear(); + m_OnLoginSingleRefToolNavigationDataClicked = true; m_Controls.m_CollectNavigationDataButton->setEnabled(false); m_NumberOfNavigationData = m_Controls.m_NumberOfNavigationDataToCollect->value(); MITK_INFO << "Collecting " << m_NumberOfNavigationData << " NavigationData ... " << endl; } void IGTNavigationToolCalibration::LoginSingleRefToolNavigationData() { if (!CheckInitialization()) { return; } if (m_NumberOfNavigationDataCounter < m_NumberOfNavigationData) { //update label text QString labelText = "Collecting Data: " + QString::number(m_NumberOfNavigationDataCounter); m_Controls.m_CollectionStatus->setText(labelText); mitk::NavigationData::Pointer referenceTool = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer); mitk::NavigationData::Pointer toolToCalibrate = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); //compute difference: // differenceND = toolToCalibrate^-1 * referenceTool mitk::NavigationData::Pointer differenceND = mitk::NavigationData::New(); differenceND->Compose(referenceTool); differenceND->Compose(toolToCalibrate->GetInverse()); //inverse mode... if (m_Controls.m_InvertQuaternions->isChecked()) { // negate identity matrix to directly show parameters that will set up in NDI 6D Software Architect differenceND = differenceND->GetInverse(); } //save difference in member m_LoggedNavigationDataOffsets.push_back(differenceND->GetPosition()); m_LoggedNavigationDataDifferences.push_back(differenceND); m_NumberOfNavigationDataCounter++; } if (m_NumberOfNavigationDataCounter == m_NumberOfNavigationData) { m_NumberOfNavigationDataCounter = 0; m_OnLoginSingleRefToolNavigationDataClicked = false; m_Controls.m_CollectNavigationDataButton->setEnabled(true); m_Controls.m_RunCalibrationButton->setEnabled(true); MITK_INFO << "Collecting " << m_NumberOfNavigationData << " NavigationData ... Finished" << endl; QString labelText = "Collected " + QString::number(m_NumberOfNavigationData) + " data samples!"; m_Controls.m_CollectionStatus->setText(labelText); } } void IGTNavigationToolCalibration::OnSetNewToolTipPosButtonClicked() { ApplyToolTipTransform(m_ComputedToolTipTransformation); RemoveToolTipPreview(); } void IGTNavigationToolCalibration::ClearOldPivot() { mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(); this->ApplyToolTipTransform(tempND); UpdateManualToolTipCalibrationView(); - m_ManualToolTipEditWidget->hide(); + //m_ManualToolTipEditWidget->hide(); //TODO this->GetDataStorage()->Remove(m_ToolSurfaceInToolCoordinatesDataNode); } void IGTNavigationToolCalibration::OnAddPivotPose() { ClearOldPivot(); //When the collect Poses Button is Clicked m_OnAddPivotPoseClicked = true; m_NumberOfNavigationData = m_Controls.m_PosesToCollect->value(); } void IGTNavigationToolCalibration::AddPivotPose() { //Save the poses to be used in computation if (PivotCount < m_NumberOfNavigationData) { mitk::NavigationData::Pointer currentPose = mitk::NavigationData::New(); currentPose->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate)); m_PivotPoses.push_back(currentPose); m_Controls.m_PoseNumber->setText(QString::number(m_PivotPoses.size())); PivotCount++; } if (PivotCount == m_NumberOfNavigationData) { m_OnAddPivotPoseClicked = false; } } void IGTNavigationToolCalibration::OnComputePivot() { mitk::PivotCalibration::Pointer myPivotCalibration = mitk::PivotCalibration::New(); for (std::size_t i = 0; i < this->m_PivotPoses.size(); i++) { myPivotCalibration->AddNavigationData(m_PivotPoses.at(i)); } QString resultString; if (myPivotCalibration->ComputePivotResult()) { mitk::NavigationData::Pointer markerTransformationTrackingCoordinates = m_PivotPoses.at(0); //Get computed pivot transfromation in tool coordinates mitk::NavigationData::Pointer ToolTipToTool = mitk::NavigationData::New(); ToolTipToTool->SetPosition(myPivotCalibration->GetResultPivotPoint()); ToolTipToTool->SetOrientation(myPivotCalibration->GetResultPivotRotation()); mitk::NavigationData::Pointer TrackerToTool = mitk::NavigationData::New(); TrackerToTool->SetOrientation(markerTransformationTrackingCoordinates->GetOrientation()); TrackerToTool->SetPosition(markerTransformationTrackingCoordinates->GetPosition()); TrackerToTool->Compose(ToolTipToTool); // Compute pivot point in relation to marker transformation for preview mitk::NavigationData::Pointer ToolTipToTracker = mitk::NavigationData::New(); ToolTipToTracker->Compose(ToolTipToTool); ToolTipToTracker->Compose(markerTransformationTrackingCoordinates); //add the preview node to the data storage ShowToolTipPreview(ToolTipToTracker); //parse result string resultString = QString("Pivot computation succeeded!\n") + QString("RMS Error: ") + QString::number(myPivotCalibration->GetResultRMSError()) + QString("\n") + QString("Pivot Point: ") + QString::number(myPivotCalibration->GetResultPivotPoint()[0]) + ";" + QString::number(myPivotCalibration->GetResultPivotPoint()[1]) + ";" + QString::number(myPivotCalibration->GetResultPivotPoint()[2]) + QString("\n") + QString("Pivot Rotation: ") + QString::number(myPivotCalibration->GetResultPivotRotation()[0]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[1]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[2]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[3]) + QString("\n"); //finally: save results to member variable m_ComputedToolTipTransformation = ToolTipToTool; //enable button to use the computed point with the tool m_Controls.m_UseComputedPivotPoint->setEnabled(true); } else { resultString = "Pivot computation failed!"; } MITK_INFO << resultString.toStdString().c_str(); m_Controls.m_ResultText->setText(resultString); } void IGTNavigationToolCalibration::UpdatePivotCount() { PivotCount = 0; while (!m_PivotPoses.empty()) { m_PivotPoses.pop_back(); } m_Controls.m_PoseNumber->setText(QString::number(PivotCount)); } void IGTNavigationToolCalibration::OnUseComputedPivotPoint() { RemoveToolTipPreview(); QString resultString = QString("Pivoted tool tip transformation was written to the tool ") + m_ToolToCalibrate->GetToolName().c_str(); ApplyToolTipTransform(m_ComputedToolTipTransformation, resultString.toStdString()); m_Controls.m_ResultText->setText(resultString); UpdatePivotCount(); } void IGTNavigationToolCalibration::ApplyToolTipTransform(mitk::NavigationData::Pointer ToolTipTransformInToolCoordinates, std::string message) { if (!CheckInitialization(false)) { return; } //Update tool in tool storage m_ToolToCalibrate->SetToolTipPosition(ToolTipTransformInToolCoordinates->GetPosition()); m_ToolToCalibrate->SetToolTipOrientation(ToolTipTransformInToolCoordinates->GetOrientation()); //And also update tracking device, so the transform is directly used mitk::TrackingDeviceSource::Pointer trackingDeviceSource; try { trackingDeviceSource = dynamic_cast(m_NavigationDataSourceOfToolToCalibrate.GetPointer()); mitk::TrackingTool::Pointer TrackingToolToCalibrate = trackingDeviceSource->GetTrackingDevice()->GetTool(m_IDToolToCalibrate); TrackingToolToCalibrate->SetToolTip(ToolTipTransformInToolCoordinates->GetPosition(), ToolTipTransformInToolCoordinates->GetOrientation()); } catch (std::exception& e) { MITK_ERROR << "Error while trying to set the tool tip to the running tracking device. Aborting! (" << e.what() << ")"; } MITK_INFO << message; } void IGTNavigationToolCalibration::ShowToolTipPreview(mitk::NavigationData::Pointer ToolTipInTrackingCoordinates) { - mitk::DataNode::Pointer m_ToolTipPointPreview = mitk::DataNode::New(); - m_ToolTipPointPreview->SetName("Modified Tool Tip Preview"); - mitk::Color blue; - blue.SetBlue(1); - m_ToolTipPointPreview->SetColor(blue); - mitk::Surface::Pointer mySphere = mitk::Surface::New(); - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(3.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - mySphere->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - m_ToolTipPointPreview->SetData(mySphere); + if(m_ToolTipPointPreview.IsNull()) + { + m_ToolTipPointPreview = mitk::DataNode::New(); + m_ToolTipPointPreview->SetName("Modified Tool Tip Preview"); + mitk::Color blue; + blue.SetBlue(1); + m_ToolTipPointPreview->SetColor(blue); + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(3.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + m_ToolTipPointPreview->SetData(mySphere); + + this->GetDataStorage()->Add(m_ToolTipPointPreview); + } m_ToolTipPointPreview->GetData()->GetGeometry()->SetIndexToWorldTransform(ToolTipInTrackingCoordinates->GetAffineTransform3D()); - this->GetDataStorage()->Add(m_ToolTipPointPreview); } void IGTNavigationToolCalibration::RemoveToolTipPreview() { this->GetDataStorage()->Remove(m_ToolTipPointPreview.GetPointer()); } void IGTNavigationToolCalibration::UpdateManualToolTipCalibrationView() { if (m_ToolToCalibrate.IsNull()) { return; } //parse human readable transformation data and display it std::stringstream translation; std::stringstream orientation; translation << m_ToolToCalibrate->GetToolTipPosition(); orientation << "Quaternion: (" << m_ToolToCalibrate->GetToolTipOrientation() << ")" << std::endl; orientation << std::endl; orientation << "Euler Angles [rad]: (" << m_ToolToCalibrate->GetToolTipOrientation().rotation_euler_angles() << ")" << std::endl; orientation << std::endl; orientation << "Matrix:" << std::endl; vnl_matrix_fixed rotMatrix = m_ToolToCalibrate->GetToolTipOrientation().rotation_matrix_transpose(); orientation << rotMatrix[0][0] << " " << rotMatrix[0][1] << " " << rotMatrix[0][2] << std::endl; orientation << rotMatrix[1][0] << " " << rotMatrix[1][1] << " " << rotMatrix[1][2] << std::endl; orientation << rotMatrix[2][0] << " " << rotMatrix[2][1] << " " << rotMatrix[2][2] << std::endl; m_Controls.m_ManualCurrentTranslation->setText(translation.str().c_str()); m_Controls.m_ManualCurrentOrientation->setPlainText(orientation.str().c_str()); } void IGTNavigationToolCalibration::OnStartManualToolTipCalibration() { if (!CheckInitialization(false)) { return; } - m_ManualToolTipEditWidget->SetToolTipSurface(false, m_ToolToCalibrate->GetDataNode()); - m_ManualToolTipEditWidget->show(); - m_ManualToolTipEditWidget->SetDefaultTooltip(m_ToolToCalibrate->GetToolTipTransform()); - m_ManualToolTipEditWidget->ReInitialize(); + + m_ToolTransformationWidget->SetToolToEdit(m_ToolToCalibrate); + m_ToolTransformationWidget->SetDefaultOffset(m_ToolToCalibrate->GetToolTipPosition()); + m_ToolTransformationWidget->SetDefaultRotation(m_ToolToCalibrate->GetToolTipOrientation()); + + m_ToolTransformationWidget->open(); +} + +void IGTNavigationToolCalibration::OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip) +{ + //This function is called, when the toolTipEdit view is closed. + //if user pressed cancle, nullptr is returned. Do nothing. Else, set values. + if (toolTip) + { + mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(toolTip);//Convert to Navigation data for simple transversion to quaternion + QString resultString = QString("Manual edited values are written to ") + m_ToolToCalibrate->GetToolName().c_str(); + ApplyToolTipTransform(tempND, resultString.toStdString()); + m_Controls.m_ResultText->setText(resultString); + } + + UpdateManualToolTipCalibrationView(); } -void IGTNavigationToolCalibration::OnRetrieveDataForManualTooltipManipulation() +void IGTNavigationToolCalibration::OnGetPositions() { - this->GetDataStorage()->Add(m_ToolSurfaceInToolCoordinatesDataNode); - m_ManualToolTipEditWidget->SetToolTipSurface(false, m_ToolSurfaceInToolCoordinatesDataNode); + if (!CheckInitialization(true)) { return; } + + //Navigation Data from Tool which should be calibrated + if (!m_AxisCalibration_ToolToCalibrate) + m_AxisCalibration_ToolToCalibrate = mitk::NavigationData::New(); + m_AxisCalibration_ToolToCalibrate->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate)); + + //Navigation Data from calibration pointer tool + if (!m_AxisCalibration_NavDataCalibratingTool) + m_AxisCalibration_NavDataCalibratingTool = mitk::NavigationData::New(); + m_AxisCalibration_NavDataCalibratingTool->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDCalibrationPointer)); + + MITK_DEBUG << "Positions for tool axis calibration:"; + MITK_DEBUG << " ToolTip: " << m_AxisCalibration_ToolToCalibrate->GetPosition() << ","; + MITK_DEBUG << " Rotation: \n" << m_AxisCalibration_ToolToCalibrate->GetRotationMatrix(); + MITK_DEBUG << " End of the tool: " << m_AxisCalibration_NavDataCalibratingTool->GetPosition(); + + QString _label = "Position recorded: " + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[0], 'f', 1) + ", " + + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[1], 'f', 1) + ", " + + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[2], 'f', 1); + m_Controls.m_ToolAxisPositionLabel->setText(_label); } -void IGTNavigationToolCalibration::OnProcessManualTooltipEditDialogCloseRequest() +void IGTNavigationToolCalibration::OnCalibrateToolAxis() { - mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_ManualToolTipEditWidget->GetManipulatedToolTip()); - this->ApplyToolTipTransform(tempND); - UpdateManualToolTipCalibrationView(); - m_ManualToolTipEditWidget->hide(); - this->GetDataStorage()->Remove(m_ToolSurfaceInToolCoordinatesDataNode); + if (!m_AxisCalibration_ToolToCalibrate || !m_AxisCalibration_NavDataCalibratingTool) + { + MITK_ERROR << "Please record position first."; + return; + } + + //Calculate the tool tip + //here is an explanation, what is happening here: + /* + The axis is equal to the (tool tip) minus the (end of the tool) in tool coordinates of the tool which should be calibrated. + The tool tip in tool coordinates is zero (definition of the tip). + The end of the tool is recorded by the calibration pointer's position and is transformed using the inverse of the tool which should be calibrated. + Normalize it. + */ + m_CalibratedToolAxis = -m_AxisCalibration_ToolToCalibrate->GetInverse()->TransformPoint(m_AxisCalibration_NavDataCalibratingTool->GetPosition()).GetVectorFromOrigin(); + MITK_DEBUG << "Tool Endpoint in Tool coordinates: " << m_CalibratedToolAxis; + m_CalibratedToolAxis.Normalize(); + MITK_DEBUG << "Tool Axis: " << m_CalibratedToolAxis; + + m_ToolToCalibrate->SetToolAxis(m_CalibratedToolAxis); + + //Update GUI + QString calibratedToolAxisString = "Tool Axis: " + QString::number(m_CalibratedToolAxis.GetElement(0), 'f', 3) + ", " + + QString::number(m_CalibratedToolAxis.GetElement(1), 'f', 3) + ", " + QString::number(m_CalibratedToolAxis.GetElement(2), 'f', 3); + m_Controls.m_ToolAxisCalibrationLabel->setText(calibratedToolAxisString); + + //Block QT signals, we don't want to emit SpinboxChanged on the first value to overwrite the next ones + m_Controls.m_ToolAxis_X->blockSignals(true); m_Controls.m_ToolAxis_Y->blockSignals(true); m_Controls.m_ToolAxis_Z->blockSignals(true); + m_Controls.m_ToolAxis_X->setValue(m_CalibratedToolAxis[0]); + m_Controls.m_ToolAxis_Y->setValue(m_CalibratedToolAxis[1]); + m_Controls.m_ToolAxis_Z->setValue(m_CalibratedToolAxis[2]); + m_Controls.m_ToolAxis_X->blockSignals(false); m_Controls.m_ToolAxis_Y->blockSignals(false); m_Controls.m_ToolAxis_Z->blockSignals(false); +} + +void IGTNavigationToolCalibration::OnToolAxisSpinboxChanged() +{ + m_CalibratedToolAxis.SetElement(0, m_Controls.m_ToolAxis_X->value()); + m_CalibratedToolAxis.SetElement(1, m_Controls.m_ToolAxis_Y->value()); + m_CalibratedToolAxis.SetElement(2, m_Controls.m_ToolAxis_Z->value()); + m_ToolToCalibrate->SetToolAxis(m_CalibratedToolAxis); + MITK_INFO << "Tool axis changed to " << m_CalibratedToolAxis; } void IGTNavigationToolCalibration::SetToolToCalibrate() { m_IDToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedToolID(); - m_ToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationTool(); if (m_IDToolToCalibrate == -1) //no valid tool to calibrate { m_Controls.m_CalToolLabel->setText(""); m_Controls.m_StatusWidgetToolToCalibrate->RemoveStatusLabels(); m_TrackingTimer->stop(); } else { + m_ToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationTool(); m_NavigationDataSourceOfToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource(); m_Controls.m_CalToolLabel->setText(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)->GetName()); //initialize widget m_Controls.m_StatusWidgetToolToCalibrate->RemoveStatusLabels(); m_Controls.m_StatusWidgetToolToCalibrate->SetShowPositions(true); m_Controls.m_StatusWidgetToolToCalibrate->SetTextAlignment(Qt::AlignLeft); m_Controls.m_StatusWidgetToolToCalibrate->AddNavigationData(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); m_Controls.m_StatusWidgetToolToCalibrate->ShowStatusLabels(); //initialize manual tool tip calibration view UpdateManualToolTipCalibrationView(); //save tool surface in tool coordinates for further editing mitk::Surface::Pointer ToolSurface = dynamic_cast(m_ToolToCalibrate->GetDataNode()->GetData())->Clone(); m_ToolSurfaceInToolCoordinatesDataNode->SetData(ToolSurface); m_ToolSurfaceInToolCoordinatesDataNode->GetData()->GetGeometry()->SetIdentity(); + + //Set the default needle axis + m_CalibratedToolAxis = m_ToolToCalibrate->GetToolAxis().GetVectorFromOrigin(); + //Block QT signals, we don't want to emit SpinboxChanged on the first value to overwrite the next ones + m_Controls.m_ToolAxis_X->blockSignals(true); m_Controls.m_ToolAxis_Y->blockSignals(true); m_Controls.m_ToolAxis_Z->blockSignals(true); + m_Controls.m_ToolAxis_X->setValue(m_CalibratedToolAxis[0]); + m_Controls.m_ToolAxis_Y->setValue(m_CalibratedToolAxis[1]); + m_Controls.m_ToolAxis_Z->setValue(m_CalibratedToolAxis[2]); + m_Controls.m_ToolAxis_X->blockSignals(false); m_Controls.m_ToolAxis_Y->blockSignals(false); m_Controls.m_ToolAxis_Z->blockSignals(false); + + UpdateManualToolTipCalibrationView(); + //start updating timer for status widgets, etc. if (!m_TrackingTimer->isActive()) m_TrackingTimer->start(100); } } void IGTNavigationToolCalibration::SetCalibrationPointer() { m_IDCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedToolID(); - m_NavigationDataSourceOfCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource(); if (m_IDCalibrationPointer == -1) { m_Controls.m_PointerLabel->setText(""); m_Controls.m_StatusWidgetCalibrationPointer->RemoveStatusLabels(); m_TrackingTimer->stop(); } else { + m_NavigationDataSourceOfCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource(); m_Controls.m_PointerLabel->setText(m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)->GetName()); //initialize widget m_Controls.m_StatusWidgetCalibrationPointer->RemoveStatusLabels(); m_Controls.m_StatusWidgetCalibrationPointer->SetShowPositions(true); m_Controls.m_StatusWidgetCalibrationPointer->SetTextAlignment(Qt::AlignLeft); m_Controls.m_StatusWidgetCalibrationPointer->AddNavigationData(m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)); m_Controls.m_StatusWidgetCalibrationPointer->ShowStatusLabels(); if (!m_TrackingTimer->isActive()) m_TrackingTimer->start(100); } } void IGTNavigationToolCalibration::UpdateOffsetCoordinates() { if (m_NavigationDataSourceOfCalibrationPointer.IsNull() || m_NavigationDataSourceOfToolToCalibrate.IsNull()) { return; } mitk::NavigationData::Pointer referenceToolND = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer); mitk::NavigationData::Pointer toolToCalibrateND = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); if (referenceToolND->IsDataValid() && toolToCalibrateND->IsDataValid()) { //computation: difference between both tools (in tool coordinates) //differenceND = toolToCalibrateND^-1 * referenceToolND mitk::NavigationData::Pointer differenceND = mitk::NavigationData::New(); differenceND->Compose(referenceToolND); differenceND->Compose(toolToCalibrateND->GetInverse()); //display this orientation in the UI m_Controls.m_OffsetCoordinates->setText( QString("x: ") + QString(QString::number(differenceND->GetPosition()[0], 103, 3)) + QString("; y: ") + (QString::number(differenceND->GetPosition()[1], 103, 3)) + QString("; z: ") + (QString::number(differenceND->GetPosition()[2], 103, 3))); m_Controls.m_OrientationOffsetCoordinates->setText( QString("qx: ") + QString(QString::number(differenceND->GetOrientation().x(), 103, 3)) + QString("; qy: ") + (QString::number(differenceND->GetOrientation().y(), 103, 3)) + QString("; qz: ") + (QString::number(differenceND->GetOrientation().z(), 103, 3)) + QString("; qr: ") + (QString::number(differenceND->GetOrientation().r(), 103, 3))); //also update preview if active if (m_ToolTipPointPreview.IsNotNull()) //NOT WORKING! TODO: fix or remove! { mitk::NavigationData::Pointer ToolTipTransform = mitk::NavigationData::New(); ToolTipTransform->SetPosition(m_ResultOffsetVector); mitk::NavigationData::Pointer ToolTipInTrackingCoordinates = mitk::NavigationData::New(); //maybe store as for better peformance... ToolTipInTrackingCoordinates->Compose(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); ToolTipInTrackingCoordinates->Compose(ToolTipTransform); m_ToolTipPointPreview->GetData()->GetGeometry()->SetIndexToWorldTransform(ToolTipInTrackingCoordinates->GetAffineTransform3D()); } } } void IGTNavigationToolCalibration::UpdateTrackingTimer() { m_Controls.m_StatusWidgetToolToCalibrate->Refresh(); m_Controls.m_StatusWidgetCalibrationPointer->Refresh(); if (m_OnLoginSingleRefToolNavigationDataClicked) LoginSingleRefToolNavigationData(); if (m_OnAddPivotPoseClicked) AddPivotPose(); // 1 == Single Reference Calibration Method if (m_IndexCurrentCalibrationMethod == 1) UpdateOffsetCoordinates(); } void IGTNavigationToolCalibration::AddLandmark() { if (!CheckInitialization()) { return; } mitk::NavigationData::Pointer navDataTool = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); mitk::Point3D landmark = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)->GetPosition(); //convert to itk transform itk::Vector translation; for (int k = 0; k < 3; k++) translation[k] = navDataTool->GetPosition()[k]; itk::Matrix rotation; for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) rotation[k][l] = navDataTool->GetOrientation().rotation_matrix_transpose()[k][l]; rotation = rotation.GetTranspose(); itk::Vector landmarkItk; landmarkItk[0] = landmark[0]; landmarkItk[1] = landmark[1]; landmarkItk[2] = landmark[2]; //compute landmark in tool coordinates itk::Matrix rotationInverse; for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) rotationInverse[k][l] = rotation.GetInverse()[k][l]; landmarkItk = rotationInverse * (landmarkItk - translation); //convert back and add landmark to pointset landmark[0] = landmarkItk[0]; landmark[1] = landmarkItk[1]; landmark[2] = landmarkItk[2]; m_RegistrationLandmarks->InsertPoint(m_RegistrationLandmarks->GetSize(), landmark); } void IGTNavigationToolCalibration::SaveCalibratedTool() { if (m_ToolToCalibrate.IsNotNull()) { mitk::NavigationTool::Pointer calibratedTool = m_ToolToCalibrate; calibratedTool->SetToolCalibrationLandmarks(this->m_CalibrationLandmarks); calibratedTool->SetToolRegistrationLandmarks(this->m_RegistrationLandmarks); mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = QFileDialog::getSaveFileName(nullptr,tr("Save Navigation Tool"), "/", "*.IGTTool").toUtf8().data(); filename.append(".IGTTool"); if (filename == "") return; if (myWriter->DoWrite(filename, calibratedTool)) MITK_INFO << "Saved calibrated tool to file " << filename; else MITK_WARN << "Can't write tool to file " << filename; } else { MITK_ERROR << "Did not find navigation tool storage of calibrated tool, aborting!"; } } bool IGTNavigationToolCalibration::CheckInitialization(bool CalibrationPointerRequired) { if ((m_IDToolToCalibrate == -1) || ((CalibrationPointerRequired) && (m_IDCalibrationPointer == -1) ) ) { QMessageBox msgBox; msgBox.setText("Tool to calibrate and/or calibration pointer not initialized, cannot proceed!"); msgBox.exec(); return false; } else { return true; } } diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h index ae582db713..741488fc68 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h @@ -1,135 +1,143 @@ /*=================================================================== 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 IGTNavigationToolCalibration_h #define IGTNavigationToolCalibration_h #include #include #include -#include + +#include "QmitkInteractiveTransformationWidget.h" + #include "ui_IGTNavigationToolCalibrationControls.h" #include //QT headers #include /*! \brief IGTNavigationToolCalibration \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \ingroup ${plugin_target}_internal */ class IGTNavigationToolCalibration : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: IGTNavigationToolCalibration(); virtual ~IGTNavigationToolCalibration(); static const std::string VIEW_ID; virtual void CreateQtPartControl(QWidget *parent); protected slots: void OnAddPivotPose(); void OnComputePivot(); void OnUseComputedPivotPoint(); void SetToolToCalibrate(); void SetCalibrationPointer(); void UpdateTrackingTimer(); void AddLandmark(); void SaveCalibratedTool(); void OnToolCalibrationMethodChanged(int index); void OnStartManualToolTipCalibration(); - void OnRetrieveDataForManualTooltipManipulation(); - void OnProcessManualTooltipEditDialogCloseRequest(); void OnRunSingleRefToolCalibrationClicked(); void OnLoginSingleRefToolNavigationDataClicked(); void OnSetNewToolTipPosButtonClicked(); - + void OnGetPositions(); + void OnCalibrateToolAxis(); + void OnToolAxisSpinboxChanged(); + void OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip); protected: virtual void SetFocus(); void UpdateOffsetCoordinates(); int m_IndexCurrentCalibrationMethod; Ui::IGTNavigationToolCalibrationControls m_Controls; //some general members mitk::NavigationTool::Pointer m_ToolToCalibrate; //<<< tool that will be calibrated int m_IDToolToCalibrate; //<<< id of tool that will be calibrated (of the navigation data source) mitk::NavigationDataSource::Pointer m_NavigationDataSourceOfToolToCalibrate; //<<< navigation data source of the tool that will be calibrated mitk::NavigationDataSource::Pointer m_NavigationDataSourceOfCalibrationPointer; //<<< navigation data source of the calibration pointer mitk::DataNode::Pointer m_ToolSurfaceInToolCoordinatesDataNode; //<<< holds the tool surface in tool coordinates (for preview purposes) int m_IDCalibrationPointer; //<<< id of the calibration pointer (of the corresponding navigation data source) QTimer* m_TrackingTimer; //<<< tracking timer that updates the status widgets void ApplyToolTipTransform(mitk::NavigationData::Pointer ToolTipTransformInToolCoordinates, std::string message = "Tool was updated with the calibrated tool tip!"); //<<< applys the given tool tip transform to the tool to calibrate bool CheckInitialization(bool CalibrationPointerRequired = true); //<<< checks if the tool to calibrate and (if required) the calibration pointer is initialized. Displays a warning and returns false if not. mitk::NavigationData::Pointer m_ComputedToolTipTransformation; //<<< holds the new tooltip transformation after it was computed to write it into the tool later // members and helper methods for pivot tool calibration std::vector m_PivotPoses; void AddPivotPose(); void ClearOldPivot(); void UpdatePivotCount(); bool m_OnAddPivotPoseClicked; int PivotCount; // members and helper methods for manual tool calibration void UpdateManualToolTipCalibrationView(); - QmitkNavigationToolCreationAdvancedWidget* m_ManualToolTipEditWidget; + QmitkInteractiveTransformationWidget* m_ToolTransformationWidget; // members and helper methods for single reference tool calibration void LoginSingleRefToolNavigationData(); std::vector< mitk::Point3D > m_LoggedNavigationDataOffsets; std::vector< mitk::NavigationData::Pointer > m_LoggedNavigationDataDifferences; bool m_OnLoginSingleRefToolNavigationDataClicked; int m_NumberOfNavigationData; int m_NumberOfNavigationDataCounter; mitk::Point3D m_ResultOffsetVector; // members and helper methods for tool tip preview mitk::DataNode::Pointer m_ToolTipPointPreview; //<<< Data node of the tool tip preview void ShowToolTipPreview(mitk::NavigationData::Pointer ToolTipInTrackingCoordinates); //<<< Adds a preview of the tool tip into the data storage void RemoveToolTipPreview(); //<<< Removes the preview // members for the tool landmark calibration mitk::PointSet::Pointer m_CalibrationLandmarks; mitk::DataNode::Pointer m_CalibrationLandmarksNode; mitk::PointSet::Pointer m_RegistrationLandmarks; mitk::DataNode::Pointer m_RegistrationLandmarksNode; + //members and helper methods for tool axis calibration + mitk::Vector3D m_CalibratedToolAxis; + mitk::NavigationData::Pointer m_AxisCalibration_ToolToCalibrate; + mitk::NavigationData::Pointer m_AxisCalibration_NavDataCalibratingTool; + }; #endif // IGTNavigationToolCalibration_h diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui index d4688a157a..20f1642f61 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui @@ -1,1004 +1,1126 @@ IGTNavigationToolCalibrationControls 0 0 - 430 + 557 958 0 0 QmitkTemplate <!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:'MS Shell Dlg 2'; font-size:8.25pt; 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-size:10pt; font-weight:600;">Navigation Tool Calibration</span></p></body></html> Tool to calibrate 0 50 16777215 50 Calibration pointer 0 30 + tabWidget true 0 Initialization <!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:'MS Shell Dlg 2'; font-size:7.8pt; 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-size:8pt; text-decoration: underline;">Choose Tracking Device and Tools</span></p></body></html> Qt::Horizontal 120 0 Tool to Calibrate: Qt::Horizontal 40 20 <none> Qt::Horizontal 40 20 150 0 Use as Tool to Calibrate Qt::Horizontal 120 0 Calibration Pointer: Qt::Horizontal 40 20 <none> Qt::Horizontal 40 20 150 0 Use as Calibration Pointer Qt::Horizontal Qt::Vertical 20 586 Tool Tip Calibration 50 false Calibration Method: Qt::Horizontal 40 20 Manual Single Reference Tool Multiple Tools Reference Pivoting Qt::Horizontal 0 Current Tool Tip Translation: true true Current Tool Tip Orientation: true true Qt::Horizontal 40 20 Start Edit Tooltip 0 0 319 160 319 160 QFrame { border-image: url(:/IGTNavigationToolCalibration/Description.svg); } QFrame::Box QFrame::Plain 1 0 0 Current Offset between Tool to calibrate and Calibration pointer: Pos: 8 Qt::AlignCenter Rot: 8 Qt::AlignCenter Qt::Horizontal 0 0 Number of tracking data to collect: 0 0 10000 100 Qt::AlignCenter 0 0 1: Collect Navigation Data Qt::Horizontal Invert calibration transformation Calibrate position true Calibrate orientation true false 2: Run Calibration Qt::Horizontal 0 0 New Tool Tip Position and/or Orientation of Tool to calibrate: Pos: 8 Qt::AlignCenter Rot: 8 Qt::AlignCenter false 3: Set New Tool Tip Position and/or Tool Orientation Qt::Vertical 20 40 Number of pivot poses to collect: 10 1000 100 Number of saved poses: 0 Qt::Horizontal 40 20 Collect Pivot Poses Calibration Result: Qt::Horizontal 40 20 175 0 Compute Pivot Point Qt::Horizontal 40 20 false 0 0 175 0 Use Computed Pivot Point Qt::Vertical 20 99 Tool Landmark Calibration <!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:'MS Shell Dlg 2'; font-size:7.8pt; 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-size:8pt; text-decoration: underline;">Calibrate tool by marking the landmarks with the pointer</span></p></body></html> Registration Landmarks 0 170 Add Pointer Position Calibration Landmarks Qt::Vertical 20 259 + + + Tool Axis Calibration + + + + + + QLayout::SetDefaultConstraint + + + + + + + + + + + + Tool axis: + + + + + + + Get Positions + + + + + + + Calibrate Tool Axis + + + + + + + + + 4 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + + + + + 4 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + + + + + 4 + + + -1000.000000000000000 + + + 1000.000000000000000 + + + + + + + + + + + + + + + + Calibrate the tool axis: +1. Make sure, tool tips of both tools are calibrated +2. Hold pointer at the end of the needle +3. Get Position +4. Calibrate tool axis + +Alternative: Manually edit the axis using the spinboxes. + + + + + + + + + Qt::Vertical + + + + 20 + 497 + + + + + + gridLayoutWidget_2 + label_18 + verticalSpacer_5 + Qt::Horizontal 40 20 Save Calibrated Navigation Tool tabWidget label groupBox groupBox_2 - QmitkNavigationDataSourceSelectionWidget + QmitkPointListWidget QWidget -
QmitkNavigationDataSourceSelectionWidget.h
+
QmitkPointListWidget.h
1
- QmitkToolTrackingStatusWidget + QmitkNavigationDataSourceSelectionWidget QWidget -
QmitkToolTrackingStatusWidget.h
+
QmitkNavigationDataSourceSelectionWidget.h
1
- QmitkPointListWidget + QmitkToolTrackingStatusWidget QWidget -
QmitkPointListWidget.h
+
QmitkToolTrackingStatusWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.cpp index 81eaf71879..8de72cb732 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.cpp @@ -1,78 +1,78 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkMITKIGTNavigationToolManagerView.h" // MITK #include // Qt #include const std::string QmitkMITKIGTNavigationToolManagerView::VIEW_ID = "org.mitk.views.mitkigtnavigationtoolmanager"; QmitkMITKIGTNavigationToolManagerView::QmitkMITKIGTNavigationToolManagerView() : QmitkAbstractView() , m_Controls(0) { } QmitkMITKIGTNavigationToolManagerView::~QmitkMITKIGTNavigationToolManagerView() { for (auto storage : m_AllStoragesHandledByThisWidget) storage->UnRegisterMicroservice(); } void QmitkMITKIGTNavigationToolManagerView::CreateQtPartControl(QWidget *parent) { // build up qt view, unless already done if (!m_Controls) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkMITKIGTNavigationToolManagerViewControls; m_Controls->setupUi(parent); connect((QObject*)(m_Controls->m_toolManagerWidget), SIGNAL(NewStorageAdded(mitk::NavigationToolStorage::Pointer, std::string)), this, SLOT(NewStorageByWidget(mitk::NavigationToolStorage::Pointer, std::string))); connect((QObject*)(m_Controls->m_ToolStorageListWidget), SIGNAL(NavigationToolStorageSelected(mitk::NavigationToolStorage::Pointer)), this, SLOT(ToolStorageSelected(mitk::NavigationToolStorage::Pointer))); } m_Controls->m_toolManagerWidget->Initialize(this->GetDataStorage()); } void QmitkMITKIGTNavigationToolManagerView::SetFocus() { m_Controls->m_ToolStorageListWidget->setFocus(); } -void QmitkMITKIGTNavigationToolManagerView::NewStorageByWidget(mitk::NavigationToolStorage::Pointer storage, std::string storageName) +void QmitkMITKIGTNavigationToolManagerView::NewStorageByWidget(mitk::NavigationToolStorage::Pointer storage) { - storage->RegisterAsMicroservice(storageName); + storage->RegisterAsMicroservice(); m_AllStoragesHandledByThisWidget.push_back(storage); } void QmitkMITKIGTNavigationToolManagerView::ToolStorageSelected(mitk::NavigationToolStorage::Pointer storage) { if (storage.IsNull()) //no storage selected { //reset everything return; } this->m_Controls->m_toolManagerWidget->LoadStorage(storage); } diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.h index c9fff653b4..b84f1edce6 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTNavigationToolManagerView.h @@ -1,63 +1,63 @@ /*=================================================================== 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 QmitkMITKIGTNavigationToolManagerView_h #define QmitkMITKIGTNavigationToolManagerView_h #include #include #include #include "ui_QmitkMITKIGTNavigationToolManagerViewControls.h" /*! \brief QmitkMITKIGTNavigationToolManagerView \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. */ class QmitkMITKIGTNavigationToolManagerView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkMITKIGTNavigationToolManagerView(); virtual ~QmitkMITKIGTNavigationToolManagerView(); virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; protected slots: - void NewStorageByWidget(mitk::NavigationToolStorage::Pointer storage, std::string); + void NewStorageByWidget(mitk::NavigationToolStorage::Pointer storage); void ToolStorageSelected(mitk::NavigationToolStorage::Pointer); protected: Ui::QmitkMITKIGTNavigationToolManagerViewControls* m_Controls; /** Someone needs to hold the smart pointers of new storages, otherwise the objects will be lost although they are listed as microservice. */ std::vector m_AllStoragesHandledByThisWidget; }; #endif // _QMITKMITKIGTNAVIGATIONTOOLMANAGERVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp index 60e70eee44..ad176e1cf9 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp @@ -1,1462 +1,1349 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkMITKIGTTrackingToolboxView.h" -#include "QmitkTrackingDeviceConfigurationWidget.h" // Qt #include #include #include // MITK #include -#include #include -#include #include #include #include -//#include #include #include -#include #include #include -#include "mitkNDIAuroraTypeInformation.h" - -// vtk -#include +#include //for exceptions #include #include -//for Microservice #include "mitkPluginActivator.h" -#include -#include -#include "usServiceReference.h" const std::string QmitkMITKIGTTrackingToolboxView::VIEW_ID = "org.mitk.views.mitkigttrackingtoolbox"; QmitkMITKIGTTrackingToolboxView::QmitkMITKIGTTrackingToolboxView() : QmitkAbstractView() , m_Controls(nullptr) , m_DeviceTypeCollection(nullptr) { m_TrackingLoggingTimer = new QTimer(this); m_TrackingRenderTimer = new QTimer(this); m_TimeoutTimer = new QTimer(this); m_tracking = false; m_connected = false; m_logging = false; + m_ShowHideToolProjection = false; + m_ShowHideToolAxis = false; m_loggedFrames = 0; m_SimpleModeEnabled = false; + m_NeedleProjectionFilter = mitk::NeedleProjectionFilter::New(); //create filename for autosaving of tool storage QString loggingPathWithoutFilename = QString(mitk::LoggingBackend::GetLogFile().c_str()); if (!loggingPathWithoutFilename.isEmpty()) //if there already is a path for the MITK logging file use this one { //extract path from path+filename (if someone knows a better way to do this feel free to change it) int lengthOfFilename = QFileInfo(QString::fromStdString(mitk::LoggingBackend::GetLogFile())).fileName().size(); loggingPathWithoutFilename.resize(loggingPathWithoutFilename.size() - lengthOfFilename); m_AutoSaveFilename = loggingPathWithoutFilename + "TrackingToolboxAutoSave.IGTToolStorage"; } else //if not: use a temporary path from IOUtil { m_AutoSaveFilename = QString(mitk::IOUtil::GetTempPath().c_str()) + "TrackingToolboxAutoSave.IGTToolStorage"; } MITK_INFO("IGT Tracking Toolbox") << "Filename for auto saving of IGT ToolStorages: " << m_AutoSaveFilename.toStdString(); //! [Thread 1] //initialize worker thread m_WorkerThread = new QThread(); m_Worker = new QmitkMITKIGTTrackingToolboxViewWorker(); //! [Thread 1] ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if (pluginContext) { QString interfaceName = QString::fromStdString(us_service_interface_iid()); QList serviceReference = pluginContext->getServiceReferences(interfaceName); if (serviceReference.size() > 0) { m_DeviceTypeServiceReference = serviceReference.at(0); const ctkServiceReference& r = serviceReference.at(0); m_DeviceTypeCollection = pluginContext->getService(r); } else { MITK_INFO << "No Tracking Device Collection!"; } } } QmitkMITKIGTTrackingToolboxView::~QmitkMITKIGTTrackingToolboxView() { this->StoreUISettings(); m_TrackingLoggingTimer->stop(); m_TrackingRenderTimer->stop(); m_TimeoutTimer->stop(); delete m_TrackingLoggingTimer; delete m_TrackingRenderTimer; delete m_TimeoutTimer; try { //! [Thread 2] // wait for thread to finish m_WorkerThread->terminate(); m_WorkerThread->wait(); //clean up worker thread if (m_WorkerThread) { delete m_WorkerThread; } if (m_Worker) { delete m_Worker; } //! [Thread 2] //remove the tracking volume this->GetDataStorage()->Remove(m_TrackingVolumeNode); //unregister microservices if (m_toolStorage) { m_toolStorage->UnRegisterMicroservice(); } - if (m_TrackingDeviceSource) { m_TrackingDeviceSource->UnRegisterMicroservice(); } + if (m_IGTLMessageProvider.IsNotNull()){ m_IGTLMessageProvider->UnRegisterMicroservice(); } } catch (std::exception& e) { MITK_WARN << "Unexpected exception during clean up of tracking toolbox view: " << e.what(); } catch (...) { MITK_WARN << "Unexpected unknown error during clean up of tracking toolbox view!"; } //store tool storage and UI settings for persistence this->AutoSaveToolStorage(); this->StoreUISettings(); m_DeviceTypeCollection = nullptr; mitk::PluginActivator::GetContext()->ungetService(m_DeviceTypeServiceReference); } void QmitkMITKIGTTrackingToolboxView::CreateQtPartControl(QWidget *parent) { // build up qt view, unless already done if (!m_Controls) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkMITKIGTTrackingToolboxViewControls; m_Controls->setupUi(parent); //create connections connect(m_Controls->m_LoadTools, SIGNAL(clicked()), this, SLOT(OnLoadTools())); connect(m_Controls->m_ConnectDisconnectButton, SIGNAL(clicked()), this, SLOT(OnConnectDisconnect())); connect(m_Controls->m_StartStopTrackingButton, SIGNAL(clicked()), this, SLOT(OnStartStopTracking())); connect(m_Controls->m_ConnectSimpleMode, SIGNAL(clicked()), this, SLOT(OnConnectDisconnect())); connect(m_Controls->m_StartTrackingSimpleMode, SIGNAL(clicked()), this, SLOT(OnStartStopTracking())); connect(m_Controls->m_FreezeUnfreezeTrackingButton, SIGNAL(clicked()), this, SLOT(OnFreezeUnfreezeTracking())); connect(m_TrackingLoggingTimer, SIGNAL(timeout()), this, SLOT(UpdateLoggingTrackingTimer())); connect(m_TrackingRenderTimer, SIGNAL(timeout()), this, SLOT(UpdateRenderTrackingTimer())); connect(m_TimeoutTimer, SIGNAL(timeout()), this, SLOT(OnTimeOut())); connect(m_Controls->m_ChooseFile, SIGNAL(clicked()), this, SLOT(OnChooseFileClicked())); connect(m_Controls->m_StartLogging, SIGNAL(clicked()), this, SLOT(StartLogging())); connect(m_Controls->m_StopLogging, SIGNAL(clicked()), this, SLOT(StopLogging())); connect(m_Controls->m_VolumeSelectionBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(OnTrackingVolumeChanged(QString))); connect(m_Controls->m_ShowTrackingVolume, SIGNAL(clicked()), this, SLOT(OnShowTrackingVolumeChanged())); connect(m_Controls->m_AutoDetectTools, SIGNAL(clicked()), this, SLOT(OnAutoDetectTools())); connect(m_Controls->m_ResetTools, SIGNAL(clicked()), this, SLOT(OnResetTools())); connect(m_Controls->m_AddSingleTool, SIGNAL(clicked()), this, SLOT(OnAddSingleTool())); connect(m_Controls->m_NavigationToolCreationWidget, SIGNAL(NavigationToolFinished()), this, SLOT(OnAddSingleToolFinished())); connect(m_Controls->m_NavigationToolCreationWidget, SIGNAL(Canceled()), this, SLOT(OnAddSingleToolCanceled())); - connect(m_Controls->m_csvFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); - connect(m_Controls->m_xmlFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); + connect(m_Controls->m_CsvFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); + connect(m_Controls->m_XmlFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); connect(m_Controls->m_UseDifferentUpdateRates, SIGNAL(clicked()), this, SLOT(OnToggleDifferentUpdateRates())); connect(m_Controls->m_RenderUpdateRate, SIGNAL(valueChanged(int)), this, SLOT(OnChangeRenderUpdateRate())); connect(m_Controls->m_DisableAllTimers, SIGNAL(stateChanged(int)), this, SLOT(EnableDisableTimerButtons(int))); connect(m_Controls->m_advancedUI, SIGNAL(clicked()), this, SLOT(OnToggleAdvancedSimpleMode())); - connect(m_Controls->m_simpleUI, SIGNAL(clicked()), this, SLOT(OnToggleAdvancedSimpleMode())); + connect(m_Controls->m_SimpleUI, SIGNAL(clicked()), this, SLOT(OnToggleAdvancedSimpleMode())); + connect(m_Controls->showHideToolProjectionCheckBox, SIGNAL(clicked()), this, SLOT(OnShowHideToolProjectionClicked())); + connect(m_Controls->showHideToolAxisCheckBox, SIGNAL(clicked()), this, SLOT(OnShowHideToolAxisClicked())); //connections for the tracking device configuration widget - connect(m_Controls->m_configurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); + connect(m_Controls->m_ConfigurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); + //! [Thread 3] //connect worker thread connect(m_Worker, SIGNAL(AutoDetectToolsFinished(bool, QString)), this, SLOT(OnAutoDetectToolsFinished(bool, QString))); connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool, QString)), this, SLOT(OnConnectFinished(bool, QString))); connect(m_Worker, SIGNAL(StartTrackingFinished(bool, QString)), this, SLOT(OnStartTrackingFinished(bool, QString))); connect(m_Worker, SIGNAL(StopTrackingFinished(bool, QString)), this, SLOT(OnStopTrackingFinished(bool, QString))); connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool, QString)), this, SLOT(OnDisconnectFinished(bool, QString))); connect(m_WorkerThread, SIGNAL(started()), m_Worker, SLOT(ThreadFunc())); + connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnConnected(bool))); + connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnDisconnected(bool))); + connect(m_Worker, SIGNAL(StartTrackingFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnStartTracking(bool))); + connect(m_Worker, SIGNAL(StopTrackingFinished(bool, QString)), m_Controls->m_ConfigurationWidget, SLOT(OnStopTracking(bool))); + + + //Add Listener, so that we know when the toolStorage changed. + std::string m_Filter = "(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.NavigationToolStorage" + ")"; + mitk::PluginActivator::GetContext()->connectServiceListener(this, "OnToolStorageChanged", QString(m_Filter.c_str())); + //move the worker to the thread m_Worker->moveToThread(m_WorkerThread); //! [Thread 3] //initialize widgets m_Controls->m_TrackingToolsStatusWidget->SetShowPositions(true); m_Controls->m_TrackingToolsStatusWidget->SetTextAlignment(Qt::AlignLeft); m_Controls->m_simpleWidget->setVisible(false); //initialize tracking volume node m_TrackingVolumeNode = mitk::DataNode::New(); m_TrackingVolumeNode->SetName("TrackingVolume"); m_TrackingVolumeNode->SetBoolProperty("Backface Culling", true); mitk::Color red; red.SetRed(1); m_TrackingVolumeNode->SetColor(red); //initialize buttons m_Controls->m_AutoDetectTools->setVisible(false); //only visible if supported by tracking device m_Controls->m_StartStopTrackingButton->setEnabled(false); m_Controls->m_StartTrackingSimpleMode->setEnabled(false); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false); //initialize warning labels - m_Controls->m_renderWarningLabel->setVisible(false); + m_Controls->m_RenderWarningLabel->setVisible(false); m_Controls->m_TrackingFrozenLabel->setVisible(false); //Update List of available models for selected tool. std::vector Compatibles; - if ((m_Controls == nullptr) || //check all these stuff for nullptr, latterly this causes crashes from time to time - (m_Controls->m_configurationWidget == nullptr) || - (m_Controls->m_configurationWidget->GetTrackingDevice().IsNull())) + if ((m_Controls == nullptr) || //check all these stuff for NULL, latterly this causes crashes from time to time + (m_Controls->m_ConfigurationWidget == nullptr) || + (m_Controls->m_ConfigurationWidget->GetTrackingDevice().IsNull())) { MITK_ERROR << "Couldn't get current tracking device or an object is nullptr, something went wrong!"; return; } else { - Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType()); + Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType()); } m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } //initialize tool storage m_toolStorage = mitk::NavigationToolStorage::New(GetDataStorage()); m_toolStorage->SetName("TrackingToolbox Default Storage"); - m_toolStorage->RegisterAsMicroservice("no tracking device"); + m_toolStorage->RegisterAsMicroservice(); //set home directory as default path for logfile m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(QDir::homePath()) + QDir::separator() + "logfile.csv"); //tracking device may be changed already by the persistence of the //QmitkTrackingDeciveConfigurationWidget this->OnTrackingDeviceChanged(); this->LoadUISettings(); //add tracking volume node only to data storage this->GetDataStorage()->Add(m_TrackingVolumeNode); if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0); else m_TrackingVolumeNode->SetOpacity(0.25); //Update List of available models for selected tool. m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } } -void QmitkMITKIGTTrackingToolboxView::SetFocus() -{ - m_Controls->m_configurationWidget->setFocus(); -} - void QmitkMITKIGTTrackingToolboxView::OnLoadTools() { //read in filename QString filename = QFileDialog::getOpenFileName(nullptr, tr("Open Tool Storage"), "/", tr("Tool Storage Files (*.IGTToolStorage)")); if (filename.isNull()) return; //read tool storage from disk std::string errorMessage = ""; mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); // try-catch block for exceptions try { this->ReplaceCurrentToolStorage(myDeserializer->Deserialize(filename.toStdString()), filename.toStdString()); } catch (mitk::IGTException) { std::string errormessage = "Error during loading the tool storage file. Please only load tool storage files created with the NavigationToolManager view."; QMessageBox::warning(nullptr, "Tool Storage Loading Error", errormessage.c_str()); return; } if (m_toolStorage->isEmpty()) { errorMessage = myDeserializer->GetErrorMessage(); MessageBox(errorMessage); return; } //update label UpdateToolStorageLabel(filename); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); //save filename for persistent storage m_ToolStorageFilename = filename; } void QmitkMITKIGTTrackingToolboxView::OnResetTools() { + //remove data nodes of surfaces from data storage to clean up + for (unsigned int i = 0; i < m_toolStorage->GetToolCount(); i++) + { + this->GetDataStorage()->Remove(m_toolStorage->GetTool(i)->GetDataNode()); + } this->ReplaceCurrentToolStorage(mitk::NavigationToolStorage::New(GetDataStorage()), "TrackingToolbox Default Storage"); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); QString toolLabel = QString(""); - m_Controls->m_toolLabel->setText(toolLabel); + m_Controls->m_ToolLabel->setText(toolLabel); m_ToolStorageFilename = ""; + + } void QmitkMITKIGTTrackingToolboxView::OnStartStopTracking() { if (!m_connected) { MITK_WARN << "Can't start tracking if no device is connected. Aborting"; return; } if (m_tracking) { OnStopTracking(); } else { OnStartTracking(); } } void QmitkMITKIGTTrackingToolboxView::OnFreezeUnfreezeTracking() { if (m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Freeze Tracking") { - m_TrackingDeviceSource->Freeze(); + m_Worker->GetTrackingDeviceSource()->Freeze(); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Unfreeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(true); } else if (m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Unfreeze Tracking") { - m_TrackingDeviceSource->UnFreeze(); + m_Worker->GetTrackingDeviceSource()->UnFreeze(); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(false); } } +void QmitkMITKIGTTrackingToolboxView::OnShowHideToolProjectionClicked() +{ + if( !m_ShowHideToolProjection ) + { + //Activate and show the tool projection + mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Tool Projection"); + //If node does not exist, create the node for the Pointset + if( node.IsNull() ) + { + node = mitk::DataNode::New(); + node->SetName("Tool Projection"); + node->SetData(m_NeedleProjectionFilter->GetProjection()); + node->SetBoolProperty("show contour", true); + this->GetDataStorage()->Add(node); + } + else + { + node->SetBoolProperty("show contour", true); + } + //Enable the checkbox for displaying the (standard) tool axis + m_Controls->showHideToolAxisCheckBox->setEnabled(true); + m_ShowHideToolProjection = true; + } + else + { + //Deactivate and hide the tool projection + mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode("Tool Projection"); + if( !node.IsNull() ) + { + this->GetDataStorage()->Remove(node); + } + m_Controls->showHideToolAxisCheckBox->setEnabled(false); + m_ShowHideToolProjection = false; + } + if( m_NeedleProjectionFilter.IsNotNull() ) + { + m_NeedleProjectionFilter->Update(); + } + //Refresh the view and the status widget + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + m_Controls->m_TrackingToolsStatusWidget->Refresh(); +} + +void QmitkMITKIGTTrackingToolboxView::OnShowHideToolAxisClicked() +{ + if( !m_ShowHideToolAxis ) + { + //Activate and show the tool axis + m_NeedleProjectionFilter->ShowToolAxis(true); + m_ShowHideToolAxis = true; + } + else + { + //Deactivate and hide the tool axis + m_NeedleProjectionFilter->ShowToolAxis(false); + m_NeedleProjectionFilter->GetProjection()->RemovePointIfExists(2); + m_ShowHideToolAxis = false; + } + //Update the filter + if( m_NeedleProjectionFilter.IsNotNull() ) + { + m_NeedleProjectionFilter->Update(); + } + //Refresh the view and the status widget + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + m_Controls->m_TrackingToolsStatusWidget->Refresh(); +} + void QmitkMITKIGTTrackingToolboxView::OnConnectDisconnect() { if (m_connected) { OnDisconnect(); } else { OnConnect(); } } void QmitkMITKIGTTrackingToolboxView::OnConnect() { - MITK_INFO << "Connect Clicked"; + MITK_DEBUG << "Connect Clicked"; //check if everything is ready to start tracking if (this->m_toolStorage.IsNull()) { MessageBox("Error: No Tools Loaded Yet!"); return; } else if (this->m_toolStorage->GetToolCount() == 0) { MessageBox("Error: No Way To Track Without Tools!"); return; } //parse tracking device data mitk::TrackingDeviceData data = mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified(); QString qstr = m_Controls->m_VolumeSelectionBox->currentText(); if ((!qstr.isNull()) || (!qstr.isEmpty())) { std::string str = qstr.toStdString(); data = m_DeviceTypeCollection->GetDeviceDataByName(str); //Data will be set later, after device generation } //! [Thread 4] //initialize worker thread m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eConnectDevice); - m_Worker->SetTrackingDevice(this->m_Controls->m_configurationWidget->GetTrackingDevice()); + m_Worker->SetTrackingDevice(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice()); m_Worker->SetInverseMode(m_Controls->m_InverseMode->isChecked()); m_Worker->SetNavigationToolStorage(this->m_toolStorage); m_Worker->SetTrackingDeviceData(data); //start worker thread m_WorkerThread->start(); //! [Thread 4] //disable buttons this->m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableDisableTimerButtons(int enable) { bool enableBool = enable; m_Controls->m_UpdateRateOptionsGroupBox->setEnabled(!enableBool); - m_Controls->m_renderWarningLabel->setVisible(enableBool); + m_Controls->m_RenderWarningLabel->setVisible(enableBool); } void QmitkMITKIGTTrackingToolboxView::OnConnectFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); //enable buttons this->m_Controls->m_MainWidget->setEnabled(true); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; } //! [Thread 6] //get data from worker thread - m_TrackingDeviceSource = m_Worker->GetTrackingDeviceSource(); m_TrackingDeviceData = m_Worker->GetTrackingDeviceData(); m_ToolVisualizationFilter = m_Worker->GetToolVisualizationFilter(); + if( m_ToolVisualizationFilter.IsNotNull() ) + { + //Connect the NeedleProjectionFilter to the ToolVisualizationFilter as third filter of the IGT pipeline + m_NeedleProjectionFilter->ConnectTo(m_ToolVisualizationFilter); + m_NeedleProjectionFilter->SelectInput(0); + } + //! [Thread 6] //enable/disable Buttons DisableOptionsButtons(); DisableTrackingConfigurationButtons(); m_Controls->m_TrackingControlLabel->setText("Status: connected"); m_Controls->m_ConnectDisconnectButton->setText("Disconnect"); m_Controls->m_ConnectSimpleMode->setText("Disconnect"); m_Controls->m_StartStopTrackingButton->setEnabled(true); m_Controls->m_StartTrackingSimpleMode->setEnabled(true); m_connected = true; + + //During connection, thi sourceID of the tool storage changed. However, Microservice can't be updated on a different thread. + //UpdateMicroservice is necessary to use filter to get the right storage belonging to a source. + //Don't do it before m_connected is true, as we don't want to call content of OnToolStorageChanged. + m_toolStorage->UpdateMicroservice(); } void QmitkMITKIGTTrackingToolboxView::OnDisconnect() { m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eDisconnectDevice); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnDisconnectFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); m_Controls->m_MainWidget->setEnabled(true); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; } //enable/disable Buttons m_Controls->m_StartStopTrackingButton->setEnabled(false); m_Controls->m_StartTrackingSimpleMode->setEnabled(false); EnableOptionsButtons(); EnableTrackingConfigurationButtons(); m_Controls->m_TrackingControlLabel->setText("Status: disconnected"); m_Controls->m_ConnectDisconnectButton->setText("Connect"); m_Controls->m_ConnectSimpleMode->setText("Connect"); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(false); m_connected = false; } void QmitkMITKIGTTrackingToolboxView::OnStartTracking() { //show tracking volume this->OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); //Reset the view to a defined start. Do it here and not in OnStartTrackingFinished, to give other tracking devices the chance to reset the view to a different direction. this->GlobalReinit(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStartTracking); m_WorkerThread->start(); this->m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStartTrackingFinished(bool success, QString errorMessage) { //! [Thread 5] m_WorkerThread->quit(); m_WorkerThread->wait(); //! [Thread 5] this->m_Controls->m_MainWidget->setEnabled(true); if (!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); return; } if (!(m_Controls->m_DisableAllTimers->isChecked())) { if (m_Controls->m_UseDifferentUpdateRates->isChecked()) { if (m_Controls->m_RenderUpdateRate->value() != 0) m_TrackingRenderTimer->start(1000 / (m_Controls->m_RenderUpdateRate->value())); m_TrackingLoggingTimer->start(1000 / (m_Controls->m_LogUpdateRate->value())); } else { m_TrackingRenderTimer->start(1000 / (m_Controls->m_UpdateRate->value())); m_TrackingLoggingTimer->start(1000 / (m_Controls->m_UpdateRate->value())); } } m_Controls->m_TrackingControlLabel->setText("Status: tracking"); //connect the tool visualization widget - for (std::size_t i = 0; i < m_TrackingDeviceSource->GetNumberOfOutputs(); i++) + for (std::size_t i = 0; i < m_Worker->GetTrackingDeviceSource()->GetNumberOfOutputs(); i++) { - m_Controls->m_TrackingToolsStatusWidget->AddNavigationData(m_TrackingDeviceSource->GetOutput(i)); + m_Controls->m_TrackingToolsStatusWidget->AddNavigationData(m_Worker->GetTrackingDeviceSource()->GetOutput(i)); } m_Controls->m_TrackingToolsStatusWidget->ShowStatusLabels(); if (m_Controls->m_ShowToolQuaternions->isChecked()) { m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(true); } else { m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(false); } //if activated enable open IGT link microservice if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()) { //create convertion filter m_IGTLConversionFilter = mitk::NavigationDataToIGTLMessageFilter::New(); m_IGTLConversionFilter->SetName("IGT Tracking Toolbox"); QString dataModeSelection = this->m_Controls->m_OpenIGTLinkDataFormat->currentText(); if (dataModeSelection == "TDATA") - {m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg);} + { + m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); + } else if (dataModeSelection == "TRANSFORM") - {m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg);} + { + m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg); + } else if (dataModeSelection == "QTDATA") - {m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendQTDataMsg);} + { + m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendQTDataMsg); + } else if (dataModeSelection == "POSITION") - {m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendQTransMsg);} + { + m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendQTransMsg); + } m_IGTLConversionFilter->ConnectTo(m_ToolVisualizationFilter); m_IGTLConversionFilter->RegisterAsMicroservice(); - //create server and message provider m_IGTLServer = mitk::IGTLServer::New(false); m_IGTLServer->SetName("Tracking Toolbox IGTL Server"); m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); m_IGTLMessageProvider->RegisterAsMicroservice(); } m_tracking = true; m_Controls->m_ConnectDisconnectButton->setEnabled(false); m_Controls->m_StartStopTrackingButton->setText("Stop Tracking"); m_Controls->m_StartTrackingSimpleMode->setText("Stop\nTracking"); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(true); - } void QmitkMITKIGTTrackingToolboxView::OnStopTracking() { if (!m_tracking) return; m_TrackingRenderTimer->stop(); m_TrackingLoggingTimer->stop(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStopTracking); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStopTrackingFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); m_Controls->m_MainWidget->setEnabled(true); if (!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); return; } m_Controls->m_TrackingControlLabel->setText("Status: connected"); if (m_logging) StopLogging(); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); m_tracking = false; m_Controls->m_StartStopTrackingButton->setText("Start Tracking"); m_Controls->m_StartTrackingSimpleMode->setText("Start\nTracking"); m_Controls->m_ConnectDisconnectButton->setEnabled(true); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false); //unregister open IGT link micro service if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()) { m_IGTLConversionFilter->UnRegisterMicroservice(); m_IGTLMessageProvider->UnRegisterMicroservice(); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingDeviceChanged() { mitk::TrackingDeviceType Type; - if (m_Controls->m_configurationWidget->GetTrackingDevice().IsNotNull()) + if (m_Controls->m_ConfigurationWidget->GetTrackingDevice().IsNotNull()) { - Type = m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(); + Type = m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType(); //enable controls because device is valid m_Controls->m_TrackingToolsGoupBox->setEnabled(true); m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } else { Type = mitk::UnspecifiedTrackingTypeInformation::GetTrackingDeviceName(); MessageBox("Error: This tracking device is not included in this project. Please make sure that the device is installed and activated in your MITK build."); m_Controls->m_TrackingToolsGoupBox->setEnabled(false); m_Controls->m_TrackingControlsGroupBox->setEnabled(false); return; } // Code to enable/disable device specific buttons - if (m_Controls->m_configurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) - { m_Controls->m_AutoDetectTools->setVisible(true); } + if (m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) + { + m_Controls->m_AutoDetectTools->setVisible(true); + } else - { m_Controls->m_AutoDetectTools->setVisible(false); } + { + m_Controls->m_AutoDetectTools->setVisible(false); + } - if (Type == mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) //Aurora - { m_Controls->m_AddSingleTool->setEnabled(false);} - else //other trackers - { m_Controls->m_AddSingleTool->setEnabled(true); } + m_Controls->m_AddSingleTool->setEnabled(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AddSingleToolIsAvailable()); // Code to select appropriate tracking volume for current type std::vector Compatibles = m_DeviceTypeCollection->GetDeviceDataForLine(Type); m_Controls->m_VolumeSelectionBox->clear(); for (std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingVolumeChanged(QString qstr) { if (qstr.isNull()) return; if (qstr.isEmpty()) return; mitk::TrackingVolumeGenerator::Pointer volumeGenerator = mitk::TrackingVolumeGenerator::New(); std::string str = qstr.toStdString(); mitk::TrackingDeviceData data = m_DeviceTypeCollection->GetDeviceDataByName(str); m_TrackingDeviceData = data; volumeGenerator->SetTrackingDeviceData(data); volumeGenerator->Update(); mitk::Surface::Pointer volumeSurface = volumeGenerator->GetOutput(); m_TrackingVolumeNode->SetData(volumeSurface); if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0); else m_TrackingVolumeNode->SetOpacity(0.25); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnShowTrackingVolumeChanged() { if (m_Controls->m_ShowTrackingVolume->isChecked()) { OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); m_TrackingVolumeNode->SetOpacity(0.25); } else { m_TrackingVolumeNode->SetOpacity(0.0); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectTools() { - if (m_Controls->m_configurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) + if (m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AutoDetectToolsAvailable()) { DisableTrackingConfigurationButtons(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eAutoDetectTools); - m_Worker->SetTrackingDevice(m_Controls->m_configurationWidget->GetTrackingDevice().GetPointer()); + m_Worker->SetTrackingDevice(m_Controls->m_ConfigurationWidget->GetTrackingDevice().GetPointer()); m_Worker->SetDataStorage(this->GetDataStorage()); m_WorkerThread->start(); - m_TimeoutTimer->start(5000); + m_TimeoutTimer->start(7000); //disable controls until worker thread is finished this->m_Controls->m_MainWidget->setEnabled(false); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectToolsFinished(bool success, QString errorMessage) { - m_TimeoutTimer->stop(); - m_WorkerThread->quit(); - m_WorkerThread->wait(); + //Check, if the thread is running. There might have been a timeOut inbetween and this causes crashes... + if (m_WorkerThread->isRunning()) + { + m_TimeoutTimer->stop(); + m_WorkerThread->quit(); + m_WorkerThread->wait(); + } //enable controls again this->m_Controls->m_MainWidget->setEnabled(true); EnableTrackingConfigurationButtons(); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); EnableTrackingConfigurationButtons(); return; } mitk::NavigationToolStorage::Pointer autoDetectedStorage = m_Worker->GetNavigationToolStorage(); //save detected tools - this->ReplaceCurrentToolStorage(autoDetectedStorage, "Autodetected NDI Aurora Storage"); + std::string _autoDetectText; + _autoDetectText = "Autodetected "; + _autoDetectText.append(this->m_TrackingDeviceData.Line); //This is the device name as string of the current TrackingDevice. + _autoDetectText.append(" Storage"); + this->ReplaceCurrentToolStorage(autoDetectedStorage, _autoDetectText); //auto save the new storage to hard disc (for persistence) AutoSaveToolStorage(); //update label QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools (Auto Detected)"; - m_Controls->m_toolLabel->setText(toolLabel); + m_Controls->m_ToolLabel->setText(toolLabel); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); EnableTrackingConfigurationButtons(); //print a logging message about the detected tools switch (m_toolStorage->GetToolCount()) { case 0: MITK_INFO("IGT Tracking Toolbox") << "Found no tools. Empty ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); break; case 1: MITK_INFO("IGT Tracking Toolbox") << "Found one tool. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); break; default: MITK_INFO("IGT Tracking Toolbox") << "Found " << m_toolStorage->GetToolCount() << " tools. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); } } void QmitkMITKIGTTrackingToolboxView::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkMITKIGTTrackingToolboxView::UpdateRenderTrackingTimer() { //update filter m_ToolVisualizationFilter->Update(); MITK_DEBUG << "Number of outputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); MITK_DEBUG << "Number of inputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedInputs(); //update tool colors to show tool status for (unsigned int i = 0; i < m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); i++) { mitk::NavigationData::Pointer currentTool = m_ToolVisualizationFilter->GetOutput(i); if (currentTool->IsDataValid()) { this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_VALID); } else { this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_WARNING); } } + //Update the NeedleProjectionFilter + if( m_NeedleProjectionFilter.IsNotNull() ) + { + m_NeedleProjectionFilter->Update(); + } + //refresh view and status widget mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_Controls->m_TrackingToolsStatusWidget->Refresh(); } void QmitkMITKIGTTrackingToolboxView::UpdateLoggingTrackingTimer() { //update logging if (m_logging) { this->m_loggingFilter->Update(); m_loggedFrames = this->m_loggingFilter->GetNumberOfRecordedSteps(); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: " + QString::number(m_loggedFrames)); //check if logging stopped automatically if ((m_loggedFrames > 1) && (!m_loggingFilter->GetRecording())){ StopLogging(); } } //refresh status widget m_Controls->m_TrackingToolsStatusWidget->Refresh(); } void QmitkMITKIGTTrackingToolboxView::OnChooseFileClicked() { QDir currentPath = QFileInfo(m_Controls->m_LoggingFileName->text()).dir(); // if no path was selected (QDir would select current working dir then) or the // selected path does not exist -> use home directory if (currentPath == QDir() || !currentPath.exists()) { currentPath = QDir(QDir::homePath()); } QString filename = QFileDialog::getSaveFileName(nullptr, tr("Choose Logging File"), currentPath.absolutePath(), "*.*"); if (filename == "") return; this->m_Controls->m_LoggingFileName->setText(filename); this->OnToggleFileExtension(); } // bug-16470: toggle file extension after clicking on radio button void QmitkMITKIGTTrackingToolboxView::OnToggleFileExtension() { QString currentInputText = this->m_Controls->m_LoggingFileName->text(); QString currentFile = QFileInfo(currentInputText).baseName(); QDir currentPath = QFileInfo(currentInputText).dir(); if (currentFile.isEmpty()) { currentFile = "logfile"; } // Setting currentPath to default home path when currentPath is empty or it does not exist if (currentPath == QDir() || !currentPath.exists()) { currentPath = QDir::homePath(); } // check if csv radio button is clicked - if (this->m_Controls->m_csvFormat->isChecked()) + if (this->m_Controls->m_CsvFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if (currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".csv"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".csv"); } } // check if xml radio button is clicked - else if (this->m_Controls->m_xmlFormat->isChecked()) + else if (this->m_Controls->m_XmlFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if (currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".xml"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".xml"); } } } void QmitkMITKIGTTrackingToolboxView::OnToggleAdvancedSimpleMode() { if (m_SimpleModeEnabled) { m_Controls->m_simpleWidget->setVisible(false); m_Controls->m_MainWidget->setVisible(true); - m_Controls->m_simpleUI->setChecked(false); + m_Controls->m_SimpleUI->setChecked(false); m_SimpleModeEnabled = false; } else { m_Controls->m_simpleWidget->setVisible(true); m_Controls->m_MainWidget->setVisible(false); m_SimpleModeEnabled = true; } } void QmitkMITKIGTTrackingToolboxView::OnToggleDifferentUpdateRates() { if (m_Controls->m_UseDifferentUpdateRates->isChecked()) { if (m_Controls->m_RenderUpdateRate->value() == 0) - m_Controls->m_renderWarningLabel->setVisible(true); + m_Controls->m_RenderWarningLabel->setVisible(true); else - m_Controls->m_renderWarningLabel->setVisible(false); + m_Controls->m_RenderWarningLabel->setVisible(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); m_Controls->m_RenderUpdateRate->setEnabled(true); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(true); m_Controls->m_LogUpdateRate->setEnabled(true); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(true); } else { - m_Controls->m_renderWarningLabel->setVisible(false); + m_Controls->m_RenderWarningLabel->setVisible(false); m_Controls->m_UpdateRate->setEnabled(true); m_Controls->m_OptionsUpdateRateLabel->setEnabled(true); m_Controls->m_RenderUpdateRate->setEnabled(false); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false); m_Controls->m_LogUpdateRate->setEnabled(false); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false); } } void QmitkMITKIGTTrackingToolboxView::OnChangeRenderUpdateRate() { if (m_Controls->m_RenderUpdateRate->value() == 0) - m_Controls->m_renderWarningLabel->setVisible(true); + m_Controls->m_RenderWarningLabel->setVisible(true); else - m_Controls->m_renderWarningLabel->setVisible(false); + m_Controls->m_RenderWarningLabel->setVisible(false); } void QmitkMITKIGTTrackingToolboxView::StartLogging() { if (m_ToolVisualizationFilter.IsNull()) { MessageBox("Cannot activate logging without a connected device. Configure and connect a tracking device first."); return; } if (!m_logging) { //initialize logging filter m_loggingFilter = mitk::NavigationDataRecorder::New(); m_loggingFilter->SetRecordOnlyValidData(m_Controls->m_SkipInvalidData->isChecked()); m_loggingFilter->ConnectTo(m_ToolVisualizationFilter); if (m_Controls->m_LoggingLimit->isChecked()){ m_loggingFilter->SetRecordCountLimit(m_Controls->m_LoggedFramesLimit->value()); } //start filter with try-catch block for exceptions try { m_loggingFilter->StartRecording(); } catch (mitk::IGTException) { std::string errormessage = "Error during start recording. Recorder already started recording?"; QMessageBox::warning(nullptr, "IGTPlayer: Error", errormessage.c_str()); m_loggingFilter->StopRecording(); return; } //update labels / logging variables this->m_Controls->m_LoggingLabel->setText("Logging ON"); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: 0"); m_loggedFrames = 0; m_logging = true; DisableLoggingButtons(); } } void QmitkMITKIGTTrackingToolboxView::StopLogging() { if (m_logging) { //stop logging m_loggingFilter->StopRecording(); m_logging = false; //update GUI this->m_Controls->m_LoggingLabel->setText("Logging OFF"); EnableLoggingButtons(); //write the results to a file - if (m_Controls->m_csvFormat->isChecked() || m_Controls->m_xmlFormat->isChecked()) + if (m_Controls->m_CsvFormat->isChecked()) + { + mitk::IOUtil::Save(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); + } + else if (m_Controls->m_XmlFormat->isChecked()) + { mitk::IOUtil::Save(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); + } } } +void QmitkMITKIGTTrackingToolboxView::SetFocus() +{ +} + void QmitkMITKIGTTrackingToolboxView::OnAddSingleTool() { QString Identifier = "Tool#"; QString Name = "NewTool"; if (m_toolStorage.IsNotNull()) { Identifier += QString::number(m_toolStorage->GetToolCount()); Name += QString::number(m_toolStorage->GetToolCount()); } else { Identifier += "0"; Name += "0"; } m_Controls->m_NavigationToolCreationWidget->Initialize(GetDataStorage(), Identifier.toStdString(), Name.toStdString()); - m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(), false); + m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_ConfigurationWidget->GetTrackingDevice()->GetType(), false); m_Controls->m_TrackingToolsWidget->setCurrentIndex(1); //disable tracking volume during tool editing lastTrackingVolumeState = m_Controls->m_ShowTrackingVolume->isChecked(); if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolFinished() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); if (this->m_toolStorage.IsNull()) { //this shouldn't happen! MITK_WARN << "No ToolStorage available, cannot add tool, aborting!"; return; } m_toolStorage->AddTool(m_Controls->m_NavigationToolCreationWidget->GetCreatedTool()); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); - m_Controls->m_toolLabel->setText(""); + m_Controls->m_ToolLabel->setText(""); //auto save current storage for persistence MITK_INFO << "Auto saving manually added tools for persistence."; AutoSaveToolStorage(); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolCanceled() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::GlobalReinit() { // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } void QmitkMITKIGTTrackingToolboxView::DisableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(false); m_Controls->m_LoggingFileName->setEnabled(false); m_Controls->m_ChooseFile->setEnabled(false); m_Controls->m_LoggingLimit->setEnabled(false); m_Controls->m_LoggedFramesLimit->setEnabled(false); - m_Controls->m_csvFormat->setEnabled(false); - m_Controls->m_xmlFormat->setEnabled(false); + m_Controls->m_CsvFormat->setEnabled(false); + m_Controls->m_XmlFormat->setEnabled(false); m_Controls->m_SkipInvalidData->setEnabled(false); m_Controls->m_StopLogging->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::EnableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(true); m_Controls->m_LoggingFileName->setEnabled(true); m_Controls->m_ChooseFile->setEnabled(true); m_Controls->m_LoggingLimit->setEnabled(true); m_Controls->m_LoggedFramesLimit->setEnabled(true); - m_Controls->m_csvFormat->setEnabled(true); - m_Controls->m_xmlFormat->setEnabled(true); + m_Controls->m_CsvFormat->setEnabled(true); + m_Controls->m_XmlFormat->setEnabled(true); m_Controls->m_SkipInvalidData->setEnabled(true); m_Controls->m_StopLogging->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::DisableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(false); m_Controls->m_UseDifferentUpdateRates->setEnabled(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); m_Controls->m_RenderUpdateRate->setEnabled(false); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false); m_Controls->m_LogUpdateRate->setEnabled(false); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false); m_Controls->m_DisableAllTimers->setEnabled(false); m_Controls->m_OtherOptionsGroupBox->setEnabled(false); m_Controls->m_EnableOpenIGTLinkMicroService->setEnabled(false); m_Controls->m_OpenIGTLinkDataFormat->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(true); m_Controls->m_UseDifferentUpdateRates->setEnabled(true); m_Controls->m_DisableAllTimers->setEnabled(true); m_Controls->m_OtherOptionsGroupBox->setEnabled(true); m_Controls->m_EnableOpenIGTLinkMicroService->setEnabled(true); m_Controls->m_OpenIGTLinkDataFormat->setEnabled(true); OnToggleDifferentUpdateRates(); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingControls() { m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingControls() { m_Controls->m_TrackingControlsGroupBox->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(true); - if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) m_Controls->m_AddSingleTool->setEnabled(true); + m_Controls->m_AddSingleTool->setEnabled(this->m_Controls->m_ConfigurationWidget->GetTrackingDevice()->AddSingleToolIsAvailable()); m_Controls->m_LoadTools->setEnabled(true); m_Controls->m_ResetTools->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(false); - if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAuroraTypeInformation::GetTrackingDeviceName()) m_Controls->m_AddSingleTool->setEnabled(false); + m_Controls->m_AddSingleTool->setEnabled(false); m_Controls->m_LoadTools->setEnabled(false); m_Controls->m_ResetTools->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName) { //first: get rid of the old one //don't reset if there is no tool storage. BugFix #17793 if (m_toolStorage.IsNotNull()){ m_toolStorage->UnLockStorage(); //only to be sure... m_toolStorage->UnRegisterMicroservice(); m_toolStorage = nullptr; } //now: replace by the new one m_toolStorage = newStorage; m_toolStorage->SetName(newStorageName); - m_toolStorage->RegisterAsMicroservice("no tracking device"); + m_toolStorage->RegisterAsMicroservice(); } void QmitkMITKIGTTrackingToolboxView::OnTimeOut() { - m_WorkerThread->terminate(); - m_WorkerThread->wait(); + MITK_WARN << "TimeOut. Quitting the thread..."; + m_WorkerThread->quit(); + //only if we can't quit use terminate. + if (!m_WorkerThread->wait(1000)) + { + MITK_ERROR << "Can't quit the thread. Terminating... Might cause further problems, be careful!"; + m_WorkerThread->terminate(); + m_WorkerThread->wait(); + } m_TimeoutTimer->stop(); } +void QmitkMITKIGTTrackingToolboxView::OnToolStorageChanged(const ctkServiceEvent event) +{ + //don't listen to any changes during connection, toolStorage is locked anyway, so this are only changes of e.g. sourceID which are not relevant for the widget. + if (!m_connected && (event.getType() == ctkServiceEvent::MODIFIED)) + { + m_Controls->m_ConfigurationWidget->OnToolStorageChanged(); + } +} + //! [StoreUISettings] void QmitkMITKIGTTrackingToolboxView::StoreUISettings() { // persistence service does not directly work in plugins for now // -> using QSettings QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); MITK_DEBUG << "Store UI settings"; // set the values of some widgets and attrbutes to the QSettings settings.setValue("ShowTrackingVolume", QVariant(m_Controls->m_ShowTrackingVolume->isChecked())); settings.setValue("toolStorageFilename", QVariant(m_ToolStorageFilename)); settings.setValue("VolumeSelectionBox", QVariant(m_Controls->m_VolumeSelectionBox->currentIndex())); settings.setValue("SimpleModeEnabled", QVariant(m_SimpleModeEnabled)); settings.setValue("OpenIGTLinkDataFormat", QVariant(m_Controls->m_OpenIGTLinkDataFormat->currentIndex())); settings.setValue("EnableOpenIGTLinkMicroService", QVariant(m_Controls->m_EnableOpenIGTLinkMicroService->isChecked())); settings.endGroup(); } //! [StoreUISettings] //! [LoadUISettings] void QmitkMITKIGTTrackingToolboxView::LoadUISettings() { // persistence service does not directly work in plugins for now -> using QSettings QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); // set some widgets and attributes by the values from the QSettings m_Controls->m_ShowTrackingVolume->setChecked(settings.value("ShowTrackingVolume", true).toBool()); m_Controls->m_EnableOpenIGTLinkMicroService->setChecked(settings.value("EnableOpenIGTLinkMicroService", true).toBool()); m_Controls->m_VolumeSelectionBox->setCurrentIndex(settings.value("VolumeSelectionBox", 0).toInt()); m_Controls->m_OpenIGTLinkDataFormat->setCurrentIndex(settings.value("OpenIGTLinkDataFormat", 0).toInt()); m_ToolStorageFilename = settings.value("toolStorageFilename", QVariant("")).toString(); if (settings.value("SimpleModeEnabled", false).toBool()) { this->OnToggleAdvancedSimpleMode(); } settings.endGroup(); //! [LoadUISettings] //! [LoadToolStorage] // try to deserialize the tool storage from the given tool storage file name if (!m_ToolStorageFilename.isEmpty()) { // try-catch block for exceptions try { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); m_toolStorage->UnRegisterMicroservice(); m_toolStorage = myDeserializer->Deserialize(m_ToolStorageFilename.toStdString()); - m_toolStorage->RegisterAsMicroservice("no tracking device"); + m_toolStorage->RegisterAsMicroservice(); //update label UpdateToolStorageLabel(m_ToolStorageFilename); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); } catch (mitk::IGTException) { MITK_WARN("QmitkMITKIGTTrackingToolBoxView") << "Error during restoring tools. Problems with file (" << m_ToolStorageFilename.toStdString() << "), please check the file?"; this->OnResetTools(); //if there where errors reset the tool storage to avoid problems later on } } //! [LoadToolStorage] } void QmitkMITKIGTTrackingToolboxView::UpdateToolStorageLabel(QString pathOfLoadedStorage) { QFileInfo myPath(pathOfLoadedStorage); //use this to seperate filename from path QString toolLabel = myPath.fileName(); if (toolLabel.size() > 45) //if the tool storage name is to long trimm the string { toolLabel.resize(40); toolLabel += "[...]"; } - m_Controls->m_toolLabel->setText(toolLabel); + m_Controls->m_ToolLabel->setText(toolLabel); } void QmitkMITKIGTTrackingToolboxView::AutoSaveToolStorage() { m_ToolStorageFilename = m_AutoSaveFilename; mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); mySerializer->Serialize(m_ToolStorageFilename.toStdString(), m_toolStorage); } - -void QmitkMITKIGTTrackingToolboxViewWorker::SetWorkerMethod(WorkerMethod w) -{ - m_WorkerMethod = w; -} - -void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) -{ - m_TrackingDevice = t; -} - -void QmitkMITKIGTTrackingToolboxViewWorker::SetDataStorage(mitk::DataStorage::Pointer d) -{ - m_DataStorage = d; -} - -void QmitkMITKIGTTrackingToolboxViewWorker::SetInverseMode(bool mode) -{ - m_InverseMode = mode; -} - -void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDeviceData(mitk::TrackingDeviceData d) -{ - m_TrackingDeviceData = d; -} - -void QmitkMITKIGTTrackingToolboxViewWorker::SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n) -{ - m_NavigationToolStorage = n; -} - -//! [Thread 7] -void QmitkMITKIGTTrackingToolboxViewWorker::ThreadFunc() -{ - switch (m_WorkerMethod) - { - case eAutoDetectTools: - this->AutoDetectTools(); - break; - case eConnectDevice: - this->ConnectDevice(); - break; - case eStartTracking: - this->StartTracking(); - break; - case eStopTracking: - this->StopTracking(); - break; - case eDisconnectDevice: - this->DisconnectDevice(); - break; - default: - MITK_WARN << "Undefined worker method was set ... something went wrong!"; - break; - } -} -//! [Thread 7] - -void QmitkMITKIGTTrackingToolboxViewWorker::AutoDetectTools() -{ - //mitk::ProgressBar::GetInstance()->AddStepsToDo(2); - mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(m_DataStorage); - try - { - mitk::NavigationToolStorage::Pointer tempStorage = m_TrackingDevice->AutoDetectTools(); - //mitk::ProgressBar::GetInstance()->Progress(); - for (int i = 0; i < tempStorage->GetToolCount(); i++) { autoDetectedStorage->AddTool(tempStorage->GetTool(i)); } - } - catch (mitk::Exception& e) - { - MITK_WARN << e.GetDescription(); - //mitk::ProgressBar::GetInstance()->Reset(); - emit AutoDetectToolsFinished(false, e.GetDescription()); - return; - } - m_NavigationToolStorage = autoDetectedStorage; - //::ProgressBar::GetInstance()->Progress(); - emit AutoDetectToolsFinished(true, ""); -} - -void QmitkMITKIGTTrackingToolboxViewWorker::ConnectDevice() -{ - std::string message = ""; - //mitk::ProgressBar::GetInstance()->AddStepsToDo(4); - - //build the IGT pipeline - mitk::TrackingDevice::Pointer trackingDevice = m_TrackingDevice; - trackingDevice->SetData(m_TrackingDeviceData); - - //set device to rotation mode transposed becaus we are working with VNL style quaternions - if (m_InverseMode) - { - trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed); - } - - //Get Tracking Volume Data - mitk::TrackingDeviceData data = m_TrackingDeviceData; - //mitk::ProgressBar::GetInstance()->Progress(); - - //Create Navigation Data Source with the factory class - mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(m_NavigationToolStorage, trackingDevice); - m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(m_ToolVisualizationFilter); - //mitk::ProgressBar::GetInstance()->Progress(); - - if (m_TrackingDeviceSource.IsNull()) - { - message = std::string("Cannot connect to device: ") + myTrackingDeviceSourceFactory->GetErrorMessage(); - emit ConnectDeviceFinished(false, QString(message.c_str())); - return; - } - - //set filter to rotation mode transposed becaus we are working with VNL style quaternions - if (m_InverseMode) - m_ToolVisualizationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); - - //First check if the created object is valid - if (m_TrackingDeviceSource.IsNull()) - { - message = myTrackingDeviceSourceFactory->GetErrorMessage(); - emit ConnectDeviceFinished(false, QString(message.c_str())); - return; - } - - MITK_INFO << "Number of tools: " << m_TrackingDeviceSource->GetNumberOfOutputs(); - //mitk::ProgressBar::GetInstance()->Progress(); - - //The tools are maybe reordered after initialization, e.g. in case of auto-detected tools of NDI Aurora - mitk::NavigationToolStorage::Pointer toolsInNewOrder = myTrackingDeviceSourceFactory->GetUpdatedNavigationToolStorage(); - - if ((toolsInNewOrder.IsNotNull()) && (toolsInNewOrder->GetToolCount() > 0)) - { - //so delete the old tools in wrong order and add them in the right order - //we cannot simply replace the tool storage because the new storage is - //not correctly initialized with the right data storage - - /* - m_NavigationToolStorage->DeleteAllTools(); - for (int i=0; i < toolsInNewOrder->GetToolCount(); i++) {m_NavigationToolStorage->AddTool(toolsInNewOrder->GetTool(i));} - - This was replaced and thereby fixed Bug 18318 DeleteAllTools() is not Threadsafe! - */ - for (int i = 0; i < toolsInNewOrder->GetToolCount(); i++) - { - m_NavigationToolStorage->AssignToolNumber(toolsInNewOrder->GetTool(i)->GetIdentifier(), i); - } - } - - //mitk::ProgressBar::GetInstance()->Progress(); - - //connect to device - try - { - m_TrackingDeviceSource->Connect(); - //mitk::ProgressBar::GetInstance()->Reset(); - //Microservice registration: - m_TrackingDeviceSource->RegisterAsMicroservice(); - m_NavigationToolStorage->UnRegisterMicroservice(); - m_NavigationToolStorage->RegisterAsMicroservice(m_TrackingDeviceSource->GetMicroserviceID()); - m_NavigationToolStorage->LockStorage(); - } - catch (...) //todo: change to mitk::IGTException - { - message = "Error on connecting the tracking device."; - emit ConnectDeviceFinished(false, QString(message.c_str())); - return; - } - emit ConnectDeviceFinished(true, QString(message.c_str())); - //mitk::ProgressBar::GetInstance()->Reset(); -} - -void QmitkMITKIGTTrackingToolboxViewWorker::StartTracking() -{ - QString errorMessage = ""; - try - { - m_TrackingDeviceSource->StartTracking(); - } - catch (...) //todo: change to mitk::IGTException - { - errorMessage += "Error while starting the tracking device!"; - emit StartTrackingFinished(false, errorMessage); - return; - } - //remember the original colors of the tools - m_OriginalColors = std::map(); - for (int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) - { - mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); - float c[3]; - currentToolNode->GetColor(c); - mitk::Color color; - color.SetRed(c[0]); - color.SetGreen(c[1]); - color.SetBlue(c[2]); - m_OriginalColors[currentToolNode] = color; - } - - emit StartTrackingFinished(true, errorMessage); -} - -void QmitkMITKIGTTrackingToolboxViewWorker::StopTracking() -{ - //stop tracking - try - { - m_TrackingDeviceSource->StopTracking(); - } - catch (mitk::Exception& e) - { - emit StopTrackingFinished(false, e.GetDescription()); - } - - //restore the original colors of the tools - for (int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) - { - mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); - if (m_OriginalColors.find(currentToolNode) == m_OriginalColors.end()) - { - MITK_WARN << "Cannot restore original color of tool " << m_NavigationToolStorage->GetTool(i)->GetToolName(); - } - else - { - currentToolNode->SetColor(m_OriginalColors[currentToolNode]); - } - } - - //emit signal - emit StopTrackingFinished(true, ""); -} - -void QmitkMITKIGTTrackingToolboxViewWorker::DisconnectDevice() -{ - try - { - if (m_TrackingDeviceSource->IsTracking()) { m_TrackingDeviceSource->StopTracking(); } - m_TrackingDeviceSource->Disconnect(); - m_TrackingDeviceSource->UnRegisterMicroservice(); - m_NavigationToolStorage->UnLockStorage(); - } - catch (mitk::Exception& e) - { - emit DisconnectDeviceFinished(false, e.GetDescription()); - } - emit DisconnectDeviceFinished(true, ""); -} diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h index 318db6d8cd..2ab9c33003 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h @@ -1,305 +1,257 @@ /*=================================================================== 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 QmitkMITKIGTTrackingToolboxView_h #define QmitkMITKIGTTrackingToolboxView_h #include #include +#include #include #include "ui_QmitkMITKIGTTrackingToolboxViewControls.h" //mitk headers #include -#include #include #include #include #include #include //QT headers #include -class QmitkMITKIGTTrackingToolboxViewWorker; +#include "QmitkMITKIGTTrackingToolboxViewWorker.h" + +//Forward declaration of MITK classes +namespace mitk +{ + class NeedleProjectionFilter; +} /*! \brief QmitkMITKIGTTrackingToolboxView This is the view of the bundle IGT Tracking Toolbox. The IGT Tracking Toolbox can be used to access tracking devices with MITK-IGT. The Tracking Toolbox can be used to log tracking data in XML or CSV format for measurement purposes. The Tracking Toolbox further allows for visualization of tools with given surfaces in combination with the NaviagtionToolManager. */ class QmitkMITKIGTTrackingToolboxView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkMITKIGTTrackingToolboxView(); virtual ~QmitkMITKIGTTrackingToolboxView(); virtual void CreateQtPartControl(QWidget *parent) override; /// /// Sets the focus to an internal widget. /// virtual void SetFocus() override; protected slots: /** @brief changes name of the filename when switching fileextension by radio button */ void OnToggleFileExtension(); /** @brief This slot is called if the user wants to load a new tool file. A new window opens where the user can choose a file. If the chosen file is corrupt or not valid the user gets an error message. If the file was loaded successfully the tools are show in the tool status widget. */ void OnLoadTools(); /** Starts tracking if tracking is stopped / stops tracking if tracking is started. */ void OnStartStopTracking(); /** Connects the device if it is disconnected / disconnects the device if it is connected. */ void OnConnectDisconnect(); /** Freezes the device if it is not frozen / unfreezes the device if it is frozen. */ void OnFreezeUnfreezeTracking(); + /** @brief Shows or hides the tool projection of the standard tool axis. */ + void OnShowHideToolProjectionClicked(); + + /** @brief Shows or hides the standard tool axis. */ + void OnShowHideToolAxisClicked(); + /** @brief This slot connects to the device. In status "connected" configuration of the device is disabled. */ void OnConnect(); /** @brief This slot disconnects from the device. */ void OnDisconnect(); /** @brief This slot tries to start tracking with the current device. If start tracking fails the user gets an error message and tracking stays off.*/ void OnStartTracking(); /** @brief This slot stops tracking. If tracking is not strated it does nothing.*/ void OnStopTracking(); /** @brief This slot is called if the user want's to choose a file name for logging. A new windows to navigate through the file system and choose a file opens.*/ void OnChooseFileClicked(); /** @brief This slot starts logging. Logging is only possible if a device is tracking. If not the logging mechanism start when the start tracking is called.*/ void StartLogging(); /** @brief This slot stops logging. If logging is not running it does nothing.*/ void StopLogging(); /** @brief This slot enables / disables UI elements depending on the tracking device after a device is changed.*/ void OnTrackingDeviceChanged(); /** @brief This slot selects the Tracking Volume appropriate for a given model */ void OnTrackingVolumeChanged(QString qstr); /** @brief Shows or hides the tracking volume according to the checkboxe's state */ void OnShowTrackingVolumeChanged(); /** @brief This slot auto detects tools of a NDI Aurora tracking device. If tools where found they will be stored internally as a tool storage. The user is also asked if he wants to save this tool storage to load it later. Only call it if a Aurora device was configured because other devices don't support auto detection.*/ void OnAutoDetectTools(); /** @brief Slot for tracking timer. The timer updates the IGT pipline and also the logging filter if logging is activated.*/ void UpdateRenderTrackingTimer(); void UpdateLoggingTrackingTimer(); /** @brief Slot for showing the rendering disabled warning label*/ void OnChangeRenderUpdateRate(); /** @brief Resets the Tracking Tools: this means all tools are removed. */ void OnResetTools(); /** @brief Opens a dialog where a new navigation tool can be created. */ void OnAddSingleTool(); /** @brief This slot is called if the user finishes the creation of a new tool. */ void OnAddSingleToolFinished(); /** @brief This slot is called if the user cancels the creation of a new tool. */ void OnAddSingleToolCanceled(); void OnTimeOut(); + /** + * \brief This function is called, when anything in the ToolStorage changed, e.g. AddTool or EditTool. + * ServiceListener is connected in the QmitkMITKIGTTrackingToolboxView. + */ + void OnToolStorageChanged(const ctkServiceEvent event); + protected slots: //help slots for enable/disable buttons void DisableLoggingButtons(); void EnableLoggingButtons(); void DisableOptionsButtons(); void EnableOptionsButtons(); void EnableTrackingConfigurationButtons(); void DisableTrackingConfigurationButtons(); void EnableTrackingControls(); void DisableTrackingControls(); void EnableDisableTimerButtons(int enable); void OnToggleAdvancedSimpleMode(); void OnToggleDifferentUpdateRates(); //slots for worker thread void OnAutoDetectToolsFinished(bool success, QString errorMessage); void OnConnectFinished(bool success, QString errorMessage); void OnStartTrackingFinished(bool success, QString errorMessage); void OnStopTrackingFinished(bool success, QString errorMessage); void OnDisconnectFinished(bool success, QString errorMessage); protected: Ui::QmitkMITKIGTTrackingToolboxViewControls* m_Controls; bool m_tracking; ///> bool which is true if tracking is running, false if not bool m_connected; ///> bool that is true when a tracking device is connected bool m_logging; ///> bool which is true if logging is running, false if not + bool m_ShowHideToolProjection; ///> bool, which will be true, if the tool projection is visible during tracking + bool m_ShowHideToolAxis; ///> bool, which will be true, if the tool axis is visible during tracking int m_loggedFrames; ///> stores the current number of logged frames if logging is on mitk::NavigationToolStorage::Pointer m_toolStorage; ///>stores the loaded tools mitk::DataNode::Pointer m_TrackingVolumeNode; ///>holds the data node of the tracking volume if volume is visualized bool lastTrackingVolumeState; ///>temporary holds the state of the tracking volume (activated/not activated) during some methods QString m_ToolStorageFilename; ///>stores the filename of the current tool storage QString m_AutoSaveFilename; ///>a filename for auto saving tools if no m_ToolStorageFilename was given by the user /** @brief Shows a message box with the text given as parameter. */ void MessageBox(std::string s); /** @brief reinits the view globally. */ void GlobalReinit(); //members for the filter pipeline - mitk::TrackingDeviceSource::Pointer m_TrackingDeviceSource; ///> member for the source of the IGT pipeline mitk::TrackingDeviceData m_TrackingDeviceData; ///> stores the tracking device data as long as this is not handled by the tracking device configuration widget mitk::NavigationDataObjectVisualizationFilter::Pointer m_ToolVisualizationFilter; ///> holds the tool visualization filter (second filter of the IGT pipeline) mitk::NavigationDataRecorder::Pointer m_loggingFilter; ///> holds the logging filter if logging is on (third filter of the IGT pipeline) + itk::SmartPointer m_NeedleProjectionFilter; ///> Contains the needle projection filter which is used for displaying the tool projection and the tool axis during tracking (optional third filter of the IGT pipeline). The filter is updated in the method UpdateRenderTrackingTimer(). //members for open IGT link server mitk::NavigationDataToIGTLMessageFilter::Pointer m_IGTLConversionFilter; ///> Converts the navigation data as open IGT link message and makes this filter available as microservice mitk::IGTLServer::Pointer m_IGTLServer; mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; /** @brief This timer updates the IGT pipline and also the logging filter if logging is activated.*/ QTimer* m_TrackingRenderTimer; QTimer* m_TrackingLoggingTimer; QTimer* m_TimeoutTimer; bool m_SimpleModeEnabled; ///>Stores if simple UI mode is enabled /** Replaces the current navigation tool storage which is stored in m_toolStorage. * Basically handles the microservice stuff: unregisteres the old storage, then * replaces the storage and registers the new one. */ void ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName); /** * \brief Stores the properties of some QWidgets (and the tool storage file name) to QSettings. */ void StoreUISettings(); /** * \brief Loads the properties of some QWidgets (and the tool storage file name) from QSettings. */ void LoadUISettings(); /** * Help method for updating the tool label */ void UpdateToolStorageLabel(QString pathOfLoadedStorage); /** * Auto saves the current tool storage to a temporary file. This ist used for persistence. */ void AutoSaveToolStorage(); //members for worker thread QThread* m_WorkerThread; QmitkMITKIGTTrackingToolboxViewWorker* m_Worker; private: ctkServiceReference m_DeviceTypeServiceReference; mitk::TrackingDeviceTypeCollection* m_DeviceTypeCollection; }; -/** - * Worker thread class for this view. - */ -class QmitkMITKIGTTrackingToolboxViewWorker : public QObject -{ - Q_OBJECT - -public: - enum WorkerMethod{ - eAutoDetectTools = 0, - eConnectDevice = 1, - eStartTracking = 2, - eStopTracking = 3, - eDisconnectDevice = 4 - }; - - void SetWorkerMethod(WorkerMethod w); - void SetTrackingDevice(mitk::TrackingDevice::Pointer t); - void SetDataStorage(mitk::DataStorage::Pointer d); - void SetInverseMode(bool mode); - void SetTrackingDeviceData(mitk::TrackingDeviceData d); - void SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n); - - itkGetMacro(NavigationToolStorage,mitk::NavigationToolStorage::Pointer); - - itkGetMacro(TrackingDeviceSource,mitk::TrackingDeviceSource::Pointer); - itkGetMacro(TrackingDeviceData,mitk::TrackingDeviceData); - itkGetMacro(ToolVisualizationFilter,mitk::NavigationDataObjectVisualizationFilter::Pointer); - - public slots: - void ThreadFunc(); - - signals: - void AutoDetectToolsFinished(bool success, QString errorMessage); - void ConnectDeviceFinished(bool success, QString errorMessage); - void StartTrackingFinished(bool success, QString errorMessage); - void StopTrackingFinished(bool success, QString errorMessage); - void DisconnectDeviceFinished(bool success, QString errorMessage); - - - protected: - - mitk::TrackingDevice::Pointer m_TrackingDevice; - WorkerMethod m_WorkerMethod; - mitk::DataStorage::Pointer m_DataStorage; - mitk::NavigationToolStorage::Pointer m_NavigationToolStorage; - - //members for the filter pipeline which is created in the worker thread during ConnectDevice() - mitk::TrackingDeviceSource::Pointer m_TrackingDeviceSource; ///> member for the source of the IGT pipeline - mitk::TrackingDeviceData m_TrackingDeviceData; ///> stores the tracking device data as long as this is not handled by the tracking device configuration widget - mitk::NavigationDataObjectVisualizationFilter::Pointer m_ToolVisualizationFilter; ///> holds the tool visualization filter (second filter of the IGT pipeline) - - //members some internal flags - bool m_InverseMode; //flag that is true when the inverse mode is enabled - - //stores the original colors of the tracking tools - std::map m_OriginalColors; - - //internal methods - void AutoDetectTools(); - void ConnectDevice(); - void StartTracking(); - void StopTracking(); - void DisconnectDevice(); -}; - - - #endif // _QMITKMITKIGTTRACKINGTOOLBOXVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui index 46a7777220..b19715464c 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui @@ -1,936 +1,953 @@ QmitkMITKIGTTrackingToolboxViewControls 0 0 - 370 - 723 + 680 + 1147 0 0 QmitkTemplate 0 Tracking - + 0 0 0 0 16777215 - 280 + 220 - - - + + + - + 0 0 + 6 75 true <!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:'MS Shell Dlg 2'; font-size:7.8pt; 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-size:10pt; font-weight:600;">Tracking Tools</span></p></body></html> 0 0 ToolStorage: - + <none> Qt::Horizontal 40 20 200 - 80 + 0 Qt::Horizontal 13 49 120 0 Auto Detection 120 0 Add Single Tool 120 0 Load Tool Storage 120 0 Reset <!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:'MS Shell Dlg 2'; font-size:7.8pt; 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-size:10pt; font-weight:600;">Tracking Control</span></p></body></html> Status: disconnected Qt::Horizontal 40 20 142 0 Connect Qt::Horizontal 40 20 142 0 Start Tracking Qt::Horizontal 40 20 <html><head/><body><p><span style=" color:#ff0000;">Tracking Frozen!</span></p></body></html> true 142 0 Freeze Tracking - - - - Qt::Vertical - - - - 20 - 40 - - - - Options Disable All Timers - + true <html><head/><body><p align="right"><span style=" color:#ff0000;">Rendering Disabled!</span></p></body></html> Qt::AutoText Update Rate Options Update Rate [per second] Qt::Horizontal 40 20 100 10 Use different Render and Log Update Rates false Render Update Rate [fps] Qt::Horizontal 40 20 false 0 100 10 false Log Update Rate [per second] Qt::Horizontal 40 20 false 1 120 10 60 Tracking Volume Options true Show Tracking Volume true Select Model: Open IGT Link Enable Open IGT Link MicroService true Select Open IGT Link Data Format: TRANSFORM QTDATA TDATA POSITION Other Options Show Tool Quaternions - + Simple UI Caution, only for backward compatibility: Inverse mode (Quaternions are stored inverse) + + + + Tool Visualization Options + + + + + + true + + + Show Tool Projection + + + + + + + false + + + Show Tool Axis + + + + + + Qt::Vertical 20 600 Logging Filename: Choose File Limit Number Of Logged Frames: Qt::Horizontal 40 20 1 9999 300 - + CSV format true - + XML format Skip invalid data Logging Status Logging OFF Logged Frames: 0 Qt::Horizontal 40 20 Start Logging Stop Logging Qt::Vertical 20 40 70 50 Connect 70 50 Start Tracking Qt::Horizontal 40 20 70 50 Advanced Mode Qt::Vertical 20 40 - QmitkTrackingDeviceConfigurationWidget + QmitkToolTrackingStatusWidget QWidget -
QmitkTrackingDeviceConfigurationWidget.h
+
QmitkToolTrackingStatusWidget.h
1
- QmitkToolTrackingStatusWidget + QmitkTrackingDeviceConfigurationWidget QWidget -
QmitkToolTrackingStatusWidget.h
+
QmitkTrackingDeviceConfigurationWidget.h
1
QmitkNavigationToolCreationWidget QWidget
QmitkNavigationToolCreationWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp new file mode 100644 index 0000000000..5064dd4ef2 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.cpp @@ -0,0 +1,250 @@ +/*=================================================================== + +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. + +===================================================================*/ + +// Qmitk +#include "QmitkMITKIGTTrackingToolboxViewWorker.h" + +#include + +QmitkMITKIGTTrackingToolboxViewWorker::QmitkMITKIGTTrackingToolboxViewWorker() +{ +} + +QmitkMITKIGTTrackingToolboxViewWorker::~QmitkMITKIGTTrackingToolboxViewWorker() +{ +} + +void QmitkMITKIGTTrackingToolboxViewWorker::SetWorkerMethod(WorkerMethod w) +{ + m_WorkerMethod = w; +} + +void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) +{ + m_TrackingDevice = t; +} + +void QmitkMITKIGTTrackingToolboxViewWorker::SetDataStorage(mitk::DataStorage::Pointer d) +{ + m_DataStorage = d; +} + +void QmitkMITKIGTTrackingToolboxViewWorker::SetInverseMode(bool mode) +{ + m_InverseMode = mode; +} + +void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDeviceData(mitk::TrackingDeviceData d) +{ + m_TrackingDeviceData = d; +} + +void QmitkMITKIGTTrackingToolboxViewWorker::SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n) +{ + m_NavigationToolStorage = n; +} + +//! [Thread 7] +void QmitkMITKIGTTrackingToolboxViewWorker::ThreadFunc() +{ + switch (m_WorkerMethod) + { + case eAutoDetectTools: + this->AutoDetectTools(); + break; + case eConnectDevice: + this->ConnectDevice(); + break; + case eStartTracking: + this->StartTracking(); + break; + case eStopTracking: + this->StopTracking(); + break; + case eDisconnectDevice: + this->DisconnectDevice(); + break; + default: + MITK_WARN << "Undefined worker method was set ... something went wrong!"; + break; + } +} +//! [Thread 7] + +void QmitkMITKIGTTrackingToolboxViewWorker::AutoDetectTools() +{ + mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(m_DataStorage); + try + { + mitk::NavigationToolStorage::Pointer tempStorage = m_TrackingDevice->AutoDetectTools(); + for (unsigned int i = 0; i < tempStorage->GetToolCount(); i++) { autoDetectedStorage->AddTool(tempStorage->GetTool(i)); } + } + catch (mitk::Exception& e) + { + MITK_WARN << e.GetDescription(); + emit AutoDetectToolsFinished(false, e.GetDescription()); + return; + } + m_NavigationToolStorage = nullptr; + m_NavigationToolStorage = autoDetectedStorage; + emit AutoDetectToolsFinished(true, ""); + MITK_INFO << "AutoDetect Tools Finished."; +} + +void QmitkMITKIGTTrackingToolboxViewWorker::ConnectDevice() +{ + std::string message = ""; + + //build the IGT pipeline + mitk::TrackingDevice::Pointer trackingDevice = m_TrackingDevice; + trackingDevice->SetData(m_TrackingDeviceData); + + //set device to rotation mode transposed becaus we are working with VNL style quaternions + if (m_InverseMode) + { + trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed); + } + + //Get Tracking Volume Data + mitk::TrackingDeviceData data = m_TrackingDeviceData; + + //Create Navigation Data Source with the factory class + mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(m_NavigationToolStorage, trackingDevice); + + m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(m_ToolVisualizationFilter); + + if (m_TrackingDeviceSource.IsNull()) + { + message = std::string("Cannot connect to device: ") + myTrackingDeviceSourceFactory->GetErrorMessage(); + emit ConnectDeviceFinished(false, QString(message.c_str())); + return; + } + + //set filter to rotation mode transposed becaus we are working with VNL style quaternions + if (m_InverseMode) + m_ToolVisualizationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); + + //First check if the created object is valid + if (m_TrackingDeviceSource.IsNull()) + { + message = myTrackingDeviceSourceFactory->GetErrorMessage(); + emit ConnectDeviceFinished(false, QString(message.c_str())); + return; + } + + MITK_INFO << "Connected device with " << m_TrackingDeviceSource->GetNumberOfOutputs() << " tools."; + + //connect to device + try + { + m_TrackingDeviceSource->Connect(); + //Microservice registration: + m_TrackingDeviceSource->RegisterAsMicroservice(); + m_NavigationToolStorage->SetSourceID(m_TrackingDeviceSource->GetMicroserviceID()); + m_NavigationToolStorage->LockStorage(); + } + catch (...) //todo: change to mitk::IGTException + { + message = "Error on connecting the tracking device."; + emit ConnectDeviceFinished(false, QString(message.c_str())); + return; + } + emit ConnectDeviceFinished(true, QString(message.c_str())); +} + +mitk::TrackingDeviceSource::Pointer QmitkMITKIGTTrackingToolboxViewWorker::GetTrackingDeviceSource() +{ + return this->m_TrackingDeviceSource; +} + +void QmitkMITKIGTTrackingToolboxViewWorker::StartTracking() +{ + QString errorMessage = ""; + try + { + m_TrackingDeviceSource->StartTracking(); + } + catch (...) //todo: change to mitk::IGTException + { + errorMessage += "Error while starting the tracking device!"; + emit StartTrackingFinished(false, errorMessage); + return; + } + //remember the original colors of the tools + m_OriginalColors = std::map(); + for (unsigned int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) + { + mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); + float c[3]; + currentToolNode->GetColor(c); + mitk::Color color; + color.SetRed(c[0]); + color.SetGreen(c[1]); + color.SetBlue(c[2]); + m_OriginalColors[currentToolNode] = color; + } + + emit StartTrackingFinished(true, errorMessage); +} + +void QmitkMITKIGTTrackingToolboxViewWorker::StopTracking() +{ + //stop tracking + try + { + m_TrackingDeviceSource->StopTracking(); + } + catch (mitk::Exception& e) + { + emit StopTrackingFinished(false, e.GetDescription()); + } + + //restore the original colors of the tools + for (unsigned int i = 0; i < this->m_NavigationToolStorage->GetToolCount(); i++) + { + mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); + if (m_OriginalColors.find(currentToolNode) == m_OriginalColors.end()) + { + MITK_WARN << "Cannot restore original color of tool " << m_NavigationToolStorage->GetTool(i)->GetToolName(); + } + else + { + currentToolNode->SetColor(m_OriginalColors[currentToolNode]); + } + } + + //emit signal + emit StopTrackingFinished(true, ""); +} + +void QmitkMITKIGTTrackingToolboxViewWorker::DisconnectDevice() +{ + try + { + if (m_TrackingDeviceSource->IsTracking()) { m_TrackingDeviceSource->StopTracking(); } + m_TrackingDeviceSource->Disconnect(); + m_TrackingDeviceSource->UnRegisterMicroservice(); + + m_NavigationToolStorage->UnLockStorage(); + + m_TrackingDeviceSource = nullptr; + } + catch (mitk::Exception& e) + { + emit DisconnectDeviceFinished(false, e.GetDescription()); + } + emit DisconnectDeviceFinished(true, ""); +} diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.h new file mode 100644 index 0000000000..97460b7824 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewWorker.h @@ -0,0 +1,98 @@ +/*=================================================================== + +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 QmitkMITKIGTTrackingToolboxViewWorker_h +#define QmitkMITKIGTTrackingToolboxViewWorker_h + +#include + +//mitk headers +#include +#include +#include + +//QT headers +#include + +/** + * Worker thread class for QmitkMITKIGTTrackingToolboxView view. + */ +class QmitkMITKIGTTrackingToolboxViewWorker : public QObject +{ + Q_OBJECT + +public: + enum WorkerMethod{ + eAutoDetectTools = 0, + eConnectDevice = 1, + eStartTracking = 2, + eStopTracking = 3, + eDisconnectDevice = 4 + }; + + QmitkMITKIGTTrackingToolboxViewWorker(); + ~QmitkMITKIGTTrackingToolboxViewWorker(); + + void SetWorkerMethod(WorkerMethod w); + void SetTrackingDevice(mitk::TrackingDevice::Pointer t); + void SetDataStorage(mitk::DataStorage::Pointer d); + void SetInverseMode(bool mode); + void SetTrackingDeviceData(mitk::TrackingDeviceData d); + void SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n); + + itkGetMacro(NavigationToolStorage, mitk::NavigationToolStorage::Pointer); + + mitk::TrackingDeviceSource::Pointer GetTrackingDeviceSource(); + itkGetMacro(TrackingDeviceData, mitk::TrackingDeviceData); + itkGetMacro(ToolVisualizationFilter, mitk::NavigationDataObjectVisualizationFilter::Pointer); + + public slots: + void ThreadFunc(); + +signals: + void AutoDetectToolsFinished(bool success, QString errorMessage); + void ConnectDeviceFinished(bool success, QString errorMessage); + void StartTrackingFinished(bool success, QString errorMessage); + void StopTrackingFinished(bool success, QString errorMessage); + void DisconnectDeviceFinished(bool success, QString errorMessage); + +protected: + + mitk::TrackingDevice::Pointer m_TrackingDevice; + WorkerMethod m_WorkerMethod; + mitk::DataStorage::Pointer m_DataStorage; + mitk::NavigationToolStorage::Pointer m_NavigationToolStorage; + + //members for the filter pipeline which is created in the worker thread during ConnectDevice() + mitk::TrackingDeviceSource::Pointer m_TrackingDeviceSource; ///> member for the source of the IGT pipeline + mitk::TrackingDeviceData m_TrackingDeviceData; ///> stores the tracking device data as long as this is not handled by the tracking device configuration widget + mitk::NavigationDataObjectVisualizationFilter::Pointer m_ToolVisualizationFilter; ///> holds the tool visualization filter (second filter of the IGT pipeline) + + //members some internal flags + bool m_InverseMode; //flag that is true when the inverse mode is enabled + + //stores the original colors of the tracking tools + std::map m_OriginalColors; + + //internal methods + void AutoDetectTools(); + void ConnectDevice(); + void StartTracking(); + void StopTracking(); + void DisconnectDevice(); +}; + +#endif // _QMITKMITKIGTTRACKINGTOOLBOXVIEWWorker_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp index 6a3b71d04d..0d9f85a552 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp @@ -1,240 +1,240 @@ /*=================================================================== 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. ===================================================================*/ // Qmitk #include "QmitkNavigationDataPlayerView.h" // QT #include #include //mitk #include #include #include #include #include #include // VTK #include const std::string QmitkNavigationDataPlayerView::VIEW_ID = "org.mitk.views.navigationdataplayer"; QmitkNavigationDataPlayerView::QmitkNavigationDataPlayerView() : m_Controls( 0 ) { } QmitkNavigationDataPlayerView::~QmitkNavigationDataPlayerView() { } void QmitkNavigationDataPlayerView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkNavigationDataPlayerViewControls; m_Controls->setupUi( parent ); this->CreateConnections(); // make deselected Player invisible m_Controls->m_TimedWidget->setVisible(false); } } void QmitkNavigationDataPlayerView::SetFocus() { if ( m_Controls ) { m_Controls->m_grpbxControls->setFocus(); } } void QmitkNavigationDataPlayerView::CreateConnections() { connect( m_Controls->m_RdbSequential, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); connect( m_Controls->m_RdbTimeBased, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); connect( m_Controls->m_BtnOpenFile, SIGNAL(released()), this, SLOT(OnOpenFile()) ); connect( m_Controls->m_ChkDisplay, SIGNAL(released()), this, SLOT(OnSetDisplay()) ); connect( m_Controls->m_chkRepeat, SIGNAL(stateChanged(int)), this, SLOT(OnSetRepeat(int)) ); connect( m_Controls->m_ChkMicroservice, SIGNAL(released()), this, SLOT(OnSetMicroservice()) ); connect( m_Controls->m_SequentialWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); connect( m_Controls->m_TimedWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); this->SetInteractionComponentsEnabledState(false); } void QmitkNavigationDataPlayerView::OnOpenFile() { mitk::NavigationDataReaderInterface::Pointer reader = nullptr; QString filter = tr("NavigationData File (*.csv *.xml)"); QString fileName = QFileDialog::getOpenFileName(nullptr, tr("Open NavigationData Set"), "", filter); if ( fileName.isNull() ) { return; } // user pressed cancel try { m_Data = dynamic_cast (mitk::IOUtil::Load(fileName.toStdString())[0].GetPointer()); } catch ( const mitk::Exception &e ) { MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); QMessageBox::critical(0, "Error Reading File", "The file '" + fileName +"' could not be read.\n" + e.GetDescription() ); return; } if (m_Controls->m_ChkConvertToPointSet->isChecked()) m_Data->ConvertNavigationDataToPointSet(); // Update Labels m_Controls->m_LblFilePath->setText(fileName); m_Controls->m_LblFrames->setText(QString::number(m_Data->Size())); m_Controls->m_LblTools->setText(QString::number(m_Data->GetNumberOfTools())); // Initialize Widgets and create Player this->OnSelectPlayer(); this->SetInteractionComponentsEnabledState(true); } void QmitkNavigationDataPlayerView::OnSelectPlayer() { if (m_Controls->m_RdbSequential->isChecked()) { m_Controls->m_SequentialWidget->setVisible(true); m_Controls->m_TimedWidget->setVisible(false); mitk::NavigationDataSequentialPlayer::Pointer seqPlayer = mitk::NavigationDataSequentialPlayer::New(); seqPlayer->SetNavigationDataSet(m_Data); m_Controls->m_SequentialWidget->SetPlayer(seqPlayer); m_Player = seqPlayer; } else { m_Controls->m_SequentialWidget->setVisible(false); m_Controls->m_TimedWidget->setVisible(true); mitk::NavigationDataPlayer::Pointer timedPlayer = mitk::NavigationDataPlayer::New(); timedPlayer->SetNavigationDataSet(m_Data); m_Controls->m_TimedWidget->SetPlayer(timedPlayer); m_Player = timedPlayer; } this->ConfigurePlayer(); // SetupRenderingPipeline this->OnSetDisplay(); } void QmitkNavigationDataPlayerView::ConfigurePlayer() { // set repeat mode according to the checkbox m_Player->SetRepeat( m_Controls->m_chkRepeat->isChecked() ); } void QmitkNavigationDataPlayerView::OnSetRepeat(int checkState) { m_Player->SetRepeat(checkState != 0); } void QmitkNavigationDataPlayerView::OnSetMicroservice(){ if(m_Controls->m_ChkMicroservice->isChecked()) { m_ToolStorage = mitk::NavigationToolStorage::New(); for (itk::ProcessObject::DataObjectPointerArraySizeType i = 0; i < m_Player->GetNumberOfIndexedOutputs(); i++) { mitk::NavigationTool::Pointer currentDummyTool = mitk::NavigationTool::New(); mitk::VirtualTrackingTool::Pointer dummyTool = mitk::VirtualTrackingTool::New(); std::stringstream name; name << "Virtual Tool " << i; dummyTool->SetToolName(name.str()); - currentDummyTool->SetTrackingTool(dummyTool.GetPointer()); currentDummyTool->SetDataNode(m_RenderingNodes.at(i)); currentDummyTool->SetIdentifier(name.str()); m_ToolStorage->AddTool(currentDummyTool); } m_Player->RegisterAsMicroservice(); m_ToolStorage->SetName("NavigationDataPlayer Tool Storage"); - m_ToolStorage->RegisterAsMicroservice(m_Player->GetMicroserviceID()); + m_ToolStorage->SetSourceID(m_Player->GetMicroserviceID()); + m_ToolStorage->RegisterAsMicroservice(); } else { if (m_ToolStorage.IsNotNull()) m_ToolStorage->UnRegisterMicroservice(); m_ToolStorage = nullptr; m_Player->UnRegisterMicroservice(); } } void QmitkNavigationDataPlayerView::OnUpdate(){ if (m_VisFilter.IsNotNull()) { m_VisFilter->Update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkNavigationDataPlayerView::OnSetDisplay(){ DestroyPipeline(); if ( (m_Controls->m_ChkDisplay->isChecked()) && ( m_Player.IsNotNull() )) { CreatePipeline(); } } void QmitkNavigationDataPlayerView::CreatePipeline(){ m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); m_VisFilter->ConnectTo(m_Player); for (unsigned int i = 0 ; i < m_Player->GetNumberOfIndexedOutputs(); i++ ) { mitk::DataNode::Pointer node = mitk::DataNode::New(); QString name = "Recorded Tool " + QString::number(i + 1); node->SetName(name.toStdString()); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(5.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); node->SetData(mySphere); m_VisFilter->SetRepresentationObject(i, mySphere); // Add Node to DataStorageand to local list of Nodes GetDataStorage()->Add(node); m_RenderingNodes.push_back(node); } m_VisFilter->Update(); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkNavigationDataPlayerView::DestroyPipeline(){ m_VisFilter = nullptr; for (unsigned int i = 0; i < m_RenderingNodes.size(); i++){ this->GetDataStorage()->Remove(m_RenderingNodes[i]); } m_RenderingNodes.clear(); } void QmitkNavigationDataPlayerView::SetInteractionComponentsEnabledState(bool isActive){ m_Controls->m_grpbxSettings->setEnabled(isActive); m_Controls->m_grpbxControls->setEnabled(isActive); } diff --git a/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManager.cpp b/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManager.cpp index 29dc0c5b06..238bf79625 100644 --- a/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManager.cpp +++ b/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManager.cpp @@ -1,100 +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. ===================================================================*/ // Blueberry #include #include // #include "OpenIGTLinkManager.h" const std::string OpenIGTLinkManager::VIEW_ID = "org.mitk.views.openigtlinkmanager"; OpenIGTLinkManager::OpenIGTLinkManager() : QmitkAbstractView() { } OpenIGTLinkManager::~OpenIGTLinkManager() { for(unsigned int i=0; i < m_AllSourcesHandledByThisWidget.size(); i++) m_AllSourcesHandledByThisWidget.at(i)->UnRegisterMicroservice(); } void OpenIGTLinkManager::SetFocus() { } void OpenIGTLinkManager::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // create GUI widgets from the Qt Designer's .ui file // connect( (QObject*)(m_Controls.m_SourceManagerWidget), // SIGNAL(NewSourceAdded(mitk::IGTLDeviceSource::Pointer, std::string)), // this, // SLOT(NewSourceByWidget(mitk::IGTLDeviceSource::Pointer,std::string)) ); connect( (QObject*)(m_Controls.m_SourceListWidget), SIGNAL(IGTLDeviceSourceSelected(mitk::IGTLDeviceSource::Pointer)), this, SLOT(SourceSelected(mitk::IGTLDeviceSource::Pointer)) ); - connect(m_Controls.checkBoxLogMessages, SIGNAL(clicked()), this, SLOT(LogMessagesClicked())); - - logMessages = m_Controls.checkBoxLogMessages->isChecked(); } void OpenIGTLinkManager::NewSourceByWidget( mitk::IGTLDeviceSource::Pointer source,std::string /*sourceName*/) { source->RegisterAsMicroservice(/*sourceName*/); m_AllSourcesHandledByThisWidget.push_back(source); } -void OpenIGTLinkManager::LogMessagesClicked() -{ - logMessages = m_Controls.checkBoxLogMessages->isChecked(); - if(m_CurrentIGTLDevice.IsNotNull()) - m_CurrentIGTLDevice->SetLogMessages(logMessages); - else - MITK_WARN << "Logging information not passed down to Message Provider."; -} - void OpenIGTLinkManager::SourceSelected( mitk::IGTLDeviceSource::Pointer source) { if (source.IsNull()) //no source selected { //reset everything return; } m_CurrentIGTLDevice = source->GetIGTLDevice(); - m_CurrentIGTLDevice->SetLogMessages(logMessages); this->m_Controls.m_SourceManagerWidget->LoadSource(source); //check if the current selected source is also a message provider mitk::IGTLMessageProvider::Pointer currentMsgProvider = mitk::IGTLMessageProvider::New(); currentMsgProvider = dynamic_cast(source.GetPointer()); if(currentMsgProvider.IsNull()) return; this->m_Controls.m_StreamManagerWidget->LoadSource(currentMsgProvider); } diff --git a/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManager.h b/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManager.h index 6e5765f4a4..259daf2f09 100644 --- a/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManager.h +++ b/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManager.h @@ -1,76 +1,73 @@ /*=================================================================== 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 OpenIGTLinkManager_h #define OpenIGTLinkManager_h #include #include #include "ui_OpenIGTLinkManagerControls.h" #include "mitkIGTLClient.h" #include "mitkIGTLDeviceSource.h" /** \brief OpenIGTLinkManager \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class OpenIGTLinkManager : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; OpenIGTLinkManager(); virtual ~OpenIGTLinkManager(); public slots: void NewSourceByWidget(mitk::IGTLDeviceSource::Pointer source, std::string); void SourceSelected(mitk::IGTLDeviceSource::Pointer source); - void LogMessagesClicked(); protected: virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; void CreatePipeline(); void DestroyPipeline(); Ui::OpenIGTLinkManagerControls m_Controls; /** Someone needs to hold the smart pointers of new sources, otherwise the * objects will be lost although they are listed as microservice. */ std::vector m_AllSourcesHandledByThisWidget; - bool logMessages; - mitk::IGTLDevice::Pointer m_CurrentIGTLDevice; }; #endif // OpenIGTLinkManager_h diff --git a/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManagerControls.ui b/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManagerControls.ui index e83ddbb914..c112355b49 100644 --- a/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManagerControls.ui +++ b/Plugins/org.mitk.gui.qt.openigtlink/src/internal/OpenIGTLinkManagerControls.ui @@ -1,105 +1,98 @@ OpenIGTLinkManagerControls 0 0 668 392 0 0 QmitkTemplate 12 75 true Select OpenIGTLink device source: 12 75 true Manage device: - - - - Log incoming / outgoing messages - - - 12 75 true Manage streams of selected device source: QmitkIGTLDeviceSourceSelectionWidget QTextEdit
QmitkIGTLDeviceSourceSelectionWidget.h
QmitkIGTLDeviceSourceManagementWidget QWidget
QmitkIGTLDeviceSourceManagementWidget.h
1
QmitkIGTLStreamingManagementWidget QWidget
QmitkIGTLStreamingManagementWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp index fd93be11be..ec17ff1d2e 100644 --- a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp +++ b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp @@ -1,525 +1,530 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include #include // Qmitk #include "QmitkToFUtilView.h" // Qt #include #include #include #include #include // MITK #include #include #include #include #include #include #include #include #include #include // VTK #include #include #include // ITK #include #include const std::string QmitkToFUtilView::VIEW_ID = "org.mitk.views.tofutil"; //Constructor QmitkToFUtilView::QmitkToFUtilView() : QmitkAbstractView() , m_Controls(nullptr) + , m_Framerateoutput(false) , m_MitkDistanceImage(nullptr), m_MitkAmplitudeImage(nullptr), m_MitkIntensityImage(nullptr), m_Surface(nullptr) , m_DistanceImageNode(nullptr), m_AmplitudeImageNode(nullptr), m_IntensityImageNode(nullptr), m_RGBImageNode(nullptr), m_SurfaceNode(nullptr) , m_ToFImageRecorder(nullptr), m_ToFImageGrabber(nullptr), m_ToFDistanceImageToSurfaceFilter(nullptr), m_ToFCompositeFilter(nullptr) , m_2DDisplayCount(0) , m_RealTimeClock(nullptr) , m_StepsForFramerate(100) , m_2DTimeBefore(0.0) , m_2DTimeAfter(0.0) , m_CameraIntrinsics(nullptr) { this->m_Frametimer = new QTimer(this); this->m_ToFDistanceImageToSurfaceFilter = mitk::ToFDistanceImageToSurfaceFilter::New(); this->m_ToFCompositeFilter = mitk::ToFCompositeFilter::New(); this->m_ToFImageRecorder = mitk::ToFImageRecorder::New(); } //Destructor, specifically calling OnToFCameraStopped() and OnToFCammeraDiconnected() QmitkToFUtilView::~QmitkToFUtilView() { OnToFCameraStopped(); OnToFCameraDisconnected(); } //Createing the PartControl Signal-Slot principal void QmitkToFUtilView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkToFUtilViewControls; m_Controls->setupUi( parent ); //Looking for Input and Defining reaction connect(m_Frametimer, SIGNAL(timeout()), this, SLOT(OnUpdateCamera())); connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(KinectAcquisitionModeChanged()), this, SLOT(OnKinectAcquisitionModeChanged()) ); // Todo in Widget2 connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(ToFCameraConnected()), this, SLOT(OnToFCameraConnected()) ); connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(ToFCameraDisconnected()), this, SLOT(OnToFCameraDisconnected()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(ToFCameraStarted()), this, SLOT(OnToFCameraStarted()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(ToFCameraStopped()), this, SLOT(OnToFCameraStopped()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(RecordingStarted()), this, SLOT(OnToFCameraStopped()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(RecordingStopped()), this, SLOT(OnToFCameraStarted()) ); } } //SetFocus-Method -> actually seting Focus to the Recorder void QmitkToFUtilView::SetFocus() { m_Controls->m_ToFRecorderWidget->setFocus(); } //Activated-Method->Generating RenderWindow void QmitkToFUtilView::Activated() { //get the current RenderWindowPart or open a new one if there is none if (this->GetRenderWindowPart(OPEN)) { mitk::ILinkedRenderWindowPart* linkedRenderWindowPart = dynamic_cast(this->GetRenderWindowPart()); if (linkedRenderWindowPart == 0) { MITK_ERROR << "No linked render window part avaiable!!!"; } else { linkedRenderWindowPart->EnableSlicingPlanes(false); } GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SliceLockedOn(); GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SliceLockedOn(); GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SliceLockedOn(); mitk::RenderingManager::GetInstance()->InitializeViews(); this->UseToFVisibilitySettings(true); if (this->m_ToFCompositeFilter) { m_Controls->m_ToFCompositeFilterWidget->SetToFCompositeFilter(this->m_ToFCompositeFilter); } if (this->GetDataStorage()) { m_Controls->m_ToFCompositeFilterWidget->SetDataStorage(this->GetDataStorage()); } if (this->m_ToFImageGrabber.IsNull()) { m_Controls->m_ToFRecorderWidget->setEnabled(false); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); m_Controls->m_ToFCompositeFilterWidget->setEnabled(false); m_Controls->m_ToFMeasurementWidget->setEnabled(false); m_Controls->m_ToFSurfaceGenerationWidget->setEnabled(false); } } } //ZomnnieView-Method -> Resetting GUI to default. Why not just QmitkToFUtilView()?! void QmitkToFUtilView::ActivatedZombieView(berry::IWorkbenchPartReference::Pointer /*zombieView*/) { ResetGUIToDefault(); } void QmitkToFUtilView::Deactivated() { } void QmitkToFUtilView::Visible() { } //Reset of the ToFUtilView void QmitkToFUtilView::Hidden() { ResetGUIToDefault(); } void QmitkToFUtilView::OnToFCameraConnected() { MITK_DEBUG <<"OnToFCameraConnected"; this->m_2DDisplayCount = 0; this->m_ToFImageGrabber = m_Controls->m_ToFConnectionWidget->GetToFImageGrabber(); // initialize surface generation this->m_ToFDistanceImageToSurfaceFilter = mitk::ToFDistanceImageToSurfaceFilter::New(); // initialize ToFImageRecorder and ToFRecorderWidget this->m_ToFImageRecorder = mitk::ToFImageRecorder::New(); this->m_ToFImageRecorder->SetCameraDevice(this->m_ToFImageGrabber->GetCameraDevice()); m_Controls->m_ToFRecorderWidget->SetParameter(this->m_ToFImageGrabber, this->m_ToFImageRecorder); m_Controls->m_ToFRecorderWidget->setEnabled(true); m_Controls->m_ToFRecorderWidget->ResetGUIToInitial(); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); // initialize ToFCompositeFilterWidget this->m_ToFCompositeFilter = mitk::ToFCompositeFilter::New(); if (this->m_ToFCompositeFilter) { m_Controls->m_ToFCompositeFilterWidget->SetToFCompositeFilter(this->m_ToFCompositeFilter); } if (this->GetDataStorage()) { m_Controls->m_ToFCompositeFilterWidget->SetDataStorage(this->GetDataStorage()); } if ( this->GetRenderWindowPart() ) // initialize measurement widget m_Controls->m_ToFMeasurementWidget->InitializeWidget(this->GetRenderWindowPart()->GetQmitkRenderWindows(),this->GetDataStorage(), this->m_ToFDistanceImageToSurfaceFilter->GetCameraIntrinsics()); else MITK_WARN << "No render window part available!!! MeasurementWidget will not work."; this->m_RealTimeClock = mitk::RealTimeClock::New(); this->m_2DTimeBefore = this->m_RealTimeClock->GetCurrentStamp(); this->RequestRenderWindowUpdate(); } void QmitkToFUtilView::ResetGUIToDefault() { if(this->GetRenderWindowPart()) { mitk::ILinkedRenderWindowPart* linkedRenderWindowPart = dynamic_cast(this->GetRenderWindowPart()); if(linkedRenderWindowPart == 0) { MITK_ERROR << "No linked render window part avaiable!!!"; } else { linkedRenderWindowPart->EnableSlicingPlanes(true); } GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SliceLockedOff(); GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SliceLockedOff(); GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Frontal); GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SliceLockedOff(); this->UseToFVisibilitySettings(false); //global reinit mitk::RenderingManager::GetInstance()->InitializeViews(); this->RequestRenderWindowUpdate(); } } void QmitkToFUtilView::OnToFCameraDisconnected() { this->GetDataStorage()->Remove(m_DistanceImageNode); if(m_RGBImageNode) this->GetDataStorage()->Remove(m_RGBImageNode); if(m_AmplitudeImageNode) this->GetDataStorage()->Remove(m_AmplitudeImageNode); if(m_IntensityImageNode) this->GetDataStorage()->Remove(m_IntensityImageNode); if(m_SurfaceNode) this->GetDataStorage()->Remove(m_SurfaceNode); m_Controls->m_ToFRecorderWidget->OnStop(); m_Controls->m_ToFRecorderWidget->setEnabled(false); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); m_Controls->m_ToFMeasurementWidget->setEnabled(false); m_Controls->m_ToFSurfaceGenerationWidget->setEnabled(false); //clean up measurement widget m_Controls->m_ToFMeasurementWidget->CleanUpWidget(); } void QmitkToFUtilView::OnKinectAcquisitionModeChanged() { if (m_ToFCompositeFilter.IsNotNull()&&m_ToFImageGrabber.IsNotNull()) { if (m_SelectedCamera.contains("Kinect")) { if (m_ToFImageGrabber->GetBoolProperty("RGB")) { this->m_RGBImageNode = ReplaceNodeData("RGB image",this->m_ToFImageGrabber->GetOutput(3)); this->m_ToFDistanceImageToSurfaceFilter->SetInput(3,this->m_ToFImageGrabber->GetOutput(3)); } else if (m_ToFImageGrabber->GetBoolProperty("IR")) { this->m_MitkAmplitudeImage = m_ToFCompositeFilter->GetOutput(1); this->m_AmplitudeImageNode = ReplaceNodeData("Amplitude image",m_MitkAmplitudeImage); } } this->UseToFVisibilitySettings(true); } } void QmitkToFUtilView::OnToFCameraStarted() { if (m_ToFImageGrabber.IsNotNull()) { // initialize camera intrinsics if (this->m_ToFImageGrabber->GetProperty("CameraIntrinsics")) { m_CameraIntrinsics = dynamic_cast(this->m_ToFImageGrabber->GetProperty("CameraIntrinsics"))->GetValue(); MITK_INFO << m_CameraIntrinsics->ToString(); } else { m_CameraIntrinsics = nullptr; MITK_ERROR << "No camera intrinsics were found!"; } // set camera intrinsics if ( m_CameraIntrinsics.IsNotNull() ) { this->m_ToFDistanceImageToSurfaceFilter->SetCameraIntrinsics(m_CameraIntrinsics); } // initial update of image grabber this->m_ToFImageGrabber->Update(); bool hasRGBImage = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("HasRGBImage",hasRGBImage); bool hasIntensityImage = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("HasIntensityImage",hasIntensityImage); bool hasAmplitudeImage = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("HasAmplitudeImage",hasAmplitudeImage); this->m_ToFCompositeFilter->SetInput(0,this->m_ToFImageGrabber->GetOutput(0)); if(hasAmplitudeImage) this->m_ToFCompositeFilter->SetInput(1,this->m_ToFImageGrabber->GetOutput(1)); if(hasIntensityImage) this->m_ToFCompositeFilter->SetInput(2,this->m_ToFImageGrabber->GetOutput(2)); // initial update of composite filter this->m_ToFCompositeFilter->Update(); this->m_MitkDistanceImage = m_ToFCompositeFilter->GetOutput(); this->m_DistanceImageNode = ReplaceNodeData("Distance image",m_MitkDistanceImage); std::string rgbFileName; m_ToFImageGrabber->GetCameraDevice()->GetStringProperty("RGBImageFileName",rgbFileName); if(hasRGBImage || (rgbFileName!="")) { if(m_ToFImageGrabber->GetBoolProperty("IR")) { this->m_MitkAmplitudeImage = m_ToFCompositeFilter->GetOutput(1); } else { this->m_RGBImageNode = ReplaceNodeData("RGB image",this->m_ToFImageGrabber->GetOutput(3)); } } else { this->m_RGBImageNode = nullptr; } if(hasAmplitudeImage) { this->m_MitkAmplitudeImage = m_ToFCompositeFilter->GetOutput(1); this->m_AmplitudeImageNode = ReplaceNodeData("Amplitude image",m_MitkAmplitudeImage); } if(hasIntensityImage) { this->m_MitkIntensityImage = m_ToFCompositeFilter->GetOutput(2); this->m_IntensityImageNode = ReplaceNodeData("Intensity image",m_MitkIntensityImage); } this->m_ToFDistanceImageToSurfaceFilter->SetInput(0,m_MitkDistanceImage); this->m_ToFDistanceImageToSurfaceFilter->SetInput(1,m_MitkAmplitudeImage); this->m_ToFDistanceImageToSurfaceFilter->SetInput(2,m_MitkIntensityImage); this->UseToFVisibilitySettings(true); this->m_SurfaceNode = ReplaceNodeData("Surface", nullptr); m_Controls->m_ToFCompositeFilterWidget->UpdateFilterParameter(); // initialize visualization widget m_Controls->m_ToFVisualisationSettingsWidget->Initialize(this->m_DistanceImageNode, this->m_AmplitudeImageNode, this->m_IntensityImageNode, this->m_SurfaceNode); m_Controls->m_ToFSurfaceGenerationWidget->Initialize(m_ToFDistanceImageToSurfaceFilter, m_ToFImageGrabber, m_CameraIntrinsics, m_SurfaceNode, GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderer()->GetVtkRenderer()->GetActiveCamera()); // set distance image to measurement widget m_Controls->m_ToFMeasurementWidget->SetDistanceImage(m_MitkDistanceImage); - this->m_Frametimer->start(0); + this->m_Frametimer->start(50); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(true); m_Controls->m_ToFCompositeFilterWidget->setEnabled(true); m_Controls->m_ToFMeasurementWidget->setEnabled(true); m_Controls->m_ToFSurfaceGenerationWidget->setEnabled(true); } } void QmitkToFUtilView::OnToFCameraStopped() { m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); m_Controls->m_ToFCompositeFilterWidget->setEnabled(false); this->m_Frametimer->stop(); } void QmitkToFUtilView::OnUpdateCamera() { if(!m_Controls->m_ToFSurfaceGenerationWidget->UpdateSurface()) { // update pipeline this->m_MitkDistanceImage->Update(); } this->RequestRenderWindowUpdate(); - this->m_2DDisplayCount++; - if ((this->m_2DDisplayCount % this->m_StepsForFramerate) == 0) + if (m_Framerateoutput) { - this->m_2DTimeAfter = this->m_RealTimeClock->GetCurrentStamp() - this->m_2DTimeBefore; - MITK_INFO << " 2D-Display-framerate (fps): " << this->m_StepsForFramerate / (this->m_2DTimeAfter/1000); - this->m_2DTimeBefore = this->m_RealTimeClock->GetCurrentStamp(); + this->m_2DDisplayCount++; + if ((this->m_2DDisplayCount % this->m_StepsForFramerate) == 0) + { + this->m_2DTimeAfter = this->m_RealTimeClock->GetCurrentStamp() - this->m_2DTimeBefore; + MITK_INFO << " 2D-Display-framerate (fps): " << this->m_StepsForFramerate / (this->m_2DTimeAfter / 1000); + this->m_2DTimeBefore = this->m_RealTimeClock->GetCurrentStamp(); + } } + } void QmitkToFUtilView::OnChangeCoronalWindowOutput(int index) { this->OnToFCameraStopped(); if(index == 0) { if(this->m_IntensityImageNode.IsNotNull()) this->m_IntensityImageNode->SetVisibility(false); if(this->m_RGBImageNode.IsNotNull()) this->m_RGBImageNode->SetVisibility(true); } else if(index == 1) { if(this->m_IntensityImageNode.IsNotNull()) this->m_IntensityImageNode->SetVisibility(true); if(this->m_RGBImageNode.IsNotNull()) this->m_RGBImageNode->SetVisibility(false); } this->RequestRenderWindowUpdate(); this->OnToFCameraStarted(); } mitk::DataNode::Pointer QmitkToFUtilView::ReplaceNodeData( std::string nodeName, mitk::BaseData* data ) { mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode(nodeName); if (node.IsNull()) { node = mitk::DataNode::New(); node->SetName(nodeName); node->SetBoolProperty("binary",false); node->SetData(data); this->GetDataStorage()->Add(node); } else { node->SetData(data); } return node; } void QmitkToFUtilView::UseToFVisibilitySettings(bool useToF) { //We need this property for every node. mitk::RenderingModeProperty::Pointer renderingModePropertyForTransferFunction = mitk::RenderingModeProperty::New(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR); // set node properties if (m_DistanceImageNode.IsNotNull()) { this->m_DistanceImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetRenderWindow() ) ); this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetRenderWindow() ) ); this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); this->m_DistanceImageNode->SetProperty("Image Rendering.Mode", renderingModePropertyForTransferFunction); } if (m_AmplitudeImageNode.IsNotNull()) { this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetRenderWindow() ) ); this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetRenderWindow() ) ); this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); this->m_AmplitudeImageNode->SetProperty("Image Rendering.Mode", renderingModePropertyForTransferFunction); } if (m_IntensityImageNode.IsNotNull()) { this->m_IntensityImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetRenderWindow() ) ); this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetRenderWindow() ) ); this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); this->m_IntensityImageNode->SetProperty("Image Rendering.Mode", renderingModePropertyForTransferFunction); } if ((m_RGBImageNode.IsNotNull())) { this->m_RGBImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetRenderWindow() ) ); this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetRenderWindow() ) ); this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); } // initialize images if (m_MitkDistanceImage.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( this->m_MitkDistanceImage->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS, true); } if(this->m_SurfaceNode.IsNotNull()) { QHash renderWindowHashMap = this->GetRenderWindowPart()->GetQmitkRenderWindows(); QHashIterator i(renderWindowHashMap); while (i.hasNext()){ i.next(); this->m_SurfaceNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(i.value()->GetRenderWindow()) ); } this->m_SurfaceNode->SetVisibility( true, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); } //disable/enable gradient background this->GetRenderWindowPart()->EnableDecorations(!useToF, QStringList(QString("background"))); if((this->m_RGBImageNode.IsNotNull())) { bool RGBImageHasDifferentResolution = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("RGBImageHasDifferentResolution",RGBImageHasDifferentResolution); if(RGBImageHasDifferentResolution) { //update the display geometry by using the RBG image node. Only for renderwindow coronal mitk::RenderingManager::GetInstance()->InitializeView( GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetRenderWindow(), this->m_RGBImageNode->GetData()->GetGeometry() ); } } } diff --git a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.h b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.h index 914b629772..379cc7b1a1 100644 --- a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.h +++ b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.h @@ -1,167 +1,168 @@ /*=================================================================== 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 QmitkToFUtilView_h #define QmitkToFUtilView_h #include #include #include #include class QTimer; #include #include #include #include #include #include #include #include /*! \brief QmitkToFUtilView Application that allows simple playing, recording, visualization, processing and measurement of Time-of-Flight (ToF) data. Currently the following features are implemented:
  • Connecting and showing ToF data from various cameras (PMD CamCube 2/3, PMD CamBoard, PMD O3, MESA SwissRanger)
  • Recording and playing of ToF data
  • Color coded visualization of ToF images
  • Preprocessing of the distance data: Threshold, median, average and bilateral filtering; surface generation
  • Simple measurement and PointSet definition
*/ class QmitkToFUtilView : public QmitkAbstractView, public mitk::IZombieViewPart { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFUtilView(); ~QmitkToFUtilView(); - virtual void CreateQtPartControl(QWidget *parent) override; /// \brief Called when the view gets activated. virtual void Activated() override; /// \brief Called when the view gets deactivated. In this case the zombie view of this view becomes active! virtual void ActivatedZombieView(berry::IWorkbenchPartReference::Pointer zombieView) override; virtual void Deactivated() override; virtual void Visible() override; virtual void Hidden() override; void SetFocus() override; protected slots: /*! \brief Slot triggered from the timer to update the images and visualization */ void OnUpdateCamera(); /*! \brief Slot called when the "Connect" button of the ConnectionWidget is pressed */ void OnToFCameraConnected(); /*! \brief Slot called when the "Disconnect" button of the ConnectionWidget is pressed */ void OnToFCameraDisconnected(); /*! \brief Slot called when the "Start" button of the RecorderWidget is pressed */ void OnToFCameraStarted(); /*! \brief Slot called when the "Stop" button of the RecorderWidget is pressed */ void OnToFCameraStopped(); /*! \brief Slot invoked when user alters the coronal window input from RGB to Intensity or vice versa. */ void OnChangeCoronalWindowOutput(int index); /*! \brief Slot invoked when acquisition mode of Kinect is changed */ void OnKinectAcquisitionModeChanged(); protected: /*! \brief initialize the visibility settings of ToF data (images + surface) \param useToF true: distance image: widget1, amplitude image: widget 2, intensity image: widget 3; false: standard */ void UseToFVisibilitySettings(bool useToF); Ui::QmitkToFUtilViewControls* m_Controls; + bool m_Framerateoutput; ///< defines if the framerate is computed condinously + QTimer* m_Frametimer; ///< Timer used to continuously update the images QString m_SelectedCamera; ///< String holding the selected camera mitk::Image::Pointer m_MitkDistanceImage; ///< member holding a pointer to the distance image of the selected camera mitk::Image::Pointer m_MitkAmplitudeImage; ///< member holding a pointer to the amplitude image of the selected camera mitk::Image::Pointer m_MitkIntensityImage; ///< member holding a pointer to the intensity image of the selected camera mitk::Surface::Pointer m_Surface; ///< member holding a pointer to the surface generated from the distance image of the selected camera mitk::DataNode::Pointer m_DistanceImageNode; ///< DataNode holding the distance image of the selected camera mitk::DataNode::Pointer m_AmplitudeImageNode; ///< DataNode holding the amplitude image of the selected camera mitk::DataNode::Pointer m_IntensityImageNode; ///< DataNode holding the intensity image of the selected camera mitk::DataNode::Pointer m_RGBImageNode; ///< DataNode holding the rgb image of the selected camera mitk::DataNode::Pointer m_SurfaceNode; ///< DataNode holding the surface generated from the distanc image of the selected camera // ToF processing and recording filter mitk::ToFImageRecorder::Pointer m_ToFImageRecorder; ///< ToF image recorder used for lossless recording of ToF image data mitk::ToFImageGrabber::Pointer m_ToFImageGrabber; ///< Source of a ToF image processing pipeline. Provides pointers to distance, amplitude and intensity image mitk::ToFDistanceImageToSurfaceFilter::Pointer m_ToFDistanceImageToSurfaceFilter; ///< Filter for calculating a surface representation from a given distance image mitk::ToFCompositeFilter::Pointer m_ToFCompositeFilter; ///< Filter combining several processing steps (thresholding, Median filtering, Bilateral filtering) int m_2DDisplayCount; ///< member used to determine whether frame rate output should be shown // members for calculating the frame rate mitk::RealTimeClock::Pointer m_RealTimeClock; ///< real time clock used to calculate the display framerate int m_StepsForFramerate; ///< number of steps used for calculating the display framerate double m_2DTimeBefore; ///< holds the time stamp at the beginning of the display framerate measurement double m_2DTimeAfter; ///< holds the time stamp at the end of the display framerate measurement mitk::CameraIntrinsics::Pointer m_CameraIntrinsics; ///< member holding the intrinsic parameters of the camera private: /*! \brief helper method to replace data of the specified node. If node does not exist it will be created \param nodeName Name of the node \param data Data object to be replaced \return returns the node */ mitk::DataNode::Pointer ReplaceNodeData(std::string nodeName, mitk::BaseData* data); void ProcessVideoTransform(); /*! \brief Reset all GUI related things to default. E.g. show sagittal and coronal slices in the renderwindows. */ void ResetGUIToDefault(); }; #endif // _QMITKTOFUTILVIEW_H_INCLUDED