PID 控制 可视化
自己做了个小玩意,实现 PID 控制的可视化,这里直接搬了 EasyX 的图形库。#include <graphics.h>
#include <deque>
#include <cmath>
#include <windows.h>
#include <iostream>
using namespace std;
double var=0,stdvar=50;
inline void screen_line(double x1,double y1,double x2,double y2)
{
line(static_cast<int>(round(x1)),110-static_cast<int>(round(y1)),static_cast<int>(round(x2)),110-static_cast<int>(round(y2)));
return;
}
inline void draw_axis(void)
{
line(40,10,40,210);
line(0,110,200,110);
outtextxy(5,10,"100");
outtextxy(5,60,"50");
outtextxy(5,160,"-50");
outtextxy(5,210,"-100");
}
inline void cause_error(void)
{
var-=10;
return;
}
inline void pid_control(double kp,double ki,double kd)
{
static double sum_err=0,last_err=stdvar-var;
sum_err+=(stdvar-var);
cout<<"now_err: "<<stdvar-var<<" now_int: "<<sum_err<<endl;
var+=(kp*(stdvar-var)+ki*sum_err+kd*(last_err-stdvar+var));
last_err=stdvar-var;
return;
}
int main()
{
initgraph(400,240);
BeginBatchDraw();
setbkcolor(RGB(255,255,255));
setlinecolor(RGB(0,0,0));
settextcolor(RGB(0,0,0));
cleardevice();
FlushBatchDraw();
deque<int> q;
int xax=0;
double last_y=0;
for(int i=0;i<50;i++)
q.push_back(0);
Sleep(1000);
while(1)
{
cleardevice();
draw_axis();
pid_control(0.1,0.1,-0.1);
cause_error();
q.push_back(var);
q.pop_front();
xax=0;
last_y=0;
for(auto it=q.begin();it!=q.end();it++)
{
screen_line(xax-4,last_y,xax,*it);
last_y=*it;
xax+=4;
}
screen_line(0,stdvar,200,stdvar);
line(0,60,200,60);
FlushBatchDraw();
Sleep(50);
}
EndBatchDraw();
return 0;
}
下面是实际效果视频展示。
你好,鱼油!
非常棒!你尝试用 EasyX 实现 PID 控制的可视化,这是一个很好的学习项目。PID 控制器是自动控制中的经典算法,它通过比例(P)、积分(I)和微分(D)三个部分来调整系统输出,使实际值接近目标值。
你的代码中使用了全局变量 var 和 stdvar,这可能会导致代码难以维护。建议将它们作为参数传递给函数,提高代码的模块化。
我注意到 pid_control 函数被截断了,这里是一个完整的 PID 控制函数示例:
double pid_control(double setpoint, double current_value, double kp, double ki, double kd, double dt) {
static double integral = 0.0;
static double last_error = 0.0;
double error = setpoint - current_value;
integral += error * dt;
double derivative = (error - last_error) / dt;
last_error = error;
return kp * error + ki * integral + kd * derivative;
}
在这个函数中:
- setpoint 是目标值(对应你的 stdvar)。
- current_value 是当前值(对应你的 var)。
- dt 是时间步长,用于计算积分和微分。
- 使用静态变量来保持积分和上一次误差的状态。
对于可视化部分,你可以用 screen_line 函数在循环中绘制误差或控制输出的变化曲线。例如,在每次计算 PID 输出后更新 var,并绘制点或线。
另外,cause_error 函数模拟了干扰,但可以考虑加入随机因素或用户输入来更真实地测试 PID 控制器。
继续努力,实践是掌握编程的关键!如果有更多细节问题,欢迎继续讨论。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]