Medical Imaging Interaction Toolkit  2018.4.99-a3d2e8fb
Medical Imaging Interaction Toolkit
mitkQuantelLaser.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkQuantelLaser.h"
14 
15 #include <chrono>
16 #include <thread>
17 #include <mutex>
18 
19 #include <tinyxml.h>
20 
21 #include <usModuleContext.h>
22 #include <usGetModuleContext.h>
23 
24 const unsigned char CR = 0xD; // == '\r' - carriage return
25 const unsigned char LF = 0xA; // == '\n' - line feed
26 
28  m_State(mitk::QuantelLaser::UNCONNECTED),
29  m_FlashlampRunning(false),
30  m_ShutterOpen(false),
31  m_LaserEmission(false),
32  m_DeviceName(),
33  m_PortNumber(mitk::SerialCommunication::COM6),
34  m_BaudRate(mitk::SerialCommunication::BaudRate115200),
35  m_DataBits(mitk::SerialCommunication::DataBits8),
36  m_Parity(mitk::SerialCommunication::None),
37  m_StopBits(mitk::SerialCommunication::StopBits1),
38  m_HardwareHandshake(mitk::SerialCommunication::HardwareHandshakeOff),
39  m_SerialCommunication(nullptr),
40  m_StayAliveMessageThread(),
41  m_SerialCommunicationMutex()
42 {
43 }
44 
46 {
47  /* stop tracking and disconnect from tracking device */
48  if ((GetState() == STATE3) || (GetState() == STATE4) || (GetState() == STATE5) || (GetState() == STATE6))
49  {
50  this->StopQswitching();
51  this->StopFlashing();
52  }
53  if (GetState() == STATE2)
54  {
55  this->CloseConnection();
56  }
57  /* cleanup stay alive thread */
58  if (m_StayAliveMessageThread.joinable())
60 
61  /* free serial communication interface */
62  if (m_SerialCommunication.IsNotNull())
63  {
64  m_SerialCommunication->ClearReceiveBuffer();
65  m_SerialCommunication->ClearSendBuffer();
66  m_SerialCommunication->CloseConnection();
67  m_SerialCommunication = nullptr;
68  }
69 }
70 
71 std::string mitk::QuantelLaser::SendAndReceiveLine(const std::string* input, std::string* answer)
72 {
73  MITK_INFO << "[Quantel Laser Debug] sending: " << input->c_str();
74  if (input == nullptr)
75  return "SERIALSENDERROR";
76 
77  std::string message;
78 
79  message = *input + '\n';
80 
81  // Clear send buffer
82  m_SerialCommunication->ClearSendBuffer();
83  m_SerialCommunication->Send(message);
84  std::this_thread::sleep_for(std::chrono::milliseconds(50));
85  std::string m;
86  do
87  {
88  long returnvalue = m_SerialCommunication->Receive(m, 1);
89  if ((returnvalue == 0) || (m.size() != 1))
90  return "SERIALRECEIVEERROR";
91  *answer += m;
92  } while (m.at(0) != LF);
93  m_SerialCommunication->ClearReceiveBuffer();
94  std::this_thread::sleep_for(std::chrono::milliseconds(100));
95  m_SerialCommunication->ClearReceiveBuffer();
96  MITK_INFO << "[Quantel Laser Debug] received: " << answer->c_str();
97  return "OK";
98 }
99 
100 void mitk::QuantelLaser::LoadResorceFile(std::string filename, std::string* lines)
101 {
102  us::ModuleResource resorceFile = us::GetModuleContext()->GetModule()->GetResource(filename);
103  std::string line;
104  if (resorceFile.IsValid() && resorceFile.IsFile())
105  {
106  us::ModuleResourceStream stream(resorceFile);
107  while (std::getline(stream, line))
108  {
109  *lines = *lines + line + "\n";
110  }
111  }
112  else
113  {
114  MITK_ERROR << "[Quantel Laser Debug] Resource file was not valid";
115  }
116 }
117 
118 bool mitk::QuantelLaser::OpenConnection(std::string configurationFile)
119 {
120  LoadResorceFile(configurationFile + ".xml", &m_XmlPumpLaserConfiguration);
121  TiXmlDocument xmlDoc;
122 
123  if (xmlDoc.Parse(m_XmlPumpLaserConfiguration.c_str(), 0, TIXML_ENCODING_UTF8))
124  {
125  TiXmlElement* root = xmlDoc.FirstChildElement("PumpLaser");
126  if (root)
127  {
128  TiXmlElement* elementNode = root->FirstChildElement("Seriell");
129  TiXmlElement* element = elementNode->FirstChildElement("PortNumber");
130  m_PortNumber = mitk::SerialCommunication::PortNumber(std::stoi(element->GetText()));
131  element = elementNode->FirstChildElement("Baud");
132  m_BaudRate = mitk::SerialCommunication::BaudRate(std::stoi(element->GetText()));
133 
135  }
136  }
137  else
138  {
139  MITK_ERROR << "[Quantel Laser Debug] Could not load configuration xml ";
140  return false;
141  }
142 
144 
145  if (m_DeviceName.empty())
146  m_SerialCommunication->SetPortNumber(m_PortNumber);
147  else
148  m_SerialCommunication->SetDeviceName(m_DeviceName);
149 
150  m_SerialCommunication->SetBaudRate(m_BaudRate);
151  m_SerialCommunication->SetDataBits(m_DataBits);
152  m_SerialCommunication->SetParity(m_Parity);
153  m_SerialCommunication->SetStopBits(m_StopBits);
154  m_SerialCommunication->SetSendTimeout(1000);
155  m_SerialCommunication->SetReceiveTimeout(1000);
156  if (m_SerialCommunication->OpenConnection() == 0) // 0 == ERROR_VALUE
157  {
158  m_SerialCommunication->CloseConnection();
159  m_SerialCommunication = nullptr;
160  MITK_ERROR << "[Quantel Laser Debug] " << "Can not open serial port";
161  return false;
162  }
163 
164  if (this->GetState() != UNCONNECTED)
165  {
166  std::string *command = new std::string;
167  std::string answer("");
168  command->assign("STOP");
169  this->SendAndReceiveLine(command, &answer);
170  return true;
171  }
172  else
173  return false;
174 }
175 
177 {
178  if (this->GetState() != UNCONNECTED)
179  {
180  this->StopQswitching();
181  this->StopFlashing();
182 
183  // close the serial connection
184  m_SerialCommunication->CloseConnection();
185  m_SerialCommunication = nullptr;
186  this->GetState();
187  }
188  return true;
189 }
190 
192 {
193  if (m_SerialCommunication == nullptr)
194  {
195  m_State = UNCONNECTED;
196  return m_State;
197  }
198 
199  if (!m_SerialCommunication->IsConnected())
200  {
201  m_State = UNCONNECTED;
202  return m_State;
203  }
204 
205  std::string *command = new std::string;
206  std::string answer("");
207  command->assign("STATE");
208  this->SendAndReceiveLine(command, &answer);
209  MITK_INFO << "[Quantel Laser Debug] get state:" << answer;
210  if (answer == "STATE = 0\n")
211  m_State = STATE0;
212  else if(answer == "STATE = 1\n")
213  {
214  m_State = STATE1;
215  m_FlashlampRunning = false;
216  m_ShutterOpen = false;
217  m_LaserEmission = false;
218  }
219  else if(answer == "STATE = 2\n") // laser ready for RUN
220  {
221  m_State = STATE2;
222  m_FlashlampRunning = false;
223  m_ShutterOpen = false;
224  m_LaserEmission = false;
225  }
226  else if(answer == "STATE = 3\n")
227  {
228  m_State = STATE3;
229  m_FlashlampRunning = true;
230  m_ShutterOpen = false;
231  m_LaserEmission = false;
232  }
233  else if(answer == "STATE = 4\n")
234  {
235  m_State = STATE4;
236  m_FlashlampRunning = true;
237  m_ShutterOpen = false;
238  m_LaserEmission = false;
239  }
240  else if (answer == "STATE = 5\n")
241  {
242  m_State = STATE5;
243  m_FlashlampRunning = true;
244  m_ShutterOpen = true;
245  m_LaserEmission = false;
246  }
247  else if (answer == "STATE = 6\n")
248  {
249  m_State = STATE6;
250  m_FlashlampRunning = true;
251  m_ShutterOpen = true;
252  m_LaserEmission = true;
253  }
254  else if (answer == "STATE = 7\n")
255  {
256  m_State = STATE7;
257  m_FlashlampRunning = true;
258  m_ShutterOpen = true;
259  m_LaserEmission = true;
260  }
261  else
262  {
263  m_State = UNCONNECTED;
264  m_FlashlampRunning = false;
265  m_ShutterOpen = false;
266  m_LaserEmission = false;
267  }
268 
269  return m_State;
270 }
271 
272 
274 {
275  do{
276  std::this_thread::sleep_for(std::chrono::seconds(2));
277  std::string *command = new std::string;
278  std::string answer("");
279  command->assign("STATE");
280  this->SendAndReceiveLine(command, &answer);
281  } while (m_KeepAlive);
282 }
283 
285 {
286  this->GetState();
287  if (!m_FlashlampRunning)
288  {
289  if (m_LaserEmission)
290  this->StopQswitching();
291 
292  std::string *command = new std::string;
293  std::string answer("");
294  command->assign("RUN");
295  this->SendAndReceiveLine(command, &answer);
296  MITK_INFO << answer;
297  if (answer.at(0) == 'O' && answer.at(1) == 'K')
298  {
299  m_FlashlampRunning = true;
300  m_ShutterOpen = false;
301  m_KeepAlive = true;
302  //m_StayAliveMessageThread = std::thread(&mitk::QuantelLaser::StayAlive, this);
303  }
304  else
305  {
306  MITK_ERROR << "[Quantel Laser Debug] " << "Cannot start flashlamps." << " Laser is telling me: " << answer;
307  return false;
308  }
309  }
310  else
311  MITK_INFO << "[Quantel Laser Debug] " << "Flashlamps are already running";
312 
313  return true;
314 }
315 
317 {
318  this->GetState();
319  if (m_FlashlampRunning)
320  {
321  if (m_LaserEmission)
322  this->StopQswitching();
323 
324  std::string *command = new std::string;
325  std::string answer("");
326  command->assign("STOP");
327  this->SendAndReceiveLine(command, &answer);
328  MITK_INFO << answer;
329  if (answer.at(0) == 'O' && answer.at(1) == 'K')
330  {
331  m_FlashlampRunning = false;
332  m_ShutterOpen = false;
333  m_KeepAlive = false;
334  }
335  else
336  {
337  MITK_ERROR << "[Quantel Laser Debug] " << "Cannot Stop flashlamps." << " Laser is telling me: " << answer;
338  return false;
339  }
340 
341  }
342  else
343  MITK_INFO << "[Quantel Laser Debug] " << "Flashlamps are not running";
344 
345  return true;
346 }
347 
349 {
350  this->GetState();
351  if (!m_LaserEmission)
352  {
353  std::string *command = new std::string;
354  std::string answer("");
355  command->assign("QSW 1");
356  this->SendAndReceiveLine(command, &answer);
357  MITK_INFO << answer;
358  if (answer.at(0) == 'O' && answer.at(1) == 'K')
359  {
360  m_FlashlampRunning = true;
361  m_ShutterOpen = true;
362  return true;
363  }
364  else
365  {
366  MITK_ERROR << "[Quantel Laser Debug] " << "Cannot start Qswitch." << " Laser is telling me: " << answer;
367  return false;
368  }
369  }
370  else
371  {
372  MITK_INFO << "[Quantel Laser Debug] " << "Laser is already emitting";
373  return true;
374  }
375 }
376 
378 {
379  this->GetState();
381  {
382  std::string *command = new std::string;
383  std::string answer("");
384  command->assign("QSW 0");
385  this->SendAndReceiveLine(command, &answer);
386  MITK_INFO << answer;
387  if (answer.at(0) == 'O' && answer.at(1) == 'K')
388  {
389  m_LaserEmission = false;
390  }
391  else
392  MITK_ERROR << "[Quantel Laser Debug] " << "Cannot stop Q-switch.";
393 
394  }
395  return true;
396 }
397 
399 {
400  return m_LaserEmission;
401 }
403 {
404  return m_FlashlampRunning;
405 }
virtual bool StopQswitching()
virtual bool CloseConnection()
Closes the connection to the device.
static char * line
Definition: svm.cpp:2870
#define MITK_INFO
Definition: mitkLogMacros.h:18
static Pointer New()
#define MITK_ERROR
Definition: mitkLogMacros.h:20
const unsigned char LF
virtual bool IsFlashing()
std::string m_DeviceName
Device Name.
DataCollection - Class to facilitate loading/accessing structured data.
mitk::SerialCommunication::Pointer m_SerialCommunication
serial communication interface
void LoadResorceFile(std::string filename, std::string *lines)
virtual bool OpenConnection(std::string configurationFile)
Opens a connection to the device.
virtual void StayAlive()
virtual bool StopFlashing()
virtual bool StartQswitching()
Module * GetModule() const
DataBits m_DataBits
Number of Data Bits per token.
serial communication interface
PortNumber m_PortNumber
COM Port Number.
BaudRate m_BaudRate
COM Port Baud Rate.
virtual bool IsEmitting()
StopBits m_StopBits
number of stop bits per token
virtual std::string SendAndReceiveLine(const std::string *input, std::string *answer)
std::string m_XmlPumpLaserConfiguration
std::thread m_StayAliveMessageThread
virtual LaserState GetState()
virtual bool StartFlashing()
Parity m_Parity
Parity mode for communication.
const unsigned char CR
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.