Articulation

关键属性

  • links (List[Link]):
    封装的连杆对象列表;每个 Link 再封装对应的刚体、网格等信息。
    对于 GPU 模式,属性如 link.poselink.linear_velocity 等通常为形状 (N, ...) 的张量。

  • links_map (Dict[str, Link]):
    名称到 Link 的映射,可用 links_map["gripper"] 这种方式快速索引。

  • root (Link):
    根连杆(基座)的 Link 对象。

  • joints (List[ArticulationJoint]), joints_map (Dict[str, ArticulationJoint]):
    封装的关节对象及其名称映射。

  • active_joints, active_joints_map:
    仅包含活动自由度(可驱动的关节)的列表及名称映射。

  • name (str):
    当前 articulation 的名字。

  • merged (bool):
    是否为合并 articulation:

    • 若为 True,很多与“单一物理对象结构”紧密相关的属性(如 linksjoints、接触力等)将不再有直接物理语义,仅保留 DOF 级别的统一访问。
    • 合并 articulation 主要用于批量管理不同 DOF/结构的对象,如统一 qpos/qvel 张量形状。
  • max_dof (int, 只读):
    所有内部 PhysxArticulation 中 DOF 的最大值,用于对 qposqvelqf 等进行零填充,使其形状统一为 (N, max_dof)

  • dof (torch.Tensor):
    每个内部 articulation 的 DOF 数,形状 (N,),在 GPU 模式下保持在 device 上。

  • pose / root_pose (Pose / sapien.Pose):
    根连杆的姿态(位置 + 四元数);poseroot_pose 的别名。

  • qpos, qvel, qacc, qf (torch.Tensor):

    • 形状:(N, max_dof),其中 N 为并行 articulation 数。
    • 在 GPU 模式下,直接映射到底层 px.cuda_articulation_* 的统一视图张量;
    • 在 CPU 模式下,对第一个物理 articulation 读写(并在第 0 维扩展一维批次)。
  • drive_targets, drive_velocities (torch.Tensor):

    • 当前活动关节的驱动位置/速度目标,形状为 (N, M)M 为活动 DOF 数。
    • GPU 模式直接从 px.cuda_articulation_target_qpos/qvel 中以 meshgrid 索引方式切片。

常用方法(高层接口)

下面列出在上层任务/控制代码中最常使用的一些方法。除非特别指出,张量形状中的:

  • (N) 表示并行环境数(或批量 articulation 数);

  • (M) 表示活动关节数;

  • max_dofArticulation.max_dof

  • get_state()torch.Tensor
    打包并返回整条 articulation 的状态:
    [
    [\text{root_pos}(3), \text{root_quat}(4), \text{root_lin_vel}(3), \text{root_ang_vel}(3), qpos(\text{max_dof}), qvel(\text{max_dof})]
    ]
    输出形状为 (N, 13 + 2 * max_dof)

  • set_state(state, env_idx=None)
    get_state() 对偶,从打包状态张量中恢复 articulation 的根姿态、线速度、角速度以及 qposqvel

    • state (Array): 形状 (N, 13 + 2 * max_dof) 或单样本;
    • env_idx (torch.Tensor, 可选): 在 GPU 模式下,只对部分环境应用状态重置,内部会暂时修改 scene._reset_mask 做安全防护。
  • get_first_collision_mesh(to_world_frame=True)trimesh.Trimesh | None
    返回第一个管理对象的整体碰撞网格(合并各 link 的碰撞几何),可选是否转到世界坐标系。可能返回 None

  • get_collision_meshes(to_world_frame=True, first_only=False)List[trimesh.Trimesh] | trimesh.Trimesh
    返回所有管理对象的碰撞网格列表,或在 first_only=True 时仅返回第一个对象的网格。

  • get_first_visual_mesh(to_world_frame=True),
    get_visual_meshes(to_world_frame=True, first_only=False)
    与碰撞网格接口类似,但使用渲染形状(visual meshes)。

  • get_net_contact_impulses(link_names)torch.Tensor
    批量获取若干 link 的净接触冲量,形状为 (N, len(link_names), 3)

    • GPU 模式下通过缓存的 PhysxGpuContactBodyImpulseQuery 高效查询;
    • CPU 模式下遍历场景接触并按 link 名义聚合。
  • get_net_contact_forces(link_names)torch.Tensor
    get_net_contact_impulses 的输出除以 scene.timestep,得到接触(N, len(link_names), 3))。

  • get_joint_target_indices(joint_indices)
    为一组活动关节(或关节索引)返回在 GPU 目标张量 (cuda_articulation_target_qpos/qvel) 中的 meshgrid 索引 (gx, gy),并进行缓存,用于后续高效写入。

  • set_joint_drive_targets(targets, joints=None, joint_indices=None)
    设置活动关节的驱动位置目标:

    • GPU 模式下仅支持 joint_indicestargets 形状通常为 (N, K);内部通过 meshgrid 索引写入目标张量;
    • CPU 模式下需要显式传入 joints 列表,逐个调用 joint.set_drive_target
  • set_joint_drive_velocity_targets(targets, joints=None, joint_indices=None)
    与上类似,但写入速度目标

  • **get_links() / get_joints() / get_active_joints() / get_name() / get_pose()
    这些方法大多是更清晰的别名或轻量封装,行为与对应属性一致,便于与原生 SAPIEN / PhysX API 对齐。


形状与后端约定
  • GPU 模式scene.gpu_sim_enabled == True)下:

    • qpos/qvel/qacc/qf 等属性直接映射为底层 px.cuda_articulation_* 张量的切片视图;
    • 读写操作将直接修改 PhysX GPU 侧的统一缓冲区;
    • 某些函数(如 compute_passive_forcecreate_pinocchio_model)目前不支持,会抛出 NotImplementedError
  • CPU 模式下:

    • qpos 等通过 self._objs[0](第一个 PhysxArticulation)的值构造 torch.Tensor,并在第 0 维增加批维度;
    • 写操作会在必要时将张量转回 NumPy,并写回到 PhysX 对象。

使用示例
from mani_skill.envs.scene import ManiSkillScene
from mani_skill.utils.structs import Articulation

# 假设已经创建好 scene,并在其中构建了若干 physx_articulations
physx_articulations = [...]  # List[physx.PhysxArticulation]
scene_idxs = torch.arange(len(physx_articulations), device="cuda")

articulation = Articulation.create_from_physx_articulations(
    physx_articulations=physx_articulations,
    scene=scene,
    scene_idxs=scene_idxs,
)

# 读取/设置关节状态
qpos = articulation.get_qpos()        # (N, max_dof)
qvel = articulation.get_qvel()

target_qpos = qpos + 0.1
articulation.set_qpos(target_qpos)

# 批量设置活动关节驱动目标(GPU 模式下,使用 joint_indices)
active_indices = torch.arange(articulation.active_joints.__len__(), device="cuda")
targets = torch.zeros_like(articulation.drive_targets)
articulation.set_joint_drive_targets(targets, joint_indices=active_indices)

# 导出第一个机器人的碰撞网格
mesh = articulation.get_first_collision_mesh(to_world_frame=True)
Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐