Skip to content
This is the development version of the documentation. It may change before the next release. See 0.6.x for the latest release.

Remote

RemoteLink is a Link implementation that connects over TCP to a separate host connected to the AUTD3 devices for sending and receiving. Use it when the machine that operates AUTD3 differs from the machine wired to the real hardware.

It consists of two processes: a server and a client.

  • RemoteServer: runs on the host wired to the real hardware. It drives a real-hardware link and relays frames over TCP.
  • RemoteLink: runs on the operating host.

On the server-side host, also add the package of the Link that drives the real hardware (such as EtherCrab).

Connection to the Simulator is also done with RemoteLink.

Pass the listening settings and a closure that opens the real-hardware link to RemoteServer::new, then call serve to start relaying.

let option = RemoteServerOption::new(bind);
RemoteServer::new(option, |_: &[DeviceLayout]| {
EchocatLink::open(&EchocatLinkOption::default())
.map_err(|e| RemoteLinkError::Link(e.to_string()))
})?
.serve()?;
Parameter Type Description
option RemoteServerOption listening address and bus thread settings
factory FnMut(&[DeviceLayout]) -> Result<impl Link> closure that opens the real-hardware link

Fields of RemoteServerOption:

Field Type Description
bind SocketAddr TCP address on which the server listens
bus BusOption bus thread settings

Fields of BusOption:

Field Type Description
pacing BusPacing bus cycle period. LinkPaced leaves the pacing to the link itself (use it for EtherCAT links)
rt_priority Option<ThreadPriority> priority of the bus thread. By default a real-time priority is attempted, with a warning on failure
rt_policy RtSchedulePolicy scheduling policy of the bus thread
rt_affinity Option<CoreId> CPU core to pin the bus thread to
stack_prefault_bytes usize bytes of the bus thread stack to page in at start-up. 0 by default; leaving it at 0 costs a page-fault delay on the first frames

serve waits for client connections and, for each one, opens the real-hardware link with factory and starts relaying tx/rx frames.

The device count of the client’s Geometry has to match the device count of the bus on the server.

Setting rt_priority requires privileges (CAP_SYS_NICE on Linux). Without them the server warns and runs with plain scheduling, which makes the bus unstable under load.

RemoteLinkOption::new(addr);
Field Type Description
addr SocketAddr address of the server to connect to
timeout Option<Duration> how long to wait on the connect and on every frame. None leaves the OS defaults, so an address that answers nothing takes minutes to fail

The server can be found over mDNS. In Rust this needs the discovery feature; Python and C# have it built in.

autd3-rs-link-remote = { version = "0.4", features = ["discovery"] }
let option = RemoteLinkOption::discover()?;

Finding no server, and finding more than one, are both errors. The error for the latter lists what was found, so one of them can be picked by name.

let option = RemoteLinkOption::discover_with(&DiscoveryOption {
instance: Some("autd3-0a1b2c3d".to_string()),
..Default::default()
})?;

Fields of DiscoveryOption:

Field Type Description
timeout Duration how long to wait for answers. 2 seconds by default; a shorter wait misses servers
instance Option<String> name of the server to look for. None means every server

Use discover_all when only the list is wanted.

for appliance in autd3_rs_link_remote::discover_all(&DiscoveryOption::default())? {
println!("{} at {}", appliance.instance, appliance.addr);
}

Over a direct cable, discovery returns the IPv6 link-local address. Nothing has to be configured on the host as long as the interface is up. A connection profile that keeps a link-local address is needed only to reach the appliance over IPv4.