tf中有C++接口,也有Python接口,tf在Python中的具体实现相对比较简单。
TF的相关数据类型,向量、点、四元数。矩阵的=都可以表示成类似于数组的形式(Tuple、List、Numpy Array表示)。
如:
t = (1.0,1.5,1.0) #平移
q = [1,0,0,0] #四元数
m = numpy.identity(3) #旋转矩阵
t平移数据用Tuple表示的,也可以用List表示(t = [1.0,1.5,1.0]),也能用numpy.array(1.0,1.5,0)表示。数据类型没有特殊的对应,都是通用的,也就没有数据类型的转换。
tf.trabsformations
基本数学运算函数:
函数 | 注释 |
---|---|
euler_matrix(ai,aj,ak,axes=‘sxyz’) | 欧拉角到矩阵 |
euler_from_matrix(matrix,axes=‘sxyz’) | 矩阵到欧拉角 |
euler_quaternion(quaternion,axes=‘sxyz’) | 四元数到欧拉角 |
quaternion_from_euler(ai,aj,ak,axes=‘sxyz’) | 欧拉角到四元数 |
quaternion_matrix(quaternion) | 四元数到矩阵 |
quaternion_from_matrix() | 矩阵到四元数 |
… | … |
在使用函数库的时候,首先要import tf
,tf.transformations给我们提供了基本的数学运算函数,使用较方便。
函数名称 | 函数功能 |
---|---|
tf.transformations.random_quaternion(rand=None) | 返回均匀随机单位四元数 |
tf.transformations.random_rotation_matrix(rand=None) | 返回均匀随机单位旋转矩阵 |
tf.transformations.random_vector(size) | 返回均匀随机单位向量 |
tf.transformations.translation_matrix(v) | 通过向量来求旋转矩阵 |
tf.transformations.translation_from_matrix(m) | 通过旋转矩阵来求向量 |
函数名称 | 函数功能 |
---|---|
tf.transformations.quaternion_about_axis(angle axis) | 通过旋转轴和旋转角返回四元数 |
tf.transformations.quaternion_conjugate(quaternion) | 返回四元数的共轭 |
tf.transformations.quaternion_from_euler() | 从欧拉角和旋转轴,求四元数 |
tf.transformations_from_matrix(matrix) | 从旋转矩阵中,返回四元数 |
tf.transformations.quaternion_multiply(quaternion1,quaternion2) | 两个四元数相乘 |
文件位置:test/scripts/py_coordinate_transformation.py
#!/usr/bin/env python
#coding=utf-8
import rospy
import tf
import math
if __name__ == '__main__':
rospy.init_node("py_coordinate_transformation")
print '第1部分,定义空间点和空间向量'
q = tf.transformations.random_quaternion(rand=None)
print '定义均匀随机四元数:'
print q
m = tf.transformations.random_rotation_matrix(rand=None)
print '定义均匀随机单位旋转矩阵:'
print m
v = tf.transformations.rand_vector(3)
print '定义均匀随机单位向量:'
print v
v_m = tf.transformation.translation_matrix(v)
print '通过向量来求旋转矩阵:'
print v_m
m_v = tf.transformation.translation_from_matrix(m)
print '通过旋转矩阵来求向量:'
print m_v
print '第2部分,定义四元数'
axis_q = tf.transformations.quaternion_about_axis(0.123,(1,0,0))
print '通过旋转轴和旋转角返回四元数:'
print axis_q
n_q = tf.transformations.quaternion_conjugate(q)
print '返回四元数q的共轭:'
print n_q
m_q = tf.transformations.quaternion_from_matrix(m)
print '从旋转矩阵中,返回四元数:'
print m_q
qxq = tf.transformations.quaternion_multiply(q,n_q)
print '两个四元数相乘'
print qxq
方法 | 作用 |
---|---|
canTransform(self,target_frame,source_frame,time) | frame是否相通 |
waitForTransform(self,target_frame,source_target,time,timeout) | 阻塞直到frame相通 |
lookupTransform(self,target_frame,source_frame,time) | 查看相对的tf,返回(trans,quat) |
time参数使用rospy.Time(0),不是rospy::time::now()
方法 | 作用 |
---|---|
chain(target_frame,source_frame,source_time,fixed_frame) | frame的连接关系 |
frameExists(self,frame_id) | frame是否存在 |
getFrameString(self) | 返回所有tf的名称 |
fromTranslationRotation(translation,rotation) | 根据平移和旋转返回4X4矩阵 |
transformPoint(target_frame,point_msg) | 将PointStamped消息转换到新frame下 |
transformPose(target_frame,pose_msg) | 将PoseStamped消息转换到新frame下 |
transformQuaternion(target_frame,quat_msg) | 将QuaternionStamped…返回相同类型 |
… | … |
文件位置:test/scripts/py_tf_listerner.py
#!/usr/bin/env python
#coding=utf-8
import ros
import tf
import math
if __name__ == '__main__':
rospy.init_node("py_tf_listener")
listener = tf.transdormListener() #TransformListener创建后就开始接收tf广播信息,最多可以缓存10s
rate = rospy.Rate(1.0)
print '1. 阻塞直到frame相通'
listener.waitForTransform('/base_link','/link1',rospy.Time(0),rospy.Duration(4)) #rospy.Time(0)不表示0时刻的tf,是指最近的一帧
while not rospy.is_shutdown():
try:
print '2. 监听对应的tf,返回平移和旋转'
(trans,rot) = listener.lookupTransform('/base_link','/link1',rospy.Time(0))
except(tf.lookupException,tf.ConnectivityException,tf.ExtrapolationException):
continue
rospy.loginfo('距离原点的位置:x=%f,y=%f,z=%f\n旋转四元数:w=%f,x=%f,y=%f,z=%f',trans[0],trans[1],trans[2],rot[0],rot[1],rot[2],rot[3])
print '3. 判断两个frame是否相通'
if listener.canTransform('/link1','base_link',rospy.Time(0)):
print 'true'
else:
print 'false'
rate.sleep()
成员函数有两个:
sendTransform(translation,rotation,time,child,parent) #向/tf发布消息
sendTransformMessage(transform) #向/tf发布消息
sendTransform()参数为平移、旋转、时间戳,从父到子的frame流,再发向/tf的topic。
sendTransformMessage(),是发送transform已经封装好了的Message给/tf。
这两种不同的发送方式功能一致。
文件位置:test/scripts/py_tf_broadcaster.py
#!/usr/bin/env python
#coding=utf-8
import rospy
import tf
import math
if __name__ == '__main__':
rospy.init_node('py_tf_broadcaster')
print 'tf.transformBroadcaster类'
print '第1种发布方式:sendTransform(translation,rotation,time,child,parent)'
br = tf.transformBroadcaster()
x = 1.0
y=2.0
z=3.0
roll=0
pitch=0
yaw=1.57
rate = rospy.Rate(1)
while not rospy.is_shutdown():
yaw += 0.1
br.sendTransform((x,y,z),tf.transformations.quaternion_from_euler(roll,pitch,yaw),rospy.Time(0),'base_link','link1')
rate.sleep()
文件位置:test/scripts/py_tf_broadcaster02.py
#!/usr/bin/env python
#coding=utf-8
import rospy
import geometry_msgs.msg
import tf
import math
if __name__ == '__main__':
rospy.init_node('py_tf_broadcaster')
print 'tf.transformBroadcaster类'
print '第2种发布方式:sendTransformMessage(transform)'
br = tf.TransformBroadcaster()
t = geometry_msgs.msg.TransformStamped()
t.header.frame_id = 'base_link'
t.header.stamp = rospy.Time(0)
t.child_frame_id = 'link1';
t.transform.translation.x = 1
t.transform.translation.y = 2
t.transform.translation.z = 3
t.transform.rotation.w = 1
t.transform.rotation.x = 0
t.transform.rotation.y = 0
t.transform.rotation.z = 0
rate = rospy.Rate(1)
while not rtospy.is_shutdown():
br.sendTransformMessage(t)
rate.sleep()
1.根据当前tf树创建一个PDF图
rosrun tf view_frames
首先订阅/tf,订阅5秒,根据这段时间接收道德tf信息,绘制成一张tf tree,再创建一个PDF图
2. 查看当前tf树
rosrun rqt_tf_tree rqt_tf_tree
查询tf tree,与上一个命令区别是该命令动态查询当前tf tree,当前的任何变化都能当即看到,如何时断开连接,捕捉到这些然后通过rqt插件显示出来。
3. 查看两个frame之间的变换关系
rosrun tf tf_echo[reference_frame][target_frame]