日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Carsim Simulink自动驾驶仿真】基于MPC的轨迹跟踪控制

發(fā)布時間:2023/12/29 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Carsim Simulink自动驾驶仿真】基于MPC的轨迹跟踪控制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

如果對Carsim的基礎(chǔ)使用還不了解,可以參考:【Carsim Simulink自動駕駛仿真】基于MPC的速度控制
如果對MPC算法原理不清楚,可以參考:如何理解MPC模型預(yù)測控制理論
項目介紹:
教程為北理工的無人駕駛車輛模型預(yù)測控制第2版。所用的仿真軟件為Carsim2020.0和MatlabR2021a。使用MPC控制思想對車輛進行軌跡跟蹤控制,并給出仿真結(jié)果。

整整弄了兩天,踩了無數(shù)的坑,所以篇幅比較大,如果還有什么其他問題,歡迎一起討論。

從網(wǎng)上下載下來的代碼運行不了,所以本文的代碼是經(jīng)過修改和調(diào)試的。

基于MPC的軌跡跟蹤控制

  • 效果圖
    • 直線跟蹤
      • 3m/s
      • 5m/s
      • 10m/s
    • 圓跟蹤
      • 3m/s
      • 5m/s
      • 10m/s
  • MATLAB框架搭建
  • 代碼的數(shù)學(xué)遺漏問題與修改
    • 運動學(xué)模型少L
    • 改寫之后的目標函數(shù)線性項少系數(shù)
  • 代碼中的其他問題及討論
    • 輸入維度不匹配的情況
    • 索引超出數(shù)組范圍
      • 1.變量的范圍
      • 2.換一個求解器
      • 3.初始值全部設(shè)為0
      • 4.對于kesi(4)和kesi(5)的賦值 (這個是我的問題)
        • 一些理解
  • 參數(shù)的選取
  • 速度問題
  • 附錄:全代碼(修改過后的)

效果圖

因為參數(shù)經(jīng)過了調(diào)整,所以效果上和書上不一樣。

直線跟蹤


圖像為:路徑,速度,誤差和前輪偏角

前輪偏角的局部放大圖為:

3m/s

5m/s

10m/s


速度的具體圖像為:

圓跟蹤


圖像為:路徑,速度和前輪偏角(誤差不知道該在Carsim中怎么畫,知道的大佬請私信,嗚嗚嗚):

軌跡放大之后:

前輪偏角為:

前輪偏角放大之后:

3m/s


速度為:

5m/s


速度為:

10m/s


速度為:

MATLAB框架搭建

書中給出的MATLAB框架如下:

因為對于這種方法輸出需要再另外處理。所以我這里直接將速度乘3.6,角度也在程序中直接處理了。對應(yīng)的框架圖為:

代碼的數(shù)學(xué)遺漏問題與修改

書中的代碼和下載下來的代碼不一樣,所以還是檢查一下這兩個地方,

運動學(xué)模型少L

在書中,推導(dǎo)運動學(xué)模型的時候,最后一個數(shù)字分母是有一個l的:

但是在代碼中,這個地方少了,需要加上。

改寫之后的目標函數(shù)線性項少系數(shù)


這里的2在書中沒有少,但是下載下來的代碼中沒有這個系數(shù)。如果沒有的可以加一下。

代碼中的其他問題及討論

輸入維度不匹配的情況

看一下S-Function的輸入是3個還是5個,輸出是2個還是直接給出5個,對應(yīng)的代碼中也應(yīng)該和其一樣。具體在S-Function中是初始化的第一個函數(shù)中的:

sizes.NumOutputs =5;%[speed,steering]sizes.NumInputs =3;

索引超出數(shù)組范圍

這個是我的主要問題,之所以報錯,是因為求解器求解不出來優(yōu)化問題,方法的話我找了一些,然后自己也試了一些:

1.變量的范圍

這里有兩種情況:

  • 第一種情況是檢查變量范圍delta_umin=[-0.05;-0.0082;];如果當中的-0.05是0.05,將其加一個負號。
  • 第二種情況其實擴大變量的范圍可以求解,但是這里不建議,如果你在擴大范圍之后可以求解,那么建議還是將其變回原來的數(shù),更改其他值。

2.換一個求解器

使用interior-point-convex,而不是active-set

%options = optimset('Algorithm','active-set'); options = optimset('Algorithm','interior-point-convex');

3.初始值全部設(shè)為0

檢查初始化函數(shù)mdlInitializeSizes中的x0和U是否都為零。注意,這里的U表示的就是控制量與參考控制的差值。

function [sys,x0,str,ts] = mdlInitializeSizes %找到以下兩個值 x0 = [0;0;0]; U=[0;0];

4.對于kesi(4)和kesi(5)的賦值 (這個是我的問題)

這個我認為爭議比較大,但是改了之后確實沒有報錯了。
先說一下,按照理論:

kesi(4)和kesi(5)就是這里的控制變量u~\tilde{u}u~。而這個u~\tilde{u}u~根據(jù)定義是:

當前速度與參考速度的插值,所以這里我們應(yīng)該將Carsim中的5個變量全部輸入到S-Funciton中,然后進行如下操作:

U(1) = u(4)/3.6 - vd1;steer_SW = u(5)*pi/180;steering_angle = steer_SW/18;U(2) = steering_angle - vd2;kesi(4)=U(1); % vel-vel_refkesi(5)=U(2); % steer_angle - steering_ref

之前我從來沒有懷疑過這里,直到我看到書中的代碼和網(wǎng)上下載的不一樣的時候,我就嘗試了一下書上的代碼,即將前四行全部注釋掉:

% U(1) = u(4)/3.6 - vd1; % steer_SW = u(5)*pi/180; % steering_angle = steer_SW/18; % U(2) = steering_angle - vd2;kesi(4)=U(1); % vel-vel_refkesi(5)=U(2); % steer_angle - steering_ref

這樣改之后我的代碼就不會出現(xiàn)問題了。

一些理解

首先我們要清楚,kesi(4,5)是控制減去參考控制,求解器解出來的X是前后兩次的控制差值。
我們先看能跑對的程序,大致過程可以簡化成設(shè)置值,求解,給出輸出三步:

U = [0,0] for 循環(huán): #第一步:設(shè)置kesikesi(4)=U(1); % vel-vel_refkesi(5)=U(2); % steer_angle - steering_ref #第二步:求解[X,~,~]=quadprog(H,f,A_cons,b_cons,[],[],lb,ub,[],options); #第三步:給出輸出u_dot(1)=X(1);u_dot(2)=X(2);U(1)=kesi(4)+u_dot(1);%用于存儲上一個時刻的控制量U(2)=kesi(5)+u_dot(2);u_real(1) = U(1) + vd1;u_real(2) = U(2) + vd2;

這里列一個表格:

時間求解之前的U,也就是上一步的Ukesiu_dot求解之后的U輸出
k-1uk?1?uk?1refu_{k-1}-u_{k-1}^{ref}uk?1??uk?1ref?uk?1?uk?1refu_{k-1}-u_{k-1}^{ref}uk?1??uk?1ref?uk?ukref?uk?1+uk?1refu_k-u_{k}^{ref}-u_{k-1}+u_{k-1}^{ref}uk??ukref??uk?1?+uk?1ref?uk?1?uk?1ref+uk?ukref?uk?1+uk?1ref=uk?ukrefu_{k-1}-u_{k-1}^{ref}+u_k-u_{k}^{ref}-u_{k-1}+u_{k-1}^{ref}=u_k-u_{k}^{ref}uk?1??uk?1ref?+uk??ukref??uk?1?+uk?1ref?=uk??ukref?u_k
之后就可以征程循環(huán)。注意這里的初始值設(shè)置為[0,0]是合理的。

我出錯的程序:

U = [0,0] for 循環(huán): #第一步:設(shè)置kesiU(1) = u(4)/3.6 - vd1;steer_SW = u(5)*pi/180;steering_angle = steer_SW/18;U(2) = steering_angle - vd2;kesi(4)=U(1); % vel-vel_refkesi(5)=U(2); % steer_angle - steering_ref #第二步:求解[X,~,~]=quadprog(H,f,A_cons,b_cons,[],[],lb,ub,[],options); #第三步:給出輸出u_dot(1)=X(1);u_dot(2)=X(2);U(1)=kesi(4)+u_dot(1);%用于存儲上一個時刻的控制量U(2)=kesi(5)+u_dot(2);u_real(1) = U(1) + vd1;u_real(2) = U(2) + vd2;

建立同樣的表格,這里唯一不一樣的是,之前的輸入其實是記憶到了程序里面,這里的輸入變成了從程序中獲取:

時間求解之前的U,也就是上一步的Ukesiu_dot求解之后的U輸出
k-1uk?1input?uk?1refu_{k-1}^{input}-u_{k-1}^{ref}uk?1input??uk?1ref?uk?1input?uk?1refu_{k-1}^{input}-u_{k-1}^{ref}uk?1input??uk?1ref?uk?ukref?uk?1input+uk?1refu_k-u_{k}^{ref}-u_{k-1}^{input}+u_{k-1}^{ref}uk??ukref??uk?1input?+uk?1ref?uk?ukrefu_k-u_{k}^{ref}uk??ukref?u_k
kukinput?ukrefu_{k}^{input}-u_{k}^{ref}ukinput??ukref?
但是按照道理來說,這個和上一個表格是一樣的,這里不一樣的是速度輸入之后需要進行變換,輸出的時候也要進行變換,這變換之后會存在的誤差比較大。還有一種可能,這里其實輸入進來的是速度和方向盤轉(zhuǎn)角,這個方向盤轉(zhuǎn)角和輪胎轉(zhuǎn)角之間有一個系數(shù),這個系數(shù)這里設(shè)置的18,但是具體設(shè)置多少,也沒有具體的深究。
總之我個人感覺可能是上一時刻的輸出uku_kuk?和這一時刻的輸入ukinputu_k^{input}ukinput?可能不一樣。希望各位大佬也給出一些解釋。

參數(shù)的選取

參數(shù)這里有4個,預(yù)測步長,控制步長,Q和R。這里Q和R都是對角陣,表格中的數(shù)值是對角陣中的數(shù),而不是Q和R的實際值。
這里我的參數(shù)為:

預(yù)測步長(NpN_pNp?)控制步長(N_c)QR
100301100

我先調(diào)整的Q和R,當軌跡不貼合的時候,調(diào)大Q,當速度收斂太慢,震蕩太久的時候調(diào)整R。根據(jù)我的經(jīng)驗Q取1就好,之后就根據(jù)速度圖像的震蕩和你的評判標準進行選擇就好。
對于預(yù)測步長和控制步長,預(yù)測的越久,說明這個智能體越有遠見,超調(diào)就會相對小一點,個人感覺控制步長太多不是什么好的事情,因為本身希望汽車進行相對較少的控制。

速度問題

這里有一個小問題,書中的速度在初始時刻是沒有減速的:

而在我做的過程中,速度在一開始都有減少:

這里我找到了問題,是兩個前輪的速度在一開始不一樣,但是按照道理,輸入都是一樣的,出現(xiàn)這樣的差異不知道怎么解決。

附錄:全代碼(修改過后的)

function [sys,x0,str,ts] = MPCtracking(t,x,u,flag)%控制量為速度和前輪偏角,模型是用運動學(xué)模型switch flagcase 0[sys,x0,str,ts]=mdlInitializeSizes;case 2sys = mdlUpdates(t,x,u);case 3sys = mdlOutputs(t,x,u);case {1,4,9}sys = [];otherwiseerror(['unhandled flag =', num2str(flag)])end %End of MPCtracking%============================================================== % 初始化 %============================================================== function [sys,x0,str,ts] = mdlInitializeSizessizes = simsizes;sizes.NumContStates =0;sizes.NumDiscStates =3;sizes.NumOutputs =5;%[speed,steering]sizes.NumInputs =3;sizes.DirFeedthrough =1;sizes.NumSampleTimes =1;sys = simsizes(sizes);x0 = [0;0;0];global U;%存儲目前的控制變量[vel,delta]U=[0;0];str = [];ts = [0.05,0]; %采樣時間:[period,offset] %End of mdlInitializeSizes%============================================================== % 更新離散狀態(tài) %============================================================== function sys = mdlUpdates(t,x,u)sys = x; %End of mdlUpdate.%============================================================== % 計算輸出,核心輸出 %============================================================== function sys = mdlOutputs(t,x,u)global a b u_dot;global U;global kesi;ticNx = 3;%狀態(tài)量的個數(shù)Nu = 2;%控制量的個數(shù)Np = 100;%預(yù)測步長Nc = 30;%控制步長Row = 10; %松弛因子yaw_angle =u(3)*pi/180;%CarSim輸出的Yaw angle為角度,角度轉(zhuǎn)換為弧度%================================================== %最后調(diào)參 %==================================================u_bound1 = 0.2;u_bound2 = 0.436;delta1 = 0.05;delta2 = 0.0082;Q_a = 1;R_a = 100; %================================================== %構(gòu)建路徑 %================================================== % %直線路徑 % vd1 = 10;%ref_velocity % vd2 = 0;%ref_steering % r(1)=vd1*t; %ref_x % r(2)=5;%ref_y % r(3)=0;%ref_heading_angle% %半徑為35m的圓形軌跡, 圓心為(0, 35), 速度為3m/s % r(1)=25*sin(0.12*t); % r(2)=25+10-25*cos(0.12*t); % r(3)=0.12*t; % vd1=3; % vd2=0.104;%半徑為25m的圓形軌跡, 圓心為(0, 35), 速度為10m/sr(1)=25*sin(0.4*t);r(2)=25+10-25*cos(0.4*t);r(3)=0.4*t;vd1=10;vd2=0.104; % %半徑為25m的圓形軌跡, 圓心為(0, 35), 速度為5m/s % r(1)=25*sin(0.2*t); % r(2)=25+10-25*cos(0.2*t); % r(3)=0.2*t; % vd1=5; % vd2=0.104; %================================================== %構(gòu)建結(jié)束 %==================================================%添加轉(zhuǎn)化后的自變量kesikesi=zeros(Nx+Nu,1);kesi(1) = u(1)-r(1);%u(1)==X(1),x_offsetkesi(2) = u(2)-r(2);%u(2)==X(2),y_offsetheading_offset = yaw_angle - r(3); %u(3)==X(3),heading_angle_offsetif (heading_offset < -pi)heading_offset = heading_offset + 2*pi;endif (heading_offset > pi)heading_offset = heading_offset - 2*pi;endkesi(3)=heading_offset;% U(1) = u(4)/3.6 - vd1; % steer_SW = u(5)*pi/180; % steering_angle = steer_SW/18; % U(2) = steering_angle - vd2;kesi(4)=U(1); % vel-vel_refkesi(5)=U(2); % steer_angle - steering_refT = 0.05;L = 2.6;%輪間距%矩陣初始化t_d = r(3);%系數(shù)Q = Q_a*eye(Nx*Np,Nx*Np); % Q(Nx*Np,Nx*Np) = Q_a*0.01;R = R_a*eye(Nu*Nc);%運動學(xué)方程u_dot = zeros(Nx,1);%%%%這里應(yīng)該沒有xa = [1 0 -vd1*sin(t_d)*T;0 1 vd1*cos(t_d)*T;0 0 1;];b = [cos(t_d)*T 0;sin(t_d)*T 0;tan(vd2)*T/L vd1*T/(L*(cos(vd2))^2);];%構(gòu)建新的狀態(tài)空間A_cell=cell(2,2);B_cell=cell(2,1);A_cell{1,1}=a;A_cell{1,2}=b;A_cell{2,1}=zeros(Nu,Nx);A_cell{2,2}=eye(Nu);B_cell{1,1}=b;B_cell{2,1}=eye(Nu);A=cell2mat(A_cell);B=cell2mat(B_cell);C=[ 1 0 0 0 0;0 1 0 0 0;0 0 1 0 0];PHI_cell=cell(Np,1);THETA_cell=cell(Np,Nc);for j=1:1:NpPHI_cell{j,1}=C*A^j;for k=1:1:Ncif k<=jTHETA_cell{j,k}=C*A^(j-k)*B;else THETA_cell{j,k}=zeros(Nx,Nu);endendendPHI=cell2mat(PHI_cell);%size(PHI)=[Nx*Np Nx+Nu]THETA=cell2mat(THETA_cell);%size(THETA)=[Nx*Np Nu*(Nc+1)]H_cell=cell(2,2);H_cell{1,1}=THETA'*Q*THETA+R;H_cell{1,2}=zeros(Nu*Nc,1);H_cell{2,1}=zeros(1,Nu*Nc);H_cell{2,2}=Row;H=cell2mat(H_cell); % H=(H+H')/2;error=PHI*kesi;f_cell=cell(1,2);f_cell{1,1} = 2*(error'*Q*THETA);f_cell{1,2} = 0;f=cell2mat(f_cell);%% 以下為約束生成區(qū)域%不等式約束A_t=zeros(Nc,Nc);%見falcone論文 P181for p=1:1:Ncfor q=1:1:Ncif q<=p A_t(p,q)=1;else A_t(p,q)=0;endend end A_I=kron(A_t,eye(Nu));%對應(yīng)于falcone論文約束處理的矩陣A,求克羅內(nèi)克積Ut=kron(ones(Nc,1), U);%umin=[-u_bound1; -u_bound2];%[min_vel, min_steer]維數(shù)與控制變量的個數(shù)相同umax=[u_bound1; u_bound2]; %[max_vel, max_steer],%0.436rad = 25degdelta_umin = [-delta1; -delta2]; % 0.0082rad = 0.47degdelta_umax = [delta1; delta2];Umin=kron(ones(Nc,1),umin);Umax=kron(ones(Nc,1),umax);A_cons_cell={A_I zeros(Nu*Nc, 1); -A_I zeros(Nu*Nc, 1)};b_cons_cell={Umax-Ut;-Umin+Ut};A_cons=cell2mat(A_cons_cell);%(求解方程)狀態(tài)量不等式約束增益矩陣,轉(zhuǎn)換為絕對值的取值范圍b_cons=cell2mat(b_cons_cell);%(求解方程)狀態(tài)量不等式約束的取值% 狀態(tài)量約束delta_Umin = kron(ones(Nc,1),delta_umin);delta_Umax = kron(ones(Nc,1),delta_umax);lb = [delta_Umin; 0];%(求解方程)狀態(tài)量下界ub = [delta_Umax; 10];%(求解方程)狀態(tài)量上界%嘗試初始值%x0 = zeros(Nc*Nu+1,1);%% 開始求解過程%options = optimset('Algorithm','active-set');options = optimset('Algorithm','interior-point-convex'); warning off all % close the warnings during computation [X,~,~]=quadprog(H,f,A_cons,b_cons,[],[],lb,ub,[],options);%% 計算輸出 u_dot(1)=X(1);u_dot(2)=X(2);U(1)=kesi(4)+u_dot(1);%用于存儲上一個時刻的控制量U(2)=kesi(5)+u_dot(2);u_real(1) = U(1) + vd1;u_real(2) = U(2) + vd2;sys= [u_real(1)*3.6; u_real(2)*180/pi; u_real(2)*180/pi;0;0]; % vel, steering, x, ytoc% End of mdlOutputs.

總結(jié)

以上是生活随笔為你收集整理的【Carsim Simulink自动驾驶仿真】基于MPC的轨迹跟踪控制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。