赞
踩
lidar-visual-inertial odometry and mapping system
激光-视觉-IMU 里程计和建图,结合了lio-sam
和vins-mono
系统的优点。
总体框架示意图:
各个节点 数据传输示意图
依赖:
ros 测试: kinetic and melodic (16.04 和20.04)
gtsam:https://gtsam.org/get_started/
sudo add-apt-repository ppa:borglab/gtsam-release-4.0
sudo apt install libgtsam-dev libgtsam-unstable-dev
ceres:https://github.com/ceres-solver/ceres-solver/releases
sudo apt-get install -y libgoogle-glog-dev
sudo apt-get install -y libatlas-base-dev
wget -O ~/Downloads/ceres.zip https://github.com/ceres-solver/ceres-solver/archive/1.14.0.zip
cd ~/Downloads/ && unzip ceres.zip -d ~/Downloads/
cd ~/Downloads/ceres-solver-1.14.0
mkdir ceres-bin && cd ceres-bin
cmake ..
sudo make install -j4
```
运行:
rosbag play handheld.bag
roslaunch lvi_sam run.launch
主函数:
初始化Ros节点
设置Log等级
ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Warn);
读取参数 每个节点都读取一遍,好费劲
读取相机参数 N个相机参数单独读取
初始化深度寄存器(在读取参数后) DepthRegister
订阅 激光和图像 话题,若不适用激光时,sub_lidar.shutdown();
发布topic:
两个线程,MultiThreadedSpinner
, 用于并行处理(图像和激光雷达)
1、跳帧,++lidar_count % (LIDAR_SKIP+1) != 0
2、得到 vins_world 到 body的转换关系transNow
Eigen::Affine3f
3、点云数据处理
x>=0&&y/x<=10&&z/x<=10
pcl::transformPointCloud
4、保存点云队列 点云+time 两个队列 cloudQueue、timeQueue
5、弹出队列中老的数据,保留5s数据
6、融合队列中的点云数据depthCloud
,即将队列中所有点云数据相加
7、融合后的点云数据降采样,(0.2,0.2,0.2)
first_image_time、last_image_time
返回PUB_THIS_FRAME
,发布时 ++pub_count
round(1.0 * pub_count / (cur_img_time - first_image_time)) <= FREQ
PUB_THIS_FRAME
时,发布topic,pub_feature
,注:depthRegister->get_depth直方图均衡化,参数:cv::createCLAHE(3.0, cv::Size(8, 8)
若 forw_img是空, 则 prev_img = cur_img = forw_img = img;
若 cur_pts.size() > 0
时,光流跟踪,当前跟踪特征点forw_pts
cv::calcOpticalFlowPyrLK
若发布 该帧时
cv::goodFeaturesToTrack
赋值,并去畸变 undistortedPoints
cv::undistortPoints
不过使用相机模型中:m_camera->liftProjective
初始化深度 通道,为返回做准备
name = "depth",values.resize(features_2d.size(), -1)
若无深度点云时,直接返回了,深度点云由lidar_callback
得到
得到当前时间段 body到世界坐标系的位姿 transNow
将点云从 世界坐标系转换到相机坐标系 transNow.inverse()
将特征点投影到单位球面上,z 总是为1 features_3d_sphere
定义求取深度的图片(-90°,90°),分辨率 bin_res =180/360
遍历所有的深度点,计算raw_id,col_id,若在图像范围内,仅保留最近的点
row_angle =atan2(p.z, sqrt(p.x * p.x + p.y * p.y)) * 180.0 / M_PI + 90.0
col_angle = atan2(p.x, p.y) * 180.0 / M_PI;
depth_cloud_local赋值,发布深度到vins_body_ros坐标系
将深度点云图 depth_cloud_local进行归一化,得到 depth_cloud_unit_sphere
通过归一化深度图 depth_cloud_unit_sphere,创建 kd_tree
遍历 归一化特征点features_3d_sphere,得到各个点的深度
(N(0) * A(0) + N(1) * A(1) + N(2) * A(2))
(N(0) * V(0) + N(1) * V(1) + N(2) * V(2))
若发布深度图,则赋值不同颜色显示,并发布
跟新各个特征的深度点depth_of_point,并返回
主函数:
Estimator estimator
全局变量estimator.setParameter()
restart_callback
sub_odom.shutdown();
MultiThreadedSpinner
, 用于并行处理m_buf
m_odom
m_buf
measurements !=0
measurements
estimator.processIMU
m_odom
重置 odometry_channel(18,-1)
激光里程计部位空时,丢掉里程计较老的帧,odom<img_time-0.05? pop_fornt
激光里程计为空时,直接返回
得到 最接近的 q_odom_lidar
odomCur
,小于图像视觉的最近里程计帧odomCur
与img时间间隔大于 0.05,直接return将其转换到 激光坐标系 q_odom_cam
转换 里程计位姿从激光坐标系到 相机坐标系
odomCur
转换为 p_eigen,v_eigenodomCur
返回 odometry_channel,由 odomCur
转换而来
主函数:
ros初始化,初始化节点+句柄+log等级显示
加载参数
如果 需闭环:参数设置
订阅话题:
发布话题:
若无闭环时,上述订阅发布话题都 shutdown
构建主线程 std::thread(process);
m_buf
m_buf
m_buf
m_process
m_buf
static int
m_process
与 lio-sam基本无差异,里程计由原 后端提供改为 视觉提供
deskew/cloud_deskewed
deskew/cloud_info
odoLock
单独的imuLock
单独的添加一帧激光点云到队列,取出最早一帧作为当前帧,计算起止时间戳,检查数据有效性
cachePointCloud
处理当前激光帧起止时刻对应的IMU数据、IMU里程计数据
deskewInfo
当前帧激光点云运动畸变校正projectPointCloud
提取有效激光点,存extractedCloud
cloudExtraction
发布当前帧校正后点云,有效点 publishClouds
重置参数,接收每帧lidar数据都要重置这些参数 resetParameters
gpsQueue
队列中loop_time_cur
的frame:key_curloop_time_pre
的frame:key_prepose_cur
、pose_pre
、pose_diff_t
位置xyz
historyKeyframeSearchRadius * 2=40
cureKeyframeCloud_new
,基于pose_diff_t
进行平移getFitnessScore
,作为噪声nearKeyframes
downSizeFilterICP
,数据赋值 nearKeyframes
timeLaserInfoCur
nearby
再extractcloud
最后结束,这个就是对周围的关键帧做一个处理cloudKeyPoses3D
为空,即第一帧时,当前帧作为初始帧
cloudKeyPoses3D
中点云为空时,直接returnextractNearby()
kdTree
中,并找出最新关键帧位姿
kdTree
:半径:50msurroundingKeyPosesDS
extractCloud(surroundingKeyPosesDS)
该优化是独立于scan-map的另一个优化
Vector(6) << 1e-2, 1e-2, M_PI*M_PI, 1e8, 1e8, 1e8
Vector(6) << 1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4
gpsQueue
队列,只添加当前帧 [-0.2,0.2]的数据
performLoopClosureDetection()
historyKeyframeSearchTimeDiff: 30.0
这两模块跟lio-sam一样
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。