Add gain control support to IDS uEye camera driver
- Added 'gain' property to gstidsueyesrc element (0-100, 0=auto) - Implemented hardware gain control using is_SetHardwareGain() API - Added --gain/-g command-line argument to launch-ids.py - Added SET_GAIN and GET_GAIN UDP control commands - Updated STATUS command to include gain value - Added get-gain and set-gain commands to camera_control.py test client - Gain can be set at startup or adjusted dynamically during runtime
This commit is contained in:
parent
e09938a5a1
commit
acbd8ec416
@ -13,6 +13,8 @@ Usage:
|
|||||||
uv run scripts/camera_control.py set-exposure 10 # Set exposure to 10ms
|
uv run scripts/camera_control.py set-exposure 10 # Set exposure to 10ms
|
||||||
uv run scripts/camera_control.py get-framerate # Get current framerate
|
uv run scripts/camera_control.py get-framerate # Get current framerate
|
||||||
uv run scripts/camera_control.py set-framerate 30 # Set framerate to 30fps
|
uv run scripts/camera_control.py set-framerate 30 # Set framerate to 30fps
|
||||||
|
uv run scripts/camera_control.py get-gain # Get current gain
|
||||||
|
uv run scripts/camera_control.py set-gain 50 # Set gain to 50
|
||||||
uv run scripts/camera_control.py status # Get pipeline status
|
uv run scripts/camera_control.py status # Get pipeline status
|
||||||
|
|
||||||
This script provides both individual control commands and full test suite functionality
|
This script provides both individual control commands and full test suite functionality
|
||||||
@ -178,6 +180,8 @@ Examples:
|
|||||||
%(prog)s set-exposure 10 # Set exposure to 10ms
|
%(prog)s set-exposure 10 # Set exposure to 10ms
|
||||||
%(prog)s get-framerate # Get current framerate
|
%(prog)s get-framerate # Get current framerate
|
||||||
%(prog)s set-framerate 30 # Set framerate to 30fps
|
%(prog)s set-framerate 30 # Set framerate to 30fps
|
||||||
|
%(prog)s get-gain # Get current gain
|
||||||
|
%(prog)s set-gain 50 # Set gain to 50
|
||||||
%(prog)s status # Get pipeline status
|
%(prog)s status # Get pipeline status
|
||||||
""",
|
""",
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||||
@ -185,7 +189,8 @@ Examples:
|
|||||||
|
|
||||||
parser.add_argument('command',
|
parser.add_argument('command',
|
||||||
nargs='?',
|
nargs='?',
|
||||||
choices=['test', 'get-exposure', 'set-exposure', 'get-framerate', 'set-framerate', 'status'],
|
choices=['test', 'get-exposure', 'set-exposure', 'get-framerate', 'set-framerate',
|
||||||
|
'get-gain', 'set-gain', 'status'],
|
||||||
help='Command to execute')
|
help='Command to execute')
|
||||||
|
|
||||||
parser.add_argument('value',
|
parser.add_argument('value',
|
||||||
@ -239,6 +244,21 @@ Examples:
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
success = simple_command(f"SET_FRAMERATE {args.value}", f"Setting framerate to {args.value}fps")
|
success = simple_command(f"SET_FRAMERATE {args.value}", f"Setting framerate to {args.value}fps")
|
||||||
|
|
||||||
|
elif args.command == 'get-gain':
|
||||||
|
success = simple_command("GET_GAIN", "Getting current gain")
|
||||||
|
|
||||||
|
elif args.command == 'set-gain':
|
||||||
|
if args.value is None:
|
||||||
|
print("Error: set-gain requires a value (0-100, 0 for auto)")
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
# Convert to int for gain
|
||||||
|
gain_value = int(args.value)
|
||||||
|
if gain_value < 0 or gain_value > 100:
|
||||||
|
print("Error: Gain must be between 0 and 100 (0 for auto)")
|
||||||
|
sys.exit(1)
|
||||||
|
success = simple_command(f"SET_GAIN {gain_value}", f"Setting gain to {gain_value}")
|
||||||
|
|
||||||
elif args.command == 'status':
|
elif args.command == 'status':
|
||||||
success = simple_command("STATUS", "Getting pipeline status")
|
success = simple_command("STATUS", "Getting pipeline status")
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,8 @@
|
|||||||
# GET_CAMERA_ID - Get current camera ID
|
# GET_CAMERA_ID - Get current camera ID
|
||||||
# SET_DEVICE_ID <value> - Set device ID (0-254, system enumeration)
|
# SET_DEVICE_ID <value> - Set device ID (0-254, system enumeration)
|
||||||
# GET_DEVICE_ID - Get current device ID
|
# GET_DEVICE_ID - Get current device ID
|
||||||
|
# SET_GAIN <value> - Set master gain (0-100, 0 for auto)
|
||||||
|
# GET_GAIN - Get current gain value
|
||||||
# STATUS - Get pipeline status and current settings
|
# STATUS - Get pipeline status and current settings
|
||||||
#
|
#
|
||||||
# Example Control Usage:
|
# Example Control Usage:
|
||||||
@ -131,7 +133,8 @@ class ControlServer:
|
|||||||
|
|
||||||
print(f"Control server listening on UDP port {self.port}")
|
print(f"Control server listening on UDP port {self.port}")
|
||||||
print(" Commands: SET_EXPOSURE <val>, GET_EXPOSURE, SET_FRAMERATE <val>, GET_FRAMERATE,")
|
print(" Commands: SET_EXPOSURE <val>, GET_EXPOSURE, SET_FRAMERATE <val>, GET_FRAMERATE,")
|
||||||
print(" SET_CAMERA_ID <val>, GET_CAMERA_ID, SET_DEVICE_ID <val>, GET_DEVICE_ID, STATUS")
|
print(" SET_CAMERA_ID <val>, GET_CAMERA_ID, SET_DEVICE_ID <val>, GET_DEVICE_ID,")
|
||||||
|
print(" SET_GAIN <val>, GET_GAIN, STATUS")
|
||||||
|
|
||||||
while self.running:
|
while self.running:
|
||||||
try:
|
try:
|
||||||
@ -185,6 +188,10 @@ class ControlServer:
|
|||||||
return self.handle_set_device_id(parts)
|
return self.handle_set_device_id(parts)
|
||||||
elif cmd == "GET_DEVICE_ID":
|
elif cmd == "GET_DEVICE_ID":
|
||||||
return self.handle_get_device_id()
|
return self.handle_get_device_id()
|
||||||
|
elif cmd == "SET_GAIN":
|
||||||
|
return self.handle_set_gain(parts)
|
||||||
|
elif cmd == "GET_GAIN":
|
||||||
|
return self.handle_get_gain()
|
||||||
elif cmd == "STATUS":
|
elif cmd == "STATUS":
|
||||||
return self.handle_status()
|
return self.handle_status()
|
||||||
else:
|
else:
|
||||||
@ -302,6 +309,33 @@ class ControlServer:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"ERROR: {str(e)}"
|
return f"ERROR: {str(e)}"
|
||||||
|
|
||||||
|
def handle_set_gain(self, parts):
|
||||||
|
"""Handle SET_GAIN command"""
|
||||||
|
if len(parts) != 2:
|
||||||
|
return "ERROR INVALID_SYNTAX: Usage: SET_GAIN <value>"
|
||||||
|
|
||||||
|
try:
|
||||||
|
value = int(parts[1])
|
||||||
|
if value < 0 or value > 100:
|
||||||
|
return "ERROR OUT_OF_RANGE: Gain must be 0-100 (0 for auto)"
|
||||||
|
|
||||||
|
self.src.set_property("gain", value)
|
||||||
|
actual = self.src.get_property("gain")
|
||||||
|
return f"OK {actual}"
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
return "ERROR INVALID_SYNTAX: Gain must be an integer"
|
||||||
|
except Exception as e:
|
||||||
|
return f"ERROR: {str(e)}"
|
||||||
|
|
||||||
|
def handle_get_gain(self):
|
||||||
|
"""Handle GET_GAIN command"""
|
||||||
|
try:
|
||||||
|
value = self.src.get_property("gain")
|
||||||
|
return f"OK {value}"
|
||||||
|
except Exception as e:
|
||||||
|
return f"ERROR: {str(e)}"
|
||||||
|
|
||||||
def handle_status(self):
|
def handle_status(self):
|
||||||
"""Handle STATUS command"""
|
"""Handle STATUS command"""
|
||||||
try:
|
try:
|
||||||
@ -309,6 +343,7 @@ class ControlServer:
|
|||||||
framerate = self.src.get_property("framerate")
|
framerate = self.src.get_property("framerate")
|
||||||
camera_id = self.src.get_property("camera-id")
|
camera_id = self.src.get_property("camera-id")
|
||||||
device_id = self.src.get_property("device-id")
|
device_id = self.src.get_property("device-id")
|
||||||
|
gain = self.src.get_property("gain")
|
||||||
|
|
||||||
# Get pipeline state
|
# Get pipeline state
|
||||||
state = "UNKNOWN"
|
state = "UNKNOWN"
|
||||||
@ -316,7 +351,7 @@ class ControlServer:
|
|||||||
_, current_state, _ = self.pipeline.get_state(0)
|
_, current_state, _ = self.pipeline.get_state(0)
|
||||||
state = current_state.value_nick.upper()
|
state = current_state.value_nick.upper()
|
||||||
|
|
||||||
return f"OK exposure={exposure} framerate={framerate} camera_id={camera_id} device_id={device_id} state={state}"
|
return f"OK exposure={exposure} framerate={framerate} camera_id={camera_id} device_id={device_id} gain={gain} state={state}"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"ERROR: {str(e)}"
|
return f"ERROR: {str(e)}"
|
||||||
|
|
||||||
@ -382,6 +417,13 @@ Examples:
|
|||||||
metavar='ID',
|
metavar='ID',
|
||||||
help='Device ID (system enumeration, 0 is first, 0-254)'
|
help='Device ID (system enumeration, 0 is first, 0-254)'
|
||||||
)
|
)
|
||||||
|
camera_group.add_argument(
|
||||||
|
'--gain', '-g',
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
metavar='GAIN',
|
||||||
|
help='Master gain (0-100, 0 for auto/default)'
|
||||||
|
)
|
||||||
|
|
||||||
# Video processing
|
# Video processing
|
||||||
video_group = parser.add_argument_group('Video Processing')
|
video_group = parser.add_argument_group('Video Processing')
|
||||||
@ -470,6 +512,9 @@ Examples:
|
|||||||
if args.device_id < 0 or args.device_id > 254:
|
if args.device_id < 0 or args.device_id > 254:
|
||||||
parser.error(f"Device ID must be between 0 and 254, got {args.device_id}")
|
parser.error(f"Device ID must be between 0 and 254, got {args.device_id}")
|
||||||
|
|
||||||
|
if args.gain < 0 or args.gain > 100:
|
||||||
|
parser.error(f"Gain must be between 0 and 100, got {args.gain}")
|
||||||
|
|
||||||
if args.port < 1 or args.port > 65535:
|
if args.port < 1 or args.port > 65535:
|
||||||
parser.error(f"UDP port must be between 1 and 65535, got {args.port}")
|
parser.error(f"UDP port must be between 1 and 65535, got {args.port}")
|
||||||
|
|
||||||
@ -528,6 +573,9 @@ src.set_property("framerate", args.framerate)
|
|||||||
src.set_property("camera-id", args.camera_id)
|
src.set_property("camera-id", args.camera_id)
|
||||||
src.set_property("device-id", args.device_id)
|
src.set_property("device-id", args.device_id)
|
||||||
|
|
||||||
|
# Gain (0 for auto/default)
|
||||||
|
src.set_property("gain", args.gain)
|
||||||
|
|
||||||
# Video crop to remove bottom pixels (if enabled)
|
# Video crop to remove bottom pixels (if enabled)
|
||||||
elements_to_link = [src]
|
elements_to_link = [src]
|
||||||
if args.crop_bottom > 0:
|
if args.crop_bottom > 0:
|
||||||
@ -671,6 +719,7 @@ if not args.quiet:
|
|||||||
print(f"Device ID: {args.device_id}")
|
print(f"Device ID: {args.device_id}")
|
||||||
print(f"Exposure: {args.exposure} ms")
|
print(f"Exposure: {args.exposure} ms")
|
||||||
print(f"Framerate: {args.framerate} Hz")
|
print(f"Framerate: {args.framerate} Hz")
|
||||||
|
print(f"Gain: {args.gain} (0=auto)")
|
||||||
if args.crop_bottom > 0:
|
if args.crop_bottom > 0:
|
||||||
print(f"Crop bottom: {args.crop_bottom} pixels")
|
print(f"Crop bottom: {args.crop_bottom} pixels")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -73,7 +73,8 @@ enum
|
|||||||
PROP_NUM_CAPTURE_BUFFERS,
|
PROP_NUM_CAPTURE_BUFFERS,
|
||||||
PROP_TIMEOUT,
|
PROP_TIMEOUT,
|
||||||
PROP_EXPOSURE,
|
PROP_EXPOSURE,
|
||||||
PROP_FRAMERATE
|
PROP_FRAMERATE,
|
||||||
|
PROP_GAIN
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_PROP_CAMERA_ID 0
|
#define DEFAULT_PROP_CAMERA_ID 0
|
||||||
@ -83,6 +84,7 @@ enum
|
|||||||
#define DEFAULT_PROP_TIMEOUT 1000
|
#define DEFAULT_PROP_TIMEOUT 1000
|
||||||
#define DEFAULT_PROP_EXPOSURE 0
|
#define DEFAULT_PROP_EXPOSURE 0
|
||||||
#define DEFAULT_PROP_FRAMERATE 0
|
#define DEFAULT_PROP_FRAMERATE 0
|
||||||
|
#define DEFAULT_PROP_GAIN 0
|
||||||
|
|
||||||
/* pad templates */
|
/* pad templates */
|
||||||
|
|
||||||
@ -162,6 +164,11 @@ gst_idsueyesrc_class_init (GstIdsueyeSrcClass * klass)
|
|||||||
"Framerate in frames per second", 0, G_MAXDOUBLE,
|
"Framerate in frames per second", 0, G_MAXDOUBLE,
|
||||||
DEFAULT_PROP_FRAMERATE,
|
DEFAULT_PROP_FRAMERATE,
|
||||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_GAIN,
|
||||||
|
g_param_spec_int ("gain", "Master Gain",
|
||||||
|
"Master gain (0-100, 0 for auto)", 0, 100,
|
||||||
|
DEFAULT_PROP_GAIN,
|
||||||
|
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -196,6 +203,7 @@ gst_idsueyesrc_init (GstIdsueyeSrc * src)
|
|||||||
src->timeout = DEFAULT_PROP_TIMEOUT;
|
src->timeout = DEFAULT_PROP_TIMEOUT;
|
||||||
src->exposure = DEFAULT_PROP_EXPOSURE;
|
src->exposure = DEFAULT_PROP_EXPOSURE;
|
||||||
src->framerate = DEFAULT_PROP_FRAMERATE;
|
src->framerate = DEFAULT_PROP_FRAMERATE;
|
||||||
|
src->gain = DEFAULT_PROP_GAIN;
|
||||||
|
|
||||||
src->stop_requested = FALSE;
|
src->stop_requested = FALSE;
|
||||||
src->caps = NULL;
|
src->caps = NULL;
|
||||||
@ -240,6 +248,17 @@ gst_idsueyesrc_set_property (GObject * object, guint property_id,
|
|||||||
gst_idsueyesrc_set_framerate_exposure (src);
|
gst_idsueyesrc_set_framerate_exposure (src);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PROP_GAIN:
|
||||||
|
src->gain = g_value_get_int (value);
|
||||||
|
if (src->is_started) {
|
||||||
|
INT ret = is_SetHardwareGain (src->hCam, src->gain, IS_IGNORE_PARAMETER,
|
||||||
|
IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER);
|
||||||
|
if (ret != IS_SUCCESS) {
|
||||||
|
GST_WARNING_OBJECT (src, "Failed to set gain to %d (error %d)",
|
||||||
|
src->gain, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -277,6 +296,9 @@ gst_idsueyesrc_get_property (GObject * object, guint property_id,
|
|||||||
case PROP_FRAMERATE:
|
case PROP_FRAMERATE:
|
||||||
g_value_set_double (value, src->framerate);
|
g_value_set_double (value, src->framerate);
|
||||||
break;
|
break;
|
||||||
|
case PROP_GAIN:
|
||||||
|
g_value_set_int (value, src->gain);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -911,6 +933,17 @@ gst_idsueyesrc_set_framerate_exposure (GstIdsueyeSrc * src)
|
|||||||
success = FALSE;
|
success = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set gain if specified (0 means use default/auto) */
|
||||||
|
if (src->gain > 0) {
|
||||||
|
ret = is_SetHardwareGain (src->hCam, src->gain, IS_IGNORE_PARAMETER,
|
||||||
|
IS_IGNORE_PARAMETER, IS_IGNORE_PARAMETER);
|
||||||
|
if (ret != IS_SUCCESS) {
|
||||||
|
GST_WARNING_OBJECT (src, "Failed to set gain to %d (error %d)",
|
||||||
|
src->gain, ret);
|
||||||
|
success = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,7 @@ struct _GstIdsueyeSrc
|
|||||||
gint timeout;
|
gint timeout;
|
||||||
gdouble exposure;
|
gdouble exposure;
|
||||||
gdouble framerate;
|
gdouble framerate;
|
||||||
|
gint gain;
|
||||||
|
|
||||||
GstClockTime acq_start_time;
|
GstClockTime acq_start_time;
|
||||||
guint32 last_frame_count;
|
guint32 last_frame_count;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user