test_body.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. from sympy.core.backend import (Symbol, symbols, sin, cos, Matrix, zeros,
  2. _simplify_matrix)
  3. from sympy.physics.vector import Point, ReferenceFrame, dynamicsymbols, Dyadic
  4. from sympy.physics.mechanics import inertia, Body
  5. from sympy.testing.pytest import raises
  6. def test_default():
  7. body = Body('body')
  8. assert body.name == 'body'
  9. assert body.loads == []
  10. point = Point('body_masscenter')
  11. point.set_vel(body.frame, 0)
  12. com = body.masscenter
  13. frame = body.frame
  14. assert com.vel(frame) == point.vel(frame)
  15. assert body.mass == Symbol('body_mass')
  16. ixx, iyy, izz = symbols('body_ixx body_iyy body_izz')
  17. ixy, iyz, izx = symbols('body_ixy body_iyz body_izx')
  18. assert body.inertia == (inertia(body.frame, ixx, iyy, izz, ixy, iyz, izx),
  19. body.masscenter)
  20. def test_custom_rigid_body():
  21. # Body with RigidBody.
  22. rigidbody_masscenter = Point('rigidbody_masscenter')
  23. rigidbody_mass = Symbol('rigidbody_mass')
  24. rigidbody_frame = ReferenceFrame('rigidbody_frame')
  25. body_inertia = inertia(rigidbody_frame, 1, 0, 0)
  26. rigid_body = Body('rigidbody_body', rigidbody_masscenter, rigidbody_mass,
  27. rigidbody_frame, body_inertia)
  28. com = rigid_body.masscenter
  29. frame = rigid_body.frame
  30. rigidbody_masscenter.set_vel(rigidbody_frame, 0)
  31. assert com.vel(frame) == rigidbody_masscenter.vel(frame)
  32. assert com.pos_from(com) == rigidbody_masscenter.pos_from(com)
  33. assert rigid_body.mass == rigidbody_mass
  34. assert rigid_body.inertia == (body_inertia, rigidbody_masscenter)
  35. assert rigid_body.is_rigidbody
  36. assert hasattr(rigid_body, 'masscenter')
  37. assert hasattr(rigid_body, 'mass')
  38. assert hasattr(rigid_body, 'frame')
  39. assert hasattr(rigid_body, 'inertia')
  40. def test_particle_body():
  41. # Body with Particle
  42. particle_masscenter = Point('particle_masscenter')
  43. particle_mass = Symbol('particle_mass')
  44. particle_frame = ReferenceFrame('particle_frame')
  45. particle_body = Body('particle_body', particle_masscenter, particle_mass,
  46. particle_frame)
  47. com = particle_body.masscenter
  48. frame = particle_body.frame
  49. particle_masscenter.set_vel(particle_frame, 0)
  50. assert com.vel(frame) == particle_masscenter.vel(frame)
  51. assert com.pos_from(com) == particle_masscenter.pos_from(com)
  52. assert particle_body.mass == particle_mass
  53. assert not hasattr(particle_body, "_inertia")
  54. assert hasattr(particle_body, 'frame')
  55. assert hasattr(particle_body, 'masscenter')
  56. assert hasattr(particle_body, 'mass')
  57. assert particle_body.inertia == (Dyadic(0), particle_body.masscenter)
  58. assert particle_body.central_inertia == Dyadic(0)
  59. assert not particle_body.is_rigidbody
  60. particle_body.central_inertia = inertia(particle_frame, 1, 1, 1)
  61. assert particle_body.central_inertia == inertia(particle_frame, 1, 1, 1)
  62. assert particle_body.is_rigidbody
  63. particle_body = Body('particle_body', mass=particle_mass)
  64. assert not particle_body.is_rigidbody
  65. point = particle_body.masscenter.locatenew('point', particle_body.x)
  66. point_inertia = particle_mass * inertia(particle_body.frame, 0, 1, 1)
  67. particle_body.inertia = (point_inertia, point)
  68. assert particle_body.inertia == (point_inertia, point)
  69. assert particle_body.central_inertia == Dyadic(0)
  70. assert particle_body.is_rigidbody
  71. def test_particle_body_add_force():
  72. # Body with Particle
  73. particle_masscenter = Point('particle_masscenter')
  74. particle_mass = Symbol('particle_mass')
  75. particle_frame = ReferenceFrame('particle_frame')
  76. particle_body = Body('particle_body', particle_masscenter, particle_mass,
  77. particle_frame)
  78. a = Symbol('a')
  79. force_vector = a * particle_body.frame.x
  80. particle_body.apply_force(force_vector, particle_body.masscenter)
  81. assert len(particle_body.loads) == 1
  82. point = particle_body.masscenter.locatenew(
  83. particle_body._name + '_point0', 0)
  84. point.set_vel(particle_body.frame, 0)
  85. force_point = particle_body.loads[0][0]
  86. frame = particle_body.frame
  87. assert force_point.vel(frame) == point.vel(frame)
  88. assert force_point.pos_from(force_point) == point.pos_from(force_point)
  89. assert particle_body.loads[0][1] == force_vector
  90. def test_body_add_force():
  91. # Body with RigidBody.
  92. rigidbody_masscenter = Point('rigidbody_masscenter')
  93. rigidbody_mass = Symbol('rigidbody_mass')
  94. rigidbody_frame = ReferenceFrame('rigidbody_frame')
  95. body_inertia = inertia(rigidbody_frame, 1, 0, 0)
  96. rigid_body = Body('rigidbody_body', rigidbody_masscenter, rigidbody_mass,
  97. rigidbody_frame, body_inertia)
  98. l = Symbol('l')
  99. Fa = Symbol('Fa')
  100. point = rigid_body.masscenter.locatenew(
  101. 'rigidbody_body_point0',
  102. l * rigid_body.frame.x)
  103. point.set_vel(rigid_body.frame, 0)
  104. force_vector = Fa * rigid_body.frame.z
  105. # apply_force with point
  106. rigid_body.apply_force(force_vector, point)
  107. assert len(rigid_body.loads) == 1
  108. force_point = rigid_body.loads[0][0]
  109. frame = rigid_body.frame
  110. assert force_point.vel(frame) == point.vel(frame)
  111. assert force_point.pos_from(force_point) == point.pos_from(force_point)
  112. assert rigid_body.loads[0][1] == force_vector
  113. # apply_force without point
  114. rigid_body.apply_force(force_vector)
  115. assert len(rigid_body.loads) == 2
  116. assert rigid_body.loads[1][1] == force_vector
  117. # passing something else than point
  118. raises(TypeError, lambda: rigid_body.apply_force(force_vector, 0))
  119. raises(TypeError, lambda: rigid_body.apply_force(0))
  120. def test_body_add_torque():
  121. body = Body('body')
  122. torque_vector = body.frame.x
  123. body.apply_torque(torque_vector)
  124. assert len(body.loads) == 1
  125. assert body.loads[0] == (body.frame, torque_vector)
  126. raises(TypeError, lambda: body.apply_torque(0))
  127. def test_body_masscenter_vel():
  128. A = Body('A')
  129. N = ReferenceFrame('N')
  130. B = Body('B', frame=N)
  131. A.masscenter.set_vel(N, N.z)
  132. assert A.masscenter_vel(B) == N.z
  133. assert A.masscenter_vel(N) == N.z
  134. def test_body_ang_vel():
  135. A = Body('A')
  136. N = ReferenceFrame('N')
  137. B = Body('B', frame=N)
  138. A.frame.set_ang_vel(N, N.y)
  139. assert A.ang_vel_in(B) == N.y
  140. assert B.ang_vel_in(A) == -N.y
  141. assert A.ang_vel_in(N) == N.y
  142. def test_body_dcm():
  143. A = Body('A')
  144. B = Body('B')
  145. A.frame.orient_axis(B.frame, B.frame.z, 10)
  146. assert A.dcm(B) == Matrix([[cos(10), sin(10), 0], [-sin(10), cos(10), 0], [0, 0, 1]])
  147. assert A.dcm(B.frame) == Matrix([[cos(10), sin(10), 0], [-sin(10), cos(10), 0], [0, 0, 1]])
  148. def test_body_axis():
  149. N = ReferenceFrame('N')
  150. B = Body('B', frame=N)
  151. assert B.x == N.x
  152. assert B.y == N.y
  153. assert B.z == N.z
  154. def test_apply_force_multiple_one_point():
  155. a, b = symbols('a b')
  156. P = Point('P')
  157. B = Body('B')
  158. f1 = a*B.x
  159. f2 = b*B.y
  160. B.apply_force(f1, P)
  161. assert B.loads == [(P, f1)]
  162. B.apply_force(f2, P)
  163. assert B.loads == [(P, f1+f2)]
  164. def test_apply_force():
  165. f, g = symbols('f g')
  166. q, x, v1, v2 = dynamicsymbols('q x v1 v2')
  167. P1 = Point('P1')
  168. P2 = Point('P2')
  169. B1 = Body('B1')
  170. B2 = Body('B2')
  171. N = ReferenceFrame('N')
  172. P1.set_vel(B1.frame, v1*B1.x)
  173. P2.set_vel(B2.frame, v2*B2.x)
  174. force = f*q*N.z # time varying force
  175. B1.apply_force(force, P1, B2, P2) #applying equal and opposite force on moving points
  176. assert B1.loads == [(P1, force)]
  177. assert B2.loads == [(P2, -force)]
  178. g1 = B1.mass*g*N.y
  179. g2 = B2.mass*g*N.y
  180. B1.apply_force(g1) #applying gravity on B1 masscenter
  181. B2.apply_force(g2) #applying gravity on B2 masscenter
  182. assert B1.loads == [(P1,force), (B1.masscenter, g1)]
  183. assert B2.loads == [(P2, -force), (B2.masscenter, g2)]
  184. force2 = x*N.x
  185. B1.apply_force(force2, reaction_body=B2) #Applying time varying force on masscenter
  186. assert B1.loads == [(P1, force), (B1.masscenter, force2+g1)]
  187. assert B2.loads == [(P2, -force), (B2.masscenter, -force2+g2)]
  188. def test_apply_torque():
  189. t = symbols('t')
  190. q = dynamicsymbols('q')
  191. B1 = Body('B1')
  192. B2 = Body('B2')
  193. N = ReferenceFrame('N')
  194. torque = t*q*N.x
  195. B1.apply_torque(torque, B2) #Applying equal and opposite torque
  196. assert B1.loads == [(B1.frame, torque)]
  197. assert B2.loads == [(B2.frame, -torque)]
  198. torque2 = t*N.y
  199. B1.apply_torque(torque2)
  200. assert B1.loads == [(B1.frame, torque+torque2)]
  201. def test_clear_load():
  202. a = symbols('a')
  203. P = Point('P')
  204. B = Body('B')
  205. force = a*B.z
  206. B.apply_force(force, P)
  207. assert B.loads == [(P, force)]
  208. B.clear_loads()
  209. assert B.loads == []
  210. def test_remove_load():
  211. P1 = Point('P1')
  212. P2 = Point('P2')
  213. B = Body('B')
  214. f1 = B.x
  215. f2 = B.y
  216. B.apply_force(f1, P1)
  217. B.apply_force(f2, P2)
  218. assert B.loads == [(P1, f1), (P2, f2)]
  219. B.remove_load(P2)
  220. assert B.loads == [(P1, f1)]
  221. B.apply_torque(f1.cross(f2))
  222. assert B.loads == [(P1, f1), (B.frame, f1.cross(f2))]
  223. B.remove_load()
  224. assert B.loads == [(P1, f1)]
  225. def test_apply_loads_on_multi_degree_freedom_holonomic_system():
  226. """Example based on: https://pydy.readthedocs.io/en/latest/examples/multidof-holonomic.html"""
  227. W = Body('W') #Wall
  228. B = Body('B') #Block
  229. P = Body('P') #Pendulum
  230. b = Body('b') #bob
  231. q1, q2 = dynamicsymbols('q1 q2') #generalized coordinates
  232. k, c, g, kT = symbols('k c g kT') #constants
  233. F, T = dynamicsymbols('F T') #Specified forces
  234. #Applying forces
  235. B.apply_force(F*W.x)
  236. W.apply_force(k*q1*W.x, reaction_body=B) #Spring force
  237. W.apply_force(c*q1.diff()*W.x, reaction_body=B) #dampner
  238. P.apply_force(P.mass*g*W.y)
  239. b.apply_force(b.mass*g*W.y)
  240. #Applying torques
  241. P.apply_torque(kT*q2*W.z, reaction_body=b)
  242. P.apply_torque(T*W.z)
  243. assert B.loads == [(B.masscenter, (F - k*q1 - c*q1.diff())*W.x)]
  244. assert P.loads == [(P.masscenter, P.mass*g*W.y), (P.frame, (T + kT*q2)*W.z)]
  245. assert b.loads == [(b.masscenter, b.mass*g*W.y), (b.frame, -kT*q2*W.z)]
  246. assert W.loads == [(W.masscenter, (c*q1.diff() + k*q1)*W.x)]
  247. def test_parallel_axis():
  248. N = ReferenceFrame('N')
  249. m, Ix, Iy, Iz, a, b = symbols('m, I_x, I_y, I_z, a, b')
  250. Io = inertia(N, Ix, Iy, Iz)
  251. # Test RigidBody
  252. o = Point('o')
  253. p = o.locatenew('p', a * N.x + b * N.y)
  254. R = Body('R', masscenter=o, frame=N, mass=m, central_inertia=Io)
  255. Ip = R.parallel_axis(p)
  256. Ip_expected = inertia(N, Ix + m * b**2, Iy + m * a**2,
  257. Iz + m * (a**2 + b**2), ixy=-m * a * b)
  258. assert Ip == Ip_expected
  259. # Reference frame from which the parallel axis is viewed should not matter
  260. A = ReferenceFrame('A')
  261. A.orient_axis(N, N.z, 1)
  262. assert _simplify_matrix(
  263. (R.parallel_axis(p, A) - Ip_expected).to_matrix(A)) == zeros(3, 3)
  264. # Test Particle
  265. o = Point('o')
  266. p = o.locatenew('p', a * N.x + b * N.y)
  267. P = Body('P', masscenter=o, mass=m, frame=N)
  268. Ip = P.parallel_axis(p, N)
  269. Ip_expected = inertia(N, m * b ** 2, m * a ** 2, m * (a ** 2 + b ** 2),
  270. ixy=-m * a * b)
  271. assert not P.is_rigidbody
  272. assert Ip == Ip_expected