Module MAPLEAF.Motion.inertia
Expand source code
# Created by: Henry Stoldt & Declan Quinn
# April 2020
from MAPLEAF.Motion import Vector
__all__ = [ "Inertia" ]
class Inertia():
___slots__ = [ "MOI", "MOICentroidLocation", "mass", "CG" ]
def __init__(self, MOI, CG, mass, MOICentroidLocation=None):
"""
* MOIVector: Ixx, Iyy, Izz
* MOICentroidLocation: The point (in the rocket frame) about which Ixx, Iyy, and Izz were calculated. Only required if different from CG
"""
self.MOI = MOI
self.CG = CG
self.mass = mass
self.MOICentroidLocation = CG if (MOICentroidLocation == None) else MOICentroidLocation
def checkDefinedAboutCG(self, inertiasList):
'''
Called by the functions that add/combine inertias.
Checks that every inertia to be added up has MOIs defined about its CG.
Throws a ValueError if this is not the case
'''
for inertia in inertiasList:
if inertia.MOICentroidLocation != inertia.CG:
raise ValueError("At least one of the inertias to be added has an MOI not defined about its CG: {}".format(inertia))
def combineInertiasAboutPoint(self, inertiasList, Point):
"""
Version of the combineInertias function below, which can combine Inertias about a point which is not coincident with the combined CG of the resulting combined object.
This changes the resulting moments of inertia.
Inputs:
inertiasList: List of other inertia objects. Can also be empty list, then parallel axis theorem is just applied to the present inertia object
Point: Point about which summed inertias will be calculated
Returns:
New instance of Inertia, with MOI defined about Point
"""
# Initialize variables to hold results
totalMass = 0
totalCG = Vector(0,0,0)
totalMOI = Vector(0,0,0)
# Add the current object to the list of Inertia objects to be combined
if self not in inertiasList:
inertiasList.append(self)
self.checkDefinedAboutCG(inertiasList)
# Add up all the inertias in the list
for inertia in inertiasList:
# Add mass and mass-weighted CG
totalMass += inertia.mass
totalCG += inertia.CG * inertia.mass
### Add inertia using parallel axis theorem ###
# Add current inertia
totalMOI += inertia.MOI
# Add adjustment for different axis location
distanceFromPoint = Point - inertia.MOICentroidLocation
xAxesDistSqr = distanceFromPoint.Y*distanceFromPoint.Y + distanceFromPoint.Z*distanceFromPoint.Z
yAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Z*distanceFromPoint.Z
zAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Y*distanceFromPoint.Y
totalMOI.X += inertia.mass*xAxesDistSqr
totalMOI.Y += inertia.mass*yAxesDistSqr
totalMOI.Z += inertia.mass*zAxesDistSqr
# Compute actual CG by dividing out the mass
totalCG = totalCG / totalMass
return Inertia(totalMOI, totalCG, totalMass, MOICentroidLocation=Point)
def combineInertias(self, inertiasList):
"""
Combines inertias about the CG of the combined object
Each component inertia must be defined about the component's CG
"""
# Add the current object to the list of Inertia objects to be combined
if self not in inertiasList:
inertiasList.append(self)
self.checkDefinedAboutCG(inertiasList)
# Calculate combined CG
totalMass = 0
totalCG = Vector(0,0,0)
for inertia in inertiasList:
totalMass += inertia.mass
totalCG += inertia.CG * inertia.mass # Adding mass-weighted CG
if totalMass > 0:
totalCG = totalCG / totalMass # Compute actual CG by dividing out the total mass
else:
totalCG = Vector(0,0,0)
# Calculate combined MOI about combined CG
totalMOI = Vector(0,0,0)
for inertia in inertiasList:
totalMOI += inertia.MOI # Add current inertia
# Add adjustment for different axis location - parallel axis theorem
distanceFromPoint = totalCG - inertia.MOICentroidLocation
xAxesDistSqr = distanceFromPoint.Y*distanceFromPoint.Y + distanceFromPoint.Z*distanceFromPoint.Z
yAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Z*distanceFromPoint.Z
zAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Y*distanceFromPoint.Y
totalMOI.X += inertia.mass*xAxesDistSqr
totalMOI.Y += inertia.mass*yAxesDistSqr
totalMOI.Z += inertia.mass*zAxesDistSqr
return Inertia(totalMOI, totalCG, totalMass)
def __add__(self, inertia2):
return self.combineInertias([inertia2])
def __str__(self):
''' Get string representation, used by str() and print() '''
if self.MOICentroidLocation == self.CG:
return 'MOI=({}) calculated about CG=({}); Mass={} '.format(self.MOI, self.CG, self.mass)
else:
return 'MOI=({}) calculated about non-CG Point=({}); CG=({}); Mass={}'.format(self.MOI, self.MOICentroidLocation, self.CG, self.mass)
def __eq__(self, inertia2):
try:
c1 = self.MOI == inertia2.MOI
c2 = self.MOICentroidLocation == inertia2.MOICentroidLocation
c3 = self.mass == inertia2.mass
c4 = self.CG == inertia2.CG
if c1 and c2 and c3 and c4:
return True
else:
return False
except AttributeError:
return False
Classes
class Inertia (MOI, CG, mass, MOICentroidLocation=None)
-
- MOIVector: Ixx, Iyy, Izz
- MOICentroidLocation: The point (in the rocket frame) about which Ixx, Iyy, and Izz were calculated. Only required if different from CG
Expand source code
class Inertia(): ___slots__ = [ "MOI", "MOICentroidLocation", "mass", "CG" ] def __init__(self, MOI, CG, mass, MOICentroidLocation=None): """ * MOIVector: Ixx, Iyy, Izz * MOICentroidLocation: The point (in the rocket frame) about which Ixx, Iyy, and Izz were calculated. Only required if different from CG """ self.MOI = MOI self.CG = CG self.mass = mass self.MOICentroidLocation = CG if (MOICentroidLocation == None) else MOICentroidLocation def checkDefinedAboutCG(self, inertiasList): ''' Called by the functions that add/combine inertias. Checks that every inertia to be added up has MOIs defined about its CG. Throws a ValueError if this is not the case ''' for inertia in inertiasList: if inertia.MOICentroidLocation != inertia.CG: raise ValueError("At least one of the inertias to be added has an MOI not defined about its CG: {}".format(inertia)) def combineInertiasAboutPoint(self, inertiasList, Point): """ Version of the combineInertias function below, which can combine Inertias about a point which is not coincident with the combined CG of the resulting combined object. This changes the resulting moments of inertia. Inputs: inertiasList: List of other inertia objects. Can also be empty list, then parallel axis theorem is just applied to the present inertia object Point: Point about which summed inertias will be calculated Returns: New instance of Inertia, with MOI defined about Point """ # Initialize variables to hold results totalMass = 0 totalCG = Vector(0,0,0) totalMOI = Vector(0,0,0) # Add the current object to the list of Inertia objects to be combined if self not in inertiasList: inertiasList.append(self) self.checkDefinedAboutCG(inertiasList) # Add up all the inertias in the list for inertia in inertiasList: # Add mass and mass-weighted CG totalMass += inertia.mass totalCG += inertia.CG * inertia.mass ### Add inertia using parallel axis theorem ### # Add current inertia totalMOI += inertia.MOI # Add adjustment for different axis location distanceFromPoint = Point - inertia.MOICentroidLocation xAxesDistSqr = distanceFromPoint.Y*distanceFromPoint.Y + distanceFromPoint.Z*distanceFromPoint.Z yAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Z*distanceFromPoint.Z zAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Y*distanceFromPoint.Y totalMOI.X += inertia.mass*xAxesDistSqr totalMOI.Y += inertia.mass*yAxesDistSqr totalMOI.Z += inertia.mass*zAxesDistSqr # Compute actual CG by dividing out the mass totalCG = totalCG / totalMass return Inertia(totalMOI, totalCG, totalMass, MOICentroidLocation=Point) def combineInertias(self, inertiasList): """ Combines inertias about the CG of the combined object Each component inertia must be defined about the component's CG """ # Add the current object to the list of Inertia objects to be combined if self not in inertiasList: inertiasList.append(self) self.checkDefinedAboutCG(inertiasList) # Calculate combined CG totalMass = 0 totalCG = Vector(0,0,0) for inertia in inertiasList: totalMass += inertia.mass totalCG += inertia.CG * inertia.mass # Adding mass-weighted CG if totalMass > 0: totalCG = totalCG / totalMass # Compute actual CG by dividing out the total mass else: totalCG = Vector(0,0,0) # Calculate combined MOI about combined CG totalMOI = Vector(0,0,0) for inertia in inertiasList: totalMOI += inertia.MOI # Add current inertia # Add adjustment for different axis location - parallel axis theorem distanceFromPoint = totalCG - inertia.MOICentroidLocation xAxesDistSqr = distanceFromPoint.Y*distanceFromPoint.Y + distanceFromPoint.Z*distanceFromPoint.Z yAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Z*distanceFromPoint.Z zAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Y*distanceFromPoint.Y totalMOI.X += inertia.mass*xAxesDistSqr totalMOI.Y += inertia.mass*yAxesDistSqr totalMOI.Z += inertia.mass*zAxesDistSqr return Inertia(totalMOI, totalCG, totalMass) def __add__(self, inertia2): return self.combineInertias([inertia2]) def __str__(self): ''' Get string representation, used by str() and print() ''' if self.MOICentroidLocation == self.CG: return 'MOI=({}) calculated about CG=({}); Mass={} '.format(self.MOI, self.CG, self.mass) else: return 'MOI=({}) calculated about non-CG Point=({}); CG=({}); Mass={}'.format(self.MOI, self.MOICentroidLocation, self.CG, self.mass) def __eq__(self, inertia2): try: c1 = self.MOI == inertia2.MOI c2 = self.MOICentroidLocation == inertia2.MOICentroidLocation c3 = self.mass == inertia2.mass c4 = self.CG == inertia2.CG if c1 and c2 and c3 and c4: return True else: return False except AttributeError: return False
Methods
def checkDefinedAboutCG(self, inertiasList)
-
Called by the functions that add/combine inertias. Checks that every inertia to be added up has MOIs defined about its CG. Throws a ValueError if this is not the case
Expand source code
def checkDefinedAboutCG(self, inertiasList): ''' Called by the functions that add/combine inertias. Checks that every inertia to be added up has MOIs defined about its CG. Throws a ValueError if this is not the case ''' for inertia in inertiasList: if inertia.MOICentroidLocation != inertia.CG: raise ValueError("At least one of the inertias to be added has an MOI not defined about its CG: {}".format(inertia))
def combineInertias(self, inertiasList)
-
Combines inertias about the CG of the combined object Each component inertia must be defined about the component's CG
Expand source code
def combineInertias(self, inertiasList): """ Combines inertias about the CG of the combined object Each component inertia must be defined about the component's CG """ # Add the current object to the list of Inertia objects to be combined if self not in inertiasList: inertiasList.append(self) self.checkDefinedAboutCG(inertiasList) # Calculate combined CG totalMass = 0 totalCG = Vector(0,0,0) for inertia in inertiasList: totalMass += inertia.mass totalCG += inertia.CG * inertia.mass # Adding mass-weighted CG if totalMass > 0: totalCG = totalCG / totalMass # Compute actual CG by dividing out the total mass else: totalCG = Vector(0,0,0) # Calculate combined MOI about combined CG totalMOI = Vector(0,0,0) for inertia in inertiasList: totalMOI += inertia.MOI # Add current inertia # Add adjustment for different axis location - parallel axis theorem distanceFromPoint = totalCG - inertia.MOICentroidLocation xAxesDistSqr = distanceFromPoint.Y*distanceFromPoint.Y + distanceFromPoint.Z*distanceFromPoint.Z yAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Z*distanceFromPoint.Z zAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Y*distanceFromPoint.Y totalMOI.X += inertia.mass*xAxesDistSqr totalMOI.Y += inertia.mass*yAxesDistSqr totalMOI.Z += inertia.mass*zAxesDistSqr return Inertia(totalMOI, totalCG, totalMass)
def combineInertiasAboutPoint(self, inertiasList, Point)
-
Version of the combineInertias function below, which can combine Inertias about a point which is not coincident with the combined CG of the resulting combined object. This changes the resulting moments of inertia.
Inputs
inertiasList: List of other inertia objects. Can also be empty list, then parallel axis theorem is just applied to the present inertia object Point: Point about which summed inertias will be calculated
Returns
New instance of Inertia, with MOI defined about Point
Expand source code
def combineInertiasAboutPoint(self, inertiasList, Point): """ Version of the combineInertias function below, which can combine Inertias about a point which is not coincident with the combined CG of the resulting combined object. This changes the resulting moments of inertia. Inputs: inertiasList: List of other inertia objects. Can also be empty list, then parallel axis theorem is just applied to the present inertia object Point: Point about which summed inertias will be calculated Returns: New instance of Inertia, with MOI defined about Point """ # Initialize variables to hold results totalMass = 0 totalCG = Vector(0,0,0) totalMOI = Vector(0,0,0) # Add the current object to the list of Inertia objects to be combined if self not in inertiasList: inertiasList.append(self) self.checkDefinedAboutCG(inertiasList) # Add up all the inertias in the list for inertia in inertiasList: # Add mass and mass-weighted CG totalMass += inertia.mass totalCG += inertia.CG * inertia.mass ### Add inertia using parallel axis theorem ### # Add current inertia totalMOI += inertia.MOI # Add adjustment for different axis location distanceFromPoint = Point - inertia.MOICentroidLocation xAxesDistSqr = distanceFromPoint.Y*distanceFromPoint.Y + distanceFromPoint.Z*distanceFromPoint.Z yAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Z*distanceFromPoint.Z zAxesDistSqr = distanceFromPoint.X*distanceFromPoint.X + distanceFromPoint.Y*distanceFromPoint.Y totalMOI.X += inertia.mass*xAxesDistSqr totalMOI.Y += inertia.mass*yAxesDistSqr totalMOI.Z += inertia.mass*zAxesDistSqr # Compute actual CG by dividing out the mass totalCG = totalCG / totalMass return Inertia(totalMOI, totalCG, totalMass, MOICentroidLocation=Point)