58 #define WIN32_LEAN_AND_MEAN 
   80 #include <ros/console.h> 
   89 #define MAX_NAME_LEN (1024) 
   92 #define SICK_SCAN_TEST_MAJOR_VER "001" 
   93 #define SICK_SCAN_TEST_MINOR_VER "000"   
   94 #define SICK_SCAN_TEST_PATCH_LEVEL "000" 
  105                 valueVal = _valueVal;
 
  106     setCheckStatus(999,
"untested");
 
  112     this->nodePtr = paramEntryPtr;
 
  117       return( this->nodePtr);
 
  119         void setValues(std::string _nameVal, std::string _typeVal, std::string _valueVal)
 
  123                 valueVal = _valueVal;
 
  135     valueMinVal = _valueMinVal;
 
  136     valueMaxVal = _valueMaxVal;
 
  185         std::string valueVal;
 
  186   std::string valueMinVal;
 
  187   std::string valueMaxVal;
 
  190   std::string errorMsg;
 
  201   kill(tokill, SIGTERM);
 
  208         std::vector<paramEntryAscii> tmpList;
 
  214                 std::string nameVal = 
"";
 
  215                 std::string typeVal = 
"";
 
  216                 std::string valueVal = 
"";
 
  217     std::string minValueVal = 
"";
 
  218     std::string maxValueVal = 
"";
 
  220     bool minValFnd = 
false;
 
  221     bool maxValFnd = 
false;
 
  224                 const char *val = paramEntry->
Value();
 
  225                 bool searchAttributes = 
true;
 
  226                 if (strcmp(val,
"param") == 0)
 
  232                         searchAttributes = 
false;
 
  240                         searchAttributes = 
false;
 
  242                 if (searchAttributes)
 
  246                         const char *tag = 
node->Name();
 
  247                         const char *val = 
node->Value();
 
  249                         if (strcmp(tag, 
"name") == 0)
 
  253                         if (strcmp(tag, 
"type") == 0)
 
  257                         if (strcmp(tag, 
"value") == 0)
 
  261       if (strcmp(tag, 
"valueMin") == 0)
 
  267       if (strcmp(tag, 
"valueMax") == 0)
 
  280     if (maxValFnd && minValFnd)
 
  286                 tmpList.push_back(tmpEntry);
 
  298         bool fndParam = 
false;
 
  303                 if (paramEntry != 
NULL)
 
  306                         node->RemoveChild(paramEntry);
 
  308         } 
while (fndParam == 
true);
 
  310         for (
int i = 0; i < paramOrgList.size(); i++)
 
  317                 node->LinkEndChild(paramTmp);
 
  325   std::string 
cmd = cmdLine;
 
  326   typedef std::vector<std::string > split_vector_type;
 
  328   split_vector_type splitVec; 
 
  329   boost::split(splitVec, cmdLine, boost::is_any_of(
" "), boost::token_compress_on); 
 
  343       execl(
"/opt/ros/kinetic/bin/roslaunch", splitVec[0].c_str(), splitVec[1].c_str(),  splitVec[2].c_str(), 
NULL); 
 
  364 int createTestLaunchFile(std::string launchFileFullName, std::vector<paramEntryAscii> entryList, std::string& testLaunchFile)
 
  366         printf(
"Try loading launchfile :%s",launchFileFullName.c_str());
 
  368         doc.
LoadFile(launchFileFullName.c_str());
 
  370         if (doc.
Error() == 
true)
 
  380                 for (
int i = 0; i < entryList.size(); i++)
 
  382                         bool replaceEntry = 
false;
 
  383                         for (
int j = 0; j < paramOrgList.size(); j++)
 
  385                                 if (entryList[i].
getName().compare(paramOrgList[j].
getName()) == 0)
 
  387                                         paramOrgList[j].setValues(entryList[i].
getName(), entryList[i].getType(), entryList[i].getValue());
 
  391                         if (replaceEntry == 
false)  
 
  394                                 paramOrgList.push_back(tmp);
 
  402         size_t pos = launchFileFullName.rfind(
'.');
 
  403         std::string resultFileName = 
"";
 
  405         if (pos != std::string::npos)
 
  407                 resultFileName = launchFileFullName.substr(0, pos);
 
  408                 resultFileName += 
"_test.launch";
 
  409                 doc.
SaveFile(resultFileName.c_str());
 
  410                 testLaunchFile = resultFileName;
 
  432         int intensity_idx = -1;
 
  433         int cartesianIdxArr[3];
 
  434         for (
int i = 0; i < 3; i++)
 
  436                 cartesianIdxArr[i] = -1;
 
  440         for (
int i = 0; i < cloud_msg->fields.size(); i++)
 
  442                 std::string fieldName =         cloud_msg->fields[i].name;
 
  443                 if (fieldName.compare(
"intensity") == 0)
 
  447                 if (fieldName.compare(
"x") == 0)
 
  449                         cartesianIdxArr[0] = i;
 
  451                 if (fieldName.compare(
"y") == 0)
 
  453                         cartesianIdxArr[1] = i;
 
  455                 if (fieldName.compare(
"z") == 0)
 
  457                         cartesianIdxArr[2] = i;
 
  461         if (intensity_idx != -1)
 
  463                 float intensitySum = 0.0;
 
  464                 float intensity2Sum = 0.0;
 
  470                         idx *= cloud_msg->point_step;  
 
  471                         int relOff = cloud_msg->fields[intensity_idx].offset;
 
  472                         float *intensityPtr = (
float *)(&(cloud_msg->data[idx+relOff]));
 
  473                         float intensity = *intensityPtr;
 
  474                         intensitySum += intensity;
 
  475                         intensity2Sum += intensity * intensity;
 
  477                 if (intensityNum > 1)
 
  479                         intensityStdDev = (intensity2Sum - 1.0 / intensityNum * (intensitySum * intensitySum));
 
  487         if (cartesianIdxArr[0] != -1 &&cartesianIdxArr[1] != -1 &&cartesianIdxArr[2] != -1)
 
  489                 float rangeSum = 0.0;
 
  490                 float range2Sum = 0.0;
 
  496                                 idx *= cloud_msg->point_step;  
 
  497                                 int relOffX = cloud_msg->fields[cartesianIdxArr[0]].offset;
 
  498                                 float *XPtr = (
float *)(&(cloud_msg->data[idx+relOffX]));
 
  500                                 int relOffY = cloud_msg->fields[cartesianIdxArr[1]].offset;
 
  501                                 float *YPtr = (
float *)(&(cloud_msg->data[idx+relOffY]));
 
  503                                 int relOffZ = cloud_msg->fields[cartesianIdxArr[2]].offset;
 
  504                                 float *ZPtr = (
float *)(&(cloud_msg->data[idx+relOffZ]));
 
  506                                 float range =sqrt(X*X+Y*Y+Z*Z);
 
  508                                 range2Sum += range * range;
 
  512                         rangeStdDev = (range2Sum - 1.0 / rangeNum * (rangeSum * rangeSum));
 
  519         ROS_INFO(
"valid PointCloud2 message received");
 
  577         std::string searchPattern = 
"(.*)cmake\\-build\\-debug.*";
 
  578         boost::regex expr(searchPattern);
 
  581         if (boost::regex_search(exeName, what, expr))
 
  583                 std::string prefixPath = what[1];  
 
  597         typedef std::vector<std::string > split_vector_type;
 
  599         split_vector_type splitVec; 
 
  600         boost::split(splitVec, pathList, boost::is_any_of(
":"), boost::token_compress_on); 
 
  601         if (splitVec.size() > 0)
 
  603                 packagePath = splitVec[0];
 
  606         for (
int i = 0; i < splitVec.size(); i++)
 
  609                 std::string tmpFileName = splitVec[i] + 
"/" + xmlFileName;
 
  610                 fin = fopen(tmpFileName.c_str(),
"r");
 
  613                         packagePath = splitVec[i];
 
  621          packageRootFolder = 
"";
 
  623         typedef std::vector<std::string > split_vector_type;
 
  624         split_vector_type splitVec; 
 
  625         boost::split(splitVec, exePath, boost::is_any_of(
"/"), boost::token_compress_on); 
 
  627         for (
int i = splitVec.size() - 1; i >= 0; i--)  
 
  629                 std::string tmpPath = 
"";
 
  630                 for (
int j = 1; j < i; j++)
 
  633                         tmpPath += splitVec[j];
 
  636                 std::string fileTmpPath = tmpPath;
 
  637                 fileTmpPath += 
"/package.xml";
 
  638                 if (boost::filesystem::exists(fileTmpPath))
 
  640                         packageRootFolder = tmpPath;
 
  656 int main(
int argc, 
char **argv)
 
  659         char sep = boost::filesystem::path::preferred_separator;
 
  660         std::string prefix = 
".";
 
  661         std::string packageRootFolder;
 
  663         std::string exeName = argv[0];
 
  667     printf(
"Usage: %s <XML-Test-Ctrl-File>\n", exeName.c_str());
 
  669     printf(
"The XML-Test-Ctrl-File controls the parameter checking of various scanner types.");
 
  670     printf(
"The XML-File sick_scan_test.xml in the test-Directory shows an example of this file type.\n");
 
  675     printf(
"Given program arguments:\n");
 
  676       for (
int i = 0; i < argc; i++)
 
  678           printf(
"%d: %s\n", i, argv[i]);
 
  684         prefix = std::string(
"..") + sep + std::string(
"..") + sep + 
"test";
 
  693         printf(
"Nodename:  %s\n", nodeName.c_str());
 
  696         printf(
"Package Path: %s\n", packageRootFolder.c_str());
 
  699         pPath = 
getenv(
"ROS_PACKAGE_PATH");
 
  701         pPath = 
"..\\..:\tmp";
 
  705                 ROS_INFO(
"Current root path entries for launch file search: %s\n", pPath);
 
  709                 ROS_FATAL(
"Cannot find ROS_PACKAGE_PATH - please run <Workspace>/devel/setup.bash");
 
  712         std::string packagePath;
 
  714   std::string testCtrlXmlFileName = argv[1];
 
  719   boost::replace_all(testCtrlXmlFileName, 
"$ROS_PACKAGE_PATH", packagePath);
 
  722         testCtrlXmlFileName = packagePath + std::string(1,
'/') + testCtrlXmlFileName;
 
  724         doc.
LoadFile(testCtrlXmlFileName.c_str());
 
  727                 ROS_ERROR(
"Package root folder %s", packageRootFolder.c_str());
 
  728                 ROS_ERROR(
"Cannot load/parse %s", testCtrlXmlFileName.c_str());
 
  733   bool launch_only = 
false;
 
  734         boost::filesystem::path p(testCtrlXmlFileName);
 
  735         boost::filesystem::path parentPath = p.parent_path();
 
  736         std::string pathName = parentPath.string();
 
  737         std::string launchFilePrefix = parentPath.parent_path().string() + std::string(1, sep) + 
"launch" + std::string(1, sep);
 
  749                 if (fileNameEntry == 
NULL)
 
  751                         ROS_ERROR(
"Cannot find tag <filename>\n");
 
  755                 if (fileNameVal != 
NULL)
 
  757                         ROS_INFO(
"Processing launch file %s\n", fileNameVal->
Value());
 
  758                         std::string launchFileFullName = launchFilePrefix + fileNameVal->
Value();
 
  759                         ROS_INFO(
"Processing %s\n", launchFileFullName.c_str());
 
  761                         if (paramListNode != 
NULL)
 
  763                                 std::vector<paramEntryAscii> paramList = 
getParamList(paramListNode);
 
  764         for (
int i = 0; i < paramList.size(); i++)
 
  766           if (paramList[i].
getName().compare(
"launch_only") == 0)
 
  768             if (paramList[i].getValue().compare(
"true") == 0)
 
  770               printf(
"launch_only set to true. Just modifying launch file and launch (without testing).");
 
  778         std::string testLaunchFile;
 
  780                                 std::string commandLine;
 
  781                                 boost::filesystem::path p(testLaunchFile);
 
  782                                 std::string testOnlyLaunchFileName = p.filename().string();
 
  783                                 commandLine = 
"roslaunch sick_scan " + testOnlyLaunchFileName;
 
  784                                 ROS_INFO(
"launch ROS test ... [%s]", commandLine.c_str());
 
  792           printf(
"Launch file [ %s ] started ...\n", commandLine.c_str());
 
  793           printf(
"No further testing...\n");
 
  799                                 ROS_INFO(
"If you receive an error message like \"... is neither a launch file ... \"" 
  800                                         "please source ROS env. via source ./devel/setup.bash");
 
  804                                 if (resultListNode != 
NULL)
 
  806                                         std::vector<paramEntryAscii> resultList = 
getParamList(resultListNode);
 
  808           enum KeyWord_Idx {MIN_ANG_KEYWORD_IDX, MAX_ANG_KEYWORD_IDX,
 
  809               SCAN_TIME_INCREMENT_KEYWORD_IDX,
 
  810               SCAN_ANGLE_INCREMENT_KEYWORD_IDX,
 
  811               MIN_RANGE_KEYWORD_IDX,
 
  812               MAX_RANGE_KEYWORD_IDX,
 
  815           std::vector<std::string> keyWordList;
 
  816           keyWordList.resize(KEYWORD_IDX_NUM);
 
  818           keyWordList[MIN_ANG_KEYWORD_IDX] = 
"min_ang";
 
  819           keyWordList[MAX_ANG_KEYWORD_IDX] = 
"max_ang";
 
  820           keyWordList[MIN_RANGE_KEYWORD_IDX] = 
"range_min";
 
  821           keyWordList[MAX_RANGE_KEYWORD_IDX] = 
"range_max";
 
  822           keyWordList[SCAN_ANGLE_INCREMENT_KEYWORD_IDX] = 
"angle_increment";
 
  823           keyWordList[SCAN_TIME_INCREMENT_KEYWORD_IDX] = 
"time_increment";
 
  825                                         for (
int i = 0; i < resultList.size(); i++)
 
  828             for (
int ki = 0; ki < keyWordList.size(); ki++)
 
  831             float measurementVal = .0F;
 
  832             std::string keyWordTag = keyWordList[ki];
 
  840               case   MIN_RANGE_KEYWORD_IDX: measurementVal = 
range_min; 
break;
 
  841               case   MAX_RANGE_KEYWORD_IDX: measurementVal = 
range_max; 
break;
 
  842               default: printf(
"Did not find a correspondence for index %d\n", ki); 
break;
 
  844             char errMsg[255] = {0};
 
  845             if (keyWordTag.compare(
"min_ang") == 0)
 
  849             if (resultList[i].
getName().compare(keyWordTag) == 0)
 
  852               enum Expected_Idx {MIN_EXP_IDX, DEF_EXP_IDX, MAX_EXP_IDX, EXP_IDX_NUM};
 
  853               float expectedValues[EXP_IDX_NUM];
 
  854               std::string valString;
 
  856               for (
int j = 0; j < EXP_IDX_NUM; j++)
 
  860                   case MIN_EXP_IDX:  valString = resultList[i].getMinValue(); 
break;
 
  861                   case DEF_EXP_IDX:  valString = resultList[i].getValue(); 
break;
 
  862                   case MAX_EXP_IDX:  valString = resultList[i].getMaxValue(); 
break;
 
  863                   default: 
ROS_ERROR(
"Check index"); 
break;
 
  867                 const char *valPtr = valString.c_str();
 
  871                   sscanf(valPtr, 
"%f", &tmpVal);
 
  872                   expectedValues[j] = tmpVal;
 
  875               valString = resultList[i].getMinValue();
 
  878               std::string resultStr = 
"FAILED";
 
  879               std::string appendResultStr = 
" <-----";
 
  880               if ( (measurementVal >=  expectedValues[MIN_EXP_IDX]) && (measurementVal <=  expectedValues[MAX_EXP_IDX]))
 
  882                 appendResultStr = 
"";
 
  883                 resultStr = 
"PASSED";
 
  890               sprintf(errMsg, 
"CHECK %s! Key: %-20s %14.9f in [%14.9f,%14.9f] %s", resultStr.c_str(), keyWordTag.c_str(), measurementVal,
 
  891                       expectedValues[MIN_EXP_IDX], expectedValues[MAX_EXP_IDX], appendResultStr.c_str());
 
  893               printf(
"%s\n", errMsg);
 
  894               resultList[i].setCheckStatus(errorCode, (errorCode == 0) ? 
"OK" : errMsg);
 
  900             if (resultList[i].
getName().compare(
"shotsPerLayer") == 0)
 
  902                                                         int expectedWidth = -1;
 
  903                                                         std::string valString = resultList[i].getValue();
 
  904                                                         const char *valPtr = valString.c_str();
 
  907                                                                 sscanf(valPtr, 
"%d", &expectedWidth);
 
  915                                                                 printf(
"CHECK PASSED! WIDTH %d == %d\n", expectedWidth, 
cloud_width);
 
  920                 printf(
"CHECK FAILED! WIDTH %d <> %d\n", expectedWidth, 
cloud_width);
 
  924               resultList[i].setCheckStatus(errorCode, (errorCode == 0) ? 
"OK" : 
"Unexpected number of shots");
 
  927                                                 if (resultList[i].
getName().compare(
"pointCloud2Height") == 0)
 
  929                 int expectedHeight = -1;
 
  930                 std::string valString = resultList[i].getValue();
 
  931                 const char *valPtr = valString.c_str();
 
  934                   sscanf(valPtr, 
"%d", &expectedHeight);
 
  940                   printf(
"CHECK PASSED! HEIGHT %d == %d\n", expectedHeight, 
cloud_height);
 
  945                   printf(
"CHECK FAILED! HEIGHT %d <> %d\n", expectedHeight, 
cloud_height);
 
  948                 resultList[i].setCheckStatus(errorCode, (errorCode == 0) ? 
"OK" : 
"Unexpected pointCloud2 height");
 
  952             if (resultList[i].
getName().compare(
"RSSIEnabled") == 0)
 
  954               int expectedWidth = -1;
 
  955               std::string valString = resultList[i].getValue();
 
  956               bool rssiEnabled = 
false;
 
  957               if (boost::iequals(valString, 
"true"))
 
  960               } 
else if (boost::iequals(valString, 
"false"))
 
  965                 ROS_WARN(
"RSSIEnabled parameter wrong. True or False are valid parameters!\n");
 
  970               if (rssiEnabled == 
true)
 
  974                   printf(
"CHECK PASSED! RSSI Standard deviation %.3e is not 0.\n",
intensityStdDev);
 
  978                   printf(
"CHECK FAILED!  RSSI standard deviation is samller than %.10e even though RSSI is enabled\n",
intensityStdDev);
 
  984               if (rssiEnabled == 
false)
 
  988                   printf(
"CHECK FAILED! RSSI standard deviation %.3e is bigger than 1e-5 even though RSSI is disabled\n",
intensityStdDev);
 
  992                   printf(
"CHECK PASSED!  RSSI Standard deviation %.3e is smaller than 1e-5.\n",
intensityStdDev);
 
  998               if (resultList[i].
getName().compare(
"ranges") == 0)
 
 1000                 int expectedWidth = -1;
 
 1001                 std::string valString = resultList[i].getValue();
 
 1002                 bool rangeTest=
false;
 
 1003                 if (boost::iequals(valString, 
"true"))
 
 1009                   ROS_WARN(
"ranges parameter wrong. True or False are valid parameters!\n");
 
 1014                 if (rangeTest==
true)
 
 1018                     printf(
"CHECK PASSED! Range Standard deviation %.3e is not 0.\n", 
rangeStdDev);
 
 1023                     printf(
"CHECK FAILED!  Range standard deviation %.3e is smaller than 1e-5!\n", 
rangeStdDev);
 
 1027                   resultList[i].setCheckStatus(errorCode, (errorCode == 0) ? 
"OK" : 
"Range standard deviation is 0 !\n");
 
 1032             TiXmlElement *paramSet = resultList[i].getPointerToXmlNode();
 
 1033             paramSet->
SetAttribute(
"errorCode", resultList[i].getErrorCode());
 
 1034             paramSet->
SetAttribute(
"errorMsg", resultList[i].getErrorMsg().c_str());
 
 1039         printf(
"Killing process %d\n", pidId);
 
 1042         std::string testCtrlResultXmlFileName = 
"";
 
 1043         size_t pos = testCtrlXmlFileName.rfind(
'.');
 
 1044         if (pos != std::string::npos)
 
 1046           boost::filesystem::path tmpFilePath =testCtrlXmlFileName.substr(0,pos);
 
 1047           boost::filesystem::path xmlDir= tmpFilePath.parent_path();
 
 1048                                         std::string xmlDirName = xmlDir.string();
 
 1049                                         xmlDirName.append(
"/results");
 
 1050           if (boost::filesystem::exists(xmlDirName))
 
 1056             boost::filesystem::create_directory(xmlDirName);
 
 1058           std::string tmpFilNamewoExtension= tmpFilePath.stem().string();
 
 1059           std::string resultFileName=xmlDir.string();
 
 1060           resultFileName.append(
"/");
 
 1061           resultFileName.append(tmpFilNamewoExtension);
 
 1062           resultFileName.append(
".res");
 
 1063           printf(
"Save to %s\n", resultFileName.c_str());
 
 1064           doc.
SaveFile(resultFileName.c_str());
 
 1071                         ROS_WARN(
"Cannot find filename entry");