123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- from sympy.core.backend import sympify
- from sympy.physics.vector import Point, ReferenceFrame, Dyadic
- from sympy.utilities.exceptions import sympy_deprecation_warning
- __all__ = ['RigidBody']
- class RigidBody:
- """An idealized rigid body.
- Explanation
- ===========
- This is essentially a container which holds the various components which
- describe a rigid body: a name, mass, center of mass, reference frame, and
- inertia.
- All of these need to be supplied on creation, but can be changed
- afterwards.
- Attributes
- ==========
- name : string
- The body's name.
- masscenter : Point
- The point which represents the center of mass of the rigid body.
- frame : ReferenceFrame
- The ReferenceFrame which the rigid body is fixed in.
- mass : Sympifyable
- The body's mass.
- inertia : (Dyadic, Point)
- The body's inertia about a point; stored in a tuple as shown above.
- Examples
- ========
- >>> from sympy import Symbol
- >>> from sympy.physics.mechanics import ReferenceFrame, Point, RigidBody
- >>> from sympy.physics.mechanics import outer
- >>> m = Symbol('m')
- >>> A = ReferenceFrame('A')
- >>> P = Point('P')
- >>> I = outer (A.x, A.x)
- >>> inertia_tuple = (I, P)
- >>> B = RigidBody('B', P, A, m, inertia_tuple)
- >>> # Or you could change them afterwards
- >>> m2 = Symbol('m2')
- >>> B.mass = m2
- """
- def __init__(self, name, masscenter, frame, mass, inertia):
- if not isinstance(name, str):
- raise TypeError('Supply a valid name.')
- self._name = name
- self.masscenter = masscenter
- self.mass = mass
- self.frame = frame
- self.inertia = inertia
- self.potential_energy = 0
- def __str__(self):
- return self._name
- def __repr__(self):
- return self.__str__()
- @property
- def frame(self):
- return self._frame
- @frame.setter
- def frame(self, F):
- if not isinstance(F, ReferenceFrame):
- raise TypeError("RigdBody frame must be a ReferenceFrame object.")
- self._frame = F
- @property
- def masscenter(self):
- return self._masscenter
- @masscenter.setter
- def masscenter(self, p):
- if not isinstance(p, Point):
- raise TypeError("RigidBody center of mass must be a Point object.")
- self._masscenter = p
- @property
- def mass(self):
- return self._mass
- @mass.setter
- def mass(self, m):
- self._mass = sympify(m)
- @property
- def inertia(self):
- return (self._inertia, self._inertia_point)
- @inertia.setter
- def inertia(self, I):
- if not isinstance(I[0], Dyadic):
- raise TypeError("RigidBody inertia must be a Dyadic object.")
- if not isinstance(I[1], Point):
- raise TypeError("RigidBody inertia must be about a Point.")
- self._inertia = I[0]
- self._inertia_point = I[1]
- # have I S/O, want I S/S*
- # I S/O = I S/S* + I S*/O; I S/S* = I S/O - I S*/O
- # I_S/S* = I_S/O - I_S*/O
- from sympy.physics.mechanics.functions import inertia_of_point_mass
- I_Ss_O = inertia_of_point_mass(self.mass,
- self.masscenter.pos_from(I[1]),
- self.frame)
- self._central_inertia = I[0] - I_Ss_O
- @property
- def central_inertia(self):
- """The body's central inertia dyadic."""
- return self._central_inertia
- def linear_momentum(self, frame):
- """ Linear momentum of the rigid body.
- Explanation
- ===========
- The linear momentum L, of a rigid body B, with respect to frame N is
- given by
- L = M * v*
- where M is the mass of the rigid body and v* is the velocity of
- the mass center of B in the frame, N.
- Parameters
- ==========
- frame : ReferenceFrame
- The frame in which linear momentum is desired.
- Examples
- ========
- >>> from sympy.physics.mechanics import Point, ReferenceFrame, outer
- >>> from sympy.physics.mechanics import RigidBody, dynamicsymbols
- >>> from sympy.physics.vector import init_vprinting
- >>> init_vprinting(pretty_print=False)
- >>> M, v = dynamicsymbols('M v')
- >>> N = ReferenceFrame('N')
- >>> P = Point('P')
- >>> P.set_vel(N, v * N.x)
- >>> I = outer (N.x, N.x)
- >>> Inertia_tuple = (I, P)
- >>> B = RigidBody('B', P, N, M, Inertia_tuple)
- >>> B.linear_momentum(N)
- M*v*N.x
- """
- return self.mass * self.masscenter.vel(frame)
- def angular_momentum(self, point, frame):
- """Returns the angular momentum of the rigid body about a point in the
- given frame.
- Explanation
- ===========
- The angular momentum H of a rigid body B about some point O in a frame
- N is given by:
- H = I . w + r x Mv
- where I is the central inertia dyadic of B, w is the angular velocity
- of body B in the frame, N, r is the position vector from point O to the
- mass center of B, and v is the velocity of the mass center in the
- frame, N.
- Parameters
- ==========
- point : Point
- The point about which angular momentum is desired.
- frame : ReferenceFrame
- The frame in which angular momentum is desired.
- Examples
- ========
- >>> from sympy.physics.mechanics import Point, ReferenceFrame, outer
- >>> from sympy.physics.mechanics import RigidBody, dynamicsymbols
- >>> from sympy.physics.vector import init_vprinting
- >>> init_vprinting(pretty_print=False)
- >>> M, v, r, omega = dynamicsymbols('M v r omega')
- >>> N = ReferenceFrame('N')
- >>> b = ReferenceFrame('b')
- >>> b.set_ang_vel(N, omega * b.x)
- >>> P = Point('P')
- >>> P.set_vel(N, 1 * N.x)
- >>> I = outer(b.x, b.x)
- >>> B = RigidBody('B', P, b, M, (I, P))
- >>> B.angular_momentum(P, N)
- omega*b.x
- """
- I = self.central_inertia
- w = self.frame.ang_vel_in(frame)
- m = self.mass
- r = self.masscenter.pos_from(point)
- v = self.masscenter.vel(frame)
- return I.dot(w) + r.cross(m * v)
- def kinetic_energy(self, frame):
- """Kinetic energy of the rigid body.
- Explanation
- ===========
- The kinetic energy, T, of a rigid body, B, is given by
- 'T = 1/2 (I omega^2 + m v^2)'
- where I and m are the central inertia dyadic and mass of rigid body B,
- respectively, omega is the body's angular velocity and v is the
- velocity of the body's mass center in the supplied ReferenceFrame.
- Parameters
- ==========
- frame : ReferenceFrame
- The RigidBody's angular velocity and the velocity of it's mass
- center are typically defined with respect to an inertial frame but
- any relevant frame in which the velocities are known can be supplied.
- Examples
- ========
- >>> from sympy.physics.mechanics import Point, ReferenceFrame, outer
- >>> from sympy.physics.mechanics import RigidBody
- >>> from sympy import symbols
- >>> M, v, r, omega = symbols('M v r omega')
- >>> N = ReferenceFrame('N')
- >>> b = ReferenceFrame('b')
- >>> b.set_ang_vel(N, omega * b.x)
- >>> P = Point('P')
- >>> P.set_vel(N, v * N.x)
- >>> I = outer (b.x, b.x)
- >>> inertia_tuple = (I, P)
- >>> B = RigidBody('B', P, b, M, inertia_tuple)
- >>> B.kinetic_energy(N)
- M*v**2/2 + omega**2/2
- """
- rotational_KE = (self.frame.ang_vel_in(frame) & (self.central_inertia &
- self.frame.ang_vel_in(frame)) / sympify(2))
- translational_KE = (self.mass * (self.masscenter.vel(frame) &
- self.masscenter.vel(frame)) / sympify(2))
- return rotational_KE + translational_KE
- @property
- def potential_energy(self):
- """The potential energy of the RigidBody.
- Examples
- ========
- >>> from sympy.physics.mechanics import RigidBody, Point, outer, ReferenceFrame
- >>> from sympy import symbols
- >>> M, g, h = symbols('M g h')
- >>> b = ReferenceFrame('b')
- >>> P = Point('P')
- >>> I = outer (b.x, b.x)
- >>> Inertia_tuple = (I, P)
- >>> B = RigidBody('B', P, b, M, Inertia_tuple)
- >>> B.potential_energy = M * g * h
- >>> B.potential_energy
- M*g*h
- """
- return self._pe
- @potential_energy.setter
- def potential_energy(self, scalar):
- """Used to set the potential energy of this RigidBody.
- Parameters
- ==========
- scalar: Sympifyable
- The potential energy (a scalar) of the RigidBody.
- Examples
- ========
- >>> from sympy.physics.mechanics import Point, outer
- >>> from sympy.physics.mechanics import RigidBody, ReferenceFrame
- >>> from sympy import symbols
- >>> b = ReferenceFrame('b')
- >>> M, g, h = symbols('M g h')
- >>> P = Point('P')
- >>> I = outer (b.x, b.x)
- >>> Inertia_tuple = (I, P)
- >>> B = RigidBody('B', P, b, M, Inertia_tuple)
- >>> B.potential_energy = M * g * h
- """
- self._pe = sympify(scalar)
- def set_potential_energy(self, scalar):
- sympy_deprecation_warning(
- """
- The sympy.physics.mechanics.RigidBody.set_potential_energy()
- method is deprecated. Instead use
- B.potential_energy = scalar
- """,
- deprecated_since_version="1.5",
- active_deprecations_target="deprecated-set-potential-energy",
- )
- self.potential_energy = scalar
- # XXX: To be consistent with the parallel_axis method in Particle this
- # should have a frame argument...
- def parallel_axis(self, point):
- """Returns the inertia dyadic of the body with respect to another
- point.
- Parameters
- ==========
- point : sympy.physics.vector.Point
- The point to express the inertia dyadic about.
- Returns
- =======
- inertia : sympy.physics.vector.Dyadic
- The inertia dyadic of the rigid body expressed about the provided
- point.
- """
- # circular import issue
- from sympy.physics.mechanics.functions import inertia
- a, b, c = self.masscenter.pos_from(point).to_matrix(self.frame)
- I = self.mass * inertia(self.frame, b**2 + c**2, c**2 + a**2, a**2 +
- b**2, -a * b, -b * c, -a * c)
- return self.central_inertia + I
|