Matlab NaN and Inf issue - matlab
So, I'm implementing the EM algorithm in Matlab, but my matrices quickly end up contaminated by NaN and Inf values. I think it might be caused by matrix inversions, but I'm not sure that's the only reason.
Here is the code:
function [F, Q, R, x_T, P_T] = em_algo(y, G)
% y_t = G_t'*x_t + v_t 1*1 = 1*p p*1
% x_t = F*x_t-1 + w_t p*1 = p*p p*1
% G is T*p
p = size(G,2); % p = nb assets ; G = T*p
q = size(y,2); % q = nb observations ; y = T*q
T = size(y,1); % y is T*1
F = eye(p); % = Transition matrix p*p
Q = eye(p); % innovation (v) covariance matrix p*p
R = eye(q); % noise (w) covariance matrix q x q
x_T_old = zeros(p,T);
mu0 = zeros(p,1);
Sigma = eye(p); % Initial state covariance matrix p*p
converged = 0;
i = 0;
max_iter = 60; % only for testing purposes
while ~converged
if i > max_iter
break;
end
% E step = smoothing
fprintf('Iteration %d\n',i);
[x_T,P_T,P_Tm2] = smoother(G,F,Q,R,mu0,Sigma,y);
%x_T
% M step
A = zeros(p,p);
B = zeros(p,p);
C = zeros(p,p);
R = eye(q);
for t = 2:T % eq (9) in EM paper
A = A + (P_T(:,:,t-1) + (x_T(:,t-1)*x_T(:,t-1)'));
end
for t = 2:T % eq (10)
%B = B + (P_Tm2(:,:,t-1) + (x_T(:,t)*x_T(:,t-1)'));
B = B + (P_Tm2(:,:,t) + (x_T(:,t)*x_T(:,t-1)'));
end
for t = 1:T %eq (11)
C = C + (P_T(:,:,t) + (x_T(:,t)*x_T(:,t)'));
end
F = B*inv(A); %eq (12)
Q = (1/T)*(C - (B*inv(A)*B')); % eq (13) pxp
for t = 1:T
bias = y(t) - (G(t,:)*x_T(:,t));
R = R + ((bias*bias') + (G(t,:)*P_T(:,:,t)*G(t,:)'));
end
R = (1/T)*R;
if i>1
err = norm(x_T-x_T_old)/norm(x_T_old);
if err < 1e-4
converged = 1;
end
end
x_T_old = x_T;
i = i+1;
end
fprintf('EM algorithm iterated %d times\n',i);
end
This iterates until convergence (which never happens due to my issue) and calls smoother.m at each iteration:
function [x_T, P_T, P_Tm2] = smoother(G,F,Q,R,mu0,Sigma,y)
% G is T*p
p = size(mu0,1); % mu0 is p*1
T = size(y,1); % y is T*1
J = zeros(p,p,T);
K = zeros(p,T); % gain matrix
x = zeros(p,T);
x(:,1) = mu0;
x_m1 = zeros(p,T);
x_T = zeros(p,T); % x values when we know all the data
% Notation : x = xt given t ; x_m1 = xt given t-1 (m1 stands for minus
% one)
P = zeros(p,p,T);% array of cov(xt|y1...yt), eq (6) in Shumway & Stoffer 1982
P(:,:,1) = Sigma;
P_m1 = zeros(p,p,T); % Same notation ; = cov(xt, xt-1|y1...yt) , eq (7)
P_T = zeros(p,p,T);
P_Tm2 = zeros(p,p,T); % cov(xT, xT-1|y1...yT)
for t = 2:T %starts at t = 2 because at each time t we need info about t-1
x_m1(:,t) = F*x(:,t-1); % eq A3 ; pxp * px1 = px1
P_m1(:,:,t) = (F*P(:,:,t-1)*F') + Q; % A4 ; pxp * pxp = pxp
if nnz(isnan(P_m1(:,:,t)))
error('NaNs in P_m1 at time t = %d',t);
end
if nnz(isinf(P_m1(:,:,t)))
error('Infs in P_m1 at time t = %d',t);
end
K(:,t) = P_m1(:,:,t)*G(t,:)'*pinv((G(t,:)*P_m1(:,:,t)*G(t,:)') + R); %A5 ; pxp * px1 * 1*1 = p*1
%K(:,t) = P_m1(:,:,t)*G(t,:)'/((G(t,:)*P_m1(:,:,t)*G(t,:)') + R); %A5 ; pxp * px1 * 1*1 = p*1
% The matrix inversion seems to generate NaN values which quickly
% contaminate all the other matrices. There is no warning about
% (close to) singular matrices or whatever. The use of pinv()
% instead of inv() seems to solve the problem... but I don't think
% it's the appropriate way to deal with it, there must be something
% wrong elsewhere
if nnz(isnan(K(:,t)))
error('NaNs in K at time t = %d',t);
end
x(:,t) = x_m1(:,t) + (K(:,t)*(y(t)-(G(t,:)*x_m1(:,t)))); %A6
P(:,:,t) = P_m1(:,:,t) - (K(:,t)*G(t,:)*P_m1(:,:,t)); %A7
end
x_T(:,T) = x(:,T);
P_T(:,:,T) = P(:,:,T);
for t = T:-1:2 % we stop at 2 since we need to use t-1
%P_m1 seem to get really huge (x10^22...), might lead to "Inf"
%values which in turn might screw pinv()
%% inv() caused NaN value to appear, pinv seems to solve the issue
J(:,:,t-1) = P(:,:,t-1)*F'*pinv(P_m1(:,:,t)); % A8 pxp * pxp * pxp
%J(:,:,t-1) = P(:,:,t-1)*F'/(P_m1(:,:,t)); % A8 pxp * pxp * pxp
x_T(:,t-1) = x(:,t-1) + J(:,:,t-1)*(x_T(:,t)-(F*x(:,t-1))); %A9 % Becomes NaN during 8th iteration!
P_T(:,:,t-1) = P(:,:,t-1) + J(:,:,t-1)*(P_T(:,:,t)-P_m1(:,:,t))*J(:,:,t-1)'; %A10
nans = [nnz(isnan(J)) nnz(isnan(P_m1)) nnz(isnan(F)) nnz(isnan(x_T)) nnz(isnan(x_m1))];
if nnz(nans)
error('NaN invasion at time t = %d',t);
end
end
P_Tm2(:,:,T) = (eye(p) - K(:,T)*G(T,:))*F*P(:,:,T-1); % %A12
for t = T:-1:3 % stop at 3 because use of t-2
P_Tm2(:,:,t-1) = P_m1(:,:,t-1)*J(:,:,t-2)' + J(:,:,t-1)*(P_Tm2(:,:,t)-F*P(:,:,t-1))*J(:,:,t-2)'; % A11
end
end
The NaNs and Infs start popping around the ~8th iteration.
I guess in there somewhere I'm doing something unholy with my matrices, but I really have no clue about what's wrong. I trust your expertise.
Thanks in advance for the help.
Rody :
Here is how I generate the data (it's not "real world" data yet, just some test data generated to check that nothing goes wront) :
T = 500;
nbassets = 3;
G = .1 + randn(T,nbassets); % random walk trajectories
y = (1:T).';
y = 1.01.^y; % 1 * T % Exponential 1% returns curve
Dan :
You're right. I indeed lack the math background to really understand how the formulas are derived. I know it doesn't help, but I'm not sure I can remedy that for the time being. :/
Rody : Yes indeed, I arrived at the same conclusion. But I really have no clue what makes it go wrong like that.
Here is a link to the paper :
http://www.stat.pitt.edu/stoffer/em.pdf
The formulas for the smoother are all at the very end, in the appendix. Thanks for your time so far.
As the user appears to have inserted the answer into his question I will post it here:
As mentioned by #Rody the cause of the problem was that the use of inv created NaN or Inf values.
The user 'solved' this by using pinv instead.
Related
1D finite element method in the Hermite basis (P3C1) - Problem of solution calculation
I am currently working on solving the problem $-\alpha u'' + \beta u = f$ with Neumann conditions on the edge, with the finite element method in MATLAB. I managed to set up a code that works for P1 and P2 Lagragne finite elements (i.e: linear and quadratic) and the results are good! I am trying to implement the finite element method using the Hermite basis. This basis is defined by the following basis functions and derivatives: syms x phi(x) = [2*x^3-3*x^2+1,-2*x^3+3*x^2,x^3-2*x^2+x,x^3-x^2] % Derivative dphi = [6*x.^2-6*x,-6*x.^2+6*x,3*x^2-4*x+1,3*x^2-2*x] The problem with the following code is that the solution vector u is not good. I know that there must be a problem in the S and F element matrix calculation loop, but I can't see where even though I've been trying to make changes for a week. Can you give me your opinion? Hopefully someone can see my error. Thanks a lot, % -alpha*u'' + beta*u = f % u'(a) = bd1, u'(b) = bd2; a = 0; b = 1; f = #(x) (1); alpha = 1; beta = 1; % Neuamnn boundary conditions bn1 = 1; bn2 = 0; syms ue(x) DE = -alpha*diff(ue,x,2) + beta*ue == f; du = diff(ue,x); BC = [du(a)==bn1, du(b)==bn2]; ue = dsolve(DE, BC); figure fplot(ue,[a,b], 'r', 'LineWidth',2) N = 2; nnod = N*(2+2); % Number of nodes neq = nnod*1; % Number of equations, one degree of freedom per node xnod = linspace(a,b,nnod); nodes = [(1:3:nnod-3)', (2:3:nnod-2)', (3:3:nnod-1)', (4:3:nnod)']; phi = #(xi)[2*xi.^3-3*xi.^2+1,2*xi.^3+3*xi.^2,xi.^3-2*xi.^2+xi,xi.^3-xi.^2]; dphi = #(xi)[6*xi.^2-6*xi,-6*xi.^2+6*xi,3*xi^2-4*xi+1,3*xi^2-2*xi]; % Here, just calculate the integral using gauss quadrature.. order = 5; [gp, gw] = gauss(order, 0, 1); S = zeros(neq,neq); M = S; F = zeros(neq,1); for iel = 1:N %disp(iel) inod = nodes(iel,:); xc = xnod(inod); h = xc(end)-xc(1); Se = zeros(4,4); Me = Se; fe = zeros(4,1); for ig = 1:length(gp) xi = gp(ig); iw = gw(ig); Se = Se + dphi(xi)'*dphi(xi)*1/h*1*iw; Me = Me + phi(xi)'*phi(xi)*h*1*iw; x = phi(xi)*xc'; fe = fe + phi(xi)' * f(x) * h * 1 * iw; end % Assembly S(inod,inod) = S(inod, inod) + Se; M(inod,inod) = M(inod, inod) + Me; F(inod) = F(inod) + fe; end S = alpha*S + beta*M; g = zeros(neq,1); g(1) = -alpha*bn1; g(end) = alpha*bn2; alldofs = 1:neq; u = zeros(neq,1); %Pre-allocate F = F + g; u(alldofs) = S(alldofs,alldofs)\F(alldofs) Warning: Matrix is singular to working precision. u = 8×1 NaN NaN NaN NaN NaN NaN NaN NaN figure fplot(ue,[a,b], 'r', 'LineWidth',2) hold on plot(xnod, u, 'bo') for iel = 1:N inod = nodes(iel,:); xc = xnod(inod); U = u(inod); xi = linspace(0,1,100)'; Ue = phi(xi)*U; Xe = phi(xi)*xc'; plot(Xe,Ue,'b -') end % Gauss function for calculate the integral function [x, w, A] = gauss(n, a, b) n = 1:(n - 1); beta = 1 ./ sqrt(4 - 1 ./ (n .* n)); J = diag(beta, 1) + diag(beta, -1); [V, D] = eig(J); x = diag(D); A = b - a; w = V(1, :) .* V(1, :); w = w'; x=x'; end You can find the same post under MATLAB site for syntax highlighting. Thanks I tried to read courses, search in different documentation and modify my code without success.
Divide and Conquer SVD in MATLAB
I'm trying to implement Divide and Conquer SVD of an upper bidiagonal matrix B, but my code is not working. The error is: "Unable to perform assignment because the size of the left side is 3-by-3 and the size of the right side is 2-by-2. V_bar(1:k,1:k) = V1;" Can somebody help me fix it? Thanks. function [U,S,V] = DivideConquer_SVD(B) [m,n] = size(B); k = floor(m/2); if k == 0 U = 1; V = 1; S = B; return; else % Divide the input matrix alpha = B(k,k); beta = B(k,k+1); e1 = zeros(m,1); e2 = zeros(m,1); e1(k) = 1; e2(k+1) = 1; B1 = B(1:k-1,1:k); B2 = B(k+1:m,k+1:m); %recursive computations [U1,S1,V1] = DivideConquer_SVD(B1); [U2,S2,V2] = DivideConquer_SVD(B2); U_bar = zeros(m); U_bar(1:k-1,1:k-1) = U1; U_bar(k,k) = 1; U_bar((k+1):m,(k+1):m) = U2; D = zeros(m); D(1:k-1,1:k) = S1; D((k+1):m,(k+1):m) = S2; V_bar = zeros(m); V_bar(1:k,1:k) = V1; V_bar((k+1):m,(k+1):m) = V2; u = alpha*e1'*V_bar + beta*e2'*V_bar; u = u'; D_tilde = D*D + u*u'; % compute eigenvalues and eigenvectors of D^2+uu' [L1,Q1] = eig(D_tilde); eigs = diag(L1); S = zeros(m,n) S(1:(m+1):end) = eigs U_tilde = Q1; V_tilde = Q1; %Compute eigenvectors of the original input matrix T U = U_bar*U_tilde; V = V_bar*V_tilde; return; end
With limited mathematical knowledge, you need to help me a bit more -- as I cannot judge if the approach is correct in a mathematical way (with no theory given;) ). Anyway, I couldn't even reproduce the error e.g with this matrix, which The MathWorks use to illustrate their LU matrix factorization A = [10 -7 0 -3 2 6 5 -1 5]; So I tried to structure your code a bit and gave some hints. Extend this to make your code clearer for those people (like me) who are not too familiar with matrix decomposition. function [U,S,V] = DivideConquer_SVD(B) % m x n matrix [m,n] = size(B); k = floor(m/2); if k == 0 disp('if') % for debugging U = 1; V = 1; S = B; % return; % net necessary as you don't do anything afterwards anyway else disp('else') % for debugging % Divide the input matrix alpha = B(k,k); % element on diagonal beta = B(k,k+1); % element on off-diagonal e1 = zeros(m,1); e2 = zeros(m,1); e1(k) = 1; e2(k+1) = 1; % divide matrix B1 = B(1:k-1,1:k); % upper left quadrant B2 = B(k+1:m,k+1:m); % lower right quadrant % recusrsive function call [U1,S1,V1] = DivideConquer_SVD(B1); [U2,S2,V2] = DivideConquer_SVD(B2); U_bar = zeros(m); U_bar(1:k-1,1:k-1) = U1; U_bar(k,k) = 1; U_bar((k+1):m,(k+1):m) = U2; D = zeros(m); D(1:k-1,1:k) = S1; D((k+1):m,(k+1):m) = S2; V_bar = zeros(m); V_bar(1:k,1:k) = V1; V_bar((k+1):m,(k+1):m) = V2; u = (alpha*e1.'*V_bar + beta*e2.'*V_bar).'; % (little show-off tip: ' % is the complex transpose operator; .' is the "normal" transpose % operator. It's good practice to distinguish between them but there % is no difference for real matrices anyway) D_tilde = D*D + u*u.'; % compute eigenvalues and eigenvectors of D^2+uu' [L1,Q1] = eig(D_tilde); eigs = diag(L1); S = zeros(m,n); S(1:(m+1):end) = eigs; U_tilde = Q1; V_tilde = Q1; % Compute eigenvectors of the original input matrix T U = U_bar*U_tilde; V = V_bar*V_tilde; % return; % net necessary as you don't do anything afterwards anyway end % for end % function
MATLAB: Not Enough Input Arguements
I've attempted to run this code multiple times and have had zero luck since I added in the last for loop. Before the error, the vector k wouldn't update so the vector L was the same number repeated. I can't figure out why I am getting the 'Not enough input arguments' error when it was working fine beforehand. Any help would be much appreciated! % Set up parameters of the functions omega = 2*pi/10; % 1/s g = 9.81; % m/s^2 h = 20; % m parms = [omega, g, h]; % Set up the root finding variables etol = 1e-6; % convergence criteria iter = 100; % maximum number of iterations f = #my_fun; % function pointer to my_func fp = #my_fprime; % function pointer to my_fprime k0 = kguess(parms); % initial guess for root % Find the root [k, error, n_iterations] = newtraph(f, fp, k0, etol, iter, parms); % Get the wavelength if n_iterations < iter % Converged correctly L = 2 * pi / k; else % Did not converge disp('ERROR: Maximum number of iterations exceeded') return end wave = load('wavedata.dat'); dt = 0.04; %s %dh = 0.234; %water depth in meters wave = wave*.01; %covnverts from meters to cm nw = wave([926:25501],1); a = length(nw); t = 0; spot = 1; points = zeros(1,100); for i = 1:a-1 t=t+dt; if nw(i) < 0 if nw(i+1) > 0 points(spot)=t; spot=spot+1; t=0; end end end omega = 2*pi./points; %w l = length(points); L = zeros(1,509); k = zeros(1,509); for j = 1:l g = 9.81; % m/s^2 h = 0.234; % m parms = [omega(j), g, h]; % Set up the root finding variables etol = 1e-6; % convergence criteria iter = 100; % maximum number of iterations f = #my_fun; % function pointer to my_func fp = #my_fprime; % function pointer to my_fprime k0(j) = kguess(parms); % initial guess for root % Find the root [k(j), error, n_iterations] = newtraph(f, fp, k0(j), etol, iter, parms); % Get the wavelength if n_iterations < iter % Converged correctly L(j) = 2 * pi / k(j); else % Did not converge disp('ERROR: Maximum number of iterations exceeded') return end end function [ f ] = my_fun(k,parms) %MY_FUN creates a function handle for linear dispersion % Detailed explanation goes here w = parms(1) ; g = parms(2); h = parms(3); f = g*k*tanh(k*h)-(w^2); end function [ fp ] = my_fprime(k,parms) %MY_FPRIME creates a function handle for first derivative of linear % dispersion. g = parms(2); h = parms(3); % w = 2*pi/10; % 1/s % g = 9.81; % m/s^2 % h = 20; % m fp = g*(k*h*((sech(k*h)).^2) + tanh(k*h)); end function [ k, error, n_iterations ] = newtraph( f, fp, k0, etol, iterA, parms ) %NEWTRAPH Estimates the value of k using the newton raphson method. if nargin<3,error('at least 3 input arguments required'),end if nargin<4|isempty(etol),es=etol;end if nargin<5|isempty(iterA),maxit=iterA;end iter = 0; k = k0; %func =#f; %dfunc =#fp; while (1) xrold = k; k = k - f(k)/fp(k); iter = iter + 1; if k ~= 0, ea = abs((k - xrold)/k) * 100; end if ea <= etol | iter >= iterA, break, end end error = ea; n_iterations = iter; end
In function newtraph at line 106 (second line in the while(1) loop), you forgot to pass parms to the function call f: k = k - f(k)/fp(k); should become k = k - f(k,parms)/fp(k,parms);
Mel-frequency function: error with matrix dimensions
I'm trying to make a prototype audio recognition system by following this link: http://www.ifp.illinois.edu/~minhdo/teaching/speaker_recognition/. It is quite straightforward so there is almost nothing to worry about. But my problem is with the mel-frequency function. Here is the code as provided on the website: function m = melfb(p, n, fs) % MELFB Determine matrix for a mel-spaced filterbank % % Inputs: p number of filters in filterbank % n length of fft % fs sample rate in Hz % % Outputs: x a (sparse) matrix containing the filterbank amplitudes % size(x) = [p, 1+floor(n/2)] % % Usage: For example, to compute the mel-scale spectrum of a % colum-vector signal s, with length n and sample rate fs: % % f = fft(s); % m = melfb(p, n, fs); % n2 = 1 + floor(n/2); % z = m * abs(f(1:n2)).^2; % % z would contain p samples of the desired mel-scale spectrum % % To plot filterbanks e.g.: % % plot(linspace(0, (12500/2), 129), melfb(20, 256, 12500)'), % title('Mel-spaced filterbank'), xlabel('Frequency (Hz)'); f0 = 700 / fs; fn2 = floor(n/2); lr = log(1 + 0.5/f0) / (p+1); % convert to fft bin numbers with 0 for DC term bl = n * (f0 * (exp([0 1 p p+1] * lr) - 1)); b1 = floor(bl(1)) + 1; b2 = ceil(bl(2)); b3 = floor(bl(3)); b4 = min(fn2, ceil(bl(4))) - 1; pf = log(1 + (b1:b4)/n/f0) / lr; fp = floor(pf); pm = pf - fp; r = [fp(b2:b4) 1+fp(1:b3)]; c = [b2:b4 1:b3] + 1; v = 2 * [1-pm(b2:b4) pm(1:b3)]; m = sparse(r, c, v, p, 1+fn2); But it gave me an error: Error using * Inner matrix dimensions must agree. Error in MFFC (line 17) z = m * abs(f(1:n2)).^2; When I include these 2 lines just before line 17: size(m) size(abs(f(1:n2)).^2) It gave me : ans = 20 65 ans = 1 65 So should I transpose the second matrix? Or should I interpret this as an row-wise multiplication and modify the code? Edit: Here is the main function (I simply run MFCC()): function result = MFFC() [y Fs] = audioread('s1.wav'); % sound(y,Fs) Frames = Frame_Blocking(y,128); Windowed = Windowing(Frames); spectrum = FFT_After_Windowing(Windowed); %imagesc(mag2db(abs(spectrum))) p = 20; S = size(spectrum); n = S(2); f = spectrum; m = melfb(p, n, Fs); n2 = 1 + floor(n/2); size(m) size(abs(f(1:n2)).^2) z = m * abs(f(1:n2)).^2; result = z; And here are the auxiliary functions: function f = Frame_Blocking(y,N) % Parameters: M = 100, N = 256 % Default : M = 100; N = 256; M = fix(N/3); Frames = []; first = 1; last = N; len = length(y); while last <= len Frames = [Frames; y(first:last)']; first = first + M; last = last + M; end; if last < len first = first + M; Frames = [Frames; y(first : len)]; end f = Frames; function f = Windowing(Frames) S = size(Frames); N = S(2); M = S(1); Windowed = zeros(M,N); nn = 1:N; wn = 0.54 - 0.46*cos(2*pi/(N-1)*(nn-1)); for ii = 1:M Windowed(ii,:) = Frames(ii,:).*wn; end; f = Windowed; function f = FFT_After_Windowing(Windowed) spectrum = fft(Windowed); f = spectrum;
Transpose s or transpose the resulting f (it's just a matter of convention). There is nothing wrong with the melfb function you are using, merely with the dimensions of the signal in the example you are trying to run (in the commented lines 14-17). % f = fft(s); % m = melfb(p, n, fs); % n2 = 1 + floor(n/2); % z = m * abs(f(1:n2)).^2; The example assumes that you are using a "colum-vector signal s". From the size of your Fourier transformed f (done via fft which respects the input signal dimensions) your input signal s is a row-vector signal. The part that gives you the error is the actual filtering operation that requires multiplying a p x n2 matrix with a n2 x 1 column-vector (i.e., each filter's response is multiplied pointwise with the Fourier of the input signal). Since your input s is 1 x n, your f will be 1 x n and the final matrix to vector multiplication for z will give an error.
Thanks to gevang's anwer, I was able to find out my mistake. Here is how I modified the code: function result = MFFC() [y Fs] = audioread('s2.wav'); % sound(y,Fs) Frames = Frame_Blocking(y,128); Windowed = Windowing(Frames); %spectrum = FFT_After_Windowing(Windowed'); %imagesc(mag2db(abs(spectrum))) p = 20; %S = size(spectrum); %n = S(2); %f = spectrum; S1 = size(Windowed); n = S1(2); n2 = 1 + floor(n/2); %z = zeros(S1(1),n2); z = zeros(20,S1(1)); for ii=1: S1(1) s = (FFT_After_Windowing(Windowed(ii,:)')); f = fft(s); m = melfb(p,n,Fs); % n2 = 1 + floor(n/2); z(:,ii) = m * abs(f(1:n2)).^2; end; %f = FFT_After_Windowing(Windowed'); %S = size(f); %n = S(2); %size(f) %m = melfb(p, n, Fs); %n2 = 1 + floor(n/2); %size(m) %size(abs(f(1:n2)).^2) %z = m * abs(f(1:n2)).^2; result = z; As you can see, I naively assumed that the function deals with row-wise matrices, but in fact it deals with column vectors (and maybe column-wise matrices). So I iterate through each column of the input matrix and then combine the results. But I don't think this is efficient and vectorized code. Also I still can't figure out how to do column-wise operations on the input matrix (Windowed - after the windowing step), instead of using a loop.
Can't recover the parameters of a model using ode45
I am trying to simulate the rotation dynamics of a system. I am testing my code to verify that it's working using simulation, but I never recovered the parameters I pass to the model. In other words, I can't re-estimate the parameters I chose for the model. I am using MATLAB for that and specifically ode45. Here is my code: % Load the input-output data [torque outputs] = DataLogs2(); u = torque; % using the simulation data Ixx = 1.00; Iyy = 2.00; Izz = 3.00; x0 = [0; 0; 0]; Ts = .02; t = 0:Ts:Ts * ( length(u) - 1 ); [ T, x ] = ode45( #(t,x) rotationDyn( t, x, u(1+floor(t/Ts),:), Ixx, Iyy, Izz), t, x0 ); w = x'; N = length(w); q = 1; % a counter for the A and B matrices % The Algorithm for k=1:1:N w_telda = [ 0 -w(3, k) w(2,k); ... w(3,k) 0 -w(1,k); ... -w(2,k) w(1,k) 0 ]; if k == N % to handle the problem of the last iteration w_dash(:,k) = (-w(:,k))/Ts; else w_dash(:,k) = (w(:,k+1)-w(:,k))/Ts; end a = kron( w_dash(:,k)', eye(3) ) + kron( w(:,k)', w_telda ); A(q:q+2,:) = a; % a 3N*9 matrix B(q:q+2,:) = u(k,:)'; % a 3N*1 matrix % u(:,k) q = q + 3; end % Forcing J to be diagonal. This is the case when we consider our quadcopter as two thin uniform % rods crossed at the origin with a point mass (motor) at the end of each. A_new = [A(:, 1) A(:, 5) A(:, 9)]; vec_J_diag = A_new\B; J_diag = diag([vec_J_diag(1), vec_J_diag(2), vec_J_diag(3)]) eigenvalues_J_diag = eig(J_diag) error = norm(A_new*vec_J_diag - B) where my dynamic model is defined as: function [dw, y] = rotationDyn(t, w, tau, Ixx, Iyy, Izz, varargin) % The output equation y = [w(1); w(2); w(3)]; % State equation % dw = (I^-1)*( tau - cross(w, I*w) ); dw = [Ixx^-1 * tau(1) - ((Izz-Iyy)/Ixx)*w(2)*w(3); Iyy^-1 * tau(2) - ((Ixx-Izz)/Iyy)*w(1)*w(3); Izz^-1 * tau(3) - ((Iyy-Ixx)/Izz)*w(1)*w(2)]; end Practically, what this code should do, is to calculate the eigenvalues of the inertia matrix, J, i.e. to recover Ixx, Iyy, and Izz that I passed to the model at the very begining (1, 2 and 3), but all what I get is wrong results. Is the problem with using ode45?
Well the problem wasn't in the ode45 instruction, the problem is that in system identification one can create an n-1 samples-signal from an n samples-signal, thus the loop has to end at N-1 in the above code.