Interpolate points on 2D mapping

38 views (last 30 days)
Derek
Derek on 11 Nov 2014
Edited: Derek on 21 Nov 2014
I am taking data that essentially generates a mapping between two, 2D sets of variables, in my case voltage (v1,v2) and position (x,y). Each pair of (v1,v2) values maps uniquely to an (x,y) pair, but does so in a non-linear fashion. I do not have an analytic function that follows this map, so what I do instead is I output a evenly spaced array of voltage values and record the resultant (x,y) positions for each voltage pair. Thus I build a numerical map between the two variable sets. My problem now is, I would like to use an interpolation method (e.g. spline, bilinear, or whatever) to artificially resolve the mapping of intermediate voltages to positions.
An example mapping might look like:
(v1,v2) -> (x,y)
(-1,0) -> (-14,-2)
(0,0) -> (0,0)
(1,0) -> (13.5,-1)
(-1,1) -> (-13,7)
(0,1) -> (0.5,8)
(1,1) -> (14,7)
(-1,2) -> (-14,12)
(0,2) -> (1,11)
(1,2) -> (14.5,11)
Then I would want to somehow interpolate this map to get what the positions for intermediate voltages would be, e.g. every 0.5 volt step.
Intuitively, this seems like a trivially easy problem. I have the map already and MATLAB has a million fitting functions, so I would think this is a three-lines-of-code sort-of problem. However, I just can't seem to find what I'm looking for. When I just spline fit the average x and y behavior separately (i.e. x(v1) averaged over horizontal slices and y(v2) averaged over vertical slices), I am able to match the map OK, but it doesn't catch the subtle variation over the map. The interp2 function kind of does what I want but it is for functions of two variables, i.e. Z(X,Y), not for a 2D mapping between variables (v1,v2)<->(x,y). So I tried interpolating y(v1,v2) and x(v1,v2) using interp2, but the output is just a 1D vector that seems very similar to my averaged 1D interpolation.
Is there something I am missing or simply doing wrong? Any help would be greatly appreciated, and I can provide more detail wherever things are unclear.
Thanks

Answers (2)

Star Strider
Star Strider on 12 Nov 2014
First, I did a (linear) regression on your data with lsqcurvefit and got a decent fit to your data. (I used lsqcurvefit because I thought it might be nonlinear and I wanted to be able to change the model easily to reflect that.) My objective function produces a (Nx2) vector to match ‘P’.
The code:
V = [-1 0; 0 0; 1 0; -1 1; 0 1; 1 1; -1 2; 0 2; 1 2];
P = [-14 -2; 0 0; 13.5 -1; -13 7; 0.5 8; 14 7; -14 12; 1 11; 14.5 11];
PV = @(b,V) [[(b(1).*V(:,1)+b(2))] [(b(3).*V(:,2)+b(4))]]; % Objective Function
[B, rn, r] = lsqcurvefit(PV, ones(4,1), V, P);
Pc = PV(B,V);
Second, the only interpolation functions I can think of that might work with your data are either griddatan or interpn.
I suggest you experiment with them, as well as with my objective function and lsqcurvefit, especially as you gather more data. You know your system and its dynamics better than I do. If you have a state space model of your system, that will likely do better than my regression to model its behaviour.

Derek
Derek on 21 Nov 2014
Edited: Derek on 21 Nov 2014
I tried implementing your code, but unfortunately lsqcurvefit is not a method in MATLAB R2008a. They give the lscov function for linear regression instead, which I was not able to get working. I tried griddatan and interpn as well. Interpn gives an identical output to when I use interp2 (not surprised), and griddatan is also incredibly similar. What is strange is the 2D interpolations give me a 1D output.. The structure I want to interpolate (actual data) is shown in the attached image, e.g. y-coordinate as a function of my two voltages, and there is another for the x-coordinate values.
My current method took slices of the data along V2, since the data varies most in this dimension, average these slices together, then fit them. This does OK and following the behavior.
When I run interp2, griddatan, or interpn, I get a 1D array out that looks just like my 1D average fit (or incredibly similar). It's not shown in these last two plots, but they are y-position plotted against V2, or the fits and associated v2_spline (finer V2) array.
What I want is a new 2D map, like the first image, but with points interpolated in between.
To clarify, my data comes as 4 1D arrays, x_pos, y_pos, V1, and V2, which are all N-data_points long (e.g. for 10 different values of V1 and 6 different values of V2 all the arrays are N=10x6=60 data points long). So to get the 1st plot I do:
iy = find(v1==v1(1)); % e.g. [0,1,2,3,4,5,6,7,8,9,10,0,1,2...,9,10] for N points
ix = find(v2==v2(1)); % e.g. [0,0,...,2,2,...,4,4...,10,10] for N points
vx = v1(ix); %e.g. [0,1,2,3,4,5,6,7,8,9,10]
vy = v2(iy); %e.g. [0,2,4,6,8,10]
vx_sp = 0:0.005:10;
vy_sp = 0:0.005:10;
ypos_sq = reshape(ypos,length(vx),length(vy));
xpos_sq = reshape(xpos,length(vx),length(vy));
mesh(vy,vx,ypos_sq); %and same for the x_map plot
and I would call interp2 (likewise interpn) like:
y2DFit = interp2(vy,vx,ypos_sq,vx_sp,vy_sp);
I don't recall my syntax for griddatan, but I think I called it correctly (not sure, cause the documentation isn't the clearest). Either way, none of these methods have interpolated my map in the way I want them to yet..

Categories

Find more on Interpolation in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!