在新建卫星地面站时,其中一项很重要的工作就是进行卫星链路预算。手动计算十分麻烦,使用Python编写了一个可视化的计算工具。


一、 概述

    卫星通信是指以人造地球卫星为中继站转发或反射无线电波,在两个或多个卫星地面站之间进行的通信。进行卫星通信时,合理规划设计卫星传输链路,是卫星用户确保系统稳定运行的重要依据。对于新建卫星地面站,其中一项重要工作就是对卫星链路进行预算,以便确定天线尺寸及功放大小。同样对于现有地面站,由于业务需要,如需再上行一路或几路载波,这时也需要计算一下现有功放容量够不够,用不用修改天线口径或功放发射功率。此时一般情况下用户会同卫星公司联系,请其提供链路预算表,以便获取相应数据,其实很多情况下用户只需同卫星公司要几个参数,自己计算即可准确知道结果。
    为方便用户快速进行链路计算并进行链路余量分析,编写了卫星通信系统链路计算软件。该软件将链路计算中繁琐的公式进行整合,用户通过简单的参数输入即可得到链路计算结果,根据计算结果合理配备地面站设备,既能满足通信要求又能节约成本,大大简化了工作流程,提高了工作效率。

二、 设计原理

                    

python仿真DOIP_卫星链路计算


图1 卫星通信系统链路计算流程图

    
    卫星通信系统链路计算流程如图1所示。采用正推法进行卫星通信系统链路计算,在给定地面站天线口径、功放发射功率等参数和相应地面站接收参数及卫星转发器参数的基础上,分别对上行链路和下行链路进行计算,最后计算总的链路余量并在此基础上调整地面站设备。上行链路计算包括上行地面站发射天线增益、上行地面站EIRP、上行链路空间自由损耗、上行饱和通量密度(PFD)、上行载温比(C/T)U、上行载噪比(C/N)U等。下行链路计算包括下行地面站接收天线增益、下行地面站G/T值、下行链路空间自由损耗、下行载温比(C/T)D、下行载噪比(C/N)D等。总的链路计算包括整个链路的总载噪比(C/N)Total、总信噪谱密度(C/N0)Total、链路余量等。

三、 软件设计

    卫星通信系统链路计算软件采用Python 3.6语言设计完成,软件的主窗体由wxFormBuilder工具设计生成。该软件操作简单、支持目前主流的Windows操作系统安装使用。软件的主要功能:卫星通信系统上行链路计算、下行链路计算、总的链路及余量计算、参数清空等,软件开发流程如图2所示。

                                    

python仿真DOIP_链路_02


图2 卫星通信系统链路计算软件开发流程图

    
    下面对开发流程进行较为详细的介绍:

    Step1:搭建应用程序主窗体,使用wxFormBuilder工具设计生成应用程序框架,创建SatelliteLink()类,添加静态文本以及可编辑文本框、添加按钮并生成相应的事件函数,将源代码保存到文件basewin.py中;

    Step2:新建主函数执行文件main_win.py,建立MainWindow()类,从basewin.py文件中继承主窗体的SatelliteLink()类,按照主窗体按钮对应的事件,分别编写上行链路计算函数Uplink_Calculate()、下行链路计算函数Downlink_Calculate()、总的链路计算函数Totallink_Calculate()、参数清空函数Zero_Everything();

    Step3:编写主函数模块,声明Application对象并启动主事件循环;

    

python仿真DOIP_python仿真DOIP_03


图3 卫星通信系统链路计算软件界面

    
    卫星通信系统链路计算软件界面如图3所示。使用说明如下:软件分为三个计算模块,左侧为上行链路计算模块,中间为下行链路计算模块,右侧为总的链路计算模块。没有加亮标注的静态文本框对应的白色可编辑文本框为待输入参数,黄色高亮静态文本框对应的灰色可编辑文本框为待求解参数,输入参数后,点击下方的按钮即可得到计算结果。另外,软件右下方有参数清空按钮,可以清除文本框中的参数。

四、 源代码

主函数:

# -*- coding: utf-8 -*-
"""
Created on Fri Apr 27 09:43:22 2018

@author: Heat
"""

import wx  
import basewin  
import math
  
  
class MainWindow(basewin.SatelliteLink):  
    # 首先,从源文件中将主窗体继承下来.
    
    # 初始化
    def __init__(self, parent):
        # 记得设置 父类中 wx.Frame.__init__ ( self, parent=0)
        super().__init__(self)

    # 上行链路预算  (计算结果保留小数点后四位)
    def Uplink_Calculate(self, event):
        # 获取上行载波频率 --GHz
        self.uplink_frequency = self.text_uplink1.GetValue()
        # 获取上行发射天线口径 --m
        self.uplink_antenna_diameter = self.text_uplink2.GetValue()
        # 获取上行天线发射效率 --上行6G,效率为0.65
        self.uplink_antenna_eff = self.text_uplink3.GetValue()
        # 获取上行天线功放发射功率; 1W即,0dBW = 30dBm;2W即,2dBW = 33dBm;
        self.uplink_sspa = self.text_uplink5.GetValue()
        # 获取上行星地距离 --m
        self.uplink_range = self.text_uplink7.GetValue()
        # 获取信号带宽 --MHz
        self.uplink_bandwidth = self.text_uplink10.GetValue()
        # 获取上行卫星品质因数 G/T --dB/K
        self.uplink_gt = self.text_uplink11.GetValue()
        
        
        # 计算上行天线发射增益 --dBi
        self.uplink_antenna_transmit_gain = float('%.4f'%(10 * math.log(
                eval(self.uplink_antenna_eff), 10) + 20 * math.log(
                        (math.pi*eval(self.uplink_antenna_diameter)*
                         eval(self.uplink_frequency)*1e9)/3e8, 10)))
        self.text_uplink4.SetValue(str(self.uplink_antenna_transmit_gain))
        # 计算上行 EIRP --dBW
        self.uplink_EIRP = float('%.4f'%(self.uplink_antenna_transmit_gain + 
                10*math.log10(eval(self.uplink_sspa))))
        self.text_uplink6.SetValue(str(self.uplink_EIRP))
        # 计算上行链路空间自由损耗
        self.uplink_path_loss = float('%.4f'%(20*math.log10(eval(
                self.uplink_frequency)*1e9) + 20*math.log10(eval(
                        self.uplink_range)*1e3) + 20*math.log10(4*math.pi/3e8)))
        self.text_uplink8.SetValue(str(self.uplink_path_loss))
        # 计算上行 PFD --dBW/m^2
        self.uplink_PFD = float('%.4f'%(self.uplink_EIRP - self.uplink_path_loss 
                                        + 10*math.log10(
                    4*math.pi/((3e8/(eval(self.uplink_frequency)*1e9))**2))))
        self.text_uplink9.SetValue(str(self.uplink_PFD))
        # 计算上行载噪比 --dB (K为玻尔兹曼常数, K=-228.6dB/K•Hz)
        self.uplink_CN = float('%.4f'%(self.uplink_EIRP - self.uplink_path_loss 
                    + eval(self.uplink_gt) + 228.6 - 10*math.log10(eval(
                                self.uplink_bandwidth)*1e6)))
        self.text_uplink12.SetValue(str(self.uplink_CN))
        
    # 下行链路预算  (计算结果保留小数点后四位)    
    def Downlink_Calculate(self, event):
        # 获取下行载波频率 --GHz
        self.downlink_frequency = self.text_downlink1.GetValue()
        # 获取下行接收天线口径 --m
        self.downlink_antenna_diameter = self.text_downlink2.GetValue()
        # 获取下行天线接收效率 --下行4G,效率为0.75
        self.downlink_antenna_eff = self.text_downlink3.GetValue()
        # 获取下行系统噪声温度 --K
        self.downlink_noise_temperature = self.text_downlink4.GetValue()
        # 获取下行卫星 EIRP --dBW
        self.satellite_EIRP = self.text_downlink7.GetValue()
        
        # 计算下行接收天线接收增益 --dBi
        self.downlink_antenna_receive_gain = float('%.4f'%(10 * math.log(
                eval(self.downlink_antenna_eff), 10) + 20 * math.log(
                        (math.pi*eval(self.downlink_antenna_diameter)*
                         eval(self.downlink_frequency)*1e9)/3e8, 10)))
        self.text_downlink5.SetValue(str(self.downlink_antenna_receive_gain))
        # 计算下行接收天线品质因数 G/T --dB/K
        self.downlink_antenna_gt = self.downlink_antenna_receive_gain - float(
                '%.4f'%(10*math.log10(eval(self.downlink_noise_temperature))))
        self.text_downlink6.SetValue(str(self.downlink_antenna_gt))
        # 计算下行链路空间自由损耗
        self.downlink_path_loss = float('%.4f'%(20*math.log10(eval(
                self.downlink_frequency)*1e9) + 20*math.log10(eval(
                        self.uplink_range)*1e3) + 20*math.log10(4*math.pi/3e8)))
        self.text_downlink8.SetValue(str(self.downlink_path_loss))
        # 计算下行载噪比 --dB
        self.downlink_CN = float('%.4f'%(eval(self.satellite_EIRP) - 
                self.downlink_path_loss + self.downlink_antenna_gt + 228.6 - 
                10*math.log10(eval(self.uplink_bandwidth)*1e6)))
        self.text_downlink9.SetValue(str(self.downlink_CN))
        
    # 计算总的链路预算 (计算结果保留小数点后四位)
    def Totallink_Calculate(self, event):
        # 获取上行链路载干比 --dB
        self.uplink_CI = self.text_totallink1.GetValue()
        # 获取卫星互调干扰 --dB
        self.satellite_CI = self.text_totallink3.GetValue()
        # 获取下行链路载干比 -- dB
        self.downlink_CI = self.text_totallink5.GetValue()
        # 获取门限信噪谱密度
        self.threshold_CN0 = self.text_totallink8.GetValue()
        
        # 计算上行载噪比 --dB
        self.text_totallink2.SetValue(str(self.uplink_CN))
        # 计算下行载噪比 --dB
        self.text_totallink4.SetValue(str(self.downlink_CN))
        # 计算总的载噪比 --dB
        self.total_CN = float('%.4f'%(10*math.log10(1/(
                1/(10**(self.uplink_CN/10)) + 
                1/(10**(self.downlink_CN/10)) +
                1/(10**(eval(self.uplink_CI)/10)) + 
                1/(10**(eval(self.satellite_CI)/10)) + 
                1/(10**(eval(self.downlink_CI)/10)) 
                ))))
        self.text_totallink6.SetValue(str(self.total_CN))
        # 计算总的信噪谱密度 --dBHz
        self.total_CN0 = float('%.4f'%(self.total_CN + 
                10*math.log10(eval(self.uplink_bandwidth)*1e6)))
        self.text_totallink7.SetValue(str(self.total_CN0))
        # 计算链路余量 --dB
        self.link_margin = float('%.4f'%(self.total_CN0 - 
                                         eval(self.threshold_CN0)))
        self.text_totallink9.SetValue(str(self.link_margin))       
        
        
    # 参数清空   
    def Zero_Everything(self, event):
        # 上行链路--参数清空
        self.text_uplink1.Clear()
        self.text_uplink2.Clear()
        self.text_uplink3.Clear()
        self.text_uplink4.Clear()
        self.text_uplink5.Clear()
        self.text_uplink6.Clear()
        self.text_uplink7.Clear()
        self.text_uplink8.Clear()
        self.text_uplink9.Clear()
        self.text_uplink10.Clear()
        self.text_uplink11.Clear()
        self.text_uplink12.Clear()
        # 下行链路 --参数清空
        self.text_downlink1.Clear()
        self.text_downlink2.Clear()
        self.text_downlink3.Clear()
        self.text_downlink4.Clear()
        self.text_downlink5.Clear()
        self.text_downlink6.Clear()
        self.text_downlink7.Clear()
        self.text_downlink8.Clear()
        self.text_downlink9.Clear()
        # 总的链路 --参数清空
        self.text_totallink1.Clear()
        self.text_totallink2.Clear()
        self.text_totallink3.Clear()
        self.text_totallink4.Clear()
        self.text_totallink5.Clear()
        self.text_totallink6.Clear()
        self.text_totallink7.Clear()
        self.text_totallink8.Clear()
        self.text_totallink9.Clear()

# 执行主函数        
if __name__ == '__main__':
    app = wx.App()
    main_win = MainWindow(None)  
    main_win.Show()
    app.MainLoop()

界面:

# -*- coding: utf-8 -*- 

###########################################################################
## Python code generated with wxFormBuilder (version Jun 17 2015)
## http://www.wxformbuilder.org/
##
## PLEASE DO "NOT" EDIT THIS FILE!
###########################################################################

import wx
import wx.xrc

###########################################################################
## Class SatelliteLink
###########################################################################

class SatelliteLink ( wx.Frame ):
	
	def __init__( self, parent ):
		wx.Frame.__init__ ( self, parent=None, id = wx.ID_ANY, title = u"卫星通信系统链路计算软件 V1.0", pos = wx.DefaultPosition, size = wx.Size( 1486,700 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
		
		self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
		self.SetFont( wx.Font( 22, 70, 90, 90, False, "华文隶书" ) )
		self.SetBackgroundColour( wx.Colour( 226, 228, 227 ) )
		
		bSizer6 = wx.BoxSizer( wx.HORIZONTAL )
		
		fgSizer3 = wx.FlexGridSizer( 0, 2, 0, 0 )
		fgSizer3.SetFlexibleDirection( wx.BOTH )
		fgSizer3.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
		
		self.m_staticText27 = wx.StaticText( self, wx.ID_ANY, u"Uplink", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText27.Wrap( -1 )
		self.m_staticText27.SetFont( wx.Font( 16, 72, 93, 92, False, "Times New Roman" ) )
		self.m_staticText27.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
		
		fgSizer3.Add( self.m_staticText27, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
		
		self.m_staticText28 = wx.StaticText( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText28.Wrap( -1 )
		fgSizer3.Add( self.m_staticText28, 0, wx.ALL, 5 )
		
		self.m_staticText29 = wx.StaticText( self, wx.ID_ANY, u"Uplink frequency (GHz)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText29.Wrap( -1 )
		self.m_staticText29.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.m_staticText29, 0, wx.ALL, 5 )
		
		self.text_uplink1 = wx.TextCtrl( self, wx.ID_ANY, u"6", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink1.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.text_uplink1, 0, wx.ALL, 5 )
		
		self.m_staticText30 = wx.StaticText( self, wx.ID_ANY, u"Uplink antenna diameter (m)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText30.Wrap( -1 )
		self.m_staticText30.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.m_staticText30, 0, wx.ALL, 5 )
		
		self.text_uplink2 = wx.TextCtrl( self, wx.ID_ANY, u"3", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink2.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.text_uplink2, 0, wx.ALL, 5 )
		
		self.m_staticText31 = wx.StaticText( self, wx.ID_ANY, u"Uplink antenna aperture efficiency (e.g. 0.65)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText31.Wrap( -1 )
		self.m_staticText31.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.m_staticText31, 0, wx.ALL, 5 )
		
		self.text_uplink3 = wx.TextCtrl( self, wx.ID_ANY, u"0.65", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink3.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.text_uplink3, 0, wx.ALL, 5 )
		
		self.m_staticText32 = wx.StaticText( self, wx.ID_ANY, u"Uplink antenna transmit gain (dBi)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText32.Wrap( -1 )
		self.m_staticText32.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText32.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer3.Add( self.m_staticText32, 0, wx.ALL, 5 )
		
		self.text_uplink4 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink4.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_uplink4.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer3.Add( self.text_uplink4, 0, wx.ALL, 5 )
		
		self.m_staticText33 = wx.StaticText( self, wx.ID_ANY, u"Uplink antenna, power at the feed (W) ", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText33.Wrap( -1 )
		self.m_staticText33.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.m_staticText33, 0, wx.ALL, 5 )
		
		self.text_uplink5 = wx.TextCtrl( self, wx.ID_ANY, u"2", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink5.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.text_uplink5, 0, wx.ALL, 5 )
		
		self.m_staticText34 = wx.StaticText( self, wx.ID_ANY, u"Uplink EIRP (dBW)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText34.Wrap( -1 )
		self.m_staticText34.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText34.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer3.Add( self.m_staticText34, 0, wx.ALL, 5 )
		
		self.text_uplink6 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink6.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_uplink6.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer3.Add( self.text_uplink6, 0, wx.ALL, 5 )
		
		self.m_staticText35 = wx.StaticText( self, wx.ID_ANY, u"Range (35778 - 41679) (km)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText35.Wrap( -1 )
		self.m_staticText35.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.m_staticText35, 0, wx.ALL, 5 )
		
		self.text_uplink7 = wx.TextCtrl( self, wx.ID_ANY, u"36000", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink7.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.text_uplink7, 0, wx.ALL, 5 )
		
		self.m_staticText36 = wx.StaticText( self, wx.ID_ANY, u"Uplink path loss (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText36.Wrap( -1 )
		self.m_staticText36.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText36.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer3.Add( self.m_staticText36, 0, wx.ALL, 5 )
		
		self.text_uplink8 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink8.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_uplink8.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer3.Add( self.text_uplink8, 0, wx.ALL, 5 )
		
		self.m_staticText37 = wx.StaticText( self, wx.ID_ANY, u"Uplink PFD at satellite (dBW/m^2)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText37.Wrap( -1 )
		self.m_staticText37.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText37.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer3.Add( self.m_staticText37, 0, wx.ALL, 5 )
		
		self.text_uplink9 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink9.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_uplink9.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer3.Add( self.text_uplink9, 0, wx.ALL, 5 )
		
		self.m_staticText38 = wx.StaticText( self, wx.ID_ANY, u"Bandwidth (MHz)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText38.Wrap( -1 )
		self.m_staticText38.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.m_staticText38, 0, wx.ALL, 5 )
		
		self.text_uplink10 = wx.TextCtrl( self, wx.ID_ANY, u"10", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink10.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.text_uplink10, 0, wx.ALL, 5 )
		
		self.m_staticText39 = wx.StaticText( self, wx.ID_ANY, u"Satellite uplink G/T (dB/K)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText39.Wrap( -1 )
		self.m_staticText39.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.m_staticText39, 0, wx.ALL, 5 )
		
		self.text_uplink11 = wx.TextCtrl( self, wx.ID_ANY, u"3", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink11.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer3.Add( self.text_uplink11, 0, wx.ALL, 5 )
		
		self.m_staticText40 = wx.StaticText( self, wx.ID_ANY, u"Uplink C/N (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText40.Wrap( -1 )
		self.m_staticText40.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText40.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer3.Add( self.m_staticText40, 0, wx.ALL, 5 )
		
		self.text_uplink12 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_uplink12.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_uplink12.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer3.Add( self.text_uplink12, 0, wx.ALL, 5 )
		
		self.button_uplink = wx.Button( self, wx.ID_ANY, u"Click to calculate the results", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.button_uplink.SetFont( wx.Font( 15, 72, 93, 92, False, "Times New Roman" ) )
		self.button_uplink.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INACTIVECAPTION ) )
		
		fgSizer3.Add( self.button_uplink, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
		
		
		bSizer6.Add( fgSizer3, 0, wx.TOP|wx.RIGHT, 20 )
		
		fgSizer4 = wx.FlexGridSizer( 0, 2, 0, 0 )
		fgSizer4.SetFlexibleDirection( wx.BOTH )
		fgSizer4.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
		
		self.m_staticText41 = wx.StaticText( self, wx.ID_ANY, u"Downlink", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText41.Wrap( -1 )
		self.m_staticText41.SetFont( wx.Font( 16, 72, 93, 92, False, "Times New Roman" ) )
		self.m_staticText41.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
		
		fgSizer4.Add( self.m_staticText41, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
		
		self.m_staticText42 = wx.StaticText( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText42.Wrap( -1 )
		fgSizer4.Add( self.m_staticText42, 0, wx.ALL, 5 )
		
		self.m_staticText43 = wx.StaticText( self, wx.ID_ANY, u"Downlink frequency (GHz)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText43.Wrap( -1 )
		self.m_staticText43.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.m_staticText43, 0, wx.ALL, 5 )
		
		self.text_downlink1 = wx.TextCtrl( self, wx.ID_ANY, u"4", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink1.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.text_downlink1, 0, wx.ALL, 5 )
		
		self.m_staticText44 = wx.StaticText( self, wx.ID_ANY, u"Downlink receive antenna diameter (m)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText44.Wrap( -1 )
		self.m_staticText44.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.m_staticText44, 0, wx.ALL, 5 )
		
		self.text_downlink2 = wx.TextCtrl( self, wx.ID_ANY, u"3", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink2.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.text_downlink2, 0, wx.ALL, 5 )
		
		self.m_staticText45 = wx.StaticText( self, wx.ID_ANY, u"Downlink receive antenna aperture efficiency (e.g. 0.65)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText45.Wrap( -1 )
		self.m_staticText45.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.m_staticText45, 0, wx.ALL, 5 )
		
		self.text_downlink3 = wx.TextCtrl( self, wx.ID_ANY, u"0.75", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink3.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.text_downlink3, 0, wx.ALL, 5 )
		
		self.m_staticText46 = wx.StaticText( self, wx.ID_ANY, u"Downlink system noise temperature(antenna+LNA) (K)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText46.Wrap( -1 )
		self.m_staticText46.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.m_staticText46, 0, wx.ALL, 5 )
		
		self.text_downlink4 = wx.TextCtrl( self, wx.ID_ANY, u"30", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink4.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.text_downlink4, 0, wx.ALL, 5 )
		
		self.m_staticText47 = wx.StaticText( self, wx.ID_ANY, u"Downlink receive antenna gain (dBi)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText47.Wrap( -1 )
		self.m_staticText47.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText47.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer4.Add( self.m_staticText47, 0, wx.ALL, 5 )
		
		self.text_downlink5 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink5.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_downlink5.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_ACTIVEBORDER ) )
		
		fgSizer4.Add( self.text_downlink5, 0, wx.ALL, 5 )
		
		self.m_staticText48 = wx.StaticText( self, wx.ID_ANY, u"Downlink receive antenna G/T (dB/K)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText48.Wrap( -1 )
		self.m_staticText48.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText48.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer4.Add( self.m_staticText48, 0, wx.ALL, 5 )
		
		self.text_downlink6 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink6.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_downlink6.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_ACTIVEBORDER ) )
		
		fgSizer4.Add( self.text_downlink6, 0, wx.ALL, 5 )
		
		self.m_staticText49 = wx.StaticText( self, wx.ID_ANY, u"Downlink satellite EIRP (dBW)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText49.Wrap( -1 )
		self.m_staticText49.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.m_staticText49, 0, wx.ALL, 5 )
		
		self.text_downlink7 = wx.TextCtrl( self, wx.ID_ANY, u"30", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink7.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer4.Add( self.text_downlink7, 0, wx.ALL, 5 )
		
		self.m_staticText50 = wx.StaticText( self, wx.ID_ANY, u"Downlink path loss (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText50.Wrap( -1 )
		self.m_staticText50.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText50.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer4.Add( self.m_staticText50, 0, wx.ALL, 5 )
		
		self.text_downlink8 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink8.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_downlink8.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer4.Add( self.text_downlink8, 0, wx.ALL, 5 )
		
		self.m_staticText51 = wx.StaticText( self, wx.ID_ANY, u"Downlink C/N (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText51.Wrap( -1 )
		self.m_staticText51.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText51.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer4.Add( self.m_staticText51, 0, wx.ALL, 5 )
		
		self.text_downlink9 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_downlink9.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_downlink9.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer4.Add( self.text_downlink9, 0, wx.ALL, 5 )
		
		self.button_downlink = wx.Button( self, wx.ID_ANY, u"Click to calculate the results", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.button_downlink.SetFont( wx.Font( 15, 72, 93, 92, False, "Times New Roman" ) )
		self.button_downlink.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INACTIVECAPTION ) )
		
		fgSizer4.Add( self.button_downlink, 0, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 5 )
		
		
		bSizer6.Add( fgSizer4, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.TOP|wx.RIGHT, 20 )
		
		fgSizer5 = wx.FlexGridSizer( 0, 2, 0, 0 )
		fgSizer5.SetFlexibleDirection( wx.BOTH )
		fgSizer5.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
		
		self.m_staticText26 = wx.StaticText( self, wx.ID_ANY, u"Total link", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText26.Wrap( -1 )
		self.m_staticText26.SetFont( wx.Font( 16, 72, 93, 92, False, "Times New Roman" ) )
		self.m_staticText26.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
		
		fgSizer5.Add( self.m_staticText26, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL, 5 )
		
		self.m_staticText271 = wx.StaticText( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText271.Wrap( -1 )
		fgSizer5.Add( self.m_staticText271, 0, wx.ALL, 5 )
		
		self.m_staticText281 = wx.StaticText( self, wx.ID_ANY, u"Uplink C/interference (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText281.Wrap( -1 )
		self.m_staticText281.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer5.Add( self.m_staticText281, 0, wx.ALL, 5 )
		
		self.text_totallink1 = wx.TextCtrl( self, wx.ID_ANY, u"28.0", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink1.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer5.Add( self.text_totallink1, 0, wx.ALL, 5 )
		
		self.m_staticText291 = wx.StaticText( self, wx.ID_ANY, u"Uplink C/N (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText291.Wrap( -1 )
		self.m_staticText291.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText291.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer5.Add( self.m_staticText291, 0, wx.ALL, 5 )
		
		self.text_totallink2 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink2.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_totallink2.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_ACTIVEBORDER ) )
		
		fgSizer5.Add( self.text_totallink2, 0, wx.ALL, 5 )
		
		self.m_staticText301 = wx.StaticText( self, wx.ID_ANY, u"Satellite C/intermod (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText301.Wrap( -1 )
		self.m_staticText301.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer5.Add( self.m_staticText301, 0, wx.ALL, 5 )
		
		self.text_totallink3 = wx.TextCtrl( self, wx.ID_ANY, u"21.0", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink3.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer5.Add( self.text_totallink3, 0, wx.ALL, 5 )
		
		self.m_staticText311 = wx.StaticText( self, wx.ID_ANY, u"Downlink C/N (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText311.Wrap( -1 )
		self.m_staticText311.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText311.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer5.Add( self.m_staticText311, 0, wx.ALL, 5 )
		
		self.text_totallink4 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink4.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_totallink4.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer5.Add( self.text_totallink4, 0, wx.ALL, 5 )
		
		self.m_staticText321 = wx.StaticText( self, wx.ID_ANY, u"Downlink C/interference (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText321.Wrap( -1 )
		self.m_staticText321.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer5.Add( self.m_staticText321, 0, wx.ALL, 5 )
		
		self.text_totallink5 = wx.TextCtrl( self, wx.ID_ANY, u"28.0", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink5.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		
		fgSizer5.Add( self.text_totallink5, 0, wx.ALL, 5 )
		
		self.m_staticText331 = wx.StaticText( self, wx.ID_ANY, u"Total link C/N (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText331.Wrap( -1 )
		self.m_staticText331.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText331.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer5.Add( self.m_staticText331, 0, wx.ALL, 5 )
		
		self.text_totallink6 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink6.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_totallink6.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_APPWORKSPACE ) )
		
		fgSizer5.Add( self.text_totallink6, 0, wx.ALL, 5 )
		
		self.m_staticText381 = wx.StaticText( self, wx.ID_ANY, u"Total link C/N0 (dBHz)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText381.Wrap( -1 )
		self.m_staticText381.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText381.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer5.Add( self.m_staticText381, 0, wx.ALL, 5 )
		
		self.text_totallink7 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink7.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_totallink7.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_ACTIVEBORDER ) )
		
		fgSizer5.Add( self.text_totallink7, 0, wx.ALL, 5 )
		
		self.m_staticText341 = wx.StaticText( self, wx.ID_ANY, u"Threshold C/N0 (dBHz)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText341.Wrap( -1 )
		self.m_staticText341.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText341.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_3DLIGHT ) )
		
		fgSizer5.Add( self.m_staticText341, 0, wx.ALL, 5 )
		
		self.text_totallink8 = wx.TextCtrl( self, wx.ID_ANY, u"48.0", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink8.SetFont( wx.Font( 12, 72, 90, 90, False, "Times New Roman" ) )
		self.text_totallink8.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_WINDOW ) )
		
		fgSizer5.Add( self.text_totallink8, 0, wx.ALL, 5 )
		
		self.m_staticText351 = wx.StaticText( self, wx.ID_ANY, u"Link Margin (dB)", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText351.Wrap( -1 )
		self.m_staticText351.SetFont( wx.Font( 14, 72, 90, 90, False, "Times New Roman" ) )
		self.m_staticText351.SetBackgroundColour( wx.Colour( 255, 255, 0 ) )
		
		fgSizer5.Add( self.m_staticText351, 0, wx.ALL, 5 )
		
		self.text_totallink9 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.text_totallink9.SetFont( wx.Font( 12, 72, 90, 92, False, "Times New Roman" ) )
		self.text_totallink9.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_ACTIVEBORDER ) )
		
		fgSizer5.Add( self.text_totallink9, 0, wx.ALL, 5 )
		
		self.button_totallink = wx.Button( self, wx.ID_ANY, u"Click to calculate the results", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.button_totallink.SetFont( wx.Font( 15, 72, 93, 92, False, "Times New Roman" ) )
		self.button_totallink.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INACTIVECAPTION ) )
		
		fgSizer5.Add( self.button_totallink, 0, wx.ALL, 5 )
		
		self.m_staticText371 = wx.StaticText( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
		self.m_staticText371.Wrap( -1 )
		fgSizer5.Add( self.m_staticText371, 0, wx.ALL, 5 )
		
		self.button_zero = wx.Button( self, wx.ID_ANY, u"Click to zero everything", wx.DefaultPosition, wx.DefaultSize, 0 )
		self.button_zero.SetFont( wx.Font( 15, 72, 93, 92, False, "Times New Roman" ) )
		self.button_zero.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_INACTIVECAPTION ) )
		
		fgSizer5.Add( self.button_zero, 0, wx.ALL, 5 )
		
		
		bSizer6.Add( fgSizer5, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.LEFT|wx.TOP, 20 )
		
		
		self.SetSizer( bSizer6 )
		self.Layout()
		
		self.Centre( wx.BOTH )
		
		# Connect Events
		self.button_uplink.Bind( wx.EVT_BUTTON, self.Uplink_Calculate )
		self.button_downlink.Bind( wx.EVT_BUTTON, self.Downlink_Calculate )
		self.button_totallink.Bind( wx.EVT_BUTTON, self.Totallink_Calculate )
		self.button_zero.Bind( wx.EVT_BUTTON, self.Zero_Everything )
	
	def __del__( self ):
		pass
	
	
	# Virtual event handlers, overide them in your derived class
	def Uplink_Calculate( self, event ):
		event.Skip()
	
	def Downlink_Calculate( self, event ):
		event.Skip()
	
	def Totallink_Calculate( self, event ):
		event.Skip()
	
	def Zero_Everything( self, event ):
		event.Skip()


备注:
    exe可执行文件打包可使用 pyinstaller 工具。打包方法参见博文:


python仿真DOIP_wxpython_04