Skip to content

Commit 2a4a5dc

Browse files
jpieperclaude
andcommitted
Add Rust API documentation to mkdocs
Add integration tutorial (docs/integration/rust.md) covering BlockingController, AsyncController, low-level Controller usage, custom queries, transport configuration, and diagnostics. Add curated API reference (docs/reference/rust.md) with docs.rs links for all key types. Add rust_doc Bazel targets for both crates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 60befcc commit 2a4a5dc

File tree

6 files changed

+430
-8
lines changed

6 files changed

+430
-8
lines changed

docs/integration/python.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,3 @@ c = moteus.Controller(id=1, query_resolution=qr)
110110
## API Reference
111111

112112
- [Python API Reference](../reference/python.md)
113-
114-
## Related Sections
115-
116-
- [Control Modes](../guides/control-modes.md) - Understanding different control strategies
117-
- [Configuration Parameters](../reference/configuration.md) - Available parameters
118-
- [Raspberry Pi Setup](../platforms/raspberry-pi.md) - Platform-specific configuration

docs/integration/rust.md

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# Rust Client Library
2+
3+
moteus provides a Rust client library for commanding and controlling moteus controllers using a supported CAN-FD adapter. The library consists of two crates:
4+
5+
- **`moteus`** — High-level controller API with transport management
6+
- **`moteus-protocol`** — Low-level `no_std` protocol encoding/decoding
7+
8+
## Installation
9+
10+
Add the moteus crate to your project:
11+
12+
```
13+
cargo add moteus
14+
```
15+
16+
Or add it directly to your `Cargo.toml`:
17+
18+
```toml
19+
[dependencies]
20+
moteus = "0.1"
21+
```
22+
23+
For async support with tokio, enable the `tokio` feature:
24+
25+
```toml
26+
[dependencies]
27+
moteus = { version = "0.1", features = ["tokio"] }
28+
```
29+
30+
For CLI argument parsing support, enable the `clap` feature:
31+
32+
```toml
33+
[dependencies]
34+
moteus = { version = "0.1", features = ["clap"] }
35+
```
36+
37+
## Basic Usage — BlockingController
38+
39+
The simplest way to use moteus is with `BlockingController`, which provides synchronous, blocking communication:
40+
41+
```rust
42+
use std::thread;
43+
use std::time::Duration;
44+
use moteus::{BlockingController, command::PositionCommand};
45+
46+
fn main() -> Result<(), moteus::Error> {
47+
// Auto-discovers transport (fdcanusb, socketcan, etc.)
48+
let mut ctrl = BlockingController::new(1)?;
49+
50+
// Clear any faults
51+
ctrl.set_stop()?;
52+
53+
// Send commands at regular intervals to prevent watchdog timeout
54+
loop {
55+
let result = ctrl.set_position(
56+
PositionCommand::new()
57+
.position(f64::NAN)
58+
.velocity(1.0)
59+
.accel_limit(0.5)
60+
)?;
61+
62+
println!("Position: {} Velocity: {}", result.position, result.velocity);
63+
64+
thread::sleep(Duration::from_millis(10));
65+
}
66+
}
67+
```
68+
69+
The `BlockingController` automatically discovers an available transport (fdcanusb, socketcan) on construction.
70+
71+
## Async Usage — AsyncController
72+
73+
For async applications, enable the `tokio` feature and use `AsyncController`:
74+
75+
```rust
76+
use moteus::AsyncController;
77+
use moteus::command::PositionCommand;
78+
79+
#[tokio::main]
80+
async fn main() -> Result<(), moteus::Error> {
81+
// Auto-discovers transport (fdcanusb, socketcan, etc.)
82+
let mut ctrl = AsyncController::new(1).await?;
83+
84+
ctrl.set_stop().await?;
85+
86+
loop {
87+
let result = ctrl.set_position(
88+
PositionCommand::new()
89+
.position(f64::NAN)
90+
.velocity(0.5)
91+
).await?;
92+
93+
println!("Position: {}", result.position);
94+
95+
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
96+
}
97+
}
98+
```
99+
100+
## Low-Level Usage — Controller
101+
102+
The `Controller` type provides frame building without any transport. This is useful for custom transports, embedded systems, or when you want full control over how frames are sent and received.
103+
104+
```rust
105+
use moteus::{Controller, command::PositionCommand};
106+
107+
let controller = Controller::new(1);
108+
109+
// Build a position command
110+
let cmd = controller.make_position_command(
111+
&PositionCommand::new().position(0.5).velocity(1.0),
112+
true // request query response
113+
);
114+
115+
// Convert to wire frame
116+
let frame = cmd.into_frame();
117+
118+
// Send frame via your own transport...
119+
// frame.arbitration_id, frame.data, frame.size
120+
```
121+
122+
Parse responses back into query results:
123+
124+
```rust
125+
use moteus::query::QueryResult;
126+
127+
// After receiving a response frame from transport...
128+
let result = controller.parse_query(&response_frame)?;
129+
println!("Mode: {:?}, Position: {}", result.mode, result.position);
130+
```
131+
132+
## Custom Query Resolution
133+
134+
By default, only a limited set of registers are queried. To request additional registers, customize the `QueryFormat`:
135+
136+
```rust
137+
use moteus::{BlockingController, Resolution, Register};
138+
use moteus::query::QueryFormat;
139+
140+
let mut query_format = QueryFormat::default();
141+
query_format.power = Resolution::Float;
142+
143+
let mut ctrl = BlockingController::new(1)?;
144+
ctrl.controller.query_format = query_format;
145+
```
146+
147+
For registers not in the standard `QueryFormat`, use the `extra` mechanism:
148+
149+
```rust
150+
use moteus::{BlockingController, Resolution, Register};
151+
use moteus::query::{QueryFormat, ExtraQuery};
152+
153+
let mut query_format = QueryFormat::default();
154+
query_format.extra[0] = ExtraQuery {
155+
register: Register::Encoder1Position,
156+
resolution: Resolution::Float,
157+
};
158+
159+
let mut ctrl = BlockingController::new(1)?;
160+
ctrl.controller.query_format = query_format;
161+
```
162+
163+
## Transport Configuration
164+
165+
### Auto-Discovery Options
166+
167+
Configure transport auto-detection with `TransportOptions`:
168+
169+
```rust
170+
use moteus::{BlockingController, TransportOptions};
171+
172+
let opts = TransportOptions::new()
173+
.socketcan_interfaces(vec!["can0"])
174+
.timeout_ms(200);
175+
176+
let mut ctrl = BlockingController::with_options(1, &opts)?;
177+
```
178+
179+
### Explicit Transport
180+
181+
You can also specify a transport directly:
182+
183+
```rust
184+
use moteus::BlockingController;
185+
use moteus::transport::socketcan::SocketCan;
186+
187+
let transport = SocketCan::new("can0")?;
188+
let mut ctrl = BlockingController::new(1)?
189+
.transport(transport);
190+
```
191+
192+
## Diagnostics
193+
194+
The `DiagnosticStream` provides access to the moteus diagnostic protocol for reading and writing configuration:
195+
196+
```rust
197+
use moteus::DiagnosticStream;
198+
199+
let mut stream = DiagnosticStream::new(1)?;
200+
201+
// Read a configuration value
202+
let response = stream.command("conf get servo.max_current_A")?;
203+
println!("{}", response);
204+
205+
// Write a configuration value
206+
stream.command("conf set servo.max_current_A 30.0")?;
207+
```
208+
209+
## Multi-Servo Coordinated Moves
210+
211+
The `move_to` function provides coordinated multi-servo motion:
212+
213+
```rust
214+
use moteus::move_to::{move_to, MoveToOptions, Setpoint};
215+
216+
let setpoints = vec![
217+
Setpoint { id: 1, position: 0.5, velocity: None, max_torque: None },
218+
Setpoint { id: 2, position: -0.3, velocity: None, max_torque: None },
219+
];
220+
221+
let opts = MoveToOptions::default();
222+
move_to(&setpoints, &opts)?;
223+
```
224+
225+
## API Reference
226+
227+
- [Rust API Reference](../reference/rust.md) — Curated summary of key types
228+
- [moteus on docs.rs](https://docs.rs/moteus/) — Full auto-generated API documentation
229+
- [moteus-protocol on docs.rs](https://docs.rs/moteus-protocol/) — Protocol crate documentation

0 commit comments

Comments
 (0)