sick_generic_parser.cpp
Go to the documentation of this file.
00001 
00050 #ifdef _MSC_VER
00051 #pragma warning(disable: 4267)
00052 #endif
00053 
00054 #define _CRT_SECURE_NO_WARNINGS
00055 #define _USE_MATH_DEFINES
00056 #include <math.h>
00057 #include <sick_scan/sick_scan_common.h>
00058 #include <ros/ros.h>
00059 
00060 #ifdef _MSC_VER
00061 #include "sick_scan/rosconsole_simu.hpp"
00062 #endif
00063 
00064 namespace sick_scan
00065 {
00066 
00073         void ScannerBasicParam::setScannerName(std::string _s)
00074         {
00075                 scannerName = _s;
00076         }
00077 
00084         std::string ScannerBasicParam::getScannerName()
00085         {
00086                 return(scannerName);
00087         }
00088 
00089 
00096         void ScannerBasicParam::setNumberOfLayers(int _layerNum)
00097         {
00098                 numberOfLayers = _layerNum;
00099         }
00100 
00107         int ScannerBasicParam::getNumberOfLayers(void)
00108         {
00109                 return(numberOfLayers);
00110 
00111         }
00112 
00119         void ScannerBasicParam::setNumberOfShots(int _shots)
00120         {
00121                 numberOfShots = _shots;
00122         }
00123 
00130         int ScannerBasicParam::getNumberOfShots(void)
00131         {
00132                 return(numberOfShots);
00133         }
00134 
00141         void ScannerBasicParam::setNumberOfMaximumEchos(int _maxEchos)
00142         {
00143                 this->numberOfMaximumEchos = _maxEchos;
00144         }
00145 
00146 
00153         int ScannerBasicParam::getNumberOfMaximumEchos(void)
00154         {
00155                 return(numberOfMaximumEchos);
00156         }
00157 
00164         void SickGenericParser::setCurrentParamPtr(ScannerBasicParam* _ptr)
00165         {
00166                 currentParamSet = _ptr;
00167         }
00168 
00169 
00175         void ScannerBasicParam::setAngularDegreeResolution(double _res)
00176         {
00177                 angleDegressResolution = _res;
00178         }
00179 
00185         double ScannerBasicParam::getAngularDegreeResolution(void)
00186         {
00187                 return(angleDegressResolution);
00188         }
00189 
00195         void ScannerBasicParam::setExpectedFrequency(double _freq)
00196         {
00197                 expectedFrequency = _freq;
00198         }
00199 
00206         double ScannerBasicParam::getExpectedFrequency()
00207         {
00208                 return(expectedFrequency);
00209         }
00210 
00211 
00217         void ScannerBasicParam::setElevationDegreeResolution(double _elevRes)
00218         {
00219                 this->elevationDegreeResolution = _elevRes;
00220         }
00221 
00222 
00228         double ScannerBasicParam::getElevationDegreeResolution()
00229         {
00230                 return(this->elevationDegreeResolution);
00231         }
00232 
00238         void ScannerBasicParam::setUseBinaryProtocol(bool _useBinary)
00239         {
00240                 this->useBinaryProtocol = _useBinary;
00241         }
00242 
00248         void ScannerBasicParam::setDeviceIsRadar(bool _deviceIsRadar)
00249         {
00250                 deviceIsRadar = _deviceIsRadar;
00251         }
00252 
00258         bool ScannerBasicParam::getDeviceIsRadar(void)
00259         {
00260                 return(deviceIsRadar);
00261         }
00262 
00268         bool ScannerBasicParam::getUseBinaryProtocol(void)
00269         {
00270                 return(this->useBinaryProtocol);
00271         }
00277         void ScannerBasicParam::setIntensityResolutionIs16Bit(bool _IntensityResolutionIs16Bit)
00278         {
00279                 this->IntensityResolutionIs16Bit = _IntensityResolutionIs16Bit;
00280         }
00281 
00287         bool ScannerBasicParam::getIntensityResolutionIs16Bit(void)
00288         {
00289                 return(IntensityResolutionIs16Bit);
00290         }
00291 
00292 
00293 
00298         ScannerBasicParam::ScannerBasicParam()
00299         {
00300                 this->elevationDegreeResolution = 0.0;
00301                 this->setUseBinaryProtocol(false);
00302         }
00303 
00309         SickGenericParser::SickGenericParser(std::string _scanType) :
00310                 AbstractParser(),
00311                 override_range_min_((float)0.05),
00312                 override_range_max_((float)100.0),
00313                 override_time_increment_((float)-1.0)
00314         {
00315                 setScannerType(_scanType);
00316                 allowedScannerNames.push_back(SICK_SCANNER_MRS_1XXX_NAME);
00317                 allowedScannerNames.push_back(SICK_SCANNER_TIM_5XX_NAME);
00318                 allowedScannerNames.push_back(SICK_SCANNER_TIM_7XX_NAME);
00319                 allowedScannerNames.push_back(SICK_SCANNER_LMS_5XX_NAME);
00320                 allowedScannerNames.push_back(SICK_SCANNER_LMS_1XX_NAME);
00321                 allowedScannerNames.push_back(SICK_SCANNER_LMS_1XXX_NAME);
00322                 allowedScannerNames.push_back(SICK_SCANNER_MRS_6XXX_NAME);
00323                 allowedScannerNames.push_back(SICK_SCANNER_RMS_3XX_NAME); // Radar scanner
00324                 basicParams.resize(allowedScannerNames.size()); // resize to number of supported scanner types
00325                 for (int i = 0; i < basicParams.size(); i++) // set specific parameter for each scanner type - scanner type is identified by name
00326                 {
00327                         basicParams[i].setDeviceIsRadar(false); // Default
00328                         basicParams[i].setScannerName(allowedScannerNames[i]);  // set scanner type for this parameter object
00329 
00330                         if (basicParams[i].getScannerName().compare(SICK_SCANNER_MRS_1XXX_NAME) == 0)  // MRS1000 - 4 layer, 1101 shots per scan
00331                         {
00332                                 basicParams[i].setNumberOfMaximumEchos(3);
00333                                 basicParams[i].setNumberOfLayers(4);
00334                                 basicParams[i].setNumberOfShots(1101);
00335                                 basicParams[i].setAngularDegreeResolution(0.25);
00336                                 basicParams[i].setElevationDegreeResolution(2.5); // in [degree]
00337                                 basicParams[i].setExpectedFrequency(50.0);
00338                                 basicParams[i].setUseBinaryProtocol(true);
00339                                 basicParams[i].setDeviceIsRadar(false); // Default
00340                         }
00341                         if (basicParams[i].getScannerName().compare(SICK_SCANNER_LMS_1XXX_NAME) == 0)  // LMS1000 - 4 layer, 1101 shots per scan
00342                         {
00343                                 basicParams[i].setNumberOfMaximumEchos(3);
00344                                 basicParams[i].setNumberOfLayers(4);
00345                                 basicParams[i].setNumberOfShots(1101);
00346                                 basicParams[i].setAngularDegreeResolution(1.00);  // 0.25° wurde nicht unterstuetzt. (SFA 4)
00347                                 basicParams[i].setElevationDegreeResolution(0.0); // in [degree]
00348                                 basicParams[i].setExpectedFrequency(50.0);
00349                                 basicParams[i].setUseBinaryProtocol(true);
00350                                 basicParams[i].setDeviceIsRadar(false); // Default
00351                         }
00352                         if (basicParams[i].getScannerName().compare(SICK_SCANNER_TIM_5XX_NAME) == 0) // TIM_5xx - 1 Layer, max. 811 shots per scan
00353       {
00354         basicParams[i].setNumberOfMaximumEchos(1);
00355         basicParams[i].setNumberOfLayers(1);
00356         basicParams[i].setNumberOfShots(811);
00357         basicParams[i].setAngularDegreeResolution(0.3333);
00358         basicParams[i].setExpectedFrequency(15.0);
00359         basicParams[i].setUseBinaryProtocol(true);
00360                                 basicParams[i].setDeviceIsRadar(false); // Default
00361                         }
00362                         if (basicParams[i].getScannerName().compare(SICK_SCANNER_TIM_7XX_NAME) == 0) // TIM_5xx - 1 Layer, max. 811 shots per scan
00363                         {
00364                                 basicParams[i].setNumberOfMaximumEchos(1);
00365                                 basicParams[i].setNumberOfLayers(1);
00366                                 basicParams[i].setNumberOfShots(811);
00367                                 basicParams[i].setAngularDegreeResolution(0.3333);
00368                                 basicParams[i].setExpectedFrequency(15.0);
00369                                 basicParams[i].setUseBinaryProtocol(true);
00370                                 basicParams[i].setDeviceIsRadar(false); // Default
00371                         }
00372       if (basicParams[i].getScannerName().compare(SICK_SCANNER_LMS_5XX_NAME) == 0) // LMS_5xx - 1 Layer
00373       {
00374         basicParams[i].setNumberOfMaximumEchos(1);
00375         basicParams[i].setNumberOfLayers(1);
00376         basicParams[i].setNumberOfShots(381);
00377         basicParams[i].setAngularDegreeResolution(0.5);
00378         basicParams[i].setExpectedFrequency(15.0);
00379         basicParams[i].setUseBinaryProtocol(true);
00380                                 basicParams[i].setDeviceIsRadar(false); // Default
00381                         }
00382       if (basicParams[i].getScannerName().compare(SICK_SCANNER_LMS_1XX_NAME) == 0) // LMS_1xx - 1 Layer
00383       {
00384         basicParams[i].setNumberOfMaximumEchos(1);
00385         basicParams[i].setNumberOfLayers(1);
00386         basicParams[i].setNumberOfShots(1141);
00387         basicParams[i].setAngularDegreeResolution(0.5);
00388         basicParams[i].setExpectedFrequency(25.0);
00389         basicParams[i].setUseBinaryProtocol(true);
00390                                 basicParams[i].setDeviceIsRadar(false); // Default
00391                         }
00392                         if (basicParams[i].getScannerName().compare(SICK_SCANNER_MRS_6XXX_NAME) == 0) //
00393                         {
00394                                 basicParams[i].setNumberOfMaximumEchos(5);
00395                                 basicParams[i].setNumberOfLayers(24);
00396                                 basicParams[i].setNumberOfShots(925);
00397                                 basicParams[i].setAngularDegreeResolution(0.13);
00398                                 basicParams[i].setElevationDegreeResolution(1.25); // in [degree]
00399                                 basicParams[i].setExpectedFrequency(50.0);
00400                                 basicParams[i].setUseBinaryProtocol(true);
00401                                 basicParams[i].setDeviceIsRadar(false); // Default
00402                         }
00403 
00404                         if (basicParams[i].getScannerName().compare(SICK_SCANNER_RMS_3XX_NAME) == 0) // Radar
00405                         {
00406                                 basicParams[i].setNumberOfMaximumEchos(1);
00407                                 basicParams[i].setNumberOfLayers(0); // for radar scanner
00408                                 basicParams[i].setNumberOfShots(65);
00409                                 basicParams[i].setAngularDegreeResolution(0.00);
00410                                 basicParams[i].setElevationDegreeResolution(0.00); // in [degree]
00411                                 basicParams[i].setExpectedFrequency(0.00);
00412                                 basicParams[i].setUseBinaryProtocol(false); // use ASCII-Protocol
00413                                 basicParams[i].setDeviceIsRadar(true); // Device is a radar
00414 
00415                         }
00416 
00417                 }
00418 
00419                 int scannerIdx = lookUpForAllowedScanner(scannerType);
00420                 if (scannerIdx == -1)  // find index of parameter set - derived from scanner type name
00421                 {
00422                         ROS_ERROR("Scanner not supported.\n");
00423                         throw new std::string("scanner type " + scannerType + " not supported.");
00424                 }
00425                 else
00426                 {
00427                         currentParamSet = &(basicParams[scannerIdx]);
00428                 }
00429         }
00430 
00435         ScannerBasicParam *SickGenericParser::getCurrentParamPtr()
00436         {
00437                 return(currentParamSet);
00438         }
00439 
00445         int SickGenericParser::lookUpForAllowedScanner(std::string scannerName)
00446         {
00447                 int iRet = -1;
00448                 for (int i = 0; i < allowedScannerNames.size(); i++)
00449                 {
00450                         if (allowedScannerNames[i].compare(scannerName) == 0)
00451                         {
00452                                 return(i);
00453                         }
00454                 }
00455 
00456                 return(iRet);
00457         }
00458 
00463         SickGenericParser::~SickGenericParser()
00464         {
00465         }
00466 
00480         int SickGenericParser::checkForDistAndRSSI(std::vector<char *>& fields, int expected_number_of_data, int& distNum, int& rssiNum, std::vector<float>& distVal, std::vector<float>& rssiVal, int& distMask)
00481         {
00482                 int iRet = ExitSuccess;
00483                 distNum = 0;
00484                 rssiNum = 0;
00485                 int baseOffset = 20;
00486 
00487                 distMask = 0;
00488                 // More in depth checks: check data length and RSSI availability
00489                         // 25: Number of data (<= 10F)
00490                 unsigned short int number_of_data = 0;
00491                 if (strstr(fields[baseOffset], "DIST") != fields[baseOffset]) // First initial check
00492                 {
00493                         ROS_WARN("Field 20 of received data does not start with DIST (is: %s). Unexpected data, ignoring scan", fields[20]);
00494                         return ExitError;
00495                 }
00496 
00497                 int offset = 20;
00498                 do
00499                 {
00500                         bool distFnd = false;
00501                         bool rssiFnd = false;
00502                         if (strlen(fields[offset]) == 5)
00503                         {
00504                                 if (strstr(fields[offset], "DIST") == fields[offset])
00505                                 {
00506                                         distFnd = true;
00507                                         distNum++;
00508                                         int distId = -1;
00509                                         if (1 == sscanf(fields[offset], "DIST%d", &distId))
00510                                         {
00511                                                 distMask |= (1 << (distId - 1)); // set bit regarding to id
00512                                         }
00513                                 }
00514                                 if (strstr(fields[offset], "RSSI") == fields[offset])
00515                                 {
00516                                         rssiNum++;
00517                                         rssiFnd = true;
00518                                 }
00519                         }
00520                         if (rssiFnd || distFnd)
00521                         {
00522                                 offset += 5;
00523                                 if (offset >= fields.size())
00524                                 {
00525                                         ROS_WARN("Missing RSSI or DIST data");
00526                                         return ExitError;
00527                                 }
00528                                 number_of_data = 0;
00529                                 sscanf(fields[offset], "%hx", &number_of_data);
00530                                 if (number_of_data != expected_number_of_data)
00531                                 {
00532                                         ROS_WARN("number of dist or rssi values mismatching.");
00533                                         return ExitError;
00534                                 }
00535                                 offset++;
00536                                 // Here is the first value
00537                                 for (int i = 0; i < number_of_data; i++)
00538                                 {
00539                                         if (distFnd)
00540                                         {
00541                                                 unsigned short iRange;
00542                                                 float range;
00543                                                 sscanf(fields[offset + i], "%hx", &iRange);
00544                                                 range = iRange / 1000.0;
00545                                                 distVal.push_back(range);
00546                                         }
00547                                         else
00548                                         {
00549                                                 unsigned short iRSSI;
00550                                                 sscanf(fields[offset + i], "%hx", &iRSSI);
00551                                                 rssiVal.push_back((float)iRSSI);
00552                                         }
00553                                 }
00554                                 offset += number_of_data;
00555                         }
00556                         else
00557                         {
00558                                 offset++; // necessary????
00559                         }
00560                 } while (offset < fields.size());
00561 
00562                 return(iRet);
00563         }
00564 
00565 
00566         void SickGenericParser::checkScanTiming(float time_increment, float scan_time, float angle_increment, float tol)
00567         {
00568                 if (this->getCurrentParamPtr()->getNumberOfLayers() > 1)
00569                 {
00570                         return;
00571                 }
00572 
00573                 float expected_time_increment = this->getCurrentParamPtr()->getNumberOfLayers() * scan_time * angle_increment / (2.0 * M_PI);
00574                 if (fabs(expected_time_increment - time_increment) > 0.00001)
00575                 {
00576                         ROS_WARN_THROTTLE(60, "The time_increment, scan_time and angle_increment values reported by the scanner are inconsistent! "
00577                                                         "Expected time_increment: %.9f, reported time_increment: %.9f. "
00578                                                         "Perhaps you should set the parameter time_increment to the expected value. This message will print every 60 seconds.",
00579                                                                                                 expected_time_increment, time_increment);
00580                 }
00581         };
00582 
00583 
00584 
00595         int SickGenericParser::parse_datagram(char* datagram, size_t datagram_length, SickScanConfig &config,
00596                 sensor_msgs::LaserScan &msg, int &numEchos, int &echoMask)
00597         {
00598                 // echoMask introduced to get a workaround for cfg bug using MRS1104
00599                 ros::NodeHandle tmpParam("~");
00600                 bool dumpData = false;
00601                 int verboseLevel = 0;
00602                 tmpParam.getParam("verboseLevel", verboseLevel);
00603 
00604                 int HEADER_FIELDS = 32;
00605                 char* cur_field;
00606                 size_t count;
00607                 int scannerIdx = lookUpForAllowedScanner(getScannerType());
00608 
00609                 // Reserve sufficient space
00610                 std::vector<char *> fields;
00611                 fields.reserve(datagram_length / 2);
00612 
00613                 // ----- only for debug output
00614                 std::vector<char> datagram_copy_vec;
00615                 datagram_copy_vec.resize(datagram_length + 1); // to avoid using malloc. destructor frees allocated mem.
00616                 char* datagram_copy = &(datagram_copy_vec[0]);
00617 
00618                 if (verboseLevel > 0) {
00619                         ROS_WARN("Verbose LEVEL activated. Only for DEBUG.");
00620                 }
00621 
00622                 if (verboseLevel > 0)
00623                 {
00624                         static int cnt = 0;
00625                         char szDumpFileName[255] = {0};
00626                         char szDir[255] = {0};
00627 #ifdef _MSC_VER
00628       strcpy(szDir,"C:\\temp\\");
00629 #else
00630                         strcpy(szDir,"/tmp/");
00631 #endif
00632                         sprintf(szDumpFileName,"%stmp%06d.bin", szDir, cnt);
00633                         bool isBinary = this->getCurrentParamPtr()->getUseBinaryProtocol();
00634                         if (isBinary)
00635                         {
00636                                 FILE *ftmp;
00637                                 ftmp = fopen(szDumpFileName,"wb");
00638                                 if (ftmp != NULL)
00639                                 {
00640                                         fwrite(datagram, datagram_length, 1, ftmp);
00641                                         fclose(ftmp);
00642                                 }
00643                         }
00644                         cnt++;
00645                 }
00646 
00647                 strncpy(datagram_copy, datagram, datagram_length); // datagram will be changed by strtok
00648                 datagram_copy[datagram_length] = 0;
00649 
00650                 // ----- tokenize
00651                 count = 0;
00652                 cur_field = strtok(datagram, " ");
00653 
00654                 while (cur_field != NULL)
00655                 {
00656                         fields.push_back(cur_field);
00657                         //std::cout << cur_field << std::endl;
00658                         cur_field = strtok(NULL, " ");
00659                 }
00660 
00661                 //std::cout << fields[27] << std::endl;
00662 
00663                 count = fields.size();
00664 
00665 
00666                 if (verboseLevel > 0)
00667                 {
00668                         static int cnt = 0;
00669                         char szDumpFileName[255] = {0};
00670                         char szDir[255] = {0};
00671 #ifdef _MSC_VER
00672                         strcpy(szDir,"C:\\temp\\");
00673 #else
00674                         strcpy(szDir,"/tmp/");
00675 #endif
00676                         sprintf(szDumpFileName,"%stmp%06d.txt", szDir, cnt);
00677                         ROS_WARN("Verbose LEVEL activated. Only for DEBUG.");
00678                         FILE *ftmp;
00679                         ftmp = fopen(szDumpFileName,"w");
00680       if (ftmp != NULL)
00681                         {
00682                                 int i;
00683                                 for (i = 0; i < count; i++)
00684                                 {
00685                                         fprintf(ftmp, "%3d: %s\n", i, fields[i]);
00686                                 }
00687                                 fclose(ftmp);
00688                         }
00689                         cnt++;
00690                 }
00691 
00692                 // Validate header. Total number of tokens is highly unreliable as this may
00693                 // change when you change the scanning range or the device name using SOPAS ET
00694                 // tool. The header remains stable, however.
00695                 if (count < HEADER_FIELDS)
00696                 {
00697                         ROS_WARN(
00698                                 "received less fields than minimum fields (actual: %d, minimum: %d), ignoring scan", (int)count, HEADER_FIELDS);
00699                         ROS_WARN("are you using the correct node? (124 --> sick_tim310_1130000m01, > 33 --> sick_tim551_2050001, 580 --> sick_tim310s01, 592 --> sick_tim310)");
00700                         // ROS_DEBUG("received message was: %s", datagram_copy);
00701                         return ExitError;
00702                 }
00703 
00704                 if (basicParams[scannerIdx].getNumberOfLayers() == 1)
00705                 {
00706                         if (strcmp(fields[15], "0"))
00707                         {
00708                                 ROS_WARN("Field 15 of received data is not equal to 0 (%s). Unexpected data, ignoring scan", fields[15]);
00709                                 return ExitError;
00710                         }
00711                 }
00712                 else // fields[15] enthält keine "0"
00713                 {
00714 
00715                         //other layers are here on alternate values
00716                         // ROS_WARN("Field 15 of received data is not equal to 0 (%s). Unexpected data, ignoring scan", fields[15]);
00717                         // return ExitError;
00718                 }
00719                 if (strcmp(fields[20], "DIST1"))
00720                 {
00721                         ROS_WARN("Field 20 of received data is not equal to DIST1i (%s). Unexpected data, ignoring scan", fields[20]);
00722                         return ExitError;
00723                 }
00724 
00725                 // More in depth checks: check data length and RSSI availability
00726                 // 25: Number of data (<= 10F)
00727                 unsigned short int number_of_data = 0;
00728                 sscanf(fields[25], "%hx", &number_of_data);
00729 
00730                 int numOfExpectedShots = basicParams[scannerIdx].getNumberOfShots();
00731                 if (number_of_data < 1 || number_of_data > numOfExpectedShots)
00732                 {
00733                         ROS_WARN("Data length is outside acceptable range 1-%d (%d). Ignoring scan", numOfExpectedShots, number_of_data);
00734                         return ExitError;
00735                 }
00736                 if (count < HEADER_FIELDS + number_of_data)
00737                 {
00738                         ROS_WARN("Less fields than expected for %d data points (%zu). Ignoring scan", number_of_data, count);
00739                         return ExitError;
00740                 }
00741                 ROS_DEBUG("Number of data: %d", number_of_data);
00742 
00743                 // Calculate offset of field that contains indicator of whether or not RSSI data is included
00744                 size_t rssi_idx = 26 + number_of_data;
00745                 bool rssi = false;
00746                 if (strcmp(fields[rssi_idx], "RSSI1") == 0)
00747                 {
00748                         rssi = true;
00749                 }
00750                 unsigned short int number_of_rssi_data = 0;
00751                 if (rssi)
00752                 {
00753                         sscanf(fields[rssi_idx + 5], "%hx", &number_of_rssi_data);
00754 
00755                         // Number of RSSI data should be equal to number of data
00756                         if (number_of_rssi_data != number_of_data)
00757                         {
00758                                 ROS_WARN("Number of RSSI data is lower than number of range data (%d vs %d", number_of_data, number_of_rssi_data);
00759                                 return ExitError;
00760                         }
00761 
00762                         // Check if the total length is still appropriate.
00763                         // RSSI data size = number of RSSI readings + 6 fields describing the data
00764                         if (count < HEADER_FIELDS + number_of_data + number_of_rssi_data + 6)
00765                         {
00766                                 ROS_WARN("Less fields than expected for %d data points (%zu). Ignoring scan", number_of_data, count);
00767                                 return ExitError;
00768                         }
00769 
00770                         if (strcmp(fields[rssi_idx], "RSSI1"))
00771                         {
00772                                 ROS_WARN("Field %zu of received data is not equal to RSSI1 (%s). Unexpected data, ignoring scan", rssi_idx + 1, fields[rssi_idx + 1]);
00773                         }
00774                 }
00775 
00776                 if (basicParams[scannerIdx].getNumberOfLayers() > 1)
00777                 {
00778                         short layer = -1;
00779                         sscanf(fields[15], "%hx", &layer);
00780                         msg.header.seq = layer;
00781                 }
00782                 // ----- read fields into msg
00783                 msg.header.frame_id = config.frame_id;
00784                 // evtl. debug stream benutzen
00785                 ROS_DEBUG("publishing with frame_id %s", config.frame_id.c_str());
00786 
00787                 ros::Time start_time = ros::Time::now(); // will be adjusted in the end
00788 
00789 
00790                 /*
00791 
00792                  */
00793                  // <STX> (\x02)
00794                  // 0: Type of command (SN)
00795                  // 1: Command (LMDscandata)
00796                  // 2: Firmware version number (1)
00797                  // 3: Device number (1)
00798                  // 4: Serial number (eg. B96518)
00799                  // 5 + 6: Device Status (0 0 = ok, 0 1 = error)
00800                  // 7: Telegram counter (eg. 99)
00801                  // 8: Scan counter (eg. 9A)
00802                  // 9: Time since startup (eg. 13C8E59)
00803 
00804 
00805                  // 10: Time of transmission (eg. 13C9CBE)
00806                  // 11 + 12: Input status (0 0)
00807                  // 13 + 14: Output status (8 0)
00808                  // 15: Reserved Byte A (0)
00809 
00810                  // 16: Scanning Frequency (5DC)
00811                 unsigned short scanning_freq = -1;
00812                 sscanf(fields[16], "%hx", &scanning_freq);
00813                 msg.scan_time = 1.0 / (scanning_freq / 100.0);
00814                 // ROS_DEBUG("hex: %s, scanning_freq: %d, scan_time: %f", fields[16], scanning_freq, msg.scan_time);
00815 
00816                 // 17: Measurement Frequency (36)
00817                 unsigned short measurement_freq = -1;
00818                 sscanf(fields[17], "%hx", &measurement_freq);
00819                 msg.time_increment = 1.0 / (measurement_freq * 100.0);
00820                 if (override_time_increment_ > 0.0)
00821                 {
00822                         // Some lasers may report incorrect measurement frequency
00823                         msg.time_increment = override_time_increment_;
00824                 }
00825                 // ROS_DEBUG("measurement_freq: %d, time_increment: %f", measurement_freq, msg.time_increment);
00826 
00827                 // 18: Number of encoders (0)
00828                 // 19: Number of 16 bit channels (1)
00829                 // 20: Measured data contents (DIST1)
00830 
00831                 // 21: Scaling factor (3F800000)
00832                 // ignored for now (is always 1.0):
00833           //      unsigned int scaling_factor_int = -1;
00834           //      sscanf(fields[21], "%x", &scaling_factor_int);
00835           //
00836           //      float scaling_factor = reinterpret_cast<float&>(scaling_factor_int);
00837           //      // ROS_DEBUG("hex: %s, scaling_factor_int: %d, scaling_factor: %f", fields[21], scaling_factor_int, scaling_factor);
00838 
00839                 // 22: Scaling offset (00000000) -- always 0
00840                 // 23: Starting angle (FFF92230)
00841                 int starting_angle = -1;
00842                 sscanf(fields[23], "%x", &starting_angle);
00843                 msg.angle_min = (starting_angle / 10000.0) / 180.0 * M_PI - M_PI / 2;
00844                 // ROS_DEBUG("starting_angle: %d, angle_min: %f", starting_angle, msg.angle_min);
00845 
00846                 // 24: Angular step width (2710)
00847                 unsigned short angular_step_width = -1;
00848                 sscanf(fields[24], "%hx", &angular_step_width);
00849                 msg.angle_increment = (angular_step_width / 10000.0) / 180.0 * M_PI;
00850                 msg.angle_max = msg.angle_min + (number_of_data - 1) * msg.angle_increment;
00851 
00852                 // 25: Number of data (<= 10F)
00853                 // This is already determined above in number_of_data
00854                 int index_min = 0;
00855 
00856 #if 1  // neuer Ansatz
00857                 int distNum = 0;
00858                 int rssiNum = 0;
00859 
00860 
00861                 checkForDistAndRSSI(fields, number_of_data, distNum, rssiNum, msg.ranges, msg.intensities, echoMask);
00862                 if (config.intensity)
00863                 {
00864                         if (rssiNum > 0)
00865                         {
00866 
00867                         }
00868                         else
00869                         {
00870                                 ROS_WARN_ONCE("Intensity parameter is enabled, but the scanner is not configured to send RSSI values! "
00871                                         "Please read the section 'Enabling intensity (RSSI) output' here: http://wiki.ros.org/sick_tim.");
00872                         }
00873                 }
00874                 numEchos = distNum;
00875 #endif
00876                 // 26 + n: RSSI data included
00877                 // IF RSSI not included:
00878                 //   26 + n + 1 .. 26 + n + 3 = unknown (but seems to be [0, 1, B] always)
00879                 //   26 + n + 4 .. count - 4 = device label
00880                 //   count - 3 .. count - 1 = unknown (but seems to be 0 always)
00881                 //   <ETX> (\x03)
00882 
00883                 msg.range_min = override_range_min_;
00884                 msg.range_max = override_range_max_;
00885 
00886                 if (basicParams[scannerIdx].getNumberOfLayers() > 1)
00887                 {
00888                         char szDummy[255] = { 0 };
00889                         sprintf(szDummy, "%s_%+04d", config.frame_id.c_str(), msg.header.seq);
00890                         msg.header.frame_id = szDummy;
00891                 }
00892                 // ----- adjust start time
00893                 // - last scan point = now  ==>  first scan point = now - number_of_data * time increment
00894 #ifndef _MSC_VER  // TIMING in Simulation not correct
00895                 msg.header.stamp = start_time - ros::Duration().fromSec(number_of_data * msg.time_increment);
00896 
00897                 // - shift forward to time of first published scan point
00898                 msg.header.stamp += ros::Duration().fromSec((double)index_min * msg.time_increment);
00899 
00900                 // - add time offset (to account for USB latency etc.)
00901                 msg.header.stamp += ros::Duration().fromSec(config.time_offset);
00902 #endif
00903                 // ----- consistency check
00904 
00905                 this->checkScanTiming(msg.time_increment, msg.scan_time, msg.angle_increment, 0.00001);
00906                 return ExitSuccess;
00907                 }
00908 
00909 
00915         void SickGenericParser::set_range_min(float min)
00916         {
00917                 override_range_min_ = min;
00918         }
00919 
00925         void SickGenericParser::set_range_max(float max)
00926         {
00927                 override_range_max_ = max;
00928         }
00929 
00930 
00936   float SickGenericParser::get_range_max(void)
00937   {
00938     return(override_range_max_);
00939   }
00940 
00946   float SickGenericParser::get_range_min(void)
00947   {
00948    return(override_range_min_);
00949   }
00950 
00956         void SickGenericParser::set_time_increment(float time)
00957         {
00958                 override_time_increment_ = time;
00959         }
00960 
00967         void SickGenericParser::setScannerType(std::string _scannerType)
00968         {
00969                 scannerType = _scannerType;
00970         }
00971 
00977         std::string SickGenericParser::getScannerType(void) {
00978                 return(scannerType);
00979 
00980         }
00981 
00982 } /* namespace sick_scan */


sick_scan
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Tue Jul 9 2019 05:05:34