| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- from sympy import Symbol, S
- from sympy.physics.vector import ReferenceFrame, Dyadic, Point, dot
- from sympy.physics.mechanics.body_base import BodyBase
- from sympy.physics.mechanics.inertia import inertia_of_point_mass, Inertia
- from sympy.utilities.exceptions import sympy_deprecation_warning
- __all__ = ['RigidBody']
- class RigidBody(BodyBase):
- """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.
- potential_energy : Sympifyable
- The potential energy of the RigidBody.
- 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=None, frame=None, mass=None,
- inertia=None):
- super().__init__(name, masscenter, mass)
- if frame is None:
- frame = ReferenceFrame(f'{name}_frame')
- self.frame = frame
- if inertia is None:
- ixx = Symbol(f'{name}_ixx')
- iyy = Symbol(f'{name}_iyy')
- izz = Symbol(f'{name}_izz')
- izx = Symbol(f'{name}_izx')
- ixy = Symbol(f'{name}_ixy')
- iyz = Symbol(f'{name}_iyz')
- inertia = Inertia.from_inertia_scalars(self.masscenter, self.frame,
- ixx, iyy, izz, ixy, iyz, izx)
- self.inertia = inertia
- def __repr__(self):
- return (f'{self.__class__.__name__}({repr(self.name)}, masscenter='
- f'{repr(self.masscenter)}, frame={repr(self.frame)}, mass='
- f'{repr(self.mass)}, inertia={repr(self.inertia)})')
- @property
- def frame(self):
- """The ReferenceFrame fixed to the body."""
- return self._frame
- @frame.setter
- def frame(self, F):
- if not isinstance(F, ReferenceFrame):
- raise TypeError("RigidBody frame must be a ReferenceFrame object.")
- self._frame = F
- @property
- def x(self):
- """The basis Vector for the body, in the x direction. """
- return self.frame.x
- @property
- def y(self):
- """The basis Vector for the body, in the y direction. """
- return self.frame.y
- @property
- def z(self):
- """The basis Vector for the body, in the z direction. """
- return self.frame.z
- @property
- def inertia(self):
- """The body's inertia about a point; stored as (Dyadic, Point)."""
- return self._inertia
- @inertia.setter
- def inertia(self, I):
- # check if I is of the form (Dyadic, Point)
- if len(I) != 2 or not isinstance(I[0], Dyadic) or not isinstance(I[1], Point):
- raise TypeError("RigidBody inertia must be a tuple of the form (Dyadic, Point).")
- self._inertia = Inertia(I[0], 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
- 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
- @central_inertia.setter
- def central_inertia(self, I):
- if not isinstance(I, Dyadic):
- raise TypeError("RigidBody inertia must be a Dyadic object.")
- self.inertia = Inertia(I, self.masscenter)
- 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 = dot(I, w) + cross(r, m * v)``
- where I and m are the central inertia dyadic and mass of rigid body 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 * (dot(dot(I, w), w) + dot(m * v, v))``
- where I and m are the central inertia dyadic and mass of rigid body B
- respectively, w 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 = S.Half * dot(
- self.frame.ang_vel_in(frame),
- dot(self.central_inertia, self.frame.ang_vel_in(frame)))
- translational_KE = S.Half * self.mass * dot(self.masscenter.vel(frame),
- self.masscenter.vel(frame))
- return rotational_KE + translational_KE
- 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
- def parallel_axis(self, point, frame=None):
- """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.
- frame : sympy.physics.vector.ReferenceFrame
- The reference frame used to construct the dyadic.
- Returns
- =======
- inertia : sympy.physics.vector.Dyadic
- The inertia dyadic of the rigid body expressed about the provided
- point.
- """
- if frame is None:
- frame = self.frame
- return self.central_inertia + inertia_of_point_mass(
- self.mass, self.masscenter.pos_from(point), frame)
|