sick_scan_common_tcp.cpp
Go to the documentation of this file.
00001 
00050 #ifdef _MSC_VER
00051 #pragma warning(disable: 4996)
00052 #pragma warning(disable: 4267)
00053 #pragma warning(disable: 4101)   // C4101: "e" : Unreferenzierte lokale Variable
00054 #define _WIN32_WINNT 0x0501
00055 
00056 #endif
00057 
00058 #include <sick_scan/sick_scan_common_tcp.h>
00059 #include <sick_scan/tcp/colaa.hpp>
00060 #include <sick_scan/tcp/colab.hpp>
00061 
00062 #include <boost/asio.hpp>
00063 #include <boost/lambda/lambda.hpp>
00064 #include <algorithm>
00065 #include <iterator>
00066 #include <boost/lexical_cast.hpp>
00067 #include <vector>
00068 #include <sick_scan/sick_generic_radar.h>
00069 
00070 #ifdef _MSC_VER
00071 #include "sick_scan/rosconsole_simu.hpp"
00072 #endif
00073 
00074 std::vector<unsigned char> exampleData(65536);
00075 std::vector<unsigned char> receivedData(65536);
00076 static long receivedDataLen = 0;
00077 static int getDiagnosticErrorCode()
00078 {
00079 #ifdef _MSC_VER
00080 #undef ERROR
00081         return(2);
00082 #else
00083         return(diagnostic_msgs::DiagnosticStatus::ERROR);
00084 #endif
00085 }
00086 namespace sick_scan
00087 {
00088    bool emulateReply(UINT8*requestData, int requestLen, std::vector<unsigned char>* replyVector)
00089    {
00090      std::string request;
00091      std::string reply;
00092      std::vector<std::string> keyWordList;
00093      std::vector<std::string> answerList;
00094 
00095      keyWordList.push_back("sMN SetAccessMode");
00096      answerList.push_back("sAN SetAccessMode 1");
00097 
00098      keyWordList.push_back("sWN EIHstCola");
00099      answerList.push_back("sWA EIHstCola");
00100 
00101      keyWordList.push_back("sRN FirmwareVersion");
00102      answerList.push_back("sRA FirmwareVersion 8 1.0.0.0R");
00103 
00104                  keyWordList.push_back("sRN OrdNum");
00105                  answerList.push_back("sRA OrdNum 7 1234567");
00106 
00107                  keyWordList.push_back("sWN TransmitTargets 1");
00108                  answerList.push_back("sWA TransmitTargets");
00109 
00110                  keyWordList.push_back("sWN TransmitObjects 1");
00111                  answerList.push_back("sWA TransmitObjects");
00112 
00113                  keyWordList.push_back("sWN TCTrackingMode 0");
00114                  answerList.push_back("sWA TCTrackingMode");
00115 
00116                  keyWordList.push_back("sRN SCdevicestate");
00117      answerList.push_back("sRA SCdevicestate 1");
00118 
00119                  keyWordList.push_back("sRN DItype");
00120                  answerList.push_back("sRA DItype D RMS3xx-xxxxxx");
00121 
00122                  keyWordList.push_back("sRN ODoprh");
00123                  answerList.push_back("sRA ODoprh 451");
00124 
00125                  keyWordList.push_back("sMN mSCloadappdef");
00126                  answerList.push_back("sAN mSCloadappdef");
00127 
00128 
00129                  keyWordList.push_back("sRN SerialNumber");
00130                  answerList.push_back("sRA SerialNumber 8 18020073");
00131 
00132                  keyWordList.push_back("sMN Run");
00133      answerList.push_back("sAN Run 1s");
00134 
00135      keyWordList.push_back("sRN ODpwrc");
00136      answerList.push_back("sRA ODpwrc 20");
00137 
00138      keyWordList.push_back("sRN LocationName");
00139      answerList.push_back("sRA LocationName B not defined");
00140 
00141      keyWordList.push_back("sEN LMDradardata 1");
00142      answerList.push_back("sEA LMDradardata 1");
00143 
00144      for (int i = 0; i < requestLen; i++)
00145      {
00146        request += (char)requestData[i];
00147      }
00148      for (int i = 0; i < keyWordList.size(); i++)
00149      {
00150        if (request.find(keyWordList[i]) != std::string::npos)
00151        {
00152          reply = (char)0x02;
00153          reply += answerList[i];
00154          reply += (char)0x03;
00155        }
00156      }
00157 
00158      replyVector->clear();
00159      for (int i = 0; i < reply.length(); i++)
00160      {
00161        replyVector->push_back((unsigned char)reply[i]);
00162      }
00163 
00164 
00165      return(true);
00166    }
00167 
00168 
00169 
00170         SickScanCommonTcp::SickScanCommonTcp(const std::string &hostname, const std::string &port, int &timelimit, SickGenericParser* parser, char cola_dialect_id)
00171                 :
00172                 SickScanCommon(parser),
00173                 socket_(io_service_),
00174                 deadline_(io_service_),
00175                 hostname_(hostname),
00176                 port_(port),
00177                 timelimit_(timelimit)
00178         {
00179 
00180                 setEmulSensor(false);
00181                 if ((cola_dialect_id == 'a') || (cola_dialect_id == 'A'))
00182                 {
00183                         this->setProtocolType(CoLa_A);
00184                 }
00185 
00186                 if ((cola_dialect_id == 'b') || (cola_dialect_id == 'B'))
00187                 {
00188                         this->setProtocolType(CoLa_B);
00189                 }
00190 
00191                 assert(this->getProtocolType() != CoLa_Unknown);
00192 
00193                 m_numberOfBytesInReceiveBuffer = 0;
00194                 m_alreadyReceivedBytes = 0;
00195                 this->setReplyMode(0);
00196                 // io_service_.setReadCallbackFunction(boost::bind(&SopasDevice::readCallbackFunction, this, _1, _2));
00197 
00198                 // Set up the deadline actor to implement timeouts.
00199                 // Based on blocking TCP example on:
00200                 // http://www.boost.org/doc/libs/1_46_0/doc/html/boost_asio/example/timeouts/blocking_tcp_client.cpp
00201                 deadline_.expires_at(boost::posix_time::pos_infin);
00202                 checkDeadline();
00203 
00204         }
00205 
00206         SickScanCommonTcp::~SickScanCommonTcp()
00207         {
00208                 // stop_scanner();
00209                 close_device();
00210         }
00211 
00212         using boost::asio::ip::tcp;
00213         using boost::lambda::var;
00214         using boost::lambda::_1;
00215 
00216 
00217         void SickScanCommonTcp::disconnectFunction()
00218         {
00219 
00220         }
00221 
00222         void SickScanCommonTcp::disconnectFunctionS(void *obj)
00223         {
00224                 if (obj != NULL)
00225                 {
00226                         ((SickScanCommonTcp *)(obj))->disconnectFunction();
00227                 }
00228         }
00229 
00230         void SickScanCommonTcp::readCallbackFunctionS(void* obj, UINT8* buffer, UINT32& numOfBytes)
00231         {
00232                 ((SickScanCommonTcp*)obj)->readCallbackFunction(buffer, numOfBytes);
00233         }
00234 
00235 
00236         void SickScanCommonTcp::setReplyMode(int _mode)
00237         {
00238                 m_replyMode = _mode;
00239         }
00240         int SickScanCommonTcp::getReplyMode()
00241         {
00242                 return(m_replyMode);
00243         }
00244 
00245 #if 0
00246         void SickScanCommonTcp::setProtocolType(char cola_dialect_id)
00247         {
00248                 if ((cola_dialect_id == 'a') || (cola_dialect_id == 'A'))
00249                 {
00250                         this->m_protocol = CoLa_A;
00251                 }
00252                 else
00253                 {
00254                         this->m_protocol = CoLa_B;
00255                 }
00256         }
00257 #endif
00258 
00263         void SickScanCommonTcp::setEmulSensor(bool _emulFlag)
00264         {
00265                 m_emulSensor = _emulFlag;
00266         }
00267 
00273         bool SickScanCommonTcp::getEmulSensor()
00274         {
00275                 return(m_emulSensor);
00276         }
00277 
00278         //
00279         // Look for 23-frame (STX/ETX) in receive buffer.
00280         // Move frame to start of buffer
00281         //
00282         // Return: 0 : No (complete) frame found
00283         //        >0 : Frame length
00284         //
00285         SopasEventMessage SickScanCommonTcp::findFrameInReceiveBuffer()
00286         {
00287                 UINT32 frameLen = 0;
00288                 UINT32 i;
00289 
00290                 // Depends on protocol...
00291                 if (getProtocolType() == CoLa_A)
00292                 {
00293                         //
00294                         // COLA-A
00295                         //
00296                         // Must start with STX (0x02)
00297                         if (m_receiveBuffer[0] != 0x02)
00298                         {
00299                                 // Look for starting STX (0x02)
00300                                 for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
00301                                 {
00302                                         if (m_receiveBuffer[i] == 0x02)
00303                                         {
00304                                                 break;
00305                                         }
00306                                 }
00307 
00308                                 // Found beginning of frame?
00309                                 if (i >= m_numberOfBytesInReceiveBuffer)
00310                                 {
00311                                         // No start found, everything can be discarded
00312                                         m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
00313                                         return SopasEventMessage(); // No frame found
00314                                 }
00315 
00316                                 // Move frame start to index 0
00317                                 UINT32 newLen = m_numberOfBytesInReceiveBuffer - i;
00318                                 memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), newLen);
00319                                 m_numberOfBytesInReceiveBuffer = newLen;
00320                         }
00321 
00322                         // Look for ending ETX (0x03)
00323                         for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
00324                         {
00325                                 if (m_receiveBuffer[i] == 0x03)
00326                                 {
00327                                         break;
00328                                 }
00329                         }
00330 
00331                         // Found end?
00332                         if (i >= m_numberOfBytesInReceiveBuffer)
00333                         {
00334                                 // No end marker found, so it's not a complete frame (yet)
00335                                 return SopasEventMessage(); // No frame found
00336                         }
00337 
00338                         // Calculate frame length in byte
00339                         frameLen = i + 1;
00340 
00341                         return SopasEventMessage(m_receiveBuffer, CoLa_A, frameLen);
00342                 }
00343                 else if (getProtocolType() == CoLa_B)
00344                 {
00345                         UINT32 magicWord;
00346                         UINT32 payloadlength;
00347 
00348                         if (m_numberOfBytesInReceiveBuffer < 4)
00349                         {
00350                                 return SopasEventMessage();
00351                         }
00352                         UINT16 pos = 0;
00353                         magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
00354                         if (magicWord != 0x02020202)
00355                         {
00356                                 // Look for starting STX (0x02020202)
00357                                 for (i = 1; i <= m_numberOfBytesInReceiveBuffer - 4; i++)
00358                                 {
00359                                         pos = i; // this is needed, as the position value is updated by getIntegerFromBuffer
00360                                         magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
00361                                         if (magicWord == 0x02020202)
00362                                         {
00363                                                 // found magic word
00364                                                 break;
00365                                         }
00366                                 }
00367 
00368                                 // Found beginning of frame?
00369                                 if (i > m_numberOfBytesInReceiveBuffer - 4)
00370                                 {
00371                                         // No start found, everything can be discarded
00372                                         m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
00373                                         return SopasEventMessage(); // No frame found
00374                                 }
00375                                 else
00376                                 {
00377                                         // Move frame start to index
00378                                         UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - i;
00379                                         memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), bytesToMove); // payload+magic+length+s+checksum
00380                                         m_numberOfBytesInReceiveBuffer = bytesToMove;
00381                                 }
00382                         }
00383 
00384                         // Pruefe Laenge des Pufferinhalts
00385                         if (m_numberOfBytesInReceiveBuffer < 9)
00386                         {
00387                                 // Es sind nicht genug Daten fuer einen Frame
00388                                 printInfoMessage("SickScanCommonNw::findFrameInReceiveBuffer: Frame cannot be decoded yet, only " +
00389                                         ::toString(m_numberOfBytesInReceiveBuffer) + " bytes in the buffer.", m_beVerbose);
00390                                 return SopasEventMessage();
00391                         }
00392 
00393                         // Read length of payload
00394                         pos = 4;
00395                         payloadlength = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
00396                         printInfoMessage("SickScanCommonNw::findFrameInReceiveBuffer: Decoded payload length is " + ::toString(payloadlength) + " bytes.", m_beVerbose);
00397 
00398                         // Ist die Datenlaenge plausibel und wuede in den Puffer passen?
00399                         if (payloadlength > (sizeof(m_receiveBuffer) - 9))
00400                         {
00401                                 // magic word + length + checksum = 9
00402                                 printWarning("SickScanCommonNw::findFrameInReceiveBuffer: Frame too big for receive buffer. Frame discarded with length:"
00403                                         + ::toString(payloadlength) + ".");
00404                                 m_numberOfBytesInReceiveBuffer = 0;
00405                                 return SopasEventMessage();
00406                         }
00407                         if ((payloadlength + 9) > m_numberOfBytesInReceiveBuffer)
00408                         {
00409                                 // magic word + length + s + checksum = 10
00410                                 printInfoMessage("SickScanCommonNw::findFrameInReceiveBuffer: Frame not complete yet. Waiting for the rest of it (" +
00411                                         ::toString(payloadlength + 9 - m_numberOfBytesInReceiveBuffer) + " bytes missing).", m_beVerbose);
00412                                 return SopasEventMessage(); // frame not complete
00413                         }
00414 
00415                         // Calculate the total frame length in bytes: Len = Frame (9 bytes) + Payload
00416                         frameLen = payloadlength + 9;
00417 
00418                         //
00419                         // test checksum of payload
00420                         //
00421                         UINT8 temp = 0;
00422                         UINT8 temp_xor = 0;
00423                         UINT8 checkSum;
00424 
00425                         // Read original checksum
00426                         pos = frameLen - 1;
00427                         checkSum = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
00428 
00429                         // Erzeuge die Pruefsumme zum Vergleich
00430                         for (UINT16 i = 8; i < (frameLen - 1); i++)
00431                         {
00432                                 pos = i;
00433                                 temp = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
00434                                 temp_xor = temp_xor ^ temp;
00435                         }
00436 
00437                         // Vergleiche die Pruefsummen
00438                         if (temp_xor != checkSum)
00439                         {
00440                                 printWarning("SickScanCommonNw::findFrameInReceiveBuffer: Wrong checksum, Frame discarded.");
00441                                 m_numberOfBytesInReceiveBuffer = 0;
00442                                 return SopasEventMessage();
00443                         }
00444 
00445                         return SopasEventMessage(m_receiveBuffer, CoLa_B, frameLen);
00446                 }
00447 
00448                 // Return empty frame
00449                 return SopasEventMessage();
00450         }
00451 
00452 
00453 
00459         void SickScanCommonTcp::processFrame(ros::Time timeStamp, SopasEventMessage& frame)
00460         {
00461 
00462                 if (getProtocolType() == CoLa_A)
00463                 {
00464                         printInfoMessage("SickScanCommonNw::processFrame: Calling processFrame_CoLa_A() with " + ::toString(frame.size()) + " bytes.", m_beVerbose);
00465                         // processFrame_CoLa_A(frame);
00466                 }
00467                 else if (getProtocolType() == CoLa_B)
00468                 {
00469                         printInfoMessage("SickScanCommonNw::processFrame: Calling processFrame_CoLa_B() with " + ::toString(frame.size()) + " bytes.", m_beVerbose);
00470                         // processFrame_CoLa_B(frame);
00471                 }
00472 
00473                 // Push frame to recvQueue
00474 
00475     DatagramWithTimeStamp dataGramWidthTimeStamp(timeStamp, std::vector<unsigned char>(frame.getRawData(), frame.getRawData() + frame.size()));
00476                 // recvQueue.push(std::vector<unsigned char>(frame.getRawData(), frame.getRawData() + frame.size()));
00477     recvQueue.push(dataGramWidthTimeStamp);
00478         }
00479 
00480         void SickScanCommonTcp::readCallbackFunction(UINT8* buffer, UINT32& numOfBytes)
00481         {
00482     ros::Time rcvTimeStamp = ros::Time::now(); // stamp received datagram
00483                 bool beVerboseHere = false;
00484                 printInfoMessage("SickScanCommonNw::readCallbackFunction(): Called with " + toString(numOfBytes) + " available bytes.", beVerboseHere);
00485 
00486                 ScopedLock lock(&m_receiveDataMutex); // Mutex for access to the input buffer
00487                 UINT32 remainingSpace = sizeof(m_receiveBuffer) - m_numberOfBytesInReceiveBuffer;
00488                 UINT32 bytesToBeTransferred = numOfBytes;
00489                 if (remainingSpace < numOfBytes)
00490                 {
00491                         bytesToBeTransferred = remainingSpace;
00492                         // printWarning("SickScanCommonNw::readCallbackFunction(): Input buffer space is to small, transferring only " +
00493                         //              ::toString(bytesToBeTransferred) + " of " + ::toString(numOfBytes) + " bytes.");
00494                 }
00495                 else
00496                 {
00497                         // printInfoMessage("SickScanCommonNw::readCallbackFunction(): Transferring " + ::toString(bytesToBeTransferred) +
00498                         //                   " bytes from TCP to input buffer.", beVerboseHere);
00499                 }
00500 
00501                 if (bytesToBeTransferred > 0)
00502                 {
00503                         // Data can be transferred into our input buffer
00504                         memcpy(&(m_receiveBuffer[m_numberOfBytesInReceiveBuffer]), buffer, bytesToBeTransferred);
00505                         m_numberOfBytesInReceiveBuffer += bytesToBeTransferred;
00506 
00507                         UINT32 size = 0;
00508 
00509                         while (1)
00510                         {
00511                                 // Now work on the input buffer until all received datasets are processed
00512                                 SopasEventMessage frame = findFrameInReceiveBuffer();
00513 
00514                                 size = frame.size();
00515                                 if (size == 0)
00516                                 {
00517                                         // Framesize = 0: There is no valid frame in the buffer. The buffer is either empty or the frame
00518                                         // is incomplete, so leave the loop
00519                                         printInfoMessage("SickScanCommonNw::readCallbackFunction(): No complete frame in input buffer, we are done.", beVerboseHere);
00520 
00521                                         // Leave the loop
00522                                         break;
00523                                 }
00524                                 else
00525                                 {
00526                                         // A frame was found in the buffer, so process it now.
00527                                         printInfoMessage("SickScanCommonNw::readCallbackFunction(): Processing a frame of length " + ::toString(frame.size()) + " bytes.", beVerboseHere);
00528                                         processFrame(rcvTimeStamp, frame);
00529                                         UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - size;
00530                                         memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[size]), bytesToMove); // payload+magic+length+s+checksum
00531                                         m_numberOfBytesInReceiveBuffer = bytesToMove;
00532 
00533                                 }
00534                         }
00535                 }
00536                 else
00537                 {
00538                         // There was input data from the TCP interface, but our input buffer was unable to hold a single byte.
00539                         // Either we have not read data from our buffer for a long time, or something has gone wrong. To re-sync,
00540                         // we clear the input buffer here.
00541                         m_numberOfBytesInReceiveBuffer = 0;
00542                 }
00543         }
00544 
00545 
00546         int SickScanCommonTcp::init_device()
00547         {
00548                 int portInt;
00549                 sscanf(port_.c_str(), "%d", &portInt);
00550                 m_nw.init(hostname_, portInt, disconnectFunctionS, (void*)this);
00551                 m_nw.setReadCallbackFunction(readCallbackFunctionS, (void*)this);
00552     if (this->getEmulSensor())
00553     {
00554       ROS_INFO("Sensor emulation is switched on - network traffic is switched off.");
00555     } else
00556     {
00557                 m_nw.connect();
00558     }
00559                 return ExitSuccess;
00560         }
00561 
00562         int SickScanCommonTcp::close_device()
00563         {
00564                 ROS_WARN("Disconnecting TCP-Connection.");
00565                 m_nw.disconnect();
00566                 return 0;
00567         }
00568 
00569 
00570         bool SickScanCommonTcp::stopScanData()
00571         {
00572                 stop_scanner();
00573                 return(true);
00574         }
00575 
00576         void SickScanCommonTcp::handleRead(boost::system::error_code error, size_t bytes_transfered)
00577         {
00578                 ec_ = error;
00579                 bytes_transfered_ += bytes_transfered;
00580         }
00581 
00582 
00583         void SickScanCommonTcp::checkDeadline()
00584         {
00585                 if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now())
00586                 {
00587                         // The reason the function is called is that the deadline expired. Close
00588                         // the socket to return all IO operations and reset the deadline
00589                         socket_.close();
00590                         deadline_.expires_at(boost::posix_time::pos_infin);
00591                 }
00592 
00593                 // Nothing bad happened, go back to sleep
00594                 deadline_.async_wait(boost::bind(&SickScanCommonTcp::checkDeadline, this));
00595         }
00596 
00597 
00598         int SickScanCommonTcp::numberOfDatagramInInputFifo()
00599   {
00600     this->recvQueue.getNumberOfEntriesInQueue();
00601   }
00602 
00603         int SickScanCommonTcp::readWithTimeout(size_t timeout_ms, char *buffer, int buffer_size, int *bytes_read, bool *exception_occured, bool isBinary)
00604         {
00605                 // Set up the deadline to the proper timeout, error and delimiters
00606                 deadline_.expires_from_now(boost::posix_time::milliseconds(timeout_ms));
00607                 const char end_delim = static_cast<char>(0x03);
00608                 int dataLen = 0;
00609                 ec_ = boost::asio::error::would_block;
00610                 bytes_transfered_ = 0;
00611 
00612                 size_t to_read;
00613 
00614                 int numBytes = 0;
00615                 // Polling - should be changed to condition variable in the future
00616                 int waitingTimeInMs = 1; // try to lookup for new incoming packages
00617                 int i;
00618                 for (i = 0; i < timeout_ms; i += waitingTimeInMs)
00619                 {
00620                         if (false == this->recvQueue.isQueueEmpty())
00621                         {
00622                                 break;
00623                         }
00624                         boost::this_thread::sleep(boost::posix_time::milliseconds(waitingTimeInMs));
00625                 }
00626                 if (i >= timeout_ms)
00627                 {
00628                         ROS_ERROR("no answer received after %zu ms. Maybe sopas mode is wrong.\n",timeout_ms);
00629                         return(ExitError);
00630                 }
00631                 boost::condition_variable cond_;
00632     DatagramWithTimeStamp datagramWithTimeStamp = this->recvQueue.pop();
00633 
00634     *bytes_read = datagramWithTimeStamp.datagram.size();
00635                 memcpy(buffer, &(datagramWithTimeStamp.datagram[0]), datagramWithTimeStamp.datagram.size());
00636                 return(ExitSuccess);
00637         }
00638 
00642         int SickScanCommonTcp::sendSOPASCommand(const char* request, std::vector<unsigned char> * reply, int cmdLen)
00643         {
00644 #if 0
00645                 if (!socket_.is_open()) {
00646                         ROS_ERROR("sendSOPASCommand: socket not open");
00647                         diagnostics_.broadcast(getDiagnosticErrorCode(), "sendSOPASCommand: socket not open.");
00648                         return ExitError;
00649                 }
00650 #endif
00651                 int sLen = 0;
00652                 int preambelCnt = 0;
00653                 bool cmdIsBinary = false;
00654 
00655     if (request != NULL)
00656                 {
00657                         sLen = cmdLen;
00658                         preambelCnt = 0; // count 0x02 bytes to decide between ascii and binary command
00659                         if (sLen >= 4)
00660                         {
00661                                 for (int i = 0; i < 4; i++) {
00662                                         if (request[i] == 0x02)
00663                                         {
00664                                                 preambelCnt++;
00665                                         }
00666                                 }
00667                         }
00668 
00669                         if (preambelCnt < 4) {
00670                                 cmdIsBinary = false;
00671                         }
00672                         else
00673                         {
00674                                 cmdIsBinary = true;
00675                         }
00676                         int msgLen = 0;
00677                         if (cmdIsBinary == false)
00678                         {
00679                                 msgLen = strlen(request);
00680                         }
00681                         else
00682                         {
00683                                 int dataLen = 0;
00684                                 for (int i = 4; i < 8; i++)
00685                                 {
00686                                         dataLen |= ((unsigned char)request[i] << (7 - i) * 8);
00687                                 }
00688                                 msgLen = 8 + dataLen + 1; // 8 Msg. Header + Packet +
00689                         }
00690 #if 1
00691       if (getEmulSensor())
00692       {
00693         emulateReply((UINT8*)request, msgLen, reply);
00694       }
00695       else
00696       {
00697         bool debugBinCmd = false;
00698         if (debugBinCmd)
00699         {
00700                                 printf("=== START HEX DUMP ===\n");
00701                                 for (int i = 0; i < msgLen; i++)
00702                                 {
00703                                         unsigned char *ptr = (UINT8*)request;
00704                                         printf("%02x ", ptr[i]);
00705                                   }
00706                                   printf("\n=== END HEX DUMP ===\n");
00707         }
00708         m_nw.sendCommandBuffer((UINT8*)request, msgLen);
00709       }
00710 #else
00711 
00712                         /*
00713                          * Write a SOPAS variable read request to the device.
00714                          */
00715                         try
00716                         {
00717                                 boost::asio::write(socket_, boost::asio::buffer(request, msgLen));
00718                         }
00719                         catch (boost::system::system_error &e)
00720                         {
00721                                 ROS_ERROR("write error for command: %s", request);
00722                                 diagnostics_.broadcast(getDiagnosticErrorCode(), "Write error for sendSOPASCommand.");
00723                                 return ExitError;
00724                         }
00725 #endif
00726                 }
00727 
00728     // Set timeout in 5 seconds
00729                 const int BUF_SIZE = 65536;
00730                 char buffer[BUF_SIZE];
00731                 int bytes_read;
00732                 // !!!
00733     if (getEmulSensor())
00734     {
00735 
00736     }
00737     else
00738     {
00739                   if (readWithTimeout(getReadTimeOutInMs(), buffer, BUF_SIZE, &bytes_read, 0, cmdIsBinary) == ExitError)
00740                   {
00741                         ROS_INFO_THROTTLE(1.0, "sendSOPASCommand: no full reply available for read after %d ms",getReadTimeOutInMs());
00742                         diagnostics_.broadcast(getDiagnosticErrorCode(), "sendSOPASCommand: no full reply available for read after timeout.");
00743                         return ExitError;
00744                 }
00745 
00746 
00747                   if (reply)
00748                   {
00749                         reply->resize(bytes_read);
00750 
00751                         std::copy(buffer, buffer + bytes_read, &(*reply)[0]);
00752                 }
00753     }
00754                 return ExitSuccess;
00755         }
00756 
00757 
00758         int SickScanCommonTcp::get_datagram(ros::Time &recvTimeStamp, unsigned char *receiveBuffer, int bufferSize, int *actual_length,
00759                                         bool isBinaryProtocol, int *numberOfRemainingFifoEntries)
00760         {
00761     if (NULL != numberOfRemainingFifoEntries)
00762     {
00763       *numberOfRemainingFifoEntries = 0;
00764     }
00765                 this->setReplyMode(1);
00766 
00767     if (this->getEmulSensor())
00768     {
00769       // boost::this_thread::sleep(boost::posix_time::milliseconds(waitingTimeInMs));
00770       ros::Time timeStamp = ros::Time::now();
00771       uint32_t nanoSec = timeStamp.nsec;
00772       double waitTime10Hz = 10.0 * (double)nanoSec / 1E9;  // 10th of sec. [0..10[
00773 
00774       uint32_t waitTime = (int)waitTime10Hz ; // round down
00775 
00776       double waitTimeUntilNextTime10Hz = 1/10.0 * (1.0 - (waitTime10Hz - waitTime));
00777 
00778       ros::Duration(waitTimeUntilNextTime10Hz).sleep();
00779       SickScanRadar radar(this);
00780                         radar.setEmulation(true);
00781       radar.simulateAsciiDatagram(receiveBuffer, actual_length);
00782       recvTimeStamp = ros::Time::now();
00783     }
00784     else
00785     {
00786                   const int maxWaitInMs = getReadTimeOutInMs();
00787                   std::vector<unsigned char> dataBuffer;
00788 #if 1 // prepared for reconnect
00789                 bool retVal = this->recvQueue.waitForIncomingObject(maxWaitInMs);
00790                 if (retVal == false)
00791                   {
00792                           ROS_WARN("Timeout during waiting for new datagram");
00793                           return ExitError;
00794                   }
00795                   else
00796                   {
00797                         // Look into receiving queue for new Datagrams
00798                         //
00799                         //
00800         DatagramWithTimeStamp datagramWithTimeStamp = this->recvQueue.pop();
00801         if (NULL != numberOfRemainingFifoEntries)
00802         {
00803           *numberOfRemainingFifoEntries = this->recvQueue.getNumberOfEntriesInQueue();
00804         }
00805         recvTimeStamp = datagramWithTimeStamp.timeStamp;
00806                           dataBuffer = datagramWithTimeStamp.datagram;
00807 
00808                   }
00809 #endif
00810                 // dataBuffer = this->recvQueue.pop();
00811       long size = dataBuffer.size();
00812                 memcpy(receiveBuffer, &(dataBuffer[0]), size);
00813                   *actual_length = size;
00814     }
00815 
00816 #if 0
00817                 static int cnt = 0;
00818                 char szFileName[255];
00819                 sprintf(szFileName, "/tmp/dg%06d.bin", cnt++);
00820 
00821                 FILE *fout;
00822 
00823                 fout = fopen(szFileName, "wb");
00824                 if (fout != NULL)
00825                 {
00826                         fwrite(receiveBuffer, size, 1, fout);
00827                         fclose(fout);
00828                 }
00829 #endif
00830                 return ExitSuccess;
00831 
00832                 if (!socket_.is_open()) {
00833                         ROS_ERROR("get_datagram: socket not open");
00834                         diagnostics_.broadcast(getDiagnosticErrorCode(), "get_datagram: socket not open.");
00835                         return ExitError;
00836                 }
00837 
00838                 /*
00839                  * Write a SOPAS variable read request to the device.
00840                  */
00841                 std::vector<unsigned char> reply;
00842 
00843                 // Wait at most 5000ms for a new scan
00844                 size_t timeout = 30000;
00845                 bool exception_occured = false;
00846 
00847                 char *buffer = reinterpret_cast<char *>(receiveBuffer);
00848 
00849                 if (readWithTimeout(timeout, buffer, bufferSize, actual_length, &exception_occured, isBinaryProtocol) != ExitSuccess)
00850                 {
00851                         ROS_ERROR_THROTTLE(1.0, "get_datagram: no data available for read after %zu ms", timeout);
00852                         diagnostics_.broadcast(getDiagnosticErrorCode(), "get_datagram: no data available for read after timeout.");
00853 
00854                         // Attempt to reconnect when the connection was terminated
00855                         if (!socket_.is_open())
00856                         {
00857 #ifdef _MSC_VER
00858                                 Sleep(1000);
00859 #else
00860                                 sleep(1);
00861 #endif
00862                                 ROS_INFO("Failure - attempting to reconnect");
00863                                 return init();
00864                         }
00865 
00866                         return exception_occured ? ExitError : ExitSuccess;    // keep on trying
00867                 }
00868 
00869                 return ExitSuccess;
00870         }
00871 
00872 } /* namespace sick_scan */


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