fix axes for animation - matlab

I'm working on a small simulation in matlab. For this purposes I want to create an animation of the simulated object (inverted pendulum). Unfortunatly the axes keep rescaling.
I tried everything. There are similar questions, but I just can't get it to work. The best i got is the code below. Where I get both axes at the same time, the scaled from -5 to 5 and those scaled by matlab.
%init visualisation
visualisation = figure();
axis([-5 5 -5 5]);
xlim([-5 5]);
ylim([-5 5]);
ax_hand = axes;
for i = 1:N
k1 = h * feval ( 'RHS', t0, x0, u );
k2 = h * feval ( 'RHS', t0 + (h/2), x0 + (k1/2), u);
k3 = h * feval ( 'RHS', t0 + h/2, x0 + k2/2, u);
k4 = h * feval ( 'RHS', t0 + h, x0 + k3, u);
x0 = x0 + ( k1 + 2*k2 + 2*k3 + k4 ) / 6;
t0 = t0 + h;
% model output
wi(1:neqn,i+1) = x0';
% model visualisation
%plotting cart
figure(visualisation);
plot(x0(3), 0, 'ro', 'LineWidth', 3);
%plotting pendulum
l = 2;
%plot(sin(x0(1))*l, cos(x0(1))*l, 'b*' , 'LineWidth', 2);
% regulator
end;

Here's one approach:
Do the first plot (possibly empty, doesn't matter). Get a handle to it, say h.
Set axis limits and include the statement axis manual fo freeze them.
Update plot (in a loop) via the 'XData' and 'YData' poperties of h.
Example:
h = plot(NaN, NaN, 'o'); %// empty plot
axis([0 10 0 5])
axis manual %// this line freezes the axes
for n = 1:10
x = 1:n;
y = sqrt(x);
set(h, 'XData', x, 'YData', y)
pause(.2)
end
Example with two plots:
h1 = plot(NaN, NaN, 'bo'); %// empty plot
hold on
h2 = plot(NaN, NaN, 'r*'); %// empty plot
axis([0 10 0 5])
axis manual %// this line freezes the axes
for n = 1:10
x1 = 1:n;
y1 = sqrt(x1);
set(h1, 'XData', x1, 'YData', y1)
x2 = 4.5;
y2 = n/2-.5;
set(h2, 'XData', x2, 'YData', y2)
pause(.2)
end

Related

How to simulate a system output with a sine wave input?

I wish to simulate the output of a certain gear system I have. How the gear system looks isn't particularly important to the problem, I managed to get the differential equation needed from the mechanical system.
Here is the code I have
% parameters
N2 = 90;
N1 = 36;
Jn1 = 0.5;
Jn2 = 0.8;
J2 = 2;
D = 8;
K = 5;
J = (N2/N1)^2 * Jn1 + Jn2 + J2;
% define the system
sys = ss([0 1; -K/J -D/J], [0; N2/(N1*J)], [1 0], 0);
% initial state: (position, velocity) [rad; rad/s]
x0 = [0; 0];
% define the time span
t = linspace(0, 15, 10000)';
% define the input step
T1 = zeros(length(t), 1);
T1(t>=0) = 1;
% compute the system step response at once
theta1 = lsim(sys, T1, t, x0);
% compute the system response as aggregate of the forced and unforced
% temporal evolutions
theta2 = lsim(sys, T1, t, [0; 0]) + initial(sys, x0, t);
% plot results
figure('color', 'white');
hold on;
yyaxis left;
plot(t, T1, '-.', 'linewidth', 2);
ylabel('[N]');
yyaxis right;
plot(t, theta1, 'linewidth', 3);
plot(t, theta2, 'k--');
xlabel('t [s]');
ylabel('[rad]');
grid minor;
legend({'$T_1$', '$\theta_1$', '$\theta_2$'}, 'Interpreter', 'latex',...
'location', 'southeast');
hold off;
This should work in generating a graph that shows the positions, my outputs, for a Heaviside/step input. My question is, how would I do this for a sine wave input. I figure I should have sin(w*t) instead of (t>=0), where w is my pulse frequency. Still, I can't seem to make this work. Any help would be really appreciated! :)
Here is the solution to my problem :)
function x = integrate(t, u, x0)
% parameters
N2 = 90;
N1 = 36;
Jn1 = 0.5;
Jn2 = 0.8;
J2 = 2;
D = 8;
K = 5;
J = (N2/N1)^2 * Jn1 + Jn2 + J2;
% integrate the differential equation
[t, x] = ode23(#fun, t, x0);
% plot results
figure('color', 'white');
% plot position
yyaxis left;
plot(t, x(:, 1));
ylabel('$x$ [rad]', 'Interpreter', 'latex');
% plot velocity
yyaxis right;
plot(t, x(:, 2));
ylabel('$\dot{x}$ [rad/s]', 'Interpreter', 'latex');
grid minor;
xlabel('$t$ [s]', 'Interpreter', 'latex');
function g = fun(t, x)
g = zeros(2, 1);
g(1) = x(2);
g(2) = (-K/J)*x(1) + (-D/J)*x(2) + (N2/(N1*J)*u(t));
end
end
Now we can use an anonymous function for example:
t = linspace(0, 120, 10000)';
x0 = [0.1; 0];
x = integrate(t, #(t)(sin(1.5*t)), x0);
Test Run
These are the output results I currently get on MATLAB R2019b. As Luis' comment has suggested I have also declared a sinusoid as T1 to serve as the input. Currently not sure if this result is the expected output.
Code Snippet:
t = linspace(0, 15, 10000)';
f = 0.1;
phi = 0;
T1 = sin(2*pi*f*t + phi);
f → Frequency of sinusoidal input (0.1Hz in this example).
phi → Phase offset of sinusoidal input/initial phase (0 in this example).
t → Time vector dictating the samples of the sinusoid.
0 → Start time (0 seconds in this example).
15 → End time (15 seconds in this example).
10000 → Number of samples between the start time (0s) and end time (15s).
Implementation in Script:
% parameters
N2 = 90;
N1 = 36;
Jn1 = 0.5;
Jn2 = 0.8;
J2 = 2;
D = 8;
K = 5;
J = (N2/N1)^2 * Jn1 + Jn2 + J2;
% define the system
sys = ss([0 1; -K/J -D/J], [0; N2/(N1*J)], [1 0], 0);
% initial state: (position, velocity) [rad; rad/s]
x0 = [0; 0];
% define the time span
t = linspace(0, 15, 10000)';
% define the input step
T1 = zeros(length(t), 1);
T1(t>=0) = 1;
f = 0.1; %Sinusoid frequency = 0.1Hz%
phi = 0; %Phase = 0%
T1 = sin(2*pi*f*t + phi);
% compute the system step response at once
theta1 = lsim(sys, T1, t, x0);
% compute the system response as aggregate of the forced and unforced
% temporal evolutions
theta2 = lsim(sys, T1, t, [0; 0]) + initial(sys, x0, t);
% plot results
figure('color', 'white');
hold on;
yyaxis left;
plot(t, T1, '-.', 'linewidth', 2);
ylabel('[N]');
yyaxis right;
plot(t, theta1, 'linewidth', 3);
plot(t, theta2, 'k--');
xlabel('t [s]');
ylabel('[rad]');
grid minor;
legend({'$T_1$', '$\theta_1$', '$\theta_2$'}, 'Interpreter', 'latex',...
'location', 'southeast');
hold off;

How to Plot a unit vector in matlab

I am trying to create 2 random points that have vectors that pass them in a random direction. Example shown below
I tried creating 2 random points and 2 random unit vectors and using the function quiver to create the graph,
c = rand(1,2);
d = rand(1,2);
A = rand(2,1)-0.5;
B = rand(2,1)-0.5;
u = A/norm(A);
v = B/norm(B);
figure(3)
scatter(c,d)
quiver(c,d,u,v)
The quiver function doesnt really help and all I get is 2 points on a graph.
Any help is appreciated.
You also need to retain the scatter plot before adding the vector plots.
theta = rand( 1, 2) * 2 * pi;
x1 = c(1) + 0.5 * [-1, 1] * cos( theta( 1));
y1 = c(2) + 0.5 * [-1, 1] * sin( theta( 1));
x2 = d(1) + 0.5 * [-1, 1] * cos( theta( 2));
y2 = d(2) + 0.5 * [-1, 1] * sin( theta( 2));
figure;
hold on;
plot( x1, y1, 'r')
plot( x2, y2, 'b')
plot( c(1), c(2), 'ro', 'MarkerFaceColor', 'r');
plot( d(1), d(2), 'bo', 'MarkerFaceColor', 'b');
xlim = get( gca, 'XLim');
ylim = get( gca, 'YLim');
lo = min( [xlim(1), ylim(1)]);
hi = max( [xlim(2), ylim(2)]);
axis equal
set( gca, 'XLim', [lo, hi], 'YLim', [lo, hi]);

How to solve second order using the first order code? [duplicate]

This question already has an answer here:
Finding solution to Cauchy prob. in Matlab
(1 answer)
Closed 5 years ago.
I have solved a ODE first order equation using matlab. The equation is $$y' = t^2$$. Now I want to solve second order differential equation using the same code. y''(x) = -y, where $y(0) =1$ and $y'(x=0) = 0$.
How to change the below code so i can find the value of y? What I tried is that, i made it to a first order differential equation, but I'm confused how to change the code.
clc; % Clears the screen
clear all;
h=0.2; % step size
x = 0:h:1; % Calculates upto y(3)
y = zeros(1,length(x));
y(1) = 1; % initial condition
F_x = #(t) t.^2; % change the function as you desire
for i=1:(length(x)-1) % calculation loop
k_1 = F_x(x(i));
k_2 = F_x(x(i)+0.5*h);
k_3 = F_x((x(i)+0.5*h));
k_4 = F_x((x(i)+h));
y(i+1) = y(i) + (1/6)*(k_1+2*k_2+2*k_3+k_4)*h; % main equation
end
So, you want to split your 2nd order ODE to 2 1st order ODE. So your system of equations is
y' = u
u' = -y
where
y(0)=1
u(0)=0
Therefore, we can modify your program
function StackOverflow
close all
set(groot,'defaultLineLineWidth',3)
dx=pi/100;
x = (0:dx:2*pi)';
N = length(x);
Y = nan(size(x,1),2);
Y(1,:) = [1, 0];
F = { #(x,y) y(2) , #(x,y) -y(1) };
for i=1:N-1 % calculation loop
k_1 = cellfun(#(f) f(x(i) , Y(i,:)) , F);
k_2 = cellfun(#(f) f(x(i) + 0.5*dx, Y(i,:) + 0.5*dx*k_1) , F);
k_3 = cellfun(#(f) f(x(i) + 0.5*dx, Y(i,:) + 0.5*dx*k_2) , F);
k_4 = cellfun(#(f) f(x(i) + dx, Y(i,:) + dx*k_3) , F);
Y(i+1,:) = Y(i,:) + (dx/6)*(k_1+2*k_2+2*k_3+k_4); % main equation
end
y = Y(:,1);
u = Y(:,2);
figure(1)
set(gcf, 'units', 'normalized')
subplot(2,1,1)
plot(x , y , '--', x, cos(x), ':')
axis('tight')
set(gca,'fontsize',14, 'Position',[0.12 0.55 0.84 0.4])
xticks(0:pi/2:2*pi)
xticklabels({})
ylabel('$y(x)=\cos(x)$', 'Interpreter', 'latex')
subplot(2,1,2)
plot(x , u, '--', x, -sin(x), ':')
set(gca,'fontsize',14, 'Position',[0.12 0.1 0.84 0.4])
axis('tight')
xticks(0:pi/2:2*pi)
xticklabels({'0', '\pi/2', '\pi', '3\pi/2', '2\pi'})
xlabel('x', 'Interpreter', 'latex')
ylabel('$y''(x)=-\sin(x)$', 'Interpreter', 'latex')
end

Optim-nonlinear equation in matlab code

I updated the question to clarify it more. Here is a graph:
For the curve in the attached photo, I hope to draw the curve. I have its equation and it is after simplification will be like this one
% Eq-2
(b*Y* cos(v) + c - k*X*sin(v))^2 + ...
sqrt(k*X*(cos(v) + 1.0) + b*Y*sin(v))^2) - d = 0.0
Where:
v = atan((2.0*Y)/X) + c
and b, c, d and k are constants.
from the attached graph,
The curve is identified in two points:
p1 # (x=0)
p2 # (y=0)
I a new on coding so accept my apologize if my question is not clear.
Thanks
So, after your edit, it is a bit more clear what you want.
I insist that your equation needs work -- the original equation (before your edit) simplified to what I have below. The curve for that looks like your plot, except the X and Y intercepts are at different locations, and funky stuff happens near X = 0 because you have numerical problems with the tangent (you might want to reformulate the problem).
But, after checking your equation, the following code should be helpful:
function solve_for_F()
% graininess of alpha
N = 100;
% Find solutions for all alphae
X = zeros(1,N);
options = optimset('Display', 'off');
alpha = linspace(0, pi/2, N);
x0 = linspace(6, 0, N);
for ii = 1:numel(alpha)
X(ii) = fzero(#(x)F(x, alpha(ii)), x0(ii), options);
end
% Convert and make an X-Y plot
Y = X .* tan(alpha);
plot(X, Y,...
'linewidth', 2,...
'color', [1 0.65 0]);
end
function fval = F(X, alpha)
Y = X*tan(alpha);
% Please, SIMPLIFY in the future
A = 1247745517111813/562949953421312;
B = 4243112111277797/4503599627370496;
V = atan2(2*Y,X) + A;
eq2 = sqrt( (5/33*( Y*sin(V) + X/2*(cos(V) + 1) ))^2 + ...
(5/33*( Y*cos(V) - X/2* sin(V) ))^2 ) - B;
fval = eq2;
end
Results:
So, I was having fun with this (thanks for that)!
Different question, different answer.
The solution below first searches for the constants causing the X and Y intercepts you were looking for (p1 and p2). For those constants that best fit the problem, it makes a plot, taking into account numerical issues.
In fact, you don't need eq. 1, because that's true always for any curve -- it's just there to confuse you, and problematic to use.
So, here it is:
function C = solve_for_F()
% Points of interest
px = 6;
py = 4.2;
% Wrapper function; search for those constants
% causing the correct X,Y intercepts (at px, py)
G = #(C) abs(F( 0, px, C)) + ... % X intercept at px
abs(F(py, 0, C)); % Y intercept at py
% Initial estimate, based on your original equation
C0 = [5/33
1247745517111813/562949953421312
4243112111277797/4503599627370496
5/66];
% Minimize the error in G by optimizing those constants
C = fminsearch(G, C0);
% Plot the solutions
plot_XY(px, py, C);
end
function plot_XY(xmax,ymax, C)
% graininess of X
N = 100;
% Find solutions for all alphae
Y = zeros(1,N);
X = linspace(0, xmax, N);
y0 = linspace(ymax, 0, N);
options = optimset('Display', 'off',...,...
'TolX' , 1e-10);
% Solve the nonlinear equation for each X
for ii = 1:numel(X)
% Wrapper function for fzero()
fcn1 = #(y)F(y, X(ii), C);
% fzero() is probably the fastest and most intuitive
% solver for this problem
[Y(ii),~,flag] = fzero(fcn1, y0(ii), options);
% However, it uses an algorithm that easily diverges
% when the function slope is large. For those cases,
% solve with fminsearch()
if flag ~= 1
% In this case, the minimum of the absolute value
% is searched for (which should be zero)
fcn2 = #(y) abs(fcn1(y));
Y(ii) = fminsearch(fcn2, y0(ii), options);
end
end
% Now plot the X,Y solutions
plot(X, Y,...
'linewidth', 2,...
'color', [1 0.65 0]);
xlabel('X'), ylabel('Y')
axis([0 xmax+.1 0 ymax+.1])
end
function fval = F(Y, X, C)
% Unpack constants
b = C(1); d = C(3);
c = C(2); k = C(4);
% pre-work
V = atan2(2*Y, X) + c;
% Eq. 2
fval = sqrt( (b*Y*sin(V) + k*X*(cos(V) + 1))^2 + ...
(b*Y*cos(V) - k*X* sin(V) )^2 ) - d;
end

Showing the graph boundaries in Matlab ezsurf

I am using this simple Matlab code to plot a 3d function. What is the best way to highlight the boundaries of the plot? (say by drawing a yellow line in the boundaries)
clc;
clear all;
syms x y;
func = x^2 + 4*y^2 - 2*x^2*y+4;
ezsurf(func, [-5,5]);
grid on;
box on;
It is possible just using the hold on/off:
1.Using plot3
clc; clear all;
syms x y;
func = x^2 + 4*y^2 - 2*x^2*y+4;
figure;
ezsurf(func, [-5,5]);
grid on;
box on;
hold on;
y1 = -5:0.1:5; x1 = 5.*ones(size(y1)); z1 = x1.^2 + 4*y1.^2 - 2*x1.^2.*y1+4;
y2 = -5:0.1:5; x2 = -5.*ones(size(y2)); z2 = x2.^2 + 4*y2.^2 - 2*x2.^2.*y2+4;
x3 = -5:0.1:5; y3 = 5.*ones(size(x3)); z3 = x3.^2 + 4*y3.^2 - 2*x3.^2.*y3+4;
x4 = -5:0.1:5; y4 = -5.*ones(size(x4)); z4 = x4.^2 + 4*y4.^2 - 2*x4.^2.*y4+4;
plot3(x1, y1, z1, 'y', x2, y2, z2, 'y', x3, y3, z3, 'y', x4, y4, z4, 'y');
hold off;
You can play with the LineWidth propriety to make this lines bigger.
Result:
2.Using ezplot3 (parametric curves)
clear x y;
hold on;
x = {'5'; '(-5)'; 't'; 't'};
y = {'t'; 't'; '5'; '(-5)'};
for i = 1:size(x,1)
funz = [char(x(i)),'^2 + 4*',char(y(i)),'^2 - 2*',char(x(i)),'^2*',char(y(i)),'+4'];
h = ezplot3( char(x(i)), char(y(i)), funz, [-5, 5]);
set(h, 'Color', 'y', 'LineWidth', 2);
end
hold off;
Result: