64 #pragma warning(disable: 4996)
65 #pragma warning(disable: 4267)
71 #if defined LDMRS_SUPPORT && LDMRS_SUPPORT > 0
74 #if defined SCANSEGMENT_XD_SUPPORT && SCANSEGMENT_XD_SUPPORT > 0
85 #if __ROS_VERSION != 1 // launchparser for native Windows/Linux and ROS-2
86 #define USE_LAUNCHPARSER // settings and parameter by LaunchParser
89 #define _USE_MATH_DEFINES
98 #define GITHASH_STR (strlen(GITHASH)>2?(std::string(" githash:")+std::string(GITHASH)):(std::string("")))
100 #define GITHASH_STR std::string("")
103 #define GITINFO_STR (strlen(GITINFO)>2?(std::string(" gitinfo:")+std::string(GITINFO)):(std::string("")))
105 #define GITINFO_STR std::string("")
108 #define DELETE_PTR(p) if(p){delete(p);p=0;}
170 bool getTagVal(std::string tagVal, std::string &tag, std::string &val)
174 pos = tagVal.find(
":=");
177 if (pos == std::string::npos)
183 tag = tagVal.substr(0, pos);
184 val = tagVal.substr(pos + 2);
215 ROS_INFO_STREAM(
"You are leaving the following version of this node:\n");
218 ROS_INFO_STREAM(
"sick_generic_laser: stop and exit (line " << __LINE__ <<
")");
219 std::this_thread::sleep_for(std::chrono::milliseconds(100));
222 std::this_thread::sleep_for(std::chrono::milliseconds(100));
223 std::cout <<
"sick_generic_laser: exit (line " << __LINE__ <<
")" << std::endl;
225 std::cout <<
"sick_generic_laser: exit (line " << __LINE__ <<
")" << std::endl;
236 std::string sopas_request = sopas_ascii_request;
237 std::vector<unsigned char> sopas_response_raw;
240 if (sopas_ascii_request[0] != 0x02)
242 sopas_request.clear();
243 sopas_request.push_back((
char)0x02);
244 sopas_request.insert(sopas_request.end(), sopas_ascii_request.begin(), sopas_ascii_request.end());
245 sopas_request.push_back((
char)0x03);
250 ROS_INFO_STREAM(
"convertSendSOPASCommand(): sopas_request = \"" << sopas_ascii_request <<
"\", sopas_response = \"" <<
sopas_response <<
"\"\n");
255 ROS_WARN_STREAM(
"## WARNING in convertSendSOPASCommand(\"" << sopas_ascii_request <<
"\"): SickScanCommon::convertSendSOPASCommand() failed.\n");
260 #if defined SCANSEGMENT_XD_SUPPORT && SCANSEGMENT_XD_SUPPORT > 0
266 ROS_INFO_STREAM(
"convertSendSOPASCommand(): sopas_request = \"" << sopas_ascii_request <<
"\", sopas_response = \"" <<
sopas_response <<
"\"\n");
271 ROS_WARN_STREAM(
"## WARNING in convertSendSOPASCommand(\"" << sopas_ascii_request <<
"\"): SickScanServices::sendSopasAndCheckAnswer() failed.\n");
275 ROS_WARN_STREAM(
"## WARNING in convertSendSOPASCommand(\"" << sopas_ascii_request <<
"\") failed: scanner not initialized\n");
283 std::size_t
length = std::max<size_t>((
size_t)1024, 2 * strlen(format));
284 std::vector<char> temp;
286 for (
int cnt = 0; temp.size() <=
length && cnt < 10; cnt++)
289 va_start(
args, format);
291 std::size_t required_length = _vsnprintf_s(temp.data(), temp.size(), _TRUNCATE, format,
args);
293 std::size_t required_length = std::vsnprintf(temp.data(), temp.size(), format,
args);
298 return std::string {temp.data(),
length};
304 static bool status_first_time =
true;
308 if (notify_status_update)
310 status_first_time =
false;
334 inline bool ends_with(std::string
const &value, std::string
const &ending)
336 if (ending.size() > value.size())
338 return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
356 int launchArgcFileIdx = -1;
357 for (
int n = 1; n < argc; n++)
359 std::string extKey =
".launch";
360 std::string argv_str = argv[n];
363 launchArgcFileIdx = n;
364 std::vector<std::string> tagList, typeList, valList;
366 bool ret = launchParser.
parseFile(argv_str, tagList, typeList, valList);
369 ROS_INFO_STREAM(
"Cannot parse launch file (check existence and content): >>>" << argv_str <<
"<<<\n");
372 for (
size_t i = 0; i < tagList.size(); i++)
374 printf(
"%-30s %-10s %-20s\n", tagList[i].c_str(), typeList[i].c_str(), valList[i].c_str());
375 if(typeList[i] ==
"bool" && !valList[i].empty())
376 rosSetParam(nhPriv, tagList[i], (
bool)(valList[i][0] ==
'1' || valList[i][0] ==
't' || valList[i][0] ==
'T'));
377 else if(typeList[i] ==
"int" && !valList[i].empty())
378 rosSetParam(nhPriv, tagList[i], (
int)std::stoi(valList[i]));
379 else if(typeList[i] ==
"float" && !valList[i].empty())
380 rosSetParam(nhPriv, tagList[i], (
float)std::stof(valList[i]));
381 else if(typeList[i] ==
"double" && !valList[i].empty())
382 rosSetParam(nhPriv, tagList[i], (
double)std::stod(valList[i]));
389 for (
int n = 1; n < argc; n++)
391 std::string argv_str = argv[n];
394 if (argv_str ==
"--ros-args") {
404 if (launchArgcFileIdx != n)
406 ROS_ERROR_STREAM(
"## ERROR parseLaunchfileSetParameter(): Tag-Value setting not valid. Use pattern: <tag>:=<value> (e.g. hostname:=192.168.0.4) (Check the entry: " << argv_str <<
")\n");
429 bool doInternalDebug =
false;
430 bool emulSensor =
false;
431 for (
int i = 0; i < argc; i++)
433 std::string argv_str = argv[i];
436 if (tag.compare(
"__internalDebug") == 0)
439 sscanf(val.c_str(),
"%d", &debugState);
442 doInternalDebug =
true;
445 if (tag.compare(
"__emulSensor") == 0)
448 sscanf(val.c_str(),
"%d", &dummyState);
457 #ifdef USE_LAUNCHPARSER
460 ROS_ERROR_STREAM(
"## ERROR sick_generic_laser: parseLaunchfileSetParameter() failed, aborting\n");
466 std::string scannerName;
469 if (
false ==
rosGetParam(nhPriv,
"scanner_type", scannerName) || scannerName.empty())
471 ROS_ERROR_STREAM(
"cannot find parameter ""scanner_type"" in the param set. Please specify scanner_type.");
473 scannerName = nodeName;
476 std::string cloud_topic =
"cloud";
484 nhPriv->
setParam(
"name", scannerName);
498 std::string hostname;
503 bool changeIP =
false;
506 if (
rosGetParam(nhPriv,
"new_IP_address", sNewIp) && !sNewIp.empty())
510 std::string port =
"2112";
518 bool subscribe_datagram =
false;
520 rosGetParam(nhPriv,
"subscribe_datagram", subscribe_datagram);
522 int device_number = 0;
524 rosGetParam(nhPriv,
"device_number", device_number);
526 std::string frame_id =
"cloud";
531 if(scannerName ==
"sick_ldmrs")
533 #if defined LDMRS_SUPPORT && LDMRS_SUPPORT > 0
535 sick_scan_xd::SickLdmrsNode ldmrs;
536 exit_code = ldmrs.init(nhPriv, hostname, frame_id);
539 ROS_ERROR(
"LDMRS initialization failed.");
554 ROS_ERROR(
"LDMRS not supported. Please build sick_scan_xd with option LDMRS_SUPPORT");
564 int tick_to_timestamp_mode = 0;
565 rosDeclareParam(nhPriv,
"tick_to_timestamp_mode", tick_to_timestamp_mode);
566 rosGetParam(nhPriv,
"tick_to_timestamp_mode", tick_to_timestamp_mode);
575 #if defined SCANSEGMENT_XD_SUPPORT && SCANSEGMENT_XD_SUPPORT > 0
577 std::cout <<
"sick_generic_laser: sick_scansegment_xd finished with " << (exit_code ==
sick_scan_xd::ExitSuccess ?
"success" :
"ERROR") << std::endl;
581 ROS_ERROR_STREAM(
"SCANSEGMENT_XD_SUPPORT deactivated, " << scannerName <<
" not supported. Please build sick_scan_xd with option SCANSEGMENT_XD_SUPPORT");
590 char colaDialectId =
'A';
604 int range_filter_handling =
parser->get_range_filter_config();
605 rosDeclareParam(nhPriv,
"range_filter_handling", range_filter_handling);
606 if (
rosGetParam(nhPriv,
"range_filter_handling", range_filter_handling))
612 float time_increment =
parser->get_time_increment();
614 if (
rosGetParam(nhPriv,
"time_increment", time_increment))
616 parser->set_time_increment(time_increment);
622 bool use_binary_protocol =
true;
624 if (
true ==
rosGetParam(nhPriv,
"emul_sensor", emulSensor))
626 ROS_INFO_STREAM(
"Found emul_sensor overwriting default settings. Emulation:" << (emulSensor ?
"True" :
"False"));
629 if (
true ==
rosGetParam(nhPriv,
"use_binary_protocol", use_binary_protocol))
631 ROS_INFO(
"Found sopas_protocol_type param overwriting default protocol:");
632 if (use_binary_protocol ==
true)
634 ROS_INFO(
"Binary protocol activated");
638 if (
parser->getCurrentParamPtr()->getNumberOfLayers() > 4)
641 use_binary_protocol =
true;
642 ROS_WARN(
"This scanner type does not support ASCII communication.\n"
643 "Binary communication has been activated.\n"
644 "The parameter \"sopas_protocol_type\" has been set to \"True\".");
648 ROS_INFO(
"ASCII protocol activated");
651 parser->getCurrentParamPtr()->setUseBinaryProtocol(use_binary_protocol);
655 if (
parser->getCurrentParamPtr()->getUseBinaryProtocol())
666 bool message_monitoring_enabled =
true;
670 rosDeclareParam(nhPriv,
"message_monitoring_enabled", message_monitoring_enabled);
671 rosGetParam(nhPriv,
"message_monitoring_enabled", message_monitoring_enabled);
672 rosDeclareParam(nhPriv,
"read_timeout_millisec_default", read_timeout_millisec_default);
673 rosGetParam(nhPriv,
"read_timeout_millisec_default", read_timeout_millisec_default);
674 rosDeclareParam(nhPriv,
"read_timeout_millisec_startup", read_timeout_millisec_startup);
675 rosGetParam(nhPriv,
"read_timeout_millisec_startup", read_timeout_millisec_startup);
676 rosDeclareParam(nhPriv,
"read_timeout_millisec_kill_node", read_timeout_millisec_kill_node);
677 rosGetParam(nhPriv,
"read_timeout_millisec_kill_node", read_timeout_millisec_kill_node);
678 int message_monitoring_read_timeout_millisec = read_timeout_millisec_default;
679 if(message_monitoring_enabled)
682 #if __ROS_VERSION > 0 // point cloud monitoring in Linux-ROS
683 if (read_timeout_millisec_kill_node > 0)
686 bool pointcloud_monitor_started = pointcloud_monitor->
startPointCloudMonitoring(nhPriv, read_timeout_millisec_kill_node, cloud_topic);
687 ROS_INFO_STREAM(
"PointCloudMonitor" << (pointcloud_monitor_started?
" ":
" NOT ") <<
"started.");
691 ROS_INFO_STREAM(
"PointCloudMonitor deactivated due to configuration read_timeout_millisec_kill_node=" << read_timeout_millisec_kill_node <<
", pointcloud will not be monitored for timeout errors.");
696 bool start_services =
true;
714 ROS_INFO_STREAM(
"Start initialising scanner [Ip: " << hostname <<
"] [Port:" << port <<
"]");
723 ROS_ERROR(
"TCP is not switched on. Probably hostname or port not set. Use roslaunch to start node.");
734 ROS_ERROR(
"## ERROR in mainGenericLaser: init failed, retrying...");
740 rosGetParam(nhPriv,
"start_services", start_services);
741 if (
true == start_services)
744 ROS_INFO(
"SickScanServices: ros services initialized");
761 #if __ROS_VERSION > 0
762 ROS_INFO_STREAM(
"Setup completed, sick_scan_xd is up and running. Pointcloud is published on topic \"" << cloud_topic <<
"\"");
764 ROS_INFO(
"Setup completed, sick_scan_xd is up and running.");
784 if(scan_msg_monitor && message_monitoring_enabled)
794 ROS_ERROR(
"## ERROR in sick_generic_laser main loop: read timeout, scanner re-init failed");
809 ROS_ERROR(
"Invalid run state in main loop");
813 printf(
"sick_generic_laser: leaving main loop...");
817 if(pointcloud_monitor)
888 nav_msg.vel_x = src_msg->
vel_x;
889 nav_msg.vel_y = src_msg->
vel_y;
890 nav_msg.omega = src_msg->
omega;
903 nav_msg.vel_x = src_msg->
vel_x;
904 nav_msg.vel_y = src_msg->
vel_y;
907 nav_msg.omega = src_msg->
omega;
908 nav_msg.coordbase = 0;
915 ROS_WARN_STREAM(
"## ERROR SickScanCommon::messageCbRosOdom(): SoftwarePLL not yet ready, timestamp can not be converted from system time to lidar time, odometry message ignored.");