Updating interpolation data after compile

I have a model that uses a lookup table as part of a nonlinear constraint. This is working well in Matlab, and solves correctly. Now I would like to look at a large number of different cases, where each case has different values in the lookup table. So far I haven’t been able to figure out how to update the interpolation data without rebuilding the ocp object. This is an issue because the actual solve is much faster than the compile, so recompiling is costing me a lot of time with many repetitions. I tried passing the new data as a parameter, but Casadi’s interpolation only accepts numerical inputs, not symbolic.

Is it possible to update interpolation data inside a model without recompiling?

Hi @aknight0,

Are you using the interpolant function of CasADi with the bspline plugin?
https://web.casadi.org/docs/#using-lookup-tables
The documentation says that the constructor “expects a set of grid points with the corresponding numerical values”.

In acados, only parameter values and numerical data, such as constraint bounds and weighting matrices, are supposed to be changed after creating an OCP solver.
Since it is not possible to create a CasADi interpolant where the data to be fitted are inputs, this is the actual limitation.

Unfortunately, I think what you are trying to do is thus not possible.

Best,
Jonathan

Understood, I’ll have to think of an alternative approach then. Thanks though.

Hi @aknight0,

I just learned that the data to be interpolated actually can be made parametric, so you should be able to change it.

Here is a snippet of Python Code that will work with CasADi 3.5.1

Thanks to @zanellia

from casadi import *

N_refpath = 10
ref_path_s = np.linspace(0, 1, N_refpath)
p = MX.sym('p', N_refpath, 1)
x = MX.sym('x', 1, 1)

interpol_path_x = casadi.interpolant("interpol_spline_x", "bspline", [ref_path_s])
interp_exp = interpol_path_x(x, p)
interp_fun = Function('interp_fun', [x, p], [interp_exp])

# test interp_fun

x_test = 0.5
p_test = np.linspace(0, 1, N_refpath)
y_test = interp_fun(x_test, p_test)
print(y_test)

p_test = np.linspace(0, 2, N_refpath)
y_test = interp_fun(x_test, p_test)
print(y_test)

# generate C code
interp_fun.generate() 

Thanks for the reply, this is exactly what I want to do. I’m having trouble getting the above method to work in Matlab though, the interpolant function throws an error if I try to provide only three arguments instead of four. Is this a Python only feature, or do I need to update the version of Casadi that came with Acados?

Figured it out, I just needed to update Casadi to the latest version. Brilliant!

Follow up question, is it possible to pass a matrix to a parameter using the set(‘p’,value) function, or does this syntax only support vectors? For example if I want to update the data for multiple lookup tables.

1 Like