Commit 350e278bdecfd733e953fb8353c5b184c88c97e9

Authored by sotodela
Committed by GitHub
1 parent ba5cb56a
Exists in master

Tracker optitrack python 37 (#279)

* add initial modifications to add optitrack tracker

* fix variable names on coordinate function of optitrack

* add transformation euler from quaternion

* fix input order of quaternions to euler_from_quaternion function

* add conversion to degrees in quaternion transformation on optitrack funcion

* fix scale

* fix coordinates order in array and modify X,Y,Z coordinate system in optitrack coordinate function

* add update cameras/frame function before Run function

* add Run function after Initialize

* removed update before Run optitrack function

* reduce Sleep_navigation variable

* add documentation to optitrack functions

* add condition to when optitrack hardware Key is not found
invesalius/constants.py
... ... @@ -666,8 +666,9 @@ ISOTRAKII = 3
666 666 PATRIOT = 4
667 667 CAMERA = 5
668 668 POLARIS = 6
669   -DEBUGTRACK = 7
670   -DISCTRACK = 8
  669 +OPTITRACK = 7
  670 +DEBUGTRACK = 8
  671 +DISCTRACK = 9
671 672 DEFAULT_TRACKER = SELECT
672 673  
673 674 NDICOMPORT = b'COM1'
... ... @@ -675,7 +676,7 @@ NDICOMPORT = b'COM1'
675 676 TRACKER = [_("Select tracker:"), _("Claron MicronTracker"),
676 677 _("Polhemus FASTRAK"), _("Polhemus ISOTRAK II"),
677 678 _("Polhemus PATRIOT"), _("Camera tracker"),
678   - _("NDI Polaris"), _("Debug tracker"), _("Disconnect tracker")]
  679 + _("NDI Polaris"), _("Optitrack"), _("Debug tracker"), _("Disconnect tracker")]
679 680  
680 681 STATIC_REF = 0
681 682 DYNAMIC_REF = 1
... ... @@ -753,7 +754,7 @@ PEEL_DEPTH = 5
753 754 MAX_PEEL_DEPTH = 30
754 755 SEED_OFFSET = 15
755 756 SEED_RADIUS = 1.5
756   -SLEEP_NAVIGATION = 0.3
  757 +SLEEP_NAVIGATION = 0.1
757 758 BRAIN_OPACITY = 0.5
758 759 N_CPU = psutil.cpu_count()
759 760 TREKKER_CONFIG = {'seed_max': 1, 'step_size': 0.1, 'min_fod': 0.1, 'probe_quality': 3,
... ...
invesalius/data/coordinates.py
... ... @@ -48,6 +48,7 @@ def GetCoordinates(trck_init, trck_id, ref_mode):
48 48 const.PATRIOT: PolhemusCoord,
49 49 const.CAMERA: CameraCoord,
50 50 const.POLARIS: PolarisCoord,
  51 + const.OPTITRACK: OptitrackCoord,
51 52 const.DEBUGTRACK: DebugCoord}
52 53 coord = getcoord[trck_id](trck_init, trck_id, ref_mode)
53 54 else:
... ... @@ -55,6 +56,46 @@ def GetCoordinates(trck_init, trck_id, ref_mode):
55 56  
56 57 return coord
57 58  
  59 +def OptitrackCoord(trck_init, trck_id, ref_mode):
  60 + """
  61 +
  62 + Obtains coordinates and angles of tracking rigid bodies (Measurement Probe, Coil, Head). Converts orientations from quaternion
  63 + rotations to Euler angles. This function uses Optitrack wrapper from Motive API 2.2.
  64 +
  65 + Parameters
  66 + ----------
  67 + :trck_init: tracker initialization instance from OptitrackTracker function at trackers.py
  68 + :trck_id: not used
  69 + :ref_mode: not used
  70 +
  71 + Returns
  72 + -------
  73 + coord: position of tracking rigid bodies
  74 + """
  75 + trck=trck_init[0]
  76 + trck.Run()
  77 +
  78 + scale = 1000*np.array([1.0, 1.0, 1.0]) # coordinates are in millimeters in Motive API
  79 +
  80 + angles_probe = np.degrees(tr.euler_from_quaternion([float(trck.qwToolTip), float(trck.qzToolTip), float(trck.qxToolTip), float(trck.qyToolTip)], axes='rzyx'))
  81 + coord1 = np.array([float(trck.PositionToolTipZ1) * scale[0], float(trck.PositionToolTipX1) * scale[1],
  82 + float(trck.PositionToolTipY1) * scale[2]])
  83 + coord1 = np.hstack((coord1, angles_probe))
  84 +
  85 + angles_head = np.degrees(tr.euler_from_quaternion([float(trck.qwHead), float(trck.qzHead), float(trck.qxHead), float(trck.qyHead)], axes='rzyx'))
  86 + coord2 = np.array([float(trck.PositionHeadZ1) * scale[0], float(trck.PositionHeadX1) * scale[1],
  87 + float(trck.PositionHeadY1) * scale[2]])
  88 + coord2 = np.hstack((coord2, angles_head))
  89 +
  90 + angles_coil = np.degrees(tr.euler_from_quaternion([float(trck.qwCoil), float(trck.qzCoil), float(trck.qxCoil), float(trck.qyCoil)], axes='rzyx'))
  91 + coord3 = np.array([float(trck.PositionCoilZ1) * scale[0], float(trck.PositionCoilX1) * scale[1],
  92 + float(trck.PositionCoilY1) * scale[2]])
  93 + coord3 = np.hstack((coord3, angles_coil))
  94 +
  95 + coord = np.vstack([coord1, coord2, coord3])
  96 + return coord
  97 +
  98 +
58 99 def PolarisCoord(trck_init, trck_id, ref_mode):
59 100 trck = trck_init[0]
60 101 trck.Run()
... ...
invesalius/data/trackers.py
... ... @@ -40,6 +40,7 @@ def TrackerConnection(tracker_id, trck_init, action):
40 40 const.PATRIOT: PolhemusTracker, # PATRIOT
41 41 const.CAMERA: CameraTracker, # CAMERA
42 42 const.POLARIS: PolarisTracker, # POLARIS
  43 + const.OPTITRACK: OptitrackTracker, #Optitrack
43 44 const.DEBUGTRACK: DebugTracker}
44 45  
45 46 trck_init = trck_fcn[tracker_id](tracker_id)
... ... @@ -62,6 +63,30 @@ def DefaultTracker(tracker_id):
62 63 # return tracker initialization variable and type of connection
63 64 return trck_init, 'wrapper'
64 65  
  66 +def OptitrackTracker(tracker_id):
  67 + """
  68 + Imports optitrack wrapper from Motive 2.2. Initialize cameras, attach listener, loads Calibration, loads User Profile
  69 + (Rigid bodies information).
  70 +
  71 + Parameters
  72 + ----------
  73 + tracker_id : Optitrack ID
  74 +
  75 + Returns
  76 + -------
  77 + trck_init : local name for Optitrack module
  78 + """
  79 + trck_init = None
  80 + try:
  81 + import optitrack
  82 + trck_init = optitrack.optr()
  83 + if trck_init.Initialize()==0:
  84 + trck_init.Run() #Runs once Run function, to update cameras.
  85 + else:
  86 + trck_init = None
  87 + except ImportError:
  88 + print('Error')
  89 + return trck_init, 'wrapper'
65 90  
66 91 def PolarisTracker(tracker_id):
67 92 from wx import ID_OK
... ...
invesalius/gui/dialogs.py
... ... @@ -869,6 +869,7 @@ def ShowNavigationTrackerWarning(trck_id, lib_mode):
869 869 const.PATRIOT: 'Polhemus PATRIOT',
870 870 const.CAMERA: 'CAMERA',
871 871 const.POLARIS: 'NDI Polaris',
  872 + const.OPTITRACK: 'Optitrack',
872 873 const.DEBUGTRACK: 'Debug tracker device'}
873 874  
874 875 if lib_mode == 'choose':
... ...