3D visionTroubleshooting

Tracking camera works in viewer but not in ROS: fix it

A tracking camera that works in the vendor viewer but reports device not connected in ROS: why the split happens and how to fix multi-camera enumeration.

LumaSpec Vision10 min read Share on LinkedIn

On this page 10 sections
  1. 01What the viewer's success rules out
  2. 02First cause: one combined launch file opening both cameras
  3. 03Second cause: another client holds the camera
  4. 04Third cause: the replug pattern and the USB bus
  5. 05Worked example: the two-camera bench on kernel 5.4.0-42
  6. 06Joining the frames: one node per camera, then a static transform
  7. 07When it is not the enumeration
  8. 08Prevention: rig the bench so it cannot recur
  9. 09The decision, case by case
  10. 10Questions

The vendor viewer lists both cameras: the depth camera and the tracking camera, each with its serial number. You start the ROS stack and the tracking camera's node answers with "device not connected". Nothing on the bench changed between the two commands, and that is the clue: the operating system still sees the camera, so the failure happens when your node tries to open it. On a Linux host where a depth camera and a tracking (visual-inertial) camera share one USB controller, the usual culprits are a combined launch file opening both devices in one process, and another client holding the interface. Four tests isolate the cause, a change to the launch architecture stops it coming back, and a worked example runs the decision on a kernel 5.4 host.

What the viewer's success rules out

A viewer that lists the camera and streams from it proves four things at once: the cable carries power, the USB link trained, the kernel driver bound, and the SDK can open the device. All four sit below anything ROS does, so a node reporting the device absent is failing at the open-and-claim step, not at the physical layer. That orders the suspects for everything that follows: software claiming first, bus state second, camera hardware last.

The same logic runs in reverse. If the viewer loses the device while the ROS stack is stopped, the problem is below the SDK — cable, hub, power, or an SDK and firmware pair that no longer match. Fix that layer first; the tests in this guide assume the viewer passes.

First cause: one combined launch file opening both cameras

Most depth-plus-tracking stacks ship a demo launch that starts both cameras inside one process. The wrapper opens devices in sequence; when the first open or the stream negotiation stalls, the second device's open times out, and the log reports the tracking camera as absent even though the viewer sees it. The failure follows the launch file, not the camera: run the tracking camera's launch on its own and it enumerates immediately.

The fix that holds is architectural. Start the depth camera from its own launch in one terminal and the tracking camera from its own launch in another, each pinned to its camera's serial number. Separate processes mean one stalled stream can no longer block the other camera's open. Reconnect the two views at the transform level instead — the section below shows how.

Second cause: another client holds the camera

These SDKs allow one claimant per device: a viewer left open, a node from an earlier launch that never exited, or a process that crashed without releasing the handle keeps the next client from opening the camera. The test takes a minute: stop every camera process on the host and run the vendor's device-enumeration command in a plain terminal. If it lists both cameras with their serials while nothing else runs, the OS layer is clean and a holder is the suspect. Start your nodes one at a time; whichever start breaks the enumeration names the holder.

The full diagnostic for this failure class is in two depth cameras USB busy: fix the interface claim error, with the general USB-access version in two cameras interface claim conflict: diagnose USB access.

Third cause: the replug pattern and the USB bus

Unplugging and replugging two or three times to bring the camera back is a signature, not a coincidence: a replug resets link training and re-enumerates the device, clearing stale hub or controller state. A defective camera fails in every client, viewer included, and no amount of replugging changes that. So when a session needs more than one replug, treat the bus as the fault and change the topology:

  • Move each streaming camera to a rear-panel root port on its own controller.
  • Replace any bus-powered or monitor-built-in hub with a powered hub that has its own supply.
  • Add a dedicated USB controller card so the two streaming cameras stop sharing one root.

Worked example: the two-camera bench on kernel 5.4.0-42

Inputs, as reported from the failing bench: one PC host on Ubuntu 18.04.5 LTS, kernel 5.4.0-42; SDK 2.41.0-0; tracking-camera firmware 0.2.0.951; one depth camera and one tracking camera on a single controller. The viewer lists both cameras with serials; the combined launch reports "device not connected" for the tracking camera only; replugging two or three times restores it.

The rule, in words: a device that one client lists and another cannot open is a claiming or enumeration fault, because a hardware fault appears in every client.

The arithmetic on the evidence:

  • 2 cameras − 1 failing = 1 healthy camera on the same controller, so the controller, the cable set and host power are good.
  • 2 clients − 1 working = the failure is confined to the node's open path, below the OS.
  • Replugs to restore: 2–3, which is above the threshold of 1, so bus state is a second fault.
  • SDK 2.41.0-0 opens firmware 0.2.0.951 in the viewer, so the firmware pair is aligned and reflashing stays off the list.

Result: a claiming and enumeration conflict, with marginal bus state behind the replug pattern. The decisions, threshold by threshold:

  • Launch the tracking camera alone. It enumerates here, so split the launches permanently and join the frames with a static transform publisher.
  • Had it failed alone with the stack stopped, install the vendor's udev rules, re-plug, and retest the enumeration as the normal user.
  • Because more than one replug is needed per session, move the tracking camera to a rear root port or its own controller; a camera that needs replugging every session is a bus fault by definition.

Joining the frames: one node per camera, then a static transform

With each camera in its own node, the streams meet again at the transform level. Publish a static transform between the tracking camera's pose frame and the depth camera's optical frame; the offset is constant because both cameras are bolted to one rig, so a static publisher is correct and costs nothing per frame. Two details decide whether the fused result is usable: the frame names must match what the drivers actually publish, and the timestamps must be comparable across the two nodes.

Check the axes first: IMU optical frame transform: verify depth camera IMU frames covers the axis conventions that most often break this transform. Calibrate the mechanical offset between the cameras once, with a target or a fixture, following multi-camera extrinsic calibration in one shared coordinate frame. After that, one static transform publisher serves every downstream consumer.

When it is not the enumeration

Three fingerprints point away from the open-and-claim layer:

And if the node never connects at any stage, with the stack otherwise clean, the handshake itself is the suspect: ROS node not connecting to a 3D camera: handshake fixes.

Prevention: rig the bench so it cannot recur

  • One streaming camera per USB root controller; add a controller card before stacking hubs.
  • Pin each launch to the camera's serial number, never to a USB path. Paths move when hubs or boot order change, which is its own failure class: multiple USB cameras on Linux: stop device path conflicts.
  • Install the vendor's udev rules at provisioning, so every non-root process can open the device.
  • Start nodes one at a time and confirm each streams before starting the next; a combined start hides which open failed.
  • Record the firmware and SDK pair that worked, and upgrade the pair together.
  • Size the host for two full-rate streams; when specifying it, industrial mini PCs with multiple USB roots are the usual choice for a two-camera cell.

The decision, case by case

If the cell's position comes from the robot controller or an encoder, the tracking camera is redundant hardware: run one depth camera on its own controller and the whole enumeration problem leaves with the second device. For that single-camera rig, a ToF depth camera or a projected structured-light camera does the job:

3D sensorsHikrobot MV-DT01WMU ToF sensing cameraMV-DT01WMU
Type
Depth / ToF camera
Price on requestView and quote
3D sensorsHikrobot MV-DPS200P-02 Projected structured-light 3D cameraMV-DPS200P-02
Type
Stereo / structured light
$8,829.00 · quotedView and quote

If you need visual odometry on the rig, keep the pair and apply the architecture: one launch per camera, serial pinning, one camera per controller, and a static transform publisher between the frames. The fingerprints and their fixes, in one table:

Fingerprint Cause Test Fix
Viewer lists it, combined launch reports it absent Combined launch claiming both devices Run the tracking launch alone One launch per camera, joined by a static transform
Enumeration succeeds only when the stack is stopped Another client holds the interface Start nodes one at a time Kill the holder, start sequentially
Two or three replugs restore it Hub or controller state Move ports, power-cycle the hub Rear root ports, powered hub, dedicated controller
Opens, then frames stall Controller bandwidth Lower the rate, split controllers Controller card; see the bandwidth guide
Gone from the viewer too after an update Firmware and SDK misaligned Check the release pair Upgrade the pair together

Pick the pair or the single camera from 3D sensors or the camera finder; the 3D topic page groups the integration guides around them.

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 camera

If the tracking launch still fails with every other process stopped, run the vendor's enumeration command once more and send the output with your launch file through the contact page — that combination pins the failing layer in one pass.

Questions

Can I keep both cameras on one combined launch file at all?

Sometimes, on a host with one camera per controller and a stack that sequences the opens cleanly — but the combined file is still the pattern most often behind device not connected. Keep the split-launch layout as your default and use the combined file only for quick demos, where a failure costs you nothing but a restart.

How do I find which process is holding the camera?

Stop every camera process, then run the vendor's device-enumeration command in a plain terminal. If the camera that failed now appears, one of your own processes was the holder — relaunch them one at a time and the failing start identifies itself. Plain lsusb confirms the bus-level device and its serial, which is what your launch files should pin.

Does the replug fix damage the camera over time?

Replugging is the diagnostic, not the repair, and it does no harm. Each replug power-cycles the link and forces a fresh enumeration, which is why two or three tries appear to fix the fault; the part that needed clearing was hub or controller state, not the camera. Use replugging to confirm the bus theory, then fix the topology so nobody repeats it on a running cell.

What should I check before ordering a second USB controller card?

Count the streams, not the cameras: add up the data rate each camera pushes at its working resolution and frame rate, and put the new card on its own chipset lane so it does not share the root the depth camera uses. One streaming camera per controller is the layout to aim for; a spare port on the same controller helps nothing.

Why does the viewer work when the node cannot open the device?

A short viewer session and a long-lived node do not exercise the SDK the same way: the node holds the streams for the process lifetime, so a claim, a permission rule or a stale handle that a quick viewer session survives will stop a node dead. Install the vendor's udev rules, confirm with the enumeration command run as your normal user, and reboot once to clear stale handles before suspecting the wrapper.