Ubuntu 18.04下ROS Melodic安装与移动小车SLAM建图实战手册
当你第一次接触机器人操作系统时,那种既兴奋又忐忑的心情我至今记忆犹新。作为机器人开发领域的瑞士军刀,ROS(Robot Operating System)确实为开发者提供了极大的便利,但它的学习曲线也足以让新手望而生畏。本文将带你从零开始,在Ubuntu 18.04系统上完成ROS Melodic的安装,并最终实现一个移动小车的SLAM建图项目。不同于普通的教程,这里我会分享那些官方文档没告诉你,但实际开发中一定会遇到的"坑"和解决方案。
1. ROS Melodic安装:从系统准备到环境验证
在开始ROS之旅前,确保你的Ubuntu 18.04系统已经更新到最新状态。打开终端(Ctrl+Alt+T),执行以下命令更新软件包列表并升级现有软件:
sudo apt update && sudo apt upgrade -y1.1 配置软件源与密钥
ROS官方源在国内访问可能较慢,我们可以使用国内镜像源加速下载。以下是配置中科大源的完整步骤:
sudo sh -c '. /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ $DISTRIB_CODENAME main" > /etc/apt/sources.list.d/ros-latest.list' sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654注意:如果密钥服务器无法访问,可以尝试替换为
hkp://pgp.mit.edu:80或其他可用服务器
1.2 完整安装ROS Melodic
ROS提供了多种安装包组合,对于初学者我推荐安装ros-melodic-desktop-full,它包含了ROS基础功能包、GUI工具和常用仿真环境:
sudo apt update sudo apt install ros-melodic-desktop-full -y安装过程可能需要15-30分钟,取决于你的网络速度。完成后,我们还需要安装一些构建工具和依赖:
sudo apt install python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential -y1.3 初始化rosdep
rosdep是ROS中用于管理依赖关系的工具,初始化时常见的问题是网络连接失败。我们可以通过以下方式解决:
sudo rosdep init rosdep update如果遇到Website may be down错误,可以尝试修改hosts文件:
echo "199.232.28.133 raw.githubusercontent.com" | sudo tee -a /etc/hosts1.4 环境配置与测试
为了让系统识别ROS命令,需要将ROS环境变量添加到bashrc中:
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc source ~/.bashrc现在,让我们运行经典的"小海龟"demo验证安装是否成功:
- 第一个终端启动ROS核心服务:
roscore- 第二个终端启动海龟仿真器:
rosrun turtlesim turtlesim_node- 第三个终端启动键盘控制节点:
rosrun turtlesim turtle_teleop_key如果能看到蓝色背景上的小海龟,并且能用键盘方向键控制它移动,恭喜你,ROS已经成功安装!
2. 创建工作空间与移动小车模型构建
2.1 初始化ROS工作空间
ROS开发通常在工作空间(workspace)中进行,以下是创建catkin工作空间的标准化流程:
mkdir -p ~/catkin_ws/src cd ~/catkin_ws/ catkin_make source devel/setup.bash提示:可以将
source ~/catkin_ws/devel/setup.bash添加到.bashrc中,这样每次打开终端都会自动加载工作空间环境
2.2 创建移动小车URDF模型
URDF(Unified Robot Description Format)是ROS中描述机器人模型的XML格式文件。我们在src目录下创建一个新的功能包:
cd ~/catkin_ws/src catkin_create_pkg mobile_robot_description urdf xacro在mobile_robot_description/urdf目录下创建mobile_robot.urdf文件,以下是简化版的小车模型定义:
<robot name="mobile_robot"> <link name="base_link"> <visual> <geometry> <box size="0.3 0.2 0.1"/> </geometry> <material name="blue"> <color rgba="0 0 0.8 1"/> </material> </visual> <collision> <geometry> <box size="0.3 0.2 0.1"/> </geometry> </collision> <inertial> <mass value="5"/> <inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/> </inertial> </link> <joint name="left_wheel_joint" type="continuous"> <parent link="base_link"/> <child link="left_wheel"/> <origin xyz="0 0.15 -0.05" rpy="1.5707 0 0"/> <axis xyz="0 1 0"/> </joint> <link name="left_wheel"> <visual> <geometry> <cylinder length="0.05" radius="0.05"/> </geometry> <material name="black"> <color rgba="0 0 0 1"/> </material> </visual> </link> <!-- 右轮定义类似,位置为x="0" y="-0.15" z="-0.05" --> </robot>2.3 添加激光雷达传感器
为了让小车能够感知环境,我们需要添加一个激光雷达传感器。在URDF中添加以下内容:
<link name="laser_link"> <visual> <geometry> <cylinder length="0.05" radius="0.03"/> </geometry> <material name="red"> <color rgba="1 0 0 1"/> </material> </visual> </link> <joint name="laser_joint" type="fixed"> <parent link="base_link"/> <child link="laser_link"/> <origin xyz="0.15 0 0.05" rpy="0 0 0"/> </joint> <!-- 添加Gazebo插件使激光雷达工作 --> <gazebo reference="laser_link"> <sensor type="ray" name="laser_sensor"> <pose>0 0 0 0 0 0</pose> <visualize>true</visualize> <update_rate>10</update_rate> <ray> <scan> <horizontal> <samples>360</samples> <resolution>1</resolution> <min_angle>-3.14159</min_angle> <max_angle>3.14159</max_angle> </horizontal> </scan> <range> <min>0.1</min> <max>10.0</max> <resolution>0.01</resolution> </range> </ray> <plugin name="laser_controller" filename="libgazebo_ros_laser.so"> <topicName>/scan</topicName> <frameName>laser_link</frameName> </plugin> </sensor> </gazebo>2.4 在Gazebo中加载模型
创建启动文件mobile_robot_gazebo.launch:
<launch> <!-- 加载空世界 --> <include file="$(find gazebo_ros)/launch/empty_world.launch"> <arg name="world_name" value="worlds/empty.world"/> </include> <!-- 加载机器人模型 --> <param name="robot_description" textfile="$(find mobile_robot_description)/urdf/mobile_robot.urdf" /> <node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model" args="-param robot_description -urdf -model mobile_robot" /> </launch>启动Gazebo仿真环境:
roslaunch mobile_robot_description mobile_robot_gazebo.launch3. SLAM建图:从理论到实现
3.1 Gmapping算法原理与配置
Gmapping是基于粒子滤波的2D SLAM算法,特别适合激光雷达建图。首先安装相关功能包:
sudo apt install ros-melodic-slam-gmapping ros-melodic-navigation创建SLAM启动文件gmapping.launch:
<launch> <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping"> <param name="base_frame" value="base_link"/> <param name="odom_frame" value="odom"/> <param name="map_update_interval" value="5.0"/> <param name="maxUrange" value="8.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="200"/> <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.5"/> <param name="angularUpdate" value="0.436"/> <param name="temporalUpdate" value="-1.0"/> <param name="resampleThreshold" value="0.5"/> <param name="particles" value="80"/> <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> </launch>3.2 键盘控制与建图实战
我们需要一个节点来控制小车移动,同时观察建图过程。创建键盘控制节点:
sudo apt install ros-melodic-teleop-twist-keyboard然后启动完整的建图流程:
- 第一个终端启动Gazebo仿真:
roslaunch mobile_robot_description mobile_robot_gazebo.launch- 第二个终端启动Gmapping:
roslaunch mobile_robot_description gmapping.launch- 第三个终端启动rviz可视化:
rosrun rviz rviz -d `rospack find mobile_robot_description`/rviz/slam.rviz- 第四个终端启动键盘控制:
rosrun teleop_twist_keyboard teleop_twist_keyboard.py cmd_vel:=/cmd_vel在rviz中添加LaserScan显示,话题选择/scan;添加Map显示,话题选择/map。现在你可以用键盘控制小车移动(i=前进,,=后退,j=左转,l=右转),同时观察地图的构建过程。
3.3 地图保存与导航测试
当建图完成后,可以使用map_server保存地图:
rosrun map_server map_saver -f ~/catkin_ws/src/mobile_robot_description/maps/my_map这将生成两个文件:my_map.pgm(地图图像)和my_map.yaml(地图配置信息)。
4. 常见问题与性能优化
4.1 安装过程中的典型错误
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
E: Unable to locate package ros-melodic-desktop-full | 软件源未正确配置 | 检查/etc/apt/sources.list.d/ros-latest.list是否存在且内容正确 |
rosdep init失败 | 网络连接问题 | 修改hosts或使用代理,参考1.3节 |
| Gazebo启动黑屏 | 显卡驱动问题 | 安装专有驱动或尝试export LIBGL_ALWAYS_SOFTWARE=1 |
| 激光雷达无数据 | 插件加载失败 | 检查URDF中Gazebo插件配置,确保libgazebo_ros_laser.so存在 |
4.2 SLAM建图质量优化技巧
运动控制优化:
- 降低小车的最大速度(建议0.2-0.5 m/s)
- 避免急转弯,转角速度控制在0.5 rad/s以内
- 使用平滑的轨迹运动,减少突然启停
Gmapping参数调整:
- 增加
particles数量(80-200)可提高建图精度,但会增加计算负担 - 减小
delta值(0.01-0.05)可获得更高分辨率的地图 - 调整
linearUpdate和angularUpdate控制地图更新频率
- 增加
环境改进:
- 确保环境有足够的特征(墙面、家具等)
- 避免大面积空白墙面或重复图案
- 保持适当的光照条件(Gazebo中可调整)
4.3 进阶功能扩展
- 使用Xacro简化URDF: Xacro是URDF的宏语言,可以简化复杂模型的描述。例如,可以将轮子的定义转化为宏:
<xacro:macro name="wheel" params="prefix x y z"> <joint name="${prefix}_wheel_joint" type="continuous"> <parent link="base_link"/> <child link="${prefix}_wheel"/> <origin xyz="${x} ${y} ${z}" rpy="1.5707 0 0"/> <axis xyz="0 1 0"/> </joint> <link name="${prefix}_wheel"> <visual> <geometry> <cylinder length="0.05" radius="0.05"/> </geometry> </visual> </link> </xacro:macro> <!-- 使用宏定义四个轮子 --> <xacro:wheel prefix="front_left" x="0.1" y="0.15" z="-0.05"/> <xacro:wheel prefix="front_right" x="0.1" y="-0.15" z="-0.05"/>- 添加RGB-D相机: 在URDF中添加Kinect或RealSense等深度相机模型,可以实现3D SLAM:
<gazebo reference="camera_link"> <sensor type="depth" name="camera"> <always_on>true</always_on> <update_rate>30.0</update_rate> <visualize>true</visualize> <camera> <horizontal_fov>1.0472</horizontal_fov> <image> <width>640</width> <height>480</height> <format>R8G8B8</format> </image> <depth_camera> <output>depth_points</output> </depth_camera> </camera> <plugin name="camera_controller" filename="libgazebo_ros_openni_kinect.so"> <baseline>0.2</baseline> <alwaysOn>true</alwaysOn> <updateRate>30.0</updateRate> <cameraName>camera</cameraName> <imageTopicName>rgb/image_raw</imageTopicName> <depthImageTopicName>depth/image_raw</depthImageTopicName> <pointCloudTopicName>depth/points</pointCloudTopicName> </plugin> </sensor> </gazebo>- 切换至Cartographer: Google的Cartographer算法比Gmapping更适合大场景建图。安装和配置方法:
sudo apt install ros-melodic-cartographer-ros ros-melodic-cartographer-rviz创建配置文件cartographer.lua,然后在launch文件中加载配置。Cartographer支持2D和3D建图,且回环检测能力更强。