problem im motion control with MATLAB - matlab

i have a problem in motion control in matlab
imagine a four bar linkage mechanism like this.as you you know in an ordinary 4 bar linkage we have 2 fix points but here we have just one & the second one it fixed to a pinion (small gear).we have the ratio of gears so we have a relation between teta1 & teta2
teta2 = 5*teta1 (the mechanism can rotate in the first fix point)
i used to write this code for motion control but the when i run it the graphs are not correct (because they should be something linke sin or cos graph)
d(n) is a auxiliry vector for solving equations
please ask if you have further questions
this is the code :
clc,
close all,
clear all,
ax=0;
ay=0;
r1=12;
r2=7;
r3=9;
r4=5;
n=0;
for teta1=0:pi/180:2*pi
n=n+1;
D = r1*exp(i*teta1)-r2*exp(i*5*teta1);
tetad(n) = angle(D);
d(n) = abs(D);
landa(n)=acos((d(n)^2+(r3)^2-(r4)^2)/(2*d(n)*r3));
alfa(n)=acos((d(n)^2+(r4)^2-(r3)^2)/(2*d(n)*r4));
teta3(n)=landa(n)+tetad(n);
teta4(n)=(+pi-alfa(n)+tetad(n));
end
aa(n)=teta1*180/pi;
hh(n)=tetad(n)*180/pi;
bb(n)=landa(n)*180/pi;
cc(n)=alfa(n)*180/pi;
nn(n)=teta3(n)*180/pi;
dd(n)=5*teta1*180/pi;
ee(n)=teta4(n)*180/pi;
figure(1),plot(aa,hh),xlabel('teta1'),ylabel('tetad');
figure(2),plot(aa,d),xlabel('teta1'),ylabel('d');
figure(3),plot(aa,bb),xlabel('teta1'),ylabel('landa');
figure(4),plot(aa,cc),xlabel('teta1'),ylabel('alfa');
figure(5),plot(aa,nn),xlabel('teta1'),ylabel('teta3');
figure(6),plot(aa,dd),xlabel('teta1'),ylabel('5*teta1');
figure(7),plot(aa,ee),xlabel('teta1'),ylabel('teta4');

I have no idea what you are trying to solve here, but probably you want to move the end of your for-loop a few lines down, so the vectors you plot contain all values and not only the last one.

Related

How do I get lines to stop extending beyond plot border? (Matlab)

I am writing a report for a class and am having some issues with the lines of an unstable plot going beyond the boundary of the graph and overlapping the title and xlabel. This is despite specifying a ylim from -2 to 2. Is there a good way to solve this issue?
Thanks!
plot(X,u(:,v0),X,u(:,v1),X,u(:,v2),X,u(:,v3),X,u(:,v4))
titlestr = sprintf('Velocity vs. Distance of %s function using %s: C=%g, imax=%g, dx=%gm, dt=%gsec',ICFType,SDType,C,imax,dx,dt);
ttl=title(titlestr);
ylabl=ylabel("u (m/s)");
xlabl=xlabel("x (m)");
ylim([-2 2])
lgnd=legend('t=0','t=1','t=2','t=3','t=4');
ttl.FontSize=18;
ylabl.FontSize=18;
xlabl.FontSize=18;
lgnd.FontSize=18;
EDIT: Minimum reproducible example
mgc=randi([-900*10^10,900*10^10], [1000,2]);
mgc=mgc*1000000;
plot(mgc(:,1),mgc(:,2))
ylim([-1,1])
This is odd. It really looks like a Bug... partly
The reason is probably that the angle of the lines are so narrow that MATLAB runs into rounding errors when calculating the points to draw for your limits very small limits given very large numbers. (You see that you don't run into this problem when you don't scale the matrix mgc.
mgc = randi([-900*10^10,900*10^10], [1000,2]);
plot(mgc(:,1),mgc(:,2))
ylim([-1,1])
but if you scale it further, you run into this problem...
mgc = randi([-900*10^10,900*10^10], [1000,2]);
plot(mgc(:,1)*1e6,mgc(:,2)*1e6)
ylim([-1,1])
While those numbers are nowhere near the maximum number a double can represent (type realmax in the command window to see that this is a number with 308 zeros!); limiting the plot to [-1,1] on one of the axes -- note that you obtain the same phenom on the x-axis -- let MATLAB run into precision problems.
First of all, you see that it plots much less lines than before (in my case)... although, I just said to zoom on the y-axis. The thing is, that MATLAB does not recalculate the lines for the section but it really zooms into it (I guess that this may cause resolution errors with regard to pixels?)
Well, lets have a look at the data (Pro-tip, you can get the data of a line from a MATLAB figure by calling this snippet
datObj = findobj(gcf,'-property','YData','-property','XData');
X = datObj.XData;
Y = datObj.YData;
xlm = get(gca,'XLim'); % get the current x-limits
) We see that it represents the original data set, which is not surprising as you can also zoom out again.
Note that his only occurs if you have such a chaotic, jagged line. If you sort it, it does not happen.
quick fix:
Now, what happens, if we calculate the exact points for this section?
m = diff(Y)./diff(X); % slope
n = Y(1:end-1)-m.*X(1:end-1); % offset
x = [(-1-n); (1-n)]./m;
y = ones(size(x))./[-1 1].';
% plot
plot([xMinus1;xPlus1],(ones(length(xMinus1),2).*[-1 1]).')
xlim(xlm); % limit to exact same scale as before
The different colors indicate that they are now individual lines and not a single wild chaos;)
It seems Max pretty much hit the nail on the head as it pertains to the reason for this error is occurring. Per Enrico's advice I went ahead and submitted a bug report. MathWorks responded saying they were unsure it was "unexpected behavior" and would look into it more shortly. They also did suggest a temporary workaround (which, in my case, may be permanent).
This workaround is to put
set(gca,'ClippingStyle','rectangle');
directly after the plotting line.
Below is a modified version of the minimum reproducible example with this modification.
mgc=randi([-900*10^10,900*10^10], [1000,2]);
mgc=mgc*1000000;
plot(mgc(:,1),mgc(:,2))
set(gca,'ClippingStyle','rectangle');
ylim([-1,1])

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!')

GUI solving equations project

I have a Matlab project in which I need to make a GUI that receives two mathematical functions from the user. I then need to find their intersection point, and then plot the two functions.
So, I have several questions:
Do you know of any algorithm I can use to find the intersection point? Of course I prefer one to which I can already find a Matlab code for in the internet. Also, I prefer it wouldn't be the Newton-Raphson method.
I should point out I'm not allowed to use built in Matlab functions.
I'm having trouble plotting the functions. What I basically did is this:
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
cla % To clear axes when plotting new functions
ezplot(fun_f);
hold on
ezplot(fun_g);
axis ([-20 20 -10 10]);
The problem is that sometimes, the axes limits do not allow me to see the other function. This will happen, if, for example, I will have one function as log10(x) and the other as y=1, the y=1 will not be shown.
I have already tried using all the axis commands but to no avail. If I set the limits myself, the functions only exist in certain limits. I have no idea why.
3 . How do I display numbers in a static text? Or better yet, string with numbers?
I want to display something like x0 = [root1]; x1 = [root2]. The only solution I found was turning the roots I found into strings but I prefer not to.
As for the equation solver, this is the code I have so far. I know it is very amateurish but it seemed like the most "intuitive" way. Also keep in mind it is very very not finished (for example, it will show me only two solutions, I'm not so sure how to display multiple roots in one static text as they are strings, hence question #3).
function [Sol] = SolveEquation(handles)
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
f = inline(fun_f);
g = inline(fun_g);
i = 1;
Sol = 0;
for x = -10:0.1:10;
if (g(x) - f(x)) >= 0 && (g(x) - f(x)) < 0.01
Sol(i) = x;
i = i + 1;
end
end
solution1 = num2str(Sol(1));
solution2 = num2str(Sol(2));
set(handles.roots1,'string',solution1);
set(handles.roots2,'string',solution2);
The if condition is because the subtraction will never give me an absolute zero, and this seems to somewhat solve it, though it's really not perfect, sometimes it will give me more than two very similar solutions (e.g 1.9 and 2).
The range of x is arbitrary, chosen by me.
I know this is a long question, so I really appreciate your patience.
Thank you very much in advance!
Question 1
I think this is a more robust method for finding the roots given data at discrete points. Looking for when the difference between the functions changes sign, which corresponds to them crossing over.
S=sign(g(x)-f(x));
h=find(diff(S)~=0)
Sol=x(h);
If you can evaluate the function wherever you want there are more methods you can use, but it depends on the size of the domain and the accuracy you want as to what is best. For example, if you don't need a great deal of accurac, your f and g functions are simple to calculate, and you can't or don't want to use derivatives, you can get a more accurate root using the same idea as the first code snippet, but do it iteratively:
G=inline('sin(x)');
F=inline('1');
g=vectorize(G);
f=vectorize(F);
tol=1e-9;
tic()
x = -2*pi:.001:pi;
S=sign(g(x)-f(x));
h=find(diff(S)~=0); % Find where two lines cross over
Sol=zeros(size(h));
Err=zeros(size(h));
if ~isempty(h) % There are some cross-over points
for i=1:length(h) % For each point, improve the approximation
xN=x(h(i):h(i)+1);
err=1;
while(abs(err)>tol) % Iteratively improve aproximation
S=sign(g(xN)-f(xN));
hF=find(diff(S)~=0);
xN=xN(hF:hF+1);
[~,I]=min(abs(f(xN)-g(xN)));
xG=xN(I);
err=f(xG)-g(xG);
xN=linspace(xN(1),xN(2),15);
end
Sol(i)=xG;
Err(i)=f(xG)-g(xG);
end
else % No crossover points - lines could meet at tangents
[h,I]=findpeaks(-abs(g(x)-f(x)));
Sol=x(I(abs(f(x(I))-g(x(I)))<1e-5));
Err=f(Sol)-g(Sol)
end
% We also have to check each endpoint
if abs(f(x(end))-g(x(end)))<tol && abs(Sol(end)-x(end))>1e-12
Sol=[Sol x(end)];
Err=[Err g(x(end))-f(x(end))];
end
if abs(f(x(1))-g(x(1)))<tol && abs(Sol(1)-x(1))>1e-12
Sol=[x(1) Sol];
Err=[g(x(1))-f(x(1)) Err];
end
toc()
Sol
Err
This will "zoom" in to the region around each suspected root, and iteratively improve the accuracy. You can tweak the parameters to see whether they give better behaviour (the tolerance tol, the 15, number of new points to generate, could be higher probably).
Question 2
You would probably be best off avoiding ezplot, and using plot, which gives you greater control. You can vectorise inline functions so that you can evaluate them like anonymous functions, as I did in the previous code snippet, using
f=inline('x^2')
F=vectorize(f)
F(1:5)
and this should make plotting much easier:
plot(x,f(x),'b',Sol,f(Sol),'ro',x,g(x),'k',Sol,G(Sol),'ro')
Question 3
I'm not sure why you don't want to display your roots as strings, what's wrong with this:
text(xPos,yPos,['x0=' num2str(Sol(1))]);

Ordinary Differential Equations in Matlab

Question -
I am working on some matlab code that solves 2 first degree differentials and 2 second order differentials. I am ok with dsolve() but when I want to plot I am currently using ezplot and it is not giving me what I want. I want to produce 1 window with four graphs. I know I would use subplot but I dont know how, an example would be nice. Also I dont know how to make my plots show the importiant area not just a large area. my code is below:
close all % close all figure windows that are open
clear all % clear all the variables currently stored in memory
clc % clear the commands in the command window
%%Problem 1%%%%%
a = (dsolve('Dv = -500*v+5000','v(0)=5'));
display (a)
b = (dsolve('Dx = -2000*x+100','x(0)=-.02'));
display (b)
%%Problem 2%%%%%
c = (dsolve('D2y+2000*Dy+26000000*y-520000000=0','Dy(0)=0','y(0)=5'));
display(c)
d = (dsolve('D2y+100*Dy+2500*y-520000000=0','Dy(0)=20','y(0)=0'));
display (d)
figure
ezplot(a);
axis([0,.01,4,10])
figure
ezplot(b);
axis([0,.01,0,10])
figure
ezplot(c);
axis([0,.01,4,10])
figure
ezplot(d);
axis([0,.01,4,10])
I didn't know until now, but it seems that ezplot only generates data points for "interesting part" of your plot. So if you specify the x-limit that ezplot does not use, you don't see anything. What you need to do is to specify the x-limits in its second argument of ezplot. Then, you can create subplots with standard suplot function, get axis handle, and specify the axis. The plotting part of your code should be like this.
figure
h1=subplot(2,2,1);
ezplot(a, [0,0.01]);
axis(h1,[0,0.01,4,10])
h2=subplot(2,2,2);
ezplot(b, [0,0.01]);
axis(h2,[0,.01,0,10])
h3=subplot(2,2,3);
ezplot(c, [0,0.01]);
axis(h3,[0,.01,4,10])
h4=subplot(2,2,4);
ezplot(d, [0,0.01]);
axis(h4,[0,.01,4,10])

Organize Points and Draw the Line

In Matlab, I've got several points in the 3D space. Those points represent a rope and I would like to draw a line linking all those points. Here is my problem: How the oraganization of those points should be done to have a "simple" and "more or less straigth line". In other words I would like to draw a line linking all the points from the first to the last one but not "going back". Maybe with a simple image i can explain better my problem:
This is what the code should do:
This is what the code shouldn't do:
Some idea of how can I achieve the intended result? How can I organize the points? I'm working with Matlab but if you know any paper where I can read how to do this it will be fine. Thank you.
If you just don't want to go back in the upper direction, the solution that #Dan suggested should be fine. Sort them in that direction before connecting.
However, if that is not a requirement but you are actually looking for a solution without ugly crossings that is as short as possible, you may want to look into solutions for the travelling salesman problem.
If you define the distance between 1 and 9 to be zero, the solution you find to the travelling salesman problem should give you a nice and short rope.
If you want to go for the TSP approach but get a little lost, just try a 'furthest insertion' start position or '2 opt' improvements as that is likely going to give a big improvement over random path selection already with minimal effort.
OK. I've found the right answer (by Gunther Struyf): Sort Coordinates Points in Matlab
In order to visualize the final result just add to Gunther's code the following lines:
row=data(:,1);
col=data(:,2);
figure
scatter(row,col,'r');
hold on
line(row(result),col(result));
The following code shows the same algorithm but for a 3D implementation:
close all;
data = [2,2, 2; 2,3,2 ; 1,2,3 ; 1,3,3 ; 2,1,3 ; 1,1,3 ; 3,2,4 ; 3,3,4 ; 3,1,5; 5,4,6; 7,3,8; 8,9,7; 9,4,7; 6,2,5; 5,8,6; 9,3,8;6,9,2];
row=data(:,1);
col=data(:,2);
frame=data(:,3);
dist = pdist2(data,data);
N = size(data,1);
result = NaN(1,N);
result(1) = 1; % first point is first row in data matrix
for ii=2:N
dist(:,result(ii-1)) = Inf;
[~, closest_idx] = min(dist(result(ii-1),:));
result(ii) = closest_idx;
end
figure
%Ploting the points directly (without sorting)
subplot(2,1,1);
scatter3(row,col,frame,'r');
hold on;
line(row,col,frame);
%Ploting after sorting
subplot(2,1,2);
scatter3(row,col,frame,'r');
hold on
line(row(result),col(result),frame(result));