4. ROS基础与环境搭建

说实话,每次带新人做机械臂项目,我都要先问一句:「ROS装了吗?」

不是我爱唠叨。而是ROS这个框架,说白了就是机器人的「操作系统」。没有它,你写个运动规划得从底层通信开始造轮子,那太痛苦了。我个人习惯用ROS Noetic,搭配Ubuntu 20.04,稳定、生态好,社区资源也最丰富。

4.1 ROS Noetic安装

安装其实不复杂,但有几个坑我得提前说。

⚠️ 注意: 请确保你的Ubuntu是20.04版本。我见过有人用18.04硬装Noetic,结果依赖全崩了。

先配置软件源。打开终端,一行一行来:

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E866B5E6E8F
sudo apt update
sudo apt install ros-noetic-desktop-full

安装完成后,记得初始化rosdep。这一步很多人会卡住,因为网络问题。我曾经在公司内网环境下折腾了整整一下午……

sudo rosdep init
rosdep update

如果rosdep update报错,多半是DNS问题。试试挂代理,或者手动下载更新包。

最后配置环境变量:

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc

验证一下:roscore 能启动,就说明装好了。

4.2 工作空间创建

工作空间,就是你的项目文件夹。我习惯叫它 catkin_ws。

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws
catkin_make

第一次编译会生成 build 和 devel 两个文件夹。别忘了:

echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

嗯,这里要注意:每次新建工作空间,都要重新source一下。不然你写的节点ROS找不到。

4.3 Catkin编译系统

Catkin是ROS的官方编译工具。说白了,它帮你把C++或Python代码变成可执行文件。

一个典型的包结构长这样:

my_package/
├── CMakeLists.txt
├── package.xml
├── src/
├── include/
├── launch/
└── config/

CMakeLists.txt 是编译规则,package.xml 是包的元信息。我刚开始学的时候,经常忘记在 package.xml 里声明依赖,结果编译报错一脸懵。

编译命令很简单:

cd ~/catkin_ws
catkin_make

如果你只想编译某个包:

catkin_make --only-pkg-with-deps my_package
💡 小技巧: 用 catkin_make -j4 可以加速编译,-j4表示用4个线程。我一般设成CPU核心数。

4.4 ROS通信机制

ROS的通信有三种方式:Topic、Service、Action。我画了张图帮你理解它们的关系。

ROS通信机制总览 ROS Master 节点管理器 Topic 发布/订阅 异步、多对多 Service 请求/响应 同步、一对一 Action 目标/反馈/结果 异步、可取消 Topic: 适合传感器数据、状态信息 Service: 适合开关、查询 Action: 适合机械臂运动、导航

4.4.1 Topic —— 最常用的通信方式

Topic是发布/订阅模式。一个节点发消息,多个节点可以收。适合传感器数据、状态信息这种持续更新的数据。

举个例子,机械臂的关节状态:

# 发布者
rostopic pub /joint_states sensor_msgs/JointState "header:
  frame_id: 'base_link'
name: ['joint1', 'joint2']
position: [0.0, 0.5]"

# 订阅者
rostopic echo /joint_states

我在项目中遇到过一个问题:Topic消息频率太高,导致CPU飙升。后来加了throttle限制频率,问题就解决了。

4.4.2 Service —— 请求-响应模式

Service适合一次性的操作,比如「打开夹爪」、「查询当前位姿」。它是同步的,客户端发请求,服务端回响应。

# 服务端
rosservice call /gripper_control std_srvs/SetBool "data: true"

# 响应
success: True
message: "Gripper opened"
🔑 关键区别: Topic是「一直说」,Service是「问一句答一句」。你想想看,机械臂抓取时,你肯定不希望每毫秒都去问「夹爪开了没」,而是发一个指令等结果就行。

4.4.3 Action —— 适合长时间任务

Action是Service的升级版。它支持:

  • 目标:发起一个任务
  • 反馈:任务进行中的状态
  • 结果:任务完成后的最终数据
  • 取消:随时可以中止任务

机械臂的运动规划就是典型的Action场景。你下发一个抓取目标,机械臂开始运动,过程中不断反馈当前位置,最后告诉你「抓到了」或「失败了」。

# Action 客户端示例
action_client.send_goal(goal)
while not action_client.wait_for_result():
    feedback = action_client.get_feedback()
    print(f"当前进度: {feedback.progress}%")
result = action_client.get_result()
💡 我的建议: 刚开始学,先玩熟Topic。Service和Action等做具体项目时再深入。别想一口吃成胖子。

4.5 本章小结

这一章我们走通了ROS Noetic的安装,建了工作空间,理解了Catkin怎么编译代码,最后搞清楚了三种通信方式各自的应用场景。

说白了,ROS就是个「消息」。你写的节点只管发消息、收消息,剩下的路由、序列化、跨进程通信,ROS全帮你干了。