#ifndef __RINEX_H__ #define __RINEX_H__ /** * GPSデータの交換に標準的なRINEXファイルについて記述 * */ /* * $Log$ */ #include #include #include #include #include #include class RINEX_Reader { public: typedef std::string string; typedef std::stringstream stringstream; typedef std::map header_t; protected: header_t _header; std::istream &src; bool _has_next; public: RINEX_Reader( std::istream &in, string &(*modify_header)(string &, string &) = NULL) : src(in), _has_next(false){ if(src.fail()){return;} char buf[256]; // ヘッダの読み出し while(!src.eof()){ src.getline(buf, sizeof(buf)); string content(buf); string label(content, 60, 20); { int real_length(label.find_last_not_of(' ') + 1); if(real_length < label.length()){ label = label.substr(0, real_length); } } //cout << label << " (" << label.length() << ")" << endl; if(label.find("END OF HEADER") == 0){break;} content = content.substr(0, 60); if(modify_header){content = modify_header(label, content);} _header[label] = content; } } virtual ~RINEX_Reader(){_header.clear();} header_t &header() {return _header;} bool has_next() const {return _has_next;} }; template class RINEX_Nav_Reader : public RINEX_Reader { protected: typedef RINEX_Nav_Reader self_t; typedef RINEX_Reader super_t; public: typedef GPS_Time gps_time_t; typedef typename GPS_SpaceNode::Satellite::Ephemeris ephemeris_t; struct SatelliteInfo { unsigned int svid; FloatT t_ot; ///< 送信時刻[s] ephemeris_t ephemeris; }; protected: SatelliteInfo info; static string &modify_header(string &label, string &content){ if((label.find("ION ALPHA") == 0) || (label.find("ION BETA") == 0) || (label.find("DELTA-UTC: A0,A1,T,W") == 0)){ for(int pos(0); (pos = content.find("D", pos)) != string::npos; ){ content.replace(pos, 1, "E"); } } return content; } void seek_next() { char buf[256]; for(int i = 0; (i < 8) && (super_t::src.good()); i++){ if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} string line_data(buf); for(int pos(0); (pos = line_data.find("D", pos)) != string::npos; ){ line_data.replace(pos, 1, "E"); } stringstream data(line_data); FloatT dummy; switch(i){ case 0: { data >> info.svid; struct tm t; data >> t.tm_year; // 年 data >> t.tm_mon; // 月 --(t.tm_mon); data >> t.tm_mday; // 日 data >> t.tm_hour; // 時 data >> t.tm_min; // 分 t.tm_sec = 0; gps_time_t gps_time(t); info.ephemeris.WN = gps_time.week; data >> info.ephemeris.t_oc; // 秒 info.ephemeris.t_oc += gps_time.seconds; data >> info.ephemeris.a_f0; data >> info.ephemeris.a_f1; data >> info.ephemeris.a_f2; break; } #define READ_AND_STORE(line_num, v0, v1, v2, v3) \ case line_num: { \ FloatT v; \ data >> v; v0 = v; \ data >> v; v1 = v; \ data >> v; v2 = v; \ data >> v; v3 = v; \ break; \ } READ_AND_STORE(1, info.ephemeris.iode, info.ephemeris.c_rs, info.ephemeris.delta_n, info.ephemeris.m0); READ_AND_STORE(2, info.ephemeris.c_uc, info.ephemeris.e, info.ephemeris.c_us, info.ephemeris.sqrt_A); READ_AND_STORE(3, info.ephemeris.t_oe, info.ephemeris.c_ic, info.ephemeris.Omega0, info.ephemeris.c_is); READ_AND_STORE(4, info.ephemeris.i0, info.ephemeris.c_rc, info.ephemeris.omega, info.ephemeris.dot_Omega0); READ_AND_STORE(5, info.ephemeris.dot_i0, dummy, info.ephemeris.WN, dummy); READ_AND_STORE(6, info.ephemeris.URA, info.ephemeris.SV_health, info.ephemeris.t_GD, info.ephemeris.iodc); READ_AND_STORE(7, info.t_ot, info.ephemeris.fit_interval, dummy, dummy); #undef READ_AND_STORE } } if(info.ephemeris.fit_interval == 0){ info.ephemeris.fit_interval = 4 * 60 * 60; // 最低4時間は有効 } super_t::_has_next = true; } public: RINEX_Nav_Reader(std::istream &in) : super_t(in, self_t::modify_header) { seek_next(); } ~RINEX_Nav_Reader(){} SatelliteInfo next() { SatelliteInfo current(info); super_t::_has_next = false; seek_next(); return current; } /** * 電離層遅延係数を取得し、セットする * * @return 成功した場合true、それ以外false */ bool extract_iono_coef(GPS_SpaceNode &space_node) const { if(_header.find("ION ALPHA") != _header.end()){ stringstream sstr(const_cast(&(_header)) ->operator[]("ION ALPHA")); sstr >> space_node.iono_coef().alpha0; sstr >> space_node.iono_coef().alpha1; sstr >> space_node.iono_coef().alpha2; sstr >> space_node.iono_coef().alpha3; }else{ return false; } if(_header.find("ION BETA") != _header.end()){ stringstream sstr(const_cast(&(_header)) ->operator[]("ION BETA")); sstr >> space_node.iono_coef().beta0; sstr >> space_node.iono_coef().beta1; sstr >> space_node.iono_coef().beta2; sstr >> space_node.iono_coef().beta3; }else{ return false; } return true; } }; template class RINEX_Observe_Reader : public RINEX_Reader { protected: typedef RINEX_Observe_Reader self_t; typedef RINEX_Reader super_t; public: typedef GPS_Time gps_time_t; struct ObservedItem { gps_time_t t_epoc; unsigned event_flag; FloatT receiver_clock_error; typedef struct { FloatT observed; unsigned lli_or_ss; } data_t; typedef std::vector data_1sat_t; typedef std::map sat_data_t; sat_data_t sat_data; }; protected: std::vector types_of_observe; ObservedItem item; static string &modify_header(string &label, string &content){ return content; } void seek_next() { if(types_of_observe.size() == 0){return;} char buf[256]; std::queue sat_list; item.sat_data.clear(); while(true){ // エポック行の読込み { unsigned num_of_followed_data(0); if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} string data_line(buf); stringstream(data_line.substr(26, 3)) >> item.event_flag; // イベントフラグ stringstream(data_line.substr(29, 3)) >> num_of_followed_data; // 衛星(flag = 0/1) or 行数(0/1以外) if(item.event_flag >= 2){ while(num_of_followed_data--){ if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} } continue; } stringstream data(data_line); // エポック時刻の抽出 struct tm t; data >> t.tm_year; // 年 data >> t.tm_mon; // 月 --(t.tm_mon); data >> t.tm_mday; // 日 data >> t.tm_hour; // 時 data >> t.tm_min; // 分 t.tm_sec = 0; item.t_epoc = gps_time_t(t); FloatT v; data >> v; // 秒 item.t_epoc += v; // 受信機クロック誤差 stringstream(data_line.substr(68)) >> item.receiver_clock_error; int prn; for(int i(0); num_of_followed_data > 0; i++, num_of_followed_data--){ if(i == 12){ // 12衛星以上の場合は次の行 if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} data_line = string(buf); i = 0; } stringstream(data_line.substr(33 + (i * 3), 2)) >> prn; switch(data_line[32 + (i * 3)]){ case ' ': case 'G': break; // NAVSTAR case 'R': prn += 200; break; // GLONASS case 'S': prn += 100; break; // SBAS default: prn += 300; } sat_list.push(prn); //cerr << prn << endl; } } // 衛星ごとの観測データの入込み while(!sat_list.empty()){ int prn(sat_list.front()); sat_list.pop(); item.sat_data[prn]; string data_line; for(int i(0); i < types_of_observe.size(); i++){ int offset_index(i % 5); if(offset_index == 0){ if(super_t::src.getline(buf, sizeof(buf)).fail()){return;} data_line = string(buf); } typename ObservedItem::data_t data; stringstream ss(data_line.substr(offset_index * 16, 16)); ss >> data.observed >> data.lli_or_ss; if(ss.fail()){data.lli_or_ss = 0;} //cerr << data.observed << ", " << data.lli_or_ss << endl; item.sat_data[prn].push_back(data); } } break; } super_t::_has_next = true; } public: RINEX_Observe_Reader(std::istream &in) : super_t(in, self_t::modify_header), types_of_observe() { if(super_t::_header.find("# / TYPES OF OBSERV") != super_t::_header.end()){ stringstream data(super_t::_header["# / TYPES OF OBSERV"]); unsigned num_types_of_observe; data >> num_types_of_observe; while(num_types_of_observe){ string param_name; data >> param_name; if(!data.good()){break;} types_of_observe.push_back(param_name); num_types_of_observe--; } if(num_types_of_observe == 0){ seek_next(); }else{ types_of_observe.clear(); } } } ~RINEX_Observe_Reader(){} ObservedItem next() { ObservedItem current(item); super_t::_has_next = false; seek_next(); return current; } /** * データ行において、ラベルに対応するインデックスを返す * 見つからなかった場合は-1が返る * */ int observed_index(const string &label) const { int res(distance(types_of_observe.begin(), find(types_of_observe.begin(), types_of_observe.end(), label))); return (res >= types_of_observe.size() ? -1 : res); } int observed_index(const char *label) const { return observed_index(string(label)); } }; #endif // __RINEX_H__