00001
00052 #ifdef _MSC_VER // compiling simulation for MS-Visual C++ - not defined for linux system
00053 #pragma warning(disable: 4996)
00054 #pragma warning(disable: 4267) // due to conversion warning size_t in the ros header file
00055 #define _WIN32_WINNT 0x0501
00056
00057 #endif
00058
00059 #include <sick_scan/sick_scan_common_nw.h>
00060 #include <sick_scan/sick_scan_common.h>
00061 #include <sick_scan/sick_generic_radar.h>
00062
00063 #include <sick_scan/sick_scan_config_internal.h>
00064
00065 #ifdef _MSC_VER
00066 #include "sick_scan/rosconsole_simu.hpp"
00067 #endif
00068
00069 #include "sick_scan/binScanf.hpp"
00070
00071 #include <sick_scan/RadarScan.h>
00072
00073
00074 #include <cstdio>
00075 #include <cstring>
00076
00077 #define _USE_MATH_DEFINES
00078
00079 #include <math.h>
00080
00081 #ifndef rad2deg
00082 #define rad2deg(x) ((x) / M_PI * 180.0)
00083 #endif
00084
00085 #define deg2rad_const (0.017453292519943295769236907684886f)
00086
00087 #include "sick_scan/tcp/colaa.hpp"
00088 #include "sick_scan/tcp/colab.hpp"
00089
00090 #include <map>
00091 #include <climits>
00092 #include <sick_scan/sick_generic_imu.h>
00093
00099 void swap_endian(unsigned char *ptr, int numBytes)
00100 {
00101 unsigned char *buf = (ptr);
00102 unsigned char tmpChar;
00103 for (int i = 0; i < numBytes / 2; i++)
00104 {
00105 tmpChar = buf[numBytes - 1 - i];
00106 buf[numBytes - 1 - i] = buf[i];
00107 buf[i] = tmpChar;
00108 }
00109 }
00110
00111
00119 std::vector<unsigned char> stringToVector(std::string s)
00120 {
00121 std::vector<unsigned char> result;
00122 for (int j = 0; j < s.length(); j++)
00123 {
00124 result.push_back(s[j]);
00125 }
00126 return result;
00127
00128 }
00129
00130
00136 static int getDiagnosticErrorCode()
00137 {
00138 #ifdef _MSC_VER
00139 #undef ERROR
00140 return(2);
00141 #else
00142 return (diagnostic_msgs::DiagnosticStatus::ERROR);
00143 #endif
00144 }
00145
00153 const std::string binScanfGetStringFromVec(std::vector<unsigned char> *replyDummy, int off, long len)
00154 {
00155 std::string s;
00156 s = "";
00157 for (int i = 0; i < len; i++)
00158 {
00159 char ch = (char) ((*replyDummy)[i + off]);
00160 s += ch;
00161 }
00162 return (s);
00163 }
00164
00165 namespace sick_scan
00166 {
00174 unsigned char sick_crc8(unsigned char *msgBlock, int len)
00175 {
00176 unsigned char xorVal = 0x00;
00177 int off = 0;
00178 for (int i = off; i < len; i++)
00179 {
00180
00181 unsigned char val = msgBlock[i];
00182 xorVal ^= val;
00183 }
00184 return (xorVal);
00185 }
00186
00192 std::string stripControl(std::vector<unsigned char> s)
00193 {
00194 bool isParamBinary = false;
00195 int spaceCnt = 0x00;
00196 int cnt0x02 = 0;
00197
00198 for (int i = 0; i < s.size(); i++)
00199 {
00200 if (s[i] != 0x02)
00201 {
00202 isParamBinary = false;
00203
00204 }
00205 else
00206 {
00207 cnt0x02++;
00208 }
00209 if (i > 4)
00210 {
00211 break;
00212 }
00213 }
00214 if (4 == cnt0x02)
00215 {
00216 isParamBinary = true;
00217 }
00218 std::string dest;
00219 if (isParamBinary == true)
00220 {
00221 int parseState = 0;
00222
00223 unsigned long lenId = 0x00;
00224 char szDummy[255] = {0};
00225 for (int i = 0; i < s.size(); i++)
00226 {
00227 switch(parseState)
00228 {
00229 case 0:
00230 if (s[i] == 0x02)
00231 {
00232 dest += "<STX>";
00233 }
00234 else
00235 {
00236 dest += "?????";
00237 }
00238 if (i == 3)
00239 {
00240 parseState = 1;
00241 }
00242 break;
00243 case 1:
00244 lenId |= s[i] << (8 * (7 - i));
00245 if (i == 7)
00246 {
00247 sprintf(szDummy, "<Len=%04lu>", lenId);
00248 dest += szDummy;
00249 parseState = 2;
00250 }
00251 break;
00252 case 2:
00253 {
00254 unsigned long dataProcessed = i - 8;
00255 if (s[i] == ' ')
00256 {
00257 spaceCnt++;
00258 }
00259 if (spaceCnt == 2)
00260 {
00261 parseState = 3;
00262 }
00263 dest += s[i];
00264 if (dataProcessed >= (lenId - 1))
00265 {
00266 parseState = 4;
00267 }
00268
00269 break;
00270 }
00271
00272 case 3:
00273 {
00274 char ch = dest[dest.length()-1];
00275 if (ch != ' ')
00276 {
00277 dest += ' ';
00278 }
00279 sprintf(szDummy, "0x%02x", s[i]);
00280 dest += szDummy;
00281
00282 unsigned long dataProcessed = i - 8;
00283 if (dataProcessed >= (lenId -1))
00284 {
00285 parseState = 4;
00286 }
00287 break;
00288 }
00289 case 4:
00290 {
00291 sprintf(szDummy, " CRC:<0x%02x>", s[i]);
00292 dest += szDummy;
00293 break;
00294 }
00295 default:
00296 break;
00297 }
00298 }
00299 }
00300 else
00301 {
00302 for (int i = 0; i < s.size(); i++)
00303 {
00304
00305 if (s[i] >= ' ')
00306 {
00307
00308 dest += s[i];
00309 }
00310 else
00311 {
00312 switch (s[i])
00313 {
00314 case 0x02:
00315 dest += "<STX>";
00316 break;
00317 case 0x03:
00318 dest += "<ETX>";
00319 break;
00320 }
00321 }
00322 }
00323 }
00324
00325 return(dest);
00326 }
00327
00332 SickScanCommon::SickScanCommon(SickGenericParser *parser) :
00333 diagnosticPub_(NULL), parser_(parser)
00334
00335 {
00336 expectedFrequency_ = this->parser_->getCurrentParamPtr()->getExpectedFrequency();
00337
00338 setSensorIsRadar(false);
00339 init_cmdTables();
00340 #ifndef _MSC_VER
00341 dynamic_reconfigure::Server<sick_scan::SickScanConfig>::CallbackType f;
00342 f = boost::bind(&sick_scan::SickScanCommon::update_config, this, _1, _2);
00343 dynamic_reconfigure_server_.setCallback(f);
00344 #else
00345
00346 {
00347 SickScanConfig cfg;
00348 ros::NodeHandle tmp("~");
00349 double min_angle, max_angle, res_angle;
00350 tmp.getParam(PARAM_MIN_ANG, min_angle);
00351 tmp.getParam(PARAM_MAX_ANG, max_angle);
00352 tmp.getParam(PARAM_RES_ANG, res_angle);
00353 cfg.min_ang = min_angle;
00354 cfg.max_ang = max_angle;
00355 cfg.skip = 0;
00356 update_config(cfg);
00357 }
00358 #endif
00359
00360 ros::NodeHandle pn("~");
00361 pn.param<bool>("publish_datagram", publish_datagram_, false);
00362 if (publish_datagram_)
00363 {
00364 datagram_pub_ = nh_.advertise<std_msgs::String>("datagram", 1000);
00365 }
00366
00367
00368
00369
00370
00371
00372 std::string cloud_topic_val = "cloud";
00373 pn.getParam("cloud_topic", cloud_topic_val);
00374
00375 ROS_INFO("Publishing laserscan-pointcloud2 to %s", cloud_topic_val.c_str());
00376 cloud_pub_ = nh_.advertise<sensor_msgs::PointCloud2>(cloud_topic_val, 100);
00377
00378
00379 cloud_radar_rawtarget_pub_ = nh_.advertise<sensor_msgs::PointCloud2>("cloud_radar_rawtarget", 100);
00380 cloud_radar_track_pub_ = nh_.advertise<sensor_msgs::PointCloud2>("cloud_radar_track", 100);
00381
00382 radarScan_pub_ = nh_.advertise<sick_scan::RadarScan>("radar", 100);
00383 imuScan_pub_ = nh_.advertise<sensor_msgs::Imu>("imu", 100);
00384
00385 pub_ = nh_.advertise<sensor_msgs::LaserScan>("scan", 1000);
00386
00387 #ifndef _MSC_VER
00388 diagnostics_.setHardwareID("none");
00389 diagnosticPub_ = new diagnostic_updater::DiagnosedPublisher<sensor_msgs::LaserScan>(pub_, diagnostics_,
00390
00391 diagnostic_updater::FrequencyStatusParam(
00392 &expectedFrequency_,
00393 &expectedFrequency_, 0.1,
00394 10),
00395
00396 diagnostic_updater::TimeStampStatusParam(
00397 -1, 1.3 * 1.0 /
00398 expectedFrequency_ -
00399 config_.time_offset));
00400 ROS_ASSERT(diagnosticPub_ != NULL);
00401 #endif
00402 }
00403
00408 int SickScanCommon::stop_scanner()
00409 {
00410
00411
00412
00413 const char requestScanData0[] = {"\x02sEN LMDscandata 0\x03\0"};
00414 int result = sendSOPASCommand(requestScanData0, NULL);
00415 if (result != 0)
00416 {
00417
00418 printf("\nSOPAS - Error stopping streaming scan data!\n");
00419 }
00420 else
00421 {
00422 printf("\nSOPAS - Stopped streaming scan data.\n");
00423 }
00424
00425 return result;
00426 }
00427
00433 unsigned long SickScanCommon::convertBigEndianCharArrayToUnsignedLong(const unsigned char *vecArr)
00434 {
00435 unsigned long val = 0;
00436 for (int i = 0; i < 4; i++)
00437 {
00438 val = val << 8;
00439 val |= vecArr[i];
00440 }
00441 return (val);
00442 }
00443
00444
00450 int sick_scan::SickScanCommon::checkForBinaryAnswer(const std::vector<unsigned char> *reply)
00451 {
00452 int retVal = -1;
00453
00454 if (reply == NULL)
00455 {
00456 }
00457 else
00458 {
00459 if (reply->size() < 8)
00460 {
00461 retVal = -1;
00462 }
00463 else
00464 {
00465 const unsigned char *ptr = &((*reply)[0]);
00466 unsigned binId = convertBigEndianCharArrayToUnsignedLong(ptr);
00467 unsigned cmdLen = convertBigEndianCharArrayToUnsignedLong(ptr + 4);
00468 if (binId == 0x02020202)
00469 {
00470 int replyLen = reply->size();
00471 if (replyLen == 8 + cmdLen + 1)
00472 {
00473 retVal = cmdLen;
00474 }
00475 }
00476 }
00477 }
00478 return (retVal);
00479
00480 }
00481
00482
00487 bool SickScanCommon::rebootScanner()
00488 {
00489
00490
00491
00492 std::vector<unsigned char> access_reply;
00493
00494 int result = sendSOPASCommand("\x02sMN SetAccessMode 3 F4724744\x03\0", &access_reply);
00495 if (result != 0)
00496 {
00497 ROS_ERROR("SOPAS - Error setting access mode");
00498 diagnostics_.broadcast(getDiagnosticErrorCode(), "SOPAS - Error setting access mode.");
00499 return false;
00500 }
00501 std::string access_reply_str = replyToString(access_reply);
00502 if (access_reply_str != "sAN SetAccessMode 1")
00503 {
00504 ROS_ERROR_STREAM("SOPAS - Error setting access mode, unexpected response : " << access_reply_str);
00505 diagnostics_.broadcast(getDiagnosticErrorCode(), "SOPAS - Error setting access mode.");
00506 return false;
00507 }
00508
00509
00510
00511
00512 std::vector<unsigned char> reboot_reply;
00513 result = sendSOPASCommand("\x02sMN mSCreboot\x03\0", &reboot_reply);
00514 if (result != 0)
00515 {
00516 ROS_ERROR("SOPAS - Error rebooting scanner");
00517 diagnostics_.broadcast(getDiagnosticErrorCode(), "SOPAS - Error rebooting device.");
00518 return false;
00519 }
00520 std::string reboot_reply_str = replyToString(reboot_reply);
00521 if (reboot_reply_str != "sAN mSCreboot")
00522 {
00523 ROS_ERROR_STREAM("SOPAS - Error rebooting scanner, unexpected response : " << reboot_reply_str);
00524 diagnostics_.broadcast(getDiagnosticErrorCode(), "SOPAS - Error setting access mode.");
00525 return false;
00526 }
00527
00528 ROS_INFO("SOPAS - Rebooted scanner");
00529
00530
00531 ros::Duration(15.0).sleep();
00532
00533 return true;
00534 }
00535
00539 SickScanCommon::~SickScanCommon()
00540 {
00541 delete diagnosticPub_;
00542
00543 printf("sick_scan driver exiting.\n");
00544 }
00545
00546
00552 std::string SickScanCommon::generateExpectedAnswerString(const std::vector<unsigned char> requestStr)
00553 {
00554 std::string expectedAnswer = "";
00555 int i = 0;
00556 char cntWhiteCharacter = 0;
00557 int initalTokenCnt = 2;
00558 std::map<std::string, int> specialTokenLen;
00559 char firstToken[1024] = {0};
00560 specialTokenLen["sRI"] = 1;
00561 std::string tmpStr = "";
00562 int cnt0x02 = 0;
00563 bool isBinary = false;
00564 for (int i = 0; i < 4; i++)
00565 {
00566 if (i < requestStr.size())
00567 {
00568 if (requestStr[i] == 0x02)
00569 {
00570 cnt0x02++;
00571 }
00572
00573 }
00574 }
00575
00576 int iStop = requestStr.size();
00577 if (cnt0x02 == 4)
00578 {
00579
00580 int cmdLen = 0;
00581 for (int i = 0; i < 4; i++)
00582 {
00583 cmdLen |= cmdLen << 8;
00584 cmdLen |= requestStr[i + 4];
00585 }
00586 iStop = cmdLen + 8;
00587 isBinary = true;
00588
00589 }
00590 int iStart = (isBinary == true) ? 8 : 0;
00591 for (int i = iStart; i < iStop; i++)
00592 {
00593 tmpStr += (char) requestStr[i];
00594 }
00595 if (isBinary)
00596 {
00597 tmpStr = "\x2" + tmpStr;
00598 }
00599 if (sscanf(tmpStr.c_str(), "\x2%s", firstToken) == 1)
00600 {
00601 if (specialTokenLen.find(firstToken) != specialTokenLen.end())
00602 {
00603 initalTokenCnt = specialTokenLen[firstToken];
00604
00605 }
00606 }
00607
00608 for (int i = iStart; i < iStop; i++)
00609 {
00610 if ((requestStr[i] == ' ') || (requestStr[i] == '\x3'))
00611 {
00612 cntWhiteCharacter++;
00613 }
00614 if (cntWhiteCharacter >= initalTokenCnt)
00615 {
00616 break;
00617 }
00618 if (requestStr[i] == '\x2')
00619 {
00620 }
00621 else
00622 {
00623 expectedAnswer += requestStr[i];
00624 }
00625 }
00626
00630 std::map<std::string, std::string> keyWordMap;
00631 keyWordMap["sWN"] = "sWA";
00632 keyWordMap["sRN"] = "sRA";
00633 keyWordMap["sRI"] = "sRA";
00634 keyWordMap["sMN"] = "sAN";
00635 keyWordMap["sEN"] = "sEA";
00636
00637 for (std::map<std::string, std::string>::iterator it = keyWordMap.begin(); it != keyWordMap.end(); it++)
00638 {
00639
00640 std::string keyWord = it->first;
00641 std::string newKeyWord = it->second;
00642
00643 size_t pos = expectedAnswer.find(keyWord);
00644 if (pos == std::string::npos)
00645 {
00646
00647 }
00648 else
00649 {
00650 if (pos == 0)
00651 {
00652 expectedAnswer.replace(pos, keyWord.length(), newKeyWord);
00653 }
00654 else
00655 {
00656 ROS_WARN("Unexpected position of key identifier.\n");
00657 }
00658 }
00659
00660 }
00661 return (expectedAnswer);
00662
00663 }
00664
00672 int SickScanCommon::sendSopasAndCheckAnswer(std::string requestStr, std::vector<unsigned char> *reply, int cmdId = -1)
00673 {
00674 std::vector<unsigned char> requestStringVec;
00675 for (int i = 0; i < requestStr.length(); i++)
00676 {
00677 requestStringVec.push_back(requestStr[i]);
00678 }
00679 int retCode = sendSopasAndCheckAnswer(requestStringVec, reply, cmdId);
00680 return (retCode);
00681 }
00682
00690 int SickScanCommon::sendSopasAndCheckAnswer(std::vector<unsigned char> requestStr, std::vector<unsigned char> *reply,
00691 int cmdId = -1)
00692 {
00693
00694 std::string cmdStr = "";
00695 int cmdLen = 0;
00696 for (int i = 0; i < requestStr.size(); i++)
00697 {
00698 cmdLen++;
00699 cmdStr += (char) requestStr[i];
00700 }
00701 int result = -1;
00702
00703 std::string errString;
00704 if (cmdId == -1)
00705 {
00706 errString = "Error unexpected Sopas Answer for request " + stripControl(requestStr);
00707 }
00708 else
00709 {
00710 errString = this->sopasCmdErrMsg[cmdId];
00711 }
00712
00713 std::string expectedAnswer = generateExpectedAnswerString(requestStr);
00714
00715
00716
00717 std::string reqStr = replyToString(requestStr);
00718 ROS_INFO("Sending : %s", stripControl(requestStr).c_str());
00719 result = sendSOPASCommand(cmdStr.c_str(), reply, cmdLen);
00720 std::string replyStr = replyToString(*reply);
00721 std::vector<unsigned char> replyVec;
00722 replyStr = "<STX>" + replyStr + "<ETX>";
00723 replyVec=stringToVector(replyStr);
00724 ROS_INFO("Receiving: %s", stripControl(replyVec).c_str());
00725
00726 if (result != 0)
00727 {
00728 std::string tmpStr = "SOPAS Communication -" + errString;
00729 ROS_INFO("%s\n", tmpStr.c_str());
00730 diagnostics_.broadcast(getDiagnosticErrorCode(), tmpStr);
00731 }
00732 else
00733 {
00734 std::string answerStr = replyToString(*reply);
00735 std::string searchPattern = generateExpectedAnswerString(requestStr);
00736
00737 if (answerStr.find(searchPattern) != std::string::npos)
00738 {
00739 result = 0;
00740 }
00741 else
00742 {
00743 if (cmdId == CMD_START_IMU_DATA)
00744 {
00745 ROS_INFO("IMU-Data transfer started. No checking of reply to avoid confusing with LMD Scandata\n");
00746 result = 0;
00747 }
00748 else
00749 {
00750 std::string tmpMsg = "Error Sopas answer mismatch " + errString + "Answer= >>>" + answerStr + "<<<";
00751 ROS_ERROR("%s\n", tmpMsg.c_str());
00752 diagnostics_.broadcast(getDiagnosticErrorCode(), tmpMsg);
00753 result = -1;
00754 }
00755 }
00756 }
00757 return result;
00758
00759 }
00760
00766 void SickScanCommon::setReadTimeOutInMs(int timeOutInMs)
00767 {
00768 readTimeOutInMs = timeOutInMs;
00769 }
00770
00776 int SickScanCommon::getReadTimeOutInMs()
00777 {
00778 return (readTimeOutInMs);
00779 }
00780
00786 int SickScanCommon::getProtocolType(void)
00787 {
00788 return m_protocolId;
00789 }
00790
00795 void SickScanCommon::setProtocolType(SopasProtocol cola_dialect_id)
00796 {
00797 m_protocolId = cola_dialect_id;
00798 }
00799
00804 int SickScanCommon::init()
00805 {
00806 int result = init_device();
00807 if (result != 0)
00808 {
00809 ROS_FATAL("Failed to init device: %d", result);
00810 return result;
00811 }
00812 result = init_scanner();
00813 if (result != 0)
00814 {
00815 ROS_INFO("Failed to init scanner Error Code: %d\nWaiting for timeout...\n"
00816 "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"
00817 "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"
00818 "1. [Recommended] Set the communication mode with the SOPAS ET software to binary and save this setting in the scanner's EEPROM.\n"
00819 "2. Use the parameter \"use_binary_protocol\" to overwrite the default settings of the driver.",
00820 result);
00821 }
00822
00823 return result;
00824 }
00825
00826
00831 int SickScanCommon::init_cmdTables()
00832 {
00833 sopasCmdVec.resize(SickScanCommon::CMD_END);
00834 sopasCmdMaskVec.resize(
00835 SickScanCommon::CMD_END);
00836 sopasCmdErrMsg.resize(
00837 SickScanCommon::CMD_END);
00838 sopasReplyVec.resize(SickScanCommon::CMD_END);
00839 sopasReplyBinVec.resize(SickScanCommon::CMD_END);
00840 sopasReplyStrVec.resize(SickScanCommon::CMD_END);
00841
00842 std::string unknownStr = "Command or Error message not defined";
00843 for (int i = 0; i < SickScanCommon::CMD_END; i++)
00844 {
00845 sopasCmdVec[i] = unknownStr;
00846 sopasCmdMaskVec[i] = unknownStr;
00847 sopasCmdErrMsg[i] = unknownStr;
00848 sopasReplyVec[i] = unknownStr;
00849 sopasReplyStrVec[i] = unknownStr;
00850 }
00851
00852 sopasCmdVec[CMD_DEVICE_IDENT_LEGACY] = "\x02sRI 0\x03\0";
00853 sopasCmdVec[CMD_DEVICE_IDENT] = "\x02sRN DeviceIdent\x03\0";
00854 sopasCmdVec[CMD_REBOOT] = "\x02sMN mSCreboot\x03";
00855 sopasCmdVec[CMD_WRITE_EEPROM] = "\x02sMN mEEwriteall\x03";
00856 sopasCmdVec[CMD_SERIAL_NUMBER] = "\x02sRN SerialNumber\x03\0";
00857 sopasCmdVec[CMD_FIRMWARE_VERSION] = "\x02sRN FirmwareVersion\x03\0";
00858 sopasCmdVec[CMD_DEVICE_STATE] = "\x02sRN SCdevicestate\x03\0";
00859 sopasCmdVec[CMD_OPERATION_HOURS] = "\x02sRN ODoprh\x03\0";
00860 sopasCmdVec[CMD_POWER_ON_COUNT] = "\x02sRN ODpwrc\x03\0";
00861 sopasCmdVec[CMD_LOCATION_NAME] = "\x02sRN LocationName\x03\0";
00862 sopasCmdVec[CMD_ACTIVATE_STANDBY] = "\x02sMN LMCstandby\x03";
00863 sopasCmdVec[CMD_SET_ACCESS_MODE_3] = "\x02sMN SetAccessMode 3 F4724744\x03\0";
00864 sopasCmdVec[CMD_GET_OUTPUT_RANGES] = "\x02sRN LMPoutputRange\x03";
00865 sopasCmdVec[CMD_RUN] = "\x02sMN Run\x03\0";
00866 sopasCmdVec[CMD_STOP_SCANDATA] = "\x02sEN LMDscandata 0\x03";
00867 sopasCmdVec[CMD_START_SCANDATA] = "\x02sEN LMDscandata 1\x03";
00868 sopasCmdVec[CMD_START_RADARDATA] = "\x02sEN LMDradardata 1\x03";
00869 sopasCmdVec[CMD_ACTIVATE_NTP_CLIENT] ="\x02sWN TSCRole 1\x03";
00870 sopasCmdVec[CMD_SET_NTP_INTERFACE_ETH]= "\x02sWN TSCTCInterface 0\x03";
00871
00872
00873
00874
00875 sopasCmdVec[CMD_SET_TRANSMIT_RAWTARGETS_ON] = "\x02sWN TransmitTargets 1\x03";
00876 sopasCmdVec[CMD_SET_TRANSMIT_RAWTARGETS_OFF] = "\x02sWN TransmitTargets 0\x03";
00877 sopasCmdVec[CMD_SET_TRANSMIT_OBJECTS_ON] = "\x02sWN TransmitObjects 1\x03";
00878 sopasCmdVec[CMD_SET_TRANSMIT_OBJECTS_OFF] = "\x02sWN TransmitObjects 0\x03";
00879 sopasCmdVec[CMD_SET_TRACKING_MODE_0] = "\x02sWN TCTrackingMode 0\x03";
00880 sopasCmdVec[CMD_SET_TRACKING_MODE_1] = "\x02sWN TCTrackingMode 1\x03";
00881
00882
00883 sopasCmdVec[CMD_LOAD_APPLICATION_DEFAULT] = "\x02sMN mSCloadappdef\x03";
00884 sopasCmdVec[CMD_DEVICE_TYPE] = "\x02sRN DItype\x03";
00885 sopasCmdVec[CMD_ORDER_NUMBER] = "\x02sRN OrdNum\x03";
00886
00887
00888
00889 sopasCmdVec[CMD_START_MEASUREMENT] = "\x02sMN LMCstartmeas\x03";
00890 sopasCmdVec[CMD_STOP_MEASUREMENT] = "\x02sMN LMCstopmeas\x03";
00891 sopasCmdVec[CMD_APPLICATION_MODE_FIELD_ON] = "\x02sWN SetActiveApplications 1 FEVL 1\x03";
00892 sopasCmdVec[CMD_APPLICATION_MODE_FIELD_OFF] = "\x02sWN SetActiveApplications 1 FEVL 0\x03";
00893 sopasCmdVec[CMD_APPLICATION_MODE_RANGING_ON] = "\x02sWN SetActiveApplications 1 RANG 1\x03";
00894 sopasCmdVec[CMD_SET_TO_COLA_A_PROTOCOL] = "\x02sWN EIHstCola 0\x03";
00895 sopasCmdVec[CMD_GET_PARTIAL_SCANDATA_CFG] = "\x02sRN LMDscandatacfg\x03";
00896 sopasCmdVec[CMD_GET_PARTIAL_SCAN_CFG] = "\x02sRN LMPscancfg\x03";
00897 sopasCmdVec[CMD_SET_TO_COLA_B_PROTOCOL] = "\x02sWN EIHstCola 1\x03";
00898
00899 sopasCmdVec[CMD_STOP_IMU_DATA] = "\x02sEN InertialMeasurementUnit 0\x03";
00900 sopasCmdVec[CMD_START_IMU_DATA] = "\x02sEN InertialMeasurementUnit 1\x03";
00901
00902
00903 sopasCmdMaskVec[CMD_SET_PARTIAL_SCAN_CFG] = "\x02sMN mLMPsetscancfg %d 1 %d 0 0\x03";
00904 sopasCmdMaskVec[CMD_SET_PARTICLE_FILTER] = "\x02sWN LFPparticle %d %d\x03";
00905 sopasCmdMaskVec[CMD_SET_MEAN_FILTER] = "\x02sWN LFPmeanfilter %d +%d 1\x03";
00906 sopasCmdMaskVec[CMD_ALIGNMENT_MODE] = "\x02sWN MMAlignmentMode %d\x03";
00907 sopasCmdMaskVec[CMD_APPLICATION_MODE] = "\x02sWN SetActiveApplications 1 %s %d\x03";
00908 sopasCmdMaskVec[CMD_SET_OUTPUT_RANGES] = "\x02sWN LMPoutputRange 1 %X %X %X\x03";
00909 sopasCmdMaskVec[CMD_SET_PARTIAL_SCANDATA_CFG] = "\x02sWN LMDscandatacfg %02d 00 %d %d 0 00 00 0 0 0 1 1\x03";
00910 sopasCmdMaskVec[CMD_SET_ECHO_FILTER] = "\x02sWN FREchoFilter %d\x03";
00911 sopasCmdMaskVec[CMD_SET_NTP_UPDATETIME] = "\x02sWN TSCTCupdatetime %d\x03";
00912 sopasCmdMaskVec[CMD_SET_NTP_TIMEZONE]= "sWN TSCTCtimezone %d";
00913 sopasCmdMaskVec[CMD_SET_IP_ADDR] = "\x02sWN EIIpAddr %02X %02X %02X %02X\x03";
00914 sopasCmdMaskVec[CMD_SET_NTP_SERVER_IP_ADDR] = "\x02sWN TSCTCSrvAddr %02X %02X %02X %02X\x03";
00915 sopasCmdMaskVec[CMD_SET_GATEWAY] = "\x02sWN EIgate %02X %02X %02X %02X\x03";
00916
00917 sopasCmdErrMsg[CMD_DEVICE_IDENT_LEGACY] = "Error reading device ident";
00918 sopasCmdErrMsg[CMD_DEVICE_IDENT] = "Error reading device ident for MRS-family";
00919 sopasCmdErrMsg[CMD_SERIAL_NUMBER] = "Error reading SerialNumber";
00920 sopasCmdErrMsg[CMD_FIRMWARE_VERSION] = "Error reading FirmwareVersion";
00921 sopasCmdErrMsg[CMD_DEVICE_STATE] = "Error reading SCdevicestate";
00922 sopasCmdErrMsg[CMD_OPERATION_HOURS] = "Error reading operation hours";
00923 sopasCmdErrMsg[CMD_POWER_ON_COUNT] = "Error reading operation power on counter";
00924 sopasCmdErrMsg[CMD_LOCATION_NAME] = "Error reading Locationname";
00925 sopasCmdErrMsg[CMD_ACTIVATE_STANDBY] = "Error acticvating Standby";
00926 sopasCmdErrMsg[CMD_SET_PARTICLE_FILTER] = "Error setting Particelefilter";
00927 sopasCmdErrMsg[CMD_SET_MEAN_FILTER] = "Error setting Meanfilter";
00928 sopasCmdErrMsg[CMD_ALIGNMENT_MODE] = "Error setting Alignmentmode";
00929 sopasCmdErrMsg[CMD_APPLICATION_MODE] = "Error setting Meanfilter";
00930 sopasCmdErrMsg[CMD_SET_ACCESS_MODE_3] = "Error Access Mode";
00931 sopasCmdErrMsg[CMD_SET_OUTPUT_RANGES] = "Error setting angular ranges";
00932 sopasCmdErrMsg[CMD_GET_OUTPUT_RANGES] = "Error reading angle range";
00933 sopasCmdErrMsg[CMD_RUN] = "FATAL ERROR unable to start RUN mode!";
00934 sopasCmdErrMsg[CMD_SET_PARTIAL_SCANDATA_CFG] = "Error setting Scandataconfig";
00935 sopasCmdErrMsg[CMD_STOP_SCANDATA] = "Error stopping scandata output";
00936 sopasCmdErrMsg[CMD_START_SCANDATA] = "Error starting Scandata output";
00937 sopasCmdErrMsg[CMD_SET_IP_ADDR] = "Error setting IP address";
00938 sopasCmdErrMsg[CMD_SET_GATEWAY] = "Error setting gateway";
00939 sopasCmdErrMsg[CMD_REBOOT] = "Error rebooting the device";
00940 sopasCmdErrMsg[CMD_WRITE_EEPROM] = "Error writing data to EEPRom";
00941 sopasCmdErrMsg[CMD_ACTIVATE_NTP_CLIENT] ="Error activating NTP client";
00942 sopasCmdErrMsg[CMD_SET_NTP_INTERFACE_ETH] ="Error setting NTP interface to ETH";
00943 sopasCmdErrMsg[CMD_SET_NTP_SERVER_IP_ADDR] ="Error setting NTP server Adress";
00944 sopasCmdErrMsg[CMD_SET_NTP_UPDATETIME] = "Error setting NTP update time";
00945 sopasCmdErrMsg[CMD_SET_NTP_TIMEZONE] = "Error setting NTP timezone";
00946
00947
00948
00949
00950
00951
00952 sopasCmdChain.push_back(CMD_SET_ACCESS_MODE_3);
00953
00954 if (parser_->getCurrentParamPtr()->getUseBinaryProtocol())
00955 {
00956 sopasCmdChain.push_back(CMD_SET_TO_COLA_B_PROTOCOL);
00957 }
00958 else
00959 {
00960
00961 sopasCmdChain.push_back(CMD_SET_TO_COLA_A_PROTOCOL);
00962 }
00963
00964 bool tryToStopMeasurement = true;
00965 if (parser_->getCurrentParamPtr()->getNumberOfLayers() == 1)
00966 {
00967
00968 tryToStopMeasurement = false;
00969
00970
00971
00972 }
00973 if (parser_->getCurrentParamPtr()->getDeviceIsRadar() == true)
00974 {
00975 sopasCmdChain.push_back(CMD_LOAD_APPLICATION_DEFAULT);
00976
00977 tryToStopMeasurement = false;
00978
00979 }
00980
00981 if (tryToStopMeasurement)
00982 {
00983 sopasCmdChain.push_back(CMD_STOP_MEASUREMENT);
00984 int numberOfLayers = parser_->getCurrentParamPtr()->getNumberOfLayers();
00985
00986 switch (numberOfLayers)
00987 {
00988 case 4:
00989 sopasCmdChain.push_back(CMD_APPLICATION_MODE_FIELD_OFF);
00990 sopasCmdChain.push_back(CMD_APPLICATION_MODE_RANGING_ON);
00991 sopasCmdChain.push_back(CMD_DEVICE_IDENT);
00992 sopasCmdChain.push_back(CMD_SERIAL_NUMBER);
00993
00994 break;
00995 case 24:
00996
00997
00998 sopasCmdChain.push_back(CMD_DEVICE_IDENT);
00999 break;
01000
01001 default:
01002 sopasCmdChain.push_back(CMD_APPLICATION_MODE_FIELD_OFF);
01003 sopasCmdChain.push_back(CMD_APPLICATION_MODE_RANGING_ON);
01004 sopasCmdChain.push_back(CMD_DEVICE_IDENT_LEGACY);
01005
01006 sopasCmdChain.push_back(CMD_SERIAL_NUMBER);
01007 break;
01008 }
01009
01010 }
01011 sopasCmdChain.push_back(CMD_FIRMWARE_VERSION);
01012 sopasCmdChain.push_back(CMD_DEVICE_STATE);
01013 sopasCmdChain.push_back(CMD_OPERATION_HOURS);
01014 sopasCmdChain.push_back(CMD_POWER_ON_COUNT);
01015 sopasCmdChain.push_back(CMD_LOCATION_NAME);
01016
01017
01018 return (0);
01019
01020 }
01021
01022
01027 int SickScanCommon::init_scanner()
01028 {
01029
01030 const int MAX_STR_LEN = 1024;
01031
01032 int maxNumberOfEchos = 1;
01033
01034
01035 maxNumberOfEchos = this->parser_->getCurrentParamPtr()->getNumberOfMaximumEchos();
01036
01037
01038 bool rssiFlag = false;
01039 bool rssiResolutionIs16Bit = true;
01040 int activeEchos = 0;
01041 ros::NodeHandle pn("~");
01042
01043 pn.getParam("intensity", rssiFlag);
01044 pn.getParam("intensity_resolution_16bit", rssiResolutionIs16Bit);
01045
01046
01047 std::string sNewIPAddr = "";
01048 boost::asio::ip::address_v4 ipNewIPAddr;
01049 bool setNewIPAddr = false;
01050 setNewIPAddr = pn.getParam("new_IP_address", sNewIPAddr);
01051 if (setNewIPAddr)
01052 {
01053 boost::system::error_code ec;
01054 ipNewIPAddr = boost::asio::ip::address_v4::from_string(sNewIPAddr, ec);
01055 if (ec == 0)
01056 {
01057 sopasCmdChain.clear();
01058 sopasCmdChain.push_back(CMD_SET_ACCESS_MODE_3);
01059 }
01060 else
01061 {
01062 setNewIPAddr = false;
01063 ROS_ERROR("ERROR: IP ADDRESS could not be parsed Boost Error %s:%d", ec.category().name(), ec.value());;
01064 }
01065
01066 }
01067 std::string sNTPIpAdress = "";
01068 boost::asio::ip::address_v4 NTPIpAdress;
01069 bool setUseNTP=false;
01070 setUseNTP = pn.getParam("ntp_server_address", sNTPIpAdress);
01071 if (setUseNTP)
01072 {
01073 boost::system::error_code ec;
01074 NTPIpAdress = boost::asio::ip::address_v4::from_string(sNTPIpAdress, ec);
01075 if (ec != 0)
01076 {
01077 setUseNTP = false;
01078 ROS_ERROR("ERROR: NTP Server IP ADDRESS could not be parsed Boost Error %s:%d", ec.category().name(), ec.value());;
01079 }
01080 }
01081
01082 this->parser_->getCurrentParamPtr()->setIntensityResolutionIs16Bit(rssiResolutionIs16Bit);
01083
01084
01085 pn.getParam("active_echos", activeEchos);
01086
01087 ROS_INFO("Parameter setting for <active_echo: %d>", activeEchos);
01088 std::vector<bool> outputChannelFlag;
01089 outputChannelFlag.resize(maxNumberOfEchos);
01090 int i;
01091 int numOfFlags = 0;
01092 for (i = 0; i < outputChannelFlag.size(); i++)
01093 {
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110 outputChannelFlag[i] = true;
01111 numOfFlags++;
01112 }
01113
01114 if (numOfFlags == 0)
01115 {
01116 outputChannelFlag[0] = true;
01117 numOfFlags = 1;
01118 ROS_WARN("Activate at least one echo.");
01119 }
01120
01121 int result;
01122
01123 int angleRes10000th = 0;
01124 int angleStart10000th = 0;
01125 int angleEnd10000th = 0;
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138 volatile bool useBinaryCmd = false;
01139 if (this->parser_->getCurrentParamPtr()->getUseBinaryProtocol())
01140 {
01141 useBinaryCmd = true;
01142 }
01143
01144 bool useBinaryCmdNow = false;
01145 int maxCmdLoop = 2;
01146
01147 const int shortTimeOutInMs = 5000;
01148 const int defaultTimeOutInMs = 20000;
01149
01150 setReadTimeOutInMs(shortTimeOutInMs);
01151
01152 bool restartDueToProcolChange = false;
01153
01154
01155 for (int i = 0; i < this->sopasCmdChain.size(); i++)
01156 {
01157 ros::Duration(0.2).sleep();
01158
01159 int cmdId = sopasCmdChain[i];
01160 std::string sopasCmd = sopasCmdVec[cmdId];
01161 std::vector<unsigned char> replyDummy;
01162 std::vector<unsigned char> reqBinary;
01163
01164 std::vector<unsigned char> sopasCmdVec;
01165 for (int j = 0; j < sopasCmd.length(); j++)
01166 {
01167 sopasCmdVec.push_back(sopasCmd[j]);
01168 }
01169 ROS_DEBUG("Command: %s", stripControl(sopasCmdVec).c_str());
01170
01171
01172
01173
01174
01175 for (int iLoop = 0; iLoop < maxCmdLoop; iLoop++)
01176 {
01177 if (iLoop == 0)
01178 {
01179 useBinaryCmdNow = useBinaryCmd;
01180
01181 }
01182 else
01183 {
01184 useBinaryCmdNow = !useBinaryCmdNow;
01185 useBinaryCmd = useBinaryCmdNow;
01186
01187 }
01188
01189 this->setProtocolType(useBinaryCmdNow ? CoLa_B : CoLa_A);
01190
01191
01192 if (useBinaryCmdNow)
01193 {
01194 this->convertAscii2BinaryCmd(sopasCmd.c_str(), &reqBinary);
01195 result = sendSopasAndCheckAnswer(reqBinary, &replyDummy);
01196 sopasReplyBinVec[cmdId] = replyDummy;
01197 }
01198 else
01199 {
01200 result = sendSopasAndCheckAnswer(sopasCmd.c_str(), &replyDummy);
01201 }
01202 if (result == 0)
01203 {
01204
01205 break;
01206 }
01207 }
01208 if (result != 0)
01209 {
01210 ROS_ERROR("%s", sopasCmdErrMsg[cmdId].c_str());
01211 diagnostics_.broadcast(getDiagnosticErrorCode(), sopasCmdErrMsg[cmdId]);
01212 }
01213 else
01214 {
01215 sopasReplyStrVec[cmdId] = replyToString(replyDummy);
01216 }
01217
01218
01219
01220
01221
01222 maxCmdLoop = 1;
01223
01224
01225
01226
01227 switch (cmdId)
01228 {
01229
01230 case CMD_SET_TO_COLA_A_PROTOCOL:
01231 {
01232 bool protocolCheck = checkForProtocolChangeAndMaybeReconnect(useBinaryCmdNow);
01233 if (false == protocolCheck)
01234 {
01235 restartDueToProcolChange = true;
01236 }
01237 useBinaryCmd = useBinaryCmdNow;
01238 setReadTimeOutInMs(defaultTimeOutInMs);
01239 }
01240 break;
01241 case CMD_SET_TO_COLA_B_PROTOCOL:
01242 {
01243 bool protocolCheck = checkForProtocolChangeAndMaybeReconnect(useBinaryCmdNow);
01244 if (false == protocolCheck)
01245 {
01246 restartDueToProcolChange = true;
01247 }
01248 useBinaryCmd = useBinaryCmdNow;
01249 setReadTimeOutInMs(defaultTimeOutInMs);
01250 }
01251 break;
01252
01253
01254
01255
01256
01257 case CMD_DEVICE_IDENT:
01258 {
01259 std::string deviceIdent = "";
01260 int cmdLen = this->checkForBinaryAnswer(&replyDummy);
01261 if (cmdLen == -1)
01262 {
01263 int idLen = 0;
01264 int versionLen = 0;
01265
01266 std::string deviceIdentKeyWord = "sRA DeviceIdent";
01267 char *ptr = (char *) (&(replyDummy[0]));
01268 ptr++;
01269 ptr += deviceIdentKeyWord.length();
01270 ptr++;
01271 sscanf(ptr, "%d", &idLen);
01272 char *ptr2 = strchr(ptr, ' ');
01273 if (ptr2 != NULL)
01274 {
01275 ptr2++;
01276 for (int i = 0; i < idLen; i++)
01277 {
01278 deviceIdent += *ptr2;
01279 ptr2++;
01280 }
01281
01282 }
01283 ptr = ptr2;
01284 ptr++;
01285 sscanf(ptr, "%d", &versionLen);
01286 ptr2 = strchr(ptr, ' ');
01287 if (ptr2 != NULL)
01288 {
01289 ptr2++;
01290 deviceIdent += " V";
01291 for (int i = 0; i < versionLen; i++)
01292 {
01293 deviceIdent += *ptr2;
01294 ptr2++;
01295 }
01296 }
01297 diagnostics_.setHardwareID(deviceIdent);
01298 if (!isCompatibleDevice(deviceIdent))
01299 {
01300 return ExitFatal;
01301 }
01302
01303 }
01304 else
01305 {
01306 long dummy0, dummy1, identLen, versionLen;
01307 dummy0 = 0;
01308 dummy1 = 0;
01309 identLen = 0;
01310 versionLen = 0;
01311
01312 const char *scanMask0 = "%04y%04ysRA DeviceIdent %02y";
01313 const char *scanMask1 = "%02y";
01314 unsigned char *replyPtr = &(replyDummy[0]);
01315 int scanDataLen0 = binScanfGuessDataLenFromMask(scanMask0);
01316 int scanDataLen1 = binScanfGuessDataLenFromMask(scanMask1);
01317 binScanfVec(&replyDummy, scanMask0, &dummy0, &dummy1, &identLen);
01318
01319 std::string identStr = binScanfGetStringFromVec(&replyDummy, scanDataLen0, identLen);
01320 int off = scanDataLen0 + identLen;
01321
01322 std::vector<unsigned char> restOfReplyDummy = std::vector<unsigned char>(replyDummy.begin() + off,
01323 replyDummy.end());
01324
01325 versionLen = 0;
01326 binScanfVec(&restOfReplyDummy, "%02y", &versionLen);
01327 std::string versionStr = binScanfGetStringFromVec(&restOfReplyDummy, scanDataLen1, versionLen);
01328 std::string fullIdentVersionInfo = identStr + " V" + versionStr;
01329 diagnostics_.setHardwareID(fullIdentVersionInfo);
01330 if (!isCompatibleDevice(fullIdentVersionInfo))
01331 {
01332 return ExitFatal;
01333 }
01334
01335 }
01336 break;
01337 }
01338
01339
01340 case CMD_SERIAL_NUMBER:
01341 if (this->parser_->getCurrentParamPtr()->getNumberOfLayers() == 4)
01342 {
01343
01344 }
01345 else
01346 {
01347 diagnostics_.setHardwareID(
01348 sopasReplyStrVec[CMD_DEVICE_IDENT_LEGACY] + " " + sopasReplyStrVec[CMD_SERIAL_NUMBER]);
01349
01350 if (!isCompatibleDevice(sopasReplyStrVec[CMD_DEVICE_IDENT_LEGACY]))
01351 {
01352 return ExitFatal;
01353 }
01354 }
01355 break;
01356
01357
01358
01359 case CMD_DEVICE_STATE:
01360 {
01361 int deviceState = -1;
01362
01363
01364
01365
01366
01367 int iRetVal = 0;
01368 if (useBinaryCmd)
01369 {
01370 long dummy0 = 0x00;
01371 long dummy1 = 0x00;
01372 deviceState = 0x00;
01373 iRetVal = binScanfVec(&(sopasReplyBinVec[CMD_DEVICE_STATE]), "%4y%4ysRA SCdevicestate %1y", &dummy0,
01374 &dummy1, &deviceState);
01375 }
01376 else
01377 {
01378 iRetVal = sscanf(sopasReplyStrVec[CMD_DEVICE_STATE].c_str(), "sRA SCdevicestate %d", &deviceState);
01379 }
01380 if (iRetVal > 0)
01381 {
01382 switch (deviceState)
01383 {
01384 case 0:
01385 ROS_DEBUG("Laser is busy");
01386 break;
01387 case 1:
01388 ROS_DEBUG("Laser is ready");
01389 break;
01390 case 2:
01391 ROS_ERROR_STREAM("Laser reports error state : " << sopasReplyStrVec[CMD_DEVICE_STATE]);
01392 if (config_.auto_reboot)
01393 {
01394 rebootScanner();
01395 };
01396 break;
01397 default:
01398 ROS_WARN_STREAM("Laser reports unknown devicestate : " << sopasReplyStrVec[CMD_DEVICE_STATE]);
01399 break;
01400 }
01401 }
01402 }
01403 break;
01404
01405 case CMD_OPERATION_HOURS:
01406 {
01407 int operationHours = -1;
01408 int iRetVal = 0;
01409
01410
01411
01412
01413 if (useBinaryCmd)
01414 {
01415 long dummy0, dummy1;
01416 dummy0 = 0;
01417 dummy1 = 0;
01418 operationHours = 0;
01419 iRetVal = binScanfVec(&(sopasReplyBinVec[CMD_OPERATION_HOURS]), "%4y%4ysRA ODoprh %4y", &dummy0, &dummy1,
01420 &operationHours);
01421 }
01422 else
01423 {
01424 operationHours = 0;
01425 iRetVal = sscanf(sopasReplyStrVec[CMD_OPERATION_HOURS].c_str(), "sRA ODoprh %x", &operationHours);
01426 }
01427 if (iRetVal > 0)
01428 {
01429 double hours = 0.1 * operationHours;
01430 pn.setParam("operationHours", hours);
01431 }
01432 }
01433 break;
01434
01435 case CMD_POWER_ON_COUNT:
01436 {
01437 int powerOnCount = -1;
01438 int iRetVal = -1;
01439 if (useBinaryCmd)
01440 {
01441 long dummy0, dummy1;
01442 powerOnCount = 0;
01443 iRetVal = binScanfVec(&(sopasReplyBinVec[CMD_POWER_ON_COUNT]), "%4y%4ysRA ODpwrc %4y", &dummy0, &dummy1,
01444 &powerOnCount);
01445 }
01446 else
01447 {
01448 iRetVal = sscanf(sopasReplyStrVec[CMD_POWER_ON_COUNT].c_str(), "sRA ODpwrc %x", &powerOnCount);
01449 }
01450 if (iRetVal > 0)
01451 {
01452 pn.setParam("powerOnCount", powerOnCount);
01453 }
01454
01455 }
01456 break;
01457
01458 case CMD_LOCATION_NAME:
01459 {
01460 char szLocationName[MAX_STR_LEN] = {0};
01461 const char *strPtr = sopasReplyStrVec[CMD_LOCATION_NAME].c_str();
01462 const char *searchPattern = "sRA LocationName ";
01463 strcpy(szLocationName, "unknown location");
01464 if (useBinaryCmd)
01465 {
01466 int iRetVal = 0;
01467 long dummy0, dummy1, locationNameLen;
01468 const char *binLocationNameMask = "%4y%4ysRA LocationName %2y";
01469 int prefixLen = binScanfGuessDataLenFromMask(binLocationNameMask);
01470 dummy0 = 0;
01471 dummy1 = 0;
01472 locationNameLen = 0;
01473
01474 iRetVal = binScanfVec(&(sopasReplyBinVec[CMD_LOCATION_NAME]), binLocationNameMask, &dummy0, &dummy1,
01475 &locationNameLen);
01476 if (iRetVal > 0)
01477 {
01478 std::string s;
01479 std::string locationNameStr = binScanfGetStringFromVec(&(sopasReplyBinVec[CMD_LOCATION_NAME]), prefixLen,
01480 locationNameLen);
01481 strcpy(szLocationName, locationNameStr.c_str());
01482 }
01483 }
01484 else
01485 {
01486 if (strstr(strPtr, searchPattern) == strPtr)
01487 {
01488 const char *ptr = strPtr + strlen(searchPattern);
01489 strcpy(szLocationName, ptr);
01490 }
01491 else
01492 {
01493 ROS_WARN("Location command not supported.\n");
01494 }
01495 }
01496 pn.setParam("locationName", std::string(szLocationName));
01497 }
01498 break;
01499 case CMD_GET_PARTIAL_SCANDATA_CFG:
01500 {
01501
01502 const char *strPtr = sopasReplyStrVec[CMD_LOCATION_NAME].c_str();
01503 ROS_INFO("Config: %s\n", strPtr);
01504 }
01505 break;
01506
01507 }
01508
01509 if (restartDueToProcolChange)
01510 {
01511 return ExitError;
01512
01513 }
01514
01515 }
01516
01517 if (setNewIPAddr)
01518 {
01519
01520 setNewIpAddress(ipNewIPAddr, useBinaryCmd);
01521 ROS_INFO("IP address changed. Node restart required");
01522 ROS_INFO("Exiting node NOW.");
01523 exit(0);
01524 }
01525
01526 if (setUseNTP)
01527 {
01528
01529 setNTPServerAndStart(NTPIpAdress, useBinaryCmd);
01530 }
01531
01532 if (this->parser_->getCurrentParamPtr()->getDeviceIsRadar())
01533 {
01534
01535
01536
01537 }
01538 else
01539 {
01540
01541
01542
01543
01544
01545
01546
01547 angleRes10000th = (int) (boost::math::round(
01548 10000.0 * this->parser_->getCurrentParamPtr()->getAngularDegreeResolution()));
01549 std::vector<unsigned char> askOutputAngularRangeReply;
01550
01551 if (useBinaryCmd)
01552 {
01553 std::vector<unsigned char> reqBinary;
01554 this->convertAscii2BinaryCmd(sopasCmdVec[CMD_GET_OUTPUT_RANGES].c_str(), &reqBinary);
01555 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_GET_OUTPUT_RANGES]);
01556 }
01557 else
01558 {
01559 result = sendSopasAndCheckAnswer(sopasCmdVec[CMD_GET_OUTPUT_RANGES].c_str(), &askOutputAngularRangeReply);
01560 }
01561
01562
01563 if (0 == result)
01564 {
01565 int askTmpAngleRes10000th = 0;
01566 int askTmpAngleStart10000th = 0;
01567 int askTmpAngleEnd10000th = 0;
01568 char dummy0[MAX_STR_LEN] = {0};
01569 char dummy1[MAX_STR_LEN] = {0};
01570 int dummyInt = 0;
01571
01572 int iDummy0, iDummy1;
01573 std::string askOutputAngularRangeStr = replyToString(askOutputAngularRangeReply);
01574
01575
01576
01577
01578
01579
01580
01581
01582 int numArgs;
01583
01584 if (useBinaryCmd)
01585 {
01586 iDummy0 = 0;
01587 iDummy1 = 0;
01588 dummyInt = 0;
01589 askTmpAngleRes10000th = 0;
01590 askTmpAngleStart10000th = 0;
01591 askTmpAngleEnd10000th = 0;
01592
01593 const char *askOutputAngularRangeBinMask = "%4y%4ysRA LMPoutputRange %2y%4y%4y%4y";
01594 numArgs = binScanfVec(&sopasReplyBinVec[CMD_GET_OUTPUT_RANGES], askOutputAngularRangeBinMask, &iDummy0,
01595 &iDummy1,
01596 &dummyInt,
01597 &askTmpAngleRes10000th,
01598 &askTmpAngleStart10000th,
01599 &askTmpAngleEnd10000th);
01600
01601 }
01602 else
01603 {
01604 numArgs = sscanf(askOutputAngularRangeStr.c_str(), "%s %s %d %X %X %X", dummy0, dummy1,
01605 &dummyInt,
01606 &askTmpAngleRes10000th,
01607 &askTmpAngleStart10000th,
01608 &askTmpAngleEnd10000th);
01609 }
01610 if (numArgs >= 6)
01611 {
01612 double askTmpAngleRes = askTmpAngleRes10000th / 10000.0;
01613 double askTmpAngleStart = askTmpAngleStart10000th / 10000.0;
01614 double askTmpAngleEnd = askTmpAngleEnd10000th / 10000.0;
01615
01616 angleRes10000th = askTmpAngleRes10000th;
01617 ROS_INFO("Angle resolution of scanner is %0.5lf [deg] (in 1/10000th deg: 0x%X)", askTmpAngleRes,
01618 askTmpAngleRes10000th);
01619
01620 }
01621 }
01622
01623
01624
01625
01626
01627
01628 ROS_INFO("MIN_ANG: %8.3f [rad] %8.3f [deg]", config_.min_ang, rad2deg(this->config_.min_ang));
01629 ROS_INFO("MAX_ANG: %8.3f [rad] %8.3f [deg]", config_.max_ang, rad2deg(this->config_.max_ang));
01630
01631
01632 double minAngSopas = rad2deg(this->config_.min_ang) + 90;
01633 double maxAngSopas = rad2deg(this->config_.max_ang) + 90;
01634 angleStart10000th = (int) (boost::math::round(10000.0 * minAngSopas));
01635 angleEnd10000th = (int) (boost::math::round(10000.0 * maxAngSopas));
01636
01637 char requestOutputAngularRange[MAX_STR_LEN];
01638
01639 std::vector<unsigned char> outputAngularRangeReply;
01640 const char *pcCmdMask = sopasCmdMaskVec[CMD_SET_OUTPUT_RANGES].c_str();
01641 sprintf(requestOutputAngularRange, pcCmdMask, angleRes10000th, angleStart10000th, angleEnd10000th);
01642
01643 if (useBinaryCmd)
01644 {
01645 unsigned char tmpBuffer[255] = {0};
01646 unsigned char sendBuffer[255] = {0};
01647 UINT16 sendLen;
01648 std::vector<unsigned char> reqBinary;
01649 int iStatus = 1;
01650
01651
01652
01653
01654 strcpy((char *) tmpBuffer, "WN LMPoutputRange ");
01655 unsigned short orgLen = strlen((char *) tmpBuffer);
01656 colab::addIntegerToBuffer<UINT16>(tmpBuffer, orgLen, iStatus);
01657 colab::addIntegerToBuffer<UINT32>(tmpBuffer, orgLen, angleRes10000th);
01658 colab::addIntegerToBuffer<UINT32>(tmpBuffer, orgLen, angleStart10000th);
01659 colab::addIntegerToBuffer<UINT32>(tmpBuffer, orgLen, angleEnd10000th);
01660 sendLen = orgLen;
01661 colab::addFrameToBuffer(sendBuffer, tmpBuffer, &sendLen);
01662
01663
01664
01665
01666
01667 reqBinary = std::vector<unsigned char>(sendBuffer, sendBuffer + sendLen);
01668
01669
01670
01671 result = sendSopasAndCheckAnswer(reqBinary, &outputAngularRangeReply);
01672 }
01673 else
01674 {
01675 result = sendSopasAndCheckAnswer(requestOutputAngularRange, &outputAngularRangeReply);
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691 askOutputAngularRangeReply.clear();
01692
01693 if (useBinaryCmd)
01694 {
01695 std::vector<unsigned char> reqBinary;
01696 this->convertAscii2BinaryCmd(sopasCmdVec[CMD_GET_OUTPUT_RANGES].c_str(), &reqBinary);
01697 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_GET_OUTPUT_RANGES]);
01698 }
01699 else
01700 {
01701 result = sendSopasAndCheckAnswer(sopasCmdVec[CMD_GET_OUTPUT_RANGES].c_str(), &askOutputAngularRangeReply);
01702 }
01703
01704 if (result == 0)
01705 {
01706 char dummy0[MAX_STR_LEN] = {0};
01707 char dummy1[MAX_STR_LEN] = {0};
01708 int dummyInt = 0;
01709 int askAngleRes10000th = 0;
01710 int askAngleStart10000th = 0;
01711 int askAngleEnd10000th = 0;
01712 int iDummy0, iDummy1;
01713 iDummy0 = 0;
01714 iDummy1 = 0;
01715 std::string askOutputAngularRangeStr = replyToString(askOutputAngularRangeReply);
01716
01717
01718
01719
01720
01721
01722
01723
01724 int numArgs;
01725
01726
01727
01728
01729
01730
01731 iDummy0 = 0;
01732 iDummy1 = 0;
01733 dummyInt = 0;
01734 askAngleRes10000th = 0;
01735 askAngleStart10000th = 0;
01736 askAngleEnd10000th = 0;
01737
01738
01739
01740
01741
01742
01743 if (useBinaryCmd)
01744 {
01745 const char *askOutputAngularRangeBinMask = "%4y%4ysRA LMPoutputRange %2y%4y%4y%4y";
01746 numArgs = binScanfVec(&sopasReplyBinVec[CMD_GET_OUTPUT_RANGES], askOutputAngularRangeBinMask, &iDummy0,
01747 &iDummy1,
01748 &dummyInt,
01749 &askAngleRes10000th,
01750 &askAngleStart10000th,
01751 &askAngleEnd10000th);
01752
01753 }
01754 else
01755 {
01756 numArgs = sscanf(askOutputAngularRangeStr.c_str(), "%s %s %d %X %X %X", dummy0, dummy1,
01757 &dummyInt,
01758 &askAngleRes10000th,
01759 &askAngleStart10000th,
01760 &askAngleEnd10000th);
01761 }
01762 if (numArgs >= 6)
01763 {
01764 double askTmpAngleRes = askAngleRes10000th / 10000.0;
01765 double askTmpAngleStart = askAngleStart10000th / 10000.0;
01766 double askTmpAngleEnd = askAngleEnd10000th / 10000.0;
01767
01768 angleRes10000th = askAngleRes10000th;
01769 ROS_INFO("Angle resolution of scanner is %0.5lf [deg] (in 1/10000th deg: 0x%X)", askTmpAngleRes,
01770 askAngleRes10000th);
01771
01772 }
01773 double askAngleRes = askAngleRes10000th / 10000.0;
01774 double askAngleStart = askAngleStart10000th / 10000.0;
01775 double askAngleEnd = askAngleEnd10000th / 10000.0;
01776
01777 askAngleStart -= 90;
01778 askAngleEnd -= 90;
01779 this->config_.min_ang = askAngleStart / 180.0 * M_PI;
01780 this->config_.max_ang = askAngleEnd / 180.0 * M_PI;
01781 ros::NodeHandle nhPriv("~");
01782 nhPriv.setParam("min_ang",
01783 this->config_.min_ang);
01784 nhPriv.setParam("max_ang",
01785 this->config_.max_ang);
01786 ROS_INFO("MIN_ANG (after command verification): %8.3f [rad] %8.3f [deg]", config_.min_ang,
01787 rad2deg(this->config_.min_ang));
01788 ROS_INFO("MAX_ANG (after command verification): %8.3f [rad] %8.3f [deg]", config_.max_ang,
01789 rad2deg(this->config_.max_ang));
01790 }
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806 outputChannelFlagId = 0x00;
01807 for (int i = 0; i < outputChannelFlag.size(); i++)
01808 {
01809 outputChannelFlagId |= ((outputChannelFlag[i] == true) << i);
01810 }
01811 if (outputChannelFlagId < 1)
01812 {
01813 outputChannelFlagId = 1;
01814 }
01815 if (this->parser_->getCurrentParamPtr()->getScannerName().compare(SICK_SCANNER_LMS_5XX_NAME) == 0)
01816 {
01817 outputChannelFlagId = 1;
01818 ROS_INFO("LMS 5xx detected overwriting output channel flag ID");
01819
01820 ROS_INFO("LMS 5xx detected overwriting resolution flag (only 8 bit supported)");
01821 this->parser_->getCurrentParamPtr()->setIntensityResolutionIs16Bit(false);
01822 rssiResolutionIs16Bit = this->parser_->getCurrentParamPtr()->getIntensityResolutionIs16Bit();
01823 }
01824 if (this->parser_->getCurrentParamPtr()->getScannerName().compare(SICK_SCANNER_MRS_1XXX_NAME) == 0)
01825 {
01826 ROS_INFO("MRS 1xxx detected overwriting resolution flag (only 8 bit supported)");
01827 this->parser_->getCurrentParamPtr()->setIntensityResolutionIs16Bit(false);
01828 rssiResolutionIs16Bit = this->parser_->getCurrentParamPtr()->getIntensityResolutionIs16Bit();
01829
01830 }
01831
01832
01833 if ((this->parser_->getCurrentParamPtr()->getNumberOfLayers() == 1)
01834 || (this->parser_->getCurrentParamPtr()->getNumberOfLayers() == 4)
01835 || (this->parser_->getCurrentParamPtr()->getNumberOfLayers() == 24)
01836 )
01837 {
01838 char requestLMDscandatacfg[MAX_STR_LEN];
01839
01840
01841 const char *pcCmdMask = sopasCmdMaskVec[CMD_SET_PARTIAL_SCANDATA_CFG].c_str();
01842 sprintf(requestLMDscandatacfg, pcCmdMask, outputChannelFlagId, rssiFlag ? 1 : 0, rssiResolutionIs16Bit ? 1 : 0);
01843 if (useBinaryCmd)
01844 {
01845 std::vector<unsigned char> reqBinary;
01846 this->convertAscii2BinaryCmd(requestLMDscandatacfg, &reqBinary);
01847
01848
01849
01850
01851
01852 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_SET_PARTIAL_SCANDATA_CFG]);
01853 }
01854 else
01855 {
01856 std::vector<unsigned char> lmdScanDataCfgReply;
01857 result = sendSopasAndCheckAnswer(requestLMDscandatacfg, &lmdScanDataCfgReply);
01858 }
01859
01860
01861
01862 char requestLMDscandatacfgRead[MAX_STR_LEN];
01863
01864
01865 strcpy(requestLMDscandatacfgRead, sopasCmdVec[CMD_GET_PARTIAL_SCANDATA_CFG].c_str());
01866 if (useBinaryCmd)
01867 {
01868 std::vector<unsigned char> reqBinary;
01869 this->convertAscii2BinaryCmd(requestLMDscandatacfgRead, &reqBinary);
01870 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_GET_PARTIAL_SCANDATA_CFG]);
01871 }
01872 else
01873 {
01874 std::vector<unsigned char> lmdScanDataCfgReadReply;
01875 result = sendSopasAndCheckAnswer(requestLMDscandatacfgRead, &lmdScanDataCfgReadReply);
01876 }
01877
01878
01879 }
01880
01881
01882 double scan_freq=0;
01883 double ang_res=0;
01884 pn.getParam("scan_freq", scan_freq);
01885 pn.getParam("ang_res", ang_res);
01886 if (scan_freq!=0 || ang_res!=0)
01887 {
01888 if(scan_freq!=0 && ang_res!=0)
01889 {
01890 char requestLMDscancfg[MAX_STR_LEN];
01891
01892 const char *pcCmdMask = sopasCmdMaskVec[CMD_SET_PARTIAL_SCAN_CFG].c_str();
01893 sprintf(requestLMDscancfg, pcCmdMask, (long)(scan_freq*100+1e-9),(long)(ang_res*10000+1e-9));
01894 if (useBinaryCmd)
01895 {
01896 std::vector<unsigned char> reqBinary;
01897 this->convertAscii2BinaryCmd(requestLMDscancfg, &reqBinary);
01898 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_SET_PARTIAL_SCAN_CFG]);
01899 }
01900 else
01901 {
01902 std::vector<unsigned char> lmdScanCfgReply;
01903 result = sendSopasAndCheckAnswer(requestLMDscancfg, &lmdScanCfgReply);
01904 }
01905
01906
01907
01908 char requestLMDscancfgRead[MAX_STR_LEN];
01909
01910
01911 strcpy(requestLMDscancfgRead, sopasCmdVec[CMD_GET_PARTIAL_SCAN_CFG].c_str());
01912 if (useBinaryCmd)
01913 {
01914 std::vector<unsigned char> reqBinary;
01915 this->convertAscii2BinaryCmd(requestLMDscancfgRead, &reqBinary);
01916 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_GET_PARTIAL_SCAN_CFG]);
01917 }
01918 else
01919 {
01920 std::vector<unsigned char> lmdScanDataCfgReadReply;
01921 result = sendSopasAndCheckAnswer(requestLMDscancfgRead, &lmdScanDataCfgReadReply);
01922 }
01923
01924 }
01925 else
01926 {
01927 ROS_ERROR("ang_res and scan_freq have to be set, only one param is set skiping scan_fre/ang_res config");
01928 }
01929 }
01930
01931 if (this->parser_->getCurrentParamPtr()->getNumberOfLayers() >= 4)
01932 {
01933 char requestEchoSetting[MAX_STR_LEN];
01934 int filterEchoSetting = 0;
01935 pn.getParam("filter_echos", filterEchoSetting);
01936 if (filterEchoSetting < 0)
01937 { filterEchoSetting = 0; }
01938 if (filterEchoSetting > 2)
01939 { filterEchoSetting = 2; }
01940
01941 const char *pcCmdMask = sopasCmdMaskVec[CMD_SET_ECHO_FILTER].c_str();
01942
01943
01944
01945
01946
01947 sprintf(requestEchoSetting, pcCmdMask, filterEchoSetting);
01948 std::vector<unsigned char> outputFilterEchoRangeReply;
01949
01950
01951 if (useBinaryCmd)
01952 {
01953 std::vector<unsigned char> reqBinary;
01954 this->convertAscii2BinaryCmd(requestEchoSetting, &reqBinary);
01955 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_SET_ECHO_FILTER]);
01956 }
01957 else
01958 {
01959 result = sendSopasAndCheckAnswer(requestEchoSetting, &outputFilterEchoRangeReply);
01960 }
01961
01962 }
01963
01964
01965 }
01967
01968
01969
01970
01971
01972
01973
01974 std::vector<int> startProtocolSequence;
01975 bool deviceIsRadar = false;
01976 if (this->parser_->getCurrentParamPtr()->getDeviceIsRadar())
01977 {
01978 ros::NodeHandle tmpParam("~");
01979 bool transmitRawTargets = true;
01980 bool transmitObjects = true;
01981 int trackingMode = 0;
01982 std::string trackingModeDescription[] = {"BASIC", "VEHICLE"};
01983
01984 int numTrackingModes = sizeof(trackingModeDescription) / sizeof(trackingModeDescription[0]);
01985
01986 tmpParam.getParam("transmit_raw_targets", transmitRawTargets);
01987 tmpParam.getParam("transmit_objects", transmitObjects);
01988 tmpParam.getParam("tracking_mode", trackingMode);
01989
01990
01991 if ((trackingMode < 0) || (trackingMode >= numTrackingModes))
01992 {
01993 ROS_WARN("tracking mode id invalid. Switch to tracking mode 0");
01994 trackingMode = 0;
01995 }
01996 ROS_INFO("Raw target transmission is switched [%s]", transmitRawTargets ? "ON" : "OFF");
01997 ROS_INFO("Object transmission is switched [%s]", transmitObjects ? "ON" : "OFF");
01998 ROS_INFO("Tracking mode is set to id [%d] [%s]", trackingMode, trackingModeDescription[trackingMode].c_str());
01999
02000 deviceIsRadar = true;
02001
02002
02003 startProtocolSequence.push_back(CMD_DEVICE_TYPE);
02004 startProtocolSequence.push_back(CMD_SERIAL_NUMBER);
02005 startProtocolSequence.push_back(CMD_ORDER_NUMBER);
02006
02007
02008
02009
02010
02011
02012 if (transmitRawTargets)
02013 {
02014 startProtocolSequence.push_back(CMD_SET_TRANSMIT_RAWTARGETS_ON);
02015 }
02016 else
02017 {
02018 startProtocolSequence.push_back(CMD_SET_TRANSMIT_RAWTARGETS_OFF);
02019 }
02020
02021 if (transmitObjects)
02022 {
02023 startProtocolSequence.push_back(CMD_SET_TRANSMIT_OBJECTS_ON);
02024 }
02025 else
02026 {
02027 startProtocolSequence.push_back(CMD_SET_TRANSMIT_OBJECTS_OFF);
02028 }
02029
02030 switch (trackingMode)
02031 {
02032 case 0:
02033 startProtocolSequence.push_back(CMD_SET_TRACKING_MODE_0);
02034 break;
02035 case 1:
02036 startProtocolSequence.push_back(CMD_SET_TRACKING_MODE_1);
02037 break;
02038 default:
02039 ROS_DEBUG("Tracking mode switching sequence unknown\n");
02040 break;
02041
02042 }
02043
02044
02045
02046
02047 startProtocolSequence.push_back(CMD_RUN);
02048 startProtocolSequence.push_back(CMD_START_RADARDATA);
02049 }
02050 else
02051 {
02052
02053 startProtocolSequence.push_back(CMD_START_MEASUREMENT);
02054 startProtocolSequence.push_back(CMD_RUN);
02055 startProtocolSequence.push_back(CMD_START_SCANDATA);
02056 if (this->parser_->getCurrentParamPtr()->getNumberOfLayers() == 4)
02057 {
02058 ros::NodeHandle tmp("~");
02059 bool imu_enable = false;
02060 tmp.getParam("imu_enable", imu_enable);
02061 if (imu_enable)
02062 {
02063 if(useBinaryCmdNow==true)
02064 {
02065 ROS_INFO("Enable IMU data transfer");
02066
02067 startProtocolSequence.push_back(CMD_START_IMU_DATA);
02068 }
02069 else{
02070 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");
02071 exit(0);
02072 }
02073
02074 }
02075 }
02076 }
02077
02078 std::vector<int>::iterator it;
02079 for (it = startProtocolSequence.begin(); it != startProtocolSequence.end(); it++)
02080 {
02081 int cmdId = *it;
02082 std::vector<unsigned char> tmpReply;
02083
02084
02085 std::string sopasCmd = sopasCmdVec[cmdId];
02086 std::vector<unsigned char> replyDummy;
02087 std::vector<unsigned char> reqBinary;
02088 std::vector<unsigned char> sopasVec;
02089 sopasVec=stringToVector(sopasCmd);
02090 ROS_DEBUG("Command: %s", stripControl(sopasVec).c_str());
02091 if (useBinaryCmd)
02092 {
02093 this->convertAscii2BinaryCmd(sopasCmd.c_str(), &reqBinary);
02094 result = sendSopasAndCheckAnswer(reqBinary, &replyDummy, cmdId);
02095 sopasReplyBinVec[cmdId] = replyDummy;
02096
02097 switch (cmdId)
02098 {
02099 case CMD_START_SCANDATA:
02100
02101
02102 break;
02103 }
02104 }
02105 else
02106 {
02107 result = sendSopasAndCheckAnswer(sopasCmd.c_str(), &replyDummy, cmdId);
02108 }
02109
02110 if (result != 0)
02111 {
02112 ROS_ERROR("%s", sopasCmdErrMsg[cmdId].c_str());
02113 diagnostics_.broadcast(getDiagnosticErrorCode(), sopasCmdErrMsg[cmdId]);
02114 }
02115 else
02116 {
02117 sopasReplyStrVec[cmdId] = replyToString(replyDummy);
02118 }
02119
02120
02121 if (cmdId == CMD_START_RADARDATA)
02122 {
02123 ROS_DEBUG("Starting radar data ....\n");
02124 }
02125
02126
02127 if (cmdId == CMD_START_SCANDATA)
02128 {
02129 ROS_DEBUG("Starting scan data ....\n");
02130 }
02131
02132 if (cmdId == CMD_RUN)
02133 {
02134 bool waitForDeviceState = true;
02135 if (this->parser_->getCurrentParamPtr()->getNumberOfLayers() == 1)
02136 {
02137 waitForDeviceState = false;
02138 }
02139 if (this->parser_->getCurrentParamPtr()->getNumberOfLayers() == 24)
02140 {
02141 waitForDeviceState = false;
02142 }
02143
02144 if (waitForDeviceState)
02145 {
02146 int maxWaitForDeviceStateReady = 45;
02147 bool scannerReady = false;
02148 for (int i = 0; i < maxWaitForDeviceStateReady; i++)
02149 {
02150 double shortSleepTime = 1.0;
02151 std::string sopasCmd = sopasCmdVec[CMD_DEVICE_STATE];
02152 std::vector<unsigned char> replyDummy;
02153
02154 int iRetVal = 0;
02155 int deviceState = 0;
02156
02157 std::vector<unsigned char> reqBinary;
02158 std::vector<unsigned char> sopasVec;
02159 sopasVec=stringToVector(sopasCmd);
02160 ROS_DEBUG("Command: %s", stripControl(sopasVec).c_str());
02161 if (useBinaryCmd)
02162 {
02163 this->convertAscii2BinaryCmd(sopasCmd.c_str(), &reqBinary);
02164 result = sendSopasAndCheckAnswer(reqBinary, &replyDummy);
02165 sopasReplyBinVec[CMD_DEVICE_STATE] = replyDummy;
02166 }
02167 else
02168 {
02169 result = sendSopasAndCheckAnswer(sopasCmd.c_str(), &replyDummy);
02170 sopasReplyStrVec[CMD_DEVICE_STATE] = replyToString(replyDummy);
02171 }
02172
02173
02174 if (useBinaryCmd)
02175 {
02176 long dummy0, dummy1;
02177 dummy0 = 0;
02178 dummy1 = 0;
02179 deviceState = 0;
02180 iRetVal = binScanfVec(&(sopasReplyBinVec[CMD_DEVICE_STATE]), "%4y%4ysRA SCdevicestate %1y", &dummy0,
02181 &dummy1, &deviceState);
02182 }
02183 else
02184 {
02185 iRetVal = sscanf(sopasReplyStrVec[CMD_DEVICE_STATE].c_str(), "sRA SCdevicestate %d", &deviceState);
02186 }
02187 if (iRetVal > 0)
02188 {
02189 if (deviceState == 1)
02190 {
02191 scannerReady = true;
02192 ROS_INFO("Scanner ready for measurement after %d [sec]", i);
02193 break;
02194 }
02195 }
02196 ROS_INFO("Waiting for scanner ready state since %d secs", i);
02197 ros::Duration(shortSleepTime).sleep();
02198
02199 if (scannerReady)
02200 {
02201 break;
02202 }
02203 }
02204 }
02205 }
02206 tmpReply.clear();
02207
02208 }
02209 return ExitSuccess;
02210 }
02211
02212
02218 std::string sick_scan::SickScanCommon::replyToString(const std::vector<unsigned char> &reply)
02219 {
02220 std::string reply_str;
02221 std::vector<unsigned char>::const_iterator it_start, it_end;
02222 int binLen = this->checkForBinaryAnswer(&reply);
02223 if (binLen == -1)
02224 {
02225 it_start = reply.begin();
02226 it_end = reply.end();
02227 }
02228 else
02229 {
02230 it_start = reply.begin() + 8;
02231 it_end = reply.end() - 1;
02232 }
02233 bool inHexPrintMode = false;
02234 for (std::vector<unsigned char>::const_iterator it = it_start; it != it_end; it++)
02235 {
02236
02237
02238 if (*it >= 0x20 && (inHexPrintMode == false))
02239 {
02240 reply_str.push_back(*it);
02241 }
02242 else
02243 {
02244 if (binLen != -1)
02245 {
02246 char szTmp[255] = {0};
02247 unsigned char val = *it;
02248 inHexPrintMode = true;
02249 sprintf(szTmp, "\\x%02x", val);
02250 for (int ii = 0; ii < strlen(szTmp); ii++)
02251 {
02252 reply_str.push_back(szTmp[ii]);
02253 }
02254 }
02255 }
02256
02257 }
02258 return reply_str;
02259 }
02260
02261 bool sick_scan::SickScanCommon::dumpDatagramForDebugging(unsigned char *buffer, int bufLen)
02262 {
02263 bool ret = true;
02264 static int cnt = 0;
02265 char szDumpFileName[255] = {0};
02266 char szDir[255] = {0};
02267 if (cnt == 0)
02268 {
02269 ROS_INFO("Attention: verboseLevel is set to 1. Datagrams are stored in the /tmp folder.");
02270 }
02271 #ifdef _MSC_VER
02272 strcpy(szDir, "C:\\temp\\");
02273 #else
02274 strcpy(szDir, "/tmp/");
02275 #endif
02276 sprintf(szDumpFileName, "%ssick_datagram_%06d.bin", szDir, cnt);
02277 bool isBinary = this->parser_->getCurrentParamPtr()->getUseBinaryProtocol();
02278 if (isBinary)
02279 {
02280 FILE *ftmp;
02281 ftmp = fopen(szDumpFileName, "wb");
02282 if (ftmp != NULL)
02283 {
02284 fwrite(buffer, bufLen, 1, ftmp);
02285 fclose(ftmp);
02286 }
02287 }
02288 cnt++;
02289
02290 return (true);
02291
02292 }
02293
02294
02300 bool sick_scan::SickScanCommon::isCompatibleDevice(const std::string identStr) const
02301 {
02302 char device_string[7];
02303 int version_major = -1;
02304 int version_minor = -1;
02305
02306 strcpy(device_string, "???");
02307
02308 if (sscanf(identStr.c_str(), "sRA 0 6 %6s E V%d.%d", device_string,
02309 &version_major, &version_minor) == 3
02310 && strncmp("TiM3", device_string, 4) == 0
02311 && version_major >= 2 && version_minor >= 50)
02312 {
02313 ROS_ERROR("This scanner model/firmware combination does not support ranging output!");
02314 ROS_ERROR("Supported scanners: TiM5xx: all firmware versions; TiM3xx: firmware versions < V2.50.");
02315 ROS_ERROR("This is a %s, firmware version %d.%d", device_string, version_major, version_minor);
02316
02317 return false;
02318 }
02319
02320 bool supported = false;
02321
02322
02323 if (sscanf(identStr.c_str(), "sRA 0 6 %6s E V%d.%d", device_string, &version_major, &version_minor) == 3)
02324 {
02325 std::string devStr = device_string;
02326
02327
02328 if (devStr.compare(0, 4, "TiM5") == 0)
02329 {
02330 supported = true;
02331 }
02332
02333 if (supported == true)
02334 {
02335 ROS_INFO("Device %s V%d.%d found and supported by this driver.", identStr.c_str(), version_major,
02336 version_minor);
02337 }
02338
02339 }
02340
02341 if ((identStr.find("MRS1xxx") !=
02342 std::string::npos)
02343 || (identStr.find("LMS1xxx") != std::string::npos)
02344 )
02345 {
02346 ROS_INFO("Deviceinfo %s found and supported by this driver.", identStr.c_str());
02347 supported = true;
02348 }
02349
02350
02351 if (identStr.find("MRS6") !=
02352 std::string::npos)
02353 {
02354 ROS_INFO("Deviceinfo %s found and supported by this driver.", identStr.c_str());
02355 supported = true;
02356 }
02357
02358 if (identStr.find("RMS3xx") !=
02359 std::string::npos)
02360 {
02361 ROS_INFO("Deviceinfo %s found and supported by this driver.", identStr.c_str());
02362 supported = true;
02363 }
02364
02365
02366 if (supported == false)
02367 {
02368 ROS_WARN("Device %s V%d.%d found and maybe unsupported by this driver.", device_string, version_major,
02369 version_minor);
02370 ROS_WARN("Full SOPAS answer: %s", identStr.c_str());
02371 }
02372 return true;
02373 }
02374
02375
02380 int SickScanCommon::loopOnce()
02381 {
02382 static int cnt = 0;
02383 diagnostics_.update();
02384
02385 unsigned char receiveBuffer[65536];
02386 int actual_length = 0;
02387 static unsigned int iteration_count = 0;
02388 bool useBinaryProtocol = this->parser_->getCurrentParamPtr()->getUseBinaryProtocol();
02389
02390 ros::Time recvTimeStamp = ros::Time::now();
02391
02392 ros::Time recvTimeStampPush = ros::Time::now();
02393
02394
02395
02396
02397
02398
02399
02400
02401 int packetsInLoop = 0;
02402
02403 const int maxNumAllowedPacketsToProcess = 25;
02404
02405 int numPacketsProcessed = 0;
02406
02407 static bool firstTimeCalled = true;
02408 static bool dumpData = false;
02409 static int verboseLevel = 0;
02410 static bool slamBundle = false;
02411 float timeIncrement;
02412 static std::string echoForSlam = "";
02413 if (firstTimeCalled == true)
02414 {
02415
02416
02417 ros::NodeHandle tmpParam("~");
02418 tmpParam.getParam("slam_echo", echoForSlam);
02419 tmpParam.getParam("slam_bundle", slamBundle);
02420 tmpParam.getParam("verboseLevel", verboseLevel);
02421 firstTimeCalled = false;
02422 }
02423 do
02424 {
02425
02426 int result = get_datagram(recvTimeStamp, receiveBuffer, 65536, &actual_length, useBinaryProtocol, &packetsInLoop);
02427 numPacketsProcessed++;
02428
02429 ros::Duration dur = recvTimeStampPush - recvTimeStamp;
02430
02431 if (result != 0)
02432 {
02433 ROS_ERROR("Read Error when getting datagram: %i.", result);
02434 diagnostics_.broadcast(getDiagnosticErrorCode(), "Read Error when getting datagram.");
02435 return ExitError;
02436 }
02437 if (actual_length <= 0)
02438 {
02439 return ExitSuccess;
02440 }
02441
02442
02443 if (iteration_count++ % (config_.skip + 1) != 0)
02444 return ExitSuccess;
02445
02446 if (publish_datagram_)
02447 {
02448 std_msgs::String datagram_msg;
02449 datagram_msg.data = std::string(reinterpret_cast<char *>(receiveBuffer));
02450 datagram_pub_.publish(datagram_msg);
02451 }
02452
02453
02454 if (verboseLevel > 0)
02455 {
02456 dumpDatagramForDebugging(receiveBuffer, actual_length);
02457 }
02458
02459
02460 bool deviceIsRadar = false;
02461
02462 if (this->parser_->getCurrentParamPtr()->getDeviceIsRadar() == true)
02463 {
02464 deviceIsRadar = true;
02465 }
02466
02467 if (true == deviceIsRadar)
02468 {
02469 SickScanRadar radar(this);
02470 int errorCode = ExitSuccess;
02471
02472 errorCode = radar.parseDatagram(recvTimeStamp, (unsigned char *) receiveBuffer, actual_length,
02473 useBinaryProtocol);
02474 return errorCode;
02475 }
02476
02477 static SickScanImu scanImu(this);
02478 if (scanImu.isImuDatagram((char *) receiveBuffer, actual_length))
02479 {
02480 int errorCode = ExitSuccess;
02481 if (scanImu.isImuAckDatagram((char *) receiveBuffer, actual_length))
02482 {
02483
02484 }
02485 else
02486 {
02487
02488 errorCode = scanImu.parseDatagram(recvTimeStamp, (unsigned char *) receiveBuffer, actual_length,
02489 useBinaryProtocol);
02490
02491 }
02492 return errorCode;
02493
02494
02495 }
02496 else
02497 {
02498
02499 sensor_msgs::LaserScan msg;
02500
02501 msg.header.stamp = recvTimeStamp;
02502 double elevationAngleInRad = 0.0;
02503
02504
02505
02506 char *buffer_pos = (char *) receiveBuffer;
02507 char *dstart, *dend;
02508 bool dumpDbg = true;
02509 bool dataToProcess = true;
02510 std::vector<float> vang_vec;
02511 vang_vec.clear();
02512 while (dataToProcess)
02513 {
02514 const int maxAllowedEchos = 5;
02515
02516 int numValidEchos = 0;
02517 int aiValidEchoIdx[maxAllowedEchos] = {0};
02518 size_t dlength;
02519 int success = -1;
02520 int numEchos = 0;
02521 int echoMask = 0;
02522 bool publishPointCloud = true;
02523
02524 if (useBinaryProtocol)
02525 {
02526
02527 std::vector<unsigned char> receiveBufferVec = std::vector<unsigned char>(receiveBuffer,
02528 receiveBuffer + actual_length);
02529 #ifdef DEBUG_DUMP_TO_CONSOLE_ENABLED
02530 if (actual_length > 1000)
02531 {
02532 DataDumper::instance().dumpUcharBufferToConsole(receiveBuffer, actual_length);
02533
02534 }
02535
02536 DataDumper::instance().dumpUcharBufferToConsole(receiveBuffer, actual_length);
02537 #endif
02538 if (receiveBufferVec.size() > 8)
02539 {
02540 long idVal = 0;
02541 long lenVal = 0;
02542 memcpy(&idVal, receiveBuffer + 0, 4);
02543 memcpy(&lenVal, receiveBuffer + 4, 4);
02544 swap_endian((unsigned char *) &lenVal, 4);
02545
02546 if (idVal == 0x02020202)
02547 {
02548 #if 0
02549 {
02550 static int cnt = 0;
02551 char szFileName[255];
02552
02553 #ifdef _MSC_VER
02554 sprintf(szFileName, "c:\\temp\\dump%05d.bin", cnt);
02555 #else
02556 sprintf(szFileName, "/tmp/dump%05d.txt", cnt);
02557 #endif
02558 FILE *fout;
02559 fout = fopen(szFileName, "wb");
02560 fwrite(receiveBuffer, actual_length, 1, fout);
02561 fclose(fout);
02562 cnt++;
02563 }
02564 #endif
02565
02566 if (lenVal < actual_length)
02567 {
02568 short elevAngleX200 = 0;
02569
02570 int scanFrequencyX100 = 0;
02571 double elevAngle = 0.00;
02572 double scanFrequency = 0.0;
02573 long measurementFrequencyDiv100 = 0;
02574 int numberOf16BitChannels = 0;
02575 int numberOf8BitChannels = 0;
02576 uint32_t SystemCountScan=0;
02577 uint32_t SystemCountTransmit=0;
02578
02579 memcpy(&elevAngleX200, receiveBuffer + 50, 2);
02580 swap_endian((unsigned char *) &elevAngleX200, 2);
02581
02582 elevationAngleInRad = -elevAngleX200 / 200.0 * deg2rad_const;
02583
02584 msg.header.seq = elevAngleX200;
02585
02586 memcpy(&SystemCountScan, receiveBuffer + 0x26, 4);
02587 swap_endian((unsigned char *) &SystemCountScan, 4);
02588
02589 memcpy(&SystemCountTransmit, receiveBuffer + 0x2A, 4);
02590 swap_endian((unsigned char *) &SystemCountTransmit, 4);
02591 bool bRet = SoftwarePLL::instance().updatePLL(recvTimeStamp.sec, recvTimeStamp.nsec,SystemCountTransmit);
02592 ros::Time tmp_time=recvTimeStamp;
02593 bRet = SoftwarePLL::instance().getCorrectedTimeStamp(recvTimeStamp.sec, recvTimeStamp.nsec,SystemCountScan);
02594
02595 ros::Duration debug_duration=recvTimeStamp-tmp_time;
02596 #ifdef DEBUG_DUMP_ENABLED
02597 double elevationAngleInDeg=elevationAngleInRad = -elevAngleX200 / 200.0;
02598
02599
02600
02601
02602 #endif
02603
02604 memcpy(&scanFrequencyX100, receiveBuffer + 52, 4);
02605 swap_endian((unsigned char *) &scanFrequencyX100, 4);
02606
02607 memcpy(&measurementFrequencyDiv100, receiveBuffer + 56, 4);
02608 swap_endian((unsigned char *) &measurementFrequencyDiv100, 4);
02609
02610
02611 msg.scan_time = 1.0 / (scanFrequencyX100 / 100.0);
02612
02613
02614 if(measurementFrequencyDiv100>10000)
02615 {
02616 measurementFrequencyDiv100/=100;
02617 }
02618 msg.time_increment = 1.0 / (measurementFrequencyDiv100 * 100.0);
02619 timeIncrement=msg.time_increment;
02620 msg.range_min = parser_->get_range_min();
02621 msg.range_max = parser_->get_range_max();
02622
02623 memcpy(&numberOf16BitChannels, receiveBuffer + 62, 2);
02624 swap_endian((unsigned char *) &numberOf16BitChannels, 2);
02625
02626 int parseOff = 64;
02627
02628
02629 char szChannel[255] = {0};
02630 float scaleFactor = 1.0;
02631 float scaleFactorOffset = 0.0;
02632 int32_t startAngleDiv10000 = 1;
02633 int32_t sizeOfSingleAngularStepDiv10000 = 1;
02634 double startAngle = 0.0;
02635 double sizeOfSingleAngularStep = 0.0;
02636 short numberOfItems = 0;
02637
02638 static int cnt = 0;
02639 cnt++;
02640
02641
02642 for (int i = 0; i < numberOf16BitChannels; i++)
02643 {
02644 int numberOfItems = 0x00;
02645 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
02646 swap_endian((unsigned char *) &numberOfItems, 2);
02647 parseOff += 21;
02648 parseOff += numberOfItems * 2;
02649 }
02650
02651
02652 memcpy(&numberOf8BitChannels, receiveBuffer + parseOff, 2);
02653 swap_endian((unsigned char *) &numberOf8BitChannels, 2);
02654
02655 parseOff = 64;
02656 enum datagram_parse_task
02657 {
02658 process_dist,
02659 process_vang,
02660 process_rssi,
02661 process_idle
02662 };
02663 for (int processLoop = 0; processLoop < 2; processLoop++)
02664 {
02665 int totalChannelCnt = 0;
02666 int distChannelCnt;
02667 int rssiCnt;
02668 bool bCont = true;
02669 int vangleCnt;
02670 datagram_parse_task task = process_idle;
02671 bool parsePacket = true;
02672 parseOff = 64;
02673 bool processData = false;
02674
02675 if (processLoop == 0)
02676 {
02677 distChannelCnt = 0;
02678 rssiCnt = 0;
02679 vangleCnt = 0;
02680 }
02681
02682 if (processLoop == 1)
02683 {
02684 processData = true;
02685 numEchos = distChannelCnt;
02686 msg.ranges.resize(numberOfItems * numEchos);
02687 if (rssiCnt > 0)
02688 {
02689 msg.intensities.resize(numberOfItems * rssiCnt);
02690 }
02691 else
02692 {
02693 }
02694 if (vangleCnt > 0)
02695 {
02696 vang_vec.resize(numberOfItems * vangleCnt);
02697 }
02698 else
02699 {
02700 vang_vec.clear();
02701 }
02702 echoMask = (1 << numEchos) - 1;
02703
02704
02705 distChannelCnt = 0;
02706 rssiCnt = 0;
02707 vangleCnt = 0;
02708
02709 }
02710
02711 szChannel[6] = '\0';
02712 scaleFactor = 1.0;
02713 scaleFactorOffset = 0.0;
02714 startAngleDiv10000 = 1;
02715 sizeOfSingleAngularStepDiv10000 = 1;
02716 startAngle = 0.0;
02717 sizeOfSingleAngularStep = 0.0;
02718 numberOfItems = 0;
02719
02720
02721 #if 1 // prepared for multiecho parsing
02722
02723 bCont = true;
02724 bool doVangVecProc = false;
02725
02726 task = process_idle;
02727 do
02728 {
02729 task = process_idle;
02730 doVangVecProc = false;
02731 int processDataLenValuesInBytes = 2;
02732
02733 if (totalChannelCnt == numberOf16BitChannels)
02734 {
02735 parseOff += 2;
02736 }
02737
02738 if (totalChannelCnt >= numberOf16BitChannels)
02739 {
02740 processDataLenValuesInBytes = 1;
02741 }
02742 bCont = false;
02743 strcpy(szChannel, "");
02744
02745 if (totalChannelCnt < (numberOf16BitChannels + numberOf8BitChannels))
02746 {
02747 szChannel[5] = '\0';
02748 strncpy(szChannel, (const char *) receiveBuffer + parseOff, 5);
02749 }
02750 else
02751 {
02752
02753 }
02754
02755 if (strstr(szChannel, "DIST") == szChannel)
02756 {
02757 task = process_dist;
02758 distChannelCnt++;
02759 bCont = true;
02760 numberOfItems = 0;
02761 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
02762 swap_endian((unsigned char *) &numberOfItems, 2);
02763
02764 }
02765 if (strstr(szChannel, "VANG") == szChannel)
02766 {
02767 vangleCnt++;
02768 task = process_vang;
02769 bCont = true;
02770 numberOfItems = 0;
02771 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
02772 swap_endian((unsigned char *) &numberOfItems, 2);
02773
02774 vang_vec.resize(numberOfItems);
02775
02776 }
02777 if (strstr(szChannel, "RSSI") == szChannel)
02778 {
02779 task = process_rssi;
02780 rssiCnt++;
02781 bCont = true;
02782 numberOfItems = 0;
02783
02784 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
02785 swap_endian((unsigned char *) &numberOfItems, 2);
02786
02787 }
02788 if (bCont)
02789 {
02790 scaleFactor = 0.0;
02791 scaleFactorOffset = 0.0;
02792 startAngleDiv10000 = 0;
02793 sizeOfSingleAngularStepDiv10000 = 0;
02794 numberOfItems = 0;
02795
02796 memcpy(&scaleFactor, receiveBuffer + parseOff + 5, 4);
02797 memcpy(&scaleFactorOffset, receiveBuffer + parseOff + 9, 4);
02798 memcpy(&startAngleDiv10000, receiveBuffer + parseOff + 13, 4);
02799 memcpy(&sizeOfSingleAngularStepDiv10000, receiveBuffer + parseOff + 17, 2);
02800 memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
02801
02802
02803 swap_endian((unsigned char *) &scaleFactor, 4);
02804 swap_endian((unsigned char *) &scaleFactorOffset, 4);
02805 swap_endian((unsigned char *) &startAngleDiv10000, 4);
02806 swap_endian((unsigned char *) &sizeOfSingleAngularStepDiv10000, 2);
02807 swap_endian((unsigned char *) &numberOfItems, 2);
02808
02809 if (processData)
02810 {
02811 unsigned short *data = (unsigned short *) (receiveBuffer + parseOff + 21);
02812
02813 unsigned char *swapPtr = (unsigned char *) data;
02814
02815 for (int i = 0;
02816 i < numberOfItems * processDataLenValuesInBytes; i += processDataLenValuesInBytes)
02817 {
02818 if (processDataLenValuesInBytes == 1)
02819 {
02820 }
02821 else
02822 {
02823 unsigned char tmp;
02824 tmp = swapPtr[i + 1];
02825 swapPtr[i + 1] = swapPtr[i];
02826 swapPtr[i] = tmp;
02827 }
02828 }
02829 int idx = 0;
02830
02831 switch (task)
02832 {
02833
02834 case process_dist:
02835 {
02836 startAngle = startAngleDiv10000 / 10000.00;
02837 sizeOfSingleAngularStep = sizeOfSingleAngularStepDiv10000 / 10000.0;
02838 sizeOfSingleAngularStep *= (M_PI / 180.0);
02839
02840 msg.angle_min = startAngle / 180.0 * M_PI - M_PI / 2;
02841 msg.angle_increment = sizeOfSingleAngularStep;
02842 msg.angle_max = msg.angle_min + (numberOfItems - 1) * msg.angle_increment;
02843
02844 float *rangePtr = NULL;
02845
02846 if (numberOfItems > 0)
02847 {
02848 rangePtr = &msg.ranges[0];
02849 }
02850 float scaleFactor_001= 0.001F * scaleFactor;
02851 for (int i = 0; i < numberOfItems; i++)
02852 {
02853 idx = i + numberOfItems * (distChannelCnt - 1);
02854 rangePtr[idx] = (float) data[i] * scaleFactor_001 + scaleFactorOffset;
02855 #ifdef DEBUG_DUMP_ENABLED
02856 if (distChannelCnt == 1)
02857 {
02858 if (i == floor(numberOfItems / 2))
02859 {
02860 double curTimeStamp = SystemCountScan + i * msg.time_increment * 1E6;
02861
02862 }
02863 }
02864 #endif
02865
02866 }
02867
02868 }
02869 break;
02870 case process_rssi:
02871 {
02872
02873
02874 float *intensityPtr = NULL;
02875
02876 if (numberOfItems > 0)
02877 {
02878 intensityPtr = &msg.intensities[0];
02879
02880 }
02881 for (int i = 0; i < numberOfItems; i++)
02882 {
02883 idx = i + numberOfItems * (rssiCnt - 1);
02884
02885 float rssiVal = 0.0;
02886 if (processDataLenValuesInBytes == 2)
02887 {
02888 rssiVal = (float) data[i];
02889 }
02890 else
02891 {
02892 unsigned char *data8Ptr = (unsigned char *) data;
02893 rssiVal = (float) data8Ptr[i];
02894 }
02895 intensityPtr[idx] = rssiVal * scaleFactor + scaleFactorOffset;
02896 }
02897 }
02898 break;
02899
02900 case process_vang:
02901 float *vangPtr = NULL;
02902 if (numberOfItems > 0)
02903 {
02904 vangPtr = &vang_vec[0];
02905 }
02906 for (int i = 0; i < numberOfItems; i++)
02907 {
02908 vangPtr[i] = (float) data[i] * scaleFactor + scaleFactorOffset;
02909 }
02910 break;
02911 }
02912 }
02913 parseOff += 21 + processDataLenValuesInBytes * numberOfItems;
02914
02915
02916 }
02917 totalChannelCnt++;
02918 } while (bCont);
02919 }
02920 #endif
02921
02922 elevAngle = elevAngleX200 / 200.0;
02923 scanFrequency = scanFrequencyX100 / 100.0;
02924
02925
02926 }
02927 }
02928 }
02929
02930
02931 parser_->checkScanTiming(msg.time_increment, msg.scan_time, msg.angle_increment, 0.00001f);
02932
02933 success = ExitSuccess;
02934
02935 dataToProcess = false;
02936 }
02937 else
02938 {
02939 dstart = strchr(buffer_pos, 0x02);
02940 if (dstart != NULL)
02941 {
02942 dend = strchr(dstart + 1, 0x03);
02943 }
02944 if ((dstart != NULL) && (dend != NULL))
02945 {
02946 dataToProcess = true;
02947 dlength = dend - dstart;
02948 *dend = '\0';
02949 dstart++;
02950 }
02951 else
02952 {
02953 dataToProcess = false;
02954 break;
02955 }
02956
02957 if (dumpDbg)
02958 {
02959 {
02960 static int cnt = 0;
02961 char szFileName[255];
02962
02963 #ifdef _MSC_VER
02964 sprintf(szFileName, "c:\\temp\\dump%05d.txt", cnt);
02965 #else
02966 sprintf(szFileName, "/tmp/dump%05d.txt", cnt);
02967 #endif
02968 FILE *fout;
02969 fout = fopen(szFileName, "wb");
02970 fwrite(dstart, dlength, 1, fout);
02971 fclose(fout);
02972 cnt++;
02973 }
02974 }
02975
02976
02977
02978
02979 numEchos = 1;
02980
02981
02982 success = parser_->parse_datagram(dstart, dlength, config_, msg, numEchos, echoMask);
02983 publishPointCloud = true;
02984
02985 numValidEchos = 0;
02986 for (int i = 0; i < maxAllowedEchos; i++)
02987 {
02988 aiValidEchoIdx[i] = 0;
02989 }
02990 }
02991
02992
02993 int numOfLayers = parser_->getCurrentParamPtr()->getNumberOfLayers();
02994
02995 if (success == ExitSuccess)
02996 {
02997 bool elevationPreCalculated = false;
02998 double elevationAngleDegree = 0.0;
02999
03000
03001 std::vector<float> rangeTmp = msg.ranges;
03002 std::vector<float> intensityTmp = msg.intensities;
03003
03004 int intensityTmpNum = intensityTmp.size();
03005 float *intensityTmpPtr = NULL;
03006 if (intensityTmpNum > 0)
03007 {
03008 intensityTmpPtr = &intensityTmp[0];
03009 }
03010
03011
03012
03013
03014 int layer = 0;
03015 int baseLayer = 0;
03016 bool useGivenElevationAngle = false;
03017 switch (numOfLayers)
03018 {
03019 case 1:
03020 baseLayer = 0;
03021 break;
03022 case 4:
03023
03024 baseLayer = -1;
03025 if (msg.header.seq == 250) layer = -1;
03026 else if (msg.header.seq == 0) layer = 0;
03027 else if (msg.header.seq == -250) layer = 1;
03028 else if (msg.header.seq == -500) layer = 2;
03029 elevationAngleDegree = this->parser_->getCurrentParamPtr()->getElevationDegreeResolution();
03030 elevationAngleDegree = elevationAngleDegree / 180.0 * M_PI;
03031
03032 break;
03033 case 24:
03034 baseLayer = -1;
03035 layer = (msg.header.seq - (-2638)) / 125;
03036 layer = (23 - layer) - 1;
03037 #if 0
03038 elevationAngleDegree = this->parser_->getCurrentParamPtr()->getElevationDegreeResolution();
03039 elevationAngleDegree = elevationAngleDegree / 180.0 * M_PI;
03040 #endif
03041
03042 elevationPreCalculated = true;
03043 if (vang_vec.size() > 0)
03044 {
03045 useGivenElevationAngle = true;
03046 }
03047 break;
03048 default:
03049 assert(0);
03050 break;
03051
03052 }
03053
03054
03055
03056
03057
03058
03059 if (numEchos > 5)
03060 {
03061 ROS_WARN("Too much echos");
03062 }
03063 else
03064 {
03065
03066 int startOffset = 0;
03067 int endOffset = 0;
03068 int echoPartNum = msg.ranges.size() / numEchos;
03069 for (int i = 0; i < numEchos; i++)
03070 {
03071
03072 bool sendMsg = false;
03073 if ((echoMask & (1 << i)) & outputChannelFlagId)
03074 {
03075 aiValidEchoIdx[numValidEchos] = i;
03076 numValidEchos++;
03077 sendMsg = true;
03078 }
03079 startOffset = i * echoPartNum;
03080 endOffset = (i + 1) * echoPartNum;
03081
03082 msg.ranges.clear();
03083 msg.intensities.clear();
03084 msg.ranges = std::vector<float>(
03085 rangeTmp.begin() + startOffset,
03086 rangeTmp.begin() + endOffset);
03087
03088 if (endOffset <= intensityTmp.size() && (intensityTmp.size() > 0))
03089 {
03090 msg.intensities = std::vector<float>(
03091 intensityTmp.begin() + startOffset,
03092 intensityTmp.begin() + endOffset);
03093 }
03094 else
03095 {
03096 msg.intensities.resize(echoPartNum);
03097 }
03098 {
03099
03100 char szTmp[255] = {0};
03101 if (this->parser_->getCurrentParamPtr()->getNumberOfLayers() > 1)
03102 {
03103 const char *cpFrameId = config_.frame_id.c_str();
03104 #if 0
03105 sprintf(szTmp, "%s_%+04d_DIST%d", cpFrameId, msg.header.seq, i + 1);
03106 #else // experimental
03107 char szSignName[10] = {0};
03108 if ((int) msg.header.seq < 0)
03109 {
03110 strcpy(szSignName, "NEG");
03111 }
03112 else
03113 {
03114 strcpy(szSignName, "POS");
03115
03116 }
03117
03118 sprintf(szTmp, "%s_%s_%03d_DIST%d", cpFrameId, szSignName, abs((int) msg.header.seq), i + 1);
03119 #endif
03120 }
03121 else
03122 {
03123 strcpy(szTmp, config_.frame_id.c_str());
03124 }
03125
03126 msg.header.frame_id = std::string(szTmp);
03127
03128 if (echoForSlam.length() > 0)
03129 {
03130 if (slamBundle)
03131 {
03132
03133 if (i == 0)
03134 {
03135
03136 msg.header.frame_id = echoForSlam;
03137 strcpy(szTmp, echoForSlam.c_str());
03138 if (elevationAngleInRad != 0.0)
03139 {
03140 float cosVal = cos(elevationAngleInRad);
03141 int rangeNum = msg.ranges.size();
03142 for (int j = 0; j < rangeNum; j++)
03143 {
03144 msg.ranges[j] *= cosVal;
03145 }
03146 }
03147 }
03148 }
03149
03150 if (echoForSlam.compare(szTmp) == 0)
03151 {
03152 sendMsg = true;
03153 }
03154 else
03155 {
03156 sendMsg = false;
03157 }
03158 }
03159
03160 }
03161 #ifndef _MSC_VER
03162 if (numOfLayers > 4)
03163 {
03164 sendMsg = false;
03165 }
03166 if (sendMsg &
03167 outputChannelFlagId)
03168 {
03169
03170 pub_.publish(msg);
03171 }
03172 #else
03173 printf("MSG received...");
03174 #endif
03175 }
03176 }
03177
03178
03179
03180 if (publishPointCloud == true)
03181 {
03182
03183
03184
03185 const int numChannels = 4;
03186
03187 int numTmpLayer = numOfLayers;
03188
03189
03190 cloud_.header.stamp = recvTimeStamp;
03191 cloud_.header.frame_id = config_.frame_id;
03192 cloud_.header.seq = 0;
03193 cloud_.height = numTmpLayer * numValidEchos;
03194 cloud_.width = msg.ranges.size();
03195 cloud_.is_bigendian = false;
03196 cloud_.is_dense = true;
03197 cloud_.point_step = numChannels * sizeof(float);
03198 cloud_.row_step = cloud_.point_step * cloud_.width;
03199 cloud_.fields.resize(numChannels);
03200 for (int i = 0; i < numChannels; i++)
03201 {
03202 std::string channelId[] = {"x", "y", "z", "intensity"};
03203 cloud_.fields[i].name = channelId[i];
03204 cloud_.fields[i].offset = i * sizeof(float);
03205 cloud_.fields[i].count = 1;
03206 cloud_.fields[i].datatype = sensor_msgs::PointField::FLOAT32;
03207 }
03208
03209 cloud_.data.resize(cloud_.row_step * cloud_.height);
03210
03211 unsigned char *cloudDataPtr = &(cloud_.data[0]);
03212
03213
03214
03215
03216 std::vector<float> cosAlphaTable;
03217 std::vector<float> sinAlphaTable;
03218 int rangeNum = rangeTmp.size() / numValidEchos;
03219 cosAlphaTable.resize(rangeNum);
03220 sinAlphaTable.resize(rangeNum);
03221
03222 for (size_t iEcho = 0; iEcho < numValidEchos; iEcho++)
03223 {
03224
03225 float angle = config_.min_ang;
03226
03227
03228 float *cosAlphaTablePtr = &cosAlphaTable[0];
03229 float *sinAlphaTablePtr = &sinAlphaTable[0];
03230
03231 float *vangPtr = &vang_vec[0];
03232 float *rangeTmpPtr = &rangeTmp[0];
03233 for (size_t i = 0; i < rangeNum; i++)
03234 {
03235 enum enum_index_descr
03236 {
03237 idx_x,
03238 idx_y,
03239 idx_z,
03240 idx_intensity,
03241 idx_num
03242 };
03243 long adroff = i * (numChannels * (int) sizeof(float));
03244
03245 adroff += (layer - baseLayer) * cloud_.row_step;
03246
03247 adroff += iEcho * cloud_.row_step * numTmpLayer;
03248
03249 unsigned char *ptr = cloudDataPtr + adroff;
03250 float *fptr = (float *)(cloudDataPtr + adroff);
03251
03252 geometry_msgs::Point32 point;
03253 float range_meter = rangeTmpPtr[iEcho * rangeNum + i];
03254 float phi = angle;
03255 float alpha = 0.0;
03256
03257 if (useGivenElevationAngle)
03258 {
03259 alpha = -vangPtr[i] * deg2rad_const;
03260 }
03261 else
03262 {
03263 if (elevationPreCalculated)
03264 {
03265 alpha = elevationAngleInRad;
03266 }
03267 else
03268 {
03269 alpha = layer * elevationAngleDegree;
03270 }
03271 }
03272
03273 if (iEcho == 0)
03274 {
03275 cosAlphaTablePtr[i] = cos(alpha);
03276 sinAlphaTablePtr[i] = sin(alpha);
03277 }
03278 else
03279 {
03280
03281 }
03282
03283 float rangeCos=range_meter * cosAlphaTablePtr[i];
03284 fptr[idx_x] = rangeCos * cos(phi);
03285 fptr[idx_y] = rangeCos * sin(phi);
03286 fptr[idx_z] = range_meter * sinAlphaTablePtr[i];
03287
03288 fptr[idx_intensity] = 0.0;
03289 if (config_.intensity)
03290 {
03291 int intensityIndex = aiValidEchoIdx[iEcho] * rangeNum + i;
03292
03293 if (intensityIndex < intensityTmpNum)
03294 {
03295 fptr[idx_intensity] = intensityTmpPtr[intensityIndex];
03296 }
03297 }
03298 angle += msg.angle_increment;
03299 }
03300
03301 static int cnt = 0;
03302 int layerOff = (layer - baseLayer);
03303
03304 }
03305
03306 bool shallIFire = false;
03307 if ((msg.header.seq == 0) || (msg.header.seq == 237))
03308 {
03309 shallIFire = true;
03310 }
03311
03312
03313 static int layerCnt = 0;
03314 static int layerSeq[4];
03315
03316 if (config_.cloud_output_mode>0)
03317 {
03318
03319 layerSeq[layerCnt % 4] = layer;
03320 if (layerCnt >= 4)
03321 {
03322 shallIFire = true;
03323 }
03324 else
03325 {
03326 shallIFire = false;
03327 }
03328
03329 layerCnt++;
03330 }
03331
03332 if (shallIFire)
03333 {
03334 if (config_.cloud_output_mode==0)
03335 {
03336
03337 cloud_pub_.publish(cloud_);
03338
03339 }
03340 else if(config_.cloud_output_mode==2)
03341 {
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351 #ifndef _MSC_VER
03352 int numTotalShots = 360;
03353 int numPartialShots = 40;
03354
03355 for (int i = 0; i < numTotalShots; i += numPartialShots)
03356 {
03357 sensor_msgs::PointCloud2 partialCloud;
03358 partialCloud = cloud_;
03359 ros::Time partialTimeStamp = cloud_.header.stamp;
03360
03361 partialTimeStamp += ros::Duration((i + 0.5 * (numPartialShots - 1)) * timeIncrement);
03362 partialTimeStamp += ros::Duration((3 * numTotalShots) * timeIncrement);
03363 partialCloud.header.stamp = partialTimeStamp;
03364 partialCloud.width = numPartialShots * 3;
03365
03366 int diffTo1100 = cloud_.width - 3 * (numTotalShots + i);
03367 if (diffTo1100 > numPartialShots)
03368 {
03369 diffTo1100 = numPartialShots;
03370 }
03371 if (diffTo1100 < 0)
03372 {
03373 diffTo1100 = 0;
03374 }
03375 partialCloud.width += diffTo1100;
03376
03377 partialCloud.height = 1;
03378
03379
03380 partialCloud.is_bigendian = false;
03381 partialCloud.is_dense = true;
03382 partialCloud.point_step = numChannels * sizeof(float);
03383 partialCloud.row_step = partialCloud.point_step * partialCloud.width;
03384 partialCloud.fields.resize(numChannels);
03385 for (int ii = 0; ii < numChannels; ii++)
03386 {
03387 std::string channelId[] = {"x", "y", "z", "intensity"};
03388 partialCloud.fields[ii].name = channelId[ii];
03389 partialCloud.fields[ii].offset = ii * sizeof(float);
03390 partialCloud.fields[ii].count = 1;
03391 partialCloud.fields[ii].datatype = sensor_msgs::PointField::FLOAT32;
03392 }
03393
03394 partialCloud.data.resize(partialCloud.row_step);
03395
03396 int partOff = 0;
03397 for (int j = 0; j < 4; j++)
03398 {
03399 int layerIdx = (j + (layerCnt)) % 4;
03400 int rowIdx = 1 + layerSeq[layerIdx % 4];
03401 int colIdx = j * numTotalShots + i;
03402 int maxAvail = cloud_.width - colIdx;
03403 if (maxAvail < 0)
03404 {
03405 maxAvail = 0;
03406 }
03407
03408 if (maxAvail > numPartialShots)
03409 {
03410 maxAvail = numPartialShots;
03411 }
03412
03413
03414 if (maxAvail > 0)
03415 {
03416 memcpy(&(partialCloud.data[partOff]),
03417 &(cloud_.data[(rowIdx * cloud_.width + colIdx + i) * cloud_.point_step]),
03418 cloud_.point_step * maxAvail);
03419
03420 }
03421
03422 partOff += maxAvail * partialCloud.point_step;
03423 }
03424 assert(partialCloud.data.size()==partialCloud.width*partialCloud.point_step);
03425
03426
03427 cloud_pub_.publish(partialCloud);
03428 #if 0
03429 memcpy(&(partialCloud.data[0]), &(cloud_.data[0]) + i * cloud_.point_step, cloud_.point_step * numPartialShots);
03430 cloud_pub_.publish(partialCloud);
03431 #endif
03432 }
03433 }
03434
03435
03436 #else
03437 printf("PUBLISH:\n");
03438 #endif
03439 }
03440 }
03441 }
03442
03443 buffer_pos = dend + 1;
03444 }
03445 }
03446
03447
03448
03449 } while ( (packetsInLoop > 0) && (numPacketsProcessed < maxNumAllowedPacketsToProcess) );
03450 return ExitSuccess;
03451 }
03452
03453
03457 void SickScanCommon::check_angle_range(SickScanConfig &conf)
03458 {
03459 if (conf.min_ang > conf.max_ang)
03460 {
03461 ROS_WARN("Maximum angle must be greater than minimum angle. Adjusting >min_ang<.");
03462 conf.min_ang = conf.max_ang;
03463 }
03464 }
03465
03471 void SickScanCommon::update_config(sick_scan::SickScanConfig &new_config, uint32_t level)
03472 {
03473 check_angle_range(new_config);
03474 config_ = new_config;
03475 }
03476
03483 int SickScanCommon::convertAscii2BinaryCmd(const char *requestAscii, std::vector<unsigned char> *requestBinary)
03484 {
03485 requestBinary->clear();
03486 if (requestAscii == NULL)
03487 {
03488 return (-1);
03489 }
03490 int cmdLen = strlen(requestAscii);
03491 if (cmdLen == 0)
03492 {
03493 return (-1);
03494 }
03495 if (requestAscii[0] != 0x02)
03496 {
03497 return (-1);
03498 }
03499 if (requestAscii[cmdLen - 1] != 0x03)
03500 {
03501 return (-1);
03502 }
03503
03504 for (int i = 0; i < 4; i++)
03505 {
03506 requestBinary->push_back(0x02);
03507 }
03508
03509 for (int i = 0; i < 4; i++)
03510 {
03511 requestBinary->push_back(0x00);
03512 }
03513
03514 unsigned long msgLen = cmdLen - 2;
03515
03516
03517
03518 std::string keyWord0 = "sMN SetAccessMode";
03519 std::string keyWord1 = "sWN FREchoFilter";
03520 std::string keyWord2 = "sEN LMDscandata";
03521 std::string keyWord3 = "sWN LMDscandatacfg";
03522 std::string keyWord4 = "sWN SetActiveApplications";
03523 std::string keyWord5 = "sEN IMUData";
03524 std::string keyWord6 = "sWN EIIpAddr";
03525 std::string keyWord7 = "sMN mLMPsetscancfg";
03526 std::string keyWord8 = "sWN TSCTCupdatetime";
03527 std::string keyWord9 = "sWN TSCTCSrvAddr";
03528
03529
03530 std::string cmdAscii = requestAscii;
03531
03532
03533 int copyUntilSpaceCnt = 2;
03534 int spaceCnt = 0;
03535 char hexStr[255] = {0};
03536 int level = 0;
03537 unsigned char buffer[255];
03538 int bufferLen = 0;
03539 if (cmdAscii.find(keyWord0) != std::string::npos)
03540 {
03541 copyUntilSpaceCnt = 2;
03542 int keyWord0Len = keyWord0.length();
03543 sscanf(requestAscii + keyWord0Len + 1, " %d %s", &level, hexStr);
03544 buffer[0] = (unsigned char) (0xFF & level);
03545 bufferLen = 1;
03546 char hexTmp[3] = {0};
03547 for (int i = 0; i < 4; i++)
03548 {
03549 int val;
03550 hexTmp[0] = hexStr[i * 2];
03551 hexTmp[1] = hexStr[i * 2 + 1];
03552 hexTmp[2] = 0x00;
03553 sscanf(hexTmp, "%x", &val);
03554 buffer[i + 1] = (unsigned char) (0xFF & val);
03555 bufferLen++;
03556 }
03557 }
03558 if (cmdAscii.find(keyWord1) != std::string::npos)
03559 {
03560 int echoCodeNumber = 0;
03561 int keyWord1Len = keyWord1.length();
03562 sscanf(requestAscii + keyWord1Len + 1, " %d", &echoCodeNumber);
03563 buffer[0] = (unsigned char) (0xFF & echoCodeNumber);
03564 bufferLen = 1;
03565 }
03566 if (cmdAscii.find(keyWord2) != std::string::npos)
03567 {
03568 int scanDataStatus = 0;
03569 int keyWord2Len = keyWord2.length();
03570 sscanf(requestAscii + keyWord2Len + 1, " %d", &scanDataStatus);
03571 buffer[0] = (unsigned char) (0xFF & scanDataStatus);
03572 bufferLen = 1;
03573 }
03574
03575 if (cmdAscii.find(keyWord3) != std::string::npos)
03576 {
03577 int scanDataStatus = 0;
03578 int keyWord3Len = keyWord3.length();
03579 int dummyArr[12] = {0};
03580 if (12 == sscanf(requestAscii + keyWord3Len + 1, " %d %d %d %d %d %d %d %d %d %d %d %d",
03581 &dummyArr[0], &dummyArr[1], &dummyArr[2],
03582 &dummyArr[3], &dummyArr[4], &dummyArr[5],
03583 &dummyArr[6], &dummyArr[7], &dummyArr[8],
03584 &dummyArr[9], &dummyArr[10], &dummyArr[11]))
03585 {
03586 for (int i = 0; i < 13; i++)
03587 {
03588 buffer[i] = 0x00;
03589 }
03590 buffer[0] = (unsigned char) (0xFF & (dummyArr[0]));
03591 buffer[1] = 0x00;
03592 buffer[2] = (unsigned char) (0xFF & dummyArr[2]);
03593 buffer[3] = (unsigned char) (0xFF & dummyArr[3]);
03594 buffer[10]= (unsigned char) (0xFF & dummyArr[10]);
03595 buffer[12] = (unsigned char) (0xFF & (dummyArr[11]));
03596
03597 bufferLen = 13;
03598 }
03599
03600 }
03601
03602 if (cmdAscii.find(keyWord4) != std::string::npos)
03603 {
03604 char tmpStr[1024] = {0};
03605 char szApplStr[255] = {0};
03606 int keyWord4Len = keyWord4.length();
03607 int scanDataStatus = 0;
03608 int dummy0, dummy1;
03609 strcpy(tmpStr, requestAscii + keyWord4Len + 2);
03610 sscanf(tmpStr, "%d %s %d", &dummy0, szApplStr, &dummy1);
03611
03612 buffer[0] = 0x00;
03613 buffer[1] = dummy0 ? 0x01 : 0x00;
03614 for (int ii = 0; ii < 4; ii++)
03615 {
03616 buffer[2 + ii] = szApplStr[ii];
03617 }
03618 buffer[6] = dummy1 ? 0x01 : 0x00;
03619 bufferLen = 7;
03620 }
03621
03622 if (cmdAscii.find(keyWord5) != std::string::npos)
03623 {
03624 int imuSetStatus = 0;
03625 int keyWord5Len = keyWord5.length();
03626 sscanf(requestAscii + keyWord5Len + 1, " %d", &imuSetStatus);
03627 buffer[0] = (unsigned char) (0xFF & imuSetStatus);
03628 bufferLen = 1;
03629 }
03630
03631 if (cmdAscii.find(keyWord6) != std::string::npos)
03632 {
03633 int adrPartArr[4];
03634 int imuSetStatus = 0;
03635 int keyWord6Len = keyWord6.length();
03636 sscanf(requestAscii + keyWord6Len + 1, " %x %x %x %x", &(adrPartArr[0]), &(adrPartArr[1]), &(adrPartArr[2]),
03637 &(adrPartArr[3]));
03638 buffer[0] = (unsigned char) (0xFF & adrPartArr[0]);
03639 buffer[1] = (unsigned char) (0xFF & adrPartArr[1]);
03640 buffer[2] = (unsigned char) (0xFF & adrPartArr[2]);
03641 buffer[3] = (unsigned char) (0xFF & adrPartArr[3]);
03642 bufferLen = 4;
03643 }
03644
03645
03646
03647
03648
03649
03650
03651
03652 if (cmdAscii.find(keyWord7) != std::string::npos)
03653 {
03654 bufferLen = 18;
03655 for(int i=0;i<bufferLen;i++)
03656 {
03657 unsigned char uch=0x00;
03658 switch (i)
03659 {
03660 case 5:
03661 uch=0x01;break;
03662 }
03663 buffer[i]=uch;
03664 }
03665 char tmpStr[1024] = {0};
03666 char szApplStr[255] = {0};
03667 int keyWord7Len = keyWord7.length();
03668 int scanDataStatus = 0;
03669 int dummy0, dummy1;
03670 strcpy(tmpStr, requestAscii + keyWord7Len + 2);
03671 sscanf(tmpStr, "%d 1 %d", &dummy0, &dummy1);
03672
03673 buffer[0] = (unsigned char)(0xFF & (dummy0 >> 24));
03674 buffer[1] = (unsigned char)(0xFF & (dummy0 >> 16));
03675 buffer[2] = (unsigned char)(0xFF & (dummy0 >> 8));
03676 buffer[3] = (unsigned char)(0xFF & (dummy0 >> 0));
03677
03678
03679 buffer[6] = (unsigned char)(0xFF & (dummy1 >> 24));
03680 buffer[7] = (unsigned char)(0xFF & (dummy1 >> 16));
03681 buffer[8] = (unsigned char)(0xFF & (dummy1 >> 8));
03682 buffer[9] = (unsigned char)(0xFF & (dummy1 >> 0));
03683
03684
03685 }
03686 if (cmdAscii.find(keyWord8) != std::string::npos)
03687 {
03688 uint32_t updatetime = 0;
03689 int keyWord8Len = keyWord8.length();
03690 sscanf(requestAscii + keyWord8Len + 1, " %d", &updatetime);
03691 buffer[0] = (unsigned char)(0xFF & (updatetime >> 24));
03692 buffer[1] = (unsigned char)(0xFF & (updatetime >> 16));
03693 buffer[2] = (unsigned char)(0xFF & (updatetime >> 8));
03694 buffer[3] = (unsigned char)(0xFF & (updatetime >> 0));
03695 bufferLen = 4;
03696 }
03697 if (cmdAscii.find(keyWord9) != std::string::npos)
03698 {
03699 int adrPartArr[4];
03700 int imuSetStatus = 0;
03701 int keyWord9Len = keyWord9.length();
03702 sscanf(requestAscii + keyWord9Len + 1, " %x %x %x %x", &(adrPartArr[0]), &(adrPartArr[1]), &(adrPartArr[2]),
03703 &(adrPartArr[3]));
03704 buffer[0] = (unsigned char) (0xFF & adrPartArr[0]);
03705 buffer[1] = (unsigned char) (0xFF & adrPartArr[1]);
03706 buffer[2] = (unsigned char) (0xFF & adrPartArr[2]);
03707 buffer[3] = (unsigned char) (0xFF & adrPartArr[3]);
03708 bufferLen = 4;
03709 }
03710
03711 bool switchDoBinaryData = false;
03712 for (int i = 1; i <= (int) (msgLen); i++)
03713 {
03714 char c = requestAscii[i];
03715 if (switchDoBinaryData == true)
03716 {
03717 if (0 == bufferLen)
03718 {
03719 if (c >= '0' && c <= '9')
03720 {
03721 c -= '0';
03722 }
03723 }
03724 else
03725 {
03726 break;
03727 }
03728 }
03729 requestBinary->push_back(c);
03730 if (requestAscii[i] == 0x20)
03731 {
03732 spaceCnt++;
03733 if (spaceCnt >= copyUntilSpaceCnt)
03734 {
03735 switchDoBinaryData = true;
03736 }
03737 }
03738
03739 }
03740
03741
03742 for (int i = 0; i < bufferLen; i++)
03743 {
03744 requestBinary->push_back(buffer[i]);
03745 }
03746
03747 msgLen = requestBinary->size();
03748 msgLen -= 8;
03749 for (int i = 0; i < 4; i++)
03750 {
03751 unsigned char bigEndianLen = msgLen & (0xFF << (3 - i) * 8);
03752 (*requestBinary)[i + 4] = ((unsigned char) (bigEndianLen));
03753 }
03754 unsigned char xorVal = 0x00;
03755 xorVal = sick_crc8((unsigned char *) (&((*requestBinary)[8])), requestBinary->size() - 8);
03756 requestBinary->push_back(xorVal);
03757 #if 0
03758 for (int i = 0; i < requestBinary->size(); i++)
03759 {
03760 unsigned char c = (*requestBinary)[i];
03761 printf("[%c]%02x ", (c < ' ') ? '.' : c, c) ;
03762 }
03763 printf("\n");
03764 #endif
03765 return (0);
03766
03767 };
03768
03769
03776 bool SickScanCommon::checkForProtocolChangeAndMaybeReconnect(bool &useBinaryCmdNow)
03777 {
03778 bool retValue = true;
03779 bool shouldUseBinary = this->parser_->getCurrentParamPtr()->getUseBinaryProtocol();
03780 if (shouldUseBinary == useBinaryCmdNow)
03781 {
03782 retValue = true;
03783 }
03784 else
03785 {
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796 if (shouldUseBinary == true)
03797 {
03798 this->setProtocolType(CoLa_B);
03799 }
03800 else
03801 {
03802 this->setProtocolType(CoLa_A);
03803 }
03804
03805 useBinaryCmdNow = shouldUseBinary;
03806 retValue = false;
03807 }
03808 return (retValue);
03809 }
03810
03811
03812 bool SickScanCommon::setNewIpAddress(boost::asio::ip::address_v4 ipNewIPAddr, bool useBinaryCmd)
03813 {
03814 int eepwritetTimeOut =1;
03815 char szCmd[255];
03816 bool result = false;
03817
03818
03819 unsigned long adrBytesLong[4];
03820 std::string s = ipNewIPAddr.to_string();
03821 const char *ptr = s.c_str();
03822
03823 sscanf(ptr,"%lu.%lu.%lu.%lu", &(adrBytesLong[0]), &(adrBytesLong[1]), &(adrBytesLong[2]), &(adrBytesLong[3]));
03824
03825
03826 unsigned char ipbytearray[4];
03827 for (int i = 0; i < 4; i++)
03828 {
03829 ipbytearray[i] = adrBytesLong[i] & 0xFF;
03830 }
03831
03832
03833 char ipcommand[255];
03834 const char *pcCmdMask = sopasCmdMaskVec[CMD_SET_IP_ADDR].c_str();
03835 sprintf(ipcommand, pcCmdMask, ipbytearray[0], ipbytearray[1], ipbytearray[2], ipbytearray[3]);
03836 if (useBinaryCmd)
03837 {
03838 std::vector<unsigned char> reqBinary;
03839 this->convertAscii2BinaryCmd(ipcommand, &reqBinary);
03840 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_SET_IP_ADDR]);
03841 reqBinary.clear();
03842 this->convertAscii2BinaryCmd(sopasCmdVec[CMD_WRITE_EEPROM].c_str(), &reqBinary);
03843 result &= sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_WRITE_EEPROM]);
03844 reqBinary.clear();
03845 this->convertAscii2BinaryCmd(sopasCmdVec[CMD_RUN].c_str(), &reqBinary);
03846 result &= sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_RUN]);
03847 reqBinary.clear();
03848 this->convertAscii2BinaryCmd(sopasCmdVec[CMD_SET_ACCESS_MODE_3].c_str(), &reqBinary);
03849 result &= sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_SET_ACCESS_MODE_3]);
03850 reqBinary.clear();
03851 this->convertAscii2BinaryCmd(sopasCmdVec[CMD_REBOOT].c_str(), &reqBinary);
03852 result &= sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_REBOOT]);
03853 }
03854 else
03855 {
03856 std::vector<unsigned char> ipcomandReply;
03857 std::vector<unsigned char> resetReply;
03858 std::string runCmd = sopasCmdVec[CMD_RUN];
03859 std::string restartCmd = sopasCmdVec[CMD_REBOOT];
03860 std::string EEPCmd = sopasCmdVec[CMD_WRITE_EEPROM];
03861 std::string UserLvlCmd = sopasCmdVec[CMD_SET_ACCESS_MODE_3];
03862 result = sendSopasAndCheckAnswer(ipcommand, &ipcomandReply);
03863 result &= sendSopasAndCheckAnswer(EEPCmd, &resetReply);
03864 result &= sendSopasAndCheckAnswer(runCmd, &resetReply);
03865 result &= sendSopasAndCheckAnswer(UserLvlCmd, &resetReply);
03866 result &= sendSopasAndCheckAnswer(restartCmd, &resetReply);
03867 }
03868 return (result);
03869 }
03870
03871 bool SickScanCommon::setNTPServerAndStart(boost::asio::ip::address_v4 ipNewIPAddr, bool useBinaryCmd)
03872 {
03873 char szCmd[255];
03874 bool result = false;
03875
03876
03877 unsigned long adrBytesLong[4];
03878 std::string s = ipNewIPAddr.to_string();
03879 const char *ptr = s.c_str();
03880
03881 sscanf(ptr,"%lu.%lu.%lu.%lu", &(adrBytesLong[0]), &(adrBytesLong[1]), &(adrBytesLong[2]), &(adrBytesLong[3]));
03882
03883
03884 unsigned char ipbytearray[4];
03885 for (int i = 0; i < 4; i++)
03886 {
03887 ipbytearray[i] = adrBytesLong[i] & 0xFF;
03888 }
03889
03890
03891 char ntpipcommand[255];
03892 char ntpupdatetimecommand[255];
03893 const char *pcCmdMask = sopasCmdMaskVec[CMD_SET_NTP_SERVER_IP_ADDR].c_str();
03894 sprintf(ntpipcommand, pcCmdMask, ipbytearray[0], ipbytearray[1], ipbytearray[2], ipbytearray[3]);
03895
03896 const char *pcCmdMaskUpdatetime = sopasCmdMaskVec[CMD_SET_NTP_UPDATETIME].c_str();
03897 sprintf(ntpupdatetimecommand, pcCmdMaskUpdatetime, 5);
03898 std::vector<unsigned char> outputFilterntpupdatetimecommand;
03899
03900 if (useBinaryCmd)
03901 {
03902 std::vector<unsigned char> reqBinary;
03903 this->convertAscii2BinaryCmd(sopasCmdVec[CMD_SET_NTP_INTERFACE_ETH].c_str(), &reqBinary);
03904 result &= sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_SET_NTP_INTERFACE_ETH]);
03905 reqBinary.clear();
03906 this->convertAscii2BinaryCmd(ntpipcommand, &reqBinary);
03907 result = sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_SET_NTP_SERVER_IP_ADDR]);
03908 reqBinary.clear();
03909 this->convertAscii2BinaryCmd(ntpupdatetimecommand, &reqBinary);
03910 result &= sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_SET_NTP_UPDATETIME]);
03911 reqBinary.clear();
03912 this->convertAscii2BinaryCmd(sopasCmdVec[CMD_ACTIVATE_NTP_CLIENT].c_str(), &reqBinary);
03913 result &= sendSopasAndCheckAnswer(reqBinary, &sopasReplyBinVec[CMD_ACTIVATE_NTP_CLIENT]);
03914 reqBinary.clear();
03915
03916 }
03917 else
03918 {
03919 std::vector<unsigned char> ipcomandReply;
03920 std::vector<unsigned char> resetReply;
03921 std::string ntpInterFaceETHCmd = sopasCmdVec[CMD_SET_NTP_INTERFACE_ETH];
03922 std::string activateNTPCmd = sopasCmdVec[CMD_ACTIVATE_NTP_CLIENT];
03923 result &= sendSopasAndCheckAnswer(ntpInterFaceETHCmd , &resetReply);
03924 result = sendSopasAndCheckAnswer(ntpipcommand, &ipcomandReply);
03925 result &= sendSopasAndCheckAnswer(activateNTPCmd, &resetReply);
03926 result &= sendSopasAndCheckAnswer(ntpupdatetimecommand, &outputFilterntpupdatetimecommand);
03927 }
03928 return (result);
03929 }
03930
03931 void SickScanCommon::setSensorIsRadar(bool _isRadar)
03932 {
03933 sensorIsRadar = _isRadar;
03934 }
03935
03936 bool SickScanCommon::getSensorIsRadar(void)
03937 {
03938 return (sensorIsRadar);
03939 }
03940
03941
03942
03943 }
03944
03945
03946