真机落地前的仿真补齐:夹持/腕力/真值位姿,让仿真能验证 S07–S09

这批是 09-24 那轮仿真工作的收尾,一直没提交。内容按目的分四块:

1) 仿真真能「夹住」工件
   sim_grasp_lock:给规与夹爪之间加接触锁(默认关,run_gauge_assembly --sim 才开)。
   没有它时仿真里规只靠摩擦,S08 棘轮一转就滑出指间,于是把「仿真不真」误读成
   「力判据不对」。新增 test_sim_grasp_lock.py。

2) 腕部力传感器进仿真
   sim_wrist_ft(+ config/wrist_ft.yaml):S07 的首选判据是腕部 FT 的轴向突变,
   而仿真里以前根本没有腕部力,S07 只能退到触觉兜底,两套判据从没在同一场景下比过。
   现在两条通道都在,接触判定可对照。

3) 真值位姿可查(不再靠猜)
   sim_live_pose / sim_pose_service:把 Gazebo 里刚体的实测位姿发布出来,
   stage2 的真值路径按**实测**位姿算孔位,而不是按场景文件里的标称位姿。
   顺带把真值孔位的推导(truth_holes)独立出来并补测。

4) 工具几何成为可配置项
   config/sim_tool_geometry.yaml + stage2 的 tool_tip_below_flange_m 启动参数:
   仿真里规会在指间下滑,工具长每次装夹都不同(实测见过 243/254mm),
   悬停高度与 S07 下探预算必须按实测值算,不能再写死。

应用层同时跟进:gauge_fsm / gauge_config 把「悬停时工具尖端入没入工件」的判据
(hover_z_guard)与拖件判定(drag_verdict)收成纯函数并补测;stage3 搜孔、
site 导出、run_gauge_assembly 与若干文档同步。
新增 test_gauge_exit_lift / test_gauge_gripper_client / test_node_handler_collisions。

测试:全仓库 1085 passed。
This commit is contained in:
arm_dev
2026-09-28 10:17:06 +08:00
parent 1b4d6168d9
commit c1cd862eea
41 changed files with 5327 additions and 115 deletions
+68
View File
@@ -0,0 +1,68 @@
# =============================================================================
# devices/sim/gazebo/config/grasp_lock.yaml
#
# 仿真"抓取锁"(grasp lock)的口径。**只对仿真有意义**,真机没有任何对应物 ——
# 真机靠夹爪的摩擦夹持,本来就不会掉。
#
# -----------------------------------------------------------------------------
# 它解决什么问题(2026-09-24 一整轮排查换来的)
# -----------------------------------------------------------------------------
# 仿真里的夹持力不是"设"出来的,而是**位置误差 × 接触刚度**(见 gauge/model.sdf
# 里 kp 那段)。规站着不动时够用;机械臂一动就不行:
#
# S01 绕工具轴快转 150°、pre_lift/粗定位是 60~100mm 的连续轨迹 ——
# 这两步里规在指间打滑。实测工具长度 0.243m → 0.285m、规歪 62°,
# S07 随后拿到的几何全错,现象是"S07 判不到接触"或"规掉了(E1)"。
#
# 真机不会这样:握力 46N、µ≈0.8、规 0.265kg —— 摩擦余量两个数量级。
# 所以这把锁补的是 **Gazebo 缺的那块物理**(刚性接触没有静摩擦迟滞、也不模拟
# 指垫橡胶的贴合),不是绕过物理:规与指垫的接触对仍在,触觉与腕部 FT 的读数
# 依旧是真实接触力。
#
# -----------------------------------------------------------------------------
# ⚠️ 一处对不上就**静默失效**(不报错,只是规不跟着走)
# -----------------------------------------------------------------------------
# 本文件的名字必须与下面三处一致:
# ① gauge/model.sdf 里 DetachableJoint 插件的 <child_model>/<child_link>
# ② gauge/model.sdf 里插件的 <attach_topic>/<detach_topic>
# ③ 真名(Gazebo 里实际存在的连杆名)—— URDF 里与固定关节相连的连杆会被
# sdformat **合并(lump)**,名字会变:手指只剩 sim_left_finger_mount。
# 查真名的办法:
# ros2 topic echo /sim/world_pose_info ← 看全部 child_frame_id
# gazebo_sim.launch.py 启动时会读 gauge 的 SDF 核对 ① ②,不一致就直接报出来。
# -----------------------------------------------------------------------------
# 总开关。关掉它仿真照样跑,只是回到"靠摩擦夹持",也就是上面那串毛病。
enabled: true
# 被夹住的物体(scene.yaml 里的物体名 = Gazebo 里的模型名)。
object: "gauge"
# 该模型里被夹的那根连杆。
object_link: "body"
# 机器人侧:模型名 = launch 里 spawn 的 -name;连杆名必须是 Gazebo 的**真名**。
#
# ⚠️ 必须锁到**不会跟着张爪动的**连杆上 —— 默认是 `sim_link7`(法兰)。
# 为什么(2026-09-24 实测,一条假 E1 的真因):
# 起初锁到 `sim_left_finger_mount`(左手指)。夹住的规被**刚性**锁在这根
# 手指上,而 S08 棘轮每轮都要"松爪 → 回转 → 夹紧":张爪时手指往外走
# 40mm,被锁住的规却还插在孔里(6mm 销 / 7mm 方孔)——两处约束打架,
# 物理解算把规**从孔里拽出来**(实测规尖跳 +17.5mm、偏摆 64°),
# 然后在回转那一步掉到地上。日志只看得到"通止规掉了(E1)"。
# `sim_grav_base_link`(夹爪本体)在 sdformat 里被**合并**进了 `sim_link7`
# (见 /sim/world_pose_info 里的 `sim_link7_fixed_joint_lump__...`),
# 所以锚点就写 `sim_link7`:张爪不影响它,松爪/夹紧都不会带偏规。
# `sim_grasp_lock.load_grasp_lock()` 会拒绝含 `finger` 的连杆名(带这段原因)。
robot_model: "rizon_sim"
robot_link: "sim_link7"
# 触发话题(gz 侧,由本模块用 ign topic 发一个空消息触发)。
# 名字必须与 gauge/model.sdf 里插件的 attach_topic/detach_topic 一致。
attach_topic: "/sim/grasp_lock/attach"
detach_topic: "/sim/grasp_lock/detach"
# 插件状态回执(会 attach/detach 成功时各发一条)。用它来判断"锁到底有没有生效",
# 而不是靠"看规掉没掉"——后者要等故障发生才知道。
state_topic: "/sim/grasp_lock/state"
# 发一次触发消息后等多久 [ms](ign topic 是短命进程,给足启动时间)。
publish_timeout_ms: 3000