00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <netinet/in.h>
00030 #include "s3000_laser/sicks3000.h"
00031
00032
00033 #define DEFAULT_RX_BUFFER_SIZE 500*1024/8
00034
00036
00037
00038 #define STX 0x02
00039 #define ACK 0xA0
00040 #define NACK 0x92
00041 #define CRC16_GEN_POL 0x8005
00042
00044 double DTOR(double val){
00045 return val*3.141592653589793/180.0;
00046 }
00047
00051 SickS3000::SickS3000( std::string port )
00052 {
00053 rx_count = 0;
00054
00055 rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
00056 rx_buffer = new uint8_t[rx_buffer_size];
00057 assert(rx_buffer);
00058
00059 recognisedScanner = false;
00060 mirror = 0;
00061
00062
00063 serial= new SerialDevice(port.c_str(), S3000_DEFAULT_TRANSFERRATE, S3000_DEFAULT_PARITY, S3000_DEFAULT_DATA_SIZE);
00064
00065 return;
00066 }
00067
00068 SickS3000::~SickS3000() {
00069
00070
00071 if (serial!=NULL) serial->ClosePort();
00072
00073
00074 if (serial!=NULL) delete serial;
00075
00076 delete [] rx_buffer;
00077 }
00078
00084 int SickS3000::Open(){
00085
00086
00087 if (this->serial->OpenPort2() == SERIAL_ERROR) {
00088 ROS_ERROR("SickS3000::Open: Error Opening Serial Port");
00089 return -1;
00090 }
00091 ROS_INFO("SickS3000::Open: serial port opened at %s", serial->GetDevice());
00092
00093 return 0;
00094 }
00095
00101 int SickS3000::Close(){
00102
00103 if (serial!=NULL) serial->ClosePort();
00104 return 0;
00105 }
00106
00108
00109 void SickS3000::SetScannerParams(sensor_msgs::LaserScan& scan, int data_count)
00110 {
00111 if (data_count == 761)
00112 {
00113
00114 scan.angle_min = static_cast<float> (DTOR(-95));
00115 scan.angle_max = static_cast<float> (DTOR(95));
00116 scan.angle_increment = static_cast<float> (DTOR(0.25));
00117 scan.time_increment = (1.0/16.6) / 761.0;
00118 scan.scan_time = (1.0/16.6);
00119 scan.range_min = 0;
00120 scan.range_max = 49;
00121
00122 recognisedScanner = true;
00123 }
00124 }
00125
00126 void SickS3000::ReadLaser( sensor_msgs::LaserScan& scan, bool& bValidData )
00127
00128 {
00129 int read_bytes=0;
00130 char cReadBuffer[4000] = "\0";
00131
00132
00133 if (serial->ReadPort(cReadBuffer, &read_bytes, 2000)==-1) {
00134 ROS_ERROR("SickS3000::ReadLaser: Error reading port");
00135 }
00136
00137 unsigned int messageOffset = rx_count;
00138 rx_count += read_bytes;
00139 if (rx_count > rx_buffer_size) {
00140 ROS_WARN("S3000 Buffer Full");
00141 rx_count = 0;
00142 }
00143 else {
00144 memcpy(&rx_buffer[messageOffset], cReadBuffer, read_bytes);
00145 ProcessLaserData(scan, bValidData);
00146 }
00147 }
00148
00149
00150 int SickS3000::ProcessLaserData(sensor_msgs::LaserScan& scan, bool& bValidData)
00151 {
00152 while(rx_count >= 22)
00153 {
00154
00155
00156 unsigned int ii;
00157 bool found = false;
00158 for (ii = 0; ii < rx_count - 22; ++ii)
00159 {
00160 if (memcmp(&rx_buffer[ii],"\0\0\0\0\0\0",6) == 0)
00161 {
00162 memmove(rx_buffer, &rx_buffer[ii], rx_count-ii);
00163 rx_count -= ii;
00164 found = true;
00165 break;
00166 }
00167 }
00168 if (!found)
00169 {
00170 memmove(rx_buffer, &rx_buffer[ii], rx_count-ii);
00171 rx_count -= ii;
00172 return 0;
00173 }
00174
00175
00176
00177
00178 unsigned short size = 2*htons(*reinterpret_cast<unsigned short *> (&rx_buffer[6]));
00179
00180 if (size > rx_buffer_size - 26)
00181 {
00182 ROS_WARN("S3000: Requested Size of data is larger than the buffer size");
00183 memmove(rx_buffer, &rx_buffer[1], --rx_count);
00184 return 0;
00185 }
00186
00187
00188 if (size > rx_count - 4)
00189 return 0;
00190
00191 unsigned short packet_checksum = *reinterpret_cast<unsigned short *> (&rx_buffer[size+2]);
00192 unsigned short calc_checksum = CreateCRC(&rx_buffer[4], size-2);
00193 if (packet_checksum != calc_checksum)
00194 {
00195 ROS_WARN("S3000: Checksum's dont match, thats bad (data packet size %d)",size);
00196 memmove(rx_buffer, &rx_buffer[1], --rx_count);
00197 continue;
00198 }
00199 else
00200 {
00201 uint8_t * data = &rx_buffer[20];
00202 if (data[0] != data[1])
00203 {
00204 ROS_WARN("S3000: Bad type header bytes dont match");
00205 }
00206 else
00207 {
00208 if (data[0] == 0xAA)
00209 {
00210 ROS_WARN("S3000: We got a I/O data packet we dont know what to do with it\n");
00211 }
00212 else if (data[0] == 0xBB)
00213 {
00214 int data_count = (size - 22) / 2;
00215 if (data_count < 0)
00216 {
00217 ROS_WARN("S3000: bad data count (%d)", data_count);
00218 memmove(rx_buffer, &rx_buffer[size+4], rx_count - (size+4));
00219 rx_count -= (size + 4);
00220 continue;
00221 }
00222 if (!recognisedScanner)
00223 SetScannerParams(scan, data_count);
00224
00225
00226 scan.ranges.clear();
00227 scan.intensities.clear();
00228
00229 scan.ranges.resize(data_count);
00230 for (int ii = 0; ii < data_count; ++ii)
00231 {
00232 unsigned short Distance_CM = (*reinterpret_cast<unsigned short *> (&data[4 + 2*ii]));
00233 Distance_CM &= 0x1fff;
00234 double distance_m = static_cast<double>(Distance_CM)/100.0;
00235 if (mirror == 1)
00236 scan.ranges[data_count - ii - 1] = static_cast<float> (distance_m);
00237 else
00238
00239 scan.ranges[ii] = static_cast<float> (distance_m);
00240 }
00241
00242
00243
00244
00245
00246
00247 bValidData = true;
00248 }
00249 else if (data[0] == 0xCC)
00250 {
00251 ROS_WARN("We got a reflector data packet we dont know what to do with it\n");
00252 }
00253 else
00254 {
00255 ROS_WARN("We got an unknown packet\n");
00256 }
00257 }
00258 }
00259
00260 memmove(rx_buffer, &rx_buffer[size+4], rx_count - (size+4));
00261 rx_count -= (size + 4);
00262 continue;
00263 }
00264 return 1;
00265 }
00266
00267
00268 static const unsigned short crc_table[256] = {
00269 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
00270 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
00271 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
00272 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
00273 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
00274 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
00275 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
00276 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
00277 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
00278 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
00279 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
00280 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
00281 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
00282 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
00283 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
00284 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
00285 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
00286 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
00287 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
00288 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
00289 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
00290 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
00291 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
00292 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
00293 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
00294 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
00295 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
00296 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
00297 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
00298 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
00299 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
00300 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
00301 };
00302
00303 unsigned short SickS3000::CreateCRC(uint8_t *Data, ssize_t length)
00304 {
00305 unsigned short CRC_16 = 0xFFFF;
00306 unsigned short i;
00307 for (i = 0; i < length; i++)
00308 {
00309 CRC_16 = (CRC_16 << 8) ^ (crc_table[(CRC_16 >> 8) ^ (Data[i])]);
00310 }
00311 return CRC_16;
00312 }
00313
00314