Evaluate a piecewise polynomial (spline)

Hi,

I have to evaluate a piecewise polynomial (PP) in the cost function of the solver, but I’m not sure how I can include that in the CasADi expression. The piecewise polynomial is the result of Matlab’s spline(…) function for a large amount of data. So in pure Matlab one would use ppval(…) for the evaluation at a certain value “x”. In my case “x” is a SX.sym from CasADi. Does anybody know how I could do that?

I’ve already tried to manually do the calculation (find the right interval with a for-loop, then compute the polynomial with the corresponding coefficients). But it seems like if-statements and for-loops don’t work with CasADi.

BR
Martin

1 Like

Hi Martin,

CasADi implements its own splines
https://web.casadi.org/docs/#using-lookup-tables
There is also a forum topic you should check out

Cheers,
Jonathan

Hi Jonathan,

CasADi implements its own splines

If I use CasADi splines I have the same problem as with ppval(…). The position where I evaluate the spline is an optimization variable (SX.sym). For example using the following lines of code

x = -1 : 0.1 : 1;
y = randn(size(x));

% state variable of dynamics equation
x_eval = SX.sym('x_eval'); 

pp_casadi = casadi.interpolant('pp', 'bspline', {x}, y);

% meaningless cost function just for demonstration
expr_ext_cost = pp_casadi(x_eval)^2;

results in the following error during code generation:

Error using casadi.Function/call (line 935)
.../casadi/core/function_internal.cpp:1821: 'eval_sx' not defined for BSplineInterpolant

Error in casadi.Function/paren (line 1763)
        res = self.call(varargin);

Error in casadi.Function/subsref (line 1744)
        [varargout{1:nargout}]= paren(self, s.subs{:});

Error in acadosNLPFormulation (line 46)
    expr_ext_cost = pp_casadi(x_eval)^2;

BR
Martin

Hi Martin,

CasADi splines have to be used with MX variables.
The following works for me:

import casadi.*

x = -1 : 0.1 : 1;
y = randn(size(x));

% state variable of dynamics equation
x_eval = MX.sym('x_eval'); 

% meaningless cost function just for demonstration
pp_casadi = casadi.interpolant('pp', 'bspline', {x}, y);
expr_ext_cost = pp_casadi(x_eval)^2;

Best,
Jonathan

Yes thanks, indeed it works with MX variables for me too. However, I also have to change all other variables of my optimization problem from SX to MX, otherwise I get another compilation error.

Is there a special reason why in the Matlab examples (except for the windturbine) all variables are SX? Does using MX increase computation times during MPC execution or something like that?

BR
Martin

One reason is that structure detection, especially simplification of expressions is not really possible for MX variables.
For example for the gnsf_irk integrator, the implicit DAE expression is automatically transformed into another structure, such that linear dependencies can be exploited in the integrator.
I developed this during my master thesis, see https://cdn.syscop.de/publications/Frey2019.pdf https://cdn.syscop.de/publications/Frey2018.pdf

I was also thinking implementing some basic structure detection for cost and constraint expressions in Matlab, where similar issues occur with MX.

Performance wise, MX should be better for vectorized operations. However, the conceptional idea of acados is to only generate the nonlinearities as CasADi functions and perform the linear algebra with BLASFEO. Thus, I think that the effects on performance are rather small, but one could investigate this.

Best,
Jonathan

Hi @FreyJo,

my problem is very related to this topic, so I hope you don’t mind me adding it to this conversation. I’m using ACADOS for an MPC tracking problem in Simulink and I’m basically struggling with how to pass a reference path to my Acados S-Function. The reference path could be a bunch of waypoints. Those waypoints could be interpolated in my S-Function in order to resample again with the same sampling frequency of my mpc problem and in this way to get the tracking error. Or, the other way would be to already compute the spline outside my S-Function.
However, that’s easier said than done…
For the first method, I could define MX objects for the waypoints, but how do I define the casadi splines inside my S-Function since it is not possible to create casadi.interpolant w.r.t MX or SX objects?
For the second method, how can I pass (if possible) functions like a bspline to my S-Function.
I would highly appreciate any help!

Best,
Miri

Hi @Miri,

I am not sure if I fully understand your problem.

Do you have a linear or nonlinear least square cost term?
It should be easy to pass the reference values to the S-Function.

Note, that I added a lot of flexibility to the Simulink interface recently, so please make sure, you use a version after this merge: https://github.com/acados/acados/pull/690

One possibility should be to have one S function for the spline that computes the references and pass those to the acados S-function, via parameters or y_ref.

Maybe, you can make a separate post and describe more precisely what you want to do and leave a reference to this one.

Best,
Jonathan