Expand description
§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_stdcompatible 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:
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:
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:
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:
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:
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:
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:
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:
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:
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 andAsyncController(optional)clap: CLI argument parsing support (optional)
§Supported Transports
- fdcanusb: USB-to-CAN adapter (serial CDC)
- SocketCAN: Linux kernel CAN interface
§Building with Bazel
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
Re-exports§
pub use controller::Controller;pub use device_address::DeviceAddress;pub use error::Error;pub use transport::factory::TransportOptions;pub use transport::Router;pub use transport::Transport;pub use transport::convenience::Fdcanusb;pub use transport::convenience::SocketCan;
Modules§
- command
- Command types for moteus motor control.
- command_
ext - Extension traits for command types to support query format overrides.
- command_
types - Moteus Command type — a routed protocol message.
- controller
- Controller API for moteus devices.
- device_
address - Device addressing for moteus controllers.
- diagnostic
- Diagnostic stream protocol for moteus controllers.
- error
- Error types for the moteus client library.
- move_to
- Multi-servo coordinated position moves.
- query
- Query types for reading telemetry from moteus controllers.
- transport
- Router layer for communicating with moteus controllers.
Structs§
- Blocking
Controller - A blocking controller for a single moteus device.
- CanFd
Frame - A CAN-FD frame.
Enums§
- Mode
- The operating mode of a moteus controller.
- Register
- Registers exposed for reading or writing from a moteus controller.
- Resolution
- The resolution (data type) used when encoding or decoding a register value.