MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkVirtualTrackingDevice.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12
14#include "mitkIGTTimeStamp.h"
15#include "mitkIGTException.h"
16
17#include <cstdlib>
18#include <cstdio>
19#include <ctime>
20#include <itksys/SystemTools.hxx>
21#include <random>
22
24
26m_AllTools(), m_RefreshRate(100), m_NumberOfControlPoints(20), m_GaussianNoiseEnabled(false),
27m_MeanDistributionParam(0.0), m_DeviationDistributionParam(1.0)
28{
30 m_Bounds[0] = m_Bounds[2] = m_Bounds[4] = -400.0; // initialize bounds to -400 ... +400 (mm) cube
31 m_Bounds[1] = m_Bounds[3] = m_Bounds[5] = 400.0;
32}
33
35{
36 if (this->GetState() == Tracking)
37 {
38 this->StopTracking();
39 }
40 if (this->GetState() == Ready)
41 {
42 this->CloseConnection();
43 }
44 /* cleanup tracking thread */
45 if (m_Thread.joinable())
46 m_Thread.join();
47
48 m_AllTools.clear();
49}
50
52{
53 //if (this->GetState() == Tracking)
54 //{
55 // return nullptr;
56 //}
57 mitk::VirtualTrackingTool::Pointer t = mitk::VirtualTrackingTool::New();
58 t->SetToolName(toolName);
59 t->SetVelocity(0.1);
60 this->InitializeSpline(t);
61 std::lock_guard<std::mutex> lock(m_ToolsMutex); // lock and unlock the mutex
62 m_AllTools.push_back(t);
63 return t;
64}
65
66
68{
69 if (this->GetState() != Ready)
70 return false;
71 this->SetState(Tracking); // go to mode Tracking
72 this->m_StopTrackingMutex.lock();
73 this->m_StopTracking = false;
74 this->m_StopTrackingMutex.unlock();
75
77
78 if (m_Thread.joinable())
79 m_Thread.detach();
80
81 m_Thread = std::thread(&VirtualTrackingDevice::ThreadStartTracking, this); // start a new thread that executes the TrackTools() method
82 return true;
83}
84
86{
87 if (this->GetState() == Tracking) // Only if the object is in the correct state
88 {
89 m_StopTrackingMutex.lock(); // m_StopTracking is used by two threads, so we have to ensure correct thread handling
90 m_StopTracking = true;
91 m_StopTrackingMutex.unlock();
92
93 m_TrackingFinishedMutex.lock();
94 this->SetState(Ready);
95 m_TrackingFinishedMutex.unlock();
96 }
97
99
100 return true;
101}
102
104{
105 std::lock_guard<std::mutex> lock(m_ToolsMutex); // lock and unlock the mutex
106 return static_cast<unsigned int>(this->m_AllTools.size());
107}
108
110{
111 std::lock_guard<std::mutex> lock(m_ToolsMutex); // lock and unlock the mutex
112 if (toolNumber < m_AllTools.size())
113 return this->m_AllTools.at(toolNumber);
114 return nullptr;
115}
116
118{
119 if (m_NumberOfControlPoints < 1)
120 {
121 mitkThrowException(mitk::IGTException) << "to few control points for spline interpolation";
122 }
123 srand(time(nullptr)); //Init random number generator
124
125 this->SetState(Ready);
126 return true;
127}
128
130{
131 if (t == nullptr)
132 return;
133
134 typedef mitk::VirtualTrackingTool::SplineType SplineType;
135 /* create random control points */
136 SplineType::ControlPointListType controlPoints;
137 controlPoints.reserve(m_NumberOfControlPoints + 1);
138
139 controlPoints.push_back(this->GetRandomPoint()); // insert point 0
140 double length = 0.0; // estimate spline length by calculating line segments lengths
141 for (unsigned int i = 1; i < m_NumberOfControlPoints - 1; ++i) // set points 1..n-2
142 {
143 SplineType::ControlPointType pos;
144 pos = this->GetRandomPoint();
145 length += controlPoints.at(i - 1).EuclideanDistanceTo(pos);
146 controlPoints.push_back(pos);
147 }
148 controlPoints.push_back(controlPoints.at(0)); // close spline --> insert point last control point with same value as first control point
149 length += controlPoints.at(controlPoints.size() - 2).EuclideanDistanceTo(controlPoints.at(controlPoints.size() - 1));
150
151 /* Create knot list. TODO: rethink knot list values and list size. Is there a better solution? */
152 SplineType::KnotListType knotList;
153 knotList.push_back(0.0);
154 for (unsigned int i = 1; i < controlPoints.size() + t->GetSpline()->GetSplineOrder() + 1; ++i)
155 knotList.push_back(i);
156 knotList.push_back(controlPoints.size() + t->GetSpline()->GetSplineOrder() + 1);
157
158 t->GetSpline()->SetControlPoints(controlPoints);
159 t->GetSpline()->SetKnots(knotList);
160 t->SetSplineLength(length);
161}
162
164{
165 bool returnValue = true;
166 if (this->GetState() == Setup)
167 return true;
168
169 this->SetState(Setup);
170 return returnValue;
171}
172
174{
175 mitk::VirtualTrackingTool* t = this->GetInternalTool(idx);
176 if (t != nullptr)
177 return t->GetSplineLength();
178 else
179 throw std::invalid_argument("invalid index");
180}
181
182void mitk::VirtualTrackingDevice::SetToolSpeed(unsigned int idx, mitk::ScalarType roundsPerSecond)
183{
184 if (roundsPerSecond < 0.0001)
185 throw std::invalid_argument("Minimum tool speed is 0.0001 rounds per second");
186
187 mitk::VirtualTrackingTool* t = this->GetInternalTool(idx);
188 if (t != nullptr)
189 t->SetVelocity(roundsPerSecond);
190 else
191 throw std::invalid_argument("invalid index");
192}
193
195{
196 std::lock_guard<std::mutex> toolsMutexLockHolder(m_ToolsMutex); // lock and unlock the mutex
197 if (idx < m_AllTools.size())
198 return m_AllTools.at(idx);
199 else
200 return nullptr;
201}
202
204{
205 /* lock the TrackingFinishedMutex to signal that the execution rights are now transfered to the tracking thread */
206 std::lock_guard<std::mutex> trackingFinishedLockHolder(m_TrackingFinishedMutex); // keep lock until end of scope
207
208 if (this->GetState() != Tracking)
209 return;
210
211 bool localStopTracking; // Because m_StopTracking is used by two threads, access has to be guarded by a mutex. To minimize thread locking, a local copy is used here
212
213 this->m_StopTrackingMutex.lock(); // update the local copy of m_StopTracking
214 localStopTracking = this->m_StopTracking;
215 this->m_StopTrackingMutex.unlock();
216
217 mitk::ScalarType t = 0.0;
218 while ((this->GetState() == Tracking) && (localStopTracking == false))
219 {
220 //for (ToolContainer::iterator itAllTools = m_AllTools.begin(); itAllTools != m_AllTools.end(); itAllTools++)
221 for (unsigned int i = 0; i < this->GetToolCount(); ++i) // use mutexed methods to access tool container
222 {
223 mitk::VirtualTrackingTool::Pointer currentTool = this->GetInternalTool(i);
224 mitk::VirtualTrackingTool::SplineType::PointType pos;
225 /* calculate tool position with spline interpolation */
226 pos = currentTool->GetSpline()->EvaluateSpline(t);
227 mitk::Point3D mp;
228 mitk::itk2vtk(pos, mp); // convert from SplineType::PointType to mitk::Point3D
229
230 //Add Gaussian Noise to Tracking Coordinates if enabled
231 if (this->m_GaussianNoiseEnabled)
232 {
233 std::random_device rd;
234 std::mt19937 generator(rd());
235 std::normal_distribution<double> dist(this->m_MeanDistributionParam, this->m_DeviationDistributionParam);
236 double noise = dist(generator);
237 mp = mp + mitk::Vector(noise);
238 }
239
240 currentTool->SetPosition(mp);
241 // Currently, a constant speed is used. TODO: use tool velocity setting
242 t += 0.001;
243 if (t >= 1.0)
244 t = 0.0;
245
246 mitk::Quaternion quat;
247 /* fix quaternion rotation */
248 quat.x() = 0.0;
249 quat.y() = 0.0;
250 quat.z() = 0.0;
251 quat.r() = 1.0;
252 quat.normalize();
253 currentTool->SetOrientation(quat);
254 // TODO: rotate once per cycle around a fixed rotation vector
255
256 currentTool->SetTrackingError(2 * (rand() / (RAND_MAX + 1.0))); // tracking error in 0 .. 2 Range
257 currentTool->SetDataValid(true);
258 currentTool->Modified();
259 }
260 itksys::SystemTools::Delay(m_RefreshRate);
261 /* Update the local copy of m_StopTracking */
262 this->m_StopTrackingMutex.lock();
263 localStopTracking = m_StopTracking;
264 this->m_StopTrackingMutex.unlock();
265 } // tracking ends if we pass this line
266}
267
269{
270 this->TrackTools();
271}
272
274{
276 pos[0] = m_Bounds[0] + (m_Bounds[1] - m_Bounds[0]) * (rand() / (RAND_MAX + 1.0)); // X = xMin + xRange * (random number between 0 and 1)
277 pos[1] = m_Bounds[2] + (m_Bounds[3] - m_Bounds[2]) * (rand() / (RAND_MAX + 1.0)); // Y
278 pos[2] = m_Bounds[4] + (m_Bounds[5] - m_Bounds[4]) * (rand() / (RAND_MAX + 1.0)); // Z
279
280 return pos;
281}
282
284{
285 this->m_GaussianNoiseEnabled = true;
286}
287
289{
290 this->m_GaussianNoiseEnabled = false;
291}
292
293void mitk::VirtualTrackingDevice::SetParamsForGaussianNoise(double meanDistribution, double deviationDistribution)
294{
295 this->m_MeanDistributionParam = meanDistribution;
296 this->m_DeviationDistributionParam = deviationDistribution;
297}
298
300{
301 return m_DeviationDistributionParam;
302}
303
305{
306 return m_MeanDistributionParam;
307}
An object of this class represents an exception of the MITK-IGT module.
static IGTTimeStamp * GetInstance()
returns a pointer to the current instance of mitkTimeStamp
void Start(itk::Object::Pointer device)
starts the time-acquisition
void Stop(itk::Object::Pointer device)
stops the time-acqusition
Interface for all Tracking Devices.
TrackingDeviceData m_Data
current device Data
Interface for all Tracking Tools.
mitk::VirtualTrackingTool * GetInternalTool(unsigned int idx)
double GetDeviationDistribution()
returns the deviation distribution for the Gaussian Noise
void InitializeSpline(mitk::VirtualTrackingTool *t)
initializes the spline path of the tool t with random control points inside the current tracking volu...
bool StartTracking() override
Starts the tracking.
void SetToolSpeed(unsigned int idx, mitk::ScalarType roundsPerSecond)
sets the speed of the tool idx in rounds per second
void DisableGaussianNoise()
disable addition of Gaussian Noise to Trackin coordinates
mitk::ScalarType m_Bounds[6]
bounding box of the tracking volume stored as {xMin, xMax, yMin, yMax, zMin, zMax}
TrackingTool * GetTool(unsigned int toolNumber) const override
void TrackTools()
This method tracks tools as long as the variable m_Mode is set to "Tracking". Tracking tools means ge...
mitk::VirtualTrackingTool::SplineType::ControlPointType ControlPointType
void ThreadStartTracking()
static start method for tracking thread
bool CloseConnection() override
Closes the connection and clears all resources.
ControlPointType GetRandomPoint()
returns a random position inside the tracking volume (defined by m_Bounds)
mitk::ScalarType GetSplineChordLength(unsigned int idx)
return the approximate length of the spline for tool with index idx in millimeter
double GetMeanDistribution()
returns the mean distribution for the Gaussian Noise
void EnableGaussianNoise()
enable addition of Gaussian Noise to tracking coordinates
unsigned int GetToolCount() const override
void SetParamsForGaussianNoise(double meanDistribution, double deviationDistribution)
sets the mean distribution and the standard deviation for the Gaussian Noise
bool StopTracking() override
Stops the tracking.
bool OpenConnection() override
Opens the connection to the device. This have to be done before the tracking is started.
TrackingTool * AddTool(const char *toolName)
Adds a tool to the tracking device.
implements TrackingTool interface
IGT Exceptions.