···4242#define INITIAL_BRIGHTNESS 0.5
4343#define INITIAL_MAX_BRIGHTNESS_STEP 0.1
4444#define INITIAL_THRESHOLD 0.1
4545-#define GRID_COLS 40 //!< Amount of columns for the histogram sample grid
4545+#define GRID_COLS 32 //!< Amount of columns for the histogram sample grid
46464747//! AEG State machine states
4848enum u_aeg_state
+85-35
src/xrt/drivers/wmr/wmr_camera.c
···2424#include "util/u_frame.h"
2525#include "util/u_trace_marker.h"
26262727+#include "wmr_config.h"
2728#include "wmr_protocol.h"
2829#include "wmr_camera.h"
29303031//! Specifies whether the user wants to enable autoexposure from the start.
3132DEBUG_GET_ONCE_BOOL_OPTION(wmr_autoexposure, "WMR_AUTOEXPOSURE", true)
32333434+//! Specifies whether the user wants to use the same exp/gain values for all cameras
3535+DEBUG_GET_ONCE_BOOL_OPTION(wmr_unify_expgain, "WMR_UNIFY_EXPGAIN", false)
3636+3337static int
3434-update_expgain(struct wmr_camera *cam, struct xrt_frame *xf);
3838+update_expgain(struct wmr_camera *cam, struct xrt_frame **frames);
35393640/*
3741 *
···9710198102 struct libusb_transfer *xfers[NUM_XFERS];
99103100100- bool manual_control; //!< Whether to control exp/gain manually or with aeg
101101- uint16_t last_exposure, exposure;
102102- uint8_t last_gain, gain;
103103- struct u_var_draggable_u16 exposure_ui; //! Widget to control `exposure` value
104104- struct u_autoexpgain *aeg;
104104+ struct wmr_camera_expgain
105105+ {
106106+ bool manual_control; //!< Whether to control exp/gain manually or with aeg
107107+ uint16_t last_exposure, exposure;
108108+ uint8_t last_gain, gain;
109109+ struct u_var_draggable_u16 exposure_ui; //! Widget to control `exposure` value
110110+ struct u_autoexpgain *aeg;
111111+ } ceg[WMR_MAX_CAMERAS]; //!< Camera exposure-gain control
112112+ bool unify_expgains; //!< Whether to use the same exposure/gain values for all cameras
105113106114 struct u_sink_debug debug_sinks[2];
107115···370378 u_frame_create_roi(xf, cam->configs[0].roi, &xf_left);
371379 u_frame_create_roi(xf, cam->configs[1].roi, &xf_right);
372380373373- update_expgain(cam, xf_left);
381381+ struct xrt_frame *frames[WMR_MAX_CAMERAS] = {xf_left, xf_right, NULL, NULL};
382382+ update_expgain(cam, frames);
374383375384 if (cam->left_sink != NULL) {
376385 xrt_sink_push_frame(cam->left_sink, xf_left);
···401410wmr_camera_open(struct xrt_prober_device *dev_holo,
402411 struct xrt_frame_sink *left_sink,
403412 struct xrt_frame_sink *right_sink,
413413+ int camera_count,
404414 enum u_logging_level log_level)
405415{
406416 DRV_TRACE_MARKER();
···410420 int i;
411421412422 cam->log_level = log_level;
413413- cam->exposure = DEFAULT_EXPOSURE;
414414- cam->gain = DEFAULT_GAIN;
415423416424 if (os_thread_helper_init(&cam->usb_thread) != 0) {
417425 WMR_CAM_ERROR(cam, "Failed to initialise threading");
···450458451459 bool enable_aeg = debug_get_bool_option_wmr_autoexposure();
452460 int frame_delay = 3; // WMR takes about three frames until the cmd changes the image
453453- cam->aeg = u_autoexpgain_create(U_AEG_STRATEGY_TRACKING, enable_aeg, frame_delay);
461461+ cam->unify_expgains = debug_get_bool_option_wmr_unify_expgain();
454462455455- cam->exposure_ui.val = &cam->exposure;
456456- cam->exposure_ui.max = WMR_MAX_EXPOSURE;
457457- cam->exposure_ui.min = WMR_MIN_EXPOSURE;
458458- cam->exposure_ui.step = 25;
463463+ for (int i = 0; i < camera_count; i++) {
464464+ struct wmr_camera_expgain *ceg = &cam->ceg[i];
465465+ ceg->manual_control = false;
466466+ ceg->last_exposure = DEFAULT_EXPOSURE;
467467+ ceg->exposure = DEFAULT_EXPOSURE;
468468+ ceg->last_gain = DEFAULT_GAIN;
469469+ ceg->gain = DEFAULT_GAIN;
470470+ ceg->exposure_ui.val = &ceg->exposure;
471471+ ceg->exposure_ui.max = WMR_MAX_EXPOSURE;
472472+ ceg->exposure_ui.min = WMR_MIN_EXPOSURE;
473473+ ceg->exposure_ui.step = 25;
474474+ ceg->aeg = u_autoexpgain_create(U_AEG_STRATEGY_TRACKING, enable_aeg, frame_delay);
475475+ }
459476460477 u_sink_debug_init(&cam->debug_sinks[0]);
461478 u_sink_debug_init(&cam->debug_sinks[1]);
462479 u_var_add_root(cam, "WMR Camera", true);
463480 u_var_add_log_level(cam, &cam->log_level, "Log level");
464464- u_var_add_bool(cam, &cam->manual_control, "Manual exposure and gain control");
465465- u_var_add_draggable_u16(cam, &cam->exposure_ui, "Exposure (usec)");
466466- u_var_add_u8(cam, &cam->gain, "Gain");
467467- u_autoexpgain_add_vars(cam->aeg, cam, "");
468468- u_var_add_gui_header(cam, NULL, "Camera Streams");
481481+482482+ u_var_add_gui_header_begin(cam, NULL, "Camera Streams");
469483 u_var_add_sink_debug(cam, &cam->debug_sinks[0], "Tracking Streams");
470484 u_var_add_sink_debug(cam, &cam->debug_sinks[1], "Controller Streams");
485485+ u_var_add_gui_header_end(cam, NULL, NULL);
486486+487487+ u_var_add_gui_header_begin(cam, NULL, "Exposure and gain control");
488488+ u_var_add_bool(cam, &cam->unify_expgains, "Use same values");
489489+490490+ for (int i = 0; i < camera_count; i++) {
491491+ struct wmr_camera_expgain *ceg = &cam->ceg[i];
492492+ char label[256] = {0};
493493+494494+ (void)snprintf(label, sizeof(label), "Control for camera %d", i);
495495+ u_var_add_gui_header_begin(cam, NULL, label);
496496+497497+ (void)snprintf(label, sizeof(label), "[%d] Manual exposure and gain control", i);
498498+ u_var_add_bool(cam, &ceg->manual_control, label);
499499+500500+ (void)snprintf(label, sizeof(label), "[%d] Exposure (usec)", i);
501501+ u_var_add_draggable_u16(cam, &ceg->exposure_ui, label);
502502+503503+ (void)snprintf(label, sizeof(label), "[%d] Gain", i);
504504+ u_var_add_u8(cam, &ceg->gain, label);
505505+506506+ (void)snprintf(label, sizeof(label), "[%d] ", i);
507507+ u_autoexpgain_add_vars(ceg->aeg, cam, label);
508508+509509+ u_var_add_gui_header_end(cam, NULL, NULL);
510510+ }
511511+512512+ u_var_add_gui_header_end(cam, NULL, "Auto exposure and gain control END");
471513472514 cam->left_sink = left_sink;
473515 cam->right_sink = right_sink;
···614656}
615657616658static int
617617-update_expgain(struct wmr_camera *cam, struct xrt_frame *xf)
659659+update_expgain(struct wmr_camera *cam, struct xrt_frame **frames)
618660{
619619- if (!cam->manual_control && xf != NULL) {
620620- u_autoexpgain_update(cam->aeg, xf);
621621- cam->exposure = u_autoexpgain_get_exposure(cam->aeg);
622622- cam->gain = u_autoexpgain_get_gain(cam->aeg);
623623- }
624624-625625- if (cam->last_exposure == cam->exposure && cam->last_gain == cam->gain) {
626626- return 0;
627627- }
628628- cam->last_exposure = cam->exposure;
629629- cam->last_gain = cam->gain;
630630-631661 int res = 0;
632662 for (int i = 0; i < cam->config_count; i++) {
633663 const struct wmr_camera_config *config = &cam->configs[i];
634664 if (config->purpose != WMR_CAMERA_PURPOSE_HEAD_TRACKING) {
635665 continue;
636666 }
637637- res = wmr_camera_set_exposure_gain(cam, config->location, cam->exposure, cam->gain);
638638- if (res != 0) {
667667+668668+ struct wmr_camera_expgain *ceg = &cam->ceg[i];
669669+670670+ if (!ceg->manual_control && frames != NULL && frames[i] != NULL) {
671671+ if (!cam->unify_expgains || i == 0) {
672672+ u_autoexpgain_update(ceg->aeg, frames[i]);
673673+ ceg->exposure = (uint16_t)u_autoexpgain_get_exposure(ceg->aeg);
674674+ ceg->gain = (uint8_t)u_autoexpgain_get_gain(ceg->aeg);
675675+ } else {
676676+ ceg->exposure = cam->ceg[0].exposure;
677677+ ceg->gain = cam->ceg[0].gain;
678678+ }
679679+ }
680680+681681+ if (ceg->last_exposure == ceg->exposure && ceg->last_gain == ceg->gain) {
682682+ continue;
683683+ }
684684+ ceg->last_exposure = ceg->exposure;
685685+ ceg->last_gain = ceg->gain;
686686+687687+ bool status = wmr_camera_set_exposure_gain(cam, config->location, ceg->exposure, ceg->gain);
688688+ if (status != 0) {
639689 WMR_CAM_ERROR(cam, "Failed to set exposure and gain for camera %d", i);
640640- return res;
641690 }
691691+ res |= status;
642692 }
643693 return res;
644694}