R3LIVE项目地址 https://github.com/hku-mars/r3live
第1-4节为前置环境配置,第5节开始编译项目
建议参考奥特学园的ROS教程自行安装或使用小鱼的一键安装ROS
奥特学院ROS教程 http://www.autolabor.com.cn/book/ROSTutorials/
小鱼一键安装ROS https://fishros.org.cn/forum/topic/20/小鱼的一键安装系列?lang=zh-CN
此外按照作者文档,除了ROS的基本模块,还需安装以下package
sudo apt-get install ros-XXX-cv-bridge ros-XXX-tf ros-XXX-message-filters ros-XXX-image-transport ros-XXX-image-transport*
其中,ros-XXX-cv-bridge
中的XXX
指所安装的ROS版本分支,本例中使用noetic版本即为ros-noetic-cv-bridge
大疆Livox驱动安装 https://github.com/Livox-SDK/livox_ros_driver
作者修改的Livox驱动 https://github.com/ziv-lin/livox_ros_driver_for_R2LIVE
livox_ros_driver 安装步骤:
1、克隆仓库并建立工作空间
git clone https://github.com/Livox-SDK/livox_ros_driver.git ws_livox/src
2、进入工作空间并编译
cd ws_livox
catkin_make
3、设置环境变量
# 临时设置
source ./devel/setup.sh
# 永久设置(注意路径需根据情况调整)
echo "source ws_livox/src/devel/setup.sh" >> ~/.bashrc
source ~/.bashrc
sudo apt-get install libcgal-dev pcl-tools
生成的点云地图可通过pcl_viewer
命令查看
pcl_viewer (map_name).pcd
如果ubuntu系统未安装opencv,建议安装3.3.1
, 3.4.16
, 4.2.1
,4.5.3
这几个已经测试没问题的版本,本例中使用4.5.2
版本也能正常运行,建议源码编译
ros-noetic-full安装时带有4版本的opencv,但如果装ros前已有opencv可能会导致新装的opencv不完整,编译时会出现链接库不一致的问题(Warning: /usr/bin/ld)
cd ~/catkin_ws/src
git clone https://github.com/hku-mars/r3live.git
cd ../
catkin_make
source ~/catkin_ws/devel/setup.bash
然而实际测试时仍然可能会遇到一些问题,在本例中编译出现过两次问题
当系统中存在多个opencv时,不建议贸然删除某个版本,可通过cmake进行版本管理
find_package(OpenCV 4.5.2 REQUIRED) #选择opencv 4.5.2版本
对自己编译的opencv则可以设置具体的包路径,要求给出能找到OpenCVConfig.cmake或OpenCVConfig-version.cmake
set(OpenCV_DIR ~/opencv/opencv-4.5.2/build/) #本例中opencv的cmake路径
在编译最末尾提示warning:/usr/bin/ld
相关的警告,提示libopencv的某个库存在不同版本可能在运行时产生冲突,可能导致运行时程序突然卡死
这是因为编译库和运行库不一致导致的问题,通常是cv_bridge编译时用了系统默认的某个版本的opencv库造成的
只需要卸载现有的cv_bridge,再下载源码用我们想要的opencv版本编译安装即可解决
sudo apt-get remove ros-${ROS_DISTRO}-cv-bridge #卸载原有cv_bridge
git clone https://github.com/ros-perception/vision_opencv.git
然后在cv_bridge
包中的CMakeLists.txt
中设为自己需要的opencv
版本再编译即可解决
R3LIVE数据集地址 https://github.com/ziv-lin/r3live_dataset
XXX.bag
为你要播放的bag名称,如图中hku_park_01.bag
rosbag play --pause XXX.bag #以可暂停方式播放bag
其他选项:--topic /topic1 /topic2 指定播放话题 | -r (rate) 指定播放速度倍率
roslaunch r3live r3live_bag.launch #启动里程计
rosbag play --pause hku_campus_seq_00.bag
运行后会先通过IMU数据进行初始化,下方的Dashboard会显示当前处理的雷达和图像帧数
通常查看imu等单帧数据量比较小的消息,直接终端rostopic echo [TOPIC]
即可,但是对于相机、雷达等单帧数据量很大的消息可能终端消息会塞满,看不到时间戳,所以可以输出保存成txt文件,方便我们检查时间戳
举个例子,比如说雷达消息的话题名是/livox/lidar
,你想输出保存成一个叫做my_lidar_data.txt
的文件,你的数据包名字是my_lidar_record.bag
,那么命令就是
rostopic echo -b my_lidar_record.bag /livox/lidar >> my_lidar_data.txt
Ctrl C
停掉,不然输出来文件太大不好打开,只能用VSCode打开根据R3LIVE作者提供的时间戳修改方式,我们可以发现作者主要修改了livox_ros_driver
中的lddc.cpp
文件,并且是在IMU消息的发布函数中进行时间初始化,记录了雷达开始发布消息时的ROS系统时间和相对于雷达启动的时间偏移量,略过了起始的100帧数据,初始化后在IMU和点云消息发布函数中进行处理即可(作者修改的是自定义消息CustomPointcloud那个函数)
但是如果使用的Livox雷达不具有IMU,比如本例中使用的mid-70,那么就需要做一些小小的修改
具体的修改方式已经整理在
https://github.com/Cyberkona/SLAM-Tools/tree/main/livox_ros_driver_with_ros_timestamp_for_mid70
,按照R3LIVE作者提供的修改方式,对livox_ros_driver
中lddc.cpp
文件进行修改
lddc.cpp
文件开头,加入用于记录起始时间的相关变量/****** Modified: add variables to change timestamp ******/
double g_ros_init_start_time = -3e8;
double init_lidar_tim = 3e10;
double init_ros_time = 0;
double skip_frame = 10;
/*********************************************************/
lddc.cpp
中的PublishCustomPointcloud
函数,在消息Publish之前加入 /****** Modified: Setup ros timestamp to system base ******/
if (1)
{
if (skip_frame)
{
skip_frame--;
init_ros_time = ros::Time::now().toSec();
init_lidar_tim = timestamp;
g_ros_init_start_time = timestamp;
ROS_INFO("========================");
ROS_INFO("Init time stamp = %lf", g_ros_init_start_time);
ROS_INFO("========================");
}
// change timestamp in function PublishPointcloud2
cloud.header.stamp = ros::Time((timestamp - init_lidar_tim) / 1e9 + init_ros_time);
}
/**********************************************************/
lddc.cpp
中的PublishPointcloud2
函数,在消息Publish之前加入 /****** Modified: Setup ros timestamp to system base ******/
if (1)
{
if (skip_frame)
{
skip_frame--;
init_ros_time = ros::Time::now().toSec();
init_lidar_tim = timestamp;
g_ros_init_start_time = timestamp;
ROS_INFO("========================");
ROS_INFO("Init time stamp = %lf", g_ros_init_start_time);
ROS_INFO("========================");
}
// change timestamp in function PublishPointcloud2
cloud.header.stamp = ros::Time((timestamp - init_lidar_tim) / 1e9 + init_ros_time);
}
/**********************************************************/
Init time stamp = (时间戳信息)
,该消息数量为skip_frame
,之后可通过上述rostopic
命令检查数据时间戳rosbag record
命令录制所需的话题成一数据包,示例如下,推荐图像选择录制压缩的话题,不然数据包太大rosbag record /livox/lidar /camera/imu /camera/color/image_raw/compressed -o my_data.bag
对于ROS中的里程计,使用的是右手系,通常X轴指向机器人向前的运动方向,Z轴指向上方,Y轴则按照右手系可以进行判断
imu_transformer
功能包进行修改,这个包需要自行下载编译
imu_pipeline
功能包集:https://github.com/ros-perception/imu_pipeline
描述:IMU Pipeline metapackage includes tools for processing and pre-processing IMU messages for easier use by later subscribers.
imu_transformer
功能包,注意修改其中imu_transformer_node.cpp
文件中的话题名,以及启动文件ned_to_enu.launch
中的静态变换与target_frame字段;需要注意的是,建议修改静态变换所使用的tf
包至tf2_ros
包!!!,能够让数据转换更加稳定(说多了都是泪TAT)imu_transformer
的转换程序,然后可以播包或者跑实机,运行正常则会输出一个新的IMU话题,推荐实机跑的时候可以录下转换好的IMU数据,以便下一次复用可以查找与相机标定有关的内容,在
config/r3live_config.yaml
文件中修改
(待补充)
r3live_bag.launch
中订阅的IMU及图像的话题名,使用RealSense提供图像与IMU话题,则图像话题修改为/camera/color/image_raw
,IMU话题修改为/camera/imu
,本例中mid-70雷达点云话题名为默认的/livox/lidar
,不需要修改;如需要换用雷达可以更改参数文件里的lidar_type
,话题名不一致可以重映射remap
或者修改前端的接口函数重新编译r3live_bag.launch
,如果需要IMU坐标系转换的话则启动ned_to_enu.launch
,最后播放数据包即可运行