Send unmapping frames to laser

This commit is contained in:
Ruben van de Ven 2025-05-21 16:55:17 +02:00
parent a14f8b135c
commit f921968386
5 changed files with 58 additions and 13 deletions

12
Cargo.lock generated
View file

@ -5131,6 +5131,17 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_repr"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
]
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.8" version = "0.6.8"
@ -5721,6 +5732,7 @@ dependencies = [
"nannou_laser", "nannou_laser",
"serde", "serde",
"serde_json", "serde_json",
"serde_repr",
"zmq", "zmq",
] ]

View file

@ -16,6 +16,7 @@ zmq = "0.10.0"
nannou = "0.19.0" nannou = "0.19.0"
nannou_egui = { version = "0.19.0", features = ["wayland"] } nannou_egui = { version = "0.19.0", features = ["wayland"] }
serde_repr = "0.1.20"
[dev-dependencies] [dev-dependencies]

View file

@ -3,12 +3,14 @@
//! UI. //! UI.
use bevy::math::Mat3; use bevy::math::Mat3;
use bevy_nannou::prelude::DARK_GRAY;
use nannou::lyon::geom::euclid::Transform2D; 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::{self as laser, util::map_range}; use nannou_laser::{self as laser, util::map_range};
use serde_json::Result; use serde_json::Result;
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}, tracks::{LaserPoints, RenderableLines}};
use zmq::Socket; use zmq::Socket;
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
@ -37,6 +39,7 @@ struct Model {
last_update: Instant, last_update: Instant,
// dimming_factor: f32, // dimming_factor: f32,
lost_alpha: f32, lost_alpha: f32,
connected: bool,
} }
struct LaserSettings { struct LaserSettings {
@ -103,6 +106,7 @@ fn zmq_receive(model: &mut Model) {
// let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?"); // let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?");
let res: Result<RenderableLines> = serde_json::from_str(&json); let res: Result<RenderableLines> = serde_json::from_str(&json);
model.lost_alpha = 1.; model.lost_alpha = 1.;
model.connected = true;
lines = match res { lines = match res {
Ok(lines) => lines, // if Ok(255), set x to 255 Ok(lines) => lines, // if Ok(255), set x to 255
@ -110,13 +114,13 @@ fn zmq_receive(model: &mut Model) {
println!("No valid json?"); println!("No valid json?");
println!("{}", _e); println!("{}", _e);
// empty if invalid // empty if invalid
RenderableLines{ RenderableLines::new()
lines: Vec::new()
}
}, // if Err("some message"), panic with error message "some message" }, // if Err("some message"), panic with error message "some message"
}; };
} else if model.last_update < Instant::now() - Duration::from_millis(100){ } else if model.last_update < Instant::now() - Duration::from_millis(100){
// set lines empty, if no new input for > 100ms (10fps) // set lines empty, if no new input for > 100ms (10fps)
model.connected = false;
if model.lost_alpha > 0.{ if model.lost_alpha > 0.{
println!("No input, clear lines!!"); println!("No input, clear lines!!");
@ -126,9 +130,7 @@ fn zmq_receive(model: &mut Model) {
} }
lines = model.current_lines.with_alpha(model.lost_alpha); lines = model.current_lines.with_alpha(model.lost_alpha);
} else { } else {
lines = RenderableLines{ lines = RenderableLines::new()
lines: Vec::new()
}
} }
} else { } else {
// No new lines, break // No new lines, break
@ -241,6 +243,7 @@ fn model(app: &App) -> Model {
current_lines: current_lines, current_lines: current_lines,
last_update: Instant::now(), last_update: Instant::now(),
lost_alpha: 1., lost_alpha: 1.,
connected: true,
// dimming_factor: 1., // dimming_factor: 1.,
} }
} }
@ -265,12 +268,19 @@ 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 pointno = points.len(); let pointno = points.len();
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 = apply_homography_matrix(LASER_H, &p); let new_position = match space {
CoordinateSpace::World => apply_homography_matrix(LASER_H, &p),
CoordinateSpace::Laser => p,
_ => panic!("Invalid coordinate space"),
};
// let new_position = apply_homography_matrix(LASER_H, &p);
// let s = 1.; // when using TMP_PYTHON_LASER_H_FOR_NANNOU -- doesn't work? // let s = 1.; // when using TMP_PYTHON_LASER_H_FOR_NANNOU -- doesn't work?
let s = 0xFFF as f32 / 2.; // when using TMP_PYTHON_LASER_H let s = 0xFFF as f32 / 2.; // when using TMP_PYTHON_LASER_H
let position = [new_position[0]/s - 1., new_position[1]/s - 1.]; let position = [new_position[0]/s - 1., new_position[1]/s - 1.];
@ -514,7 +524,15 @@ fn view_line_canvas(app: &App, model: &Model, frame: Frame) {
let draw = app.draw(); let draw = app.draw();
// set background to blue // set background to blue
draw.background().color(DARKGRAY);
let bgcolor = match model.current_lines.space {
CoordinateSpace::Laser => MEDIUMSLATEBLUE,
_ => match model.connected{
true => DARKGRAY,
false => LIGHTCORAL,
},
};
draw.background().color(bgcolor);
let win = app.window_rect(); let win = app.window_rect();
@ -522,6 +540,8 @@ fn view_line_canvas(app: &App, model: &Model, frame: Frame) {
let translate_x = -300.; let translate_x = -300.;
let translate_y = -100.; let translate_y = -100.;
draw_grid(&draw, &win, scale, 1.); draw_grid(&draw, &win, scale, 1.);
// let t = app.time; // let t = app.time;

View file

@ -2,7 +2,7 @@ use bevy::prelude::*;
use serde::{Serialize,Deserialize}; use serde::{Serialize,Deserialize};
use std::time::Instant; use std::time::Instant;
use nannou_laser as laser; use nannou_laser as laser;
use serde_repr::*;
#[derive(Serialize,Deserialize)] #[derive(Serialize,Deserialize)]
pub struct Frame { pub struct Frame {
@ -67,14 +67,25 @@ impl RenderableLine {
} }
} }
// see also trap/lines.py for matching values
#[derive(Clone, Debug, Serialize_repr, Deserialize_repr)]
#[repr(u8)]
pub enum CoordinateSpace {
Image = 1,
UndistortedImage = 2,
World = 3,
Laser = 4,
}
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RenderableLines{ pub struct RenderableLines{
pub lines: Vec<RenderableLine> pub lines: Vec<RenderableLine>,
pub space: CoordinateSpace, // enum in python
} }
impl RenderableLines{ impl RenderableLines{
pub fn new() -> Self{ pub fn new() -> Self{
RenderableLines { lines: Vec::new() } RenderableLines { lines: Vec::new(), space: CoordinateSpace::World }
} }
// pub fn append(&mut self, &mut rl: RenderableLines){ // pub fn append(&mut self, &mut rl: RenderableLines){
@ -93,7 +104,7 @@ impl RenderableLines{
return self.clone(); return self.clone();
} }
Self { lines: self.lines.iter().map(|l| { l.with_alpha(alpha)}).collect() } Self { lines: self.lines.iter().map(|l| { l.with_alpha(alpha)}).collect(), space: self.space.clone() }
} }
} }
@ -124,7 +135,7 @@ impl From<&Track> for RenderableLines{
} }
lines.push(RenderableLine{points}) lines.push(RenderableLine{points})
} }
RenderableLines { lines } RenderableLines { lines, space: CoordinateSpace::World }
} }
} }

View file

@ -57,6 +57,7 @@ fn receive_zmq_lines(
if items[0].is_readable() { if items[0].is_readable() {
let json = subscriber.recv_string(0).unwrap().unwrap(); let json = subscriber.recv_string(0).unwrap().unwrap();
// dbg!(&json[4..]); // dbg!(&json[4..]);
dbg!(&json);
// let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?"); // let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?");
let res: Result<RenderableLines> = serde_json::from_str(&json); let res: Result<RenderableLines> = serde_json::from_str(&json);