mechanizmos58

vpython_catenary_animation

Aug 26th, 2021 (edited)
977
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #27_08_21
  2.  
  3. '''
  4. From:
  5. "Modeling a Catenary Cable as a Bunch of Masses Connected by Springs"
  6. in Rhett Allain's Physics Explained Channel
  7.  
  8. tested on: Linux Mint 20.2, Geany 1.36, python 3.8.10,
  9. Web Epiphany, i5-7260U CPU @ 2.20GHz × 2, Iris Plus Graphics 640
  10. vpython version: ['7.6.1', 'jupyter']
  11.  
  12. '''
  13.  
  14. from vpython import *
  15. import sys
  16.  
  17. def main():
  18.     print(version)
  19.  
  20.     scene.width, scene.height = 1900, 980
  21.     scene.align = 'left'
  22.     scene.autoscale = False
  23.     scene.autozoom = False
  24.     scene.userspin = True
  25.     scene.userzoom = True
  26.     scene.userpan = False
  27.     scene.resizable = False
  28.     scene.range = 0.25
  29.  
  30.     CATENARY = 1
  31.  
  32.     HORIZONTAL = 1
  33.  
  34.     RATE = 200
  35.  
  36.     dt = 0.001
  37.  
  38.     # NUMBER OF BALLS (CHAIN LINKS)
  39.     N = 20
  40.  
  41.     # LINEAR LENGTH OF CHAIN IN "RELAXED" STATE
  42.     L = 0.2
  43.  
  44.     # TOTAL MASS
  45.     M = 0.1
  46.  
  47.     # INDIVIDUAL MASS
  48.     #mass = M/N
  49.     mass = 0.005
  50.  
  51.     # SPRING CONSTANT
  52.     k = 70
  53.  
  54.     # GRAVITY ACCELERATION VECTOR
  55.     A = vec(0, -9.8, 0)
  56.  
  57.     # Fdrag = -C * momentum (p)
  58.     C = 3.0
  59.  
  60.     if CATENARY:
  61.         leftend = vec(-0.1, 0.1, 0)
  62.     else:
  63.         leftend = vec(0, 0.2, 0)
  64.  
  65.     if HORIZONTAL or CATENARY:
  66.         ds = vec(1, 0, 0) * L/(N-1)
  67.     else:
  68.         ds = vec(0, -1, 0) * L/(N-1)
  69.  
  70.     # SPRING "RELAXED" LENGTH
  71.     Srel = L/(N-1)
  72.  
  73.     # BALL RADIUS
  74.     R = 0.004
  75.  
  76.     # CONSTRUCT THE CHAIN
  77.     balls = []
  78.     for i in range(N):
  79.         balls += [sphere(pos=leftend+i*ds, radius=R, m=mass,
  80.         color=color.white, p=vec(0,0,0), F=vec(0,0,0))]
  81.     springs = []
  82.     for i in range(N-1):
  83.         springs += [cylinder(pos=leftend+i*ds, axis=ds, radius=R/6)]
  84.  
  85.  
  86.     t = 0
  87.     while t < 4:
  88.  
  89.         rate(RATE)
  90.  
  91.         # CHAIN LEFTEND
  92.         balls[0].F = vec(0,0,0)
  93.  
  94.         # CHAIN MIDDLE
  95.         for i in range(1, N-1):
  96.  
  97.             Fgrav = balls[i].m * A
  98.             Fspr0 = -k*(mag(springs[i-1].axis)-Srel) * norm(springs[i-1].axis)
  99.             Fspr1 = +k*(mag(springs[i].axis)-Srel) * norm(springs[i].axis)
  100.             Fdrag = -C * balls[i].p
  101.  
  102.             balls[i].F = Fspr0 + Fspr1 + Fgrav + Fdrag
  103.  
  104.         # CHAIN RIGHTEND
  105.         if CATENARY:
  106.             balls[-1].F = vec(0,0,0)
  107.         else:
  108.             Fgrav = balls[-1].m * A
  109.             Fspr0 = -k*(mag(springs[-1].axis)-Srel) * norm(springs[-1].axis)
  110.             Fdrag = -C * balls[-1].p
  111.  
  112.             balls[-1].F = Fspr0 + Fgrav + Fdrag
  113.  
  114.         for ball in balls:
  115.             ball.p += ball.F * dt
  116.             ball.pos += ball.p * dt/ball.m
  117.  
  118.         for i in range(1, N):
  119.             springs[i-1].axis = balls[i].pos - balls[i-1].pos
  120.             springs[i-1].pos = balls[i-1].pos
  121.  
  122.         t += dt
  123.  
  124.     # PRINT FINAL LENGTH OF CHAIN
  125.     Lnew = 0
  126.     for i in range(1,N):
  127.         dLnew = mag(balls[i].pos - balls[i-1].pos)
  128.         Lnew += dLnew
  129.     print('New Length', Lnew)
  130.  
  131.  
  132. class g: ...
  133.  
  134.  
  135. if __name__ == '__main__':
  136.     sys.exit(main())
  137.  
RAW Paste Data