Isaac Sim API 文档索引
📚 本文档集合概述
本文档集合按功能分类整理了Isaac Sim的主要API,适合学习和快速查阅。涵盖了从基础核心API到高级功能的完整参考。
📑 文档目录
斜体的文档内容位于Isaac Sim 4.5 API参考文档(二)
🏗️ 基础组件
| 文档 | 描述 | 主要功能 |
|---|---|---|
| 核心API | 核心API接口 | World、PhysicsContext、SimulationContext等基础类 |
| 场景与任务 | 场景管理和预定义任务 | Scene管理、Task框架、场景注册等 |
| 材质与物理 | 材质系统和物理属性 | 视觉材质、物理材质、粒子材质等 |
🤖 机器人相关
| 文档 | 描述 | 主要功能 |
|---|---|---|
| 机器人 | 机器人相关API | 机械臂、轮式机器人、抓取器等 |
| 控制器 | 各种控制器实现 | 关节控制、抓取控制、运动控制等 |
| 机器人示例 | 机器人示例代码 | Franka、UR10等常用机器人示例 |
| 运动规划 | 运动规划和行为控制 | 路径规划、行为树等 |
📡 传感与环境
| 文档 | 描述 | 主要功能 |
|---|---|---|
| 传感器 | 传感器相关API | 相机、激光雷达、接触传感器等 |
| 对象与几何 | 3D对象和几何体 | 基本形状、关节对象等 |
🔧 工具与集成
| 文档 | 描述 | 主要功能 |
|---|---|---|
| 导入工具 | 资产导入工具 | URDF、MJCF等格式导入 |
| 仿真工具 | 仿真相关工具 | 数据生成、UI组件等 |
| ROS2集成 | ROS2相关集成和桥接 | ROS2消息、服务、话题等 |
🚀 快速开始示例
from isaacsim.core.api import World
from omni.isaac.franka import Franka
from isaacsim.core.api.objects import DynamicCuboid
import numpy as np
# 1. 创建仿真世界
world = World()
world.scene.add_default_ground_plane()
# 2. 添加机器人
robot = world.scene.add(Franka(prim_path="/World/Franka", name="my_franka"))
# 3. 添加物体
cube = world.scene.add(
DynamicCuboid(
prim_path="/World/Cube",
name="target_cube",
position=np.array([0.3, 0.0, 0.05]),
size=0.04,
color=np.array([1.0, 0.0, 0.0])
)
)
# 4. 初始化并运行仿真
world.reset()
for i in range(1000):
world.step(render=True)
# 在这里添加你的控制逻辑
if i % 100 == 0:
print(f"Step {i}: Robot position = {robot.get_world_pose()[0]}")
📖 学习资源
官方资源
- 官方文档: docs.omniverse.nvidia.com/isaacsim/la…
- 示例代码: 查看Isaac Sim安装目录的
standalone_examples文件夹
社区资源
- 开发者论坛: forums.developer.nvidia.com/c/omniverse…
- GitHub仓库: github.com/NVIDIA-Omni…
- 视频教程: NVIDIA Isaac Sim bilibili频道
ℹ️ 使用说明
- 查找API: 通过上方的表格快速定位所需功能模块
- 示例学习: 查看机器人示例文档获取实际应用代码
- 深入了解: 查看具体文档了解详细API参考
- 问题解决: 参考官方论坛或GitHub仓库解决实际问题
🤝 贡献指南
如您想为本文档做出贡献:
- 提交问题或建议到相关GitHub仓库
- 为新功能编写示例代码
- 改进现有的文档说明
- 分享使用经验和最佳实践
最后更新: 2025-05-10
版本: Isaac Sim 4.5.0
维护者: scilwb
Isaac Sim API - 核心API
📋 概述
核心API接口,包括World、PhysicsContext、SimulationContext等基础类。这些类构成了Isaac Sim仿真的基础架构。
🌟 主要类
🌍 World类
位置: isaacsim.core.api.World
功能说明: 主要仿真世界类,继承自SimulationContext,提供完整的仿真环境管理功能。
代码示例:
from isaacsim.core.api import World
# 创建世界
world = World(
physics_dt=1.0/60.0, # 物理时间步长
rendering_dt=1.0/60.0, # 渲染时间步长
stage_units_in_meters=1.0, # 场景单位
backend="numpy" # 后端选择
)
# 添加默认地面
world.scene.add_default_ground_plane()
# 重置世界
world.reset()
# 运行仿真
for i in range(1000):
world.step(render=True)
关键方法:
-
_init_stage(self, physics_dt=None, rendering_dt=None, ...) →Usd.Stage- 初始化舞台
- 设置物理和渲染参数
-
_initialize_stage_async(self, physics_dt=None, rendering_dt=None, ...) →Usd.Stage- 异步初始化舞台
- 支持异步操作
-
add_physics_callback(self, callback_name: str, callback_fn: Callable[[float], None]) → None- 添加物理步骤回调函数
- 在每次物理步骤前调用
-
add_render_callback(self, callback_name: str, callback_fn: Callable) → None- 添加渲染回调函数
- 在每次渲染后调用
-
add_stage_callback(self, callback_name: str, callback_fn: Callable) → None- 添加舞台事件回调
- 处理打开/关闭等事件
⚡ PhysicsContext类
位置: isaacsim.core.api.PhysicsContext
功能说明: 提供物理场景及其设置的高级管理功能。处理物理场景的创建、配置和管理。
代码示例:
from isaacsim.core.api import PhysicsContext
# 创建物理上下文
physics_context = PhysicsContext(
physics_dt=1.0/60.0, # 物理时间步长
prim_path="/physicsScene", # 物理场景路径
set_defaults=True # 设置默认值
)
# 启用功能
physics_context.enable_ccd(True) # 启用连续碰撞检测
physics_context.enable_gpu_dynamics(True) # 启用GPU动力学
physics_context.enable_stablization(True) # 启用稳定化
关键方法:
-
enable_ccd(self, flag: bool) → None- 启用连续碰撞检测
- 防止高速物体穿透
-
enable_gpu_dynamics(self, flag: bool) → None- 启用GPU动力学管道
- 用于可变形体等
-
enable_stablization(self, flag: bool) → None- 启用求解器稳定化
- 提高物理稳定性
-
get_broadphase_type(self) → str- 获取广相碰撞检测算法类型
-
get_current_physics_scene_prim(self) → Optional[Usd.Prim]- 返回当前物理场景Prim
🔄 SimulationContext类
位置: isaacsim.core.api.SimulationContext
功能说明: 处理时间相关事件,管理物理和渲染步骤,包含PhysicsContext实例。
代码示例:
from isaacsim.core.api import SimulationContext
# 创建仿真上下文
sim_context = SimulationContext(
physics_dt=1.0/60.0, # 物理时间步
rendering_dt=1.0/60.0, # 渲染时间步
backend="numpy", # 后端
device="cuda" # 设备
)
# 添加回调函数
def my_physics_callback(dt):
print(f"Physics step: dt={dt}")
sim_context.add_physics_callback("my_callback", my_physics_callback)
关键方法:
-
add_physics_callback(self, callback_name: str, callback_fn: Callable[[float], None]) → None- 添加物理步骤回调函数
-
add_render_callback(self, callback_name: str, callback_fn: Callable) → None- 添加渲染回调函数
-
add_stage_callback(self, callback_name: str, callback_fn: Callable) → None- 添加舞台事件回调
-
_physics_timer_callback_fn(self, step_size: int)- 物理计时器回调函数
-
_timeline_timer_callback_fn(self, event)- 时间轴计时器回调函数
💡 实际应用示例
创建完整的仿真环境
from isaacsim.core.api import World, PhysicsContext
import numpy as np
class MySimulation:
def __init__(self):
# 创建世界
self.world = World(physics_dt=1.0/120.0) # 高精度物理
# 配置物理
physics_context = self.world.get_physics_context()
physics_context.enable_ccd(True)
physics_context.enable_gpu_dynamics(True)
# 添加回调
self.setup_callbacks()
def setup_callbacks(self):
# 物理回调
self.world.add_physics_callback("physics_update", self.physics_update)
# 渲染回调
self.world.add_render_callback("render_update", self.render_update)
def physics_update(self, dt):
# 在每个物理步骤执行
print(f"Physics step: {dt}")
def render_update(self):
# 在每个渲染步骤执行
pass
def run(self):
# 重置世界
self.world.reset()
# 运行仿真
for i in range(1000):
self.world.step(render=True)
# 每100步打印信息
if i % 100 == 0:
print(f"Simulation step: {i}")
# 使用示例
sim = MySimulation()
sim.run()
异步仿真初始化
import asyncio
from isaacsim.core.api import World
async def async_simulation_setup():
# 创建世界
world = World()
# 异步初始化舞台
await world._initialize_stage_async(
physics_dt=1.0/60.0,
rendering_dt=1.0/30.0,
set_defaults=True
)
# 添加地面
world.scene.add_default_ground_plane()
# 重置世界
world.reset()
return world
# 运行异步初始化
async def main():
world = await async_simulation_setup()
# 运行仿真
for i in range(100):
world.step(render=True)
await asyncio.sleep(0.01) # 模拟异步操作
# 执行
asyncio.run(main())
🔧 常见问题解决
1. 物理不稳定问题
# 增加物理精度,启用额外功能
physics_context = world.get_physics_context()
physics_context.set_physics_dt(1.0/180.0) # 更高频率
physics_context.enable_stablization(True) # 稳定化
physics_context.enable_ccd(True) # 连续碰撞检测
2. 性能优化
# 使用GPU加速
world = World(
physics_dt=1.0/60.0,
backend="torch", # 使用PyTorch后端
device="cuda" # 使用GPU
)
# 启用GPU动力学
physics_context = world.get_physics_context()
physics_context.enable_gpu_dynamics(True)
3. 回调函数管理
class CallbackManager:
def __init__(self, world):
self.world = world
self.callbacks = {}
def add_callback(self, name, callback_type, function):
if callback_type == "physics":
self.world.add_physics_callback(name, function)
elif callback_type == "render":
self.world.add_render_callback(name, function)
self.callbacks[name] = (callback_type, function)
def remove_callback(self, name):
if name in self.callbacks:
callback_type, _ = self.callbacks[name]
if callback_type == "physics":
self.world.remove_physics_callback(name)
elif callback_type == "render":
self.world.remove_render_callback(name)
del self.callbacks[name]
📚 API继承关系
BaseClass
↓
SimulationContext
↓
World
- World 继承 SimulationContext
- SimulationContext 包含 PhysicsContext
- 每个类都有特定的职责和功能
最后更新: 2025-05-10
版本: Isaac Sim 4.5.0
Isaac Sim API - 场景与任务
📋 概述
场景管理和预定义任务,提供完整的场景构建和任务规划框架。支持灵活的场景对象管理和模块化任务设计。
🎬 场景管理
🌍 Scene类
位置: isaacsim.core.api.scenes.Scene
功能说明: 管理场景中的所有对象,处理对象注册、状态重置等。
代码示例:
from isaacsim.core.api.scenes import Scene
from isaacsim.core.api.objects import DynamicCuboid, GroundPlane
from isaacsim.robot.manipulators import SingleManipulator
import numpy as np
# 创建场景实例
scene = Scene()
# 添加地面平面
ground_plane = scene.add_default_ground_plane(
z_position=0,
name="default_ground",
static_friction=0.5,
dynamic_friction=0.5,
restitution=0.8
)
# 添加物体
cube = scene.add(DynamicCuboid(
prim_path="/World/Cube",
name="target_cube",
position=np.array([0.3, 0.0, 0.05]),
size=0.04,
color=np.array([1.0, 0.0, 0.0])
))
# 添加机器人
robot = scene.add(SingleManipulator(
prim_path="/World/Robot",
name="my_robot",
end_effector_prim_name="end_effector"
))
# 获取场景对象
retrieved_cube = scene.get_object("target_cube")
retrieved_robot = scene.get_object("my_robot")
# 检查对象是否存在
if scene.object_exists("target_cube"):
print("Cube found in scene")
# 计算对象边界框
min_bounds, max_bounds = scene.compute_object_AABB("target_cube")
print(f"Cube bounds: min={min_bounds}, max={max_bounds}")
# 启用边界框计算
scene.enable_bounding_boxes_computations()
# 清空场景(可选仅清空注册表)
scene.clear(registry_only=False) # 清空整个场景
scene.clear(registry_only=True) # 仅清空注册表
关键方法:
-
add(self, obj: SingleXFormPrim) → SingleXFormPrim- 添加对象到场景注册表
-
add_default_ground_plane(self, z_position=0, name='default_ground_plane', ...) → GroundPlane- 创建并添加默认地面平面
-
add_ground_plane(self, size=None, z_position=0, name='ground_plane', ...) → GroundPlane- 创建并添加自定义地面平面
-
get_object(self, name: str) → SingleXFormPrim- 根据名称获取注册的对象
-
object_exists(self, name: str) → bool- 检查对象是否存在于场景中
-
compute_object_AABB(self, name: str) → Tuple[numpy.ndarray, numpy.ndarray]- 计算对象的轴对齐边界框
-
enable_bounding_boxes_computations(self) → None- 启用边界框计算
-
disable_bounding_boxes_computations(self) → None- 禁用边界框计算
-
clear(self, registry_only: bool = False) → None- 清空场景或仅清空注册表
📝 SceneRegistry类
位置: isaacsim.core.api.scenes.SceneRegistry
功能说明: 追踪和管理场景中不同类型的对象。
代码示例:
from isaacsim.core.api.scenes import SceneRegistry
# 创建场景注册表
registry = SceneRegistry()
# 注册不同类型的对象
registry.add_articulated_system("robot1", robot)
registry.add_rigid_object("cube1", cube)
registry.add_sensor("camera1", camera)
registry.add_task("pick_place", pick_place_task)
registry.add_material("plastic", plastic_material)
registry.add_deformable("cloth1", cloth_object)
# 按类型获取对象
robots = registry.get_articulated_systems()
cubes = registry.get_rigid_objects()
cameras = registry.get_sensors()
# 获取特定对象
robot = registry.get_articulated_system("robot1")
cube = registry.get_rigid_object("cube1")
# 获取所有对象名称
all_names = registry.get_all_object_names()
对象类型方法:
关节系统:
add_articulated_system(name, system)get_articulated_system(name)get_articulated_systems()
关节视图:
add_articulated_view(name, view)get_articulated_view(name)get_articulated_views()
刚体对象:
add_rigid_object(name, object)get_rigid_object(name)get_rigid_objects()
几何对象:
add_geometry_object(name, object)get_geometry_object(name)get_geometry_objects()
可变形体:
add_deformable(name, deformable)get_deformable(name)get_deformables()
布料:
add_cloth(name, cloth)get_cloth(name)get_cloths()
材质:
add_material(name, material)get_material(name)get_materials()
传感器:
add_sensor(name, sensor)get_sensor(name)get_sensors()
任务:
add_task(name, task)get_task(name)get_tasks()
回调管理:
add_callbacks(callbacks)get_callbacks_on_physics_step()get_callbacks_on_render()
📋 任务框架
📚 BaseTask类
位置: isaacsim.core.api.tasks.BaseTask
功能说明: 任务的基础类,提供模块化的任务设计框架。
代码示例:
from isaacsim.core.api.tasks import BaseTask
import numpy as np
class CustomTask(BaseTask):
def __init__(self, name="my_task", offset=None):
super().__init__(name=name, offset=offset)
# 定义任务所需的观测值
self.observation_space = {
"robot_joint_positions": 7, # 机器人关节位置
"object_position": 3, # 物体位置
"object_orientation": 4 # 物体方向
}
# 初始化任务状态
self.reset()
def set_up_scene(self, scene: Scene) → None:
"""设置场景"""
super().set_up_scene(scene)
# 添加场景对象
self.robot = scene.add(SingleManipulator(
prim_path="/World/Robot",
name="task_robot"
))
self.target_object = scene.add(DynamicCuboid(
prim_path="/World/Target",
name="target_object",
position=np.array([0.5, 0.0, 0.05])
))
# 设置为任务对象
self._task_objects = {
"robot": self.robot,
"target": self.target_object
}
def get_observations(self) → dict:
"""获取观测值"""
observations = super().get_observations()
# 添加任务特定的观测
observations.update({
"robot_joint_positions": self.robot.get_joint_positions(),
"object_position": self.target_object.get_world_pose()[0],
"object_orientation": self.target_object.get_world_pose()[1]
})
return observations
def calculate_metrics(self) → dict:
"""计算任务指标"""
# 计算成功率、距离等指标
robot_ee_pos, _ = self.robot.get_end_effector_pose()
object_pos, _ = self.target_object.get_world_pose()
distance = np.linalg.norm(robot_ee_pos - object_pos)
return {
"distance_to_object": distance,
"success": distance < 0.05,
}
def is_done(self) → bool:
"""检查任务是否完成"""
metrics = self.calculate_metrics()
return metrics.get("success", False)
def get_description(self) → str:
"""获取任务描述"""
return "Move robot end-effector to target object"
def get_params(self) → dict:
"""获取任务参数"""
return {
"task_type": "reach",
"target_object": "cube",
"robot_type": "manipulator"
}
def post_reset(self) → None:
"""重置后调用"""
super().post_reset()
# 重置物体位置
random_pos = np.array([
np.random.uniform(0.3, 0.7),
np.random.uniform(-0.3, 0.3),
0.05
])
self.target_object.set_world_pose(position=random_pos)
def pre_step(self, time_step_index: int, simulation_time: float) → None:
"""仿真步前调用"""
super().pre_step(time_step_index, simulation_time)
# 执行任务逻辑
if time_step_index % 10 == 0:
self.check_progress()
def cleanup(self) → None:
"""清理临时对象"""
# 清理任务创建的临时对象
pass
# 使用自定义任务
task = CustomTask(name="reach_task")
world.add_task(task)
关键方法:
-
set_up_scene(self, scene: Scene) → None- 设置任务场景
-
get_observations(self) → dict- 获取当前观测值
-
calculate_metrics(self) → dict- 计算任务相关指标
-
is_done(self) → bool- 检查任务是否完成
-
get_description(self) → str- 获取任务描述
-
get_params(self) → dict- 获取任务参数
-
get_task_objects(self) → dict- 获取任务相关对象
-
post_reset(self) → None- 重置后调用
-
pre_step(self, time_step_index: int, simulation_time: float) → None- 仿真步前调用
-
cleanup(self) → None- 清理临时对象
🎯 预定义任务
📦 拾放任务 - PickPlace
位置: isaacsim.core.api.tasks.PickPlace
功能说明: 模拟机器人拾放操作的任务。
代码示例:
from isaacsim.core.api.tasks import PickPlace
import numpy as np
# 创建拾放任务
pick_place_task = PickPlace(
name="pick_place_demo",
cube_initial_position=np.array([0.3, 0.0, 0.05]),
cube_initial_orientation=np.array([0, 0, 0, 1]),
target_position=np.array([0.5, 0.0, 0.05]),
cube_size=np.array([0.04, 0.04, 0.04]),
offset=np.array([0, 0, 0])
)
# 设置场景
pick_place_task.set_up_scene(scene)
# 执行任务循环
for i in range(1000):
# 获取观测
observations = pick_place_task.get_observations()
print(f"Observations: {observations}")
# 计算指标
metrics = pick_place_task.calculate_metrics()
print(f"Metrics: {metrics}")
# 检查是否完成
if pick_place_task.is_done():
print("Task completed!")
break
# 执行仿真步
world.step(render=True)
# 清理任务
pick_place_task.cleanup()
关键属性:
cube_initial_position: 立方体初始位置cube_initial_orientation: 立方体初始方向target_position: 目标放置位置cube_size: 立方体尺寸
🎯 跟随目标任务 - FollowTarget
位置: isaacsim.core.api.tasks.FollowTarget
功能说明: 让机器人跟随移动目标的任务。
代码示例:
from isaacsim.core.api.tasks import FollowTarget
# 创建跟随目标任务
follow_task = FollowTarget(
name="follow_demo",
target_prim_path=None, # 自动创建目标
target_name="moving_target",
target_position=np.array([1.0, 0.0, 0.5]),
target_orientation=np.array([0, 0, 0, 1]),
offset=np.array([0, 0, 0])
)
# 设置场景
follow_task.set_up_scene(scene)
# 添加障碍物
obstacle_pos = np.array([0.5, 0.5, 0.1])
follow_task.add_obstacle(position=obstacle_pos)
# 执行任务
for i in range(1000):
# 更新目标位置(模拟运动轨迹)
time = i * 0.01
target_pos = np.array([
0.5 + 0.5 * np.cos(time),
0.5 * np.sin(time),
0.5
])
follow_task.set_target_position(target_pos)
# 获取观测
observations = follow_task.get_observations()
# 计算指标
metrics = follow_task.calculate_metrics()
# 检查是否完成
if follow_task.is_done():
print("Target reached!")
# 执行仿真步
world.step(render=True)
# 动态管理障碍物
if i == 500:
follow_task.add_obstacle(position=np.array([0.8, 0.2, 0.1]))
if i == 700:
follow_task.remove_obstacle()
关键方法:
-
add_obstacle(self, position=None)- 添加障碍物
-
get_obstacle_to_delete(self) → None- 获取要删除的障碍物
📚 堆叠任务 - Stacking
位置: isaacsim.core.api.tasks.Stacking
功能说明: 多物体堆叠任务。
代码示例:
from isaacsim.core.api.tasks import Stacking
# 创建堆叠任务
stacking_task = Stacking(
name="stacking_demo",
cube_initial_positions=np.array([
[0.2, -0.2, 0.025],
[0.3, 0.0, 0.025],
[0.4, 0.2, 0.025]
]),
cube_initial_orientations=None, # 使用默认方向
stack_target_position=np.array([0.6, 0.0, 0.025]),
cube_size=np.array([0.03, 0.03, 0.05]),
offset=np.array([0, 0, 0])
)
# 设置场景
stacking_task.set_up_scene(scene)
# 获取立方体名称
cube_names = stacking_task.get_cube_names()
print(f"Cubes to stack: {cube_names}")
# 执行堆叠任务
for i in range(2000):
# 预步处理
stacking_task.pre_step(i, world.current_time)
# 获取观测
observations = stacking_task.get_observations()
# 计算指标
metrics = stacking_task.calculate_metrics()
print(f"Stacking metrics: {metrics}")
# 检查是否完成
if stacking_task.is_done():
print("Stacking completed!")
break
# 执行仿真步
world.step(render=True)
# 重置任务
stacking_task.post_reset()
关键方法:
-
get_cube_names(self) → List[str]- 获取立方体名称列表
-
pre_step(self, time_step_index: int, simulation_time: float) → None- 每步前处理
💡 实际应用示例
多任务管理器
class TaskManager:
def __init__(self, scene):
self.scene = scene
self.tasks = {}
self.current_task = None
self.task_history = []
def add_task(self, task_name, task):
"""添加任务"""
self.tasks[task_name] = task
task.set_up_scene(self.scene)
def start_task(self, task_name):
"""开始执行任务"""
if task_name not in self.tasks:
raise ValueError(f"Task {task_name} not found")
# 结束当前任务
if self.current_task:
self.current_task.cleanup()
# 开始新任务
self.current_task = self.tasks[task_name]
self.current_task.post_reset()
self.task_history.append(task_name)
print(f"Started task: {task_name}")
def update_current_task(self):
"""更新当前任务"""
if not self.current_task:
return None
# 获取观测
observations = self.current_task.get_observations()
# 计算指标
metrics = self.current_task.calculate_metrics()
# 检查是否完成
is_done = self.current_task.is_done()
return {
"observations": observations,
"metrics": metrics,
"is_done": is_done
}
def get_task_sequence(self):
"""获取任务序列"""
return self.task_history
def execute_task_sequence(self, task_sequence, max_steps_per_task=1000):
"""执行任务序列"""
results = []
for task_name in task_sequence:
print(f"Executing task: {task_name}")
self.start_task(task_name)
# 执行任务直到完成或超时
for step in range(max_steps_per_task):
# 预步处理
self.current_task.pre_step(step, step * 0.01)
# 更新任务
task_result = self.update_current_task()
# 执行仿真步
world.step(render=True)
# 检查是否完成
if task_result["is_done"]:
results.append({
"task": task_name,
"status": "completed",
"steps": step + 1,
"metrics": task_result["metrics"]
})
break
else:
# 超时
results.append({
"task": task_name,
"status": "timeout",
"steps": max_steps_per_task,
"metrics": task_result["metrics"]
})
return results
# 使用示例
task_manager = TaskManager(scene)
# 添加多个任务
task_manager.add_task("pick_place_1", PickPlace(
name="pick_1",
cube_initial_position=np.array([0.3, 0.0, 0.05]),
target_position=np.array([0.5, 0.0, 0.05])
))
task_manager.add_task("pick_place_2", PickPlace(
name="pick_2",
cube_initial_position=np.array([0.4, 0.2, 0.05]),
target_position=np.array([0.6, 0.2, 0.05])
))
task_manager.add_task("stacking", Stacking(
name="stack_3_cubes",
cube_initial_positions=np.array([
[0.3, -0.1, 0.025],
[0.3, 0.0, 0.025],
[0.3, 0.1, 0.025]
]),
stack_target_position=np.array([0.7, 0.0, 0.025])
))
# 执行任务序列
task_sequence = ["pick_place_1", "pick_place_2", "stacking"]
results = task_manager.execute_task_sequence(task_sequence)
# 打印结果
for result in results:
print(f"Task: {result['task']}")
print(f"Status: {result['status']}")
print(f"Steps: {result['steps']}")
print(f"Metrics: {result['metrics']}")
print("---")
场景配置管理器
class SceneConfigurationManager:
def __init__(self):
self.configurations = {}
def save_configuration(self, name, scene):
"""保存场景配置"""
config = {
"objects": {},
"materials": {},
"lighting": {},
"physics": {}
}
# 保存所有注册对象
registry = scene.scene_registry
for obj_name in registry.get_all_object_names():
obj = registry.get_object(obj_name)
config["objects"][obj_name] = {
"type": type(obj).__name__,
"prim_path": obj.prim_path,
"position": obj.get_world_pose()[0].tolist() if hasattr(obj, 'get_world_pose') else None,
"orientation": obj.get_world_pose()[1].tolist() if hasattr(obj, 'get_world_pose') else None
}
self.configurations[name] = config
print(f"Saved configuration: {name}")
def load_configuration(self, name, scene):
"""加载场景配置"""
if name not in self.configurations:
raise ValueError(f"Configuration {name} not found")
config = self.configurations[name]
# 清空当前场景
scene.clear(registry_only=False)
# 重建场景
for obj_name, obj_config in config["objects"].items():
# 这里需要根据对象类型创建相应的对象
# 简化示例
if obj_config["type"] == "DynamicCuboid":
obj = DynamicCuboid(
prim_path=obj_config["prim_path"],
name=obj_name,
position=np.array(obj_config["position"]) if obj_config["position"] else None,
orientation=np.array(obj_config["orientation"]) if obj_config["orientation"] else None
)
scene.add(obj)
print(f"Loaded configuration: {name}")
def list_configurations(self):
"""列出所有配置"""
return list(self.configurations.keys())
def create_configuration_from_template(self, name, template_type):
"""根据模板创建配置"""
templates = {
"pick_place": {
"objects": {
"robot": {"type": "Franka", "position": [0, 0, 0]},
"cube": {"type": "DynamicCuboid", "position": [0.3, 0.0, 0.05]},
"table": {"type": "FixedCuboid", "position": [0.5, 0, -0.5]}
}
},
"assembly": {
"objects": {
"robot": {"type": "UR10", "position": [0, -0.5, 0]},
"part1": {"type": "DynamicCuboid", "position": [0.2, 0.2, 0.05]},
"part2": {"type": "DynamicCuboid", "position": [0.3, 0.2, 0.05]},
"assembly_area": {"type": "FixedCuboid", "position": [0.5, 0, 0]}
}
}
}
if template_type in templates:
self.configurations[name] = templates[template_type]
else:
raise ValueError(f"Template {template_type} not found")
# 使用示例
config_manager = SceneConfigurationManager()
# 保存当前场景配置
config_manager.save_configuration("pick_place_scenario", scene)
# 创建模板配置
config_manager.create_configuration_from_template("assembly_task", "assembly")
# 加载配置
config_manager.load_configuration("assembly_task", scene)
# 列出所有配置
configs = config_manager.list_configurations()
print(f"Available configurations: {configs}")
任务性能分析器
class TaskPerformanceAnalyzer:
def __init__(self):
self.metrics_history = {}
self.task_timelines = {}
def start_analysis(self, task_name):
"""开始分析任务"""
self.metrics_history[task_name] = []
self.task_timelines[task_name] = {
"start_time": time.time(),
"events": []
}
def record_metrics(self, task_name, step, metrics):
"""记录指标"""
if task_name not in self.metrics_history:
self.start_analysis(task_name)
timestamp = time.time()
record = {
"step": step,
"timestamp": timestamp,
"metrics": metrics.copy()
}
self.metrics_history[task_name].append(record)
def record_event(self, task_name, event_type, description):
"""记录事件"""
if task_name not in self.task_timelines:
self.start_analysis(task_name)
event = {
"timestamp": time.time(),
"type": event_type,
"description": description
}
self.task_timelines[task_name]["events"].append(event)
def analyze_task_performance(self, task_name):
"""分析任务性能"""
if task_name not in self.metrics_history:
return None
metrics_history = self.metrics_history[task_name]
timeline = self.task_timelines[task_name]
# 计算统计信息
completion_time = (metrics_history[-1]["timestamp"] -
timeline["start_time"])
total_steps = metrics_history[-1]["step"]
# 分析成功/失败事件
success_events = [e for e in timeline["events"] if e["type"] == "success"]
failure_events = [e for e in timeline["events"] if e["type"] == "failure"]
# 计算平均指标
avg_metrics = {}
for key in metrics_history[0]["metrics"].keys():
values = [record["metrics"][key] for record in metrics_history
if key in record["metrics"]]
if values:
avg_metrics[key] = np.mean(values)
analysis = {
"task_name": task_name,
"completion_time": completion_time,
"total_steps": total_steps,
"average_metrics": avg_metrics,
"success_count": len(success_events),
"failure_count": len(failure_events),
"timeline": timeline["events"]
}
return analysis
def generate_report(self, task_names=None):
"""生成性能报告"""
if task_names is None:
task_names = list(self.metrics_history.keys())
report = {
"generation_time": time.time(),
"tasks": {}
}
for task_name in task_names:
analysis = self.analyze_task_performance(task_name)
if analysis:
report["tasks"][task_name] = analysis
# 计算总体统计
if task_names:
report["summary"] = {
"total_tasks": len(task_names),
"average_completion_time": np.mean([
report["tasks"][t]["completion_time"]
for t in task_names
]),
"total_success_rate": (
sum(report["tasks"][t]["success_count"] for t in task_names) /
len(task_names)
)
}
return report
# 使用示例
analyzer = TaskPerformanceAnalyzer()
# 分析任务执行
task_name = "pick_place_task"
analyzer.start_analysis(task_name)
for step in range(1000):
# 记录指标
metrics = task.calculate_metrics()
analyzer.record_metrics(task_name, step, metrics)
# 记录重要事件
if metrics.get("success", False):
analyzer.record_event(task_name, "success", "Task completed successfully")
break
elif step % 100 == 0:
analyzer.record_event(task_name, "checkpoint", f"Step {step} reached")
world.step(render=True)
# 生成报告
report = analyzer.generate_report()
print(json.dumps(report, indent=2))
🔧 常见问题解决
1. 场景对象管理
def debug_scene_objects(scene):
"""调试场景对象"""
# 获取所有对象
registry = scene.scene_registry
all_objects = registry.get_all_object_names()
print(f"Total objects: {len(all_objects)}")
# 按类型分类
object_types = {}
for obj_name in all_objects:
obj = registry.get_object(obj_name)
obj_type = type(obj).__name__
if obj_type not in object_types:
object_types[obj_type] = []
object_types[obj_type].append(obj_name)
# 打印分类信息
for obj_type, names in object_types.items():
print(f"{obj_type}: {len(names)} objects")
for name in names:
print(f" - {name}")
2. 任务状态管理
class TaskStateManager:
def __init__(self):
self.task_states = {}
self.state_history = {}
def save_state(self, task_name, state_data):
"""保存任务状态"""
self.task_states[task_name] = state_data.copy()
if task_name not in self.state_history:
self.state_history[task_name] = []
self.state_history[task_name].append({
"timestamp": time.time(),
"state": state_data.copy()
})
def restore_state(self, task_name):
"""恢复任务状态"""
if task_name not in self.task_states:
return None
return self.task_states[task_name].copy()
def get_state_history(self, task_name):
"""获取状态历史"""
return self.state_history.get(task_name, [])
# 使用示例
state_manager = TaskStateManager()
# 保存当前状态
current_state = {
"robot_position": robot.get_joint_positions(),
"object_positions": {
"cube1": cube1.get_world_pose()[0],
"cube2": cube2.get_world_pose()[0]
},
"task_progress": 0.7
}
state_manager.save_state("stacking_task", current_state)
# 恢复状态
restored_state = state_manager.restore_state("stacking_task")
if restored_state:
robot.set_joint_positions(restored_state["robot_position"])
3. 性能优化
class ScenePerformanceOptimizer:
@staticmethod
def optimize_physics_settings(world):
"""优化物理设置"""
physics_context = world.get_physics_context()
# 使用GPU物理
physics_context.enable_gpu_dynamics(True)
# 调整求解器参数
physics_context.set_solver_iterations(4)
physics_context.set_solver_type("PGS")
# 启用CCD
physics_context.enable_ccd(True)
@staticmethod
def optimize_rendering_settings(world):
"""优化渲染设置"""
# 调整渲染频率
world.set_rendering_dt(1/30.0) # 30 FPS
# 减少阴影质量
# 设置LOD等级
pass
@staticmethod
def batch_operations(scene, operations):
"""批量操作优化"""
# 关闭实时更新
scene.disable_bounding_boxes_computations()
# 执行批量操作
for operation in operations:
operation()
# 重新启用更新
scene.enable_bounding_boxes_computations()
📊 任务类型对比
| 任务类型 | 主要功能 | 适用场景 | 关键指标 |
|---|---|---|---|
| PickPlace | 拾放物体 | 基础操作训练 | 成功率、时间 |
| FollowTarget | 跟随移动目标 | 跟踪控制 | 跟踪误差、响应速度 |
| Stacking | 物体堆叠 | 精细操作 | 堆叠高度、稳定性 |
| CustomTask | 自定义任务 | 特殊需求 | 任务特定指标 |
最后更新: 2025-05-10
版本: Isaac Sim 4.5.0
Isaac Sim API - 材质与物理
📋 概述
材质系统和物理属性,包括视觉材质、物理材质等。涵盖从基础材质到高级物理特性的完整管理。
🎨 视觉材质
🌈 OmniPBR材质
位置: isaacsim.core.api.materials.OmniPBR
功能说明: 基于物理的渲染材质,支持完整的PBR工作流。
代码示例:
from isaacsim.core.api.materials import OmniPBR
import numpy as np
# 创建PBR材质
pbr_material = OmniPBR(
prim_path="/World/Looks/MyPBRMaterial",
name="my_pbr_material",
color=np.array([0.8, 0.1, 0.1]), # 基础颜色
texture_path="/path/to/texture.png",
texture_scale=np.array([2.0, 2.0]) # 纹理缩放
)
# 设置材质属性
pbr_material.set_color(np.array([0.9, 0.2, 0.2]))
pbr_material.set_metallic_constant(0.5) # 金属度
pbr_material.set_reflection_roughness(0.3) # 粗糙度
pbr_material.set_project_uvw(True) # 启用UV投影
# 获取材质属性
color = pbr_material.get_color()
metallic = pbr_material.get_metallic_constant()
roughness = pbr_material.get_reflection_roughness()
# 应用到对象
object.apply_visual_material(pbr_material)
关键方法:
-
set_color(self, color: numpy.ndarray) → None- 设置基础颜色 (RGB)
-
get_color(self) → numpy.ndarray- 获取基础颜色
-
set_metallic_constant(self, amount: float) → None- 设置金属度 (0.0-1.0)
-
get_metallic_constant(self) → float- 获取金属度
-
set_reflection_roughness(self, amount: float) → None- 设置表面粗糙度
-
get_reflection_roughness(self) → float- 获取粗糙度
-
set_texture(self, texture_path: str) → None- 设置纹理贴图
-
get_texture(self) → str- 获取纹理路径
-
set_texture_scale(self, scale: numpy.ndarray) → None- 设置纹理缩放
-
get_texture_scale(self) → numpy.ndarray- 获取纹理缩放
-
set_texture_translate(self, translate: numpy.ndarray) → None- 设置纹理偏移
-
get_texture_translate(self) → numpy.ndarray- 获取纹理偏移
-
set_project_uvw(self, flag: bool) → None- 设置UV投影模式
-
get_project_uvw(self) → bool- 获取UV投影状态
🔍 OmniGlass材质
位置: isaacsim.core.api.materials.OmniGlass
功能说明: 高质量玻璃材质,支持折射和透射。
代码示例:
from isaacsim.core.api.materials import OmniGlass
# 创建玻璃材质
glass_material = OmniGlass(
prim_path="/World/Looks/GlassMaterial",
name="glass_material",
color=np.array([0.8, 0.9, 1.0]), # 玻璃颜色
ior=1.5, # 折射率
depth=0.02, # 厚度
thin_walled=False # 是否薄壁
)
# 设置玻璃属性
glass_material.set_ior(1.3) # 设置折射率
glass_material.set_depth(0.05) # 设置厚度
glass_material.set_thin_walled(True) # 设置薄壁模式
# 获取属性
color = glass_material.get_color()
ior = glass_material.get_ior()
depth = glass_material.get_depth()
thin_walled = glass_material.get_thin_walled()
# 应用到对象
glass_object.apply_visual_material(glass_material)
关键方法:
-
set_color(self, color: numpy.ndarray) → None- 设置玻璃颜色
-
get_color(self) → Optional[numpy.ndarray]- 获取玻璃颜色
-
set_ior(self, ior: float) → None- 设置折射率 (Index of Refraction)
-
get_ior(self) → Optional[float]- 获取折射率
-
set_depth(self, depth: float) → None- 设置玻璃厚度
-
get_depth(self) → Optional[float]- 获取玻璃厚度
-
set_thin_walled(self, thin_walled: bool) → None- 设置薄壁模式
-
get_thin_walled(self) → Optional[bool]- 获取薄壁模式状态
📺 PreviewSurface材质
位置: isaacsim.core.api.materials.PreviewSurface
功能说明: 轻量级预览材质,适合快速原型。
代码示例:
from isaacsim.core.api.materials import PreviewSurface
# 创建预览材质
preview_material = PreviewSurface(
prim_path="/World/Looks/PreviewMaterial",
name="preview_material",
color=np.array([0.5, 0.5, 0.5]),
roughness=0.7,
metallic=0.0
)
# 设置材质属性
preview_material.set_color(np.array([0.8, 0.4, 0.2]))
preview_material.set_roughness(0.5)
preview_material.set_metallic(0.1)
# 应用材质
object.apply_visual_material(preview_material)
关键方法:
-
set_color(self, color: numpy.ndarray) → None- 设置材质颜色
-
get_color(self) → numpy.ndarray- 获取材质颜色
-
set_roughness(self, roughness: float) → None- 设置粗糙度
-
get_roughness(self) → float- 获取粗糙度
-
set_metallic(self, metallic: float) → None- 设置金属度
-
get_metallic(self) → float- 获取金属度
⚙️ 物理材质
🧱 PhysicsMaterial材质
位置: isaacsim.core.api.materials.PhysicsMaterial
功能说明: 刚体物理材质,控制摩擦和弹性。
代码示例:
from isaacsim.core.api.materials import PhysicsMaterial
# 创建物理材质
physics_material = PhysicsMaterial(
prim_path="/World/Physics/Material",
name="physics_material",
static_friction=0.7, # 静摩擦系数
dynamic_friction=0.5, # 动摩擦系数
restitution=0.3 # 弹性系数
)
# 设置物理属性
physics_material.set_static_friction(0.8)
physics_material.set_dynamic_friction(0.6)
physics_material.set_restitution(0.4)
# 获取属性
static_friction = physics_material.get_static_friction()
dynamic_friction = physics_material.get_dynamic_friction()
restitution = physics_material.get_restitution()
# 应用到刚体
rigid_body.apply_physics_material(physics_material)
关键方法:
-
set_static_friction(self, friction: float) → None- 设置静摩擦系数
-
get_static_friction(self) → float- 获取静摩擦系数
-
set_dynamic_friction(self, friction: float) → None- 设置动摩擦系数
-
get_dynamic_friction(self) → float- 获取动摩擦系数
-
set_restitution(self, restitution: float) → None- 设置弹性系数 (0.0-1.0)
-
get_restitution(self) → float- 获取弹性系数
🌊 DeformableMaterial材质
位置: isaacsim.core.api.materials.DeformableMaterial
功能说明: 可变形体材质,用于模拟软体。
代码示例:
from isaacsim.core.api.materials import DeformableMaterial
# 创建可变形材质
deformable_material = DeformableMaterial(
prim_path="/World/Physics/DeformableMaterial",
name="soft_material"
)
# 设置材质属性
deformable_material.set_youngs_modulus(1e6) # 杨氏模量
deformable_material.set_poissons_ratio(0.3) # 泊松比
deformable_material.set_damping_scale(0.1) # 阻尼系数
deformable_material.set_elasticity_damping(0.1) # 弹性阻尼
deformable_material.set_dynamic_friction(0.5) # 摩擦系数
# 获取属性
youngs = deformable_material.get_youngs_modulus()
poisson = deformable_material.get_poissons_ratio()
damping = deformable_material.get_damping_scale()
# 应用到软体
soft_body.apply_deformable_material(deformable_material)
关键方法:
-
set_youngs_modulus(self, value: float) → None- 设置杨氏模量(刚度)
-
get_youngs_modulus(self) → float- 获取杨氏模量
-
set_poissons_ratio(self, value: float) → None- 设置泊松比
-
get_poissons_ratio(self) → float- 获取泊松比
-
set_damping_scale(self, value: float) → None- 设置整体阻尼系数
-
get_damping_scale(self) → float- 获取阻尼系数
-
set_elasticity_damping(self, value: float) → None- 设置弹性阻尼
-
get_elasticity_damping(self) → float- 获取弹性阻尼
-
set_dynamic_friction(self, value: float) → None- 设置动摩擦系数
-
get_dynamic_friction(self) → float- 获取动摩擦系数
💧 ParticleMaterial材质
位置: isaacsim.core.api.materials.ParticleMaterial
功能说明: 粒子材质,用于流体、布料等模拟。
代码示例:
from isaacsim.core.api.materials import ParticleMaterial
# 创建粒子材质
particle_material = ParticleMaterial(
prim_path="/World/Physics/ParticleMaterial",
name="fluid_material"
)
# 设置粒子属性
particle_material.set_friction(0.5) # 摩擦力
particle_material.set_drag(0.1) # 阻力
particle_material.set_cohesion(0.01) # 内聚力
particle_material.set_adhesion(0.0) # 粘附力
particle_material.set_damping(0.0) # 阻尼
particle_material.set_gravity_scale(1.0) # 重力缩放
particle_material.set_particle_friction_scale(1.0) # 粒子摩擦缩放
particle_material.set_particle_adhesion_scale(1.0) # 粒子粘附缩放
# 获取属性
friction = particle_material.get_friction()
drag = particle_material.get_drag()
cohesion = particle_material.get_cohesion()
# 应用到粒子系统
particle_system.apply_particle_material(particle_material)
关键方法:
-
set_friction(self, value: float) → None- 设置粒子摩擦系数
-
get_friction(self) → float- 获取摩擦系数
-
set_drag(self, value: float) → None- 设置阻力系数
-
get_drag(self) → float- 获取阻力系数
-
set_cohesion(self, value: float) → None- 设置内聚力
-
get_cohesion(self) → float- 获取内聚力
-
set_adhesion(self, value: float) → None- 设置粘附力
-
get_adhesion(self) → float- 获取粘附力
-
set_damping(self, value: float) → None- 设置阻尼
-
get_damping(self) → float- 获取阻尼
-
set_gravity_scale(self, value: float) → None- 设置重力缩放
-
get_gravity_scale(self) → float- 获取重力缩放
-
set_particle_friction_scale(self, value: float) → None- 设置粒子间摩擦缩放
-
get_particle_friction_scale(self) → float- 获取粒子间摩擦缩放
-
set_particle_adhesion_scale(self, value: float) → None- 设置粒子间粘附缩放
-
get_particle_adhesion_scale(self) → float- 获取粒子间粘附缩放
📊 材质视图类
🔍 DeformableMaterialView类
位置: isaacsim.core.api.materials.DeformableMaterialView
功能说明: 批量处理可变形材质的视图类。
代码示例:
from isaacsim.core.api.materials import DeformableMaterialView
import numpy as np
# 创建可变形材质视图
material_view = DeformableMaterialView(
prim_paths_expr="/World/Physics/SoftBodies/*/Material",
name="deformable_materials"
)
# 初始化
material_view.initialize()
# 批量设置属性
youngs_moduli = np.array([1e6, 5e5, 2e6]) # 多个材质的杨氏模量
material_view.set_youngs_moduli(youngs_moduli)
# 批量获取属性
dampings = material_view.get_damping_scales() # 返回所有材质的阻尼值
frictions = material_view.get_dynamic_frictions() # 返回所有材质的摩擦系数
# 按索引设置特定材质
material_view.set_youngs_moduli(
values=np.array([2e6]),
indices=[0] # 只设置第一个材质
)
💧 ParticleMaterialView类
位置: isaacsim.core.api.materials.ParticleMaterialView
功能说明: 批量处理粒子材质的视图类。
代码示例:
from isaacsim.core.api.materials import ParticleMaterialView
# 创建粒子材质视图
particle_view = ParticleMaterialView(
prim_paths_expr="/World/Particles/*/Material",
name="particle_materials"
)
# 批量设置属性
frictions = np.array([0.5, 0.3, 0.7])
particle_view.set_frictions(frictions)
# 批量获取属性
drags = particle_view.get_drags()
cohesions = particle_view.get_cohesions()
💡 实际应用示例
复合材质系统
class CompositeMaterialSystem:
def __init__(self):
self.materials = {}
def create_metal_material(self, name, color, metallic=0.9, roughness=0.3):
"""创建金属材质"""
material = OmniPBR(
prim_path=f"/World/Looks/{name}",
name=name,
color=color
)
material.set_metallic_constant(metallic)
material.set_reflection_roughness(roughness)
self.materials[name] = material
return material
def create_plastic_material(self, name, color, roughness=0.5):
"""创建塑料材质"""
material = OmniPBR(
prim_path=f"/World/Looks/{name}",
name=name,
color=color
)
material.set_metallic_constant(0.0)
material.set_reflection_roughness(roughness)
self.materials[name] = material
return material
def create_glass_material(self, name, color, ior=1.5, thin_walled=False):
"""创建玻璃材质"""
material = OmniGlass(
prim_path=f"/World/Looks/{name}",
name=name,
color=color,
ior=ior,
thin_walled=thin_walled
)
self.materials[name] = material
return material
def create_physical_material(self, name, static_friction=0.7,
dynamic_friction=0.5, restitution=0.0):
"""创建物理材质"""
material = PhysicsMaterial(
prim_path=f"/World/Physics/{name}",
name=name,
static_friction=static_friction,
dynamic_friction=dynamic_friction,
restitution=restitution
)
self.materials[name] = material
return material
def apply_complete_material(self, object, visual_material_name,
physics_material_name):
"""应用完整材质(视觉+物理)"""
visual_material = self.materials.get(visual_material_name)
physics_material = self.materials.get(physics_material_name)
if visual_material:
object.apply_visual_material(visual_material)
if physics_material:
object.apply_physics_material(physics_material)
# 使用示例
material_system = CompositeMaterialSystem()
# 创建各种材质
metal_material = material_system.create_metal_material(
"steel", np.array([0.7, 0.7, 0.8]), metallic=0.9, roughness=0.2
)
plastic_material = material_system.create_plastic_material(
"red_plastic", np.array([0.8, 0.1, 0.1]), roughness=0.4
)
glass_material = material_system.create_glass_material(
"clear_glass", np.array([0.9, 0.95, 1.0]), ior=1.5
)
# 创建物理材质
rubber_physics = material_system.create_physical_material(
"rubber", static_friction=1.2, dynamic_friction=1.0, restitution=0.8
)
# 应用材质到对象
material_system.apply_complete_material(
my_object,
visual_material_name="red_plastic",
physics_material_name="rubber"
)
动态材质控制器
class DynamicMaterialController:
def __init__(self):
self.material_presets = self.create_presets()
self.current_preset = None
def create_presets(self):
"""创建材质预设"""
presets = {}
# 金属预设
presets["steel"] = {
"visual": {
"type": "pbr",
"color": np.array([0.7, 0.7, 0.8]),
"metallic": 0.9,
"roughness": 0.2
},
"physics": {
"static_friction": 0.6,
"dynamic_friction": 0.4,
"restitution": 0.0
}
}
# 橡胶预设
presets["rubber"] = {
"visual": {
"type": "pbr",
"color": np.array([0.2, 0.2, 0.2]),
"metallic": 0.0,
"roughness": 0.9
},
"physics": {
"static_friction": 1.2,
"dynamic_friction": 1.0,
"restitution": 0.8
}
}
# 冰预设
presets["ice"] = {
"visual": {
"type": "glass",
"color": np.array([0.9, 0.95, 1.0]),
"ior": 1.31,
"thin_walled": False
},
"physics": {
"static_friction": 0.1,
"dynamic_friction": 0.05,
"restitution": 0.2
}
}
return presets
def apply_preset(self, object, preset_name):
"""应用材质预设"""
if preset_name not in self.material_presets:
raise ValueError(f"Preset {preset_name} not found")
preset = self.material_presets[preset_name]
# 创建并应用视觉材质
visual_config = preset["visual"]
if visual_config["type"] == "pbr":
visual_material = OmniPBR(
prim_path=f"/World/Looks/{preset_name}_visual",
name=f"{preset_name}_visual",
color=visual_config["color"]
)
visual_material.set_metallic_constant(visual_config["metallic"])
visual_material.set_reflection_roughness(visual_config["roughness"])
elif visual_config["type"] == "glass":
visual_material = OmniGlass(
prim_path=f"/World/Looks/{preset_name}_visual",
name=f"{preset_name}_visual",
color=visual_config["color"],
ior=visual_config["ior"],
thin_walled=visual_config["thin_walled"]
)
# 创建并应用物理材质
physics_config = preset["physics"]
physics_material = PhysicsMaterial(
prim_path=f"/World/Physics/{preset_name}_physics",
name=f"{preset_name}_physics",
static_friction=physics_config["static_friction"],
dynamic_friction=physics_config["dynamic_friction"],
restitution=physics_config["restitution"]
)
# 应用材质
object.apply_visual_material(visual_material)
object.apply_physics_material(physics_material)
self.current_preset = preset_name
def interpolate_materials(self, object, preset1, preset2, factor):
"""在两个预设间插值"""
config1 = self.material_presets[preset1]
config2 = self.material_presets[preset2]
# 插值视觉属性
color1 = config1["visual"]["color"]
color2 = config2["visual"]["color"]
interpolated_color = color1 * (1 - factor) + color2 * factor
# 创建插值材质
visual_material = OmniPBR(
prim_path="/World/Looks/interpolated_visual",
name="interpolated_visual",
color=interpolated_color
)
# 插值物理属性
physics1 = config1["physics"]
physics2 = config2["physics"]
physics_material = PhysicsMaterial(
prim_path="/World/Physics/interpolated_physics",
name="interpolated_physics",
static_friction=physics1["static_friction"] * (1 - factor) + physics2["static_friction"] * factor,
dynamic_friction=physics1["dynamic_friction"] * (1 - factor) + physics2["dynamic_friction"] * factor,
restitution=physics1["restitution"] * (1 - factor) + physics2["restitution"] * factor
)
# 应用材质
object.apply_visual_material(visual_material)
object.apply_physics_material(physics_material)
# 使用示例
material_controller = DynamicMaterialController()
# 应用预设
material_controller.apply_preset(my_object, "steel")
# 材质过渡动画
for t in np.linspace(0, 1, 100):
material_controller.interpolate_materials(my_object, "steel", "rubber", t)
world.step(render=True)
软体材质配置器
class SoftBodyMaterialConfigurator:
def __init__(self):
self.presets = {
"jelly": {
"youngs_modulus": 1e4,
"poissons_ratio": 0.45,
"damping_scale": 0.1,
"elasticity_damping": 0.2,
"dynamic_friction": 0.3
},
"rubber": {
"youngs_modulus": 1e6,
"poissons_ratio": 0.4,
"damping_scale": 0.05,
"elasticity_damping": 0.05,
"dynamic_friction": 0.8
},
"cloth": {
"youngs_modulus": 5e4,
"poissons_ratio": 0.3,
"damping_scale": 0.2,
"elasticity_damping": 0.1,
"dynamic_friction": 0.5
}
}
def configure_deformable(self, object, preset_name):
"""配置可变形材质"""
if preset_name not in self.presets:
raise ValueError(f"Preset {preset_name} not found")
preset = self.presets[preset_name]
# 创建可变形材质
material = DeformableMaterial(
prim_path=f"/World/Physics/Deformable/{preset_name}",
name=f"deformable_{preset_name}"
)
# 应用预设属性
material.set_youngs_modulus(preset["youngs_modulus"])
material.set_poissons_ratio(preset["poissons_ratio"])
material.set_damping_scale(preset["damping_scale"])
material.set_elasticity_damping(preset["elasticity_damping"])
material.set_dynamic_friction(preset["dynamic_friction"])
# 应用到对象
object.apply_deformable_material(material)
return material
def create_custom_deformable(self, object, name, **properties):
"""创建自定义可变形材质"""
material = DeformableMaterial(
prim_path=f"/World/Physics/Deformable/{name}",
name=f"deformable_{name}"
)
# 应用自定义属性
if "youngs_modulus" in properties:
material.set_youngs_modulus(properties["youngs_modulus"])
if "poissons_ratio" in properties:
material.set_poissons_ratio(properties["poissons_ratio"])
if "damping_scale" in properties:
material.set_damping_scale(properties["damping_scale"])
if "elasticity_damping" in properties:
material.set_elasticity_damping(properties["elasticity_damping"])
if "dynamic_friction" in properties:
material.set_dynamic_friction(properties["dynamic_friction"])
# 应用到对象
object.apply_deformable_material(material)
return material
# 使用示例
configurator = SoftBodyMaterialConfigurator()
# 应用预设
soft_object = world.scene.add(SoftBody(prim_path="/World/SoftObject"))
configurator.configure_deformable(soft_object, "jelly")
# 创建自定义材质
custom_object = world.scene.add(SoftBody(prim_path="/World/CustomSoft"))
configurator.create_custom_deformable(
custom_object,
"custom_soft",
youngs_modulus=5e5,
poissons_ratio=0.35,
damping_scale=0.15,
elasticity_damping=0.1,
dynamic_friction=0.6
)
🔧 常见问题解决
1. 材质不生效
def debug_material_application(object):
"""诊断材质应用问题"""
# 检查对象类型
print(f"Object type: {type(object)}")
# 检查是否有碰撞形状
if hasattr(object, 'get_collision_approximation'):
print(f"Collision approximation: {object.get_collision_approximation()}")
# 尝试直接在USD层面应用材质
from omni.usd import get_context
stage = get_context().get_stage()
prim = stage.GetPrimAtPath(object.prim_path)
# 检查材质绑定
if prim.HasAPI(UsdShade.MaterialBindingAPI):
binding_api = UsdShade.MaterialBindingAPI(prim)
material_binding = binding_api.GetDirectBinding()
print(f"Current material binding: {material_binding}")
2. 物理材质优化
class PhysicsMaterialOptimizer:
def __init__(self):
self.optimal_configurations = {
"high_friction_contact": {
"static_friction": 1.5,
"dynamic_friction": 1.2
},
"low_friction_sliding": {
"static_friction": 0.1,
"dynamic_friction": 0.05
},
"bouncy_surface": {
"restitution": 0.9,
"static_friction": 0.5,
"dynamic_friction": 0.4
}
}
def optimize_contact(self, object1, object2, contact_type):
"""优化两个对象间的接触"""
config = self.optimal_configurations.get(contact_type)
if not config:
return
# 创建优化的材质
material = PhysicsMaterial(
prim_path=f"/World/Physics/Optimized_{contact_type}",
name=f"optimized_{contact_type}",
static_friction=config.get("static_friction", 0.7),
dynamic_friction=config.get("dynamic_friction", 0.5),
restitution=config.get("restitution", 0.0)
)
# 应用到两个对象
object1.apply_physics_material(material)
object2.apply_physics_material(material)
3. 材质性能优化
class MaterialPerformanceOptimizer:
@staticmethod
def optimize_material_for_realtime(material):
"""优化材质以提高实时性能"""
if isinstance(material, OmniPBR):
# 降低纹理分辨率
material.set_texture_scale(np.array([0.5, 0.5]))
# 简化反射计算
material.set_reflection_roughness(0.5) # 适中的粗糙度
elif isinstance(material, OmniGlass):
# 减少折射复杂度
material.set_thin_walled(True)
@staticmethod
def batch_optimize_materials(materials):
"""批量优化多个材质"""
for material in materials:
MaterialPerformanceOptimizer.optimize_material_for_realtime(material)
📊 材质属性参考表
物理材质常用数值
| 材料类型 | 静摩擦系数 | 动摩擦系数 | 弹性系数 |
|---|---|---|---|
| 钢铁 | 0.5-0.7 | 0.4-0.6 | 0.0-0.1 |
| 橡胶 | 1.0-1.5 | 0.8-1.2 | 0.6-0.9 |
| 塑料 | 0.3-0.5 | 0.2-0.4 | 0.1-0.3 |
| 玻璃 | 0.4-0.6 | 0.3-0.5 | 0.0-0.2 |
| 冰 | 0.1-0.2 | 0.05-0.1 | 0.1-0.3 |
| 布料 | 0.5-0.8 | 0.4-0.7 | 0.0-0.1 |
可变形材质参考
| 材料类型 | 杨氏模量 (Pa) | 泊松比 | 阻尼系数 |
|---|---|---|---|
| 橡胶 | 1e6 - 1e7 | 0.4-0.45 | 0.05-0.1 |
| 海绵 | 1e4 - 1e5 | 0.3-0.4 | 0.1-0.2 |
| 皮革 | 1e7 - 1e8 | 0.3-0.35 | 0.02-0.05 |
| 布料 | 1e6 - 5e6 | 0.2-0.3 | 0.1-0.2 |
| 凝胶 | 1e3 - 1e4 | 0.45-0.49 | 0.2-0.5 |
最后更新: 2025-05-10
版本: Isaac Sim 4.5.0
Isaac Sim API - 机器人
📋 概述
机器人相关API,包括机械臂、轮式机器人、抓取器等。提供完整的机器人控制、运动规划和操作功能。
🤖 主要类
🦾 机械臂 - SingleManipulator
位置: isaacsim.robot.manipulators.SingleManipulator
功能说明: 管理单个末端执行器的机械臂,可选配抓取器。
代码示例:
from isaacsim.robot.manipulators import SingleManipulator
from isaacsim.core.api import World
# 创建世界
world = World()
# 创建机械臂
manipulator = SingleManipulator(
prim_path="/World/Manipulator",
name="my_arm",
end_effector_prim_name="end_effector",
gripper=None # 可选配抓取器
)
# 设置关节位置
joint_positions = [0.0, -1.0, 0.0, -2.0, 0.0, 1.0, 0.0]
manipulator.set_joint_positions(joint_positions)
# 获取末端执行器位置
ee_position, ee_orientation = manipulator.get_end_effector_pose()
print(f"End effector position: {ee_position}")
关键方法:
-
apply_action(self, control_actions: ArticulationAction) → None- 应用关节位置、速度或力矩控制
- 支持多种控制模式
-
get_applied_action(self) → ArticulationAction- 获取最后应用的动作
-
get_applied_joint_efforts(self, joint_indices=None) → numpy.ndarray- 获取关节力矩
-
get_articulation_body_count(self) → int- 获取机器人连杆数量
-
enable_gravity(self) → None- 启用重力影响
-
disable_gravity(self) → None- 禁用重力影响
-
apply_visual_material(self, visual_material, weaker_than_descendants=False) → None- 应用视觉材质
🚗 轮式机器人控制器
差速控制器 - DifferentialController
位置: isaacsim.robot.wheeled_robots.DifferentialController
功能说明: 使用单轮模型的差速驱动控制器。
代码示例:
from isaacsim.robot.wheeled_robots import DifferentialController
import numpy as np
# 创建差速控制器
controller = DifferentialController(
name="diff_controller",
wheel_radius=0.035, # 轮半径
wheel_base=0.12 # 轮间距
)
# 发送控制命令 [线速度, 角速度]
command = np.array([0.5, 0.1]) # 0.5 m/s前进,0.1 rad/s转向
action = controller.forward(command)
# 应用到机器人
robot.apply_action(action)
控制公式:
- ω_R = 1/(2r) × (2V + ω×b)
- ω_L = 1/(2r) × (2V - ω×b)
其中:
- ω_R, ω_L: 右轮、左轮角速度
- V: 期望线速度
- ω: 期望角速度
- r: 轮半径
- b: 轮间距
关键方法:
-
forward(self, command: numpy.ndarray) → ArticulationAction- 将 [线速度, 角速度] 转换为 [左轮, 右轮] 目标
-
reset(self) → None- 重置控制器状态
阿克曼控制器 - AckermannController
位置: isaacsim.robot.wheeled_robots.AckermannController
功能说明: 使用自行车模型的阿克曼转向控制器。
代码示例:
from isaacsim.robot.wheeled_robots import AckermannController
# 创建阿克曼控制器
controller = AckermannController(
name="ackermann_controller",
wheel_base=0.3, # 前后轴距
track_width=0.25, # 左右轮距
front_wheel_radius=0.05, # 前轮半径
back_wheel_radius=0.05, # 后轮半径
max_wheel_velocity=10.0 # 最大轮速
)
# 发送控制命令 [转向角, 前进速度]
command = np.array([0.2, 1.0]) # 0.2 rad转向,1.0 m/s前进
action = controller.forward(command)
关键方法:
-
forward(self, command: numpy.ndarray) → ArticulationAction- 计算左右轮角度和角速度
-
reset(self) → None- 重置控制器状态
全向轮控制器 - HolonomicController
位置: isaacsim.robot.wheeled_robots.HolonomicController
功能说明: 计算全向移动所需的关节驱动命令。使用二次规划最小化"净力"。
代码示例:
from isaacsim.robot.wheeled_robots import HolonomicController
# 创建全向控制器(需要预先定义轮子属性)
controller = HolonomicController(
name="holonomic_controller",
wheel_dof_names=["wheel_fl", "wheel_fr", "wheel_bl", "wheel_br"]
)
# 设置麦轮属性
controller.setup_mecanum_wheels(
wheel_positions=[...], # 轮子位置
roller_angles=[...] # 滚轮角度
)
# 发送控制命令 [前进, 侧移, 旋转]
command = np.array([0.5, 0.2, 0.1])
action = controller.forward(command)
关键方法:
-
build_base(self)- 构建控制器基础
-
forward(self, command: numpy.ndarray) → ArticulationAction- 计算轮速以实现期望速度
-
reset(self) → None- 重置控制器
🤲 抓取器
平行抓手 - ParallelGripper
位置: isaacsim.robot.manipulators.grippers.ParallelGripper
功能说明: 管理具有两个手指的平行抓手。
代码示例:
from isaacsim.robot.manipulators.grippers import ParallelGripper
import numpy as np
# 创建平行抓手
gripper = ParallelGripper(
end_effector_prim_path="/World/Robot/gripper",
joint_prim_names=["left_finger", "right_finger"],
joint_opened_positions=np.array([0.02, 0.02]),
joint_closed_positions=np.array([0.0, 0.0]),
action_deltas=np.array([0.001, 0.001]) # 增量步长
)
# 使用抓手
gripper.open() # 打开
gripper.close() # 关闭
# 应用自定义动作
action = gripper.forward("open")
robot.apply_action(action)
关键方法:
-
open(self) → None- 打开抓手
-
close(self) → None- 关闭抓手
-
forward(self, action: str) → ArticulationAction- 根据动作字符串返回关节动作
-
get_action_deltas(self) → numpy.ndarray- 获取动作增量
-
apply_action(self, control_actions: ArticulationAction) → None- 应用关节动作
吸盘抓手 - SurfaceGripper
位置: isaacsim.robot.manipulators.grippers.SurfaceGripper
功能说明: 管理表面抓手(如吸盘)。
代码示例:
from isaacsim.robot.manipulators.grippers import SurfaceGripper
# 创建吸盘抓手
surface_gripper = SurfaceGripper(
end_effector_prim_path="/World/Robot/suction_cup",
translate=0.0, # 平移距离
direction="x", # 方向
grip_threshold=0.01, # 抓取阈值
force_limit=1.0e6, # 力限制
torque_limit=1.0e4 # 扭矩限制
)
# 使用吸盘
surface_gripper.close() # 启动吸盘
surface_gripper.open() # 关闭吸盘
关键方法:
-
forward(self, action: str) → ArticulationAction- 计算对应的关节动作
-
close(self) → None- 激活吸盘
-
open(self) → None- 关闭吸盘
🔧 工具函数
轮式机器人工具函数
位置: isaacsim.robot.wheeled_robots
角度标准化
def normalize_angle(angle):
"""将角度标准化到 [-pi, pi]"""
while angle > np.pi:
angle -= 2 * np.pi
while angle < -np.pi:
angle += 2 * np.pi
return angle
PID控制
def pid_control(target, current, Kp=0.1):
"""简单的比例控制器"""
return Kp * (target - current)
Stanley控制器
def stanley_control(state, cx, cy, cyaw, last_target_idx,
p=0.5, i=0.01, d=10, k=0.5):
"""Stanley转向控制算法"""
# 实现Stanley算法逻辑
pass
五次多项式规划
def quintic_polynomials_planner(sx, sy, syaw, sv, sa,
gx, gy, gyaw, gv, ga,
max_accel, max_jerk, dt):
"""五次多项式轨迹规划器"""
# 实现五次多项式规划
pass
目标索引计算
def calc_target_index(state, cx, cy):
"""计算轨迹列表中的目标索引"""
# 实现目标点计算逻辑
pass
💡 实际应用示例
机械臂拾放任务
from isaacsim.core.api import World
from isaacsim.robot.manipulators import SingleManipulator
from isaacsim.robot.manipulators.grippers import ParallelGripper
from isaacsim.robot.manipulators.controllers import PickPlaceController
import numpy as np
class RobotPickPlace:
def __init__(self):
# 创建环境
self.world = World()
self.world.scene.add_default_ground_plane()
# 创建机器人
self.robot = self.world.scene.add(SingleManipulator(
prim_path="/World/Robot",
name="pick_place_robot"
))
# 创建抓手
self.gripper = ParallelGripper(
end_effector_prim_path="/World/Robot/gripper"
)
# 创建拾放控制器
self.controller = PickPlaceController(
name="pick_place_controller",
gripper=self.gripper,
robot_articulation=self.robot
)
def pick_and_place(self, pick_pos, place_pos):
# 重置环境
self.world.reset()
# 执行拾放动作
while not self.controller.is_done():
current_positions = self.robot.get_joint_positions()
action = self.controller.forward(
picking_position=pick_pos,
placing_position=place_pos,
current_joint_positions=current_positions,
end_effector_offset=np.array([0, 0, 0.1])
)
self.robot.apply_action(action)
self.world.step(render=True)
print("Pick and place task completed!")
def run(self):
# 定义拾放位置
pick_position = np.array([0.3, 0.0, 0.05])
place_position = np.array([0.5, 0.0, 0.1])
# 执行任务
self.pick_and_place(pick_position, place_position)
# 运行示例
demo = RobotPickPlace()
demo.run()
轮式机器人导航
from isaacsim.core.api import World
from isaacsim.robot.wheeled_robots import DifferentialController
import numpy as np
class DifferentialRobotNavigation:
def __init__(self):
self.world = World()
# 创建轮式机器人(假设已定义)
self.robot = self.world.scene.add(DifferentialRobot(
prim_path="/World/DiffRobot",
wheel_radius=0.05,
wheel_base=0.2
))
# 创建控制器
self.controller = DifferentialController(
name="nav_controller",
wheel_radius=0.05,
wheel_base=0.2
)
def navigate_to_target(self, target_position):
self.world.reset()
while True:
# 获取当前状态
current_pos, current_rot = self.robot.get_world_pose()
# 计算到目标的向量
to_target = target_position - current_pos[:2]
distance = np.linalg.norm(to_target)
# 如果到达目标,停止
if distance < 0.1:
break
# 计算所需角度
target_angle = np.arctan2(to_target[1], to_target[0])
current_angle = self.get_yaw_from_quaternion(current_rot)
angle_diff = self.normalize_angle(target_angle - current_angle)
# 生成控制命令
linear_vel = min(distance * 2.0, 1.0) # 比例控制
angular_vel = angle_diff * 3.0
command = np.array([linear_vel, angular_vel])
action = self.controller.forward(command)
# 应用控制
self.robot.apply_action(action)
self.world.step(render=True)
def normalize_angle(self, angle):
while angle > np.pi:
angle -= 2 * np.pi
while angle < -np.pi:
angle += 2 * np.pi
return angle
def get_yaw_from_quaternion(self, quat):
# 从四元数计算yaw角
siny_cosp = 2 * (quat[3] * quat[2] + quat[0] * quat[1])
cosy_cosp = 1 - 2 * (quat[1] * quat[1] + quat[2] * quat[2])
return np.arctan2(siny_cosp, cosy_cosp)
# 运行示例
nav_robot = DifferentialRobotNavigation()
target = np.array([5.0, 3.0]) # 目标位置
nav_robot.navigate_to_target(target)
全向轮机器人控制
class HolonomicRobotController:
def __init__(self):
self.world = World()
# 创建麦轮机器人(假设已定义)
self.robot = self.world.scene.add(MecanumRobot(
prim_path="/World/MecanumRobot"
))
# 创建全向控制器
self.controller = HolonomicController(
name="mecanum_controller",
wheel_dof_names=[
"wheel_fl", "wheel_fr",
"wheel_bl", "wheel_br"
]
)
# 设置麦轮属性
self.setup_mecanum_properties()
def setup_mecanum_properties(self):
# 设置轮子位置和滚轮角度
wheel_positions = np.array([
[0.2, 0.2], # 前左
[0.2, -0.2], # 前右
[-0.2, 0.2], # 后左
[-0.2, -0.2] # 后右
])
roller_angles = np.array([
np.pi/4, -np.pi/4,
-np.pi/4, np.pi/4
])
# 配置控制器
self.controller.setup_mecanum_wheels(
wheel_positions, roller_angles
)
def move_omnidirectional(self, forward, lateral, rotate):
# 生成控制命令
command = np.array([forward, lateral, rotate])
action = self.controller.forward(command)
# 应用控制
self.robot.apply_action(action)
def run_demo(self):
self.world.reset()
# 前进
for _ in range(100):
self.move_omnidirectional(1.0, 0.0, 0.0)
self.world.step(render=True)
# 侧移
for _ in range(100):
self.move_omnidirectional(0.0, 1.0, 0.0)
self.world.step(render=True)
# 旋转
for _ in range(100):
self.move_omnidirectional(0.0, 0.0, 1.0)
self.world.step(render=True)
# 组合运动
for _ in range(100):
self.move_omnidirectional(0.5, 0.5, 0.5)
self.world.step(render=True)
# 运行示例
holonomic_demo = HolonomicRobotController()
holonomic_demo.run_demo()
🔧 常见问题解决
1. 关节控制不响应
# 检查关节配置
def check_articulation(robot):
print(f"DOF Count: {robot.num_dof}")
print(f"Joint Names: {robot.dof_names}")
print(f"Joint Positions: {robot.get_joint_positions()}")
print(f"Joint Velocities: {robot.get_joint_velocities()}")
# 设置合理的增益
robot.set_gains(
kps=np.array([1000] * robot.num_dof),
kds=np.array([100] * robot.num_dof)
)
2. 轮式机器人滑动问题
# 设置合适的物理材质
from isaacsim.core.api.materials import PhysicsMaterial
# 创建高摩擦材质
tire_material = PhysicsMaterial(
prim_path="/World/Materials/TireMaterial",
static_friction=1.5,
dynamic_friction=1.0,
restitution=0.0
)
# 应用到轮子
for wheel in robot.get_wheel_prims():
wheel.apply_physics_material(tire_material)
3. 抓手精度问题
# 优化抓手控制精度
def fine_tune_gripper(gripper):
# 减小增量步长
gripper.set_action_deltas(np.array([0.0001, 0.0001]))
# 增加控制频率
gripper.set_control_frequency(240) # Hz
# 使用位置控制模式
gripper.set_effort_modes("position")
📚 API继承关系
BaseClass
↓
SingleXFormPrim
↓
SingleArticulation
↓
SingleManipulator
↓
Robot类 (Franka, UR10 等)
最后更新: 2025-05-10
版本: Isaac Sim 4.5.0
Isaac Sim API - 控制器
📋 概述
各种控制器实现,包括关节控制、抓取控制、运动控制等。提供灵活的控制器架构和预定义控制算法。
🎯 主要类
🔧 关节控制器 - ArticulationController
位置: isaacsim.core.api.controllers.ArticulationController
功能说明: PD控制器,支持位置、速度和力矩控制所有自由度。
代码示例:
from isaacsim.core.api.controllers import ArticulationController
from isaacsim.core.api import World
import numpy as np
# 创建世界和机器人
world = World()
robot = world.scene.add(Robot(prim_path="/World/Robot"))
# 创建关节控制器
controller = ArticulationController(
name="robot_controller",
articulation_view=robot.get_articulation_view()
)
# 初始化控制器
controller.initialize()
# 设置PD增益
kps = np.array([100, 100, 100, 50, 50, 50, 10]) # 位置增益
kds = np.array([10, 10, 10, 5, 5, 5, 1]) # 阻尼增益
controller.set_gains(kps=kps, kds=kds)
# 设置关节目标位置
target_positions = np.array([0, -1.57, 0, -2.0, 0, 1.57, 0.7])
action = ArticulationAction(joint_positions=target_positions)
controller.apply_action(action)
# 运行控制循环
for i in range(1000):
world.step(render=True)
# 可以实时调整目标
if i % 100 == 0:
current_pos = robot.get_joint_positions()
print(f"Current joint positions: {current_pos}")
关键方法:
-
apply_action(self, control_actions: ArticulationAction) → None- 应用关节控制动作
- 支持位置、速度、力矩控制
-
get_applied_action(self) → ArticulationAction- 获取最后应用的动作
-
set_gains(self, kps=None, kds=None, save_to_usd=False) → None- 设置PD控制器增益
- kps: 位置增益
- kds: 阻尼增益
-
set_max_efforts(self, values: numpy.ndarray, joint_indices=None) → None- 设置最大力矩
-
set_effort_modes(self, mode: str, joint_indices=None) → None- 设置控制模式("force", "acceleration")
-
get_joint_limits(self) → Tuple[numpy.ndarray, numpy.ndarray]- 获取关节限位
-
get_effort_modes(self) → List[str]- 获取当前控制模式
📦 抓取控制器基类 - BaseGripperController
位置: isaacsim.core.api.controllers.BaseGripperController
功能说明: 抓取器控制的基础接口。
代码示例:
from isaacsim.core.api.controllers import BaseGripperController
from isaacsim.robot.manipulators.grippers import ParallelGripper
class CustomGripperController(BaseGripperController):
def __init__(self, gripper):
super().__init__(name="custom_gripper_controller")
self.gripper = gripper
def forward(self, action: str, current_joint_positions: np.ndarray) → ArticulationAction:
"""实现抓取逻辑"""
if action == "open":
return self.open(current_joint_positions)
elif action == "close":
return self.close(current_joint_positions)
else:
raise ValueError(f"Unknown action: {action}")
def open(self, current_joint_positions: np.ndarray) → ArticulationAction:
"""打开抓手"""
# 返回打开动作
return ArticulationAction(
joint_positions=self.gripper.joint_opened_positions
)
def close(self, current_joint_positions: np.ndarray) → ArticulationAction:
"""关闭抓手"""
# 返回关闭动作
return ArticulationAction(
joint_positions=self.gripper.joint_closed_positions
)
# 使用自定义控制器
gripper = ParallelGripper(end_effector_prim_path="/World/Robot/gripper")
controller = CustomGripperController(gripper)
# 控制抓手
action = controller.forward("close", robot.get_joint_positions())
robot.apply_action(action)
关键方法:
-
forward(self, action: str, current_joint_positions: numpy.ndarray) → ArticulationAction- 主控制方法
-
open(self, current_joint_positions: numpy.ndarray) → ArticulationAction- 打开抓手
-
close(self, current_joint_positions: numpy.ndarray) → ArticulationAction- 关闭抓手
-
reset(self) → None- 重置控制器状态
📦 拾放控制器 - PickPlaceController
位置: isaacsim.robot.manipulators.controllers.PickPlaceController
功能说明: 执行拾放任务的状态机控制器。
代码示例:
from isaacsim.robot.manipulators.controllers import PickPlaceController
from isaacsim.robot.manipulators.grippers import ParallelGripper
# 创建拾放控制器
pick_place_controller = PickPlaceController(
name="pick_place",
gripper=gripper,
robot_articulation=robot,
events_dt=[1.0, 1.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], # 各阶段持续时间
end_effector_initial_height=0.3, # 末端执行器初始高度
end_effector_grasp_height=0.03 # 抓取高度
)
# 执行拾放任务
picking_position = np.array([0.3, 0.0, 0.05]) # 拾取位置
placing_position = np.array([0.5, 0.0, 0.1]) # 放置位置
world.reset()
# 主控制循环
while not pick_place_controller.is_done():
current_positions = robot.get_joint_positions()
# 生成控制动作
action = pick_place_controller.forward(
picking_position=picking_position,
placing_position=placing_position,
current_joint_positions=current_positions,
end_effector_offset=np.array([0, 0, 0.1]), # 末端偏移
end_effector_orientation=np.array([0, 1, 0, 0]) # 末端方向
)
# 应用动作
robot.apply_action(action)
# 执行仿真步进
world.step(render=True)
# 获取当前阶段
current_event = pick_place_controller.get_current_event()
print(f"Current phase: {current_event}")
print("Pick and place task completed!")
状态机阶段:
- Phase 0: 移动到拾取位置上方
- Phase 1: 下降到拾取高度
- Phase 2: 等待稳定
- Phase 3: 关闭抓手
- Phase 4: 抬起物体
- Phase 5: 移动到放置位置上方
- Phase 6: 下降到放置高度
- Phase 7: 打开抓手
- Phase 8: 抬起末端执行器
- Phase 9: 返回初始位置
关键方法:
-
forward(self, picking_position, placing_position, current_joint_positions, ...) → ArticulationAction- 执行当前阶段的控制
-
is_done(self) → bool- 检查任务是否完成
-
get_current_event(self) → int- 获取当前执行阶段
-
pause(self) → None- 暂停状态机
-
is_paused(self) → bool- 检查是否暂停
-
reset(self) → None- 重置状态机
📚 堆叠控制器 - StackingController
位置: isaacsim.robot.manipulators.controllers.StackingController
功能说明: 管理多物体堆叠任务的控制器。
代码示例:
from isaacsim.robot.manipulators.controllers import StackingController
# 创建堆叠控制器
stacking_controller = StackingController(
name="stacking_controller",
pick_place_controller=pick_place_controller,
picking_order_cube_names=["cube1", "cube2", "cube3"],
robot_observation_name="robot_observations"
)
# 重置控制器
stacking_controller.reset(picking_order_cube_names=["cube1", "cube2", "cube3"])
# 执行堆叠任务
while not stacking_controller.is_done():
# 获取观测值
observations = world.scene.get_observations()
# 生成控制动作
action = stacking_controller.forward(
observations=observations,
end_effector_orientation=np.array([0, 1, 0, 0])
)
# 应用动作
robot.apply_action(action)
world.step(render=True)
# 监控进度
current_cube = stacking_controller.get_current_cube()
print(f"Currently stacking: {current_cube}")
print("Stacking task completed!")
关键方法:
-
forward(self, observations: dict, end_effector_orientation=None, end_effector_offset=None) → ArticulationAction- 执行堆叠逻辑
-
is_done(self) → bool- 检查堆叠任务是否完成
-
reset(self, picking_order_cube_names=None) → None- 重置堆叠任务
📊 动作数据结构
ArticulationAction 类
位置: isaacsim.core.utils.types.ArticulationAction
功能说明: 表示关节动作的数据结构。
代码示例:
from isaacsim.core.utils.types import ArticulationAction
import numpy as np
# 创建关节动作
action = ArticulationAction(
joint_positions=np.array([0, 1, 0, -1, 0, 1, 0]), # 目标位置
joint_velocities=np.array([0, 0, 0, 0, 0, 0, 0]), # 目标速度
joint_efforts=None # 目标力矩
)
# 访问数据
print(f"Joint positions: {action.joint_positions}")
print(f"Joint velocities: {action.joint_velocities}")
# 获取单个关节动作
dof_action = action.get_dof_action(index=2)
print(f"DOF 2 action: {dof_action}")
# 转换为字典
action_dict = action.get_dict()
print(f"Action as dict: {action_dict}")
# 获取动作长度
length = action.get_length()
print(f"Action length: {length}")
关键方法:
-
get_dict(self) → dict- 转换为字典格式
-
get_dof_action(self, index: int) → dict- 获取特定自由度的动作
-
get_length(self) → Optional[int]- 获取动作维度
ArticulationActions 类(批处理)
位置: isaacsim.core.utils.types.ArticulationActions
功能说明: 批量关节动作数据结构。
代码示例:
from isaacsim.core.utils.types import ArticulationActions
import numpy as np
# 创建批量动作
batch_actions = ArticulationActions(
joint_positions=np.array([
[0, 1, 0, -1, 0, 1, 0],
[0.1, 1.1, 0.1, -1.1, 0.1, 1.1, 0.1]
]), # 2个动作
joint_velocities=None,
joint_efforts=None,
joint_indices=np.array([0, 1, 2, 3, 4, 5, 6]) # 指定关节索引
)
# 访问数据
print(f"Batch size: {batch_actions.batch_size}")
print(f"Joint positions shape: {batch_actions.joint_positions.shape}")
💡 实际应用示例
自定义PD控制器
class CustomPDController:
def __init__(self, robot):
self.robot = robot
self.target_positions = None
self.target_velocities = None
# PD参数
self.kp = np.array([1000, 1000, 500, 500, 200, 200, 100])
self.kd = np.array([100, 100, 50, 50, 20, 20, 10])
# 积分项(PID)
self.ki = np.array([1, 1, 0.5, 0.5, 0.2, 0.2, 0.1])
self.error_integral = np.zeros(7)
# 最大力矩限制
self.max_efforts = np.array([100, 100, 50, 50, 20, 20, 10])
def set_target(self, positions, velocities=None):
"""设置目标位置和速度"""
self.target_positions = positions
self.target_velocities = velocities if velocities is not None else np.zeros_like(positions)
def compute_torques(self, dt=1/60.0):
"""计算关节力矩"""
# 获取当前状态
current_positions = self.robot.get_joint_positions()
current_velocities = self.robot.get_joint_velocities()
# 计算误差
position_error = self.target_positions - current_positions
velocity_error = self.target_velocities - current_velocities
# 更新积分项
self.error_integral += position_error * dt
# PID控制
torques = (self.kp * position_error +
self.kd * velocity_error +
self.ki * self.error_integral)
# 应用力矩限制
torques = np.clip(torques, -self.max_efforts, self.max_efforts)
return torques
def step(self):
"""执行一步控制"""
if self.target_positions is None:
return
# 计算力矩
torques = self.compute_torques()
# 应用控制
action = ArticulationAction(joint_efforts=torques)
self.robot.apply_action(action)
# 使用示例
controller = CustomPDController(robot)
controller.set_target(target_positions)
for i in range(1000):
controller.step()
world.step(render=True)
任务空间控制器
class TaskSpaceController:
def __init__(self, robot):
self.robot = robot
self.end_effector_link = "end_effector"
# 控制增益
self.position_gain = 1000
self.orientation_gain = 100
# 雅可比矩阵相关
self.jacobian = None
self.joint_damping = 0.01
def compute_jacobian(self):
"""计算雅可比矩阵"""
# 这里需要根据具体机器人实现
# 一般通过机器人模型API获取
pass
def compute_inverse_kinematics(self, target_pose):
"""使用雅可比矩阵求逆运动学"""
# 获取当前末端位姿
current_pose = self.robot.get_end_effector_pose()
# 计算位姿误差
position_error = target_pose[:3] - current_pose[:3]
orientation_error = self.compute_orientation_error(target_pose[3:], current_pose[3:])
# 组合误差
task_error = np.concatenate([
self.position_gain * position_error,
self.orientation_gain * orientation_error
])
# 计算雅可比矩阵
self.compute_jacobian()
# 伪逆法求解关节速度
joint_velocities = np.linalg.pinv(
self.jacobian + self.joint_damping * np.eye(self.jacobian.shape[1])
) @ task_error
return joint_velocities
def compute_orientation_error(self, target_quat, current_quat):
"""计算方向误差"""
# 四元数误差计算
# 这里简化实现,实际应该用四元数乘法
return target_quat - current_quat
def control_to_pose(self, target_pose):
"""控制到目标位姿"""
# 计算关节速度
joint_velocities = self.compute_inverse_kinematics(target_pose)
# 应用速度控制
action = ArticulationAction(joint_velocities=joint_velocities)
self.robot.apply_action(action)
# 使用示例
task_controller = TaskSpaceController(robot)
# 设置目标位姿 [x, y, z, qx, qy, qz, qw]
target_pose = np.array([0.5, 0.0, 0.5, 0, 0, 0, 1])
# 执行控制
for i in range(1000):
task_controller.control_to_pose(target_pose)
world.step(render=True)
行为树控制器
from enum import Enum
class TaskStatus(Enum):
RUNNING = 0
SUCCESS = 1
FAILURE = 2
class BehaviorTreeNode:
def __init__(self, name):
self.name = name
self.status = TaskStatus.RUNNING
def tick(self, blackboard):
"""执行节点逻辑"""
raise NotImplementedError
class SequenceNode(BehaviorTreeNode):
def __init__(self, name, children):
super().__init__(name)
self.children = children
self.current_child = 0
def tick(self, blackboard):
"""按顺序执行子节点"""
if self.current_child >= len(self.children):
self.status = TaskStatus.SUCCESS
return self.status
child_status = self.children[self.current_child].tick(blackboard)
if child_status == TaskStatus.SUCCESS:
self.current_child += 1
if self.current_child >= len(self.children):
self.status = TaskStatus.SUCCESS
elif child_status == TaskStatus.FAILURE:
self.status = TaskStatus.FAILURE
self.current_child = 0 # 重置
else:
self.status = TaskStatus.RUNNING
return self.status
class MoveToPositionNode(BehaviorTreeNode):
def __init__(self, name, target_position):
super().__init__(name)
self.target_position = target_position
self.threshold = 0.01
def tick(self, blackboard):
"""移动到目标位置"""
robot = blackboard["robot"]
controller = blackboard["controller"]
# 获取当前位置
current_pos, _ = robot.get_end_effector_pose()
# 计算距离
distance = np.linalg.norm(current_pos[:3] - self.target_position)
if distance < self.threshold:
self.status = TaskStatus.SUCCESS
else:
# 生成移动命令
direction = self.target_position - current_pos[:3]
direction = direction / np.linalg.norm(direction)
# 计算关节目标
target_pose = np.concatenate([self.target_position, [0, 0, 0, 1]])
joint_vels = controller.compute_inverse_kinematics(target_pose)
# 应用控制
action = ArticulationAction(joint_velocities=joint_vels)
robot.apply_action(action)
self.status = TaskStatus.RUNNING
return self.status
class GripperNode(BehaviorTreeNode):
def __init__(self, name, action): # action: "open" or "close"
super().__init__(name)
self.action = action
def tick(self, blackboard):
gripper_controller = blackboard["gripper_controller"]
robot = blackboard["robot"]
# 执行抓手动作
current_positions = robot.get_joint_positions()
action = gripper_controller.forward(self.action, current_positions)
robot.apply_action(action)
# 等待动作完成
# 这里简化,实际应检查抓手状态
self.status = TaskStatus.SUCCESS
return self.status
# 构建行为树
behavior_tree = SequenceNode("pick_and_place", [
MoveToPositionNode("move_to_pick", np.array([0.3, 0.0, 0.05])),
GripperNode("open_gripper", "open"),
MoveToPositionNode("approach_object", np.array([0.3, 0.0, 0.01])),
GripperNode("close_gripper", "close"),
MoveToPositionNode("lift_object", np.array([0.3, 0.0, 0.1])),
MoveToPositionNode("move_to_place", np.array([0.5, 0.0, 0.1])),
MoveToPositionNode("lower_object", np.array([0.5, 0.0, 0.01])),
GripperNode("release_object", "open"),
MoveToPositionNode("move_away", np.array([0.5, 0.0, 0.2]))
])
# 初始化黑板
blackboard = {
"robot": robot,
"controller": task_controller,
"gripper_controller": gripper_controller
}
# 执行行为树
while behavior_tree.status == TaskStatus.RUNNING:
behavior_tree.tick(blackboard)
world.step(render=True)
if behavior_tree.status == TaskStatus.SUCCESS:
print("Task completed successfully!")
else:
print("Task failed!")
🔧 常见问题解决
1. 控制精度问题
def improve_control_precision():
# 增加PD增益
controller.set_gains(
kps=np.array([2000, 2000, 1500, 1000, 500, 500, 200]),
kds=np.array([200, 200, 150, 100, 50, 50, 20])
)
# 增加控制频率
world = World(physics_dt=1/240.0) # 从60Hz增加到240Hz
# 使用更精确的积分器
physics_context = world.get_physics_context()
physics_context.set_solver_type("PGS") # 或 "TGS"
physics_context.set_solver_iterations(4)
2. 控制抖动问题
class SmoothController:
def __init__(self, controller):
self.controller = controller
self.filter_factor = 0.9 # 低通滤波系数
self.last_action = None
def apply_action(self, action):
"""应用平滑后的动作"""
if self.last_action is None:
self.last_action = action
else:
# 低通滤波
if action.joint_positions is not None:
action.joint_positions = (
self.filter_factor * self.last_action.joint_positions +
(1 - self.filter_factor) * action.joint_positions
)
self.last_action = action
self.controller.apply_action(action)
3. 控制器状态管理
class ControllerManager:
def __init__(self):
self.controllers = {}
self.active_controller = None
def add_controller(self, name, controller):
"""添加控制器"""
self.controllers[name] = controller
def switch_controller(self, name):
"""切换控制器"""
if name in self.controllers:
if self.active_controller:
self.active_controller.reset()
self.active_controller = self.controllers[name]
print(f"Switched to controller: {name}")
else:
raise ValueError(f"Controller {name} not found")
def update(self, *args, **kwargs):
"""更新当前控制器"""
if self.active_controller:
return self.active_controller.forward(*args, **kwargs)
return None
# 使用示例
manager = ControllerManager()
manager.add_controller("pick_place", pick_place_controller)
manager.add_controller("stacking", stacking_controller)
# 根据任务切换控制器
manager.switch_controller("pick_place")
# ... 执行拾放任务
manager.switch_controller("stacking")
# ... 执行堆叠任务
📚 控制器模式比较
| 控制模式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 位置控制 | 精确定位任务 | 精度高,稳定 | 响应慢,刚性强 |
| 速度控制 | 轨迹跟踪 | 响应快,平滑 | 精度稍差 |
| 力控制 | 接触任务 | 柔顺性好 | 稳定性要求高 |
| 混合控制 | 复杂任务 | 灵活性高 | 实现复杂 |
🎯 控制器设计准则
- 模块化设计: 每个控制器专注于特定任务
- 状态管理: 清晰的状态转换逻辑
- 参数可调: 提供可调节的控制参数
- 错误处理: 优雅处理异常情况
- 性能优化: 考虑实时性要求
最后更新: 2025-05-10
版本: Isaac Sim 4.5.0