217 lines
		
	
	
		
			No EOL
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			No EOL
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
use bevy::prelude::*;
 | 
						|
 | 
						|
use bevy_nannou::prelude::*;
 | 
						|
use bevy_nannou::NannouPlugin;
 | 
						|
 | 
						|
use nannou_laser::point::Rgb;
 | 
						|
 | 
						|
use trap::laser::apply_homography_matrix;
 | 
						|
use trap::laser::python_cv_h_into_mat3;
 | 
						|
use trap::laser::LaserApi;
 | 
						|
use trap::laser::LaserModel;
 | 
						|
use trap::laser::LaserTimer;
 | 
						|
use trap::laser::TMP_PYTHON_LASER_H;
 | 
						|
use trap::shapes::PositionAndIntensity;
 | 
						|
use trap::tracks::LaserPoints;
 | 
						|
use trap::tracks::RenderableLines;
 | 
						|
use trap::tracks::SpawnedTime;
 | 
						|
use trap::tracks::Track;
 | 
						|
use trap::zmqplugin::ZmqPlugin;
 | 
						|
// use iyes_perf_ui::PerfUiPlugin;
 | 
						|
 | 
						|
use nannou_laser as laser;
 | 
						|
use trap::zmqplugin::ZmqReceiveTarget;
 | 
						|
 | 
						|
use std::time::Duration;
 | 
						|
 | 
						|
 | 
						|
pub mod trap;
 | 
						|
 | 
						|
fn main() {
 | 
						|
    let mut app = App::new();
 | 
						|
    // app.add_plugins((DefaultPlugins, NannouPlugin))
 | 
						|
    app.add_plugins((DefaultPlugins, NannouPlugin))
 | 
						|
        // .add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin)
 | 
						|
        // .add_plugins(bevy::diagnostic::EntityCountDiagnosticsPlugin)
 | 
						|
        // .add_plugins(bevy::diagnostic::SystemInformationDiagnosticsPlugin)
 | 
						|
        // .add_plugins(PerfUiPlugin)
 | 
						|
        .add_systems(Startup, setup)
 | 
						|
        .add_systems(Startup, setup_laser)
 | 
						|
        // .add_systems(Update, update)
 | 
						|
        .add_systems(Update, exit_system)
 | 
						|
 | 
						|
 | 
						|
        .add_plugins(ZmqPlugin { 
 | 
						|
            // url: "tcp://localhost:5558".to_string(),
 | 
						|
            url: "tcp://100.109.175.82:99174".to_string(),
 | 
						|
            // url: "tcp://127.0.0.1:99173".to_string(),
 | 
						|
            filter: "".to_string(),
 | 
						|
            target: ZmqReceiveTarget::LINES
 | 
						|
        })
 | 
						|
 | 
						|
        
 | 
						|
        .run();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Because of world.insert_non_send_resource, this is an exclusive system
 | 
						|
// see: https://bevy-cheatbook.github.io/programming/exclusive.html
 | 
						|
fn setup_laser(mut commands: Commands) {
 | 
						|
 | 
						|
    // laser works on non-exclusive system (like the normal setup()), _but_ world
 | 
						|
    // is needed in the laser callback
 | 
						|
    
 | 
						|
    // Initialise the state that we want to live on the laser thread and spawn the stream.
 | 
						|
    let laser_model = LaserModel::new();
 | 
						|
    let _laser_api = laser::Api::new();
 | 
						|
    // let detected_dacs = _laser_api.detect_dacs(DacVariant::DacVariantHelios);
 | 
						|
    
 | 
						|
    // while let Ok(res) = detected_dacs {
 | 
						|
    //     if let laser::DetectDacs::Helios { previous_dac } = res {
 | 
						|
    //         info!("DACS: {:?}", previous_dac);
 | 
						|
    //     }
 | 
						|
    // }
 | 
						|
 | 
						|
    let laser_stream = _laser_api
 | 
						|
        .new_frame_stream(laser_model, laser_frame_producer)
 | 
						|
        // .detected_dac(dac)
 | 
						|
        .build()
 | 
						|
        .unwrap();
 | 
						|
 | 
						|
 | 
						|
    let api = LaserApi {
 | 
						|
        _laser_api,
 | 
						|
        laser_stream,
 | 
						|
        // current_points: Vec::new(),
 | 
						|
    };
 | 
						|
    commands.spawn((api, LaserTimer {
 | 
						|
        // create the non-repeating fuse timer
 | 
						|
        timer: Timer::new(Duration::from_millis(1000), TimerMode::Repeating),
 | 
						|
    }));
 | 
						|
}
 | 
						|
 | 
						|
fn setup(mut commands: Commands) {
 | 
						|
    // Spawn a camera for our main window
 | 
						|
    // TODO: look into https://docs.rs/visioncortex/latest/visioncortex/struct.PerspectiveTransform.html
 | 
						|
 | 
						|
    commands.spawn(render::NannouCamera);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
fn text2points_with_color(position_and_intensity: PositionAndIntensity, color: Rgb) -> laser::Point{
 | 
						|
    let used_color = color.map(|v| v * position_and_intensity[2]);
 | 
						|
    let p  = [position_and_intensity[0], -position_and_intensity[1]];
 | 
						|
    laser::Point::new(p, color)
 | 
						|
}
 | 
						|
 | 
						|
fn text2points(position_and_intensity: PositionAndIntensity) -> laser::Point{
 | 
						|
    let color = match position_and_intensity[2] {
 | 
						|
        1.0 => [1.0; 3],
 | 
						|
        0.0 => [0.0; 3],
 | 
						|
        _ => [1.0; 3] // TODO add provided color
 | 
						|
    };
 | 
						|
    let p  = [position_and_intensity[0], -position_and_intensity[1]];
 | 
						|
    laser::Point::new(p, color)
 | 
						|
}
 | 
						|
 | 
						|
// impl Into<Mat3> for [[f32;3]; 3] {
 | 
						|
//     fn from(m) -> Self{
 | 
						|
 | 
						|
//     }
 | 
						|
// }
 | 
						|
 | 
						|
const LASER_H: Mat3 = python_cv_h_into_mat3(TMP_PYTHON_LASER_H);
 | 
						|
// const LASER_H: Mat3 = python_cv_h_into_mat3(TMP_PYTHON_LASER_H_FOR_NANNOU);
 | 
						|
 | 
						|
fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
 | 
						|
    
 | 
						|
    // let dt = model.t.elapsed().as_millis();
 | 
						|
    // let use_second = (dt % 1000) > 500;
 | 
						|
 | 
						|
    // let positions = match use_second {
 | 
						|
    //     true => trap::shapes::YOUR_FUTURE,
 | 
						|
    //     false => trap::shapes::ARE_YOU_SURE,
 | 
						|
    // };
 | 
						|
    
 | 
						|
    let points = model.current_points.clone();
 | 
						|
 | 
						|
    let mut new_points = Vec::new();
 | 
						|
    for point in points.into_iter() {
 | 
						|
        let p = point.position;
 | 
						|
        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 = 0xFFF as f32; // when using TMP_PYTHON_LASER_H
 | 
						|
 | 
						|
        let new_point = laser::Point {
 | 
						|
            position: [new_position[0]/s, new_position[1]/s],
 | 
						|
            .. point
 | 
						|
        };
 | 
						|
        new_points.push(new_point);
 | 
						|
    }
 | 
						|
 | 
						|
    info!("Points {}", new_points.len());
 | 
						|
    // println!("{:?}", new_points);
 | 
						|
    frame.add_lines(new_points);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
fn get_laser_lines(use_second: bool) -> Vec<nannou_laser::Point>{
 | 
						|
    let positions = match use_second {
 | 
						|
        true => trap::shapes::YOUR_FUTURE,
 | 
						|
        false => trap::shapes::ARE_YOU_SURE,
 | 
						|
    };
 | 
						|
    let points = positions.iter().cloned().map(text2points).collect();
 | 
						|
    return points
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
fn exit_system(keys: Res<ButtonInput<KeyCode>>, mut exit: EventWriter<AppExit>) {
 | 
						|
    if keys.just_pressed(KeyCode::KeyQ) {
 | 
						|
        info!("Sending exit command");
 | 
						|
        exit.send(AppExit::Success);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
fn update(
 | 
						|
    // mut commands: Commands,
 | 
						|
    // keys: Res<ButtonInput<KeyCode>>,
 | 
						|
    draws: Query<&Draw>,
 | 
						|
    mut lasers: Query<(&mut LaserApi, &mut LaserTimer)>,
 | 
						|
    tracks: Query<(&Track, &SpawnedTime)>,
 | 
						|
    time: Res<Time>,
 | 
						|
) {
 | 
						|
    let mut lines = RenderableLines::new();
 | 
						|
    for (track, created_at) in tracks.iter() {
 | 
						|
        // println!("{} {}, history: {}", track.track_id.to_string(), created_at.instant.elapsed().as_millis(), track.history.len());
 | 
						|
        let rl = RenderableLines::from(track);
 | 
						|
        lines.lines.extend(rl.lines);
 | 
						|
    }
 | 
						|
   
 | 
						|
    for (laser_api, mut laser_timer) in lasers.iter_mut() {
 | 
						|
        
 | 
						|
        laser_timer.timer.tick(time.delta());
 | 
						|
        
 | 
						|
        let version = laser_timer.timer.elapsed().as_millis() > 500;
 | 
						|
        debug!("{} {}", version, laser_timer.timer.elapsed().as_millis());
 | 
						|
        // let lines = get_laser_lines(version);
 | 
						|
        let points: LaserPoints = (&lines).into();
 | 
						|
        laser_api.laser_stream.send(|laser|  {
 | 
						|
            let laserpoints: LaserPoints = points;
 | 
						|
            // TODO: homography
 | 
						|
            laser.current_points = laserpoints; 
 | 
						|
        }).unwrap();
 | 
						|
    }
 | 
						|
 | 
						|
    for draw in draws.iter() {
 | 
						|
        draw.background().color(DIM_GRAY);
 | 
						|
 | 
						|
        draw.ellipse().color(LIGHT_GRAY).w_h(100.0, 100.0);
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
} |