use clap::{Parser, ValueEnum}; use image::RgbImage; use std::path::PathBuf; mod camera; mod gcode_stage; mod openflexure_stage; mod stage_io; use crate::camera::Camera; use crate::stage_io::StageIO; use crate::xy_stage::XYStage; mod xy_stage; #[derive(clap::Parser, Debug)] #[command(version, about, long_about = None)] struct CliArgs { /// Interface to talk to movement stage #[arg(long, default_value = "/dev/ttyACM0")] stage_device: String, /// Speed of the stage device (bps) #[arg(long, default_value = "115200")] tty_speed: u32, /// Stage movement backend #[arg(long, value_enum)] backend: Backend, /// Id of camera to fetch images from. #[arg(long, default_value = "0")] camera_index: u32, /// Directory all captured images are stored. #[arg(long, value_name = "out-dir")] output_directory: PathBuf, } // [derive(DebugCopy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] #[derive(Debug, Clone, ValueEnum)] enum Backend { /// OpenFlexure stage OpenFlexure, /// GCode stage GCode, } fn store_image(number: u32, pos: nalgebra::Vector3, dir: &PathBuf, img: &RgbImage) { let img_file = &dir.join(format!("img-{:05}-{:0},{:0}.png", number, pos[0], pos[1])); img.save(img_file).unwrap(); } fn main() { env_logger::init(); let args = CliArgs::parse(); if !args.output_directory.is_dir() { panic!("--out-dir needs to be an existing directory"); } let origin = nalgebra::vector![0.0, 0.0, 0.0]; // Picture source let mut cam = Camera::new(args.camera_index).unwrap(); cam.capture().unwrap(); // Warm up camera. // Movement let stage_io = StageIO::new(&args.stage_device, args.tty_speed).unwrap(); let mut stage: Box = match args.backend { Backend::GCode => Box::new(gcode_stage::GCodeStage::new(stage_io).unwrap()), Backend::OpenFlexure => { Box::new(openflexure_stage::OpenFlexureStage::new(stage_io, 1.12).unwrap()) } }; // Local testing. Just take a line of pictures. let mut max_xy = stage.get_range(); // Only interested in lerp-ing X for now. max_xy[1] = 0.0; max_xy[2] = 0.0; for n in 0..10 { let pos = max_xy * n as f64 / 10.0; stage.move_absolute_cartesian(pos).unwrap(); store_image(n, pos, &args.output_directory, &cam.capture().unwrap()); } } #[derive(Default)] struct App {} impl eframe::App for App { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::CentralPanel::default().show(ctx, |ui| { ui.heading("My egui Application"); }); } }