sick_scan_common_tcp.cpp
Go to the documentation of this file.
1 
50 #ifdef _MSC_VER
51 #pragma warning(disable: 4996)
52 #pragma warning(disable: 4267)
53 #pragma warning(disable: 4101) // C4101: "e" : Unreferenzierte lokale Variable
54 #define _WIN32_WINNT 0x0501
55 
56 #endif
57 
59 #include <sick_scan/tcp/colaa.hpp>
60 #include <sick_scan/tcp/colab.hpp>
61 
62 #include <boost/asio.hpp>
63 #include <boost/lambda/lambda.hpp>
64 #include <algorithm>
65 #include <iterator>
66 #include <boost/lexical_cast.hpp>
67 #include <vector>
69 
70 #ifdef _MSC_VER
71 #include "sick_scan/rosconsole_simu.hpp"
72 #endif
73 
74 std::vector<unsigned char> exampleData(65536);
75 std::vector<unsigned char> receivedData(65536);
76 static long receivedDataLen = 0;
78 {
79 #ifdef _MSC_VER
80 #undef ERROR
81  return(2);
82 #else
83  return(diagnostic_msgs::DiagnosticStatus::ERROR);
84 #endif
85 }
86 namespace sick_scan
87 {
88  bool emulateReply(UINT8*requestData, int requestLen, std::vector<unsigned char>* replyVector)
89  {
90  std::string request;
91  std::string reply;
92  std::vector<std::string> keyWordList;
93  std::vector<std::string> answerList;
94 
95  keyWordList.push_back("sMN SetAccessMode");
96  answerList.push_back("sAN SetAccessMode 1");
97 
98  keyWordList.push_back("sWN EIHstCola");
99  answerList.push_back("sWA EIHstCola");
100 
101  keyWordList.push_back("sRN FirmwareVersion");
102  answerList.push_back("sRA FirmwareVersion 8 1.0.0.0R");
103 
104  keyWordList.push_back("sRN OrdNum");
105  answerList.push_back("sRA OrdNum 7 1234567");
106 
107  keyWordList.push_back("sWN TransmitTargets 1");
108  answerList.push_back("sWA TransmitTargets");
109 
110  keyWordList.push_back("sWN TransmitObjects 1");
111  answerList.push_back("sWA TransmitObjects");
112 
113  keyWordList.push_back("sWN TCTrackingMode 0");
114  answerList.push_back("sWA TCTrackingMode");
115 
116  keyWordList.push_back("sRN SCdevicestate");
117  answerList.push_back("sRA SCdevicestate 1");
118 
119  keyWordList.push_back("sRN DItype");
120  answerList.push_back("sRA DItype D RMS3xx-xxxxxx");
121 
122  keyWordList.push_back("sRN ODoprh");
123  answerList.push_back("sRA ODoprh 451");
124 
125  keyWordList.push_back("sMN mSCloadappdef");
126  answerList.push_back("sAN mSCloadappdef");
127 
128 
129  keyWordList.push_back("sRN SerialNumber");
130  answerList.push_back("sRA SerialNumber 8 18020073");
131 
132  keyWordList.push_back("sMN Run");
133  answerList.push_back("sAN Run 1s");
134 
135  keyWordList.push_back("sRN ODpwrc");
136  answerList.push_back("sRA ODpwrc 20");
137 
138  keyWordList.push_back("sRN LocationName");
139  answerList.push_back("sRA LocationName B not defined");
140 
141  keyWordList.push_back("sEN LMDradardata 1");
142  answerList.push_back("sEA LMDradardata 1");
143 
144  for (int i = 0; i < requestLen; i++)
145  {
146  request += (char)requestData[i];
147  }
148  for (int i = 0; i < keyWordList.size(); i++)
149  {
150  if (request.find(keyWordList[i]) != std::string::npos)
151  {
152  reply = (char)0x02;
153  reply += answerList[i];
154  reply += (char)0x03;
155  }
156  }
157 
158  replyVector->clear();
159  for (int i = 0; i < reply.length(); i++)
160  {
161  replyVector->push_back((unsigned char)reply[i]);
162  }
163 
164 
165  return(true);
166  }
167 
168 
169 
170  SickScanCommonTcp::SickScanCommonTcp(const std::string &hostname, const std::string &port, int &timelimit, SickGenericParser* parser, char cola_dialect_id)
171  :
172  SickScanCommon(parser),
173  socket_(io_service_),
174  deadline_(io_service_),
175  hostname_(hostname),
176  port_(port),
177  timelimit_(timelimit)
178  {
179 
180  setEmulSensor(false);
181  if ((cola_dialect_id == 'a') || (cola_dialect_id == 'A'))
182  {
183  this->setProtocolType(CoLa_A);
184  }
185 
186  if ((cola_dialect_id == 'b') || (cola_dialect_id == 'B'))
187  {
188  this->setProtocolType(CoLa_B);
189  }
190 
191  assert(this->getProtocolType() != CoLa_Unknown);
192 
195  this->setReplyMode(0);
196  // io_service_.setReadCallbackFunction(boost::bind(&SopasDevice::readCallbackFunction, this, _1, _2));
197 
198  // Set up the deadline actor to implement timeouts.
199  // Based on blocking TCP example on:
200  // http://www.boost.org/doc/libs/1_46_0/doc/html/boost_asio/example/timeouts/blocking_tcp_client.cpp
201  deadline_.expires_at(boost::posix_time::pos_infin);
202  checkDeadline();
203 
204  }
205 
207  {
208  // stop_scanner();
209  close_device();
210  }
211 
212  using boost::asio::ip::tcp;
213  using boost::lambda::var;
214  using boost::lambda::_1;
215 
216 
218  {
219 
220  }
221 
223  {
224  if (obj != NULL)
225  {
227  }
228  }
229 
230  void SickScanCommonTcp::readCallbackFunctionS(void* obj, UINT8* buffer, UINT32& numOfBytes)
231  {
232  ((SickScanCommonTcp*)obj)->readCallbackFunction(buffer, numOfBytes);
233  }
234 
235 
237  {
238  m_replyMode = _mode;
239  }
241  {
242  return(m_replyMode);
243  }
244 
245 #if 0
246  void SickScanCommonTcp::setProtocolType(char cola_dialect_id)
247  {
248  if ((cola_dialect_id == 'a') || (cola_dialect_id == 'A'))
249  {
250  this->m_protocol = CoLa_A;
251  }
252  else
253  {
254  this->m_protocol = CoLa_B;
255  }
256  }
257 #endif
258 
263  void SickScanCommonTcp::setEmulSensor(bool _emulFlag)
264  {
265  m_emulSensor = _emulFlag;
266  }
267 
274  {
275  return(m_emulSensor);
276  }
277 
278  //
279  // Look for 23-frame (STX/ETX) in receive buffer.
280  // Move frame to start of buffer
281  //
282  // Return: 0 : No (complete) frame found
283  // >0 : Frame length
284  //
286  {
287  UINT32 frameLen = 0;
288  UINT32 i;
289 
290  // Depends on protocol...
291  if (getProtocolType() == CoLa_A)
292  {
293  //
294  // COLA-A
295  //
296  // Must start with STX (0x02)
297  if (m_receiveBuffer[0] != 0x02)
298  {
299  // Look for starting STX (0x02)
300  for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
301  {
302  if (m_receiveBuffer[i] == 0x02)
303  {
304  break;
305  }
306  }
307 
308  // Found beginning of frame?
309  if (i >= m_numberOfBytesInReceiveBuffer)
310  {
311  // No start found, everything can be discarded
312  m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
313  return SopasEventMessage(); // No frame found
314  }
315 
316  // Move frame start to index 0
317  UINT32 newLen = m_numberOfBytesInReceiveBuffer - i;
318  memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), newLen);
319  m_numberOfBytesInReceiveBuffer = newLen;
320  }
321 
322  // Look for ending ETX (0x03)
323  for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
324  {
325  if (m_receiveBuffer[i] == 0x03)
326  {
327  break;
328  }
329  }
330 
331  // Found end?
332  if (i >= m_numberOfBytesInReceiveBuffer)
333  {
334  // No end marker found, so it's not a complete frame (yet)
335  return SopasEventMessage(); // No frame found
336  }
337 
338  // Calculate frame length in byte
339  frameLen = i + 1;
340 
341  return SopasEventMessage(m_receiveBuffer, CoLa_A, frameLen);
342  }
343  else if (getProtocolType() == CoLa_B)
344  {
345  UINT32 magicWord;
346  UINT32 payloadlength;
347 
349  {
350  return SopasEventMessage();
351  }
352  UINT16 pos = 0;
353  magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
354  if (magicWord != 0x02020202)
355  {
356  // Look for starting STX (0x02020202)
357  for (i = 1; i <= m_numberOfBytesInReceiveBuffer - 4; i++)
358  {
359  pos = i; // this is needed, as the position value is updated by getIntegerFromBuffer
360  magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
361  if (magicWord == 0x02020202)
362  {
363  // found magic word
364  break;
365  }
366  }
367 
368  // Found beginning of frame?
369  if (i > m_numberOfBytesInReceiveBuffer - 4)
370  {
371  // No start found, everything can be discarded
372  m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
373  return SopasEventMessage(); // No frame found
374  }
375  else
376  {
377  // Move frame start to index
378  UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - i;
379  memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), bytesToMove); // payload+magic+length+s+checksum
380  m_numberOfBytesInReceiveBuffer = bytesToMove;
381  }
382  }
383 
384  // Pruefe Laenge des Pufferinhalts
386  {
387  // Es sind nicht genug Daten fuer einen Frame
388  printInfoMessage("SickScanCommonNw::findFrameInReceiveBuffer: Frame cannot be decoded yet, only " +
389  ::toString(m_numberOfBytesInReceiveBuffer) + " bytes in the buffer.", m_beVerbose);
390  return SopasEventMessage();
391  }
392 
393  // Read length of payload
394  pos = 4;
395  payloadlength = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
396  printInfoMessage("SickScanCommonNw::findFrameInReceiveBuffer: Decoded payload length is " + ::toString(payloadlength) + " bytes.", m_beVerbose);
397 
398  // Ist die Datenlaenge plausibel und wuede in den Puffer passen?
399  if (payloadlength > (sizeof(m_receiveBuffer) - 9))
400  {
401  // magic word + length + checksum = 9
402  printWarning("SickScanCommonNw::findFrameInReceiveBuffer: Frame too big for receive buffer. Frame discarded with length:"
403  + ::toString(payloadlength) + ".");
405  return SopasEventMessage();
406  }
407  if ((payloadlength + 9) > m_numberOfBytesInReceiveBuffer)
408  {
409  // magic word + length + s + checksum = 10
410  printInfoMessage("SickScanCommonNw::findFrameInReceiveBuffer: Frame not complete yet. Waiting for the rest of it (" +
411  ::toString(payloadlength + 9 - m_numberOfBytesInReceiveBuffer) + " bytes missing).", m_beVerbose);
412  return SopasEventMessage(); // frame not complete
413  }
414 
415  // Calculate the total frame length in bytes: Len = Frame (9 bytes) + Payload
416  frameLen = payloadlength + 9;
417 
418  //
419  // test checksum of payload
420  //
421  UINT8 temp = 0;
422  UINT8 temp_xor = 0;
423  UINT8 checkSum;
424 
425  // Read original checksum
426  pos = frameLen - 1;
427  checkSum = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
428 
429  // Erzeuge die Pruefsumme zum Vergleich
430  for (UINT16 i = 8; i < (frameLen - 1); i++)
431  {
432  pos = i;
433  temp = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
434  temp_xor = temp_xor ^ temp;
435  }
436 
437  // Vergleiche die Pruefsummen
438  if (temp_xor != checkSum)
439  {
440  printWarning("SickScanCommonNw::findFrameInReceiveBuffer: Wrong checksum, Frame discarded.");
442  return SopasEventMessage();
443  }
444 
445  return SopasEventMessage(m_receiveBuffer, CoLa_B, frameLen);
446  }
447 
448  // Return empty frame
449  return SopasEventMessage();
450  }
451 
452 
453 
460  {
461 
462  if (getProtocolType() == CoLa_A)
463  {
464  printInfoMessage("SickScanCommonNw::processFrame: Calling processFrame_CoLa_A() with " + ::toString(frame.size()) + " bytes.", m_beVerbose);
465  // processFrame_CoLa_A(frame);
466  }
467  else if (getProtocolType() == CoLa_B)
468  {
469  printInfoMessage("SickScanCommonNw::processFrame: Calling processFrame_CoLa_B() with " + ::toString(frame.size()) + " bytes.", m_beVerbose);
470  // processFrame_CoLa_B(frame);
471  }
472 
473  // Push frame to recvQueue
474 
475  DatagramWithTimeStamp dataGramWidthTimeStamp(timeStamp, std::vector<unsigned char>(frame.getRawData(), frame.getRawData() + frame.size()));
476  // recvQueue.push(std::vector<unsigned char>(frame.getRawData(), frame.getRawData() + frame.size()));
477  recvQueue.push(dataGramWidthTimeStamp);
478  }
479 
481  {
482  ros::Time rcvTimeStamp = ros::Time::now(); // stamp received datagram
483  bool beVerboseHere = false;
484  printInfoMessage("SickScanCommonNw::readCallbackFunction(): Called with " + toString(numOfBytes) + " available bytes.", beVerboseHere);
485 
486  ScopedLock lock(&m_receiveDataMutex); // Mutex for access to the input buffer
487  UINT32 remainingSpace = sizeof(m_receiveBuffer) - m_numberOfBytesInReceiveBuffer;
488  UINT32 bytesToBeTransferred = numOfBytes;
489  if (remainingSpace < numOfBytes)
490  {
491  bytesToBeTransferred = remainingSpace;
492  // printWarning("SickScanCommonNw::readCallbackFunction(): Input buffer space is to small, transferring only " +
493  // ::toString(bytesToBeTransferred) + " of " + ::toString(numOfBytes) + " bytes.");
494  }
495  else
496  {
497  // printInfoMessage("SickScanCommonNw::readCallbackFunction(): Transferring " + ::toString(bytesToBeTransferred) +
498  // " bytes from TCP to input buffer.", beVerboseHere);
499  }
500 
501  if (bytesToBeTransferred > 0)
502  {
503  // Data can be transferred into our input buffer
504  memcpy(&(m_receiveBuffer[m_numberOfBytesInReceiveBuffer]), buffer, bytesToBeTransferred);
505  m_numberOfBytesInReceiveBuffer += bytesToBeTransferred;
506 
507  UINT32 size = 0;
508 
509  while (1)
510  {
511  // Now work on the input buffer until all received datasets are processed
513 
514  size = frame.size();
515  if (size == 0)
516  {
517  // Framesize = 0: There is no valid frame in the buffer. The buffer is either empty or the frame
518  // is incomplete, so leave the loop
519  printInfoMessage("SickScanCommonNw::readCallbackFunction(): No complete frame in input buffer, we are done.", beVerboseHere);
520 
521  // Leave the loop
522  break;
523  }
524  else
525  {
526  // A frame was found in the buffer, so process it now.
527  printInfoMessage("SickScanCommonNw::readCallbackFunction(): Processing a frame of length " + ::toString(frame.size()) + " bytes.", beVerboseHere);
528  processFrame(rcvTimeStamp, frame);
529  UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - size;
530  memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[size]), bytesToMove); // payload+magic+length+s+checksum
531  m_numberOfBytesInReceiveBuffer = bytesToMove;
532 
533  }
534  }
535  }
536  else
537  {
538  // There was input data from the TCP interface, but our input buffer was unable to hold a single byte.
539  // Either we have not read data from our buffer for a long time, or something has gone wrong. To re-sync,
540  // we clear the input buffer here.
542  }
543  }
544 
545 
547  {
548  int portInt;
549  sscanf(port_.c_str(), "%d", &portInt);
550  m_nw.init(hostname_, portInt, disconnectFunctionS, (void*)this);
552  if (this->getEmulSensor())
553  {
554  ROS_INFO("Sensor emulation is switched on - network traffic is switched off.");
555  } else
556  {
557  m_nw.connect();
558  }
559  return ExitSuccess;
560  }
561 
563  {
564  ROS_WARN("Disconnecting TCP-Connection.");
565  m_nw.disconnect();
566  return 0;
567  }
568 
569 
571  {
572  stop_scanner();
573  return(true);
574  }
575 
576  void SickScanCommonTcp::handleRead(boost::system::error_code error, size_t bytes_transfered)
577  {
578  ec_ = error;
579  bytes_transfered_ += bytes_transfered;
580  }
581 
582 
584  {
585  if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now())
586  {
587  // The reason the function is called is that the deadline expired. Close
588  // the socket to return all IO operations and reset the deadline
589  socket_.close();
590  deadline_.expires_at(boost::posix_time::pos_infin);
591  }
592 
593  // Nothing bad happened, go back to sleep
594  deadline_.async_wait(boost::bind(&SickScanCommonTcp::checkDeadline, this));
595  }
596 
597 
599  {
600  this->recvQueue.getNumberOfEntriesInQueue();
601  }
602 
603  int SickScanCommonTcp::readWithTimeout(size_t timeout_ms, char *buffer, int buffer_size, int *bytes_read, bool *exception_occured, bool isBinary)
604  {
605  // Set up the deadline to the proper timeout, error and delimiters
606  deadline_.expires_from_now(boost::posix_time::milliseconds(timeout_ms));
607  const char end_delim = static_cast<char>(0x03);
608  int dataLen = 0;
609  ec_ = boost::asio::error::would_block;
610  bytes_transfered_ = 0;
611 
612  size_t to_read;
613 
614  int numBytes = 0;
615  // Polling - should be changed to condition variable in the future
616  int waitingTimeInMs = 1; // try to lookup for new incoming packages
617  int i;
618  for (i = 0; i < timeout_ms; i += waitingTimeInMs)
619  {
620  if (false == this->recvQueue.isQueueEmpty())
621  {
622  break;
623  }
624  boost::this_thread::sleep(boost::posix_time::milliseconds(waitingTimeInMs));
625  }
626  if (i >= timeout_ms)
627  {
628  ROS_ERROR("no answer received after %zu ms. Maybe sopas mode is wrong.\n",timeout_ms);
629  return(ExitError);
630  }
632  DatagramWithTimeStamp datagramWithTimeStamp = this->recvQueue.pop();
633 
634  *bytes_read = datagramWithTimeStamp.datagram.size();
635  memcpy(buffer, &(datagramWithTimeStamp.datagram[0]), datagramWithTimeStamp.datagram.size());
636  return(ExitSuccess);
637  }
638 
642  int SickScanCommonTcp::sendSOPASCommand(const char* request, std::vector<unsigned char> * reply, int cmdLen)
643  {
644 #if 0
645  if (!socket_.is_open()) {
646  ROS_ERROR("sendSOPASCommand: socket not open");
647  diagnostics_.broadcast(getDiagnosticErrorCode(), "sendSOPASCommand: socket not open.");
648  return ExitError;
649  }
650 #endif
651  int sLen = 0;
652  int preambelCnt = 0;
653  bool cmdIsBinary = false;
654 
655  if (request != NULL)
656  {
657  sLen = cmdLen;
658  preambelCnt = 0; // count 0x02 bytes to decide between ascii and binary command
659  if (sLen >= 4)
660  {
661  for (int i = 0; i < 4; i++) {
662  if (request[i] == 0x02)
663  {
664  preambelCnt++;
665  }
666  }
667  }
668 
669  if (preambelCnt < 4) {
670  cmdIsBinary = false;
671  }
672  else
673  {
674  cmdIsBinary = true;
675  }
676  int msgLen = 0;
677  if (cmdIsBinary == false)
678  {
679  msgLen = strlen(request);
680  }
681  else
682  {
683  int dataLen = 0;
684  for (int i = 4; i < 8; i++)
685  {
686  dataLen |= ((unsigned char)request[i] << (7 - i) * 8);
687  }
688  msgLen = 8 + dataLen + 1; // 8 Msg. Header + Packet +
689  }
690 #if 1
691  if (getEmulSensor())
692  {
693  emulateReply((UINT8*)request, msgLen, reply);
694  }
695  else
696  {
697  bool debugBinCmd = false;
698  if (debugBinCmd)
699  {
700  printf("=== START HEX DUMP ===\n");
701  for (int i = 0; i < msgLen; i++)
702  {
703  unsigned char *ptr = (UINT8*)request;
704  printf("%02x ", ptr[i]);
705  }
706  printf("\n=== END HEX DUMP ===\n");
707  }
708  m_nw.sendCommandBuffer((UINT8*)request, msgLen);
709  }
710 #else
711 
712  /*
713  * Write a SOPAS variable read request to the device.
714  */
715  try
716  {
717  boost::asio::write(socket_, boost::asio::buffer(request, msgLen));
718  }
719  catch (boost::system::system_error &e)
720  {
721  ROS_ERROR("write error for command: %s", request);
722  diagnostics_.broadcast(getDiagnosticErrorCode(), "Write error for sendSOPASCommand.");
723  return ExitError;
724  }
725 #endif
726  }
727 
728  // Set timeout in 5 seconds
729  const int BUF_SIZE = 65536;
730  char buffer[BUF_SIZE];
731  int bytes_read;
732  // !!!
733  if (getEmulSensor())
734  {
735 
736  }
737  else
738  {
739  if (readWithTimeout(getReadTimeOutInMs(), buffer, BUF_SIZE, &bytes_read, 0, cmdIsBinary) == ExitError)
740  {
741  ROS_INFO_THROTTLE(1.0, "sendSOPASCommand: no full reply available for read after %d ms",getReadTimeOutInMs());
742  diagnostics_.broadcast(getDiagnosticErrorCode(), "sendSOPASCommand: no full reply available for read after timeout.");
743  return ExitError;
744  }
745 
746 
747  if (reply)
748  {
749  reply->resize(bytes_read);
750 
751  std::copy(buffer, buffer + bytes_read, &(*reply)[0]);
752  }
753  }
754  return ExitSuccess;
755  }
756 
757 
758  int SickScanCommonTcp::get_datagram(ros::Time &recvTimeStamp, unsigned char *receiveBuffer, int bufferSize, int *actual_length,
759  bool isBinaryProtocol, int *numberOfRemainingFifoEntries)
760  {
761  if (NULL != numberOfRemainingFifoEntries)
762  {
763  *numberOfRemainingFifoEntries = 0;
764  }
765  this->setReplyMode(1);
766 
767  if (this->getEmulSensor())
768  {
769  // boost::this_thread::sleep(boost::posix_time::milliseconds(waitingTimeInMs));
770  ros::Time timeStamp = ros::Time::now();
771  uint32_t nanoSec = timeStamp.nsec;
772  double waitTime10Hz = 10.0 * (double)nanoSec / 1E9; // 10th of sec. [0..10[
773 
774  uint32_t waitTime = (int)waitTime10Hz ; // round down
775 
776  double waitTimeUntilNextTime10Hz = 1/10.0 * (1.0 - (waitTime10Hz - waitTime));
777 
778  ros::Duration(waitTimeUntilNextTime10Hz).sleep();
779  SickScanRadar radar(this);
780  radar.setEmulation(true);
781  radar.simulateAsciiDatagram(receiveBuffer, actual_length);
782  recvTimeStamp = ros::Time::now();
783  }
784  else
785  {
786  const int maxWaitInMs = getReadTimeOutInMs();
787  std::vector<unsigned char> dataBuffer;
788 #if 1 // prepared for reconnect
789  bool retVal = this->recvQueue.waitForIncomingObject(maxWaitInMs);
790  if (retVal == false)
791  {
792  ROS_WARN("Timeout during waiting for new datagram");
793  return ExitError;
794  }
795  else
796  {
797  // Look into receiving queue for new Datagrams
798  //
799  //
800  DatagramWithTimeStamp datagramWithTimeStamp = this->recvQueue.pop();
801  if (NULL != numberOfRemainingFifoEntries)
802  {
803  *numberOfRemainingFifoEntries = this->recvQueue.getNumberOfEntriesInQueue();
804  }
805  recvTimeStamp = datagramWithTimeStamp.timeStamp;
806  dataBuffer = datagramWithTimeStamp.datagram;
807 
808  }
809 #endif
810  // dataBuffer = this->recvQueue.pop();
811  long size = dataBuffer.size();
812  memcpy(receiveBuffer, &(dataBuffer[0]), size);
813  *actual_length = size;
814  }
815 
816 #if 0
817  static int cnt = 0;
818  char szFileName[255];
819  sprintf(szFileName, "/tmp/dg%06d.bin", cnt++);
820 
821  FILE *fout;
822 
823  fout = fopen(szFileName, "wb");
824  if (fout != NULL)
825  {
826  fwrite(receiveBuffer, size, 1, fout);
827  fclose(fout);
828  }
829 #endif
830  return ExitSuccess;
831 
832  if (!socket_.is_open()) {
833  ROS_ERROR("get_datagram: socket not open");
834  diagnostics_.broadcast(getDiagnosticErrorCode(), "get_datagram: socket not open.");
835  return ExitError;
836  }
837 
838  /*
839  * Write a SOPAS variable read request to the device.
840  */
841  std::vector<unsigned char> reply;
842 
843  // Wait at most 5000ms for a new scan
844  size_t timeout = 30000;
845  bool exception_occured = false;
846 
847  char *buffer = reinterpret_cast<char *>(receiveBuffer);
848 
849  if (readWithTimeout(timeout, buffer, bufferSize, actual_length, &exception_occured, isBinaryProtocol) != ExitSuccess)
850  {
851  ROS_ERROR_THROTTLE(1.0, "get_datagram: no data available for read after %zu ms", timeout);
852  diagnostics_.broadcast(getDiagnosticErrorCode(), "get_datagram: no data available for read after timeout.");
853 
854  // Attempt to reconnect when the connection was terminated
855  if (!socket_.is_open())
856  {
857 #ifdef _MSC_VER
858  Sleep(1000);
859 #else
860  sleep(1);
861 #endif
862  ROS_INFO("Failure - attempting to reconnect");
863  return init();
864  }
865 
866  return exception_occured ? ExitError : ExitSuccess; // keep on trying
867  }
868 
869  return ExitSuccess;
870  }
871 
872 } /* namespace sick_scan */
SickScanCommonTcp(const std::string &hostname, const std::string &port, int &timelimit, SickGenericParser *parser, char cola_dialect_id)
std::vector< unsigned char > exampleData(65536)
uint16_t UINT16
int getReadTimeOutInMs()
get timeout in milliseconds
bool emulateReply(UINT8 *requestData, int requestLen, std::vector< unsigned char > *replyVector)
bool init(std::string ipAddress, unsigned short portNumber, Tcp::DisconnectFunction disconnectFunction, void *obj)
boost::asio::ip::tcp::socket socket_
static int getDiagnosticErrorCode()
void sendCommandBuffer(UINT8 *buffer, UINT16 len)
virtual int get_datagram(ros::Time &recvTimeStamp, unsigned char *receiveBuffer, int bufferSize, int *actual_length, bool isBinaryProtocol, int *numberOfRemainingFifoEntries)
Read a datagram from the device.
bool getEmulSensor()
get emulation flag (using emulation instead of "real" scanner - currently implemented for radar ...
bool sleep() const
static void readCallbackFunctionS(void *obj, UINT8 *buffer, UINT32 &numOfBytes)
#define printInfoMessage(a, b)
uint32_t UINT32
bool setReadCallbackFunction(Tcp::ReadFunction readFunction, void *obj)
#define ROS_WARN(...)
virtual int sendSOPASCommand(const char *request, std::vector< unsigned char > *reply, int cmdLen)
Send a SOPAS command to the device and print out the response to the console.
Command Language ASCI.
static void disconnectFunctionS(void *obj)
UINT32 size() const
BYTE * getRawData()
get SOPAS raw data include header and CRC
diagnostic_updater::Updater diagnostics_
int getProtocolType(void)
get protocol type as enum
#define ROS_INFO_THROTTLE(period,...)
Queue< DatagramWithTimeStamp > recvQueue
void setProtocolType(SopasProtocol cola_dialect_id)
set protocol type as enum
#define ROS_INFO(...)
void simulateAsciiDatagram(unsigned char *receiveBuffer, int *actual_length)
#define ROS_ERROR_THROTTLE(period,...)
std::vector< unsigned char > datagram
Command Language binary.
boost::asio::deadline_timer deadline_
UINT32 m_numberOfBytesInReceiveBuffer
Number of bytes in buffer.
void readCallbackFunction(UINT8 *buffer, UINT32 &numOfBytes)
Unknown Command Language.
boost::system::error_code ec_
static long receivedDataLen
void processFrame(ros::Time timeStamp, SopasEventMessage &frame)
Class that represents a message that was sent by a sensor. (Event message)
std::string toString(INT32 value)
Definition: toolbox.cpp:275
virtual int init()
init routine of scanner
bool connect()
Connects to a sensor via tcp and reads the device name.
bool disconnect()
Closes the connection to the LMS. This is the opposite of init().
static Time now()
SopasEventMessage findFrameInReceiveBuffer()
virtual int stop_scanner()
Stops sending scan data.
Mutex m_receiveDataMutex
Access mutex for buffer.
void broadcast(int lvl, const std::string msg)
void setEmulSensor(bool _emulFlag)
Set emulation flag (using emulation instead of "real" scanner - currently implemented for radar...
UINT8 m_receiveBuffer[480000]
Low-Level receive buffer for all data.
std::vector< unsigned char > receivedData(65536)
#define ROS_ERROR(...)
int readWithTimeout(size_t timeout_ms, char *buffer, int buffer_size, int *bytes_read=0, bool *exception_occured=0, bool isBinary=false)
void printWarning(std::string message)
void handleRead(boost::system::error_code error, size_t bytes_transfered)
uint8_t UINT8


sick_scan
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Tue Jul 9 2019 04:55:32