bool mitk::PivotCalibration::ComputePivotPoint() { double defaultThreshold = 1e-1; std::vector<mitk::NavigationData::Pointer> _CheckedTransforms; for (size_t i = 0; i < m_NavigationDatas.size(); ++i) { if (!m_NavigationDatas.at(i)->IsDataValid()) { MITK_WARN << "Skipping invalid transform " << i << "."; continue; } _CheckedTransforms.push_back(m_NavigationDatas.at(i)); } if (_CheckedTransforms.empty()) { MITK_WARN << "Checked Transforms are empty"; return false; } unsigned int rows = 3 * _CheckedTransforms.size(); unsigned int columns = 6; vnl_matrix< double > A(rows, columns), minusI(3, 3, 0), R(3, 3); vnl_vector< double > b(rows), x(columns), t(3); minusI(0, 0) = -1; minusI(1, 1) = -1; minusI(2, 2) = -1; //do the computation and set the internal variables unsigned int currentRow = 0; for (size_t i = 0; i < _CheckedTransforms.size(); ++i) { t = _CheckedTransforms.at(i)->GetPosition().GetVnlVector();// t = the current position of the tracked sensor t *= -1; b.update(t, currentRow); //b = combines the position for each collected transform in one column vector R = _CheckedTransforms.at(i)->GetOrientation().rotation_matrix_transpose().transpose(); // R = the current rotation of the tracked sensor, *rotation_matrix_transpose().transpose() is used to obtain original matrix A.update(R, currentRow, 0); //A = the matrix which stores the rotations for each collected transform and -I A.update(minusI, currentRow, 3); currentRow += 3; } vnl_svd<double> svdA(A); //The singular value decomposition of matrix A svdA.zero_out_absolute(defaultThreshold); //there is a solution only if rank(A)=6 (columns are linearly //independent) if (svdA.rank() < 6) { MITK_WARN << "svdA.rank() < 6"; return false; } else { x = svdA.solve(b); //x = the resulting pivot point m_ResultRMSError = (A * x - b).rms(); //the root mean sqaure error of the computation //sets the Pivot Point m_ResultPivotPoint[0] = x[0]; m_ResultPivotPoint[1] = x[1]; m_ResultPivotPoint[2] = x[2]; } return true; }
/* Description: */ bool PivotCalibration2::ComputePivotCalibration() { if (this->ToolToReferenceMatrices.size() < 10) { this->ErrorText = "Not enough input transforms are available"; return false; } if (this->GetMaximumToolOrientationDifferenceDeg() < this->MinimumOrientationDifferenceDeg) { this->ErrorText = "Not enough variation in the input transforms"; return false; } unsigned int rows = 3 * this->ToolToReferenceMatrices.size(); unsigned int columns = 6; vnl_matrix<double> A(rows, columns); vnl_matrix<double> minusI(3, 3, 0); minusI(0, 0) = -1; minusI(1, 1) = -1; minusI(2, 2) = -1; vnl_matrix<double> R(3, 3); vnl_vector<double> b(rows); vnl_vector<double> x(columns); vnl_vector<double> t(3); std::vector<vtkSmartPointer<vtkMatrix4x4> >::const_iterator it; std::vector<vtkSmartPointer<vtkMatrix4x4> >::const_iterator matricesEnd = this->ToolToReferenceMatrices.end(); unsigned int currentRow; vtkMatrix4x4* referenceOrientationMatrix = this->ToolToReferenceMatrices.front(); for (currentRow = 0, it = this->ToolToReferenceMatrices.begin(); it != matricesEnd; it++, currentRow += 3) { for (int i = 0; i < 3; i++) { t(i) = (*it)->GetElement(i, 3); } t *= -1; b.update(t, currentRow); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { R(i, j) = (*it)->GetElement(i, j); } } A.update(R, currentRow, 0); A.update(minusI, currentRow, 3); } vnl_svd<double> svdA(A); svdA.zero_out_absolute(1e-1); x = svdA.solve(b); //set the RMSE this->PivotRMSE = (A * x - b).rms(); //set the transformation this->ToolTipToToolMatrix->SetElement(0, 3, x[0]); this->ToolTipToToolMatrix->SetElement(1, 3, x[1]); this->ToolTipToToolMatrix->SetElement(2, 3, x[2]); this->ErrorText.empty(); return true; }