Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,10 @@ def compute(db: og.Database) -> bool:
True if the node computed successfully.
"""
if db.per_instance_state.initialized is False:
db.per_instance_state.initialized = True
stage = omni.usd.get_context().get_stage()
if stage is None:
carb.log_warn("USD stage is not available yet, retrying on next call")
return False
with Usd.EditContext(stage, stage.GetSessionLayer()):
render_product_path = db.inputs.renderProductPath
if not render_product_path:
Expand Down Expand Up @@ -146,6 +148,8 @@ def compute(db: og.Database) -> bool:
print(traceback.format_exc())
return False

db.per_instance_state.initialized = True

db.outputs.execOut = og.ExecutionAttributeState.ENABLED
return True

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Retry-state tests for HSBCameraHelper."""

import importlib.util
from pathlib import Path
from unittest.mock import MagicMock, patch

import omni.kit.test
from pxr import Usd

MODULE_PATH = Path(__file__).resolve().parents[1] / "nodes" / "OgnHSBCameraHelper.py"
SPEC = importlib.util.spec_from_file_location("_hsb_camera_helper_validation", MODULE_PATH)
MODULE = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(MODULE)
OgnHSBCameraHelper = MODULE.OgnHSBCameraHelper


class TestHSBCameraHelperValidation(omni.kit.test.AsyncTestCase):
"""Verify transient setup failures leave the helper retryable."""

@staticmethod
def _db() -> MagicMock:
db = MagicMock()
db.per_instance_state.initialized = False
db.inputs.renderProductPath = "/Render/Product"
db.inputs.resetSimulationTimeOnStop = True
db.inputs.useSystemTime = False
db.inputs.type = "vb1940_csi_linux"
db.inputs.ipAddress = "127.0.0.1"
db.inputs.dataPlaneType = 0
db.inputs.dataPlaneId = 0
db.inputs.sensorId = 0
return db

@patch.object(MODULE.omni.usd, "get_context")
async def test_missing_stage_leaves_state_uninitialized(self, mock_get_context: MagicMock) -> None:
db = self._db()
mock_get_context.return_value.get_stage.return_value = None

self.assertFalse(OgnHSBCameraHelper.compute(db))
self.assertFalse(db.per_instance_state.initialized)

@patch.object(MODULE.rep.writers, "get", side_effect=RuntimeError("temporary writer failure"))
@patch.object(MODULE.omni.syntheticdata.SyntheticData, "convert_sensor_type_to_rendervar", return_value="LdrColor")
@patch.object(MODULE.omni.usd, "get_context")
async def test_writer_failure_leaves_state_uninitialized(
self, mock_get_context: MagicMock, _mock_convert: MagicMock, _mock_writer_get: MagicMock
) -> None:
db = self._db()
stage = Usd.Stage.CreateInMemory()
stage.DefinePrim("/Render/Product")
mock_get_context.return_value.get_stage.return_value = stage

self.assertFalse(OgnHSBCameraHelper.compute(db))
self.assertFalse(db.per_instance_state.initialized)
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,20 @@ def compute(db: og.Database) -> bool:
True if the node computes successfully, otherwise false.
"""
if db.per_instance_state.initialized is False:
db.per_instance_state.initialized = True
stage = omni.usd.get_context().get_stage()
if stage is None:
carb.log_warn("USD stage is not available yet, retrying on next call")
return False
with Usd.EditContext(stage, stage.GetSessionLayer()):
render_product_path = db.inputs.renderProductPath
if not render_product_path:
carb.log_warn("Render product not valid")
db.per_instance_state.initialized = False
return False

if stage.GetPrimAtPath(render_product_path) is None:
render_product_prim = stage.GetPrimAtPath(render_product_path)
if not render_product_prim or not render_product_prim.IsValid():
carb.log_warn("Render product not created yet, retrying on next call")
db.per_instance_state.initialized = False
return False
db.per_instance_state.resetSimulationTimeOnStop = db.inputs.resetSimulationTimeOnStop

Expand All @@ -120,20 +122,22 @@ def compute(db: og.Database) -> bool:
sd.SensorType.Rgb.name
)
writer = rep.writers.get(db.per_instance_state.rv + f"UCX{time_type}PublishImage")
if writer is None:
carb.log_error("UCX camera image writer was not found")
return False
writer.initialize(
port=db.inputs.port,
tag=db.inputs.tag,
sendCudaBuffer=bool(db.inputs.sendCudaBuffer),
)

if writer is not None:
db.per_instance_state.append_writer(writer)

db.per_instance_state.append_writer(writer)
db.per_instance_state.attach_writers(render_product_path)
except Exception:
print(traceback.format_exc())
carb.log_error(f"UCXCameraHelper: Failed to setup writer: {traceback.format_exc()}")
return False

db.per_instance_state.initialized = True

db.outputs.execOut = og.ExecutionAttributeState.ENABLED
return True

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Retry-state tests for UCXCameraHelper."""

import importlib.util
from pathlib import Path
from unittest.mock import MagicMock, patch

import omni.kit.test
from pxr import Usd

MODULE_PATH = Path(__file__).resolve().parents[1] / "nodes" / "OgnUCXCameraHelper.py"
SPEC = importlib.util.spec_from_file_location("_ucx_camera_helper_validation", MODULE_PATH)
MODULE = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(MODULE)
OgnUCXCameraHelper = MODULE.OgnUCXCameraHelper


class TestUCXCameraHelperValidation(omni.kit.test.AsyncTestCase):
"""Verify transient setup failures leave the helper retryable."""

@staticmethod
def _db() -> MagicMock:
db = MagicMock()
db.per_instance_state.initialized = False
db.inputs.renderProductPath = "/Render/Product"
db.inputs.resetSimulationTimeOnStop = True
db.inputs.frameSkipCount = 0
db.inputs.useSystemTime = False
db.inputs.port = 13337
db.inputs.tag = 10
db.inputs.sendCudaBuffer = True
return db

@patch.object(MODULE.omni.usd, "get_context")
async def test_missing_stage_leaves_state_uninitialized(self, mock_get_context: MagicMock) -> None:
db = self._db()
mock_get_context.return_value.get_stage.return_value = None

self.assertFalse(OgnUCXCameraHelper.compute(db))
self.assertFalse(db.per_instance_state.initialized)

@patch.object(MODULE.rep.writers, "get", side_effect=RuntimeError("temporary writer failure"))
@patch.object(MODULE.omni.syntheticdata.SyntheticData, "convert_sensor_type_to_rendervar", return_value="LdrColor")
@patch.object(MODULE.omni.usd, "get_context")
async def test_writer_failure_leaves_state_uninitialized(
self, mock_get_context: MagicMock, _mock_convert: MagicMock, _mock_writer_get: MagicMock
) -> None:
db = self._db()
stage = Usd.Stage.CreateInMemory()
stage.DefinePrim("/Render/Product")
mock_get_context.return_value.get_stage.return_value = stage

self.assertFalse(OgnUCXCameraHelper.compute(db))
self.assertFalse(db.per_instance_state.initialized)