cvxgrp / cvxpygen

Code generation with CVXPY
Apache License 2.0
128 stars 17 forks source link

Tracking MPC #56

Open gibor1992 opened 1 day ago

gibor1992 commented 1 day ago

Hi guys! I'm trying to generate the code for a Tracking Linear MPC with the following code:


# define dimensions
m = 1  # inputs
n = 2  # states
H = 10  # prediction horizon

# define variables
X = cp.Variable((n, H + 1), name='X')  # t=0...H state variable
U = cp.Variable((m, H), name='U')  # t=0...H-1 input variable
sc_U = cp.Variable((1,), name='sc_U')  # t=0...H-1 soft constr on input
sc_X2 = cp.Variable((1,), name='sc_X2')  # t=0...H-1 soft constr on state

# define parameters
Q = cp.Parameter((n, n), name='Q', PSD=True)
Qf = cp.Parameter((n, n), name='Qf', PSD=True)
R = cp.Parameter((m, m), name='R', PSD=True)

A = cp.Parameter((n, n), name='A')
B = cp.Parameter((n, m), name='B')

x0 = cp.Parameter(n, name='x0')
u_prev = cp.Parameter((1, 1), name='u_prev')
U_MAX = cp.Parameter((1, 1), name='U_MAX', nonneg=True)

x2_max = cp.Parameter((1, H), name='x2_max')
x2_min = cp.Parameter((1, H), name='x2_min')
X_ref = cp.Parameter((n, H), name='X_ref')

lambda_u = cp.Parameter((1, 1), name='lambda_u')  # weight on constraint violation.
lambda_z2 = cp.Parameter((1, 1), name='lambda_z2')  # weight on constraint violation.

#define cost function 
cost = 0.0
constr =[]
constr += [X[:, 0] == x0]

for t in range(H-1):
    cost += cp.quad_form(U[:, t], R)
    cost += cp.quad_form(X_ref[:, t] - X[:, t+1], Q)
    constr += [X[:, t + 1] == A @ X[:, t] + B @ U[:, t]]
    constr += [ cp.abs(U[:,t]) <= U_MAX ] 
    constr += [-X[1,t] <= -x2_min[0,t]]
    constr += [ X[1,t] <=  x2_max[0,t]]

cost += cp.quad_form(X_ref[:, H-1] - X[:, H], Qf)

print(cost)
print(constr)

# define problem
problem = cp.Problem(cp.Minimize(cost), constr)
print("Prob is DCP:", problem.is_dcp())
# generate code 
from cvxpygen import cpg
cpg.generate_code(problem, code_dir='DIntMPC', wrapper=False) 

However, despite i check that is a DCP problem, it returns me this message:

Prob is DCP: True
Generating code with CVXPYgen ...
Execution error
DPPError: You are solving a parameterized problem that is not DPP. Because the problem is not DPP, subsequent solves will not be faster than the first one. For more information, see the documentation on Disciplined Parametrized Programming, at https://www.cvxpy.org/tutorial/dpp/index.html

How can I solve this type of problem? Thanks in advance, Giulio

maxschaller commented 1 day ago

Hi Giulio,

Your problem is required to be DCP and DPP, which imposes a few extra rules on top of DCP. In short, all parameters should enter your expressions in an affine way.

In your case, the quadratic forms make the problem non-DPP. The standard trick here is to replace something like

cp.quad_form(U[:, t], R) with cp.sum_squares(L.T @ U[:, t]),

where L is the Cholesky factor of R. When assigning the value of the parameter L you can use np.linalg.cholesky.