do-mpc / do-mpc

Model predictive control python toolbox
https://www.do-mpc.com/
GNU Lesser General Public License v3.0
959 stars 178 forks source link

Using output of the model in objective function #90

Closed sandeepparameshwara closed 3 years ago

sandeepparameshwara commented 3 years ago

Hello, I am a new user of this library and i find it very interesting. However, I have a query. I need to use optimization algorithm of this library. I already have the model as FMU (Functional Mockup unit). It is like a black box, all physics are inside the model. I am able to provide input and read the output from it. Hence, in the place of simulator, I want to use my FMU. That means, I will be reading the output of the model but not all states. do-mpc requires objective function in terms of declared states and inputs. I want my objective function to be in terms of inputs and outputs (not states). That means, I also want to set bounds on my outputs y(t) not on states. So, do I have an option to use the library in my case? To be clear, my state space model is of the form

d/dt(x) = A*x(t) + B*u(t)
y(t) =  C*x(t) + D*u(t)

My main optimization block looks something like this:

for k in range(100):
    u0 = mpc.make_step(x0)
    y_next = #provide u0 to FMU and read FMU outputs y_next 

The output of my FMU is y(t), this y(t) should be used in optimization algorithm in lterm and mterm I just need to develop the MPC controller and actually want to integrate the controller with the real model, not the simulator. So, I am confused in closing the simulation loop.

Any suggestions are welcome, sorry if I sound very ignorant here. Sandeep

4flixt commented 3 years ago

Hi Sandeep,

to close the loop you will need to use a state-estimator. Basically a function that takes your measurement and estimates the matching states. You can read up on the the "Kalman Filter" which is a standard tool for linear systems.

Currently, do-mpc has only the much more advanced moving horizon estimator (MHE) implemented for that task (useful for complex non-linear systems). We aim to add the Kalman Filter (and some variants) in a future update. For your simple task I would recommend to use a Kalman Filter (either self implemented which shouldn't be too hard given the state-space model (A,B,C,D) or from some other toolbox).

Regarding your second question "how can I add the outputs in the cost function"? Hopefully your outputs are some functional transformation of the states (and inputs, parameters, ...). You can thus just implement that function e.g. with set_meas. After the model creation your measurement expressions are available from the model as model.y. You can use that to formulate the objective function and set constraints with set_nl_cons.

Hope that helps! If you are satisfied with the answer feel free to close the issue :)

Best, Felix

sandeepparameshwara commented 3 years ago

Thank you. It helps. I will close this now and will open a separate issue if needed in future.. :+1:

sandeepparameshwara commented 3 years ago

Hi, sorry to reopen this, but I am facing this problem where I am getting the error:

Traceback (most recent call last):
  File "/home/sandeep/Master_Thesis/Python/MPC_Controller.py", line 43, in <module>
    mpc.set_objective(mterm=mterm,lterm=lterm)
  File "/home/sandeep/anaconda3/lib/python3.8/site-packages/do_mpc/controller.py", line 473, in set_objective
    assert set(symvar(mterm)).issubset(set(symvar(vertcat(_x, _p)))), 'mterm must be solely a function of _x and _p.'
AssertionError: mterm must be solely a function of _x and _p.

In the objective function, i need mterm = (y-yr)'Q(y-yr) and lterm=mterm I set the measurement and cost like this:

_x = model.set_variable(var_type='_x',var_name='x',shape=(24,1))
model.set_meas('y_out',C@_x)
Q = diag([1,1,1,1,1,1])
R = diag([1,1,1,1])
yr = SX([50,50,50,0,0,0])
model.setup()
_y =model.y
mterm = transpose(_y-yr)@Q@(_y-yr)
lterm = transpose(_y-yr)@Q@(_y-yr)
rterm = transpose(_u)@R@_u
mpc.set_objective(mterm=mterm,lterm=lterm)
mpc.set_rterm(u=np.array([[1,1,1,1]]))

Whats the problem here?

4flixt commented 3 years ago

Hi Sandeep,

the problem is that the mterm must solely be a function of the states and parameters as the error states. I see that your measurement is just a function of the states but in this particular case do-mpc cannot know that because measurements in general can be a function of e.g. the inputs (e.g. y = Ax+Bu). I see that you only have y=Cx so theoretically it would work.

To make it work in practice you could do the following:

# Don't use set_meas here.
y = C@_x 
# now you can write:
mterm = transpose(_y-yr)@Q@(_y-yr)
lterm = transpose(_y-yr)@Q@(_y-yr)

on a sidenote: you can also do write (y-yr).T to transpose.

Best, Felix