CustusX  22.04-rc5
An IGT application
cxIgstkTracker.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxIgstkTracker.h"
13 
14 #include <QStringList>
15 #include "cxLogger.h"
16 #include "cxTypeConversions.h"
17 #include "cxToolUsingIGSTK.h"
18 #include "cxIgstkTool.h"
19 #include <time.h>
20 #include "cxSettings.h"
21 
22 namespace cx
23 {
24 
25 IgstkTracker::IgstkTracker(ToolFileParser::TrackerInternalStructure internalStructure) :
26  mInternalStructure(internalStructure),
27  mValid(false),
28  mUid(""),
29  mName(""),
30  mTracker(NULL),
31  mCommunication(CommunicationType::New()),
32  mTrackerObserver(ObserverType::New()),
33  mOpen(false),
34  mInitialized(false),
35  mTracking(false)
36 {
37  mCommunication->SetPortNumber(igstk::SerialCommunication::PortNumber0);
38  mCommunication->SetParity(igstk::SerialCommunication::NoParity);
39  mCommunication->SetBaudRate(igstk::SerialCommunication::BaudRate115200);
40  mCommunication->SetDataBits(igstk::SerialCommunication::DataBits8);
41  mCommunication->SetStopBits(igstk::SerialCommunication::StopBits1);
42  mCommunication->SetHardwareHandshake(igstk::SerialCommunication::HandshakeOff);
43 
44  bool logging = settings()->value("IGSTKDebugLogging", true).toBool();
45  if (logging)
46  {
47  QString comLogging = mInternalStructure.mLoggingFolderName + "RecordedStreamByCustusX.txt";
48  mCommunication->SetCaptureFileName(cstring_cast(comLogging));
49  mCommunication->SetCapture(true);
50  }
51 
52  switch (mInternalStructure.mType)
53  {
54  case tsNONE:
55  mUid = mName = "None";
56  reportError("Tracker is of type TRACKER_NONE, this means it's not valid.");
57  mValid = false;
58  return;
59  break;
60  case tsPOLARIS:
61  mUid = mName = "Polaris";
62  mTempPolarisTracker = PolarisTrackerType::New();
63  mTempPolarisTracker->SetCommunication(mCommunication);
64  report("Tracker is set to Polaris");
65  mTracker = mTempPolarisTracker.GetPointer();
66  mValid = true;
67  break;
68  case tsPOLARIS_CLASSIC:
69  mUid = mName = "None";
70  report("Polaris Classic is not supported");
71  mValid = false;
72  break;
73  //There is no special handling of the tracking system if its spectra or vicra, polaris is polaris as we see it
74  case tsAURORA:
75  mUid = mName = "Aurora";
76  mTempAuroraTracker = AuroraTrackerType::New();
77  mTempAuroraTracker->SetCommunication(mCommunication);
78  report("Tracker is set to Aurora");
79  mTracker = mTempAuroraTracker.GetPointer();
80  mValid = true;
81  break;
82  case tsMICRON:
83  mUid = mName = "Micron";
84  report("Tracker is set to Micron, not supported");
85  //TODO: implement support for a micron tracker...
86  mValid = false;
87  break;
88  default:
89  break;
90  }
91  mTrackerObserver->SetCallbackFunction(this, &IgstkTracker::trackerTransformCallback);
92  mTracker->AddObserver(igstk::IGSTKEvent(), mTrackerObserver);
93  mCommunication->AddObserver(igstk::IGSTKEvent(), mTrackerObserver);
94  this->addLogging();
95 }
96 
98 {
99 }
100 
101 TRACKING_SYSTEM IgstkTracker::getType() const
102 {
103  return mInternalStructure.mType;
104 }
105 
106 QString IgstkTracker::getName() const
107 {
108  return mName;
109 }
110 
111 QString IgstkTracker::getUid() const
112 {
113  return mUid;
114 }
115 
117 {
118  return mTracker;
119 }
120 
122 {
123 // igstk::SerialCommunication::ResultType result = igstk::SerialCommunication::FAILURE;
124 // for(int i=0; i<5; ++i)
125 // {
126 // result = mCommunication->OpenCommunication();
127 // if(result == igstk::SerialCommunication::SUCCESS)
128 // break;
129 // else
130 // reportWarning("Could not open communication.");
131 // }
132  if (mCommunication->OpenCommunication() == false)
133  reportWarning("Could not open communication.");
134  mTracker->RequestOpen();
135 }
136 
138 {
139  mTracker->RequestClose();
140  if (mCommunication->CloseCommunication() == false)
141  reportWarning("Could not close communication.");
142 }
143 
144 void IgstkTracker::attachTools(std::map<QString, IgstkToolPtr> tools)
145 {
146  if (!this->isInitialized())
147  return;
148 
149  for (std::map<QString, IgstkToolPtr>::iterator it = tools.begin(); it != tools.end(); ++it)
150  {
151  IgstkToolPtr tool = it->second;
152 
153  if (tool && tool->getPointer())
154  {
155  if (tool->getTrackerType() != mInternalStructure.mType)
157  "Tracker is attaching a tool that is not of the correct type. Trackers type: "
158  + qstring_cast(mInternalStructure.mType) + ", tools tracker type: "
159  + qstring_cast(tool->getTrackerType()));
160 
161  tool->getPointer()->RequestAttachToTracker(mTracker);
162 
163  if (tool->isReference())
164  mTracker->RequestSetReferenceTool(tool->getPointer());
165 // if(tool->getType() == Tool::TOOL_REFERENCE)
166 // mTracker->RequestSetReferenceTool(tool->getPointer());
167  }
168  }
169 }
170 
171 void IgstkTracker::detachTools(std::map<QString, IgstkToolPtr> tools)
172 {
173  if (!this->isInitialized())
174  return;
175 
176  for (std::map<QString, IgstkToolPtr>::iterator it = tools.begin(); it != tools.end(); ++it)
177  {
178  IgstkToolPtr tool = it->second;
179 
180  if (tool && tool->getPointer())
181  {
182  tool->getPointer()->RequestDetachFromTracker();
183  }
184  }
185 }
186 
188 {
189  mTracker->RequestStartTracking();
190 }
191 
193 {
194  mTracker->RequestStopTracking();
195 }
196 
198 {
199  return mValid;
200 }
201 
203 {
204  return mOpen;
205 }
206 
208 {
209  return mInitialized;
210 }
211 
213 {
214  return mTracking;
215 }
216 
217 void IgstkTracker::trackerTransformCallback(const itk::EventObject &event)
218 {
219  //successes
220  if (igstk::TrackerOpenEvent().CheckEvent(&event))
221  {
222  this->internalOpen(true);
223  this->internalInitialized(true);
224  }
225  else if (igstk::TrackerCloseEvent().CheckEvent(&event))
226  {
227  this->internalOpen(false);
228  this->internalInitialized(false);
229  }
230  else if (igstk::TrackerInitializeEvent().CheckEvent(&event))
231  {
232  //Never happens???
233  //this->internalInitialized(true);
234  //report(mUid+" is initialized.");
235  reportWarning("This never happens for some reason... check code");
236  }
237  else if (igstk::TrackerStartTrackingEvent().CheckEvent(&event))
238  {
239  this->internalTracking(true);
240  }
241  else if (igstk::TrackerStopTrackingEvent().CheckEvent(&event))
242  {
243  this->internalTracking(false);
244  }
245  else if (igstk::TrackerUpdateStatusEvent().CheckEvent(&event))
246  {
247  //reportDebug(mUid+" is updated."); //SPAM!
248  }
249  else if (igstk::TrackerToolTransformUpdateEvent().CheckEvent(&event))
250  {
251  //reportDebug(mUid+" has updated a transform."); //SPAM
252  }
253  //communication success
254  else if (igstk::CompletedEvent().CheckEvent(&event))
255  {
256  // this seems to appear after every transmit (several times/second)
257  //report(mUid+" set up communication correctly."); //SPAM
258  }
259  //coordinate system success
260  else if (igstk::CoordinateSystemSetTransformEvent().CheckEvent(&event))
261  {
262  //report();
263  }
264  //failures
265  else if (igstk::InvalidRequestErrorEvent().CheckEvent(&event))
266  {
267  reportWarning(mUid + " received an invalid request. This means that the internal igstk tracker did not accept the request. Do not know which request.");
268  this->shutdown();
269  }
270  else if (igstk::TrackerOpenErrorEvent().CheckEvent(&event))
271  {
272  reportError(mUid + " could not open.");
273  //this->shutdown();
274  }
275  else if (igstk::TrackerCloseErrorEvent().CheckEvent(&event))
276  {
277  reportError(mUid + " could not close.");
278  //this->shutdown();
279  }
280  else if (igstk::TrackerInitializeErrorEvent().CheckEvent(&event))
281  {
282  reportError(mUid + " could not initialize.");
283  //this->shutdown();
284  }
285  else if (igstk::TrackerStartTrackingErrorEvent().CheckEvent(&event))
286  {
287  reportError(mUid + " could not start tracking.");
288  //this->shutdown();
289  }
290  else if (igstk::TrackerStopTrackingErrorEvent().CheckEvent(&event))
291  {
292  reportError(mUid + " could not stop tracking.");
293  //this->shutdown();
294  }
295  else if (igstk::TrackerUpdateStatusErrorEvent().CheckEvent(&event))
296  {
297  reportError(mUid + " could not update.");
298  //this->shutdown();
299  }
300  //communication failure
301  else if (igstk::InputOutputErrorEvent().CheckEvent(&event))
302  {
303  //this happens when you pull out the cable while tracking
304  reportError(mUid + " cannot communicate with input/output.");
305  this->shutdown();
306  }
307  else if (igstk::InputOutputTimeoutEvent().CheckEvent(&event))
308  {
309  reportError(mUid + " input/output communication timed out.");
310  //this->shutdown();
311  }
312  else if (igstk::OpenPortErrorEvent().CheckEvent(&event))
313  {
314  reportError(mUid + " could not open communication with tracker.");
315  this->shutdown();
316  }
317  else if (igstk::ClosePortErrorEvent().CheckEvent(&event))
318  {
319  reportError(mUid + " could not close communication with tracker.");
320  this->shutdown();
321  }
322  else
323  {
324  event.Print(std::cout);
325  }
326 }
327 
329 {
330  bool logging = settings()->value("IGSTKDebugLogging", true).toBool();
331  if (logging)
332  {
333  std::ofstream* loggerFile = new std::ofstream();
334  QString logFile = mInternalStructure.mLoggingFolderName + "Tracker_Logging.txt";
335  loggerFile->open(cstring_cast(logFile));
336  mTrackerLogger = igstk::Logger::New();
337  mTrackerLogOutput = itk::StdStreamLogOutput::New();
338  mTrackerLogOutput->SetStream(*loggerFile);
339  mTrackerLogger->AddLogOutput(mTrackerLogOutput);
340  mTrackerLogger->SetPriorityLevel(itk::Logger::DEBUG);
341 
342  mTracker->SetLogger(mTrackerLogger);
343  mCommunication->SetLogger(mTrackerLogger);
344  }
345 }
346 
348 {
349  if (mOpen == value)
350  return;
351  mOpen = value;
352 
353  report(mUid + " is " + (value ? "open" : "closed") + ".");
354  emit open(mOpen);
355 }
356 
358 {
359  if (mInitialized == value)
360  return;
361  mInitialized = value;
362 
363  report(mUid + " is " + (value ? "" : "un") + "initialized.");
365 }
366 
368 {
369  if (mTracking == value)
370  return;
371  mTracking = value;
372 
373  report(mUid + " is " + (value ? "" : "not ") + "tracking.");
374  emit tracking(mTracking);
375 }
376 
378 {
379  reportWarning(mUid + " experienced a unrecoverable error, reconfiguration is required.");
380  emit error();
381 }
382 
384 {
385  mCommunication->CloseCommunication();
386 
387  //because the tracker now is closed we don't get the callback events so we need to reset the trackers internal
388  //status manually
389  this->internalTracking(false);
390  this->internalInitialized(false);
391  this->internalOpen(false);
392  this->internalError(true);
393 }
394 
395 } //namespace cx
QString qstring_cast(const T &val)
void internalError(bool value)
tsPOLARIS_CLASSIC
NDIs Polaris Classic tracker.
bool mTracking
whether or not the tracker is tracking
QString mLoggingFolderName
path to where log should be saved
void reportError(QString msg)
Definition: cxLogger.cpp:71
tsNONE
Not specified.
igstk::SerialCommunicationForPosix CommunicationType
tsPOLARIS
NDIs Polaris tracker.
PolarisTrackerType::Pointer mTempPolarisTracker
pointer to a temp polaris tracker
bool mValid
whether this tracker is constructed correctly or not
ObserverType::Pointer mTrackerObserver
observer listening for igstk events
bool isInitialized() const
boost::shared_ptr< class IgstkTool > IgstkToolPtr
TRACKING_SYSTEM mType
the trackers type
void detachTools(std::map< QString, IgstkToolPtr > tools)
detach the list of tools from the tracker hw
cstring_cast_Placeholder cstring_cast(const T &val)
void trackerTransformCallback(const itk::EventObject &eventVar)
callback receiving events from the observer
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: cxSettings.cpp:66
void startTracking()
start tracking
void initialized(bool)
void open()
open the tracker for communication
bool mOpen
whether or not the tracker is open
TrackerType * mTracker
pointer to the base class of the internal igstk tracker
void close()
close the
QString mUid
the trackers unique id
void internalTracking(bool value)
igstk::Tracker TrackerType
itk::ReceptorMemberCommand< IgstkTracker > ObserverType
bool isOpen() const
void reportWarning(QString msg)
Definition: cxLogger.cpp:70
void shutdown()
shuts down the tracker, made to be used when an unrecoverable error occures
CommunicationType::Pointer mCommunication
pointer to the serial communication used to communicate with the NDI trackers
igstk::Logger::Pointer mTrackerLogger
logging the internal igstk behavior
bool isValid() const
whether this tracker is constructed correctly or not
TRACKING_SYSTEM getType() const
returns the trackers type
Settings * settings()
Shortcut for accessing the settings instance.
Definition: cxSettings.cpp:21
bool mInitialized
whether or not the tracker is initialized
TrackerType * getPointer() const
return a pointer to the internal tracker base
void internalOpen(bool value)
QString getUid() const
get the tracker unique id
QString getName() const
get the trackers name
tsAURORA
NDIs Aurora tracker.
void internalInitialized(bool value)
void report(QString msg)
Definition: cxLogger.cpp:69
void attachTools(std::map< QString, IgstkToolPtr > tools)
attach a list of tools to the tracker hw
void addLogging()
adds logging to the internal igstk components
AuroraTrackerType::Pointer mTempAuroraTracker
pointer to a temp aurora tracker
ToolFileParser::TrackerInternalStructure mInternalStructure
the trackers type
itk::StdStreamLogOutput::Pointer mTrackerLogOutput
output to write the log to
QString mName
the trackers name
tsMICRON
Claron Technologys Micron tracker.
bool isTracking() const
void stopTracking()
stop tracking
void tracking(bool)
Namespace for all CustusX production code.