Expand description
Controller trait - 控制器通用接口
定义了所有控制器必须实现的接口。
§设计理念
- Tick 模式: 用户控制循环,控制器只负责计算
- 时间感知: 显式传入
dt,便于单元测试 - 类型安全: 使用强类型单位(
Rad,NewtonMeter) - 错误处理: 关联类型
Error允许自定义错误
§时间跳变处理
当检测到异常的 dt 时(如系统卡顿、线程调度延迟),
on_time_jump() 方法会被调用。
⚠️ 重要: 对于时间敏感的控制器(如 PID),必须覆盖此方法:
- ✅ 必须重置: 微分项(D term),防止计算出巨大的导数
- ❌ 不要清零: 积分项(I term),否则机械臂会瞬间失去抗重力能力
§示例
use piper_client::control::Controller;
use piper_client::types::{JointArray, Rad, NewtonMeter};
use std::time::Duration;
struct MyController {
target: JointArray<Rad>,
last_error: JointArray<f64>,
}
impl Controller for MyController {
type Error = std::io::Error;
fn tick(
&mut self,
current: &JointArray<Rad>,
dt: Duration,
) -> Result<JointArray<NewtonMeter>, Self::Error> {
// 计算控制输出
let error = self.target.map_with(*current, |t, c| t - c);
let output = error.map(|e| NewtonMeter(e.0 * 10.0)); // 简单 P 控制
self.last_error = error.map(|e| e.0);
Ok(output)
}
fn on_time_jump(&mut self, _dt: Duration) -> Result<(), Self::Error> {
// ✅ 重置微分项相关状态
self.last_error = JointArray::from([0.0; 6]);
// ❌ 不要清零积分项!
Ok(())
}
}Traits§
- Controller
- 控制器通用接口