Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

FociSTM

  • 使用可能な最大焦点数は
    • 拡張モードの場合は
  • サンプリングレートはで, は0より大きい16-bit符号なし整数である

FociSTMの使用方法は以下のようになる. これは, アレイの中心から直上の点を中心とした半径の円周上で焦点を回すサンプルである. 円周上を200点サンプリングし, 一周をで回るようにしている. (すなわち, サンプリング周波数はである.)

use autd3::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let autd = Controller::open([AUTD3::default()], Nop::new())?;
let center = autd.center() + Vector3::new(0., 0., 150.0 * mm);
let point_num = 200;
let radius = 30.0 * mm;
let _ = 
FociSTM {
    foci: (0..point_num)
        .map(|i| {
            let theta = 2.0 * PI * i as f32 / point_num as f32;
            let p = radius * Vector3::new(theta.cos(), theta.sin(), 0.0);
            center + p
        })
        .collect::<Vec<_>>(),
    config: 1.0 * Hz,
};
Ok(())
}
#include <ranges>
#include<autd3.hpp>
#include<autd3/link/nop.hpp>
using namespace std::ranges::views;
int main() {
using namespace autd3;
auto autd = Controller::open({AUTD3{
                                 .pos = Point3::origin(),
                                 .rot = Quaternion::Identity(),
                             }},
                             link::Nop{});
const Point3 center = autd.center() + Vector3(0, 0, 150);
constexpr auto points_num = 200;
constexpr auto radius = 30.0f;
FociSTM(iota(0) | take(points_num) | transform([&](auto i) {
          const auto theta = 2.0f * pi * static_cast<float>(i) /
                             static_cast<float>(points_num);
          Point3 p =
              center + radius * Vector3(std::cos(theta), std::sin(theta), 0);
          return p;
        }) | std::ranges::to<std::vector<Point3>>(),
        1.0f * Hz);
return 0; }
using AUTD3Sharp;
using AUTD3Sharp.Utils;
using AUTD3Sharp.Link;
using static AUTD3Sharp.Units;
using var autd = Controller.Open([new AUTD3(pos: Point3.Origin, rot: Quaternion.Identity)], new Nop());
var center = autd.Center() + new Vector3(0, 0, 150);
const int pointNum = 200;
const float radius = 30.0f;
new FociSTM(
    foci: Enumerable.Range(0, pointNum).Select(i =>
    {
        var theta = 2.0f * MathF.PI * i / pointNum;
        return center + radius * new Vector3(MathF.Cos(theta), MathF.Sin(theta), 0);
    }),
    config: 1.0f * Hz
);
import numpy as np
from pyautd3 import AUTD3, Controller, FociSTM, Hz
from pyautd3.link.nop import Nop
autd = Controller.open([AUTD3(pos=[0.0, 0.0, 0.0], rot=[1, 0, 0, 0])], Nop())
center = autd.center() + np.array([0.0, 0.0, 150.0])
point_num = 200
radius = 30.0
FociSTM(
    foci=(
        center + radius * np.array([np.cos(theta), np.sin(theta), 0])
        for theta in (2.0 * np.pi * i / point_num for i in range(point_num))
    ),
    config=1.0 * Hz,
)

configには周波数のほか, 周期やサンプリング設定を指定することができる.

サンプリング点数とサンプリング周期に関する制約によって, 指定した周波数で出力できない可能性がある. 例えば, 上記の例は200点をで回すため, サンプリング周波数はとすれば良い. しかし, 例えばpoint_num=199にすると, サンプリング周波数をにしなければならないが, を満たすような整数は存在せずエラーになる.

FociSTM::into_nearestを使用すると, 最も近いが選択されるようになるが, 指定した周波数と実際の周波数がずれる可能性があるため注意が必要である.

多焦点

FociSTMでは最大8焦点を同時に出すことができる.

以下は2焦点の例である.

use autd3::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let autd = Controller::open([AUTD3::default()], Nop::new())?;
let center = autd.center() + Vector3::new(0., 0., 150.0 * mm);
let point_num = 200;
let radius = 30.0 * mm;
let _ = 
FociSTM {
    foci: (0..point_num)
        .map(|i| {
            let theta = 2.0 * PI * i as f32 / point_num as f32;
            let p = radius * Vector3::new(theta.cos(), theta.sin(), 0.0);
            ControlPoints {
                points: [
                    ControlPoint {
                        point: center + p,
                        phase_offset: Phase::ZERO,
                    },
                    ControlPoint {
                        point: center - p,
                        phase_offset: Phase::ZERO,
                    },
                ],
                intensity: Intensity::MAX,
            }
        })
        .collect::<Vec<_>>(),
    config: 1.0 * Hz,
};
Ok(())
}
#include <ranges>
#include<autd3.hpp>
#include<autd3/link/nop.hpp>
using namespace std::ranges::views;
int main() {
using namespace autd3;
auto autd = Controller::open({AUTD3{
                                 .pos = Point3::origin(),
                                 .rot = Quaternion::Identity(),
                             }},
                             link::Nop{});
const Point3 center = autd.center() + Vector3(0, 0, 150);
constexpr auto points_num = 200;
constexpr auto radius = 30.0f;
FociSTM stm(iota(0) | take(points_num) | transform([&](auto i) {
              const auto theta = 2.0f * pi * static_cast<float>(i) /
                                 static_cast<float>(points_num);
              Vector3 p = radius * Vector3(std::cos(theta), std::sin(theta), 0);
              return ControlPoints<2>{
                  .points = {ControlPoint{.point = center + p,
                                          .phase_offset = Phase::ZERO},
                             ControlPoint{.point = center - p,
                                          .phase_offset = Phase::ZERO}},
                  .intensity = std::numeric_limits<Intensity>::max()};
            }) | std::ranges::to<std::vector<ControlPoints<2>>>(),
            1.0f * Hz);
return 0; }
using AUTD3Sharp;
using AUTD3Sharp.Utils;
using AUTD3Sharp.Link;
using static AUTD3Sharp.Units;
using var autd = Controller.Open([new AUTD3(pos: Point3.Origin, rot: Quaternion.Identity)], new Nop());
var center = autd.Center() + new Vector3(0, 0, 150);
const int pointNum = 200;
const float radius = 30.0f;
new FociSTM(
    foci: Enumerable.Range(0, pointNum).Select(i =>
        {
            var theta = 2.0f * MathF.PI * i / pointNum;
            var p = radius * new Vector3(MathF.Cos(theta), MathF.Sin(theta), 0);
            return new ControlPoints(
                points: [
                    new ControlPoint { Point = center + p, PhaseOffset = Phase.Zero},
                    new ControlPoint { Point = center - p, PhaseOffset = Phase.Zero}
                ],
                intensity: Intensity.Max
            );
        }),
    config: 1.0f * Hz
);
import numpy as np
from pyautd3 import AUTD3, Controller, ControlPoint, ControlPoints, Intensity, FociSTM, Hz, Phase
from pyautd3.link.nop import Nop
autd = Controller.open([AUTD3(pos=[0.0, 0.0, 0.0], rot=[1, 0, 0, 0])], Nop())
center = autd.center() + np.array([0.0, 0.0, 150.0])
point_num = 200
radius = 30.0
FociSTM(
    foci=(
        ControlPoints(
            points=[
                ControlPoint(
                    point=center + radius * np.array([np.cos(theta), np.sin(theta), 0]),
                    phase_offset=Phase.ZERO,
                ),
                ControlPoint(
                    point=center - radius * np.array([np.cos(theta), np.sin(theta), 0]),
                    phase_offset=Phase.ZERO,
                ),
            ],
            intensity=Intensity.MAX,
        )
        for theta in (2.0 * np.pi * i / point_num for i in range(point_num))
    ),
    config=1.0 * Hz,
)

FociSTMの多焦点音場は単純な単焦点音場の重ね合わせである. すなわち, 振動子の位置, 各焦点位置, 超音波周波数, 音速に対して, 以下の計算により位相を求めている. ここで, は各焦点の位相オフセットである. 振幅に関しては, ではなく, ソフトウェアからの指定値を使用する.

制約

データ量を削減するため, FociSTMでは, 焦点位置座標をを単位とする符号あり固定小数点数にエンコードして使用する. そのため, 各軸方向に対して, すべての振動子からの範囲にある焦点しか出力できない.

また, 内部計算も固定小数点数で行っているため, gain::Focusなどとは異なる位相になる可能性がある. 詳しくは, ファームウェアのドキュメントを参照.