Towards Time-Optimal Tunnel-Following for Quadrotors---acados quadrotors_nav/common.py——2

6.8

0 GPT提问

def projFrenSerretBasis(s: Union[ca.MX, float]):
    ''' project to the Frenet Serret space
    <-- kap_impl : Curvature
    <-- tau_impl : torsion
    <-- dGamma_ds, d2Gamma_ds2, d3Gamma_ds3 : First 3 derivates of the curve w.r.t arc length
    <-- et_MX, en_MX, eb_MX : tangent , normal , binormal unit vectors'''

    InterOpts = {'degree': [5]}
    y_ref_MX = ca.interpolant("y_ref", "bspline", [s_ref], y_ref, InterOpts)
    z_ref_MX = ca.interpolant("z_ref", "bspline", [s_ref], z_ref, InterOpts)
    x_ref_MX = ca.interpolant("x_ref", "bspline", [s_ref], x_ref, InterOpts)


    [d2GammaX_ds2, dGammaX_ds] = ca.hessian(x_ref_MX(s), s)
    [d2GammaY_ds2, dGammaY_ds] = ca.hessian(y_ref_MX(s), s)
    [d2GammaZ_ds2, dGammaZ_ds] = ca.hessian(z_ref_MX(s), s)

    [d4GammaX_ds4, d3GammaX_ds3] = ca.hessian(d2GammaX_ds2, s)
    [d4GammaY_ds4, d3GammaY_ds3] = ca.hessian(d2GammaY_ds2, s)
    [d4GammaZ_ds4, d3GammaZ_ds3] = ca.hessian(d2GammaZ_ds2, s)

    dGamma_ds = ca.vertcat(dGammaX_ds, dGammaY_ds, dGammaZ_ds)
    d2Gamma_ds2 = ca.vertcat(d2GammaX_ds2, d2GammaY_ds2, d2GammaZ_ds2)
    d3Gamma_ds3 = ca.vertcat(d3GammaX_ds3, d3GammaY_ds3, d3GammaZ_ds3)
    d4Gamma_ds4 = ca.vertcat(d4GammaX_ds4, d4GammaY_ds4, d4GammaZ_ds4)

    kap = ca.norm_2(d2Gamma_ds2)
    kapBar_MX = ca.jacobian(kap, s)

    et_MX = dGamma_ds
    en_MX = d2Gamma_ds2/ kap
    eb_MX = ca.cross(et_MX, en_MX)

    etBar_MX = d2Gamma_ds2
    enBar_MX = (1/ kap**3) * (kap**2 * d3Gamma_ds3 - d2Gamma_ds2 @ d3Gamma_ds3.T @ d2Gamma_ds2)
    ebBar_MX = (1/ kap) * ca.cross(dGamma_ds, d3Gamma_ds3)
    tau_MX =  ca.dot(en_MX, ebBar_MX) 
    tauBar_MX =  ca.jacobian(tau_MX, s)

    return kap, tau_MX, et_MX, en_MX, eb_MX, kapBar_MX, tauBar_MX, etBar_MX, enBar_MX, ebBar_MX 我有一个问题,你能不能教教我这些公式是怎么推导的,并且告诉我这个 ca.jacobian是在干嘛

1 Gpt回答

一、Frenet–Serret 坐标系基本公式

对于一个以弧长 s s s 为参数的平滑曲线 γ ( s ) \gamma(s) γ(s) ,其 Frenet–Serret 坐标系定义如下:

  1. 切向量

    t ( s ) = d γ d s \mathbf{t}(s) = \frac{d\gamma}{ds} t(s)=dsdγ

    如果曲线以弧长参数化,则 ∥ t ( s ) ∥ = 1 \|\mathbf{t}(s)\| = 1 t(s)=1

  2. 曲率
    曲率描述了曲线弯曲的程度,定义为第二阶导数的范数:

    κ ( s ) = ∥ d 2 γ d s 2 ∥ \kappa(s) = \left\|\frac{d^2\gamma}{ds^2}\right\| κ(s)= ds2d2γ

    在程序中用变量 kap 表示。

  3. 法向量
    法向量给出了曲线弯曲的方向,由二阶导数归一化得到:

    n ( s ) = d 2 γ d s 2 κ ( s ) \mathbf{n}(s) = \frac{\frac{d^2\gamma}{ds^2}}{\kappa(s)} n(s)=κ(s)ds2d2γ

    代码中用 en_MX = d2Gamma_ds2/kap 实现。

  4. 副法向量
    副法向量通过切向量和法向量的叉积定义:

    b ( s ) = t ( s ) × n ( s ) \mathbf{b}(s) = \mathbf{t}(s) \times \mathbf{n}(s) b(s)=t(s)×n(s)

    代码中用 eb_MX = ca.cross(et_MX, en_MX) 实现。

  5. Frenet–Serret 公式
    这些单位向量满足以下微分关系:

    t ′ ( s ) = κ ( s ) n ( s ) , n ′ ( s ) = − κ ( s ) t ( s ) + τ ( s ) b ( s ) , b ′ ( s ) = − τ ( s ) n ( s ) , \begin{aligned} \mathbf{t}'(s) &= \kappa(s) \mathbf{n}(s), \\ \mathbf{n}'(s) &= -\kappa(s) \mathbf{t}(s) + \tau(s) \mathbf{b}(s), \\ \mathbf{b}'(s) &= -\tau(s) \mathbf{n}(s), \end{aligned} t(s)n(s)b(s)=κ(s)n(s),=κ(s)t(s)+τ(s)b(s),=τ(s)n(s),

    其中 τ ( s ) \tau(s) τ(s) 是扭率(torsion),描述曲线如何扭转。


二、代码中公式的对应与推导

1. 计算导数

程序通过 ca.hessian 求解 B 样条插值得到的函数的导数。比如:

[d2GammaX_ds2, dGammaX_ds] = ca.hessian(x_ref_MX(s), s)
  • 一阶导数 d γ x d s \frac{d\gamma_x}{ds} dsdγx 用变量 dGammaX_ds 表示;
  • 二阶导数 d 2 γ x d s 2 \frac{d^2\gamma_x}{ds^2} ds2d2γx 用变量 d2GammaX_ds2 表示。

x x x y y y z z z 分量分别计算,然后用 ca.vertcat 将它们组合成向量:

d γ d s = [ d γ x d s d γ y d s d γ z d s ] (代码中为  d G a m m a _ d s ) \frac{d\gamma}{ds} = \begin{bmatrix} \frac{d\gamma_x}{ds} \\ \frac{d\gamma_y}{ds} \\ \frac{d\gamma_z}{ds} \end{bmatrix} \quad \text{(代码中为 } dGamma\_ds \text{)} dsdγ= dsdγxdsdγydsdγz (代码中为 dGamma_ds)

d 2 γ d s 2 = [ d 2 γ x d s 2 d 2 γ y d s 2 d 2 γ z d s 2 ] (代码中为  d 2 G a m m a _ d s 2 ) \frac{d^2\gamma}{ds^2} = \begin{bmatrix} \frac{d^2\gamma_x}{ds^2} \\ \frac{d^2\gamma_y}{ds^2} \\ \frac{d^2\gamma_z}{ds^2} \end{bmatrix} \quad \text{(代码中为 } d2Gamma\_ds2 \text{)} ds2d2γ= ds2d2γxds2d2γyds2d2γz (代码中为 d2Gamma_ds2)

同样地,三阶和四阶导数也被计算出来,记为 d3Gamma_ds3d4Gamma_ds4

2. 曲率和曲率导数

  • 曲率
    代码中:

    kap = ca.norm_2(d2Gamma_ds2)
    

    对应数学公式:

    κ = ∥ d 2 γ d s 2 ∥ \kappa = \left\| \frac{d^2\gamma}{ds^2} \right\| κ= ds2d2γ

  • 曲率的导数
    代码中:

    kapBar_MX = ca.jacobian(kap, s)
    

    这表示求 κ \kappa κ 关于 s s s 的导数:

    κ ˙ = d κ d s \dot{\kappa} = \frac{d\kappa}{ds} κ˙=dsdκ

    这里 ca.jacobian 用于计算函数 κ ( s ) \kappa(s) κ(s) s s s 的雅可比(即导数)。

3. 单位向量

  • 切向量
    代码中:

    et_MX = dGamma_ds
    

    对应公式:

    t ( s ) = d γ d s \mathbf{t}(s) = \frac{d\gamma}{ds} t(s)=dsdγ

    注意:如果路径已经以弧长参数化,则 ∥ t ( s ) ∥ = 1 \|\mathbf{t}(s)\|=1 t(s)=1

  • 法向量
    代码中:

    en_MX = d2Gamma_ds2 / kap
    

    对应公式:

    n ( s ) = γ ′ ′ ( s ) κ ( s ) \mathbf{n}(s) = \frac{\gamma''(s)}{\kappa(s)} n(s)=κ(s)γ′′(s)

  • 副法向量
    代码中:

    eb_MX = ca.cross(et_MX, en_MX)
    

    对应公式:

    b ( s ) = t ( s ) × n ( s ) \mathbf{b}(s) = \mathbf{t}(s) \times \mathbf{n}(s) b(s)=t(s)×n(s)

4. 单位向量的导数

代码中带有 Bar 的变量代表的是对 s s s 求导后的结果:

  • 切向量的导数

    etBar_MX = d2Gamma_ds2
    

    对应公式(由于 t = γ ′ ( s ) \mathbf{t} = \gamma'(s) t=γ(s)):

    t ˙ ( s ) = γ ′ ′ ( s ) \dot{\mathbf{t}}(s) = \gamma''(s) t˙(s)=γ′′(s)

    在 Frenet–Serret 公式中应满足 t ˙ = κ n \dot{\mathbf{t}} = \kappa \mathbf{n} t˙=κn,这与 γ ′ ′ ( s ) = κ n \gamma''(s) = \kappa \mathbf{n} γ′′(s)=κn 一致。

  • 法向量的导数

enBar_MX = (1/ kap**3) * (kap**2 * d3Gamma_ds3 - d2Gamma_ds2 @ d3Gamma_ds3.T @ d2Gamma_ds2)

该公式是从

n = γ ′ ′ ( s ) κ ( s ) \mathbf{n} = \frac{\gamma''(s)}{\kappa(s)} n=κ(s)γ′′(s)

s s s 求导后,通过商法则推导得到的结果。推导过程涉及到 γ ′ ′ ′ ( s ) \gamma'''(s) γ′′′(s) κ ˙ \dot{\kappa} κ˙ 的结合。

  • 副法向量的导数
     ebBar_MX = (1/ kap) * ca.cross(dGamma_ds, d3Gamma_ds3)
    
    对应公式为对 b = t × n \mathbf{b} = \mathbf{t} \times \mathbf{n} b=t×n 求导,结果中包含 γ ′ ( s ) \gamma'(s) γ(s) γ ′ ′ ′ ( s ) \gamma'''(s) γ′′′(s) 的叉积,再除以曲率 κ \kappa κ

5. 扭率及其导数

  • 扭率

    tau_MX = ca.dot(en_MX, ebBar_MX)
    

    对应公式:

    − τ ( s ) n ( s ) = b ˙ ( s ) -\tau(s)\mathbf{n}(s) = \dot{\mathbf{b}}(s) τ(s)n(s)=b˙(s)

    其中 b ˙ ( s ) \dot{\mathbf{b}}(s) b˙(s) 就是副法向量的导数,负号表示 n \mathbf{n} n的方向和 d b d s \frac{d\mathbf{b}}{ds} dsdb方向相反, τ \tau τ表示标量,只是大小

  • 扭率的导数

    tauBar_MX = ca.jacobian(tau_MX, s)
    

    表示求扭率 τ ( s ) \tau(s) τ(s) 关于 s s s 的导数:

    τ ˙ = d τ d s \dot{\tau} = \frac{d\tau}{ds} τ˙=dsdτ


三、ca.jacobian 的作用

  • ca.jacobian 是 CasADi 的一个函数,用于计算一个函数对给定变量的雅可比矩阵。

  • 对于一个标量函数 f ( s ) f(s) f(s),其雅可比矩阵就是该函数对 s s s 的导数,即:

    d f d s \frac{df}{ds} dsdf

  • 在本代码中:

    • kapBar_MX = ca.jacobian(kap, s) 计算的是曲率 κ ( s ) \kappa(s) κ(s) 关于 s s s 的导数 d κ d s \frac{d\kappa}{ds} dsdκ
    • tauBar_MX = ca.jacobian(tau_MX, s) 计算的是扭率 τ ( s ) \tau(s) τ(s) 关于 s s s 的导数 d τ d s \frac{d\tau}{ds} dsdτ

这样,我们就能够获得曲率和扭率变化的速率,这在动态路径跟踪和控制中是非常有用的信息。


四、总结

  1. 路径的导数

    • 一阶导数: γ ′ ( s ) \gamma'(s) γ(s)(切向量 t \mathbf{t} t
    • 二阶导数: γ ′ ′ ( s ) \gamma''(s) γ′′(s) 用于计算曲率 κ = ∥ γ ′ ′ ( s ) ∥ \kappa = \|\gamma''(s)\| κ=γ′′(s)
    • 三阶导数: γ ′ ′ ′ ( s ) \gamma'''(s) γ′′′(s) 用于计算法向量和导数
  2. Frenet-Serret 基

    • 切向量: t = γ ′ ( s ) \mathbf{t} = \gamma'(s) t=γ(s)
    • 法向量: n = γ ′ ′ ( s ) κ \mathbf{n} = \frac{\gamma''(s)}{\kappa} n=κγ′′(s)
    • 副法向量: b = t × n \mathbf{b} = \mathbf{t} \times \mathbf{n} b=t×n
  3. 导数及其雅可比

    • 曲率的导数: κ ˙ = d κ d s \dot{\kappa} = \frac{d\kappa}{ds} κ˙=dsdκca.jacobian(kap, s) 实现
    • 扭率: − n τ = b ˙ - \mathbf{n} \tau = \dot{\mathbf{b}} nτ=b˙ 。负号表示 n \mathbf{n} n的方向和 d b d s \frac{d\mathbf{b}}{ds} dsdb方向相反, τ \tau τ表示标量,只是大小
    • 扭率的导数: τ ˙ = d τ d s \dot{\tau} = \frac{d\tau}{ds} τ˙=dsdτca.jacobian(tau_MX, s) 实现
  4. ca.jacobian

    • 用于计算函数相对于某变量的偏导数或导数矩阵。在本例中,它用于求曲率和扭率关于进度 s s s 的导数。

这些公式与代码直接对应,带有 “Bar” 的变量表示对原始量关于 s s s 求导得到的结果。希望这些 LaTeX 公式和解释能帮助你更好地理解代码的数学推导过程。

6.9

0 GPT提问

扭率 为什么是tau_MX = ca.dot(en_MX, ebBar_MX),
是不是少了个负号,但是程序里面没有负号。
还有就是副法向量的导数是怎么求的
ebBar_MX = (1/ kap) * ca.cross(dGamma_ds, d3Gamma_ds3)

1 GPT回答

下面我来详细说明这段代码中扭率( τ \tau τ)和副法向量导数的推导思路,以及 ca.jacobian 的作用。


一、扭率的定义与符号约定

在经典的 Frenet–Serret 公式中,扭率通常定义:

  1. 定义为

    − n τ = d b d s - \mathbf{n} \tau = \frac{d\mathbf{b}}{ds} nτ=dsdb,负号表示 n \mathbf{n} n的方向和 d b d s \frac{d\mathbf{b}}{ds} dsdb方向相反, τ \tau τ表示标量,只是大小


二、副法向量的导数推导

给定 Frenet–Serret 基的定义:

  • 切向量:

    t = d γ d s \mathbf{t} = \frac{d\gamma}{ds} t=dsdγ

  • 法向量:

    n = γ ′ ′ ( s ) κ , κ = ∥ γ ′ ′ ( s ) ∥ \mathbf{n} = \frac{\gamma''(s)}{\kappa}, \quad \kappa = \left\|\gamma''(s)\right\| n=κγ′′(s),κ=γ′′(s)

  • 副法向量:

    b = t × n \mathbf{b} = \mathbf{t} \times \mathbf{n} b=t×n

对副法向量求导,根据叉积的导数法则:

d b d s = d t d s × n + t × d n d s \frac{d\mathbf{b}}{ds} = \frac{d\mathbf{t}}{ds} \times \mathbf{n} + \mathbf{t} \times \frac{d\mathbf{n}}{ds} dsdb=dsdt×n+t×dsdn

根据 Frenet–Serret 公式:

d t d s = κ n , d n d s = − κ t + τ b \frac{d\mathbf{t}}{ds} = \kappa \mathbf{n}, \quad \frac{d\mathbf{n}}{ds} = -\kappa \mathbf{t} + \tau \mathbf{b} dsdt=κn,dsdn=κt+τb

代入上式:
d b d s = ( κ n ) × n + t × ( − κ t + τ b ) = 0 + τ ( t × b ) = τ ( t × b ) \begin{aligned} \frac{d\mathbf{b}}{ds} &= (\kappa \mathbf{n}) \times \mathbf{n} + \mathbf{t} \times (-\kappa \mathbf{t} + \tau \mathbf{b}) \\ &= \mathbf{0} + \tau (\mathbf{t} \times \mathbf{b}) \\ &= \tau (\mathbf{t} \times \mathbf{b}) \end{aligned} dsdb=(κn)×n+t×(κt+τb)=0+τ(t×b)=τ(t×b)

而由于 t × b = − n \mathbf{t} \times \mathbf{b} = -\mathbf{n} t×b=n(遵循右手定则),故有:

d b d s = − τ   n \frac{d\mathbf{b}}{ds} = -\tau\, \mathbf{n} dsdb=τn
这个公式里面的负号是个方向,负号表示 n \mathbf{n} n的方向和 d b d s \frac{d\mathbf{b}}{ds} dsdb方向相反, τ \tau τ表示标量,只是大小

代码中是这样写的,为了后续用到,只用大小,不用方向。

tau_MX = ca.dot(en_MX, ebBar_MX)

tau的推导

来源tau_MX

来源tau_MX


三、副法向量导数的计算

代码中计算副法向量导数的部分为:

ebBar_MX = (1/ kap) * ca.cross(dGamma_ds, d3Gamma_ds3)

解释如下:

  • d Γ / d s d\Gamma/ds dΓ/ds 对应 t \mathbf{t} t(切向量),即 dGamma_ds
  • d 3 γ / d s 3 d^3\gamma/ds^3 d3γ/ds3 对应 γ ′ ′ ′ ( s ) \gamma'''(s) γ′′′(s),即 d3Gamma_ds3

在弧长参数化的情况下,副法向量的导数可以推导为:

d b d s = 1 κ ( t × γ ′ ′ ′ ( s ) ) \frac{d\mathbf{b}}{ds} = \frac{1}{\kappa}\left(\mathbf{t} \times \gamma'''(s)\right) dsdb=κ1(t×γ′′′(s))

这就是代码中用的公式:

ebBar_MX = 1 κ   ca.cross ( d G a m m a _ d s , d 3 G a m m a _ d s 3 ) \text{ebBar\_MX} = \frac{1}{\kappa}\, \text{ca.cross}(dGamma\_ds, d3Gamma\_ds3) ebBar_MX=κ1ca.cross(dGamma_ds,d3Gamma_ds3)

这个公式的推导基于对 b = t × n \mathbf{b} = \mathbf{t} \times \mathbf{n} b=t×n 求导,并利用 n = γ ′ ′ ( s ) κ \mathbf{n} = \frac{\gamma''(s)}{\kappa} n=κγ′′(s) 以及 t = γ ′ ( s ) \mathbf{t} = \gamma'(s) t=γ(s) 得到。


四、总结

  1. 关于扭率

    • 经典 Frenet–Serret 公式中常见的定义为 τ = − n ⋅ b ′ \tau = -\mathbf{n} \cdot \mathbf{b}' τ=nb,但也有定义为 τ = n ⋅ b ′ \tau = \mathbf{n} \cdot \mathbf{b}' τ=nb 的约定。代码中使用的是后一种定义,因此没有负号。
  2. 关于副法向量导数

    • 副法向量 b \mathbf{b} b 定义为 b = t × n \mathbf{b} = \mathbf{t} \times \mathbf{n} b=t×n
    • 其导数 d b d s \frac{d\mathbf{b}}{ds} dsdb 推导可得:
      d b d s = 1 κ ( t × γ ′ ′ ′ ( s ) ) \frac{d\mathbf{b}}{ds} = \frac{1}{\kappa}\left(\mathbf{t} \times \gamma'''(s)\right) dsdb=κ1(t×γ′′′(s))
    • 代码中写为:
      ebBar_MX = (1/ kap) * ca.cross(dGamma_ds, d3Gamma_ds3)
      
  3. ca.jacobian

    • ca.jacobian(f, s) 用于计算函数 f ( s ) f(s) f(s) 关于变量 s s s 的雅可比矩阵,即对 s s s 求导。代码中用于计算曲率和扭率的导数(如 kapBar_MXtauBar_MX)。

只要整个模型中保持一致的符号约定,即使与某些文献中有负号差异,也是可以接受的。关键在于系统内各个部分的定义和使用是一致的。

希望这能帮助你理解这些公式的推导思路以及代码中 ca.jacobian 的作用!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值