System designHow-to

Connect a camera only when subscribed to free the GigE link

Set connect_while_subscribed so a GigE camera connects only when a subscriber needs its frames, then verify with netstat and tcpdump that the stream stopped.

LumaSpec Vision10 min read Share on LinkedIn

On this page 9 sections
  1. 01Why a third camera breaks a link that two shared
  2. 02What subscriber-gating changes
  3. 03Turn the setting on
  4. 04Prove the stream actually stopped
  5. 05Worked example: three 5 MP cameras on one 1 GbE switch
  6. 06Common mistakes
  7. 07When gating is the wrong fix
  8. 08The decision, per case
  9. 09Questions

Three GigE cameras, one 1 GbE switch: two stream cleanly, and the third pushes the link past what it can carry. The fix is not a bigger switch — it is to stop streaming what nobody is reading. Connect a camera when a node subscribes to its image topic and disconnect it when the last subscriber leaves, and the idle camera contributes zero bytes to the link. You will set one driver parameter, prove the stream is down with netstat and tcpdump, and budget the link with three numbers. The guide is for anyone running several GigE area scan cameras through one switch or one network interface.

A 1 Gbit/s link moves 125 MB/s at the wire: 1,000 Mbit/s ÷ 8 bits per byte. GigE Vision wraps every image fragment in a UDP/IP datagram inside an Ethernet frame, and headers plus inter-packet gaps cost roughly 5-8% of that gross rate. Plan on about 118 MB/s of usable image payload per 1 GbE link, counting only cameras that are connected at the same moment. The constraint is simultaneous demand, not an average.

When the sum goes over, the switch drops packets and the symptoms arrive together: blank or torn frames, retransmissions and buffer overflow errors in the driver. GigE Vision stream packet loss: diagnose blank frames treats the symptom side; if your logs show buffer faults, this GigE camera buffer overflow walkthrough covers the same failure from the capture side. How much frame rate one camera may claim from a link is its own sum: GigE Vision for a high speed camera: how much frame rate fits works it through.

Most cameras that hit this ceiling are 5 MP class running near full rate; a 2.5 MP sensor halves the per-camera load. The MV-CU020-90GC is a 2.5 MP color GigE camera with a 1/1.7" sensor, C-mount and global shutter.

Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
Interface
GigE
Resolution
Up to 3 MP
$309.00View partBuild a system with it

What subscriber-gating changes

Subscriber-gating moves connect and disconnect out of your application code and into the driver. The driver watches the subscriber count on the image topic: the first subscriber starts the camera, the last unsubscribe stops it. The node, the topic and the publisher stay advertised throughout, so a viewer that comes back receives frames without a launch restart. The camera keeps its IP address and its control channel; only the UDP image stream closes.

Two consequences matter. First, the idle camera costs nothing: no packets on the link, and the driver process falls to essentially zero CPU, which is the fastest signal that the stream is really down. Second, every subscribe cycle runs the SDK's start and stop paths, and those are the heaviest paths a camera driver has. If a driver has ever hung on shutdown for you, the same fragility is in play — camera crash when stopping acquisition: isolate the cause walks that failure down. Gating is also not the same as pausing frames inside a live session: pause and resume camera acquisition in a vision system covers stopping acquisition while the camera stays connected, which suits one camera with a duty cycle rather than a saturated shared link.

Turn the setting on

The parameter is driver-side and defaults to False, so nothing changes until you set it. One ROS 2 camera driver implements the pattern as connect_while_subscribed; set it in the launch file, not in the parameter yaml.

parameters = {
    'connect_while_subscribed': True,
}
  1. Check the build. Set the parameter and judge behavior, not launch output: if the camera still streams with zero subscribers, your build predates the feature. Update the driver first — an outdated clone behaves exactly like a correct one from the launch file.
  2. Set the flag where it lives. Pass connect_while_subscribed: True in the parameters block of the camera node's launch entry, as above. The yaml needs no edit.
  3. Restart the launch and subscribe from a viewer; frames should arrive as before.
  4. Drop the subscriber. Close the viewer, then run the checks in the next section before you trust the setting.
  5. Soak it. Run a couple of weeks of open-and-close cycles before the rig goes into service. Start and stop is the code path that breaks first.

Prove the stream actually stopped

Publisher count will not help you — it stays at 1 by design. Work down this list instead; the whole check takes two minutes.

  1. ros2 topic info /camera/image_raw — you want Subscription count: 0. Publisher count: 1 is the healthy resting state.
  2. ros2 node info on the driver and on anything that ever opened the topic. A forgotten recorder or viewer keeps the camera connected.
  3. Watch the driver process's CPU. It should fall to near zero with no subscribers, because frames stop at the SDK boundary.
  4. Run netstat -ap on the host: a UDP listener appears when the camera connects and disappears when it disconnects. A missing listener is the direct proof that the stream is closed.
  5. Run tcpdump -i eth0 host 192.168.1.50 (your interface and camera IP) while the camera streams, then after the last unsubscribe: packets while connected, silence after.

If subscriber-gating is on and CPU stays high with zero subscribers, the connection did not close. That is the build problem from step 1, not a network problem.

Worked example: three 5 MP cameras on one 1 GbE switch

Inputs, with where each comes from:

  • Cameras: three 5 MP GigE models in mono8, so 1 byte per pixel — the camera class behind the "two run, three do not" case.
  • Frame rate: 10 fps each, set in software, because that is all an operator display needs.
  • Link: one 1 GbE switch — 125 MB/s gross, about 118 MB/s usable payload.

The rule in words: a connected GigE camera sends at its set frame rate continuously, so the sum of simultaneously connected streams must stay below the usable link rate, with headroom for bursts.

stream (MB/s) = pixels × fps × bytes per pixel ÷ 1,000,000 one camera: 5,000,000 × 10 × 1 ÷ 1,000,000 = 50 MB/s two cameras: 2 × 50 = 100 MB/s → 100 ÷ 118 ≈ 85% of the link three cameras: 3 × 50 = 150 MB/s → 150 ÷ 118 ≈ 127%, over by about 32 MB/s

Result: two cameras fit with roughly 15% headroom, which is why that pair ran clean. The third adds 50 MB/s to a link with about 18 MB/s left, so the switch drops roughly a fifth of the demand — and you see blank frames, not a subtle loss.

Decision: never connect the third camera while two are streaming. Cycle which pair is live through subscriptions and let gating hold the idle camera at 0 MB/s. Design to a working limit of about 100 MB/s of simultaneous stream on a 1 GbE link (≈85% of usable) and treat 118 MB/s as the hard ceiling. To run all three continuously instead, each camera drops to about 7 fps: 5,000,000 × 7 × 1 ÷ 1,000,000 = 35 MB/s, and 3 × 35 = 105 MB/s, about 89% of usable.

Common mistakes

  • The flag is set but nothing changes. Your driver build predates the feature; an outdated clone is indistinguishable from a correct one at the launch file. Update, restart, then judge by CPU and netstat, not by logs.
  • Trusting the publisher count. Publisher count: 1 is the resting state, not proof of streaming. Subscription count: 0, near-zero CPU and a missing UDP listener are the signals that matter.
  • A forgotten subscriber. One recorder, diagnostic node or open viewer holds the camera open. ros2 node info on every node in the system finds it.
  • Putting the flag in the yaml. It belongs in the launch file's parameter block; the yaml needs no change.
  • Reaching for a software trigger instead. Setting trigger_mode to "Software" changes when frames are captured, not whether the camera is connected, and it hands you the pacing job that gating does automatically.

When gating is the wrong fix

Gating fits displays and occasional checks, not continuous inspection: a line that needs every frame cannot have one camera disconnected. For those cases change the numbers instead. Cut frame rate or crop the ROI until the sum fits the 118 MB/s budget, enable jumbo frames to shave overhead, or stop sharing one interface. A controller with 5+ LAN ports gives every GigE camera its own NIC, and PoE camera ports carry data and power over one cable. For switch sizing and per-port budgeting across a whole cell, see GigE camera network planning: switch ports and bandwidth.

The vision controllers below take that path: choose by LAN port count first, then by CPU for the image processing you run alongside the streams.

Vision controllersHikrobot MV-VC3301H-128G66 I3-8100, 8GB+128G SSD, No PoE, PCIe expansion supported, Incl. VM6200Pro licenseMV-VC3301H-128G66
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
$2,419.00View part
Vision controllersHikrobot MV-VC5525-256G70-NN VC5000 Vision Controller, 12th-I5, 32GB+256G SSD, Supported PCIEMV-VC5525-256G70-NN
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
$4,479.00 · quotedView and quote
Vision controllersHikrobot MV-VC4712-256G10-2TH Ultra 7 255H, 16G×2+256GSSD+2THDD, PCIe expansion, Without VM license keyMV-VC4712-256G10-2TH
LAN ports
3-4 LAN ports
USB 3 ports
2 USB 3 ports
$6,049.00 · quotedView and quote

The decision, per case

  • Two display cameras on one 1 GbE link: run them straight. You sit near 85% utilization with nothing to configure.
  • Three or more cameras used one or two at a time: enable connect_while_subscribed, cycle subscriptions from your viewers, and keep the two-minute verification in your commissioning checklist.
  • All cameras needed at once, continuously: shrink frame rate or ROI until the sum fits about 100 MB/s, or give each camera its own port on a multi-LAN controller. Jumbo frames recover a few percent more.
  • The link still saturates after all that: move one camera off the shared link. The camera finder filters by interface, so a USB3 or 10GigE model ends the contention without touching the network design.

If you are sizing the rig from scratch, work out the network budget before the camera list and step through the camera configurator. More multi-camera networking work lives on the systems topic page, and layout questions reach the team through the contact page.

Questions

Does the camera stay reachable on the network after it disconnects?

Yes. Subscribe-gating closes the image stream, not the device: the camera keeps its IP address and its control channel, so discovery still finds it and the next subscriber reconnects it in place. What disappears is the UDP image stream and its listener on the host, which is what frees roughly 50 MB/s in the worked example. Gating therefore behaves as a bandwidth control, not an on/off switch for the camera.

How many bytes per pixel does a GigE camera stream use?

The pixel format sets it exactly: mono8 and other 8-bit raw formats are 1 byte per pixel, YUV422 is 2, RGB8 is 3, and packed 10- or 12-bit mono formats land near 1.25-1.5. Multiply pixels by frame rate by that factor to get megabytes per second. A 5 MP camera at 24 fps in RGB8 needs about 360 MB/s, which is why color or high-bit-depth streams rarely share a single 1 GbE link.

Why does the publisher count stay at 1 after I unsubscribe?

The publisher belongs to the driver process, not to the camera connection. The driver keeps the node, topic and publisher advertised so a late subscriber finds them instantly; what closes is the connection to the camera itself. Judge the state by Subscription count: 0, by the driver process falling to near-zero CPU, and by the UDP listener vanishing from netstat -ap. Publisher count reads 1 whether the camera is streaming or idle.

Is reconnecting on every subscribe hard on the driver?

It exercises the SDK's start and stop paths every cycle, and those carry the most thread handling in any camera driver, so soak-test before you trust it: run normal operation with viewers opening and closing for a couple of weeks and watch for hangs. If your workload toggles cameras dozens of times per minute, prefer a dedicated NIC per camera over cycling connections, and keep gating for occasional display switching.

Can all three cameras run continuously if I lower the frame rate?

Yes, if each stream shrinks enough. Divide the usable link rate by the camera count: 118 MB/s ÷ 3 gives about 39 MB/s per camera, and a 5 MP mono8 camera reaches that at about 7 fps — 3 × 35 = 105 MB/s, roughly 89% of the link. Watch motion blur below about 8-10 fps on moving parts; if that hurts, gating or a second NIC beats slowing every camera down.

Does this pattern only apply to ROS 2?

The parameter name is driver-specific, but the pattern is not: connect on demand, disconnect when idle, and keep the sum of simultaneous streams inside the link budget. Any middleware that knows its subscriber count can do it, and recorders and debug viewers are usually the subscribers people forget. The verification tools are middleware-agnostic too: netstat, tcpdump and CPU use tell the truth about any GigE camera.