C++ - ISS 位置・速度(BLH(WGS84)座標)一覧 JSON 生成!

Updated:


前回、 C++ で NASA 提供の最新の TLE(2行軌道要素形式)から任意の時刻(JST; 日本標準時)の ISS の位置・速度(WGS84 座標; いわゆる、緯度・経度・高度(BLH)という座標)を、 SGP4 アルゴリズムを用いて計算しました。

今回は、応用として、10秒間隔で2日分の JSON データを生成します。

0. 前提条件

  • Debian GNU/Linux 10.10 (64bit) での作業を想定。
  • GCC 10.2.0 (G++ 10.2.0) (C++17) でのコンパイル&ビルドを想定。
  • ここでは、各種座標系、 SGP4 アルゴリズム(Simplified General Perturbations Satellite Orbit Model 4; NASA, NORAD が使用している、近地球域の衛星の軌道計算用で、周回周期225分未満の衛星に使用すべきアルゴリズム)等についての詳細は説明しない。(各種座標系については次項で概要のみ説明)

1. 各種座標系について(概要)

  • TEME 座標とは「真赤道面平均春分点」のことで、 “True Equator, Mean Equinox” の略。
  • PEF 座標とは「擬地球固定座標系」のことで、 “Pseudo Earth Fixed” の略。
  • ECEF 座標とは「地球中心・地球固定直交座標系」のことで、 “Earth Centered, Earth Fixed” の略。
  • WGS84 座標とは「世界測地系1984」のことで、 “World Geodetic System 1984” の略。 GPS で使用する測地系。

2. C++ ソースコードの作成

ここでは、実行部分のみ掲載。(全てのコードは GitHub リポジトリとして公開している)

File: iss_sgp4_json.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/***********************************************************
  指定日時から48時間分の ISS 位置/速度を計算し、 JSON 出力
  : 但し、座標系は BLH(Beta(Latitude), Lambda(Longitude), Height)

    DATE        AUTHOR       VERSION
    2021.06.10  mk-mode.com  1.00 新規作成

  Copyright(C) 2021 mk-mode.com All Rights Reserved.
  ---
  引数 : JST(日本標準時)
           書式:最大23桁の数字
                 (先頭から、西暦年(4), 月(2), 日(2), 時(2), 分(2), 秒(2),
                             1秒未満(9)(小数点以下9桁(ナノ秒)まで))
                 無指定なら現在(システム日時)と判断。
  ---
  MEMO:
    TEME: True Equator, Mean Equinox; 真赤道面平均春分点
     PEF: Pseudo Earth Fixed; 擬地球固定座標系
    ECEF: Earth Centered, Earth Fixed; 地球中心・地球固定直交座標系
***********************************************************/
#include "blh.hpp"
#include "eop.hpp"
#include "sgp4.hpp"
#include "time.hpp"
#include "tle.hpp"

#include <cstdlib>   // for EXIT_XXXX
#include <ctime>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

namespace iss_sgp4_json {

static constexpr char         kFOut[] = "iss.json";  // 書き込みファイル
static constexpr unsigned int kDay    = 2;           // 計算日数(日)
static constexpr unsigned int kSec    = 10;          // 計算間隔(秒)
static constexpr double       kSecD   = 86400.0;     // 秒数(1日分)
}

int main(int argc, char* argv[]) {
  namespace ns = iss_sgp4_json;
  std::string     f(ns::kFOut);  // 書き込みファイル
  std::string     tm_str;        // time string
  unsigned int    s_tm;          // size of time string
  unsigned int    i;             // loop index
  unsigned int    j;             // loop index
  int             s_nsec;        // size of nsec string
  int             ret;           // return of functions
  struct          tm t = {};     // for work
  struct timespec jst;           // JST
  struct timespec utc;           // UTC
  struct timespec ut1;           // UT1
  struct timespec tai;           // TAI
  struct timespec jst_wk;        // JST(作業用)
  struct timespec utc_wk;        // UTC(作業用)
  struct timespec ut1_wk;        // UT1(作業用)
  struct timespec tai_wk;        // TAI(作業用)
  double          pm_x;          // 極運動(x)
  double          pm_y;          // 極運動(y)
  double          lod;           // LOD
  std::string     lod_str;       // LOD 文字列
  std::vector<std::string> tle;  // TLE
  ns::Satellite   sat;           // 衛星情報
  ns::PvTeme      teme;          // 位置・速度(TEME)
  ns::PvBlh       blh;           // 位置・速度(BLH)

  try {
    // 現在日時(UT1) 取得
    if (argc > 1) {
      // コマンドライン引数より取得
      tm_str = argv[1];
      s_tm = tm_str.size();
      if (s_tm > 23) { 
        std::cout << "[ERROR] Over 23-digits!" << std::endl;
        return EXIT_FAILURE;
      }
      s_nsec = s_tm - 14;
      std::istringstream is(tm_str);
      is >> std::get_time(&t, "%Y%m%d%H%M%S");
      jst.tv_sec  = mktime(&t);
      jst.tv_nsec = 0;
      if (s_tm > 14) {
        jst.tv_nsec = std::stod(
            tm_str.substr(14, s_nsec) + std::string(9 - s_nsec, '0'));
      }
    } else {
      // 現在日時の取得
      ret = std::timespec_get(&jst, TIME_UTC);
      if (ret != 1) {
        std::cout << "[ERROR] Could not get now time!" << std::endl;
        return EXIT_FAILURE;
      }
    }

    // 書き込みファイル open
    std::ofstream ofs(f);
    if (!ofs) return 0;

    // LOOP (日)
    ofs << "{" << std::endl;
    ofs << "  \"counts\": " << ns::kSecD * ns::kDay / ns::kSec
        << "," << std::endl;
    ofs << "  \"data\": [" << std::endl;
    ofs << std::setprecision(12);
    for (i = 0; i < ns::kDay; ++i) {
      jst = ns::ts_add(jst, i * ns::kSecD);

      // EOP データ取得
      utc = ns::jst2utc(jst);
      ns::Eop o_e(utc);
      pm_x = o_e.pm_x;
      pm_y = o_e.pm_y;
      lod  = o_e.lod;
      ut1  = ns::utc2ut1(utc);
      tai  = ns::utc2tai(utc);

      // LOOP (指定秒間隔)
      for (j = 0; j < int(ns::kSecD); j += ns::kSec) {
        jst_wk = ns::ts_add(jst, j);
        utc_wk = ns::ts_add(utc, j);
        ut1_wk = ns::ts_add(ut1, j);
        tai_wk = ns::ts_add(tai, j);

        // TLE 読み込み, gravconst 取得
        ns::Tle o_t(ut1_wk);
        tle = o_t.get_tle();

        // ISS 初期位置・速度の取得
        ns::Sgp4 o_s(ut1_wk, tle);
        sat = o_s.twoline2rv();

        // 指定 UT1 の ISS 位置・速度の取得
        teme = o_s.propagate(sat);

        // TEME -> BLH 変換
        ns::Blh o_b(ut1_wk, tai_wk, pm_x, pm_y, lod);
        blh = o_b.teme2blh(teme);

        // 結果出力
        ofs << "    {" << std::endl;
        ofs << "      \"jst\": \"" << ns::gen_time_str(jst_wk) << "\","
            << std::endl;
        ofs << "      \"utc\": \"" << ns::gen_time_str(utc_wk) << "\","
            << std::endl;
        ofs << "      \"latitude\": "  << blh.r.b << "," << std::endl;
        ofs << "      \"longitude\": " << blh.r.l << "," << std::endl;
        ofs << "      \"height\": "    << blh.r.h << "," << std::endl;
        ofs << "      \"velocity\": "  << blh.v   << std::endl;
        if (i == 1 && j == int(ns::kSecD) - ns::kSec) {
          ofs << "    }"  << std::endl;
        } else {
          ofs << "    }," << std::endl;
        }
      }
    }
    ofs << "  ]" << std::endl;
    ofs << "}" << std::endl;

    // 書き込みファイル close
    ofs.close();
  } catch (...) {
      std::cerr << "EXCEPTION!" << std::endl;
      return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

3. ソースコードのビルド(コンパイル&リンク)

  • リポジトリMakefile があるので、それを使用して make するだけ。(リビルドする際は make clean をしてから)
$ make

4. 準備

  • うるう秒ファイルを こちら からダウンロードし、実行プログラムと同じディレクトリ内に Leap_Second.dat として配置する。
  • 地球姿勢(回転)パラメータ用のデータファイルを、当ブログ過去記事「C++ - EOP(地球姿勢パラメータ)データファイル 生成!」を参考に生成し、実行プログラムと同じディレクトリ内に eop.txt として配置する。(計算対象日の EOP データが存在しないと、計算できないので注意)
  • TLE(Two-line elements; 2行軌道要素形式)データを こちら からダウンロードし、実行プログラムと同じディレクトリ内に tle.txt として配置する。
  • 今回は10秒間隔で2日分の JSON データを生成するが、変更したければ、実行プログラムのソースコード内で変更する。

5. 動作確認

コマンドライン引数には計算開始の JST(日本標準時) を最大23桁(年(4)・月(2)・日(2)・時(2)・分(2)・秒(2)・ナノ秒(9))で指定し、実行。(JST を指定しない場合は、システム時刻を JST とみなす)

$ ./iss_sgp4_json 20210620120000

正常に終了すれば、実行プログラムと同じディレクトリ内に iss.json というファイルが生成されるはずなので、確認してみる。

File: iss.json

{
  "counts": 17280,
  "data": [
    {
      "jst": "2021-06-20 12:00:00.000",
      "utc": "2021-06-20 03:00:00.000",
      "latitude": 30.6852287033,
      "longitude": 42.4874645672,
      "height": 420.157879821,
      "velocity": 7.66381350115
    },
    {
      "jst": "2021-06-20 12:00:10.000",
      "utc": "2021-06-20 03:00:10.000",
      "latitude": 31.1337983271,
      "longitude": 42.9888055227,
      "height": 420.208711161,
      "velocity": 7.66384675711
    },

      :
===< 中略 >===
      :

    {
      "jst": "2021-06-22 11:59:40.000",
      "utc": "2021-06-22 02:59:40.000",
      "latitude": 29.9612854401,
      "longitude": 29.8458082217,
      "height": 420.194896958,
      "velocity": 7.66352515201
    },
    {
      "jst": "2021-06-22 11:59:50.000",
      "utc": "2021-06-22 02:59:50.000",
      "latitude": 30.4134578348,
      "longitude": 30.3391444088,
      "height": 420.243986755,
      "velocity": 7.6635598178
    }
  ]
}

以上。





 

Sponsored Link

 

Comments