由于csdn文章长度的限制,将本篇文章分成两篇发布,另一篇文章见frenet坐标与cartesian坐标相互转换与代码实现(第一部分)。
也可以直接通过公众号iDoitnow的frenet坐标与cartesian坐标相互转换与代码实现直接阅读完整版
文章目录
1 frenet转cartesian坐标系
frenet转cartesian坐标系是已知$ s$ 、$ \dot{s}$、 s ¨ \ddot{s} s¨ 、 l l l、 l ′ l' l′、$ l’’ $,求 r ⃗ \vec{r} r、 θ \theta θ 、 v ⃗ \vec{v} v 、 a ⃗ \vec{a} a、 k k k 。
1.1 求 r ⃗ \vec{r} r
由图中的几何关系可得
r
⃗
=
r
r
⃗
+
l
n
r
⃗
(30)
\vec{r}=\vec{r_r}+l\vec{n_r} \tag{30}
r=rr+lnr(30)
1.2 求 v ⃗ \vec{v} v
由公式(18)和(17)可得
v
⃗
n
r
⃗
=
l
˙
v
⃗
τ
r
⃗
=
(
1
−
k
r
l
)
s
˙
(31)
\begin{align*} \vec{v}\vec{n_r}&=\dot{l} \\ \vec{v}\vec{\tau_r}&=(1-k_rl)\dot{s} \end{align*} \tag{31}
vnrvτr=l˙=(1−krl)s˙(31)
将上面两个式子展开可得
∣
v
⃗
∣
∣
n
r
⃗
∣
s
i
n
(
θ
−
θ
r
)
=
∣
v
⃗
∣
⋅
1
⋅
s
i
n
(
θ
−
θ
r
)
=
l
˙
∣
v
⃗
∣
∣
τ
r
⃗
∣
c
o
s
(
θ
−
θ
r
)
=
∣
v
⃗
∣
⋅
1
⋅
c
o
s
(
θ
−
θ
r
)
=
(
1
−
k
r
l
)
s
˙
(32)
\begin{align*} |\vec{v}||\vec{n_r}|sin(\theta - \theta_r)&=|\vec{v}| \cdot 1 \cdot sin(\theta - \theta_r)=\dot{l} \\ |\vec{v}||\vec{\tau_r}| cos(\theta-\theta_r)&=|\vec{v}| \cdot 1 \cdot cos(\theta-\theta_r)=(1-k_rl)\dot{s} \end{align*}\tag{32}
∣v∣∣nr∣sin(θ−θr)∣v∣∣τr∣cos(θ−θr)=∣v∣⋅1⋅sin(θ−θr)=l˙=∣v∣⋅1⋅cos(θ−θr)=(1−krl)s˙(32)
将上面两个式子两侧分别平方并相加可得
∣
v
⃗
∣
=
(
l
˙
2
+
(
1
−
k
r
l
)
2
s
˙
2
)
1
2
(33)
|\vec{v}|={(\dot{l}^2 + (1-k_rl)^2 \dot{s}^2)}^{\frac{1}{2}} \tag{33}
∣v∣=(l˙2+(1−krl)2s˙2)21(33)
将(32)两式相除可得
t
a
n
(
θ
−
θ
r
)
=
l
˙
(
1
−
k
r
l
)
s
˙
(34)
tan(\theta-\theta_r)=\frac{\dot{l}}{(1-k_rl)\dot{s}} \tag{34}
tan(θ−θr)=(1−krl)s˙l˙(34)
结合公式(22),可得
θ
=
θ
r
+
a
r
c
t
a
n
l
˙
(
1
−
k
r
l
)
s
˙
=
θ
r
+
a
r
c
t
a
n
l
′
1
−
k
r
l
(35)
\theta = \theta_r + arctan\frac{\dot{l}}{(1-k_rl)\dot{s}}=\theta_r + arctan\frac{l'}{1-k_rl} \tag{35}
θ=θr+arctan(1−krl)s˙l˙=θr+arctan1−krll′(35)
1.3 求 a ⃗ \vec{a} a和 a τ a_{\tau} aτ
由公式(23)和(25)可得
a
⃗
n
r
⃗
=
l
¨
+
k
r
(
1
−
k
r
l
)
s
˙
2
a
⃗
τ
r
⃗
=
s
¨
(
1
−
k
r
l
)
+
k
r
s
˙
2
l
′
+
(
k
r
′
l
−
k
r
l
′
)
s
˙
2
(36)
\begin{align*} \vec{a} \vec{n_r} &= \ddot{l} + k_r(1-k_rl) \dot{s}^2 \\ \vec{a} \vec{\tau_r} &= \ddot{s}(1-k_rl) + k_r \dot{s}^2l' + (k_r'l-k_rl') \dot{s}^2 \end{align*}\tag{36}
anraτr=l¨+kr(1−krl)s˙2=s¨(1−krl)+krs˙2l′+(kr′l−krl′)s˙2(36)
与求解
v
⃗
\vec{v}
v类似,将上两式分别平方在相加可得
∣
a
⃗
∣
=
(
(
l
¨
+
k
r
(
1
−
k
r
l
)
s
˙
2
)
2
+
(
s
¨
(
1
−
k
r
l
)
+
k
r
s
˙
2
l
′
+
(
k
r
′
l
−
k
r
l
′
)
s
˙
2
)
2
)
1
2
(37)
|\vec{a}|=((\ddot{l} + k_r(1-k_rl) \dot{s}^2)^2 + (\ddot{s}(1-k_rl) + k_r \dot{s}^2l' + (k_r'l-k_rl') \dot{s}^2 )^2)^{\frac{1}{2}} \tag{37}
∣a∣=((l¨+kr(1−krl)s˙2)2+(s¨(1−krl)+krs˙2l′+(kr′l−krl′)s˙2)2)21(37)
将(36)两式再相除可得
t
a
n
(
θ
a
−
θ
r
)
=
l
¨
+
k
r
(
1
−
k
r
l
)
s
˙
2
s
¨
(
1
−
k
r
l
)
+
k
r
s
˙
2
l
′
+
(
k
r
′
l
−
k
r
l
′
)
s
˙
2
(38)
tan(\theta_a - \theta_r) = \frac{ \ddot{l} + k_r(1-k_rl) \dot{s}^2}{ \ddot{s}(1-k_rl) + k_r \dot{s}^2l' + (k_r'l-k_rl') \dot{s}^2} \tag{38}
tan(θa−θr)=s¨(1−krl)+krs˙2l′+(kr′l−krl′)s˙2l¨+kr(1−krl)s˙2(38)
其中,
θ
a
\theta_a
θa为向量
a
⃗
\vec{a}
a与笛卡尔坐标系
X
X
X轴的夹角。
由上式可得
θ
a
=
θ
r
+
a
r
c
t
a
n
l
¨
+
k
r
(
1
−
k
r
l
)
s
˙
2
s
¨
(
1
−
k
r
l
)
+
k
r
s
˙
2
l
′
+
(
k
r
′
l
−
k
r
l
′
)
s
˙
2
(39)
\theta_a = \theta_r + arctan\frac{ \ddot{l} + k_r(1-k_rl) \dot{s}^2}{ \ddot{s}(1-k_rl) + k_r \dot{s}^2l' + (k_r'l-k_rl') \dot{s}^2} \tag{39}
θa=θr+arctans¨(1−krl)+krs˙2l′+(kr′l−krl′)s˙2l¨+kr(1−krl)s˙2(39)
对于切线加速度
a
τ
=
∣
v
˙
⃗
∣
a_{\tau}=|\vec{\dot{v}}|
aτ=∣v˙∣,将公式
(
10
)
(10)
(10)两边同时点乘
τ
⃗
\vec{\tau}
τ可得
a
τ
=
∣
v
˙
⃗
∣
=
a
⃗
τ
⃗
=
∣
a
⃗
∣
c
o
s
(
θ
a
−
θ
)
(40)
a_{\tau}=|\vec{\dot{v}}|=\vec{a} \vec{\tau} = |\vec{a}|cos(\theta_a - \theta) \tag{40}
aτ=∣v˙∣=aτ=∣a∣cos(θa−θ)(40)
1.4 求 k k k
将公式
(
10
)
(10)
(10)两边点乘
n
⃗
\vec{n}
n可得
a
⃗
n
⃗
=
k
∣
v
⃗
∣
2
(41)
\vec{a} \vec{n}=k |\vec{v}|^2 \tag{41}
an=k∣v∣2(41)
由上式可得
k
=
a
⃗
n
⃗
∣
v
⃗
∣
2
(42)
k = \frac{\vec{a} \vec{n}}{|\vec{v}|^2} \tag{42}
k=∣v∣2an(42)
1.5 小结
综上,可得
{
r
⃗
=
r
r
⃗
+
l
n
r
⃗
∣
v
⃗
∣
=
(
l
˙
2
+
(
1
−
k
r
l
)
2
s
˙
2
)
1
2
θ
=
θ
r
+
a
r
c
t
a
n
l
˙
(
1
−
k
r
l
)
s
˙
=
θ
r
+
a
r
c
t
a
n
l
′
1
−
k
r
l
∣
a
⃗
∣
=
(
(
l
¨
+
k
r
(
1
−
k
r
l
)
s
˙
2
)
2
+
(
s
¨
(
1
−
k
r
l
)
+
k
r
s
˙
2
l
′
+
(
k
r
′
l
−
k
r
l
′
)
s
˙
2
)
2
)
1
2
θ
a
=
θ
r
+
a
r
c
t
a
n
l
¨
+
k
r
(
1
−
k
r
l
)
s
˙
2
s
¨
(
1
−
k
r
l
)
+
k
r
s
˙
2
l
′
+
(
k
r
′
l
−
k
r
l
′
)
s
˙
2
a
τ
=
∣
a
⃗
∣
c
o
s
(
θ
a
−
θ
)
k
=
a
⃗
n
⃗
∣
v
⃗
∣
2
(43)
\begin{cases} \vec{r}&=\quad\vec{r_r}+l\vec{n_r} \\ |\vec{v}|&= \quad {(\dot{l}^2 + (1-k_rl)^2 \dot{s}^2)}^{\frac{1}{2}} \\ \theta &= \quad \theta_r + arctan\frac{\dot{l}}{(1-k_rl)\dot{s}}=\theta_r + arctan\frac{l'}{1-k_rl} \\ |\vec{a}|&=\quad ((\ddot{l} + k_r(1-k_rl) \dot{s}^2)^2 + (\ddot{s}(1-k_rl) + k_r \dot{s}^2l' + (k_r'l-k_rl') \dot{s}^2 )^2)^{\frac{1}{2}} \\ \theta_a &=\quad \theta_r + arctan\frac{ \ddot{l} + k_r(1-k_rl) \dot{s}^2}{ \ddot{s}(1-k_rl) + k_r \dot{s}^2l' + (k_r'l-k_rl') \dot{s}^2}\\ a_{\tau}&=\quad |\vec{a}|cos(\theta_a - \theta)\\ k &= \quad \frac{\vec{a} \vec{n}}{|\vec{v}|^2} \end{cases} \tag{43}
⎩
⎨
⎧r∣v∣θ∣a∣θaaτk=rr+lnr=(l˙2+(1−krl)2s˙2)21=θr+arctan(1−krl)s˙l˙=θr+arctan1−krll′=((l¨+kr(1−krl)s˙2)2+(s¨(1−krl)+krs˙2l′+(kr′l−krl′)s˙2)2)21=θr+arctans¨(1−krl)+krs˙2l′+(kr′l−krl′)s˙2l¨+kr(1−krl)s˙2=∣a∣cos(θa−θ)=∣v∣2an(43)
2. 代码实现(python)
cartesian到frenet坐标转换:
import numpy as np
from math import *
def cartesian_to_frenet(rs, rx, ry, rtheta, rkappa, rdkappa, x, y, v, a_v, theta, kappa):
vec_r = np.array([x, y])
vec_rr = np.array([rx, ry])
vec_nr = np.array([cos(rtheta + np.pi / 2), sin(rtheta + np.pi / 2)])
if np.cross(vec_r - vec_rr, vec_nr) >= 1.0e-6: # 投影点应与目标点组成的向量应与nr平行
print("The reference point [rx, ry] and [x, y] don't match")
vec_t = np.array([cos(theta), sin(theta)])
vec_v = np.array([v * cos(theta), v * sin(theta)])
vec_n = np.array([cos(theta + np.pi / 2), sin(theta + np.pi / 2)])
vec_a = a_v * vec_t + v * v * kappa * vec_n
vec_tr = np.array([cos(rtheta), sin(rtheta)])
# 计算s、l
l = np.dot(vec_r - vec_rr, vec_nr)
s = rs
# 计算dot_s
dot_s = np.dot(vec_v, vec_tr) / (1 - rkappa * l)
dot_l = np.dot(vec_v, vec_nr)
ddot_l = np.dot(vec_a, vec_nr) - rkappa * (1 - rkappa * l) * dot_s * dot_s
# 计算dl
dl = dot_l / dot_s
# 计算ddl、dot_s
ddot_s = np.dot(vec_a, vec_tr) / (1 - rkappa * l) \
+ dot_s * dot_s * rkappa * dl / (1 - rkappa * l) \
+ dot_s * dot_s * (rdkappa * l + rkappa * dl) / (1 - rkappa * l)
ddl = (ddot_l - dl * ddot_s) / (dot_s * dot_s)
return np.array([s, dot_s, ddot_s]), np.array([l, dl, ddl])
frenet到cartesian坐标转换:
import numpy as np
from math import *
def normalize_angle(angle):
a = fmod(angle+np.pi, 2*np.pi)
if a < 0.0:
a += (2.0*np.pi)
return a - np.pi
def frenet_to_cartesian(rs, rx, ry, rtheta, rkappa, rdkappa, s_condition, d_condition):
if fabs(rs - s_condition[0]) >= 1.0e-6:
print("The reference point s and s_condition[0] don't match")
vec_rr = np.array([rx, ry])
vec_nr = np.array([cos(rtheta + np.pi / 2), sin(rtheta + np.pi / 2)])
# 计算r,得到的就是目标点坐标(x, y)
vec_r = vec_rr + d_condition[0] * vec_nr
dot_l = d_condition[1] * s_condition[1]
ddot_l = d_condition[2] * s_condition[1] * s_condition[1] + s_condition[2] * d_condition[1]
# 计算速度v
v = sqrt(dot_l**2 + (1 - rkappa * d_condition[0])**2 * s_condition[1]**2)
# 计算theta
theta = normalize_angle(rtheta + atan2(d_condition[1], (1 - rkappa * d_condition[0])))
# 计算加速度a、theta_a和切线加速度a_v
a_part1 = ddot_l + rkappa * (1 - rkappa * d_condition[0]) * (s_condition[1] * s_condition[1])
a_part2 = (s_condition[2] * (1 - rkappa * d_condition[0])
- rkappa * s_condition[1] * s_condition[1] * d_condition[1]
- s_condition[1] * s_condition[1] *(rdkappa * d_condition[0] + rkappa * d_condition[1]))
a = sqrt(a_part1 * a_part1 + a_part2 * a_part2)
theta_a = normalize_angle(rtheta + atan2(a_part1, a_part2))
a_v = a * cos(theta_a - theta)
# 计算kappa
vec_n = np.array([-sin(theta), cos(theta)]) # 切线单位向量n
kappa = a * np.dot(np.array([cos(theta_a), sin(theta_a)]), vec_n) / (v*v)
return vec_r[0], vec_r[1], v, a_v, theta, kappa
2. 参考文献
B站up主忠厚老实的老王的自动驾驶决策规划视频
文章首发公众号:iDoitnow如果喜欢话,可以关注一下

被折叠的 条评论
为什么被折叠?



