当前位置: 首页 > 知识库问答 >
问题:

利用非线性模型预测控制在GEKKO中实现横向控制

陆涵畅
2023-03-14

我正在尝试为一个由横向动力学模型定义的自动车辆实施横向控制器。我的问题是CVs没有达到SP设定的理想参考点或目标点。我使用以下运动方程和目标函数。我使用半经验公式(pacejka)计算Fyf Fyr提供的轮胎力。这是运动方程和目标函数。提前谢谢。

from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
import time 
import math


#%% NMPC model
T = 5
nt = 51
m = GEKKO(remote=False)
m.time = np.linspace(0,T,nt)

#Model Parameters
X_speed = m.Param(value=10.0)
mass=m.Param(value=1611.0)
c=m.Param(value=1.351) 
b=m.Param(value=1.5242)
Iz=m.Param(value=3048.1) 

Cyf=m.Param(value=1.30)
Dyf=m.Param(value=3449.94238709)
Byf=m.Param(value=0.223771457713)
Eyf=m.Param(value=-0.6077272729)

Cyr=m.Param(value=1.30)
Dyr=m.Param(value=3846.47835351)
Byr=m.Param(value=0.207969093485)
Eyr=m.Param(value=-0.7755647971)

#Variables
slip_angle_front_tire = m.Var(value=0.0, lb=-10.0, ub=14.0 )
slip_angle_rear_tire = m.Var(value=0.0, lb=-10.0, ub=14.0 )

phi_f = m.Var(value=0.0)
phi_r = m.Var(value=0.0)

maxF = 5000

Ffy = m.Var(value=0.0, lb=-.0*maxF, ub=maxF )
Fry = m.Var(value=0.0, lb=-1.0*maxF, ub=maxF )

 
xpos = m.Var(value=0.0)
dy = m.Var(value=0.0)
dpsi = m.Var(value=0.0)

#MV
steering = m.MV(value=0, lb=-0.40, ub=0.40 )

#CV
ypos = m.CV(value=0.0 ,lb =-200.0,ub=200.0 )
psipos = m.CV(value=0.0,lb=-3.5,ub=3.5)

#Equations
m.Equation(ypos.dt() == dy)
m.Equation(psipos.dt() == dpsi)

m.Equation(slip_angle_front_tire == steering - m.atan( (dy+b*dpsi)/X_speed ) )
m.Equation(slip_angle_rear_tire == -1.0*m.atan( (dy-c*dpsi) / X_speed))

m.Equation(phi_f == (1-Eyf)*(slip_angle_front_tire) + (Eyf/Byf)*(m.atan(Byf*slip_angle_front_tire) ) )
m.Equation(phi_r == (1-Eyr)*(slip_angle_rear_tire) + (Eyr/Byr)*(m.atan(Byr*slip_angle_rear_tire) ) )

m.Equation(Ffy == (Dyf*( m.sin(Cyf*m.atan(Byf*phi_f ) ) ) ) *2.0 )
m.Equation(Fry == (Dyr*( m.sin(Cyr*m.atan(Byr*phi_r ) ) ) ) *2.0 )

m.Equation(mass*dy.dt() == (Ffy*m.cos(steering) ) + (Fry) - (X_speed*dpsi*mass) ) 
m.Equation(dpsi.dt()*Iz == ( b*Ffy*m.cos(steering) ) - ( c*Fry) )

#Global options
m.options.IMODE = 6 #MPC
m.options.CV_TYPE = 2
m.options.MV_TYPE = 0

#MV tuning
steering.STATUS = 1
steering.DCOST = 0.01

#CV Tuning
ypos.STATUS = 1
psipos.STATUS = 1

ypos.TR_INIT = 2
psipos.TR_INIT = 2


ypos.WSP = 100 
psipos.WSP = 10

ypos.SP = 9.2
psipos.SP = 1.5

print('Solver starts ...')
t = time.time()
m.solve(disp=True)
print('Solver took ', time.time() - t, 'seconds')

plt.figure()

plt.subplot(4,1,1)
plt.plot(m.time,steering.value,'b-',LineWidth=2)
plt.ylabel('steering wheel')

plt.subplot(4,1,2)
plt.plot(m.time,ypos.value,'r--',LineWidth=2)
plt.ylabel('y-point')

plt.subplot(4,1,3)
plt.plot(m.time,psipos.value,'r--',LineWidth=2)
plt.ylabel('yaw angle')
plt.xlabel('time')
plt.show()

共有1个答案

云季萌
2023-03-14

对于参考轨迹,您需要包括时间常数TAU,以了解达到设定点的速度。

ypos.TAU = 1.5
psipos.TAU = 1.5

在动态优化练习中,还有关于调优MPC应用程序的其他信息。

您需要的另一个修正是Ffy=m.Var(value=0.0,lb=-1.0*maxF,ub=maxF)中的-1.0。否则,它永远无法达到设定点。似乎无法达到两个设定点,因此它优先尝试满足权重较高的ypos设定点。您可能需要另一个MV来控制ypospsipos。否则,您可以考虑打开<代码>转向< /代码>界限,看看它是否可以找到更少的限制更好的解决方案。我还将结束时间设置为10,有101个点,因为它需要额外的时间来稳定到新的设定点。

from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
import time 
import math


#%% NMPC model
T = 10
nt = 101
m = GEKKO(remote=False)
m.time = np.linspace(0,T,nt)

#Model Parameters
X_speed = m.Param(value=10.0)
mass=m.Param(value=1611.0)
c=m.Param(value=1.351) 
b=m.Param(value=1.5242)
Iz=m.Param(value=3048.1) 

Cyf=m.Param(value=1.30)
Dyf=m.Param(value=3449.94238709)
Byf=m.Param(value=0.223771457713)
Eyf=m.Param(value=-0.6077272729)

Cyr=m.Param(value=1.30)
Dyr=m.Param(value=3846.47835351)
Byr=m.Param(value=0.207969093485)
Eyr=m.Param(value=-0.7755647971)

#Variables
slip_angle_front_tire = m.Var(value=0.0, lb=-10.0, ub=14.0 )
slip_angle_rear_tire = m.Var(value=0.0, lb=-10.0, ub=14.0 )

phi_f = m.Var(value=0.0)
phi_r = m.Var(value=0.0)

maxF = 5000

Ffy = m.Var(value=0.0, lb=-1.0*maxF, ub=maxF )
Fry = m.Var(value=0.0, lb=-1.0*maxF, ub=maxF )


xpos = m.Var(value=0.0)
dy = m.Var(value=0.0)
dpsi = m.Var(value=0.0)

#MV
steering = m.MV(value=0, lb=-0.4, ub=0.4 )

#CV
ypos = m.CV(value=0.0 ,lb =-200.0,ub=200.0 )
psipos = m.CV(value=0.0,lb=-3.5,ub=3.5)

#Equations
m.Equation(ypos.dt() == dy)
m.Equation(psipos.dt() == dpsi)

m.Equation(slip_angle_front_tire == steering - m.atan( (dy+b*dpsi)/X_speed ) )
m.Equation(slip_angle_rear_tire == -1.0*m.atan( (dy-c*dpsi) / X_speed))

m.Equation(phi_f == (1-Eyf)*(slip_angle_front_tire) + (Eyf/Byf)*(m.atan(Byf*slip_angle_front_tire) ) )
m.Equation(phi_r == (1-Eyr)*(slip_angle_rear_tire) + (Eyr/Byr)*(m.atan(Byr*slip_angle_rear_tire) ) )

m.Equation(Ffy == (Dyf*( m.sin(Cyf*m.atan(Byf*phi_f ) ) ) ) *2.0 )
m.Equation(Fry == (Dyr*( m.sin(Cyr*m.atan(Byr*phi_r ) ) ) ) *2.0 )

m.Equation(mass*dy.dt() == (Ffy*m.cos(steering) ) + (Fry) - (X_speed*dpsi*mass) ) 
m.Equation(dpsi.dt()*Iz == ( b*Ffy*m.cos(steering) ) - ( c*Fry) )

#Global options
m.options.IMODE = 6 #MPC
m.options.CV_TYPE = 2
m.options.MV_TYPE = 1

#MV tuning
steering.STATUS = 1
steering.DCOST = 0.1

#CV Tuning
ypos.STATUS = 1
psipos.STATUS = 1

ypos.TR_INIT = 2
psipos.TR_INIT = 2

ypos.WSP = 100 
psipos.WSP = 10

ypos.SP = 9.2
psipos.SP = 1.5

ypos.TAU = 1.5
psipos.TAU = 1.5

print('Solver starts ...')
t = time.time()
m.solve(disp=True)
print('Solver took ', time.time() - t, 'seconds')

plt.figure()

plt.subplot(3,1,1)
plt.plot(m.time,steering.value,'b-',LineWidth=2)
plt.ylabel('steering wheel')

plt.subplot(3,1,2)
plt.plot([0,10],[9.2,9.2],'k-')
plt.plot(m.time,ypos.value,'r--',LineWidth=2)
plt.ylabel('y-point')

plt.subplot(3,1,3)
plt.plot([0,10],[1.5,1.5],'k-')
plt.plot(m.time,psipos.value,'g:',LineWidth=2)
plt.ylabel('yaw angle')
plt.xlabel('time')
plt.show()
 类似资料:
  • 所以我让学生在地图中显示,每个学生都有布尔值。我使用这个值来确定标记是否应该使用方法在地图上显示。! 我有一个开关按钮,通过更新实时数据库中的值来显示和隐藏标记,但它并不总是有效的。 问题是,当值设置为=>时,标记不会隐藏!!,但当值设置为时,标记就会出现!?唯一的方法,让标记隐藏是如果我关闭地图,然后再打开它,这当然不是任何人想要的。! 我如何显示标记 如何更新标记 TestUserStuden

  • 好的,我有一个视图控制器,它是一个AVPlayer。我希望这个控制器能够旋转到横向模式并自由肖像 当我关闭屏幕时,我仍然需要以前的控制器处于纵向。这应该不是问题,因为竖屏被锁定为我设置中的唯一方向,我想保持这种状态。但是我希望这个屏幕能够自由移动。任何想法和提示都将不胜感激。 app delegate方法对我无效。重写也不应在函数中自动旋转或支持InterfaceOrientations

  • CodeIgniter 的开发基于 MVC(模型-视图-控制器)设计模式。MVC 是一种 用于将应用程序的逻辑层和表现层分离出来的软件方法。在实践中,由于这种分离 所以你的页面中只包含很少的 PHP 脚本。 模型 代表你的数据结构。通常来说,模型类将包含帮助你对数据库进行增删改查的方法。 视图 是要展现给用户的信息。一个视图通常就是一个网页,但是在 CodeIgniter 中, 一个视图也可以是一

  • 问题内容: 我试图对我的应用程序强制使用“横向”模式,因为我的应用程序绝对不是针对“人像”模式设计的。我怎样才能做到这一点? 问题答案: 现在可以使用HTML5 Webapp清单。 见下文。 原始答案: 您不能将网站或Web应用程序锁定在特定方向。它违反了设备的自然行为。 您可以使用CSS3媒体查询来 检测 设备方向,如下所示: 或通过绑定JavaScript方向更改事件,如下所示: 2014年1

  • ...Spring implements a controller in a very abstract way, which enables you to create a wide variety of controllers. 控制器作为应用程序逻辑的处理入口,它会负责去调用你已经实现的一些服务。通常,一个控制器会接收并解析用户的请求,然后把它转换成一个模型交给视图,由视图渲染出页面最终呈现

  • 问题内容: 引用的SO是一个非常有用的问题,答案非常有用。但是,这之后我剩下的问题是:如何对模态实例控制器进行单元测试?在引用的SO中,测试了调用控制器,但模拟了模态实例控制器。可以说后者也应该进行测试,但是事实证明这非常棘手。原因如下: 我将在此处从引用的SO复制相同的示例: 因此,我首先想到的是,我将直接在测试中实例化该控制器,就像在测试中的其他任何控制器一样: 这不起作用,因为在这种情况下,