扩展 Newton 求解器#
本页面向为 Isaac Lab 添加 Newton 求解器或构建自定义耦合求解器的贡献者,介绍 NewtonManager 的扩展约定:管理器负责哪些内容、钩子何时运行,以及子类必须提供什么。
如果只需选择和配置已有求解器,请使用面向使用者的页面: 后端与预设 介绍后端和预设选择, 求解器调参指南 介绍随附求解器, 耦合求解器 介绍耦合方式的选择。
何时需要求解器管理器#
每个 Newton 求解器都通过 NewtonManager 子类提供。以下情况需要编写新管理器:
Newton 求解器尚无 Isaac Lab 管理器;
求解器需要自己的接触分配、构建器属性或重置处理;
多个求解器必须推进同一共享模型,且子步顺序属于算法的一部分。
如果现有求解器能够推进整个模型,或场景可划分为命名求解器条目,就不必新建管理器。 CouplerProxyCfg 和 CouplerAdmmCfg 已支持这种划分, NewtonCouplerManager 将它们解析为共享模型上的条目视图。刚体与可变形物体混合场景应优先使用此路径。只有共享接触检测、但各求解器以不同方式使用接触,或求解器间需要自定义力、冲量或状态传递时,才编写耦合管理器。
职责与边界#
NewtonManager 是类级单例:所有状态保存在基类上,没有实例方法,因此每个仿真中恰好只有一个管理器子类处于启用状态。
负责方 |
职责 |
|---|---|
仿真上下文 |
根据 |
|
构建器、最终 |
管理器子类 |
构造求解器,以及求解器自身的内部状态、接触缓冲区或构建器属性。 |
耦合器条目 |
当前管理器为耦合器时,共享模型中互不重叠的一部分。 |
任务配置 |
|
NewtonCfg 将 solver_cfg.class_type 复制到自身的 class_type ,因此任务配置从不直接指定管理器。
生命周期#
公共入口按以下顺序运行。子类钩子为私有方法,由基类调用。
公共调用 |
执行内容 |
子类钩子 |
|---|---|---|
保存仿真上下文,从仿真配置读取重力,并创建场景数据后端。 |
无 |
|
|
通过当前管理器的 |
|
完成模型构建,然后分配状态和重置掩码。 |
|
|
构建求解器,检查是否已赋值,再分配接触。 |
|
|
硬重置对重新完成构建的模型再次运行 |
|
|
执行一次执行器处理和 |
|
|
刷新运动学,再将刚体、线缆和粒子状态写入 Fabric 以供渲染。 |
|
|
释放求解器、模型和全部类级状态。 |
|
_build_solver() 在模型完成构建后运行,因此可根据实际模型确定求解器资源大小。 _register_builder_attributes() 在添加粒子和 finalize() 之前运行,是唯一可注册 Newton 自定义属性的位置。
step() 根据 handles_decimation() 选择两条路径之一。所有执行器都使用支持图捕获的 Newton 快速路径时,执行器与子步在同一个图中运行, step() 执行完整控制降采样循环,因此每次调用运行 decimation x num_substeps 次 _step_solver() 。否则,执行器即时运行,只有子步通过 _simulate_physics_only() 捕获为图,环境通过重复调用 step() 实现控制降采样。两条路径都通过同一子步循环调用 _step_solver() 。
图捕获可能在多个时机发生。通常由 initialize_solver() 捕获;启用支持图捕获的快速路径时, set_decimation() 在控制降采样倍数确定后捕获,RTX 路径则延迟到首次 step() 。所有路径都会检查 _supports_cuda_graph_capture() ,非 RTX 路径还检查 _requires_initial_reset_before_graph_capture() 。
警告
设置 _use_single_state = False 时,基类管理器在每个子步后交换 NewtonManager._state_0 和 NewtonManager._state_1 ;子步数为奇数时,最后一个子步改为拷贝。不要在 _build_solver() 中缓存 State 引用;每次使用时,通过类属性读取当前状态。
扩展约定#
子类必须实现 _build_solver() ,并为 NewtonManager 本身而非 cls 上的四个槽位赋值。如果 _solver 仍未设置, initialize_solver() 会抛出 RuntimeError 。其他三个槽位不验证,保留默认值,因此遗漏它们的子类会使用双缓冲状态运行,没有碰撞流程,也不接收可视化器施加的力。
槽位 |
含义 |
|---|---|
|
构造的 Newton |
|
求解器在单个 |
|
基类管理器应负责 Newton 碰撞流程时为 |
|
求解器使用 |
from newton import Model
from newton.solvers import SolverMySolver
from isaaclab.utils import configclass
from isaaclab_newton.physics import NewtonManager, NewtonSolverCfg
@configclass
class MySolverCfg(NewtonSolverCfg):
class_type: type[NewtonManager] | str = "{DIR}.my_solver_manager:NewtonMySolverManager"
solver_type: str = "my_solver"
iterations: int = 16
class NewtonMySolverManager(NewtonManager):
@classmethod
def _build_solver(cls, model: Model, solver_cfg: MySolverCfg) -> None:
NewtonManager._solver = SolverMySolver(model, iterations=solver_cfg.iterations)
NewtonManager._use_single_state = False
NewtonManager._needs_collision_pipeline = True
NewtonManager._supports_rigid_body_force_input = True
其他方法仅在求解器需要时覆盖:
_create_solver():构造求解器而不改变管理器状态,使耦合器能够嵌套使用该求解器。_initialize_contacts():分配自定义接触缓冲区。_step_solver(state_0, state_1, control, contacts, substep_dt):修改单个子步,同时保留基础仿真循环。_simulate_physics_only():在子步循环前后添加逐步工作。_reset_solver_internals():为被重置的世界清除求解器自身状态。_register_builder_attributes():在构建器上注册 Newton 自定义粒子、形状或刚体属性。_prepare_builder_for_finalize():在finalize()前规范化导入或复制的构建器数据。_supports_cuda_graph_capture():返回False,回退到即时执行。_requires_initial_reset_before_graph_capture():将无界面图捕获延迟到重置后的第一步。_solver_specific_clear():释放子类负责的类级状态。_check_solver_status()和_log_solver_debug():在步进后运行。
NewtonMPMManager 覆盖了两个构建器钩子。
配置不受支持时,应在 _build_solver() 中抛出异常,而不是静默降级。管理器应命名为 Newton<Solver>Manager 。
耦合路径#
四种架构的区别在于由谁驱动子步循环:
路径 |
结构 |
|---|---|
独立求解器 |
一个管理器子类、一个求解器、一个模型。基类负责子步循环。 |
代理耦合 |
|
ADMM 耦合 |
|
自定义共享模型管理器 |
子类自行构造多个子求解器,并覆盖 |
自定义共享模型管理器绕过条目归属解析,因此不能复用耦合器的选择器或验证。代理与 ADMM 的取舍见 耦合求解器 。