System designTroubleshooting

Duplicate hand-eye calibration publishers: find and fix the conflict

Two live copies of an RViz calibration panel publish the same target detections twice. Find the duplicate publishers and keep one so hand-eye capture works.

LumaSpec Vision8 min read Share on LinkedIn

On this page 9 sections
  1. 01Why the X button hides the panel but leaves it running
  2. 02The symptom: doubled detections and a three-line error burst
  3. 03Find the duplicate: three checks in order
    1. Check 1: count the panels in Panels->Delete Panel
    2. Check 2: count the publishers in rqt_graph
    3. Check 3: one publisher, detections still doubled
  4. 04Worked example: a 15 ms advertise-error burst from one duplicated panel
  5. 05Fix it in four steps
  6. 06Keep it fixed: a 30-second pre-capture checklist
  7. 07When one publisher still gives bad data
  8. 08Where to go next
  9. 09Questions

Two target detections arrive for every pose, the hand-eye solve will not converge, and the camera tests fine. Before you blame the solver, count the publishers on the topic. The usual culprit is a second copy of the calibration panel, still alive inside RViz after you closed the visible one with the X button. Both copies subscribe to the camera feed and both publish to /handeye_calibration/target_detection, so the capture tool receives interleaved detections it cannot tell apart. This page gives you the log signature, a three-check routine that finds every duplicate in about a minute, the four-step fix, and a short checklist that keeps the capture clean. It applies to any RViz-based hand-eye workflow, whether the feed comes from a 2D camera or a 3D sensor.

Why the X button hides the panel but leaves it running

An RViz panel is a plugin loaded into the RViz process, not a separate program. The X button on the panel dock removes the widget from the window; the plugin object, its subscriptions, its timers and its publishers all stay alive inside the RViz node. The Panels menu still lists the panel, because the panel still exists.

Adding the same panel again from the Panels menu creates a second, fully live instance beside the hidden first one. The plugin mechanism builds a fresh panel object for every panel you add, and a standard panel never stops the instance before it. Each instance runs its own target detection on the camera feed, and each publishes what it finds to the same topic name, /handeye_calibration/target_detection. One RViz window ends up with two publishers on one topic, and the capture tool receives every detection twice.

Anything that publishes from a panel behaves this way, so the checks below are worth running after any panel change, not only after calibration work.

The symptom: doubled detections and a three-line error burst

Two signatures give the duplicate away.

The first shows up in the capture tool. Every pose yields two target detections, or the tool flags duplicate detections and refuses to store them, and the solve that follows is unreliable no matter how many poses you record.

The second shows up in the terminal the moment you add the panel. The node prints three errors of the form "Tried to advertise a service that is already advertised in this node", one for each image transport the panel's image view creates:

/handeye_calibration/target_detection/compressedDepth/set_parameters
/handeye_calibration/target_detection/compressed/set_parameters
/handeye_calibration/target_detection/theora/set_parameters

Those are the parameter services that the compressedDepth, compressed and theora transports create for the detection topic. The first panel already created them inside the RViz node; the second panel tries to create the same three and is refused. Both panels keep publishing detections either way, which is the doubling you see in the capture tool.

Find the duplicate: three checks in order

Work from the most likely cause to the least. Each check takes seconds.

Check 1: count the panels in Panels->Delete Panel

Open the Panels menu and choose Delete Panel. The dialog lists one entry for every live panel instance in the window. Look for two or more HandEyeCalibration entries and delete until exactly one remains. This is both the test and, in the common case, the whole fix: a hidden duplicate only dies here.

Check 2: count the publishers in rqt_graph

Open rqt_graph while the session runs. A healthy capture shows one publisher oval feeding /handeye_calibration/target_detection; two ovals mean two live publishers. Then run ros2 node list: two RViz nodes mean an earlier process is still alive from a previous session, and closing that window removes its publisher too. The same one-instance-per-camera discipline that governs vision software governs panels, as covered in multiple vision software instances: one camera per process.

Check 3: one publisher, detections still doubled

With exactly one publisher on the graph, the doubling comes from the subscription side: the capture tool subscribed twice, or a relay re-publishes detections under the same name. Subscribe to the single stream the panel detects on and nothing else; the target detection topic guide explains how to pick that stream.

Worked example: a 15 ms advertise-error burst from one duplicated panel

Here is how to turn the log signature into a decision.

Inputs: the three error lines the terminal prints right after the second panel loads, each naming one service, each carrying a Unix-epoch timestamp in seconds:

Service named in the error Timestamp (s)
/handeye_calibration/target_detection/compressedDepth/set_parameters 1594318848.806460152
/handeye_calibration/target_detection/compressed/set_parameters 1594318848.813994890
/handeye_calibration/target_detection/theora/set_parameters 1594318848.821224490

Rule: a duplicated panel lives in the same RViz node as the original, so its refused service advertisements arrive as one burst, inside one node, under one topic prefix. A camera-driver fault names the camera topic instead, and a collision across two separate processes would not say "in this node".

Arithmetic:

1594318848.813994890 - 1594318848.806460152 = 0.007534738 s = 7.5 ms
1594318848.821224490 - 1594318848.813994890 = 0.007229600 s = 7.2 ms
1594318848.821224490 - 1594318848.806460152 = 0.014764338 s = 15 ms

Result: three same-node advertise errors, 7.5 ms and 7.2 ms apart, the whole burst inside 15 ms, every service under /handeye_calibration/target_detection.

Decision: three or more advertise errors, one node, one calibration-topic prefix, arriving within one second of each other means a duplicated panel. Go to Panels->Delete Panel and keep a single HandEyeCalibration entry. The 15 ms here is the burst length on an unloaded machine; on a loaded workstation it stretches, but a genuine burst stays far inside the one-second limit. Errors that name your camera topic point to the driver or a relay instead.

Fix it in four steps

  1. Delete the duplicates: in the RViz window running the capture, open Panels->Delete Panel and remove every HandEyeCalibration entry except one. Deleting is the only way to stop a hidden instance; X would only hide it again.
  2. Confirm one publisher: open rqt_graph and check that a single oval feeds /handeye_calibration/target_detection. If ros2 node list still shows two RViz nodes, close the stale window as well.
  3. Probe one pose: move the robot to a single calibration pose and confirm the capture tool registers exactly one detection, not two and not zero.
  4. Record and solve: run the full routine. A nine-point alignment needs nine clean detections for nine poses, as described in robot hand-eye calibration: how nine-point alignment works. Once the solve converges, put the result to work with using eye-to-hand calibration results to compute robot-base picks.

Keep it fixed: a 30-second pre-capture checklist

  • Panels->Delete Panel lists exactly one HandEyeCalibration entry, because this is the only place a hidden panel still shows.
  • rqt_graph shows one publisher oval into /handeye_calibration/target_detection, because one source of detections is what the solver assumes.
  • ros2 node list shows one RViz node, because a stale session publishes from the background.
  • The terminal stays quiet after the panel loads, because advertise errors mean a second instance inside the node.
  • A session that went wrong ends in an RViz restart, because adding another panel to a window that hides old ones multiplies the problem.

More systems-side diagnostics live on the systems topic page.

When one publisher still gives bad data

A single publisher is necessary but not sufficient. If detections still look wrong after the fix, work down this list.

Wrong feed. The panel detects on one specific stream, and capturing from a processed or re-published variant corrupts timing and content; match the feed as in the target detection topic guide linked above. If the capture tool cannot find the target frame at all, that is a different failure covered in hand-eye calibration target frame missing: what to check.

Moving hardware. If the camera or the target shifts between poses, detections disagree even with one publisher. Bolt the camera to a rigid camera stand instead of a tripod on the bench. The LS-MNT-0040 slide-table stand gives you 700 mm of height and a 400 x 450 mm base, enough to hold a camera steady over a fixed target through a full pose routine.

Camera standsMachine vision camera stand, professional slide-table type, height 700 mm, 400 x 450 mm base (LS-MNT-0040)LS-MNT-0040
Type
Camera stands
$629.00View partBuild a system with it

For the capture device itself, a projected structured-light 3D camera such as the MV-DPS200P-02 hands the detection stage a dense cloud of the target rather than a bare 2D image.

3D sensorsHikrobot MV-DPS200P-02 Projected structured-light 3D cameraMV-DPS200P-02
Type
Stereo / structured light
$8,829.00 · quotedView and quote

Frames, not counts. Fixing the count can also expose a coordinate-frame mistake that the doubling hid: a cloud that arrives rotated points at the transform chain, as in point cloud rotated 90 degrees after hand-eye calibration, and a residual offset at the gripper shows up as the pick error described in diagnose an eye in hand pick point offset.

Where to go next

With one panel, one publisher and one RViz node, capture becomes deterministic again: one detection per pose, a solve that converges, and a transform you can trust at the gripper. If you are specifying the hardware side of a new cell, start with the 3D sensor finder and the stand configurator below. If a capture still refuses to behave with the duplication gone, contact the applications team with your log and an rqt_graph screenshot.

Build the whole station

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.

Start with the mounting

Questions

Why does the X button on an RViz panel not stop it?

The X control removes the panel widget from the window layout only. The panel object stays loaded inside the RViz process with its subscriptions, timers and publishers running. To stop one for real, use Panels->Delete Panel, which destroys the instance; exiting RViz stops everything, including the hidden copies.

How many publishers should the target detection topic have during capture?

Exactly one. /handeye_calibration/target_detection exists so the capture tool collects detections from a single source; two publishers mean two live panels or a hidden relay, and the tool receives interleaved streams it cannot separate afterwards. Before the first pose, rqt_graph should show one publisher oval into the topic and one subscriber oval from the capture tool.

Can I run one calibration panel in each of two RViz windows?

No. Both instances publish under the same topic name, so the doubling is identical to the two-panels-in-one-window case, and the two processes appear as two nodes in ros2 node list. Keep one RViz window with one calibration panel for the whole capture session, then close it cleanly.

Will deleting a duplicate panel throw away my calibration results?

Deleting an instance stops its publishers and drops its in-memory state, but files you already saved stay untouched, and an exported transform stays valid. A capture recorded while two publishers interleaved detections cannot be cleaned afterwards, so re-record those poses once exactly one HandEyeCalibration entry remains.

What produces the 'Tried to advertise a service that is already advertised in this node' error?

Two components inside one process tried to create the same service name. In this workflow a second calibration panel loads its image view while the compressed, compressedDepth and theora transports under /handeye_calibration/target_detection already exist, the node refuses each duplicate advertisement, and both panels keep publishing from then on.