autd3_driver/
autd3_device.rs

1use crate::{
2    defined::mm,
3    geometry::{Device, IntoDevice, Isometry, Point3, Transducer, Translation, UnitQuaternion},
4};
5use getset::Getters;
6
7/// AUTD3 device.
8#[derive(Clone, Copy, Debug, Getters)]
9pub struct AUTD3 {
10    /// The position of the AUTD3 device.
11    pub pos: Point3,
12    /// The rotation of the AUTD3 device.
13    pub rot: UnitQuaternion,
14}
15
16impl Default for AUTD3 {
17    fn default() -> Self {
18        Self {
19            pos: Point3::origin(),
20            rot: UnitQuaternion::identity(),
21        }
22    }
23}
24
25impl AUTD3 {
26    /// The number of transducers in x-axis.
27    pub const NUM_TRANS_X: usize = 18;
28    /// The number of transducers in y-axis.
29    pub const NUM_TRANS_Y: usize = 14;
30    /// The number of transducers in a unit.
31    pub const NUM_TRANS_IN_UNIT: usize = Self::NUM_TRANS_X * Self::NUM_TRANS_Y - 3;
32    /// The spacing between transducers.
33    pub const TRANS_SPACING: f32 = 10.16 * mm;
34    /// The width of the device (including the substrate).
35    pub const DEVICE_WIDTH: f32 = 192.0 * mm;
36    /// The height of the device (including the substrate).
37    pub const DEVICE_HEIGHT: f32 = 151.4 * mm;
38
39    /// Create a new AUTD3 device.
40    #[must_use]
41    pub const fn new(pos: Point3, rot: UnitQuaternion) -> Self {
42        Self { pos, rot }
43    }
44
45    #[must_use]
46    const fn is_missing_transducer(x: usize, y: usize) -> bool {
47        if Self::NUM_TRANS_X <= x || Self::NUM_TRANS_Y <= y {
48            return true;
49        }
50        y == 1 && (x == 1 || x == 2 || x == 16)
51    }
52
53    /// Gets the index in x- and y-axis from the transducer index.
54    #[must_use]
55    pub const fn grid_id(idx: usize) -> (usize, usize) {
56        let local_id = idx % Self::NUM_TRANS_IN_UNIT;
57        let uid = match local_id {
58            0..19 => local_id,
59            19..32 => local_id + 2,
60            _ => local_id + 3,
61        };
62        (uid % Self::NUM_TRANS_X, uid / Self::NUM_TRANS_X)
63    }
64}
65
66impl IntoDevice for AUTD3 {
67    fn into_device(self, dev_idx: u16) -> Device {
68        tracing::debug!("Configure device[{}]: {:?}", dev_idx, self);
69        let isometry = Isometry {
70            rotation: self.rot,
71            translation: Translation::from(self.pos),
72        };
73        Device::new(
74            dev_idx,
75            self.rot,
76            itertools::iproduct!(0..Self::NUM_TRANS_Y, 0..Self::NUM_TRANS_X)
77                .filter(|&(y, x)| !Self::is_missing_transducer(x, y))
78                .map(|(y, x)| {
79                    isometry
80                        * Point3::new(
81                            x as f32 * Self::TRANS_SPACING,
82                            y as f32 * Self::TRANS_SPACING,
83                            0.,
84                        )
85                })
86                .enumerate()
87                .map(|(i, p)| Transducer::new(i as _, dev_idx, p.xyz()))
88                .collect(),
89        )
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn test_num_devices() {
99        let dev = AUTD3::default().into_device(0);
100        assert_eq!(AUTD3::NUM_TRANS_IN_UNIT, dev.num_transducers());
101    }
102
103    #[rstest::rstest]
104    #[test]
105    #[case(0, Point3::new(0., 0., 0.))]
106    #[case(1, Point3::new(AUTD3::TRANS_SPACING, 0., 0.))]
107    #[case(18, Point3::new(0., AUTD3::TRANS_SPACING, 0.))]
108    #[case(248, Point3::new(17. * AUTD3::TRANS_SPACING, 13. * AUTD3::TRANS_SPACING, 0.))]
109    fn test_position(#[case] idx: usize, #[case] expected: Point3) {
110        let dev = AUTD3::default().into_device(0);
111        assert_eq!(&expected, dev[idx].position());
112    }
113
114    #[rstest::rstest]
115    #[test]
116    #[case(0, 0, false)]
117    #[case(1, 0, false)]
118    #[case(2, 0, false)]
119    #[case(3, 0, false)]
120    #[case(4, 0, false)]
121    #[case(5, 0, false)]
122    #[case(6, 0, false)]
123    #[case(7, 0, false)]
124    #[case(8, 0, false)]
125    #[case(9, 0, false)]
126    #[case(10, 0, false)]
127    #[case(11, 0, false)]
128    #[case(12, 0, false)]
129    #[case(13, 0, false)]
130    #[case(14, 0, false)]
131    #[case(15, 0, false)]
132    #[case(16, 0, false)]
133    #[case(17, 0, false)]
134    #[case(0, 1, false)]
135    #[case(1, 1, true)]
136    #[case(2, 1, true)]
137    #[case(3, 1, false)]
138    #[case(4, 1, false)]
139    #[case(5, 1, false)]
140    #[case(6, 1, false)]
141    #[case(7, 1, false)]
142    #[case(8, 1, false)]
143    #[case(9, 1, false)]
144    #[case(10, 1, false)]
145    #[case(11, 1, false)]
146    #[case(12, 1, false)]
147    #[case(13, 1, false)]
148    #[case(14, 1, false)]
149    #[case(15, 1, false)]
150    #[case(16, 1, true)]
151    #[case(17, 1, false)]
152    #[case(0, 2, false)]
153    #[case(1, 2, false)]
154    #[case(2, 2, false)]
155    #[case(3, 2, false)]
156    #[case(4, 2, false)]
157    #[case(5, 2, false)]
158    #[case(6, 2, false)]
159    #[case(7, 2, false)]
160    #[case(8, 2, false)]
161    #[case(9, 2, false)]
162    #[case(10, 2, false)]
163    #[case(11, 2, false)]
164    #[case(12, 2, false)]
165    #[case(13, 2, false)]
166    #[case(14, 2, false)]
167    #[case(15, 2, false)]
168    #[case(16, 2, false)]
169    #[case(17, 2, false)]
170    #[case(0, 3, false)]
171    #[case(1, 3, false)]
172    #[case(2, 3, false)]
173    #[case(3, 3, false)]
174    #[case(4, 3, false)]
175    #[case(5, 3, false)]
176    #[case(6, 3, false)]
177    #[case(7, 3, false)]
178    #[case(8, 3, false)]
179    #[case(9, 3, false)]
180    #[case(10, 3, false)]
181    #[case(11, 3, false)]
182    #[case(12, 3, false)]
183    #[case(13, 3, false)]
184    #[case(14, 3, false)]
185    #[case(15, 3, false)]
186    #[case(16, 3, false)]
187    #[case(17, 3, false)]
188    #[case(0, 4, false)]
189    #[case(1, 4, false)]
190    #[case(2, 4, false)]
191    #[case(3, 4, false)]
192    #[case(4, 4, false)]
193    #[case(5, 4, false)]
194    #[case(6, 4, false)]
195    #[case(7, 4, false)]
196    #[case(8, 4, false)]
197    #[case(9, 4, false)]
198    #[case(10, 4, false)]
199    #[case(11, 4, false)]
200    #[case(12, 4, false)]
201    #[case(13, 4, false)]
202    #[case(14, 4, false)]
203    #[case(15, 4, false)]
204    #[case(16, 4, false)]
205    #[case(17, 4, false)]
206    #[case(0, 5, false)]
207    #[case(1, 5, false)]
208    #[case(2, 5, false)]
209    #[case(3, 5, false)]
210    #[case(4, 5, false)]
211    #[case(5, 5, false)]
212    #[case(6, 5, false)]
213    #[case(7, 5, false)]
214    #[case(8, 5, false)]
215    #[case(9, 5, false)]
216    #[case(10, 5, false)]
217    #[case(11, 5, false)]
218    #[case(12, 5, false)]
219    #[case(13, 5, false)]
220    #[case(14, 5, false)]
221    #[case(15, 5, false)]
222    #[case(16, 5, false)]
223    #[case(17, 5, false)]
224    #[case(0, 6, false)]
225    #[case(1, 6, false)]
226    #[case(2, 6, false)]
227    #[case(3, 6, false)]
228    #[case(4, 6, false)]
229    #[case(5, 6, false)]
230    #[case(6, 6, false)]
231    #[case(7, 6, false)]
232    #[case(8, 6, false)]
233    #[case(9, 6, false)]
234    #[case(10, 6, false)]
235    #[case(11, 6, false)]
236    #[case(12, 6, false)]
237    #[case(13, 6, false)]
238    #[case(14, 6, false)]
239    #[case(15, 6, false)]
240    #[case(16, 6, false)]
241    #[case(17, 6, false)]
242    #[case(0, 7, false)]
243    #[case(1, 7, false)]
244    #[case(2, 7, false)]
245    #[case(3, 7, false)]
246    #[case(4, 7, false)]
247    #[case(5, 7, false)]
248    #[case(6, 7, false)]
249    #[case(7, 7, false)]
250    #[case(8, 7, false)]
251    #[case(9, 7, false)]
252    #[case(10, 7, false)]
253    #[case(11, 7, false)]
254    #[case(12, 7, false)]
255    #[case(13, 7, false)]
256    #[case(14, 7, false)]
257    #[case(15, 7, false)]
258    #[case(16, 7, false)]
259    #[case(17, 7, false)]
260    #[case(0, 8, false)]
261    #[case(1, 8, false)]
262    #[case(2, 8, false)]
263    #[case(3, 8, false)]
264    #[case(4, 8, false)]
265    #[case(5, 8, false)]
266    #[case(6, 8, false)]
267    #[case(7, 8, false)]
268    #[case(8, 8, false)]
269    #[case(9, 8, false)]
270    #[case(10, 8, false)]
271    #[case(11, 8, false)]
272    #[case(12, 8, false)]
273    #[case(13, 8, false)]
274    #[case(14, 8, false)]
275    #[case(15, 8, false)]
276    #[case(16, 8, false)]
277    #[case(17, 8, false)]
278    #[case(0, 9, false)]
279    #[case(1, 9, false)]
280    #[case(2, 9, false)]
281    #[case(3, 9, false)]
282    #[case(4, 9, false)]
283    #[case(5, 9, false)]
284    #[case(6, 9, false)]
285    #[case(7, 9, false)]
286    #[case(8, 9, false)]
287    #[case(9, 9, false)]
288    #[case(10, 9, false)]
289    #[case(11, 9, false)]
290    #[case(12, 9, false)]
291    #[case(13, 9, false)]
292    #[case(14, 9, false)]
293    #[case(15, 9, false)]
294    #[case(16, 9, false)]
295    #[case(17, 9, false)]
296    #[case(0, 10, false)]
297    #[case(1, 10, false)]
298    #[case(2, 10, false)]
299    #[case(3, 10, false)]
300    #[case(4, 10, false)]
301    #[case(5, 10, false)]
302    #[case(6, 10, false)]
303    #[case(7, 10, false)]
304    #[case(8, 10, false)]
305    #[case(9, 10, false)]
306    #[case(10, 10, false)]
307    #[case(11, 10, false)]
308    #[case(12, 10, false)]
309    #[case(13, 10, false)]
310    #[case(14, 10, false)]
311    #[case(15, 10, false)]
312    #[case(16, 10, false)]
313    #[case(17, 10, false)]
314    #[case(0, 11, false)]
315    #[case(1, 11, false)]
316    #[case(2, 11, false)]
317    #[case(3, 11, false)]
318    #[case(4, 11, false)]
319    #[case(5, 11, false)]
320    #[case(6, 11, false)]
321    #[case(7, 11, false)]
322    #[case(8, 11, false)]
323    #[case(9, 11, false)]
324    #[case(10, 11, false)]
325    #[case(11, 11, false)]
326    #[case(12, 11, false)]
327    #[case(13, 11, false)]
328    #[case(14, 11, false)]
329    #[case(15, 11, false)]
330    #[case(16, 11, false)]
331    #[case(17, 11, false)]
332    #[case(0, 12, false)]
333    #[case(1, 12, false)]
334    #[case(2, 12, false)]
335    #[case(3, 12, false)]
336    #[case(4, 12, false)]
337    #[case(5, 12, false)]
338    #[case(6, 12, false)]
339    #[case(7, 12, false)]
340    #[case(8, 12, false)]
341    #[case(9, 12, false)]
342    #[case(10, 12, false)]
343    #[case(11, 12, false)]
344    #[case(12, 12, false)]
345    #[case(13, 12, false)]
346    #[case(14, 12, false)]
347    #[case(15, 12, false)]
348    #[case(16, 12, false)]
349    #[case(17, 12, false)]
350    #[case(0, 13, false)]
351    #[case(1, 13, false)]
352    #[case(2, 13, false)]
353    #[case(3, 13, false)]
354    #[case(4, 13, false)]
355    #[case(5, 13, false)]
356    #[case(6, 13, false)]
357    #[case(7, 13, false)]
358    #[case(8, 13, false)]
359    #[case(9, 13, false)]
360    #[case(10, 13, false)]
361    #[case(11, 13, false)]
362    #[case(12, 13, false)]
363    #[case(13, 13, false)]
364    #[case(14, 13, false)]
365    #[case(15, 13, false)]
366    #[case(16, 13, false)]
367    #[case(17, 13, false)]
368    fn test_is_missing_transducer(#[case] x: usize, #[case] y: usize, #[case] expected: bool) {
369        assert_eq!(expected, AUTD3::is_missing_transducer(x, y));
370    }
371
372    #[test]
373    fn test_is_missing_transducer_out_of_range() {
374        itertools::iproduct!(18..=256, 0..=256).for_each(|(x, y)| {
375            assert!(AUTD3::is_missing_transducer(x, y));
376        });
377        itertools::iproduct!(0..=256, 14..=256).for_each(|(x, y)| {
378            assert!(AUTD3::is_missing_transducer(x, y));
379        });
380    }
381
382    #[rstest::rstest]
383    #[test]
384    #[case(0, (0, 0))]
385    #[case(1, (1, 0))]
386    #[case(2, (2, 0))]
387    #[case(3, (3, 0))]
388    #[case(4, (4, 0))]
389    #[case(5, (5, 0))]
390    #[case(6, (6, 0))]
391    #[case(7, (7, 0))]
392    #[case(8, (8, 0))]
393    #[case(9, (9, 0))]
394    #[case(10, (10, 0))]
395    #[case(11, (11, 0))]
396    #[case(12, (12, 0))]
397    #[case(13, (13, 0))]
398    #[case(14, (14, 0))]
399    #[case(15, (15, 0))]
400    #[case(16, (16, 0))]
401    #[case(17, (17, 0))]
402    #[case(18, (0, 1))]
403    #[case(19, (3, 1))]
404    #[case(20, (4, 1))]
405    #[case(21, (5, 1))]
406    #[case(22, (6, 1))]
407    #[case(23, (7, 1))]
408    #[case(24, (8, 1))]
409    #[case(25, (9, 1))]
410    #[case(26, (10, 1))]
411    #[case(27, (11, 1))]
412    #[case(28, (12, 1))]
413    #[case(29, (13, 1))]
414    #[case(30, (14, 1))]
415    #[case(31, (15, 1))]
416    #[case(32, (17, 1))]
417    #[case(33, (0, 2))]
418    #[case(34, (1, 2))]
419    #[case(35, (2, 2))]
420    #[case(36, (3, 2))]
421    #[case(37, (4, 2))]
422    #[case(38, (5, 2))]
423    #[case(39, (6, 2))]
424    #[case(40, (7, 2))]
425    #[case(41, (8, 2))]
426    #[case(42, (9, 2))]
427    #[case(43, (10, 2))]
428    #[case(44, (11, 2))]
429    #[case(45, (12, 2))]
430    #[case(46, (13, 2))]
431    #[case(47, (14, 2))]
432    #[case(48, (15, 2))]
433    #[case(49, (16, 2))]
434    #[case(50, (17, 2))]
435    #[case(51, (0, 3))]
436    #[case(52, (1, 3))]
437    #[case(53, (2, 3))]
438    #[case(54, (3, 3))]
439    #[case(55, (4, 3))]
440    #[case(56, (5, 3))]
441    #[case(57, (6, 3))]
442    #[case(58, (7, 3))]
443    #[case(59, (8, 3))]
444    #[case(60, (9, 3))]
445    #[case(61, (10, 3))]
446    #[case(62, (11, 3))]
447    #[case(63, (12, 3))]
448    #[case(64, (13, 3))]
449    #[case(65, (14, 3))]
450    #[case(66, (15, 3))]
451    #[case(67, (16, 3))]
452    #[case(68, (17, 3))]
453    #[case(69, (0, 4))]
454    #[case(70, (1, 4))]
455    #[case(71, (2, 4))]
456    #[case(72, (3, 4))]
457    #[case(73, (4, 4))]
458    #[case(74, (5, 4))]
459    #[case(75, (6, 4))]
460    #[case(76, (7, 4))]
461    #[case(77, (8, 4))]
462    #[case(78, (9, 4))]
463    #[case(79, (10, 4))]
464    #[case(80, (11, 4))]
465    #[case(81, (12, 4))]
466    #[case(82, (13, 4))]
467    #[case(83, (14, 4))]
468    #[case(84, (15, 4))]
469    #[case(85, (16, 4))]
470    #[case(86, (17, 4))]
471    #[case(87, (0, 5))]
472    #[case(88, (1, 5))]
473    #[case(89, (2, 5))]
474    #[case(90, (3, 5))]
475    #[case(91, (4, 5))]
476    #[case(92, (5, 5))]
477    #[case(93, (6, 5))]
478    #[case(94, (7, 5))]
479    #[case(95, (8, 5))]
480    #[case(96, (9, 5))]
481    #[case(97, (10, 5))]
482    #[case(98, (11, 5))]
483    #[case(99, (12, 5))]
484    #[case(100, (13, 5))]
485    #[case(101, (14, 5))]
486    #[case(102, (15, 5))]
487    #[case(103, (16, 5))]
488    #[case(104, (17, 5))]
489    #[case(105, (0, 6))]
490    #[case(106, (1, 6))]
491    #[case(107, (2, 6))]
492    #[case(108, (3, 6))]
493    #[case(109, (4, 6))]
494    #[case(110, (5, 6))]
495    #[case(111, (6, 6))]
496    #[case(112, (7, 6))]
497    #[case(113, (8, 6))]
498    #[case(114, (9, 6))]
499    #[case(115, (10, 6))]
500    #[case(116, (11, 6))]
501    #[case(117, (12, 6))]
502    #[case(118, (13, 6))]
503    #[case(119, (14, 6))]
504    #[case(120, (15, 6))]
505    #[case(121, (16, 6))]
506    #[case(122, (17, 6))]
507    #[case(123, (0, 7))]
508    #[case(124, (1, 7))]
509    #[case(125, (2, 7))]
510    #[case(126, (3, 7))]
511    #[case(127, (4, 7))]
512    #[case(128, (5, 7))]
513    #[case(129, (6, 7))]
514    #[case(130, (7, 7))]
515    #[case(131, (8, 7))]
516    #[case(132, (9, 7))]
517    #[case(133, (10, 7))]
518    #[case(134, (11, 7))]
519    #[case(135, (12, 7))]
520    #[case(136, (13, 7))]
521    #[case(137, (14, 7))]
522    #[case(138, (15, 7))]
523    #[case(139, (16, 7))]
524    #[case(140, (17, 7))]
525    #[case(141, (0, 8))]
526    #[case(142, (1, 8))]
527    #[case(143, (2, 8))]
528    #[case(144, (3, 8))]
529    #[case(145, (4, 8))]
530    #[case(146, (5, 8))]
531    #[case(147, (6, 8))]
532    #[case(148, (7, 8))]
533    #[case(149, (8, 8))]
534    #[case(150, (9, 8))]
535    #[case(151, (10, 8))]
536    #[case(152, (11, 8))]
537    #[case(153, (12, 8))]
538    #[case(154, (13, 8))]
539    #[case(155, (14, 8))]
540    #[case(156, (15, 8))]
541    #[case(157, (16, 8))]
542    #[case(158, (17, 8))]
543    #[case(159, (0, 9))]
544    #[case(160, (1, 9))]
545    #[case(161, (2, 9))]
546    #[case(162, (3, 9))]
547    #[case(163, (4, 9))]
548    #[case(164, (5, 9))]
549    #[case(165, (6, 9))]
550    #[case(166, (7, 9))]
551    #[case(167, (8, 9))]
552    #[case(168, (9, 9))]
553    #[case(169, (10, 9))]
554    #[case(170, (11, 9))]
555    #[case(171, (12, 9))]
556    #[case(172, (13, 9))]
557    #[case(173, (14, 9))]
558    #[case(174, (15, 9))]
559    #[case(175, (16, 9))]
560    #[case(176, (17, 9))]
561    #[case(177, (0, 10))]
562    #[case(178, (1, 10))]
563    #[case(179, (2, 10))]
564    #[case(180, (3, 10))]
565    #[case(181, (4, 10))]
566    #[case(182, (5, 10))]
567    #[case(183, (6, 10))]
568    #[case(184, (7, 10))]
569    #[case(185, (8, 10))]
570    #[case(186, (9, 10))]
571    #[case(187, (10, 10))]
572    #[case(188, (11, 10))]
573    #[case(189, (12, 10))]
574    #[case(190, (13, 10))]
575    #[case(191, (14, 10))]
576    #[case(192, (15, 10))]
577    #[case(193, (16, 10))]
578    #[case(194, (17, 10))]
579    #[case(195, (0, 11))]
580    #[case(196, (1, 11))]
581    #[case(197, (2, 11))]
582    #[case(198, (3, 11))]
583    #[case(199, (4, 11))]
584    #[case(200, (5, 11))]
585    #[case(201, (6, 11))]
586    #[case(202, (7, 11))]
587    #[case(203, (8, 11))]
588    #[case(204, (9, 11))]
589    #[case(205, (10, 11))]
590    #[case(206, (11, 11))]
591    #[case(207, (12, 11))]
592    #[case(208, (13, 11))]
593    #[case(209, (14, 11))]
594    #[case(210, (15, 11))]
595    #[case(211, (16, 11))]
596    #[case(212, (17, 11))]
597    #[case(213, (0, 12))]
598    #[case(214, (1, 12))]
599    #[case(215, (2, 12))]
600    #[case(216, (3, 12))]
601    #[case(217, (4, 12))]
602    #[case(218, (5, 12))]
603    #[case(219, (6, 12))]
604    #[case(220, (7, 12))]
605    #[case(221, (8, 12))]
606    #[case(222, (9, 12))]
607    #[case(223, (10, 12))]
608    #[case(224, (11, 12))]
609    #[case(225, (12, 12))]
610    #[case(226, (13, 12))]
611    #[case(227, (14, 12))]
612    #[case(228, (15, 12))]
613    #[case(229, (16, 12))]
614    #[case(230, (17, 12))]
615    #[case(231, (0, 13))]
616    #[case(232, (1, 13))]
617    #[case(233, (2, 13))]
618    #[case(234, (3, 13))]
619    #[case(235, (4, 13))]
620    #[case(236, (5, 13))]
621    #[case(237, (6, 13))]
622    #[case(238, (7, 13))]
623    #[case(239, (8, 13))]
624    #[case(240, (9, 13))]
625    #[case(241, (10, 13))]
626    #[case(242, (11, 13))]
627    #[case(243, (12, 13))]
628    #[case(244, (13, 13))]
629    #[case(245, (14, 13))]
630    #[case(246, (15, 13))]
631    #[case(247, (16, 13))]
632    #[case(248, (17, 13))]
633    fn test_grid_id(#[case] idx: usize, #[case] expected: (usize, usize)) {
634        assert_eq!(expected, AUTD3::grid_id(idx));
635    }
636}