SNOPT 退出条件 41

Exit condition 41 on SNOPT

我正在尝试 运行 使用 SNOPT 进行优化。

现在,当我 运行 它时,我始终得到退出条件 41。

我已将以下参数添加到求解器:

prog.SetSolverOption(solver.solver_id(),"Function Precision","1e-6")
prog.SetSolverOption(solver.solver_id(),"Major Optimality Tolerance","1e-3")
prog.SetSolverOption(solver.solver_id(),"Superbasics limit","600")
#print("Trying to Solve")
result = solver.Solve(prog)
print(result.is_success())

但我仍然满足于相同的退出条件。

错误似乎来自我正在使用的插值函数。 (当我删除它时,我不再收到错误)。

t, c, k = interpolate.splrep(sref, kapparef, s=0, k=3)

kappafnc = interpolate.BSpline(t, c, k, extrapolate=False)

我认为这是导致问题的函数:

  def car_continous_dynamics(self, state, force, steering):
        beta = steering
        s = state[0]
        #print(s)
        n = state[1]
        alpha = state[2]
        v = state[3]
        #State = s, n, alpha , v
        #s= distance along the track, n = perpendicular distance along the track
        #alpha = velocity angle relative to the track
        #v= magnitude of the velocity of the car

        s_val = 0
        if s.value() >0:
          s_val = s.value()
          
        
        Cm1 = 0.28
        Cm2 = 0.05
        Cr0 = 0.011
        Cr2 = 0.006
        m = 0.043
        phi_dot = v*beta*15.5
        Fxd = (Cm1 - Cm2 * v) * force - Cr2 * v * v - Cr0 *tanh(5 * v)
        s_dot = v*cos(alpha+.5*beta)/(1)##-n*self.kappafunc(s_val))
        n_dot= v*sin(alpha+.5*beta)
        alpha_dot = phi_dot #-s_dot*self.kappafunc(s_val)
        v_dot=Fxd/m*cos(beta*.5)

        # concatenate velocity and acceleration
        #print(s_dot)
        #print(n_dot)
        #print(alpha_dot)
        #print(v_dot)
        state_dot = np.array((s_dot,n_dot,alpha_dot,v_dot))
        #print("State dot")

        #print(state_dot.dtype.name)
        #print(state_dot)
        #print(state_dot)
        return state_dot
``

在 SNOPT 中调试 INFO 41 通常具有挑战性,它通常是由一些错误的梯度引起的(但也可能是由于问题真的很难优化)。

你应该检查你的梯度是否表现良好。我看到你有

s_val = 0
if s.value() >0:
    s_val = s.value()

有两个潜在的问题

  1. 你的 s 带有梯度(你可以检查 s.derivatives(),它有非零梯度),但是当你计算 s_val 时,这是一个 float没有渐变的对象。因此你失去了梯度信息。
  2. s_val 在 0 处不可微。

我会在你的函数中使用 s 而不是 s_val(没有分支 if s.value() > 0)。并且还添加了一个约束 s>=0 by

prog.AddBoundingBoxConstraint(0, np.inf, s)

有了这个边界框约束,SNOPT保证在每次迭代中,is的值总是非负的。