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


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:11