志存高远,做最好的自己|

静候佳茵

园龄:4年10个月粉丝:21关注:1

车辆编队纵向跟踪控制律设计与仿真

一、车辆纵向动力学建模

1. 轮胎动力学方程

假设每个轮胎都是刚性的,即不考虑轮胎的弹性迟滞损失导致的地面法向反作用力Fz的偏移。又假设车辆四轮驱动,每个轮胎都受到驱动力矩Td、制动力矩Tb、地面切向反作用力Fx、地面法向反作用力Fz、驱动轴作用于车轮的水平力Fp、车轮负荷W。对轮胎受力分析,如下图1所示。

图1 轮胎的地面受力图

以车轮滚动中心O为参考点,列出如下的轮胎动力学力矩平衡方程

Iwωwi·=TdiTbiFxireff(i=fl,fr,rl,rr)

其中reff是车轮的滚动半径。
假如四个轮具有相同的结构参数和运动规律,那么上面的方程可以简化成

(1)Iwωw·=TdTbFxreff

2. 车辆行驶方程式

汽车在倾斜道路上行驶,对它进行纵向力分析,如下图2所示。

图2 在倾斜道路上行驶的车辆的纵向力分析图

根据牛顿第二定律,得到

mx··=Fxf+FxrRxfRxrFaeromgsinθ

其中FxfFxr是驱动力,大小为TdireffRxfRxr是滚动阻力,Faero是等效的纵向空气阻力。令Fx=Fxf+Fxr,Rx=Rxf+Rxr,则有

(2)mx··=FxRxFaeromgsinθ

而车辆的纵向加速度为

(3)x··=reffωw·=reffRωe·

其中R是发动机到车轮的传动比,ωe是发动机输出的角速度。
结合(2)(3)可得车辆行驶方程式

(4)Fx=mreffRωe·+Rx+Faero+mgsinθ

3. 车轮动力流和负载

假设车轮不存在液力变矩器,车辆动力传动系统中的动力流和负载可由下图3所示

图3 车辆动力传动系统中的动力流和负载

3.1 轮胎驱动转矩

因为地面切向反作用力与驱动力近似相等,所以联立轮胎动力学方程(1)、车辆行驶方程式(4)消去Fx,可以得到轮胎驱动转矩表达式

Td=IwRωe·+mreff2Rωe·+Tb+reff(Rx+Faero+mgsinθ)

3.2 变速器驱动转矩

图4 变速器模型示意图

变速器具有减速增距的效果,力矩增大R倍。有如下方程式

{Itωt·=TtTwheelsTwheels=RTdωt=ωe

其中Itωt·是变速器传动轴的转动惯量和角加速度,Itωt·是变速器的力矩损耗,Ttωt是输入给变速器的转矩和角速度。
输入给变速器的转矩Tt

Tt=(It+IwR2+mreff2R2)ωe·+RTb+reffR(Rx+Faero+mgsinθ)

3.3 发动机净扭矩

图5 发动机惯性模型示意图

有如下方程式:

{Ieωe·=TeTpTp=Tt

其中Ieωe·是曲轴的转动惯量和角加速度,Ieωe·是曲轴的力矩损耗,Tp是发动机输出的转矩。
输入给曲轴的转矩Te

(5)Te=(Ie+It+IwR2+mreff2R2)ωe·+RTb+reffR(Rx+Faero+mgsinθ)

4. 车辆加速度与发动机净扭矩关系式

忽略风速,则空气阻力与车辆纵向运动相对速度的平方成正比,有Faero=cxx·2cx为空气阻力系数。而

(6)x·=reffωw=reffRωe

结合(5)(6),得到发动机输出的角加速度与发动机净扭矩的关系

(7)ωe·=1Je(TecxR3reff3ωe2RTbreffR(Rx+mgsinθ))

其中等效转动惯量Je=Ie+It+IwR2+mreff2R2
结合(3)(6)(7),得到车辆加速度与发动机净扭矩之间关系

(8)x··=reffRJe(TecxRreffx·2RTbreffR(Rx+mgsinθ))

5. 简化的车辆纵向动力学方程

不考虑路面的倾斜度,即θ=0,公式(8)可化简为

x··=reffRJe(TecxRreffx·2R(reffRx+Tb))

{M=Jef=R2reff2Rxc=R2reff2cxu=Rreff(TeRTb)

其中Mfc为系统参数,u为控制参数。

则得到简化后车辆纵向动力学方程

(9)x··=ucx·2fM

二、车辆编队纵向滑模控制系统结构

1、车辆纵向跟随队列结构

如下图6所示是车辆跟随队列结构图,第i辆车应与前一辆车(即第ii车)应该保持li的期望车距,xi表示第i辆车到参考位置的距离。定义间距误差ϵ是与前一车辆的实际间距与期望的车辆间距之间的差异,即

(10)ϵi=xi1xi+lii=1,2,...

图6 车辆纵向跟随队列结构图

显然,系统控制目标是

(11)ϵi0

假设车辆编队中的所有车均满足车辆纵向动力学方程(9),则(9)可以改写成

(12)xi··=uicixi·2fiMii=0,1,2,...

2、车辆跟随滑模系统设计

滑模变结构控制是根据系统所期望的动态特性来设计系统的切换超平面,通过滑动模态控制器使系统状态从超平面之外向切换超平面收束。系统一旦到达切换超平面,控制作用将保证系统沿切换超平面到达系统原点,这一沿切换超平面向原点滑动的过程称为滑模控制。接下来具体说明如何把滑模控制应用在车辆纵向跟随队列中。

2.1 切换函数设计

图7 车辆跟随滑模系统状态轨迹运动图

ei1=ϵiei2=ei1·,结合公式(10)(12),可以整理出状态方程

(13){ei1·=ei2ei2·=uiMiciMi(ei2+xi1·)2FiMixi1··

可以设计切换函数

(14)Si=q1ei1+q2ei2q1>0,q2>0

该切换函数满足滑模稳定性,即图7中的②。这是因为一旦系统状态达到切换超平面,即Si=0,那么可以解得ϵi=eq1q2t。所以当t时,ϵi0,满足控制目标要求。

2.2 滑模控制律设计

常用的滑模趋近律有

  • 指数趋近律:Si·=λSi
  • 等速趋近律:Si·=λsgn(Si)
  • 准滑模控制:Si·=λsat(Si)sat(s)={1,s<Δs/Δ,ΔsΔ1,s>Δ

这里仅采用指数趋近律,设计滑模控制律(仿真中三种趋近律都采用了,并且进行了比较)。
对公式(14)左右两边求导,结合公式(13),得到的表达式与指数趋近律联立消去Si·,得到控制律

(15)ui=ci(ei2+xi1·)2Miq1q2ei2+Mixi1··+FiMiq2λSi

该控制律满足滑模可达性,即图7中的①。证明方法如下:
Lyapunov函数 Vi=12Si2,对时间求导,结合公式(13)(14)(15)

Vi·=SiSi·=Si(q1ei1·+q2ei2·)=Si(q1ei2+q2[uiMiciMi(ei2+xi1·)2FiMixi1··])=λSi2<0

可知当Si>0时,Si·<0Si<0时,Si·>0,所以Si0

三、车辆编队滑模控制算法设计

下图8展示的是车辆跟随滑模控制算法流程。算法在设计上的主要难点是如何把一个连续的运动过程表达出来,这里将其离散化,以min_time为时间间隔,间隔数nums,车辆系统运行的总时间为min_timenums。每个时间间隔内,根据起始车0的加速度得到车0的状态,然后依次更新车1、车2、车3...的控制律,控制这些车的状态。更新某车控制律的方法就是公式(15),得到某车(非车0)加速度的方法就是公式(12),得到某车速度的方法是前一时间间隔的速度同这两次加速度平均值与时间间隔的乘积之和,得到某车位移的方法是前一时间间隔的位移同这两次速度平均值与时间间隔的乘积之和。至于车0的加速度规律,我们可以自主设计。(在第四节具体程序实现时,没有按j进行循环,而是重复列举计算,效果一致)

图8 车辆跟随滑模控制算法流程图

四、仿真程序的编写

实验环境:AMD R53500U 64位win10操作系统。编程语言是conda python3.8.13 。绘图库:matplotlib3.5.1。仿真程序脚本如下:

import matplotlib.pyplot as plt

'''
指数趋近律、等速趋近律、准滑模控制的车辆跟随问题仿真,
运行结果以图片形式保存在同目录下。
'''

# q1, q2分别是切换函数ei1, ei2前面的系数
q1, q2 = 1.5, 2
# lan是指数趋近律前面的系数
lan = 0.6
# 设定期望车间距均为18
l1, l2, l3, l4 = 18, 18, 18, 18
# 设定汽车质量
m1, m2, m3, m4 = 2000, 1500, 1500, 1000
# 设定动力学模型分子的速度平方项前的系数ci(按照模型符号是负的)
c1, c2, c3, c4 = 0.8, 0.6, 0.6, 0.5
# 设定动力学模型分子的常数项系数Fi(按照模型符号是负的)
f1, f2, f3, f4 = 300, 250, 250, 200
# 设定五辆车汽车的位移、速度、加速度
x0, x1, x2, x3, x4 = [100.], [84.], [70.], [49.5], [32.]  
v0, v1, v2, v3, v4 = [20.], [12.], [16.], [15.], [16.]
a1, a2, a3, a4 = [0.], [0.], [0.], [0.]


# 设定趋近律
def reaching_law(m:int , s:float, q2:int, mode='exponential'):
    '''
    mode: 指数趋近律exponential
          等速趋近律uniform 
          准滑模控制quasi_sliding
    '''
    if mode == 'exponential':
        return -m * lan * s / q2
    if mode == 'uniform':
        epslion = 0.3
        if s > 0:
            return -m * epslion / q2
        if s == 0:
            return 0
        if s < 0:
            return m * epslion / q2
    if mode == 'quasi_sliding':
        delta, epslion = 0.8, 2.
        if s < -delta:
            return m * epslion / q2
        if s > delta:
            return -m * epslion / q2
        else:
            return -m * epslion * s / (delta * q2)


# 设定第一辆车的加速度(分段函数), 要注意t的长度和a0的长度相等
def get_a0(t:list):    
    a0 = []
    for i in t:
        if i < 2:
            a0.append(0)
            continue
        if i >= 2 and i < 5:
            a0.append(-1 / 6 * (i-2))
            continue
        if i >= 5 and i < 12:
            a0.append(-0.5)
            continue
        if i >= 12 and i < 18:
            a0.append((i-12) / 3 - 0.5) 
            continue
        if i >= 18 and i < 21:
            a0.append(1.5)
            continue
        if i >= 21 and i < 24:
            a0.append((21 - i)/2 + 1.5)
            continue
        if i >= 24 and i <= 30:
            # 注意i=30, 所以是取两端, 故为301份
            a0.append(0)
    return a0


if __name__ == "__main__":
    # 将30秒划分成301份, [0, 0.1, 0.2, ..., 29.9, 30]
    t = [float(i/10) for i in range(301)] 
    a0 = get_a0(t)

    # 四辆车的车间距误差ei1列表
    e11 = [x1[0] - x0[0] + l1]
    e21 = [x2[0] - x1[0] + l2]
    e31 = [x3[0] - x2[0] + l3]
    e41 = [x4[0] - x3[0] + l4]

    # 四辆车的车间距误差导数ei2的列表
    e12 = [v1[0] - v0[0]]
    e22 = [v2[0] - v1[0]]
    e32 = [v3[0] - v2[0]]
    e42 = [v4[0] - v3[0]]

    # 四辆车切换函数的列表
    s1 = [q1 * e11[0] + q2 * e12[0]]
    s2 = [q1 * e21[0] + q2 * e22[0]]
    s3 = [q1 * e31[0] + q2 * e32[0]]
    s4 = [q1 * e41[0] + q2 * e42[0]]

    # 四辆车控制律的列表
    u1, u2, u3, u4 = [0], [0], [0], [0]

    for i in range(1, 301):
        # 最前车0的速度、加速度更新,可以看出更新时用了直线等效, 
        # 0.1指的是时间标度(列表t划分的, 也是之后绘图打印的x轴)
        v0.append(v0[i-1] + 0.1 * (a0[i] + a0[i - 1]) * 0.5)
        x0.append(x0[i-1] + 0.1 * (v0[i] + v0[i - 1]) * 0.5)

        # 车1的车间距误差及导数更新
        e11.append(x1[i-1] - x0[i-1]+l1)
        e12.append(v1[i-1] - v0[i-1])
        # 车1的切换函数更新
        s1.append(q1 * e11[i] + q2 * e12[i])
        # 等效控制
        u1equ = c1 * (e12[i] + v0[i]) * (e12[i] + v0[i]) - m1 * \
            q1 * e12[i] / q2 + m1 * a0[i] + f1 
        # 反馈控制(指数趋近律)
        # # 默认采用指数趋近律, 下同
        # u1n = reaching_law(m1, s1[i], q2)    
        # # 采用等速趋近律
        # u1n = reaching_law(m1, s1[i], q2, mode='uniform')
        # 采用准滑模控制
        u1n = reaching_law(m1, s1[i], q2, mode='quasi_sliding')
        # 更新控制律
        u1.append(u1equ + u1n)
        # 利用控制律更新车1的加速度、速度、位移,加速度是利用动力学模型得到的
        a1.append((-c1 * v1[i-1] * v1[i-1] + u1[i] - f1) / m1)
        v1.append(v1[i-1] + 0.1 * (a1[i] + a1[i - 1]) * 0.5)
        x1.append(x1[i-1] + 0.1 * (v1[i] + v1[i - 1]) * 0.5)
        
        # 车2、3、4过程同车1  
        e21.append(x2[i-1] - x1[i-1]+l2)
        e22.append(v2[i-1] - v1[i-1])
        s2.append(q1 * e21[i] + q2 * e22[i])
        u2equ = c2 * (e22[i] + v1[i]) * (e22[i] + v1[i]) - m2 * q1 *\
             e22[i] / q2 + m2 * a1[i] + f2
        # 默认采用指数趋近律
        # u2n = reaching_law(m2, s2[i], q2)     
        # # 采用等速趋近律
        # u2n = reaching_law(m2, s2[i], q2, mode='uniform')     
        # # 采用准滑模控制
        u2n = reaching_law(m2, s2[i], q2, mode='quasi_sliding') 

        u2.append(u2equ + u2n)
        a2.append((-c2 * v2[i-1] * v2[i-1] + u2[i] -f2) / m2)
        v2.append(v2[i-1] + 0.1 * (a2[i] + a2[i - 1]) * 0.5)
        x2.append(x2[i-1] + 0.1 * (v2[i] + v2[i - 1]) * 0.5)

        e31.append(x3[i-1] - x2[i-1]+l3)
        e32.append(v3[i-1] - v2[i-1])
        s3.append(q1 * e31[i] + q2 * e32[i])
        u3equ = c3 * (e32[i] + v2[i]) * (e32[i] + v2[i]) - m3 * q1 *\
             e32[i] / q2 + m3 * a2[i] + f3 
        # u3n = reaching_law(m3, s3[i], q2)
        # u3n = reaching_law(m3, s3[i], q2, mode='uniform')
        u3n = reaching_law(m3, s3[i], q2, mode='quasi_sliding')
        u3.append(u3equ + u3n)
        a3.append((-c3 * v3[i-1] * v3[i-1] + u3[i] -f3) / m3)
        v3.append(v3[i-1] + 0.1 * (a3[i] + a3[i - 1]) * 0.5)
        x3.append(x3[i-1] + 0.1 * (v3[i] + v3[i - 1]) * 0.5)


        e41.append(x4[i-1] - x3[i-1]+l4)
        e42.append(v4[i-1] - v3[i-1])
        s4.append(q1 * e41[i] + q2 * e42[i])
        u4equ = c4 * (e42[i] + v3[i]) * (e42[i] + v3[i]) - m4 * q1 *\
             e42[i] / q2 + m4 * a3[i] + f4 
        # u4n = reaching_law(m4, s4[i], q2)
        # u4n = reaching_law(m4, s4[i], q2, mode='uniform')
        u4n = reaching_law(m4, s4[i], q2, mode='quasi_sliding')
        u4.append(u4equ + u4n)
        a4.append((-c4 * v4[i-1] * v4[i-1] + u4[i] -f4) / m4)
        v4.append(v4[i-1] + 0.1 * (a4[i] + a4[i - 1]) * 0.5)
        x4.append(x4[i-1] + 0.1 * (v4[i] + v4[i - 1]) * 0.5)
    
    
    # 开始绘图
    # 绘制加速度曲线
    plt.figure()                            # 设置画布
    plt.plot(t, a0, label='car 0')     # :是指绘制点划线
    plt.plot(t, a1, label='car 1')
    plt.plot(t, a2, label='car 2')
    plt.plot(t, a3, label='car 3')
    plt.plot(t, a4, label='car 4')
    plt.xlabel("Time(s)",fontsize=13)
    plt.ylabel("Acceleration(m/s^2)",fontsize=13)
    plt.xlim(0, 30)    
    plt.legend()
    plt.savefig('./acceleration.png')       # 保存图像

    # 绘制速度曲线
    plt.clf()                        # 清空画布,不然会前后图像会重叠
    plt.plot(t, v0, ':', label='car 0')    
    plt.plot(t, v1, ':', label='car 1')
    plt.plot(t, v2, ':', label='car 2')
    plt.plot(t, v3, ':', label='car 3')
    plt.plot(t, v4, ':', label='car 4')
    plt.xlabel("Time(s)",fontsize=13)
    plt.ylabel("velocity(m/s)",fontsize=13)
    plt.xlim(0, 30)    
    plt.legend()
    plt.savefig('./velocity.png')    # 保存图像

    # 绘制位置曲线
    plt.clf()
    plt.plot(t, x0, ':', label='car 0')
    plt.plot(t, x1, ':', label='car 1')
    plt.plot(t, x2, ':', label='car 2')
    plt.plot(t, x3, ':', label='car 3')
    plt.plot(t, x4, ':', label='car 4')
    plt.xlabel("Time(s)",fontsize=13)
    plt.ylabel("position(m)",fontsize=13)
    plt.xlim(0, 30)    
    plt.legend()
    plt.savefig('./position.png')

    # 绘制车间距误差ei1曲线
    plt.clf()
    plt.plot(t, e11, label='car 1')
    plt.plot(t, e21, label='car 2')
    plt.plot(t, e31, label='car 3')
    plt.plot(t, e41, label='car 4')
    plt.xlabel("Time(s)",fontsize=13)
    plt.ylabel("space error(m)",fontsize=13)
    plt.xlim(0, 30)
    plt.legend()
    plt.savefig('./space_error.png')

    # 绘制车间距误差导数ei2曲线
    plt.clf()
    plt.plot(t, e12, ':', label='car 1')
    plt.plot(t, e22, ':', label='car 2')
    plt.plot(t, e32, ':', label='car 3')
    plt.plot(t, e42, ':', label='car 4')
    plt.xlabel("Time(s)",fontsize=13)
    plt.ylabel("space_error_derivative(m)",fontsize=13)
    plt.xlim(0, 30)
    plt.legend()
    plt.savefig('./space_error_derivative.png')

    # 绘制切换函数曲线
    plt.clf()
    plt.plot(t, s1, label='car 1')
    plt.plot(t, s2, label='car 2')
    plt.plot(t, s3, label='car 3')
    plt.plot(t, s4, label='car 4')
    plt.xlabel("Time(s)",fontsize=13)
    plt.ylabel("Switching Function",fontsize=13)
    plt.xlim(0, 30)
    plt.legend()
    plt.savefig('./Switching_Function.png')

    # 绘制控制输入U曲线
    plt.clf()
    plt.plot(t, u1, label='car 1')
    plt.plot(t, u2, label='car 2')
    plt.plot(t, u3, label='car 3')
    plt.plot(t, u4, label='car 4')
    plt.xlabel("Time(s)",fontsize=13)
    plt.ylabel("Control Input",fontsize=13)
    plt.xlim(0, 30)
    plt.legend()
    plt.savefig('./Control_Input.png')

五、仿真结果和分析

1. 参数设定

分别设置四辆车的质量、空气阻力相关的系数、常数项系数;设置期望间距;设置五辆车的初始位移、速度、加速度;设置指数趋近律前面的系数λ;设置切换函数前的系数,具体结果如下

# q1, q2分别是切换函数ei1, ei2前面的系数
q1, q2 = 1.5, 2
lan = 0.6 # lan是指数趋近律前面的系数
epslion = 0.3 # 等速趋近律参数
delta, epslion = 0.8, 2. # 准滑模控制参数
# 设定期望车间距均为18
l1, l2, l3, l4 = 18, 18, 18, 18
# 设定汽车质量
m1, m2, m3, m4 = 2000, 1500, 1500, 1000
# 设定动力学模型分子的速度平方项前的系数ci(按照模型符号是负的)
c1, c2, c3, c4 = 0.8, 0.6, 0.6, 0.5
# 设定动力学模型分子的常数项系数Fi(按照模型符号是负的)
f1, f2, f3, f4 = 300, 250, 250, 200
# 设定五辆车汽车的位移、速度、加速度
x0, x1, x2, x3, x4 = [100.], [84.], [70.], [49.5], [32.]  
v0, v1, v2, v3, v4 = [20.], [12.], [16.], [15.], [16.]
a1, a2, a3, a4 = [0.], [0.], [0.], [0.]

设置车0的加速度,方程如下

a0={0t<2t262t<50.55t<12t1230.512t<181.518t<21t212+1.521t<24024t<30

2. 指数趋近律

图9 指数趋近律控制仿真结果

上图是指数趋近律控制仿真结果。结果与我们前面理论推导的相符合,采用指数趋近律,滑模在非有限时间内可达,切换函数最终趋近于0,车间距误差最终趋近于0,趋近律的控制速度很快。没有抖振,并且控制输入比较平滑,在本场景的参数设定下,是比较理想的控制方式。

3. 等速趋近律

下图表示的是等速趋近律仿真结果。发现加速度出现明显的抖振,尤其是队列中后面的车抖振的更加明显,滑模稳定性很差。同时可以发现等速趋近律控制速度很慢,相同时间内可达性能远不如指数趋近律。在本场景的参数设定下,该控制方式不理想。

图10 等速趋近律仿真结果

4. 准滑模控制

图11 准滑模控制仿真结果

上图表示的是准滑模控制仿真结果。没有抖振,滑模稳定性较好,趋近律的控制速度比较快,滑模在有限时间内可达,但加速度和控制输入的平滑性不如指数趋近律。在本场景的参数设定下,也是比较理想的控制方式。

5. 仿真结论

在本场景的参数设定下,如果追求控制的速度和平滑性,选用指数趋近律作为控制方式;如果追求控制的长期精确性,选用准滑模控制作为控制方式;等速趋近律会产生抖振,且控制速度很慢,一般不选用。

posted @   静候佳茵  阅读(1112)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起