ROS路径规划基础教程.docx
- 文档编号:26070104
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:15
- 大小:481.09KB
ROS路径规划基础教程.docx
《ROS路径规划基础教程.docx》由会员分享,可在线阅读,更多相关《ROS路径规划基础教程.docx(15页珍藏版)》请在冰豆网上搜索。
ROS路径规划基础教程
我们主要研究其中最重要的move_base包。
在总体框架图中可以看到,move_base提供了ROS导航的配置、运行、交互接口,它主要包括两个部分:
(1)全局路径规划(globalplanner):
根据给定的目标位置进行总体路径的规划;
(2)本地实时规划(localplanner):
根据附近的障碍物进行躲避路线规划。
一、数据结构
ROS中定义了MoveBaseActionGoal数据结构来存储导航的目标位置数据,其中最重要的就是位置坐标(position)和方向(orientation)。
rosmsgshowMoveBaseActionGoal
[move_base_msgs/MoveBaseActionGoal]:
std_msgs/Headerheader
uint32seq
timestamp
stringframe_id
actionlib_msgs/GoalIDgoal_id
timestamp
stringid
move_base_msgs/MoveBaseGoalgoal
geometry_msgs/PoseStampedtarget_pose
std_msgs/Headerheader
uint32seq
timestamp
stringframe_id
geometry_msgs/Posepose
geometry_msgs/Pointposition
float64x
float64y
float64z
geometry_msgs/Quaternionorientation
float64x
float64y
float64z
float64w
二、配置文件
move_base使用前需要配置一些参数:
运行成本、机器人半径、到达目标位置的距离,机器人移动的速度,这些参数都在rbx1_nav包的以下几个配置文件中:
•base_local_planner_params.yaml
•costmap_common_params.yaml
•global_costmap_params.yaml
•local_costmap_params.yaml
三、全局路径规划(globalplanner)
在ROS的导航中,首先会通过全局路径规划,计算出机器人到目标位置的全局路线。
这一功能是navfn这个包实现的。
navfn通过Dijkstra最优路径的算法,计算costmap上的最小花费路径,作为机器人的全局路线。
将来在算法上应该还会加入A*算法。
四、本地实时规划(localplanner)
本地的实时规划是利用base_local_planner包实现的。
该包使用TrajectoryRollout和DynamicWindowapproaches算法计算机器人每个周期内应该行驶的速度和角度(dx,dy,dthetavelocities)。
base_local_planner这个包通过地图数据,通过算法搜索到达目标的多条路经,利用一些评价标准(是否会撞击障碍物,所需要的时间等等)选取最优的路径,并且计算所需要的实时速度和角度。
其中,TrajectoryRollout和DynamicWindowapproaches算法的主要思路如下:
(1)采样机器人当前的状态(dx,dy,dtheta);
(2)针对每个采样的速度,计算机器人以该速度行驶一段时间后的状态,得出一条行驶的路线。
(3)利用一些评价标准为多条路线打分。
(4)根据打分,选择最优路径。
(5)重复上面过程。
五、ArbotiX仿真——手动设定目标
在这一步,我们暂时使用空白地图(blank_map.pgm),就在空地上进行无障碍仿真。
首先运行ArbotiX节点,并且加载机器人的URDF文件。
roslaunchrbx1_bringupfake_turtlebot.launch
然后运行move_base和加载空白地图的launch文件(fake_move_base_blank_map.launch):
roslaunchrbx1_navfake_move_base_blank_map.launch
该文件的具体内容如下:
--Runthemapserverwithablankmap-->
--Runastatictransformbetween/odomand/map-->
其中调用了fake_move_base.launch文件,是运行move_base节点并进行参数配置。
然后调用rviz就可以看到机器人了。
rosrunrvizrviz-d`rospackfindrbx1_nav`/nav_fuerte.vcg
我们先以1m的速度进行一下测试:
让机器人前进一米:
rostopicpub/move_base_simple/goalgeometry_msgs/PoseStamped\
'{header:
{frame_id:
"base_link"},pose:
{position:
{x:
1.0,y:
0,z:
0},orientation:
{x:
0,y:
0,z:
0,w:
1}}}'
让机器人后退一米,回到原来的位置:
rostopicpub/move_base_simple/goalgeometry_msgs/PoseStamped\
'{header:
{frame_id:
"map"},pose:
{position:
{x:
0,y:
0,z:
0},orientation:
{x:
0,y:
0,z:
0,w:
1}}}'
在rviz中的轨迹图如下:
在机器人移动过程中,有一条蓝色的线(被黄线挡住了)就是机器人的全局规划的路径;红色的箭头是实施规划的路线,会不断更新,有的时候会呈现很大的弧线,那是因为机器人在转向的过程中尽量希望保持平稳的角度。
如果觉得路径规划的精度不够,可以修改配置文件中的pdist_scale参数进行修正。
然后我们可以认为的确定目标位置,点击rviz上方的2DNavGoal按键,然后左键选择目标位置,机器人就开始自动导航了。
六、ArbotiX仿真——带有障碍物的路径规划
首先我们让机器人走一个正方形的路线。
先通过上面的命令,让机器人回到原始位置(0,0,0),然后按reset按键,把所有的箭头清除。
接着运行走正方形路径的代码:
rosrunrbx1_navmove_base_square.py
在rviz中可以看到:
四个顶角的粉色圆盘就是我们设定的位置,正方形比较规则,可见定位还是比较准确的。
然我们先来分析一下走正方形路线的代码:
#!
/usr/bin/envpython
importroslib;roslib.load_manifest('rbx1_nav')
importrospy
importactionlib
fromactionlib_msgs.msgimport*
fromgeometry_msgs.msgimportPose,Point,Quaternion,Twist
frommove_base_msgs.msgimportMoveBaseAction,MoveBaseGoal
fromtf.transformationsimportquaternion_from_euler
fromvisualization_msgs.msgimportMarker
frommathimportradians,pi
classMoveBaseSquare():
def__init__(self):
rospy.init_node('nav_test',anonymous=False)
rospy.on_shutdown(self.shutdown)
#Howbigisthesquarewewanttherobottonavigate?
#设定正方形的尺寸,默认是一米
square_size=rospy.get_param("~square_size",1.0)#meters
#Createalisttoholdthetargetquaternions(orientations)
#创建一个列表,保存目标的角度数据
quaternions=list()
#FirstdefinethecornerorientationsasEulerangles
#定义四个顶角处机器人的方向角度(Eulerangles:
http:
//zh.wikipedia.org/wiki/%E6%AC%A7%E6%8B%89%E8%A7%92)
euler_angles=(pi/2,pi,3*pi/2,0)
#Thenconverttheanglestoquaternions
#将上面的Eulerangles转换成Quaternion的格式
forangleineuler_angles:
q_angle=quaternion_from_euler(0,0,angle,axes='sxyz')
q=Quaternion(*q_angle)
quaternions.append(q)
#Createalisttoholdthewaypointposes
#创建一个列表存储导航点的位置
waypoints=list()
#Appendeachofthefourwaypointstothelist.Eachwaypoint
#isaposeconsistingofapositionandorientationinthemapframe.
#创建四个导航点的位置(角度和坐标位置)
waypoints.append(Pose(Point(square_size,0.0,0.0),quaternions[0]))
waypoints.append(Pose(Point(square_size,square_size,0.0),quaternions[1]))
waypoints.append(Pose(Point(0.0,square_size,0.0),quaternions[2]))
waypoints.append(Pose(Point(0.0,0.0,0.0),quaternions[3]))
#InitializethevisualizationmarkersforRViz
#初始化可视化标记
self.init_markers()
#Setavisualizationmarkerateachwaypoint
#给每个定点的导航点一个可视化标记(就是rviz中看到的粉色圆盘标记)
forwaypointinwaypoints:
p=Point()
p=waypoint.position
self.markers.points.append(p)
#Publishertomanuallycontroltherobot(e.g.tostopit)
#发布TWist消息控制机器人
self.cmd_vel_pub=rospy.Publisher('cmd_vel',Twist)
#Subscribetothemove_baseactionserver
#订阅move_base服务器的消息
self.move_base=actionlib.SimpleActionClient("move_base",MoveBaseAction)
rospy.loginfo("Waitingformove_baseactionserver...")
#Wait60secondsfortheactionservertobecomeavailable
#等待move_base服务器建立
self.move_base.wait_for_server(rospy.Duration(60))
rospy.loginfo("Connectedtomovebaseserver")
rospy.loginfo("Startingnavigationtest")
#Initializeacountertotrackwaypoints
#初始化一个计数器,记录到达的顶点号
i=0
#Cyclethroughthefourwaypoints
#主循环,环绕通过四个定点
whilei<4andnotrospy.is_shutdown():
#Updatethemarkerdisplay
#发布标记指示四个目标的位置,每个周期发布一起,确保标记可见
self.marker_pub.publish(self.markers)
#Intializethewaypointgoal
#初始化goal为MoveBaseGoal类型
goal=MoveBaseGoal()
#Usethemapframetodefinegoalposes
#使用map的frame定义goal的frameid
goal.target_pose.header.frame_id='map'
#Setthetimestampto"now"
#设置时间戳
goal.target_pose.header.stamp=rospy.Time.now()
#Setthegoalposetothei-thwaypoint
#设置目标位置是当前第几个导航点
goal.target_pose.pose=waypoints[i]
#Starttherobotmovingtowardthegoal
#机器人移动
self.move(goal)
i+=1
defmove(self,goal):
#SendthegoalposetotheMoveBaseActionserver
#把目标位置发送给MoveBaseAction的服务器
self.move_base.send_goal(goal)
#Allow1minutetogetthere
#设定1分钟的时间限制
finished_within_time=self.move_base.wait_for_result(rospy.Duration(60))
#Ifwedon'tgetthereintime,abortthegoal
#如果一分钟之内没有到达,放弃目标
ifnotfinished_within_time:
self.move_base.cancel_goal()
rospy.loginfo("Timedoutachievinggoal")
else:
#Wemadeit!
state=self.move_base.get_state()
ifstate==GoalStatus.SUCCEEDED:
rospy.loginfo("Goalsucceeded!
")
definit_markers(self):
#Setupourwaypointmarkers
#设置标记的尺寸
marker_scale=0.2
marker_lifetime=0#0isforever
marker_ns='waypoints'
marker_id=0
marker_color={'r':
1.0,'g':
0.7,'b':
1.0,'a':
1.0}
#Defineamarkerpublisher.
#定义一个标记的发布者
self.marker_pub=rospy.Publisher('waypoint_markers',Marker)
#Initializethemarkerpointslist.
#初始化标记点的列表
self.markers=Marker()
self.markers.ns=marker_ns
self.markers.id=marker_id
self.markers.type=Marker.SPHERE_LIST
self.markers.action=Marker.ADD
self.markers.lifetime=rospy.Duration(marker_lifetime)
self.markers.scale.x=marker_scale
self.markers.scale.y=marker_scale
self.markers.color.r=marker_color['r']
self.markers.color.g=marker_color['g']
self.markers.color.b=marker_color['b']
self.markers.color.a=marker_color['a']
self.markers.header.frame_id='map'
self.markers.header.stamp=rospy.Time.now()
self.markers.points=list()
defshutdown(self):
rospy.loginfo("Stoppingtherobot...")
#Cancelanyactivegoals
self.move_base.cancel_goal()
rospy.sleep
(2)
#Stoptherobot
self.cmd_vel_pub.publish(Twist())
rospy.sleep
(1)
if__name__=='__main__':
try:
MoveBaseSquare()
exceptrospy.ROSInterruptException:
rospy.loginfo("Navigationtestfinished.")
但是,在实际情况中,往往需要让机器人自动躲避障碍物。
move_base包的一个强大的功能就是可以在全局规划的过程中自动躲避障碍物,而不影响全局路径。
障碍物可以是静态的(比如墙、桌子等),也可以是动态的(比如人走过)。
现在我们尝试在之前的正方形路径中加入障碍物。
把之前运行fake_move_base_blank_map.launch的中断Ctrl-C掉,然后运行:
roslaunchrbx1_navfake_move_base_obstacle.launch
然后就会看到在rviz中出现了障碍物。
然后在运行之前走正方形路线的代码:
rosrunrbx1_navmove_base_square.py
这回我们可以看到,在全局路径规划的时候,机器人已经将障碍物绕过去了,下过如下图:
在上图中,黑色的线是障碍物,周围浅色的椭圆形是根据配置文件中的inflation_radius参数计算出来的安全缓冲区。
全局规划的路径基本已经是最短路径了。
在仿真的过程中也可以动态重配置那四个配置文件,修改仿真参数。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ROS 路径 规划 基础教程