switching to high quality piper tts and added label translations
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
from abc import ABC
|
||||
from collections import namedtuple
|
||||
from sympy.physics.mechanics.body_base import BodyBase
|
||||
from sympy.physics.vector import Vector, ReferenceFrame, Point
|
||||
|
||||
__all__ = ['LoadBase', 'Force', 'Torque']
|
||||
|
||||
|
||||
class LoadBase(ABC, namedtuple('LoadBase', ['location', 'vector'])):
|
||||
"""Abstract base class for the various loading types."""
|
||||
|
||||
def __add__(self, other):
|
||||
raise TypeError(f"unsupported operand type(s) for +: "
|
||||
f"'{self.__class__.__name__}' and "
|
||||
f"'{other.__class__.__name__}'")
|
||||
|
||||
def __mul__(self, other):
|
||||
raise TypeError(f"unsupported operand type(s) for *: "
|
||||
f"'{self.__class__.__name__}' and "
|
||||
f"'{other.__class__.__name__}'")
|
||||
|
||||
__radd__ = __add__
|
||||
__rmul__ = __mul__
|
||||
|
||||
|
||||
class Force(LoadBase):
|
||||
"""Force acting upon a point.
|
||||
|
||||
Explanation
|
||||
===========
|
||||
|
||||
A force is a vector that is bound to a line of action. This class stores
|
||||
both a point, which lies on the line of action, and the vector. A tuple can
|
||||
also be used, with the location as the first entry and the vector as second
|
||||
entry.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
A force of magnitude 2 along N.x acting on a point Po can be created as
|
||||
follows:
|
||||
|
||||
>>> from sympy.physics.mechanics import Point, ReferenceFrame, Force
|
||||
>>> N = ReferenceFrame('N')
|
||||
>>> Po = Point('Po')
|
||||
>>> Force(Po, 2 * N.x)
|
||||
(Po, 2*N.x)
|
||||
|
||||
If a body is supplied, then the center of mass of that body is used.
|
||||
|
||||
>>> from sympy.physics.mechanics import Particle
|
||||
>>> P = Particle('P', point=Po)
|
||||
>>> Force(P, 2 * N.x)
|
||||
(Po, 2*N.x)
|
||||
|
||||
"""
|
||||
|
||||
def __new__(cls, point, force):
|
||||
if isinstance(point, BodyBase):
|
||||
point = point.masscenter
|
||||
if not isinstance(point, Point):
|
||||
raise TypeError('Force location should be a Point.')
|
||||
if not isinstance(force, Vector):
|
||||
raise TypeError('Force vector should be a Vector.')
|
||||
return super().__new__(cls, point, force)
|
||||
|
||||
def __repr__(self):
|
||||
return (f'{self.__class__.__name__}(point={self.point}, '
|
||||
f'force={self.force})')
|
||||
|
||||
@property
|
||||
def point(self):
|
||||
return self.location
|
||||
|
||||
@property
|
||||
def force(self):
|
||||
return self.vector
|
||||
|
||||
|
||||
class Torque(LoadBase):
|
||||
"""Torque acting upon a frame.
|
||||
|
||||
Explanation
|
||||
===========
|
||||
|
||||
A torque is a free vector that is acting on a reference frame, which is
|
||||
associated with a rigid body. This class stores both the frame and the
|
||||
vector. A tuple can also be used, with the location as the first item and
|
||||
the vector as second item.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
A torque of magnitude 2 about N.x acting on a frame N can be created as
|
||||
follows:
|
||||
|
||||
>>> from sympy.physics.mechanics import ReferenceFrame, Torque
|
||||
>>> N = ReferenceFrame('N')
|
||||
>>> Torque(N, 2 * N.x)
|
||||
(N, 2*N.x)
|
||||
|
||||
If a body is supplied, then the frame fixed to that body is used.
|
||||
|
||||
>>> from sympy.physics.mechanics import RigidBody
|
||||
>>> rb = RigidBody('rb', frame=N)
|
||||
>>> Torque(rb, 2 * N.x)
|
||||
(N, 2*N.x)
|
||||
|
||||
"""
|
||||
|
||||
def __new__(cls, frame, torque):
|
||||
if isinstance(frame, BodyBase):
|
||||
frame = frame.frame
|
||||
if not isinstance(frame, ReferenceFrame):
|
||||
raise TypeError('Torque location should be a ReferenceFrame.')
|
||||
if not isinstance(torque, Vector):
|
||||
raise TypeError('Torque vector should be a Vector.')
|
||||
return super().__new__(cls, frame, torque)
|
||||
|
||||
def __repr__(self):
|
||||
return (f'{self.__class__.__name__}(frame={self.frame}, '
|
||||
f'torque={self.torque})')
|
||||
|
||||
@property
|
||||
def frame(self):
|
||||
return self.location
|
||||
|
||||
@property
|
||||
def torque(self):
|
||||
return self.vector
|
||||
|
||||
|
||||
def gravity(acceleration, *bodies):
|
||||
"""
|
||||
Returns a list of gravity forces given the acceleration
|
||||
due to gravity and any number of particles or rigidbodies.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
>>> from sympy.physics.mechanics import ReferenceFrame, Particle, RigidBody
|
||||
>>> from sympy.physics.mechanics.loads import gravity
|
||||
>>> from sympy import symbols
|
||||
>>> N = ReferenceFrame('N')
|
||||
>>> g = symbols('g')
|
||||
>>> P = Particle('P')
|
||||
>>> B = RigidBody('B')
|
||||
>>> gravity(g*N.y, P, B)
|
||||
[(P_masscenter, P_mass*g*N.y),
|
||||
(B_masscenter, B_mass*g*N.y)]
|
||||
|
||||
"""
|
||||
|
||||
gravity_force = []
|
||||
for body in bodies:
|
||||
if not isinstance(body, BodyBase):
|
||||
raise TypeError(f'{type(body)} is not a body type')
|
||||
gravity_force.append(Force(body.masscenter, body.mass * acceleration))
|
||||
return gravity_force
|
||||
|
||||
|
||||
def _parse_load(load):
|
||||
"""Helper function to parse loads and convert tuples to load objects."""
|
||||
if isinstance(load, LoadBase):
|
||||
return load
|
||||
elif isinstance(load, tuple):
|
||||
if len(load) != 2:
|
||||
raise ValueError(f'Load {load} should have a length of 2.')
|
||||
if isinstance(load[0], Point):
|
||||
return Force(load[0], load[1])
|
||||
elif isinstance(load[0], ReferenceFrame):
|
||||
return Torque(load[0], load[1])
|
||||
else:
|
||||
raise ValueError(f'Load not recognized. The load location {load[0]}'
|
||||
f' should either be a Point or a ReferenceFrame.')
|
||||
raise TypeError(f'Load type {type(load)} not recognized as a load. It '
|
||||
f'should be a Force, Torque or tuple.')
|
||||
Reference in New Issue
Block a user