PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
AtracsysTracker.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 
7 // Local includes
8 #include "AtracsysTracker.h"
9 
10 // System includes
11 #include <algorithm>
12 #include <cmath>
13 #include <fstream>
14 #include <map>
15 #include <string>
16 
17 // Atracsys includes
18 #include "ftkErrors.h"
19 #include "ftkEvent.h"
20 #include "ftkOptions.h"
21 #include "ftkInterface.h"
22 #include "ftkPlatform.h"
23 #include "ftkTypes.h"
24 
25 #include <igsioCommon.h>
26 
27 #define ATRACSYS_BUFFER_SIZE 1024
28 #define RESET_DROPPED_FRAME_COUNT 1
29 
30 //----------------------------------------------------------------------------
31 bool strToInt32(const std::string& str, int& var)
32 {
33  bool noexception = false;
34  try
35  {
36  var = std::atoi(str.c_str());
37  noexception = true;
38  }
39  catch (std::invalid_argument& e)
40  {
41  LOG_WARNING(std::string("Cannot convert ") + str + std::string(" to int32"));
42  }
43  catch (std::out_of_range& e)
44  {
45  LOG_WARNING(str + std::string(" is out of range for int32"));
46  }
47  return noexception;
48 }
49 
50 //----------------------------------------------------------------------------
51 bool strToFloat32(const std::string& str, float& var)
52 {
53  bool noexception = false;
54  try
55  {
56  var = std::atof(str.c_str());
57  noexception = true;
58  }
59  catch (std::invalid_argument& e)
60  {
61  LOG_WARNING(std::string("Cannot convert ") + str + std::string(" to float"));
62  }
63  catch (std::out_of_range& e)
64  {
65  LOG_WARNING(str + std::string(" is out of range for float"));
66  }
67  return noexception;
68 }
69 
70 //----------------------------------------------------------------------------
71 class AtracsysTracker::AtracsysInternal
72 {
73 public:
74  AtracsysInternal()
75  {
76  // populate result to string
77  ResultToStringMap[ERROR_UNABLE_TO_GET_FTK_HANDLE] = "Unable to get Atracsys library handle.";
78  ResultToStringMap[ERROR_NO_DEVICE_CONNECTED] = "No Atracsys device connected.";
79  ResultToStringMap[ERROR_UNABLE_TO_LOAD_MARKER] = "Unable to load marker.";
80  ResultToStringMap[ERROR_FAILURE_TO_LOAD_INI] = "Failed to load marker's ini file.";
81  ResultToStringMap[ERROR_OPTION_AVAILABLE_ONLY_ON_FTK] = "Attempted to call fusionTrack only option with non-fusionTrack device connected.";
82  ResultToStringMap[ERROR_OPTION_AVAILABLE_ONLY_ON_STK] = "Attempted to call spryTrack only option with non-spryTrack device connected.";
83  ResultToStringMap[ERROR_FAILED_TO_CLOSE_SDK] = "Failed to close the Atracsys SDK.";
84  ResultToStringMap[ERROR_FAILED_TO_EXPORT_CALIB] = "Failed to export cameras calibration.";
85  ResultToStringMap[ERROR_FAILED_TO_EXTRACT_FRAME_INFO] = "Failed to extract frame info.";
86  ResultToStringMap[ERROR_CANNOT_CREATE_FRAME_INSTANCE] = "Failed to create frame.";
87  ResultToStringMap[ERROR_CANNOT_INITIALIZE_FRAME] = "Failed to initialize frame.";
88  ResultToStringMap[ERROR_NO_FRAME_AVAILABLE] = "No frame available from tracker.";
89  ResultToStringMap[ERROR_INVALID_FRAME] = "Invalid frame received from tracker.";
90  ResultToStringMap[ERROR_TOO_MANY_MARKERS] = "Too many markers in frame.";
91  ResultToStringMap[ERROR_ENABLE_LASER] = "Failed to enable laser, this is a spryTrack only option.";
92  ResultToStringMap[ERROR_SET_USER_LED] = "Failed to set the user LED.";
93  ResultToStringMap[ERROR_ENABLE_USER_LED] = "Failed to enable / disable the user LED.";
94  ResultToStringMap[ERROR_ENABLE_IMAGE_STREAMING] = "Failed to enable / disable image streaming.";
95  ResultToStringMap[ERROR_ENABLE_WIRELESS_MARKER_PAIRING] = "Failed to enable / disable wireless marker pairing.";
96  ResultToStringMap[ERROR_ENABLE_WIRELESS_MARKER_STATUS_STREAMING] = "Failed to enable / disable wireless marker status streaming.";
97  ResultToStringMap[ERROR_ENABLE_WIRELESS_MARKER_BATTERY_STREAMING] = "Failed to enable / disable wireless marker battery streaming.";
98  ResultToStringMap[ERROR_DISCONNECT_ATTEMPT_WHEN_NOT_CONNECTED] = "Disconnect called when not connected to tracker.";
99  ResultToStringMap[ERROR_CANNOT_GET_MARKER_INFO] = "Cannot get info about paired wireless markers.";
100  ResultToStringMap[ERROR_FAILED_TO_SET_STK_PROCESSING_TYPE] = "Failed to set spryTrack image processing type.";
101  }
102 
103  virtual ~AtracsysInternal()
104  {
105  FtkLib = nullptr;
106  LibVersion = "";
107  CalibrationDate = "";
108  TrackerSN = 0;
109  }
110 
111  // is virtual device or not
112  bool isVirtual = false;
113 
114  // is paused or not
115  bool isPaused = true;
116 
117  // handle to FtkLib library
118  ftkLibrary FtkLib = nullptr;
119 
120  // library version
121  std::string LibVersion;
122 
123  // calibration date
124  std::string CalibrationDate;
125 
126  // serial number of tracker
127  uint64 TrackerSN = 0;
128 
129  // ftk frame data
130  ftkFrameQuery* Frame = nullptr;
131 
132  // mapping error code to user readable result string
133  std::map<AtracsysTracker::ATRACSYS_RESULT, std::string> ResultToStringMap;
134 
135  // helper function to load ftkGeometry from file
136  ATRACSYS_RESULT LoadFtkGeometryFromFile(const std::string& filename, ftkGeometry& geom);
137 
138  // helper function to load ftkGeometry from string
139  ATRACSYS_RESULT LoadFtkGeometryFromString(const std::string& geomString, ftkGeometry& geom);
140 
141  std::map<int, std::vector<std::array<float, 3>>> Geometries;
142 
143  // correspondence between atracsys option name and its actual id in the sdk
144  // this map is filled automatically by the sdk, DO NOT hardcode/change any id
145  std::map<std::string, ftkOptionsInfo> DeviceOptionMap{};
146 
147  //----------------------------------------------------------------------------
148  // callback function stores all option id
149  static void DeviceOptionEnumerator(uint64_t serialNumber, void* userData, ftkOptionsInfo* option)
150  {
151  AtracsysTracker::AtracsysInternal* ptr =
152  reinterpret_cast<AtracsysTracker::AtracsysInternal*>(userData);
153  if (!ptr)
154  {
155  return;
156  }
157  ptr->DeviceOptionMap.emplace(option->name, *option);
158  }
159 
160  // Code from ATRACSYS
161  class IniFile
162  {
163  protected:
164  //----------------------------------------------------------------------------
165  long findEOL(char& c, char* addr, size_t size)
166  {
167  for (long u = 0; u < (long)size; u++)
168  {
169  c = addr[u];
170  if (c == 0 || c == '\n') // note that MAX may only have a '\r'
171  {
172  return u;
173  }
174  }
175  return -1;
176  }
177 
178  //----------------------------------------------------------------------------
179  bool parseLine(std::string& line)
180  {
181  size_t first_bracket = line.find_first_of("["),
182  last_bracket = line.find_last_of("]"),
183  equal = line.find_first_of("=");
184 
185  if (first_bracket != std::string::npos &&
186  last_bracket != std::string::npos)
187  {
188  // Found section
189  _currentSection = line.substr(first_bracket + 1,
190  last_bracket - first_bracket - 1);
191  sections[_currentSection] = KeyValues();
192  }
193  else if (equal != std::string::npos && _currentSection != "")
194  {
195  // Found property in a section
196  std::string key = line.substr(0, equal),
197  val = line.substr(equal + 1);
198  sections[_currentSection][key] = val;
199  }
200  else
201  {
202  // If the line is empty, just skip it, if not and is a comment, just
203  // skip it
204  // as well, otherwise the parsing cannot be done.
205  line.erase(remove_if(line.begin(),
206  line.end(), isspace), line.end());
207  if (!line.empty() && line.substr(0, 1) != ";")
208  {
209  return false;
210  }
211  }
212  return true;
213  }
214  std::string _currentSection;
215 
216  public:
217  typedef std::map< std::string, std::string > KeyValues;
218  typedef std::map< std::string, KeyValues > Sections;
219 
220  Sections sections;
221 
222  //----------------------------------------------------------------------------
223  bool parse(char* addr, size_t size)
224  {
225  sections.clear();
226  _currentSection = "";
227 
228  std::string strLine;
229 
230  while (size)
231  {
232  char c;
233  long lineSize = findEOL(c, addr, size);
234 
235  if (lineSize != 0)
236  {
237  if (lineSize > 0)
238  {
239  strLine = std::string(addr, lineSize);
240  }
241  else
242  {
243  strLine = std::string(addr);
244  }
245 
246  strLine.erase(remove(strLine.begin(), strLine.end(), '\r'), strLine.end());
247  if (!parseLine(strLine))
248  {
249  return false;
250  }
251 
252  if (lineSize < 0)
253  {
254  return true; // EOF at the end of the line
255  }
256  }
257  if (c == 0 || size == size_t(lineSize))
258  {
259  return true; // !!! eof not reached
260  }
261  addr += lineSize + 1;
262  size -= lineSize + 1;
263  }
264  return true;
265  }
266 
267  //----------------------------------------------------------------------------
268  // Return false in case of syntax error
269  bool save(std::string str)
270  {
271  FILE* file = fopen(str.c_str(), "wb");
272  if (!file)
273  {
274  return false;
275  }
276 
277  Sections::iterator iterS = sections.begin();
278 
279  while (iterS != sections.end())
280  {
281  fprintf(file, "[%s]\n", iterS->first.c_str());
282 
283  KeyValues& kw = iterS->second;
284  KeyValues::iterator iterK = kw.begin();
285 
286  while (iterK != kw.end())
287  {
288  fprintf(file, "%s=%s\n",
289  iterK->first.c_str(), iterK->second.c_str());
290  iterK++;
291  }
292  iterS++;
293  }
294  fclose(file);
295  return true;
296  }
297 
298  //----------------------------------------------------------------------------
299  bool toBuffer(char** out, size_t& outSize)
300  {
301  if (!out)
302  {
303  return false;
304  }
305 
306  std::string buffer;
307  char temp[ATRACSYS_BUFFER_SIZE];
308 
309  Sections::iterator iterS = sections.begin();
310 
311  while (iterS != sections.end())
312  {
313  sprintf(temp, "[%s]\n", iterS->first.c_str());
314  buffer += temp;
315 
316  KeyValues& kw = iterS->second;
317  KeyValues::iterator iterK = kw.begin();
318 
319  while (iterK != kw.end())
320  {
321  sprintf(temp, "%s=%s\n",
322  iterK->first.c_str(), iterK->second.c_str());
323  buffer += temp;
324  iterK++;
325  }
326  iterS++;
327  }
328 
329  outSize = buffer.length() + 1;
330  char* str = new (std::nothrow) char[outSize];
331 
332  if (!str)
333  {
334  return false;
335  }
336 
337  strncpy(str, buffer.c_str(), outSize - 1);
338  str[outSize - 1] = 0;
339  *out = str;
340 
341  return true;
342  } // Buffer must be unallocated by user
343  };
344 
345  //----------------------------------------------------------------------------
346  bool checkSection(IniFile& p, const std::string& section)
347  {
348  if (p.sections.find(section) == p.sections.end())
349  {
350  return false;
351  }
352  return true;
353  }
354 
355  //----------------------------------------------------------------------------
356  bool checkKey(IniFile& p, const std::string& section, const std::string& key)
357  {
358  if (p.sections[section].find(key) == p.sections[section].end())
359  {
360  return false;
361  }
362 
363  return true;
364  }
365 
366  //----------------------------------------------------------------------------
367  bool assignUint32(IniFile& p, const std::string& section,
368  const std::string& key,
369  uint32* variable)
370  {
371  if (!checkKey(p, section, key))
372  {
373  return false;
374  }
375 
376  char* pEnd;
377  std::string val(p.sections[section][key]);
378 
379  *variable = uint32(strtol(val.c_str(), &pEnd, 10));
380 
381  return true;
382  }
383 
384  //----------------------------------------------------------------------------
385  bool assignFloatXX(IniFile& p, const std::string& section,
386  const std::string& key,
387  floatXX* variable)
388  {
389  if (!checkKey(p, section, key))
390  {
391  return false;
392  }
393 
394  char* pEnd;
395 
396  *variable =
397  floatXX(strtod(p.sections[section][key].c_str(), &pEnd));
398 
399  return true;
400  }
401 
402  //----------------------------------------------------------------------------
403  bool LoadIniFile(std::ifstream& is, ftkGeometry& geometry)
404  {
405  std::string line, fileContent("");
406 
407  while (!is.eof())
408  {
409  getline(is, line);
410  fileContent += line + "\n";
411  }
412 
413  return ParseIniFile(fileContent, geometry);
414  }
415 
416  //----------------------------------------------------------------------------
417  // this method from https://thispointer.com/find-and-replace-all-occurrences-of-a-sub-string-in-c/
418  void stringFindAndReplaceAll(std::string& data, std::string toSearch, std::string replaceStr)
419  {
420  // Get the first occurrence
421  size_t pos = data.find(toSearch);
422 
423  // Repeat till end is reached
424  while (pos != std::string::npos)
425  {
426  // Replace this occurrence of Sub String
427  data.replace(pos, toSearch.size(), replaceStr);
428  // Get the next occurrence from the current position
429  pos = data.find(toSearch, pos + replaceStr.size());
430  }
431  }
432 
433  //----------------------------------------------------------------------------
434  bool ParseIniFile(std::string fileContent, ftkGeometry& geometry)
435  {
436  stringFindAndReplaceAll(fileContent, "\\n", "\n");
437 
438  IniFile parser;
439 
440  if (!parser.parse(const_cast<char*>(fileContent.c_str()),
441  fileContent.size()))
442  {
443  return false;
444  }
445 
446  if (!checkSection(parser, "geometry"))
447  {
448  return false;
449  }
450 
451  uint32 tmp;
452 
453  if (!assignUint32(parser, "geometry", "count", &tmp))
454  {
455  return false;
456  }
457  geometry.version = 0u;
458  geometry.pointsCount = tmp;
459  if (!assignUint32(parser, "geometry", "id", &geometry.geometryId))
460  {
461  return false;
462  }
463 
464  char sectionName[10u];
465 
466  for (uint32 i(0u); i < geometry.pointsCount; ++i)
467  {
468  sprintf(sectionName, "fiducial%u", i);
469 
470  if (!checkSection(parser, sectionName))
471  {
472  return false;
473  }
474 
475  if (!assignFloatXX(parser, sectionName, "x",
476  &geometry.positions[i].x))
477  {
478  return false;
479  }
480  if (!assignFloatXX(parser, sectionName, "y",
481  &geometry.positions[i].y))
482  {
483  return false;
484  }
485  if (!assignFloatXX(parser, sectionName, "z",
486  &geometry.positions[i].z))
487  {
488  return false;
489  }
490  }
491 
492  std::vector<std::array<float, 3>> pts;
493  for (uint32 i(0u); i < geometry.pointsCount; ++i)
494  {
495  std::array<float, 3> pt = { geometry.positions[i].x, geometry.positions[i].y, geometry.positions[i].z };
496  pts.push_back(pt);
497  }
498  this->Geometries[geometry.geometryId] = pts;
499 
500  return true;
501  }
502 };
503 
504 //----------------------------------------------------------------------------
505 struct DeviceData
506 {
507  uint64 SerialNumber;
508  ftkDeviceType Type;
509 };
510 
511 //----------------------------------------------------------------------------
512 void FusionTrackEnumerator(uint64 sn, void* user, ftkDeviceType devType)
513 {
514  if (user != 0)
515  {
516  DeviceData* ptr = reinterpret_cast<DeviceData*>(user);
517  ptr->SerialNumber = sn;
518  ptr->Type = devType;
519  }
520 }
521 
522 //----------------------------------------------------------------------------
523 AtracsysTracker::ATRACSYS_RESULT AtracsysTracker::AtracsysInternal::LoadFtkGeometryFromFile(const std::string& filename, ftkGeometry& geom)
524 {
525  std::ifstream input;
526  input.open(filename.c_str());
527 
528  if (!input.fail() && this->LoadIniFile(input, geom))
529  {
530  return ERROR_FAILURE_TO_LOAD_INI;
531  }
532  else
533  {
534  ftkBuffer buffer;
535  buffer.reset();
536  if (ftkGetData(this->FtkLib, this->TrackerSN, this->DeviceOptionMap["Data Directory"].id, &buffer) != ftkError::FTK_OK || buffer.size < 1u)
537  {
538  return ERROR_FAILURE_TO_LOAD_INI;
539  }
540 
541  std::string fullFile(reinterpret_cast<char*>(buffer.data));
542  fullFile += "\\" + filename;
543 
544  input.open(fullFile.c_str());
545 
546  if (!input.fail() && this->LoadIniFile(input, geom))
547  {
548  return SUCCESS;
549  }
550  }
551 
552  return ERROR_FAILURE_TO_LOAD_INI;
553 }
554 // END CODE FROM ATRACSYS
555 
556 //----------------------------------------------------------------------------
557 AtracsysTracker::ATRACSYS_RESULT AtracsysTracker::AtracsysInternal::LoadFtkGeometryFromString(const std::string& geomString, ftkGeometry& geom)
558 {
559  if (this->ParseIniFile(geomString, geom))
560  {
561  return SUCCESS;
562  }
563  return ERROR_FAILURE_TO_LOAD_INI;
564 }
565 
566 //----------------------------------------------------------------------------
567 // provided an option name with Atracsys' nomenclature, this method returns the pointer
568 // to the corresponding ftkOptionsInfo which contains various information about the option
569 // (notably its id and value type)
570 bool AtracsysTracker::GetOptionInfo(const std::string& optionName, const ftkOptionsInfo*& info)
571 {
572  std::map<std::string, ftkOptionsInfo>::const_iterator it = this->Internal->DeviceOptionMap.find(optionName);
573  if (it == this->Internal->DeviceOptionMap.cend())
574  {
575  return false;
576  }
577  else
578  {
579  info = &(it->second);
580  return true;
581  }
582 }
583 
584 //----------------------------------------------------------------------------
585 // this method sets a value to an option in the device. The option name follows Atracsys' nomenclature.
586 AtracsysTracker::ATRACSYS_RESULT AtracsysTracker::SetOption(const std::string& optionName, const std::string& attributeValue)
587 {
588  if (this->Internal->isVirtual)
589  {
590  return SUCCESS;
591  }
592 
593  std::string optionStr{ optionName };
594  // if Embedded processing is on and the option has an Embedded variant, add the prefix
595  if (isOnboardProcessing && this->Internal->DeviceOptionMap.find("Embedded " + optionName) != this->Internal->DeviceOptionMap.end())
596  {
597  optionStr = "Embedded " + optionStr;
598  }
599 
600  const ftkOptionsInfo* info;
601 
602  if (!this->GetOptionInfo(optionStr, info))
603  {
604  LOG_WARNING(std::string("Info for option \"") + optionStr + std::string("\" not found."));
605  return ERROR_OPTION_NOT_FOUND;
606  }
607 
608  if (info->type == ftkOptionType::FTK_INT32)
609  {
610  int32_t val;
611  if (!strToInt32(attributeValue, val))
612  {
613  return ERROR_SET_OPTION;
614  }
615 
616  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, val) != ftkError::FTK_OK)
617  {
618  ftkBuffer buffer{};
619  if (ftkGetLastErrorString(this->Internal->FtkLib, sizeof(buffer.data), buffer.data) == ftkError::FTK_OK)
620  {
621  LOG_WARNING(std::string(buffer.data));
622  }
623  else
624  {
625  LOG_WARNING(std::string("Unknown error setting option ") + optionStr);
626  }
627  }
628  }
629  else if (info->type == ftkOptionType::FTK_FLOAT32)
630  {
631  float_t val;
632  if (!strToFloat32(attributeValue, val))
633  {
634  return ERROR_SET_OPTION;
635  }
636 
637  if (ftkSetFloat32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, val) != ftkError::FTK_OK)
638  {
639  ftkBuffer buffer{};
640  if (ftkGetLastErrorString(this->Internal->FtkLib, sizeof(buffer.data), buffer.data) == ftkError::FTK_OK)
641  {
642  LOG_WARNING(std::string(buffer.data));
643  }
644  else
645  {
646  LOG_WARNING(std::string("Unknown error setting option ") + optionStr);
647  }
648  }
649  }
650  else if (info->type == ftkOptionType::FTK_DATA)
651  {
652  LOG_WARNING(std::string("Option of type \"data\" not supported yet"));
653  }
654  LOG_INFO(std::string("Option \"") + optionStr + std::string("\" successfully set at value ") + attributeValue);
655 
656  return SUCCESS;
657 }
658 
659 // ------------------------------------------
660 // universally available options & methods
661 // ------------------------------------------
662 
664  : Internal(new AtracsysInternal()) {}
665 
667 {
668  delete Internal;
669  Internal = nullptr;
670 }
671 
672 //----------------------------------------------------------------------------
674 {
675  this->Internal->isPaused = tof;
676 }
677 
678 //----------------------------------------------------------------------------
680 {
681  return isOnboardProcessing;
682 }
683 
684 //----------------------------------------------------------------------------
686 {
687  return this->Internal->isVirtual;
688 }
689 
690 //----------------------------------------------------------------------------
692 {
693  if (this->Internal->FtkLib != nullptr && this->Internal->TrackerSN != 0)
694  {
695  // already connected
696  return SUCCESS;
697  }
698 
699  // initialize SDK
700  this->Internal->FtkLib = ftkInit();
701 
702  if (this->Internal->FtkLib == NULL)
703  {
705  }
706 
707  DeviceData device;
708  device.SerialNumber = 0uLL;
709 
710  // scan for devices
711  ftkError err = ftkEnumerateDevices(this->Internal->FtkLib, FusionTrackEnumerator, &device);
712  if (err != ftkError::FTK_OK && err != ftkError::FTK_WAR_USB_TOO_SLOW)
713  {
714  ftkClose(&this->Internal->FtkLib);
715  this->Internal->FtkLib = nullptr;
717  }
718 
719  if (device.SerialNumber == 0uLL)
720  {
721  ftkClose(&this->Internal->FtkLib);
722  this->Internal->FtkLib = nullptr;
724  }
725 
726  this->Internal->TrackerSN = device.SerialNumber;
727 
728  ftkBuffer sdkVersion;
729  ftkVersion(&sdkVersion);
730  this->Internal->LibVersion = sdkVersion.data;
731 
732  switch (device.Type)
733  {
734  case ftkDeviceType::DEV_SPRYTRACK_180:
735  this->DeviceType = SPRYTRACK_180;
736  break;
737  case ftkDeviceType::DEV_SPRYTRACK_300:
738  this->DeviceType = SPRYTRACK_300;
739  break;
740  case ftkDeviceType::DEV_FUSIONTRACK_500:
741  this->DeviceType = FUSIONTRACK_500;
742  break;
743  case ftkDeviceType::DEV_FUSIONTRACK_250:
744  this->DeviceType = FUSIONTRACK_250;
745  break;
746  default:
747  this->DeviceType = UNKNOWN_DEVICE;
748  }
749 
750  // allocate memory for ftk frame to be used throughout life of the object
751  this->Internal->Frame = ftkCreateFrame();
752 
753  if (this->Internal->Frame == nullptr)
754  {
755  ftkDeleteFrame(this->Internal->Frame);
756  this->Internal->Frame = nullptr;
758  }
759 
760  if (ftkSetFrameOptions(false, this->MaxAdditionalEventsNumber,
761  this->Max2dFiducialsNumber, this->Max2dFiducialsNumber,
762  this->Max3dFiducialsNumber, this->MaxMarkersNumber,
763  this->Internal->Frame) != ftkError::FTK_OK)
764  {
765  ftkDeleteFrame(this->Internal->Frame);
766  this->Internal->Frame = nullptr;
768  }
769 
770  if (ftkEnumerateOptions(this->Internal->FtkLib, this->Internal->TrackerSN,
771  &AtracsysTracker::AtracsysInternal::DeviceOptionEnumerator, this->Internal) != ftkError::FTK_OK
772  || this->Internal->DeviceOptionMap.find("Data Directory") == this->Internal->DeviceOptionMap.cend())
773  {
774  return ERROR_OPTION_NOT_FOUND;
775  }
776 
777  // Needs to be after the device option enumeration
778  const ftkOptionsInfo* info;
779  if (!this->GetOptionInfo("Calibration processing datetime", info))
780  {
781  LOG_ERROR("Option unknown: \"Calibration processing datetime\"");
782  return ERROR_OPTION_NOT_FOUND;
783  }
784  ftkBuffer buff;
785  ftkGetData(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, &buff);
786  this->Internal->CalibrationDate = std::string(buff.data);
787 
788  // Check whether onboard processing is off or on (spryTrack only)
789  if (this->DeviceType == SPRYTRACK_180 || this->DeviceType == SPRYTRACK_300)
790  {
791  if (!this->GetOptionInfo("Enable embedded processing", info))
792  {
793  LOG_WARNING(std::string("Embedded processing not part of the option list."));
794  return ERROR_OPTION_NOT_FOUND;
795  }
796  else
797  {
798  int32 val;
799  ftkGetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, &val, ftkOptionGetter::FTK_VALUE);
800  isOnboardProcessing = (val == 1) ? true : false;
801  LOG_INFO("Embedded processing is initially " << (isOnboardProcessing ? "enabled" : "disabled"));
802  }
803  }
804 
805  return SUCCESS;
806 }
807 
808 //----------------------------------------------------------------------------
810 {
811  if (this->Internal->isVirtual)
812  {
813  return SUCCESS;
814  }
815 
816  if (this->Internal->FtkLib == nullptr && this->Internal->TrackerSN == 0)
817  {
819  }
820 
821  // de-allocate memory for frame
822  ftkDeleteFrame(this->Internal->Frame);
823  this->Internal->Frame = nullptr;
824 
825  ftkError err = ftkClose(&this->Internal->FtkLib);
826  if (err != ftkError::FTK_OK)
827  {
829  }
830  return SUCCESS;
831 }
832 
833 //----------------------------------------------------------------------------
835 {
836  version = this->Internal->LibVersion;
837  return SUCCESS;
838 }
839 
840 //----------------------------------------------------------------------------
842 {
843  date = this->Internal->CalibrationDate;
844  return SUCCESS;
845 }
846 
847 //----------------------------------------------------------------------------
849 {
850  deviceType = this->DeviceType;
851  return SUCCESS;
852 }
853 
854 //----------------------------------------------------------------------------
856  std::array<float, 10>& leftIntrinsic, std::array<float, 10>& rightIntrinsic,
857  std::array<float, 3>& rightPosition, std::array<float, 3>& rightOrientation)
858 {
859  if (!this->Internal->isVirtual || this->SetOption("Calibration export", "1") != SUCCESS)
860  {
861  LOG_ERROR("Could not export calibration.");
863  }
864  else
865  {
866  if (ftkGetLastFrame(this->Internal->FtkLib, this->Internal->TrackerSN, this->Internal->Frame, 20) != ftkError::FTK_OK)
867  {
869  }
870  else
871  {
872  ftkFrameInfoData info;
873  info.WantedInformation = ftkInformationType::CalibrationParameters;
874  if (ftkExtractFrameInfo(this->Internal->Frame, &info) != ftkError::FTK_OK)
875  {
877  }
878  else
879  {
880  ftkStereoParameters sps = info.Calibration;
881  leftIntrinsic = { sps.LeftCamera.FocalLength[0], sps.LeftCamera.FocalLength[1],
882  sps.LeftCamera.OpticalCentre[0], sps.LeftCamera.OpticalCentre[1],
883  sps.LeftCamera.Distorsions[0], sps.LeftCamera.Distorsions[1], sps.LeftCamera.Distorsions[2],
884  sps.LeftCamera.Distorsions[3], sps.LeftCamera.Distorsions[4], sps.LeftCamera.Skew };
885  rightIntrinsic = { sps.RightCamera.FocalLength[0], sps.RightCamera.FocalLength[1],
886  sps.RightCamera.OpticalCentre[0], sps.RightCamera.OpticalCentre[1],
887  sps.RightCamera.Distorsions[0], sps.RightCamera.Distorsions[1], sps.RightCamera.Distorsions[2],
888  sps.RightCamera.Distorsions[3], sps.RightCamera.Distorsions[4], sps.RightCamera.Skew };
889  rightPosition = { sps.Translation[0], sps.Translation[1], sps.Translation[2] };
890  rightOrientation = { sps.Rotation[0], sps.Rotation[1], sps.Rotation[2] };
891  }
892  }
893  }
894  return SUCCESS;
895 }
896 
897 //----------------------------------------------------------------------------
899 {
900  id = this->Internal->TrackerSN;
901  return SUCCESS;
902 }
903 
904 //----------------------------------------------------------------------------
906 {
907  ftkGeometry geom;
908  this->Internal->LoadFtkGeometryFromFile(filePath, geom);
909  if (!this->Internal->isVirtual &&
910  ftkSetGeometry(this->Internal->FtkLib, this->Internal->TrackerSN, &geom) != ftkError::FTK_OK)
911  {
913  }
914  geometryId = geom.geometryId;
915  return SUCCESS;
916 }
917 
918 //----------------------------------------------------------------------------
920 {
921  ftkGeometry geom;
922  this->Internal->LoadFtkGeometryFromString(geomString, geom);
923  if (!this->Internal->isVirtual &&
924  ftkSetGeometry(this->Internal->FtkLib, this->Internal->TrackerSN, &geom) != ftkError::FTK_OK)
925  {
927  }
928  geometryId = geom.geometryId;
929  return SUCCESS;
930 }
931 
932 //----------------------------------------------------------------------------
934 {
935  if (this->Internal->isVirtual)
936  {
938  }
939 
940  // get correct device option number
941  const ftkOptionsInfo* info;
942  if (!this->GetOptionInfo("Active Wireless Markers info", info))
943  {
944  return ERROR_OPTION_NOT_FOUND;
945  }
946 
947  ftkBuffer buffer;
948  if (ftkGetData(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, &buffer) != ftkError::FTK_OK)
949  {
951  }
952  markerInfo = std::string(buffer.data, buffer.data + buffer.size);
953  return SUCCESS;
954 }
955 
956 //----------------------------------------------------------------------------
957 AtracsysTracker::ATRACSYS_RESULT AtracsysTracker::GetLoadedGeometries(std::map<int, std::vector<std::array<float, 3>>>& geometries)
958 {
959  geometries = this->Internal->Geometries;
960  return SUCCESS;
961 }
962 
963 //----------------------------------------------------------------------------
965 {
966  std::map<AtracsysTracker::ATRACSYS_RESULT, std::string>::iterator it;
967  it = this->Internal->ResultToStringMap.find(result);
968  if (it != end(this->Internal->ResultToStringMap))
969  {
970  return it->second;
971  }
972  return std::string("Unknown error has occured. Result value: " + result);
973 }
974 
975 //----------------------------------------------------------------------------
977  std::map<std::string, std::string>& events, uint64_t& sdkTimestamp)
978 {
979  ftkError err = ftkGetLastFrame(this->Internal->FtkLib, this->Internal->TrackerSN, this->Internal->Frame, 20);
980  if (err != ftkError::FTK_OK)
981  {
983  }
984 
985  switch (this->Internal->Frame->markersStat)
986  {
987  case ftkQueryStatus::QS_WAR_SKIPPED:
988  return ERROR_INVALID_FRAME;
989  case ftkQueryStatus::QS_ERR_INVALID_RESERVED_SIZE:
990  return ERROR_INVALID_FRAME;
991  case ftkQueryStatus::QS_OK:
992  break;
993  default:
994  return ERROR_INVALID_FRAME;
995  }
996 
997  if (this->Internal->Frame->markersStat == ftkQueryStatus::QS_ERR_OVERFLOW)
998  {
999  return ERROR_TOO_MANY_MARKERS;
1000  }
1001 
1002  // make sure markers vector is empty before populating
1003  markers.clear();
1004 
1005  for (size_t m = 0; m < this->Internal->Frame->markersCount; m++)
1006  {
1007  const ftkMarker& marker = this->Internal->Frame->markers[m];
1008 
1009  // A marker
1010  vtkNew<vtkMatrix4x4> toolToTracker;
1011  for (int row = 0; row < 3; row++)
1012  {
1013  toolToTracker->SetElement(row, 3, marker.translationMM[row]);
1014  for (int column = 0; column < 3; column++)
1015  {
1016  toolToTracker->SetElement(row, column, marker.rotation[row][column]);
1017  }
1018  }
1019 
1020  Marker atracsysMarker(marker.status, marker.id, marker.geometryId,
1021  toolToTracker.GetPointer(), marker.geometryPresenceMask, marker.registrationErrorMM);
1022 
1023  // Add the corresponding 3D fiducials
1024  for (size_t f3 = 0; f3 < FTK_MAX_FIDUCIALS; f3++)
1025  {
1026  const uint32 f = marker.fiducialCorresp[f3];
1027  if (f == INVALID_ID) // no more 3D fids for this marker
1028  {
1029  continue;
1030  }
1031  else
1032  {
1033  Fiducial fid;
1034  // 3D stuff
1035  const ftk3DFiducial& ftkFid3d = this->Internal->Frame->threeDFiducials[f];
1036  fid.Fid3dStatus = ftkFid3d.status;
1037  fid.xMm = ftkFid3d.positionMM.x;
1038  fid.yMm = ftkFid3d.positionMM.y;
1039  fid.zMm = ftkFid3d.positionMM.z;
1040  fid.epipolarErrorPx = ftkFid3d.epipolarErrorPixels;
1041  fid.probability = ftkFid3d.probability;
1042  fid.triangulErrorMm = ftkFid3d.triangulationErrorMM;
1043  // Left 2D stuff
1044  const ftkRawData& leftRaw = this->Internal->Frame->rawDataLeft[ftkFid3d.leftIndex];
1045  fid.Fid2dLeftStatus = leftRaw.status;
1046  fid.xLeftPx = leftRaw.centerXPixels;
1047  fid.yLeftPx = leftRaw.centerYPixels;
1048  fid.heightLeftPx = leftRaw.height;
1049  fid.widthLeftPx = leftRaw.width;
1050  fid.pixCountLeft = leftRaw.pixelsCount;
1051  // Right 2D stuff
1052  const ftkRawData& rightRaw = this->Internal->Frame->rawDataRight[ftkFid3d.rightIndex];
1053  fid.Fid2dRightStatus = rightRaw.status;
1054  fid.xRightPx = rightRaw.centerXPixels;
1055  fid.yRightPx = rightRaw.centerYPixels;
1056  fid.heightRightPx = rightRaw.height;
1057  fid.widthRightPx = rightRaw.width;
1058  fid.pixCountRight = rightRaw.pixelsCount;
1059 
1060  if (!atracsysMarker.AddFiducial(fid))
1061  {
1062  return ERROR_TOO_MANY_FIDUCIALS;
1063  }
1064  }
1065  }
1066  markers.push_back(atracsysMarker);
1067  }
1068 
1069  // make sure events map is empty before populating
1070  events.clear();
1071 
1072  // Parse events
1073  for (size_t e = 0; e < this->Internal->Frame->eventsCount; e++)
1074  {
1075  const ftkEvent& event = *this->Internal->Frame->events[e];
1076 
1077  if (event.Type == FtkEventType::fetTempV4)
1078  {
1079  std::stringstream ss;
1080  const EvtTemperatureV4Payload* ptr = reinterpret_cast<EvtTemperatureV4Payload*>(event.Data);
1081  for (unsigned int i = 0; i < event.Payload / sizeof(EvtTemperatureV4Payload) - 1; i++, ++ptr)
1082  {
1083  ss << ptr->SensorId << " " << ptr->SensorValue << " ";
1084  }
1085  ss << ptr->SensorId << " " << ptr->SensorValue;
1086  events.emplace("tempv4", ss.str());
1087  }
1088  }
1089 
1090  // Save sdk timestamp
1091  sdkTimestamp = this->Internal->Frame->imageHeader->timestampUS;
1092 
1093  return SUCCESS;
1094 }
1095 
1096 //----------------------------------------------------------------------------
1097 AtracsysTracker::ATRACSYS_RESULT AtracsysTracker::SetUserLEDState(int red, int green, int blue, int frequency, bool enabled /* = true */)
1098 {
1099  if (this->Internal->isVirtual)
1100  {
1101  return SUCCESS;
1102  }
1103 
1104  // get correct device option number
1105  const ftkOptionsInfo* info;
1106  if (!this->GetOptionInfo("User-LED frequency", info))
1107  {
1108  return ERROR_OPTION_NOT_FOUND;
1109  }
1110  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, frequency) != ftkError::FTK_OK)
1111  {
1112  return ERROR_SET_USER_LED;
1113  }
1114  if (!this->GetOptionInfo("User-LED red component", info))
1115  {
1116  return ERROR_OPTION_NOT_FOUND;
1117  }
1118  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, red) != ftkError::FTK_OK)
1119  {
1120  return ERROR_SET_USER_LED;
1121  }
1122  if (!this->GetOptionInfo("User-LED green component", info))
1123  {
1124  return ERROR_OPTION_NOT_FOUND;
1125  }
1126  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, green) != ftkError::FTK_OK)
1127  {
1128  return ERROR_SET_USER_LED;
1129  }
1130  if (!this->GetOptionInfo("User-LED blue component", info))
1131  {
1132  return ERROR_OPTION_NOT_FOUND;
1133  }
1134  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, blue) != ftkError::FTK_OK)
1135  {
1136  return ERROR_SET_USER_LED;
1137  }
1138  // enable user LED
1139  return this->EnableUserLED(enabled);
1140 }
1141 
1142 //----------------------------------------------------------------------------
1144 {
1145  if (this->Internal->isVirtual)
1146  {
1147  return SUCCESS;
1148  }
1149 
1150  // get correct device option number
1151  const ftkOptionsInfo* info;
1152  if (!this->GetOptionInfo("Enables the user-LED", info))
1153  {
1154  return ERROR_OPTION_NOT_FOUND;
1155  }
1156  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, enabled) != ftkError::FTK_OK)
1157  {
1158  return ERROR_ENABLE_USER_LED;
1159  }
1160  return SUCCESS;
1161 }
1162 
1163 //----------------------------------------------------------------------------
1165 {
1166  if (this->Internal->isVirtual)
1167  {
1168  return SUCCESS;
1169  }
1170 
1171  // get correct device option number
1172  const ftkOptionsInfo* info;
1173  if (!this->GetOptionInfo("Enables lasers", info))
1174  {
1175  return ERROR_OPTION_NOT_FOUND;
1176  }
1177 
1178  int laserEnabledValue = enabled ? 3 : 0; // 3 = both lasers on
1179 
1180  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, laserEnabledValue) != ftkError::FTK_OK)
1181  {
1182  return ERROR_ENABLE_LASER;
1183  }
1184  return SUCCESS;
1185 }
1186 
1187 //----------------------------------------------------------------------------
1189 {
1190  if (this->Internal->isVirtual)
1191  {
1192  return SUCCESS;
1193  }
1194 
1195  // get correct device option number
1196  const ftkOptionsInfo* info;
1197  if (!this->GetOptionInfo("Active Wireless Pairing Enable", info))
1198  {
1199  return ERROR_OPTION_NOT_FOUND;
1200  }
1201 
1202  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, enabled) != ftkError::FTK_OK)
1203  {
1205  }
1206  return SUCCESS;
1207 }
1208 
1209 //----------------------------------------------------------------------------
1211 {
1212  if (this->Internal->isVirtual)
1213  {
1214  return SUCCESS;
1215  }
1216 
1217  // get correct device option number
1218  const ftkOptionsInfo* info;
1219  if (!this->GetOptionInfo("Active Wireless button statuses streaming", info))
1220  {
1221  return ERROR_OPTION_NOT_FOUND;
1222  }
1223 
1224  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, enabled) != ftkError::FTK_OK)
1225  {
1227  }
1228  return SUCCESS;
1229 }
1230 
1231 //----------------------------------------------------------------------------
1233 {
1234  if (this->Internal->isVirtual)
1235  {
1236  return SUCCESS;
1237  }
1238 
1239  // get correct device option number
1240  const ftkOptionsInfo* info;
1241  if (!this->GetOptionInfo("Active Wireless battery state streaming", info))
1242  {
1243  return ERROR_OPTION_NOT_FOUND;
1244  }
1245 
1246  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, enabled) != ftkError::FTK_OK)
1247  {
1249  }
1250  return SUCCESS;
1251 }
1252 
1253 //----------------------------------------------------------------------------
1255 {
1256  if (n < 0)
1257  {
1258  return ERROR_SET_OPTION;
1259  }
1260  this->MaxAdditionalEventsNumber = n;
1261  return SUCCESS;
1262 }
1263 
1264 //----------------------------------------------------------------------------
1266 {
1267  if (n < 0)
1268  {
1269  return ERROR_SET_OPTION;
1270  }
1271  this->Max2dFiducialsNumber = n;
1272  return SUCCESS;
1273 }
1274 
1275 //----------------------------------------------------------------------------
1277 {
1278  if (n < 0)
1279  {
1280  return ERROR_SET_OPTION;
1281  }
1282  this->Max3dFiducialsNumber = n;
1283  return SUCCESS;
1284 }
1285 
1286 //----------------------------------------------------------------------------
1288 {
1289  if (n < 0)
1290  {
1291  return ERROR_SET_OPTION;
1292  }
1293  this->MaxMarkersNumber = n;
1294  return SUCCESS;
1295 }
1296 
1297 // ------------------------------------------
1298 // spryTrack only options
1299 // ------------------------------------------
1300 
1302 {
1303  if (this->Internal->isVirtual)
1304  {
1305  return SUCCESS;
1306  }
1307 
1308  // get correct device option number
1309  const ftkOptionsInfo* info;
1310  if (!this->GetOptionInfo("Enable embedded processing", info))
1311  {
1312  return ERROR_OPTION_NOT_FOUND;
1313  }
1314 
1315  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, enabled) != ftkError::FTK_OK)
1316  {
1318  }
1319  LOG_INFO("Embedded processing successfully " << (enabled ? "enabled" : "disabled"));
1320  return SUCCESS;
1321 }
1322 
1323 //----------------------------------------------------------------------------
1325 {
1326  if (this->Internal->isVirtual)
1327  {
1328  return SUCCESS;
1329  }
1330 
1331  // get correct device option number
1332  const ftkOptionsInfo* info;
1333  if (!this->GetOptionInfo("Enable images sending", info))
1334  {
1335  return ERROR_OPTION_NOT_FOUND;
1336  }
1337 
1338  if (ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, enabled) != ftkError::FTK_OK)
1339  {
1341  }
1342  LOG_INFO("Image streaming successfully " << (enabled ? "enabled" : "disabled"));
1343  return SUCCESS;
1344 }
1345 
1346 //----------------------------------------------------------------------------
1348 {
1349  if (this->DeviceType != SPRYTRACK_180 && this->DeviceType != SPRYTRACK_300)
1350  {
1351  LOG_WARNING("Embedded processing is available only on spryTracks.");
1353  }
1354  bool succeeded = true;
1355  if (processingType == PROCESSING_ONBOARD)
1356  {
1357  succeeded = succeeded && (this->EnableOnboardProcessing(true) == SUCCESS);
1358  succeeded = succeeded && (this->EnableImageStreaming(false) == SUCCESS);
1359  isOnboardProcessing = true;
1360  }
1361  else if (processingType == PROCESSING_ON_PC)
1362  {
1363  succeeded = succeeded && (this->EnableOnboardProcessing(false) == SUCCESS);
1364  succeeded = succeeded && (this->EnableImageStreaming(true) == SUCCESS);
1365  isOnboardProcessing = false;
1366  }
1367 
1368  if (!succeeded)
1369  {
1371  }
1372  return SUCCESS;
1373 }
1374 
1375 // ------------------------------------------
1376 // fusionTrack only options
1377 // ------------------------------------------
1378 
1380 {
1381  if (this->Internal->isVirtual)
1382  {
1383  droppedFrameCount = 0;
1384  return SUCCESS;
1385  }
1386 
1387  if (this->DeviceType == FUSIONTRACK_250 || this->DeviceType == FUSIONTRACK_500)
1388  {
1389  int32 lost = 0, corrupted = 0;
1390  // get correct device option number
1391  const ftkOptionsInfo* info;
1392  if (!this->GetOptionInfo("Counter of lost frames", info))
1393  {
1394  return ERROR_OPTION_NOT_FOUND;
1395  }
1396  ftkGetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, &lost, ftkOptionGetter::FTK_VALUE);
1397  if (!this->GetOptionInfo("Counter of corrupted frames", info))
1398  {
1399  return ERROR_OPTION_NOT_FOUND;
1400  }
1401  ftkGetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, &corrupted, ftkOptionGetter::FTK_VALUE);
1402 
1403  droppedFrameCount = lost + corrupted;
1404  return SUCCESS;
1405  }
1407 }
1408 
1409 //----------------------------------------------------------------------------
1411 {
1412  if (this->Internal->isVirtual)
1413  {
1414  return SUCCESS;
1415  }
1416 
1417  if (this->DeviceType == FUSIONTRACK_250 || this->DeviceType == FUSIONTRACK_500)
1418  {
1419  // get correct device option number
1420  const ftkOptionsInfo* info;
1421  if (!this->GetOptionInfo("Resets lost counters", info))
1422  {
1423  return ERROR_OPTION_NOT_FOUND;
1424  }
1425  ftkSetInt32(this->Internal->FtkLib, this->Internal->TrackerSN, info->id, RESET_DROPPED_FRAME_COUNT);
1426  return SUCCESS;
1427  }
1429 }
1430 
1431 // ------------------------------------------
1432 // Fiducial methods
1433 // ------------------------------------------
1434 
1435 // any 2 fiducials within this 3D distance in mm will be considered equal
1436 const float EQUALITY_DISTANCE_MM = 2.0;
1437 
1439 {
1440  // pow is much slower than just x*x for squaring numbers
1441  float dist2 = (this->xMm - f.xMm) * (this->xMm - f.xMm) + (this->yMm - f.yMm) * (this->yMm - f.yMm) + (this->zMm - f.zMm) * (this->zMm - f.zMm);
1442  return sqrt(dist2) < EQUALITY_DISTANCE_MM;
1443 }
1444 
1445 // compare fiducials on distance from the origin
1447 {
1448  float distF1 = sqrt(this->xMm * this->xMm + this->yMm * this->yMm + this->zMm * this->zMm);
1449  float distF2 = sqrt(f.xMm * f.xMm + f.yMm * f.yMm + f.zMm * f.zMm);
1450  return distF1 < distF2;
1451 }
1452 
1453 // ------------------------------------------
1454 // Marker methods
1455 // ------------------------------------------
1456 
1458 {
1459  this->MarkerStatus = 0;
1460  this->TrackingId = -1;
1461  this->GeometryId = -1;
1462  this->GeometryPresenceMask = -1;
1463  this->RegistrationErrorMm = 0.0;
1464 }
1465 AtracsysTracker::Marker::Marker(int status, int trackingId, int geometryId,
1466  vtkMatrix4x4* toolToTracker, int geometryPresenceMask, float registrationErrorMM)
1467 {
1468  this->MarkerStatus = status;
1469  this->TrackingId = trackingId;
1470  this->GeometryId = geometryId;
1471  this->ToolToTracker->DeepCopy(toolToTracker);
1472  this->GeometryPresenceMask = geometryPresenceMask;
1473  this->RegistrationErrorMm = registrationErrorMM;
1474 }
1475 
1477 {
1478  this->MarkerStatus = obj.MarkerStatus;
1479  this->TrackingId = obj.TrackingId;
1480  this->GeometryId = obj.GeometryId;
1481  this->ToolToTracker->DeepCopy(obj.ToolToTracker.GetPointer());
1482  this->GeometryPresenceMask = obj.GeometryPresenceMask;
1483  this->RegistrationErrorMm = obj.RegistrationErrorMm;
1484  this->fiducials = obj.fiducials;
1485 }
1486 
1488 {
1489  if (fiducials.size() < FTK_MAX_FIDUCIALS)
1490  {
1491  fiducials.push_back(fid);
1492  return true;
1493  }
1494  else
1495  {
1496  return false;
1497  }
1498 }
const uint32_t * data
Definition: phidget22.h:3971
ATRACSYS_RESULT SetUserLEDState(int red, int green, int blue, int frequency, bool enabled=true)
#define ATRACSYS_BUFFER_SIZE
ATRACSYS_RESULT GetCalibrationDate(std::string &date)
const char * key
Definition: phidget22.h:5111
ATRACSYS_RESULT GetDeviceId(uint64_t &id)
#define RESET_DROPPED_FRAME_COUNT
const char int line
Definition: phidget22.h:2458
void Pause(bool tof)
ATRACSYS_RESULT GetLoadedGeometries(std::map< int, std::vector< std::array< float, 3 >>> &geometries)
ATRACSYS_RESULT EnableUserLED(bool enabled)
ATRACSYS_RESULT SetMax3dFiducialsNumber(int n)
ATRACSYS_RESULT GetDeviceType(DEVICE_TYPE &deviceType)
for i
ATRACSYS_RESULT Disconnect()
ATRACSYS_RESULT SetOption(const std::string &, const std::string &)
ATRACSYS_RESULT EnableWirelessMarkerBatteryStreaming(bool enabled)
ATRACSYS_RESULT EnableWirelessMarkerStatusStreaming(bool enabled)
ATRACSYS_RESULT EnableOnboardProcessing(bool enabled)
ATRACSYS_RESULT GetDroppedFrameCount(int &droppedFrameCount)
ATRACSYS_RESULT SetMaxMarkersNumber(int n)
Image slice number p
Definition: algo4.m:14
ATRACSYS_RESULT LoadMarkerGeometryFromFile(std::string filePath, int &geometryId)
bool strToInt32(const std::string &str, int &var)
ATRACSYS_RESULT GetMarkersInFrame(std::vector< Marker > &markers, std::map< std::string, std::string > &events, uint64_t &sdkTimestamp)
std::string ResultToString(ATRACSYS_RESULT result)
bool GetOptionInfo(const std::string &, const ftkOptionsInfo *&)
ATRACSYS_RESULT LoadMarkerGeometryFromString(std::string filePath, int &geometryId)
int enabled
Definition: phidget22.h:3369
ATRACSYS_RESULT ResetLostFrameCount()
bool operator==(const Fiducial &f)
ATRACSYS_RESULT SetMaxAdditionalEventsNumber(int n)
bool strToFloat32(const std::string &str, float &var)
ATRACSYS_RESULT GetMarkerInfo(std::string &markerInfo)
ATRACSYS_RESULT EnableImageStreaming(bool enabled)
ATRACSYS_RESULT GetSDKversion(std::string &version)
ATRACSYS_RESULT GetCamerasCalibration(std::array< float, 10 > &leftIntrinsic, std::array< float, 10 > &rightIntrinsic, std::array< float, 3 > &rightPosition, std::array< float, 3 > &rightOrientation)
bool operator<(const Fiducial &f) const
PhidgetGPS_Date * date
Definition: phidget22.h:3617
ATRACSYS_RESULT SetSpryTrackProcessingType(SPRYTRACK_IMAGE_PROCESSING_TYPE processingType)
void FusionTrackEnumerator(uint64 sn, void *user, ftkDeviceType devType)
ATRACSYS_RESULT SetLaserEnabled(bool enabled)
virtual ~AtracsysTracker()
ATRACSYS_RESULT SetMax2dFiducialsNumber(int n)
double frequency
Definition: phidget22.h:3246
ATRACSYS_RESULT EnableWirelessMarkerPairing(bool enabled)
const float EQUALITY_DISTANCE_MM
ATRACSYS_RESULT Connect()
bool AddFiducial(Fiducial fid)