Fraxinus  17.12-rc3
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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 
35 
36 #include <QPushButton>
37 #include <QTextStream>
38 #include <QFileDialog>
39 #include <QMessageBox>
40 #include "cxTypeConversions.h"
41 #include "cxLogger.h"
42 #include "cxTrackingService.h"
43 #include "cxVector3D.h"
44 #include "cxDefinitionStrings.h"
46 #include "cxTool.h"
47 #include "cxTrackingService.h"
48 #include <cxActiveToolWidget.h>
49 #include "cxDoubleWidgets.h"
50 #include "cxVisServices.h"
52 
53 namespace cx
54 {
55 
56 //------------------------------------------------------------------------------
58  BaseWidget(parent, "lap_frame_tool_calibration_widget", "LapFrame Calibrate"),
59  mServices(services),
60  mCalibrateButton(new QPushButton("Calibrate")),
61  mReferencePointLabel(new QLabel("Ref. point:")),
62  mTestButton(new QPushButton("Test calibration")),
63  mCalibrationLabel(new QLabel("Calibration: \n")),
64  mDeltaLabel(new QLabel("Delta:"))
65 {
66  QVBoxLayout* toplayout = new QVBoxLayout(this);
67 
68  mCameraAngleAdapter = DoubleProperty::initialize("Camera Angle", "",
69  "Additional tilt of calibration around tool y-axis,\nfor use with cameras tilted relative to tool direction",
70  0.0, DoubleRange(-M_PI/2, M_PI/2, M_PI/180), 0);
71  mCameraAngleAdapter->setInternal2Display(180.0/M_PI);
72 
73  mCalibRefTool = StringPropertySelectTool::New(mServices->tracking());
74  mCalibRefTool->setValueName("Calibration Frame");
75  mCalibRefTool->setHelp("Select Calibration Reference Frame");
76 
77  mCalibratingTool = StringPropertySelectTool::New(mServices->tracking());
78  mCalibratingTool->setValueName("Tool");
79  mCalibratingTool->setHelp("Select which Tool to calibrate");
80 
81  this->setToolTip("Calibrate tool matrix using a custom frame");
82 
83 // toplayout->addWidget(new QLabel("<b>Select a tool with a known reference point:</b>"));
84  toplayout->addWidget(new LabeledComboBoxWidget(this, mCalibRefTool));
85  toplayout->addWidget(mReferencePointLabel);
86  toplayout->addWidget(new LabeledComboBoxWidget(this, mCalibratingTool));
87 // toplayout->addWidget(new ActiveToolWidget(this));
88  toplayout->addWidget(new SpinBoxAndSliderGroupWidget(this, mCameraAngleAdapter));
89  toplayout->addWidget(mCalibrateButton);
90  toplayout->addWidget(mCalibrationLabel);
91  toplayout->addWidget(this->createHorizontalLine());
92  toplayout->addWidget(mTestButton);
93  toplayout->addWidget(mDeltaLabel);
94  toplayout->addStretch();
95 
96  mReferencePointLabel->setText("<i> Use only with the special Laparascopic <br>"
97  "calibration frame as reference. </i>");
98 
99  connect(mCalibrateButton, SIGNAL(clicked()), this, SLOT(calibrateSlot()));
100  connect(mTestButton, SIGNAL(clicked()), this, SLOT(testCalibrationSlot()));
101 
102  connect(mCalibRefTool.get(), SIGNAL(changed()), this, SLOT(toolSelectedSlot()));
103 
104  //setting default state
105  this->toolSelectedSlot();
106 
107  connect(mServices->tracking().get(), &cx::TrackingService::stateChanged, this, &LapFrameToolCalibrationWidget::trackingStartedSlot);
108 }
109 
111 {}
112 
113 void LapFrameToolCalibrationWidget::calibrateSlot()
114 {
115  ToolPtr refTool = mCalibRefTool->getTool();
116  ToolPtr tool = mCalibratingTool->getTool();
117  double cameraAngle = mCameraAngleAdapter->getValue();
118  if(!refTool || !tool)
119  {
120  reportError(QString("Calibration prerequisited not met: calref:%1, tool:%2").arg(refTool!=0).arg(tool!=0) );
121  return;
122  }
123  if(!refTool->getVisible() || !tool->getVisible() || !refTool->hasReferencePointWithId(1))
124  {
125  reportError(QString("Calibration prerequisited not met: calref vis:%1, tool vis :%2, refpoint:%3").arg(refTool->getVisible()).arg(tool->getVisible()).arg(refTool->hasReferencePointWithId(1)) );
126  return;
127  }
128 
129  LapFrameToolCalibrationCalculator calc(tool, refTool, cameraAngle);
130  Transform3D calibration = calc.get_calibration_sMt();
131 
132  QMessageBox msgBox;
133  msgBox.setText("Do you want to overwrite "+tool->getName()+"'s calibration file?");
134  msgBox.setInformativeText("This cannot be undone.");
135  msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
136  msgBox.setDefaultButton(QMessageBox::Ok);
137  int ret = msgBox.exec();
138 
139  if(ret == QMessageBox::Ok)
140  {
141  try
142  {
143  tool->setCalibration_sMt(calibration);
144  }
145  catch(std::exception& e)
146  {
147  QMessageBox msgBox2;
148  msgBox2.setText("Unknown error, could not calibrate the tool: "+tool->getName()+".");
149  msgBox2.setInformativeText(QString(e.what()));
150  msgBox2.setStandardButtons(QMessageBox::Ok);
151  msgBox2.setDefaultButton(QMessageBox::Ok);
152  int ret2 = msgBox2.exec();
153  return;
154  }
155  mCalibrationLabel->setText(QString("Calibration matrix for %1:\n%2").arg(tool->getName(), qstring_cast(calibration)));
156  }
157 }
158 
159 void LapFrameToolCalibrationWidget::testCalibrationSlot()
160 {
161  ToolPtr refTool = mCalibRefTool->getTool();
162  ToolPtr tool = mCalibratingTool->getTool();
163  double cameraAngle = mCameraAngleAdapter->getValue();
164 
165  if(!refTool || !tool || !refTool->hasReferencePointWithId(1))
166  return;
167 
168  LapFrameToolCalibrationCalculator calc(tool, refTool, cameraAngle);
169  Vector3D delta_selectedTool = calc.get_delta_ref();
170 
171  QString delta = QString("%1 mm").arg(delta_selectedTool.length(), 6, 'g', 1);
172  mDeltaLabel->setText("<b>Delta "+tool->getName()+":</b> "+qstring_cast(delta_selectedTool)+" <br> <b>Accuracy:</b> " + delta);
173 
174  report("Delta "+tool->getName()+": "+qstring_cast(delta_selectedTool)+" Length: "+ delta);
175 
176 
177 }
178 
179 void LapFrameToolCalibrationWidget::toolSelectedSlot()
180 {
181  // QString text("Ref. point: <UNDEFINED POINT>");
182  mCalibrateButton->setEnabled(false);
183  mTestButton->setEnabled(false);
184 
185  if (mCalibRefTool->getTool())
186  {
187 // mCalibrationLabel->setText("Calibration:\n" + qstring_cast(mCalibratingTool->getTool()->getCalibration_sMt()));
188 // Transform3D calibration = mCalibratingTool->getTool()->getCalibration_sMt();
189 // mCalibrationLabel->setText(QString("Calibration matrix for %1:\n%2").arg(tool->getName(), qstring_cast(calibration)));
190  mCalibrateButton->setEnabled(true);
191  mTestButton->setEnabled(true);
192  }
193 
194  // mReferencePointLabel->setText(text);
195 }
196 //------------------------------------------------------------------------------
197 
198 void LapFrameToolCalibrationWidget::trackingStartedSlot()
199 {
200  ToolPtr ref = mServices->tracking()->getTool("calibration_tool");
201  if (ref)
202  mCalibRefTool->setValue(ref->getUid());
203 }
204 
205 //------------------------------------------------------------------------------
206 //------------------------------------------------------------------------------
207 //------------------------------------------------------------------------------
208 
209 
210 
211 
213  mTool(tool), mCalibrationRef(calRef), mCameraAngle(cameraAngle)
214 {
215  m_sMpr = mTool->getCalibration_sMt() * mTool->get_prMt().inv();
216 
217 // m_qMcr = Transform3D::fromString(" 0.0, 0.0, -1.0, -71.5,"
218 // " 0.0, -1.0, 0.0, -8.0,"
219 // "-1.0, 0.0, 0.0, -8.8,"
220 // " 0.0, 0.0, 0.0, 1.0");
221 
222  m_qMcr = Transform3D::Identity();
223  m_qMpr = m_qMcr * mCalibrationRef->get_prMt().inv();
224 }
225 
227 {
228  Vector3D p(0,0,0);
229  Transform3D qMpr = m_qMcr * mCalibrationRef->get_prMt().inv();
230 
231  Vector3D calibPoint_pr = qMpr.inv().coord(p);
232  Vector3D toolPoint_pr = mTool->get_prMt().coord(p);
233  return calibPoint_pr - toolPoint_pr;
234 }
235 
237 {
238  Transform3D calibration = m_sMpr * m_qMpr.inv() * createTransformRotateY(mCameraAngle);
239  this->useOnlyRotationalPart(&calibration);
240  return calibration;
241 }
242 
253 void LapFrameToolCalibrationCalculator::useOnlyRotationalPart(Transform3D* transform)
254 {
255  Transform3D::LinearMatrixType rotationalPart = transform->rotation();
256  transform->linear() = rotationalPart;
257 }
258 
259 }
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:92
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:61
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
Utility class for describing a bounded numeric range.
Definition: cxDoubleRange.h:53
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:63
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:109
static StringPropertySelectToolPtr New(TrackingServicePtr trackingService)
void report(QString msg)
Definition: cxLogger.cpp:90
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