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
00038 SickS3000::SickS3000( std::string port, int baudrate, std::string parity, int datasize )
00039 : serial_( port.c_str(), baudrate, parity.c_str(), datasize )
00040 {
00041 rx_count = 0;
00042
00043 rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
00044 rx_buffer = new uint8_t[rx_buffer_size];
00045 assert(rx_buffer);
00046
00047 recognisedScanner = false;
00048 }
00049
00050 SickS3000::~SickS3000()
00051 {
00052 delete [] rx_buffer;
00053 }
00054
00060 bool SickS3000::Open()
00061 {
00062 return serial_.OpenPort();
00063 }
00064
00070 bool SickS3000::Close()
00071 {
00072 return serial_.ClosePort();
00073 }
00074
00076
00077 bool SickS3000::SetScannerParams(sensor_msgs::LaserScan& scan, int data_count)
00078 {
00079 if (data_count == 761)
00080 {
00081 float freq_hz = 16.6;
00082
00083 scan.angle_min = deg_to_rad(-95);
00084 scan.angle_max = deg_to_rad(95);
00085 scan.angle_increment = deg_to_rad(0.25);
00086 scan.scan_time = 1.0 / freq_hz;
00087 scan.time_increment = scan.scan_time / data_count;
00088 scan.range_min = 0;
00089 scan.range_max = 49;
00090
00091 return true;
00092 }
00093
00094 if (data_count == 381)
00095 {
00096 float freq_hz = 20.0;
00097
00098 scan.angle_min = deg_to_rad(-95);
00099 scan.angle_max = deg_to_rad(95);
00100 scan.angle_increment = deg_to_rad(0.5);
00101 scan.scan_time = 1.0 / freq_hz;
00102 scan.time_increment = scan.scan_time / data_count;
00103 scan.range_min = 0;
00104 scan.range_max = 49;
00105
00106 return true;
00107 }
00108
00109 if (data_count == 541)
00110 {
00111 float freq_hz = 12.7;
00112
00113 scan.angle_min = deg_to_rad(-135);
00114 scan.angle_max = deg_to_rad(135);
00115 scan.angle_increment = deg_to_rad(0.5);
00116 scan.scan_time = 1.0 / freq_hz;
00117 scan.time_increment = scan.scan_time / data_count;
00118 scan.range_min = 0;
00119 scan.range_max = 40;
00120
00121 return true;
00122 }
00123
00124 return false;
00125 }
00126
00127 bool SickS3000::ReadLaser( sensor_msgs::LaserScan& scan )
00128 {
00129 int bytes_read=0;
00130
00131
00132 if (serial_.ReadPort(read_buffer_, READ_BUFFER_SIZE, bytes_read)==false)
00133 {
00134 ROS_ERROR("SickS3000::ReadLaser: Error reading port");
00135 return false;
00136 }
00137
00138 if (rx_count + bytes_read > rx_buffer_size)
00139 {
00140 ROS_WARN("S3000 Buffer Full");
00141 rx_count = 0;
00142 return false;
00143 }
00144
00145 memcpy(&rx_buffer[rx_count], read_buffer_, bytes_read);
00146 rx_count += bytes_read;
00147
00148 bool bValidData=false;
00149 ProcessLaserData(scan, bValidData);
00150
00151 return bValidData;
00152 }
00153
00156
00157 int SickS3000::ProcessLaserData(sensor_msgs::LaserScan& scan, bool& bValidData)
00158 {
00159 while(rx_count >= 22)
00160 {
00161
00162 unsigned int ii;
00163 bool found = false;
00164 for (ii = 0; ii < rx_count - 22; ++ii)
00165 {
00166 if (memcmp(&rx_buffer[ii],"\0\0\0\0\0\0",6) == 0)
00167 {
00168 memmove(rx_buffer, &rx_buffer[ii], rx_count-ii);
00169 rx_count -= ii;
00170 found = true;
00171 break;
00172 }
00173 }
00174
00175 if (!found)
00176 {
00177 memmove(rx_buffer, &rx_buffer[ii], rx_count-ii);
00178 rx_count -= ii;
00179 return 0;
00180 }
00181
00182
00183
00184
00185 unsigned short size = 2*htons(*reinterpret_cast<unsigned short *> (&rx_buffer[6]));
00186
00187 if (size > rx_buffer_size - 26)
00188 {
00189 ROS_WARN("S3000: Requested Size of data is larger than the buffer size");
00190 memmove(rx_buffer, &rx_buffer[1], --rx_count);
00191 return 0;
00192 }
00193
00194
00195 if (size > rx_count - 4)
00196 return 0;
00197
00198
00199 unsigned short packet_checksum = *reinterpret_cast<unsigned short *> (&rx_buffer[size+2]);
00200 unsigned short calc_checksum = CreateCRC(&rx_buffer[4], size-2);
00201 if (packet_checksum != calc_checksum)
00202 {
00203 ROS_WARN("S3000: Checksum's dont match, thats bad (data packet size %d)",size);
00204 memmove(rx_buffer, &rx_buffer[1], --rx_count);
00205 continue;
00206 }
00207
00208 else
00209 {
00210 uint8_t * data = &rx_buffer[20];
00211 if (data[0] != data[1])
00212 {
00213 ROS_WARN("S3000: Bad type header bytes dont match");
00214 }
00215 else
00216 {
00217 if (data[0] == 0xAA)
00218 {
00219 ROS_WARN("S3000: We got a I/O data packet we dont know what to do with it\n");
00220 }
00221 else if (data[0] == 0xBB)
00222 {
00223 int data_count = (size - 22) / 2;
00224 if (data_count < 0)
00225 {
00226 ROS_WARN("S3000: bad data count (%d)", data_count);
00227 memmove(rx_buffer, &rx_buffer[size+4], rx_count - (size+4));
00228 rx_count -= (size + 4);
00229 continue;
00230 }
00231 if (!recognisedScanner)
00232 {
00233
00234 if(SetScannerParams(scan, data_count)) recognisedScanner=true;
00235 }
00236
00237
00238 scan.ranges.clear();
00239 scan.intensities.clear();
00240
00241 scan.ranges.resize(data_count);
00242 for (int ii = 0; ii < data_count; ++ii)
00243 {
00244 unsigned short Distance_CM = (*reinterpret_cast<unsigned short *> (&data[4 + 2*ii]));
00245 Distance_CM &= 0x1fff;
00246 double distance_m = static_cast<double>(Distance_CM)/100.0;
00247 scan.ranges[ii] = static_cast<float> (distance_m);
00248 }
00249
00250
00251
00252 bValidData = true;
00253 }
00254 else if (data[0] == 0xCC && data[1] == 0xCC )
00255 {
00256 size_t read_pos=2;
00257
00258 uint16_t reflector_count = *reinterpret_cast<uint16_t*>( &data[read_pos] );
00259 read_pos += sizeof(reflector_count);
00260
00261 ROS_DEBUG_STREAM( "reflectors=" << reflector_count );
00262 bValidData = ( reflector_count > 0 );
00263
00264 uint32_t reflector_data, num_ranges = ( scan.angle_max - scan.angle_min ) / scan.angle_increment;
00265
00266 scan.header.stamp = ros::Time::now();
00267 scan.ranges.resize( num_ranges );
00268 std::fill( scan.ranges.begin(), scan.ranges.end(), scan.range_min-1 );
00269 scan.intensities.clear();
00270
00271 for ( size_t i=0; i< reflector_count; ++i )
00272 {
00273 reflector_data = *reinterpret_cast<uint32_t*>( &data[read_pos] );
00274 read_pos += sizeof(reflector_data);
00275
00276 int raw_angle = reflector_data & 0xFFFF;
00277 int raw_dist = ( reflector_data >> 16 ) & 0x1FFF;
00278 ROS_DEBUG("reflector %lu: angle=%.2fdeg distance=%.2fm", i, raw_angle*0.01, raw_dist*0.01 );
00279
00280 float scan_angle = scan.angle_max - deg_to_rad(raw_angle*0.01);
00281 int range_idx = ( scan.angle_max - scan_angle ) / scan.angle_increment;
00282
00283 if ( range_idx >= 0 && range_idx < scan.ranges.size() ) scan.ranges[range_idx] = raw_dist*0.01;
00284 else ROS_WARN("invalid reflector angle=%.2frad, idx=%d/%lu", scan_angle, range_idx, scan.ranges.size() );
00285 }
00286 }
00287 else
00288 {
00289 ROS_WARN("We got an unknown packet\n");
00290 }
00291
00292 }
00293 }
00294
00295 memmove(rx_buffer, &rx_buffer[size+4], rx_count - (size+4));
00296 rx_count -= (size + 4);
00297 continue;
00298 }
00299 return 1;
00300 }
00301
00302
00303 static const unsigned short crc_table[256] =
00304 {
00305 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
00306 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
00307 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
00308 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
00309 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
00310 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
00311 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
00312 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
00313 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
00314 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
00315 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
00316 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
00317 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
00318 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
00319 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
00320 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
00321 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
00322 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
00323 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
00324 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
00325 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
00326 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
00327 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
00328 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
00329 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
00330 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
00331 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
00332 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
00333 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
00334 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
00335 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
00336 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
00337 };
00338
00339 unsigned short SickS3000::CreateCRC(const uint8_t *Data, ssize_t length)
00340 {
00341 unsigned short CRC_16 = 0xFFFF;
00342 unsigned short i;
00343 for (i = 0; i < length; i++)
00344 {
00345 CRC_16 = (CRC_16 << 8) ^ (crc_table[(CRC_16 >> 8) ^ (Data[i])]);
00346 }
00347 return CRC_16;
00348 }