【movebase】机器人使用vlp-16多线雷达cartographer纯定位+movebase导航

文章详细介绍了在ROS1Noetic环境下,如何使用Cartographer进行纯定位,包括launch文件和lua配置文件的修改,以及点云数据转换为laserscan的步骤。此外,还涉及到激光里程计的设置,如laser_scan_matcher_odometry的使用,以及move_base的相关参数配置,如costmap_common_params.yaml、global_costmap_params.yaml和local_costmap_params.yaml等。最后,文章讨论了在无里程计和imu时,如何通过设置避免定位偏移和漂移问题。
摘要由CSDN通过智能技术生成


环境:
ubuntu 20.04 + ros1 noetic
gazebo 11
机器人有urdf,tf树最上层为base_link,无里程计和imu
使用vlp-16点云数据生成激光里程计数据

没有用过imu,所以文章内容不太能给使用imu的人提供参考
文章内容如有错误,欢迎指出交流。

1、cartographer纯定位

launch文件相关修改

参考链接文章,修改occupancy_grid_node_main文件
launch文件参考

<launch>
  <param name="/use_sim_time" value="true" />

  <node name="cartographer_node" pkg="cartographer_ros"
      type="cartographer_node" args="
          -configuration_directory $(find cartographer_ros)/configuration_files
          -configuration_basename robot_simple_2d_localization.lua
          -load_state_filename /home/letitia/robot_simple_ws/src/robot_simple_navigation/maps/warehouse/warehouse.pbstream"
      output="screen">
    <remap from="/points2" to="/velodyne_points" />
  </node>

  <node name="cartographer_occupancy_grid_node" pkg="cartographer_ros"
      type="cartographer_occupancy_grid_node" args="-resolution 0.05
      							                    -pure_localization 1" />

  <node name="rviz" pkg="rviz" type="rviz" required="true"
      args="-d $(find cartographer_ros)/configuration_files/demo_nav_2d.rviz" />

</launch>

lua文件相关修改

复制backpack_2d_localization.lua,将复制的文件改为自己的名字,并打开修改里面参数,可参考链接文章

include "修改为建图时的lua文件名.lua"

TRAJECTORY_BUILDER.pure_localization_trimmer = {
  max_submaps_to_keep = 3, 
}
POSE_GRAPH.optimize_every_n_nodes = 20

return options

2、激光里程计

两个包都放到工作空间的src文件里面

pointcloud2转laserscan

无论是激光里程计还是move_base,直接使用点云数据的效果都不好,所以先将pointcloud2转laserscan,使用到pointcloud_to_laserscan工具,github地址(如果直接git clone,下载的是ros2版本的,ros1需要在分支里找一个合适的版本下载zip)
launch配置参考(中文记得删)

<node pkg="pointcloud_to_laserscan" type="pointcloud_to_laserscan_node" name="pointcloud_to_laserscan">
  # remap到自己的话题
  <remap from="cloud_in" to="/velodyne_points"/>
  <remap from="scan" to="/scan"/>
  <rosparam>
      # target_frame: camera_link # Leave disabled to output scan in pointcloud frame
      transform_tolerance: 0.01
      # z轴读取范围,根据自己的情况改下面两个
      min_height: -0.03
      max_height: 1.5
      # 扫描角度,根据自己的情况改下面两个
      angle_min: -1.4
      angle_max: 1.4
      angle_increment: 0.0087 # M_PI/360.0
      scan_time: 0.1
      range_min: 0.5
      range_max: 30
      use_inf: true
      inf_epsilon: 1.0

      # Concurrency level, affects number of pointclouds queued for processing and number of threads used
      # 0 : Detect number of cores
      # 1 : Single threaded
      # 2->inf : Parallelism level
      concurrency_level: 1
  </rosparam>

</node>

里程计

因为laser_scan_matcher没有发布odom话题,这里用的是laser_scan_matcher_odometry,github链接。还有一个激光雷达工具是rf2o_laser_odometry,我感觉在无imu时,效果差不太多,不过这个工具运行时在终端里有很多输出,建议单独写在一个launch文件里并在另一个终端打开,这样不影响看move_base的输出。
launch配置参考

<node pkg="laser_scan_matcher_odometry" type="laser_scan_matcher_odometry_node"
    name="laser_scan_matcher_odometry_node" output="screen">

  <param name="fixed_frame" value="odom" />
  <param name="base_frame" value="base_link" />
  <param name="max_iterations" value="10" />
</node>

3、movebase

movebase主要是4个参数文件

costmap_common_params.yaml

#机器人几何参,如果机器人是圆形,设置 robot_radius,如果是其他形状设置 footprint
# robot_radius: 0.12 #圆形
footprint: [[-0.389, -0.228], [-0.389, 0.228], [0.389, 0.228], [0.389, -0.228]] #其他形状

#代价比例系数,越大则代价值越小
cost_scaling_factor: 3.0

obstacle_range: 1.0 # 用于障碍物探测,比如: 值为 3.0,意味着检测到距离小于 3 米的障碍物时,就会引入代价地图
raytrace_range: 2.0 # 用于清除障碍物,比如:值为 3.5,意味着清除代价地图中 3.5 米以外的障碍物

#导航包所需要的传感器
observation_sources: scan # points2试着配过,自己感觉不好用
scan:
  {data_type: LaserScan, topic: /scan, marking: true, clearing: true, expected_update_rate: 0}

global_costmap_params.yaml

global_costmap:
  global_frame: map #地图坐标系
  robot_base_frame: base_link #机器人坐标系
  # 以此实现坐标变换

  update_frequency: 10.0 #代价地图更新频率
  publish_frequency: 8.0 #代价地图的发布频率
  transform_tolerance: 0.5 #等待坐标变换发布信息的超时时间

  #膨胀半径,扩展在碰撞区域以外的代价区域,使得机器人规划路径避开障碍物
  inflation_radius: 0.5

  plugins: 
    - {name: static_layer,            type: "costmap_2d::StaticLayer"}
    - {name: obstacle_layer,          type: "costmap_2d::VoxelLayer"}
    - {name: inflation_layer,         type: "costmap_2d::InflationLayer"}

全局代价地图的膨胀半径最好比局部代价地图的大一些

local_costmap_params.yaml

local_costmap:
  global_frame: map #这里如果放odom会报错或警告的话,就改为map
  robot_base_frame: base_link #机器人坐标系

  update_frequency: 15.0 #代价地图更新频率
  publish_frequency: 10.0 #代价地图的发布频率
  transform_tolerance: 0.5 #等待坐标变换发布信息的超时时间

  #膨胀半径,扩展在碰撞区域以外的代价区域,使得机器人规划路径避开障碍物
  inflation_radius: 0.2

  obstacle_range: 1.5 # 用于障碍物探测,比如: 值为 3.0,意味着检测到距离小于 3 米的障碍物时,就会引入代价地图
  raytrace_range: 2.0 # 用于清除障碍物,比如:值为 3.5,意味着清除代价地图中 3.5 米以外的障碍物
  rolling_window: true #是否使用动态窗口,默认为false,在静态的全局地图中,地图不会变化
  width: 1.5 # 局部地图宽度 单位是 m
  height: 1.5 # 局部地图高度 单位是 m
  resolution: 0.05 # 局部地图分辨率 单位是 m,一般与静态地图分辨率保持一致(carto建图的那个系数

  plugins:
    - {name: static_layer,            type: "costmap_2d::StaticLayer"}
    - {name: inflation_layer,         type: "costmap_2d::InflationLayer"}

局部路径规划teb_local_planner.yaml(我用的teb)

recovery_behavior_enabled: False
clearing_rotation_allowed: False

TebLocalPlannerROS:
 
 odom_topic: odom
 map_frame: /map
 
 #Trajectory
 teb_autosize: True 
 dt_ref: 0.3 
 dt_hysteresis: 0.03
 global_plan_overwrite_orientation: True 
 allow_init_with_backwards_motion: False 
 max_global_plan_lookahead_dist: 3.0 
 feasibility_check_no_poses: 5 
 
 # Robot
 max_vel_x: 10.0
 max_vel_y: 0.0 
 max_vel_x_backwards: 1.0 
 max_vel_theta: 10.0 
 acc_lim_x: 0.15 
 acc_lim_y: 0  
 acc_lim_theta: 2.5 
 
 min_turning_radius: 0.5 #差动小车不想总是原地转,可以把这里不设为0
 
 cmd_angle_instead_rotvel: False
 
 footprint_model:
  type: "polygon"
  vertices: [[-0.389, -0.228], [-0.389, 0.228], [0.389, 0.228], [0.389, -0.228]]
 
 
 xy_goal_tolerance: 0.2  
 yaw_goal_tolerance: 0.2
 free_goal_vel: False 
 complete_global_plan: True
 
 # Obstacles
 min_obstacle_dist: 0.1 
 include_costmap_obstacles: True 
 costmap_obstacles_behind_robot_dist: 1.5  # default:1.5  0.0~20.0
 obstacle_poses_affected: 15   
 costmap_converter_plugin: ""
 costmap_converter_spin_thread: True
 costmap_converter_rate: 5
 include_dynamic_obstacles: True 
 dynamic_obstacle_inflation_dist: 0.6 
 
 # Optimization  
 no_inner_iterations: 5 
 no_outer_iterations: 4  
 optimization_activate: True 
 optimization_verbose: False 
 penalty_epsilon: 0.05
 obstacle_cost_exponent: 4
 weight_max_vel_x: 1  
 weight_max_vel_theta: 1 
 weight_acc_lim_x: 2  
 weight_acc_lim_theta: 1  
 weight_kinematics_nh: 1000
 weight_kinematics_forward_drive: 1
 weight_kinematics_turning_radius: 1 
 weight_optimaltime: 1 # must be > 0 
 weight_shortest_path: 0 
 weight_obstacle: 100
 weight_inflation: 0.2   
 weight_dynamic_obstacle: 10
 weight_dynamic_obstacle_inflation: 0.2  
 weight_viapoint: 1  
 weight_adapt_factor: 2 
 
 # Homotopy Class Planner
 enable_homotopy_class_planning: True 
 enable_multithreading: False 
 max_number_classes: 5 
 selection_cost_hysteresis: 1.0 
 selection_prefer_initial_plan: 0.95
 selection_obst_cost_scale: 1.0
 selection_alternative_time_cost: False
 
 roadmap_graph_no_samples: 15
 roadmap_graph_area_width: 5
 roadmap_graph_area_length_scale: 1.0
 h_signature_prescaler: 0.5
 h_signature_threshold: 0.1
 obstacle_heading_threshold: 0.45
 switching_blocking_period: 0.0
 viapoints_all_candidates: True
 delete_detours_backwards: True
 max_ratio_detours_duration_best_duration: 3.0
 visualize_hc_graph: False
 visualize_with_time_as_z_axis_scale: False
 
 # Recovery
 
 shrink_horizon_backup: True
 shrink_horizon_min_duration: 10
 oscillation_recovery: False 
 oscillation_v_eps: 0.1
 oscillation_omega_eps: 0.1
 oscillation_recovery_min_duration: 10
 oscillation_filter_duration: 10

4、launch文件

<node name="map_server" pkg="map_server" type="map_server" args="$(find robot_simple_navigation)/maps/warehouse/warehouse.yaml"/>

<include file="$(find pointcloud_to_laserscan)/launch/point_to_scan.launch"/>

<node pkg="laser_scan_matcher_odometry" type="laser_scan_matcher_odometry_node"
  name="laser_scan_matcher_odometry_node" output="screen">

  <param name="fixed_frame" value="odom" />
  <param name="base_frame" value="base_link" />
  <param name="max_iterations" value="10" />
</node>

<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true">
    <param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" />
    <param name="controller_frequency" value="10.0" />

    <rosparam file="$(find robot_simple_navigation)/config/costmap_common_params.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find robot_simple_navigation)/config/costmap_common_params.yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find robot_simple_navigation)/config/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find robot_simple_navigation)/config/global_costmap_params.yaml" command="load" />
    <rosparam file="$(find robot_simple_navigation)/config/teb_local_planner.yaml" command="load" />
</node>

总结

尝试了几种激光里程计,但都会出现偏移甚至漂移出地图的情况,虽然多设置几次目标地点让机器人走一走可以后期修正回来,但未修正期间是有可能撞到障碍物的,所以在无里程计和imu的时候,如果是cartographer建的图,建议纯定位时还是直接用cartographer提供的odom(cartographer查阅TF-tree上的base_scan相对于map的关系,根据激光点云定位base_scan,并根据base_link与base_scan的关系追踪base_link的位姿,最终推算odom相对于map的位姿关系并发布tf,发布的不是话题哦),基本上没有漂移的问题。

参考

cartographer pure_localization 纯定位修改 +初始化位置
【移动机器人技术】Cartographer使用流程-建图-纯定位-导航

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值