1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use autd_geometry::consts::NUM_TRANS_IN_UNIT;
use autd_geometry::Geometry;
use autd_geometry::Vector3;
use crate::consts::ULTRASOUND_WAVELENGTH;
use crate::convert_to_pwm_params;
use crate::Gain;
pub struct BesselBeamGain {
point: Vector3,
dir: Vector3,
theta_z: f64,
amp: u8,
data: Option<Vec<u8>>,
}
impl BesselBeamGain {
pub fn create(point: Vector3, dir: Vector3, theta_z: f64) -> Box<BesselBeamGain> {
BesselBeamGain::create_with_amp(point, dir, theta_z, 0xff)
}
pub fn create_with_amp(
point: Vector3,
dir: Vector3,
theta_z: f64,
amp: u8,
) -> Box<BesselBeamGain> {
Box::new(BesselBeamGain {
point,
dir,
theta_z,
amp,
data: None,
})
}
}
impl Gain for BesselBeamGain {
fn get_data(&self) -> &[u8] {
assert!(self.data.is_some());
match &self.data {
Some(data) => data,
None => panic!(),
}
}
fn build(&mut self, geometry: &Geometry) {
if self.data.is_some() {
return;
}
let num_devices = geometry.num_devices();
let num_trans = NUM_TRANS_IN_UNIT * num_devices;
let mut data = Vec::with_capacity(num_trans * 2);
let dir = self.dir.normalize();
let v = Vector3::new(dir.y, -dir.x, 0.);
let theta_w = v.norm().asin();
let point = self.point;
let theta_z = self.theta_z;
for i in 0..num_trans {
let trp = geometry.position(i);
let r = trp - point;
let xr = r.cross(&v);
let r = r * theta_w.cos() + xr * theta_w.sin() + v * (v.dot(&r) * (1. - theta_w.cos()));
let dist = theta_z.sin() * (r.x * r.x + r.y * r.y).sqrt() - theta_z.cos() * r.z;
let phase = (dist % ULTRASOUND_WAVELENGTH) / ULTRASOUND_WAVELENGTH;
let phase = (255.0 * (1.0 - phase)) as u8;
let amp: u8 = self.amp;
let (d, s) = convert_to_pwm_params(amp, phase);
data.push(s);
data.push(d);
}
self.data = Some(data);
}
}