在看完自主导航小车实践的教程(自主导航小车实践)后,很多小伙伴留言说,在学习自主导航小车的时候手上没有合适的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环境安装
首先,通过以下命令行安装运行依赖项:
<code class="prism language-bash has-numbering"><span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> ros-kinetic-turtlebot-gazebo <span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> ros-kinetic-turtlebot-simulator </code>
安装完毕以后我们使用如下命令启动turtlebot stage仿真环境,先直观感受一下stage仿真环境和自主导航这个功能
<code class="prism language-bash has-numbering"> roslaunch turtlebot_stage turtlebot_in_stage.launch </code>
启动stage仿真以后我们会看到如下界面:
一个是我们熟悉的RVIZ的界面,另外一个是turtlebot的stage仿真环境,如果你不喜欢2D的视角,我们可以选择stage窗口中的 view-> perspective camera 将视角切换成3D视角。
我们点击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 目录下创建一个包来存放我们实验的文件:
<code class="prism language-bash has-numbering">catkin_create_pkg my_turtlebot_nav roscpp rospy std_msgs <span class="token function">cd</span> my_turtlebot_nav <span class="token function">mkdir</span> launch <span class="token function">cd</span> launch </code>
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 新建一个窗口输入以下命令
<code class="prism language-bash has-numbering">roslaunch turtlebot_teleop keyboard_teleop.launch </code>
这时候通过 “i,u, o, k” 建即可控制机器人移动,这里相当于是我们启动了一个方正的turtlebot 机器人,这个机器人运行在一个’房间‘里面这个机器人可以接受cmd_vel话题的数据,同时发布里程计数据和机器人身上的激光传感器的数据。激光的数据可以通过rostopic list 等命令进行查看
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移动,扫描环境中的地图
<code class="prism language-bash has-numbering">roslaunch my_turtlebot_nav turtlebot_stage.launch </code>
<code class="prism language-bash has-numbering">roslaunch turtlebot_teleop keyboard_teleop.launch </code>
<code class="prism language-bash has-numbering">roslaunch my_turtlebot_nav gmapping.launch </code>
通过键盘的 “i,u, o, k” 建控制机器人在房间里面移动,扫描地图。(实际扫描了几次,发现这个gmapping在机器人旋转的时候就会出现地图变形的情况,还不如在实物上跑的效果好。估计是由于这个仿真环境是把Kinect的数据弄成激光数据的缘故,而我们实际使用的激光雷达都是360度的),下面是几次里面比较好的地图了┭┮﹏┭┮
视频地址:https://www.bilibili.com/video/av75059044/ 7 用map_server保存地图:
<code class="prism language-bash has-numbering">rosrun map_server map_saver -f <span class="token function">test </span> </code>
这时候可以看到当前目录下存在以“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 这个包里面直接拷贝过来
<code class="prism language-bash has-numbering">roslaunch my_turtlebot_nav turtlebot_stage.launch roslaunch my_turtlebot_nav turtlebot_navigation.launch </code>
用RVIZ中的 “2D Nav Goal” 设定一个目标点就可以让小车自动运行到目标点了 视频地址:https://www.bilibili.com/video/av75052359
2、gazebo 仿真环境
基于前面介绍的stage仿真环境,这里我们首先介绍如何利用gazebo仿真环境来一步一步的配置自主导航小车的每一个环节。 1、安装依赖项:
<code class="prism language-bash has-numbering"><span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> ros-kinetic-turtlebot <span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> ros-kinetic-turtlebot-*</code>
<code class="prism language-bash has-numbering"></code>
2、启动turtlebot Gazebo仿真节点,即可看到如下界面
<code class="prism language-bash has-numbering">roslaunch turtlebot_gazebo turtlebot_world.launch </code>
(注意:如果你发现你的gazebo没法打开,这可能是你下载的模型包不完整,可以参考“ROS下gazebo不能加载模型文件”这篇博客修改) 3、作为测试仿真环境是否正常工作,我们同样使用turtlebot的键盘包来测试gazebo仿真模型是否可以接受到“cmd_vel”这个话题的数据。 启动键盘遥控节点
<code class="prism language-bash has-numbering">roslaunch turtlebot_teleop keyboard_teleop.launch </code>
启动turtlebot Gazebo仿真节点
<code class="prism language-bash has-numbering">roslaunch turtlebot_gazebo turtlebot_world.launch </code>
到这里我们基本上已经实现了用gazebo来模拟一个机器人底盘,上层的组件按照我们在stage环境中配置好的文件,可直接使用。(注意:需要重新建图,并更换AMCL中的地图文件) 这个任务就留给大家当做作业吧:
- 1、用我们刚刚配置的 my_turtlebot_nav 包来控制gazebo中的turtlebot,实现2D导航
- 2、ROS stage 仿真与gazebo仿真有什么不一样的?
- 3、gazeboz中使用不同世界模型文件