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つのみ同時に送信することができる.
sender
送信時の設定をsender経由で指定できる.
use autd3::prelude::*;
use std::time::Duration;
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: Some(Duration::from_millis(1)),
receive_interval: Some(Duration::from_millis(1)),
timeout: None,
parallel: ParallelMode::Auto,
},
);
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});
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,
}
);
var d = new Null();
sender.Send(d);
from pyautd3 import AUTD3, Controller, Duration, Null, SenderOption
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,
),
)
d = Null()
sender.send(d)
ここで,
send_interval: 送信間隔receive_interval: 受信間隔timeout: タイムアウト時間. 詳細は送信データのチェックについてを参照parallel: 並列計算モード (Rust版のみ). 詳細は並列計算についてを参照
であり, デフォルト値は上記の通り.
なお, Controller::sendはController::default_sender_option (変更可能) とStdSleeperを使用した場合と等価である.
送信データのチェックについて
タイムアウトの値が
- 0より大きい場合, 送信データがデバイスで処理されるか, 指定したタイムアウト時間が経過するまで待機する. 送信データがデバイスで処理されたのが確認できなかった場合にエラーを返す.
- 0の場合,
send関数は送信データがデバイスで処理されたか確認できなくてもエラーを返さない.
確実にデータを送信したい場合はこれを適当な値に設定しておくことをおすすめする.
SenderOptionで指定しない場合, デフォルト値 () が使用される.
複数をまとめて送信する場合は, それぞれのデータのタイムアウト値の最大値が使用される.
並列計算について (Rust版のみ)
各データの内部での計算は, デバイス単位で並列に実行することができる.
ParallelMode::Onを指定すると並列計算を有効化, ParallelMode::Offを指定すると無効化する.
ParallelMode::Autoの場合, デバイスの数が以下に示す各データの並列計算スレッショルド値を超える場合に並列計算が有効化される.
| 並列計算スレッショルド値 | |
|---|---|
Clear/GPIOOutputs/ForceFan/PhaseCorrection/ReadsFPGAState/SwapSegment/Silencer/Synchronize/FociSTM (焦点数が4000未満)/Modulation | 18446744073709551615 |
PulseWidthEncoder/FociSTM (焦点数が4000以上)// GainSTM/Gain | CPUのコア数 |
inspect (Rustのみ)
GainやModulation, GainSTM, FociSTMの計算は並列化やメモリアロケーションを最小にするために遅延されており, 計算結果は送信フレーム内に直接構成される.
そのため, これらの計算結果を送信前に直接確認することはできない.
Controller::inspectを使用することで, 送信することなく, これらの計算結果を確認することができる.
use autd3::prelude::*;
#[allow(unused_variables)]
fn main() -> Result<(), Box<dyn std::error::Error>> {
let autd = Controller::open([AUTD3::default()], autd3::link::Nop::new())?;
let r = autd.inspect(Null {})?;
dbg!(&r[0]); // result of device 0
// &r[0] = Some(
// GainInspectionResult {
// name: "Null",
// data: [
// Drive {
// phase: 0x00,
// intensity: 0x00,
// },
// ︙
// Drive {
// phase: 0x00,
// intensity: 0x00,
// },
// ],
// segment: S0,
// transition_mode: None,
// },
// )
Ok(())
}