// // pid.cpp// MATLAB pid 函数的 C 实现 演示程序单文件版本// 编译: g -stdc17 -O2 pid.cpp -o pid// 运行: ./pid// #includeiostream#includeiomanip#includestring#includecmath#includestdexcept#includecstdio// -------------------------------------------------------------// PID 控制器类 (对应 MATLAB: C pid(Kp, Ki, Kd, Tf, Ts))// -------------------------------------------------------------classPIDController{public:// 构造: pid(Kp, Ki, Kd) / pid(Kp,Ki,Kd,Tf) / pid(Kp,Ki,Kd,Tf,Ts)PIDController(doubleKp1.0,doubleKi0.0,doubleKd0.0,doubleTf0.0,// 微分滤波时间常数, 0 无滤波doubleTs-1.0)// 采样时间, -1 连续:Kp_(Kp),Ki_(Ki),Kd_(Kd),Tf_(Tf),Ts_(Ts){if(Tf_0.0)throwstd::invalid_argument(Tf must be 0);reset();}// ---- 参数设置/读取 ----voidsetKp(doublev){Kp_v;}voidsetKi(doublev){Ki_v;}voidsetKd(doublev){Kd_v;}voidsetTf(doublev){if(v0)throwstd::invalid_argument(Tf 0);Tf_v;}voidsetTs(doublev){Ts_v;}doublegetKp()const{returnKp_;}doublegetKi()const{returnKi_;}doublegetKd()const{returnKd_;}doublegetTf()const{returnTf_;}doublegetTs()const{returnTs_;}// 输出限幅voidsetOutputLimits(doubleumin,doubleumax){if(uminumax)throwstd::invalid_argument(umin must be umax);useSaturation_true;umin_umin;umax_umax;}// 重置内部状态voidreset(){integral_0.0;prevError_0.0;prevDeriv_0.0;prevOutput_0.0;firstCall_true;}// ---- 离散更新: u C * e ----doubleupdate(doubleerror,doubledt){if(dt0.0)throwstd::invalid_argument(dt must be 0);// 比例项doublePKp_*error;// 积分项 (梯形积分)if(Ki_!0.0){integral_0.5*dt*(errorprevError_);}doubleIKi_*integral_;// 微分项 (带可选一阶滤波)doubleD0.0;if(Kd_!0.0){if(Tf_0.0){doubleaTf_/(Tf_dt);doublebKd_/(Tf_dt);Da*prevDeriv_b*(error-prevError_);prevDeriv_D;}else{DKd_*(error-prevError_)/dt;prevDeriv_D;}}// 总输出doubleuPID;// 输出饱和 条件积分抗饱和if(useSaturation_){if(uumax_){uumax_;if(Ki_!0.0)integral_-0.5*dt*(errorprevError_);}elseif(uumin_){uumin_;if(Ki_!0.0)integral_-0.5*dt*(errorprevError_);}}prevError_error;prevOutput_u;firstCall_false;returnu;}// 便捷接口: 直接传 setpoint 和 measurementdoublecompute(doublesetpoint,doublemeasurement,doubledt){returnupdate(setpoint-measurement,dt);}// 打印描述std::stringtoString()const{charbuf[512];std::snprintf(buf,sizeof(buf),PID: Kp%.6g, Ki%.6g, Kd%.6g, Tf%.6g, Ts%.6g,Kp_,Ki_,Kd_,Tf_,Ts_);returnstd::string(buf);}private:doubleKp_,Ki_,Kd_;doubleTf_;doubleTs_;// 内部状态doubleintegral_0.0;doubleprevError_0.0;doubleprevDeriv_0.0;doubleprevOutput_0.0;boolfirstCall_true;// 饱和booluseSaturation_false;doubleumin_0.0,umax_0.0;};// -------------------------------------------------------------// 演示程序// -------------------------------------------------------------intmain(){// 类似 MATLAB: C pid(2, 1, 0.5, 0.1)PIDControllerC(2.0,1.0,0.5,0.1);// 输出限幅C.setOutputLimits(-100.0,100.0);constdoubleTs0.01;// 采样周期 10msdoublesetpoint1.0;doublemeasurement0.0;doubleplant0.0;// 一阶被控对象状态std::coutstd::fixedstd::setprecision(4);std::cout t(s) sp y u\n;for(intk0;k500;k){doubleuC.compute(setpoint,measurement,Ts);// 一阶对象: y[k1] y[k] Ts*( -y[k] u )plantTs*(-plantu);measurementplant;if(k%500)std::coutstd::setw(6)k*Ts std::setw(6)setpoint std::setw(6)measurement std::setw(8)u\n;}std::coutC.toString()std::endl;return0;}