Beispiel #1
0
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]))
Beispiel #2
0
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]))
Beispiel #3
0
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
Beispiel #4
0
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 
Beispiel #5
0
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)
Beispiel #6
0
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
Beispiel #7
0
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