我是Matlab的新手。我有一个脚本,使用ode45
和arrow.m
演示在Matlab中通过3D空间移动时带有质量的摆动弹簧的运动。该程序几乎可以完成我想要的操作。现在,钻石的密度显示出弹簧的速度(除了ode45
并以个人喜欢的数字样本作为参数),并且速度几乎准确地用函数的步长(至少是我的计算机运行代码的速度)来说明。我想要做的是让代码中注释掉的位置矢量仅显示在质量的瞬时位置(即曲线的端点),而不显示在菱形显示的每个点。我四处寻找帮助,但是我尝试执行的所有操作似乎都会导致错误。如果有人能指出我正确的方向,将不胜感激。请尝试运行该程序,您将明白我的意思,并且还可以使用该函数的参数。
function elasticPendulum(totalTime)
time=1;
totalTime=20
X=1
Vx=0
Y=0
Vy=0
Z=1.1
Vz=0
w=3;
g=9;
l=1;
while (time<totalTime)
tspan=[0,time];
x0=[X,Vx,Y,Vy,Z,Vz];
[t,x]=ode45(@F,tspan,x0);
plot3(x(:,1),x(:,3),x(:,5),'dk'), axis([-2 2 -2 2 -10 2]);
grid on;
o=[0, 0, 0];
Xeq=[0, 0, -(g/(w^2)+l)];
arrow(o,Xeq,'Length',5);
%{
Xt=[x(:,1) x(:,3) x(:,5)]
arrow(o,Xt,'Length',5);
%}
time=time+.1*(((x(2))^2+(x(4))^2+(x(6))^2)^(1/2))
pause(.1);
end
function xprime=F(t,x)
r=sqrt(x(1)^2+x(3)^2+x(5)^2);
xprime=[x(2);-w*(r-l)/r*x(1);x(4);-w*(r-l)/r*x(3);x(6);-w*(r-l)/r*x(5)-g];
end
end
我认为您可以简单地通过设置Xt
为此来完成您想要的,这样在每次迭代中只绘制最后一个向量:
Xt = [x(end,1) x(end,3) x(end,5)];
另外,您提到“除ode45接受个人喜欢的数字样本外,一切都在起作用”。您可以ode45
简单地通过更改来告诉您使用固定步长输出tspan
:
tspan = 0:dt:time;
在哪里dt = 1/time
(或者您可以使用linspace
)。这与使用固定步长求解器不是一回事–请阅读我对这个问题的答案,以便对此有所了解。
我认为您没有正确更新动画。您更新时间,但不更新初始条件。因此,您可以在while
循环的每次迭代中通过相同的路径进行集成。您是否有理由在每次迭代中调整结束时间?您是否正在寻找振荡周期或其他东西?
另外,您的动画制作方法相当粗糙/效率低下。您应该阅读有关可以通过Matlab的ODE求解器设置的输出选项odeset
的信息。特别是'OutputFcn'
。您甚至可以使用和/或查看一些内置输出函数的代码,例如,在命令窗口中键入edit odeplot
或edit odephas3
。这是我为您创建的一个简单的输出函数:
function elasticPendulum
totalTime = 20;
stepsPerSec = 10;
X = 1; Vx = 0;
Y = 0; Vy = 0;
Z = 1.1; Vz = 0;
w = 3; g = 9; l = 1;
opts = odeset('OutputFcn',@(t,x,flag)arrowplot(t,x,flag,w,l,g));
tspan = linspace(0,totalTime,totalTime*stepsPerSec);
x0 = [X,Vx,Y,Vy,Z,Vz];
ode45(@(t,x)F(t,x,w,l,g),tspan,x0,opts);
function xprime=F(t,x,w,l,g) %#ok<INUSL>
r=sqrt(x(1)^2+x(3)^2+x(5)^2);
xprime=[x(2);-w*(r-l)/r*x(1);x(4);-w*(r-l)/r*x(3);x(6);-w*(r-l)/r*x(5)-g];
function status=arrowplot(t,x,flag,w,l,g) %#ok<INUSL>
persistent h; % Handle for moving arrow
status = 0;
o = [0, 0, 0];
switch flag
case 'init'
axis([-2 2 -2 2 -10 2]); grid on; hold on;
Xeq = [0, 0, -(g/(w^2)+l)];
arrow(o,Xeq,'Length',5);
plot3(x(1,:),x(3,:),x(5,:),'dk'); % Initial position
Xt = [x(1,end) x(3,end) x(5,end)];
h = arrow(o,Xt,'Length',5); % Initial arrow, get handle
case 'done'
hold off; status = 1;
otherwise
plot3(x(1,:),x(3,:),x(5,:),'dk'); % Plot new positions
Xt = [x(1,end) x(3,end) x(5,end)];
arrow(h,'Start',o,'Stop',Xt,'Length',5); % Update arrow
pause(0.1);
end
plot3
每次迭代(中的otherwise
情况arrowplot
)的调用仍然效率低下,因为它添加了新的高级绘图对象,从而占用了更多内存。更好/更快的方法是从第一个调用获取句柄plot3
并使用set
并get
添加新的数据点。请参阅代码,odeplot
以及odephas3
如何执行此操作(有点高级)。
请注意,我还如何通过匿名函数而不是通过创建子函数来传递参数。这有点风格问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句