def forceFromCoefficients(rocketState, environment, Cd, Cl, CMx, CMy, CMz, CPLocation, refArea, refLength): ''' Initialize ForceMomentSystem from all aerodynamic coefficients ''' q = AeroParameters.getDynamicPressure(rocketState, environment) if q == 0.0: # No force without dynamic pressure return ForceMomentSystem(Vector(0, 0, 0)) nonDimConstant = q * refArea #### Drag #### localFrameAirVel = AeroParameters.getLocalFrameAirVel( rocketState, environment) dragDirection = localFrameAirVel.normalize() dragForce = dragDirection * Cd #### Lift #### # Find the lift force direction # Lift force will be in the same plane as the normalForceDirection & rocketFrameAirVel vectors # But, the lift force will be perpendicular to rocketFraeAirVel, whereas the normalForceDirection might form an acute angle with it # Rotate the normal force direction vector until it's perpendicular with rocketFrameAirVel normalForceDir = AeroParameters.getNormalAeroForceDirection( rocketState, environment) rotAxis = localFrameAirVel.crossProduct(normalForceDir) angle = math.pi / 2 - localFrameAirVel.angle(normalForceDir) rotatorQuat = Quaternion(rotAxis, angle) liftDirection = rotatorQuat.rotate(normalForceDir) liftForce = liftDirection * Cl # Combine and redimensionalize totalForce = (dragForce + liftForce) * nonDimConstant #### Moments #### moments = Vector(CMx, CMy, CMz) * nonDimConstant * refLength return ForceMomentSystem(totalForce, CPLocation, moments)
def getAppliedForce(self, rocketState, time, environment, CG): ''' Calculates force/moment applied by the recovery system using a simple drag coefficient + area model ''' #### Calculate Aero Force #### if self.currentStage == 0: # No recovery system deployed yet return ForceMomentSystem(Vector(0,0,0)) else: # 3DoF force-only aero airVel = AeroParameters.getAirVelRelativeToVehicle(rocketState, environment) dragForceMagnitude = self.chuteCds[self.currentStage] * self.chuteAreas[self.currentStage] * AeroParameters.getDynamicPressure(rocketState, environment) totalForce = airVel.normalize() * dragForceMagnitude return ForceMomentSystem(totalForce)
def getAppliedForce(self, rocketState, time, environment, CG): #### If control system exists, use actuator deflections 1:1 to set fin angles #### if self.controlSystem != None: # Update fin angles for i in range(self.numFins): self.finList[i].finAngle = self.actuatorList[i].getDeflection( time) #### Pre-calculate common properties for all child Fins #### precomputedData = self._getPreComputedFinAeroData( rocketState, environment, CG) #### Add up forces from all child Fins #### aeroForce = ForceMomentSystem(Vector(0, 0, 0), self.position) for fin in self.finList: aeroForce += fin.getAppliedForce(rocketState, time, environment, CG, precomputedData) # TODO: Correct for sub/transonic rolling moment fin-fin interference from a high number of fins # Apply fin-body interference factor to total forces in the normal (X/Y) directions and moments totalInterferenceFactor = self.bodyOnFinInterferenceFactor * self.finNumberInterferenceFactor aeroForce.force.X *= totalInterferenceFactor aeroForce.force.Y *= totalInterferenceFactor aeroForce.moment.X *= totalInterferenceFactor aeroForce.moment.Y *= totalInterferenceFactor return aeroForce
def forceFromCdCN(rocketState, environment, Cd, CN, CPLocation, refArea, moment=None): ''' Convenience function for Barrowman Aero methods Initialize ForceMomentSystem from aerodynamic coefficients Cd and CN Cd should NOT already be adjusted for angle of attack Moment should be a dimensional moment vector ''' angleOfAttack = AeroParameters.getTotalAOA(rocketState, environment) q = AeroParameters.getDynamicPressure(rocketState, environment) #### Axial Force #### CA = getDragToAxialForceFactor(angleOfAttack) * Cd axialForce = Vector(0, 0, -CA) #Axial force is in the negative Z-direction #### Normal Force #### normalForce = AeroParameters.getNormalAeroForceDirection( rocketState, environment) * CN totalForce = (axialForce + normalForce) * refArea * q return ForceMomentSystem(totalForce, CPLocation, moment)
def __init__(self, componentDictReader, rocket, stage): self.rocket = rocket self.stage = stage self.componentDictReader = componentDictReader self.name = componentDictReader.getDictName() mass = componentDictReader.getFloat("mass") # Position in simulation definition is relative to stage position self.position = componentDictReader.getVector( "position" ) + stage.position # Store position relative to nosecone here # CG in simulation definition is relative to component position cg = componentDictReader.getVector( "cg" ) + self.position # Store cg location relative to nosecone here try: MOI = componentDictReader.getVector("MOI") except: MOI = Vector(mass * 0.01, mass * 0.01, mass * 0.01) # Avoid having zero moments of inertia self.inertia = Inertia(MOI, cg, mass) self.zeroForce = ForceMomentSystem(Vector(0, 0, 0))
def uniformlyAcceleratingRotationTest(self, integrationMethod): constantZMoment = ForceMomentSystem(self.zeroVec, moment=Vector(0, 0, 1)) restingState = RigidBodyState(self.zeroVec, self.zeroVec, self.zeroQuat, self.zeroAngVel) def constZMomentFunc(*allArgs): return constantZMoment def constInertiaFunc(*allArgs): return self.constInertia acceleratingZRotBody = RigidBody(restingState, constZMomentFunc, constInertiaFunc, integrationMethod=integrationMethod, simDefinition=self.simDefinition) acceleratingZRotBody.timeStep(1) newOrientation = acceleratingZRotBody.state.orientation newAngVel = acceleratingZRotBody.state.angularVelocity #print("{}: {}".format(integrationMethod, newOrientation)) assertAngVelAlmostEqual( self, newAngVel, AngularVelocity(axisOfRotation=Vector(0, 0, 1), angularVel=1)) if integrationMethod == "Euler": assertQuaternionsAlmostEqual( self, newOrientation, Quaternion(axisOfRotation=Vector(0, 0, 1), angle=0)) else: assertQuaternionsAlmostEqual( self, newOrientation, Quaternion(axisOfRotation=Vector(0, 0, 1), angle=0.5))
def uniformXAccelerationTest(self, integrationMethod): constantXForce = ForceMomentSystem(Vector(1, 0, 0)) movingXState = RigidBodyState(self.zeroVec, self.zeroVec, self.zeroQuat, self.zeroAngVel) def constInertiaFunc(*allArgs): return self.constInertia def constXForceFunc(*allArgs): return constantXForce movingXBody = RigidBody(movingXState, constXForceFunc, constInertiaFunc, integrationMethod=integrationMethod, simDefinition=self.simDefinition) movingXBody.timeStep(1) newPos = movingXBody.state.position newVel = movingXBody.state.velocity assertVectorsAlmostEqual(self, newVel, Vector(1, 0, 0)) if integrationMethod == "Euler": assertVectorsAlmostEqual(self, newPos, Vector(0, 0, 0)) else: assertVectorsAlmostEqual(self, newPos, Vector(0.5, 0, 0))
def setUp(self): self.appliedForce1 = ForceMomentSystem(Vector(0, 0, 10), Vector(1, 0, 0), Vector(0, 0, 0)) self.appliedForce2 = ForceMomentSystem(Vector(0, 0, 10), Vector(2, 0, 0), Vector(0, 0, 0)) self.appliedForce3 = ForceMomentSystem(Vector(10, 0, 0), Vector(0, 1, 0), Vector(0, 0, 0)) self.correctForce1 = ForceMomentSystem(Vector(0, 0, 20), Vector(0, 0, 0), Vector(0, -30, 0)) self.correctForce2 = ForceMomentSystem(Vector(10, 0, 10), Vector(0, 0, 0), Vector(0, -10, -10))
def test_fixedForceInit(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/FixedForce.mapleaf", silent=True) rocketDictReader = SubDictReader("Rocket", simDef) rocket = Rocket(rocketDictReader, silent=True) fixedForce = rocket.stages[0].getComponentsOfType(FixedForce)[0] expectedFMS = ForceMomentSystem(Vector(0,0,0), Vector(0,0,0), Vector(0,1,0)) assertForceMomentSystemsAlmostEqual(self, fixedForce.force, expectedFMS)
def test_CPZ(self): force = Vector(0, 1, 0) location = Vector(0, 0, 0) moment = Vector(1, 0, 0) testForce = ForceMomentSystem(force, location, moment) expectedCPZ = -1 calculatedCPZ = AeroFunctions._getCPZ(testForce) self.assertAlmostEqual(expectedCPZ, calculatedCPZ)
def __init__(self, componentDictReader, rocket, stage): self.rocket = rocket self.stage = stage self.componentDictReader = componentDictReader self.name = componentDictReader.getDictName() self.zeroForce = ForceMomentSystem(Vector(0, 0, 0)) inertiaTableFilePath = componentDictReader.getString("filePath") self._parseInertiaTable(inertiaTableFilePath)
def test_zeroSag(self): unadjustedForce = ForceMomentSystem(Vector(10, 9, -10), moment=Vector(10, 11, 12)) adjustedForce = self.rail.applyLaunchTowerForce( self.initState, 0, unadjustedForce) # Check that force is zero (don't let object sag/fall) assertVectorsAlmostEqual(self, adjustedForce.force, Vector(0, 0, 0)) # Check moments are zero assertVectorsAlmostEqual(self, adjustedForce.moment, Vector(0, 0, 0))
def test_getFixedForce(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/FixedForce.mapleaf", silent=True) rocketDictReader = SubDictReader("Rocket", simDef) rocket = Rocket(rocketDictReader, silent=True) fixedForce = rocket.stages[0].getComponentsOfType(FixedForce)[0] force = fixedForce.getAppliedForce("fakeState", 0, "fakeEnv", Vector(0,0,0)) expectedForce = ForceMomentSystem(Vector(0,0,0), moment=Vector(0,1,0)) self.assertEqual(force.force, expectedForce.force) self.assertEqual(force.moment, expectedForce.moment)
def getAppliedForce(self, rocketState, time, envConditions, rocketCG): mag = -2000 * self.getTankLevelDerivative( time, rocketState ) # Force magnitude proportional to flow rate out of the tank forceVector = Vector(0, 0, mag) self.rocket.appendToForceLogLine( " {:>6.4f}".format(mag) ) # This will end up in the log file, in the SampleZForce column return ForceMomentSystem(forceVector)
def test_LeaveRail(self): unadjustedForce = ForceMomentSystem(Vector(10, 9, 11), moment=Vector(10, 11, 12)) self.initState.position = Vector(4, 0, 4) # Greater than 5m away adjustedForce = self.rail.applyLaunchTowerForce( self.initState, 0, unadjustedForce) # Check that forces/moments are unaffected assertVectorsAlmostEqual(self, adjustedForce.force, Vector(10, 9, 11)) assertVectorsAlmostEqual(self, adjustedForce.moment, Vector(10, 11, 12))
def test_alignForceWithRail(self): unadjustedForce = ForceMomentSystem(Vector(10, 9, 11), moment=Vector(10, 11, 12)) adjustedForce = self.rail.applyLaunchTowerForce( self.initState, 0, unadjustedForce) # Check that force direction is now aligned with rail forceDirection = adjustedForce.force.normalize() assertVectorsAlmostEqual(self, self.rail.initialDirection, forceDirection) # Check moments are zero assertVectorsAlmostEqual(self, adjustedForce.moment, Vector(0, 0, 0))
def getAppliedForce(self, rocketState, time, environmentalConditions, rocketCG): # Only apply damping force if current stage's engine is firing # (Other stage's motors will have different exit planes) if time > self.stage.motor.ignitionTime and time < self.stage.engineShutOffTime: currentRocketInertia = self.rocket.getInertia(time, rocketState) # Differentiate rate of MOI change dt = 0.001 nextRocketInertia = self.rocket.getInertia(time + dt, rocketState) MOIChangeRate = (currentRocketInertia.MOI.X - nextRocketInertia.MOI.X) / dt dampingFactor = MOIChangeRate * self.dampingFraction angVel = rocketState.angularVelocity dampingMoment = Vector(-angVel.X * dampingFactor, -angVel.Y * dampingFactor, 0) return ForceMomentSystem(Vector(0, 0, 0), moment=dampingMoment) else: return ForceMomentSystem(Vector(0, 0, 0))
def getAppliedForce(self, state, time, environment, CG): #TODO: Model "thrust damping" - where gases moving quickly in the engine act to damp out rotation about the x and y axes #TODO: Thrust vs altitude compensation timeSinceIgnition = max(0, time - self.ignitionTime) # Determine thrust magnitude if timeSinceIgnition < 0 or timeSinceIgnition > self.times[-1]: thrustMagnitude = 0 else: thrustMagnitude = linInterp(self.times, self.thrustLevels, timeSinceIgnition) # Create Vector thrust = Vector(0, 0, thrustMagnitude) return ForceMomentSystem(thrust)
def __init__(self, componentDictReader, rocket, stage): ''' A Zero-inertia component that applies a constant ForceMomentSystem to the rocket ''' self.componentDictReader = componentDictReader self.rocket = rocket self.stage = stage self.name = componentDictReader.getDictName() # Object is just a force, inertia is zero self.inertia = Inertia(Vector(0, 0, 0), Vector(0, 0, 0), 0) force = componentDictReader.getVector("force") forceLocation = componentDictReader.getVector("position") moment = componentDictReader.getVector("moment") self.force = ForceMomentSystem(force, forceLocation, moment)
def test_combineForceMomentSystems_2(self): # Example Question 16 - http://www.ce.siue.edu/examples/Worked_examples_Internet_text-only/Data_files-Worked_Exs-Word_&_pdf/Equivalent_forces.pdf # Define Force-Moment 1 force1 = Vector(0, -3.464, -2) m1 = Vector(0, -51.962, -30) location1 = Vector(4, 1.5, 4.402) fms1 = ForceMomentSystem(force1, location1, m1) # Define Force-Moment 2 force2 = Vector(-6, 0, 0) m2 = Vector(-80, 0, 0) location2 = Vector(8, 1.5, 1) fms2 = ForceMomentSystem(force2, location2, m2) # Combine combinedForce = fms1 + fms2 combinedForceAtOrigin = combinedForce.getAt(Vector(0, 0, 0)) # Define correct/expected result expectedResultantForce = Vector(-6, -3.464, -2) expectedResultantMoment = Vector( 12.249, 2, -4.856 ) # Only includes moments generated by forces, not the moments applied resultantLocation = Vector(0, 0, 0) expectedResult = ForceMomentSystem(expectedResultantForce, resultantLocation, expectedResultantMoment) # Compare from test.testUtilities import assertVectorsAlmostEqual assertVectorsAlmostEqual(self, combinedForceAtOrigin.force, expectedResult.force) assertVectorsAlmostEqual(self, combinedForceAtOrigin.location, expectedResult.location) assertVectorsAlmostEqual(self, combinedForceAtOrigin.moment - m1 - m2, expectedResult.moment, 3)
def setUp(self): self.zeroVec = Vector(0, 0, 0) self.zeroQuat = Quaternion(axisOfRotation=Vector(1, 0, 0), angle=0) self.zeroAngVel = AngularVelocity(axisOfRotation=Vector(1, 0, 0), angularVel=0) self.zeroForce = ForceMomentSystem(self.zeroVec) self.oneVec = Vector(1, 1, 1) self.simDefinition.setValue( "SimControl.TimeStepAdaptation.minTimeStep", "1") #TODO: Get some tests for the higher order adaptive methods in here self.integrationMethods = [ "Euler", "RK2Heun", "RK2Midpoint", "RK4", "RK12Adaptive" ] self.constInertia = Inertia(self.oneVec, self.zeroVec, 1)
def getGravityForce(self, inertia, state) -> ForceMomentSystem: ''' Inputs: inertia: (`MAPLEAF.Motion.Inertia`) state: (`MAPLEAF.Motion.RigidBodyState`/`MAPLEAF.Motion.RigidBodyState_3DoF`) Returns: gravityForce: (ForceMomentSystem) defined in the rocket's local frame ''' # Get gravity force in the global frame gravityForce = self.earthModel.getGravityForce(inertia, state) try: # Convert to local frame if in 6DoF simulation gravityForce = state.orientation.conjugate().rotate(gravityForce) # rotate into local frame when in 6DoF mode except AttributeError: pass # Don't do anything in 3DoF mode (No local frame exists) return ForceMomentSystem(gravityForce, inertia.CG)
def getAppliedForce(self, state, time, environmentalConditions, rocketCG): ''' Computes the aerodynamic force experienced by the stage. Does not include gravitational force - gravity is added at the rocket level. ''' # Add up forces from all subcomponents totalAppliedComponentForce = ForceMomentSystem(Vector(0, 0, 0), rocketCG) for component in self.components: componentForce = component.getAppliedForce( state, time, environmentalConditions, rocketCG) # Log applied forces and moments if desired if hasattr(component, "forcesLog"): component.forcesLog.append(componentForce.force) component.momentsLog.append(componentForce.moment) totalAppliedComponentForce += componentForce return totalAppliedComponentForce
def applyLaunchTowerForce(self, state, time, unadjustedForce): ''' If on launch tower, projects forces experienced onto the launch tower directions and sets Moments = 0 Returns two values: onTower(Bool), adjustedForce(Motion.ForceMomentSystem) ''' distanceTravelled = (state.position - self.getPosition(time)).length() if distanceTravelled < self.length: # Vehicle still on launch rail # Project total force onto the launch rail direction (dot product) adjustedForceMagnitude = unadjustedForce.force * self.getDirection( time) adjustedForceVector = self.initialDirection * adjustedForceMagnitude # No resultant moments while on the launch rail adjustedForce = ForceMomentSystem(adjustedForceVector) return adjustedForce else: # Vehicle has left the rail return unadjustedForce
def test_nonPrincipalAxisRotation(self): initAngVel = AngularVelocity(rotationVector=Vector(1, 0, 1)) rotatingZState = RigidBodyState(self.zeroVec, self.zeroVec, self.zeroQuat, initAngVel) constForce = ForceMomentSystem(self.zeroVec) def constForceFunc(*allArgs): return constForce constInertia = Inertia(Vector(2, 2, 8), self.zeroVec, 1) def constInertiaFunc(*allArgs): return constInertia rotatingZBody = RigidBody(rotatingZState, constForceFunc, constInertiaFunc, integrationMethod="RK4", simDefinition=self.simDefinition) dt = 0.01 nTimeSteps = 10 totalTime = dt * nTimeSteps for i in range(nTimeSteps): rotatingZBody.timeStep(dt) finalAngVel = rotatingZBody.state.angularVelocity omega = (constInertia.MOI.Z - constInertia.MOI.X) / constInertia.MOI.X expectedAngVel = AngularVelocity( rotationVector=Vector(cos(omega * totalTime), sin(omega * totalTime), 1)) assertAngVelAlmostEqual(self, finalAngVel, expectedAngVel)
def step1MomentFunc(*allArgs): return ForceMomentSystem( self.zeroVec, moment=Vector(0, 0.5, 0) ) #Acceleration and deceleration steps to give 90 degree rotations in each axis
def step2MomentFunc(*allArgs): return ForceMomentSystem(self.zeroVec, moment=Vector( 0, -0.5, 0)) #using a time step of pi
def step3MomentFunc(*allArgs): return ForceMomentSystem( self.zeroVec, moment=Vector(0, 0, 0.5) ) #There is one acceleration and one deceleration for each rotation to make it static
def step4MomentFunc(*allArgs): return ForceMomentSystem(self.zeroVec, moment=Vector(0, 0, -0.5))
def _barrowmanAeroFunc(self, rocketState, time, environment, precomputedData, CG=Vector(0, 0, 0), finDeflectionAngle=None): ''' Precomputed Data is a named tuple (PreComputedFinAeroData) which contains data/results from the parts of the fin aerodynamics calculation that are common to all fins in a FinSet (drag calculations mostly). These calculations are performed at the FinSet level. Only the parts of the Fin Aero Computation that change from fin to fin (normal force mostly, since different fins can have different angles of attack) are computed here ''' Mach = AeroParameters.getMachNumber(rocketState, environment) dynamicPressure = AeroParameters.getDynamicPressure( rocketState, environment) if finDeflectionAngle == None: finDeflectionAngle = self.finAngle # Adjusted by parent finset during each timestep, when the FinSet is controlled # Unpack precomputedData airVelRelativeToFin, CPXPos, totalDragCoefficient = precomputedData #### Compute normal force----------------------------------------------------------------------------------------------------------------- # Find fin normal vector after fin deflection finDeflectionRotation = Quaternion( axisOfRotation=self.spanwiseDirection, angle=radians(finDeflectionAngle)) finNormal = finDeflectionRotation.rotate(self.undeflectedFinNormal) # Get the tangential velocity component vector, per unit radial distance from the rocket centerline rollAngVel = AngularVelocity(0, 0, rocketState.angularVelocity.Z) unitSpanTangentialAirVelocity = rollAngVel.crossProduct( self.spanwiseDirection) * (-1) def subsonicNormalForce(Mach): # Subsonic linear method tempBeta = AeroParameters.getBeta(Mach) CnAlpha = getFinCnAlpha_Subsonic_Barrowman(self.span, self.planformArea, tempBeta, self.midChordSweep) return getSubsonicFinNormalForce(airVelRelativeToFin, unitSpanTangentialAirVelocity, finNormal, self.spanwiseDirection, self.CPSpanWisePosition.length(), CnAlpha, self) def supersonicNormalForce(Mach): # Supersonic Busemann method gamma = AeroFunctions.getGamma() tempBeta = AeroParameters.getBeta(Mach) K1, K2, K3, Kstar = getBusemannCoefficients(Mach, tempBeta, gamma) # Mach Cone coords machAngle = asin(1 / Mach) machCone_negZPerRadius = 1 / tan(machAngle) machConeEdgeZPos = [] outerRadius = self.spanSliceRadii[-1] for i in range(len(self.spanSliceRadii)): machConeAtCurrentRadius = ( outerRadius - self.spanSliceRadii[i] ) * machCone_negZPerRadius + self.tipPosition machConeEdgeZPos.append(machConeAtCurrentRadius) return getSupersonicFinNormalForce( airVelRelativeToFin, unitSpanTangentialAirVelocity, finNormal, machConeEdgeZPos, self.spanwiseDirection, self.CPSpanWisePosition.length(), K1, K2, K3, Kstar, self) if Mach <= 0.8: normalForceMagnitude, finMoment = subsonicNormalForce(Mach) elif Mach < 1.4: # Interpolate in transonic region # TODO: Do this with less function evaluations? Perhaps precompute AOA and Mach combinations and simply interpolate? Lazy precompute? Cython? x1, x2 = 0.8, 1.4 # Start, end pts of interpolated region dx = 0.001 # Find normal force and derivative at start of interpolation interval f_x1, m_x1 = subsonicNormalForce(x1) f_x12, m_x12 = subsonicNormalForce(x1 + dx) # Find normal force and derivative at end of interpolation interval f_x2, m_x2 = supersonicNormalForce(x2) f_x22, m_x22 = supersonicNormalForce(x2 + dx) normalForceMagnitude = Interpolation.cubicInterp( Mach, x1, x2, f_x1, f_x2, f_x12, f_x22, dx) finMoment = Interpolation.cubicInterp(Mach, x1, x2, m_x1, m_x2, m_x12, m_x22, dx) else: normalForceMagnitude, finMoment = supersonicNormalForce(Mach) # Complete redimensionalization of normal force coefficients by multiplying by dynamic pressure # Direct the normal force along the fin's normal direction normalForce = normalForceMagnitude * dynamicPressure * finNormal finMoment *= dynamicPressure #### Get axial force----------------------------------------------------------------------------------------------------------------------- avgAOA = getFinSliceAngleOfAttack( self.spanSliceRadii[round(len(self.spanSliceAreas) / 2)], airVelRelativeToFin, unitSpanTangentialAirVelocity, finNormal, self.spanwiseDirection, self.stallAngle) # Approximate average fin AOA totalAxialForceCoefficient = AeroFunctions.getDragToAxialForceFactor( avgAOA) * totalDragCoefficient axialForceMagnitude = totalAxialForceCoefficient * self.rocket.Aref * dynamicPressure axialForceDirection = self.spanwiseDirection.crossProduct(finNormal) axialForce = axialForceDirection * axialForceMagnitude #### Get CP Location ---------------------------------------------------------------------------------------------------------------------- CPChordWisePosition = self.position - Vector( 0, 0, CPXPos ) # Ignoring the change in CP position due to fin deflection for now globalCP = self.CPSpanWisePosition + CPChordWisePosition #### Assemble total force moment system objects-------------------------------------------------------------------------------------------- totalForce = normalForce + axialForce return ForceMomentSystem(totalForce, globalCP, moment=Vector(0, 0, finMoment)), globalCP