嵌入式中间件ROS详解:从概念到实战
本文系统介绍了机器人操作系统(ROS)作为嵌入式中间件的核心概念和应用。
中间件作为嵌入式系统的核心组件,为应用程序提供通信支持、应用支持和公共服务。机器人操作系统(ROS)作为最流行的嵌入式中间件之一,为机器人开发提供了强大的框架支持。本文将深入解析ROS的核心概念、系统架构、通信机制,并通过树莓派实战演示ROS应用开发。
一、中间件基础概念
1.1 中间件定义与功能
中间件是介于应用系统和系统软件之间的软件层,使用系统软件提供的基础服务,衔接网络上应用系统的各个部分或不同的应用,实现资源共享和功能共享。主要提供三大功能:
-
通信支持:早期分布式中间件采用远程调用和消息两种通信方式
-
应用支持:为上层应用开发提供统一平台和运行环境
-
公共服务:对应用软件中共性功能或约束的提取和复用
1.2 嵌入式系统中间件特性
在嵌入式系统中,中间件处于嵌入式应用和操作系统之间,主要作用是对嵌入式应用屏蔽底层操作系统的异构性。由于嵌入式应用场景差异,不同系统通常集成不同的中间件,需要支持移动环境、流媒体应用、DRE环境等多样化需求。

二、ROS核心概念解析
2.1 ROS本质与定位
ROS(Robot Operating System)本质上是一个中间件而非传统操作系统,被称为"元操作系统"或"机器人软件框架"。其设计理念可表述为:
ROS = Plumbing + Tools + Capabilities + Ecosystem
-
Plumbing:通信机制
-
Tools:开发工具
-
Capabilities:应用功能
-
Ecosystem:生态系统
ROS需要运行在现有操作系统(如Linux)之上,专注于机器人开发中的通信、设备驱动、数据可视化等。
2.2 ROS发展历程
ROS发展经历了多个重要阶段:
-
2007年:ROS最初版本发布
-
2010年:ROS 1.0版本推出
-
2015年:ROS 2.0开始开发
-
2017年:ROS 2.0首个稳定版发布

2.3 ROS核心特点
-
点对点设计:分布式网络架构,节点间通过RPC+TCP/UDP通信
-
多语言支持:支持Python、C++、Java等编程语言
-
架构精简:功能节点可单独编译,集成众多开源项目
-
工具丰富:3D可视化工具、物理仿真环境、数据记录工具等
-
开源免费:BSD许可,可修改、可复用、可商用
三、ROS系统架构详解
3.1 系统层次结构
ROS系统从维护和分布角度分为两大板块:
main核心部分:Willow Garage公司和开发者维护,提供分布式计算基础工具
universe全球代码:各国ROS社区维护,包括库代码和应用级代码
从功能角度分为三个级别:
计算图级(程序运行描述)
-
节点(Node):执行具体任务的进程,可分布式运行
-
话题(Topic):节点间传输数据的总线,采用发布/订阅模型
-
服务(Service):使用客户端/服务器模型,支持双向通信
-
节点管理器(ROS Master):为节点提供命名注册服务

文件系统级(程序组织)
-
功能包(Package):ROS软件组织基本形式
-
功能包集(Stack):多个功能包集合
-
消息类型(Message):进程间传递的信息格式
-
服务类型(Service):服务通信的请求与应答数据类型
社区级(资源共享)
-
发行版:可独立安装的版本化功能包集
-
软件源:共享代码的网站或主机服务
-
ROS Wiki:主要技术文档论坛
-
邮件列表:主要交流渠道
3.2 软件层次架构
从实现角度分为三个层次:
-
OS层:建立在Linux之上,提供硬件抽象和底层驱动
-
中间层:封装OS层接口,提供TCPROS/UDPROS通信
-
应用层:调用中间层接口实现各种应用功能
四、ROS通信机制深度解析
4.1 话题通信机制
话题通信采用发布/订阅模型,实现流程如下:
-
Talker向ROS Master注册
-
Listener向ROS Master注册
-
ROS Master进行信息匹配
-
Listener向Talker发送连接请求
-
Talker确认连接请求
-
建立网络连接并传输数据
# 话题发布者示例
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
def talker():
pub = rospy.Publisher('chatter', String, queue_size=10)
rospy.init_node('talker', anonymous=True)
rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
hello_str = "hello world %s" % rospy.get_time()
rospy.loginfo(hello_str)
pub.publish(hello_str)
rate.sleep()
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass
4.2 服务通信机制
服务通信采用请求/响应模型,适合强逻辑处理场景:
-
Server向ROS Master注册
-
Client向ROS Master注册
-
ROS Master进行信息匹配
-
Client与Server建立连接
-
进行请求-响应通信
4.3 参数通信机制
通过参数服务器实现节点间参数共享:
-
Talker设置参数值
-
Listener查询参数值
-
ROS Master返回参数值
4.4 话题与服务对比
| 条目 | 话题 | 服务 |
|---|---|---|
| 同步性 | 异步 | 同步 |
| 通信模型 | 发布/订阅 | 客户端/服务器 |
| 实时性 | 弱 | 强 |
| 适用场景 | 数据传输 | 逻辑处理 |

五、ROS2架构革新
5.1 从ROS到ROS2的演进
ROS1存在实时性不足、资源管理弱等问题,ROS2进行了重大架构升级:
-
架构颠覆:告别Master,使用基于DDS的Discovery机制
-
API重新设计:保持类似用法但更现代化
-
编译系统升级:使用ament、colcon替代catkin
-
多平台支持:支持Linux、Windows、macOS、RTOS等
5.2 DDS通信核心
ROS2采用以数据为中心的发布/订阅(DCPS)模型,创建"全局数据空间"。DDS核心实体包括:
-
参与者(Participant):对应ROS节点
-
发布者(Publisher):数据发布执行者
-
订阅者(Subscriber):数据订阅执行者
-
数据写入器(DataWriter):特定话题的消息发布者
-
数据读取器(DataReader):特定话题的消息订阅者
5.3 QoS服务质量策略
ROS2引入丰富的QoS策略,用户可通过选择不同配置文件优化通信表现:
-
发布/订阅机制的QoS设定
-
服务QoS设定
-
传感器数据QoS设定
-
参数QoS设定
六、树莓派ROS实战演练
6.1 环境准备与安装
# 安装基础工具
dnf install wget yum tree git python3-devel
# 配置ROS环境
echo "source /opt/ros/noetic/setup.bash" >> ~/.bash_profile
source ~/.bash_profile
# 安装Python依赖
pip3 install empy==3.3.2
6.2 第一个ROS程序:小海龟仿真
# 启动ROS核心
roscore
# 新终端启动小海龟仿真
rosrun turtlesim turtlesim_node
# 新终端控制小海龟
rosrun turtlesim turtle_teleop_key
6.3 话题通信实战编程
创建ROS工作区和功能包:
# 创建工作区
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
# 创建功能包
catkin_create_pkg my_ros_pkg roscpp std_msgs
# 编译工作区
cd ~/catkin_ws
catkin_make
话题发布者代码示例:
// topic_publisher.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok()) {
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
话题订阅者代码示例:
// topic_subscriber.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
ros::spin();
return 0;
}
6.4 自定义消息控制小海龟
通过编程实现小海龟圆周运动:
#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
def turtle_circle():
rospy.init_node('turtle_controller', anonymous=True)
pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
rate = rospy.Rate(10)
while not rospy.is_shutdown():
vel_msg = Twist()
vel_msg.linear.x = 1.0 # 线速度
vel_msg.angular.z = 1.0 # 角速度
pub.publish(vel_msg)
rate.sleep()
if __name__ == '__main__':
try:
turtle_circle()
except rospy.ROSInterruptException:
pass
七、ROS在openEuler上的移植优化
7.1 混合关键性部署
openEuler Embedded支持混合关键性部署,通过Jailhouse框架实现实时与非实时任务隔离:
# 启用Jailhouse
jailhouse enable /usr/share/jailhouse/cells/rpi4.cell
# 创建Linux cell
jailhouse cell linux /usr/share/jailhouse/cells/rpi4-linux.cell \
/boot/Image -d /usr/share/jailhouse/cells/dts/inmate-rpi4.dtb \
-c "console=ttyAMA1,115200 root=/dev/mmcb1k0p2"
7.2 实时性优化策略
-
中断线程化:减少关中断时间,提高系统可抢占性
-
优先级继承:解决优先级反转问题
-
自旋锁优化:采用Qspinlock减少CPU资源浪费
附录:常用命令速查
|
功能 |
命令 |
|---|---|
|
查看节点 |
|
|
查看话题 |
|
|
消息发布 |
|
|
包管理 |
|
|
编译工作区 |
|
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)