1 #include "PlusConfigure.h" 3 #include "vtksys/CommandLineArguments.hxx" 20 #define NUM_BACKGROUND_FRAMES 100 21 #define DEFAULT_NUM_DATA_FRAMES 100 22 #define ATRACSYS_MAX_FIDUCIALS 6 26 #define ATR_SUCCESS ATR_RESULT::SUCCESS 36 std::string description;
55 return (std::abs(a) > prec) ? a : 0.0;
67 vec3(
const vec3&
x1) =
default;
68 vec3(
const Fiducial& f) :
x{ f.
xMm },
y{ f.yMm }, z{ f.zMm } {};
69 vec3(
double _x,
double _y,
double _z) :
x{ _x },
y{ _y }, z{ _z } {};
71 vec3& operator=(
const vec3& other) =
default;
72 vec3& operator=(vec3&& other) =
default;
73 vec3 operator-()
const 75 return { -this->
x, -this->
y, -this->z };
78 vec3& operator+=(
const vec3& other)
86 vec3& operator-=(
const vec3& other)
94 vec3& operator/=(
const double&
value)
102 vec3& operator*=(
const double&
value)
110 vec3 operator+ (
const vec3&
x2)
const 112 vec3 result{ *
this };
117 vec3 operator- (
const vec3&
x1)
const 119 vec3 result{ *
this };
124 vec3 operator* (
const double value)
const 129 friend vec3 operator* (
const double value,
const vec3&
x1)
134 vec3 operator/ (
const double value)
const 136 vec3 result{ *
this };
141 double operator* (
const vec3&
x1)
const 143 return x1.x * this->
x + x1.y * this->
y + x1.z * this->z;
148 return std::sqrt(this->normSqr());
151 double normSqr()
const 153 return *
this * *
this;
160 *
this /= this->norm();
164 vec3 cross(
const vec3&
x2)
const 166 return { this->
y * x2.z - this->z *
x2.y, this->z *
x2.x - this->
x * x2.z, this->
x * x2.y - this->
y * x2.x };
171 int main(
int argc,
char** argv)
174 bool printHelp(
false);
175 std::string markerName;
176 std::string description;
177 std::string destinationPath;
179 int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
184 vtksys::CommandLineArguments args;
185 args.Initialize(argc, argv);
187 args.AddArgument(
"--help", vtksys::CommandLineArguments::NO_ARGUMENT, &printHelp,
"Print this help.");
188 args.AddArgument(
"--marker-name", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &markerName,
"Name of marker.");
189 args.AddArgument(
"--description", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &description,
"Decsription of marker (i.e. purpose, color, size, and any other desired metadata).");
190 args.AddArgument(
"--geometryId", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &geometryId,
"Id of the geometry we are creating. Must be unique.");
191 args.AddArgument(
"--destination-path", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &destinationPath,
"Where the generated marker geometry ini file will be written to.");
192 args.AddArgument(
"--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel,
"Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace).");
193 args.AddArgument(
"--num-frames", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &numFrames,
"Number of frames to use in generating marker geometry ini file.");
194 args.AddArgument(
"--int-time", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &intTime,
"Integration time for the camera.");
195 args.AddArgument(
"--img-thresh", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &imgThresh,
"Image compression threshold.");
197 std::this_thread::sleep_for(std::chrono::milliseconds(4000));
201 std::cerr <<
"Problem parsing arguments." << std::endl;
202 std::cout <<
"Help: " << args.GetHelp() << std::endl;
208 std::cout << args.GetHelp() << std::endl;
214 if (markerName.empty())
216 LOG_ERROR(
"--marker-name argument is required!");
217 std::cout <<
"Help: " << args.GetHelp() << std::endl;
221 if (description.empty())
223 LOG_ERROR(
"--description argument is required!");
224 std::cout <<
"Help: " << args.GetHelp() << std::endl;
228 if (geometryId == -1)
230 LOG_ERROR(
"--geometryId argument is required!");
231 std::cout <<
"Help: " << args.GetHelp() << std::endl;
239 if (result !=
ATR_SUCCESS && result != ATR_RESULT::WARNING_CONNECTED_IN_USB2)
245 else if (result == ATR_RESULT::WARNING_CONNECTED_IN_USB2)
253 if (
DeviceType == Tracker::DEVICE_TYPE::SPRYTRACK_180)
276 LOG_INFO(
"\nBackground acquisition. Do NOT place the marker in front of the camera.");
277 LOG_INFO(
"Press <ENTER> to continue.");
286 LOG_ERROR(
"Failed to collect background noise fiducial frames.");
291 LOG_INFO(
"Background collection successful (" << backgroundFids.size() <<
" stray reflections).\n");
295 LOG_INFO(
"Place marker facing the camera in the first half of the working volume\nand rotate slowly the marker until geometry file is generated (left LED off).");
296 LOG_INFO(
"Press <ENTER> to continue.");
300 LOG_INFO(
"Trying to get a good initial guess of the geometry...");
305 LOG_ERROR(
"Failed to collect initial foreground fiducials.");
310 LOG_INFO(
"Initial guess for marker geometry obtained.");
313 geom.name = markerName;
314 geom.description = description;
315 geom.destPath = destinationPath;
316 geom.geometryId = geometryId;
317 geom.fids = foregroundFids;
320 LOG_INFO(
"Collecting marker frames to refine geometry...");
325 LOG_ERROR(
"Failed to collect marker frames with initial geometry guess.");
330 LOG_INFO(
"Refining geometry...");
334 LOG_ERROR(
"Failed to refine geometry.");
350 int pos = barWidth *
i /
N;
351 for (
int i = 0;
i < barWidth; ++
i) {
352 if (
i < pos) std::cout <<
"=";
353 else if (
i == pos) std::cout <<
">";
354 else std::cout <<
" ";
356 std::cout <<
"] " <<
int(100 *
i /
N) <<
" %\r";
366 std::map<std::string, std::string> events;
368 while (m < numFrames)
374 fidFrameList.push_back(fid3dFrame);
376 else if (result == ATR_RESULT::ERROR_NO_FRAME_AVAILABLE)
396 for (FiducialsSequence::size_type frameNum = 0; frameNum < fidFrameList.size(); frameNum++)
398 frame = fidFrameList[frameNum];
400 std::copy(frame.begin(), frame.end(), std::inserter(fids, fids.end()));
404 std::sort(fids.begin(), fids.end());
405 Fiducials::iterator it = std::unique(fids.begin(), fids.end());
414 std::map<std::string, std::string> events;
424 std::remove_if(fid3dFrame.begin(), fid3dFrame.end(),
426 return std::find(backFids.begin(), backFids.end(), item) != backFids.end();
437 for (
const auto& f : fid3dFrame)
439 deter += std::floor(f.probability);
441 if (deter == fid3dFrame.size())
447 else if (result == ATR_RESULT::ERROR_NO_FRAME_AVAILABLE)
465 vec3 c(0.0, 0.0, 0.0);
467 for (
const auto& fid : fids)
471 c /= static_cast<double>(fids.size());
474 std::multimap<double, int, std::greater<double>> dists;
475 for (
int i = 0;
i < fids.size(); ++
i)
477 dists.insert({ (c - vec3(fids[
i])).norm(),
i });
482 for (
auto prev = dists.begin(), curr = ++dists.begin(); curr != dists.end(); ++prev, ++curr)
484 if (std::abs(prev->first - curr->first) > 0.1)
486 auto fidId = (prev == dists.begin()) ? prev->second : curr->second;
487 x = vec3(fids[fidId]);
492 std::multimap<double, int, std::greater<double>> dists2;
493 for (
int i = 0;
i < fids.size(); ++
i)
495 double num = ((
x - vec3(fids[
i])).cross(
x - c)).norm();
496 dists2.insert({ num / (
x - c).norm(),
i });
500 for (
auto prev = dists2.begin(), curr = ++dists2.begin(); curr != dists2.end(); ++prev, ++curr)
502 if (std::abs(prev->first - curr->first) > 0.1)
504 auto fidId = (prev == dists2.begin()) ? prev->second : curr->second;
505 p = vec3(fids[fidId]);
510 vec3 vx = (
x - c).normalize();
511 vec3 vz = (vx.cross(
p - c)).normalize();
512 vec3 vy = vz.cross(vx);
515 for (
auto& fid : fids)
518 fid.
xMm = (vec3(f) - c) * vx;
519 fid.yMm = (vec3(f) - c) * vy;
520 fid.zMm = (vec3(f) - c) * vz;
527 std::ostringstream os;
530 os <<
"; " << geom.name << std::endl;
531 os <<
"; " << geom.description << std::endl;
533 auto tm = *std::localtime(&
t);
534 os <<
"; " << std::put_time(&tm,
"%Y-%m-%d %H:%M:%S") << std::endl;
537 os <<
"[geometry]" << std::endl;
538 os <<
"count=" << geom.fids.size() << std::endl;
539 os <<
"id=" << geom.geometryId << std::endl;
541 for (Fiducials::size_type
i = 0;
i < geom.fids.size();
i++)
543 os <<
"[fiducial" <<
i <<
"]" << std::endl;
544 os <<
"x=" << geom.fids[
i].xMm << std::endl;
545 os <<
"y=" << geom.fids[
i].yMm << std::endl;
546 os <<
"z=" << geom.fids[
i].zMm << std::endl;
560 LOG_ERROR(
"Unable to load initial marker.");
566 std::vector<Marker> markersFrame;
567 std::map<std::string, std::string> events;
569 while (m < numFrames)
574 if (markersFrame.size() == 1)
577 markerFrameList.push_back(markersFrame.front());
580 else if (result == ATR_RESULT::ERROR_NO_FRAME_AVAILABLE)
597 for (
int m = 0; m < markerFrameList.size(); ++m)
599 Fiducials fids = markerFrameList[m].GetFiducials();
602 for (
int i = 0;
i < fids.size(); ++
i)
604 accFids[
i].xMm += fids[
i].xMm;
605 accFids[
i].yMm += fids[
i].yMm;
606 accFids[
i].zMm += fids[
i].zMm;
611 for (
int i = 0;
i < accFids.size(); ++
i)
613 accFids[
i].xMm =
remDecimals(accFids[
i].xMm / markerFrameList.size(), 1e-4);
614 accFids[
i].yMm =
remDecimals(accFids[
i].yMm / markerFrameList.size(), 1e-4);
615 accFids[
i].zMm =
remDecimals(accFids[
i].zMm / markerFrameList.size(), 1e-4);
627 std::string fileName;
628 if (geom.destPath.empty())
630 fileName =
"./" + geom.name +
".ini";
634 fileName = geom.destPath +
'/' + geom.name +
".ini";
636 LOG_INFO(
"Writing marker geometry to: " << fileName);
std::vector< Fiducials > FiducialsSequence
Atracsys::Tracker::RESULT ATR_RESULT
PlusStatus RefineMarkerGeometry(CustomGeometry &geom, MarkerSequence &markerFrameList)
RESULT SetUserLEDState(int red, int green, int blue, int frequency, bool enabled=true)
std::vector< Fiducial > Fiducials
RESULT EnableUserLED(bool enabled)
#define ATRACSYS_MAX_FIDUCIALS
std::string to_string(ClariusAvailability avail)
#define NUM_BACKGROUND_FRAMES
PlusStatus WriteGeometryToIniFile(const CustomGeometry &geom)
RESULT SetSpryTrackProcessingType(SPRYTRACK_IMAGE_PROCESSING_TYPE processingType)
Tracker::DEVICE_TYPE DeviceType
RESULT LoadMarkerGeometryFromString(std::string filePath, int &geometryId)
#define DEFAULT_NUM_DATA_FRAMES
PlusStatus CollectFiducialSequence(FiducialsSequence &fidFrameList, int numFrames)
RESULT GetDeviceType(DEVICE_TYPE &deviceType)
const char const char * value
static vtkIGSIOLogger * Instance()
int main(int argc, char **argv)
RESULT SetOption(const std::string &, const std::string &)
std::vector< Marker > MarkerSequence
double remDecimals(double a, double prec)
Direction vectors of rods y
std::string WriteGeometryToString(const CustomGeometry &geom)
RESULT GetFiducialsInFrame(std::vector< Fiducial > &fiducials, std::map< std::string, std::string > &events, uint64_t &sdkTimestamp)
void TransformMarkerCoordinateSystem(Fiducials &fids)
RESULT GetMarkersInFrame(std::vector< Marker > &markers, std::map< std::string, std::string > &events, uint64_t &sdkTimestamp)
PlusStatus CaptureInitialGeometry(Fiducials &backgroundFids, Fiducials &fids)
PlusStatus ProcessBackgroundFiducials(FiducialsSequence &fidFrameList, Fiducials &backgroundFids)
void ProgressBar(int i, int N, int barWidth=70)
PlusStatus CollectMarkerSequence(CustomGeometry &geom, MarkerSequence &markerFrameList, int numFrames)
std::string ResultToString(RESULT result)