use piper_sdk::client::control::{Controller, PidController};
use piper_sdk::client::types::{JointArray, Rad};
use std::time::Duration;
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
piper_sdk::init_logger!();
println!("🎯 Piper SDK - PID Control Example");
println!("===================================\n");
let target_position = JointArray::from([Rad(1.0); 6]);
let mut pid = PidController::new(target_position)
.with_gains(10.0, 0.5, 0.1) .with_integral_limit(5.0) .with_output_limit(50.0);
println!("🔧 PID 控制器配置:");
println!(" - Kp (比例增益): 10.0");
println!(" - Ki (积分增益): 0.5");
println!(" - Kd (微分增益): 0.1");
println!(" - 积分限制: 5.0");
println!(" - 输出限制: 50.0 Nm");
println!(" - 目标位置: {:?}", target_position[0]);
println!();
let dt = Duration::from_millis(10); let mut current_position = JointArray::from([Rad(0.0); 6]);
println!("▶️ 开始控制循环 (模拟)...\n");
for iteration in 0..100 {
let output = pid.tick(¤t_position, dt)?;
for i in 0..6 {
let force = output[i].0;
let position_change = force * dt.as_secs_f64() * 0.01;
current_position[i] = Rad(current_position[i].0 + position_change);
}
if iteration % 10 == 0 {
let error = (target_position[0].0 - current_position[0].0).abs();
let integral = pid.integral()[0];
println!(
" Iter {}: 位置: {:.4} | 误差: {:.4} | 积分: {:.4} | 输出: {:.2} Nm",
iteration, current_position[0].0, error, integral, output[0].0
);
}
std::thread::sleep(Duration::from_millis(1));
}
println!("\n✅ 控制循环完成!");
println!(" 最终位置: {:?}", current_position[0]);
println!(" 目标位置: {:?}", target_position[0]);
println!(
" 最终误差: {:.6} rad",
(target_position[0].0 - current_position[0].0).abs()
);
println!();
println!("⚠️ 模拟时间跳变...");
let large_dt = Duration::from_millis(100);
pid.on_time_jump(large_dt)?;
println!(" ✅ on_time_jump() 调用成功");
println!(" ✅ 微分项已重置");
println!(" ✅ 积分项保留 (防止机械臂下坠)");
println!();
println!("🔄 重置控制器...");
pid.reset()?;
println!(" ✅ 所有内部状态已清零");
println!(" ✅ 积分项: {:.6}", pid.integral()[0]);
println!();
println!("💡 PID 控制器特性:");
println!(" ✨ Builder 模式 (链式配置)");
println!(" ✨ 积分饱和保护 (防止 Integral Windup)");
println!(" ✨ 输出钳位 (安全保护)");
println!(" ✨ 时间跳变处理 (保留积分项)");
println!(" ✨ 强类型单位 (Rad, NewtonMeter)");
println!();
println!("🎉 示例完成!");
Ok(())
}