diff --git a/src/config.rs b/src/config.rs index bb7e43ebb0b..c031dd618ae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,6 +10,8 @@ use serde::{Deserialize, Serialize}; pub struct ConfigFile { pub control_board_path: String, pub meb_path: String, + pub front_cam: String, + pub bottom_cam: String } impl Default for ConfigFile { @@ -17,6 +19,8 @@ impl Default for ConfigFile { Self { control_board_path: "/dev/ttyACM0".to_string(), meb_path: "/dev/ttyACM2".to_string(), + front_cam: "/dev/video1".to_string(), + bottom_cam: "/dev/video0".to_string() } } } diff --git a/src/main.rs b/src/main.rs index ed273a3cc7f..240505e3956 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,6 +47,24 @@ async fn meb() -> &'static MainElectronicsBoard { .await } +static FRONT_CAM_CELL: OnceCell = OnceCell::const_new(); +async fn front_cam() -> &'static Camera { + FRONT_CAM_CELL + .get_or_init(|| async { + Camera::jetson_new(&Configuration::default().front_cam, "front", Path::new("/tmp/front_feed.mp4")).unwrap() + }) + .await +} + +static BOTTOM_CAM_CELL: OnceCell = OnceCell::const_new(); +async fn bottom_cam() -> &'static Camera { + BOTTOM_CAM_CELL + .get_or_init(|| async { + Camera::jetson_new(&Configuration::default().bottom_cam, "bottom", Path::new("/tmp/bottom_feed.mp4")).unwrap() + }) + .await +} + #[tokio::main] async fn main() { let shutdown_tx = shutdown_handler().await; @@ -154,38 +172,34 @@ async fn run_mission(mission: &str) -> Result<()> { Ok(()) } "descend" | "forward" => { - let cam = Camera::jetson_new("/dev/video1", "front", Path::new("/tmp/feed.mp4"))?; - println!("Opened camera"); let _ = descend_and_go_forward(&FullActionContext::new( control_board().await, meb().await, - &cam, + front_cam().await, + bottom_cam().await )) .execute() .await; Ok(()) } "gate_run" => { - let cam = Camera::jetson_new("/dev/video0", "front", Path::new("/tmp/feed.mp4"))?; - //let _cam_extra = - //Camera::jetson_new("/dev/video0", "front", Path::new("/tmp/feed_extra.mp4"))?; println!("Opened camera"); let _ = gate_run(&FullActionContext::new( control_board().await, meb().await, - &cam, + front_cam().await, + bottom_cam().await )) .execute() .await; Ok(()) } "example" => { - let cam = Camera::jetson_new("/dev/video1", "front", Path::new("/tmp/feed.mp4"))?; - println!("Opened camera"); let _ = initial_descent(&FullActionContext::new( control_board().await, meb().await, - &cam, + front_cam().await, + bottom_cam().await )) .execute() .await; diff --git a/src/missions/action_context.rs b/src/missions/action_context.rs index 47305d48f8f..7979ef9a49e 100644 --- a/src/missions/action_context.rs +++ b/src/missions/action_context.rs @@ -1,13 +1,14 @@ -use async_trait::async_trait; use core::fmt::Debug; -use opencv::prelude::Mat; +use async_trait::async_trait; +use opencv::core::Mat; use tokio::io::{AsyncWriteExt, WriteHalf}; use tokio_serial::SerialStream; use crate::{ comms::{control_board::ControlBoard, meb::MainElectronicsBoard}, - video_source::MatSource, }; +use crate::video_source::appsink::Camera; +use crate::video_source::MatSource; /** * Inherit this trait if you have a control board @@ -23,46 +24,67 @@ pub trait GetMainElectronicsBoard: Send + Sync { fn get_main_electronics_board(&self) -> &MainElectronicsBoard; } +/** + * Inherit this trait if you have a front camera + */ +#[async_trait] +pub trait GetFrontCamMat: { + async fn get_front_camera_mat(&self) -> Mat; +} + +/** + * Inherit this trait if you have a bottom camera + */ +#[async_trait] +pub trait GetBottomCamMat: { + async fn get_bottom_camera_mat(&self) -> Mat; +} + #[derive(Debug)] pub struct EmptyActionContext; -pub struct FullActionContext<'a, T: AsyncWriteExt + Unpin + Send, U: MatSource> { +pub struct FullActionContext<'a, T: AsyncWriteExt + Unpin + Send> { control_board: &'a ControlBoard, main_electronics_board: &'a MainElectronicsBoard, - frame_source: &'a U, + front_cam: &'a Camera, + bottom_cam: &'a Camera, } -impl<'a, T: AsyncWriteExt + Unpin + Send, U: MatSource> FullActionContext<'a, T, U> { +impl<'a, T: AsyncWriteExt + Unpin + Send> FullActionContext<'a, T> { pub const fn new( control_board: &'a ControlBoard, main_electronics_board: &'a MainElectronicsBoard, - frame_source: &'a U, + front_cam: &'a Camera, + bottom_cam: &'a Camera, ) -> Self { Self { control_board, main_electronics_board, - frame_source, + front_cam, + bottom_cam, } } } -impl GetControlBoard> - for FullActionContext<'_, WriteHalf, T> +impl GetControlBoard> for FullActionContext<'_, WriteHalf> { fn get_control_board(&self) -> &ControlBoard> { self.control_board } } -impl GetMainElectronicsBoard for FullActionContext<'_, WriteHalf, T> { +impl GetMainElectronicsBoard for FullActionContext<'_, WriteHalf> { fn get_main_electronics_board(&self) -> &MainElectronicsBoard { self.main_electronics_board } } #[async_trait] -impl MatSource for FullActionContext<'_, T, U> { - async fn get_mat(&self) -> Mat { - self.frame_source.get_mat().await - } +impl GetFrontCamMat for FullActionContext<'_, T> { + async fn get_front_camera_mat(&self) -> Mat { self.front_cam.get_mat().await } } + +#[async_trait] +impl GetBottomCamMat for FullActionContext<'_, T> { + async fn get_bottom_camera_mat(&self) -> Mat { self.bottom_cam.get_mat().await } +} \ No newline at end of file diff --git a/src/missions/basic.rs b/src/missions/basic.rs index c3f9f3ea5ec..ffa1e981882 100644 --- a/src/missions/basic.rs +++ b/src/missions/basic.rs @@ -20,6 +20,7 @@ use tokio::{ time::{sleep, Duration}, }; use tokio_serial::SerialStream; +use crate::missions::action_context::GetFrontCamMat; #[derive(Debug)] pub struct DelayAction { @@ -78,7 +79,7 @@ pub fn descend_and_go_forward< } pub fn gate_run< - Con: Send + Sync + GetControlBoard> + GetMainElectronicsBoard + MatSource, + Con: Send + Sync + GetControlBoard> + GetMainElectronicsBoard + GetFrontCamMat, >( context: &Con, ) -> impl ActionExec + '_ { diff --git a/src/missions/vision.rs b/src/missions/vision.rs index 863e87116cd..da52c0fa757 100644 --- a/src/missions/vision.rs +++ b/src/missions/vision.rs @@ -1,7 +1,6 @@ use std::marker::PhantomData; use super::action::{Action, ActionExec}; -use crate::video_source::MatSource; use crate::vision::{Draw, Offset2D, RelPos, VisualDetector}; use anyhow::Result; use async_trait::async_trait; @@ -13,6 +12,7 @@ use opencv::{core::Vector, imgcodecs::imwrite}; use std::fs::create_dir_all; #[cfg(feature = "logging")] use uuid::Uuid; +use crate::missions::action_context::GetFrontCamMat; /// Runs a vision routine to obtain object position /// @@ -37,7 +37,7 @@ impl<'a, T, U, V> VisionNormOffset<'a, T, U, V> { impl Action for VisionNormOffset<'_, T, U, V> {} #[async_trait] -impl + Send + Sync> +impl + Send + Sync> ActionExec for VisionNormOffset<'_, T, U, V> where U::Position: RelPos + Draw, @@ -50,7 +50,7 @@ where } #[allow(unused_mut)] - let mut mat = self.context.get_mat().await; + let mut mat = self.context.get_front_camera_mat().await.clone(); let detections = self.model.detect(&mat); #[cfg(feature = "logging")] println!("Detect attempt: {}", detections.is_ok());