MATLAB vector element conflict. - matlab

I have been having trouble getting rid of this error. I have read several similar question, but I just must be overlooking something very simple. The following code uses ODE45. There are 3 initial conditions, and it appears to me that my function outputs 3 variables as well. However, it says:
"??? Error using ==> odearguments at 116
DBTS returns a vector of length 2, but the length of initial
conditions vector is 3. The vector returned by DBTS and the
initial conditions vector must have the same number of elements."
This is my m-file:
function dDdt=Dbts(t,i)
global p1 p2 p3 n V1 Gb Ib U
I=i(1);
X=i(2);
G=i(3);
dIdt=-(n*(I-Ib))+(U/V1);
dXdt=-(p2*X)+(p3*I);
dGdt=-(p1*G)-(X*(G-Gb))+(9.0*exp(-0.05*t));
dDdt=[dIdt;dXdt;dGdt];
This is what I put into main:
global p1 p2 p3 n V1 Gb Ib
p1=0.028735;
p2=0.0228344;
p3=.00005035;
n=.0926;
V1=12;
Gb=81;
Ib=15;
global G X I U
TT=[];
SS=[];
i0=[0 0 0];
tspan=[0 400];
[t,i]=ode45(#Dbts,tspan,i0);
At this point the error I posted above comes up. I know I must have miscalculated something here, but I just can't pinpoint it. If anyone could please help with this, I would be extremely grateful. All I have to do is plot 3 graphs when I fix this problem.

I think it's because U isn't defined:
>> size(U)
ans =
0 0
so the size of DiDt is 0x0 and consequently the output of Dbts is 2x1.

Related

Matlab State Space Model Response system

I have a following lab where i was asked to write the command matlab lines for these questions:
If initial Conditions are: x(0)=[2;0].๐‘“๐‘–๐‘›๐‘‘ ๐‘กโ„Ž๐‘’ ๐‘Ÿ๐‘’๐‘ ๐‘๐‘œ๐‘›๐‘ ๐‘’ ๐‘ฆ(๐‘ก).
Find the response y(t) due to step input with Amplitude of
Find the Transfer Function for the above state space model
Derive back the state space model from (3).
a = [0,1;0,4];
b = [0;1];
c = [0 -5];
x0=[2;0];
sys = ss(a,b,c,2);
initial(sys,x0); % to get 1
[n,d]=ss2tf(a,b,c,0);
mySys_tf=tf(n,d) % to get 3
[num den] = tfdata(mySys_tf, 'v')
tf2ss(num,den) % to get 4
I have written this code but it seems like its not giving me any results in the response graph and thus i can't also solve 2 and it get error in 4 if you can help me out to check what is wrong
I believe that the error comes from the fact that the system is unstable. If you were to plot the system's reaction to a step input using step() then you will see how it goes to infinity. I also don't know how far you are into your controls course and if you've seen the root locus yet, but you can plot the root locus of the system via rlocus(sys) and you'll see that the real portion of the root is on the right half of the plane and therefore letting you know that the system is unstable.
The response is 0 and will stay zero as x(2) = 0. It requires an input u to get x(2) off zero. So the graph is totally fine.
use step(sys) and you will see the drop to -Inf. Optionally you can define the end-time. Call step(sys,1) to see a reasonable range.
You solved 3 & 4 yourself.
To check stability you simply need to ask MATLAB isstable(sys) (isn't it continent? Well, there is a danger that people will forget the theory behind it and how it is connected...)
To check observability: rank(obsv(sys)) and make sure that it is the same as the system matrix
assert(rank(obsv(sys)) == length(sys.A), 'System is not observable!')

Matlab error message regarding use of polyfit function in script file

I am trying to run a script file which draws a line on a plotted graph. Sometimes the script file works but occasionally it does not work and the line drawn on the graph is not where I want it. When the file does not work I get the following error message:
Warning: Polynomial is not unique. Degree >= number of data points.
> In polyfit at 70
In FIXING_force_and_rate_of_rise at 48
Does anyone know what this error message means? What does it mean when a polynomial is not unique?
If it helps, when I click on the error message I get taken to this explanation:
Solve least squares problem.
[Q,R] = qr(V,0);
ws = warning('off','all');
p = R\(Q'*y);
% Same as p = V\y;
warning(ws);
if size(R,2) > size(R,1)
warning(message('MATLAB:polyfit:PolyNotUnique'))
elseif warnIfLargeConditionNumber(R)
if nargout > 2
warning(message('MATLAB:polyfit:RepeatedPoints'));
else
warning(message('MATLAB:polyfit:RepeatedPointsOrRescale'));
end
A section of the code I am trying to run is pasted below. Line 48 is where I think the error is: [SlpBL2]=polyfit(Time_scale(300:T2), Force_trace(300:T2),1);
Reject the 1st 300 data points
BL1=min(Force_trace(300:end));
col='rcgy'
figure; set(gcf, 'windowstyle', 'docked', 'color', 'w')
for j=1:100
cla
Force_trace=Force_trace-BL1;
Peak1=max(Force_trace(300:end-30));
Extrapolation_point=Peak1*0.10;
D=Force_trace<Extrapolation_point;
T2=find(D,1,'last');
[SlpBL2]=polyfit(Time_scale(300:T2), Force_trace(300:T2),1);
Slope=SlpBL2(1);
BL2=SlpBL2(2);
plot(Time_scale, Force_trace)
hold on
plot([0, Time_scale(T2)], [BL2, Time_scale(T2)*Slope+BL2],col(1))
disp(['round number ' int2str(j) ' baseline is ' num2str(BL2)])
if abs(BL2)<1e-10
break
end
BL1=BL2;
drawnow
end
Thanks in advance for your help!
Code discussion
Since you are fitting a one-degree polynomial to data, passing less than two data points is the only reason that error would be thrown.
This will happen if T2 is always 300 or empty (meaning that D is all false.
Explanation
In order to exactly fit a polynomial of degree n, n+1 data points are required to uniquely determine the n+1 coefficients of the polynomial.
For example, a cubic has the form:
.
A cubic equation requires four points of data to uniquely determine the four coefficients.
With less than n+1 data points, an exact polynomial can not be created since, assuming there is an underlying function from which the data was drawn, there are an infinite number of solutions.
However, a polynomial whose coefficients form the smallest/shortest solution can readily be calculated; this is the least-squares solution.
This brief overview (section 2) gives a succinct overview of this and overdetermined solutions, which is more common in my experience.
Consider this input:
>> x = linspace(0,1,50);
>> y = x.^3 + x.^2;
>> p3 = polyfit(x([1,25,50]),y([1,25,50]),3);
Warning: Polynomial is not unique; degree >= number of data points.
> In polyfit at 70
>> p4 = polyfit(x([1,10,25,50]),y([1,10,25,50]),3);
and the plot here:
The undetermined solution follows the true function closely but not exactly.

How can I use of norm(a,b) in matlab if a, b are double type?

I must to use angle = atan2(norm(cross(a,b)),dot(a,b)), for calculating the angle between two vectors a,b and these are double type and norm is undefined for this type. How do I resolve this problem? I need to calculate the angle between two vectors this way.
In your comments, you have shown us how you are actually writing out the angle calculation and it is not the same as how you have put it in your post.
atan2(norm(cross(I(i,j,:),I_avg)),dot(I(i,j,:),I_avg));
I is an image you are loading in. I'm assuming it's colour because of the way you are subsetting I. Because I is a 3D matrix, doing I(i,j,:) will give you a 1 x 1 x 3 vector when in fact this has to be a 1D vector. norm does not recognize this structure which is why you're getting this error. Therefore, you need to use squeeze to remove the singleton dimensions so that this will become a 3 x 1 vector, rather than a 1 x 1 x 3 vector. As such, you need to rewrite your code so that you're doing this instead. Bear in mind that in your comments, angle is always overwritten inside the for loop, so you probably want to save the results of each pixel. With this, you probably want to create a 2D array of angles that will store these results. In other words:
I=imread('thesis.jpg');
I = double(I);
angles = zeros(m,n);
I_avg = squeeze(I_avg); %// Just in case
for i=1:m
for j=1:n
pixels = squeeze(I(i,j,:)); %// Add this statement and squeeze
angles(i,j) = atan2(norm(pixels,I_avg)),dot(pixels,I_avg)); %// Change
end
end
Minor note
MATLAB has a built-in function called angle that determines the angle from the origin to a complex number in the complex plane. It is not recommended you call your variable angle as this will unintentionally shadow over the angle function, and any other code that you create from this point onwards may rely on that actual angle function, and you will get unintended results.
Another minor note
Using i and j as loop variables is not recommended. These letters are reserved for the complex number, and this can produce unintentional results. Take a look at this question and post by Shai here - Using i and j as variables in Matlab. As such, it is suggested you use other variable names instead.
As #rayryeng has successfully answered this question, I would like to turn my post into a more general one by sharing my experience in debugging in Matlab. I hope anyone who somehow managed to find this post get more or less thinking about the habits a good programmer should have.
The question goes like: "How would I do if I get errors?"
Here's an excellent article by Eric in which he lists the rule-of-thumbs when you encounter a bug and wish to get rid of it. It's originally been cited by Stackoverflow, and that's the reason I read it.
If you still get no clue / idea how you can play with your code, see how this person does:
Pin-point the buggy line
(The number should start with 0) Make sure before running a script, you clear out any previously stored variables, including the notorious i and j's (you should never see them in any workspace). If any one is needed for the buggy code to run, save('buggy.mat','importantvar') before clear and load('buggy.mat') after clear.
By doing so, you can isolate your buggy code from anything else, which could have bad influences. For example, in a previously called script, there is a line
double = [2,4,6]; % you should never name a variable `double`
and in the next script, you have
>> e = str2num('uint8(200)')
e =
200
>> double(e)
Index exceeds matrix dimensions.
>>
>> f = single(2.36)
f =
2.3600
>> double(f)
Subscript indices must either be real positive integers or
logicals.
>>
The reason is double is no longer an inbuild function, but a user-defined variable. Too bad to pick up a name carelessly!
....anyway, let's clear the workspace and get rid of double.
>> clear
Read the error message, thoroughly.
Now let's begin with OP's problem. The original code (trimmed) goes like this -
img = imread('peppers.png');
a = img(300,200,:);
b = img(200,300,:);
d = norm(cross(a,b));
.... hence the error
Undefined function 'norm' for input arguments of type 'uint8'.
Error in untitled (line 6)
d = norm(cross(a,b));
Most beginners are only interested in the first line of the error message, which by it alone usually doesn't provide any useful help, or only in the red color, which leads to the famous question "my code does not work!"
But think twice. You still have another 2 lines unread! Error in untitled (line 6) says I'm running a script named untitled and the (first) error lies in line 6, and the code in that line is d = norm(cross(a,b));.
Now, at least you know a little more about your code - "My code d = norm(cross(a,b)); doesn't work!"
Although most likely we may also vote this kind of question to get closed, it's still much much better than a simply "It does not work!".
Now we can pin-point the buggy line
try
% this line will raise an error
d = norm(cross(a,b));
catch err
disp(err.message)
end
Look into the functions
First, make sure the inner function cross works as expected -
>> cross(a,b)
ans(:,:,1) =
0
ans(:,:,2) =
255
ans(:,:,3) =
0
>>
Good. So now we can even narrow down the error to the outer norm.
One more thing to mention. You can always find Mathworks' documentation for any in-build function, by typing "matlab function", such as "matlab norm" in Google (or any other search engine) and clicking on the first result. If you prefer, you can also type in Matlab command window doc _function_ such as doc norm and read the doc in Matlab. It's of course a pleasure of us on Stackoverflow to give you the reference by doing the same thing, but it takes a longer time because a human is, in this aspect, always slower than a search engine.
The error reads Undefined function 'norm' for input arguments of type 'uint8'.. So the input for norm should not be uint8, unsigned 8-bit integer. But what should it be?
% why `norm` "does not work"?
% this line runs perfectly well
norm(cross([1,2,3], [4,5,6]))
% so what is working?
class([1,2,3]) % so `norm` works for `double`
One thing we can do now is convert a and b to double precision. Let's try it now.
% try fixing 'uint8' error
a2 = double(a);
b2 = double(b);
whos a b % now they are double, which `norm` should work for
try
% this line will raise an error
d = norm(cross(a2,b2));
catch err
disp(err.message)
end
Now the error becomes Input must be 2-D.. What's wrong with the input?
% what is "must be 2-D" error?
size(a2) % a2 is 3-D
disp(b2) % b2 is also 3-D
This gives output in command window
ans =
1 1 3
(:,:,1) =
255
(:,:,2) =
150
(:,:,3) =
0
In OP's problem, he/she is trying to calculate something about color difference (to the best of my knowledge) which involves the angle between two color vectors in RGB space. So the vectors are needed. With imread, each pixel of the image is stored as 3 elements in the matrix, first 2 dimension being its physical position, the 3 dimension being RGB channel components. Hence pixel(200,300) with color rgb[255,150,0] is stored by us in variable b wihch is a 3-D vector.
By understanding what we need and what Matlab can do, we can combine these two points into one. We need the norm of the cross product of a and b, while the useful information (the 3 component values) is stored in the 3rd dimension. Matlab can calculate the norm of the cross product of a vector with all its information in the 1st dimension. (Here, "dimension" refers to that of the Matlab variable; a vector with 3 elements in its 1st dimension is physically a 3-D vector).
After thinking twice, we are now able to debug our code - just put all 3 elements into the 1st dimension.
% so we want the 3 elements in the 3rd dimension become in the 1st dim
a3 = squeeze(a2);
b3 = reshape(b2,numel(b2),[]);
try
d = norm(cross(a3,b3));
catch err
disp(err.message)
end
d
Bonus: If by default Matlab treats a 3-D vector as a "1-D array", then most probably the cross function has not been working correctly. Let's make a check -
>> clear
>> a = [1,2,3]
a =
1 2 3
>> b=[4,5,6]
b =
4 5 6
>> cross(a,b)
ans =
-3 6 -3
>>
The result should be the same as the one we can get by calculating by hand.
Now if we put the components into the 3rd dimension of the variable -
>> clear
>> a(1,1,:)=[1,2,3]
a(:,:,1) =
1
a(:,:,2) =
2
a(:,:,3) =
3
>> b(1,1,:)=[4,5,6]
b(:,:,1) =
4
b(:,:,2) =
5
b(:,:,3) =
6
>> cross(a,b)
ans(:,:,1) =
-3
ans(:,:,2) =
6
ans(:,:,3) =
-3
>>
.... seems OK. cross also puts the result in the 3rd dimension. In fact, Mathworks' documentation says
If A and B are vectors, then they must have a length of 3.
If A and B are matrices or multidimensional arrays, then they must
have the same size. In this case, the cross function treats A and B as
collections of three-element vectors. The function calculates the
cross product of corresponding vectors along the first array dimension
whose size equals 3.
At last, one thing is always correct to anyone who wants to do something with programming - be cautious and prudent when writing your code.

Matlab, on the quest to find a simple way to control the output of a function

I have already asked a similar question here, I will try this time to be a lot more elaborate in consideration that what puzzles me the most about Matlab still is how to handle/control output as in plotting/listing.
I have the following function
function e = calcEulerSum2(n)
for i=1:n % step size still one, although left blank
e = 1;
e = e + sum(1./factorial(1:n)); % computes a vector of length n and takes
end % the factorial of its entries, then piecewise division
end
To approximate e using the Taylor Summation method. I am now asked to compute the absolute error using
abserror(n):=abs(calcEulerSum2(n)-exp(1))
for values of n= 10^0,10^1,...,10^16.
My idea was to make the above function sensitive for vector input (if you call it like that, I have read vectorization on here as well). I thought this would be the best thing I could do, because I obviously want to evaluate the above function for a couple of values of n and then maybe plot the result in a graph to see the results.
However, I believe that my understanding of MATLAB is too rudimentary as of now to find a simple solution to that problem.
Additional: With the help of this website I already managed to solve a similar problem, using a recursive definition of e to get a vector output for each successful iteration using:
function e = calcEulerSum3(n)
for i = n % here the idea is to let n be a continuous vector
e(1)=1; % base case
e(i+1)=e(i)+1/factorial(i); % recursive definition to approx e
end
This function now understands vector input, but only if the vector is what I would call continuous on the integer line, for example n'=[ 1 2 3 4 5 ] and so on to make the recursive iteration through a vector work. This time however, my vector n as above would destroy this concept.
Question(s):
Are there simple ways to handle the above output abserror(n) ?, because I have a feeling that I am overachieving by trying to vectorize my functions
Update: As suggested by #vish the following function does a much better job for my purpose:
function e = calcEulerSum2(n) %Updated
for i=1:n % step size still one, although left blank
e = 1;
e = e + cumsum(1./factorial(1:n)); % computes a vector of length n and takes
end % the factorial of its entries, then piecewise division
end
the output of this program for n=3 would be
calcEulerSum2(3)
ans =
2.0000 2.5000 2.6667
This is great and indeed what I am looking for, but lets say I want to plot the absolute error now for several values of n, for the sake of the argument I will choose smaller values (because I understand that 10^16! is really blunt to input), but still many. So if I decide I want to print out the absolute error abserror(n) for the following values of n
n = [1 4 9 11 17 18 19 22 27 29 31 33 ]
how would I do that?
Not sure you are computing what you think you are computing.
The for loop is totally not needed since you keep overwriting e at every iteration and you only return the last one.
factorial(1:3) == [1,2,6]
then you sum the reciprocals.
The first iteration of the loop factorial(1:1) goes nowhere.
Try
cumsum(1./factorial(1:7))
l think that's what you wanted
Edit: , factorial(10^5) is too big to be meaningful, i think going from 1 to n=16 will give you good enough results. (not 10^16)
2nd edit
run this
N=0:16;
res = exp(1) - cumsum(1./factorial(N))
see what happens
you can also plot it on a log scale.
semilogy(res)

How can I solve this MATLAB "Matrix dimensions must agree" error?

I am typing some code for a class but every time I run the function I get the same error:
??? Error using ==> plus
Matrix dimensions must agree.
Error in ==> Test at 6
f32=3.*exp((-x2.^2-y1.^2)./3);
I know that the problem is a simple index error, but I can't seem to find it anywhere. Can somebody help me?
Also I'm having the same problem with the following line of code:
f34=(exp(-0.3./x2))./(log(y2).*sqrt(x2));
EDIT #1:
x2 is defined as 0:0.1:5 and y1 is defined as -5:0.1:5, but that is what I have been assigned to define them as. And I know exp is not a function because I have used it elsewhere in my file.
EDIT #2:
OK. So if I can't use my current x and y is there anyway I can define them to keep them on those bounds while still making them the same size?
UPDATE:
OK, now that you have confirmed that your variables x2 and y1 contain different numbers of elements, you have a couple of solutions to choose from:
For each variable, you can create a set number of values over the respective ranges using the function LINSPACE. For example:
x2 = linspace(0,5,101); %# 101 values spanning the range 0 to 5
y1 = linspace(-5,5,101); %# 101 values spanning the range -5 to 5
However, when you compute the result f32 (which will also be a 101-element array), it will only be evaluated at the respective pairs of values in x2 and y1 (e.g. x2(1) and y1(1), x2(50) and y1(50), etc.).
If you would rather evaluate f32 at every unique pair of points over the ranges of x2 and y1, you should instead use the function MESHGRID to generate your values. This will also allow you to have a different numbers of points over the ranges for x2 and y1:
[x2,y1] = meshgrid(0:0.1:5,-5:0.1:5);
The above will create x2 and y1 as 101-by-51 arrays such that f32 will also be a 101-by-51 array evaluated at all the points over the given ranges of values.
Previous answer:
The first thing to test is if all the variables you are putting into the equation are the same size or scalar values, which they would have to be since you are using element-wise operators like .^ and .*. For the first equation, see what output you get when you do this:
size(x2)
size(y1)
If they give the same result, or either is [1 1], then that's not your problem.
The next thing to check is whether or not you have shadowed the EXP function by creating a variable by the name exp. If you're running the code as a script in the command window, type whos and see if a variable named exp shows up. If it does, you need to delete or rename it so that you can use the function EXP.
How do you expect -x2.^2-y1.^2 to work when x2 and y1 is of different size? x2=0:0.1:5 has fifty or so entires while y1=-5:0.1:5 has a hundred or so entries.