Files
wifi-densepose/crates/ruvector-nervous-system/src/eventbus/event.rs
ruv d803bfe2b1 Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
2026-02-28 14:39:40 -05:00

218 lines
5.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Event Types and Trait Definitions
//!
//! Implements DVS (Dynamic Vision Sensor) events and sparse event surfaces.
use std::sync::atomic::{AtomicU64, Ordering};
/// Core event trait for timestamped event streams
pub trait Event: Send + Sync {
/// Get event timestamp (microseconds)
fn timestamp(&self) -> u64;
/// Get source identifier (e.g., pixel coordinate hash)
fn source_id(&self) -> u16;
/// Get event payload/data
fn payload(&self) -> u32;
}
/// Dynamic Vision Sensor event
///
/// Represents a single event from a DVS camera or general event source.
/// Typically 10-1000× more efficient than frame-based data.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct DVSEvent {
/// Event timestamp in microseconds
pub timestamp: u64,
/// Source identifier (e.g., pixel index or sensor ID)
pub source_id: u16,
/// Payload data (application-specific)
pub payload_id: u32,
/// Polarity (on/off, increase/decrease)
pub polarity: bool,
/// Optional confidence score
pub confidence: Option<f32>,
}
impl Event for DVSEvent {
#[inline]
fn timestamp(&self) -> u64 {
self.timestamp
}
#[inline]
fn source_id(&self) -> u16 {
self.source_id
}
#[inline]
fn payload(&self) -> u32 {
self.payload_id
}
}
impl DVSEvent {
/// Create a new DVS event
pub fn new(timestamp: u64, source_id: u16, payload_id: u32, polarity: bool) -> Self {
Self {
timestamp,
source_id,
payload_id,
polarity,
confidence: None,
}
}
/// Create event with confidence score
pub fn with_confidence(mut self, confidence: f32) -> Self {
self.confidence = Some(confidence);
self
}
}
/// Sparse event surface for tracking last event per source
///
/// Efficiently tracks active events across a 2D surface (e.g., DVS camera pixels)
/// using atomic operations for lock-free updates.
pub struct EventSurface {
surface: Vec<AtomicU64>,
width: usize,
height: usize,
}
impl EventSurface {
/// Create new event surface
pub fn new(width: usize, height: usize) -> Self {
let size = width * height;
let mut surface = Vec::with_capacity(size);
for _ in 0..size {
surface.push(AtomicU64::new(0));
}
Self {
surface,
width,
height,
}
}
/// Update surface with new event
#[inline]
pub fn update(&self, event: &DVSEvent) {
let idx = event.source_id as usize;
if idx < self.surface.len() {
self.surface[idx].store(event.timestamp, Ordering::Relaxed);
}
}
/// Get all events that occurred since timestamp
pub fn get_active_events(&self, since: u64) -> Vec<(usize, usize, u64)> {
let mut active = Vec::new();
for (idx, timestamp_atom) in self.surface.iter().enumerate() {
let timestamp = timestamp_atom.load(Ordering::Relaxed);
if timestamp > since {
let x = idx % self.width;
let y = idx / self.width;
active.push((x, y, timestamp));
}
}
active
}
/// Get timestamp at specific coordinate
pub fn get_timestamp(&self, x: usize, y: usize) -> Option<u64> {
if x < self.width && y < self.height {
let idx = y * self.width + x;
Some(self.surface[idx].load(Ordering::Relaxed))
} else {
None
}
}
/// Clear all events
pub fn clear(&self) {
for atom in &self.surface {
atom.store(0, Ordering::Relaxed);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dvs_event_creation() {
let event = DVSEvent::new(1000, 42, 123, true);
assert_eq!(event.timestamp(), 1000);
assert_eq!(event.source_id(), 42);
assert_eq!(event.payload(), 123);
assert_eq!(event.polarity, true);
assert_eq!(event.confidence, None);
}
#[test]
fn test_dvs_event_with_confidence() {
let event = DVSEvent::new(1000, 42, 123, false).with_confidence(0.95);
assert_eq!(event.confidence, Some(0.95));
}
#[test]
fn test_event_surface_update() {
let surface = EventSurface::new(640, 480);
let event1 = DVSEvent::new(1000, 0, 0, true);
let event2 = DVSEvent::new(2000, 100, 0, false);
surface.update(&event1);
surface.update(&event2);
assert_eq!(surface.get_timestamp(0, 0), Some(1000));
assert_eq!(surface.get_timestamp(100, 0), Some(2000));
}
#[test]
fn test_event_surface_active_events() {
let surface = EventSurface::new(10, 10);
// Add events at different times
for i in 0..5 {
let event = DVSEvent::new(1000 + i * 100, i as u16, 0, true);
surface.update(&event);
}
// Query events since timestamp 1200
let active = surface.get_active_events(1200);
assert_eq!(active.len(), 2); // Events at 1300 and 1400
}
#[test]
fn test_event_surface_clear() {
let surface = EventSurface::new(10, 10);
let event = DVSEvent::new(1000, 5, 0, true);
surface.update(&event);
assert_eq!(surface.get_timestamp(5, 0), Some(1000));
surface.clear();
assert_eq!(surface.get_timestamp(5, 0), Some(0));
}
#[test]
fn test_event_surface_bounds() {
let surface = EventSurface::new(10, 10);
// Out of bounds should return None
assert_eq!(surface.get_timestamp(10, 0), None);
assert_eq!(surface.get_timestamp(0, 10), None);
}
}