Skip to content
Closed
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
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ endif()
# Build dependencies (OpenXR SDK, etc.)
add_subdirectory(deps)

# Project warning set. Deliberately after add_subdirectory(deps): directory-scope
# compile options are inherited only by subdirectories added *after* this call, so
# third-party trees keep their own flags while everything below (src/, examples/,
# plugins) is held to ours. See cmake/CompilerWarnings.cmake.
include(cmake/CompilerWarnings.cmake)
isaac_teleop_enable_compiler_warnings()

# Enable CTest at top level so tests from subdirectories are discoverable
if(BUILD_TESTING)
# Make sure to call this after `deps` is added so that Catch2 is available
Expand Down
67 changes: 67 additions & 0 deletions cmake/CompilerWarnings.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# ==============================================================================
# Compiler warnings for first-party code
# ==============================================================================
# isaac_teleop_enable_compiler_warnings() applies the project's warning set to the
# CALLING directory scope, which CMake then inherits into every subdirectory added
# after the call. The top-level CMakeLists.txt therefore calls it *after*
# add_subdirectory(deps) so third-party trees (OpenXR SDK, yaml-cpp, pybind11,
# mcap, flatbuffers, Catch2, ...) keep building with their own flags and are never
# held to warning levels we do not control.
#
# Known gap: the OAK plugin (OFF by default) fetches DepthAI, and transitively XLink,
# via FetchContent from inside src/plugins/, so that tree DOES inherit these flags. It
# builds as long as warnings are not errors; with ISAAC_TELEOP_WARNINGS_AS_ERRORS=ON it
# fails with 41 errors in xlink-src on GCC 13 (unused-parameter, stringop-truncation,
# parentheses, ...). Note stringop-truncation is a GCC default rather than part of this
# set, so plain -Werror would break XLink even with ISAAC_TELEOP_ENABLE_WARNINGS=OFF.
# Turning warnings-as-errors on in CI therefore needs OAK excluded, or a -Wno-
# suppression scoped to the fetched tree.
#
# The OGLO and Noitom plugins also fetch from inside src/plugins/, but neither
# contributes third-party translation units — OGLO uses header-only nlohmann/json plus
# the system libdbus, and Noitom links a prebuilt libMocapApi.so — so both build clean
# under -Werror.

option(ISAAC_TELEOP_ENABLE_WARNINGS "Enable the project warning set on first-party C++ targets" ON)
option(ISAAC_TELEOP_WARNINGS_AS_ERRORS "Promote the project warning set to errors (-Werror / /WX)" OFF)

function(isaac_teleop_enable_compiler_warnings)
if(NOT ISAAC_TELEOP_ENABLE_WARNINGS)
message(STATUS "Compiler warnings: disabled (ISAAC_TELEOP_ENABLE_WARNINGS=OFF)")
return()
endif()

set(_gnu_like
-Wall
-Wextra
# Deliberately off: C-style aggregate init of OpenXR/Vulkan structs (which
# zero-fill the tail on purpose) trips this on essentially every call site.
# The native_openxr example already suppressed it for the same reason.
-Wno-missing-field-initializers
# Bug classes worth failing a build over.
-Wnon-virtual-dtor # deleting through a base pointer without a virtual dtor
-Woverloaded-virtual # a derived overload silently hiding a base virtual
-Wimplicit-fallthrough # unannotated switch fallthrough
-Wextra-semi # stray ';' after a member function definition
)

set(_msvc
/W4
/permissive-
)

if(ISAAC_TELEOP_WARNINGS_AS_ERRORS)
list(APPEND _gnu_like -Werror)
list(APPEND _msvc /WX)
endif()

add_compile_options(
"$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:GNU,Clang,AppleClang>>:${_gnu_like}>"
"$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:${_msvc}>"
)

message(STATUS "Compiler warnings: enabled (warnings as errors: ${ISAAC_TELEOP_WARNINGS_AS_ERRORS})")
endfunction()
2 changes: 1 addition & 1 deletion examples/camera_viz/pipeline/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def _record_error(self, exc: BaseException, where: str) -> None:
with self._error_lock:
if self._error is None:
self._error = exc
logger.error("VizRunner %s thread failed: %s", where, exc, exc_info=True)
logger.error("VizRunner %s thread failed: %s", where, exc, exc_info=exc)
self._stop.set()
with self._data_cond:
self._data_cond.notify_all()
Expand Down
4 changes: 2 additions & 2 deletions examples/camera_viz/sources/oakd.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import threading
import time
from dataclasses import dataclass, field
from typing import List, Optional
from typing import ClassVar, List, Optional

import numpy as np

Expand Down Expand Up @@ -120,7 +120,7 @@ class _OakdDevice:
closes it.
"""

_SOCKET_MAP = {
_SOCKET_MAP: ClassVar[dict[str, str]] = {
"RGB": "CAM_A",
"CAM_A": "CAM_A",
"LEFT": "CAM_B",
Expand Down
36 changes: 19 additions & 17 deletions examples/camera_viz/sources/synthetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,27 +234,29 @@ def _produce_loop(self) -> None:
diag_l = (x_grid_l + y_grid) / float(w + h)
diag_r = (x_grid_r + y_grid) / float(w + h)

# Defined once, above the loop: taking phase as a parameter avoids
# rebuilding a closure over it on every generated frame.
def fill(buf, diag, phase):
r = (cp.sin((diag + phase) * 6.2831853) * 127.0 + 128.0).astype(
cp.uint8
)
g = (
cp.sin((diag + phase + 0.3333) * 6.2831853) * 127.0 + 128.0
).astype(cp.uint8)
b = (
cp.sin((diag + phase + 0.6667) * 6.2831853) * 127.0 + 128.0
).astype(cp.uint8)
buf[..., 0] = r
buf[..., 1] = g
buf[..., 2] = b
buf[..., 3] = 255

while not self._stop.is_set():
t = (time.monotonic_ns() - self._t0_ns) * 1e-9
phase = (t * self._hue_speed_hz) % 1.0

def fill(buf, diag):
r = (cp.sin((diag + phase) * 6.2831853) * 127.0 + 128.0).astype(
cp.uint8
)
g = (
cp.sin((diag + phase + 0.3333) * 6.2831853) * 127.0 + 128.0
).astype(cp.uint8)
b = (
cp.sin((diag + phase + 0.6667) * 6.2831853) * 127.0 + 128.0
).astype(cp.uint8)
buf[..., 0] = r
buf[..., 1] = g
buf[..., 2] = b
buf[..., 3] = 255

fill(self._left[self._write_idx], diag_l)
fill(self._right[self._write_idx], diag_r)
fill(self._left[self._write_idx], diag_l, phase)
fill(self._right[self._write_idx], diag_r, phase)
cp.cuda.Stream.null.synchronize()

with self._lock:
Expand Down
2 changes: 1 addition & 1 deletion examples/camera_viz/sources/zed.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ def _hint():

# Pyzed Mats are pitched GPU buffers — one per eye, reused every
# grab() / retrieve_image() pair.
for eye, slot in self._slots.items():
for slot in self._slots.values():
slot.zed_mat = sl.Mat()

self._camera = camera
Expand Down
2 changes: 1 addition & 1 deletion examples/camera_viz/transports/rtp_h264_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def _send_loop(self) -> None:
raise RuntimeError(
f"RtpH264Sender: encode failed {consecutive_encode_failures} "
f"times in a row; surfacing to supervisor for full restart"
)
) from e
continue

for pkt in packets:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import isaacteleop.deviceio as deviceio
import isaacteleop.oxr as oxr
from isaacteleop.cloudxr import CloudXRLauncher
import itertools


# Route MuJoCo warnings to stderr instead of writing MUJOCO_LOG.TXT in CWD.
Expand Down Expand Up @@ -74,7 +75,7 @@ def _mujoco_warning(msg) -> None:
def _finger_chain(root: int, joints: tuple) -> list:
"""[(root,j0), (j0,j1), (j1,j2), ...] — adjacent-pair bone segments."""
chain = [(root, joints[0])]
for a, b in zip(joints[:-1], joints[1:]):
for a, b in itertools.pairwise(joints):
chain.append((a, b))
return chain

Expand Down
17 changes: 7 additions & 10 deletions examples/native_openxr/xdev_list/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <openxr/openxr.h>

#include <XR_MNDX_xdev_space.h>
#include <cstring>
#include <exception>
#include <iostream>
#include <stdexcept>
Expand Down Expand Up @@ -92,13 +93,6 @@ std::vector<XrXDevIdMNDX> enumerate_xdevs(const OpenXRBundle& openxr_bundle, XrX
return xdevIds;
}

/*!
* Print information about available XDevs using XR_MNDX_xdev_space extension
*/
static void print_xdev_info(const OpenXRBundle& openxr_bundle)
{
}

/*!
* XDev List Application - Prints information about available XDevs
*/
Expand Down Expand Up @@ -156,7 +150,10 @@ class XDevListApp : public HeadlessApp
throw std::runtime_error("Failed to get properties for XDev " + std::to_string(xdevId));
}

std::string serial_str = properties.serial ? properties.serial : "";
// serial is a fixed char[256], never a pointer, so a null check would always be true.
// Bound the length so a runtime that fills the array without a terminator cannot
// walk past it.
std::string serial_str(properties.serial, ::strnlen(properties.serial, sizeof(properties.serial)));
if (serial_str == "Head Device (0)" || serial_str == "Head Device (1)")
{
std::cout << "[CREATE HAND] XDev ID=" << xdevId << " Name=\"" << properties.name << "\""
Expand All @@ -168,7 +165,7 @@ class XDevListApp : public HeadlessApp
else
{
std::cout << "[SKIP] XDev ID=" << xdevId << " Name=\"" << properties.name << "\""
<< " Serial=\"" << (properties.serial ? properties.serial : "") << "\"" << std::endl;
<< " Serial=\"" << serial_str << "\"" << std::endl;
}
}

Expand All @@ -179,7 +176,7 @@ class XDevListApp : public HeadlessApp
}
};

int main(int argc, char* argv[])
int main(int /*argc*/, char* argv[])
try
{
XDevListApp app;
Expand Down
4 changes: 2 additions & 2 deletions examples/noitom/noitom_retargeting.py
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,7 @@ def compute_robot_reference_positions(
parsed = _parse_upper_body(frame)
if parsed is None:
return {}
torso, left, right, _pelvis_world = parsed
_torso, left, right, _pelvis_world = parsed
yaw_delta = _resolve_yaw_delta(current_yaw - calib.body_yaw_isaac, settings)
anchor = settings.robot_pelvis_world.astype(np.float64)
positions: dict[int, np.ndarray] = {int(BodyJoint.PELVIS): anchor.copy()}
Expand Down Expand Up @@ -1754,7 +1754,7 @@ def _solve_wrist_target(
yaw_delta = _resolve_yaw_delta(_compute_torso_yaw(torso) - calib_yaw, settings)

if settings.use_posture_based_arms:
shoulder_robot, elbow_robot, wrist_robot = _arm_fk_robot_blended(
_shoulder_robot, elbow_robot, wrist_robot = _arm_fk_robot_blended(
arm, neutral, settings, yaw_delta, is_left
)
forearm = wrist_robot - elbow_robot
Expand Down
2 changes: 1 addition & 1 deletion examples/oxr/cpp/oxr_session_sharing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <memory>
#include <thread>

int main(int argc, char** argv)
int main(int /*argc*/, char** argv)
try
{
std::cout << "OpenXR Session Sharing Example" << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion examples/oxr/cpp/oxr_simple_api_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* Internal lifecycle methods (initialize, update, cleanup) are hidden!
*/

int main(int argc, char** argv)
int main(int /*argc*/, char** argv)
try
{
std::cout << "OpenXR Simple API Demo" << std::endl;
Expand Down
3 changes: 2 additions & 1 deletion examples/retargeting/python/wuji_hand_retargeter_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import signal
import sys
import time
from typing import ClassVar

import numpy as np

Expand Down Expand Up @@ -147,7 +148,7 @@ class _ReplayUnpickler(pickle.Unpickler):
recording may have been produced elsewhere or shared.
"""

_ALLOWED = {
_ALLOWED: ClassVar[set[tuple[str, str]]] = {
("numpy", "ndarray"),
("numpy", "dtype"),
("numpy.core.multiarray", "_reconstruct"), # numpy < 2
Expand Down
2 changes: 1 addition & 1 deletion examples/schemaio/full_body_printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void print_body_pose(const core::FullBodyPoseT& data, size_t sample_count)

} // namespace

int main(int argc, char** argv)
int main(int /*argc*/, char** argv)
try
{
std::cout << "Full Body Printer (XR_BD_body_tracking)" << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion examples/schemaio/pedal_printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void print_pedal_data(const core::Generic3AxisPedalOutputT& data, size_t sample_
std::cout << std::endl;
}

int main(int argc, char** argv)
int main(int /*argc*/, char** argv)
try
{
std::cout << "Pedal Printer (collection: " << COLLECTION_ID << ")" << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion examples/schemaio/pedal_pusher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Generic3AxisPedalPusher
core::SchemaPusher m_pusher;
};

int main(int argc, char** argv)
int main(int /*argc*/, char** argv)
try
{
std::cout << "Schema Pusher (collection: " << COLLECTION_ID << ")" << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion examples/teleop/python/joint_space_device_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def build_pipeline(
head = retargeter.connect(
{JointStateRetargeter.JOINTS: source.output(JointStateSource.JOINTS)}
)
action_labels = _POSE_LABELS + ["gripper_value"]
action_labels = [*_POSE_LABELS, "gripper_value"]
reorderer = TensorReorderer(
input_config={"ee_pose": _POSE_LABELS, "gripper_command": ["gripper_value"]},
output_order=action_labels,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def _positive_int(value: str) -> int:
try:
n = int(value)
except ValueError:
raise argparse.ArgumentTypeError(f"expected a positive integer, got {value!r}")
raise argparse.ArgumentTypeError(
f"expected a positive integer, got {value!r}"
) from None
if n <= 0:
raise argparse.ArgumentTypeError(f"must be a positive integer, got {n}")
return n
Expand All @@ -44,7 +46,7 @@ def _parse_uuid_bytes(uuid_text: str) -> bytes:
raise argparse.ArgumentTypeError(
f"--channel-uuid: invalid UUID {uuid_text!r} (expected canonical form, "
"e.g. 550e8400-e29b-41d4-a716-446655440000)"
)
) from None


def _enqueue_outbound_message(sink, payload: bytes) -> None:
Expand Down
Loading