From 4f620ad899b3f601c2727fbccb9a2cdee25d92d9 Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Sun, 8 Mar 2026 13:24:25 +0100 Subject: [PATCH] Make a XYStage trait, and have OpenFlexureStage implement it. This way, we can have multiple implementations of a stage that moves in XY direction. Signed-off-by: Henner Zeller --- hostcontrol/src/main.rs | 53 ++++--------------- .../src/{stage.rs => openflexure_stage.rs} | 40 +++++++------- hostcontrol/src/xy_stage.rs | 21 ++++++++ 3 files changed, 50 insertions(+), 64 deletions(-) rename hostcontrol/src/{stage.rs => openflexure_stage.rs} (89%) create mode 100644 hostcontrol/src/xy_stage.rs diff --git a/hostcontrol/src/main.rs b/hostcontrol/src/main.rs index 4b98db6..4004786 100644 --- a/hostcontrol/src/main.rs +++ b/hostcontrol/src/main.rs @@ -1,10 +1,13 @@ use clap::Parser; use std::{thread::sleep, time::Duration}; -mod stage; +mod openflexure_stage; mod stage_io; use crate::stage_io::StageIO; +use crate::xy_stage::XYStage; + +mod xy_stage; #[derive(clap::Parser, Debug)] #[command(version, about, long_about = None)] @@ -22,28 +25,14 @@ fn main() { let args = CliArgs::parse(); env_logger::init(); let stage_io = StageIO::new(&args.stage_device, args.tty_speed).unwrap(); - let mut s = stage::Stage::new(stage_io, 1.12).unwrap(); - let origin = nalgebra::vector![3000.0, 0.0, -6000.0]; - //println!("{}", s.version().unwrap()); - - //let a = nalgebra::vector![-10000.0, 0.0, -1250.0]; - //let b = nalgebra::vector![18000.0, -15000.0, -1600.0]; - //let c = nalgebra::vector![0.0, -15000.0, -250.0]; - + let mut s = openflexure_stage::OpenFlexureStage::new(stage_io, 1.12).unwrap(); + let origin = nalgebra::vector![0.0, 0.0, 0.0]; s.move_absolute_cartesian(origin).unwrap(); + sleep(Duration::from_secs(1)); + let mut max_xy = s.get_range(); + max_xy[2] = 0.0; + s.move_absolute_cartesian(max_xy).unwrap(); sleep(Duration::from_secs(5)); - //s.move_absolute_cartesian(origin + a).unwrap(); - ////sleep(Duration::from_secs(5)); - ////s.move_absolute_cartesian(origin).unwrap(); - ////s.move_absolute_cartesian(origin + c).unwrap(); - ////sleep(Duration::from_secs(5)); - ////s.move_absolute_cartesian(origin + nalgebra::vector![0.0, -16000.0, -500.0]).unwrap(); - ////println!("D"); - ////sleep(Duration::from_secs(5)); - ////s.move_absolute_cartesian(origin + nalgebra::vector![0.0, 0.0, 0.0]).unwrap(); - //println!("{:?}", s.get_position_cartesian()); - - //Ok(()) } struct App {} @@ -61,25 +50,3 @@ impl eframe::App for App { }); } } - -// -// let mut s = stage::Stage::new("/dev/ttyACM0", 1.12).unwrap(); -// let origin = nalgebra::vector![3000.0, 0.0, -6000.0]; -// println!("{}", s.version().unwrap()); -// -// let a = nalgebra::vector![18000.0, 0.0, -1250.0]; -// let b = nalgebra::vector![18000.0, -15000.0, -1600.0]; -// let c = nalgebra::vector![0.0, -15000.0, -250.0]; -// -// s.move_absolute_cartesian(origin).unwrap(); -// //sleep(Duration::from_secs(5)); -// //s.move_absolute_cartesian(origin + a).unwrap(); -// //sleep(Duration::from_secs(5)); -// //s.move_absolute_cartesian(origin + c).unwrap(); -// //sleep(Duration::from_secs(5)); -// //s.move_absolute_cartesian(origin + nalgebra::vector![0.0, -16000.0, -500.0]).unwrap(); -// //println!("D"); -// //sleep(Duration::from_secs(5)); -// //s.move_absolute_cartesian(origin + nalgebra::vector![0.0, 0.0, 0.0]).unwrap(); -// println!("{:?}", s.get_position_cartesian()); -//} diff --git a/hostcontrol/src/stage.rs b/hostcontrol/src/openflexure_stage.rs similarity index 89% rename from hostcontrol/src/stage.rs rename to hostcontrol/src/openflexure_stage.rs index 1c4060a..d5b3ddc 100644 --- a/hostcontrol/src/stage.rs +++ b/hostcontrol/src/openflexure_stage.rs @@ -1,7 +1,7 @@ //! Stage controller for openflexure-delta like stage controllers. -use crate::stage_io::{StageIO, StageIOError}; -use thiserror::Error; +use crate::stage_io::StageIO; +use crate::xy_stage::{XYStage, StageError,Result}; fn new_camera_rotation(theta: f64) -> nalgebra::Matrix3 { nalgebra::matrix![ @@ -22,23 +22,14 @@ fn new_delta_into_cartesian(flex_h: f64, flex_a: f64, flex_b: f64) -> nalgebra:: ] } -#[derive(Error, Debug)] -pub enum StageError { - #[error("Interface issue")] - Communication(#[from] StageIOError), - #[error("protocol error")] - Mumble, -} - -pub struct Stage { +pub struct OpenFlexureStage { stage_io: StageIO, delta_pos: nalgebra::Vector3, cartesian_to_delta: nalgebra::Matrix3, delta_to_cartesian: nalgebra::Matrix3, } -pub type Result = std::result::Result; -impl Stage { +impl OpenFlexureStage { pub fn new(stage_io: StageIO, camera_rotation: f64) -> Result { // TODO: non-blocking moves let delta_to_cartesian = new_camera_rotation(camera_rotation).try_inverse().unwrap() @@ -90,7 +81,19 @@ impl Stage { self.move_relative_delta(diff) } - pub fn move_absolute_cartesian(&mut self, a: nalgebra::Vector3) -> Result<()> { + pub fn move_relative_cartesian(&mut self, d: nalgebra::Vector3) -> Result<()> { + let abs = self.get_position_cartesian() + d; + self.move_absolute_cartesian(abs) + } + + pub fn version(&mut self) -> Result { + Ok(self.stage_io.send_request("version\n")?) + } +} + +impl XYStage for OpenFlexureStage { + fn move_absolute_cartesian(&mut self, a: nalgebra::Vector3) -> Result<()> { + // TODO: check range with get_movement_box() let current = self.get_position_delta(); let target = self.cartesian_to_delta * a; let target = nalgebra::vector![target[0] as i32, target[1] as i32, target[2] as i32]; @@ -110,12 +113,7 @@ impl Stage { self.move_absolute_delta(target) } - pub fn move_relative_cartesian(&mut self, d: nalgebra::Vector3) -> Result<()> { - let abs = self.get_position_cartesian() + d; - self.move_absolute_cartesian(abs) - } - - pub fn version(&mut self) -> Result { - Ok(self.stage_io.send_request("version\n")?) + fn get_range(&self) -> nalgebra::Vector3 { + nalgebra::vector![10000.0, 10000.0, 5000.0] } } diff --git a/hostcontrol/src/xy_stage.rs b/hostcontrol/src/xy_stage.rs new file mode 100644 index 0000000..8a22179 --- /dev/null +++ b/hostcontrol/src/xy_stage.rs @@ -0,0 +1,21 @@ + +use crate::stage_io::StageIOError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum StageError { + #[error("Interface issue")] + Communication(#[from] StageIOError), + #[error("protocol error")] + Mumble, +} + +pub type Result = std::result::Result; +pub trait XYStage { + /// Move to absolute coordinates (x,y,z) in micrometers. + fn move_absolute_cartesian(&mut self, a: nalgebra::Vector3) -> Result<()>; + + /// Get range of valid cartesian coordinates box. For now, assuming one + /// corner is fixed at (0,0,0), the other remote corner is this range. + fn get_range(&self) -> nalgebra::Vector3; +}