반응형

이전 글에서 다룬 Anti-Windup algorithm을 적용한 PID 제어기에 대해서 구현해보았다.

어떤 특성이 있는지 그래프와 함께 볼 수 있다.

 

실험 코드 및 구현

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
using namespace std;
double dt = 0.01;

double Kp = 1.00;
double Ki = 2.00;
double Kd = 0.00;
double y_min = -3.00;
double y_max = 3.00;

double pid_aw(double y, double y_cmd)
{
	static double integral = 0;

	// Calculate error
	double error = y_cmd - y;

	// Proportional term
	double Pout = Kp * error;

	// Integral term
	integral += Ki * error * dt;
	double Iout = integral;

	double out_tmp = Pout + Iout;

	// Anti-Windup Algorithm
	// Restrict to max/min
	if (out_tmp > y_max)
		integral = fmax(y_min, fmin(y_max - Pout, y_max));
	else if (out_tmp < y_min)
		integral = fmax(y_min, fmin(y_min - Pout, y_max));

	// Save error to previous error
	Iout = integral;
	double out = Pout + Iout;

	return out;
}

double pid(double y, double y_cmd)
{
	static double integral = 0;

	// Calculate error
	double error = y_cmd - y;

	// Proportional term
	double Pout = Kp * error;

	// Integral term
	integral += Ki * error * dt;
	double Iout = integral;

	// Save error to previous error
	Iout = integral;
	double out = fmax(y_min, fmin(Pout + Iout, y_max));

	return out;
}

int main()
{
	FILE* fid = fopen("test.txt", "w");

	double TimeEnd = 20.0;
	double u = 1;
	double x = 0;
	double x_prev = 0;
	double y = 0.0;

	double x1 = 0;
	double x1_prev = 0;
	double u1_cmd = 0;
	double y1 = 0;

	double x2 = 0;
	double x2_prev = 0;
	double u2_cmd = 0;
	double y2 = 0;

	double alpha = 0.01;
	double time = 0;
	for (int i = 0; i < (int)(TimeEnd / dt); i++) {

		if (time < 4)
			u = 1;
		else if (time < 6)
			u = -1;
		else if (time < 8)
			u = 2;
		else if (time < 12)
			u = -2;
		else
			u = 0;

		fprintf(fid, "%10.2f %10.6f %10.6f %10.6f %10.6f %10.6f %10.6f\n", time, u, y, y1, u1_cmd, y2, u2_cmd);

		time += dt;

		x = (1.00 - alpha) * x_prev + (alpha)*u;
		x_prev = x;
		y = x * 0.5;
		
        // PID with Anti-windup algorithm
		u1_cmd = pid_aw(y1, u);
		x1 = (1.00 - alpha) * x1_prev + (alpha)*u1_cmd;
		x1_prev = x1;
		y1 = x1 * 0.5;

		// Pure PID
		u2_cmd = pid(y2, u);
		x2 = (1.00 - alpha) * x2_prev + (alpha)*u2_cmd;
		x2_prev = x2;
		y2 = x2 * 0.5;

	}
	fclose(fid);
}

 

데이터 비교

시계열에 따른 응답은 그래프와 같다.

y1, u1_cmd는 Anti-windup 알고리즘을 넣은 PID제어기,

y2, u2_cmd는 순수 PID 제어기이다.

0~8초 구간에서는 제어기 응답이 유사하지만,

8~16초 구간을 보면 초록색 선 (u2_cmd)은 적분기 누적을 벗어나는데 시간이 걸려서

노란 선(u1_cmd)보다 느리게 응답이 따라오는 것을 볼 수 있다.

이로 인해 시스템 응답 또한 상대적으로 느린 것을 볼 수 있다.

 

끝.

 

** EOF **

 

728x90

'G.N.C.' 카테고리의 다른 글

이산 선형 칼만 필터 중간 유도 정리  (0) 2024.04.11
Van der Pol Oscillator  (0) 2024.03.15

+ Recent posts