27 lines
25 KiB
XML
27 lines
25 KiB
XML
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|||
|
|
<project version="4">
|
|||
|
|
<component name="CopilotDiffPersistence">
|
|||
|
|
<option name="pendingDiffs">
|
|||
|
|
<map>
|
|||
|
|
<entry key="/main (snapshot).rs">
|
|||
|
|
<value>
|
|||
|
|
<PendingDiffInfo>
|
|||
|
|
<option name="filePath" value="/main (snapshot).rs" />
|
|||
|
|
<option name="originalContent" value="mod policy; mod pingEsp32; mod command; use pingEsp32::Link; use std::time::Duration; fn main() -> std::io::Result<()> { let mut link = Link::open_default()?; link.send_angles(&[1.57;8])?; let mut cmd = command::spawn_listener(); let mut i = 0; while i > -1 { i += 1; if cmd.poll_from_terminal() { let state = cmd.load(); let vec = command::state_to_vector(state); println!("[CommandState] {:?} (state=0b{:03b})", vec, state); } while let Some(msg) = link.recv_timeout(Duration::from_millis(20)) { if msg.is_data() { if let Some(mut obs) = msg.telemetry() { let state = cmd.load(); let cmd_vec = command::state_to_vector(state); obs[6] = cmd_vec[0]; obs[7] = cmd_vec[1]; obs[8] = cmd_vec[2]; println!("收到 36 维观测值(含指令): {:?}", obs); let action = policy::policy(obs).expect("TODO: panic message"); link.send_angles(&action)?; println!("[Action]:{:?}, 【{}】", action, i); } } else if msg.is_reply() { println!("[REPLY] {}", msg.text()); } else { println!("[TEXT] {}", msg.text()); } } std::thread::sleep(Duration::from_millis(5)); } Ok(()) } " />
|
|||
|
|
<option name="updatedContent" value="mod policy; mod pingEsp32; mod command; use pingEsp32::Link; use std::time::Duration; fn main() -> std::io::Result<()> { let mut link = Link::open_default()?; link.send_angles(&[1.57;8])?; let mut cmd = command::spawn_listener(); let mut i = 0; while i > -1 { i += 1; if let Some(vec) = cmd.poll_from_terminal() { println!("[CommandState] {:?}", vec); if vec == [0.0, 0.0, 0.0] { println!("[Command] released -> zero"); } } while let Some(msg) = link.recv_timeout(Duration::from_millis(20)) { if msg.is_data() { if let Some(mut obs) = msg.telemetry() { let cmd_vec = cmd.current_vector(); obs[6] = cmd_vec[0]; obs[7] = cmd_vec[1]; obs[8] = cmd_vec[2]; println!("收到 36 维观测值(含指令): {:?}", obs); let action = policy::policy(obs).expect("TODO: panic message"); link.send_angles(&action)?; println!("[Action]:{:?}, 【{}】", action, i); } } else if msg.is_reply() { println!("[REPLY] {}", msg.text()); } else { println!("[TEXT] {}", msg.text()); } } std::thread::sleep(Duration::from_millis(5)); } Ok(()) }" />
|
|||
|
|
</PendingDiffInfo>
|
|||
|
|
</value>
|
|||
|
|
</entry>
|
|||
|
|
<entry key="/pingEsp32 (snapshot).rs">
|
|||
|
|
<value>
|
|||
|
|
<PendingDiffInfo>
|
|||
|
|
<option name="filePath" value="/pingEsp32 (snapshot).rs" />
|
|||
|
|
<option name="originalContent" value="use std::io::{BufRead, BufReader, Read, Write}; use std::net::TcpStream; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{self, Receiver, Sender, RecvTimeoutError}; use std::sync::Arc; use std::thread::{self, JoinHandle}; use std::time::Duration; use std::f32::consts::PI; pub const ESP32_IP: &str = "192.168.4.1"; pub const ESP32_PORT: u16 = 3333; pub const NUM_SERVOS: usize = 8; const TELEMETRY_MAGIC: [u8; 2] = [0xA5, 0x5A]; const TELEMETRY_FRAME_LEN: usize = 22; /// 从 ESP32 收到的一条消息(可包含 ASCII 文本,也可包含 36 维 IMU 数据) #[derive(Debug, Clone)] pub struct Esp32Message { text: String, telemetry: Option<[f32; 36]>, } impl Esp32Message { pub fn new_text(text: impl Into<String>) -> Self { Self { text: text.into(), telemetry: None, } } pub fn new_telemetry(data: [f32; 36]) -> Self { Self { text: "IMU".to_string(), telemetry: Some(data), } } /// 是否是数据推送(二进制 IMU 帧) pub fn is_data(&self) -> bool { self.telemetry.is_some() } /// 是否是应答,比如 "ESP32: OK ..." pub fn is_reply(&self) -> bool { self.telemetry.is_none() && self.text.starts_with("ESP32:") } pub fn text(&self) -> &str { &self.text } /// 返回 36 维 f32 数组;其余位置按 0.0 填充。 pub fn telemetry(&self) -> Option<[f32; 36]> { self.telemetry } } // ==================== 双向连接 ==================== pub struct Link { writer: TcpStream, rx: Receiver<Esp32Message>, stop: Arc<AtomicBool>, reader_job: Option<JoinHandle<()>>, } impl Link { /// 建立连接并启动后台接收线程 pub fn open(ip: &str, port: u16) -> std::io::Result<Self> { let addr = format!("{}:{}", ip, port); println!("[*] 连接 {} ...", addr); println!("请连接上esp32的wifi热点后再运行本程序【ESP32_AP】"); let stream = TcpStream::connect(&addr)?; stream.set_nodelay(true)?; stream.set_read_timeout(Some(Duration::from_millis(200)))?; println!("[+] 已连接"); let reader_stream = stream.try_clone()?; let (tx, rx): (Sender<Esp32Message>, Receiver<Esp32Message>) = mpsc::channel(); let stop = Arc::new(AtomicBool::new(false)); let reader_job = spawn_reader(reader_stream, tx, Arc::clone(&stop)); Ok(Self { writer: stream, rx, stop, reader_job: Some(reader_job), }) } pub fn open_default() -> std::io::Result<Self> { Self::open(ESP32_IP, ESP32_PORT) } // ---------- 发送 ---------- /// 发送弧度列表 pub fn send_angles(&mut self, rads: &[f32]) -> std::io::Result<()> { let n = rads.len().min(NUM_SERVOS); let payload = rads[..n] .iter() .map(|r| format!("{:.4}", r.clamp(0.0, PI))) .collect::<Vec<_>>() .join(","); self.send_line(&format!("RAD:{}", payload)) } /// 发送角度列表 pub fn send_degrees(&mut self, degs: &[f32]) -> std::io::Result<()> { let n = degs.len().min(NUM_SERVOS); let payload = degs[..n] .iter() .map(|d| form
|
|||
|
|
<option name="updatedContent" value="use std::io::{BufRead, BufReader, Read, Write}; use std::net::TcpStream; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{self, Receiver, Sender, RecvTimeoutError}; use std::sync::Arc; use std::thread::{self, JoinHandle}; use std::time::Duration; use std::f32::consts::PI; pub const ESP32_IP: &str = "192.168.4.1"; pub const ESP32_PORT: u16 = 3333; pub const NUM_SERVOS: usize = 8; const TELEMETRY_MAGIC: [u8; 2] = [0xA5, 0x5A]; const TELEMETRY_FRAME_LEN: usize = 22; /// 从 ESP32 收到的一条消息(可包含 ASCII 文本,也可包含 36 维 IMU 数据) #[derive(Debug, Clone)] pub struct Esp32Message { text: String, telemetry: Option<[f32; 36]>, } impl Esp32Message { pub fn new_text(text: impl Into<String>) -> Self { Self { text: text.into(), telemetry: None, } } pub fn new_telemetry(data: [f32; 36]) -> Self { Self { text: "IMU".to_string(), telemetry: Some(data), } } /// 是否是数据推送(二进制 IMU 帧) pub fn is_data(&self) -> bool { self.telemetry.is_some() } /// 是否是应答,比如 "ESP32: OK ..." pub fn is_reply(&self) -> bool { self.telemetry.is_none() && self.text.starts_with("ESP32:") } pub fn text(&self) -> &str { &self.text } /// 返回 36 维 f32 数组;其余位置按 0.0 填充。 pub fn telemetry(&self) -> Option<[f32; 36]> { self.telemetry } } // ==================== 双向连接 ==================== pub struct Link { writer: TcpStream, rx: Receiver<Esp32Message>, stop: Arc<AtomicBool>, reader_job: Option<JoinHandle<()>>, } impl Link { /// 建立连接并启动后台接收线程 pub fn open(ip: &str, port: u16) -> std::io::Result<Self> { let addr = format!("{}:{}", ip, port); println!("[*] 连接 {} ...", addr); println!("请连接上esp32的wifi热点后再运行本程序【ESP32_AP】"); let stream = TcpStream::connect(&addr)?; stream.set_nodelay(true)?; stream.set_read_timeout(Some(Duration::from_millis(200)))?; println!("[+] 已连接"); let reader_stream = stream.try_clone()?; let (tx, rx): (Sender<Esp32Message>, Receiver<Esp32Message>) = mpsc::channel(); let stop = Arc::new(AtomicBool::new(false)); let reader_job = spawn_reader(reader_stream, tx, Arc::clone(&stop)); Ok(Self { writer: stream, rx, stop, reader_job: Some(reader_job), }) } pub fn open_default() -> std::io::Result<Self> { Self::open(ESP32_IP, ESP32_PORT) } // ---------- 发送 ---------- /// 发送弧度列表 pub fn send_angles(&mut self, rads: &[f32]) -> std::io::Result<()> { let n = rads.len().min(NUM_SERVOS); let payload = rads[..n] .iter() .map(|r| format!("{:.4}", r.clamp(0.0, PI))) .collect::<Vec<_>>() .join(","); self.send_line(&format!("RAD:{}", payload)) } /// 发送角度列表 pub fn send_degrees(&mut self, degs: &[f32]) -> std::io::Result<()> { let n = degs.len().min(NUM_SERVOS); let payload = degs[..n] .iter() .map(|d| forma
|
|||
|
|
</PendingDiffInfo>
|
|||
|
|
</value>
|
|||
|
|
</entry>
|
|||
|
|
</map>
|
|||
|
|
</option>
|
|||
|
|
</component>
|
|||
|
|
</project>
|