跳到主要内容

RFrame 部署指南

文档总入口:《RFrame 使用入口》

1. 文档定位​

本文说明以下内容:

  1. 目标机要安装什么;
  2. 全局 rframe.json 和业务 Channel JSON 怎么分别管理;
  3. 应用如何带着配置启动;
  4. 部署完成后如何验收。

本文不讲 CMake 和源码构建,见《RFrame 编译指南》;不讲 C++ API 实现,见《RFrame 开发指南》。

2. 适用范围​

本文覆盖以下能力的部署:

  • 日志;
  • AppCore;
  • ChannelManager 基础使用;
  • HybridChannel;
  • HybridRpcChannel。

示例工程:deb 包 robby-r-frame-example(安装后位于 /opt/robby/RFrameExample/)。

3. 安装部署包​

3.1. 检查环境​

cat /etc/os-release
dpkg --print-architecture

如果 Hybrid 配置启用 ROS 2:

source /opt/ros/humble/setup.bash
echo "$ROS_DISTRO"

使用自定义 ROS 2 消息或 service 时,还要 source 对应消息工作区:

source /path/to/message_workspace/install/setup.bash

3.2. 安装固定版本​

sudo apt-get update
apt-cache policy r-frame r-frame-plugin
apt-cache madison r-frame
RFRAME_VERSION='<经过验证的版本>'
sudo apt-get install -y --no-install-recommends \
"r-frame=${RFRAME_VERSION}"

使用 JSON channel 配置(推荐方式)需要 r-frame-plugin(提供 JsonDynamicDataPlugin,即 ChannelConfigLoader 的 JSON 解析能力):

PLUGIN_VERSION='<与 RFrame 匹配的版本>'
sudo apt-get install -y --no-install-recommends \
"r-frame-plugin=${PLUGIN_VERSION}"

启用远端后端(ROS 2 / zenoh / WebSocket 等)时同样由该包提供。校验 JSON 解析可用:

grep JsonDynamicDataPlugin /opt/robby/r-frame/config/plugins.json

r-frame 和 r-frame-plugin 必须来自兼容的同一 SDK 发布批次。

3.3. 安装 Python wheel​

r-frame deb 同时交付 native library 和 Python binding:

  • 系统 Python 的 binding 安装在 /usr/lib/python3/dist-packages;
  • 同批次 wheel 保留在 /usr/local/lib/rframe/*.whl,供虚拟环境或自定义 Python 使用。
  • r-frame-plugin 的 Python ROS 2 provider wheel 位于 /usr/local/lib/rframe-plugin/rframe_plugin_ros2_python-*.whl,导入名为 rframe_ros2;使用该 provider 时需另外安装。

使用系统 Python 时,安装 deb 后直接验证,无需再次执行 pip:

/usr/bin/python3 -c 'import rframe; print(rframe.__file__)'

使用虚拟环境时,安装 deb 中携带的同批次 wheel:

python3 -m venv --system-site-packages /opt/<app>/venv
source /opt/<app>/venv/bin/activate

ls /usr/local/lib/rframe/*.whl
python -m pip install --no-deps /usr/local/lib/rframe/rframe-*.whl
python -m pip install --no-deps /usr/local/lib/rframe-plugin/rframe_plugin_ros2_python-*.whl
python -c 'import rframe; print(rframe.__version__, rframe.__build_tag__)'
dpkg-query -W -f='${Version}\n' r-frame

--system-site-packages 使虚拟环境能够访问 ROS 2 通过系统包安装的 Python 模块;不使用 ROS 2 时可以省略。wheel 只提供 Python binding,运行时仍依赖同批次 r-frame deb 提供的 native library。不要单独分发 wheel,也不要混用不同 RFrame 发布批次的 deb 和 wheel。

自定义 Python(例如 /opt/py310/bin/python3)需使用该解释器对应的 pip。安装上述两个 deb 后,执行:

sudo /opt/py310/bin/python3 -m pip install --no-deps /usr/local/lib/rframe/rframe-*.whl
sudo /opt/py310/bin/python3 -m pip install --no-deps /usr/local/lib/rframe-plugin/rframe_plugin_ros2_python-*.whl

使用 ROS 2 时,Python 小版本必须与 rclpy 扩展匹配;例如 CPython 3.10 的 rclpy 扩展不能由 Python 3.12 加载。安装后检查实际导入路径:

/opt/py310/bin/python3 -c 'import rframe, rframe_ros2; print(rframe.__file__); print(rframe_ros2.__file__)'

rframe_ros2 是应用自有 rclpy node/executor 的可选 provider,不会因安装 wheel 自动启用,也不替代 Hybrid SHM 通道。使用 rframe_ros2.install() 注册时,core 必须提供 rframe.channel_provider.register_channel_provider 和 ChannelManager.create_with_provider;仅能 import 不代表该接口已兼容。已确认 rc51 core 不具备此接口,需与支持 provider API 的 core 版本配套使用。

4. 部署目录​

/opt/<app>/
├── bin/ # 业务可执行文件
├── config/
│ ├── rframe.json # RFrame 全局配置(日志)
│ └── channels.json # 业务自行加载的 Channel 配置
├── lib/ # 业务私有动态库(如有)
└── VERSION # 应用、RFrame、插件版本记录

记录安装版本和动态库解析结果:

dpkg-query -W r-frame r-frame-plugin 2>/dev/null
ldd /opt/<app>/bin/<app>

5. RFrame 全局配置 rframe.json​

5.1. 文件查找顺序​

RFrame 按以下顺序选择第一份存在的主配置:

  1. $RFRAME_CONFIG_PATH;
  2. ./rframe.json;
  3. ~/.config/rframe/rframe.json;
  4. /etc/rframe/rframe.json。

生产部署建议显式指定:

export RFRAME_CONFIG_PATH=/opt/<app>/config/rframe.json

必须在应用调用 AppCore::init() 前设置,运行期间不要切换到另一份文件。

5.2. 用户配置​

全局 rframe.json 只配置日志级别:

{
"log": {
"level": "info"
}
}

全局配置只暴露日志段:

配置段加载者作用
logAppCore / GlobalConfig框架日志级别

其他框架设置由 SDK 和安装包管理,不属于用户配置项。

Channel 配置不写入全局 rframe.json,由业务运行时从独立 JSON 文件或字符串主动加载。

5.3. 配置优先级​

log.level 支持 trace、debug、info、warn、error、off,默认值为 info。

配置优先级为:

RFRAME_LOG_LEVEL > rframe.json > 框架默认值

如需临时覆盖日志级别:

export RFRAME_LOG_LEVEL=debug

6. Channel JSON 怎么写​

Channel 配置存放在业务自己的 JSON 文件中,例如 /opt/<app>/config/channels.json:

{
"channels": {
"实例名称": {
"type": "hybrid"
}
}
}

channels 的键是 ChannelManager 使用的实例名称,不是 topic 或 service 名称。

6.1. HybridChannel:SHM-only​

{
"channels": {
"local_reader": {
"type": "hybrid",
"topic": "/example/local",
"handler": "reader",
"hybrid": {
"enable_shm": true,
"enable_remote": false,
"auto_route": false
},
"shm": {
"memory_size": 65536,
"type_name": "std_msgs/msg/String"
}
}
}
}

SHM-only 不需要 ros2 子对象。memory_size 必须是数字;queue_size 默认 10,非默认才写。

6.2. HybridChannel:SHM + ROS 2​

下面把订阅清单中的头相机压缩图转换成 loader 可读取的配置:

{
"channels": {
"head_color_reader": {
"type": "hybrid",
"topic": "/robby/sensors/camera/head/color/compressed",
"handler": "reader",
"hybrid": {
"enable_shm": true,
"enable_remote": true,
"auto_route": false
},
"shm": {
"memory_size": 5242880,
"type_name": "sensor_msgs/msg/CompressedImage"
},
"ros2": {
"type_name": "sensor_msgs/msg/CompressedImage",
"qos": {
"reliability": "best_effort"
}
}
}
}
}

接口事实来源:RobbySensorCenter 相机话题清单。

配置规则:

  • type 固定为 hybrid;
  • handler 取 reader、writer 或 dual;
  • 公共 topic 会传给启用的子通路;
  • 新配置使用 enable_remote,它与旧字段 enable_ros2 对应同一 ABI 字段;
  • 启用哪个后端,就提供哪个子对象;
  • ROS 2 QoS 放在 ros2.qos,只写与默认不同的项(如 reliability: best_effort);
  • 框架默认字段(require_all=false、SHM 优先去重等)不写;
  • 旧配置里的兼容字段 hybrid.dedup 不要再写;require_all=true 表示任一启用后端打开失败时整体失败。

只使用 ROS 2 时,将 enable_shm 设为 false 并删除 shm 对象。

6.3. HybridRpcChannel:SHM-only​

{
"channels": {
"calculator_rpc": {
"type": "hybrid_rpc",
"hybrid_rpc": {
"service_prefix": "/example/calculator",
"enable_shm": true,
"enable_ros2": false,
"auto_route": false
}
}
}
}

6.4. HybridRpcChannel:SHM + ROS 2​

{
"channels": {
"calculator_rpc": {
"type": "hybrid_rpc",
"hybrid_rpc": {
"service_prefix": "/example/calculator",
"enable_shm": true,
"enable_ros2": true
},
"ros2": {
"service_prefix": "/example/calculator",
"service_type": "example_interfaces/srv/AddTwoInts",
"default_timeout_ms": 3000
}
}
}
}

ros2.default_timeout_ms 自身默认 2000ms,上例显式写 3000ms 与 hybrid_rpc 级默认对齐;不写则该级按 2000ms。

Hybrid RPC 不写 topic 和 handler。hybrid_rpc.service_prefix 与 ros2.service_prefix 必须一致,client/server 必须使用相同 service type。

6.5. Channel JSON 加载方式​

配置来源适用场景加载入口
独立 channels.json文件化部署或多组配置切换loadFromFile() / loadByName()
JSON 字符串配置中心下发或测试loadFromString() / loadSingleChannel()

正式 Channel 配置统一保留 {"channels": {...}} 外层。业务代码加载后,将得到的 MsgChannelConfig 交给 ChannelManager::createChannel();具体代码见《RFrame 开发指南》。

7. 启动应用​

source /opt/ros/humble/setup.bash # 启用 ROS 2 时
source /path/to/message_workspace/install/setup.bash # 自定义类型时
export RFRAME_CONFIG_PATH=/opt/<app>/config/rframe.json
exec /opt/<app>/bin/<app>

Python 应用使用同一套环境变量:

source /opt/ros/humble/setup.bash # 启用 ROS 2 时
source /path/to/message_workspace/install/setup.bash # 自定义类型时
export RFRAME_CONFIG_PATH=/opt/<app>/config/rframe.json
python3 -u /opt/<app>/bin/app.py

部署前确认 Python binding 可导入:

python3 -c 'import rframe; print(rframe.__file__)'

应用内部应按以下顺序工作:

AppCore::init()
→ 业务加载 channels.json 或 JSON 字符串
→ ChannelManager 创建 Channel
→ 执行业务
→ AppCore::shutdown()
→ ChannelManager 统一清理其托管的 Channel

具体 C++ 实现见《RFrame 开发指南》。

8. 配置检查​

配置检查器来自示例 deb 的 channel 散装单元,先编译一次:

sudo apt install robby-r-frame-example
cmake -S /opt/robby/RFrameExample/src/channel -B /tmp/rfe-channel
cmake --build /tmp/rfe-channel -j4 --target channel_config_json_example

然后检查部署的 channels 配置:

/tmp/rfe-channel/channel_config_json_example /opt/<app>/config/channels.json

检查实例数量、type、valid、topic、handler、启用后端和 timeout。然后按名称打开目标 Channel:

/tmp/rfe-channel/channel_config_json_example \
/opt/<app>/config/channels.json head_color_reader

如何生成检查器见《RFrame 编译指南》。