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
00030
00031
00032 #include <sick_lms400.h>
00033 #include <angles/angles.h>
00034
00035 const int CMD_BUFFER_SIZE = 255;
00036
00037
00039
00040 asr_sick_lms_400::asr_sick_lms_400::asr_sick_lms_400 (const char* host, int port, int debug_mode)
00041 {
00042 portno_ = port;
00043 hostname_ = host;
00044 verbose_ = debug_mode;
00045 memset (command_, 0, BUF_SIZE);
00046 MeasurementQueue_ = new std::vector<MeasurementQueueElement_t >;
00047 }
00048
00050
00051
00052 int
00053 asr_sick_lms_400::asr_sick_lms_400::Connect ()
00054 {
00055
00056 sockfd_ = socket (AF_INET, SOCK_STREAM, 0);
00057 if (sockfd_ < 0)
00058 return (-1);
00059
00060
00061 memset (&serv_addr_, 0, sizeof (serv_addr_));
00062 serv_addr_.sin_port = htons (portno_);
00063 serv_addr_.sin_family = AF_INET;
00064 #if defined (HAVE_GETADDRINFO)
00065 addr_ptr = NULL;
00066 if (getaddrinfo (hostname_, NULL, NULL, &(addr_ptr)))
00067 {
00068 ROS_ERROR ("getaddrinfo() failed with error");
00069 return (-1);
00070 }
00071 assert (addr_ptr);
00072 assert (addr_ptr->ai_addr);
00073 if ((addr_ptr->ai_addr->sa_family) != AF_INET)
00074 {
00075 ROS_ERROR ("unsupported internet address family");
00076 return (-1);
00077 }
00078 serv_addr.sin_addr.s_addr = (reinterpret_cast<struct sockaddr_in*> (addr_ptr->ai_addr))->sin_addr.s_addr;
00079 freeaddrinfo (addr_ptr);
00080 addr_ptr = NULL;
00081 #else
00082 server_ = gethostbyname (hostname_);
00083 if ((server_) == NULL)
00084 return (-1);
00085 memcpy (&(serv_addr_.sin_addr.s_addr), server_->h_addr, server_->h_length);
00086 #endif
00087
00088
00089 if (connect (sockfd_, reinterpret_cast<struct sockaddr*> (&serv_addr_), sizeof (serv_addr_)) < 0)
00090 return (-1);
00091
00092 return (0);
00093 }
00094
00096
00097
00098 int
00099 asr_sick_lms_400::asr_sick_lms_400::Disconnect ()
00100 {
00101 return (close (sockfd_));
00102 }
00103
00105
00106 int
00107 asr_sick_lms_400::asr_sick_lms_400::EnableRIS (int onoff)
00108 {
00109 char cmd[CMD_BUFFER_SIZE];
00110 snprintf (cmd, CMD_BUFFER_SIZE, "sWN MDblex %i", onoff);
00111 SendCommand (cmd);
00112
00113 if (ReadAnswer () != 0)
00114 return (-1);
00115 ExtendedRIS_ = onoff;
00116 return (0);
00117 }
00118
00120
00121 int
00122 asr_sick_lms_400::asr_sick_lms_400::SetMeanFilterParameters (int num_scans)
00123 {
00124 char cmd[CMD_BUFFER_SIZE];
00125 snprintf (cmd, CMD_BUFFER_SIZE, "sWN FLmean 0 %i", num_scans);
00126 SendCommand (cmd);
00127
00128 if (ReadAnswer () != 0)
00129 return (-1);
00130 MeanFilterNumScans_ = num_scans;
00131 return (0);
00132 }
00133
00135
00136 int
00137 asr_sick_lms_400::asr_sick_lms_400::SetRangeFilterParameters (float range_min, float range_max)
00138 {
00139 char cmd[CMD_BUFFER_SIZE];
00140 snprintf (cmd, CMD_BUFFER_SIZE, "sWN FLrang %+f %+f", (float)range_min, (float)range_max);
00141 SendCommand (cmd);
00142
00143 if (ReadAnswer () != 0)
00144 return (-1);
00145 RangeFilterBottomLimit_ = range_min;
00146 RangeFilterTopLimit_ = range_max;
00147 return (0);
00148 }
00149
00151
00152 int
00153 asr_sick_lms_400::asr_sick_lms_400::EnableFilters (int filter_mask)
00154 {
00155 char cmd[CMD_BUFFER_SIZE];
00156 snprintf (cmd, CMD_BUFFER_SIZE, "sWN FLsel %+i", filter_mask);
00157 SendCommand (cmd);
00158
00159 if (ReadAnswer () != 0)
00160 return (-1);
00161 FilterMask_ = filter_mask;
00162 return (0);
00163 }
00164
00166
00167 unsigned char*
00168 asr_sick_lms_400::asr_sick_lms_400::ParseIP (char* ip)
00169 {
00170 char* tmp = (char*) malloc (strlen (ip) + 1);
00171 unsigned char* _ip = (unsigned char*) malloc (4);
00172
00173 strcpy (tmp, ip);
00174 _ip[0] = atoi (strtok (tmp, "."));
00175 for (int i = 1; i < 4; i++)
00176 _ip[i] = atoi (strtok (NULL, "."));
00177
00178 free (tmp);
00179 return (_ip);
00180 }
00181
00183
00184 int
00185 asr_sick_lms_400::asr_sick_lms_400::SetUserLevel (int8_t userlevel, const char* password)
00186 {
00187 char cmd[CMD_BUFFER_SIZE];
00188 snprintf (cmd, CMD_BUFFER_SIZE, "sMN SetAccessMode %d %s", userlevel, password);
00189 SendCommand (cmd);
00190 return (ReadConfirmationAndAnswer ());
00191 }
00192
00194
00195 int
00196 asr_sick_lms_400::asr_sick_lms_400::GetMACAddress (char** macaddress)
00197 {
00198 char *mac = (char*) malloc (20);
00199 int index = 0;
00200 char* tmp;
00201
00202 SendCommand ("sRN EImac ");
00203 if (ReadAnswer () != 0)
00204 return (-1);
00205
00206 strtok ((char*) buffer_, " ");
00207 strtok (NULL, " ");
00208
00209 for (int i = 0; i < 6; i++)
00210 {
00211 tmp = strtok (NULL, "-");
00212 strncpy (&mac[index], tmp, 2);
00213 index += 2;
00214 mac[index++] = ':';
00215 }
00216
00217 mac[--index] = 0;
00218 *macaddress = mac;
00219 return (0);
00220 }
00221
00223
00224 int
00225 asr_sick_lms_400::asr_sick_lms_400::SetIP (char* ip)
00226 {
00227 unsigned char* ip_str;
00228 ip_str = ParseIP (ip);
00229 char cmd[80];
00230
00231 snprintf (cmd, 80, "sWN EIip %X %X %X %X", ip_str[0], ip_str[1], ip_str[2], ip_str[3]);
00232 free (ip_str);
00233 SendCommand (cmd);
00234
00235 return (ReadAnswer ());
00236 }
00237
00239
00240 int
00241 asr_sick_lms_400::asr_sick_lms_400::SetGateway (char* gw)
00242 {
00243 unsigned char* gw_str;
00244 gw_str = ParseIP (gw);
00245 char cmd[CMD_BUFFER_SIZE];
00246
00247 snprintf (cmd, CMD_BUFFER_SIZE, "sWN EIgate %X %X %X %X", gw_str[0], gw_str[1], gw_str[2], gw_str[3]);
00248 free (gw_str);
00249 SendCommand (cmd);
00250
00251 return (ReadAnswer ());
00252 }
00253
00255
00256 int
00257 asr_sick_lms_400::asr_sick_lms_400::SetNetmask (char* mask)
00258 {
00259 unsigned char* mask_str;
00260 mask_str = ParseIP (mask);
00261 char cmd[CMD_BUFFER_SIZE];
00262
00263 snprintf (cmd, CMD_BUFFER_SIZE, "sWN EImask %X %X %X %X", mask_str[0], mask_str[1], mask_str[2], mask_str[3]);
00264 free (mask_str);
00265 SendCommand (cmd);
00266
00267 return (ReadAnswer ());
00268 }
00269
00271
00272 int
00273 asr_sick_lms_400::asr_sick_lms_400::SetPort (uint16_t port)
00274 {
00275 char cmd[CMD_BUFFER_SIZE];
00276
00277 snprintf (cmd,CMD_BUFFER_SIZE, "sWN EIport %04X", port);
00278 SendCommand (cmd);
00279
00280 return (ReadAnswer ());
00281 }
00282
00284
00285 int
00286 asr_sick_lms_400::asr_sick_lms_400::ResetDevice ()
00287 {
00288 const char* cmd = "sMN mDCreset ";
00289 SendCommand (cmd);
00290
00291 return (ReadAnswer ());
00292 }
00293
00295
00296 int
00297 asr_sick_lms_400::asr_sick_lms_400::TerminateConfiguration ()
00298 {
00299 const char* cmd = "sMN Run";
00300 SendCommand (cmd);
00301
00302 return (ReadConfirmationAndAnswer ());
00303 }
00304
00306
00307 int
00308 asr_sick_lms_400::asr_sick_lms_400::SetAngularResolution (const char* password, float ang_res,
00309 float angle_start, float angle_range)
00310 {
00311 char cmd[CMD_BUFFER_SIZE];
00312 snprintf (cmd, CMD_BUFFER_SIZE, "sMN mSCconfigbyang 04 %s %+f 01 %+f %+f",
00313 password, ang_res, angle_start, angle_range);
00314 SendCommand (cmd);
00315
00316 return (ReadConfirmationAndAnswer ());
00317 }
00318
00320
00321 int
00322 asr_sick_lms_400::asr_sick_lms_400::SetScanningFrequency (const char* password, float freq,
00323 float angle_start, float angle_range)
00324 {
00325 char cmd[CMD_BUFFER_SIZE];
00326 snprintf (cmd, CMD_BUFFER_SIZE, "sMN mSCconfigbyfreq 04 %s %+f 01 %+f %+f",
00327 password, freq, angle_start, angle_range);
00328 SendCommand (cmd);
00329
00330 return (ReadConfirmationAndAnswer ());
00331 }
00332
00334
00335 int
00336 asr_sick_lms_400::asr_sick_lms_400::SetResolutionAndFrequency (float freq, float ang_res,
00337 float angle_start, float angle_range)
00338 {
00339 char cmd[CMD_BUFFER_SIZE];
00340 snprintf (cmd, CMD_BUFFER_SIZE, "sMN mSCsetscanconfig %+.2f %+.2f %+.2f %+.2f",
00341 freq, ang_res, angle_start, angle_range);
00342 SendCommand (cmd);
00343
00344 int error = ReadConfirmationAndAnswer ();
00345
00346
00347 if (error == 0)
00348 {
00349 strtok ((char*)buffer_, " "); strtok (NULL, " ");
00350 int ErrorCode = strtol (strtok (NULL, " "), NULL, 16);
00351 long int sf = strtol (strtok (NULL, " "), NULL, 16);
00352 long int re = strtol (strtok (NULL, " "), NULL, 16);
00353
00354 if ((ErrorCode != 0) && (verbose_ > 0))
00355 printf (">> Warning: got an error code %d\n", ErrorCode);
00356
00357 scanning_frequency_ = sf;
00358 resolution_ = re;
00359
00360 if (verbose_ > 0)
00361 printf (">> Measured value quality is: %ld [5-10]\n",
00362 strtol (strtok (NULL, " "), NULL, 16));
00363 }
00364
00365 return (error);
00366 }
00367
00369
00370 int
00371 asr_sick_lms_400::asr_sick_lms_400::StartMeasurement (bool intensity)
00372 {
00373 char cmd[CMD_BUFFER_SIZE];
00374 if (intensity)
00375 snprintf (cmd, CMD_BUFFER_SIZE, "sMN mLRreqdata %x", 0x20);
00376 else
00377 snprintf (cmd, CMD_BUFFER_SIZE, "sMN mLRreqdata %x", 0x21);
00378
00379 SendCommand (cmd);
00380
00381 return (ReadConfirmationAndAnswer ());
00382 }
00383
00385
00386 sensor_msgs::LaserScan
00387 asr_sick_lms_400::asr_sick_lms_400::ReadMeasurement ()
00388 {
00389 sensor_msgs::LaserScan scan;
00390
00391 char cs_read = 0, cs_calc = 0;
00392 int length = 0;
00393 int current = 0;
00394
00395 memset (buffer_, 0, 256);
00396 if (!MeasurementQueue_->empty ())
00397 {
00398 if (verbose_ > 0)
00399 ROS_DEBUG (">>> Reading from queue...\n");
00400 memcpy (buffer_, (char*) MeasurementQueue_->front ().string, MeasurementQueue_->front ().length + 1);
00401 free (MeasurementQueue_->front ().string);
00402 MeasurementQueue_->erase (MeasurementQueue_->begin ());
00403 }
00404 else
00405 {
00406 if (verbose_ == 2)
00407 ROS_DEBUG (">>> Queue empty. Reading from socket...\n");
00408 n_ = read (sockfd_, buffer_, 8);
00409 if (n_ < 0)
00410 {
00411 if (verbose_ > 0)
00412 ROS_DEBUG (">>> E: error reading from socket!\n");
00413 return (scan);
00414 }
00415 if (buffer_[0] != 0x02 || buffer_[1] != 0x02 || buffer_[2] != 0x02 || buffer_[3] != 0x02)
00416 {
00417 if (verbose_ > 0)
00418 ROS_DEBUG (">>> E: error expected 4 bytes STX's!\n");
00419 n_ = read (sockfd_, buffer_, 255);
00420 return (scan);
00421 }
00422
00423
00424 length = ( (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | (buffer_[7]) );
00425 do
00426 {
00427 n_ = read (sockfd_, &buffer_[current], length-current);
00428 current += n_;
00429 } while (current < length);
00430
00431
00432 int ret = read (sockfd_, &cs_read, 1);
00433 if (ret < 1)
00434 {
00435 ROS_ERROR ("LMS400 didnt get any data in read %d",ret);
00436 return (scan);
00437 }
00438
00439 for (int i = 0; i < length; i++)
00440 cs_calc ^= buffer_[i];
00441
00442 if (cs_calc != cs_read)
00443 {
00444 if (verbose_ > 0)
00445 ROS_WARN (">>> E: checksums do not match!\n");
00446 return (scan);
00447 }
00448 }
00449
00450
00451 MeasurementHeader_t meas_header;
00452 memcpy (&meas_header, (void *)buffer_, sizeof (MeasurementHeader_t));
00453
00454 float min_angle = meas_header.StartingAngle / 10000.0;
00455 float resolution = meas_header.AngularStepWidth / 10000.0;
00456 float max_angle = ((float) meas_header.NumberMeasuredValues) * resolution + min_angle;
00457
00458
00459 if (verbose_ == 2)
00460 ROS_DEBUG (">>> Reading %d values from %f to %f", meas_header.NumberMeasuredValues, meas_header.StartingAngle / 10000.0,
00461 ((float) meas_header.NumberMeasuredValues) * resolution + min_angle);
00462
00463 uint16_t distance = 0;
00464 uint8_t remission = 0;
00465 int index = sizeof (MeasurementHeader_t);
00466
00467
00468 scan.angle_min = angles::from_degrees (min_angle);
00469 scan.angle_max = angles::from_degrees (max_angle);
00470 scan.angle_increment = angles::from_degrees (resolution);
00471 scan.range_min = 0.7;
00472 scan.range_max = 3.6;
00473 scan.ranges.resize (meas_header.NumberMeasuredValues);
00474 scan.intensities.resize (meas_header.NumberMeasuredValues);
00475
00476 memcpy (&scan.scan_time, &buffer_[sizeof(MeasurementHeader_t) + meas_header.NumberMeasuredValues * 3 + 14], 2);
00477
00478
00479 for (int i = 0; i < meas_header.NumberMeasuredValues; i++)
00480 {
00481 if (meas_header.Format == 0x20 || meas_header.Format == 0x21)
00482 {
00483 memcpy (&distance, (void *)&buffer_[index], sizeof (uint16_t) );
00484 index += sizeof (uint16_t);
00485 }
00486 if (meas_header.Format == 0x20 || meas_header.Format == 0x22)
00487 {
00488 memcpy (&remission, (void *)&buffer_[index], sizeof (uint8_t) );
00489 index += sizeof (uint8_t);
00490 }
00491 scan.ranges[i] = distance * meas_header.DistanceScaling / 1000.0;
00492 scan.intensities[i] = remission * meas_header.RemissionScaling;
00493
00494 if (verbose_ == 2)
00495 ROS_DEBUG (" >>> [%i] dist: %i\t remission: %i", i, distance * meas_header.DistanceScaling, remission * meas_header.RemissionScaling);
00496 }
00497
00498 scan.header.frame_id = "lms400_tilt_laser";
00499 scan.header.stamp = ros::Time::now ();
00500
00501 return (scan);
00502 }
00503
00505
00506 int
00507 asr_sick_lms_400::asr_sick_lms_400::StopMeasurement ()
00508 {
00509 char cmd[CMD_BUFFER_SIZE];
00510 snprintf (cmd, CMD_BUFFER_SIZE, "sMN mLRstopdata");
00511 SendCommand (cmd);
00512
00513 return (ReadConfirmationAndAnswer ());
00514 }
00515
00517
00518 int
00519 asr_sick_lms_400::asr_sick_lms_400::SendCommand (const char* cmd)
00520 {
00521 if (verbose_ > 0)
00522 ROS_DEBUG (">> Sent: \"%s\"\n", cmd);
00523 AssembleCommand ((unsigned char *) cmd, strlen (cmd));
00524
00525 n_ = write (sockfd_, command_, commandlength_);
00526 if (n_ < 0)
00527 return (-1);
00528
00529 return (0);
00530 }
00531
00533
00534 int
00535 asr_sick_lms_400::asr_sick_lms_400::ReadResult ()
00536 {
00537 memset (buffer_, 0, 256);
00538 n_ = read (sockfd_, buffer_, 8);
00539 if (n_ < 0)
00540 return (-1);
00541
00542 if (buffer_[0] != 0x02 || buffer_[1] != 0x02 || buffer_[2] != 0x02 || buffer_[3] != 0x02)
00543 {
00544 if (verbose_ > 0)
00545 ROS_WARN ("> E: expected 4 bytes STX's!");
00546 n_ = read (sockfd_, buffer_, 255);
00547 return (-1);
00548 }
00549
00550
00551 int length = ( (buffer_[4] << 24) | (buffer_[5] << 16) | (buffer_[6] << 8) | (buffer_[7]) );
00552 int current = 0;
00553 do
00554 {
00555 n_ = read (sockfd_, &buffer_[current], length-current);
00556 current += n_;
00557 } while (current < length);
00558
00559 bufferlength_ = length;
00560 if ((verbose_ > 0) && (buffer_[0] != 0x20))
00561 ROS_DEBUG (">> Received: \"%s\"\n", buffer_);
00562
00563
00564 if (strncmp ((const char*)buffer_, "sFA", 3) == 0)
00565 {
00566 strtok ((char*)buffer_, " ");
00567 ROS_DEBUG (">> E: Got an error message with code 0x%s\n", strtok (NULL, " "));
00568 }
00569
00570
00571 char cs_read = 0;
00572 int ret = read (sockfd_, &cs_read, 1);
00573 if (ret < 1)
00574 {
00575 ROS_ERROR ("LMS400 didnt get any data in read %d",ret);
00576 return (-1);
00577 }
00578
00579 if (buffer_[0] == 's')
00580 return (0);
00581 else if (buffer_[0] == 0x20)
00582 return (ReadResult ());
00583 else if (bufferlength_ > sizeof (MeasurementHeader_t))
00584 {
00585 if (verbose_ > 0)
00586 ROS_DEBUG (">>>> ReadResult: probably found a data packet!\n>>>> %s\n", buffer_);
00587
00588 unsigned char* tmp = (unsigned char*) malloc (bufferlength_ + 1);
00589 memcpy (tmp, buffer_, bufferlength_ + 1);
00590 MeasurementQueueElement_t q;
00591 q.string = tmp;
00592 q.length = bufferlength_;
00593 MeasurementQueue_->push_back (q);
00594
00595 return (ReadResult ());
00596 }
00597
00598 return (0);
00599 }
00600
00602
00603 int
00604 asr_sick_lms_400::asr_sick_lms_400::ReadAnswer ()
00605 {
00606 return (ReadResult ());
00607 }
00608
00610
00611 int
00612 asr_sick_lms_400::asr_sick_lms_400::ReadConfirmationAndAnswer ()
00613 {
00614 ReadResult ();
00615 if (buffer_[0] == 's' && buffer_[1] == 'F' && buffer_[2] == 'A')
00616 return (-1);
00617 else
00618 return (ReadResult ());
00619 }
00620
00622
00623 int
00624 asr_sick_lms_400::asr_sick_lms_400::AssembleCommand (unsigned char* cmd, int len)
00625 {
00626 unsigned char checksum = 0;
00627 int index = 0;
00628
00629 command_[0] = 0x02;
00630 command_[1] = 0x02;
00631 command_[2] = 0x02;
00632 command_[3] = 0x02;
00633 command_[4] = (len >> 24) & 0xff;
00634 command_[5] = (len >> 16) & 0xff;
00635 command_[6] = (len >> 8) & 0xff;
00636 command_[7] = (len ) & 0xff;
00637
00638 for (index = 0; index < len; index++)
00639 {
00640 command_[index + 8] = cmd[index];
00641 checksum ^= cmd[index];
00642 }
00643 command_[8 + len] = checksum;
00644 command_[9 + len] = 0x00;
00645
00646 commandlength_ = 9 + len;
00647 return (0);
00648 }