Advertisement

GPS秒转北京时间(年月日时分秒)+ gps 周、周内秒转gps时间戳(单位秒) C++ 代码

阅读量:

该文本详细介绍了两种GPS时间转换方法及其对应的RTKlib库实现:
GPS秒转北京时间:

  • 通过gpstime2bjtime函数将GPS系统时间(秒)转换为北京当地时间(年月日时分秒),并解释了算法逻辑。
  • 包括对闰年的处理方法(每四年一次闰年),以及如何通过循环计算当前日期和时间段。
    GPS周及周内秒转GPS时间戳:
  • 通过readGNSSdata和main函数将原始数据中的周内秒转换为总 GPS 时间戳。
  • 展示了如何读取数据并进行时间戳计算,并将其写入输出文件。
    该内容适合对RTK定位系统开发人员参考使用。

目录

一、GPS秒转北京时间(年月日时分秒)- 代码如下:

二、gps 周、周内秒转gps时间戳(单位秒)- 代码如下:

在RTKlib中存在一个 time2epoch 方法, 根据官方文档说明该方法用于将gtype_t类型的结构转换为日/时格式的时间戳.

一、GPS秒转北京时间(年月日时分秒)- 代码如下:

复制代码
 void gpstime2bjtime(double gps_time, double *ep)

    
 {
    
    // 分离整数和小数
    
    int gps_t; 
    
    double gps_sec;
    
    gps_t  = (int)gps_time;
    
    gps_sec = gps_time - gps_t;
    
     
    
     
    
    const int mday[] = { /* # of days in a month */
    
         31,28,31,30,31,30,31,31,30,31,30,31,31,28,31,30,31,30,31,31,30,31,30,31,
    
         31,29,31,30,31,30,31,31,30,31,30,31,31,28,31,30,31,30,31,31,30,31,30,31};
    
    int days, sec, mon, day;
    
     
    
    /* leap year if year%4==0 in 1901-2099 */
    
    days = (int)(gps_t / 86400);
    
    sec = (int)(gps_t - (time_t)days*86400) + 8*60*60 - 18;  // UTC转北京时间:北京多了8个时区间( 8*60*60 ),闰了18秒     
    
    
    
    for (day=days%1461, mon=0; mon<48; mon++)    
    
    {
    
       if (day >= mday[mon]) day -= mday[mon];
    
       else break;
    
    }
    
       
    
    ep[0] = 1970 + days/1461*4 + mon/12;
    
    ep[1] = mon%12 + 1;
    
    ep[2] = day + 1;
    
    ep[3] = sec / 3600;   
    
    ep[4] = sec%3600 / 60;
    
    ep[5] = sec%60 + gps_sec;      
    
 }

首先, 它构建了一个名为mday的数组, 具体来说共有48个元素, 每个元素代表连续四年的每个月份, 从起始时间点1970年开始计算(即1970-1973)。这里为何设置为四个月呢? 在判断时需要考虑闰年 的影响: 在非世纪年的格里高利历中能被4整除的年份为闰年, 而在世纪year 中则需满足既能被4整除又能被400整除的条件才是leap year. 以时间为背景来看, 从1970年至2023年间仅有一个世纪year 即2000 year , 它同样符合leap year 的标准. 因此, 在判断时我们只需关注是否能被4整除即可.

自1970年起,在mday数组中对应的第三个位置上记录的第一个闰年的二月具有29天这一特征后,则可推断每四年就是一个完整的闰年周期开始。为此定义了四个整型变量days、sec、mon、day:

复制代码
>     days=(int)(t.time/86400);
>

days是天数,即从GPS秒除86400(即一天的24h)取整,即为天数。

复制代码
>     sec=(int)(t.time-(time_t)days*86400);
>

sec是秒数,即天内秒。

复制代码
>       1. for (day=days%1461,mon=0;mon<48;mon++) {

>  
>       2.         if (day>=mday[mon]) day-=mday[mon]; else break;
>  
>       3.     }
>  
>  
>

mon代表月份数值,在此情境中取值范围为0至47。day为模1461运算后的余数值。值得注意的是,在本系统中,默认情况下将该余数值与mday数组中的各个月份天数进行对比操作。具体来说,则是将当前余数值与mday数组中每个月份对应的天数值依次进行比较:若当前余数值大于或等于该月的实际天数,则减去该月的具体天数,并转而与下一个月进行同样的比较操作;如此反复直至找到一个满足条件的月份(即当前余数值小于当月实际天数),此时确定的时间段即为所求的具体月份。

复制代码
>       1. ep[0]=1970+days/1461*4+mon/12; //年数

>  
>       2. ep[1]=mon%12+1; //月
>  
>       3. ep[2]=day+1;//日
>  
>       4. ep[3]=sec/3600; //时
>  
>       5. ep[4]=sec%3600/60; //分
>  
>       6. ep[5]=sec%60+t.sec;//秒
>  
>  
>

mon由于其取值范围为0至47,在进行模12运算时需要加1。
day的计算基于days这一整天数结果,在这种情况下相当于往后推一天的时间段。

二、gps 周、周内秒转gps时间戳(单位秒)- 代码如下:

复制代码
>       1. #include <iostream>

>  
>       2. #include <iomanip>
>  
>       3. #include <fstream>
>  
>       4. #include <math.h>
>  
>       5. #include <string>
>  
>       6. #include<sstream>
>  
>       7. #include <stdlib.h>
>  
>       8.  
>  
>       9.  
>  
>       10.  
>  
>       11. using namespace std;  
>  
>       12.  
>  
>       13.  
>  
>       14. // 输入文件路径
>  
>       15. std::string P_trueweek = "/home/jht/VIns_Code/GNSS_IMU_Cam_EKFTC_me_Beihang/output/P_true.txt";
>  
>       16.  
>  
>       17. // 输出文件路径 (ecef 坐标下的位置)
>  
>       18. FILE *P_tru_sec = fopen("/home/jht/VIns_Code/GNSS_IMU_Cam_EKFTC_me_Beihang/output/P_true_sec.txt", "w");  
>  
>       19.  
>  
>       20.  
>  
>       21.  
>  
>       22. // 读数据函数
>  
>       23. std::ifstream  csv_truefile(P_trueweek);  
>  
>       24. std::string line_llh;
>  
>       25.  
>  
>       26. void read_GNSS_data(const std::string &line, double &time,double XYZ[3])
>  
>       27. {
>  
>       28.    std::stringstream  lineStream(line);
>  
>       29.  
>  
>       30.    std::string   dataRecord[4];  
>  
>       31.    std::getline(lineStream, dataRecord[0], ',');  // 这里的数据间是 逗号,用','
>  
>       32.    std::getline(lineStream, dataRecord[1], ',');
>  
>       33.    std::getline(lineStream, dataRecord[2], ',');
>  
>       34.    std::getline(lineStream, dataRecord[3], ',');
>  
>       35.  
>  
>       36.  
>  
>       37.    time = std::stod(dataRecord[0]); //时间:s;
>  
>       38.  
>  
>       39.    XYZ[0] =  std::stod(dataRecord[1]);  //原始数据是增量信息
>  
>       40.    XYZ[1] =  std::stod(dataRecord[2]);  
>  
>       41.    XYZ[2] =  std::stod(dataRecord[3]);
>  
>       42. }
>  
>       43.  
>  
>       44.  
>  
>       45.  
>  
>       46.  
>  
>       47.  
>  
>       48. int main()
>  
>       49. {
>  
>       50.    double XYZ[3];
>  
>       51.    const int week = 2255; // 不同的数据,这个周要变
>  
>       52.    double timeweeks; // 周内秒的时间
>  
>       53.    double timesec;
>  
>       54.  
>  
>       55.  
>  
>       56.    while(1)
>  
>       57.    {
>  
>       58.       std::getline(csv_truefile, line_llh);
>  
>       59.       read_GNSS_data(line_llh,timeweeks,XYZ);  
>  
>       60.  
>  
>       61.       timesec = week*7*24*3600 + timeweeks + 315964800.0;
>  
>       62.  
>  
>       63.       fprintf(P_tru_sec, "%.5f,%.3f,%.3f,%.3f\n",timesec,XYZ[0],XYZ[1],XYZ[2]);
>  
>       64.    }
>  
>       65.  
>  
>       66.     return 0;
>  
>       67. }
>  
>       68.  
>  
>       69.  
>  
>       70.  
>  
>  
>

感谢

GPS周-周内秒、日历时、UTC转换和逆转换

全部评论 (0)

还没有任何评论哟~