autd3_simulator/
simulator.rs

1/*
2 * File: simulator.rs
3 * Project: src
4 * Created Date: 24/05/2023
5 * Author: Shun Suzuki
6 * -----
7 * Last Modified: 27/07/2023
8 * Modified By: Shun Suzuki (suzuki@hapis.k.u-tokyo.ac.jp)
9 * -----
10 * Copyright (c) 2023 Shun Suzuki. All rights reserved.
11 *
12 */
13
14use std::{
15    error::Error,
16    f32::consts::PI,
17    ffi::OsStr,
18    net::ToSocketAddrs,
19    path::{Path, PathBuf},
20    sync::{Arc, RwLock},
21};
22
23use crate::{
24    common::transform::{to_gl_pos, to_gl_rot},
25    field_compute_pipeline::{Config, FieldComputePipeline},
26    imgui_renderer::ImGuiRenderer,
27    renderer::Renderer,
28    slice_viewer::SliceViewer,
29    sound_sources::{Drive, SoundSources},
30    trans_viewer::TransViewer,
31    update_flag::UpdateFlag,
32    viewer_settings::ViewerSettings,
33    Quaternion, Vector3, SCALE,
34};
35use autd3_core::{autd3_device::AUTD3, geometry::Device, TxDatagram, FPGA_CLK_FREQ};
36use autd3_firmware_emulator::CPUEmulator;
37use crossbeam_channel::{bounded, Receiver, Sender, TryRecvError};
38use vulkano::{
39    command_buffer::{
40        AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
41    },
42    sync::GpuFuture,
43};
44use winit::{
45    event::{Event, WindowEvent},
46    event_loop::{ControlFlow, EventLoopBuilder},
47    platform::run_return::EventLoopExtRunReturn,
48};
49
50use futures_util::future::FutureExt;
51use tokio::{runtime::Builder, sync::oneshot};
52use tonic::{transport::Server, Request, Response, Status};
53
54use autd3_protobuf::*;
55
56enum Signal {
57    ConfigGeometry(Geometry),
58    Send(TxRawData),
59    Close,
60}
61
62struct SimulatorServer {
63    rx_buf: Arc<RwLock<autd3_core::RxDatagram>>,
64    sender: Sender<Signal>,
65}
66
67#[tonic::async_trait]
68impl simulator_server::Simulator for SimulatorServer {
69    async fn config_geomety(
70        &self,
71        req: Request<Geometry>,
72    ) -> Result<Response<GeometryResponse>, Status> {
73        if self
74            .sender
75            .send(Signal::ConfigGeometry(req.into_inner()))
76            .is_err()
77        {
78            return Err(Status::unavailable("Simulator is closed"));
79        }
80        Ok(Response::new(GeometryResponse {}))
81    }
82
83    async fn send_data(&self, req: Request<TxRawData>) -> Result<Response<SendResponse>, Status> {
84        if self.sender.send(Signal::Send(req.into_inner())).is_err() {
85            return Err(Status::unavailable("Simulator is closed"));
86        }
87        Ok(Response::new(SendResponse { success: true }))
88    }
89
90    async fn read_data(&self, _: Request<ReadRequest>) -> Result<Response<RxMessage>, Status> {
91        let rx = self.rx_buf.read().unwrap();
92        Ok(Response::new(RxMessage {
93            data: rx.iter().flat_map(|c| [c.ack, c.msg_id]).collect(),
94        }))
95    }
96
97    async fn close(&self, _: Request<CloseRequest>) -> Result<Response<CloseResponse>, Status> {
98        if self.sender.send(Signal::Close).is_err() {
99            return Err(Status::unavailable("Simulator is closed"));
100        }
101        Ok(Response::new(CloseResponse { success: true }))
102    }
103}
104
105/// AUTD Simulator
106#[derive(Default)]
107pub struct Simulator {
108    window_width: Option<u32>,
109    window_height: Option<u32>,
110    vsync: Option<bool>,
111    port: Option<u16>,
112    gpu_idx: Option<i32>,
113    settings: ViewerSettings,
114    config_path: Option<PathBuf>,
115}
116
117impl Simulator {
118    pub fn new() -> Self {
119        Self {
120            window_width: None,
121            window_height: None,
122            vsync: None,
123            port: None,
124            gpu_idx: None,
125            settings: ViewerSettings::default(),
126            config_path: None,
127        }
128    }
129
130    /// Set window size
131    pub fn with_window_size(mut self, width: u32, height: u32) -> Self {
132        self.window_width = Some(width);
133        self.window_height = Some(height);
134        self
135    }
136
137    /// Set vsync
138    pub fn with_vsync(mut self, vsync: bool) -> Self {
139        self.vsync = Some(vsync);
140        self
141    }
142
143    /// Set port
144    pub fn with_port(mut self, port: u16) -> Self {
145        self.port = Some(port);
146        self
147    }
148
149    /// Set GPU index
150    ///
151    /// # Arguments
152    ///
153    /// * `gpu_idx` - GPU index. If -1, use the most suitable GPU.
154    ///
155    pub fn with_gpu_idx(mut self, gpu_idx: i32) -> Self {
156        self.gpu_idx = Some(gpu_idx);
157        self
158    }
159
160    /// Set viewer settings
161    pub fn with_settings(mut self, settings: ViewerSettings) -> Self {
162        self.settings = settings;
163        self
164    }
165
166    /// Set config path where settings are saved
167    pub fn with_config_path<S: AsRef<OsStr> + Sized>(mut self, config_path: S) -> Self {
168        self.config_path = Some(Path::new(&config_path).to_owned());
169        self
170    }
171
172    /// Get viewer settings
173    pub fn get_settings(&self) -> &ViewerSettings {
174        &self.settings
175    }
176
177    /// Run Simulator
178    ///
179    /// # Returns
180    ///
181    /// ## Platform-specific
182    ///
183    /// X11 / Wayland: This function returns 1 upon disconnection from the display server.
184    pub fn run(&mut self) -> i32 {
185        spdlog::info!("Initializing window...");
186
187        let (tx, rx) = bounded(32);
188
189        let (tx_shutdown, rx_shutdown) = oneshot::channel::<()>();
190        let port = self.port.unwrap_or(self.settings.port);
191
192        let rx_buf = Arc::new(RwLock::new(autd3_core::RxDatagram::new(0)));
193        let rx_buf_clone = rx_buf.clone();
194
195        let server_th = std::thread::spawn(move || {
196            spdlog::info!("Waiting for client connection on http://0.0.0.0:{}", port);
197            let body = async {
198                Server::builder()
199                    .add_service(simulator_server::SimulatorServer::new(SimulatorServer {
200                        rx_buf: rx_buf_clone,
201                        sender: tx,
202                    }))
203                    .serve_with_shutdown(
204                        format!("0.0.0.0:{port}")
205                            .to_socket_addrs()
206                            .unwrap()
207                            .next()
208                            .unwrap(),
209                        rx_shutdown.map(drop),
210                    )
211                    .await
212            };
213            Builder::new_multi_thread()
214                .enable_all()
215                .build()
216                .unwrap()
217                .block_on(body)
218        });
219
220        self.run_simulator(server_th, rx_buf, rx, tx_shutdown)
221    }
222
223    fn run_simulator(
224        &mut self,
225        server_th: std::thread::JoinHandle<Result<(), tonic::transport::Error>>,
226        rx_buf: Arc<RwLock<autd3_core::RxDatagram>>,
227        receiver: Receiver<Signal>,
228        shutdown: tokio::sync::oneshot::Sender<()>,
229    ) -> i32 {
230        let mut event_loop = EventLoopBuilder::<()>::with_user_event().build();
231
232        let mut render = Renderer::new(
233            &event_loop,
234            "AUTD Simulator",
235            self.window_width.unwrap_or(self.settings.window_width) as _,
236            self.window_height.unwrap_or(self.settings.window_height) as _,
237            self.vsync.unwrap_or(self.settings.vsync),
238            self.gpu_idx.unwrap_or(self.settings.gpu_idx),
239        );
240
241        render.move_camera(&self.settings);
242
243        let mut sources = SoundSources::new();
244
245        let mut cpus: Vec<CPUEmulator> = Vec::new();
246
247        let mut field_compute_pipeline = FieldComputePipeline::new(&render, &self.settings);
248        let mut slice_viewer = SliceViewer::new(&render, &self.settings);
249        let mut imgui = ImGuiRenderer::new(self.settings.clone(), &self.config_path, &render);
250        let mut trans_viewer = TransViewer::new(&render);
251
252        let mut is_initialized = false;
253        let mut is_source_update = false;
254        let mut is_running = true;
255
256        let server_th_ref = &server_th;
257        let res = event_loop.run_return(move |event, _, control_flow| {
258            cpus.iter_mut().for_each(CPUEmulator::update);
259            if cpus.iter().any(CPUEmulator::should_update) {
260                rx_buf.write().unwrap().copy_from_iter(cpus.iter().map(|c| {
261                    autd3_core::RxMessage {
262                        ack: c.ack(),
263                        msg_id: c.msg_id(),
264                    }
265                }));
266            }
267
268            match receiver.try_recv() {
269                Ok(Signal::ConfigGeometry(geometry)) => {
270                    sources.clear();
271                    cpus.clear();
272
273                    let devices = Vec::<_>::from_msg(&geometry);
274                    devices.iter().for_each(|autd3| {
275                        autd3.get_transducers(0).iter().for_each(|(_, p, r)| {
276                            sources.add(
277                                to_gl_pos(Vector3::new(p.x as _, p.y as _, p.z as _)),
278                                to_gl_rot(Quaternion::new(r.w as _, r.i as _, r.j as _, r.k as _)),
279                                Drive::new(1.0, 0.0, 1.0, 40e3, self.settings.sound_speed),
280                                1.0,
281                            );
282                        });
283                    });
284
285                    cpus = (0..sources.len() / AUTD3::NUM_TRANS_IN_UNIT)
286                        .map(|i| CPUEmulator::new(i, AUTD3::NUM_TRANS_IN_UNIT))
287                        .collect();
288
289                    *rx_buf.write().unwrap() = autd3_core::RxDatagram::new(devices.len());
290
291                    field_compute_pipeline.init(&render, &sources);
292                    trans_viewer.init(&render, &sources);
293                    slice_viewer.init(&self.settings);
294                    imgui.init(devices.len());
295
296                    is_initialized = true;
297                }
298                Ok(Signal::Send(raw)) => {
299                    let tx = TxDatagram::from_msg(&raw);
300                    cpus.iter_mut().for_each(|cpu| {
301                        cpu.send(&tx);
302                    });
303                    rx_buf.write().unwrap().copy_from_iter(cpus.iter().map(|c| {
304                        autd3_core::RxMessage {
305                            ack: c.ack(),
306                            msg_id: c.msg_id(),
307                        }
308                    }));
309
310                    is_source_update = true;
311                }
312                Ok(Signal::Close) => {
313                    is_initialized = false;
314                    sources.clear();
315                    cpus.clear();
316                }
317                Err(TryRecvError::Empty) => {}
318                _ => {}
319            }
320
321            match event {
322                Event::WindowEvent {
323                    event: WindowEvent::CloseRequested,
324                    ..
325                } => {
326                    is_running = false;
327                    *control_flow = ControlFlow::Exit;
328                }
329                Event::WindowEvent {
330                    event: WindowEvent::Resized(..),
331                    window_id,
332                } if window_id == render.window().id() => {
333                    render.resize();
334                    imgui.resized(render.window(), &event);
335                }
336                Event::WindowEvent {
337                    event:
338                        WindowEvent::ScaleFactorChanged {
339                            scale_factor,
340                            new_inner_size,
341                        },
342                    window_id,
343                } if window_id == render.window().id() => {
344                    *new_inner_size = render
345                        .window()
346                        .inner_size()
347                        .to_logical::<u32>(render.window().scale_factor())
348                        .to_physical(scale_factor);
349                    render.resize();
350                    let event_imgui: Event<'_, ()> = Event::WindowEvent {
351                        window_id,
352                        event: WindowEvent::ScaleFactorChanged {
353                            scale_factor,
354                            new_inner_size,
355                        },
356                    };
357                    imgui.resized(render.window(), &event_imgui);
358                }
359                Event::MainEventsCleared => {
360                    imgui.prepare_frame(render.window());
361                    render.window().request_redraw();
362                }
363                Event::NewEvents(_) => {
364                    imgui.update_delta_time();
365                    render.window().request_redraw();
366                }
367                Event::RedrawRequested(_) => {
368                    let before_pipeline_future = match render.start_frame() {
369                        Err(e) => {
370                            eprintln!("{}", e);
371                            return;
372                        }
373                        Ok(future) => future,
374                    };
375                    let after_future = {
376                        let framebuffer = render.frame_buffer();
377
378                        let mut builder = AutoCommandBufferBuilder::primary(
379                            render.command_buffer_allocator(),
380                            render.queue().queue_family_index(),
381                            CommandBufferUsage::OneTimeSubmit,
382                        )
383                        .unwrap();
384
385                        let clear_values = vec![
386                            Some(self.settings.background.into()),
387                            Some(1f32.into()),
388                            None,
389                        ];
390                        builder
391                            .begin_render_pass(
392                                RenderPassBeginInfo {
393                                    clear_values,
394                                    ..RenderPassBeginInfo::framebuffer(framebuffer)
395                                },
396                                SubpassContents::Inline,
397                            )
398                            .unwrap()
399                            .set_viewport(0, [render.viewport()]);
400
401                        if is_initialized {
402                            render.move_camera(&self.settings);
403                            let view = render.get_view();
404                            let proj = render.get_projection(&self.settings);
405                            let slice_model = slice_viewer.model();
406                            trans_viewer.render(view, proj, &mut builder);
407                            slice_viewer.render(&render, view, proj, &self.settings, &mut builder);
408                            builder.end_render_pass().unwrap();
409
410                            let mut update_flag = imgui.update(
411                                &mut cpus,
412                                &mut sources,
413                                &render,
414                                &mut builder,
415                                &mut self.settings,
416                            );
417                            if is_source_update {
418                                update_flag.set(UpdateFlag::UPDATE_SOURCE_DRIVE, true);
419                                is_source_update = false;
420                            }
421
422                            if update_flag.contains(UpdateFlag::UPDATE_SOURCE_DRIVE) {
423                                cpus.iter().for_each(|cpu| {
424                                    let cycles = cpu.fpga().cycles();
425                                    let drives = cpu.fpga().duties_and_phases(imgui.stm_idx());
426                                    let m = if self.settings.mod_enable {
427                                        cpu.fpga().modulation_at(imgui.mod_idx()) as f32 / 255.
428                                    } else {
429                                        1.
430                                    };
431                                    sources
432                                        .drives_mut()
433                                        .skip(cpu.id() * AUTD3::NUM_TRANS_IN_UNIT)
434                                        .take(AUTD3::NUM_TRANS_IN_UNIT)
435                                        .enumerate()
436                                        .for_each(|(i, d)| {
437                                            d.amp = (PI * drives[i].0 as f32 * m
438                                                / cycles[i] as f32)
439                                                .sin();
440                                            d.phase =
441                                                2. * PI * drives[i].1 as f32 / cycles[i] as f32;
442                                            d.set_wave_number(
443                                                FPGA_CLK_FREQ as f32 / cycles[i] as f32,
444                                                self.settings.sound_speed,
445                                            );
446                                        });
447                                });
448                            }
449
450                            field_compute_pipeline.update(
451                                &render,
452                                &sources,
453                                &self.settings,
454                                &update_flag,
455                            );
456                            slice_viewer.update(&render, &self.settings, &update_flag);
457                            trans_viewer.update(&sources, &update_flag);
458
459                            let command_buffer = builder.build().unwrap();
460
461                            let field_image = slice_viewer.field_image_view();
462
463                            if update_flag.contains(UpdateFlag::SAVE_IMAGE) {
464                                let image_buffer_content = field_image.read().unwrap();
465                                let img_x = (self.settings.slice_width
466                                    / self.settings.slice_pixel_size)
467                                    as u32;
468                                let img_y = (self.settings.slice_height
469                                    / self.settings.slice_pixel_size)
470                                    as u32;
471                                let mut img_buf = image::ImageBuffer::new(img_x, img_y);
472                                img_buf
473                                    .enumerate_pixels_mut()
474                                    .zip(image_buffer_content.iter())
475                                    .for_each(|((_, _, pixel), [r, g, b, a])| {
476                                        let r = (r * 255.0) as u8;
477                                        let g = (g * 255.0) as u8;
478                                        let b = (b * 255.0) as u8;
479                                        let a = (a * 255.0) as u8;
480                                        *pixel = image::Rgba([r, g, b, a]);
481                                    });
482                                image::imageops::flip_vertical(&img_buf)
483                                    .save(&self.settings.image_save_path)
484                                    .unwrap();
485                            }
486
487                            let config = Config {
488                                source_num: sources.len() as _,
489                                color_scale: self.settings.slice_color_scale,
490                                width: (self.settings.slice_width / self.settings.slice_pixel_size)
491                                    as _,
492                                height: (self.settings.slice_height
493                                    / self.settings.slice_pixel_size)
494                                    as _,
495                                pixel_size: self.settings.slice_pixel_size as _,
496                                scale: SCALE,
497                                model: slice_model.into(),
498                                ..Default::default()
499                            };
500                            let after_compute = field_compute_pipeline
501                                .compute(&render, config, field_image, &self.settings)
502                                .join(before_pipeline_future);
503                            let future = after_compute
504                                .then_execute(render.queue(), command_buffer)
505                                .unwrap();
506
507                            future.boxed()
508                        } else {
509                            builder.end_render_pass().unwrap();
510
511                            imgui.waiting(&render, &mut builder);
512
513                            let command_buffer = builder.build().unwrap();
514
515                            let future = before_pipeline_future
516                                .then_execute(render.queue(), command_buffer)
517                                .unwrap();
518
519                            future.boxed()
520                        }
521                    };
522
523                    render.finish_frame(after_future);
524                }
525                event => {
526                    imgui.handle_event(render.window(), &event);
527                }
528            }
529
530            if server_th_ref.is_finished() || !is_running {
531                spdlog::default_logger().flush();
532
533                *control_flow = ControlFlow::Exit;
534            }
535        });
536
537        let _ = shutdown.send(());
538        if let Err(e) = server_th.join().unwrap() {
539            match e.source() {
540                Some(e) => spdlog::error!("Server error: {}", e),
541                None => spdlog::error!("Server error: {}", e),
542            }
543        }
544
545        res
546    }
547}