# CasADi-driven MPC in Simulink (part 2)

Estimated reading time: 3 minutesIn this post, we have a new take on nonlinear MPC in Simulink using CasADi.

# Interpreter mode

In an earlier post on MPC in Simulink, we used an interpreted 'Matlab system' block in the simulink diagram. This is flexible, but slow because of interpreter overhead.

# code-generation mode

In an earlier post on S-Functions, we showed how Casadi-generated C code can be embedded efficiently in a Simulink diagram using S-functions.
The result is fast, but has restrictions: only `SqpMethod`

combined with `Qrqp`

or `Osqp`

solver can be code-generated (as of 3.5), not e.g. `ipopt`

.

# C api mode

Here, we will work with CasADi's C API (new since 3.5) and make Ipopt run within Simulink.

## Constructing a Function

After constructing an Ipopt solver, we create a $\mathbb{R}^2$ symbol to represent current state, and call the solver with symbolic lower and upper variable bounds:

```
solver = nlpsol('solver', 'ipopt', prob, options);
s0 = MX.sym('s0',2);
lbw_sym = MX(lbw);
ubw_sym = MX(ubw);
lbw_sym(1:2) = s0;
ubw_sym(1:2) = s0;
sol_sym = solver('x0', w0, 'lbx', lbw_sym, 'ubx', ubw_sym,...
'lbg', lbg, 'ubg', ubg);
```

The resultant expression graph, which has the NLP solver embedded, is used to create a Function mapping from current state to optimal control action to be applied:

`f = Function('f',{s0},{sol_sym.x(3)});`

Next, we save the Function to the disk. It should be noted that the steps up to here could as well be done from Python, or using different modeling techniques (e.g. Opti).

`f.save('f.casadi');`

## C API

Classic CasADi codegen gives you an API with C functions for querying dimensions of inputs and outputs and evaluating. Those C functions are prefixed with the CasADi Function name:

```
#include "f.h"
int_T n_in = f_n_in();
int_T n_out = f_n_out();
int_T sz_arg, sz_res, sz_iw, sz_w;
f_work(&sz_arg, &sz_res, &sz_iw, &sz_w);
f(arg,res,iw,w,0);
```

The C API mirrors this syntax, but uses an identifier argument instead of prefixing:

```
#include <casadi/casadi_c.h>
int_T n_in = casadi_c_n_in_id(id);
int_T n_out = casadi_c_n_out_id(id);
casadi_c_work_id(id, &sz_arg, &sz_res, &sz_iw, &sz_w);
```

This identifier is obtained from loading the saved file from disk, and specifying a particular Function by name:

```
int ret = casadi_c_push_file("f.casadi");
int id = casadi_c_id("f");
```

Calling the function involves checking out and releasing thread-local memory:

```
int mem = casadi_c_checkout_id(id);
casadi_c_eval_id(id, arg, res, iw, w, mem);
casadi_c_release_id(id, mem);
```

## Compilation

Different from code-generation, our S-function is still dependent on the CasADi runtime.

We'll need to compile the S-function using appropriate include and link flags:

```
lib_path = GlobalOptions.getCasadiPath();
inc_path = GlobalOptions.getCasadiIncludePath();
mex('-v',['-I' inc_path],['-L' lib_path],'-lcasadi', 'casadi_fun.c')
```

# Conclusion

With the above ingredients, one can embed arbitrary CasADi Functions into Simulink with minimal overhead. A fully functional example is available: do_demo.m (run this file first), casadi_fun.c, mpc_demo.slx