unexpected output from a for loop in matlab - matlab

am trying to execute the following code on matlab i've a for loop inside a function and it's supposed to store a result at every iteration ,, but when it executes it just gives me the result of the last iteration,, is there something wrong with the sequence of the code ?
the inpit data1 is a data vector of size (33167*1)
i doubt that there is sometnig wrong with the foor loop.. there is the code i wrote :
function [vectorDominant] = processData(data1 , samplingRate , startRange, endRange)
%(length(data)/1000)
data = data1;
windowSize = 10;
samplingRate = samplingRate;
frame_len = samplingRate*windowSize;
l = length(data);
num_frames = floor(l/frame_len);
t = 1;
for i = 1 : num_frames
frame = data( (i-1)*frame_len+1 : frame_len*i);
% --- haming window ------
hammingData=frame.*hamming(length(frame));
%---- remove dc offset from data ----
dataWindowed = detrend(hammingData);
% ---- apply fft ----
fourierTransform_data=fft(dataWindowed);
y = fourierTransform_data ;
%plot(abs(fourierTransform_data))
%------- find dominant-----
len = (length(frame)/2) -1;
y = y(1:len);
[v,k] = max(y);
fftLength = length(frame);
freq = (0:(samplingRate/fftLength) :(samplingRate/2));
%plot(freq,abs(y)), grid('on'), title('dominant freq')
freq = freq(find(freq>=startRange & freq<=endRange));
dominantFrequency = freq(k);
%array[(length(data)/1000)];
%var = 1;
%while var<= length(num_frames)
n = (length(data)/1000);
vectorDominant = zeros(n,1); % to preallocate it first as it changes size every iterartion
vectorDominant(i) = dominantFrequency;
%var = var+1;
%end
end
end
the argument i give it is processData(ax, 100, 0.1, 2) where ax is the
data vector and it returns the following ans =
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0.2000
the whole result must have numbers like the last one (0.2000) not zeros

Every time through the loop you recreate vectorDominant to be a vector of zeros and then set one element of it to be the newly calculated value. Presumably the first 2 of the following lines should be done once before entering the loop.
n = (length(data)/1000);
vectorDominant = zeros(n,1);
vectorDominant(i) = dominantFrequency;
Presumably n should also be num_frames not the value calculated above.

Related

Compute matrix with symbolic variable

I have the following MATLAB script:
var_theta = sym('theta', [1,7]);
matrix_DH = computeDH(var_theta);
T_matrix = zeros(4,4,7);
for i = 1:7
T_matrix(:,:,i) = computeT(matrix_DH(i,1), matrix_DH(i,2), matrix_DH(i,3), matrix_DH(i,4));
end
function matrixT = computeT(alpha, d, r, theta)
matrixT = zeros(4,4);
matrixT(1,:) = [cos(theta) -1*sin(theta) 0 r]; % first row
matrixT(2,:) = [sin(theta)*cos(alpha) cos(theta)*cos(alpha) -sin(alpha) -d*sin(alpha)]; % 2n row
matrixT(3,:) = [sin(theta)*sin(alpha) cos(theta)*sin(alpha) cos(alpha) d*cos(alpha)]; % 3rd row
matrixT(4,:) = [0 0 0 1]; % last row
end
function DH = computeDH(theta)
DH = zeros(7,4);
L = 0.4;
M = 0.39;
DH(1,:) = [0.5*pi 0 0 theta(1,1)];
DH(2,:) = [-0.5*pi 0 0 theta(2)];
DH(3,:) = [-0.5*pi L 0 theta(3)];
DH(4,:) = [0.5*pi 0 0 theta(4)];
DH(5,:) = [0.5*pi M 0 theta(5)];
DH(6,:) = [-0.5*pi 0 0 theta(6)];
DH(7,:) = [0 0 0 theta(7)];
end
I would like to obtain the desired array of T_matrix without evaluating the theta's. My objective is that after getting the matrices, derivate each position by each theta in order to compute the Jacobian. So at the end I would like the resulting matrices as a function of the thetas. The problem is that whenever I insert the symbolic variable into the matrix it says:
The following error occurred converting from sym to double:
Unable to convert expression into double array.
Error in computeT_robotics>computeDH (line 21)
DH(1,:) = [0.5*pi, 0, 0, theta(1)];
As Anthony stated, the matrices that my theta is included in, need to be declared as sym as well in order to be able to save symbolic results.
Final code:
var_theta = sym('theta', [1,7]);
matrix_DH = computeDH(var_theta);
T_matrix = sym('T_matrix',[4 4 7]);
for i = 1:7
T_matrix(:,:,i) = computeT(matrix_DH(i,1), matrix_DH(i,2), matrix_DH(i,3), matrix_DH(i,4));
end
function matrixT = computeT(alpha, d, r, theta)
matrixT = sym('matrixT', [4 4]);
matrixT(1,:) = [cos(theta) -1*sin(theta) 0 r]; % first row
matrixT(2,:) = [sin(theta)*cos(alpha) cos(theta)*cos(alpha) -sin(alpha) -d*sin(alpha)]; % 2n row
matrixT(3,:) = [sin(theta)*sin(alpha) cos(theta)*sin(alpha) cos(alpha) d*cos(alpha)]; % 3rd row
matrixT(4,:) = [0 0 0 1]; % last row
end
function DH = computeDH(theta)
DH = sym('DH',[7 4]);
L = 0.4;
M = 0.39;
DH(1,:) = [0.5*pi 0 0 theta(1,1)];
DH(2,:) = [-0.5*pi 0 0 theta(2)];
DH(3,:) = [-0.5*pi L 0 theta(3)];
DH(4,:) = [0.5*pi 0 0 theta(4)];
DH(5,:) = [0.5*pi M 0 theta(5)];
DH(6,:) = [-0.5*pi 0 0 theta(6)];
DH(7,:) = [0 0 0 theta(7)];
end

MATLAB: Limit from n to infinity for power of a matrix

I am trying to compute lim(n->inf) for D^n, where D is a diagonal matrix:
D = [1.0000 0 0 0; 0 0.6730 0 0; 0 0 0.7600 0; 0 0 0 0.7370]
n = 1
L = limit(D^n,n,inf)
This returns the error:
Undefined function 'limit' for input arguments of type 'double'.
I am sure this should result in most entries except the upper-left entry going to zero, but I need to be able to present this with MATLAB results. Is there something else I need to include in my limit function?
If your problem is to compute the inf-limit of a diagonal matrix, you'd better create your own function and handle manually the possible cases :
function Mlim = get_diag_matrix_inf_limit(M)
% get the diagonal
M_diag = diag(M);
% All possible cases
I_nan = M_diag <= -1;
I_0 = abs(M_diag) < 1;
I_1 = M_diag == 1;
I_inf = M_diag > 1;
% Update diagonal
M_diag(I_nan) = nan;
M_diag(I_0) = 0;
M_diag(I_1) = 1;
M_diag(I_inf) = Inf;
% Generate new diagonal matrix
Mlim = diag(M_diag);
end

Don't know how to Correct : "In an assignment A(I) = B, the number of elements in B and I must be the same."

I saw other topics about this error but I couldn't figure it out. The error "In an assignment A(I) = B, the number of elements in B and I must be the same" occurs at the second for loop. How can I change my code to avoid this error?
h1 = [70 31.859 15 5.774 3.199 2.15 1.626];
h2 = [31.859 15 5.774 3.199 2.15 1.626 1.415];
b = [1253 1253 1253 1253 1253 1253 1253];
R = [455.4 425.6 377.6 374.9 371.3 273.7 268.3];
r = [0.5448714286 0.5291754292 0.6150666667 0.4459646692 0.3279149734 0.2437209302 0.1297662977];
k = [200 200 200 200 200 200 200];
s = sqrt(r/(1-r));
v2 = [20 0 0 0 0 0 0];
v1 = [0 0 0 0 0 0 0];
Ch1 = [0 0 0 0 0 0 0];
Ch2 = [0 0 0 0 0 0 0];
C = [100 100 100 100 100 100 100];
F = b .* k .* sqrt(R-(h1-h2))- R.*sin((acos((R-((h1-h2)./2))./R))) .* (pi/2) .* (1./sqrt(r./(1-r))) .* (atan(sqrt(r./(1-r))))-(pi/4) - (1./(sqrt(r./(1-r)) .* sqrt(h2./R))).* log((h2+R.*((sqrt(h1./R).*tan(1/2 .* atan(sqrt(r./(1-r)).*sqrt(h1./r).*log(1./(1-k))))).^2).*sqrt(1-r))./h2)
M = -R.*R.*(k./2).*(.2*(sqrt(h2./R)*tan(0.5*(atan(s)))-(pi/8).*sqrt(h2./R).*log(1./1-r)))-(acos((R-((h1-h2)./2))./R))
for i=1:6
v1(i) = ((v2(i)*h2)/h1);
v2(i+1) = v1(i);
end
vr = ((v1.*h1)./h2)./(((tan(0.5.*((atan(s)))-(pi/8).*sqrt(h2./R).*log(1./(1-r)))).^(2))+1)
%--------------------------------------------------------------------------
% Calculating E
w = (((2.*R.*h2).^(3/2))./(300.*(b.^2)))
if (w <= (3*10^-4));
E = ((0.0821.*((log(w))^2))+(1.25.*log(w))+4.89)
end
if ((3*10^-4)<= w <= (2.27*10^-3));
E = ((0.0172.*((log(w)).^2))+(0.175.*log(w))+0.438)
end
if (w > (2.27*10^-3))
E = 0.01
end
%--------------------------------------------------------------------------
% Calculating Ch:
y = ((((2.*R).^(0.5)).*((h2).^(1.5)))./(b.^2))
N1 = (0.5-(1/pi).*atan((log(y)+8.1938)./(1.1044)))
N = ((h2./h1).*N1)
for i=1:1;7
Ch2(i) = (h2.*((N.*((Ch1(i)./h2)-(C./h2)))+(C/h2)))
Ch1(i+1) = Ch2(i)
end
DeltaStrain = (E.*((Ch2./h2)-(Ch1./h1)))
if DeltaStrain > 0;
Stepp = ((2/pi).*(sqrt(DeltaStrain))))
Control = 2;
else
Stepp = ((2/pi).*(sqrt(-DeltaStrain))
Control = 0;
end
In the line
Ch2(i) = (h2.*((N.*((Ch1(i)./h2)-(C./h2)))+(C/h2)))
h2 is a vector, and Ch2(i) is a scalar. You cannot assign the value of a vector to a scalar. I suspect you want to replace the entire for loop. Right now you have
for i=1:1;7
Ch2(i) = (h2.*((N.*((Ch1(i)./h2)-(C./h2)))+(C/h2)))
Ch1(i+1) = Ch2(i)
end
(?? what is the meaning of 1:1;7? Is that a typo? I am thinking you want 1:7...
Since you seem to be using the result of one loop to change the value of Ch1 which you are using again in the next loop, it may be tricky to vectorize; but I wonder what you are expecting the output to be, since you really do have a vector as the result of the RHS of the equation. I can't be sure if you want to compute the result for one element at a time, or whether you want to compute vectors (and end up appending results to Ch1 and Ch2). The following line would run without throwing an error - but it may not be the calculation you want. Please clarify what you are hoping to achieve if this is an incorrect guess.
for i = 1:7
Ch2(i) = h2.*(N.*((Ch1(i) - C(i))./h2(i))) + C(i)./h2(i);
Ch1(i+1) = Ch2(i);
end

How to set up a matrix with a fixed pattern

I need to write a script to automatically setup a matrix A. The size of this matrix is linked to the value of another variable in the workspace, N. In general, A will have N + N*(N-1)/2 rows and N columns.
The first N rows and N columns are basically just a diagonal matrix, which is easy to setup using diag.
I'm having problems setting up the lower part of the matrix. Basically, it needs to have the following form:
-1 0 0 0
0 -1 0 0
0 0 -1 0
0 0 0 -1
1 -1 0 0
1 0 -1 0
1 0 0 -1
0 1 -1 0
0 1 0 -1
0 0 1 -1
I'm sure the pattern is clear.
How do I code this so that Matlab sets up this matrix for ANY value of N?
Thanks
With some algebraic manipulation:
L=(N*(N+1)/2):-1:1;
R=ceil((sqrt(8*L+1)-1)/2);
A=bsxfun(#eq, N-1:-1:0, R')-bsxfun(#eq, N:-1:1, (L-(R.*(R-1))/2).');
UPDATE
Performance version including preallocation.
N=4;
result = zeros(N*(N+1)/2,N+1);
t = N;
endpos = 0;
for t = N:-1:1
result(endpos+1:endpos+t,:) = [zeros(t, N-t) ones(t,1) -eye(t)];
endpos = endpos + t;
end
result = result(:,2:end);
Note that I have replaced the while loop as you seem to prefer a for.
I will leave the original here as well for comparison:
Here you go:
result = [];
N = 4;
t = MaxN;
while t > 0
block = [zeros(t, N-t) ones(t,1) -eye(t)];
result = [result; block];
t = t-1;
end
result = result(:,2:end);
Thank everyone! I will post my own solution here (doesn't pre-allocate though). Might adjust it to #Dennis's solution.
N = max(size(a));
P = N*(N-1)/2;
A = zeros(N+P,N);
A(1:N,1:N) = diag(-a);
B=[];
for i = N-1:-1:1
Block = [zeros(i,N-1-i) ones(i,1) -eye(i)];
B = [B; Block];
clear Block
end
A(N+1:end,:) = B;
clear N P B i

how to repeat function with for loop?

I am trying to generate a pn sequence and it works. However, when I try I call the function with different inputs in a for-loop, it gives me the same results each time. As if it is not affected by using the for loop. Why?
This is my code:
%e.g. noof flip flops 4 ==>
function[op_seq]=pnseq(a,b,c)
a = 7;
%generator polynomial x4+x+1 ==>
b = [1 0 0 1 1 0 1 ]
%initial state [1 0 0 0] ==>
c = [1 0 0 0 1 0 1 ]
%refere figure to set a relation between tap function and initial state
%
for j= 1:50,
x = a;
tap_ff =b;
int_stat= c;
for i = 1:1: length(int_stat)
old_stat(i) = int_stat(i);
gen_pol(i) = tap_ff(i);
end
len = (2 ^x)-1;
gen_pol(i+1)= 1;
gen_l = length(gen_pol);
old_l = length(old_stat);
for i1 = 1: 1:len
% feed back input genration
t = 1;
for i2 = 1:old_l
if gen_pol(i2)==1
stat_str(t) = old_stat(gen_l - i2);
i2 = i2+1;
t = t+1;
else
i2 = i2+1;
end
end
stat_l = length(stat_str);
feed_ip = stat_str(1);
for i3 = 1: stat_l-1
feed_ip = bitxor(feed_ip,stat_str(i3 + 1));
feed_ipmag(i1) = feed_ip;
i3 = i3+1;
end
% shifting elements
new_stat = feed_ip;
for i4 = 1:1:old_l
new_stat(i4+1) = old_stat(i4);
old_stat(i4)= new_stat(i4);
end
op_seq(i1) = new_stat(old_l +1);
end
%op_seq;
end
I assume you're doing something like:
for n = 1:10
...
% set a,b,c for this n
...
op_seq =pnseq(a,b,c)
...
end
and that you see the same op_seq output for each case. This is because you have a,b,c as inputs, but you overwrite them at the start of your function. If I remove, or comment out the following lines in your function:
a = 7;
b = [1 0 0 1 1 0 1 ]
c = [1 0 0 0 1 0 1 ]
Then I get different results for calling the function with different a,b,c. There is nothing random in your function, so the same inputs give the same outputs.