rigidbody.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. from sympy import Symbol, S
  2. from sympy.physics.vector import ReferenceFrame, Dyadic, Point, dot
  3. from sympy.physics.mechanics.body_base import BodyBase
  4. from sympy.physics.mechanics.inertia import inertia_of_point_mass, Inertia
  5. from sympy.utilities.exceptions import sympy_deprecation_warning
  6. __all__ = ['RigidBody']
  7. class RigidBody(BodyBase):
  8. """An idealized rigid body.
  9. Explanation
  10. ===========
  11. This is essentially a container which holds the various components which
  12. describe a rigid body: a name, mass, center of mass, reference frame, and
  13. inertia.
  14. All of these need to be supplied on creation, but can be changed
  15. afterwards.
  16. Attributes
  17. ==========
  18. name : string
  19. The body's name.
  20. masscenter : Point
  21. The point which represents the center of mass of the rigid body.
  22. frame : ReferenceFrame
  23. The ReferenceFrame which the rigid body is fixed in.
  24. mass : Sympifyable
  25. The body's mass.
  26. inertia : (Dyadic, Point)
  27. The body's inertia about a point; stored in a tuple as shown above.
  28. potential_energy : Sympifyable
  29. The potential energy of the RigidBody.
  30. Examples
  31. ========
  32. >>> from sympy import Symbol
  33. >>> from sympy.physics.mechanics import ReferenceFrame, Point, RigidBody
  34. >>> from sympy.physics.mechanics import outer
  35. >>> m = Symbol('m')
  36. >>> A = ReferenceFrame('A')
  37. >>> P = Point('P')
  38. >>> I = outer (A.x, A.x)
  39. >>> inertia_tuple = (I, P)
  40. >>> B = RigidBody('B', P, A, m, inertia_tuple)
  41. >>> # Or you could change them afterwards
  42. >>> m2 = Symbol('m2')
  43. >>> B.mass = m2
  44. """
  45. def __init__(self, name, masscenter=None, frame=None, mass=None,
  46. inertia=None):
  47. super().__init__(name, masscenter, mass)
  48. if frame is None:
  49. frame = ReferenceFrame(f'{name}_frame')
  50. self.frame = frame
  51. if inertia is None:
  52. ixx = Symbol(f'{name}_ixx')
  53. iyy = Symbol(f'{name}_iyy')
  54. izz = Symbol(f'{name}_izz')
  55. izx = Symbol(f'{name}_izx')
  56. ixy = Symbol(f'{name}_ixy')
  57. iyz = Symbol(f'{name}_iyz')
  58. inertia = Inertia.from_inertia_scalars(self.masscenter, self.frame,
  59. ixx, iyy, izz, ixy, iyz, izx)
  60. self.inertia = inertia
  61. def __repr__(self):
  62. return (f'{self.__class__.__name__}({repr(self.name)}, masscenter='
  63. f'{repr(self.masscenter)}, frame={repr(self.frame)}, mass='
  64. f'{repr(self.mass)}, inertia={repr(self.inertia)})')
  65. @property
  66. def frame(self):
  67. """The ReferenceFrame fixed to the body."""
  68. return self._frame
  69. @frame.setter
  70. def frame(self, F):
  71. if not isinstance(F, ReferenceFrame):
  72. raise TypeError("RigidBody frame must be a ReferenceFrame object.")
  73. self._frame = F
  74. @property
  75. def x(self):
  76. """The basis Vector for the body, in the x direction. """
  77. return self.frame.x
  78. @property
  79. def y(self):
  80. """The basis Vector for the body, in the y direction. """
  81. return self.frame.y
  82. @property
  83. def z(self):
  84. """The basis Vector for the body, in the z direction. """
  85. return self.frame.z
  86. @property
  87. def inertia(self):
  88. """The body's inertia about a point; stored as (Dyadic, Point)."""
  89. return self._inertia
  90. @inertia.setter
  91. def inertia(self, I):
  92. # check if I is of the form (Dyadic, Point)
  93. if len(I) != 2 or not isinstance(I[0], Dyadic) or not isinstance(I[1], Point):
  94. raise TypeError("RigidBody inertia must be a tuple of the form (Dyadic, Point).")
  95. self._inertia = Inertia(I[0], I[1])
  96. # have I S/O, want I S/S*
  97. # I S/O = I S/S* + I S*/O; I S/S* = I S/O - I S*/O
  98. # I_S/S* = I_S/O - I_S*/O
  99. I_Ss_O = inertia_of_point_mass(self.mass,
  100. self.masscenter.pos_from(I[1]),
  101. self.frame)
  102. self._central_inertia = I[0] - I_Ss_O
  103. @property
  104. def central_inertia(self):
  105. """The body's central inertia dyadic."""
  106. return self._central_inertia
  107. @central_inertia.setter
  108. def central_inertia(self, I):
  109. if not isinstance(I, Dyadic):
  110. raise TypeError("RigidBody inertia must be a Dyadic object.")
  111. self.inertia = Inertia(I, self.masscenter)
  112. def linear_momentum(self, frame):
  113. """ Linear momentum of the rigid body.
  114. Explanation
  115. ===========
  116. The linear momentum L, of a rigid body B, with respect to frame N is
  117. given by:
  118. ``L = m * v``
  119. where m is the mass of the rigid body, and v is the velocity of the mass
  120. center of B in the frame N.
  121. Parameters
  122. ==========
  123. frame : ReferenceFrame
  124. The frame in which linear momentum is desired.
  125. Examples
  126. ========
  127. >>> from sympy.physics.mechanics import Point, ReferenceFrame, outer
  128. >>> from sympy.physics.mechanics import RigidBody, dynamicsymbols
  129. >>> from sympy.physics.vector import init_vprinting
  130. >>> init_vprinting(pretty_print=False)
  131. >>> m, v = dynamicsymbols('m v')
  132. >>> N = ReferenceFrame('N')
  133. >>> P = Point('P')
  134. >>> P.set_vel(N, v * N.x)
  135. >>> I = outer (N.x, N.x)
  136. >>> Inertia_tuple = (I, P)
  137. >>> B = RigidBody('B', P, N, m, Inertia_tuple)
  138. >>> B.linear_momentum(N)
  139. m*v*N.x
  140. """
  141. return self.mass * self.masscenter.vel(frame)
  142. def angular_momentum(self, point, frame):
  143. """Returns the angular momentum of the rigid body about a point in the
  144. given frame.
  145. Explanation
  146. ===========
  147. The angular momentum H of a rigid body B about some point O in a frame N
  148. is given by:
  149. ``H = dot(I, w) + cross(r, m * v)``
  150. where I and m are the central inertia dyadic and mass of rigid body B, w
  151. is the angular velocity of body B in the frame N, r is the position
  152. vector from point O to the mass center of B, and v is the velocity of
  153. the mass center in the frame N.
  154. Parameters
  155. ==========
  156. point : Point
  157. The point about which angular momentum is desired.
  158. frame : ReferenceFrame
  159. The frame in which angular momentum is desired.
  160. Examples
  161. ========
  162. >>> from sympy.physics.mechanics import Point, ReferenceFrame, outer
  163. >>> from sympy.physics.mechanics import RigidBody, dynamicsymbols
  164. >>> from sympy.physics.vector import init_vprinting
  165. >>> init_vprinting(pretty_print=False)
  166. >>> m, v, r, omega = dynamicsymbols('m v r omega')
  167. >>> N = ReferenceFrame('N')
  168. >>> b = ReferenceFrame('b')
  169. >>> b.set_ang_vel(N, omega * b.x)
  170. >>> P = Point('P')
  171. >>> P.set_vel(N, 1 * N.x)
  172. >>> I = outer(b.x, b.x)
  173. >>> B = RigidBody('B', P, b, m, (I, P))
  174. >>> B.angular_momentum(P, N)
  175. omega*b.x
  176. """
  177. I = self.central_inertia
  178. w = self.frame.ang_vel_in(frame)
  179. m = self.mass
  180. r = self.masscenter.pos_from(point)
  181. v = self.masscenter.vel(frame)
  182. return I.dot(w) + r.cross(m * v)
  183. def kinetic_energy(self, frame):
  184. """Kinetic energy of the rigid body.
  185. Explanation
  186. ===========
  187. The kinetic energy, T, of a rigid body, B, is given by:
  188. ``T = 1/2 * (dot(dot(I, w), w) + dot(m * v, v))``
  189. where I and m are the central inertia dyadic and mass of rigid body B
  190. respectively, w is the body's angular velocity, and v is the velocity of
  191. the body's mass center in the supplied ReferenceFrame.
  192. Parameters
  193. ==========
  194. frame : ReferenceFrame
  195. The RigidBody's angular velocity and the velocity of it's mass
  196. center are typically defined with respect to an inertial frame but
  197. any relevant frame in which the velocities are known can be
  198. supplied.
  199. Examples
  200. ========
  201. >>> from sympy.physics.mechanics import Point, ReferenceFrame, outer
  202. >>> from sympy.physics.mechanics import RigidBody
  203. >>> from sympy import symbols
  204. >>> m, v, r, omega = symbols('m v r omega')
  205. >>> N = ReferenceFrame('N')
  206. >>> b = ReferenceFrame('b')
  207. >>> b.set_ang_vel(N, omega * b.x)
  208. >>> P = Point('P')
  209. >>> P.set_vel(N, v * N.x)
  210. >>> I = outer (b.x, b.x)
  211. >>> inertia_tuple = (I, P)
  212. >>> B = RigidBody('B', P, b, m, inertia_tuple)
  213. >>> B.kinetic_energy(N)
  214. m*v**2/2 + omega**2/2
  215. """
  216. rotational_KE = S.Half * dot(
  217. self.frame.ang_vel_in(frame),
  218. dot(self.central_inertia, self.frame.ang_vel_in(frame)))
  219. translational_KE = S.Half * self.mass * dot(self.masscenter.vel(frame),
  220. self.masscenter.vel(frame))
  221. return rotational_KE + translational_KE
  222. def set_potential_energy(self, scalar):
  223. sympy_deprecation_warning(
  224. """
  225. The sympy.physics.mechanics.RigidBody.set_potential_energy()
  226. method is deprecated. Instead use
  227. B.potential_energy = scalar
  228. """,
  229. deprecated_since_version="1.5",
  230. active_deprecations_target="deprecated-set-potential-energy",
  231. )
  232. self.potential_energy = scalar
  233. def parallel_axis(self, point, frame=None):
  234. """Returns the inertia dyadic of the body with respect to another point.
  235. Parameters
  236. ==========
  237. point : sympy.physics.vector.Point
  238. The point to express the inertia dyadic about.
  239. frame : sympy.physics.vector.ReferenceFrame
  240. The reference frame used to construct the dyadic.
  241. Returns
  242. =======
  243. inertia : sympy.physics.vector.Dyadic
  244. The inertia dyadic of the rigid body expressed about the provided
  245. point.
  246. """
  247. if frame is None:
  248. frame = self.frame
  249. return self.central_inertia + inertia_of_point_mass(
  250. self.mass, self.masscenter.pos_from(point), frame)