E3 · 力读回:对象、作用点、表达系和采样#
Sim Atlas 学习首页 · 先读材料与几何、求解与时间
本篇回答 E2 状态机的 normal_force/slip 输入应从哪里来,什么情况下仍然不能直接使用。固定源码版本仍是 Drake 1.57.0;没有执行读回、接触、传感或 DexLab 评测。
1. 先选择要观察的物理量#
原生读回 |
对象、单位、排列 |
不可替代的另一量 |
|---|---|---|
|
actuator 坐标下总驱动,N 或 N·m |
物体接触力、传感器 wrench |
|
对应该实例 v 的广义接触力,N 或 N·m |
任意指定点的三维力 |
|
B 受到的力,作用在 C,world 表达,N |
A 的力、body frame 分量 |
|
A 受到的 |
point 结果的 B 侧约定 |
|
joint child C 在 Jc 处、Jc 表达的 wrench,按 JointIndex |
只由接触产生的力 |
solver 内部 γ |
每项 constraint 的冲量,接触为 N·s |
已除 h 的公开报告力 |
joint reaction 可以包含为实现机构运动而传递的重力、惯性、驱动和其它作用;不能将其绝对值直接称作手指夹持力。generalized contact force 是投影后的 Jᵀf,一般不可唯一反推全部接触点力。广义/反力端口、point 合同、hydro 合同
2. ContactResults 的两类结果必须分别遍历#
get_contact_results_output_port().Eval(plant_context) 返回 ContactResults。分别遍历 num_point_pair_contacts()/point_pair_contact_info(i) 和 num_hydroelastic_contacts()/hydroelastic_contact_info(i);fallback 场景只遍历一个集合会漏掉另一种接触。另有 deformable contacts,本文例子无 deformable body,不能把该范围默默推广为所有形变体观测。集合接口、Python 绑定
2.1 Point 的正法向与 slip#
point 结果给 BodyIndex,内部 point_pair() 给 GeometryId。其 normal n_BA 指 B→A,但 contact_force() 是 B 受到的力,因此压缩法向幅值应按本约定取
理想有效压缩结果 fn≥0;诊断时应保留带符号的值及原始向量,不能先 abs/clip 把 A/B 错置掩盖。若关心 A,先取 fA=−fB。slip_speed() 是接触点相对切向速度的非负范数,separation_speed() 是带符号的法向分离速度;不要用 world 中某个 body 的 x 速度代替。结果字段
离散实现先从 contact frame 的 [ft1,ft2,fn] 旋转为 world 的 fB;slip 取 solver 接触切向速度的 norm。不同步的 body pose 与这个力记录拼在一起,会产生错误力臂。离散读回装配
2.2 Hydro 的压力、wrench 和实体映射#
surface 的 id_M()/id_N() 分别对应 HydroelasticContactInfo 中的 A/B 侧。它们是GeometryId,不是 BodyIndex;用 inspector 的 geometry→FrameId,再用 Plant 的 GetBodyFromFrameId 找到实际 body。一个 body 上多个几何的结果可以分开,也可在相同参考点与表达系下求和。
F_Ac_W() 已是积分后的 A 侧空间力,排列 [τx,τy,τz,fx,fy,fz]。surface 的 tri_e_MN()/poly_e_MN() 是弹性压力场;在离散输出中它与旧几何关联,而最终 wrench 来自各面片的求解力累加。不要把 max pressure × total area 当成总法向力,也不能用单一 surface normal 代表曲面所有局部法向。surface 身份与场、离散积分读回
公开 HydroelasticContactInfo 没有与 point 完全同义的单个 slip_speed() 字段。若任务需要 hydro slip,应指定位置/面片、两物体相对运动及表面速度,再定义最大值、面积/压力加权统计等观测合同;不同定义不能混成同一个阈值。该观测设计不由总 wrench 自动确定,也不是本例已实现的触觉传感器。
3. 换参考点与换表达系是两步#
已知作用在 C、world 表达的 wrench [τC;f],想改到 O,且不改变物理受力对象:
原生 SpatialForce.Shift(p_CO_W) 的参数从旧作用点 C 指向新作用点 O,即 p_WO−p_WC。源码对应 τO=τC−p_CO×f,与上式相同。之后以 R_SW=R_WSᵀ 将 torque 和 force 都旋转到 sensor frame S;只旋转力而不处理力矩/作用点,会得到错误 wrench。Shift 合同
例如 C=(1,0,0) m,O=(0,0,0),f=(0,2,0) N,τC=0,则 τO=(0,0,2) N·m。这个解析算例只检查符号与单位,没有执行 Drake。
point 是 C 处无附加偶矩的力;转换到传感器原点时通常有力矩。hydro 可因分布式 traction 在 centroid 自带非零力矩,不能将它先降成三维力再重建。A/B 作用反作用只有在同一点、同表达系时六维向量才直接互为负;两 body 原点不同的 wrench 要先 shift 对齐。
两个对向手指给物体的净力可以近零,同时每侧压紧力都很大。故“合力 norm”不是夹持力,||τ_contact|| 也不是。任务接口要明确观测的是左指法向和、右指法向和、两者最小值、还是传感器特定轴;对应坐标、符号和过滤对象必须一并记录。
4. force、impulse 与时间窗口#
4.1 离散输出的力等于冲量除以 h#
SAP 首先求 γ;PackContactSolverResults 按 contact 范围提取 γn/γt,再分别除以 Plant h 得 fn/ft;广义接触力为 ΣJᵀγ/h。这是该离散更新所对应的等效步平均力,不是无限时间分辨率下的瞬时撞击峰值。实际除 h
例如 γn=.02 N·s、h=.001 s,报告 fn=20 N;这个单位换算不证明真实峰值就是20 N,也不意味着把 h 减半后 γ不变。对长时间窗求冲量,应对每个不同物理更新的力乘其 h 后累加,不能按日志行数重复积分同一个 hold/sample。内部 ContactSolverResults.ft 旁的遗留注释误称 tangential velocities;数据赋值与除 h 的路径明确表明它存力,真正速度字段是 vt。内部字段对照
连续模型的 contact force 是当前状态下的正则化力;连续冲量需要对时间积分。两类值都以 N 表示,不代表具有相同时间窗口,不能直接比较逐帧最大值。
4.2 默认 sampled contact 属于上一次已计算更新#
离散 Plant 默认将 dynamics 输出保存在 step memory。状态 x[n+1] 已更新时,contact geometry 来自该步起始配置 q[n],力来自为这一步求出的冲量,接触速度由 J(q[n])v[n+1] 等定义。当前读回时间、几何时间和力对应的更新区间必须区分。采样方程、memory 保存
在第一次物理更新前,sampled ContactResults 为空;这不证明几何不相交,也不证明 SceneGraph 失效。直接 SetPositions 改了 live q,旧 sampled 输出也不会立刻变成新配置的接触。启用 live 输出会在当前状态计算下一步离散动力学相关结果,可能触发一次求解;它仍不是连续模型瞬时力。ExecuteForcedEvents 会推进物理状态,不能当作无副作用的“刷新力缓存”。输出合同、未采样时为空
ContactResults 本身不是附带完整实验时间元数据的日志。例子只记录 query_time_s,没有把它伪装成 sample_time_s。正式复用 DexLab 时应沿用其真实事件时序记录,而不是事后假设 query_time−h 必为采样时刻;初始化、强制事件、事件左/右极限和异步记录都会使这种猜测不可靠。
5. 把读回接到 E2 任务之前#
contact_inspection.py 的 read_contact_fields 明确输出 point 的 B 侧 force 和 hydro 的 A 侧 wrench,保留 geometry/body 身份和作用点;对 NumPy 数值做副本,不把 cache-backed 引用保存为长期快照。构造函数没有调用该 reader,整个文件在本阶段也没有执行。Python point/hydro 绑定、surface 几何字段绑定
接入 E2 的 normal_force/slip guard 至少要落实:过滤指定指尖/目标物体、统一受力侧、确定法向/作用点、处理多个 contact、定义时间窗口和空样本语义、保留有效性。空结果可能表示未采样、无接触或该类别没有 contact,不应无条件变成一条“可靠零力”观测。过期数据即便力超过阈值,也不满足 E2 的新鲜度合同。
这些是原生数据到任务观测的明确映射;本轮没有新建跨引擎传感框架,也没有给 DexLab 的 Drake Issue #117 补记运行验收。源码阅读版本、候选 wheel 和已验收实验版本继续分开。
6. 阅读练习与答案#
point 的 normal 为 B→A,结果 force 是 B 所受,直接
normal·force为何通常是负?hydro
F_Ac_W与 pointcontact_force()可以直接用相同符号求和吗?10 N 的离散报告力每隔 0.1 ms 记录一行,Plant h=1 ms;可否每行乘 1 ms 求冲量?
创建 Context 后看到空 contact results,是否足够证明 sphere 与地面没有穿透?
为什么左、右指的接触合力为零不表示没夹紧?
hydro 只有总 wrench,是否足够构造唯一的局部 slip_speed?
将 C 点力矩换到 O 点,Shift 应传
p_WC−p_WO还是相反?
答案
压缩力将 B 推向 A→B,而 normal 指 B→A;按本约定 fn=−normal·force。
不可。前者作用于 A,后者作用于 B;先统一对象、表达系和作用点。
不可,会重复积分同一物理更新的 sampled 力。先按更新身份去重,再乘对应 h。
不够。默认 sampled 输出首次步进前为空;也须检查几何与采样状态。
两个大而相反的内夹力可抵消,净合力不能刻画两侧压紧水平。
不够。需要指定局部位置、相对速度及统计方法;总 wrench 不唯一决定分布。
传从旧点 C 指向新点 O 的
p_WO−p_WC,对应 τO=τC+(pWC−pWO)×f。
本专题的来源、静态核验和未运行范围见E3 验证记录。下一项建议 E4:传感器、渲染和可视化,在相同坐标/采样合同上继续展开。