ROS云课三分钟-如何借助AI写出一段能跑的ROS导航相关代码-两点巡逻案例

在(1,1)和(3,3)之间持续巡逻。 

视频

ROS云课三分钟-如何借助AI写出一段能跑的ROS导航相关代码-两点巡逻案例

 

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion

def send_goal(goal_pub, waypoint):
    rospy.loginfo("Sending goal to: (%.2f, %.2f)", waypoint.pose.position.x, waypoint.pose.position.y)
    goal_pub.publish(waypoint)

def main():
    rospy.init_node('patrol_robot', anonymous=True)

    waypoints = [
        PoseStamped(
            header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
            pose=Pose(
                position=Point(x=1.0, y=1.0, z=0.0),
                orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
            )
        ),
        PoseStamped(
            header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
            pose=Pose(
                position=Point(x=3.0, y=3.0, z=0.0),
                orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
            )
        )
    ]

    goal_pub = rospy.Publisher('/move_base_simple/goal', PoseStamped, queue_size=10)
    rospy.sleep(1)
    try:
        while not rospy.is_shutdown():
            for waypoint in waypoints:
                send_goal(goal_pub, waypoint)
                rospy.sleep(30)
    except rospy.ROSInterruptException:
        pass

if __name__ == '__main__':
    main()

一键配置Teb仿真

echo "Upgrade Mission Begins."
 
echo "-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
 
mQINBFzvJpYBEADY8l1YvO7iYW5gUESyzsTGnMvVUmlV3XarBaJz9bGRmgPXh7jc
VFrQhE0L/HV7LOfoLI9H2GWYyHBqN5ERBlcA8XxG3ZvX7t9nAZPQT2Xxe3GT3tro
u5oCR+SyHN9xPnUwDuqUSvJ2eqMYb9B/Hph3OmtjG30jSNq9kOF5bBTk1hOTGPH4
K/AY0jzT6OpHfXU6ytlFsI47ZKsnTUhipGsKucQ1CXlyirndZ3V3k70YaooZ55rG
aIoAWlx2H0J7sAHmqS29N9jV9mo135d+d+TdLBXI0PXtiHzE9IPaX+ctdSUrPnp+
TwR99lxglpIG6hLuvOMAaxiqFBB/Jf3XJ8OBakfS6nHrWH2WqQxRbiITl0irkQoz
pwNEF2Bv0+Jvs1UFEdVGz5a8xexQHst/RmKrtHLct3iOCvBNqoAQRbvWvBhPjO/p
V5cYeUljZ5wpHyFkaEViClaVWqa6PIsyLqmyjsruPCWlURLsQoQxABcL8bwxX7UT
hM6CtH6tGlYZ85RIzRifIm2oudzV5l+8oRgFr9yVcwyOFT6JCioqkwldW52P1pk/
/SnuexC6LYqqDuHUs5NnokzzpfS6QaWfTY5P5tz4KHJfsjDIktly3mKVfY0fSPVV
okdGpcUzvz2hq1fqjxB6MlB/1vtk0bImfcsoxBmF7H+4E9ZN1sX/tSb0KQARAQAB
tCZPcGVuIFJvYm90aWNzIDxpbmZvQG9zcmZvdW5kYXRpb24ub3JnPokCVAQTAQgA
PgIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYhBMHPbjHmut6IaLFytPQu1vur
F8ZUBQJgsdhRBQkLTMW7AAoJEPQu1vurF8ZUTMwP/3f7EkOPIFjUdRmpNJ2db4iB
RQu5b2SJRG+KIdbvQBzKUBMV6/RUhEDPjhXZI3zDevzBewvAMKkqs2Q1cWo9WV7Z
PyTkvSyey/Tjn+PozcdvzkvrEjDMftIk8E1WzLGq7vnPLZ1q/b6Vq4H373Z+EDWa
DaDwW72CbCBLWAVtqff80CwlI2x8fYHKr3VBUnwcXNHR4+nRABfAWnaU4k+oTshC
Qucsd8vitNfsSXrKuKyz91IRHRPnJjx8UvGU4tRGfrHkw1505EZvgP02vXeRyWBR
fKiL1vGy4tCSRDdZO3ms2J2m08VPv65HsHaWYMnO+rNJmMZj9d9JdL/9GRf5F6U0
quoIFL39BhUEvBynuqlrqistnyOhw8W/IQy/ymNzBMcMz6rcMjMwhkgm/LNXoSD1
1OrJu4ktQwRhwvGVarnB8ihwjsTxZFylaLmFSfaA+OAlOqCLS1OkIVMzjW+Ul6A6
qjiCEUOsnlf4CGlhzNMZOx3low6ixzEqKOcfECpeIj80a2fBDmWkcAAjlHu6VBhA
TUDG9e2xKLzV2Z/DLYsb3+n9QW7KO0yZKfiuUo6AYboAioQKn5jh3iRvjGh2Ujpo
22G+oae3PcCc7G+z12j6xIY709FQuA49dA2YpzMda0/OX4LP56STEveDRrO+CnV6
WE+F5FaIKwb72PL4rLi4
=i0tj
-----END PGP PUBLIC KEY BLOCK-----" >> ~/ros.asc
 
sudo apt-key add ros.asc
 
sudo apt update
  
echo "Upgrade Mission Completed."
 
echo "Teb Mission Begins."
 
sudo apt install ros-kinetic-stage-ros ros-kinetic-teb-local-planner ros-kinetic-teb-local-planner-tutorials ros-kinetic-global-planner* -y
 
echo "Teb Mission Completed."

启动对应环境

ROS云课三分钟-差动和车式移动机器人导航中的运动学特征-2025更新-优快云博客

roslaunch teb_local_planner_tutorials robot_carlike_in_stage.launch

纯手工导航之前已经讲过了,使用 → 2D Nav Goal就可以实现。

如果用代码实现呢?

用AI直接生成代码,遇到报错不要担心也不要灰心,非常正常。

将问题直接抛给AI,让它思考解决。 


具体过程:

https://yiyan.baidu.com/share/cxro2Il098

代码能跑未必符合要求,只是代码没有语法和逻辑错误。

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion

def send_goal(goal_pub, waypoint):
    rospy.loginfo("Sending goal to: (%.2f, %.2f)", waypoint.pose.position.x, waypoint.pose.position.y)
    goal_pub.publish(waypoint)

def main():
    rospy.init_node('patrol_robot', anonymous=True)

    waypoints = [
        PoseStamped(
            header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
            pose=Pose(
                position=Point(x=1.0, y=1.0, z=0.0),
                orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
            )
        ),
        PoseStamped(
            header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
            pose=Pose(
                position=Point(x=3.0, y=3.0, z=0.0),
                orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
            )
        )
    ]

    goal_pub = rospy.Publisher('/move_base_simple/goal', PoseStamped, queue_size=10)
    rospy.sleep(1)
    try:
        while not rospy.is_shutdown():
            for waypoint in waypoints:
                send_goal(goal_pub, waypoint)
                rospy.sleep(5)
    except rospy.ROSInterruptException:
        pass

if __name__ == '__main__':
    main()


Code Explanation:

  1. Imports:
    • rospy: The ROS Python client library for communicating with ROS.
    • PoseStampedPosePointQuaternion: Messages from the geometry_msgs package used to represent position and orientation.
  2. Function send_goal:
    • Takes a publisher (goal_pub) and a waypoint as arguments.
    • Logs the position of the waypoint to the console.
    • Publishes the waypoint to the specified topic.
  3. Function main:
    • Initializes the ROS node with the name patrol_robot.
    • Defines a list of waypoints with specific positions and orientations.
    • Creates a publisher to send goals to the /move_base_simple/goal topic.
    • Enters a loop to continuously send each waypoint as a goal, waiting 5 seconds between each.
    • Handles ROS interruptions gracefully by catching rospy.ROSInterruptException.
  4. Execution:
    • The script calls main() when executed, starting the patrol behavior.

下面是您的代码,每一行都添加了详细的中文注释。之后,我会给出一些代码修改建议,比如在判定机器人到达巡逻点后再发送下一个巡逻点。

#!/usr/bin/env python

import rospy  # 导入rospy库,用于与ROS系统进行通信
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion  # 导入用于表示位置和姿态的消息类型

def send_goal(goal_pub, waypoint):
    # 在控制台输出要发送的目标位置
    rospy.loginfo("Sending goal to: (%.2f, %.2f)", waypoint.pose.position.x, waypoint.pose.position.y)
    # 通过发布者发布目标位置
    goal_pub.publish(waypoint)

def main():
    # 初始化ROS节点,节点名为'patrol_robot',允许使用匿名名称
    rospy.init_node('patrol_robot', anonymous=True)
    
    # 定义一个包含多个巡逻点的列表
    waypoints = [
        PoseStamped(
            header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),  # 设置坐标帧和时间戳
            pose=Pose(
                position=Point(x=1.0, y=1.0, z=0.0),  # 设置位置坐标
                orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)  # 设置姿态(四元数)
            )
        ),
        PoseStamped(
            header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),  # 设置坐标帧和时间戳
            pose=Pose(
                position=Point(x=3.0, y=3.0, z=0.0),  # 设置位置坐标
                orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)  # 设置姿态(四元数)
            )
        )
    ]

    # 创建一个发布者,用于向'/move_base_simple/goal'主题发布目标
    goal_pub = rospy.Publisher('/move_base_simple/goal', PoseStamped, queue_size=10)
    rospy.sleep(1)  # 暂停一秒以确保发布者设置完成

    try:
        # 持续循环,直到节点被关闭
        while not rospy.is_shutdown():
            # 遍历每个巡逻点
            for waypoint in waypoints:
                send_goal(goal_pub, waypoint)  # 发送当前巡逻点
                rospy.sleep(30)  # 等待30秒后发送下一个巡逻点
    except rospy.ROSInterruptException:
        # 捕获并优雅地处理ROS中断异常
        pass

if __name__ == '__main__':
    # 当脚本被执行时,调用main函数
    main()

python复制代码

#!/usr/bin/env python
import rospy # 导入rospy库,用于与ROS系统进行通信
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion # 导入用于表示位置和姿态的消息类型
def send_goal(goal_pub, waypoint):
# 在控制台输出要发送的目标位置
rospy.loginfo("Sending goal to: (%.2f, %.2f)", waypoint.pose.position.x, waypoint.pose.position.y)
# 通过发布者发布目标位置
goal_pub.publish(waypoint)
def main():
# 初始化ROS节点,节点名为'patrol_robot',允许使用匿名名称
rospy.init_node('patrol_robot', anonymous=True)
# 定义一个包含多个巡逻点的列表
waypoints = [
PoseStamped(
header=rospy.Header(frame_id="map", stamp=rospy.Time.now()), # 设置坐标帧和时间戳
pose=Pose(
position=Point(x=1.0, y=1.0, z=0.0), # 设置位置坐标
orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0) # 设置姿态(四元数)
)
),
PoseStamped(
header=rospy.Header(frame_id="map", stamp=rospy.Time.now()), # 设置坐标帧和时间戳
pose=Pose(
position=Point(x=3.0, y=3.0, z=0.0), # 设置位置坐标
orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0) # 设置姿态(四元数)
)
)
]
# 创建一个发布者,用于向'/move_base_simple/goal'主题发布目标
goal_pub = rospy.Publisher('/move_base_simple/goal', PoseStamped, queue_size=10)
rospy.sleep(1) # 暂停一秒以确保发布者设置完成
try:
# 持续循环,直到节点被关闭
while not rospy.is_shutdown():
# 遍历每个巡逻点
for waypoint in waypoints:
send_goal(goal_pub, waypoint) # 发送当前巡逻点
rospy.sleep(30) # 等待30秒后发送下一个巡逻点
except rospy.ROSInterruptException:
# 捕获并优雅地处理ROS中断异常
pass
if __name__ == '__main__':
# 当脚本被执行时,调用main函数
main()

代码修改建议:

为了在判定机器人到达巡逻点后再发送下一个巡逻点,可以使用actionlib库来实现简单的状态反馈机制。具体步骤如下:

  1. 使用actionlib进行目标状态反馈
    • 使用move_base_msgs/MoveBaseAction来发送目标,并监听其反馈状态。
  2. 代码实现
#!/usr/bin/env python

import rospy
import actionlib
from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion

def send_goal(client, waypoint):
    # 创建新的目标
    goal = MoveBaseGoal()
    goal.target_pose = waypoint

    # 在控制台输出要发送的目标位置
    rospy.loginfo("Sending goal to: (%.2f, %.2f)", waypoint.pose.position.x, waypoint.pose.position.y)
    
    # 发送目标并等待结果
    client.send_goal(goal)
    client.wait_for_result(rospy.Duration(60))  # 等待结果,超时时间为60秒
    
    # 检查目标是否成功到达
    if client.get_result():
        rospy.loginfo("Reached goal")
    else:
        rospy.logwarn("Failed to reach goal")

def main():
    rospy.init_node('patrol_robot', anonymous=True)
    
    # 定义一个包含多个巡逻点的列表
    waypoints = [
        PoseStamped(
            header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
            pose=Pose(
                position=Point(x=1.0, y=1.0, z=0.0),
                orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
            )
        ),
        PoseStamped(
            header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
            pose=Pose(
                position=Point(x=3.0, y=3.0, z=0.0),
                orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
            )
        )
    ]

    # 创建一个action客户端,用于与move_base进行通信
    client = actionlib.SimpleActionClient('move_base', MoveBaseAction)
    client.wait_for_server(rospy.Duration(5))  # 等待move_base服务器启动

    try:
        while not rospy.is_shutdown():
            for waypoint in waypoints:
                send_goal(client, waypoint)  # 发送当前巡逻点
                rospy.sleep(5)  # 等待5秒,确保反馈处理完成
    except rospy.ROSInterruptException:
        pass

if __name__ == '__main__':
    main()

python复制代码

#!/usr/bin/env python
import rospy
import actionlib
from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion
def send_goal(client, waypoint):
# 创建新的目标
goal = MoveBaseGoal()
goal.target_pose = waypoint
# 在控制台输出要发送的目标位置
rospy.loginfo("Sending goal to: (%.2f, %.2f)", waypoint.pose.position.x, waypoint.pose.position.y)
# 发送目标并等待结果
client.send_goal(goal)
client.wait_for_result(rospy.Duration(60)) # 等待结果,超时时间为60秒
# 检查目标是否成功到达
if client.get_result():
rospy.loginfo("Reached goal")
else:
rospy.logwarn("Failed to reach goal")
def main():
rospy.init_node('patrol_robot', anonymous=True)
# 定义一个包含多个巡逻点的列表
waypoints = [
PoseStamped(
header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
pose=Pose(
position=Point(x=1.0, y=1.0, z=0.0),
orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
)
),
PoseStamped(
header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
pose=Pose(
position=Point(x=3.0, y=3.0, z=0.0),
orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
)
)
]
# 创建一个action客户端,用于与move_base进行通信
client = actionlib.SimpleActionClient('move_base', MoveBaseAction)
client.wait_for_server(rospy.Duration(5)) # 等待move_base服务器启动
try:
while not rospy.is_shutdown():
for waypoint in waypoints:
send_goal(client, waypoint) # 发送当前巡逻点
rospy.sleep(5) # 等待5秒,确保反馈处理完成
except rospy.ROSInterruptException:
pass
if __name__ == '__main__':
main()

主要变化:

  • 引入actionlib:用于处理目标的发送和状态反馈。
  • 使用MoveBaseAction:通过actionlib.SimpleActionClientmove_base进行通信,发送目标并等待结果。
  • 检查目标到达状态:在发送下一个目标之前,检查当前目标是否成功到达。

当然!这段代码是用于与机器人操作系统(ROS)进行交互的一个Python脚本,目的是让一个机器人在指定的路径点上巡逻。下面我会逐步解释这段代码的含义和功能。


1. 什么是ROS?

ROS(Robot Operating System)是一个开源的机器人软件框架,它为机器人开发者提供工具、库和功能,用来构建机器人应用。这段代码就是使用了ROS来实现一个简单的巡逻功能。


2. 代码的结构

代码主要由几个部分组成:

  • 导入库
  • 定义功能函数
  • 主程序逻辑

接下来我们详细解释每一部分。


3. 代码详细解释

(1)导入库
 

python复制代码

#!/usr/bin/env python
import rospy # 导入rospy库,用于与ROS系统进行通信
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion # 导入消息类型
  • #!/usr/bin/env python
    • 这是一个shebang行,告诉系统用Python解释器来运行脚本。
  • import rospy
    • 导入rospy库,这是Python与ROS交互的核心库,提供了通信、节点管理等功能。
  • from geometry_msgs.msg import ...
    • 导入ROS中定义的消息类型,用于描述机器人的位置姿态(包括PoseStampedPosePoint, 和 Quaternion)。

(2)定义函数:send_goal
 

python复制代码

def send_goal(goal_pub, waypoint):
# 在控制台输出要发送的目标位置
rospy.loginfo("Sending goal to: (%.2f, %.2f)", waypoint.pose.position.x, waypoint.pose.position.y)
# 通过发布者发布目标位置
goal_pub.publish(waypoint)
  • 函数功能
    • 负责向一个主题(topic)发布机器人的目标位置(目标点)。
  • 参数解释
    • goal_pub:一个发布者对象,负责向ROS主题发送消息。
    • waypoint:目标点的信息(包括位置和姿态)。
  • 函数内容
    1. rospy.loginfo(...)
      • 输出日志信息到控制台,告诉用户当前发送的目标点的坐标(x 和 y)。
    2. goal_pub.publish(waypoint)
      • 把目标点(waypoint)通过发布者发送到指定的主题。

(3)主程序:main
 

python复制代码

def main():
# 初始化ROS节点,节点名为'patrol_robot',允许使用匿名名称
rospy.init_node('patrol_robot', anonymous=True)
  • 节点初始化
    • rospy.init_node('patrol_robot', anonymous=True)
      • 初始化一个ROS节点,节点名称是patrol_robot
      • anonymous=True表示如果已经有一个同名节点,会自动给节点名后加随机字符以避免冲突。

定义巡逻点
 

python复制代码

# 定义一个包含多个巡逻点的列表
waypoints = [
PoseStamped(
header=rospy.Header(frame_id="map", stamp=rospy.Time.now()), # 设置坐标帧和时间戳
pose=Pose(
position=Point(x=1.0, y=1.0, z=0.0), # 设置位置坐标
orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0) # 设置姿态(四元数)
)
),
PoseStamped(
header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
pose=Pose(
position=Point(x=3.0, y=3.0, z=0.0),
orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
)
)
]
  • waypoints是什么?
    • 这是一个包含目标点的列表,机器人会依次移动到这些目标点。
  • 目标点结构(PoseStamped
    1. header
      • frame_id="map"
        • 指定参考坐标系,这里用的是map(地图坐标系)。
      • stamp=rospy.Time.now()
        • 设置时间戳为当前时间。
    2. pose
      • 包含两个子字段:
        • position:目标点的位置,用xyz三个坐标描述。
        • orientation:目标点的姿态,用四元数(x, y, z, w)表示方向和旋转。
  • 示例目标点
    • 第一个点:位置在(1.0, 1.0),没有旋转(四元数0.0, 0.0, 0.0, 1.0表示无旋转)。
    • 第二个点:位置在(3.0, 3.0)。

创建发布者
 

python复制代码

# 创建一个发布者,用于向'/move_base_simple/goal'主题发布目标
goal_pub = rospy.Publisher('/move_base_simple/goal', PoseStamped, queue_size=10)
rospy.sleep(1) # 暂停一秒以确保发布者设置完成
  • 发布者功能
    • 向主题/move_base_simple/goal发送PoseStamped类型的消息。
    • 这个主题通常由导航栈(navigation stack)监听,用来接收目标点。
  • queue_size=10
    • 指定消息队列的大小,以防止消息发送过快而丢失。
  • rospy.sleep(1)
    • 暂停程序1秒,确保发布者在发送消息前已经准备好。

循环发送目标点
 

python复制代码

try:
# 持续循环,直到节点被关闭
while not rospy.is_shutdown():
# 遍历每个巡逻点
for waypoint in waypoints:
send_goal(goal_pub, waypoint) # 发送当前巡逻点
rospy.sleep(30) # 等待30秒后发送下一个巡逻点
except rospy.ROSInterruptException:
# 捕获并优雅地处理ROS中断异常
pass
  • 主循环
    • while not rospy.is_shutdown()
      • 持续运行,直到接收到退出信号(如用户按下Ctrl+C)。
    • for waypoint in waypoints
      • 遍历每个巡逻点,依次发送给发布者。
    • rospy.sleep(30)
      • 等待30秒后发送下一个目标点,模拟机器人在目标点之间移动的时间。
  • 异常处理
    • 捕获rospy.ROSInterruptException,当用户中断程序(如Ctrl+C)时优雅地退出。

程序入口
 

python复制代码

if __name__ == '__main__':
# 当脚本被执行时,调用main函数
main()
  • 检查当前脚本是否是直接运行(而不是被其他脚本导入)。
  • 如果是直接运行,就调用main()函数启动程序。

4. 总结

  1. 这段代码定义了一个ROS节点patrol_robot
  2. 节点会向主题/move_base_simple/goal发布目标位置,控制机器人移动到指定点。
  3. 机器人会在两个目标点(1.0, 1.0) 和 (3.0, 3.0)之间巡逻,每30秒切换一次目标点。
  4. 如果用户手动停止程序,节点会优雅地退出。

希望这些解释能帮助你更好地理解这段代码!如果还有问题,可以随时提问!


非常好的总结!以下是对上述内容要点的精简回顾与整理,帮助进一步巩固理解:


1. 什么是ROS?

  • ROS(Robot Operating System):一个开源的机器人软件框架,提供工具、库和功能,用于构建机器人应用程序。
  • 本代码通过ROS实现机器人巡逻功能

2. 代码结构

代码分为三个主要部分:

  1. 导入库
    • rospy:Python与ROS交互的核心库。
    • 消息类型:如 PoseStampedPosePointQuaternion,描述机器人位置和姿态。
  2. 定义功能函数
    • send_goal(goal_pub, waypoint):向指定主题发布机器人目标位置。
  3. 主程序逻辑
    • 包含节点初始化、定义目标点、设置发布者、目标点循环发送等核心逻辑。

3. 代码详细功能解析

(1) 导入库
 

python复制代码

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import PoseStamped, Pose, Point, Quaternion
  • Shebang (#!/usr/bin/env python)
    • 指定脚本用Python解释器运行。
  • rospy
    • 提供与ROS系统交互的功能,如节点创建、通信等。
  • 消息类型 (geometry_msgs.msg)
    • 用于描述目标点的数据结构(如位置坐标和姿态信息)。

(2) 定义函数:send_goal
 

python复制代码

def send_goal(goal_pub, waypoint):
rospy.loginfo("Sending goal to: (%.2f, %.2f)", waypoint.pose.position.x, waypoint.pose.position.y)
goal_pub.publish(waypoint)
  • 功能:向主题发布机器人目标点。
  • 参数
    • goal_pub:发布者对象。
    • waypoint:目标点(包含位置和姿态信息)。
  • 主要逻辑
    • 使用 rospy.loginfo 输出日志,显示目标点坐标。
    • 调用 goal_pub.publish(waypoint) 发布目标点。

(3) 主程序:main
  1. 初始化节点
     

    python复制代码

    rospy.init_node('patrol_robot', anonymous=True)
    • 初始化一个名为 patrol_robot 的ROS节点。
    • anonymous=True:避免节点名称冲突,自动添加随机后缀。
  2. 定义巡逻点
     

    python复制代码

    waypoints = [
    PoseStamped(
    header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
    pose=Pose(
    position=Point(x=1.0, y=1.0, z=0.0),
    orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
    )
    ),
    PoseStamped(
    header=rospy.Header(frame_id="map", stamp=rospy.Time.now()),
    pose=Pose(
    position=Point(x=3.0, y=3.0, z=0.0),
    orientation=Quaternion(x=0.0, y=0.0, z=0.0, w=1.0)
    )
    )
    ]
    • waypoints:目标点列表(机器人巡逻路径)。
    • 每个目标点包含:
      • header
        • frame_id="map":指定参考坐标系为地图坐标系。
        • stamp=rospy.Time.now():设置时间戳为当前时间。
      • pose
        • position:目标点位置坐标(x, y, z)。
        • orientation:目标点姿态(四元数x, y, z, w)。
  3. 创建发布者
     

    python复制代码

    goal_pub = rospy.Publisher('/move_base_simple/goal', PoseStamped, queue_size=10)
    rospy.sleep(1)
    • 主题/move_base_simple/goal(通常由导航栈监听)。
    • 消息类型PoseStamped
    • queue_size=10:指定消息队列大小。
    • rospy.sleep(1):确保发布者准备就绪。
  4. 循环发送目标点
     

    python复制代码

    try:
    while not rospy.is_shutdown():
    for waypoint in waypoints:
    send_goal(goal_pub, waypoint)
    rospy.sleep(30)
    except rospy.ROSInterruptException:
    pass
    • 主循环
      • 持续运行,直到接收到退出信号(如Ctrl+C)。
      • 遍历 waypoints 列表,依次将目标点发送给发布者。
      • 等待30秒后发送下一个目标点。
    • 异常处理
      • 捕获 rospy.ROSInterruptException,实现优雅退出。

(4) 程序入口
 

python复制代码

if __name__ == '__main__':
main()
  • 检查脚本是否直接运行(非被导入)。
  • 调用 main() 函数启动程序。

4. 总结

  • 节点名称patrol_robot
  • 功能
    • 定义了两个巡逻点((1.0, 1.0) 和 (3.0, 3.0))。
    • 通过发布 /move_base_simple/goal 主题,控制机器人依次移动到目标点。
    • 每30秒切换一次目标点,模拟巡逻行为。
  • 优雅退出
    • 捕获中断信号(如Ctrl+C),实现程序的正常退出。

如果还有进一步的疑问或需要对某些部分进行扩展,欢迎随时提问!


在 Linux 终端中,你可以使用一个循环来反复执行 ./draw_circles_pro 程序。有多种方法可以实现这一点,下面是一些常见的方式:

使用 while 循环

你可以使用一个简单的 while 循环来无限次运行程序,直到你手动中断它(通常是通过按 Ctrl + C):

 

bash复制代码

while true; do
./draw_circles_pro
done

使用 for 循环

如果你想运行程序特定的次数,比如 10 次,可以使用 for 循环:

 

bash复制代码

for i in {1..10}; do
./draw_circles_pro
done

添加延迟

如果需要在每次执行之间添加延迟,比如等待 1 秒,可以使用 sleep 命令:

 

bash复制代码

while true; do
./draw_circles_pro
sleep 1
done

注意事项

  1. 确保程序可执行:在运行之前,确保 draw_circles_pro 文件有可执行权限。你可以使用以下命令来添加执行权限:

     

    bash复制代码

    chmod +x draw_circles_pro
  2. 中断循环:要中断循环,通常可以按 Ctrl + C。这会发送一个中断信号 (SIGINT) 来终止当前运行的程序。

  3. 日志文件:如果你想记录程序的输出,可以将输出重定向到一个文件:

     

    bash复制代码

    while true; do
    ./draw_circles_pro >> output.log 2>&1
    done

    这会将标准输出和标准错误输出都记录到 output.log 文件中。

选择适合你需求的循环方式,然后在终端中运行即可。

卡顿测试,顺利通过。 

### ROS 堂实现两点间自动巡逻机器人操作系统(ROS)环境下,创建一个简单的节来实现在两个指定位置之间的自主巡逻是一项常见的任务。为了完成这一目标,通常会涉及到导航堆栈的应用以及编写自定义逻辑以循环访问预设的目标。 对于具体实施,可以采用`move_base`包作为基础框架的一部分[^1]。此包提供了全局路径规划和局部避障的能力,允许机器人安全地移动到给定的目的地坐标。下面是一个简化版的例子,展示了如何设置这样的巡逻行为: #### 创建巡逻 首先,在Python脚本中导入必要的库初始化ROS: ```python import rospy from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal import actionlib from geometry_msgs.msg import PoseWithCovarianceStamped, Quaternion from tf.transformations import quaternion_from_euler def goal_pose(pose): goal_pose = MoveBaseGoal() goal_pose.target_pose.header.frame_id = 'map' goal_pose.target_pose.pose.position.x = pose[0][0] goal_pose.target_pose.pose.position.y = pose[0][1] goal_pose.target_pose.pose.orientation.w = 1.0 return goal_pose ``` 接着设定要巡访的位置列表,通过action client发送这些目标至`move_base`服务器: ```python if __name__ == '__main__': rospy.init_node('patrol') points = [[(-2,-2),(0,0)], [(2,2), (0,0)]] client = actionlib.SimpleActionClient('move_base',MoveBaseAction) client.wait_for_server() while not rospy.is_shutdown(): for point in points: goal = goal_pose(point) client.send_goal(goal) client.wait_for_result() ``` 上述代码片段展示了一个基本结构用于控制机器人按照预定路线执行巡逻操作。这里假设地图已经建立好且已知起与终的具体坐标;实际应用时可能还需要考虑更多细节如姿态调整、误差处理等[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangrelay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值