Orbit 使用指南 10|在机器人上安装传感器 | Isaac Sim | Omniverse

news2024/11/17 7:32:35

如是我闻: 资产类(asset classes)允许我们创建和模拟机器人,而传感器 (sensors) 则帮助我们获取关于环境的信息,获取不同的本体感知和外界感知信息。例如,摄像头传感器可用于获取环境的视觉信息,接触传感器可以用来获取机器人与环境的接触信息。

在本指南中,我们将看到如何给机器人添加不同的传感器。我们将在本指南中使用ANYmal-C机器人。ANYmal-C是一款四足机器人,拥有12个自由度,它有4条腿,每条腿有3个自由度。这款机器人配备了以下传感器:

  • 机器人头部的摄像头传感器,提供RGB-D图像
  • 提供地形高度信息的高度扫描传感器
  • 机器人脚部的接触传感器,提供接触信息

本指南对应于orbit/source/standalone/tutorials/04_sensors目录下的add_sensors_on_robot.py脚本。让我们先搂一眼完整的代码

# Copyright (c) 2022-2024, The ORBIT Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""
This script demonstrates how to add and simulate on-board sensors for a robot.

We add the following sensors on the quadruped robot, ANYmal-C (ANYbotics):

* USD-Camera: This is a camera sensor that is attached to the robot's base.
* Height Scanner: This is a height scanner sensor that is attached to the robot's base.
* Contact Sensor: This is a contact sensor that is attached to the robot's feet.

.. code-block:: bash

    # Usage
    ./orbit.sh -p source/standalone/tutorials/04_sensors/add_sensors_on_robot.py

"""

from __future__ import annotations

"""Launch Isaac Sim Simulator first."""


import argparse

from omni.isaac.orbit.app import AppLauncher

# add argparse arguments
parser = argparse.ArgumentParser(description="Tutorial on adding sensors on a robot.")
parser.add_argument("--num_envs", type=int, default=2, help="Number of environments to spawn.")
# 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 torch
import traceback

import carb

import omni.isaac.orbit.sim as sim_utils
from omni.isaac.orbit.assets import ArticulationCfg, AssetBaseCfg
from omni.isaac.orbit.scene import InteractiveScene, InteractiveSceneCfg
from omni.isaac.orbit.sensors import CameraCfg, ContactSensorCfg, RayCasterCfg, patterns
from omni.isaac.orbit.utils import configclass

##
# Pre-defined configs
##
from omni.isaac.orbit_assets.anymal import ANYMAL_C_CFG  # isort: skip


@configclass
class SensorsSceneCfg(InteractiveSceneCfg):
    """Design the scene with sensors on the robot."""

    # ground plane
    ground = AssetBaseCfg(prim_path="/World/defaultGroundPlane", spawn=sim_utils.GroundPlaneCfg())

    # lights
    dome_light = AssetBaseCfg(
        prim_path="/World/Light", spawn=sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
    )

    # robot
    robot: ArticulationCfg = ANYMAL_C_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")

    # sensors
    camera = CameraCfg(
        prim_path="{ENV_REGEX_NS}/Robot/base/front_cam",
        update_period=0.1,
        height=480,
        width=640,
        data_types=["rgb", "distance_to_image_plane"],
        spawn=sim_utils.PinholeCameraCfg(
            focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 1.0e5)
        ),
        offset=CameraCfg.OffsetCfg(pos=(0.510, 0.0, 0.015), rot=(0.5, -0.5, 0.5, -0.5), convention="ros"),
    )
    height_scanner = RayCasterCfg(
        prim_path="{ENV_REGEX_NS}/Robot/base",
        update_period=0.02,
        offset=RayCasterCfg.OffsetCfg(pos=(0.0, 0.0, 20.0)),
        attach_yaw_only=True,
        pattern_cfg=patterns.GridPatternCfg(resolution=0.1, size=[1.6, 1.0]),
        debug_vis=True,
        mesh_prim_paths=["/World/defaultGroundPlane"],
    )
    contact_forces = ContactSensorCfg(
        prim_path="{ENV_REGEX_NS}/Robot/.*_FOOT", update_period=0.0, history_length=6, debug_vis=True
    )


def run_simulator(
    sim: sim_utils.SimulationContext,
    scene: InteractiveScene,
):
    """Run the simulator."""

    # Define simulation stepping
    sim_dt = sim.get_physics_dt()
    sim_time = 0.0
    count = 0

    # Simulate physics
    while simulation_app.is_running():
        # Reset
        if count % 500 == 0:
            # reset counter
            count = 0
            # reset the scene entities
            # root state
            # we offset the root state by the origin since the states are written in simulation world frame
            # if this is not done, then the robots will be spawned at the (0, 0, 0) of the simulation world
            root_state = scene["robot"].data.default_root_state.clone()
            root_state[:, :3] += scene.env_origins
            scene["robot"].write_root_state_to_sim(root_state)
            # set joint positions with some noise
            joint_pos, joint_vel = (
                scene["robot"].data.default_joint_pos.clone(),
                scene["robot"].data.default_joint_vel.clone(),
            )
            joint_pos += torch.rand_like(joint_pos) * 0.1
            scene["robot"].write_joint_state_to_sim(joint_pos, joint_vel)
            # clear internal buffers
            scene.reset()
            print("[INFO]: Resetting robot state...")
        # Apply default actions to the robot
        # -- generate actions/commands
        targets = scene["robot"].data.default_joint_pos
        # -- apply action to the robot
        scene["robot"].set_joint_position_target(targets)
        # -- write data to sim
        scene.write_data_to_sim()
        # perform step
        sim.step()
        # update sim-time
        sim_time += sim_dt
        count += 1
        # update buffers
        scene.update(sim_dt)

        # print information from the sensors
        print("-------------------------------")
        print(scene["camera"])
        print("Received shape of rgb   image: ", scene["camera"].data.output["rgb"].shape)
        print("Received shape of depth image: ", scene["camera"].data.output["distance_to_image_plane"].shape)
        print("-------------------------------")
        print(scene["height_scanner"])
        print("Received max height value: ", torch.max(scene["height_scanner"].data.ray_hits_w[..., -1]).item())
        print("-------------------------------")
        print(scene["contact_forces"])
        print("Received max contact force of: ", torch.max(scene["contact_forces"].data.net_forces_w).item())


def main():
    """Main function."""

    # Initialize the simulation context
    sim_cfg = sim_utils.SimulationCfg(dt=0.005, substeps=1)
    sim = sim_utils.SimulationContext(sim_cfg)
    # Set main camera
    sim.set_camera_view(eye=[3.5, 3.5, 3.5], target=[0.0, 0.0, 0.0])
    # design scene
    scene_cfg = SensorsSceneCfg(num_envs=args_cli.num_envs, env_spacing=2.0)
    scene = InteractiveScene(scene_cfg)
    # Play the simulator
    sim.reset()
    # Now we are ready!
    print("[INFO]: Setup complete...")
    # Run the simulator
    run_simulator(sim, scene)


if __name__ == "__main__":
    try:
        # run the main execution
        main()
    except Exception as err:
        carb.log_error(err)
        carb.log_error(traceback.format_exc())
        raise
    finally:
        # close sim app
        simulation_app.close()

代码解析

与之前我们在场景中添加资产的教程类似,传感器也是通过场景配置添加到场景中的。所有的传感器都继承自sensors.SensorBase类,并通过各自的配置类进行配置。每个传感器实例都可以定义自己的更新周期,即传感器更新的频率。更新周期通过sensors.SensorBaseCfg.update_period属性以秒为单位指定。

根据指定的路径和传感器类型,传感器会被附加到场景中的原始图元(prims)上。传感器可能直接和在场景中已创建的原始图元关联,或者可能被附加到一个已存在的原始图元上。例如,摄像头传感器会附加在一个已经创建好的原始图元上,而对于接触传感器,激活中的接触报告是刚体原始图元上的一个属性。

接下来,我们将介绍如何使用不同的传感器以及如何配置。要了解更多关于它们的描述,请查看sensors模块。

摄像头传感器 (Camera sensor)

摄像头是使用sensors.CameraCfg类来定义的。它基于USD摄像头传感器,不同的数据类型由Omniverse Replicator API来捕获。由于摄像头在场景中有对应的原始图元(prim),所以在指定的原始图元路径上会创建原始图元。

摄像头传感器的配置包括以下参数:

  • spawn:创建的USD摄像头类型。可以是PinholeCameraCfg(针孔摄像头配置)或FisheyeCameraCfg(鱼眼摄像头配置)。

  • offset:摄像头传感器相对于父原始图元的偏移。

  • data_types:要捕获的数据类型。可以是rgb、distance_to_image_plane(到图像平面的距离)、normals(法线)或其他USD摄像头传感器支持的类型。

为了将RGB-D摄像头传感器附加到机器人的头部,我们指定了一个相对于机器人基座的偏移(offset)。偏移是相对于基座指定的平移和旋转,以及偏移的指定方式。

接下来,我们来看如何使用摄像头传感器配置。我们将更新周期设置为0.1秒,这意味着摄像头传感器以10Hz的频率更新。原始图元路径表达式设置为{ENV_REGEX_NS}/Robot/base/front_cam,其中{ENV_REGEX_NS}是环境命名空间,"Robot"是机器人的名称,"base"是摄像头附加的原始图元的名称,而"front_cam"是与摄像头传感器关联的原始图元的名称。

高度扫描仪(scanner)

高度扫描仪作为一种虚拟传感器,通过使用NVIDIA Warp的光线投射内核来实现。通过sensors.RayCasterCfg,我们可以指定要投射的光线模式以及要对哪些网格进行光线投射。由于它们是虚拟传感器,在场景中没有相应的原始物体(prims)被创建。相反,它们附加到场景中的一个原始物体上,这用于指定传感器的位置。

在本指南中,基于光线投射的高度扫描仪附加到机器人的基座上。光线的模式使用pattern属性指定。对于均匀网格模式,我们使用GridPatternCfg指定模式。由于我们只关心高度信息,我们不需要考虑机器人的滚转和俯仰。因此,我们将attach_yaw_only设置为true。

对于高度扫描仪,我们可以可视化光线击中网格的点。这是通过将debug_vis属性设置为true来完成的。

高度扫描仪的整个配置如下:

   height_scanner = RayCasterCfg(
        prim_path="{ENV_REGEX_NS}/Robot/base",
        update_period=0.02,
        offset=RayCasterCfg.OffsetCfg(pos=(0.0, 0.0, 20.0)),
        attach_yaw_only=True,
        pattern_cfg=patterns.GridPatternCfg(resolution=0.1, size=[1.6, 1.0]),
        debug_vis=True,
        mesh_prim_paths=["/World/defaultGroundPlane"],
    )

接触传感器 (Contact sensor)

接触传感器利用PhysX的接触报告API来获取机器人与环境的接触信息。由于它依赖于PhysX,接触传感器期望在机器人的刚体上启用接触报告API。这可以通过在资产配置中设置activate_contact_sensors为true来完成。

通过sensors.ContactSensorCfg,可以指定我们想要获取接触信息的原始物体(prims)。可以设置额外的标志以获取更多关于接触的信息,例如接触空中时间、过滤原始物体之间的接触力等。

在本指南中,我们将接触传感器附加到机器人的脚上。机器人的脚被命名为"LF_FOOT"、“RF_FOOT”、“LH_FOOT"和"RF_FOOT”。我们传递一个正则表达式".*_FOOT"来简化原始物体路径的指定。这个正则表达式匹配所有以"_FOOT"结尾的原始物体。

我们将更新周期设置为0,以使传感器与模拟以相同的频率更新。此外,对于接触传感器,我们可以指定要存储的接触信息的历史长度。对于这个教程,我们将历史长度设置为6,这意味着存储了最后6个模拟步骤的接触信息。

接触传感器的整个配置如下:

    contact_forces = ContactSensorCfg(
        prim_path="{ENV_REGEX_NS}/Robot/.*_FOOT", update_period=0.0, history_length=6, debug_vis=True
    )

运行模拟循环

与使用资产时相似,传感器的缓冲区和物理句柄只有在播放模拟时才会初始化,即,在创建场景后调用sim.reset()是很重要的。

    # Play the simulator
    sim.reset()

除此之外,模拟循环与之前的指南类似。传感器作为场景更新的一部分进行更新,它们内部处理基于它们更新周期的缓冲区更新。

可以通过它们的data属性访问传感器的数据。作为示例,我们展示如何访问本教程中创建的不同传感器的数据:

        # print information from the sensors
        print("-------------------------------")
        print(scene["camera"])
        print("Received shape of rgb   image: ", scene["camera"].data.output["rgb"].shape)
        print("Received shape of depth image: ", scene["camera"].data.output["distance_to_image_plane"].shape)
        print("-------------------------------")
        print(scene["height_scanner"])
        print("Received max height value: ", torch.max(scene["height_scanner"].data.ray_hits_w[..., -1]).item())
        print("-------------------------------")
        print(scene["contact_forces"])
        print("Received max contact force of: ", torch.max(scene["contact_forces"].data.net_forces_w).item())

代码运行

现在让我们运行脚本并查看结果:

./orbit.sh -p source/standalone/tutorials/04_sensors/add_sensors_on_robot.py --num_envs 2

在这里插入图片描述

这个命令应该会打开一个带有地面平面、灯光和两个四足机器人的舞台。在机器人周围,应该会看到红色的球体,这些球体表示光线击中网格的点。另外,你可以切换视口到摄像机视图,以查看摄像头传感器捕获的RGB图像。请查看这里以了解如何切换视口到摄像机视图的更多信息。

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

虽然在这个教程中,我们讲解了创建和使用不同的传感器,但在sensors模块中还有许多其他传感器可用。我们在source/standalone/tutorials/04_sensors目录中包含了使用这些传感器的示例。这些脚本可以使用以下命令运行:

# Frame Transformer
./orbit.sh -p source/standalone/tutorials/04_sensors/run_frame_transformer.py

# Ray Caster
./orbit.sh -p source/standalone/tutorials/04_sensors/run_ray_caster.py

# Ray Caster Camera
./orbit.sh -p source/standalone/tutorials/04_sensors/run_ray_caster_camera.py

# USD Camera
./orbit.sh -p source/standalone/tutorials/04_sensors/run_usd_camera.py

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

以上

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

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

相关文章

【小沐学Python】Python实现Web图表功能(Lux)

文章目录 1、简介2、安装3、测试3.1 入门示例3.2 入门示例2 结语 1、简介 https://github.com/lux-org/lux 用于智能可视化发现的 Python API Lux 是一个 Python 库,通过自动化可视化和数据分析过程来促进快速简便的数据探索。通过简单地在 Jupyter 笔记本中打印出…

我的风采——android studio

目录 实现“我的风采”页面要求理论代码生成apk文件 实现“我的风采”页面 要求 要求利用’java框架的边框布局实现“找的风采 ”页而,其中中间为你的生活照,左右和下面为按钮,上面为标签 理论 Java GUI编程是Java程序设计的重要组成部分…

QT(C++)-error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”

1、项目场景: 在VS中采用QT(C)调试时,出现error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”错误 2、解决方案: 在“解决方案资源管理器”中选中出现此类BUG的项目,右键-…

uniapp-Form示例(uviewPlus)

示例说明 Vue版本&#xff1a;vue3 组件&#xff1a;uviewPlus&#xff08;Form 表单 | uview-plus 3.0 - 全面兼容nvue的uni-app生态框架 - uni-app UI框架&#xff09; 说明&#xff1a;表单组建、表单验证、提交验证等&#xff1b; 截图&#xff1a; 示例代码 <templat…

PCIe总线-PCIe总线简介(一)

1.概述 早期的计算机使用PCI&#xff08;Peripheral Component Interconnect&#xff09;总线与外围设备相连&#xff0c;PCI总线使用单端并行信号进行数据传输&#xff0c;由于单端信号很容易被外部系统干扰&#xff0c;其总线频率很难进一步提高。目前&#xff0c;为了提高总…

k8s笔记27--快速了解 k8s pod和cgroup的关系

k8s笔记27--快速了解 k8s pod和 cgroup 的关系 介绍pod & cgroup注意事项说明 介绍 随着云计算、云原生技术的成熟和广泛应用&#xff0c;K8S已经成为容器编排的事实标准&#xff0c;学习了解容器、K8S技术对于新时代的IT从业者显得极其重要了。 之前在文章 docker笔记13–…

UDS升级入门,手把手教你——开篇

前面关于OTA的文章&#xff0c;写的比较乱&#xff0c;索性整了一个专栏&#xff0c;来认真梳理下&#xff0c;话不多开整。 准备工作&#xff1a; 1、QT环境 上位机开发 2、MDK环境&#xff0c;STM32F103&#xff0c;vscode MCU开发环境&#xff0c;调试 3、JFlash环境安…

【C语言数据结构】排序

1.排序的概念 在深入研究各个排序算法之前&#xff0c;首先&#xff0c;我们要对排序有个大概的了解&#xff0c;即与排序相关的一些概念 Q&#xff1a;什么是排序&#xff1f; A&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小…

基于Java中的SSM框架实现考研指导平台系统项目【项目源码+论文说明】

基于Java中的SSM框架实现考研指导平台系统演示 摘要 应对考研的学生&#xff0c;为了更好的使校园考研有一个更好的环境好好的学习&#xff0c;建议一个好的校园网站&#xff0c;是非常有必要的。提供学生的学习提供一个交流的空间。帮助同学们在学习高数、学习设计、学习统计…

使能 Linux 内核自带的 FlexCAN 驱动

一. 简介 前面一篇文章学习了 ALPHA开发板修改CAN的设备树节点信息&#xff0c;并加载测试过设备树文件&#xff0c;文件如下&#xff1a; ALPHA开发板修改CAN的设备树节点信息-CSDN博客 本文是学习使能 IMX6ULL的 CAN驱动&#xff0c;也就是通过内核配置来实现。 二. 使能…

Spring Cloud五:Spring Cloud与持续集成/持续部署(CI/CD)

Spring Cloud一&#xff1a;Spring Cloud 简介 Spring Cloud二&#xff1a;核心组件解析 Spring Cloud三&#xff1a;API网关深入探索与实战应用 Spring Cloud四&#xff1a;微服务治理与安全 文章目录 一、Spring Cloud在CI/CD中的角色1. 服务注册与发现&#xff1a;自动化管理…

YOLOV5 部署:TensorRT的安装和使用

1、介绍 TensorRT 可以加速神经网络的推理时间,常常在工业生产中使用 因为TensorRT需要使用到cuda和cudnn加速,所以需要安装这两个,安装的具体步骤参考前文: YOLOV5 部署:cuda和cuDNN安装-CSDN博客 2、TensorRT 下载 TensorRT下载地址:NVIDIA TensorRT Download | NV…

分类预测 | Matlab实现CNN-LSTM-Mutilhead-Attention卷积神经网络-长短期记忆网络融合多头注意力机制多特征分类预测

分类预测 | Matlab实现CNN-LSTM-Mutilhead-Attention卷积神经网络-长短期记忆网络融合多头注意力机制多特征分类预测 目录 分类预测 | Matlab实现CNN-LSTM-Mutilhead-Attention卷积神经网络-长短期记忆网络融合多头注意力机制多特征分类预测分类效果基本介绍模型描述程序设计参…

初识kafka-数据存储篇1

目录 背景 1 kafka总体体系结构 2 疑问解答 2.1 高吞吐低延迟 2.2 实现分布式存储和数据读取 2.3 如何保证数据不丢失 背景 最近在和产品过项目审批的时候&#xff0c;深刻感受到业务方对系统的时时响应提出了更高的要求。目前手上大部分的业务都是基础定时任务去实现的&…

[Java基础揉碎]单例模式

目录 什么是设计模式 什么是单例模式 饿汉式与懒汉式 饿汉式vs懒汉式 懒汉式存在线程安全问题 什么是设计模式 1.静态方法和属性的经典使用 2.设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、 以及解决问题的思考方式。设计模式就像是经典的棋谱&am…

使用 RunwayML 对图像进行 Camera 操作

RunwayML 是一個功能強大的平台&#xff0c;可以讓您使用 AI 和机器学习来增强您的图像和视频。 它提供一系列预训练模型&#xff0c;可用于各种任务&#xff0c;包括图像编辑、风格化和特效。 在本文中&#xff0c;我们将介绍如何使用 RunwayML 对图像进行 Camera 操作。我们…

游戏引擎中的地形系统

一、地形的几何 1.1 高度图 记录不同定点的高度&#xff0c;对每个网格/顶点应用高度、材质等信息&#xff0c;我们每个顶点可以根据高度改变位移 但是这种方法是不适用于开放世界的。很难直接画出几百万公里的场景 1.2 自适应网格细分 当fov越来越窄的时候&#xff0c;网格…

Stable diffusion(四)

训练自己的Lora 【DataSet】【Lora trainer】【SD Lora trainer】 前置的知识 batch size&#xff1a;模型一次性处理几张图片。一次性多处理图片&#xff0c;模型能够综合捕捉多张图片的特征&#xff0c;最终的成品效果可能会好。但是处理多个batch size也意味着更大的显存…

第一篇:概述、 目录、适用范围及术语 --- IAB/MRC《增强现实(AR)广告(效果)测量指南1.0 》

第一篇&#xff1a;概述、目录、适用范围及术语 - IAB与MRC及《增强现实广告效果测量指南1.0》 --- 我为什么要翻译美国IAB科技公司系列标准 ​​​​​​​​​​​​​​ 翻译计划 第一篇概述—IAB与MRC及《增强现实广告效果测量指南》之目录、适用范围及术语第二篇广告效…

【ArcGIS】统计土地利用数据每类面积及占比

1.栅格转面 转换工具/从栅格/栅格转面&#xff0c;得到面.shp 不要勾选简化面&#xff0c;否则会影响面积 2.添加面积字段&#xff0c;计算面积 面.shp添加双精度字段area 查看面.shp属性表中有没有gridcode为0的&#xff0c;如有的话编辑矢量&#xff0c;删除该要素。 计…