I am trying to transcribe one of my scripts into App Designer in Matlab so that I easily distribute it to students. The idea is to show forces and moments acting in 6 degrees of freedom on a vehicle in real time (based on user input through a joystick). I am using a very simplistic animation made of multiple 3D arrow plots at the moment (which refreshes every 0.1 s), but it does the job. What I would like to get is shown in the first figure, whereas the second figure shows what I actually get in App Designer.
The relevant lines of code in App Designer which I use for the plotting are as follows:
function plot_ROV(app)
% Plot the forces and moments acting on the ROV in the correct graph:
quiver3(app.UIAxes,0,0,0,1,0,0);
hold(app.UIAxes);
quiver3(app.UIAxes,0,0,0,0,1,0);
hold(app.UIAxes);
quiver3(app.UIAxes,0,0,0,0,0,1);
hold(app.UIAxes);
quiver3(app.UIAxes,0,0,0,app.Surge,0,0,'LineWidth',5,'Color',app.Colors(1,:));
hold(app.UIAxes);
quiver3(app.UIAxes,0,0,0,0,app.Sway,0,'LineWidth',5,'Color',app.Colors(2,:));
hold(app.UIAxes);
quiver3(app.UIAxes,0,0,0,0,0,app.Heave,'LineWidth',5,'Color',app.Colors(3,:));
hold(app.UIAxes);
app.circular_arrow3([1,0,0],app.Roll,0.2,app.Colors(4,:));
hold(app.UIAxes);
app.circular_arrow3([0,1,0],app.Pitch,0.2,app.Colors(5,:));
hold(app.UIAxes);
app.circular_arrow3([0,0,1],app.Yaw,0.2,app.Colors(6,:));
hold(app.UIAxes);
legend(app.UIAxes,'x-axis','y-axis','z-axis','surge','sway','heave','roll','roll',...
'pitch','pitch','yaw','yaw','Location','BestOutside');
end
function circular_arrow3(app,axis,angle,radius,color)
% Generate the data for the circle in 2D space:
np = 10; % no. points
a = linspace(0,angle*pi,np);
p = [radius.*cos(a);radius.*sin(a);zeros(1,np)];
% Select the correct rotation matrix depending on the axis:
if sum((axis-[1,0,0]).^2)==0
R = [0,0,1;0,1,0;-1,0,0];
elseif sum((axis-[0,1,0]).^2)==0
R = [1,0,0;0,0,-1;0,1,0];
p(2,:) = - p(2,:);
elseif sum((axis-[0,0,1]).^2)==0
R = eye(3);
else
error('Only rotations about the x-, y- and z-axes are supported');
end
% Rotate the points:
pr = zeros(size(p));
for i=1:np
pr(:,i) = R*p(:,i);
end
% Calculate the difference between the last two points:
x = pr(1,end);
y = pr(2,end);
z = pr(3,end);
u = pr(1,end)-pr(1,end-1);
v = pr(2,end)-pr(2,end-1);
w = pr(3,end)-pr(3,end-1);
% Plot the points:
plot3(app.UIAxes,pr(1,:),pr(2,:),pr(3,:),'LineWidth',4,'Color',color);
hold(app.UIAxes);
quiver3(app.UIAxes,x,y,z,u,v,w,'LineWidth',6,'Color',color);
end
Now, by comparing the two figures, I think my problem is that the hold command is not working, at least not the way I intend it to: only the points from the last circular arrow are shown. Since I do not have much experience with App Designer, my feeling is I must have done a basic mistake.
Thanks in advance for the help!
In the plot_ROV function you call hold several times providing only one input parameter (namely the handle of the axes) that is without specifying the on property (hold(app.UIAxes);.
If the hold function is called in such a way, its effect is to toggle the property on / off in each call.
You can fix the issue either:
removing all the calls to hold butg the first one: just on call is enough to "add" subsequents items in the axes through the plotting functions
you can keep all the calls, but you have to specify the on property
hold(app.UIAxes,'on');
For more information about the hold function you can refer to the hold on-line documentation
I'm using scatter function to plot data containing only 25000 rows, however when I use saveas function to save the image as png, it takes 2+ minutes to do so.
For example:
scatter(x,y,'filled');
pic_name = ['scatterplot.png'];
tic
saveas(gcf,pic_name,'png');
toc
Elapsed time is 152.681511 seconds.
Is there a quicker way to save a scatter plot?
scatter is known to be slow for high number of datapoints; that might include saving them (each point has a difference color, thus needs separate handling).
You might want to try plotting the data differently, like described here: matlab: scatter plots with high number of datapoints
This way, you get the same behaviour as with regular plots.
Instead of calling saveas(), you could try calling getframe() and then calling imwrite(), like this:
npoints = 25000;
x = linspace(0,3*pi, npoints);
y = cos(x) + rand(1, npoints);
scatter_series_handle = scatter(x,y,'filled');
pic_name = ['scatterplot.png'];
axes_handle = get(scatter_series_handle, 'Parent');
figure_handle = get(axes_handle, 'Parent');
img = getframe(figure_handle);
imwrite(img.cdata, pic_name, 'png');
I'm using Matlab to read a large (NetCDF) data set with information about a magnetic field. The data set is a three-dimensional array of 318x562x554 and I can retrieve have three one-dimensional array (318x1, 562x1 and 554x1) with each axis values of the coordinates. I would like to know the magnetic field values on points that do not fit on the data set grid. These points are in this case trajectory coordinates of a spacecraft placed in a two-dimensional array (3xn,n depends on how many coordinates you have).
x = ncread(file,'X_axis');
y = ncread(file,'Y_axis');
z = ncread(file,'Z_axis');
Bx = ncread(file,'Bx');
[x2,y2,z2] = meshgrid(y,x,z);
length = numel(interval_ET_5000);
Bx_intp = zeros(1,length);
for i = 1:length
[xi,yi,zi] = meshgrid(position_MEX_Mars_5000(1,i),...
position_MEX_Mars_5000(2,i),...
position_MEX_Mars_5000(3,i));
F = interp3(x2,y2,z2,Bx,xi,yi,zi);
Bx_intp(i) = F;
end
I have tried many things that didn't even work. This 'works' but not correct because the values in Bx_intp are way to high. Also because of the doing coordinates one at the time in a for loop makes it very slow, a normal run is about 3500 coordinates.
So basicly what I am looking for is a reverse scatteredInterpolant. This function accepts random data points and you interpolate the values on a meshgrid. But now I have a regular grid and I want interpolation on random points.
Thanks for the tip Ashish Uthama! I got it working with the code below. For other people with the same problem. You need ndgrid instead of meshgrid for griddedInterpolant and the coordinates need to be monotonic increasing.
x = ncread(file,'X_axis');
y = ncread(file,'Y_axis');
z = ncread(file,'Z_axis');
Bx = ncread(file,'Bx');
[x2,y2,z2] = ndgrid(x,y,z);
F = griddedInterpolant(x2,y2,z2,Bx,'linear','none');
Bx_intp = F(position_MEX_Mars_5000(1,i),...
position_MEX_Mars_5000(2,i),...
position_MEX_Mars_5000(3,i));
My question is similar to the post: matlab curve with label
I have some data (acquired using a function too long to show here), which gives me 2 arrays: Nv4 (337x1) and t (337x1) and I want to plot 'a=40' on the plot line.
I should be able to use contour label, but I need to convert my data as matrix format first. The post above gives a link to explain how to convert our data, unfortunately the link has expired and I have no idea how I should convert my data to. An example would be useful !
I'm posting this as a new question because I don't have enough reputation to post a comment
I guess there is another way, simply with text. Here is a sample:
% Create a sample curve
x = 1:337;
y = sqrt(x);
plot(x,y);
% Define position to display the text
i = round(numel(x)/2);
% Get the local slope
d = (y(i+1)-y(i))/(x(i+1)-x(i));
X = diff(get(gca, 'xlim'));
Y = diff(get(gca, 'ylim'));
p = pbaspect;
a = atan(d*p(2)*X/p(1)/Y)*180/pi;
% Display the text
text(x(i), y(i), 'a=40', 'BackgroundColor', 'w', 'rotation', a);
And here is the result:
Best,
So i have this graph with these two gaussians created in matlab
This Graph have been created using the following bit of matlab code
TimeTakenWDriver = textread('TimeTakenWDriver.txt');
TimeTakenWODriver = textread('TimeTakenWODriver.txt');
fig1 = figure;
h1 = histfit(TimeTakenWDriver);
std1 = std(TimeTakenWDriver);
std2 = std(TimeTakenWODriver);
mean1 = mean(TimeTakenWDriver)
mean2 = mean(TimeTakenWODriver)
delete(h1(1));
set(h1(2),'color','b');
hold on;
h2 = histfit(TimeTakenWODriver);
delete(h2(1));
set(h2(2),'color','r');
Now i want to find the two y coordinates that corresponds to the two means "the two top-points" ive searched around but cant get any of the solutions i find to work because of the way i create my graphs. Any ideas?
You can try getting the data directly from the plot:
C = get(get(gca, 'Children'), 'YData');
and then find the peak value using max:
max(C(:))
Note that if you have two or more plots on the same axes (as in your example), C would be a cell array, so you need to access each cell separately to get the peaks:
cellfun(#(x)max(x(:)), C)