(02)Cartographer源码无死角解析-(36) PoseExtrapolator→AddImuData()、TrimOdometryData()
admin
2024-04-21 02:38:30
0

讲解关于slam一系列文章汇总链接:史上最全slam从零开始,针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下:
(02)Cartographer源码无死角解析- (00)目录_最新无死角讲解:https://blog.csdn.net/weixin_43013761/article/details/127350885
 
文末正下方中心提供了本人联系方式,点击本人照片即可显示WX→官方认证{\color{blue}{文末正下方中心}提供了本人 \color{red} 联系方式,\color{blue}点击本人照片即可显示WX→官方认证}文末正下方中心提供了本人联系方式,点击本人照片即可显示WX→官方认证
 

一、前言

接下来就是对 PoseExtrapolator 的成员函数进行细致分析了,需要注意的是,对于成员函数的分析,也是有逻辑,有目的的,并不是杂乱无章的分析。主要围绕着如下接口函数分析:

  //const = 0,表示该函数不改变成员变量且为纯虚函数,子类必须从重写virtual common::Time GetLastPoseTime() const = 0;//返回最后一次推断器推断出位姿的时间点virtual common::Time GetLastExtrapolatedTime() const = 0;//添加 pose,与前面的 GetLastPoseTime() 函数就联系起来了。virtual void AddPose(common::Time time, const transform::Rigid3d& pose) = 0;//添加 Imu 数据,virtual void AddImuData(const sensor::ImuData& imu_data) = 0;//添加里程计数据virtual void AddOdometryData(const sensor::OdometryData& odometry_data) = 0;//推断器进行位姿推断virtual transform::Rigid3d ExtrapolatePose(common::Time time) = 0;//该函数输入一个存储时间的vector容器对象//返回该些时间点对应的位姿,以及最后一个时间点的重力对齐矩阵virtual ExtrapolationResult ExtrapolatePosesWithGravity(const std::vector& times) = 0;// Returns the current gravity alignment estimate as a rotation from// the tracking frame into a gravity aligned frame.// 传入一个时间点,返回该时间点的重力对齐矩阵virtual Eigen::Quaterniond EstimateGravityOrientation(common::Time time) = 0;

上面的注释暂时不一定是全正确的,后续一边分析一遍修改。这些接口函数都在 src/cartographer/cartographer/mapping/pose_extrapolator.cc 中被重写。
 

二、时间获取

先来看两个比较简单的函数:

// 返回上次校准位姿的时间
common::Time PoseExtrapolator::GetLastPoseTime() const {// 如果尚未添加任何位姿, 则返回Time::min()if (timed_pose_queue_.empty()) {return common::Time::min();}return timed_pose_queue_.back().time;
}// 获取上一次预测位姿的时间
common::Time PoseExtrapolator::GetLastExtrapolatedTime() const {if (!extrapolation_imu_tracker_) {return common::Time::min();}return extrapolation_imu_tracker_->time();
}

逻辑比较简单,如果 timed_pose_queue_ 与 extrapolation_imu_tracker_ 为空则返回 common::Time::min(),返回最后一个数据的时间点。
 

三、AddImuData()

对于添加数据有三个函数:

void PoseExtrapolator::AddPose()
void PoseExtrapolator::AddImuData()
void PoseExtrapolator::AddOdometryData()

从简单的说起,也就是 PoseExtrapolator::AddImuData() ,该函数代码实现如下:

// 向imu数据队列中添加imu数据,并进行数据队列的修剪
void PoseExtrapolator::AddImuData(const sensor::ImuData& imu_data) {CHECK(timed_pose_queue_.empty() ||imu_data.time >= timed_pose_queue_.back().time);imu_data_.push_back(imu_data);TrimImuData();
}

逻辑比较建简单,如果 timed_pose_queue_ 队列不为空的时候,要求目前传入的 imu_data 时间点大于队列中最后一个元素的时间点。然后把 imu_data 添加到 timed_pose_queue_ 成为最后一个数据。然后调用 TrimImuData() 函数。

// 修剪imu的数据队列,丢掉过时的imu数据
void PoseExtrapolator::TrimImuData() {// 保持imu队列中第二个数据的时间要大于最后一个位姿的时间, imu_date_最少是1个while (imu_data_.size() > 1 && !timed_pose_queue_.empty() &&imu_data_[1].time <= timed_pose_queue_.back().time) {imu_data_.pop_front();}
}

同时满足如下三个条件,则会一直循环把 imu_data_ 的最前面(第一个) 数据抛掉。

(1)\color{blue}{(1)}(1) imu_data_ 中的元素个数大于1 → imu_data_.size() > 1

(2)\color{blue}{(2)}(2) timed_pose_queue_ 队列不为空 → !timed_pose_queue_.empty()

(3)\color{blue}{(3)}(3) timed_pose_queue_ 最后一个元素的时间需要大于 imu_data_[1].time → imu_data_[1].time <= timed_pose_queue_.back().time

也就说 ①imu_data_元素只有一个的时候,会停止循环。②或者timed_pose_queue_队列为空,也会停止循环。③亦或者 imu_data_ 第一个元素的时间大于 timed_pose_queue_ 最后一个元素的时间,也会停止循环。

小伙伴门,迷糊吗?\color{red}{ 小伙伴门,迷糊吗?}小伙伴门,迷糊吗? 总的来说, AddImuData() 函数起始已经保证了 imu_data_ 数据是按时间顺序排列的,排在后面数据的时间戳大于前面数据的时间戳。目的就是让 imu_data_ 队列中的所有数据的时间戳,都大于 timed_pose_queue_ 最后一个数据的时间戳。

其作用是什么,为什么要这样做,后续再分析探讨。
 

四、AddOdometryData()→逻辑讲解

首先这里说一下,该函数目的是获得如下两个变量:

angular_velocity_from_odometry_  //根据里程计计算出来的角速度
linear_velocity_from_odometry_   //根据里程计计算出来的线速度

这里先对其逻辑进行解析,源码的注释在后面。

(1)\color{blue}{(1)}(1) 首先保证新添加的数据都迟于之前的数据,然后添加到 odometry_data_ 队列中。然后对 odom 数据队列进行修剪,保证修剪之后的 odometry_data_ 中的数据时间戳,都小于 timed_pose_queue_ 队列中最后一个数据的时间戳。

(2)\color{blue}{(2)}(2) 获得 odometry_data_ 队列第一个数据与最后一个数据,求得时间差 odometry_time_delta,以及两个时刻 odometry 的位姿变换,源码实现如下:

  const transform::Rigid3d odometry_pose_delta =odometry_data_newest.pose.inverse() * odometry_data_oldest.pose;

首先,这里的 odometry_data_newest.pose 与 odometry_data_oldest.pose 表示基于

 
 
 

相关内容

热门资讯

求歌名~~~~~~~~~ 求歌名~~~~~~~~~?!!!11范德萨发的说法罗大佑 光阴的故事春天的花开秋天的风以及冬天的...
现在很多青壮年人为什么不喜欢看... 现在很多青壮年人为什么不喜欢看电视?看电视的为什么都是中老年人?事实就是这样的
身为一名吃货,有哪些长得难看但... 身为一名吃货,有哪些长得难看但却很好吃的东西?榴莲,榴莲的外形是非常难看的,有很多刺,很不好看,但是...
女孩子说不喜欢你意味着什么 女孩子说不喜欢你意味着什么我就是个女生,对于你说的这个问题,从我的角度出发,如果我几次不回一个人的短...
云生结海楼前面一句是什么的 云生结海楼前面一句是什么的月下飞天镜,云生结海楼
西游记二十一回至五十回内容梗慨 西游记二十一回至五十回内容梗慨这么多,我才不会那么多东西
如果你被自己好朋友耍了你会怎么... 如果你被自己好朋友耍了你会怎么办?宽容别人就是善待自己.人与人之间的相处本来就有利益关系,因为人都是...
虎子和虎二是一个人吗? 虎子和虎二是一个人吗?不是一个人,年龄不同。应该不是吧。这个问题不太好判断不知道诶,可能不是_应该不...
梦幻龙族阿兰姆之瞳的爆率. 梦幻龙族阿兰姆之瞳的爆率.选那个箱子几率大点?就像龙心在第3.4个箱子暴率大那样.......顺便问...
我一直在想,网上能不能少些尽是... 我一直在想,网上能不能少些尽是主角光环主角无敌的小说,多些主角一步步成长,但能力正常,没有天下无敌其...
有个以隋唐为背景的网络游戏,仿... 有个以隋唐为背景的网络游戏,仿照地下城的那种玩法。里面有个职业可以专职成舞娘或者重炮有个以隋唐为背景...
头伏吃饺子芹菜韭菜靠边站,用它... 头伏吃饺子,芹菜韭菜靠边站,用它做馅汤汁四溢味道香,全家都爱吃! 俗话说“热在三伏”,每到三伏天到来...
原创 国... #国内一线大学和国际一线大学的食堂餐,网友:这才是真正的高大上 在求知的殿堂里,大学食堂不仅是味蕾...
原创 沧... 沧州特产以老豆腐、金丝小枣、青县泥塑和武术器械最为著称。这座环渤海城市的物产与人文紧密交织,既有运河...
用别人的手机打开游戏红包有问题... 用别人的手机打开游戏红包有问题吗?您好。用别人的手机打开游戏红包是没有问题的,但是您要经过人家的同意...
如果解释"顾左右而言... 如果解释"顾左右而言他"这句话?心不在焉的意思。
方与圆的好词 方与圆的好词有方字和圆字的词语有:随方就圆!还有:方圆百里!
超神系统猪脚他和妹妹最后什么关... 超神系统猪脚他和妹妹最后什么关系和小石头。貌似是
求女主每世都叫清欢,系统是个宠... 求女主每世都叫清欢,系统是个宠物的快穿玄幻文,每一个世界男主都以不同的身份在她身边快穿女主渣化之路
为什么会遇见你 为什么会遇见你缘分来了谁也挡不住缘分走了谁也得不到伤心是难免的那是一种强烈的心痛心痛的时候真希望当初...