class RoverPST: margem_ui = 20 def __init__(self, arg0): self.conexao_krpc = arg0 # Conexão com o KRPC self.centro_espacial = arg0.space_center # Objeto do Centro Espacial self.marcadores = self.centro_espacial.waypoint_manager # Gerenciador de Marcadores no mapa self.rover = self.centro_espacial.active_vessel # Objeto do Rover (Nave Atual) self.ponto_ref_orbital = self.rover.orbit.body.reference_frame # Ponto de Referência Orbital self.ponto_ref_superficie = self.rover.surface_reference_frame # Ponto de Referência da Superfície self.ponto_ref_rover = self.rover.reference_frame # Ponto de Referência do Rover self.parametros_rover = self.rover.flight( self.ponto_ref_orbital) # Parâmetros de "voo" do Rover # Definindo Vetores de posição e direção: self.posicao_rover = Vetor.Vetor(0, 0) self.posicao_alvo = Vetor.Vetor(0, 0) self.direcao_rover = Vetor.Vetor(0, 0) self.distancia_entre_pontos = Vetor.Vetor(0, 0) # Variáveis de Angulo: self.angulo_alvo = 0.0 self.angulo_rover = 0.0 print("O nome do Rover é: {0:.30}".format(self.rover.name)) self.alvo = self.definir_alvo() if self.alvo is not None: print("Está buscando o alvo: {0:.30}".format(str(self.alvo.name)), "\n") self.ctrl_direcao = ControlePID() self.ctrl_direcao.ajustar_pid(0.01, 0.001, 0.01) self.ctrl_aceleracao = ControlePID() self.ctrl_aceleracao.ajustar_pid(0.5, 0.001, 0.1) self.ctrl_distancia_alvo = ControlePID() self.ctrl_distancia_alvo.ajustar_pid(0.1, 0.001, 5) self.ctrl_distancia_alvo.limitar_saida(-1, 1) self.limite_distancia_alvo = 50 self.velocidade_maxima = 15 self.velocidade_curva = 3 self.construir_painel_info() self.controlar_rover() def controlar_rover(self): while True: try: self.definir_vetor_direcao(self.definir_alvo()) self.informar_ctrl_pid() # Com tudo calculado, pilotar o rover: if self.distancia_entre_pontos.magnitude( ) > self.limite_distancia_alvo: self.acelerar_rover(self.ctrl_aceleracao.computar_pid()) self.pilotar_rover() else: self.acelerar_rover( self.ctrl_aceleracao.computar_pid() * self.ctrl_distancia_alvo.computar_pid()) self.atualizar_infos() except AttributeError: print("Sem alvo selecionado") sleep(1) sleep(0.05) def informar_ctrl_pid(self): # Informar ao PID de controle de direção os ângulos e tentar zerar a diferença entre eles: self.ctrl_direcao.entrada_pid(self.angulo_rover - abs(self.angulo_alvo)) self.ctrl_direcao.limite_pid(0) # Informar ao PID de aceleração a velocidade horizontal e limitar: self.ctrl_aceleracao.entrada_pid( self.parametros_rover.horizontal_speed) self.ctrl_distancia_alvo.entrada_pid( self.limite_distancia_alvo - self.distancia_entre_pontos.magnitude()) self.ctrl_distancia_alvo.limite_pid(0) diferenca_angulo = self.angulo_rover - abs(self.angulo_alvo) if abs(diferenca_angulo) > 30: self.ctrl_aceleracao.limite_pid(self.velocidade_curva) else: self.ctrl_aceleracao.limite_pid(self.velocidade_maxima) def definir_vetor_direcao(self, alvo): # Vetor de posição do Rover em relacão à superfície: self.posicao_rover = Vetor.Vetor( self.posicionar_vetor( self.rover.position(self.ponto_ref_superficie))) # Vetor de posição do Alvo em relacão ao rover e a órbita: self.posicao_alvo = Vetor.Vetor( self.posicionar_vetor(alvo.position(self.ponto_ref_rover))) # Vetor de posição do alvo em relacão à superfície e ao rover: self.direcao_rover = Vetor.Vetor(alvo.position(self.ponto_ref_rover)) # Vetor de distância do alvo em relacão rover: self.distancia_entre_pontos = self.posicao_rover.subtrai( self.posicao_alvo) # Calculando angulos até o alvo e da direção do rover self.angulo_alvo = Vetor.angulo_direcao(self.distancia_entre_pontos) self.angulo_rover = Vetor.angulo_direcao(self.direcao_rover) def pilotar_rover(self): if not 0 < self.angulo_alvo - self.angulo_rover < 1: self.rover.control.wheel_steering = -self.ctrl_direcao.computar_pid( ) else: self.rover.control.wheel_steering = 0 def posicionar_vetor(self, arg): if type(arg) is Vetor.Vetor: vetor = (arg.x, arg.y, 0) vetor_retorno = self.centro_espacial.transform_position( vetor, self.ponto_ref_superficie, self.ponto_ref_orbital) else: vetor_retorno = self.centro_espacial.transform_position( arg, self.ponto_ref_superficie, self.ponto_ref_orbital) return round(vetor_retorno[0], 2), round(vetor_retorno[1], 2), round(vetor_retorno[2], 2) def acelerar_rover(self, arg0): self.rover.control.wheel_throttle = arg0 def definir_alvo(self): try: self.alvo = self.centro_espacial.target_vessel return self.alvo except AttributeError: return None def construir_painel_info(self): # Tela do jogo: self.tela_itens = self.conexao_krpc.ui.stock_canvas # Tamanho da tela de jogo tamanho_tela = self.tela_itens.rect_transform.size # Adicionar um painel para conter os elementos de UI painel_info = self.tela_itens.add_panel(True) # Posicionar o painel a esquerda da tela painel_transform = painel_info.rect_transform painel_transform.size = (200.0, 100.0) painel_transform.position = (-int(tamanho_tela[0] * 0.25), int(tamanho_tela[1] * 0.16)) self.txt_angulo_rover = painel_info.add_text("Angulo Rover: ", True) self.txt_angulo_alvo = painel_info.add_text("Angulo Alvo: ", True) self.txt_angulo_distancia = painel_info.add_text( "Angulo Distancia: ", True) self.txt_distancia_alvo = painel_info.add_text( "Distância até o alvo: ", True) self.txt_angulo_rover.rect_transform.size = (200.0, __class__.margem_ui) self.txt_angulo_alvo.rect_transform.size = (200.0, __class__.margem_ui) self.txt_angulo_distancia.rect_transform.size = (200.0, __class__.margem_ui) self.txt_distancia_alvo.rect_transform.size = (200.0, __class__.margem_ui) self.txt_angulo_rover.rect_transform.position = (__class__.margem_ui, __class__.margem_ui) self.txt_angulo_alvo.rect_transform.position = (__class__.margem_ui, 0) self.txt_angulo_distancia.rect_transform.position = ( __class__.margem_ui, -__class__.margem_ui) self.txt_distancia_alvo.rect_transform.position = ( __class__.margem_ui, -(__class__.margem_ui * 2)) self.txt_angulo_rover.color = (0.0, 0.0, 0.0) self.txt_angulo_rover.size = 12 self.txt_angulo_alvo.color = (0.0, 0.0, 0.0) self.txt_angulo_alvo.size = 12 self.txt_angulo_distancia.color = (1.0, 1.0, 1.0) self.txt_angulo_distancia.size = 12 self.txt_distancia_alvo.color = (1.0, 1.0, 1.0) self.txt_distancia_alvo.size = 12 def atualizar_infos(self): self.txt_angulo_rover.content = "Correção de Ângulo: " + str( round(self.angulo_rover - abs(self.angulo_alvo), 2)) self.txt_angulo_alvo.content = "Acelerador: " + str( round(self.ctrl_aceleracao.computar_pid(), 2)) self.txt_angulo_distancia.content = "Angulo Distância: " + str( Vetor.angulo_direcao(self.distancia_entre_pontos)) self.txt_distancia_alvo.content = "Distância: " + str( round(self.distancia_entre_pontos.magnitude(), 1)) + "m"
class SuicideBurn: margem_ui = 20 conexao = None centro_espacial = None def __init__(self, arg): __class__.conexao = arg __class__.centro_espacial = conexao.space_center self.nave_atual = __class__.centro_espacial.active_vessel # objeto da nave self.ponto_ref = self.nave_atual.orbit.body.reference_frame self.voo_nave = self.nave_atual.flight(self.ponto_ref) # Parâmetros da nave self.altitude_da_nave = conexao.add_stream(getattr, self.voo_nave, "surface_altitude") self.vel_vert_nave = conexao.add_stream(getattr, self.voo_nave, "vertical_speed") self.massa_total_nave = conexao.add_stream(getattr, self.nave_atual, "mass") self.ut = conexao.add_stream(getattr, __class__.centro_espacial, "ut") self.controle_acel = ControlePID() self.controle_pouso = ControlePID() self.nav = Navegacao() self.distancia_pouso = 50 # Altura pra começar o Hover self.forca_grav = self.nave_atual.orbit.body.surface_gravity self.exec_suicide_burn = False self.pode_pousar = False self.nave_twr_max = 1 self.acel_max = 0 self.empuxo_total = 0 self.distancia_ate_queima = 0 self.tempo_da_queima = 0 self.construir_painel_info() def iniciar_suicide_burn(self): print("Nave Atual: ", self.nave_atual.name) print(str(self.nave_atual.situation)) print("Força da Gravidade Atual: ", self.forca_grav, "Corpo Celeste: ", self.nave_atual.orbit.body.name) self.calcular_parametros() print("Força de TWR da Nave: ", self.nave_twr_max) self.controle_acel.tempo_amostragem(40) self.controle_pouso.tempo_amostragem(40) self.controle_acel.ajustar_pid(0.025, 0.001, 0.025) # <== AJUSTES PID self.controle_pouso.ajustar_pid(0.1, 0.001, 0.1) # <== AJUSTES PID # Limita a aceleração da nave: self.nave_atual.auto_pilot.engage() # LIGAR O PILOTO self.decolagem_de_teste() self.calcular_parametros() self.controle_acel.limitar_saida(0, 1) self.controle_pouso.limitar_saida(0.75 / self.nave_twr_max, 1) self.controle_pouso.limite_pid(0) self.nav.navegacao(__class__.centro_espacial, self.nave_atual) while not self.exec_suicide_burn: # LOOP esperando para executar o SuicideBurn self.calcular_parametros() self.pode_pousar = False self.nav.mirar_nave() # Ativa freios e RCS para melhorar o controle da descida: if 100 < self.altitude_da_nave() < 10000: self.nave_atual.control.brakes = True else: self.nave_atual.control.brakes = False if self.altitude_da_nave() < 4000: self.nave_atual.control.rcs = True # self.controle_acel.ajustar_pid(round(self.nave_twr_max, 1) / 200, 0.001, 1) if (0 > self.altitude_da_nave() - self.distancia_ate_queima - self.distancia_pouso) and (self.vel_vert_nave() < -1): self.exec_suicide_burn = True print("Iniciando o Suicide Burn!") sleep(0.1) # -=-=- Loop Principal do Suicide Burn -=-=- while self.exec_suicide_burn: # Calcula os valores de aceleração e TWR do foguete: self.calcular_parametros() # Desce o trem de pouso da nave em menos de 100 metros if self.altitude_da_nave() < 100: self.nave_atual.control.gear = True # Informa aos PIDs a altitude, limite e velocidade da nave self.controle_acel.entrada_pid(self.altitude_da_nave()) self.controle_acel.limite_pid(self.distancia_ate_queima) self.controle_pouso.entrada_pid(self.vel_vert_nave()) # Aponta nave para o retrograde se a velocidade horizontal for maior que 1m/s if self.altitude_da_nave() > self.distancia_pouso: self.pode_pousar = False else: self.pode_pousar = True if self.voo_nave.horizontal_speed > 0.2: self.nav.mirar_nave() else: self.nave_atual.control.target_pitch = 0 # Acelera o foguete de acordo com o PID: correcao_anterior = self.nave_atual.control.throttle try: if self.pode_pousar is False: self.aceleracao( float((correcao_anterior + self.controle_acel.computar_pid() + 1 / self.nave_twr_max) / 3)) print("Valor Saída ACEL: ", self.controle_acel.computar_pid()) else: self.aceleracao(float(self.controle_pouso.computar_pid())) print("Valor Saída POUSO: ", self.controle_pouso.computar_pid()) except ZeroDivisionError: print("Erro no cálculo da aceleração. Usando valor antigo") self.aceleracao(correcao_anterior) # Verifica se o foguete pousou self.checar_pouso() sleep(0.05) def calcular_parametros(self): # Calcular TWR: try: if self.nave_atual.available_thrust == 0.0: self.empuxo_atual = self.nave_atual.available_thrust else: self.empuxo_atual = 0.0 for motor in self.nave_atual.parts.engines: self.empuxo_atual += motor.available_thrust self.nave_twr_max = self.empuxo_atual / (self.massa_total_nave() * self.forca_grav) # Aceleração Máxima da Nave: self.acel_max = (self.nave_twr_max * self.forca_grav) - self.forca_grav # Tempo de queima dessa aceleração e distancia até iniciar a queima de suicide burn com essa aceleração: self.tempo_da_queima = abs(self.vel_vert_nave()) / self.acel_max self.distancia_ate_queima = abs(self.vel_vert_nave()) * self.tempo_da_queima \ + 1 / 2 * self.acel_max * (self.tempo_da_queima ** 2) except ZeroDivisionError: self.nave_twr_max = 1 self.tempo_da_queima = 0 self.distancia_ate_queima = 0 # Mostrar dados: try: self.txt_altitude.content = str("Altitude: {0:.1f}{1}".format( self.altitude_da_nave(), "m")) self.txt_velocidade.content = str("Velocidade: {0:.1f}{1}".format( self.vel_vert_nave(), "m/s")) self.txt_suicide_dist.content = str( "Distância até Suicide: {0:>20.1f}{1}".format( (self.altitude_da_nave() - self.distancia_ate_queima - self.distancia_pouso), "m")) except ZeroDivisionError: self.txt_altitude.content = "Impossível buscar altitude" self.txt_velocidade.content = "Impossível buscar velocidade" self.txt_suicide_dist.content = "Impossível buscar distância" try: self.txt_twr.content = str("TWR: {0:.1f}".format( self.nave_twr_max)) except ZeroDivisionError: self.txt_twr.content = "Impossível buscar TWR" def aceleracao(self, valor): """ Acelera a nave de acordo com o valor Se o valor for negativo, o resultado é 0, se for maior que 1, fica 1""" valor = valor if valor > 0 else 0 valor = valor if valor < 1 else 1 self.nave_atual.control.throttle = valor def decolagem_de_teste(self): situacao_da_nave = str(self.nave_atual.situation) # Se o veículo está pousado ou na base de lançamento, ele sobe: if situacao_da_nave == "VesselSituation.landed" or situacao_da_nave == "VesselSituation.pre_launch": if situacao_da_nave == "VesselSituation.pre_launch": self.nave_atual.control.activate_next_stage() self.nave_atual.control.gear = False self.calcular_parametros() self.aceleracao(1) while self.altitude_da_nave() <= self.distancia_pouso: self.nave_atual.control.target_pitch = 0 sleep(0.1) self.aceleracao(0) sleep(0.1) self.nave_atual.control.target_pitch = 0 # mirar pra cima <<< else: self.aceleracao(0) def checar_pouso(self): situacao_da_nave = str(self.nave_atual.situation) if situacao_da_nave == "VesselSituation.landed" or \ situacao_da_nave == "VesselSituation.splashed" and self.pode_pousar: while self.nave_atual.control.throttle > 0.1: acel = self.nave_atual.control.throttle - 0.1 self.aceleracao(acel) sleep(0.1) print("Pouso finalizado.") self.aceleracao(0) self.nave_atual.auto_pilot.disengage() self.nave_atual.control.rcs = True self.nave_atual.control.sas = True self.nave_atual.control.brakes = False self.pode_pousar = False self.nave_atual.auto_pilot.disengage() # DESLIGAR O PILOTO self.exec_suicide_burn = False def construir_painel_info(self): # Tela do jogo: self.tela_itens = __class__.conexao.ui.stock_canvas # Tamanho da tela de jogo tamanho_tela = self.tela_itens.rect_transform.size # Adicionar um painel para conter os elementos de UI painel_info = self.tela_itens.add_panel(True) # Posicionar o painel a esquerda da tela painel_transform = painel_info.rect_transform painel_transform.size = (400.0, 100.0) painel_transform.position = (-int(tamanho_tela[0] * 0.25), int(tamanho_tela[1] * 0.16)) self.txt_altitude = painel_info.add_text("Altitude: ", True) self.txt_velocidade = painel_info.add_text("Velocidade: ", True) self.txt_twr = painel_info.add_text("TWR: ", True) self.txt_suicide_dist = painel_info.add_text("Distância Suicide: ", True) self.txt_altitude.rect_transform.size = (400.0, __class__.margem_ui) self.txt_velocidade.rect_transform.size = (400.0, __class__.margem_ui) self.txt_twr.rect_transform.size = (400.0, __class__.margem_ui) self.txt_suicide_dist.rect_transform.size = (400.0, __class__.margem_ui) self.txt_altitude.rect_transform.position = (__class__.margem_ui, __class__.margem_ui) self.txt_velocidade.rect_transform.position = (__class__.margem_ui, 0) self.txt_twr.rect_transform.position = (__class__.margem_ui, -__class__.margem_ui) self.txt_suicide_dist.rect_transform.position = ( __class__.margem_ui, -(__class__.margem_ui * 2)) self.txt_altitude.color = (0.0, 0.0, 0.0) self.txt_altitude.size = 12 self.txt_velocidade.color = (0.0, 0.0, 0.0) self.txt_velocidade.size = 12 self.txt_twr.color = (1.0, 1.0, 1.0) self.txt_twr.size = 12 self.txt_suicide_dist.color = (1.0, 1.0, 1.0) self.txt_suicide_dist.size = 12 # Adicionar botões: bt_sburn = painel_info.add_button("Suicide Burn", True) bt_cancelar = painel_info.add_button("Cancelar", True) bt_sburn.rect_transform.position = (100.0, -__class__.margem_ui) bt_cancelar.rect_transform.position = (100.0, __class__.margem_ui) # stream para checar se o botao foi clicado bt_sburn_clk = __class__.conexao.add_stream(getattr, bt_sburn, "clicked") bt_cancelar_clk = __class__.conexao.add_stream(getattr, bt_cancelar, "clicked") cancelar = False # Esperar clique do botão: while not (bt_sburn_clk()): try: self.txt_altitude.content = str("Altitude: {0:.1f}{1}".format( self.altitude_da_nave(), "m")) self.txt_velocidade.content = str( "Velocidade: {0:.1f}{1}".format(self.vel_vert_nave(), "m/s")) except: self.txt_altitude.content = "Impossível buscar altitude" self.txt_velocidade.content = "Impossível buscar velocidade" try: for motor in self.nave_atual.parts.engines: self.empuxo_total += motor.max_thrust twr_atual = float(self.empuxo_total / (self.massa_total_nave() * self.forca_grav)) self.txt_twr.content = str("TWR: {0:.1f}".format(twr_atual)) self.empuxo_total = 0 except: self.txt_twr.content = "Impossível buscar TWR" sleep(0.5) if bt_cancelar_clk(): cancelar = True break if not cancelar: self.iniciar_suicide_burn() bt_sburn.clicked = False bt_sburn.remove()
class DecolagemOrbital(): #Elementos da UI: margem_ui = 20 #Parametros: GRAV = 9.81 conexao = None centro_espacial = None def __init__(self, conexao): __class__.conexao = conexao __class__.centro_espacial = conexao.space_center self.iniciar_decolagem() def iniciar_decolagem(self): #Parametros padrao de decolagem: self.alt_inicio_curva = 150 self.alt_fim_curva = 60000 self.alt_final = 85000 self.inclinacao = "Normal" self.programa = 0 self.escudos_soltos = False #Parametros de voo: self.nave_atual = __class__.centro_espacial.active_vessel # objeto da nave ponto_ref = self.nave_atual.orbit.body.reference_frame voo_nave = self.nave_atual.flight(ponto_ref) self.ut = __class__.conexao.add_stream(getattr, __class__.centro_espacial, "ut") self.controle_acel = ControlePID() #Variaveis da nave: self.altitude = __class__.conexao.add_stream(getattr, voo_nave, "mean_altitude") self.max_q = __class__.conexao.add_stream(getattr, voo_nave, "dynamic_pressure") self.apoastro = __class__.conexao.add_stream(getattr, self.nave_atual.orbit, "apoapsis_altitude") self.periastro = __class__.conexao.add_stream(getattr, self.nave_atual.orbit, "periapsis_altitude") self.tempo_ate_apoastro = __class__.conexao.add_stream( getattr, self.nave_atual.orbit, "time_to_apoapsis") self.construir_painel_info() #<<< Mostrar painel de informacoes while True: if self.programa == 0: self.iniciar_lançamento() elif self.programa == 1: self.giro_gravitacional() elif self.programa == 2: self.circularizar() sleep(0.40) def iniciar_lançamento(self): # Iniciar Lancamento: self.nave_atual.control.sas = False # desligar SAS self.nave_atual.control.rcs = False # desligar RCS # Contagem regressiva... self.set_txt_titulo("Lançamento em:") for segundo in range(5, 0, -1): self.set_txt_status(segundo) sleep(1) # Acertar aceleracao: motores = self.nave_atual.parts.engines empuxo_total_lancamento = motores[0].max_thrust massa_total_lancamento = self.nave_atual.mass # massa da nave try: acel_lancamento = float( (1.5 / (empuxo_total_lancamento / (massa_total_lancamento * __class__.GRAV)))) except: acel_lancamento = 1 self.nave_atual.control.throttle = acel_lancamento # ACELERAR COM 1.5 DE TWR # Lançar e ativar piloto automático if (str(self.nave_atual.situation) == "VesselSituation.pre_launch"): self.nave_atual.control.activate_next_stage() self.nave_atual.auto_pilot.engage() # ativa o piloto auto self.nave_atual.auto_pilot.target_pitch_and_heading(90, 90) # direção self.programa = 1 def giro_gravitacional(self): self.set_txt_titulo("Altitude em Relação ao Solo:") #Controle de Aceleração self.controle_acel.set_valor_limite(25000) #Limite de pressão dinâmica self.controle_acel.limitar_saida(0.9, 3) #Limite de controle do TWR self.controle_acel.ajustar_pid(0.001, 0.001, 0.0001) angulo_giro = 0 # angulo de giro while (True): # loop do giro de gravidade self.set_txt_status(("{0:.1f}".format(self.altitude()) + " metros")) #Mostra Altitude # Giro de Gravidade if (self.altitude() > float(self.alt_inicio_curva) and self.altitude() < float(self.alt_fim_curva)): try: incremento = math.sqrt( (self.altitude() - self.alt_inicio_curva) / (self.alt_fim_curva - self.alt_inicio_curva)) except: pass if self.inclinacao == "Rasa": novo_angulo = math.sqrt(incremento * 0.8) * 90.0 elif self.inclinacao == "Normal": novo_angulo = (incremento) * 85.0 elif self.inclinacao == "Aguda": novo_angulo = math.pow(incremento, 1.2) * 80.0 if (math.fabs(novo_angulo - angulo_giro) > 0.3): angulo_giro = novo_angulo self.nave_atual.auto_pilot.target_pitch_and_heading( float(90 - angulo_giro), 90) #Controlar Aceleração para evitar o MaxQ: self.controle_acel.set_valor_entrada(self.max_q()) try: nova_acel = float((self.controle_acel.computar_pid() / (self.nave_atual.available_thrust / (self.nave_atual.mass * __class__.GRAV)))) except: nova_acel = 0 self.nave_atual.control.throttle = nova_acel if (self.altitude() > 20000): self.controle_acel.set_valor_limite(20000) # Diminuir aceleracao ao chegar perto do apoastro alvo if (self.apoastro() >= self.alt_final * 0.95): self.set_txt_titulo("Aproximando-se do apoastro alvo") self.nave_atual.control.throttle = 0.20 # mudar aceleração pra 25% break self.soltar_escudos() sleep(0.40) # Desativa motores ao chegar no apoastro while (self.apoastro() < self.alt_final): self.set_txt_titulo("Altitude do Apoastro:") self.set_txt_status("{0:.1f}".format(self.apoastro()) + "m, alvo: " + "{0:.1f}".format(self.alt_final) + "m.") self.soltar_escudos() sleep(0.40) self.set_txt_titulo("Apoastro alvo alcançado") self.nave_atual.control.throttle = 0 # cortar motor sleep(1) # esperar ate sair da atmosfera self.set_txt_titulo("Esperando sair da atmosfera") while (self.altitude() < 65000): self.set_txt_status("Altitude: " + "{0:.1f}".format(self.altitude()) + " metros") self.soltar_escudos() sleep(0.40) self.programa = 2 def soltar_escudos(self): # Soltar Fairings da nave: if (self.altitude() > 50000 and self.escudos_soltos == False): for escudo in self.nave_atual.parts.fairings: try: if not (escudo.jettisoned): self.set_txt_status("Soltando escudos...") sleep(1) escudo.jettison() self.set_txt_status("Escudos soltos.") self.escudos_soltos = True sleep(1) except: self.set_txt_status("Erro ao soltar escudos...") sleep(1) def circularizar(self): # Planejar circularizacao self.set_txt_titulo("Planejando queima de circularização") gm = self.nave_atual.orbit.body.gravitational_parameter # pegar parametro G apo = self.nave_atual.orbit.apoapsis # apoastro da orbita sma = self.nave_atual.orbit.semi_major_axis # semieixo da orbita v1 = math.sqrt(gm * ((2.0 / apo) - (1.0 / sma))) v2 = math.sqrt(gm * ((2.0 / apo) - (1.0 / apo))) delta_v = v2 - v1 #Adicionar a manobra node = self.nave_atual.control.add_node( self.ut() + self.nave_atual.orbit.time_to_apoapsis, prograde=delta_v) # Calcular tempo de queima (equacao de foguete) massa_total = self.nave_atual.mass # massa total do foguete isp = self.nave_atual.specific_impulse * __class__.GRAV # isp multiplicado pela constante grav empuxo_total = self.nave_atual.available_thrust # empuxo disponivel massa_seca = massa_total / math.exp( delta_v / isp) # massa seca do foguete taxa_queima = empuxo_total / isp # taxa de fluxo, empuxo / isp tempo_queima = (massa_total - massa_seca) / taxa_queima #tempo de queima # Orientar nave ao noh self.set_txt_status("Orientando nave para queima de circularização") self.nave_atual.control.rcs = True self.nave_atual.auto_pilot.reference_frame = node.reference_frame self.nave_atual.auto_pilot.target_direction = (0.0, 1.0, 0.0) # esperar ate a queima self.set_txt_titulo("Esperando até a queima de circularização") tempo_ate_queima = float(self.ut() + self.nave_atual.orbit.time_to_apoapsis - (tempo_queima / 2.0)) self.set_txt_status(("Tempo de queima: " + "{0:.1f}".format(tempo_queima) + " segundos")) espera = 5 self.nave_atual.auto_pilot.wait() __class__.centro_espacial.warp_to(tempo_ate_queima - espera) self.nave_atual.auto_pilot.target_direction = (0.0, 1.0, 0.0) # executar queima self.set_txt_titulo("Pronto para executar queima") queima_restante = __class__.conexao.add_stream( node.remaining_burn_vector, node.reference_frame) while (self.tempo_ate_apoastro() - (tempo_queima / 2.0) > 0.1): self.set_txt_status( str("Ignição em " + "{0:.1f}".format(self.tempo_ate_apoastro() - (tempo_queima / 2.0)) + " segundos...")) self.set_txt_titulo("Executando queima") self.nave_atual.control.throttle = 1 while (queima_restante()[1] > 1): sleep(0.20) if (queima_restante()[1] < 50 and self.nave_atual.control.throttle > 0.1): self.set_txt_titulo("Ajustando...") self.nave_atual.control.throttle = 0.1 self.set_txt_status("Delta V restante: " + "{0:.1f}".format(queima_restante()[1]) + "m/s") self.nave_atual.control.throttle = 0 node.remove() self.set_txt_titulo("Lançamento completo.") self.set_txt_status("Apoastro: " + "{0:.1f}".format(self.apoastro()) + "m, Periastro: " + "{0:.1f}".format(self.periastro()) + "m") self.nave_atual.auto_pilot.disengage() self.nave_atual.control.sas = True self.incremento = 0 self.angulo_giro = 0 self.novo_angulo = 0 sleep(5) __class__.conexao.close() def construir_painel_info(self): # Tela do jogo: self.tela_itens = __class__.conexao.ui.stock_canvas # Tamanho da tela de jogo tamanho_tela = self.tela_itens.rect_transform.size # Adicionar um painel para conter os elementos de UI painel_info = self.tela_itens.add_panel(True) # Posicionar o painel a esquerda da tela painel_transform = painel_info.rect_transform painel_transform.size = (400.0, 100.0) painel_transform.position = (-int(tamanho_tela[0] * 0.25), int(tamanho_tela[1] * 0.16)) # Adicionar caixa de texto para altitude cx_txt = painel_info.add_input_field(True) self.txt_titulo = painel_info.add_text("Digite a Altitude Final: ", True) self.txt_status = painel_info.add_text("", False) self.txt_titulo.rect_transform.size = (400.0, __class__.margem_ui) self.txt_status.rect_transform.size = (400.0, __class__.margem_ui) self.txt_titulo.rect_transform.position = (__class__.margem_ui, __class__.margem_ui) self.txt_status.rect_transform.position = (__class__.margem_ui, -__class__.margem_ui) self.txt_titulo.color = (0.0, 0.0, 0.0) self.txt_titulo.size = (14) self.txt_status.color = (1.0, 1.0, 1.0) self.txt_status.size = (18) cx_txt.rect_transform.position = (-100.0, -__class__.margem_ui) cx_txt.value = str(self.alt_final) # Adicionar botões: bt_decolar = painel_info.add_button("Decolar", True) bt_configurar = painel_info.add_button("Configurar", True) bt_ok = painel_info.add_button("OK", False) bt_inc_nor = painel_info.add_button("Normal", False) bt_inc_agu = painel_info.add_button("Aguda", False) bt_inc_ras = painel_info.add_button("Rasa", False) bt_decolar.rect_transform.position = (100.0, -__class__.margem_ui) bt_configurar.rect_transform.position = (100.0, __class__.margem_ui) bt_ok.rect_transform.position = (100.0, -__class__.margem_ui) bt_inc_nor.rect_transform.position = (-100.0, -__class__.margem_ui) bt_inc_agu.rect_transform.position = (-100.0, -__class__.margem_ui) bt_inc_ras.rect_transform.position = (-100.0, -__class__.margem_ui) # stream para checar se o botao foi clicado bt_decolar_clk = __class__.conexao.add_stream(getattr, bt_decolar, "clicked") bt_ok_clk = __class__.conexao.add_stream(getattr, bt_ok, "clicked") bt_configurar_clk = __class__.conexao.add_stream( getattr, bt_configurar, "clicked") bt_inc_nor_clk = __class__.conexao.add_stream(getattr, bt_inc_nor, "clicked") bt_inc_agu_clk = __class__.conexao.add_stream(getattr, bt_inc_agu, "clicked") bt_inc_ras_clk = __class__.conexao.add_stream(getattr, bt_inc_ras, "clicked") # Esperar clique do botão: while not (bt_decolar_clk()): numero = True if (cx_txt.changed): try: self.alt_final = float(cx_txt.value) except Exception: numero = False if (numero) and (self.alt_final > 70500.0): self.set_txt_titulo("Digite a Altitude Final: ") bt_decolar.visible = True bt_configurar.visible = True else: self.set_txt_titulo( "Precisa ser um número, acima de 71km!") bt_decolar.visible = False bt_configurar.visible = False sleep(0.50) if bt_configurar_clk(): self.set_txt_titulo("Escolha a inclinação de subida orbital:") bt_inc_nor.visible = True bt_ok.visible = True bt_configurar.visible = False bt_decolar.visible = False cx_txt.visible = False while (True): if bt_inc_nor_clk(): self.inclinacao = "Aguda" bt_inc_nor.clicked = False bt_inc_nor.visible = False bt_inc_agu.visible = True if bt_inc_agu_clk(): self.inclinacao = "Rasa" bt_inc_agu.clicked = False bt_inc_agu.visible = False bt_inc_ras.visible = True if bt_inc_ras_clk(): self.inclinacao = "Normal" bt_inc_ras.clicked = False bt_inc_ras.visible = False bt_inc_nor.visible = True if bt_ok_clk(): bt_decolar.visible = True bt_configurar.visible = True bt_ok.visible = False bt_inc_nor.visible = False bt_inc_agu.visible = False bt_inc_ras.visible = False bt_ok.clicked = False bt_configurar.clicked = False cx_txt.visible = True self.set_txt_titulo("Digite a Altitude Final: ") break bt_inc_ras.remove() bt_inc_nor.remove() bt_inc_agu.remove() bt_ok.remove() bt_decolar.remove() bt_configurar.remove() cx_txt.remove() self.txt_status.visible = True def set_txt_titulo(self, texto): self.txt_titulo.content = texto def set_txt_status(self, texto): self.txt_status.content = ("Status: " + str(texto))