赞
踩
本篇博客字数较多,难免存在争议、问题,我们评论区多交流。
!!! 表示解释的不好,存在问题,欢迎各位小伙伴评论留言。
在调整新机器人上的导航包时遇到的大部分问题都在本地规划器调谐参数之外的区域。机器人的里程计,定位,传感器以及有效运行导航的其他先决条件常常会出错。所以,第一件事是确保机器人本身准备好了,具有导航能力。这包括三个组件检查:距离传感器、里程计、定位。
距离传感器
如激光雷达、距离传感器等,传感器没有正常工作,无法提供信息,那么导航将无法顺利完成。
可以尝试在rviz中查看传感器信息,是否可以通过话题Topic获取传感器信息,并以预期的速度获取。
里程计
往往机器人无法正确定位,问题根源不在Amcl算法调参,而是里程计不可靠。
可以通过两个健全检查,验证里程计是否可靠。
第一个测试检查角速度是否合理 :打开rviz,将坐标系设置为“odom”,显示机器人提供的激光扫描, 设置topic的延时时间(decay time)为20s左右,然后原地旋转,然后,看看扫描出来的边线在随后的旋转中如何相互匹配。理想情况下,每次扫描将刚好落在相互的顶端,会重叠在一起,但是有些旋转漂移是预期的,所以我只是确保扫描之间误差,不会超过一度或两度以上。
第二个测试检查线速度是否合理:机器人放置在与距离墙壁几米远地方,然后以上面相同的方式设置rviz。接着控制机器人向墙壁前进,从rviz中聚合的激光扫描看看扫描出来边线的厚度。理想情况下,墙体应该看起来像一个扫描,但我只是确保它的厚度不超过几厘米。如果显示扫描边线的分散在半米以上,但有些可能是错误的测距。
定位
假设里程计和距离传感器都可靠,建图结果和Amcl定位结果通常并不会太糟糕。首先,我将运行gmapping或karto,并操纵机器人来生成环境地图。然后,我将在该地图上进行Amcl定位,良好的定位效果应该是可视化激光扫描和环境地图,机器人移动过程中激光扫描保持与环境地图很好地匹配。
这项工作并不像看起来那么简单。如果对概念和推理了解不清楚,可能会随意尝试,这将浪费大量的时间。 本文旨在引导读者正确微调导航参数。当在设置一些关键参数的时候,需要知道“如何”和“为什么”。
在ROS中,实现导航功能需要使用到的三个包是:
(1) move_base:根据参照的消息进行路径规划,使移动机器人到达指定的位置。
(2) amcl:根据已经有的地图进行定位。
(3) gmapping:根据激光数据(或者深度数据模拟的激光数据)建立地图。
结构框架图:
move_base的输入topic:
以上四个Topic是必须持续提供给导航系统的,下面这个是可随时发布的topic:
move_base包内包括三种插件:base_local_planner、base_global_planner和recovery_behavior,这三种插件都得用户指定,否则系统会指定默认值。
base_local_planner插件:
base_global_planner插件:
recovery_behavior插件:
DWA与Trajectory Rollout的区别主要是在机器人的控制空间采样差异。Trajectory Rollout采样点来源于整个前向模拟阶段所有可用速度集合,而DWA采样点仅仅来源于一个模拟步骤中的可用速度集合。这意味着相比之下DWA是一种更加有效算法,因为其使用了更小采样空间;然而对于低加速度的机器人来说可能Trajectory Rollout更好,因为DWA不能对常加速度做前向模拟。
当前上面这些插件只是官方实现的,我们也可以来实现自己的规划算法,以插件的形式包含进move_base,这样就可以来改进这些路径规划算法了。
move_base_params.yaml,这个文件可有可无,因为可以直接在launch文件中直接设定如base_global_planner / base_local_planner,如
<param name="base_global_planner" value="global_planner/GlobalPlanner" />
<param name="planner_frequency" value="1.0" />
<param name="planner_patience" value="5.0" />
<param name="base_local_planner" value="dwa_local_planner/DWAPlannerROS" />
<param name="controller_frequency" value="5.0" />
<param name="controller_patience" value="5.0" />
下面介绍move_base_params.yaml
# move_base软件包的通用配置参数,参数意义如下: # shutdown_costmaps:当move_base在不活动状态时,是否关掉costmap # controller_frequency:向底盘控制移动话题cmd_vel发送命令的频率,单位Hz # controller_patience:在空间清理操作执行前,控制器花多长时间等有效控制下发 # planner_frequency:全局规划操作的执行频率.如果设置为0.0,则全局规划器仅 # 在接收到新的目标点或者局部规划器报告路径堵塞时才会重新执行规划操作 # planner_patience:在空间清理操作执行前,留给规划器多长时间来找出一条有效规划 # oscillation_timeout:执行修复机制前,允许振荡的时长 # oscillation_distance:来回运动在多大距离以上不会被认为是振荡(DWA planner里也有一个类似的参数) # base_local_planner:指定用于move_base的局部规划器插件名称 # base_global_planner:指定用于move_base的全局规划器插件名称 # recovery_behavior_enabled:是否启用机器人恢复行为 # recovery_behaviors:定义机器人恢复行为 # clearing_rotation_allowed:机器人是否在尝试清理空间时进行原地旋转 # max_planning_retries:在执行恢复行为前允许重新规划的次数。-1.0 的值对应于无限重试 shutdown_costmaps: false controller_frequency: 5.0 controller_patience: 3.0 planner_frequency: 1.0 planner_patience: 5.0 oscillation_timeout: 8.0 oscillation_distance: 0.3 recovery_behavior_enabled: true base_local_planner: "dwa_local_planner/DWAPlannerROS" base_global_planner: "global_planner/GlobalPlanner" recovery_behaviors: clearing_rotation_allowed: true max_planning_retries:
move_base_params.yaml里参数不全,更多参数与解释见 http://wiki.ros.org/move_base
global_planner_params.yaml,全局路径规划器也是以插件的形式被使用,这里主要对全局路径规划器GlobalPlanner插件及参数进行申明,
GlobalPlanner: # Also see: http://wiki.ros.org/global_planner old_navfn_behavior: true # 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: false # 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: 0.5 # 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: 2.0 # default 0.0 lethal_cost: 253 # default 253 neutral_cost: 66 # default 50 cost_factor: 0.55 # 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
这样的设定是在一篇论文中进行实验得到的。https://github.com/ros-planning/navigation/blob/indigo-devel/navfn/include/navfn/navfn.h
如果我们想在 RVIZ 中查看势力图可以将 visualize_potential 值由 FALSE 设为 TRUE。
注意:不是所有的参数都能在ROS网页上找到,可以运行rosrun rqt_reconfigure rqt_reconfigure
来查看。
局部路径规划器也是以插件的形式被使用,这里分别进行局部路径规划器DWALocalPlannerROS和TebLocalPlannerROS插件及参数进行申明
1.DWA:
DWA局部规划器采用动态窗口方法,它是一个能够驱动底盘移动的控制器,该控制器连接了路径规划器和机器人,使用地图,规划器产生从起点到目标点的运动轨迹,在移动时,规划器在机器人周围产生一个用网格地图表示的函数,利用这个函数来确定发送给机器人的速度dx,dy和dtheta。ROS 维基上提供了这种算法执行过程的介绍:
前向模拟是DWA算法的第二步。在这一步中,DWA规划器会对机器人进行速度采样,并检查由这些速度样本表示的圆形轨迹,并最终消除不良速度(如轨迹与障碍物相交)。在机器人的一段时间间隔内,每个速度样本由仿真时间控制及仿真。
评估正向模拟轨迹是通过计算目标函数进行的,最大化目标函数获得最佳速度对。目标函数的值依赖于三个组成部分:到目标点的过程、清除障碍物和前进速度。在ROS 中,目标函数的计算公式如下:
参数解释与调整:
dwa_local_planner_params.yaml
DWAPlannerROS: max_vel_x: 0.44 # 0.55 min_vel_x: 0.32 max_vel_y: 0.0 min_vel_y: 0.0 max_vel_trans: 0.6 # choose slightly less than the base's capability min_vel_trans: 0.05 # this is the min trans velocity when there is negligible rotational velocity trans_stopped_vel: 0.1 # Warning! # do not set min_trans_vel to 0.0 otherwise dwa will always think translational velocities # are non-negligible and small in place rotational velocities will be created. max_vel_theta: 0.8 # choose slightly less than the base's capability min_vel_theta: 0.45 # this is the min angular velocity when there is negligible translational velocity theta_stopped_vel: 0.1 acc_lim_x: 18.0 # maximum is theoretically 2.0, but we acc_lim_theta: 18.0 acc_lim_y: 0.0 # diff drive robot # Goal Tolerance Parameters yaw_goal_tolerance: 0.8 # 0.05 xy_goal_tolerance: 0.3 # 0.10 latch_xy_goal_tolerance: false # Forward Simulation Parameters sim_time: 2.1 # 1.7 vx_samples: 8 # 3 vy_samples: 1 # diff drive robot, there is only one sample vtheta_samples: 20 # 20 # Trajectory Scoring Parameters path_distance_bias: 35.0 # 32.0 - weighting for how much it should stick to the global path plan goal_distance_bias: 26.0 # 24.0 - wighting for how much it should attempt to reach its goal occdist_scale: 0.6 # 0.01 - weighting for how much the controller should avoid obstacles forward_point_distance: 0.2 # 0.325 - how far along to place an additional scoring point stop_time_buffer: 0.2 # 0.2 - amount of time a robot must stop in before colliding for a valid traj. scaling_speed: 0.25 # 0.25 - absolute velocity at which to start scaling the robot's footprint max_scaling_factor: 0.2 # 0.2 - how much to scale the robot's footprint when at speed. # Oscillation Prevention Parameters oscillation_reset_dist: 0.05 # 0.05 - how far to travel before resetting oscillation flags # Differential-drive robot configuration - necessary? # holonomic_robot: false
sim_time:我们可以将模拟时间sim_time视为允许机器人以采样速度移动的时间。仿真时间越长,计算负荷越大,同时规划器产生的路径也会变长。注意: 如果将仿真时间设置为非常低的值(≤2.0) 将导致性能有限,特别是当机器人需要通过狭窄的门口或家具之间的间隙时,因为没有足够的时间来获得最佳轨迹来通过狭窄的通道。另一方面,由于使用DWA本地规划器,所有的轨迹都是简单的圆弧,如果将仿真时间设置的非常高(>=5.0) ,会导致长曲线不是非常灵活。因为规划器在每个时间间隔后都会积极地重新规划,可以进行小的调整。对于高性能的计算机,4.0秒的值也是足够的。
sim_granularity:模拟步长,轨迹上采样点之间的距离,影响轨迹上点的密集程度。单位米
vx_sample,vy_sample 确定在 x,y 方向上取多少平移速度样本,vth_sample 控制旋转速度样本的数量。样本的数量取决于你的计算能力。在大多数情况下,倾向设置 vth_sample 高于平移速度样本,因为通常旋转比直线前进更复杂。如果将机器人y向最大速度设置为零(或者说不会在y方向运动),则不需要在 y 方向上提取速度样本,vy_sample设为0即可。
path_distance_bias:DWA规划结果与全局路径接近程度的权重。较大的值将使本地规划器更倾向于跟踪全局路径。wiki官网说明是:The weighting for how much the controller should stay close to the path it was given.
goal_distance_bias:是机器人尝试到达目标点的权重。实验表明增加 goal_distance_bias 值,会使规划路径与全局路径的一致性偏低。wiki官网说明是:The weighting for how much the controller should attempt to reach its local goal, also controls speed.
max_trans_vel:机器人的最大平移速度
min_trans_vel:机器人的最小平移速度
max_rot_vel:机器人的最大角速度的绝对值,单位为 rad/s
min_rot_vel:机器人的最小角速度的绝对值,单位为 rad/s
max_vel_x:X轴上的最大速度
min_vel_x:X轴上的最小速度,如果为负值表示可以后退
max_vel_y:Y轴上的最大速度
min_vel_y:Y轴上的最小速度
max_vel_theta:机器人的最大旋转速度,单位是弧度/秒。不要把这个值设的太高,不然机器人会错过它的目标方向
min_vel_theta:机器人的最小旋转速度
acc_lim_x:在x方向的加速度极限
acc_lim_y:在y方向的加速度极限,该值只有全向移动的机器人才需配置,对于差速驱动(非完整驱动)机器人,设为0
acc_lim_theta:角速度的加速度的极限
yaw_goal_tolerance:到达目标点时偏行角允许的误差,单位弧度
xy_goal_tolerance:到达目标点时,在xy平面内与目标点的距离误差
latch_xy_goal_tolerance(bool,默认:false):如果为true,如果机器人到达目标 xy 位置,它将简单地旋转到位,即使这样做会超出目标容差。即当机器人到达目标点后通过旋转调整姿态(方向)后,偏离了目标点,也认为完成。
vx_samples:x方向速度空间的采样点数
vy_samples:y方向速度空间采样点数
vtheta_samples:角速度空间时要使用的采样点数
vth_samples:旋转方向的速度空间采样点数
controller_frequency:发送给底盘控制移动指令的频率,注意,在dwa_local_planner中,这个参数如果没有设置,则会使用在move_base包中设置的同名参数的值
occdist_scale:定义控制器躲避障碍物的权重,这个值偏大容易导致机器人陷入困境
stop_time_buffer:为防止碰撞,机器人必须提前停止的时间长度
scaling_speed:开始缩放机器人footprint的机器人底盘的速度
max_scaling_factor:最大缩放参数,机器人在运动时的footprint的缩放比例
publish_cost_grid:是否发布规划器在规划路径时的代价网格。如果设置为true,那么就会在~/cost_cloud话题上发布sensor_msgs/PointCloud2类型消息
oscillation_reset_dist:机器人至少走多少米,才不会被认为陷入了震荡
prune_plan:机器人前进是是否清除身后1m外的轨迹
trans_stopped_vel:机器人被认为属于“停止”状态的平移速度,如果机器人速度低于这个值,则认为机器人已停止
rot_stopped_vel:机器人被认为属于“停止”状态的旋转速度,如果机器人旋转速度低于这个值,则认为机器人已停止
forward_point_distance:以机器人为中心,额外放置一个计分点的距离
holonomic_robot:如果机器人是全向移动机器人那么为true,差分的则设为false
2.TEB:
TebLocalPlannerROS: odom_topic: odom map_frame: /odom # Trajectory teb_autosize: True dt_ref: 0.3 #期望的轨迹时间分辨率 dt_hysteresis: 0.03 #根据当前时间分辨率自动调整大小的滞后现象,通常约为。建议使用dt ref的10%。 #min_samples (int, default: 3) #最小样本数(始终大于2) global_plan_overwrite_orientation: True #覆盖由全局规划器提供的局部子目标的方向 #global_plan_viapoint_sep (double, default: -0.1 (disabled)) 如果为正值,则通过点(via-points )从全局计划(路径跟踪模式)展开,该值确定参考路径的分辨率(沿着全局计划的每两个连续通过点之间的最小间隔,可以参考参数weight_viapoint来调整大小 allow_init_with_backwards_motion: False max_global_plan_lookahead_dist: 3.0 #指定考虑优化的全局计划子集的最大长度 #force_reinit_new_goal_dist (double, default: 1.0) 重新引导轨迹如果先前的目标是更新分离超过指定值米(跳过hot-starting) feasibility_check_no_poses: 5 #每个采样间隔的姿态可行性分析数,default:4 #publish_feedback (bool, default: false) 发布包含完整轨迹和动态障碍的列表的规划器反馈 #shrink_horizon_backup (bool, default: true) 允许规划器在自动检测到问题(e.g. infeasibility)的情况下临时缩小horizon(50%) #shrink_horizon_min_duration (double, default: 10.0) 指定最低持续时间减少地平线以备不可行轨迹检测 # Robot max_vel_x: 0.4 #max_vel_x (double, default: 0.4) max_vel_x_backwards: 0.15 #max_vel_x_backwards (double, default: 0.2) acc_lim_x: 2.0 #acc_lim_x (double, default: 0.5) max_vel_theta: 1.0 #max_vel_theta (double, default: 0.3) acc_lim_theta: 1.0 #acc_lim_theta (double, default: 0.5) #仅适用于全向轮 # max_vel_y (double, default: 0.0) # acc_lim_y (double, default: 0.5) #最小转弯半径 min_turning_radius: 0.0 # min_turning_radius (double, default: 0.0) diff-drive: 0 #是否允许原地转 cmd_angle_instead_rotvel: True # cmd_angle_instead_rotvel(bool,defaule:false) 是否允许原地转 wheelbase: 0.0 #wheelbase (double, default: 1.0) diff-drive: 0.0 footprint_model: # types: "point", "circular", "two_circles", "line", "polygon" # type: "point" radius: 0.36 # for type "circular" # line_start: [-0.3, 0.0] # for type "line" 线模型起始坐标 # line_end: [0.3, 0.0] # for type "line" 线模型尾部坐标 # front_offset: 0.2 # for type "two_circles" 前圆心坐标 # front_radius: 0.2 # for type "two_circles" 前圆半径 # rear_offset: 0.2 # for type "two_circles" 后圆心坐标 # rear_radius: 0.2 # for type "two_circles" 后圆半径 # vertices: [ [0.25, -0.05], [0.18, -0.05], [0.18, -0.18], [-0.19, -0.18], [-0.25, 0], [-0.19, 0.18], [0.18, 0.18], [0.18, 0.05], [0.25, 0.05] ] # for type "polygon"多边形边界点 # GoalTolerance xy_goal_tolerance: 0.2 #目标位置的允许距离误差 yaw_goal_tolerance: 0.2 #目标位置的允许角度误差 free_goal_vel: False #去除目标速度的约束 # Obstacles min_obstacle_dist: 0.1 # 与障碍的最小期望距离,注意,teb_local_planner本身不考虑膨胀半径 include_costmap_obstacles: True #应否考虑到局部costmap的障碍 costmap_obstacles_behind_robot_dist: 1.0 #考虑后面n米内的障碍物 obstacle_poses_affected: 30 #为了保持距离,每个障碍物位置都与轨道上最近的位置相连。 #inflation_dist (double, default: 0.6) 障碍物周围缓冲区(应大于min_obstacle_dist才能生效) #legacy_obstacle_association (bool, default: false) 切换到旧的的策略 #obstacle_association_force_inclusion_factor (double, default: 1.5) n * min_obstacle_dist的半径范围内强制考虑障碍 #obstacle_association_cutoff_factor (double, default: 5) 只有在参数legacy为false时才使用此2参数 costmap_converter_plugin: "" #定义插件名称,用于将costmap的单元格转换成点/线/多边形。若设置为空字符,则视为禁用转换,将所有点视为点障碍 costmap_converter_spin_thread: True #如果为true,则costmap转换器将以不同的线程调用其回调队列, default:true costmap_converter_rate: 5 #定义costmap_converter插件处理当前costmap的频率(该值不高于costmap更新率 # Optimization no_inner_iterations: 5 #在每个外循环迭代中调用的实际求解器迭代次数 no_outer_iterations: 4 #在每个外循环迭代中调用的实际求解器迭代次数 optimization_activate: True optimization_verbose: False penalty_epsilon: 0.1 #为硬约束近似的惩罚函数添加一个小的安全范围 weight_max_vel_x: 2 #满足最大允许平移速度的优化权重 weight_max_vel_theta: 0 #满足最大允许平移速度的优化权重 weight_acc_lim_x: 1 #满足最大允许平移加速度的优化权重。 weight_acc_lim_theta: 0.01 #满足最大允许角加速度的优化权重。 weight_kinematics_nh: 1000 #运动学的优化权重 weight_kinematics_forward_drive: 2 #强制机器人仅选择正向(正的平移速度)的优化权重。 weight_kinematics_turning_radius: 1 #采用最小转向半径的优化权重 weight_optimaltime: 1 #根据转换/执行时间对轨迹进行收缩的优化权重。 weight_obstacle: 50 #保持与障碍物的最小距离的优化权重 default: 50.0 # weight_viapoint: 1 #跟踪全据路径的权重 # weight_inflation (double, default: 0.1) #膨胀半径权重 weight_dynamic_obstacle: 10 # not in use yet # weight_adapt_factor: 2 #迭代地增加某些权重 alternative_time_cost: False # Homotopy Class Planner enable_homotopy_class_planning: False #激活并行规划(因为一次优化多个轨迹,占用更多的CPU资源 enable_multithreading: True #激活多个线程,以便在不同的线程中规划每个轨迹 simple_exploration: False max_number_classes: 2 #考虑到的不同轨迹的最大数量 #selection_cost_hysteresis: 1.0 #轨迹成本 #selection_obst_cost_scale: 1.0 #障碍物成本 #selection_alternative_time_cost: False #如果为真,时间成本(时间差平方和)被总转移时间(时间差和)所替代。 roadmap_graph_no_samples: 15 #指定为创建路线图而生成的样本数 roadmap_graph_area_width: 5 #指定该区域的宽度 h_signature_prescaler: 0.5 #(0.2 < value <= 1)缩放用于区分同伦类的内部参数(H-signature)。 #警告:只能减少此参数,如果在局部costmap中遇到太多障碍物的情况,请勿选择极低值,否则无法将障碍物彼此区分开线缩放用于区分同伦类的内部参数(H-signature)。 h_signature_threshold: 0.1 #如果实部和复部的差都低于规定的阈值,则假定两个h签名相等。 obstacle_keypoint_offset: 0.1 obstacle_heading_threshold: 0.45 #指定障碍标头和目标标头之间的标量积的值,以便将(障碍)考虑到勘探中 visualize_hc_graph: False #可视化创建的图形,用于探索不同的轨迹(在rviz中检查标记消息) #viapoints_all_candidates (bool, default: true) 如果为真,则不同拓扑的所有轨迹都附加到这组vio -points上,否则只有共享与初始/全局计划相同拓扑的轨迹与它们连接
TEB下次再更新
注意:不是所有的参数都能在ROS网页上找到,但是你可以通过运行rosrun rqt_reconfigure rqt_reconfigure
来查看。
代价地图,简单来说就是在原始地图上进行各种加工,方便后续路径规划。
在ROS中使用costmap_2d这个软件包来实现的,该软件包在原始地图上生成了两张新的地图。一个是global_costmap,另外一个是local_costmap,一个是为全局路径规划准备的,另一个是为局部路径规划准备的。无论是global_costmap还是local_costmap,都可以配置多个图层,包括下面几种:
几个图层通过融合,得到master_layer:
下图显示了膨胀层、膨胀半径的意义
代价地图配置文件一般包含3个:costmap_common_params.yaml、global_costmap_params.yaml、local_costmap_params.yaml,下面依次介绍,并解释参数含义。
costmap_common_params.yaml,该文件存储代价地图需要监听的传感器话题,代价地图公有参数等,全局代价地图和局部代价地图公有的参数放置进来,如此只需要载入这个配置文件就能完成共有参数的配置,避免了在全局代价地图和局部代价地图配置文件中重复配置一些相同参数的冗余。
#map_type: voxel #map_type: costmap #robot_radius: 0.25 footprint: [[0.23,0.19],[0.25,0],[0.23,-0.19],[-0.23, -0.19],[-0.23,0.19]] obstacle_layer: enabled: true combination_method: 1 track_unknown_space: false origin_z: 0.0 z_voxels: 20 z_resolution: 0.1 unknown_cost_value: 0 unknown_threshold: 8 mark_threshold: 0 publish_voxel_map: false obstacle_range: 6.0 raytrace_range: 7.0 robot_radius: 0.25 inflation_radius: 0.25 max_obstacle_height: 0.40 min_obstacle_height: 0.03 observation_sources: scan #point_cloud_sensor scan: {sensor_frame: base_link, observation_persistence: 0.0, max_obstacle_height: 0.3, min_obstacle_height: 0.05, data_type: LaserScan, topic: /scan, marking: true,clearing: true} inflation_layer: enabled: true cost_scaling_factor: 5.0 # exponential rate at which the obstacle cost drops off (default: 10) inflation_radius: 0.25 # max. distance from an obstacle at which costs are incurred for planning paths. static_layer: enabled: true
配置参数分为2类:机器人形状和代价地图各layer图层。代价地图各layer图层包括:静态层static_layer(由SLAM建立得到的地图提供数据)、障碍层obstacle_layer(由激光雷达等障碍扫描传感器提供实时数据)、膨胀层inflation_layer(在以上两层地图上进行膨胀(向外扩张),以避免机器人撞上障碍物)或者有voxel_layer体素层,Other Layers(你还可以通过插件的形式自己实现costmap,目前已有Social Costmap Layer、Range Sensor Layer等开源插件)。
inflation_radius 和 cost_scaling_factor 是决定膨胀的主要参数。inflation_radius 控制零成本点距离障碍物有多远,膨胀层会把障碍物的代价膨胀直到该半径为止。cost_scaling_factor 越大,膨胀点越宽,代价地图的边界越平滑,使得机器人越来越靠中间,远离墙边或障障碍物
建议costmap的曲线是具有相对较低斜率的曲线(也就是让代价图的边缘不是消失的那么突然,如下方右图),以便最佳路径尽可能远离每侧的障碍物。优点是机器人可以在障碍物中间移动。
static_layer:静态地图层,即SLAM中构建的地图层
enabled:是否启用该地图层
costmap resolution:地图分辨率,该参数可分别为局部代价图和代价成本图设置,该参数直接影响计算量和路径规划效果。当分辨率较低(>=0.05m)时,在狭窄的通道内,障碍物区域可能会重叠,导致局部规划无法找到一条合理通过的路径。如果你有足够的计算能力,可以考虑增大这个参数获取更好精度的地图。参数上限需要看激光雷达设备的分辨率,否则会出现很多小的“未知点”,因为分辨率过大,超过设备的能力范围。!!!!!!!!!!不知道建图时候分辨率怎么改呢还
global_costmap_params.yaml,该文件存储特定于全局代价地图的配置参数
global_costmap: global_frame: map robot_base_frame: base_link update_frequency: 1.0 publish_frequency: 1.0 static_map: true rolling_window: false resolution: 0.05 transform_tolerance: 1.0 #inflation_radius: 0.1 plugins: - {name: static_layer, type: "costmap_2d::StaticLayer"} - {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"} - {name: inflation_layer, type: "costmap_2d::InflationLayer"}
local_costmap_params.yaml,该文件存储特定于局部代价地图的配置参数
local_costmap:
global_frame: odom
robot_base_frame: base_link
update_frequency: 3.0
publish_frequency: 3.0
#static_map: false
rolling_window: true
width: 2.5
height: 2.5
resolution: 0.05
plugins:
- {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
- {name: inflation_layer, type: "costmap_2d::InflationLayer"}
恢复行为的类型:ROS 导航包有两种恢复行为,分别是清除代价地图恢复和旋转恢复。清除代价地图恢复是将本地代价地图还原成全局代价地图的状态。旋转恢复是通过旋转 360°来恢复。
ROS当中有两种恢复运动的方式,第一种,clear_costmap_recovery,第二种,rotate_recovery。清除costmap当中的基本恢复状态,他会旋转360度在原来的位置。
你应该查看你的激光雷达的扫描的分辨率,如果你想要的得到的地图的分辨率大于激光雷达的分辨率,那么就是出现一些 UNKNOW的点
ROS 导航包有两种恢复行为,分别是清除代价地图恢复和旋转恢复。清除代价地图恢复是将本地代价地图还原成全局代价地图的状态。旋转恢复是通过旋转 360°来恢复。 解救机器人:有时由于旋转故障,旋转恢复将无法执行。在这一点上,机器人可能会放弃,因为它已经尝试了所有的恢复行为。在大多数试验中,我们观察到,当机器人放弃时,实际上有很多方法可以解救机器人。为了避免放弃,我们使用 SMAC H 来连续尝试不同的恢复行为,通过其他额外的行为,例如设置非常接近机器人的临时目标,并返回到以前访问过得姿态(即退出)。这些方法可以显著提高机器人的耐久性,并且从以前观察到的无望空间中解救出来。
为了清除代价地图恢复,你可以设置一个相对较高的模拟时间 sim_time,这意味着轨迹很长,你可能需要考虑增加 res et_distance 参数的值,这样可以消除本地代价地图上更大的区域,并且有更好的机会寻找一条路径。
怎样终止正在进行的导航navigation
how to cancel a navigation goal or how to stop current navigation?
导航时,取消当前目标点或者暂停导航是一个常见的问题
用如指令即可实现导航停止,小车停止:
rostopic pub /move_base/cancel actionlib_msgs/GoalID -- {}
或者
ros::Publisher cancle_pub_ = nh_.advertise<actionlib_msgs::GoalID>("move_base/cancel",1);
actionlib_msgs::GoalID first_goal;
cancle_pub_.publish(first_goal);
问题 8.1 陷入困境 在使用 ROS 导航的时候,这个问题经常出现,无论是在仿真还是实际中,机器人都可能陷入困境然后放弃目标 8.2 不同方向的不同速度 在导航堆栈中我们观察到一些奇怪的行为。当目标点设置在相对于 TF 原点的-x 方向时,dwa 局部规划器规划不稳定(局部规划路径跳跃),而且机器人的移动速度非常慢。但是当把目标设置在+x 方向时,dwa 局部规划器就比较稳定了,并且移动速度很快。 8.3 实际和仿真 实际与仿真是有区别的。在现实情况中,障碍物有各种各样的形状。例如,在实验室中有一个垂直的柜子,防止门闭上,由于太细,机器人有时无法检测到然后撞击上去。而且实际中也会有更多复杂的人类活动。 8.4 前后矛盾 使用 ROS 导航堆栈可能会出现不一致的行为。例如进门时,在不同时间本地代价地图会一次又一次的生成,这可能会影响路径规划,特别是在分辨率较低的时候。另外,机器人没有内存,它不记得上次从门进入房间,所以每次尝试进门都需要重新开始。因此,如果没有与以前相同的进门角度,机器人可能会卡住并放弃目标。
https://blog.csdn.net/hiram_zhang/article/details/88374519
https://blog.csdn.net/gwplovekimi/article/details/110230942
https://zhuanlan.zhihu.com/p/143202720
https://blog.csdn.net/qq_15390133/article/details/106875963
AMCL 是处理机器人定位的 ROS 包。它是自适应蒙特卡罗定位的缩写(Adaptive Monte Carlo Localization)。这种定位方法的原理如下:每个样本存储表示机器人姿态的位置和方向数据。粒子是随机抽样的,当机器人移动时,粒子根据他们的状态记忆机器人的动作,采用递归贝叶斯估计进行重采样。
请参考 ROS 维基 http://wiki.ros.org/amcl 了解更多信息。
粒子滤波,是一种思想,比如要计算一个矩形里面一个不规则形状的面积,这个问题不好直接计算,但是可以拿一把豆子均匀撒到矩形中,统计落在不规则形状中豆子的占比就能算出其面积了。在机器人定位问题中,我们在地图的任意位置撒上许多粒子点,然后通过传感器观测数据按照一定的评价方法对每个粒子点进行打分,评分高的粒子点表示机器人有更大的可能在此位置;在下一轮撒点时,就在评分高的粒子点附近多撒一些点,这样通过不断的迭代,粒子点就会聚拢到一个地方。这个粒子点聚集的地方,就是机器人位置的最优估计点。如下图中,红色的粒子点慢慢聚拢到一团。
重要性采样,在粒子滤波的迭代过程中,评分高的粒子点会被下一轮迭代时更加看重,这样不断迭代真实估计值附近的粒子点会越来越多。
机器人绑架,当机器人被突然从一个地方抱走到另一个地方,这个时候前一轮迭代得到的粒子点完全不能在新的位置上试用,这样继续迭代下去就会发生位置估计的错误。
自适应蒙特卡洛,自适应主要体现在两个方面。通过判断粒子点的平均分突变来识别机器人绑架问题,并在全局重新撒点来解决机器人绑架问题;通过判断粒子点的聚集程度来确定位置估计是否准确,在估计比较准确的时候降低需要维护的粒子点数目,这样来降低算法的计算开销。
amcl.yaml,该文件定义说明了机器人定位算法Amcl的可变参数
<?xml version="1.0" ?> <launch> <node pkg="amcl" type="amcl" name="amcl" output="screen"> <!-- Publish scans from best pose at a max of 10 Hz --> <param name="odom_model_type" value="diff"/> <param name="odom_alpha5" value="0.1"/> <param name="transform_tolerance" value="0.2" /> <param name="gui_publish_rate" value="10.0"/> <!-- Maximum rate (Hz) at which scans and paths are published for visualization, -1.0 to disable. --> <param name="laser_max_beams" value="60"/> <param name="min_particles" value="500"/> <param name="max_particles" value="800"/> <param name="kld_err" value="0.05"/> <param name="kld_z" value="0.99"/> <param name="odom_alpha1" value="0.3"/> <!-- Specifies the expected noise in odometry's rotation estimate from the rotational component of the robot's motion. --> <param name="odom_alpha2" value="1.2"/> <!-- Specifies the expected noise in odometry's rotation estimate from translational component of the robot's motion. --> <!-- translation std dev, m --> <param name="odom_alpha3" value="3.7"/> <!-- Specifies the expected noise in odometry's translation estimate from the translational component of the robot's motion. --> <param name="odom_alpha4" value="0.3"/> <!-- Specifies the expected noise in odometry's translation estimate from the rotational component of the robot's motion. --> <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_model_type" value="beam"/> --> <param name="laser_likelihood_max_dist" value="2.0"/> <param name="update_min_d" value="0.1"/> <!-- Translational movement required before performing a filter update. --> <param name="update_min_a" value="0.1"/> <!-- Rotational movement required before performing a filter update. 0.1 represents 5.7 degrees --> <param name="odom_frame_id" value="odom"/> <param name="resample_interval" value="1"/> <!-- Number of filter updates required before resampling. --> <!-- Increase tolerance because the computer can get quite busy --> <param name="transform_tolerance" value="1.0"/> <!-- Default 0.1; time with which to post-date the transform that is published, to indicate that this transform is valid into the future. --> <param name="recovery_alpha_slow" value="0.001"/> <!-- Exponential decay rate for the slow average weight filter, used in deciding when to recover by adding random poses. --> <param name="recovery_alpha_fast" value="0.1"/> <!-- Exponential decay rate for the fast average weight filter, used in deciding when to recover by adding random poses. --> </node> </launch>
下次更新
下次更新
举例:
demo.urdf
<?xmlversion"1.0" encoding"UTF8" ?>
<robot name "joint_rpy_demo">
<link name="base footprint">
</link>
<link name="base_link">
</link>
<joint name="base joint" type="fixed">
<origin xyz="0 0 1.0" rpy="0 0 0" />
<parent link="base footprint"/>
<child link="base link" />
</joint>
</robot>
launch
<?xmlversion"1.0" encoding"UTF8" ?>
<launch>
<param name="robot_description" textfile="$(find pkg)/urdf/demo.urdf" />
<node name="robot state publisher" pkg="robot state publisher" type="robot state publisher" />
<node pkg="rviz" type="rviz" name="rviz" />
</launch>
rviz可视化:baselink于basefootprint方1米位置,<origin xyz="0 0 1.0" rpy="0 0 0" />
。
当修改joint关系如下:
<origin xyz="0 0 1.0" rpy="1.57 0 0" />
<parent link="base_footprint"/>
<child link="baselink"/>
可以发现坐标系绕x轴旋转了90度(红色-x轴,绿色-y轴,蓝色-z轴),并且以右手握四指指向方向为正方向。在urdf中的定义rpy(roll, pitch, yaw)分别表示绕x、y、z轴旋转,取值是弧度制,以3.14为旋转180度为单位。同时三者存在执行顺序:
<origin xyz="0 0 1.0" rpy="1.57 1.57 0" />
表示先绕x轴90度、再绕y轴90度
<origin xyz="0 0 1.0" rpy="1.57 1.57 -1.57" />
表示先绕x轴90度、再绕y轴90度、最后绕z轴-90度
此外,一定切记,所有的旋转都是按照parent的坐标系坐标轴进行操作的。
推荐课程:https://www.bilibili.com/video/BV1Ci4y1L7ZZ/?p=260
推荐课件:http://www.autolabor.com.cn/book/ROSTutorials/
https://wenku.baidu.com/view/7d1ee9cf82c758f5f61fb7360b4c2e3f572725a0.html?wkts=1682482079196&bdQuery=urdf%E4%B8%AD+rpy%E5%A6%82%E4%BD%95%E8%AE%BE%E7%BD%AE
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。