利用Matlab编写一个模拟乒乓球发球的动画,输入发球的速度,角度,计算乒乓球的轨迹并显示。
GUI界面设计
设计GUI窗体界面如下:
首先在按钮(运行的回调中)获取GUI中的输入的参数:
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
t1=str2double(get(handles.edit1,'String'))/180*pi;
t2=str2double(get(handles.edit2,'String'))/180*pi;
v=str2double(get(handles.edit3,'String'));
% 乒乓球初速度和初始位置
x=0;y=0;z=1083-760;vx=v*sin(t1);vy=v*cos(t1)*cos(t2);vz=v*cos(t1)*sin(t2);
R=20;% 小球半径
g=9.8;% 重力加速度;
k=0.5*0.5*1.29*(3.14*0.02*0.02);% 空气阻力系数
f=0.00432;% 空气浮力
m= 0.0027; % 乒乓球质量
% 时间步长
dt=0.01;
Time=0;
绘制乒乓球的桌面
% 绘制桌面
xtable=[-1 -1 1 1 -1]*1525/2;
ytable=[0 1 1 0 0]*2740;
ztable=[0 1 0 0 0];
axes(handles.axes1)
patch(xtable,ytable,ztable,'k')
hold on
view(-130,30)
% 绘制球网
xw=[-1 -1 1 1 -1]*1525/2;
yw=[1 1 1 1 1]*2740/2;
zw=[0 1 1 0 0]*152.5;
patch(xw,yw,zw,'b')
乒乓球运动轨迹计算
考虑重力,空气浮力和空气阻力计算乒乓球的加速度,采用向前欧拉法近似计算乒乓球的轨迹
% 绘制小球
[X,Y,Z]=sphere;
X=X*R+x;
Y=Y*R+y;
Z=Z*R+z;
surf(-X,Y,Z,'edgecolor','r','facecolor','r')
% 更新小球位置
x=x+vx*dt*1000;
y=y+vy*dt*1000;
z=z+vz*dt*1000;
% 更新小球速度
ax=-sign(vx)*k*vx*vx/m;
ay=-sign(vy)*k*vy*vy/m;
az=-sign(vz)*k*vz*vz/m-g+f/m;
vx=vx+ax*dt;
vy=vy+ay*dt;
vz=vz+az*dt;
axis equal
axis([-800 800 -200 3000 -10 1000])
% 判断仿真结束
if abs(x)>1525/2 || y>2740 || y<0 || z<0
break
end
if abs(y-2740/2)<1 && z<152.5
break
end
Time=Time+dt;
pause(0.1)
surf(-X,Y,Z,'edgecolor','g','facecolor','g')
给定乒乓球落点,迭代计算乒乓球的发射方式
% 获取落点位置
xe=str2double(get(handles.edit4,'String'));
ye=str2double(get(handles.edit5,'String'));
flag=0;
R=20;% 小球半径
g=9.8;% 重力加速度;
k=0.5*0.5*1.29*(3.14*0.02*0.02);% 空气阻力系数
f=0.00432;% 空气浮力
m= 0.0027; % 乒乓球质量
for t1=-30/180*pi:0.005:30/180*pi
if flag==1
break
end
for t2=-20/180*pi:0.01:40/180*pi
if flag==1
break
end
for v=0:0.01:12
x=0;y=0;z=1083-760;vx=v*sin(t1);vy=v*cos(t1)*cos(t2);vz=v*cos(t1)*sin(t2);
% 时间步长
dt=0.01;Time=0;
while(1)
% 更新小球位置
x=x+vx*dt*1000;
y=y+vy*dt*1000;
z=z+vz*dt*1000;
% 更新小球速度
ax=-sign(vx)*k*vx*vx/m;
ay=-sign(vy)*k*vy*vy/m;
az=-sign(vz)*k*vz*vz/m-g+f/m;
vx=vx+ax*dt;
vy=vy+ay*dt;
vz=vz+az*dt;
% 判断仿真结束
if abs(x)>1525/2 || y>2740 || y<0 || z<0
break
end
if abs(y-2740/2)<1 && z<152.5
break
end
if abs(x-xe)<5 && abs(y-ye)<5 && abs(z)<5
flag=1;
T1=t1;
T2=t2;
V=v;
break
end
end
end
end
end
if flag==0
set(handles.text9,'string','落地点无法到达')
set(handles.text10,'string','')
set(handles.text11,'string','')
else
set(handles.text9,'string',['摆角为:',num2str(T1/pi*180)])
set(handles.text10,'string',['俯仰角为',num2str(T2/pi*180)])
set(handles.text11,'string',['速度为',num2str(v)])
%text(-700,2740/2,300,['摆角为:',num2str(T1/pi*180),';俯仰角为',num2str(T2/pi*180),';速度为',num2str(v)])
t1=T1;t2=T2;v=V;
x=0;y=0;z=1083-760;vx=v*sin(t1);vy=v*cos(t1)*cos(t2);vz=v*cos(t1)*sin(t2);
R=20;% 小球半径
g=9.8;% 重力加速度;
k=0.5*0.5*1.29*(3.14*0.02*0.02);% 空气阻力系数
f=0.00432;% 空气浮力
m= 0.0027; % 乒乓球质量
% 时间步长
dt=0.01;
Time=0;
while(1)
% 绘制桌面
xtable=[-1 -1 1 1 -1]*1525/2;
ytable=[0 1 1 0 0]*2740;
ztable=[0 1 0 0 0];
axes(handles.axes1)
patch(xtable,ytable,ztable,'k')
hold on
view(-130,30)
% 绘制球网
xw=[-1 -1 1 1 -1]*1525/2;
yw=[1 1 1 1 1]*2740/2;
zw=[0 1 1 0 0]*152.5;
patch(xw,yw,zw,'b')
% 绘制小球
[X,Y,Z]=sphere;
X=X*R+x;
Y=Y*R+y;
Z=Z*R+z;
surf(-X,Y,Z,'edgecolor','r','facecolor','r')
% 更新小球位置
x=x+vx*dt*1000;
y=y+vy*dt*1000;
z=z+vz*dt*1000;
% 更新小球速度
ax=-sign(vx)*k*vx*vx/m;
ay=-sign(vy)*k*vy*vy/m;
az=-sign(vz)*k*vz*vz/m-g+f/m;
vx=vx+ax*dt;
vy=vy+ay*dt;
vz=vz+az*dt;
axis equal
axis([-800 800 -200 3000 -10 1000])
% 判断仿真结束
if abs(x)>1525/2 || y>2740 || y<0 || z<0
break
end
if abs(y-2740/2)<1 && z<152.5
break
end
Time=Time+dt;
pause(0.01)
surf(-X,Y,Z,'edgecolor','g','facecolor','g')
end
end