
在(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:
- Imports:
rospy: The ROS Python client library for communicating with ROS.PoseStamped,Pose,Point,Quaternion: Messages from thegeometry_msgspackage used to represent position and orientation.
- Function
send_goal:- Takes a publisher (
goal_pub) and awaypointas arguments. - Logs the position of the
waypointto the console. - Publishes the
waypointto the specified topic.
- Takes a publisher (
- Function
main:- Initializes the ROS node with the name
patrol_robot. - Defines a list of
waypointswith specific positions and orientations. - Creates a publisher to send goals to the
/move_base_simple/goaltopic. - Enters a loop to continuously send each waypoint as a goal, waiting 5 seconds between each.
- Handles ROS interruptions gracefully by catching
rospy.ROSInterruptException.
- Initializes the ROS node with the name
- Execution:
- The script calls
main()when executed, starting the patrol behavior.
- The script calls
下面是您的代码,每一行都添加了详细的中文注释。之后,我会给出一些代码修改建议,比如在判定机器人到达巡逻点后再发送下一个巡逻点。
#!/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库来实现简单的状态反馈机制。具体步骤如下:
- 使用
actionlib进行目标状态反馈:- 使用
move_base_msgs/MoveBaseAction来发送目标,并监听其反馈状态。
- 使用
- 代码实现:
#!/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.SimpleActionClient与move_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中定义的消息类型,用于描述机器人的位置和姿态(包括
PoseStamped,Pose,Point, 和Quaternion)。
- 导入ROS中定义的消息类型,用于描述机器人的位置和姿态(包括
(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:目标点的信息(包括位置和姿态)。
- 函数内容:
rospy.loginfo(...):- 输出日志信息到控制台,告诉用户当前发送的目标点的坐标(
x和y)。
- 输出日志信息到控制台,告诉用户当前发送的目标点的坐标(
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表示如果已经有一个同名节点,会自动给节点名后加随机字符以避免冲突。
- 初始化一个ROS节点,节点名称是
定义巡逻点
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):header:frame_id="map":- 指定参考坐标系,这里用的是
map(地图坐标系)。
- 指定参考坐标系,这里用的是
stamp=rospy.Time.now():- 设置时间戳为当前时间。
pose:- 包含两个子字段:
position:目标点的位置,用x、y、z三个坐标描述。orientation:目标点的姿态,用四元数(x, y, z, w)表示方向和旋转。
- 包含两个子字段:
- 示例目标点:
- 第一个点:位置在(1.0, 1.0),没有旋转(四元数
0.0, 0.0, 0.0, 1.0表示无旋转)。 - 第二个点:位置在(3.0, 3.0)。
- 第一个点:位置在(1.0, 1.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. 总结
- 这段代码定义了一个ROS节点
patrol_robot。 - 节点会向主题
/move_base_simple/goal发布目标位置,控制机器人移动到指定点。 - 机器人会在两个目标点(1.0, 1.0) 和 (3.0, 3.0)之间巡逻,每30秒切换一次目标点。
- 如果用户手动停止程序,节点会优雅地退出。
希望这些解释能帮助你更好地理解这段代码!如果还有问题,可以随时提问!
非常好的总结!以下是对上述内容要点的精简回顾与整理,帮助进一步巩固理解:
1. 什么是ROS?
- ROS(Robot Operating System):一个开源的机器人软件框架,提供工具、库和功能,用于构建机器人应用程序。
- 本代码通过ROS实现机器人巡逻功能。
2. 代码结构
代码分为三个主要部分:
- 导入库:
rospy:Python与ROS交互的核心库。- 消息类型:如
PoseStamped,Pose,Point,Quaternion,描述机器人位置和姿态。
- 定义功能函数:
send_goal(goal_pub, waypoint):向指定主题发布机器人目标位置。
- 主程序逻辑:
- 包含节点初始化、定义目标点、设置发布者、目标点循环发送等核心逻辑。
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
- 初始化节点
python复制代码rospy.init_node('patrol_robot', anonymous=True)- 初始化一个名为
patrol_robot的ROS节点。 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:目标点列表(机器人巡逻路径)。- 每个目标点包含:
header:frame_id="map":指定参考坐标系为地图坐标系。stamp=rospy.Time.now():设置时间戳为当前时间。
pose:position:目标点位置坐标(x, y, z)。orientation:目标点姿态(四元数x, y, z, w)。
- 创建发布者
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):确保发布者准备就绪。
- 主题:
- 循环发送目标点
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 |
注意事项
-
确保程序可执行:在运行之前,确保
draw_circles_pro文件有可执行权限。你可以使用以下命令来添加执行权限:bash复制代码chmod +x draw_circles_pro -
中断循环:要中断循环,通常可以按
Ctrl + C。这会发送一个中断信号 (SIGINT) 来终止当前运行的程序。 -
日志文件:如果你想记录程序的输出,可以将输出重定向到一个文件:
bash复制代码while true; do./draw_circles_pro >> output.log 2>&1done这会将标准输出和标准错误输出都记录到
output.log文件中。
选择适合你需求的循环方式,然后在终端中运行即可。

卡顿测试,顺利通过。
1522

被折叠的 条评论
为什么被折叠?



