当前位置: 首页 > 工具软件 > Pride > 使用案例 >

Pride_pppar源码解析(一)

仲霍英
2023-12-01

经过多天的思考,终于决定把看pride代码的心得写在博客里面了,有很多不太懂的地方也请大家一起探讨。

pride_pppar.sh

pirde_pppar.sh是pride软件的核心执行脚本,其自动的对数据进行处理和解算。
使用方式:

pride_pppar config_template YYYYMMDD YYYYMMDD y/n

其中,config_template是配置文件;第一个YYYYMMDD是处理数据的起始时间;第二个YYYYMMDD是处理数据的结束时间;最后y/n是是否固定模糊度。

vim pride_pppar.sh

打开pride_pppar.sh第一个函数就是该脚本的主程序:

main()
{
     CheckCmdArgs "$@" || exit 1
     CheckExecutables || exit 1

     local ctrl_file="$1"
     local ymd_start=(${2:0:4} ${2:4:2} ${2:6:2})
     local ymd_end=(${3:0:4} ${3:4:2} ${3:6:2})
     local AR="${4:0:1}"
 
     ctrl_file=$(readlink -f "$ctrl_file") # convert to absolute path
 
     # Output processing infomation
     echo -e "$MSGINF Processing date range: ${ymd_start[*]}  <==>  ${ymd_end[*]}"
     echo -e "$MSGINF Control file: ${ctrl_file}"
     echo -e "$MSGINF AR switch: ${AR}"
 
     # Processing day-by-day
     readonly local mjd_start=$(ymd2mjd ${ymd_start[*]})
     readonly local mjd_end=$(ymd2mjd ${ymd_end[*]})
     local work_dir=$(pwd) ydoy
     for mjd in $(seq $mjd_start $mjd_end)
     do
         cd "${work_dir}"
         ydoy=($(mjd2ydoy ${mjd}))
         mkdir -p ./${ydoy[0]}/${ydoy[1]}
         cd ./${ydoy[0]}/${ydoy[1]}
         if [ $? -eq 0 ]; then
             ProcessSingleDay $mjd "$ctrl_file" ${AR} || echo -e "$MSGWAR ${ydoy[*]} processing failed"
         else
             echo -e "$MSGERR no such directory: ${work_dir}/$year/$doy"
             echo -e "$MSGWAR skip processing: $year $doy"
         fi
     done
}

主程序前两行检查分别调用CheckArgsCheckExecutables函数检查了pride_pppar 后面跟的参数的个数是否满足要求以及是否包含pride执行所需的一些执行程序,例如lsqget_argsarsig等等,这些执行程序都是pride软件自带的可执行程序,当然还会检查一些其他linux脚本处理程序,如wgetreadlink

然后就是一系列的基本操作,如将pride_pppar后面参数读入并赋值给本地变量;将配置文件转换为绝对路径;输出处理过程的信息等。

然后在起始时间和结束时间之间按天进行循环处理。在处理的时候会创建一个新的二重文件夹,以year/ydoy的形式将处理所需文件、结果文件输出到对应的ydoy文件夹中。调用的函数为ProcessSingleDay

ProcessSingleDay的内容如下:

ProcessSingleDay() { # purpose: process data of single day
                    # usage  : ProcessSingleDay mjd ctrl_file AR(y/n)
     local mjd=$1
     local ctrl_file="$2"
     local AR=$3
 
     local ydoy=($(mjd2ydoy $mjd))
     local year=${ydoy[0]}
     local doy=${ydoy[1]}
     local ymd=($(ydoy2ymd ${ydoy[*]}))
     local mon=${ymd[1]}
     local day=${ymd[2]}
     unset ydoy ymd
 
     echo -e "$MSGSTA ProcessSingleDay $year $doy..."

     # Copy a local ctrl_file
     cp -f "$ctrl_file" . || return 1
     ctrl_file=$(basename "$ctrl_file")

     # Create ctrl_file for current day
     sed -i -e "/^Session time/s/-YYYY-/$year/g" \
            -e "/^Session time/s/-MM-/$mon/g" \
            -e "/^Session time/s/-DD-/$day/g" "$ctrl_file"
     sed -i "/Rinex directory/s/-YEAR-/$year/g; s/-DOY-/$doy/g" "$ctrl_file"

    # Prepare products & tables
     local table_dir=$(get_ctrl "$ctrl_file" "Table directory")
     local product_dir=$(get_ctrl "$ctrl_file" "Sp3 directory")
     CopyTables "$table_dir" $mjd || return 1
     PrepareProducts $mjd "$product_dir" ${ctrl_file} ${AR}
     if [ $? -ne 0 ]; then
         echo -e "$MSGERR PrepareProducts failed"
         return 1
     fi
 
     # Download rinexnav file
     local rinex_dir=$(get_ctrl "$ctrl_file" "Rinex directory")
     local rinexnav="brdc${doy}0.${year:2:2}n"
     local urlnav="ftp://igs.gnsswhu.cn/pub/gps/data/daily/${year}/$doy/${year:2:2}n/${rinexnav}.Z"
     if [ ! -f "${rinex_dir}/${rinexnav}" ]; then
         echo -e "$MSGSTA Downloading ${rinexnav}..."
         WgetDownload "$urlnav"
         if [ $? -eq 0 ]; then
             uncompress -f ${rinexnav}.Z && mv ${rinexnav} ${rinex_dir}
             [ -f ${rinex_dir}/${rinexnav} ] && echo -e "$MSGSTA Downloading ${rinexnav} done" || return 1
         else
             echo -e "$MSGERR download rinexnav failed: ${rinex_dir}/${rinexnav}"
             return 1
        fi
    fi

     sites=($(awk '/^ [0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z][0-9a-zA-Z] [KS]/ {print $1}' "$ctrl_file"))
    [ ${#sites[@]} -eq 0 ] && echo -e "$MSGWAR ${year} ${doy}: no site to be processed" && return 1
     for site in ${sites[*]}
     do
         ProcessSingleSite "$site" $year $doy "${ctrl_file}" $AR
         if [ $? -ne 0 ]; then
             echo -e "$MSGWAR ProcessSingleDay: skip processing $year $doy $site"
            local tp types=(kin pos rck ztd htg amb res stt con)
             for tp in ${types[*]}
             do
                rm -f ${tp}_${year}${doy}
            done
        fi
     done
     rm -f ${ctrl_file}
     echo -e "$MSGSTA ProcessSingleDay $year $doy done"
 }

该函数是内嵌在pride_pppar.sh中的处理单天GPS数据的函数。处理流程如下:

  1. 首先将输入参数赋值给本地变量
  2. 复制到本地配置文件
  3. 对该天创建一个专属配置文件(基于大的config_template)
  4. 将table文件夹和产品文件夹的路径从配置文件中读取出来
  5. 调用PrepareProducts准备该天处理所需的产品,如clk、fcb、dcb、sp3等,若没有,就从pride默认的网站下载。
  6. 准备观测O文件和广播星历文件,若没有则通过WgetDownload函数从默认的网站下载。
  7. 从配置文件中读取要处理的sites列表,并对列表中的测站进行循环,按站进行单站PPP。
  8. 调用ProcessSingleSite函数处理单站

ProcessSingleSite函数的处理流程如下:

  1. 首先将输入参数赋值给本地变量
  2. 检查观测文件是否存在,不存在则报错
  3. 计算测站的初始坐标,用于lsq。如果sit.xyz中不包含初始坐标,则调用ComputeInitialPos函数计算初始坐标,该函数调用了rnx2rtkp(rtklib)脚本计算测站初始位置。
  4. 数据预处理,调用tedit程序,主要包括周跳检测等数据预处理过程。并将处理后的观测值生成为rhd健康文件
  5. 创建每个测站的专属配置文件
  6. 迭代调用lsq和redig程序对数据进行清洗,主要针对lsq后的残差。
  7. 最终处理,调用lsq进行最后的最小二乘。倘若需要固定模糊度,则调用arsig进行模糊度固定,固定后再进行lsq计算出固定解。
  8. 对生成的结果文件重命名。除咯结束

config_template

该文件是pride_pppar的配置文件,包括PPP处理策略以及解算测站等等信息。其内容非常关键。

Interval = 30 
#Rinex数据的处理间隔
Session time = -YYYY- -MM- -DD- 00 00 00 86360
# -YYYY- RINEX数据的年份, -MM- 和 –DD- 代表月和天。 实际处理的时候 –YYYY-, -MM- and –DD- 可以不用更改,‘pride_pppar’可以自动识别并自动填写, 下面的 ‘-YEAR-‘, ‘-DOY-’ 也是这样。
Rinex directory = /home/username/path-to-data/-YEAR-/-DOY-/ 
# RIinex文件夹的绝对路径,其中的username和path-to-data需要自行更改
Sp3 directory   = /home/username/path-to-product/product/
# SP3文件的绝对路径,同上更改
Table directory = /home/username/path-to-table/table/
# Table文件夹的绝对路径


Remove bias = YES
# 是否使用fcb移除相位偏差,倘若是LAMBDA方法则不需要
ZTD model  = PWC:60
# 天顶对流层延迟模型,采用分段常数,60:1小时
HTG model        = PWC:720
# 对流层水平梯度:分段常数

Ambiguity fixing    = FIX 
# 模糊度固定与否
Common observing    = 600
# 最小共同观测时间,用于模糊度解算时检验有效时间是否大于此
Cutoff elevation    =n 15
# 模糊度固定的截止高度角
Widelane decision   = 0.20 0.15 1000.
# 锥函数的阈值偏差(=0.4 in Dong和Bock;/ 锥形函数的阈值σ(=0.33 in Dong和Bock;/ 判定函数的错误率
Narrowlane decision = 0.15 0.15 1000.
# 同上
Critical search     = 2 4 1.8 3.0
# 最大删除模糊度/最小保留模糊度/卡方检验统计量/比值试验临界值

## Satellite list
+GPS satellites
 *PN
  01
  02
  03
  04
  05
  06
  07
  08
  09
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32                                                                                                                                 
 -GPS satellite
#可以通过在卫星号前面加‘#’来排除该卫星

# Station list
+Station used
*NAME TP MAP CLKm EV ZTDm PoDm HTGm PoDm RAGm PHSc PoXEm PoYNm PoZHm
algo S  GMF 9000  7 0.20 .020 .005 .002 3.00 .006 10.00 10.00 10.00
zimm S  GMF 9000  7 0.20 .020 .005 .002 3.00 .006 10.00 10.00 10.00
-Station used 

# 可以自行添加测站,按照上面‘*’后面的格式
#TP:【K/S】指代动态或者静态模式
# MAP:对流层投影函数(如:GMF,VM1,NMF)
# CLKm: lsq中的初始接收机钟经度/m
# EV: 截至高度角/度
# ZTDm: 先验对流层延迟模型经度/m
# PoDm:分段天顶对流层延迟参数的푚/√h过程噪声
# HTGm: 以米为单位的先验水平对流层梯度值精度
#PoDm: 分段天顶水平对流层梯度参数的푚/√h过程噪声
# RAGm: lsq中伪距观测值的噪声/m
# PHSc: lsq中相位观测值的噪声/周
#PoXE PoYN PoZH : 初始坐标(XYZ/ENU)的先验经度/m

pride_pppar的使用

  1. 在工作文件夹中创建data文件夹,data文件夹下创建year/doy,并将相应的测站o文件和广播星历放在相应的year/doy文件夹下。
  2. 复制pride软件包中example文件夹下的config_template文件到工作目录,并修改其中的部分内容,必须修改的内容:观测值绝对路径、tables文件夹绝对路径,处理测站。
  3. 复制pride软件包中tables文件夹到工作文件夹下。修改其中的leap.sec文件和jpleph_de04(此文件有效期到2019年12月31日)。
  4. 修改pride软件包中lib/rdsp3.f90中第71行为:
if (line(1:2).ne.'#c'.and.line(1:2).ne.'#d') cycle
  1. 执行pride_pppar config_template YYYYMMDD YYYYMMDD y/n即可
 类似资料: