【自动驾驶】控制算法(八)横向控制Ⅰ | 算法与流程
写在前面:
🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝
个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。
🔍 本文系 清流君 原创之作,荣幸在CSDN首发🐒
若您觉得内容有价值,还请评论告知一声,以便更多人受益。
转载请注明出处,尊重原创,从我做起。
👍 点赞、评论、收藏,三连走一波,让我们一起养成好习惯😜
在这里,您将收获的不只是技术干货,还有思维的火花!
📚 系列专栏:【运动控制】系列,带您深入浅出,领略控制之美。🖊
愿我的分享能为您带来启迪,如有不足,敬请指正,让我们共同学习,交流进步!
🎭 人生如戏,我们并非能选择舞台和剧本,但我们可以选择如何演绎 🌟
感谢您的支持与关注,让我们一起在知识的海洋中砥砺前行~~~
文章目录
- 引言
- 一、算法输入与输出
- 1、算法输入
- 2、算法输出
- 二、算法流程
- 1、算法过程概述
- 2、算法流程图
- 三、具体算法
- 1、AB 计算模块
- 2、LQR模块
- (1)急加速
- (2)急速过弯
- 3、误差与曲率计算模块
- (1)规划点
- (2)匹配点
- (3)方向向量
- (4)误差的距离的向量
- (5)横向误差
- (6)纵向误差
- (7)投影点切线方向与x轴夹角
- (8)横向误差导数
- (9)航向角误差
- (10)弧速度
- (11)横摆角速度误差
- (12)投影点曲率
- (13)输出
- 4、前馈控制计算模块
- 5、最终控制计算模块
- 四、预测模块
- 1、预测模块的重要性
- 2、预测模块算法
- 五、完整算法流程图
- 六、总结
- 参考资料
引言
本篇博客是 自动驾驶控制算法 系列的第八节第Ⅰ部分。内容整理自 B站知名up主 忠厚老实的老王 的视频,作为博主的学习笔记,分享给大家共同学习。
本节内容是整个横向控制的核心,要把前七节所有内容都用在第八节上。第八节分四小节,本小节讲解具体算法,下一小节讲解模型搭建和代码编程,再下一小节讲解代码优化、注意事项以及仿真结果。
算法这一讲可以说是整个第八节的核心所在。写代码、做仿真的来源是算法,有了具体算法后,无论用什么平台仿真,用什么语言编写程序,都是水到渠成的事情。只要照着算法编程逻辑是十分清晰的,因为算法已经把逻辑梳理好了,只要照着算法编就可以了。
相反如果没有写过算法,然后就直接就去编程也可以,但只针对较简单的项目、简单的算法。对于复杂算法,建议各位先把算法写好,把逻辑理清楚,然后再编程。
本篇博客讲解横向控制算法,前面讲到的控制律:
u = − k e r r + δ f u=-ke_{rr}+\delta _f u=−kerr+δf其中, k = l q r ( A , B , Q , R ) {{k}=\mathrm{lqr}(A,B,Q,R)} k=lqr(A,B,Q,R) 或 d l q r ( A ˉ , B ˉ , Q , R ) {{\mathrm{dlqr}(\bar{A},\bar{B},Q,R)}} dlqr(Aˉ,Bˉ,Q,R)的解。
关于这些量的计算:
- A 、 B A、B A、B 的计算在第三节和第四节
- k k k 的计算在第五节
- e r r e_{rr} err 的计算在第四节和第七节
- δ f \delta_f δf 的计算在第六节
第四节讲的是连续规划轨迹的误差计算,第七节是讲的是离散规划轨迹的误差计算。
将前七节所有的知识把综合起来,就变成了第八节,讲解横向控制的完整算法。横向控制很复杂,模块非常多,所以必须要把算法梳理一遍,不然很容易出错。
一、算法输入与输出
1、算法输入
根据前七讲,算法输入分为三类:
-
整车参数
轴距L、质心到前后轮的距离 a 、 b a、b a、b 、侧偏刚度 C α C_{\alpha} Cα、质量 m m m、转动惯量 I I I。 -
车辆位置与状态
包括车辆的 ( x , y , φ ) (x,y,\varphi) (x,y,φ) 以及它的速度 v x 、 v y v_x、v_y vx、vy ,横摆角速度 φ ˙ \dot \varphi φ˙。 -
规划轨迹点
轨迹点为四维数组,包含坐标 x r , y r x_r,y_r xr,yr 以及轨迹点的切线方向与 x 轴夹角 θ r \theta_r θr 以及轨迹点的曲率 κ r \kappa_r κr。
( x r y r θ r κ r ) = ( x 1 x 2 ⋯ y 1 y 2 ⋯ θ 1 θ 2 ⋯ κ 1 κ 2 ⋯ ) \left. \left( \begin{array}{c} x_r\\ y_r\\ \theta _r\\ \kappa _r\\ \end{array} \right. \right) =\left( \begin{matrix} x_1& x_2& \cdots\\ y_1& y_2& \cdots\\ \theta _1& \theta _2& \cdots\\ \kappa _1& \kappa _2& \cdots\\ \end{matrix} \right) xryrθrκr = x1y1θ1κ1x2y2θ2κ2⋯⋯⋯⋯
2、算法输出
算法输出为
u = − k e r r + δ f u=-ke_{rr}+\delta _f u=−kerr+δf
二、算法流程
1、算法过程概述
第一步:通过整车参数加上 v x v_x vx,可以算出 A 、 B A、B A、B,再设置权重矩阵 Q 、 R Q、R Q、R,通过 LQR 可得到反馈矩阵 k k k。
第二步:车辆的位置状态,加上规划轨迹点,可以算出误差 e r r e_{rr} err 以及投影曲率 κ \kappa κ ,即真实位置在轨迹点的投影曲率。
第三步:第一步得到反馈矩阵 k k k,以及第二步所得到的投影的曲率 κ \kappa κ,加上整车参数,再加 v x v_x vx,可得到前馈控制 δ f \delta_f δf。
第四步:第一步得到了 k k k 加上第二步得到的误差 e r r e_{rr} err,再加上第三步得到 δ f \delta_f δf,可以得到 u = − k e r r + δ f u=-ke_{rr}+\delta _f u=−kerr+δf
2、算法流程图
流程图可以直观地反映算法的结构,基本上流程画出来,算法逻辑顺序就理清楚了,流程图如下:

-
A 、 B A、B A、B 计算模块
首先是整车参数和 v x v_x vx 作为输入模块,输入进 A 、 B A、B A、B 计算模块,可算出 A 、 B A、B A、B -
LQR模块
把 A 、 B A、B A、B 算出来后,再输入 Q Q Q 和 R R R 进入 LQR 模块,就可算出最终的反馈矩阵 k k k。 -
误差曲率计算模块
接下来是车辆状态及速度,加上规划轨迹点以及 v x v_x vx 作为输入,这里把 v x v_x vx 单独拿出来,因为 v x v_x vx 在其他模块上也有用。作为输入之后输入进误差和 k k k 的计算模块,得到误差以及曲率 κ \kappa κ。 -
前馈控制计算模块
整车参数再加上 v x v_x vx 再加上 k k k 及 κ \kappa κ 输入前馈控制计算模块,可算出前馈控制 δ f \delta_f δf。 -
最终控制计算模块
最后将反馈矩阵 k k k 、前馈 δ f \delta_f δf 以及误差代入最终控制计算模块,可得到最后的控制量 u u u,
其中, A 、 B A、B A、B 计算模块、误差 e r r e_{rr} err、反馈矩阵 k k k 计算模块、前馈控制 δ f \delta_f δf 计算模块都用到 v x v_x vx ,将 v x v_x vx 连在一起,这样得到完整算法的流程图。
流程图包含了从第三节到第七节的所有内容,这就是后续编程的理论依据,以后写代码就是按照流程图来写。
可以看一下整个算法分为五个模块,写算法具体就是写这五个模块,模块写出来了,算法也就编写出来了。
三、具体算法
下面看一下这五个模块的算法到底该如何编写。
1、AB 计算模块
本模块最简单,代公式即可,因为 A 、 B A、B A、B 的具体表达式的在前面推导过:
A = ( 0 1 0 0 0 C α f + C α r m v x − C α f + C α r m a C α f − b C α r m v x 0 0 0 1 0 a C α f − b C α r I v x − a C α f − b C α r I a 2 C α f + b 2 C α r I v x ) A=\left( \begin{matrix} 0& 1& 0& 0\\ 0& \frac{C_{\alpha f}+C_{\alpha r}}{mv_x}& -\frac{C_{\alpha f}+C_{\alpha r}}{m}& \frac{aC_{\alpha f}-bC_{\alpha r}}{mv_x}\\ 0& 0& 0& 1\\ 0& \frac{aC_{\alpha f}-bC_{\alpha r}}{Iv_x}& -\frac{aC_{\alpha f}-bC_{\alpha r}}{I}& \frac{a^2C_{\alpha f}+b^2C_{\alpha r}}{Iv_x}\\ \end{matrix} \right) A= 00001mvxCαf+Cαr0IvxaCαf−bCαr0−mCαf+Cαr0−IaCαf−bCαr0mvxaCαf−bCαr1Ivxa2Cαf+b2Cαr B = ( 0 − C α f m 0 − a C α f I ) B=\left( \begin{array}{c} 0\\ -\frac{C_{\alpha f}}{m}\\ 0\\ -\frac{aC_{\alpha f}}{I}\\ \end{array} \right) B= 0−mCαf0−IaCαf 上式和车辆参数、 v x v_x vx 有关的矩阵,把车辆参数及 v x v_x vx 代入计算即可。
注意:要考虑当 v x = 0 v_x=0 vx=0 时的奇异性, A A A 中有无穷大出现,所以在编程时要考虑奇异性。
2、LQR模块
LQR 模块是最费时间的模块,需要解黎卡提方程,需要矩阵迭代。但是有小技巧可以加快 LQR 模块的计算。因为 LQR 只与 A 、 B 、 Q 、 R A、B、Q、R A、B、Q、R 有关,而 A 、 B A、B A、B 只与整车参数和 v x v_x vx 有关,整车参数可近似认为不变。
注意:整车参数只是近似认为不变,并不是一成不变。在某些情况下就是整车参数不能认为近似不变,必须要考虑整车参数变化所带来对 k k k 的影响。
在什么情况下不可近似处理呢?
(1)急加速
如果车辆在疯狂加速,即加速度非常大、非常猛时:

根据达朗贝尔原理,车辆有很大的惯性力,导致前后轮的垂向力发生变化。虽然前后轮的垂向力加起来等于车重,但分配不一样,不是轮子分别近似分配 1 / 4 1/ 4 1/4 ,可能前轮垂向力减小的非常多,而后轮垂向力会增大的非常多,垂向力的变化直接导致轮胎侧偏刚度发生变化,所以在加速特别猛时,不能把侧偏刚度看成常数,要考虑侧偏刚度的变化。
(2)急速过弯
非常急速的过弯时,整个车都倾斜起来:

此时车左右轮明显不对称,因为右轮几乎承受了车的全部重量,而左轮几乎没有承受任何力,导致自行车模型不再适用。
所有的理论都基于自行车模型,即把左右两个轮认为是一个轮,等于是把车压扁了,意味着自行车模型只适用于左右对称或是近似对称的情况。而在极速过弯情况下,不能认为左右轮对称。
在前急加速模型仍然可用自行车模型,因为左右两个轮对称,仅需考虑侧偏刚度变化带来对 k k k 的影响,而后面急速过弯就完全不可以用自行车模型,所以在路径规划时,要极力避免急速过弯的情况出现。因为急加速还可以调整,但如果是急速过弯的话,就完全没办法调整。
在汽车界一般认为侧向加速度就是超过 0.4 0.4 0.4 倍的重力加速度,即 a y > 0.4 g a_y>0.4g ay>0.4g,就属于急速过弯。
回到模块上来,如果认为整车参数近似不变,那么 A 、 B A、B A、B 只与 v x v_x vx 有关。
k = l q r ( A , B , Q , R ) {{k}=\mathrm{lqr}(A,B,Q,R)} k=lqr(A,B,Q,R) 或 d l q r ( A ˉ , B ˉ , Q , R ) {{\mathrm{dlqr}(\bar{A},\bar{B},Q,R)}} dlqr(Aˉ,Bˉ,Q,R),这样每个 v x v_x vx 都有唯一的 k k k 与之对应。
因此,可离线算出 v x v_x vx 与 k k k 的对应表,实际应用中不需要求解黎卡提方程,直接查表即可。
比如有如下形式的对应表:
| v x v_x vx | k k k |
|---|---|
| 0.01 | k 1 k_1 k1 |
| 0.02 | k 2 k_2 k2 |
| 0.03 | k 3 k_3 k3 |
| … | … |
| 50 | k n k_n kn |
反映了 v x v_x vx 与 k k k 的对应关系。这样测出 v x v_x vx 后,直接查表查出 k k k,这就是用离线查表法计算 LQR。
查表法计算 LQR 的优缺点如下:
- 优点
大大加快计算速度 - 缺点
耗费存储空间
这是典型为了加快程序运算速度而采用空间换时间的算法,通过查表法算, LQR 可以把速度提升好几个数量级,特别是在控制中,对实时性的要求是最高的,这就意味着必须要尽一切可能加快程序运算速度。
一般在实际应用中的 LQR 不是通过调包计算的,而是查表查出来的。而且查表法算LQR 对高速运动的控制也有效果,因为高速和低速的区别就在于侧偏刚度变化,其他变化不大。
在这种情况下, k k k 就和 v x v_x vx 以及侧偏刚度 C α C_\alpha Cα 有关,就是从一维表格变成三维表格。可以把速度以及侧偏刚度输进去,查 k k k 出来,一样可以达到控制效果,而且高速对控制性的实时性要求更高,因为低速控制实时性不高的话,危险性不大。但高速情况下的控制,若实时性不够会很容易发生事故。
3、误差与曲率计算模块
该模块是整个算法的核心。
(1)规划点
首先要有规划轨迹,就是一系列的四维数组点:
( x r y r θ r κ r ) = ( x 1 x 2 ⋯ y 1 y 2 ⋯ θ 1 θ 2 ⋯ κ 1 κ 2 ⋯ ) \left. \left( \begin{array}{c} x_r\\ y_r\\ \theta _r\\ \kappa _r\\ \end{array} \right. \right) =\left( \begin{matrix} x_1& x_2& \cdots\\ y_1& y_2& \cdots\\ \theta _1& \theta _2& \cdots\\ \kappa _1& \kappa _2& \cdots\\ \end{matrix} \right) xryrθrκr = x1y1θ1κ1x2y2θ2κ2⋯⋯⋯⋯
(2)匹配点
遍历 ( x R , y r ) (x_R,y_r) (xR,yr) 找到与 ( x , y ) (x,y) (x,y) 最近的规划点的序列号,记为 d m i n d_{min} dmin。
【序列号】是距离最短的点的下标序列,遍历所有规划点,比如找到第四个规划点距离车辆当前位置 ( x , y ) (x,y) (x,y) 最近,那么 d m i n = 4 d_{min}=4 dmin=4。最短距离的点叫做匹配点, d m i n d_{min} dmin 就是匹配点的序列号。
(3)方向向量
写出匹配点的切线方向量 τ ⃗ \vec{\tau} τ 与法线方向量 n ⃗ \vec{n} n:
τ ⃗ = ( cos ( θ d min ) sin ( θ d min ) ) n ⃗ = ( − sin ( θ d min ) cos ( θ d min ) ) \vec{\tau}=\left( \begin{array}{c} \cos \left( \theta _{d_{\min}} \right)\\ \sin \left( \theta _{d_{\min}} \right)\\ \end{array} \right) \quad \vec{n}=\left( \begin{array}{c} -\sin \left( \theta _{d_{\min}} \right)\\ \cos \left( \theta _{d_{\min}} \right)\\ \end{array} \right) τ=(cos(θdmin)sin(θdmin))n=(−sin(θdmin)cos(θdmin))
(4)误差的距离的向量
误差的距离的向量 d − e ⃗ r r d_-\vec{e}_{rr} d−err:
d − e ⃗ r r = ( x − x d m i n y − y d m i n ) d_-\vec{e}_{rr}=\left( \begin{array}{c} x-x_{d_{min}}\\ y-y_{d_{min}}\\ \end{array} \right) d−err=(x−xdminy−ydmin) 实际上就是两个向量的减法,第一个向量是车辆真实位矢向量,第二个向量是匹配点的位矢向量,这两个相减就是误差的距离向量,对应的就是第七节的 x ⃗ − x ⃗ m \vec{x}-\vec{x}_m x−xm。
(5)横向误差
e d = n ⃗ T ⋅ d − e ⃗ r r e_d=\vec{n}^{T}\cdot d_{-}\vec{e}_{\mathrm{rr}} ed=nT⋅d−err
(6)纵向误差
e s = τ ⃗ T ⋅ d − e ⃗ r r e_s=\vec{\tau}^T\cdot d_-\vec{e}_{rr} es=τT⋅d−err
(7)投影点切线方向与x轴夹角
计算 θ r \theta_r θr,即投影点切线方向与 x x x 轴夹角,因为匹配点不等于投影点,所以还要进行相应的运算:
θ r = θ d min + κ d min ⋅ e s \theta _r=\theta _{d_{\min}}+\kappa_{d_{\min}}\cdot e_s θr=θdmin+κdmin⋅es
(8)横向误差导数
e ˙ d = ∣ v ⃗ ∣ sin ( θ − θ r ) = v y cos ( φ − θ r ) + v x sin ( φ − θ r ) \dot{e}_d=|\vec{v}|\sin \left( \theta -\theta _r \right) =v_y\cos \left( \varphi -\theta _r \right) +v_x\sin \left( \varphi -\theta _r \right) e˙d=∣v∣sin(θ−θr)=vycos(φ−θr)+vxsin(φ−θr)
(9)航向角误差
e φ = φ − θ r e_{\varphi}=\varphi-\theta_r eφ=φ−θr
(10)弧速度
s ˙ = v cos ( θ − θ r ) 1 − κ d m i n ⋅ e d = v x cos ( φ − θ r ) − v y sin ( φ − θ r ) 1 − κ d min e d \dot{s}=\frac{v\cos \left( \theta -\theta _r \right)}{1-\kappa _{d_{min}}\cdot e_d}=\frac{v_x\cos \left( \varphi -\theta _r \right) -v_y\sin \left( \varphi -\theta _r \right)}{1-\kappa_{d_{\min}}e_d} s˙=1−κdmin⋅edvcos(θ−θr)=1−κdminedvxcos(φ−θr)−vysin(φ−θr)
(11)横摆角速度误差
e ˙ φ = φ ˙ − κ d min ⋅ s ˙ \dot{e}_{\varphi}=\dot{\varphi}-\kappa_{\text{d}_{\min}}\cdot \dot{s} e˙φ=φ˙−κdmin⋅s˙
(12)投影点曲率
κ r = κ d min \kappa _r=\kappa _{\text{d}_{\min}} κr=κdmin
(13)输出
第三个模块的算法是整个控制算法中最复杂的,这一块涉及到的公式很多,而且很容易出问题。
为了得到 LQR 的 A A A 和 B B B,做了一系列假设,其中假设 e φ e_\varphi eφ 比较小,所以 sin e φ = e φ \sin e_\varphi=e_\varphi sineφ=eφ,以及 cos e φ \cos e_\varphi coseφ近似认为是1,然后才能得到 A A A 和 B B B 的具体的表达式。
但第九步 e φ = φ − θ r e_{\varphi}=\varphi-\theta_r eφ=φ−θr 有问题,角度具有多值性,即 φ + 2 π \varphi + 2\pi φ+2π,还是原来角度,但从 e φ e_\varphi eφ 的角度上来说, φ + 2 π \varphi + 2\pi φ+2π 就不是小角度了,包括 θ r \theta_r θr 也一样, θ r = 0 \theta_r=0 θr=0 和 θ r = 2 π \theta_r=2 \pi θr=2π 实际上是同一个角度,但如果用 e φ = φ − θ r e_{\varphi}=\varphi-\theta_r eφ=φ−θr,可能导致 e φ e_{\varphi} eφ 很大。
最终控制 u = − k e r r + δ f u=-ke_{rr}+\delta _f u=−kerr+δf ,误差 e r r = ( e d , e ˙ d , e φ , e ˙ φ ) T e_{rr}=\left( e_d,\dot{e}_d,e_{\varphi},\dot{e}_{\varphi} \right) ^T err=(ed,e˙d,eφ,e˙φ)T ,最终控制中的 u u u 和 e φ e_{\varphi} eφ 有关系,这样可能导致 e φ e_{\varphi} eφ 在短时间内突变成多 2 π 2\pi 2π,导致控制量 u u u 在短时间内突变,进而导致控制失效。
所以第九步最容易出错,在具体写代码时注意避免。
4、前馈控制计算模块
k 3 = k ( 3 ) k_{3}=k(3) k3=k(3) δ f = κ [ a + b − b k 3 − m v x 2 a + b ( b C α f + a C α r k 3 − a C α r ) ] \delta _f=\kappa\left[ a+b-bk_3-\frac{mv_{x}^{2}}{a+b}\left( \frac{b}{C_{\alpha f}}+\frac{a}{C_{\alpha r}}k_3-\frac{a}{C_{\alpha r}} \right) \right] δf=κ[a+b−bk3−a+bmvx2(Cαfb+Cαrak3−Cαra)]
5、最终控制计算模块
δ = − k e r r + δ f \delta =-ke_{rr}+\delta _f δ=−kerr+δf 这样关于横线控制五个模块的算法都已经讲完了。
只要写好这五个模块,通过流程图把这五个模块拼起来,就可以得到最终控制量 u u u。
四、预测模块
但这样还不够,因为这五个模块只是前七节讲到的内容,为了更好地体现算法性能,还要再加预测模块。
1、预测模块的重要性
为什么要加预测模块?
首先因为车本身具有惯性,导致控制天生有滞后性。为了解决这个问题,要进行提前控制,加入预测模块。
这里具体解释一下。比如有一段规划轨迹:

如果是人开车,看到这样一条路径规划,会不会去打方向盘?应该不会,因为人具有预见性,能看到未来路径到底长什么样。虽然现在的状态和规划路径有误差,但是如果保持当前状态行驶,在未来一段时间内,车和规划路径就没有误差了。所以人不会打方向盘,因为人能知道未来的路径规划是什么。
但算法不行,算法开车只会机械地寻找与真实位置最接近的规划轨迹点。如果算出误差不等于0,那么算法就会打方向盘。
下面的例子也说明了同样的道理:

人开车的话,知道未来的路径规划不是直线,所以即使现在的运动状态和规划的轨迹完全贴合,没有误差,人也会提前动方向盘。
但算法开车只看此时误差为 0 0 0,算法不会动方向盘,只在匀速直线运行到下一时刻时,发现此时误差不等于 0 0 0,才会动方向盘。所以算法控制具有一定的滞后性,看不到未来的路径规划,只关心哪个轨迹点与真实位置最近。
所以要加上预测模块,为了更好地控制,算法需要具有一定的预见性。
预测就是在车辆当前状态下,假设车辆在一段时间内做匀速直线运动,运动后的点就是预测点。比如说下面这样:

红色点为预测点,如果没有预测,算法很明显和轨迹有误差 d d d,所以 d d d 不等于 0 0 0, u u u 就不等于 0 0 0,算法就会打方向盘。
但是如果做了预测,其实就是求预测点和轨迹之间的误差。预测点和轨迹贴在一起,没有误差,就意味着 x p r e x_{pre} xpre 和轨迹重合, u = 0 u=0 u=0,所以就不打方向盘,这时算法就具有预见性。
对于上面提到的第二种情况也一样,比如预测点在这本来用原本真实点计算误差,那就是 0 0 0,现在用预测点和规划点计算误差,此时误差不等于 0 0 0,所以打方向盘。
2、预测模块算法
下面编写具体的预测算法,比如下图的直角坐标系:

车辆速度为 v v v,与 x x x 轴夹角为 θ \theta θ,预测时间记为 t s t_s ts,假设在预测时间内,车辆做匀速直线运动,那么前视距离为 v t s vt_s vts。若有加速度信号,则前视距离为 v t s + 1 2 a t s 2 vt_s+\frac{1}{2}at_{s}^{2} vts+21ats2。
预测点的信息记为 ( x p r e , y p r e , φ p r e , v x p r e , v y p r e , φ ˙ p r e ) ( x_{pre},y_{pre},\varphi _{pre},v_{xpre},v_{ypre},\dot{\varphi}_{pre}) (xpre,ypre,φpre,vxpre,vypre,φ˙pre)
根据几何关系有:
x p r e = x + v t s cos θ = x + v t s cos ( β + φ ) = x + v x t s cos φ + v y t s sin φ y p r e = y + v t s sin θ = y + v y t s cos φ + v x t s sin φ φ p r e = φ + φ ˙ t s v x p r e = v x v y pre = v y φ ˙ pre = φ ˙ \begin{aligned} x_{pre}&=x+vt_s\cos \theta =x+vt_s\cos \left( \beta +\varphi \right) =x+v_xt_s\cos \varphi +v_yt_s\sin \varphi\\ y_{pre}&=y+vt_s\sin \theta =y+v_yt_s\cos \varphi +v_xt_s\sin \varphi\\ \varphi _{pre}&=\varphi +\dot{\varphi}t_s\\ v_{xpre}&=v_x\\ v_{y\text{pre}}&=v_y\\ \dot{\varphi}_{\text{pre}}&=\dot{\varphi}\\ \end{aligned} xpreypreφprevxprevypreφ˙pre=x+vtscosθ=x+vtscos(β+φ)=x+vxtscosφ+vytssinφ=y+vtssinθ=y+vytscosφ+vxtssinφ=φ+φ˙ts=vx=vy=φ˙ 这就是预测模块的完整算法。
五、完整算法流程图
加入预测模块后的算法流程图:

六、总结
本来是真实的 ( x , y , φ , v x , v y , φ ˙ ) (x,y,\varphi ,v_x,v_y,\dot{\varphi}) (x,y,φ,vx,vy,φ˙) 和规划轨迹 ( x r , y r , θ r , κ r ) \left( x_r,y_r,\theta _r,\kappa _r \right) (xr,yr,θr,κr) 做误差计算,现在加入预测模块,就用预测点的 ( x p r e , y p r e , φ p r e , v x p r e , v y p r e , φ ˙ p r e ) \left( x_{pre},y_{pre},\varphi _{pre},v_{xpre},v_{ypre},\dot{\varphi}_{pre} \right) (xpre,ypre,φpre,vxpre,vypre,φ˙pre) 和规划轨迹做预测,这样算法具有一定的预见性。
这才是想要的完整算法,后续编程就按照算法流程图来编写,一共六大模块,已经全部讲完。
本篇博客就写到这里,但第八节还没有完,下一小节讲解具体的代码编写以及模型搭建。欢迎关注!
参考资料
【基础】自动驾驶控制算法第八节(一)横向控制算法与流程图
后记:
🌟 感谢您耐心阅读这篇关于 横向控制Ⅰ | 算法与流程 的技术博客。 📚
🎯 如果您觉得这篇博客对您有所帮助,请不要吝啬您的点赞和评论 📢
🌟您的支持是我继续创作的动力。同时,别忘了收藏本篇博客,以便日后随时查阅。🚀
🚗 让我们一起期待更多的技术分享,共同探索移动机器人的无限可能!💡
🎭感谢您的支持与关注,让我们一起在知识的海洋中砥砺前行 🚀
相关文章:
【自动驾驶】控制算法(八)横向控制Ⅰ | 算法与流程
写在前面: 🌟 欢迎光临 清流君 的博客小天地,这里是我分享技术与心得的温馨角落。📝 个人主页:清流君_CSDN博客,期待与您一同探索 移动机器人 领域的无限可能。 🔍 本文系 清流君 原创之作&…...
Android SSE 单向接收数据
Server-Sent Events(SSE)是一种在客户端和服务器之间实现单向实时通信的技术。它允许服务器向客户端推送数据,但客户端无法使用 SSE 向服务器发送数据。这使得其适用于需要持续接收服务器数据的应用场景(如实时通知、股票行情、社…...
排序《数据结构》
排序 《数据结构》 1.排序的概念及其运用1.1 排序的概念1.2 排序运用1.3常见的排序算法1.4 排序动图演示 2.常见排序算法的实现2.1 插入排序2.2希尔排序2.3 快排左边做keyi,右边先走,可以保证相遇位置比keyi小 2.4 快速排序优化快排(非递归&a…...
flutter 提示框2 Dialog
flutter 提示框 写在点击的方法体中 child里放自己喜欢的 showDialog( context: context, builder: (BuildContext context) { final Dialog alertDialog Dialog( backgroundColor: Colors.transparent,shadowColor:Colors.transparent,child: Container(height: mediawi…...
如何选择SDR无线图传方案
在开源软件定义无线电(SDR)领域,有几个项目提供了无线图传的解决方案。以下是一些开源SDR无线图传方案: 1. **OpenHD**:这是一个远程高清数字图像传输的开源解决方案,它使用SDR技术来实现高清视频的无线传…...
关于Python类中方法__init__()解析
# import numpy as npclass Car():def __init__(self, maker, name, year):self.maker makerself.name nameself.year yearprint(self.searchMakrt() "123")def searchMakrt(self):print("汽车制作厂家为: " self.maker)# passreturn &quo…...
微信小程序 自定义组件
1. 微信小程序 自定义组件 微信小程序支持组件化开发,这有助于我们复用代码,提高开发效率。下面我将给出一个简单的微信小程序组件化示例,包括一个自定义组件的创建和使用。 1.1. 创建自定义组件 首先,在项目的 components 目录…...
Mac+Pycharm配置PyQt6教程
安装包 pip install PyQt6 PyQt6-tools #查看Qt版本 pip show PyQt6 pip show pyqt6-tools 配置扩展工具 QTD(界面设计) Program:/Users/wan/PycharmProjects/NewDemo/venv/lib/python3.11/site-packages/qt6_applications/Qt/bin/Designer.app Working directo…...
如何保证Redis与Mysql双写一致性?
https://www.cnblogs.com/coderacademy/p/18137480 延迟双删 对于上面链接的文章,里面的延迟双删没有给出具体的例子,也没有直接指出具体解决的问题是针对那种缓存策略,这里补充一下,延时双删缓存针对的是Cache aside pattern(缓…...
9.8笔试记录
1.在c中哪些运算符不能重载? 在 C 中,有以下几个运算符不能被重载: . :成员访问运算符。例如obj.member中的.不能被重载。 :: :作用域解析运算符。用于指定命名空间、类等的作用域,不能被重载。 ?: ࿱…...
SRE-系统管理篇
SRE-系统管理篇 进程管理 进程的概念: 运行起来的程序,命令,服务等等都可以称作进行,进程都是运行在内存当中的。 程序的概念: 一般指安装包,程序代码,应用它们存放在磁盘上面的。 守护进程的概念: 守护进程,一直运行的进程,也可以叫做服务。 进程的分类 僵…...
傅里叶级数,傅里叶变换
先读文章:傅里叶分析之掐死教程(完整版)更新于2014.06.06 - 知乎 (zhihu.com) 傅里叶级数 一、内容:每个周期性函数都可以表示为无穷多个不同频率的正弦函数的叠加。 二、公式: 三、从时域到频域所保留的三点信息&…...
零知识证明在BSV网络上的应用
发表时间:2023年6月15日 2024年7月19日,BSV区块链主网上成功通过使用零知识证明验证了一笔交易。 零知识证明是一种技术,它允许一方(证明者)在不透露任何秘密的情况下,向另一方(验证者&…...
无任何门槛!3分钟5步,发布属于你的第一个智能体小程序,99%的人还不知道怎么用
相信大家都用微信小程序,但是大部分人应该还没有过属于自己的小程序吧。 今天程哥就带大家花三分钟用五步,来创建一个属于自己的微信小程序。 之前Coze在发布渠道里也有发布小程序的渠道,但是试过的人都知道,这个是有一定门槛的…...
怎么强制撤销excel工作表保护?
经常不是用的Excel文件设置了工作表保护,偶尔打开文件的时候想要编辑文件,但是发现忘记了密码,那么这种情况,我们怎么强制撤销excel工作表保护?今天分享两种解决方法。 方法一、 将excel文件转换为其他文件格式&…...
每天学习一个字符串类函数之memmove函数
目录 前言: 一、头文件 二、memmove函数的作用 三、理解memmove函数的定义 1、返回类型 2、参数 四、使用memmove函数 案例1: 案例2: 五、解决数据拷贝之前被覆盖的方法 六、模拟实现memmove函数 前言: 上一篇博客,我…...
【机器人工具箱Robotics Toolbox开发笔记(十三)】三自由度机器人圆弧轨迹规划仿真实例
在实际应用场景中,我们通常预先明确了目标末端的运动轨迹,随后引导机器人进行相应的动作。本实例具体展示了如何基于给定的两个点,计算出末端的精确位姿,并以此为基础,进一步规划出一条平滑的圆弧轨迹供机器人执行。这样的流程确保了机器人能够沿着预定的路径,精准且高效…...
软件工程-图书管理系统的概要设计
软件概要设计说明书 目录 软件概要设计说明书 一、引言 1.1 编写目的 1.2 背景 1.3 定义 1.3.1特定对象 1.3.2专业术语 1.4 参考资料 二、总体设计 2.1 需求规定 2.1.1信息要求 2.1.2功能要求 2.2 运行环境 2.3 基本概要设计和处理流程 2.4 体系结构设计 2.5 模…...
springboot 整合swagger
没有多余废话,就是干 spring-boot 2.7.8 springfox-boot-starter 3.0.0 结构 POM.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/…...
Flutter 进阶:绘制加载动画
绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 Load…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
