用NVIDIA ISAAC-SDK开发机器人应用程序

描述

NVIDIA ISAAC 软件开发工具包 的模块化和易于使用的感知堆栈继续加速各种移动机器人的发展。 ISAAC sdk2020.1 引入了 Python API ,使那些熟悉 Python 的人更容易构建机器人应用程序。

在这篇文章中,我们将探讨这个特性,并分享如何使用 Python 构建您自己的 ISAAC 应用程序的分步指南。我们在 ISAAC SDK 中介绍 Python 编程,并举例说明如何创建应用程序;如何使用代码、模块和数据流;以及如何处理不同的数据类型。我们用示例来总结文章,将子图添加到同一个应用程序中,并将其部署到 Jetson 上。我们还将向您展示如何使用 Jupyter 笔记本电脑,这是一个面向 Python 开发人员的强大 UI 工具。对于更高级的 Python 开发人员,我们还提供了在移动机器人上部署 ISAAC 应用程序以及在 ISAAC Sim 中部署协作机器人手臂的例子。

API

图 1 。使用 Jupyter 笔记本和 ISAAC SDK Python API 在 ISAAC Sim 中控制虚拟机器人。

ISAAC SDK 中 Python 编程入门

为了指导您使用 Python 创建一个 ISAAC 应用程序,请创建一个 mybot.py 应用程序文件。从 apps 文件夹下的新文件夹开始, //apps/mybot 。用下面的代码创建一个构建文件,并将其保存在 //apps/mybot/BUILD 下,以便 Bazel 能够识别它。

ISAAC SDK 中 Python 编程入门

为了指导您使用 Python 创建一个 ISAAC 应用程序,请创建一个 mybot.py 应用程序文件。从 apps 文件夹下的新文件夹开始, //apps/mybot 。用下面的代码创建一个构建文件,并将其保存在 //apps/mybot/BUILD 下,以便 Bazel 能够识别它。

load("//engine/build:isaac.bzl", "isaac_py_app")
isaac_py_app( name = "mybot", srcs = ["mybot.py"], data = [], modules=[], deps = [ "//engine/pyalice", ],
)

在构建文件中, //engine/pyalice 是 Python API 的支持代码, mybot.py 是用 Python 编写的 robot 应用程序。将下面的代码放入 //apps/mybot/mybot.py 并用 bazel run apps/mybot:mybot 运行它。您可以通过控制台 spew 判断它正在运行,您可以使用经典的 CTR L-C 随时停止它。

from engine.pyalice import Application app = Application(name="mybot")
app.run()

当应用程序运行时,将浏览器指向 http://localhost:3000 ,您将在 视力 中看不到任何内容,这是 ISAAC SDK 中的可视化工具。

了解代码、模块和数据流

ISAAC SDK 为机器人应用程序提供了许多构建块,称为 代码 。

其中一些代码可以按原样提供,比如 录音机 。其他模块打包为模块,必须在代码集可用之前显式加载这些模块。将以下模块添加到刚刚创建的 Bazel 构建文件中,以便加载它们。

 modules = [ "message_generators", "viewers", ],

现在可以使用在 app.run 之前创建的应用程序实例从 Python 加载它们:

app.load_module('message_generators')
app.load_module('viewers')

在 ISAAC SDK 中,数据由传感器生成,并在代码实例之间流动,直到它们被执行器消耗。要从加载的 codelet 创建实例,请在调用之前将以下代码添加到 Python 应用程序应用程序运行.

node_src = app.add('src')
component_src = \ node_src.add(app.registry.isaac.message_generators.ImageLoader, 'ImageLoader')

这里创建了一个名为 src 的节点。消息生成器模块提供的 ImageLoader 的组件以 ImageLoader 的名称创建,并附加到 src 的节点上。它将指定 PNG 文件中的图像数据作为 ColorCameraProto 消息发布,就像它们来自真实的相机一样。您可以指定要从中加载数据的图像以及其他几个参数(尽管在本示例中这些参数并不重要)以及消息发布的频率。有关详细信息,请参阅 ISAAC 消息_ generators . ImageLoader 。

component_src.config['color_filename'] = '/home/bob/Pictures/panda.png'
component_src.config['focal_length'] = [35.0, 35.0]
component_src.config['optical_center'] = [300.0, 400.0]
component_src.config['tick_period'] = '1hz'

为了可视化摄像机图像, 彩色摄影机 代码将有所帮助。类似地,您可以使用以下代码创建它的实例:

node_sink = app.add('sink')
component_sink = \ node_sink.add(app.registry.isaac.viewers.ColorCameraViewer, 'ColorCameraViewer')

数据应该在代码之间流动。但是,必须在它们之间建立连接才能使数据流动。从文档中可以看出, CameraGenerator 有三个输出通道。选择 ColorCameraProto 消息发布到的 color _ left 频道。类似地,您可以看到 ColorCameraViewer 代码从 color_listener 通道读取消息。连接它们(称为“边缘”):

app.connect(component_src, 'color', component_sink, 'color_listener')

再次运行应用程序( mybot.py ),并检查 Sight 是否有图像。

在 Python 中使用不同的 ISAAC 图像数据类型

ISAAC SDK 允许您在应用程序中使用多个数据源:

  • 记录的传感器数据(容器)
  • 真实传感器数据(摄像机)
  • 模拟传感器数据

在本节中,我们将解释如何在 Python 应用程序中使用这些数据类型。

使用摄像头

ISAAC SDK 支持许多带有 V4L2Camera codelet 的 USB 摄像头。

在本节中,您将使用 Realsense 摄像头,它由 realsense 模块中的 RealsenseCamera 代码集支持。类似地,你可以从视线中看到摄像机镜头,就像之前的图像一样。因为这是对 ImageLoader 的直接替换,所以可以使用命令行参数在它们之间进行切换。有关如何在 Python 中处理命令行参数的更多信息, argparse- 命令行选项、参数和子命令的解析器 。您将得到如下代码示例:

parser = argparse.ArgumentParser(description='Sample Python API app')
parser.add_argument('--source',
                   type=str,
                   dest='source',
                   help='The source to get data from',
                   choices=['camera', 'image'],
                   default='camera')
args, _ = parser.parse_known_args()
if args.source == 'image':
   app.load_module('message_generators')
   component_src = \
     node_src.add(app.registry.isaac.message_generators.ImageLoader, 'src')
   component_src.config['color_filename'] = '/home/bob/Pictures/panda.png'
   component_src.config['focal_length'] = [35.0, 35.0]
   component_src.config['optical_center'] = [300.0, 400.0]
   component_src.config['tick_period'] = '1hz'
   app.connect(component_src, 'color', viewer_component, 'color_listener')
elif args.source == 'camera':
   app.load_module('realsense')
   camera = app.add("cam").add(app.registry.isaac.RealsenseCamera)
   camera.config.rows = 480
   camera.config.cols = 640
   camera.config.color_framerate = 30
   camera.config.depth_framerate = 30
   app.connect(camera, 'color', viewer_component, 'color_listener')
app.run()

如前所示, PythonAPI 提供了处理不同环境的灵活性。

使用木桶

使用真实的传感器数据是直观的,但是这样做并不总是实际可行的。木桶能帮上忙。 Cask 是用于记录 ISAAC SDK 中的消息的格式。在 ISAAC SDK 中,可以记录一个消息流,并在以后回放以用于调试或分析。要从 Realsense 摄像头录制图像流,请尝试在 //apps/samples/camera:record_realsense 运行示例应用程序。

有了录音桶,你可以在没有真正的传感器的情况下随时随地重放和播放消息流。假设记录的容器位于 /home/bob/cask/ 的文件夹中。您可以使用 Replay 代码来检索消息:

   player_node = app.add('player')
   player_component = player_node.add(app.registry.isaac.alice.Replay)
   player_component.config['cask_directory'] = '/home/bob/cask'
   app.connect(player_component, 'color', viewer_component, 'color_listener')

类似地,您可以向 Python 应用程序添加一个 cask 作为一个可能的选项,就像您使用 realseness camera 一样。这里,名称 color 是用于记录彩色相机图像流的通道名称。然后你就可以查看视频流,就好像它来自真实的摄像机一样。

使用模拟传感器

如前所述,您已经有了一个 Python 应用程序,可以在记录的传感器数据( cask )和真实传感器数据( camera )之间切换。现在再添加一个可能的数据源:来自 ISAAC Sim Unity3D 的模拟传感器。将 Sim 选项添加到命令行参数源,并将模拟相机消息流连接到查看器以进行可视化,如以下代码示例所示:

parser.add_argument('--source', type=str, dest='source', help='The source to get data from', choices=['cask', 'camera', 'image', 'sim'], default='sim')
… if args.source == 'image': ...
elif args.source == 'cask': ...
elif args.source == 'camera': ...
elif args.source == 'sim': app.load('packages/navsim/apps/navsim_tcp.subgraph.json') app.connect('interface/output', 'color', 'viewer/ColorCameraViewer', 'color_listener') app.run()

检索 ISAAC 是 Unity3D 。有关详细信息,请参阅 ISAAC Sim Unity3D 。

启动 ISAAC 是 Unity3D :

./build/sample.x86_64 --scene medium_warehouse

默认情况下, Python 应用程序尝试与同一主机上的模拟对话。如果应用程序正在另一台主机上运行,请为组件 interface/output 配置相应的主机参数。有关详细信息,请参阅 isaac.alice.TcpSubscriber 。运行该应用程序,模拟摄像机的镜头可以看到。

镜头来自安装在模拟机器人上的模拟摄像机。试着在模拟图形用户界面( GUI )上玩一些可移动的物体,比如纳米盒子,看看模拟相机的工作原理和真相机一样。

用子图把它拉到一起

正如您所注意到的,组件(从代码创建的实例)和连接它们的边组成了一个图形。这样的图可以从 JSON 文件加载,也可以根据需要从 Python 应用程序加载。有关详细信息,请参阅 MIG 。

例如,模拟通信子图 packages/navsim/apps/navsim_tcp.subgraph.json 封装了用于使用 TCP 与 ISAAC Sim Unity3D 或 NVIDIA Omniverse 通信的节点、组件和边。要使其对应用程序可用,请将以下 Bazel 数据依赖项添加到您先前创建的生成文件中:

 data = [ "//packages/navsim/apps:navsim_tcp_subgraph", ],

在 Python 应用程序中,可以使用以下命令加载它:

app.load('packages/navsim/apps/navsim_tcp.subgraph.json')

子图组件更像是由一组节点组成的配方,而不是容器。加载子图更像是按照配方创建节点和组件。在视图中,您可以看到从子图(图 4 )创建的所有节点(场景管理器、接口)。通过将它们与其他节点连接,可以使用 app.connect 创建更复杂的应用程序。

API图 4 。显示各种子图使用情况的计算图。

当加载多个子图时,命名冲突 MIG ht 会发生,因为在任何应用程序中,节点都需要具有唯一的名称。若要避免此类冲突,请使用另一个参数加载子图:

app.load( 'packages/navsim/apps/navsim_tcp.subgraph.json', 'simulation',
)

这里,第二个参数是 JSON 文件中指定的所有节点的“ node name prefix ”。例如, packages/navsim/apps/navsim_tcp.subgraph.json 文件指定一个名为 interface 的节点。前面的语句将创建一个名为 simulation.interface 的节点,而不是 interface 。

在 Jetson 上部署应用程序

现在有了一个 Python 应用程序。在真正的 Jetson 板上运行只需要一个命令:

./engine/build/deploy.sh -h -p //apps/mybot:mybot-pkg -d jetpack43

有关将应用程序部署到 Jetson 的更多信息,请参阅 入门 和 在 Jetson 上部署和运行 。

使用 SSH 连接到您的 Jetson 板或从 GUI 打开一个终端并检查文件夹 /home/nvidia/deploy/bob/mybot-pkg 。如果您在 Jetson 和开发设置上使用不同的用户名,请将 nvidia 替换为 Jetson 板上的用户名,将 bob 替换为开发设置上的用户名。

使用以下命令在 Jetson 上运行应用程序:

nvidia@Jetson:~/deploy/bob/mybot-pkg$ ./run apps/mybot/mybot.py

如果您正在使用存储库之外的资源,请考虑将它们添加到应用程序的 Bazel 依赖项中,以便可以使用 deploy.sh 将它们与应用程序一起自动部署到 deploy.sh 。

如果您在 PC 机上使用 ISAAC Sim Unity3D ,则可以正常通信。

使用 Jupyter 笔记本

因为这里有 pythonapi ,所以 Jupyter 笔记本肯定可以工作。将以下生成文件与空的 mybot.ipynb 一起使用:

isaac_jupyter_app(
   name = "mybot",
   modules = [
       "message_generators",
       "viewers",
   ],
   notebook = "mybot.ipynb",
)

以类似于 Jetson 板或 X86 工作站的方式部署应用程序,并使用以下命令启动 Jupyter :

jupyter notebook apps/mybot/mybot.ipynb

你现在可以走了。 run 函数被阻塞,只有在 robotic 应用程序停止时才返回。要以交互方式使用 robotics 应用程序,请相应地使用 start 和 stop 函数。

Python 在模拟移动机器人中的应用

在使用模拟传感器工作的部分,有一个模拟机器人,上面安装了模拟摄像机。 ISAAC Sim Unity3D 是用来模拟移动机器人的。对于在 ISAAC Sim Unity3D 中控制带有差分基座的模拟机器人的示例 robot 应用程序,请检查 //apps/navsim:navsim_navigate 中的应用程序。组件和子图可以在 JSON 文件 apps/navsim/navsim_navigate.app.json 中找到。有关详细信息,请参见 ISAAC Sim Unity3D 。

用 Python 模拟机器人手臂

除了移动机器人, 用 Jupyter 笔记本电脑进行简单的联合控制 SDK 也可以用于构建机器人手臂的应用程序。有了 Omniverse ISAAC ,你可以在没有真正硬件的情况下使用模拟机械手臂。有关更多信息,请按照 用 Jupyter 笔记本电脑进行简单的联合控制 上的“ UR10 in 用 Jupyter 笔记本电脑进行简单的联合控制 用 Jupyter 笔记本电脑进行简单的联合控制 Sim ”会话说明操作。应用程序将在模拟中控制机械臂,如图 5 所示。

API图 5 。通用机器人的 UR10 正在使用 Jupyter 笔记本电脑进行模拟控制。

以下是应用程序中发生的情况。第一件事是加载一个子图,允许通过 TCP 与模拟器通信。

app.load(filename="packages/navsim/apps/navsim_tcp.subgraph.json", prefix="simulation")

若要为关节生成平滑运动,请为节点加载另一个子图:

app.load( filename="packages/planner/apps/multi_joint_lqr_control.subgraph.json", prefix="lqr")

该子图封装 LQR 规划器的节点,生成当前关节状态和目标关节位置的命令。将仿真节点与规划器的节点连接起来,以使机械臂关节状态消息和命令消息在它们之间流动:

app.connect(simulation_node["output"], "joint_state", lqr_interface, "joint_state")
app.connect(lqr_interface, "joint_command", simulation_node["input"], "joint_position")

用 Python 编码的代码集 PyCodelet JointPositionControl 从滑块读取目标关节位置值,并将这些值作为 CompositeProto 消息发布:

class JointPositionControl(Codelet):
    def start(self):
        self.tx = self.isaac_proto_tx("CompositeProto", "command")
      self._widget = CompositeWidget(self.config.joints "position", self.config.limits)
    def tick(self):
        self.tx._msg = self._widget.composite
      self.tx.publish()

有关详细信息,请参见 创建 Python 代码 。

然后, JointPositionControl 代码集连接到一个节点,并连接到 LQR planner 的目标输入通道:

widget_node = app.add("command_generator")
joint_commander = widget_node.add(JointPositionControl)
app.connect(joint_commander, "command", lqr_interface, "joint_target")

启动应用程序应用程序启动你可以随意使用手臂。

带模拟摄像机的模拟机械臂

在 Omniverse ISAAC Sim 中,要有一个带摄像头的机械臂,请加载 stage omni:/Isaac/Samples/Isaac_SDK/Scenario/sortbot_sim.usd 。在 Omniverse ISAAC Sim 中启动仿真和机器人引擎桥,并将视口从透视切换到腕部摄影机,如图 6 和 7 所示。

API图 6 。 ISAAC Sim 中机器人的透视图。

与之前的应用程序一样,您可以将模拟摄影机通道连接到 ColorCameraViewer 代码板以可视化画面,并将 DepthCameraViewer 连接到可视化模拟深度传感器数据。

app.load_module("viewers")
viewers = app.add("viewers")
color_viewer = viewers.add(app.registry.isaac.viewers.ColorCameraViewer, "ColorViewer")
app.connect(simulation_node["output"], "color", color_viewer, "color_listener")
depth_viewer = viewers.add(app.registry.isaac.viewers.DepthCameraViewer, "DepthViewer")
app.connect(simulation_node["output"], "depth", depth_viewer, "depth_listener")
depth_viewer.config.max_visualization_depth = 3

启动应用程序,模拟的摄像机镜头应该会出现在眼前:

API图 7 。 ISAAC 模拟中机器人的手腕视图。

总结

在本文中,您使用 pythonapi 从头创建了一个机器人应用程序。您使应用程序可以使用真实的摄影机、录制的摄影机数据和模拟摄影机。我们还向您展示了如何使用 pythonapi 处理模拟移动机器人和模拟机械臂。做机器人玩得开心!

  关于作者

  Yang Liu 是一名软件工程师,负责开发 NVIDIA ISAAC SDK 的各个部分。他获得了达拉斯德克萨斯大学计算机科学博士学位。

  审核编辑:郭婷

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分