MATLAB: Non-linear curve fitting for forced vibration acceleration data

dampingleast squareslsqcurvefitMATLABvibration

I'm trying to fit a curve to my data using MATLAB's lsqcurvefit function. The data is from an accelerometer (in g's), and I'm trying to fit curves at each of the resonance modes.
The function that the non-linear solver is using is the standard one for amplitude as a function of frequency:
I also measured the force, which had a max value of around 3.5 N, and mass was around 3-4 kg of the whole system. I applied a FFT to the data and added a Hanning window, so now I essentially have amplitude v.s. frequency (Hz). When I try giving lsqcurvefit initial conditions which are close to what I would expect to final values, it gets it completely wrong (see below). I'm also only displaying the datapoints close to the peak for brevity.
On the other hand, when I played around with the initial estimate, I was able to get an ok fit but with completely arbitrary values:
Below is my code:
% Using equation x = F./(m*sqrt(((2*omega_0*damping).^2)+((omega_0.^2 - omega.^2).^2)));
% x(1) = omega_0;
% x(2) = damping;
% x(3) = F;
% x(4) = m;
pa_avg = [0.0034;0.0033;0.0036;0.0043;0.0071;0.0113;0.0130;0.0117;0.0114;0.0123;0.0130;0.0168...
0.0228;0.0218;0.0147;0.0122;0.0173;0.0257;0.0321;0.0321;0.0320;0.0406;0.0533;0.0629...
0.0714;0.0787;0.0763;0.0619;0.0429;0.0259;0.0165;0.0145;0.0144;0.0134;0.0114;0.0088...
0.0070;0.0057;0.0042;0.0028;0.0021;0.0021;0.0023;0.0028;0.0030;0.0024;0.0018;0.0015...
0.0015;0.0015;0.0016;0.0014;0.0012;0.0010;0.0010;0.0009;0.0009;0.0009;0.0009;0.0009;0.0008];
f = 890:10:1490;
w = 2*pi*f(90:150); % Convert to radians/sec
func = @(x,xdata) x(3)./(x(4).*sqrt(((2*x(1)*x(2)).^2)+((x(1).^2 - xdata.^2).^2)));
x0 = [2*pi*1140, 0.3, 10000, 50]; % Initial guess which results in an ok fit
x = lsqcurvefit(func,x0,w,pa_avg(90:150));
semilogy(w/(2*pi),func(x,w))
hold on
semilogy(w/(2*pi), pa_avg(90:150), "o")
legend("Fitted function", "Actual Data")
I tried integrating the acceleration data twice to get displacement but this didn't work at all.
I also tried treating F_0/m as a single variable, acceleration, but this didn't make any difference. Any help is much appreciated.

Best Answer

There are some errors.
First, ‘w’ should be calculated by multiplying it by , or using the deg2rad function. It also needs to be converted to a column vector to match ‘pa_avg’ that also has problems, and should be:
pa_avg = [0.0034;0.0033;0.0036;0.0043;0.0071;0.0113;0.0130;0.0117;0.0114;0.0123;0.0130;0.0168;...
0.0228;0.0218;0.0147;0.0122;0.0173;0.0257;0.0321;0.0321;0.0320;0.0406;0.0533;0.0629;...
0.0714;0.0787;0.0763;0.0619;0.0429;0.0259;0.0165;0.0145;0.0144;0.0134;0.0114;0.0088;...
0.0070;0.0057;0.0042;0.0028;0.0021;0.0021;0.0023;0.0028;0.0030;0.0024;0.0018;0.0015;...
0.0015;0.0015;0.0016;0.0014;0.0012;0.0010;0.0010;0.0009;0.0009;0.0009;0.0009;0.0009;0.0008];
I used the ga (genetic algorithm) function and quickly got a reasonably decent fit (at least by my criteria) with:
x =
19.8404873275757
0.3168359375
35.9852020359039
34.2824745559692
The fitness function I used:
ftns = @(x) norm(pa_avg - func(x,w));
producing:
Note that ‘x(1)’ is in rad/sec, so it would convert to 1136.76942273353 °/sec.
.