kcan 0.3.0

CAN controller primitives for actuator and motor control.
Documentation
# kcan

CAN controller primitives and CLI tools for actuator and motor control.

## Status

Published by Trevor Knott, Knott Dynamics.

Keywords: KCAN, CubeMars, RobStride, Scrin, Aisling, Trevor Knott, Knott Dynamics.

## Features

- MIT force-control frame packing for supported CubeMars AK actuators, including AK60-39 V3.0 KV80.
- CubeMars direct servo command builders, including V3.2 motor-disable and feedback configuration.
- Knott Dynamics K00 (5010-class) and K01 (6512-class) standard-CAN support: NMT, probe,
  watchdog/heartbeat, position-velocity and position-torque PDOs, flash commands, typed SDOs,
  telemetry parsing, and the complete 80-parameter registry.
- Feedback decoding, tuned specs for primary AK models, conservative defaults for other AK names, unit conversions, and safe velocity clamping.
- Generic `CanBus` trait for tests, embedded adapters, or Linux SocketCAN.
- Optional `serde` feature for serializable actuator configs, snapshots, commands, and feedback.
- Optional `socketcan` feature for direct Linux SocketCAN usage.
- Optional `tui` feature for a Scrin/Scrin Widgets actuator dashboard, wide actuator pane wall, read-only telemetry analytics, and safe control-intent model.
- Cross-family actuator snapshots with derived health labels and protocol-specific dashboard metrics.
- CAN monitor utilities for rolling frame logs, trace CSV export/replay, basic protocol classification, data formatting, and Scrin/Aisling TUI viewing.
- Standard `Display` output for CAN IDs and frames, plus `FromStr` for CAN IDs with explicit standard/extended kind.
- `Display` and `FromStr` support for model names, direct modes, helper commands, and RobStride frame kinds.
- `kcan` command for model listing and frame generation.

## Crate Layout

`kcan` remains the main user-facing crate and binary name.

Use companion crates only when you need a narrower layer:

```toml
kcan = "0.3"
kcan-core = "0.1"
kcan-viewer = "0.1"
```

- `kcan-core`: no-std CAN frame/protocol primitives for embedded or dependency-light reuse.
- `kcan-viewer`: Scrin/Aisling pane-wall viewer components for larger terminal apps.
- `kcan`: actuator models, controllers, monitor utilities, optional SocketCAN/TUI integration, and the `kcan` CLI.

## Quick Use

For a beginner cheat sheet, see `docs.md`.

Build a RobStride status query frame in Rust:

```rust
use kcan::{RobStrideModel, robstride_status_query_frame};

let model: RobStrideModel = "rs01".parse()?;
let frame = robstride_status_query_frame(0x01)?;

assert_eq!(model.to_string(), "RS-01");
assert_eq!(frame.id().raw(), 0x501);
# Ok::<(), kcan::Error>(())
```

Build a CubeMars MIT neutral frame in Rust:

```rust
use kcan::{MitCommand, MotorModel, mit_command_frame};

let frame = mit_command_frame(MotorModel::Ak60_6, 0x03, MitCommand::neutral())?;

assert_eq!(frame.id().raw(), 0x0803);
assert_eq!(frame.len(), 8);
# Ok::<(), kcan::Error>(())
```

Build a Knott Dynamics K00/K01 position-velocity target frame in Rust:

```rust
use kcan::{KnottDynamicsModel, knott_dynamics_position_velocity_frame};

let model: KnottDynamicsModel = "k01".parse()?;
let frame = knott_dynamics_position_velocity_frame(1, 1.0, -2.0)?;

assert_eq!(model.to_string(), "K01");
assert_eq!(frame.id().raw(), 0x301);
assert_eq!(frame.data(), &[0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0xC0]);
# Ok::<(), kcan::Error>(())
```

Build a CubeMars AK60-39 V3.0 KV80 MIT neutral frame:

```sh
cargo run --bin kcan -- cubemars mit ak60-39 0x03
```

Run the CLI help:

```sh
cargo run --bin kcan -- help
```

List supported models:

```sh
cargo run --bin kcan -- models
```

Build a CubeMars direct velocity frame:

```sh
cargo run --bin kcan -- cubemars direct 0x03 velocity 1000
```

Build CubeMars V3.2 motor-disable and 32-bit position feedback configuration frames:

```sh
cargo run --bin kcan -- cubemars direct 0x03 disable
cargo run --bin kcan -- cubemars direct 0x03 feedback-config position-32bit
```

The feedback configuration command writes motor Flash. Build and inspect it offline first, and do not transmit it repeatedly.

Use `MotorController::receive_feedback_update` or `MotorManager::receive_feedback_update` to consume V3.2 `0x29` status and optional `0x2A` 32-bit position frames as separate typed events in wire order.

Build a RobStride status query frame:

```sh
cargo run --bin kcan -- robstride status rs01 0x01
```

Build Knott Dynamics management, command, and SDO frames:

```sh
cargo run --bin kcan -- knott nmt 1 disabled idle
cargo run --bin kcan -- knott disable 1
cargo run --bin kcan -- knott probe 1
cargo run --bin kcan -- knott position-velocity 1 1.0 -2.0
cargo run --bin kcan -- knott position-torque 1 1.0 0.5
cargo run --bin kcan -- knott read 1 firmware_version
cargo run --bin kcan -- knott write 1 idle torque_limit 1.0
cargo run --bin kcan -- knott flash 1 idle store
cargo run --bin kcan -- knott heartbeat 1
```

The CLI only builds and prints frames; it does not transmit them. Commands that depend on device
state require a `current_mode` argument and use the checked builders. Supply a freshly read mode,
not an assumed startup mode. A stale host observation cannot replace firmware-side validation.

K00 and K01 use the same wire protocol. Model identity does not inject unverified motor limits;
safe limits and protection thresholds remain driver configuration. Calibration is deliberately
not available over CAN. Heartbeat is not a neutral command: it services the watchdog and can keep
the previous active command alive. Flash store persists the current configuration and is permitted
only while disabled or idle with PWM off. Use `knott disable <node>` for the canonical PWM-off
request; damping is electrical braking and is not torque-off. The typed SDO builder intentionally
rejects a zero watchdog timeout because zero disables the command watchdog.

Enable SocketCAN support with:

```toml
kcan = { version = "0.2", features = ["socketcan"] }
```

Run the sample TUI dashboard with:

```sh
cargo run --example tui_dashboard --features tui
```

List supported CubeMars models and generated frame IDs with:

```sh
cargo run --example cubemars_models
```

Print hardware-free CubeMars direct frames:

```sh
cargo run --example cubemars_direct_frames
```

Print hardware-free AK60-39 V3.0 KV80 base frames:

```sh
cargo run --example cubemars_ak60_39_base
```

Print hardware-free RobStride frames:

```sh
cargo run --example robstride_frames
```

Print hardware-free Knott Dynamics frames:

```sh
cargo run --example knott_dynamics_frames
```

Run a simulated CAN monitor with:

```sh
cargo run --example can_monitor_demo --features tui
```

Run a live SocketCAN monitor with:

```sh
cargo run --example socketcan_monitor --features socketcan,tui -- can0
```

Run a live read-only actuator dashboard with CubeMars, RobStride, and Knott Dynamics targets:

```sh
cargo run --example socketcan_dashboard --features socketcan,tui -- can0 cubemars:ak60-6:0x03 robstride:rs01:0x01 knott:k01:0x02
```