Required Info
| Field |
Value |
| Camera Model |
RealSense D435 |
| Firmware Version |
5.17.0.10 |
| Product ID |
0B07 |
| Serial Number |
138422078366 |
| USB Type |
USB 3.2 |
| Operating System & Version |
Ubuntu 22.04.5 LTS |
| Kernel Version |
6.8.0-117-generic x86_64 |
| Platform |
Industrial PC / x86_64 |
| Librealsense SDK Version |
ROS node reports LibRealSense v2.57.7; system also has librealsense2-utils 2.58.1 installed |
| RealSense ROS Wrapper Version |
4.57.7 |
| ROS Distro |
ROS2 Humble |
| Language |
C++ / ROS2 / V4L2 / librealsense advanced-mode probe |
| Segment |
Robotics / industrial vision |
Issue Description
On our machine, besides using the 3D data for pick point selection, we also build a color picture of the object (by stiching together slices of the color picture) to determine the type of object using an AI network. For that, we need calibrate and set the color white balance parameter on each machine. This works fine in an earlier version of the program that does not use ROS2, but not using the ROS2 RealSense wrapper.
First, the RGB stream does not reliably start with the requested manual color settings if those settings are applied as normal ROS startup parameters. The camera initially comes up overexposed / with unstable color unless we delay applying the final RGB settings until after color frames have started arriving.
Our current workaround is:
- Start the RealSense ROS2 camera node.
- Wait until the first
/camera/color/image_raw frame is received.
- Wait an additional warmup delay, currently 5 seconds.
- Apply the final RGB/depth settings via ROS parameters:
rgb_camera.enable_auto_exposure = false
rgb_camera.exposure = 7
rgb_camera.enable_auto_white_balance = false
rgb_camera.white_balance = 4550
rgb_camera.saturation = 31
rgb_camera.sharpness = 81
depth_module.enable_auto_exposure = false
depth_module.exposure = 160
This delayed startup apply makes the initial image look correct. Applying the same settings too early during ROS node startup was not sufficient/reliable.
Second, after the stream has been running, the RGB image can suddenly change tint during continuous streaming. When this happens, all exposed camera state still reports the expected values: ROS parameters, V4L2 controls, RealSense color frame metadata, and D400 advanced-mode color correction all remain unchanged and correct.
Restarting the program / reopening the RealSense stream immediately fixes the tint. Reapplying the same RGB camera settings during the bad state does not fix it.
This suggests a hidden RGB ISP / color pipeline state issue in firmware or librealsense that is not exposed through ROS parameters, V4L2 controls, RealSense frame metadata, or D400 advanced-mode color correction.
Stream / Settings
Color stream:
- 848x480 @ 60 FPS
- ROS output format: RGB8
- V4L2 node reports YUYV on
/dev/video20
Applied settings:
rgb_camera.enable_auto_exposure = false
rgb_camera.exposure = 7
rgb_camera.enable_auto_white_balance = false
rgb_camera.white_balance = 4550
rgb_camera.saturation = 31
rgb_camera.sharpness = 81
depth_module.enable_auto_exposure = false
depth_module.exposure = 160
Observed Behavior
Here is a picture where the tint changes mid picture (Picture is stitched from multiple frames)

After the tint shift, periodically reapplying the same camera settings did not recover the image. Restarting the program / stream recovered it.
Image channel statistics from saved RGB images showed the visual change:
- Bad state:
B/G ~= 1.10 - 1.116
- After restart / good state:
B/G ~= 1.05, R/G ~= 1.04
The actual items can vary in color, so the strongest evidence is the visible tint shift plus the fact that restarting the stream restores the expected appearance while metadata remains identical.
Bad-State Frame Metadata
While the tint issue was present, /corner_finder/camera/color/metadata reported:
{
"actual_exposure": 7,
"gain_level": 0,
"auto_exposure": 0,
"brightness": 0,
"contrast": 50,
"saturation": 31,
"sharpness": 81,
"auto_white_balance_temperature": 0,
"manual_white_balance": 4550,
"backlight_compensation": 0,
"hue": 0,
"gamma": 300,
"power_line_frequency": 3,
"low_light_compensation": 0
}
Good-State Frame Metadata After Restart
After restarting the program / stream, the image looked correct again, but metadata was effectively identical:
{
"actual_exposure": 7,
"gain_level": 0,
"auto_exposure": 0,
"brightness": 0,
"contrast": 50,
"saturation": 31,
"sharpness": 81,
"auto_white_balance_temperature": 0,
"manual_white_balance": 4550,
"backlight_compensation": 0,
"hue": 0,
"gamma": 300,
"power_line_frequency": 3,
"low_light_compensation": 0
}
V4L2 State During Bad State
Direct V4L2 controls on the RGB node also looked correct:
white_balance_automatic = 0
white_balance_temperature = 4550
auto_exposure = Manual Mode
exposure_time_absolute = 7
saturation = 31
sharpness = 81
brightness = 0
contrast = 50
gamma = 300
hue = 0
gain = 64
D400 Advanced Mode State
We also queried D400 advanced mode using rs400::advanced_mode:
advanced_mode_enabled 1
color_control 0 0 0 0 0
color_correction 0.298828 0.293945 0.293945 0.114258 -0 -0 -0 -0 -0 -0 -0 -0
These values were the same in bad and good states.
So do you have any suggestions what I could try to get the white balance settings to stick?
Required Info
Issue Description
On our machine, besides using the 3D data for pick point selection, we also build a color picture of the object (by stiching together slices of the color picture) to determine the type of object using an AI network. For that, we need calibrate and set the color white balance parameter on each machine. This works fine in an earlier version of the program that does not use ROS2, but not using the ROS2 RealSense wrapper.
First, the RGB stream does not reliably start with the requested manual color settings if those settings are applied as normal ROS startup parameters. The camera initially comes up overexposed / with unstable color unless we delay applying the final RGB settings until after color frames have started arriving.
Our current workaround is:
/camera/color/image_rawframe is received.rgb_camera.enable_auto_exposure = falsergb_camera.exposure = 7rgb_camera.enable_auto_white_balance = falsergb_camera.white_balance = 4550rgb_camera.saturation = 31rgb_camera.sharpness = 81depth_module.enable_auto_exposure = falsedepth_module.exposure = 160This delayed startup apply makes the initial image look correct. Applying the same settings too early during ROS node startup was not sufficient/reliable.
Second, after the stream has been running, the RGB image can suddenly change tint during continuous streaming. When this happens, all exposed camera state still reports the expected values: ROS parameters, V4L2 controls, RealSense color frame metadata, and D400 advanced-mode color correction all remain unchanged and correct.
Restarting the program / reopening the RealSense stream immediately fixes the tint. Reapplying the same RGB camera settings during the bad state does not fix it.
This suggests a hidden RGB ISP / color pipeline state issue in firmware or librealsense that is not exposed through ROS parameters, V4L2 controls, RealSense frame metadata, or D400 advanced-mode color correction.
Stream / Settings
Color stream:
/dev/video20Applied settings:
rgb_camera.enable_auto_exposure = falsergb_camera.exposure = 7rgb_camera.enable_auto_white_balance = falsergb_camera.white_balance = 4550rgb_camera.saturation = 31rgb_camera.sharpness = 81depth_module.enable_auto_exposure = falsedepth_module.exposure = 160Observed Behavior
Here is a picture where the tint changes mid picture (Picture is stitched from multiple frames)

After the tint shift, periodically reapplying the same camera settings did not recover the image. Restarting the program / stream recovered it.
Image channel statistics from saved RGB images showed the visual change:
B/G ~= 1.10 - 1.116B/G ~= 1.05,R/G ~= 1.04The actual items can vary in color, so the strongest evidence is the visible tint shift plus the fact that restarting the stream restores the expected appearance while metadata remains identical.
Bad-State Frame Metadata
While the tint issue was present,
/corner_finder/camera/color/metadatareported:{ "actual_exposure": 7, "gain_level": 0, "auto_exposure": 0, "brightness": 0, "contrast": 50, "saturation": 31, "sharpness": 81, "auto_white_balance_temperature": 0, "manual_white_balance": 4550, "backlight_compensation": 0, "hue": 0, "gamma": 300, "power_line_frequency": 3, "low_light_compensation": 0 }Good-State Frame Metadata After Restart
After restarting the program / stream, the image looked correct again, but metadata was effectively identical:
{ "actual_exposure": 7, "gain_level": 0, "auto_exposure": 0, "brightness": 0, "contrast": 50, "saturation": 31, "sharpness": 81, "auto_white_balance_temperature": 0, "manual_white_balance": 4550, "backlight_compensation": 0, "hue": 0, "gamma": 300, "power_line_frequency": 3, "low_light_compensation": 0 }V4L2 State During Bad State
Direct V4L2 controls on the RGB node also looked correct:
D400 Advanced Mode State
We also queried D400 advanced mode using rs400::advanced_mode:
advanced_mode_enabled 1
color_control 0 0 0 0 0
color_correction 0.298828 0.293945 0.293945 0.114258 -0 -0 -0 -0 -0 -0 -0 -0
These values were the same in bad and good states.
So do you have any suggestions what I could try to get the white balance settings to stick?