具身智能入门Isaac Sim——Core API-4
本文摘要介绍了在NVIDIA Isaac Sim中进行物理仿真设置和数据记录的操作流程。主要内容包括: 物理属性设置:详细说明如何添加物体(魔方)、配置刚体属性、碰撞形状和质量,演示了物体从自由下落到碰撞反弹的全过程设置方法,包括调整物理材质实现弹性效果。 数据记录功能:展示如何通过FollowTarget示例记录机械臂运动数据,包括关节位置和目标位置等信息,并保存为JSON格式文件。 数据回放操
目录
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
更多推荐



















所有评论(0)