Python工程数学7VPython制作3D图形和动画(下)摆动动画

打印 上一主题 下一主题

主题 917|帖子 917|积分 2751

7.4 摆动动画

从静止位置偏转的摆会产生摆动。这些摆动和其他活动一样可以制作动画。
在制作摆的活动动画时,必须起首创建描述摆活动的微分方程体系。
然后在动画循环中使用简朴的求和算法求解该微分方程系。根据微分方程系的解,可以盘算出摆锤的 x-y 位置。
7.4.1 单摆

理想单摆(数学摆)的活动可以用下面的微分方程来描述:

接下来,我们将使用下面的代换:

因此,您将得到一个包罗两个一阶微分方程的微分方程体系:

由于精度对于动画并非绝对必要,算法的效率才是最重要的,因此使用欧拉法是求解该微分方程系的便捷方法。
下例演示了单摆的活动。微分方程系在动画循环中使用欧拉法的求和算法求解。摆锤由代表螺纹的圆柱体对象(圆柱体)和代表质量的球体对象(球体)组成。
  1. #18_pendulum.py
  2. from vpython import *
  3. y0=-5. #shift on the y-axis
  4. b=5. #width of the ceiling
  5. l=8. #length of the pendulum
  6. phi=45. #deflection
  7. r=0.5 #radius of the sphere
  8. scene.width=600
  9. scene.height=600
  10. scene.center =vector(0,y0,0)
  11. scene.range=1.5*b
  12. scene.background = color.white
  13. box(size=vector(b,b/20.,b/2.),color=color.gray(0.8)) #ceiling
  14. rod=cylinder(axis=vector(0,l,0),radius=0.05)
  15. mass = sphere(radius=r,color=color.red)
  16. mass.pos=vector(0,rod.pos.y,0)
  17. g=9.81 #gravitational acceleration
  18. w02=g/l  #square of the angular frequency
  19. phi=radians(phi)
  20. w=0. #initial angular velocity
  21. dt=0.02
  22. while True:
  23.     rate(100)
  24.     phi=phi+w*dt
  25.     w=w-w02*sin(phi)*dt
  26.     x= l*sin(phi)
  27.     y=-l*cos(phi)
  28.     rod.axis=vector(x,y,0)
  29.     mass.pos  =vector(x,y,0)
复制代码
第6行定义了偏转角 phi。利用和算法 phi=phi+wdt 和 w=w-w02sin(phi)*dt 在动画循环(第 22 至 29 行)中求解摆活动的微分方程系(第 24 和 25 行)。第 26 和 27 行盘算当前球体位置的 x 和 y 坐标。第 28 和 29 行更新杆和球体的位置。
7.4.2 弹簧摆

弹簧摆的摆动活动可以用以下微分方程描述:

通过代换可以得到以下微分方程系:


下例展示了弹簧-质量体系的摆动。质量由一个球形物体表示。
  1. #19_spring_pendulum.py
  2. from vpython import *
  3. y0=-5. #shift on the y-acis
  4. b=8.   #width of the ceiling
  5. l=0.8*y0 #length of the spring
  6. r=1.#radius of the mass
  7. c=1.#spring constant
  8. m=1.#mass of the sphere
  9. scene.width=600
  10. scene.height=600
  11. scene.center =vector(0,y0,0)
  12. scene.background = color.white
  13. box(pos=vector(0,b/40.,0),size=vector(b,b/20.,b/2.),
  14. color=color.gray(0.8)) #ceiling
  15. spring=helix(axis=vector(0,l,0),radius=0.6,color=color.yellow)
  16. spring.thickness=0.2
  17. spring.coils=8
  18. mass=sphere(pos=spring.pos,radius=r,color=color.red)
  19. w02=c/m   #square of the angular frequency
  20. y=-0.6*l #deflection
  21. v=0. #initial velocity
  22. dt=0.02
  23. while True:
  24.     rate(100)
  25.     y=y+v*dt
  26.     v=v-w02*y*dt
  27.     spring.axis=vector(0,y+l,0)
  28.     mass.pos =vector(0,y+l-r,0)
复制代码
第 03 和 11 行将坐标原点向上移动了 5 个长度单位。第 05 至 08 行定义了弹簧摆的数据。
在第 14 行中,helix() 方法创建了弹簧对象 spring。第 15 和 16 行补充了弹簧对象的属性。第 17 行中,sphere() 方法创建了球体对象质量。
挠度(初始值)设置为弹簧长度 l 的 60%(第 19 行)。
在无限循环中(第 22 行至第 27 行),使用欧拉方法求解微分方程体系(第 24 行和第 25 行)。
第 26 和 27 行更新了弹簧末了和球心的位置。

7.5 事件处理

对于事件处理,VPython 还提供了下令按钮(按钮)、单选按钮(单选)、多选选项(复选框和菜单)和滑块(滑块)等控件。
对于每个事件,都必须定义一个函数来执行相关操作。事件总是按照以下模式实现的:control(bind=function, ...)
控件标识符可以是一个控件的名称,如按钮、滑块、复选框或单选按钮。为使 controlelement 方法可以或许触发事件,必须将一个自定义函数作为参数通报给该方法。该函数将分配给绑定属性。自定义函数的括号必须省略。所有其他参数取决于控件的类型。下例显示了如何使用滑块()方法改变电压指针的旋转频率。复选框()方法可以激活以双倍频率旋转的功率指针。button()方法可用于停息和重启动画。
  1. #20_event-processing.py
  2. from vpython import *
  3. scene.title="<h2>Rotating voltage and power pointer</h2>"
  4. scene.width=scene.height=600
  5. scene.background=color.white
  6. runs = True
  7. col=color.yellow
  8. def start(b):
  9.     global runs
  10.     runs = not runs
  11.     if runs: b.text = "Pause"
  12.     else: b.text = "Start"
  13. def omega(s):
  14.     txtA.text = "{:1.2f}".format(s.value)
  15. def visibleP(b):
  16.     if b.checked:
  17.         p.visible = True
  18.     else:
  19.         p.visible = False
  20. u_s=2.
  21. p_s=1.5
  22. d=0.025
  23. scene.range = 1.2*u_s
  24. u=arrow(pos=vec(0,0,0),axis=vec(0,u_s,0),color=color.blue)
  25. p=arrow(pos=vec(0,0,0),axis=vec(p_s,0,0),color=col)
  26. p.visible=False
  27. u.shaftwidth=d
  28. p.shaftwidth=d
  29. button(text="Pause",pos=scene.title_anchor,bind=start)
  30. scene.append_to_caption("\n\n")
  31. scene.caption="\n Change frequency:\n\n"
  32. sldF=slider(min=0,max=6.28,value=1,length=300,bind=omega,right=4)
  33. txtA=wtext(text="{:1.2f}".format(sldF.value))
  34. scene.append_to_caption(" rad/s\n\n")
  35. checkbox(bind=visibleP, text="Show power pointer\n\n")
  36. dt=0.01
  37. w=1.
  38. while True:
  39.     rate(1/dt)
  40.     if runs:
  41.         w=sldF.value
  42.         u.rotate(angle=w*dt,axis=vec(0,0,1))
  43.         p.rotate(angle=2.0*w*dt,axis=vec(0,0,1))
复制代码
如果全局 runs 变量的值(第 07 和 11 行)为 True,动画将在 while 循环(第 43 至 48 行)中执行。如果要停息动画,必须单击 “停息 ”按钮。然后,按钮的标签将变为 Start(开始)。在这种情况下,第 34 行的 button() 方法会调用第 10 至 14 行的自定义 start(b) 函数。下令按钮位于场景的左上角。start(b) 函数通过 bind=start 调用。函数定义的括号和函数参数 b 必须省略。
在第 37 行中,slider() 方法调用了第 16 和 17 行中的自定义 bind=omega 函数。设置值存储在 sldF
对象中,并显示在第 38 行的 txtA 文本字段中。在第 46 行,使用 w=sldF.value 赋值改变旋转频率。
第 40 行的 checkbox(bind=visible,...) 方法调用了第 19 至 23 行的自定义函数 visible(b)。如果激活复选框控件,电源指针就会打开。

参考资料

7.6 项目任务:耦合弹簧摆的动画

在此任务中,我们需要在 VPython 中制作一个耦合弹簧摆的振荡动画,该摆由两个弹簧-质量体系组成,弹簧常数为 c1 和 c2,质量为 m1 和 m2。弹簧-质量体系沿 y 轴方向摆动。阻尼应临时忽略。
该解决方案包括三个步骤:

  • 创建微分方程体系:


  • 使用以下代换将该方程体系转换为一阶微分方程体系:
    并由此得到以下一阶微分方程系:


  • 利用欧拉法创建微分方程系的求解算法:

  1. from vpython import *
  2. y0 = -5.  # shift on the y-axis
  3. b = 10.  # width of the ceiling
  4. r = 1.  # radius of the mass
  5. l = 0.9 * y0
  6. c1 = 1.  # spring constant
  7. m1 = 1.  # mass of the sphere
  8. c2 = 1.
  9. m2 = 1.
  10. scene.width = 600
  11. scene.height = 800
  12. scene.center = vector(0, 2 * y0, 0)
  13. scene.background = color.white
  14. box(pos=vector(0, b / 40., 0), size=vector(b, b / 20., b / 2.),
  15.      color=color.gray(0.8))  # ceiling
  16. # 计算弹簧 1 的底部和顶部端点
  17. spring1_bottom = vector(0, 0, 0)
  18. spring1_top = spring1_bottom + vector(0, l, 0)
  19. spring1 = helix(pos=spring1_bottom, axis=spring1_top - spring1_bottom,
  20.                  color=color.yellow, radius=0.5 * r, thickness=0.2, coils=10)
  21. mass1 = sphere(pos=spring1_top, radius=r, color=color.red)
  22. # 类似地计算弹簧 2 的端点
  23. spring2_bottom = spring1_top
  24. spring2_top = spring2_bottom + vector(0, l, 0)
  25. spring2 = helix(pos=spring2_bottom, axis=spring2_top - spring2_bottom,
  26.                  color=color.green, radius=0.5 * r, thickness=0.2, coils=10)
  27. mass2 = sphere(pos=vector(0,2*l,0),radius=r, color=color.blue)
  28. y1=-0.6*l #deflection
  29. y2=0
  30. v1=v2=0 #initial velocity
  31. lk=l-r
  32. dt=0.02
  33. while True:
  34.     rate(50)
  35.     y1=y1 + v1*dt
  36.     v1=v1-(c1+c2)/m1*y1*dt+c2/m1*y2*dt #-0.05*v1*dt
  37.     y2=y2 + v2*dt
  38.     v2=v2-c2/m2*(y2-y1)*dt #-0.05*v2*dt
  39.     spring1.axis=vector(0,y1+l,0)
  40.     mass1.pos =vector(0,y1+lk,0)
  41.     spring2.axis=vector(0,y1+y2+l,0)
  42.     spring2.pos.y =mass1.pos.y
  43.     mass2.pos =spring2.pos+vector(0,y1+y2+lk,0)
复制代码

7.7 项目任务: 两个耦合简朴摆的动画

对于接下来的任务,我们需要制作一个摆体系的动画,该摆体系由两个简朴的数学摆组成,其质量 m 通过弹簧(弹簧常数 c)毗连。起首,您必须再次创建弹簧-质量体系的微分方程体系:

然后,使用下面的代换:

因此,您将得到下面的一阶微分方程系:

使用缩写

并根据欧拉法从一阶微分方程体系中开发出算法
一阶微分方程系:
  1. #22_double_pendulum.py
  2. from vpython import *
  3. phi1=radians(-5.)
  4. phi2=radians(5.)
  5. b=12.   #width of the ceiling
  6. y0=-b/2.#shift on the y-axis
  7. a=b/2.  #distance between the pendulums
  8. l=0.9*b #length of the pendulums
  9. r=b/15. #radius of the spheres
  10. m=10.   #mass of the spheres
  11. c=4. #spring constant
  12. scene.width=600
  13. scene.height=600
  14. scene.center=vector(0,y0,0)
  15. scene.range=0.8*b
  16. scene.background = color.white
  17. box(size=vector(b,b/20.,b/4.),color=color.gray(0.8)) #ceiling
  18. rod1=cylinder(axis=vector(0,l,0),radius=0.05)
  19. rod1.pos=vector(-a/2.,0,0)
  20. rod2=cylinder(axis=vector(0,l,0),radius=0.05)
  21. rod2.pos=vector(a/2.,0,0)
  22. mass1 = sphere(radius=r,color=color.red)
  23. mass2 = sphere(radius=r,color=color.blue)
  24. spring=helix(axis=vector(a,0,0),radius=0.4)
  25. spring.thickness=0.1
  26. spring.coils=10
  27. g=9. #gravitational acceleration
  28. w02=g/l  #pendulum frequency
  29. k=c/m    #spring frequency
  30. w1=w2=0 #angular velocity
  31. dt=0.02
  32. while True:
  33.     rate(100)
  34.     phi1=phi1+w1*dt
  35.     w1=w1-w02*phi1*dt+k*(phi2-phi1)*dt #-0.05*w1*dt
  36.     phi2=phi2+w2*dt
  37.     w2=w2-w02*phi1*dt-k*(phi2-phi1)*dt #-0.05*w2*dt
  38.     x1= l*sin(phi1)
  39.     y1=-l*cos(phi1)
  40.     x2= l*sin(phi2)
  41.     y2=-l*cos(phi2)
  42.     rod1.axis=vector(x1,y1,0)
  43.     mass1.pos =vector(x1-a/2.,y1,0)
  44.     rod2.axis=vector(x2,y2,0)
  45.     mass2.pos =vector(x2+a/2.,y2,0)
  46.     spring.pos=mass1.pos+vector(r,0,0)
  47.     spring.axis.x=x2-x1+a-2*r
  48.     spring.axis.y=y2-y1
复制代码
在第 03 和 04 行,您可以改变两个摆的偏转角 phi1 和 phi2。
第 10 和 11 行定义了摆锤的质量和耦合弹簧的弹簧常数。
第 34 至 37 行求解了微分方程体系。测试时可将其删除。
在第 38 至 41 行,根据偏转角 phi1 和 phi2 盘算当前的 x-y 坐标。
在第 42 至 48 行,为每个摆锤和耦合弹簧分配当前位置。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

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

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

尚未崩坏

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表