P1:设备契约层收尾 + Flexiv 驱动适配器 + 触觉四路数据打通

新增包
- arm_kinematics:从 arm_application 提取几何雅可比 + DLS 逆解(纯 numpy)。
  它被应用层和驱动层共用,留在应用层会让驱动反向依赖应用层。
  arm_application/geom_ik.py 改为 re-export shim,现有 import 一行未改。
- arm_driver_flexiv:非夕驱动适配器。只补 manifest 声明而现有节点缺失的接口
  (/home /enable /clear_fault /switch_tool /soft_drag /compliant_descent),
  已有能力不重复实现。RDK 访问经 rdk_py310 下的长驻桥,本包不 import flexivrdk。

新接口
- arm_msgs/SwitchTool.srv、arm_msgs/CompliantDescent.action
- 合并 capabilities 里语义重复的 set_tool / switch_tool

修复(都是只在真机上暴露、且难以定位的问题)
- rdk_client 会永久挂死:select 的"可读"不等于"有完整一行",readline 遇到
  半行 JSON 会一直阻塞等换行符,超时机制完全失效。改用 os.read + 自己做行缓冲。
- CompliantDescent 行程少一步:descended + step > max 在浮点累加下会提前跳出,
  永远到不了标称行程。改用整数步数计数。
- CompliantDescentRunner 的 TF frame 退化成 _base_link:没继承节点已解析的 SN。
- resolve_orisys_config 仍指向旧路径;load_orisys_from_site 读的是旧键 config。

触觉四路数据打通
- 深度图 / 力矢量场原先被 tactile_worker 有意丢弃(注释写"图像不过队列"),
  从未发布到 ROS。新增 image_utils(数组→Image,编码自动判定)、独立的图像
  队列(maxsize=1 满则丢旧)与 /tactile/<side>/{image,vector}。
  默认关闭(tactile.image_hz=0),开启也不影响三力的 30fps 时序。
- mock 后端也会发图像,无硬件即可验证整条发布链路。

配置
- site.yaml 新增 tactile.image_hz;移除与 model 重复的旧键 tactile.config
- 型号配置从 src/arm_application/config/orisys/ 迁到
  devices/sensors/orisys/models/dd03/(随 SDK 一起放)

测试:198 个(原 139)
- arm_kinematics 24(雅可比/逆解的解析算例与不变量)
- arm_driver_flexiv 69(下压状态机 34 + RDK 协议层 35)
- arm_application 59(图像打包 36 + 矢量场探测 23)
This commit is contained in:
arm_dev
2026-09-23 11:17:12 +08:00
parent 6edb8d39ab
commit 883ed6b0b9
39 changed files with 4295 additions and 245 deletions
+2
View File
@@ -23,8 +23,10 @@ rosidl_generate_interfaces(${PROJECT_NAME}
"srv/SetNamedPose.srv"
"srv/GetArmState.srv"
"srv/GripperExecute.srv"
"srv/SwitchTool.srv"
"action/MoveToPose.action"
"action/FollowJointTrajectory.action"
"action/CompliantDescent.action"
DEPENDENCIES std_msgs geometry_msgs builtin_interfaces sensor_msgs
)
@@ -0,0 +1,40 @@
# 柔顺下臂:从当前悬停位姿沿工具系 −Z 缓慢下压,直到触觉检测到接触。
#
# 通止规装配 S07(下臂接触)专用原语。
#
# 为什么不用 RDK 的柔顺模式:非夕 RDK 的 compliant motion 会接管整臂阻抗,
# 而装配的其它阶段(跟踪 / 对准 / 拧入)都走 JTC 位置控制;在两种控制权之间
# 来回切换代价高、掉电风险大。这里用「小幅步进 + 力反馈」在应用层做等效:
# 每步 0.2~1.0 mm,步间等稳定,一旦切向力相对基线跳变立即停住。
# 对通止规这种「碰到就必须停」的场景足够,而且任何一步都可以安全中断。
#
# 力阈值全部是「相对静止基线的增量」:Orisys 读数是形变任意单位且基线会漂移,
# 绝对值没有意义。基线由传感器节点的 measure_baseline 服务在启动时测定。
# --- 目标与判据 ---
float64 target_x_m # 目标法兰 X(基座系,m)。NaN = 保持当前 XY 不动
float64 target_y_m # 目标法兰 Y(基座系,m)。NaN = 保持当前 XY 不动
float64 contact_axis # 监测哪条切向通道:0 = 第一路切向,1 = 第二路切向
float64 contact_delta # 接触判据:|切向力| 相对静止基线的增量(传感器原生单位)
float64 max_normal_delta # 法向力安全上限(相对基线增量)。<=0 = 不检查
string side # 用哪只手指的触觉:left | right(装配时是持规那只)
# --- 运动参数 ---
float64 descent_step_m # 每步下压量(m),建议 0.0002 ~ 0.0010
float64 descent_speed_mps # 名义下压速度(m/s)。步进间隔 = step / speed
float64 max_descent_m # 最多下压距离(m)。安全上限,到了判失败并停住
float64 settle_sec # 每步后等待稳定(s)。0 = 不等,靠触觉话题新鲜度
float64 timeout_sec # 总超时(s)。0 = 由 max_descent_m / descent_speed_mps 推算
---
bool success # true = 检测到接触且已停住
string message # 失败原因:超时 / 触觉断流 / 达到行程上限 / 法向力超限
geometry_msgs/PoseStamped contact_pose # 接触瞬间的法兰位姿(基座系)
float64 descended_m # 实际下压距离(m)
float64 contact_delta_observed # 触发瞬间的切向增量
float64 normal_delta_observed # 触发瞬间的法向增量
---
float64 progress # 0.0 ~ 1.0(descended_m / max_descent_m)
float64 descended_m # 当前已下压距离(m)
float64 tangential_delta # 当前切向增量(相对基线)
float64 normal_delta # 当前法向增量(相对基线)
string status # approaching | contacting | retracting | done | error
+17
View File
@@ -0,0 +1,17 @@
# 切换到已保存的工具坐标系(如 tool1)。
#
# 背景:非夕的工具坐标系(TCP + 质量 + 质心)在 Studio 里预先配好并命名,
# RDK 只提供「按名字切换」一个操作。通止规装配要求工具系全程垂直向下锁定,
# 所以在流程开始前必须确认已切到正确的工具。
#
# 实现:arm_driver_flexiv 调用 scripts/rdk_switch_tool.py(子进程,rdk_py310)。
# 注意 RDK 是独占访问,切换时臂必须处于 IDLE 且没有其它进程连着 RDK。
string tool_name # Studio 里已保存的工具名。空字符串 = 只查询当前状态,不切换
string sn # 目标臂 SN(如 Rizon4-063989)。空 = 用 site.yaml 的 robot.sn
---
bool success # 是否已达到目标状态(已在该工具上也算成功)
string message # 失败原因;成功时为当前工具名说明
string current_tool # 操作后的当前工具名
float64 tool_mass_kg # 该工具的质量(kg);查询不到为 0
float64[3] tool_com_m # 该工具的质心(法兰系,m);查询不到为全 0