1. 通过命令发送/cmd_vel控制底盘移动

- 启动tb3仿真:

  启动:

$ roslaunch tb3_sim_bringup tb3_empty_world.launch

  开启rviz显示:

$ rosrun rviz rviz -d `rospack find tb3_sim_bringup`/rviz/demo.rviz

- 通过命令发布/cmd_vel话题控制底盘:

$ rostopic pub -r 10 /cmd_vel geometry_msgs/Twist '{linear: {x: 0.1, y: 0, z: 0}, angular: {x: 0, y: 0, z: -0.5}}'

  tb3开始移动,效果如下:

  要想停止移动,首先按ctrl+c终止rostopic发送,再输入:

$ rostopic pub -1 /cmd_vel geometry_msgs/Twist '{}'

2. 通过node节点发送/cmd_vel控制底盘移动

- 停止之前的仿真:

  分别按ctrl+c停止之前的节点。

- 从新启动仿真

  启动:

$ roslaunch tb3_sim_bringup tb3_empty_world.launch

  开启rviz显示:

$ rosrun rviz rviz -d `rospack find tb3_sim_bringup`/rviz/demo.rviz

  运行timed_out_and_back.py开启一个新节点。

$ rosrun tb3_sim_nav timed_out_and_back.py

- 代码解析

#!/usr/bin/env pythonimport rospy
from geometry_msgs.msg import Twist
from math import piclass OutAndBack():def __init__(self):# Give the node a namerospy.init_node('out_and_back', anonymous=False)# Set rospy to execute a shutdown function when exiting       rospy.on_shutdown(self.shutdown)# Publisher to control the robot's speedself.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=1)# How fast will we update the robot's movement?rate = 50# Set the equivalent ROS rate variabler = rospy.Rate(rate)# Set the forward linear speed to 0.2 meters per second linear_speed = 0.2# Set the travel distance to 1.0 metersgoal_distance = 1.0# How long should it take us to get there?linear_duration = goal_distance / linear_speed# Set the rotation speed to 1.0 radians per secondangular_speed = 1.0# Set the rotation angle to Pi radians (180 degrees)goal_angle = pi# How long should it take to rotate?angular_duration = goal_angle / angular_speed# Loop through the two legs of the trip  for i in range(2):# Initialize the movement commandmove_cmd = Twist()# Set the forward speedmove_cmd.linear.x = linear_speed# Move forward for a time to go the desired distanceticks = int(linear_duration * rate)for t in range(ticks):self.cmd_vel.publish(move_cmd)r.sleep()# Stop the robot before the rotationmove_cmd = Twist()self.cmd_vel.publish(move_cmd)rospy.sleep(1)# Now rotate left roughly 180 degrees  # Set the angular speedmove_cmd.angular.z = angular_speed# Rotate for a time to go 180 degreesticks = int(goal_angle * rate)for t in range(ticks):           self.cmd_vel.publish(move_cmd)r.sleep()# Stop the robot before the next legmove_cmd = Twist()self.cmd_vel.publish(move_cmd)rospy.sleep(1)    # Stop the robotself.cmd_vel.publish(Twist())def shutdown(self):# Always stop the robot when shutting down the node.rospy.loginfo("Stopping the robot...")self.cmd_vel.publish(Twist())rospy.sleep(1)if __name__ == '__main__':try:OutAndBack()except:rospy.loginfo("Out-and-Back node terminated.")

  该段代码主要实现前进一个指定量的距离,以及转动一个指定量的角度。具体实现思路是通过恒定线速度乘以时间来估计距离,通过恒定角速度乘以时间来估计转动角度。可以看出这是一种非常简单的开环控制,因此在物理机器人实际环境中的应用十分不可靠,但是仿真效果还行。要想实现精确的闭环控制还需要结合/odom话题来加以实现。

3. /odom与/cmd_vel控制的结合

- 停止之前的仿真:

  分别按ctrl+c停止之前的节点。

- 从新启动仿真

  启动:

$ roslaunch tb3_sim_bringup tb3_empty_world.launch

  开启rviz显示:

$ rosrun rviz rviz -d `rospack find tb3_sim_bringup`/rviz/demo.rviz

  运行odom_out_and_back.py开启一个新节点。

$ rosrun tb3_sim_nav odom_out_and_back.py

- 代码解析

#!/usr/bin/env pythonimport rospy
from geometry_msgs.msg import Twist, Point, Quaternion
import tf
from transform_utils import quat_to_angle, normalize_angle
from math import radians, copysign, sqrt, pow, piclass OutAndBack():def __init__(self):# Give the node a namerospy.init_node('out_and_back', anonymous=False)# Set rospy to execute a shutdown function when exiting       rospy.on_shutdown(self.shutdown)# Publisher to control the robot's speedself.cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=5)# How fast will we update the robot's movement?rate = 20# Set the equivalent ROS rate variabler = rospy.Rate(rate)# Set the forward linear speed to 0.15 meters per second linear_speed = 0.15# Set the travel distance in metersgoal_distance = 1.0# Set the rotation speed in radians per secondangular_speed = 0.5# Set the angular tolerance in degrees converted to radiansangular_tolerance = radians(1.0)# Set the rotation angle to Pi radians (180 degrees)goal_angle = pi# Initialize the tf listenerself.tf_listener = tf.TransformListener()# Give tf some time to fill its bufferrospy.sleep(2)# Set the odom frameself.odom_frame = '/odom'# Find out if the robot uses /base_link or /base_footprinttry: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 transform between /odom and /base_link or /base_footprint")rospy.signal_shutdown("tf Exception")  # Initialize the position variable as a Point typeposition = Point()# Loop once for each leg of the tripfor i in range(2):# Initialize the movement commandmove_cmd = Twist()# Set the movement command to forward motionmove_cmd.linear.x = linear_speed# Get the starting position values     (position, rotation) = self.get_odom()x_start = position.xy_start = position.y# Keep track of the distance traveleddistance = 0# Enter the loop to move along a sidewhile distance < goal_distance and not rospy.is_shutdown():# Publish the Twist message and sleep 1 cycle         self.cmd_vel.publish(move_cmd)r.sleep()# Get the current position(position, rotation) = self.get_odom()# Compute the Euclidean distance from the startdistance = sqrt(pow((position.x - x_start), 2) + pow((position.y - y_start), 2))# Stop the robot before the rotationmove_cmd = Twist()self.cmd_vel.publish(move_cmd)rospy.sleep(1)# Set the movement command to a rotationmove_cmd.angular.z = angular_speed# Track the last angle measuredlast_angle = rotation# Track how far we have turnedturn_angle = 0while abs(turn_angle + angular_tolerance) < abs(goal_angle) and not rospy.is_shutdown():# Publish the Twist message and sleep 1 cycle         self.cmd_vel.publish(move_cmd)r.sleep()# Get the current rotation(position, rotation) = self.get_odom()# Compute the amount of rotation since the last loopdelta_angle = normalize_angle(rotation - last_angle)# Add to the running totalturn_angle += delta_anglelast_angle = rotation# Stop the robot before the next legmove_cmd = Twist()self.cmd_vel.publish(move_cmd)rospy.sleep(1)# Stop the robot for goodself.cmd_vel.publish(Twist())def get_odom(self):# Get the current transform between the odom and base framestry:(trans, rot)  = self.tf_listener.lookupTransform(self.odom_frame, self.base_frame, rospy.Time(0))except (tf.Exception, tf.ConnectivityException, tf.LookupException):rospy.loginfo("TF Exception")returnreturn (Point(*trans), quat_to_angle(Quaternion(*rot)))def shutdown(self):# Always stop the robot when shutting down the node.rospy.loginfo("Stopping the robot...")self.cmd_vel.publish(Twist())rospy.sleep(1)if __name__ == '__main__':try:OutAndBack()except:rospy.loginfo("Out-and-Back node terminated.")

  该段代码通过提取gazebo给出的base_frame与odom_frame之间的tf关系,给出机器人的实时位置和姿态角,再通过与起始时刻位置姿态进行对比,得到前进距离和转过角度的实时信息,将其反馈并与/cmd_vel结合,就形成了闭环控制。闭环控制的好处是可以较好的低效地面摩擦、转动轴承摩擦等阻力对于精确控制带来的影响,因此控制精度会有较大提升。但实际物理世界使用过程中odom里程计测量并不完美,会有随时间增长的不可逆的误差累计,因此实际使用过程中的效果也不会很理想,当然通过标定可以降低这些误差,但不能完全消除。
  在gazebo仿真下,以上两个例子的效果区分并不明显,而且与实际物理机器人使用效果有较大不同,其原因是gazebo仿真中目前并没有细化考虑这些阻力和传感器误差。如果希望可以与真实机器人使用结果更为接近,可以在gazebo中加入较大的摩擦阻力和传感器误差。不过这并不是我们作为初学者的学习目的,因此不必过于纠结。

3. 控制命令组合

  最后,我们再尝试一下上面运行命令的组合效果,跑一个正方形的轨迹。这基本上是之前运动命令的直接叠加,因此我们不再进行代码的解析,读者可以自行查看代码。

- 停止之前的仿真:

  分别按ctrl+c停止之前的节点。

- 从新启动仿真

  启动:

$ roslaunch tb3_sim_bringup tb3_empty_world.launch

  开启rviz显示:

$ rosrun rviz rviz -d `rospack find tb3_sim_bringup`/rviz/demo.rviz

  运行nav_square.py开启一个新节点。

$ rosrun tb3_sim_nav nav_square.py

  运行效果:


参考资料:
[1] ROS官方wiki:http://wiki.ros.org/
[2] TurtleBot3电子手册:http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/
[3] 《ROS by Example》 R.Patrick Goebel

通过Gazebo仿真学TurtleBot3(四)——简单的/cmd_vel控制相关推荐

  1. Gazebo仿真记录 Turtlebot3 + D435i

    在Gazebo环境中在Turtlebot3上添加深度相机D435和IMU. 步骤 1.准备工作 创建ROS工作空间,下载turtlebot3相关代码和realsense2_description 模型 ...

  2. turtlebot3 在gazebo仿真下 通过 gmapping slam 建立二维平面地图——全过程

    turtlebot3 在gazebo仿真下 通过 gmapping slam 建立二维平面地图--全过程 ROS中的地图 使用rosbag记录数据 rosbag record rosbag play ...

  3. ROS开发笔记(5)——基于 python 开发 Turtlebot3 Gazebo仿真环境下键盘操控移动机器人(Teleop-bot )

    前文中记录了随机移动机器人的开发过程,本文内容为Turtlebot3 Gazebo仿真环境下Teleop-bot 键盘操控移动机器人,主要包含以下几个部分: 1.键盘驱动(按键驱动发布keys话题) ...

  4. 无人机仿真—PX4编译,gazebo仿真及简单off board控制模式下无人机起飞

    无人机仿真-PX4编译,gazebo仿真及简单off board控制模式下无人机起飞 前言 在上篇记录中,已经对整体的PX4仿真环境有了一定的了解,现如今就要开始对无人机进行起飞等仿真环境工作,在整体 ...

  5. 机器人SLAM与自主导航——(四)Gazebo仿真机器人导航

    (1)创建launch文件 启动Gazebo仿真环境: mrobot_gazebo/launch/mrobot_laser_nav_gazebo.launch 启动move_base导航功能节点: m ...

  6. PX4无人机-Gazebo仿真实现移动物体的跟踪

    原文链接PX4无人机-Gazebo仿真实现移动物体的跟踪末尾有演示视频 这个学期我们有一个智能机器人系统的课设,我们组分配到的题目是<仿真环境下使用无人机及相机跟踪移动物体>,本文主要记录 ...

  7. 【ROS仿真实战】Gazebo仿真平台介绍及安装方法(一)

    文章目录 前言 一.Gazebo简介 二.Gazebo仿真平台的基本概念 三.Gazebo仿真平台的安装方法 四.总结 前言 Gazebo仿真平台是一个广泛应用于机器人研发.测试和教育等领域的开源软件 ...

  8. 【ros学习】14.urdf、xacro机器人建模与rviz、gazebo仿真详解

    一.起因 学校的这学期课程是ros机器人开发实战,我们学习小组也要搞一个自己的机器人模型,我们组又叫葫芦组,所以我就做了个葫芦形状的机器人,虽说有点丑,本来想用maya建模再导入的,奈何不太懂maya ...

  9. 【ROS2仿真-01】运动小车的gazebo仿真

    一.提要 本文对于初学者的Gazebo仿真给出导学,通过学习,能使初学者对ROS2和gazebo配合得到初步认知.本文是系列文档,我们将讲述小车的种种仿真,本篇只是开头,讲最简单的仿真----运动仿真 ...

最新文章

  1. 双一流高校通知「19级硕士秋季学期不开学!」决定引热议,你怎么看?
  2. 微信小程序 --- 图片自适应、本地图片的使用
  3. 运用BT在centos下搭建一个博客论坛
  4. win32 禁用缩放功能_Firefox 73 将引入全局缩放功能,在所有网站都可适用
  5. android布局属性,Android 布局学习之——LinearLayout属性baselineAligned的作用及baseline...
  6. 数学建模 割平面算法求解整数规划基本原理与编程实现
  7. TensorFlow工作笔记003---python异常大全IndentationError: unexpected indent_expected indented block
  8. Java Matcher源码学习记录
  9. 设计模式(十六)迭代器模式 Iterator
  10. 一台计算机安装了fortran语言,win10系统fortran怎么安装_win10系统fortran安装教程
  11. python实现txt内容合并
  12. 【JavaScript】新浪微博批量删除脚本
  13. java 6面骰子_Java实现的简单掷骰子游戏示例
  14. VTN线下体验店 汇聚全球高端品牌 打造非凡购物体验
  15. cdn的费是多少_cdn费用是多少
  16. python的matplotlib库
  17. 从零实现Vue的组件库(十二)- Table 实现
  18. 小程序引用公共js,不看可惜了!!
  19. 感觉自己成长慢,单点突破可以让你成长快10倍
  20. 人不可貌象、小三不可斗量

热门文章

  1. 机动车号牌查询, 在线查询, api 查询
  2. 服务器网口显示感叹号,业务服务器或更新服务器连接失败(认证失败,黄色感叹号)怎么回事?...
  3. Dynamics crm2013 IFD部署后启用多组织
  4. 5.19 对学生按姓名进行随机排序 [原创Excel教程]
  5. 淘客基地免费商城CMS增加拾牛APP下载公告
  6. php小卖铺源码,PHP自动化售货发卡网源码-小酒资源
  7. stm32智能小车设计
  8. maya arnold渲染器产品快速灯光渲染模板文件下载
  9. 什么是条形码?条形码的历史
  10. 华为云宣布将在全球范围内推出区块链服务