MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkIGTTrackingLabView.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
13
14// Blueberry
15#include <berryISelectionService.h>
16#include <berryIWorkbenchWindow.h>
17
18// Qmitk
20
21#include <QmitkRenderWindow.h>
28
29#include <mitkIGTException.h>
30#include <mitkNodePredicateNot.h>
31#include <mitkNodePredicateProperty.h>
32#include <mitkNodePredicateDataType.h>
33#include <itkVector.h>
34
35#include <vtkTransform.h>
36#include <vtkTransformPolyDataFilter.h>
37#include <vtkAppendPolyData.h>
38#include <vtkPoints.h>
39
40// Qt
41#include <QMessageBox>
42#include <QIcon>
43#include <QPushButton>
44
45// vtk
46#include <mitkVtkResliceInterpolationProperty.h>
47
48
49const std::string QmitkIGTTrackingLabView::VIEW_ID = "org.mitk.views.igttrackinglab";
50
52: QmitkAbstractView()
53,m_Source(nullptr)
54,m_PermanentRegistrationFilter(nullptr)
55,m_Visualizer(nullptr)
56,m_VirtualView(nullptr)
57,m_PSRecordingPointSet(nullptr)
58,m_PointSetRecording(false)
59,m_PermanentRegistration(false)
60,m_CameraView(false)
61,m_ImageFiducialsDataNode(nullptr)
62,m_TrackerFiducialsDataNode(nullptr)
63,m_PermanentRegistrationSourcePoints(nullptr)
64{
65}
66
67//###############################################################################################
68//###############################################################################################
69//############################## Timer method for IGT pipeline updating #########################
70//###############################################################################################
71//###############################################################################################
72
74{
76 {
78 {
81 }
82 }
83
84 if (m_CameraView && m_VirtualView.IsNotNull()) {m_VirtualView->Update();}
85
87 {
88 int size = m_PSRecordingPointSet->GetSize();
89 mitk::NavigationData::Pointer nd = m_PointSetRecordingNavigationData;
90
91 if(size > 0)
92 {
93 mitk::Point3D p = m_PSRecordingPointSet->GetPoint(size-1);
94 if(p.EuclideanDistanceTo(nd->GetPosition()) > (double) m_Controls.m_PSRecordingSpinBox->value())
95 m_PSRecordingPointSet->InsertPoint(size, nd->GetPosition());
96 }
97 else
98 m_PSRecordingPointSet->InsertPoint(size, nd->GetPosition());
99 }
100 }
101
102//###############################################################################################
103//###############################################################################################
104//############################## Slots of CONFIGURATION step ####################################
105//###############################################################################################
106//###############################################################################################
107
109{
110 if(m_Source.IsNotNull())
111 if(m_Source->IsTracking())
112 return;
113
114 mitk::DataStorage* ds = this->GetDataStorage();
115
116 if(ds == nullptr)
117 {
118 MITK_WARN << "IGTSurfaceTracker: Error. Cannot access DataStorage. Navigation not possible";
119 return;
120 }
121
122 //Building up the filter pipeline
123 try
124 {
126 }
127 catch(mitk::IGTException& e)
128 {
129 MITK_WARN << "Error while building the IGT-Pipeline: " << e.GetDescription();
130 this->DestroyIGTPipeline(); // destroy the pipeline if building is incomplete
131 return;
132 }
133 catch(...)
134 {
135 MITK_WARN << "Unexpected error while building the IGT-Pipeline";
136 this->DestroyIGTPipeline();
137 return;
138 }
139}
140
142{
143 if (m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource().IsNotNull())
144 {
145 m_InstrumentNavigationData = m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedToolID());
146 }
147 else
148 {
149 m_Controls.m_PointerNameLabel->setText("<not available>");
150 return;
151 }
152
153 if (m_InstrumentNavigationData.IsNotNull())
154 {
155 m_Controls.m_PointerNameLabel->setText(m_InstrumentNavigationData->GetName());
156 }
157 else
158 {
159 m_Controls.m_PointerNameLabel->setText("<not available>");
160 }
161}
162
164{
165 if (m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource().IsNotNull())
166 {
167 m_ObjectmarkerNavigationData = m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_TrackingDeviceSelectionWidget->GetSelectedToolID());
168 MITK_INFO << "Objectmarker rotation: " << m_ObjectmarkerNavigationData->GetOrientation();
169 }
170 else
171 {
172 m_Controls.m_ObjectmarkerNameLabel->setText("<not available>");
173 return;
174 }
175
176 if (m_ObjectmarkerNavigationData.IsNotNull())
177 {
178 m_Controls.m_ObjectmarkerNameLabel->setText(m_ObjectmarkerNavigationData->GetName());
179 }
180 else
181 {
182 m_Controls.m_ObjectmarkerNameLabel->setText("<not available>");
183 }
184}
185
186//###############################################################################################
187//###############################################################################################
188//####################### Slots of INITIAL REGISTRATION step ####################################
189//###############################################################################################
190//###############################################################################################
191
193{
194 //Check for initialization
195 if (!CheckRegistrationInitialization()) return;
196
197 mitk::PointSet::Pointer imageFiducials = dynamic_cast<mitk::PointSet*>(m_ImageFiducialsDataNode->GetData());
198 mitk::PointSet::Pointer trackerFiducials = dynamic_cast<mitk::PointSet*>(m_TrackerFiducialsDataNode->GetData());
199
200 //############### conversion to vtk data types (we will use the vtk landmark based transform) ##########################
201 //convert point sets to vtk poly data
204 for (int i=0; i<imageFiducials->GetSize(); i++)
205 {
206 double point[3] = {imageFiducials->GetPoint(i)[0],imageFiducials->GetPoint(i)[1],imageFiducials->GetPoint(i)[2]};
207 sourcePoints->InsertNextPoint(point);
208 double point_targets[3] = {trackerFiducials->GetPoint(i)[0],trackerFiducials->GetPoint(i)[1],trackerFiducials->GetPoint(i)[2]};
209 targetPoints->InsertNextPoint(point_targets);
210 }
211
212 //########################### here, the actual transform is computed ##########################
213 //compute transform
215 transform->SetSourceLandmarks(sourcePoints);
216 transform->SetTargetLandmarks(targetPoints);
217 transform->SetModeToRigidBody();
218 transform->Modified();
219 transform->Update();
220 //compute FRE of transform
221 double FRE = mitk::StaticIGTHelperFunctions::ComputeFRE(imageFiducials, trackerFiducials, transform);
222 m_Controls.m_RegistrationWidget->SetQualityDisplayText("FRE: " + QString::number(FRE) + " mm");
223 //#############################################################################################
224
225 //############### conversion back to itk/mitk data types ##########################
226 //convert from vtk to itk data types
227 itk::Matrix<float,3,3> rotationFloat = itk::Matrix<float,3,3>();
228 itk::Vector<float,3> translationFloat = itk::Vector<float,3>();
229 itk::Matrix<double,3,3> rotationDouble = itk::Matrix<double,3,3>();
230 itk::Vector<double,3> translationDouble = itk::Vector<double,3>();
231
232 vtkSmartPointer<vtkMatrix4x4> m = transform->GetMatrix();
233 for(int k=0; k<3; k++) for(int l=0; l<3; l++)
234 {
235 rotationFloat[k][l] = m->GetElement(k,l);
236 rotationDouble[k][l] = m->GetElement(k,l);
237
238 }
239 for(int k=0; k<3; k++)
240 {
241 translationFloat[k] = m->GetElement(k,3);
242 translationDouble[k] = m->GetElement(k,3);
243 }
244 //create affine transform 3D surface
245 mitk::AffineTransform3D::Pointer mitkTransform = mitk::AffineTransform3D::New();
246 mitkTransform->SetMatrix(rotationDouble);
247 mitkTransform->SetOffset(translationDouble);
248 //#############################################################################################
249
250 //############### object is transformed ##########################
251 //save transform
252 m_T_ObjectReg = mitk::NavigationData::New(mitkTransform); // this is stored in a member because it is needed for permanent registration later on
253
254 //transform surface
255 if(m_Controls.m_SurfaceActive->isChecked() && m_Controls.m_ObjectComboBox->GetSelectedNode().IsNotNull())
256 {
257 m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(mitkTransform);
258 }
259 //################################################################
260
261 //############### if activated: ct image is also transformed ##########################
262 //transform ct image
263 //todo: Explain that AffineTransform3D is used, because NavigationData does not support spacing!
264 if(m_Controls.m_ImageActive->isChecked() && m_Controls.m_ImageComboBox->GetSelectedNode().IsNotNull())
265 {
266 //first we have to store the original ct image transform to compose it with the new transform later
267 mitk::AffineTransform3D::Pointer imageTransform = m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform();
268 m_T_ImageGeo = mitk::AffineTransform3D::New(); // this is also stored in a member because it is needed for permanent registration later on
269 //now the new transform of the ct image is computed
270 m_T_ImageGeo->Compose(imageTransform);
271 imageTransform->Compose(mitkTransform);
272 mitk::AffineTransform3D::Pointer newImageTransform = mitk::AffineTransform3D::New(); //create new image transform... setting the composed directly leads to an error
273 itk::Matrix<mitk::ScalarType,3,3> rotationFloatNew = imageTransform->GetMatrix();
274 itk::Vector<mitk::ScalarType,3> translationFloatNew = imageTransform->GetOffset();
275 newImageTransform->SetMatrix(rotationFloatNew);
276 newImageTransform->SetOffset(translationFloatNew);
277 m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(newImageTransform);
278 m_T_ImageReg = m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform();
279 }
280 //################################################################
281
282}
283
284
286{
287 mitk::NavigationData::Pointer nd = m_InstrumentNavigationData;
288
289 if( nd.IsNull() || !nd->IsDataValid())
290 {
291 QMessageBox::warning( nullptr, "Invalid tracking data", "Navigation data is not available or invalid!", QMessageBox::Ok );
292 return;
293 }
294
295 if(m_TrackerFiducialsDataNode.IsNotNull() && m_TrackerFiducialsDataNode->GetData() != nullptr)
296 {
297 mitk::PointSet::Pointer ps = dynamic_cast<mitk::PointSet*>(m_TrackerFiducialsDataNode->GetData());
298 ps->InsertPoint(ps->GetSize(), nd->GetPosition());
299 }
300 else
301 QMessageBox::warning(nullptr, "IGTSurfaceTracker: Error", "Can not access Tracker Fiducials. Adding fiducial not possible!");
302}
303
304
306{
307 mitk::DataStorage* ds = this->GetDataStorage();
308 if( ds == nullptr )
309 return;
310
311 // let the registration widget know about the slice navigation controllers
312 // in the active render window part (crosshair updates)
313 foreach(QmitkRenderWindow* renderWindow, this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindows().values())
314 {
315 m_Controls.m_RegistrationWidget->AddSliceNavigationController(renderWindow->GetSliceNavigationController());
316 }
317
318 if(m_ImageFiducialsDataNode.IsNull())
319 {
320 m_ImageFiducialsDataNode = mitk::DataNode::New();
321 mitk::PointSet::Pointer ifPS = mitk::PointSet::New();
322
323 m_ImageFiducialsDataNode->SetData(ifPS);
324
325 mitk::Color color;
326 color.Set(1.0f, 0.0f, 0.0f);
327 m_ImageFiducialsDataNode->SetName("Image Fiducials");
328 m_ImageFiducialsDataNode->SetColor(color);
329 m_ImageFiducialsDataNode->SetBoolProperty( "updateDataOnRender", false );
330
332 }
333 m_Controls.m_RegistrationWidget->SetImageFiducialsNode(m_ImageFiducialsDataNode);
334
335 if(m_TrackerFiducialsDataNode.IsNull())
336 {
337 m_TrackerFiducialsDataNode = mitk::DataNode::New();
338 mitk::PointSet::Pointer tfPS = mitk::PointSet::New();
339 m_TrackerFiducialsDataNode->SetData(tfPS);
340
341 mitk::Color color;
342 color.Set(0.0f, 1.0f, 0.0f);
343 m_TrackerFiducialsDataNode->SetName("Tracking Fiducials");
344 m_TrackerFiducialsDataNode->SetColor(color);
345 m_TrackerFiducialsDataNode->SetBoolProperty( "updateDataOnRender", false );
346
348 }
349
350 m_Controls.m_RegistrationWidget->SetTrackerFiducialsNode(m_TrackerFiducialsDataNode);
351}
352
353//###############################################################################################
354//###############################################################################################
355//####################### Slots of PERMANENT REGISTRATION step ##################################
356//###############################################################################################
357//###############################################################################################
358
360{
361 if(on)
362 {
363 //######################################################################
364 //######################## initialization ##############################
365 //######################################################################
366
367 //some initial checks
369 {
370 m_Controls.m_UsePermanentRegistrationToggle->setChecked(false);
371 return;
372 }
373
374 //remember initial object transform to calculate the object to marker transform later on and convert it to navigation data
375 mitk::AffineTransform3D::Pointer transform = this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->GetIndexToWorldTransform();
376 mitk::NavigationData::Pointer T_Object = mitk::NavigationData::New(transform,false); //TODO: catch exception during conversion?
377
378 //then reset the transform because we will now start to calculate the permanent registration
379 this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIdentity();
380 if(m_Controls.m_ImageActive->isChecked()) {this->m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ImageGeo);}
381
382 //create the permanent registration filter
383 m_PermanentRegistrationFilter = mitk::NavigationDataObjectVisualizationFilter::New();
384
385 //######################################################################
386 //first: initialize permanent registration of surface (always activated)
387 //######################################################################
388
389 //connect filter to source
391
392 //set representation object
393 m_PermanentRegistrationFilter->SetRepresentationObject(0,this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData());
394
395 //get the marker transform out of the navigation data
396 mitk::NavigationData::Pointer T_Marker = m_ObjectmarkerNavigationData;
397
398 //compute transform from object to marker (T_MarkerRel = T_Object * T_Marker^-1)
399 mitk::NavigationData::Pointer T_MarkerRel = mitk::NavigationData::New();
400 T_MarkerRel->Compose(T_Object);
401 T_MarkerRel->Compose(T_Marker->GetInverse());
402 m_T_MarkerRel = T_MarkerRel;
403 m_PermanentRegistrationFilter->SetOffset(0,m_T_MarkerRel->GetAffineTransform3D());
404
405 //######################################################################
406 //second: initialize permanent registration of image (if activated)
407 //######################################################################
408 if (m_Controls.m_ImageActive->isChecked() && (m_Controls.m_ImageComboBox->GetSelectedNode().IsNotNull()))
409 {
410 mitk::DataNode::Pointer imageNode = this->m_Controls.m_ImageComboBox->GetSelectedNode();
411 imageNode->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_LINEAR) );
413 m_PermanentRegistrationFilter->SetRepresentationObject(1,imageNode->GetData());
414
415 //for the image we can't use NavigationData objects as transforms because an image needs additional geometry information, e.g., spacing
416 //thus we use mitk::AffineTransform3D objects
417
418 //computer transform from image to marker (T_ImageRel = T_ImageGeo * T_MarkerRel)
419 mitk::AffineTransform3D::Pointer T_ImageRel = mitk::AffineTransform3D::New();
420 T_ImageRel->SetIdentity();
421 T_ImageRel->Compose(m_T_ImageGeo);
422 T_ImageRel->Compose(m_T_MarkerRel->GetAffineTransform3D());
423 m_PermanentRegistrationFilter->SetOffset(1,T_ImageRel);
424 }
425
426 //some general stuff
428 m_ObjectmarkerNavigationDataLastUpdate = mitk::NavigationData::New();
429 }
430 else //if off = disable the permanent registration
431 {
432 //stop permanent registration
434
435 //restore old registration
436 if(m_T_ObjectReg.IsNotNull()) {this->m_Controls.m_ObjectComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ObjectReg->GetAffineTransform3D());}
437 if(m_T_ImageReg.IsNotNull()) {this->m_Controls.m_ImageComboBox->GetSelectedNode()->GetData()->GetGeometry()->SetIndexToWorldTransform(m_T_ImageReg);}
438
439 //delete filter
441 }
442}
443
444//###############################################################################################
445//###############################################################################################
446//####################### Slots of POINT SET RECORDING step #####################################
447//###############################################################################################
448//###############################################################################################
449
451{
452 mitk::DataStorage* ds = this->GetDataStorage();
453
454 if(record)
455 {
456 if (m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedToolID() == -1)
457 {
458 QMessageBox::warning(nullptr, "Error", "No tool selected for point set recording!");
459 m_Controls.m_PointSetRecordCheckBox->setChecked(false);
460 return;
461 }
462 m_PointSetRecordingNavigationData = m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_PointSetRecordingToolSelectionWidget->GetSelectedToolID());
463
464 //initialize point set
465 mitk::DataNode::Pointer psRecND = ds->GetNamedNode("Recorded Points");
466 if(m_PSRecordingPointSet.IsNull() || psRecND.IsNull())
467 {
468 m_PSRecordingPointSet = nullptr;
469 m_PSRecordingPointSet = mitk::PointSet::New();
470 mitk::DataNode::Pointer dn = mitk::DataNode::New();
471 dn->SetName("Recorded Points");
472 dn->SetColor(0.,1.,0.);
473 dn->SetData(m_PSRecordingPointSet);
474 ds->Add(dn);
475 }
476 else
477 {
478 m_PSRecordingPointSet->Clear();
479 }
480 m_PointSetRecording = true;
481 }
482
483 else
484 {
485 m_PointSetRecording = false;
486 }
487}
488
489//###############################################################################################
490//###############################################################################################
491//####################### Slots of VIRTUAL CAMERA VIEW step #####################################
492//###############################################################################################
493//###############################################################################################
494
496{
497if (m_Controls.m_CameraViewSelection->GetSelectedToolID() == -1)
498 {
499 m_Controls.m_ActivateNeedleView->setChecked(false);
500 QMessageBox::warning(nullptr, "Error", "No tool selected for camera view!");
501 return;
502 }
503
504if(on)
505 {
506 m_VirtualView = mitk::CameraVisualization::New();
507 m_VirtualView->SetInput(m_Controls.m_CameraViewSelection->GetSelectedNavigationDataSource()->GetOutput(m_Controls.m_CameraViewSelection->GetSelectedToolID()));
508
509 mitk::Vector3D viewDirection;
510 viewDirection[0] = (int)(m_Controls.m_NeedleViewX->isChecked());
511 viewDirection[1] = (int)(m_Controls.m_NeedleViewY->isChecked());
512 viewDirection[2] = (int)(m_Controls.m_NeedleViewZ->isChecked());
513 if (m_Controls.m_NeedleViewInvert->isChecked()) viewDirection *= -1;
514 m_VirtualView->SetDirectionOfProjectionInToolCoordinates(viewDirection);
515
516 mitk::Vector3D viewUpVector;
517 viewUpVector[0] = (int)(m_Controls.m_NeedleUpX->isChecked());
518 viewUpVector[1] = (int)(m_Controls.m_NeedleUpY->isChecked());
519 viewUpVector[2] = (int)(m_Controls.m_NeedleUpZ->isChecked());
520 if (m_Controls.m_NeedleUpInvert->isChecked()) viewUpVector *= -1;
521 m_VirtualView->SetViewUpInToolCoordinates(viewUpVector);
522
523 m_VirtualView->SetRenderer(this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetQmitkRenderWindow("3d")->GetRenderer());
524 //next line: better code when this plugin is migrated to mitk::abstractview
525 //m_VirtualView->SetRenderer(mitk::BaseRenderer::GetInstance(this->GetRenderWindowPart(mitk::WorkbenchUtil::OPEN)->GetRenderWindow("3d")->GetRenderWindow()));
526 m_CameraView = true;
527
528 //make pointer itself invisible
529 m_Controls.m_CameraViewSelection->GetSelectedNavigationTool()->GetDataNode()->SetBoolProperty("visible",false);
530
531 //disable UI elements
532 m_Controls.m_ViewDirectionBox->setEnabled(false);
533 m_Controls.m_ViewUpBox->setEnabled(false);
534 }
535else
536 {
537 m_VirtualView = nullptr;
538 m_CameraView = false;
539 m_Controls.m_CameraViewSelection->GetSelectedNavigationTool()->GetDataNode()->SetBoolProperty("visible",true);
540
541 m_Controls.m_ViewDirectionBox->setEnabled(true);
542 m_Controls.m_ViewUpBox->setEnabled(true);
543 }
544
545}
546
547//###############################################################################################
548//###############################################################################################
549//############################## some general UI methods, always needed #########################
550//###############################################################################################
551//###############################################################################################
552
554{
555 if (m_Timer->isActive()) m_Timer->stop();
556}
557
559{
560 // create GUI widgets from the Qt Designer's .ui file
561 m_Controls.setupUi( parent );
562 this->CreateBundleWidgets();
563 this->CreateConnections();
564}
565
566
568{
569 //initialize registration widget
570 m_Controls.m_RegistrationWidget->HideStaticRegistrationRadioButton(true);
571 m_Controls.m_RegistrationWidget->HideContinousRegistrationRadioButton(true);
572 m_Controls.m_RegistrationWidget->HideUseICPRegistrationCheckbox(true);
573}
574
575
577{
578 //initialize timer
579 m_Timer = new QTimer(this);
580
581 //create connections
582 connect(m_Timer, SIGNAL(timeout()), this, SLOT(UpdateTimer()));
583 connect( m_Controls.m_UsePermanentRegistrationToggle, SIGNAL(toggled(bool)), this, SLOT(OnPermanentRegistration(bool)) );
584 connect( m_Controls.m_TrackingDeviceSelectionWidget, SIGNAL(NavigationDataSourceSelected(mitk::NavigationDataSource::Pointer)), this, SLOT(OnSetupNavigation()) );
585 connect( m_Controls.m_UseAsPointerButton, SIGNAL(clicked()), this, SLOT(OnInstrumentSelected()) );
586 connect( m_Controls.m_UseAsObjectmarkerButton, SIGNAL(clicked()), this, SLOT(OnObjectmarkerSelected()) );
587 connect( m_Controls.m_RegistrationWidget, SIGNAL(AddedTrackingFiducial()), this, SLOT(OnAddRegistrationTrackingFiducial()) );
588 connect( m_Controls.m_RegistrationWidget, SIGNAL(PerformFiducialRegistration()), this, SLOT(OnInitialRegistration()) );
589 connect( m_Controls.m_PointSetRecordCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnPointSetRecording(bool)) );
590 connect( m_Controls.m_ActivateNeedleView, SIGNAL(toggled(bool)), this, SLOT(OnVirtualCamera(bool)) );
591
592 //start timer
593 m_Timer->start(30);
594
595 //initialize Combo Boxes
596 m_Controls.m_ObjectComboBox->SetDataStorage(this->GetDataStorage());
597 m_Controls.m_ObjectComboBox->SetAutoSelectNewItems(false);
598 m_Controls.m_ObjectComboBox->SetPredicate(mitk::NodePredicateDataType::New("Surface"));
599
600 m_Controls.m_ImageComboBox->SetDataStorage(this->GetDataStorage());
601 m_Controls.m_ImageComboBox->SetAutoSelectNewItems(false);
602 m_Controls.m_ImageComboBox->SetPredicate(mitk::NodePredicateDataType::New("Image"));
603}
604
606{
607 m_Controls.m_UseAsPointerButton->setFocus();
608}
609
610//###############################################################################################
611//###############################################################################################
612//####################### some additional slots and help methods ################################
613//####################### for cleaner code - not that important ################################
614//####################### to understand the basic functions ################################
615//###############################################################################################
616//###############################################################################################
617
619{
620 if(m_Source.IsNotNull())
621 {
622 m_Source->StopTracking();
623 m_Source->Disconnect();
624 m_Source = nullptr;
625 }
627 m_Visualizer = nullptr;
628 m_VirtualView = nullptr;
629}
630
632{
633 // a couple of variables which we need in this method
634 std::string warningMessage = "";
635 bool initializationErrorDetected = false;
636 mitk::PointSet::Pointer imageFiducials,trackerFiducials;
637
638 // check some initialization stuff
640 {
641 warningMessage = "Initialization not finished!";
642 MITK_WARN << warningMessage;
643 QMessageBox::warning(nullptr, "Registration not possible", warningMessage.c_str());
644 return false;
645 }
646 else
647 {
648 imageFiducials = dynamic_cast<mitk::PointSet*>(m_ImageFiducialsDataNode->GetData());
649 trackerFiducials = dynamic_cast<mitk::PointSet*>(m_TrackerFiducialsDataNode->GetData());
650 }
651
652 // now, do a lot of other checks...
653 if (m_Controls.m_SurfaceActive->isChecked() && m_Controls.m_ObjectComboBox->GetSelectedNode().IsNull())
654 {
655 warningMessage = "No surface selected for registration.\nRegistration is not possible";
656 initializationErrorDetected = true;
657 }
658 else if (m_Controls.m_ImageActive->isChecked() && m_Controls.m_ImageComboBox->GetSelectedNode().IsNull())
659 {
660 warningMessage = "No image selected for registration.\nRegistration is not possible";
661 initializationErrorDetected = true;
662 }
663 else if (imageFiducials.IsNull() || trackerFiducials.IsNull())
664 {
665 warningMessage = "Fiducial data objects not found. \n"
666 "Please set 3 or more fiducials in the image and with the tracking system.\n\n"
667 "Registration is not possible";
668 initializationErrorDetected = true;
669 }
670 else if ((imageFiducials->GetSize() < 3) || (trackerFiducials->GetSize() < 3) || (imageFiducials->GetSize() != trackerFiducials->GetSize()))
671 {
672 warningMessage = "Not enough fiducial pairs found. At least 3 fiducial must exist for the image and the tracking system respectively.";
673 initializationErrorDetected = true;
674 }
675
676 // finally: if an err was detected, give a warning and an error popup, then return false
677 if(initializationErrorDetected)
678 {
679 MITK_WARN << warningMessage;
680 QMessageBox::warning(nullptr, "Registration not possible", warningMessage.c_str());
681 return false;
682 }
683 //if no error was detected simply return true
684 else {return true;}
685
686}
687
688bool QmitkIGTTrackingLabView::IsTransformDifferenceHigh(mitk::NavigationData::Pointer transformA, mitk::NavigationData::Pointer transformB, double euclideanDistanceThreshold, double angularDifferenceThreshold)
689{
690 if(transformA.IsNull() || transformA.IsNull())
691 {return false;}
692 mitk::Point3D posA,posB;
693 posA = transformA->GetPosition();
694 posB = transformB->GetPosition();
695
696
697 if(posA.EuclideanDistanceTo(posB) > euclideanDistanceThreshold)
698 {return true;}
699
700 double returnValue;
701 mitk::Quaternion rotA,rotB;
702 rotA = transformA->GetOrientation();
703 rotB = transformB->GetOrientation();
704
705 itk::Vector<double,3> point; //caution 5D-Tools: Vector must lie in the YZ-plane for a correct result.
706 point[0] = 0.0;
707 point[1] = 0.0;
708 point[2] = 100000.0;
709
710 rotA.normalize();
711 rotB.normalize();
712
713 itk::Matrix<double,3,3> rotMatrixA;
714 for(int i=0; i<3; i++) for(int j=0; j<3; j++) rotMatrixA[i][j] = rotA.rotation_matrix_transpose().transpose()[i][j];
715
716 itk::Matrix<double,3,3> rotMatrixB;
717 for(int i=0; i<3; i++) for(int j=0; j<3; j++) rotMatrixB[i][j] = rotB.rotation_matrix_transpose().transpose()[i][j];
718
719 itk::Vector<double,3> pt1 = rotMatrixA * point;
720 itk::Vector<double,3> pt2 = rotMatrixB * point;
721
722 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)));
723 returnValue = acos(returnValue);
724
725 if(returnValue*57.3 > angularDifferenceThreshold){return true;}
726
727 return false;
728}
mitk::NavigationDataObjectVisualizationFilter::Pointer m_Visualizer
visualization filter
static const std::string VIEW_ID
mitk::NavigationDataObjectVisualizationFilter::Pointer m_PermanentRegistrationFilter
this filter transforms from tracking coordinates into mitk world coordinates if needed it is intercon...
void CreateQtPartControl(QWidget *parent) override
mitk::PointSet::Pointer m_PSRecordingPointSet
bool IsTransformDifferenceHigh(mitk::NavigationData::Pointer transformA, mitk::NavigationData::Pointer transformB, double euclideanDistanceThreshold=.8, double angularDifferenceThreshold=.8)
mitk::TrackingDeviceSource::Pointer m_Source
source that connects to the tracking device
mitk::NavigationData::Pointer m_T_MarkerRel
void OnVirtualCamera(bool on)
This method activates the virtual camera.
mitk::NavigationData::Pointer m_ObjectmarkerNavigationDataLastUpdate
this is the position of the object marker from the last call of update(); it is used to check the dif...
void OnAddRegistrationTrackingFiducial()
This method adds a new fiducial to the tracker fiducials PointSet.
QmitkIGTTrackingLabView()
default constructor
mitk::NavigationData::Pointer m_InstrumentNavigationData
navigation data of instrument
mitk::AffineTransform3D::Pointer m_T_ImageGeo
QTimer * m_Timer
central timer which updates the IGT pipeline
void OnInitialRegistration()
This method calls the initial fiducial registration.
void DestroyIGTPipeline()
This method destroys the filter pipeline.
mitk::NavigationData::Pointer m_T_ObjectReg
void CreateConnections()
This method creates the SIGNAL SLOT connections.
mitk::NavigationData::Pointer m_ObjectmarkerNavigationData
navigation data of object marker
mitk::NavigationData::Pointer m_PointSetRecordingNavigationData
void OnPermanentRegistration(bool on)
This method activates the permanent registration based on one tool's position.
void OnPointSetRecording(bool record)
This method starts the PointSet recording.
Ui::QmitkIGTTrackingLabViewControls m_Controls
mitk::DataNode::Pointer m_TrackerFiducialsDataNode
~QmitkIGTTrackingLabView() override
default destructor
void InitializeRegistration()
This method initializes the registration for the FiducialRegistrationWidget.
mitk::AffineTransform3D::Pointer m_T_ImageReg
mitk::CameraVisualization::Pointer m_VirtualView
filter to update the vtk camera according to the reference navigation data
mitk::DataNode::Pointer m_ImageFiducialsDataNode
void CreateBundleWidgets()
This method creates all widgets this bundle needs.
void OnSetupNavigation()
This method sets up the navigation pipeline during initialization.
An object of this class represents an exception of the MITK-IGT module.
MITKIGTBASE_EXPORT double ComputeFRE(mitk::PointSet::Pointer imageFiducials, mitk::PointSet::Pointer realWorldFiducials, vtkSmartPointer< vtkLandmarkTransform > transform=nullptr)
Computes the fiducial registration error out of two sets of fiducials. The two sets must have the sam...