ScannerSickS300.cpp
Go to the documentation of this file.
00001 /****************************************************************
00002  *
00003  * Copyright (c) 2010
00004  *
00005  * Fraunhofer Institute for Manufacturing Engineering   
00006  * and Automation (IPA)
00007  *
00008  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00009  *
00010  * Project name: care-o-bot
00011  * ROS stack name: cob_driver
00012  * ROS package name: cob_sick_s300
00013  * Description:
00014  *                                                              
00015  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00016  *                      
00017  * Author: Christian Connette, email:christian.connette@ipa.fhg.de
00018  * Supervised by: Christian Connette, email:christian.connette@ipa.fhg.de
00019  *
00020  * Date of creation: Jan 2009
00021  * ToDo:
00022  *
00023  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  *     * Redistributions of source code must retain the above copyright
00029  *       notice, this list of conditions and the following disclaimer.
00030  *     * Redistributions in binary form must reproduce the above copyright
00031  *       notice, this list of conditions and the following disclaimer in the
00032  *       documentation and/or other materials provided with the distribution.
00033  *     * Neither the name of the Fraunhofer Institute for Manufacturing 
00034  *       Engineering and Automation (IPA) nor the names of its
00035  *       contributors may be used to endorse or promote products derived from
00036  *       this software without specific prior written permission.
00037  *
00038  * This program is free software: you can redistribute it and/or modify
00039  * it under the terms of the GNU Lesser General Public License LGPL as 
00040  * published by the Free Software Foundation, either version 3 of the 
00041  * License, or (at your option) any later version.
00042  * 
00043  * This program is distributed in the hope that it will be useful,
00044  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00045  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00046  * GNU Lesser General Public License LGPL for more details.
00047  * 
00048  * You should have received a copy of the GNU Lesser General Public 
00049  * License LGPL along with this program. 
00050  * If not, see <http://www.gnu.org/licenses/>.
00051  *
00052  ****************************************************************/
00053 
00054 #include <cob_sick_s300/ScannerSickS300.h>
00055 
00056 //-----------------------------------------------
00057 
00058 typedef unsigned char BYTE;
00059 
00060 const double ScannerSickS300::c_dPi = 3.14159265358979323846;
00061 
00062 const unsigned char ScannerSickS300::c_StartBytes[10] = {0,0,0,0,0,0,0,0,255,7};
00063 
00064 unsigned char ScannerSickS300::m_iScanId = 7;
00065 
00066 const unsigned short ScannerSickS300::crc_LookUpTable[256]
00067            = { 
00068            0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 
00069            0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 
00070            0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 
00071            0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 
00072            0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 
00073            0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 
00074            0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 
00075            0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 
00076            0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 
00077            0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 
00078            0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 
00079            0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 
00080            0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 
00081            0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 
00082            0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 
00083            0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 
00084            0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 
00085            0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 
00086            0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 
00087            0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 
00088            0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 
00089            0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 
00090            0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 
00091            0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 
00092            0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 
00093            0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 
00094            0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 
00095            0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 
00096            0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 
00097            0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 
00098            0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 
00099            0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 
00100          }; 
00101 
00102 //-----------------------------------------------
00103 ScannerSickS300::ScannerSickS300()
00104 {
00105         m_Param.iDataLength = 1104;
00106         m_Param.iHeaderLength = 24;
00107         // scanner has a half degree resolution and a VoW of 270 degrees
00108         m_Param.iNumScanPoints = 541;
00109         m_Param.dScale = 0.01;
00110         m_Param.dStartAngle = -135.0/180.0*c_dPi;
00111         m_Param.dStopAngle = 135.0/180.0*c_dPi;
00112 
00113         // allows to set different Baud-Multipliers depending on used SerialIO-Card
00114         m_dBaudMult = 1.0;
00115 
00116         // init scan with zeros
00117         m_viScanRaw.assign(541, 0);
00118         m_iPosReadBuf2 = 0;
00119 
00120 }
00121 
00122 
00123 //-------------------------------------------
00124 ScannerSickS300::~ScannerSickS300()
00125 {
00126         m_SerialIO.close();
00127 }
00128 
00129 
00130 // ---------------------------------------------------------------------------
00131 bool ScannerSickS300::open(const char* pcPort, int iBaudRate, int iScanId=7)
00132 {
00133     int bRetSerial;
00134  
00135         // for Care-O-bot3 S300 is set fixed to 500kBaud
00136         if (iBaudRate != 500000)
00137                 return false;
00138 
00139         // update scan id (id=8 for slave scanner, else 7)
00140         m_iScanId = iScanId;
00141         
00142         // initialize Serial Interface
00143         m_SerialIO.setBaudRate(iBaudRate);
00144         m_SerialIO.setDeviceName(pcPort);
00145         m_SerialIO.setBufferSize(READ_BUF_SIZE - 10 , WRITE_BUF_SIZE -10 );
00146         m_SerialIO.setHandshake(SerialIO::HS_NONE);
00147         m_SerialIO.setMultiplier(m_dBaudMult);
00148         bRetSerial = m_SerialIO.open();
00149         m_SerialIO.setTimeout(0.0);
00150         m_SerialIO.SetFormat(8, SerialIO::PA_NONE, SerialIO::SB_ONE);
00151 
00152     if(bRetSerial == 0)
00153     {
00154             // Clears the read and transmit buffer.
00155             m_iPosReadBuf2 = 0;
00156             m_SerialIO.purge();
00157             return true;
00158     }
00159     else
00160     {
00161         return false;
00162     }
00163 }
00164 
00165 
00166 //-------------------------------------------
00167 void ScannerSickS300::purgeScanBuf()
00168 {
00169         m_iPosReadBuf2 = 0;
00170         m_SerialIO.purge();
00171 }
00172 
00173 
00174 //-------------------------------------------
00175 void ScannerSickS300::resetStartup()
00176 {
00177 }
00178 
00179 
00180 //-------------------------------------------
00181 void ScannerSickS300::startScanner()
00182 {
00183 }
00184 
00185 
00186 //-------------------------------------------
00187 void ScannerSickS300::stopScanner()
00188 {
00189 }
00190 
00191 
00192 //-----------------------------------------------
00193 bool ScannerSickS300::getScan(std::vector<double> &vdDistanceM, std::vector<double> &vdAngleRAD, std::vector<double> &vdIntensityAU, unsigned int &iTimestamp, unsigned int &iTimeNow)
00194 {
00195         bool bRet = false;
00196         int i,j;
00197         int iNumRead;
00198         int iNumData;
00199         int iFirstByteOfHeader;
00200         int iFirstByteOfData;
00201         unsigned int iTelegramNumber;
00202         unsigned int uiReadCRC;
00203         unsigned int uiCalcCRC;
00204         std::vector<ScanPolarType> vecScanPolar;
00205         vecScanPolar.resize(m_Param.iNumScanPoints);
00206 
00207         iNumRead = m_SerialIO.readNonBlocking((char*)m_ReadBuf, SCANNER_S300_READ_BUF_SIZE-2);
00208         
00209         if( iNumRead < m_Param.iDataLength )
00210         {
00211                 // not enough data in queue --> abort reading
00212                 printf("Not enough data in queue, read data at slower rate!\n");
00213                 return false;
00214         }
00215         
00216         // Try to find scan. Searching backwards in the receive queue.
00217         for(i=iNumRead-m_Param.iDataLength; i>=0; i--)
00218         {
00219                 // parse through the telegram until header with correct scan id is found
00220                 if (
00221                                 ( m_ReadBuf[i+0] == c_StartBytes[0] ) &&
00222                                 ( m_ReadBuf[i+1] == c_StartBytes[1] ) &&
00223                                 ( m_ReadBuf[i+2] == c_StartBytes[2] ) &&
00224                                 ( m_ReadBuf[i+3] == c_StartBytes[3] ) &&
00225                                 ( m_ReadBuf[i+4] == c_StartBytes[4] ) &&
00226                                 ( m_ReadBuf[i+5] == c_StartBytes[5] ) &&
00227                                 ( m_ReadBuf[i+8] == c_StartBytes[8] ) &&
00228                                 ( m_ReadBuf[i+9] == m_iScanId )
00229                  )
00230 
00231                 {
00232                         // ---- Start bytes found
00233                         iFirstByteOfHeader = i;
00234                         
00235                         //extract time stamp from header:
00236                         iTimestamp = (m_ReadBuf[i+17]<<24) | (m_ReadBuf[i+16]<<16) | (m_ReadBuf[i+15]<<8) |  (m_ReadBuf[i+14]);
00237                         iTelegramNumber = (m_ReadBuf[i+19]<<8) |  (m_ReadBuf[i+18]);
00238                         
00239                         if(iNumRead-iFirstByteOfHeader > m_Param.iDataLength+4+17) {
00240                                 /*
00241                                 Besides the actual data set we found some parts of the following message.
00242                                 This means we grabbed these during transmission of a new message, let's use that to sync ros time with sick time
00243                                 */
00244                                 iTimeNow = (m_ReadBuf[i+m_Param.iDataLength+4+17]<<24) | (m_ReadBuf[i+m_Param.iDataLength+4+16]<<16) | (m_ReadBuf[i+m_Param.iDataLength+4+15]<<8) |  (m_ReadBuf[i+m_Param.iDataLength+4+14]);
00245                         } else iTimeNow = 0;
00246                         
00247                         iFirstByteOfData = i + m_Param.iHeaderLength;
00248                         
00249                         // check length of transmitted data (see Telegram in .h for reference)
00250                         // read out how many bytes were transmitted (every data package has two bytes)
00251                         iNumData = 2 * getUnsignedWord(m_ReadBuf[iFirstByteOfHeader + 6],
00252                                                                                  m_ReadBuf[iFirstByteOfHeader + 7]);
00253                         // if the Data does not correspond to the expected amount --> abort the reading process
00254                         if ( iNumData != m_Param.iDataLength ) {
00255                           continue;
00256                         }
00257 
00258                         // check CRC
00259                         // Telgramm includes "24 bytes Header" (4 byte Reply-Header + 20 Bytes Tel.-Header) + 
00260                         // + 1082 bytes Data + 2 bytes CRC (last two bytes) (see h-file for more details)
00261                         // --> iNumData (1104) total telegram bytes +4 Bytes from the reply header (--> +4)
00262                         uiReadCRC = getUnsignedWord(m_ReadBuf[iFirstByteOfHeader + 4 + iNumData - 1],
00263                                                                                 m_ReadBuf[iFirstByteOfHeader + 4 + iNumData - 2]);
00264                         // calc CRC
00265                         uiCalcCRC = createCRC(&m_ReadBuf[iFirstByteOfHeader + 4], m_Param.iDataLength - 2);
00266 
00267                         // if CRC check is positive --> read out data
00268                         if (uiReadCRC == uiCalcCRC)
00269                         {
00270                                 for(j=0; j<m_Param.iNumScanPoints; j++)
00271                                 {
00272                                         // read data-words from the scan
00273                                         m_viScanRaw[j] = getUnsignedWord(m_ReadBuf[iFirstByteOfData + 2 * j + 1],
00274                                                                                                          m_ReadBuf[iFirstByteOfData + 2 * j ]);
00275                                 }
00276                                 // Scan was succesfully read from buffer
00277                                 bRet = true;
00278                                 break;
00279                         }
00280                 }
00281         }
00282         
00283         if(bRet)
00284         {
00285                 // convert data into range and intensity information
00286                 convertScanToPolar(m_viScanRaw, vecScanPolar);
00287 
00288                 // resize vectors to size of Scan
00289                 vdDistanceM.resize(vecScanPolar.size());
00290                 vdAngleRAD.resize(vecScanPolar.size());
00291                 vdIntensityAU.resize(vecScanPolar.size());
00292                 // assign outputs
00293                 for(unsigned int i=0; i < vecScanPolar.size(); i++)
00294                 {
00295                         vdDistanceM[i] = vecScanPolar[i].dr;
00296                         vdAngleRAD[i] = vecScanPolar[i].da;
00297                         vdIntensityAU[i] = vecScanPolar[i].di;
00298                 }       
00299         }
00300 
00301         return bRet;
00302 }
00303 
00304 
00305 //-------------------------------------------
00306 unsigned int ScannerSickS300::createCRC(unsigned char *ptrData, int Size)
00307 { 
00308         int CounterWord; 
00309         unsigned short CrcValue=0xFFFF;
00310 
00311         for (CounterWord = 0; CounterWord < Size; CounterWord++) 
00312         { 
00313                 CrcValue = (CrcValue << 8) ^ crc_LookUpTable[ (((BYTE)(CrcValue >> 8)) ^ *ptrData) ]; 
00314                 ptrData++; 
00315         } 
00316 
00317         return (CrcValue); 
00318 }
00319 
00320 
00321 //-------------------------------------------
00322 void ScannerSickS300::convertScanToPolar(std::vector<int> viScanRaw,
00323                                                         std::vector<ScanPolarType>& vecScanPolar )
00324 {       
00325         double dDist;
00326         double dAngle, dAngleStep;
00327         double dIntens;
00328 
00329         dAngleStep = fabs(m_Param.dStopAngle - m_Param.dStartAngle) / double(m_Param.iNumScanPoints - 1) ;
00330         
00331         for(int i=0; i<m_Param.iNumScanPoints; i++)
00332         {
00333                 dDist = double ((viScanRaw[i] & 0x1FFF) * m_Param.dScale);
00334 
00335                 dAngle = m_Param.dStartAngle + i*dAngleStep;
00336                 dIntens = double(viScanRaw[i] & 0x2000);
00337 
00338                 vecScanPolar[i].dr = dDist;
00339                 vecScanPolar[i].da = dAngle;
00340                 vecScanPolar[i].di = dIntens;
00341         }
00342 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends


cob_sick_s300
Author(s): Florian Weisshardt
autogenerated on Fri Mar 1 2013 17:47:50