ROS代码经验系列-- tf进行位置查询变换
include文件:
#include "tf/transform_broadcaster.h"
#include "tf/transform_listener.h"
#include "tf/message_filter.h"
#include "tf/tf.h"
#include "message_filters/subscriber.h"
某时刻机器人在地图上的位置:
当机器人在移动过程中,tf会不断接收 base_link->odom 的位置关系信息,这些信息是根据时间不断变化并被记录下来的。当其它节点需要获取某个时间点上的 base_link的位置时就可以通过下面的方法查询:
x, y, yaw 就是base_link 在t 时刻在地图上的位置:
bool getOdomPose(tf::Stamped<tf::Pose>& odom_pose,
double& x, double& y, double& yaw,
const ros::Time& t, const std::string& base_link)
{
// Get the robot's pose
tf::Stamped<tf::Pose> ident (tf::Transform(tf::createIdentityQuaternion(),
tf::Vector3(0,0,0)), t, base_link );
try
{
tf_ = new tf::TransformListener();
tf_->transformPose(odom_frame_id_, ident, odom_pose);
}
catch(tf::TransformException e)
{
ROS_WARN("Failed to compute odom pose, skipping scan (%s)", e.what());
return false;
}
x = odom_pose.getOrigin().x();
y = odom_pose.getOrigin().y();
double pitch,roll;
odom_pose.getBasis().getEulerYPR(yaw, pitch, roll); return true;
}
机器人某个位置相对map的位置关系:
机器人是矩形,四个角儿相对中心的位置已知,获取四个角相对map的位置
tf::Stamped<tf::Pose> corner1(
tf::Pose(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.30, -0.45, 0.0)),
ros::Time(0), "base_link");
tf::Stamped<tf::Pose> corner2(
tf::Pose(tf::Quaternion(0, 0, 0, 1), tf::Vector3(0.30, 0.45, 0.0)),
ros::Time(0), "base_link");
tf::Stamped<tf::Pose> corner3(
tf::Pose(tf::Quaternion(0, 0, 0, 1), tf::Vector3(-0.30, -0.45, 0.0)),
ros::Time(0), "base_link");
tf::Stamped<tf::Pose> corner4(
tf::Pose(tf::Quaternion(0, 0, 0, 1), tf::Vector3(-0.30, 0.45, 0.0)),
ros::Time(0), "base_link");
transform_listener = new tf::TransformListener();
tf::Stamped<tf::Pose> transformed_corner_1;
transform_listener.transformPose("map", corner_1, transformed_corner_1);
tf::Stamped<tf::Pose> transformed_corner_2;
transform_listener.transformPose("map", corner_2, transformed_corner_2);
tf::Stamped<tf::Pose> transformed_corner_3;
transform_listener.transformPose("map", corner_3, transformed_corner_3);
tf::Stamped<tf::Pose> transformed_corner_1;
transform_listener.transformPose("map", corner_4, transformed_corner_4);
随机器人移动点在t+1时刻的位置
已知 t 时刻的位置是 pose_old,求t+1 时刻的位置 pose_new
tf_ = new tf::TransformListener();
tf::StampedTransform tx_odom;
try
{
tf_->lookupTransform(base_frame_id_, ros::Time::now(),
base_frame_id_, msg.header.stamp,
global_frame_id_, tx_odom);
}
catch(tf::TransformException e)
{
ROS_WARN("Failed to transform initial pose in time (%s)", e.what());
tx_odom.setIdentity();
} tf::Pose pose_old, pose_new;
tf::poseMsgToTF(msg.pose.pose, pose_old);
pose_new = tx_odom.inverse() * pose_old; // Transform into the global frame
ROS_INFO("Setting pose (%.6f): %.3f %.3f %.3f",
ros::Time::now().toSec(),
pose_new.getOrigin().x(),
pose_new.getOrigin().y(),
getYaw(pose_new));
这里认为global_frame_id是不动的,pose_old和pose_new都是在global_frame_id坐标系下的坐标。但是pose_old描述的物体是随着base_frame_id同步移动的
关于fixed frame的解释:2.3 Transforms in Time
相对角度的转换Quaternion
当base_link代表机器人时,激光扫描仪laser_scan安装的角度与base_link不平行,即激光数据的零度不对应机器人的正前方零度。已知 laser_scan->angle_min 和 laser_scan->angle_increment 为激光数据信息,转换角度到base_link的位置代码如下,该算法可以考虑到激光器上下颠倒安装的情况导致angle_increment为负:
tf::Quaternion q;
q.setRPY(0.0, 0.0, laser_scan->angle_min);
tf::Stamped<tf::Quaternion> min_q(q, laser_scan->header.stamp,
laser_scan->header.frame_id);
q.setRPY(0.0, 0.0, laser_scan->angle_min + laser_scan->angle_increment);
tf::Stamped<tf::Quaternion> inc_q(q, laser_scan->header.stamp,
laser_scan->header.frame_id);
try
{
tf_->transformQuaternion(base_frame_id_, min_q, min_q);
tf_->transformQuaternion(base_frame_id_, inc_q, inc_q);
}
catch(tf::TransformException& e)
{
ROS_WARN("Unable to transform min/max laser angles into base frame: %s",
e.what());
return;
} double angle_min = tf::getYaw(min_q);
double angle_increment = tf::getYaw(inc_q) - angle_min; //考虑到了激光器上下颠倒安装的情况导致为负数
已知 W->B 和B->A的坐标转换,求W->A的坐标转换
ROS 主动蒙特卡罗粒子滤波定位算法 AMCL 解析-- map与odom坐标转换的方法
有时间差的lookupTransform
ros上的详细教程
turtle1和turtle2都是 world 的child frame. turtle1->world 和turtle2->world 的tf都不断发布的,现在需要知道这样的一个transform转换关系:
5秒中之前turtle1相对与现在的turtle2的位置关系
try{
ros::Time now = ros::Time::now();
ros::Time past = now - ros::Duration(5.0);
listener.waitForTransform("/turtle2", now,
"/turtle1", past,
"/world", ros::Duration(1.0));
listener.lookupTransform("/turtle2", now,
"/turtle1", past,
"/world", transform);
得到的转换结果可以这样理解, ( transform.getOrigin().x(), transform.getOrigin().y() ) 是以turtle2为原点的XY平面上turtle1的坐标。
转载:https://blog.csdn.net/crazyquhezheng/article/details/49124115
ROS代码经验系列-- tf进行位置查询变换的更多相关文章
- SLAM+语音机器人DIY系列:(二)ROS入门——7.理解tf的原理
摘要 ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便.我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS ...
- solr与.net系列课程(四)solr查询参数的讲解与.net如何获取solr数据
solr与.net系列课程(四)solr查询参数的讲解与.net如何获取solr数据 上一节我们完成了solr连接数据库,细心的朋友会发现一个问题,就是solr其实和语言没有任何关系,配置完成后任何语 ...
- 【SqlServer系列】表单查询
1 概述 如下几个问题,如果你能解决,请继续往下看,若不能解决,请先复习SQL基础知识,再来阅读本篇文章.本篇文章深度中等左右. Q1:表StudentScores如下,用一条SQL语句查询出每门 ...
- ROS与Matlab系列:一个简单的运动控制
ROS与Matlab系列:一个简单的运动控制 转自:http://blog.exbot.net/archives/2594 Matlab拥有强大的数据处理.可视化绘图能力以及众多成熟的算法函数,非常适 ...
- (原创)高DPI适配经验系列:(四)高DPI适配示例
一.前言 光说不练假把式. 原理说再多,也不如一个例子直观明了.所以本篇文章就来通过一个例子演示一下高DPI适配的流程. 相信看完的你,一定会有所收获! 本文地址:https://www.cnblog ...
- 【百度地图API】建立全国银行位置查询系统(五)——如何更改百度地图的信息窗口内容?
原文:[百度地图API]建立全国银行位置查询系统(五)--如何更改百度地图的信息窗口内容? 摘要: 酷讯.搜房.去哪儿网等大型房产.旅游酒店网站,用的是百度的数据库,却显示了自定义的信息窗口内容,这是 ...
- 【百度地图API】建立全国银行位置查询系统(四)——如何利用百度地图的数据生成自己的标注
原文:[百度地图API]建立全国银行位置查询系统(四)--如何利用百度地图的数据生成自己的标注 摘要: 上一章留个悬念,"如果自己没有地理坐标的数据库,应该怎样制作银行的分布地图呢?&quo ...
- 【百度地图API】建立全国银行位置查询系统(三)——如何在地图上添加银行标注
原文:[百度地图API]建立全国银行位置查询系统(三)--如何在地图上添加银行标注 <摘要>你将在第三章中学会以下知识: 如何在地图上添加带银行logo的标注?(你也可以换成商场logo, ...
- 【百度地图API】建立全国银行位置查询系统(二)——怎样为地图添加控件
原文:[百度地图API]建立全国银行位置查询系统(二)--怎样为地图添加控件 <摘要>你将在第二章中学会以下知识: 使用手写代码的利器——notepad++: 如何为地图添加控件——鱼骨. ...
随机推荐
- RabbitMQ,想说爱你不容易(附详细安装教程)
前言 本文讲述的只是主要是 RabbitMQ 的入门知识,学习本文主要可以掌握以下知识点: MQ 的发展史 AMQP 协议 Rabbit MQ 的安装 Rabbit MQ 在 Java API 中的使 ...
- 区块链学习1:Merkle树(默克尔树)和Merkle根
☞ ░ 前往老猿Python博文目录 ░ 一.简介 默克尔树(Merkle tree,MT)又翻译为梅克尔树,是一种哈希二叉树,树的根就是Merkle根. 关于Merkle树老猿推荐大家阅读<M ...
- PyQt(Python+Qt)学习随笔:QTreeWidgetItem项标记flags相关方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTreeWidgetItem项可以通过flags()返回项的标记,返回值类型为类型Qt.ItemF ...
- 第十二章 Python标准库内置模块和包简介
在<第十章 Python的模块和包>老猿详细介绍了Python模块和包的相关概念,模块和包是Python功能扩展的重要手段,也是Python开放的重要特征.为了提供强大的能力,Python ...
- PyQt(Python+Qt)学习随笔:Qt Designer中窗口对象的windowFilePath属性
windowFilePath属性仅对窗口对象有效,用于关联一个窗口和对应的文件及路径. 当窗口没有设置标题属性的情况下,则窗口标题展示展示windowFilePath对应的文件名的信息(路径信息不展示 ...
- leetcode计划(二)——ps:复习面试题计划+锻炼计划
5.24周日 下周是新的一周,发布任务 一.leetcode计划题目:300,416,494,474(前四个动态规划)(plus:860),232,225,155(后三个栈) 建议之后可以先做:cs- ...
- 学习JUC源码(1)——AQS同步队列(源码分析结合图文理解)
前言 最近结合书籍<Java并发编程艺术>一直在看AQS的源码,发现AQS核心就是:利用内置的FIFO双向队列结构来实现线程排队获取int变量的同步状态,以此奠定了很多并发包中大部分实现基 ...
- Devpress (DxReport)使用ReportDesigner (一) 基本功能
1. Devpress (DxReport)编辑 (1) 新建一个XtraReport. (2) 在报告上点右键添加元素: 元素说明: (1) 其中有报告头,报告尾,页头,页尾,组头,组尾,详细. ...
- 笔记-[SDOI2012]任务安排
笔记-[SDOI2012]任务安排 [SDOI2012]任务安排 \(f_i\) 表示分配到第 \(i\) 个任务的最小费用. 令 \(st_i=\sum_{h=1}^iT_h\),\(sc_i=\s ...
- 题解-Enemy is weak
Enemy is weak 求序列 \(a\{n\}\) 中的三元逆序对数量. 数据范围:\(3\le n\le 1e6\). 这题真是一道又好又水的题,可是我看别人的题解做法真是玄学难懂,于是蒟蒻要 ...