System designTroubleshooting

GigE driver resets your USB camera in ROS2: stop the USB sweep

Why a GigE camera driver resets a USB camera sharing its ROS2 container, how to read the setXu and bad-magic errors, and the fixes that keep both online.

LumaSpec Vision11 min läs Dela på LinkedIn

På denna sida 11 avsnitt
  1. 01The decision: stop the sweep, then split the processes
  2. 02The signature: three log lines that name the culprit
  3. 03Why the vendor GUI leaves the USB camera alone
  4. 04What the sweep actually does to the device
  5. 05Worked example: 168 ms from first timeout to bad magic
  6. 06Rule out the other suspects first
  7. 07The fix, in order
  8. 08Prove it on the bench before restart of production
  9. 09When the usual advice is wrong
  10. 10Production checklist
  11. 11Questions

You run a GigE camera and a USB camera in one ROS2 Humble system, each through its own driver, both loaded into one component_container. Each camera works alone. Together, the USB camera dies the moment the GigE driver initializes: setXu failed, error code=-1, then Device response with bad magic, magic=0x0. The same two cameras coexist when the GigE camera runs in the vendor's GUI instead, which clears the cabling, the power and the machine. What resets the USB camera is the GigE SDK's USB transport layer sweeping the bus at initialization, a known failure class with a known fix. Here is how to read the logs, what to rule out, and the fix order that keeps both cameras online.

The decision: stop the sweep, then split the processes

Commit to this order:

  1. Run the two-minute control test: GigE camera in the vendor GUI, USB driver running. Both stay up, so the hardware is innocent and the sweep is the culprit.
  2. Update the GigE camera's SDK to a build whose release notes fix USB resets at initialization, installed only from the manufacturer or its distributors.
  3. Scope the driver's enumeration to the GigE interface, wherever the wrapper exposes transport-layer or interface selection.
  4. Whatever else you do, take the USB camera node out of the shared component_container and run one camera driver per process.

Step 1 costs nothing and stops you buying hubs. Step 2 removes the cause. Steps 3 and 4 contain it. The networking and launch-order side of running both interfaces in one ROS2 graph is covered in how to mix USB and GigE cameras in one ROS launch; this article is the case those settings do not touch.

The signature: three log lines that name the culprit

The failure writes these lines, in this order (container prefix trimmed for width):

[02/03 17:15:50.218340][error][28454][UsbEnumeratorLibusb.cpp:162] Failed to get string descriptor: error=Operation timed out
[02/03 17:15:50.229070][error][28454][UsbEnumeratorLibusb.cpp:162] Failed to get string descriptor: error=Input/Output Error
[02/03 17:15:50.386569][error][28601][ObLibuvcDevicePort.cpp:280] setXu failed, error code=-1
[02/03 17:15:50.386569][warning][28601][ObException.hpp:48] Request failed, statusCode: 5, msg: Device response with bad magic, magic=0x0, expectOpCode=0x4252

Read them as one story. A libusb-based enumerator is walking the USB devices and reading their string descriptors; on a camera that is busy streaming, that control transfer times out, and the retry meets a device the OS no longer considers present. Then the camera's own driver fails mid-control-transfer with error code=-1 and a response buffer of zeros. magic=0x0 is the tell: a live device that misreads a command returns a wrong magic, while a device reset mid-transaction returns nothing and the buffer reads back zero. The two id fields differ, 28454 versus 28601, so the enumerator and the streaming driver are separate threads of the same container, one treading on the other.

Why the vendor GUI leaves the USB camera alone

The control test: leave the USB camera streaming under its ROS2 driver, stop the GigE driver, and run the GigE camera in the vendor's GUI. Both cameras stay up, the outcome reported for exactly this pairing, and it is decisive. Power deficits, marginal links and host USB problems do not care which program owns the GigE camera; a reset issued inside one program's initialization does.

The explanation that fits every observation: the GUI enumerates only the interface it opens, while the driver wrapper initializes the whole system, and the producer enumerates every transport layer the SDK carries, USB3 Vision included. The same architectural fact surfaces as other symptoms elsewhere. The same device seen by two transport layers is the camera listed twice by two transport layers case, and a GigE camera that never appears at all is ping works but zero cameras: the transport layer is not loaded. One producer, many transport layers: every combination of loaded, unloaded and duplicated is a different support ticket.

What the sweep actually does to the device

A GenTL producer is the plumbing under most industrial camera SDKs: one library, several transport layers, and enumeration of every interface at system initialization. On Linux, the USB half of that enumeration runs through libusb: open device, read string descriptors, move on. At least one industrial camera SDK has shipped release notes carrying the line "Fixed issue where camera initialization causes other USB devices to reset in linux". That is this failure class, admitted and fixed upstream: initialization itself reset devices it never needed to touch.

On Linux, resetting a USB device restarts that device's driver stack, and to every open handle it looks close to an unplug and replug. In-flight control transfers fail, and the next one reads back zeros. Any USB device the sweep touches is a candidate victim: a depth camera on a libuvc-style driver, or a USB3 area scan camera such as the LS-CMR-0166.

Area scan cameras12 MP USB3 area scan camera, IMX226, 1/1.7" rolling shutter, 30 fps, 4000 × 3000 resolution (LS-CMR-0166)LS-CMR-0166
Sensor format
1/1.7"
Interface
USB3
Resolution
12 MP
Shutter
Rolling
$560.00View partBuild a system with it

Whether the victim recovers is down to its own driver. Some re-open the re-enumerated device and pick the stream back up within seconds; others abort at the first failed control transfer and stay down until restarted. Plan for the second kind.

Worked example: 168 ms from first timeout to bad magic

Inputs: the four log lines above, timestamped to the microsecond and all inside second 17:15:50, with the GigE driver initializing in that window and the GUI control test passed. The rule: a port reset during enumeration shows as timeout, then input/output error, then a zeroed control response inside a fraction of a second; power and thermal problems ramp over seconds to minutes; kernel USB memory limits never touch descriptor reads at all.

t1 = 229.070 ms - 218.340 ms = 10.730 ms t2 = 386.569 ms - 229.070 ms = 157.499 ms t_total = 386.569 ms - 218.340 ms = 168.229 ms

The whole failure, from first descriptor timeout to the dead control transfer, fits inside 168 ms, about a sixth of a second. No thermal or electrical mechanism does that. Combine it with the trigger, the GigE driver's startup, and the passed GUI test, and commit: the enumeration sweep reset the port.

Carry this threshold forward. A failure window under one second, locked to the other driver's startup, is the sweep; apply the fix order below. A window of seconds to minutes that tracks camera load is power or the link; apply the table below instead.

Rule out the other suspects first

Suspect Its signature The test What the test tells you
GigE SDK USB sweep Timeout, I/O error, then bad magic, magic=0x0 within about 170 ms of GigE driver startup GigE camera in the vendor GUI, USB driver live Both stay up: hardware innocent, use the fix order below
USB power budget Drops minutes into full-load streaming, with both cameras drawing current Powered hub, or a port on a different controller Failure follows the GigE startup, not the load: not power
Kernel USB transfer memory Camera enumerates, then large transfers fail with submission errors Stream the USB camera alone at full rate for ten minutes Clean alone: not memory, since descriptor reads are tiny
USB link quality Sporadic I/O errors with no GigE driver in the process, or enumeration at USB 2.0 speed One hour of the USB camera alone, no GigE driver Clean until the GigE driver starts: not the link

The fix, in order

  1. Run the control test from the section above and write down the outcome. It is your evidence, and it takes two minutes.
  2. Update the GigE camera's SDK. Download only from the manufacturer or its distributors, read the release notes for a line about other USB devices resetting at initialization, and rebuild the wrapper against the new build. This is the fix that removes the cause.
  3. Scope the enumeration. Where the wrapper exposes transport-layer or interface selection, enumerate GigE Vision only. That kind of setting lives in the driver's camera-discovery configuration. If the wrapper has no such parameter, do not patch the SDK binary; go to step 4.
  4. Split the processes. Take the USB camera node out of the shared component_container and launch it as its own node. If you run containers, pass only the USB camera's device into that container; passing a USB camera into containers with a CDI spec shows the scoped way. One open client per USB camera is the rule regardless, because a second claim fails hard, as in failed to claim USB interface: one client owns a USB3 Vision camera. If more USB cameras follow, keep the habit and read multiple USB cameras on Linux: stop device path conflicts.
  5. Lock the links. A bouncing GigE link forces the driver to rediscover its camera, and every rediscovery runs the sweep again, mid-run this time. Screw-lock the GigE connector and seat the USB run on a locked connector. The LS-CBL-0199 is a 3 m GigE camera cable with screw locks and a drag-chain rating; the LS-CBL-0219 is the 3 m USB3.0 high-flex counterpart.

Once the two drivers are separated, the GigE side's classic remaining failure under burst traffic is buffer overflow on the host NIC; GigE camera buffer overflow troubleshooting covers the packet-size and driver settings that stop it.

Prove it on the bench before restart of production

  • Cold-start the cell three times in each start order, GigE first and USB first. Six clean starts is the pass condition.
  • Soak for one hour with both cameras streaming, and search the logs for setXu and bad magic. Zero hits passes.
  • Unplug and re-plug the USB camera mid-stream, then watch the next ten seconds. A driver that re-opens the re-enumerated device rides out a foreign reset; a driver that aborts does not. You want the first behavior on a line where the fix is containment rather than removal.
  • If you must stay on the affected SDK build, bisect the wrapper: build it from source, disable successive parts of its startup routine, and restart after each change until the USB camera survives. The call you disabled last is the sweep.

When the usual advice is wrong

A powered hub does not help here: a port reset issued by host software passes through the hub to the device, and the control test already cleared power. A shorter or different USB cable does not help: link problems do not wait politely for the GigE driver to start. Another computer does not help if the same SDK build is installed on it, and you will reproduce the reset there too, one re-cable later. And ROS2 is not the culprit; nothing in it resets USB devices. The shared component_container merely puts two libusb users in one address space and turns one crash into two cameras' outage. That is reason enough to split it, but the reset itself belongs to the camera SDK.

Production checklist

At the bench:

  • GUI control test done, both cameras stayed up
  • SDK updated from the manufacturer; release notes name the USB-reset fix
  • Wrapper searched for transport-layer or interface selection; GigE-only enumeration set where it exists
  • USB camera node out of the shared component_container; one camera driver per process
  • Container device pass-through scoped to the USB camera only

In the cabinet:

  • GigE connector screw-locked; USB connector locked or positively seated

At sign-off:

  • Six cold starts, three per start order, clean
  • One-hour soak with both cameras streaming, no setXu or bad-magic lines
  • Replug recovery of the USB driver demonstrated at the bench

If the re-cable grows into a rebuild, the camera finder lists both sides of the system and the configurator below starts at the accessories step. For a review of a two-camera cell layout, use the contact page.

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 cables and extras

Frågor

Does a powered USB hub protect the USB camera from the reset?

No. The reset is issued by host software during the GigE SDK's enumeration, and a hub cannot block a port reset from reaching the device; it passes straight through. A hub fixes undervoltage, whose signature is different: the camera drops minutes into full-load streaming, not within a fifth of a second of the GigE driver starting. Run the GUI control test first; if both cameras stay up, power was never the problem.

Does this happen with two USB cameras and no GigE camera?

No. The sweep comes from the GigE SDK's USB transport layer; with no GigE driver in the process, nothing walks the bus at initialization. Two USB drivers together have their own failure modes, device path mix-ups and one client claiming an interface the other needs, which show up as wrong-device images or claim errors rather than a reset at another camera's startup. Keep the one-driver-per-process habit anyway; it makes every USB incident local to one camera.

Is the USB reset specific to Linux?

The known fix note names Linux, quoting "camera initialization causes other USB devices to reset in linux", and the enumeration path involved, libusb, is Linux-side plumbing. Windows loads a different USB driver model for the same SDK, so the same build may behave differently there. Do not assume either way: run the same GUI-versus-driver control test on the target operating system before you sign off the architecture.

What can I do if the GigE SDK build cannot be changed on the line?

If the wrapper exposes no transport-layer selection and the SDK build is frozen, isolation is the lever you have. Give each camera driver its own process, and pass only the USB camera's device into its container. Test the USB driver's replug recovery explicitly, because on a shared host a port reset still reaches the device: a driver that re-opens after the replug rides it out, one that aborts does not. Separating the two cameras onto different hosts removes the overlap completely.

How do I check whether my USB driver survives a surprise replug?

Stream from the USB camera, note the topic rate, unplug and re-plug its cable, and watch the next ten seconds. A driver that re-opens the re-enumerated device picks its stream back up on its own; a driver that aborts at the first failed control transfer stays down until restarted. Ground yourself before touching the connector, because a static discharge can damage the camera's USB front end.