chore: 框架科学优化前的完整基线
在开始'设备契约层 + 目录重构 + 通止规装配'改造之前,先钉住当前可运行状态, 使后续任何删除/重构都可回退。 本基线包含: - 现有 ROS 2 工作区全部源码(arm_application / arm_control / arm_bringup 等) - 官方 flexiv_ros2 栈(含 flexiv_hardware / flexiv_controllers 等符号链接) - 设备契约层 src/arm_interfaces(新增,46 项单测通过) - devices/ 设备选型与品牌清单(新增) - scripts/gen_site_example.py 与由它生成的 config/site.example.yaml 按 .gitignore 排除:build/ / install/ / log/ / config/site.yaml / 模型权重二进制。
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# devices/sensors/orisys/ —— Orisys 视触觉(框架核心)
|
||||
|
||||
**这是整个框架的核心。** 后续所有 ROS 2 项目都会围绕它开发,它也会持续迭代优化更新,
|
||||
所以它单独占一个文件夹,不与其它传感器混放。
|
||||
|
||||
## 先搞清楚它输出什么
|
||||
|
||||
这是上层算法真正依赖的数据契约。**注意单位与坐标系的定义,这是最容易出错的地方。**
|
||||
|
||||
| 数据 | 维度 | 说明 | 框架内部话题 |
|
||||
|------|------|------|--------------|
|
||||
| 切向力 1 | 标量 | 任意单位(非牛顿),且**基线会漂移** | `~/tangential_1` |
|
||||
| 切向力 2 | 标量 | 同上,另一正交方向 | `~/tangential_2` |
|
||||
| 法向力 | 标量 | 同上 | `~/normal` |
|
||||
| 深度图 | 图像 | 接触面深度 | `~/depth` |
|
||||
| 力矢量图 | 图像 | 接触点的力矢量可视化 | `~/force_vector` |
|
||||
|
||||
### 两个必须记住的坑
|
||||
|
||||
**1. 力是任意单位,不是牛顿。** 现有 `site.yaml` 里所有力阈值(`touch_delta`、`press_delta`、
|
||||
`safe_press_delta` 等)全部是「相对静止均值的**增量**」,不是绝对值。节点启动后会先自动测基线。
|
||||
改阈值时改的也是增量,不是绝对读数。
|
||||
|
||||
**2. 基线会漂移,所以阈值必须相对化。** 写任何新的力判据时,不允许直接比较绝对读数。
|
||||
|
||||
**3. 切向力的 X / Y 通道归属尚未确认。** 通止规装配里「接触到面时某一路切向力突变」「拧紧判定时
|
||||
某一路切向力超阈值」都需要知道是哪个通道。在确认之前,框架按**两个切向通道都监控、任一满足即判定**
|
||||
来实现,避免猜错通道导致整段流程静默失效。确认后会把配置项收敛为指定通道。
|
||||
|
||||
## 厂商物料放置要求
|
||||
|
||||
| 项 | 要求 |
|
||||
|----|------|
|
||||
| SDK 格式 | 厂商**原始发布格式**,不要转换、不要重新打包 |
|
||||
| SDK 命名 | **保持厂商原目录名与文件名**,一律不要改名。SDK 内部常按自己包名做导入与资源查找 |
|
||||
| SDK 版本 | 在 `manifest.yaml` 的 `version` 记录,并写进 `docs/CHANGELOG_ORISYS.md` |
|
||||
| 型号配置 | 每个型号一份配置放 `models/<型号名>/`,不要混在一起 |
|
||||
| 相机路径 | **必须用 `/dev/v4l/by-path/` 稳定路径**,不要写 `/dev/video0` —— video 编号会随插拔漂移,这是现有框架已经踩过的坑 |
|
||||
| 生效 | 放好 SDK → `pip install -e` 或加进 `PYTHONPATH` → 改 `registry.yaml` 选 `orisys` → 改 `site.yaml` 的 `tactile.models.<型号>` → 重启 `scripts/run_tactile.sh` |
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
sensors/orisys/
|
||||
├── README.md # 本文件
|
||||
├── manifest.yaml # 型号清单 + 能力 + 配置项声明
|
||||
├── sdk/ # ★ 厂商 SDK 原样放置
|
||||
│ └── README.md # 放进来之后怎么让它生效(见下)
|
||||
├── models/ # ★ 多个传感器型号
|
||||
│ ├── README.md
|
||||
│ └── <型号名>/ # 每个型号一份配置
|
||||
│ └── config.json
|
||||
└── driver/ # 适配器:统一成上面的数据契约
|
||||
```
|
||||
|
||||
## 多型号怎么切换
|
||||
|
||||
传感器有多个型号,切换只改两处,**不改任何代码**:
|
||||
|
||||
1. `devices/registry.yaml` → `sensors: orisys`(选厂商,通常不用改)
|
||||
2. `config/site.yaml` → `tactile.model: "<型号名>"`,指向 `models/<型号名>/config.json`
|
||||
|
||||
型号之间的差异(通道数、内参、标定参数、拼接参数)全部由 `models/<型号名>/` 承载。
|
||||
上层只订阅统一话题,换型号不影响上层代码。
|
||||
|
||||
## 当前状态(迁移参考)
|
||||
|
||||
| 现有位置 | 内容 | 迁移去向 |
|
||||
|----------|------|----------|
|
||||
| `src/arm_application/arm_application/orisys_tactile.py` | SDK 适配 + 多进程 worker + `load_orisys_from_site` | `driver/` |
|
||||
| `src/arm_application/arm_application/tactile_node.py` | ROS 节点,双指各一个进程 | `driver/` |
|
||||
| `src/arm_application/arm_application/tactile_cli.py` | 读数量级 CLI(调试阈值用) | 保留为调试工具 |
|
||||
| `src/arm_application/arm_application/tactile_interface.py` | 数据类 | `driver/`,其中的 `MockTactile` 类已死,P2 删除 |
|
||||
| `src/arm_application/config/orisys/dd03.json` | 当前型号 dd03 的厂商配置 | `models/dd03/config.json` |
|
||||
|
||||
**已解决的历史坑,迁移时必须保留这些做法:**
|
||||
|
||||
- 左右指各起一个独立进程,**不要合并成一个进程双路并行** —— 会抢 CUDA 上下文互相拖慢。
|
||||
- `tactile.cuda` 保持 `false`,`infer_backend` 用 `cpu`。
|
||||
- 退出时残留的孤儿 worker 会占死 `/dev/video`,`run_tactile.sh` 里那段 `pkill` 清理必须保留。
|
||||
@@ -0,0 +1,162 @@
|
||||
# =============================================================================
|
||||
# devices/sensors/orisys/manifest.yaml
|
||||
#
|
||||
# Orisys 视触觉传感器驱动清单(框架核心)。
|
||||
#
|
||||
# 这里【不放现场数值】。video 路径 / 型号 / 发布率一律在 config/site.yaml。
|
||||
# =============================================================================
|
||||
|
||||
id: orisys
|
||||
label: Orisys 视触觉传感器
|
||||
kind: sensor
|
||||
vendor: orisys
|
||||
version: "待填 —— 放入 SDK 后在此记录实际版本号"
|
||||
|
||||
# 从哪里读出「当前用哪个型号」。值是 config_schema 里的 field key。
|
||||
# 框架据此叠加该型号的额外能力(型号能力与顶层能力取并集)。
|
||||
model_selector: model
|
||||
|
||||
description: >
|
||||
视触觉传感器,输出两路切向力 + 一路法向力,以及深度图与力矢量图。
|
||||
采用双指方案,左右指各一个独立进程(防止抢 CUDA 上下文)。
|
||||
是本框架的长期核心,后续所有项目围绕它开发。
|
||||
|
||||
# 重要:上层算法依赖的数据契约
|
||||
outputs:
|
||||
- topic: tangential_1
|
||||
type: scalar
|
||||
unit: 任意单位(非牛顿)
|
||||
notes: 基线会漂移,所有阈值必须按「相对静止均值的增量」使用
|
||||
|
||||
- topic: tangential_2
|
||||
type: scalar
|
||||
unit: 任意单位(非牛顿)
|
||||
notes: 与 tangential_1 正交。通止规装配需要确认哪一路对应哪个方向,见 README
|
||||
|
||||
- topic: normal
|
||||
type: scalar
|
||||
unit: 任意单位(非牛顿)
|
||||
notes: 法向力。拧紧判定需要「法向力突增」这一条件
|
||||
|
||||
- topic: depth
|
||||
type: image
|
||||
unit: null
|
||||
notes: 接触面深度图
|
||||
|
||||
- topic: force_vector
|
||||
type: image
|
||||
unit: null
|
||||
notes: 接触点力矢量可视化
|
||||
|
||||
# --- 厂商物料放置要求 ------------------------------------------------------
|
||||
assets:
|
||||
- path: sdk
|
||||
required: true
|
||||
what: Orisys 厂商 SDK(Python 包或原生库)
|
||||
format: 厂商原始发布格式,不要转换、不要重新打包
|
||||
naming: 保持厂商原目录名与文件名,一律不要改名
|
||||
where_used: driver 通过 PYTHONPATH 或 pip install -e 加载
|
||||
notes: >
|
||||
SDK 内部常按自己的包名做导入与资源查找,改名会直接导致 ImportError。
|
||||
|
||||
- path: models
|
||||
required: true
|
||||
what: 各传感器型号的配置
|
||||
format: 每个型号一个子目录,内含 config.json
|
||||
naming: 子目录名即型号名,会被 site.yaml 的 tactile.model 引用
|
||||
where_used: driver 按 site.yaml 选中的型号加载对应配置
|
||||
|
||||
# --- 适配器 ----------------------------------------------------------------
|
||||
driver:
|
||||
package: arm_driver_orisys
|
||||
executable: orisys_tactile_driver
|
||||
build: colcon
|
||||
notes: >
|
||||
必须保持「左右指各一个独立进程」的架构,不要合并。
|
||||
必须保留退出时清理孤儿 worker 的逻辑(否则占死 /dev/video)。
|
||||
|
||||
# --- 能力声明 --------------------------------------------------------------
|
||||
capabilities:
|
||||
- read_tangential
|
||||
- read_normal
|
||||
- read_depth
|
||||
- read_force_vector
|
||||
- measure_baseline
|
||||
|
||||
# --- 配置项声明 ------------------------------------------------------------
|
||||
config_schema:
|
||||
- key: model
|
||||
site_path: tactile.model
|
||||
type: str
|
||||
required: true
|
||||
doc: 当前使用的传感器型号名。必须与 devices/sensors/orisys/models/ 下的子目录名一致。
|
||||
|
||||
- key: left_video
|
||||
site_path: tactile.left_video
|
||||
type: str
|
||||
required: true
|
||||
doc: >
|
||||
左指相机路径。必须用 /dev/v4l/by-path/ 下的稳定路径,
|
||||
不要写 /dev/video0(编号会随插拔漂移)。
|
||||
|
||||
- key: right_video
|
||||
site_path: tactile.right_video
|
||||
type: str
|
||||
required: true
|
||||
doc: 右指相机路径,同样用 by-path 稳定路径。
|
||||
|
||||
- key: baseline_seconds
|
||||
site_path: tactile.baseline_seconds
|
||||
type: float
|
||||
unit: s
|
||||
required: false
|
||||
default: 2.0
|
||||
doc: 启动后采集静止基线的时间。所有力阈值都是相对这个基线的增量。
|
||||
|
||||
- key: publish_hz
|
||||
site_path: tactile.publish_hz
|
||||
type: float
|
||||
unit: Hz
|
||||
required: false
|
||||
default: 20.0
|
||||
doc: 数据发布率。
|
||||
|
||||
- key: cuda
|
||||
site_path: tactile.cuda
|
||||
type: bool
|
||||
required: false
|
||||
default: false
|
||||
doc: >
|
||||
双指并行时保持 false —— 开 GPU 会让两路互相抢 CUDA 上下文,反而更慢。
|
||||
|
||||
- key: infer_backend
|
||||
site_path: tactile.infer_backend
|
||||
type: str
|
||||
required: false
|
||||
default: cpu
|
||||
doc: 推理后端。cpu / cupy / opencl。双指场景建议 cpu。
|
||||
|
||||
# --- 力阈值(通止规装配用)-------------------------------------------------
|
||||
# 全部是「相对静止均值的增量」,不是绝对值。见 README 的坑点说明。
|
||||
force_thresholds:
|
||||
- key: touch_delta
|
||||
site_path: hole_detect.stage3.touch_delta
|
||||
unit: 增量
|
||||
doc: 触面判定 —— 超过这个增量认为接触到了工件表面
|
||||
|
||||
- key: screw_done_shear_delta
|
||||
site_path: system.screw_done_shear_delta
|
||||
unit: 增量
|
||||
doc: >
|
||||
拧紧判定条件之一 —— 切向力超过这个增量。
|
||||
必须与 screw_done_normal_delta 同时满足才判定拧紧到位。
|
||||
|
||||
- key: screw_done_normal_delta
|
||||
site_path: system.screw_done_normal_delta
|
||||
unit: 增量
|
||||
doc: 拧紧判定条件之二 —— 法向力突增。
|
||||
|
||||
- key: safe_delta
|
||||
site_path: hole_detect.stage3.safe_press_delta
|
||||
unit: 增量
|
||||
doc: 安全上限。任何时候超过立即抬升并报错。
|
||||
@@ -0,0 +1,59 @@
|
||||
# devices/sensors/orisys/models/ —— 传感器型号配置
|
||||
|
||||
## 放什么
|
||||
|
||||
每个传感器型号一个子目录,子目录内存放该型号的厂商配置。
|
||||
|
||||
## 格式与命名要求(必须遵守)
|
||||
|
||||
| 项 | 要求 | 违反的后果 |
|
||||
|----|------|-----------|
|
||||
| 子目录名 | **就是型号名**,会被 `config/site.yaml` 的 `tactile.model` 引用 | 选型找不到配置 |
|
||||
| 配置文件名 | 固定为 `config.json` | 驱动按固定名加载 |
|
||||
| 内容格式 | 厂商原始 JSON 结构,不要自己重排字段 | 解析失败 |
|
||||
| 新增型号 | 从现有型号复制整个目录再改,不要在原型号上改 | 污染在用型号 |
|
||||
| 生效 | 改 `site.yaml` 的 `tactile.model` → 重启 `scripts/run_tactile.sh` | — |
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
models/
|
||||
├── README.md # 本文件
|
||||
├── dd03/ # 当前在用型号
|
||||
│ └── config.json # 从 src/arm_application/config/orisys/dd03.json 迁来
|
||||
└── <新型号>/
|
||||
└── config.json
|
||||
```
|
||||
|
||||
## 型号之间的差异由这里承载
|
||||
|
||||
不同型号可能在以下方面不同,**全部通过这个目录承载,上层代码不感知**:
|
||||
|
||||
- 相机分辨率与内参(影响深度图与力矢量图的标定)
|
||||
- 力的通道数(有的型号只有 1 路切向力)
|
||||
- 基线与噪声特性(影响阈值标定)
|
||||
- 左右指的拼接参数
|
||||
- 是否需要旋转配置(现有 `site.yaml` 里的 `left_rotation` / `right_rotation`)
|
||||
|
||||
## 新增一个型号的完整步骤
|
||||
|
||||
```bash
|
||||
# 1. 复制现有型号作为模板
|
||||
cp -r devices/sensors/orisys/models/dd03 devices/sensors/orisys/models/<新型号>
|
||||
|
||||
# 2. 按厂商资料修改 config.json 里的分辨率/内参/通道数
|
||||
|
||||
# 3. 在 site.yaml 里切换型号
|
||||
# tactile:
|
||||
# model: "<新型号>"
|
||||
|
||||
# 4. 重启并对比读数
|
||||
bash scripts/run_tactile.sh --cli
|
||||
```
|
||||
|
||||
## 关键提醒
|
||||
|
||||
换型号之后,**必须重新测基线并重新标定所有力阈值**。
|
||||
`site.yaml` 里的 `touch_delta` / `screw_done_shear_delta` / `screw_done_normal_delta` /
|
||||
`safe_delta` 都是「相对静止均值的增量」,不同型号的噪声水平不同,直接沿用旧阈值会导致
|
||||
接触判定误触发或完全不触发。
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "dd03",
|
||||
"type": "single_camera",
|
||||
"version": "1.0",
|
||||
"camera": {
|
||||
"resolution_raw": [1280, 720],
|
||||
"fps": 30,
|
||||
"resolution_stitch": [420, 450],
|
||||
"source_scale": 0.4,
|
||||
"old": [672, 728, 1, 0.5],
|
||||
"work": [504, 546, 1],
|
||||
"work2": [420, 450, 0.8],
|
||||
"work3": [350, 375, 4, 0.7],
|
||||
"work4": [280, 300, 4, 0.4, 0.2]
|
||||
},
|
||||
"tracker": {
|
||||
"adaptive": true,
|
||||
"lower_threshold": 12.0,
|
||||
"upper_threshold": 18.0,
|
||||
"loop_closure_interval": 1,
|
||||
"algorithm": "dis",
|
||||
"dis_preset": "medium",
|
||||
"dis_mode": 3,
|
||||
"algorithm_list": ["raft", "dis"],
|
||||
"hhd_downsample": 3
|
||||
},
|
||||
"contact": {
|
||||
"min_contour_area": 3000,
|
||||
"flow_threshold": 0.2,
|
||||
"div_threshold": 0.022,
|
||||
"expansion_threshold": 0.01,
|
||||
"kernel_size": [5, 5],
|
||||
"denoise_sigma": 12
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
# devices/sensors/orisys/sdk/ —— 放置 Orisys 厂商 SDK
|
||||
|
||||
## 放什么
|
||||
|
||||
Orisys 视触觉传感器的厂商 SDK(Python 包、原生库、或 ROS 包)。
|
||||
|
||||
## 格式与命名要求(必须遵守)
|
||||
|
||||
| 项 | 要求 | 违反的后果 |
|
||||
|----|------|-----------|
|
||||
| 格式 | 厂商原始发布格式。若是 `.whl`/`.tar.gz`,展开后放进来,不要留压缩包 | 无法 import |
|
||||
| 目录名 | 保持厂商原包名(如 `orisys_sdk/`),**一律不要改名** | Python 内部按包名做相对导入与资源查找,改名直接 `ImportError` |
|
||||
| 文件名 | 一律不改名 | 原生库按 `.so` 原名加载 |
|
||||
| 版本 | 记录进 `../manifest.yaml` 的 `version` | 日后无法排查版本问题 |
|
||||
| 原生库 | 若含 `.so`,确认架构是 x86_64 | 加载报错 |
|
||||
| 编译产物 | 不要把 `build/` 提交进 git | 仓库膨胀 |
|
||||
|
||||
## 放好之后怎么让它生效
|
||||
|
||||
```bash
|
||||
# 方式 A:可编辑安装(推荐,方便日后迭代 SDK)
|
||||
conda activate ros_flexiv
|
||||
pip install -e devices/sensors/orisys/sdk
|
||||
|
||||
# 方式 B:加入 PYTHONPATH(不改环境,只在当前 shell 生效)
|
||||
export PYTHONPATH="$PWD/devices/sensors/orisys/sdk:$PYTHONPATH"
|
||||
|
||||
# 冒烟验证
|
||||
python3 -c "import orisys_sdk; print(orisys_sdk.__file__)"
|
||||
```
|
||||
|
||||
然后:
|
||||
|
||||
```bash
|
||||
# 1. 确认选型
|
||||
cat devices/registry.yaml # sensors: orisys
|
||||
|
||||
# 2. 在 site.yaml 里选中型号
|
||||
# tactile:
|
||||
# model: "dd03" # 必须与 models/ 下的子目录名一致
|
||||
# left_video: "..." # 必须用 /dev/v4l/by-path/ 稳定路径
|
||||
# right_video: "..."
|
||||
|
||||
# 3. 确认型号配置存在
|
||||
ls devices/sensors/orisys/models/dd03/config.json
|
||||
|
||||
# 4. 启动
|
||||
bash scripts/run_tactile.sh # 图传 + 状态话题
|
||||
bash scripts/run_tactile.sh --cli # 只读数值,用来调阈值
|
||||
```
|
||||
|
||||
## 迭代 SDK 时的注意事项
|
||||
|
||||
这个 SDK 会持续迭代更新,升级时按下面顺序做:
|
||||
|
||||
1. 把新版本放在原目录名旁边(如 `sdk_new/`),**不要直接覆盖旧版本**;
|
||||
2. 用 `--cli` 对比新旧版本的读数(量纲、基线漂移、噪声水平是否变化);
|
||||
3. 读数一致后再切换;
|
||||
4. 更新 `../manifest.yaml` 的 `version` 字段;
|
||||
5. **如果量纲变了**,`site.yaml` 里所有力阈值(`touch_delta` / `screw_done_shear_delta` /
|
||||
`screw_done_normal_delta` / `safe_delta`)都需要重新标定 —— 这些阈值是相对基线的增量,
|
||||
单位一变全部失效。
|
||||
|
||||
## 已踩过的坑(不要重犯)
|
||||
|
||||
1. **左右指必须各一个独立进程**,不要合并成单进程双路 —— 会抢 CUDA 上下文互相拖慢。
|
||||
2. **`cuda` 保持 `false`**,`infer_backend` 用 `cpu`。
|
||||
3. **退出时残留的孤儿 worker 会占死 `/dev/video`**,导致下次启动失败。
|
||||
`run_tactile.sh` 里那段 `pkill` 清理逻辑必须保留。
|
||||
4. **不要用 `/dev/video0`**,用 `/dev/v4l/by-path/pci-...-video-index0`。
|
||||
Reference in New Issue
Block a user