Skip to content

FAQ: how to work with parametric BSplines?

JacobDGrunnet edited this page Feb 15, 2023 · 8 revisions

TLDR: Use the casadi.bspline class if you need to parameterize a bspline LUT based on its coeffcients

To avoid fitting the spline on every invocation or you want to supply the spline coeffcients as a parameter you can use the parametric bspline class casadi.bspline. In this class the coefficients are parametric (Mx) and the knots are constants. You can thus parameterize your casadi expressions with the bspline coefficients as long as you keep the knots constant or rescale the BSpline basis and coefficients to fit your use-case.

To create a parametric BSpline first create an MX graph and wrap the expression in a casadi function.

Below is a simple matlab example

%Example showing parametric interpolation on a 2D spline
%z=(2*x)^2+y^2

%Degree of spline
d=3;

%Notice that you need to ensure sensible end conditions using for instance not a knot
x=linspace(-1,1,4);
y=linspace(-1,1,5);
xKnots = [ones(1,d)*x(1) x ones(1,d)*x(end)];
yKnots = [ones(1,d)*y(1) y ones(1,d)*y(end)];

%The coefficients have been pre-computed
coeff=[5.0000    2.2683    5.3659    3.3171    5.3659    2.2683    5.0000
       0.5778    0.1789    0.3772    0.0780    0.3772    0.1789    0.5778
       1.7333    0.5366    1.1317    0.2341    1.1317    0.5366    1.7333
       1.7333    0.5366    1.1317    0.2341    1.1317    0.5366    1.7333
       0.5778    0.1789    0.3772    0.0780    0.3772    0.1789    0.5778
       5.0000    2.2683    5.3659    3.3171    5.3659    2.2683    5.0000];

%Reshape coefficients to be a vector
coeff=reshape(coeff,[],1);

%Import casadi
import casadi.*

%Mx symbol corresponding to the dimension of spline
vSym=MX.sym('v',2);

%Coefficient vector as an MX symbol
coeffSym=MX.sym('coeff',numel(coeff));

%Create MX graph parameterized with the spline coefficients
splineMx=bspline(vSym, coeffSym, {xKnots, yKnots} , [d d], 1, struct());

%Create casadi function based on the Mx graph
splineFunc=casadi.Function('spline',{vSym,coeffSym},{splineMx},struct());

%Use the created spline casadi function
z=splineFunc([0.5,0.3333],coeff)

%Plot
XV=reshape(X,1,[]);
YV=reshape(Y,1,[]);
V=[XV;YV]';

zinterp=zeros(size(V,1),1);
for k=1:size(V,1)
    zinterp(k)=full(splineFunc(V(k,:)',coeff));
end

figure()
ZBsp=reshape(zinterp,size(X));
surf(X,Y,ZBsp)
hold on
mesh(X,Y,Z)
title('Casadi implementation of BSpline approximation')
Clone this wiki locally