def __check_cancel_orbita(f_atv): """ checa condições de abandonar a orbita. A condição é executada pelo comando de pilotagem @param f_atv: pointer para aeronave @return True se condição de abandonar a orbita, senão False (condição de permanecer em orbita) """ # check input assert f_atv # verifica condições para execução if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # aeronave não ativa. cai fora... return True # condição de cancelamento ? if f_atv.v_atv_cnl_esp: # coloca a aeronave na condição de abandonar a orbita abnd.abort_prc(f_atv) # return return True # return return False
def restaura_associado(f_atv, f_cine_data, f_stk_context): """ restaura o procedimento associado e o contexto da pilha @param f_atv: pointer to aeronave @param f_cine_data: kinematics data @param f_stk_context: pointer to stack """ # logger # M_LOG.info("restaura_associado:>>") # check input assert f_atv assert f_stk_context is not None # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("restaura_associado") l_log.setLevel(logging.ERROR) l_log.error(u"<E01: aeronave não ativa.") # abort procedure abnd.abort_prc(f_atv) # cai fora... return False # stack not empty ? if len(f_stk_context) > 0: # pop context # f_atv.en_atv_brk_ptr = f_stk_context.pop() f_atv.en_trf_fnc_ope, f_atv.en_atv_fase, f_atv.ptr_trf_prc, f_atv.ptr_atv_brk, f_cine_data.i_brk_ndx = f_stk_context.pop( ) # M_LOG.debug("restaura_associado:fnc_ope/fase:[{}]/[{}]".format(ldefs.DCT_FNC_OPE[f_atv.en_trf_fnc_ope], ldefs.DCT_FASE[f_atv.en_atv_fase])) # M_LOG.debug("restaura_associado:ptr_trf_prc:[{}]".format(f_atv.ptr_trf_prc)) # M_LOG.debug("restaura_associado:ptr_atv_brk:[{}]".format(f_atv.ptr_atv_brk)) # M_LOG.debug("restaura_associado:i_brk_ndx:[{}]".format(f_cine_data.i_brk_ndx)) # cai fora... return True # coloca a aeronave em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # volta a fase de verificar condições f_atv.en_atv_fase = ldefs.E_FASE_ZERO # logger # M_LOG.info("restaura_associado:<<") # cai fora... return False
def prc_dir_ponto(f_atv, ff_pto_x, ff_pto_y, f_cine_data): """ procedimento de direcionamento a ponto @param f_atv: ponteiro para struct aeronaves @param ff_pto_x: coordenada x do ponto (longitude) @param ff_pto_y: coordenada y do ponto (latitude) @param f_cine_data: ponteiro para pilha @return True se aeronave atingiu ponto, senão False """ # check input assert f_atv assert f_cine_data # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("prc_dir_ponto") l_log.setLevel(logging.ERROR) l_log.error("<E01: aeronave não ativa.") # abort procedure abnd.abort_prc(f_atv) # cai fora... return None # calcula raio do cone de tolerância lf_pto_rcone = f_atv.f_trf_alt_atu * math.tan(math.radians(10)) # calcula distância da aeronave ao ponto (x, y) f_cine_data.f_dst_anv_pto_x = ff_pto_x - f_atv.f_trf_x f_cine_data.f_dst_anv_pto_y = ff_pto_y - f_atv.f_trf_y # calcula distância euclidiana da aeronave ao ponto (linha reta) lf_dst_anv_pto = math.sqrt((f_cine_data.f_dst_anv_pto_x**2) + (f_cine_data.f_dst_anv_pto_y**2)) # calcula distância euclidiana do passo da aeronave (linha reta) lf_passo_anv = math.sqrt((f_cine_data.f_delta_x**2) + (f_cine_data.f_delta_y**2)) # (distância ao ponto <= raio de tolerância) ou (distância ao ponto <= passo da aeronave) ? (aeronave vai ultrapassar o ponto) if (lf_dst_anv_pto <= lf_pto_rcone) or (lf_dst_anv_pto <= lf_passo_anv): # sinaliza que aeronave ATINGIU o ponto return True # calcula nova proa de demanda f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(f_cine_data.f_dst_anv_pto_x, f_cine_data.f_dst_anv_pto_y) # M_LOG.debug("__ckeck_ok:f_atv_pro_dem:[{}]".format(f_atv.f_atv_pro_dem)) # em curva ? if f_atv.f_atv_pro_dem != f_atv.f_trf_pro_atu: # calcula sentido de curva pelo menor ângulo scrv.sentido_curva(f_atv) # faz o bloqueio do ponto próximo razc.calc_razao_curva(f_atv, ff_pto_x, ff_pto_y, f_cine_data) # sinaliza que aeronave ainda NÂO atingiu o ponto return False
def __cmd_pil_curva(self, f_atv, fo_cmd_pil, fen_cmd_ope): """ comando de pilotagem de curva """ # check input assert f_atv # força aeronave a abandonar qualquer procedimento abnd.abort_prc(f_atv) # coloca a aeronave em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL cdbg.M_DBG.debug("__cmd_pil_curva: fo_cmd_pil.t_param_1[0]: {}".format(fo_cmd_pil.t_param_1[0])) cdbg.M_DBG.debug("__cmd_pil_curva: fo_cmd_pil.t_param_2[0]: {}".format(fo_cmd_pil.t_param_2[0])) cdbg.M_DBG.debug("__cmd_pil_curva: fo_cmd_pil.t_param_3[0]: {}".format(fo_cmd_pil.t_param_3[0])) # curva a direita ? if ldefs.E_CDIR == fen_cmd_ope: # graus ? if (fo_cmd_pil.t_param_1 is not None) and fo_cmd_pil.t_param_1[1]: # obtém a proa desejada (demanda) cdbg.M_DBG.debug("__cmd_pil_curva: f_atv.f_atv_pro_dem (A): {}".format(f_atv.f_atv_pro_dem)) f_atv.f_atv_pro_dem = (360. + f_atv.f_trf_pro_atu + fo_cmd_pil.t_param_1[0]) % 360. cdbg.M_DBG.debug("__cmd_pil_curva: f_atv.f_atv_pro_dem (D): {}".format(f_atv.f_atv_pro_dem)) # proa ? elif (fo_cmd_pil.t_param_2 is not None) and fo_cmd_pil.t_param_2[1]: # obtém a proa desejada (demanda) cdbg.M_DBG.debug("__cmd_pil_curva: f_atv.f_atv_pro_dem (A): {}".format(f_atv.f_atv_pro_dem)) f_atv.f_atv_pro_dem = fo_cmd_pil.t_param_2[0] % 360. cdbg.M_DBG.debug("__cmd_pil_curva: f_atv.f_atv_pro_dem (D): {}".format(f_atv.f_atv_pro_dem)) # senão, curva indefinida... else: # proa negativa f_atv.f_atv_pro_dem = -1. # razão ? if (fo_cmd_pil.t_param_3 is not None) and (fo_cmd_pil.t_param_3[1]) and (fo_cmd_pil.t_param_3[0] != 0.): # curva direita (razão positiva) f_atv.f_atv_raz_crv = abs(fo_cmd_pil.t_param_3[0]) else: # curva direita (razão positiva) f_atv.f_atv_raz_crv = abs(f_atv.f_atv_raz_crv) # curva a esquerda ? elif ldefs.E_CESQ == fen_cmd_ope: # graus ? if (fo_cmd_pil.t_param_1 is not None) and fo_cmd_pil.t_param_1[1]: # obtém a proa desejada (demanda) f_atv.f_atv_pro_dem = (360. + f_atv.f_trf_pro_atu - fo_cmd_pil.t_param_1[0]) % 360. # proa ? elif (fo_cmd_pil.t_param_2 is not None) and fo_cmd_pil.t_param_2[1]: # obtém a proa desejada (demanda) f_atv.f_atv_pro_dem = fo_cmd_pil.t_param_2[0] % 360. # senão, curva indefinida... else: # proa negativa f_atv.f_atv_pro_dem = -1. # razão ? if (fo_cmd_pil.t_param_3 is not None) and (fo_cmd_pil.t_param_3[1]) and (fo_cmd_pil.t_param_3[0] != 0.): # curva esquerda (razão negativa) f_atv.f_atv_raz_crv = -abs(fo_cmd_pil.t_param_3[0]) else: # curva esquerda (razão negativa) f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) # curva pelo menor ângulo ? elif ldefs.E_CMNR == fen_cmd_ope: # graus ? if (fo_cmd_pil.t_param_1 is not None) and fo_cmd_pil.t_param_1[1]: # obtém a proa desejada (demanda) f_atv.f_atv_pro_dem = (360. + f_atv.f_trf_pro_atu + fo_cmd_pil.t_param_1[0]) % 360. # proa ? elif (fo_cmd_pil.t_param_2 is not None) and fo_cmd_pil.t_param_2[1]: # obtém a proa desejada (demanda) f_atv.f_atv_pro_dem = fo_cmd_pil.t_param_2[0] % 360. # senão, curva indefinida... else: # proa negativa f_atv.f_atv_pro_dem = -1. # razão ? if (fo_cmd_pil.t_param_3 is not None) and (fo_cmd_pil.t_param_3[1]) and (fo_cmd_pil.t_param_3[0] != 0.): # razão de curva f_atv.f_atv_raz_crv = abs(fo_cmd_pil.t_param_3[0]) else: # razão de curva f_atv.f_atv_raz_crv = abs(f_atv.f_atv_raz_crv) # força a curva pelo menor ângulo scrv.sentido_curva(f_atv) # proa ? elif ldefs.E_PROA == fen_cmd_ope: # obtém a proa desejada (demanda) f_atv.f_atv_pro_dem = fo_cmd_pil.t_param_2[0] % 360. # força a curva pelo menor ângulo scrv.sentido_curva(f_atv) # senão,... else: # logger l_log = logging.getLogger("CFlightEngine::__cmd_pil_curva") l_log.setLevel(logging.CRITICAL) l_log.critical(u"<E01: comando operacional ({}) não existe.".format(fen_cmd_ope))
def __check_ok(f_atv, f_cine_data): """ preparar a aeronave para decolagem @param f_atv: pointer to struct aeronaves @param f_cine_data: dados da cinemática """ # check input assert f_atv # pointer to aerodrome l_aer = f_cine_data.ptr_aer # aerodrome ok ? if (l_aer is None) or (not l_aer.v_aer_ok): # logger l_log = logging.getLogger("__check_ok") l_log.setLevel(logging.ERROR) l_log.error("<E01: aeródromo de decolagem inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # cancel flight f_atv.en_atv_est_atv = ldefs.E_CANCELADA # aeródromo de decolagem inexistente. cai fora... return # pointer to runway l_pst = f_cine_data.ptr_pis # runway ok ? if (l_pst is None) or (not l_pst.v_pst_ok): # logger l_log = logging.getLogger("__check_ok") l_log.setLevel(logging.ERROR) l_log.error("<E02: pista de decolagem inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # cancel flight f_atv.en_atv_est_atv = ldefs.E_CANCELADA # pista de decolagem inexistente. cai fora... return # aceleração f_atv.f_atv_acel = f_atv.ptr_trf_prf.f_prf_raz_max_var_vel * ldefs.D_FATOR_ACEL # velocidade atual f_atv.f_trf_vel_atu = 0. # velocidade de decolagem f_atv.f_atv_vel_dem = f_atv.ptr_trf_prf.f_prf_vel_dec # rumo da pista # i_pst_rumo (mlabru) f_atv.f_trf_pro_atu = \ f_atv.f_atv_pro_dem = l_pst.f_pst_true # elevação do aeródromo f_atv.f_trf_alt_atu = \ f_atv.f_atv_alt_dem = l_aer.f_aer_elev # posiciona aeronave na cabeceira da pista em x/y f_atv.f_trf_x = l_pst.f_pst_x f_atv.f_trf_y = l_pst.f_pst_y # sinaliza a fase de processamento de decolagem f_atv.en_atv_fase = ldefs.E_FASE_DECOLAGEM
def prc_decolagem(f_atv, f_cine_data, fstk_context): """ @param f_atv: ponteiro para struct aeronaves @param f_cine_data: ponteiro para pilha @param fstk_context: pilha de contexto """ # check input assert f_atv assert f_cine_data assert fstk_context # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("prc_decolagem") l_log.setLevel(logging.ERROR) l_log.error("<E01: aeronave [{}/{}] não ativa.".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # aeronave não ativa. cai fora... return # performance ok ? if (f_atv.ptr_trf_prf is None) or (not f_atv.ptr_trf_prf.v_prf_ok): # logger l_log = logging.getLogger("prc_decolagem") l_log.setLevel(logging.ERROR) l_log.error("<E02: performance não existe. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # performance não existe. cai fora... return # processa as fases # fase de preparação ? if ldefs.E_FASE_ZERO == f_atv.en_atv_fase: # verifica condição para execução __check_ok(f_atv, f_cine_data) # fase de decolagem ? elif ldefs.E_FASE_DECOLAGEM == f_atv.en_atv_fase: # realiza o processamento __do_dep(f_atv, f_cine_data, fstk_context) # fase estabilizada ? elif ldefs.E_FASE_ESTABILIZADA == f_atv.en_atv_fase: # verifica o término da decolagem if f_atv.f_trf_alt_atu == f_atv.f_atv_alt_dem: # obtém do contexto a função operacional anterior len_fnc_ope_tmp, _, _, _, _ = fstk_context[-1] # restaura a pilha de procedimento ou por comando de pilotagem if (ldefs.E_SUBIDA == f_atv.en_trf_fnc_ope_ant) or (ldefs.E_SUBIDA == len_fnc_ope_tmp): # restaura a pilha de procedimento tass.restaura_associado(f_atv, f_cine_data, fstk_context) # senão,... else: # decolagem incluida num tráfego, coloca em MANUAL f_atv.f_atv_alt_dem = f_atv.ptr_trf_prf.f_prf_teto_sv f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # senão,... else: # logger l_log = logging.getLogger("prc_decolagem") l_log.setLevel(logging.ERROR) l_log.error("<E04: fase da decolagem não identificada. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv)
def __do_dep(f_atv, f_cine_data, fstk_context): """ realizar o procedimento de decolagem @param f_atv: ponteiro para struct aeronaves @param f_cine_data: dados de cinemática @param fstk_context: ponteiro para pilha """ # check input assert f_atv assert f_cine_data assert fstk_context # obtém do contexto a função operacional anterior len_fnc_ope_tmp, _, _, _, _ = fstk_context[-1] # atingiu a velocidade de decolagem ? if f_atv.f_trf_vel_atu != f_atv.ptr_trf_prf.f_prf_vel_dec: # não atingiu a velocidade de decolagem, cai fora... return # pointer aerodrome l_aer = f_cine_data.ptr_aer # aerodrome ok ? if (l_aer is None) or (not l_aer.v_aer_ok): # logger l_log = logging.getLogger("__do_dep") l_log.setLevel(logging.ERROR) l_log.error("<E01: aeródromo de decolagem inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # cancel flight f_atv.en_atv_est_atv = ldefs.E_CANCELADA # aeródromo de decolagem inexistente. cai fora... return # verifica se é uma decolagem com subida ou decolagem pura if (ldefs.E_SUBIDA == f_atv.en_trf_fnc_ope_ant) or (ldefs.E_SUBIDA == len_fnc_ope_tmp): # pointer to subida l_sub = f_cine_data.ptr_sub # subida ok ? if (l_sub is None) or (not l_sub.v_prc_ok): # logger l_log = logging.getLogger("__do_dep") l_log.setLevel(logging.ERROR) l_log.error("<E02: decolagem/subida inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # cancel flight f_atv.en_atv_est_atv = ldefs.E_CANCELADA # decolagem/subida inexistente. cai fora... return # pointer to first climb breakpoint l_brk = l_sub.lst_sub_brk[0] # breakpoint ok ? if (l_brk is None) or (not l_brk.v_brk_ok): # logger l_log = logging.getLogger("__do_dep") l_log.setLevel(logging.ERROR) l_log.error("<E03: decolagem/subida breakpoint inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # cancel flight f_atv.en_atv_est_atv = ldefs.E_CANCELADA # decolagem/subida breakpoint inexistente. cai fora... return # pointer to runway l_pst = f_cine_data.ptr_pis # runway ok ? if (l_pst is None) or (not l_pst.v_pst_ok): # logger l_log = logging.getLogger("__do_dep") l_log.setLevel(logging.ERROR) l_log.error("<E04: pista de decolagem inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # cancel flight f_atv.en_atv_est_atv = ldefs.E_CANCELADA # pista de decolagem inexistente. cai fora... return # calcula a radial entre o 1*brk da subida e a pista lf_delta_x = l_brk.f_brk_x - l_pst.f_pst_x lf_delta_y = l_brk.f_brk_y - l_pst.f_pst_y lf_radial_pstta_brk = cpd.calc_proa_demanda(lf_delta_x , lf_delta_y) # calcula o ângulo entre o rumo da pista e o 1*brk da subida # i_pst_rumo (mlabru) lf_ang_pista_brk = abs(l_pst.f_pst_true - lf_radial_pstta_brk) # regra de cálculo da altitude na decolagem com Subida: # livrar obstáculos na decolagem (montanhas, prédios, ...) # limites: ângulo limite de 15 graus entre rumo da pista e o primeiro ponto da subida # se a diferença dos ângulos (fAngPistaBkp) for maior que 15 graus, então a altitude # de demanda será 400ft (não é nível) acima da elevação do aeródromo # se a diferença dos ângulos (fAngPistaBkp) for menor ou igual a 15 graus, a altitude # de demanda será 50ft acima da elevação do aeródromo if lf_ang_pista_brk > 15.: # calcula 400ft acima da altitude da pista (converte ft -> m) f_atv.f_atv_alt_dem = (400. * cdefs.D_CNV_FT2M) + l_aer.f_aer_elev # senão,... else: # calcula 50ft acima da altitude da pista (converte ft -> m) f_atv.f_atv_alt_dem = (50. * cdefs.D_CNV_FT2M) + l_aer.f_aer_elev # determina a razão máxima de subida na decolagem para todos os casos # # PBN (casos de DEP no SBGL e SBRJ) # Descomentado este trecho para as seguintes considerações: # a) aeródromos com pistas curtas (caso SBGL) as aeronaves consigam aplicar a # RazMaxSubDec, porém o gradiente tem que estar zerado no primeiro ponto da Subida. # b) aeródromos com pistas longas, a AnvRazSub possa ser aplicada mediante o cálculo do # gradiente (se houver) para atingir o primeiro ponto da Subida. # # Obs_1: Com o retorno da verificação do gradiente, evitou-se que aeronaves decolando # em pistas longas chegassem a subir como se fossem foguetes devido ao uso # generalizado da prf_raz_max_sub_dec para todos os casos. # Obs_2: Ambos casos a aceleração na DEP tem que ser 4 vezes (campo do arquivo ".ini") if 0. == l_brk.f_brk_raz_vel: # razão de subida é a razão máxima de subida na decolagem f_atv.f_atv_raz_sub = f_atv.ptr_trf_prf.f_prf_raz_max_sub_dec # senão,... else: # calcula a razão de subida em função do gradiente f_atv.f_atv_raz_sub = f_atv.f_trf_vel_atu * l_brk.f_brk_raz_vel # decolagem pura, sem subida else: # regra de cálculo da altitude na decolagem pura: # livrar obstáculos na decolagem (montanhas, prédios, ...). A altitude de demanda será # 50ft acima da elevação do aeródromo # calcula 50ft acima da altitude da pista f_atv.f_atv_alt_dem = (50. * cdefs.D_CNV_FT2M) + l_aer.f_aer_elev # razão de subida é a razão máxima de subida na decolagem f_atv.f_atv_raz_sub = f_atv.ptr_trf_prf.f_prf_raz_max_sub_dec # regra da velocidade na decolagem: # velocidade limite de 250kt para as aeronaves que estiverem voando abaixo de 10000ft (FL100) # verifica a altitude atual da aeronave if (f_atv.f_trf_alt_atu * cdefs.D_CNV_M2FT) < ldefs.D_ALT_MAX_TMA: # determina a velocidade de subida na decolagem (limitada a 250kt) f_atv.f_atv_vel_dem = min(f_atv.ptr_trf_prf.f_prf_vel_sub_dec, ldefs.D_VEL_MAX_TMA) # ajusta aceleração f_atv.f_atv_acel = f_atv.ptr_trf_prf.f_prf_raz_var_vel # determina fase final da decolagem f_atv.en_atv_fase = ldefs.E_FASE_ESTABILIZADA
def trata_associado(f_atv, f_brk, fi_brk_ndx, f_stk_context): """ armazena na pilha o procedimento associado @param f_atv: pointer to aeronave @param f_brk: pointer to breakpoint @param fi_brk_ndx: índice do breakpoint atual @param f_stk_context: pointer to stack @return True se armazenou dados da aeronave na pilha, senão False """ # logger # M_LOG.info("trata_associado:>>") # check input assert f_atv assert f_stk_context is not None # active flight ? if not f_atv.v_atv_ok or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("trata_associado") l_log.setLevel(logging.ERROR) l_log.error(u"<E01: aeronave não ativa.") # abort procedure abnd.abort_prc(f_atv) # cai fora... return False # M_LOG.debug("trata_associado:: bkp:[{}] f_brk.ptr_brk_prc:[{}]".format(f_brk.i_brk_id, f_brk.ptr_brk_prc)) # existe um procedimento associado ? if (f_brk.ptr_brk_prc is not None) and (ldefs.E_NOPROC != f_brk.ptr_brk_prc ): # and (0 != f_brk.BkpNumProc): # push actual context f_stk_context.append( (f_atv.en_trf_fnc_ope, f_atv.en_atv_fase, f_atv.ptr_trf_prc, f_atv.ptr_atv_brk, fi_brk_ndx)) # M_LOG.debug("trata_associado::fnc_ope/fase(A):[{}]/[{}]".format(ldefs.DCT_FNC_OPE[f_atv.en_trf_fnc_ope], ldefs.DCT_FASE[f_atv.en_atv_fase])) # M_LOG.debug("trata_associado::ptr_trf_prc(A):[{}]".format(f_atv.ptr_trf_prc)) # M_LOG.debug("trata_associado::ptr_atv_brk(A):[{}]".format(f_atv.ptr_atv_brk)) # load new context f_atv.en_trf_fnc_ope = f_brk.en_brk_fnc_ope f_atv.en_atv_fase = ldefs.E_FASE_ZERO f_atv.ptr_trf_prc = f_brk.ptr_brk_prc # M_LOG.debug("trata_associado::fnc_ope/fase(D):[{}]/[{}]".format(ldefs.DCT_FNC_OPE[f_atv.en_trf_fnc_ope], ldefs.DCT_FASE[f_atv.en_atv_fase])) # M_LOG.debug("trata_associado::ptr_trf_prc(D):[{}]".format(f_atv.ptr_trf_prc)) # M_LOG.debug("trata_associado::ptr_atv_brk(D):[{}]".format(f_atv.ptr_atv_brk)) # EXISTE procedimento associado ao breakpoint return True # logger # M_LOG.info("trata_associado:<<") # NÂO existe procedimento associado ao breakpoint return False
def prc_trajetoria(f_atv, f_cine_data, f_stk_context): """ @param f_atv: pointer to struct aeronave @param f_cine_data: kinematics data @param f_stk_context: pointer to stack """ # check input assert f_atv assert f_cine_data assert f_stk_context is not None # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error(u"prc_trajetoria:<E01: aeronave não ativa.") # cai fora... return # pointer to trajetória l_trj = f_atv.ptr_trf_prc # trajetória ok ? if (l_trj is None) or (not l_trj.v_prc_ok): # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error(u"<E02: trajetória inexistente. aeronave:[{}/{}].".format( f_atv.i_trf_id, f_atv.s_trf_ind)) # trajetória not found, abort procedure abnd.abort_prc(f_atv) # return return # fase de iniciação ? if ldefs.E_FASE_ZERO == f_atv.en_atv_fase: # reseta o flag altitude/velocidade para iniciar uma nova trajetória f_atv.i_atv_change_alt_vel = 0 # inicia o index de breakpoints f_cine_data.i_brk_ndx = 0 # inicia com dados do primeiro breakpoint l_brk = f_atv.ptr_atv_brk = l_trj.lst_trj_brk[0] # breakpoint ok ? if (l_brk is None) or not l_brk.v_brk_ok: # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error( u"<E03: trajetória/breakpoint inexistente. aeronave:[{}/{}] fase:[{}]." .format(f_atv.i_trf_id, f_atv.s_trf_ind, ldefs.DCT_FASE[f_atv.en_atv_fase])) # não encontrou o breakpoint, abort procedure abnd.abort_prc(f_atv) # return return # obtém dados do breakpoint da trajetória obrk.obtem_brk(f_atv, l_brk, f_cine_data) # fase de direção ao ponto ? elif ldefs.E_FASE_DIRPONTO == f_atv.en_atv_fase: # obter dados do breakpoint da trajetória l_brk = f_atv.ptr_atv_brk # breakpoint ok ? if (l_brk is None) or not l_brk.v_brk_ok: # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error( u"<E04: trajetória/breakpoint inexistente. aeronave:[{}/{}] fase:[{}]." .format(f_atv.i_trf_id, f_atv.s_trf_ind, ldefs.DCT_FASE[f_atv.en_atv_fase])) # não encontrou o breakpoint, abort procedure abnd.abort_prc(f_atv) # return return # obtém as coordenadas do ponto a ser bloqueado lf_brk_x = f_cine_data.f_coord_x_brk lf_brk_y = f_cine_data.f_coord_y_brk # M_LOG.debug("prc_trajetoria:stk.f_brk_x:[{}] stk.f_brk_y:[{}]".format(f_cine_data.f_coord_x_brk, f_cine_data.f_coord_y_brk)) '''# tratamento para vôo lateral # foi comandado na pilotagem vôo lateral ? if f_atv.f_atv_dst_vlat > 0.: lf_radial = 0. # calcula a radial if 'D' == f_atv.c_atv_dir_vlat: lf_radial = 180. else: lf_radial = 0. if lf_radial <= 90.: lf_radial = 90. - lf_radial else: lf_radial = 450. - lf_radial # converte para radianos lf_radial = math.radians(lf_radial) # calcula as coordenadas x e y relativo ao fixo lf_brk_x = f_atv.f_atv_dst_vlat * math.cos(lf_radial) lf_brk_y = f_atv.f_atv_dst_vlat * math.sin(lf_radial) # calcula a projeção do ponto a ser deslocado "nnn NM" à direita ou à esquerda lf_brk_x = lf_brk_x + l_brk.f_brk_x lf_brk_y = lf_brk_y + l_brk.f_brk_y ''' # faz o direcionamento ao breakpoint if dp.prc_dir_ponto(f_atv, lf_brk_x, lf_brk_y, f_cine_data): # ao bloquear o breakpoint, tem um procedimento associado ? if not tass.trata_associado(f_atv, l_brk, f_cine_data.i_brk_ndx, f_stk_context): # não tem procedimento associado, muda de fase f_atv.en_atv_fase = ldefs.E_FASE_BREAKPOINT # fase rumo/altitude ? elif ldefs.E_FASE_RUMOALT == f_atv.en_atv_fase: # dados do breakpoint da trajetória l_brk = f_atv.ptr_atv_brk # breakpoint ok ? if (l_brk is None) or not l_brk.v_brk_ok: # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error( u"<E05: trajetória/breakpoint inexistente. aeronave:[{}/{}] fase:[{}]." .format(f_atv.i_trf_id, f_atv.s_trf_ind, ldefs.DCT_FASE[f_atv.en_atv_fase])) # não encontrou o breakpoint, abort procedure abnd.abort_prc(f_atv) # return return # proa e a altitude estão estabilizadas ? if (f_atv.f_trf_pro_atu == f_atv.f_atv_pro_dem) and (f_atv.f_trf_alt_atu == f_atv.f_atv_alt_dem): # não existe procedimento associado ? if not tass.trata_associado(f_atv, f_cine_data.i_brk_ndx, f_stk_context): # muda de fase f_atv.en_atv_fase = ldefs.E_FASE_BREAKPOINT # fase de breakpoint ? elif ldefs.E_FASE_BREAKPOINT == f_atv.en_atv_fase: # é o último breakpoint da trajetoria atual ? if f_atv.ptr_atv_brk == l_trj.lst_trj_brk[-1]: # reset flag altitude/velocidade f_atv.i_atv_change_alt_vel = 0 # não tem dados na pilha ? if not tass.restaura_associado(f_atv, f_cine_data, f_stk_context): # qual a proa que a aeroanve deve seguir após bloquear o último breakpoint ? # trajetória tem proa ? if l_trj.f_trj_proa > 0.: # demanda é a proa da trajetória f_atv.f_atv_pro_dem = l_trj.f_trj_proa # otherwise, trajetória NÃO tem proa... else: # demanda é a proa atual f_atv.f_atv_pro_dem = f_atv.f_trf_pro_atu # força a curva pelo menor lado scrv.sentido_curva(f_atv) # otherwise, tem dados na pilha... else: # o procedimento restaurado NÃO é trajetória ? if ldefs.E_TRAJETORIA != f_atv.en_trf_fnc_ope: # logger # M_LOG.info(u"prc_trajetoria:<E06: procedimento restaurado NÃO é trajetória.") # return return # dados da trajetória anterior l_trj = f_atv.ptr_trf_prc # é o último ponto da trajetoria anterior ? if f_atv.ptr_atv_brk._pNext is None: # bloqueou o último ponto da trajetória anterior, força procedimento manual abnd.abort_prc(f_atv) # qual proa a aeroanve deve seguir após bloquear o último breakpoint ? # trajetória tem proa ? if l_trj.f_trj_proa > 0.: # demanda é a proa da trajetória f_atv.f_atv_pro_dem = l_trj.f_trj_proa # otherwise, trajetória NÃO tem proa... else: # demanda é a proa atual f_atv.f_atv_pro_dem = f_atv.f_trf_pro_atu # força a curva pelo menor lado scrv.sentido_curva(f_atv) # otherwise, não é o último breakpoint da trajetória anterior else: # aponta para o próximo breakpoint da trajetória l_brk = f_atv.ptr_atv_brk = f_atv.ptr_atv_brk._pNext # breakpoint ok ? if (l_brk is None) or not l_brk.v_brk_ok: # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error( u"<E07: trajetória anterior não é último ponto. aeronave:[{}/{}] fase:[{}]." .format(f_atv.i_trf_id, f_atv.s_trf_ind, ldefs.DCT_FASE[f_atv.en_atv_fase])) # não encontrou o breakpoint, abort procedure abnd.abort_prc(f_atv) # return return # obtém dados do breakpoint da trajetória anterior obrk.obtem_brk(f_atv, l_brk, f_cine_data) # otherwise, não é o último breakpoint else: # próximo breakpoint f_cine_data.i_brk_ndx += 1 # aponta para o próximo breakpoint l_brk = f_atv.ptr_atv_brk = l_trj.lst_trj_brk[ f_cine_data.i_brk_ndx] # breakpoint ok ? if (l_brk is None) or not l_brk.v_brk_ok: # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error( u"<E08: trajetória/breakpoint inexistente. aeronave:[{}/{}] fase:[{}]." .format(f_atv.i_trf_id, f_atv.s_trf_ind, ldefs.DCT_FASE[f_atv.en_atv_fase])) # não encontrou o breakpoint, abort procedure abnd.abort_prc(f_atv) # return return # obtém dados do breakpoint atual obrk.obtem_brk(f_atv, l_brk, f_cine_data) # fase de direcionamento a um fixo ? elif ldefs.E_FASE_DIRFIXO == f_atv.en_atv_fase: # reseta o flag altitude/velocidade para iniciar uma nova trajetória f_atv.i_atv_change_alt_vel = 0 # aponta para o breakpoint l_brk = f_atv.ptr_atv_brk # breakpoint ok ? if (l_brk is None) or not l_brk.v_brk_ok: # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error( u"<E09: trajetória/breakpoint inexistente. aeronave:[{}/{}] fase:[{}]." .format(f_atv.i_trf_id, f_atv.s_trf_ind, ldefs.DCT_FASE[f_atv.en_atv_fase])) # não encontrou o breakpoint, abort procedure abnd.abort_prc(f_atv) # return return # obtém dados do breakpoint atual obrk.obtem_brk(f_atv, l_brk, f_cine_data) # otherwise, erro na valor da fase else: # logger l_log = logging.getLogger("prc_trajetoria") l_log.setLevel(logging.ERROR) l_log.error( u"<E10: fase na trajetória não identificada. fase:[{}].".format( ldefs.DCT_FASE[f_atv.en_atv_fase]))
def prc_espera(f_atv, f_cine_data, f_stk_context, ff_delta_t): """ DOCUMENT ME! @param f_atv: pointer para struct aeronaves @param f_cine_data: dados da cinemática @param f_stk_context: pointer para pilha @param ff_delta_t: tempo decorrido desde a última atualização """ # check input assert f_atv assert f_cine_data assert f_stk_context is not None # aeronave ativa ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("prc_espera") l_log.setLevel(logging.ERROR) l_log.error(u"<E01: aeronave não ativa.") # aeronave não ativa. cai fora... return # performance existe ? if (f_atv.ptr_trf_prf is None) or (not f_atv.ptr_trf_prf.v_prf_ok): # logger l_log = logging.getLogger("prc_espera") l_log.setLevel(logging.ERROR) l_log.error(u"<E02: performance não existe.") # performance não existe. cai fora... return # aponta para a espera planejada e valida pointer l_esp = f_atv.ptr_trf_prc if (l_esp is None) or (not l_esp.v_prc_ok): # logger l_log = logging.getLogger("prc_espera::prc_espera") l_log.setLevel(logging.ERROR) l_log.error("<E03: espera inexistente. aeronave:[%d/%s]", f_atv.i_trf_id, f_atv.s_trf_ind) # não encontrou a espera, força a aeronave abandonar o procedimento abnd.abort_prc(f_atv) # espera inexistente. cai fora... return # aeronave abaixo de 14000ft ? if (f_atv.f_trf_alt_atu <= M_14000FT) and (f_atv.f_trf_vel_atu > M_VEL_MAX): # velocidade máxima é de 230KT f_atv.f_atv_vel_dem = M_VEL_MAX # preparação de dados ? if ldefs.E_FASE_ZERO == f_atv.en_atv_fase: # obtém dados do fixo de espera e valida pointer l_fix = l_esp.ptr_esp_fix if (l_fix is None) or (not l_fix.v_fix_ok): # logger l_log = logging.getLogger("prc_espera::prc_espera") l_log.setLevel(logging.ERROR) l_log.error("<E04: fixo da espera inexistente. aeronave:[%d/%s]", f_atv.i_trf_id, f_atv.s_trf_ind) # não encontrou o fixo, força a aeronave abandonar o procedimento abnd.abort_prc(f_atv) # fixo da espera inexistente. cai fora... return # checa condição de cancelamento, caso tenha sido comandado pelo piloto if __check_cancel_espera(f_atv, l_esp): # break return # direciona ao fixo de espera !!!REVER!!! if dp.prc_dir_ponto(f_atv, l_fix.f_fix_x, l_fix.f_fix_y, f_cine_data): # determina qual o setor de entrada na espera f_atv.en_atv_fase = __setor_entrada(f_atv, l_esp) # valida proa para perna de afastamento # f_esp_rumo (mlabru) f_cine_data.f_afasta = l_esp.f_esp_true - 180. # normaliza proa para perna de afastamento if f_cine_data.f_afasta < 0.: f_cine_data.f_afasta += 360. # limita a razão de subida/descida na espera em no máximo 1000FT/MIN !!!REVER!!! if f_atv.f_atv_raz_sub > M_RAZ_SUB: # salva a razão atual f_cine_data.f_raz_sub_des = f_atv.f_atv_raz_sub # limita a razão f_atv.f_atv_raz_sub = M_RAZ_SUB # seguir na perna de aproximação em direção oposta (perna de afastamento) elif ldefs.E_FASE_SETOR1 == f_atv.en_atv_fase: # ajusta a razão de curva em relação ao sentido da espera if ldefs.E_DIREITA == l_esp.en_esp_sentido_curva: # curva pela direita (positivo) f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) # senão,... else: # curva pela esquerda (negativo) f_atv.f_atv_raz_crv = abs(f_atv.f_atv_raz_crv) # inicia dados da espera na pilha f_cine_data.i_setor_ent = 1 f_cine_data.i_bloqueio_fixo = 1 # seguir numa paralela no sentido "oposto" da perna de aproximação f_atv.f_atv_pro_dem = f_cine_data.f_afasta # obtém o tempo limite na perna de aproximação considerando o limite de 14000FT f_cine_data.h_tempo = 90. if (f_atv.f_trf_alt_atu > M_14000FT) else 50. # sinaliza nova fase f_atv.en_atv_fase = ldefs.E_FASE_TEMPO # seguir no rumo perna de afastamento defasado de 30 graus elif ldefs.E_FASE_SETOR2 == f_atv.en_atv_fase: # curva pela direita ? if ldefs.E_DIREITA == l_esp.en_esp_sentido_curva: # calcula a nova proa de demanda f_atv.f_atv_pro_dem = f_cine_data.f_afasta - 30. # normaliza if f_atv.f_atv_pro_dem < 0.: f_atv.f_atv_pro_dem += 360. # senão, curva pela esquerda else: # calcula a nova proa de demanda f_atv.f_atv_pro_dem = f_cine_data.f_afasta + 30. # normaliza if f_atv.f_atv_pro_dem > 360.: f_atv.f_atv_pro_dem -= 360. # razão de curva pelo menor lado scrv.sentido_curva(f_atv) # tempo na defasagem (1 minuto e meio no limite de 14000FT) f_cine_data.h_tempo = 90. if (f_atv.f_trf_alt_atu > M_14000FT) else 60. # sinaliza nova fase f_atv.en_atv_fase = ldefs.E_FASE_TEMPOSETOR # entrada pelo setor 3 elif ldefs.E_FASE_SETOR3 == f_atv.en_atv_fase: # entrada pelo setor 3 f_atv.f_atv_pro_dem = f_cine_data.f_afasta # entra na órbita f_atv.en_atv_fase = ldefs.E_FASE_CRVAFASTA # curva pela esquerda ? if ldefs.E_ESQUERDA == l_esp.en_esp_sentido_curva: # curva pela esquerda (negativa) f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) # senão, curva pela direita else: # curva pela direita (positiva) f_atv.f_atv_raz_crv = abs(f_atv.f_atv_raz_crv) # permanência na perna de aproximação elif ldefs.E_FASE_TEMPO == f_atv.en_atv_fase: # permanece na perna de aproximação ? if f_cine_data.h_tempo > 0.: # decrementa o tempo na perna f_cine_data.h_tempo -= ff_delta_t # senão, estorou o tempo else: # nova fase f_atv.en_atv_fase = ldefs.E_FASE_VOLTA # permanência nos 30 graus do rumo para o setor 2 elif ldefs.E_FASE_TEMPOSETOR == f_atv.en_atv_fase: # permanece nos 30 graus ? if f_cine_data.h_tempo > 0.: # decrementa o tempo na perna f_cine_data.h_tempo -= ff_delta_t # senão, estorou o tempo else: # nova fase f_atv.en_atv_fase = ldefs.E_FASE_VOLTA # fase volta ? elif ldefs.E_FASE_VOLTA == f_atv.en_atv_fase: # acessa dados do fixo de espera e valida parâmetro l_fix = l_esp.ptr_esp_fix if (l_fix is None) or not l_fix.v_fix_ok: # logger l_log = logging.getLogger("prc_espera::prc_espera") l_log.setLevel(logging.ERROR) l_log.error("<E05: fixo da espera inexistente. aeronave: [%d/%s]", f_atv.i_trf_id, f_atv.s_trf_ind) # não encontrou o fixo, força a aeronave abandonar o procedimento abnd.abort_prc(f_atv) # fixo da espera inexistente. caifora... return # calcula distância da aeronave ao ponto (x, y) lf_coord_x = l_fix.f_fix_x - f_atv.f_trf_x lf_coord_y = l_fix.f_fix_y - f_atv.f_trf_y # calcula distância linear da aeronave ao ponto lf_dst_anv_pto = math.sqrt((lf_coord_x**2) + (lf_coord_y**2)) # calcula nova proa de demanda f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(lf_coord_x, lf_coord_y) # calcula novo sentido de curva scrv.sentido_curva(f_atv) # aeronave atingiu o fixo de espera ? (distância ao ponto <= passo da aeronave) if lf_dst_anv_pto <= math.sqrt((f_cine_data.f_delta_x**2) + (f_cine_data.f_delta_y**2)): # checa condição de cancelamento e ajusta a razão if __check_cancel_espera(f_atv, l_esp): # ajusta a razão de subida/descida f_atv.f_atv_raz_sub = f_atv.f_prf_raz_des_crz # break return # função operacional anterior era aproximação ? if ldefs.E_APROXIMACAO == f_atv.en_trf_fnc_ope_ant: # aeronave chegou na altitude do fixo de espera ? if f_atv.f_trf_alt_atu == f_atv.f_atv_alt_dem: # existe algo na pilha ? if len(f_stk_context) > 0: # desempilha o contexto f_atv.en_trf_fnc_ope, f_atv.en_atv_fase, f_atv.ptr_trf_prc, f_atv.ptr_atv_brk, f_cine_data.i_brk_ndx = f_stk_context.pop( ) # velocidade e proa f_atv.f_atv_vel_dem = f_atv.ptr_trf_prf.f_prf_vel_apx # f_esp_rumo (mlabru) f_atv.f_atv_pro_dem = l_esp.f_esp_true # calcula novo sentido de curva scrv.sentido_curva(f_atv) # razão de subida f_atv.f_atv_raz_sub = f_cine_data.f_raz_sub_des # break return # aprumar no rumo da espera (sentido afastamento) f_atv.f_atv_pro_dem = f_cine_data.f_afasta # entrar na órbita f_atv.en_atv_fase = ldefs.E_FASE_CRVAFASTA f_cine_data.i_setor_ent = 0 f_cine_data.i_bloqueio_fixo = 0 # espera a direita ? if ldefs.E_DIREITA == l_esp.en_esp_sentido_curva: if (1 == f_cine_data.i_setor_ent) and ( 1 == f_cine_data.i_bloqueio_fixo): # ajusta a razão de curva f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) else: # ajusta a razão de curva f_atv.f_atv_raz_crv = abs(f_atv.f_atv_raz_crv) # senão, espera a esquerda else: if (1 == f_cine_data.i_setor_ent) and ( 1 == f_cine_data.i_bloqueio_fixo): # ajusta a razão de curva f_atv.f_atv_raz_crv = abs(f_atv.f_atv_raz_crv) else: # ajusta a razão de curva f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) # fase curva de afastamento ? elif ldefs.E_FASE_CRVAFASTA == f_atv.en_atv_fase: # já aprumou ? if f_atv.f_trf_pro_atu == f_atv.f_atv_pro_dem: # obtém o tempo (limite de 14000FT) f_cine_data.h_tempo = 90. if ( f_atv.f_trf_alt_atu > M_14000FT) else 50. # sinaliza nova fase f_atv.en_atv_fase = ldefs.E_FASE_TEMPO # senão,... else: # logger l_log = logging.getLogger("prc_espera::prc_espera") l_log.setLevel(logging.ERROR) l_log.error("<E06: fase [{}/{}] da espera não identificada.".format( f_atv.en_atv_fase, ldefs.DCT_FASE[f_atv.en_atv_fase]))
def __ckeck_ok(f_atv, f_cine_data): """ verifica condições da aeronave para o direcionamento ao fixo @param f_atv: ponteiro para aeronave @param f_cine_data: ponteiro para pilha """ # check input assert f_atv assert f_cine_data # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("prc_dir_fixo::__check_ok") l_log.setLevel(logging.ERROR) l_log.error("<E01: aeronave não ativa.") # cai fora... return # aponta para o fixo a ser interceptado e valida ponteiro l_fix = f_atv.ptr_atv_fix_prc # M_LOG.debug("prc_dir_fixo::ptr_atv_fix_prc:[{}/{}].".format(f_atv.ptr_atv_fix_prc.i_fix_id, f_atv.ptr_atv_fix_prc.s_fix_desc)) if (l_fix is None) or (not l_fix.v_fix_ok): # logger l_log = logging.getLogger("prc_dir_fixo::__ckeck_ok") l_log.setLevel(logging.ERROR) l_log.error(u"<E02: fixo inexistente. aeronave:[{}/{}].".format( f_atv.i_trf_id, f_atv.s_trf_ind)) # não encontrou o fixo, força a aeronave abandonar o procedimento abnd.abort_prc(f_atv) # return return # VOR ? if ldefs.E_VOR == l_fix.en_fix_tipo: # calcula raio do cone de tolerância l_fix.f_fix_rcone = f_atv.f_trf_alt_atu * math.tan(math.radians(30)) # otherwise, outro tipo de fixo else: # calcula raio do cone de tolerância l_fix.f_fix_rcone = f_atv.f_trf_alt_atu * math.tan(math.radians(40)) # distância ao fixo <= raio do cone (ver DadosDinâmicos) if f_atv.f_atv_dst_fix <= l_fix.f_fix_rcone: # sinaliza que aeronave atingiu o ponto através raio do cone f_cine_data.v_interceptou_fixo = True # coloca em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # volta a fase de verificar condições f_atv.en_atv_fase = ldefs.E_FASE_ZERO # return interceptou o fixo return # calcula distância da aeronave ao fixo (x, y) lf_dst_x = f_cine_data.f_dst_anv_fix_x**2 lf_dst_y = f_cine_data.f_dst_anv_fix_y**2 # calcula distância do "passo" da aeronave (x, y) lf_dlt_x = f_cine_data.f_delta_x**2 lf_dlt_y = f_cine_data.f_delta_y**2 # aeronave atingiu fixo ? (distância <= passo da aeronave) if math.sqrt(lf_dst_x + lf_dst_y) <= math.sqrt(lf_dlt_x + lf_dlt_y): # considera que a aeronave atingiu o fixo pelas coordenadas x, y f_cine_data.v_interceptou_fixo = True # coloca em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # volta a fase de verificar condições f_atv.en_atv_fase = ldefs.E_FASE_ZERO # return interceptou o fixo return # calcula nova proa de demanda f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(f_cine_data.f_dst_anv_fix_x, f_cine_data.f_dst_anv_fix_y) # calcula sentido de curva pelo menor ângulo scrv.sentido_curva(f_atv) # ajusta a razão de curva da aeronave razc.calc_razao_curva(f_atv, l_fix.f_fix_x, l_fix.f_fix_y, f_cine_data) # nova fase de processamento f_atv.en_atv_fase = ldefs.E_FASE_DIRFIXO
def __direciona(f_atv, f_cine_data): """ direcionar a aeronave a um fixo específico @param f_atv: ponteiro para struct aeronaves @param f_cine_data: ponteiro para pilha """ # check input assert f_atv assert f_cine_data # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("prc_dir_fixo::__direciona") l_log.setLevel(logging.ERROR) l_log.error("<E01: aeronave não ativa.") # cai fora... return # pointer to beacon & check l_fix = f_atv.ptr_atv_fix_prc if (l_fix is None) or (not l_fix.v_fix_ok): # logger l_log = logging.getLogger("prc_dir_fixo::__direciona") l_log.setLevel(logging.ERROR) l_log.error(u"<E02: fixo inexistente. aeronave:[{}/{}].".format( f_atv.i_trf_id, f_atv.s_trf_ind)) # não encontrou o fixo, força a aeronave abandonar o procedimento abnd.abort_prc(f_atv) # return return # VOR ? if ldefs.E_VOR == l_fix.en_fix_tipo: # calcula raio do cone de tolerância do fixo l_fix.f_fix_rcone = f_atv.f_trf_alt_atu * math.tan(math.radians(30)) # otherwise, outro tipo... else: # calcula raio do cone de tolerância do fixo l_fix.f_fix_rcone = f_atv.f_trf_alt_atu * math.tan(math.radians(40)) # distância ao fixo <= raio do cone (ver DadosDinamicos) if f_atv.f_atv_dst_fix <= l_fix.f_fix_rcone: # sinaliza que aeronave atingiu o ponto através raio do cone f_cine_data.v_interceptou_fixo = True # coloca em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # volta a fase de verificar condições f_atv.en_atv_fase = ldefs.E_FASE_ZERO # return interceptou o fixo return # calcula distância da aeronave ao fixo (x, y) lf_dst_x = f_cine_data.f_dst_anv_fix_x**2 lf_dst_y = f_cine_data.f_dst_anv_fix_y**2 # calcula distância do "passo" da aeronave (x, y) lf_dlt_x = f_cine_data.f_delta_x**2 lf_dlt_y = f_cine_data.f_delta_y**2 # aeronave atingiu fixo ? (distância <= passo da aeronave) if math.sqrt(lf_dst_x + lf_dst_y) <= math.sqrt(lf_dlt_x + lf_dlt_y): # considera que a aeronave atingiu o fixo pelas coordenadas x, y f_cine_data.v_interceptou_fixo = True # coloca em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # volta a fase de verificar condições f_atv.en_atv_fase = ldefs.E_FASE_ZERO # return interceptou o fixo return # calcula nova proa de demanda f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(f_cine_data.f_dst_anv_fix_x, f_cine_data.f_dst_anv_fix_y) # verifica se mudou a proa (curvando...) if f_atv.f_atv_pro_dem != f_atv.f_trf_pro_atu: # bloqueia o fixo razc.calc_razao_curva(f_atv, l_fix.f_fix_x, l_fix.f_fix_y, f_cine_data)
def obtem_brk(f_atv, f_brk, f_cine_data): """ @param f_atv: pointer to struct aeronaves @param f_brk: pointer to struct breakpoints @param f_cine_data: pointer to kinematic data """ # logger # M_LOG.info("obtem_brk:>>") # check input assert f_atv assert f_cine_data # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("obtem_brk") l_log.setLevel(logging.ERROR) l_log.error(u"<E01: aeronave não ativa.") # cai fora... return # performance ok ? if (f_atv.ptr_trf_prf is None) or (not f_atv.ptr_trf_prf.v_prf_ok): # logger l_log = logging.getLogger("obtem_brk") l_log.setLevel(logging.ERROR) l_log.error(u"<E02: performance não existe.") # cai fora... return # breakpoint ok ? if (f_brk is None) or (not f_brk.v_brk_ok): # logger l_log = logging.getLogger("obtem_brk::obtem_brk") l_log.setLevel(logging.ERROR) l_log.error(u"<E03: breakpoint inexistente. aeronave:[{}/{}].".format( f_atv.i_trf_id, f_atv.s_trf_ind)) # não encontrou o breakpoint, força a abandonar o procedimento abnd.abort_prc(f_atv) # cai fora... return # + se a altitude NÃO foi alterada (i_atv_change_alt_vel = 0 ou 2) # - obtém a altitude do breakpoint # + se a altitude foi alterada (i_atv_change_alt_vel = 1 ou 3) # - mantém a altitude inserida pelo piloto e despreza as altitudes dos próximos pontos # i_atv_change_alt_vel = 0 > normal (sem alteração velocidade/altitude) # i_atv_change_alt_vel = 1 > mudou apenas a altitude # i_atv_change_alt_vel = 2 > mudou apenas a velocidade # i_atv_change_alt_vel = 3 > mudou ambas # subida ou trajetória ? if f_atv.en_trf_fnc_ope in [ldefs.E_SUBIDA, ldefs.E_TRAJETORIA]: # checa de onde obter a altitude # do breakpoint, da altitude de trajetória do tráfego ou da performance da aeronave # altitude NÃO foi alterada ? if (0 == f_atv.i_atv_change_alt_vel) or ( 2 == f_atv.i_atv_change_alt_vel): # é uma subida ? if ldefs.E_SUBIDA == f_atv.en_trf_fnc_ope: # breakpoint tem altitude ? if f_brk.f_brk_alt > 0.: # altitude do breakpoint maior (ou igual) ao teto de serviço ? if f_brk.f_brk_alt >= f_atv.ptr_trf_prf.f_prf_teto_sv: # demanda o teto de serviço f_atv.f_atv_alt_dem = f_atv.ptr_trf_prf.f_prf_teto_sv # otherwise, altitude abaixo do teto de serviço... else: # se altitude do ponto maior que altitude de trajetória do tráfego if (f_brk.f_brk_alt > f_atv.f_trf_alt_trj) and ( f_atv.f_trf_alt_trj > 0.): # demanda a altitude de trajetória do tráfego f_atv.f_atv_alt_dem = f_atv.f_trf_alt_trj # otherwise,... else: # demanda a altitude do breakpoint f_atv.f_atv_alt_dem = f_brk.f_brk_alt # é uma trajetória ? elif ldefs.E_TRAJETORIA == f_atv.en_trf_fnc_ope: # M_LOG.debug("obtem_brk:f_brk_alt:[{}].".format(f_brk.f_brk_alt)) # breakpoint tem altitude ? if f_brk.f_brk_alt > 0.: # altitude do breakpoint maior (ou igual) ao teto de serviço ? if f_brk.f_brk_alt >= f_atv.ptr_trf_prf.f_prf_teto_sv: # demanda o teto de serviço f_atv.f_atv_alt_dem = f_atv.ptr_trf_prf.f_prf_teto_sv # otherwise, abaixo do teto de serviço else: # demanda a altitude do breakpoint f_atv.f_atv_alt_dem = f_brk.f_brk_alt # otherwise, breakpoint não tem altitude else: # altitude de trajetória tem dado ? if f_atv.f_trf_alt_trj > 0.: # demanda a altitude de trajetória do tráfego f_atv.f_atv_alt_dem = f_atv.f_trf_alt_trj # otherwise, não é subida nem trajetória... else: # demanda a altitude do breakpoint ou o teto de serviço, quem for menor f_atv.f_atv_alt_dem = min(f_brk.f_brk_alt, f_atv.ptr_trf_prf.f_prf_teto_sv) # coordenada é do tipo 'T' (temporal) ? if f_brk.i_brk_t > 0: pass '''# aponta o fixo de referência # FIXO * l_pFix = None ; # &f_pAtm.AtmFix [ (int)f_brk.f_brk_x ] ; # !!!REVER!!! # calcula a projeção do ponto f_cine_data.fCoordXBkp = l_pFix.fFixX + ( f_atv.f_trf_vel_atu * f_brk.i_brk_t * sinf ( f_brk.f_brk_y )) f_cine_data.fCoordYBkp = l_pFix.fFixY + ( f_atv.f_trf_vel_atu * f_brk.i_brk_t * cosf ( f_brk.f_brk_y )) ''' # coordenada é do tipo 'R' (rumo e altitude) elif f_brk.i_brk_t < 0: pass '''# é razão ou gradiente ? if f_brk.f_brk_x <= 0.: # obtém a razão de subida f_atv.f_atv_raz_sub = f_atv.ptr_trf_prf.f_prf_raz_sub_crz # otherwise,... else: # o gradiente é uma porcentagem e uma razão de subida um valor inteiro. O # gradiente nunca é maior que 10%. A razão de subida sempre é maior que # 100ft/min. Assumir que valores maiores que 10 é razão de subida e valores # menores ou iguais a 10 é gradiente. # ref: Tratamento do Gradiente de Subida conforme MMA 100-31, pag.108. # é gradiente ? if f_brk.f_brk_x <= 10.: # aplica a forma simplificada do gradiente !!!REVER!!! li_val = int(f_atv.f_trf_vel_atu * f_brk.f_brk_x) # calcula o módulo 50 li_mod = li_val % 50 if li_mod > 0: # se não for múltiplo de 50, arrendondar para o múltiplo mais próximo if li_mod < 26: li_val -= li_mod else: li_val += 50 - li_mod # armazena o gradiente aplicado o múltiplo de 50 f_atv.f_atv_raz_sub = float(li_val) # otherwise, é uma razão de subida else: # armazena a razão de subida (ft/min -> m/s) f_atv.f_atv_raz_sub = f_brk.f_brk_x * cdefs.D_CNV_FT2M / 60. # obtém o rumo f_atv.f_atv_pro_dem = math.degrees(f_brk.f_brk_y) # calcula a curva pelo menor lado scrv.sentido_curva(f_atv) ''' # otherwise, 0 == f_brk.i_brk_t else: # armazena na pilha as coordenadas cartesianas do breakpoint f_cine_data.f_coord_x_brk = f_brk.f_brk_x f_cine_data.f_coord_y_brk = f_brk.f_brk_y # M_LOG.debug("obtem_brk:f_cine_data.f_brk_x:[{}] f_cine_data.f_brk_y:[{}]".format(f_cine_data.f_coord_x_brk, f_cine_data.f_coord_y_brk)) # trata o procedimento que chamou a rotina # trajetória ? if ldefs.E_TRAJETORIA == f_atv.en_trf_fnc_ope: # checks assert f_atv.ptr_trf_prc assert f_atv.ptr_trf_prc.v_prc_ok # + se a velocidade NÃO foi alterada (i_atv_change_alt_vel = 0 ou 1) # - obtém a velocidade do breakpoint # + se a velocidade foi alterada (i_atv_change_alt_vel = 2 ou 3) # - mantém a velocidade inserida pelo piloto e despreza as velocidades dos próximos pontos # i_atv_change_alt_vel = 0 > normal (sem alteração velocidade/altitude) # i_atv_change_alt_vel = 1 > mudou apenas a altitude, # i_atv_change_alt_vel = 2 > mudou apenas a velocidade # i_atv_change_alt_vel = 3 > mudou ambas # checa de onde obter a velocidade # do breakpoint, velocidade do tráfego ou performance # velocidade NÃO foi alterada ? if (0 == f_atv.i_atv_change_alt_vel) or ( 1 == f_atv.i_atv_change_alt_vel): # star ? if f_atv.ptr_trf_prc.v_trj_star: # breakpoint tem velocidade ? if f_brk.f_brk_vel > 0.: # converte a VelMaxCrz para IAS lf_vel = f_atv.ptr_trf_prf.f_prf_vel_max_crz # calcIAS(f_atv.ptr_trf_prf.f_prf_vel_max_crz, f_atv.f_atv_alt_dem, Exercicio.fExeVarTempISA) # demanda a velocidade do breakpoint ou VelMaxCrz (IAS) o que for menor f_atv.f_atv_vel_dem = min(f_brk.f_brk_vel, lf_vel) # otherwise, é trajetória ACC... else: # velocidade de trajetória do tráfego tem dado ? if f_atv.f_trf_vel_trj > 0.: # demanda a velocidade de trajetória do tráfego (convertido para IAS na conversão) f_atv.f_atv_vel_dem = f_atv.f_trf_vel_trj # otherwise, não tem velocidade de trajetória do tráfego... else: # breakpoint tem velocidade ? if f_brk.f_brk_vel > 0.: # velocidade do breakpoint extrapolou o limite da performance ? if f_brk.f_brk_vel > f_atv.ptr_trf_prf.f_prf_vel_max_crz: # demanda a VelMaxCrz convertida para IAS f_atv.f_atv_vel_dem = f_atv.ptr_trf_prf.f_prf_vel_max_crz # calcIAS(f_atv.ptr_trf_prf.fAtrPrfVelMaxCrz, f_atv.f_atv_alt_dem, Exercicio.fExeVarTempISA) # velocidade do breakpoint abaixo do limite da performance... else: # demanda a velocidade do breakpoint convertida para IAS f_atv.f_atv_vel_dem = f_brk.f_brk_vel # calcIAS(f_brk.f_brk_vel, f_atv.f_atv_alt_dem, Exercicio.fExeVarTempISA) # otherwise, breakpoint não tem velocidade... else: # demanda a velocidade atual do tráfego f_atv.f_atv_vel_dem = f_atv.f_trf_vel_atu # força cálculo do MACH # f_atv.vAnvISOMACH = False # ajustar a razão de subida ou descida da aeronave em trajetória # aeronave descendo ? if f_atv.f_trf_alt_atu > f_atv.f_atv_alt_dem: # aplica a razão de descida em cruzeiro f_atv.f_atv_raz_sub = f_atv.ptr_trf_prf.f_prf_raz_des_crz # aeronave subindo ? elif f_atv.f_trf_alt_atu < f_atv.f_atv_alt_dem: # aplica a razão de subida em cruzeiro f_atv.f_atv_raz_sub = f_atv.ptr_trf_prf.f_prf_raz_sub_crz # aeronave nivelada ? elif f_atv.f_trf_alt_atu == f_atv.f_atv_alt_dem: # não aplica a razão de subida ou descida f_atv.f_atv_raz_sub = 0. # subida ? elif ldefs.E_SUBIDA == f_atv.en_trf_fnc_ope: # teste de altimetria para corrigir o caso em que a aeronave ao cumprir pontos sem o # valor da "altitude", ela possa manter o valor da última altitude de demanda. Com a # "altitude do breakpoint sem valor", forçava a aeronave a entrar na condição de vôo # abaixo de 10000FT, o que não é correto, pois, a mesma já cumpriu esta etapa do vôo # obtém altitude do ponto atual lf_brk_alt = f_brk.f_brk_alt # extrapolou o limite da performance ? if f_brk.f_brk_alt > f_atv.ptr_trf_prf.f_prf_teto_sv: # ajusta a altitude pela performance lf_brk_alt = f_atv.ptr_trf_prf.f_prf_teto_sv # breakpoint NÃO tem altitude ? if 0 == lf_brk_alt: # mantém a altitude de demanda do ponto anterior lf_brk_alt = f_atv.f_atv_alt_dem # converte a velocidade de cruzeiro da performance para IAS lf_vel = f_atv.ptr_trf_prf.f_prf_vel_crz # calcIAS(f_atv.ptr_trf_prf.f_prf_vel_crz, f_atv.f_atv_alt_dem, Exercicio.fExeVarTempISA) # altitude do breakpoint é menor (ou igual) que altitude máxima na TMA ? if (lf_brk_alt * cdefs.D_CNV_M2FT) <= ldefs.D_ALT_MAX_TMA: # velocidade de subida na DEP é maior que 250KT ? if f_atv.ptr_trf_prf.f_prf_vel_sub_dec >= ldefs.D_VEL_MAX_TMA: # velocidade NÃO foi alterada ? if (0 == f_atv.i_atv_change_alt_vel) or ( 1 == f_atv.i_atv_change_alt_vel): # velocidade do breakpoint é valida ? if 0. < f_brk.f_brk_vel <= ldefs.D_VEL_MAX_TMA: # demanda a velocidade da performance ou a velocidade do breakpoint, o que for menor f_atv.f_atv_vel_dem = min(lf_vel, f_brk.f_brk_vel) # otherwise, inválida... else: # demanda a velocidade da performance ou a velocidade limite 250KT, o que for menor f_atv.f_atv_vel_dem = min(lf_vel, ldefs.D_VEL_MAX_TMA) # otherwise, velocidade de subida na DEP está abaixo de 250KT else: # velocidade NÃO foi alterada ? if (0 == f_atv.i_atv_change_alt_vel) or ( 1 == f_atv.i_atv_change_alt_vel): # velocidade do breakpoint é valida ? if 0. < f_brk.f_brk_vel <= ldefs.D_VEL_MAX_TMA: # demanda a velocidade da performance ou a velocidade do breakpoint, o que for menor f_atv.f_atv_vel_dem = min(lf_vel, f_brk.f_brk_vel) # otherwise, inválida... else: # demanda a velocidade da performance ou a velocidade limite 250KT, o que for menor f_atv.f_atv_vel_dem = min(lf_vel, f_brk.f_brk_vel) # otherwise, altitude do breakpoint é maior que a altitude máxima na TMA... else: # velocidade NÃO foi alterada ? if (0 == f_atv.i_atv_change_alt_vel) or ( 1 == f_atv.i_atv_change_alt_vel): # breakpoint tem velocidade ? if f_brk.f_brk_vel > 0.: # demanda a velocidade da performance ou velocidade do breakpoint, o que for menor f_atv.f_atv_vel_dem = min(lf_vel, f_brk.f_brk_vel) # velocidade da performance maior que velocidade de demanda atual ? elif lf_vel > f_atv.f_atv_vel_dem: # demanda a velocidade da performance (cruzeiro) f_atv.f_atv_vel_dem = lf_vel # coordenada cartesiana ou temporal ? if f_brk.i_brk_t >= 0: # obtém a razão de subida de cruzeiro f_atv.f_atv_raz_sub = f_atv.ptr_trf_prf.f_prf_raz_sub_crz # tem gradiente entre os pontos ? if 0. != f_brk.f_brk_raz_vel: # calcula a razão de subida em função do gradiente f_atv.f_atv_raz_sub += f_atv.f_trf_vel_atu * f_brk.f_brk_raz_vel # otherwise, NÃO tem gradiente entre os pontos... else: # obtém a razão de subida da performance f_atv.f_atv_raz_sub = f_atv.ptr_trf_prf.f_prf_raz_sub_crz # aproximação ou aproximação perdida elif f_atv.en_trf_fnc_ope in [ldefs.E_APROXIMACAO, ldefs.E_APXPERDIDA]: # aproximação perdida ? if ldefs.E_APXPERDIDA == f_atv.en_trf_fnc_ope: # demanda a velocidade de subida na decolagem f_atv.f_atv_vel_dem = f_atv.ptr_trf_prf.f_prf_vel_sub_dec # former case, fall throught to next item # coordenada cartesiana ou temporal ? if f_brk.i_brk_t >= 0: # desacelerando ? if f_brk.f_brk_raz_vel <= 0.: # razão de desaceleração de descida na aproximação f_atv.f_atv_raz_sub = f_atv.ptr_trf_prf.f_prf_raz_des_apx # otherwise, acelerando... else: # razão de velocidade f_atv.f_atv_raz_sub = f_brk.f_brk_raz_vel # otherwise, função operacional não reconhecida... else: # logger l_log = logging.getLogger("obtem_brk::obtem_brk") l_log.setLevel(logging.ERROR) l_log.error(u"<E04: função operacional [{}] não reconhecida.".format( ldefs.DCT_FNC_OPE[f_atv.en_trf_fnc_ope])) # cooredenada coordenadas rumo/azimute ? if f_brk.i_brk_t < 0: # seleciona próxima fase f_atv.en_atv_fase = ldefs.E_FASE_RUMOALT # otherwise, outro tipo de coordenada... else: # seleciona próxima fase f_atv.en_atv_fase = ldefs.E_FASE_DIRPONTO
def prc_subida(f_atv, f_cine_data, f_stk_context): """ realiza o procedimento de subida após o procedimento de decolagem @param f_atv: pointer to struct aeronaves @param f_cine_data: dados da cinemática @param f_stk_context: pointer to stack """ # check input assert f_atv assert f_stk_context is not None # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("prc_subida") l_log.setLevel(logging.ERROR) l_log.error("<E01: aeronave [{}/{}] não ativa.".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # aeronave não ativa. cai fora... return False # pointer to subida l_sub = f_atv.ptr_trf_prc # subida ok ? if (l_sub is None) or (not l_sub.v_prc_ok): # logger l_log = logging.getLogger("prc_subida") l_log.setLevel(logging.ERROR) l_log.error("<E02: subida inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # subida inexistente. cai fora... return # fase de iniciação ? if ldefs.E_FASE_ZERO == f_atv.en_atv_fase: # inicia o contador de breakpoints f_cine_data.i_brk_ndx = 0 # empilha o contexto futuro f_stk_context.append((f_atv.en_trf_fnc_ope, ldefs.E_FASE_SUBIDA, l_sub, None, 0)) # salva a subida f_cine_data.ptr_sub = l_sub # obtém o aeródromo e pista da subida f_cine_data.ptr_aer = l_sub.ptr_sub_aer f_cine_data.ptr_pis = l_sub.ptr_sub_pis # carrega o contexto atual f_atv.ptr_trf_prc = l_sub.ptr_sub_prc_dec f_atv.en_trf_fnc_ope = ldefs.E_DECOLAGEM f_atv.en_atv_fase = ldefs.E_FASE_ZERO # fase subida ? elif ldefs.E_FASE_SUBIDA == f_atv.en_atv_fase: # inicia com o número do breakpoint atual l_brk = f_atv.ptr_atv_brk = l_sub.lst_sub_brk[f_cine_data.i_brk_ndx] # breakpoint ok ? if (l_brk is None) or (not l_brk.v_brk_ok): # logger l_log = logging.getLogger("prc_subida") l_log.setLevel(logging.ERROR) l_log.error("<E03: subida/breakpoint inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # subida/breakpoint inexistente. cai fora... return # obtém dados do breakpoint da subida obrk.obtem_brk(f_atv, l_brk, f_cine_data) # fase direcionamento a ponto ? elif ldefs.E_FASE_DIRPONTO == f_atv.en_atv_fase: # chegou ao breakpoint ? if dp.prc_dir_ponto(f_atv, f_cine_data.f_coord_x_brk, f_cine_data.f_coord_y_brk, f_cine_data): # próxima fase f_atv.en_atv_fase = ldefs.E_FASE_BREAKPOINT # obtém o breakpoint atual l_brk = f_atv.ptr_atv_brk # breakpoint ok ? if (l_brk is None) or (not l_brk.v_brk_ok): # logger l_log = logging.getLogger("prc_subida") l_log.setLevel(logging.ERROR) l_log.error("<E04: subida/breakpoint inexistente. aeronave:[{}/{}].".format(f_atv.i_atv_id, f_atv.s_atv_ind)) # abort procedure abnd.abort_prc(f_atv) # subida/breakpoint inexistente. cai fora... return # trata o procedimento associado tass.trata_associado(f_atv, l_brk, f_cine_data.i_brk_ndx, f_stk_context) # fase rumo e altitude ? elif ldefs.E_FASE_RUMOALT == f_atv.en_atv_fase: # altitude atual(ft) é maior que a altitude máxima da TMA(ft) ? if (f_atv.f_atv_alt_atu * cdefs.D_CNV_M2FT) > ldefs.D_ALT_MAX_TMA: # ajusta a velocidade de demanda em função do nível de vôo f_atv.f_atv_vel_dem = f_atv.f_ptr_prf.f_prf_vel_crz # calcIAS(f_atv.f_ptr_prf.f_prf_vel_crz, f_atv.f_atv_alt_atu, ldefs.D_EXE_VAR_TEMP_ISA) # proa e a altitude estão estabilizadas ? if (f_atv.f_atv_pro_atu == f_atv.f_atv_pro_dem) and (f_atv.f_atv_alt_atu == f_atv.f_atv_alt_dem): # nova fase f_atv.en_atv_fase = ldefs.E_FASE_BREAKPOINT # trata o procedimento associado tass.trata_associado(f_atv, l_brk, f_cine_data.i_brk_ndx, f_stk_context) # fase breakpoints ? elif ldefs.E_FASE_BREAKPOINT == f_atv.en_atv_fase: # é o último breakpoint da subida ? if f_atv.ptr_atv_brk == l_sub.lst_sub_brk[-1]: # reseta o flag altitude/velocidade f_atv.i_atv_change_alt_vel = 0 # restaura pilha, se necessário tass.restaura_associado(f_atv, f_cine_data, f_stk_context) # otherwise, NÃO é o último breakpoint da subida... else: # próximo breakpoint f_cine_data.i_brk_ndx += 1 # aponta para o próximo breakpoint l_brk = f_atv.ptr_atv_brk = l_sub.lst_sub_brk[f_cine_data.i_brk_ndx] # breakpoint ok ? if (l_brk is None) or (not l_brk.v_brk_ok): # logger l_log = logging.getLogger("prc_subida") l_log.setLevel(logging.ERROR) l_log.error("<E05: subida/breakpoint inexistente. aeronave:[{}/{}].".format(f_atv.i_atv_id, f_atv.s_atv_ind)) # abort procedure abnd.abort_prc(f_atv) # subida/breakpoint inexistente. cai fora... return # obtém dados do breakpoint atual obrk.obtem_brk(f_atv, l_brk, f_cine_data) # otherwise, fase não identificada else: # logger l_log = logging.getLogger("prc_subida") l_log.setLevel(logging.ERROR) l_log.error("<E06: fase na subida não identificada.") # abort procedure abnd.abort_prc(f_atv)
def prc_aproximacao(f_atv, f_cine_data, f_stk_context): """ realiza o procedimento de aproximação @param f_atv: pointer to aeronave @param f_cine_data: dados da cinemática @param f_stk_context: pointer to stack """ # check input assert f_atv # active flight ? if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("prc_aproximacao") l_log.setLevel(logging.ERROR) l_log.error(u"<E01: aeronave não ativa.") # abort procedure abnd.abort_prc(f_atv) # cai fora... return # performance ok ? if (f_atv.ptr_trf_prf is None) or (not f_atv.ptr_trf_prf.v_prf_ok): # logger l_log = logging.getLogger("prc_aproximacao") l_log.setLevel(logging.ERROR) l_log.error(u"<E02: performance não existe.") # abort procedure abnd.abort_prc(f_atv) # cai fora... return # pointer to aproximação l_apx = f_atv.ptr_trf_prc # aproximação ok ? if (l_apx is None) or (not l_apx.v_prc_ok): # logger l_log = logging.getLogger("prc_aproximacao") l_log.setLevel(logging.ERROR) l_log.error(u"<E03: aproximação inexistente. aeronave:[{}/{}].".format( f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # return return # variáveis locais l_brk = None # fase de preparação dos dados para o procedimento ? if ldefs.E_FASE_ZERO == f_atv.en_atv_fase: # inicia o index de breakpoints f_cine_data.i_brk_ndx = 0 # inicia com dados do primeiro breakpoint l_brk = f_atv.ptr_atv_brk = l_apx.lst_apx_brk[0] # breakpoint ok ? if (l_brk is None) or (not l_brk.v_brk_ok): # logger l_log = logging.getLogger("prc_aproximacao") l_log.setLevel(logging.ERROR) l_log.error( u"<E04: fase zero. apx/breakpoint inexistente. aeronave:[{}/{}]." .format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # return return # obtém dados do breakpoint obrk.obtem_brk(f_atv, l_brk, f_cine_data) # fase de direcionamento aos breakpoints do procedimento ? elif ldefs.E_FASE_DIRPONTO == f_atv.en_atv_fase: # interceptou o breakpoint ? if dp.prc_dir_ponto(f_atv, f_cine_data.f_coord_x_brk, f_cine_data.f_coord_y_brk, f_cine_data): # se não houver um procedimento associado, faz uma espera, senão executa o procedimento f_atv.en_atv_fase = ldefs.E_FASE_ESPERA if f_atv.ptr_atv_brk is not None else ldefs.E_FASE_ASSOCIADO # fase rumo e altitude ? elif ldefs.E_FASE_RUMOALT == f_atv.en_atv_fase: # atingiu a proa e a altitude de demanda estabelecidas ? if (f_atv.f_trf_pro_atu == f_atv.f_atv_pro_dem) and (f_atv.f_trf_alt_atu == f_atv.f_atv_alt_dem): # se não houver um procedimento associado, faz uma espera, senão executa o procedimento f_atv.en_atv_fase = ldefs.E_FASE_ESPERA if f_atv.ptr_atv_brk is not None else ldefs.E_FASE_ASSOCIADO # fase de espera ? (mantém a aeronave em orbita até alcançar a altitude do breakpoint) elif ldefs.E_FASE_ESPERA == f_atv.en_atv_fase: # dados do breakpoint l_brk = f_atv.ptr_atv_brk assert l_brk # NÃO atingiu a altitude do breakpoint ? if f_atv.f_trf_alt_atu != l_brk.f_brk_alt: # obtém dados do breakpoint (Espera com altitude de demanda) obrk.obtem_brk(f_atv, l_brk, f_cine_data) # empilha o contexto atual devido a mudança na função operacional f_stk_context.append( (f_atv.en_trf_fnc_ope, ldefs.E_FASE_ASSOCIADO, f_atv.ptr_trf_prc, f_atv.ptr_atv_brk, f_cine_data.i_brk_ndx)) # salva a função operacional atual f_atv.en_trf_fnc_ope_ant = ldefs.E_APROXIMACAO # estabelece a nova função operacional e a nova fase por não ter atingido a altitude do breakpoint f_atv.en_trf_fnc_ope = ldefs.E_ESPERA f_atv.en_atv_fase = ldefs.E_FASE_ZERO f_atv.ptr_trf_prc = l_apx.ptr_apx_prc_esp # otherwise, atingiu a altitude do breakpoint... else: # estabelece nova velocidade de demanda e sinaliza nova fase f_atv.f_atv_vel_dem = f_atv.ptr_trf_prf.f_prf_vel_apx f_atv.en_atv_fase = ldefs.E_FASE_ASSOCIADO # fase associado ? (identifica se houve encadeamento de outros procedimentos) elif ldefs.E_FASE_ASSOCIADO == f_atv.en_atv_fase: # dados do breakpoint l_brk = f_atv.ptr_atv_brk assert l_brk # sinaliza nova fase f_atv.en_atv_fase = ldefs.E_FASE_BREAKPOINT # existe procedimento associado (APX, APE, TRJ, ESP...) ao breakpoint ? if tass.trata_associado(f_atv, l_brk, f_cine_data.i_brk_ndx, f_stk_context): # é o último breakpoint da aproximação atual ? if f_atv.ptr_atv_brk == l_apx.lst_apx_brk[-1]: f_cine_data.i_brk_ndx -= 1 # já passou por todos os breakpoints ? elif ldefs.E_FASE_BREAKPOINT == f_atv.en_atv_fase: # é o último breakpoint da aproximação atual ? if f_atv.ptr_atv_brk == l_apx.lst_apx_brk[-1]: # possível ILS ? if l_apx.ptr_apx_prc_ils is not None: # ils ok ? if __obtem_ils(f_atv, l_apx): # coloca em procedimento de ILS f_atv.en_trf_fnc_ope = ldefs.E_ILS f_atv.en_atv_fase = ldefs.E_FASE_ZERO # otherwise, ils not ok... else: # coloca em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # pode fazer aproximação perdida caso não esteja em condições para aproximação ? if l_apx.ptr_apx_prc_ape is not None: # dados do breakpoint l_brk = f_atv.ptr_atv_brk assert l_brk # está em condição de pouso ? if (abs(f_atv.f_trf_alt_atu - l_brk.f_brk_alt) <= 0.01) and ( abs(f_atv.f_trf_vel_atu - f_atv.ptr_trf_prf.f_prf_vel_apx) <= 0.01): # pouso ok ? if not __obtem_pouso(f_atv, l_apx): # coloca em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # otherwise, NÃO está em condição de pouso... else: # aproximação perdida ok ? if __obtem_apx_per(f_atv, l_apx): # prepara para procedimento de aproximação perdida f_atv.en_trf_fnc_ope = ldefs.E_APXPERDIDA f_atv.en_atv_fase = ldefs.E_FASE_ZERO # otherwise, aproximação perdida not ok... else: # coloca em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # otherwise, NÃO pode fazer aproximação perdida nem ILS, faz pouso forçado... else: # pouso ok ? if not __obtem_pouso(f_atv, l_apx): # coloca em manual f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # otherwise, não é o último breakpoint else: # próximo breakpoint f_cine_data.i_brk_ndx += 1 # aponta para o próximo breakpoint l_brk = f_atv.ptr_atv_brk = l_apx.lst_apx_brk[ f_cine_data.i_brk_ndx] # breakpoint ok ? if (l_brk is None) or (not l_brk.v_brk_ok): # logger l_log = logging.getLogger("prc_aproximacao") l_log.setLevel(logging.ERROR) l_log.error( u"<E05: fase breakpoint. apx/breakpoint inexistente. aeronave:[{}/{}]." .format(f_atv.i_trf_id, f_atv.s_trf_ind)) # abort procedure abnd.abort_prc(f_atv) # apx/breakpoint inexistente. cai fora... return # obtém dados do breakpoint obrk.obtem_brk(f_atv, l_brk, f_cine_data) # otherwise,... else: # logger l_log = logging.getLogger("prc_aproximacao") l_log.setLevel(logging.ERROR) l_log.error( u"<E06: fase da aproximação não identificada. fase:[{}].".format( ldefs.DCT_FASE[f_atv.en_atv_fase]))