strand_cam_storetype/lib.rs
1// Copyright (C) The Strand-Braid Authors
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! Type definitions for [Strand Camera's](https://strawlab.org/strand-cam)
5//! state management and browser UI communication.
6//!
7//! This crate provides core data structures that represent the complete state
8//! of a Strand Camera instance, including camera settings, recording status,
9//! feature detection configuration, and various processing modes. These types
10//! are primarily used for:
11//!
12//! - Serializing camera state for the web-based user interface
13//! - Managing recording sessions across different file formats
14//! - Configuring real-time image processing features
15//! - Coordinating LED control and Kalman tracking functionality
16//!
17//! ## Key Components
18//!
19//! - [`StoreType`]: The main state container for all camera configuration and
20//! status
21//! - Recording management for MP4, FMF, and UFMF formats
22//! - Feature detection and tracking configuration
23//! - LED control and triggering systems
24//! - AprilTag detection and checkerboard calibration support
25//!
26//! ## Communication
27//!
28//! The types in this crate support Server-Sent Events for real-time browser
29//! updates and remote camera control via HTTP APIs.
30
31// Copyright 2020-2023 Andrew D. Straw.
32//
33// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
34// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT
35// or http://opensource.org/licenses/MIT>, at your option. This file may not be
36// copied, modified, or distributed except according to those terms.
37
38#![warn(missing_docs)]
39use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
40
41use serde::{Deserialize, Serialize};
42use strand_cam_bui_types::RecordingPath;
43
44use strand_http_video_streaming_types::{CircleParams, Shape};
45
46use flydra_feature_detector_types::ImPtDetectCfg;
47use strand_cam_remote_control::{BitrateSelection, CodecSelection, RecordingFrameRate, TagFamily};
48
49/// A numeric value with associated metadata for user interface controls.
50///
51/// This structure represents camera parameters that have a current value within
52/// a defined range, along with human-readable name and units. It's commonly used
53/// for camera settings like gain, exposure time, and frame rate that can be
54/// adjusted through sliders or input controls in the web interface.
55///
56/// # Examples
57///
58/// ```rust
59/// use strand_cam_storetype::RangedValue;
60///
61/// let gain = RangedValue {
62/// name: "Gain".to_string(),
63/// unit: "dB".to_string(),
64/// current: 12.5,
65/// min: 0.0,
66/// max: 30.0,
67/// };
68/// ```
69#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
70#[serde(deny_unknown_fields)]
71pub struct RangedValue {
72 /// Human-readable name of the parameter (e.g., "Gain", "Exposure Time").
73 pub name: String,
74 /// Units of measurement (e.g., "dB", "ms", "fps").
75 pub unit: String,
76 /// Current value of the parameter.
77 pub current: f64,
78 /// Minimum allowed value.
79 pub min: f64,
80 /// Maximum allowed value.
81 pub max: f64,
82}
83
84use strand_led_box_comms::DeviceState;
85
86/// Commands that can be sent to LED control devices.
87///
88/// Re-exported from `strand_led_box_comms` for convenience.
89pub use strand_led_box_comms::ToDevice as ToLedBoxDevice;
90
91// Note: this does not start with a slash because we do not want an absolute
92// root path in case we are in a case where we are proxied by braid. I.e. it
93// should work at `http://braid/cam-proxy/cam-name/strand-cam-events` as well as
94// `http://strand-cam/strand-cam-events`.
95
96/// URL path for Strand Camera's Server-Sent Events endpoint.
97///
98/// This path is used to establish SSE connections for real-time updates
99/// from the camera to web browsers. The path is relative to support
100/// both direct connections and proxy scenarios through Braid.
101pub const STRAND_CAM_EVENTS_URL_PATH: &str = "strand-cam-events";
102
103/// Event name for Strand Camera SSE messages.
104///
105/// Used to identify camera state update events in the Server-Sent Events stream.
106pub const STRAND_CAM_EVENT_NAME: &str = "strand-cam";
107
108/// Event name for connection key SSE messages.
109///
110/// Used for session management and authentication in the browser interface.
111pub const CONN_KEY_EVENT_NAME: &str = "connection-key";
112
113/// Event name for the server-is-quitting SSE message.
114///
115/// Broadcast to every connected browser just before the server shuts down so
116/// that all clients (not only the one that initiated the quit) show the
117/// "Strand Camera has quit" screen and stop trying to reconnect.
118pub const STRAND_CAM_QUIT_EVENT_NAME: &str = "strand-cam-quit";
119
120/// Information about a newer available release of Strand Camera.
121///
122/// Populated by the background version check when the version-check server
123/// reports a version newer than the running one. Surfaced to every connected
124/// browser as a dismissible banner.
125#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
126#[serde(deny_unknown_fields)]
127pub struct VersionUpdate {
128 /// The newest available version as a semver string, e.g. `"1.0.0-rc.3"`.
129 pub available: String,
130 /// Human-readable message from the version-check server.
131 pub message: String,
132 /// URL with release notes / downloads, rendered as a link.
133 pub url: String,
134}
135
136/// Complete state representation of a Strand Camera instance.
137///
138/// This is the primary data structure that encapsulates all configuration,
139/// status, and capability information for a running camera. It includes
140/// everything from basic camera settings to complex processing features
141/// like object detection, Kalman tracking, and AprilTag recognition.
142///
143/// The structure is designed to be serialized and sent to web browsers
144/// for real-time monitoring and control of the camera system.
145///
146/// # Feature Compilation
147///
148/// Many fields are conditional based on compile-time features:
149/// - `has_image_tracker_compiled`: Object detection capabilities
150/// - `has_flydratrax_compiled`: Kalman tracking and LED control
151/// - `has_checkercal_compiled`: Checkerboard calibration
152/// - `apriltag_state`: AprilTag detection (None if not compiled)
153#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
154#[serde(deny_unknown_fields)]
155pub struct StoreType {
156 /// Whether we are running inside Braid.
157 pub is_braid: bool,
158 /// What version of ffmpeg is available to Strand Camera
159 pub ffmpeg_version: Option<String>,
160 /// Whether we have Nvidia NvEnc encoder available.
161 pub is_nvenc_functioning: bool,
162 /// Whether we have VideoToolbox
163 pub is_videotoolbox_functioning: bool,
164 /// is saving MP4 file
165 pub is_recording_mp4: Option<RecordingPath>,
166 /// is saving FMF file
167 pub is_recording_fmf: Option<RecordingPath>,
168 /// is saving UFMF file
169 pub is_recording_ufmf: Option<RecordingPath>,
170 /// Format string template for MP4 filenames.
171 pub format_str_mp4: String,
172 /// Format string template for FMF filenames.
173 pub format_str: String,
174 /// Format string template for UFMF filenames.
175 pub format_str_ufmf: String,
176 /// Name of the camera device.
177 pub camera_name: String,
178 /// Current gamma correction value applied to the camera.
179 pub camera_gamma: Option<f32>,
180 /// Base filename for recordings (without extension).
181 pub recording_filename: Option<String>,
182 /// Maximum frame rate for MP4 recording.
183 pub mp4_max_framerate: RecordingFrameRate,
184 // pub mp4_recording_config: Mp4RecordingConfig,
185 /// Bitrate selection for MP4 encoding.
186 pub mp4_bitrate: BitrateSelection,
187 /// Video codec selection for MP4 encoding.
188 pub mp4_codec: CodecSelection,
189 /// CUDA device number (only used if using nvidia encoder)
190 pub mp4_cuda_device: String,
191 /// Automatic gain control mode.
192 pub gain_auto: Option<strand_cam_types::AutoMode>,
193 /// Camera gain settings and range.
194 pub gain: RangedValue,
195 /// Automatic exposure control mode.
196 pub exposure_auto: Option<strand_cam_types::AutoMode>,
197 /// Camera exposure time settings and range.
198 pub exposure_time: RangedValue,
199 /// Whether software frame rate limiting is enabled.
200 pub frame_rate_limit_enabled: bool,
201 /// None when frame_rate_limit is not supported
202 pub frame_rate_limit: Option<RangedValue>,
203 /// Camera trigger mode (internal, external, etc.).
204 pub trigger_mode: strand_cam_types::TriggerMode,
205 /// Which trigger input to use.
206 pub trigger_selector: strand_cam_types::TriggerSelector,
207 /// Width of captured images in pixels.
208 pub image_width: u32,
209 /// Height of captured images in pixels.
210 pub image_height: u32,
211 /// Whether object detection with image-tracker crate is compiled.
212 // We could have made this a cargo feature, but this
213 // adds complication to the builds. Here, the cost
214 // is some extra unused code paths in the compiled
215 // code, as well as larger serialized objects.
216 pub has_image_tracker_compiled: bool,
217 // used only with image-tracker crate
218 /// Whether object detection is currently used.
219 pub is_doing_object_detection: bool,
220 /// Current measured frame rate in frames per second.
221 pub measured_fps: f32,
222 /// is saving object detection CSV file
223 pub is_saving_im_pt_detect_csv: Option<RecordingPath>,
224 // used only with image-tracker crate
225 /// Configuration for image point detection algorithms.
226 pub im_pt_detect_cfg: ImPtDetectCfg,
227 /// Whether flydratrax (2D kalman tracking and LED triggering) is compiled.
228 pub has_flydratrax_compiled: bool,
229 /// Configuration for Kalman tracking of detected objects.
230 pub kalman_tracking_config: KalmanTrackingConfig,
231 /// Configuration for LED control and triggering.
232 pub led_program_config: LedProgramConfig,
233 /// Whether connection to LED control device has been lost.
234 pub led_box_device_lost: bool,
235 /// Current state of the LED control device.
236 pub led_box_device_state: Option<DeviceState>,
237 /// Path to the LED control device.
238 pub led_box_device_path: Option<String>,
239 /// Whether checkerboard calibration is compiled.
240 pub has_checkercal_compiled: bool,
241 /// Current state of checkerboard calibration process.
242 pub checkerboard_data: CheckerboardCalState,
243 /// Path where debug data is being saved.
244 pub checkerboard_save_debug: Option<String>,
245 /// Number of frames to buffer for post-trigger recording.
246 pub post_trigger_buffer_size: usize,
247 /// List of available CUDA devices for hardware acceleration.
248 pub cuda_devices: Vec<String>,
249 /// This is None if no apriltag support is compiled in. Otherwise Some(_).
250 pub apriltag_state: Option<ApriltagState>,
251 /// State of image operations processing.
252 pub im_ops_state: ImOpsState,
253 /// Format string template for AprilTag CSV filenames.
254 pub format_str_apriltag_csv: String,
255 /// Whether there was an error during frame processing.
256 pub had_frame_processing_error: bool,
257 /// The camera calibration (does not contain potential information about water)
258 pub camera_calibration: Option<braid_mvg::Camera<f64>>,
259 /// A newer available release discovered by the background version check, or
260 /// `None` if up to date (or the check has not yet found a newer version).
261 pub version_update: Option<VersionUpdate>,
262}
263
264/// State and configuration of AprilTag detection.
265///
266/// AprilTags are fiducial markers that can be detected in images for
267/// tracking and localization purposes. This structure controls whether
268/// detection is enabled and manages recording of detection results.
269#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Default)]
270#[serde(deny_unknown_fields)]
271pub struct ApriltagState {
272 /// Whether AprilTag detection is currently enabled.
273 pub do_detection: bool,
274 /// Which AprilTag family to detect (e.g., tag36h11, tag25h9).
275 pub april_family: TagFamily,
276 /// Path where AprilTag detection results are being saved to CSV.
277 pub is_recording_csv: Option<RecordingPath>,
278}
279
280/// Configuration for image operations and UDP data streaming.
281///
282/// This structure configures real-time image processing that detects
283/// features and streams results over UDP to external applications.
284/// It's used for low-latency tracking applications where processed
285/// data needs to be sent immediately to other systems.
286#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
287#[serde(deny_unknown_fields)]
288pub struct ImOpsState {
289 /// Whether image operations detection is enabled.
290 pub do_detection: bool,
291 /// UDP socket address where detection results are sent.
292 pub destination: SocketAddr,
293 /// The IP address of the socket interface from which the data is sent.
294 pub source: IpAddr,
295 /// X coordinate of the region center for detection.
296 pub center_x: u32,
297 /// Y coordinate of the region center for detection.
298 pub center_y: u32,
299 /// Intensity threshold for feature detection.
300 pub threshold: u8,
301}
302
303impl Default for ImOpsState {
304 fn default() -> Self {
305 Self {
306 do_detection: false,
307 destination: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)),
308 source: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
309 center_x: 0,
310 center_y: 0,
311 threshold: 0,
312 }
313 }
314}
315
316/// Default filename template for AprilTag CSV recordings.
317///
318/// This template includes timestamp formatting and camera name substitution:
319/// - `%Y%m%d_%H%M%S.%f`: Date and time with microseconds
320/// - `{CAMNAME}`: Replaced with actual camera name
321/// - `.csv.gz`: Compressed CSV format
322pub const APRILTAG_CSV_TEMPLATE_DEFAULT: &str = "apriltags%Y%m%d_%H%M%S.%f_{CAMNAME}.csv.gz";
323
324/// LED triggering modes for controlling external lighting.
325///
326/// This enum determines how LED lighting systems are controlled
327/// in response to tracked object positions.
328#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
329#[serde(deny_unknown_fields)]
330pub enum LEDTriggerMode {
331 /// LEDs remain in a constant state (off or on).
332 Off, // could probably be better named "Unchanging" or "Constant"
333 /// LEDs are triggered based on tracked object positions.
334 PositionTriggered,
335}
336
337/// Configuration for Kalman filter-based object tracking.
338///
339/// This structure configures 2D tracking of objects detected in the camera
340/// image using Kalman filtering. It's designed for tracking small objects
341/// like insects or particles within a defined arena.
342///
343/// # Usage
344///
345/// Typically used in behavioral experiments where objects need to be
346/// tracked continuously for triggering responses or data collection.
347#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
348#[serde(deny_unknown_fields)]
349pub struct KalmanTrackingConfig {
350 /// Whether Kalman tracking is currently enabled.
351 pub enabled: bool,
352 /// Diameter of the tracking arena in meters.
353 ///
354 /// Used to scale tracking parameters and validate object positions.
355 pub arena_diameter_meters: f32,
356 /// Minimum central moment required for object detection.
357 ///
358 /// Objects with central moments below this threshold are ignored.
359 /// This helps filter out noise and very small detections.
360 pub min_central_moment: f32,
361}
362
363impl std::default::Default for KalmanTrackingConfig {
364 fn default() -> Self {
365 Self {
366 enabled: true,
367 arena_diameter_meters: 0.2,
368 min_central_moment: 0.0,
369 }
370 }
371}
372
373/// Configuration for LED control and position-based triggering.
374///
375/// This structure defines how external LED lighting responds to
376/// tracked object positions. It supports triggering LEDs when
377/// objects enter or exit defined regions of interest.
378///
379/// # Two-Stage Triggering
380///
381/// The system supports a two-stage approach:
382/// 1. Initial trigger when object enters `led_on_shape_pixels`
383/// 2. Secondary trigger based on `led_second_stage_radius`
384/// 3. Hysteresis prevents rapid on/off switching
385#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
386#[serde(deny_unknown_fields)]
387pub struct LedProgramConfig {
388 /// How LEDs should respond to object positions.
389 pub led_trigger_mode: LEDTriggerMode,
390 /// Geometric shape that defines the LED trigger region.
391 pub led_on_shape_pixels: Shape,
392 /// Which LED channel to control (for multi-channel LED systems).
393 pub led_channel_num: u8,
394 /// Radius for second-stage LED triggering logic.
395 pub led_second_stage_radius: u16,
396 /// Hysteresis distance in pixels to prevent rapid switching.
397 ///
398 /// Objects must move this distance before triggering state changes,
399 /// preventing flickering when objects are near trigger boundaries.
400 pub led_hysteresis_pixels: f32,
401}
402
403impl std::default::Default for LedProgramConfig {
404 fn default() -> Self {
405 Self {
406 led_trigger_mode: LEDTriggerMode::Off,
407 led_channel_num: 1,
408 led_on_shape_pixels: Shape::Circle(CircleParams {
409 center_x: 640,
410 center_y: 512,
411 radius: 50,
412 }),
413 led_second_stage_radius: 50,
414 led_hysteresis_pixels: 3.0,
415 }
416 }
417}
418
419/// State of checkerboard camera calibration process.
420///
421/// Checkerboard calibration is used to determine camera intrinsic parameters
422/// (focal length, principal point, distortion) by detecting checkerboard
423/// patterns at different positions and orientations.
424///
425/// # Calibration Process
426///
427/// 1. Enable checkerboard detection
428/// 2. Present checkerboard patterns to the camera
429/// 3. System automatically detects and collects pattern data
430/// 4. Once enough patterns are collected, calibration can be computed
431#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
432#[serde(deny_unknown_fields)]
433pub struct CheckerboardCalState {
434 /// Whether checkerboard detection and collection is enabled.
435 pub enabled: bool,
436 /// Number of valid checkerboard patterns collected so far.
437 pub num_checkerboards_collected: u32,
438 /// Number of internal corners along the width of the checkerboard.
439 pub width: u32,
440 /// Number of internal corners along the height of the checkerboard.
441 pub height: u32,
442}
443
444impl Default for CheckerboardCalState {
445 fn default() -> Self {
446 Self {
447 enabled: false,
448 num_checkerboards_collected: 0,
449 width: 8,
450 height: 6,
451 }
452 }
453}
454
455/// Commands and callbacks that can be sent to control camera behavior.
456///
457/// This enum represents different types of control messages that can be
458/// sent to modify camera settings, trigger actions, or control peripheral
459/// devices like LED systems.
460///
461/// # Usage
462///
463/// These callbacks are typically sent from the web interface or external
464/// control systems to modify camera behavior in real-time.
465#[derive(Debug, Serialize, Deserialize, Clone)]
466#[serde(deny_unknown_fields)]
467pub enum CallbackType {
468 /// Camera control commands (exposure, gain, triggering, etc.).
469 ToCamera(strand_cam_remote_control::CamArg),
470 /// Notification for firehose data streaming connections.
471 FirehoseNotify(strand_bui_backend_session_types::ConnectionKey),
472 // used only with image-tracker crate
473 /// Re-initialize the background model from the currently incoming images.
474 ///
475 /// Used for background subtraction in object detection algorithms.
476 TakeCurrentImageAsBackground,
477 // used only with image-tracker crate
478 /// Set the background model to a uniform image with the given pixel value.
479 ///
480 /// The value is the gray level (0-255) assigned to every pixel of the
481 /// background mean; the model variance is set to zero. The browser UI's
482 /// "Set background to mid-gray" button sends 127.0.
483 ClearBackground(f32),
484 /// Commands to send to LED control devices.
485 ToLedBox(ToLedBoxDevice),
486}