MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
QmitkIGTNavigationToolCalibration.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#include <numeric>
14
15// Blueberry
16#include <berryISelectionService.h>
17#include <berryIWorkbenchWindow.h>
18
19// Qmitk
21
22// mitk
25#include <mitkTrackingDevice.h>
26#include <mitkTrackingTool.h>
29#include <mitkNavigationData.h>
30
31// Qt
32#include <QMessageBox>
33#include <QFileDialog>
34#include <QFileInfo>
35
36// vtk
37#include <vtkSphereSource.h>
38
39const std::string QmitkIGTNavigationToolCalibration::VIEW_ID = "org.mitk.views.igtnavigationtoolcalibration";
40
45
47{
48 //The following code is required due to a bug in the point list widget.
49 //If this is removed, MITK crashes when closing the view:
50 m_Controls.m_RegistrationLandmarkWidget->SetPointSetNode(nullptr);
51 m_Controls.m_CalibrationLandmarkWidget->SetPointSetNode(nullptr);
52
53 //clean up data storage
54 this->GetDataStorage()->Remove(m_ToolTipPointPreview);
55
56
58}
59
64
66{
67 //if pivot calibration (3) or manual(0) is chosen only calibration pointer is needed
68 if (index == 0 || index == 3) {
69
70 if (!CheckInitialization(false)) {
71 return;
72 }
73 }
74 else{
75 if (!CheckInitialization()) { return; }
76 }
77
79 m_Controls.m_CalibrationMethodsWidget->setCurrentIndex(index);
81}
82
84{
85 m_TrackingTimer = new QTimer(this);
86
87 // create GUI widgets from the Qt Designer's .ui file
88 m_Controls.setupUi(parent);
89 connect(m_Controls.m_SetToolToCalibrate, SIGNAL(clicked()), this, SLOT(SetToolToCalibrate()));
90 connect(m_Controls.m_SetPointer, SIGNAL(clicked()), this, SLOT(SetCalibrationPointer()));
91 connect(m_TrackingTimer, SIGNAL(timeout()), this, SLOT(UpdateTrackingTimer()));
92 connect(m_Controls.m_AddLandmark, SIGNAL(clicked()), this, SLOT(AddLandmark()));
93 connect(m_Controls.m_SaveCalibratedTool, SIGNAL(clicked()), this, SLOT(SaveCalibratedTool()));
94 connect(m_Controls.m_AddPivotPose, SIGNAL(clicked()), this, SLOT(OnAddPivotPose()));
95 connect(m_Controls.m_ComputePivot, SIGNAL(clicked()), this, SLOT(OnComputePivot()));
96 connect(m_Controls.m_UseComputedPivotPoint, SIGNAL(clicked()), this, SLOT(OnUseComputedPivotPoint()));
97 connect(m_Controls.m_StartEditTooltipManually, SIGNAL(clicked()), this, SLOT(OnStartManualToolTipCalibration()));
98 connect(m_Controls.m_GetPositions, SIGNAL(clicked()), this, SLOT(OnGetPositions()));
99 connect(m_Controls.m_ToolAxis_X, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged()));
100 connect(m_Controls.m_ToolAxis_Y, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged()));
101 connect(m_Controls.m_ToolAxis_Z, SIGNAL(valueChanged(double)), this, SLOT(OnToolAxisSpinboxChanged()));
102 connect(m_Controls.m_CalibrateToolAxis, SIGNAL(clicked()), this, SLOT(OnCalibrateToolAxis()));
103 connect((QObject*)(m_ToolTransformationWidget), SIGNAL(EditToolTipFinished(mitk::AffineTransform3D::Pointer)), this,
104 SLOT(OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer)));
105 connect(m_Controls.m_CalibrationMethodComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnToolCalibrationMethodChanged(int)));
106
107 connect((QObject*)(m_Controls.m_RunCalibrationButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnRunSingleRefToolCalibrationClicked()));
108 connect((QObject*)(m_Controls.m_CollectNavigationDataButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnLoginSingleRefToolNavigationDataClicked()));
109 connect((QObject*)(m_Controls.m_SetNewToolTipPosButton), SIGNAL(clicked()), (QObject*) this, SLOT(OnSetNewToolTipPosButtonClicked()));
110
117
118 //for pivot calibration
120 PivotCount = 0;
121 m_PivotPoses = std::vector<mitk::NavigationData::Pointer>();
122
123 m_CalibrationLandmarks = mitk::PointSet::New();
124 m_CalibrationLandmarksNode = mitk::DataNode::New();
126 m_Controls.m_CalibrationLandmarkWidget->SetPointSetNode(m_CalibrationLandmarksNode);
127
128 m_RegistrationLandmarks = mitk::PointSet::New();
129 m_RegistrationLandmarksNode = mitk::DataNode::New();
131 m_Controls.m_RegistrationLandmarkWidget->SetPointSetNode(m_RegistrationLandmarksNode);
132
133 m_ToolSurfaceInToolCoordinatesDataNode = mitk::DataNode::New();
134 m_ToolSurfaceInToolCoordinatesDataNode->SetName("ToolSurface(ToolCoordinates)");
135
136 m_LoggedNavigationDataDifferences = std::vector< mitk::NavigationData::Pointer >();
137}
138
139
141{
142 if (!CheckInitialization()) { return; }
143
144 mitk::NavigationData::Pointer ToolTipTransform = mitk::NavigationData::New();
145
146 if (m_Controls.m_CalibratePosition->isChecked())
147 {
148 //1: Compute mean translational offset vector
149 m_ResultOffsetVector.Fill(0);
150 for (std::vector<mitk::Point3D>::iterator vecIter = m_LoggedNavigationDataOffsets.begin(); vecIter != m_LoggedNavigationDataOffsets.end(); vecIter++)
151 {
152 m_ResultOffsetVector[0] = m_ResultOffsetVector[0] + (*vecIter)[0];
153 m_ResultOffsetVector[1] = m_ResultOffsetVector[1] + (*vecIter)[1];
154 m_ResultOffsetVector[2] = m_ResultOffsetVector[2] + (*vecIter)[2];
155 }
159
160 this->m_Controls.m_ResultOfCalibration->setText(
161 QString("x: ") + QString(QString::number(m_ResultOffsetVector[0], 103, 3)) +
162 QString("; y: ") + (QString::number(m_ResultOffsetVector[1], 103, 3)) +
163 QString("; z: ") + (QString::number(m_ResultOffsetVector[2], 103, 3)));
164
165 ToolTipTransform->SetPosition(m_ResultOffsetVector);
166 }
167
168
169 if (m_Controls.m_CalibrateOrientation->isChecked())
170 {
171 //2: Compute mean orientation
172 mitk::Quaternion meanOrientation;
173 std::vector <mitk::Quaternion> allOrientations = std::vector <mitk::Quaternion>();
174 for (std::size_t i = 0; i < m_LoggedNavigationDataDifferences.size(); i++) { allOrientations.push_back(m_LoggedNavigationDataDifferences.at(i)->GetOrientation()); }
175 meanOrientation = mitk::QuaternionAveraging::CalcAverage(allOrientations);
176 this->m_Controls.m_ResultOfCalibrationOrientation->setText(
177 QString("qx: ") + QString(QString::number(meanOrientation.x(), 103, 3)) +
178 QString("; qy: ") + (QString::number(meanOrientation.y(), 103, 3)) +
179 QString("; qz: ") + (QString::number(meanOrientation.z(), 103, 3)) +
180 QString("; qr: ") + (QString::number(meanOrientation.r(), 103, 3)));
181
182 ToolTipTransform->SetOrientation(meanOrientation);
183 }
184
185 MITK_INFO << "Computed calibration: ";
186 MITK_INFO << "Translation Vector: " << ToolTipTransform->GetPosition();
187 MITK_INFO << "Quaternion: (" << ToolTipTransform->GetOrientation() << ")";
188 MITK_INFO << "Euler Angles [rad]: (" << ToolTipTransform->GetOrientation().rotation_euler_angles() << ")";
189 MITK_INFO << "Matrix:";
190 vnl_matrix_fixed<double, 3, 3> rotMatrix = ToolTipTransform->GetOrientation().rotation_matrix_transpose();
191 MITK_INFO << rotMatrix[0][0] << " " << rotMatrix[0][1] << " " << rotMatrix[0][2] << std::endl;
192 MITK_INFO << rotMatrix[1][0] << " " << rotMatrix[1][1] << " " << rotMatrix[1][2] << std::endl;
193 MITK_INFO << rotMatrix[2][0] << " " << rotMatrix[2][1] << " " << rotMatrix[2][2] << std::endl;
194
195 //3: write everything into the final tool tip transform and save it as member (it will be written to the tool later on)
196 mitk::NavigationData::Pointer ToolTipInTrackingCoordinates = mitk::NavigationData::New();
197 ToolTipInTrackingCoordinates->Compose(ToolTipTransform);
198 ToolTipInTrackingCoordinates->Compose(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate));
199 ShowToolTipPreview(ToolTipInTrackingCoordinates);
200 m_Controls.m_SetNewToolTipPosButton->setEnabled(true);
201 m_ComputedToolTipTransformation = ToolTipTransform;
202
203}
204
206{
207
208 if (!CheckInitialization()) { return; }
209
210 //reset old data
213
215 m_Controls.m_CollectNavigationDataButton->setEnabled(false);
216 m_NumberOfNavigationData = m_Controls.m_NumberOfNavigationDataToCollect->value();
217 MITK_INFO << "Collecting " << m_NumberOfNavigationData << " NavigationData ... " << endl;
218}
219
221{
222 if (!CheckInitialization()) { return; }
223
225 {
226 //update label text
227 QString labelText = "Collecting Data: " + QString::number(m_NumberOfNavigationDataCounter);
228 m_Controls.m_CollectionStatus->setText(labelText);
229
230 mitk::NavigationData::Pointer referenceTool = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer);
231 mitk::NavigationData::Pointer toolToCalibrate = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate);
232
233 //compute difference:
234 // differenceND = toolToCalibrate^-1 * referenceTool
235 mitk::NavigationData::Pointer differenceND = mitk::NavigationData::New();
236 differenceND->Compose(referenceTool);
237 differenceND->Compose(toolToCalibrate->GetInverse());
238
239 //inverse mode...
240 if (m_Controls.m_InvertQuaternions->isChecked())
241 {
242 // negate identity matrix to directly show parameters that will set up in NDI 6D Software Architect
243 differenceND = differenceND->GetInverse();
244 }
245
246 //save difference in member
247 m_LoggedNavigationDataOffsets.push_back(differenceND->GetPosition());
248 m_LoggedNavigationDataDifferences.push_back(differenceND);
250 }
251
253 {
256 m_Controls.m_CollectNavigationDataButton->setEnabled(true);
257 m_Controls.m_RunCalibrationButton->setEnabled(true);
258 MITK_INFO << "Collecting " << m_NumberOfNavigationData << " NavigationData ... Finished" << endl;
259 QString labelText = "Collected " + QString::number(m_NumberOfNavigationData) + " data samples!";
260 m_Controls.m_CollectionStatus->setText(labelText);
261 }
262}
263
269
271{
272 mitk::NavigationData::Pointer tempND = mitk::NavigationData::New();
273 this->ApplyToolTipTransform(tempND);
275 //m_ManualToolTipEditWidget->hide(); //TODO
276 this->GetDataStorage()->Remove(m_ToolSurfaceInToolCoordinatesDataNode);
277}
279{
281 //When the collect Poses Button is Clicked
283 m_NumberOfNavigationData = m_Controls.m_PosesToCollect->value();
284
285}
286
288{
289 //Save the poses to be used in computation
291 {
292 mitk::NavigationData::Pointer currentPose = mitk::NavigationData::New();
293 currentPose->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate));
294 m_PivotPoses.push_back(currentPose);
295 m_Controls.m_PoseNumber->setText(QString::number(m_PivotPoses.size()));
296 PivotCount++;
297 }
299 {
301 }
302}
303
305{
306
307 mitk::PivotCalibration::Pointer myPivotCalibration = mitk::PivotCalibration::New();
308 for (std::size_t i = 0; i < this->m_PivotPoses.size(); i++)
309 {
310 myPivotCalibration->AddNavigationData(m_PivotPoses.at(i));
311 }
312 QString resultString;
313 if (myPivotCalibration->ComputePivotResult())
314 {
315 mitk::NavigationData::Pointer markerTransformationTrackingCoordinates = m_PivotPoses.at(0);
316
317 //Get computed pivot transformation in tool coordinates
318
319 mitk::NavigationData::Pointer ToolTipToTool = mitk::NavigationData::New();
320 ToolTipToTool->SetPosition(myPivotCalibration->GetResultPivotPoint());
321 ToolTipToTool->SetOrientation(mitk::Quaternion(0,0,0,1));
322 mitk::NavigationData::Pointer TrackerToTool = mitk::NavigationData::New();
323 TrackerToTool->SetOrientation(markerTransformationTrackingCoordinates->GetOrientation());
324 TrackerToTool->SetPosition(markerTransformationTrackingCoordinates->GetPosition());
325 TrackerToTool->Compose(ToolTipToTool);
326
327 // Compute pivot point in relation to marker transformation for preview
328 mitk::NavigationData::Pointer ToolTipToTracker = mitk::NavigationData::New();
329 ToolTipToTracker->Compose(ToolTipToTool);
330 ToolTipToTracker->Compose(markerTransformationTrackingCoordinates);
331
332 //add the preview node to the data storage
333 ShowToolTipPreview(ToolTipToTracker);
334
335 //parse result string
336 resultString = QString("Pivot computation succeeded!\n")
337 + QString("RMS Error: ") + QString::number(myPivotCalibration->GetResultRMSError()) + QString("\n")
338 + QString("Pivot Point: ") + QString::number(myPivotCalibration->GetResultPivotPoint()[0]) + ";" + QString::number(myPivotCalibration->GetResultPivotPoint()[1]) + ";" + QString::number(myPivotCalibration->GetResultPivotPoint()[2]) + QString("\n");
339
340 //finally: save results to member variable
341 m_ComputedToolTipTransformation = ToolTipToTool;
342
343
344 //enable button to use the computed point with the tool
345 m_Controls.m_UseComputedPivotPoint->setEnabled(true);
346 }
347 else
348 {
349 resultString = "Pivot computation failed!";
350 }
351 MITK_INFO << resultString.toStdString().c_str();
352 m_Controls.m_ResultText->setText(resultString);
353
354}
356{
357 PivotCount = 0;
358 while (!m_PivotPoses.empty())
359 {
360 m_PivotPoses.pop_back();
361 }
362 m_Controls.m_PoseNumber->setText(QString::number(PivotCount));
363}
364
366{
368 QString resultString = QString("Pivoted tool tip transformation was written to the tool ") + m_ToolToCalibrate->GetToolName().c_str();
369 ApplyToolTipTransform(m_ComputedToolTipTransformation, resultString.toStdString());
370 m_Controls.m_ResultText->setText(resultString);
372}
373
374void QmitkIGTNavigationToolCalibration::ApplyToolTipTransform(mitk::NavigationData::Pointer ToolTipTransformInToolCoordinates, std::string message)
375{
376 if (!CheckInitialization(false)) { return; }
377
378 //Update tool in tool storage
379 m_ToolToCalibrate->SetToolTipPosition(ToolTipTransformInToolCoordinates->GetPosition());
380 m_ToolToCalibrate->SetToolAxisOrientation(ToolTipTransformInToolCoordinates->GetOrientation());
381
382 //And also update tracking device, so the transform is directly used
383 mitk::TrackingDeviceSource::Pointer trackingDeviceSource;
384 try
385 {
386 trackingDeviceSource = dynamic_cast<mitk::TrackingDeviceSource*>(m_NavigationDataSourceOfToolToCalibrate.GetPointer());
387 mitk::TrackingTool::Pointer TrackingToolToCalibrate = trackingDeviceSource->GetTrackingDevice()->GetTool(m_IDToolToCalibrate);
388 TrackingToolToCalibrate->SetToolTipPosition(ToolTipTransformInToolCoordinates->GetPosition(), ToolTipTransformInToolCoordinates->GetOrientation());
389 }
390 catch (std::exception& e)
391 {
392 MITK_ERROR << "Error while trying to set the tool tip to the running tracking device. Aborting! (" << e.what() << ")";
393 }
394 MITK_INFO << message;
395}
396
397void QmitkIGTNavigationToolCalibration::ShowToolTipPreview(mitk::NavigationData::Pointer ToolTipInTrackingCoordinates)
398{
399 if(m_ToolTipPointPreview.IsNull())
400 {
401 m_ToolTipPointPreview = mitk::DataNode::New();
402 m_ToolTipPointPreview->SetName("Modified Tool Tip Preview");
403 mitk::Color blue;
404 blue.SetBlue(1);
405 m_ToolTipPointPreview->SetColor(blue);
406 mitk::Surface::Pointer mySphere = mitk::Surface::New();
408 vtkData->SetRadius(3.0f);
409 vtkData->SetCenter(0.0, 0.0, 0.0);
410 vtkData->Update();
411 mySphere->SetVtkPolyData(vtkData->GetOutput());
412 m_ToolTipPointPreview->SetData(mySphere);
413
414 this->GetDataStorage()->Add(m_ToolTipPointPreview);
415 }
416 m_ToolTipPointPreview->GetData()->GetGeometry()->SetIndexToWorldTransform(ToolTipInTrackingCoordinates->GetAffineTransform3D());
417}
418
420{
421 this->GetDataStorage()->Remove(m_ToolTipPointPreview.GetPointer());
422}
424{
425 if (m_ToolToCalibrate.IsNull()) { return; }
426 //parse human readable transformation data and display it
427 std::stringstream translation;
428 std::stringstream orientation;
429 translation << m_ToolToCalibrate->GetToolTipPosition();
430 orientation << "Quaternion: (" << m_ToolToCalibrate->GetToolAxisOrientation() << ")" << std::endl;
431 orientation << std::endl;
432 orientation << "Euler Angles [rad]: (" << m_ToolToCalibrate->GetToolAxisOrientation().rotation_euler_angles() << ")" << std::endl;
433 orientation << std::endl;
434 orientation << "Matrix:" << std::endl;
435 vnl_matrix_fixed<double, 3, 3> rotMatrix = m_ToolToCalibrate->GetToolAxisOrientation().rotation_matrix_transpose();
436 orientation << rotMatrix[0][0] << " " << rotMatrix[0][1] << " " << rotMatrix[0][2] << std::endl;
437 orientation << rotMatrix[1][0] << " " << rotMatrix[1][1] << " " << rotMatrix[1][2] << std::endl;
438 orientation << rotMatrix[2][0] << " " << rotMatrix[2][1] << " " << rotMatrix[2][2] << std::endl;
439 m_Controls.m_ManualCurrentTranslation->setText(translation.str().c_str());
440 m_Controls.m_ManualCurrentOrientation->setPlainText(orientation.str().c_str());
441}
442
453
454void QmitkIGTNavigationToolCalibration::OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip)
455{
456 //This function is called, when the toolTipEdit view is closed.
457 //if user pressed cancel, nullptr is returned. Do nothing. Else, set values.
458 if (toolTip)
459 {
460 mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(toolTip);//Convert to Navigation data for simple transversion to quaternion
461 QString resultString = QString("Manual edited values are written to ") + m_ToolToCalibrate->GetToolName().c_str();
462 ApplyToolTipTransform(tempND, resultString.toStdString());
463 m_Controls.m_ResultText->setText(resultString);
465 }
466
468}
469
471{
472 if (!CheckInitialization(true)) { return; }
473
474 //Navigation Data from Tool which should be calibrated
476 m_AxisCalibration_ToolToCalibrate = mitk::NavigationData::New();
477 m_AxisCalibration_ToolToCalibrate->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate));
478
479 //Navigation Data from calibration pointer tool
481 m_AxisCalibration_NavDataCalibratingTool = mitk::NavigationData::New();
482 m_AxisCalibration_NavDataCalibratingTool->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDCalibrationPointer));
483
484 MITK_DEBUG << "Positions for tool axis calibration:";
485 MITK_DEBUG << " ToolTip: " << m_AxisCalibration_ToolToCalibrate->GetPosition() << ",";
486 MITK_DEBUG << " Rotation: \n" << m_AxisCalibration_ToolToCalibrate->GetRotationMatrix();
487 MITK_DEBUG << " End of the tool: " << m_AxisCalibration_NavDataCalibratingTool->GetPosition();
488
489 QString _label = "Position recorded: " + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[0], 'f', 1) + ", "
490 + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[1], 'f', 1) + ", "
491 + QString::number(m_AxisCalibration_NavDataCalibratingTool->GetPosition()[2], 'f', 1);
492 m_Controls.m_ToolAxisPositionLabel->setText(_label);
493}
494
496{
498 {
499 MITK_ERROR << "Please compute tool tip first.";
500 QMessageBox::information(nullptr, "Error", "Please compute / specify tool tip first");
501 return;
502 }
504 {
505 MITK_ERROR << "Please record position first.";
506 QMessageBox::information(nullptr, "Error", "Please record position first");
507 return;
508 }
509
510 //Calculate the tool tip
511 //here is an explanation, what is happening here:
512 /*
513 The axis is equal to the (tool tip) minus the (end of the tool) in tool coordinates of the tool which should be calibrated.
514 The tool tip is defined as the origin of the tool coordinate system.
515 The end of the tool is recorded by the calibration pointer's position and is transformed into the coordinate system of the tool to be calibrated
516 Normalize it.
517 */
518 //m_CalibratedToolAxis = -m_AxisCalibration_ToolToCalibrate->TransformPoint(m_AxisCalibration_NavDataCalibratingTool->GetPosition()).GetVectorFromOrigin();
519 m_CalibratedToolAxis = -m_AxisCalibration_ToolToCalibrate->GetInverse()->TransformPoint(m_AxisCalibration_NavDataCalibratingTool->GetPosition()).GetVectorFromOrigin();
520 MITK_DEBUG << "Tool Endpoint in Tool coordinates: " << m_CalibratedToolAxis;
521 m_CalibratedToolAxis.Normalize();
522 MITK_DEBUG << "Tool Axis: " << m_CalibratedToolAxis;
523
524 m_ToolToCalibrate->SetToolAxis(mitk::Point3D(m_CalibratedToolAxis));
525
526 // Update TrackingTool
527 m_ComputedToolTipTransformation->SetPosition(m_ToolToCalibrate->GetToolTipPosition());
528 m_ComputedToolTipTransformation->SetOrientation(m_ToolToCalibrate->GetToolAxisOrientation());
530
531 //Update GUI
532 QString calibratedToolAxisString = "Tool Axis: " + QString::number(m_CalibratedToolAxis.GetElement(0), 'f', 3) + ", " +
533 QString::number(m_CalibratedToolAxis.GetElement(1), 'f', 3) + ", " + QString::number(m_CalibratedToolAxis.GetElement(2), 'f', 3);
534 m_Controls.m_ToolAxisCalibrationLabel->setText(calibratedToolAxisString);
535
536 //Block QT signals, we don't want to emit SpinboxChanged on the first value to overwrite the next ones
537 m_Controls.m_ToolAxis_X->blockSignals(true); m_Controls.m_ToolAxis_Y->blockSignals(true); m_Controls.m_ToolAxis_Z->blockSignals(true);
538 m_Controls.m_ToolAxis_X->setValue(m_CalibratedToolAxis[0]);
539 m_Controls.m_ToolAxis_Y->setValue(m_CalibratedToolAxis[1]);
540 m_Controls.m_ToolAxis_Z->setValue(m_CalibratedToolAxis[2]);
541 m_Controls.m_ToolAxis_X->blockSignals(false); m_Controls.m_ToolAxis_Y->blockSignals(false); m_Controls.m_ToolAxis_Z->blockSignals(false);
542}
543
545{
546 m_CalibratedToolAxis.SetElement(0, m_Controls.m_ToolAxis_X->value());
547 m_CalibratedToolAxis.SetElement(1, m_Controls.m_ToolAxis_Y->value());
548 m_CalibratedToolAxis.SetElement(2, m_Controls.m_ToolAxis_Z->value());
549 m_ToolToCalibrate->SetToolAxis(mitk::Point3D(m_CalibratedToolAxis));
550 // Update TrackingTool
552 {
553 m_ComputedToolTipTransformation = mitk::NavigationData::New();
554 }
555 m_ComputedToolTipTransformation->SetPosition(m_ToolToCalibrate->GetToolTipPosition());
556 m_ComputedToolTipTransformation->SetOrientation(m_ToolToCalibrate->GetToolAxisOrientation());
558
559 MITK_INFO << "Tool axis changed to " << m_CalibratedToolAxis;
560}
561
563{
564 m_IDToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedToolID();
565 if (m_IDToolToCalibrate == -1) //no valid tool to calibrate
566 {
567 m_Controls.m_CalToolLabel->setText("<none>");
568 m_Controls.m_StatusWidgetToolToCalibrate->RemoveStatusLabels();
569 m_TrackingTimer->stop();
570 }
571 else
572 {
573 m_ToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationTool();
574 m_NavigationDataSourceOfToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource();
575 m_Controls.m_CalToolLabel->setText(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)->GetName());
576 //initialize widget
577 m_Controls.m_StatusWidgetToolToCalibrate->RemoveStatusLabels();
578 m_Controls.m_StatusWidgetToolToCalibrate->SetShowPositions(true);
579 m_Controls.m_StatusWidgetToolToCalibrate->SetTextAlignment(Qt::AlignLeft);
580 m_Controls.m_StatusWidgetToolToCalibrate->AddNavigationData(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate));
581 m_Controls.m_StatusWidgetToolToCalibrate->ShowStatusLabels();
582 //initialize manual tool tip calibration view
584 //save tool surface in tool coordinates for further editing
585 mitk::Surface::Pointer ToolSurface = dynamic_cast<mitk::Surface*>(m_ToolToCalibrate->GetDataNode()->GetData())->Clone();
586 m_ToolSurfaceInToolCoordinatesDataNode->SetData(ToolSurface);
587 m_ToolSurfaceInToolCoordinatesDataNode->GetData()->GetGeometry()->SetIdentity();
588 // update tool tip and rotation information for tool tip calibration tab
590 // update tool axis information for tool axis calibration tab
591 mitk::Point3D toolAxis = m_ToolToCalibrate->GetToolAxis();
592 m_CalibratedToolAxis[0] = toolAxis[0];
593 m_CalibratedToolAxis[1] = toolAxis[1];
594 m_CalibratedToolAxis[2] = toolAxis[2];
595 m_Controls.m_ToolAxis_X->blockSignals(true); m_Controls.m_ToolAxis_Y->blockSignals(true); m_Controls.m_ToolAxis_Z->blockSignals(true);
596 m_Controls.m_ToolAxis_X->setValue(m_CalibratedToolAxis[0]);
597 m_Controls.m_ToolAxis_Y->setValue(m_CalibratedToolAxis[1]);
598 m_Controls.m_ToolAxis_Z->setValue(m_CalibratedToolAxis[2]);
599 m_Controls.m_ToolAxis_X->blockSignals(false); m_Controls.m_ToolAxis_Y->blockSignals(false); m_Controls.m_ToolAxis_Z->blockSignals(false);
600
601 //start updating timer for status widgets, etc.
602 if (!m_TrackingTimer->isActive()) m_TrackingTimer->start(100);
603 }
604}
605
607{
608 m_IDCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedToolID();
609 if (m_IDCalibrationPointer == -1)
610 {
611 m_Controls.m_PointerLabel->setText("<none>");
612 m_Controls.m_StatusWidgetCalibrationPointer->RemoveStatusLabels();
613 m_TrackingTimer->stop();
614 }
615 else
616 {
617 m_NavigationDataSourceOfCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource();
618 m_Controls.m_PointerLabel->setText(m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)->GetName());
619 //initialize widget
620 m_Controls.m_StatusWidgetCalibrationPointer->RemoveStatusLabels();
621 m_Controls.m_StatusWidgetCalibrationPointer->SetShowPositions(true);
622 m_Controls.m_StatusWidgetCalibrationPointer->SetTextAlignment(Qt::AlignLeft);
623 m_Controls.m_StatusWidgetCalibrationPointer->AddNavigationData(m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer));
624 m_Controls.m_StatusWidgetCalibrationPointer->ShowStatusLabels();
625 if (!m_TrackingTimer->isActive()) m_TrackingTimer->start(100);
626 }
627}
628
630{
632 {
633 return;
634 }
635
636 mitk::NavigationData::Pointer referenceToolND = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer);
637 mitk::NavigationData::Pointer toolToCalibrateND = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate);
638
639 if (referenceToolND->IsDataValid() && toolToCalibrateND->IsDataValid())
640 {
641 //computation: difference between both tools (in tool coordinates)
642 //differenceND = toolToCalibrateND^-1 * referenceToolND
643 mitk::NavigationData::Pointer differenceND = mitk::NavigationData::New();
644 differenceND->Compose(referenceToolND);
645 differenceND->Compose(toolToCalibrateND->GetInverse());
646
647 //display this orientation in the UI
648 m_Controls.m_OffsetCoordinates->setText(
649 QString("x: ") + QString(QString::number(differenceND->GetPosition()[0], 103, 3)) +
650 QString("; y: ") + (QString::number(differenceND->GetPosition()[1], 103, 3)) +
651 QString("; z: ") + (QString::number(differenceND->GetPosition()[2], 103, 3)));
652
653 m_Controls.m_OrientationOffsetCoordinates->setText(
654 QString("qx: ") + QString(QString::number(differenceND->GetOrientation().x(), 103, 3)) +
655 QString("; qy: ") + (QString::number(differenceND->GetOrientation().y(), 103, 3)) +
656 QString("; qz: ") + (QString::number(differenceND->GetOrientation().z(), 103, 3)) +
657 QString("; qr: ") + (QString::number(differenceND->GetOrientation().r(), 103, 3)));
658
659 //also update preview if active
660 if (m_ToolTipPointPreview.IsNotNull()) //NOT WORKING! TODO: fix or remove!
661 {
662 mitk::NavigationData::Pointer ToolTipTransform = mitk::NavigationData::New();
663 ToolTipTransform->SetPosition(m_ResultOffsetVector);
664 mitk::NavigationData::Pointer ToolTipInTrackingCoordinates = mitk::NavigationData::New(); //maybe store as for better performance...
665 ToolTipInTrackingCoordinates->Compose(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate));
666 ToolTipInTrackingCoordinates->Compose(ToolTipTransform);
667 m_ToolTipPointPreview->GetData()->GetGeometry()->SetIndexToWorldTransform(ToolTipInTrackingCoordinates->GetAffineTransform3D());
668 }
669 }
670}
671
673{
674 m_Controls.m_StatusWidgetToolToCalibrate->Refresh();
675 m_Controls.m_StatusWidgetCalibrationPointer->Refresh();
676
678
680
681 // 1 == Single Reference Calibration Method
683
684}
685
687{
688 if (!CheckInitialization()) { return; }
689 mitk::NavigationData::Pointer navDataTool = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate);
690 mitk::Point3D landmark = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)->GetPosition();
691
692 //convert to itk transform
693 itk::Vector<double, 3> translation;
694 for (int k = 0; k < 3; k++) translation[k] = navDataTool->GetPosition()[k];
695 itk::Matrix<double, 3, 3> rotation;
696 for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) rotation[k][l] = navDataTool->GetOrientation().rotation_matrix_transpose()[k][l];
697 rotation = rotation.GetTranspose();
698 itk::Vector<double> landmarkItk;
699 landmarkItk[0] = landmark[0];
700 landmarkItk[1] = landmark[1];
701 landmarkItk[2] = landmark[2];
702
703 //compute landmark in tool coordinates
704 itk::Matrix<double, 3, 3> rotationInverse;
705 for (int k = 0; k < 3; k++) for (int l = 0; l < 3; l++) rotationInverse[k][l] = rotation.GetInverse()[k][l];
706 landmarkItk = rotationInverse * (landmarkItk - translation);
707
708 //convert back and add landmark to pointset
709 landmark[0] = landmarkItk[0];
710 landmark[1] = landmarkItk[1];
711 landmark[2] = landmarkItk[2];
712 m_RegistrationLandmarks->InsertPoint(m_RegistrationLandmarks->GetSize(), landmark);
713}
714
716{
717 if (m_ToolToCalibrate.IsNotNull())
718 {
719 mitk::NavigationTool::Pointer calibratedTool = m_ToolToCalibrate;
720 calibratedTool->SetToolControlPoints(this->m_CalibrationLandmarks);
721 calibratedTool->SetToolLandmarks(this->m_RegistrationLandmarks);
722 mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New();
723 QString filename = QFileDialog::getSaveFileName(nullptr,tr("Save Navigation Tool"), "/", "*.IGTTool");
724 if (filename.isEmpty()) return;
725
726 // ensure that file suffix is set
727 QFileInfo file(filename);
728 if (file.suffix().isEmpty())
729 {
730 filename += ".IGTTool";
731 }
732
733 if (myWriter->DoWrite(filename.toStdString(), calibratedTool)) MITK_INFO << "Saved calibrated tool to file " << filename;
734 else MITK_WARN << "Can't write tool to file " << filename;
735 }
736 else
737 {
738 MITK_ERROR << "Did not find navigation tool storage of calibrated tool, aborting!";
739 }
740}
741
743{
744 if ((m_IDToolToCalibrate == -1) ||
745 ((CalibrationPointerRequired) &&
747 )
748 )
749 {
750 QMessageBox msgBox;
751 msgBox.setText("Tool to calibrate and/or calibration pointer not initialized, cannot proceed!");
752 msgBox.exec();
753 return false;
754 }
755 else { return true; }
756}
mitk::NavigationData::Pointer m_ComputedToolTipTransformation
void ApplyToolTipTransform(mitk::NavigationData::Pointer ToolTipTransformInToolCoordinates, std::string message="Tool was updated with the calibrated tool tip!")
Ui::IGTNavigationToolCalibrationControls m_Controls
void OnManualEditToolTipFinished(mitk::AffineTransform3D::Pointer toolTip)
void ShowToolTipPreview(mitk::NavigationData::Pointer ToolTipInTrackingCoordinates)
std::vector< mitk::NavigationData::Pointer > m_LoggedNavigationDataDifferences
std::vector< mitk::NavigationData::Pointer > m_PivotPoses
std::vector< mitk::Point3D > m_LoggedNavigationDataOffsets
bool CheckInitialization(bool CalibrationPointerRequired=true)
mitk::NavigationDataSource::Pointer m_NavigationDataSourceOfCalibrationPointer
mitk::NavigationData::Pointer m_AxisCalibration_ToolToCalibrate
QmitkInteractiveTransformationWidget * m_ToolTransformationWidget
mitk::NavigationDataSource::Pointer m_NavigationDataSourceOfToolToCalibrate
mitk::NavigationData::Pointer m_AxisCalibration_NavDataCalibratingTool
An object of this class offers an UI to create a widget to access the advanced tool creation options.
void SetDefaultRotation(const mitk::Quaternion _defaultValues)
void SetDefaultOffset(const mitk::Point3D _defaultValues)
void SetToolToEdit(const mitk::NavigationTool::Pointer _tool)
static mitk::Quaternion CalcAverage(const std::vector< Quaternion > &quaternions, Mode mode=SimpleMean)
Connects a mitk::TrackingDevice to a MITK-IGT NavigationData-Filterpipeline.