• 参考线平滑-CostThetaSmoother-Ipopt


    CostThetaSmootherApollo中离散点参考线平滑方法的一种。

    1. 优化目标

    在这里插入图片描述

    1.1 平滑性

    参考线平滑的首要目标当然是平滑性,使用向量 P 1 P 2 ⃗ \vec{P_1 P_2} P1P2 P 2 P 3 ⃗ \vec{P_2 P_3} P2P3 之间夹角的余弦值来表示,显然 cos ⁡ θ \cos{\theta} cosθ越小,三个点 P 1 , P 2 , P 3 P_1,P_2,P_3 P1,P2,P3越接近一条直线,越平滑。因为 θ \theta θ越接近 0 0 0 cos ⁡ θ \cos{\theta} cosθ越大,所以应该使 − cos ⁡ θ -\cos{\theta} cosθ越小。
    J s m o o t h = − ∑ i = 2 N − 1 cos ⁡ θ i = − ∑ i = 2 N − 1 P i − 1 P i ⃗ ⋅ P i P i + 1 ⃗ ∣ P i − 1 P i ⃗ ∣ ∣ P i P i + 1 ⃗ ∣ = − ∑ i = 2 N − 1 ( x i − x i − 1 ) ( x i + 1 − x i ) + ( y i − y i − 1 ) ( y i + 1 − y i ) ( x i − 1 − x i ) 2 + ( y i − 1 − y i ) 2 ( x i + 1 − x i ) 2 + ( y i + 1 − y i ) 2 (1-1) J_{smooth} = - \sum^{N-1}_{i=2} \cos{\theta_i} = - \sum^{N-1}_{i=2} \frac{\vec{P_{i-1} P_i} \cdot \vec{P_i P_{i+1}}} {|\vec{P_{i-1} P_i}| |\vec{P_i P_{i+1}}|} = - \sum^{N-1}_{i=2} \frac{(x_i - x_{i-1}) (x_{i+1} - x_i) + (y_i - y_{i-1}) (y_{i+1} - y_i)} {\sqrt{(x_{i-1} - x_i)^2 + (y_{i-1} - y_i)^2} \sqrt{(x_{i+1} - x_i)^2 + (y_{i+1} - y_i)^2}} \tag{1-1} Jsmooth=i=2N1cosθi=i=2N1Pi1Pi ∣∣PiPi+1 Pi1Pi PiPi+1 =i=2N1(xi1xi)2+(yi1yi)2 (xi+1xi)2+(yi+1yi)2 (xixi1)(xi+1xi)+(yiyi1)(yi+1yi)(1-1)

    1.2 几何性

    平滑后的参考线,希望能够保留原始道路的几何信息,不会把弯道的处的参考线平滑成一条直线。使用平滑后点与原始点的距离来表示。
    J d e v i a t i o n = ∑ i = 1 N ∣ P r , i P i ⃗ ∣ 2 = ∑ i = 1 N ( ( x i − x i , r ) 2 + ( y i − y i , r ) 2 ) (1-2) J_{deviation} = \sum^N_{i=1} | \vec{P_{r,i} P_i}|^ 2 = \sum^N_{i=1} ( (x_i - x_{i,r})^ 2 + (y_i - y_{i,r})^ 2 ) \tag{1-2} Jdeviation=i=1NPr,iPi 2=i=1N((xixi,r)2+(yiyi,r)2)(1-2)

    1.3 均匀性

    平滑后的参考线的每两个相邻点之间的长度尽量均匀一直。
    J l e n g t h = ∑ i = 1 N − 1 ∣ P i P i + 1 ⃗ ∣ 2 = ∑ i = 1 N − 1 ( ( x i + 1 − x i ) 2 + ( y i + 1 − y i ) 2 ) (1-3) J_{length} = \sum^{N-1}_{i=1} | \vec{P_i P_{i+1}}|^2 = \sum^{N-1}_{i=1} ( (x_{i+1} - x_i)^2 + (y_{i+1} - y_i)^2 ) \tag{1-3} Jlength=i=1N1PiPi+1 2=i=1N1((xi+1xi)2+(yi+1yi)2)(1-3)

    因此,参考线平滑的优化目标可以定义为:
    J = w s m o o t h ∗ J s m o o t h + w d e v i a t i o n ∗ J d e v i a t i o n + w l e n g t h ∗ J l e n g t h (1-4) J = w_{smooth} * J_{smooth} + w_{deviation} * J_{deviation} + w_{length} * J_{length} \tag{1-4} J=wsmoothJsmooth+wdeviationJdeviation+wlengthJlength(1-4)

    2. 约束条件

    只考虑边界约束,即:
    x i , l o w e r ≤ x i ≤ x i , u p p e r y i , l o w e r ≤ y i ≤ y i , u p p e r (2-1) x_{i,lower} \leq x_i \leq x_{i,upper} \\ y_{i,lower} \leq y_i \leq y_{i,upper} \tag{2-1} xi,lowerxixi,upperyi,loweryiyi,upper(2-1)
    可以转化为:
    x i , r − b o u n d ≤ x i ≤ x i , r + b o u n d y i , r − b o u n d ≤ y i ≤ y i , r + b o u n d (2-2) x_{i,r} - bound \leq x_i \leq x_{i,r} + bound \\ y_{i,r} - bound \leq y_i \leq y_{i,r} + bound \tag{2-2} xi,rboundxixi,r+boundyi,rboundyiyi,r+bound(2-2)
    对参考线的起点和终点进行约束,令其等于原始参考线上的点:
    x 1 , r ≤ x 1 ≤ x 1 , r y 1 , r ≤ y 1 ≤ y 1 , r (2-3) x_{1,r} \leq x_1 \leq x_{1,r} \\ y_{1,r} \leq y_1 \leq y_{1,r} \tag{2-3} x1,rx1x1,ry1,ry1y1,r(2-3)

    3. Ipopt

    根据Ipopt求解器使用要求,需要求解梯度向量函数、雅可比矩阵和黑森矩阵。需要注意的是,在Apollo中通过配置可以使用ADOL-C自动求梯度向量函数、雅可比矩阵和黑森矩阵,也可以自己求解。但是Apollo这里的代码实现有问题,在不使用ADOL-C时,cost function代码中没有 J l e n g t h J_{length} Jlength优化项,并且 J d e v i a t i o n J_{deviation} Jdeviation项少了权重系数。

    bool CosThetaIpoptInterface::eval_f(int n, const double* x, bool new_x,
                                        double& obj_value) {
      CHECK_EQ(static_cast(n), num_of_variables_);
      // 使用ADOL-C自动求解优化目标函数
      if (use_automatic_differentiation_) {
        eval_obj(n, x, &obj_value);
        return true;
      }
    
      obj_value = 0.0;
      for (size_t i = 0; i < num_of_points_; ++i) {
        size_t index = i << 1;
        // 缺少了权重系数
        obj_value +=
            (x[index] - ref_points_[i].first) * (x[index] - ref_points_[i].first) +
            (x[index + 1] - ref_points_[i].second) *
                (x[index + 1] - ref_points_[i].second);
      }
      for (size_t i = 0; i < num_of_points_ - 2; i++) {
        size_t findex = i << 1;
        size_t mindex = findex + 2;
        size_t lindex = mindex + 2;
        obj_value -=
            weight_cos_included_angle_ *
            (((x[mindex] - x[findex]) * (x[lindex] - x[mindex])) +
             ((x[mindex + 1] - x[findex + 1]) * (x[lindex + 1] - x[mindex + 1]))) /
            std::sqrt((x[mindex] - x[findex]) * (x[mindex] - x[findex]) +
                      (x[mindex + 1] - x[findex + 1]) *
                          (x[mindex + 1] - x[findex + 1])) /
            std::sqrt((x[lindex] - x[mindex]) * (x[lindex] - x[mindex]) +
                      (x[lindex + 1] - x[mindex + 1]) *
                          (x[lindex + 1] - x[mindex + 1]));
      }
      // 缺少了点之间线段长度均匀紧凑的优化项
      return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    下面的代码是通过ADOL-C求解的,可见是完全按照第一部分叙述的优化目标计算的。

    /** Template to return the objective value */
    template 
    bool CosThetaIpoptInterface::eval_obj(int n, const T* x, T* obj_value) {
      *obj_value = 0.0;
      for (size_t i = 0; i < num_of_points_; ++i) {
        size_t index = i << 1;
        *obj_value +=
            weight_anchor_points_ *
            ((x[index] - ref_points_[i].first) * (x[index] - ref_points_[i].first) +
             (x[index + 1] - ref_points_[i].second) *
                 (x[index + 1] - ref_points_[i].second));
      }
      for (size_t i = 0; i < num_of_points_ - 2; ++i) {
        size_t findex = i << 1;
        size_t mindex = findex + 2;
        size_t lindex = mindex + 2;
        *obj_value -=
            weight_cos_included_angle_ *
            (((x[mindex] - x[findex]) * (x[lindex] - x[mindex])) +
             ((x[mindex + 1] - x[findex + 1]) * (x[lindex + 1] - x[mindex + 1]))) /
            (sqrt((x[mindex] - x[findex]) * (x[mindex] - x[findex]) +
                  (x[mindex + 1] - x[findex + 1]) *
                      (x[mindex + 1] - x[findex + 1])) *
             sqrt((x[lindex] - x[mindex]) * (x[lindex] - x[mindex]) +
                  (x[lindex + 1] - x[mindex + 1]) *
                      (x[lindex + 1] - x[mindex + 1])));
      }
    
      // Total length
      for (size_t i = 0; i < num_of_points_ - 1; ++i) {
        size_t findex = i << 1;
        size_t nindex = findex + 2;
        *obj_value +=
            weight_length_ *
            ((x[findex] - x[nindex]) * (x[findex] - x[nindex]) +
             (x[findex + 1] - x[nindex + 1]) * (x[findex + 1] - x[nindex + 1]));
      }
      return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    ciscoRV110W(强网杯2020)
    【JavaSE】关于多态那些事儿
    【LeetCode:2586. 统计范围内的元音字符串数 | 模拟】
    FFmepg使用指南
    Elasticsearch面试题
    Git 从了解到精通(2)分支管理及代码冲突和Stashing
    nginx负载均衡(动静分离)
    java 转换excel日期格式
    MySQL索引底层数据结构与算法
    真卷,隔壁半夜房间还亮着灯,原来在偷偷学习分布式服务框架
  • 原文地址:https://blog.csdn.net/mpt0816/article/details/127668492