欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)

程序员文章站 2022-04-14 07:51:08
...

IDL制作Himawari-8太阳角度数据集(太阳方位角、天顶角)
计算卫星方位角和方位角与计算太阳方位角的原理相同,根据《卫星轨道坐标系及坐标转换》(向汝建)https://max.book118.com/html/2015/0312/13226794.shtm一文中的总结,计算方位的步骤为以下几步:
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
计算太阳角度,首先计算儒略日JD,需要从HSD数据中读入observation start time

openr,h8_lun,inputfile,/get_lun
;获取Observation start time
point_lun,h8_lun,46
imgtime=dblarr(1);R8
readu,h8_lun,imgtime

由于HSD数据中读入的observation start time为MJD,又知MJD=JD-2400000.5,故而

jd = imgtime[0]*1.0d + 2400000.5

imgtime要时一个后面带d的double型数,乘以1.0d就可以使数据转为double类型,否则IDL会出现搞笑一幕:
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
如果是UTC时间,在IDL,Python或者matlab中都有将UTC时间转为儒略日时间的函数,可直接转换。
JD计算完成后是计算观测点的ECI坐标,即笛卡尔坐标系下的坐标。

IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
计算ECI坐标,这里在之前的生成Himawari-8几何校正文件一文中https://blog.csdn.net/qq_33339770/article/details/102957857,对影像上每个像元的经纬度都进行过计算,故可形成像元坐标文件,这里的坐标是lon,lat,alt(可用ENVI自带DEM数据提取高程,也可直接定义为0)。
也可以自己定义左上角坐标80.0,60.0,行列数6001或12001,像元宽高0.02或0.01来书写lon,lat文件,但是最终计算结果会在纬度为0.0的一行结果反向,不想单独处理这一行,故而选择使用通过HSD文件中的行列偏移计算出的坐标文件。
需要将lon,lat,alt转为ECI坐标系下的x0,y0,z0坐标,根据论文中所述,地理经度在ECI坐标中是时间的函数,故而首先计算地方恒星时:地方恒星时=Greenwich恒星时+lon
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
Greenwich恒星时的查找表比较麻烦,可以选择自己计算,计算的方法在论文中描述如下:
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
首先计算UTC时间为0:00的恒星时:
ut是这一日的儒略日小数,也就是上图公式中的ΔT,由于儒略日的起始时间是公元前4713年1月1日中午12点,故而回溯半天(+0.5)再对1取余。
根据论文计算UTC 0:00的恒星时为(单位为秒):

UT = (jd+0.5) mod 1.0
jd_2000 = 2451545.0
t_cen = (jd - UT - jd_2000) / 36525.0
GMST = 24110.54841 + t_cen * (8640184.812866 + t_cen *(0.093104 - t_cen * 6.2E-6))

然后计算ΔT时间的恒星时,并将恒星时化为正值:

omega_e = 1.00273790934; Earth rotations per sidereal day
seconds_per_day = 86400.0
GMST = ( GMST + seconds_per_day * omega_E * UT) MOD seconds_per_day
GMST[where(GMST LT 0.0)] += seconds_per_day

omega_e为地球每恒星日转过的弧度
之后将恒星时转为弧度:

rval = 2.0 * pi * GMST / seconds_per_day

整段计算恒星时的代码如下(此段theta_JD函数参考https://github.com/larrylart/Unimap/blob/db5c5b503d441bb784c7ed551741233ac7350e08/src/sky/sat_code/observe.cpp中的函数ThetaG):

;计算格林威治时间并转为角度
Function thetaG_JD,jd
  COMPILE_OPT idl2

  pi=3.14159265358979323846
  omega_e = 1.00273790934; Earth rotations per sidereal day
  
  UT = (jd+0.5) mod 1.0
  seconds_per_day = 86400.0
  jd_2000 = 2451545.0
  t_cen = (jd - UT - jd_2000) / 36525.0
  GMST = 24110.54841 + t_cen * (8640184.812866 + t_cen *(0.093104 - t_cen * 6.2E-6))
  GMST = ( GMST + seconds_per_day * omega_E * UT) MOD seconds_per_day
  GMST[where(GMST LT 0.0)] += seconds_per_day
  rval = 2.0 * pi * GMST / seconds_per_day
  return,rval
END

将地理经度带入公式,其后即可计算地方恒星时
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)

d2r=0.01745329252;pi/180
theta=(thetaG_JD(jd)+lon*d2r) MOD (2*pi)

有了地方恒星时,则可以将lon,lat,alt转为ECI坐标下的x0,y0,z0:
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)

;经纬度转球面坐标(WGS_72椭球)
Function ll2xyz_ellips,jd,lon,lat,alt
  COMPILE_OPT idl2
  pi=3.14159265358979323846
  d2r=0.01745329252;pi/180
  r2d=57.295779513;180/pi
  Re=6378.14;赤道半径6378.140km(长半轴)

  theta=(thetaG_JD(jd)+lon*d2r) MOD (2*pi)
  ;转换到ECI坐标系下
  f=1.0/298.256;地球扁率
  c=1/sqrt(1+f*(f-2)*sin(lat*d2r)*sin(lat*d2r))
  S=(1-f)*(1-f)*C
  ;计算ECI坐标系下的坐标x,y,z
  x=(Re+alt/1000.0)*C*cos(lat*d2r)*cos(theta)
  y=(Re+alt/1000.0)*C*cos(lat*d2r)*sin(theta)
  z=(Re+alt/1000.0)*S*sin(lat*d2r)
  return,hash('x0',x,'y0',y,'z0',z)
END

上述代码将经纬度坐标转为椭球体上的xyz坐标,也可以将地球视为球体,转为球面的坐标:

;经纬度转球面坐标(球体)
Function ll2xyz_sphere,jd,lon,lat,alt
  COMPILE_OPT idl2
  pi=3.14159265358979323846
  d2r=0.01745329252;pi/180
  r2d=57.295779513;180/pi
  Re=6378.14;赤道半径6378.140km(长半轴)

  theta=(thetaG_JD(jd)+lon*d2r) MOD (2*pi)
  x=Re*cos(lat*d2r)*cos(theta)
  y=Re*cos(lat*d2r)*sin(theta)
  z=Re*sin(lat*d2r)
  return,hash('x0',x,'y0',y,'z0',z)
END

对于ECI坐标计算存疑的,可以带入论文中的一套数据来验证计算出的x0,y0,z0是否正确,作者验证过椭球ECI坐标为正确的。
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
有了观测点的ECI坐标(x0,y0,z0),同时可从HSD数据集中读到Sun’s position(ECI坐标)

;获取Sun's position
point_lun,h8_lun,510
sun_pos=dblarr(3);R8
readu,h8_lun,sun_pos

则可以计算观测点与太阳的向量差[rx,ry,rz]=[xs-x0,ys-y0,zs-z0]
这个向量差为ECI坐标系下的差向量,需要转为测站坐标系(地心坐标系)下的极坐标形式的向量差,就可以得到方位角、高度角(与天顶角互余)。
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
这里θ为天顶角(高度角的余角),φ为方位角
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
计算太阳方位角、天顶角的代码如下:

;太阳天顶角、方位角
Function obslook_solar,jd,sun_pos,lon,lat,alt
  COMPILE_OPT idl2

  pi=3.14159265358979323846
  d2r=0.01745329252;pi/180
  r2d=57.295779513;180/pi
  Re=6378.14;赤道半径6378.140km

  ;计算经纬度对应的ECI坐标
  xyz=ll2xyz_ellips(jd,lon,lat,alt)
  theta=(thetaG_JD(jd)+lon*d2r) MOD (2*pi)
  x0=xyz['x0']
  y0=xyz['y0']
  z0=xyz['z0']
  OBJ_DESTROY,xyz
  ;计算相对距离
  xs=sun_pos[*,*,0]
  ys=sun_pos[*,*,1]
  zs=sun_pos[*,*,2]
  ;卫星的位置是ECI坐标系,定义为[xs,ys,zs],观察者是[x0,y0,z0]
  ;那么距离向量就是[rx,ry,rz]=[xs-x0,ys-y0,zs-z0]
  rx=xs-x0
  ry=ys-y0
  rz=zs-z0 
  ;[rx,ry,rz]是ECI坐标,要生成视角,需要转为地心地平线系统
  ;这个系统的z轴指向天顶,x轴指向南,y轴指向西(地心坐标),地心坐标系随地球旋转
  ls=sin(lat*d2r)*cos(theta)*rx+sin(lat*d2r)*sin(theta)*ry-cos(lat*d2r)*rz;南方,极坐标下:x=r*sin(el)*cos(az)
  lse=-sin(theta)*rx+cos(theta)*ry;西方,极坐标下:y=r*sin(el)*sin(az)
  lz=cos(lat*d2r)*cos(theta)*rx+cos(lat*d2r)*sin(theta)*ry+sin(lat*d2r)*rz;天顶,极坐标下:z=r*cos(el)
  ;az:AzimuthAngle,方位角
  az=atan(-lse/ls);atan(y/x)
  az[where(ls gt 0)] += pi
  az[where(az lt 0)] +=pi*2 
  ;相对距离
  rg=sqrt(rx*rx+ry*ry+rz*rz) 
  ;el:ZenithAngle,天顶角
  el=asin(lz/rg)
  ;弧度转角度
  el=el*r2d
  az=az*r2d
  ;输出SOA,SOZ
  az[where(az GT 180.0)] -= 360.0
  return,hash('SOA',az,'SOZ',90.0-el)
END

对角度的计算验证也可以带入论文中的一组数据,这里作者未带入数据,直接拿结果与NC文件中的角度数据集对比正确。
IDL处理葵花8Himawari-8标准HSD数据——制作大气校正数据集(二)
代码传入数据说明,此文中的imgtime),lon,lat,alt均与矫正裁剪后影像同等大小,为60016001或1200112001大小的数组,sun_pos需要存储三维的太阳坐标(xs,ys,zs)故数组大小为600160013或12001120013
imgtime数组的数值必须带d的double型数,包装成数组时可以采取下面的方法:

obstime=make_array(cols,rows,value=imgtime[0]*1.0d)

这样的话JD的计算就不需要*1.0d

jd = obstime+ 2400000.5

由于HSD每个波段分为10个分块,每个分块的Observation start time和Sun’s position都有变化,为准确的计算太阳角度,需要将10块imgtime和sun_pos读取之后作为此波段的time和sunpos数组,之后与影像一起进行几何校正和裁剪,即可作为角度数据集的输入数组。