GAMP源码阅读:PPP中的模型改正:对流层延迟、电离层延迟

news2024/11/24 9:19:29

原始 Markdown文档、Visio流程图、XMind思维导图见:https://github.com/LiZhengXiao99/Navigation-Learning

在这里插入图片描述

文章目录

    • 一、对流层延迟改正
      • 1、原理
      • 2、model_trop():对流层改正入口函数
      • 3、tropmodel():Saastamoinen 模型改正计算延迟
        • 1. Saastamoinen 模型
        • 2. 标准大气模型
        • 3. GPT 模型
        • 4. tropmodel() 代码
      • 4、trop_model_prec():精密对流层模型
      • 5、tropmapf():计算干湿延迟投影系数
      • 6、tropmapf_nmf():Neill 投影函数
    • 二、电离层延迟改正
      • 1、原理
      • 2、model_iono():电离层改正入口函数
      • 3、ionmodel():克罗布歇模型计算电离层改正量
      • 4、iontec():TEC 模型计算电离层改正量
        • 1. readtec():电离层 IONEX 文件读取
        • 2. iontec():TEC 格网改正入口函数
        • 3. iondelay():计算指定时间电离层延迟
        • 4. ionppp():计算电离层穿刺点
        • 5. dataindex():获取 TEC 格网数据下标
        • 6. interptec():插值计算穿刺点处 TEC

image-20231103180051412

一、对流层延迟改正

1、原理

对流层一般指距离地面 50km 内的大气层,是大气层质量的主要部分。当导航信号穿过对流层时,由于传播介质密度的增加,信号传播路径和传播速度会发生改变,由此引起的 GNSS 观测值误差称为对流层延迟。对流层延迟一般可分为干延迟和湿延迟,对于载波相位和伪距完全相同,一般在米级大小,可通过模型改正和参数估计的方法来削弱其影响。修正模型如下:
T = M d r y T d r y + M w e t T w e t T=M_{d r y} T_{d r y}+M_{w e t} T_{w e t} T=MdryTdry+MwetTwet
式中, T d r y , T w e t T_{d r y}, T_{w e t} Tdry,Twet 分别表示接收机天顶对流层的干延迟和湿延迟; M d r y , M w e t M_{d r y}, M_{w e t} Mdry,Mwet 分别表示干延迟和湿延迟的投影函数。对流层干延迟比较稳定,主要与测站高度、大气温度和大气压相关,可通过模型改正,常用模型有 Saastamoninen 模型、Hopfield 模型等。湿延迟不同于干延迟,变化较大,主要与水汽含量相关,一般估计天顶对流层湿延迟,通过投影函数计算各卫星的电离层湿延迟,常用的投影函数有全球投影函数(Global Mapping Function,GMF)、Niell 投影函数(NMF)和 Vienna投影函数(Vienna Mapping Function,VMF)等。本文使用 Saastamoninen 模型改正对流层干延迟,使用 GMF 投影函数估计接收机天顶对流层湿延迟。

2、model_trop():对流层改正入口函数

  • Saastamoinen 模型:调用 tropmodel() 计算对流层延迟,方差设为 0.3*0.3。
  • 估计对流层:从 x 中取估计的 ZTD,调用 trop_model_prec() 改正,方差在其中计算(0.01*0.01)。

计算得到的对流层改正量,作为参数 dtrp 传出

static int model_trop(gtime_t time, const double *pos, const double *azel,
	const prcopt_t *opt, const double *x, double *dtdx,
	const nav_t *nav, double *dtrp, double *shd, double *var)
{
	double trp[3]={0};
	double zwd;

	// Saastamoinen 模型改正计算延迟,方差设为 0.3*0.3
	if (opt->tropopt==TROPOPT_SAAS) {
		*dtrp=tropmodel(time,pos,azel,REL_HUMI,&zwd,0);
		*dtrp+=zwd;
		*var=SQR(ERR_SAAS);
		return 1;
	}
	// 估计对流层模式,从 x 中取估计的 ZTD,调用 trop_model_prec() 改正,方差在其中计算
	if (opt->tropopt==TROPOPT_EST||opt->tropopt==TROPOPT_ESTG) {
		matcpy(trp,x+IT(opt),opt->tropopt==TROPOPT_EST?1:3,1);
		*dtrp=trop_model_prec(time,pos,azel,opt,trp,dtdx,shd,var);
		return 1;
	}
	return 0;
}

3、tropmodel():Saastamoinen 模型改正计算延迟

1. Saastamoinen 模型

Saastamoinen 模型将对流层分为两层进行积分,第 1 层为从地表到 10   k m 10 \mathrm{~km} 10 km 高度的对流层顶,该层的温度变化率为;第 2 层为从 10   k m 10 \mathrm{~km} 10 km 50   k m 50 \mathrm{~km} 50 km 高度的平流层顶,该层的温度视为常数。 Saastamoinen 模型首次将被积函数按照天顶距三角函数展开逐项进行积分, 并把对流层天顶延迟分为对流层干延迟和湿延迟两个分量之和,两个分量的表达式为:
{ Z H D = 0.002277 P f ( φ , h ) Z W D = 0.002277 e f ( φ , h ) ( 0.05 + 1255 T ) f ( φ , h ) = 1 − 0.00266 cos ⁡ ( 2 φ ) − 0.00028 h \left\{\begin{array}{l}Z H D=\frac{0.002277 P}{f(\varphi, h)} \\ Z W D=\frac{0.002277 e}{f(\varphi, h)}\left(0.05+\frac{1255}{T}\right) \\ f(\varphi, h)=1-0.00266 \cos (2 \varphi)-0.00028 h\end{array}\right. ZHD=f(φ,h)0.002277PZWD=f(φ,h)0.002277e(0.05+T1255)f(φ,h)=10.00266cos(2φ)0.00028h
或者:
T r s = 0.002277 cos ⁡ z { p + ( 1255 T + 0.05 ) e − tan ⁡ 2 z } T_{r}^{s}=\frac{0.002277}{\cos z}\left\{p+\left(\frac{1255}{T}+0.05\right) e-\tan ^{2} z\right\} Trs=cosz0.002277{p+(T1255+0.05)etan2z}
其中, P , T , e , φ P, T, e, \varphi P,T,e,φ h h h 分别为地表气压 ( h P a ) (\mathrm{hPa}) (hPa) 、地表温度 ( K ) (\mathrm{K}) (K) 、水汽压 ( h P a ) (\mathrm{hPa}) (hPa) 、测站纬度 ( r a d ) (\mathrm{rad}) (rad) 和高程 ( k m ) (\mathrm{km}) (km) ,可以由标准大气模型基于经验计算,也可由 GPT 模型提供。

2. 标准大气模型

根据经验模型计算求大气压 P、温度 T、大气水汽压力 e:
p = 1013.25 × ( 1 − 2.2557 × 1 0 − 5 h ) 5.2568 T = 15.0 − 6.5 × 1 0 − 3 h + 273.15 e = 6.108 × exp ⁡ { 17.15 T − 4684.0 T − 38.45 } × h r e l 100 \begin{array}{l}p=1013.25 \times\left(1-2.2557 \times 10^{-5} h\right)^{5.2568} \\ T=15.0-6.5 \times 10^{-3} h+273.15 \\ e=6.108 \times \exp \left\{\frac{17.15 T-4684.0}{T-38.45}\right\} \times \frac{h_{r e l}}{100}\end{array} p=1013.25×(12.2557×105h)5.2568T=15.06.5×103h+273.15e=6.108×exp{T38.4517.15T4684.0}×100hrel

其中 z z z 是天顶角,与高度角互余: z = π / 2 − E l r s z=\pi / 2-E l_{r}^{s} z=π/2Elrs

3. GPT 模型

GPT 系列模型是 Boehm 等利用欧洲中尺度天气预报中心 (European Centre for Medium-Range Weather Forecasts, ECMWF) 长期的再分析气象资料建立的全球气象参数经验模型, 仅需知道测站地理位置信息与年积日便可以获得地表温度、大气压力和水汽压等气象参数,在全球范围内得到广泛应用。

作者用的 ftp://tai.bipm.org/iers/convupdt/chapter9/GPT.F 文件对应的模型,把 IGS 中心提供的函数改成 c 语言版本的 getGPT() 函数,这个 GPT.F 可以通过资源管理器下载,用 notepade++、或者 VScode 查看:

5f5cec497ffb8ae62cb16a7ae2519cff

4. tropmodel() 代码

用标准大气模型或 GPT 模型计算一些标准大气值,包括总压 p、大气温度 T、水汽压力 e;然后计算了静力学延迟(干延迟) trph计算了湿延迟 trpw。

humi 传 0,就只计算干延迟,湿延迟作为参数估计

extern double tropmodel(gtime_t time, const double *pos, const double *azel,
                        double humi, double *zwd, int atmodel)
{
    const double temp0=15.0;   /* temparature at sea level */
    double hgt,pres,temp,e,z,trph,trpw;
	int b1,b2;
	mjd_t mjd;
	double dmjd,undo,d1,d2;
    
    if (pos[2]<-100.0||pos[2]>1E6||azel[1]<=0) {
        //���㿪ʼ�ĵ�һ����Ԫ�߳�������-100.0����������������Ϣ
        b1=(PPP_Glo.iEpoch==1)&&(PPP_Glo.revs==0);
        b2=(PPP_Glo.nEpoch-1==PPP_Glo.iEpoch)&&(PPP_Glo.revs==1);

        //����deltaEp����
        if (!b1&&!b2&&PPP_Glo.delEp<20) {
            sprintf(PPP_Glo.chMsg,"*** WARNING: tropmodel: height=%7.3f elev=%4.1f\n",pos[2],azel[1]*R2D);
            outDebug(OUTWIN,OUTFIL,OUTTIM);
        }

        return 0.0;
    }
    if (pos[2]>=1.0/2.2557E-5) return 0.0;

    hgt=pos[2]<0.0?0.0:pos[2];

    //�̹߳���ᵼ�¼��������ֵ���������ӳ���Ϊ�����
    if (hgt>15000.0) {
        //���㿪ʼ�ĵ�һ����Ԫ�߳�������-100.0����������������Ϣ
        b1=(PPP_Glo.iEpoch)==1&&(PPP_Glo.revs==0)&&(PPP_Glo.prcOpt_Ex.solType==0||
			PPP_Glo.prcOpt_Ex.solType==3||PPP_Glo.prcOpt_Ex.solType==4);
        b2=(PPP_Glo.nEpoch-1==PPP_Glo.iEpoch)&&(PPP_Glo.revs==1)&&(PPP_Glo.prcOpt_Ex.solType==1
			||PPP_Glo.prcOpt_Ex.solType==2);

        if (!b1&&!b2&&PPP_Glo.delEp<20) {
			sprintf(PPP_Glo.chMsg,"*** WARNING: tropmodel: height=%7.3f\n",hgt);
            outDebug(OUTWIN,OUTFIL,OUTTIM);
        }
        hgt=15000.0;
    }

    // 计算大气参数,标准大气模型 or GPT 模型
    /* standard atmosphere */
    if (atmodel!=1) {
        pres=1013.25*pow(1.0-2.2557E-5*hgt,5.2568);         // 求大气压P (E.5.1)
        temp=temp0-6.5E-3*hgt+273.16;                       // 求温度temp (E.5.2)
        e=6.108*humi*exp((17.15*temp-4684.0)/(temp-38.45)); // 求大气水汽压力e (E.5.3)
    }
    else {
        time2mjd(time,&mjd);
        dmjd=mjd.day+(mjd.ds.sn+mjd.ds.tos)/86400.0;
        
        undo=0.0;
        getGPT(pos,dmjd,&pres,&temp,&undo);

        d1=1013.25*pow(1.0-2.2557E-5*hgt,5.2568);
        d2=15.0-6.5E-3*hgt;

        temp+=273.16;
        e=6.108*humi*exp((17.15*temp-4684.0)/(temp-38.45));
    }
    
    // 计算对流层延迟
    /* saastamoninen model */
    z=PI/2.0-azel[1];                   // 求天顶角z 卫星高度角azel[1]的余角
    trph=0.0022768*pres/(1.0-0.00266*cos(2.0*pos[0])-0.00028*hgt/1E3)/cos(z);   // 干延迟
    trpw=0.002277*(1255.0/temp+0.05)*e/cos(z);  // 湿延迟

    *zwd=trpw;

    return trph;
}

4、trop_model_prec():精密对流层模型

  • 先调用 tropmodel() 相对湿度传 0 计算干延迟 zhd

  • 调用 tropmapf() NMF 投影函数计算干延迟投影系数 m_h、湿延迟投影系数 m_w

  • 格网梯度模型计算梯度系数
    m ( E l r s ) = m W ( E l r s ) { 1 + cot ⁡ E l r s ( G N , r cos ⁡ A z r s + G E , r sin ⁡ A z r s ) } T r s = m H ( E l r s ) Z H , r + m ( E l r s ) ( Z T , r − Z H , r ) \begin{array}{l}m\left(E l_{r}^{s}\right)=m_{W}\left(E l_{r}^{s}\right)\left\{1+\cot E l_{r}^{s}\left(G_{N, r} \cos A z_{r}^{s}+G_{E, r} \sin A z_{r}^{s}\right)\right\} \\ T_{r}^{s}=m_{H}\left(E l_{r}^{s}\right) Z_{H, r}+m\left(E l_{r}^{s}\right)\left(Z_{T, r}-Z_{H, r}\right)\end{array} m(Elrs)=mW(Elrs){1+cotElrs(GN,rcosAzrs+GE,rsinAzrs)}Trs=mH(Elrs)ZH,r+m(Elrs)(ZT,rZH,r)

  • 方差设为 0.01*0.01。

  • 根据干湿延迟和投影系数计算对流层延迟改正量,返回。
    T = M d r y T d r y + M w e t T w e t T=M_{d r y} T_{d r y}+M_{w e t} T_{w e t} T=MdryTdry+MwetTwet

static double trop_model_prec(gtime_t time, const double *pos, const double *azel, 
	const prcopt_t *opt, const double *x, double *dtdx, double *shd, double *var)
{
	const double zazel[]={0.0,PI/2.0};
	double zhd,zwd,m_h,m_w,cotz,grad_n,grad_e;

	// 利用对流层误差模型进行改正,然后将残余误差当作一个未知参数进行估计
	/* zenith hydrostatic delay */
	zhd=tropmodel(time,pos,zazel,0.0,&zwd,1);
    PPP_Glo.zhd=zhd;

	// 调用 tropmapf() NMF 投影函数计算干延迟投影系数 m_h、湿延迟投影系数 m_w
	/* mapping function */
	m_h=tropmapf(time,pos,azel,&m_w);

	*shd=m_h*zhd;

	// 格网梯度模型计算梯度系数
	if (opt->tropopt>=TROPOPT_ESTG&&azel[1]>0.0) {
		/* m_w=m_0+m_0*cot(el)*(Gn*cos(az)+Ge*sin(az)): ref [6]  (E.5.5) */
		cotz=1.0/tan(azel[1]);
		grad_n=m_w*cotz*cos(azel[0]);
		grad_e=m_w*cotz*sin(azel[0]);
		m_w+=grad_n*x[1]+grad_e*x[2];
		dtdx[1]=grad_n*(x[0]);			// (E.5.6)
		dtdx[2]=grad_e*(x[0]);
	}
	dtdx[0]=m_w;
	*var=SQR(0.01);	// 方差设为 0.01*0.01

	//return m_h*zhd+m_w*(x[0]-zhd);
	return m_h*zhd+m_w*(x[0]);
}

5、tropmapf():计算干湿延迟投影系数

干投影函数是通过返回值获得的,而湿投影是通过输入/输出参数mapfw获得的,有两种投影函数的计算方法,分别是 GMF 和 NMF ,默认使用的是 NMF 方法,RTKLIB 可以通过定义IERS_MODEL宏来使用 GMF 方法;GAMP 作者好像实现了一个 tropmapf_gmf() 函数,但是没有调用。

extern double tropmapf(gtime_t time, const double pos[], const double azel[],
                       double *mapfw)
{
#ifdef IERS_MODEL
    const double ep[]={2000,1,1,12,0,0};
    double mjd,lat,lon,hgt,zd,gmfh,gmfw;
#endif
    
    if (pos[2]<-1000.0||pos[2]>20000.0) {
        if (mapfw) *mapfw=0.0;
        return 0.0;
    }
#ifdef IERS_MODEL
    mjd=51544.5+(timediff(time,epoch2time(ep)))/86400.0;
    lat=pos[0];
    lon=pos[1];
    hgt=pos[2]-geoidh(pos); /* height in m (mean sea level) */
    zd =PI/2.0-azel[1];
    
    /* call GMF */
    gmf_(&mjd,&lat,&lon,&hgt,&zd,&gmfh,&gmfw);
    
    if (mapfw) *mapfw=gmfw;
    return gmfh;
#else
    return tropmapf_nmf(time,pos,azel,mapfw); /* NMF */
#endif
}

6、tropmapf_nmf():Neill 投影函数

M d y = 1 + a d r v 1 + b d r y 1 + c d r y sin ⁡ E + a d r y sin ⁡ E + b d r y sin ⁡ E + c d r y + ( 1 sin ⁡ E − 1 + a h t 1 + b h t 1 + c h t sin ⁡ E + a h t sin ⁡ E + b h t sin ⁡ E + c h t ) M wet  = 1 + a wet  1 + b w e t 1 + c wet  sin ⁡ E + a w e t sin ⁡ E + b wet  sin ⁡ E + c w e t a d r y = a c v g ( φ ) + a u m p ( φ ) cos ⁡ ( 2 π D O Y − 28 365.25 ) \begin{array}{c}M_{d y}=\frac{1+\frac{a_{d r v}}{1+\frac{b_{d r y}}{1+c_{d r y}}}}{\sin E+\frac{a_{d r y}}{\sin E+\frac{b_{d r y}}{\sin E+c_{d r y}}}}+\left(\frac{1}{\sin E}-\frac{1+\frac{a_{h t}}{1+\frac{b_{h t}}{1+c_{h t}}}}{\sin E+\frac{a_{h t}}{\sin E+\frac{b_{h t}}{\sin E+c_{h t}}}}\right) \\ M_{\text {wet }}=\frac{1+\frac{a_{\text {wet }}}{1+\frac{b_{w e t}}{1+c_{\text {wet }}}}}{\sin E+\frac{a_{w e t}}{\sin E+\frac{b_{\text {wet }}}{\sin E+c_{w e t}}}} \\ a_{d r y}=a_{c v g}(\varphi)+a_{u m p}(\varphi) \cos \left(2 \pi \frac{D O Y-28}{365.25}\right)\end{array} Mdy=sinE+sinE+sinE+cdrybdryadry1+1+1+cdrybdryadrv+ sinE1sinE+sinE+sinE+chtbhtaht1+1+1+chtbhtaht Mwet =sinE+sinE+sinE+cwetbwet awet1+1+1+cwet bwetawet adry=acvg(φ)+aump(φ)cos(2π365.25DOY28)

其中, E E E 为卫星高度角, h h h 为测站高程,系数 a h t = 2.53 e − 5 , b h t = 5.49 e − 3 a_{h t}=2.53 e-5, b_{h t}=5.49 e-3 aht=2.53e5,bht=5.49e3 c h t = 1.14 e − 3 , a a v g ( φ ) , a a m p ( φ ) c_{h t}=1.14 e-3, a_{a v g}(\varphi), a_{a m p}(\varphi) cht=1.14e3,aavg(φ),aamp(φ) 查表内插的方法获得, D O Y D O Y DOY 为年积日,如果测站在南半球时 D O Y − 180 D O Y-180 DOY180

extern double tropmapf_nmf(gtime_t time, const double pos[], const double azel[],
                  double *mapfw)
{
    /* ref [5] table 3 */
    /* hydro-ave-a,b,c, hydro-amp-a,b,c, wet-a,b,c at latitude 15,30,45,60,75 */
    const double coef[][5]={
        { 1.2769934E-3, 1.2683230E-3, 1.2465397E-3, 1.2196049E-3, 1.2045996E-3},
        { 2.9153695E-3, 2.9152299E-3, 2.9288445E-3, 2.9022565E-3, 2.9024912E-3},
        { 62.610505E-3, 62.837393E-3, 63.721774E-3, 63.824265E-3, 64.258455E-3},
        
        { 0.0000000E-0, 1.2709626E-5, 2.6523662E-5, 3.4000452E-5, 4.1202191E-5},
        { 0.0000000E-0, 2.1414979E-5, 3.0160779E-5, 7.2562722E-5, 11.723375E-5},
        { 0.0000000E-0, 9.0128400E-5, 4.3497037E-5, 84.795348E-5, 170.37206E-5},
        
        { 5.8021897E-4, 5.6794847E-4, 5.8118019E-4, 5.9727542E-4, 6.1641693E-4},
        { 1.4275268E-3, 1.5138625E-3, 1.4572752E-3, 1.5007428E-3, 1.7599082E-3},
        { 4.3472961E-2, 4.6729510E-2, 4.3908931E-2, 4.4626982E-2, 5.4736038E-2}
    };
    const double aht[]={ 2.53E-5, 5.49E-3, 1.14E-3}; /* height correction */
    
    double y,cosy,ah[3],aw[3],dm,el=azel[1],lat=pos[0]*R2D,hgt=pos[2];
    int i;
    
    if (el<=0.0) {
        if (mapfw) *mapfw=0.0;
        return 0.0;
    }
    /* year from doy 28, added half a year for southern latitudes */
    y=(time2doy(time)-28.0)/365.25+(lat<0.0?0.5:0.0);
    
    cosy=cos(2.0*PI*y);
    lat=fabs(lat);
    
    for (i=0;i<3;i++) {
        ah[i]=interpc(coef[i  ],lat)-interpc(coef[i+3],lat)*cosy;
        aw[i]=interpc(coef[i+6],lat);
    }
    /* ellipsoidal height is used instead of height above sea level */
    dm=(1.0/sin(el)-mapf(el,aht[0],aht[1],aht[2]))*hgt/1E3;
    
    if (mapfw) *mapfw=mapf(el,aw[0],aw[1],aw[2]);   // mapfw 湿延迟函数
    
    return mapf(el,ah[0],ah[1],ah[2])+dm;   // 返回干延迟投影函数
}

二、电离层延迟改正

1、原理

受太阳辐射的影响,距地面 60km 以上的大气层处于部分电离或完全电离状态,该区域被称为电离层。当电磁波信号通过电离层时,传播速度和传播路径会发生改变,给 GNSS 观测值带来误差,即电离层延迟。电离层延迟大小由电子密度和信号频率决定,影响可达数十米。由于 GNSS 信号的特性,同一频率载波相位和伪距观测值电离层延迟大小相等,符号相反。在一些条件下,可使用经验模型改正或约束观测值中的电离层延迟,常用的电离层延迟经验模型有 Klobuchar 模型、Bent 模型和电离层格网模型等。本文对电离层延迟的处理使用最常用的两种方法:使用非差非组合模型估计各卫星第一频率倾斜电离层延迟;使用无电离层组合消除电离层延迟一阶项,忽略二阶及以上项。

2、model_iono():电离层改正入口函数

  • TEC 格网模型改正:调用 iontec() 计算改正量,方差也在 iontec() 中计算。
  • 广播星历改正:调用 ionmodel() 克罗布歇模型计算改正量,方差设为 0.5 乘以电离层改正量再平方。
  • 电离层估计:从参数向量 x 中取改正量,方差设为 0。
  • L1/L2消电离层组合:电离层改正量和方差设为 0。

计算得到的 L1 频率的电离层改正量,作为参数 dion 传出,当使用其它频率信号时,依据所用信号频组中第一个频率的波长与 L1 波长的比例关系,对上一步得到的电离层延时进行修正,不考虑模糊度情况下改正公式为:
I = Φ 2 − Φ 1 1 − ( f 1 / f 2 ) 2 I=\frac{\Phi_{2}-\Phi_{1}}{1-\left(f_{1} / f_{2}\right)^{2}} I=1(f1/f2)2Φ2Φ1

3、ionmodel():克罗布歇模型计算电离层改正量

使用克罗布歇模型计算 L1 的电离层改正量,将晚间的电离层时延视为常数,取值为 5ns,把白天的时延看成是余弦函数中正的部分。于是天顶方向调制在 L1 载波上的测距码的电离层时延可表示为:
T g = 5 × 1 0 − 9 + A cos ⁡ 2 π P ( t − 1 4 h ) T_{g}=5 \times 10^{-9}+A \cos \frac{2 \pi}{P}\left(t-14^{h}\right) Tg=5×109+AcosP2π(t14h)
振幅 A A A 和周期 P P P 是模型中需要计算的部分,分别为:
A = ∑ i = 0 3 α i ( φ m ) i P = ∑ i = 0 3 β i ( φ m ) i \begin{array}{l} A=\sum_{i=0}^{3} \alpha_{i}\left(\varphi_{m}\right)^{i} \\ P=\sum_{i=0}^{3} \beta_{i}\left(\varphi_{m}\right)^{i} \end{array} A=i=03αi(φm)iP=i=03βi(φm)i
全球定位系统向单频接收机用户提供的电离层延迟改正时就采用上述模型。其中 α i \alpha_i αi β i \beta_i βi 是地面控制系统根据该天为一年中的第几天(将一年分为 37 个区间)以及前 5 天太阳的平均辐射流量(共分10档)从 370 组常数中选取的,然后编入星导航电文播发给用户。卫星在其播发的导航电文中提供了这 8 个电离层延迟参数:
p ion  = ( α 0 , α 1 , α 2 , α 3 , β 0 , β 1 , β 2 , β 3 ) T p_{\text {ion }}=\left(\alpha_{0}, \alpha_{1}, \alpha_{2}, \alpha_{3}, \beta_{0}, \beta_{1}, \beta_{2}, \beta_{3}\right)^{T} pion =(α0,α1,α2,α3,β0,β1,β2,β3)T
根据根据参数 α 0 , α 1 , α 2 , α 3 \alpha_0,\alpha_1,\alpha_2,\alpha_3 α0α1α2α3 确定振幅 A A A,根据根据参数 β 0 , β 1 , β 2 , β 3 \beta_0,\beta_1,\beta_2,\beta_3 β0β1β2β3 确定周期 T T T,再给定一个以秒为单位的当地时间 t t t,就能算出天顶电离层延迟。再由天顶对流层延迟根据倾斜率转为卫星方向对流层延迟。

电离层分布在离地面 60-1000km 的区域内。当卫星不在测站的天顶时,信号传播路径上每点的地方时和纬度均不相同,为了简化计算,我们将整个电离层压缩为一个单层,将整个电离层中的自由电子都集中在该单层上,用它来代替整个电离层。这个电离层就称为中心电离层。中心电离层离地面的高度通常取 350km。需要计算卫星言号传播路径与中心电离层的交点 P ′ P^{\prime} P 的时角 t t t 和地磁纬度 φ m \varphi_{m} φm ,因为只有 P ′ P^{\prime} P 才能反映卫星信号所受到的电离层延迟的总的情况。

综上,已知大地经度、 大地纬度、卫星的高度角和卫星测站的方位角,电离层延迟计算方法如下:

计算测站 P P P P ′ P^{\prime} P 在地心的夹角:
ψ = 0.0137 / ( E l + 0.11 ) − 0.022 \psi=0.0137 /(E l+0.11)-0.022 ψ=0.0137/(El+0.11)0.022
计算交点 P ′ P^{\prime} P 的地心纬度:
φ i = φ + ψ cos ⁡ A z \varphi_{i}=\varphi+\psi \cos A z φi=φ+ψcosAz

{ φ l > + 0.416 φ l = + 0.416 φ l > − 0.416 φ l = − 0.416 \left\{\begin{array}{ll}\varphi_{l}>+0.416 & \varphi_{l}=+0.416 \\ \varphi{l}>-0.416 & \varphi_{l}=-0.416\end{array}\right. {φl>+0.416φl>0.416φl=+0.416φl=0.416

计算交点 P ′ P^{\prime} P 的地心经度:
λ i = λ + ψ sin ⁡ A z / cos ⁡ φ i \lambda_{i}=\lambda+\psi \sin A z / \cos \varphi_{i} λi=λ+ψsinAz/cosφi
计算地磁纬度:
φ m = φ i + 0.064 cos ⁡ ( λ i − 1.617 ) \varphi_{m}=\varphi_{i}+0.064 \cos \left(\lambda_{i}-1.617\right) φm=φi+0.064cos(λi1.617)
计算观测瞬间交点 P ′ P^{\prime} P 处的地方时:
t = 4.32 × 1 0 4 λ i + t t=4.32 \times 10^{4} \lambda_{i}+t t=4.32×104λi+t

{ t > 86400 t = t − 86400 t < 0 t = t + 86400 \left\{\begin{array}{ll}t>86400 & t=t-86400 \\ t<0 & t=t+86400\end{array}\right. {t>86400t<0t=t86400t=t+86400

计算倾斜因子:
F = 1.0 + 16.0 × ( 0.53 − E l ) 3 F=1.0+16.0 \times(0.53-E l)^{3} F=1.0+16.0×(0.53El)3
最后计算电离层时间延迟:
x = 2 π ( t − 50400 ) / ∑ n = 0 3 β n φ m n I r s = { F × 5 × 1 0 − 9 F × ( 5 × 1 0 − 9 + ∑ n = 1 4 α n φ m n × ( 1 − x 2 2 + x 4 24 ) ) ( ∣ x ∣ > 1.57 ) \begin{array}{l}x=2 \pi(t-50400) / \sum_{n=0}^{3} \beta_{n} \varphi_{m}{ }^{n} \\ I_{r}^{s}=\left\{\begin{array}{cc}F \times 5 \times 10^{-9} \\ F \times\left(5 \times 10^{-9}+\sum_{n=1}^{4} \alpha_{n} \varphi_{m}{ }^{n} \times\left(1-\frac{x^{2}}{2}+\frac{x^{4}}{24}\right)\right) & (|x|>1.57)\end{array}\right.\end{array} x=2π(t50400)/n=03βnφmnIrs={F×5×109F×(5×109+n=14αnφmn×(12x2+24x4))(x>1.57)

extern double ionmodel(gtime_t t, const double *ion, const double *pos,
                       const double *azel)
{
    const double ion_default[]={ /* 2004/1/1 */
        0.1118E-07,-0.7451E-08,-0.5961E-07, 0.1192E-06,
        0.1167E+06,-0.2294E+06,-0.1311E+06, 0.1049E+07
    };
    double tt,f,psi,phi,lam,amp,per,x;
    int week;
    
    if (pos[2]<-1E3||azel[1]<=0) return 0.0;
    if (norm(ion,8)<=0.0) ion=ion_default;  // 若没有电离层参数,用默认参数


    /* earth centered angle (semi-circle) */    // 地球中心角
    psi=0.0137/(azel[1]/PI+0.11)-0.022;         // 计算地心角(E.5.6)
    
    /* subionospheric latitude/longitude (semi-circle) */   
    phi=pos[0]/PI+psi*cos(azel[0]);                 // 计算穿刺点地理纬度(E.5.7)
    if      (phi> 0.416) phi= 0.416;        // phi不超出(-0.416,0.416)范围
    else if (phi<-0.416) phi=-0.416;
    lam=pos[1]/PI+psi*sin(azel[0])/cos(phi*PI);     // 计算穿刺点地理经度(E.5.8)
    
    /* geomagnetic latitude (semi-circle) */
    phi+=0.064*cos((lam-1.617)*PI);                 // 计算穿刺点地磁纬度(E.5.9)
    
    /* local time (s) */
    tt=43200.0*lam+time2gpst(t,&week);              // 计算穿刺点地方时(E.5.10)
    tt-=floor(tt/86400.0)*86400.0; /* 0<=tt<86400 */
    
    /* slant factor */
    f=1.0+16.0*pow(0.53-azel[1]/PI,3.0);            // 计算投影系数(E.5.11)
    
    /* ionospheric delay */
    amp=ion[0]+phi*(ion[1]+phi*(ion[2]+phi*ion[3]));
    per=ion[4]+phi*(ion[5]+phi*(ion[6]+phi*ion[7]));
    amp=amp<    0.0?    0.0:amp;
    per=per<72000.0?72000.0:per;
    x=2.0*PI*(tt-50400.0)/per;                      // (E.5.12)
    
    return CLIGHT*f*(fabs(x)<1.57?5E-9+amp*(1.0+x*x*(-0.5+x*x/24.0)):5E-9);     //(E.5.13)
}

4、iontec():TEC 模型计算电离层改正量

image-20231104110835242

格网改正模型电离层格网模型文件 IONEX,通过内插获得穿刺点位置,并结合当天电离层格网数据求出穿刺点的垂直电子含量,获得电离层延迟误差 。

1. readtec():电离层 IONEX 文件读取

IONEX 文件分四大部分:文件头结束于END OF HEADER多组总电子含量,每组以START OF TEC MAP ,结束于END OF TEC MAP多组电子含量均方根误差 ,与总电子含量对应,开始于START OF RMS MAP,结束于END OF RMS MAPDCB数据块开始于START OF AUS DATA,结束于END OF AUS DATA,也称辅助数据块(Auxiliary Data Blocks)。

image-20231104111521575

readtec() 执行流程

image-20231104111854787

  • 开辟内存空间
  • 扩展file的*到efile[] ,遍历efile[]
  • fopen()以读的方式打开
  • 调用readionexh()读 ionex 文件头
  • 调用readionexb()读 ionex 文件体 ,其中会调用 addtec() 将 tec 格网数据存到nav->tec[]
  • 读取完之后,调用combtec()合并 tec 格网数据
  • 存 DCB 参数到nav->cbias
extern void readtec(const char *file, nav_t *nav, int opt)
{
    FILE *fp;
    double lats[3]={0},lons[3]={0},hgts[3]={0},rb=0.0,nexp=-1.0;
    double dcb[MAXSAT]={0},rms[MAXSAT]={0};
    int i,n;
    char *efiles[MAXEXFILE];
    
    trace(3,"readtec : file=%s\n",file);
    
    /* clear of tec grid data option */
    if (!opt) { //如果没有opt,释放nav->tec,nav->ntmax置0
        free(nav->tec); nav->tec=NULL; nav->nt=nav->ntmax=0;
    }
    for (i=0;i<MAXEXFILE;i++) {     //为efile[]开辟空间
        if (!(efiles[i]=(char *)malloc(1024))) {
            for (i--;i>=0;i--) free(efiles[i]);
            return;
        }
    }
    /* expand wild card in file path */
    n=expath(file,efiles,MAXEXFILE);    //扩展file的*到efile[]
    
    //遍历efile[]
    for (i=0;i<n;i++) {
        if (!(fp=fopen(efiles[i],"r"))) {       //以读的方式打开
            trace(2,"ionex file open error %s\n",efiles[i]);
            continue;
        }
        /* read ionex header */     //调用readionexh()读ionex文件头
        if (readionexh(fp,lats,lons,hgts,&rb,&nexp,dcb,rms)<=0.0) {     
            trace(2,"ionex file format error %s\n",efiles[i]);
            continue;
        }
        /* read ionex body */       //调用readionexb()读ionex文件体
        readionexb(fp,lats,lons,hgts,rb,nexp,nav);
        
        fclose(fp);
    }
    for (i=0;i<MAXEXFILE;i++) free(efiles[i]);
    
    /* combine tec grid data */
    if (nav->nt>0) combtec(nav);    //调用combtec()合并tec格网数据
    
    /* P1-P2 dcb */
    for (i=0;i<MAXSAT;i++) {
        nav->cbias[i][0]=CLIGHT*dcb[i]*1E-9; /* ns->m */	//存DCB到nav->cbias
    }
}

调用函数:

  • readionexh():读取文件头,循环读取每一行,根据注释读取前面内容,如果遇到START OF AUX DATA ,调用 readionexdcb() 读取 DCB 参数。
  • readionexdcb():循环读取 DCB 参数和对应的均方根误差,直到END OF AUS DATA
  • readionexb():循环读取 TEC 格网数据和均方根误差,type为 1 是 TEC 格网,type为2是均分根误差,调用addtec()将tec格网数据存到nav->tec[]
  • combtec():合并nav->tec[]中时间相同的项。
2. iontec():TEC 格网改正入口函数

image-20231104112203634

由所属时间段两端端点的 TEC 网格数据时间插值计算出电离层延迟 (L1) (m)

  • 检测高度角和接收机高度是否大于阈值
  • nav_t.tec中找出第一个tec[i].time>time信号接收时间
  • 确保 time是在所给出的nav_t.tec包含的时间段之中 ,通过确认所找到的时间段的右端点减去左端点,来确保时间间隔不为0
  • 调用iondelay()来计算所属时间段两端端点的电离层延时
  • 由两端的延时,插值计算出观测时间点处的值
extern int iontec(gtime_t time, const nav_t *nav, const double *pos,
                  const double *azel, int opt, double *delay, double *var)
{
    double dels[2],vars[2],a,tt;
    int i,stat[2];

    // 检测高度角和接收机高度是否大于阈值
    if (azel[1]<MIN_EL||pos[2]<MIN_HGT) {
        *delay=0.0;
        *var=VAR_NOTEC;
        return 1;
    }
    // 从 nav_t.tec 中找出第一个 tec[i].time>time 信号接收时间
    for (i=0;i<nav->nt;i++) {
        if (timediff(nav->tec[i].time,time)>0.0) break;
    }
    // 确保 time 是在所给出的 nav_t.tec 包含的时间段之中
    if (i==0||i>=nav->nt) {
        printf("%s: tec grid out of period\n",time_str(time,0));
        return 0;
    }
    // 通过确认所找到的时间段的右端点减去左端点,来确保时间间隔 != 0
    if ((tt=timediff(nav->tec[i].time,nav->tec[i-1].time))==0.0) {
        printf("tec grid time interval error\n");
        return 0;
    }
    // 调用 iondelay 来计算所属时间段两端端点的电离层延时
    /* ionospheric delay by tec grid data */
    stat[0]=iondelay(time,nav->tec+i-1,pos,azel,opt,dels  ,vars  );
    stat[1]=iondelay(time,nav->tec+i  ,pos,azel,opt,dels+1,vars+1);
    
    // 由两端的延时,插值计算出观测时间点处的值
    if (!stat[0]&&!stat[1]) {   // 两个端点都计算出错,输出错误信息,返回 0
        printf("%s: tec grid out of area pos=%6.2f %7.2f azel=%6.1f %5.1f\n",
              time_str(time,0),pos[0]*R2D,pos[1]*R2D,azel[0]*R2D,azel[1]*R2D);
        return 0;
    }
    // 两个端点都有值,线性插值出观测时间点的值,返回 1
    if (stat[0]&&stat[1]) { /* linear interpolation by time */
        a=timediff(time,nav->tec[i-1].time)/tt;
        *delay=dels[0]*(1.0-a)+dels[1]*a;
        *var  =vars[0]*(1.0-a)+vars[1]*a;
    }
    // 只有一个端点有值,将其结果作为观测时间处的值,返回 1
    else if (stat[0]) { /* nearest-neighbour extrapolation by time */
        *delay=dels[0];
        *var  =vars[0];
    }
    else {
        *delay=dels[1];
        *var  =vars[1];
    }

    return 1;
}
3. iondelay():计算指定时间电离层延迟
  • while大循环tec->ndata[2]次:
  • 调用ionppp()函数,计算当前电离层高度,穿刺点的位置 {lat,lon,h} (rad,m)和倾斜率
  • 按照M-SLM映射函数重新计算倾斜率
  • 在日固系中考虑地球自转,重新计算穿刺点经度
  • 调用interptec()格网插值获取vtec
  • *delay+=fact*fs*vtec ,*var+=fact*fact*fs*fs*rms*rms
static int iondelay(gtime_t time, const tec_t *tec, const double *pos,
                    const double *azel, int opt, double *delay, double *var)
{
    const double fact=40.30E16/FREQ1/FREQ1; /* tecu->L1 iono (m) */
    double fs,posp[3]={0},vtec,rms,hion,rp;
    int i;
    
    *delay=*var=0.0;
    
    for (i=0;i<tec->ndata[2];i++) { /* for a layer */
        hion=tec->hgts[0]+tec->hgts[2]*i;

        // 调用ionppp()函数,计算当前电离层高度,穿刺点的位置 {lat,lon,h} (rad,m)和倾斜率( )
        /* ionospheric pierce point position */
        fs=ionppp(pos,azel,tec->rb,hion,posp);
        
        // 按照 M-SLM 映射函数重新计算倾斜率
        /*if (opt&2) {*/
        /* modified single layer mapping function (M-SLM) ref [2] */
        rp=tec->rb/(tec->rb+hion)*sin(0.9782*(PI/2.0-azel[1]));
        fs=1.0/sqrt(1.0-rp*rp);

        // 在日固系中考虑地球自转,重新计算穿刺点经度
        //} 
        //if (opt&1) {
        //    /* earth rotation correction (sun-fixed coordinate) */
        //    posp[1]+=2.0*PI*timediff(time,tec->time)/86400.0;
        //}

        // 调用 interptec() 格网插值获取 vtec
        /* interpolate tec grid data */
        if (!interptec(tec,i,posp,&vtec,&rms)) return 0;
        
        *delay+=fact*fs*vtec;
        *var+=fact*fact*fs*fs*rms*rms;
    }
    
    return 1;
}
4. ionppp():计算电离层穿刺点

位置 {lat,lon,h} (rad,m)和倾斜率做返回值
z = π / 2 − E l r s z ′ = arcsin ⁡ ( R E R E + H sin ⁡ z ) α = z − z ′ ϕ I P P = arcsin ⁡ ( cos ⁡ α sin ⁡ ϕ r + sin ⁡ α cos ⁡ ϕ r cos ⁡ A z r s ) \begin{array}{l}z=\pi / 2-E l_{r}^{s} \\ z^{\prime}=\arcsin \left(\frac{R_{E}}{R_{E}+H} \sin z\right) \\ \alpha=z-z^{\prime} \\ \phi_{I P P}=\arcsin \left(\cos \alpha \sin \phi_{r}+\sin \alpha \cos \phi_{r} \cos A z_{r}^{s}\right)\end{array} z=π/2Elrsz=arcsin(RE+HREsinz)α=zzϕIPP=arcsin(cosαsinϕr+sinαcosϕrcosAzrs)

extern double ionppp(const double *pos, const double *azel, double re,
                     double hion, double *posp)
{
    double cosaz,rp,ap,sinap,tanap;
    // z 并不是仰角 azel[1],而是仰角关于的补角,所以程序中在计算 rp 是采用的是 cos(azel[1]) 的写法
    rp=re/(re+hion)*cos(azel[1]);
    ap=PI/2.0-azel[1]-asin(rp);     // (E.5.14) (E.5.16)
    sinap=sin(ap);
    tanap=tan(ap);
    cosaz=cos(azel[0]);
    posp[0]=asin(sin(pos[0])*cos(ap)+cos(pos[0])*sinap*cosaz);      // (E.5.17)
    
    if ((pos[0]> 70.0*D2R&& tanap*cosaz>tan(PI/2.0-pos[0]))||
        (pos[0]<-70.0*D2R&&-tanap*cosaz>tan(PI/2.0+pos[0]))) {
        posp[1]=pos[1]+PI-asin(sinap*sin(azel[0])/cos(posp[0]));    // (E.5.18a)
    }
    else {
        posp[1]=pos[1]+asin(sinap*sin(azel[0])/cos(posp[0]));       // (E.5.18b)
    }
    return 1.0/sqrt(1.0-rp*rp); // 返回倾斜率

    // 可能因为后面再从 TEC 网格数据中插值时,并不需要高度信息,所以这里穿刺点位置 posp[2] 没有赋值
}
5. dataindex():获取 TEC 格网数据下标

先判断点位是否在格网中,之后获取网格点的 tec 数据在 tec.data 中的下标

static int dataindex(int i, int j, int k, const int *ndata) //(i:lat,j:lon,k:hgt)
{
    if (i<0||ndata[0]<=i||j<0||ndata[1]<=j||k<0||ndata[2]<=k) return -1;
    return i+ndata[0]*(j+ndata[1]*k);
}
6. interptec():插值计算穿刺点处 TEC

通过在经纬度网格点上进行双线性插值,计算第 k 个高度层时穿刺点处的电子数总量 TEC
TEC ⁡ ( t , ϕ I P P , λ I P P ) = ( t − t i ) T E C ( t i , ϕ I P P , λ I P P + ω ( t − t i ) ) + ( t i + 1 − t ) T E C ( t i + 1 , ϕ I P P , λ I P P + ω ( t − t i + 1 ) ) t i + 1 − t i \operatorname{TEC}\left(t, \phi_{I P P}, \lambda_{I P P}\right)=\frac{\left(t-t_{i}\right) T E C\left(t_{i}, \phi_{I P P}, \lambda_{I P P}+\omega\left(t-t_{i}\right)\right)+\left(t_{i+1}-t\right) T E C\left(t_{i+1}, \phi_{I P P}, \lambda_{I P P}+\omega\left(t-t_{i+1}\right)\right)}{t_{i+1}-t_{i}} TEC(t,ϕIPP,λIPP)=ti+1ti(tti)TEC(ti,ϕIPP,λIPP+ω(tti))+(ti+1t)TEC(ti+1,ϕIPP,λIPP+ω(tti+1))

static int interptec(const tec_t *tec, int k, const double *posp, double *value,
                     double *rms)
{
    double dlat,dlon,a,b,d[4]={0},r[4]={0};
    int i,j,n,index;
    
    *value=*rms=0.0;    // 将 value和 rms所指向的值置为 0
    
    if (tec->lats[2]==0.0||tec->lons[2]==0.0) return 0;
    
    // 将穿刺点的经纬度分别减去网格点的起始经纬度,再除以网格点间距,对结果进行取整,
    // 得到穿刺点所在网格的序号和穿刺点所在网格的位置(比例) i,j 
    dlat=posp[0]*R2D-tec->lats[0];
    dlon=posp[1]*R2D-tec->lons[0];
    if (tec->lons[2]>0.0) dlon-=floor( dlon/360)*360.0; /*  0<=dlon<360 */
    else                  dlon+=floor(-dlon/360)*360.0; /* -360<dlon<=0 */
    
    a=dlat/tec->lats[2];
    b=dlon/tec->lons[2];
    i=(int)floor(a); a-=i;
    j=(int)floor(b); b-=j;
    
    // 调用 dataindex() 函数分别计算这些网格点的 tec 数据在 tec.data中的下标,
    // 按从左下到右上的顺序
    // 从而得到这些网格点处的 TEC 值和相应误差的标准差
    /* get gridded tec data */
    for (n=0;n<4;n++) {
        if ((index=dataindex(i+(n%2),j+(n<2?0:1),k,tec->ndata))<0) continue;
        d[n]=tec->data[index];
        r[n]=tec->rms [index];
    }
    if (d[0]>0.0&&d[1]>0.0&&d[2]>0.0&&d[3]>0.0) {
        // 穿刺点位于网格内,使用双线性插值计算出穿刺点的 TEC 值
        /* bilinear interpolation (inside of grid) */
        *value=(1.0-a)*(1.0-b)*d[0]+a*(1.0-b)*d[1]+(1.0-a)*b*d[2]+a*b*d[3];
        *rms  =(1.0-a)*(1.0-b)*r[0]+a*(1.0-b)*r[1]+(1.0-a)*b*r[2]+a*b*r[3];
    }
    // 穿刺点不位于网格内,使用最邻近的网格点值作为穿刺点的 TEC 值,不过前提是网格点的 TEC>0
    /* nearest-neighbour extrapolation (outside of grid) */
    else if (a<=0.5&&b<=0.5&&d[0]>0.0) {*value=d[0]; *rms=r[0];}
    else if (a> 0.5&&b<=0.5&&d[1]>0.0) {*value=d[1]; *rms=r[1];}
    else if (a<=0.5&&b> 0.5&&d[2]>0.0) {*value=d[2]; *rms=r[2];}
    else if (a> 0.5&&b> 0.5&&d[3]>0.0) {*value=d[3]; *rms=r[3];}
    // 否则,选用四个网格点中 >0 的值的平均值作为穿刺点的 TEC 值
    else {
        i=0;
        for (n=0;n<4;n++) if (d[n]>0.0) {i++; *value+=d[n]; *rms+=r[n];}
        if(i==0) return 0;
        *value/=i; *rms/=i;
    }
    return 1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1171354.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

redis数据库缓存服务器

redis比mysql访问数据快 非关系型数据库以键值对的方式存储数据 作用&#xff1a;加快访问速度&#xff0c;缓解数据库压力 redis最新版本7 特点 丰富的数据结构 list,set,hash等数据结构的存储 支持持久化 支持事务 “一个完整的动作&#xff0c;要么全部执行&#xff0…

模拟与高精度

文章目录 模拟[NOIP2003 普及组] 乒乓球[NOIP2015 普及组] 扫雷游戏[NOIP2016 提高组] 玩具谜题 高精度P1601 AB Problem&#xff08;高精&#xff09;P1303 A*B Problem[NOIP1998 普及组] 阶乘之和 #mermaid-svg-LVtcjL47i4zwUnwI {font-family:"trebuchet ms",verd…

面试梳理-Redis01

目录 开场白-追命3连 使用场景 01缓存穿透场景与方案 02布隆过滤器 03缓存击穿场景与方案 04缓存雪崩场景与方案 开场白-追命3连 看你项目中有说用到Redis&#xff0c;都是哪些场景使用了Redis呢&#xff1f; 如果发生了缓存穿透、击穿、雪崩如何应对呢&#xff1f;缓存…

程序员笔记本电脑选 windows 还是 MAC

计算机选择是每个进入 IT 行业同学的第一个重要选择&#xff0c;那么你是怎么选择的呢&#xff1f; 选择操作系统&#xff08;Windows还是macOS&#xff09;取决于程序员的需求、偏好和工作流程。每个操作系统都有其优点和缺点&#xff0c;下面将分别讨论它们&#xff0c;以帮助…

一文搞懂设计模式之七大原则

大家好&#xff0c;我是晴天。在接下来的一个多月里&#xff0c;我将跟大家一起学习设计模式的一些基础知识和基本应用。不要问我为什么突然想起来写一个设计模式系列的文章&#xff0c;问就是&#xff1a;爱过。。。 问题引出 作为程序猿的我们&#xff0c;隔三岔五的就会因为…

上班族必备:制作电子宣传册的网站

​对于上班族来说&#xff0c;制作电子宣传册是一项非常重要的技能。因为宣传册是展示公司形象、产品特点、服务优势的重要工具&#xff0c;也是与客户沟通交流的重要手段。那么&#xff0c;如何制作一份高质量的电子宣传册呢&#xff1f;今天就为大家推荐几个制作电子宣传册的…

hackergame2023菜菜WP

文章目录 总结Hackergame2023更深更暗组委会模拟器猫咪小测标题HTTP集邮册Docker for everyone惜字如金 2.0Git? Git!高频率星球低带宽星球小型大语言模型星球旅行日记3.0JSON ⊂ YAML? 总结 最近看到科大在举办CTF比赛&#xff0c;刚好我学校也有可以参加&#xff0c;就玩了…

SQL左连接实战案例

要求&#xff1a;用表df1和表df2的数据&#xff0c;得到df3 一、创建表 CREATE TABLE df1 (姓名 varchar(255) DEFAULT NULL,年龄 int DEFAULT NULL,部门 varchar(255) DEFAULT NULL,id int DEFAULT NULL );CREATE TABLE df2 (部门 varchar(255) DEFAULT NULL,年龄 int DEFAU…

【LeetCode刷题-链表】--328.奇偶链表

328.奇偶链表 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next; }* }*/ clas…

【漏洞复现】Apache_Tomcat_PUT方法任意写文件(CVE-2017-12615)

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证工具扫描验证POC 1.6、修复建议 说明内容漏洞编号CVE-2017-12615漏洞名称Tomcat_PU…

python实现多帧torch.istft的结果可以由多个单帧torch.istft的结果重叠拼接得到

&#x1f525; &#x1f525; &#x1f525; 背景&#xff1a;做某个项目&#xff08;由于项目处于保密状态&#xff0c;只提供思路&#xff09;&#xff0c;需要求多帧的istft。但是手头只有单帧的istft代码(当然不能python代码&#xff0c;不然就直接调包)。 &#x1f4e3; …

Quartus II 13.0波形仿真(解决无法产生仿真波形问题)

目录 前言 新建工程 创建Verilog文件&#xff0c;写代码 波形仿真&#xff08;解决没有输出波问题&#xff09; 前言 这么说把Quartus II 13.0是我目前来讲见过最恶心的软件&#xff0c;总是一大堆麻烦事&#xff0c;稍微哪里没弄好就后面全都出问题。很多人在写完Verilog代…

ke9案例三:页面提交文件,我服务器端接收

案例三:页面提交文件,我服务器端接收 ProcessFile.java 1value "/process-file" 2获取邮件消息的所有部分part--Collection<Part> partsrequest.getParts(); 3遍历每一个part 4之后可以打印头文件等String headerpart.getHeader("content-disposition&q…

配件管理系统软件哪家好?企业配件管理要怎么做?

在许多企业中&#xff0c;生产数据的记录仍然依赖于纸质流转卡&#xff0c;这种传统的方式带来了许多问题。手工填写导致的字迹潦草、数据不准确或不完全、统计困难等都是无法避免的问题。为了解决这些问题&#xff0c;我们推荐使用一款智能配件管理系统&#xff0c;帮助企业从…

Springboot搭建微服务案例之Eureka注册中心

一、父工程依赖管理 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org…

常见通信协议

博客内容&#xff1a;UART,IIC,SPI 文章目录 一、UART二、IIC三、SPI总结 一、UART 一种串行通信接口协议&#xff0c;用于在计算机系统和外部设备之间进行数据传输。UART可以支持异步和同步两种通信方式。在异步通信方式下&#xff0c;数据传输不需要在发送方和接收方之间进行…

自学SLAM(7)非线性优化实践:曲线拟合问题(使用ceres库和SLAM常用的g2o库)

前言 本次文章针对的是第四个视屏中的实践问题 肯定会有部分方法没有说到&#xff0c;比如高斯牛顿法&#xff0c;后面我会把此次视屏对应的作业写好&#xff0c;然后补充到此次博客&#xff01;&#xff01; 文章目录 前言1.曲线拟合题目&#xff1a;2.非线性最小二乘2.1 黄金…

网络基础扫盲-初识网络

博客内容&#xff1a;初识网络 文章目录 一、OSI七层网络模型二、TCP/IP四层模型1、MAC地址与IP地址 前言 在以前网络不够发之前&#xff0c;各个实验室进行一些研究时需要进行数据的交流&#xff0c;但是那时车马很慢&#xff0c;一生只够跑几次&#xff0c;所以就有人研究了网…

Reshape.XL 1.2 for Excel插件 Crack

特征 插件 Reshape.XL 包括 130 个基本可组合功能。使用它们&#xff0c;您可以快速轻松地进行非常复杂的数据转换和处理。它们的架构和基本定义受到 SQL 和 R 语言的强烈启发。 到目前为止&#xff0c;类似的功能只能通过脚本语言供程序员使用。借助 Reshape.XL 插件&#xf…

Pyhotn: Mac安装selenium和chromedriver-119

1.0 安装selenium 终端输入&#xff1a; pip install selenium 查看版本&#xff1a; pip show selenium2.0 安装chromedriver 查看chrome版本 网上大多数是&#xff0c;基本到114就停了。 https://registry.npmmirror.com/binary.html?pathchromedriver/ 各种搜索&#…