CustusX  16.5
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 #include "cxIgstkTracker.h"
34 
35 #include <QStringList>
36 #include "cxLogger.h"
37 #include "cxTypeConversions.h"
38 #include "cxEnumConverter.h"
39 #include "cxToolUsingIGSTK.h"
40 #include "cxIgstkTool.h"
41 #include <time.h>
42 #include "cxSettings.h"
43 
44 namespace cx
45 {
46 
47 IgstkTracker::IgstkTracker(ToolFileParser::TrackerInternalStructure internalStructure) :
48  mInternalStructure(internalStructure),
49  mValid(false),
50  mUid(""),
51  mName(""),
52  mTracker(NULL),
53  mCommunication(CommunicationType::New()),
54  mTrackerObserver(ObserverType::New()),
55  mOpen(false),
56  mInitialized(false),
57  mTracking(false)
58 {
59  mCommunication->SetPortNumber(igstk::SerialCommunication::PortNumber0);
60  mCommunication->SetParity(igstk::SerialCommunication::NoParity);
61  mCommunication->SetBaudRate(igstk::SerialCommunication::BaudRate115200);
62  mCommunication->SetDataBits(igstk::SerialCommunication::DataBits8);
63  mCommunication->SetStopBits(igstk::SerialCommunication::StopBits1);
64  mCommunication->SetHardwareHandshake(igstk::SerialCommunication::HandshakeOff);
65 
66  bool logging = settings()->value("IGSTKDebugLogging", true).toBool();
67  if (logging)
68  {
69  QString comLogging = mInternalStructure.mLoggingFolderName + "RecordedStreamByCustusX.txt";
70  mCommunication->SetCaptureFileName(cstring_cast(comLogging));
71  mCommunication->SetCapture(true);
72  }
73 
74  switch (mInternalStructure.mType)
75  {
76  case tsNONE:
77  mUid = mName = "None";
78  reportError("Tracker is of type TRACKER_NONE, this means it's not valid.");
79  mValid = false;
80  return;
81  break;
82  case tsPOLARIS:
83  mUid = mName = "Polaris";
84  mTempPolarisTracker = PolarisTrackerType::New();
85  mTempPolarisTracker->SetCommunication(mCommunication);
86  report("Tracker is set to Polaris");
87  mTracker = mTempPolarisTracker.GetPointer();
88  mValid = true;
89  break;
90  case tsPOLARIS_CLASSIC:
91  mUid = mName = "None";
92  report("Polaris Classic is not supported");
93  mValid = false;
94  break;
95  //There is no special handling of the tracking system if its spectra or vicra, polaris is polaris as we see it
96  case tsAURORA:
97  mUid = mName = "Aurora";
98  mTempAuroraTracker = AuroraTrackerType::New();
99  mTempAuroraTracker->SetCommunication(mCommunication);
100  report("Tracker is set to Aurora");
101  mTracker = mTempAuroraTracker.GetPointer();
102  mValid = true;
103  break;
104  case tsMICRON:
105  mUid = mName = "Micron";
106  report("Tracker is set to Micron, not supported");
107  //TODO: implement support for a micron tracker...
108  mValid = false;
109  break;
110  default:
111  break;
112  }
113  mTrackerObserver->SetCallbackFunction(this, &IgstkTracker::trackerTransformCallback);
114  mTracker->AddObserver(igstk::IGSTKEvent(), mTrackerObserver);
115  mCommunication->AddObserver(igstk::IGSTKEvent(), mTrackerObserver);
116  this->addLogging();
117 }
118 
120 {
121 }
122 
123 TRACKING_SYSTEM IgstkTracker::getType() const
124 {
125  return mInternalStructure.mType;
126 }
127 
128 QString IgstkTracker::getName() const
129 {
130  return mName;
131 }
132 
133 QString IgstkTracker::getUid() const
134 {
135  return mUid;
136 }
137 
139 {
140  return mTracker;
141 }
142 
144 {
145 // igstk::SerialCommunication::ResultType result = igstk::SerialCommunication::FAILURE;
146 // for(int i=0; i<5; ++i)
147 // {
148 // result = mCommunication->OpenCommunication();
149 // if(result == igstk::SerialCommunication::SUCCESS)
150 // break;
151 // else
152 // reportWarning("Could not open communication.");
153 // }
154  if (mCommunication->OpenCommunication() == false)
155  reportWarning("Could not open communication.");
156  mTracker->RequestOpen();
157 }
158 
160 {
161  mTracker->RequestClose();
162  if (mCommunication->CloseCommunication() == false)
163  reportWarning("Could not close communication.");
164 }
165 
166 void IgstkTracker::attachTools(std::map<QString, IgstkToolPtr> tools)
167 {
168  if (!this->isInitialized())
169  return;
170 
171  for (std::map<QString, IgstkToolPtr>::iterator it = tools.begin(); it != tools.end(); ++it)
172  {
173  IgstkToolPtr tool = it->second;
174 
175  if (tool && tool->getPointer())
176  {
177  if (tool->getTrackerType() != mInternalStructure.mType)
179  "Tracker is attaching a tool that is not of the correct type. Trackers type: "
180  + qstring_cast(mInternalStructure.mType) + ", tools tracker type: "
181  + qstring_cast(tool->getTrackerType()));
182 
183  tool->getPointer()->RequestAttachToTracker(mTracker);
184 
185  if (tool->isReference())
186  mTracker->RequestSetReferenceTool(tool->getPointer());
187 // if(tool->getType() == Tool::TOOL_REFERENCE)
188 // mTracker->RequestSetReferenceTool(tool->getPointer());
189  }
190  }
191 }
192 
193 void IgstkTracker::detachTools(std::map<QString, IgstkToolPtr> tools)
194 {
195  if (!this->isInitialized())
196  return;
197 
198  for (std::map<QString, IgstkToolPtr>::iterator it = tools.begin(); it != tools.end(); ++it)
199  {
200  IgstkToolPtr tool = it->second;
201 
202  if (tool && tool->getPointer())
203  {
204  tool->getPointer()->RequestDetachFromTracker();
205  }
206  }
207 }
208 
210 {
211  mTracker->RequestStartTracking();
212 }
213 
215 {
216  mTracker->RequestStopTracking();
217 }
218 
220 {
221  return mValid;
222 }
223 
225 {
226  return mOpen;
227 }
228 
230 {
231  return mInitialized;
232 }
233 
235 {
236  return mTracking;
237 }
238 
239 void IgstkTracker::trackerTransformCallback(const itk::EventObject &event)
240 {
241  //successes
242  if (igstk::TrackerOpenEvent().CheckEvent(&event))
243  {
244  this->internalOpen(true);
245  this->internalInitialized(true);
246  }
247  else if (igstk::TrackerCloseEvent().CheckEvent(&event))
248  {
249  this->internalOpen(false);
250  this->internalInitialized(false);
251  }
252  else if (igstk::TrackerInitializeEvent().CheckEvent(&event))
253  {
254  //Never happens???
255  //this->internalInitialized(true);
256  //report(mUid+" is initialized.");
257  reportWarning("This never happens for some reason... check code");
258  }
259  else if (igstk::TrackerStartTrackingEvent().CheckEvent(&event))
260  {
261  this->internalTracking(true);
262  }
263  else if (igstk::TrackerStopTrackingEvent().CheckEvent(&event))
264  {
265  this->internalTracking(false);
266  }
267  else if (igstk::TrackerUpdateStatusEvent().CheckEvent(&event))
268  {
269  //reportDebug(mUid+" is updated."); //SPAM!
270  }
271  else if (igstk::TrackerToolTransformUpdateEvent().CheckEvent(&event))
272  {
273  //reportDebug(mUid+" has updated a transform."); //SPAM
274  }
275  //communication success
276  else if (igstk::CompletedEvent().CheckEvent(&event))
277  {
278  // this seems to appear after every transmit (several times/second)
279  //report(mUid+" set up communication correctly."); //SPAM
280  }
281  //coordinate system success
282  else if (igstk::CoordinateSystemSetTransformEvent().CheckEvent(&event))
283  {
284  //report();
285  }
286  //failures
287  else if (igstk::InvalidRequestErrorEvent().CheckEvent(&event))
288  {
289  reportWarning(mUid + " received an invalid request. This means that the internal igstk tracker did not accept the request. Do not know which request.");
290  this->shutdown();
291  }
292  else if (igstk::TrackerOpenErrorEvent().CheckEvent(&event))
293  {
294  reportError(mUid + " could not open.");
295  //this->shutdown();
296  }
297  else if (igstk::TrackerCloseErrorEvent().CheckEvent(&event))
298  {
299  reportError(mUid + " could not close.");
300  //this->shutdown();
301  }
302  else if (igstk::TrackerInitializeErrorEvent().CheckEvent(&event))
303  {
304  reportError(mUid + " could not initialize.");
305  //this->shutdown();
306  }
307  else if (igstk::TrackerStartTrackingErrorEvent().CheckEvent(&event))
308  {
309  reportError(mUid + " could not start tracking.");
310  //this->shutdown();
311  }
312  else if (igstk::TrackerStopTrackingErrorEvent().CheckEvent(&event))
313  {
314  reportError(mUid + " could not stop tracking.");
315  //this->shutdown();
316  }
317  else if (igstk::TrackerUpdateStatusErrorEvent().CheckEvent(&event))
318  {
319  reportError(mUid + " could not update.");
320  //this->shutdown();
321  }
322  //communication failure
323  else if (igstk::InputOutputErrorEvent().CheckEvent(&event))
324  {
325  //this happens when you pull out the cable while tracking
326  reportError(mUid + " cannot communicate with input/output.");
327  this->shutdown();
328  }
329  else if (igstk::InputOutputTimeoutEvent().CheckEvent(&event))
330  {
331  reportError(mUid + " input/output communication timed out.");
332  //this->shutdown();
333  }
334  else if (igstk::OpenPortErrorEvent().CheckEvent(&event))
335  {
336  reportError(mUid + " could not open communication with tracker.");
337  this->shutdown();
338  }
339  else if (igstk::ClosePortErrorEvent().CheckEvent(&event))
340  {
341  reportError(mUid + " could not close communication with tracker.");
342  this->shutdown();
343  }
344  else
345  {
346  event.Print(std::cout);
347  }
348 }
349 
351 {
352  bool logging = settings()->value("IGSTKDebugLogging", true).toBool();
353  if (logging)
354  {
355  std::ofstream* loggerFile = new std::ofstream();
356  QString logFile = mInternalStructure.mLoggingFolderName + "Tracker_Logging.txt";
357  loggerFile->open(cstring_cast(logFile));
358  mTrackerLogger = igstk::Logger::New();
359  mTrackerLogOutput = itk::StdStreamLogOutput::New();
360  mTrackerLogOutput->SetStream(*loggerFile);
361  mTrackerLogger->AddLogOutput(mTrackerLogOutput);
362  mTrackerLogger->SetPriorityLevel(itk::Logger::DEBUG);
363 
364  mTracker->SetLogger(mTrackerLogger);
365  mCommunication->SetLogger(mTrackerLogger);
366  }
367 }
368 
370 {
371  if (mOpen == value)
372  return;
373  mOpen = value;
374 
375  report(mUid + " is " + (value ? "open" : "closed") + ".");
376  emit open(mOpen);
377 }
378 
380 {
381  if (mInitialized == value)
382  return;
383  mInitialized = value;
384 
385  report(mUid + " is " + (value ? "" : "un") + "initialized.");
387 }
388 
390 {
391  if (mTracking == value)
392  return;
393  mTracking = value;
394 
395  report(mUid + " is " + (value ? "" : "not ") + "tracking.");
396  emit tracking(mTracking);
397 }
398 
400 {
401  reportWarning(mUid + " experienced a unrecoverable error, reconfiguration is required.");
402  emit error();
403 }
404 
406 {
407  mCommunication->CloseCommunication();
408 
409  //because the tracker now is closed we don't get the callback events so we need to reset the trackers internal
410  //status manually
411  this->internalTracking(false);
412  this->internalInitialized(false);
413  this->internalOpen(false);
414  this->internalError(true);
415 }
416 
417 } //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:92
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:87
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:91
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:42
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:90
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)