Error state kalman filter estimates wrong values - matlab

I've implemented this error state kalman filter, which has IMU data as input (220Hz) and it corrects the prediction with UWB measurements (50 Hz).
I want to estimate the pose of a quadrotor.
The code is:
function [x_hat,bound_p] = ESKF(d_meas,p_am,clockUWB,dt,u)
% u = IMU inputs
% d_meas = UWB measure
% p_am = anchor coordinate. There are 4 anchors that send the measurement one at a time cyclically
g = [0 0 9.81]';
am = u(1:3); % from acc
wm = u(4:6); % from gyro
persistent P Q R I dx_hat x_n p q v ba bw Fw
if isempty(P)
sig_an = 0.05; % [m/s^2]
sig_wn = 0.01; % [rad/s]
sig_wbn = 0.0001; % [rad/s*sqrt(s)]
sig_abn = 0.0001; % [m/(s^2*sqrt(s)]
sig_uwb = 0.0214; % [m]
Q_an = sig_an*sig_an*eye(3); % [m^2/s^2]
Q_wn = sig_wn*sig_wn*eye(3); % [rad^2]
Q_abn = sig_abn*sig_abn*eye(3); % [m^2/s^4]
Q_wbn = sig_wbn*sig_wbn*eye(3); % [rad^2/s^2]
clockUWB = 0;
dx_hat = zeros(15,1); % error state
x_n = [5 4 5 1 0 0 1 0 0 0 0 0 0 0 0 0]'; % initial state
P = eye(15,15);
Fw = [zeros(3,12);eye(12,12)];
Q = blkdiag(Q_an,Q_wn,Q_wbn,Q_abn);
R = sig_uwb*sig_uwb;
I = eye(length(dx_hat));
p = x_n(1:3);
v = x_n(4:6);
q = x_n(7:10);
bw = x_n(11:13);
ba = x_n(14:16);
end
%% NOMINAL STATE
if ((wm - bw) == [0 0 0]')
qw = [1 0 0 0]';
else
nw = norm(wm - bw);
qw = [cos(nw*dt/2); ((wm - bw)/nw)*sin(nw*dt/2)];
end
R_ui = quat2rotm(q');
% PREDICTION
p = p + v*dt + 1/2*(R_ui*(am - ba) + g)*dt*dt;
v = v + (R_ui*(am - ba) + g)*dt;
q = quatmultiply(q',qw')';
q = q/norm(q);
% bw = bw;
% ba = ba;
%% ERROR STATE
% delta_p = delta_p + delta_v*dt;
% delta_v = delta_v + (-R_ui*skew(am - ba)*delta_th - R_ui*delta_ba)*dt + an);
% delta_th = R_ui'*delta_th - delta_bw*dt + wn;
% delta_bw = delta_bw + wbn*ones(3,1);
% delta_ba = delta_ba + abn*ones(3,1);
F = [ eye(3), eye(3)*dt, zeros(3,3), zeros(3,3), zeros(3,3);
zeros(3,3), eye(3), -R_ui*skew(am-ba)*dt, zeros(3,3), -R_ui*dt;
zeros(3,3), zeros(3,3), R_ui', -eye(3)*dt, zeros(3,3);
zeros(3,3), zeros(3,3), zeros(3,3), eye(3), zeros(3,3);
zeros(3,3), zeros(3,3), zeros(3,3), zeros(3,3), eye(3)];
%PREDCTION
dx_hat = F*dx_hat;
P = F * P * F' + Fw * Q * Fw';
%% UPDATE
% Only when measures arrive
if (clockUWB == 1)
h = p - p_am;
d_am = norm(h);
H = [ (1/(2*d_am))*2*h'*eye(3), zeros(1,3), zeros(1,3), zeros(1,3), zeros(1,3)];
K = P * H' * inv(H * P * H' + R);
dx_hat = K * (d_meas - d_am);
delta_x = [dx_hat(1:6);[1,1/2*dx_hat(7:9)']';dx_hat(10:15)];
P = (I - K * H) * P * (I - K * H)' + K * R * K';
%% ERROR INJECTION
p = p + delta_x(1:3);
v = v + delta_x(4:6);
q = quatmultiply(q',delta_x(7:10)')';
q = q/norm(q);
bw = bw + delta_x(11:13);
ba = ba + delta_x(14:16);
sig_p = 3*[sqrt(P(1,1));sqrt(P(2,2));sqrt(P(2,2))];
bound_p = [p(1) + sig_p(1),p(1) - sig_p(1),p(2) + sig_p(2),p(2) - sig_p(2),p(3) + sig_p(3),p(3) - sig_p(3)];
x_hat = [p;v;q;bw;ba];
yaw_err = abs(dx_hat(9));
yaw_err_old = yaw_err;
%% RESET ERROR
G = blkdiag(eye(6),eye(3) - skew(1/2*dx_hat(7:9)),eye(6));
delta_x = zeros(16,1);
dx_hat = zeros(15,1);
P = G * P * G';
else
x_hat = [p;v;q;bw;ba];
delta_x = zeros(16,1);
sig_p = 3*[sqrt(P(1,1));sqrt(P(2,2));sqrt(P(2,2))];
bound_p = [p(1) + sig_p(1),p(1) - sig_p(1),p(2) + sig_p(2),p(2) - sig_p(2),p(3) + sig_p(3),p(3) - sig_p(3)];
end
end
It estimates position perfectly, and also velocity is nice.
The problem is that it estimates roll, pitch and yaw (which I derive from the quaternion thanks to quat2eul function) very badly and some bias are totally wrong.
Can someone tell me where the code is wrong?
Thanks
This is the main simulink model
In the green block there is the function of the filter.
In order to simulate a trajectory and UWB measurements in the UWB block there is this script:
function [xt,yt,zt,d_meas,p_am] = fcn(t,clock)
sig_uwb = 0.0214;
dn = normrnd(0,sig_uwb);
persistent k i
if isempty(k)
k = 0;
clock = 0;
i = 0;
end
x = 3*cos(1/3*t) + 3;
y = 3*sin(1/3*t) + 3;
z = 5;
a1 = [-4.12,-3.67,2.72]; % anchors coordinates
a2 = [2.45,-2.70,0.063];
a3 = [-2.43,3.07,0.075];
a4 = [3.65,2.42,2.62];
d1 = norm(a1 - [x,y,z]);
d2 = norm(a2 - [x,y,z]);
d3 = norm(a3 - [x,y,z]);
d4 = norm(a4 - [x,y,z]);
A = [a1,d1;a2,d2;a3,d3;a4,d4];
if (clock == 1)
k = k + 1;
i = mod(k,4) + 1;
d_meas = A(i,4) + dn;
p_am = A(i,(1:3))';
else
d_meas = 0;
p_am = zeros(3,1);
end
xt = x;
yt = y;
zt = z;
So the drone simulates a circular trajectory with radius equals to 3.
The IMU block contains just 2 vector:
am = [0 -1/3 -9.81] and wm = [0 0 1/3].
The bias should be constant and 0. I obtain instead values like 3 or 2 and non constant.
Roll and pitch aren't 0 as they should.
The text I am using to implement the ESKF are Quaternion kinematics for the error-state KF from pag. 52.

Related

Euclidian distances in speaker recognition system

I'm new in Matlab and now I have a problem for the implementation of a simple speaker recognition system using PNCC and MFFC.
My problem is on matrix dimension in fact, when I run my program, it give me this error:
Matrix dimensions must agree.
Error in disteu (line 43)
d(n,:) = sum((x(:, n+copies) - y) .^2, 1);
Error in test (line 22)
d = disteu(v, code{l});
Error in main (line 4)
test('C:\Users\Antonio\Documents\MATLAB\test',5, code);
Just for the sake of clarity I have attached my code.
Could anyone help me please?
function d = disteu(x, y)
% DISTEU Pairwise Euclidean distances between columns of two matrices
%
% Input:
% x, y: Two matrices whose each column is an a vector data.
%
% Output:
% d: Element d(i,j) will be the Euclidean distance between two
% column vectors X(:,i) and Y(:,j)
%
% Note:
% The Euclidean distance D between two vectors X and Y is:
% D = sum((x-y).^2).^0.5
% D = sum((x-y).^2).^0.5
[M, N] = size(x);
[M2, P] = size(y);
if (M ~= M2)
y=padarray(y,0,0,'post');
x=padarray(x,21,0,'post');
[M, N] = size(x)
[M2, P] = size(y)
y=padarray(y,0,0,'post');
[M2, P] = size(y)
end
%error('Matrix dimensions do not match.')
d = zeros(N, P);
if (N < P)
copies = zeros(1,P);
for n = 1:N
d(n,:) = sum((x(:, n+copies) - y) .^2, 1);
end
else
copies = zeros(1,N);
for p = 1:P
d(:,p) = sum((x - y(:, p+copies)) .^2, 1)';
end
end
d = d.^0.5;
function [aadDCT] = PNCC(rawdata, fsamp)
ad_x = rawdata;
%addpath voicebox/; % With Spectral Subtraction - default parameters
%ad_x = specsub(rawdata, fsamp);
dLamda_L = 0.999;
dLamda_S = 0.999;
dSampRate = fsamp;
dLowFreq = 200;% Changed to 40 from 200 as low freq is 40 in gabor as well
dHighFreq = dSampRate / 2;
dPowerCoeff = 1 / 15;
iFiltType = 1;
dFactor = 2.0;
dGammaThreshold = 0.005;
iM = 0; % Changed from 2 to 0 as number of frames coming out to be different due to queue
iN = 4;
iSMType = 0;
dLamda = 0.999;
dLamda2 = 0.5;
dDelta1 = 1;
dLamda3 = 0.85;
dDelta2 = 0.2;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Flags
%
bPreem = 1; % pre-emphasis flag
bSSF = 1;
bPowerLaw = 1;
bDisplay = 0;
dFrameLen = 0.025; % 25.6 ms window length, which is the default setting in CMU Sphinx
dFramePeriod = 0.010; % 10 ms frame period
iPowerFactor = 1;
global iNumFilts;
iNumFilts = 40;
if iNumFilts<30
iFFTSize = 512;
else
iFFTSize = 1024;
end
% For derivatives
deltawindow = 2; % to calculate 1st derivative
accwindow = 2; % to calculate 2nd derivative
% numcoeffs = 13; % number of cepstral coefficients to be used
numcoeffs = 13;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Flags
%
%
% Array Queue Ring-buffer
%
global Queue_aad_P;
global Queue_iHead;
global Queue_iTail;
global Queue_iWindow;
global Queue_iNumElem;
Queue_iWindow = 2 * iM + 1;
Queue_aad_P = zeros(Queue_iWindow, iNumFilts);
Queue_iHead = 0;
Queue_iTail = 0;
Queue_iNumElem = 0;
iFL = floor(dFrameLen * dSampRate);
iFP = floor(dFramePeriod * dSampRate);
iNumFrames = floor((length(ad_x) - iFL) / iFP) + 1;
iSpeechLen = length(ad_x);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Pre-emphasis using H(z) = 1 - 0.97 z ^ -1
%
if (bPreem == 1)
ad_x = filter([1 -0.97], 1, double(ad_x));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Obtaning the gammatone coefficient.
%
% Based on M. Snelly's auditory toolbox.
% In actual C-implementation, we just use a table
%
bGamma = 1;
[wts,binfrqs] = fft2melmx(iFFTSize, dSampRate, iNumFilts, 1, dLowFreq, dHighFreq, iFiltType);
wts = wts';
wts(size(wts, 1) / 2 + 1 : size(wts, 1), : ) = [];
aad_H = wts;
i_FI = 0;
i_FI_Out = 0;
if bSSF == 1
adSumPower = zeros(1, iNumFrames - 2 * iM);
else
adSumPower = zeros(1, iNumFrames);
end
%dLamda_L = 0.998;
aad_P = zeros(iNumFrames, iNumFilts);
aad_P_Out = zeros(iNumFrames - 2 * iM, iNumFilts);
ad_Q = zeros(1, iNumFilts);
ad_Q_Out = zeros(1, iNumFilts);
ad_QMVAvg = zeros(1, iNumFilts);
ad_w = zeros(1, iNumFilts);
ad_w_sm = zeros(1, iNumFilts);
ad_QMVAvg_LA = zeros(1, iNumFilts);
MEAN_POWER = 1e10;
dMean = 5.8471e+08;
dPeak = 2.7873e+09 / 15.6250;
% (1.7839e8, 2.0517e8, 2.4120e8, 2.9715e8, 3.9795e8) 95, 96, 97, 98, 99
% percentile from WSJ-si84
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
dPeakVal = 4e+07;% % 4.0638e+07 --> Mean from WSJ0-si84 (Important!!!)
%%%%%%%%%%%
dMean = dPeakVal;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Obtaining the short-time Power P(i, j)
%
for m = 0 : iFP : iSpeechLen - iFL
ad_x_st = ad_x(m + 1 : m + iFL) .* hamming(iFL);
adSpec = fft(ad_x_st, iFFTSize);
ad_X = abs(adSpec(1: iFFTSize / 2));
aadX(:, i_FI + 1) = ad_X;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Calculating the Power P(i, j)
%
for j = 1 : iNumFilts
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Squared integration
%
if iFiltType == 2
aad_P(i_FI + 1, j) = sum((ad_X .* aad_H(:, j)) .^ 2);
else
aad_P(i_FI + 1, j) = sum((ad_X .^ 2 .* aad_H(:, j)));
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Calculating the Power P(i, j)
%
dSumPower = sum(aad_P(i_FI + 1, : ));
if bSSF == 1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Ring buffer (using a Queue)
%
if (i_FI >= 2 * iM + 1)
Queue_poll();
end
Queue_offer(aad_P(i_FI + 1, :));
ad_Q = Queue_avg();
if (i_FI == 2 * iM)
ad_QMVAvg = ad_Q.^ (1 / 15);
ad_PBias = (ad_Q) * 0.9;
end
if (i_FI >= 2 * iM)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Bias Update
%
for i = 1 : iNumFilts,
if (ad_Q(i) > ad_PBias(i))
ad_PBias(i) = dLamda * ad_PBias(i) + (1 - dLamda) * ad_Q(i);
else
ad_PBias(i) = dLamda2 * ad_PBias(i) + (1 - dLamda2) * ad_Q(i);
end
end
for i = 1 : iNumFilts,
ad_Q_Out(i) = max(ad_Q(i) - ad_PBias(i), 0) ;
if (i_FI == 2 * iM)
ad_QMVAvg2(i) = 0.9 * ad_Q_Out(i);
ad_QMVAvg3(i) = ad_Q_Out(i);
ad_QMVPeak(i) = ad_Q_Out(i);
end
if (ad_Q_Out(i) > ad_QMVAvg2(i))
ad_QMVAvg2(i) = dLamda * ad_QMVAvg2(i) + (1 - dLamda) * ad_Q_Out(i);
else
ad_QMVAvg2(i) = dLamda2 * ad_QMVAvg2(i) + (1 - dLamda2) * ad_Q_Out(i);
end
dOrg = ad_Q_Out(i);
ad_QMVAvg3(i) = dLamda3 * ad_QMVAvg3(i);
if (ad_Q(i) < dFactor * ad_PBias(i))
ad_Q_Out(i) = ad_QMVAvg2(i);
else
if (ad_Q_Out(i) <= dDelta1 * ad_QMVAvg3(i))
ad_Q_Out(i) = dDelta2 * ad_QMVAvg3(i);
end
end
ad_QMVAvg3(i) = max(ad_QMVAvg3(i), dOrg);
ad_Q_Out(i) = max(ad_Q_Out(i), ad_QMVAvg2(i));
end
ad_w = ad_Q_Out ./ max(ad_Q, eps);
for i = 1 : iNumFilts,
if iSMType == 0
ad_w_sm(i) = mean(ad_w(max(i - iN, 1) : min(i + iN ,iNumFilts)));
elseif iSMType == 1
ad_w_sm(i) = exp(mean(log(ad_w(max(i - iN, 1) : min(i + iN ,iNumFilts)))));
elseif iSMType == 2
ad_w_sm(i) = mean((ad_w(max(i - iN, 1) : min(i + iN ,iNumFilts))).^(1/15))^15;
elseif iSMType == 3
ad_w_sm(i) = (mean( (ad_w(max(i - iN, 1) : min(i + iN ,iNumFilts))).^15 )) ^ (1 / 15);
end
end
aad_P_Out(i_FI_Out + 1, :) = ad_w_sm .* aad_P(i_FI - iM + 1, :);
adSumPower(i_FI_Out + 1) = sum(aad_P_Out(i_FI_Out + 1, :));
if adSumPower(i_FI_Out + 1) > dMean
dMean = dLamda_S * dMean + (1 - dLamda_S) * adSumPower(i_FI_Out + 1);
else
dMean = dLamda_L * dMean + (1 - dLamda_L) * adSumPower(i_FI_Out + 1);
end
aad_P_Out(i_FI_Out + 1, :) = aad_P_Out(i_FI_Out + 1, :) / (dMean) * MEAN_POWER;
i_FI_Out = i_FI_Out + 1;
end
else % if not SSF
adSumPower(i_FI + 1) = sum(aad_P(i_FI + 1, :));
if adSumPower(i_FI_Out + 1) > dMean
dMean = dLamda_S * dMean + (1 - dLamda_S) * adSumPower(i_FI_Out + 1);
else
dMean = dLamda_L * dMean + (1 - dLamda_L) * adSumPower(i_FI_Out + 1);
end
aad_P_Out(i_FI + 1, :) = aad_P(i_FI + 1, :) / (dMean) * MEAN_POWER;
end
i_FI = i_FI + 1;
end
%adSorted = sort(adSumPower);
%dMaxPower = adSorted(round(0.98 * length(adSumPower)));
%aad_P_Out = aad_P_Out / dMaxPower * 1e10;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Apply the nonlinearity
%
%dPowerCoeff
if bPowerLaw == 1
aadSpec = aad_P_Out .^ dPowerCoeff;
else
aadSpec = log(aad_P_Out + eps);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% DCT
%
aadDCT = dct(aadSpec')';
%aadDCT(:, numcoeffs+1:iNumFilts) = [];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% MVN
%
% for i = 1 : numcoeffs
% aadDCT( :, i ) = (aadDCT( : , i ) - mean(aadDCT( : , i)))/std(aadDCT(:,i));
% end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Temporal Derivatives
% calculate 1st derivative (velocity)
dt1 = deltacc(aadDCT', deltawindow);
% calculate 2nd derivative (acceleration)
dt2 = deltacc(dt1, accwindow);
% append dt1 and dt2 to mfcco
aadDCT = [aadDCT'; dt2];
% aadDCT = [aadDCT'; dt2];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Display
%
if bDisplay == 1
figure
aadSpec = idct(aadDCT', iNumFilts);
imagesc(aadSpec); axis xy;
end
aadDCT = aadDCT';
%{
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Writing the feature in Sphinx format
%
[iM, iN] = size(aadDCT);
iNumData = iM * iN;
fid = fopen(szOutFeatFileName, 'wb');
fwrite(fid, iNumData, 'int32');
iCount = fwrite(fid, aadDCT(:), 'float32');
fclose(fid);
%}
end
function dt = deltacc(input, winlen)
% calculates derivatives of a matrix, whose columns are feature vectors
tmp = 0;
for cnt = 1 : winlen
tmp = tmp + cnt*cnt;
end
nrm = 1 / (2*tmp);
dt = zeros(size(input));
rows = size(input,1);
cols = size(input,2);
for col = 1 : cols
for cnt = 1 : winlen
inx1 = col - cnt; inx2 = col + cnt;
if inx1 < 1; inx1 = 1; end
if inx2 > cols; inx2 = cols; end
dt(:, col) = dt(:, col) + (input(:, inx2) - input(:, inx1)) * cnt;
end
end
dt = dt * nrm;
end
function [] = Queue_offer(ad_x)
global Queue_aad_P;
global Queue_iHead;
global Queue_iTail;
global Queue_iWindow;
global Queue_iNumElem;
Queue_aad_P(Queue_iTail + 1, :) = ad_x;
Queue_iTail = mod(Queue_iTail + 1, Queue_iWindow);
Queue_iNumElem = Queue_iNumElem + 1;
if Queue_iNumElem > Queue_iWindow
error ('Queue overflow');
end
end
function [ad_x] = Queue_poll()
global Queue_aad_P;
global Queue_iHead;
global Queue_iTail;
global Queue_iWindow;
global Queue_iNumElem;
if Queue_iNumElem <= 0
error ('No elements');
end
ad_x = Queue_aad_P(Queue_iHead + 1, :);
Queue_iHead = mod(Queue_iHead + 1, Queue_iWindow);
Queue_iNumElem = Queue_iNumElem - 1;
end
function[adMean] = Queue_avg()
global Queue_aad_P;
global Queue_iHead;
global Queue_iTail;
global Queue_iWindow;
global Queue_iNumElem;
global iNumFilts;
adMean = zeros(1, iNumFilts); % Changed from 40 (number of filter banks)
iPos = Queue_iHead;
for i = 1 : Queue_iNumElem
adMean = adMean + Queue_aad_P(iPos + 1 ,: );
iPos = mod(iPos + 1, Queue_iWindow);
end
adMean = adMean / Queue_iNumElem;
end
function test(testdir, n, code)
for k = 1:n % read test sound file of each speaker
file = sprintf('%ss%d.wav', testdir, k);
[s, fs] = audioread(file);
%x = s + 0.01*randn(length(s),1); %AWGN Noise
%[SNR1] = snr(s);
%[SNR2] = snr(x) ;
v = PNCC(s, fs); % Compute MFCC's
distmin = inf;
k1 = 0;
for l = 1:length(code) % each trained codebook, compute distortion
d = disteu(v, code{l});
dist = sum(min(d,[],2)) / size(d,1);
if dist < distmin
distmin = dist;
k1 = l;
end
end
msg = sprintf('speaker%d -->> s%d', k, k1);
disp(msg);
end
function r = vqlbg(d,k)
%
% Inputs: d contains training data vectors (one per column)
% k is number of centroids required
e = .01;
r = mean(d, 2);
dpr = 10000;
for i = 1:log2(k)
r = [r*(1+e), r*(1-e)];
while (1 == 1)
z = interdists(d, r);
[m,ind] = min(z, [], 2);
t = 0;
for j = 1:2^i
r(:, j) = mean(d(:, find(ind == j)), 2);
x = interdists(d(:, find(ind == j)), r(:, j));
for q = 1:length(x)
t = t + x(q);
end
end
if (((dpr - t)/t) < e)
break;
else
dpr = t;
end
end
end %Output: r contains the result VQ codebook (k columns, one for each centroids)

Active contours with open ends

Does anyone know how to make an open active contour? I'm familiar with closed contours and I have several Matlab programs describing them. I've tried to change the matrix P but that was not enough: My Matlab code is as follows:
% Read in the test image
GrayLevelClump=imread('cortex.png');
cortex_grad=imread('cortex_grad.png');
rect=[120 32 340 340];
img=imcrop(GrayLevelClump,rect);
grad_mag=imcrop(cortex_grad(:,:,3),rect);
% Draw the initial snake as a line
a=300;b=21;c=21;d=307;
snake = brlinexya(a,b,c,d); % startpoints,endpoints
x0=snake(:,1);
y0=snake(:,2);
N=length(x0);
x0=x0(1:N-1)';
y0=y0(1:N-1)';
% parameters for the active contour
alpha = 5;
beta = 10;
gamma = 1;
kappa=1;
iterations = 50;
% Make a force field
[u,v] = GVF(-grad_mag, 0.2, 80);
%disp(' Normalizing the GVF external force ...');
mag = sqrt(u.*u+v.*v);
px = u./(mag+(1e-10)); py = v./(mag+(1e-10));
% Make the coefficient matrix P
x=x0;
y=y0;
N = length(x0);
a = gamma*(2*alpha+6*beta)+1;
b = gamma*(-alpha-4*beta);
c = gamma*beta;
P = diag(repmat(a,1,N));
P = P + diag(repmat(b,1,N-1), 1) + diag( b, -N+1);
P = P + diag(repmat(b,1,N-1),-1) + diag( b, N-1);
P = P + diag(repmat(c,1,N-2), 2) + diag([c,c],-N+2);
P = P + diag(repmat(c,1,N-2),-2) + diag([c,c], N-2);
P = inv(P);
d = gamma * (-alpha);
e = gamma * (2*alpha);
% Do the modifications to the matrix in order to handle OAC
P(1:2,:) = 0;
P(1,1) = -gamma;
P(2,1) = d;
P(2,2) = e;
P(2,3) = d;
P(N-1:N,:) = 0;
P(N-1,N-2) = d;
P(N-1,N-1) = e;
P(N-1,N) = d;
P(N,N) = -gamma;
x=x';
y=y';
figure,imshow(grad_mag,[]);
hold on, plot([x;x(1)],[y;y(1)],'r');
plot(x([1 end]),y(([1 end])), 'b.','MarkerSize', 20);
for ii = 1:50
% Calculate external force
vfx = interp2(px,x,y,'*linear');
vfy = interp2(py,x,y,'*linear');
tf=isnan(vfx);
ind=find(tf==1);
if ~isempty(ind)
vfx(ind)=0;
end
tf=isnan(vfy);
ind=find(tf==1);
if ~isempty(ind)
vfy(ind)=0;
end
% Move control points
x = P*(x+gamma*vfx);
y = P*(y+gamma*vfy);
%x = P * (gamma* x + gamma*vfx);
%y = P * (gamma* y + gamma*vfy);
if mod(ii,5)==0
plot([x;x(1)],[y;y(1)],'b')
end
end
plot([x;x(1)],[y;y(1)],'r')
I've modified the coefficient matrix P in order to handle cases with open ended active contours, but that is clearly not enough.
My image:

Plot of two variables varied simultaneously, on x-axis

My following code generates a graph with a looping variable for the x-axis. Specifically, eta_22 varies from 0 to 1, with loop iteration size of 0.01.
The code below the line is the source function file.
My question is: How can I generate a graph with eta_1 varying from 0 to 1, with loop iteration size of 0.01 as well? (I want a plot of AA on the y-axis, and eta_1, eta_2 varying from 0 to 1.)
My attempts: I have tried to create nested "for" loops, but the plot itself is looping. I have tried to put the plot line outside of the "for" loops as well, but that did not work.
Thanks for any help.
global Lambda mu mu_A mu_T beta tau eta_1 eta_2 lambda_T rho_1 rho_2 gamma
alpha = 100;
TIME = 365;
eta_22 = zeros(1,alpha);
AA = zeros(1,alpha);
for m = 1:1:alpha
eta_2 = m./alpha;
eta_22(m) = m./alpha;
Lambda = 531062;
mu = (1/70)/365;
mu_A = 0.25/365;
mu_T = 0.2/365;
beta = 0.187/365;
tau = 4/365;
lambda_T = 0.1;
rho_1 = 1/60;
rho_2 = (rho_1)./(270.*rho_1-1);
gamma = 1e-3;
eta_1 = 0;
S0 = 191564208;
T0 = 131533276;
H0 = 2405659;
C0 = 1805024;
C10 = 1000000;
C20 = 1000000;
CT10 = 500000;
CT20 = 500000;
y0 = [S0, T0, H0, C0, C10, C20, CT10, CT20];
[t,y] = ode45('SimplifiedEqns',[0:1:TIME],y0);
S = y(:,1);
T = y(:,2);
H = y(:,3);
C = y(:,4);
C1 = y(:,5);
C2 = y(:,6);
CT1 = y(:,7);
CT2 = y(:,8);
N = S + T + H + C + C1 + C2 + CT1 + CT2;
HIVinf1=[0:1:TIME];
HIVinf2=[beta.*(S+T).*(C1+C2)./N];
HIVinf=trapz(HIVinf1,HIVinf2);
AA(m) = HIVinf;
end
plot(100.*eta_22,AA./1000)
_____________________________________________________________________________________________________
function ydot = SimplifiedEqns(t,y)
global Lambda mu mu_A mu_T beta tau eta_1 eta_2 lambda_T rho_1 rho_2 gamma
S = y(1);
T = y(2);
H = y(3);
C = y(4);
C1 = y(5);
C2 = y(6);
CT1 = y(7);
CT2 = y(8);
N = S + T + H + C + C1 + C2 + CT1 + CT2;
ydot = zeros(8,1);
ydot(1)=Lambda-mu.*S-beta.*(H+C+C1+C2).*(S./N)-tau.*(T+C).*(S./N);
ydot(2)=tau.*(T+C).*(S./N)-beta.*(H+C+C1+C2).*(T./N)-(mu+mu_T).*T;
ydot(3)=beta.*(H+C+C1+C2).*(S./N)-tau.*(T+C).*(H./N)-(mu+mu_A).*H;
ydot(4)=beta.*(H+C+C1+C2).*(T./N)+tau.*(T+C).*(H./N)-(mu+mu_A+mu_T+lambda_T).*C;
ydot(5)=lambda_T.*C-(mu+mu_A+rho_1+eta_1).*C1;
ydot(6)=rho_1.*C1-(mu+mu_A+rho_2+eta_2).*C2;
ydot(7)=eta_1.*C1-(mu+rho_1+gamma).*CT1;
ydot(8)=eta_2.*C2-(mu+rho_2+gamma.*(rho_1)./(rho_1+rho_2)).*CT2+(rho_1).*CT1;
end
The simplest way:
eta_1=0:1/alpha:1;
eta_2=0:1/alpha:1;
lsize=length(eta_1) % I assume eta_1 and eta_2 are of the same size
for i=1:lsize
%Update your AA(i) here
end
plot(eta_1,AA,eta_2,AA)

Integral Calculation

I would like to perform what follows:
where
The parameters shown in the latter figure can be obtained as follows:
%% Inizialization
time = 614.4; % Analysis Time
Uhub = 11;
HubHt = 90;
alpha = 0.14;
TI = 'A'; % Turbulent Intensity (A,B,C as in the IEC or Specific value)
N1 = 4096;
N2 = 32;
N3 = 32;
N = N1*N2*N3; % Total Number of Point
t = 0:(time/(N1-1)):time; % Sampled Time Vector
L1 = Uhub*time; % Box length along X
L2 = 150; % Box length along Y
L3 = 220; % Box length along Z
dx = L1/N1; % Grid Resolution along X-axis
dy = L2/N2; % Grid Resolution along Y-axis
dz = L3/N3; % Grid Resolution along Z-axis
V = L1*L2*L3; % Analysis Box Volume
gamma = 3.9; % Turbulent Eddies Distorsion Factor
c = 1.476;
b = 5.6;
if HubHt < 60
lambda1 = 0.7*HubHt;
else
lambda1 = 42;
end
L = 0.8*lambda1;
if isequal(TI,'A')
Iref = 0.16;
sigma1 = Iref*(0.75*Uhub + b);
elseif isequal(TI,'B')
Iref = 0.14;
sigma1 = Iref*(0.75*Uhub + b);
elseif isequal(TI,'C')
Iref = 0.12;
sigma1 = Iref*(0.75*Uhub + b);
else
sigma1 = str2num(TI)*Uhub/100;
end
sigma_iso = 0.55*sigma1;
sigma2 = 0.7*sigma1;
sigma3 = 0.5*sigma1;
%% Wave number vectors
ik1 = cat(2,(-N1/2:-1/2),(1/2:N1/2));
ik2 = -N2/2:N2/2-1;
ik3 = -N3/2:N3/2-1;
[x y z] = ndgrid(ik1,ik2,ik3);
k1 = reshape((2*pi*L/L1)*x,N1*N2*N3,1);
k2 = reshape((2*pi*L/L2)*y,N1*N2*N3,1);
k3 = reshape((2*pi*L/L3)*z,N1*N2*N3,1);
k = sqrt(k1.^2 + k2.^2 + k3.^2);
%% Calculation of beta by means of the Energy Spectrum Integration
E = #(k) (1.453*k.^4)./((1 + k.^2).^(17/6));
%//Independent integration on segments
Local_int = arrayfun(#(i)quad(E,i-1,i), 2:(N1*N2*N3));
%//integral additivity + cumulative removal of queues
E_int = 1.5 - [0 fliplr(cumsum(fliplr(Local_int)))]; %//To remove queues
E_int = reshape(E_int,N,1);
S = k.*sqrt(E_int);
beta = (c*gamma)./S;
%% Help Parameters
k30 = k3 + beta.*k1;
k0 = sqrt(k1.^2 + k2.^2 + k30.^2);
C1 = (beta.*k1.^2.*(k1.^2 + k2.^2 - k3.*k30))./(k.^2.*(k1.^2 + k2.^2));
C2 = (k2.*k0.^2./((k1.^2 + k2.^2).^(3/2))).*atan2((beta.*k1.*sqrt(k1.^2 + k2.^2)),(k0.^2 - k30.*k1.*beta));
xhsi1 = C1 - (k2./k1).*C2;
xhsi2 = (k2./k1).*C1 + C2;
E_k0 = (1.453*k0.^4)./((1 + k0.^2).^(17/6));
For instance, typing in
phi_33 = #(k2,k3) (E_k0./(4*pi.*k.^4)).*((k1.^2 + k2.^2));
F_33 = arrayfun(#(i) dblquad(phi_33,k3(i),k3(i+1),k2(i),k2(i+1)), 1:((N1*N2*N3)-1));
Matlab retrieves the following error msg:
Error using +
Matrix dimensions must agree.
Error in #(k2,k3)(E_k0./(4*pi.*k.^4)).*((k1.^2+k2.^2))
Do you have a clue how to overcome this issue?
I really look forward to hearing from you.
Best regards,
FPE
The error is easily explained:
First you define E_k0 then you try to call Ek0.
phi_11 = #(k1,k2,k3) (E_k0./4*pi.*kabs.^4).*(k0abs.^2 - k1.^2 - 2*k1.*k03.*xhsi1 + (k1.^2 + k2.^2).*xhsi1.^2);
I solved it this way:
Code a function for each of the PHI elements, such as (for PHI11)
function phi_11 = phi_11_new(k1,k2,k3,beta,i)
k = sqrt(k1(i).^2 + k2.^2 + k3.^2);
k30 = k3 + beta(i).*k1(i);
k0 = sqrt(k1(i).^2 + k2.^2 + k30.^2);
E_k0 = 1.453.*k0.^4./((1 + k0.^2).^(17/6));
C1 = (beta(i).k1(i).^2).(k1(i).^2 + k2.^2 - k3.k30)./(k.^2.(k1(i).^2 + k2.^2));
C2 = k2.*k0.^2./((k1(i).^2 + k2.^2).^(3/2)).*atan2((beta(i).*k1(i).*sqrt(k1(i).^2 + k2.^2)),(k0.^2 - k30.*k1(i).*beta(i)));
xhsi1 = C1 - k2./k1(i).*C2;
xhsi1_q = xhsi1.^2;
phi_11 = E_k0./(4.*pi.k0.^4).(k0.^2 - k1(i).^2 - 2.*k1(i).*k30.*xhsi1 + (k1(i).^2 + k2.^2).*xhsi1_q);
end
I recall this function within the main code as follows
for l = 1:numel(k1)
phi11 = #(k2,k3) phi_11(k1,k2,k3,l)
F11(l) = integral2(phi,-1000,1000,-1000,1000);
end
at it seems it works.

Perform step-by-step integral

I have this piece of code:
time = 614.4;
Uhub = 11;
HubHt = 90;
TI = 'A';
N1 = 4096;
N2 = 32;
N3 = 32;
L1 = Uhub*time;
L2 = 150;
L3 = 220;
V = L1*L2*L3;
gamma = 3.9;
c = 1.476;
b = 5.6;
if HubHt < 60
lambda1 = 0.7*HubHt;
else
lambda1 = 42;
end
L = 0.8*lambda1;
if isequal(TI,'A')
Iref = 0.16;
sigma1 = Iref*(0.75*Uhub + b);
elseif isequal(TI,'B')
Iref = 0.14;
sigma1 = Iref*(0.75*Uhub + b);
elseif isequal(TI,'C')
Iref = 0.12;
sigma1 = Iref*(0.75*Uhub + b);
else
sigma1 = str2num(TI)*Uhub/100;
end
sigma_iso = 0.55*sigma1;
%% Wave number vectors
ik1 = cat(2,(-N1/2:-1/2),(1/2:N1/2));
ik2 = -N2/2:N2/2-1;
ik3 = -N3/2:N3/2-1;
[x y z] = ndgrid(ik1,ik2,ik3);
k1 = reshape((2*pi*L/L1)*x,N1*N2*N3,1);
k2 = reshape((2*pi*L/L2)*y,N1*N2*N3,1);
k3 = reshape((2*pi*L/L3)*z,N1*N2*N3,1);
k = sqrt(k1.^2 + k2.^2 + k3.^2);
Now I should calculate
where
The procedure to calculate the integral is
At the moment I'm using this loop
E = #(k) (1.453*k.^4)./((1 + k.^2).^(17/6));
E_int = zeros(1,N1*N2*N3);
E_int(1) = 1.5;
for i = 2:(N1*N2*N3)
E_int(i) = E_int(i) + quad(E,i-1,i);
end
neglecting for the k>400 approximation. I believe that my loop is not right.
How would you suggest to calculate the integral?
I thank you in advance.
WKR,
Francesco
This is a list of correction from the more obvious to the possibly more subtle. (Indeed I start from what you wrote in the final part going upwards).
From what you write:
E = #(k) (1.453*k.^4)./((1 + k.^2).^(17/6));
E_int = zeros(1,N1*N2*N3);
E_int(1) = 1.5;
for i = 2:(N1*N2*N3)
%//No point in doing this:
%//E_int(i) = E_int(i) + quad(E,i-1,i);
%//According to what you write, it should be:
E_int(i) = E_int(i-1) + quad(E,i-1,i);
end
You could speed the whole thing up by doing
%//Independent integration on segments
Local_int = arrayfun(#(i)quad(E,i-1,i), 2:(N1*N2*N3));
Local_int = [1.5 Local_int];
%//integral additivity
E_int = cumsum(Local_int);
Moreover, if the known condition (point 2.) really is "... ( = 1.5 if k' = 0)", then the whole implementation should really be more like
%//Independent integration on segments
Local_int = arrayfun(#(i)quad(E,i-1,i), 2:(N1*N2*N3));
%//integral additivity + cumulative removal of queues
E_int = 1.5 - [0 fliplr(cumsum(fliplr(Local_int)))]; %//To remove queues