NVIDIA ISAAC 軟件開發工具包 的模塊化和易于使用的感知堆棧繼續加速各種移動機器人的發展。 ISAAC sdk2020.1 引入了 Python API ,使那些熟悉 Python 的人更容易構建機器人應用程序。
在這篇文章中,我們將探討這個特性,并分享如何使用 Python 構建您自己的 ISAAC 應用程序的分步指南。我們在 ISAAC SDK 中介紹 Python 編程,并舉例說明如何創建應用程序;如何使用代碼、模塊和數據流;以及如何處理不同的數據類型。我們用示例來總結文章,將子圖添加到同一個應用程序中,并將其部署到 Jetson 上。我們還將向您展示如何使用 Jupyter 筆記本電腦,這是一個面向 Python 開發人員的強大 UI 工具。對于更高級的 Python 開發人員,我們還提供了在移動機器人上部署 ISAAC 應用程序以及在 ISAAC Sim 中部署協作機器人手臂的例子。
圖 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("http://engine/build:isaac.bzl", "isaac_py_app") isaac_py_app( name = "mybot", srcs = ["mybot.py"], data = [], modules=[], deps = [ "http://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 = [ "http://packages/navsim/apps:navsim_tcp_subgraph", ],
在 Python 應用程序中,可以使用以下命令加載它:
app.load('packages/navsim/apps/navsim_tcp.subgraph.json')
子圖組件更像是由一組節點組成的配方,而不是容器。加載子圖更像是按照配方創建節點和組件。在視圖中,您可以看到從子圖(圖 4 )創建的所有節點(場景管理器、接口)。通過將它們與其他節點連接,可以使用app.connect
創建更復雜的應用程序。
當加載多個子圖時,命名沖突 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 所示。
以下是應用程序中發生的情況。第一件事是加載一個子圖,允許通過 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 編碼的代碼集 PyCodeletJointPositionControl
從滑塊讀取目標關節位置值,并將這些值作為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 中,要有一個帶攝像頭的機械臂,請加載 stageomni:/Isaac/Samples/Isaac_SDK/Scenario/sortbot_sim.usd
。在 Omniverse ISAAC Sim 中啟動仿真和機器人引擎橋,并將視口從透視切換到腕部攝影機,如圖 6 和 7 所示。
與之前的應用程序一樣,您可以將模擬攝影機通道連接到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
啟動應用程序,模擬的攝像機鏡頭應該會出現在眼前:
總結
在本文中,您使用 pythonapi 從頭創建了一個機器人應用程序。您使應用程序可以使用真實的攝影機、錄制的攝影機數據和模擬攝影機。我們還向您展示了如何使用 pythonapi 處理模擬移動機器人和模擬機械臂。做機器人玩得開心!
關于作者
Yang Liu 是一名軟件工程師,負責開發 NVIDIA ISAAC SDK 的各個部分。他獲得了達拉斯德克薩斯大學計算機科學博士學位。
審核編輯:郭婷
-
API
+關注
關注
2文章
1487瀏覽量
61821 -
應用程序
+關注
關注
37文章
3244瀏覽量
57610 -
python
+關注
關注
56文章
4782瀏覽量
84467
發布評論請先 登錄
相關推薦
評論