Johnliu/optitrack emulation#367
Open
JohnYanxinLiu wants to merge 40 commits into
Open
Conversation
…handlers Refactor the emulator server around a pre-packed MODELDEF wire cache and add the NAT_REQUEST_MODELDEF and NAT_KEEPALIVE handlers so libNatNet 4.4 clients complete the unicast handshake. Mock a real Motive server (server name "Motive") and move hardcoded Drone reference constants into a new defaults.py so scene semantics stay out of the wire layer. Drop the vendored NatNet SDK README that should not live in-tree. Co-authored-by: Cursor <cursoragent@cursor.com>
…defaults Cover the MODELDEF/frame serializers, the unicast handshake protocol, and the defaults/server catalog. A package-level test/conftest.py puts the extension root on sys.path and registers the `unit` marker so `pytest test/` runs the suite directly without per-file boilerplate. Co-authored-by: Cursor <cursoragent@cursor.com>
…ture Add repo_path() and reexport_unit_tests() to tests/conftest.py so the thin proxy files re-export co-located package tests without hardcoded Path(__file__).parents[N] walks or per-file sys.path boilerplate; rewrite the robot and sim proxies to use them. Register the `integration` marker and the robot_autonomy_stack bring-up fixture (gated behind --run-integration) for the new integration tier. Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce tests/integration/ as a new tier between unit and system: real components wired together (robot autonomy container + a host-side component) with no sim or GPU. Move the NatNet emulator <-> natnet_ros2 test here as the first resident (marks: integration, natnet), driven by the shared robot_autonomy_stack fixture, and remove the old tests/sim/motive_emulator location. Co-authored-by: Cursor <cursoragent@cursor.com>
Update AGENTS.md, tests/README.md, and the add-unit-tests / optitrack-development skills to describe the four test tiers (unit, integration, system), the repo_path/reexport_unit_tests proxy pattern, the --run-integration flag, and the new tests/integration/natnet location. Co-authored-by: Cursor <cursoragent@cursor.com>
NatNet emulator installation is baked into the isaac-sim image, bind-mounted for live edits, and enabled in Kit config. Co-authored-by: Cursor <cursoragent@cursor.com>
Remap vision_pose_converter to the interface/mavros namespace, install mavros_extras in the robot image, and add layered PX4_PARAM_PROFILE env files so Isaac SITL can fuse NatNet external vision (EKF2_EV_CTRL, no GPS, indoor mag disabled). Document the vision profile and provide an overrides bundle for NatNet + vision sim bring-up. Co-authored-by: Cursor <cursoragent@cursor.com>
PX4 with EKF2_GPS_CTRL=0 has valid local vision fusion but no global position, so AUTO.LOITER preflight fails until an origin is set. Add mavros_gp_origin_node to publish a one-shot set_gp_origin after MAVROS connects, skipping when a real origin already exists. Launched alongside vision_pose_converter when publish_to_mavros is enabled. Co-authored-by: Cursor <cursoragent@cursor.com>
…vertised tolerances
9a6a546 to
d6c6ef4
Compare
d6c6ef4 to
83b5929
Compare
926b715 to
9ce2bfb
Compare
23428fb to
dfe7f17
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an OptiTrack/NatNet motion-capture “loop” for AirStack—covering a Python NatNet server emulator (incl. Isaac Sim wrapper), updated natnet_ros2 client bringup/config for multi-robot profiles + MAVROS bridging, and expanded pytest coverage (unit, new integration tier, and system-test sentinels) to validate end-to-end external-vision operation.
Changes:
- Introduce an Isaac Sim extension implementing a NatNet 4.x unicast server emulator + USD-driven configuration and pose sampling.
- Update
natnet_ros2to support per-robot multi-body profiles, configurable vision-pose topic wiring, and a one-shot MAVROS GPS origin publisher for no-GNSS arming/modes. - Extend the pytest harness with an
integrationtier, NatNet liveliness sentinel checks, and improved system-test robustness for vision/NatNet profiles.
Reviewed changes
Copilot reviewed 117 out of 117 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/system/test_takeoff_hover_land.py | Adds vision-profile settle time, arm-retry behavior, and vision-aware timeouts for takeoff/land system tests. |
| tests/system/test_liveliness.py | Adds NatNet pose topic sentinel (gated on LAUNCH_NATNET=true) to catch broken mocap streaming in-system. |
| tests/system/test_build_packages.py | Switches to pytest.fail(...) for clearer failure output in build/package system tests. |
| tests/system/test_build_docker.py | Switches to pytest.fail(...) for clearer failure output in docker build system tests. |
| tests/sim/README.md | Documents new NatNet emulator unit-test proxy location and usd-core-guarded USD tests. |
| tests/sim/optitrack_natnet_emulator/test_unicast_protocol.py | Proxy registering emulator unicast-protocol unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_target_resolution.py | Proxy registering emulator target-resolution unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_server_lifecycle.py | Proxy registering emulator server-lifecycle unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_server_from_config.py | Proxy registering emulator server-from-config unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_serializers.py | Proxy registering emulator serializer unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_scene_setup.py | Proxy registering emulator scene-setup helper unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_pose_streaming.py | Proxy registering emulator pose-streaming unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_pose_sampling.py | Proxy registering emulator pose-sampling unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_interface_config.py | Proxy registering emulator config-model unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_interface_authoring.py | Proxy registering emulator USD authoring unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_frames.py | Proxy registering emulator pose→frame builder unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_discovery.py | Proxy registering emulator interface discovery/formatting unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_defaults_and_catalog.py | Proxy registering emulator defaults + server-catalog unit tests for centralized pytest discovery. |
| tests/sim/optitrack_natnet_emulator/test_catalog.py | Proxy registering emulator catalog-builder unit tests for centralized pytest discovery. |
| tests/sim/motive_emulator/README.md | Removes obsolete placeholder README in favor of the new emulator + integration tier. |
| tests/sensor_probes.py | Uses is_isaac_sim() helper for sim checks (includes isaacsim_natnet variant). |
| tests/robot/sensors/lidar_point_cloud_filter/test_validation_core.py | Migrates proxy to register_unit_tests() helper. |
| tests/robot/README.md | Updates docs to describe register_unit_tests() proxy pattern (vs importlib re-export). |
| tests/robot/perception/natnet_ros2/test_natnet_ros2.py | Migrates natnet_ros2 proxy to register_unit_tests() helper. |
| tests/requirements.txt | Adds SciPy and USD (usd-core) to support emulator math + optional USD-based tests. |
| tests/README.md | Documents the new integration tier and adds isaacsim_natnet to default sim targets. |
| tests/pytest.ini | Registers new integration pytest marker. |
| tests/integration/README.md | Introduces integration-tier structure, purpose, fixture usage, and execution guidance. |
| tests/integration/natnet/README.md | Documents host-emulator ↔ robot-container NatNet integration scenario and expectations. |
| tests/docker/docker-compose.yaml | Plumbs NatNet-related env vars into the test runner container. |
| tests/colcon_unit_test_packages.yaml | Minor cleanup of comments for colcon unit-test package list. |
| simulation/isaac-sim/launch_scripts/example_one_px4_pegasus_launch_script.py | Ensures GPS home/origin is written before PX4 SITL starts to align with GCS datum. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_target_resolution.py | Adds USD-stage target resolution unit tests (guarded by pxr). |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_server_lifecycle.py | Adds server manager lifecycle tests using a mocked server factory. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_server_from_config.py | Adds tests validating MODELDEF handshake and restart behavior using real sockets. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_server_catalog.py | Adds tests for MODELDEF payload cache behavior and catalog packing. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_scene_setup.py | Adds hermetic tests for launch-script helper config construction and validation. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_pose_streaming.py | Adds loopback tests verifying sampled USD pose makes it into NAT_FRAMEOFDATA. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_interface_config.py | Adds unit tests for the pure-Python interface config model and validation. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_interface_authoring.py | Adds USD author/read round-trip tests for interface prim attributes. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_frames.py | Adds unit tests for pose→frame conversion, flags, and packing expectations. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_discovery.py | Adds unit tests for human-readable interface formatting/inspection helper. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_defaults.py | Adds tests ensuring default tracked-body bindings match expected natnet_ros2 config. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/test_catalog.py | Adds catalog packing limits/ordering tests and duplicate-target detection tests. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/natnet_test_helpers.py | Adds shared UDP test helpers (ephemeral ports, minimal client, server context manager). |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/conftest.py | Adds local test-path setup + marker registration for direct extension test runs. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/setup.py | Adds setuptools metadata to allow pip editable install inside Isaac Sim image. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/schema/schema.usda | Adds codeless USD schema describing interface prim attributes for Kit UI friendliness. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/README.md | Documents emulator architecture, configuration, protocol notes, and test tiers. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/server/natnet_unicast_server.py | Implements NatNet unicast server command handling + data flush behavior. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/server/natnet_server_types.py | Adds ctypes wire structs and packing logic for serverinfo/packet headers. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/server/natnet_model_types.py | Adds MODELDEF-related ctypes structs and packing routines. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/server/natnet_common.py | Defines protocol/model size limits used by the emulator. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/server/init.py | Exposes server classes/types as a small import surface. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/isaac/usd_bindings.py | Adds USD author/read/find helpers for the NatNet interface prim. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/isaac/scene_setup.py | Adds launch-script helpers to author interface prims and start server managers. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/isaac/frames.py | Implements pose→NatNet frame conversion, axis emulation, and optional pose noise. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/isaac/catalog.py | Builds MODELDEF catalogs from config and detects duplicate target prims. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/isaac/init.py | Exposes Isaac integration API surface for scripts/UI. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/defaults.py | Defines default tracked-body bindings used by tests/examples. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/emulator/init.py | Exposes top-level emulator API (server + defaults + catalog helper). |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/natnet/init.py | Adds namespace package init for NatNet modules. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/optitrack/init.py | Adds namespace package init for OptiTrack-related modules. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/config/extension.toml | Registers Kit extension modules and dependencies. |
| simulation/isaac-sim/extensions/optitrack.natnet.emulator/.gitignore | Ignores local SDK/build artifacts and Python cache files. |
| simulation/isaac-sim/docker/user_TEMPLATE.config.json | Enables the NatNet emulator extension by default in Isaac Sim user config template. |
| simulation/isaac-sim/docker/sitl-files/px4-vision.env | Adds PX4 SITL parameter bundle for external-vision (vision_pose → EKF2) fusion. |
| simulation/isaac-sim/docker/sitl-files/default.env | Adds default (no override) SITL bundle placeholder for compose selection. |
| simulation/isaac-sim/docker/Dockerfile.isaac-ros | Installs PX4 deps directly and adds editable install of NatNet emulator extension. |
| simulation/isaac-sim/docker/docker-compose.yaml | Loads SITL param bundles and mounts/enables the NatNet emulator extension. |
| robot/ros_ws/src/perception/perception_bringup/launch/perception.launch.xml | Updates NatNet-related bringup comment to reflect new multi-robot config schema. |
| robot/ros_ws/src/perception/natnet_ros2/test/test_natnet_ros2.py | Expands unit tests for topic wiring + launch helper flattening (ROS deps stubbed). |
| robot/ros_ws/src/perception/natnet_ros2/test/test_natnet_logic.cpp | Adds tests for namespaced topic handling and configured-body filtering. |
| robot/ros_ws/src/perception/natnet_ros2/src/vision_pose_converter_node.py | Adds topic-parameterized wiring for flexible vision_pose bridging. |
| robot/ros_ws/src/perception/natnet_ros2/src/mavros_gp_origin_node.py | Adds one-shot synthetic GPS origin publisher guarded against overriding existing origin. |
| robot/ros_ws/src/perception/natnet_ros2/package.xml | Adds geographic_msgs dependency for GPS origin publication message type. |
| robot/ros_ws/src/perception/natnet_ros2/launch/vision_pose_converter.launch.xml | Switches from remaps to explicit topic params supplied by natnet profile config. |
| robot/ros_ws/src/perception/natnet_ros2/launch/mavros_gp_origin.launch.xml | Adds launch file wiring the GPS origin node into MAVROS topic namespace. |
| robot/ros_ws/src/perception/natnet_ros2/include/natnet_ros2/natnet_logic.hpp | Adds helpers for namespacing per-body topic overrides and multi-body id filtering. |
| robot/ros_ws/src/perception/natnet_ros2/config/natnet_config.yaml | Replaces single-body params with multi-robot, multi-body profile schema + vision_pose block. |
| robot/ros_ws/src/perception/natnet_ros2/config/mavros_gp_origin.yaml | Adds Lisbon-defaulted GPS origin config matching GCS/sim datum. |
| robot/ros_ws/src/perception/natnet_ros2/CMakeLists.txt | Installs new Python node and refines comments around install behavior. |
| robot/docker/Dockerfile.robot | Makes ROS LD_LIBRARY_PATH arch suffix configurable via build arg; adds mavros extras. |
| robot/docker/docker-compose.yaml | Passes TARGET_ARCH=aarch64 at build time for VOXL and L4T profiles. |
| overrides/isaac-natnet-vision.env | Adds convenience env-file override for NatNet + PX4 external-vision profile runs. |
| mkdocs.yml | Adds navigation entry for NatNet emulator documentation. |
| docs/simulation/isaac_sim/spawning_drones.md | Documents new NatNet-enabled Pegasus launch scripts. |
| docs/simulation/isaac_sim/pegasus_scene_setup.md | Documents SITL_PARAM_PROFILE bundles and external-vision setup. |
| docs/simulation/isaac_sim/docker.md | Documents SITL env bundles and related compose wiring. |
| docs/robot/docker/index.md | Documents TARGET_ARCH build-arg semantics for ROS library path suffixing. |
| docs/development/intermediate/testing/unit_testing.md | Updates unit-test proxy explanation to register_unit_tests() and references emulator. |
| docs/development/intermediate/testing/index.md | Updates unit-test docs to reflect register_unit_tests() proxy mechanism. |
| docs/development/intermediate/docker-build-profiles.md | Documents TARGET_ARCH build arg and provides examples. |
| airstack.sh | Updates default --sim help text to include isaacsim_natnet. |
| AGENTS.md | Adds optitrack-development skill reference and updates testing tier descriptions. |
| .github/workflows/system-tests.yml | Adds isaacsim_natnet to workflow defaults and ensures isaac profile selection matches both isaac targets. |
| .env | Bumps version to 0.19.0-alpha.4. |
| .agents/skills/run-system-tests/SKILL.md | Updates docs for isaacsim_natnet default sim targets and proxy pattern. |
| .agents/skills/docker-build-profiles/SKILL.md | Updates docs to emphasize TARGET_ARCH as build arg and its effect on LD_LIBRARY_PATH. |
| .agents/skills/add-unit-tests/SKILL.md | Updates proxy guidance to use register_unit_tests() and documents its contract. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What features did you add and/or bugs did you address?
Which GitHub issue does this address?
N/A
Additional description if not fully described in the GitHub issue
Optitrack (MoCAP) NatNet protocol implementation:
robot client (natnet_ros2)
Isaac Sim Motive emulator
protocol handshake
and libNatNet 4.4 unicast mocked server behavior.
Please add videos and images to demonstrate the feature. Please upload videos to somewhere persistent (e.g. YouTube or Vimeo) for archival purposes.
N/A
How did you implement it?
How do you run and use it?
The recommended way to exercise the full feature set — multi-drone NatNet vision-pose — also covers the single-drone case.
Bring up the full stack
This starts 3 robot containers and Isaac Sim running
example_multi_px4_pegasus_natnet_launch_script.pywithLAUNCH_NATNET=trueandSITL_PARAM_PROFILE=px4-vision. Wait until Isaac Sim reaches the Pegasus "Play" state and the robot containers report ROS 2 nodes live.Verify NatNet topics are publishing
For each drone, confirm the OptiTrack rigid-body pose is being received and published:
Expected: all topics publishing at ~120 Hz (NatNet stream rate).
Step 3 — Verify local odometry is updating
Check that the
x,y,zvalues in the pose field match the spawn positions of the drones in Isaac Sim (drones spawn spaced along the X axis at the same interval). Confirm values are updating as the simulation runs.Step 4 — Takeoff all drones via Foxglove
Open Foxglove (GCS) and connect to
ws://localhost:8765. For each robot:ros2 topic echo /robot_N/odometry --oncereportsz ≈ 10.0.Step 5 — Run the random walk navigation planner
With all drones hovering, trigger the navigation task using the random walk (exploration) planner from the Foxglove GCS panel. Verify that:
status: navigatingfeedback appears in the GCS for each robot.Teardown
Testing with PyTest
What pytests were added?
robot/ros_ws/src/perception/natnet_ros2/test/test_natnet_logic.cpp— C++ unit tests for thenatnet_logic.hppstate machine (body fan-out, tracking-valid gating, covariance injection, multi-body profiles).robot/ros_ws/src/perception/natnet_ros2/test/test_natnet_ros2.py— Python unit tests forVisionPoseConverterNode(quaternion canonicalisation, configurable-topic wiring) andnatnet_ros2.launch.pyprofile-flattening helpers (env expansion, body array construction, namespacing).simulation/isaac-sim/extensions/optitrack.natnet.emulator/test/— 17 unit tests covering the emulator serializers, unicast handshake protocol, MODELDEF catalog, pose sampling, scene setup, and server lifecycle.tests/integration/natnet/test_natnet_integration.py— 3 integration tests: (1) rawNatNetUnicastServerhand-built single-body frames →natnet_ros2_nodein the robot container; (2)NatNetServerManagersampling an in-memory USD stage; (3) multi-body profile (drone + target) exercising per-body topic overrides and pose/pose_cov toggles. Metric: all body topics must publish at ≥ 5 Hz for 12 s.Exact commands:
CI system tests (GPU runner) — trigger via PR comment:
PASSED; C++ tests reported bycolcon test, Python tests by pytest.test_natnet_pose_hzvariants eachPASSED; check the per-test Hz measurement logged to stdout (should be ≥ 5 Hz).liveliness: all containers healthy,/clockactive, sentinel ROS 2 nodes present for allNUM_ROBOTS.sensors: camera, LiDAR, and (whenLAUNCH_NATNET=true)vision_posetopics all stream at expected Hz; checkmetrics.jsonHz values and the CI PR comment diff vs baseline.takeoff_hover_land: drone completes all 4 phases (PX4-ready → takeoff → hover → land) without coordinate errors; pass/fail visible in the CI PR comment.Documentation
natnet_ros2README,docker-build-profiles.md,unit_testing.md, OSMO tutorial, andtests/integration/docs to navigation.robot/ros_ws/src/perception/natnet_ros2/README.mdfor NatNet setup (sim and real hardware),docs/tutorials/airstack_on_osmo.mdfor cloud-GPU dev, anddocs/development/intermediate/testing/unit_testing.mdfor the test proxy pattern; agent skills (optitrack-development,add-unit-tests) are updated.Versioning
.envfile according to semantic versioning?Yes