ROS仿真环境中实现自主导航

676
0
2020年10月22日 09时06分

在看完自主导航小车实践的教程(自主导航小车实践)后,很多小伙伴留言说,在学习自主导航小车的时候手上没有合适的ROS机器人底盘做实验,缺少动手操作的机会,学习不深刻。对于底盘问题,我们也分享过一个制作麦克纳姆轮底盘的教程,手头有材料的同学可以参考参考(ROS麦克纳姆轮底盘制作)
这里还有另外一种方式解决底盘的问题,我们可以通过ROS提供的仿真环境来理解这个自主导航小车的框架,ROS中提供有很多的机器人的仿真模型比如说pr2、turtlebot、turtlebot3等机器人,仿真环境有gazebo和stage等环境。那么有小伙伴可能会问:仿真环境中的机器人与实际机器人控制起来差别大吗?ROS提供的仿真机器人模型与实际机器人差异很小,基本上可以达到仿真环境的效果,如果使用好一点的激光雷达,建图的效果可能会更好。为了解决在理解自主导航小车框架时,没有实际机器人操作这个问题。我们整理一个利用turtlebot的仿真模型实现自主导航小车的教程。

 

我们发现一个真实的ROS底盘主要有三个功能:

  • 1、接收“/cmd_vel”这个话题的控制数据
  • 2、发布odom里程计数据
  • 3、提供激光雷达或者视觉相机的数据 /scan

因此,只要我们使用仿真环境中的机器人接收“/cmd_vel”话题数据,控制仿真环境中的机器人运动,同时接收仿真机器人发布的odom里程计话题和激光雷达数据,这样就可以用仿真模型“替代”一个真实世界的机器人。

讲解完思路以后,我们开始实际操作环节(系统环境 Ubuntu 1604 + ROS Kinect 代码)。

 

1、turtlebot stage 仿真环境

ROS常用的仿真环境有gazebo和stage两种,gazebo更加的强大,但是在虚拟机上运行不顺畅。这里我们首先介绍利用stage 仿真环境来一步一步的配置自主导航小车的每一个环节,在第二部分介绍使用gazebo来仿真。

 

1.1 stage环境安装

首先,通过以下命令行安装运行依赖项:

 

sudo apt-get install ros-kinetic-turtlebot-gazebo
sudo apt-get install ros-kinetic-turtlebot-simulator

 

安装完毕以后我们使用如下命令启动turtlebot stage仿真环境,先直观感受一下stage仿真环境和自主导航这个功能

 

 roslaunch turtlebot_stage turtlebot_in_stage.launch

 

启动stage仿真以后我们会看到如下界面:

 

1

 

一个是我们熟悉的RVIZ的界面,另外一个是turtlebot的stage仿真环境,如果你不喜欢2D的视角,我们可以选择stage窗口中的 view-> perspective camera 将视角切换成3D视角。

 

2

 

我们点击RVIZ中的 “2D Nav Goal” 设定一个目标点就可以让小车自动运行到这个点了

视频地址:https://www.bilibili.com/video/av75041785/

 

我们现在来看看这个单独配置stage节点、gmapping建图节点、导航节点。其实这些在turtlebot_stage 包中的 turtlebot_in_stage.launch 文件中都有描述,你也可以直接看这个launch文件。

 

1.2 turtlebot 仿真环境中gmapping 建图

1 我们在catkin_ws/src 目录下创建一个包来存放我们实验的文件:

 

catkin_create_pkg my_turtlebot_nav roscpp rospy std_msgs
cd my_turtlebot_nav 
mkdir launch
cd launch

 

2 接下来我们在launch文件夹下面创建一个名为“turtlebot_stage.launch” 的文件,并填入以下内容:

 

<?xml version="1.0"?>
<launch>
  <arg name="base"       default="$(optenv TURTLEBOT_BASE kobuki)"/>  <!-- create, rhoomba -->
  <arg name="stacks"     default="$(optenv TURTLEBOT_STACKS hexagons)"/>  <!-- circles, hexagons -->
  <arg name="3d_sensor"  default="$(optenv TURTLEBOT_3D_SENSOR kinect)"/>  <!-- kinect, asus_xtion_pro -->

  <!-- Name of the map to use (without path nor extension) and initial position -->
  <arg name="map_file"       default=" $(env TURTLEBOT_STAGE_MAP_FILE)"/> <!-- robopark_plan -->
  <arg name="world_file"     default=" $(env TURTLEBOT_STAGE_WORLD_FILE)"/>
  <arg name="initial_pose_x" default="2.0"/>
  <arg name="initial_pose_y" default="2.0"/>
  <arg name="initial_pose_a" default="0.0"/>

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

  <!--  ******************** Stage ********************  -->
  <node pkg="stage_ros" type="stageros" name="stageros" args="$(arg world_file)">
    <param name="base_watchdog_timeout" value="0.5"/>
    <remap from="odom" to="odom"/>
    <remap from="base_pose_ground_truth" to="base_pose_ground_truth"/>
    <remap from="cmd_vel" to="mobile_base/commands/velocity"/>
    <remap from="base_scan" to="scan"/>
  </node>

  <!--  ***************** Robot Model *****************  -->
  <include file="$(find turtlebot_bringup)/launch/includes/robot.launch.xml">
    <arg name="base" value="$(arg base)" />
    <arg name="stacks" value="$(arg stacks)" />
    <arg name="3d_sensor" value="$(arg 3d_sensor)" />
  </include>
  <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher">
    <param name="use_gui" value="true"/>
  </node>

  <!-- Command Velocity multiplexer -->
  <node pkg="nodelet" type="nodelet" name="mobile_base_nodelet_manager" args="manager"/>
  <node pkg="nodelet" type="nodelet" name="cmd_vel_mux" args="load yocs_cmd_vel_mux/CmdVelMuxNodelet mobile_base_nodelet_manager">
    <param name="yaml_cfg_file" value="$(find turtlebot_bringup)/param/mux.yaml"/>
    <remap from="cmd_vel_mux/output" to="mobile_base/commands/velocity"/>
  </node>

</launch>

 

3 启动刚刚创建的launch文件

 

cd catkin_ws/
source devel/setup.bash
roslaunch my_turtlebot_nav turtlebot_stage.launch 

 

相比于我们刚刚用的演示的demo,现在只有一个stage窗口启动的,没有其他的导航节点启动。这就相当于我们启动机器人的底盘是一样的。这里我们测试用turtlebot自带的键盘遥控节点测试 是否可以用个键盘控制仿真环境中的机器人移动

 

4

 

 

4 新建一个窗口输入以下命令

 

roslaunch turtlebot_teleop keyboard_teleop.launch 

 

这时候通过 “i,u, o, k” 建即可控制机器人移动,这里相当于是我们启动了一个方正的turtlebot 机器人,这个机器人运行在一个’房间‘里面这个机器人可以接受cmd_vel话题的数据,同时发布里程计数据和机器人身上的激光传感器的数据。激光的数据可以通过rostopic list 等命令进行查看

 

5

 

5 有了这样一个机器人,我们利用机器人携带的激光传感器进行建图工作,这里方便简单我们使用我们熟悉的gmapping建图的方式。新建一个名为gmapping.launch的文件,填入以下内容:

 

<?xml version="1.0"?>
<launch>
  <arg name="scan_topic" default="scan" />
  <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
    <param name="odom_frame" value="odom"/>
    <param name="base_frame" value="base_link"/>
    <param name="map_frame" value="map"/>

    <!-- Process 1 out of every this many scans (set it to a higher number to skip more scans)  -->
    <param name="throttle_scans" value="1"/>
    <param name="map_update_interval" value="5.0"/> <!-- default: 5.0 -->

    <!-- The maximum usable range of the laser. A beam is cropped to this value.  -->
    <param name="maxUrange" value="5.0"/>

    <!-- The maximum range of the sensor. If regions with no obstacles within the range of the sensor should appear as free space in the map, set maxUrange < maximum range of the real sensor <= maxRange -->
    <param name="maxRange" value="10.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="minimumScore" value="0.0"/>
    <!-- Number of beams to skip in each scan. -->
    <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"/>

    <!-- Process a scan each time the robot translates this far  -->
    <param name="linearUpdate" value="0.1"/>

    <!-- Process a scan each time the robot rotates this far  -->
    <param name="angularUpdate" value="0.05"/>

    <param name="temporalUpdate" value="-1.0"/>
    <param name="resampleThreshold" value="0.5"/>

    <!-- Number of particles in the filter. default 30        -->
    <param name="particles" value="10"/>

<!-- Initial map size  -->
    <param name="xmin" value="-10.0"/>
    <param name="ymin" value="-10.0"/>
    <param name="xmax" value="10.0"/>
    <param name="ymax" value="10.0"/>

    <!-- Processing parameters (resolution of the map)  -->
    <param name="delta" value="0.02"/>

    <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>
</launch>

 

 

6 接下来我们分别打开三个终端,启动stage节点、和gmapping节点利用遥控器遥控turtlebot移动,扫描环境中的地图

 

roslaunch my_turtlebot_nav turtlebot_stage.launch 

 

roslaunch turtlebot_teleop keyboard_teleop.launch 

 

roslaunch my_turtlebot_nav gmapping.launch 

 

通过键盘的 “i,u, o, k” 建控制机器人在房间里面移动,扫描地图。(实际扫描了几次,发现这个gmapping在机器人旋转的时候就会出现地图变形的情况,还不如在实物上跑的效果好。估计是由于这个仿真环境是把Kinect的数据弄成激光数据的缘故,而我们实际使用的激光雷达都是360度的),下面是几次里面比较好的地图了┭┮﹏┭┮

 

7

 

视频地址:https://www.bilibili.com/video/av75059044/

 

7 用map_server保存地图:

 

rosrun map_server map_saver -f test

 

这时候可以看到当前目录下存在以“test”开头的两个文件

在这里插入图片描述

 

1.3 turtlebot 仿真环境中导航

创建文件 turtlebot_navigation.launch 并填入以下内容:

 

<?xml version="1.0"?>
<launch>
  <arg name="initial_pose_x" default="2.0"/>
  <arg name="initial_pose_y" default="2.0"/>
  <arg name="initial_pose_a" default="0.0"/>

  <!--  ************** Navigation  ***************  -->
  <include file="$(find my_turtlebot_nav)/launch/include/move_base.launch.xml"/>

  <!--  ****** Maps *****  -->
  <arg name="map_file" default="$(find my_turtlebot_nav)/map/maze.yaml"/>
  <node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)">
    <param name="frame_id" value="/map"/>
  </node>
 

  <include file="$(find my_turtlebot_nav)/launch/include/amcl.launch.xml">
    <arg name="scan_topic" value="scan"/>
    <arg name="use_map_topic" value="true"/>
    <arg name="initial_pose_x" value="$(arg initial_pose_x)"/>
    <arg name="initial_pose_y" value="$(arg initial_pose_y)"/>
    <arg name="initial_pose_a" value="$(arg initial_pose_a)"/>
  </include>

  <!--  **************** Visualisation ****************  -->
  <node name="rviz" pkg="rviz" type="rviz" args="-d $(find my_turtlebot_nav)/rviz/robot_navigation.rviz"/>
</launch>

 

 

这里AMCL和move_base是单独的文件进行配置的,我把我所用的包都放在了这个github地址上,你可以直接down下来,或者从turtlebot_navigation 这个包里面直接拷贝过来

 

roslaunch my_turtlebot_nav turtlebot_stage.launch 
roslaunch my_turtlebot_nav turtlebot_navigation.launch 

 

用RVIZ中的 “2D Nav Goal” 设定一个目标点就可以让小车自动运行到目标点了

视频地址:https://www.bilibili.com/video/av75052359

 

2、gazebo 仿真环境

基于前面介绍的stage仿真环境,这里我们首先介绍如何利用gazebo仿真环境来一步一步的配置自主导航小车的每一个环节。

1、安装依赖项:

 

sudo apt-get install ros-kinetic-turtlebot
sudo apt-get install ros-kinetic-turtlebot-*

 

2、启动turtlebot Gazebo仿真节点,即可看到如下界面

 

roslaunch turtlebot_gazebo turtlebot_world.launch

 

7

 

(注意:如果你发现你的gazebo没法打开,这可能是你下载的模型包不完整,可以参考“ROS下gazebo不能加载模型文件”这篇博客修改)
3、作为测试仿真环境是否正常工作,我们同样使用turtlebot的键盘包来测试gazebo仿真模型是否可以接受到“cmd_vel”这个话题的数据。
启动键盘遥控节点

 

roslaunch turtlebot_teleop keyboard_teleop.launch

 

启动turtlebot Gazebo仿真节点

 

roslaunch turtlebot_gazebo turtlebot_world.launch

 

到这里我们基本上已经实现了用gazebo来模拟一个机器人底盘,上层的组件按照我们在stage环境中配置好的文件,可直接使用。(注意:需要重新建图,并更换AMCL中的地图文件

这个任务就留给大家当做作业吧:

  • 1、用我们刚刚配置的 my_turtlebot_nav 包来控制gazebo中的turtlebot,实现2D导航
  • 2、ROS stage 仿真与gazebo仿真有什么不一样的?
  • 3、gazeboz中使用不同世界模型文件

 

8

 

 

 

 

发表评论

后才能评论