本仓库为李家乐《基于ROS2的智能汽车SOA通信机制研究及实现》毕业论文的工程实现
在 ROS2 Humble 上搭建了一套**面向服务架构(SOA)**车身控制原型系统,涵盖按键、车灯、车门、车速、诊断五类原子服务,并以业务逻辑节点编排六大典型场景,打通从 x86 开发到 RK3588 嵌入式目标板(鲁班猫4)部署的开发—测试—部署全链路。
| 维度 | 说明 |
|---|---|
| 技术栈 | ROS2 Humble · CycloneDDS · libgpiod · SocketCAN · Docker buildx · pytest |
| 代码规模 | 3 个 ROS2 包 · 9 个常驻节点 · 7 类消息 · 8 项服务 |
| 测试体系 | 7 个 pytest 模块 · 34 项用例(32 通过 / 2 预期跳过) |
| 部署形态 | amd64 开发容器(VS Code Remote) + arm64 部署镜像(鲁班猫4) |
系统按五层 SOA 架构组织,层间通过 ROS2 topic / service 通信,DDS 中间件统一使用 CycloneDDS:
┌─────────────────────────────────────────────────────────────┐
│ L5 业务逻辑层 business_logic_node │
│ (编排 6 类场景:上锁/解锁/远近光/示宽灯…)│
├─────────────────────────────────────────────────────────────┤
│ L4 服务注册层 service_registry_node │
│ (RegisterService / DiscoverService / │
│ Heartbeat 三项服务,TTL 30 s) │
├─────────────────────────────────────────────────────────────┤
│ L3 原子服务层 button_service · headlight_service · │
│ door_service · vehicle_speed_service · │
│ diagnostic_service │
├─────────────────────────────────────────────────────────────┤
│ L2 设备抽象层 gpio_driver_node · can_driver_node │
│ (/button*_state · /can_rx · /led_control)│
├─────────────────────────────────────────────────────────────┤
│ L1 硬件层 GPIO(按键/LED) · CAN(vcan0 模拟或 │
│ can0 物理总线) │
└─────────────────────────────────────────────────────────────┘
ROS2_SOA_Body_Control/
├── .devcontainer/ # VS Code Dev Container 定义
│ ├── devcontainer.json
│ └── setup.sh # 容器内一键安装 ROS2 + 依赖
├── Dockerfile.deploy # 多阶段部署镜像(builder + runtime)
├── src/
│ ├── body_control_interfaces/ # 7 msg + 8 srv
│ │ ├── msg/ (ButtonEvent, CanFrame, DoorStatus, LatencyTest,
│ │ │ LEDControl, LightStatus, ServiceStatus)
│ │ └── srv/ (DiscoverService, GetSpeed, Heartbeat, LockDoor,
│ │ RegisterService, SetHeadlightMode, StartDiagnostic,
│ │ UnlockDoor)
│ ├── body_control_cpp/ # 主业务包:10 个 C++ 节点
│ │ ├── include/body_control_cpp/ *.hpp
│ │ ├── src/ *.cpp + remote_consumer_node.py
│ │ ├── launch/
│ │ │ ├── body_control_simulate.launch.py # 开发容器/模拟环境
│ │ │ ├── body_control_real.launch.py # 鲁班猫4 物理硬件
│ │ │ └── perf_test.launch.py # 性能/QoS 测试
│ │ └── test/ # 7 个 pytest 测试模块
│ └── ros2_can_interface/ # 历史遗留的 CAN 测试包
├── test_results/ # 实测数据(按测试类别分目录)
build/、install/、log/ 为 colcon 产物,已在 .gitignore 中排除。
前置条件:宿主机安装 Docker(≥ 20.10)和 VS Code + Dev Containers 扩展。
git clone <this-repo> ROS2_SOA_Body_Control
cd ROS2_SOA_Body_Control
code .
# 弹窗选择 "Reopen in Container",等待容器构建完成容器内已预置:
- ROS2 Humble + CycloneDDS + libgpiod + ros2-socketcan + colcon
- 环境变量:
RMW_IMPLEMENTATION=rmw_cyclonedds_cpp、ROS_DOMAIN_ID=24 - 工作区挂载到
/ros2_ws - 以
--privileged --network=host运行,宿主机/dev透传,可直接访问 GPIO/CAN 硬件
首次运行时,需创建虚拟 CAN 接口:
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0# 1. 添加 ROS2 Humble 源
sudo apt update && sudo apt install -y curl gnupg lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key \
-o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \
http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" \
| sudo tee /etc/apt/sources.list.d/ros2.list
# 2. 安装 ROS2 及项目依赖
sudo apt update
sudo apt install -y \
ros-humble-ros-base ros-humble-rmw-cyclonedds-cpp \
ros-humble-ros2-socketcan \
python3-colcon-common-extensions python3-rosdep \
build-essential cmake \
libgpiod-dev gpiod libsocketcan-dev can-utils
# 3. 配置环境变量
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
echo "export ROS_DOMAIN_ID=24" >> ~/.bashrc
echo "export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp" >> ~/.bashrc
source ~/.bashrc接口包定义了消息与服务类型,必须先行编译:
cd /ros2_ws
rm -rf build install log
colcon build --packages-select body_control_interfaces
source install/setup.bash
colcon build --packages-select body_control_cpp
source install/setup.bash后续增量编译(--symlink-install 可免重建 Python 脚本):
colcon build --packages-select body_control_cpp --symlink-install三个 launch 文件覆盖不同场景:
| Launch 文件 | 用途 | 节点数 | CAN 接口 | GPIO 模式 |
|---|---|---|---|---|
body_control_simulate.launch.py |
开发容器 / 模拟运行 | 9 | vcan0 |
模拟(simulate=True) |
body_control_real.launch.py |
鲁班猫4 物理硬件 | 9 | can0 |
物理 GPIO |
perf_test.launch.py |
性能 / QoS 测试环境 | 10 | vcan0(自动创建) |
模拟(simulate=True) |
模拟运行:
ros2 launch body_control_cpp body_control_simulate.launch.py性能 / QoS 测试(可传入 QoS 参数):
ros2 launch body_control_cpp perf_test.launch.py \
qos_reliability:=best_effort qos_history_depth:=1常用调试命令:
ros2 node list
ros2 topic echo /button1_state
ros2 service call /lock_door body_control_interfaces/srv/LockDoor "{door_id: 1}"
ros2 service call /set_headlight_mode \
body_control_interfaces/srv/SetHeadlightMode "{mode: 2}"| 层级 | 节点 | 关键接口(话题 / 服务) | 备注 |
|---|---|---|---|
| L2 | gpio_driver_node |
pub /buttonN_state · sub /led_control |
simulate 参数切换模拟/物理 |
| L2 | can_driver_node |
pub /can_rx · srv /send_can_frame |
interface 参数:vcan0 / can0 |
| L3 | button_service_node |
pub /button_event |
去抖、单击/长按识别 |
| L3 | headlight_service_node |
srv /set_headlight_mode · pub /light_status |
关/示宽/近光/远光 4 档 |
| L3 | door_service_node |
srv /lock_door · srv /unlock_door · pub /door_status |
|
| L3 | vehicle_speed_service_node |
srv /get_speed |
数据来自 /can_rx |
| L3 | diagnostic_service_node |
srv /start_diagnostic |
服务存活/响应自检 |
| L4 | service_registry_node |
srv /register_service · srv /discover_service · srv /heartbeat |
TTL 30 s,自动清理过期注册 |
| L5 | business_logic_node |
订阅事件、组合调用上述服务 | 实现 6 类业务场景 |
| 测试 | latency_echo_node |
回环话题 / 服务,供测试用 | 仅 perf_test.launch.py 启动 |
ButtonEvent · CanFrame · DoorStatus · LatencyTest · LEDControl · LightStatus · ServiceStatus
DiscoverService · GetSpeed · Heartbeat · LockDoor · RegisterService · SetHeadlightMode · StartDiagnostic · UnlockDoor
| # | 场景 | 触发条件 | 服务编排链 |
|---|---|---|---|
| 1 | 一键上锁 | 按键 1 短按 | button → business_logic → door(/lock_door) |
| 2 | 一键解锁 | 按键 1 长按 | button → business_logic → door(/unlock_door) |
| 3 | 远近光切换 | 按键 2 短按 | button → business_logic → headlight(/set_headlight_mode) |
| 4 | 示宽灯切换 | 按键 2 长按 | button → business_logic → headlight |
| 5 | 车速读取 | 周期或按需 | business_logic → vehicle_speed(/get_speed) → CAN |
| 6 | 自检诊断 | 启动后或周期 | business_logic → diagnostic(/start_diagnostic) |
cd /ros2_ws
source install/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export ROS_DOMAIN_ID=24
export QUICK_TEST=1 # 缩短迭代次数,约 8.5 分钟
python3 -m pytest src/body_control_cpp/test/ -v省略 QUICK_TEST=1 则按论文中的完整迭代次数运行,耗时显著增加。测试结果自动写入 test_results/<category>/。
| 模块 | 覆盖目标 |
|---|---|
test_functionality.py |
6 大业务场景端到端可用性 |
test_soa_features.py |
注册/发现/心跳、解耦替换、异常恢复 |
test_topic_latency.py |
话题端到端时延(不同 QoS 配置) |
test_service_latency.py |
服务调用 RTT(P50/P95/P99) |
test_qos_comparison.py |
reliable vs best_effort 行为对比 |
test_reliability.py |
丢包率、重连恢复 |
test_baseline.py |
资源占用、空载基线 |
辅助模块:conftest.py(pytest fixture)、node_launcher.py(节点生命周期)、perf_utils.py(统计/CSV 输出)。
- 服务调用 RTT:P50 1.0–2.0 ms,P99 ≤ 3.4 ms(容器内 vcan0)
- SOA 特性时延:注册 / 发现 / 心跳均为亚毫秒到毫秒级
- 服务注册中心常驻开销:RSS ≈ 63 MB
- 整体用例:34 项中 32 通过、2 预期跳过(依赖未提供的物理硬件)
docker buildx create --name multiarch --use # 仅首次
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t calerli/ros2_soa_body_control:latest \
-f Dockerfile.deploy \
--push .Dockerfile.deploy 采用两阶段构建:builder 阶段在 ubuntu:22.04 上 colcon build 全部包,runtime 阶段仅复制 install/ 和运行期依赖(ros-humble-ros-base、rmw_cyclonedds_cpp、libgpiod2、libsocketcan2、ros2-socketcan 等),镜像体积精简。
# 在鲁班猫4上:先初始化 CAN 接口
sudo ip link set can0 type can bitrate 500000
sudo ip link set up can0
docker pull calerli/ros2_soa_body_control:latest
docker run -d --name ros2_soa_body_control \
--privileged --network host \
-v /dev:/dev \
calerli/ros2_soa_body_control:latest \
ros2 launch body_control_cpp body_control_real.launch.py
docker logs -f ros2_soa_body_control调试时进入容器:
docker exec -it ros2_soa_body_control bash
ros2 node list