消息类型:

1. Twist - 线速度角速度

通常被用于发送到/cmd_vel话题,被base controller节点监听,控制机器人运动

geometry_msgs/Twist

geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z

linear.x指向机器人前方,linear.y指向左方,linear.z垂直向上满足右手系,平面移动机器人常常linear.y和linear.z均为0

angular.z代表平面机器人的角速度,因为此时z轴为旋转轴

示例:

#! /usr/bin/env python
'''
Author: xushangnjlh at gmail dot com
Date: 2017/05/22 @package forward_and_back
'''
import rospy
from geometry_msgs.msg import Twist
from math import pi class ForwardAndBack():
def __init__(self):
rospy.init_node('forward_and_back', anonymous=False)
rospy.on_shutdown(self.shutdown)
# this "forward_and_back" node will publish Twist type msgs to /cmd_vel
# topic, where this node act like a Publisher
self.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=5) # parameters
rate = 50
r = rospy.Rate(rate) linear_speed = 0.2
goal_distance = 5
linear_duration = goal_distance/linear_speed angular_speed = 1.0
goal_angular = pi
angular_duration = goal_angular/angular_speed # forward->rotate->back->rotate
for i in range(2):
# this is the msgs variant, has Twist type, no data now
move_cmd = Twist() move_cmd.linear.x = linear_speed #
# should keep publishing
ticks = int(linear_duration*rate)
for t in range(ticks):
# one node can publish msgs to different topics, here only publish
# to /cmd_vel
self.cmd_vel.publish(move_cmd)
r.sleep # sleep according to the rate # stop 1 ms before ratate
move_cmd = Twist()
self.cmd_vel.publish(move_cmd)
rospy.sleep(1) move_cmd.angular_speed.z = angular_speed
ticks = int(angular_duration*rate)
for t in range(ticks):
self.cmd_vel.publish(move_cmd)
r.sleep() self.cmd_vel.publish(Twist())
rospy.sleep(1) def shutdown(self):
rospy.loginfo("Stopping the robot")
self.cmd_vel.publish(Twist())
rospy.sleep(1) if __name__=='__main__':
try:
ForwardAndBack()
except:
rospy.loginfo("forward_and_back node terminated by exception")

2. nav_msgs/Odometry - 里程计(位姿+线速度角速度+各自协方差)

通常,发布到/cmd_vel topic然后被机器人(例如/base_controller节点)监听到的Twist消息是不可能准确地转换为实际的机器人运动路径的,误差来源于机器人内部传感器误差(编码器),标定精度,以及环境影响(地面是否打滑平整);因此我们可以用更准确的Odometry消息类型类获取机器人位姿(/odom到/base_link的tf变换)。在标定准确时,该消息类型与真实的机器人位姿误差大致在1%量级(即使在rviz中显示的依然误差较大)。

还包括

  • 参考系信息,Odometry使用/odom作为parent frame id,/base_link作为child frame id;也就是说世界参考系为/odom(通常设定为起始位姿,固定不动),移动参考系为/base_link(这里还有点不理解,后面来填坑)
  • 时间戳,因此不仅知道运动轨迹,还可以知道对应时间点
Header header
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
# 展开
Header header
uint32 seq
time stamp
string frame_id
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/Pose pose
geometry_msgs/Point position
float64 x
float64 y
float64 z
geometry_msgs/Quaternion orientation
float64 x
float64 y
float64 z
float64 w
float64[36] covariance
geometry_msgs/TwistWithCovariance twist
geometry_msgs/Twist twist
geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z
float64[36] covariance

示例:

运动路径和位姿通过内部的Odometry获取,该Odemetry的位姿通过监听tf坐标系变换获取(/odom和/base_link)

#! /usr/bin/env python
'''
Author: xushangnjlh at gmail dot com
Date: 2017/05/23 @package odometry_forward_and_back
'''
import rospy
from geometry_msgs.msg import Twist, Point, Quaternion
import tf
from rbx1_nav.tranform_utils import quat_to_angle, normalize_angle
from math import pi, radians, copysign, sqrt, pow class Odometry_forward_and_back:
def __init__(self):
rospy.ini_node('odometry_forward_and_back', anonymous=False)
rospy.on_shutdown(self.shutdown) self.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=5) rate = 20
r = rospy.Rate(rate)
linear_speed = 0.2
goal_distance =1.0
angular_speed = 1.0
goal_angle = pi
angular_tolerance = radians(2.5) # Initialize tf listener, and give some time to fill its buffer
self.tf_listener = tf.TransformListener()
rospy.sleep(2) # Set odom_frame and base_frame
self.odom_frame = '/odom' try:
self.tf_listener.waitForTransform(self.odom_frame,
'/base_footprint',
rospy.Time(),
rospy.Duration(1.0))
self.base_frame = '/base_footprint'
except(tf.Exception, tf.ConnectivityException, tf.LookupException):
try:
self.tf_listener.waitForTransform(self.odom_frame,
'/base_link',
rospy.Time(),
rospy.Duration(1.0))
self.base_frame = '/base_link'
except(tf.Exception, tf.ConnectivityException, tf.LookupException):
rospy.loginfo("Cannot find base_frame transformed from /odom")
rospy.signal_shutdown("tf Exception") position = Point() for i in range(2):
move_cmd = Twist()
move_cmd.linear.x = linear_speed
# Initial pose, obtained from internal odometry
(position, rotation) = self.get_odom()
x_start = position.x
y_start = position.y
distance = 0 # Keep publishing Twist msgs, until the internal odometry reach the goal
while distance < goal_distance and not rospy.is_shutdown():
self.cmd_vel.publish(move_cmd)
r.sleep()
(position, rotation) = self.get_odom()
distance = sqrt( pow( (position.x-x_start), 2 ) + \
pow( (position.y-y_start), 2 ) ) # Stop 1 ms before rotate
move_cmd = Twist()
self.cmd_vel.publish(move_cmd)
rospy.sleep(1) move_cmd.angular.z = angular_speed
# should be the current ration from odom
angle_last = rotation
angle_turn = 0
while abs(angle_turn+angular_tolerance) < abs(goal_angle) \
and not rospy.is_shutdown():
self.cmd_vel.publish(move_cmd)
r.sleep()
(position, rotation) = self.get_odom
delta_angle = normalize_angle(rotation - angle_last)
angle_turn += delta_angle
angle_last = rotation move_cmd = Twist()
self.cmd_vel.publish(move_cmd)
rospy.sleep(1) self.cmd_vel.publish(Twist()) def get_dom(self):
try:
(trans, rot) = self.tf_listener.lookupTransfrom(self.odom_frame,
self.base_frame,
rospy.Time(0))
except(tf.Exception, tf.ConnectivityException, tf.LookupException):
rospy.loginfo("TF exception, cannot get_dom()!")
return
# angle is only yaw : RPY()[2]
return (Point(*trans), quat_to_angle(*rot)) def shutdown(self):
rospy.loginfo("Stopping the robot...")
self.cmd_vel.publish(Twist(0))
rospy.sleep(1) if __name__=='__main__':
try:
Odometry_forward_and_back()
except:
rospy.loginfo("Odometry_forward_and_back node terminated!")

注意这里存在tf操作:

self.tf_listener = tf.TransformListener()
rospy.sleep(2)

创建TransformListener对象监听坐标系变换,这里需要sleep 2ms用于tf缓冲。

可以通过以下API获取tf变换,保存在TransformListener对象中,通过lookupTransform获取:

# TransformListener.waitForTransform('ref_coordinate', 'moving_coordinate', rospy.Time(), rospy.Duration(1.0))
self.tf_listener.waitForTransform(self.odom_frame, '/base_footprint', rospy.Time(), rospy.Duration(1.0))
(trans, rot) = self.tf_listener.lookupTransform(self.odom_frame, self.base_frame, rospy.Time(0))

ROS Twist和Odometry消息类型使用(Python)的更多相关文章

  1. ros中文术语表及消息类型表

    前言:整理一些ros常用表格,包括中文术语对照表. 一.中文术语表 二.消息类型表 -END-

  2. ROS多个master消息互通

    需求 有时候我们需要有几个不同的master, 他们之间要交换topic的内容,这时候就不能使用ros自带的设置同一个master的方法. 我们的处理方法是,构造一个client和一个server,他 ...

  3. rabbitmq(中间消息代理)在python中的使用

    在之前的有关线程,进程的博客中,我们介绍了它们各自在同一个程序中的通信方法.但是不同程序,甚至不同编程语言所写的应用软件之间的通信,以前所介绍的线程.进程队列便不再适用了:此种情况便只能使用socke ...

  4. Language Guide (proto3) | proto3 语言指南(一)定义消息类型

    定义消息类型 首先让我们看一个非常简单的例子.假设您想定义一个搜索请求消息格式,其中每个搜索请求都有一个查询字符串.您感兴趣的特定结果页以及每页的结果数.下面是用于定义.proto消息类型的文件. s ...

  5. RabbitMQ消息中介之Python使用

    本文介绍RabbitMQ在python下的基本使用 1. RabbitMQ安装,安装RabbitMQ需要预安装erlang语言,Windows直接下载双击安装即可 RabbitMQ下载地址:http: ...

  6. Activemq消息类型

    Activemq消息类型JMS规范中的消息类型包括TextMessage.MapMessage.ObjectMessage.BytesMessage.和StreamMessage等五种.ActiveM ...

  7. 分析器错误消息: 类型“test.test.testx”不明确: 它可能来自程序集“F:\testProject\bin\test.test.DLL”或程序集“F:\testProject\bin \testProject.DLL”。请在类型名称中显式指定程序集。

    问题描述: RT 分析器错误消息: 类型“test.test.testx”不明确: 它可能来自程序集“F:\testProject\bin\test.test.DLL”或程序集“F:\testProj ...

  8. ActiveMQ之二--JMS消息类型

    1.前言 //发送文本消息 session.createTextMessage(msg); //接受文本消息 public void onMessage(Message msg) { TextMess ...

  9. JMS消息类型模型

    JMS有两种消息类型模型,一种是P2P(Point To Point), 另一种是Pub/Sub(Publisher/Subscriber),二者之间的主要区别在于消息是否支持重复消费. P2P模型中 ...

随机推荐

  1. 六种排序算法的JavaScript实现以及总结

    最近几天在系统的复习排序算法,之前都没有系统性的学习过,也没有留下过什么笔记,所以很快就忘了,这次好好地学习一下. 首先说明为了减少限制,以下代码通通运行于Node V8引擎而非浏览器,源码在我的Gi ...

  2. 阅读SessionFactory源码

    一.阅读类注释 ①.SessionFactory的主要任务是创建Session的实例.通常一个应用程序只有一个单一的SessionFactory对象,而且线程从这个SessionFactory中获取S ...

  3. C++、Java、Objective-C、Swift 二进制兼容测试

    鉴于目前动态库在iOS App中使用越来越广泛,二进制的兼容问题可能会成为一个令人头疼的问题.本文主要对比一下C++.Java.Objecive-C和Swift的二进制兼容问题. iOS端动态库使用情 ...

  4. jquery ajax 标准写法

    $.ajax({ url:"http://www.microsoft.com", //请求的url地址 dataType:"json", //返回格式为json ...

  5. 调节Ubuntu分辨率

    列出当前支持的分辨率 使用 xrandr 命令新增显示模式 至此分辨率更改完成 重启后会失效 在 ~/.profile 最末尾添加修改分辨率的命令

  6. 20145238-荆玉茗 《网络对抗》-逆向及Bof基础实践

    20145238荆玉茗<网络对抗>-逆向及Bof基础实践 1 逆向及Bof基础实践说明 1.1 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:m ...

  7. 用@ExceptionHandler 来进行异常处理

    有时候我们想统一处理一个Controller中抛出的异常怎么搞呢? 直接在Controller里面加上用@ExceptionHandler标注一个处理异常的方法像下面这样子 @ExceptionHan ...

  8. sqlserver事务怎么开启 怎么提交 怎么回滚

    1.自动transaction每句statement都是一个transaction.例一个update指令更新多笔纪录, 要就全部成功, 只要失败,全部会回复原值. 2.ExplicitTransac ...

  9. Faster Alternatives to glReadPixels and glTexImage2D in OpenGL ES

    In the development of Shou, I’ve been using GLSL with NEON to manipulate image rotation, scaling and ...

  10. 【转载】对C#DateTime的一些扩展,计算周内第一天,最后一天

    /// <summary> /// DateTime的一些扩展 /// </summary> public class DateTime2 { /// <summary& ...