3d plot of Tridimensional parabolic motion - matlab

I am trying to get a 3D plot of a parabolic motion. I am trying to simulate debris from an airplane falling from a certain altitude. Obviously, the parabolic motion and the absence of other forces is a simplification.
These are the initial conditions.
h_0=14325 % m
x0=0 % m
y0=0 m
V_0= 200*.3048 %m/s
gamma = 0.78 %rad
Obviously, I want my object to reach the ground. I created the following code, but the plot is a little strange. I don't understand where or what is wrong
g=9.8;
z0= 14325;
x0=0;
y0=0;
V_0= 200*0.3048;
gamma=0.78;
V_0x=V_0*cos(gamma);
V_0y=0;
V_0z=V_0*sin(gamma);
t = linspace(0,2*V_0*sin(gamma)/g);
x=x0+V_0x*t;
y=y0+V_0y*t;
z=z0+V_0z-.5*g*t.^2;
indices=z>=0;
x = x(indices);
y = y(indices);
z = z(indices);
plot3(x,y,z)
hold on
plot3(x0,y0,z0,'ro','MarkerSize',5)
xlabel('Posizione x (m)')
ylabel('Posizione y (m)')
zlabel('Posizione z (m)')
grid on

Related

Rotating a 3D figure in MATLAB

I generated a 3D surface in matlab.
clear all;
close all;
clc;
x = [1:0.1:5];
y=[1:50];
[n1 n2] = size(x);
[m1, m2] = size(y);
for i = 1 : m2
for j = 1 : n2
z(i,j) = (x(1,j)) / (y(1,i));
end
end
[x, y] = meshgrid(x, y);
surf(y, x, z)
colorbar
xlabel('x')
ylabel('y')
zlabel('z')
I got the following plotted surface:
I am interested now to rotate the cube of a quarter turn in the clockwise direction. I know that I can use the "rotate3d on" and choose the best Az and EI, but I didn't understand what are Az and EI and how should be equal to respond to my need?
For example:
There also another function called camroll(). But I don't know what must the value in () in order to rotate the cube of a quarter turn in the clockwise direction. Does 90 degree is the correct answer?
Any help will be very appreciated!
To rotate the figure axis you can use the view command:
surf(rand(20))
for az = 360:-1:-0
view(az, 30)
pause(0.01)
end
Azimus has values in between 0° and 360°. To turn the axis figure by 90° in counter-clockwise direction you oculd choose the azimuths of: [270, 180, 90, 0]
as #ASantosRibeiro mentioned, the rotate function will produce the output you want. As an aside, here is a vectorized version of your code, which you might find useful if you have a significantly larger data set.
x = 1:0.1:5;
y=1:50;
X = repmat(x',1,size(y,2)).';
Y = repmat(y',1,size(x,2));
Z = X./Y;
figure
hSurf = surf(Y,X,Z);
rotate(hSurf,[1,0,0],45) % As proposed by #ASantosRibeiro
colorbar
xlabel('x')
ylabel('y')
zlabel('z')
The repmat function is used to replicate both x and y in order to form X and Y with correct sizes to be allowed to divide one by the other in order to form Z. This operation is quite similar to the call to meshgrid in your code. For a small dataset like the one in your example the running times are similar with both methods (on my laptop), however when I use x = 1:0.1:500 and y = 1:500 for example the vectorized version takes 3x less time, so it might be worthwhile to look at it.
Hope that helps you!

How can I plot a 3d vector fast in matlab?

I'm working on a project which includes use of accelerometer and gyroscope to get the orientation an object. I can pass the 3d orientation vector from arduino to matlab via serial communication.
I want to plot the vector in matlab to make real time analysis. I'm using quiver3d and drawnow functions in a loop to plot the vector but quiver3d function is very slow so I can see the orientation of object after like 20 seconds later.
Is there any way to plot 3d vectors faster?
Thanks.
quiver plot may be too much for plotting only one vector in 3-D. You can achieve a similar plot by using a simple plot3 such as the one plotted below.
In this plot, the origin of the vector is the blue dot, and the direction is given by the red line.
The code
%v is the direction of the vector (3 cartesian coordinates)
v = sort(randn(100,3));
v = bsxfun(#rdivide,v,sqrt(sum(v.^2,2)));
%xyz the origin of the vector
ind = linspace(-pi,pi,100);
x = cos(ind);
y = sin(ind);
z = ind;
%the plotting function
figure
for ii = 1:numel(ind)
plot3(x(ii),y(ii),z(ii),'bo'); %origin in blue
set(gca,'XLim', [-3 3], 'YLim', [-3 3], 'ZLim', [-3 3]);
hold on;
hl = plot3( linspace(x(ii), x(ii)+v(ii,1),10), ...
linspace(y(ii), y(ii)+v(ii,2),10), ...
linspace(z(ii), z(ii)+v(ii,3),10), ...
'r'); %direction in red
view(80,10);
pause(0.1);
%clf
end

plotting trajectory data in matlab

I have trajectory information in 3 dimensions in matlab. These are of a gesture someone is making. When I connect the points in matlab by using plot3, I can see the trajectory nicely.
However, the trajectory is a line in the plot, but I don't know in which direction the gesture has been made as the time is not visualized. Is it possible to visualize this in a 3d plot (where the dimensions are x, y and z)? For example, the colour at the start is bright red and the colour at the end is black.
Thanks for your help,
Héctor
You need the comet3 plot (if you don't mind animations).
If you do mind animations, and you're looking for a static figure, I'd use a quiver.
Example:
% value of the parameter in the parametric equation
t = 0:0.5:2*pi;
% modified coordinate axes
u = [1 0 0].';
v = [0 2 0].';
% coordinates of the ellipse
Ell = bsxfun(#plus, bsxfun(#times, u, cos(t)), bsxfun(#times, v, sin(t)));
% difference vectors between all data points will be used as "velocities"
dEll = diff(Ell, 1,2);
% Quiver the ellipse
quiver3(...
Ell(1,1:end-1), Ell(2,1:end-1), Ell(3,1:end-1), ...
dEll(1,:), dEll(2,:), dEll(3,:), ...
2, 'r') % = scale, LineSpec
axis tight equal
Result:

Rotating Axes Around Line of Fit MATLAB

I'm currently frustrated by the following problem:
I've got trajectory data (i.e.: Longitude and Latitude data) which I interpolate to find a linear fitting (using polyfit and polyval in matlab).
What I'd like to do is to rotate the axes in a way that the x-axis (the Longitude one) ends up lying on the best-fit line, and therefore my data should now lie on this (rotated) axis.
What I've tried is to evaluate the rotation matrix from the slope of the line-of-fit (m in the formula for a first grade polynomial y=mx+q) as
[cos(m) -sin(m);sin(m) cos(m)]
and then multiply my original data by this matrix...to no avail!
I keep obtaining a plot where my data lay in the middle and not on the x-axis where I expect them to be.
What am I missing?
Thank you for any help!
Best Regards,
Wintermute
A couple of things:
If you have a linear function y=mx+b, the angle of that line is atan(m), not m. These are approximately the same for small m', but very different for largem`.
The linear component of a 2+ order polyfit is different than the linear component of a 1st order polyfit. You'll need to fit the data twice, once at your working level, and once with a first order fit.
Given a slope m, there are better ways of computing the rotation matrix than using trig functions (e.g. cos(atan(m))). I always try to avoid trig functions when performing geometry and replace them with linear algebra operations. This is usually faster, and leads to fewer problems with singularities. See code below.
This method is going to lead to problems for some trajectories. For example, consider a north/south trajectory. But that is a longer discussion.
Using the method described, plus the notes above, here is some sample code which implements this:
%Setup some sample data
long = linspace(1.12020, 1.2023, 1000);
lat = sin ( (long-min(long)) / (max(long)-min(long))*2*pi )*0.0001 + linspace(.2, .31, 1000);
%Perform polynomial fit
p = polyfit(long, lat, 4);
%Perform linear fit to identify rotation
pLinear = polyfit(long, lat, 1);
m = pLinear(1); %Assign a common variable for slope
angle = atan(m);
%Setup and apply rotation
% Compute rotation metrix using trig functions
rotationMatrix = [cos(angle) sin(angle); -sin(angle) cos(angle)];
% Compute same rotation metrix without trig
a = sqrt(m^2/(1+m^2)); %a, b are the solution to the system:
b = sqrt(1/(1+m^2)); % {a^2+b^2 = 1}, {m=a/b}
% %That is, the point (b,a) is on the unit
% circle, on a line with slope m
rotationMatrix = [b a; -a b]; %This matrix rotates the point (b,a) to (1,0)
% Generally you rotate data after removing the mean value
longLatRotated = rotationMatrix * [long(:)-mean(long) lat(:)-mean(lat)]';
%Plot to confirm
figure(2937623)
clf
subplot(211)
hold on
plot(long, lat, '.')
plot(long, polyval(p, long), 'k-')
axis tight
title('Initial data')
xlabel('Longitude')
ylabel('Latitude')
subplot(212)
hold on;
plot(longLatRotated(1,:), longLatRotated(2,:),'.b-');
axis tight
title('Rotated data')
xlabel('Rotated x axis')
ylabel('Rotated y axis')
The angle you are looking for in the rotation matrix is the angle of the line makes to the horizontal. This can be found as the arc-tangent of the slope since:
tan(\theta) = Opposite/Adjacent = Rise/Run = slope
so t = atan(m) and noting that you want to rotate the line back to horizontal, define the rotation matrix as:
R = [cos(-t) sin(-t)
sin(-t) cos(-t)]
Now you can rotate your points with R

How to plot a second graph instead of color coding in matlab

i just started with my master thesis and i already am in trouble with my capability/understanding of matlab.
The thing is, i have a trajectory on a surface of a planet/moon whatever (a .mat with the time, and the coordinates. Then i have some .mat with time and the measurement at that time.
I am able to plot this as a color coded trajectory (using the measurement and the coordinates) in scatter(). This works awesomely nice.
However my problem is that i need something more sophisticated.
I now need to take the trajectory and instead of color-coding it, i am supposed to add the graph (value) of the measurement (which is given for each point) to the trajectory (which is not always a straight line). I will added a little sketch to explain what i want. The red arrow shows what i want to add to my plot and the green shows what i have.
You can always transform your data yourself: (using the same notation as #Shai)
x = 0:0.1:10;
y = x;
m = 10*sin(x);
So what you need is the vector normal to the curve at each datapoint:
dx = diff(x); % backward finite differences for 2:end points
dx = [dx(1) dx]; % forward finite difference for 1th point
dy = diff(y);
dy = [dy(1) dy];
curve_tang = [dx ; dy];
% rotate tangential vectors 90° counterclockwise
curve_norm = [-dy; dx];
% normalize the vectors:
nrm_cn = sqrt(sum(abs(curve_norm).^2,1));
curve_norm = curve_norm ./ repmat(sqrt(sum(abs(curve_norm).^2,1)),2,1);
Multiply that vector with the measurement (m), offset it with the datapoint coordinates and you're done:
mx = x + curve_norm(1,:).*m;
my = y + curve_norm(2,:).*m;
plot it with:
figure; hold on
axis equal;
scatter(x,y,[],m);
plot(mx,my)
which is imo exactly what you want. This example has just a straight line as coordinates, but this code can handle any curve just fine:
x=0:0.1:10;y=x.^2;m=sin(x);
t=0:pi/50:2*pi;x=5*cos(t);y=5*sin(t);m=sin(5*t);
If I understand your question correctly, what you need is to rotate your actual data around an origin point at a certain angle. This is pretty simple, as you only need to multiply the coordinates by a rotation matrix. You can then use hold on and plot to overlay your plot with the rotated points, as suggested in the comments.
Example
First, let's generate some data that resembles yours and create a scatter plot:
% # Generate some data
t = -20:0.1:20;
idx = (t ~= 0);
y = ones(size(t));
y(idx) = abs(sin(t(idx)) ./ t(idx)) .^ 0.25;
% # Create a scatter plot
x = 1:numel(y);
figure
scatter(x, x, 10, y, 'filled')
Now let's rotate the points (specified by the values of x and y) around (0, 0) at a 45° angle:
P = [x(:) * sqrt(2), y(:) * 100] * [1, 1; -1, 1] / sqrt(2);
and then plot them on top of the scatter plot:
hold on
axis square
plot(P(:, 1), P(:, 2))
Note the additional things have been done here for visualization purposes:
The final x-coordinates have been stretched (by sqrt(2)) to the appropriate length.
The final y-coordinates have been magnified (by 100) so that the rotated plot stands out.
The axes have been squared to avoid distortion.
This is what you should get:
It seems like you are interested in 3D plotting.
If I understand your question correctly, you have a 2D curve represented as [x(t), y(t)].
Additionally, you have some value m(t) for each point.
Thus we are looking at the plot of a 3D curve [x(t) y(t) m(t)].
you can easily achieve this using
plot3( x, y, m ); % assuming x,y, and m are sorted w.r.t t
alternatively, you can use the 3D version of scatter
scatter3( x, y, m );
pick your choice.
Nice plot BTW.
Good luck with your thesis.