コード例 #1
0
    def __init__(self,
                 propelant_anim=None,
                 initial_position_x=0,
                 nave_azul=None,
                 nave_preta=None,
                 nave_amarela=None):
        self.dead = False
        self.move_x = 0
        self.move_y = 70
        self.position_x = initial_position_x
        self.behavior = self.rand_behavior()
        self.skin_azul = nave_azul
        self.skin_amarela = nave_amarela
        self.skin_preta = nave_preta
        if self.behavior == "ZigZag":
            self.rand_zigzag_range = randint(8, 40)
            self.zig_x_1 = self.move_x + self.position_x - self.rand_zigzag_range
            self.zig_x_2 = self.move_x + self.position_x + self.rand_zigzag_range
        self.current_direction = DIRECTION_RIGHT
        self.elapsed_shoot_time = 0
        self.nave_type = randint(0, 2)

        self.shoot_type_rand = randint(1, 10)
        if self.shoot_type_rand >= 1 and self.shoot_type_rand <= 5:
            self.shoot_type = 1
        elif self.shoot_type_rand >= 6 and self.shoot_type_rand <= 8:
            self.shoot_type = 2
        else:
            self.shoot_type = 3

        self.propellant = Propellant(propelant_anim, self.position_x,
                                     self.move_y + 12, "enemy")
        self.moving_right = False
        self.moving_left = False
コード例 #2
0
    def load(self, initial_position_x, propellant_anim, nave_azul,
             nave_amarela, nave_preta):
        self.dead = False
        self.move_x = 0
        self.move_y = 70
        self.position_x = initial_position_x
        self.skin_azul = nave_azul
        self.skin_amarela = nave_amarela
        self.skin_preta = nave_preta
        self.behavior = self.rand_behavior()
        if self.behavior == "ZigZag":
            self.rand_zigzag_range = randint(8, 40)
            self.zig_x_1 = self.move_x + self.position_x - self.rand_zigzag_range
            self.zig_x_2 = self.move_x + self.position_x + self.rand_zigzag_range
        self.current_direction = DIRECTION_RIGHT
        self.elapsed_shoot_time = 0
        self.nave_type = randint(0, 2)

        self.shoot_type_rand = randint(1, 10)
        if 1 <= self.shoot_type_rand <= 5:
            self.shoot_type = 1
        elif 6 <= self.shoot_type_rand <= 8:
            self.shoot_type = 2
        else:
            self.shoot_type = 3

        self.propellant = Propellant(propellant_anim, self.position_x,
                                     self.move_y + 16.7, "enemy")
コード例 #3
0
 def __init__(self, propellant_anim, initial_position):
     self.dead = False
     self.move_x = 0
     self.moving_left = False
     self.moving_right = False
     self.shooting = False
     self.speed = 0
     self.position_x = initial_position
     self.imageID = self.loadImage()
     self.propellant = Propellant(propellant_anim, self.position_x, -43.3,
                                  "player")
コード例 #4
0
 def applyDict(self, dictionary):
     """Makes the motor copy properties from the dictionary that is passed in, which must be formatted like
     the result passed out by 'getDict'"""
     self.nozzle.setProperties(dictionary['nozzle'])
     if dictionary['propellant'] is not None:
         self.propellant = Propellant(dictionary['propellant'])
     else:
         self.propellant = None
     self.grains = []
     for entry in dictionary['grains']:
         self.grains.append(grainTypes[entry['type']]())
         self.grains[-1].setProperties(entry['properties'])
     self.config.setProperties(dictionary['config'])
コード例 #5
0
    def init_queue(self):

        for i in range(20):
            new = Enemy()
            self.enemy_queue.push(new)

        for i in range(50):
            new = Asteroide()
            self.asteroid_queue.push(new)

        for i in range(100):
            new = Shoot()
            self.bullets_queue.push(new)

        for i in range(10):
            new = Planeta()
            self.planets_queue.push(new)

        for i in range(50):
            new = Explode()
            self.explosion_queue.push(new)

        for i in range(30):
            new = Propellant()
            self.propellant_queue.push(new)

        for i in range(20):
            new = Power_up()
            self.power_queue.push(new)
コード例 #6
0
    def init_queue(self):

        for i in range(10):
            new = Enemy()
            self.enemy_queue.push(new)

        for i in range(10):
            new = Asteroide()
            self.asteroid_queue.push(new)

        for i in range(50):
            new = Shoot()
            self.bullets_queue.push(new)

        for i in range(3):
            new = Flor()
            self.flowers_queue.push(new)

        for i in range(5):
            new = Planeta()
            self.planets_queue.push(new)

        for i in range(21):
            new = Explode()
            self.explosion_queue.push(new)

        for i in range(11):
            new = Propellant()
            self.propellant_queue.push(new)
コード例 #7
0
ファイル: flight.py プロジェクト: cuspaceflight/midas
def make_panthera(temperature, of_ratio, ox_tank_volume=None, ox_mass=110):
    # A test with 30s burn time on White Giant

    aluminium = Material(2700, 270e6)

    nitrous_density = nitrous_thermophys(temperature)["rho_l"]
    ipa_density = ipa_thermophys(temperature)["rho_l"]

    # Densities multiplied by 0.9 to allow for ullage space
    if ox_tank_volume == None and (type(ox_mass) == int
                                   or type(ox_mass) == float):
        # We are doing a mass-driven rocket. Mass of propellant is fixed, size is not
        ox_tank_volume = ox_mass / (nitrous_density * 0.9)

        fuel_mass = ox_mass * (1 / (1 + of_ratio))
        fuel_tank_volume = fuel_mass / (ipa_density * 0.9)

    elif ox_mass == None and (type(ox_tank_volume) == int
                              or type(ox_tank_volume) == float):
        # We are doing a volume-driven rocket. Volume of tanks (and thus) height of tanks) is fixed, mass is not
        fuel_mass = ox_mass * (1 / (1 + of_ratio))

        ox_mass = ox_tank_volume * (nitrous_density * 0.9)
        fuel_tank_volume = fuel_mass / (ipa_density * 0.9)

    nitrous = Propellant("nitrous-self-pressurised", temperature,
                         ox_tank_volume, ox_mass)
    ipa = Propellant("ipa-helium-pressurised", temperature, fuel_tank_volume,
                     fuel_mass, nitrous.pressure)

    # Recommended to have a 20-25% pressure drop across the injector, rounded up to 30% to account for additional plumbing pressure losses
    # This is equal to a loss of 25% of upstream pressure
    # Replace this with actual design data at a later date

    chamber_pressure = nitrous.pressure * 0.5

    target_ox_flow = 3.25
    target_fuel_flow = target_ox_flow * (1 / (1 + of_ratio))

    white_giant = LiquidEngine("ipa-helium-pressurised",
                               "nitrous-self-pressurised", chamber_pressure,
                               target_ox_flow + target_fuel_flow, of_ratio, 4,
                               0.15)
    #white_giant.construct_injector(nitrous.pressure, nitrous.temperature, ipa.pressure, ipa.temperature)

    panthera = Rocket(ipa, nitrous, aluminium, white_giant, 10, 0.15)
    return (panthera)
コード例 #8
0
class Enemy():
    # Inicia os parametros
    # self.dead = define se o objeto deve ser desenhado
    # self.move_x = controla o movimento no eixo x
    # self.move_y = controla o movimento no eixo y, inicia fora da tela (70)
    # self.position_x = define a posição inical do inimigo
    # self.beahavior = define o comportamento sobre a movimentação do inimigo
    # self.skin_* = Texturas pre carregadas
    # self.ran_zigzag = define o alcance do movimento em zig zag
    # self.current_direction = indica a direção atual que ele está
    # self.elapsed_shoot_time = indica o tempo desde o ultimo tiro
    # self.nave_type = Textura da nave
    # self.shoot_type_rand = define a quantidade de tiros que o inimigo pode atirar
    # self.propellant = Objeto "propulsor" da nave
    def __init__(self,
                 propelant_anim=None,
                 initial_position_x=0,
                 nave_azul=None,
                 nave_preta=None,
                 nave_amarela=None):
        self.dead = False
        self.move_x = 0
        self.move_y = 70
        self.position_x = initial_position_x
        self.behavior = self.rand_behavior()
        self.skin_azul = nave_azul
        self.skin_amarela = nave_amarela
        self.skin_preta = nave_preta
        if self.behavior == "ZigZag":
            self.rand_zigzag_range = randint(8, 40)
            self.zig_x_1 = self.move_x + self.position_x - self.rand_zigzag_range
            self.zig_x_2 = self.move_x + self.position_x + self.rand_zigzag_range
        self.current_direction = DIRECTION_RIGHT
        self.elapsed_shoot_time = 0
        self.nave_type = randint(0, 2)

        self.shoot_type_rand = randint(1, 10)
        if self.shoot_type_rand >= 1 and self.shoot_type_rand <= 5:
            self.shoot_type = 1
        elif self.shoot_type_rand >= 6 and self.shoot_type_rand <= 8:
            self.shoot_type = 2
        else:
            self.shoot_type = 3

        self.propellant = Propellant(propelant_anim, self.position_x,
                                     self.move_y + 12, "enemy")
        self.moving_right = False
        self.moving_left = False

    # Descreve como o objeto deve ser desenhado
    def draw(self):
        # self.propellant.draw()
        #
        glColor3f(1.0, 1.0, 1.0)
        # glDisable(GL_LIGHTING)
        glEnable(GL_TEXTURE_2D)

        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
        glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

        if self.nave_type == 0:
            glBindTexture(GL_TEXTURE_2D, self.skin_azul)
        elif self.nave_type == 1:
            glBindTexture(GL_TEXTURE_2D, self.skin_amarela)
        elif self.nave_type == 2:
            glBindTexture(GL_TEXTURE_2D, self.skin_preta)

        glPushMatrix()

        # glBegin(GL_QUADS)
        # glTexCoord2f(0, 1)
        # glVertex3f(self.move_x + self.position_x -4.0,
        #            self.move_y, 0)
        # glTexCoord2f(1, 1)
        # glVertex3f(self.move_x + self.position_x +4.0,
        #            self.move_y, 0)
        # glTexCoord2f(1, 0)
        #
        # glVertex3f(self.move_x + self.position_x + 4.0,
        #            self.move_y + 12, 0)
        # glTexCoord2f(0, 0)
        # glVertex3f(self.move_x + self.position_x - 4.0,
        #            self.move_y + 12, 0)
        # glEnd()

        if self.moving_right:
            glRotate(10, 0.1, 0.7, 0.2)
        elif self.moving_left:
            glRotate(-10, 0.1, 0.7, 0.2)

        #Vermelho, baixo
        glBegin(GL_TRIANGLES)
        # glColor3f(1.0, 0.0, 0.0)
        glTexCoord2f(0, 1)
        glTexCoord2f(1, 1)
        glVertex3f(self.move_x + self.position_x + 5.0, self.move_y + 12, -2.0)
        glTexCoord2f(1, 0)
        glVertex3f(self.move_x + self.position_x + 0.0, self.move_y, 0.0)
        glTexCoord2f(0, 0)
        glVertex3f(self.move_x + self.position_x - 5.0, self.move_y + 12, -2.0)
        glEnd()
        # VERDE esq
        glBegin(GL_TRIANGLES)
        # glColor3f(0.0, 1.0, 0.0)
        glTexCoord2f(0, 1)
        glTexCoord2f(1, 1)
        glVertex3f(self.move_x + self.position_x - 5.0, self.move_y + 12, -2.0)
        glTexCoord2f(1, 0)
        glVertex3f(self.move_x + self.position_x + 0.0, self.move_y, 0.0)
        glTexCoord2f(0, 0)
        glVertex3f(self.move_x + self.position_x + 0.0, self.move_y + 12, 2.0)
        glEnd()
        #############3 Azul escuro dir
        glBegin(GL_TRIANGLES)
        # glColor3f(0.5, 0.5, 1.0)
        glTexCoord2f(0, 1)
        glTexCoord2f(1, 1)
        glVertex3f(self.move_x + self.position_x + 5.0, self.move_y + 12, -2.0)
        glTexCoord2f(1, 0)
        glVertex3f(self.move_x + self.position_x + 0.0, self.move_y, 0.0)
        glTexCoord2f(0, 0)
        glVertex3f(self.move_x + self.position_x + 0.0, self.move_y + 12, 2.0)
        glEnd()
        #####################Roxo FRENTE
        glBegin(GL_TRIANGLES)
        # glColor3f(0.0, 0.0, 1.0)
        glTexCoord2f(0, 1)
        glTexCoord2f(1, 1)
        glVertex3f(self.move_x + self.position_x + 0.0, self.move_y + 12, 2.0)
        glTexCoord2f(1, 0)
        glVertex3f(self.move_x + self.position_x + 5.0, self.move_y + 12, -2.0)
        glTexCoord2f(0, 0)
        glVertex3f(self.move_x + self.position_x - 5.0, self.move_y + 12, -2.0)
        glEnd()
        glPopMatrix()
        glDisable(GL_TEXTURE_2D)

    # Define como é feito o movimento para a direita da nave
    def move_right(self):
        self.move_x += 0.7
        self.propellant.move_me(0.7, 0)

    # Define como é feito o movimento para a esquerda da nave
    def move_left(self):
        self.move_x -= 0.7
        self.propellant.move_me(-0.7, 0)

    # Define como é feito o movimento para baixo da nave
    def move_down(self):
        self.move_y -= 0.5
        self.propellant.move_me(0, -0.5)

    # Checa se a nave morreu / saiu da tela
    def check_dead(self):
        self.check_range()

    # Define a forma que a nave se move
    def move_yourself(self):
        if self.behavior == "Vertical":
            self.move_down()
        elif self.behavior == "Diagonal":
            self.check_max(-49, 49)
            if self.current_direction == DIRECTION_RIGHT:
                self.moving_right = True
                self.moving_left = False
                self.move_right()
                self.move_down()
            elif self.current_direction == DIRECTION_LEFT:
                self.moving_right = False
                self.moving_left = True
                self.move_left()
                self.move_down()
        elif self.behavior == "ZigZag":
            self.check_max(self.zig_x_1, self.zig_x_2)
            if self.current_direction == DIRECTION_RIGHT:
                self.moving_right = True
                self.moving_left = False
                self.move_right()
                self.move_down()
            elif self.current_direction == DIRECTION_LEFT:
                self.moving_right = False
                self.moving_left = True
                self.move_left()
                self.move_down()

    #  Define a ação a ser feita
    def act(self):
        self.move_yourself()

    # Checa se a nave bateu no alcance minimo ou maximo
    def check_max(self, min_range, max_range):
        if self.move_x + self.position_x - 4.0 <= min_range:
            self.current_direction = DIRECTION_RIGHT
        elif self.move_x + self.position_x + 4.0 >= max_range:
            self.current_direction = DIRECTION_LEFT

    # Checa se a nave está fora da tela
    def check_range(self):
        if self.move_y <= -90:
            self.dead = True
            self.propellant.im_dead()

    # Retorna uma tupla do tipo (x1 , x2)
    def get_x(self):
        return self.move_x + self.position_x - 5.0, \
            self.move_x + self.position_x + 5.0

    # Retorna uma tupla do tipo (y1 , y2)
    def get_y(self):
        return self.move_y, self.move_y + 12.0

    # Retorna uma tupla do tipo (z1 , z2)
    def get_z(self):
        return -2, 2

    # Retorna um comportamento randomico
    def rand_behavior(self):
        choice = randint(0, 91)
        if choice <= 30:
            return "Diagonal"
        elif choice >= 31 and choice <= 60:
            return "Vertical"
        elif choice >= 61 and choice <= 90:
            return "ZigZag"
        else:
            return "Daniel"

    # Carrega os valores do objeto
    def load(self, initial_position_x, propellant_anim, nave_azul,
             nave_amarela, nave_preta):
        self.dead = False
        self.move_x = 0
        self.move_y = 70
        self.position_x = initial_position_x
        self.skin_azul = nave_azul
        self.skin_amarela = nave_amarela
        self.skin_preta = nave_preta
        self.behavior = self.rand_behavior()
        if self.behavior == "ZigZag":
            self.rand_zigzag_range = randint(8, 40)
            self.zig_x_1 = self.move_x + self.position_x - self.rand_zigzag_range
            self.zig_x_2 = self.move_x + self.position_x + self.rand_zigzag_range
        self.current_direction = DIRECTION_RIGHT
        self.elapsed_shoot_time = 0
        self.nave_type = randint(0, 2)

        self.shoot_type_rand = randint(1, 10)
        if 1 <= self.shoot_type_rand <= 5:
            self.shoot_type = 1
        elif 6 <= self.shoot_type_rand <= 8:
            self.shoot_type = 2
        else:
            self.shoot_type = 3

        self.propellant = Propellant(propellant_anim, self.position_x,
                                     self.move_y + 16.7, "enemy")
        self.moving_right = False
        self.moving_left = False
コード例 #9
0
class Motor():
    """The motor class stores a number of grains, a nozzle instance, a propellant, and a configuration that it uses
    to run simulations. Simulations return a simRes object that includes any warnings or errors associated with the
    simulation and the data. The propellant field may be None if the motor has no propellant set, and the grains list
    is allowed to be empty. The nozzle field and config must be filled, even if they are empty property collections."""
    def __init__(self, propDict=None):
        self.grains = []
        self.propellant = None
        self.nozzle = Nozzle()
        self.config = MotorConfig()

        if propDict is not None:
            self.applyDict(propDict)

    def getDict(self):
        """Returns a serializable representation of the motor. The dictionary has keys 'nozzle', 'propellant',
        'grains', and 'config', which hold to the properties of their corresponding fields. Grains is a list
        of dicts, each containing a type and properties. Propellant may be None if the motor has no propellant
        set."""
        motorData = {}
        motorData['nozzle'] = self.nozzle.getProperties()
        if self.propellant is not None:
            motorData['propellant'] = self.propellant.getProperties()
        else:
            motorData['propellant'] = None
        motorData['grains'] = [{
            'type': grain.geomName,
            'properties': grain.getProperties()
        } for grain in self.grains]
        motorData['config'] = self.config.getProperties()
        return motorData

    def applyDict(self, dictionary):
        """Makes the motor copy properties from the dictionary that is passed in, which must be formatted like
        the result passed out by 'getDict'"""
        self.nozzle.setProperties(dictionary['nozzle'])
        if dictionary['propellant'] is not None:
            self.propellant = Propellant(dictionary['propellant'])
        else:
            self.propellant = None
        self.grains = []
        for entry in dictionary['grains']:
            self.grains.append(grainTypes[entry['type']]())
            self.grains[-1].setProperties(entry['properties'])
        self.config.setProperties(dictionary['config'])

    def calcKN(self, regDepth, dThroat):
        """Returns the motor's Kn when it has each grain has regressed by its value in regDepth, which should be a list
        with the same number of elements as there are grains in the motor."""
        burnoutThres = self.config.getProperty('burnoutWebThres')
        gWithReg = zip(self.grains, regDepth)
        perGrain = [
            gr.getSurfaceAreaAtRegression(reg) *
            int(gr.isWebLeft(reg, burnoutThres)) for gr, reg in gWithReg
        ]
        surfArea = sum(perGrain)
        nozz = self.nozzle.getThroatArea(dThroat)
        return surfArea / nozz

    def calcIdealPressure(self, regDepth, dThroat, lastPressure, kn=None):
        """Returns the steady-state pressure of the motor at a given reg. Kn is calculated automatically, but it can
        optionally be passed in to save time on motors where calculating surface area is expensive."""
        density = self.propellant.getProperty('density')
        ballA, ballN, gamma, temp, molarMass = self.propellant.getCombustionProperties(
            lastPressure)
        if kn is None:
            kn = self.calcKN(regDepth, dThroat)
        num = kn * density * ballA
        exponent = 1 / (1 - ballN)
        denom = ((gamma / ((8314 / molarMass) * temp)) *
                 ((2 / (gamma + 1))**((gamma + 1) / (gamma - 1))))**0.5
        return (num / denom)**exponent

    def calcIdealThrustCoeff(self, chamberPres, dThroat, exitPres=None):
        """Calculates C_f, the ideal thrust coefficient for the motor's nozzle and propellant, and the given chamber
        pressure. If nozzle exit presure isn't provided, it will be calculated."""
        if chamberPres == 0:
            return 0

        _, _, gamma, _, _ = self.propellant.getCombustionProperties(
            chamberPres)
        if exitPres is None:
            exitPres = self.nozzle.getExitPressure(gamma, chamberPres)
        ambPres = self.config.getProperty("ambPressure")
        exitArea = self.nozzle.getExitArea()
        throatArea = self.nozzle.getThroatArea(dThroat)

        term1 = (2 * (gamma**2)) / (gamma - 1)
        term2 = (2 / (gamma + 1))**((gamma + 1) / (gamma - 1))
        term3 = 1 - ((exitPres / chamberPres)**((gamma - 1) / gamma))

        momentumThrust = (term1 * term2 * term3)**0.5
        pressureThrust = (
            (exitPres - ambPres) * exitArea) / (throatArea * chamberPres)

        return momentumThrust + pressureThrust

    def calcForce(self, chamberPres, dThroat, exitPres=None):
        """Calculates the force of the motor at a given regression depth per grain. Calculates exit pressure by
        default, but can also use a value passed in. This method uses a combination of the techniques described
        in these resources to adjust the thrust coefficient: https://apps.dtic.mil/dtic/tr/fulltext/u2/a099791.pdf
        and http://rasaero.com/dloads/Departures%20from%20Ideal%20Performance.pdf."""
        thrustCoeffIdeal = self.calcIdealThrustCoeff(chamberPres, dThroat,
                                                     exitPres)
        divLoss = self.nozzle.getDivergenceLosses()
        throatLoss = self.nozzle.getThroatLosses(dThroat)
        skinLoss = self.nozzle.getSkinLosses()
        efficiency = self.nozzle.getProperty('efficiency')
        thrustCoeffAdj = divLoss * throatLoss * efficiency * (
            skinLoss * thrustCoeffIdeal + (1 - skinLoss))
        thrust = thrustCoeffAdj * self.nozzle.getThroatArea(
            dThroat) * chamberPres
        return max(thrust, 0)

    def runSimulation(self, callback=None):
        """Runs a simulation of the motor and returns a simRes instance with the results. Constraints are checked,
        including the number of grains, if the motor has a propellant set, and if the grains have geometry errors. If
        all of these tests are passed, the motor's operation is simulated by calculating Kn, using this value to get
        pressure, and using pressure to determine thrust and other statistics. The next timestep is then prepared by
        using the pressure to determine how the motor will regress in the given timestep at the current pressure.
        This process is repeated and regression tracked until all grains have burned out, when the results and any
        warnings are returned."""
        burnoutWebThres = self.config.getProperty('burnoutWebThres')
        burnoutThrustThres = self.config.getProperty('burnoutThrustThres')
        dTime = self.config.getProperty('timestep')

        simRes = SimulationResult(self)

        # Check for geometry errors
        if len(self.grains) == 0:
            aText = 'Motor must have at least one propellant grain'
            simRes.addAlert(
                SimAlert(SimAlertLevel.ERROR, SimAlertType.CONSTRAINT, aText,
                         'Motor'))
        for gid, grain in enumerate(self.grains):
            if isinstance(
                    grain, EndBurningGrain
            ) and gid != 0:  # Endburners have to be at the foward end
                aText = 'End burning grains must be the forward-most grain in the motor'
                simRes.addAlert(
                    SimAlert(SimAlertLevel.ERROR, SimAlertType.CONSTRAINT,
                             aText, 'Grain ' + str(gid + 1)))
            for alert in grain.getGeometryErrors():
                alert.location = 'Grain ' + str(gid + 1)
                simRes.addAlert(alert)
        for alert in self.nozzle.getGeometryErrors():
            simRes.addAlert(alert)

        # Make sure the motor has a propellant set
        if self.propellant is None:
            alert = SimAlert(SimAlertLevel.ERROR, SimAlertType.CONSTRAINT,
                             'Motor must have a propellant set', 'Motor')
            simRes.addAlert(alert)
        else:
            for alert in self.propellant.getErrors():
                simRes.addAlert(alert)

        # If any errors occurred, stop simulation and return an empty sim with errors
        if len(simRes.getAlertsByLevel(SimAlertLevel.ERROR)) > 0:
            print("Error in sim")
            print(simRes.getAlertsByLevel(SimAlertLevel.ERROR)[0].description)
            print("in",
                  simRes.getAlertsByLevel(SimAlertLevel.ERROR)[0].location)
            return simRes

        # Pull the required numbers from the propellant
        density = self.propellant.getProperty('density')

        # Generate coremaps for perforated grains
        for grain in self.grains:
            grain.simulationSetup(self.config)

        # Setup initial values
        perGrainReg = [0 for grain in self.grains]

        # At t = 0, the motor has ignited
        simRes.channels['time'].addData(0)
        simRes.channels['kn'].addData(self.calcKN(perGrainReg, 0))
        igniterPres = self.config.getProperty('igniterPressure')
        simRes.channels['pressure'].addData(
            self.calcIdealPressure(perGrainReg, 0, igniterPres, None))
        simRes.channels['force'].addData(0)
        simRes.channels['mass'].addData([
            grain.getVolumeAtRegression(0) * density for grain in self.grains
        ])
        simRes.channels['massFlow'].addData([0 for grain in self.grains])
        simRes.channels['massFlux'].addData([0 for grain in self.grains])
        simRes.channels['regression'].addData([0 for grains in self.grains])
        simRes.channels['web'].addData(
            [grain.getWebLeft(0) for grain in self.grains])
        simRes.channels['exitPressure'].addData(0)
        simRes.channels['dThroat'].addData(0)

        # Check port/throat ratio and add a warning if it is large enough
        aftPort = self.grains[-1].getPortArea(0)
        if aftPort is not None:
            minAllowed = self.config.getProperty('minPortThroat')
            ratio = aftPort / geometry.circleArea(
                self.nozzle.props['throat'].getValue())
            if ratio < minAllowed:
                desc = 'Initial port/throat ratio of ' + str(round(
                    ratio, 3)) + ' was less than ' + str(minAllowed)
                simRes.addAlert(
                    SimAlert(SimAlertLevel.WARNING, SimAlertType.CONSTRAINT,
                             desc, 'N/A'))

        # Perform timesteps
        while simRes.shouldContinueSim(burnoutThrustThres):
            # Calculate regression
            massFlow = 0
            perGrainMass = [0 for grain in self.grains]
            perGrainMassFlow = [0 for grain in self.grains]
            perGrainMassFlux = [0 for grain in self.grains]
            perGrainWeb = [0 for grain in self.grains]
            for gid, grain in enumerate(self.grains):
                if grain.getWebLeft(perGrainReg[gid]) > burnoutWebThres:
                    # Calculate regression at the current pressure
                    reg = dTime * self.propellant.getBurnRate(
                        simRes.channels['pressure'].getLast())
                    # Find the mass flux through the grain based on the mass flow fed into from grains above it
                    perGrainMassFlux[gid] = grain.getPeakMassFlux(
                        massFlow, dTime, perGrainReg[gid], reg, density)
                    # Find the mass of the grain after regression
                    perGrainMass[gid] = grain.getVolumeAtRegression(
                        perGrainReg[gid]) * density
                    # Add the change in grain mass to the mass flow
                    massFlow += (simRes.channels['mass'].getLast()[gid] -
                                 perGrainMass[gid]) / dTime
                    # Apply the regression
                    perGrainReg[gid] += reg
                    perGrainWeb[gid] = grain.getWebLeft(perGrainReg[gid])
                perGrainMassFlow[gid] = massFlow
            simRes.channels['regression'].addData(perGrainReg[:])
            simRes.channels['web'].addData(perGrainWeb)

            simRes.channels['mass'].addData(perGrainMass)
            simRes.channels['massFlow'].addData(perGrainMassFlow)
            simRes.channels['massFlux'].addData(perGrainMassFlux)

            # Calculate KN
            dThroat = simRes.channels['dThroat'].getLast()
            simRes.channels['kn'].addData(self.calcKN(perGrainReg, dThroat))

            # Calculate Pressure
            lastPressure = simRes.channels['pressure'].getLast()
            lastKn = simRes.channels['kn'].getLast()
            pressure = self.calcIdealPressure(perGrainReg, dThroat,
                                              lastPressure, lastKn)
            simRes.channels['pressure'].addData(pressure)

            # Calculate Exit Pressure
            _, _, gamma, _, _ = self.propellant.getCombustionProperties(
                pressure)
            exitPressure = self.nozzle.getExitPressure(gamma, pressure)
            simRes.channels['exitPressure'].addData(exitPressure)

            # Calculate force
            force = self.calcForce(simRes.channels['pressure'].getLast(),
                                   dThroat, exitPressure)
            simRes.channels['force'].addData(force)

            simRes.channels['time'].addData(simRes.channels['time'].getLast() +
                                            dTime)

            # Calculate any slag deposition or erosion of the throat
            if pressure == 0:
                slagRate = 0
            else:
                slagRate = (1 /
                            pressure) * self.nozzle.getProperty('slagCoeff')
            erosionRate = pressure * self.nozzle.getProperty('erosionCoeff')
            change = dTime * ((-2 * slagRate) + (2 * erosionRate))
            simRes.channels['dThroat'].addData(dThroat + change)

            if callback is not None:
                # Uses the grain with the largest percentage of its web left
                progress = max([
                    g.getWebLeft(r) / g.getWebLeft(0)
                    for g, r in zip(self.grains, perGrainReg)
                ])
                if callback(
                        1 - progress
                ):  # If the callback returns true, it is time to cancel
                    return simRes

        simRes.success = True

        if simRes.getPeakMassFlux() > self.config.getProperty('maxMassFlux'):
            desc = 'Peak mass flux exceeded configured limit'
            alert = SimAlert(SimAlertLevel.WARNING, SimAlertType.CONSTRAINT,
                             desc, 'Motor')
            simRes.addAlert(alert)

        if simRes.getMaxPressure() > self.config.getProperty('maxPressure'):
            desc = 'Max pressure exceeded configured limit'
            alert = SimAlert(SimAlertLevel.WARNING, SimAlertType.CONSTRAINT,
                             desc, 'Motor')
            simRes.addAlert(alert)

        # Note that this only adds all errors found on the first datapoint where there were errors to avoid repeating
        # errors. It should be revisited if getPressureErrors ever returns multiple types of errors
        for pressure in simRes.channels['pressure'].getData():
            if pressure > 0:
                err = self.propellant.getPressureErrors(pressure)
                if len(err) > 0:
                    simRes.addAlert(err[0])
                    break

        return simRes
コード例 #10
0
class Nave():
    # Inicia os parametros
    # self.dead = indica se o objeto deve ser desenhado
    # self.move_x = controla o movimento executado pela nave
    # self.position_x = indica a posição x inicial da nave
    # self.imageID = variavel para a textura da nave
    # self.propellant = Objeto "propulsor" da nave

    def __init__(self, propellant_anim, initial_position):
        self.dead = False
        self.move_x = 0
        self.moving_left = False
        self.moving_right = False
        self.shooting = False
        self.speed = 0
        self.position_x = initial_position
        self.imageID = self.loadImage()
        self.propellant = Propellant(propellant_anim, self.position_x, -43.3,
                                     "player")

    # Carrega a imagem da nave do player
    def loadImage(self, imageName="img/nave2.png"):
        im = Image.open(imageName)
        ix, iy, image = im.size[0], im.size[1], im.tobytes()
        ID = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, ID)
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ix, iy, 0, GL_RGBA,
                     GL_UNSIGNED_BYTE, image)
        return ID

    # Descreve como o objeto deve ser desenhado
    def draw(self):
        self.propellant.draw()

        glColor3f(1.0, 1.0, 1.0)
        glDisable(GL_LIGHTING)
        glEnable(GL_TEXTURE_2D)

        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
        glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

        glBindTexture(GL_TEXTURE_2D, self.imageID)

        glPushMatrix()

        glBegin(GL_QUADS)
        glTexCoord2f(0, 1)
        glVertex3f(self.move_x + self.position_x - 4.0, -40.0, 1)
        glTexCoord2f(1, 1)
        glVertex3f(self.move_x + self.position_x + 4.0, -40.0, 1)
        glTexCoord2f(1, 0)

        glVertex3f(self.move_x + self.position_x + 4.0, -28.0, 1)
        glTexCoord2f(0, 0)
        glVertex3f(self.move_x + self.position_x - 4.0, -28.0, 1)
        glEnd()

        glPopMatrix()
        glDisable(GL_TEXTURE_2D)

    # Define como é feito o movimento para a direita da nave
    # e verifica se o movimento pode ser feito
    def move_right(self):
        if self.move_x + self.position_x + 4.0 <= 47:
            self.move_x += 1.5 + self.speed
            self.propellant.move_me(1.5 + self.speed, 0)

    # Define como é feito o movimento para a esquerda da nave
    # e verifica se o movimento pode ser feito
    def move_left(self):
        if self.move_x + self.position_x - 4.0 >= -47:
            self.move_x -= 1.5 + self.speed
            self.propellant.move_me(-(1.5 + self.speed), 0)

    def check_dead(self):
        pass

    def act(self):
        if self.moving_left:
            self.move_left()
        if self.moving_right:
            self.move_right()

    # Retorna uma tupla do tipo (x1 , x2)
    def get_x(self):
        return (self.move_x + self.position_x - 4.0,
                self.move_x + self.position_x + 4.0)

    # Retorna uma tupla do tipo (y1 , y2)
    def get_y(self):
        return (-46.0, -34.0)