在做激光雷达数据的滤波时,定义了一个新的LaserScan类型变量filtered_scan,把滤波后的scan数据赋值给filtered_scan,并作为新的topic发布出去。
遇到了问题,只要给filtered_scan赋值,就会报段错误(segmentation fault)。为了解决这个问题查了一些资料才明白了原因。
解决方法
为了方便一些心急的同学,先直接上解决办法吧,先用以下代码设置激光雷达一次扫描的数据量,
scan.ranges.resize(num_readings);
scan.intensities.resize(num_readings);
再进行赋值,就不会有问题了。
问题原因
查看sensor_msgs/LaserScan.msg文件,发现ranges和intensities是这么被定义的
float32[] ranges # range data [m] (Note: values < range_min or > range_max should be discarded)
float32[] intensities # intensity data [device-specific units]. If your
# device does not provide intensities, please leave
# the array empty.
这里的数组使用的是无长度限制的,也就是方扩号内没有东西。
在使用的时候,不能够直接用数组赋值那样去做,它实际上是一个向量,往里面填充数据应使用c++中vector的push_back、resize之类的函数。换句话说,应该使用resize先设定容器大小,再往里填充数据。
参考代码
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "laser_scan_publisher");
ros::NodeHandle n;
ros::Publisher scan_pub = n.advertise<sensor_msgs::LaserScan>("scan", 50);
//随意产生一些数据,测试代码使用
unsigned int num_readings = 100;
double laser_frequency = 40;
double ranges[num_readings];
double intensities[num_readings];
int count = 0;
ros::Rate r(1.0);
while(n.ok())
{
//随意产生一些数据,测试代码使用
for(unsigned int i = 0; i < num_readings; ++i)
{
ranges[i] = count;
intensities[i] = 100 + count;
}
ros::Time scan_time = ros::Time::now();
//创建Laserscan类型对象scan,以供发布
sensor_msgs::LaserScan scan;
scan.header.stamp = scan_time;
scan.header.frame_id = "laser_frame";
scan.angle_min = -1.57;
scan.angle_max = 1.57;
scan.angle_increment = 3.14 / num_readings;
scan.time_increment = (1 / laser_frequency) / (num_readings);
scan.range_min = 0.0;
scan.range_max = 100.0;
//在对ranges和intensities赋值前先用resize()设定数组大小
scan.ranges.resize(num_readings);
scan.intensities.resize(num_readings);
for(unsigned int i = 0; i < num_readings; ++i)
{
scan.ranges[i] = ranges[i];
scan.intensities[i] = intensities[i];
}
scan_pub.publish(scan);
++count;
r.sleep();
}
}