目前爲止, 我們都旨在構建一個能夠自主運行的機器人,這個就研究方向更加合理的名詞應該叫自主移動機器人. 推薦一本個人覺得很不錯的書 Ronald C. Arkin - 2011- Introduction to Autonomous Mobile Robots. 本文的主要目的是先把框架搭起來, 採用原型模式, 然後在此基礎上循環的進行深化, 望能夠起到拋磚引玉的作用.
Part 5 機器人環境探索與避障
一個完整的自主移動機器人應該是一個see-think-act的環路, 包括機器人感知, 定位與製圖, 路徑規劃, 運動控制.
導航規劃部分可以分爲全局的目標導航(路徑規劃), 和局部的導航(避障). 機器人剛開始進入環境. 沒有明確的終點設定, 機器人在環境中進行自由探索, 主要依賴避障來控制機器人的運動.
Turtlebot提供Kinect相機可以用於避障, 對於RGB-D深度相機的避障可分爲兩類. 第一就是直接採用Kinect點雲避障, 可以使用SBPL (Search-based planning library), OMPL (Open Motion Planning Library)等庫. 第二類, 將點雲轉換爲平面的laser scan, 類似於gmapping, cartographer, 採用DWA (Dynamic Window Approach) 或者 TEB (Timed Elastic Band algorithm)避障.
這裏我們採用一種更加簡單的方式, 將點雲進行裁剪, 然後在水平方向求和, 根據左右兩邊障礙物點雲判斷向左向右運動, 參考robot-photographer.
1 架構
本文中所述的自主移動機器人採用turtlebot, 從Kinect 採集點雲傳入obstacle avoidance 節點中,給出避障轉向; navigation節點根據機器人避障轉向信息和收到的指令信息做出最終的控制決策,傳入到locomotion節點; 最後locomotion節點給出機器人的運動控制命令.
在明白框架後, 故事就很清晰了, 畢竟沒有怎麼涉及理論的東西,
2 軟件
整個project中, 包含四個文件夾turtlebotslam_gazebo, turtlebotslam_obstacle_avoidance, turtlebotslam_navigation, turtlebotslam_locomotion, 其目錄如下所示:
├── turtlebotslam_gazebo
│ ├── CMakeLists.txt
│ ├── launch
│ │ ├── gmapping_demo.launch
│ │ ├── includes
│ │ │ ├── create.launch.xml
│ │ │ ├── kobuki.launch.xml
│ │ │ └── roomba.launch.xml
│ │ ├── keyboard_teleop.launch
│ │ ├── keyop.launch
│ │ ├── turtlebotslam_gazebo.launch
│ │ └── turtlebotslam_rviz.launch
│ ├── package.xml
│ ├── rviz
│ │ └── navigation.rviz
│ ├── src
│ └── worlds
│ ├── barrier.world
│ ├── cafe.world
│ ├── corridor.world
│ ├── empty.world
│ └── playground.world
├── turtlebotslam_locomotion
│ ├── CMakeLists.txt
│ ├── CMakeLists.txt~
│ ├── include
│ │ ├── direction_source.h
│ │ ├── driving_direction.h
│ │ ├── locomotion.hpp
│ │ ├── locomotion_state.h
│ │ └── turtlebotslam_locomotion
│ ├── launch
│ │ └── locomotion.launch
│ ├── package.xml
│ ├── param
│ │ └── keyop_smoother.yaml
│ └── src
│ └── locomotion.cpp
├── turtlebotslam_navigation
│ ├── CMakeLists.txt
│ ├── CMakeLists.txt~
│ ├── include
│ │ ├── direction_source.h
│ │ ├── driving_direction.h
│ │ └── navigation.hpp
│ ├── launch
│ │ └── navigation.launch
│ ├── package.xml
│ └── src
│ └── navigation.cpp
├── turtlebotslam_obstacle_avoidance
│ ├── CMakeLists.txt
│ ├── CMakeLists.txt~
│ ├── include
│ │ ├── driving_direction.h
│ │ ├── obstacle_avoidance.hpp
│ │ └── turtlebotslam_control
│ ├── launch
│ │ └── obstacle_avoidance.launch
│ ├── package.xml
│ └── src
│ └── obstacle_avoidance.cpp
我將所有需要啓動的部分全部打包到一個單一的launch文件, 包括Gazebo 環境, 機器人模型, 以及深度圖像到點雲的轉換等利用ROS自帶基礎庫的配置部分. 也包括rviz, 避障, 導航, 運動控制, 及gmapping功能部分, 見turtlebotslam_gazebo.launch
<?xml version="1.0"?>
<launch>
<!-- <arg name="world_file" default="$(env TURTLEBOT_GAZEBO_WORLD_FILE)"/> -->
參數說明
<arg name="base" value="$(optenv TURTLEBOT_BASE kobuki)"/> <!-- create, roomba -->
<arg name="battery" value="$(optenv TURTLEBOT_BATTERY /proc/acpi/battery/BAT0)"/> <!-- /proc/acpi/battery/BAT0 -->
<arg name="gui" default="true"/>
<arg name="stacks" value="$(optenv TURTLEBOT_STACKS hexagons)"/> <!-- circles, hexagons -->
<arg name="3d_sensor" value="$(optenv TURTLEBOT_3D_SENSOR kinect)"/> <!-- kinect, asus_xtion_pro -->
在Gazebo中啓動world
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="use_sim_time" value="true"/>
<arg name="debug" value="false"/>
<arg name="gui" value="$(arg gui)" />
<!--arg name="world_name" value="$(arg world_file)"/-->
<arg name="world_name" value="$(find turtlebotslam_gazebo)/worlds/barrier.world"/>
<!--remap from="/camera/rgb/image_raw/compressed" to="/stlucia/camera/image/compressed"/-->
</include>
機器人描述文件
<include file="$(find turtlebotslam_gazebo)/launch/includes/$(arg base).launch.xml">
<arg name="base" value="$(arg base)"/>
<arg name="stacks" value="$(arg stacks)"/>
<arg name="3d_sensor" value="$(arg 3d_sensor)"/>
</include>
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
<param name="publish_frequency" type="double" value="30.0" />
</node>
深度圖像到laser scan
<!-- Fake laser -->
<node pkg="nodelet" type="nodelet" name="laserscan_nodelet_manager" args="manager"/>
<node pkg="nodelet" type="nodelet" name="depthimage_to_laserscan"
args="load depthimage_to_laserscan/DepthImageToLaserScanNodelet laserscan_nodelet_manager">
<param name="scan_height" value="10"/>
<param name="output_frame_id" value="/camera_depth_frame"/>
<param name="range_min" value="0.45"/>
<remap from="image" to="/camera/depth/image_raw"/>
<remap from="scan" to="/scan"/>
</node>
啓動rviz
<include file="$(find turtlebotslam_gazebo)/launch/turtlebotslam_rviz.launch">
</include>
避障
<include file="$(find turtlebotslam_obstacle_avoidance)/launch/obstacle_avoidance.launch">
</include>
導航
<include file="$(find turtlebotslam_navigation)/launch/navigation.launch">
</include>
運動控制
<include file="$(find turtlebotslam_locomotion)/launch/locomotion.launch">
</include>
製圖
<include file="$(find turtlebotslam_gazebo)/launch/gmapping_demo.launch">
</include>
</launch>
工程的源碼下載地址請見:
在ROS中開始自主機器人仿真 - 5 機器人環境探索與避障
3 仿真結果
至此, 一個簡易的自主移動機器人便可以工作了.
下面的命令便可啓動整個仿真過程:
roslaunch turtlebotslam_gazebo turtlebotslam_gazebo.launch
運行結果如下: