深度解析:跨求解器的 Proxy 与 ADMM 多物理耦合)
Newton 耦合求解器框架newton.solvers.experimental.coupled深度解析跨求解器的 Proxy 与 ADMM 多物理耦合【免费下载链接】newtonAn open-source, GPU-accelerated physics simulation engine built upon NVIDIA Warp, specifically targeting roboticists and simulation researchers.项目地址: https://gitcode.com/GitHub_Trending/newton9/newton本文以newton.solvers.experimental实验性命名空间为主体系统讲解 Newton 耦合求解器框架的核心 APIModelView、CouplingInterface、SolverCoupled、SolverCoupledProxy、SolverCoupledADMM并结合仓库源码剖析共享 Model、入口视图所有权、Proxy 滞后迭代与 ADMM 对称约束两种耦合路径的调用机制帮助读者掌握刚体求解器 VBD/XPBD/MPM 软体求解器混合场景的构建与调参方法。1. 为什么需要耦合求解器一个 Model多个后端Newton 的定位是构建在 NVIDIA Warp 之上的 GPU 物理引擎其稳定求解器SolverMuJoCo、SolverKamino、SolverVBD、SolverXPBD、SolverImplicitMPM、SolverStyle3D、SolverFeatherstone、SolverSemiImplicit见 newton/solvers.py 与 newton/_src/solvers/init.py 的惰性导入表_LAZY_IMPORTS各自擅长不同材料模型。而真实场景经常把不同求解器各自最擅长的部分拼在一起MuJoCo/Kamino 驱动的刚性机构、VBD 布料、XPBD 颗粒与 MPM 材料的交互或者用 ADMM 约束连接的刚体-粒子系统。耦合框架让一个仿真步可以拆给多个求解器后端执行同时这些后端通过一个共享的newton.Model交换力、位姿与约束信息。这正是 newton/_src/solvers/coupled/ 目录下 9 个模块所实现的内容。该框架刻意暴露为实验性命名空间而非newton.solvers上的扁平符号导入方式必须显式写明from newton.solvers import SolverMuJoCo, SolverVBD from newton.solvers.experimental.coupled import ( SolverCoupledADMM, SolverCoupled, SolverCoupledProxy, )从 newton/solvers.py 的源码可以看到experimental与experimental.coupled是通过_LazyCoupledModule惰性加载的模块对象只有在真正访问newton.solvers.experimental.coupled.SolverCoupledProxy时才导入newton._src.solvers.coupled从而不拖累常规求解器的导入路径。这也说明该 API 属于实验性质接口可能变化适合受控实验与求解器集成工作。框架的五个核心类型newton/_src/solvers/coupled/init.py类型职责ModelView共享Model上的视图本地覆盖层copy-on-writeCouplingInterface需要自定义耦合行为的求解器实现的钩子协议MixinSolverCoupled共享基类模型分区、状态分发、入口步进、结果对齐SolverCoupledProxy滞后lagged/交错staggered代理耦合包装器SolverCoupledADMM面向模型派生关节、附件与接触行的定迭代 ADMM 耦合包装器完整的概念文档见 docs/concepts/coupling.rst本文在其基础上补充源码级证据。2. 共享 Model、入口视图与所有权ModelView 的实现机制耦合仿真从单个newton.Model出发但每个子求解器拿到的不是裸 Model而是一个ModelView。其设计目标是子求解器看到相同的模型拓扑但只拥有分配给本入口的刚体、粒子、关节或形状。ModelView的实现newton/_src/solvers/coupled/model_view.py有三个要点读穿透read-through委托__getattr__中所有未被视图覆盖的属性都回落到父 Modelgetattr(parent, name)因此可以像普通Model一样把视图传给SolverFoo(modelview)构造子求解器。写时覆盖 类型校验__setattr__只允许覆盖父 Model 存在的属性并用_types_compatible()校验wp.array的 dtype/ndim/device、np.ndarray的 dtype/ndim防止视图悄悄改变数组布局。copy-on-write写时复制视图提供一族修改器方法第一次修改某数组时才克隆父数组_cow_array()父 Model 永不被改动。文档中的原话是ModelViewapplies view-local changes with copy-on-write semantics so the coupler can hide, immobilize, or rescale endpoints without changing the parent model.ModelView提供的关键修改器每个方法都只写视图本地的克隆数组底层是wp.kernel批量更新disable_body_dynamics(body_indices)置零选定刚体的body_inv_mass/body_inv_inertia逆动力学属性把非拥有刚体变成不动端scale_body_mass(body_indices, factor)按factor缩放body_mass、body_inertia同时反缩放逆质量与逆惯性张量。源码注释明确说明用途小于 1 让代理刚体更轻耦合更软大于 1 更重mark_proxy_bodies/mark_proxy_particles在视图本地body_flags/particle_flags上 OR 进BodyFlags.PROXY/ParticleFlags.PROXY位父模型不变disable_particles、zero_particle_mass、scale_particle_mass、set_particle_mass粒子侧对应操作其中scale_particle_mass的文档注明Used by the ADMM coupler to inject the proximal term as a mass rescalingdisable_joints置位joint_enabledFalse并把ROD类型关节替换为D6set_body_inertial_properties/add_body_lumped_inertia/add_particle_lumped_mass设置完整惯性张量或叠加集中质量/各向同性惯性。ModelView.state()会用视图本地的数量重跑Model.state()通过_TemporaryStateArrayOverrides上下文临时裁剪particle_q、body_q等源数组因此子求解器在视图上创建的State也只覆盖本视图拥有的实体。入口Entry与所有权声明一个SolverCoupled.Entry描述一个子求解器及其拥有对象。构造阶段的流程是为每个入口创建 Model 视图 → 在视图上禁用/缩放非拥有端点 → 调用入口的solver(view)工厂构造子求解器 → 保留每个入口的输入/输出State。一个典型入口声明来自官方概念文档entry SolverCoupled.Entry( namesoft, solverlambda view: SolverVBD(modelview, iterations20, rigid_compliant_almTrue), bodiessoft_body_ids, particlescloth_particle_ids, shapescloth_shape_ids, substeps2, )substeps允许单个求解器以更小的时间间隔推进。顶层步执行后只有各入口拥有的输出会被对齐回调用者的共享state_out防止两个子求解器互相覆盖同一个刚体/粒子除非显式耦合算法负责仲裁。共享基类SolverCoupled还负责按入口的 substep 调度、把State与Control中的公开力输入复制到入口本地状态、入口本地的碰撞可见性与形状所有权、给有私有历史缓冲的求解器发输入状态通知、以及从公开模型质量/惯性数组回退估计有效质量。3. CouplingInterface耦合钩子协议一些求解器把关键状态放在公开State数组之外或能比通用动量回退更精确地报告接口力。这些求解器通过继承CouplingInterfacenewton/_src/solvers/coupled/interface.py提供钩子。钩子都是带默认实现的普通方法只需重写需要自定义的部分无法支持某钩子的求解器应重写为抛NotImplementedError而不是悄悄走无效路径。钩子契约源码模块 docstring 中给出的完整签名清单def coupling_eval_effective_mass(endpoint_kind, endpoint_index, endpoint_local_pos, out) - None: ... def coupling_eval_effective_mass_block( endpoint_kind, endpoint_index, endpoint_local_pos, out_mass, out_inertiaNone ) - None: ... def coupling_notify_input_state_update(state, flags, *, iteration_restartFalse, dt0.0) - None: ... def coupling_supports_inertial_property_refresh() - bool: ... def coupling_supports_full_surface_soft_contacts() - bool: ... def coupling_rewind_proxy_body( body_local_to_proxy_global, state, coupling_forces, body_gravity_acceleration, dt ) - None: ... def coupling_rewind_proxy_particle( particle_local_to_proxy_global, state, coupling_forces, particle_gravity_acceleration, dt ) - None: ... def coupling_harvest_proxy_wrenches( body_local_to_proxy_global, out_body_f, *, body_qd_before, state, state_out, contacts, dt, ) - None: ... def coupling_harvest_proxy_particle_forces( particle_local_to_proxy_global, out_particle_f, *, particle_qd_before, state, state_out, contacts, dt, ) - None: ... def coupling_prepare_proxy_contacts(state, contacts, *, contacts_freshly_detectedFalse): ...几个实现细节值得注意端点数组采用 SoA 布局endpoint_kind存EndpointKind.BODY(0)/PARTICLE(1)endpoint_index存求解器视图内的本地刚体/粒子 idendpoint_local_pos存刚体坐标系下的端点位置粒子为 0。默认有效质量估计coupling_eval_effective_mass的默认实现会检查模型上body_inv_mass/particle_inv_mass是否存在分四种分支启动不同的 Warp kernel两者都没有时输出 0_coupling_zero_mass_kernel。coupling_eval_effective_mass_block的惯性回退有一个约束对每个轴刚体有效惯性不得小于模型惯性kernel 中inertia * max(out_mass/mass, 1.0)。重力加速度钩子coupling_eval_gravity_acceleration默认按gravity[body_world[i]]逐端点取值。代理与 ADMM 耦合器会把这些加速度数组显式传给 rewind/harvest 钩子使做了重力缩放或补偿的求解器不会重复施加重力。默认 harvest 的动量回退coupling_harvest_proxy_wrenches默认实现要求state_out.body_qd存在且dt 0用harvest_proxy_momentum_forces_kernel从求解前后的动量差估计反馈力粒子侧默认只处理ParticleFlags.ACTIVE的粒子。文档特别强调这是回退方案接触密集或求解器私有交互的场景应优先实现自定义 harvest 钩子。默认代理接触过滤coupling_prepare_proxy_contacts用filter_proxy_rigid_contacts_kernel剔除代理-静态、代理-代理刚体接触——因为通用动量 harvest 把代理反馈当作目标端动量变化若再把两个虚拟对象之间的约束回喂源端就会造成双计。另外两点边界力注入本身不是钩子耦合器直接写公开的state.body_f、state.particle_f、control.joint_f缓冲区再走正常求解器步进虚拟/近端质量修改则是改ModelView并走正常notify_model_changed()路径刷新私有缓存。4. Proxy 耦合滞后代理与参数详解Proxy 耦合把由一个求解器拥有的端点表示为另一个求解器里的代理端点源求解器拥有真实对象目标求解器收到带缩放虚拟惯性的代理刚体/代理粒子针对代理求解自己的局部问题然后在后续 pass 或迭代中把反馈送回源端。这对子步内天然单向、但可通过重复滞后迭代收敛的耦合算法非常合适例如刚体作为代理碰撞体进入软体求解、XPBD 粒子驱动 MPM 迁移粒子、VBD 把接触力回传给刚体源。SolverCoupledProxy 配置solver SolverCoupledProxy( model, entries[rigid_entry, soft_entry], couplingSolverCoupledProxy.Config( proxies[ SolverCoupledProxy.Proxy( sourcerigid, # 源入口名 destinationsoft, # 目标入口名 bodiesrobot_body_ids, # 源端点 proxy_bodiesrobot_proxy_body_ids, # 目标端代理端点 particles(), proxy_particles(), mass_scale0.25, # 目标视图中代理质量/惯性缩放 modelagged, # 或 staggered proxy_relaxation0.5, # 反馈松弛系数 ) ], iterations4, ), )参数语义依据官方概念文档 ModelView源码source/destination命名入口bodies、particles是源端点proxy_bodies、proxy_particles是目标端点某代理列表为None时复用源索引mass_scale在目标视图中缩放代理刚体的质量/惯性与代理粒子质量底层走ModelView.scale_body_mass/scale_particle_massproxy_relaxation在每次目标求解后把 harvest 的反馈与上一轮滞后反馈缓冲做混合小于 1 为欠松弛更稳、等于 1 保持 harvest 反馈不变、大于 1 为过松弛更快但更脆代理局部碰撞检测是可选的代理可以提供接收目标ModelView的collision_pipeline工厂若返回 pipeline耦合器持有持久接触缓冲并按collide_interval刷新内层代理迭代复用该结果返回None或未提供工厂时目标求解使用外层step()传入的接触。两种调度模式LAGGED把源端开始时位姿 结束时速度同步到目标代理回卷目标代理速度中已被施加过的反馈、公开力输入与重力然后步进目标端。这是最常用的松弛不动点模式STAGGERED把源端结束时位姿与速度直接同步到目标端并跳过通用滞后回卷适用于调度本身已给目标端提供了当前源端状态的场景。目标步进后耦合器执行 harvest若目标求解器实现了 body/particle harvest 钩子钩子可报告接触原生力或迁移冲量否则使用共享动量回退估计。代理循环当前最多支持两个求解器入口在此限制内刚体与粒子映射按(source, destination)分组一轮代理迭代内对每对求解器执行一次源端步进 一次目标端步进因此单条代理声明可以同时携带刚体与粒子映射。实际示例刚体-VBD 耦合布料仓库示例 newton/examples/multiphysics/example_mujoco_vbd_coupled_solver.py 演示了完整链路自由刚体箱 铰接摆链由SolverMuJoCo或SolverKamino驱动与 VBD 布料和软体交互形变端的接触力回传使刚体反弹并落定。示例要点from newton.solvers.experimental.coupled import SolverCoupledProxy from newton.solvers import SolverKamino, SolverMuJoCo, SolverVBD # --rigid-solver mujoco|kamino 选择刚体后端 # 直接通过 SolverCoupledProxy 构建 rigid/VBD proxy 耦合运行方式python -m newton.examples mujoco_vbd_coupled_solver python -m newton.examples mujoco_vbd_coupled_solver --solver vbd # 单一 VBD 参考基线同目录还有一组耦合示例example_mujoco_mpm_coupled_solver.py、example_xpbd_vbd_coupled_solver.py、example_vbd_mpm_coupled_solver.py 覆盖 VBD↔MPM、XPBD↔VBD 等组合ADMM 路径见 example_admm_contact_solver.py 与 example_mujoco_vbd_admm_solver.py。5. ADMM 耦合对称约束路径ADMM 耦合是对称路径不在其他求解器里放虚拟代理而是在不同入口拥有的端点之间构造接口行。每次迭代恢复入口状态 → 配置了 proximal 速度目标时施加 → 让子求解器推进 → 解局部接口行 → 更新对偶变量 → 把等值反号的耦合力 splat 回端点力缓冲区。与 proxy 相比ADMM 对子求解器侵入更小入口不需要表示代理体、过滤代理接触或 harvest 代理反馈代价是耦合器必须显式实现每种受支持的接口行且瞬态接触与刚性附件通常需要每步多轮耦合迭代。支持的行来源跨求解器模型关节仅当连接的两个刚体分属不同入口、且关节本身不被任一子求解器拥有时由耦合器接管避免同一约束被解两次。当前通用路径支持BALL、FIXED、REVOLUTE球关节生成平移锚点重合行固定关节附加角度行旋转关节保持铰链轴并可根据模型关节摩擦附加干摩擦行。PRISMATIC、距离关节与 D6 行尚不在实验性 API 内。body-particle 附件一个端点是粒子、无法用模型关节表示的接口。SolverCoupledADMM.add_body_particle_attachment()会在coupling:body_particle_attachment自定义属性下登记 body id、particle id、体局部点、刚度、阻尼与启用状态导入器也可以直接写同名的自定义属性。端点未拥有或同入口拥有的行被忽略只有跨求解器附件由 ADMM 耦合。接触行由Config.contact_pairs中的ContactPair显式开启SolverCoupledADMM.auto_detect_contact_pairs(entries)可为所有入口两两组合生成完整列表。启用后耦合器持有私有检测数据按求解器所有权建行粒子条目与其他入口刚体上形状之间的粒子-形状行、跨入口形状对的刚体-刚体行、跨入口粒子集经私有 hash-grid 流产生的粒子-粒子行。摩擦系数在建行时从shape_material_mu、Model.particle_mu等模型材料属性读取不是ContactPair字段。接触行使用各向同性 Coulomb 最大耗散投影不直接解锥互补。SolverCoupledADMM.Config 参数源码 newton/_src/solvers/coupled/solver_coupled_admm.py 中Config默认值节选含单位参数默认值含义iterations5每步的 ADMM 迭代次数固定值CUDA Graph 捕获友好rho1.0接口行的惩罚权重gamma0.0近端质量缩放/速度权重非负baumgarte0.0附件/接触行的位置误差稳定化比例非负joint_stiffness/joint_damping1.0e4 / 0.0平移关节附件的行刚度 [N/m] / 阻尼 [N·s/m]joint_angular_stiffness/joint_angular_damping1.0e4 / 0.0角度附件fixed/revolute行刚度 [N·m/rad] / 阻尼 [N·m·s/rad]joint_proximal_bodiesTrue跨求解器关节的相邻刚体在各子视图中保持动态本地惯性代理joint_proximal_mass_scale1.0安装关节代理惯性前对源有效质量的乘子rigid_contact_matching-刚体接触帧间匹配disabled/latest/stickycontact_matching_pos_threshold/contact_matching_normal_dot_thresholdNone接触匹配的世界坐标距离阈值 [m] 与法线点积下限None 用CollisionPipeline默认contact_matching_force_scale-匹配接触双变量热启动的力缩放0 关闭双变量热启动contact_pairs[]要启用的接触对空列表即禁用 ADMM 管理的接触ADMM 接触缓冲是定容设备数组持久接触通过稳定的接触键跨步热启动局部变量与对偶变量粒子-粒子流是接触式、hash-grid 基础的但属于 ADMM 耦合器内部实现不应作为公开接触流使用。当gamma 0时耦合器会在每个入口的ModelView中缩放拥有的刚体/粒子质量利用上文ModelView.scale_body_mass/scale_particle_mass请子求解器刷新模型派生缓存并把入口输入速度向上一轮 ADMM 迭代移动端点有效质量有求解器钩子就用钩子否则用模型回退。这样既兼容能给出机构质量估计的求解器如 MuJoCo Warp 的 GPU 有效质量钩子也让更简单的求解器可以参与。6. 求解器特有的钩子行为各后端只在公开模型/状态行为不足时依赖自定义钩子VBD使用代理接触准备、body-proxy harvest 与输入状态通知。通知钩子让 VBD 在代理位姿同步或 ADMM 迭代重启时保持私有的上一帧刚体状态对齐harvest 路径把最终的刚体-刚体与刚体-粒子接触力直接缩放到代理刚体上而不是依赖聚合动量差。VBD 还支持代理关节SolverCoupledProxy会在目标视图中保持已配置的 fixed/prismatic/revolute 关节或其proxy_joints别名启用使约束继续在代理刚体之间起作用对单自由度驱动耦合器会把源端 target 重映射到目标本地索引并在每次目标求解前复制joint_target_q、joint_target_qd。Implicit MPM支持代理刚体/代理粒子的 rewind/harvest 钩子。transfer-active 代理粒子可参与 P2G/G2P 动量迁移同时被排除在材料体积、应力、应变与本构更新之外通过 collider-particle id 注册的形变碰撞粒子走碰撞冲量收集而非材料迁移。XPBD粒子接触 kernel 理解代理粒子与代理刚体拥有粒子可与目标代理粒子碰撞但代理-代理、代理-静态、代理粒子对代理刚体的接触会被过滤避免目标求解在两个代理端点之间产生反馈。MuJoCo提供来自 MuJoCo Warp 数据的 GPU 有效质量钩子使代理虚拟惯性与 ADMM 端点权重使用机构质量估计而非裸刚体质量。7. Proxy 还是 ADMM选型与当前限制选 Proxy 当一个求解器可以把另一个求解器的端点合理地当作障碍、迁移参与者或虚拟体来对待一个子步。它对碰撞体式交互更好调参可复用目标求解器的接触机制并且是目前支持 MPM transfer-active 代理粒子与形变碰撞粒子的路径。选 ADMM 当接口应当表示为入口之间的对称约束或摩擦接触跨求解器关节、body-particle 附件、需要等值反号力的接触行。它更结构化但调参更多、受支持的行类型更窄。两者共享同一套基础概念Model 视图、所有权、入口本地状态、力缓冲注入、输入状态通知与有效质量钩子。同一场景往往两种建式都可以数值行为却不同Proxy 类似针对求解器特定动力学的松弛不动点迭代ADMM 类似跨入口求解器与接口行的定迭代约束优化分解。当前实验性限制写作使用时务必留意Proxy 稳定性对调参敏感虚拟惯性缩放、接触刚度、求解器迭代数、lagged/staggered 调度都会显著影响阻尼与收敛通用动量 harvest 只是回退求解器私有的接触模式应尽可能暴露自定义 harvest 钩子ADMM 接触检测是内部的不把调用方的任意Contacts行作为公开接口流ADMM 关节支持仅限 ball/fixed/revolute 行粒子-粒子 ADMM 接触用私有流无自定义钩子时有效质量加权回退到简单的模型质量/惯性USD 所有权声明、自动耦合求解器构建与高层调参指南尚不属于实验性公开 API全表面边/面刚-软接触目前仅SolverVBD消费入口级接触过滤会为其丢弃其他子求解器的这类记录且仅当该入口拥有记录引用的所有角点时才保留给 VBD跨两个入口的记录会被双方丢弃代理粒子完全不支持。官方建议把耦合求解器当作面向受控实验与求解器集成工作的进阶特性在新示例中优先配合聚焦的回归测试与显式的场景调参使用。8. 小结与延伸阅读newton.solvers.experimental.coupled提供了一套完整的一个共享 Model N 个求解器视图的多物理耦合基建ModelView用 copy-on-write 实现所有权隔离CouplingInterface用带默认实现的标准钩子吸收求解器差异SolverCoupledProxy与SolverCoupledADMM分别覆盖松弛不动点与定迭代 ADMM 两条收敛路径。理解这三层之后newton/examples/multiphysics/ 下 rigid-soft、ADMM、VBD↔MPM、XPBD↔VBD 各示例都可以按同一套模型阅读入口声明 → 视图修改 → 代理/接触行声明 → 迭代调参。延伸阅读docs/concepts/coupling.rst官方概念文档、docs/solvers/index.rst求解器选型指南、newton/_src/solvers/coupled/ 源码interface.py钩子契约、solver_coupled_admm.py中Config的完整 docstring。【免费下载链接】newtonAn open-source, GPU-accelerated physics simulation engine built upon NVIDIA Warp, specifically targeting roboticists and simulation researchers.项目地址: https://gitcode.com/GitHub_Trending/newton9/newton创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考