【自动驾驶】Frenet坐标系与Cartesian坐标系(一)
一般情况下,我们使用Cartesian坐标系(笛卡尔坐标系)来描述物体的坐标,但对于车辆来说,笛卡尔坐标系并不是最佳选择。因为即使知道了笛卡尔坐标系下车辆的位置信息,也难以表达车辆与道路之间的相对位置,导致二者之间的相对关系不明确。因此,传统规划算法在笛卡尔坐标系下规划出的路径对于开放道路有良好的效果,但是对于公路环境,忽略车道信息导致路径的自由度太高而容易违反道路交通规则。Frenet坐标系在无
文章目录
参考资料
【自动驾驶】Frenet坐标系与Cartesian坐标系(二)
1. Frenet坐标系介绍
1.1 Cartesian坐标系
-
一般情况下,我们使用Cartesian坐标系(笛卡尔坐标系)来描述物体的坐标,但对于车辆来说,笛卡尔坐标系并不是最佳选择。因为即使知道了笛卡尔坐标系下车辆的位置信息,也难以表达车辆与道路之间的相对位置,导致二者之间的相对关系不明确。
-
因此,传统规划算法在笛卡尔坐标系下规划出的路径对于开放道路有良好的效果,但是对于公路环境,忽略车道信息导致路径的自由度太高而容易违反道路交通规则。
1.2 Frenet坐标系
Frenet坐标系在无人驾驶领域被普遍使用,特别是在城市、高速等道路交通环境下无人驾驶的路径规划系统中。
Frenet坐标系使用道路的中心线作为参考线,使用参考线的切线向量和法线向量建立坐标系。相比笛卡尔坐标系,Frenet坐标系简化了路径规划问题。
下图是自动驾驶车辆在全局坐标系与Frenet坐标系中的位置示意。
假设自动驾驶车辆在全局坐标系下的坐标为 ( x , y ) (x,y) (x,y),从车辆的位置 ( x , y ) (x,y) (x,y)向参考线 T T T作投影,投影点为 F F F,则点 F F F与车辆位置 ( x , y ) (x,y) (x,y)的距离即为横向位移 d d d(方向为参考线当前的法向,称为横向,Lateral);从参考线的起始点到投影点 F F F的曲线距离即为纵向位移 s s s(方向沿着参考线,称为纵向,Longitudinal)。
基于Frenet坐标系,将自动驾驶车辆每时每刻的位置状态分解在 s s s和 d d d两个方向来描述车辆的运动状态,从而在轨迹曲线拟合时,减少处理坐标信息的工作量。
1.3 Frenet公式
在向量微积分中,弗勒内-塞雷公式(Frenet–Serret 公式)用来描述欧几里得空间 R 3 R^3 R3中的粒子在连续可微曲线上的运动。更具体的说,弗勒内公式描述了曲线的切向,法向,副法方向之间的关系。
下图是空间曲线的切向量 T T T,法向量 N N N 和副法向量 B B B,以及切向量和法向量张成的密切平面。
单位切向量 T T T,单位法向量 N N N,单位副法向量 B B B,被称作 弗勒内标架,他们的具体定义如下:
- T T T 是单位切向量,方向指向粒子运动的方向。
- N N N 是切向量 T T T 对弧长参数的微分单位化得到的向量。
- B B B 是 T T T 和 N N N 的外积 T × N T\times N T×N。
下图是螺旋线上弗勒内标架的运动。蓝色的箭头表示切向量,红色的箭头表示法向量,黑色的箭头表示副法向量。
Frenet公式如下:
{
d
T
d
s
=
κ
N
d
N
d
s
=
−
κ
T
+
τ
B
d
B
d
s
=
−
τ
N
(1.1)
\tag{1.1} \left\{\begin{aligned} \frac{d T}{d s}&= \kappa N \\ \frac{d N}{d s}&= -\kappa T+\tau B \\ \frac{d B}{d s}&= -\tau N \end{aligned}\right.
⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧dsdTdsdNdsdB=κN=−κT+τB=−τN(1.1)
其中,
d
(
⋅
)
d
s
\frac{d(\cdot)}{d s}
dsd(⋅) 表示是对弧长的微分,
κ
\kappa
κ 为曲率(curvature),
τ
\tau
τ 为挠率 ( torsion)。弗勒内公式描述了空间曲线曲率挠率的变化规律。
- 曲率:曲线不能形成一条直线的度量值,曲率越趋于 0 ,则曲线越趋近于直线;
- 挠率:是曲线不能形成在同一平面内运动曲线的度量值,挠率越趋于 0 ,则曲线越趋近于在同一平面内运动。
将公式(1.1)写作矩阵的形式,有
[
T
′
N
′
B
′
]
=
[
0
κ
0
−
κ
0
τ
0
−
τ
0
]
[
T
N
B
]
(1.2)
\tag{1.2} \left[\begin{array}{l} \mathbf{T}^{\prime} \\ \mathbf{N}^{\prime} \\ \mathbf{B}^{\prime} \end{array}\right]=\left[\begin{array}{ccc} 0 & \kappa & 0 \\ -\kappa & 0 & \tau \\ 0 & -\tau & 0 \end{array}\right]\left[\begin{array}{c} \mathbf{T} \\ \mathbf{N} \\ \mathbf{B} \end{array}\right]
⎣⎡T′N′B′⎦⎤=⎣⎡0−κ0κ0−τ0τ0⎦⎤⎣⎡TNB⎦⎤(1.2)
其中系数矩阵是反对称矩阵。
对于无人驾驶路径规划应用,一般对高度信息不感兴趣,因此可以将车辆运动曲线投影到同一平面内,挠率可设定为 0 ,这样Frenet公式可以进一步简化为:
{
d
T
d
s
=
κ
N
d
N
d
s
=
−
κ
T
(1.3)
\tag{1.3} \left\{\begin{aligned} \frac{d T}{d s}&=\kappa N \\ \frac{d N}{d s}&=-\kappa T \end{aligned}\right.
⎩⎪⎪⎨⎪⎪⎧dsdTdsdN=κN=−κT(1.3)
2. Frenet坐标系与全局笛卡尔坐标系转换
在Frenet坐标系下,经规划得到横向、纵向运动轨迹后,需要将其重新映射到全局笛卡尔坐标系,以供控制模块调用。
如图 所示, 受车辆运动学、动力学特性及道路环境 (避障) 限制, 车辆的实际行驶轨迹与参考线难以重合。
图中主要参数说明
首先,
t
⃗
,
n
⃗
\mathrm{\vec{t}}, \mathrm{\vec{n}}
t,n 都是单位向量且有:
{
t
⃗
r
=
[
cos
θ
r
,
sin
θ
r
]
T
n
⃗
r
=
[
−
sin
θ
r
,
cos
θ
r
]
T
t
⃗
x
=
[
cos
θ
x
,
sin
θ
x
]
T
n
⃗
x
=
[
−
sin
θ
x
,
cos
θ
x
]
T
(1.4)
\tag{1.4} \left\{ \begin{aligned} \vec{t}_{r} &=\left[\cos \theta_{r}, \sin \theta_{r}\right]^T \\ \vec{n}_{r} &=\left[-\sin \theta_{r}, \cos \theta_{r}\right]^T \\ \vec{t}_{x} &=\left[\cos \theta_{x}, \sin \theta_{x}\right]^T \\ \vec{n}_{x} &=\left[-\sin \theta_{x}, \cos \theta_{x}\right]^T \end{aligned} \right.
⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧trnrtxnx=[cosθr,sinθr]T=[−sinθr,cosθr]T=[cosθx,sinθx]T=[−sinθx,cosθx]T(1.4)
- θ r : \theta_{r}: θr: 表示参考线 r ⃗ \vec{r} r 的方向角
- n ⃗ r \vec{n}_{r} nr : 表示r(s)单位法向量
- t ⃗ r \vec{t}_{r} tr : 表示r(s)单位切向量
- θ x \theta_{x} θx : 表示 x ⃗ \vec{x} x的方向角
- n ⃗ x \vec{n}_{x} nx : 表示 x ⃗ \vec{x} x 单位法向量
- t ⃗ x \vec{t}_{x} tx : 表示 x ⃗ \vec{x} x 单位切向量
全局坐标系下
在全局坐标系下, 任意时刻 t t t 的车辆运动状态可以描述为 [ x ⃗ , θ x , κ x , v x , a x ] \left[\vec{x}, \theta_{x}, \kappa_{x}, v_{x}, a_{x}\right] [x,θx,κx,vx,ax]。
其中:
- x ⃗ \vec{x} x 为车辆当前位置 Q Q Q, 表示车辆在全局坐标系下的位置信息 ( x , y ) (x, y) (x,y), 是一个向量;
- θ x \theta_{x} θx 为方位角,即全局坐标系下的朝向;
- κ x \kappa_{x} κx 为曲率
- v x = ∣ ∣ x ˙ ⃗ ∣ ∣ v_{x}=||\vec{\dot x}|| vx=∣∣x˙∣∣ 为Cartesian坐标系下的线速度;
- a x = d v x d t a_{x}=\frac{dv_x}{dt} ax=dtdvx 为加速度.
- 图中的 r ⃗ ( t ) \vec{r}(t) r(t) 为位置 Q Q Q 投影到参考线上的投影点 P P P 在全局坐标系 下的位置向量。
Frenet坐标系下
在 Frenet坐标系下, 车辆的运动状态可以描述为 [ s , s ˙ , s ¨ , d , d ˙ , d ¨ , d ′ , d ′ ′ ] \left[s, \dot{s}, \ddot{s}, d, \dot{d}, \ddot{d} , d^{\prime}, d^{\prime \prime}\right] [s,s˙,s¨,d,d˙,d¨,d′,d′′].
其中:
- s s s 为纵向位移,即Frenet纵坐标;
- s ˙ = d s d t \dot{s}=\frac{ds}{dt} s˙=dtds 为Frenet纵向速 度;
- s ¨ = s ˙ d t \ddot{s}=\frac{\dot{s}}{dt} s¨=dts˙ 为Frenet纵向加速度;
- d d d 为横向位移, 即Frenet横坐标;
- d ˙ \dot{d} d˙ 为Frenet横向速度;
- d ¨ \ddot{d} d¨ 为Frenet横向加速度;
- d ′ = d d s ( d ) d^{\prime}=\frac{\mathrm{d}}{\mathrm{d}s}(d) d′=dsd(d) 为横向位移对纵向坐标的一阶导数,
- d ′ ′ = d d s ( d ′ ) d^{\prime \prime}=\frac{\mathrm{d}}{\mathrm{d}s}(d^{\prime}) d′′=dsd(d′) 为 横向位移对纵向坐标的二阶导数.
tips: x ˙ = d x d t \dot{x}=\frac{dx}{dt} x˙=dtdx, x ′ = d x d s x'=\frac{dx}{ds} x′=dsdx
由于正文篇幅字数的限制,这里只给出转换公式,具体推导见下一篇博客。
2.1 Cartesian转 Frenet公式
已知 ( x , y , θ x , v x , a x , k x ) , ( s r , x r , y r , θ r , k r , k r ′ ) (x, y, \theta_x, v_x, a_x, k_x), (s_r, x_r, y_r, \theta_r, k_r, k_r') (x,y,θx,vx,ax,kx),(sr,xr,yr,θr,kr,kr′)的前提下,求 [ s , s ˙ , s ¨ , d , d ˙ , d ¨ , d ′ , d ′ ′ ] \left[s, \dot{s}, \ddot{s}, d, \dot{d}, \ddot{d} , d^{\prime}, d^{\prime \prime}\right] [s,s˙,s¨,d,d˙,d¨,d′,d′′].
公式总结如下:
{
s
=
s
r
s
˙
=
v
x
cos
Δ
θ
(
1
−
κ
r
d
)
s
¨
=
a
x
cos
Δ
θ
−
s
˙
2
[
d
′
(
k
x
1
−
k
r
d
cos
Δ
θ
−
k
r
)
−
(
k
r
′
d
+
k
r
d
′
)
]
1
−
k
r
d
d
=
sign
(
(
y
−
y
r
)
cos
(
θ
r
)
−
(
x
−
x
r
)
sin
(
θ
r
)
)
(
x
−
x
r
)
2
+
(
y
−
y
r
)
2
d
˙
=
v
x
sin
Δ
θ
d
¨
=
a
x
sin
Δ
θ
d
′
=
(
1
−
κ
r
d
)
tan
Δ
θ
d
′
′
=
−
(
κ
r
′
d
+
κ
r
d
′
)
tan
Δ
θ
+
1
−
κ
r
d
cos
2
Δ
θ
(
κ
x
1
−
κ
r
d
cos
Δ
θ
−
κ
r
)
(1.5)
\tag{1.5} \left\{ \begin{aligned} s&=s_r\\ \dot{s} &=\frac{v_x\cos{\Delta \theta}}{\left(1-\kappa_{r} d\right) }\\ \ddot{s}&=\frac{a_{x} \cos \Delta \theta-\dot{s}^{2}\left[d^{\prime}\left(k_{x} \frac{1-k_{r} d}{\cos \Delta \theta}-k_{r}\right)-\left(k_{r}^{\prime} d+k_{r} d^{\prime}\right)\right]}{1-k_{r} d}\\ d&=\operatorname{sign}\left(\left(y-y_{r}\right) \cos \left(\theta_{r}\right)-\left(x-x_{r}\right) \sin \left(\theta_{r}\right)\right) \sqrt{\left(x-x_{r}\right)^{2}+\left(y-y_{r}\right)^{2}}\\ \dot d &= v_x\sin{\Delta \theta}\\ \ddot d &= a_x\sin{\Delta \theta}\\ d^{\prime}&=\left(1-\kappa_{r} d\right) \tan \Delta \theta \\ d^{\prime \prime} &=-(\kappa_{r}^{\prime} d+\kappa_{r} d^{\prime}) \tan \Delta \theta+ \frac{1-\kappa_{r} d}{\cos ^{2} \Delta \theta}\left(\kappa_{x} \frac{1-\kappa_{r} d}{\cos \Delta \theta}-\kappa_{r}\right) \end{aligned} \right.
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧ss˙s¨dd˙d¨d′d′′=sr=(1−κrd)vxcosΔθ=1−krdaxcosΔθ−s˙2[d′(kxcosΔθ1−krd−kr)−(kr′d+krd′)]=sign((y−yr)cos(θr)−(x−xr)sin(θr))(x−xr)2+(y−yr)2=vxsinΔθ=axsinΔθ=(1−κrd)tanΔθ=−(κr′d+κrd′)tanΔθ+cos2Δθ1−κrd(κxcosΔθ1−κrd−κr)(1.5)
-
python实现
import numpy as np from math import * def cartesian2Frenet(x,y,theta_x,v_x,a_x,k_x,s_r,x_r,y_r,theta_r,k_r,k_r_): """全局坐标系转Frenet坐标系 Args: x (_type_): Cartesian坐标系下的车辆横坐标位置 y (_type_): Cartesian坐标系下的车辆纵坐标位置 theta_x (_type_): 为方位角,即全局坐标系下的朝向; v_x (_type_): Cartesian坐标系下的线速度大小; a_x (_type_): Cartesian坐标系下的加速度 k_x (_type_): 曲率 s_r (_type_): 投影点的弧长 x_r (_type_): 投影点P点在Cartesian坐标系下的x坐标 y_r (_type_): 投影点P点在Cartesian坐标系下的y坐标 theta_r (_type_): 投影点P点在Cartesian坐标系下的朝向角 k_r (_type_): 曲率 k_r_ (_type_): 曲率对弧长s的一阶导数_ Returns: _type_: Frenet坐标系下车辆的运动状态 """ delta_theta = theta_x-theta_r one_kr_d = 1-k_r*d s=s_r d=np.sign((y-y_r)*cos(theta_r)-(x-x_r)*sin(theta_r))*sqrt((x-x_r)**2+(y-y_r)**2) dot_d = v_x*sin(delta_theta) ddot_d = a_x*sin(delta_theta) dot_s=v_x*cos(delta_theta)/one_kr_d d_=one_kr_d*tan(delta_theta) d__=-(k_r_*d+k_r*d_)*tan(delta_theta)+one_kr_d/(cos(delta_theta))**2*(k_x*one_kr_d/cos(delta_theta)-k_r) ddot_s = (a_x*cos(delta_theta)-dot_s**2*(d_*(k_x*one_kr_d/cos(delta_theta)-k_r)-(k_r_*d+k_r*d_)))/one_kr_d return s,dot_s,ddot_s,d,dot_d,ddot_d,d_,d__
2.2 Frenet转Cartesian公式
首先,作为参考系,投影点P点在笛卡尔坐标系下的坐标,角度,切向量角度以及曲率都已知,即 x r , y r , θ r , k r , k r ′ x_r, y_r, θ_r,k_r,k_r' xr,yr,θr,kr,kr′。Frenet坐标系下, 车辆的运动状态 [ s , s ˙ , s ¨ , d , d ˙ , d ¨ , d ′ , d ′ ′ ] \left[s, \dot{s}, \ddot{s}, d, \dot{d}, \ddot{d} , d^{\prime}, d^{\prime \prime}\right] [s,s˙,s¨,d,d˙,d¨,d′,d′′]也已知。求在全局坐标系下的 [ x , y , θ x , κ x , v x , a x ] \left[x,y, \theta_{x}, \kappa_{x}, v_{x}, a_{x}\right] [x,y,θx,κx,vx,ax]。
公式总结如下:
{
x
=
x
r
−
d
sin
(
θ
r
)
y
=
y
r
+
d
cos
(
θ
r
)
θ
x
=
arctan
(
d
′
1
−
k
r
d
)
+
θ
r
v
x
=
[
s
˙
(
1
−
k
r
d
)
]
2
+
(
s
˙
d
′
)
2
a
x
=
s
¨
1
−
k
r
d
cos
Δ
θ
+
s
˙
2
cos
Δ
θ
[
d
′
(
k
x
1
−
k
r
d
cos
Δ
θ
−
k
r
)
−
(
k
r
′
d
+
k
r
d
′
)
]
k
x
=
(
(
d
′
′
+
(
k
r
′
d
+
k
r
d
′
)
tan
Δ
θ
)
cos
2
Δ
θ
1
−
k
r
d
+
k
r
)
cos
Δ
θ
1
−
k
r
d
(1.6)
\tag{1.6} \left\{\begin{aligned} x&= x_{r}-d\sin \left(\theta_{r}\right) \\ y&= y_{r}+d \cos \left(\theta_{r}\right) \\ \theta_{x}&= \arctan(\frac{d'}{1-k_r d})+\theta_r\\ v_{x}&= \sqrt{\left[\dot{s}\left(1-k_{r} d\right)\right]^{2}+\left(\dot{s} d^{\prime}\right)^{2}} \\ a_{x}&=\ddot{s} \frac{1-k_{r} d}{\cos \Delta \theta}+\frac{\dot{s}^{2}}{\cos \Delta \theta}\left[d^{\prime}\left(k_{x} \frac{1-k_{r} d}{\cos \Delta \theta}-k_{r}\right)-\left(k_{r}^{\prime} d+k_{r} d^{\prime}\right)\right] \\ k_{x}&= \left(\left(d^{\prime \prime}+\left(k_{r}^{\prime} d+k_{r} d^{\prime}\right) \tan \Delta \theta\right) \frac{\cos ^{2}\Delta \theta}{1-k_{r}d}+k_{r}\right) \frac{\cos \Delta \theta}{1-k_{r} d} \\ \end{aligned}\right.
⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧xyθxvxaxkx=xr−dsin(θr)=yr+dcos(θr)=arctan(1−krdd′)+θr=[s˙(1−krd)]2+(s˙d′)2=s¨cosΔθ1−krd+cosΔθs˙2[d′(kxcosΔθ1−krd−kr)−(kr′d+krd′)]=((d′′+(kr′d+krd′)tanΔθ)1−krdcos2Δθ+kr)1−krdcosΔθ(1.6)
-
python实现
import numpy as np from math import * def frenet2Cartesian(s,dot_s,ddot_s,d,dot_d,ddot_d,d_,d__,x_r,y_r,theta_r,k_r,k_r_): """Frenet转Cartesian Args: s (_type_): 为纵向位移,即Frenet纵坐标; dot_s (_type_): Frenet纵向速 度 ddot_s (_type_): Frenet纵向加速度, d (_type_): 横向位移, 即Frenet横坐标 dot_d (_type_): Frenet横向速度 ddot_d (_type_): Frenet横向加速度 d_ (_type_): 横向位移对纵向坐标的一阶导数 d__ (_type_): 横向位移对纵向坐标的二阶导数 x_r (_type_): 投影点P点在Cartesian坐标系下的x坐标 y_r (_type_): 投影点P点在Cartesian坐标系下的y坐标 theta_r (_type_): 投影点P点在Cartesian坐标系下的朝向角 k_r (_type_): 曲率 k_r_ (_type_): 曲率对弧长s的一阶导数_ Returns: _type_: _description_ """ x = x_r-d*sin(theta_r) y = y_r+d*cos(theta_r) one_kr_d= 1-k_r*d theta_x = theta_r+atan2(d_,one_kr_d) delta_theta = theta_x-theta_r v_x = sqrt((dot_s*one_kr_d)**2+(dot_s*d_)**2) k_x = cos(delta_theta)/one_kr_d*(k_r+(cos(delta_theta))**2/one_kr_d*(d__+(k_r_*d+k_r*d_)*tan(delta_theta))) a_x = ddot_s*one_kr_d/cos(delta_theta)+dot_s**2/cos(delta_theta)*(d_*(k_x*one_kr_d/cos(delta_theta)-k_r)-(k_r_*d+k_r*d_)) return x,y,theta_x,v_x,a_x,k_x
推导过程请详见:
【自动驾驶】Frenet坐标系与Cartesian坐标系(二)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)