Controller
ここでは, Controller
に存在するAPIを紹介する.
fpga_state
FPGAの状態を取得する.
これを使用する前に, ReadsFPGAState
で状態取得を有効化しておく必要がある.
use autd3::prelude::*;
#[allow(unused_variables)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut autd = Controller::open([AUTD3::default()], autd3::link::Nop::new())?;
autd.send(ReadsFPGAState::new(|_dev| true))?;
let info = autd.fpga_state()?;
Ok(())
}
#include<autd3.hpp>
#include<autd3/link/nop.hpp>
int main() {
using namespace autd3;
auto autd =
Controller::open({AUTD3{}}, link::Nop{});
autd.send(ReadsFPGAState([](const auto&) { return true; }));
const auto info = autd.fpga_state();
return 0; }
using AUTD3Sharp;
using AUTD3Sharp.Link;
using AUTD3Sharp.Utils;
using var autd = Controller.Open([new AUTD3()], new Nop());
autd.Send(new ReadsFPGAState(_ => true));
var info = autd.FPGAState();
from pyautd3 import Controller, AUTD3, ReadsFPGAState
from pyautd3.link.nop import Nop
autd = Controller.open([AUTD3()], Nop())
autd.send(ReadsFPGAState(lambda _: True))
info = autd.fpga_state()
ReadsFPGAState
コンストラクタの引数はFn(&Device) -> bool
で, デバイス毎に状態取得を有効化するかどうかを指定する.
有効化していないデバイスに対してfpga_state
はNone
を返す.
FPGAの状態としては, 現在以下の情報が取得できる.
is_thermal_assert
: ファン制御用の温度センサがアサートされているかどうかcurrent_mod_segment
: 現在のModulation Segmentcurrent_stm_segment
: 現在のFociSTM/GainSTM Segmentcurrent_gain_segment
: 現在のGain Segmentis_gain_mode
: 現在Gainが使用されているかどうかis_stm_mode
: 現在FociSTM/GainSTMが使用されているかどうか
send
デバイスにデータを送信する.
データは単体か2つのみ同時に送信することができる.
group_send
group_send
関数を使用すると, デバイスをグルーピングすることができる.
use autd3::prelude::*;
use autd3::gain::IntoBoxedGain;
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut autd = Controller::open(
[AUTD3::default(), AUTD3::default()],
autd3::link::Nop::new(),
)?;
let x = 0.;
let y = 0.;
let z = 0.;
autd.group_send(
|dev| match dev.idx() {
0 => Some("focus"),
1 => Some("null"),
_ => None,
},
HashMap::from([
(
"focus",
Focus {
pos: Point3::new(x, y, z),
option: Default::default(),
}
.into_boxed(),
),
("null", Null {}.into_boxed()),
]),
)?;
Ok(())
}
#include<chrono>
#include<autd3.hpp>
#include<autd3/link/nop.hpp>
int main() {
using namespace autd3;
auto autd =
Controller::open({AUTD3{}}, link::Nop{});
const auto x = 0.0;
const auto y = 0.0;
const auto z = 0.0;
autd.group_send(
[](const Device& dev) -> std::optional<const char*> {
if (dev.idx() == 0) {
return "null";
} else if (dev.idx() == 1) {
return "focus";
} else {
return std::nullopt;
}
},
std::unordered_map<const char*, std::shared_ptr<driver::Datagram>>{
{"focus",
std::make_shared<Focus>(Focus(Point3(x, y, z), FocusOption{}))},
{"null", std::make_shared<Null>()}});
return 0; }
using AUTD3Sharp;
using AUTD3Sharp.Link;
using AUTD3Sharp.Gain;
using AUTD3Sharp.Modulation;
using AUTD3Sharp.Utils;
using var autd = Controller.Open([new AUTD3()], new Nop());
var x = 0.0f;
var y = 0.0f;
var z = 0.0f;
autd.GroupSend(dev =>
{
return dev.Idx() switch
{
0 => "null",
1 => "focus",
_ => null
};
},
new GroupDictionary {
{ "null", new Null() },
{ "focus", new Focus(pos: new Point3(x, y, z), option: new FocusOption()) }
}
);
from pyautd3 import AUTD3, Controller, Device
from pyautd3.gain import Focus, FocusOption, Null
from pyautd3.link.nop import Nop
autd = Controller.open([AUTD3()], Nop())
x = 0.0
y = 0.0
z = 0.0
def key_map(dev: Device) -> str | None:
if dev.idx == 0:
return "null"
if dev.idx == 1:
return "focus"
return None
autd.group_send(
key_map=key_map,
data_map={"null": Null(), "focus": Focus(pos=[x, y, z], option=FocusOption())},
)
gain::Group
とは異なり, 通常のsend
で送信できるデータなら何でも使用できる.
ただし, デバイス単位でしかグルーピングできない.
NOTE: このサンプルでは, キーとして文字列を使用しているが,
HashMap
のキーとして使用できるものなら何でも良い.
sender
送信時の設定をsender
経由で指定できる.
use std::time::Duration;
use autd3::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut autd = Controller::open([AUTD3::default()], autd3::link::Nop::new())?;
let mut sender = autd.sender(SenderOption {
send_interval: Duration::from_millis(1),
receive_interval: Duration::from_millis(1),
timeout: None,
parallel: ParallelMode::Auto,
sleeper: SpinSleeper::default(),
});
let d = Null {};
sender.send(d)?;
Ok(())
}
#include<chrono>
#include<autd3.hpp>
#include<autd3/link/nop.hpp>
int main() {
using namespace autd3;
auto autd = Controller::open({AUTD3{}}, link::Nop{});
auto sender = autd.sender(SenderOption{
.send_interval = std::chrono::milliseconds(1),
.receive_interval = std::chrono::milliseconds(1),
.timeout = std::nullopt,
.parallel = ParallelMode::Auto,
.sleeper = SpinSleeper(),
});
const Null d;
sender.send(d);
return 0; }
using AUTD3Sharp;
using AUTD3Sharp.Link;
using AUTD3Sharp.Gain;
using AUTD3Sharp.Utils;
using var autd = Controller.Open([new AUTD3()], new Nop());
var sender = autd.Sender(
new SenderOption
{
SendInterval = Duration.FromMillis(1),
ReceiveInterval = Duration.FromMillis(1),
Timeout = null,
Parallel = ParallelMode.Auto,
Sleeper = new SpinSleeper()
}
);
var d = new Null();
sender.Send(d);
from pyautd3 import AUTD3, Controller, Duration, Null, SenderOption, SpinSleeper, ParallelMode
from pyautd3.link.nop import Nop
autd = Controller.open([AUTD3()], Nop())
sender = autd.sender(
SenderOption(
send_interval=Duration.from_millis(1),
receive_interval=Duration.from_millis(1),
timeout=None,
parallel=ParallelMode.Auto,
sleeper=SpinSleeper(),
)
)
d = Null()
sender.send(d)
ここで,
send_interval
: 送信間隔receive_interval
: 受信間隔timeout
: タイムアウト時間. 詳細はタイムアウトについてを参照parallel
: 並列計算モード. 詳細は並列計算についてを参照sleeper
: 送受信間隔を調整する構造体SpinSleeper
:spin_sleep
を使用StdSleeper
:std::thread::sleep
を使用WaitableSleeper
: (Windowsのみ)Waitable Timer
を使用
であり, デフォルト値は上記の通り.
なお, Controller::send
, Controller::group_send
はデフォルトのSenderOption
を使用した場合と等価である.
タイムアウトについて
タイムアウトの値が
- 0より大きい場合, 送信データがデバイスで処理されるか, 指定したタイムアウト時間が経過するまで待機する. 送信データがデバイスで処理されたのが確認できなかった場合にエラーを返す.
- 0の場合,
send
関数は送信データがデバイスで処理されたかどうかのチェックを行わない.
確実にデータを送信したい場合はこれを適当な値に設定しておくことをおすすめする.
SenderOption
で指定しない場合, 以下に示す各データのデフォルト値が使用される.
タイムアウト値 | |
---|---|
Clear /GPIOOutputs /ForceFan /PhaseCorrection /PulseWidthEncoder /ReadsFPGAState /SwapSegment /Silencer /Synchronize /FociSTM /GainSTM /Modulation | |
Gain |
複数をまとめて送信する場合は, それぞれのデータのタイムアウト値の最大値が使用される.
並列計算について
各データの内部での計算は, デバイス単位で並列に実行することができる.
ParallelMode::On
を指定すると並列計算を有効化, ParallelMode::Off
を指定すると無効化する.
ParallelMode::Auto
の場合, 有効なデバイスの数が以下に示す各データの並列計算スレッショルド値を超える場合に並列計算が有効化される.
並列計算スレッショルド値 | |
---|---|
Clear /GPIOOutputs /ForceFan /PhaseCorrection /ReadsFPGAState /SwapSegment /Silencer /Synchronize /FociSTM (焦点数が4000未満)/Modulation | 18446744073709551615 |
PulseWidthEncoder /FociSTM (焦点数が4000以上)// GainSTM /Gain | 4 |