Files
ros_contorl/scripts
arm_dev 811e71df1f 仿真上料:夹爪真能夹住通止规(新增 sim_load_gauge.py + 夹爪出力钳位)
仿真里没有"人把规塞进夹爪"这一步,之前整条流程拖到 S07 才暴露(下探 25mm
什么也没碰到,看着像力阈值问题)。新增 scripts/sim_load_gauge.py 顶这一步。

上料为什么难(四个原因叠加,都实测踩过):
  1. URDF 里夹爪关节 effort=80Nm → 位置控制器把规顶飞。urdf_normalize 新增
     _clamp_grip_effort:按握力 45N 与指节杠杆反推,指节 4.79Nm / 主关节 45N。
  2. **指腹接触面不在 tcp_frame 原点上**:URDF 里 inner_finger_pad_joint
     z=0.0235、finger_tcp_joint z=0.0360(同父链节同方向)→ 指腹中心比
     tcp_frame 高 12.5mm。所以规尖→指腹中心是 0.043,不是夹持段中心的
     0.0555。用错值的现象极迷惑:gz 报得出 Contacts、也能读到接触,但规
     就是托不住、一路滑下去。ΔZ 扫描实测:0/±5mm 掉、+10~+15mm 夹住。
  3. 摆完位就自由落体:ROS 往返 100ms+ 而物理步进 1ms,等合爪指令到达,
     规已掉 125mm。改成**像人手一样托着** —— 合爪期间 50Hz 按当前指腹位姿
     把规瞬移回两指之间,托到真夹住为止。
  4. 合到多少不猜:从松到紧扫开口,扫到"松手后不掉"为止。指腹实际接触面
     未必在 tcp_frame 原点,拿"指间间距=开口"反推闭合量会差好几毫米。

结果:漂移 0.4mm、两指 |fnormal|≈46.5N(正好是 45N 设计握力)。
另修 _set_gauge_pose 的 ign service 口径说明与 _gauge_pose_now 的解析。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-24 14:42:56 +08:00
..

scripts — 唯一操作入口

实现细节在 docs/WORKSPACE.md 和 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 权重: 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。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 的 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:

# 对:服务不存在时立刻返回
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 一开始就是对的。