杰瑞科技汇

python脚本turtlebot

核心概念:ROS 和 Python

在开始写代码之前,你必须理解几个核心概念:

  1. ROS (Robot Operating System):这不是一个真正的操作系统,而是一个用于编写机器人软件的灵活框架,它提供了硬件抽象、设备驱动、库、可视化工具、消息传递、包管理等功能。
  2. 节点:一个可执行文件,是 ROS 执行计算的基本单元,你的 Python 脚本就是一个节点。
  3. 话题:节点之间用于发送和接收数据的异步通信机制,你可以把它想象成一个广播电台,一个节点“发布”消息到某个“频道”(话题),其他节点可以“订阅”这个频道来接收消息。
  4. 消息:一个数据结构,用于在节点之间传递,速度消息包含线速度和角速度。
  5. :一个包含 ROS 节点、库、配置文件等的软件单元,用于组织代码。

前提条件

在运行任何 Python 脚本之前,请确保你已经:

  1. 设置好 TurtleBot:你已经成功配置了你的 TurtleBot (TurtleBot3),并且可以通过 roscoreturtlebot3_core 等节点让它正常工作。

  2. 安装必要的 Python 库

    # ROS 已经内置了 rospy,但你可能需要安装一些额外的工具
    sudo apt-get install ros-noetic-turtlebot3-msgs
    sudo apt-get install ros-noetic-turtlebot3
  3. 设置环境变量:每次打开新终端时,都需要加载 ROS 和 TurtleBot 的环境变量。

    # 加载 ROS Noetic 环境 (如果你的 ROS 版本是 Noetic)
    source /opt/ros/noetic/setup.bash
    # 加载你的工作空间环境 (如果你有的话)
    source ~/catkin_ws/devel/setup.bash
    # 设置 TurtleBot3 型号 (Burger, Waffle, Waffle Pi)
    export TURTLEBOT3_MODEL=burger

    提示:为了避免每次都输入,可以将最后两行添加到你家目录下的 .bashrc 文件中。


第一个 Python 脚本:发布速度命令

这是最基础也是最常用的操作:让机器人移动,我们通过向 /cmd_vel 话题发布 geometry_msgs/Twist 类型的消息来控制机器人。

创建一个 ROS 包

你需要一个地方来存放你的代码,在 catkin_ws/src 目录下创建一个新的包。

cd ~/catkin_ws/src
catkin_create_pkg my_turtlebot_scripts rospy std_msgs geometry_msgs

这会创建一个名为 my_turtlebot_scripts 的包,并依赖了 rospy (ROS Python 库)、std_msgs (标准消息) 和 geometry_msgs (几何消息,如 Twist)。

编写 Python 脚本

my_turtlebot_scripts 包中创建一个 scripts 文件夹,并在里面创建你的 Python 脚本。

cd my_turtlebot_scripts
mkdir scripts
cd scripts
touch move_forward.py

用你喜欢的编辑器打开 move_forward.py 并粘贴以下代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from geometry_msgs.msg import Twist
def move_turtlebot():
    """
    一个简单的函数,用于让 TurtleBot 向前移动。
    """
    # 1. 初始化 ROS 节点
    # anonymous=True 参数确保节点名称是唯一的,即使你多次运行同一个脚本
    rospy.init_node('move_forward_node', anonymous=True)
    # 2. 创建一个 Publisher 对象
    # 它将发布消息到 '/cmd_vel' 话题
    # Twist 是消息类型,队列大小为 10
    pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
    # 3. 设置循环的频率
    # 10Hz 意味着这个循环每秒运行 10 次
    rate = rospy.Rate(10)
    # 4. 创建一个 Twist 消息对象
    # 这个对象将包含我们想要发送的速度命令
    move_cmd = Twist()
    # 5. 设置速度值
    # Twist 消息有两个主要部分:linear (线性) 和 angular (角速度)
    # 我们只设置线性速度的 x 分量
    move_cmd.linear.x = 0.2  # 前进速度 (m/s)
    move_cmd.linear.y = 0.0
    move_cmd.linear.z = 0.0
    move_cmd.angular.x = 0.0
    move_cmd.angular.y = 0.0
    move_cmd.angular.z = 0.0  # 角速度 (rad/s)
    # 6. 在节点运行时持续发布消息
    # rospy.is_ok() 在按下 Ctrl+C 时会返回 False
    while not rospy.is_shutdown():
        rospy.loginfo("Moving forward...")
        pub.publish(move_cmd)
        rate.sleep() # 确保循环以设定的频率运行
if __name__ == '__main__':
    try:
        move_turtlebot()
    except rospy.ROSInterruptException:
        pass

使脚本可执行

chmod +x move_forward.py

运行脚本

你可以运行它了。打开三个终端

终端 1:启动 ROS 核心

roscore

终端 2:启动 TurtleBot3 模拟器 (或真实机器人) 如果你使用的是 Gazebo 仿真器:

# 启动仿真环境
roslaunch turtlebot3_gazebo turtlebot3_world.launch
# 如果你使用的是真实机器人,则运行:
# roslaunch turtlebot3_bringup turtlebot3_robot.launch

终端 3:运行你的 Python 脚本

# 确保你在 catkin_ws 的根目录下
source devel/setup.bash
rosrun my_turtlebot_scripts move_forward.py

你应该会看到你的 TurtleBot (或仿真中的机器人) 开始向前移动,按 Ctrl+C 可以停止脚本,机器人也会停止。


进阶示例:基于键盘控制的避障

这个例子更复杂一些,它将订阅激光雷达的数据,并根据数据来决定是前进还是转向避障。

编写脚本

scripts 文件夹中创建 obstacle_avoidance.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan
class ObstacleAvoider:
    def __init__(self):
        # 初始化节点
        rospy.init_node('obstacle_avoider_node', anonymous=True)
        # 创建 Publisher 和 Subscriber
        self.vel_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
        self.scan_sub = rospy.Subscriber('/scan', LaserScan, self.scan_callback)
        # 设置循环频率
        self.rate = rospy.Rate(10)
        # 速度命令对象
        self.cmd = Twist()
        # 安全距离 (单位: 米)
        self.safe_distance = 0.5
    def scan_callback(self, scan_data):
        """
        处理接收到的激光雷达数据
        """
        # 激光雷达数据是一个数组,索引 0 是正前方
        # 我们取前方一小片区域的平均值
        front_distance = scan_data.ranges[0]
        rospy.loginfo("Front distance: {:.2f} m".format(front_distance))
        if front_distance < self.safe_distance:
            # 如果检测到障碍物,后退并转向
            rospy.logwarn("Obstacle detected! Turning...")
            self.cmd.linear.x = -0.1  # 后退
            self.cmd.angular.z = 0.5  # 转向
        else:
            # 如果没有障碍物,前进
            rospy.loginfo("Path is clear. Moving forward...")
            self.cmd.linear.x = 0.2  # 前进
            self.cmd.angular.z = 0.0  # 不转向
    def run(self):
        """
        主循环,持续发布速度命令
        """
        while not rospy.is_shutdown():
            self.vel_pub.publish(self.cmd)
            self.rate.sleep()
if __name__ == '__main__':
    try:
        avoider = ObstacleAvoider()
        avoider.run()
    except rospy.ROSInterruptException:
        pass

运行脚本

同样,打开三个终端

终端 1:

roscore

终端 2: (启动仿真器,它已经包含了激光雷达传感器)

roslaunch turtlebot3_gazebo turtlebot3_world.launch

终端 3: (运行新的脚本)

rosrun my_turtlebot_scripts obstacle_avoidance.py

你的机器人会向前移动,当它接近墙壁或障碍物时,会自动后退并转向,以避开障碍物。


调试和可视化工具

  1. rostopic:一个强大的命令行工具,用于查看和调试话题。

    • rostopic list:列出所有活动的话题。
    • rostopic echo /scan:实时打印 /scan 话题的内容(激光雷达数据)。
    • rostopic echo /cmd_vel:实时打印你发布的速度命令。
    • rostopic hz /scan:检查 /scan 话题的发布频率。
  2. rqt_graph:可视化 ROS 节点和话题的连接关系。 在一个终端中运行:

    rosrun rqt_graph rqt_graph

    你会看到一个动态图,清晰地显示了你的 Python 节点 (/move_forward_node) 如何连接到 /cmd_vel 话题,以及 /scan 节点如何连接到你的 obstacle_avoider_node

控制 TurtleBot 的 Python 脚本遵循一个固定的模式:

  1. rospy.init_node(...):初始化你的节点。
  2. rospy.Publisher(...):创建发布者,用于发送命令(如速度)。
  3. rospy.Subscriber(...):创建订阅者,用于接收传感器数据(如激光雷达、摄像头图像)。
  4. while not rospy.is_shutdown()::创建主循环。
  5. rate.sleep():在循环中使用,以控制代码执行频率。
  6. pub.publish(message):在循环中发布消息。
  7. 在回调函数中处理数据:订阅者接收到的数据会自动传递给你定义的回调函数。

从发布简单的速度命令开始,然后尝试订阅传感器数据,这是掌握 ROS 和 TurtleBot 编程的关键一步,祝你玩得开心!

分享:
扫描分享到社交APP
上一篇
下一篇