第1章:ROS环境搭建与核心概念

大家好,我是你们的讲师。做SLAM这些年,我踩过最多的坑,就是环境问题。ROS版本不对、依赖缺失、工作空间混乱……这些看似基础的东西,往往能卡住你好几天。今天咱们就从零开始,把ROS Noetic的环境搭好,再把核心概念捋一遍。

本章核心目标: 搭建一个稳定可用的ROS Noetic开发环境,理解ROS的通信机制,能独立编写launch文件。

1.1 ROS Noetic 安装与配置

ROS Noetic是ROS1的最后一个长期支持版本,搭配Ubuntu 20.04使用。我个人习惯用apt安装,干净利落。

# 1. 设置sources.list
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'

# 2. 添加密钥
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

# 3. 更新并安装完整桌面版
sudo apt update
sudo apt install ros-noetic-desktop-full

# 4. 初始化rosdep
sudo rosdep init
rosdep update

# 5. 设置环境变量
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc

# 6. 验证安装
roscore

注意: 如果你用的是虚拟机,记得给Ubuntu分配至少4GB内存和2个CPU核心。我曾经在2GB内存的虚拟机上跑ROS,结果roscore启动后直接卡死,排查了半天才发现是内存不够。

1.2 工作空间创建

工作空间是ROS项目的根目录。说白了,你所有的代码、包、编译产物都放在这里。我建议每个项目单独建一个工作空间,别把所有东西混在一起。

# 创建并初始化工作空间
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws
catkin_make

# 每次打开新终端,记得source一下
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

小技巧: 用echo $ROS_PACKAGE_PATH检查你的工作空间是否被正确识别。如果输出里没有你的工作空间路径,说明source没生效。

1.3 Package结构

一个标准的ROS Package长这样:

my_package/
├── CMakeLists.txt    # 编译规则
├── package.xml       # 包信息与依赖
├── src/              # 源代码
├── include/          # 头文件
├── launch/           # launch文件
├── msg/              # 自定义消息
├── srv/              # 自定义服务
└── config/           # 配置文件

创建新包用这个命令:

cd ~/catkin_ws/src
catkin_create_pkg my_package roscpp rospy std_msgs
cd ~/catkin_ws
catkin_make

核心要点: package.xml里要写清楚依赖,否则编译时会报错。我见过有人漏写roscpp依赖,结果编译通过但运行时找不到节点,排查了半小时。

1.4 Topic / Service / Action 通信机制

ROS的通信机制,说白了就是节点之间怎么说话。我画了一张图帮你理解:

ROS通信机制总览 发布者节点 订阅者节点 Topic 客户端节点 服务端节点 Service Action客户端 Action服务端 Action Topic:单向数据流 | Service:请求-响应 | Action:带反馈的长时间任务

Topic(话题)

Topic是ROS最常用的通信方式。发布者往话题里发数据,订阅者从话题里收数据。这是单向的、异步的。比如激光雷达数据,就是通过/scan话题发布的。

# 查看所有话题
rostopic list

# 查看话题内容
rostopic echo /scan

# 查看话题发布频率
rostopic hz /scan

Service(服务)

Service是请求-响应模式。客户端发请求,服务端处理完返回结果。适合一次性的操作,比如「打开摄像头」、「重置里程计」。注意,Service是同步的,客户端会阻塞等待响应。

# 调用服务
rosservice call /gazebo/reset_world "{}"

Action(动作)

Action是Service的升级版。它适合长时间的任务,比如「导航到目标点」。客户端可以随时查询进度,也可以中途取消。Action有三个通道:goal(目标)、feedback(反馈)、result(结果)。

我的经验: 在SLAM建图时,地图保存用Service就够了。但导航任务一定要用Action,因为你可以实时看到机器人走到哪了,还能随时让它停下来。

1.5 Launch文件编写

Launch文件用来一次性启动多个节点。你想想看,每次建图都要开好几个终端,多麻烦。用launch文件,一键搞定。

<?xml version="1.0"?>
<launch>
    <!-- 启动核心节点 -->
    <node name="core_node" pkg="my_package" type="core_node" output="screen"/>
    
    <!-- 启动激光雷达驱动 -->
    <node name="lidar_driver" pkg="rplidar_ros" type="rplidarNode">
        <param name="serial_port" value="/dev/ttyUSB0"/>
        <param name="frame_id" value="laser"/>
    </node>
    
    <!-- 启动SLAM建图 -->
    <include file="$(find slam_gmapping)/launch/gmapping.launch"/>
    
    <!-- 启动可视化 -->
    <node name="rviz" pkg="rviz" type="rviz" args="-d $(find my_package)/config/slam.rviz"/>
</launch>

关键点:

  • pkg:包名
  • type:可执行文件名
  • name:节点别名,可以重名
  • output="screen":把日志输出到终端,调试时很有用
  • include:嵌套其他launch文件

避坑指南: 我曾经在launch文件里忘了写output="screen",结果节点启动失败,但终端没有任何错误信息。后来用rosnode list发现节点根本没起来,才意识到是launch文件的问题。所以调试阶段,一定要加上output="screen"。

好了,这一章的内容就到这里。环境搭好了,概念理清了,下一章咱们就开始写第一个ROS节点,让机器人动起来。

可可精品资料库