36 #include "sensor_msgs/LaserScan.h"
37 #include "std_srvs/Empty.h"
41 #define _countof(_Array) (int)(sizeof(_Array) / sizeof(_Array[0]))
44 #define DEG2RAD(x) ((x)*M_PI/180.)
45 #define RESET_TIMEOUT 15 // 15 second
59 double scan_time,
bool inverted,
60 float angle_min,
float angle_max,
64 static int scan_count = 0;
65 sensor_msgs::LaserScan scan_msg;
67 scan_msg.header.stamp =
start;
68 scan_msg.header.frame_id = frame_id;
71 bool reversed = (angle_max > angle_min);
73 scan_msg.angle_min = M_PI - angle_max;
74 scan_msg.angle_max = M_PI - angle_min;
76 scan_msg.angle_min = M_PI - angle_min;
77 scan_msg.angle_max = M_PI - angle_max;
79 scan_msg.angle_increment =
80 (scan_msg.angle_max - scan_msg.angle_min) / (
double)(node_count-1);
82 scan_msg.scan_time = scan_time;
83 scan_msg.time_increment = scan_time / (double)(node_count-1);
84 scan_msg.range_min = 0.15;
85 scan_msg.range_max = max_distance;
87 scan_msg.intensities.resize(node_count);
88 scan_msg.ranges.resize(node_count);
89 bool reverse_data = (!inverted && reversed) || (inverted && !reversed);
91 for (
size_t i = 0; i < node_count; i++) {
92 float read_value = (float) nodes[i].
dist_mm_q2/4.0
f/1000;
93 if (read_value == 0.0)
94 scan_msg.ranges[i] = std::numeric_limits<float>::infinity();
96 scan_msg.ranges[i] = read_value;
97 scan_msg.intensities[i] = (float) (nodes[i].
quality >> 2);
100 for (
size_t i = 0; i < node_count; i++) {
101 float read_value = (float)nodes[i].
dist_mm_q2/4.0
f/1000;
102 if (read_value == 0.0)
103 scan_msg.ranges[node_count-1-i] = std::numeric_limits<float>::infinity();
105 scan_msg.ranges[node_count-1-i] = read_value;
106 scan_msg.intensities[node_count-1-i] = (float) (nodes[i].
quality >> 2);
116 sl_lidar_response_device_info_t devinfo;
121 ROS_ERROR(
"Error, operation time out. RESULT_OPERATION_TIMEOUT! ");
123 ROS_ERROR(
"Error, unexpected error, code: %x",op_result);
129 char sn_str[35] = {0};
130 for (
int pos = 0; pos < 16 ;++pos) {
131 sprintf(sn_str + (pos * 2),
"%02X", devinfo.serialnum[pos]);
133 char mode_str[16] = {0};
135 sprintf(mode_str,
"A%dM%d",(devinfo.model>>4),(devinfo.model&0xf));
143 ROS_INFO(
"RPLIDAR MODE:%s",mode_str);
145 ROS_INFO(
"Firmware Ver: %d.%02d",devinfo.firmware_version>>8, devinfo.firmware_version & 0xFF);
146 ROS_INFO(
"Hardware Rev: %d",(
int)devinfo.hardware_version);
157 ROS_ERROR(
"Error, cannot reset rplidar: %x", op_result);
165 sl_lidar_response_device_health_t healthinfo;
170 switch (healthinfo.status) {
172 ROS_INFO(
"RPLidar health status : OK.");
175 ROS_INFO(
"RPLidar health status : Warning.");
178 ROS_ERROR(
"Error, rplidar internal error detected. Please reboot the device to retry.");
181 ROS_ERROR(
"Error, Unknown internal error detected. Please reboot the device to retry.");
185 ROS_ERROR(
"Error, cannot retrieve rplidar health code: %x", op_result);
191 std_srvs::Empty::Response &res)
202 std_srvs::Empty::Response &res)
222 int main(
int argc,
char * argv[]) {
225 std::string channel_type;
227 int tcp_port = 20108;
230 std::string serial_port;
231 int serial_baudrate = 115200;
232 std::string frame_id;
233 bool inverted =
false;
234 bool initial_reset =
false;
235 bool angle_compensate =
true;
236 float angle_compensate_multiple = 1.0;
237 int points_per_circle = 360;
238 std::string scan_mode;
240 double scan_frequency;
244 nh_private.param<std::string>(
"channel_type", channel_type,
"serial");
245 nh_private.param<std::string>(
"tcp_ip", tcp_ip,
"192.168.0.7");
246 nh_private.param<
int>(
"tcp_port", tcp_port, 20108);
247 nh_private.param<std::string>(
"udp_ip", udp_ip,
"192.168.11.2");
248 nh_private.param<
int>(
"udp_port", udp_port, 8089);
249 nh_private.param<std::string>(
"serial_port", serial_port,
"/dev/ttyUSB0");
250 nh_private.param<
int>(
"serial_baudrate", serial_baudrate, 115200);
251 nh_private.param<std::string>(
"frame_id", frame_id,
"laser_frame");
252 nh_private.param<
bool>(
"inverted", inverted,
false);
253 nh_private.param<
bool>(
"initial_reset", initial_reset,
false);
254 nh_private.param<
bool>(
"angle_compensate", angle_compensate,
false);
255 nh_private.param<std::string>(
"scan_mode", scan_mode, std::string());
256 if(channel_type ==
"udp"){
257 nh_private.param<
double>(
"scan_frequency", scan_frequency, 20.0);
260 nh_private.param<
double>(
"scan_frequency", scan_frequency, 10.0);
266 ROS_INFO(
"RPLIDAR running on ROS package rplidar_ros, SDK Version:%d.%d.%d",ver_major,ver_minor,ver_patch);
273 if(channel_type ==
"tcp"){
276 else if(channel_type ==
"udp"){
283 if(channel_type ==
"tcp"){
284 ROS_ERROR(
"Error, cannot connect to the ip addr %s with the tcp port %s.",tcp_ip.c_str(),std::to_string(tcp_port).c_str());
286 else if(channel_type ==
"udp"){
287 ROS_ERROR(
"Error, cannot connect to the ip addr %s with the udp port %s.",udp_ip.c_str(),std::to_string(udp_port).c_str());
290 ROS_ERROR(
"Error, cannot bind to the specified serial port %s.",serial_port.c_str());
320 ROS_INFO(
"Rplidar reset successfully");
329 sl_lidar_response_device_info_t devinfo;
331 bool scan_frequency_tunning_after_scan =
false;
334 scan_frequency_tunning_after_scan =
true;
340 if(!scan_frequency_tunning_after_scan){
347 if (scan_mode.empty()) {
348 op_result =
drv->
startScan(
false ,
true , 0, ¤t_scan_mode);
350 std::vector<LidarScanMode> allSupportedScanModes;
354 sl_u16 selectedScanMode = sl_u16(-1);
355 for (std::vector<LidarScanMode>::iterator iter = allSupportedScanModes.begin(); iter != allSupportedScanModes.end(); iter++) {
356 if (iter->scan_mode == scan_mode) {
357 selectedScanMode = iter->id;
362 if (selectedScanMode == sl_u16(-1)) {
363 ROS_ERROR(
"scan mode `%s' is not supported by lidar, supported modes:", scan_mode.c_str());
364 for (std::vector<LidarScanMode>::iterator iter = allSupportedScanModes.begin(); iter != allSupportedScanModes.end(); iter++) {
365 ROS_ERROR(
"\t%s: max_distance: %.1f m, Point number: %.1fK", iter->scan_mode,
366 iter->max_distance, (1000/iter->us_per_sample));
378 points_per_circle = (int)(1000*1000/current_scan_mode.
us_per_sample/scan_frequency);
379 angle_compensate_multiple = points_per_circle/360.0 + 1;
380 if(angle_compensate_multiple < 1)
381 angle_compensate_multiple = 1.0;
383 ROS_INFO(
"current scan mode: %s, sample rate: %d Khz, max_distance: %.1f m, scan frequency:%.1f Hz, ", current_scan_mode.
scan_mode,(
int)(1000/current_scan_mode.
us_per_sample+0.5),max_distance, scan_frequency);
387 ROS_ERROR(
"Can not start scan: %08x!", op_result);
392 double scan_duration;
402 scan_duration = (end_scan_time - start_scan_time).toSec();
405 if(scan_frequency_tunning_after_scan){
406 ROS_INFO(
"set lidar scan frequency to %.1f Hz(%.1f Rpm) ",scan_frequency,scan_frequency*60);
408 scan_frequency_tunning_after_scan =
false;
415 if (angle_compensate) {
416 const int angle_compensate_nodes_count = 360*angle_compensate_multiple;
417 int angle_compensate_offset = 0;
422 for( ; i < count; i++ ) {
425 int angle_value = (int)(angle * angle_compensate_multiple);
426 if ((angle_value - angle_compensate_offset) < 0) angle_compensate_offset = angle_value;
427 for (j = 0; j < angle_compensate_multiple; j++) {
429 int angle_compensate_nodes_index = angle_value-angle_compensate_offset+j;
430 if(angle_compensate_nodes_index >= angle_compensate_nodes_count)
431 angle_compensate_nodes_index = angle_compensate_nodes_count-1;
432 angle_compensate_nodes[angle_compensate_nodes_index] = nodes[i];
437 publish_scan(&scan_pub, angle_compensate_nodes, angle_compensate_nodes_count,
438 start_scan_time, scan_duration, inverted,
439 angle_min, angle_max, max_distance,
442 int start_node = 0, end_node = 0;
454 publish_scan(&scan_pub, &nodes[start_node], end_node-start_node +1,
455 start_scan_time, scan_duration, inverted,
456 angle_min, angle_max, max_distance,
464 start_scan_time, scan_duration, inverted,
465 angle_min, angle_max, max_distance,