You launch the hand-eye calibration stack, open Rviz, and every TF display turns red: the fixed frame does not exist, and Rviz prints "No transform from [base] to frame [world]". The marker detector is publishing, the robot driver is up, nothing on the robot side is broken. Rviz is anchored to a frame that nobody in your stack publishes. This page shows you how to confirm which frames your tf tree really contains, which frame to anchor to while you work, how to publish a proper world frame with one command, and why none of it changes the calibration result. The same five-minute diagnosis applies to ROS 1 and ROS 2 cells.
Why does Rviz say "No transform from [base] to frame [world]"?
Rviz anchors every TF-based display to the single frame named under Global Options → Fixed Frame and draws a display only when tf holds a connected path to that anchor. Nothing in a marker hand-eye stack publishes a frame called world, so every TF display reports the error.
Read the message left to right. The bracketed frame on the left, base, is one tf knows: your robot driver publishes it. The frame on the right, world, is the anchor Rviz was told to use, and tf has no path to it because no node creates it. Tutorials and saved Rviz configs often assume something else provides that root: a SLAM stack publishes map, a static broadcaster publishes world. A standalone marker calibration stack includes neither, so the inherited default is missing from the first launch.
If your cell also runs SLAM, the same failure appears around the map frame and the fix pattern is identical; resolving a missing map frame in RViz for ROS 2 SLAM walks that variant. In both cases the camera driver and the marker node are innocent. The anchor is display configuration, nothing more.
Which frame should you pick as the fixed frame?
Set Fixed Frame to a frame that already exists: camera_link while you verify the marker detection, base_link once you want robot and marker in one view. The dropdown under Global Options lists only frames tf has heard of, so pick from the list rather than typing a tutorial's name.
A stack like this one publishes, on the camera side, camera_link as the tracking base, camera_rgb_optical_frame for the optical frame, and camera_marker, which the detector republishes continuously as a tf frame. On the robot side you get base_link and the effector frame, wrist_3_link in the example launch. Until the calibration result is published, these form two disconnected components: a TF display anchored at base_link lists the camera frames with a no-path warning. That warning is expected at this stage and is not a fault.
How do you list the frames your tf tree actually contains?
Run the tree dump: rosrun tf2_tools view_frames.py on ROS 1, ros2 run tf2_tools view_frames on ROS 2; rqt_tf_tree shows the same tree live. Every frame in that output is a legal fixed frame.
The dump for this stack shows the two components and their rates: camera_marker updates at the camera rate, 30 Hz class for the depth cameras used in these rigs, while the robot frames follow the driver's joint-state rate. If a frame you expected is absent, the publisher is the suspect, and the fix for a missing camera frame in the tf tree starts there. If camera_marker specifically never appears, run the hand-eye calibration target frame checks before touching Rviz again.
How do you publish a real world frame?
Publish a static identity transform whose parent is world and whose child is base_link, and world becomes the root of the tree. The six zeros mean no offset, so the display anchor adds nothing to any pose you measure or publish.
# ROS 1: x y z, yaw pitch roll, parent, child, period in ms (100 ms = 10 Hz)
rosrun tf static_transform_publisher 0 0 0 0 0 0 world base_link 100
# ROS 2: same identity transform, latched, no period argument
ros2 run tf2_ros static_transform_publisher 0 0 0 0 0 0 world base_link
Keep world on the parent side so it sits at the root; swap the two names and the error still clears, but your anchor hangs as a leaf under the robot. Identity is honest when world just means "the robot base origin". If your plant defines world at a cell corner or a floor mark, measure that offset once and put the real numbers in place of the zeros. Wrap the command as a node in your master launch, so world exists before anyone opens Rviz.
Why is the /aruco_single/result image not showing?
An image topic needs no tf at all: Rviz draws /aruco_single/result only if you add an Image display subscribed to that exact topic name, so the fixed frame error was never the reason the picture is missing.
- Run
rostopic listand confirm the exact name. The example launches the detector as aruco_single, so the result lands on /aruco_single/result. - Run
rostopic hz /aruco_single/result. A steady rate near the camera frequency means the stream is alive and only the Rviz config is wrong: add an Image display and enter that exact topic. - If the topic is absent, check the node's remaps. The example subscribes /camera_info and a rectified color image; confirm your driver publishes both.
- If images flow but the marker overlay never appears, the detection parameters do not match the scene. The example sets marker_size 0.08, which is an 80 mm marker: measure the black square's edge on your printed target, not the white margin. marker_id 26 must match the printed pattern, and image_is_rectified must match the stream you subscribe to.
Does a wrong fixed frame affect the hand-eye calibration result?
No. Rviz is a viewer only; the calibration package, easy_handeye in this stack, samples tf directly between tracking_base_frame and robot_base_frame, so the display anchor never enters the result math. Fix the display anyway, because judging sample poses without a common view is how weak calibrations pass unnoticed.
What does move the result is the usual trio: the number and spread of robot poses, which the nine-point hand-eye alignment walkthrough explains; detection quality at every pose; and time alignment between joint states and camera images. Once the result is published, the two components merge under one root and world, base_link and camera_link all resolve as anchors. Before you send picks to the robot, check the camera-to-base result the way the eye-to-hand verification guide lays out. More 3D set-up checks live on the 3D vision topic page.
How do you keep the fixed frame valid next session?
Save the working frame into the Rviz config with File → Save Config, start the world publisher from your master launch so it exists before anyone opens Rviz, and rerun the tree dump after every driver or camera change, because frame names follow the driver.
- One owner for world: the master launch publishes it and nothing else does.
- Ship the corrected config with the cell, so the next person does not inherit a world-blind default.
- Dump the tree after any launch change; five seconds of reading beats an hour of guessing.
- Never copy another cell's saved config; it carries that cell's frame names and anchors.
When the depth camera is due for replacement, an industrial 3D sensor takes the same role in the rig, and a structured-light camera such as the MV-DPS200P-02 is the modern stand-in:
- Type
- Stereo / structured light
For cells that steer a laser line across the scene instead of projecting a fixed pattern, the category also lists a laser galvanometer stereo camera, the MV-DLS300P-04:
- Type
- Stereo / structured light
Both sit in the 3D sensors category, and the camera finder filters that list by type and series. To spec the camera, mount and controller as one build, start the configurator at the camera step:
The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.
Questions
Does the fixed frame I choose change the calibration numbers?
No. Rviz only draws the tree; the calibration package samples tf directly between the tracking base frame and the robot base frame, so the display anchor never enters the math. The indirect risk is real, though: a broken viewer hides weak sample poses, so fix the anchor before you judge the calibration.
Why does Rviz open with world or map already set as fixed frame?
Saved configs and tutorials assume a stack that provides a root frame: SLAM publishes map, a static broadcaster publishes world. A bare marker calibration setup ships neither publisher, so nothing fills that inherited default at first launch. The Global Options dropdown is ground truth, because it lists only frames tf currently holds.
Can I rename base_link to world instead of adding a static transform?
Not cleanly. The robot driver publishes the base frame name it was configured with, and the calibration launch references that same name, so a rename has to be edited into every config that touches it. A zero-transform static publisher gives you the same display root in one line and touches nothing else.
Which Rviz displays need a valid fixed frame and which do not?
Everything that draws tf data fails without a path to the anchor: the TF display, RobotModel, PointCloud2, Marker and Map. Image and Camera displays draw the raw topic and never consult tf, so a fixed frame error cannot blank them. If the point cloud renders but the image does not, debug the image topic on its own.
What changes when I swap the depth camera for an industrial 3D sensor?
Frame names change with the driver, not with the method. Run the tree dump first, note the new tracking base and optical frames, update tracking_base_frame in the calibration launch and the Rviz fixed frame, then repeat the full calibration. A result computed against the old camera frame does not transfer to the new one.

