Good day,
I would like to do the following in Matlab:
var1 = 10;
var2 = 15;
var3 = 20;
j = 1;
for i = [var1,var2,var3]
a(j) = i + 10;
j = j + 1;
end
clear j;
With result:
a(1) = var1 + 10 = 20
a(2) = var1 + 10 = 25
a(3) = var1 + 10 = 30
Any ideas?
Engaging heavy use of crystal ball. It appears that you'd like to dynamically generate the names var1, var2, etc. Don't. There is just about never an advantage to naming variables this way. Use cell arrays instead:
var{1} = 10;
var{2} = 15;
var{3} = 20;
so that you can just use:
for i = 1:length(var)
a(j) = var{i} + 10;
...
Note the curly brace.
If your variables are all the same size, it's even better to use array slices. var(:, i) or var(:,:,:,i), for example
There was a similar question with a successful answer: foreach loop with strings in Matlab
maybe use the cell array syntax with {}:
for i = {var1,var2,var3}
a(j) = i + 10;
j = j + 1;
end
Both #FloHin and #Peter have mentioned using cells, which is a great method to help you when you have a limited number of non-scalar variables. In case you are dealing with unknown number of such variables that follow a certain format, you can use eval function to get the value of the current variable on-demand:
var1 = 10;
var2 = 15;
var3 = 20;
var4 = 30;
# ...
# more variables following the varN = x pattern
all_variables = who('var*');
num = numel(all_variables);
a = zeros(num, 1);
for i = 1:num
a(i) = eval(all_variables{i}) + 10;
end
Related
I have an m-file ParamStruct.m. Below are the contents of that file:
global Params
total_params = [];
Params.one = 1;
Params.two = 2;
Params.three = 3;
total_params = [total_params;Params];
Params.one = 4;
Params.two = 5;
Params.three = 6;
total_params = [total_params;Params];
for ii = length(total_params)
Add_Param_Vals
end
Then I have another m-file which I use as a script called Add_Param_Values. The contents of that file are as follows:
global Params
disp("adding values: ")
Params.one + Params.two
The purpose of the two m-files is to 1.) define two Params structs in ParamStruct.m, then call Add_Param_Values from ParamStruct so that for each call, I can utilize the current Params struct as indexed by the for loop in ParamStruct. For example, when I run ParamStruct at the output I would like to see the following:
adding values:
ans =
3
adding values:
ans =
9
But instead I am seeing
adding values:
ans =
9
So it seems like it is only utilizing the last element in the total_params variable and I dont know how to correct that. I do not want to modify anything in the Add_Param_Vals m-file as I am not the owner of it. Any ideas??
Sorry for the post. I was able to figure it out. Here is what I ended up doing:
global Params
total_params = [];
Params.one = 1;
Params.two = 2;
Params.three = 3;
total_params = [total_params;Params];
Params.one = 4;
Params.two = 5;
Params.three = 6;
total_params = [total_params;Params];
for ii = 1:length(total_params)
Params = total_params(ii);
Add_Param_Vals
end
I have a simple nested for loop indexing problem that I'm unable to solve.
I would like to index x from 1:NaNb using only i and j. So I would like to replace "a" in the following code with combination of i and j where it will index from 1 to Na*Nb. The two for loops cannot be changed as they are used for other calculations. The only thing that should be modified is "a". Will appreciate for any suggestions. Thank you in advance!
for i = 1:Na
for j = 1:Nb
x(a) = ABC;
end
end
With the limit context and variable types/declarations, this is what I came up with. The index of x() is calculated by using a combination of i and j.
Method 1:
Na = 10;
Nb = 10;
x = strings(1,Na*Nb);
for i = 1:Na
for j = 1:Nb
x(1,((i-1)*Na + j)) = 'ABC';
end
end
Method 2:
Na = 10;
Nb = 10;
x = strings(1,Na*Nb);
Index = 1;
for i = 1:Na
for j = 1:Nb
x(Index) = 'ABC';
Index = Index + 1;
end
end
If ABC is a variable of type integer
Na = 10;
Nb = 10;
ABC = 1;
x = zeros(1,Na*Nb);
for i = 1:Na
for j = 1:Nb
x(1,((i-1)*Na + j)) = ABC;
end
end
Using MATLAB version: R2019b
In the Simulink model below my interpreted function output is a vector with 38 elements. I have two functions that have the same outputs one of them works perfectly (desiredtrajectory_sim.m) but the other one doesn't (desiredtrajectory.m).
Any suggestions. thanks
Here is the Simulink model
function [desired_state] = desiredtrajectory_sim(in)
t = in(1);
Sf = [ 1; 2; pi/4];
dSf = [0;0;0];
Pf = [ 0.1*t; 0; 0.5*sin(0.03*pi*t) + 2; 0; 0.01*pi*t ; 0];
dPf = [ 0.1; 0; 0.5*0.03*pi*cos(0.03*pi*t); 0; 0.01*pi; 0];
pf = Sf(1); qf = Sf(2); betaf = Sf(3);
xf = Pf(1); yf = Pf(2); zf = Pf(3);
phif = Pf(4); thetaf = Pf(5); psif = Pf(6);
rf = sqrt(pf^2 + qf^2 - 2*pf*qf*cos(betaf));
h1 = sqrt(0.5*(pf^2 + qf^2 - 0.5*rf^2));
h2 = sqrt(0.5*(rf^2 + pf^2 - 0.5*qf^2));
h3 = sqrt(0.5*(qf^2 + rf^2 - 0.5*pf^2));
alpha1 = acos((4*(h1^2+h2^2)-9*pf^2)/(8*h1*h2));
alpha2 = acos((4*(h1^2+h3^2)-9*qf^2)/(8*h1*h3));
Rot = RPYtoRot_ZXY(phif, thetaf, psif);
r1 = Rot*[2/3*h1;0;0];
r2 = Rot*[2/3*h2*cos(alpha1);2/3*h2*sin(alpha1);0];
r3 = Rot*[2/3*h3*cos(alpha2);-2/3*h3*sin(alpha2);0];
pos_des1 = [xf;yf;zf] + r1;
pos_des2 = [xf;yf;zf] + r2;
pos_des3 = [xf;yf;zf] + r3;
omega = [0 -sin(psif) cos(thetaf)*cos(psif);...
0 -cos(psif) cos(thetaf)*sin(psif);...
1 0 -sin(thetaf)]*dPf(4:6);
vel_des1 = dPf(1:3) + cross(omega, r1);
vel_des2 = dPf(1:3) + cross(omega, r2);
vel_des3 = dPf(1:3) + cross(omega, r3);
acc_des = [0;0;0];
desired_state1 = [pos_des1;vel_des1;acc_des];
desired_state2 = [pos_des2;vel_des2;acc_des];
desired_state3 = [pos_des3;vel_des3;acc_des];
desired_state = [desired_state1;desired_state2;desired_state3; psif; 0; Pf;
Sf]
size(desired_state)
end
Here is the Simulink block and the error message
As you can notice the bus gives just one element compared to the previous one which gives 38 elements, although they have the same output.
function [desired_state] = desiredtrajectory(in)%(t, pos)
tm= in(1)
pos = in(2:10);
syms t xf yf zf phif thetaf psif pf qf betaf
rf = sqrt(pf^2+qf^2-2*pf*qf*cos(betaf));
h1 = sqrt(0.5*(pf^2+qf^2-0.5*rf^2));
h2 = sqrt(0.5*(rf^2+pf^2-0.5*qf^2));
h3 = sqrt(0.5*(qf^2+rf^2-0.5*pf^2));
alf1 = acos((4*(h1^2+h2^2)-9*pf^2)/(8*h1*h2));
alf2 = acos((4*(h1^2+h3^2)-9*qf^2)/(8*h1*h3));
Rot = RPYtoRot_ZXY(phif, thetaf, psif);
eps = [Rot*[2/3;0;0]+[xf;yf;zf]
Rot*[2/3*h2*cos(alf1);2/3*h2*sin(alf1);0]+[xf;yf;zf]
Rot*[2/3*h2*cos(alf2);-2/3*h3*sin(alf2);0]+[xf;yf;zf]];
X = [ xf yf zf phif thetaf psif pf qf betaf];
Sf = [ 1; 2; pi/4];
dSf = [0;0;0];
Pf = [ 0.1*t; 0; 0.5*sin(0.03*pi*t) + 2; 0; 0.01*pi*t ; 0];
dPf = [ 0.1; 0; 0.5*0.03*pi*cos(0.03*pi*t); 0; 0.01*pi; 0];
qd = [Pf; Sf];
qddot = [dPf; dSf];
jac = jacobian(eps,X);
%%%%%%%%%%%%%
pf = Sf(1); qf = Sf(2); betaf = Sf(3);
xf = Pf(1); yf = Pf(2); zf = Pf(3);
phif = Pf(4); thetaf = Pf(5); psif = Pf(6);
x1=pos(1);
y1=pos(2);
z1=pos(3);
x2=pos(4);
y2=pos(5);
z2=pos(6);
x3=pos(7);
y3=pos(8);
z3=pos(9);
qpf=[(x1+x2+x3)/3;...
(y1+y2+y3)/3;...
(z1+z2+z3)/3;...
atan2((2*z1/3-z2/3-z3/3),(2*y1/3-y2/3-y3/3)); ...
-atan2((2*z1/3-z2/3-z3/3),(2*x1/3-x2/3-x3/3)); ...
atan2((2*y1/3-y2/3-y3/3),(2*x1/3-x2/3-x3/3))];
qsf=[sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2); ...
sqrt((x1-x3)^2+(y1-y3)^2+(z1-z3)^2); ...
acos((pf^2+qf^2-rf^2)/(2*pf*qf))];
q = [qpf;qsf];
%%%%%%%%%%%%%
%%%pos_desired%%%%%%%
pos_des = eval(eps);
pos_des =subs(pos_des,t,tm);
jacval = eval(jac);
qd = eval(qd);%subs(qd,t,tm);
q = eval(q);
qe = qd - q;
qddot = eval(qddot);%subs(qddot,t,tm);
kappa=0.2*eye(9);
qrefdot = qddot + kappa*qe;
vel_des = jacval*qrefdot;
vel_des = subs(vel_des,t,tm);
acc_des = zeros(3,1);
yaw = 0;
yawdot = 0;
% =================== Your code ends here ===================
desired_state1 = [pos_des(1:3);vel_des(1:3);acc_des];
desired_state2 = [pos_des(4:6);vel_des(4:6);acc_des];
desired_state3 = [pos_des(7:9);vel_des(7:9);acc_des];
Pf = subs(Pf,t,tm);
Sf = subs(Sf,t,tm);
format short
digits(3);
desired_state = vpa([desired_state1;desired_state2;desired_state3; psif; 0;
Pf; Sf])
size(desired_state)
end
The second image shows that the output of the second function is a scalar - the dimension at the output of the block is 1 - not 38 as you believe it is.
That is, your functions do not give the same output as you believe they do.
The error is because the Selector blocks expect their inputs to be dimension 38, and they are not.
To determine why what you believe is happening is not actually what is happening, you could use the editor to set a break point in the m-code, run the model, then step through the code to determine why it gives a scalar output when you expect it to do otherwise.
Another approach would be to run your functions from the MATLAB Command Line with fake input data. Something like
tmp = desiredtrajectory(randn(10,1))
would be appropriate here.
The answer is that desiredtrajectory outputs desired_state, which is a symbolic variable. Yes it contains a 38 element vector, but Simulink treats the object itself is a scalar.
The real problem though is that you can't propagate a symbolic variable down a Simulink signal. You need the output to be a numeric vector.
One way to overcome this is to put the line
desired_state = double(desired_state);
at the end of your file to cast the symbolic object to a double, which will have 38 elements.
(However it's not clear why you are using symbolic math in the first place, and I'd suggest it would be better, and is certainly more efficient, if you didn't use it.)
I need to compute the sum of this series
I need the output this way:
If n = 3;
x = function_name(n)
I need to get x = 11.
If n = 5;
x = function_name(n)
I need to get x = 45.
I believe I need a for-loop to iterate; but am finding it difficult to iterate the increment value itself.
I guess you want the sum of the cumsum of the differences d of the numbers:
d = 2;
n = 5;
s = d:d:d*(n-1)
cs = cumsum( [1 s] )
scs = sum(cs)
%// or as anonymous function
scsh = #(n,d) sum( cumsum( [1 d:d:d*(n-1)] ) )
scs =
45
scsh(5,2) =
45
No need for a loop!
inc=2;
sum=1;
next=1;
n=input('what is n?\n');
for i=2:n
next=next+inc;
sum=sum+next;
inc=inc+2;
end
disp('sum is ');
disp(sum);
function Total = abc(n)
nth_term=1;
Total = 1 ;
for d = 2:2:(2*(n-1))
nth_term = nth_term + d;
Total =Total + nth_term;
end
end
I wrote a code in Matlab which I predefine the variable "a" and then set up a for loop of 5 iterations where the variable "a" goes through some basic operations. However, the for loop output only saves the fifth iteration of "a." How do I save all 5 iterations in a 1x5 array?
The code is as follows:
a = 10;
k = 0.5;
n = 2;
for m = 1:5
a = a + (a*k) + n;
end
Edit:
I just found it that I have to create a new variable.
a = 10;
k = 0.5;
n = 2;
a_n = zeros(1,5);
for m = 1:5
a = a + (a*k) + n;
a_n(m) = a;
end
You may need to store value of a after each iteration into an another variable x
a = 10;
k = 0.5;
n = 2;
for m = 1:5
a = a + (a*k) + n;
x(m) = a;
end
x
Output:
x =
17.000 27.500 43.250 66.875 102.312
You would need to use a different variable to store the 5 iterations as an array.
Code would look something like this:
a = 10;
k = 0.5;
n = 2;
b = [];
for m = 1:5
a = (a + (a*k) + n)
b = [b a];
end
You can now print b for all 5 iteration values.
Here is an alternate way to update values into the 1-D matrix.