PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPivotDetectionTest.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
13 #include "PlusConfigure.h"
14 #include "PlusMath.h"
15 #include "igsioTrackedFrame.h"
16 #include "vtkPlusDataCollector.h"
17 #include "vtkMatrix4x4.h"
18 #include "vtkMinimalStandardRandomSequence.h"
19 #include "vtkIGSIOSequenceIO.h"
21 #include "vtkPivotDetectionAlgo.h"
22 #include "vtkPlusChannel.h"
23 #include "vtkSmartPointer.h"
24 #include "vtkIGSIOTrackedFrameList.h"
25 #include "vtkTransform.h"
26 #include "vtkIGSIOTransformRepository.h"
27 #include "vtkXMLDataElement.h"
28 #include "vtkXMLUtilities.h"
29 #include "vtksys/CommandLineArguments.hxx"
30 #include "vtksys/SystemTools.hxx"
31 #include <iostream>
32 #include <stdlib.h>
33 
35 const double ERROR_THRESHOLD_MM=0.001;
36 
37 int main (int argc, char* argv[])
38 {
39  std::string inputConfigFileName;
40  std::string inputBaselineFileName;
41 
42  std::string inputTrackedStylusTipSequenceMetafile;
43  std::string stylusTipToStylusTransformNameStr;
44 
45  int verboseLevel=vtkPlusLogger::LOG_LEVEL_UNDEFINED;
46 
47  vtksys::CommandLineArguments cmdargs;
48  cmdargs.Initialize(argc, argv);
49 
50  cmdargs.AddArgument("--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputConfigFileName, "Configuration file name");
51  cmdargs.AddArgument("--baseline-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputBaselineFileName, "Name of file storing baseline calibration results");
52  cmdargs.AddArgument("--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel, "Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
53 
54  cmdargs.AddArgument("--tracker-input-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputTrackedStylusTipSequenceMetafile, "Input tracker sequence metafile name with path");
55  cmdargs.AddArgument("--stylus-tip-to-stylus-transform", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &stylusTipToStylusTransformNameStr,
56  "Transform name that describes the probe pose relative to a static reference (default: StylusTipToReference)");
57 
58  if ( !cmdargs.Parse() )
59  {
60  std::cerr << "Problem parsing arguments" << std::endl;
61  std::cout << "Help: " << cmdargs.GetHelp() << std::endl;
62  exit(EXIT_FAILURE);
63  }
64  vtkPlusLogger::Instance()->SetLogLevel(verboseLevel);
65 
66  LOG_INFO("Initialize");
67  // Read configuration
68  vtkSmartPointer<vtkXMLDataElement> configRootElement = vtkSmartPointer<vtkXMLDataElement>::New();
69  if (PlusXmlUtils::ReadDeviceSetConfigurationFromFile(configRootElement, inputConfigFileName.c_str())==PLUS_FAIL)
70  {
71  LOG_ERROR("Unable to read configuration from file " << inputConfigFileName.c_str());
72  return EXIT_FAILURE;
73  }
74 
75  // Initialize stylus detection
76  vtkSmartPointer<vtkPivotDetectionAlgo> PivotDetection = vtkSmartPointer<vtkPivotDetectionAlgo>::New();
77  if (PivotDetection == NULL)
78  {
79  LOG_ERROR("Unable to instantiate pivot detection algorithm class!");
80  exit(EXIT_FAILURE);
81  }
82 
83  if (PivotDetection->ReadConfiguration(configRootElement) != PLUS_SUCCESS)
84  {
85  LOG_ERROR("Unable to read pivot calibration configuration!");
86  exit(EXIT_FAILURE);
87  }
88 
89  // Read stylus tracker data
90  vtkSmartPointer<vtkIGSIOTrackedFrameList> trackedStylusTipFrames = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
91  if( !stylusTipToStylusTransformNameStr.empty() )
92  {
93  trackedStylusTipFrames->SetValidationRequirements(REQUIRE_UNIQUE_TIMESTAMP | REQUIRE_TRACKING_OK);
94  }
95 
96  LOG_INFO("Read stylus tracker data from " << inputTrackedStylusTipSequenceMetafile);
97  if( vtkIGSIOSequenceIO::Read(inputTrackedStylusTipSequenceMetafile, trackedStylusTipFrames) != PLUS_SUCCESS )
98  {
99  LOG_ERROR("Failed to read stylus data from sequence metafile: " << inputTrackedStylusTipSequenceMetafile << ". Exiting...");
100  exit(EXIT_FAILURE);
101  }
102 
103  vtkSmartPointer<vtkIGSIOTransformRepository> transformRepository = vtkSmartPointer<vtkIGSIOTransformRepository>::New();
104 
105  // Check stylus tool
106  igsioTransformName stylusToReferenceTransformName(PivotDetection->GetObjectMarkerCoordinateFrame(), PivotDetection->GetReferenceCoordinateFrame());
107 
108  vtkSmartPointer<vtkIGSIOTransformRepository> transformRepositoryCalibration = vtkSmartPointer<vtkIGSIOTransformRepository>::New();
109  if ( transformRepositoryCalibration->ReadConfiguration(configRootElement) != PLUS_SUCCESS )
110  {
111  LOG_ERROR("Failed to read CoordinateDefinitions!");
112  exit(EXIT_FAILURE);
113  }
114  vtkSmartPointer<vtkMatrix4x4> stylusTipToStylusTransform = vtkSmartPointer<vtkMatrix4x4>::New();
115  bool valid = false;
116  transformRepositoryCalibration->GetTransform(stylusTipToStylusTransformNameStr, stylusTipToStylusTransform, &valid);
117  double pivotFound[3] = {0,0,0};
118  double pivotLandmark[3] = {0,0,0};
119  if (valid)
120  {
121  // Acquire positions for pivot calibration
122  for (int i=0; i < trackedStylusTipFrames->GetNumberOfTrackedFrames(); ++i)
123  {
124  //vtkPlusLogger::PrintProgressbar((100.0 * i) / trackedStylusTipFrames->GetNumberOfTrackedFrames());
125  vtkSmartPointer<vtkMatrix4x4> stylusToReferenceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
126 
127  if ( transformRepository->SetTransforms(*(trackedStylusTipFrames->GetTrackedFrame(i))) != PLUS_SUCCESS )
128  {
129  LOG_ERROR("Failed to update transforms in repository with tracked frame!");
130  exit(EXIT_FAILURE);
131  }
132 
133  valid = false;
134  if ( (transformRepository->GetTransform(stylusToReferenceTransformName, stylusToReferenceMatrix, &valid) != PLUS_SUCCESS) || (!valid) )
135  {
136  LOG_ERROR("No valid transform found between stylus to reference!");
137  exit(EXIT_FAILURE);
138  }
139  vtkSmartPointer<vtkMatrix4x4> stylusTipToReferenceTransformMatrix = vtkMatrix4x4::New();
140  vtkMatrix4x4::Multiply4x4(stylusToReferenceMatrix,stylusTipToStylusTransform,stylusTipToReferenceTransformMatrix);
141  PivotDetection->InsertNextStylusTipToReferenceTransform(stylusTipToReferenceTransformMatrix);
142  PivotDetection->IsNewPivotPointFound(valid);
143  if(valid)
144  {
145  PivotDetection->GetPivotPointsReference()->GetPoint(PivotDetection->GetPivotPointsReference()->GetNumberOfPoints()-1, pivotFound);
146  LOG_INFO("\nPivot found (" << pivotFound[0]<<", " << pivotFound[1]<<", " << pivotFound[2]<<") at "<<trackedStylusTipFrames->GetTrackedFrame(i)->GetTimestamp()<<"[ms]");
147  }
148  PivotDetection->IsPivotDetectionCompleted(valid);
149  if(valid)
150  {
151  break;
152  }
153  }
154  }
155  else
156  {
157  LOG_ERROR("No valid transform found between stylus to stylus tip!");
158  }
159 
160  if (!inputBaselineFileName.empty())
161  {
162  // Load baseline stylus detection
163  vtkSmartPointer<vtkXMLDataElement> baselineRootElem = vtkSmartPointer<vtkXMLDataElement>::Take(vtkXMLUtilities::ReadElementFromFile(inputBaselineFileName.c_str()));
164  if (baselineRootElem == NULL)
165  {
166  LOG_ERROR("Unable to read the baseline configuration file: " << inputBaselineFileName);
167  }
168  // Phantom registration to read landmarks but there could b done in a nicer way
169  vtkSmartPointer<vtkPlusPhantomLandmarkRegistrationAlgo> pivotDetectionBaselineLandmarks = vtkSmartPointer<vtkPlusPhantomLandmarkRegistrationAlgo>::New();
170  if (pivotDetectionBaselineLandmarks == NULL)
171  {
172  LOG_ERROR("Unable to instantiate phantom registration algorithm class!");
173  exit(EXIT_FAILURE);
174  }
175  if (pivotDetectionBaselineLandmarks->ReadConfiguration(baselineRootElem) != PLUS_SUCCESS)
176  {
177  LOG_ERROR("Unable to read pivot Detection Baseline Landmarks!");
178  exit(EXIT_FAILURE);
179  }
180 
181  int numberOfLandmarks = pivotDetectionBaselineLandmarks->GetDefinedLandmarks()->GetNumberOfPoints();
182  if (numberOfLandmarks != PivotDetection->GetExpectedPivotsNumber())
183  {
184  LOG_ERROR("Number of defined landmarks should be "<<PivotDetection->GetExpectedPivotsNumber()<< " instead of " << numberOfLandmarks << "!");
185  exit(EXIT_FAILURE);
186  }
187  //if (PivotDetection->GetPivotPointsReference()->GetNumberOfPoints()==numberOfLandmarks)
188  //{
189  for (int id =0; id<PivotDetection->GetPivotPointsReference()->GetNumberOfPoints();id++)
190  {
191  // Compare to baseline
192  pivotDetectionBaselineLandmarks->GetDefinedLandmarks()->GetPoint(id, pivotLandmark);
193  PivotDetection->GetPivotPointsReference()->GetPoint(id, pivotFound);
194  pivotLandmark[0]=pivotFound[0]-pivotLandmark[0];
195  pivotLandmark[1]=pivotFound[1]-pivotLandmark[1];
196  pivotLandmark[2]=pivotFound[2]-pivotLandmark[2];
197  if (vtkMath::Norm(pivotLandmark)>ERROR_THRESHOLD_MM)
198  {
199  LOG_ERROR("Comparison of calibration data to baseline failed");
200  std::cout << "Exit failure!!!" << std::endl;
201  return EXIT_FAILURE;
202  }
203  else
204  {
205  LOG_INFO("\nPivot "<< id << " found (" << pivotFound[0]<<", " << pivotFound[1]<<", " << pivotFound[2]);
206  }
207  }
208  //}
209  //else
210  //{
211  // LOG_ERROR("Comparison of calibration data to baseline failed, not the same number of detected landmarks");
212  // std::cout << "Exit failure!!!" << std::endl;
213  // return EXIT_FAILURE;
214  //}
215 
216  }
217  else
218  {
219  LOG_DEBUG("Baseline file is not specified. Computed results are not compared to baseline results.");
220  }
221 
222  std::cout << "Exit success!!!" << std::endl;
223  return EXIT_SUCCESS;
224 }
225 
226 
const double ERROR_THRESHOLD_MM
for i
#define PLUS_FAIL
Definition: PlusCommon.h:43
int main(int argc, char *argv[])
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
static vtkIGSIOLogger * Instance()
static PlusStatus ReadDeviceSetConfigurationFromFile(vtkXMLDataElement *config, const char *filename)
Definition: PlusXmlUtils.h:23