a2r_mocap receives OptiTrack/Motive NatNet rigid-body frames and exposes one
canonical C++ implementation through C++, Python, and ROS 2. It supports Linux
x86-64 only.
Raw frames use motive_world, meters, and quaternions in (x, y, z, w) order.
No axis conversion, calibration, filtering, or stale-pose replacement occurs.
All rigid bodies from a NatNet update are returned in one Frame; invalid
bodies remain in the C++/Python frame with tracking_valid == false.
Motive streaming must be enabled and reachable through the requested network interfaces. Server and local addresses are always supplied by the caller.
Build and install the core library and diagnostic CLI:
cmake -S core -B build/core -DCMAKE_BUILD_TYPE=Release
cmake --build build/core
cmake --install build/core --prefix install/coreRun the hardware diagnostic:
./install/core/bin/a2r_mocap_print --server <motive-ip> --local <local-ip>python3 -m pip install .import a2r_mocap
config = a2r_mocap.ClientConfig()
config.server_address = "<motive-ip>"
config.local_address = "<local-ip>"
client = a2r_mocap.MocapClient(config)
client.connect()
frame = client.wait_for_next_frame(0.5)None means a normal wait timeout. FrameTiming.receive_age_seconds is a
monotonic receive-age value, not an epoch timestamp.
Use the Docker development environment on hosts without ROS 2:
make -C docker/dev build
make -C docker/dev testRun the ROS node after sourcing the colcon workspace:
ros2 run a2r_mocap_ros a2r_mocap_node --ros-args \
-p server_address:=<motive-ip> -p local_address:=<local-ip> \
-p target_frame:=motive_worldFor another target frame, TF2 must provide target_frame <- motive_world.
The node publishes each selected valid body on mocap/<name>/pose and as TF
with parent target_frame and child <name>. Tracking loss stops publication;
it does not republish the previous pose. Motive names used for ROS must match
[A-Za-z][A-Za-z0-9_]*.
Tested: Ubuntu 22.04 / ROS 2 Humble in docker/dev. Hardware validation with
Motive/NatNet has not yet been performed.
This project intentionally excludes markers, replay/recording, filtering, reconnect/discovery, calibration, transform graphs, MR. POP geometry, and planner/JSON logic. See THIRD_PARTY_NOTICES.md for NatNet terms.
Make sure your Motive has NatNet enabled in the settings, Local Interface set to the correct IP address for streaming, and the Z-Axis as the Up Axis.
TODO: add individual-marker reception as a separate data type without changing the rigid-body API.