3D激光SLAM:ALOAM---后端lasermapping通过Ceres进行帧到地图的位姿优化

举报
月照银海似蛟龙 发表于 2022/07/30 00:14:45 2022/07/30
【摘要】 3D激光SLAM:ALOAM---后端lasermapping通过Ceres进行帧到地图的位姿优化 前言代码分析Ceres优化时间测试 前言 上一篇博客构建了线约束和面约束,添加到了残差...

3D激光SLAM:ALOAM---后端lasermapping通过Ceres进行帧到地图的位姿优化

前言

上一篇博客构建了线约束和面约束,添加到了残差模块。
ALOAM:后端 lasermapping构建角点约束与面点约束

本片主要介绍通过ceres构建的约束的CostFuction,及后续的通过Ceres进行位姿优化

角点的约束添加在这个地方
在这里插入图片描述
这里的CostFunction是通过LidarEdgeFactor自定义的结构体建立的
和前端里程计用的角点约束是一样的在这篇博客中做了分析
原理就是求当前点到a、b点构成的直线的距离作为残差

面点的约束添加在这个地方
在这里插入图片描述
输入参数有:

  • curr_point 当前点
  • norm 归一化得平面法向量
  • negative_OA_dot_norm 法向量模的倒数

代码分析

然后可以分析 这个 LidarPlaneNormFactor 自定义的结构体了

struct LidarPlaneNormFactor
{

	LidarPlaneNormFactor(Eigen::Vector3d curr_point_, Eigen::Vector3d plane_unit_norm_,
						 double negative_OA_dot_norm_) : curr_point(curr_point_), plane_unit_norm(plane_unit_norm_),
														 negative_OA_dot_norm(negative_OA_dot_norm_) {}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

构造函数,通过生成结构体时的参数,初始化三个变量,和上面的三个是一样的

  • curr_point 当前点
  • plane_unit_norm 归一化得平面法向量
  • negative_OA_dot_norm 法向量模的倒数
	template <typename T>
	bool operator()(const T *q, const T *t, T *residual) const
	{

  
 
  • 1
  • 2
  • 3

在前面说了分析Ceres的costfunction重点就是看这个重载()函数
参数模块在前,残差在后

Eigen::Quaternion<T> q_w_curr{q[3], q[0], q[1], q[2]};

  
 
  • 1

把q转成 eigen的形式

Eigen::Matrix<T, 3, 1> t_w_curr{t[0], t[1], t[2]};

  
 
  • 1

把t转成 eigen的形式

Eigen::Matrix<T, 3, 1> cp{T(curr_point.x()), T(curr_point.y()), T(curr_point.z())};

  
 
  • 1

当前点 转成 eigen 的形式

		Eigen::Matrix<T, 3, 1> point_w;//当前点投影到局部地图坐标系下的点
		point_w = q_w_curr * cp + t_w_curr;//将当前点投影到局部地图坐标系下

  
 
  • 1
  • 2

q_w_curr和t_w_curr是当前帧到局部地图的位姿变换
上面的操作将当前点投影到局部地图上

		Eigen::Matrix<T, 3, 1> norm(T(plane_unit_norm.x()), T(plane_unit_norm.y()), T(plane_unit_norm.z()));
		residual[0] = norm.dot(point_w) + T(negative_OA_dot_norm);//求点到平面的距离

  
 
  • 1
  • 2

第一行就是把法向量转成eigen的形式
第二行就是求点到平面的距离
dot就是点乘,求解和前面说的一样
在这里插入图片描述
残差可以不取模,因为在ceres里面会平方的。

		return true;
	}

  
 
  • 1
  • 2

最后重载函数返回true即可

	static ceres::CostFunction *Create(const Eigen::Vector3d curr_point_, const Eigen::Vector3d plane_unit_norm_,
									   const double negative_OA_dot_norm_)
	{
		return (new ceres::AutoDiffCostFunction<
				LidarPlaneNormFactor, 1, 4, 3>(
			new LidarPlaneNormFactor(curr_point_, plane_unit_norm_, negative_OA_dot_norm_)));
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

定义一个Creat函数,在里面实现AutoDiffCostFunction的定义,最后返回一个CostFunction

之后可以回到后端处理cpp—lasermapping.cpp中,在前面的博客添加了角点和面点约束,在上面分析了CostFunction,下面就是调用Ceres求解了

					// 调用Ceres求解
					TicToc t_solver;
					ceres::Solver::Options options;
					options.linear_solver_type = ceres::DENSE_QR;//稠密的问题 用DENSE_QR的求解方式
					options.max_num_iterations = 4;//最大迭代次数
					options.minimizer_progress_to_stdout = false;
					options.check_gradients = false;
					options.gradient_check_relative_precision = 1e-4;
					ceres::Solver::Summary summary;
					ceres::Solve(options, &problem, &summary);//求解
					printf("mapping solver time %f ms \n", t_solver.toc());//一次ceres求解的时间

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

就是Ceres的常规操作了, 由于涉及局部地图了,属于稠密问题,所以求解方式使用的DENSE_QR求解。最大迭代次数为4次。在终端打印一次ceres求解的时间。

Ceres优化时间测试

这优化过程中,在终端设置了这些的打印信息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
分别是:

  • 构建角点和面点约束的时间
  • 一次ceres求解的时间
  • 两次迭代优化用的时间

在这篇ALOAM:gazebo仿真测试场景搭建中搭建了测试场景,下面来测试下Ceres的优化时间是多少

场景是这样的,角点和面点很丰富
在这里插入图片描述

这个是ALOAM出的地图(AGV没动)
在这里插入图片描述
终端打印的数据(一帧)
在这里插入图片描述
局部地图提取的时间是0.12ms
局部地图中的角点数为1061 面点数是682
建立kd-tree的时间为0.20ms
构建角点和面点约束的时间为 1.59ms
一次ceres求解的时间为 1.75ms
两次迭代优化用的时间 为 7.04ms

文章来源: blog.csdn.net,作者:月照银海似蛟龙,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_32761549/article/details/125914299

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。