这个标定文件得出的是:IMU到Lidar的外参
github链接:链接: https://github.com/ethz-asl/lidar_align
将源码放在src下,进行编译:
catkin_make
解决办法:安装nlopt,但最新的(2.6.2) libnlopt-dev包在Ubuntu20中被破坏了,由于某种原因它被编译成了一个静态库(.so共享对象缺失)。快速的解决方法是从Github上下载NLOPT并自己编译,连接NLopt文档。
下载好NLopt,进行编译安装,流程如下:
mkdir build
cd build
cmake ..
make
sudo make install
那么在 /usr/local/lib/cmake 目录下出现 nlopt 文件。
然后,在lidar_align工程目录下,并在CMakeLists.txt里加上这样一句话:
list(APPEND CMAKE_FIND_ROOT_PATH ${CMAKE_SOURCE_DIR})
set (CMAKE_PREFIX_PATH "/usr/local/lib/cmake/nlopt")
以上为第一步操作,如果问题尚未解决,第二步操作如下:
将**/home/cupido/lidar-align/src/lidar_align/NLOPTConfig.cmake文件移动到/home/cupido/lidar-align/src**下(与lidar_align同级,注意自己的路径)。
Ubuntu20.04用的应该是c++14,注意CMakeLists.txt的修改,如下:
或者set(CMAKE_CXX_STANDARD 14)
【注】:至此,编译应该没有问题了。
如果原始数据集话题内容较多,而且非常大,全部进行计算会导致系统内存不足而停止运算,报错如下:
//从park_dataset.bag中提取激光雷达点云和IMU数据,注意激光雷达点云数据格式:sensor_msgs/PointCloud2、IMU数据格式:sensor_msgs/Imu
rosbag filter park_dataset.bag cal.bag "topic == '/points_raw' or topic =='/imu_raw'" // 生成cal.bag
//处于初步调试学习使用这个工具包的阶段,暂时要求能出结果就行。使用rosbag命令提取一个时间段内的数据进行计算就行。
rosbag filter cal.bag caltime.bag "t.to_sec() >1593996300.00 and t.to_sec() <= 1593996350.00" // 生成caltime.bag
处理后的caltime.bag包的数据量将会很小
参考博客:rosbag 时间和topic过滤
这个工具包原本是用来标定激光雷达和里程计的,所以需要改写IMU接口以替换里程计接口,改写部分,如下:
// 找到odom部分注释掉,如下:
std::vector<std::string> types;
// types.push_back(std::string("geometry_msgs/TransformStamped"));
// rosbag::View view(bag, rosbag::TypeQuery(types));
// size_t tform_num = 0;
// for (const rosbag::MessageInstance& m : view) {
// std::cout << " Loading transform: \e[1m" << tform_num++
// << "\e[0m from ros bag" << '\r' << std::flush;
// geometry_msgs::TransformStamped transform_msg =
// *(m.instantiate());
// Timestamp stamp = transform_msg.header.stamp.sec * 1000000ll +
// transform_msg.header.stamp.nsec / 1000ll;
// Transform T(Transform::Translation(transform_msg.transform.translation.x,
// transform_msg.transform.translation.y,
// transform_msg.transform.translation.z),
// Transform::Rotation(transform_msg.transform.rotation.w,
// transform_msg.transform.rotation.x,
// transform_msg.transform.rotation.y,
// transform_msg.transform.rotation.z));
// odom->addTransformData(stamp, T);
// }
//在注释的位置粘贴如下代码
types.push_back(std::string("sensor_msgs/Imu"));
rosbag::View view(bag, rosbag::TypeQuery(types));
size_t imu_num = 0;
double shiftX=0,shiftY=0,shiftZ=0,velX=0,velY=0,velZ=0;
ros::Time time;
double timeDiff,lastShiftX,lastShiftY,lastShiftZ;
for (const rosbag::MessageInstance& m : view){
std::cout <<"Loading imu: \e[1m"<< imu_num++<<"\e[0m from ros bag"<<'\r'<< std::flush;
sensor_msgs::Imu imu=*(m.instantiate<sensor_msgs::Imu>());
Timestamp stamp = imu.header.stamp.sec * 1000000ll +imu.header.stamp.nsec / 1000ll;
if(imu_num==1){
time=imu.header.stamp;
Transform T(Transform::Translation(0,0,0),Transform::Rotation(1,0,0,0));
odom->addTransformData(stamp, T);
}
else{
timeDiff=(imu.header.stamp-time).toSec();
time=imu.header.stamp;
velX=velX+imu.linear_acceleration.x*timeDiff;
velY=velX+imu.linear_acceleration.y*timeDiff;
velZ=velZ+(imu.linear_acceleration.z-9.801)*timeDiff;
lastShiftX=shiftX;
lastShiftY=shiftY;
lastShiftZ=shiftZ;
shiftX=lastShiftX+velX*timeDiff+imu.linear_acceleration.x*timeDiff*timeDiff/2;
shiftY=lastShiftY+velY*timeDiff+imu.linear_acceleration.y*timeDiff*timeDiff/2;
shiftZ=lastShiftZ+velZ*timeDiff+(imu.linear_acceleration.z-9.801)*timeDiff*timeDiff/2;
Transform T(Transform::Translation(shiftX,shiftY,shiftZ),
Transform::Rotation(imu.orientation.w,
imu.orientation.x,
imu.orientation.y,
imu.orientation.z));
odom->addTransformData(stamp, T);
}
}
主要是你数据集所在的路径:
启动进行标定:
catkin_make
source devel/setup.bash
roslaunch lidar_align lidar_align.launch
计算完成后,在程序包的results文件夹里会出现一个.txt文件和一个.ply文件。
.txt文件查看标定结果,主要是变化矩阵,变化向量和四元数。
用pcl viewer打开,执行如下指令:
pcl_ply2pcd xxxxx.ply view.pcd
pcl_viewer view.pcd
这里展示拿lidar_align测出来的kitti的外参与kitti官方给的外参值对照图,如下:
由图片可以看出来,标得不是很准,考虑可能是准备的数据集有问题。
lidar_align测出来的kitti的外参即为:IMU到Lidar的外参值
1、使用lidar_align联合标定lidar与imu的外参
2、激光雷达和IMU联合标定并运行LIOSAM