ROS仿真笔记之——基于rrt_exploration的单个机器人自主探索建图

之前博文已经介绍过机器人exploration以及多机器人SLAM map merage《ROS学习笔记之——多机器人探索环境》《ROS仿真笔记之——基于gazebo的多机器人探索环境仿真》《ROS仿真笔记之——移动机器人SLAM地图融合》《ROS仿真笔记之——移动机器人自主探索式地图构建》之前的都是基于功能包(http://wiki.ros.org/multirobot_map_merge/

目录

原理

仿真

实验

参考资料



原理

该包的基本原理是,基于2D的,通常采用图像算法的边缘检测来检测已知区域与未知区域的边界。基于Rapidly-exploring Random Trees的探索策略。由于RRT基本上是朝向未知区域的(unexplored and unvisited),并且RRT可以扩展到更高维区域。同时采用local tree与global tree来检查边缘点,使得机器人的exploration更加高效。

一旦检测到边缘后,就会取其中心为目标点,然后让机器人去探索该点。而为了检测边缘点,需要对整张地图进行处理,而这个操作通常是耗时的,为此大量的研究人员focus在检测frontier edges的效率上。

本包中,RRT树只是用于search边缘点,而检测到的边缘点经过滤波就会依次安排给机器人。当机器人接收到point时,就会运动到对应的点。在此期间,机器人上的传感器将会扫描建图。

而通过多个独立的RRT树来加速边缘点的检测,则是本包的创新点。

如下图所示,主要分为三个模块。

  • 基于RRT的边界检测模块(负责检测边界点)
  • 滤波模块(存储边界点,并通过mean shift算法来聚类,检测出无效以及旧的边界点)
  • 以及task allocator模块(接收到滤波模块传来的边界点后,分配到机器人)

而本包还需要与SLAM及path planning模块相结合来使用

 

 关于global与local detector。如下图所示。当检测到一个边界点时,local detector会reset,并且会基于机器人当前的位置重新生长。这带来两个好处:1、检测边界点更快。因为机器人总是会向着边界点移动,而如果RRT树从机器人当前的位置开始,那么它到达未知区域的概率更高。2、机器人可能会miss掉一些地图上边角的小的边界点,而为了解决这个问题,就通过global detector。但随着地图的变大,global detector会越来越慢(或者说,随着树的变大,exploration会变慢),为此需要local detector

而关于assigner,其基于以下几个要素来分配机器人导航的目标点:

  • Navigation cost
  • Information gain

仿真

而本博文基于rrt_exploration包来进行仿真。网上也有大把基于此包的博客。但是本人实现时都无法跑动(可能是版本的原因?老显示tf无法链)为此,更改了原包的机器人模型为turtlebot3 waffle并且调了一些路径规划的参数,终于调出来了,效果如下视频所示~

single kobuki robot slam based on rrt

单机器人自主探索建图

单机器人自主探索建图(1)

换成kobuki模型效果好很多~

运行命令:

roslaunch rrt_exploration_tutorials single_simulated_house.launch
roslaunch rrt_exploration single.launch 

注意要保证move base的开启

single_simulated_house.launch

<!--  Launch file for signle robot on Gazebo -->
<launch>
<env name="GAZEBO_RESOURCE_PATH" value="$(find rrt_exploration_tutorials)/launch/includes/meshes"/>
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="use_sim_time" value="true"/>
<arg name="debug" value="false"/>
<arg name="world_name" value="$(find rrt_exploration_tutorials)/launch/includes/worlds/house.world"/>
<!-- <remap from="/robot_1/cmd_vel" to="/robot_1/mobile_base/commands/velocity"/> -->
</include>

<group ns="robot_1">
<include file="$(find rrt_exploration_tutorials)/launch/includes/robot.launch.xml">
<arg name="robot_name" value="robot_1"/>
<arg name="init_pose" value="-x 0.0 -y 0.0 -z 0.0"/>
</include>

<include file="$(find rrt_exploration_tutorials)/launch/includes/move_baseSafe.launch">
<arg name="namespace" value="robot_1"/>
</include> 
</group>

<node pkg="rviz" type="rviz" name="rviz" args="-d $(find rrt_exploration_tutorials)/launch/includes/rviz_config/single.rviz">
<remap from="move_base_simple/goal" to="robot_1/move_base_simple/goal"/>
</node>

</launch>



move_baseSafe.launch

<!-- move base -->
<launch>
  <master auto="start"/>

  <arg name="namespace"/>

   <arg name="model" default="$(env TURTLEBOT3_MODEL)" doc="model type [burger, waffle, waffle_pi]"/>
  <!-- <arg name="cmd_vel_topic" default="/cmd_vel" /> -->
  <!-- <arg name="odom_topic" default="odom" />
  <arg name="move_forward_only" default="false"/> -->


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

    <!-- <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen" >
      <remap from="scan" to="base_scan"/>
      <param name="map_frame" value="$(arg namespace)/map"/>
      <param name="odom_frame" value="$(arg namespace)/odom"/>
      <param name="base_frame" value="$(arg namespace)/base_link"/>
      <param name="map_update_interval" value="2.0"/>
      <param name="maxUrange" value="50.0"/>
      <param name="maxRange" value="50.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="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.01"/>
      <param name="angularUpdate" value="0.01"/>
      <param name="temporalUpdate" value="0.1"/>
      <param name="resampleThreshold" value="0.5"/>
      <param name="particles" value="30"/>
      <param name="xmin" value="-5.0"/>
      <param name="ymin" value="-5.0"/>
      <param name="xmax" value="5.0"/>
      <param name="ymax" value="5.0"/>
      <param name="delta" value="0.1"/>
      <param name="llsamplerange" value="0.01"/>
      <param name="llsamplestep" value="0.01"/>
      <param name="lasamplerange" value="0.005"/>
      <param name="lasamplestep" value="0.005"/>
      <param name="minimumScore" value="0.005"/>
    </node> -->


  <!-- <node pkg="move_base" type="move_base" respawn="false" name="move_base_node" output="screen">
    <param name="footprint_padding" value="0.01" />
    <param name="controller_frequency" value="5.0" />
    <param name="controller_patience" value="3.0" />
    <param name="oscillation_timeout" value="30.0" />
    <param name="oscillation_distance" value="0.5" />
    <param name="planner_patience" value="1" />
    <param name="controller_patience" value="1" /> 
    <remap from="cmd_vel" to="mobile_base/commands/velocity"/>
    <param name="recovery_behavior_enabled" value="false" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/global_costmap_params.yaml" command="load" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/base_local_planner_params.yaml" command="load" />  
    <param name="global_costmap/global_frame" value="$(arg namespace)/map"/>
    <param name="global_costmap/robot_base_frame" value="$(arg namespace)/base_link"/>
    <param name="global_costmap/laser_scan_sensor/sensor_frame" value="/$(arg namespace)/base_laser_link"/>
    <param name="global_costmap/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>    
    <param name="local_costmap/global_frame" value="$(arg namespace)/odom"/>
    <param name="local_costmap/robot_base_frame" value="$(arg namespace)/base_link"/>
    <param name="local_costmap/laser_scan_sensor/sensor_frame" value="$(arg namespace)/base_laser_link"/>
    <param name="local_costmap/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>
    <param name="local_costmap/obstacle_layer/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>
  </node> -->

   <!-- <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
    <param name="base_frame" value="$(arg namespace)/base_link"/>
    <param name="odom_frame" value="$(arg namespace)/odom"/>
    <param name="map_frame"  value="$(arg namespace)/map"/>
    <param name="map_update_interval" value="2.0"/>
    <param name="maxUrange" value="3.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="50"/>
    <param name="srr" value="0.1"/>
    <param name="srt" value="0.2"/>
    <param name="str" value="0.1"/>
    <param name="stt" value="0.2"/>
    <param name="linearUpdate" value="1.0"/>
    <param name="angularUpdate" value="0.2"/>
    <param name="temporalUpdate" value="0.5"/>
    <param name="resampleThreshold" value="0.5"/>
    <param name="particles" value="100"/>
    <param name="xmin" value="-10.0"/>
    <param name="ymin" value="-10.0"/>
    <param name="xmax" value="10.0"/>
    <param name="ymax" value="10.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"/>
  </node> -->

   <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
    <param name="base_frame" value="$(arg namespace)/base_link"/>
    <param name="odom_frame" value="$(arg namespace)/odom"/>
    <param name="map_frame"  value="$(arg namespace)/map"/>
    <param name="map_update_interval" value="2.0"/>
    <param name="maxUrange" value="50.0"/>
    <param name="maxRange" value="50.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="50"/> -->
    <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.01"/>
    <param name="angularUpdate" value="0.01"/>
    <param name="temporalUpdate" value="0.1"/>
    <param name="resampleThreshold" value="0.5"/>
    <param name="particles" value="100"/>
    <param name="xmin" value="-10.0"/>
    <param name="ymin" value="-10.0"/>
    <param name="xmax" value="10.0"/>
    <param name="ymax" value="10.0"/>
    <param name="delta" value="0.1"/>
    <param name="llsamplerange" value="0.01"/>
    <param name="llsamplestep" value="0.01"/>
    <param name="lasamplerange" value="0.005"/>
    <param name="lasamplestep" value="0.005"/>
    <param name="minimumScore" value="0.005"/>
  </node>


   <node pkg="move_base" type="move_base" respawn="false" name="move_base_node" output="screen">
    <param name="footprint_padding" value="0.01" />
    <param name="controller_frequency" value="5.0" />
    <param name="controller_patience" value="3.0" />
    <param name="oscillation_timeout" value="30.0" />
    <param name="oscillation_distance" value="0.05" />
    <param name="planner_patience" value="1" />
    <param name="controller_patience" value="1" /> 
    <!-- <remap from="cmd_vel" to="mobile_base/commands/velocity"/> -->
    <remap from="cmd_vel" to="cmd_vel"/>
    <param name="recovery_behavior_enabled" value="false" />
    <param name="clearing_rotation_allowed" value="true" />
    <param name="min_vel_x" value="-0.3" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/global_costmap_params.yaml" command="load" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/base_local_planner_params.yaml" command="load" />  
    
    <!-- <rosparam file="$(find turtlebot3_navigation)/param/a_costmap_common_params_$(arg model).yaml" command="load" ns="global_costmap" /> -->
    <!-- <rosparam file="$(find turtlebot3_navigation)/param/a_costmap_common_params_$(arg model).yaml" command="load" ns="local_costmap" /> -->
    <!-- <rosparam file="$(find turtlebot3_navigation)/param/a_local_costmap_params.yaml" command="load" /> -->
    <!-- <rosparam file="$(find turtlebot3_navigation)/param/a_global_costmap_params.yaml" command="load" /> -->

    <!-- move_based对应的参数 -->
    <!-- <rosparam file="$(find turtlebot3_navigation)/param/move_base_params.yaml" command="load" /> -->
    <!-- 局部路径规划对应的参数 -->
    <!-- <rosparam file="$(find rrt_exploration_tutorials)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find rrt_exploration_tutorials)/param/global_costmap_params.yaml" command="load" /> -->
    <!-- <rosparam file="$(find rrt_exploration_tutorials)/param/base_local_planner_params.yaml" command="load" /> -->

    <!-- <param name="base_local_planner" value="dwa_local_planner/DWAPlannerROS" />
    <rosparam file="$(find turtlebot3_navigation)/param/dwa_local_planner_params_$(arg model).yaml" command="load" />
    <remap from="odom" to="$(arg odom_topic)"/>
    <param name="DWAPlannerROS/min_vel_x" value="0.0" if="$(arg move_forward_only)" /> -->

    <param name="global_costmap/global_frame" value="$(arg namespace)/map"/>
    <param name="global_costmap/robot_base_frame" value="$(arg namespace)/base_link"/>
    <param name="global_costmap/laser_scan_sensor/sensor_frame" value="/$(arg namespace)/base_laser_link"/>
    <param name="global_costmap/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>    
    <param name="local_costmap/global_frame" value="$(arg namespace)/odom"/>
    <param name="local_costmap/robot_base_frame" value="$(arg namespace)/base_link"/>
    <param name="local_costmap/laser_scan_sensor/sensor_frame" value="$(arg namespace)/base_laser_link"/>
    <param name="local_costmap/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>
    <param name="local_costmap/obstacle_layer/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>
  </node> 

   <!-- <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen"> -->
    <!-- 启动局部路径规划base_local_planner,选用dwa_local_planner/DWAPlannerROS方法 -->
    <!-- <param name="base_local_planner" value="dwa_local_planner/DWAPlannerROS" /> -->
    <!-- 启动costmap节点及对应的参数 -->
    <!-- <rosparam file="$(find turtlebot3_navigation)/param/costmap_common_params_$(arg model).yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find turtlebot3_navigation)/param/costmap_common_params_$(arg model).yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find turtlebot3_navigation)/param/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find turtlebot3_navigation)/param/global_costmap_params.yaml" command="load" /> -->
    <!-- move_based对应的参数 -->
    <!-- <rosparam file="$(find turtlebot3_navigation)/param/move_base_params.yaml" command="load" /> -->
    <!-- 局部路径规划对应的参数 -->
    <!-- <rosparam file="$(find turtlebot3_navigation)/param/dwa_local_planner_params_$(arg model).yaml" command="load" />
    <remap from="cmd_vel" to="$(arg cmd_vel_topic)"/>
    <remap from="odom" to="$(arg odom_topic)"/>
    <param name="global_costmap/global_frame" value="$(arg namespace)/map"/>
    <param name="global_costmap/robot_base_frame" value="$(arg namespace)/base_link"/>
    <param name="global_costmap/laser_scan_sensor/sensor_frame" value="$(arg namespace)/base_scan"/>
    <param name="global_costmap/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>    
    <param name="local_costmap/global_frame" value="$(arg namespace)/odom"/>
    <param name="local_costmap/robot_base_frame" value="$(arg namespace)/base_link"/>
    <param name="local_costmap/laser_scan_sensor/sensor_frame" value="$(arg namespace)/base_scan"/>
    <param name="local_costmap/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>
    <param name="local_costmap/obstacle_layer/laser_scan_sensor/topic" value="/$(arg namespace)/base_scan"/>
    <param name="DWAPlannerROS/min_vel_x" value="0.0" if="$(arg move_forward_only)" />
  </node> -->

</launch>

robot.launch.xml

<!--
  Spawns Kobuki inside a Gazebo simulation
  -->
<launch>
  <arg name="robot_name"/>
  <arg name="init_pose"/>
  <arg name="model" default="$(env TURTLEBOT3_MODEL)" doc="model type [burger, waffle, waffle_pi]"/>

  <include file="$(find turtlebot3_bringup)/launch/includes/description.launch.xml">
    <arg name="model" value="$(arg model)" />
  </include>

  <param name="robot_description" command="$(find xacro)/xacro --inorder $(find turtlebot3_description)/urdf/turtlebot3_$(arg model).urdf.xacro" />
  <node pkg="gazebo_ros" type="spawn_model" name="spawn_$(arg robot_name)" 
        args="$(arg init_pose) -unpause -urdf -param robot_description -model $(arg robot_name)" respawn="false">
  </node>

  <!-- <param name="robot_description"
        command="$(find xacro)/xacro.py '$(find rrt_exploration_tutorials)/launch/includes/urdf/kobuki_standalone.urdf.xacro'"/>
  <node pkg="gazebo_ros" type="spawn_model" name="spawn_$(arg robot_name)" 
        args="$(arg init_pose) -unpause -urdf -param robot_description -model $(arg robot_name)" respawn="false">
  </node> -->
 
   <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
   <param name="publish_frequency" type="double" value="30.0" />
   <param name="use_tf_static" type="bool" value="false" />
   <param name="tf_prefix" type="string" value="$(arg robot_name)"/>
   </node>
</launch>

single.launch

<!-- Launch file for the rrt-detector and the assigner -->


<launch>
<arg name="eta" value="1.0"/>
<arg name="Geta" value="15.0"/>
<param name="namespace_init_count" value="1"/>


  <node pkg="rrt_exploration" type="global_rrt_detector" name="global_detector" output="screen">
  <param name="eta" value="$(arg Geta)"/>
  <param name="map_topic" value="robot_1/map"/>
  </node>
  
  <node pkg="rrt_exploration" type="local_rrt_detector" name="local_detector" output="screen">
  <param name="eta" value="$(arg eta)"/>
  <param name="map_topic" value="robot_1/map"/>
  <param name="robot_frame" value="robot_1/base_link"/>
  </node>
 
  
  <node pkg="rrt_exploration" type="filter.py" name="filter" output="screen">
  <param name="map_topic" value="robot_1/map"/>
  <param name="info_radius" value="1"/> 
  <param name="costmap_clearing_threshold" value="70"/> 
  <param name="goals_topic" value="/detected_points"/>
  <param name="namespace" value="robot_"/> 
  <param name="n_robots" value="1"/>
  <param name="rate" value="100"/>
  </node>
  
  <node pkg="rrt_exploration" type="assigner.py" name="assigner" output="screen">
  <param name="map_topic" value="robot_1/map"/>
  <param name="global_frame" value="robot_1/map"/>
  <param name="info_radius" value="1"/> 
  <param name="info_multiplier" value="3.0"/> 
  <param name="hysteresis_radius" value="3.0"/> 
  <param name="hysteresis_gain" value="2.0"/> 
  <param name="frontiers_topic" value="/filtered_points"/> 
  <param name="n_robots" value="1"/>
  <param name="namespace" value="robot_"/>
  <param name="delay_after_assignement" value="0.5"/>
  <param name="rate" value="100"/>
  </node>
  
</launch>

实验

实验效果及视频如下:

(experiment) single kobuki robot slam based on rrt

参考资料

http://wiki.ros.org/rrt_exploration/Tutorials/singleRobot

https://github.com/hasauino/rrt_exploration_tutorials

https://github.com/hasauino/rrt_exploration

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值