参考线平滑-CostThetaSmoother-Ipopt

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

1. 优化目标

参考线平滑-CostThetaSmoother-Ipopt_第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;
}

下面的代码是通过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;
}

你可能感兴趣的:(Auto,Driving,python,算法)