13 #include "PlusConfigure.h" 15 #include "igsioTrackedFrame.h" 17 #include "vtkMatrix4x4.h" 18 #include "vtkMinimalStandardRandomSequence.h" 22 #include "vtkSmartPointer.h" 23 #include "vtkIGSIOTrackedFrameList.h" 24 #include "vtkTransform.h" 25 #include "vtkIGSIOTransformRepository.h" 26 #include "vtkXMLDataElement.h" 27 #include "vtkXMLUtilities.h" 28 #include "vtksys/CommandLineArguments.hxx" 29 #include "vtksys/SystemTools.hxx" 39 int main(
int argc,
char* argv[])
41 std::string inputConfigFileName;
42 std::string inputBaselineFileName;
44 int numberOfPointsToAcquire = 100;
45 int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
46 double outlierGenerationProbability = 0.0;
48 vtksys::CommandLineArguments cmdargs;
49 cmdargs.Initialize(argc, argv);
51 cmdargs.AddArgument(
"--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputConfigFileName,
"Configuration file name");
52 cmdargs.AddArgument(
"--baseline-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputBaselineFileName,
"Name of file storing baseline calibration results");
53 cmdargs.AddArgument(
"--number-of-points-to-acquire", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &numberOfPointsToAcquire,
"Number of acquired points during the pivot calibration (default: 100)");
54 cmdargs.AddArgument(
"--outlier-generation-probability", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outlierGenerationProbability,
"Probability for a point being an outlier. If this number is larger than 0 then some valid measurement points are replaced by randomly generated samples to test the robustness of the algorithm. (range: 0.0-1.0; default: 0.0)");
55 cmdargs.AddArgument(
"--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel,
"Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
59 std::cerr <<
"Problem parsing arguments" << std::endl;
60 std::cout <<
"Help: " << cmdargs.GetHelp() << std::endl;
66 std::string programPath(
"./"), errorMsg;
67 if (!vtksys::SystemTools::FindProgramPath(argv[0], programPath, errorMsg))
71 programPath = vtksys::SystemTools::GetParentDirectory(programPath.c_str());
73 LOG_INFO(
"Initialize");
76 vtkSmartPointer<vtkXMLDataElement> configRootElement = vtkSmartPointer<vtkXMLDataElement>::New();
79 LOG_ERROR(
"Unable to read configuration from file " << inputConfigFileName.c_str());
86 vtkSmartPointer<vtkPlusDataCollector> dataCollector = vtkSmartPointer<vtkPlusDataCollector>::New();
87 if (dataCollector->ReadConfiguration(configRootElement) !=
PLUS_SUCCESS)
89 LOG_ERROR(
"Unable to parse configuration from file " << inputConfigFileName.c_str());
95 LOG_ERROR(
"Unable to initialize data collection!");
100 LOG_ERROR(
"Unable to start data collection!");
105 if (dataCollector->GetDevice(aDevice, std::string(
"TrackerDevice")) !=
PLUS_SUCCESS)
107 LOG_ERROR(
"Unable to locate device by ID: \'TrackerDevice\'");
112 LOG_ERROR(
"Unable to locate channel by ID: \'TrackerStream\'");
117 LOG_ERROR(
"Channel \'" << aChannel->
GetChannelId() <<
"\' is not tracking!");
122 vtkSmartPointer<vtkPlusPivotCalibrationAlgo> pivotCalibration = vtkSmartPointer<vtkPlusPivotCalibrationAlgo>::New();
123 if (pivotCalibration == NULL)
125 LOG_ERROR(
"Unable to instantiate pivot calibration algorithm class!");
129 if (pivotCalibration->ReadConfiguration(configRootElement) !=
PLUS_SUCCESS)
131 LOG_ERROR(
"Unable to read pivot calibration configuration!");
136 igsioTrackedFrame trackedFrame;
139 vtkSmartPointer<vtkIGSIOTransformRepository> transformRepository = vtkSmartPointer<vtkIGSIOTransformRepository>::New();
140 transformRepository->SetTransforms(trackedFrame);
143 igsioTransformName stylusToReferenceTransformName(pivotCalibration->GetObjectMarkerCoordinateFrame(), pivotCalibration->GetReferenceCoordinateFrame());
145 vtkSmartPointer<vtkMinimalStandardRandomSequence> random = vtkSmartPointer<vtkMinimalStandardRandomSequence>::New();
146 random->SetSeed(183495439);
147 int numberOfOutliers = 0;
150 for (
int i = 0;
i < numberOfPointsToAcquire; ++
i)
152 vtksys::SystemTools::Delay(50);
153 vtkPlusLogger::PrintProgressbar((100.0 *
i) / numberOfPointsToAcquire);
155 vtkSmartPointer<vtkMatrix4x4> stylusToReferenceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
158 igsioTrackedFrame trackedFrame;
161 LOG_ERROR(
"Failed to get tracked frame!");
165 if (transformRepository->SetTransforms(trackedFrame) !=
PLUS_SUCCESS)
167 LOG_ERROR(
"Failed to update transforms in repository with tracked frame!");
171 ToolStatus status(TOOL_INVALID);
172 if (transformRepository->GetTransform(stylusToReferenceTransformName, stylusToReferenceMatrix, &status) !=
PLUS_SUCCESS || status != TOOL_OK)
174 LOG_ERROR(
"No valid transform found between stylus to reference!");
180 if (random->GetValue() < outlierGenerationProbability)
184 double rotX = random->GetRangeValue(-160, 160);
186 double rotY = random->GetRangeValue(-160, 160);
188 double rotZ = random->GetRangeValue(-160, 160);
189 double translation[3] = {0};
191 translation[0] = random->GetRangeValue(-1000, 1000);
193 translation[1] = random->GetRangeValue(-1000, 1000);
195 translation[2] = random->GetRangeValue(-1000, 1000);
197 vtkSmartPointer<vtkTransform> randomStylusToReferenceTransform = vtkSmartPointer<vtkTransform>::New();
198 randomStylusToReferenceTransform->Identity();
199 randomStylusToReferenceTransform->Translate(translation);
200 randomStylusToReferenceTransform->RotateX(rotX);
201 randomStylusToReferenceTransform->RotateY(rotY);
202 randomStylusToReferenceTransform->RotateZ(rotZ);
203 stylusToReferenceMatrix->DeepCopy(randomStylusToReferenceTransform->GetMatrix());
206 pivotCalibration->InsertNextCalibrationPoint(stylusToReferenceMatrix);
208 vtkPlusLogger::PrintProgressbar(100.0);
210 if (numberOfOutliers > 0)
212 LOG_INFO(
"Number of generated outlier samples: " << numberOfOutliers);
215 if (pivotCalibration->DoPivotCalibration(transformRepository) !=
PLUS_SUCCESS)
217 LOG_ERROR(
"Calibration error!");
221 LOG_INFO(
"Number of detected outliers: " << pivotCalibration->GetNumberOfDetectedOutliers());
222 LOG_INFO(
"Mean calibration error: " << pivotCalibration->GetPivotCalibrationErrorMm() <<
" mm");
225 if (transformRepository->WriteConfiguration(configRootElement) !=
PLUS_SUCCESS)
227 LOG_ERROR(
"Failed to write pivot calibration result to configuration element!");
231 std::string calibrationResultFileName =
"StylusCalibrationTest.xml";
232 LOG_INFO(
"Writing calibration result (" << pivotCalibration->GetObjectPivotPointCoordinateFrame() <<
" to " << pivotCalibration->GetObjectMarkerCoordinateFrame() <<
" transform) to " << calibrationResultFileName);
233 vtksys::SystemTools::RemoveFile(calibrationResultFileName.c_str());
234 igsioCommon::XML::PrintXML(calibrationResultFileName.c_str(), configRootElement);
236 if (!inputBaselineFileName.empty())
239 std::string objectMarkerCoordinateFrame = pivotCalibration->GetObjectMarkerCoordinateFrame();
240 std::string objectPivotCoordinateFrame = pivotCalibration->GetObjectPivotPointCoordinateFrame();
241 if (
CompareCalibrationResultsWithBaseline(inputBaselineFileName.c_str(), calibrationResultFileName.c_str(), objectMarkerCoordinateFrame.c_str(), objectPivotCoordinateFrame.c_str()) != 0)
243 LOG_ERROR(
"Comparison of calibration data to baseline failed");
244 std::cout <<
"Exit failure!!!" << std::endl;
250 LOG_DEBUG(
"Baseline file is not specified. Computed results are not compared to baseline results.");
253 std::cout <<
"Exit success!!!" << std::endl;
262 int numberOfFailures = 0;
265 vtkSmartPointer<vtkXMLDataElement> currentRootElem = vtkSmartPointer<vtkXMLDataElement>::Take(vtkXMLUtilities::ReadElementFromFile(currentResultFileName));
266 if (currentRootElem == NULL)
268 LOG_ERROR(
"Unable to read the current configuration file: " << currentResultFileName);
269 return ++numberOfFailures;
272 vtkSmartPointer<vtkMatrix4x4> stylusTipToStylusTransformCurrent = vtkSmartPointer<vtkMatrix4x4>::New();
273 double currentError(0);
274 if (
vtkPlusConfig::GetInstance()->ReadTransformToCoordinateDefinition(currentRootElem, stylusTipCoordinateFrame, stylusCoordinateFrame, stylusTipToStylusTransformCurrent, ¤tError) !=
PLUS_SUCCESS)
276 LOG_ERROR(
"Failed to read current pivot calibration result from configuration file!");
277 return ++numberOfFailures;
281 vtkSmartPointer<vtkXMLDataElement> baselineRootElem = vtkSmartPointer<vtkXMLDataElement>::Take(vtkXMLUtilities::ReadElementFromFile(baselineFileName));
282 if (baselineRootElem == NULL)
284 LOG_ERROR(
"Unable to read the baseline configuration file: " << baselineFileName);
285 return ++numberOfFailures;
288 vtkSmartPointer<vtkMatrix4x4> stylusTipToStylusTransformBaseline = vtkSmartPointer<vtkMatrix4x4>::New();
289 double baselineError(0);
290 if (
vtkPlusConfig::GetInstance()->ReadTransformToCoordinateDefinition(baselineRootElem, stylusTipCoordinateFrame, stylusCoordinateFrame, stylusTipToStylusTransformBaseline, &baselineError) !=
PLUS_SUCCESS)
292 LOG_ERROR(
"Failed to read current stylus calibration result from configuration file!");
293 return ++numberOfFailures;
297 double posDiff = igsioMath::GetPositionDifference(stylusTipToStylusTransformCurrent, stylusTipToStylusTransformBaseline);
298 double rotDiff = igsioMath::GetOrientationDifference(stylusTipToStylusTransformCurrent, stylusTipToStylusTransformBaseline);
300 std::ostringstream currentTransform;
301 stylusTipToStylusTransformCurrent->PrintSelf(currentTransform, vtkIndent(0));
302 std::ostringstream baselineTransform;
303 stylusTipToStylusTransformBaseline->PrintSelf(baselineTransform, vtkIndent(0));
308 LOG_INFO(
"Current StylusTipToStylus transform: " << currentTransform.str());
309 LOG_INFO(
"Baseline StylusTipToStylus transform: " << baselineTransform.str());
316 LOG_INFO(
"Current transform: " << currentTransform.str());
317 LOG_INFO(
"Baseline transform: " << baselineTransform.str());
321 return numberOfFailures;
Abstract interface for tracker and video devices.
virtual PlusStatus GetTrackedFrame(double timestamp, igsioTrackedFrame &trackedFrame, bool enableImageData=true)
bool GetTrackingDataAvailable()
int main(int argc, char *argv[])
const double ROTATION_ERROR_THRESHOLD
static vtkPlusConfig * GetInstance()
PlusStatus GetOutputChannelByName(vtkPlusChannel *&aChannel, const char *aChannelId)
const double TRANSLATION_ERROR_THRESHOLD
int CompareCalibrationResultsWithBaseline(const char *baselineFileName, const char *currentResultFileName, const char *stylusCoordinateFrame, const char *stylusTipCoordinateFrame)
virtual char * GetChannelId()
static vtkIGSIOLogger * Instance()
Contains an optional timestamped circular buffer containing the video images and a number of timestam...
void SetDeviceSetConfigurationData(vtkXMLDataElement *deviceSetConfigurationData)
static PlusStatus ReadDeviceSetConfigurationFromFile(vtkXMLDataElement *config, const char *filename)