52 #ifdef _MSC_VER // compiling simulation for MS-Visual C++ - not defined for linux system 53 #pragma warning(disable: 4996) 54 #pragma warning(disable: 4267) // due to conversion warning size_t in the ros header file 55 #define _WIN32_WINNT 0x0501 66 #include "sick_scan/rosconsole_simu.hpp" 71 #include <sick_scan/RadarScan.h> 77 #define _USE_MATH_DEFINES 82 #define rad2deg(x) ((x) / M_PI * 180.0) 85 #define deg2rad_const (0.017453292519943295769236907684886f) 101 unsigned char *buf = (ptr);
102 unsigned char tmpChar;
103 for (
int i = 0; i < numBytes / 2; i++)
105 tmpChar = buf[numBytes - 1 - i];
106 buf[numBytes - 1 - i] = buf[i];
121 std::vector<unsigned char> result;
122 for (
int j = 0; j < s.length(); j++)
124 result.push_back(s[j]);
142 return (diagnostic_msgs::DiagnosticStatus::ERROR);
157 for (
int i = 0; i < len; i++)
159 char ch = (char) ((*replyDummy)[i + off]);
174 unsigned char sick_crc8(
unsigned char *msgBlock,
int len)
176 unsigned char xorVal = 0x00;
178 for (
int i = off; i < len; i++)
181 unsigned char val = msgBlock[i];
194 bool isParamBinary =
false;
198 for (
int i = 0; i < s.size(); i++)
202 isParamBinary =
false;
216 isParamBinary =
true;
219 if (isParamBinary ==
true)
223 unsigned long lenId = 0x00;
224 char szDummy[255] = {0};
225 for (
int i = 0; i < s.size(); i++)
244 lenId |= s[i] << (8 * (7 - i));
247 sprintf(szDummy,
"<Len=%04lu>", lenId);
254 unsigned long dataProcessed = i - 8;
264 if (dataProcessed >= (lenId - 1))
274 char ch = dest[dest.length()-1];
279 sprintf(szDummy,
"0x%02x", s[i]);
282 unsigned long dataProcessed = i - 8;
283 if (dataProcessed >= (lenId -1))
291 sprintf(szDummy,
" CRC:<0x%02x>", s[i]);
302 for (
int i = 0; i < s.size(); i++)
333 diagnosticPub_(NULL), parser_(parser)
341 dynamic_reconfigure::Server<sick_scan::SickScanConfig>::CallbackType
f;
349 double min_angle, max_angle, res_angle;
353 cfg.min_ang = min_angle;
354 cfg.max_ang = max_angle;
362 if (publish_datagram_)
372 std::string cloud_topic_val =
"cloud";
373 pn.
getParam(
"cloud_topic", cloud_topic_val);
375 ROS_INFO(
"Publishing laserscan-pointcloud2 to %s", cloud_topic_val.c_str());
413 const char requestScanData0[] = {
"\x02sEN LMDscandata 0\x03\0"};
418 printf(
"\nSOPAS - Error stopping streaming scan data!\n");
422 printf(
"\nSOPAS - Stopped streaming scan data.\n");
435 unsigned long val = 0;
436 for (
int i = 0; i < 4; i++)
459 if (reply->size() < 8)
465 const unsigned char *ptr = &((*reply)[0]);
468 if (binId == 0x02020202)
470 int replyLen = reply->size();
471 if (replyLen == 8 + cmdLen + 1)
492 std::vector<unsigned char> access_reply;
494 int result =
sendSOPASCommand(
"\x02sMN SetAccessMode 3 F4724744\x03\0", &access_reply);
497 ROS_ERROR(
"SOPAS - Error setting access mode");
502 if (access_reply_str !=
"sAN SetAccessMode 1")
504 ROS_ERROR_STREAM(
"SOPAS - Error setting access mode, unexpected response : " << access_reply_str);
512 std::vector<unsigned char> reboot_reply;
516 ROS_ERROR(
"SOPAS - Error rebooting scanner");
521 if (reboot_reply_str !=
"sAN mSCreboot")
523 ROS_ERROR_STREAM(
"SOPAS - Error rebooting scanner, unexpected response : " << reboot_reply_str);
528 ROS_INFO(
"SOPAS - Rebooted scanner");
543 printf(
"sick_scan driver exiting.\n");
554 std::string expectedAnswer =
"";
556 char cntWhiteCharacter = 0;
557 int initalTokenCnt = 2;
558 std::map<std::string, int> specialTokenLen;
559 char firstToken[1024] = {0};
560 specialTokenLen[
"sRI"] = 1;
561 std::string tmpStr =
"";
563 bool isBinary =
false;
564 for (
int i = 0; i < 4; i++)
566 if (i < requestStr.size())
568 if (requestStr[i] == 0x02)
576 int iStop = requestStr.size();
581 for (
int i = 0; i < 4; i++)
583 cmdLen |= cmdLen << 8;
584 cmdLen |= requestStr[i + 4];
590 int iStart = (isBinary ==
true) ? 8 : 0;
591 for (
int i = iStart; i < iStop; i++)
593 tmpStr += (char) requestStr[i];
597 tmpStr =
"\x2" + tmpStr;
599 if (sscanf(tmpStr.c_str(),
"\x2%s", firstToken) == 1)
601 if (specialTokenLen.find(firstToken) != specialTokenLen.end())
603 initalTokenCnt = specialTokenLen[firstToken];
608 for (
int i = iStart; i < iStop; i++)
610 if ((requestStr[i] ==
' ') || (requestStr[i] ==
'\x3'))
614 if (cntWhiteCharacter >= initalTokenCnt)
618 if (requestStr[i] ==
'\x2')
623 expectedAnswer += requestStr[i];
630 std::map<std::string, std::string> keyWordMap;
631 keyWordMap[
"sWN"] =
"sWA";
632 keyWordMap[
"sRN"] =
"sRA";
633 keyWordMap[
"sRI"] =
"sRA";
634 keyWordMap[
"sMN"] =
"sAN";
635 keyWordMap[
"sEN"] =
"sEA";
637 for (std::map<std::string, std::string>::iterator it = keyWordMap.begin(); it != keyWordMap.end(); it++)
640 std::string keyWord = it->first;
641 std::string newKeyWord = it->second;
643 size_t pos = expectedAnswer.find(keyWord);
644 if (pos == std::string::npos)
652 expectedAnswer.replace(pos, keyWord.length(), newKeyWord);
656 ROS_WARN(
"Unexpected position of key identifier.\n");
661 return (expectedAnswer);
674 std::vector<unsigned char> requestStringVec;
675 for (
int i = 0; i < requestStr.length(); i++)
677 requestStringVec.push_back(requestStr[i]);
694 std::string cmdStr =
"";
696 for (
int i = 0; i < requestStr.size(); i++)
699 cmdStr += (char) requestStr[i];
703 std::string errString;
706 errString =
"Error unexpected Sopas Answer for request " +
stripControl(requestStr);
721 std::vector<unsigned char> replyVec;
722 replyStr =
"<STX>" + replyStr +
"<ETX>";
728 std::string tmpStr =
"SOPAS Communication -" + errString;
737 if (answerStr.find(searchPattern) != std::string::npos)
745 ROS_INFO(
"IMU-Data transfer started. No checking of reply to avoid confusing with LMD Scandata\n");
750 std::string tmpMsg =
"Error Sopas answer mismatch " + errString +
"Answer= >>>" + answerStr +
"<<<";
809 ROS_FATAL(
"Failed to init device: %d", result);
815 ROS_INFO(
"Failed to init scanner Error Code: %d\nWaiting for timeout...\n" 816 "If the communication mode set in the scanner memory is different from that used by the driver, the scanner's communication mode is changed.\n" 817 "This requires a restart of the TCP-IP connection, which can extend the start time by up to 30 seconds. There are two ways to prevent this:\n" 818 "1. [Recommended] Set the communication mode with the SOPAS ET software to binary and save this setting in the scanner's EEPROM.\n" 819 "2. Use the parameter \"use_binary_protocol\" to overwrite the default settings of the driver.",
842 std::string unknownStr =
"Command or Error message not defined";
964 bool tryToStopMeasurement =
true;
968 tryToStopMeasurement =
false;
977 tryToStopMeasurement =
false;
981 if (tryToStopMeasurement)
986 switch (numberOfLayers)
1030 const int MAX_STR_LEN = 1024;
1032 int maxNumberOfEchos = 1;
1038 bool rssiFlag =
false;
1039 bool rssiResolutionIs16Bit =
true;
1040 int activeEchos = 0;
1043 pn.
getParam(
"intensity", rssiFlag);
1044 pn.
getParam(
"intensity_resolution_16bit", rssiResolutionIs16Bit);
1047 std::string sNewIPAddr =
"";
1048 boost::asio::ip::address_v4 ipNewIPAddr;
1049 bool setNewIPAddr =
false;
1050 setNewIPAddr = pn.
getParam(
"new_IP_address", sNewIPAddr);
1053 boost::system::error_code ec;
1054 ipNewIPAddr = boost::asio::ip::address_v4::from_string(sNewIPAddr, ec);
1062 setNewIPAddr =
false;
1063 ROS_ERROR(
"ERROR: IP ADDRESS could not be parsed Boost Error %s:%d", ec.category().name(), ec.value());;
1067 std::string sNTPIpAdress =
"";
1068 boost::asio::ip::address_v4 NTPIpAdress;
1069 bool setUseNTP=
false;
1070 setUseNTP = pn.
getParam(
"ntp_server_address", sNTPIpAdress);
1073 boost::system::error_code ec;
1074 NTPIpAdress = boost::asio::ip::address_v4::from_string(sNTPIpAdress, ec);
1078 ROS_ERROR(
"ERROR: NTP Server IP ADDRESS could not be parsed Boost Error %s:%d", ec.category().name(), ec.value());;
1085 pn.
getParam(
"active_echos", activeEchos);
1087 ROS_INFO(
"Parameter setting for <active_echo: %d>", activeEchos);
1088 std::vector<bool> outputChannelFlag;
1089 outputChannelFlag.resize(maxNumberOfEchos);
1092 for (i = 0; i < outputChannelFlag.size(); i++)
1110 outputChannelFlag[i] =
true;
1114 if (numOfFlags == 0)
1116 outputChannelFlag[0] =
true;
1118 ROS_WARN(
"Activate at least one echo.");
1123 int angleRes10000th = 0;
1124 int angleStart10000th = 0;
1125 int angleEnd10000th = 0;
1138 volatile bool useBinaryCmd =
false;
1141 useBinaryCmd =
true;
1144 bool useBinaryCmdNow =
false;
1147 const int shortTimeOutInMs = 5000;
1148 const int defaultTimeOutInMs = 20000;
1152 bool restartDueToProcolChange =
false;
1161 std::vector<unsigned char> replyDummy;
1162 std::vector<unsigned char> reqBinary;
1165 for (
int j = 0; j < sopasCmd.length(); j++)
1167 sopasCmdVec.push_back(sopasCmd[j]);
1175 for (
int iLoop = 0; iLoop < maxCmdLoop; iLoop++)
1179 useBinaryCmdNow = useBinaryCmd;
1184 useBinaryCmdNow = !useBinaryCmdNow;
1185 useBinaryCmd = useBinaryCmdNow;
1192 if (useBinaryCmdNow)
1233 if (
false == protocolCheck)
1235 restartDueToProcolChange =
true;
1237 useBinaryCmd = useBinaryCmdNow;
1244 if (
false == protocolCheck)
1246 restartDueToProcolChange =
true;
1248 useBinaryCmd = useBinaryCmdNow;
1259 std::string deviceIdent =
"";
1266 std::string deviceIdentKeyWord =
"sRA DeviceIdent";
1267 char *ptr = (
char *) (&(replyDummy[0]));
1269 ptr += deviceIdentKeyWord.length();
1271 sscanf(ptr,
"%d", &idLen);
1272 char *ptr2 = strchr(ptr,
' ');
1276 for (
int i = 0; i < idLen; i++)
1278 deviceIdent += *ptr2;
1285 sscanf(ptr,
"%d", &versionLen);
1286 ptr2 = strchr(ptr,
' ');
1290 deviceIdent +=
" V";
1291 for (
int i = 0; i < versionLen; i++)
1293 deviceIdent += *ptr2;
1306 long dummy0, dummy1, identLen, versionLen;
1312 const char *scanMask0 =
"%04y%04ysRA DeviceIdent %02y";
1313 const char *scanMask1 =
"%02y";
1314 unsigned char *replyPtr = &(replyDummy[0]);
1317 binScanfVec(&replyDummy, scanMask0, &dummy0, &dummy1, &identLen);
1320 int off = scanDataLen0 + identLen;
1322 std::vector<unsigned char> restOfReplyDummy = std::vector<unsigned char>(replyDummy.begin() + off,
1326 binScanfVec(&restOfReplyDummy,
"%02y", &versionLen);
1328 std::string fullIdentVersionInfo = identStr +
" V" + versionStr;
1361 int deviceState = -1;
1374 &dummy1, &deviceState);
1382 switch (deviceState)
1407 int operationHours = -1;
1415 long dummy0, dummy1;
1429 double hours = 0.1 * operationHours;
1430 pn.
setParam(
"operationHours", hours);
1437 int powerOnCount = -1;
1441 long dummy0, dummy1;
1452 pn.
setParam(
"powerOnCount", powerOnCount);
1460 char szLocationName[MAX_STR_LEN] = {0};
1462 const char *searchPattern =
"sRA LocationName ";
1463 strcpy(szLocationName,
"unknown location");
1467 long dummy0, dummy1, locationNameLen;
1468 const char *binLocationNameMask =
"%4y%4ysRA LocationName %2y";
1472 locationNameLen = 0;
1481 strcpy(szLocationName, locationNameStr.c_str());
1486 if (strstr(strPtr, searchPattern) == strPtr)
1488 const char *ptr = strPtr + strlen(searchPattern);
1489 strcpy(szLocationName, ptr);
1493 ROS_WARN(
"Location command not supported.\n");
1496 pn.
setParam(
"locationName", std::string(szLocationName));
1509 if (restartDueToProcolChange)
1521 ROS_INFO(
"IP address changed. Node restart required");
1547 angleRes10000th = (int) (boost::math::round(
1549 std::vector<unsigned char> askOutputAngularRangeReply;
1553 std::vector<unsigned char> reqBinary;
1565 int askTmpAngleRes10000th = 0;
1566 int askTmpAngleStart10000th = 0;
1567 int askTmpAngleEnd10000th = 0;
1568 char dummy0[MAX_STR_LEN] = {0};
1569 char dummy1[MAX_STR_LEN] = {0};
1572 int iDummy0, iDummy1;
1573 std::string askOutputAngularRangeStr =
replyToString(askOutputAngularRangeReply);
1589 askTmpAngleRes10000th = 0;
1590 askTmpAngleStart10000th = 0;
1591 askTmpAngleEnd10000th = 0;
1593 const char *askOutputAngularRangeBinMask =
"%4y%4ysRA LMPoutputRange %2y%4y%4y%4y";
1597 &askTmpAngleRes10000th,
1598 &askTmpAngleStart10000th,
1599 &askTmpAngleEnd10000th);
1604 numArgs = sscanf(askOutputAngularRangeStr.c_str(),
"%s %s %d %X %X %X", dummy0, dummy1,
1606 &askTmpAngleRes10000th,
1607 &askTmpAngleStart10000th,
1608 &askTmpAngleEnd10000th);
1612 double askTmpAngleRes = askTmpAngleRes10000th / 10000.0;
1613 double askTmpAngleStart = askTmpAngleStart10000th / 10000.0;
1614 double askTmpAngleEnd = askTmpAngleEnd10000th / 10000.0;
1616 angleRes10000th = askTmpAngleRes10000th;
1617 ROS_INFO(
"Angle resolution of scanner is %0.5lf [deg] (in 1/10000th deg: 0x%X)", askTmpAngleRes,
1618 askTmpAngleRes10000th);
1634 angleStart10000th = (int) (boost::math::round(10000.0 * minAngSopas));
1635 angleEnd10000th = (int) (boost::math::round(10000.0 * maxAngSopas));
1637 char requestOutputAngularRange[MAX_STR_LEN];
1639 std::vector<unsigned char> outputAngularRangeReply;
1641 sprintf(requestOutputAngularRange, pcCmdMask, angleRes10000th, angleStart10000th, angleEnd10000th);
1645 unsigned char tmpBuffer[255] = {0};
1646 unsigned char sendBuffer[255] = {0};
1648 std::vector<unsigned char> reqBinary;
1654 strcpy((
char *) tmpBuffer,
"WN LMPoutputRange ");
1655 unsigned short orgLen = strlen((
char *) tmpBuffer);
1656 colab::addIntegerToBuffer<UINT16>(tmpBuffer, orgLen, iStatus);
1657 colab::addIntegerToBuffer<UINT32>(tmpBuffer, orgLen, angleRes10000th);
1658 colab::addIntegerToBuffer<UINT32>(tmpBuffer, orgLen, angleStart10000th);
1659 colab::addIntegerToBuffer<UINT32>(tmpBuffer, orgLen, angleEnd10000th);
1667 reqBinary = std::vector<unsigned char>(sendBuffer, sendBuffer + sendLen);
1691 askOutputAngularRangeReply.clear();
1695 std::vector<unsigned char> reqBinary;
1706 char dummy0[MAX_STR_LEN] = {0};
1707 char dummy1[MAX_STR_LEN] = {0};
1709 int askAngleRes10000th = 0;
1710 int askAngleStart10000th = 0;
1711 int askAngleEnd10000th = 0;
1712 int iDummy0, iDummy1;
1715 std::string askOutputAngularRangeStr =
replyToString(askOutputAngularRangeReply);
1734 askAngleRes10000th = 0;
1735 askAngleStart10000th = 0;
1736 askAngleEnd10000th = 0;
1745 const char *askOutputAngularRangeBinMask =
"%4y%4ysRA LMPoutputRange %2y%4y%4y%4y";
1749 &askAngleRes10000th,
1750 &askAngleStart10000th,
1751 &askAngleEnd10000th);
1756 numArgs = sscanf(askOutputAngularRangeStr.c_str(),
"%s %s %d %X %X %X", dummy0, dummy1,
1758 &askAngleRes10000th,
1759 &askAngleStart10000th,
1760 &askAngleEnd10000th);
1764 double askTmpAngleRes = askAngleRes10000th / 10000.0;
1765 double askTmpAngleStart = askAngleStart10000th / 10000.0;
1766 double askTmpAngleEnd = askAngleEnd10000th / 10000.0;
1768 angleRes10000th = askAngleRes10000th;
1769 ROS_INFO(
"Angle resolution of scanner is %0.5lf [deg] (in 1/10000th deg: 0x%X)", askTmpAngleRes,
1770 askAngleRes10000th);
1773 double askAngleRes = askAngleRes10000th / 10000.0;
1774 double askAngleStart = askAngleStart10000th / 10000.0;
1775 double askAngleEnd = askAngleEnd10000th / 10000.0;
1777 askAngleStart -= 90;
1779 this->
config_.min_ang = askAngleStart / 180.0 * M_PI;
1780 this->
config_.max_ang = askAngleEnd / 180.0 * M_PI;
1786 ROS_INFO(
"MIN_ANG (after command verification): %8.3f [rad] %8.3f [deg]",
config_.min_ang,
1788 ROS_INFO(
"MAX_ANG (after command verification): %8.3f [rad] %8.3f [deg]",
config_.max_ang,
1807 for (
int i = 0; i < outputChannelFlag.size(); i++)
1818 ROS_INFO(
"LMS 5xx detected overwriting output channel flag ID");
1820 ROS_INFO(
"LMS 5xx detected overwriting resolution flag (only 8 bit supported)");
1826 ROS_INFO(
"MRS 1xxx detected overwriting resolution flag (only 8 bit supported)");
1838 char requestLMDscandatacfg[MAX_STR_LEN];
1842 sprintf(requestLMDscandatacfg, pcCmdMask,
outputChannelFlagId, rssiFlag ? 1 : 0, rssiResolutionIs16Bit ? 1 : 0);
1845 std::vector<unsigned char> reqBinary;
1856 std::vector<unsigned char> lmdScanDataCfgReply;
1862 char requestLMDscandatacfgRead[MAX_STR_LEN];
1868 std::vector<unsigned char> reqBinary;
1874 std::vector<unsigned char> lmdScanDataCfgReadReply;
1884 pn.
getParam(
"scan_freq", scan_freq);
1886 if (scan_freq!=0 || ang_res!=0)
1888 if(scan_freq!=0 && ang_res!=0)
1890 char requestLMDscancfg[MAX_STR_LEN];
1893 sprintf(requestLMDscancfg, pcCmdMask, (
long)(scan_freq*100+1e-9),(
long)(ang_res*10000+1e-9));
1896 std::vector<unsigned char> reqBinary;
1902 std::vector<unsigned char> lmdScanCfgReply;
1908 char requestLMDscancfgRead[MAX_STR_LEN];
1914 std::vector<unsigned char> reqBinary;
1920 std::vector<unsigned char> lmdScanDataCfgReadReply;
1927 ROS_ERROR(
"ang_res and scan_freq have to be set, only one param is set skiping scan_fre/ang_res config");
1933 char requestEchoSetting[MAX_STR_LEN];
1934 int filterEchoSetting = 0;
1935 pn.
getParam(
"filter_echos", filterEchoSetting);
1936 if (filterEchoSetting < 0)
1937 { filterEchoSetting = 0; }
1938 if (filterEchoSetting > 2)
1939 { filterEchoSetting = 2; }
1947 sprintf(requestEchoSetting, pcCmdMask, filterEchoSetting);
1948 std::vector<unsigned char> outputFilterEchoRangeReply;
1953 std::vector<unsigned char> reqBinary;
1974 std::vector<int> startProtocolSequence;
1975 bool deviceIsRadar =
false;
1979 bool transmitRawTargets =
true;
1980 bool transmitObjects =
true;
1981 int trackingMode = 0;
1982 std::string trackingModeDescription[] = {
"BASIC",
"VEHICLE"};
1984 int numTrackingModes =
sizeof(trackingModeDescription) /
sizeof(trackingModeDescription[0]);
1986 tmpParam.
getParam(
"transmit_raw_targets", transmitRawTargets);
1987 tmpParam.
getParam(
"transmit_objects", transmitObjects);
1988 tmpParam.
getParam(
"tracking_mode", trackingMode);
1991 if ((trackingMode < 0) || (trackingMode >= numTrackingModes))
1993 ROS_WARN(
"tracking mode id invalid. Switch to tracking mode 0");
1996 ROS_INFO(
"Raw target transmission is switched [%s]", transmitRawTargets ?
"ON" :
"OFF");
1997 ROS_INFO(
"Object transmission is switched [%s]", transmitObjects ?
"ON" :
"OFF");
1998 ROS_INFO(
"Tracking mode is set to id [%d] [%s]", trackingMode, trackingModeDescription[trackingMode].c_str());
2000 deviceIsRadar =
true;
2012 if (transmitRawTargets)
2021 if (transmitObjects)
2030 switch (trackingMode)
2039 ROS_DEBUG(
"Tracking mode switching sequence unknown\n");
2047 startProtocolSequence.push_back(
CMD_RUN);
2054 startProtocolSequence.push_back(
CMD_RUN);
2059 bool imu_enable =
false;
2060 tmp.
getParam(
"imu_enable", imu_enable);
2063 if(useBinaryCmdNow==
true)
2065 ROS_INFO(
"Enable IMU data transfer");
2070 ROS_FATAL(
"IMU USAGE NOT POSSIBLE IN ASCII COMMUNICATION MODE.\nTo use the IMU the communication with the scanner must be set to binary mode.\n This can be done by inserting the line:\n<param name=\"use_binary_protocol\" type=\"bool\" value=\"True\" />\n into the launchfile.\n See also https://github.com/SICKAG/sick_scan/blob/master/doc/IMU.md");
2078 std::vector<int>::iterator it;
2079 for (it = startProtocolSequence.begin(); it != startProtocolSequence.end(); it++)
2082 std::vector<unsigned char> tmpReply;
2086 std::vector<unsigned char> replyDummy;
2087 std::vector<unsigned char> reqBinary;
2088 std::vector<unsigned char> sopasVec;
2123 ROS_DEBUG(
"Starting radar data ....\n");
2134 bool waitForDeviceState =
true;
2137 waitForDeviceState =
false;
2141 waitForDeviceState =
false;
2144 if (waitForDeviceState)
2146 int maxWaitForDeviceStateReady = 45;
2147 bool scannerReady =
false;
2148 for (
int i = 0; i < maxWaitForDeviceStateReady; i++)
2150 double shortSleepTime = 1.0;
2152 std::vector<unsigned char> replyDummy;
2155 int deviceState = 0;
2157 std::vector<unsigned char> reqBinary;
2158 std::vector<unsigned char> sopasVec;
2176 long dummy0, dummy1;
2181 &dummy1, &deviceState);
2189 if (deviceState == 1)
2191 scannerReady =
true;
2192 ROS_INFO(
"Scanner ready for measurement after %d [sec]", i);
2196 ROS_INFO(
"Waiting for scanner ready state since %d secs", i);
2220 std::string reply_str;
2221 std::vector<unsigned char>::const_iterator it_start, it_end;
2225 it_start = reply.begin();
2226 it_end = reply.end();
2230 it_start = reply.begin() + 8;
2231 it_end = reply.end() - 1;
2233 bool inHexPrintMode =
false;
2234 for (std::vector<unsigned char>::const_iterator it = it_start; it != it_end; it++)
2238 if (*it >= 0x20 && (inHexPrintMode ==
false))
2240 reply_str.push_back(*it);
2246 char szTmp[255] = {0};
2247 unsigned char val = *it;
2248 inHexPrintMode =
true;
2249 sprintf(szTmp,
"\\x%02x", val);
2250 for (
int ii = 0; ii < strlen(szTmp); ii++)
2252 reply_str.push_back(szTmp[ii]);
2265 char szDumpFileName[255] = {0};
2266 char szDir[255] = {0};
2269 ROS_INFO(
"Attention: verboseLevel is set to 1. Datagrams are stored in the /tmp folder.");
2272 strcpy(szDir,
"C:\\temp\\");
2274 strcpy(szDir,
"/tmp/");
2276 sprintf(szDumpFileName,
"%ssick_datagram_%06d.bin", szDir, cnt);
2281 ftmp = fopen(szDumpFileName,
"wb");
2284 fwrite(buffer, bufLen, 1, ftmp);
2302 char device_string[7];
2303 int version_major = -1;
2304 int version_minor = -1;
2306 strcpy(device_string,
"???");
2308 if (sscanf(identStr.c_str(),
"sRA 0 6 %6s E V%d.%d", device_string,
2309 &version_major, &version_minor) == 3
2310 && strncmp(
"TiM3", device_string, 4) == 0
2311 && version_major >= 2 && version_minor >= 50)
2313 ROS_ERROR(
"This scanner model/firmware combination does not support ranging output!");
2314 ROS_ERROR(
"Supported scanners: TiM5xx: all firmware versions; TiM3xx: firmware versions < V2.50.");
2315 ROS_ERROR(
"This is a %s, firmware version %d.%d", device_string, version_major, version_minor);
2320 bool supported =
false;
2323 if (sscanf(identStr.c_str(),
"sRA 0 6 %6s E V%d.%d", device_string, &version_major, &version_minor) == 3)
2325 std::string devStr = device_string;
2328 if (devStr.compare(0, 4,
"TiM5") == 0)
2333 if (supported ==
true)
2335 ROS_INFO(
"Device %s V%d.%d found and supported by this driver.", identStr.c_str(), version_major,
2341 if ((identStr.find(
"MRS1xxx") !=
2343 || (identStr.find(
"LMS1xxx") != std::string::npos)
2346 ROS_INFO(
"Deviceinfo %s found and supported by this driver.", identStr.c_str());
2351 if (identStr.find(
"MRS6") !=
2354 ROS_INFO(
"Deviceinfo %s found and supported by this driver.", identStr.c_str());
2358 if (identStr.find(
"RMS3xx") !=
2361 ROS_INFO(
"Deviceinfo %s found and supported by this driver.", identStr.c_str());
2366 if (supported ==
false)
2368 ROS_WARN(
"Device %s V%d.%d found and maybe unsupported by this driver.", device_string, version_major,
2370 ROS_WARN(
"Full SOPAS answer: %s", identStr.c_str());
2385 unsigned char receiveBuffer[65536];
2386 int actual_length = 0;
2387 static unsigned int iteration_count = 0;
2401 int packetsInLoop = 0;
2403 const int maxNumAllowedPacketsToProcess = 25;
2405 int numPacketsProcessed = 0;
2407 static bool firstTimeCalled =
true;
2408 static bool dumpData =
false;
2409 static int verboseLevel = 0;
2410 static bool slamBundle =
false;
2411 float timeIncrement;
2412 static std::string echoForSlam =
"";
2413 if (firstTimeCalled ==
true)
2418 tmpParam.
getParam(
"slam_echo", echoForSlam);
2419 tmpParam.
getParam(
"slam_bundle", slamBundle);
2420 tmpParam.
getParam(
"verboseLevel", verboseLevel);
2421 firstTimeCalled =
false;
2426 int result =
get_datagram(recvTimeStamp, receiveBuffer, 65536, &actual_length, useBinaryProtocol, &packetsInLoop);
2427 numPacketsProcessed++;
2433 ROS_ERROR(
"Read Error when getting datagram: %i.", result);
2437 if (actual_length <= 0)
2443 if (iteration_count++ % (
config_.skip + 1) != 0)
2448 std_msgs::String datagram_msg;
2449 datagram_msg.data = std::string(reinterpret_cast<char *>(receiveBuffer));
2454 if (verboseLevel > 0)
2460 bool deviceIsRadar =
false;
2464 deviceIsRadar =
true;
2467 if (
true == deviceIsRadar)
2472 errorCode = radar.
parseDatagram(recvTimeStamp, (
unsigned char *) receiveBuffer, actual_length,
2478 if (scanImu.
isImuDatagram((
char *) receiveBuffer, actual_length))
2488 errorCode = scanImu.
parseDatagram(recvTimeStamp, (
unsigned char *) receiveBuffer, actual_length,
2499 sensor_msgs::LaserScan
msg;
2501 msg.header.stamp = recvTimeStamp;
2502 double elevationAngleInRad = 0.0;
2506 char *buffer_pos = (
char *) receiveBuffer;
2507 char *dstart, *dend;
2508 bool dumpDbg =
true;
2509 bool dataToProcess =
true;
2510 std::vector<float> vang_vec;
2512 while (dataToProcess)
2514 const int maxAllowedEchos = 5;
2516 int numValidEchos = 0;
2517 int aiValidEchoIdx[maxAllowedEchos] = {0};
2522 bool publishPointCloud =
true;
2524 if (useBinaryProtocol)
2527 std::vector<unsigned char> receiveBufferVec = std::vector<unsigned char>(receiveBuffer,
2528 receiveBuffer + actual_length);
2529 #ifdef DEBUG_DUMP_TO_CONSOLE_ENABLED 2530 if (actual_length > 1000)
2538 if (receiveBufferVec.size() > 8)
2542 memcpy(&idVal, receiveBuffer + 0, 4);
2543 memcpy(&lenVal, receiveBuffer + 4, 4);
2546 if (idVal == 0x02020202)
2551 char szFileName[255];
2554 sprintf(szFileName,
"c:\\temp\\dump%05d.bin", cnt);
2556 sprintf(szFileName,
"/tmp/dump%05d.txt", cnt);
2559 fout = fopen(szFileName,
"wb");
2560 fwrite(receiveBuffer, actual_length, 1, fout);
2566 if (lenVal < actual_length)
2568 short elevAngleX200 = 0;
2570 int scanFrequencyX100 = 0;
2571 double elevAngle = 0.00;
2572 double scanFrequency = 0.0;
2573 long measurementFrequencyDiv100 = 0;
2574 int numberOf16BitChannels = 0;
2575 int numberOf8BitChannels = 0;
2576 uint32_t SystemCountScan=0;
2577 uint32_t SystemCountTransmit=0;
2579 memcpy(&elevAngleX200, receiveBuffer + 50, 2);
2582 elevationAngleInRad = -elevAngleX200 / 200.0 *
deg2rad_const;
2584 msg.header.seq = elevAngleX200;
2586 memcpy(&SystemCountScan, receiveBuffer + 0x26, 4);
2587 swap_endian((
unsigned char *) &SystemCountScan, 4);
2589 memcpy(&SystemCountTransmit, receiveBuffer + 0x2A, 4);
2590 swap_endian((
unsigned char *) &SystemCountTransmit, 4);
2596 #ifdef DEBUG_DUMP_ENABLED 2597 double elevationAngleInDeg=elevationAngleInRad = -elevAngleX200 / 200.0;
2604 memcpy(&scanFrequencyX100, receiveBuffer + 52, 4);
2605 swap_endian((
unsigned char *) &scanFrequencyX100, 4);
2607 memcpy(&measurementFrequencyDiv100, receiveBuffer + 56, 4);
2608 swap_endian((
unsigned char *) &measurementFrequencyDiv100, 4);
2611 msg.scan_time = 1.0 / (scanFrequencyX100 / 100.0);
2614 if(measurementFrequencyDiv100>10000)
2616 measurementFrequencyDiv100/=100;
2618 msg.time_increment = 1.0 / (measurementFrequencyDiv100 * 100.0);
2619 timeIncrement=msg.time_increment;
2623 memcpy(&numberOf16BitChannels, receiveBuffer + 62, 2);
2624 swap_endian((
unsigned char *) &numberOf16BitChannels, 2);
2629 char szChannel[255] = {0};
2630 float scaleFactor = 1.0;
2631 float scaleFactorOffset = 0.0;
2632 int32_t startAngleDiv10000 = 1;
2633 int32_t sizeOfSingleAngularStepDiv10000 = 1;
2634 double startAngle = 0.0;
2635 double sizeOfSingleAngularStep = 0.0;
2636 short numberOfItems = 0;
2642 for (
int i = 0; i < numberOf16BitChannels; i++)
2644 int numberOfItems = 0x00;
2645 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
2648 parseOff += numberOfItems * 2;
2652 memcpy(&numberOf8BitChannels, receiveBuffer + parseOff, 2);
2653 swap_endian((
unsigned char *) &numberOf8BitChannels, 2);
2656 enum datagram_parse_task
2663 for (
int processLoop = 0; processLoop < 2; processLoop++)
2665 int totalChannelCnt = 0;
2670 datagram_parse_task task = process_idle;
2671 bool parsePacket =
true;
2673 bool processData =
false;
2675 if (processLoop == 0)
2682 if (processLoop == 1)
2685 numEchos = distChannelCnt;
2686 msg.ranges.resize(numberOfItems * numEchos);
2689 msg.intensities.resize(numberOfItems * rssiCnt);
2696 vang_vec.resize(numberOfItems * vangleCnt);
2702 echoMask = (1 << numEchos) - 1;
2711 szChannel[6] =
'\0';
2713 scaleFactorOffset = 0.0;
2714 startAngleDiv10000 = 1;
2715 sizeOfSingleAngularStepDiv10000 = 1;
2717 sizeOfSingleAngularStep = 0.0;
2721 #if 1 // prepared for multiecho parsing 2724 bool doVangVecProc =
false;
2726 task = process_idle;
2729 task = process_idle;
2730 doVangVecProc =
false;
2731 int processDataLenValuesInBytes = 2;
2733 if (totalChannelCnt == numberOf16BitChannels)
2738 if (totalChannelCnt >= numberOf16BitChannels)
2740 processDataLenValuesInBytes = 1;
2743 strcpy(szChannel,
"");
2745 if (totalChannelCnt < (numberOf16BitChannels + numberOf8BitChannels))
2747 szChannel[5] =
'\0';
2748 strncpy(szChannel, (
const char *) receiveBuffer + parseOff, 5);
2755 if (strstr(szChannel,
"DIST") == szChannel)
2757 task = process_dist;
2761 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
2765 if (strstr(szChannel,
"VANG") == szChannel)
2768 task = process_vang;
2771 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
2774 vang_vec.resize(numberOfItems);
2777 if (strstr(szChannel,
"RSSI") == szChannel)
2779 task = process_rssi;
2784 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
2791 scaleFactorOffset = 0.0;
2792 startAngleDiv10000 = 0;
2793 sizeOfSingleAngularStepDiv10000 = 0;
2796 memcpy(&scaleFactor, receiveBuffer + parseOff + 5, 4);
2797 memcpy(&scaleFactorOffset, receiveBuffer + parseOff + 9, 4);
2798 memcpy(&startAngleDiv10000, receiveBuffer + parseOff + 13, 4);
2799 memcpy(&sizeOfSingleAngularStepDiv10000, receiveBuffer + parseOff + 17, 2);
2800 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
2804 swap_endian((
unsigned char *) &scaleFactorOffset, 4);
2805 swap_endian((
unsigned char *) &startAngleDiv10000, 4);
2806 swap_endian((
unsigned char *) &sizeOfSingleAngularStepDiv10000, 2);
2811 unsigned short *
data = (
unsigned short *) (receiveBuffer + parseOff + 21);
2813 unsigned char *swapPtr = (
unsigned char *) data;
2816 i < numberOfItems * processDataLenValuesInBytes; i += processDataLenValuesInBytes)
2818 if (processDataLenValuesInBytes == 1)
2824 tmp = swapPtr[i + 1];
2825 swapPtr[i + 1] = swapPtr[i];
2836 startAngle = startAngleDiv10000 / 10000.00;
2837 sizeOfSingleAngularStep = sizeOfSingleAngularStepDiv10000 / 10000.0;
2838 sizeOfSingleAngularStep *= (M_PI / 180.0);
2840 msg.angle_min = startAngle / 180.0 * M_PI - M_PI / 2;
2841 msg.angle_increment = sizeOfSingleAngularStep;
2842 msg.angle_max = msg.angle_min + (numberOfItems - 1) * msg.angle_increment;
2844 float *rangePtr = NULL;
2846 if (numberOfItems > 0)
2848 rangePtr = &msg.ranges[0];
2850 float scaleFactor_001= 0.001F * scaleFactor;
2851 for (
int i = 0; i < numberOfItems; i++)
2853 idx = i + numberOfItems * (distChannelCnt - 1);
2854 rangePtr[idx] = (float) data[i] * scaleFactor_001 + scaleFactorOffset;
2855 #ifdef DEBUG_DUMP_ENABLED 2856 if (distChannelCnt == 1)
2858 if (i == floor(numberOfItems / 2))
2860 double curTimeStamp = SystemCountScan + i * msg.time_increment * 1E6;
2874 float *intensityPtr = NULL;
2876 if (numberOfItems > 0)
2878 intensityPtr = &msg.intensities[0];
2881 for (
int i = 0; i < numberOfItems; i++)
2883 idx = i + numberOfItems * (rssiCnt - 1);
2885 float rssiVal = 0.0;
2886 if (processDataLenValuesInBytes == 2)
2888 rssiVal = (float) data[i];
2892 unsigned char *data8Ptr = (
unsigned char *) data;
2893 rssiVal = (float) data8Ptr[i];
2895 intensityPtr[idx] = rssiVal * scaleFactor + scaleFactorOffset;
2901 float *vangPtr = NULL;
2902 if (numberOfItems > 0)
2904 vangPtr = &vang_vec[0];
2906 for (
int i = 0; i < numberOfItems; i++)
2908 vangPtr[i] = (float) data[i] * scaleFactor + scaleFactorOffset;
2913 parseOff += 21 + processDataLenValuesInBytes * numberOfItems;
2922 elevAngle = elevAngleX200 / 200.0;
2923 scanFrequency = scanFrequencyX100 / 100.0;
2935 dataToProcess =
false;
2939 dstart = strchr(buffer_pos, 0x02);
2942 dend = strchr(dstart + 1, 0x03);
2944 if ((dstart != NULL) && (dend != NULL))
2946 dataToProcess =
true;
2947 dlength = dend - dstart;
2953 dataToProcess =
false;
2961 char szFileName[255];
2964 sprintf(szFileName,
"c:\\temp\\dump%05d.txt", cnt);
2966 sprintf(szFileName,
"/tmp/dump%05d.txt", cnt);
2969 fout = fopen(szFileName,
"wb");
2970 fwrite(dstart, dlength, 1, fout);
2983 publishPointCloud =
true;
2986 for (
int i = 0; i < maxAllowedEchos; i++)
2988 aiValidEchoIdx[i] = 0;
2997 bool elevationPreCalculated =
false;
2998 double elevationAngleDegree = 0.0;
3001 std::vector<float> rangeTmp = msg.ranges;
3002 std::vector<float> intensityTmp = msg.intensities;
3004 int intensityTmpNum = intensityTmp.size();
3005 float *intensityTmpPtr = NULL;
3006 if (intensityTmpNum > 0)
3008 intensityTmpPtr = &intensityTmp[0];
3016 bool useGivenElevationAngle =
false;
3017 switch (numOfLayers)
3025 if (msg.header.seq == 250) layer = -1;
3026 else if (msg.header.seq == 0) layer = 0;
3027 else if (msg.header.seq == -250) layer = 1;
3028 else if (msg.header.seq == -500) layer = 2;
3030 elevationAngleDegree = elevationAngleDegree / 180.0 * M_PI;
3035 layer = (msg.header.seq - (-2638)) / 125;
3036 layer = (23 - layer) - 1;
3039 elevationAngleDegree = elevationAngleDegree / 180.0 * M_PI;
3042 elevationPreCalculated =
true;
3043 if (vang_vec.size() > 0)
3045 useGivenElevationAngle =
true;
3066 int startOffset = 0;
3068 int echoPartNum = msg.ranges.size() / numEchos;
3069 for (
int i = 0; i < numEchos; i++)
3072 bool sendMsg =
false;
3075 aiValidEchoIdx[numValidEchos] = i;
3079 startOffset = i * echoPartNum;
3080 endOffset = (i + 1) * echoPartNum;
3083 msg.intensities.clear();
3084 msg.ranges = std::vector<float>(
3085 rangeTmp.begin() + startOffset,
3086 rangeTmp.begin() + endOffset);
3088 if (endOffset <= intensityTmp.size() && (intensityTmp.size() > 0))
3090 msg.intensities = std::vector<float>(
3091 intensityTmp.begin() + startOffset,
3092 intensityTmp.begin() + endOffset);
3096 msg.intensities.resize(echoPartNum);
3100 char szTmp[255] = {0};
3103 const char *cpFrameId =
config_.frame_id.c_str();
3105 sprintf(szTmp,
"%s_%+04d_DIST%d", cpFrameId, msg.header.seq, i + 1);
3106 #else // experimental 3107 char szSignName[10] = {0};
3108 if ((
int) msg.header.seq < 0)
3110 strcpy(szSignName,
"NEG");
3114 strcpy(szSignName,
"POS");
3118 sprintf(szTmp,
"%s_%s_%03d_DIST%d", cpFrameId, szSignName, abs((
int) msg.header.seq), i + 1);
3123 strcpy(szTmp,
config_.frame_id.c_str());
3126 msg.header.frame_id = std::string(szTmp);
3128 if (echoForSlam.length() > 0)
3136 msg.header.frame_id = echoForSlam;
3137 strcpy(szTmp, echoForSlam.c_str());
3138 if (elevationAngleInRad != 0.0)
3140 float cosVal = cos(elevationAngleInRad);
3141 int rangeNum = msg.ranges.size();
3142 for (
int j = 0; j < rangeNum; j++)
3144 msg.ranges[j] *= cosVal;
3150 if (echoForSlam.compare(szTmp) == 0)
3162 if (numOfLayers > 4)
3167 outputChannelFlagId)
3173 printf(
"MSG received...");
3180 if (publishPointCloud ==
true)
3185 const int numChannels = 4;
3187 int numTmpLayer = numOfLayers;
3190 cloud_.header.stamp = recvTimeStamp;
3193 cloud_.height = numTmpLayer * numValidEchos;
3194 cloud_.width = msg.ranges.size();
3195 cloud_.is_bigendian =
false;
3197 cloud_.point_step = numChannels *
sizeof(float);
3199 cloud_.fields.resize(numChannels);
3200 for (
int i = 0; i < numChannels; i++)
3202 std::string channelId[] = {
"x",
"y",
"z",
"intensity"};
3203 cloud_.fields[i].name = channelId[i];
3204 cloud_.fields[i].offset = i *
sizeof(float);
3205 cloud_.fields[i].count = 1;
3206 cloud_.fields[i].datatype = sensor_msgs::PointField::FLOAT32;
3211 unsigned char *cloudDataPtr = &(
cloud_.data[0]);
3216 std::vector<float> cosAlphaTable;
3217 std::vector<float> sinAlphaTable;
3218 int rangeNum = rangeTmp.size() / numValidEchos;
3219 cosAlphaTable.resize(rangeNum);
3220 sinAlphaTable.resize(rangeNum);
3222 for (
size_t iEcho = 0; iEcho < numValidEchos; iEcho++)
3228 float *cosAlphaTablePtr = &cosAlphaTable[0];
3229 float *sinAlphaTablePtr = &sinAlphaTable[0];
3231 float *vangPtr = &vang_vec[0];
3232 float *rangeTmpPtr = &rangeTmp[0];
3233 for (
size_t i = 0; i < rangeNum; i++)
3235 enum enum_index_descr
3243 long adroff = i * (numChannels * (int)
sizeof(
float));
3245 adroff += (layer - baseLayer) *
cloud_.row_step;
3247 adroff += iEcho *
cloud_.row_step * numTmpLayer;
3249 unsigned char *ptr = cloudDataPtr + adroff;
3250 float *fptr = (
float *)(cloudDataPtr + adroff);
3252 geometry_msgs::Point32 point;
3253 float range_meter = rangeTmpPtr[iEcho * rangeNum + i];
3257 if (useGivenElevationAngle)
3263 if (elevationPreCalculated)
3265 alpha = elevationAngleInRad;
3269 alpha = layer * elevationAngleDegree;
3275 cosAlphaTablePtr[i] = cos(alpha);
3276 sinAlphaTablePtr[i] = sin(alpha);
3283 float rangeCos=range_meter * cosAlphaTablePtr[i];
3284 fptr[idx_x] = rangeCos * cos(phi);
3285 fptr[idx_y] = rangeCos * sin(phi);
3286 fptr[idx_z] = range_meter * sinAlphaTablePtr[i];
3288 fptr[idx_intensity] = 0.0;
3291 int intensityIndex = aiValidEchoIdx[iEcho] * rangeNum + i;
3293 if (intensityIndex < intensityTmpNum)
3295 fptr[idx_intensity] = intensityTmpPtr[intensityIndex];
3298 angle += msg.angle_increment;
3302 int layerOff = (layer - baseLayer);
3306 bool shallIFire =
false;
3307 if ((msg.header.seq == 0) || (msg.header.seq == 237))
3313 static int layerCnt = 0;
3314 static int layerSeq[4];
3316 if (
config_.cloud_output_mode>0)
3319 layerSeq[layerCnt % 4] = layer;
3334 if (
config_.cloud_output_mode==0)
3340 else if(
config_.cloud_output_mode==2)
3352 int numTotalShots = 360;
3353 int numPartialShots = 40;
3355 for (
int i = 0; i < numTotalShots; i += numPartialShots)
3357 sensor_msgs::PointCloud2 partialCloud;
3361 partialTimeStamp +=
ros::Duration((i + 0.5 * (numPartialShots - 1)) * timeIncrement);
3362 partialTimeStamp +=
ros::Duration((3 * numTotalShots) * timeIncrement);
3363 partialCloud.header.stamp = partialTimeStamp;
3364 partialCloud.width = numPartialShots * 3;
3366 int diffTo1100 =
cloud_.width - 3 * (numTotalShots + i);
3367 if (diffTo1100 > numPartialShots)
3369 diffTo1100 = numPartialShots;
3375 partialCloud.width += diffTo1100;
3377 partialCloud.height = 1;
3380 partialCloud.is_bigendian =
false;
3381 partialCloud.is_dense =
true;
3382 partialCloud.point_step = numChannels *
sizeof(float);
3383 partialCloud.row_step = partialCloud.point_step * partialCloud.width;
3384 partialCloud.fields.resize(numChannels);
3385 for (
int ii = 0; ii < numChannels; ii++)
3387 std::string channelId[] = {
"x",
"y",
"z",
"intensity"};
3388 partialCloud.fields[ii].name = channelId[ii];
3389 partialCloud.fields[ii].offset = ii *
sizeof(float);
3390 partialCloud.fields[ii].count = 1;
3391 partialCloud.fields[ii].datatype = sensor_msgs::PointField::FLOAT32;
3394 partialCloud.data.resize(partialCloud.row_step);
3397 for (
int j = 0; j < 4; j++)
3399 int layerIdx = (j + (layerCnt)) % 4;
3400 int rowIdx = 1 + layerSeq[layerIdx % 4];
3401 int colIdx = j * numTotalShots + i;
3402 int maxAvail =
cloud_.width - colIdx;
3408 if (maxAvail > numPartialShots)
3410 maxAvail = numPartialShots;
3416 memcpy(&(partialCloud.data[partOff]),
3418 cloud_.point_step * maxAvail);
3422 partOff += maxAvail * partialCloud.point_step;
3424 assert(partialCloud.data.size()==partialCloud.width*partialCloud.point_step);
3429 memcpy(&(partialCloud.data[0]), &(
cloud_.data[0]) + i *
cloud_.point_step,
cloud_.point_step * numPartialShots);
3437 printf(
"PUBLISH:\n");
3443 buffer_pos = dend + 1;
3449 }
while ( (packetsInLoop > 0) && (numPacketsProcessed < maxNumAllowedPacketsToProcess) );
3459 if (conf.min_ang > conf.max_ang)
3461 ROS_WARN(
"Maximum angle must be greater than minimum angle. Adjusting >min_ang<.");
3462 conf.min_ang = conf.max_ang;
3485 requestBinary->clear();
3486 if (requestAscii == NULL)
3490 int cmdLen = strlen(requestAscii);
3495 if (requestAscii[0] != 0x02)
3499 if (requestAscii[cmdLen - 1] != 0x03)
3504 for (
int i = 0; i < 4; i++)
3506 requestBinary->push_back(0x02);
3509 for (
int i = 0; i < 4; i++)
3511 requestBinary->push_back(0x00);
3514 unsigned long msgLen = cmdLen - 2;
3518 std::string keyWord0 =
"sMN SetAccessMode";
3519 std::string keyWord1 =
"sWN FREchoFilter";
3520 std::string keyWord2 =
"sEN LMDscandata";
3521 std::string keyWord3 =
"sWN LMDscandatacfg";
3522 std::string keyWord4 =
"sWN SetActiveApplications";
3523 std::string keyWord5 =
"sEN IMUData";
3524 std::string keyWord6 =
"sWN EIIpAddr";
3525 std::string keyWord7 =
"sMN mLMPsetscancfg";
3526 std::string keyWord8 =
"sWN TSCTCupdatetime";
3527 std::string keyWord9 =
"sWN TSCTCSrvAddr";
3530 std::string cmdAscii = requestAscii;
3533 int copyUntilSpaceCnt = 2;
3535 char hexStr[255] = {0};
3537 unsigned char buffer[255];
3539 if (cmdAscii.find(keyWord0) != std::string::npos)
3541 copyUntilSpaceCnt = 2;
3542 int keyWord0Len = keyWord0.length();
3543 sscanf(requestAscii + keyWord0Len + 1,
" %d %s", &level, hexStr);
3544 buffer[0] = (
unsigned char) (0xFF & level);
3546 char hexTmp[3] = {0};
3547 for (
int i = 0; i < 4; i++)
3550 hexTmp[0] = hexStr[i * 2];
3551 hexTmp[1] = hexStr[i * 2 + 1];
3553 sscanf(hexTmp,
"%x", &val);
3554 buffer[i + 1] = (
unsigned char) (0xFF & val);
3558 if (cmdAscii.find(keyWord1) != std::string::npos)
3560 int echoCodeNumber = 0;
3561 int keyWord1Len = keyWord1.length();
3562 sscanf(requestAscii + keyWord1Len + 1,
" %d", &echoCodeNumber);
3563 buffer[0] = (
unsigned char) (0xFF & echoCodeNumber);
3566 if (cmdAscii.find(keyWord2) != std::string::npos)
3568 int scanDataStatus = 0;
3569 int keyWord2Len = keyWord2.length();
3570 sscanf(requestAscii + keyWord2Len + 1,
" %d", &scanDataStatus);
3571 buffer[0] = (
unsigned char) (0xFF & scanDataStatus);
3575 if (cmdAscii.find(keyWord3) != std::string::npos)
3577 int scanDataStatus = 0;
3578 int keyWord3Len = keyWord3.length();
3579 int dummyArr[12] = {0};
3580 if (12 == sscanf(requestAscii + keyWord3Len + 1,
" %d %d %d %d %d %d %d %d %d %d %d %d",
3581 &dummyArr[0], &dummyArr[1], &dummyArr[2],
3582 &dummyArr[3], &dummyArr[4], &dummyArr[5],
3583 &dummyArr[6], &dummyArr[7], &dummyArr[8],
3584 &dummyArr[9], &dummyArr[10], &dummyArr[11]))
3586 for (
int i = 0; i < 13; i++)
3590 buffer[0] = (
unsigned char) (0xFF & (dummyArr[0]));
3592 buffer[2] = (
unsigned char) (0xFF & dummyArr[2]);
3593 buffer[3] = (
unsigned char) (0xFF & dummyArr[3]);
3594 buffer[10]= (
unsigned char) (0xFF & dummyArr[10]);
3595 buffer[12] = (
unsigned char) (0xFF & (dummyArr[11]));
3602 if (cmdAscii.find(keyWord4) != std::string::npos)
3604 char tmpStr[1024] = {0};
3605 char szApplStr[255] = {0};
3606 int keyWord4Len = keyWord4.length();
3607 int scanDataStatus = 0;
3609 strcpy(tmpStr, requestAscii + keyWord4Len + 2);
3610 sscanf(tmpStr,
"%d %s %d", &dummy0, szApplStr, &dummy1);
3613 buffer[1] = dummy0 ? 0x01 : 0x00;
3614 for (
int ii = 0; ii < 4; ii++)
3616 buffer[2 + ii] = szApplStr[ii];
3618 buffer[6] = dummy1 ? 0x01 : 0x00;
3622 if (cmdAscii.find(keyWord5) != std::string::npos)
3624 int imuSetStatus = 0;
3625 int keyWord5Len = keyWord5.length();
3626 sscanf(requestAscii + keyWord5Len + 1,
" %d", &imuSetStatus);
3627 buffer[0] = (
unsigned char) (0xFF & imuSetStatus);
3631 if (cmdAscii.find(keyWord6) != std::string::npos)
3634 int imuSetStatus = 0;
3635 int keyWord6Len = keyWord6.length();
3636 sscanf(requestAscii + keyWord6Len + 1,
" %x %x %x %x", &(adrPartArr[0]), &(adrPartArr[1]), &(adrPartArr[2]),
3638 buffer[0] = (
unsigned char) (0xFF & adrPartArr[0]);
3639 buffer[1] = (
unsigned char) (0xFF & adrPartArr[1]);
3640 buffer[2] = (
unsigned char) (0xFF & adrPartArr[2]);
3641 buffer[3] = (
unsigned char) (0xFF & adrPartArr[3]);
3652 if (cmdAscii.find(keyWord7) != std::string::npos)
3655 for(
int i=0;i<bufferLen;i++)
3657 unsigned char uch=0x00;
3665 char tmpStr[1024] = {0};
3666 char szApplStr[255] = {0};
3667 int keyWord7Len = keyWord7.length();
3668 int scanDataStatus = 0;
3670 strcpy(tmpStr, requestAscii + keyWord7Len + 2);
3671 sscanf(tmpStr,
"%d 1 %d", &dummy0, &dummy1);
3673 buffer[0] = (
unsigned char)(0xFF & (dummy0 >> 24));
3674 buffer[1] = (
unsigned char)(0xFF & (dummy0 >> 16));
3675 buffer[2] = (
unsigned char)(0xFF & (dummy0 >> 8));
3676 buffer[3] = (
unsigned char)(0xFF & (dummy0 >> 0));
3679 buffer[6] = (
unsigned char)(0xFF & (dummy1 >> 24));
3680 buffer[7] = (
unsigned char)(0xFF & (dummy1 >> 16));
3681 buffer[8] = (
unsigned char)(0xFF & (dummy1 >> 8));
3682 buffer[9] = (
unsigned char)(0xFF & (dummy1 >> 0));
3686 if (cmdAscii.find(keyWord8) != std::string::npos)
3688 uint32_t updatetime = 0;
3689 int keyWord8Len = keyWord8.length();
3690 sscanf(requestAscii + keyWord8Len + 1,
" %d", &updatetime);
3691 buffer[0] = (
unsigned char)(0xFF & (updatetime >> 24));
3692 buffer[1] = (
unsigned char)(0xFF & (updatetime >> 16));
3693 buffer[2] = (
unsigned char)(0xFF & (updatetime >> 8));
3694 buffer[3] = (
unsigned char)(0xFF & (updatetime >> 0));
3697 if (cmdAscii.find(keyWord9) != std::string::npos)
3700 int imuSetStatus = 0;
3701 int keyWord9Len = keyWord9.length();
3702 sscanf(requestAscii + keyWord9Len + 1,
" %x %x %x %x", &(adrPartArr[0]), &(adrPartArr[1]), &(adrPartArr[2]),
3704 buffer[0] = (
unsigned char) (0xFF & adrPartArr[0]);
3705 buffer[1] = (
unsigned char) (0xFF & adrPartArr[1]);
3706 buffer[2] = (
unsigned char) (0xFF & adrPartArr[2]);
3707 buffer[3] = (
unsigned char) (0xFF & adrPartArr[3]);
3711 bool switchDoBinaryData =
false;
3712 for (
int i = 1; i <= (int) (msgLen); i++)
3714 char c = requestAscii[i];
3715 if (switchDoBinaryData ==
true)
3719 if (c >=
'0' && c <=
'9')
3729 requestBinary->push_back(c);
3730 if (requestAscii[i] == 0x20)
3733 if (spaceCnt >= copyUntilSpaceCnt)
3735 switchDoBinaryData =
true;
3742 for (
int i = 0; i < bufferLen; i++)
3744 requestBinary->push_back(buffer[i]);
3747 msgLen = requestBinary->size();
3749 for (
int i = 0; i < 4; i++)
3751 unsigned char bigEndianLen = msgLen & (0xFF << (3 - i) * 8);
3752 (*requestBinary)[i + 4] = ((
unsigned char) (bigEndianLen));
3754 unsigned char xorVal = 0x00;
3755 xorVal =
sick_crc8((
unsigned char *) (&((*requestBinary)[8])), requestBinary->size() - 8);
3756 requestBinary->push_back(xorVal);
3758 for (
int i = 0; i < requestBinary->size(); i++)
3760 unsigned char c = (*requestBinary)[i];
3761 printf(
"[%c]%02x ", (c <
' ') ?
'.' : c, c) ;
3778 bool retValue =
true;
3780 if (shouldUseBinary == useBinaryCmdNow)
3796 if (shouldUseBinary ==
true)
3805 useBinaryCmdNow = shouldUseBinary;
3814 int eepwritetTimeOut =1;
3816 bool result =
false;
3819 unsigned long adrBytesLong[4];
3820 std::string
s = ipNewIPAddr.to_string();
3821 const char *ptr = s.c_str();
3823 sscanf(ptr,
"%lu.%lu.%lu.%lu", &(adrBytesLong[0]), &(adrBytesLong[1]), &(adrBytesLong[2]), &(adrBytesLong[3]));
3826 unsigned char ipbytearray[4];
3827 for (
int i = 0; i < 4; i++)
3829 ipbytearray[i] = adrBytesLong[i] & 0xFF;
3833 char ipcommand[255];
3835 sprintf(ipcommand, pcCmdMask, ipbytearray[0], ipbytearray[1], ipbytearray[2], ipbytearray[3]);
3838 std::vector<unsigned char> reqBinary;
3856 std::vector<unsigned char> ipcomandReply;
3857 std::vector<unsigned char> resetReply;
3874 bool result =
false;
3877 unsigned long adrBytesLong[4];
3878 std::string
s = ipNewIPAddr.to_string();
3879 const char *ptr = s.c_str();
3881 sscanf(ptr,
"%lu.%lu.%lu.%lu", &(adrBytesLong[0]), &(adrBytesLong[1]), &(adrBytesLong[2]), &(adrBytesLong[3]));
3884 unsigned char ipbytearray[4];
3885 for (
int i = 0; i < 4; i++)
3887 ipbytearray[i] = adrBytesLong[i] & 0xFF;
3891 char ntpipcommand[255];
3892 char ntpupdatetimecommand[255];
3894 sprintf(ntpipcommand, pcCmdMask, ipbytearray[0], ipbytearray[1], ipbytearray[2], ipbytearray[3]);
3897 sprintf(ntpupdatetimecommand, pcCmdMaskUpdatetime, 5);
3898 std::vector<unsigned char> outputFilterntpupdatetimecommand;
3902 std::vector<unsigned char> reqBinary;
3919 std::vector<unsigned char> ipcomandReply;
3920 std::vector<unsigned char> resetReply;
void setReadTimeOutInMs(int timeOutInMs)
set timeout in milliseconds
std::vector< std::string > sopasCmdErrMsg
void check_angle_range(SickScanConfig &conf)
check angle setting in the config and adjust the min_ang to the max_ang if min_ang greater than max_a...
int loopOnce()
parsing datagram and publishing ros messages
bool isImuDatagram(char *datagram, size_t datagram_length)
virtual int init_scanner()
initialize scanner
std::vector< std::string > sopasCmdMaskVec
int binScanfGuessDataLenFromMask(const char *scanfMask)
std::vector< std::string > sopasReplyStrVec
void publish(const boost::shared_ptr< M > &message) const
std::vector< std::string > sopasCmdVec
double getElevationDegreeResolution(void)
get angular resolution in VERTICAL direction for multilayer scanner
int getReadTimeOutInMs()
get timeout in milliseconds
double expectedFrequency_
void update_config(sick_scan::SickScanConfig &new_config, uint32_t level=0)
updating configuration
std::vector< unsigned char > stringToVector(std::string s)
Universal swapping function.
const std::string binScanfGetStringFromVec(std::vector< unsigned char > *replyDummy, int off, long len)
Convert part of unsigned char vector into a std::string.
void setHardwareID(const std::string &hwid)
std::string stripControl(std::vector< unsigned char > s)
Converts a SOPAS command to a human readable string.
static SoftwarePLL & instance()
bool isImuAckDatagram(char *datagram, size_t datagram_length)
double getExpectedFrequency(void)
get expected scan frequency
bool dumpDatagramForDebugging(unsigned char *buffer, int bufLen)
ros::Publisher cloud_radar_track_pub_
SickScanCommon(SickGenericParser *parser)
Construction of SickScanCommon.
float get_range_min(void)
Getting minimum range.
int convertAscii2BinaryCmd(const char *requestAscii, std::vector< unsigned char > *requestBinary)
Convert ASCII-message to Binary-message.
virtual int init_device()=0
void swap_endian(unsigned char *ptr, int numBytes)
Universal swapping function.
int parseDatagram(ros::Time timeStamp, unsigned char *receiveBuffer, int actual_length, bool useBinaryProtocol)
int binScanfVec(const std::vector< unsigned char > *vec, const char *fmt,...)
bool setNewIpAddress(boost::asio::ip::address_v4 ipNewIPAddr, bool useBinaryCmd)
bool getIntensityResolutionIs16Bit(void)
Get the RSSI Value length.
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
dynamic_reconfigure::Server< sick_scan::SickScanConfig > dynamic_reconfigure_server_
ros::Publisher cloud_radar_rawtarget_pub_
bool getCorrectedTimeStamp(uint32_t &sec, uint32_t &nanoSec, uint32_t tick)
diagnostic_updater::Updater diagnostics_
std::vector< std::string > sopasReplyVec
bool checkForProtocolChangeAndMaybeReconnect(bool &useBinaryCmdNow)
checks the current protocol type and gives information about necessary change
virtual bool rebootScanner()
Send a SOPAS command to the scanner that should cause a soft reset.
int getNumberOfLayers(void)
Getting number of scanner layers.
int getProtocolType(void)
get protocol type as enum
SopasProtocol m_protocolId
int getNumberOfMaximumEchos(void)
Get number of maximum echoes for this laser scanner type.
void setProtocolType(SopasProtocol cola_dialect_id)
set protocol type as enum
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
std::vector< int > sopasCmdChain
ros::Publisher imuScan_pub_
void addFrameToBuffer(UINT8 *sendBuffer, UINT8 *cmdBuffer, UINT16 *len)
std::string replyToString(const std::vector< unsigned char > &reply)
Converts reply from sendSOPASCommand to string.
virtual int parse_datagram(char *datagram, size_t datagram_length, SickScanConfig &config, sensor_msgs::LaserScan &msg, int &numEchos, int &echoMask)
Parsing Ascii datagram.
static int getDiagnosticErrorCode()
return diagnostic error code (small helper function) This small helper function was introduced to all...
void checkScanTiming(float time_increment, float scan_time, float angle_increment, float tol)
bool setNTPServerAndStart(boost::asio::ip::address_v4 ipNewIPAddr, bool useBinaryCmd)
float get_range_max(void)
Getting maximum range.
bool getUseBinaryProtocol(void)
flag to decide between usage of ASCII-sopas or BINARY-sopas
std::string generateExpectedAnswerString(const std::vector< unsigned char > requestStr)
Generate expected answer string from the command string.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define ROS_WARN_STREAM(args)
ScannerBasicParam * getCurrentParamPtr()
Gets Pointer to parameter object.
static DataDumper & instance()
SickGenericParser * parser_
double getAngularDegreeResolution(void)
Get angular resolution in degress.
std::string getScannerName(void)
Getting name (type) of scanner.
ros::Publisher datagram_pub_
int checkForBinaryAnswer(const std::vector< unsigned char > *reply)
Check block for correct framing and starting sequence of a binary message.
void setSensorIsRadar(bool _isRadar)
virtual ~SickScanCommon()
Destructor of SickScanCommon.
ros::Publisher radarScan_pub_
#define SICK_SCANNER_MRS_1XXX_NAME
int sendSopasAndCheckAnswer(std::string request, std::vector< unsigned char > *reply, int cmdId)
send command and check answer
unsigned long convertBigEndianCharArrayToUnsignedLong(const unsigned char *vecArr)
Convert little endian to big endian (should be replaced by swap-routine)
virtual int init()
init routine of scanner
void setIntensityResolutionIs16Bit(bool _IntensityResolutionIs16Bit)
Set the RSSI Value length.
bool getParam(const std::string &key, std::string &s) const
unsigned char sick_crc8(unsigned char *msgBlock, int len)
calculate crc-code for last byte of binary message XOR-calucation is done ONLY over message content (...
virtual int stop_scanner()
Stops sending scan data.
int parseDatagram(ros::Time timeStamp, unsigned char *receiveBuffer, int actual_length, bool useBinaryProtocol)
virtual int get_datagram(ros::Time &recvTimeStamp, unsigned char *receiveBuffer, int bufferSize, int *actual_length, bool isBinaryProtocol, int *numberOfRemainingFifoEntries)=0
Read a datagram from the device.
#define SICK_SCANNER_LMS_5XX_NAME
bool getSensorIsRadar(void)
void broadcast(int lvl, const std::string msg)
bool isCompatibleDevice(const std::string identStr) const
check the identification string
#define ROS_ERROR_STREAM(args)
diagnostic_updater::DiagnosedPublisher< sensor_msgs::LaserScan > * diagnosticPub_
sensor_msgs::PointCloud2 cloud_
int dumpUcharBufferToConsole(unsigned char *buffer, int bufLen)
ros::Publisher cloud_pub_
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
static sick_scan::SickScanCommonTcp * s
std::vector< std::vector< unsigned char > > sopasReplyBinVec
bool updatePLL(uint32_t sec, uint32_t nanoSec, uint32_t curtick)
Updates PLL internale State should be called only with network send timestamps.
int init_cmdTables()
init command tables and define startup sequence
bool getDeviceIsRadar(void)
flag to mark the device as radar (instead of laser scanner)
virtual int sendSOPASCommand(const char *request, std::vector< unsigned char > *reply, int cmdLen=-1)=0
Send a SOPAS command to the device and print out the response to the console.