目录

1 添加物理属性

1.1 学习目标

1.2 添加魔方

1.3 添加刚体属性

1.4 添加碰撞属性

1.5 添加质量

1.6 可视化碰撞形状

1.7 自定义碰撞体

1.8 添加物理材质

2 数据记录

2.1 学习目标

2.2 录制数据

2.3 代码概览

2.3.1 日志记录

2.3.2 数据检查

2.4 回放数据

2.5 代码概览


1 添加物理属性

1.1 学习目标

展示如何向场景中添加物体,并为仿真运行配置这些物体。

1.2 添加魔方

(1)创建新场景

在Isaac Sim中点击File(文件)选项卡,然后点击New Stage(新建场景)。

(2)从资源库拖入物体

在Content Browser(内容浏览器)中,导航至Isaac Sim > Props > Rubiks_Cube > rubiks_cube.usd,然后将rubiks_cube.usd文件拖拽到场景(Stage)中。这会以“有效载荷(Payload)”的形式将魔方添加到场景里。

(3)设置位置

左键点击选中魔方,在Properties(属性)面板中,将Position(位置) 设置为 (0, 0, 0.1),相当于把Z平移调整至0.1(这边可以左右鼠标滑动至数值)

(4)添加地面

在场景面板中,右键点击Create > Isaac > Environment > Flat Grid来创建一个平坦的地面。

(5)开始仿真

点击左侧工具栏的PLAY(运行)。发现魔方并没有掉落到地面上,这是因为该魔方此时还不是一个“刚体(Rigid Body)”。

(6)停止仿真

点击 STOP(停止)。

1.3 添加刚体属性

(1)右键点击魔方(Rubik’s Cube),选择Add > Physics > Rigid Body。这会为魔方添加刚体属性,使其受物理引擎影响(例如受重力作用)。

(2)开始仿真

点击PLAY开始运行,发现魔方直接穿过地面掉下去了。这是因为魔方虽然有了重力(刚体),但还没有“碰撞形状”(Collision Shape),物理引擎不知道它什么时候撞到了地面。

(3)停止仿真

点击STOP。

1.4 添加碰撞属性

(1)添加碰撞预设

右键点击魔方(Rubik’s Cube),选择Add > Physics > Collider Presets。这会为魔方添加碰撞属性,使其能与其他物体(如地面、机械臂)发生物理接触。

(2)开始仿真

点击PLAY开始运行,看到魔方稳稳地掉落在地面上,不再穿模。

(3)停止仿真

点击 STOP。

1.5 添加质量

(1)物理属性配置

除了碰撞属性外,还可以为魔方添加质量 (Mass)、惯性 (Inertia) 和质心 (Center of Mass),以配置其物理特性。

(2)添加质量属性

右键点击魔方,选择Add > Physics > Mass,这会为魔方增加一个质量属性。

(3)设置栏目,将Mass数值设置为0.1,使其重量变为100克。

PS.质量为0、密度未设定时,仿真计算默认密度1000kg/m^3、并根据体积和密度默认值自动计算质量。

1.6 可视化碰撞形状

(1)开启可视化

右键点击视口(Viewport)左上角的眼睛图标(Eye),选择Show By Type > Physics > Colliders > All。这会显示场景中所有物体的碰撞形状。

(2)地面的碰撞体是粉红色的:这表示它是一个静态物体(Static Object),它固定在空间中,不会移动,专门用来阻挡其他东西

魔方的碰撞体是绿色的:这表示它是一个动态物体(Dynamic Object)。它受重力影响会掉落,并且可以被撞开或抓取。

1.7 自定义碰撞体
通过给方形的魔方穿上一层“球形外衣”,让它像球一样滚动。

(1)删除旧碰撞体

左键点击路径为World/rubiks_cube/RubikCube 的魔方网格(Mesh),向下滚动到 Physics/Collider栏目,点击右侧的x删除当前的碰撞体。如果没有就忽略。

(2)创建球体形状

选中RubikCube网格,选择菜单Create > Shape > Sphere。这会在魔方周围添加一个球体形状。注意这边一定要将Sphere嵌套在RubikCube内,并且将Sphere坐标设置为(0,0,0)。

(3)调整球体大小

向下滚动到Geometry栏目,将Radius(半径) 设置为 0.07,使球体缩小到刚好包裹住魔方。

(4)添加碰撞属性

选中刚才创建的球体,选择Add > Physics > Collider Presets。

(5)隐藏球体视觉效果

在右上角的Stage面板中,点击球体右侧的小眼睛图标。这样在仿真时只会看到魔方,而看不见那个球。

(6)设置斜坡

选中FlatGrid(地面),点击属性面板Transform右侧的Toggle Offset Mode图标,然后将 Rotation(旋转) 设置为 (10, 0, 0),使地面倾斜 10 度。

(7)开始仿真

点击PLAY,会看到原本是方形的魔方竟然在地面上滚了起来。

(8)停止仿真

点击STOP。

1.8 添加物理材质

(1)调整位置

左键点击魔方,在属性面板中将Position(位置/Translate) 设置为 (0, 0, 1),将其移动到更高的地方。

(2)创建材质

右键点击魔方,选择Create > Physics > Physics Material > Rigid Body Material。这会为魔方添加物理材质属性。将生成的材质文件拖动到World/rubiks_cube/Looks 文件夹中以便管理。

(3)设置弹性

在属性面板中,向下滚动到Physics Material 栏目,将Restitution(恢复系数/弹性) 设置为 1。这会使物体具有完美弹性(即碰撞后不损失动能,会持续弹跳)。

(4)绑定材质到球体

选中之前创建的Sphere碰撞体。在属性面板中找到Physics > Physics Material on Selected Material栏目,点击选择框,选中刚才创建在 /World/rubiks_cube/Looks/PhysicsMaterial的材质。

(5)开始仿真

点击PLAY。你会看到魔方掉落在地并像皮球一样剧烈弹跳。

(6)停止仿真

点击 STOP。

2 数据记录

2.1 学习目标

       展示如何在NVIDIA Isaac Sim中使用DataLogger(数据记录器)记录数据并进行回放。完成本教程后,你将能够:

  • 在NVIDIA Isaac Sim的工作流中记录各种状态(States)和动作(Actions)。

  • 对记录下来的数据进行回放,以便分析或调试。

2.2 录制数据

按照以下步骤,使用“跟随目标”(Follow Target)扩展示例来录制数据

(1)打开示例窗口

依次点击顶部菜单栏的Windows > Examples > Robotics Examples,打开“机器人示例”窗口。选择Manipulation > Follow Target Task来启用该任务示例。

(2)加载场景

在World Controls(世界控制)下方,点击LOAD按钮。此时场景中会加载出一台Franka 机械臂和一个作为视觉目标的方块。

(3)设置保存路径

在Follow Target 菜单的 Data Logging(数据记录)部分,选择用于保存JSON 数据文件的输出目录。这边可以默认保存路径、也可自定。

(4)启动任务

在Task Controls(任务控制)下方,找到Follow Target。

(5)开始录制

点击START按钮。

(6)进行交互

在场景中移动那个视觉目标方块。会看到Franka机械臂通过RMPFlowController控制器自动跟随方块移动。

(7)保存并结束

移动几秒钟后,点击SAVE DATA(保存数据)。

(8)点击File > New From Stage Template > Empty(文件 > 从场景模板新建 > 空白)来创建一个干净的新场景。

(9)确认结果

录制好的数据文件(JSON 格式)现在应该已经保存在Output Directory文本框中指定的目录下了。

2.3 代码概览
2.3.1 日志记录

数据记录:

def _on_logging_event(self, val):
    world = self.get_world()
    data_logger = world.get_data_logger() # a DataLogger object is defined in the World by default
    if not world.get_data_logger().is_started():
        robot_name = self._task_params["robot_name"]["value"]
        target_name = self._task_params["target_name"]["value"]

        # A data logging function is called at every time step index if the data logger is started already.
        # We define the function here. The tasks and scene are passed to this function when called.

        def frame_logging_func(tasks, scene):
            return {
                "joint_positions": scene.get_object(robot_name).get_joint_positions().tolist(),# save data as lists since its a JSON file.
                "applied_joint_positions": scene.get_object(robot_name)
                .get_applied_action()
                .joint_positions.tolist(),
                "target_position": scene.get_object(target_name).get_world_pose()[0].tolist(),
            }

        data_logger.add_data_frame_logging_func(frame_logging_func) # adds the function to be called at each physics time step.
    if val:
        data_logger.start() # starts the data logging
    else:
        data_logger.pause()
    return

数据存储:

    def _on_save_data_event(self, log_path):
        world = self.get_world()
        data_logger = world.get_data_logger()
        data_logger.save(log_path=log_path)
        data_logger.reset()
        return
2.3.2 数据检查

DataLogger(数据记录器)负责记录每一帧数据所对应的秒数(时间)以及时间步长(Time Step)。

根据存储路径找到XX.json文件,可以看到类似下面的数据:

{"Isaac Sim Data": [{"current_time": 1.4833334106951952, "current_time_step": 89, "data": {"joint_positions": [0.07561380416154861, -1.2318825721740723, 0.11344202607870102, -2.4259397983551025, 0.0970514565706253, 1.6226640939712524, 0.8470714688301086, 4.0, 3.997776985168457], "applied_joint_positions": [0.07291083037853241, -1.2202218770980835, 0.1190749853849411, -2.39223575592041, 0.11230156570672989, 1.3975754976272583, 0.9029524326324463, 4.0, 4.0], "target_position": [0.0, 10.0, 70.0]}}, {"current_time": 1.5000000782310963, "current_time_step": 90, "data": {"joint_positions": [0.07484950870275497, -1.2287049293518066, 0.11509127914905548, -2.416816234588623, 0.09880664199590683, 1.603981614112854, 0.8490884304046631, 4.0, 3.997793197631836], "applied_joint_positions": [0.07221028953790665, -1.2172484397888184, 0.1205318346619606, -2.3833296298980713, 0.11395926028490067, 1.3804354667663574, 0.9063650369644165, 4.0, 4.0], "target_position": [0.0, 10.0, 70.0]}}, {"current_time": 1.5166667457669973, "current_time_step": 91, "data": {"joint_positions": [0.07410304993391037, -1.2255841493606567, 0.11668683588504791, -2.4077510833740234, 0.10055229812860489, 1.58543062210083, 0.8511277437210083, 4.0, 3.997816562652588], "applied_joint_positions": [0.07153353840112686, -1.2144113779067993, 0.1219213530421257, -2.3745198249816895, 0.11559101194143295, 1.363703727722168, 0.9096996784210205, 4.0, 4.0], "target_position": [0.0, 10.0, 70.0]}] }
2.4 回放数据

使用Robotics Examples下提供的另一个扩展示例来播放录制好的数据。

(1)打开回放示例窗口

依次点击Windows > Examples > Robotics Examples打开窗口。在菜单中选择并启用 Manipulation > Replay Follow Target Task(回放跟随目标任务)。

(2)加载场景

在World Controls下点击LOAD,加载带有视觉目标方块的Franka机械臂。

(3)指定数据文件

Task Control > Data File更新目标轨迹路径。将其指向在上一步“录制数据”环节中保存的那个JSON文件。

(4)仅回放轨迹 (Replay Trajectory):

点击Data Replay下的Replay Trajectory。此时只会回放机械臂的动作,等待轨迹播放完成。

(5)重置

点击Reset按钮。

(6)回放完整场景 (Replay Scene)

点击Task Control下的Replay Scene。此时会同时回放机械臂的动作以及目标方块的位置移动。

(7)清理场景

点击File > New From Stage Template > Empty 创建一个全新的空白场景。

2.5 代码概览

代码路径:ISAAC_SIM_DIR/exts/isaacsim.examples.interactive/isaacsim/examples/interactive/replay_follow_target/replay_follow_target.py

也可直接点开:

轨迹回放:

async def _on_replay_trajectory_event_async(self, data_file):
    # Loads the data from the json file
    self._data_logger.load(log_path=data_file)
    world = self.get_world()
    await world.play_async()
    # Adds the physics callback to set the joint targets every frame
    world.add_physics_callback("replay_trajectory", self._on_replay_trajectory_step)
    return

def _on_replay_trajectory_step(self, step_size):
    if self._world.current_time_step_index < self._data_logger.get_num_of_data_frames():
        # To sync time steps and get the data frame at the same time step
        data_frame = self._data_logger.get_data_frame(data_frame_index=self._world.current_time_step_index)
        # Applies the same recorded action to the articulation controller
        self._articulation_controller.apply_action(
            ArticulationAction(joint_positions=data_frame.data["applied_joint_positions"])
        )
    return

场景回放:

def _on_replay_scene_step(self, step_size):
    if self._world.current_time_step_index < self._data_logger.get_num_of_data_frames():
        target_name = self._task_params["target_name"]["value"]
        data_frame = self._data_logger.get_data_frame(data_frame_index=self._world.current_time_step_index)
        self._articulation_controller.apply_action(
            ArticulationAction(joint_positions=data_frame.data["applied_joint_positions"])
        )
        # Sets the world position of the goal cube to the same recorded position
        self._world.scene.get_object(target_name).set_world_pose(
            position=np.array(data_frame.data["target_position"])
        )
    return
Logo

电影级数字人,免显卡端渲染SDK,十行代码即可调用,工业级demo免费开源下载!

更多推荐