# moteus
Rust client library for moteus brushless motor controllers.
This crate provides a high-level API for communicating with moteus
controllers over CAN-FD. It supports multiple transport backends and
automatic device discovery.
## Crate Structure
This library is split into two crates:
- **moteus-protocol**: Low-level protocol encoding/decoding. `no_std`
compatible for embedded use.
- **moteus**: High-level API with transport implementations for FdCanUSB
and SocketCAN.
## Quick Start - Auto-Discovery (Recommended)
The simplest way to use moteus is with automatic transport discovery:
```rust,no_run
use moteus::{BlockingController, command::PositionCommand};
fn main() -> Result<(), moteus::Error> {
// Auto-discovers transport
let mut ctrl = BlockingController::new(1)?;
// Clear any faults
ctrl.set_stop()?;
// Command position mode
loop {
let result = ctrl.set_position(PositionCommand::new().position(f32::NAN))?;
println!("Position: {}", result.position);
std::thread::sleep(std::time::Duration::from_millis(20));
}
}
```
## Builder Pattern API
Commands are built using the builder pattern for clear, self-documenting code:
```rust
use moteus::command::PositionCommand;
// Simple position command
let cmd = PositionCommand::new().position(0.5);
// Position with velocity
let cmd = PositionCommand::new()
.position(0.5)
.velocity(1.0);
// Full control over all parameters
let cmd = PositionCommand::new()
.position(0.5)
.velocity(1.0)
.feedforward_torque(0.1)
.kp_scale(0.8)
.kd_scale(1.0)
.maximum_torque(2.0);
```
## Explicit Transport
For more control, you can specify a transport explicitly:
```rust,no_run
use moteus::{BlockingController, Fdcanusb};
fn main() -> Result<(), moteus::Error> {
// A single-bus convenience transport, ready to hand to a controller.
let transport = Fdcanusb::open("/dev/fdcanusb")?;
let mut ctrl = BlockingController::with_transport(1, transport);
ctrl.set_stop()?;
Ok(())
}
```
You can also build a [`Router`] over one or more explicit devices:
```rust,no_run
use moteus::{BlockingController, Router};
use moteus::transport::socketcan::SocketCanDevice;
fn main() -> Result<(), moteus::Error> {
let transport = Router::from_device(SocketCanDevice::new("can0")?);
let mut ctrl = BlockingController::with_transport(1, transport);
ctrl.set_stop()?;
Ok(())
}
```
## Transport Options
Configure transport auto-detection with options:
```rust,no_run
use moteus::{BlockingController, TransportOptions};
use std::time::Duration;
fn main() -> Result<(), moteus::Error> {
let opts = TransportOptions::new()
.socketcan_interfaces(vec!["can0"])
.timeout(Duration::from_millis(200));
let mut ctrl = BlockingController::with_options(1, &opts)?;
Ok(())
}
```
## Low-Level Protocol Access
For embedded or custom transport use cases, the `moteus-protocol` crate
can be used directly to construct and parse CAN-FD frames:
```rust
use moteus_protocol::{CanFdFrame, command::{PositionCommand, PositionFormat}};
// Create a position command frame using builder pattern
let mut frame = CanFdFrame::new();
frame.arbitration_id = 0x8001; // dest=1, source=0
let cmd = PositionCommand::new()
.position(0.5)
.velocity(1.0);
cmd.serialize(&mut frame, &PositionFormat::default());
// frame.data and frame.size now contain the encoded command
```
## Controller Configuration
Use the builder pattern to configure controller settings:
```rust,no_run
use moteus::{Controller, BlockingController, Resolution};
use moteus::query::QueryFormat;
fn main() -> Result<(), moteus::Error> {
// Configure a controller with custom settings
let ctrl = Controller::new(1)
.source_id(0x10)
.query_format(QueryFormat::comprehensive());
// Use with auto-discovered transport
let ctrl = BlockingController::with_controller(ctrl)?;
Ok(())
}
```
## Query Format Overrides
You can override the query format on a per-call basis:
```rust
use moteus::command_ext::CommandExt;
use moteus::command::PositionCommand;
use moteus::query::QueryFormat;
// Override query format for this specific call
let cmd = PositionCommand::new()
.position(0.5)
.with_query(QueryFormat::comprehensive());
```
## Resolution Configuration
Control the resolution of commands and queries to optimize bandwidth:
```rust
use moteus::{Controller, Resolution};
use moteus_protocol::query::QueryFormat;
let mut ctrl = Controller::new(1);
// Customize query resolution
ctrl.query_format.position = Resolution::Float;
ctrl.query_format.velocity = Resolution::Float;
ctrl.query_format.torque = Resolution::Int16;
```
## Features
- `tokio`: Async I/O transports and `AsyncController` (optional)
- `clap`: CLI argument parsing support (optional)
## Supported Transports
- **fdcanusb**: USB-to-CAN adapter (serial CDC)
- **SocketCAN**: Linux kernel CAN interface
## Building with Bazel
```bash
tools/bazel build //lib/rust/moteus
tools/bazel test //lib/rust:host
```
## Versions prior to 0.5.0
Versions of this crate prior to 0.5.0 were developed independently by
Omelia Iliffe. The source for those versions can be found at:
[https://github.com/omelia-iliffe/moteus-rs](https://github.com/omelia-iliffe/moteus-rs)