def prc_pouso(f_atv): """ @param f_atv: ponteiro para struct aeronaves """ # globais global glb_ui_ang_teta, glb_f_dst_eixo, glb_f_dst_rampa, glb_f_dst_anv_ptq global glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y, glb_f_raio_curva # 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_pouso") l_log.setLevel(logging.ERROR) l_log.error("<E01: aeronave não ativa.") # 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_pouso") l_log.setLevel(logging.ERROR) l_log.error(u"<E02: performance não existe.") # performance não existe. cai fora... return # posição da aeronave (dir/esq) em relação ao eixo da pista len_pos_anv = 0 # pointer to aerodrome l_aer = f_atv.ptr_atv_aer if (l_aer is None) or (not l_aer.v_aer_ok): # logger l_log = logging.getLogger("prc_pouso") l_log.setLevel(logging.ERROR) l_log.error(u"<E03: aeródromo inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # aerodrome not found, abort procedure abnd.abort_prc(f_atv) # aeródromo inexistente. cai fora... return # pointer to runway l_pst = f_atv.ptr_atv_pst if (l_pst is None) or (not l_pst.v_pst_ok): # logger l_log = logging.getLogger("prc_pouso") l_log.setLevel(logging.ERROR) l_log.error(u"<E04: pista inexistente. aeronave:[{}/{}].".format(f_atv.i_trf_id, f_atv.s_trf_ind)) # runway not found, abort procedure abnd.abort_prc(f_atv) # pista inexistente. cai fora... return # fases do procedimento de pouso # fase de preparação para o procedimento ? if ldefs.E_FASE_ZERO == f_atv.en_atv_fase: # velocidade de aproximação f_atv.f_atv_vel_dem = f_atv.ptr_trf_prf.f_prf_vel_apx # M_LOG.debug("prc_pouso:f_atv.f_atv_vel_dem:[{}]".format(f_atv.f_atv_vel_dem)) # estabiliza a altitude f_atv.f_atv_alt_dem = f_atv.f_trf_alt_atu # M_LOG.debug("prc_pouso:f_atv.f_atv_alt_dem:[{}]".format(f_atv.f_atv_alt_dem)) # calcula o raio de curvatura assert abs(f_atv.f_atv_raz_crv) > 0 # M_LOG.debug("prc_pouso:f_atv.f_atv_raz_crv:[{}]".format(f_atv.f_atv_raz_crv)) glb_f_raio_curva = f_atv.f_trf_vel_atu / abs(math.radians(f_atv.f_atv_raz_crv)) # M_LOG.debug("prc_pouso:glb_f_raio_curva:[{}]".format(glb_f_raio_curva)) # calcula o ponto de toque glb_f_dst_anv_ptq_x = l_pst.f_pst_x - f_atv.f_trf_x # M_LOG.debug("prc_pouso:glb_f_dst_anv_ptq_x:[{}]".format(glb_f_dst_anv_ptq_x)) glb_f_dst_anv_ptq_y = l_pst.f_pst_y - f_atv.f_trf_y # M_LOG.debug("prc_pouso:glb_f_dst_anv_ptq_y:[{}]".format(glb_f_dst_anv_ptq_y)) # posição da aeronave em relação a pista (dir/esq) len_pos_anv = scrv.sent_crv(l_pst.i_pst_rumo, cpd.calc_proa_demanda(-glb_f_dst_anv_ptq_x, -glb_f_dst_anv_ptq_y)) # M_LOG.debug("prc_pouso:len_pos_anv:[{}]".format(len_pos_anv)) # calcula ângulo formado pela aeronave e a pista (teta) glb_ui_ang_teta = abs(l_pst.i_pst_rumo - cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y)) if glb_ui_ang_teta > 180.: glb_ui_ang_teta = 360. - glb_ui_ang_teta # M_LOG.debug("prc_pouso:glb_ui_ang_teta:[{}]".format(glb_ui_ang_teta)) # calcula distância da aeronave ao ponto (em linha reta) glb_f_dst_anv_ptq = math.sqrt((glb_f_dst_anv_ptq_x ** 2) + (glb_f_dst_anv_ptq_y ** 2)) # M_LOG.debug("prc_pouso:glb_f_dst_anv_ptq:[{}]".format(glb_f_dst_anv_ptq)) # calcula distância do eixo da pista glb_f_dst_eixo = abs(glb_f_dst_anv_ptq * math.sin(math.radians(glb_ui_ang_teta))) # M_LOG.debug("prc_pouso:glb_f_dst_eixo:[{}]".format(glb_f_dst_eixo)) # calcula distância da rampa assert abs(math.tan(math.radians(ldefs.D_DST_RAMPA))) > 0 glb_f_dst_rampa = (f_atv.f_trf_alt_atu - l_aer.f_aer_elev) / math.tan(math.radians(ldefs.D_DST_RAMPA)) # M_LOG.debug("prc_pouso:glb_f_dst_rampa:[{}]".format(glb_f_dst_rampa)) # aeronave afastada mais de 2R do eixo da pista ? if glb_f_dst_eixo >= (2 * glb_f_raio_curva): # aeronave pelo menos (3R + distância na rampa) antes da cabeceira ? if (glb_ui_ang_teta < 90.) and (abs(glb_f_dst_anv_ptq * math.cos(math.radians(glb_ui_ang_teta))) >= ((3 * glb_f_raio_curva) + glb_f_dst_rampa)): # aeronave a direita da pista ? if ldefs.E_DIREITA == len_pos_anv: # aeronave a direita da pista f_atv.f_atv_pro_dem = l_pst.i_pst_rumo - 90. if f_atv.f_atv_pro_dem < 0: f_atv.f_atv_pro_dem += 360. # otherwise,... else: # aeronave a esquerda da pista f_atv.f_atv_pro_dem = l_pst.i_pst_rumo + 90. if f_atv.f_atv_pro_dem >= 360.: f_atv.f_atv_pro_dem -= 360. # calcula sentido de curva pelo menor ângulo scrv.sentido_curva(f_atv) # voa para interceptar eixo da pista f_atv.en_atv_fase = ldefs.E_FASE_EIXO # otherwise,... else: # aeronave após a distância que garante condição de alinhamento f_atv.f_atv_pro_dem = l_pst.i_pst_rumo + 180. if f_atv.f_atv_pro_dem >= 360.: f_atv.f_atv_pro_dem -= 360. # aeronave a direita da pista ? if ldefs.E_DIREITA == len_pos_anv: # aeronave a direita da pista f_atv.f_atv_raz_crv = abs(f_atv.f_atv_raz_crv) # otherwise,... else: # aeronave a esquerda da pista f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) # define nova fase f_atv.en_atv_fase = ldefs.E_FASE_OPOSTA # otherwise,... else: # aeronave está no eixo da pista ? if abs(glb_f_dst_eixo) <= 0.01: # aeronave está no rumo da pista ? if abs(f_atv.f_trf_pro_atu - l_pst.i_pst_rumo) <= 0.01: # aeronave antes da rampa ? if (glb_ui_ang_teta < 90.) and (abs(glb_f_dst_anv_ptq * math.cos(math.radians(glb_ui_ang_teta))) >= glb_f_dst_rampa): # voar até iniciar rampa f_atv.en_atv_fase = ldefs.E_FASE_ALINHAR # otherwise,... else: # aeronave após a rampa f_atv.f_atv_pro_dem = l_pst.i_pst_rumo - 90. if f_atv.f_atv_pro_dem < 0: f_atv.f_atv_pro_dem += 360. # ajusta razão de curva para esquerda f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) # voar até se afastar 2R do eixo f_atv.en_atv_fase = ldefs.E_FASE_AFASTA # otherwise, proas diferentes else: # proa da aeronave oposta a da pista ? if (abs(l_pst.i_pst_rumo - f_atv.f_trf_pro_atu) - 180.) <= 0.01: # aeronave após a rampa f_atv.f_atv_pro_dem = l_pst.i_pst_rumo + 90. if f_atv.f_atv_pro_dem >= 360.: f_atv.f_atv_pro_dem -= 360. # ajusta razão de curva para esquerda f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) # voar até se afastar 2R do eixo f_atv.en_atv_fase = ldefs.E_FASE_AFASTA # otherwise, distância do eixo menor 2R else: # aeronave a direita da pista ? if ldefs.E_DIREITA == len_pos_anv: f_atv.f_atv_pro_dem = l_pst.i_pst_rumo + 90. if f_atv.f_atv_pro_dem >= 360.: f_atv.f_atv_pro_dem -= 360. # otherwise, aeronave a esquerda da pista else: f_atv.f_atv_pro_dem = l_pst.i_pst_rumo - 90. if f_atv.f_atv_pro_dem < 0: f_atv.f_atv_pro_dem += 360. # força a curva pelo menor lado scrv.sentido_curva(f_atv) # voar até se afastar 2R do eixo f_atv.en_atv_fase = ldefs.E_FASE_AFASTA # fase voando até se afastar 2R do eixo da pista ? elif ldefs.E_FASE_AFASTA == f_atv.en_atv_fase: # calcula o raio de curvatura assert abs(f_atv.f_atv_raz_crv) > 0 glb_f_raio_curva = f_atv.f_trf_vel_atu / abs(math.radians(f_atv.f_atv_raz_crv)) # calcula o ponto de toque glb_f_dst_anv_ptq_x = l_pst.f_pst_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_y - f_atv.f_trf_y # calcula ângulo formado pela aeronave e a pista (teta) glb_ui_ang_teta = abs(l_pst.i_pst_rumo - cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y)) if glb_ui_ang_teta > 180.: glb_ui_ang_teta = 360. - glb_ui_ang_teta # calcula a distância ao ponto de toque (em linha reta) glb_f_dst_anv_ptq = math.sqrt((glb_f_dst_anv_ptq_x ** 2) + (glb_f_dst_anv_ptq_y ** 2)) # calcula a distância ao eixo glb_f_dst_eixo = abs(glb_f_dst_anv_ptq * math.sin(math.radians(glb_ui_ang_teta))) # aeronave distante pelo menos 2R do eixo da pista ? if glb_f_dst_eixo >= (2 * glb_f_raio_curva): # volta a fase inicial f_atv.en_atv_fase = ldefs.E_FASE_ZERO # fase voar na proa oposta para poder retornar a pista ? elif ldefs.E_FASE_OPOSTA == f_atv.en_atv_fase: # calcula o raio de curvatura assert abs(f_atv.f_atv_raz_crv) > 0. glb_f_raio_curva = f_atv.f_trf_vel_atu / abs(math.radians(f_atv.f_atv_raz_crv)) # calcula o ponto de toque glb_f_dst_anv_ptq_x = l_pst.f_pst_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_y - f_atv.f_trf_y # posição da aeronave em relação a pista (direita/esquerda) len_pos_anv = scrv.sent_crv(l_pst.i_pst_rumo, cpd.calc_proa_demanda(-glb_f_dst_anv_ptq_x, -glb_f_dst_anv_ptq_y)) # calcula ângulo formado pela aeronave e a pista (teta) glb_ui_ang_teta = abs(l_pst.i_pst_rumo - cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y)) if glb_ui_ang_teta > 180.: glb_ui_ang_teta = 360. - glb_ui_ang_teta # distância ao ponto de toque (em linha reta) glb_f_dst_anv_ptq = math.sqrt((glb_f_dst_anv_ptq_x ** 2) + (glb_f_dst_anv_ptq_y ** 2)) # distância ao eixo da pista glb_f_dst_eixo = abs(glb_f_dst_anv_ptq * math.sin(math.radians(glb_ui_ang_teta))) # distância a rampa assert abs(math.tan(math.radians(ldefs.D_DST_RAMPA))) > 0. glb_f_dst_rampa = (f_atv.f_trf_alt_atu - l_aer.f_aer_elev) / math.tan(math.radians(ldefs.D_DST_RAMPA)) # aeronave a 2R do eixo e mais de (glb_f_raio_curva + DistRampa) da cabeceira ? if (glb_ui_ang_teta < 90.) and ((abs(glb_f_dst_anv_ptq) * math.cos(math.radians(glb_ui_ang_teta))) >= (glb_f_raio_curva + glb_f_dst_rampa)): # aeronave a direita da pista ? if ldefs.E_DIREITA == len_pos_anv: f_atv.f_atv_pro_dem = l_pst.i_pst_rumo - 90. if f_atv.f_atv_pro_dem < 0: f_atv.f_atv_pro_dem += 360. # otherwise, aeronave a esquerda da pista else: f_atv.f_atv_pro_dem = l_pst.i_pst_rumo + 90. if f_atv.f_atv_pro_dem >= 360.: f_atv.f_atv_pro_dem -= 360. # força a curva pelo menor lado scrv.sentido_curva(f_atv) # voar para interceptar eixo da pista f_atv.en_atv_fase = ldefs.E_FASE_EIXO # fase voando para interceptar eixo da pista ? elif ldefs.E_FASE_EIXO == f_atv.en_atv_fase: # proas iguais ? if abs(f_atv.f_trf_pro_atu - f_atv.f_atv_pro_dem) <= 0.01: # calcula o raio de curvatura assert abs(f_atv.f_atv_raz_crv) > 0 glb_f_raio_curva = f_atv.f_trf_vel_atu / abs(math.radians(f_atv.f_atv_raz_crv)) # calcula a distância ao ponto de toque (componentes x e y) glb_f_dst_anv_ptq_x = l_pst.f_pst_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_y - f_atv.f_trf_y # calcula ângulo formado pela aeronave e a pista (teta) glb_ui_ang_teta = abs(l_pst.i_pst_rumo - cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y)) if glb_ui_ang_teta > 180.: glb_ui_ang_teta = 360. - glb_ui_ang_teta # calcula a distância ao ponto de toque (em linha reta) glb_f_dst_anv_ptq = math.sqrt((glb_f_dst_anv_ptq_x ** 2) + (glb_f_dst_anv_ptq_y ** 2)) # distância da aeronave ao eixo glb_f_dst_eixo = abs(glb_f_dst_anv_ptq * math.sin(math.radians(glb_ui_ang_teta))) # distância da aeronave ao eixo da pista > raio de curvatura ? if glb_f_dst_eixo <= glb_f_raio_curva: # curva em direção ao rumo da pista f_atv.f_atv_pro_dem = l_pst.i_pst_rumo # força a curva pelo menor lado scrv.sentido_curva(f_atv) # curva para buscar alinhamento com eixo da pista f_atv.en_atv_fase = ldefs.E_FASE_CURVA # fase curvando para buscar alinhamento inicial com eixo da pista ? elif ldefs.E_FASE_CURVA == f_atv.en_atv_fase: # aeronave alinhada com a pista ? if abs(f_atv.f_trf_pro_atu - f_atv.f_atv_pro_dem) <= 0.01: # calcula a distância ao ponto de toque (componentes x e y) glb_f_dst_anv_ptq_x = l_pst.f_pst_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_y - f_atv.f_trf_y # calcula proa de demanda f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y) # força a curva pelo menor lado scrv.sentido_curva(f_atv) # aeronave mantendo o alinhamento com a pista f_atv.en_atv_fase = ldefs.E_FASE_ALINHAR # fase aeronave mantendo o alinhamento com a pista ? elif ldefs.E_FASE_ALINHAR == f_atv.en_atv_fase: # calcula a distância ao ponto de toque (componentes x e y) glb_f_dst_anv_ptq_x = l_pst.f_pst_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_y - f_atv.f_trf_y # calcula ângulo formado pela aeronave e a pista (teta) glb_ui_ang_teta = abs(l_pst.i_pst_rumo - cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y)) if glb_ui_ang_teta > 180.: glb_ui_ang_teta = 360. - glb_ui_ang_teta # calcula a distância ao ponto de toque (em linha reta) glb_f_dst_anv_ptq = math.sqrt((glb_f_dst_anv_ptq_x ** 2) + (glb_f_dst_anv_ptq_y ** 2)) if glb_ui_ang_teta < 90.: # aeronave antes da cabeceira (considerando dt = 1s) glb_f_alt_rampa = glb_f_dst_anv_ptq * math.tan(math.radians(ldefs.D_DST_RAMPA)) if ((f_atv.f_trf_alt_atu - l_aer.f_aer_elev) >= glb_f_alt_rampa - abs(f_atv.ptr_trf_prf.f_prf_raz_des_apx)) and \ ((f_atv.f_trf_alt_atu - l_aer.f_aer_elev) < glb_f_alt_rampa + abs(f_atv.ptr_trf_prf.f_prf_raz_des_apx)): # início da rampa de descida assert abs(glb_f_dst_anv_ptq) > 0 # calcula a razão de descida f_atv.f_atv_raz_sub = ((f_atv.f_trf_alt_atu - l_aer.f_aer_elev) * f_atv.f_atv_vel_gnd) / glb_f_dst_anv_ptq # altitude de demanda é a elevação do aeródromo f_atv.f_atv_alt_dem = l_aer.f_aer_elev # voa aeronave na rampa f_atv.en_atv_fase = ldefs.E_FASE_RAMPA # aeronave procurando novo alinhamento ? if f_atv.f_trf_pro_atu != f_atv.f_atv_pro_dem: # aeronave procurando novo alinhamento f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y) # força a curva pelo menor lado scrv.sentido_curva(f_atv) # otherwise, teta >= 90. else: # aeronave após a cabeceira f_atv.f_atv_pro_dem = l_pst.i_pst_rumo + 180. if f_atv.f_atv_pro_dem >= 360.: f_atv.f_atv_pro_dem -= 360. # inicia a razão de curva f_atv.f_atv_raz_crv = -abs(f_atv.f_atv_raz_crv) # voa até se afastar 2R do eixo da pista f_atv.en_atv_fase = ldefs.E_FASE_AFASTA # fase aeronave mantendo o alinhamento na aproximação com a pista ? elif ldefs.E_FASE_APXALINHAR == f_atv.en_atv_fase: # calcula o ponto de toque (componentes x e y) glb_f_dst_anv_ptq_x = l_pst.f_pst_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_y - f_atv.f_trf_y # calcula ângulo formado pela aeronave e a pista (teta) glb_ui_ang_teta = abs(l_pst.i_pst_rumo - cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y)) if glb_ui_ang_teta > 180.: glb_ui_ang_teta = 360. - glb_ui_ang_teta # calcula o ponto de toque (em linha reta) glb_f_dst_anv_ptq = math.sqrt((glb_f_dst_anv_ptq_x ** 2) + (glb_f_dst_anv_ptq_y ** 2)) # aeronave antes da cabeceira (considerando dt = 1s) if glb_ui_ang_teta < 90.: # início da rampa de descida assert abs(glb_f_dst_anv_ptq) > 0 # calcula a razão de descida f_atv.f_atv_raz_sub = (f_atv.f_trf_alt_atu * f_atv.f_atv_vel_gnd) / glb_f_dst_anv_ptq # altitude de demanda é a elevação do aeródromo f_atv.f_atv_alt_dem = l_aer.f_aer_elev # voa aeronave na rampa f_atv.en_atv_fase = ldefs.E_FASE_RAMPA # aeronave procurando novo alinhamento ? if f_atv.f_trf_pro_atu != f_atv.f_atv_pro_dem: # aeronave procurando novo alinhamento f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y) # força a curva pelo menor lado scrv.sentido_curva(f_atv) # fase aeronave na rampa ? elif ldefs.E_FASE_RAMPA == f_atv.en_atv_fase: # inicia a aceleração f_atv.f_atv_acel = 0. # calcula o ponto de toque (componentes x e y) glb_f_dst_anv_ptq_x = l_pst.f_pst_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_y - f_atv.f_trf_y # calcula ângulo formado pela aeronave e a pista (teta) glb_ui_ang_teta = abs(l_pst.i_pst_rumo - cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y)) if glb_ui_ang_teta > 180.: glb_ui_ang_teta = 360. - glb_ui_ang_teta # # calcula o ponto de toque (em linha reta) glb_f_dst_anv_ptq = math.sqrt((glb_f_dst_anv_ptq_x ** 2) + (glb_f_dst_anv_ptq_y ** 2)) # verifica a cabeceira oposta if glb_ui_ang_teta >= 90.: # aeronave após cabeceira glb_f_dst_anv_ptq_x = l_pst.f_pst_cab_opos_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_cab_opos_y - f_atv.f_trf_y # aeronave procurando novo alinhamento ? if f_atv.f_trf_pro_atu != f_atv.f_atv_pro_dem: # aeronave procurando novo alinhamento f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y) # força a curva pelo menor lado scrv.sentido_curva(f_atv) # aeronave tocou a pista ? if abs(f_atv.f_trf_alt_atu - l_aer.f_aer_elev) <= 0.01: # calcula a distância ao fim da pista (componentes x e y) glb_f_dst_anv_ptq_x = l_pst.f_pst_cab_opos_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_cab_opos_y - f_atv.f_trf_y # inicia a proa de demanda f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y) # força a curva pelo menor lado scrv.sentido_curva(f_atv) # ajusta a velocidade para pouso f_atv.f_atv_vel_dem = 0. # desaceleração no pouso f_atv.f_atv_acel = 2 * abs(f_atv.ptr_trf_prf.f_prf_raz_max_var_vel) # prepara a aeronave para parada na pista f_atv.en_atv_fase = ldefs.E_FASE_PISTA # fase aeronave pára na pista ? elif ldefs.E_FASE_PISTA == f_atv.en_atv_fase: # calcula a distância da aeronave a cabeceira oposta (componentes x e y) glb_f_dst_anv_ptq_x = l_pst.f_pst_cab_opos_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_cab_opos_y - f_atv.f_trf_y # calcula a distância da aeronave a cabeceira oposta (em linha reta) glb_f_dst_anv_ptq = math.sqrt((glb_f_dst_anv_ptq_x ** 2) + (glb_f_dst_anv_ptq_y ** 2)) assert abs(f_atv.f_atv_acel) > 0 # espaço de pista menor que o necessário para frear a aeronave ? if glb_f_dst_anv_ptq < (f_atv.f_trf_vel_atu ** 2) / (2 * f_atv.f_atv_acel): # aumenta a frenagem f_atv.f_atv_acel = 4 * abs(f_atv.ptr_trf_prf.f_prf_raz_max_var_vel) # aeronave procurando novo alinhamento ? if f_atv.f_trf_pro_atu != f_atv.f_atv_pro_dem: # chegou ao fim da pista ? if (abs(l_pst.f_pst_cab_opos_x - f_atv.f_trf_x) <= abs(glb_f_dst_anv_ptq_x)) and \ (abs(l_pst.f_pst_cab_opos_y - f_atv.f_trf_y) <= abs(glb_f_dst_anv_ptq_y)): # ajusta demanda ao rumo da pista f_atv.f_atv_pro_dem = l_pst.i_pst_rumo # otherwise,... else: # calcula distância ao fim da pista glb_f_dst_anv_ptq_x = l_pst.f_pst_cab_opos_x - f_atv.f_trf_x glb_f_dst_anv_ptq_y = l_pst.f_pst_cab_opos_y - f_atv.f_trf_y # calcula nova proa de demanda f_atv.f_atv_pro_dem = cpd.calc_proa_demanda(glb_f_dst_anv_ptq_x, glb_f_dst_anv_ptq_y) # força a curva pelo menor lado scrv.sentido_curva(f_atv) # aeronave parou ? if 0. == f_atv.f_trf_vel_atu: # ajusta os dados da aeronave no solo # f_atv.v_atv_visu = False # f_atv.v_atv_movi = False f_atv.en_trf_fnc_ope = ldefs.E_MANUAL f_atv.en_atv_est_atv = ldefs.E_CANCELADA # otherwise, erro no valor da fase else: # logger l_log = logging.getLogger("prc_pouso") l_log.setLevel(logging.ERROR) l_log.error(u"<E05: fase no pouso não identificada:[{}].".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_cine_data.f_afasta = l_esp.f_esp_rumo - 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_atv.f_atv_pro_dem = l_esp.f_esp_rumo # 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 __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.") # 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.") # 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.") # 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.") # 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 lf_ang_pista_brk = abs(l_pst.i_pst_rumo - 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 __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 """ # logger # M_LOG.info("__ckeck_ok:>>") # 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 # logger # M_LOG.info(u"__ckeck_ok:<E03: interceptou o fixo.") # return 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 # logger # M_LOG.info(u"__ckeck_ok:<E04: interceptou o fixo.") # return 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 """ # logger # M_LOG.info("__direciona:>>") # 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 # logger # M_LOG.info(u"__direciona:<E03: interceptou o fixo.") # return 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 # logger # M_LOG.info(u"__direciona:<E04: interceptou o fixo.") # return 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 dados_dinamicos(f_atv, f_cine_data, ff_delta_t, f_stime): """ atualiza os dados dinâmicos da aeronave @param f_atv: pointer para aeronave @param f_cine_data: pointer para CINDATA @param f_stime: pointer para sim_time """ # logger # M_LOG.info("dados_dinamicos:>>") # check input assert f_atv assert f_cine_data assert f_stime # checks (II) if (not f_atv.v_atv_ok) or (ldefs.E_ATIVA != f_atv.en_trf_est_atv): # logger l_log = logging.getLogger("dados_dinamicos::dados_dinamicos") l_log.setLevel(logging.ERROR) l_log.error(u"<E01: aeronave não ativa.") # cai fora... return # calcula a nova velocidade e a velocidade média do percurso lf_vel_med, lb_vel = __atualiza_velocidade(f_atv, ff_delta_t) # if f_atv.f_atv_vel_mac_atu != f_atv.f_atv_vel_mac_dem: # calcula e atualiza a velocidade MACH atual da aeronave # __atualiza_mach(f_atv, ff_delta_t) # atualiza a proa da aeronave lb_proa = __atualiza_proa(f_atv, ff_delta_t) # calcula a nova altitude e a variação de altitude lf_alfa, lb_alt = __atualiza_altitude(f_atv, ff_delta_t, lf_vel_med) # atualiza a posição da aeronave __atualiza_posicao(f_atv, f_cine_data, ff_delta_t, lf_vel_med, lf_alfa) # cálculo da distância e radial ao radar f_atv.f_atv_dst_crd = math.sqrt((f_atv.f_trf_x**2) + (f_atv.f_trf_y**2)) f_atv.f_atv_rad_crd = cpd.calc_proa_demanda(f_atv.f_trf_x, f_atv.f_trf_y) # cálculo do tempo estimado para a aeronave alcancar o fixo (ETO) if (f_atv.ptr_atv_fix_eto is not None) and f_atv.ptr_atv_fix_eto.v_fix_ok: # calcula distância da aeronave ao fixo ETO (x, y) lf_dst_anv_fix_x = f_atv.ptr_atv_fix_eto.f_fix_x - f_atv.f_trf_x lf_dst_anv_fix_y = f_atv.ptr_atv_fix_eto.f_fix_y - f_atv.f_trf_y # calcula distância da aeronave ao fixo (em linha reta) f_atv.f_atv_dst_fix = math.sqrt((lf_dst_anv_fix_x**2) + (lf_dst_anv_fix_y**2)) # cálculo do ETO (sem aceleração) f_atv.i_atv_hora_eto = ( f_atv.f_atv_dst_fix / f_atv.f_atv_vel_tas) + f_stime.get_hora_sim() # f_pExe.iExeHoraAtu # otherwise, registra a falha no arquivo de log else: # logger # l_log = logging.getLogger("dados_dinamicos") # l_log.setLevel(logging.ERROR) # l_log.error("<E01: ETO fixo inexistente. aeronave:[%d/%s].", f_atv.i_trf_id, f_atv.s_trf_ind) pass # cálculo da distância e radial relativamente ao fixo de referência base para o procedimento de direcionamento a fixo if (f_atv.ptr_atv_fix_prc is not None) and f_atv.ptr_atv_fix_prc.v_fix_ok: # calcula distância da aeronave ao fixo (x, y) f_cine_data.f_dst_anv_fix_x = f_atv.ptr_atv_fix_prc.f_fix_x - f_atv.f_trf_x f_cine_data.f_dst_anv_fix_y = f_atv.ptr_atv_fix_prc.f_fix_y - f_atv.f_trf_y # calcula distância e radial da aeronave ao fixo (em linha reta) f_atv.f_atv_dst_fix = math.sqrt((f_cine_data.f_dst_anv_fix_x**2) + (f_cine_data.f_dst_anv_fix_y**2)) f_atv.f_atv_rad_fix = cpd.calc_proa_demanda( -f_cine_data.f_dst_anv_fix_x, -f_cine_data.f_dst_anv_fix_y) # otherwise,... else: # força aeronave para vôo manual # f_atv.f_atv_pro_dem = f_atv.f_trf_pro_atu # f_atv.f_atv_vel_dem = f_atv.f_trf_vel_atu # f_atv.f_atv_alt_dem = f_atv.f_trf_alt_atu # f_atv.ptr_atv_fix_prc = None # f_atv.ptr_atv_fix_drd = None # f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # logger # l_log = logging.getLogger("dados_dinamicos") # l_log.setLevel(logging.NOTSET) # l_log.error("E02: PRO fixo inexistente. aeronave:[%d/%s].", f_atv.i_trf_id, f_atv.s_trf_ind) pass # cálculo da distância e radial relativamento ao fixo de referência base para um comando de Azim/Dist if (f_atv.ptr_atv_fix_drd is not None) and f_atv.ptr_atv_fix_drd.v_fix_ok: # calcula distância da aeronave ao fixo (x, y) lf_delta_x = f_atv.ptr_atv_fix_drd.f_fix_x - f_atv.f_trf_x lf_delta_y = f_atv.ptr_atv_fix_drd.f_fix_y - f_atv.f_trf_y # calcula da distância e radial da aeronave ao fixo (em linha reta) f_atv.f_atv_dst_fix = math.sqrt((lf_delta_x**2) + (lf_delta_y**2)) f_atv.f_atv_rad_fix = cpd.calc_proa_demanda(-lf_delta_x, -lf_delta_y) # otherwise,... else: # força a aeronave para vôo manual # f_atv.f_atv_pro_dem = f_atv.f_trf_pro_atu # f_atv.f_atv_vel_dem = f_atv.f_trf_vel_atu # f_atv.f_atv_alt_dem = f_atv.f_trf_alt_atu # f_atv.ptr_atv_fix_prc = None # f_atv.ptr_atv_fix_drd = None # f_atv.en_trf_fnc_ope = ldefs.E_MANUAL # logger # l_log = logging.getLogger("dados_dinamicos") # l_log.setLevel(logging.ERROR) # l_log.error("<E01: DRD fixo inexistente. aeronave:[%d/%s].", f_atv.i_trf_id, f_atv.s_trf_ind) pass # temporização para o SPI ? if 0 < f_atv.i_atv_spi < 18: # incrementa SPI f_atv.i_atv_spi += 1 # otherwise,... else: # reset SPI f_atv.i_atv_spi = -1
def prc_dir_ponto(f_atv, ff_pto_lng, ff_pto_lat, f_cine_data): """ procedimento de direcionamento a ponto @param f_atv: ponteiro para struct aeronaves @param ff_pto_lng: longitude do ponto @param ff_pto_lat: latitude do ponto @param f_cine_data: ponteiro para pilha @return True se aeronave atingiu ponto, senão False """ # logger # M_LOG.info("prc_dir_ponto:>>") # 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_lng - f_atv.f_trf_x f_cine_data.f_dst_anv_pto_y = ff_pto_lat - 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): # logger # M_LOG.info(u"prc_dir_ponto:<E02: aeronave atingiu o ponto.") # 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_lng, ff_pto_lat, f_cine_data) # logger # M_LOG.info("prc_dir_ponto:<<") # sinaliza que aeronave ainda NÂO atingiu o ponto return False