用Cartographer做二维的激光SLAM,用杉川给的ROS例子发布LaserScan数据,发现在Rviz中显示的数据,本来应该是平直的墙变成弧形的,建图也是混乱的,如下图:
研究杉川的ROS例子,转换过程在ltme_node.cpp里,发现参数有些问题,相关代码如下:
const int LidarDriver::DEFAULT_SCAN_FREQUENCY = 15;
const double LidarDriver::ANGLE_MIN_LIMIT = -2.356;
const double LidarDriver::ANGLE_MAX_LIMIT = 2.356;
const double LidarDriver::DEFAULT_ANGLE_EXCLUDED_MIN = -3.142;
const double LidarDriver::DEFAULT_ANGLE_EXCLUDED_MAX = -3.142;
const double LidarDriver::RANGE_MIN_LIMIT = 0.05;
const double LidarDriver::RANGE_MAX_LIMIT = 30;
int beam_count = 0;
switch (scan_frequency) {
case 10: beam_count = 3072; break;
case 15: beam_count = 2048; break;
case 20: beam_count = 1536; break;
case 25:
case 30: beam_count = 1024; break;
default: beam_count = 2048; break;
}
int beam_index_min = std::ceil(angle_min_ * beam_count / (2 * M_PI));
int beam_index_max = std::floor(angle_max_ * beam_count / (2 * M_PI));
int beam_index_excluded_min = std::ceil(angle_excluded_min_ * beam_count / (2 * M_PI));
int beam_index_excluded_max = std::floor(angle_excluded_max_ * beam_count / (2 * M_PI));
sensor_msgs::LaserScan laser_scan;
laser_scan.header.frame_id = frame_id_;
laser_scan.angle_min = angle_min_;
laser_scan.angle_max = angle_max_;
laser_scan.angle_increment = 2 * M_PI / beam_count * average_factor_;
laser_scan.time_increment = 1.0 / scan_frequency / beam_count * average_factor_;
laser_scan.scan_time = 1.0 / scan_frequency;
laser_scan.range_min = range_min_;
laser_scan.range_max = range_max_;
发现参数里都用的2*M_PI(360度),看着没什么问题,但是杉川3i-T1这款雷达是270度的扫描范围的,所以用360度就有问题了,需要改成270度的,如下:
//int beam_index_min = std::ceil(angle_min_ * beam_count / (2 * M_PI));
//int beam_index_max = std::floor(angle_max_ * beam_count / (2 * M_PI));
int beam_index_min = std::ceil(angle_min_ * beam_count / (4.712));
int beam_index_max = std::floor(angle_max_ * beam_count / (4.712));
//int beam_index_excluded_min = std::ceil(angle_excluded_min_ * beam_count / (2 * M_PI));
//int beam_index_excluded_max = std::floor(angle_excluded_max_ * beam_count / (2 * M_PI));
int beam_index_excluded_min = std::ceil(angle_excluded_min_ * beam_count / (4.712));
int beam_index_excluded_max = std::floor(angle_excluded_max_ * beam_count / (4.712));
sensor_msgs::LaserScan laser_scan;
laser_scan.header.frame_id = frame_id_;
laser_scan.angle_min = angle_min_;
laser_scan.angle_max = angle_max_;
//laser_scan.angle_increment = 2 * M_PI / beam_count * average_factor_;
laser_scan.angle_increment = (4.712) / beam_count * average_factor_;
laser_scan.time_increment = 1.0 / scan_frequency / beam_count * average_factor_;
laser_scan.scan_time = 1.0 / scan_frequency;
laser_scan.range_min = range_min_;
laser_scan.range_max = range_max_;
再次测试还是有问题,扫描出的仍然是弧形的,继续跟代码,最后发现接收到的每块数据的点数不对,研究SDK的说明:
最后发现ROS的例子虽然可以设置扫描频率,但是只是数据解析这改变了,设备的扫描频率并没有改变……,先用官方软件改完频率,再用ROS的例子跑,终于正常了,建图效果还不错: