PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
PlusServerRemoteControl.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 
12 #include "PlusConfigure.h"
13 #include "igtlCommon.h"
14 #include "igtlTrackingDataMessage.h"
15 #include "igtl_header.h"
21 #include "vtkPlusSendTextCommand.h"
24 #include "vtkPlusVersionCommand.h"
26 #ifdef PLUS_USE_STEALTHLINK
28 #endif
29 #ifdef PLUS_USE_CLARIUS
30  #include "vtkPlusClariusCommand.h"
31 #endif
32 
33 #include <vtkNew.h>
34 #include "vtksys/CommandLineArguments.hxx"
35 #include "vtksys/Process.h"
36 #include "vtkXMLUtilities.h"
37 
38 #include "igtlTransformMessage.h"
39 
40 // For catching Ctrl-C
41 #include <csignal>
42 #include <cstdlib>
43 #include <cstdio>
44 
45 //----------------------------------------------------------------------------
46 // For CTRL-C signal handling
47 static bool StopClientRequested = false;
48 
49 //----------------------------------------------------------------------------
50 // A customized vtkPlusOpenIGTLinkClient that can display the received transformation matrices
51 class vtkPlusOpenIGTLinkClientWithTransformLogging : public vtkPlusOpenIGTLinkClient
52 {
53 public:
54  static vtkPlusOpenIGTLinkClientWithTransformLogging* New();
55  vtkTypeMacro(vtkPlusOpenIGTLinkClientWithTransformLogging, vtkPlusOpenIGTLinkClient);
56 
57  bool OnMessageReceived(igtl::MessageHeader::Pointer messageHeader)
58  {
59  bool messageBodyReceived = false;
60  igtl::MessageBase::Pointer bodyMsg = this->IgtlMessageFactory->CreateReceiveMessage(messageHeader);
61  if (bodyMsg.IsNull())
62  {
63  LOG_ERROR("Unable to create message of type: " << messageHeader->GetMessageType());
64  return false;
65  }
66 
67  if (typeid(*bodyMsg) == typeid(igtl::TransformMessage))
68  {
69  igtl::TransformMessage::Pointer transformMsg = dynamic_cast<igtl::TransformMessage*>(bodyMsg.GetPointer());
70  transformMsg->SetMessageHeader(messageHeader);
71  transformMsg->AllocatePack();
72  SocketReceive(transformMsg->GetBufferBodyPointer(), transformMsg->GetBufferBodySize());
73  messageBodyReceived = true;
74 
75  int c = transformMsg->Unpack(1);
76  if (!(c & igtl::MessageHeader::UNPACK_BODY))
77  {
78  LOG_ERROR("Failed to receive TRANSFORM reply (invalid body)");
79  return messageBodyReceived;
80  }
81 
82  // Store the transform data into a matrix
83  igtl::Matrix4x4 mx;
84  transformMsg->GetMatrix(mx);
85  LOG_INFO("Matrix for " << transformMsg->GetDeviceName() << " TRANSFORM received: ");
86  igtl::PrintMatrix(mx);
87  }
88  else
89  {
90  LOG_INFO("Received " << messageHeader->GetMessageType() << " message.");
91  }
92 
93  return messageBodyReceived;
94  }
95 
96 protected:
97  vtkPlusOpenIGTLinkClientWithTransformLogging() {};
98  virtual ~vtkPlusOpenIGTLinkClientWithTransformLogging() {};
99 private:
100  vtkPlusOpenIGTLinkClientWithTransformLogging(const vtkPlusOpenIGTLinkClientWithTransformLogging&);
101  void operator=(const vtkPlusOpenIGTLinkClientWithTransformLogging&);
102 };
103 
104 vtkStandardNewMacro(vtkPlusOpenIGTLinkClientWithTransformLogging);
105 
106 // Utility functions for sending commands
107 
108 //----------------------------------------------------------------------------
109 // Print command XML string
111 {
112  vtkSmartPointer<vtkXMLDataElement> cmdConfig = vtkSmartPointer<vtkXMLDataElement>::New();
113  command->WriteConfiguration(cmdConfig);
114  std::ostringstream xmlStr;
115  vtkXMLUtilities::FlattenElement(cmdConfig, xmlStr);
116  xmlStr << std::ends;
117  LOG_INFO(">>> Command: " << xmlStr.str());
118 }
119 
120 //----------------------------------------------------------------------------
121 PlusStatus ExecuteStartAcquisition(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, std::string outputFilename, bool enableCompression, int commandId)
122 {
123  vtkSmartPointer<vtkPlusStartStopRecordingCommand> cmd = vtkSmartPointer<vtkPlusStartStopRecordingCommand>::New();
124  cmd->SetNameToStart();
125  cmd->SetId(commandId);
126  cmd->SetOutputFilename(outputFilename.c_str());
127  cmd->SetEnableCompression(enableCompression);
128  if (!deviceId.empty())
129  {
130  cmd->SetCaptureDeviceId(deviceId.c_str());
131  }
132  PrintCommand(cmd);
133  return client->SendCommand(cmd);
134 }
135 
136 //----------------------------------------------------------------------------
137 PlusStatus ExecuteStopAcquisition(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, std::string outputFilename, int commandId)
138 {
139  vtkSmartPointer<vtkPlusStartStopRecordingCommand> cmd = vtkSmartPointer<vtkPlusStartStopRecordingCommand>::New();
140  cmd->SetNameToStop();
141  cmd->SetId(commandId);
142  cmd->SetOutputFilename(outputFilename.c_str());
143  if (!deviceId.empty())
144  {
145  cmd->SetCaptureDeviceId(deviceId.c_str());
146  }
147  PrintCommand(cmd);
148  return client->SendCommand(cmd);
149 }
150 
151 //----------------------------------------------------------------------------
152 PlusStatus ExecuteSuspendAcquisition(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, int commandId)
153 {
154  vtkSmartPointer<vtkPlusStartStopRecordingCommand> cmd = vtkSmartPointer<vtkPlusStartStopRecordingCommand>::New();
155  cmd->SetNameToSuspend();
156  cmd->SetId(commandId);
157  if (!deviceId.empty())
158  {
159  cmd->SetCaptureDeviceId(deviceId.c_str());
160  }
161  PrintCommand(cmd);
162  return client->SendCommand(cmd);
163 }
164 
165 //----------------------------------------------------------------------------
166 PlusStatus ExecuteResumeAcquisition(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, int commandId)
167 {
168  vtkSmartPointer<vtkPlusStartStopRecordingCommand> cmd = vtkSmartPointer<vtkPlusStartStopRecordingCommand>::New();
169  cmd->SetNameToResume();
170  cmd->SetId(commandId);
171  if (!deviceId.empty())
172  {
173  cmd->SetCaptureDeviceId(deviceId.c_str());
174  }
175  PrintCommand(cmd);
176  return client->SendCommand(cmd);
177 }
178 
179 //----------------------------------------------------------------------------
181  const std::string& deviceId,
182  const std::string& inputFilename,
183  const std::string& outputFilename,
184  const std::string& outputImageName, int commandId)
185 {
186  vtkSmartPointer<vtkPlusReconstructVolumeCommand> cmd = vtkSmartPointer<vtkPlusReconstructVolumeCommand>::New();
187  cmd->SetNameToReconstruct();
188  cmd->SetId(commandId);
189  if (!deviceId.empty())
190  {
191  cmd->SetVolumeReconstructorDeviceId(deviceId.c_str());
192  }
193  cmd->SetInputSeqFilename(inputFilename.c_str());
194  if (!outputFilename.empty())
195  {
196  cmd->SetOutputVolFilename(outputFilename.c_str());
197  }
198  if (!outputImageName.empty())
199  {
200  cmd->SetOutputVolDeviceName(outputImageName.c_str());
201  }
202  PrintCommand(cmd);
203  return client->SendCommand(cmd);
204 }
205 
206 //----------------------------------------------------------------------------
207 PlusStatus ExecuteStartReconstruction(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, int commandId)
208 {
209  vtkSmartPointer<vtkPlusReconstructVolumeCommand> cmd = vtkSmartPointer<vtkPlusReconstructVolumeCommand>::New();
210  cmd->SetNameToStart();
211  cmd->SetId(commandId);
212  if (!deviceId.empty())
213  {
214  cmd->SetVolumeReconstructorDeviceId(deviceId.c_str());
215  }
216  PrintCommand(cmd);
217  return client->SendCommand(cmd);
218 }
219 
220 //----------------------------------------------------------------------------
221 PlusStatus ExecuteSuspendReconstruction(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, int commandId)
222 {
223  vtkSmartPointer<vtkPlusReconstructVolumeCommand> cmd = vtkSmartPointer<vtkPlusReconstructVolumeCommand>::New();
224  cmd->SetNameToSuspend();
225  cmd->SetId(commandId);
226  if (!deviceId.empty())
227  {
228  cmd->SetVolumeReconstructorDeviceId(deviceId.c_str());
229  }
230  PrintCommand(cmd);
231  return client->SendCommand(cmd);
232 }
233 
234 //----------------------------------------------------------------------------
235 PlusStatus ExecuteResumeReconstruction(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, int commandId)
236 {
237  vtkSmartPointer<vtkPlusReconstructVolumeCommand> cmd = vtkSmartPointer<vtkPlusReconstructVolumeCommand>::New();
238  cmd->SetNameToResume();
239  cmd->SetId(commandId);
240  if (!deviceId.empty())
241  {
242  cmd->SetVolumeReconstructorDeviceId(deviceId.c_str());
243  }
244  PrintCommand(cmd);
245  return client->SendCommand(cmd);
246 }
247 
248 //----------------------------------------------------------------------------
249 PlusStatus ExecuteGetSnapshotReconstruction(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, const std::string& outputFilename, const std::string& outputImageName, int commandId)
250 {
251  vtkSmartPointer<vtkPlusReconstructVolumeCommand> cmd = vtkSmartPointer<vtkPlusReconstructVolumeCommand>::New();
252  cmd->SetNameToGetSnapshot();
253  cmd->SetId(commandId);
254  if (!deviceId.empty())
255  {
256  cmd->SetVolumeReconstructorDeviceId(deviceId.c_str());
257  }
258  if (!outputFilename.empty())
259  {
260  cmd->SetOutputVolFilename(outputFilename.c_str());
261  }
262  if (!outputImageName.empty())
263  {
264  cmd->SetOutputVolDeviceName(outputImageName.c_str());
265  }
266  PrintCommand(cmd);
267  return client->SendCommand(cmd);
268 }
269 
270 //----------------------------------------------------------------------------
271 PlusStatus ExecuteStopReconstruction(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, const std::string& outputFilename, const std::string& outputImageName, int commandId)
272 {
273  vtkSmartPointer<vtkPlusReconstructVolumeCommand> cmd = vtkSmartPointer<vtkPlusReconstructVolumeCommand>::New();
274  cmd->SetNameToStop();
275  cmd->SetId(commandId);
276  if (!deviceId.empty())
277  {
278  cmd->SetVolumeReconstructorDeviceId(deviceId.c_str());
279  }
280  if (!outputFilename.empty())
281  {
282  cmd->SetOutputVolFilename(outputFilename.c_str());
283  }
284  if (!outputImageName.empty())
285  {
286  cmd->SetOutputVolDeviceName(outputImageName.c_str());
287  }
288  PrintCommand(cmd);
289  return client->SendCommand(cmd);
290 }
291 
292 //----------------------------------------------------------------------------
293 #ifdef PLUS_USE_STEALTHLINK
294 PlusStatus ExecuteGetExamData(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, const std::string& dicomOutputDirectory, const std::string& volumeEmbeddedTransformToFrame,
295  const bool& keepReceivedDicomFiles, int commandId)
296 {
297  vtkSmartPointer<vtkPlusStealthLinkCommand> cmd = vtkSmartPointer<vtkPlusStealthLinkCommand>::New();
298  cmd->SetNameToGetExam();
299  cmd->SetId(commandId);
300  if (!deviceId.empty())
301  {
302  cmd->SetStealthLinkDeviceId(deviceId.c_str());
303  }
304  if (!dicomOutputDirectory.empty())
305  {
306  cmd->SetDicomImagesOutputDirectory(dicomOutputDirectory.c_str());
307  }
308  if (!volumeEmbeddedTransformToFrame.empty())
309  {
310  cmd->SetVolumeEmbeddedTransformToFrame(volumeEmbeddedTransformToFrame.c_str());
311  }
312  cmd->SetKeepReceivedDicomFiles(keepReceivedDicomFiles);
313  PrintCommand(cmd);
314  return client->SendCommand(cmd);
315 }
316 #endif
317 
318 //----------------------------------------------------------------------------
319 #ifdef PLUS_USE_CLARIUS
320 PlusStatus ExecuteSaveRawData(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, const std::string& outputFilename,
321  const double& lastNSeconds, bool enableCompression, int commandId)
322 {
323  vtkSmartPointer<vtkPlusClariusCommand> cmd = vtkSmartPointer<vtkPlusClariusCommand>::New();
324  cmd->SetNameToSaveRawData();
325  cmd->SetId(commandId);
326  if (!deviceId.empty())
327  {
328  cmd->SetClariusDeviceId(deviceId.c_str());
329  }
330  if (!outputFilename.empty())
331  {
332  cmd->SetOutputFilename(outputFilename);
333  }
334  cmd->SetRawDataLastNSeconds(lastNSeconds);
335  cmd->SetCompressRawData(enableCompression);
336  PrintCommand(cmd);
337  return client->SendCommand(cmd);
338 }
339 #endif
340 
341 //----------------------------------------------------------------------------
343 {
344  vtkSmartPointer<vtkPlusVersionCommand> cmd = vtkSmartPointer<vtkPlusVersionCommand>::New();
345  cmd->SetNameToVersion();
346  cmd->SetId(commandId);
347  PrintCommand(cmd);
348  return client->SendCommand(cmd);
349 }
350 
351 //----------------------------------------------------------------------------
353 {
354  vtkSmartPointer<vtkPlusRequestIdsCommand> cmd = vtkSmartPointer<vtkPlusRequestIdsCommand>::New();
355  cmd->SetNameToRequestChannelIds();
356  cmd->SetId(commandId);
357  PrintCommand(cmd);
358  return client->SendCommand(cmd);
359 }
360 
361 //----------------------------------------------------------------------------
362 PlusStatus ExecuteGetDeviceIds(vtkPlusOpenIGTLinkClient* client, const std::string& deviceType, int commandId)
363 {
364  vtkSmartPointer<vtkPlusRequestIdsCommand> cmd = vtkSmartPointer<vtkPlusRequestIdsCommand>::New();
365  cmd->SetNameToRequestDeviceIds();
366  cmd->SetId(commandId);
367  cmd->SetDeviceType(deviceType.c_str());
368  PrintCommand(cmd);
369  return client->SendCommand(cmd);
370 }
371 
372 //----------------------------------------------------------------------------
374  const std::string& transformName,
375  const std::string& transformValue,
376  const std::string& transformError,
377  const std::string& transformDate,
378  const std::string& transformPersistent, int commandId)
379 {
380  vtkSmartPointer<vtkPlusUpdateTransformCommand> cmd = vtkSmartPointer<vtkPlusUpdateTransformCommand>::New();
381  cmd->SetNameToUpdateTransform();
382  cmd->SetId(commandId);
383  cmd->SetTransformName(transformName.c_str());
384  double value = 0.0;
385  igsioCommon::StringToDouble(transformError.c_str(), value);
386  cmd->SetTransformError(value);
387  cmd->SetTransformDate(transformDate.c_str());
388  cmd->SetTransformPersistent(igsioCommon::IsEqualInsensitive(transformPersistent, "TRUE"));
389  std::vector<std::string> elems;
390  vtkMatrix4x4* transformValueMatrix = vtkMatrix4x4::New();
391  igsioCommon::SplitStringIntoTokens(transformValue, ' ', elems);
392  if (elems.size() != 16)
393  {
394  LOG_ERROR("Invalid formatting of matrix string.");
395  return PLUS_FAIL;
396  }
397  for (int i = 0; i < 4; i++)
398  {
399  for (int j = 0; j < 4; j++)
400  {
401  igsioCommon::StringToDouble((elems[i * 4 + j]).c_str(), value);
402  transformValueMatrix->SetElement(i, j, value);
403  }
404  }
405  cmd->SetTransformValue(transformValueMatrix);
406  transformValueMatrix->Delete();
407  PrintCommand(cmd);
408  return client->SendCommand(cmd);
409 }
410 
411 //----------------------------------------------------------------------------
412 PlusStatus ExecuteGetTransform(vtkPlusOpenIGTLinkClient* client, const std::string& transformName, int commandId)
413 {
414  vtkSmartPointer<vtkPlusGetTransformCommand> cmd = vtkSmartPointer<vtkPlusGetTransformCommand>::New();
415  cmd->SetNameToGetTransform();
416  cmd->SetId(commandId);
417  cmd->SetTransformName(transformName.c_str());
418  PrintCommand(cmd);
419  return client->SendCommand(cmd);
420 }
421 
422 //----------------------------------------------------------------------------
423 PlusStatus ExecuteGetPoint(vtkPlusOpenIGTLinkClient* client, const std::string& inputFilename)
424 {
425  vtkNew<vtkPlusIgtlMessageFactory> factory;
426  igtl::MessageBase::Pointer msg = factory->CreateSendMessage("GET_POINT", IGTL_HEADER_VERSION_2);
427  msg->AllocateBuffer();
428  msg->SetMetaDataElement("Filename", IANA_TYPE_US_ASCII, inputFilename);
429  msg->Pack();
430  return client->SendMessage(msg);
431 }
432 
433 //----------------------------------------------------------------------------
434 PlusStatus ExecuteSaveConfig(vtkPlusOpenIGTLinkClient* client, const std::string& outputFilename, int commandId)
435 {
436  vtkSmartPointer<vtkPlusSaveConfigCommand> cmd = vtkSmartPointer<vtkPlusSaveConfigCommand>::New();
437  cmd->SetNameToSaveConfig();
438  cmd->SetId(commandId);
439  cmd->SetFilename(outputFilename.c_str());
440  PrintCommand(cmd);
441  return client->SendCommand(cmd);
442 }
443 
444 //----------------------------------------------------------------------------
446 {
447  vtkSmartPointer<vtkPlusIgtlMessageFactory> factory = vtkSmartPointer<vtkPlusIgtlMessageFactory>::New();
448  igtl::MessageBase::Pointer msg = factory->CreateSendMessage("STT_TDATA", IGTL_HEADER_VERSION_1);
449  igtl::StartTrackingDataMessage* startMsg = dynamic_cast<igtl::StartTrackingDataMessage*>(msg.GetPointer());
450  startMsg->SetResolution(25);
451  startMsg->Pack();
452  return client->SendMessage(msg);
453 }
454 
455 //----------------------------------------------------------------------------
457 {
458  vtkSmartPointer<vtkPlusIgtlMessageFactory> factory = vtkSmartPointer<vtkPlusIgtlMessageFactory>::New();
459  igtl::MessageBase::Pointer msg = factory->CreateSendMessage("STP_TDATA", IGTL_HEADER_VERSION_1);
460  igtl::StopTrackingDataMessage* stopMsg = dynamic_cast<igtl::StopTrackingDataMessage*>(msg.GetPointer());
461  stopMsg->Pack();
462  return client->SendMessage(msg);
463 }
464 
465 //----------------------------------------------------------------------------
466 PlusStatus ExecuteSendText(vtkPlusOpenIGTLinkClient* client, const std::string& deviceId, const std::string& text, bool responseExpected, int commandId)
467 {
468  vtkSmartPointer<vtkPlusSendTextCommand> cmd = vtkSmartPointer<vtkPlusSendTextCommand>::New();
469  cmd->SetNameToSendText();
470  cmd->SetId(commandId);
471  cmd->SetText(text.c_str());
472  cmd->SetDeviceId(deviceId.c_str());
473  cmd->SetResponseExpected(responseExpected);
474  PrintCommand(cmd);
475  return client->SendCommand(cmd);
476 }
477 
478 //----------------------------------------------------------------------------
480  bool& didTimeout,
481  std::string& outContent,
482  std::string& outErrorMessage,
483  igtl::MessageBase::MetaDataMap& parameters,
484  int timeoutSec = 30)
485 {
486  int32_t commandId;
487  std::string commandName;
488 
489  PlusStatus result;
490 
491  const double replyTimeoutSec = timeoutSec;
492  if (client->ReceiveReply(result, commandId, outErrorMessage, outContent, parameters, commandName, replyTimeoutSec) != PLUS_SUCCESS)
493  {
494  LOG_ERROR("Failed to receive reply to the command");
495  didTimeout = true;
496  return PLUS_FAIL;
497  }
498 
499  LOG_INFO("Command ID: " << commandId);
500  LOG_INFO("Status: " << (result == PLUS_SUCCESS ? "SUCCESS" : "FAIL"));
501  if (result == PLUS_FAIL)
502  {
503  LOG_INFO("Error: " << outErrorMessage);
504  }
505  LOG_INFO("Message: " << outContent);
506  for (igtl::MessageBase::MetaDataMap::const_iterator it = parameters.begin(); it != parameters.end(); ++it)
507  {
508  LOG_INFO(it->first << ": " << it->second.second);
509  }
510 
511  return result;
512 }
513 
514 //----------------------------------------------------------------------------
515 PlusStatus StartPlusServerProcess(const std::string& configFile, vtksysProcess*& processPtr)
516 {
517  processPtr = NULL;
518  std::string executablePath = vtkPlusConfig::GetInstance()->GetPlusExecutablePath("PlusServer");
519 
520  if (!vtksys::SystemTools::FileExists(executablePath.c_str(), true))
521  {
522  LOG_ERROR("Unable to find executable at: " << executablePath);
523  return PLUS_FAIL;
524  }
525 
526  try
527  {
528  processPtr = vtksysProcess_New();
529 
530  // Command name and parameters
531  std::vector<const char*> command;
532  command.push_back(executablePath.c_str()); // command name
533  std::string param1 = std::string("--config-file=") + configFile;
534  command.push_back(param1.c_str()); // command parameter
535  command.push_back(0); // The array must end with a NULL pointer.
536  vtksysProcess_SetCommand(processPtr, &*command.begin());
537 
538  // Redirect PlusServer output to this process output (otherwise server execution would be blocked)
539  vtksysProcess_SetPipeFile(processPtr, vtksysProcess_Pipe_STDOUT, "PlusServerRemoteControlStdOut.log");
540  vtksysProcess_SetPipeFile(processPtr, vtksysProcess_Pipe_STDERR, "PlusServerRemoteControlStdErr.log");
541 
542  LOG_INFO("Start PlusServer...");
543  vtksysProcess_Execute(processPtr);
544  LOG_DEBUG("PlusServer started");
545 
546  return PLUS_SUCCESS;
547  }
548  catch (...)
549  {
550  LOG_ERROR("Failed to start PlusServer");
551  return PLUS_FAIL;
552  }
553 }
554 
555 //----------------------------------------------------------------------------
556 void StopPlusServerProcess(vtksysProcess*& processPtr)
557 {
558  if (processPtr == NULL)
559  {
560  return;
561  }
562  vtksysProcess_Kill(processPtr);
563  processPtr = NULL;
564 }
565 
566 #define RETURN_IF_FAIL(cmd) if (cmd!=PLUS_SUCCESS) { return PLUS_FAIL; };
567 
568 //----------------------------------------------------------------------------
570 {
571  const char captureDeviceId[] = "CaptureDevice";
572  const char capturingOutputFileName[] = "OpenIGTTrackedVideoRecordingTest.mha"; // must match the extension defined in the config file
573 
574  const char volumeReconstructionDeviceId[] = "VolumeReconstructorDevice";
575  const char* batchReconstructionInputFileName = capturingOutputFileName;
576  const char batchReconstructionOutputImageName[] = "VolumeReconstructedBatch";
577  const char snapshotReconstructionOutputImageName[] = "VolumeReconstructedSnapshot";
578  const char liveReconstructionOutputImageName[] = "VolumeReconstructedLive";
579  const char batchReconstructionOutputFileName[] = "VolumeReconstructedBatch.nrrd";
580  const char snapshotReconstructionOutputFileName[] = "VolumeReconstructedSnapshot.nrrd";
581  const char liveReconstructionOutputFileName[] = "VolumeReconstructedLive.nrrd";
582 
583  std::string replyMessage;
584  std::string errorMessage;
585  igtl::MessageBase::MetaDataMap parameters;
586  int commandId = 1;
587  bool didTimeout(false);
588 
589  if (client->GetServerIGTLVersion() >= OpenIGTLink_PROTOCOL_VERSION_3)
590  {
591  ExecuteVersion(client, commandId++);
592  PlusStatus result = ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters, 3);
593  if (result == PLUS_FAIL && didTimeout && client->GetServerIGTLVersion() >= OpenIGTLink_PROTOCOL_VERSION_3)
594  {
595  // Version 3 and greater expect a reply to the version command, if it timed out, it is an error
596  LOG_ERROR("Version handshake to the server timed out but it was unexpected.");
597  exit(EXIT_FAILURE);
598  }
599  else if (result == PLUS_SUCCESS && parameters.find("Version") != parameters.end())
600  {
601  LOG_INFO("Server IGTL Version: " << parameters["Version"].second);
602  }
603  else
604  {
605  LOG_ERROR("Version handshake to the server failed.");
606  exit(EXIT_FAILURE);
607  }
608  parameters.clear();
609  }
610 
611  // Basic commands
612  ExecuteGetChannelIds(client, commandId++);
613  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
614  if (client->GetServerIGTLVersion() < OpenIGTLink_PROTOCOL_VERSION_3)
615  {
616  if (replyMessage != "TrackedVideoStream")
617  {
618  LOG_ERROR("Incorrect reply sent. Got: " << replyMessage << ". Expected: \"TrackedVideoStream\"");
619  }
620  }
621  else
622  {
623  if (parameters.size() == 0 || parameters.find("TrackedVideoStream") == parameters.end())
624  {
625  LOG_ERROR("Empty result or entry not found in list of device IDs.");
626  }
627  else
628  {
629  if (!igsioCommon::IsEqualInsensitive(parameters["TrackedVideoStream"].second, "TrackedVideoStream"))
630  {
631  LOG_ERROR("Incorrect parameter returned. Got: " << parameters["TrackedVideoStream"].second << ". Expected: \"TrackedVideoStream\"");
632  }
633  }
634  }
635  parameters.clear();
636 
637  ExecuteGetDeviceIds(client, "VirtualVolumeReconstructor", commandId++);
638  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
639  if (client->GetServerIGTLVersion() < OpenIGTLink_PROTOCOL_VERSION_3)
640  {
641  if (replyMessage != "VolumeReconstructorDevice")
642  {
643  LOG_ERROR("Incorrect reply sent. Got: " << replyMessage << ". Expected: \"VolumeReconstructorDevice\"");
644  }
645  }
646  else
647  {
648  if (parameters.size() == 0)
649  {
650  LOG_ERROR("Empty result returned for list of device IDs.");
651  }
652  else
653  {
654  if (!igsioCommon::IsEqualInsensitive(parameters["VolumeReconstructorDevice"].second, "VolumeReconstructorDevice"))
655  {
656  LOG_ERROR("Incorrect parameter returned.");
657  }
658  }
659  }
660  parameters.clear();
661 
662  ExecuteUpdateTransform(client, "Test1ToReference", "1 0 0 10 0 1.2 0.1 12 0.1 0.2 -0.9 -20 0 0 0 1", "1.4", "100314_182141", "TRUE", commandId++);
663  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
664  parameters.clear();
665  ExecuteGetTransform(client, "Test1ToReference", commandId++);
666  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
667  parameters.clear();
668  ExecuteSaveConfig(client, "Test1SavedConfig.xml", commandId++);
669  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
670  parameters.clear();
671  ExecuteStartTDATA(client, commandId++);
672  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
673  parameters.clear();
674  ExecuteStopTDATA(client, commandId++);
675  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
676  parameters.clear();
677 
678  // Capturing
679  ExecuteStartAcquisition(client, captureDeviceId, capturingOutputFileName, false, commandId++);
680  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
681  parameters.clear();
682  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
683  ExecuteSuspendAcquisition(client, captureDeviceId, commandId++);
684  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
685  parameters.clear();
686  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
687  ExecuteResumeAcquisition(client, captureDeviceId, commandId++);
688  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
689  parameters.clear();
690  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
691  ExecuteStopAcquisition(client, captureDeviceId, capturingOutputFileName, commandId++);
692  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
693  parameters.clear();
694  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
695 
696  // Volume reconstruction from file
697  ExecuteReconstructFromFile(client, volumeReconstructionDeviceId, batchReconstructionInputFileName, batchReconstructionOutputFileName, batchReconstructionOutputImageName, commandId++);
698  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
699  parameters.clear();
700  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
701 
702  // Live volume reconstruction
703  ExecuteStartReconstruction(client, volumeReconstructionDeviceId, commandId++);
704  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
705  parameters.clear();
706  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
707  ExecuteSuspendReconstruction(client, volumeReconstructionDeviceId, commandId++);
708  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
709  parameters.clear();
710  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
711  ExecuteResumeReconstruction(client, volumeReconstructionDeviceId, commandId++);
712  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
713  parameters.clear();
714  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
715  ExecuteGetSnapshotReconstruction(client, volumeReconstructionDeviceId, snapshotReconstructionOutputFileName, snapshotReconstructionOutputImageName, commandId++);
716  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
717  parameters.clear();
718  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
719  ExecuteGetSnapshotReconstruction(client, volumeReconstructionDeviceId, snapshotReconstructionOutputFileName, snapshotReconstructionOutputImageName, commandId++);
720  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
721  parameters.clear();
722  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
723  ExecuteGetSnapshotReconstruction(client, volumeReconstructionDeviceId, snapshotReconstructionOutputFileName, snapshotReconstructionOutputImageName, commandId++);
724  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
725  parameters.clear();
726  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
727  ExecuteStopReconstruction(client, volumeReconstructionDeviceId, liveReconstructionOutputFileName, liveReconstructionOutputImageName, commandId++);
728  RETURN_IF_FAIL(ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters));
729  parameters.clear();
730  vtkIGSIOAccurateTimer::DelayWithEventProcessing(2.0);
731 
732  return PLUS_SUCCESS;
733 }
734 
735 // -------------------------------------------------
736 // For CTRL-C signal handling
738 {
739  StopClientRequested = true;
740 }
741 
742 //----------------------------------------------------------------------------
743 int main(int argc, char** argv)
744 {
745  // Check command line arguments.
746  std::string serverHost = "127.0.0.1";
747  int serverPort = 18944;
748  std::string command;
749  std::string deviceId;
750  std::string inputFilename = "PlusServerRecording.nrrd";
751  std::string outputFilename;
752  std::string outputImageName;
753  std::string transformName;
754  std::string transformError;
755  std::string transformDate;
756  std::string transformPersistent;
757  std::string transformValue;
758  std::string dicomOutputDirectory;
759  std::string volumeEmbeddedTransformToFrame;
760  int serverHeaderVersion(-1);
761  std::string text;
762  bool keepReceivedDicomFiles = false;
763  bool responseExpected = false;
764  bool enableCompression = false;
765  int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
766  bool keepConnected = false;
767  std::string serverConfigFileName;
768  bool runTests = false;
769  int serverIGTLVersion(-1);
770  int commandId(0);
771  double lastNSeconds(-1.0);
772 
773  vtksys::CommandLineArguments args;
774  args.Initialize(argc, argv);
775 
776  args.AddArgument("--host", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &serverHost, "Host name of the OpenIGTLink server (default: 127.0.0.1)");
777  args.AddArgument("--port", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &serverPort, "Port address of the OpenIGTLink server (default: 18944)");
778  args.AddArgument("--command", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &command,
779  "Command name to be executed on the server (START_ACQUISITION, STOP_ACQUISITION, SUSPEND_ACQUISITION, RESUME_ACQUISITION, RECONSTRUCT, START_RECONSTRUCTION, SUSPEND_RECONSTRUCTION, RESUME_RECONSTRUCTION, STOP_RECONSTRUCTION, GET_RECONSTRUCTION_SNAPSHOT, GET_CHANNEL_IDS, GET_DEVICE_IDS, GET_EXAM_DATA, SAVE_RAW_DATA, SEND_TEXT, UPDATE_TRANSFORM, GET_TRANSFORM, GET_POINT)");
780  args.AddArgument("--command-id", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &commandId, "Command ID to send to the server.");
781  args.AddArgument("--server-igtl-version", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &serverHeaderVersion, "The version of IGTL used by the server. Remove this parameter when querying is dynamic.");
782  args.AddArgument("--device", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &deviceId, "ID of the controlled device (optional, default: first VirtualStreamCapture or VirtualVolumeReconstructor device). In case of GET_DEVICE_IDS it is not an ID but a device type.");
783  args.AddArgument("--input-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputFilename, "File name of the input, used for RECONSTRUCT command");
784  args.AddArgument("--output-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputFilename, "File name of the output, used for START command (optional, default: 'PlusServerRecording.nrrd' for acquisition, no output for volume reconstruction)");
785  args.AddArgument("--output-image-name", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputImageName, "OpenIGTLink device name of the reconstructed file (optional, default: image is not sent)");
786  args.AddArgument("--text", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &text, "Text to be sent to the device");
787  args.AddArgument("--transform-name", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &transformName, "The name of the transform to update. Form=[From]To[To]Transform");
788  args.AddArgument("--transform-date", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &transformDate, "The date of the transform to update.");
789  args.AddArgument("--transform-error", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &transformError, "The error of the transform to update.");
790  args.AddArgument("--transform-persistent", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &transformPersistent, "The persistence of the transform to update.");
791  args.AddArgument("--transform-value", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &transformValue, "The actual transformation matrix to update.");
792  args.AddArgument("--use-compression", vtksys::CommandLineArguments::NO_ARGUMENT, &enableCompression, "Set capture device to record compressed data. Only supported with .nrrd capture.");
793  args.AddArgument("--keep-connected", vtksys::CommandLineArguments::NO_ARGUMENT, &keepConnected, "Keep the connection to the server after command completion (exits on CTRL-C).");
794  args.AddArgument("--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel, "Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
795  args.AddArgument("--dicom-directory", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &dicomOutputDirectory, "The folder directory for the dicom images acquired from the StealthLink Server");
796  args.AddArgument("--volumeEmbeddedTransformToFrame", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &volumeEmbeddedTransformToFrame, "The reference frame in which the dicom image will be represented. Ex: RAS,LPS,Reference,Tracker etc");
797  args.AddArgument("--keepReceivedDicomFiles", vtksys::CommandLineArguments::NO_ARGUMENT, &keepReceivedDicomFiles, "Keep the dicom files in the designated folder after having acquired them from the server");
798  args.AddArgument("--response-expected", vtksys::CommandLineArguments::NO_ARGUMENT, &responseExpected, "Wait for a response after sending text");
799  args.AddArgument("--server-config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &serverConfigFileName, "Starts a PlusServer instance with the provided config file. When this process exits, the server is stopped.");
800  args.AddArgument("--run-tests", vtksys::CommandLineArguments::NO_ARGUMENT, &runTests, "Test execution of all remote control commands. Requires a running PlusServer, which can be launched by --server-config-file");
801  args.AddArgument("--last-n-seconds", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &lastNSeconds, "Number of seconds of raw data to acquire from Clarius");
802 
803  if (!args.Parse())
804  {
805  std::cerr << "Problem parsing arguments." << std::endl;
806  std::cout << "Help: " << args.GetHelp() << std::endl;
807  exit(EXIT_FAILURE);
808  }
809 
810  if (command.empty() && !keepConnected && !runTests)
811  {
812  LOG_ERROR("The program has nothing to do, as neither --command, --keep-connected, nor --run-tests is specifed");
813  std::cout << "Help: " << args.GetHelp() << std::endl;
814  exit(EXIT_FAILURE);
815  }
816 
817  vtkPlusLogger::Instance()->SetLogLevel(verboseLevel);
818 
819  // Start a PlusServer
820  vtksysProcess* plusServerProcess = NULL;
821  if (!serverConfigFileName.empty())
822  {
823  if (StartPlusServerProcess(serverConfigFileName, plusServerProcess) != PLUS_SUCCESS)
824  {
825  LOG_ERROR("Failed to start PlusServer");
826  exit(EXIT_FAILURE);
827  }
828  }
829  // From this point PlusServer may be running, therefore before calling exit() the server process must be stopped (otherwise the process does not stop ever)
830 
831  // Connect to PlusServer
832  vtkSmartPointer<vtkPlusOpenIGTLinkClient> client = vtkSmartPointer<vtkPlusOpenIGTLinkClient>::New();
833  if (keepConnected)
834  {
835  // We use vtkPlusOpenIGTLinkClientWithTransformLogging instead of vtkPlusOpenIGTLinkClient to log the received transforms
836  client = vtkSmartPointer<vtkPlusOpenIGTLinkClientWithTransformLogging>::New();
837  }
838  client->SetServerHost(serverHost.c_str());
839  client->SetServerPort(serverPort);
840  if (serverIGTLVersion > 0)
841  {
842  client->SetServerIGTLVersion(serverIGTLVersion);
843  }
844  if (client->Connect(15.0) == PLUS_FAIL)
845  {
846  LOG_ERROR("Failed to connect to server at " << serverHost << ":" << serverPort);
847  StopPlusServerProcess(plusServerProcess);
848  exit(EXIT_FAILURE);
849  }
850 
851  int processReturnValue = EXIT_SUCCESS;
852 
853  // Run a command
854  if (!command.empty())
855  {
856  PlusStatus commandExecutionStatus = PLUS_SUCCESS;
857  // Execute command
858  if (igsioCommon::IsEqualInsensitive(command, "START_ACQUISITION"))
859  {
860  commandExecutionStatus = ExecuteStartAcquisition(client, deviceId, outputFilename, enableCompression, commandId);
861  }
862  else if (igsioCommon::IsEqualInsensitive(command, "STOP_ACQUISITION"))
863  {
864  commandExecutionStatus = ExecuteStopAcquisition(client, deviceId, outputFilename, commandId);
865  }
866  else if (igsioCommon::IsEqualInsensitive(command, "SUSPEND_ACQUISITION"))
867  {
868  commandExecutionStatus = ExecuteSuspendAcquisition(client, deviceId, commandId);
869  }
870  else if (igsioCommon::IsEqualInsensitive(command, "RESUME_ACQUISITION"))
871  {
872  commandExecutionStatus = ExecuteResumeAcquisition(client, deviceId, commandId);
873  }
874  else if (igsioCommon::IsEqualInsensitive(command, "START_RECONSTRUCTION"))
875  {
876  commandExecutionStatus = ExecuteStartReconstruction(client, deviceId, commandId);
877  }
878  else if (igsioCommon::IsEqualInsensitive(command, "SUSPEND_RECONSTRUCTION"))
879  {
880  commandExecutionStatus = ExecuteSuspendReconstruction(client, deviceId, commandId);
881  }
882  else if (igsioCommon::IsEqualInsensitive(command, "RESUME_RECONSTRUCTION"))
883  {
884  commandExecutionStatus = ExecuteResumeReconstruction(client, deviceId, commandId);
885  }
886  else if (igsioCommon::IsEqualInsensitive(command, "GET_RECONSTRUCTION_SNAPSHOT"))
887  {
888  commandExecutionStatus = ExecuteGetSnapshotReconstruction(client, deviceId, outputFilename, outputImageName, commandId);
889  }
890  else if (igsioCommon::IsEqualInsensitive(command, "STOP_RECONSTRUCTION"))
891  {
892  commandExecutionStatus = ExecuteStopReconstruction(client, deviceId, outputFilename, outputImageName, commandId);
893  }
894  else if (igsioCommon::IsEqualInsensitive(command, "RECONSTRUCT"))
895  {
896  commandExecutionStatus = ExecuteReconstructFromFile(client, deviceId, inputFilename, outputFilename, outputImageName, commandId);
897  }
898  else if (igsioCommon::IsEqualInsensitive(command, "GET_CHANNEL_IDS"))
899  {
900  commandExecutionStatus = ExecuteGetChannelIds(client, commandId);
901  }
902  else if (igsioCommon::IsEqualInsensitive(command, "GET_DEVICE_IDS"))
903  {
904  commandExecutionStatus = ExecuteGetDeviceIds(client, deviceId /* actually a device type */, commandId);
905  }
906  else if (igsioCommon::IsEqualInsensitive(command, "UPDATE_TRANSFORM"))
907  {
908  commandExecutionStatus = ExecuteUpdateTransform(client, transformName, transformValue, transformError, transformDate, transformPersistent, commandId);
909  }
910  else if (igsioCommon::IsEqualInsensitive(command, "SAVE_CONFIG"))
911  {
912  commandExecutionStatus = ExecuteSaveConfig(client, outputFilename, commandId);
913  }
914  else if (igsioCommon::IsEqualInsensitive(command, "SEND_TEXT"))
915  {
916  commandExecutionStatus = ExecuteSendText(client, deviceId, text, responseExpected, commandId);
917  }
918  else if (igsioCommon::IsEqualInsensitive(command, "GET_TRANSFORM"))
919  {
920  commandExecutionStatus = ExecuteGetTransform(client, transformName, commandId);
921  }
922  else if (igsioCommon::IsEqualInsensitive(command, "GET_POINT"))
923  {
924  commandExecutionStatus = ExecuteGetPoint(client, inputFilename);
925  }
926  else if (igsioCommon::IsEqualInsensitive(command, "GET_EXAM_DATA"))
927  {
928 #ifdef PLUS_USE_STEALTHLINK
929  commandExecutionStatus = ExecuteGetExamData(client, deviceId, dicomOutputDirectory, volumeEmbeddedTransformToFrame, keepReceivedDicomFiles, commandId);
930 #else
931  LOG_ERROR("Plus is not built with StealthLink support");
932  commandExecutionStatus = PLUS_FAIL;
933 #endif
934  }
935  else if (igsioCommon::IsEqualInsensitive(command, "SAVE_RAW_DATA"))
936  {
937 #ifdef PLUS_USE_CLARIUS
938  commandExecutionStatus = ExecuteSaveRawData(client, deviceId, outputFilename, lastNSeconds, enableCompression, commandId);
939 #else
940  LOG_ERROR("Plus is not built with Clarius support");
941  commandExecutionStatus = PLUS_FAIL;
942 #endif
943  }
944  else
945  {
946  LOG_ERROR("Unknown command: " << command);
947  client->Disconnect();
948  commandExecutionStatus = PLUS_FAIL;
949  }
950  if (commandExecutionStatus == PLUS_SUCCESS)
951  {
952  std::string replyMessage;
953  std::string errorMessage;
954  bool didTimeout;
955  igtl::MessageBase::MetaDataMap parameters;
956  if (ReceiveAndPrintReply(client, didTimeout, replyMessage, errorMessage, parameters) != PLUS_SUCCESS)
957  {
958  processReturnValue = EXIT_FAILURE;
959  }
960  }
961  else
962  {
963  // command execution failed
964  processReturnValue = EXIT_FAILURE;
965  }
966  if (!keepConnected)
967  {
968  // we don't need to remain connected if a command has been executed
969  StopClientRequested = true;
970  }
971  }
972 
973  // Run automatic tests
974  if (runTests)
975  {
976  if (RunTests(client) != PLUS_SUCCESS)
977  {
978  processReturnValue = EXIT_FAILURE;
979  }
980  // we don't need to remain connected if tests have been executed
981  StopClientRequested = true;
982  }
983 
984  // Remain connected until the user requests to stop
985  if (!StopClientRequested)
986  {
987  std::cout << "Press Ctrl-C to quit:" << std::endl;
988  // Set up signal catching
989  signal(SIGINT, SignalInterruptHandler);
990  // Run client until requested
991  const double commandQueuePollIntervalSec = 0.010;
992  while (!StopClientRequested)
993  {
994  // the customized client logs the transformation matrices in the data receiver thread
995  vtkIGSIOAccurateTimer::DelayWithEventProcessing(commandQueuePollIntervalSec);
996  }
997  }
998 
999  client->Disconnect();
1000  StopPlusServerProcess(plusServerProcess);
1001  return processReturnValue;
1002 }
PlusStatus ExecuteSendText(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, const std::string &text, bool responseExpected, int commandId)
PlusStatus ExecuteStartTDATA(vtkPlusOpenIGTLinkClient *client, int commandId)
PlusStatus ExecuteStartReconstruction(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, int commandId)
virtual PlusStatus WriteConfiguration(vtkXMLDataElement *aConfig)
static bool StopClientRequested
std::string GetPlusExecutablePath(const std::string &executableName)
This is an abstract superclass for commands in the OpenIGTLink network interface for Plus.
igsioStatus PlusStatus
Definition: PlusCommon.h:40
igtlUint64 SocketReceive(void *data, igtlUint64 length)
#define RETURN_IF_FAIL(cmd)
PlusStatus SendMessage(igtl::MessageBase::Pointer packedMessage)
int main(int argc, char **argv)
for i
PlusStatus RunTests(vtkPlusOpenIGTLinkClient *client)
PlusStatus ExecuteGetPoint(vtkPlusOpenIGTLinkClient *client, const std::string &inputFilename)
#define PLUS_FAIL
Definition: PlusCommon.h:43
PlusStatus ReceiveAndPrintReply(vtkPlusOpenIGTLinkClient *client, bool &didTimeout, std::string &outContent, std::string &outErrorMessage, igtl::MessageBase::MetaDataMap &parameters, int timeoutSec=30)
PlusStatus ExecuteSuspendReconstruction(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, int commandId)
static vtkPlusConfig * GetInstance()
PlusStatus ExecuteStopTDATA(vtkPlusOpenIGTLinkClient *client, int commandId)
PlusStatus StartPlusServerProcess(const std::string &configFile, vtksysProcess *&processPtr)
PlusStatus ExecuteVersion(vtkPlusOpenIGTLinkClient *client, int commandId)
PhidgetLCD_Font int int const char * text
Definition: phidget22.h:4287
static vtkPlusOpenIGTLinkClient * New()
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
PlusStatus ExecuteSuspendAcquisition(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, int commandId)
PlusStatus ExecuteUpdateTransform(vtkPlusOpenIGTLinkClient *client, const std::string &transformName, const std::string &transformValue, const std::string &transformError, const std::string &transformDate, const std::string &transformPersistent, int commandId)
PlusStatus ExecuteGetTransform(vtkPlusOpenIGTLinkClient *client, const std::string &transformName, int commandId)
PlusStatus ExecuteReconstructFromFile(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, const std::string &inputFilename, const std::string &outputFilename, const std::string &outputImageName, int commandId)
PlusStatus ExecuteStopReconstruction(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, const std::string &outputFilename, const std::string &outputImageName, int commandId)
PlusStatus ExecuteSaveConfig(vtkPlusOpenIGTLinkClient *client, const std::string &outputFilename, int commandId)
const char const char * value
Definition: phidget22.h:5111
PlusStatus ExecuteResumeAcquisition(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, int commandId)
PlusStatus ExecuteStartAcquisition(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, std::string outputFilename, bool enableCompression, int commandId)
virtual bool OnMessageReceived(igtl::MessageHeader::Pointer messageHeader)
static vtkIGSIOLogger * Instance()
PlusStatus ExecuteGetChannelIds(vtkPlusOpenIGTLinkClient *client, int commandId)
PlusStatus ExecuteResumeReconstruction(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, int commandId)
This class provides a network interface to access Plus functions as an OpenIGTLink client.
void StopPlusServerProcess(vtksysProcess *&processPtr)
void SignalInterruptHandler(int s)
void PrintCommand(vtkPlusCommand *command)
PlusStatus ExecuteGetSnapshotReconstruction(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, const std::string &outputFilename, const std::string &outputImageName, int commandId)
vtkStandardNewMacro(vtkPlusOpenIGTLinkClientWithTransformLogging)
PlusStatus ExecuteStopAcquisition(vtkPlusOpenIGTLinkClient *client, const std::string &deviceId, std::string outputFilename, int commandId)
PlusStatus ReceiveReply(PlusStatus &result, int32_t &outOriginalCommandId, std::string &outErrorString, std::string &outContent, igtl::MessageBase::MetaDataMap &outParameters, std::string &outCommandName, double timeoutSec=0)
PlusStatus ExecuteGetDeviceIds(vtkPlusOpenIGTLinkClient *client, const std::string &deviceType, int commandId)
PlusStatus SendCommand(vtkPlusCommand *command)