OptiTrack e2e: NatNet emulator + real-robot PX4 external-vision fusion#373
Closed
JohnYanxinLiu wants to merge 8 commits into
Closed
OptiTrack e2e: NatNet emulator + real-robot PX4 external-vision fusion#373JohnYanxinLiu wants to merge 8 commits into
JohnYanxinLiu wants to merge 8 commits into
Conversation
… launch scripts Extracted from the optitrack_emulation branch (#367) onto the reworked test-infra base. Adds the sim-side NatNet server emulator so the natnet_ros2 client can be exercised end-to-end in Isaac Sim without OptiTrack hardware: - simulation/isaac-sim/extensions/optitrack.natnet.emulator/** — NatNet server emulation, USD bindings, UI extension, and its co-located unit tests. - launch_scripts: example_one/multi_px4_pegasus_natnet_launch_script.py (spawn the emulator alongside PX4), and example_one_px4_pegasus_launch_script.py gains the shared GPS world-origin setup (gps_utils) so sim, GCS, and the robot agree on the world datum. - docs/simulation/isaac_sim/natnet_emulator.md + optitrack-development skill. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ion baseline Take the natnet_ros2 package from #367 onto the reworked base: the C++ NatNet client (natnet_ros2_node + client adapter + natnet_logic seam), the base mavros_gp_origin and vision_pose_converter nodes, per-robot natnet_config profiles, launch files, and the co-located C++/Python unit tests. natnet_ros2 is already listed in tests/colcon_unit_test_packages.yaml, so the base's YAML-driven collection picks up the updated unit tests directly — no proxy files. Real-robot PX4 external-vision fusion (px4_param_setter, geoid-corrected origin, EV-pose bounds) is layered on next. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Layer the Hummingbird real-robot fusion pipeline onto natnet_ros2 so an OptiTrack-only drone (no GNSS/mag/baro) fuses mocap pose into PX4 EKF2: - mavros_gp_origin_node: publishes a guarded synthetic GPS origin. On real HW, use_geoid_altitude feeds the egm96-5 geoid undulation (N ≈ 54 m at Lisbon) so mavros's ellipsoidal→AMSL conversion cancels and local z == OptiTrack z (fixes the ~36 m = 90 − 54 boot offset; see docs). Auto-skipped in sim. - vision_pose_converter_node: rate-limited mocap → MAVROS vision_pose bridge. - px4_params.yaml: the external-vision EKF2 param set. - natnet_ros2.launch.py wires the bridges when a robot's vision_pose block is on. px4_param_setter reworked into a **checker** (R3): auto_set=false by default — it reads and *flags* FCU params that differ from the desired set instead of writing them; on_mismatch=warn|halt (default warn). Set the params in QGroundControl; the node is the pre-flight safety net. auto_set=true restores the legacy enforce path. Excludes the duplicate vendored NatNet SDK (sensors/natnet_ros2) and deployment override .envs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reconcile #367's optitrack test bits onto the base's YAML-driven collection instead of its old proxy/register_unit_tests pattern: - colcon_unit_test_packages.yaml: add a `sim:` workspace listing optitrack.natnet.emulator. The base's sim glob (simulation/**/<pkg>/test) collects its 15 co-located test files directly — replaces #367's 14 proxy files under tests/sim/optitrack_natnet_emulator/. - tests/requirements.txt: scipy + usd-core (emulator server math + USD bindings). - emulator test/conftest.py: drop the stale "CI uses proxies" note. - perception.launch.xml: natnet include comment points at the natnet_config schema. No isaacsim_natnet added to the default sim matrix (that would re-run the whole system suite under natnet — the dedicated e2e test lands next instead). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two-tier OptiTrack testing instead of re-running the whole system suite under a third `isaacsim_natnet` sim: - tests/integration/natnet/ (from #367): host emulator → natnet_ros2 pose Hz, no GPU. Uses the base's integration tier (robot_autonomy_stack fixture, `integration` mark) as-is. - tests/system/test_optitrack_e2e.py (new, `optitrack` mark): one dedicated Isaac bring-up (example_one_px4_pegasus_natnet_launch_script + LAUNCH_NATNET=true, 1 robot) asserting only the NatNet chain — emulator → natnet_ros2 pose_cov >= 5 Hz, then PX4 local_position alive (EKF2 fusing the vision). Skips when isaac-sim isn't built. Fix a conftest collision: the emulator's test/conftest.py was imported as bare `conftest` under --import-mode=importlib, shadowing tests/conftest.py and breaking `from conftest import` in the system tests. Root conftest now puts each unit-test package's import root on sys.path generically, so the per-package conftest is removed. Register the `optitrack` mark and slot the e2e last in _MODULE_ORDER. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the PX4 external-vision setup guide into docs/ (was a repo-root markdown) and wire it into the mkdocs nav under Perception. Adapt it to the reworked param checker (auto_set default off; check-and-flag, not enforce), and add a "height datum" section explaining the ~36 m local_z offset: AirStack's 90.0 ellipsoidal world datum minus the egm96-5 geoid undulation (N ≈ 54 m at Lisbon) = 36 m; fixed by publishing the geoid-corrected origin altitude so mavros's conversion cancels. Documents why it's invisible in sim and why the shared 90.0 datum must not be changed globally. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
test_streamed_frame_carries_sampled_usd_pose compared the sampled pose to 3-decimal exactness (`round(x,3) == 7.0`), which trips on float32 + USD xform-decompose noise (7.0 sampled back as 7.001) depending on the usd-core version. Use pytest.approx with abs=1e-2 — mm precision is more than enough for the emulator's pose round-trip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Version-increment gate: bump above the test-infra base (alpha.8). Record the OptiTrack emulator + real-robot external-vision fusion + tests in the changelog. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
Split into three smaller, stacked PRs for reviewability (same content, re-partitioned by feature/test-tier):
|
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?
Final phase of the OptiTrack work. Supersedes Johnliu/optitrack emulation #367 — rebuilt cleanly on the reworked test harness instead of rebasing Johnliu/optitrack emulation #367's 44 interleaved commits, and folds in the real-robot PX4 external-vision fixes that lived only on the Hummingbird repo.
Stacked on Test infra rework: YAML-driven unit-test collection + integration tier #372 (
johnliu/test-infra-rework) — base this PR onjohnliu/test-infra-reworkso the diff shows only the 8 OptiTrack commits. Retarget todevelopafter l4t deployment fixes: make the Jetson profile build + boot on real hardware #371 + Test infra rework: YAML-driven unit-test collection + integration tier #372 merge.Additional description if not fully described in the GitHub issue
Two capabilities, plus the test wiring:
1. Sim NatNet emulator (end-to-end without hardware) —
simulation/isaac-sim/extensions/optitrack.natnet.emulator/**streams rigid-body poses as a real NatNet server, sonatnet_ros2can be driven in Isaac Sim. Plus the natnet Pegasus launch scripts.2. Real-robot PX4 external-vision fusion — extends
natnet_ros2:mavros_gp_originpublishes a guarded synthetic GPS origin. On real hardwareuse_geoid_altitudefeeds the egm96-5 geoid undulation so mavros's ellipsoidal→AMSL conversion cancels andlocal_position.z == OptiTrack z— fixing the ~36 m boot offset (90 m ellipsoidal world datum − ~54 m geoid = 36 m; invisible in sim because the geoid path is skipped underuse_sim_time).vision_pose_converterbridges mocap pose → MAVROSvision_pose.px4_param_setteris a checker, not an enforcer:auto_setoff by default (read + flag, never write),on_mismatch=warn(default) |halt. Set the EKF2 params in QGC; the node is the pre-flight safety net.How did you implement it?
sim:entry intests/colcon_unit_test_packages.yaml(the base'ssimulation/**/<pkg>/testglob) — replacing Johnliu/optitrack emulation #367's 14 proxy files +register_unit_tests.isaacsim_natnetin the default sim matrix. That would re-run the whole liveliness/sensors/flight suite under NatNet for two assertions. Instead: the cheap host-sidetests/integration/natnet/(emulator →natnet_ros2Hz, no GPU) + one dedicatedtests/system/test_optitrack_e2e.py(optitrackmark, single NatNet Isaac bring-up).test/conftest.pycollided with the rootconftestunder--import-mode=importlib; the root conftest now puts each unit-test package's import root onsys.pathgenerically, so the per-package conftest is removed.sensors/natnet_ros2, ~7k lines of proprietary headers) and deployment-specific override.envs.How do you run and use it?
Testing with PyTest
unit): emulator server/protocol +natnet_ros2co-located tests — 153 pass locally, 0 failures. Loosened one emulator pose assertion topytest.approx(abs=1e-2)(float32/USD-decompose noise).integration):tests/integration/natnet/— host emulator →natnet_ros2pose Hz, no GPU.optitrack, new mark):tests/system/test_optitrack_e2e.py— one Isaac bring-up asserting emulator →natnet_ros2pose_cov ≥ 5 Hz then PX4local_positionalive. Skips when isaac-sim isn't built.-m unitclean; the sim e2e passes on a GPU runner (single-robot; multi-robot flight variants are hardware-bound).Documentation
docs/robot/px4_external_vision.md(the setup guide + the height-datum explainer + the param-checker flags).natnet_ros2/README.mdcovers the client.Versioning
.envVERSION→0.19.0-alpha.9(above Test infra rework: YAML-driven unit-test collection + integration tier #372's alpha.8) + CHANGELOG.🤖 Generated with Claude Code