# scripts — 唯一操作入口 实现细节在 [docs/WORKSPACE.md](../docs/WORKSPACE.md) 和 [docs/](../docs/)。 **每天:** `run_real.sh` · `run_camera_d405.sh` · `run_visual_servo_rt.sh` · `go_home.sh` **三阶段串联:** `run_all.sh --arm 89 [--hole k2] [--skip-stage1]`(`run_pipeline.sh` 是它的旧名别名) **手眼:** `run_handeye.sh`(`teach` / `merge` / `calibrate` / `show`) **夹爪:** `run_gripper.sh --arm 89|91` · `run_dual_gripper.sh` **入孔:** `run_hole_detect.sh --arm … [--preview]` **触觉:** `run_tactile.sh [--cli]` **通止规装配:** `run_gauge_assembly.sh --arm 89 [--dry-run] [--holes N] [--backend …]` - 一台状态机走完 S00–S11(自检 → 回 home/预绕 → 粗定位 → 跟踪 → 稳定拍照 → 悬停 → 柔顺接触 → 棘轮拧入 → 拧出 → 换孔 → 复位)。 - `--dry-run` **不发任何运动指令**,只验编排与自检 —— 改完配置先这么跑。 - 前置服务(臂 / 腕部相机 / 夹爪 / 触觉)要自己先起;缺哪项由 **S00 自检逐项报出** 并停住(不代你启动,也不"带病往下跑")。 - 掉件(E1):流程停在 home 等人,把规塞回爪里后发一次 `ros2 topic pub --once /gauge/reload_ok std_msgs/msg/Bool "{data: true}"`。 - 判据、调参顺序、还没做的部分:[docs/GAUGE_ASSEMBLY.md](../docs/GAUGE_ASSEMBLY.md) **权重:** `weights.sh`(`list` / `labels` / `convert` / `doctor` / `show`) - 转换:`weights.sh convert <文件> --name <模型名>` —— PT→ONNX→TensorRT,自动改名归位 + 固化标签 - 标签:`weights.sh labels <模型名>` 看,`--set "工件,通止规"` 改 - 体检:`weights.sh doctor --check-engines`(能查出 engine 与 TensorRT 版本不匹配这类静默失效) - 规则写在 [models/README.md](../models/README.md)。`export_yolo_trt.sh` 现在是它的兼容转发壳。 **配置:** `show_site_config.sh` · `lib/export_site_env.py` **仿真:** `run_sim_gz.sh`(Gazebo 物理仿真,唯一能做接触/力控验证的入口) 停:`stop_sim_gz.sh`(**别敲 `pkill -f gz`** —— 会杀掉调用它的 shell,见脚本文件头) - 环境是独立 conda 环境 `ros_gz_sim`(`install_sim_env.sh` 装、`sim_env.sh` 激活),与真机环境隔离 - 相机验收:`python3 scripts/check_sim_cameras.py` —— **别用 `ros2 topic hz` 或肉眼看图验收相机**, 仿真相机的错误几乎全是静默的(深度单位、frame_id、内参、位姿方向),都能出图却是错的。 这条命令把深度反投影到 world,要求命中已知平面(地面/台面)才算通过。 - 场景验收:`python3 scripts/check_sim_scene.py` —— 同样别靠肉眼。它管四件事: 物体的摆放(悬空/穿模/出界/互相嵌入)、场景里的像素门槛与**真机生效值**是否漂移、 孔检测的成像几何(亮环/孔间距换算成像素后够不够门槛)、以及粗定位用的手外相机 能不能**完整**看见工件。第二条尤其重要:门槛抄了两份,不一致时仿真会"通过"而真机不认。 - 注意 `run_sim.sh` 不是 Gazebo,它走 mock 驱动(假数据 + RViz),永远不会产生接触力 **环境:** `env.sh` · `build_all.sh` **RDK:** `test_rdk_python.sh` · `rdk_switch_tool.sh` · `rdk_drag_bridge.py` **改注释/写文档后自检:** `python3 scripts/check_text_only.py` - 用途:证明这次改动**只动了文字**(注释、docstring、提示信息),没碰逻辑。 它把改动前后的源码解析成语法树,删掉 docstring、抹平字符串常量后比对; "翻译 f-string 时漏掉一个 `{}` 插值""顺手改了个变量名"这类问题会被抓出来。 - `python3 scripts/check_text_only.py` 查所有改过的 `.py`;也可以直接跟文件名。 基准是 `git HEAD`,所以要在**提交之前**跑。老手滑手滑的代价比跑一条命令高得多。 - 规矩写在 [docs/FRAMEWORK_RULES.md](../docs/FRAMEWORK_RULES.md) 的 R6.5。 一句话:**注释/docstring/提示信息用中文;标识符、话题名、字段名保留英文** (但 `src/flexiv_*/` 是厂商上游代码,不许翻译,见 R4.4)。 **搁置未用:** `fetch_isaac_flexiv.sh`(拉 Flexiv 的 Isaac Sim / RDK 源码到 `thirdparty/`;Isaac 路线目前搁置,Gazebo 是选定平台) `lib/parse_arm_args.sh` 解析 `--arm 89|91`。 `lib/load_site_config.sh` 把 `config/site.yaml` 变成 `SITE_*`。 ## 排查脚本卡住时的常识 几个脚本开头会等外部条件(控制器 ACTIVE、相机出图、触觉就绪)。**正确的判活顺序是 先 `ros2 service list` / `ros2 topic list` 看目标在不在,再去 call / echo**: ```bash # 对:服务不存在时立刻返回 timeout 3 ros2 service list | grep -q '^/controller_manager/list_controllers$' || exit 1 timeout 3 ros2 service call /controller_manager/list_controllers ... # 错:服务不存在时每次 call 都要耗满超时才返回, # 30 次循环 = 白等两三分钟(实测 63s),看起来就像脚本卡死了 for _i in $(seq 1 30); do timeout 5 ros2 service call ... ; done ``` `run_all.sh` / `run_stage2_locate.sh` / `run_stage3_search.sh` 已按正确顺序改过; `run_handeye.sh` 一开始就是对的。