scipy 简单不等式约束打破QP问题(控制分配)

2ic8powd  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(151)

优化问题:* 仅用于上下文,并非严格需要。* 使用SciPy的“最小化”,该代码是在给定作用于船舶的环境力的情况下,将最佳控制力分配给船舶上的推进器(风、波浪和海流)在3个自由度中的纵荡、横荡和偏航,以保持船舶的位置 (对动力定位很重要).本船有4个推进器,1台定角推进器(隧道)和3个旋转推进器(方位角)。固定推进器在一个方向上有一个力(x1)和旋转推进器具有在两个方向x和y上的力,作为变量对实现(x2,x3),(x4,x5),(x6,x7)。* 例如,x2和x3分别是用于旋转推进器1的x和y方向上的力。* 对于3个DOF也存在3个松弛变量以确保解。

Problem on standard form

编程问题:我想通过对其中一个推进器实施不等式约束来限制它的力,但通过实施约束“ineq 1”,所有输出都最小化为零。该约束应限制x1,非常简单,如下所示:(x1〈x1_最大值)随访:“minimize”似乎忽略了约束字典中的第一个约束,不管它是等式约束还是不等式约束。但是,第二个约束仍然有效。
仅具有等式约束的输出Correct output
中断不等式约束的输出Incorrect output with inequality

"我所尝试的是"

  • ...尝试不同的算法
  • ...测试约束中的每个正/负组合
  • 使用数组/向量A,如标准形式A*x〈B,而不仅仅是x[0]
  • ...使用数字代替fmax[0]
  • ...尝试了其他设计变量及其组合
    代码

在第42行中的“cons 1”和“cons 2”之间切换,查看不同的结果。

import numpy as np
from scipy.optimize import minimize

# Parameters

nf  = 1         # No. of fixed thrusters
nr  = 3         # No. of rotating thrusters
nt  = nf + 2*nr # No. of actuators
ns  = 3         # No. of slack variables (slacks)
n   = nt + ns   # Design variables
Lx  = np.array([30.5, 22.25, -35.5, -35.5])         # Thruster position
W   = np.diag([1, 1, 1, 1, 1, 1, 1])                # Weighting for thrusters
Q   = np.diag([1, 1, 1])*5000                       # Weighting for slacks
Te  = np.array([[0,1,0,1,0,1,0],                    # Thrust config. matrix
                [1,0,1,0,1,0,1],
                [Lx[0],0,Lx[1],0,Lx[2],0,Lx[3]]])
fmax = np.array([ 50000,  60000,  75000,  75000])

tau = np.array([50000,35000,0]) # Environmental forces in surge, sway & yaw
x0 = np.zeros(n)

# Problem definition

def obj(x):
    fe = x[:nt]
    s  = x[nt:]
    return fe.transpose()@W@fe + s.transpose()@Q@s

def eqcon(x):
    fe = x[:nt]
    s  = x[nt:]
    return tau + s - Te@fe # = 0

def ineq1(x):
    return fmax[0] - x[0] # > 0

cons1 = {'type': 'eq',   'fun': eqcon}

cons2 = {'type': 'eq',   'fun': eqcon,
         'type': 'ineq', 'fun': ineq1}

# Computing

opt = {'disp': True}
res = minimize(obj, x0, method='SLSQP', constraints=cons2, options=opt)

# Debugging

print("Environmental forces (surge, sway & yaw): ", tau)
print("Forces: ", np.round(res.x[:nt],1))
print("Slacks: ", np.round(res.x[nt:],1))
print(f"Thruster 1 has angle 90.00 with force {res.x[0]/1000:0.2f} kN")

angles = np.zeros(nr)
ux = res.x[nf:nt][::2]      # Every other force element in x for azimuth: ux2, ux3, ...
uy = res.x[nf:nt][1:][::2]  # uy2, uy3, ...

for i in range(nr):
    angles[i] = np.arctan2(uy[i], ux[i]) * 180 / np.pi
    print(f"Thruster {nf+i+1} has angle {angles[i]:0.2f} with force {np.sqrt(ux[i]**2+uy[i]**2)/1000:0.2f} kN")

有什么想法吗?

ulmd4ohb

ulmd4ohb1#

约束应为字典列表,因此使用

cons2 = [{'type': 'eq',   'fun': eqcon},
         {'type': 'ineq', 'fun': ineq1}]

应该可以解决你的问题。也就是说,字典中的键应该是唯一的。否则,你就不能通过不明确的键来访问字典中的特定值。

相关问题