def test_burnTimeAdjustFactor(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/test2.mapleaf") # Create normal motor rocketDictReader1 = SubDictReader("Rocket", simDef) motorRocket1 = Rocket(rocketDictReader1) motor1 = motorRocket1.stages[0].getComponentsOfType(TabulatedMotor)[0] burnTimeAdjustFactor = "1.11" # Create impulse-adjusted motor simDef.setValue("Rocket.Sustainer.Motor.burnTimeAdjustFactor", burnTimeAdjustFactor) rocketDictReader2 = SubDictReader("Rocket", simDef) motorRocket2 = Rocket(rocketDictReader2) motor2 = motorRocket2.stages[0].getComponentsOfType(TabulatedMotor)[0] # Check that total impulse hasn't changed impulse1 = motor1.getTotalImpulse() impulse2 = motor2.getTotalImpulse() self.assertAlmostEqual(impulse1, impulse2) # Check that burn time has changed burnTime1 = motor1.times[-1] burnTime2 = motor2.times[-1] self.assertAlmostEqual(burnTime2 / burnTime1, float(burnTimeAdjustFactor))
def _createStages(self): ''' Initialize each of the stages and all of their subcomponents. ''' stageDicts = self._getStageSubDicts() # If we're initializing a dropped stage, figure out which one if self.stage != None: stageNumbers = [] stageNumberSet = set() for stageDict in stageDicts: stageNumber = self.rocketDictReader.getFloat(stageDict + ".stageNumber") stageNumbers.append(stageNumber) stageNumberSet.add(stageNumber) if len(stageNumbers) != len(stageNumberSet): raise ValueError("For multi-stage rockets, each stage must have a unique stage number. Set the Rocket.StageName.stageNumber value for each stage. 0 for first stage, 1 for second, etc...") stageNumbers.sort() stageToInitialize = stageNumbers[self.stage] # Initialize Stage(s) initializingAllStages = (self.stage == None) for stageDictionary in stageDicts: stageDictReader = SubDictReader(stageDictionary, self.simDefinition) stageNumber = stageDictReader.getFloat("stageNumber") if initializingAllStages or stageNumber == stageToInitialize: newStage = Stage(stageDictReader, self) self.stages.append(newStage) if newStage.name not in self.__dict__: # Avoid clobbering existing info setattr(self, newStage.name, newStage) # Make stage available as rocket.stageName
def setUp(self): configFilePath = "MAPLEAF/Examples/Simulations/Wind.mapleaf" self.simDef = SimDefinition(configFilePath, silent=True) self.simDef.setValue("Environment.MeanWindModel", "Constant") self.simDef.setValue("SimControl.loggingLevel", "0") rocketDictReader = SubDictReader("Rocket", self.simDef) envReader = SubDictReader("Environment", self.simDef) self.rocket = Rocket(rocketDictReader, silent=True) self.mWM = meanWindModelFactory(envReader, self.rocket)
def setUp(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/test3.mapleaf", silent=True) rocketDictReader = SubDictReader("Rocket", simDef) self.rocket = Rocket(rocketDictReader, silent=True) simDef = SimDefinition("MAPLEAF/Examples/Simulations/test6.mapleaf", silent=True) rocketDictReader = SubDictReader("Rocket", simDef) self.rocket2 = Rocket(rocketDictReader, silent=True) self.finSet1 = self.rocket2.stages[0].getComponentsOfType(FinSet)[0] self.finSet2 = self.rocket2.stages[0].getComponentsOfType(FinSet)[1] self.dummyVelocity1 = Vector(0, 0, 50) self.dummyVelocity2 = Vector(1, 0, 20) self.dummyVelocity3 = Vector(0, 0, -100) self.dummyOrientation1 = Quaternion(Vector(1, 0, 0), math.radians(2)) self.dummyOrientation2 = Quaternion(Vector(1, 0, 0), math.radians(-2)) self.dummyOrientation3 = Quaternion(Vector(0, 1, 0), math.radians(2)) self.dummyOrientation4 = Quaternion(Vector(1, 0, 0), 0) self.dummyOrientation5 = Quaternion(Vector(1, 1, 0), math.radians(2)) self.dummyOrientation6 = Quaternion(Vector(1,0,0), math.radians(90)) self.dummyAngularVelocity1 = AngularVelocity(rotationVector = Vector(0,0,0)) self.dummyAngularVelocity2 = AngularVelocity(rotationVector = Vector(0,0,1)) self.dummyAngularVelocity3 = AngularVelocity(rotationVector = Vector(0,0,-1)) self.dummyAngularVelocity4 = AngularVelocity(rotationVector = Vector(1,0,0)) self.dummyAngularVelocity5 = AngularVelocity(rotationVector = Vector(-1,0,0)) self.dummyAngularVelocity6 = AngularVelocity(rotationVector = Vector(0,1,0)) self.dummyAngularVelocity7 = AngularVelocity(rotationVector = Vector(0,-1,0)) self.dummyAngularVelocity8 = AngularVelocity(rotationVector = Vector(1,1,0)) self.currentConditions = self.rocket2.environment.getAirProperties(Vector(0,0,200)) # m self.rocketState1 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 200), Quaternion(Vector(0, 0, 1), 0), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState2 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 200), Quaternion(Vector(1, 0, 0), math.radians(2)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState3 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 500), Quaternion(Vector(1, 0, 0), math.radians(2)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState4 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, -200), Quaternion(Vector(1, 0, 0), math.radians(180)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState5 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, -200), Quaternion(Vector(1, 0, 0), math.radians(178)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState6 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, -200), Quaternion(Vector(1, 0, 0), math.radians(182)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState7 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, -200), Quaternion(Vector(1, 0, 0), math.radians(90)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState8 = RigidBodyState(Vector(0, 0, 200), Vector(20.04, -0.12, -52.78), Quaternion(Vector(0, 1, 0), math.radians(90)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState9 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 200), Quaternion(Vector(1, 0, 0), math.radians(-2)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState10 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 200), Quaternion(Vector(0, 0, 1), 0), AngularVelocity(rotationVector=Vector(0, 0, 1))) self.rocketState11 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 200), Quaternion(Vector(0, 1, 0), math.radians(2)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState12 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 200), Quaternion(Vector(0, 1, 0), math.radians(-2)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState13 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 500), Quaternion(Vector(1, 0, 0), math.radians(4)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState14 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 500), Quaternion(Vector(1, 0, 0), math.radians(6)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState15 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 500), Quaternion(Vector(1, 0, 0), math.radians(8)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState16 = RigidBodyState(Vector(0, 0, 200), Vector(0, 0, 344), Quaternion(Vector(1, 0, 0), math.radians(0)), AngularVelocity(rotationVector=Vector(0, 0, 0)))
def test_TabulatedAeroForce(self): # Init rocket that uses tabulated aero data simDef = SimDefinition("MAPLEAF/Examples/Simulations/NASATwoStageOrbitalRocket.mapleaf", silent=True) rocketDictReader = SubDictReader("Rocket", simDef) rocket = Rocket(rocketDictReader, silent=True) comp1, comp2, comp3 = rocket.stages[0].getComponentsOfType(TabulatedAeroForce) if comp1.Lref == 3.0: tabMoment = comp1 tabFOrce = comp2 else: tabMoment = comp2 tabForce = comp1 zeroAOAState = RigidBodyState(Vector(0,0,0), Vector(0,0,100), Quaternion(1,0,0,0), Vector(0,0,0)) # CD, CL, CMx, CMy, CMz expectedAero = [ 0.21, 0, 0, 0, 0 ] calculatedAero = tabForce._getAeroCoefficients(zeroAOAState, self.currentConditions) assertIterablesAlmostEqual(self, expectedAero, calculatedAero) expectedAero = [ 0, 0, 0, 0, 0 ] calculatedAero = tabMoment._getAeroCoefficients(zeroAOAState, self.currentConditions) assertIterablesAlmostEqual(self, expectedAero, calculatedAero)
def setUp(self): self.rocket = "fakeNewsRocket" # May have to convert this into a real Rocket at some point, but it's faster this way self.simDefinition = SimDefinition( "MAPLEAF/Examples/Simulations/Wind.mapleaf", silent=True) self.simDefinition.setValue("Environment.MeanWindModel", "Constant") envReader = SubDictReader("Environment", self.simDefinition) self.mWM = meanWindModelFactory(envReader, self.rocket)
def test_rocketCGCalculation(self): # Check actual CG Loc Calculation # Top stage CG: # # Nosecone: 1 kg @ 0m # Recovery: 5 kg @ -2m # BodyTube: 1 kg @ -0.762m # Mass: 50 kg @ -2.6m # Motor: 11.4885 kg @ 2.130434783 # Fins: 1 kg @ -4.011m # Total Weight = 69.4885 kg # Stage 1 CG: -2.4564359077698 expectedCG = Vector(0, 0, -1.731185736) # Remove overrides from rocket definition file simDef = SimDefinition("MAPLEAF/Examples/Simulations/Wind.mapleaf", silent=True) simDef.removeKey("Rocket.Sustainer.constCG") simDef.removeKey("Rocket.Sustainer.constMass") simDef.removeKey("Rocket.Sustainer.constMOI") rocketDictReader = SubDictReader("Rocket", simDef) rocket = Rocket(rocketDictReader, silent=True) rocketInertia = rocket.getInertia(0, rocket.rigidBody.state) assertVectorsAlmostEqual(self, rocketInertia.CG, expectedCG, n=4)
def test_customGust(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/Wind.mapleaf", silent=True) simDef.setValue("Environment.TurbulenceModel", "customSineGust") simDef.setValue("Environment.CustomSineGust.startAltitude", "0") simDef.setValue("Environment.CustomSineGust.magnitude", "9") simDef.setValue("Environment.CustomSineGust.sineBlendDistance", "30") simDef.setValue("Environment.CustomSineGust.thickness", "200") simDef.setValue("Environment.CustomSineGust.direction", "(0 1 0)") envReader = SubDictReader("Environment", simDef) turbModel = turbulenceModelFactory(envReader) v1 = turbModel.getTurbVelocity(0, Vector(1, 0, 0), 0) assertVectorsAlmostEqual(self, v1, Vector(0, 0, 0)) v1 = turbModel.getTurbVelocity(15, Vector(1, 0, 0), 0) assertVectorsAlmostEqual(self, v1, Vector(0, 4.5, 0)) v1 = turbModel.getTurbVelocity(30, Vector(1, 0, 0), 0) assertVectorsAlmostEqual(self, v1, Vector(0, 9, 0)) v1 = turbModel.getTurbVelocity(230, Vector(1, 0, 0), 0) assertVectorsAlmostEqual(self, v1, Vector(0, 9, 0)) v1 = turbModel.getTurbVelocity(245, Vector(1, 0, 0), 0) assertVectorsAlmostEqual(self, v1, Vector(0, 4.5, 0)) v1 = turbModel.getTurbVelocity(260, Vector(1, 0, 0), 0) assertVectorsAlmostEqual(self, v1, Vector(0, 0, 0))
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_SolidMotor(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/Jake1.mapleaf") rocketDictReader = SubDictReader("Rocket", simDef) motorRocket = Rocket(rocketDictReader) motor = motorRocket.stages[0].motor # Try getting thrust, if it works with 0 oxidizer flow rate, then we're good t = motor.getAppliedForce('fakeState', 0.12, 'fakeEnv', 'fakeCG').force.Z
def test_getFixedForceInertia(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] inertia = fixedForce.getInertia(0, "fakeState") expectedInertia = Inertia(Vector(0,0,0), Vector(0,0,0), 0) self.assertEqual(inertia, expectedInertia)
def test_MotorMOI(self): motorRocket = self.motorRocket motor = self.motorRocket.stages[0].getComponentsOfType( TabulatedMotor)[0] ### Oxidizer MOI Tests ### def getOxMOI(time): return motor._getOxInertia(time).MOI ActualOxMOI = getOxMOI(0) expectedOxMOI = Vector(1.0, 1.0, 0.1) assertIterablesAlmostEqual(self, ActualOxMOI, expectedOxMOI) ActualOxMOI = getOxMOI(2.505) expectedOxMOI = Vector(0.5, 0.5, 0.05) assertIterablesAlmostEqual(self, ActualOxMOI, expectedOxMOI) ActualOxMOI = getOxMOI(5.0) expectedOxMOI = Vector(0, 0, 0) assertIterablesAlmostEqual(self, ActualOxMOI, expectedOxMOI) ActualOxMOI = getOxMOI(10) expectedOxMOI = Vector(0, 0, 0) assertIterablesAlmostEqual(self, ActualOxMOI, expectedOxMOI) ### Fuel MOI Tests ### def getFuelMOI(time): return motor._getFuelInertia(time).MOI ActualFuelMOI = getFuelMOI(0) expectedFuelMOI = Vector(0.15, 0.15, 0.02) assertIterablesAlmostEqual(self, ActualFuelMOI, expectedFuelMOI) ActualFuelMOI = getFuelMOI(2.505) expectedFuelMOI = Vector(0.075, 0.075, 0.01) assertIterablesAlmostEqual(self, ActualFuelMOI, expectedFuelMOI) ActualFuelMOI = getFuelMOI(5) expectedFuelMOI = Vector(0, 0, 0) assertIterablesAlmostEqual(self, ActualFuelMOI, expectedFuelMOI) ActualFuelMOI = getFuelMOI(10) expectedFuelMOI = Vector(0, 0, 0) assertIterablesAlmostEqual(self, ActualFuelMOI, expectedFuelMOI) simDef = SimDefinition("MAPLEAF/Examples/Simulations/Jake1.mapleaf") rocketDictReader = SubDictReader("Rocket", simDef) jakeRocket = Rocket(rocketDictReader) motor = jakeRocket.stages[0].motor motorInertia = motor.getInertia(3, jakeRocket.rigidBody.state) expectedInertiaAfterBurnout = Inertia(Vector(0, 0, 0), Vector(0, 0, 0), 0.0) assertInertiasAlmostEqual(self, motorInertia, expectedInertiaAfterBurnout)
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 optimizationRunnerFactory(simDefinitionFilePath=None, simDefinition=None, optimizationReader=None, silent=False, parallel=False) -> OptimizingSimRunner: ''' Provide a subdictionary reader pointed at an optimization dictionary. Will read the dictionary, initialize an optimizing simulation runner and return it. ''' if simDefinition != None or simDefinitionFilePath != None: simDefinition = loadSimDefinition(simDefinitionFilePath, simDefinition, silent) optimizationReader = SubDictReader('Optimization', simDefinition) # Ensure no output is produced during each simulation (cost function evaluation) simDefinition.setValue("SimControl.plot", "None") simDefinition.setValue("SimControl.RocketPlot", "Off") else: if optimizationReader == None: raise ValueError('subDictReader not initialized for a nested optimization') method = optimizationReader.tryGetString('method', defaultValue='PSO') if method == 'PSO': return PSORunner(optimizationReader, silent=silent, parallel=parallel) elif 'scipy.optimize.minimize' in method: return ScipyMinimizeRunner(optimizationReader, silent=silent, parallel=parallel) else: raise ValueError('Optimization method: {} not implemented, try PSO'.format(method))
def rocketComponentFactory(subDictPath, rocket, stage): """ Initializes a rocket component based on the stringNameToClassMap Inputs: subDictPath: (string) Path to subDict in simulation definition, like "Rocket.Stage1.Nosecone" rocket: (Rocket) that the component is a part of stage: (Stage) That the component is a part of Also uses the stringNameToClassMap dictionary """ # Create SubDictReader for the rocket component's dictionary componentDictReader = SubDictReader(subDictPath, rocket.simDefinition) # Figure out which class to initialize className = componentDictReader.getString("class") referencedClass = stringNameToClassMap[className] # Initialize the rocket component newComponent = referencedClass(componentDictReader, rocket, stage) # Initialize logging component forces (if desired) initializeForceLogging(newComponent, subDictPath, rocket) return newComponent
def integratorFactory(integrationMethod="Euler", simDefinition=None, discardedTimeStepCallback=None): ''' Returns a callable integrator object Inputs: * integrationMethod: (str) Name of integration method: Examples = "Euler", "RK4", "RK23Adaptive", and "RK45Adaptive" * simDefinition: (`MAPLEAF.IO.SimDefinition`) for adaptive integration, provide a simdefinition file with time step adaptation parameters * discardedTimeStepCallback: (1-argument function reference) for adaptive integration, this function (if provided) is called when a time step is computed, but then discarded and re-computed with a smaller timestep to remain below the max estimated error threshold. Used by MAPLEAF to remove force calculation logs from those discarded time steps ''' if "Adapt" in integrationMethod: if simDefinition == None: raise ValueError("SimDefinition object required to initialize adaptive integrator") from MAPLEAF.IO import SubDictReader adaptDictReader = SubDictReader("SimControl.TimeStepAdaptation", simDefinition) # Adaptive Integration controller = adaptDictReader.getString("controller") if controller == "PID": PIDCoeffs = [ float(x) for x in adaptDictReader.getString("PID.coefficients").split() ] safetyFactor = None elif controller == "elementary": safetyFactor = adaptDictReader.getFloat("Elementary.safetyFactor") PIDCoeffs = None targetError = adaptDictReader.getFloat("targetError") minFactor = adaptDictReader.getFloat("minFactor") maxFactor = adaptDictReader.getFloat("maxFactor") maxTimeStep = adaptDictReader.getFloat("maxTimeStep") minTimeStep = adaptDictReader.getFloat("minTimeStep") return AdaptiveIntegrator( method=integrationMethod, controller=controller, targetError=targetError, maxMinSafetyFactors=[maxFactor, minFactor, safetyFactor], PIDCoeffs=PIDCoeffs, maxTimeStep=maxTimeStep, minTimeStep=minTimeStep, discardedTimeStepCallback=discardedTimeStepCallback ) else: # Constant time step integrator return ClassicalIntegrator(method=integrationMethod)
def setUp(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/test3.mapleaf", silent=True) rocketDictReader = SubDictReader("Rocket", simDef) self.rocket = Rocket(rocketDictReader, silent=True) self.nosecone = self.rocket.stages[0].getComponentsOfType(NoseCone)[0] self.bodytube = self.rocket.stages[0].getComponentsOfType(BodyTube)[0] # Find the Fixed Mass component that's actually just a Fixed Mass, not a child class (Nosecone, Bodytube) fixedMassComponents = self.rocket.stages[0].getComponentsOfType(FixedMass) for comp in fixedMassComponents: if type(comp) == FixedMass: self.fixedMass = comp self.environment = Environment(silent=True) self.currentConditions = self.environment.getAirProperties(Vector(0,0,200)) # m
def createRocket(self, stage=None): ''' Initializes a rocket, complete with an Environment object and logs, both owned by the instance of this class Returns an instance of Rocket with it's Environment/Logs initialized. Can be called by external classes to obtain a prepped rocket (used a lot this way in test cases). ''' # Initialize Rocket rocketDictReader = SubDictReader("Rocket", self.simDefinition) rocket = Rocket(rocketDictReader, silent=self.silent, stageToInitialize=stage, simRunner=self, environment=self.environment) # Initialize Rocket if self.simDefinition.getValue('SimControl.RocketPlot') in [ 'On', 'on' ]: rocket.plotShape() # Reference to this simRunner used to add to logs if stage == None: self._setUpConsoleLogging() self.stagingIndex = 0 # Initially zero, after dropping first stage: 1, after dropping second stage: 2, etc... return rocket
def test_pinkNoiseStdDev(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/Wind.mapleaf", silent=True) simDef.setValue("Environment.TurbulenceModel", "PinkNoise1D") simDef.setValue("Environment.PinkNoiseModel.velocityStdDeviation", "1") simDef.setValue("Environment.PinkNoiseModel.randomSeed1", "63583") simDef.setValue("Environment.turbulenceOffWhenUnderChute", "False") # Make sure turbulence intensity is not present since it overrides the given std deviation simDef.removeKey("Environment.PinkNoiseModel.turbulenceIntensity") envReader = SubDictReader("Environment", simDef) turbModel = turbulenceModelFactory(envReader) v1 = turbModel.getTurbVelocity(1, Vector(1, 0, 0), None) self.assertAlmostEqual(v1[0], 0.7946604314895807 / 2.26) v2 = turbModel.getTurbVelocity(1, Vector(1, 0, 0), None) self.assertAlmostEqual(v2[0], 0.5874110050866364 / 2.26)
def test_rocketInertiaOverrides(self): # Check CG Override simDef = SimDefinition("MAPLEAF/Examples/Simulations/Wind.mapleaf") rocketDictReader = SubDictReader("Rocket", simDef) rocket = Rocket(rocketDictReader, silent=True) cgLoc = rocket.getCG(0, rocket.rigidBody.state) expectedCGLoc = Vector(0, 0, -2.65) assertVectorsAlmostEqual(self, cgLoc, expectedCGLoc) # Check Mass override expectedMass = 50 actualMass = rocket.getMass(0, rocket.rigidBody.state) self.assertAlmostEqual(actualMass, expectedMass) # Check MOI Override + getInertia function expectedMOI = Vector(85, 85, 0.5) actualInertia = rocket.getInertia(0, rocket.rigidBody.state) assertVectorsAlmostEqual(self, actualInertia.MOI, expectedMOI) assertVectorsAlmostEqual(self, actualInertia.CG, expectedCGLoc) self.assertAlmostEqual(actualInertia.mass, expectedMass)
def setUp(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/test3.mapleaf") rocketDictReader = SubDictReader("Rocket", simDef) self.rocket = Rocket(rocketDictReader) self.environment = Environment(silent=True) self.currentConditions = self.environment.getAirProperties( Vector(0, 0, 200)) # m self.rocketState1 = RigidBodyState( Vector(0, 0, 200), Vector(0, 0, 200), Quaternion(Vector(0, 0, 1), 0), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState2 = RigidBodyState( Vector(0, 0, 200), Vector(0, 0, 200), Quaternion(Vector(1, 0, 0), math.radians(2)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState3 = RigidBodyState( Vector(0, 0, 200), Vector(0, 0, 500), Quaternion(Vector(1, 0, 0), math.radians(2)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState4 = RigidBodyState( Vector(0, 0, 200), Vector(0, 0, -200), Quaternion(Vector(1, 0, 0), math.radians(180)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState5 = RigidBodyState( Vector(0, 0, 200), Vector(0, 0, -200), Quaternion(Vector(1, 0, 0), math.radians(178)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState6 = RigidBodyState( Vector(0, 0, 200), Vector(0, 0, -200), Quaternion(Vector(1, 0, 0), math.radians(182)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState7 = RigidBodyState( Vector(0, 0, 200), Vector(0, 0, -200), Quaternion(Vector(1, 0, 0), math.radians(90)), AngularVelocity(rotationVector=Vector(0, 0, 0))) self.rocketState8 = RigidBodyState( Vector(0, 0, 200), Vector(20.04, -0.12, -52.78), Quaternion(Vector(0, 1, 0), math.radians(90)), AngularVelocity(rotationVector=Vector(0, 0, 0)))
def test_controlTimeStepChecking(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/Canards.mapleaf", silent=True) simDef.setValue("SimControl.timeDiscretization", "Euler") simDef.setValue("SimControl.loggingLevel", "0") simDef.setValue("SimControl.timeStep", "0.01") simDef.setValue("Rocket.ControlSystem.updateRate", "101") rocketDictReader = SubDictReader("Rocket", simDef) # controlledCanardRocket = Rocket(rocketDictReader, silent=True) # self.assertAlmostEqual(controlledCanardRocket.controlSystem.controlTimeStep, 1/101) simDef.setValue("SimControl.timeStep", "0.011") simDef.setValue("Rocket.ControlSystem.updateRate", "100") controlledCanardRocket = Rocket(rocketDictReader, silent=True) self.assertAlmostEqual( controlledCanardRocket.controlSystem.controlTimeStep, 1 / 100) # simDef.setValue("SimControl.timeStep", "0.009") # controlledCanardRocket = Rocket(rocketDictReader, silent=True) # self.assertAlmostEqual(controlledCanardRocket.controlSystem.controlTimeStep, 1/100) # simDef.setValue("SimControl.timeStep", "0.1") # controlledCanardRocket = Rocket(rocketDictReader, silent=True) # self.assertAlmostEqual(controlledCanardRocket.controlSystem.controlTimeStep, 1/100) simDef.setValue("SimControl.timeStep", "0.001") simDef.setValue("SimControl.timeDiscretization", "RK45Adaptive") simDef.setValue("SimControl.TimeStepAdaptation.controller", "PID") simDef.setValue("Rocket.ControlSystem.updateRate", "100") controlledCanardRocket = Rocket(rocketDictReader, silent=True) self.assertEqual(controlledCanardRocket.rigidBody.integrate.method, "RK4") self.assertEqual(type(controlledCanardRocket.rigidBody.integrate), ClassicalIntegrator) self.assertEqual(controlledCanardRocket.controlSystem.controlTimeStep, 1 / 100)
def _createOptimizer(self): ''' Reads the Optimization.ParticleSwarm dictionary and creates a pyswarms.GlobalBestPSO object Returns the Optimizer, the user's desired number of iterations, and showConvergence (bool) ''' pathToParticleSwarmDict = self.optimizationReader.simDefDictPathToReadFrom + '.ParticleSwarm' pSwarmReader = SubDictReader(pathToParticleSwarmDict, self.optimizationReader.simDefinition) nParticles = pSwarmReader.tryGetInt("nParticles", defaultValue=20) nIterations = pSwarmReader.tryGetInt("nIterations", defaultValue=50) c1 = pSwarmReader.tryGetFloat("cognitiveParam", defaultValue=0.5) c2 = pSwarmReader.tryGetFloat("socialParam", defaultValue=0.6) w = pSwarmReader.tryGetFloat("inertiaParam", defaultValue=0.9) pySwarmOptions = { 'c1':c1, 'c2':c2, 'w':w } nVars = len(self.varNames) varBounds = (self.minVals, self.maxVals) from pyswarms.single import \ GlobalBestPSO # Import here because for most sims it's not required optimizer = GlobalBestPSO(nParticles, nVars, pySwarmOptions, bounds=varBounds, init_pos=self.initPositions) if self.bestPosition != None and self.bestCost != None: optimizer.swarm.best_pos = self.bestPosition optimizer.swarm.best_cost = self.bestCost showConvergence = self.optimizationReader.tryGetBool("showConvergencePlot", defaultValue=False) if not self.silent: print("Optimization Parameters:") print("{} Particles".format(nParticles)) print("{} Iterations".format(nIterations)) print("c1 = {}, c2 = {}, w = {}\n".format(c1, c2, w)) costFunctionDefinition = self.optimizationReader.getString("costFunction") print("Cost Function:") print(costFunctionDefinition + "\n") return optimizer, nIterations, showConvergence
def __init__(self, rocketDictReader, silent=False, stageToInitialize=None, simRunner=None, environment=None): ''' Initialization of Rocket(s) is most easily completed through an instance of Simulation To get a single Rocket object, initialize a Simulation and call `MAPLEAF.SimulationRunners.Simulation.createRocket()`. This will return a Rocket initialized on the pad with all its stages, ready for flight. If initializing manually, can either provide fileName or simDefinition. If a simDefinition is provided, it will be used and fileName will be ignored. Inputs: * rocketDictReader: (`MAPLEAF.IO.SubDictReader`) SubDictReader pointed at the "Rocket" dictionary of the desired simulation definition file. * silent: (bool) controls console output * stageToInitialize: (int or None) controls whether to initialize a complete Rocket or a single (usually dropped) stage. None = initialize complete rocket. n = initialize only stage n, where n >= 1. * simRunner: (`MAPLEAF.SimulationRunners.Simulation`) reference to the current simulation driver/runner * environment: (`MAPLEAF.ENV.Environment`) environment model from which the rocket will retrieve atmospheric properties and wind speeds ''' self.rocketDictReader = rocketDictReader self.simDefinition = rocketDictReader.simDefinition self.simRunner = simRunner ''' Parent instance of `MAPLEAF.SimulationRunners.Simulation` (or derivative sim runner). This is usually the object that has created the current instance of Rocket. ''' self.environment = environment ''' Instance of `MAPLEAF.ENV.Environment` ''' if self.environment == None: # If no environment is passed in, create one self.environment = Environment(self.simDefinition, silent=silent) self.name = rocketDictReader.getString("name") self.silent = silent ''' Controls output to console ''' self.stage = stageToInitialize ''' If controls whether the whole rocket is initialized (if == None), or a single stage is initialized (Integer stage number) ''' self.stages = [] ''' A list of `MAPLEAF.Rocket.Stage` objects that make up the rocket, ordered from top to bottom. Populated by `_initializeStages`. ''' self.recoverySystem = None ''' Reference to the current Rocket's (which can represent a dropped stage) recovery system. Only a single recovery system is allowed per stage. Set in `MAPLEAF.Rocket.RecoverySystem.__init__` ''' self.rigidBody = None ''' (`MAPLEAF.Motion.RigidBody` or `MAPLEAF.Motion.RigidBody_3DoF`) Responsible for motion integration. Set in `_initializeRigidBody()`. ''' self.isUnderChute = False ''' (bool) Controlled by `MAPLEAF.Rocket.Recovery.RecoverySystem._deployNextStage()` ''' self.mainChuteDeployTime = None ''' (float) Filled in during flight by `MAPLEAF.Rocket.Recovery.RecoverySystem._deployNextStage()` ''' self.engineShutOffTime = None ''' (float) Filled in by `MAPLEAF.Rocket.Propulsion.TabulatedMotor.__init__()` upon initialization ''' self.turbulenceOffWhenUnderChute = rocketDictReader.getBool("Environment.turbulenceOffWhenUnderChute") ''' (bool) ''' self.maxDiameter = self._getMaxBodyTubeDiameter() ''' (float) Holds maximum constant-size body tube diameter, from bodytube components in stages ''' self.Aref = math.pi * self.maxDiameter**2 / 4 ''' Reference area for force and moment coefficients. Maximum rocket cross-sectional area. Remains constant during flight to retain a 1:1 relationship b/w coefficients in different parts of flight. Always based on the maximum body tube diameter in the fully-assembled rocket. ''' # TODO: Remove self.targetLocation = None self.simEventDetector = SimEventDetector(self) ''' (`MAPLEAF.Rocket.SimEventDetector`) Used to trigger things like recovery systems and staging ''' self.eventTimeStep = rocketDictReader.getFloat("SimControl.TimeStepAdaptation.eventTimingAccuracy") ''' If using an adaptive time stepping method, the time step will be overridden near non-time-deterministic discrete events, possibly all the way down to this minimum value ''' self.addZeroLengthBoatTailsToAccountForBaseDrag = rocketDictReader.getBool("Aero.addZeroLengthBoatTailsToAccountForBaseDrag") ''' Controls whether zero-length boat tails are automatically added to the bottom of rockets without them, to make sure base drag is accounted for ''' self.fullyTurbulentBL = rocketDictReader.getBool("Aero.fullyTurbulentBL") ''' Controls whether skin friction is solved assuming a fully turbulent BL or using laminar/transitional flow at lower Reynolds numbers ''' self.surfaceRoughness = rocketDictReader.getFloat("Aero.surfaceRoughness") ''' Default surface roughness for all rocket components ''' self.finenessRatio = None ''' Used in some aerodynamic functions. Updated after initializing subcomponents, and throughout the flight. None if no BodyComponent(s) are present in the rocket ''' self.engineShutOff = False '''Used to shut off engines in MAPLEAF.Rocket.Propulsion.DefinedMotor class. Currently set in MAPLE_AF.GNC.Navigation''' #### Init Hardware in the loop #### subDicts = rocketDictReader.getImmediateSubDicts() if "Rocket.HIL" in subDicts: self.hardwareInTheLoopControl = "yes" quatUpdateRate = rocketDictReader.getInt("HIL.quatUpdateRate") posUpdateRate = rocketDictReader.getInt("HIL.posUpdateRate") velUpdateRate = rocketDictReader.getInt("HIL.velUpdateRate") teensyComPort = rocketDictReader.getString("HIL.teensyComPort") imuComPort = rocketDictReader.getString("HIL.imuComPort") teensyBaudrate = rocketDictReader.getInt("HIL.teensyBaudrate") imuBaudrate = rocketDictReader.getInt("HIL.imuBaudrate") self.hilInterface = HILInterface(quatUpdateRate,posUpdateRate,velUpdateRate, teensyComPort, imuComPort, teensyBaudrate, imuBaudrate) else: self.hardwareInTheLoopControl = "no" #### Initialize Logging #### self.timeStepLog = None ''' Log containing one entry per time step, logs rocket state. None if logging level == 0 ''' self.derivativeEvaluationLog = None ''' Log containing one entry per rocket motion derivative evaluation, contains component forces. None if logging level < 2 ''' loggingLevel = int(self.simDefinition.getValue("SimControl.loggingLevel")) self.loggingLevel = loggingLevel if loggingLevel > 0: # Create the time step log and add columns to track the rocket state between each time step self.timeStepLog = TimeStepLog() zeroVector = Vector(0,0,0) self.timeStepLog.addColumn("Position(m)", zeroVector) self.timeStepLog.addColumn("Velocity(m/s)", zeroVector) self.timeStepLog.addColumn("OrientationQuaternion", Quaternion(0,0,0,0)) self.timeStepLog.addColumn("EulerAngle(rad)", zeroVector) self.timeStepLog.addColumn("AngularVelocity(rad/s)", zeroVector) if "Adapt" in self.simDefinition.getValue("SimControl.timeDiscretization"): self.timeStepLog.addColumn("EstimatedIntegrationError", 0) if loggingLevel > 1: self.derivativeEvaluationLog = Log() zeroVector = Vector(0,0,0) self.derivativeEvaluationLog.addColumn("Position(m)", zeroVector) self.derivativeEvaluationLog.addColumn("Velocity(m/s)", zeroVector) self.derivativeEvaluationLog.addColumn("OrientationQuaternion", Quaternion(0,0,0,0)) self.derivativeEvaluationLog.addColumn("AngularVelocity(rad/s)", zeroVector) self.derivativeEvaluationLog.addColumn("CG(m)", zeroVector) self.derivativeEvaluationLog.addColumn("MOI(kg*m^2)", zeroVector) self.derivativeEvaluationLog.addColumn("Mass(kg)", 0) self.derivativeEvaluationLog.addColumn("Wind(m/s)", zeroVector) self.derivativeEvaluationLog.addColumn("AirDensity(kg/m^3)", 0) self.derivativeEvaluationLog.addColumn("Mach", 0) self.derivativeEvaluationLog.addColumn("UnitRe", 0) self.derivativeEvaluationLog.addColumn("AOA(deg)", 0) self.derivativeEvaluationLog.addColumn("RollAngle(deg)", 0) self.derivativeEvaluationLog.addColumn("CPZ(m)", 0) self.derivativeEvaluationLog.addColumn("AeroF(N)", zeroVector) self.derivativeEvaluationLog.addColumn("AeroM(Nm)", zeroVector) self.derivativeEvaluationLog.addColumn("GravityF(N)", zeroVector) self.derivativeEvaluationLog.addColumn("TotalF(N)", zeroVector) #### Init Components #### self._createStages() self._initializeRigidBody() self._switchToStatefulRigidBodyIfRequired() self._sortStagesAndComponents() self._initializeStagingTriggers() self._precomputeComponentProperties() #### Init Parent classes #### CompositeObject.__init__(self, self.stages) self._updateFinenessRatio() # Adjust rigid body state position to correspond to the rocket's CG instead of nose cone tip position self._moveStatePositionToCG() #### Init Guidance/Navigation/Control System (if required) #### self.controlSystem = None ''' None for uncontrolled rockets. `MAPLEAF.GNC.ControlSystems.RocketControlSystem` for controlled rockets ''' if ( rocketDictReader.tryGetString("ControlSystem.controlledSystem") != None or rocketDictReader.tryGetString("ControlSystem.MomentController.Type") == "IdealMomentController") and stageToInitialize == None: # Only create a control system if this is NOT a dropped stage ControlSystemDictReader = SubDictReader("Rocket.ControlSystem", simDefinition=self.simDefinition) controlSystemLogging = loggingLevel > 3 self.controlSystem = RocketControlSystem(ControlSystemDictReader, self, log=controlSystemLogging, silent=silent)
def setUp(self): simDef = SimDefinition("MAPLEAF/Examples/Simulations/test2.mapleaf") rocketDictReader = SubDictReader("Rocket", simDef) self.motorRocket = Rocket(rocketDictReader)
def __init__(self, simDefinition=None, silent=False): ''' Sets up the Wind, Atmospheric, and Earth models requested in the Sim Definition file ''' self.launchRail = None if simDefinition != None: # Whenever we're running a real simulation, should always end up here envDictReader = SubDictReader("Environment", simDefinition) self.meanWindModel = meanWindModelFactory(envDictReader, silent=silent) self.turbulenceModel = turbulenceModelFactory(envDictReader, silent=silent) self.atmosphericModel = atmosphericModelFactory(envDictReader=envDictReader) self.earthModel = earthModelFactory(envDictReader) self.launchSiteElevation = envDictReader.tryGetFloat("LaunchSite.elevation") self.launchSiteLatitude = envDictReader.tryGetFloat("LaunchSite.latitude") self.launchSiteLongitude = envDictReader.tryGetFloat("LaunchSite.longitude") # Check if being launched from a launch rail launchRailLength = envDictReader.getFloat("LaunchSite.railLength") if launchRailLength > 0: # Initialize a launch rail, aligned with the rocket's initial direction initialRocketPosition_towerFrame = envDictReader.getVector("Rocket.position") # Check whether precise initial orientation has been specified rotationAxis = envDictReader.tryGetVector("Rocket.rotationAxis", defaultValue=None) if rotationAxis != None: rotationAngle = math.radians(envDictReader.getFloat("Rocket.rotationAngle")) initOrientation = Quaternion(rotationAxis, rotationAngle) else: # Calculate initial orientation quaternion in launch tower frame rotationAxis = envDictReader.tryGetVector("Rocket.rotationAxis", defaultValue=None) if rotationAxis != None: rotationAngle = math.radians(self.rocketDictReader.getFloat("Rocket.rotationAngle")) initOrientation = Quaternion(rotationAxis, rotationAngle) else: # Calculate initial orientation quaternion in launch tower frame initialDirection = envDictReader.getVector("Rocket.initialDirection").normalize() angleFromVertical = Vector(0,0,1).angle(initialDirection) rotationAxis = Vector(0,0,1).crossProduct(initialDirection) initOrientation = Quaternion(rotationAxis, angleFromVertical) # TODO: Get from rocket, or calculate the same way - so that it works with rotationAxis + Angle initialDirection = envDictReader.getVector("Rocket.initialDirection").normalize() angleFromVertical = Vector(0,0,1).angle(initialDirection) rotationAxis = Vector(0,0,1).crossProduct(initialDirection) initOrientation = Quaternion(rotationAxis, angleFromVertical) initPosition_seaLevelENUFrame = initialRocketPosition_towerFrame + Vector(0, 0, self.launchSiteElevation) launchTowerState_local = RigidBodyState(position=initPosition_seaLevelENUFrame, orientation=initOrientation) launchTowerState_global = self.earthModel.convertIntoGlobalFrame(launchTowerState_local, self.launchSiteLatitude, self.launchSiteLongitude) towerDirection_global = launchTowerState_global.orientation.rotate(Vector(0, 0, 1)) self.launchRail = LaunchRail(launchTowerState_global.position, towerDirection_global, launchRailLength, earthRotationRate=self.earthModel.rotationRate) else: # Construct default environment from default parameters when no sim definition is passed in # Need additional default value here in case a SimDefinition is not passed in (otherwise SimDefinition takes care of default values) self.meanWindModel = meanWindModelFactory() self.turbulenceModel = None self.atmosphericModel = atmosphericModelFactory() self.earthModel = earthModelFactory() self.launchSiteElevation = float(defaultConfigValues["Environment.LaunchSite.elevation"]) self.launchSiteLatitude = float(defaultConfigValues["Environment.LaunchSite.latitude"]) self.launchSiteLongitude = float(defaultConfigValues["Environment.LaunchSite.longitude"])
def setUp(self): self.rocket = "fakeNewsRocket" # May have to convert this into a real Rocket at some point, but it's faster this way self.simDefinition = SimDefinition( "MAPLEAF/Examples/Simulations/Wind.mapleaf", silent=True) self.envReader = SubDictReader("Environment", self.simDefinition)
def _createNestedOptimization(self, simDef): innerOptimizationReader = SubDictReader(self.optimizationReader.simDefDictPathToReadFrom + '.InnerOptimization', simDef) return optimizationRunnerFactory(optimizationReader=innerOptimizationReader, silent=self.silent, parallel=self.parallel)