PID 제어

정승균·2021년 2월 2일
0

자율주행 제어

목록 보기
3/8
post-thumbnail

Ⅰ. P controller


  • Error 에 비례해서 control input 생성

    u(t)=Kpe(t)u(t) = K_pe(t)
  • But, Overshoot이 생김


Ⅱ. PD controller


  • error의 미분값을 고려
    u(t)=Kpe(t)+Kdddte(t)u(t) = K_pe(t) + K_d\frac{d}{dt}e(t)
  • Overshoot을 줄일 수 있음

  • But, system에 bias가 있는 경우 잡지 못함

  • 주의할 점으로 보통 측정값에는 노이즈가 끼기 때문에 state-estimator나 low-pass-filter를 사용하는 것이 좋음

Ⅲ. PID controller


  • error의 누적값을 고려
    u(t)=Kpe(t)+Kdddte(t)+Ki0te(t)dtu(t) = K_pe(t) + K_d\frac{d}{dt}e(t) + K_i\int_0^t e(t)dt
  • steady-state-error를 없앨 수 있음

  • 주의할 점으로 wind-up 문제가 있음


Ⅳ. 코드 예시


import numpy as np
import matplotlib.pyplot as plt

# paramters
dt = 0.1
L = 3.0


class LateralPlant(object):
    def __init__(self, x=0.0, y=0.0, yaw=0.0, v=0.0):
        self.x = x
        self.y = y
        self.yaw = yaw
        self.v = v

        self.max_steering = np.radians(30)

    def update(self, steer, a=0):
        steer += np.radians(3)
        steer = np.clip(steer, -self.max_steering, self.max_steering)
        self.x += self.v * np.cos(self.yaw) * dt
        self.y += self.v * np.sin(self.yaw) * dt
        self.yaw += self.v / L * np.tan(steer) * dt
        self.yaw = self.yaw % (2.0 * np.pi)
        self.v += a * dt


if __name__ == "__main__":
    plant = LateralPlant(x=0.0, y=0.0, yaw=0.0, v=1.0)
    target_y = 1.0
    kp = 0.4
    kd = 2.0
    ki = 0.003

    ys = []
    ts = []
    prev_error = plant.y - target_y
    int_error = 0.0
    for step in range(500):
        t = step * dt
        error = plant.y - target_y

        diff_error = error - prev_error
        prev_error = error
        int_error += error

        steer = - kp * error - kd * diff_error/dt - ki * int_error
        plant.update(steer)

        ys.append(plant.y)
        ts.append(t)

    plt.figure()
    plt.plot([0, ts[-1]], [target_y, target_y], 'r-', label="reference")
    plt.plot(ts, ys, 'b-', label="PID controller")
    plt.xlabel('X (m)')
    plt.ylabel('Y (m)')
    plt.legend(loc="best")
    plt.axis("equal")

    plt.show()

0개의 댓글