jointsmethod.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. from sympy.physics.mechanics import (Body, Lagrangian, KanesMethod, LagrangesMethod,
  2. RigidBody, Particle)
  3. from sympy.physics.mechanics.body_base import BodyBase
  4. from sympy.physics.mechanics.method import _Methods
  5. from sympy import Matrix
  6. from sympy.utilities.exceptions import sympy_deprecation_warning
  7. __all__ = ['JointsMethod']
  8. class JointsMethod(_Methods):
  9. """Method for formulating the equations of motion using a set of interconnected bodies with joints.
  10. .. deprecated:: 1.13
  11. The JointsMethod class is deprecated. Its functionality has been
  12. replaced by the new :class:`~.System` class.
  13. Parameters
  14. ==========
  15. newtonion : Body or ReferenceFrame
  16. The newtonion(inertial) frame.
  17. *joints : Joint
  18. The joints in the system
  19. Attributes
  20. ==========
  21. q, u : iterable
  22. Iterable of the generalized coordinates and speeds
  23. bodies : iterable
  24. Iterable of Body objects in the system.
  25. loads : iterable
  26. Iterable of (Point, vector) or (ReferenceFrame, vector) tuples
  27. describing the forces on the system.
  28. mass_matrix : Matrix, shape(n, n)
  29. The system's mass matrix
  30. forcing : Matrix, shape(n, 1)
  31. The system's forcing vector
  32. mass_matrix_full : Matrix, shape(2*n, 2*n)
  33. The "mass matrix" for the u's and q's
  34. forcing_full : Matrix, shape(2*n, 1)
  35. The "forcing vector" for the u's and q's
  36. method : KanesMethod or Lagrange's method
  37. Method's object.
  38. kdes : iterable
  39. Iterable of kde in they system.
  40. Examples
  41. ========
  42. As Body and JointsMethod have been deprecated, the following examples are
  43. for illustrative purposes only. The functionality of Body is fully captured
  44. by :class:`~.RigidBody` and :class:`~.Particle` and the functionality of
  45. JointsMethod is fully captured by :class:`~.System`. To ignore the
  46. deprecation warning we can use the ignore_warnings context manager.
  47. >>> from sympy.utilities.exceptions import ignore_warnings
  48. This is a simple example for a one degree of freedom translational
  49. spring-mass-damper.
  50. >>> from sympy import symbols
  51. >>> from sympy.physics.mechanics import Body, JointsMethod, PrismaticJoint
  52. >>> from sympy.physics.vector import dynamicsymbols
  53. >>> c, k = symbols('c k')
  54. >>> x, v = dynamicsymbols('x v')
  55. >>> with ignore_warnings(DeprecationWarning):
  56. ... wall = Body('W')
  57. ... body = Body('B')
  58. >>> J = PrismaticJoint('J', wall, body, coordinates=x, speeds=v)
  59. >>> wall.apply_force(c*v*wall.x, reaction_body=body)
  60. >>> wall.apply_force(k*x*wall.x, reaction_body=body)
  61. >>> with ignore_warnings(DeprecationWarning):
  62. ... method = JointsMethod(wall, J)
  63. >>> method.form_eoms()
  64. Matrix([[-B_mass*Derivative(v(t), t) - c*v(t) - k*x(t)]])
  65. >>> M = method.mass_matrix_full
  66. >>> F = method.forcing_full
  67. >>> rhs = M.LUsolve(F)
  68. >>> rhs
  69. Matrix([
  70. [ v(t)],
  71. [(-c*v(t) - k*x(t))/B_mass]])
  72. Notes
  73. =====
  74. ``JointsMethod`` currently only works with systems that do not have any
  75. configuration or motion constraints.
  76. """
  77. def __init__(self, newtonion, *joints):
  78. sympy_deprecation_warning(
  79. """
  80. The JointsMethod class is deprecated.
  81. Its functionality has been replaced by the new System class.
  82. """,
  83. deprecated_since_version="1.13",
  84. active_deprecations_target="deprecated-mechanics-jointsmethod"
  85. )
  86. if isinstance(newtonion, BodyBase):
  87. self.frame = newtonion.frame
  88. else:
  89. self.frame = newtonion
  90. self._joints = joints
  91. self._bodies = self._generate_bodylist()
  92. self._loads = self._generate_loadlist()
  93. self._q = self._generate_q()
  94. self._u = self._generate_u()
  95. self._kdes = self._generate_kdes()
  96. self._method = None
  97. @property
  98. def bodies(self):
  99. """List of bodies in they system."""
  100. return self._bodies
  101. @property
  102. def loads(self):
  103. """List of loads on the system."""
  104. return self._loads
  105. @property
  106. def q(self):
  107. """List of the generalized coordinates."""
  108. return self._q
  109. @property
  110. def u(self):
  111. """List of the generalized speeds."""
  112. return self._u
  113. @property
  114. def kdes(self):
  115. """List of the generalized coordinates."""
  116. return self._kdes
  117. @property
  118. def forcing_full(self):
  119. """The "forcing vector" for the u's and q's."""
  120. return self.method.forcing_full
  121. @property
  122. def mass_matrix_full(self):
  123. """The "mass matrix" for the u's and q's."""
  124. return self.method.mass_matrix_full
  125. @property
  126. def mass_matrix(self):
  127. """The system's mass matrix."""
  128. return self.method.mass_matrix
  129. @property
  130. def forcing(self):
  131. """The system's forcing vector."""
  132. return self.method.forcing
  133. @property
  134. def method(self):
  135. """Object of method used to form equations of systems."""
  136. return self._method
  137. def _generate_bodylist(self):
  138. bodies = []
  139. for joint in self._joints:
  140. if joint.child not in bodies:
  141. bodies.append(joint.child)
  142. if joint.parent not in bodies:
  143. bodies.append(joint.parent)
  144. return bodies
  145. def _generate_loadlist(self):
  146. load_list = []
  147. for body in self.bodies:
  148. if isinstance(body, Body):
  149. load_list.extend(body.loads)
  150. return load_list
  151. def _generate_q(self):
  152. q_ind = []
  153. for joint in self._joints:
  154. for coordinate in joint.coordinates:
  155. if coordinate in q_ind:
  156. raise ValueError('Coordinates of joints should be unique.')
  157. q_ind.append(coordinate)
  158. return Matrix(q_ind)
  159. def _generate_u(self):
  160. u_ind = []
  161. for joint in self._joints:
  162. for speed in joint.speeds:
  163. if speed in u_ind:
  164. raise ValueError('Speeds of joints should be unique.')
  165. u_ind.append(speed)
  166. return Matrix(u_ind)
  167. def _generate_kdes(self):
  168. kd_ind = Matrix(1, 0, []).T
  169. for joint in self._joints:
  170. kd_ind = kd_ind.col_join(joint.kdes)
  171. return kd_ind
  172. def _convert_bodies(self):
  173. # Convert `Body` to `Particle` and `RigidBody`
  174. bodylist = []
  175. for body in self.bodies:
  176. if not isinstance(body, Body):
  177. bodylist.append(body)
  178. continue
  179. if body.is_rigidbody:
  180. rb = RigidBody(body.name, body.masscenter, body.frame, body.mass,
  181. (body.central_inertia, body.masscenter))
  182. rb.potential_energy = body.potential_energy
  183. bodylist.append(rb)
  184. else:
  185. part = Particle(body.name, body.masscenter, body.mass)
  186. part.potential_energy = body.potential_energy
  187. bodylist.append(part)
  188. return bodylist
  189. def form_eoms(self, method=KanesMethod):
  190. """Method to form system's equation of motions.
  191. Parameters
  192. ==========
  193. method : Class
  194. Class name of method.
  195. Returns
  196. ========
  197. Matrix
  198. Vector of equations of motions.
  199. Examples
  200. ========
  201. As Body and JointsMethod have been deprecated, the following examples
  202. are for illustrative purposes only. The functionality of Body is fully
  203. captured by :class:`~.RigidBody` and :class:`~.Particle` and the
  204. functionality of JointsMethod is fully captured by :class:`~.System`. To
  205. ignore the deprecation warning we can use the ignore_warnings context
  206. manager.
  207. >>> from sympy.utilities.exceptions import ignore_warnings
  208. This is a simple example for a one degree of freedom translational
  209. spring-mass-damper.
  210. >>> from sympy import S, symbols
  211. >>> from sympy.physics.mechanics import LagrangesMethod, dynamicsymbols, Body
  212. >>> from sympy.physics.mechanics import PrismaticJoint, JointsMethod
  213. >>> q = dynamicsymbols('q')
  214. >>> qd = dynamicsymbols('q', 1)
  215. >>> m, k, b = symbols('m k b')
  216. >>> with ignore_warnings(DeprecationWarning):
  217. ... wall = Body('W')
  218. ... part = Body('P', mass=m)
  219. >>> part.potential_energy = k * q**2 / S(2)
  220. >>> J = PrismaticJoint('J', wall, part, coordinates=q, speeds=qd)
  221. >>> wall.apply_force(b * qd * wall.x, reaction_body=part)
  222. >>> with ignore_warnings(DeprecationWarning):
  223. ... method = JointsMethod(wall, J)
  224. >>> method.form_eoms(LagrangesMethod)
  225. Matrix([[b*Derivative(q(t), t) + k*q(t) + m*Derivative(q(t), (t, 2))]])
  226. We can also solve for the states using the 'rhs' method.
  227. >>> method.rhs()
  228. Matrix([
  229. [ Derivative(q(t), t)],
  230. [(-b*Derivative(q(t), t) - k*q(t))/m]])
  231. """
  232. bodylist = self._convert_bodies()
  233. if issubclass(method, LagrangesMethod): #LagrangesMethod or similar
  234. L = Lagrangian(self.frame, *bodylist)
  235. self._method = method(L, self.q, self.loads, bodylist, self.frame)
  236. else: #KanesMethod or similar
  237. self._method = method(self.frame, q_ind=self.q, u_ind=self.u, kd_eqs=self.kdes,
  238. forcelist=self.loads, bodies=bodylist)
  239. soln = self.method._form_eoms()
  240. return soln
  241. def rhs(self, inv_method=None):
  242. """Returns equations that can be solved numerically.
  243. Parameters
  244. ==========
  245. inv_method : str
  246. The specific sympy inverse matrix calculation method to use. For a
  247. list of valid methods, see
  248. :meth:`~sympy.matrices.matrixbase.MatrixBase.inv`
  249. Returns
  250. ========
  251. Matrix
  252. Numerically solvable equations.
  253. See Also
  254. ========
  255. sympy.physics.mechanics.kane.KanesMethod.rhs:
  256. KanesMethod's rhs function.
  257. sympy.physics.mechanics.lagrange.LagrangesMethod.rhs:
  258. LagrangesMethod's rhs function.
  259. """
  260. return self.method.rhs(inv_method=inv_method)