2021-02-02 GNSS之Rtklib代码调试(一)、参数设置及文件读入

1 篇文章 1 订阅
1 篇文章 0 订阅

GNSS之Rtklib代码调试(一)、参数设置及文件读入

1.前言

作为一名GNSS专业的准研究生,趁寒假的时间准备自己对自己学过的东西做一下简单的梳理。
但是了解的越多越发现自己在本科学的东西根本就不够用。
所以,希望自己做梳理的同时能够帮助还未入门但准备学习GNSS专业的小白们。
让我们一起努力吧!

本篇文章的主要内容是在下载完Github上的开源代码并搭建好环境之后,如何进行同GUI(图形用户界面)功能一样的数据处理操作。
本篇内容会以定位后处理(即postpos)的静态(static)PPP(精密单点定位)为例进行讲解
目前,只是做一个流程的大致介绍,之后的数据处理过程会结合专业知识进行详细介绍。
如果还没有进行相应软件下载以及还未进行环境配置的可看2中的详细内容。

2.环境准备

(1). Visual Studio 2019

下载网址:https://visualstudio.microsoft.com/zh-hans/vs/

链接:VS2019下载链接.
(注:VS的其他版本如2010,2017或者其他的IDE也可,只要能够编译C就可以,只是VS用习惯了)

(2). Rtklib 2.4.3

下载网址:http://www.rtklib.com/

链接:Rtklib 2.4.3下载链接.
(注:建议大家下载2.4.2p13版本,2020年最新的版本有一些bug,我还没有调试通过,注意下载右侧的,左侧是可运行的二进制文件,即.exe)
rtklib官网截图

(3). 创建解决方案

其他人有写,自己看。

链接:解决方案创建1.
---------解决方案创建2.

(4). 传入文件配置

在这里插入图片描述
各类文件的下载地址可以看这个链接:
网址:http://www.xsensing.cn/article/767472814310555648
链接:文件下载说明.
(注:上面示例中的sp3和clk文件是SHAO的,链接可能比较难找,大家可以直接从武汉大学IGS数据处理中心下载武汉大学的处理结果)

3.1程序函数调用结构

main
postInit
read_fildir
substrend
addchar

3.2程序函数调用顺序

通过main函数把文件夹目录传入postInit函数,
之后通过调用read_fildir将文件夹中的所有文件名称读入一个字符串数组(就是一个char类型的二维数组),
之后通过substrend函数读取每个文件的后缀来判断文件类型,并读入相应的参数中,
然后通过addchar新建一个输出结果文件的文件名(实质是根据观测值文件名进行修改后缀所得)

4.分段代码

(1).引入头文件

#include <stdio.h>
#include <assert.h>
#include <iostream>
#include <thread>
#include "dirent.h"
#include <string.h>
#include <stdlib.h>
#include "src/rtklib.h"

(2).main函数

书接上回~ 2中的(3)完成之后,需要在解决方案的源文件中添加一份新建项**main.c**
作为程序的入口(main.cpp也可)
using namespace std;

int main(void) 
{
	/* 文件夹路径输入 */
	char filePath1[] = "C:/Users/Desktop/test/";
	/* 以“后处理postpos”为例 */
	postInit(filePath1);
	return 0;
}

(3).postInit函数

/* postInit ---------------------------------------------------------
 * 将各类文件导入数据处理程序
 * args   : char* filepath		I	文件夹路径
 *		   
 * return : NULL
 * notes  : NULL
 *-------------------------------------------------------------------*/
I表示输入,O表示输出

(注:该函数在使用前应预先定义或声明函数read_filedir、substrend)

extern void postInit(char* filepath)
{
	gtime_t ts = { 0 }, te = { 0 };
	double ti = 0.0, tu = 0.0;
	int i, n = 0, stat;
	char* rov, * base, * p, * q, * r;
	char file[FILENUM][FILESIZE] = { "" };
	char *infile[FILENUM], outfile[FILESIZE];
	char proname[FILESIZE];

	read_filedir(filepath, file);
	// 处理参数
	prcopt_t prcopt = {
		PMODE_PPP_STATIC,0,2,SYS_ALL,		/* mode,soltype,nf,navsys */
		15.0 * D2R,{{0,0}},					/* elmin,snrmask */
		EPHOPT_PREC,1,1,1,                  /* sateph,modear,glomodear,bdsmodear */
		5,0,10,1,							/* maxout,minlock,minfix,armaxiter */
		IONOOPT_IFLC,TROPOPT_ESTG,0,2,      /* estion,esttrop,dynamics,tidecorr */
		1,0,0,0,0,							/* niter,codesmooth,intpref,sbascorr,sbassatsel */
		0,0,								/* rovpos,refpos */
		{100.0,100.0},						/* eratio[] */
		{100.0,0.003,0.003,0.0,1.0},		/* err[] */
		{30.0,0.03,0.3},					/* std[] */
		{1E-4,1E-3,1E-4,1E-1,1E-2,0.0},		/* prn[] */
		5E-12,								/* sclkstab */
		{3.0,0.9999,0.25,0.1,0.05},			/* thresar */
		0.0,0.0,0.05,						/* elmaskar,almaskhold,thresslip */
		30.0,30.0,30.0,						/* maxtdif,maxinno,maxgdop */
		{0},{0},{0},						/* baseline,ru,rb */
		{"*",""},							/* anttype */ //added202012191019withPostpos929
		{{0}},{{0}},{0}						/* antdel,pcv,exsats */
	};
	// 输出参数
	solopt_t solopt = {
		SOLF_XYZ,TIMES_GPST,1,3,    /* posf,times,timef,timeu */
		1,1,1,0,0,0,0,              /* degf,outhead,outopt,outvel,datum,height,geoid */
		0,2,0,                      /* solstatic,sstat,trace */
		{0.0,0.0},                  /* nmeaintv */
		" ",""                      /* separator/program name */
	};
	// 文件参数
#pragma region fileOpt
	filopt_t filopt = { "" };
	for (int i = 0; i < FILENUM; i++)
	{
		char* substr = substrend(*(file + i), 4);
		char* substr2 = substrend(*(file + i), 1);
		if (strcmp(substr, ".atx") == 0)
		{
			sprintf(filopt.satantp, *(file + i)); /* satellite antenna parameters file */
			sprintf(filopt.rcvantp, *(file + i)); /* receiver antenna parameters file */
		}
		if (strcmp(substr, ".snx") == 0)
			sprintf(filopt.stapos, *(file + i)); /* station positions file */
		if (strcmp(substr, ".BSX") == 0)
			sprintf(filopt.dcb, *(file + i)); /* dcb data file */
		if (strcmp(substr, ".erp") == 0)
			sprintf(filopt.eop, *(file + i)); /* eop data file */
		if (strcmp(substr, ".blq") == 0)
			sprintf(filopt.blq, *(file + i)); /* ocean tide loading blq file */
		if (strcmp(substr2, "o") == 0 || strcmp(substr2, "O") == 0)
		{
			addchar(*(file + i), outfile, "pos");
			strcpy(proname, file[i]);
		}
		infile[i] = *(file + i);
		free(substr);
		free(substr2);
		n += 1;
	}
#pragma endregion

	rov = (char*)"";
	base = (char*)"";
	//trace file output -----------------------------------
	if (solopt.trace != 0)
	{
#ifndef  TRACE
#define TRACE
#endif
	}
	stat = postpos(ts, te, 0, 0, &prcopt, &solopt, &filopt, infile, n, outfile, rov, base);
	printf("%s has done.\n", proname);
}

(4-1).read_filedir函数

/* read_filedir -----------------------------------------------------
 * 根据文件夹所在的路径filePath,将文件夹下的所有数据文件名读入到file[][]中
 * args   : char* filepath		I	文件夹路径
 *		    char** result		IO	文件夹内文件名集合
 * return : NULL
 * notes  : FILENUM是文件夹内文件的数量,FILESIZE是文件夹内文件名的最大的长度
 *-------------------------------------------------------------------*/
#define FILESIZE	100
#define FILENUM		9

static void read_filedir(char* filePath, char file[FILENUM][FILESIZE])
{
	int i = 0, j = 0;
	int filesize = 0;
	DIR* dir = NULL;
	struct dirent* entry;
	char temp[FILESIZE];

	if ((dir = opendir(filePath)) == NULL)
	{
		printf("opendir failed!");
	}
	else
	{
		while (entry = readdir(dir))
		{
			if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
				continue;
			strcpy(temp, filePath);
			strcat(temp, entry->d_name);
			strcpy(file[i], temp);
			i++;
			// printf("filename%d = %s\n", i, entry->d_name);
		}
	}
}

(4-2).substrend函数

/* substrend -----------------------------------------------------
 * 读取字符串str的后n位并返回
 * args   : char* str			I	原字符串
 *		    int n				I	字符串的后n位
 * return : char* substr		O	原字符串的后n个字符
 * notes  : 
 *-------------------------------------------------------------------*/
static char* substrend(const char* str, int n)
{
	int k = 0;
	char* substr = (char*)malloc(n + 1);
	int length = strlen(str);
	if (n >= length)
	{
		substr = str;
		return substr;
	}
	for (int i = length - n; i < length; i++)
	{
		substr[k] = str[i];
		k++;
	}
	substr[k] = '\0';
	return substr;
}

(4-3).addchar函数

static void addchar(const char* str, char * aim, char* add)
{
	int count = strlen(str);
	char temp[FILESIZE];
	strcpy(temp, str);

	*(temp + count - 1) = '\0';
	strcat(temp, add);
	strcpy(aim, temp);
}

(PS:这个函数写的属实是,哈哈哈哈哈哈哈哈哈)

  • 5
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
实现基于北斗BDS-3的星历文件gnss伪距单点定位程序,你需要掌握以下几个方面的知识: 1. 北斗BDS-3卫星系统的基本原理和星历数据格式; 2. gnss伪距单点定位的基本原理和算法; 3. 编程语言和开发环境。 下面是一个基于Python语言的北斗BDS-3星历文件gnss伪距单点定位程序示例: ```python import numpy as np # 读取北斗BDS-3星历文件 def read_bds3_nav_file(file_path): with open(file_path, 'r') as f: lines = f.readlines() nav_data = {} for i in range(0, len(lines), 8): prn = int(lines[i][2:4]) nav_data[prn] = {} nav_data[prn]['toc'] = float(lines[i][4:23]) nav_data[prn]['af0'] = float(lines[i][23:42]) nav_data[prn]['af1'] = float(lines[i][42:61]) nav_data[prn]['af2'] = float(lines[i][61:80]) nav_data[prn]['iode'] = int(lines[i+1][4:23]) nav_data[prn]['crs'] = float(lines[i+1][23:42]) nav_data[prn]['deltan'] = float(lines[i+1][42:61]) nav_data[prn]['m0'] = float(lines[i+1][61:80]) nav_data[prn]['cuc'] = float(lines[i+2][4:23]) nav_data[prn]['ecc'] = float(lines[i+2][23:42]) nav_data[prn]['cus'] = float(lines[i+2][42:61]) nav_data[prn]['sqrtA'] = float(lines[i+2][61:80]) nav_data[prn]['toe'] = float(lines[i+3][4:23]) nav_data[prn]['cic'] = float(lines[i+3][23:42]) nav_data[prn]['omega0'] = float(lines[i+3][42:61]) nav_data[prn]['cis'] = float(lines[i+3][61:80]) nav_data[prn]['i0'] = float(lines[i+4][4:23]) nav_data[prn]['crc'] = float(lines[i+4][23:42]) nav_data[prn]['omega'] = float(lines[i+4][42:61]) nav_data[prn]['omegadot'] = float(lines[i+4][61:80]) nav_data[prn]['idot'] = float(lines[i+5][4:23]) nav_data[prn]['l2code'] = int(lines[i+5][23:42]) nav_data[prn]['week'] = int(lines[i+5][42:61]) nav_data[prn]['l2pflag'] = int(lines[i+5][61:80]) nav_data[prn]['accuracy'] = int(lines[i+6][4:23]) nav_data[prn]['health'] = int(lines[i+6][23:42]) nav_data[prn]['tgd1'] = float(lines[i+6][42:61]) nav_data[prn]['tgd2'] = float(lines[i+6][61:80]) nav_data[prn]['iodc'] = int(lines[i+7][4:23]) nav_data[prn]['transmit_time'] = float(lines[i+7][23:42]) nav_data[prn]['fit_interval'] = int(lines[i+7][42:61]) return nav_data # 计算卫星位置 def calculate_satellite_position(nav_data, prn, transmit_time): t = transmit_time - nav_data[prn]['toe'] a = nav_data[prn]['sqrtA'] ** 2 n0 = 7.2921151467e-5 n = n0 + nav_data[prn]['deltan'] M = nav_data[prn]['m0'] + n * t E = M for i in range(10): E = M + nav_data[prn]['ecc'] * np.sin(E) v = np.arctan2(np.sqrt(1 - nav_data[prn]['ecc'] ** 2) * np.sin(E), np.cos(E) - nav_data[prn]['ecc']) phi = v + nav_data[prn]['omega'] u = phi + nav_data[prn]['cus'] * np.sin(2 * phi) + nav_data[prn]['cuc'] * np.cos(2 * phi) r = a * (1 - nav_data[prn]['ecc'] * np.cos(E)) + nav_data[prn]['crc'] * np.cos(2 * phi) + nav_data[prn]['crs'] * np.sin(2 * phi) i = nav_data[prn]['i0'] + nav_data[prn]['idot'] * t + nav_data[prn]['cis'] * np.sin(2 * phi) + nav_data[prn]['cic'] * np.cos(2 * phi) x = r * np.cos(u) y = r * np.sin(u) z = 0 xe = x * np.cos(n * t) - y * np.cos(i) * np.sin(n * t) ye = x * np.sin(n * t) + y * np.cos(i) * np.cos(n * t) ze = y * np.sin(i) return np.array([xe, ye, ze]) # 计算接收机位置 def calculate_receiver_position(satellite_positions, pseudoranges): A = np.zeros((len(satellite_positions) - 1, 4)) b = np.zeros((len(satellite_positions) - 1, 1)) for i in range(1, len(satellite_positions)): A[i-1, :] = np.append(satellite_positions[i, :] - satellite_positions[0, :], 1) b[i-1, 0] = pseudoranges[i] - pseudoranges[0] + np.dot(satellite_positions[0, :], satellite_positions[0, :]) - np.dot(satellite_positions[i, :], satellite_positions[i, :]) x = np.linalg.lstsq(A, b, rcond=None)[0] receiver_position = x[0:3, 0] receiver_clock_error = x[3, 0] return receiver_position, receiver_clock_error # 主程序 if __name__ == '__main__': # 读取北斗BDS-3星历文件 nav_data = read_bds3_nav_file('bds3_nav.txt') # 读取伪距数据 pseudoranges = [22326531.20, 21570022.07, 24881521.91, 23717318.44, 22394411.94] # 计算卫星位置 satellite_positions = np.zeros((len(pseudoranges), 3)) transmit_time = nav_data[1]['transmit_time'] for i in range(len(pseudoranges)): satellite_positions[i, :] = calculate_satellite_position(nav_data, i+1, transmit_time) # 计算接收机位置 receiver_position, receiver_clock_error = calculate_receiver_position(satellite_positions, pseudoranges) # 输出结果 print('Receiver position: x=%f, y=%f, z=%f' % (receiver_position[0], receiver_position[1], receiver_position[2])) print('Receiver clock error: %f' % receiver_clock_error) ``` 这段代码实现了北斗BDS-3星历文件的读取、卫星位置计算、接收机位置计算和结果输出等功能。其中,read_bds3_nav_file函数用于读取星历文件,calculate_satellite_position函数用于计算卫星位置,calculate_receiver_position函数用于计算接收机位置。主程序中给出了一个示例,包括伪距数据和结果输出。需要注意的是,这段代码中只考虑了单频伪距测量,因此计算出的接收机位置精度较低,如果需要提高精度需要考虑多频伪距测量、载波相位测量等因素。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值