Fraxinus  18.10
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 "cxEnumConverter.h"
18 #include "cxToolUsingIGSTK.h"
19 #include "cxIgstkTool.h"
20 #include <time.h>
21 #include "cxSettings.h"
22 
23 namespace cx
24 {
25 
26 IgstkTracker::IgstkTracker(ToolFileParser::TrackerInternalStructure internalStructure) :
27  mInternalStructure(internalStructure),
28  mValid(false),
29  mUid(""),
30  mName(""),
31  mTracker(NULL),
32  mCommunication(CommunicationType::New()),
33  mTrackerObserver(ObserverType::New()),
34  mOpen(false),
35  mInitialized(false),
36  mTracking(false)
37 {
38  mCommunication->SetPortNumber(igstk::SerialCommunication::PortNumber0);
39  mCommunication->SetParity(igstk::SerialCommunication::NoParity);
40  mCommunication->SetBaudRate(igstk::SerialCommunication::BaudRate115200);
41  mCommunication->SetDataBits(igstk::SerialCommunication::DataBits8);
42  mCommunication->SetStopBits(igstk::SerialCommunication::StopBits1);
43  mCommunication->SetHardwareHandshake(igstk::SerialCommunication::HandshakeOff);
44 
45  bool logging = settings()->value("IGSTKDebugLogging", true).toBool();
46  if (logging)
47  {
48  QString comLogging = mInternalStructure.mLoggingFolderName + "RecordedStreamByCustusX.txt";
49  mCommunication->SetCaptureFileName(cstring_cast(comLogging));
50  mCommunication->SetCapture(true);
51  }
52 
53  switch (mInternalStructure.mType)
54  {
55  case tsNONE:
56  mUid = mName = "None";
57  reportError("Tracker is of type TRACKER_NONE, this means it's not valid.");
58  mValid = false;
59  return;
60  break;
61  case tsPOLARIS:
62  mUid = mName = "Polaris";
63  mTempPolarisTracker = PolarisTrackerType::New();
64  mTempPolarisTracker->SetCommunication(mCommunication);
65  report("Tracker is set to Polaris");
66  mTracker = mTempPolarisTracker.GetPointer();
67  mValid = true;
68  break;
69  case tsPOLARIS_CLASSIC:
70  mUid = mName = "None";
71  report("Polaris Classic is not supported");
72  mValid = false;
73  break;
74  //There is no special handling of the tracking system if its spectra or vicra, polaris is polaris as we see it
75  case tsAURORA:
76  mUid = mName = "Aurora";
77  mTempAuroraTracker = AuroraTrackerType::New();
78  mTempAuroraTracker->SetCommunication(mCommunication);
79  report("Tracker is set to Aurora");
80  mTracker = mTempAuroraTracker.GetPointer();
81  mValid = true;
82  break;
83  case tsMICRON:
84  mUid = mName = "Micron";
85  report("Tracker is set to Micron, not supported");
86  //TODO: implement support for a micron tracker...
87  mValid = false;
88  break;
89  default:
90  break;
91  }
92  mTrackerObserver->SetCallbackFunction(this, &IgstkTracker::trackerTransformCallback);
93  mTracker->AddObserver(igstk::IGSTKEvent(), mTrackerObserver);
94  mCommunication->AddObserver(igstk::IGSTKEvent(), mTrackerObserver);
95  this->addLogging();
96 }
97 
99 {
100 }
101 
102 TRACKING_SYSTEM IgstkTracker::getType() const
103 {
104  return mInternalStructure.mType;
105 }
106 
107 QString IgstkTracker::getName() const
108 {
109  return mName;
110 }
111 
112 QString IgstkTracker::getUid() const
113 {
114  return mUid;
115 }
116 
118 {
119  return mTracker;
120 }
121 
123 {
124 // igstk::SerialCommunication::ResultType result = igstk::SerialCommunication::FAILURE;
125 // for(int i=0; i<5; ++i)
126 // {
127 // result = mCommunication->OpenCommunication();
128 // if(result == igstk::SerialCommunication::SUCCESS)
129 // break;
130 // else
131 // reportWarning("Could not open communication.");
132 // }
133  if (mCommunication->OpenCommunication() == false)
134  reportWarning("Could not open communication.");
135  mTracker->RequestOpen();
136 }
137 
139 {
140  mTracker->RequestClose();
141  if (mCommunication->CloseCommunication() == false)
142  reportWarning("Could not close communication.");
143 }
144 
145 void IgstkTracker::attachTools(std::map<QString, IgstkToolPtr> tools)
146 {
147  if (!this->isInitialized())
148  return;
149 
150  for (std::map<QString, IgstkToolPtr>::iterator it = tools.begin(); it != tools.end(); ++it)
151  {
152  IgstkToolPtr tool = it->second;
153 
154  if (tool && tool->getPointer())
155  {
156  if (tool->getTrackerType() != mInternalStructure.mType)
158  "Tracker is attaching a tool that is not of the correct type. Trackers type: "
159  + qstring_cast(mInternalStructure.mType) + ", tools tracker type: "
160  + qstring_cast(tool->getTrackerType()));
161 
162  tool->getPointer()->RequestAttachToTracker(mTracker);
163 
164  if (tool->isReference())
165  mTracker->RequestSetReferenceTool(tool->getPointer());
166 // if(tool->getType() == Tool::TOOL_REFERENCE)
167 // mTracker->RequestSetReferenceTool(tool->getPointer());
168  }
169  }
170 }
171 
172 void IgstkTracker::detachTools(std::map<QString, IgstkToolPtr> tools)
173 {
174  if (!this->isInitialized())
175  return;
176 
177  for (std::map<QString, IgstkToolPtr>::iterator it = tools.begin(); it != tools.end(); ++it)
178  {
179  IgstkToolPtr tool = it->second;
180 
181  if (tool && tool->getPointer())
182  {
183  tool->getPointer()->RequestDetachFromTracker();
184  }
185  }
186 }
187 
189 {
190  mTracker->RequestStartTracking();
191 }
192 
194 {
195  mTracker->RequestStopTracking();
196 }
197 
199 {
200  return mValid;
201 }
202 
204 {
205  return mOpen;
206 }
207 
209 {
210  return mInitialized;
211 }
212 
214 {
215  return mTracking;
216 }
217 
218 void IgstkTracker::trackerTransformCallback(const itk::EventObject &event)
219 {
220  //successes
221  if (igstk::TrackerOpenEvent().CheckEvent(&event))
222  {
223  this->internalOpen(true);
224  this->internalInitialized(true);
225  }
226  else if (igstk::TrackerCloseEvent().CheckEvent(&event))
227  {
228  this->internalOpen(false);
229  this->internalInitialized(false);
230  }
231  else if (igstk::TrackerInitializeEvent().CheckEvent(&event))
232  {
233  //Never happens???
234  //this->internalInitialized(true);
235  //report(mUid+" is initialized.");
236  reportWarning("This never happens for some reason... check code");
237  }
238  else if (igstk::TrackerStartTrackingEvent().CheckEvent(&event))
239  {
240  this->internalTracking(true);
241  }
242  else if (igstk::TrackerStopTrackingEvent().CheckEvent(&event))
243  {
244  this->internalTracking(false);
245  }
246  else if (igstk::TrackerUpdateStatusEvent().CheckEvent(&event))
247  {
248  //reportDebug(mUid+" is updated."); //SPAM!
249  }
250  else if (igstk::TrackerToolTransformUpdateEvent().CheckEvent(&event))
251  {
252  //reportDebug(mUid+" has updated a transform."); //SPAM
253  }
254  //communication success
255  else if (igstk::CompletedEvent().CheckEvent(&event))
256  {
257  // this seems to appear after every transmit (several times/second)
258  //report(mUid+" set up communication correctly."); //SPAM
259  }
260  //coordinate system success
261  else if (igstk::CoordinateSystemSetTransformEvent().CheckEvent(&event))
262  {
263  //report();
264  }
265  //failures
266  else if (igstk::InvalidRequestErrorEvent().CheckEvent(&event))
267  {
268  reportWarning(mUid + " received an invalid request. This means that the internal igstk tracker did not accept the request. Do not know which request.");
269  this->shutdown();
270  }
271  else if (igstk::TrackerOpenErrorEvent().CheckEvent(&event))
272  {
273  reportError(mUid + " could not open.");
274  //this->shutdown();
275  }
276  else if (igstk::TrackerCloseErrorEvent().CheckEvent(&event))
277  {
278  reportError(mUid + " could not close.");
279  //this->shutdown();
280  }
281  else if (igstk::TrackerInitializeErrorEvent().CheckEvent(&event))
282  {
283  reportError(mUid + " could not initialize.");
284  //this->shutdown();
285  }
286  else if (igstk::TrackerStartTrackingErrorEvent().CheckEvent(&event))
287  {
288  reportError(mUid + " could not start tracking.");
289  //this->shutdown();
290  }
291  else if (igstk::TrackerStopTrackingErrorEvent().CheckEvent(&event))
292  {
293  reportError(mUid + " could not stop tracking.");
294  //this->shutdown();
295  }
296  else if (igstk::TrackerUpdateStatusErrorEvent().CheckEvent(&event))
297  {
298  reportError(mUid + " could not update.");
299  //this->shutdown();
300  }
301  //communication failure
302  else if (igstk::InputOutputErrorEvent().CheckEvent(&event))
303  {
304  //this happens when you pull out the cable while tracking
305  reportError(mUid + " cannot communicate with input/output.");
306  this->shutdown();
307  }
308  else if (igstk::InputOutputTimeoutEvent().CheckEvent(&event))
309  {
310  reportError(mUid + " input/output communication timed out.");
311  //this->shutdown();
312  }
313  else if (igstk::OpenPortErrorEvent().CheckEvent(&event))
314  {
315  reportError(mUid + " could not open communication with tracker.");
316  this->shutdown();
317  }
318  else if (igstk::ClosePortErrorEvent().CheckEvent(&event))
319  {
320  reportError(mUid + " could not close communication with tracker.");
321  this->shutdown();
322  }
323  else
324  {
325  event.Print(std::cout);
326  }
327 }
328 
330 {
331  bool logging = settings()->value("IGSTKDebugLogging", true).toBool();
332  if (logging)
333  {
334  std::ofstream* loggerFile = new std::ofstream();
335  QString logFile = mInternalStructure.mLoggingFolderName + "Tracker_Logging.txt";
336  loggerFile->open(cstring_cast(logFile));
337  mTrackerLogger = igstk::Logger::New();
338  mTrackerLogOutput = itk::StdStreamLogOutput::New();
339  mTrackerLogOutput->SetStream(*loggerFile);
340  mTrackerLogger->AddLogOutput(mTrackerLogOutput);
341  mTrackerLogger->SetPriorityLevel(itk::Logger::DEBUG);
342 
343  mTracker->SetLogger(mTrackerLogger);
344  mCommunication->SetLogger(mTrackerLogger);
345  }
346 }
347 
349 {
350  if (mOpen == value)
351  return;
352  mOpen = value;
353 
354  report(mUid + " is " + (value ? "open" : "closed") + ".");
355  emit open(mOpen);
356 }
357 
359 {
360  if (mInitialized == value)
361  return;
362  mInitialized = value;
363 
364  report(mUid + " is " + (value ? "" : "un") + "initialized.");
366 }
367 
369 {
370  if (mTracking == value)
371  return;
372  mTracking = value;
373 
374  report(mUid + " is " + (value ? "" : "not ") + "tracking.");
375  emit tracking(mTracking);
376 }
377 
379 {
380  reportWarning(mUid + " experienced a unrecoverable error, reconfiguration is required.");
381  emit error();
382 }
383 
385 {
386  mCommunication->CloseCommunication();
387 
388  //because the tracker now is closed we don't get the callback events so we need to reset the trackers internal
389  //status manually
390  this->internalTracking(false);
391  this->internalInitialized(false);
392  this->internalOpen(false);
393  this->internalError(true);
394 }
395 
396 } //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.