找回密码
 注册
关于网站域名变更的通知
查看: 1286|回复: 1
打印 上一主题 下一主题

在MATLAB中实现模拟小球上抛和反弹运动

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-3-3 13:57 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
在高中物理中我就学到物体的平抛运动,今天我们在这里也老调重弹下,再次来回顾下这个经典的过程,不过这次讲解的要比之前平抛运动稍微复杂一些:
* V) R# ]2 E! i6 t
" ]2 G) n; S, p( n, ~. N3 S$ o7 E小球的上抛运动的完整过程描述如下:
7 G+ z. h0 E) T5 K2 h0 T
3 o9 U1 V3 I& H* P& Q9 H3 O8 V8 X, U1、我们站在高度为H的看台上抛一个小球
( R3 `' W4 O6 O2、上抛的初速度为V,角度为θ
$ \2 U8 W7 V& p: O/ I3、小球与空气摩擦力与速度成正比,摩擦系数为μ
1 L1 x) s& t: W& ]6 o3 ]0 D* S; b4、小球撞地之后能量损失,速度变为原来的k倍,然后继续反弹- z  i4 G  x, U5 v( j& O

, F3 l6 P. y3 w9 f& D. O在上面基础上我们继续讨论,比如我们高炮部队,要给予敌方阵地毁灭一击,那么:% M5 x7 j+ O6 T7 n/ n, y/ G% |

9 l8 h1 O/ o. S# S5 B) `  s1 x' i, E1、在已知炮弹初速度V的情况下,以什么角度θ,能使炮弹飞的最远
1 `9 j6 ]' H! R) r+ }2、在已知炮弹初速度V和敌方阵地水平距离L的情况下,发射角度θ等于多少时,能整好命中敌方) }4 ~3 X6 Y* R2 P; f( U2 a! E

- M& \( W( C* S# a' f& D哈哈,这几个问题好像不是高中的平抛运动能够解决的哦。其实原理和小球的运动方程很容易建立,但是求解起来是有些麻烦的。
6 K" U# T! [9 F5 R. H- v% P* s" }; [
我们本次教程这里介绍如何使用MATLAB求解并模拟这个问题,主要设计的内容有:( Y6 Z/ ]2 I# a: {4 p8 s

( q6 n) A: T2 a: D; \0 t: U5 a3 t: F1、小球运动微分法方程求解, M' O5 n/ S9 s
2、小球着陆时,过零点检测(重点)
' h  H+ N* \* p' F3、小球反弹运动轨迹模拟, f. c7 b: n2 f: l
4、炮弹飞行距离目标最优化* X( W8 w4 e! a, X$ W- H
5、发射角度θ的数值求解$ Y# m  y. |0 t# H3 G

. J" l$ s% o6 K# H
! F; j& `+ V  Q4 U3 |由于教程的内容很多,这次主要讲解前三个问题,后两个问题留在稍候的下次教程中讲解!!!3 a7 I( t$ h+ ]: W. }
* w4 J& m  {! ~

/ W. u- K7 M- B
8 _# s. H8 `; q! v$ t7 x0 O+ X小球空中运动方程,只要稍微有一点高中物理和高等数学基础的朋友应该都可以看懂这个方程吧:% X/ W; E8 ]- ?6 N1 A/ j

8 E0 U  z) n: j : F& _. K* P- R+ Y2 q
; X: t( h5 G1 y" `! J# N3 y! u
上面是相当简单的一个常微分方程组,要求解这个方程组也相当容易,MATLAB提供的ode45函数足以胜任。
0 ^, G! j; s) N5 L
" ?8 l9 l/ u( Q: y& A编写主函数main.m* g( [' r) p2 z% {* t
  • function main()
  • global m mu g
  • m=1; % 小球质量
  • mu=0.3; % 摩擦系数
  • V0=100; % 初始速度
  • theta=pi/6; % 初始角度
  • g=9.8; % 重力加速
  • k=0.8; % 撞击系数
  • H=10; % 初始高度
  • tspan=[0 10]; % 求解时间范围
  • x0=[0,V0*cos(theta),H,V0*sin(theta)]; % 微分方程初值
  • [t,x]=ode45(@odefun,tspan,x0);
  • X=x(:,1);
  • Vx=x(:,2);
  • Y=x(:,3);
  • Vy=x(:,4);
  • figure
  • plot(t,x)
  • legend('X','Vx','Y','Vy')
  • xlabel('时间')
  • ylabel('变量')
  • grid on
  • figure
  • plot(X,Y)
  • xlabel('水平方向')
  • ylabel('竖直方向')
  • title('小球运动轨迹')
  • grid on
    0 P* F$ x/ S  e5 k* |$ ], L. f8 n

/ f+ t9 b6 T* `& i/ a7 N, n' v) |# `; _' w) b
' z' v( `" [; I  V/ ~
继续编写微分方程组描述函数odefun.m  {  z% C/ n8 C+ Z  f* F1 Z) Y

# y2 m2 v) t9 r' M* I
  • function dx=odefun(t,x)
  • % 微分方程描述函数
  • global m mu g
  • % X=x(1);
  • Vx=x(2);
  • % Y=x(3);
  • Vy=x(4);
  • % 运动微分方程
  • dx=[Vx
  •     -mu*Vx/m       % dVx/dt
  •     Vy
  • -mu*Vy/m-g];   % dVy/dt7 g. U. E- ?* Z( S# L" o& j

( S4 \8 S' `* }  Z( q
% |  K7 F, [' @- R6 b/ {, F! P) S运行之后我们得到如下结果:
5 ~- S1 |9 Y9 X; V5 T+ }: [) v) O4 X0 R: R9 R
- i  }* b0 a) i( ]. e

5 u+ F1 m) ~+ c# [6 X0 W! D  d9 ]1 G0 e, A
从上面的“小球运动轨迹图形”可看出,小球在水平位移265米左右就撞地了,小球撞地以后会反弹,显然上图撞地之后的数据就是无效的。
9 S0 i, s- O, e1 ?6 h, {& Y2 ~0 f
但是要模拟小球的着陆撞击反弹过程,我们希望程序能够自动检测到那个小球撞击的时刻,听起来好像有些深奥哦,其实这个也没什么高深的,因为MATLAB的ode45函数早就为我们考虑到这点了,此时只需要设置ODE方程的一个过零点检测,也就是设置ode45函数的events属性即可。+ ^6 ~  Y* ?3 n4 G

2 d" \8 n  A. e' i% B修改main.m函数,主要是通过options参数添加events事件检测(黄色部分):, ?# P, D3 q* w' q/ x. U$ O
' ^" o9 ~4 T5 U
  • function main
  • global m mu g
  • m=1; % 小球质量
  • mu=0.3; % 摩擦系数
  • V0=100; % 初始速度
  • theta=pi/6; % 初始角度
  • g=9.8; % 重力加速
  • k=0.8; % 撞击系数
  • H=10; % 初始高度
  • tspan=[0 10]; % 求解时间范围
  • x0=[0,V0*cos(theta),H,V0*sin(theta)]; % 微分方程初值
  • options=odeset('events',@events); % 设置小球过零点(撞地)检测条件
  • [t,x,te,xe,ie]=ode45(@odefun,tspan,x0,options);
  • X=x(:,1);
  • Vx=x(:,2);
  • Y=x(:,3);
  • Vy=x(:,4);
  • figure
  • plot(t,x)
  • legend('X','Vx','Y','Vy')
  • xlabel('时间')
  • ylabel('变量')
  • title('参数随时间变化图形')
  • grid on
  • figure
  • plot(X,Y)
  • xlabel('水平方向')
  • ylabel('竖直方向')
  • title('小球运动轨迹图形')
  • grid on' O; B6 B8 L6 B* |; ]4 R% Q; }. m

" J! c; k) B! U& q
) f/ J! f: ?6 f; g6 j& n- P" u& ^" e1 M' I$ w4 j% [4 P3 S$ u
编写events.m文件描述需要检测的事件(过零点检测):
/ A+ a% s$ Y/ ]) i" r9 @
  • function [value,isterminal,direction]=events(t,x)
  • % 事件检查函数,此时需要做的是过零点检测
  • Y=x(3);
  • % ode45函数自动检查当value=0是否成立
  • % 在此问题上我们要求检测Y=0的点,因此设置value=Y
  • % 如果我们要检测Y=2,那么就设置value=Y-2
  • value=Y;
  • % 检测到指定条件时,是否终止ode45函数的运行
  • % 1表示终止,0表示继续
  • % 在我们这个问题上,我们只要检测到零点时就停止程序
  • isterminal=1;
  • % value过零点检测的方向
  • % -1表示由正到负,+1表示由负到正
  • % 对于我们这个问题,当然是由正到负
  • direction=-1;
    ; |4 G" N. U# b4 Z5 e+ f2 R5 v" s( q# V4 @
- e1 |; F, A! B. p+ s

8 c  b4 R& s" J' r4 H' E0 j8 H) C4 A5 ~# h8 s0 `# l0 ]8 K
再次运行程序,得到如下运动轨迹图:
/ P2 _  f* h$ @/ t$ i% D
/ F! t( X* p1 O- \' Z- s3 v , f: A, M* p0 m- ?, O

% f) Y9 E  O, R' i& p; ~从图形可以看出,程序在检测到小球着陆,也就是Y=0时自动终止程序运行了,并通过ode45的te和xe参数返回事件发生的时刻te和此时所有的状态参数xe。% O' B/ v: {  ]3 r- \
3 a; z- W0 U0 ?# D; `- V; ^
之前的工作我们已经完成了方程求解和零点检测,但是还是没有完整的描述整个小球上抛运动的过程呀,比如反弹就没有。我们希望程序能够自动将整个过程都能够展现出来。
. _! q0 k" N, X, Y6 w  Q2 U+ t
- t7 ]: x( M, O" y' y, C有些网络是不是想说:“是不是MATLAB的ode45函数也为我们考虑到这点,并早已经准备好了某个函数或者参数提供给我们直接调用呀?”哈哈,这次很惋惜的告诉您,这个需要我们自己动手丰衣足食了,MATLAB不总是靠得住的,毕竟软件是死的,人是活的。。。。0 R; Y( T1 k2 m; L* y

1 X! X& A' i) U' P对于反弹以及全过程描述,其实也不难!我们只要在检测到撞地点以后,以撞击时候的参数为初值继续求解微分方程,这样一直下去。最后将所有的小过程连接起来,于是完整的小球上抛和反弹过程就可以展现出来了!每个小过程的求解,我们可以在循环语句中进行!
4 e6 W1 ?$ Q8 V6 U  p& m+ f, R
% ~* t8 X9 Q; s于是重新修改(黄色部分)main.m函数:
3 B5 F( R( i0 e- G  y7 ^. O5 D. o
1 `1 l* O& H7 `- a. n4 ^) l9 B9 ~
  • function main
  • global m mu g
  • m=1; % 小球质量
  • mu=0.25; % 摩擦系数
  • V0=100; % 初始速度
  • theta=pi/6; % 初始角度
  • g=9.8; % 重力加速
  • k=0.9; % 撞击系数
  • H=10; % 初始高度
  • tspan=[0 100]; % 求解时间范围
  • x0=[0,V0*cos(theta),H,V0*sin(theta)]; % 微分方程初值
  • options=odeset('events',@events); % 设置小球过零点(撞地)检测条件
  • n=10; % 反弹次数
  • % 初始化必要的参数
  • tout=tspan(1); % 记录完整过程的时间
  • xout=x0; % 记录完整过程的参数
  • teout=[]; % 记录撞击点时刻
  • xeout=[]; % 记录撞击点参数

  • & H1 ^1 H3 n3 k* S) A
  • for i=1:n
  •     [t,x,te,xe]=ode45(@odefun,tspan,x0,options);
  •     % 保存该阶段的参数
  •     tout=[tout;t(2:end)];
  •     xout=[xout;x(2:end,: )];
  •     teout=[teout;te];
  •     xeout=[xeout;xe];
  •    
  •     % 修改方程求解区间
  •     tspan(1)=te;
  •     % 修改初值方程
  •     x0(1)=xe(1); % 水平位移
  •     x0(2)=xe(2)*k; % 水平速度,注意乘以撞击系数
  •     x0(3)=0; % 竖直位移
  •     x0(4)=-xe(4)*k; % 竖直速度,注意乘以撞击系数,并且反弹
  • end
  • X=xout(:,1);
  • Vx=xout(:,2);
  • Y=xout(:,3);
  • Vy=xout(:,4);
  • figure
  • plot(tout,xout)
  • hold on
  • plot(teout,xeout,'ro','MarkeRFaceColor','red')
  • legend('X','Vx','Y','Vy')
  • xlabel('时间')
  • ylabel('变量')
  • title('参数随时间变化图形')
  • grid on
  • figure
  • plot(X,Y)
  • hold on
  • plot(xeout(:,1),xeout(:,3),'ro','MarkerFaceColor','red')
  • xlabel('水平方向')
  • ylabel('竖直方向')
  • title('小球运动轨迹图形')
  • grid on4 @# G( S$ y1 c0 z' V  w# q
, L: ?- \& ]# l2 v8 |* o- B

2 S0 Q$ ]8 f0 _6 |8 c! K: j$ X/ p
- ?) S+ b: Q3 f) C) x# v* v  A重新运行main函数,可以到小球上抛以反弹运动的完整过程了:+ x. N$ D1 q+ E. N# Z1 X& i' t# V# H

& Y. F1 H2 N% R4 R* [8 [
, j- D8 L1 x' x, v 17 分钟前 上传
% u! P/ T/ b; B! H下载附件 (36.32 KB)( V3 Q5 ^9 X" g" S
3 O$ Y1 b! y- g8 W! d! b/ j$ G

, J) K4 t  Q* F
" F5 v7 a5 o1 K$ f) v+ n4 x  G1 P" u; I: H' s' [" C7 j
) q! Q$ n0 C) u8 K
% I- M5 \  V3 K# h8 e

该用户从未签到

2#
发表于 2020-3-3 16:33 | 只看该作者
在MATLAB中实现模拟小球上抛和反弹运动
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-20 23:20 , Processed in 0.140625 second(s), 26 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表