CustusX  20.03-rc1
An IGT application
cxLapFrameToolCalibrationWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 
14 
15 #include <QPushButton>
16 #include <QTextStream>
17 #include <QFileDialog>
18 #include <QMessageBox>
19 #include "cxTypeConversions.h"
20 #include "cxLogger.h"
21 #include "cxTrackingService.h"
22 #include "cxVector3D.h"
24 #include "cxTool.h"
25 #include "cxTrackingService.h"
26 #include <cxActiveToolWidget.h>
27 #include "cxDoubleWidgets.h"
28 #include "cxVisServices.h"
30 
31 namespace cx
32 {
33 
34 //------------------------------------------------------------------------------
36  BaseWidget(parent, "lap_frame_tool_calibration_widget", "LapFrame Calibrate"),
37  mServices(services),
38  mCalibrateButton(new QPushButton("Calibrate")),
39  mReferencePointLabel(new QLabel("Ref. point:")),
40  mTestButton(new QPushButton("Test calibration")),
41  mCalibrationLabel(new QLabel("Calibration: \n")),
42  mDeltaLabel(new QLabel("Delta:"))
43 {
44  QVBoxLayout* toplayout = new QVBoxLayout(this);
45 
46  mCameraAngleAdapter = DoubleProperty::initialize("Camera Angle", "",
47  "Additional tilt of calibration around tool y-axis,\nfor use with cameras tilted relative to tool direction",
48  0.0, DoubleRange(-M_PI/2, M_PI/2, M_PI/180), 0);
49  mCameraAngleAdapter->setInternal2Display(180.0/M_PI);
50 
51  mCalibRefTool = StringPropertySelectTool::New(mServices->tracking());
52  mCalibRefTool->setValueName("Calibration Frame");
53  mCalibRefTool->setHelp("Select Calibration Reference Frame");
54 
55  mCalibratingTool = StringPropertySelectTool::New(mServices->tracking());
56  mCalibratingTool->setValueName("Tool");
57  mCalibratingTool->setHelp("Select which Tool to calibrate");
58 
59  this->setToolTip("Calibrate tool matrix using a custom frame");
60 
61 // toplayout->addWidget(new QLabel("<b>Select a tool with a known reference point:</b>"));
62  toplayout->addWidget(new LabeledComboBoxWidget(this, mCalibRefTool));
63  toplayout->addWidget(mReferencePointLabel);
64  toplayout->addWidget(new LabeledComboBoxWidget(this, mCalibratingTool));
65 // toplayout->addWidget(new ActiveToolWidget(this));
66  toplayout->addWidget(new SpinBoxAndSliderGroupWidget(this, mCameraAngleAdapter));
67  toplayout->addWidget(mCalibrateButton);
68  toplayout->addWidget(mCalibrationLabel);
69  toplayout->addWidget(this->createHorizontalLine());
70  toplayout->addWidget(mTestButton);
71  toplayout->addWidget(mDeltaLabel);
72  toplayout->addStretch();
73 
74  mReferencePointLabel->setText("<i> Use only with the special Laparascopic <br>"
75  "calibration frame as reference. </i>");
76 
77  connect(mCalibrateButton, SIGNAL(clicked()), this, SLOT(calibrateSlot()));
78  connect(mTestButton, SIGNAL(clicked()), this, SLOT(testCalibrationSlot()));
79 
80  connect(mCalibRefTool.get(), SIGNAL(changed()), this, SLOT(toolSelectedSlot()));
81 
82  //setting default state
83  this->toolSelectedSlot();
84 
85  connect(mServices->tracking().get(), &cx::TrackingService::stateChanged, this, &LapFrameToolCalibrationWidget::trackingStartedSlot);
86 }
87 
89 {}
90 
91 void LapFrameToolCalibrationWidget::calibrateSlot()
92 {
93  ToolPtr refTool = mCalibRefTool->getTool();
94  ToolPtr tool = mCalibratingTool->getTool();
95  double cameraAngle = mCameraAngleAdapter->getValue();
96  if(!refTool || !tool)
97  {
98  reportError(QString("Calibration prerequisited not met: calref:%1, tool:%2").arg(refTool!=0).arg(tool!=0) );
99  return;
100  }
101  if(!refTool->getVisible() || !tool->getVisible() || !refTool->hasReferencePointWithId(1))
102  {
103  reportError(QString("Calibration prerequisited not met: calref vis:%1, tool vis :%2, refpoint:%3").arg(refTool->getVisible()).arg(tool->getVisible()).arg(refTool->hasReferencePointWithId(1)) );
104  return;
105  }
106 
107  LapFrameToolCalibrationCalculator calc(tool, refTool, cameraAngle);
108  Transform3D calibration = calc.get_calibration_sMt();
109 
110  QMessageBox msgBox;
111  msgBox.setText("Do you want to overwrite "+tool->getName()+"'s calibration file?");
112  msgBox.setInformativeText("This cannot be undone.");
113  msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
114  msgBox.setDefaultButton(QMessageBox::Ok);
115  int ret = msgBox.exec();
116 
117  if(ret == QMessageBox::Ok)
118  {
119  try
120  {
121  tool->setCalibration_sMt(calibration);
122  }
123  catch(std::exception& e)
124  {
125  QMessageBox msgBox2;
126  msgBox2.setText("Unknown error, could not calibrate the tool: "+tool->getName()+".");
127  msgBox2.setInformativeText(QString(e.what()));
128  msgBox2.setStandardButtons(QMessageBox::Ok);
129  msgBox2.setDefaultButton(QMessageBox::Ok);
130  int ret2 = msgBox2.exec();
131  return;
132  }
133  mCalibrationLabel->setText(QString("Calibration matrix for %1:\n%2").arg(tool->getName(), qstring_cast(calibration)));
134  }
135 }
136 
137 void LapFrameToolCalibrationWidget::testCalibrationSlot()
138 {
139  ToolPtr refTool = mCalibRefTool->getTool();
140  ToolPtr tool = mCalibratingTool->getTool();
141  double cameraAngle = mCameraAngleAdapter->getValue();
142 
143  if(!refTool || !tool || !refTool->hasReferencePointWithId(1))
144  return;
145 
146  LapFrameToolCalibrationCalculator calc(tool, refTool, cameraAngle);
147  Vector3D delta_selectedTool = calc.get_delta_ref();
148 
149  QString delta = QString("%1 mm").arg(delta_selectedTool.length(), 6, 'g', 1);
150  mDeltaLabel->setText("<b>Delta "+tool->getName()+":</b> "+qstring_cast(delta_selectedTool)+" <br> <b>Accuracy:</b> " + delta);
151 
152  report("Delta "+tool->getName()+": "+qstring_cast(delta_selectedTool)+" Length: "+ delta);
153 
154 
155 }
156 
157 void LapFrameToolCalibrationWidget::toolSelectedSlot()
158 {
159  // QString text("Ref. point: <UNDEFINED POINT>");
160  mCalibrateButton->setEnabled(false);
161  mTestButton->setEnabled(false);
162 
163  if (mCalibRefTool->getTool())
164  {
165 // mCalibrationLabel->setText("Calibration:\n" + qstring_cast(mCalibratingTool->getTool()->getCalibration_sMt()));
166 // Transform3D calibration = mCalibratingTool->getTool()->getCalibration_sMt();
167 // mCalibrationLabel->setText(QString("Calibration matrix for %1:\n%2").arg(tool->getName(), qstring_cast(calibration)));
168  mCalibrateButton->setEnabled(true);
169  mTestButton->setEnabled(true);
170  }
171 
172  // mReferencePointLabel->setText(text);
173 }
174 //------------------------------------------------------------------------------
175 
176 void LapFrameToolCalibrationWidget::trackingStartedSlot()
177 {
178  ToolPtr ref = mServices->tracking()->getTool("calibration_tool");
179  if (ref)
180  mCalibRefTool->setValue(ref->getUid());
181 }
182 
183 //------------------------------------------------------------------------------
184 //------------------------------------------------------------------------------
185 //------------------------------------------------------------------------------
186 
187 
188 
189 
191  mTool(tool), mCalibrationRef(calRef), mCameraAngle(cameraAngle)
192 {
193  m_sMpr = mTool->getCalibration_sMt() * mTool->get_prMt().inv();
194 
195 // m_qMcr = Transform3D::fromString(" 0.0, 0.0, -1.0, -71.5,"
196 // " 0.0, -1.0, 0.0, -8.0,"
197 // "-1.0, 0.0, 0.0, -8.8,"
198 // " 0.0, 0.0, 0.0, 1.0");
199 
200  m_qMcr = Transform3D::Identity();
201  m_qMpr = m_qMcr * mCalibrationRef->get_prMt().inv();
202 }
203 
205 {
206  Vector3D p(0,0,0);
207  Transform3D qMpr = m_qMcr * mCalibrationRef->get_prMt().inv();
208 
209  Vector3D calibPoint_pr = qMpr.inv().coord(p);
210  Vector3D toolPoint_pr = mTool->get_prMt().coord(p);
211  return calibPoint_pr - toolPoint_pr;
212 }
213 
215 {
216  Transform3D calibration = m_sMpr * m_qMpr.inv() * createTransformRotateY(mCameraAngle);
217  this->useOnlyRotationalPart(&calibration);
218  return calibration;
219 }
220 
231 void LapFrameToolCalibrationCalculator::useOnlyRotationalPart(Transform3D* transform)
232 {
233  Transform3D::LinearMatrixType rotationalPart = transform->rotation();
234  transform->linear() = rotationalPart;
235 }
236 
237 }
QString qstring_cast(const T &val)
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
Transform3D createTransformRotateY(const double angle)
void reportError(QString msg)
Definition: cxLogger.cpp:71
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:40
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Utility class for describing a bounded numeric range.
Definition: cxDoubleRange.h:32
Transform3D get_calibration_sMt()
new calibration matrix for the input tool.
Vector3D get_delta_ref()
how far from the reference point the sampled point is, in pr&#39;s coord
Composite widget for string selection.
Composite widget for scalar data manipulation.
static QFrame * createHorizontalLine()
Creates a horizontal line which can be inserted into widgets.
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:88
static StringPropertySelectToolPtr New(TrackingServicePtr trackingService)
void report(QString msg)
Definition: cxLogger.cpp:69
static DoublePropertyPtr initialize(const QString &uid, QString name, QString help, double value, DoubleRange range, int decimals, QDomNode root=QDomNode())
LapFrameToolCalibrationWidget(VisServicesPtr services, QWidget *parent)
LapFrameToolCalibrationCalculator(ToolPtr tool, ToolPtr calRef, double cameraAngle)
#define M_PI
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr