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