A depth camera that streams cleanly at QVGA starts logging "Depth buffer is corrupt" the moment you raise it to VGA and watch from your desk, with arrival sizes well short of the expected 614400 bytes. The camera is rarely broken. The stream is being asked to cross a link that cannot carry it, and sometimes a second bottleneck sits inside the robot as well. You will finish with the bandwidth arithmetic for any depth mode, the exact switch to the compressed transports for remote viewing, and a loopback test that separates network loss from a saturated camera link.
Why does a depth buffer arrive corrupt over remote ROS?
The frames are not corrupt at the camera. They arrive short because the raw depth topic needs more bandwidth than the wireless link can carry — one 640×480, 16-bit frame is 614,400 bytes, and at 30 Hz that is 18.4 MB/s, several times past what the link delivers. The driver reads a fixed-size buffer for every frame, and each warning line states exactly what arrived: 120160, 476240, 240336, 360512, even 4448 bytes. Every short count is one failure: transmission stopped part-way through the frame, so the driver discards it. The cost shows in the log's own FPS line, which falls to 14.73 delivered depth frames per second against 30 configured while color holds 30.38.
A short size is a transport failure, not a decoder failure. If your log instead reports a bad magic number on full-size buffers, that is a different fault with its own fix, covered in bad magic number on depth streams: why frames arrive corrupt.
How much bandwidth does VGA depth need?
Multiply width by height by two bytes and by the frame rate: 640 × 480 × 2 × 30 gives 18,432,000 bytes per second, about 18.4 MB/s or 147 Mbps before topic overhead. That single stream already exceeds a typical robot Wi-Fi link several times over. Here is the worked example for the failing mode:
- 640 × 480 = 307,200 pixels per frame.
- 307,200 pixels × 2 B = 614,400 B per frame — the number the driver itself quotes, which confirms the arithmetic and the driver agree.
- 614,400 B × 30 Hz = 18,432,000 B/s ≈ 18.4 MB/s.
- 18,432,000 B/s × 8 = 147,456,000 bit/s ≈ 147 Mbps of airtime, before ROS and TCP overhead.
The same math at QVGA gives 320 × 240 × 2 × 30 = 4,608,000 B/s ≈ 4.6 MB/s, one quarter of the VGA figure. That is why the smaller mode ran clean while VGA did not. The arithmetic scales linearly: double the frame rate and you double the megabytes per second. For the same calculation carried to point clouds and multi-camera payloads, see stream depth data over a network: bandwidth math and compression.
How do you confirm the network is the cause?
Run one viewer on the robot itself and one on your desk and compare them. Corruption only on the remote subscription puts the loss on the network path; corruption on both at once indicts the camera's internal link instead. Keep every remote subscriber off the link first, and run the VGA depth viewer on the robot. A steady 30 fps with no short-size warnings clears the camera and its driver. Then subscribe remotely and watch two indicators: delivered depth fps in the driver log, and throughput on the link. A saturated wireless hop shows the truncation warnings returning as soon as the raw topic flows.
For algorithm work, avoid live streaming while you tune. Record frames on the robot and replay them offline, the capture path described in 3D camera recording to H5 files for offline processing. That moves no bytes across the wireless hop during debugging.
How do you switch the depth topic to the compressed transport?
Install the image_transport plugin package, then add one argument to each viewer command — compressed for color, compressedDepth for depth. The same topics then travel as JPEG/PNG-compressed data with no change to the camera driver or launch files. In order:
- Install the plugin package where you subscribe, and on the robot so the variants are advertised:
sudo apt install ros-melodic-image-transport-plugins(Ubuntu 18.04) orsudo apt install ros-kinetic-image-transport-plugins(Ubuntu 16.04); on newer distributions the same package exists under your distribution's name. - Launch the camera driver exactly as before.
- Add the transport argument to each viewer command on the remote PC:
rosrun image_view image_view image:=/camera/rgb/image_rect_color _image_transport:=compressed
rosrun image_view image_view image:=/camera/depth/image_rect_raw _image_transport:=compressedDepth
The plugins add the compressed and compressedDepth transports, and color travels as JPEG- or PNG-compressed data; the image_transport tutorials that ship with the package document it. Each transport appears as its own variant of the topic, so the argument simply selects which one the viewer pulls. If a compressed variant never appears, the plugin package is missing on the publishing side; compressed image topic not published: get /compressed streams working walks that case.
On one comparable robot set-up, viewing both topics compressed drew about 450 kb/s combined against roughly 5 MB/s uncompressed — an elevenfold cut — and cleared most of the corruption. What remained is the next section.
Why does corruption persist even on the robot's own loopback?
Because a second bottleneck sits inside the robot. If the same short-size warnings appear with the subscriber running on the robot itself and no network in the path, the camera-to-computer link cannot sustain VGA depth alongside color, and no transport setting will fix it. The signature is identical to network loss — short sizes such as 120160 or 360512 bytes, stream markers drifting apart (Expected 21ab, got 220f) — because the driver only sees what arrived, not where it was delayed. VGA depth alone is an 18.4 MB/s pull, and the camera's streams share one route into the robot's computer.
Work down the ladder that made QVGA clean:
- Set the camera back to QVGA_30Hz with rqt_reconfigure and confirm the warnings stop; in this log it did.
- Cut the depth frame rate before the resolution when latency costs less than detail.
- Run one stream at a time while you measure, not all of them together.
- Put the camera on a direct port rather than behind a hub: depth camera fails on a USB hub: why raw streams refuse to start and depth camera frames not updating: fix USB bandwidth stalls cover the internal-link failure modes.
Decision: loopback clean means compress and re-budget the wireless hop; loopback corrupt means fix the camera path first, because no transport change will help.
Which size and frame rate fits a robot Wi-Fi link?
Budget roughly 2-4 MB/s of usable TCP throughput on a typical 802.11n-class 2.4 GHz link. Uncompressed VGA depth at full rate is about seven times over that budget, while the compressed streams measured on a comparable setup fit with more than five times headroom. The basis: a single-stream 802.11n radio advertises 65-72 Mbps at the PHY, and real TCP throughput on a busy 2.4 GHz band lands near 25-40% of that. Measure your own link before commissioning.
| Mode | Bytes per frame | At full rate | At 15 Hz | On a 2.5 MB/s link |
|---|---|---|---|---|
| 320×240, 16-bit (QVGA) | 153,600 B | 4.6 MB/s (37 Mbps) | 2.3 MB/s | Raw fits at 15 Hz; compressed easily |
| 640×480, 16-bit (VGA) | 614,400 B | 18.4 MB/s (147 Mbps) | 9.2 MB/s | Raw fails; compressed at 15 Hz fits |
The uncompressed ceiling explains the failure arithmetically: 2,500,000 ÷ 614,400 ≈ 4 full VGA frames per second against 30 offered, so most frames arrive short or never. Compression on depth-like frames typically cuts five- to fifteen-fold, which brings VGA depth at full rate to roughly 1.2-3.7 MB/s — marginal on this link — and the same stream at 15 Hz to 0.6-1.8 MB/s, which fits with margin. QVGA compressed lands near 0.3-0.9 MB/s.
Decision by link type: on wired gigabit, run raw — 18.4 MB/s is about 15% of a 1 Gbps wire — and stream depth frames to a remote PC over gigabit ethernet covers that set-up. On wireless, subscribe compressed and hold full rate only at QVGA; at VGA, drop to 15 Hz compressed.
When should depth processing move onto the robot?
When the remote PC is only watching, stop shipping frames across the air altogether. Run the depth pipeline on a controller mounted in the cell and publish compact results, so the wireless link carries kilobytes of outcomes instead of megabytes of frames. Detections, poses, volumes and pass/fail flags survive any wireless link, and the raw stream never touches the air.
For a single depth camera plus two or three 2D cameras, a compact controller is enough: the MV-VC2140-128G40-1T carries 3-4 LAN ports and 2 USB 3 ports with 8 GB of memory for exactly that cell size. Keep the on-board pipeline allocation-free so the frame rate holds under load — reuse image buffers instead of per-frame allocation shows the pattern.
For a heavier cell — more cameras on the wire, PoE for the camera links — step up a series:
| Specification | MV-VC2140-128G40-1T | MV-VC3301H-128G66 | MV-VC5525-256G70-NN |
|---|---|---|---|
| CPU | Intel® Processor N97 | Intel® Core i3-8100 | Intel® Core i5-12400 |
| Memory | 8 GB | 8 GB | 32 GB |
| Storage | 128 GB SSD + 1 TB HDD | 128G SSD | 256 GB SSD |
| GPU | Intel® UHD Graphics | Intel® HD Graphics 630 | Intel® UHD Graphics 730 |
| Operating system | Unactivated 64-bit Windows 10 LTSC 21H2 | Windows 10 64-bit, Not activated | Unactivated Windows 10 |
| Encryption method | Not support | VM6200Pro license key | – |
| Video output | HDMI interface × 1, VGA interface × 1; Supports independent display outputs at the same time; Max. resolution 1920 × 1080 @ 60 Hz | HDMI interface × 1, VGA interface × 1; Supports independent display output at the same time; Max. resolution 1920 × 1080 @ 60 Hz | HDMI interface × 1, VGA interface × 1; Supports independent display output at the same time; Max. resolution 1920 × 1080 @ 60 Hz |
| Digital I/O | Opto-isolated input × 8; Opto-isolated output × 8 | 8 digital isolated inputs supported; 16 opto-isolated outputs supported (NPN/PNP switchable) | Opto-isolated input × 8; Opto-isolated output × 12 ( supports NPN/PNP switching), digital-isolated low-side driver output × 8; Non-isolated bi-directional differential I/O × 4 |
| Light interface | Light interface with 24 VDC constant voltage × 4; (Brightness is adjustable. Max. current 3 A for single light interface, and total max. power consumption 80 W. Supports light mode switching between strobe and solid via external control) | 4-channel 24 V constant-voltage light drive, Max. power per channel: 72 W, Max. power (4 channels): 150 W | 24 VDC constant voltage × 8; (Max. power consumption of single channel is 72 W, total max. power consumption 190 W) |
| Network interface | GigE interface × 4 | 6× Gigabit Ethernet ports | GigE interface × 7, including interface for PoE × 4 |
| USB Interface | USB 2.0 × 2; USB 3.0 × 2 | USB 2.0 × 4; USB 3.0 × 4; Built-in USB 2.0 × 1 | USB 2.0 × 4, USB 3.0 × 4, built-in USB 2.0 × 1 |
| Serial Port | RS-232 × 1, supports switching to RS-485 or RS-422 | 2× full-function RS-232, RS-485/RS-422 switchable | RS-232 × 2 by default, supports switching to RS-485 and RS-422 |
| Price | $1,679.00 | $2,419.00 | $4,479.00 · quoted |
All 3 share: Certification CE, KC. Values as printed in each product's data sheet; open a part for its drawing and full specifications.
If you are choosing the depth camera itself rather than debugging one, match measuring range and field of view first, then budget its stream with the same arithmetic. The 3D sensors category lists laser profilers, stereo and structured-light cameras and ToF depth cameras such as the MV-DT01WMU side by side.
What checks prevent a repeat on the next cell?
Compute the bandwidth budget before the first wireless test — frame bytes times frame rate against a measured link throughput, with about 30% margin. Treat any drop in the driver's usable-FPS line as loss upstream rather than a slow viewer. Keep the list and the failure stays rare:
Before commissioning
- Compute bytes per frame × rate for every stream you plan to publish, and compare against a measured link throughput. Five minutes of arithmetic catches an over-budget mode.
- Decide per topic what crosses the wireless hop: results and compressed previews only. Raw frames stay on the local segment.
During commissioning
- Subscribe with compressed and compressedDepth from the first remote session; never debug against the raw topic over Wi-Fi.
- Run the loopback test once at the final resolution: clean clears the camera path, corrupt sends you to the USB fixes before the network gets blamed.
- Record a run locally and replay it when algorithm work needs full-rate frames.
In operation
- Watch the driver's delivered-FPS line: 30 configured against about 15 delivered is loss upstream, and it precedes the short-size warnings.
- Re-run the budget whenever resolution, frame rate or stream count changes.
More depth-transport fixes live on the 3D camera topic page, the vision controllers category is the shop page for the on-robot computer, and the contact page is open if you want us to check your stream table's arithmetic.
Questions
Do the compressed topics appear by themselves once the plugins are installed?
Yes. image_transport advertises every installed transport as a sibling of the raw topic, so after installing the image_transport_plugins package the publisher offers compressed and compressedDepth variants next to the raw image topics. If a variant never appears, the plugin package is missing on the machine that publishes, or the subscriber is asking for a transport name that is not installed there.
How large is one clean VGA depth frame in bytes?
640 × 480 pixels × 2 bytes per 16-bit sample = 614,400 bytes, the exact figure the driver quotes when it rejects a short buffer. Any warning with a size below 614,400 means the same thing whatever the number: 120,160, 240,336 and 476,240 bytes are all frames that stopped arriving part-way through.
What bandwidth does uncompressed VGA depth need on a wired link?
About 18.4 MB/s, or 147 Mbps of the wire. A switched gigabit link moves roughly 110 MB/s of usable TCP traffic, so raw full-rate depth takes about 15% of the wire and leaves room for color and control traffic. Compression is a wireless fix, not a wired one.
Can I keep the raw topic for processing and compress only for viewing?
Yes, and that is the normal pattern on a mixed link. Run the algorithm on the machine beside the camera where the raw topic is local, and subscribe remotely only to compressed variants. What fails is pulling the raw topic across the wireless hop. On a local or wired segment the raw topic costs nothing extra and keeps every bit intact.
Which transport should I use for the color stream?
Use compressed for color. The transport package sends images as JPEG- or PNG-compressed data, and a 640×480 RGB frame is 921,600 bytes raw, so uncompressed color alone draws 27.6 MB/s at that same frame rate and can saturate the link by itself. Where JPEG artifacts would matter for a color inspection, keep that stream on the lossless transport or view it locally.