serialcomm_s300.cpp
Go to the documentation of this file.
00001 /*
00002  *
00003  * serialcomm_s300.cpp
00004  *
00005  *
00006  * Copyright (C) 2014
00007  * Software Engineering Group
00008  * RWTH Aachen University
00009  *
00010  *
00011  * Author: Dimitri Bohlender
00012  *
00013  *
00014  * This program is free software; you can redistribute it and/or modify
00015  * it under the terms of the GNU General Public License as published by
00016  * the Free Software Foundation; either version 3 of the License, or
00017  * (at your option) any later version.
00018  *
00019  * This program is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00022  * GNU General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00027  *
00028  *
00029  * Origin:
00030  *  Copyright (C) 2010
00031  *     Andreas Hochrath, Torsten Fiolka
00032  *     Autonomous Intelligent Systems Group
00033  *     University of Bonn, Germany
00034  *
00035  *  Player - One Hell of a Robot Server
00036  *  serialstream.cc & sicks3000.cc
00037  *  Copyright (C) 2003
00038  *     Brian Gerkey
00039  *  Copyright (C) 2000
00040  *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
00041  *
00042  */
00043 
00044 #include "serialcomm_s300.h"
00045 
00046 #include <assert.h>
00047 #include <math.h>
00048 #include <errno.h>
00049 #include <fcntl.h>
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052 #include <string.h>
00053 #include <netinet/in.h>
00054 #include <sys/types.h>
00055 #include <sys/stat.h>
00056 
00057 #include <termios.h>
00058 #include <unistd.h>
00059 #include <sys/ioctl.h>
00060 
00061 #include <iostream>
00062 
00063 SerialCommS300::SerialCommS300()
00064 {
00065   m_rxCount = 0;
00066   m_ranges = NULL;
00067 }
00068 
00069 SerialCommS300::~SerialCommS300()
00070 {
00071   disconnect();
00072 }
00073 
00074 int SerialCommS300::connect(const std::string& deviceName, unsigned int baudRate)
00075 {
00076 
00077   m_fd = ::open(deviceName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
00078   if (m_fd < 0)
00079   {
00080     std::cout << "SerialCommS300: unable to open serial port " << deviceName << "\n";
00081     return -1;
00082   }
00083 
00084   setFlags();
00085   if (setBaudRate(baudRateToBaudCode(baudRate)))
00086     return -1;
00087 
00088   tcflush(m_fd, TCIOFLUSH);
00089   usleep(1000);
00090   tcflush(m_fd, TCIFLUSH);
00091 
00092   return 0;
00093 
00094 }
00095 
00096 void SerialCommS300::setFlags()
00097 {
00098 
00099   // set up new settings
00100   struct termios term;
00101   memset(&term, 0, sizeof(term));
00102 
00103   tcgetattr(m_fd, &term);
00104 
00105   term.c_cc[VMIN] = 0;
00106   term.c_cc[VTIME] = 0;
00107   term.c_cflag = CS8 | CREAD;
00108   term.c_iflag = INPCK;
00109   term.c_oflag = 0;
00110   term.c_lflag = 0;
00111 
00112   if (tcsetattr(m_fd, TCSANOW, &term) < 0)
00113     std::cout << "SerialCommS300: failed to set tty device attributes";
00114   tcflush(m_fd, TCIOFLUSH);
00115 
00116 }
00117 
00118 int SerialCommS300::setBaudRate(int baudRate)
00119 {
00120 
00121   struct termios term;
00122 
00123   if (tcgetattr(m_fd, &term) < 0)
00124   {
00125     std::cout << "SerialCommS300: unable to get device attributes\n";
00126     return 1;
00127   }
00128 
00129   if (cfsetispeed(&term, baudRate) < 0 || cfsetospeed(&term, baudRate) < 0)
00130   {
00131     std::cout << "SerialCommS300: failed to set serial baud rate " << baudRate << "\n";
00132     return 1;
00133   }
00134 
00135   if (tcsetattr(m_fd, TCSAFLUSH, &term) < 0)
00136   {
00137     std::cout << "SerialCommS300: unable to set device attributes\n";
00138     return 1;
00139   }
00140 
00141   return 0;
00142 }
00143 
00144 int SerialCommS300::baudRateToBaudCode(int baudRate)
00145 {
00146   switch (baudRate)
00147   {
00148     case 38400:
00149       return B38400;
00150     case 115200:
00151       return B115200;
00152     case 500000:
00153       return B500000;
00154     default:
00155       return B500000;
00156   };
00157 }
00158 
00159 int SerialCommS300::disconnect()
00160 {
00161   ::close(m_fd);
00162   return 0;
00163 }
00164 
00165 static const unsigned short crc_table[256] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108,
00166                                               0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210,
00167                                               0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b,
00168                                               0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
00169                                               0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee,
00170                                               0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6,
00171                                               0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d,
00172                                               0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
00173                                               0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5,
00174                                               0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc,
00175                                               0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4,
00176                                               0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
00177                                               0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13,
00178                                               0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a,
00179                                               0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e,
00180                                               0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
00181                                               0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1,
00182                                               0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb,
00183                                               0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0,
00184                                               0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
00185                                               0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657,
00186                                               0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9,
00187                                               0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882,
00188                                               0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
00189                                               0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e,
00190                                               0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07,
00191                                               0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d,
00192                                               0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
00193                                               0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
00194 
00195 unsigned short SerialCommS300::createCRC(unsigned char* data, ssize_t length)
00196 {
00197 
00198   unsigned short CRC_16 = 0xFFFF;
00199   unsigned short i;
00200 
00201   for (i = 0; i < length; i++)
00202   {
00203     CRC_16 = (CRC_16 << 8) ^ (crc_table[(CRC_16 >> 8) ^ (data[i])]);
00204   }
00205 
00206   return CRC_16;
00207 
00208 }
00209 
00210 int SerialCommS300::readData()
00211 {
00212 
00213   if (RX_BUFFER_SIZE - m_rxCount > 0)
00214   {
00215 
00216     // Read a packet from the laser
00217     int len = read(m_fd, &m_rxBuffer[m_rxCount], RX_BUFFER_SIZE - m_rxCount);
00218     if (len == 0)
00219     {
00220       return -1;
00221     }
00222 
00223     if (len < 0)
00224     {
00225       std::cout << "SerialCommS300: error reading form serial port: " << strerror(errno) << "\n";
00226       return -1;
00227     }
00228 
00229     m_rxCount += len;
00230 
00231   }
00232 
00233   while (m_rxCount >= 22)
00234   {
00235 
00236     // find our continuous data header
00237     int ii;
00238     bool found = false;
00239     for (ii = 0; ii < m_rxCount - 22; ++ii)
00240     {
00241       if (memcmp(&m_rxBuffer[ii], "\0\0\0\0\0\0", 6) == 0 && memcmp(&m_rxBuffer[ii+8], "\xFF", 1) == 0)
00242       {
00243         memmove(m_rxBuffer, &m_rxBuffer[ii], m_rxCount - ii);
00244         m_rxCount -= ii;
00245         found = true;
00246         break;
00247       }
00248     }
00249 
00250     if (!found)
00251     {
00252       memmove(m_rxBuffer, &m_rxBuffer[ii], m_rxCount - ii);
00253       m_rxCount -= ii;
00254       return -1;
00255     }
00256 
00257     // get relevant bits of the header
00258     // size includes all data from the data block number
00259     // through to the end of the packet including the checksum
00260     unsigned short size = 2 * htons(*reinterpret_cast<unsigned short *> (&m_rxBuffer[6]));
00261     //printf("size %d", size);
00262     if (size > RX_BUFFER_SIZE - 26)
00263     {
00264       std::cout << "SerialCommS300: Requested Size of data is larger than the buffer size\n";
00265       memmove(m_rxBuffer, &m_rxBuffer[1], --m_rxCount);
00266       return -1;
00267     }
00268 
00269     // check if we have enough data yet
00270     if (size > m_rxCount - 4)
00271       return -1;
00272 
00273     // determine which protocol is used
00274     unsigned short protocol = (*reinterpret_cast<unsigned short *> (&m_rxBuffer[10]));
00275     if (protocol != PROTOCOL_1_02 && protocol != PROTOCOL_1_03)
00276     {
00277         std::cout << "SerialCommS300: protocol version " << std::hex << protocol << std::dec << " is unsupported\n";
00278         return -1;
00279     }
00280 
00281     // read & calculate checksum according to the protocol
00282     unsigned short packet_checksum, calc_checksum;
00283     if (protocol == PROTOCOL_1_02)
00284     {
00285         packet_checksum = *reinterpret_cast<unsigned short *> (&m_rxBuffer[size + 2]);
00286         calc_checksum = createCRC(&m_rxBuffer[4], size - 2);
00287     }
00288     else if (protocol == PROTOCOL_1_03)
00289     {
00290         packet_checksum = *reinterpret_cast<unsigned short *> (&m_rxBuffer[size + 12]);
00291         calc_checksum = createCRC(&m_rxBuffer[4], size + 8);
00292     }
00293 
00294     if (packet_checksum != calc_checksum)
00295     {
00296       std::cout << "SerialCommS300: Checksum's dont match, thats bad (data packet size " << size << ")\n";
00297       memmove(m_rxBuffer, &m_rxBuffer[1], --m_rxCount);
00298       continue;
00299     }
00300     else
00301     {
00302       uint8_t* data = &m_rxBuffer[20];
00303       if (data[0] != data[1])
00304       {
00305         std::cout << "SerialCommS300: Bad type header bytes dont match\n";
00306       }
00307       else
00308       {
00309         if (data[0] == 0xAA)
00310         {
00311           std::cout << "SerialCommS300: We got a I/O data packet we dont know what to do with it\n";
00312         }
00313         else if (data[0] == 0xBB)
00314         {
00315           int data_count;
00316           if (protocol == PROTOCOL_1_02)
00317               data_count = (size - 22) / 2;
00318           else if (protocol == PROTOCOL_1_03)
00319               data_count = (size - 12) / 2;
00320 
00321           if (data_count < 0)
00322           {
00323             std::cout << "SerialCommS300: bad data count (" << data_count << ")\n";
00324             memmove(m_rxBuffer, &m_rxBuffer[size + 4], m_rxCount - (size + 4));
00325             m_rxCount -= (size + 4);
00326             continue;
00327           }
00328 
00329           if (m_ranges)
00330             delete[] m_ranges;
00331 
00332           m_ranges = new float[data_count];
00333           m_rangesCount = data_count;
00334 
00335           for (int ii = 0; ii < data_count; ++ii)
00336           {
00337             unsigned short distance_cm = (*reinterpret_cast<unsigned short *> (&data[4 + 2 * ii]));
00338             distance_cm &= 0x1fff; // remove status bits
00339             m_ranges[ii] = static_cast<double> (distance_cm) / 100.0;
00340           }
00341 
00342           memmove(m_rxBuffer, &m_rxBuffer[size + 4], m_rxCount - (size + 4));
00343           m_rxCount -= (size + 4);
00344 
00345           return 0;
00346 
00347         }
00348         else if (data[0] == 0xCC)
00349         {
00350           std::cout << "SerialCommS300: We got a reflector data packet we dont know what to do with it\n";
00351         }
00352         else
00353         {
00354           std::cout << "SerialCommS300: We got an unknown packet\n";
00355         }
00356       }
00357     }
00358 
00359     memmove(m_rxBuffer, &m_rxBuffer[size + 4], m_rxCount - (size + 4));
00360     m_rxCount -= (size + 4);
00361     continue;
00362   }
00363 
00364   return -1;
00365 
00366 }
00367 


sicks300
Author(s): Dimitri Bohlender
autogenerated on Mon Oct 6 2014 07:37:46