You dialed in the exposure and the temporal filter at the command line until the depth image looked right on the bench. Production does not run a command line: it runs your program, at every start-up, on every camera. The pattern below carries those verified settings into C++ — build one configuration string, write it to the camera's parameter node through the vendor SDK, apply it, read every value back, and only then open the stream. The worked example uses an exposure of 5000 µs and a 10-frame temporal filter on a 25 fps camera, and shows the arithmetic that turns the filter setting into milliseconds of response time. It is written for integrators who write their own acquisition code.
Why set 3D camera parameters from your own C++ program?
Because production runs your program, not a configuration tool: settings written in code at start-up are repeatable on every boot, identical across every camera on the floor, versionable beside the rest of the source, and free of the one manual step an operator can forget.
The command line is where you discover values: raise the exposure until the noise floor drops, raise the temporal filter until the surface flicker stops, write down what worked. Discovery belongs at the bench. Repetition belongs in code, for three reasons. Every start-up applies exactly the values you signed off — 5000 µs and a 10-frame filter in this example, whatever yours turned out to be. The configuration can be reviewed and rolled back with the rest of the source. And the next camera on the floor gets the identical treatment from the identical binary, with no tool to open and no value to retype from a notebook.
What do you need before you start?
Four things: the vendor SDK installed on the build machine, the camera's IP address, the settings you already verified at the command line — in this example an exposure of 5000 µs and a 10-frame temporal filter — and the SDK's parameter reference that lists the real names and units.
Treat every class, method and key name printed below as a placeholder that shows the pattern; the names that decide live in your SDK's own API reference, and GenICam-style SDKs list them as feature nodes with their units. The example address 192.168.1.42 stands in for whatever your network gives the camera. Bring the bench results as plain numbers with units: exposure 5000 µs, temporal filter 10 frames, confidence threshold 0.5 on the scale your reference states.
Which settings belong in the pre-stream configuration?
Write everything that shapes the image — exposure time, temporal filter, confidence threshold, region of interest — before the stream opens, and write nothing from the calibration: intrinsics and distortion belong to the factory data, and writing over them corrupts the depth output.
Exposure time comes first because everything else inherits it. The 5000 µs here is a bench value for a matte part about a metre out; move the camera or change the part finish and the value moves too, which is why the 3D camera working distance and positioning guide treats mounting distance as a setting in its own right. A longer exposure lifts the signal from dark parts but spends duty cycle, a cost the latency section below makes exact.
Temporal filter frames trade noise for response time; confidence threshold decides which pixels you trust; region of interest bounds where the camera looks. All three belong beside exposure in the same pre-stream write.
The ordering rule carries over from 2D work: set the exposure before the stream opens, not after — the initialization order guide shows what happens when the sequence slips.
One thing never goes into this write: calibration. Intrinsics and distortion are factory data — read them and use them, as the depth camera intrinsics guide shows, but never write over them from an application program.
If the line runs mixed parts, parameter sets can change per part between scans; that is a different pattern with its own timing cost, covered in the per-part switching guide.
How do you write the settings from C++ step by step?
Six steps: open a session to the camera by IP, open its parameter set, write the configuration string or the individual values, apply them, read every value back and compare, then open the stream and drop the first frame.
- Build a minimal program against the SDK and open the device, using the vendor's own sample as the first target.
- Open a session by IP address, before any streaming call exists.
- Open the parameter set — the feature node tree on tree-style SDKs, one configuration-string node on document-style SDKs.
- Write the values, either as the single string or as individual writes.
- Apply, if your SDK separates writing from applying; call the apply unconditionally once you know which pattern yours uses.
- Read every value back and compare with the constants; abort the start-up on any mismatch.
- Open the stream, discard the first captured frame, and start inspecting.
The write, apply and read-back core, with the test that proves the write, looks like this:
// Placeholder names: use the class, method and key names from your SDK's own reference.
#include <stdexcept>
#include <string>
int main() {
const std::string camera_ip = "192.168.1.42"; // your camera's address
const int exposure_us = 5000; // bench-verified
const int filter_frames = 10; // bench-verified
const std::string confidence_min = "0.5"; // scale per your SDK reference
Device device(camera_ip); // session open, stream still closed
Params params = device.OpenParams();
params.Set("exposure_us", std::to_string(exposure_us));
params.Set("temporal_filter_frames", std::to_string(filter_frames));
params.Set("confidence_threshold", confidence_min);
device.ApplySettings();
// The test that proves the write took:
if (std::stoi(params.Get("exposure_us")) != exposure_us) {
throw std::runtime_error("exposure read-back mismatch");
}
Stream stream = device.OpenStream(); // only now start capturing
Frame frame = stream.Capture(); // frame from before the write: discard
frame = stream.Capture(); // first frame under the new settings
return 0;
}
Where the SDK takes a whole document instead of individual writes, the same three values pack into one string:
// Illustrative key names: your SDK's parameter reference lists the real ones.
const std::string config = R"({
"exposure_us": 5000,
"temporal_filter_frames": 10,
"confidence_threshold": 0.5
})";
params.SetConfigJson(config); // one string write to the configuration node
How do you prove the settings took effect?
Two tests: a read-back that compares each parameter against the value you wrote — an exposure of 5000 µs must read back as 5000 µs, not 5 or 500000 — and a capture test on the valid-pixel share of a reference part.
The read-back catches the quiet failures: a misspelled key the SDK ignores, a value clipped to a range limit, a unit written into the wrong field. Guard the read itself: the feature node readability check is a two-line test that confirms the node exists before you read it.
The capture test closes the loop on image content. Count the pixels whose confidence passes your threshold on a matte reference part and require the share to clear a line you set from that part; 95 percent is a workable start for a matte target, lower for anything shiny or curved. If the share collapses right after a write, the write landed wrong — wrong key, wrong unit or wrong node.
Between the write and the first trusted frame sits the pipeline drain: frames captured before the change still carry the old settings. Capture once and throw the frame away, then start counting; some models need two discards, so test yours once and encode the count in your acquisition class. The two-capture rule after a parameter change explains the timing.
How much latency does a temporal filter add?
The filter's frame count times the frame period: at 25 frames per second the period is 40 ms, so a 10-frame filter adds 10 × 40 ms = 400 ms between a real change on the part and a settled depth value.
Worked example, with the arithmetic in the open:
- Frame period: T = 1 / 25 fps = 0.04 s = 40 ms per frame.
- Exposure duty: 5000 µs / 40,000 µs = 0.125, so the sensor integrates for 12.5 percent of each frame period.
- Filter latency: 10 frames × 40 ms = 400 ms between a real change on the part and a fully settled depth value.
- Budget share: with 1000 ms of the robot cycle given to vision, the filter alone takes 400 / 1000 = 40 percent; at 5 frames the cost halves to 200 ms.
Decision: cap the filter at a third of the vision budget. With 1000 ms available and 40 ms frames, 1000 / 3 ≈ 333 ms, and 333 / 40 = 8.3, so run 8 frames — 8 × 40 = 320 ms — and no more. If noise demands more averaging, raise the frame rate before the frame count: the latency scales with the product of the two.
Duty cycle has its own cliff. Modes that stack several exposures inside one frame need the idle part of the period, and an exposure near the period leaves them none; at 12.5 percent there is room. Keep the exposure under about half the frame period unless your mode's own documentation says it fits.
Which mistakes cost the most debugging time?
Three failure modes cause most of the lost days: values written in the wrong unit, values written after the stream is already open, and values assumed to persist through a power cycle.
- No read-back: some SDKs ignore a misspelled key without a word, and you find out from bad parts instead of the log. Read back every value and abort on any mismatch.
- A write after the stream opens: some devices stall, others apply with a pipeline hiccup. When a change must happen mid-run, budget the drain the same way — the live parameter control guide shows the pattern for exposure changes during streaming.
- An unknown state at start-up: a camera borrowed from another station carries that station's settings. Reset to known defaults before your write; the programmatic reset guide gives the sequence.
- A moved camera with an unchanged exposure: mounting distance and part finish move the value. Re-run the bench sweep when either changes, then update the constants.
Which 3D cameras does this workflow fit?
Any 3D camera whose SDK exposes a writable parameter set fits this pattern: a ToF camera for general depth on a fixed station, a projected structured-light camera for detailed stationary scenes, a galvanometer stereo camera for steered measurements, and a laser profiler for moving lines.
Four sensor types cover most depth work, and the write–apply–read-back sequence is identical across them; what changes is the key list in the configuration string:
- Type
- Depth / ToF camera
- Type
- Stereo / structured light
- Type
- Stereo / structured light
Choose by geometry and motion:
- Fixed station, general depth and robot guidance: the MV-DT01WMU ToF sensing camera.
- Detailed geometry on a part that can hold still for the pattern: the MV-DPS200P-02 projected structured-light camera.
- Measurements where the beam must aim rather than flood: the MV-DLS300P-04 laser galvanometer stereo camera.
- Parts moving past the sensor on a conveyor: a 3D laser profile sensor, which writes its exposure per profile line against the encoder:
- Type
- Laser profiler
The 3D sensors category lists every series with its type filter, and the camera finder narrows by resolution and interface once the geometry case is decided.
What should you check before you ship?
Six checks, each runnable on the bench before the camera is mounted: read-back passes, the first frame is discarded, filter latency sits inside the cycle budget, start-up logs the applied settings, power-cycle behavior is known, and the configuration lives in source control.
- Read-back passes on every key, not just exposure — a partial pass hides a partial write.
- The first frame after the write is discarded, and you have tested how many frames your model really needs dropped.
- Filter latency in milliseconds sits inside the vision budget: frames × frame period, worked out at your camera's real frame rate.
- Start-up logs the applied configuration, so the floor can answer "what was it running with?" without guessing.
- Power-cycle behavior is known: persisted by the SDK where it offers that, rewritten by you at every boot regardless.
- The configuration constants live in source control next to the acquisition code, reviewed like any other change.
Selecting the camera itself, rather than wiring this pattern into an existing station, starts at the camera step of the configurator:
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.
The 3D topic page collects the depth-side setup guides that build on this one, and the applications team will check a parameter list against a specific camera before you order — reach us through the contact page.
Questions
Do parameter writes survive a power cycle?
Treat a write as session-only unless your SDK offers an explicit save or persist call on the parameter set. The reliable habit works regardless: rewrite the whole configuration from your program at every start-up, so a power cycle, a swapped camera or a firmware update always lands on the same known settings.
Why does my exposure change not appear in the very next frame?
Frames already inside the camera's pipeline were captured under the old exposure and still have to drain out. Capture once and throw the frame away, then take the real one. Some devices need two discards after a write, so test your model once and encode the discard count in your acquisition class.
Can I switch parameter sets between parts while the camera keeps streaming?
Yes, and some lines need it for mixed part flows. Each switch costs the pipeline drain plus the new settings' settle time, so a 10-frame filter at 25 fps makes every changeover about 400 ms slower. If the recipe is fixed per shift, write once at start-up and switch only when parts actually change.
Should I write the exposure in milliseconds or microseconds?
Write it in the unit your SDK's parameter reference states for that node — most 3D camera parameter stores use microseconds, so 5000 means 5 ms. The read-back comparison is your safety net: write 5000, read 5000, and if the accepted value differs by a factor of 1000, you wrote into the wrong unit field.
Does the same pattern work for laser profilers and structured-light cameras?
Yes. Session, write, apply, read-back, then stream is common across 3D camera families; what changes is the key list and units. A profiler adds per-profile exposure and encoder scaling, structured light adds pattern projection settings, and ToF adds integration and filter nodes — each model's parameter reference is the authority for its own names.



