**前情提要:已经建立了odom与base_footprint的关系,并可使用按键检验 **
《教程 Re:Zero ROS (六)—— 获取&编写&检验 -> odom坐标系》
https://blog.csdn.net/Lovely_him/article/details/107948765
教程 Re:Zero ROS (七/完)
—— 建图&定位&导航 - 代价地图&路径规划
slam_gmapping
。如果是Ubuntu16.04/kinetic则可以直接安装在电脑内,版本不一样则可能无法直接安装在电脑上,则需要到git下载源代码到工程内编译。如果你跟着第二篇教程安装了完整的ros桌面包,应该就已经安装了slam_gmapping
。slam_gmapping
https://wiki.ros.org/slam_gmapping
ros-perception /slam_gmapping
https://github.com/ros-perception/slam_gmapping
scan_topic
、base_frame
、odom_frame
分别指激光雷达消息、机器人底盘坐标、里程计坐标。根据中科院的教程中的说明,slam_gmapping 只用到了tf树中的odom
与base
的关系,和激光雷达消息。然后(主要)返回tf树内map
与odom
坐标的关系与一张map地图。gmapping/param
https://wiki.ros.org/gmapping
slam_gmapping参数介绍
https://blog.csdn.net/Csdn_Darry/article/details/78272464
<arg name="scan_topic" default="scan" />
<arg name="base_frame" default="base_footprint"/>
<arg name="odom_frame" default="odom"/>
<node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
<param name="base_frame" value="$(arg base_frame)"/>
<param name="odom_frame" value="$(arg odom_frame)"/>
<param name="map_update_interval" value="0.2"/>
<param name="maxUrange" value="20.0"/>
<param name="maxRange" value="25.0"/>
<param name="sigma" value="0.05"/>
<param name="kernelSize" value="1"/>
<param name="lstep" value="0.05"/>
<param name="astep" value="0.05"/>
<param name="iterations" value="5"/>
<param name="lsigma" value="0.075"/>
<param name="ogain" value="3.0"/>
<param name="lskip" value="0"/>
<param name="minimumScore" value="200"/>
<param name="srr" value="0.01"/>
<param name="srt" value="0.02"/>
<param name="str" value="0.01"/>
<param name="stt" value="0.02"/>
<param name="linearUpdate" value="0.5"/>
<param name="angularUpdate" value="0.436"/>
<param name="temporalUpdate" value="-1.0"/>
<param name="resampleThreshold" value="0.5"/>
<param name="particles" value="80"/>
<param name="xmin" value="-25.0"/>
<param name="ymin" value="-25.0"/>
<param name="xmax" value="25.0"/>
<param name="ymax" value="25.0"/>
<param name="delta" value="0.05"/>
<param name="llsamplerange" value="0.01"/>
<param name="llsamplestep" value="0.01"/>
<param name="lasamplerange" value="0.005"/>
<param name="lasamplestep" value="0.005"/>
<remap from="scan" to="$(arg scan_topic)"/>
node>
与
标签),然后在car_odom.launch
内载入。注意,这个和第五篇教程内的导入控制器参数时,的情况不一样。这次是启动一个节点,内含节点的参数,需要使用.launch
后缀。而上次是纯参数,使用.yaml
后缀。robot_gmapping.launch.xml
就是存放“启动slam节点”代码的文件。car_odom.launch
<launch>
<include file="$(find carpack_control)/launch/car_control.launch" />
<node name="odom_gazebo" pkg="carpack_move" type="odom_gazebo.py"/>
<node name="odom_imu" pkg="carpack_move" type="odom_imu.py"/>
<node name="odom_text" pkg="carpack_move" type="odom_text.py"/>
<include file="$(find carpack_move)/launch/include/robot_gmapping.launch.xml" />
launch>
4)在看中科院的例程时,我发现launch还可以改成后缀为.launch.xml
(文件开头可以不添加) ,且载入方式不变。因为后缀不是
.launch
,所以不能直接启动。这就实现了必须载入到其他launch才可以使用的情况,避免单独启动时发生错误。这一点在第三篇时就讲过了。 所以最终工程结构是如此。
5)编译无误后,启动car_odom.launch
和car_rviz.launch
文件,建图需要在rviz中完成。如果打开rviz可能看不到Map
地图,就是因为没有添加Map
地图。在左下角add
内找到Map
添加即可,添加后左上角选择File -> Save Config
保存rviz配置,以便下次打开时也有Map
。
- 6)接下来就是控制按键,走完全程后,地图就建好了。注意别撞墙,不然会建图错误,最后结果可能错位。这部分教程在另一位dalao帖子内也有简述。建图结束后使用指令保存地图(实现准备好文件夹)。最后工程结构如下。
注意!如果在建图时出现map
地图瞬移一小段位置(视觉表现为一卡一卡的),那其实是因为odom定位偏了,发送了坐标上的跳变。所以小车相对地图的位置发生跳变,又因为地图是靠激光雷达传感器扫描的,如果偏太多时已经扫描过的地方就会和刚扫描的地方对不上,形成错位。(我写的那个odom定位就偏得挺厉害的,最夸张的时候大概能偏一两个格子单位。)
rosrun map_server map_saver -f ~/car_ws/src/carpack_move/map/map_runway
rosrun map_server map_saver -f <路径/文件名>
在ROS下搭建仿真模拟环境,编程控制小车完成定位导航仿真
https://blog.csdn.net/qq_41133375/article/details/106494744
7)最后,我们打开tf树图和节点图查看一下。对比之前,多了一级map
是由/slam_gmapping
节点维持的关系。节点图显示了/slam_gmapping
节点既向tf树发布消息也订阅tf树,符合预期想法。除了rqt_graph
图内显示的4个话题外,/slam_gmapping
节点还发布了其他话题和服务。可以通过wiki-ros查询其作用与使用方法。至此slam
实践完毕。
map_server
https://wiki.ros.org/map_server/
amcl
https://wiki.ros.org/amcl/
/map_server
节点用于提供地图文件。上一节我们已经使用/slam_gmapping
完成建图,rviz内的地图也是由/slam_gmapping
提供。这是在不知道地图,需要建图的情况下使用的。如果已知地图,则需要使用/map_server
节点加载地图,向tf树发送map
与odom
之间的关系。之前的教程也说过,不能同时发送不同数据同一对象的tf消息给tf树,不然tf坐标关系会发送不连续的跳变。而且/slam_gmapping
和/map_server
都会提供/map
话题,那么订阅该话题的节点则会连续的收到两幅地图,一幅已经建好的map,一幅还没建好的map。表现为rviz内Map
一闪一闪的。car_odom.launch
<arg name="map_file" default="$(find carpack_move)/map/map_runway.yaml"/>
<node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" ns="slam"/>
amcl
功能包是提供定位功能的,在中科院的教程视频中由详细提到,建议去查看。使用方法依旧是开启节点,配置参数。依旧大部分参数都是默认的依旧只需要修改开头的几个参数,分别是激光雷达的消息、 tf 树坐标系的名称,还有小车模型的起始位置。robot_amcl.launch.xml
<launch>
<arg name="use_map_topic" default="True"/>
<arg name="scan_topic" default="/scan"/>
<arg name="initial_pose_x" default="-0.5"/>
<arg name="initial_pose_y" default="0.0"/>
<arg name="initial_pose_a" default="0.0"/>
<arg name="odom_frame_id" default="odom"/>
<arg name="base_frame_id" default="base_footprint"/>
<arg name="global_frame_id" default="map"/>
<node pkg="amcl" type="amcl" name="amcl">
<param name="use_map_topic" value="$(arg use_map_topic)"/>
<param name="odom_model_type" value="diff"/>
<param name="odom_alpha5" value="0.1"/>
<param name="gui_publish_rate" value="10.0"/>
<param name="laser_max_beams" value="810"/>
<param name="laser_max_range" value="-1"/>
<param name="min_particles" value="500"/>
<param name="max_particles" value="5000"/>
<param name="kld_err" value="0.05"/>
<param name="kld_z" value="0.99"/>
<param name="odom_alpha1" value="0.2"/>
<param name="odom_alpha2" value="0.2"/>
<param name="odom_alpha3" value="0.2"/>
<param name="odom_alpha4" value="0.2"/>
<param name="laser_z_hit" value="0.5"/>
<param name="laser_z_short" value="0.05"/>
<param name="laser_z_max" value="0.05"/>
<param name="laser_z_rand" value="0.5"/>
<param name="laser_sigma_hit" value="0.2"/>
<param name="laser_lambda_short" value="0.1"/>
<param name="laser_model_type" value="likelihood_field"/>
<param name="laser_likelihood_max_dist" value="2.0"/>
<param name="update_min_d" value="0.1"/>
<param name="update_min_a" value="0.2"/>
<param name="odom_frame_id" value="$(arg odom_frame_id)"/>
<param name="base_frame_id" value="$(arg base_frame_id)"/>
<param name="global_frame_id" value="$(arg global_frame_id)"/>
<param name="resample_interval" value="1"/>
<param name="transform_tolerance" value="1.0"/>
<param name="recovery_alpha_slow" value="0.0"/>
<param name="recovery_alpha_fast" value="0.0"/>
<param name="initial_pose_x" value="$(arg initial_pose_x)"/>
<param name="initial_pose_y" value="$(arg initial_pose_y)"/>
<param name="initial_pose_a" value="$(arg initial_pose_a)"/>
<remap from="/scan" to="$(arg scan_topic)"/>
<remap from="/tf_static" to="/tf_static"/>
node>
launch>
3)再新建robot_amcl.launch.xml
文件存放上列代码。然后,在car_odom.launch
内载入。最后工程结构如下。编译 (其实ros不会编译launch文件,所以修改后不编译也可以) 无误后启动launch文件,打开gazebo与rviz,查看效果。
<launch>
<include file="$(find carpack_control)/launch/car_control.launch" />
<node name="odom_gazebo" pkg="carpack_move" type="odom_gazebo.py"/>
<node name="odom_imu" pkg="carpack_move" type="odom_imu.py"/>
<node name="odom_text" pkg="carpack_move" type="odom_text.py"/>
<arg name="map_file" default="$(find carpack_move)/map/map_runway.yaml"/>
<node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)"/>
<include file="$(find carpack_move)/launch/include/robot_amcl.launch.xml" />
launch>
map
与base_footprint
关系已经变为由/amcl
节点提供,然后在节点图内可以发现/map
话题也改为由/map_server
节点提供。move_base
节点功能是包涵在Navigtion
软件包功能内的。我记得我当初安装ros桌面包时这个软件包是没有安装完全,所以跟着北邮学长教程做实验时总是开启不了导航功能。Navigtion
是ros最基本的功能之一,请一定要安装完全。Navigtion
下还扩展了很多其他小的插件(软件包?),下面教学中用到的几个都要安装。(因为安装途径和方法众多,所以我没有放指令,请自行百度。)navigation
http://wiki.ros.org/navigation/
ROS 学习篇(八)机器人的导航功能--navigation
https://blog.csdn.net/tansir94/article/details/83720740
car_odom.launch
<include file="$(find carpack_move)/launch/include/move_base.launch.xml"/>
move_base.launch.xml
<launch>
<arg name="odom_topic" default="/odom_topic" />
<arg name="laser_topic" default="/scan" />
<arg name="cmd_vel_name" default="/motor_output" />
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<remap from="/odom" to="$(arg odom_topic)"/>
<remap from="/scan" to="$(arg laser_topic)"/>
<remap from="/cmd_vel" to="$(arg cmd_vel_name)"/>
node>
launch>
odom
消息的话题,即之前我们编写的/odom_topic
话题;激光雷达消息的话题,即由gazebo
节点发布的/scan
话题;发布控制输出的话题,这个是move_base
节点发布的/cmd_vel
话题,是根据路径规划的结果返回控制车模的线速度和角速度(或者是角度)。/cmd_vel
话题发布的msg类型属于geometry_msgs/Twist
消息,和之前编写的motor_control
控制器节点接受的motor_output
话题消息类型一致。可以直接将move_base
节点发布的话题/cmd_vel
与motor_control
节点订阅的话题motor_output
相连接。所以值重映射端口,因为节点/软件包内已经写好功能,我们只需要修改个参数就可以了。move_base
节点直接向话题发布消息,达到控制小车的目的。节点还发布和订阅了很多他话题,其作用在wiki-ros内有详细说明,其中还讲到很多其他配置参数,我们一会再介绍与配置。先打开rviz,添加一些显示配置。add -> By topic
后可以在界面内找到,多了/move_base
节点发布的很多内容。我们都加载进rviz,方便我们之后调试实验时查看效果。move_base
http://wiki.ros.org/move_base
move_base
插件。/move_base -> /NavfnROS -> /plan
这个是全局规划插件发布的话题,全局规划路径。因为我们还没有配置参数,所以使用的是默认的NavfnROS
全局规划插件。/move_base -> /TrajectoryPlannerROS -> /global_plan
这个是局部规划插件发布的话题,跟随全局路径的局部规划路径,而下面那个/local_plan
是跟随/global_plan
路径的更小一级的局部规划。即模型小车计划下一个所要到达的坐标点,根据这个可以推算出/cmd_vel
所需的控制消息。(根据资料的个人理解)/move_base -> /current_goal
这个是发布的话题,小车导航移动的目标点,和订阅的目标点/move_base_simple
话题差不多,两者都比较少用。这2个话题都只会显示静态的,相对于小车坐标的目标点消息 /move_base -> /global_costmap
分别是/costmap
全局代价地图和/footprint
设定的小车体积,默认参数是一个小圆圈,绿色显示的。这个是由全局代价地图插件生成的,之后介绍代价地图时再细讲。/move_base -> /local_costmap
分别是/costmap
局部(动态)代价地图和/footprint
设定的小车体积,和全局(静态)代价地图那个一样,因为其实两者是加载了同一份默认参数。这个是由全局代价地图插件生成的,之后介绍代价地图时再细讲。/LaserScan
激光雷达消息与/PoseArray
move_base
发布的,今天一留意才发现原来是是amcl
发布的)add -> By display type
内寻找Axes
添加2次,然后在配置中分别设置为tf树的map
与odom
。然后就能看到2个飘的很厉害的坐标原点了。在跑的时候可以观察其偏移情况,直接反映了定位效果。move_base_params.yaml
,然后加载进/move_base
。具体操作与工程结构如下。move_base.launch.xml
<launch>
<arg name="odom_topic" default="/odom_topic" />
<arg name="laser_topic" default="/scan" />
<arg name="cmd_vel_name" default="/motor_output" />
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<rosparam file="$(find carpack_move)/param/move_base_params.yaml" command="load" />
<remap from="/odom" to="$(arg odom_topic)"/>
<remap from="/scan" to="$(arg laser_topic)"/>
<remap from="/cmd_vel" to="$(arg cmd_vel_name)"/>
node>
launch>
move_base_params.yaml
参数文件内填入以下内容,每个参数的具体含义可以查看以下链接。Setup and Configuration of the Navigation Stack on a Robot
http://wiki.ros.org/navigation/Tutorials/RobotSetup
move_base参数配置
https://blog.csdn.net/L_smartworld/article/details/88661411
【↑↑↑ 含 move_base 多个插件的参数介绍 ↑↑↑】
move_base_params.yaml
# Move base node parameters. For full documentation of the parameters in this file, please see
#
# http://www.ros.org/wiki/move_base
#
shutdown_costmaps: false
controller_frequency: 5.0
controller_patience: 2.0
planner_frequency: 10.0
planner_patience: 10.0
oscillation_timeout: 10.0
oscillation_distance: 0.1
# local planner - default is trajectory rollout
base_local_planner: "teb_local_planner/TebLocalPlannerROS" #"dwa_local_planner/DWAPlannerROS" # #dwa_local_planner/DWAPlannerROS
base_global_planner: "global_planner/GlobalPlanner" #alternatives: "navfn/NavfnROS", carrot_planner/CarrotPlanner,
clearing_rotation_allowed: false
#We plan to integrate recovery behaviors for turtlebot but currently those belong to gopher and still have to be adapted.
## recovery behaviors; we avoid spinning, but we need a fall-back replanning
recovery_behavior_enabled: true
max_planning_retries: -1
#recovery_behaviors:
#- name: 'dwa_local_planner'
#type: 'dwa_local_planner/DWAPlannerROS'
#- name: 'conservative_reset1'
#type: 'clear_costmap_recovery/ClearCostmapRecovery'
#- name: 'aggressive_reset1'
#type: 'clear_costmap_recovery/ClearCostmapRecovery'
#- name: 'clearing_rotation1'
#type: 'rotate_recovery/RotateRecovery'
#- name: 'super_conservative_reset2'
#type: 'clear_costmap_recovery/ClearCostmapRecovery'
#- name: 'conservative_reset2'
#type: 'clear_costmap_recovery/ClearCostmapRecovery'
#- name: 'aggressive_reset2'
#type: 'clear_costmap_recovery/ClearCostmapRecovery'
#- name: 'clearing_rotation2'
#type: 'rotate_recovery/RotateRecovery'
#super_conservative_reset1:
#reset_distance: 3.0
#conservative_reset1:
#reset_distance: 1.5
#aggressive_reset1:
#reset_distance: 0.0
#super_conservative_reset2:
#reset_distance: 3.0
#conservative_reset2:
#reset_distance: 1.5
#aggressive_reset2:
#reset_distance: 0.0
base_local_planner
和base_global_planner
指定了全局规划器和局部规划器,如果不填写的话就是默认的NavfnROS
和TrajectoryPlannerROS
。该参数指定的格式:teb_local_planner/TebLocalPlannerROS
和global_planner/GlobalPlanner
,前面是插件的名字,斜杠后接参数文件的命名空间,即指定加载哪个参数文件。可以根据插件名字在wiki-ros查看相关插件的配置参数teb_local_planner
http://wiki.ros.org/teb_local_planner
global_planner
http://wiki.ros.org/global_planner
controller_frequency
&planner_frequency
是关于控制和刷新频率的,(频率虽越快越好,都是实际其他部件的频率其实是由上限的,比如map
与odom
间定位的刷新频率为20Hz左右,而odom
与base_footprint
间计算的刷新频率为50Hz左右,对比我平时跑智能车时2ms中断来算频率都有200Hz。)参数的频率设置高了也没关系,只是运行时会报出警告提示:更新频率跟不上。add -> By topic
内查看,可以发现之前的NavfnROS
已经变为了GlobalPlanner
,表示我们已经成功改变了参数,将全局路径规划器更改为GlobalPlanner
。然后把rviz左边显示栏中的其中一个Map -> topic
改为/move_base/GlobalPlanner/potential
却发现警告错误,提示因为没有指定map
。这是我们还没开始配置插件GlobalPlanner
的参数,没有给它指定对应的/map
话题,即没有提供地图文件。NavfnROS
已经变为了GlobalPlanner
。(需要在节点图内取消Leaf topic
选项才能显示未被使用话题)1)在讲路径规划器前还需要先配置代价地图,分别为全局(静态)代价地图global_costmap
与局部(动态)代价地图local_costmap
,还有通用的代价地图参数costmap_common_params
。先分别创建对应的文件和修改.launch.xml
文件。
2)共有3个参数文件,其中costmap_common_params.yaml
为通用参数文件,需要加载2次,然后分别挂载不同的命名空间。(我还没试过分开2个文件,分开配置不同的数据会不会好一点呢?) 然后加载局部(动态)代价地图local_costmap
和全局(静态)代价地图global_costmap
参数。其实这个加载顺序无影响,因为肯定是全部加载完才运行的 (类似c语言头文件那样?) 。
move_base.launch.xml
<rosparam file="$(find carpack_move)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find carpack_move)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find carpack_move)/param/local_costmap_params.yaml" command="load" />
<rosparam file="$(find carpack_move)/param/global_costmap_params.yaml" command="load" />
【↓↓↓ 非常详细 ↓↓↓】
学习costmap代价地图
https://blog.csdn.net/weixin_42005898/article/details/100051838
costmap_2d
http://wiki.ros.org/costmap_2d/
costmap_common_params.yaml
通用参数文件内容。用于设定3种不同图层的参数,在帖子学习costmap代价地图内由详细说明,推荐先阅读帖子。footprint
就是小车的大概轮廓。可以参数名表示多边形轮廓。obstacle_layer
设定障碍地图层,常用。inflation_layer
设定膨胀地图层,常用。static_layer
设定静态地图层,常用。注意是否需要修改map
话题名字。observation_sources
参数指订阅的传感器话题,我只用了基本的激光雷达,在之前的节点图中可以看到/move_base
还没有订阅/scan
话题的,开启并指定话题名称后应该就订阅了。(下文验证)obstacle_range
参数和raytrace_range
参数很重要,在局部(动态)代价地图中会用到这2个参数。costmap_common_params.yaml
#---standard pioneer footprint---
#---(in meters)---
#footprint: [ [0.254, -0.0508], [0.1778, -0.0508], [0.1778, -0.1778], [-0.1905, -0.1778], [-0.254, 0], [-0.1905, 0.1778], [0.1778, 0.1778], [0.1778, 0.0508], [0.254, 0.0508] ]
footprint: [ [0.30,0.25], [-0.30,0.25], [-0.30,-0.25], [0.30,-0.25] ]
transform_tolerance: 1
map_type: costmap
obstacle_layer:
enabled: true
obstacle_range: 8.0
raytrace_range: 5.0
inflation_radius: 0.25
track_unknown_space: false
combination_method: 1
observation_sources: laser_scan_sensor
laser_scan_sensor:
data_type: LaserScan
topic: scan
marking: true
clearing: true
#obstacle_range: 0.2
#raytrace_range: 8.0
#inf_is_valid: true
min_obstacle_height: 0.1
max_obstacle_height: 0.3
inflation_layer:
enabled: true
cost_scaling_factor: 20 # exponential rate at which the obstacle cost drops off (default: 10)
inflation_radius: 0.35 # max. distance from an obstacle at which costs are incurred for planning paths.
static_layer:
enabled: true
map_topic: "/map"
global_frame
参数是地图(地图坐标),相对的robot_base_frame
参数为小车底盘坐标。中间跨了一级里程计坐标,比较特殊。obstacle_layer
障碍图层,导致无法壁障,因为无法获取动态障碍,只能一直跟随全局路径规划。全局(静态)代价地图就不需要动态障碍图层了(之前试了一下,好像没什么效果就注释掉了)。注意添加的格式,标签type
的内容是规定好的,而标签name
的内容则是上一个文件——costmap_common_params.yaml
内的参数命名空间的名字。不过按照推荐命名规范,应该也能猜到了,就是去掉下划线改大小写的区别。static_map
参数,如果这个参数改成false
时,还开启了obstacle_layer
图层,则相对于建图效果——在已有的地图上扫描到新的障碍,将新的障碍加进行的地图内——白色自由区域变为障碍。global_costmap_params.yaml
global_costmap:
global_frame: /map
robot_base_frame: /base_footprint
update_frequency: 2.0
publish_frequency: 0.5
static_map: true
rolling_window: false
transform_tolerance: 0.1
origin_x: -0.5
origin_y: 0
plugins:
- {name: static_layer, type: "costmap_2d::StaticLayer"}
- {name: voxel_layer, type: "costmap_2d::VoxelLayer"}
- {name: inflation_layer, type: "costmap_2d::InflationLayer"}
#- {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
global_frame
参数是里程计坐标,和全局(静态)代价地图的global_frame
参数不一样! 重要,plugins
插件参数选择也不一样,局部(动态)代价地图不需要加载static_layer
静态图层,需要加载obstacle_layer
动态图层。这个至关重要,不然就无法利用obstacle_layer/observation_sources
内的激光雷达来动态避障。local_costmap_params.yaml
local_costmap:
global_frame: /odom
robot_base_frame: /base_footprint
update_frequency: 5.0
publish_frequency: 5.0
static_map: false
rolling_window: true
width: 7
height: 7
resolution: 0.050000
origin_x: -5.0
origin_y: 0
transform_tolerance: 0.1
plugins:
- {name: voxel_layer, type: "costmap_2d::VoxelLayer"}
- {name: inflation_layer, type: "costmap_2d::InflationLayer"}
- {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
2D New Goal
,为move_base
添加一个全局路径规划的目标点。这个操作相当于往/move_base_simple/goal
话题发送了一个一次消息。用户可以写一个.py
文件,往/move_base_simple/goal
话题发送目标点,坐到持续导航。这种功能一般用于探索未知区域,没有正在的目标点只能手动一步步探索。/move_base
节点也按预期设定好的发送控制消息,小车动起来啦!能看到小车跟着局部路径规划、全局路径规划行走。看不到下图的绿线效果(路径规划),是因为没有设置好显示对象。之前我们添加配置时选择的是默认的路径规划器生成的话题。改了move_base_params.yaml
内的base_global_planner
参数后,话题名称变了,所以要手动修改。修改完后别忘记保存rviz配置。在下拉的设置里除了可以修改显示的对象,还可以修改显示的颜色、粗细等,请积极探索。/move_base
已经订阅了激光雷达的话题,这是因为局部(动态)代价地图添加 obstacle_layer
障碍层插件,该插件内订阅了/scan
话题。NavfnROS
插件与GlobalPlanner
插件有什么不同。其实我也不是很清楚……在中科院的教程中只简单说明GlobalPlanner
插件比较常用。在下面的帖子中有较详细的解释说明,可以参考一下。ROS: global_planner 整体解析
https://blog.csdn.net/heyijia0327/article/details/45030929
global_planner
http://wiki.ros.org/global_planner
move_base.launch.xml
<rosparam file="$(find carpack_move)/param/global_planner_params.yaml" command="load" />
use_grid_path
沿网格走就直接全局路径生成失败,因为赛道太小,不能沿网格走。global_planner_params.yaml
GlobalPlanner: # Also see: http://wiki.ros.org/global_planner
old_navfn_behavior: false # Exactly mirror behavior of navfn, use defaults for other boolean parameters, default false
use_quadratic: true # Use the quadratic approximation of the potential. Otherwise, use a simpler calculation, default true
use_dijkstra: true # Use dijkstra's algorithm. Otherwise, A*, default true
use_grid_path: false # Create a path that follows the grid boundaries. Otherwise, use a gradient descent method, default false
allow_unknown: false # Allow planner to plan through unknown space, default true
#Needs to have track_unknown_space: true in the obstacle / voxel layer (in costmap_commons_param) to work
planner_window_x: 0.0 # default 0.0
planner_window_y: 0.0 # default 0.0
default_tolerance: 1.0 # If goal in obstacle, plan to the closest point in radius default_tolerance, default 0.0
publish_scale: 100 # Scale by which the published potential gets multiplied, default 100
planner_costmap_publish_frequency: 0.0 # default 0.0
lethal_cost: 200 # default 253
neutral_cost: 50 # default 50
cost_factor: 1.0 # Factor to multiply each cost from costmap by, default 3.0
publish_potential: true # Publish Potential Costmap (this is not like the navfn pointcloud2 potential), default true
visualize_potential: true
teb_local_planner_params
规划器与dwa_local_planner_params
规划器的区别我也不太清楚,另一位参赛大佬写过调参心得,各位可以参考一下。weight_optimaltime
参数的,这个参数决定了局部路径规划与全局路径规划的贴合程度。如果……如果这个参数过大(默认为1,我设置0.2)就无法避障,因为大多数障碍都是放在全局路径规划上的,如果局部规划和全局规划太贴合就也会直接穿过障碍。智能车竞赛——TEB轨迹规划算法的参数调试
https://www.guyuehome.com/9811
<rosparam file="$(find carpack_move)/param/teb_local_planner_params.yaml" command="load" />
move_base
参数列表修改。motor_control.py
关节控制器文件内添加一些判断 motor_control.py
关节控制器很慢,直接减小 odom
里程计坐标系漂移程度,定位更加准,就能慢慢挪过去了。智能车仿真 —— 2020室外光电组仿真指导(一)
https://blog.csdn.net/qq_37668436/article/details/107142166
move_base.launch.xml
文件内容。其中多了base_frame_id
等坐标名字的参数定义,按照推荐操作是:在启动节点时对参数文件内的frame_id
相关参数重新定义,方便移植和避免错误。比如有些不同文件需要同一个值的参数,如果不小心只修改了一遍就报错了。在我的工程中其实由很多我自己加添加的命名空间,在做教程时都去掉了。详细内容可以到git下载我的工程查看。move_base.launch.xml
<launch>
<arg name="base_frame_id" default="base_footprint"/>
<arg name="odom_frame_id" default="odom"/>
<arg name="global_frame_id" default="map"/>
<arg name="odom_topic" default="/odom_topic" />
<arg name="laser_topic" default="/scan" />
<arg name="cmd_vel_name" default="/motor_output" />
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<rosparam file="$(find carpack_move)/param/move_base_params.yaml" command="load" />
<rosparam file="$(find carpack_move)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find carpack_move)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find carpack_move)/param/local_costmap_params.yaml" command="load" />
<rosparam file="$(find carpack_move)/param/global_costmap_params.yaml" command="load" />
<rosparam file="$(find carpack_move)/param/global_planner_params.yaml" command="load" />
<rosparam file="$(find carpack_move)/param/teb_local_planner_params.yaml" command="load" />
<param name="global_costmap/global_frame" value="$(arg global_frame_id)"/>
<param name="global_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
<param name="local_costmap/global_frame" value="$(arg odom_frame_id)"/>
<param name="local_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
<param name="DWAPlannerROS/global_frame_id" value="$(arg odom_frame_id)"/>
<param name="TebLocalPlannerROS/odom_topic" value="$(arg odom_topic)"/>
<remap from="/odom" to="$(arg odom_topic)"/>
<remap from="/scan" to="$(arg laser_topic)"/>
<remap from="/cmd_vel" to="$(arg cmd_vel_name)"/>
node>
launch>
navfn_global_planner_params.yaml
NavfnROS:
visualize_potential: false #Publish potential for rviz as pointcloud2, not really helpful, default false
allow_unknown: true #Specifies whether or not to allow navfn to create plans that traverse unknown space, default true
#Needs to have track_unknown_space: true in the obstacle / voxel layer (in costmap_commons_param) to work
planner_window_x: 0.0 #Specifies the x size of an optional window to restrict the planner to, default 0.0
planner_window_y: 0.0 #Specifies the y size of an optional window to restrict the planner to, default 0.0
default_tolerance: 0.0 #If the goal is in an obstacle, the planer will plan to the nearest point in the radius of default_tolerance, default 0.0
#The area is always searched, so could be slow for big values
dwa_local_planner_params.yaml
DWAPlannerROS:
# Robot Configuration Parameters
max_vel_x: 0.5
min_vel_x: 0
max_vel_y: 0.0
min_vel_y: 0.0
# The velocity when robot is moving in a straight line
max_trans_vel: 0.55
min_trans_vel: 0.1
trans_stopped_vel: 0.1
max_rot_vel: 5.0
min_rot_vel: 0.8
rot_stopped_vel: 0.8
acc_lim_x: 1.0
acc_lim_theta: 2.0
acc_lim_y: 0.0
# Goal Tolerance Parametes
yaw_goal_tolerance: 0.3
xy_goal_tolerance: 0.15
latch_xy_goal_tolerance: false
# Forward Simulation Parameters
sim_time: 0.5
sim_granularity: 0.025
vx_samples: 20
vy_samples: 0
vtheta_samples: 40
# Trajectory Scoring Parameters
path_distance_bias: 32.0
goal_distance_bias: 24.0
occdist_scale: 0.1
forward_point_distance: 0.325
stop_time_buffer: 0.2
scaling_speed: 0.25
max_scaling_factor: 0.2
# Oscillation Prevention Parameters
oscillation_reset_dist: 0.05
# Debugging
publish_traj_pc : true
publish_cost_grid_pc: true
global_frame_id: odom
controller_racecar.yaml
关节控制器参数文件的PID解锁最大速度;然后再细调一下,就能达到40s左右的时间。这成绩是应该能进线下国赛了。这就意味着,今年,学完这个教程,知道怎么建立ros仿真小车工程后,再花几天时间就调局部路径规划器的参数,就能获得”全国智能车汽车竞赛“创意组别——ros组的国赛成绩!…… 才怪呢! 大概……因为线下赛是需要真车模,而且跑完全程,如果是第一次参赛可能还是悬。(2020年08月13日)智能车竞赛——ROS组仿真篇
https://www.guyuehome.com/9697
《 个人空间 》
https://blog.csdn.net/Lovely_him
/*********目录*********/
- 教程 Re:Zero ROS (七/完)
- —— 建图&定位&导航 - 代价地图&路径规划
- 1. slam_gmapping 建图
- 2.map_server 提供地图 & amcl 定位
- 3.Move base 导航
- 4. 配置move_base参数 -> move_base_params
- 5.配置 代价地图 参数 -> costmap_common_params
- 6. 配置 全局路径规划器 参数 -> global_planner_params
- 7. 配置 局部路径规划器 参数 -> teb_local_planner_params
- 8.总结