PID 控制策略及计算广告中的应用

定义

PID, Proportional, Integral and Derivative, 比例-积分-微分 控制系统.
一种 “控制-观察-调整控制-再观察” 的迭代方法. 每轮迭代中, 得到系统的输出后,计算与预定目标的误差, 包括 {比例,积分,微分} 3种表达,将其叠加到输入中,从而控制系统的行为.

直接上公式.
u ( t ) = P + I + D = K p ∗ e ( t ) + K i ∗ ∫ 0 t e ( t ) d t + K d ∗ d   e ( t ) d t (1) u(t)=P+I+D \\ = K_p*e(t)+K_i*\int_0^t e(t)\mathrm dt+K_d*\frac{\mathrm d\ e(t)}{\mathrm dt} \tag 1 u(t)=P+I+D=Kpe(t)+Ki0te(t)dt+Kddtd e(t)(1)

适用场景

自动驾驶中, 希望汽车提速并稳定到100Km/h, 应该怎么控制动力输出(油门)?
整个系统中有 {风向风力, 地面摩擦力(干燥/湿滑), 汽车载重, 轮胎温度} 等多个影响因素. 控制变量为汽车油门, 即前进动力.
当一切都已知, 自然可以直接计算出来最优的动力分配函数f(t). 但这个假设太理想了, 并且计算难以完成, 所以需要 “控制-观察反馈-调整控制” 这样迭代去完成任务.

工作原理举例

同上汽车加速的任务.
e ( t ) = 100 − v t e(t)=100-v_t e(t)=100vt, 表示当前车速与目标的差值.
u(t)表示各策略叠加后的当前动力输出.

proportional-比例部分

一开始e最大, 乘以固定的系数 P 后也较大.
随着速度的提升, 该控制项的输出会逐步减弱.
但因为风力, 地面摩擦力等原因, 会在某个时刻与 该控制项输出 相等, 速度再也提不上去, 形成稳态误差.

integral-积分部分

离散情况下, 积分就是求和, 把历史上近几轮迭代的 e(t) 相加.
功用:

  1. 达到稳态误差后, 该控制项的和继续增大, 叠加到动力上可以消除稳态误差, 最终达到目标.
  2. p部分力量较弱时, 方便加速提前达到目标.

derivative-微分部分

离散情况下, 微分就是 Δ e = e ( t ) − e ( t − 1 ) \Delta e=e(t)-e(t-1) Δe=e(t)e(t1),
汽车加速中, 离目标值越来越近, 所以 Δ e \Delta e Δe为负, 与一个整数D相乘后依旧为负数.
功用:

  1. 如果动力足够大, 离散的间隔也大, 就会超速, 此控制项用于避免超速, 避免震荡.

可视化仿真

见参考[1]文末.

调参经验

Kp,Ki,Kd 三个参数是 task-specific 的, 通常通过仿真系统人工寻参而得.
Kp 是基础部分, 可先控制 Ki, Kd 两项为0, 二分法迭代.
继续 调整 Ki 与 Kd. 当一个系统没有稳态误差时, Ki 可以置0.

python简易实现

import matplotlib
import matplotlib.pyplot as plt
import matplotlib.axes
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签

class Car:
    """
    被控制系统是一辆汽车
    新的速度=原有速度+加速度-阻力
    """

    def __init__(self):
        self.mass = 100
        self.velocity = 0
        self.accelerated_velocity_arr = []

    def get_current_speed(self, force):
        force_accelerated_velocity = force / self.mass
        wind_accelerated_velocity = - self.velocity * 0.1 / self.mass
        self.velocity = self.velocity + force_accelerated_velocity + wind_accelerated_velocity
        self.accelerated_velocity_arr.append(force_accelerated_velocity + wind_accelerated_velocity)
        return self.velocity


class PIDController:
    """
    输出
    """

    def __init__(self, target_val, kp, ki, kd):
        self.target_val = target_val
        self.controlled_system = Car()

        self.kp = kp
        self.ki = ki
        self.kd = kd

        self.out_put_arr = [0]
        self.observed_val_arr = []

        self.now_val = 0
        self.sum_err = 0
        self.now_err = 0
        self.last_err = 0

    def iterate(self):
        self.observed_val_arr.append(self.controlled_system.get_current_speed(self.out_put_arr[-1]))
        self.now_err = self.target_val - self.observed_val_arr[-1]
        # 这一块是严格按照公式来写的
        out_put = self.kp * self.now_err \
                  + self.ki * self.sum_err \
                  + self.kd * (self.now_err - self.last_err)
        self.out_put_arr.append(out_put)
        self.last_err = self.now_err
        self.sum_err += self.last_err
        return out_put


# 对pid进行初始化,目标值是1000 ,Kp=0.1 ,Ki=0.15, Kd=0.1
controller = PIDController(100, 3, 0.1, 0.2)
# 然后循环100次把数存进数组中去
for i in range(0, 300):
    controller.iterate()
print('controller.out_put_arr,', controller.out_put_arr)
print('car.ccelerated_velocity_arr,', controller.controlled_system.accelerated_velocity_arr)
print('controller.observed_val_arr,', controller.observed_val_arr)
fig, ax1 = plt.subplots()
ax1 = ax1  # type: matplotlib.axes.Axes
ax1.set_xlabel('iterations')
ax1.set_ylabel('force_out_put   (N)', color='red')
# ax1.set_ylim()
ax1.plot(controller.out_put_arr, color="red", label='force_out_put')
ax1.legend(loc=2)

ax2 = ax1.twinx()
ax2.plot(controller.observed_val_arr, color='blue', label='car_speed')
ax2.set_ylabel('car_speed   (Km/h)',color='blue')
ax2.legend(loc=1)
plt.title('PID 控制系统示意')
plt.show()


在这里插入图片描述

参考

  1. 知乎, PID控制算法原理
  2. 知乎, 广告出价–如何使用PID控制广告投放成本
  3. mathworks 无人机例子视频讲解, What is PID Control?
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值