LOAM_velodyne学习(四)

TransformMaintenance

来到了最后一个模块,代码不是很长,我们在看完代码之后,再详细说明这个模块的功能

依然主函数开始

int main(int argc, char** argv)
{ros::init(argc, argv, "transformMaintenance");ros::NodeHandle nh;//订阅了两个节点ros::Subscriber subLaserOdometry = nh.subscribe<nav_msgs::Odometry> ("/laser_odom_to_init", 5, laserOdometryHandler);ros::Subscriber subOdomAftMapped = nh.subscribe<nav_msgs::Odometry> ("/aft_mapped_to_init", 5, odomAftMappedHandler);//发布一个节点ros::Publisher pubLaserOdometry2 = nh.advertise<nav_msgs::Odometry> ("/integrated_to_init", 5);pubLaserOdometry2Pointer = &pubLaserOdometry2;laserOdometry2.header.frame_id = "/camera_init";laserOdometry2.child_frame_id = "/camera";tf::TransformBroadcaster tfBroadcaster2;tfBroadcaster2Pointer = &tfBroadcaster2;laserOdometryTrans2.frame_id_ = "/camera_init";laserOdometryTrans2.child_frame_id_ = "/camera";ros::spin();return 0;
}

主函数非常简单,可以看出integrated_to_init消息是由发布器pubLaserOdometry2发布的,实际上就是由发布器pubLaserOdometry2Pointer发布的。我们找到pubLaserOdometry2Pointer,发现回调函数laserOdometryHandler就是pubLaserOdometry2Pointer的发布函数,这意味着,发现每次接收到laser_odom_to_init消息并调用回调函数laserOdometryHandler时,就发布一次integrated_to_init消息。

看来重点是这个回调函数laserOdometryHandler,我们来仔细看看

void laserOdometryHandler(const nav_msgs::Odometry::ConstPtr& laserOdometry)
{double roll, pitch, yaw;//对收到的消息进行解析,得到transformSumgeometry_msgs::Quaternion geoQuat = laserOdometry->pose.pose.orientation;tf::Matrix3x3(tf::Quaternion(geoQuat.z, -geoQuat.x, -geoQuat.y, geoQuat.w)).getRPY(roll, pitch, yaw);transformSum[0] = -pitch;transformSum[1] = -yaw;transformSum[2] = roll;transformSum[3] = laserOdometry->pose.pose.position.x;transformSum[4] = laserOdometry->pose.pose.position.y;transformSum[5] = laserOdometry->pose.pose.position.z;//位姿更新transformAssociateToMap();//位姿信息进行存储,准备发布geoQuat = tf::createQuaternionMsgFromRollPitchYaw(transformMapped[2], -transformMapped[0], -transformMapped[1]);laserOdometry2.header.stamp = laserOdometry->header.stamp;laserOdometry2.pose.pose.orientation.x = -geoQuat.y;laserOdometry2.pose.pose.orientation.y = -geoQuat.z;laserOdometry2.pose.pose.orientation.z = geoQuat.x;laserOdometry2.pose.pose.orientation.w = geoQuat.w;laserOdometry2.pose.pose.position.x = transformMapped[3];laserOdometry2.pose.pose.position.y = transformMapped[4];laserOdometry2.pose.pose.position.z = transformMapped[5];pubLaserOdometry2Pointer->publish(laserOdometry2);laserOdometryTrans2.stamp_ = laserOdometry->header.stamp;laserOdometryTrans2.setRotation(tf::Quaternion(-geoQuat.y, -geoQuat.z, geoQuat.x, geoQuat.w));laserOdometryTrans2.setOrigin(tf::Vector3(transformMapped[3], transformMapped[4], transformMapped[5]));tfBroadcaster2Pointer->sendTransform(laserOdometryTrans2);
}

但是,这里还是有个小坑的。这个节点接收了两个消息,分别是laserOdometry节点和laserMapping节点发布的,而这两个节点发布的频率不同,那么是怎么处理的呢?

我们仔细看一看剩下的一个回调函数

void odomAftMappedHandler(const nav_msgs::Odometry::ConstPtr& odomAftMapped)
{double roll, pitch, yaw;geometry_msgs::Quaternion geoQuat = odomAftMapped->pose.pose.orientation;tf::Matrix3x3(tf::Quaternion(geoQuat.z, -geoQuat.x, -geoQuat.y, geoQuat.w)).getRPY(roll, pitch, yaw);transformAftMapped[0] = -pitch;transformAftMapped[1] = -yaw;transformAftMapped[2] = roll;transformAftMapped[3] = odomAftMapped->pose.pose.position.x;transformAftMapped[4] = odomAftMapped->pose.pose.position.y;transformAftMapped[5] = odomAftMapped->pose.pose.position.z;transformBefMapped[0] = odomAftMapped->twist.twist.angular.x;transformBefMapped[1] = odomAftMapped->twist.twist.angular.y;transformBefMapped[2] = odomAftMapped->twist.twist.angular.z;transformBefMapped[3] = odomAftMapped->twist.twist.linear.x;transformBefMapped[4] = odomAftMapped->twist.twist.linear.y;transformBefMapped[5] = odomAftMapped->twist.twist.linear.z;
}

也是很简单的解析函数,作用是在接收到了laserMapping的消息后,更新位姿,这里注意,laserMapping发布的是优化过后的位姿!看到这里,就逐渐能明白作者如何完成两个不同频率之间的协调了。

当接收到laserMapping的消息后,立马更新位姿,这样得到了优化的结果;而这个优化结果会被回调函数laserOdometryHandler​​​​​​​里的transformAssociateToMap这一个函数一直利用来建图,一直到下一次接收到laserMapping​​​​​​​的消息,再一次更新位姿,我们画图来说明:

也就是说,最后采用的位姿是TransformMaintenance发布的integrated_to_init消息。而且由上面的分析可知,TransformMaintenance的发布频率和laserOdometry的发布频率是一致的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253936.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP数据库类

<?phpclass Db{//私有静态属性存储实例化对象自身private static $instance;//存储PDO类的实例化private $pdo;//PDOStatement类private $stmt;//禁止外部实例化对象&#xff0c;链接数据库private function __construct($config,$port,$charset){try{$this->pdo new P…

oracle参数文件、控制文件、数据文件、日志文件的位置及查询方法

参数文件&#xff1a;所有参数文件一般在 $ORACLE_HOME/dbs 下 sqlplus查询语句&#xff1a;show parameter spfile; 网络连接文件&#xff1a; $ORACLE_HOME/dbs/network/admin 目录中 控制文件&#xff1a;select * from v$controlfile; 数据文件&#xff1a;一般在oracleda…

Bishops Alliance—— 最大上升子序列

原题链接&#xff1a;http://codeforces.com/gym/101147/problem/F 题意&#xff1a;n*n的棋盘&#xff0c;给m个主教的坐标及其私有距离p&#xff0c;以及常数C&#xff0c;求位于同一对角线上满足条件&#xff1a;dist(i, j) > p[i]^2 p[j]^2 C 的主教集合的元素个数最…

LeGO-LOAM学习

前言 在学习了LOAM之后&#xff0c;了解到LeGO-LOAM&#xff08;面向复杂情况的轻量级优化地面的雷达里程计&#xff09;&#xff0c;进行了一个学习整理。 Github&#xff1a;https://github.com/RobustFieldAutonomyLab/LeGO-LOAM 论文&#xff1a;https://github.com/Robu…

char data[0]用法总结

struct MyData { int nLen; char data[0]; }; 开始没有理解红色部分的内容&#xff0c;上网搜索下&#xff0c;发现用处很大&#xff0c;记录下来。 在结构中&#xff0c;data是一个数组名&#xff1b;但该数组没有元素&#xff1b;该数组…

(一)低功耗设计目的与功耗的类型

一、低功耗设计的目的 1.便携性设备等需求 电子产品在我们生活中扮演了极其重要的作用&#xff0c;便携性的电子设备便是其中一种。便携性设备需要电池供电、需要消耗电池的能量。在同等电能提供下&#xff0c;低功耗设计的产品就能够工作更长的时间。时间的就是生命&#xff…

(转)彻底学会使用epoll(一)——ET模式实现分析

注&#xff1a;之前写过两篇关于epoll实现的文章&#xff0c;但是感觉懂得了实现原理并不一定会使用&#xff0c;所以又决定写这一系列文章&#xff0c;希望能够对epoll有比较清楚的认识。是请大家转载务必注明出处&#xff0c;算是对我劳动成果的一点点尊重吧。另外&#xff0…

MFC的消息映射有什么作用

绝对以下这三个解释的比较简洁&#xff0c;特此做个记录&#xff01;以感谢回答的这些人&#xff01; MFC的消息映射有什么作用: Windows操作系统主要是有消息来处理的&#xff0c;每个程序都有自己的消息队列&#xff0c;并且这些消息是有优先级的&#xff0c;也就是谁会先…

线性表的链式存储结构

链式存储结构的定义 1.概念定义&#xff1a; - n个结点离散分配 - 彼此通过指针相连 - 每个结点只有一个前驱结点和一个后继结点 - 首结点没有前驱结点&#xff0c;尾结点没有后继结点 2.专业术语 -首结点&#xff1a;第一个有有效数据的结点 -尾结点&#xff1a;最后一个有有效…

Apache 设置http跳转至HTTPS访问

为什么80%的码农都做不了架构师&#xff1f;>>> <VirtualHost>...</VirtualHost> 中添加如下配置 <IfModule mod_rewrite.c>RewriteEngine onRewriteCond %{SERVER_PORT} 80RewriteRule ^(.*)$ https://域名/$1 [R301,L] </IfModule> 转…

JAVA线程概念

一、程序与进程 1、程序&#xff1a;一段静态的代码。 2、进程&#xff1a;程序的一次动态执行过程&#xff0c;它对应从代码加载、执行到执行完毕的一个完整过程。 3、进程也称任务&#xff0c;支持多个进程同时执行的OS就被称为多进程OS或多任务OS。 二、进程与线程 在一…

(二)功耗的分析

前面学习了进行低功耗的目的个功耗的构成&#xff0c;今天就来分享一下功耗的分析。由于是面向数字IC前端设计的学习&#xff0c;所以这里的功耗分析是基于DC中的power compiler工具&#xff1b;更精确的功耗分析可以采用PT&#xff0c;关于PT的功耗分析可以查阅其他资料&#…

Hibernate创建hqll时报错

Hibernate 问题,在执行Query session.createQuery(hql) 报错误 出错截图&#xff1a; 这条语句在java运行环境下&#xff0c;直接连数据库不出错&#xff0c;如果在hiberante,struts环境下就出错 出错原因&#xff1a;jar包冲突&#xff0c;struts2和hibernate框架中都有antlr包…

.NET Core TDD 前传: 编写易于测试的代码 -- 全局状态

第1篇: 讲述了如何创造"缝". "缝"(seam)是需要知道的概念. 第2篇, 避免在构建对象时写出不易测试的代码. 第3篇, 依赖项和迪米特法则. 本文是第4篇, 将介绍全局状态引起的问题. 全局状态 全局状态, 也可以叫做应用程序状态, 它是一组变量, 这些变量维护着…

(三)系统与架构级低功耗设计

前面讲解了使用EDA工具&#xff08;主要是power compiler&#xff09;进行功耗分析的流程&#xff0c;这里我们将介绍在数字IC中进行低功耗设计的方法&#xff0c;同时也结合EDA工具&#xff08;主要是Design Compiler&#xff09;如何实现。我们的讲解的低功耗设计主要是自顶向…

python---统计列表中数字出现的次数

1 import collections 2 3 a [1,2,3,1,2,3,4,1,2,5,4,6,7,7,8,9,6,2,23,4,2,1,5,6,7,8,2] 4 b collections.Counter(a) 5 for c in b&#xff1a; print c,b[c] 转载于:https://www.cnblogs.com/lxs1314/p/7236321.html

MFC入门(一)——MFC是一个编程框架

MFC (Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架&#xff0c;它的目的就是让程序员在此基础上来建立Windows下的应用程序&#xff0c;这是一种相对SDK来说更为简单的方法。因为总体上&#xff0c;MFC框架定义了应用程序的轮廓&#xff0c;并…

2.数据结构笔记学习--线性表基本操作

线性表的结构定义&#xff1a; 顺序表的结构定义&#xff1a; typedef struct {int data[maxSize]; //存放顺序表元素的数组&#xff0c;一般用 int A[maxSize];int length; //存放顺序表的长度,一般用 int n; }SeqList; 单链表结点定义&#xff1a; typedef struct L…

(四)RTL级低功耗设计

前面介绍了系统级的低功耗设计&#xff0c;换句话说就是在系统级降低功耗可以考虑的方面。系统级的低功耗设计&#xff0c;主要是由系统级设计、具有丰富经验的人员实现&#xff0c;虽然还轮不到我们设计&#xff0c;我们了解一下还是比较好的。我们前端设计人员的重点不在系统…

Unity3D 游戏前端开发技能树(思维导图)

如果做游戏也是一种游戏,那么这个游戏的自由度实在是太高了.(导图源文件链接&#xff1a;http://pan.baidu.com/s/1eSHpH5o 密码&#xff1a;qzl5) 最近要用思维导图软件Xmind把自己的思路好好捋一捋,算是温故知新吧. 转载于:https://www.cnblogs.com/qiaogaojian/p/6098962.ht…