├── .gitattributes
├── VERSION.md
├── isaac-zmq-server
├── src
│ ├── isaac_zmq_server
│ │ ├── __init__.py
│ │ ├── fonts
│ │ │ ├── Inter-Medium.ttf
│ │ │ └── LICENSE.txt
│ │ ├── ui.py
│ │ └── server.py
│ ├── server_control_message_pb2.py
│ └── client_stream_message_pb2.py
├── build_server.sh
├── run_server.sh
├── README.md
└── Dockerfile
├── exts
├── isaacsim.zmq.bridge.examples
│ ├── isaacsim
│ │ └── zmq
│ │ │ └── bridge
│ │ │ └── examples
│ │ │ ├── core
│ │ │ ├── __init__.py
│ │ │ ├── proto_util.py
│ │ │ ├── server_control_message_pb2.py
│ │ │ ├── client_stream_message_pb2.py
│ │ │ ├── rate_limiter.py
│ │ │ └── client.py
│ │ │ ├── __init__.py
│ │ │ ├── example_headless.py
│ │ │ ├── ui.py
│ │ │ ├── mission.py
│ │ │ └── extension.py
│ ├── data
│ │ ├── arch.png
│ │ ├── ext.png
│ │ ├── icon.png
│ │ ├── multi.png
│ │ ├── buttons.png
│ │ ├── preview.png
│ │ ├── 2d_to_3d.png
│ │ ├── create_menu.png
│ │ ├── franka_mission.png
│ │ ├── play_stream.svg
│ │ └── stop_stream.svg
│ ├── docs
│ │ ├── README.md
│ │ └── CHANGELOG.md
│ ├── premake5.lua
│ └── config
│ │ └── extension.toml
└── isaacsim.zmq.bridge
│ ├── data
│ ├── icon.png
│ └── preview.png
│ ├── docs
│ ├── README.md
│ └── CHANGELOG.md
│ ├── isaacsim
│ └── zmq
│ │ └── bridge
│ │ └── __init__.py
│ ├── config
│ └── extension.toml
│ ├── plugins
│ ├── nodes
│ │ ├── OgnIsaacBridgeZMQCamera.ogn
│ │ ├── OgnIsaacBridgeZMQNode.ogn
│ │ ├── OgnIsaacBridgeZMQCamera.cpp
│ │ ├── icons
│ │ │ └── isaac-sim.svg
│ │ └── OgnIsaacBridgeZMQNode.cpp
│ └── isaacsim.zmq.bridge
│ │ └── OgnIsaacBridgeZMQNodeExtension.cpp
│ └── premake5.lua
├── assets
├── props
│ ├── looks.usd
│ ├── model.usd
│ ├── scale.usd
│ ├── sensor.usd
│ ├── physics.usd
│ ├── base_camera.usd
│ ├── sensor_camera.usd
│ ├── interface_camera.usd
│ ├── phyisics_camera.usd
│ └── camera.usda
├── franka_world.usda
└── franka_multi_cam_world.usda
├── tools
├── repoman
│ ├── omni
│ │ └── repo
│ │ │ └── format
│ │ │ └── .gitignore
│ ├── repoman.py
│ └── repoman_bootstrapper.py
└── packman
│ ├── config.packman.xml
│ ├── python.bat
│ ├── python.sh
│ ├── bootstrap
│ ├── fetch_file_from_packman_bootstrap.cmd
│ ├── download_file_from_url.ps1
│ ├── configure.bat
│ ├── install_package.py
│ ├── generate_temp_file_name.ps1
│ └── generate_temp_folder.ps1
│ ├── packman.cmd
│ ├── packmanconf.py
│ └── packman
├── deps
├── pip.toml
├── kit-sdk.packman.xml
├── host-deps.packman.xml
├── repo-deps.packman.xml
├── ext-deps.packman.xml
└── kit-sdk-deps.packman.xml
├── repo.sh
├── premake5.lua
├── .gitignore
├── .gitlab-ci.yml
├── LICENSE.txt
├── proto
├── server_control_message.proto
└── client_stream_message.proto
├── repo.toml
└── SECURITY.md
/.gitattributes:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/VERSION.md:
--------------------------------------------------------------------------------
1 | 107.3.3
--------------------------------------------------------------------------------
/isaac-zmq-server/src/isaac_zmq_server/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/core/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/isaac-zmq-server/build_server.sh:
--------------------------------------------------------------------------------
1 | docker build -t isaac-zmq-server -f Dockerfile .
--------------------------------------------------------------------------------
/assets/props/looks.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/looks.usd
--------------------------------------------------------------------------------
/assets/props/model.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/model.usd
--------------------------------------------------------------------------------
/assets/props/scale.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/scale.usd
--------------------------------------------------------------------------------
/assets/props/sensor.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/sensor.usd
--------------------------------------------------------------------------------
/assets/props/physics.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/physics.usd
--------------------------------------------------------------------------------
/assets/props/base_camera.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/base_camera.usd
--------------------------------------------------------------------------------
/assets/props/sensor_camera.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/sensor_camera.usd
--------------------------------------------------------------------------------
/assets/props/interface_camera.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/interface_camera.usd
--------------------------------------------------------------------------------
/assets/props/phyisics_camera.usd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/assets/props/phyisics_camera.usd
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/data/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge/data/icon.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/data/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge/data/preview.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/arch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/arch.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/ext.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/ext.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/icon.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/multi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/multi.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/buttons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/buttons.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/preview.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/2d_to_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/2d_to_3d.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/create_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/create_menu.png
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/franka_mission.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/exts/isaacsim.zmq.bridge.examples/data/franka_mission.png
--------------------------------------------------------------------------------
/isaac-zmq-server/src/isaac_zmq_server/fonts/Inter-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isaac-sim/IsaacSimZMQ/HEAD/isaac-zmq-server/src/isaac_zmq_server/fonts/Inter-Medium.ttf
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/docs/README.md:
--------------------------------------------------------------------------------
1 | # Isaac SIM ZMQ Bridge OmniGraph Nodes [isaacsim.zmq.bridge]
2 |
3 | Extention to facilitate communication between Omniverse and External application via ZMQ
4 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/docs/README.md:
--------------------------------------------------------------------------------
1 | # Isaac SIM ZMQ Bridge [isaacsim.zmq.bridge.examples]
2 |
3 | Extention to facilitate communication between Omniverse and External application via ZMQ
4 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/docs/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
4 |
5 |
6 | ## [1.0.0] - 2025-03-03
7 | - Initial version
8 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/docs/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
4 |
5 |
6 | ## [1.0.0] - 2025-03-03
7 | - Initial version
8 |
--------------------------------------------------------------------------------
/tools/repoman/omni/repo/format/.gitignore:
--------------------------------------------------------------------------------
1 | # Dummy omni.repo.format Python module so we don't have to pull down the format package.
2 |
3 | # Ignore everything in this directory, except this file to ensure the folder is created.
4 | *
5 | !.gitignore
--------------------------------------------------------------------------------
/deps/pip.toml:
--------------------------------------------------------------------------------
1 | [[dependency]]
2 | python = "../_build/target-deps/python"
3 | packages = [
4 | "pyzmq==25.1.2", # 26.4.0 no longer works as prebunlde.
5 | "protobuf==5.26.0",
6 | ]
7 |
8 | target = "../_build/target-deps/pip_prebundle"
9 | platforms = ["*-x86_64", "*-aarch64"]
10 | download_only = false
11 | append_to_install_folder = true
12 |
--------------------------------------------------------------------------------
/tools/packman/config.packman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/deps/kit-sdk.packman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/premake5.lua:
--------------------------------------------------------------------------------
1 | -- Use folder name to build extension name and tag. Version is specified explicitly.
2 | local ext = get_current_extension_info()
3 |
4 | project_ext (ext)
5 |
6 | -- Link only those files and folders into the extension target directory
7 | repo_build.prebuild_link {
8 | { "%{target_deps}/pip_prebundle", ext.target_dir.."/pip_prebundle" },
9 | }
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/__init__.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | EXT_NAME = "isaacsim.zmq.bridge.examples"
5 |
6 | from .core.proto_util import register_proto_modules
7 |
8 | register_proto_modules()
9 |
10 | from .core.annotators import *
11 | from .core.client import *
12 | from .extension import *
13 |
--------------------------------------------------------------------------------
/repo.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | # Set OMNI_REPO_ROOT early so `repo` bootstrapping can target the repository
6 | # root when writing out Python dependencies.
7 | export OMNI_REPO_ROOT="$( cd "$(dirname "$0")" ; pwd -P )"
8 |
9 | SCRIPT_DIR=$(dirname ${BASH_SOURCE})
10 | cd "$SCRIPT_DIR"
11 |
12 | # Use "exec" to ensure that envrionment variables don't accidentally affect other processes.
13 | exec "tools/packman/python.sh" tools/repoman/repoman.py "$@"
14 |
--------------------------------------------------------------------------------
/isaac-zmq-server/run_server.sh:
--------------------------------------------------------------------------------
1 | xhost +local:appuser
2 | docker run --gpus all --network host \
3 | -e DISPLAY=$DISPLAY \
4 | -v /tmp/.X11-unix:/tmp/.X11-unix \
5 | -e XAUTHORITY=$XAUTHORITY \
6 | -v $XAUTHORITY:$XAUTHORITY \
7 | -v ./src:/isaac-zmq-server/src \
8 | --device /dev/input \
9 | --device /dev/input/event21 \
10 | --device /dev/input/event22 \
11 | --device /dev/input/event23 \
12 | --privileged \
13 | -it --rm \
14 | isaac-zmq-server bash
15 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/isaacsim/zmq/bridge/__init__.py:
--------------------------------------------------------------------------------
1 | ## Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
2 | ##
3 | ## NVIDIA CORPORATION and its licensors retain all intellectual property
4 | ## and proprietary rights in and to this software, related documentation
5 | ## and any modifications thereto. Any use, reproduction, disclosure or
6 | ## distribution of this software and related documentation without an express
7 | ## license agreement from NVIDIA CORPORATION is strictly prohibited.
8 | ##
9 |
10 | # This file is needed so tests don't fail.
11 |
--------------------------------------------------------------------------------
/deps/host-deps.packman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/premake5.lua:
--------------------------------------------------------------------------------
1 | -- Shared build scripts from repo_build package.
2 | repo_build = require("omni/repo/build")
3 |
4 | -- Repo root
5 | root = repo_build.get_abs_path(".")
6 |
7 | -- Set the desired MSVC, WINSDK, and MSBUILD versions before executing the kit template premake configuration.
8 | MSVC_VERSION = "14.27.29110"
9 | WINSDK_VERSION = "10.0.18362.0"
10 | MSBUILD_VERSION = "Current"
11 |
12 | -- Execute the kit template premake configuration, which creates the solution, finds extensions, etc.
13 | dofile("_repo/deps/repo_kit_tools/kit-template/premake5.lua")
14 |
15 | include("exts/isaacsim.zmq.bridge.examples/premake5.lua")
16 | include("exts/isaacsim.zmq.bridge/premake5.lua")
17 |
--------------------------------------------------------------------------------
/tools/repoman/repoman.py:
--------------------------------------------------------------------------------
1 | import contextlib
2 | import io
3 | import os
4 | import sys
5 |
6 | import packmanapi
7 | from repoman_bootstrapper import repoman_bootstrap
8 |
9 | REPO_ROOT = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../..")
10 | REPO_DEPS_FILE = os.path.join(REPO_ROOT, "deps/repo-deps.packman.xml")
11 |
12 |
13 | def bootstrap():
14 | """
15 | Bootstrap all omni.repo modules.
16 |
17 | Pull with packman from repo.packman.xml and add them all to python sys.path to enable importing.
18 | """
19 | # with contextlib.redirect_stdout(io.StringIO()):
20 | deps = packmanapi.pull(REPO_DEPS_FILE)
21 | for dep_path in deps.values():
22 | if dep_path not in sys.path:
23 | sys.path.append(dep_path)
24 |
25 |
26 | if __name__ == "__main__":
27 | repoman_bootstrap()
28 | bootstrap()
29 | import omni.repo.man
30 |
31 | omni.repo.man.main(REPO_ROOT)
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # all folders starting with _ are local
2 | _*/
3 |
4 | .DS_Store
5 | **/.vscode/ipch
6 |
7 | # byte-compiled python files
8 | *.py[cod]
9 |
10 | /.vs
11 |
12 | /app
13 |
14 | /assets/.thumbs
15 | /assets/build
16 | /source/apps
17 | /assets/props/.thumbs
18 |
19 | *.cbin
20 | *.cinfo
21 |
22 | # Too big to upload
23 |
24 | exts/isaacsim.zmq.bridge/bin/lib/*.*
25 | exts/isaacsim.zmq.bridge/bin/libisaacsim.zmq.bridge.plugin.so
26 |
27 | /scratch.py
28 | /temp.py
29 | /release
30 |
31 |
32 | /vendor/Video_Codec_SDK_12.2.72
33 |
34 | tests/rtsp/deps
35 | tests/rtsp/src/build
36 | .nvcode
37 | .nvidia-omniverse
38 | _conan
39 | _deps
40 | _repo
41 | _build
42 | _compiler
43 |
44 | .vscode/
45 | source/
46 |
47 | exts/isaacsim.zmq.bridge/isaacsim/zmq/bridge/ogn/
48 | exts/isaacsim.zmq.bridge/PACKAGE-LICENSES/
49 | exts/isaacsim.zmq.bridge/ogn/
50 | exts/isaacsim.zmq.bridge/bin/
51 |
52 |
53 | exts/isaacsim.zmq.bridge.examples/pip_prebundle
54 | exts/isaacsim.zmq.bridge.examples/PACKAGE-LICENSES
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | include:
2 | - project: 'omniverse/devplat/gitlab/templates/common/compliance'
3 | file: 'modules/omniverse-repo-compliance.gitlab-ci.yml'
4 | ref: v1_latest
5 |
6 | variables:
7 | OSEC_NSPECT_ID: NSPECT-9GUM-4H71
8 | OSEC_SONARQUBE_ENABLED: true
9 | OSEC_CHECKMARX_ENABLED: false
10 | OSEC_PULSE_TRUFFLEHOG_ENABLED: true
11 | OSEC_OMNI_PULSE_ENABLED: false
12 |
13 | # overrides for sonarqube job to enable C/C++ analysis
14 | osec:sonarqube:
15 | variables:
16 | SONAR_CFAMILY_COMPILE_COMMANDS: _build/linux-x86_64/release/compile_commands.json
17 | SONAR_EXCLUSIONS: "_build/**,_repo/**,\
18 | \
19 | source/tests/**,\
20 | "
21 | LINBUILD_EMBEDDED: "1"
22 | before_script:
23 | # Additions to enable C/C++ scan via sonar's compile_commands.json, you still need all of the
24 | # packman headers and generated headers in place for this analysis to work.
25 | # So we run repo --generate
26 | - ./repo.sh build --generate --config release
27 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/config/extension.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | version = "1.1.0"
3 | authors = ["Lior Ben Horin "]
4 | title = "isaacsim zmq bridge examples"
5 | description="Extention to facilitate communication between Isaac SIM and External application via ZMQ"
6 | readme = "docs/README.md"
7 | repository="https://github.com/isaac-sim/IsaacSimZMQ"
8 | category = "Sample"
9 | keywords = ["bridge","example", "zmq"]
10 | changelog="docs/CHANGELOG.md"
11 | preview_image = "data/preview.png"
12 | icon = "data/icon.png"
13 |
14 | # Use omni.ui to build simple UI
15 | [dependencies]
16 | "omni.kit.uiapp" = {}
17 | "isaacsim.zmq.bridge" = {}
18 |
19 |
20 | [[python.module]]
21 | path = "pip_prebundle"
22 |
23 | # Main python module this extension provides, it will be publicly available as "import lbenhorin.nvidia.vision_pipeline".
24 | [[python.module]]
25 | name = "isaacsim.zmq.bridge.examples"
26 |
27 | [[test]]
28 | # Extra dependencies only to be used during test run
29 | dependencies = [
30 | "omni.kit.ui_test" # UI testing extension
31 | ]
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/play_stream.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/isaac-zmq-server/README.md:
--------------------------------------------------------------------------------
1 | # Example container to mock as Server for Isaac Sim ZMQ Bridge
2 |
3 |
4 | This example container provides a starting point for building your own server to communicate with Isaac Sim using ZMQ and Protobuf.
5 | You can use it to run and test your CV models, or any other task that will form a closed loop with Isaac Sim.
6 |
7 | The server also provides a GUI to visualize the data sensor messages being recived, using the [DearPyGui](https://github.com/hoffstadt/DearPyGui) library, which is a simple and easy to use and extend.
8 |
9 | ---
10 |
11 | ## Instructions
12 |
13 | #### Server (Python inside a contatiner)
14 |
15 | 1. Build the docker image and run it
16 | ```bash
17 | cd isaac-zmq-server
18 | ./build_server.sh
19 | ./run_server.sh
20 | ```
21 | 2. Inside the container, run the server
22 | ```bash
23 | python example.py
24 | ```
25 | 3. Optional - For the Franka RMPFlow (Multi Camera), start two servers
26 |
27 |
28 | ```bash
29 | # Inside the container
30 | python example.py # server 1 for main camera
31 | # in a second container
32 | python example.py --subscribe_only 1 --port 5591 # server 2 for gripper camera
33 | ```
34 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/data/stop_stream.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tools/packman/python.bat:
--------------------------------------------------------------------------------
1 | :: Copyright 2019-2020 NVIDIA CORPORATION
2 | ::
3 | :: Licensed under the Apache License, Version 2.0 (the "License");
4 | :: you may not use this file except in compliance with the License.
5 | :: You may obtain a copy of the License at
6 | ::
7 | :: http://www.apache.org/licenses/LICENSE-2.0
8 | ::
9 | :: Unless required by applicable law or agreed to in writing, software
10 | :: distributed under the License is distributed on an "AS IS" BASIS,
11 | :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | :: See the License for the specific language governing permissions and
13 | :: limitations under the License.
14 |
15 | @echo off
16 | setlocal enableextensions
17 |
18 | call "%~dp0\packman" init
19 | set "PYTHONPATH=%PM_MODULE_DIR%;%PYTHONPATH%"
20 |
21 | if not defined PYTHONNOUSERSITE (
22 | set PYTHONNOUSERSITE=1
23 | )
24 |
25 | REM For performance, default to unbuffered; however, allow overriding via
26 | REM PYTHONUNBUFFERED=0 since PYTHONUNBUFFERED on windows can truncate output
27 | REM when printing long strings
28 | if not defined PYTHONUNBUFFERED (
29 | set PYTHONUNBUFFERED=1
30 | )
31 |
32 | "%PM_PYTHON%" %*
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | SPDX-License-Identifier: MIT
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a
5 | copy of this software and associated documentation files (the "Software"),
6 | to deal in the Software without restriction, including without limitation
7 | the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | and/or sell copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 | DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/config/extension.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | version = "1.1.0"
3 | title = "isaac sim zmq bridge omnigraph nodes"
4 | description = "An Omnigraph node to communicate data in/out from Omniverse via zMQ"
5 | category = "Sample"
6 | keywords = ["bridge","example", "zmq", "cpp", "nodes", "omnigraph"]
7 | icon = "data/icon.png"
8 | preview_image = "data/preview.png"
9 | changelog = "docs/CHANGELOG.md"
10 | readme = "docs/README.md"
11 | authors = ["Lior Ben Horin "]
12 | repository="https://github.com/isaac-sim/IsaacSimZMQ"
13 |
14 | [dependencies]
15 | "omni.graph.core" = {}
16 | "omni.graph.tools" = {}
17 |
18 | [[python.module]]
19 | name = "isaacsim.zmq.bridge"
20 |
21 | [[native.plugin]]
22 | path = "bin/*.plugin"
23 |
24 |
25 | # Order of linkins is critical!
26 | # [[native.library]]
27 | # path = "bin/lib/libsodium.so.23"
28 | #[[native.library]]
29 | #path = "bin/lib/libsodium.so.18"
30 | #[[native.library]]
31 | #path = "bin/lib/libpgm-5.2.so.0"
32 | #[[native.library]]
33 | #path = "bin/lib/libnorm.so.1"
34 | [[native.library]]
35 | path = "bin/lib/libzmq.so.5"
36 | [[native.library]]
37 | path = "bin/lib/libzmq.so"
38 |
39 | [documentation]
40 | pages = [
41 | "docs/CHANGELOG.md",
42 | ]
43 |
--------------------------------------------------------------------------------
/proto/server_control_message.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | // Vector3 represents a 3D vector with x, y, z components
4 | message Vector3 {
5 | double x = 1;
6 | double y = 2;
7 | double z = 3;
8 | }
9 |
10 | // CameraControlCommand represents all camera-related controls
11 | message CameraControlCommand {
12 | Vector3 joints_vel = 1; // Velocities for camera mount joints (x, y, z axes)
13 | double focal_length = 2; // The focal length value
14 | }
15 |
16 | // SettingsCommand represents general control parameters
17 | message SettingsCommand {
18 | bool adaptive_rate = 1; // Whether to use adaptive rate
19 | }
20 |
21 | // FrankaCommand represents a command for the Franka robot
22 | message FrankaCommand {
23 | Vector3 effector_pos = 1; // The effector position
24 | bool show_marker = 2; // Whether to show the marker
25 | }
26 |
27 | // ServerControlMessage is the main message that can contain any of the command types
28 | message ServerControlMessage {
29 | // Only one of these fields will be set
30 | oneof command {
31 | CameraControlCommand camera_control_command = 1;
32 | SettingsCommand settings_command = 2;
33 | FrankaCommand franka_command = 3;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/repo.toml:
--------------------------------------------------------------------------------
1 | ########################################################################################################################
2 | # Repo tool base settings
3 | ########################################################################################################################
4 |
5 | [repo]
6 |
7 | # Use the Kit Template repo configuration as a base. Only override things specific to the repo.
8 | import_configs = ["${root}/_repo/deps/repo_kit_tools/kit-template/repo.toml"]
9 |
10 | # Repository Name
11 | name = "IsaacSimZMQ"
12 |
13 | [repo_build]
14 | msbuild.vs_version = "vs2019"
15 | post_build.commands = []
16 |
17 | [repo_build.premake]
18 | linux_x86_64_cxx_abi=true
19 |
20 | [repo_build.docker]
21 | enabled = false
22 |
23 |
24 | [repo_precache_exts]
25 | registries = [
26 | {name = "kit/default", url = "omniverse://kit-extensions.ov.nvidia.com/exts/kit/default"},
27 | {name = "kit/sdk", url = "omniverse://kit-extensions.ov.nvidia.com/exts/kit/sdk/${kit_version_short}/${kit_git_hash}"},
28 | ]
29 |
30 | ext_folders = [
31 | "${root}/exts",
32 | "${root}/exts/apps",
33 | ]
34 |
35 | [repo_symstore]
36 | enabled = false
37 |
38 | [repo_build.fetch.pip]
39 | ignore_pip_cache_failure = true
40 | licensing_enabled = false
41 | publish_pip_cache = false
42 |
43 | [repo_build.licensing]
44 | enabled = false
--------------------------------------------------------------------------------
/deps/repo-deps.packman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/tools/packman/python.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2019-2020 NVIDIA CORPORATION
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | set -e
18 |
19 | PACKMAN_CMD="$(dirname "${BASH_SOURCE}")/packman"
20 | if [ ! -f "$PACKMAN_CMD" ]; then
21 | PACKMAN_CMD="${PACKMAN_CMD}.sh"
22 | fi
23 | source "$PACKMAN_CMD" init
24 | export PYTHONPATH="${PM_MODULE_DIR}:${PYTHONPATH}"
25 |
26 | if [ -z "${PYTHONNOUSERSITE:-}" ]; then
27 | export PYTHONNOUSERSITE=1
28 | fi
29 |
30 | # For performance, default to unbuffered; however, allow overriding via
31 | # PYTHONUNBUFFERED=0 since PYTHONUNBUFFERED on windows can truncate output
32 | # when printing long strings
33 | if [ -z "${PYTHONUNBUFFERED:-}" ]; then
34 | export PYTHONUNBUFFERED=1
35 | fi
36 |
37 | # workaround for our python not shipping with certs
38 | if [[ -z ${SSL_CERT_DIR:-} ]]; then
39 | export SSL_CERT_DIR=/etc/ssl/certs/
40 | fi
41 |
42 | "${PM_PYTHON}" "$@"
43 |
--------------------------------------------------------------------------------
/tools/packman/bootstrap/fetch_file_from_packman_bootstrap.cmd:
--------------------------------------------------------------------------------
1 | :: Copyright 2019 NVIDIA CORPORATION
2 | ::
3 | :: Licensed under the Apache License, Version 2.0 (the "License");
4 | :: you may not use this file except in compliance with the License.
5 | :: You may obtain a copy of the License at
6 | ::
7 | :: http://www.apache.org/licenses/LICENSE-2.0
8 | ::
9 | :: Unless required by applicable law or agreed to in writing, software
10 | :: distributed under the License is distributed on an "AS IS" BASIS,
11 | :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | :: See the License for the specific language governing permissions and
13 | :: limitations under the License.
14 |
15 | :: You need to specify as input to this command
16 | @setlocal
17 | @set PACKAGE_NAME=%1
18 | @set TARGET_PATH=%2
19 |
20 | @echo Fetching %PACKAGE_NAME% ...
21 |
22 | @powershell -ExecutionPolicy ByPass -NoLogo -NoProfile -File "%~dp0download_file_from_url.ps1" ^
23 | -source "https://bootstrap.packman.nvidia.com/%PACKAGE_NAME%" -output %TARGET_PATH%
24 | :: A bug in powershell prevents the errorlevel code from being set when using the -File execution option
25 | :: We must therefore do our own failure analysis, basically make sure the file exists:
26 | @if not exist %TARGET_PATH% goto ERROR_DOWNLOAD_FAILED
27 |
28 | @endlocal
29 | @exit /b 0
30 |
31 | :ERROR_DOWNLOAD_FAILED
32 | @echo Failed to download file from S3
33 | @echo Most likely because endpoint cannot be reached or file %PACKAGE_NAME% doesn't exist
34 | @endlocal
35 | @exit /b 1
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/core/proto_util.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | import carb
5 | import omni
6 | import importlib
7 | import sys
8 | import types
9 |
10 |
11 | def register_proto_modules():
12 | """Register Protobuf modules in a persistent namespace to prevent hot-reload issues.
13 |
14 | Problem: Protobuf modules raise exceptions when hot-reloaded during extension reloads.
15 | Solution: Store imported modules in a persistent namespace (omni.__proto__) that survives
16 | extension reloads, preventing the need to reimport the modules.
17 | """
18 | namespace = "__proto__"
19 |
20 | # Create persistent namespace
21 | if not hasattr(omni, namespace):
22 | omni.__proto__ = types.ModuleType(f"omni.{namespace}")
23 | sys.modules[f"omni.{namespace}"] = omni.__proto__
24 |
25 | # List of protobuf modules to register
26 | proto_modules = [
27 | "server_control_message_pb2",
28 | "client_stream_message_pb2",
29 | ]
30 |
31 | # Import each module if not already registered
32 | for module_name in proto_modules:
33 | if not hasattr(omni.__proto__, module_name):
34 | try:
35 | imported_module = importlib.import_module(f".{module_name}", package=__package__)
36 | setattr(omni.__proto__, module_name, imported_module)
37 | except ImportError as e:
38 | carb.log_warn(f"Warning: Failed to import {module_name}: {e}")
39 |
--------------------------------------------------------------------------------
/tools/packman/bootstrap/download_file_from_url.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | Copyright 2019 NVIDIA CORPORATION
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | #>
16 |
17 | param(
18 | [Parameter(Mandatory=$true)][string]$source=$null,
19 | [string]$output="out.exe"
20 | )
21 | $filename = $output
22 |
23 | $triesLeft = 4
24 | $delay = 2
25 | do
26 | {
27 | $triesLeft -= 1
28 |
29 | try
30 | {
31 | Write-Host "Downloading from bootstrap.packman.nvidia.com ..."
32 | $wc = New-Object net.webclient
33 | $wc.Downloadfile($source, $fileName)
34 | exit 0
35 | }
36 | catch
37 | {
38 | Write-Host "Error downloading $source!"
39 | Write-Host $_.Exception|format-list -force
40 | if ($triesLeft)
41 | {
42 | Write-Host "Retrying in $delay seconds ..."
43 | Start-Sleep -seconds $delay
44 | }
45 | $delay = $delay * $delay
46 | }
47 | } while ($triesLeft -gt 0)
48 | # We only get here if the retries have been exhausted, remove any left-overs:
49 | if (Test-Path $fileName)
50 | {
51 | Remove-Item $fileName
52 | }
53 | exit 1
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | ## Security
2 |
3 | NVIDIA is dedicated to the security and trust of our software products and services, including all source code repositories managed through our organization.
4 |
5 | If you need to report a security issue, please use the appropriate contact points outlined below. **Please do not report security vulnerabilities through GitHub/GitLab.**
6 |
7 | ## Reporting Potential Security Vulnerability in an NVIDIA Product
8 |
9 | To report a potential security vulnerability in any NVIDIA product:
10 | - Web: [Security Vulnerability Submission Form](https://www.nvidia.com/object/submit-security-vulnerability.html)
11 | - E-Mail: psirt@nvidia.com
12 | - We encourage you to use the following PGP key for secure email communication: [NVIDIA public PGP Key for communication](https://www.nvidia.com/en-us/security/pgp-key)
13 | - Please include the following information:
14 | - Product/Driver name and version/branch that contains the vulnerability
15 | - Type of vulnerability (code execution, denial of service, buffer overflow, etc.)
16 | - Instructions to reproduce the vulnerability
17 | - Proof-of-concept or exploit code
18 | - Potential impact of the vulnerability, including how an attacker could exploit the vulnerability
19 |
20 | While NVIDIA currently does not have a bug bounty program, we do offer acknowledgement when an externally reported security issue is addressed under our coordinated vulnerability disclosure policy. Please visit our [Product Security Incident Response Team (PSIRT)](https://www.nvidia.com/en-us/security/psirt-policies/) policies page for more information.
21 |
22 | ## NVIDIA Product Security
23 |
24 | For all security-related concerns, please visit NVIDIA's Product Security portal at https://www.nvidia.com/en-us/security
25 |
26 |
--------------------------------------------------------------------------------
/deps/ext-deps.packman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/example_headless.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | # to run this file:
5 | # ISAACSIM_PYTHON exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/example_headless.py --ext-folder ./exts
6 |
7 | import isaacsim
8 | from isaacsim.simulation_app import SimulationApp
9 |
10 | # Set headless mode to True for GUI enabled.
11 | simulation_app = SimulationApp({"headless": True})
12 |
13 | import carb
14 | import omni.kit.app
15 |
16 | # Get the extension manager and enable our extension
17 | manager = omni.kit.app.get_app().get_extension_manager()
18 | manager.set_extension_enabled_immediate("isaacsim.zmq.bridge.examples", True)
19 |
20 |
21 | from isaacsim.zmq.bridge.examples import EXT_NAME
22 | from isaacsim.zmq.bridge.examples.example_missions import (
23 | FrankaMultiVisionMission,
24 | FrankaVisionMission,
25 | )
26 |
27 | # select an example mission here
28 | mission = FrankaVisionMission()
29 | # mission = FrankaMultiVisionMission() # Uncomment to use this mission instead
30 |
31 | # Load the mission USD file and set up the scene
32 | mission.load_mission()
33 | mission.reset_world()
34 |
35 | # Warm up the simulation with a few steps
36 | # This helps ensure caputured images wont have artifacts
37 | for i in range(100):
38 | simulation_app.update()
39 | print(f"[{EXT_NAME}] Warm up step {i+1}/20")
40 |
41 | # Start the mission
42 | # This will start the world simulation.
43 | mission.start_mission()
44 | print(f"[{EXT_NAME}] Streaming data...")
45 |
46 |
47 | while True:
48 | simulation_app.update() # run forever
49 |
50 | # This line is never reached,
51 | # Left to demonstrate how to gracefully close the app
52 | simulation_app.close()
53 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/plugins/nodes/OgnIsaacBridgeZMQCamera.ogn:
--------------------------------------------------------------------------------
1 | {
2 | "OgnIsaacBridgeZMQCamera": {
3 | "version": 1,
4 | "icon": "icons/isaac-sim.svg",
5 | "categories": "function",
6 | "description": ["Node to retrive camera extrinsics/intrinsics params"],
7 | "language": "c++",
8 | "metadata": {
9 | "uiName": "Isaac Bridge ZMQ Camera Params"
10 | },
11 | "inputs": {
12 | "execIn": {
13 | "type": "execution",
14 | "description": "Signal to the graph that this node is ready to be executed."
15 | },
16 | "cameraPrimPath": {
17 | "type": "path",
18 | "description": "Path of the camera prim.",
19 | "uiName": "Camera Prim Path"
20 | },
21 | "width": {
22 | "type": "uint",
23 | "description": "Camera resolution width",
24 | "default": 720
25 | },
26 | "height": {
27 | "type": "uint",
28 | "description": "Camera resolution height",
29 | "default": 720
30 | }
31 | },
32 | "outputs": {
33 | "cameraViewTransform" : {
34 | "type" : "frame[4]",
35 | "description" : "",
36 | "uiName" : "Camera View Transform in ROS world"
37 | },
38 | "cameraIntrinsics" : {
39 | "type" : "matrixd[3]",
40 | "description" : "",
41 | "uiName" : "Camera Intrinsitcs Matrix"
42 | },
43 | "cameraWorldScale" : {
44 | "type" : "double[3]",
45 | "description" : "",
46 | "uiName" : "Camera World Scale"
47 | }
48 | }
49 |
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/plugins/isaacsim.zmq.bridge/OgnIsaacBridgeZMQNodeExtension.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | // SPDX-License-Identifier: MIT
3 |
4 | #define CARB_EXPORTS
5 |
6 | #include
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | // Standard plugin definitions required by Carbonite.
14 | const struct carb::PluginImplDesc pluginImplDesc = { "isaacsim.zmq.bridge.plugin",
15 | "IsaacSim ZMQ Bridge C++ Ogn Nodes.", "NVIDIA",
16 | carb::PluginHotReload::eEnabled, "dev" };
17 |
18 | // These interface dependencies are required by all OmniGraph node types
19 | CARB_PLUGIN_IMPL_DEPS(omni::graph::core::IGraphRegistry,
20 | omni::fabric::IPath,
21 | omni::fabric::IToken)
22 |
23 | // This macro sets up the information required to register your node type definitions with OmniGraph
24 | DECLARE_OGN_NODES()
25 |
26 | namespace isaacsim
27 | {
28 | namespace zmq
29 | {
30 | namespace bridge
31 | {
32 |
33 | class OmniGraphIsaacZMQNodeExtension : public omni::ext::IExt
34 | {
35 | public:
36 | void onStartup(const char* extId) override
37 | {
38 | // This macro walks the list of pending node type definitions and registers them with OmniGraph
39 | INITIALIZE_OGN_NODES()
40 | }
41 |
42 | void onShutdown() override
43 | {
44 | // This macro walks the list of registered node type definitions and deregisters all of them. This is required
45 | // for hot reload to work.
46 | RELEASE_OGN_NODES()
47 | }
48 |
49 | private:
50 | };
51 |
52 | }
53 | }
54 | }
55 |
56 |
57 | CARB_PLUGIN_IMPL(pluginImplDesc, isaacsim::zmq::bridge::OmniGraphIsaacZMQNodeExtension)
58 |
59 | void fillInterface(isaacsim::zmq::bridge::OmniGraphIsaacZMQNodeExtension& iface)
60 | {
61 | }
62 |
--------------------------------------------------------------------------------
/isaac-zmq-server/src/server_control_message_pb2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: server_control_message.proto
4 | # Protobuf Python Version: 5.26.0
5 | """Generated protocol buffer code."""
6 | from google.protobuf import descriptor as _descriptor
7 | from google.protobuf import descriptor_pool as _descriptor_pool
8 | from google.protobuf import symbol_database as _symbol_database
9 | from google.protobuf.internal import builder as _builder
10 | # @@protoc_insertion_point(imports)
11 |
12 | _sym_db = _symbol_database.Default()
13 |
14 |
15 |
16 |
17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cserver_control_message.proto\"*\n\x07Vector3\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01\"J\n\x14\x43\x61meraControlCommand\x12\x1c\n\njoints_vel\x18\x01 \x01(\x0b\x32\x08.Vector3\x12\x14\n\x0c\x66ocal_length\x18\x02 \x01(\x01\"(\n\x0fSettingsCommand\x12\x15\n\radaptive_rate\x18\x01 \x01(\x08\"D\n\rFrankaCommand\x12\x1e\n\x0c\x65\x66\x66\x65\x63tor_pos\x18\x01 \x01(\x0b\x32\x08.Vector3\x12\x13\n\x0bshow_marker\x18\x02 \x01(\x08\"\xb2\x01\n\x14ServerControlMessage\x12\x37\n\x16\x63\x61mera_control_command\x18\x01 \x01(\x0b\x32\x15.CameraControlCommandH\x00\x12,\n\x10settings_command\x18\x02 \x01(\x0b\x32\x10.SettingsCommandH\x00\x12(\n\x0e\x66ranka_command\x18\x03 \x01(\x0b\x32\x0e.FrankaCommandH\x00\x42\t\n\x07\x63ommandb\x06proto3')
18 |
19 | _globals = globals()
20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'server_control_message_pb2', _globals)
22 | if not _descriptor._USE_C_DESCRIPTORS:
23 | DESCRIPTOR._loaded_options = None
24 | _globals['_VECTOR3']._serialized_start=32
25 | _globals['_VECTOR3']._serialized_end=74
26 | _globals['_CAMERACONTROLCOMMAND']._serialized_start=76
27 | _globals['_CAMERACONTROLCOMMAND']._serialized_end=150
28 | _globals['_SETTINGSCOMMAND']._serialized_start=152
29 | _globals['_SETTINGSCOMMAND']._serialized_end=192
30 | _globals['_FRANKACOMMAND']._serialized_start=194
31 | _globals['_FRANKACOMMAND']._serialized_end=262
32 | _globals['_SERVERCONTROLMESSAGE']._serialized_start=265
33 | _globals['_SERVERCONTROLMESSAGE']._serialized_end=443
34 | # @@protoc_insertion_point(module_scope)
35 |
--------------------------------------------------------------------------------
/proto/client_stream_message.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | // BBox2DType represents a single bounding box with semantic information
4 | message BBox2DType {
5 | uint32 semanticId = 1; // Unique identifier for the semantic class
6 | int32 xMin = 2; // Left coordinate of the bounding box
7 | int32 yMin = 3; // Top coordinate of the bounding box
8 | int32 xMax = 4; // Right coordinate of the bounding box
9 | int32 yMax = 5; // Bottom coordinate of the bounding box
10 | float occlusionRatio = 6; // Ratio indicating how much of the object is occluded (0-1)
11 | }
12 |
13 | // BBox2DInfo contains metadata for a collection of bounding boxes
14 | message BBox2DInfo {
15 | map idToLabels = 1; // Maps semantic IDs to human-readable labels
16 | repeated int32 bboxIds = 2; // List of bounding box identifiers
17 | }
18 |
19 | // BBox2D represents a complete set of bounding boxes with their metadata
20 | message BBox2D {
21 | repeated BBox2DType data = 1; // Collection of bounding boxes
22 | BBox2DInfo info = 2; // Metadata for the bounding boxes
23 | }
24 |
25 | // Clock contains timing information for synchronization
26 | message Clock {
27 | double sim_dt = 1; // Simulation delta time (seconds)
28 | double sys_dt = 2; // System delta time (seconds)
29 | double sim_time = 3; // Current simulation time (seconds)
30 | double sys_time = 4; // Current system time (seconds)
31 | }
32 |
33 | // Camera contains camera parameters and transformation matrices
34 | message Camera {
35 | repeated double view_matrix_ros = 1; // Flattened 4x4 matrix (size 16) for camera pose in ROS format
36 | repeated double camera_scale = 2; // Size 3 vector for camera scaling factors
37 | repeated double intrinsics_matrix = 3; // Flattened 3x3 matrix (size 9) for camera intrinsics
38 | }
39 |
40 | // ClientStreamMessage is the main message containing all data transmitted
41 | message ClientStreamMessage {
42 | BBox2D bbox2d = 1; // Bounding box data
43 | Clock clock = 2; // Timing information
44 | Camera camera = 3; // Camera parameters
45 | bytes color_image = 4; // RGB image data (encoded)
46 | bytes depth_image = 5; // Depth image data (encoded)
47 | }
48 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/core/server_control_message_pb2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: server_control_message.proto
4 | # Protobuf Python Version: 5.26.0
5 | """Generated protocol buffer code."""
6 | from google.protobuf import descriptor as _descriptor
7 | from google.protobuf import descriptor_pool as _descriptor_pool
8 | from google.protobuf import symbol_database as _symbol_database
9 | from google.protobuf.internal import builder as _builder
10 | # @@protoc_insertion_point(imports)
11 |
12 | _sym_db = _symbol_database.Default()
13 |
14 |
15 |
16 |
17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cserver_control_message.proto\"*\n\x07Vector3\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01\x12\t\n\x01z\x18\x03 \x01(\x01\"J\n\x14\x43\x61meraControlCommand\x12\x1c\n\njoints_vel\x18\x01 \x01(\x0b\x32\x08.Vector3\x12\x14\n\x0c\x66ocal_length\x18\x02 \x01(\x01\"(\n\x0fSettingsCommand\x12\x15\n\radaptive_rate\x18\x01 \x01(\x08\"D\n\rFrankaCommand\x12\x1e\n\x0c\x65\x66\x66\x65\x63tor_pos\x18\x01 \x01(\x0b\x32\x08.Vector3\x12\x13\n\x0bshow_marker\x18\x02 \x01(\x08\"\xb2\x01\n\x14ServerControlMessage\x12\x37\n\x16\x63\x61mera_control_command\x18\x01 \x01(\x0b\x32\x15.CameraControlCommandH\x00\x12,\n\x10settings_command\x18\x02 \x01(\x0b\x32\x10.SettingsCommandH\x00\x12(\n\x0e\x66ranka_command\x18\x03 \x01(\x0b\x32\x0e.FrankaCommandH\x00\x42\t\n\x07\x63ommandb\x06proto3')
18 |
19 | _globals = globals()
20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'server_control_message_pb2', _globals)
22 | if not _descriptor._USE_C_DESCRIPTORS:
23 | DESCRIPTOR._loaded_options = None
24 | _globals['_VECTOR3']._serialized_start=32
25 | _globals['_VECTOR3']._serialized_end=74
26 | _globals['_CAMERACONTROLCOMMAND']._serialized_start=76
27 | _globals['_CAMERACONTROLCOMMAND']._serialized_end=150
28 | _globals['_SETTINGSCOMMAND']._serialized_start=152
29 | _globals['_SETTINGSCOMMAND']._serialized_end=192
30 | _globals['_FRANKACOMMAND']._serialized_start=194
31 | _globals['_FRANKACOMMAND']._serialized_end=262
32 | _globals['_SERVERCONTROLMESSAGE']._serialized_start=265
33 | _globals['_SERVERCONTROLMESSAGE']._serialized_end=443
34 | # @@protoc_insertion_point(module_scope)
35 |
--------------------------------------------------------------------------------
/deps/kit-sdk-deps.packman.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/isaac-zmq-server/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nvidia/cuda:12.8.0-devel-ubuntu22.04
2 |
3 | # Create a non-root user and group for security
4 | RUN addgroup --system appgroup
5 | RUN adduser --system appuser --ingroup appgroup
6 |
7 | # Detect architecture during build time
8 | ARG TARGETARCH
9 | RUN echo "Target architecture: ${TARGETARCH}"
10 |
11 | # Install dependencies based on architecture
12 | RUN apt-get update && \
13 | if [ "${TARGETARCH}" = "arm64" ]; then \
14 | # Full dependencies for aarch64 (to build DearPyGui)
15 | apt-get --no-install-recommends install -y \
16 | python3 \
17 | python3-pip \
18 | libgl1-mesa-glx \
19 | libglib2.0-0 \
20 | git \
21 | build-essential \
22 | cmake \
23 | libpython3-dev \
24 | python3-setuptools \
25 | python3-wheel \
26 | libgl1-mesa-glx \
27 | libx11-dev \
28 | libgl-dev \
29 | libxrandr-dev \
30 | libxinerama-dev \
31 | libxcursor-dev \
32 | libxi-dev \
33 | && rm -rf /var/lib/apt/lists/*; \
34 | else \
35 | # Minimal dependencies for x86_64
36 | apt-get --no-install-recommends install -y \
37 | libgl1-mesa-glx \
38 | libglib2.0-0 \
39 | python3 \
40 | python3-pip \
41 | && rm -rf /var/lib/apt/lists/*; \
42 | fi
43 |
44 | RUN ln -sf /usr/bin/python3 /usr/bin/python \
45 | && ln -sf /usr/bin/pip3 /usr/bin/pip
46 |
47 | # Switch to the non-root user for security
48 | USER appuser
49 |
50 | # Install Python dependencies
51 | # - dearpygui: GUI framework for Python
52 | RUN if [ "${TARGETARCH}" = "arm64" ]; then \
53 | # For aarch64, build dearpygui from source
54 | cd /tmp && \
55 | git clone https://github.com/hoffstadt/DearPyGui.git && \
56 | cd DearPyGui && \
57 | git checkout v2.0.0 && git submodule update --init --recursive && \
58 | python3 -m setup bdist_wheel --plat-name linux_$(uname -m) --dist-dir ../dist && \
59 | cd ../dist && \
60 | pip install *.whl; \
61 | else \
62 | # For x86_64, install dearpygui directly
63 | pip install dearpygui==2.0.0; \
64 | fi
65 |
66 | ENV MESA_GL_VERSION_OVERRIDE=4.5
67 |
68 | # Install Python dependencies
69 | # - pytorch: for CUDA 12.8
70 | # - zmq: ZeroMQ messaging library
71 | # - opencv-python: Computer vision library
72 | # - protobuf: Protocol Buffers library
73 | RUN pip install torch --index-url https://download.pytorch.org/whl/cu128
74 | RUN pip install \
75 | pyzmq==26.4.0 \
76 | opencv-python \
77 | protobuf==5.26.0
78 |
79 | # Set the working directory for the application
80 | WORKDIR /isaac-zmq-server/src
81 |
82 | # Add the source code to the image (We will also mount it for dynamic updates)
83 | ADD ./src /isaac-zmq-server/src
--------------------------------------------------------------------------------
/isaac-zmq-server/src/client_stream_message_pb2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: client_stream_message.proto
4 | # Protobuf Python Version: 5.26.0
5 | """Generated protocol buffer code."""
6 | from google.protobuf import descriptor as _descriptor
7 | from google.protobuf import descriptor_pool as _descriptor_pool
8 | from google.protobuf import symbol_database as _symbol_database
9 | from google.protobuf.internal import builder as _builder
10 | # @@protoc_insertion_point(imports)
11 |
12 | _sym_db = _symbol_database.Default()
13 |
14 |
15 |
16 |
17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1b\x63lient_stream_message.proto\"p\n\nBBox2DType\x12\x12\n\nsemanticId\x18\x01 \x01(\r\x12\x0c\n\x04xMin\x18\x02 \x01(\x05\x12\x0c\n\x04yMin\x18\x03 \x01(\x05\x12\x0c\n\x04xMax\x18\x04 \x01(\x05\x12\x0c\n\x04yMax\x18\x05 \x01(\x05\x12\x16\n\x0eocclusionRatio\x18\x06 \x01(\x02\"\x81\x01\n\nBBox2DInfo\x12/\n\nidToLabels\x18\x01 \x03(\x0b\x32\x1b.BBox2DInfo.IdToLabelsEntry\x12\x0f\n\x07\x62\x62oxIds\x18\x02 \x03(\x05\x1a\x31\n\x0fIdToLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\">\n\x06\x42\x42ox2D\x12\x19\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0b.BBox2DType\x12\x19\n\x04info\x18\x02 \x01(\x0b\x32\x0b.BBox2DInfo\"K\n\x05\x43lock\x12\x0e\n\x06sim_dt\x18\x01 \x01(\x01\x12\x0e\n\x06sys_dt\x18\x02 \x01(\x01\x12\x10\n\x08sim_time\x18\x03 \x01(\x01\x12\x10\n\x08sys_time\x18\x04 \x01(\x01\"R\n\x06\x43\x61mera\x12\x17\n\x0fview_matrix_ros\x18\x01 \x03(\x01\x12\x14\n\x0c\x63\x61mera_scale\x18\x02 \x03(\x01\x12\x19\n\x11intrinsics_matrix\x18\x03 \x03(\x01\"\x88\x01\n\x13\x43lientStreamMessage\x12\x17\n\x06\x62\x62ox2d\x18\x01 \x01(\x0b\x32\x07.BBox2D\x12\x15\n\x05\x63lock\x18\x02 \x01(\x0b\x32\x06.Clock\x12\x17\n\x06\x63\x61mera\x18\x03 \x01(\x0b\x32\x07.Camera\x12\x13\n\x0b\x63olor_image\x18\x04 \x01(\x0c\x12\x13\n\x0b\x64\x65pth_image\x18\x05 \x01(\x0c\x62\x06proto3')
18 |
19 | _globals = globals()
20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'client_stream_message_pb2', _globals)
22 | if not _descriptor._USE_C_DESCRIPTORS:
23 | DESCRIPTOR._loaded_options = None
24 | _globals['_BBOX2DINFO_IDTOLABELSENTRY']._loaded_options = None
25 | _globals['_BBOX2DINFO_IDTOLABELSENTRY']._serialized_options = b'8\001'
26 | _globals['_BBOX2DTYPE']._serialized_start=31
27 | _globals['_BBOX2DTYPE']._serialized_end=143
28 | _globals['_BBOX2DINFO']._serialized_start=146
29 | _globals['_BBOX2DINFO']._serialized_end=275
30 | _globals['_BBOX2DINFO_IDTOLABELSENTRY']._serialized_start=226
31 | _globals['_BBOX2DINFO_IDTOLABELSENTRY']._serialized_end=275
32 | _globals['_BBOX2D']._serialized_start=277
33 | _globals['_BBOX2D']._serialized_end=339
34 | _globals['_CLOCK']._serialized_start=341
35 | _globals['_CLOCK']._serialized_end=416
36 | _globals['_CAMERA']._serialized_start=418
37 | _globals['_CAMERA']._serialized_end=500
38 | _globals['_CLIENTSTREAMMESSAGE']._serialized_start=503
39 | _globals['_CLIENTSTREAMMESSAGE']._serialized_end=639
40 | # @@protoc_insertion_point(module_scope)
41 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/core/client_stream_message_pb2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: client_stream_message.proto
4 | # Protobuf Python Version: 5.26.0
5 | """Generated protocol buffer code."""
6 | from google.protobuf import descriptor as _descriptor
7 | from google.protobuf import descriptor_pool as _descriptor_pool
8 | from google.protobuf import symbol_database as _symbol_database
9 | from google.protobuf.internal import builder as _builder
10 | # @@protoc_insertion_point(imports)
11 |
12 | _sym_db = _symbol_database.Default()
13 |
14 |
15 |
16 |
17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1b\x63lient_stream_message.proto\"p\n\nBBox2DType\x12\x12\n\nsemanticId\x18\x01 \x01(\r\x12\x0c\n\x04xMin\x18\x02 \x01(\x05\x12\x0c\n\x04yMin\x18\x03 \x01(\x05\x12\x0c\n\x04xMax\x18\x04 \x01(\x05\x12\x0c\n\x04yMax\x18\x05 \x01(\x05\x12\x16\n\x0eocclusionRatio\x18\x06 \x01(\x02\"\x81\x01\n\nBBox2DInfo\x12/\n\nidToLabels\x18\x01 \x03(\x0b\x32\x1b.BBox2DInfo.IdToLabelsEntry\x12\x0f\n\x07\x62\x62oxIds\x18\x02 \x03(\x05\x1a\x31\n\x0fIdToLabelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\">\n\x06\x42\x42ox2D\x12\x19\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0b.BBox2DType\x12\x19\n\x04info\x18\x02 \x01(\x0b\x32\x0b.BBox2DInfo\"K\n\x05\x43lock\x12\x0e\n\x06sim_dt\x18\x01 \x01(\x01\x12\x0e\n\x06sys_dt\x18\x02 \x01(\x01\x12\x10\n\x08sim_time\x18\x03 \x01(\x01\x12\x10\n\x08sys_time\x18\x04 \x01(\x01\"R\n\x06\x43\x61mera\x12\x17\n\x0fview_matrix_ros\x18\x01 \x03(\x01\x12\x14\n\x0c\x63\x61mera_scale\x18\x02 \x03(\x01\x12\x19\n\x11intrinsics_matrix\x18\x03 \x03(\x01\"\x88\x01\n\x13\x43lientStreamMessage\x12\x17\n\x06\x62\x62ox2d\x18\x01 \x01(\x0b\x32\x07.BBox2D\x12\x15\n\x05\x63lock\x18\x02 \x01(\x0b\x32\x06.Clock\x12\x17\n\x06\x63\x61mera\x18\x03 \x01(\x0b\x32\x07.Camera\x12\x13\n\x0b\x63olor_image\x18\x04 \x01(\x0c\x12\x13\n\x0b\x64\x65pth_image\x18\x05 \x01(\x0c\x62\x06proto3')
18 |
19 | _globals = globals()
20 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'client_stream_message_pb2', _globals)
22 | if not _descriptor._USE_C_DESCRIPTORS:
23 | DESCRIPTOR._loaded_options = None
24 | _globals['_BBOX2DINFO_IDTOLABELSENTRY']._loaded_options = None
25 | _globals['_BBOX2DINFO_IDTOLABELSENTRY']._serialized_options = b'8\001'
26 | _globals['_BBOX2DTYPE']._serialized_start=31
27 | _globals['_BBOX2DTYPE']._serialized_end=143
28 | _globals['_BBOX2DINFO']._serialized_start=146
29 | _globals['_BBOX2DINFO']._serialized_end=275
30 | _globals['_BBOX2DINFO_IDTOLABELSENTRY']._serialized_start=226
31 | _globals['_BBOX2DINFO_IDTOLABELSENTRY']._serialized_end=275
32 | _globals['_BBOX2D']._serialized_start=277
33 | _globals['_BBOX2D']._serialized_end=339
34 | _globals['_CLOCK']._serialized_start=341
35 | _globals['_CLOCK']._serialized_end=416
36 | _globals['_CAMERA']._serialized_start=418
37 | _globals['_CAMERA']._serialized_end=500
38 | _globals['_CLIENTSTREAMMESSAGE']._serialized_start=503
39 | _globals['_CLIENTSTREAMMESSAGE']._serialized_end=639
40 | # @@protoc_insertion_point(module_scope)
41 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/ui.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | import asyncio
5 | import os
6 | from pathlib import Path
7 |
8 | import carb
9 | import omni.ext
10 | import omni.ui as ui
11 | import omni.usd
12 | from omni.kit.notification_manager import NotificationStatus, post_notification
13 | from omni.kit.widget.toolbar import WidgetGroup
14 |
15 | from . import EXT_NAME
16 | from .mission import Mission
17 |
18 |
19 | def get_data_path() -> Path:
20 | manager = omni.kit.app.get_app().get_extension_manager()
21 | extension_path = manager.get_extension_path_by_module("isaacsim.zmq.bridge.examples")
22 | return Path(extension_path).joinpath("data")
23 |
24 |
25 | class ZMQClientButtonGroup(WidgetGroup):
26 | """
27 | UI widget group that provides buttons to start/stop streaming and reset the world.
28 | """
29 |
30 | def __init__(self):
31 | WidgetGroup.__init__(self)
32 | self._is_streaming = False
33 | self.mission = None
34 |
35 | def set_mission(self, mission: Mission) -> None:
36 | """
37 | Set the active mission for this button group.
38 |
39 | Args:
40 | mission (Mission): The mission to control with this button group
41 | """
42 | self.mission = mission
43 |
44 | def clean(self) -> None:
45 | """Clean up resources when the widget is destroyed."""
46 | super().clean()
47 | # self._start_stop_button = None
48 | self._reset_button = None
49 |
50 | def get_style(self) -> dict:
51 | return {}
52 |
53 | def on_reset_click(self) -> None:
54 | """
55 | Handle click on the reset world button.
56 |
57 | This method resets the world for the current mission.
58 | If no mission is set, it displays a popup notification.
59 | """
60 | if not self.mission:
61 | post_notification(
62 | f"[{EXT_NAME}] Please load a mission - Menu > Create > Isaac ZMQ Examples",
63 | duration=4,
64 | status=NotificationStatus.WARNING,
65 | )
66 | return
67 |
68 | self._reset_button.checked = False
69 | self.mission.reset_world_async()
70 |
71 | def create(self, default_size) -> None:
72 | """
73 | Create the UI buttons for the widget group.
74 | """
75 | # Create reset world button
76 | self._reset_button = ui.ToolButton(
77 | image_url="${glyphs}/menu_refresh.svg",
78 | name="resert_world",
79 | tooltip=f"Reset World",
80 | width=default_size,
81 | height=default_size,
82 | clicked_fn=self.on_reset_click,
83 | )
84 | self.set_visiblity(False)
85 |
86 | def set_visiblity(self, visible: bool) -> None:
87 | """
88 | Set the visibility of the buttons.
89 |
90 | Args:
91 | visible (bool): Whether the buttons should be visible
92 | """
93 | if hasattr(self, "_reset_button"):
94 | self._reset_button.visible = visible
95 |
--------------------------------------------------------------------------------
/tools/packman/packman.cmd:
--------------------------------------------------------------------------------
1 | :: RUN_PM_MODULE must always be at the same spot for packman update to work (batch reloads file during update!)
2 | :: [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
3 | :: Reset errorlevel status (don't inherit from caller)
4 | @call :ECHO_AND_RESET_ERROR
5 |
6 | :: You can remove this section if you do your own manual configuration of the dev machines
7 | call :CONFIGURE
8 | if %errorlevel% neq 0 ( exit /b %errorlevel% )
9 |
10 | :: Everything below is mandatory
11 | if not defined PM_PYTHON goto :PYTHON_ENV_ERROR
12 | if not defined PM_MODULE goto :MODULE_ENV_ERROR
13 |
14 | set PM_VAR_PATH_ARG=
15 |
16 | if "%1"=="pull" goto :SET_VAR_PATH
17 | if "%1"=="install" goto :SET_VAR_PATH
18 |
19 | :RUN_PM_MODULE
20 | "%PM_PYTHON%" -S -s -u -E "%PM_MODULE%" %* %PM_VAR_PATH_ARG%
21 | if %errorlevel% neq 0 ( exit /b %errorlevel% )
22 |
23 | :: Marshall environment variables into the current environment if they have been generated and remove temporary file
24 | if exist "%PM_VAR_PATH%" (
25 | for /F "usebackq tokens=*" %%A in ("%PM_VAR_PATH%") do set "%%A"
26 | )
27 | if %errorlevel% neq 0 ( goto :VAR_ERROR )
28 |
29 | if exist "%PM_VAR_PATH%" (
30 | del /F "%PM_VAR_PATH%"
31 | )
32 | if %errorlevel% neq 0 ( goto :VAR_ERROR )
33 |
34 | set PM_VAR_PATH=
35 | goto :eof
36 |
37 | :: Subroutines below
38 | :PYTHON_ENV_ERROR
39 | @echo User environment variable PM_PYTHON is not set! Please configure machine for packman or call configure.bat.
40 | exit /b 1
41 |
42 | :MODULE_ENV_ERROR
43 | @echo User environment variable PM_MODULE is not set! Please configure machine for packman or call configure.bat.
44 | exit /b 1
45 |
46 | :VAR_ERROR
47 | @echo Error while processing and setting environment variables!
48 | exit /b 1
49 |
50 | :: pad [xxxx]
51 | :ECHO_AND_RESET_ERROR
52 | @echo off
53 | if /I "%PM_VERBOSITY%"=="debug" (
54 | @echo on
55 | )
56 | exit /b 0
57 |
58 | :SET_VAR_PATH
59 | :: Generate temporary path for variable file
60 | for /f "delims=" %%a in ('%PM_PYTHON% -S -s -u -E -c "import tempfile;file = tempfile.NamedTemporaryFile(mode='w+t', delete=False);print(file.name)"') do (set PM_VAR_PATH=%%a)
61 | set PM_VAR_PATH_ARG=--var-path="%PM_VAR_PATH%"
62 | goto :RUN_PM_MODULE
63 |
64 | :CONFIGURE
65 | :: Must capture and set code page to work around issue #279, powershell invocation mutates console font
66 | :: This issue only happens in Windows CMD shell when using 65001 code page. Some Git Bash implementations
67 | :: don't support chcp so this workaround is a bit convoluted.
68 | :: Test for chcp:
69 | chcp > nul 2>&1
70 | if %errorlevel% equ 0 (
71 | for /f "tokens=2 delims=:" %%a in ('chcp') do (set PM_OLD_CODE_PAGE=%%a)
72 | ) else (
73 | call :ECHO_AND_RESET_ERROR
74 | )
75 | :: trim leading space (this is safe even when PM_OLD_CODE_PAGE has not been set)
76 | set PM_OLD_CODE_PAGE=%PM_OLD_CODE_PAGE:~1%
77 | if "%PM_OLD_CODE_PAGE%" equ "65001" (
78 | chcp 437 > nul
79 | set PM_RESTORE_CODE_PAGE=1
80 | )
81 | call "%~dp0\bootstrap\configure.bat"
82 | set PM_CONFIG_ERRORLEVEL=%errorlevel%
83 | if defined PM_RESTORE_CODE_PAGE (
84 | :: Restore code page
85 | chcp %PM_OLD_CODE_PAGE% > nul
86 | )
87 | set PM_OLD_CODE_PAGE=
88 | set PM_RESTORE_CODE_PAGE=
89 | exit /b %PM_CONFIG_ERRORLEVEL%
90 |
--------------------------------------------------------------------------------
/isaac-zmq-server/src/isaac_zmq_server/ui.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | import dearpygui.dearpygui as dpg
5 |
6 |
7 | class App:
8 | """
9 | Base class for creating the GUI with DearPyGUI.
10 |
11 | This class provides the basic structure for creating a window, setting up
12 | the application, and handling the main loop. Derived classes should implement
13 | the create_app_body and create_network_iface methods.
14 | """
15 |
16 | def __init__(self):
17 | """Initialize the application with default window settings."""
18 | self.window_name = "DearPyGUI App"
19 | self.window_width = 800
20 | self.window_height = 600
21 | self.resizeable = False
22 |
23 | def create_app_body(self):
24 | """
25 | Create the body of the application.
26 |
27 | This method should be implemented by derived classes to define the
28 | UI elements of the application.
29 |
30 | Raises:
31 | NotImplementedError: If the derived class does not implement this method.
32 | """
33 | raise NotImplementedError
34 |
35 | def create_network_iface(self):
36 | """
37 | Create the network interface for the application.
38 |
39 | This method should be implemented by derived classes to set up
40 | network communication.
41 |
42 | Raises:
43 | NotImplementedError: If the derived class does not implement this method.
44 | """
45 | raise NotImplementedError
46 |
47 | def _create_app(self) -> None:
48 | """
49 | Create the application window.
50 | """
51 | # Initialize DearPyGUI
52 | dpg.create_context()
53 | dpg.create_viewport(
54 | title=self.window_name,
55 | width=self.window_width,
56 | height=self.window_height,
57 | resizable=self.resizeable,
58 | )
59 | dpg.setup_dearpygui()
60 |
61 | # Set up fonts
62 | self.font_scale = 20
63 | with dpg.font_registry():
64 | font_medium = dpg.add_font("./isaac_zmq_server/fonts/Inter-Medium.ttf", 16 * self.font_scale)
65 |
66 | dpg.set_global_font_scale(1 / self.font_scale)
67 | dpg.bind_font(font_medium)
68 |
69 | # Create the application body
70 | self.create_app_body()
71 |
72 | # Show the viewport
73 | dpg.show_viewport()
74 |
75 | def _run(self) -> None:
76 | """
77 | Run the main application loop.
78 | """
79 | while dpg.is_dearpygui_running():
80 | dpg.render_dearpygui_frame()
81 |
82 | def _cleanup(self) -> None:
83 | """
84 | Clean up resources when the application is closed.
85 |
86 | This method cleans up the ZMQ server and destroys the DearPyGUI context.
87 | """
88 | self.zmq_server.cleanup()
89 | dpg.destroy_context()
90 |
91 | @classmethod
92 | def run_app(cls) -> None:
93 | """
94 | Static method to run the application.
95 | """
96 | app = cls()
97 | app._create_app()
98 | app.create_network_iface()
99 | app._run()
100 | app._cleanup()
101 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/premake5.lua:
--------------------------------------------------------------------------------
1 | -- Setup the basic extension information.
2 | local ext = get_current_extension_info()
3 | project_ext(ext)
4 |
5 | -- --------------------------------------------------------------------------------------------------------------
6 | -- Helper variable containing standard configuration information for projects containing OGN files.
7 | local ogn = get_ogn_project_information(ext, "isaacsim/zmq/bridge")
8 |
9 | -- --------------------------------------------------------------------------------------------------------------
10 | -- Link folders that should be packaged with the extension.
11 | repo_build.prebuild_link {
12 | { "data", ext.target_dir.."/data" },
13 | { "docs", ext.target_dir.."/docs" },
14 | }
15 |
16 | -- --------------------------------------------------------------------------------------------------------------
17 | -- Copy the __init__.py to allow building of a non-linked ogn/ import directory.
18 | -- In a mixed extension this would be part of a separate Python-based project but since here it is just the one
19 | -- file it can be copied directly with no build dependencies.
20 | repo_build.prebuild_copy {
21 | { "isaacsim/zmq/bridge/__init__.py", ogn.python_target_path }
22 | }
23 |
24 | -- --------------------------------------------------------------------------------------------------------------
25 | -- Breaking this out as a separate project ensures the .ogn files are processed before their results are needed.
26 | project_ext_ogn( ext, ogn )
27 |
28 | -- --------------------------------------------------------------------------------------------------------------
29 | -- Build the C++ plugin that will be loaded by the extension.
30 | project_ext_plugin(ext, ogn.plugin_project)
31 | -- It is important that you add all subdirectories containing C++ code to this project
32 | add_files("source", "plugins/"..ogn.module)
33 | add_files("nodes", "plugins/nodes")
34 |
35 | -- same as BUILD_SHARED_LIBS=OFF in CMake, for static linking
36 | staticruntime "On"
37 |
38 | includedirs { "%{target_deps}/python/include/python3.10",
39 | "%{target_deps}/usd/release/include",
40 | "%{target_deps}/protobuf/include",
41 | "%{target_deps}/zmq/include",
42 | "%{target_deps}/cppzmq/include",
43 | "%{target_deps}/libsodium/include",
44 | "%{target_deps}/abseil/include",
45 | }
46 | libdirs { "%{target_deps}/usd/release/lib",
47 | "%{target_deps}/protobuf/lib",
48 | "%{target_deps}/zmq/lib",
49 | "%{target_deps}/libsodium/lib",
50 | "%{target_deps}/abseil/lib",
51 | }
52 | buildoptions { "-fexceptions" }
53 |
54 | -- Dynamic linking
55 | links {"zmq"}
56 |
57 | -- Static linking
58 | linkoptions {
59 | "-Wl,--allow-multiple-definition",
60 | "-Wl,--whole-archive",
61 | -- Abseil
62 | "%{target_deps}/abseil/lib/libabsl_*.a",
63 | -- Protobuf
64 | "%{target_deps}/protobuf/lib/lib*.a",
65 | "-Wl,--no-whole-archive"
66 | }
67 |
68 | -- Begin OpenUSD
69 | add_usd("arch", "gf", "sdf", "tf", "usd", "usdGeom", "usdUtils")
70 | -- End OpenUSD
71 |
72 | -- Add the standard dependencies all OGN projects have; includes, libraries to link, and required compiler flags
73 | add_ogn_dependencies(ogn)
74 |
75 | -- -- RPATH linking
76 | -- linkoptions {
77 | -- "-Wl,-rpath,\\$$ORIGIN/lib"
78 | -- }
79 | cppdialect "C++17"
80 |
81 | -- Additional build options for static linking of abseil
82 | defines { "ABSL_BUILD_DLL=0" }
83 |
84 | filter "action:gmake*"
85 | linkoptions { "-static-libgcc", "-static-libstdc++" }
86 | filter {}
87 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/plugins/nodes/OgnIsaacBridgeZMQNode.ogn:
--------------------------------------------------------------------------------
1 | {
2 | "OgnIsaacBridgeZMQNode": {
3 | "version": 1,
4 | "uiName": "ZMQ Client Node",
5 | "icon": "icons/isaac-sim.svg",
6 | "description": [
7 | "This is a ZMQ Client responsible for sending out sensory data"
8 | ],
9 | "categories": ["function"],
10 | "language": "c++",
11 | "scheduling": "pure",
12 | "inputs": {
13 | "execIn": {
14 | "type": "execution",
15 | "description": "The input execution port."
16 | },
17 | "port": {
18 | "type": "uint",
19 | "description": "ZMQ server port",
20 | "default": 5561
21 | },
22 | "ip": {
23 | "type": "string",
24 | "description": "ZMQ server ip",
25 | "default": "localhost"
26 | },
27 | "deltaSimulationTime": {
28 | "type": "double",
29 | "description": "simulation delta time"
30 | },
31 | "deltaSystemTime": {
32 | "type": "double",
33 | "description": "system delta time"
34 | },
35 | "simulationTime": {
36 | "type": "double",
37 | "description": "simulation time"
38 | },
39 | "systemTime": {
40 | "type": "double",
41 | "description": "system time"
42 | },
43 | "bufferSizeColor": {
44 | "type": "uint64",
45 | "description": "Size (in bytes) of the buffer (0 if the input is a texture)"
46 | },
47 | "dataPtrColor": {
48 | "type": "uint64",
49 | "description": "Pointer to the raw data (cuda device pointer or host pointer)",
50 | "default": 0
51 | },
52 | "bufferSizeDepth": {
53 | "type": "uint64",
54 | "description": "Size (in bytes) of the buffer (0 if the input is a texture)"
55 | },
56 | "dataPtrDepth": {
57 | "type": "uint64",
58 | "description": "Pointer to the raw data (cuda device pointer or host pointer)",
59 | "default": 0
60 | },
61 | "bboxIdsBBox2d" : {
62 | "type": "uint[]",
63 | "description": "."
64 | },
65 | "bufferSizeBBox2d" : {
66 | "type": "uint",
67 | "description": ""
68 | },
69 | "dataBBox2d" : {
70 | "type": "uchar[]",
71 | "description": ""
72 | },
73 | "heightBBox2d" : {
74 | "type": "uint",
75 | "description": ""
76 | },
77 | "widthBBox2d" : {
78 | "type": "uint",
79 | "description": ""
80 | },
81 | "primPathsBBox2d" : {
82 | "type": "token[]",
83 | "description": ""
84 | },
85 | "labelsBBox2d" : {
86 | "type": "token[]",
87 | "description": ""
88 | },
89 | "idsBBox2d" : {
90 | "type": "uint[]",
91 | "description": ""
92 | },
93 | "cameraViewTransform" : {
94 | "type" : "frame[4]",
95 | "description" : "",
96 | "uiName" : "Camera View Transform in ROS world"
97 | },
98 | "cameraIntrinsics" : {
99 | "type" : "matrixd[3]",
100 | "description" : "",
101 | "uiName" : "Camera Intrinsitcs Matrix"
102 | },
103 | "cameraWorldScale" : {
104 | "type" : "double[3]",
105 | "description" : "",
106 | "uiName" : "Camera World Scale"
107 | }
108 | },
109 | "outputs": {}
110 | }
111 | }
--------------------------------------------------------------------------------
/assets/props/camera.usda:
--------------------------------------------------------------------------------
1 | #usda 1.0
2 | (
3 | customLayerData = {
4 | dictionary cameraSettings = {
5 | dictionary Front = {
6 | double3 position = (5, 0, 0)
7 | double radius = 5
8 | }
9 | dictionary Perspective = {
10 | double3 position = (-1.4111027697500935, 2.015850069579361, 1.1834364504018025)
11 | double3 target = (-0.16134589688674472, 0.23661424000629805, 0.5193712021654908)
12 | }
13 | dictionary Right = {
14 | double3 position = (0, -5, 0)
15 | double radius = 5
16 | }
17 | dictionary Top = {
18 | double3 position = (0, 0, 5)
19 | double radius = 5
20 | }
21 | string boundCamera = "/OmniverseKit_Persp"
22 | }
23 | dictionary omni_layer = {
24 | string authoring_layer = "./camera.usda"
25 | dictionary locked = {
26 | bool "./looks.usd" = 1
27 | bool "./model.usd" = 1
28 | bool "./physics.usd" = 1
29 | bool "./scale.usd" = 1
30 | bool "./sensor.usd" = 1
31 | }
32 | dictionary muteness = {
33 | }
34 | }
35 | dictionary physicsSettings = {
36 | int "/persistent/simulation/minFrameRate" = 60
37 | }
38 | dictionary renderSettings = {
39 | float3 "rtx:debugView:pixelDebug:textColor" = (0, 1e18, 0)
40 | float3 "rtx:fog:fogColor" = (0.75, 0.75, 0.75)
41 | float3 "rtx:index:backgroundColor" = (0, 0, 0)
42 | float3 "rtx:index:regionOfInterestMax" = (0, 0, 0)
43 | float3 "rtx:index:regionOfInterestMin" = (0, 0, 0)
44 | float3 "rtx:post:backgroundZeroAlpha:backgroundDefaultColor" = (0, 0, 0)
45 | float3 "rtx:post:colorcorr:contrast" = (1, 1, 1)
46 | float3 "rtx:post:colorcorr:gain" = (1, 1, 1)
47 | float3 "rtx:post:colorcorr:gamma" = (1, 1, 1)
48 | float3 "rtx:post:colorcorr:offset" = (0, 0, 0)
49 | float3 "rtx:post:colorcorr:saturation" = (1, 1, 1)
50 | float3 "rtx:post:colorgrad:blackpoint" = (0, 0, 0)
51 | float3 "rtx:post:colorgrad:contrast" = (1, 1, 1)
52 | float3 "rtx:post:colorgrad:gain" = (1, 1, 1)
53 | float3 "rtx:post:colorgrad:gamma" = (1, 1, 1)
54 | float3 "rtx:post:colorgrad:lift" = (0, 0, 0)
55 | float3 "rtx:post:colorgrad:multiply" = (1, 1, 1)
56 | float3 "rtx:post:colorgrad:offset" = (0, 0, 0)
57 | float3 "rtx:post:colorgrad:whitepoint" = (1, 1, 1)
58 | float3 "rtx:post:lensDistortion:lensFocalLengthArray" = (10, 30, 50)
59 | float3 "rtx:post:lensFlares:anisoFlareFalloffX" = (450, 475, 500)
60 | float3 "rtx:post:lensFlares:anisoFlareFalloffY" = (10, 10, 10)
61 | float3 "rtx:post:lensFlares:cutoffPoint" = (2, 2, 2)
62 | float3 "rtx:post:lensFlares:haloFlareFalloff" = (10, 10, 10)
63 | float3 "rtx:post:lensFlares:haloFlareRadius" = (75, 75, 75)
64 | float3 "rtx:post:lensFlares:isotropicFlareFalloff" = (50, 50, 50)
65 | float3 "rtx:post:lensFlares:spectralBlurWavelengthRange" = (380, 550, 770)
66 | float3 "rtx:post:tonemap:whitepoint" = (1, 1, 1)
67 | float3 "rtx:raytracing:indexdirect:svoBrickSize" = (32, 32, 32)
68 | float3 "rtx:raytracing:inscattering:singleScatteringAlbedo" = (0.9, 0.9, 0.9)
69 | float3 "rtx:raytracing:inscattering:transmittanceColor" = (0.5, 0.5, 0.5)
70 | float3 "rtx:sceneDb:ambientLightColor" = (0.1, 0.1, 0.1)
71 | float2 "rtx:viewTile:resolution" = (0, 0)
72 | }
73 | }
74 | defaultPrim = "World"
75 | endTimeCode = 1000000
76 | metersPerUnit = 1
77 | startTimeCode = 0
78 | subLayers = [
79 | @./sensor.usd@,
80 | @./physics.usd@,
81 | @./looks.usd@,
82 | @./scale.usd@,
83 | @./model.usd@
84 | ]
85 | timeCodesPerSecond = 60
86 | upAxis = "Z"
87 | )
88 |
89 | def Xform "World"
90 | {
91 | custom string cmd_path = ""
92 | }
93 |
94 |
--------------------------------------------------------------------------------
/tools/repoman/repoman_bootstrapper.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2019-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 | #
4 |
5 | import json
6 | import logging
7 | import os
8 | import platform
9 | from pathlib import Path
10 |
11 | logger = logging.getLogger(__name__)
12 |
13 | REPO_ROOT = os.path.join(os.path.dirname(os.path.normpath(__file__)), "../..")
14 | REPO_CACHE_FILE = os.path.join(REPO_ROOT, "repo-cache.json")
15 |
16 |
17 | def repoman_bootstrap():
18 | _path_checks()
19 | _prep_cache_paths()
20 |
21 |
22 | def _path_checks():
23 | """Check for problematic path conditions and warn appropriately."""
24 | cwd = os.getcwd()
25 | if " " in cwd:
26 | logger.warning(
27 | "Current working directory: %s contains whitespace which may cause issues with some tooling such as premake within repo_build. It is recommended to move your project to a path without spaces.",
28 | cwd,
29 | )
30 |
31 | # Check if current working directory is within a OneDrive folder
32 | if platform.system() == "Windows":
33 | onedrive_path = os.getenv("OneDrive") # For personal OneDrive
34 | onedrive_business_path = os.getenv("OneDriveCommercial") # For business accounts
35 |
36 | if not onedrive_path and not onedrive_business_path:
37 | # OneDrive is not installed or synced
38 | return
39 |
40 | if (onedrive_path and cwd.startswith(onedrive_path)) or (
41 | onedrive_business_path and cwd.startswith(onedrive_business_path)
42 | ):
43 | logger.warning(
44 | "Current working directory: %s appears to be within a OneDrive folder. This may cause filesystem issues with Packman linking dependencies. It is recommended to move your project outside of OneDrive.",
45 | cwd,
46 | )
47 |
48 |
49 | def _prep_cache_paths():
50 | """
51 | There are several environment variables that repo_man can optionally set to control where various caches are placed. They will all be relative to the repository root.
52 | - PM_PACKAGES_ROOT: this is where Packman stores its package cache
53 | - PIP_CACHE_DIR: this is where pip stores its wheel cache
54 | - UV_CACHE_DIR: this is where uv stores its wheel and package cache
55 |
56 | There are several gating flags as well to prevent repo_man from using the pip/uv default cache dir envvars unless explicitly set by us.
57 | - OM_PIP_CACHE: gating pip cache dir flag for omni.repo.man.deps.pip_install_requirements
58 | - OM_UV_CACHE: gating uv cache dir flag for omni.repo.man.deps._uv_requirements_load
59 | """
60 |
61 | repo_cache_file = Path(REPO_CACHE_FILE)
62 | if repo_cache_file.is_file():
63 | # cache file is present, read it in and set environment variables.
64 | cache_path_data = json.loads(repo_cache_file.read_text())
65 | # resolve REPO_ROOT rather than relative path to avoid any chdir shenanigans.
66 | resolved_root = Path(REPO_ROOT).resolve()
67 |
68 | for cache, cache_path in cache_path_data.items():
69 | # Expand $HOME and ~
70 | resolved_path = Path(os.path.expandvars(os.path.expanduser(cache_path)))
71 | if not resolved_path.is_dir():
72 | # Relative path to current working directory or absolute path is not present.
73 | # It's possible repo was somehow executed outside of the repository root.
74 | resolved_path = resolved_root / cache_path
75 |
76 | # Fully resolve path to avoid weird dir popping in some workflows.
77 | os.environ[cache] = resolved_path.resolve().as_posix()
78 | resolved_path.mkdir(parents=True, exist_ok=True)
79 |
80 | # Set repo_man breadcrumb to respect PIP_CACHE_DIR and UV_CACHE_DIR.
81 | # Unset OMNI_REPO_ROOT to force the caching of installed Python deps
82 | # in the packman cache dir.
83 | if cache == "PIP_CACHE_DIR":
84 | os.environ["OM_PIP_CACHE"] = "1"
85 | os.environ["OMNI_REPO_ROOT"] = ""
86 | elif cache == "UV_CACHE_DIR":
87 | os.environ["OM_UV_CACHE"] = "1"
88 | os.environ["OMNI_REPO_ROOT"] = ""
89 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/core/rate_limiter.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | import time
5 |
6 | from isaacsim.core.api.world import World
7 |
8 |
9 | # Concept mechanisim for controling stream rate, only used when not using c++ nodes
10 | class RateLimitedCallback:
11 | """
12 | Controls the execution rate of callbacks in the physics simulation.
13 |
14 | This class ensures that a callback function is executed at a specified rate,
15 | regardless of the physics simulation step frequency. It also provides an
16 | adaptive rate mechanism that adjusts the execution rate based on the actual
17 | execution time of the callback.
18 |
19 | Note: This class is only used when not using C++ OGN nodes for streaming.
20 | """
21 |
22 | def __init__(
23 | self,
24 | name: str,
25 | rate: float,
26 | fn: callable,
27 | start_time: float = 0.0,
28 | adeptive_rate: bool = True,
29 | ) -> None:
30 | """
31 | Initialize a rate-limited callback.
32 |
33 | Args:
34 | name (str): Name of the callback for identification
35 | rate (float): Target execution rate in seconds (1/Hz)
36 | fn (callable): Function to call at the specified rate
37 | start_time (float): Real world time at which the simulation started
38 | adeptive_rate (bool): Whether to adaptively adjust the rate based on execution time
39 | """
40 | self.world = World.instance()
41 | self.name = name
42 | self.fn = fn # function to call at rate
43 | self.rate = rate # 1/Hz
44 | self.previous_step_time = 0
45 | self.accumulated_time = 0
46 | self.last_exec_time = 0
47 |
48 | self.adeptive_rate = adeptive_rate
49 | self.start_time = start_time # real world time at which the simulation started
50 | self.interval = 3 # seconds between rate adjustments
51 | self.accumulated_interval_time = 0
52 | self.exec_count = 0
53 | self.actual_rate = rate
54 | self.adj_rate = rate
55 | self.rates_diff = 0
56 |
57 | def rate_limit(self, dt: float) -> None:
58 | """
59 | Execute the callback function at the specified rate.
60 |
61 | This method is called every simulation step, but only executes the callback
62 | function when enough time has accumulated to match the specified rate.
63 |
64 | When adaptive rate is enabled, it measures the actual execution rate and
65 | adjusts the target rate to compensate for execution time of the callback.
66 |
67 | Args:
68 | dt (float): Time step of the physics simulation
69 | """
70 | # -> Times here are real world times
71 | real_time = time.time() - self.start_time
72 | interval_time = real_time - self.accumulated_interval_time
73 |
74 | # Sample the actual rate each interval, by counting executions
75 | # Find the difference and set new adjusted rate
76 | if interval_time >= self.interval and self.adeptive_rate:
77 | self.accumulated_interval_time = real_time
78 | interval_rate = self.exec_count / interval_time
79 | self.actual_rate = (1 / interval_rate) if interval_rate > 0 else self.rate
80 | self.exec_count = 0
81 |
82 | # Adjust rate to compensate for execution time
83 | self.rates_diff = self.rate - self.actual_rate
84 | if abs(self.rate - self.actual_rate) > 0.001:
85 | self.adj_rate += self.rates_diff
86 |
87 | if not self.adeptive_rate:
88 | self.adj_rate = self.rate
89 |
90 | # -> Times here are simulated physical times
91 | elapsed_time = self.world.current_time - self.previous_step_time
92 | self.previous_step_time = self.world.current_time
93 |
94 | # Accumulate time until we reach the adjusted rate
95 | self.accumulated_time += elapsed_time
96 |
97 | # Execute the callback when enough time has accumulated
98 | if self.accumulated_time >= self.adj_rate:
99 | self.last_exec_time = self.fn(self.rate, self.world.current_time)
100 | self.accumulated_time -= self.adj_rate
101 | self.exec_count += 1
102 |
--------------------------------------------------------------------------------
/isaac-zmq-server/src/isaac_zmq_server/fonts/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)
2 |
3 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
4 | This license is copied below, and is also available with a FAQ at:
5 | http://scripts.sil.org/OFL
6 |
7 | -----------------------------------------------------------
8 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
9 | -----------------------------------------------------------
10 |
11 | PREAMBLE
12 | The goals of the Open Font License (OFL) are to stimulate worldwide
13 | development of collaborative font projects, to support the font creation
14 | efforts of academic and linguistic communities, and to provide a free and
15 | open framework in which fonts may be shared and improved in partnership
16 | with others.
17 |
18 | The OFL allows the licensed fonts to be used, studied, modified and
19 | redistributed freely as long as they are not sold by themselves. The
20 | fonts, including any derivative works, can be bundled, embedded,
21 | redistributed and/or sold with any software provided that any reserved
22 | names are not used by derivative works. The fonts and derivatives,
23 | however, cannot be released under any other type of license. The
24 | requirement for fonts to remain under this license does not apply
25 | to any document created using the fonts or their derivatives.
26 |
27 | DEFINITIONS
28 | "Font Software" refers to the set of files released by the Copyright
29 | Holder(s) under this license and clearly marked as such. This may
30 | include source files, build scripts and documentation.
31 |
32 | "Reserved Font Name" refers to any names specified as such after the
33 | copyright statement(s).
34 |
35 | "Original Version" refers to the collection of Font Software components as
36 | distributed by the Copyright Holder(s).
37 |
38 | "Modified Version" refers to any derivative made by adding to, deleting,
39 | or substituting -- in part or in whole -- any of the components of the
40 | Original Version, by changing formats or by porting the Font Software to a
41 | new environment.
42 |
43 | "Author" refers to any designer, engineer, programmer, technical
44 | writer or other person who contributed to the Font Software.
45 |
46 | PERMISSION AND CONDITIONS
47 | Permission is hereby granted, free of charge, to any person obtaining
48 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
49 | redistribute, and sell modified and unmodified copies of the Font
50 | Software, subject to the following conditions:
51 |
52 | 1) Neither the Font Software nor any of its individual components,
53 | in Original or Modified Versions, may be sold by itself.
54 |
55 | 2) Original or Modified Versions of the Font Software may be bundled,
56 | redistributed and/or sold with any software, provided that each copy
57 | contains the above copyright notice and this license. These can be
58 | included either as stand-alone text files, human-readable headers or
59 | in the appropriate machine-readable metadata fields within text or
60 | binary files as long as those fields can be easily viewed by the user.
61 |
62 | 3) No Modified Version of the Font Software may use the Reserved Font
63 | Name(s) unless explicit written permission is granted by the corresponding
64 | Copyright Holder. This restriction only applies to the primary font name as
65 | presented to the users.
66 |
67 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
68 | Software shall not be used to promote, endorse or advertise any
69 | Modified Version, except to acknowledge the contribution(s) of the
70 | Copyright Holder(s) and the Author(s) or with their explicit written
71 | permission.
72 |
73 | 5) The Font Software, modified or unmodified, in part or in whole,
74 | must be distributed entirely under this license, and must not be
75 | distributed under any other license. The requirement for fonts to
76 | remain under this license does not apply to any document created
77 | using the Font Software.
78 |
79 | TERMINATION
80 | This license becomes null and void if any of the above conditions are
81 | not met.
82 |
83 | DISCLAIMER
84 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
85 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
86 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
87 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
88 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
89 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
90 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
91 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
92 | OTHER DEALINGS IN THE FONT SOFTWARE.
--------------------------------------------------------------------------------
/tools/packman/packmanconf.py:
--------------------------------------------------------------------------------
1 | # Copyright 2021-2024 NVIDIA CORPORATION
2 |
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 |
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Use this file to bootstrap packman into your Python environment. Simply
16 | # add the path by doing sys.insert to where packmanconf.py is located and then execute:
17 | #
18 | # >>> import packmanconf
19 | # >>> packmanconf.init()
20 | #
21 | # It will use the configured remote(s) and the version of packman in the same folder,
22 | # giving you full access to the packman API via the following module
23 | #
24 | # >> import packmanapi
25 | # >> dir(packmanapi)
26 |
27 | import os
28 | import platform
29 | import sys
30 |
31 |
32 | MIN_PYTHON_VERSION = (3, 10, 0)
33 | MAX_PYTHON_VERSION = (3, 11, 2)
34 |
35 |
36 | def is_valid_python_version(version: tuple[int, int, int] = sys.version_info[:3]):
37 | return MIN_PYTHON_VERSION <= version <= MAX_PYTHON_VERSION
38 |
39 |
40 | def validate_python_version(version: tuple[int, int, int] = sys.version_info[:3]):
41 | if not is_valid_python_version(version):
42 |
43 | def ver_str(pyver):
44 | return ".".join(str(x) for x in pyver)
45 |
46 | raise RuntimeError(
47 | f"This version of packman requires Python {ver_str(MIN_PYTHON_VERSION)} "
48 | f"up to {ver_str(MAX_PYTHON_VERSION)}, but {ver_str(version)} was provided"
49 | )
50 |
51 |
52 | def init():
53 | """Call this function to initialize the packman configuration.
54 |
55 | Calls to the packman API will work after successfully calling this function.
56 |
57 | Note:
58 | This function only needs to be called once during the execution of your
59 | program. Calling it repeatedly is harmless but wasteful.
60 | Compatibility with your Python interpreter is checked and upon failure
61 | the function will report what is required.
62 |
63 | Example:
64 | >>> import packmanconf
65 | >>> packmanconf.init()
66 | >>> import packmanapi
67 | >>> packmanapi.set_verbosity_level(packmanapi.VERBOSITY_HIGH)
68 | """
69 | validate_python_version()
70 | conf_dir = os.path.dirname(os.path.abspath(__file__))
71 | os.environ["PM_INSTALL_PATH"] = conf_dir
72 | packages_root = get_packages_root(conf_dir)
73 | version = get_version(conf_dir)
74 | module_dir = get_module_dir(conf_dir, packages_root, version)
75 | sys.path.insert(1, module_dir)
76 |
77 |
78 | def get_packages_root(conf_dir: str) -> str:
79 | root = os.getenv("PM_PACKAGES_ROOT")
80 | if not root:
81 | platform_name = platform.system()
82 | if platform_name == "Windows":
83 | drive, _ = os.path.splitdrive(conf_dir)
84 | root = os.path.join(drive, "packman-repo")
85 | elif platform_name == "Darwin":
86 | # macOS
87 | root = os.path.join(
88 | os.path.expanduser("~"), "Library/Application Support/packman-cache"
89 | )
90 | elif platform_name == "Linux":
91 | try:
92 | cache_root = os.environ["XDG_HOME_CACHE"]
93 | except KeyError:
94 | cache_root = os.path.join(os.path.expanduser("~"), ".cache")
95 | return os.path.join(cache_root, "packman")
96 | else:
97 | raise RuntimeError(f"Unsupported platform '{platform_name}'")
98 | # make sure the path exists:
99 | os.makedirs(root, exist_ok=True)
100 | return root
101 |
102 |
103 | def get_module_dir(conf_dir, packages_root: str, version: str) -> str:
104 | module_dir = os.path.join(packages_root, "packman-common", version)
105 | if not os.path.exists(module_dir):
106 | import tempfile
107 |
108 | tf = tempfile.NamedTemporaryFile(delete=False)
109 | target_name = tf.name
110 | tf.close()
111 | # Forced to change to https because some customers will simply not allow http,
112 | # even when it's used in a safe way (with download checksum verification).
113 | # See issue #367 for more background.
114 | url = f"https://bootstrap.packman.nvidia.com/packman-common@{version}.zip"
115 | print(f"Downloading '{url}' ...")
116 | import urllib.request
117 |
118 | urllib.request.urlretrieve(url, target_name)
119 | from importlib.machinery import SourceFileLoader
120 |
121 | # import module from path provided
122 | script_path = os.path.join(conf_dir, "bootstrap", "install_package.py")
123 | ip = SourceFileLoader("install_package", script_path).load_module()
124 | print("Unpacking ...")
125 | ip.install_common_module(target_name, module_dir)
126 | os.unlink(tf.name)
127 | return module_dir
128 |
129 |
130 | def get_version(conf_dir: str):
131 | path = os.path.join(conf_dir, "packman")
132 | if not os.path.exists(path): # in dev repo fallback
133 | path += ".sh"
134 | with open(path, "rt", encoding="utf8") as launch_file:
135 | for line in launch_file.readlines():
136 | if "PM_PACKMAN_VERSION" in line:
137 | _, value = line.split("=")
138 | return value.strip()
139 | raise RuntimeError(f"Unable to find 'PM_PACKMAN_VERSION' in '{path}'")
140 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/mission.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | import asyncio
5 | import time
6 | from pathlib import Path
7 | import zmq.asyncio
8 |
9 | import omni
10 | import carb
11 |
12 | import isaacsim.core.utils.stage as stage_utils
13 | from isaacsim.core.api.world import World
14 |
15 | from . import EXT_NAME, ZMQClient
16 |
17 |
18 | class Mission:
19 | """Base class for all ZMQ bridge missions.
20 |
21 | This class provides the foundation for creating missions that communicate with external
22 | applications via ZeroMQ. Derived classes should implement the mission-specific logic
23 | by overriding methods like before_reset_world, after_reset_world, start_mission, etc.
24 | """
25 |
26 | name = "Mission"
27 | world_usd_path = None # Should be set by derived classes to point to the USD world file
28 |
29 | def __init__(self, server_ip: str = "localhost"):
30 | self.zmq_client = ZMQClient(server_ip=server_ip)
31 |
32 | self.receive_commands = False
33 |
34 | def before_reset_world(self) -> None:
35 | """
36 | Prepare the world for reset
37 | """
38 | carb.log_warn(f"[{EXT_NAME}] before reset world: NOT IMPLEMENTED")
39 |
40 | def after_reset_world(self) -> None:
41 | """
42 | Execute any operation that requried a clean world.
43 | """
44 | carb.log_warn(f"[{EXT_NAME}] after reset world: NOT IMPLEMENTED")
45 |
46 | def start_mission(self) -> None:
47 | """
48 | Starts the mission by initializing the necessary sockets, annotators, and callbacks.
49 | """
50 | carb.log_warn(f"[{EXT_NAME}] start mission: NOT IMPLEMENTED")
51 |
52 | def reset_world(self) -> None:
53 | self.world = World(physics_dt=1.0 / self.physics_dt)
54 | # Clear only the registry to maintain stage structure
55 | self.world.scene.clear(registry_only=True)
56 | self.before_reset_world()
57 | self.world.reset()
58 | self.after_reset_world()
59 |
60 | def stop_mission(self) -> None:
61 | """
62 | Stops the current mission by setting the `receive_commands` flag to False and removing all callbacks from the ZMQ client.
63 | It also ensures that all connections are disconnected asynchronously.
64 |
65 | """
66 | carb.log_warn(f"[{EXT_NAME}] stop mission: NOT IMPLEMENTED")
67 |
68 | def subscribe_to_protobuf_in_loop(
69 | self, socket: zmq.asyncio.Socket, proto_class, fn: callable, *args, **kwargs
70 | ) -> None:
71 | """
72 | Runs a loop that continuously receives protobuf messages from a ZeroMQ socket and calls a given function for each received message.
73 |
74 | Args:
75 | socket (zmq.asyncio.Socket): The ZeroMQ socket to receive data from.
76 | proto_class: The protobuf message class to parse the received data.
77 | fn (callable): The function to call for each received protobuf message.
78 | """
79 |
80 | async def _async_executor() -> None:
81 | # Continue receiving data as long as receive_commands flag is True
82 | while self.receive_commands:
83 | proto_msg = await self.zmq_client.receive_protobuf(socket, proto_class)
84 | fn(proto_msg, *args, **kwargs)
85 | carb.log_info(f"[{socket}] Stopped listening for protobuf messages.")
86 |
87 | asyncio.ensure_future(_async_executor())
88 |
89 | @classmethod
90 | def mission_usd_path(cls) -> str:
91 | """
92 | For the headless example, we need to import the stage progrematically.
93 | """
94 | # Get the extension path to locate assets
95 | manager = omni.kit.app.get_app().get_extension_manager()
96 | extension_path = manager.get_extension_path_by_module("isaacsim.zmq.bridge.examples")
97 | data_path = Path(extension_path).joinpath("data")
98 | assets_path = data_path.parent.parent.parent / "assets"
99 | source_usd = str(assets_path / cls.world_usd_path)
100 |
101 | return source_usd
102 |
103 | @classmethod
104 | def load_mission(cls, source_usd: str) -> None:
105 | """
106 | Loads the mission by opening the stage file.
107 | """
108 | print(f"[{EXT_NAME}] loading mission")
109 | stage_utils.open_stage(source_usd)
110 |
111 | def reset_world_async(self) -> None:
112 | carb.log_warn(f"[{EXT_NAME}] reset world async: NOT IMPLEMENTED")
113 |
114 | @classmethod
115 | async def _async_load(cls, source_usd: str) -> None:
116 | await stage_utils.open_stage_async(source_usd)
117 |
118 | @classmethod
119 | def load_mission_async(cls) -> None:
120 | print(f"[{EXT_NAME}] loading mission")
121 | asyncio.ensure_future(cls._async_load())
122 |
123 | async def stop_mission_async(self) -> None:
124 | """
125 | Stop the mission and clean up resources.
126 | """
127 | carb.log_warn(f"[{EXT_NAME}] stop mission: NOT IMPLEMENTED")
128 |
129 | async def _reset(self) -> None:
130 | """
131 | similar to reset_world() but async
132 | """
133 | await self.stop_mission_async()
134 | self.world = World(physics_dt=1.0 / self.physics_dt)
135 | # Clear only the registry to maintain stage structure
136 | self.world.scene.clear(registry_only=True)
137 | # Initialize simulation context asynchronously
138 | await self.world.initialize_simulation_context_async()
139 | self.before_reset_world()
140 | await self.world.reset_async()
141 | self.after_reset_world()
142 | self.start_mission()
143 |
144 | def reset_world_async(self) -> None:
145 | asyncio.ensure_future(self._reset())
146 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/extension.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 |
5 | from functools import partial
6 |
7 | import carb
8 | import omni.ext
9 | import omni.ui as ui
10 | import omni.usd
11 | from omni.kit.menu.utils import MenuItemDescription, add_menu_items, remove_menu_items
12 | from omni.kit.notification_manager import post_notification
13 | from omni.kit.widget.toolbar import get_instance
14 | import omni.timeline
15 |
16 | from . import EXT_NAME
17 | from .example_missions import FrankaMultiVisionMission, FrankaVisionMission
18 | from .ui import ZMQClientButtonGroup
19 |
20 |
21 | class IsaacSimZMQBridgeExamples(omni.ext.IExt):
22 | """Extension for demonstrating ZMQ bridge functionality in Isaac Sim.
23 |
24 | This extension provides UI elements and mission management for ZMQ bridge examples,
25 | allowing users to load different example missions and control their execution.
26 | """
27 |
28 | server_ip = "localhost"
29 |
30 | def on_startup(self, ext_id) -> None:
31 | self.mission = None
32 |
33 | # Append example buttons to the main isaac sim toolbar
34 | self.toolbar = get_instance()
35 | self.button_group = ZMQClientButtonGroup()
36 | self.toolbar.add_widget(self.button_group, 100, self.toolbar.get_context())
37 |
38 | # Append example menu items to the main isaac sim menu
39 | self._franka_mission_menu = MenuItemDescription(
40 | name="Franka RMPFlow",
41 | glyph="plug.svg",
42 | onclick_fn=FrankaVisionMission.load_mission_async,
43 | )
44 | self._franka_multi_mission_menu = MenuItemDescription(
45 | name="Franka RMPFlow (Multi Camera)",
46 | glyph="plug.svg",
47 | onclick_fn=FrankaMultiVisionMission.load_mission_async,
48 | )
49 |
50 | self._menu_items = [
51 | MenuItemDescription(
52 | name="Isaac ZMQ Examples",
53 | glyph="plug.svg",
54 | sub_menu=[self._franka_mission_menu, self._franka_multi_mission_menu],
55 | )
56 | ]
57 | add_menu_items(self._menu_items, "Create")
58 |
59 | # Subscribe to stage events to detect when a new stage is loaded / Cleared
60 | self.stage_load_sub = (
61 | omni.usd.get_context()
62 | .get_stage_event_stream()
63 | .create_subscription_to_pop(self.stage_event, name="event_stage_loaded")
64 | )
65 | self.check_stage()
66 |
67 | # Subscribe to timeline events to detect when the timeline is stopped
68 | self.timeline = omni.timeline.get_timeline_interface()
69 | self.timeline_sub = (
70 | self.timeline
71 | .get_timeline_event_stream()
72 | .create_subscription_to_pop(self.timeline_event,
73 | name="timeline_event")
74 | )
75 |
76 | def timeline_event(self, event) -> None:
77 | if event.type == int(omni.timeline.TimelineEventType.STOP):
78 | if self.mission:
79 | self.mission.stop_mission()
80 |
81 | def stage_event(self, event) -> None:
82 | """Handle stage events.
83 |
84 | When a stage is opened, check if it matches any of our example missions.
85 | """
86 | if event.type == int(omni.usd.StageEventType.OPENED):
87 | self.check_stage()
88 |
89 | def check_stage(self) -> None:
90 | """Check the current stage and set the appropriate mission.
91 |
92 | This method examines the loaded USD file and sets the corresponding mission
93 | if it matches one of our example missions.
94 | """
95 | # set the mission based on the loaded stage
96 | stage = omni.usd.get_context().get_stage()
97 | if not stage:
98 | return
99 | usd_path = stage.GetRootLayer().realPath
100 | if usd_path.endswith(FrankaVisionMission.world_usd_path):
101 | self._set_mission(FrankaVisionMission, "FrankaVisionMission")
102 | elif usd_path.endswith(FrankaMultiVisionMission.world_usd_path):
103 | self._set_mission(FrankaMultiVisionMission, "FrankaMultiVisionMission")
104 | else:
105 | self._clear_mission()
106 | return
107 |
108 | def _set_mission(self, mission_class, mission_name) -> None:
109 | """Set the active mission.
110 |
111 | Creates an instance of the specified mission class and assigns it to the button group.
112 |
113 | Args:
114 | mission_class: The mission class to instantiate
115 | mission_name: The name of the mission for logging
116 | """
117 | print(f"[{EXT_NAME}] Setting {mission_name}.")
118 | post_notification(f"[{EXT_NAME}] Setting {mission_name}.", duration=2)
119 | self.mission = mission_class(server_ip=self.server_ip)
120 | self.button_group.set_mission(self.mission)
121 | self.button_group.set_visiblity(True)
122 |
123 | def _clear_mission(self) -> None:
124 | """Clear the active mission.
125 |
126 | Called when the loaded stage doesn't match any of our example missions.
127 | """
128 | carb.log_warn(f"[{EXT_NAME}] Stage is empty - Setting mission to None")
129 | post_notification(f"[{EXT_NAME}] Setting mission to None", duration=2)
130 | self.mission = None
131 | self.button_group.set_mission(None)
132 | self.button_group.set_visiblity(False)
133 |
134 | def on_shutdown(self) -> None:
135 | """Clean up resources when the extension is disabled.
136 |
137 | Stops any active mission and removes UI elements.
138 | """
139 | if self.mission:
140 | self.mission.stop_mission()
141 |
142 | self.toolbar.remove_widget(self.button_group)
143 | self.button_group = None
144 |
145 | remove_menu_items(self._menu_items, "Create")
146 |
147 | self.stage_load_sub = None
148 | self.timeline_sub = None
149 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/plugins/nodes/OgnIsaacBridgeZMQCamera.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | // SPDX-License-Identifier: MIT
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #include
15 |
16 | #include
17 | #include
18 | #include
19 |
20 | #include
21 |
22 |
23 | using omni::graph::core::Type;
24 | using omni::graph::core::BaseDataType;
25 |
26 |
27 | namespace isaacsim {
28 | namespace zmq {
29 | namespace bridge {
30 |
31 |
32 | class OgnIsaacBridgeZMQCamera
33 | {
34 | // int m_evaluationCount{ 0 };
35 |
36 | public:
37 | OgnIsaacBridgeZMQCamera()
38 | {
39 | CARB_LOG_INFO("OgnIsaacBridgeZMQCamera::constructor\n");
40 | }
41 | ~OgnIsaacBridgeZMQCamera()
42 | {
43 | CARB_LOG_INFO("OgnIsaacBridgeZMQCamera::destructor\n");
44 | }
45 |
46 |
47 | static bool compute(OgnIsaacBridgeZMQCameraDatabase& db);
48 |
49 | static pxr::GfMatrix4d get_view_matrix_ros(const pxr::UsdPrim& cameraPrim);
50 |
51 | static pxr::GfMatrix3d get_intrinsics_matrix(const pxr::UsdPrim& cameraPrim, uint32_t width, uint32_t height);
52 |
53 | };
54 |
55 |
56 | pxr::GfMatrix4d OgnIsaacBridgeZMQCamera::get_view_matrix_ros(const pxr::UsdPrim& cameraPrim)
57 | {
58 | // c++ implementation omni.isaac.sensor.camera.Camera.get_view_matrix_ros() by ai :)
59 |
60 | // Step 1: Get the world-to-camera transformation matrix
61 | pxr::UsdGeomXformable xformable(cameraPrim);
62 | pxr::GfMatrix4d local_to_world_tf = xformable.ComputeLocalToWorldTransform(pxr::UsdTimeCode::Default());
63 |
64 | // Convert the matrix type from double to float and transpose
65 | pxr::GfMatrix4d world_w_cam_u_T = local_to_world_tf.GetTranspose();
66 |
67 | // Step 2: Define R_U_TRANSFORM as a fixed transformation matrix
68 | static const pxr::GfMatrix4d r_u_transform_converted(
69 | 1, 0, 0, 0,
70 | 0, -1, 0, 0,
71 | 0, 0, -1, 0,
72 | 0, 0, 0, 1
73 | );
74 |
75 | // Step 3: Perform matrix inversion using GfMatrix4f's Inverse() method
76 | pxr::GfMatrix4d inverse_world_w_cam_u_T = world_w_cam_u_T.GetInverse();
77 |
78 | // Step 4: Perform matrix multiplication of r_u_transform_converted and inverse_world_w_cam_u_T
79 | pxr::GfMatrix4d result_matrix = r_u_transform_converted * inverse_world_w_cam_u_T;
80 |
81 | // Return the final view matrix
82 | return result_matrix;
83 |
84 |
85 | // results from a python call:
86 | // [[ 8.8442159e-01 -4.1348362e-01 -2.1640186e-01 0.0000000e+00]
87 | // [-4.0163556e-01 -9.1051155e-01 9.8272912e-02 0.0000000e+00]
88 | // [-2.3767065e-01 -3.2561711e-09 -9.7134584e-01 0.0000000e+00]
89 | // [ 0.0000000e+00 0.0000000e+00 0.0000000e+00 1.0000000e+00]]
90 |
91 | //results from this call - appear to be 10x smaller...
92 | // 0.884422 -0.413484 -0.216402 0.000000
93 | // -0.401636 -0.910512 0.098273 0.000000
94 | // -0.237671 0.000000 -0.971346 0.000000
95 | // 0.000000 0.000000 0.000000 1.000000
96 | }
97 |
98 |
99 | pxr::GfMatrix3d OgnIsaacBridgeZMQCamera::get_intrinsics_matrix(const pxr::UsdPrim& cameraPrim, uint32_t width, uint32_t height)
100 | {
101 | // c++ implementation omni.isaac.sensor.camera.Camera.get_intrinsics_matrix() by ai :)
102 |
103 | // Get attributes for focal length and horizontal aperture
104 | pxr::UsdGeomCamera camera(cameraPrim);
105 |
106 | pxr::VtValue focal_length_value;
107 | camera.GetFocalLengthAttr().Get(&focal_length_value, pxr::UsdTimeCode::Default());
108 |
109 | static constexpr float scale_factor = 10.0f; // Used in multiple places
110 | float focal_length = focal_length_value.Get() / scale_factor;
111 |
112 | pxr::VtValue horizontal_aperture_value;
113 | camera.GetHorizontalApertureAttr().Get(&horizontal_aperture_value, pxr::UsdTimeCode::Default());
114 | float horizontal_aperture = horizontal_aperture_value.Get() / scale_factor;
115 |
116 | float vertical_aperture = horizontal_aperture * (static_cast(height) / width);
117 |
118 | // Calculate intrinsic parameters
119 | float fx = width * focal_length / horizontal_aperture;
120 | float fy = height * focal_length / vertical_aperture;
121 | float cx = width * 0.5f;
122 | float cy = height * 0.5f;
123 |
124 | // Return the intrinsic matrix as pxr::GfMatrix3f
125 | return pxr::GfMatrix3d(fx, 0.0f, cx, 0.0f, fy, cy, 0.0f, 0.0f, 1.0f);
126 | }
127 |
128 |
129 | bool OgnIsaacBridgeZMQCamera::compute(OgnIsaacBridgeZMQCameraDatabase& db)
130 | {
131 | // Get USD Stage
132 | const IPath& iPath = *db.abi_context().iPath;
133 | long stageId = db.abi_context().iContext->getStageId(db.abi_context());
134 | pxr::UsdStageRefPtr stage = pxr::UsdUtilsStageCache::Get().Find(pxr::UsdStageCache::Id::FromLongInt(stageId));
135 |
136 | // // // Get Camera Prim
137 | std::string cameraPrimPathStr = db.inputs.cameraPrimPath();
138 | if (cameraPrimPathStr.empty())
139 | {
140 | db.logWarning("No target prim path specified");
141 | return true;
142 | }
143 | pxr::SdfPath cameraPrimPath(cameraPrimPathStr.c_str());
144 | pxr::UsdPrim cameraPrim = stage->GetPrimAtPath(cameraPrimPath);
145 |
146 | // // Get the local-to-world transform of the camera prim
147 | pxr::UsdGeomXformable xformable(cameraPrim);
148 | pxr::GfMatrix4d prim_tf = xformable.ComputeLocalToWorldTransform(pxr::UsdTimeCode::Default());
149 | pxr::GfTransform transform;
150 | transform.SetMatrix(prim_tf);
151 | pxr::GfVec3d scale = transform.GetScale();
152 | db.outputs.cameraWorldScale() = scale;
153 |
154 | uint32_t width = db.inputs.width();
155 | uint32_t height = db.inputs.height();
156 |
157 | // // Get the view matrix corrected for ROS conventions
158 | pxr::GfMatrix4d view_matrix_ros = get_view_matrix_ros(cameraPrim);
159 | db.outputs.cameraViewTransform() = view_matrix_ros;
160 |
161 | // // Get the camera intrinsics matrix
162 | pxr::GfMatrix3d intrinsics_matrix = get_intrinsics_matrix(cameraPrim, width, height);
163 | db.outputs.cameraIntrinsics() = intrinsics_matrix;
164 |
165 | // Returning true tells Omnigraph that the compute was successful and the output value is now valid.
166 | return true;
167 | }
168 |
169 | // This macro provides the information necessary to OmniGraph that lets it automatically register and deregister
170 | // your node type definition.
171 | REGISTER_OGN_NODE()
172 |
173 |
174 | } // bridge
175 | } // zmq
176 | } // isaacsim
177 |
--------------------------------------------------------------------------------
/tools/packman/bootstrap/configure.bat:
--------------------------------------------------------------------------------
1 | :: Copyright 2019-2023 NVIDIA CORPORATION
2 | ::
3 | :: Licensed under the Apache License, Version 2.0 (the "License");
4 | :: you may not use this file except in compliance with the License.
5 | :: You may obtain a copy of the License at
6 | ::
7 | :: http://www.apache.org/licenses/LICENSE-2.0
8 | ::
9 | :: Unless required by applicable law or agreed to in writing, software
10 | :: distributed under the License is distributed on an "AS IS" BASIS,
11 | :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | :: See the License for the specific language governing permissions and
13 | :: limitations under the License.
14 |
15 | set PM_PACKMAN_VERSION=7.28
16 |
17 | :: Specify where packman command is rooted
18 | set PM_INSTALL_PATH=%~dp0..
19 |
20 | :: The external root may already be configured and we should do minimal work in that case
21 | if defined PM_PACKAGES_ROOT goto ENSURE_DIR
22 |
23 | :: If the folder isn't set we assume that the best place for it is on the drive that we are currently
24 | :: running from
25 | set PM_DRIVE=%CD:~0,2%
26 |
27 | set PM_PACKAGES_ROOT=%PM_DRIVE%\packman-repo
28 |
29 | :: We use *setx* here so that the variable is persisted in the user environment
30 | echo Setting user environment variable PM_PACKAGES_ROOT to %PM_PACKAGES_ROOT%
31 | setx PM_PACKAGES_ROOT %PM_PACKAGES_ROOT%
32 | if %errorlevel% neq 0 ( goto ERROR )
33 |
34 | :: The above doesn't work properly from a build step in VisualStudio because a separate process is
35 | :: spawned for it so it will be lost for subsequent compilation steps - VisualStudio must
36 | :: be launched from a new process. We catch this odd-ball case here:
37 | if defined PM_DISABLE_VS_WARNING goto ENSURE_DIR
38 | if not defined VSLANG goto ENSURE_DIR
39 | echo The above is a once-per-computer operation. Unfortunately VisualStudio cannot pick up environment change
40 | echo unless *VisualStudio is RELAUNCHED*.
41 | echo If you are launching VisualStudio from command line or command line utility make sure
42 | echo you have a fresh launch environment (relaunch the command line or utility).
43 | echo If you are using 'linkPath' and referring to packages via local folder links you can safely ignore this warning.
44 | echo You can disable this warning by setting the environment variable PM_DISABLE_VS_WARNING.
45 | echo.
46 |
47 | :: Check for the directory that we need. Note that mkdir will create any directories
48 | :: that may be needed in the path
49 | :ENSURE_DIR
50 | if not exist "%PM_PACKAGES_ROOT%" (
51 | echo Creating packman packages cache at %PM_PACKAGES_ROOT%
52 | mkdir "%PM_PACKAGES_ROOT%"
53 | )
54 | if %errorlevel% neq 0 ( goto ERROR_MKDIR_PACKAGES_ROOT )
55 |
56 | :: The Python interpreter may already be externally configured
57 | if defined PM_PYTHON_EXT (
58 | set PM_PYTHON=%PM_PYTHON_EXT%
59 | goto PACKMAN
60 | )
61 |
62 | set PM_PYTHON_VERSION=3.10.17-nv1-windows-x86_64
63 | set PM_PYTHON_BASE_DIR=%PM_PACKAGES_ROOT%\python
64 | set PM_PYTHON_DIR=%PM_PYTHON_BASE_DIR%\%PM_PYTHON_VERSION%
65 | set PM_PYTHON=%PM_PYTHON_DIR%\python.exe
66 |
67 | if exist "%PM_PYTHON%" goto PACKMAN
68 | if not exist "%PM_PYTHON_BASE_DIR%" call :CREATE_PYTHON_BASE_DIR
69 |
70 | set PM_PYTHON_PACKAGE=python@%PM_PYTHON_VERSION%.cab
71 | for /f "delims=" %%a in ('powershell -ExecutionPolicy ByPass -NoLogo -NoProfile -File "%~dp0\generate_temp_file_name.ps1"') do set TEMP_FILE_NAME=%%a
72 | set TARGET=%TEMP_FILE_NAME%.zip
73 | call "%~dp0fetch_file_from_packman_bootstrap.cmd" %PM_PYTHON_PACKAGE% "%TARGET%"
74 | if %errorlevel% neq 0 (
75 | echo !!! Error fetching python from CDN !!!
76 | goto ERROR
77 | )
78 |
79 | for /f "delims=" %%a in ('powershell -ExecutionPolicy ByPass -NoLogo -NoProfile -File "%~dp0\generate_temp_folder.ps1" -parentPath "%PM_PYTHON_BASE_DIR%"') do set TEMP_FOLDER_NAME=%%a
80 | echo Unpacking Python interpreter ...
81 | "%SystemRoot%\system32\expand.exe" -F:* "%TARGET%" "%TEMP_FOLDER_NAME%" 1> nul
82 | del "%TARGET%"
83 | :: Failure during extraction to temp folder name, need to clean up and abort
84 | if %errorlevel% neq 0 (
85 | echo !!! Error unpacking python !!!
86 | call :CLEAN_UP_TEMP_FOLDER
87 | goto ERROR
88 | )
89 |
90 | :: If python has now been installed by a concurrent process we need to clean up and then continue
91 | if exist "%PM_PYTHON%" (
92 | call :CLEAN_UP_TEMP_FOLDER
93 | goto PACKMAN
94 | ) else (
95 | if exist "%PM_PYTHON_DIR%" ( rd /s /q "%PM_PYTHON_DIR%" > nul )
96 | )
97 |
98 | :: Perform atomic move (allowing overwrite, /y)
99 | move /y "%TEMP_FOLDER_NAME%" "%PM_PYTHON_DIR%" 1> nul
100 | :: Verify that python.exe is now where we expect
101 | if exist "%PM_PYTHON%" goto PACKMAN
102 |
103 | :: Wait a second and try again (can help with access denied weirdness)
104 | timeout /t 1 /nobreak 1> nul
105 | move /y "%TEMP_FOLDER_NAME%" "%PM_PYTHON_DIR%" 1> nul
106 | if %errorlevel% neq 0 (
107 | echo !!! Error moving python %TEMP_FOLDER_NAME% -> %PM_PYTHON_DIR% !!!
108 | call :CLEAN_UP_TEMP_FOLDER
109 | goto ERROR
110 | )
111 |
112 | :PACKMAN
113 | :: The packman module may already be externally configured
114 | if defined PM_MODULE_DIR_EXT (
115 | set PM_MODULE_DIR=%PM_MODULE_DIR_EXT%
116 | ) else (
117 | set PM_MODULE_DIR=%PM_PACKAGES_ROOT%\packman-common\%PM_PACKMAN_VERSION%
118 | )
119 |
120 | set PM_MODULE=%PM_MODULE_DIR%\run.py
121 |
122 | if exist "%PM_MODULE%" goto END
123 |
124 | :: Clean out broken PM_MODULE_DIR if it exists
125 | if exist "%PM_MODULE_DIR%" ( rd /s /q "%PM_MODULE_DIR%" > nul )
126 |
127 | set PM_MODULE_PACKAGE=packman-common@%PM_PACKMAN_VERSION%.zip
128 | for /f "delims=" %%a in ('powershell -ExecutionPolicy ByPass -NoLogo -NoProfile -File "%~dp0\generate_temp_file_name.ps1"') do set TEMP_FILE_NAME=%%a
129 | set TARGET=%TEMP_FILE_NAME%
130 | call "%~dp0fetch_file_from_packman_bootstrap.cmd" %PM_MODULE_PACKAGE% "%TARGET%"
131 | if %errorlevel% neq 0 (
132 | echo !!! Error fetching packman from CDN !!!
133 | goto ERROR
134 | )
135 |
136 | echo Unpacking ...
137 | "%PM_PYTHON%" -S -s -u -E "%~dp0\install_package.py" "%TARGET%" "%PM_MODULE_DIR%"
138 | if %errorlevel% neq 0 (
139 | echo !!! Error unpacking packman !!!
140 | goto ERROR
141 | )
142 |
143 | del "%TARGET%"
144 |
145 | goto END
146 |
147 | :ERROR_MKDIR_PACKAGES_ROOT
148 | echo Failed to automatically create packman packages repo at %PM_PACKAGES_ROOT%.
149 | echo Please set a location explicitly that packman has permission to write to, by issuing:
150 | echo.
151 | echo setx PM_PACKAGES_ROOT {path-you-choose-for-storing-packman-packages-locally}
152 | echo.
153 | echo Then launch a new command console for the changes to take effect and run packman command again.
154 | exit /B %errorlevel%
155 |
156 | :ERROR
157 | echo !!! Failure while configuring local machine :( !!!
158 | exit /B %errorlevel%
159 |
160 | :CLEAN_UP_TEMP_FOLDER
161 | rd /S /Q "%TEMP_FOLDER_NAME%"
162 | exit /B
163 |
164 | :CREATE_PYTHON_BASE_DIR
165 | :: We ignore errors and clean error state - if two processes create the directory one will fail which is fine
166 | md "%PM_PYTHON_BASE_DIR%" > nul 2>&1
167 | exit /B 0
168 |
169 | :END
170 |
--------------------------------------------------------------------------------
/tools/packman/bootstrap/install_package.py:
--------------------------------------------------------------------------------
1 | # Copyright 2019 NVIDIA CORPORATION
2 |
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 |
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import logging
16 | import zipfile
17 | import tempfile
18 | import sys
19 | import os
20 | import stat
21 | import time
22 | import hashlib
23 | from typing import Any, Callable, Union
24 |
25 |
26 | RENAME_RETRY_COUNT = 100
27 | RENAME_RETRY_DELAY = 0.1
28 |
29 | logging.basicConfig(level=logging.WARNING, format="%(message)s")
30 | logger = logging.getLogger("install_package")
31 |
32 |
33 | def remove_directory_item(path):
34 | if os.path.islink(path) or os.path.isfile(path):
35 | try:
36 | os.remove(path)
37 | except PermissionError:
38 | # make sure we have access and try again:
39 | os.chmod(path, stat.S_IRWXU)
40 | os.remove(path)
41 | else:
42 | # try first to delete the dir because this will work for folder junctions, otherwise we would follow the junctions and cause destruction!
43 | clean_out_folder = False
44 | try:
45 | # make sure we have access preemptively - this is necessary because recursing into a directory without permissions
46 | # will only lead to heart ache
47 | os.chmod(path, stat.S_IRWXU)
48 | os.rmdir(path)
49 | except OSError:
50 | clean_out_folder = True
51 |
52 | if clean_out_folder:
53 | # we should make sure the directory is empty
54 | names = os.listdir(path)
55 | for name in names:
56 | fullname = os.path.join(path, name)
57 | remove_directory_item(fullname)
58 | # now try to again get rid of the folder - and not catch if it raises:
59 | os.rmdir(path)
60 |
61 |
62 | class StagingDirectory:
63 | def __init__(self, staging_path):
64 | self.staging_path = staging_path
65 | self.temp_folder_path = None
66 | os.makedirs(staging_path, exist_ok=True)
67 |
68 | def __enter__(self):
69 | self.temp_folder_path = tempfile.mkdtemp(prefix="ver-", dir=self.staging_path)
70 | return self
71 |
72 | def get_temp_folder_path(self):
73 | return self.temp_folder_path
74 |
75 | # this function renames the temp staging folder to folder_name, it is required that the parent path exists!
76 | def promote_and_rename(self, folder_name):
77 | abs_dst_folder_name = os.path.join(self.staging_path, folder_name)
78 | os.rename(self.temp_folder_path, abs_dst_folder_name)
79 |
80 | def __exit__(self, type, value, traceback):
81 | # Remove temp staging folder if it's still there (something went wrong):
82 | path = self.temp_folder_path
83 | if os.path.isdir(path):
84 | remove_directory_item(path)
85 |
86 |
87 | def rename_folder(staging_dir: StagingDirectory, folder_name: str):
88 | try:
89 | staging_dir.promote_and_rename(folder_name)
90 | except OSError as exc:
91 | # if we failed to rename because the folder now exists we can assume that another packman process
92 | # has managed to update the package before us - in all other cases we re-raise the exception
93 | abs_dst_folder_name = os.path.join(staging_dir.staging_path, folder_name)
94 | if os.path.exists(abs_dst_folder_name):
95 | logger.warning(
96 | f"Directory {abs_dst_folder_name} already present, package installation already completed"
97 | )
98 | else:
99 | raise
100 |
101 |
102 | def call_with_retry(
103 | op_name: str, func: Callable, retry_count: int = 3, retry_delay: float = 20
104 | ) -> Any:
105 | retries_left = retry_count
106 | while True:
107 | try:
108 | return func()
109 | except (OSError, IOError) as exc:
110 | logger.warning(f"Failure while executing {op_name} [{str(exc)}]")
111 | if retries_left:
112 | retry_str = "retry" if retries_left == 1 else "retries"
113 | logger.warning(
114 | f"Retrying after {retry_delay} seconds"
115 | f" ({retries_left} {retry_str} left) ..."
116 | )
117 | time.sleep(retry_delay)
118 | else:
119 | logger.error("Maximum retries exceeded, giving up")
120 | raise
121 | retries_left -= 1
122 |
123 |
124 | def rename_folder_with_retry(staging_dir: StagingDirectory, folder_name):
125 | dst_path = os.path.join(staging_dir.staging_path, folder_name)
126 | call_with_retry(
127 | f"rename {staging_dir.get_temp_folder_path()} -> {dst_path}",
128 | lambda: rename_folder(staging_dir, folder_name),
129 | RENAME_RETRY_COUNT,
130 | RENAME_RETRY_DELAY,
131 | )
132 |
133 |
134 | def generate_sha256_for_file(file_path: Union[str, os.PathLike]) -> str:
135 | """Returns the SHA-256 hex digest for the file at `file_path`"""
136 | hash = hashlib.sha256()
137 | # Read the file in binary mode and update the hash object with data
138 | with open(file_path, "rb") as file:
139 | for chunk in iter(lambda: file.read(4096), b""):
140 | hash.update(chunk)
141 | return hash.hexdigest()
142 |
143 |
144 | def install_common_module(package_path, install_path):
145 | COMMON_SHA256 = "c49ce665f107f44d0d92ebb1e7b62417e94b37399dc3c92584d03b1ac44bb132"
146 | package_sha256 = generate_sha256_for_file(package_path)
147 | if package_sha256 != COMMON_SHA256:
148 | raise RuntimeError(
149 | f"Package at '{package_path}' must have a sha256 of '{COMMON_SHA256}' "
150 | f"but was found to have '{package_sha256}'"
151 | )
152 | staging_path, version = os.path.split(install_path)
153 | with StagingDirectory(staging_path) as staging_dir:
154 | output_folder = staging_dir.get_temp_folder_path()
155 | with zipfile.ZipFile(package_path, allowZip64=True) as zip_file:
156 | zip_file.extractall(output_folder)
157 |
158 | # attempt the rename operation
159 | rename_folder_with_retry(staging_dir, version)
160 |
161 | print(f"Package successfully installed to {install_path}")
162 |
163 |
164 | if __name__ == "__main__":
165 | executable_paths = os.getenv("PATH")
166 | paths_list = executable_paths.split(os.path.pathsep) if executable_paths else []
167 | target_path_np = os.path.normpath(sys.argv[2])
168 | target_path_np_nc = os.path.normcase(target_path_np)
169 | for exec_path in paths_list:
170 | if os.path.normcase(os.path.normpath(exec_path)) == target_path_np_nc:
171 | raise RuntimeError(f"packman will not install to executable path '{exec_path}'")
172 | install_common_module(sys.argv[1], target_path_np)
173 |
--------------------------------------------------------------------------------
/isaac-zmq-server/src/isaac_zmq_server/server.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | import threading
5 | import time
6 | import traceback
7 |
8 | import zmq
9 |
10 |
11 | class ZMQServer:
12 | """
13 | Server for handling ZMQ communication.
14 |
15 | This class implements a singleton pattern and provides methods for creating
16 | ZMQ sockets, sending and receiving data in separate threads, and cleaning up
17 | resources when they are no longer needed.
18 | """
19 |
20 | _instance = None
21 |
22 | def __new__(cls, *args, **kwargs):
23 | """Implement singleton pattern for ZMQServer."""
24 | if not cls._instance:
25 | cls._instance = super().__new__(cls, *args, **kwargs)
26 | return cls._instance
27 |
28 | def __init__(self):
29 | """Initialize the ZMQServer with empty collections for sockets and threads."""
30 | # Skip initialization if already initialized (singleton pattern)
31 | if hasattr(self, "push_sockets"):
32 | return
33 |
34 | self.push_sockets = {}
35 | self.pull_sockets = {}
36 | self.reciveing_threads = {}
37 | self.sending_threads = {}
38 |
39 | # ZMQ context
40 | self._context = None
41 |
42 | def context(self) -> zmq.Context:
43 | """
44 | Returns the ZMQ context instance.
45 | If the context has not been initialized, it creates a new ZMQ context and assigns it to the `_context` attribute.
46 |
47 | Returns:
48 | zmq.Context: The ZMQ context instance.
49 | """
50 | if not self._context:
51 | self._context = zmq.Context()
52 | return self._context
53 |
54 | def get_pull_socket(self, port: int) -> zmq.Socket:
55 | """
56 | Creates and returns a new pull socket that is bound to the specified port.
57 |
58 | Args:
59 | port (int): The port number to bind the socket to.
60 |
61 | Returns:
62 | zmq.Socket: The newly created pull socket.
63 | """
64 | addr = f"tcp://*:{port}"
65 | sock = self.context().socket(zmq.PULL)
66 | sock.set_hwm(1) # High water mark: only buffer 1 message
67 | sock.bind(addr)
68 | sock.setsockopt(zmq.RCVTIMEO, 1000) # 1 second timeout for receiving
69 | poller = zmq.Poller()
70 | poller.register(sock, zmq.POLLIN)
71 | self.pull_sockets[port] = sock
72 | return sock
73 |
74 | def get_push_socket(self, port: int) -> zmq.Socket:
75 | """
76 | Creates and returns a ZeroMQ PUSH socket bound to the specified port.
77 |
78 | Args:
79 | port (int): The port number to bind the socket to.
80 |
81 | Returns:
82 | zmq.Socket: The created PUSH socket.
83 | """
84 | addr = f"tcp://*:{port}"
85 | sock = self.context().socket(zmq.PUSH)
86 | sock.setsockopt(zmq.SNDTIMEO, 1000) # 1 second timeout for sending
87 | sock.bind(addr)
88 | self.push_sockets[port] = sock
89 | return sock
90 |
91 | def subscribe_to_socket_in_loop(self, name: str, port: int, fn: callable) -> None:
92 | """
93 | Receives messages from a socket in a loop and calls a given function for each message.
94 |
95 | This method creates a new thread that continuously receives messages from the specified
96 | port and passes them to the provided callback function.
97 |
98 | Args:
99 | name (str): The name of the receiving thread.
100 | port (int): The port number to receive messages from.
101 | fn (callable): A callable function that takes a message as input.
102 | """
103 | # Create socket for receiving
104 | sock = self.get_pull_socket(port)
105 | stop_event = threading.Event()
106 |
107 | def loop():
108 | """Thread function that continuously receives messages."""
109 | while not stop_event.is_set():
110 | try:
111 | msg = sock.recv()
112 | fn(msg)
113 | except zmq.Again:
114 | continue
115 | except:
116 | print("[isaac-zmq-server] Unable to unpack from socket...")
117 | print(traceback.format_exc())
118 | continue
119 |
120 | # Clean up when thread is finsihed
121 | sock.close()
122 | del self.pull_sockets[port]
123 |
124 | # Start the thread
125 | worker = threading.Thread(target=loop)
126 | self.reciveing_threads[name] = (worker, stop_event)
127 | worker.start()
128 |
129 | def publish_protobuf_in_loop(self, name: str, port: int, rate_hz: float, fn: callable) -> None:
130 | """
131 | Sends protobuf messages from a socket in a loop at a specified rate.
132 |
133 | This method creates a new thread that continuously sends protobuf messages at the specified
134 | rate to the specified port. The protobuf message to send is obtained by calling the provided
135 | callback function.
136 |
137 | Args:
138 | name (str): The name of the sending thread.
139 | port (int): The port number to send data to.
140 | rate_hz (float): The rate at which data is sent in Hz.
141 | fn (callable): A callable function that returns a protobuf message.
142 | """
143 | # Create socket for sending
144 | sock = self.get_push_socket(port)
145 | stop_event = threading.Event()
146 |
147 | def loop():
148 | """Thread function that continuously sends protobuf messages at the specified rate."""
149 | while not stop_event.is_set():
150 | try:
151 | # Get the protobuf message from the callback function
152 | proto_msg = fn()
153 | # Serialize the protobuf message and send it
154 | sock.send(proto_msg.SerializeToString())
155 | except zmq.Again:
156 | continue
157 | except Exception as e:
158 | print(f"[isaac-zmq-server] Unable to send protobuf to socket: {e}")
159 | continue
160 |
161 | # Sleep to maintain the desired rate
162 | time.sleep(1 / rate_hz)
163 |
164 | # Clean up when thread is finished
165 | sock.close()
166 | del self.push_sockets[port]
167 |
168 | # Start the sending thread
169 | worker = threading.Thread(target=loop)
170 | self.sending_threads[name] = (worker, stop_event)
171 | worker.start()
172 |
173 | def cleanup(self) -> None:
174 | """
175 | Stops and joins all receiving and sending threads.
176 |
177 | This function is used to clean up the threads when they are no longer needed.
178 | It sets the stop event for each thread and then joins them to ensure they have finished.
179 | """
180 | # Stop and join all receiving threads
181 | for name, (worker, stop_event) in self.reciveing_threads.items():
182 | stop_event.set()
183 | worker.join()
184 |
185 | # Stop and join all sending threads
186 | for name, (worker, stop_event) in self.sending_threads.items():
187 | stop_event.set()
188 | worker.join()
189 |
--------------------------------------------------------------------------------
/tools/packman/packman:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright 2019-2025 NVIDIA CORPORATION
4 |
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 |
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | SAVED_SETTINGS=`echo $-`
17 | # Fail on undefined variables
18 | set -u
19 | # Don't exit on errors
20 | set +e
21 |
22 | if echo ${PM_VERBOSITY-} | grep -i "debug" > /dev/null ; then
23 | set -x
24 | PM_CURL_SILENT=""
25 | PM_WGET_QUIET=""
26 | else
27 | PM_CURL_SILENT="-s -S"
28 | PM_WGET_QUIET="--quiet"
29 | fi
30 | export PM_PACKMAN_VERSION=7.28
31 |
32 |
33 | cleanup() {
34 | # Remove temporary variable file if it exists
35 | if [[ -n "${PM_VAR_PATH:-}" && -f "$PM_VAR_PATH" ]]; then
36 | rm -f "$PM_VAR_PATH"
37 | fi
38 |
39 | # Restore the settings we may have altered during our run
40 | if [[ "$SAVED_SETTINGS" == *"e"* ]]; then
41 | set -e
42 | fi
43 |
44 | if [[ "$SAVED_SETTINGS" != *"x"* ]]; then
45 | set +x
46 | fi
47 |
48 | # the e setting is always set in source mode so we remove it here so it
49 | # doesn't leak (in regular ./ execution doesn't matter)
50 | set +u
51 | }
52 |
53 | main() {
54 | # This is necessary for newer macOS
55 | if [ `uname` == 'Darwin' ]; then
56 | export LC_ALL=en_US.UTF-8
57 | export LANG=en_US.UTF-8
58 | fi
59 |
60 | # We cannot rely on realpath, it isn't installed on macOS and some Linux distros
61 | get_abs_filename() {
62 | echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
63 | }
64 |
65 | # Specify where packman command exists
66 | export PM_INSTALL_PATH="$(get_abs_filename "$(dirname "${BASH_SOURCE}")")"
67 |
68 | # The packages root may already be configured by the user
69 | if [ -z "${PM_PACKAGES_ROOT:-}" ]; then
70 | # Set variable temporarily in this process so that the following execution will work
71 | if [ `uname` == 'Darwin' ]; then
72 | export PM_PACKAGES_ROOT="${HOME}/Library/Application Support/packman-cache"
73 | else
74 | if [ -z "${XDG_CACHE_HOME:-}" ]; then
75 | export PM_PACKAGES_ROOT="${HOME}/.cache/packman"
76 | else
77 | export PM_PACKAGES_ROOT="${XDG_CACHE_HOME}/packman"
78 | fi
79 | fi
80 | fi
81 |
82 | # Ensure the packages root path exists:
83 | if [ ! -d "$PM_PACKAGES_ROOT" ]; then
84 | echo "Creating packman packages cache at $PM_PACKAGES_ROOT"
85 | mkdir -p -m a+rwx "$PM_PACKAGES_ROOT" || return 1
86 | fi
87 |
88 | execute_with_retry()
89 | {
90 | local CMD="$1"
91 | local MAX_TRIES=4
92 | local DELAY=2
93 | local TRIES=0
94 | local exit_code
95 |
96 | while [ $TRIES -lt $MAX_TRIES ]
97 | do
98 | ((TRIES++))
99 | eval $CMD
100 | exit_code=$?
101 | if [ $exit_code -eq 0 ]; then
102 | return 0
103 | fi
104 |
105 | if [ $TRIES -lt $MAX_TRIES ]; then
106 | echo "Attempt $TRIES failed. Retrying in $DELAY seconds ..."
107 | sleep $DELAY
108 | DELAY=$((DELAY * DELAY))
109 | echo "Retrying ..."
110 | fi
111 | done
112 |
113 | echo "Command failed after $MAX_TRIES attempts: $CMD"
114 | return $exit_code
115 | }
116 |
117 | fetch_file_from_s3()
118 | {
119 | local SOURCE=$1
120 | local SOURCE_URL=https://bootstrap.packman.nvidia.com/$SOURCE
121 | local TARGET=$2
122 | echo "Fetching $SOURCE from bootstrap.packman.nvidia.com ..."
123 | local CMD="curl -o $TARGET $SOURCE_URL $PM_CURL_SILENT"
124 | if command -v wget >/dev/null 2>&1; then
125 | CMD="wget $PM_WGET_QUIET -O$TARGET $SOURCE_URL"
126 | fi
127 | execute_with_retry "$CMD"
128 | return $?
129 | }
130 |
131 | generate_temp_file_name()
132 | {
133 | if [ `uname` == "Darwin" ]; then
134 | local tmpfile=`mktemp -t packman`
135 | else
136 | local tmpfile=`mktemp -t packman.XXXXXXXX`
137 | fi
138 | echo "$tmpfile"
139 | }
140 |
141 | install_python()
142 | {
143 | PLATFORM=`uname`
144 | PROCESSOR=`uname -m`
145 | PYTHON_VERSION=3.10.17-nv1
146 |
147 | if [ $PLATFORM == 'Darwin' ]; then
148 | PYTHON_PACKAGE=3.10.5-1-macos-x86_64
149 | elif [ $PLATFORM == 'Linux' ] && [ $PROCESSOR == 'x86_64' ]; then
150 | PYTHON_PACKAGE=$PYTHON_VERSION-linux-x86_64
151 | elif [ $PLATFORM == 'Linux' ] && [ $PROCESSOR == 'aarch64' ]; then
152 | PYTHON_PACKAGE=$PYTHON_VERSION-linux-aarch64
153 | else
154 | echo "Operating system not supported"
155 | return 1
156 | fi
157 |
158 | PYTHON_INSTALL_FOLDER="$PM_PACKAGES_ROOT/python/$PYTHON_PACKAGE"
159 | if [ ! -d "$PYTHON_INSTALL_FOLDER" ]; then
160 | mkdir -p "$PYTHON_INSTALL_FOLDER" || return 1
161 | fi
162 |
163 | export PM_PYTHON="$PYTHON_INSTALL_FOLDER/python"
164 |
165 | if [ ! -f "$PM_PYTHON" ]; then
166 | PYTHON_PACKAGE_TMP=$(generate_temp_file_name)
167 | fetch_file_from_s3 "python@$PYTHON_PACKAGE.tar.gz" "$PYTHON_PACKAGE_TMP" || return 1
168 | echo "Unpacking python"
169 | tar -xf "$PYTHON_PACKAGE_TMP" -C "$PYTHON_INSTALL_FOLDER" || return 1
170 | rm "$PYTHON_PACKAGE_TMP" || return 1
171 | fi
172 | }
173 |
174 | # Ensure python is available:
175 | if [ -z "${PM_PYTHON_EXT:-}" ]; then
176 | install_python || return 1
177 | else
178 | PM_PYTHON="$PM_PYTHON_EXT"
179 | fi
180 |
181 | # The packman module may be externally configured
182 | if [ -z "${PM_MODULE_DIR_EXT:-}" ]; then
183 | PM_MODULE_DIR="$PM_PACKAGES_ROOT/packman-common/$PM_PACKMAN_VERSION"
184 | else
185 | PM_MODULE_DIR="$PM_MODULE_DIR_EXT"
186 | fi
187 | export PM_MODULE="$PM_MODULE_DIR/run.py"
188 |
189 | # Ensure the packman package exists:
190 | if [ ! -f "$PM_MODULE" ]; then
191 | # Remove a previously corrupt packman-common if it's there
192 | if [ -d "$PM_MODULE_DIR" ]; then
193 | rm -rf "$PM_MODULE_DIR" || return 1
194 | fi
195 | PM_MODULE_PACKAGE="packman-common@$PM_PACKMAN_VERSION.zip"
196 | TARGET=$(generate_temp_file_name)
197 | # We always fetch packman from S3:
198 | fetch_file_from_s3 "$PM_MODULE_PACKAGE" "$TARGET" || return 1
199 | echo "Unpacking ..."
200 | "$PM_PYTHON" -S -s -u -E "$PM_INSTALL_PATH/bootstrap/install_package.py" "$TARGET" "$PM_MODULE_DIR" || return 1
201 | rm "$TARGET" || return 1
202 | fi
203 |
204 | # Generate temporary file name for environment variables:
205 | PM_VAR_PATH=`mktemp -u -t tmp.$$.pmvars.XXXXXX`
206 |
207 | if [ $# -ne 0 ]; then
208 | PM_VAR_PATH_ARG=--var-path="$PM_VAR_PATH"
209 | else
210 | PM_VAR_PATH_ARG=""
211 | fi
212 |
213 | "$PM_PYTHON" -S -s -u -E "$PM_MODULE" "$@" ${PM_VAR_PATH_ARG:-} || return 1
214 | # Export the variables if the file was used:
215 | if [ -f "$PM_VAR_PATH" ]; then
216 | while read -r line
217 | do
218 | if [ ${#line} -gt 0 ]; then
219 | export "$line"
220 | fi
221 | done < "$PM_VAR_PATH"
222 | fi
223 |
224 | # Return success
225 | return 0
226 | }
227 |
228 | main "$@"
229 | exit_code=$?
230 | cleanup
231 |
232 | # Determine execution context and return accordingly
233 | if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
234 | # This is direct execution
235 | exit $exit_code
236 | else
237 | # This is sourced execution
238 | return $exit_code
239 | fi
240 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge.examples/isaacsim/zmq/bridge/examples/core/client.py:
--------------------------------------------------------------------------------
1 | # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | # SPDX-License-Identifier: MIT
3 |
4 | import asyncio
5 | import traceback
6 | import zmq
7 | import zmq.asyncio
8 |
9 | import carb
10 | import omni
11 |
12 | from isaacsim.core.api.world import World
13 |
14 | from .rate_limiter import RateLimitedCallback
15 | from .. import EXT_NAME
16 |
17 | class ZMQClient:
18 | """
19 | The ZMQClient class provides a singleton instance which handles the creation and management of ZMQ sockets.
20 |
21 | This class is responsible for:
22 | - Creating and managing ZMQ sockets for communication with external applications
23 | - Handling connection and disconnection of sockets
24 | - Managing physics callbacks for rate-limited data streaming (Python-only mode)
25 | - Providing methods for sending and receiving data through ZMQ
26 | """
27 |
28 | _instance = None
29 |
30 | def __new__(cls, *args, **kwargs):
31 | # Implement singleton pattern
32 | if not cls._instance:
33 | cls._instance = super().__new__(cls)
34 | return cls._instance
35 |
36 | def __init__(self, server_ip: str = "localhost"):
37 | self.server_ip = server_ip
38 | self.push_sockets = {}
39 | self.pull_sockets = {}
40 | self.phyx_callbacks = {}
41 | self.annotators = {}
42 |
43 | # ZMQ context
44 | self._context = None
45 |
46 | # Timing and rate control
47 | self.start_time = 0
48 | self._adeptive_rate = True
49 |
50 | def context(self) -> zmq.asyncio.Context:
51 | """
52 | Returns the ZMQ context if it has not been initialized yet.
53 | Initializes and returns the ZMQ context if it has not been initialized.
54 |
55 | Returns:
56 | zmq.asyncio.Context: The ZMQ context.
57 | """
58 | if not self._context:
59 | self._context = zmq.asyncio.Context()
60 | return self._context
61 |
62 | def get_pull_socket(self, port: int) -> zmq.Socket:
63 | """
64 | Creates and returns a ZeroMQ PULL socket connected to the specified port.
65 |
66 | This socket type is used to receive data from a remote PUSH socket.
67 |
68 | Args:
69 | port (int): The port number to connect the socket to.
70 |
71 | Returns:
72 | zmq.Socket: The created PULL socket.
73 | """
74 | addr = f"tcp://{self.server_ip}:{port}"
75 | sock = self.context().socket(zmq.PULL)
76 | sock.set_hwm(1) # High water mark: only buffer 1 message
77 | sock.connect(addr)
78 | self.pull_sockets[addr] = sock
79 | return sock
80 |
81 | async def receive_protobuf(self, sock: zmq.asyncio.Socket, proto_class) -> object:
82 | """
83 | Asynchronously receives a protobuf message from a ZeroMQ socket.
84 |
85 | Args:
86 | sock (zmq.asyncio.Socket): The ZeroMQ socket to receive data from.
87 | proto_class: The protobuf message class to parse the received data.
88 |
89 | Returns:
90 | object: The received data as a protobuf message.
91 | """
92 | message_bytes = await sock.recv()
93 | proto_msg = proto_class()
94 | proto_msg.ParseFromString(message_bytes)
95 | return proto_msg
96 |
97 | async def disconnect_all(self) -> None:
98 | """
99 | Disconnects all ZeroMQ sockets and terminates the ZeroMQ context.
100 |
101 | This method iterates over all push and pull sockets, disconnects them, and closes them.
102 | It then clears the socket dictionaries and terminates the ZeroMQ context.
103 | """
104 | # Disconnect and close all push sockets
105 | for addr, sock in self.push_sockets.items():
106 | await asyncio.sleep(0.1)
107 | try:
108 | sock.setsockopt(zmq.LINGER, 0) # Don't wait for pending messages
109 | sock.disconnect(addr)
110 | except asyncio.CancelledError:
111 | pass
112 | except zmq.error.ZMQError:
113 | carb.log_warn(f"[{EXT_NAME}] zmq error - non critical\n {traceback.format_exc()}")
114 | except Exception:
115 | carb.log_error(traceback.format_exc())
116 |
117 | sock.close()
118 |
119 | # Disconnect and close all pull sockets
120 | for addr, sock in self.pull_sockets.items():
121 | await asyncio.sleep(0.1)
122 | try:
123 | sock.disconnect(addr)
124 | except asyncio.CancelledError:
125 | pass
126 | except zmq.error.ZMQError:
127 | carb.log_warn(f"[{EXT_NAME}] zmq error - non critical\n {traceback.format_exc()}")
128 | except Exception:
129 | carb.log_error(traceback.format_exc())
130 |
131 | sock.close()
132 |
133 | # Clear socket dictionaries
134 | self.pull_sockets = {}
135 | self.push_sockets = {}
136 |
137 | # Terminate ZMQ context
138 | if self._context:
139 | self._context.term()
140 | self._context = None
141 |
142 | ######################################################################################
143 | # The following methods are used only when the C++ node modes is not in use
144 | # They provide Python-based alternatives for streaming data
145 | ######################################################################################
146 |
147 | def get_push_socket(self, port: int) -> zmq.Socket:
148 | """
149 | Creates and returns a ZeroMQ PUSH socket connected to the specified port.
150 |
151 | This socket type is used to send data to a remote PULL socket.
152 |
153 | Args:
154 | port (int): The port number to connect the socket to.
155 |
156 | Returns:
157 | zmq.Socket: The created PUSH socket.
158 | """
159 | addr = f"tcp://{self.server_ip}:{port}"
160 | sock = self.context().socket(zmq.PUSH)
161 | sock.set_hwm(1) # High water mark: only buffer 1 message
162 | sock.setsockopt(zmq.SNDTIMEO, 1000) # 1 sec timeout for sending
163 | sock.connect(addr)
164 | self.push_sockets[addr] = sock
165 | return sock
166 |
167 | def add_physx_step_callback(self, name: str, hz: float, fn: callable) -> None:
168 | """
169 | Adds a callback function to be executed at a specified simulation steps frequency.
170 |
171 | This method creates a rate-limited callback that will be executed during physics
172 | simulation steps at the specified frequency.
173 |
174 | Args:
175 | name (str): The name of the callback.
176 | hz (float): The frequency at which the callback is executed.
177 | fn (callable): The callback function to be executed.
178 | """
179 | self.world = World.instance()
180 | rate_limited_callback = RateLimitedCallback(name, hz, fn, self.start_time)
181 | self.world.add_physics_callback(name, rate_limited_callback.rate_limit)
182 | self.phyx_callbacks[name] = rate_limited_callback
183 | return
184 |
185 | def remove_physx_callbacks(self) -> None:
186 | """
187 | Removes all registered physics callbacks.
188 |
189 | This method iterates over the `phyx_callbacks` dictionary and unsubscribes each callback
190 | from the physics simulation.
191 | """
192 | for name, cb in self.phyx_callbacks.items():
193 | self.world.remove_physics_callback(name)
194 | del cb
195 |
196 | @property
197 | def adeptive_rate(self) -> bool:
198 | return self._adeptive_rate
199 |
200 | @adeptive_rate.setter
201 | def adeptive_rate(self, value: bool) -> None:
202 | """
203 | Set the adaptive rate setting and update all callbacks.
204 |
205 | When adaptive rate is enabled, the system will automatically adjust
206 | the callback frequency to match the desired rate, accounting for
207 | execution time of the callbacks.
208 |
209 | Args:
210 | value (bool): True to enable adaptive rate, False to disable it.
211 | """
212 | if value != self._adeptive_rate:
213 | self._adeptive_rate = value
214 | for cb in self.phyx_callbacks.values():
215 | cb.adeptive_rate = value
216 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/plugins/nodes/icons/isaac-sim.svg:
--------------------------------------------------------------------------------
1 |
2 |
152 |
--------------------------------------------------------------------------------
/tools/packman/bootstrap/generate_temp_file_name.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | Copyright 2019 NVIDIA CORPORATION
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | #>
16 |
17 | $out = [System.IO.Path]::GetTempFileName()
18 | Write-Host $out
19 | # SIG # Begin signature block
20 | # MIIaVwYJKoZIhvcNAQcCoIIaSDCCGkQCAQExDzANBglghkgBZQMEAgEFADB5Bgor
21 | # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
22 | # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAK+Ewup1N0/mdf
23 | # 1l4R58rxyumHgZvTmEhrYTb2Zf0zd6CCCiIwggTTMIIDu6ADAgECAhBi50XpIWUh
24 | # PJcfXEkK6hKlMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYDVQQGEwJVUzEdMBsGA1UE
25 | # ChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0
26 | # IE5ldHdvcmsxNTAzBgNVBAMTLFN5bWFudGVjIENsYXNzIDMgU0hBMjU2IENvZGUg
27 | # U2lnbmluZyBDQSAtIEcyMB4XDTE4MDcwOTAwMDAwMFoXDTIxMDcwOTIzNTk1OVow
28 | # gYMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtT
29 | # YW50YSBDbGFyYTEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0aW9uMQ8wDQYDVQQL
30 | # DAZJVC1NSVMxGzAZBgNVBAMMEk5WSURJQSBDb3Jwb3JhdGlvbjCCASIwDQYJKoZI
31 | # hvcNAQEBBQADggEPADCCAQoCggEBALEZN63dA47T4i90jZ84CJ/aWUwVtLff8AyP
32 | # YspFfIZGdZYiMgdb8A5tBh7653y0G/LZL6CVUkgejcpvBU/Dl/52a+gSWy2qJ2bH
33 | # jMFMKCyQDhdpCAKMOUKSC9rfzm4cFeA9ct91LQCAait4LhLlZt/HF7aG+r0FgCZa
34 | # HJjJvE7KNY9G4AZXxjSt8CXS8/8NQMANqjLX1r+F+Hl8PzQ1fVx0mMsbdtaIV4Pj
35 | # 5flAeTUnz6+dCTx3vTUo8MYtkS2UBaQv7t7H2B7iwJDakEQKk1XHswJdeqG0osDU
36 | # z6+NVks7uWE1N8UIhvzbw0FEX/U2kpfyWaB/J3gMl8rVR8idPj8CAwEAAaOCAT4w
37 | # ggE6MAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF
38 | # BwMDMGEGA1UdIARaMFgwVgYGZ4EMAQQBMEwwIwYIKwYBBQUHAgEWF2h0dHBzOi8v
39 | # ZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkMF2h0dHBzOi8vZC5zeW1jYi5j
40 | # b20vcnBhMB8GA1UdIwQYMBaAFNTABiJJ6zlL3ZPiXKG4R3YJcgNYMCsGA1UdHwQk
41 | # MCIwIKAeoByGGmh0dHA6Ly9yYi5zeW1jYi5jb20vcmIuY3JsMFcGCCsGAQUFBwEB
42 | # BEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3JiLnN5bWNkLmNvbTAmBggrBgEFBQcw
43 | # AoYaaHR0cDovL3JiLnN5bWNiLmNvbS9yYi5jcnQwDQYJKoZIhvcNAQELBQADggEB
44 | # AIJKh5vKJdhHJtMzATmc1BmXIQ3RaJONOZ5jMHn7HOkYU1JP0OIzb4pXXkH8Xwfr
45 | # K6bnd72IhcteyksvKsGpSvK0PBBwzodERTAu1Os2N+EaakxQwV/xtqDm1E3IhjHk
46 | # fRshyKKzmFk2Ci323J4lHtpWUj5Hz61b8gd72jH7xnihGi+LORJ2uRNZ3YuqMNC3
47 | # SBC8tAyoJqEoTJirULUCXW6wX4XUm5P2sx+htPw7szGblVKbQ+PFinNGnsSEZeKz
48 | # D8jUb++1cvgTKH59Y6lm43nsJjkZU77tNqyq4ABwgQRk6lt8cS2PPwjZvTmvdnla
49 | # ZhR0K4of+pQaUQHXVIBdji8wggVHMIIEL6ADAgECAhB8GzU1SufbdOdBXxFpymuo
50 | # MA0GCSqGSIb3DQEBCwUAMIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNp
51 | # Z24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNV
52 | # BAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
53 | # IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmlj
54 | # YXRpb24gQXV0aG9yaXR5MB4XDTE0MDcyMjAwMDAwMFoXDTI0MDcyMTIzNTk1OVow
55 | # gYQxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEf
56 | # MB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazE1MDMGA1UEAxMsU3ltYW50
57 | # ZWMgQ2xhc3MgMyBTSEEyNTYgQ29kZSBTaWduaW5nIENBIC0gRzIwggEiMA0GCSqG
58 | # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXlUPU3N9nrjn7UqS2JjEEcOm3jlsqujdp
59 | # NZWPu8Aw54bYc7vf69F2P4pWjustS/BXGE6xjaUz0wt1I9VqeSfdo9P3Dodltd6t
60 | # HPH1NbQiUa8iocFdS5B/wFlOq515qQLXHkmxO02H/sJ4q7/vUq6crwjZOeWaUT5p
61 | # XzAQTnFjbFjh8CAzGw90vlvLEuHbjMSAlHK79kWansElC/ujHJ7YpglwcezAR0yP
62 | # fcPeGc4+7gRyjhfT//CyBTIZTNOwHJ/+pXggQnBBsCaMbwDIOgARQXpBsKeKkQSg
63 | # mXj0d7TzYCrmbFAEtxRg/w1R9KiLhP4h2lxeffUpeU+wRHRvbXL/AgMBAAGjggF4
64 | # MIIBdDAuBggrBgEFBQcBAQQiMCAwHgYIKwYBBQUHMAGGEmh0dHA6Ly9zLnN5bWNk
65 | # LmNvbTASBgNVHRMBAf8ECDAGAQH/AgEAMGYGA1UdIARfMF0wWwYLYIZIAYb4RQEH
66 | # FwMwTDAjBggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYB
67 | # BQUHAgIwGRoXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwNgYDVR0fBC8wLTAroCmg
68 | # J4YlaHR0cDovL3Muc3ltY2IuY29tL3VuaXZlcnNhbC1yb290LmNybDATBgNVHSUE
69 | # DDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwxGjAY
70 | # BgNVBAMTEVN5bWFudGVjUEtJLTEtNzI0MB0GA1UdDgQWBBTUwAYiSes5S92T4lyh
71 | # uEd2CXIDWDAfBgNVHSMEGDAWgBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG
72 | # 9w0BAQsFAAOCAQEAf+vKp+qLdkLrPo4gVDDjt7nc+kg+FscPRZUQzSeGo2bzAu1x
73 | # +KrCVZeRcIP5Un5SaTzJ8eCURoAYu6HUpFam8x0AkdWG80iH4MvENGggXrTL+QXt
74 | # nK9wUye56D5+UaBpcYvcUe2AOiUyn0SvbkMo0yF1u5fYi4uM/qkERgSF9xWcSxGN
75 | # xCwX/tVuf5riVpLxlrOtLfn039qJmc6yOETA90d7yiW5+ipoM5tQct6on9TNLAs0
76 | # vYsweEDgjY4nG5BvGr4IFYFd6y/iUedRHsl4KeceZb847wFKAQkkDhbEFHnBQTc0
77 | # 0D2RUpSd4WjvCPDiaZxnbpALGpNx1CYCw8BaIzGCD4swgg+HAgEBMIGZMIGEMQsw
78 | # CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV
79 | # BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxNTAzBgNVBAMTLFN5bWFudGVjIENs
80 | # YXNzIDMgU0hBMjU2IENvZGUgU2lnbmluZyBDQSAtIEcyAhBi50XpIWUhPJcfXEkK
81 | # 6hKlMA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcN
82 | # AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw
83 | # LwYJKoZIhvcNAQkEMSIEIPW+EpFrZSdzrjFFo0UT+PzFeYn/GcWNyWFaU/JMrMfR
84 | # MA0GCSqGSIb3DQEBAQUABIIBAA8fmU/RJcF9t60DZZAjf8FB3EZddOaHgI9z40nV
85 | # CnfTGi0OEYU48Pe9jkQQV2fABpACfW74xmNv3QNgP2qP++mkpKBVv28EIAuINsFt
86 | # YAITEljLN/VOVul8lvjxar5GSFFgpE5F6j4xcvI69LuCWbN8cteTVsBGg+eGmjfx
87 | # QZxP252z3FqPN+mihtFegF2wx6Mg6/8jZjkO0xjBOwSdpTL4uyQfHvaPBKXuWxRx
88 | # ioXw4ezGAwkuBoxWK8UG7Qu+7CSfQ3wMOjvyH2+qn30lWEsvRMdbGAp7kvfr3EGZ
89 | # a3WN7zXZ+6KyZeLeEH7yCDzukAjptaY/+iLVjJsuzC6tCSqhgg1EMIINQAYKKwYB
90 | # BAGCNwMDATGCDTAwgg0sBgkqhkiG9w0BBwKggg0dMIINGQIBAzEPMA0GCWCGSAFl
91 | # AwQCAQUAMHcGCyqGSIb3DQEJEAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglg
92 | # hkgBZQMEAgEFAAQg14BnPazQkW9whhZu1d0bC3lqqScvxb3SSb1QT8e3Xg0CEFhw
93 | # aMBZ2hExXhr79A9+bXEYDzIwMjEwNDA4MDkxMTA5WqCCCjcwggT+MIID5qADAgEC
94 | # AhANQkrgvjqI/2BAIc4UAPDdMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVT
95 | # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
96 | # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBp
97 | # bmcgQ0EwHhcNMjEwMTAxMDAwMDAwWhcNMzEwMTA2MDAwMDAwWjBIMQswCQYDVQQG
98 | # EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0
99 | # IFRpbWVzdGFtcCAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
100 | # wuZhhGfFivUNCKRFymNrUdc6EUK9CnV1TZS0DFC1JhD+HchvkWsMlucaXEjvROW/
101 | # m2HNFZFiWrj/ZwucY/02aoH6KfjdK3CF3gIY83htvH35x20JPb5qdofpir34hF0e
102 | # dsnkxnZ2OlPR0dNaNo/Go+EvGzq3YdZz7E5tM4p8XUUtS7FQ5kE6N1aG3JMjjfdQ
103 | # Jehk5t3Tjy9XtYcg6w6OLNUj2vRNeEbjA4MxKUpcDDGKSoyIxfcwWvkUrxVfbENJ
104 | # Cf0mI1P2jWPoGqtbsR0wwptpgrTb/FZUvB+hh6u+elsKIC9LCcmVp42y+tZji06l
105 | # chzun3oBc/gZ1v4NSYS9AQIDAQABo4IBuDCCAbQwDgYDVR0PAQH/BAQDAgeAMAwG
106 | # A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwQQYDVR0gBDowODA2
107 | # BglghkgBhv1sBwEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5j
108 | # b20vQ1BTMB8GA1UdIwQYMBaAFPS24SAd/imu0uRhpbKiJbLIFzVuMB0GA1UdDgQW
109 | # BBQ2RIaOpLqwZr68KC0dRDbd42p6vDBxBgNVHR8EajBoMDKgMKAuhixodHRwOi8v
110 | # Y3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNybDAyoDCgLoYsaHR0
111 | # cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5jcmwwgYUGCCsG
112 | # AQUFBwEBBHkwdzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t
113 | # ME8GCCsGAQUFBzAChkNodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl
114 | # cnRTSEEyQXNzdXJlZElEVGltZXN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUA
115 | # A4IBAQBIHNy16ZojvOca5yAOjmdG/UJyUXQKI0ejq5LSJcRwWb4UoOUngaVNFBUZ
116 | # B3nw0QTDhtk7vf5EAmZN7WmkD/a4cM9i6PVRSnh5Nnont/PnUp+Tp+1DnnvntN1B
117 | # Ion7h6JGA0789P63ZHdjXyNSaYOC+hpT7ZDMjaEXcw3082U5cEvznNZ6e9oMvD0y
118 | # 0BvL9WH8dQgAdryBDvjA4VzPxBFy5xtkSdgimnUVQvUtMjiB2vRgorq0Uvtc4GEk
119 | # JU+y38kpqHNDUdq9Y9YfW5v3LhtPEx33Sg1xfpe39D+E68Hjo0mh+s6nv1bPull2
120 | # YYlffqe0jmd4+TaY4cso2luHpoovMIIFMTCCBBmgAwIBAgIQCqEl1tYyG35B5AXa
121 | # NpfCFTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln
122 | # aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtE
123 | # aWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTYwMTA3MTIwMDAwWhcNMzEw
124 | # MTA3MTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j
125 | # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT
126 | # SEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBMIIBIjANBgkqhkiG9w0BAQEF
127 | # AAOCAQ8AMIIBCgKCAQEAvdAy7kvNj3/dqbqCmcU5VChXtiNKxA4HRTNREH3Q+X1N
128 | # aH7ntqD0jbOI5Je/YyGQmL8TvFfTw+F+CNZqFAA49y4eO+7MpvYyWf5fZT/gm+vj
129 | # RkcGGlV+Cyd+wKL1oODeIj8O/36V+/OjuiI+GKwR5PCZA207hXwJ0+5dyJoLVOOo
130 | # CXFr4M8iEA91z3FyTgqt30A6XLdR4aF5FMZNJCMwXbzsPGBqrC8HzP3w6kfZiFBe
131 | # /WZuVmEnKYmEUeaC50ZQ/ZQqLKfkdT66mA+Ef58xFNat1fJky3seBdCEGXIX8RcG
132 | # 7z3N1k3vBkL9olMqT4UdxB08r8/arBD13ays6Vb/kwIDAQABo4IBzjCCAcowHQYD
133 | # VR0OBBYEFPS24SAd/imu0uRhpbKiJbLIFzVuMB8GA1UdIwQYMBaAFEXroq/0ksuC
134 | # MS1Ri6enIZ3zbcgPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG
135 | # MBMGA1UdJQQMMAoGCCsGAQUFBwMIMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcw
136 | # AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8v
137 | # Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0
138 | # MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGln
139 | # aUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdp
140 | # Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMFAGA1UdIARJMEcw
141 | # OAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2Vy
142 | # dC5jb20vQ1BTMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAQEAcZUS6VGH
143 | # VmnN793afKpjerN4zwY3QITvS4S/ys8DAv3Fp8MOIEIsr3fzKx8MIVoqtwU0HWqu
144 | # mfgnoma/Capg33akOpMP+LLR2HwZYuhegiUexLoceywh4tZbLBQ1QwRostt1AuBy
145 | # x5jWPGTlH0gQGF+JOGFNYkYkh2OMkVIsrymJ5Xgf1gsUpYDXEkdws3XVk4WTfraS
146 | # Z/tTYYmo9WuWwPRYaQ18yAGxuSh1t5ljhSKMYcp5lH5Z/IwP42+1ASa2bKXuh1Eh
147 | # 5Fhgm7oMLSttosR+u8QlK0cCCHxJrhO24XxCQijGGFbPQTS2Zl22dHv1VjMiLyI2
148 | # skuiSpXY9aaOUjGCAk0wggJJAgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
149 | # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV
150 | # BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0ECEA1C
151 | # SuC+Ooj/YEAhzhQA8N0wDQYJYIZIAWUDBAIBBQCggZgwGgYJKoZIhvcNAQkDMQ0G
152 | # CyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yMTA0MDgwOTExMDlaMCsGCyqG
153 | # SIb3DQEJEAIMMRwwGjAYMBYEFOHXgqjhkb7va8oWkbWqtJSmJJvzMC8GCSqGSIb3
154 | # DQEJBDEiBCCHEAmNNj2zWjWYRfEi4FgzZvrI16kv/U2b9b3oHw6UVDANBgkqhkiG
155 | # 9w0BAQEFAASCAQCdefEKh6Qmwx7xGCkrYi/A+/Cla6LdnYJp38eMs3fqTTvjhyDw
156 | # HffXrwdqWy5/fgW3o3qJXqa5o7hLxYIoWSULOCpJRGdt+w7XKPAbZqHrN9elAhWJ
157 | # vpBTCEaj7dVxr1Ka4NsoPSYe0eidDBmmvGvp02J4Z1j8+ImQPKN6Hv/L8Ixaxe7V
158 | # mH4VtXIiBK8xXdi4wzO+A+qLtHEJXz3Gw8Bp3BNtlDGIUkIhVTM3Q1xcSEqhOLqo
159 | # PGdwCw9acxdXNWWPjOJkNH656Bvmkml+0p6MTGIeG4JCeRh1Wpqm1ZGSoEcXNaof
160 | # wOgj48YzI+dNqBD9i7RSWCqJr2ygYKRTxnuU
161 | # SIG # End signature block
162 |
--------------------------------------------------------------------------------
/tools/packman/bootstrap/generate_temp_folder.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | Copyright 2019 NVIDIA CORPORATION
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | #>
16 |
17 | param(
18 | [Parameter(Mandatory=$true)][string]$parentPath=$null
19 | )
20 | [string] $name = [System.Guid]::NewGuid()
21 | $out = Join-Path $parentPath $name
22 | New-Item -ItemType Directory -Path ($out) | Out-Null
23 | Write-Host $out
24 |
25 | # SIG # Begin signature block
26 | # MIIaVwYJKoZIhvcNAQcCoIIaSDCCGkQCAQExDzANBglghkgBZQMEAgEFADB5Bgor
27 | # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
28 | # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB29nsqMEu+VmSF
29 | # 7ckeVTPrEZ6hsXjOgPFlJm9ilgHUB6CCCiIwggTTMIIDu6ADAgECAhBi50XpIWUh
30 | # PJcfXEkK6hKlMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYDVQQGEwJVUzEdMBsGA1UE
31 | # ChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0
32 | # IE5ldHdvcmsxNTAzBgNVBAMTLFN5bWFudGVjIENsYXNzIDMgU0hBMjU2IENvZGUg
33 | # U2lnbmluZyBDQSAtIEcyMB4XDTE4MDcwOTAwMDAwMFoXDTIxMDcwOTIzNTk1OVow
34 | # gYMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQHDAtT
35 | # YW50YSBDbGFyYTEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0aW9uMQ8wDQYDVQQL
36 | # DAZJVC1NSVMxGzAZBgNVBAMMEk5WSURJQSBDb3Jwb3JhdGlvbjCCASIwDQYJKoZI
37 | # hvcNAQEBBQADggEPADCCAQoCggEBALEZN63dA47T4i90jZ84CJ/aWUwVtLff8AyP
38 | # YspFfIZGdZYiMgdb8A5tBh7653y0G/LZL6CVUkgejcpvBU/Dl/52a+gSWy2qJ2bH
39 | # jMFMKCyQDhdpCAKMOUKSC9rfzm4cFeA9ct91LQCAait4LhLlZt/HF7aG+r0FgCZa
40 | # HJjJvE7KNY9G4AZXxjSt8CXS8/8NQMANqjLX1r+F+Hl8PzQ1fVx0mMsbdtaIV4Pj
41 | # 5flAeTUnz6+dCTx3vTUo8MYtkS2UBaQv7t7H2B7iwJDakEQKk1XHswJdeqG0osDU
42 | # z6+NVks7uWE1N8UIhvzbw0FEX/U2kpfyWaB/J3gMl8rVR8idPj8CAwEAAaOCAT4w
43 | # ggE6MAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUF
44 | # BwMDMGEGA1UdIARaMFgwVgYGZ4EMAQQBMEwwIwYIKwYBBQUHAgEWF2h0dHBzOi8v
45 | # ZC5zeW1jYi5jb20vY3BzMCUGCCsGAQUFBwICMBkMF2h0dHBzOi8vZC5zeW1jYi5j
46 | # b20vcnBhMB8GA1UdIwQYMBaAFNTABiJJ6zlL3ZPiXKG4R3YJcgNYMCsGA1UdHwQk
47 | # MCIwIKAeoByGGmh0dHA6Ly9yYi5zeW1jYi5jb20vcmIuY3JsMFcGCCsGAQUFBwEB
48 | # BEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3JiLnN5bWNkLmNvbTAmBggrBgEFBQcw
49 | # AoYaaHR0cDovL3JiLnN5bWNiLmNvbS9yYi5jcnQwDQYJKoZIhvcNAQELBQADggEB
50 | # AIJKh5vKJdhHJtMzATmc1BmXIQ3RaJONOZ5jMHn7HOkYU1JP0OIzb4pXXkH8Xwfr
51 | # K6bnd72IhcteyksvKsGpSvK0PBBwzodERTAu1Os2N+EaakxQwV/xtqDm1E3IhjHk
52 | # fRshyKKzmFk2Ci323J4lHtpWUj5Hz61b8gd72jH7xnihGi+LORJ2uRNZ3YuqMNC3
53 | # SBC8tAyoJqEoTJirULUCXW6wX4XUm5P2sx+htPw7szGblVKbQ+PFinNGnsSEZeKz
54 | # D8jUb++1cvgTKH59Y6lm43nsJjkZU77tNqyq4ABwgQRk6lt8cS2PPwjZvTmvdnla
55 | # ZhR0K4of+pQaUQHXVIBdji8wggVHMIIEL6ADAgECAhB8GzU1SufbdOdBXxFpymuo
56 | # MA0GCSqGSIb3DQEBCwUAMIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNp
57 | # Z24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNV
58 | # BAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
59 | # IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmlj
60 | # YXRpb24gQXV0aG9yaXR5MB4XDTE0MDcyMjAwMDAwMFoXDTI0MDcyMTIzNTk1OVow
61 | # gYQxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEf
62 | # MB0GA1UECxMWU3ltYW50ZWMgVHJ1c3QgTmV0d29yazE1MDMGA1UEAxMsU3ltYW50
63 | # ZWMgQ2xhc3MgMyBTSEEyNTYgQ29kZSBTaWduaW5nIENBIC0gRzIwggEiMA0GCSqG
64 | # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDXlUPU3N9nrjn7UqS2JjEEcOm3jlsqujdp
65 | # NZWPu8Aw54bYc7vf69F2P4pWjustS/BXGE6xjaUz0wt1I9VqeSfdo9P3Dodltd6t
66 | # HPH1NbQiUa8iocFdS5B/wFlOq515qQLXHkmxO02H/sJ4q7/vUq6crwjZOeWaUT5p
67 | # XzAQTnFjbFjh8CAzGw90vlvLEuHbjMSAlHK79kWansElC/ujHJ7YpglwcezAR0yP
68 | # fcPeGc4+7gRyjhfT//CyBTIZTNOwHJ/+pXggQnBBsCaMbwDIOgARQXpBsKeKkQSg
69 | # mXj0d7TzYCrmbFAEtxRg/w1R9KiLhP4h2lxeffUpeU+wRHRvbXL/AgMBAAGjggF4
70 | # MIIBdDAuBggrBgEFBQcBAQQiMCAwHgYIKwYBBQUHMAGGEmh0dHA6Ly9zLnN5bWNk
71 | # LmNvbTASBgNVHRMBAf8ECDAGAQH/AgEAMGYGA1UdIARfMF0wWwYLYIZIAYb4RQEH
72 | # FwMwTDAjBggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYB
73 | # BQUHAgIwGRoXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwNgYDVR0fBC8wLTAroCmg
74 | # J4YlaHR0cDovL3Muc3ltY2IuY29tL3VuaXZlcnNhbC1yb290LmNybDATBgNVHSUE
75 | # DDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8EBAMCAQYwKQYDVR0RBCIwIKQeMBwxGjAY
76 | # BgNVBAMTEVN5bWFudGVjUEtJLTEtNzI0MB0GA1UdDgQWBBTUwAYiSes5S92T4lyh
77 | # uEd2CXIDWDAfBgNVHSMEGDAWgBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG
78 | # 9w0BAQsFAAOCAQEAf+vKp+qLdkLrPo4gVDDjt7nc+kg+FscPRZUQzSeGo2bzAu1x
79 | # +KrCVZeRcIP5Un5SaTzJ8eCURoAYu6HUpFam8x0AkdWG80iH4MvENGggXrTL+QXt
80 | # nK9wUye56D5+UaBpcYvcUe2AOiUyn0SvbkMo0yF1u5fYi4uM/qkERgSF9xWcSxGN
81 | # xCwX/tVuf5riVpLxlrOtLfn039qJmc6yOETA90d7yiW5+ipoM5tQct6on9TNLAs0
82 | # vYsweEDgjY4nG5BvGr4IFYFd6y/iUedRHsl4KeceZb847wFKAQkkDhbEFHnBQTc0
83 | # 0D2RUpSd4WjvCPDiaZxnbpALGpNx1CYCw8BaIzGCD4swgg+HAgEBMIGZMIGEMQsw
84 | # CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV
85 | # BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxNTAzBgNVBAMTLFN5bWFudGVjIENs
86 | # YXNzIDMgU0hBMjU2IENvZGUgU2lnbmluZyBDQSAtIEcyAhBi50XpIWUhPJcfXEkK
87 | # 6hKlMA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcN
88 | # AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw
89 | # LwYJKoZIhvcNAQkEMSIEIG5YDmcpqLxn4SB0H6OnuVkZRPh6OJ77eGW/6Su/uuJg
90 | # MA0GCSqGSIb3DQEBAQUABIIBAA3N2vqfA6WDgqz/7EoAKVIE5Hn7xpYDGhPvFAMV
91 | # BslVpeqE3apTcYFCEcwLtzIEc/zmpULxsX8B0SUT2VXbJN3zzQ80b+gbgpq62Zk+
92 | # dQLOtLSiPhGW7MXLahgES6Oc2dUFaQ+wDfcelkrQaOVZkM4wwAzSapxuf/13oSIk
93 | # ZX2ewQEwTZrVYXELO02KQIKUR30s/oslGVg77ALnfK9qSS96Iwjd4MyT7PzCkHUi
94 | # ilwyGJi5a4ofiULiPSwUQNynSBqxa+JQALkHP682b5xhjoDfyG8laR234FTPtYgs
95 | # P/FaeviwENU5Pl+812NbbtRD+gKlWBZz+7FKykOT/CG8sZahgg1EMIINQAYKKwYB
96 | # BAGCNwMDATGCDTAwgg0sBgkqhkiG9w0BBwKggg0dMIINGQIBAzEPMA0GCWCGSAFl
97 | # AwQCAQUAMHcGCyqGSIb3DQEJEAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglg
98 | # hkgBZQMEAgEFAAQgJhABfkDIPbI+nWYnA30FLTyaPK+W3QieT21B/vK+CMICEDF0
99 | # worcGsdd7OxpXLP60xgYDzIwMjEwNDA4MDkxMTA5WqCCCjcwggT+MIID5qADAgEC
100 | # AhANQkrgvjqI/2BAIc4UAPDdMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVT
101 | # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
102 | # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBp
103 | # bmcgQ0EwHhcNMjEwMTAxMDAwMDAwWhcNMzEwMTA2MDAwMDAwWjBIMQswCQYDVQQG
104 | # EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0
105 | # IFRpbWVzdGFtcCAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
106 | # wuZhhGfFivUNCKRFymNrUdc6EUK9CnV1TZS0DFC1JhD+HchvkWsMlucaXEjvROW/
107 | # m2HNFZFiWrj/ZwucY/02aoH6KfjdK3CF3gIY83htvH35x20JPb5qdofpir34hF0e
108 | # dsnkxnZ2OlPR0dNaNo/Go+EvGzq3YdZz7E5tM4p8XUUtS7FQ5kE6N1aG3JMjjfdQ
109 | # Jehk5t3Tjy9XtYcg6w6OLNUj2vRNeEbjA4MxKUpcDDGKSoyIxfcwWvkUrxVfbENJ
110 | # Cf0mI1P2jWPoGqtbsR0wwptpgrTb/FZUvB+hh6u+elsKIC9LCcmVp42y+tZji06l
111 | # chzun3oBc/gZ1v4NSYS9AQIDAQABo4IBuDCCAbQwDgYDVR0PAQH/BAQDAgeAMAwG
112 | # A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwQQYDVR0gBDowODA2
113 | # BglghkgBhv1sBwEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5j
114 | # b20vQ1BTMB8GA1UdIwQYMBaAFPS24SAd/imu0uRhpbKiJbLIFzVuMB0GA1UdDgQW
115 | # BBQ2RIaOpLqwZr68KC0dRDbd42p6vDBxBgNVHR8EajBoMDKgMKAuhixodHRwOi8v
116 | # Y3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNybDAyoDCgLoYsaHR0
117 | # cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5jcmwwgYUGCCsG
118 | # AQUFBwEBBHkwdzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t
119 | # ME8GCCsGAQUFBzAChkNodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl
120 | # cnRTSEEyQXNzdXJlZElEVGltZXN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUA
121 | # A4IBAQBIHNy16ZojvOca5yAOjmdG/UJyUXQKI0ejq5LSJcRwWb4UoOUngaVNFBUZ
122 | # B3nw0QTDhtk7vf5EAmZN7WmkD/a4cM9i6PVRSnh5Nnont/PnUp+Tp+1DnnvntN1B
123 | # Ion7h6JGA0789P63ZHdjXyNSaYOC+hpT7ZDMjaEXcw3082U5cEvznNZ6e9oMvD0y
124 | # 0BvL9WH8dQgAdryBDvjA4VzPxBFy5xtkSdgimnUVQvUtMjiB2vRgorq0Uvtc4GEk
125 | # JU+y38kpqHNDUdq9Y9YfW5v3LhtPEx33Sg1xfpe39D+E68Hjo0mh+s6nv1bPull2
126 | # YYlffqe0jmd4+TaY4cso2luHpoovMIIFMTCCBBmgAwIBAgIQCqEl1tYyG35B5AXa
127 | # NpfCFTANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGln
128 | # aUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtE
129 | # aWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTYwMTA3MTIwMDAwWhcNMzEw
130 | # MTA3MTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j
131 | # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBT
132 | # SEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBMIIBIjANBgkqhkiG9w0BAQEF
133 | # AAOCAQ8AMIIBCgKCAQEAvdAy7kvNj3/dqbqCmcU5VChXtiNKxA4HRTNREH3Q+X1N
134 | # aH7ntqD0jbOI5Je/YyGQmL8TvFfTw+F+CNZqFAA49y4eO+7MpvYyWf5fZT/gm+vj
135 | # RkcGGlV+Cyd+wKL1oODeIj8O/36V+/OjuiI+GKwR5PCZA207hXwJ0+5dyJoLVOOo
136 | # CXFr4M8iEA91z3FyTgqt30A6XLdR4aF5FMZNJCMwXbzsPGBqrC8HzP3w6kfZiFBe
137 | # /WZuVmEnKYmEUeaC50ZQ/ZQqLKfkdT66mA+Ef58xFNat1fJky3seBdCEGXIX8RcG
138 | # 7z3N1k3vBkL9olMqT4UdxB08r8/arBD13ays6Vb/kwIDAQABo4IBzjCCAcowHQYD
139 | # VR0OBBYEFPS24SAd/imu0uRhpbKiJbLIFzVuMB8GA1UdIwQYMBaAFEXroq/0ksuC
140 | # MS1Ri6enIZ3zbcgPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG
141 | # MBMGA1UdJQQMMAoGCCsGAQUFBwMIMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcw
142 | # AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8v
143 | # Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0
144 | # MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGln
145 | # aUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdp
146 | # Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMFAGA1UdIARJMEcw
147 | # OAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2Vy
148 | # dC5jb20vQ1BTMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAQEAcZUS6VGH
149 | # VmnN793afKpjerN4zwY3QITvS4S/ys8DAv3Fp8MOIEIsr3fzKx8MIVoqtwU0HWqu
150 | # mfgnoma/Capg33akOpMP+LLR2HwZYuhegiUexLoceywh4tZbLBQ1QwRostt1AuBy
151 | # x5jWPGTlH0gQGF+JOGFNYkYkh2OMkVIsrymJ5Xgf1gsUpYDXEkdws3XVk4WTfraS
152 | # Z/tTYYmo9WuWwPRYaQ18yAGxuSh1t5ljhSKMYcp5lH5Z/IwP42+1ASa2bKXuh1Eh
153 | # 5Fhgm7oMLSttosR+u8QlK0cCCHxJrhO24XxCQijGGFbPQTS2Zl22dHv1VjMiLyI2
154 | # skuiSpXY9aaOUjGCAk0wggJJAgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
155 | # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV
156 | # BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0ECEA1C
157 | # SuC+Ooj/YEAhzhQA8N0wDQYJYIZIAWUDBAIBBQCggZgwGgYJKoZIhvcNAQkDMQ0G
158 | # CyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yMTA0MDgwOTExMDlaMCsGCyqG
159 | # SIb3DQEJEAIMMRwwGjAYMBYEFOHXgqjhkb7va8oWkbWqtJSmJJvzMC8GCSqGSIb3
160 | # DQEJBDEiBCDvFxQ6lYLr8vB+9czUl19rjCw1pWhhUXw/SqOmvIa/VDANBgkqhkiG
161 | # 9w0BAQEFAASCAQB9ox2UrcUXQsBI4Uycnhl4AMpvhVXJME62tygFMppW1l7QftDy
162 | # LvfPKRYm2YUioak/APxAS6geRKpeMkLvXuQS/Jlv0kY3BjxkeG0eVjvyjF4SvXbZ
163 | # 3JCk9m7wLNE+xqOo0ICjYlIJJgRLudjWkC5Skpb1NpPS8DOaIYwRV+AWaSOUPd9P
164 | # O5yVcnbl7OpK3EAEtwDrybCVBMPn2MGhAXybIHnth3+MFp1b6Blhz3WlReQyarjq
165 | # 1f+zaFB79rg6JswXoOTJhwICBP3hO2Ua3dMAswbfl+QNXF+igKLJPYnaeSVhBbm6
166 | # VCu2io27t4ixqvoD0RuPObNX/P3oVA38afiM
167 | # SIG # End signature block
168 |
--------------------------------------------------------------------------------
/exts/isaacsim.zmq.bridge/plugins/nodes/OgnIsaacBridgeZMQNode.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2 | // SPDX-License-Identifier: MIT
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 |
14 | #include
15 | #include
16 |
17 | #include
18 |
19 | #include
20 | #include "client_stream_message.pb.h"
21 |
22 |
23 | using omni::graph::core::Type;
24 | using omni::graph::core::BaseDataType;
25 |
26 | #define CUDA_CHECK(call) \
27 | do { \
28 | cudaError_t err = call; \
29 | if (err != cudaSuccess) { \
30 | fprintf(stderr, "CUDA error at %s %d: %s\n", __FILE__, __LINE__, \
31 | cudaGetErrorString(err)); \
32 | /* Instead of exiting, log the error and continue */ \
33 | return true; \
34 | } \
35 | } while (0)
36 |
37 | namespace zmq_lib = zmq; // assign namespace to zmq library to avoid conflicts with our library
38 |
39 | namespace isaacsim {
40 | namespace zmq {
41 | namespace bridge {
42 |
43 | struct InputDataBBox2d {
44 | uint32_t semanticId;
45 | int xMin;
46 | int yMin;
47 | int xMax;
48 | int yMax;
49 | float occlusionRatio;
50 | };
51 |
52 | class OgnIsaacBridgeZMQNode {
53 | std::unique_ptr m_zmqContext;
54 | std::unique_ptr m_zmqSocket;
55 | uint32_t m_port;
56 | std::string m_ip;
57 | std::mutex m_mutex;
58 | cudaStream_t m_cudaStream;
59 | bool m_cudaStreamNotCreated{ true };
60 | uint32_t m_zmqFailCount{ 0 };
61 |
62 | public:
63 | OgnIsaacBridgeZMQNode()
64 | : m_zmqContext(std::make_unique(1)) {
65 | CARB_LOG_INFO("OgnIsaacBridgeZMQNode::constructor\n");
66 | }
67 | ~OgnIsaacBridgeZMQNode() {
68 | CARB_LOG_INFO("OgnIsaacBridgeZMQNode::destructor\n");
69 | if (m_zmqSocket) {
70 | m_zmqSocket->close();
71 | }
72 | if (m_zmqContext) {
73 | m_zmqContext->close();
74 | }
75 |
76 | // Clean up CUDA stream if it was created
77 | if (!m_cudaStreamNotCreated) {
78 | cudaError_t err = cudaStreamDestroy(m_cudaStream);
79 | if (err != cudaSuccess) {
80 | // Just log the error instead of using CUDA_CHECK
81 | CARB_LOG_ERROR("Error destroying CUDA stream in destructor: %s", cudaGetErrorString(err));
82 | }
83 | }
84 | }
85 |
86 | static bool compute(OgnIsaacBridgeZMQNodeDatabase& db);
87 |
88 | bool initializeSocket(uint32_t port, const std::string& ip) {
89 | std::lock_guard lock(m_mutex);
90 |
91 | m_port = port;
92 | m_ip = ip;
93 | m_zmqFailCount = 0;
94 |
95 | try {
96 | m_zmqSocket = std::make_unique(*m_zmqContext, zmq_lib::socket_type::push);
97 |
98 | int linger = 0;
99 | m_zmqSocket->setsockopt(ZMQ_LINGER, &linger, sizeof(linger));
100 |
101 | int hwm = 1;
102 | m_zmqSocket->setsockopt(ZMQ_SNDHWM, &hwm, sizeof(hwm));
103 |
104 | std::string address = "tcp://" + m_ip + ":" + std::to_string(m_port);
105 | m_zmqSocket->connect(address);
106 | CARB_LOG_INFO("Connected to %s\n", address.c_str());
107 | return true;
108 | } catch (const std::exception& e) {
109 | CARB_LOG_WARN("Failed to create socket or connect to %s:%d: %s", m_ip.c_str(), m_port, e.what());
110 | m_zmqSocket.reset();
111 | return false;
112 | }
113 | }
114 | };
115 |
116 |
117 | bool OgnIsaacBridgeZMQNode::compute(OgnIsaacBridgeZMQNodeDatabase& db) {
118 | // Static variable to track the last time an error was logged
119 | // This persists between function calls to limit error message frequency
120 | static double lastErrorLogTime = 0.0;
121 |
122 | // Get the internal state for this node
123 | auto& state = db.internalState();
124 |
125 | // Get the port and IP address from the inputs
126 | uint32_t port = db.inputs.port();
127 | const omni::graph::core::ogn::const_string& ip = db.inputs.ip();
128 | std::string std_ip(ip.data(), ip.size());
129 |
130 | // If the socket is not initialized, or the port or IP address has changed, initialize the socket
131 | if (!state.m_zmqSocket || port != state.m_port || std_ip != state.m_ip) {
132 | if (!state.initializeSocket(port, std_ip)) {
133 | return true;
134 | }
135 | }
136 |
137 | // Create Protobuf message
138 | ClientStreamMessage message;
139 |
140 | // Bounding boxes 2d
141 | const InputDataBBox2d* bbox_data = reinterpret_cast(db.inputs.dataBBox2d().data());
142 | size_t num_boxes = db.inputs.dataBBox2d().size() / sizeof(InputDataBBox2d);
143 | auto& bbox_ids = db.inputs.idsBBox2d();
144 | auto& bbox_bbox_ids = db.inputs.bboxIdsBBox2d();
145 | auto& bbox_labels = db.inputs.labelsBBox2d();
146 |
147 | // Populate bbox2d data
148 | for (size_t i = 0; i < num_boxes; ++i) {
149 | const InputDataBBox2d& bbox = bbox_data[i];
150 | BBox2DType* bbox_proto = message.mutable_bbox2d()->add_data();
151 | bbox_proto->set_semanticid(bbox.semanticId);
152 | bbox_proto->set_xmin(bbox.xMin);
153 | bbox_proto->set_ymin(bbox.yMin);
154 | bbox_proto->set_xmax(bbox.xMax);
155 | bbox_proto->set_ymax(bbox.yMax);
156 | bbox_proto->set_occlusionratio(bbox.occlusionRatio);
157 | }
158 |
159 | // Populate bboxIds
160 | for (size_t i = 0; i < bbox_bbox_ids.size(); ++i) {
161 | message.mutable_bbox2d()->mutable_info()->add_bboxids(bbox_bbox_ids[i]);
162 | }
163 |
164 | // Populate idToLabels
165 | for (size_t i = 0; i < bbox_ids.size(); ++i) {
166 | int id = bbox_ids[i];
167 | std::string label = db.tokenToString(bbox_labels[i]);
168 | (*message.mutable_bbox2d()->mutable_info()->mutable_idtolabels())[std::to_string(id)] = label;
169 | }
170 |
171 | // Simulation & System time
172 | double sim_dt = db.inputs.deltaSimulationTime();
173 | double sys_dt = db.inputs.deltaSystemTime();
174 | double sim_time = db.inputs.simulationTime();
175 | double sys_time = db.inputs.systemTime();
176 |
177 | message.mutable_clock()->set_sim_dt(sim_dt);
178 | message.mutable_clock()->set_sys_dt(sys_dt);
179 | message.mutable_clock()->set_sim_time(sim_time);
180 | message.mutable_clock()->set_sys_time(sys_time);
181 |
182 | // Camera data
183 | const pxr::GfMatrix4d& view_matrix = db.inputs.cameraViewTransform();
184 | const pxr::GfVec3d& scale = db.inputs.cameraWorldScale();
185 | const pxr::GfMatrix3d& intrinsics_matrix = db.inputs.cameraIntrinsics();
186 |
187 | // Flatten and populate view_matrix_ros
188 | for (int row = 0; row < 4; ++row) {
189 | for (int col = 0; col < 4; ++col) {
190 | message.mutable_camera()->add_view_matrix_ros(view_matrix[row][col]);
191 | }
192 | }
193 |
194 | // Populate camera_scale
195 | message.mutable_camera()->add_camera_scale(scale[0]);
196 | message.mutable_camera()->add_camera_scale(scale[1]);
197 | message.mutable_camera()->add_camera_scale(scale[2]);
198 |
199 | // Flatten and populate intrinsics_matrix
200 | for (int row = 0; row < 3; ++row) {
201 | for (int col = 0; col < 3; ++col) {
202 | message.mutable_camera()->add_intrinsics_matrix(intrinsics_matrix[row][col]);
203 | }
204 | }
205 |
206 | // RGB & DEPTH
207 |
208 | // Copy from Device to Host
209 | size_t data_size_color = db.inputs.bufferSizeColor();
210 | uint64_t raw_ptr_color = db.inputs.dataPtrColor();
211 | auto data_ptr_color = std::make_unique(data_size_color);
212 |
213 | size_t data_size_depth = db.inputs.bufferSizeDepth();
214 | uint64_t raw_ptr_depth = db.inputs.dataPtrDepth();
215 | auto data_ptr_depth = std::make_unique(data_size_depth / sizeof(float));
216 |
217 | // Create CUDA stream if not already created
218 | if (state.m_cudaStreamNotCreated) {
219 | CUDA_CHECK(cudaStreamCreate(&state.m_cudaStream));
220 | state.m_cudaStreamNotCreated = false;
221 | }
222 |
223 | // If the stream is not created, warn and return true
224 | if (state.m_cudaStreamNotCreated) {
225 | CARB_LOG_WARN("CUDA stream not created, will not stream images");
226 | return true;
227 | }
228 |
229 | // Use the stream for memory operations
230 | CUDA_CHECK(cudaMemcpyAsync(data_ptr_color.get(), reinterpret_cast(raw_ptr_color),
231 | data_size_color, cudaMemcpyDeviceToHost, state.m_cudaStream));
232 |
233 | CUDA_CHECK(cudaMemcpyAsync(data_ptr_depth.get(), reinterpret_cast(raw_ptr_depth),
234 | data_size_depth, cudaMemcpyDeviceToHost, state.m_cudaStream));
235 |
236 | CUDA_CHECK(cudaStreamSynchronize(state.m_cudaStream));
237 |
238 | // Add image data to Protobuf message
239 | message.set_color_image(data_ptr_color.get(), data_size_color);
240 | message.set_depth_image(reinterpret_cast(data_ptr_depth.get()), data_size_depth);
241 |
242 | // Serialize Protobuf message
243 | std::string serialized_message;
244 | message.SerializeToString(&serialized_message);
245 |
246 | // ZMQ Data sending
247 | zmq_lib::message_t zmq_message(serialized_message.size());
248 | memcpy(zmq_message.data(), serialized_message.data(), serialized_message.size());
249 | auto message_sent = state.m_zmqSocket->send(zmq_message, zmq_lib::send_flags::dontwait);
250 |
251 | if (!message_sent.has_value()) {
252 | state.m_zmqFailCount++;
253 | double currentTime = db.inputs.systemTime();
254 | // Log the error state every 5 seconds,
255 | // and only if errors are accumulating.
256 | if (state.m_zmqFailCount > 20 && currentTime - lastErrorLogTime >= 5.0) {
257 | CARB_LOG_ERROR("Failed to send message (no server available)");
258 | lastErrorLogTime = currentTime;
259 | }
260 | } else {
261 | state.m_zmqFailCount = 0;
262 | }
263 |
264 | return true;
265 | }
266 |
267 | // This macro provides the information necessary to OmniGraph that lets it automatically register and deregister
268 | // your node type definition.
269 | REGISTER_OGN_NODE()
270 |
271 | } // bridge
272 | } // zmq
273 | } // isaacsim
274 |
--------------------------------------------------------------------------------
/assets/franka_world.usda:
--------------------------------------------------------------------------------
1 | #usda 1.0
2 | (
3 | customLayerData = {
4 | dictionary cameraSettings = {
5 | dictionary Front = {
6 | double3 position = (5, 0, 0)
7 | double radius = 5
8 | }
9 | dictionary Perspective = {
10 | double3 position = (0.40973424888394017, 1.937909539741277, 0.7595238826797109)
11 | double3 target = (0.5786803092460564, 1.2909837464738065, 0.6568495708366566)
12 | }
13 | dictionary Right = {
14 | double3 position = (0, -5, 0)
15 | double radius = 5
16 | }
17 | dictionary Top = {
18 | double3 position = (0, 0, 5)
19 | double radius = 5
20 | }
21 | string boundCamera = "/OmniverseKit_Persp"
22 | }
23 | dictionary omni_layer = {
24 | string authoring_layer = "./franka_world.usda"
25 | dictionary locked = {
26 | bool "./props/camera.usda" = 1
27 | bool "./props/looks.usd" = 0
28 | bool "./props/model.usd" = 0
29 | bool "./props/physics.usd" = 0
30 | bool "./props/scale.usd" = 0
31 | bool "./props/sensor.usd" = 0
32 | }
33 | }
34 | dictionary physicsSettings = {
35 | int "/persistent/simulation/minFrameRate" = 60
36 | }
37 | dictionary renderSettings = {
38 | }
39 | }
40 | defaultPrim = "World"
41 | endTimeCode = 1000000
42 | metersPerUnit = 1
43 | startTimeCode = 0
44 | timeCodesPerSecond = 60
45 | upAxis = "Z"
46 | )
47 |
48 | def Xform "World"
49 | {
50 | custom string cmd_path = ""
51 |
52 | def Xform "GroundPlane"
53 | {
54 | quatf xformOp:orient = (1, 0, 0, 0)
55 | float3 xformOp:scale = (1, 1, 1)
56 | double3 xformOp:translate = (0, 0, 0)
57 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
58 |
59 | def Mesh "CollisionMesh"
60 | {
61 | uniform bool doubleSided = 0
62 | int[] faceVertexCounts = [4]
63 | int[] faceVertexIndices = [0, 1, 2, 3]
64 | normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)]
65 | point3f[] points = [(-25, -25, 0), (25, -25, 0), (25, 25, 0), (-25, 25, 0)]
66 | color3f[] primvars:displayColor = [(0.5, 0.5, 0.5)]
67 | bool primvars:isMatteObject = 1
68 | texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1)] (
69 | interpolation = "varying"
70 | )
71 | }
72 |
73 | def Plane "CollisionPlane" (
74 | prepend apiSchemas = ["PhysicsCollisionAPI"]
75 | )
76 | {
77 | uniform token axis = "Z"
78 | bool primvars:isMatteObject = 1
79 | uniform token purpose = "guide"
80 | }
81 | }
82 |
83 | def Mesh "Target" (
84 | prepend apiSchemas = ["SemanticsAPI:Semantics_1Vc4", "MaterialBindingAPI"]
85 | )
86 | {
87 | float3[] extent = [(-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)]
88 | int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
89 | int[] faceVertexIndices = [0, 1, 3, 2, 4, 6, 7, 5, 6, 2, 3, 7, 4, 5, 1, 0, 4, 0, 2, 6, 5, 7, 3, 1]
90 | rel material:binding = (
91 | bindMaterialAs = "weakerThanDescendants"
92 | )
93 | normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0)] (
94 | interpolation = "faceVarying"
95 | )
96 | point3f[] points = [(-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5)]
97 | texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1), (1, 0), (1, 1), (0, 1), (0, 0), (0, 1), (0, 0), (1, 0), (1, 1), (0, 0), (1, 0), (1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 1), (1, 0), (1, 1), (0, 1), (0, 0)] (
98 | interpolation = "faceVarying"
99 | )
100 | string semantic:Semantics_1Vc4:params:semanticData = "object"
101 | string semantic:Semantics_1Vc4:params:semanticType = "class"
102 | uniform token subdivisionScheme = "none"
103 | quatd xformOp:orient = (1, 0, 0, 0)
104 | double3 xformOp:scale = (0.05, 0.05, 0.05)
105 | double3 xformOp:translate = (0.4, 0, 0.025)
106 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
107 | }
108 |
109 | def RectLight "RectLight" (
110 | prepend apiSchemas = ["ShapingAPI"]
111 | )
112 | {
113 | float3[] extent = [(-50, -50, -0), (50, 50, 0)]
114 | float inputs:exposure = 0
115 | float inputs:height = 100
116 | float inputs:intensity = 8000
117 | bool inputs:normalize = 1
118 | float inputs:shaping:cone:angle = 180
119 | float inputs:shaping:cone:softness
120 | float inputs:shaping:focus
121 | color3f inputs:shaping:focusTint
122 | asset inputs:shaping:ies:file
123 | float inputs:width = 100
124 | bool visibleInPrimaryRay = 0
125 | quatd xformOp:orient = (0.7071067811865476, 0, 0, 0.7071067811865475)
126 | double3 xformOp:scale = (0.0007000000000030127, 0.0007000000000030127, 0.0007000000000030127)
127 | double3 xformOp:translate = (0.9131000543134977, -9.084533137818426e-15, 1.553758659902226)
128 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
129 | }
130 |
131 | def Xform "camera" (
132 | displayName = "camera"
133 | references = @./props/interface_camera.usd@
134 | )
135 | {
136 | quatd xformOp:orient = (0.18301270189221946, -0.18301270189221924, -0.6830127018922193, 0.6830127018922194)
137 | float3 xformOp:rotateXYZ = (0, 0, 0)
138 | double3 xformOp:scale = (0.1, 0.1, 0.1)
139 | double3 xformOp:translate = (0.8, 1.3, 0.7)
140 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
141 | }
142 | }
143 |
144 | def Xform "Environment"
145 | {
146 | quatd xformOp:orient = (1, 0, 0, 0)
147 | double3 xformOp:scale = (1, 1, 1)
148 | double3 xformOp:translate = (0, 0, 0)
149 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
150 |
151 | def DomeLight "sky" (
152 | prepend apiSchemas = ["ShapingAPI"]
153 | )
154 | {
155 | float inputs:exposure = -1
156 | float inputs:intensity = 1000
157 | float inputs:shaping:cone:angle = 180
158 | float inputs:shaping:cone:softness
159 | float inputs:shaping:focus
160 | color3f inputs:shaping:focusTint
161 | asset inputs:shaping:ies:file
162 | float inputs:specular = 1
163 | asset inputs:texture:file = @https://omniverse-content-production.s3.us-west-2.amazonaws.com/Environments/2023_1/DomeLights/Indoor/ZetoCGcom_ExhibitionHall_Interior1.hdr@
164 | token inputs:texture:format = "latlong"
165 | token visibility = "inherited"
166 | bool visibleInPrimaryRay = 1
167 | quatd xformOp:orient = (1, 0, 0, 0)
168 | double3 xformOp:scale = (1, 1, 1)
169 | double3 xformOp:translate = (0, 0, 0)
170 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
171 | }
172 | }
173 |
174 | def PhysicsScene "physicsScene" (
175 | prepend apiSchemas = ["PhysxSceneAPI"]
176 | )
177 | {
178 | vector3f physics:gravityDirection = (0, 0, -1)
179 | float physics:gravityMagnitude = 9.81
180 | uniform token physxScene:broadphaseType = "MBP"
181 | bool physxScene:enableCCD = 1
182 | bool physxScene:enableGPUDynamics = 0
183 | bool physxScene:enableStabilization = 1
184 | uniform token physxScene:solverType = "TGS"
185 | uint physxScene:timeStepsPerSecond = 60
186 | }
187 |
188 | def "Render" (
189 | hide_in_stage_window = true
190 | no_delete = true
191 | )
192 | {
193 | def "OmniverseKit"
194 | {
195 | def "HydraTextures" (
196 | hide_in_stage_window = true
197 | no_delete = true
198 | )
199 | {
200 | def RenderProduct "omni_kit_widget_viewport_ViewportTexture_0" (
201 | prepend apiSchemas = ["OmniRtxSettingsCommonAdvancedAPI_1", "OmniRtxSettingsRtAdvancedAPI_1", "OmniRtxSettingsPtAdvancedAPI_1", "OmniRtxPostColorGradingAPI_1", "OmniRtxPostChromaticAberrationAPI_1", "OmniRtxPostBloomPhysicalAPI_1", "OmniRtxPostMatteObjectAPI_1", "OmniRtxPostCompositingAPI_1", "OmniRtxPostDofAPI_1", "OmniRtxPostMotionBlurAPI_1", "OmniRtxPostTvNoiseAPI_1", "OmniRtxPostTonemapIrayReinhardAPI_1", "OmniRtxPostDebugSettingsAPI_1", "OmniRtxDebugSettingsAPI_1"]
202 | hide_in_stage_window = true
203 | no_delete = true
204 | )
205 | {
206 | rel camera =
207 | token omni:rtx:background:source:texture:textureMode = "repeatMirrored"
208 | token omni:rtx:background:source:type = "domeLight"
209 | bool omni:rtx:dlss:frameGeneration = 0
210 | string omni:rtx:material:db:rtSensorNameToIdMap = "DefaultMaterial:0;AsphaltStandardMaterial:1;AsphaltWeatheredMaterial:2;VegetationGrassMaterial:3;WaterStandardMaterial:4;GlassStandardMaterial:5;FiberGlassMaterial:6;MetalAlloyMaterial:7;MetalAluminumMaterial:8;MetalAluminumOxidizedMaterial:9;PlasticStandardMaterial:10;RetroMarkingsMaterial:11;RetroSignMaterial:12;RubberStandardMaterial:13;SoilClayMaterial:14;ConcreteRoughMaterial:15;ConcreteSmoothMaterial:16;OakTreeBarkMaterial:17;FabricStandardMaterial:18;PlexiGlassStandardMaterial:19;MetalSilverMaterial:20"
211 | bool omni:rtx:material:db:syncLoads = 1
212 | bool omni:rtx:post:registeredCompositing:invertColorCorrection = 1
213 | bool omni:rtx:post:registeredCompositing:invertToneMap = 1
214 | bool omni:rtx:pt:lightcache:cached:dontResolveConflicts = 1
215 | int omni:rtx:pt:maxSamplesPerLaunch = 2073600
216 | int omni:rtx:pt:mgpu:maxPixelsPerRegionExponent = 12
217 | color3f omni:rtx:rt:ambientLight:color = (0.1, 0.1, 0.1)
218 | bool omni:rtx:rt:demoire = 0
219 | bool omni:rtx:rt:lightcache:spatialCache:dontResolveConflicts = 1
220 | bool omni:rtx:scene:hydra:materialSyncLoads = 1
221 | bool omni:rtx:scene:hydra:mdlMaterialWarmup = 1
222 | uint omni:rtx:viewTile:limit = 4294967295
223 | rel orderedVars =
224 | custom bool overrideClipRange = 0
225 | uniform int2 resolution = (1280, 720)
226 | }
227 | }
228 | }
229 |
230 | def RenderSettings "OmniverseGlobalRenderSettings" (
231 | prepend apiSchemas = ["OmniRtxSettingsGlobalRtAdvancedAPI_1", "OmniRtxSettingsGlobalPtAdvancedAPI_1"]
232 | no_delete = true
233 | )
234 | {
235 | rel products =
236 | }
237 |
238 | def "Vars"
239 | {
240 | def RenderVar "LdrColor" (
241 | hide_in_stage_window = true
242 | no_delete = true
243 | )
244 | {
245 | uniform string sourceName = "LdrColor"
246 | }
247 | }
248 | }
249 |
250 |
--------------------------------------------------------------------------------
/assets/franka_multi_cam_world.usda:
--------------------------------------------------------------------------------
1 | #usda 1.0
2 | (
3 | customLayerData = {
4 | dictionary cameraSettings = {
5 | dictionary Front = {
6 | double3 position = (5, 0, 0)
7 | double radius = 5
8 | }
9 | dictionary Perspective = {
10 | double3 position = (0.40973424888394017, 1.937909539741277, 0.7595238826797109)
11 | double3 target = (0.5786803092460564, 1.2909837464738065, 0.6568495708366566)
12 | }
13 | dictionary Right = {
14 | double3 position = (0, -5, 0)
15 | double radius = 5
16 | }
17 | dictionary Top = {
18 | double3 position = (0, 0, 5)
19 | double radius = 5
20 | }
21 | string boundCamera = "/OmniverseKit_Persp"
22 | }
23 | dictionary omni_layer = {
24 | string authoring_layer = "./franka_world.usda"
25 | dictionary locked = {
26 | bool "./props/camera.usda" = 1
27 | bool "./props/looks.usd" = 0
28 | bool "./props/model.usd" = 0
29 | bool "./props/physics.usd" = 0
30 | bool "./props/scale.usd" = 0
31 | bool "./props/sensor.usd" = 0
32 | }
33 | }
34 | dictionary physicsSettings = {
35 | int "/persistent/simulation/minFrameRate" = 60
36 | }
37 | dictionary renderSettings = {
38 | }
39 | }
40 | defaultPrim = "World"
41 | endTimeCode = 1000000
42 | metersPerUnit = 1
43 | startTimeCode = 0
44 | timeCodesPerSecond = 60
45 | upAxis = "Z"
46 | )
47 |
48 | def Xform "World"
49 | {
50 | custom string cmd_path = ""
51 |
52 | def Xform "GroundPlane"
53 | {
54 | quatf xformOp:orient = (1, 0, 0, 0)
55 | float3 xformOp:scale = (1, 1, 1)
56 | double3 xformOp:translate = (0, 0, 0)
57 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
58 |
59 | def Mesh "CollisionMesh"
60 | {
61 | uniform bool doubleSided = 0
62 | int[] faceVertexCounts = [4]
63 | int[] faceVertexIndices = [0, 1, 2, 3]
64 | normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)]
65 | point3f[] points = [(-25, -25, 0), (25, -25, 0), (25, 25, 0), (-25, 25, 0)]
66 | color3f[] primvars:displayColor = [(0.5, 0.5, 0.5)]
67 | bool primvars:isMatteObject = 1
68 | texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1)] (
69 | interpolation = "varying"
70 | )
71 | }
72 |
73 | def Plane "CollisionPlane" (
74 | prepend apiSchemas = ["PhysicsCollisionAPI"]
75 | )
76 | {
77 | uniform token axis = "Z"
78 | bool primvars:isMatteObject = 1
79 | uniform token purpose = "guide"
80 | }
81 | }
82 |
83 | def Mesh "Target" (
84 | prepend apiSchemas = ["SemanticsAPI:Semantics_1Vc4", "MaterialBindingAPI"]
85 | )
86 | {
87 | float3[] extent = [(-0.5, -0.5, -0.5), (0.5, 0.5, 0.5)]
88 | int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
89 | int[] faceVertexIndices = [0, 1, 3, 2, 4, 6, 7, 5, 6, 2, 3, 7, 4, 5, 1, 0, 4, 0, 2, 6, 5, 7, 3, 1]
90 | rel material:binding = (
91 | bindMaterialAs = "weakerThanDescendants"
92 | )
93 | normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, 1, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (0, -1, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (-1, 0, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0), (1, 0, 0)] (
94 | interpolation = "faceVarying"
95 | )
96 | point3f[] points = [(-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5)]
97 | texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1), (1, 0), (1, 1), (0, 1), (0, 0), (0, 1), (0, 0), (1, 0), (1, 1), (0, 0), (1, 0), (1, 1), (0, 1), (0, 0), (1, 0), (1, 1), (0, 1), (1, 0), (1, 1), (0, 1), (0, 0)] (
98 | interpolation = "faceVarying"
99 | )
100 | string semantic:Semantics_1Vc4:params:semanticData = "object"
101 | string semantic:Semantics_1Vc4:params:semanticType = "class"
102 | uniform token subdivisionScheme = "none"
103 | quatd xformOp:orient = (1, 0, 0, 0)
104 | double3 xformOp:scale = (0.05, 0.05, 0.05)
105 | double3 xformOp:translate = (0.4, 0, 0.025)
106 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
107 | }
108 |
109 | def RectLight "RectLight" (
110 | prepend apiSchemas = ["ShapingAPI"]
111 | )
112 | {
113 | float3[] extent = [(-50, -50, -0), (50, 50, 0)]
114 | float inputs:exposure = 0
115 | float inputs:height = 100
116 | float inputs:intensity = 8000
117 | bool inputs:normalize = 1
118 | float inputs:shaping:cone:angle = 180
119 | float inputs:shaping:cone:softness
120 | float inputs:shaping:focus
121 | color3f inputs:shaping:focusTint
122 | asset inputs:shaping:ies:file
123 | float inputs:width = 100
124 | bool visibleInPrimaryRay = 0
125 | quatd xformOp:orient = (0.7071067811865476, 0, 0, 0.7071067811865475)
126 | double3 xformOp:scale = (0.0007000000000030127, 0.0007000000000030127, 0.0007000000000030127)
127 | double3 xformOp:translate = (0.9131000543134977, -9.084533137818426e-15, 1.553758659902226)
128 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
129 | }
130 |
131 | def Xform "camera" (
132 | displayName = "camera"
133 | references = @./props/interface_camera.usd@
134 | )
135 | {
136 | quatd xformOp:orient = (0.18301270189221946, -0.18301270189221924, -0.6830127018922193, 0.6830127018922194)
137 | float3 xformOp:rotateXYZ = (0, 0, 0)
138 | double3 xformOp:scale = (0.1, 0.1, 0.1)
139 | double3 xformOp:translate = (0.8, 1.3, 0.7)
140 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
141 | }
142 | }
143 |
144 | def Xform "Environment"
145 | {
146 | quatd xformOp:orient = (1, 0, 0, 0)
147 | double3 xformOp:scale = (1, 1, 1)
148 | double3 xformOp:translate = (0, 0, 0)
149 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
150 |
151 | def DomeLight "sky" (
152 | prepend apiSchemas = ["ShapingAPI"]
153 | )
154 | {
155 | float inputs:exposure = -1
156 | float inputs:intensity = 1000
157 | float inputs:shaping:cone:angle = 180
158 | float inputs:shaping:cone:softness
159 | float inputs:shaping:focus
160 | color3f inputs:shaping:focusTint
161 | asset inputs:shaping:ies:file
162 | float inputs:specular = 1
163 | asset inputs:texture:file = @https://omniverse-content-production.s3.us-west-2.amazonaws.com/Environments/2023_1/DomeLights/Indoor/ZetoCGcom_ExhibitionHall_Interior1.hdr@
164 | token inputs:texture:format = "latlong"
165 | token visibility = "inherited"
166 | bool visibleInPrimaryRay = 1
167 | quatd xformOp:orient = (1, 0, 0, 0)
168 | double3 xformOp:scale = (1, 1, 1)
169 | double3 xformOp:translate = (0, 0, 0)
170 | uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"]
171 | }
172 | }
173 |
174 | def PhysicsScene "physicsScene" (
175 | prepend apiSchemas = ["PhysxSceneAPI"]
176 | )
177 | {
178 | vector3f physics:gravityDirection = (0, 0, -1)
179 | float physics:gravityMagnitude = 9.81
180 | uniform token physxScene:broadphaseType = "MBP"
181 | bool physxScene:enableCCD = 1
182 | bool physxScene:enableGPUDynamics = 0
183 | bool physxScene:enableStabilization = 1
184 | uniform token physxScene:solverType = "TGS"
185 | uint physxScene:timeStepsPerSecond = 60
186 | }
187 |
188 | def "Render" (
189 | hide_in_stage_window = true
190 | no_delete = true
191 | )
192 | {
193 | def "OmniverseKit"
194 | {
195 | def "HydraTextures" (
196 | hide_in_stage_window = true
197 | no_delete = true
198 | )
199 | {
200 | def RenderProduct "omni_kit_widget_viewport_ViewportTexture_0" (
201 | prepend apiSchemas = ["OmniRtxSettingsCommonAdvancedAPI_1", "OmniRtxSettingsRtAdvancedAPI_1", "OmniRtxSettingsPtAdvancedAPI_1", "OmniRtxPostColorGradingAPI_1", "OmniRtxPostChromaticAberrationAPI_1", "OmniRtxPostBloomPhysicalAPI_1", "OmniRtxPostMatteObjectAPI_1", "OmniRtxPostCompositingAPI_1", "OmniRtxPostDofAPI_1", "OmniRtxPostMotionBlurAPI_1", "OmniRtxPostTvNoiseAPI_1", "OmniRtxPostTonemapIrayReinhardAPI_1", "OmniRtxPostDebugSettingsAPI_1", "OmniRtxDebugSettingsAPI_1"]
202 | hide_in_stage_window = true
203 | no_delete = true
204 | )
205 | {
206 | rel camera =
207 | token omni:rtx:background:source:texture:textureMode = "repeatMirrored"
208 | token omni:rtx:background:source:type = "domeLight"
209 | bool omni:rtx:dlss:frameGeneration = 0
210 | string omni:rtx:material:db:rtSensorNameToIdMap = "DefaultMaterial:0;AsphaltStandardMaterial:1;AsphaltWeatheredMaterial:2;VegetationGrassMaterial:3;WaterStandardMaterial:4;GlassStandardMaterial:5;FiberGlassMaterial:6;MetalAlloyMaterial:7;MetalAluminumMaterial:8;MetalAluminumOxidizedMaterial:9;PlasticStandardMaterial:10;RetroMarkingsMaterial:11;RetroSignMaterial:12;RubberStandardMaterial:13;SoilClayMaterial:14;ConcreteRoughMaterial:15;ConcreteSmoothMaterial:16;OakTreeBarkMaterial:17;FabricStandardMaterial:18;PlexiGlassStandardMaterial:19;MetalSilverMaterial:20"
211 | bool omni:rtx:material:db:syncLoads = 1
212 | bool omni:rtx:post:registeredCompositing:invertColorCorrection = 1
213 | bool omni:rtx:post:registeredCompositing:invertToneMap = 1
214 | bool omni:rtx:pt:lightcache:cached:dontResolveConflicts = 1
215 | int omni:rtx:pt:maxSamplesPerLaunch = 2073600
216 | int omni:rtx:pt:mgpu:maxPixelsPerRegionExponent = 12
217 | color3f omni:rtx:rt:ambientLight:color = (0.1, 0.1, 0.1)
218 | bool omni:rtx:rt:demoire = 0
219 | bool omni:rtx:rt:lightcache:spatialCache:dontResolveConflicts = 1
220 | bool omni:rtx:scene:hydra:materialSyncLoads = 1
221 | bool omni:rtx:scene:hydra:mdlMaterialWarmup = 1
222 | uint omni:rtx:viewTile:limit = 4294967295
223 | rel orderedVars =
224 | custom bool overrideClipRange = 0
225 | uniform int2 resolution = (1280, 720)
226 | }
227 | }
228 | }
229 |
230 | def RenderSettings "OmniverseGlobalRenderSettings" (
231 | prepend apiSchemas = ["OmniRtxSettingsGlobalRtAdvancedAPI_1", "OmniRtxSettingsGlobalPtAdvancedAPI_1"]
232 | no_delete = true
233 | )
234 | {
235 | rel products =
236 | }
237 |
238 | def "Vars"
239 | {
240 | def RenderVar "LdrColor" (
241 | hide_in_stage_window = true
242 | no_delete = true
243 | )
244 | {
245 | uniform string sourceName = "LdrColor"
246 | }
247 | }
248 | }
249 |
250 |
--------------------------------------------------------------------------------