Files
TG3/tg3_data_collection/README.md

149 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TG3 data episode sync
机器人只在 `/home/nvidia/tg3_data_collection/ready` 暴露已经收到 SIGINT、写完
`metadata.yaml`、通过 `ros2 bag info` 并生成 SHA-256 清单的 episode。本机服务用免密 SSH/rsync 复制到
`Data_Get/.incoming`,逐文件校验并 fsync 后再原子改名为 `Data_Get/<episode_id>`。本机
`VERIFIED` 收据持久化成功后,正式服务会再次完整哈希本机 payload,再让 Nvidia 侧固定根目录
helper 比对原始 manifest SHA-256,原子移入 `deleting/` 后清理。因此完整数据最终只保留在 PS 本机,Nvidia 只是临时
staging;中断、哈希错误或本机落盘失败都不会触发远端删除。
数据只走本机到 Nvidia 的 SSH 链路,与公网或 EAI 本地 OmniSocket Hub 无关。当前默认:
```text
nvidia@192.168.41.2:/home/nvidia/tg3_data_collection/ready/
-> /home/ps/Desktop/TG3_TS1P_OmniSocket_Teleop/Data_Get/
```
EAI 不运行 recorder/sync,也不保存 MCAP 或图像数据。
先确认免密与依赖:
```bash
ssh -o BatchMode=yes nvidia@192.168.41.2 true
command -v rsync
ssh nvidia@192.168.41.2 command -v rsync
```
先把固定根目录删除 helper 部署到 Nvidia。它的 CLI 只接受安全 episode ID 和 64 位
manifest SHA-256,不接受 root 参数,也不会枚举或触碰 `active/`、`failed/`。helper 在
`deleting/` 树之外的 `delete_ledger/` 先持久化独立删除授权;即使递归删除中断且 tombstone
里的 READY/manifest 已消失,仍能凭该授权安全续删,最后才删除授权文件:
```bash
scp tg3_local_teleop/delete_ready_episode.py \
nvidia@192.168.41.2:/home/nvidia/tg3_local_teleop/
ssh nvidia@192.168.41.2 \
chmod 755 /home/nvidia/tg3_local_teleop/delete_ready_episode.py
```
安装本机用户服务:
```bash
mkdir -p ~/.config/systemd/user
cp tg3_data_collection/tg3-data-get-sync.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now tg3-data-get-sync.service
```
状态:
```bash
systemctl --user --no-pager status tg3-data-get-sync.service
python3 -m json.tool Data_Get/sync_status.json
```
也可以只执行一次,便于首次部署验收:
```bash
systemctl --user stop tg3-data-get-sync.service
python3 tg3_data_collection/data_get_sync.py --once --delete-remote-after-sync
systemctl --user start tg3-data-get-sync.service
```
同步器使用 `Data_Get/.data_get_sync.lock` 做 flock;正式服务运行时,另一个 `--once` 会明确
报“已有同步进程”,不会与服务同时复制或删除。不带 `--delete-remote-after-sync` 的手动命令
只复制、验真并保留远端,正式 unit 已显式启用自动回收。
日常轮询不会每 2 秒重新读取并哈希全部历史 MCAP;首次原子发布时已经完成深度校验。
如果进程在远端删除 ACK 返回前退出,`VERIFIED` 会保持 `pending`。每次真正调用 helper
之前都会重新完整哈希本机 payload;失败后从 30 秒开始指数退避,最大 15 分钟,进程重启也
遵守持久化的 `next_retry_unix_s`,避免每 2 秒重读大型 MCAP。helper 使用独立 600 秒超时,
能继续清理同摘要 tombstone/ledger,也会把已经不存在的同一目标视为成功。
需要定期审计已有本地数据时单独执行(可能耗时较长):
```bash
python3 tg3_data_collection/data_get_sync.py --once --verify-existing
```
某个旧 episode 损坏会写入 `sync_status.json`,但不会阻止同一轮继续拉取其他新 episode。
一个完成目录至少包含:
```text
<episode_id>/
READY
VERIFIED
manifest.json
bag/metadata.yaml
bag/*.mcap
ros2_bag.stdout.log
ros2_bag.stderr.log
```
同步端会再次核对 `READY`、episode ID、每个 MCAP/metadata 的长度和 SHA-256;远端
manifest 在传输中发生变化也会拒绝发布最终目录。随后 fsync 所有复制文件和目录、以
NOREPLACE 语义原子发布、fsync 父目录,最后写入并 fsync `VERIFIED`。收据绑定 episode、
远端身份、原始 manifest SHA-256、已校验文件数和字节数,并记录 `pending/deleted`。
`.incoming`、`sync_status.json` 和全部 episode 已由 `Data_Get/.gitignore` 排除。
临时目录按 `<episode>.<manifest_sha256>.partial` 隔离,rsync 同时使用删除同步;发布前还会
拒绝 manifest 未列出的任何 `*.mcap` 或 `metadata.yaml`,避免旧中断文件混入新 episode。
`sync_status.json` 的 `state=delete_pending` 表示本机数据已完整发布,但远端回收尚未收到
成功 ACK;`pending_remote_cleanup`、`last_delete_error`、`delete_count` 和
`last_deleted_episode` 可用于排查。此状态下不要手工删除本机数据,服务会在下一轮重试。
已有本机同名目录不会直接授权删除:没有可信 `VERIFIED` 时必须重新做完整哈希,并要求
本机与当前远端 manifest 原始摘要一致,之后才补收据并回收远端。同名碰撞、损坏、符号
链接、错误 root 或摘要不符都保留远端并报错。
历史 `retained/deleted` 收据可以来自旧机器人 IP,不会阻塞新地址的同步;仍为 `pending` 的
跨 IP 收据不会静默授权新机器人删除,只会逐项报错且不影响其他新 episode 继续同步。
自动回收 helper 严格只覆盖 `ready/`,录制中的 `active/` 永远不能由 PS 同步器处理,
也不能对 `failed/` 使用 READY 凭据。当前正式配置为
`retain_failed_episodes=false`:录制器只把失败原因写入状态和 journal,随后精确删除自己
刚创建的失败 payload,因此机器人不会长期保留失败 MCAP。若以后改回 `true` 以保留故障
诊断,必须另建独立验真与回收协议,不能整目录清空。
## 解码双臂关节数据
MCAP 内的自定义 TG3 消息使用 CDR 编码。解码器读取项目保存的消息定义,并把实际反馈、
遥操目标、厂家桥后命令和 xTELE 原始目标分别导出为长表 CSV。首次使用在独立虚拟环境
安装依赖:
```bash
python3 -m venv /tmp/tg3-mcap-venv
/tmp/tg3-mcap-venv/bin/pip install mcap==1.4.0 mcap-ros2-support==0.5.7
/tmp/tg3-mcap-venv/bin/python tg3_data_collection/decode_joint_data.py \
Data_Get/<episode_id>
```
输出位于 `Data_Get/<episode_id>/decoded_joints/`:
- `robot_arm_feedback.csv`:`/robot_state`、`/freq_change/arm_status` 和
`/data_logger/arm_status` 的实测位置、速度、电流、温度及错误码;
- `teleop_joint_target.csv`:`/encoder_identical_joint` 的 14 轴遥操目标;
- `vendor_arm_command.csv`:`/arm/cmd` 的厂家桥后控制参数;
- `iarm_source_joint.csv`:`/tg3/data_collection/iarm_frame` 中的 TS1P 原始目标;
- `summary.json`:关节顺序、Motor ID、单位和行数。
关节顺序为左臂 7 轴后右臂 7 轴,Motor ID 分别为 `11..17` 和 `21..27`;位置单位
为 rad,速度单位为 rad/s。输出目录必须不存在,避免误覆盖已经分析或标注过的数据。
迁移后需要同步修改 service 中的本机项目路径和机器人 SSH 地址。如果 Nvidia 的
`192.168.41.2` 改变,只改 unit 的 `--remote` 并重新部署 helper;它不在机器人
`config.toml` 或 OmniSocket Peer 设置中。启用自动删除时远端路径必须保持固定的
`/home/nvidia/tg3_data_collection/ready`,同步器会拒绝对其他 root 启用删除。