meteor_detect/examples/meteor_detection_system.rs
2025-04-05 14:46:27 +08:00

235 lines
8.5 KiB
Rust
Raw Permalink 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.

use anyhow::Result;
use log::{error, info, warn};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::mpsc::{self, Sender};
use tokio::time;
// 导入Camera模块组件
use meteor_detect::camera::{CameraController, CameraSettings, ExposureMode, Resolution, FrameBuffer, Frame};
use meteor_detect::config::Config;
/// 演示如何使用相机模块构建完整的流星检测系统
#[tokio::main]
async fn main() -> Result<()> {
// 初始化日志
env_logger::init();
// 1. 创建和初始化相机
let config = create_detector_config();
let mut camera = CameraController::new(&config).await?;
info!("初始化相机系统");
camera.initialize().await?;
info!("启动相机捕获");
camera.start_capture().await?;
// 2. 获取帧缓冲器的引用(用于检测器访问)
let frame_buffer = camera.get_frame_buffer();
// 3. 创建通信通道
// 用于从检测器向主程序发送事件
let (event_tx, mut event_rx) = mpsc::channel(10);
// 用于从健康监控向主程序发送健康状态
let (health_tx, mut health_rx) = mpsc::channel(10);
// 4. 启动检测器任务,从缓冲区读取帧进行处理
start_detector_task(frame_buffer.clone(), event_tx).await;
// 5. 启动健康监控任务 - 只发送健康状态,而不是直接操作相机
start_health_monitor_task(health_tx).await;
// 6. 主线程处理检测事件和健康状态
info!("等待检测事件...");
let mut saved_events = 0;
// 创建轮询健康状态的定时器
let mut health_interval = time::interval(Duration::from_secs(30));
loop {
tokio::select! {
// 处理检测事件
Some(event) = event_rx.recv() => {
info!("收到流星检测事件: 时间={}, 置信度={:.2}",
event.timestamp, event.confidence);
// 保存事件视频
match camera.save_meteor_event(
event.timestamp,
event.confidence,
event.bounding_box,
5, // 事件前5秒
3, // 事件后3秒
).await {
Ok(saved_event) => {
info!("已保存流星事件视频: {}", saved_event.video_path);
saved_events += 1;
// 在这里可以添加额外处理,如上传到云存储、发送通知等
},
Err(e) => {
error!("保存流星事件失败: {}", e);
}
}
// 演示目的保存3个事件后退出
if saved_events >= 3 {
info!("已保存足够的事件,退出处理循环");
break;
}
},
// 处理健康检查的时间间隔
_ = health_interval.tick() => {
// 直接在主线程中执行健康检查
match camera.check_health().await {
Ok(is_healthy) => {
if !is_healthy {
warn!("相机健康检查失败,可能需要干预");
} else {
info!("相机健康状态: 正常");
}
},
Err(e) => {
error!("健康检查失败: {}", e);
}
}
// 获取和记录相机状态
if let Ok(status) = camera.get_status().await {
info!("相机状态: {}", status);
}
},
// 接收健康监控发送的消息(演示目的,实际中可以根据需要处理)
Some(health_msg) = health_rx.recv() => {
info!("收到健康监控消息: {}", health_msg);
},
// 如果所有通道都已关闭,退出循环
else => break,
}
}
// 7. 清理资源
info!("停止相机捕获");
camera.stop_capture().await?;
info!("流星检测系统演示完成");
Ok(())
}
/// 启动检测器任务
async fn start_detector_task(frame_buffer: Arc<FrameBuffer>, event_tx: Sender<DetectionEvent>) {
tokio::spawn(async move {
info!("启动流星检测器");
let mut detection_count = 0;
let mut last_detection_time = chrono::Utc::now();
// 模拟检测循环
loop {
// 模拟帧分析(实际应用中会连续分析每一帧)
time::sleep(Duration::from_secs(2)).await;
// 从帧缓冲区获取最新帧
if let Some(frame) = frame_buffer.get(0) {
let now = chrono::Utc::now();
// 确保距离上次检测至少10秒防止重复检测
if (now - last_detection_time).num_seconds() >= 10 {
// 这里应该是实际的检测算法
// 为演示目的,我们随机生成一些检测结果
let detection_seed = rand::random::<f32>();
if detection_seed < 0.3 { // 30%的概率检测到流星
detection_count += 1;
last_detection_time = now;
info!("检测到流星 #{}", detection_count);
// 发送检测事件到主线程
let event = DetectionEvent {
timestamp: now,
confidence: 0.7 + (detection_seed * 0.3), // 0.7-1.0之间的置信度
bounding_box: (
(rand::random::<f32>() * 800.0) as u32, // x
(rand::random::<f32>() * 600.0) as u32, // y
(50.0 + rand::random::<f32>() * 100.0) as u32, // width
(50.0 + rand::random::<f32>() * 100.0) as u32, // height
),
};
if event_tx.send(event).await.is_err() {
warn!("无法发送检测事件,接收端可能已关闭");
break;
}
}
}
} else {
warn!("无法获取帧,缓冲区可能为空");
time::sleep(Duration::from_millis(500)).await;
}
// 演示目的5次检测后退出
if detection_count >= 5 {
info!("已达到预设检测次数,检测器退出");
break;
}
}
});
}
/// 启动健康监控任务
async fn start_health_monitor_task(health_tx: Sender<String>) {
tokio::spawn(async move {
info!("启动健康监控任务 (模拟)");
let mut interval = time::interval(Duration::from_secs(45));
// 简单模拟健康监控,不直接访问相机
// 在实际应用中,这可能会监控系统各个部分的状态
loop {
interval.tick().await;
// 发送简单的健康状态消息回主线程
// 这是一个简化的演示
if health_tx.send("系统运行正常".to_string()).await.is_err() {
warn!("无法发送健康状态,接收端可能已关闭");
break;
}
}
});
}
/// 创建用于检测系统的配置
fn create_detector_config() -> Config {
let camera_settings = CameraSettings {
device: "0".to_string(),
// 对于流星检测,建议使用更高分辨率
resolution: Resolution::HD1080p,
fps: 30,
// 对于夜间观测,手动曝光通常更好
exposure: ExposureMode::Manual(500000), // 500毫秒曝光
// 增加增益以提高低光灵敏度
gain: 200,
focus_locked: true,
};
Config {
camera: camera_settings,
// 其他配置字段,使用其默认值
..Default::default()
}
}
/// 流星检测事件
struct DetectionEvent {
/// 事件时间戳
timestamp: chrono::DateTime<chrono::Utc>,
/// 检测置信度 (0-1)
confidence: f32,
/// 边界框 (x, y, 宽度, 高度)
bounding_box: (u32, u32, u32, u32),
}