Custom homography per laser

This commit is contained in:
Ruben van de Ven 2025-05-21 18:50:18 +02:00
parent f921968386
commit 7ae6768edb
2 changed files with 68 additions and 7 deletions

View file

@ -8,13 +8,16 @@ use nannou::lyon::geom::euclid::Transform2D;
use nannou::{geom::Rect, math::map_range as nannou_map_range}; use nannou::{geom::Rect, math::map_range as nannou_map_range};
use nannou::prelude::*; use nannou::prelude::*;
use nannou_egui::{self, egui, Egui}; use nannou_egui::{self, egui, Egui};
use nannou_laser::DacId;
use nannou_laser::{self as laser, util::map_range}; use nannou_laser::{self as laser, util::map_range};
use serde_json::Result; use serde_json::Result;
use serde::{Serialize,Deserialize};
use trap_rust::trap::tracks::CoordinateSpace; use trap_rust::trap::tracks::CoordinateSpace;
use trap_rust::trap::{laser::{apply_homography_matrix, python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H}, tracks::{LaserPoints, RenderableLines}}; use trap_rust::trap::{laser::{apply_homography_matrix, python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H, DacConfig}, tracks::{LaserPoints, RenderableLines}};
use zmq::Socket; use zmq::Socket;
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
use std::collections::HashMap;
fn main() { fn main() {
nannou::app(model).update(update).run(); nannou::app(model).update(update).run();
@ -29,6 +32,7 @@ struct Model {
laser_model: LaserModel, laser_model: LaserModel,
// A copy of the laser settings so that we can control them with the GUI. // A copy of the laser settings so that we can control them with the GUI.
laser_settings: LaserSettings, laser_settings: LaserSettings,
per_laser_config: DacConfigMap,
// For receiving newly detected DACs. // For receiving newly detected DACs.
dac_rx: mpsc::Receiver<laser::DetectedDac>, dac_rx: mpsc::Receiver<laser::DetectedDac>,
// The UI for control over laser parameters and settings. // The UI for control over laser parameters and settings.
@ -153,6 +157,30 @@ fn zmq_receive(model: &mut Model) {
} }
// #[derive(Serialize, Deserialize)]
// #[serde(remote = "DacId")]
// pub enum DacIdSerializable {
// EtherDream { mac_address: [u8; 6] },
// Helios { id: u32 },
// }
// DEPRECATED
type DacConfigMap = HashMap<DacId, DacConfig>;
// Some hardcoded config. Not spending time on reading/writing config atm.
fn get_dac_configs() -> DacConfigMap{
let mut dac_configs: DacConfigMap = HashMap::new();
dac_configs.insert(
DacId::Helios { id: 926298163 },
DacConfig{homography: python_cv_h_into_mat3(TMP_PYTHON_LASER_H)}
);
dac_configs
}
fn model(app: &App) -> Model { fn model(app: &App) -> Model {
// Create a window to receive keyboard events. // Create a window to receive keyboard events.
let w_id_lasersettings = app let w_id_lasersettings = app
@ -213,6 +241,9 @@ fn model(app: &App) -> Model {
{ {
let dac = res.expect("error occurred during DAC detection"); let dac = res.expect("error occurred during DAC detection");
if detected.insert(dac.id()) { if detected.insert(dac.id()) {
// DacId::EtherDream { mac_address: () }
dbg!(&detected);
println!("{:#?}", dac); println!("{:#?}", dac);
if dac_tx.send(dac).is_err() { if dac_tx.send(dac).is_err() {
break; break;
@ -244,6 +275,7 @@ fn model(app: &App) -> Model {
last_update: Instant::now(), last_update: Instant::now(),
lost_alpha: 1., lost_alpha: 1.,
connected: true, connected: true,
per_laser_config: get_dac_configs()
// dimming_factor: 1., // dimming_factor: 1.,
} }
} }
@ -263,19 +295,19 @@ fn model(app: &App) -> Model {
// frame.add_lines(points); // frame.add_lines(points);
// } // }
const LASER_H: Mat3 = python_cv_h_into_mat3(TMP_PYTHON_LASER_H);
fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){ fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
let points: LaserPoints = (&model.current_lines).into(); let points: LaserPoints = (&model.current_lines).into();
let space = &model.current_lines.space; let space = &model.current_lines.space;
let pointno = points.len(); let pointno = points.len();
dbg!(model.config.homography);
let mut new_points = Vec::new(); let mut new_points = Vec::new();
for point in points.into_iter() { for point in points.into_iter() {
let p = point.position; let p = point.position;
let new_position = match space { let new_position = match space {
CoordinateSpace::World => apply_homography_matrix(LASER_H, &p), CoordinateSpace::World => apply_homography_matrix(model.config.homography, &p),
CoordinateSpace::Laser => p, CoordinateSpace::Laser => p,
_ => panic!("Invalid coordinate space"), _ => panic!("Invalid coordinate space"),
@ -328,9 +360,13 @@ fn update(_app: &App, model: &mut Model, update: Update) {
// First, check for new laser DACs. // First, check for new laser DACs.
for dac in model.dac_rx.try_recv() { for dac in model.dac_rx.try_recv() {
println!("Detected DAC {:?}!", dac.id()); println!("Detected DAC {:?}!", dac.id());
let config = match model.per_laser_config.contains_key(&dac.id()) {
true => &model.per_laser_config[&dac.id()],
false => &DacConfig::default(),
};
let stream = model let stream = model
.laser_api .laser_api
.new_frame_stream(model.laser_model.clone(), laser_frame_producer) .new_frame_stream(model.laser_model.with_config(config), laser_frame_producer)
.detected_dac(dac) .detected_dac(dac)
.build() .build()
.expect("failed to establish stream with newly detected DAC"); .expect("failed to establish stream with newly detected DAC");

View file

@ -1,7 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use nannou_laser as laser; use nannou_laser as laser;
use std::time::Instant; use std::time::Instant;
use serde::{Deserialize, Serialize};
use super::tracks::{LaserPoints, RenderableLines}; use super::tracks::{LaserPoints, RenderableLines};
pub const TMP_PYTHON_LASER_H: [[f32;3];3] = [[ 2.47442963e+02, -7.01714050e+01, -9.71749119e+01], pub const TMP_PYTHON_LASER_H: [[f32;3];3] = [[ 2.47442963e+02, -7.01714050e+01, -9.71749119e+01],
@ -34,6 +34,7 @@ pub struct LaserModel{
pub t: Instant, // register start time, so that animations can be moving pub t: Instant, // register start time, so that animations can be moving
pub current_lines: RenderableLines, pub current_lines: RenderableLines,
pub dimming: f32, pub dimming: f32,
pub config: DacConfig, // per dac configuration
} }
impl LaserModel{ impl LaserModel{
@ -41,9 +42,16 @@ impl LaserModel{
Self{ Self{
t: Instant::now(), t: Instant::now(),
current_lines: RenderableLines::new(), current_lines: RenderableLines::new(),
dimming: 0.3 dimming: 0.3,
config: DacConfig::default(),
} }
} }
pub fn with_config(&self, config: &DacConfig) -> Self{
LaserModel{
config: config.clone(),
.. self.clone()}
}
} }
#[derive(Component)] #[derive(Component)]
@ -58,3 +66,20 @@ pub struct LaserApi{
pub struct LaserTimer { pub struct LaserTimer {
pub timer: Timer, pub timer: Timer,
} }
#[derive(Serialize, Deserialize, Clone)]
pub struct DacConfig{
// #[serde(with = "DacIdSerializable")]
// id: DacId,
pub homography: Mat3
}
const LASER_H: Mat3 = python_cv_h_into_mat3(TMP_PYTHON_LASER_H);
impl Default for DacConfig{
fn default() -> DacConfig{
DacConfig { homography: Mat3::IDENTITY }
}
}