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}