Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
217
crates/ruvector-nervous-system/src/eventbus/event.rs
Normal file
217
crates/ruvector-nervous-system/src/eventbus/event.rs
Normal file
@@ -0,0 +1,217 @@
|
||||
//! 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user