Orbit 使用指南 03 | 与刚体交互 | Isaac Sim | Omniverse

如是我闻: “在之前的指南中,我们讨论了独立脚本( standalone script)的基本工作原理以及如何在模拟器中生成不同的对象(prims)。在指南03中,我们将展示如何创建并与刚体进行交互。为此,我们使用Orbit中提供的assets.RigidObject类。”

指南03 对应于orbit/source/standalone/tutorials/01_assets目录下的run_rigid_object.py 脚本,让我们先搂一眼完整的代码

# Copyright (c) 2022-2024, The ORBIT Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause"""
This script demonstrates how to create a rigid object and interact with it... code-block:: bash# Usage./orbit.sh -p source/standalone/tutorials/01_assets/run_rigid_object.py"""from __future__ import annotations"""Launch Isaac Sim Simulator first."""import argparsefrom omni.isaac.orbit.app import AppLauncher# add argparse arguments
parser = argparse.ArgumentParser(description="Tutorial on spawning and interacting with a rigid object.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app"""Rest everything follows."""import torchimport omni.isaac.core.utils.prims as prim_utilsimport omni.isaac.orbit.sim as sim_utils
import omni.isaac.orbit.utils.math as math_utils
from omni.isaac.orbit.assets import RigidObject, RigidObjectCfg
from omni.isaac.orbit.sim import SimulationContextdef design_scene():"""Designs the scene."""# Ground-planecfg = sim_utils.GroundPlaneCfg()cfg.func("/World/defaultGroundPlane", cfg)# Lightscfg = sim_utils.DomeLightCfg(intensity=2000.0, color=(0.8, 0.8, 0.8))cfg.func("/World/Light", cfg)# Create separate groups called "Origin1", "Origin2", "Origin3"# Each group will have a robot in itorigins = [[0.25, 0.25, 0.0], [-0.25, 0.25, 0.0], [0.25, -0.25, 0.0], [-0.25, -0.25, 0.0]]for i, origin in enumerate(origins):prim_utils.create_prim(f"/World/Origin{i}", "Xform", translation=origin)# Rigid Objectcone_cfg = RigidObjectCfg(prim_path="/World/Origin.*/Cone",spawn=sim_utils.ConeCfg(radius=0.1,height=0.2,rigid_props=sim_utils.RigidBodyPropertiesCfg(),mass_props=sim_utils.MassPropertiesCfg(mass=1.0),collision_props=sim_utils.CollisionPropertiesCfg(),visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0), metallic=0.2),),init_state=RigidObjectCfg.InitialStateCfg(),)cone_object = RigidObject(cfg=cone_cfg)# return the scene informationscene_entities = {"cone": cone_object}return scene_entities, originsdef run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, RigidObject], origins: torch.Tensor):"""Runs the simulation loop."""# Extract scene entities# note: we only do this here for readability. In general, it is better to access the entities directly from#   the dictionary. This dictionary is replaced by the InteractiveScene class in the next tutorial.cone_object = entities["cone"]# Define simulation steppingsim_dt = sim.get_physics_dt()sim_time = 0.0count = 0# Simulate physicswhile simulation_app.is_running():# resetif count % 250 == 0:# reset counterssim_time = 0.0count = 0# reset root stateroot_state = cone_object.data.default_root_state.clone()# sample a random position on a cylinder around the originsroot_state[:, :3] += originsroot_state[:, :3] += math_utils.sample_cylinder(radius=0.1, h_range=(0.25, 0.5), size=cone_object.num_instances, device=cone_object.device)# write root state to simulationcone_object.write_root_state_to_sim(root_state)# reset bufferscone_object.reset()print("----------------------------------------")print("[INFO]: Resetting object state...")# apply sim datacone_object.write_data_to_sim()# perform stepsim.step()# update sim-timesim_time += sim_dtcount += 1# update bufferscone_object.update(sim_dt)# print the root positionif count % 50 == 0:print(f"Root position (in world): {cone_object.data.root_state_w[:, :3]}")def main():"""Main function."""# Load kit helpersim_cfg = sim_utils.SimulationCfg()sim = SimulationContext(sim_cfg)# Set main camerasim.set_camera_view(eye=[1.5, 0.0, 1.0], target=[0.0, 0.0, 0.0])# Design scenescene_entities, scene_origins = design_scene()scene_origins = torch.tensor(scene_origins, device=sim.device)# Play the simulatorsim.reset()# Now we are ready!print("[INFO]: Setup complete...")# Run the simulatorrun_simulator(sim, scene_entities, scene_origins)if __name__ == "__main__":# run the main functionmain()# close sim appsimulation_app.close()

代码解析

在这个脚本中,我们将主函数main分割成两个独立的函数,这两个函数是在模拟器中设置任何模拟的两个主要步骤:

  1. 场景设计:顾名思义,这部分负责将所有图元( prims)添加到场景中。

  2. 模拟运行:这部分负责步进模拟器,与场景中的原始物体进行互动,例如,改变它们的姿态,并对它们应用指令。

区别这两个步骤是必要的,因为第二步只有在第一步完成并且模拟器被重置后才会发生。一旦模拟器被重置(自动播放模拟),新的(启用物理的)原始物体(prims)不应该被添加到场景中,因为这可能会导致意外的行为。然而,可以通过它们各自的句柄(respective handles)与原始物体(prims)进行互动。

场景设计

与前一个指南类似,我们使用地面平面和光源填充场景。此外,我们使用assets.RigidObject类将一个刚体添加到场景中。这个类负责在输入路径处生成原始物体,并初始化它们对应的刚体物理句柄。

在本指南中,我们使用与“生成对象指南”中的刚体圆锥相似的生成配置,创建一个圆锥形的刚体对象。唯一的区别是,现在我们将生成配置包装进assets.RigidObjectCfg类中。这个类包含有关资产生成策略、默认初始状态和其他元信息的信息。当这个类传递给assets.RigidObject类时,它会在播放模拟时生成对象并初始化相应的物理句柄。

作为例子,关于多次生成刚体原始物体,我们创建了它们的父Xform原始物体,/World/Origin{i},这对应于不同的生成位置。当正则表达式/World/Origin*/Cone传递给assets.RigidObject类时,它会在每个/World/Origin{i}位置生成刚体原始物体。例如,如果场景中存在/World/Origin1/World/Origin2,则刚体原始物体分别在位置/World/Origin1/Cone/World/Origin2/Cone处生成。

    # Create separate groups called "Origin1", "Origin2", "Origin3"# Each group will have a robot in itorigins = [[0.25, 0.25, 0.0], [-0.25, 0.25, 0.0], [0.25, -0.25, 0.0], [-0.25, -0.25, 0.0]]for i, origin in enumerate(origins):prim_utils.create_prim(f"/World/Origin{i}", "Xform", translation=origin)# Rigid Objectcone_cfg = RigidObjectCfg(prim_path="/World/Origin.*/Cone",spawn=sim_utils.ConeCfg(radius=0.1,height=0.2,rigid_props=sim_utils.RigidBodyPropertiesCfg(),mass_props=sim_utils.MassPropertiesCfg(mass=1.0),collision_props=sim_utils.CollisionPropertiesCfg(),visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0), metallic=0.2),),init_state=RigidObjectCfg.InitialStateCfg(),)cone_object = RigidObject(cfg=cone_cfg)

由于我们是想与刚体进行互动,我们将这个实体返回给主函数。然后在模拟循环中使用这个实体与刚体进行互动。在后续的指南中,我们将看到使用scene.InteractiveScene类处理多个场景实体的更便捷方式。

    # return the scene informationscene_entities = {"cone": cone_object}return scene_entities, origins

运行模拟循环

我们修改模拟循环已进行与刚体的互动,包括三个步骤

  1. 在固定时间间隔重置模拟状态、
  2. 步进模拟
  3. 以及更新刚体的内部缓冲区。

为了简便一些,我们从场景的字典中提取出刚体的实体,并将其存储在一个变量中。

在固定时间间隔重置模拟状态

为了重置生成的刚体原始物体的模拟状态,我们需要设置它们的姿态和速度。这两者共同定义了生成的刚体对象的根状态。重要的是要注意,这个状态是在模拟世界框架中定义的,而不是它们的父Xform原始物体的框架。这是因为物理引擎只理解世界框架,而不理解父Xform原始物体的框架。因此,在设置之前,我们需要将刚体原始物体的期望状态转换到世界框架中。

我们使用assets.RigidObject.data.default_root_state属性来获取生成的刚体原始物体的默认根状态。这个默认状态可以从assets.RigidObjectCfg.init_state属性配置,我们在这个指南中将其保留为身份。然后,我们随机化根状态的平移,并使用assets.RigidObject.write_root_state_to_sim()方法设置刚体原始物体的期望状态。正如名称所示,这个方法将刚体原始物体的根状态写入到模拟缓冲区中。

            # reset root stateroot_state = cone_object.data.default_root_state.clone()# sample a random position on a cylinder around the originsroot_state[:, :3] += originsroot_state[:, :3] += math_utils.sample_cylinder(radius=0.1, h_range=(0.25, 0.5), size=cone_object.num_instances, device=cone_object.device)# write root state to simulationcone_object.write_root_state_to_sim(root_state)# reset bufferscone_object.reset()

PS:我这段真看了半天,就只能直译了,我现在的理解是,我们要是想刷新这个圆锥的状态,就必须找出他的根状态,在根状态上做改变,当然如果是单纯的图形的话,在上一级Xform上改动也就可以了,也就是这一段代码,对orbit同样绝望还必须得用的可以私信我,我们一起研究一下

 root_state = cone_object.data.default_root_state.clone()

步进模拟

在步进模拟之前,我们执行assets.RigidObject.write_data_to_sim()方法。这个方法将其他数据,比如外部力,写入模拟缓冲区。在本指南中,我们没有对刚体施加任何外部力,所以这个方法不是必需的。然而,为了完整性,我们将他写在这里。

        # apply sim datacone_object.write_data_to_sim()

更新状态

在步进模拟之后,我们更新刚体原始物体的内部缓冲区,以便在assets.RigidObject.data属性内反映它们的新状态。这是通过使用assets.RigidObject.update()方法完成的。

        # update bufferscone_object.update(sim_dt)

代码执行

现在我们已经讲解了代码,让我们运行脚本并查看结果:

./orbit.sh -p source/standalone/tutorials/01_assets/run_rigid_object.py

这应该会打开一个带有地面平面、灯光和几个绿色圆锥的舞台。圆锥必须从随机高度落下并落在地面上。

在这里插入图片描述

要停止模拟,可以关闭窗口,或在UI中按停止按钮,或在终端中按Ctrl+C。

本指南展示了如何生成刚体对象,并将它们包装在RigidObject类中以初始化它们的物理句柄,这允许设置和获取它们的状态。在下一个指南中,我们将看到如何与由关节连接的刚体对象集合即关节物体进行互动。

愿本文渡一切机器人模拟器苦

以上

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/751682.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

48、C++/堆区动态内存管理 类中特殊成员函数学习20240313

一、设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 代码&#xff1a; #include <iostream>us…

走进volatile的世界,探索它与可见性,有序性,原子性之间的爱恨情仇!

写在开头 在之前的几篇博文中&#xff0c;我们都提到了 volatile 关键字&#xff0c;这个单词中文释义为&#xff1a;不稳定的&#xff0c;易挥发的&#xff0c;在Java中代表变量修饰符&#xff0c;用来修饰会被不同线程访问和修改的变量&#xff0c;对于方法&#xff0c;代码…

Arduino RP2040 LittleFS的使用介绍

Arduino RP2040 LittleFS的使用 &#x1f4cc;RP2040基于Earle F. Philhower, III的开发核心固件&#xff1a;https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json&#x1f388;相关开发文档在线说明&#xff1a;https://ardu…

每日一题——LeetCode2789.合并后数组中的最大元素

方法一 倒序遍历&#xff1a; 将数组倒序过来看&#xff0c;就是从最后一个数开始&#xff0c;如果它前面一个数小于等于它就可以把前面一个数吃掉同时加上前一个数的值形成一个新的数&#xff0c;如果碰到一个更大的数就吃不动了&#xff0c;那么就换那个更大的数去继续吃前面…

ts版本微信小程序在wxml保存文件不刷新页面的解决办法

将project.config.json中的skylineRenderEnable改为false "skylineRenderEnable": false

惯导系统静止初始化方法与代码实现并在gazebo中测试

惯导系统静止初始化方法与代码实现并在gazebo中测试 前言静止初始化方法惯导静止初始化实现代码在gazebo中进行测试 前言 在进行GPS加IMU的组合导航或者Lidar加IMU的组合导航时&#xff0c;用EKF或者ESKF的滤波方法时&#xff0c;需要提前知道惯导的测量噪声、初始零偏、重力方…

POJO简介

文章目录 简介POJO与ELB的区别POJO真正的意思 常见的POJO类DTODAOPOVOEntity 简介 什么是POJO&#xff1f;POJO&#xff08;Plain Ordinary Java Object&#xff09;简单的Java对象&#xff0c;实际就是普通JavaBeans&#xff0c;是为了避免和EJB(EJB是Enterprise Java Beans技…

Ubuntu 22.04 Nvidia Audio2Face Error:Failed to build TensorRT engine

背景 1.在Ubuntu22.04上安装Audio2Face后启动&#xff0c;嘴形不会实时同步。控制台显示如【图一】&#xff1a; 【图一】 2.log日志如下: Error: Error during running command: [‘/home/admin/omniverse/libs/deps/321b626abba810c3f8d1dd4d247d2967/exts/omni.audio2fac…

【论文阅读】DiffSpeaker: Speech-Driven 3D Facial Animation with Diffusion Transformer

DiffSpeaker: 使用扩散Transformer进行语音驱动的3D面部动画 code&#xff1a;GitHub - theEricMa/DiffSpeaker: This is the official repository for DiffSpeaker: Speech-Driven 3D Facial Animation with Diffusion Transformer paper&#xff1a;https://arxiv.org/pdf/…

clickhouse学习笔记01(小滴课堂)

老王经历-数据库架构演变历史 你是否能分清OLTP和OLAP系统 急速掌握-数据库里面行存储和列式存储 新一代列式存储ClickHouse介绍和应用场景说明 Linux服务器容器化部署ClickHouse实战 记得要在安全组里配置开放端口号。 到这我们就安装完了。 简单使用&#xff1a; 创建你的第…

鲲鹏920集成100G网卡RDMA测试说明

1、背景介绍 目前鲲鹏920处理器内集成了两个100G网卡&#xff0c;支持RDMA&#xff08;Roce V2&#xff09;&#xff0c;说明如下 为了测试网卡性能&#xff0c;需要进行RDMA测试&#xff0c;两块鲲鹏920的板卡通过盛科的8180 100G交换芯片实现交换功能。 盛科8180芯片介绍如下…

2.亿级积分数据分库分表:增量数据同步之代码双写,为什么没用Canal?

1.亿级积分数据分库分表&#xff1a;总体方案设计 上一篇博客中写了一下积分数据分库分表的总体方案设计&#xff0c;里面说了采用应用程序代码双写的方式实现的增量数据同步&#xff0c;本篇就对这一块进行一些细化的介绍&#xff0c;包括&#xff1a; 为什么不用Canal监听数…

【S5PV210】 | GPIO编程

【S5PV210】 | GPIO编程 时间:2024年3月17日22:02:32 目录 [TOC] 1.参考 1.s5pv210开发与学习:1.5之裸机汇编流水点灯_s5pv210汇编指令集-CSDN博客 2.s5pv210开发与学习:1.8之裸机蜂鸣器实验_pv210 蜂鸣器-CSDN博客 3.s5pv210开发与学习:1.9之裸机按键控制LED_s5pv210 按键…

机器学习——压缩网络作业

文章目录 任务描述介绍知识蒸馏网络设计 Baseline实践 任务描述 网络压缩&#xff1a;使用小模型模拟大模型的预测/准确性。在这个任务中&#xff0c;需要训练一个非常小的模型来完成HW3&#xff0c;即在food-11数据集上进行分类。 介绍 有许多种网络/模型压缩的类型&#xff0…

代码随想录day23(2)二叉树:从中序与后序遍历序列构造二叉树(leetcode106)

题目要求&#xff1a;根据一棵树的中序遍历与后序遍历构造二叉树。 思路&#xff1a;408的经典题目&#xff0c;思路和手撕的思路差不多&#xff0c;先从后序中找到根节点&#xff0c;再从中序中找到此节点&#xff0c;然后分割成左右子树&#xff0c;记录一下左右子树的节点个…

PyQt5使用

安装Pyqt5信号与槽使用可视化界面编辑UI (Pyside2)ui生成之后的使用(两种方法)1 ui转化为py文件 进行import2 动态调用UI文件 安装Pyqt5 pip install pyqt5-tools这时候我们使用纯代码实现一个简单的界面 from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButto…

2024 年(第 12 届)“泰迪杯”数据挖掘挑战赛——B 题:基于多模态特征融合的图像文本检索完整思路与源代码分享

一、问题背景 随着近年来智能终端设备和多媒体社交网络平台的飞速发展&#xff0c;多媒体数据呈现海量增长 的趋势&#xff0c;使当今主流的社交网络平台充斥着海量的文本、图像等多模态媒体数据&#xff0c;也使得人 们对不同模态数据之间互相检索的需求不断增加。有效的信…

Rocket MQ 从入门到实践

为什么要使用消息队列&#xff0c;解决什么问题&#xff1f;&#xff08;消峰、解藕、异步&#xff09; 消峰填谷 客户端》 网关 〉 消息队列》秒杀服务 异步解耦 消息队列中的重要概念理解。&#xff08;主题、消费组、队列&#xff0c;游标&#xff1f;&#xff09; 主题&…

新手向-从VNCTF2024的一道题学习QEMU Escape

[F] 说在前面 本文的草稿是边打边学边写出来的&#xff0c;文章思路会与一个“刚打完用户态 pwn 题就去打 QEMU Escape ”的人的思路相似&#xff0c;在分析结束以后我又在部分比较模糊的地方加入了一些补充&#xff0c;因此阅读起来可能会相对轻松&#xff08;当然也不排除这是…

Transformer总结

1.Transform背景介绍 1.1Transform的优势 相比于之前占领市场的LSTM和GRU模型&#xff0c;Transformer有两个显著的优势&#xff1a; &#xff08;1&#xff09;Transform能够使用分布式GPU进行并行训练&#xff0c;提升模型训练效率 &#xff08;2&#xff09; 在分析预测…