Commit 490d87a83a37a37b3544842d88e251fdb2869c20

Authored by Victor Hugo Souza
Committed by GitHub
2 parents dd8b84f9 0b8581bf
Exists in master

Merge pull request #369 from rmatsuda/Thread-for-coordinates

Creation of a new thread for coordinates acquisition
invesalius/constants.py
@@ -818,6 +818,7 @@ SEED_RADIUS = 1.5 @@ -818,6 +818,7 @@ SEED_RADIUS = 1.5
818 818
819 # Increased the default sleep parameter from 0.1 to 0.15 to decrease CPU load during navigation. 819 # Increased the default sleep parameter from 0.1 to 0.15 to decrease CPU load during navigation.
820 SLEEP_NAVIGATION = 0.15 820 SLEEP_NAVIGATION = 0.15
  821 +SLEEP_COORDINATES = 0.05
821 822
822 BRAIN_OPACITY = 0.5 823 BRAIN_OPACITY = 0.5
823 N_CPU = psutil.cpu_count() 824 N_CPU = psutil.cpu_count()
invesalius/data/coordinates.py
@@ -19,6 +19,9 @@ @@ -19,6 +19,9 @@
19 19
20 from math import sin, cos 20 from math import sin, cos
21 import numpy as np 21 import numpy as np
  22 +import queue
  23 +import threading
  24 +import wx
22 25
23 import invesalius.data.bases as db 26 import invesalius.data.bases as db
24 import invesalius.data.transformations as tr 27 import invesalius.data.transformations as tr
@@ -28,9 +31,21 @@ from time import sleep @@ -28,9 +31,21 @@ from time import sleep
28 from random import uniform 31 from random import uniform
29 from invesalius.pubsub import pub as Publisher 32 from invesalius.pubsub import pub as Publisher
30 33
  34 +class TrackerCoordinates():
  35 + def __init__(self):
  36 + self.coord = None
  37 + self.markers_flag = [False, False, False]
31 38
32 -def GetCoordinates(trck_init, trck_id, ref_mode): 39 + def SetCoordinates(self, coord, markers_flag):
  40 + self.coord = coord
  41 + self.markers_flag = markers_flag
  42 + wx.CallAfter(Publisher.sendMessage, 'Sensors ID', markers_flag=self.markers_flag)
33 43
  44 + def GetCoordinates(self):
  45 + return self.coord, self.markers_flag
  46 +
  47 +
  48 +def GetCoordinatesForThread(trck_init, trck_id, ref_mode):
34 """ 49 """
35 Read coordinates from spatial tracking devices using 50 Read coordinates from spatial tracking devices using
36 51
@@ -52,11 +67,13 @@ def GetCoordinates(trck_init, trck_id, ref_mode): @@ -52,11 +67,13 @@ def GetCoordinates(trck_init, trck_id, ref_mode):
52 const.OPTITRACK: OptitrackCoord, 67 const.OPTITRACK: OptitrackCoord,
53 const.DEBUGTRACKRANDOM: DebugCoordRandom, 68 const.DEBUGTRACKRANDOM: DebugCoordRandom,
54 const.DEBUGTRACKAPPROACH: DebugCoordRandom} 69 const.DEBUGTRACKAPPROACH: DebugCoordRandom}
55 - coord = getcoord[trck_id](trck_init, trck_id, ref_mode) 70 +
  71 + coord, markers_flag = getcoord[trck_id](trck_init, trck_id, ref_mode)
56 else: 72 else:
57 print("Select Tracker") 73 print("Select Tracker")
58 74
59 - return coord 75 + return coord, markers_flag
  76 +
60 77
61 def OptitrackCoord(trck_init, trck_id, ref_mode): 78 def OptitrackCoord(trck_init, trck_id, ref_mode):
62 """ 79 """
@@ -93,8 +110,10 @@ def OptitrackCoord(trck_init, trck_id, ref_mode): @@ -93,8 +110,10 @@ def OptitrackCoord(trck_init, trck_id, ref_mode):
93 coord3 = np.array([float(trck.PositionCoilZ1) * scale[0], float(trck.PositionCoilX1) * scale[1], 110 coord3 = np.array([float(trck.PositionCoilZ1) * scale[0], float(trck.PositionCoilX1) * scale[1],
94 float(trck.PositionCoilY1) * scale[2]]) 111 float(trck.PositionCoilY1) * scale[2]])
95 coord3 = np.hstack((coord3, angles_coil)) 112 coord3 = np.hstack((coord3, angles_coil))
  113 +
96 coord = np.vstack([coord1, coord2, coord3]) 114 coord = np.vstack([coord1, coord2, coord3])
97 - return coord 115 +
  116 + return coord, [trck.probeID, trck.HeadID, trck.coilID]
98 117
99 118
100 def PolarisCoord(trck_init, trck_id, ref_mode): 119 def PolarisCoord(trck_init, trck_id, ref_mode):
@@ -117,9 +136,9 @@ def PolarisCoord(trck_init, trck_id, ref_mode): @@ -117,9 +136,9 @@ def PolarisCoord(trck_init, trck_id, ref_mode):
117 coord3 = np.hstack((trans_obj, angles_obj)) 136 coord3 = np.hstack((trans_obj, angles_obj))
118 137
119 coord = np.vstack([coord1, coord2, coord3]) 138 coord = np.vstack([coord1, coord2, coord3])
120 - # Publisher.sendMessage('Sensors ID', probe_id=trck.probeID, ref_id=trck.refID, obj_id=trck.objID)  
121 139
122 - return coord 140 + return coord, [trck.probeID, trck.refID, trck.objID]
  141 +
123 142
124 def PolarisP4Coord(trck_init, trck_id, ref_mode): 143 def PolarisP4Coord(trck_init, trck_id, ref_mode):
125 trck = trck_init[0] 144 trck = trck_init[0]
@@ -134,45 +153,41 @@ def PolarisP4Coord(trck_init, trck_id, ref_mode): @@ -134,45 +153,41 @@ def PolarisP4Coord(trck_init, trck_id, ref_mode):
134 obj = obj[2:] 153 obj = obj[2:]
135 154
136 if probe[:7] == "MISSING": 155 if probe[:7] == "MISSING":
137 - if not "coord1" in locals():  
138 - coord1 = np.hstack(([0, 0, 0], [0, 0, 0])) 156 + coord1 = np.hstack(([0, 0, 0], [0, 0, 0]))
139 else: 157 else:
140 q = [int(probe[i:i + 6]) * 0.0001 for i in range(0, 24, 6)] 158 q = [int(probe[i:i + 6]) * 0.0001 for i in range(0, 24, 6)]
141 t = [int(probe[i:i + 7]) * 0.01 for i in range(24, 45, 7)] 159 t = [int(probe[i:i + 7]) * 0.01 for i in range(24, 45, 7)]
142 angles_probe = np.degrees(tr.euler_from_quaternion(q, axes='rzyx')) 160 angles_probe = np.degrees(tr.euler_from_quaternion(q, axes='rzyx'))
143 trans_probe = np.array(t).astype(float) 161 trans_probe = np.array(t).astype(float)
144 coord1 = np.hstack((trans_probe, angles_probe)) 162 coord1 = np.hstack((trans_probe, angles_probe))
145 -  
146 - if ref[:7] == "MISSING":  
147 - if not "coord2" in locals(): 163 + if ref[:7] == "MISSING":
148 coord2 = np.hstack(([0, 0, 0], [0, 0, 0])) 164 coord2 = np.hstack(([0, 0, 0], [0, 0, 0]))
149 - else:  
150 - q = [int(ref[i:i + 6]) * 0.0001 for i in range(0, 24, 6)]  
151 - t = [int(ref[i:i + 7]) * 0.01 for i in range(24, 45, 7)]  
152 - angles_ref = np.degrees(tr.euler_from_quaternion(q, axes='rzyx'))  
153 - trans_ref = np.array(t).astype(float)  
154 - coord2 = np.hstack((trans_ref, angles_ref))  
155 -  
156 - if obj[:7] == "MISSING":  
157 - if not "coord3" in locals(): 165 + else:
  166 + q = [int(ref[i:i + 6]) * 0.0001 for i in range(0, 24, 6)]
  167 + t = [int(ref[i:i + 7]) * 0.01 for i in range(24, 45, 7)]
  168 + angles_ref = np.degrees(tr.euler_from_quaternion(q, axes='rzyx'))
  169 + trans_ref = np.array(t).astype(float)
  170 + coord2 = np.hstack((trans_ref, angles_ref))
  171 +
  172 + if obj[:7] == "MISSING":
158 coord3 = np.hstack(([0, 0, 0], [0, 0, 0])) 173 coord3 = np.hstack(([0, 0, 0], [0, 0, 0]))
159 - else:  
160 - q = [int(obj[i:i + 6]) * 0.0001 for i in range(0, 24, 6)]  
161 - t = [int(obj[i:i + 7]) * 0.01 for i in range(24, 45, 7)]  
162 - angles_obj = np.degrees(tr.euler_from_quaternion(q, axes='rzyx'))  
163 - trans_obj = np.array(t).astype(float)  
164 - coord3 = np.hstack((trans_obj, angles_obj)) 174 + else:
  175 + q = [int(obj[i:i + 6]) * 0.0001 for i in range(0, 24, 6)]
  176 + t = [int(obj[i:i + 7]) * 0.01 for i in range(24, 45, 7)]
  177 + angles_obj = np.degrees(tr.euler_from_quaternion(q, axes='rzyx'))
  178 + trans_obj = np.array(t).astype(float)
  179 + coord3 = np.hstack((trans_obj, angles_obj))
165 180
166 - Publisher.sendMessage('Sensors ID', probe_id=trck.probeID, ref_id=trck.refID, obj_id=trck.objID)  
167 - coord = np.vstack([coord1, coord2, coord3]) 181 + coord = np.vstack([coord1, coord2, coord3])
  182 +
  183 + return coord, [trck.probeID, trck.refID, trck.objID]
168 184
169 - return coord  
170 185
171 def CameraCoord(trck_init, trck_id, ref_mode): 186 def CameraCoord(trck_init, trck_id, ref_mode):
172 trck = trck_init[0] 187 trck = trck_init[0]
173 - coord, probeID, refID = trck.Run()  
174 - Publisher.sendMessage('Sensors ID', probe_id=probeID, ref_id=refID)  
175 - return coord 188 + coord, probeID, refID, coilID = trck.Run()
  189 +
  190 + return coord, [probeID, refID, coilID]
176 191
177 def ClaronCoord(trck_init, trck_id, ref_mode): 192 def ClaronCoord(trck_init, trck_id, ref_mode):
178 trck = trck_init[0] 193 trck = trck_init[0]
@@ -193,9 +208,7 @@ def ClaronCoord(trck_init, trck_id, ref_mode): @@ -193,9 +208,7 @@ def ClaronCoord(trck_init, trck_id, ref_mode):
193 208
194 coord = np.vstack([coord1, coord2, coord3]) 209 coord = np.vstack([coord1, coord2, coord3])
195 210
196 - Publisher.sendMessage('Sensors ID', probe_id=trck.probeID, ref_id=trck.refID)  
197 -  
198 - return coord 211 + return coord, [trck.probeID, trck.refID, trck.coilID]
199 212
200 213
201 def PolhemusCoord(trck, trck_id, ref_mode): 214 def PolhemusCoord(trck, trck_id, ref_mode):
@@ -210,7 +223,7 @@ def PolhemusCoord(trck, trck_id, ref_mode): @@ -210,7 +223,7 @@ def PolhemusCoord(trck, trck_id, ref_mode):
210 elif trck[1] == 'wrapper': 223 elif trck[1] == 'wrapper':
211 coord = PolhemusWrapperCoord(trck[0], trck_id, ref_mode) 224 coord = PolhemusWrapperCoord(trck[0], trck_id, ref_mode)
212 225
213 - return coord 226 + return coord, None
214 227
215 228
216 def PolhemusWrapperCoord(trck, trck_id, ref_mode): 229 def PolhemusWrapperCoord(trck, trck_id, ref_mode):
@@ -362,16 +375,13 @@ def DebugCoordRandom(trk_init, trck_id, ref_mode): @@ -362,16 +375,13 @@ def DebugCoordRandom(trk_init, trck_id, ref_mode):
362 # coord4 = np.array([uniform(1, 200), uniform(1, 200), uniform(1, 200), 375 # coord4 = np.array([uniform(1, 200), uniform(1, 200), uniform(1, 200),
363 # uniform(-180.0, 180.0), uniform(-180.0, 180.0), uniform(-180.0, 180.0)]) 376 # uniform(-180.0, 180.0), uniform(-180.0, 180.0), uniform(-180.0, 180.0)])
364 377
365 - Publisher.sendMessage('Sensors ID', probe_id=int(uniform(0, 5)), ref_id=int(uniform(0, 5)), obj_id=int(uniform(0, 5)))  
366 -  
367 - return np.vstack([coord1, coord2, coord3, coord4]) 378 + return np.vstack([coord1, coord2, coord3, coord4]), [int(uniform(0, 5)), int(uniform(0, 5)), int(uniform(0, 5))]
368 379
369 380
370 def coordinates_to_transformation_matrix(position, orientation, axes='sxyz'): 381 def coordinates_to_transformation_matrix(position, orientation, axes='sxyz'):
371 """ 382 """
372 Transform vectors consisting of position and orientation (in Euler angles) in 3d-space into a 4x4 383 Transform vectors consisting of position and orientation (in Euler angles) in 3d-space into a 4x4
373 transformation matrix that combines the rotation and translation. 384 transformation matrix that combines the rotation and translation.
374 -  
375 :param position: A vector of three coordinates. 385 :param position: A vector of three coordinates.
376 :param orientation: A vector of three Euler angles in degrees. 386 :param orientation: A vector of three Euler angles in degrees.
377 :param axes: The order in which the rotations are done for the axes. See transformations.py for details. Defaults to 'sxyz'. 387 :param axes: The order in which the rotations are done for the axes. See transformations.py for details. Defaults to 'sxyz'.
@@ -391,9 +401,7 @@ def transformation_matrix_to_coordinates(matrix, axes='sxyz'): @@ -391,9 +401,7 @@ def transformation_matrix_to_coordinates(matrix, axes='sxyz'):
391 """ 401 """
392 Given a matrix that combines the rotation and translation, return the position and the orientation 402 Given a matrix that combines the rotation and translation, return the position and the orientation
393 determined by the matrix. The orientation is given as three Euler angles. 403 determined by the matrix. The orientation is given as three Euler angles.
394 -  
395 The inverse of coordinates_of_transformation_matrix when the parameter 'axes' matches. 404 The inverse of coordinates_of_transformation_matrix when the parameter 'axes' matches.
396 -  
397 :param matrix: A 4x4 transformation matrix. 405 :param matrix: A 4x4 transformation matrix.
398 :param axes: The order in which the rotations are done for the axes. See transformations.py for details. Defaults to 'sxyz'. 406 :param axes: The order in which the rotations are done for the axes. See transformations.py for details. Defaults to 'sxyz'.
399 :return: The position (a vector of length 3) and Euler angles for the orientation in degrees (a vector of length 3). 407 :return: The position (a vector of length 3) and Euler angles for the orientation in degrees (a vector of length 3).
@@ -479,6 +487,7 @@ def dynamic_reference_m2(probe, reference): @@ -479,6 +487,7 @@ def dynamic_reference_m2(probe, reference):
479 :param reference: sensor two defined as reference 487 :param reference: sensor two defined as reference
480 :return: rotated and translated coordinates 488 :return: rotated and translated coordinates
481 """ 489 """
  490 +
482 M = coordinates_to_transformation_matrix( 491 M = coordinates_to_transformation_matrix(
483 position=reference[:3], 492 position=reference[:3],
484 orientation=reference[3:], 493 orientation=reference[3:],
@@ -489,6 +498,7 @@ def dynamic_reference_m2(probe, reference): @@ -489,6 +498,7 @@ def dynamic_reference_m2(probe, reference):
489 orientation=probe[3:], 498 orientation=probe[3:],
490 axes='rzyx', 499 axes='rzyx',
491 ) 500 )
  501 +
492 M_dyn = np.linalg.inv(M) @ M_p 502 M_dyn = np.linalg.inv(M) @ M_p
493 503
494 al, be, ga = tr.euler_from_matrix(M_dyn, 'rzyx') 504 al, be, ga = tr.euler_from_matrix(M_dyn, 'rzyx')
@@ -529,3 +539,17 @@ def offset_coordinate(p_old, norm_vec, offset): @@ -529,3 +539,17 @@ def offset_coordinate(p_old, norm_vec, offset):
529 """ 539 """
530 p_offset = p_old - offset * norm_vec 540 p_offset = p_old - offset * norm_vec
531 return p_offset 541 return p_offset
  542 +
  543 +class ReceiveCoordinates(threading.Thread):
  544 + def __init__(self, trck_init, trck_id, TrackerCoordinates, event):
  545 + threading.Thread.__init__(self, name='ReceiveCoordinates')
  546 + self.trck_init = trck_init
  547 + self.trck_id = trck_id
  548 + self.event = event
  549 + self.TrackerCoordinates = TrackerCoordinates
  550 +
  551 + def run(self):
  552 + while not self.event.is_set():
  553 + coord_raw, markers_flag = GetCoordinatesForThread(self.trck_init, self.trck_id, const.DEFAULT_REF_MODE)
  554 + self.TrackerCoordinates.SetCoordinates(coord_raw, markers_flag)
  555 + sleep(const.SLEEP_COORDINATES)
532 \ No newline at end of file 556 \ No newline at end of file
invesalius/data/coregistration.py
@@ -219,7 +219,7 @@ class CoordinateCorregistrate(threading.Thread): @@ -219,7 +219,7 @@ class CoordinateCorregistrate(threading.Thread):
219 else: 219 else:
220 self.icp, self.m_icp = self.icp_queue.get_nowait() 220 self.icp, self.m_icp = self.icp_queue.get_nowait()
221 # print(f"Set the coordinate") 221 # print(f"Set the coordinate")
222 - coord_raw = dco.GetCoordinates(trck_init, trck_id, self.ref_mode_id) 222 + coord_raw, markers_flag = self.tracker.TrackerCoordinates.GetCoordinates()
223 coord, m_img = corregistrate_object_dynamic(coreg_data, coord_raw, self.ref_mode_id, [self.icp, self.m_icp]) 223 coord, m_img = corregistrate_object_dynamic(coreg_data, coord_raw, self.ref_mode_id, [self.icp, self.m_icp])
224 224
225 # XXX: This is not the best place to do the logic related to approaching the target when the 225 # XXX: This is not the best place to do the logic related to approaching the target when the
@@ -294,7 +294,7 @@ class CoordinateCorregistrateNoObject(threading.Thread): @@ -294,7 +294,7 @@ class CoordinateCorregistrateNoObject(threading.Thread):
294 self.icp, self.m_icp = self.icp_queue.get_nowait() 294 self.icp, self.m_icp = self.icp_queue.get_nowait()
295 # print(f"Set the coordinate") 295 # print(f"Set the coordinate")
296 #print(self.icp, self.m_icp) 296 #print(self.icp, self.m_icp)
297 - coord_raw = dco.GetCoordinates(trck_init, trck_id, self.ref_mode_id) 297 + coord_raw, markers_flag = self.tracker.TrackerCoordinates.GetCoordinates()
298 coord, m_img = corregistrate_dynamic(coreg_data, coord_raw, self.ref_mode_id, [self.icp, self.m_icp]) 298 coord, m_img = corregistrate_dynamic(coreg_data, coord_raw, self.ref_mode_id, [self.icp, self.m_icp])
299 # print("Coord: ", coord) 299 # print("Coord: ", coord)
300 m_img_flip = m_img.copy() 300 m_img_flip = m_img.copy()
invesalius/data/viewer_volume.py
@@ -368,7 +368,9 @@ class Viewer(wx.Panel): @@ -368,7 +368,9 @@ class Viewer(wx.Panel):
368 368
369 self.interactor.Render() 369 self.interactor.Render()
370 370
371 - def OnSensors(self, probe_id, ref_id, obj_id=0): 371 + def OnSensors(self, markers_flag):
  372 + probe_id, ref_id, obj_id = markers_flag
  373 +
372 if not self.probe: 374 if not self.probe:
373 self.CreateSensorID() 375 self.CreateSensorID()
374 376
invesalius/gui/dialogs.py
@@ -3648,8 +3648,7 @@ class ICPCorregistrationDialog(wx.Dialog): @@ -3648,8 +3648,7 @@ class ICPCorregistrationDialog(wx.Dialog):
3648 import invesalius.project as prj 3648 import invesalius.project as prj
3649 3649
3650 self.m_change = nav_prop[0] 3650 self.m_change = nav_prop[0]
3651 - self.tracker_id = nav_prop[1]  
3652 - self.trk_init = nav_prop[2] 3651 + self.tracker = nav_prop[1]
3653 self.obj_ref_id = 2 3652 self.obj_ref_id = 2
3654 self.obj_name = None 3653 self.obj_name = None
3655 self.obj_actor = None 3654 self.obj_actor = None
@@ -3805,7 +3804,7 @@ class ICPCorregistrationDialog(wx.Dialog): @@ -3805,7 +3804,7 @@ class ICPCorregistrationDialog(wx.Dialog):
3805 self.interactor.Render() 3804 self.interactor.Render()
3806 3805
3807 def GetCurrentCoord(self): 3806 def GetCurrentCoord(self):
3808 - coord_raw = dco.GetCoordinates(self.trk_init, self.tracker_id, const.DYNAMIC_REF) 3807 + coord_raw, markers_flag = self.tracker.TrackerCoordinates.GetCoordinates()
3809 coord, _ = dcr.corregistrate_dynamic((self.m_change, 0), coord_raw, const.DEFAULT_REF_MODE, [None, None]) 3808 coord, _ = dcr.corregistrate_dynamic((self.m_change, 0), coord_raw, const.DEFAULT_REF_MODE, [None, None])
3810 return coord[:3] 3809 return coord[:3]
3811 3810
invesalius/navigation/icp.py
@@ -48,7 +48,7 @@ class ICP(): @@ -48,7 +48,7 @@ class ICP():
48 def OnICP(self, navigation, tracker, m_change): 48 def OnICP(self, navigation, tracker, m_change):
49 ref_mode_id = navigation.GetReferenceMode() 49 ref_mode_id = navigation.GetReferenceMode()
50 50
51 - dialog = dlg.ICPCorregistrationDialog(nav_prop=(m_change, tracker.tracker_id, tracker.trk_init, ref_mode_id)) 51 + dialog = dlg.ICPCorregistrationDialog(nav_prop=(m_change, tracker, ref_mode_id))
52 52
53 if dialog.ShowModal() == wx.ID_OK: 53 if dialog.ShowModal() == wx.ID_OK:
54 m_icp, point_coord, transformed_points, prev_error, final_error = dialog.GetValue() 54 m_icp, point_coord, transformed_points, prev_error, final_error = dialog.GetValue()
invesalius/navigation/navigation.py
@@ -255,7 +255,7 @@ class Navigation(): @@ -255,7 +255,7 @@ class Navigation():
255 coreg_data = [m_change, obj_ref_mode] 255 coreg_data = [m_change, obj_ref_mode]
256 256
257 if self.ref_mode_id: 257 if self.ref_mode_id:
258 - coord_raw = dco.GetCoordinates(tracker.trk_init, tracker.tracker_id, self.ref_mode_id) 258 + coord_raw, markers_flag = tracker.TrackerCoordinates.GetCoordinates()
259 else: 259 else:
260 coord_raw = np.array([None]) 260 coord_raw = np.array([None])
261 261
invesalius/navigation/tracker.py
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #-------------------------------------------------------------------------- 18 #--------------------------------------------------------------------------
19 19
20 import numpy as np 20 import numpy as np
  21 +import threading
21 22
22 import invesalius.constants as const 23 import invesalius.constants as const
23 import invesalius.data.coordinates as dco 24 import invesalius.data.coordinates as dco
@@ -36,6 +37,12 @@ class Tracker(): @@ -36,6 +37,12 @@ class Tracker():
36 37
37 self.tracker_connected = False 38 self.tracker_connected = False
38 39
  40 + self.thread_coord = None
  41 +
  42 + self.event_coord = threading.Event()
  43 +
  44 + self.TrackerCoordinates = dco.TrackerCoordinates()
  45 +
39 def SetTracker(self, new_tracker): 46 def SetTracker(self, new_tracker):
40 if new_tracker: 47 if new_tracker:
41 self.DisconnectTracker() 48 self.DisconnectTracker()
@@ -49,6 +56,9 @@ class Tracker(): @@ -49,6 +56,9 @@ class Tracker():
49 else: 56 else:
50 self.tracker_id = new_tracker 57 self.tracker_id = new_tracker
51 self.tracker_connected = True 58 self.tracker_connected = True
  59 + self.thread_coord = dco.ReceiveCoordinates(self.trk_init, self.tracker_id, self.TrackerCoordinates,
  60 + self.event_coord)
  61 + self.thread_coord.start()
52 62
53 def DisconnectTracker(self): 63 def DisconnectTracker(self):
54 if self.tracker_connected: 64 if self.tracker_connected:
@@ -62,6 +72,11 @@ class Tracker(): @@ -62,6 +72,11 @@ class Tracker():
62 self.tracker_connected = False 72 self.tracker_connected = False
63 self.tracker_id = 0 73 self.tracker_id = 0
64 74
  75 + if self.thread_coord:
  76 + self.event_coord.set()
  77 + self.thread_coord.join()
  78 + self.event_coord.clear()
  79 +
65 Publisher.sendMessage('Update status text in GUI', 80 Publisher.sendMessage('Update status text in GUI',
66 label=_("Tracker disconnected")) 81 label=_("Tracker disconnected"))
67 print("Tracker disconnected!") 82 print("Tracker disconnected!")
@@ -81,7 +96,7 @@ class Tracker(): @@ -81,7 +96,7 @@ class Tracker():
81 coord_samples = {} 96 coord_samples = {}
82 97
83 for i in range(n_samples): 98 for i in range(n_samples):
84 - coord_raw = dco.GetCoordinates(self.trk_init, self.tracker_id, ref_mode_id) 99 + coord_raw, markers_flag = self.TrackerCoordinates.GetCoordinates()
85 100
86 if ref_mode_id == const.DYNAMIC_REF: 101 if ref_mode_id == const.DYNAMIC_REF:
87 coord = dco.dynamic_reference_m(coord_raw[0, :], coord_raw[1, :]) 102 coord = dco.dynamic_reference_m(coord_raw[0, :], coord_raw[1, :])