openrr_teleop/
switcher.rs

1use std::{
2    sync::{
3        atomic::{AtomicBool, Ordering},
4        Arc, Mutex,
5    },
6    time::Duration,
7};
8
9use arci::{
10    gamepad::{Button, Gamepad, GamepadEvent},
11    Speaker,
12};
13use tokio::sync::Mutex as TokioMutex;
14use tracing::{debug, warn};
15
16use super::control_mode::ControlMode;
17
18pub struct ControlModeSwitcher<S>
19where
20    S: Speaker,
21{
22    current_index: Arc<Mutex<usize>>,
23    control_modes: Arc<TokioMutex<Vec<Arc<dyn ControlMode>>>>,
24    speaker: S,
25    is_running: Arc<AtomicBool>,
26}
27
28impl<S> ControlModeSwitcher<S>
29where
30    S: Speaker,
31{
32    #[track_caller]
33    pub fn new(
34        control_modes: Vec<Arc<dyn ControlMode>>,
35        speaker: S,
36        initial_mode_index: usize,
37    ) -> Self {
38        assert!(!control_modes.is_empty());
39        Self {
40            current_index: Arc::new(Mutex::new(initial_mode_index)),
41            control_modes: Arc::new(TokioMutex::new(control_modes)),
42            speaker,
43            is_running: Arc::new(AtomicBool::new(false)),
44        }
45    }
46
47    pub async fn increment_mode(&self) -> Result<(), arci::Error> {
48        let len = self.control_modes.lock().await.len();
49        {
50            let mut index = self.current_index.lock().unwrap();
51            *index = (*index + 1) % len;
52        }
53        self.speak_current_mode().await
54    }
55
56    pub async fn speak_current_mode(&self) -> Result<(), arci::Error> {
57        let modes = self.control_modes.lock().await;
58        let i = self.current_index();
59        let mode = modes[i].mode();
60        let submode = modes[i].submode();
61        self.speaker.speak(&format!("{mode}{submode}"))?.await
62    }
63
64    fn current_index(&self) -> usize {
65        *self.current_index.lock().unwrap()
66    }
67
68    fn is_running(&self) -> bool {
69        self.is_running.load(Ordering::Relaxed)
70    }
71
72    pub fn stop(&self) {
73        self.is_running.store(false, Ordering::Relaxed);
74    }
75
76    pub async fn main<G>(&self, gamepad: G)
77    where
78        G: 'static + Gamepad,
79    {
80        let modes = self.control_modes.clone();
81        let index = self.current_index.clone();
82        let is_running = self.is_running.clone();
83        self.is_running.store(true, Ordering::Relaxed);
84        self.speak_current_mode().await.unwrap();
85        let gamepad = Arc::new(gamepad);
86        let gamepad_cloned = gamepad.clone();
87        tokio::spawn(async move {
88            let mut interval = tokio::time::interval(Duration::from_millis(50));
89            while is_running.load(Ordering::Relaxed) {
90                debug!("tick");
91                let mode = { modes.lock().await[*index.lock().unwrap()].clone() };
92                mode.proc().await;
93                interval.tick().await;
94            }
95            gamepad_cloned.stop();
96        });
97        while self.is_running() {
98            let ev = gamepad.next_event().await;
99            debug!("event: {ev:?}");
100            match ev {
101                GamepadEvent::ButtonPressed(Button::North) => {
102                    self.increment_mode().await.unwrap();
103                }
104                GamepadEvent::Unknown => {
105                    warn!("gamepad Unknown");
106                    self.stop();
107                }
108                _ => {
109                    let mode = { self.control_modes.lock().await[self.current_index()].clone() };
110                    mode.handle_event(ev);
111                }
112            }
113        }
114    }
115}