徒手画风螺旋线

文摘   教育   2023-12-19 17:26   北京  

国际民航组织(ICAO)有几个出版物是数学家写的,其中DOC8168是讲如何用数学防止撞山撞障碍物,DOC9689则是讲如何用数学防止航空器空中相撞和危险接近。飞行离不开数学,从达芬奇开始。而当今时代,数学离不开计算机,上述出版物里面的所有公式和算法,都可以经由计算机打包成函数库,从而极大简化阅读,投入实战。

中国民航的AC-91-27标题是《飞行程序》,来自DOC8168第一卷,基本目标应该是飞行员使用、签派员熟悉、管制员了解。AC-97-5《飞行程序设计规范》则来自DOC8168第二卷,供程序设计人员使用。

本篇结合计算机编程讨论上述两个AC都提到的风螺旋线,以使飞行员进一步了解数学如何帮助我们避障,减少航图中的疑惑,并鼓励飞行员广泛参与到程序设计中来。

传统的程序设计人员使用AUTO CAD来分析飞行程序并画图,底层逻辑不可控,今天我们改用Python徒手画,并利用Folium直接呈现在地形图上,地理数据采用天地图,且Python、Folium、天地图均可合法免费获取


什么是风螺旋线

先提个问题:如上图,飞机飞向某个点,然后在这个点做一个盘旋,盘旋改出的时候会不会有地形问题?

根据速度和坡度,可以计算出盘旋的半径:

r = TAS / (20 * np.pi * R)  # 无风半径 公式I-2-3-3

从而确定基本航迹,看上去没问题,但是风却是不确定因素,最差的情况是刮东风,导致飞机改出位置在红三角处,很可能受地形影响。

因此,能不能在这里盘旋,需要考虑最差情况,即此处的东风极值,风速×盘旋时间,得到出圈距离,然后比较障碍物或地形因素。

如果只转半圈,则需要考虑西风极值,以及盘旋半圈所需时间,得到出圈距离;如果只转90度,考虑南风,以及四分之一圈所需时间。

所有方向,考虑最不利风,最终出圈距离连成线,就是风螺旋线,如下图(蓝色、黄色三角分别是180度、90度对应的出圈位置):


再来看8168描述的风螺旋线图:

实现代码:

from geopy.distance import geodesic
import geopy
import numpy as np

def getLatLon(f1, f2, center, hdg):  # 根据位置点对中心点的偏移位置计算经纬度
    d1 = np.arctan2(f1, f2) / np.pi * 180
    d = hdg + d1  # 实际方位
    e = (f1 ** 2 + f2 ** 2) ** 0.5 / 1000  # 距离
    p = geopy.distance.distance(kilometers=e).destination(center, bearing=d)  # 求坐标
    return [p.latitude, p.longitude]

def spiral(r,RWhdg,p,R,w,Edir,delta,lr): # r值,跑道真航向,圆心,R值,风速,E偏流增减方向,E偏流角,左右旋
    Spiral=[]
    start=0
    for bearing in np.arange(start,start+lr*(Turn+135), lr*1):  # 设置角度范围
        pos = geopy.distance.distance(kilometers=r).destination(p, bearing=bearing + RWhdg -lr*180 )  # 求盘旋轨迹坐标
        x0 = pos.latitude
        y0 = pos.longitude
        E = abs((bearing-start) / R * w / 3600)  # 计算Etheta 来自公式I-2-3-4
        pos1 = geopy.distance.distance(kilometers=E).destination((x0, y0),
                            bearing=bearing + RWhdg -lr*180  - lr*Edir * delta)  # 求风螺旋轨迹坐标
        x1 = pos1.latitude
        y1 = pos1.longitude
        Spiral.append([x1, y1])  # 风螺旋线

    return Spiral

if __name__ == '__main__':
    # 基本参数
    lat=39.3382
    lon=112.3105
    center = (lat, lon) # 绘图中心
    waypoint=center # 航路点,也是螺旋中心点
    RWhdg =97 # 跑道方向,或下一段航迹方向
    magvar=6.8 # 磁差
    RWhdg = RWhdg - magvar  # 消除磁差
    IAS = 380  # km/h 最大表速 来自表I-4-1-1,查航图速度限制
    Alt = 2400  # 关键点高(米) 来自航图
    ISAd = 15  # 与ISA的温度差
    bank = 25  # 坡度,来自表I-2-3-1
    w = 30*1.852  # 风速,来自表I-1-2-3-1
    Turn = 90  # 转弯角度
    lr=1 # 螺旋方向 左旋-1,右旋 1

    # 初步计算
    bank = bank / 180 * np.pi # 转为弧度
    TAS = IAS * 171233 * ((288 + ISAd) - 0.006496 * Alt) ** 0.5 / (288 - 0.006496 * Alt) ** 2.628  # 公式I-2-1 附录1
    R = 6355 * np.tan(bank) / (np.pi * TAS)  # 转弯率 公式I-2-3-1
    if R > 3:
        R = 3
    r = TAS / (20 * np.pi * R)  # 无风半径 公式I-2-3-3
    C = (TAS + 56) * 6 / 3600  # 飞行员延迟距离  来自表I-2-3-2
    v = TAS
    delta = np.arcsin(w / v) / np.pi * 180  # w/v对应的角度 来自图I-2-3-4
    E0 = Turn / R * w / 3600  # 计算E0 对应表I-2-3-2的E值

    print('IAS=', IAS, 'TAS=', TAS)
    print('R=', R)
    print('r=', r)
    print('C=', C)
    print('E0=', E0)

    Edir=lr # E偏流方向
    TT=180-Turn #
    po = getLatLon(-r * 10000, center, RWhdg + TT)  # 确定转弯圆心,假设为过点转弯
    # 风螺旋线坐标数据
    spiraline=spiral(r,RWhdg+TT-90,po,R,w,Edir,delta,lr)
    print(spiraline)

这段代码直接用地球经纬度计算,结果可以直接输出到各类地图;打印参数用于与8168表格核对,以验证计算准确性;两个函数则可以直接打包引用。

小结:风螺旋线,就是盘旋或转弯过程中,在最不利风的影响下,飞机的出圈位置,转的越久,距离越远。用这条线测算障碍物的影响,比用盘旋半径做的轨迹靠谱的多。


风速打哪儿来

一年365天,天天风不同,风向可以取0-360°,那么风速怎么办?

8168给出了几种方案:

ICAO标准风:12×h+87km/h(h为飞行高度,单位千米),不考虑风向,均按照最不利风向。这是地球上最大的风,如果没有重大宇宙事件发生,应该不会有大的变化。
全向风:将所有测得的风,去掉风速最大的5%,剩余数据中的最大风速。不考虑风向,均按照最不利风向这个类似于跳水比赛的打分,去掉极值,体现真实。
统计风:实际测得的风向和风速。在风向有显著特点的地区,使用统计风更经济。

指定风:相对机场高度较低的地点,使用指定风,由8168的表I-2-3-1直接指定,40kt、30kt、25kt,随高度降低。不考虑风向,均按照最不利风向。本案例为指定风30kt。

小结:懒人可以直接用标准风和指定风;想获取实测风数据的,可以找航科院,那里有10年以上的QAR数据,覆盖所有的航路点、转弯点,挖掘即得。


转弯的膝盖

假设要建一座新机场,这是它的进场程序,几个航路点依次是IAF、IF、FAF、MAPt。我们知道飞机速度很大,不可能沿灰色线直角转弯;如果到了IF点(实心标记)转弯,就需要转半个圆才能回到下一段航路上,这称为过点转弯。通常我们不这么飞。

如果提前一个盘旋半径的距离转弯,转90°即可回到下一个航段,最经济最安全,这称为旁切转弯。这是最常见的转弯方式。

但是研究真实飞行轨迹的话,还要考虑两个因素:定位容差和飞行员误差。

定位容差意思是任何时候飞机的定位没那么准,有时候是卫星信号问题,你拿着手机不动,获得的坐标可能时不时小范围跳变;有时候是飞机设备问题,也有可能是坐标本身没那么精确,所以8168给出的方案是:

    TSE=1.852 # RNP-1,1NM
    ATT=0.8*TSE # 见2.2.1

ATT表示定位容差,也就是转弯起点有可能前后差0.8海里。

飞行员误差是说飞行员有最多6秒延迟转弯的可能:

C = (TAS + 56) * 6 / 3600  # 飞行员延迟距离  来自表I-2-3-2

两个因素叠加,最早的转弯起点比上图起点早ATT那么远(蓝线),最晚的转弯起点则比上图起点晚ATT+C(红线)。

上图红线表示最晚转弯的情况,蓝线表示最早转弯的情况。现在可以把风的因素考虑进去,得出最晚转弯螺旋线:

这时蓝线和红线之间的部分,是飞机有可能飞过的区域,且呈高斯分布状态,中央多,边缘少;之外的区域则属于飞机基本不可能去的地方。

小结:飞机因为速度大,不可能转直角弯;旁切转弯是最佳方案;由于定位容差和飞行员误差的原因,实际转弯轨迹会在某个区间,这个区间可以被计算出来,其形状有点像人的膝盖。


如何用风螺旋线避障

先回顾一下超障的概念。关于MOC的概念,在“低温修正批判”有介绍,记不清的可以去翻翻。上图则是截面图,可以看到整个航路宽度中,中间的50%是主区,障碍物高度和飞行高度间隔是MOC,例如IAF段MOC=300米;副区则是两侧各25%,间隔高度呈线性缩减直至0。

本篇的案例,假定是RNP1进场,RNP0.3进近,那么起始段总宽是5nm,主区宽度是2.5nm,如果用灰色表示副区,整体画出来是上面这个样子,夹在灰区中间的部分是主区。

显然,主区副区都严重受地形影响,需要换地方。

地方政府给划了新的地块建设机场,现在看主区副区都可以接受。

现在处理膝盖问题。为了便于理解,先说过点转弯:前面讲过,转弯有最早和最晚的情况,上图黄色区域的上下边界即表示定位容差;转弯还有左右误差的可能性,所以要研究沿主区边界转弯的极端情况,上图黄区的左右边界即表示主区宽度;那么从黄区的四个角分别画转弯轨迹,可以得到扩展的主区范围。此处省略,很少有人这么飞。

常用的旁切转弯,考虑到定位容差、飞行员误差,根据前面的计算,黄格转为粉红格区域,从该区域四个角分别为起点画转弯轨迹,可以得到扩展的主区范围:

四条轨迹中,左下角的转弯轨迹完全在原主区,因此忽略;其余三条(两红一蓝)转弯轨迹分别侵入了主区之外,因此有必要重新调整主区,确保对正五边之前三条轨迹不会侵入灰区;主区调整之后,再调整相应副区:

基于风螺旋线的转弯保护区就此成型。现在,由于地形的影响肉眼可见,这个程序也不可用,需要继续找新地块。

跑道位置和方向调整之后,地形对主区副区来讲都满足要求。最后,还要分析人工建筑物:

总结:飞机进场到着陆期间的程序,必须严格评估障碍物,8168提供了整套数学方法,既保证飞行中不会碰撞障碍物,也不会过度限制空域,导致经济建设受阻。其中风螺旋线是比较难啃的一块,搞明白之后其余数学公式都可以轻松理解运用。


后记

上面构建的函数和图形,仍然需要人工去判别障碍物是否超限,有没有更好的办法,让计算机自动判别呢?那必须。

地形数据,介绍下SRTM:本世纪初,奋进号航天飞机对地球表面做了全面扫描,获取了南北纬60度之间全部地形的雷达影像数据,后经处理成为DEM,即全球数字高程模型,面向公众免费下载。国内可在国家基础学科公共科学数据中心网站下载。其高程误差最大也就20米,完全满足地形分析的需求。

人工建筑物信息,可以找当地政府获取。

障碍物信息收集齐全后,可以用以下函数判定是否超限:

def fence(point, fence):  # 检测位置点是否出圈,不支持异构
    c = point  # 障碍物坐标
    f = fence.copy() # 围界坐标列表
    eage = len(f)
    f.append(fence[0])  # 闭合圈
    yes = True
    for k in range(eage):  # 遍历每个边
        a = f[k]  # 边线起点
        b = f[k + 1]  # 边线终点
        hdg1 = geoDegree(a, b, 0)  # 计算每个边线的航迹角
        d = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2]  # 边线中点坐标
        hdg2 = geoDegree(c, d, 0)  # 计算障碍物和边线中点的航迹角
        diff = hdg2 - hdg1  # 航迹差
        if diff < 0:
            diff += 360
        if 180 >= diff >= 0:  # 任何一边突破,认为在区域外,结束判断
            yes = False
            break
    return yes



simpler is safer
越简单,越安全



深入了解数学防撞,请进入下列链接:


空管达人X(涉及DOC9689)

低温修正批判(涉及MOC概念




Ubuntu330
简约是王道 Keep It Simple, Stupid