Closed tjstienstra closed 1 year ago
class MasslessBody(RigidBody):
"""Massless rigid body
Explanation
-----------
The main purpose of this class is to allow the usage of just a frame and point
when defining a joint. This class should only be used as long as sympy's joints
framework does not yet support passing only a frame and point to the joint
constructor.
"""
def __init__(self, name: str, masscenter: Point, frame: ReferenceFrame) -> None:
"""Initialize a massless body."""
super().__init__(
name, masscenter, frame, S.Zero, Inertia(masscenter, Dyadic(0)))
@RigidBody.mass.setter
def mass(self, mass: Expr) -> None:
"""Body's mass."""
if mass != 0:
raise AttributeError("Massless bodies must have zero mass.")
RigidBody.mass.fset(self, mass)
@RigidBody.inertia.setter
def inertia(self, inertia: Inertia) -> None:
"""Body's inertia about a point; stored as (Dyadic, Point)."""
if inertia[0] != Dyadic(0):
raise AttributeError("Massless bodies do not have inertia.")
RigidBody.inertia.fset(self, inertia)
@RigidBody.potential_energy.setter
def potential_energy(self, potential_energy: Expr) -> None:
"""Potential energy of the body."""
if potential_energy != 0:
raise AttributeError("Massless bodies do not have potential energy.")
RigidBody.potential_energy.fset(self, potential_energy)
def linear_momentum(self, frame: ReferenceFrame) -> Vector:
"""Linear momentum of the body."""
return Vector(0)
def angular_momentum(self, point: Point, frame: ReferenceFrame) -> Vector:
"""Angular momentum of the body about a point in a frame."""
return Vector(0)
def kinetic_energy(self, frame: ReferenceFrame) -> Expr:
"""Kinetic energy of the body."""
return S.Zero
class Attachment:
"""Joint attachment.
Explanation
-----------
This class holds an immutable reference to a reference frame and a point to be used
in SymPy's joints framework.
"""
def __init__(self, frame: ReferenceFrame, point: Point) -> None:
if not isinstance(frame, ReferenceFrame):
raise TypeError("Frame must be a ReferenceFrame.")
if not isinstance(point, Point):
raise TypeError("Point must be a Point.")
self._frame = frame
self._point = point
@property
def frame(self) -> ReferenceFrame:
"""Reference frame of the attachment."""
return self._frame
@property
def point(self) -> Point:
"""Point of the attachment."""
return self._point
def to_massless_body(self, name: str) -> MasslessBody:
"""Convert the attachment to a massless body.
Notes
-----
This method is used to convert an attachment to a massless body. This is
necessary because sympy's joints framework does not yet support passing only a
frame and point to the joint constructor. Therefore, this method may be removed
once this functionality is added to sympy.
"""
return MasslessBody(name, self.point, self.frame)
def __getitem__(self, item):
return (self.frame, self.point)[item]
Just wrote up this simple class, but I'll probably not yet convert to using attachments and instead use a separate point and interframe property.
At the moment the rear and front frame use the NewtonianBodyMixin. However, this automatically makes them use only a single reference frame, while it is possible that a rotation occurs within the frame due to flexibility. Therefore it is better to use the same concept as always in the joints framework, namely a point and an interframe per joint. While this seems an easy fix, it would be ideal to create the pin joint in the WhippleBicycle just based on the interframe and the point. However, the joints framework does not yet the creation of a joint without using a body. Either a zero-weight body will have to be created or the joints framework should be updated. As the last would be the best option this issue consists out of three tasks:
namedtuple(frame=frame, point=point)
asparent
andchild
steer_interframe
andwheel_interframe
propertiessteer_interframe
andwheel_interframe
properties