Detects configured ArUco markers and publishes scene-object poses as ROS 2 detections, TF frames, and optional RViz markers.
Create a workspace virtual environment with ROS packages visible, then install the Python dependencies:
cd ~/ws
uv venv --system-site-packages
uv pip install -r src/aruco_perception/requirements.txtThe YAML launch file is launch/table_setup.launch.yaml:
ros2 launch aruco_perception table_setup.launch.yaml \
publish_markers:=trueIt starts the robot-table and RK-table RealSense cameras, continuously updates each pose while its
configured anchor is visible, and subscribes object detection to every sensor. Cameras without an anchor_frame, such
as an end-effector camera, must provide their image, camera-info, and pose through an external TF
chain.
Launch arguments:
config_path: setup YAML; defaults to the installedconfig/table_setup.yml.max_tf_age: seconds a higher-priority sensor remains preferred after observing a marker, and the maximum age of camera and marker poses used for detection; defaults to0.5.publish_markers: publish labeled pose arrows on/recognized_object_markers; defaults tofalse.robot_table_camera_serial: physical camera assigned to the stable/cameras/robot_table_camerarole; defaults to_336222301119.rk_table_camera_serial: physical camera assigned to the stable/cameras/rk_table_camerarole; defaults to_230322273236.
config/table_setup.yml contains:
sensors: image and camera-info topics for each camera, in priority order. An anchored camera also declaresanchor_frameandcamera_link_frame; its transform is refreshed on/tfwhenever the anchor is visible. A camera withoutanchor_frameuses an existing TF chain. For each object marker, the first sensor with a fresh observation is used; later sensors are fallbacks.model: the SceneX model location. Withpath_type: ros,packageandpathare resolved through the ROS package index and converted to an RDF graph at startup.ref_frame: the common output frame, currentlytable_anchor.frames: frame IRIs, marker IDs and sizes, or fixed offsets from marker frames. Frames with an IRI and nofixedentry are inferred from the RDF model relative toref_frameand published as static TFs. Afixedlist defines ordered marker alternatives for a detected movable frame. Translation offsets are metres;roll,pitch, andyaware radians.objects: maps configured frames to names and IRIs published invision_msgs/Detection3DArray.
/recognized_objects(vision_msgs/Detection3DArray): available object poses intable_anchor./tf_static: RDF-derived fixed frames such asrobot_table_topandrk_table_top./tf: continuously refreshedtable_anchor -> robot_table_camera_linkandrk_anchor -> rk_table_camera_linktransforms while their anchors are visible, plus detectedtable_anchor -> marker_<id>and derivedtable_anchor -> drawer_handletransforms while their observations are fresh./recognized_object_markers(visualization_msgs/MarkerArray): optional green pose arrows with white object-name labels./world_pose_node/debug_image: the latest calibration image with detected marker axes.
The drawer detection and TF are published only while marker 1 or marker 2 is visible and fresh.
Because TF lookups are bidirectional and composed across the tree, no duplicate
camera -> object transform is published. Query an object relative to any connected camera:
ros2 run tf2_ros tf2_echo \
robot_table_camera_color_optical_frame drawer_handle