简介:该PDF为智能车控制系统方向的专业参考文献,围绕智能车路径跟踪中传统PID算法存在的超调与振荡问题,引入单神经元自学习、自整定能力,系统阐述一种改进的单神经元自适应PID控制算法。论文从智能车控制理论与算法谈起,比较位置式PID与增量型PID的适用场景与误差特性,再过渡到单神经元自适应PID控制器结构、学习速率及参数调节方法,并给出实验验证结论。内容面向智能车竞赛团队、自动化控制方向学习者以及嵌入式系统开发者,兼具理论推导与工程参考价值。资源为单文件PDF格式,大小约1.36MB,已有166人浏览学习。读者可通过该论文理解自适应PID相较传统PID在自学习、系统响应与鲁棒性方面的提升,掌握转向和速度控制中P、I、D参数的整定思路,为解决实际赛道环境下小车易受干扰振荡、稳定性不足等问题提供理论依据与实施参考。
1. 智能车控制里PID参数自整定的死结与出路
智能车竞速最磨人的环节往往不在机械调校,而在转向环和速度环那组PID参数。赛道摩擦力随温度变化、CCD图像受光照干扰、电池电压下降后电机响应明显变慢,固定一组Kp、Ki、Kd跑完全程,基本只能在“直道超调”和“弯道迟钝”之间二选一。原因在于智能车本质是非线性时变系统,而传统PID是线性定常控制思路,环境一变参数就失效。这篇论文给出的解法是把增量式PID的固定系数替换成单神经元的三个加权系数,由Hebb学习规则在线更新,外加一个全局比例系数K,让系统自己把参数调到当前路况需要的位置。下面从数字PID的离散化推导讲起,用Python复现论文中的四种学习规则仿真,最后落到K值和三个学习速率的整定顺序上,适合正在做智能车、平衡车、无人机以及电机闭环的嵌入式开发者。
2. 从位置式到增量式:数字PID的离散化推导与选型
2.1 连续PID到位置式数字PID的替换映射
连续系统的PID调节器对偏差e(t)做比例、积分、微分三种运算后线性叠加,控制量u(t)的表达式是:
u(t) = Kp * e(t) + (Kp / Ti) * ∫e(τ)dτ + Kp * Td * de(t)/dt智能车赛道信息由CCD逐帧采样得到,偏差e是离散序列,计算机只能按采样时刻计算控制量,因此必须把连续式离散化。做法是:用采样时刻kT替代连续时间t,用求和式Σ替代积分运算,用差分替代微分,得到数字PID位置式:
u(k) = Kp * e(k) + Ki * Σe(i) + Kd * [e(k) - e(k-1)]其中Ki对应积分系数(通常写作KpT/Ti),Kd对应微分系数(写作KpTd/T)。这个式子就是论文里位置型PID的基础形态,也是理解后面所有推导的起点。
实际工程里还要注意积分分离和抗饱和,位置式输出是控制量的绝对大小,一旦执行机构饱和,累加项会持续积分,恢复时产生明显超调。这部分在论文中虽未展开,但工程上处理不好,位置式会直接导致舵机打满后回不来。
2.2 位置式PID的累加误差与存储代价
位置式算法最大的问题在于偏差累加项Σe(i)。从系统启动到当前时刻的所有偏差都要参与计算,这意味着控制器需要保存完整的历史偏差序列,或者持续维护一个累加变量。对MCU来说,持续维护累加变量看似省内存,但累加值会受早期大偏差的“记忆”拖累:启动瞬间偏差大,累加值迅速冲高,后续偏差再小也难以及时拉回,这就是积分饱和现象。
另一个隐患是截断误差累积。累加项在嵌入式浮点计算中不断叠加,每一次截断误差都会被保留并放大,最终反映为稳态偏移。论文指出位置式PID输出是全量输出,用到过去偏差的累加值,容易产生大的累加误差,这正是智能车这类需要长时间连续运行的控制场景应该规避的。
2.3 增量式PID推导与执行机构适配
增量式算法不需要累加。把位置式在第k-1拍的输出写出来,与第k拍相减,得到控制量的增量:
u(k-1) = Kp * e(k-1) + Ki * Σe(i) + Kd * [e(k-1) - e(k-2)] Δu(k) = u(k) - u(k-1) = Kp * [e(k) - e(k-1)] + Ki * e(k) + Kd * [e(k) - 2*e(k-1) + e(k-2)]整个计算只依赖最近三次偏差采样值,不需要历史累加,单片机实现时只需维护e(k)、e(k-1)、e(k-2)三个变量。智能车场景里CCD给出的路径信息天然是离散序列,增量式PID与这种离散感知结构正好匹配,这是论文选它作为单神经元控制器基础的重要原因。
执行机构层面也能解释为什么增量式更合适。舵机和电机驱动接受的控制量本质是“下一步相对当前位置转多少”,增量式输出天然贴合这个语义;即便某拍计算出错,产生的也只是单拍误动作,不会像位置式那样把错误累加到整个控制量上。
| 连续PID项 | 离散替换形式 | 增量式对应分量 |
|---|---|---|
| 比例项 Kp·e(t) | Kp·e(k) | Kp·[e(k)−e(k−1)] |
| 积分项 (Kp/Ti)·∫e(τ)dτ | Ki·Σe(i) | Ki·e(k) |
| 微分项 Kp·Td·de/dt | Kd·[e(k)−e(k−1)] | Kd·[e(k)−2e(k−1)+e(k−2)] |
提示:增量式PID没有消除积分作用,只是把积分“藏”进了u(k)=u(k−1)+Δu(k)的累加过程里,理解这一点对后续理解单神经元权值更新很有帮助。
3. 单神经元自适应PID控制器结构与学习规则
3.1 从增量式PID到单神经元状态映射
把上一章的增量式公式稍作变形,就能看出单神经元自适应PID的结构来源。定义三个状态输入:
x1(k) = e(k) // 对应增量式中的积分分量 x2(k) = e(k) - e(k-1) // 对应比例分量 x3(k) = e(k) - 2*e(k-1) + e(k-2) // 对应微分分量则增量式PID可以统一写成:
Δu(k) = w1*x1(k) + w2*x2(k) + w3*x3(k)传统PID中w1=Ki、w2=Kp、w3=Kd是三个固定常数。单神经元自适应PID把它们换成三个可学习的加权系数,并引入全局比例系数K,输出形式变为:
u(k) = u(k-1) + K * Σ w'i(k) * xi(k), i = 1, 2, 3 w'i(k) = wi(k) / Σ wj(k)注意下标对应关系很容易看错:w1挂的是积分分量x1,对应学习速率ηI;w2挂比例分量x2,对应ηP;w3挂微分分量x3,对应ηD。论文中三个权值的学习速率各不相同,正是因为三个分量在控制行为中扮演的角色不同。
这个结构和增量式PID的关系可以看作泛化:当K=1且w'1=Ki、w'2=Kp、w'3=Kd时,单神经元控制器完全退化为增量式PID。反过来说,单神经元PID等于给增量式PID装了一个“参数在线调整器”,调整的依据就是下面要讲的学习规则。
3.2 三种经典学习规则对比
单神经元的自学习能力来自权值更新规则。论文对比了三种经典规则,核心差异在于权值修正量的计算是否引入教师信号e(k)和被控量u(k)。
无监督Hebb规则只保留输入与输出的相关性,更新公式为:
Δwi(k) = η * u(k) * xi(k)它没有外部误差引导,纯粹依赖“同时激活的神经元连接增强”这一机制,权值会持续漂移且方向不可控,单独使用很难收敛。
有监督Delta规则引入误差e(k)作为教师信号:
Δwi(k) = η * e(k) * xi(k)误差修正能力强,收敛速度快,但没有保留Hebb规则中“输出参与调节”的机制,在系统接近稳态时容易产生权值振荡。
有监督Hebb规则把两者结合,让误差信号同时参与Hebb乘法结构:
Δwi(k) = η * e(k) * u(k) * xi(k)论文采用的正是这个基础结构,再往下做改进。三种规则在相同被控对象上的动态差异,第四章的仿真可以直观对比。
3.3 加权系数归一化与K值的分工
归一化处理w'i=wi/Σwj有明确的工程意义:三个权值的绝对大小被消掉,只剩下相对比例决定控制行为,控制输出的整体幅值由K单独承担。这样把“权值比例调节”和“输出增益调节”两个问题解耦了,调参时可以先固定K把权值比例学对,再调K匹配执行机构量程。
K值的作用在论文中有明确论述:K取得偏大,调节变快但超调加剧,严重时系统失稳;被控对象时延较大时必须减小K以保稳定;K偏小则响应太慢。后面第五章会专门讨论K的整定方法。
下面给出一个可直接移植到嵌入式工程的单神经元自适应PID类,默认采用论文改进前的有监督Hebb规则,方便对比:
import numpy as np class SingleNeuronPID: """单神经元自适应PID,增量式输出""" def __init__(self, K=0.6, eta=(0.35, 0.40, 0.30), theta=1.0): self.K = K self.eta = np.array(eta) # [etaI, etaP, etaD] self.theta = theta self.w = np.array([0.3, 0.6, 0.1]) # [w1(I), w2(P), w3(D)] self.u_prev = 0.0 self.e_prev = 0.0 self.e_prev2 = 0.0 def update(self, e): x = np.array([e, e - self.e_prev, e - 2 * self.e_prev + self.e_prev2]) w_norm = self.w / np.sum(self.w) du = self.K * np.dot(w_norm, x) u = self.u_prev + du delta_e = e - self.e_prev incentive = e + self.theta * delta_e self.w += self.eta * e * u * incentive self.e_prev2 = self.e_prev self.e_prev = e self.u_prev = u return u构造参数里K控制输出增益,eta的三个分量分别是积分、比例、微分学习速率,theta是改进项系数。w初始值不参与归一化后的稳态行为,只会影响启动阶段的暂态响应,实际移植时可以把已调好的PID参数按比例放进去做初值。如果想让三个eta保持一致,归一化后的权值比例在学习过程中不会发生变化,系统退化为固定增益增量式PID,这也是一个快速自检手段。
4. 改进Hebb学习规则的仿真复现与结果判读
4.1 被控对象模型与方波激励设定
论文仿真采用被控对象为带纯延迟的二阶离散模型:
y(k) = 0.365*y(k-1) + 0.25*y(k-2) + 0.10*u(k-1) + 0.632*u(k-2)这个模型的特征是输出依赖前两拍自身值和前两拍控制量,意味着控制指令施加后需要两拍才能看到反馈,属于中等时延对象。智能车的电机驱动和舵机系统经过简化后可以近似成类似形态,因此论文把它作为验证控制算法的统一平台。
参考输入为幅值0.5的方波信号,表达式为yd(k)=0.5*sgn(sin(4πt)),仿真采样时间1ms。方波信号的好处是每个半周期都提供一个阶跃跳变,能持续考察控制器在不同误差幅值和误差方向下的响应能力,比单纯阶跃响应更能暴露参数自整定的收敛速度。
4.2 改进点e(k)+θΔe(k)的工程动机
论文的核心改进是把权值更新公式中的xi(k)替换为e(k)+θΔe(k),其中Δe(k)=e(k)-e(k-1)。乍看只是换了一个激励项,背后的逻辑值得拆解。
原始有监督Hebb规则的权值修正量正比于e(k)本身。当系统趋近稳态时,e(k)趋近于零,权值更新幅度随之塌缩,学习基本停滞。此时如果还存在小幅稳态误差,要么靠积分项的残余慢慢磨,要么就停在一个固定偏差上。加入θΔe(k)后,即使e(k)很小,只要误差还在变化,Δe项就会继续驱动权值更新,相当于在学习过程中引入误差变化率的“前瞻”作用。
θ作为变化率项的权重,论文在1ms采样下取θ=1。这里有一个工程细节:实车CCD采样周期通常在10ms到20ms量级,Δe比1ms采样时大一个数量级,θ继续取1会让权值更新过于激进,系统容易高频振荡,常见做法是把θ按采样周期比例缩小到0.1~0.3,或者对Δe做归一化处理后再进入激励项。
4.3 四种学习规则的完整仿真代码
用Python把四种学习规则放在同一个循环框架里对比,可以省去Matlab的Simulink环境,直接在Jupyter或命令行跑:
import numpy as np def simulate(rule="improved", N=4000, K=0.6, eta=(0.35, 0.40, 0.30), theta=1.0): T = 1e-3 y = np.zeros(N) # 被控对象输出 u = np.zeros(N) # 控制量 e = np.zeros(N) # 偏差 w = np.array([0.3, 0.6, 0.1]) # [w1(I), w2(P), w3(D)] eta = np.array(eta) for k in range(2, N): ref = 0.5 * np.sign(np.sin(4 * np.pi * k * T)) y[k] = (0.365 * y[k-1] + 0.25 * y[k-2] + 0.10 * u[k-1] + 0.632 * u[k-2]) e[k] = ref - y[k] x = np.array([e[k], e[k] - e[k-1], e[k] - 2*e[k-1] + e[k-2]]) w_norm = w / np.sum(w) u[k] = u[k-1] + K * np.dot(w_norm, x) if rule == "hebb": dw = eta * u[k] * x elif rule == "delta": dw = eta * e[k] * x elif rule == "supervised_hebb": dw = eta * e[k] * u[k] * x else: # improved incentive = e[k] + theta * (e[k] - e[k-1]) dw = eta * e[k] * u[k] * incentive w += dw return y, u, e循环内的执行顺序是先计算输出,再更新权值,这符合单片机中断服务程序里“先控制后学习”的落盘习惯。代码里rule参数可以切换四种学习规则,theta只在improved分支生效。运行后分别考察y曲线对方波的跟踪情况,重点看四个指标:上升时间、超调量、进入稳态所需的振荡周期数、稳态误差。
论文的仿真结论是改进后的算法在抗干扰性和稳定性上优于其余三种规则。实际复现时能看到一个典型差异:改进Hebb规则下系统在第二个方波周期内基本进入稳态,而纯无监督Hebb在多个周期后仍有明显振铃。有监督Delta收敛快但超调突出,原始有监督Hebb比改进型多一两次过冲修正。这个对比同时验证了θΔe项对稳态收敛的加速作用。
仿真参数说明: K = 0.6 神经元比例系数,控制整体增益 eta = 0.35 对应积分权值w1的学习速率 0.40 对应比例权值w2的学习速率 0.30 对应微分权值w3的学习速率 theta = 1.0 改进项系数,论文在1ms采样下取1注意:仿真的1ms采样时间与实车CCD帧率通常不匹配。把这段代码移植到真实硬件前,先按实际采样周期重新计算θ和三个学习速率的量级,否则权值更新会偏激进。
5. 从仿真到实车:K值与学习速率的整定顺序
5.1 K值量级与时延的耦合取舍
仿真里K=0.6能稳定工作,移植到实车后几乎不可能直接沿用。原因是被控对象变了,仿真模型只有两拍时延,而舵机带机械惯性和齿隙,电机还嵌套电流环和速度环,等效时延远大于两拍。K值必须重新从较小的量级起步,推荐以0.1为步进从0.2往上试探。
K值偏大的典型症状是系统持续振荡且振荡频率较低,此时即便减小η也无济于事,因为K是整个控制回路的总增益,所有分量的幅值都乘在它身上。反过来,如果响应慢得像在“爬”,检查K是否过小。先定K再调学习速率,这个顺序不能颠倒。
5.2 学习速率调整顺序:先P后D再I
三个学习速率分别控制权值更新的快慢,调整顺序遵循经典PID调参逻辑:先让系统“动起来不失控”,再压超调,最后消误差。
第一步调ηP。观察阶跃响应,如果超调明显,降低ηP;如果上升过慢,增大ηP。第二步调ηD,主要用来抑制超调引起的高频振铃,ηD过大会放大偏差的二阶差分,表现为高频抖动,需要和传感器噪声一起排查。第三步调ηI,只有当系统出现长时间无法消除的稳态误差时才需要增大ηI,ηI过大引入低频振荡,且这种振荡与K值过大时的振荡形态相近,容易误判。
| 响应现象 | 调整动作 |
|---|---|
| 上升慢,跟踪滞后 | 增大K或ηP |
| 超调量偏大 | 减小ηP |
| 稳态附近高频抖动 | 减小ηD |
| 稳态误差长时间不消 | 增大ηI |
| 低频持续振荡 | 减小K |
三个学习速率不宜同时大幅度改动,每次只动一个,记录阶跃响应的超调量和上升时间变化。权值初值可以直接用增量式PID整定好的Kp、Ki、Kd按比例映射过去,这样启动阶段就接近优参数区间,学习规则只在环境变化时做小范围修正,收敛速度明显快于从任意初值开始。
5.3 用数据观测权值收敛过程
学习是否收敛不能只靠看响应曲线,还需要观测权值本身。把w_norm的三个分量和误差e(k)打包成结构体,通过串口以固定周期发出,用VOFA+或者Serial Plotter可视化,能看到权值比例从初值逐渐迁移到适合当前路况的位置。判断收敛的标准是:w'1、w'2、w'3在连续若干个方波周期内保持基本稳定,同时误差平方均值不再下降。
嵌入式端的主频和任务调度有限,不一定每个控制周期都做权值更新。常见做法是把权值更新周期放宽到CCD的一帧时间,比如控制周期1ms、权值更新周期16ms,控制输出仍按1ms执行,中间插值用最近一次更新后的权值即可。这样既维持了控制频率,又显著降低了学习部分的计算开销,同时让权值更新对单帧噪声不敏感。
本文还有配套的精品资源,点击获取