RFrame 部署指南
文档总入口:《RFrame 使用入口》
1. 文档定位
本文说明以下内容:
- 目标机要安装什么;
- 全局
rframe.json和业务 Channel JSON 怎么分别管理; - 应用如何带着配置启动;
- 部署完成后如何验收。
本文不讲 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 按以下顺序选择第一份存在的主配置:
$RFRAME_CONFIG_PATH;./rframe.json;~/.config/rframe/rframe.json;/etc/rframe/rframe.json。
生产部署建议显式指定:
export RFRAME_CONFIG_PATH=/opt/<app>/config/rframe.json
必须在应用调用 AppCore::init() 前设置,运行期间不要切换到另一份文件。
5.2. 用户配置
全局 rframe.json 只配置日志级别:
{
"log": {
"level": "info"
}
}
全局配置只暴露日志段:
| 配置段 | 加载者 | 作用 |
|---|---|---|
log | AppCore / 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 编译指南》。