Plotting wind speed and wind direction over time - matlab

I'm trying to make a plot that can display both wind speed and wind direction over time. A colleague suggested adding a line pointing in the wind direction to each point on a time-series plot of wind speed.
I thought it would be fairly simple to calculate the line. I used trig formulas from here. However the plot is not displaying as I'd expect. All of the lines look as if they have zero slope rather than vary from -1 to 1.
Here is my code:
wdates = [ 7.357325746759259E5; 7.357325747916667E5; 7.357325749074074E5; 7.357325750231481E5; 7.357325751388889E5; 7.357325752546296E5; 7.357325753703704E5; 7.357325754861111E5; 7.357325756018518E5; 7.357325757175926E5; 7.357325758333333E5; 7.357325759490741E5; 7.357325760648148E5];
topspeed = rand(size(wdates)) * 2;
toprdir = [0 pi/6 pi/4 pi/3 pi/2 2*pi/3 3*pi/4 pi 5*pi/4 4*pi/3 3*pi/2 5*pi/3 7*pi/4];
toprdir = toprdir';
h = figure(1);
plot(wdates,topspeed,'s');
datetick('x')
hold all;
%find slope
topslopes = tan(toprdir);
for i=1:length(wdates)
%find start point.
clear x;
clear y;
x(1) = wdates(i);
y(1) = topspeed(i);
d = .0001;
%x(2) = d * cos(atan(topslopes(i))) + x(1); %did not work?
%y(2) = d * sin(atan(topslopes(i))) + y(1); %did not work?
x(2) = d * cos(toprdir(i)) + x(1);
y(2) = d * sin(toprdir(i)) + y(1);
plot(x,y);
end
And here is the result.

You are seeing that all the lines look like they have a slope of zero because your axes have very different ranges.
Instead, create a scaling factor based on your axes ranges. Note that, I just approximated values for dy, dx, but you should calculate what they should be based on your data and physical dimensions of each of your axis (e.g. make sure a 45 deg line looks like 45 degrees). You can use "axis square" to make dimensions the same.
dy = 1;
dx = 0.001;
x(2) = dx * cos(toprdir(i)) + x(1);
y(2) = dy * sin(toprdir(i)) + y(1);
With these lines modified, the resulting graph looks as follows:

Related

Alternative to rlocfind to find intersection of line of constant damping ratio with root locus in Matlab

To find the gain at the point where the root locus intersects a line of constant damping ratio, the rlocfind function can be used, but the user has to manually select a point and Matlab finds the closest point on the root locus to the selection. Is there a way to find the exact point of intersection without having to make the selection manually?
h = tf([2 5 1],[1 2 3]);
rlocus(h)
z = 0.707; sgrid(z,0)
k = rlocfind(h)
Can the value of gain be found without using rlocfind if the correct gain value is greater than 1? For example, for the following transfer function the gain value should be 23.4.
h = tf(1,poly([-2 -4 -6]))
minfun = #(k) (0.75 - tf2dampingratio(h, k))^2;
gain = fminbnd(minfun, 0, 1) % 0.1970
rlocus(h) % Root locus
ylim([-3 3])
z = 0.75; sgrid(z,0)
K = rlocfind(h)
function dampingratio = tf2dampingratio(h, k)
[num, den] = tfdata(h);
poles = roots(den{:} + k * num{:});
dampingratio = cos(pi - angle(poles(1)))
end
I don't know of a MATLAB function that can do that directly. We can, however, write a small function to do the calculation for us. We know that the root locus is the plot of how the poles of a system move when used in negative feedback with some gain (see the MATLAB docs). And the damping ratio is the cosine of the angle the pole makes with the negative real axis (illustration from Wikipedia).
h = tf([2 5 1],[1 2 3]);
minfun = #(k) (0.707 - tf2dampingratio(h, k))^2;
gain = fminbnd(minfun, 0, 1); % 0.1970
function dampingratio = tf2dampingratio(h, k)
[num, den] = tfdata(h);
poles = roots(den{:} + k * num{:});
dampingratio = cos(pi - angle(poles(1)));
end

Spiral of non-overlapping circles

I want to create a spiral of circle markers which never overlap with each other. This is what I got so far, but it overlaps the first markers, and the last ones are too far apart from each other.
t = pi : pi/20 : 20*pi;
t = asind(1./t);
r = t;
x = r .* cos(t);
y = r .* sin(t);
plot(x,y,'o-');
axis equal; hold on
Plotting without redefining t as asinf(1/t) as follows, is shown in the second plot.
t = pi : pi/20 : 20*pi;
r = t;
x = r .* cos(t);
y = r .* sin(t);
plot(x,y,'o-');
Any ideas on how does the spacing of the angles t must be to accomplish that the markers don't overlap?
You can approximate the arc length, greatly simplifying Gilles-Phillipe's solution. This is a simplification, which means that the distance between the markers is not identical everywhere. However the distances are fairly consistent, especially further out.
The approximation here is to assume that the spiral is, locally, a circle. The arc length then is r*dt at a position in the spiral a distance r from the origin, for a change in angle of dt radian.
We now no longer need to solve symbolic equations. I wrote the code in a loop. I'm sure it's possible to vectorize it, making the whole thing two lines of code, but I'll leave that as an exercise to the reader.
This is the code:
d = 1; % step size
q = 1/(2*pi); % spiral constant -- radius grows by q every 1 radian turn
N = 300; % number of points
t = 0; % initial angle
r = d; % initial radius
p = zeros(100,2);
p(1,:) = [r*cos(t),r*sin(t)]; % first point
for ii=2:N
dt = d/r;
t = t+dt;
r = r+dt*q;
p(ii,:) = [r*cos(t),r*sin(t)];
end
clf
plot(p(:,1),p(:,2),'o-')
axis equal
Try this:
syms s;
scale = 10;
l = scale/2 : scale/2 : 40*scale;
t = double(arrayfun(#(y) vpasolve((0.5*(s*sqrt(1+s^2)+asinh(s)))==y,s), l));
x = t .* cos(t);
y = t .* sin(t);
plot(x,y,'o-');
pbaspect([1 1 1]);
axis(scale*[-5 5 -5 5])
The idea is to parameterize using the arclength of the curve. The arclength of this spiral is l=1/2*(t*sqrt(1+t*t)+asinh(t)) (can be found using Matlab symbolic integration). To place points uniformly, we do a uniform sampling of the arclength, and find the corresponding t by solving the equation. Since it cannot be solved easily symbolically, we use a numerical solver.
Note that the scale and the aspect ratio of the plot is really important for it to look uniform and non-overlapping. This is why I added axis/ratio definition. Since each point is solved numerically, it can take quite some time to evaluate. There may be a faster way to do it, but at least you have a result.
I obtain the following result:

How do I visualize the intersection of spheres in MATLAB?

It seems this question has been asked in a few places (including on SO). I recently came across the need for this when visualizing results of a trilateration problem.
In almost every case, the answer directs the inquiry to look at Wolfram for the math but excludes any code. The math really is a great reference, but if I'm asking a question on programming, some code might help as well. (It certainly is also appreciated when answers to a code question avoid pithy comments like "writing the code is trivial").
So how can one visualize the intersection of spheres in MATLAB? I have a simple solution below.
I wrote a small script to do just this. Feel free to make suggestions and edits. It works by checking if the surface of each sphere falls within the volume of all of the other spheres.
For sphere intersection, it's better (but slower) to use a larger number of faces in the sphere() function call. This should give denser results in the visualization. For the sphere-alone visualization, a smaller number (~50) should suffice. See the comments for how to visualize each.
close all
clear
clc
% centers : 3 x N matrix of [X;Y;Z] coordinates
% dist : 1 x N vector of sphere radii
%% Plot spheres (fewer faces)
figure, hold on % One figure to rule them all
[x,y,z] = sphere(50); % 50x50-face sphere
for i = 1 : size(centers,2)
h = surfl(dist(i) * x + centers(1,i), dist(i) * y + centers(2,i), dist(i) * z + centers(3,i));
set(h, 'FaceAlpha', 0.15)
shading interp
end
%% Plot intersection (more faces)
% Create a 1000x1000-face sphere (bigger number = better visualization)
[x,y,z] = sphere(1000);
% Allocate space
xt = zeros([size(x), size(centers,2)]);
yt = zeros([size(y), size(centers,2)]);
zt = zeros([size(z), size(centers,2)]);
xm = zeros([size(x), size(centers,2), size(centers,2)]);
ym = zeros([size(y), size(centers,2), size(centers,2)]);
zm = zeros([size(z), size(centers,2), size(centers,2)]);
% Calculate each sphere
for i = 1 : size(centers, 2)
xt(:,:,i) = dist(i) * x + centers(1,i);
yt(:,:,i) = dist(i) * y + centers(2,i);
zt(:,:,i) = dist(i) * z + centers(3,i);
end
% Determine whether the points of each sphere fall within another sphere
% Returns booleans
for i = 1 : size(centers, 2)
[xm(:,:,:,i), ym(:,:,:,i), zm(:,:,:,i)] = insphere(xt, yt, zt, centers(1,i), centers(2,i), centers(3,i), dist(i)+0.001);
end
% Exclude values of x,y,z that don't fall in every sphere
xmsum = sum(xm,4);
ymsum = sum(ym,4);
zmsum = sum(zm,4);
xt(xmsum < size(centers,2)) = 0;
yt(ymsum < size(centers,2)) = 0;
zt(zmsum < size(centers,2)) = 0;
% Plot intersection
for i = 1 : size(centers,2)
xp = xt(:,:,i);
yp = yt(:,:,i);
zp = zt(:,:,i);
zp(~(xp & yp & zp)) = NaN;
surf(xt(:,:,i), yt(:,:,i), zp, 'EdgeColor', 'none');
end
and here is the insphere function
function [x_new,y_new,z_new] = insphere(x,y,z, x0, y0, z0, r)
x_new = (x - x0).^2 + (y - y0).^2 + (z - z0).^2 <= r^2;
y_new = (x - x0).^2 + (y - y0).^2 + (z - z0).^2 <= r^2;
z_new = (x - x0).^2 + (y - y0).^2 + (z - z0).^2 <= r^2;
end
Sample visualizations
For the 6 spheres used in these examples, it took an average of 1.934 seconds to run the combined visualization on my laptop.
Intersection of 6 spheres:
Actual 6 spheres:
Below, I've combined the two so you can see the intersection in the view of the spheres.
For these examples:
centers =
-0.0065 -0.3383 -0.1738 -0.2513 -0.2268 -0.3115
1.6521 -5.7721 -1.7783 -3.5578 -2.9894 -5.1412
1.2947 -0.2749 0.6781 0.2438 0.4235 -0.1483
dist =
5.8871 2.5280 2.7109 1.6833 1.9164 2.1231
I hope this helps anyone else who may desire to visualize this effect.

MATLAB projectile motion with air resistance

I am trying to calculate maximum distance and maximum height of a projectile for an angle theta below.
I assume my way of plotting the graphs of distance against theta and height against theta (on the same graph) are wrong. Any pointers on that will be helpful.
e=100;
m = 1;
g = 9.8;
cd = 0.55;
r = 0.02;
p = 1.21;
a = pi*r^2;
v = sqrt((2*e)/m);
k = (1/2)*cd*a*p;
% For loop to calculate Distance and
for theta = (0:pi/4);
vx = v*cos(theta);
vy = v*sin(theta);
t = sqrt(m/(g*k))*atan(vy*sqrt(k/(m*g)));
x = (m/k)* log((1/vx)+(k/m)*t) - log(1/(vx));
h = (m/k)*(log(cos(atan(vy*sqrt(k/(m*g))-sqrt((g*k)/m)*t))-log(cos((atan(vy*sqrt(k/m*g)))))));
plot (x, theta);
plot (h, theta);
end
You don't need to loop through different values of theta. Try this instead:
theta = (0:0.01:pi/4); % theta = [0 0.01 0.02 0.03 ... pi/4]
vx = v*cos(theta);
vy = v*sin(theta);
t = sqrt(m/(g*k)) * atan(vy .* sqrt(k/(m*g))); % element wise matrix multiplication
x = (m/k)* log((1./vx)+(k/m)*t) - log(1./(vx));
h = (m/k)*(log(cos(atan(vy .* sqrt(k/(m*g))- sqrt((g*k)/m)*t))-log(cos((atan(vy .* sqrt(k/m*g)))))));
plot (x, theta);
plot (h, theta);
x vs theta:
Also try this:
MATLAB: Creating a Function to Plot Projectile with Drag
MATLAB: Numerical approximation of projectile motion with air resistance
Hope this helps!
The variable t is not defined. Also the loop variable should be integer, for example:
N = 10;
for i = 0:N-1
theta = pi/4*i/(N-1)
(...)
end

Matlab Programming : plotting susceptance vs firing angle alpha

I'm not that strong in programming. I was trying to plot two equations from Power Electronics in Matlab. My code is as follows. I am getting a blank plot when I plot Btcr and alpha! Kindly let me know whats wrong.
Plotting Susceptance vs Firing Angle
%Variables
V = 1;
L = 0.005;
freq = 60;
omega = 2 * pi * freq;
theta = 0:0.01:360*2;
for alpha = 90:10:180
sigma = 2*(180 - alpha)
Btcr = (sigma + sind(2*alpha))/(omega*L*3.14);
end
plot(Btcr, alpha);
Your for-loop is unnecessary. You are actually overwriting the previous values of sigma and Btcr each time you go through the loop, so at the end you don't have vectors of data, just two numbers. You can fix this by removing the loop altogether:
alpha = 90:10:180
sigma = 2*(180 - alpha)
Btcr = (sigma + sind(2*alpha))/(omega*L*3.14);
plot(Btcr, alpha);