PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
vtkPlusAtracsysCommand.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2 Program: Plus
3 Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4 See License.txt for details.
5 =========================================================Plus=header=end*/
6 
7 #include "PlusConfigure.h"
10 
11 #include "vtkPlusDataCollector.h"
12 #include "vtkObjectFactory.h"
13 #include "vtkPlusChannel.h"
14 #include "vtkPlusDevice.h"
15 
16 #include <vtkVariant.h>
17 #include <vtkSmartPointer.h>
18 
19 #include <iterator>
20 #include <limits>
21 #include <map>
22 #include <string>
23 
24 namespace
25 {
26  static const std::string ATRACSYS_CMD_NAME = "AtracsysCommand";
27 }
28 
30 
31 //----------------------------------------------------------------------------
33 {
34  this->AtracsysDeviceId = "";
35 }
36 
37 //----------------------------------------------------------------------------
39 {
40 }
41 
42 //----------------------------------------------------------------------------
44 {
45  SetName(ATRACSYS_CMD_NAME);
46 }
47 
48 //----------------------------------------------------------------------------
49 void vtkPlusAtracsysCommand::PrintSelf(ostream& os, vtkIndent indent)
50 {
51  this->Superclass::PrintSelf(os, indent);
52 }
53 
54 //----------------------------------------------------------------------------
55 void vtkPlusAtracsysCommand::GetCommandNames(std::list<std::string>& cmdNames)
56 {
57  cmdNames.clear();
58  cmdNames.push_back(ATRACSYS_CMD_NAME);
59 }
60 
61 //----------------------------------------------------------------------------
62 std::string vtkPlusAtracsysCommand::GetDescription(const std::string& commandName)
63 {
64  std::string desc;
65  if (commandName.empty() || igsioCommon::IsEqualInsensitive(commandName, ATRACSYS_CMD_NAME))
66  {
67  desc += ATRACSYS_CMD_NAME;
68  desc += ": Send command to Atracsys device.";
69  }
70 
71  return desc;
72 }
73 
74 //----------------------------------------------------------------------------
76 {
78  {
79  return PLUS_FAIL;
80  }
81 
82  this->SetAtracsysDeviceId(aConfig->GetAttribute("DeviceId"));
83 
84  // Parse nested elements and store requested parameter changes
85  for (int elemIndex = 0; elemIndex < aConfig->GetNumberOfNestedElements(); ++elemIndex)
86  {
87  vtkXMLDataElement* currentElem = aConfig->GetNestedElement(elemIndex);
88  if (igsioCommon::IsEqualInsensitive(currentElem->GetName(), vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_FLAG))
89  {
90  const char* parameterName = currentElem->GetAttribute("Name");
91  const char* parameterValue = currentElem->GetAttribute("Value");
92 
93  if (!parameterName || !parameterValue)
94  {
95  LOG_ERROR("Unable to find required Name or Value attribute in " << (currentElem->GetName() ? currentElem->GetName() : "(undefined)") << " element in Atracsys SetFlag command");
96  continue;
97  }
98 
99  this->CommandList[parameterName] = parameterValue;
100  }
101  else if (igsioCommon::IsEqualInsensitive(currentElem->GetName(), vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_LED_RGBF))
102  {
103  const char* rValue = currentElem->GetAttribute("Red");
104  const char* gValue = currentElem->GetAttribute("Green");
105  const char* bValue = currentElem->GetAttribute("Blue");
106  const char* freqValue = currentElem->GetAttribute("Frequency");
107 
108  if (!rValue || !gValue || !bValue || !freqValue)
109  {
110  LOG_ERROR("Unable to find required Red, Green, Blue or Frequency attribute in " << (currentElem->GetName() ? currentElem->GetName() : "(undefined)") << " element in Atracsys " << vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_LED_RGBF << " command");
111  continue;
112  }
113 
114  bool valid = false;
115  this->LedR = vtkVariant(rValue).ToInt(&valid);
116  if (!valid)
117  {
118  LOG_ERROR("Failed to parse Red value in AtracsysCommand " << vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_LED_RGBF << " message.");
119  continue;
120  }
121  this->LedG = vtkVariant(gValue).ToInt(&valid);
122  if (!valid)
123  {
124  LOG_ERROR("Failed to parse Green value in AtracsysCommand " << vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_LED_RGBF << " message.");
125  continue;
126  }
127  this->LedB = vtkVariant(bValue).ToInt(&valid);
128  if (!valid)
129  {
130  LOG_ERROR("Failed to parse Blue value in AtracsysCommand " << vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_LED_RGBF << " message.");
131  continue;
132  }
133  this->LedFreq = vtkVariant(freqValue).ToInt(&valid);
134  if (!valid)
135  {
136  LOG_ERROR("Failed to parse Frequency value in AtracsysCommand " << vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_LED_RGBF << " message.");
137  continue;
138  }
139 
140  this->CommandList[vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_LED_RGBF] = ""; // flag value to update LED with provided values
141  }
142  else if (igsioCommon::IsEqualInsensitive(currentElem->GetName(), vtkPlusAtracsysTracker::ATRACSYS_COMMAND_ENABLE_TOOL))
143  {
144  const char* toolId = currentElem->GetAttribute("ToolId");
145  const char* enabled = currentElem->GetAttribute("Enabled");
146 
147  if (!toolId || !enabled)
148  {
149  LOG_ERROR("Unable to find required ToolId or Enabled attribute in " << (currentElem->GetName() ? currentElem->GetName() : "(undefined)") << " element in Atracsys " << vtkPlusAtracsysTracker::ATRACSYS_COMMAND_ENABLE_TOOL << " command");
150  continue;
151  }
152 
154  this->EnableDisableTools[toolId] = enabled;
155  }
156  else if (igsioCommon::IsEqualInsensitive(currentElem->GetName(), vtkPlusAtracsysTracker::ATRACSYS_COMMAND_ADD_TOOL))
157  {
158  const char* toolId = currentElem->GetAttribute("ToolId");
159  const char* geometry = currentElem->GetAttribute("Geometry");
160 
161  if (!toolId || !geometry)
162  {
163  LOG_ERROR("Unable to find required Name or Value attribute in " << (currentElem->GetName() ? currentElem->GetName() : "(undefined)") << " element in Atracsys " << vtkPlusAtracsysTracker::ATRACSYS_COMMAND_ADD_TOOL << " command");
164  continue;
165  }
166 
168  this->Markers[toolId] = geometry;
169  }
170  else
171  {
172  // invalid command
173  LOG_ERROR("Invalid command name (" << currentElem->GetName() << ") provided to AtracsysCommand.")
174  }
175  }
176 
177  return PLUS_SUCCESS;
178 }
179 
180 //----------------------------------------------------------------------------
182 {
184  {
185  return PLUS_FAIL;
186  }
187 
188  XML_WRITE_STRING_ATTRIBUTE_IF_NOT_EMPTY(AtracsysDeviceId, aConfig);
189 
190  // Write parameters as nested elements
191  std::map<std::string, std::string>::iterator commandIt;
192  for (commandIt = this->CommandList.begin(); commandIt != this->CommandList.end(); commandIt++)
193  {
194  if (igsioCommon::IsEqualInsensitive(commandIt->first, vtkPlusAtracsysTracker::ATRACSYS_COMMAND_SET_LED_RGBF))
195  {
196  // write SetLED element
197  vtkSmartPointer<vtkXMLDataElement> ledElem = vtkSmartPointer<vtkXMLDataElement>::New();
199  ledElem->SetAttribute("Red", std::to_string(this->LedR).c_str());
200  ledElem->SetAttribute("Green", std::to_string(this->LedG).c_str());
201  ledElem->SetAttribute("Blue", std::to_string(this->LedB).c_str());
202  ledElem->SetAttribute("Frequency", std::to_string(this->LedFreq).c_str());
203  aConfig->AddNestedElement(ledElem);
204  }
205  else if (igsioCommon::IsEqualInsensitive(commandIt->first, vtkPlusAtracsysTracker::ATRACSYS_COMMAND_ENABLE_TOOL))
206  {
207  // write EnableTool element
208  vtkSmartPointer<vtkXMLDataElement> enableToolElem = vtkSmartPointer<vtkXMLDataElement>::New();
210  enableToolElem->SetAttribute("ToolId", commandIt->second.c_str());
211  std::map<std::string, std::string>::iterator enabledToolValue = this->EnableDisableTools.find(commandIt->second);
212  enableToolElem->SetAttribute("Enabled", enabledToolValue->second.c_str());
213  aConfig->AddNestedElement(enableToolElem);
214  }
215  else if (igsioCommon::IsEqualInsensitive(commandIt->first, vtkPlusAtracsysTracker::ATRACSYS_COMMAND_ADD_TOOL))
216  {
217  // write AddTool element
218  vtkSmartPointer<vtkXMLDataElement> addToolElem = vtkSmartPointer<vtkXMLDataElement>::New();
220  addToolElem->SetAttribute("ToolId", commandIt->second.c_str());
221  std::map<std::string, std::string>::iterator marker = this->Markers.find(commandIt->second);
222  addToolElem->SetAttribute("Geometry", marker->second.c_str());
223  aConfig->AddNestedElement(addToolElem);
224  }
225  else
226  {
227  // write SetFlag element
228  vtkSmartPointer<vtkXMLDataElement> flagElem = vtkSmartPointer<vtkXMLDataElement>::New();
230  flagElem->SetAttribute("Name", commandIt->first.c_str());
231  flagElem->SetAttribute("Value", commandIt->second.c_str());
232  aConfig->AddNestedElement(flagElem);
233  }
234  }
235 
236  return PLUS_SUCCESS;
237 }
238 
239 PlusStatus vtkPlusAtracsysCommand::StringToBool(std::string strVal, bool& boolVal)
240 {
241  if (igsioCommon::IsEqualInsensitive(strVal, "TRUE"))
242  {
243  boolVal = true;
244  return PLUS_SUCCESS;
245  }
246  else if (igsioCommon::IsEqualInsensitive(strVal, "FALSE"))
247  {
248  boolVal = false;
249  return PLUS_SUCCESS;
250  }
251  return PLUS_FAIL;
252 }
253 
254 //----------------------------------------------------------------------------
256 {
257  LOG_DEBUG("vtkPlusAtracsysCommand::Execute: " << (!this->Name.empty() ? this->Name : "(undefined)")
258  << ", device: " << (this->AtracsysDeviceId.empty() ? "(undefined)" : this->AtracsysDeviceId));
259 
260  if (this->Name.empty())
261  {
262  this->QueueCommandResponse(PLUS_FAIL, "Command failed. See error message.", "No command name specified.");
263  return PLUS_FAIL;
264  }
265  else if (!igsioCommon::IsEqualInsensitive(this->Name, ATRACSYS_CMD_NAME))
266  {
267  this->QueueCommandResponse(PLUS_FAIL, "Command failed. See error message.", "Unknown command name: " + this->Name + ".");
268  return PLUS_FAIL;
269  }
270 
271  vtkPlusAtracsysTracker* atracsysDevice = GetAtracsysDevice();
272  if (atracsysDevice == NULL)
273  {
274  this->QueueCommandResponse(PLUS_FAIL, "Command failed. See error message.", std::string("Device ")
275  + (this->AtracsysDeviceId.empty() ? "(undefined)" : this->AtracsysDeviceId) + std::string(" is not found."));
276  return PLUS_FAIL;
277  }
278 
279  std::string atracsysDeviceId = (atracsysDevice->GetDeviceId().empty() ? "(unknown)" : atracsysDevice->GetDeviceId());
280  std::string resultString = "<CommandReply>";
281  std::string error = "";
282  std::map <std::string, std::pair<IANA_ENCODING_TYPE, std::string> > metaData;
283  PlusStatus status = PLUS_SUCCESS;
284 
285  std::map<std::string, std::string>::iterator commandIt;
286  for (commandIt = this->CommandList.begin(); commandIt != this->CommandList.end(); commandIt++)
287  {
288  std::string commandName = commandIt->first;
289  std::string value = commandIt->second;
290  resultString += "<Parameter Name=\"" + commandName + "\"";
291 
292  PlusStatus conversion = PLUS_SUCCESS;
293  PlusStatus setInDevice = PLUS_SUCCESS;
294 
296  {
297  bool enabled;
298  conversion = this->StringToBool(value, enabled);
299  setInDevice = atracsysDevice->SetLedEnabled(enabled);
300  }
302  {
303  bool enabled;
304  conversion = this->StringToBool(value, enabled);
305  setInDevice = atracsysDevice->SetLaserEnabled(enabled);
306  }
308  {
309  bool enabled;
310  conversion = this->StringToBool(value, enabled);
311  setInDevice = atracsysDevice->SetVideoEnabled(enabled);
312  }
314  {
315  // value is a placeholder, we can ignore it
316  setInDevice = atracsysDevice->SetUserLEDState(this->LedR, this->LedG, this->LedB, this->LedFreq, true);
317  }
319  {
320  // value contains ToolId to enable / disable
321  std::string strEnabled = this->EnableDisableTools.find(value)->second;
322  bool boolEnabled;
323  conversion = this->StringToBool(strEnabled, boolEnabled);
324  setInDevice = atracsysDevice->SetToolEnabled(value, boolEnabled);
325  }
327  {
328  // value contains ToolId of geometry to add
329  std::string geometry = this->Markers.find(value)->second;
330  setInDevice = atracsysDevice->AddToolGeometry(value, geometry);
331  }
332  else
333  {
334  LOG_WARNING("Unrecognized AtracsysCommand recieved with name: " << commandName
335  << ". Please see the documentation for a list of available commands.");
336  return PLUS_FAIL;
337  }
338 
339  if (conversion == PLUS_FAIL || setInDevice == PLUS_FAIL)
340  {
341  status = PLUS_FAIL;
342  }
343 
344  resultString += " Success=\"true\"/>";
345  metaData[commandName] = std::make_pair(IANA_TYPE_US_ASCII, "SUCCESS");
346  }
347  resultString += "</CommandReply>";
348 
349  vtkSmartPointer<vtkPlusCommandRTSCommandResponse> commandResponse = vtkSmartPointer<vtkPlusCommandRTSCommandResponse>::New();
350  commandResponse->UseDefaultFormatOff();
351  commandResponse->SetClientId(this->ClientId);
352  commandResponse->SetOriginalId(this->Id);
353  commandResponse->SetDeviceName(this->DeviceName);
354  commandResponse->SetCommandName(this->GetName());
355  commandResponse->SetStatus(status);
356  commandResponse->SetRespondWithCommandMessage(this->RespondWithCommandMessage);
357  commandResponse->SetErrorString(error);
358  commandResponse->SetResultString(resultString);
359  commandResponse->SetParameters(metaData);
360  this->CommandResponseQueue.push_back(commandResponse);
361 
362  return status;
363 }
364 
365 //----------------------------------------------------------------------------
367 {
368  vtkPlusDataCollector* dataCollector = GetDataCollector();
369  if (dataCollector == NULL)
370  {
371  LOG_ERROR("Data collector is invalid");
372  return NULL;
373  }
374  if (!this->AtracsysDeviceId.empty())
375  {
376  // Reconstructor device ID is specified
377  vtkPlusDevice* device = NULL;
378  if (dataCollector->GetDevice(device, this->AtracsysDeviceId) != PLUS_SUCCESS)
379  {
380  LOG_ERROR("No Atracsys device has been found by the name " << this->AtracsysDeviceId);
381  return NULL;
382  }
383  // device found
385  if (atracsysDevice == NULL)
386  {
387  // wrong type
388  LOG_ERROR("The specified device " << this->AtracsysDeviceId << " is not an Atracsys device");
389  return NULL;
390  }
391  return atracsysDevice;
392  }
393  else
394  {
395  // No Atracsys device id is specified, auto-detect the first one and use that
396  for (DeviceCollectionConstIterator it = dataCollector->GetDeviceConstIteratorBegin(); it != dataCollector->GetDeviceConstIteratorEnd(); ++it)
397  {
399  if (atracsysDevice != NULL)
400  {
401  // found an Atracsys device
402  this->SetAtracsysDeviceId(atracsysDevice->GetDeviceId());
403  return atracsysDevice;
404  }
405  }
406  LOG_ERROR("No Atracsys device has been found");
407  return NULL;
408  }
409 }
static const char * ATRACSYS_COMMAND_SET_FLAG
PlusStatus AddToolGeometry(std::string toolId, std::string geomString)
static vtkPlusAtracsysTracker * SafeDownCast(vtkObject *o)
vtkPlusAtracsysTracker * GetAtracsysDevice()
virtual void PrintSelf(ostream &os, vtkIndent indent)
Abstract interface for tracker and video devices.
Definition: vtkPlusDevice.h:60
std::vector< vtkPlusDevice * >::const_iterator DeviceCollectionConstIterator
Definition: vtkPlusDevice.h:48
PlusStatus SetLedEnabled(bool enabled)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *aConfig)
std::map< std::string, std::string > Markers
PlusStatus GetDevice(vtkPlusDevice *&aDevice, const std::string &aDeviceId) const
std::string Name
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *aConfig)
static const char * ATRACSYS_COMMAND_VIDEO_ENABLED
igsioStatus PlusStatus
Definition: PlusCommon.h:40
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *aConfig)
virtual std::string GetDeviceId() const
PlusStatus StringToBool(std::string strVal, bool &boolVal)
std::string to_string(ClariusAvailability avail)
PlusStatus SetLaserEnabled(bool enabled)
static const char * ATRACSYS_COMMAND_ENABLE_TOOL
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus SetUserLEDState(int red, int green, int blue, int frequency, bool enabled=true)
DeviceCollectionConstIterator GetDeviceConstIteratorBegin() const
static const char * ATRACSYS_COMMAND_LED_ENABLED
DeviceCollectionConstIterator GetDeviceConstIteratorEnd() const
Manages devices that record image or positional data.
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
static const char * ATRACSYS_COMMAND_LASER_ENABLED
int enabled
Definition: phidget22.h:3369
vtkStandardNewMacro(vtkPlusAtracsysCommand)
bool RespondWithCommandMessage
void QueueCommandResponse(PlusStatus status, const std::string &message, const std::string &error="", const igtl::MessageBase::MetaDataMap *metaData=nullptr)
virtual vtkPlusDataCollector * GetDataCollector()
std::string DeviceName
virtual void PrintSelf(ostream &os, vtkIndent indent)
const char const char * value
Definition: phidget22.h:5111
std::map< std::string, std::string > CommandList
static const char * ATRACSYS_COMMAND_SET_LED_RGBF
std::map< std::string, std::string > EnableDisableTools
virtual void GetCommandNames(std::list< std::string > &cmdNames)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *aConfig)
static const char * ATRACSYS_COMMAND_ADD_TOOL
PlusCommandResponseList CommandResponseQueue
virtual std::string GetDescription(const std::string &commandName)
This command allows OpenIGTLink commands to configure specific functionalities in the Atracsys device...
PlusStatus SetToolEnabled(std::string toolId, bool enabled)
PlusStatus SetVideoEnabled(bool enabled)
Interface to the Atracsys trackers This class talks with a Atracsys Tracker over the sTk Passive Trac...