可变形物体#

可变形物体是在仿真中形状会发生变化的资产。与刚体不同,它没有刚性的根坐标系;其状态由仿真网格中每个节点的位置和速度组成。

Isaac Lab 按仿真几何体的维度,将可变形物体分为三类:

属性

体积

表面

线缆

模拟对象

软质实体:橡胶块、泰迪熊、器官

布料、薄片、膜

绳索、软管、电线、线束

仿真几何体

四面体网格( UsdGeom.TetMesh )

三角网格( UsdGeom.Mesh )

开放曲线( UsdGeom.BasisCurves ),以胶囊体线段模拟

资产类

DeformableObject

DeformableObject

CableObject

运行时状态

节点位置和速度

节点位置和速度

各线段的位姿和速度

体积和表面可变形物体使用同一资产类和编写方式,区别仅在于所分配的物理材质。线缆使用独立的资产类,具有自己的生成器、材质和状态布局,详见 线缆 。

流体和颗粒介质等基于粒子的材料不属于这里所说的可变形物体。它们使用独立的资产和求解器;参见 隐式 MPM 。

备注

这三类物体都仍在持续开发。在 Newton 上,可变形物体与刚体物体和关节体一起实现在 isaaclab_newton.assets 中。线缆支持尤其处于实验阶段,其生成器配置、资产类和材质默认值仍可能变化。

后端支持情况#

类型

PhysX

Newton

OvPhysX

体积

Yes

支持,仅限 VBD 求解器

实验性,仅限 CUDA 设备

表面

Yes

支持,仅限 VBD 求解器

实验性,仅限 CUDA 设备

线缆

No

支持,仅限 VBD 求解器

No

在 Newton 上,各类可变形物体都由 VBD 求解器模拟,因此包含它们的场景必须选择使用 VBD 求解器的物理配置。求解器参数、在同一场景中运行刚性机器人与可变形物体的方法,以及调参流程,见 VBD 求解器 和 耦合求解器 。

OvPhysX 的可变形体还存在节点数量和启动开销方面的限制,详见 OvPhysX 后端 。

体积和表面可变形物体#

编写资产#

可变形物体使用网格生成器,并增加两个字段:

  • deformable_props :后端特有的 *DeformableBodyPropertiesCfg 。设置此字段才会将网格变为可变形物体。

  • physics_material :可变形材质配置,其类型决定使用体积还是表面模型。

将生成器放入 DeformableObjectCfg ,即可创建运行时资产。

import isaaclab.sim as sim_utils
from isaaclab.assets import DeformableObjectCfg
from isaaclab_physx.sim.schemas import PhysxDeformableBodyPropertiesCfg
from isaaclab_physx.sim.spawners.materials import PhysxDeformableBodyMaterialCfg

cfg = DeformableObjectCfg(
    prim_path="/World/env_.*/Cube",
    spawn=sim_utils.MeshCuboidCfg(
        size=(0.2, 0.2, 0.2),
        deformable_props=PhysxDeformableBodyPropertiesCfg(),
        physics_material=PhysxDeformableBodyMaterialCfg(
            youngs_modulus=1.0e5, poissons_ratio=0.4, density=1000.0
        ),
    ),
)

在 Newton 上,同一物体需要替换这两个后端配置:

import isaaclab.sim as sim_utils
from isaaclab.assets import DeformableObjectCfg
from isaaclab_newton.sim.schemas import NewtonDeformableBodyPropertiesCfg
from isaaclab_newton.sim.spawners.materials import NewtonDeformableBodyMaterialCfg

cfg = DeformableObjectCfg(
    prim_path="/World/env_.*/Cube",
    spawn=sim_utils.MeshCuboidCfg(
        size=(0.2, 0.2, 0.2),
        deformable_props=NewtonDeformableBodyPropertiesCfg(),
        physics_material=NewtonDeformableBodyMaterialCfg(
            k_mu=3.5714e4, k_lambda=1.4286e5, density=1000.0
        ),
    ),
)

这两个后端采用不同的弹性参数:PhysX 使用 youngs_modulus 和 poissons_ratio ,Newton 使用拉梅参数 k_mu 和 k_lambda 。上述值表示同一种材料,通过 k_mu = E / (2 * (1 + nu)) 和 k_lambda = E * nu / ((1 + nu) * (1 - 2 * nu)) 转换。

表面可变形物体采用同样的方式编写,但使用二维网格生成器和表面材质:

from isaaclab_newton.sim.spawners.materials import NewtonSurfaceDeformableBodyMaterialCfg

cloth = DeformableObjectCfg(
    prim_path="{ENV_REGEX_NS}/Cloth",
    spawn=sim_utils.MeshRectangleCfg(
        size=(0.2, 0.2),
        edge_refinement=8,
        deformable_props=NewtonDeformableBodyPropertiesCfg(),
        visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.95, 0.85, 0.1)),
        physics_material=NewtonSurfaceDeformableBodyMaterialCfg(
            density=1.0, particle_radius=0.002, tri_ke=5e2, tri_ka=5e2, edge_ke=0.5
        ),
    ),
    init_state=DeformableObjectCfg.InitialStateCfg(pos=(0.4, 0.0, 0.1)),
)

上述材质值来自 Isaac-Lift-Cloth-Franka 调整后的配置,而非默认值。各参数的作用和默认值见 VBD 求解器 ,其中也介绍了布料自接触。自接触默认关闭,因此启用前布料可以穿过自身。

edge_refinement 设置这两类物体的仿真分辨率:最大表面边长为包围盒对角线长度除以该值,体积可变形物体也将其作为四面体划分的目标。默认值为 4.0 ,且必须至少为 1.0 。接近 1.0 的值会显著减慢四面体划分。

网格生成器会拒绝无法工作的组合: deformable_props 与 rigid_props 或 mass_props 同时设置,或配合非可变形材质的 physics_material ,都会在生成时抛出 ValueError 。

从 USD 加载#

可变形物体也可以来自预先编写的资产。将 deformable_props 和 physics_material 传给 UsdFileCfg ;生成器会在加载的 prim 上应用可变形模式,如果 prim 已有该模式,则原地修改。

cfg_usd = sim_utils.UsdFileCfg(
    usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Objects/Teddy_Bear/teddy_bear.usd",
    deformable_props=PhysxDeformableBodyPropertiesCfg(),
    physics_material=PhysxDeformableBodyMaterialCfg(),
    scale=[0.05, 0.05, 0.05],
)

体积还是表面#

没有显式的类型字段,也没有独立的布料资产类。编写时,类型由材质配置决定:继承自 SurfaceDeformableBodyMaterialBaseCfg 的材质产生表面可变形物体,其他材质产生体积可变形物体。这决定写入的 USD 内容:体积模型使用 UsdGeom.TetMesh 仿真网格,表面模型使用可视网格的三角 UsdGeom.Mesh 副本。

初始化时,资产从舞台重新判断类型。PhysX 和 OvPhysX 读取绑定物理材质上应用的模式;无法确定时,再根据网格拓扑判断。Newton 只使用拓扑,将 prim 下的 UsdGeom.TetMesh 视为体积,将普通 UsdGeom.Mesh 视为表面。

因此,材质配置决定实际模型:将体积材质与布料形状的网格搭配,会生成经四面体划分的实体,而不是薄片。

四面体划分#

体积可变形物体需要四面体仿真网格。如果生成的 prim 尚未包含 UsdGeom.TetMesh ,Isaac Lab 会生成一个;各后端都需要可选的 tetrahedralization 依赖:

uv sync --inexact --extra tetrahedralization

# With the legacy installer.
./isaaclab.sh -i tetrahedralization

表面可变形物体无需该依赖;从 USD 加载、且可变形 prim 下已包含预先划分的 UsdGeom.TetMesh 的体积物体也不需要。

运行时状态#

可变形物体的状态定义在节点上,以仿真世界坐标系表示。下文的 N 为 max_sim_vertices_per_body 。

  • data.nodal_pos_w 和 data.nodal_vel_w :形状为 (num_instances, N) ,元素类型为 vec3f ,分别表示位置 [m] 和速度 [m/s]。

  • data.nodal_state_w :相同数据,形状为 (num_instances, N) ,元素类型为 vec6f 。

  • data.default_nodal_state_w :生成时的状态,用于重置。

  • data.root_pos_w 和 data.root_vel_w :形状为 (num_instances,) 。它们是 派生量,由仿真节点的平均值计算得到。不存在根方向。

通过带索引的设置方法写回状态。 transform_nodal_pos() 相对于当前节点均值应用位姿偏移,从而将生成状态缓冲区分配到各环境原点。

nodal_state = cube.data.default_nodal_state_w.torch[env_ids].clone()
nodal_state[..., :3] = cube.transform_nodal_pos(nodal_state[..., :3], pos, quat)
cube.write_nodal_state_to_sim_index(nodal_state, env_ids=env_ids)
cube.reset(env_ids=env_ids)

与其他资产一样, DeformableObject 可与 InteractiveScene 、 scene.get_state / scene.reset_to 和 reset_scene_to_default 事件项集成。

备注

不带后缀的写入方法( write_nodal_state_to_sim 等)已弃用,应使用 _to_sim_index 和 _to_sim_mask 变体。掩码变体支持 CUDA 图捕获。

线缆#

线缆是一维杆:单个开放的 UsdGeom.BasisCurves prim,带有 PhysicsCurvesDeformableSimAPI 模式,以一串通过线缆关节连接的胶囊体线段进行模拟。

编写线缆#

线缆由 CableCfg 和 CableMaterialCfg 配置。 positions 中相邻的点构成线段,每段生成直径为 thickness 的胶囊体,并通过线缆关节与相邻线段连接。 N 个控制点产生 N-1 个线段刚体和 N-2 个关节;根线段自由悬浮。

参数

描述

positions

线缆局部坐标系中的控制点 [m]。至少需要 三个 坐标值有限的点,且相邻点间距必须大于 1e-8 m。

physics_material

必需的 CableMaterialCfg ;见 线缆材质参数 。厚度也会写入曲线的 widths 属性,使可视半径与物理半径一致。

collision_props

可选的碰撞属性。省略时,线缆不发生碰撞;设置后(通常为 [UsdPhysicsCollisionCfg(collision_enabled=True)] ),线缆会与地面和其他线缆碰撞。见 线缆碰撞 。

visual_material

可选的 VisualMaterialCfg ,用于设置曲线外观。

visual_material_path

可视材质在线缆几何 prim 下的子路径,默认为 "material" 。

physics_material_path

物理材质在线缆几何 prim 下的子路径,默认为 "physics_material" 。

import isaaclab.sim as sim_utils
from isaaclab.assets import CableObject, CableObjectCfg

cable = CableObject(
    cfg=CableObjectCfg(
        prim_path="/World/Env_0/Cable",
        spawn=sim_utils.CableCfg(
            positions=[(index * 0.1, 0.0, 0.0) for index in range(10)],
            visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.7, 0.2, 0.2)),
            physics_material=sim_utils.CableMaterialCfg(
                thickness=0.03,
                density=1000.0,
                stretch_stiffness=1.0e9,
                bend_stiffness=1.0e6,
            ),
            collision_props=[sim_utils.UsdPhysicsCollisionCfg(collision_enabled=True)],
        ),
        init_state=CableObjectCfg.InitialStateCfg(pos=(0.0, 0.0, 0.5)),
    )
)

这会沿线缆局部 x 轴生成一条 0.9 m 长的红色直线缆:9 个胶囊体线段(每段长 0.1 m,直径 0.03 m),通过 8 个线缆关节连接。继承的 init_state 设置线缆根节点在各环境中的初始位姿。

线缆材质参数#

CableMaterialCfg 定义线缆的几何和刚度。编写时会验证所有值;非有限值或超出范围的值会在创建任何 prim 前抛出 ValueError 。

刚度字段是弹性模量,不是关节刚度。每个杆关节都有自己的离散化刚度,使用该关节的对偶静止长度 L = 0.5 * (L_parent + L_child) 计算,其中 L_parent 和 L_child 是它连接的两个线段的静止长度。

参数

描述

thickness

线缆完整厚度(直径)[m],必须有限且为正。以 radius = thickness / 2 用于胶囊体截面、弯曲截面二次矩和碰撞半径。默认 0.001 。

density

线缆密度 [kg/m^3],必须有限且为正。各线段质量由密度和胶囊体体积计算得到。默认 1000.0 。

stretch_stiffness

轴向(拉伸)弹性模量 E [Pa],必须有限且非负。转换为各关节的轴向刚度 E * A / L ,其中 A 是圆形截面积。值越高,伸长越小。默认 1.0e9 。

bend_stiffness

弯曲弹性模量 E [Pa],必须有限且非负。转换为各关节的弯曲刚度 E * I / L ,其中 I 是圆形截面的二次矩。 0.0 表示柔软的绳索;增大该值可模拟较硬的软管或电线。默认 1.0e6 。

shear_stiffness

横向剪切弹性模量 [Pa],必须有限且非负。可选:保留 None 时不写入该属性,求解器复用 stretch_stiffness 。默认 None 。

twist_stiffness

扭转弹性模量 [Pa],必须有限且非负。可选:保留 None 时不写入该属性,求解器复用弯曲 结构 刚度。默认 None 。

备注

线缆关节具有四种自由度:线性的拉伸和剪切,以及角向的弯曲和扭转。未设置 shear_stiffness 或 twist_stiffness 并不 表示线缆没有剪切或扭转阻力,而是由求解器回退到拉伸和弯曲值。显式设置 0.0 与不设置不同:前者会去除该阻力。

这两种回退并不对称。剪切复用拉伸模量,作用于同一截面积;扭转复用弯曲 结构 刚度 E * I / L ,而显式设置的 twist_stiffness 作用于极惯性矩 J = 2 * I 。因此,设置 twist_stiffness = bend_stiffness 会得到回退刚度的两倍,而不是相同值。

未提供阻尼配置。杆关节具有阻尼,但 Isaac Lab 编写的 USD 曲线材质模式中没有对应属性。

如果需要指定轴向 E * A 或弯曲 E * I ,可反解这些关系来确定模量; examples/cables.py 演示了如何根据目标刚度和线段几何计算。

线缆碰撞#

碰撞需通过 collision_props 显式启用。启用后,导入器采用 仅过滤相邻线段 的规则:直接连接的线段共享关节锚点,不过滤会产生抖动,因此将其过滤;其他所有线段对都发生碰撞。由此:

  • 线缆会与地面和其他线缆碰撞。

  • 同一 线缆的不相邻线段会碰撞,因此线缆回绕自身时可以通过自接触阻止继续运动。

省略 collision_props 时,线缆作为仅参与动力学的杆导入,不发生碰撞。

线缆运行时状态#

CableObject 提供各线段的世界状态,并与 InteractiveScene 、 scene.get_state / scene.reset_to 和 reset_scene_to_default 事件项集成。

  • cable.data.segment_pose_w :形状为 (num_instances, num_segments) ,元素类型为 wp.transformf ,位置 [m] 在前,四元数 (x, y, z, w) 在后。Torch 视图最后一维的长度为 7。

  • cable.data.segment_velocity_w :形状为 (num_instances, num_segments) ,元素类型为 wp.spatial_vectorf ,线速度 [m/s] 在前,角速度 [rad/s] 在后。Torch 视图最后一维的长度为 6。

  • cable.data.default_segment_pose_w 和 default_segment_velocity_w :生成时的状态。

通过索引或掩码设置方法写回各线段状态;掩码形式支持 CUDA 图捕获。

cable.write_segment_pose_to_sim_index(segment_pose=cable.data.default_segment_pose_w)
cable.write_segment_velocity_to_sim_index(segment_velocity=cable.data.default_segment_velocity_w)

写入会直接更新两个仿真状态中的最大坐标刚体状态,并将受影响的环境标记为需要重置求解器。

从 USD 加载线缆#

物理属性直接写在曲线上: spawn_cable() 应用 PhysicsCurvesDeformableSimAPI 模式并绑定可变形曲线材质,曲线随后以原生方式导入。拓扑来自曲线自身的 points 和 curveVertexCounts ,无需自定义边属性。

因此,也可以通过 UsdFileCfg 从外部 USD 加载线缆,例如在 DCC 工具中编写的资产,前提是曲线已经具备:

  • 加载的 prim 下有单个开放、线性、非周期的 UsdGeom.BasisCurves ;

  • 已应用 PhysicsCurvesDeformableSimAPI 模式;以及

  • 已绑定可变形曲线材质( PhysicsCurvesDeformableMaterialAPI ),在 physics: 命名空间中提供 thickness 、 density 、 stretchStiffness 和 bendStiffness 。

这对应两种失败情况。没有仿真模式的曲线不属于可变形物体导入范围,会被静默跳过。具有该模式但无法解析厚度的曲线会使用默认半径导入,并发出警告。请通过 spawn_cable() 编写线缆,或在构造前将模式和材质应用到导入的 prim 上。

线缆渲染#

线缆在 Kit 视口中以 UsdGeom.BasisCurves 渲染。每次渲染更新时,根据线缆各线段端点刷新曲线点,使渲染形状始终与仿真一致。

备注

曲线点通过 CPU Fabric 同步,因为 RTX Hydra 委托不会读取 BasisCurves 的 GPU Fabric 数组(NVBug 6502662)。同步时会跳过周期曲线。

线缆限制#

  • 每个对象只能包含一条独立、未与其他线缆焊接的线缆。 CableObject 要求 prim_path 下恰好有一个带 PhysicsCurvesDeformableSimAPI 的 BasisCurves prim,其中包含一条未与其他线缆焊接的开放曲线。多曲线 BasisCurves prim、周期(闭合)曲线,以及曲线之间硬性重合的 PhysicsAttachment 焊接,都会在初始化时失败。

  • 线缆端点可以铰接固定,不能夹紧固支。 连接到 xform 目标的 PhysicsAttachment 会转换为球关节,因此只约束位置,线缆可以在锚点处自由转动。无法表示需要传递方向约束的刚性插头和端部接头。

  • 没有阻尼调节参数。 提供了四种刚度模量,但没有对应的阻尼参数。

  • 渲染同步仅使用 CPU (NVBug 6502662);周期曲线不会同步。

备注

只有附件刚度未设置或为无穷大时,才会创建附件关节。有限刚度仅保留为元数据,不创建关节。这两种情况均以导入警告而非错误报告,因此线缆仍会正常初始化,即使附件实际缺失。如果附件似乎不起作用,请检查导入器输出。

备注

运行时对象拒绝的拓扑仍会参与仿真:物理模型从整个 USD 舞台构建,因此每条带 PhysicsCurvesDeformableSimAPI 的曲线都会导入,无论是否由 CableObject 包装。可通过 NewtonManager 的 get_model() / get_state_0() 和自行创建的 newton.selection.ArticulationView 控制它们。这些情况没有对应的 Isaac Lab 资产包装器。

材质参数的实际效果#

下方每个动画都将同一场景运行三次,只改变一个材质参数,其余保持不变。标签给出各次运行使用的值。

体积#

三种杨氏模量下,软球落到桌面上的效果

杨氏模量 :控制整体刚度。设为 1e3 Pa 时,球体撞击后压成扁饼;设为 1e5 Pa 时,几乎不变形。软体过软或过硬时,应首先调整此参数。#

三种泊松比下,软球落到桌面上的效果

泊松比 :控制材料受压时保持体积的程度。设为 0.10 时,球体压扁但不向四周展开;设为 0.49 时,材料近乎不可压缩,同样的压缩会使其向外明显鼓起。#

三种粒子半径下,软球静置于桌面上的效果

粒子半径 :各仿真节点周围的接触厚度,并非材质属性。半径越大,越早在远离表面的位置检测到接触,因此球体会明显浮在桌面上方,也无法压得很薄。半径过小可能漏检接触或检测过晚;相对网格分辨率过大,则会过早产生接触。#

表面#

三种拉伸刚度下,布料垂覆在滚筒上的效果

拉伸刚度 :抵抗面内伸长的能力。较低值使布料在自重下拉伸和下垂,较高值则使其保持接近静止长度。#

三种弯曲刚度下,布料从滚筒上落下的效果

弯曲刚度 :抵抗折叠的能力。设为 1e-2 时,布料揉皱成松散的一堆;设为 1e0 时,会保持较大、较硬的褶皱,并继续垂覆在滚筒上。这类似丝绸与帆布的区别。#

线缆#

三种弯曲刚度下,线缆跨在两根支柱之间的效果

弯曲刚度 :设为 1e0 时,线缆像松绳一样在支撑点之间下垂;设为 1e2 时,则像较硬的软管一样保持平直。#

三种扭转刚度下,带配重的悬挂线缆在顶端扭转的效果

扭转刚度 :在锚点处扭转带配重的线缆。设为 1e-1 时,扭转在局部被吸收,线缆仍直垂;设为 1e1 时,扭转沿杆传递,直到发生屈曲并卷成螺旋。如果线缆需要抵抗缠绕,应显式设置该值;未设置时会按前述规则回退到弯曲值。#

示例与任务#

先运行示例,确认生成器、求解器和可视化器都能在当前环境中正常工作。

类型

示例

任务

体积

deformables

Isaac-Lift-Soft-Franka, Isaac-Lift-Soft-Franka-Camera

表面

deformables

Isaac-Lift-Cloth-Franka, Isaac-Lift-Cloth-Franka-Camera

线缆

cables

Isaac-Lift-Cable-Franka, Isaac-Lift-Cable-Franka-Camera

# Volume and surface deformables falling onto a ground plane.
uv run --extra tetrahedralization isaaclab example deformables

# A pile of cables that collide and settle. Newton VBD only.
uv run isaaclab example cables

# A larger cable pile, without a visualizer, stopping after a fixed number of steps.
uv run isaaclab example cables --visualizer none --num_cables 40 --num_segments 15 --max_steps 500

scripts/environments/state_machine/lift_franka_soft.py 使用脚本状态机驱动 Isaac-Lift-Soft-Franka ,可作为可变形物体操作任务的起点。