gps_pvt 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/Rakefile +1 -0
- data/exe/gps_pvt +3 -1
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +787 -205
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +2 -3
- data/ext/ninja-scan-light/tool/navigation/ANTEX.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +7 -7
- data/ext/ninja-scan-light/tool/navigation/MagneticField.h +4 -3
- data/ext/ninja-scan-light/tool/navigation/NTCM.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +29 -14
- data/ext/ninja-scan-light/tool/navigation/RINEX_Clock.h +458 -0
- data/ext/ninja-scan-light/tool/navigation/SBAS.h +3 -3
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/SP3.h +49 -42
- data/ext/ninja-scan-light/tool/param/quaternion.h +2 -2
- data/ext/ninja-scan-light/tool/param/vector3.h +2 -2
- data/ext/ninja-scan-light/tool/swig/GPS.i +95 -51
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +1 -2
- data/lib/gps_pvt/receiver.rb +16 -0
- data/lib/gps_pvt/version.rb +1 -1
- metadata +3 -2
| @@ -0,0 +1,458 @@ | |
| 1 | 
            +
            /*
         | 
| 2 | 
            +
             * Copyright (c) 2022, M.Naruoka (fenrir)
         | 
| 3 | 
            +
             * All rights reserved.
         | 
| 4 | 
            +
             *
         | 
| 5 | 
            +
             * Redistribution and use in source and binary forms, with or without modification,
         | 
| 6 | 
            +
             * are permitted provided that the following conditions are met:
         | 
| 7 | 
            +
             *
         | 
| 8 | 
            +
             * - Redistributions of source code must retain the above copyright notice,
         | 
| 9 | 
            +
             *   this list of conditions and the following disclaimer.
         | 
| 10 | 
            +
             * - Redistributions in binary form must reproduce the above copyright notice,
         | 
| 11 | 
            +
             *   this list of conditions and the following disclaimer in the documentation
         | 
| 12 | 
            +
             *   and/or other materials provided with the distribution.
         | 
| 13 | 
            +
             * - Neither the name of the naruoka.org nor the names of its contributors
         | 
| 14 | 
            +
             *   may be used to endorse or promote products derived from this software
         | 
| 15 | 
            +
             *   without specific prior written permission.
         | 
| 16 | 
            +
             *
         | 
| 17 | 
            +
             * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         | 
| 18 | 
            +
             * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
         | 
| 19 | 
            +
             * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
         | 
| 20 | 
            +
             * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
         | 
| 21 | 
            +
             * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
         | 
| 22 | 
            +
             * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
         | 
| 23 | 
            +
             * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
         | 
| 24 | 
            +
             * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
         | 
| 25 | 
            +
             * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
         | 
| 26 | 
            +
             * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
         | 
| 27 | 
            +
             * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
         | 
| 28 | 
            +
             * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         | 
| 29 | 
            +
             *
         | 
| 30 | 
            +
             */
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            /** @file
         | 
| 33 | 
            +
             * @brief Loader of RINEX Clock extension, support versions are 3 including 3.04
         | 
| 34 | 
            +
             */
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            #ifndef __RINEX_CLOCK__
         | 
| 37 | 
            +
            #define __RINEX_CLOCK__
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            #include <cstring>
         | 
| 40 | 
            +
            #include <cctype>
         | 
| 41 | 
            +
            #include <string>
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            #include "RINEX.h"
         | 
| 44 | 
            +
            #include "GPS.h"
         | 
| 45 | 
            +
            #include "algorithm/interpolate.h"
         | 
| 46 | 
            +
            #include "GPS_Solver_Base.h"
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            template <class FloatT>
         | 
| 49 | 
            +
            struct RINEX_CLK {
         | 
| 50 | 
            +
              struct record_t {
         | 
| 51 | 
            +
                char type[2], name[9];
         | 
| 52 | 
            +
                std::tm epoch;
         | 
| 53 | 
            +
                int epoch_year4, epoch_mon12;
         | 
| 54 | 
            +
                FloatT epoch_sec;
         | 
| 55 | 
            +
                int items_followed;
         | 
| 56 | 
            +
                bool valid[6];
         | 
| 57 | 
            +
                union {
         | 
| 58 | 
            +
                  FloatT array[6];
         | 
| 59 | 
            +
                  struct {
         | 
| 60 | 
            +
                    FloatT bias, bias_sigma, rate, rate_sigma, acc, acc_sigma;
         | 
| 61 | 
            +
                  } v;
         | 
| 62 | 
            +
                } values;
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                GPS_Time<FloatT> get_epoch() const {
         | 
| 65 | 
            +
                  return GPS_Time<FloatT>(epoch) + (epoch_sec - epoch.tm_sec);
         | 
| 66 | 
            +
                }
         | 
| 67 | 
            +
                record_t &set_epoch(const GPS_Time<FloatT> &t){
         | 
| 68 | 
            +
                  epoch = t.c_tm();
         | 
| 69 | 
            +
                  epoch_year4 = epoch.tm_year + 1900;
         | 
| 70 | 
            +
                  epoch_mon12 = epoch.tm_mon + 1;
         | 
| 71 | 
            +
                  epoch_sec = std::fmod(t.seconds, 60);
         | 
| 72 | 
            +
                  return *this;
         | 
| 73 | 
            +
                }
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                std::string get_name() const {
         | 
| 76 | 
            +
                  std::string res;
         | 
| 77 | 
            +
                  for(std::size_t i(0); i < sizeof(name); ++i){
         | 
| 78 | 
            +
                    if(!std::isgraph(name[i])){break;}
         | 
| 79 | 
            +
                    res.push_back(name[i]);
         | 
| 80 | 
            +
                  }
         | 
| 81 | 
            +
                  return res;
         | 
| 82 | 
            +
                }
         | 
| 83 | 
            +
                record_t &set_name(const std::string &str){
         | 
| 84 | 
            +
                  std::memset(name, ' ', sizeof(name));
         | 
| 85 | 
            +
                  str.copy(name, str.size() > sizeof(name) ? sizeof(name) : str.size());
         | 
| 86 | 
            +
                  return *this;
         | 
| 87 | 
            +
                }
         | 
| 88 | 
            +
              };
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              struct per_node_t {
         | 
| 91 | 
            +
                std::map<GPS_Time<FloatT>, FloatT> bias;
         | 
| 92 | 
            +
                typedef InterpolatableSet<GPS_Time<FloatT>, FloatT, FloatT> interpolator_t;
         | 
| 93 | 
            +
                static const typename interpolator_t::condition_t interpolator_cnd_default;
         | 
| 94 | 
            +
                mutable struct {
         | 
| 95 | 
            +
                  interpolator_t bias;
         | 
| 96 | 
            +
                } subset;
         | 
| 97 | 
            +
                bool precheck(const GPS_Time<FloatT> &t) const {
         | 
| 98 | 
            +
                  subset.bias.update(t, bias, interpolator_cnd_default);
         | 
| 99 | 
            +
                  return subset.bias.ready;
         | 
| 100 | 
            +
                }
         | 
| 101 | 
            +
                FloatT clock_error(const GPS_Time<FloatT> &t) const {
         | 
| 102 | 
            +
                  return subset.bias.update(t, bias, interpolator_cnd_default).interpolate(t);
         | 
| 103 | 
            +
                }
         | 
| 104 | 
            +
                FloatT clock_error_dot(const GPS_Time<FloatT> &t) const {
         | 
| 105 | 
            +
                  FloatT res;
         | 
| 106 | 
            +
                  subset.bias.update(t, bias, interpolator_cnd_default).interpolate(t, &res);
         | 
| 107 | 
            +
                  return res;
         | 
| 108 | 
            +
                }
         | 
| 109 | 
            +
              };
         | 
| 110 | 
            +
              struct satellites_t {
         | 
| 111 | 
            +
                typedef std::map<int, per_node_t> buf_t; // prn => per_node_t
         | 
| 112 | 
            +
                buf_t buf;
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                enum system_t {
         | 
| 115 | 
            +
                  SYSTEM_GPS,
         | 
| 116 | 
            +
                  SYSTEM_SBAS,
         | 
| 117 | 
            +
                  SYSTEM_QZSS,
         | 
| 118 | 
            +
                  SYSTEM_GLONASS,
         | 
| 119 | 
            +
                  SYSTEM_GALILEO,
         | 
| 120 | 
            +
                  SYSTEM_BEIDOU,
         | 
| 121 | 
            +
                  SYSTEM_IRNSS,
         | 
| 122 | 
            +
                  NUM_OF_SYSTEMS,
         | 
| 123 | 
            +
                };
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                static const int offset_list[NUM_OF_SYSTEMS];
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                protected:
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                typedef typename GPS_Solver_Base<FloatT>::satellite_t sat_t;
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                mutable struct per_system_t {
         | 
| 132 | 
            +
                  struct {
         | 
| 133 | 
            +
                    const satellites_t *sats;
         | 
| 134 | 
            +
                  } clk_rate;
         | 
| 135 | 
            +
                  struct {
         | 
| 136 | 
            +
                    const void *impl;
         | 
| 137 | 
            +
                    sat_t (*impl_select)(const void *, const int &, const GPS_Time<FloatT> &);
         | 
| 138 | 
            +
                  } pos_vel;
         | 
| 139 | 
            +
                  system_t sys;
         | 
| 140 | 
            +
                } per_system[NUM_OF_SYSTEMS];
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                static sat_t select(
         | 
| 143 | 
            +
                    const void *ptr, const int &prn, const GPS_Time<FloatT> &receiver_time){
         | 
| 144 | 
            +
                  const per_system_t *ptr_sys(reinterpret_cast<const per_system_t *>(ptr));
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  // retrieve position/velocity supplier
         | 
| 147 | 
            +
                  sat_t res(
         | 
| 148 | 
            +
                      ptr_sys->pos_vel.impl_select(ptr_sys->pos_vel.impl, prn, receiver_time));
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  int sat_id((prn & 0xFF) + offset_list[ptr_sys->sys]);
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                  // check clock_error/clock_error_dot availability
         | 
| 153 | 
            +
                  typename buf_t::const_iterator it(ptr_sys->clk_rate.sats->buf.find(sat_id));
         | 
| 154 | 
            +
                  if((it == ptr_sys->clk_rate.sats->buf.end()) || !it->second.precheck(receiver_time)){
         | 
| 155 | 
            +
                    // unavailable case
         | 
| 156 | 
            +
                    static const sat_t &unavailable(sat_t::unavailable());
         | 
| 157 | 
            +
                    res.impl_t = unavailable.impl_t;
         | 
| 158 | 
            +
                    res.impl_clock_error = unavailable.impl_clock_error;
         | 
| 159 | 
            +
                    res.impl_clock_error_dot = unavailable.impl_clock_error_dot;
         | 
| 160 | 
            +
                    return res;
         | 
| 161 | 
            +
                  }
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                  struct impl_t {
         | 
| 164 | 
            +
                    static inline const per_node_t &sat(const void *ptr) {
         | 
| 165 | 
            +
                      return *reinterpret_cast<const per_node_t *>(ptr);
         | 
| 166 | 
            +
                    }
         | 
| 167 | 
            +
                    static typename GPS_Solver_Base<FloatT>::float_t clock_error(
         | 
| 168 | 
            +
                        const void *ptr, const GPS_Time<FloatT> &t_tx) {
         | 
| 169 | 
            +
                      return sat(ptr).clock_error(t_tx);
         | 
| 170 | 
            +
                    }
         | 
| 171 | 
            +
                    static typename GPS_Solver_Base<FloatT>::float_t clock_error_dot(
         | 
| 172 | 
            +
                        const void *ptr, const GPS_Time<FloatT> &t_tx) {
         | 
| 173 | 
            +
                      return sat(ptr).clock_error_dot(t_tx);
         | 
| 174 | 
            +
                    }
         | 
| 175 | 
            +
                  };
         | 
| 176 | 
            +
                  res.impl_t = &(it->second);
         | 
| 177 | 
            +
                  res.impl_clock_error = impl_t::clock_error;
         | 
| 178 | 
            +
                  res.impl_clock_error_dot = impl_t::clock_error_dot;
         | 
| 179 | 
            +
                  return res;
         | 
| 180 | 
            +
                }
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                public:
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                template <class SelectorT>
         | 
| 185 | 
            +
                bool push(SelectorT &slct, const system_t &sys = SYSTEM_GPS) const {
         | 
| 186 | 
            +
                  if(sys >= NUM_OF_SYSTEMS){return false;}
         | 
| 187 | 
            +
                  per_system[sys].clk_rate.sats = this;
         | 
| 188 | 
            +
                  per_system[sys].sys = sys;
         | 
| 189 | 
            +
                  if(slct.impl_select != select){
         | 
| 190 | 
            +
                    per_system[sys].pos_vel.impl = slct.impl;
         | 
| 191 | 
            +
                    per_system[sys].pos_vel.impl_select = slct.impl_select;
         | 
| 192 | 
            +
                  }
         | 
| 193 | 
            +
                  slct.impl_select = select;
         | 
| 194 | 
            +
                  slct.impl = &per_system[sys];
         | 
| 195 | 
            +
                  return true;
         | 
| 196 | 
            +
                }
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                struct count_t {
         | 
| 199 | 
            +
                  int gps, sbas, qzss, glonass, galileo, beidou, irnss, unknown;
         | 
| 200 | 
            +
                };
         | 
| 201 | 
            +
                count_t count() const {
         | 
| 202 | 
            +
                  count_t res = {0};
         | 
| 203 | 
            +
                  for(typename buf_t::const_iterator it(buf.begin()), it_end(buf.end());
         | 
| 204 | 
            +
                      it != it_end; ++it){
         | 
| 205 | 
            +
                    switch((char)(it->first >> 8)){
         | 
| 206 | 
            +
                      case '\0': {
         | 
| 207 | 
            +
                        int id(it->first & 0xFF);
         | 
| 208 | 
            +
                        if(id < 100){++res.gps;}
         | 
| 209 | 
            +
                        else if(id < 192){++res.sbas;}
         | 
| 210 | 
            +
                        else{++res.qzss;}
         | 
| 211 | 
            +
                        break;
         | 
| 212 | 
            +
                      }
         | 
| 213 | 
            +
                      case 'R': ++res.glonass;  break;
         | 
| 214 | 
            +
                      case 'E': ++res.galileo;  break;
         | 
| 215 | 
            +
                      case 'C': ++res.beidou;   break;
         | 
| 216 | 
            +
                      case 'I': ++res.irnss;    break;
         | 
| 217 | 
            +
                      default: ++res.unknown; break;
         | 
| 218 | 
            +
                    }
         | 
| 219 | 
            +
                  }
         | 
| 220 | 
            +
                  return res;
         | 
| 221 | 
            +
                }
         | 
| 222 | 
            +
              };
         | 
| 223 | 
            +
              typedef std::map<std::string, per_node_t> collection_t; // satellites + receivers, name => per_node_t
         | 
| 224 | 
            +
            };
         | 
| 225 | 
            +
             | 
| 226 | 
            +
            template <class FloatT>
         | 
| 227 | 
            +
            const typename RINEX_CLK<FloatT>::per_node_t::interpolator_t::condition_t
         | 
| 228 | 
            +
                RINEX_CLK<FloatT>::per_node_t::interpolator_cnd_default = {
         | 
| 229 | 
            +
                  5, // max_x_size
         | 
| 230 | 
            +
                  60 * 60 * 2, // subset.cnd.max_dx_range
         | 
| 231 | 
            +
                };
         | 
| 232 | 
            +
             | 
| 233 | 
            +
            template <class FloatT>
         | 
| 234 | 
            +
            const int RINEX_CLK<FloatT>::satellites_t::offset_list[NUM_OF_SYSTEMS] = {
         | 
| 235 | 
            +
              0, 0, 0, // GPS, SBAS, QZSS
         | 
| 236 | 
            +
              (int)'R' << 8, // GLONASS
         | 
| 237 | 
            +
              (int)'E' << 8, // GALILEO
         | 
| 238 | 
            +
              (int)'C' << 8, // BEIDOU
         | 
| 239 | 
            +
              (int)'I' << 8, // IRNSS,
         | 
| 240 | 
            +
            };
         | 
| 241 | 
            +
             | 
| 242 | 
            +
            template <class FloatT = double>
         | 
| 243 | 
            +
            class RINEX_CLK_Reader : public RINEX_Reader<> {
         | 
| 244 | 
            +
              protected:
         | 
| 245 | 
            +
                typedef RINEX_Reader<> super_t;
         | 
| 246 | 
            +
              public:
         | 
| 247 | 
            +
                typedef typename RINEX_CLK<FloatT>::record_t record_t;
         | 
| 248 | 
            +
                static const typename super_t::convert_item_t head_v3[7];
         | 
| 249 | 
            +
                static const typename super_t::convert_item_t head_v304[7];
         | 
| 250 | 
            +
             | 
| 251 | 
            +
              protected:
         | 
| 252 | 
            +
                record_t record;
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                void read_header(){
         | 
| 255 | 
            +
                  if(super_t::src.fail()){return;}
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                  char buf[256];
         | 
| 258 | 
            +
                  int label_offset(60);
         | 
| 259 | 
            +
             | 
| 260 | 
            +
                  // Read header
         | 
| 261 | 
            +
                  for(int line(0); !super_t::src.eof(); ++line){
         | 
| 262 | 
            +
                    super_t::src.getline(buf, sizeof(buf));
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                    std::string content(buf);
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                    if(line == 0){ // Check version and type extraction
         | 
| 267 | 
            +
                      switch(content.find("RINEX VERSION / TYPE")){
         | 
| 268 | 
            +
                        case 60:
         | 
| 269 | 
            +
                          super_t::version_type.parse(content);
         | 
| 270 | 
            +
                          break;
         | 
| 271 | 
            +
                        case 65: {
         | 
| 272 | 
            +
                          double temp(0);
         | 
| 273 | 
            +
                          super_t::conv_t<double>::f(content, 0, 4, &temp, 2);
         | 
| 274 | 
            +
                          super_t::version_type.version = (int)(temp * 100);
         | 
| 275 | 
            +
                          if(super_t::version_type.version != 304){return;}
         | 
| 276 | 
            +
                          if(content[21] != 'C'){return;}
         | 
| 277 | 
            +
                          super_t::version_type.file_type
         | 
| 278 | 
            +
                              = super_t::version_type_t::FTYPE_CLOCK;
         | 
| 279 | 
            +
                          super_t::version_type.sat_system
         | 
| 280 | 
            +
                              = super_t::version_type_t::char2sys_v3(content[42]);
         | 
| 281 | 
            +
                          label_offset = 65;
         | 
| 282 | 
            +
                          break;
         | 
| 283 | 
            +
                        }
         | 
| 284 | 
            +
                        default: // includes std::string::npos:
         | 
| 285 | 
            +
                          return;
         | 
| 286 | 
            +
                      }
         | 
| 287 | 
            +
                    }
         | 
| 288 | 
            +
             | 
| 289 | 
            +
                    std::string label(content, label_offset, 20);
         | 
| 290 | 
            +
                    {
         | 
| 291 | 
            +
                      int real_length(label.find_last_not_of(' ') + 1);
         | 
| 292 | 
            +
                      if(real_length < (int)label.length()){
         | 
| 293 | 
            +
                        label = label.substr(0, real_length);
         | 
| 294 | 
            +
                      }
         | 
| 295 | 
            +
                    }
         | 
| 296 | 
            +
             | 
| 297 | 
            +
                    if(label.find("END OF HEADER") == 0){break;}
         | 
| 298 | 
            +
             | 
| 299 | 
            +
                    _header[label].push_back(content.substr(0, label_offset));
         | 
| 300 | 
            +
                  }
         | 
| 301 | 
            +
                }
         | 
| 302 | 
            +
             | 
| 303 | 
            +
              public:
         | 
| 304 | 
            +
                void seek_next() {
         | 
| 305 | 
            +
                  super_t::_has_next = false;
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                  char buf[1024];
         | 
| 308 | 
            +
                  std::string str;
         | 
| 309 | 
            +
                  bool v304(super_t::version_type.version == 304);
         | 
| 310 | 
            +
                  while(true){
         | 
| 311 | 
            +
                    if(super_t::src.getline(buf, sizeof(buf)).fail()){return;}
         | 
| 312 | 
            +
                    str.assign(buf);
         | 
| 313 | 
            +
                    if(str.size() < (v304 ? 45 : 37)){continue;}
         | 
| 314 | 
            +
                    str.copy(record.type, 2);
         | 
| 315 | 
            +
                    if((std::memcmp(record.type, "AR", 2) == 0)
         | 
| 316 | 
            +
                        || (std::memcmp(record.type, "AS", 2) == 0)
         | 
| 317 | 
            +
                        || (std::memcmp(record.type, "CR", 2) == 0)
         | 
| 318 | 
            +
                        || (std::memcmp(record.type, "DR", 2) == 0)
         | 
| 319 | 
            +
                        || (std::memcmp(record.type, "MS", 2) == 0)){
         | 
| 320 | 
            +
                      break;
         | 
| 321 | 
            +
                    }
         | 
| 322 | 
            +
                  }
         | 
| 323 | 
            +
                  std::memset(record.name, ' ', sizeof(record.name));
         | 
| 324 | 
            +
                  str.copy(record.name, v304 ? 9 : 4, 3);
         | 
| 325 | 
            +
                  v304 ? super_t::convert(head_v304, str, &record) : super_t::convert(head_v3, str, &record);
         | 
| 326 | 
            +
                  record.epoch.tm_year = record.epoch_year4 - 1900; // greater than 1980
         | 
| 327 | 
            +
                  record.epoch.tm_mon = record.epoch_mon12 - 1; // month [0, 11]
         | 
| 328 | 
            +
                  record.epoch.tm_sec = (int)record.epoch_sec;
         | 
| 329 | 
            +
             | 
| 330 | 
            +
                  for(int i(0), j(2), k(v304 ? 45 : 40); i < 6; ++i, ++j, k += (v304 ? 21 : 20)){
         | 
| 331 | 
            +
                    record.valid[i] = false;
         | 
| 332 | 
            +
                    if(i >= record.items_followed){continue;}
         | 
| 333 | 
            +
                    if(j % 4 == 0){
         | 
| 334 | 
            +
                      j = 0; k = 3;
         | 
| 335 | 
            +
                      if(super_t::src.getline(buf, sizeof(buf)).fail()){break;}
         | 
| 336 | 
            +
                      str.assign(buf);
         | 
| 337 | 
            +
                    }
         | 
| 338 | 
            +
                    if(!super_t::template conv_t<FloatT>::e_dot_head(
         | 
| 339 | 
            +
                        str, k, 19, &record.values.array[i], 12)){break;}
         | 
| 340 | 
            +
                    record.valid[i] = true;
         | 
| 341 | 
            +
                  }
         | 
| 342 | 
            +
             | 
| 343 | 
            +
                  super_t::_has_next = true;
         | 
| 344 | 
            +
                }
         | 
| 345 | 
            +
             | 
| 346 | 
            +
                RINEX_CLK_Reader(std::istream &in)
         | 
| 347 | 
            +
                    : super_t(in, static_cast<void(super_t::*)()>(
         | 
| 348 | 
            +
                        &RINEX_CLK_Reader::read_header)) {
         | 
| 349 | 
            +
                  seek_next();
         | 
| 350 | 
            +
                }
         | 
| 351 | 
            +
                ~RINEX_CLK_Reader(){}
         | 
| 352 | 
            +
             | 
| 353 | 
            +
                void next() {
         | 
| 354 | 
            +
                  seek_next();
         | 
| 355 | 
            +
                }
         | 
| 356 | 
            +
             | 
| 357 | 
            +
              protected:
         | 
| 358 | 
            +
                static int read_all(
         | 
| 359 | 
            +
                    std::istream &in,
         | 
| 360 | 
            +
                    void *buf, bool (*callback)(void *, const record_t &)){
         | 
| 361 | 
            +
                  RINEX_CLK_Reader reader(in);
         | 
| 362 | 
            +
                  if(reader.version_type.file_type != version_type_t::FTYPE_CLOCK){
         | 
| 363 | 
            +
                    return -1;
         | 
| 364 | 
            +
                  }
         | 
| 365 | 
            +
                  int res(0);
         | 
| 366 | 
            +
                  for(; reader.has_next(); reader.next()){
         | 
| 367 | 
            +
                    if(!reader.record.valid[0]){continue;}
         | 
| 368 | 
            +
                    if(!callback(buf, reader.record)){continue;}
         | 
| 369 | 
            +
                    ++res;
         | 
| 370 | 
            +
                  }
         | 
| 371 | 
            +
                  return res;
         | 
| 372 | 
            +
                }
         | 
| 373 | 
            +
             | 
| 374 | 
            +
              public:
         | 
| 375 | 
            +
                static int read_all(
         | 
| 376 | 
            +
                    std::istream &in,
         | 
| 377 | 
            +
                    typename RINEX_CLK<FloatT>::satellites_t &dst){
         | 
| 378 | 
            +
                  struct func_t {
         | 
| 379 | 
            +
                    static bool add(void *ptr, const record_t &record){
         | 
| 380 | 
            +
                      typename RINEX_CLK<FloatT>::satellites_t &dst(
         | 
| 381 | 
            +
                          *reinterpret_cast<typename RINEX_CLK<FloatT>::satellites_t *>(ptr));
         | 
| 382 | 
            +
                      if((record.type[0] != 'A') || (record.type[1] != 'S')){return false;}
         | 
| 383 | 
            +
                      int offset(0);
         | 
| 384 | 
            +
                      char sys(record.name[0]);
         | 
| 385 | 
            +
                      switch(sys){
         | 
| 386 | 
            +
                        case 'G': break; // GPS
         | 
| 387 | 
            +
                        case 'R': offset = (int)'R' << 8; break; // GLONASS
         | 
| 388 | 
            +
                        case 'E': offset = (int)'E' << 8; break; // Galileo
         | 
| 389 | 
            +
                        case 'C': offset = (int)'C' << 8; break; // BeiDou
         | 
| 390 | 
            +
                        case 'J': offset = 192; break; // QZSS
         | 
| 391 | 
            +
                        case 'S': offset = 100; break; // SBAS
         | 
| 392 | 
            +
                        case 'I': offset = (int)'I' << 8; break; // IRNSS
         | 
| 393 | 
            +
                        default: return false;
         | 
| 394 | 
            +
                      }
         | 
| 395 | 
            +
                      if(record.name[1] < '0' || record.name[1] > '9'
         | 
| 396 | 
            +
                          || record.name[2] < '0' || record.name[2] > '9'){return false;}
         | 
| 397 | 
            +
                      int idx((record.name[1] - '0') * 10 + (record.name[2] - '0') + offset);
         | 
| 398 | 
            +
                      dst.buf[idx].bias[record.get_epoch()] = record.values.v.bias;
         | 
| 399 | 
            +
                      return true;
         | 
| 400 | 
            +
                    }
         | 
| 401 | 
            +
                  };
         | 
| 402 | 
            +
                  return read_all(in, &dst, func_t::add);
         | 
| 403 | 
            +
                }
         | 
| 404 | 
            +
             | 
| 405 | 
            +
                static int read_all(
         | 
| 406 | 
            +
                    std::istream &in,
         | 
| 407 | 
            +
                    typename RINEX_CLK<FloatT>::collection_t &dst){
         | 
| 408 | 
            +
                  struct func_t {
         | 
| 409 | 
            +
                    static bool add(void *ptr, const record_t &record){
         | 
| 410 | 
            +
                      typename RINEX_CLK<FloatT>::collection_t &dst(
         | 
| 411 | 
            +
                          *reinterpret_cast<typename RINEX_CLK<FloatT>::collection_t *>(ptr));
         | 
| 412 | 
            +
                      dst[record.get_name()].bias[record.get_epoch()] = record.values.v.bias;
         | 
| 413 | 
            +
                      return true;
         | 
| 414 | 
            +
                    }
         | 
| 415 | 
            +
                  };
         | 
| 416 | 
            +
                  return read_all(in, &dst, func_t::add);
         | 
| 417 | 
            +
                }
         | 
| 418 | 
            +
            };
         | 
| 419 | 
            +
             | 
| 420 | 
            +
            #define GEN_D(offset, length, container_type, container_member, value_type) \
         | 
| 421 | 
            +
                {super_t::template conv_t<value_type>::d, offset, length, \
         | 
| 422 | 
            +
                  offsetof(container_type, container_member)}
         | 
| 423 | 
            +
            #define GEN_I(offset, length, container_type, container_member, value_type) \
         | 
| 424 | 
            +
                {super_t::template conv_t<value_type>::d, offset, length, \
         | 
| 425 | 
            +
                  offsetof(container_type, container_member), 1}
         | 
| 426 | 
            +
            #define GEN_F2(offset, length, precision, container_type, container_member, value_type) \
         | 
| 427 | 
            +
                {super_t::template conv_t<value_type>::f_dot_head, offset, length, \
         | 
| 428 | 
            +
                  offsetof(container_type, container_member), precision}
         | 
| 429 | 
            +
            #define GEN_F(offset, length, precision, container_type, container_member) \
         | 
| 430 | 
            +
                GEN_F2(offset, length, precision, container_type, container_member, FloatT)
         | 
| 431 | 
            +
             | 
| 432 | 
            +
            template <class FloatT>
         | 
| 433 | 
            +
            const typename RINEX_CLK_Reader<FloatT>::convert_item_t RINEX_CLK_Reader<FloatT>::head_v3[] = {
         | 
| 434 | 
            +
              GEN_I( 8,  4,     record_t, epoch_year4,    int),
         | 
| 435 | 
            +
              GEN_I(13,  2,     record_t, epoch_mon12,    int),
         | 
| 436 | 
            +
              GEN_I(16,  2,     record_t, epoch.tm_mday,  int),
         | 
| 437 | 
            +
              GEN_I(19,  2,     record_t, epoch.tm_hour,  int),
         | 
| 438 | 
            +
              GEN_I(22,  2,     record_t, epoch.tm_min,   int),
         | 
| 439 | 
            +
              GEN_F(24, 10,  6, record_t, epoch_sec),
         | 
| 440 | 
            +
              GEN_D(34,  3,     record_t, items_followed, int),
         | 
| 441 | 
            +
            };
         | 
| 442 | 
            +
             | 
| 443 | 
            +
            template <class FloatT>
         | 
| 444 | 
            +
            const typename RINEX_CLK_Reader<FloatT>::convert_item_t RINEX_CLK_Reader<FloatT>::head_v304[] = {
         | 
| 445 | 
            +
              GEN_I(13,  4,     record_t, epoch_year4,    int),
         | 
| 446 | 
            +
              GEN_I(18,  2,     record_t, epoch_mon12,    int),
         | 
| 447 | 
            +
              GEN_I(21,  2,     record_t, epoch.tm_mday,  int),
         | 
| 448 | 
            +
              GEN_I(24,  2,     record_t, epoch.tm_hour,  int),
         | 
| 449 | 
            +
              GEN_I(27,  2,     record_t, epoch.tm_min,   int),
         | 
| 450 | 
            +
              GEN_F(29,  9,  6, record_t, epoch_sec),
         | 
| 451 | 
            +
              GEN_D(40,  2,     record_t, items_followed, int),
         | 
| 452 | 
            +
            };
         | 
| 453 | 
            +
             | 
| 454 | 
            +
            #undef GEN_D
         | 
| 455 | 
            +
            #undef GEN_I
         | 
| 456 | 
            +
            #undef GEN_F
         | 
| 457 | 
            +
             | 
| 458 | 
            +
            #endif /* __RINEX_CLOCK__ */
         | 
| @@ -1387,16 +1387,16 @@ sf[SF_ ## TARGET] * msg_t::TARGET(buf) | |
| 1387 1387 |  | 
| 1388 1388 | 
             
                      // the first line
         | 
| 1389 1389 | 
             
                      out << "     ";
         | 
| 1390 | 
            -
                      for( | 
| 1390 | 
            +
                      for(std::size_t j(0); j < sizeof(igp.properties[0]) / sizeof(igp.properties[0][0]); ++j){
         | 
| 1391 1391 | 
             
                        int lng(position_index_t::idx2lng(j));
         | 
| 1392 1392 | 
             
                        out << (lng == 0 ? '0' : (lng % 90 == 0 ? '|' : (lng % 30 == 0 ? '+' : ' ')));
         | 
| 1393 1393 | 
             
                      }
         | 
| 1394 1394 | 
             
                      out << std::endl;
         | 
| 1395 1395 |  | 
| 1396 | 
            -
                      for( | 
| 1396 | 
            +
                      for(std::size_t i(0); i < sizeof(igp.properties) / sizeof(igp.properties[0]); ++i){
         | 
| 1397 1397 | 
             
                        out.width(4);
         | 
| 1398 1398 | 
             
                        out << position_index_t::idx2lat(i) << ' ';
         | 
| 1399 | 
            -
                        for( | 
| 1399 | 
            +
                        for(std::size_t j(0); j < sizeof(igp.properties[0]) / sizeof(igp.properties[0][0]); ++j){
         | 
| 1400 1400 | 
             
                          if(!igp.properties[i][j].is_available()){
         | 
| 1401 1401 | 
             
                            out << ' ';
         | 
| 1402 1402 | 
             
                          }else{
         | 
| @@ -128,7 +128,7 @@ class SBAS_SinglePositioning : public SolverBaseT { | |
| 128 128 | 
             
                      }
         | 
| 129 129 | 
             
                    };
         | 
| 130 130 | 
             
                    satellite_t res = {
         | 
| 131 | 
            -
                        &(it_sat->second),
         | 
| 131 | 
            +
                        &(it_sat->second), &(it_sat->second),
         | 
| 132 132 | 
             
                        impl_t::position, impl_t::velocity,
         | 
| 133 133 | 
             
                        impl_t::clock_error, impl_t::clock_error_dot};
         | 
| 134 134 | 
             
                    return res;
         | 
| @@ -185,7 +185,7 @@ struct SP3_Product { | |
| 185 185 | 
             
                    }
         | 
| 186 186 | 
             
                  };
         | 
| 187 187 | 
             
                  typename GPS_Solver_Base<FloatT>::satellite_t res = {
         | 
| 188 | 
            -
                    this,
         | 
| 188 | 
            +
                    this, this,
         | 
| 189 189 | 
             
                    impl_t::position, impl_t::velocity,
         | 
| 190 190 | 
             
                    impl_t::clock_error, impl_t::clock_error_dot
         | 
| 191 191 | 
             
                  };
         | 
| @@ -248,29 +248,33 @@ struct SP3_Product { | |
| 248 248 | 
             
              }
         | 
| 249 249 |  | 
| 250 250 | 
             
              enum system_t {
         | 
| 251 | 
            -
                SYSTEM_GPS | 
| 252 | 
            -
                SYSTEM_SBAS | 
| 253 | 
            -
                SYSTEM_QZSS | 
| 254 | 
            -
                SYSTEM_GLONASS | 
| 255 | 
            -
                SYSTEM_LEO | 
| 256 | 
            -
                SYSTEM_GALILEO | 
| 257 | 
            -
                SYSTEM_BEIDOU | 
| 258 | 
            -
                SYSTEM_IRNSS | 
| 251 | 
            +
                SYSTEM_GPS,
         | 
| 252 | 
            +
                SYSTEM_SBAS,
         | 
| 253 | 
            +
                SYSTEM_QZSS,
         | 
| 254 | 
            +
                SYSTEM_GLONASS,
         | 
| 255 | 
            +
                SYSTEM_LEO,
         | 
| 256 | 
            +
                SYSTEM_GALILEO,
         | 
| 257 | 
            +
                SYSTEM_BEIDOU,
         | 
| 258 | 
            +
                SYSTEM_IRNSS,
         | 
| 259 | 
            +
                NUM_OF_SYSTEMS,
         | 
| 259 260 | 
             
              };
         | 
| 260 261 |  | 
| 261 | 
            -
             | 
| 262 | 
            -
             | 
| 263 | 
            -
             | 
| 264 | 
            -
             | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
               | 
| 269 | 
            -
             | 
| 270 | 
            -
               | 
| 271 | 
            -
             | 
| 272 | 
            -
             | 
| 273 | 
            -
             | 
| 262 | 
            +
              static const int offset_list[NUM_OF_SYSTEMS];
         | 
| 263 | 
            +
             | 
| 264 | 
            +
              protected:
         | 
| 265 | 
            +
             | 
| 266 | 
            +
              mutable struct per_system_t {
         | 
| 267 | 
            +
                const SP3_Product<FloatT> *product;
         | 
| 268 | 
            +
                system_t sys;
         | 
| 269 | 
            +
              } per_system[NUM_OF_SYSTEMS];
         | 
| 270 | 
            +
             | 
| 271 | 
            +
              static typename GPS_Solver_Base<FloatT>::satellite_t select(
         | 
| 272 | 
            +
                  const void *ptr, const int &prn, const GPS_Time<FloatT> &receiver_time){
         | 
| 273 | 
            +
                const per_system_t *ptr_impl(reinterpret_cast<const per_system_t *>(ptr));
         | 
| 274 | 
            +
                return ptr_impl->product->select((prn & 0xFF) + offset_list[ptr_impl->sys], receiver_time);
         | 
| 275 | 
            +
              }
         | 
| 276 | 
            +
             | 
| 277 | 
            +
              public:
         | 
| 274 278 |  | 
| 275 279 | 
             
              /**
         | 
| 276 280 | 
             
               * push SP3 product to satellite selector
         | 
| @@ -281,19 +285,11 @@ static typename GPS_Solver_Base<FloatT>::satellite_t select_ ## sys( \ | |
| 281 285 | 
             
               */
         | 
| 282 286 | 
             
              template <class SelectorT>
         | 
| 283 287 | 
             
              bool push(SelectorT &slct, const system_t &sys = SYSTEM_GPS) const {
         | 
| 284 | 
            -
                 | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
             | 
| 288 | 
            -
             | 
| 289 | 
            -
                  case SYSTEM_GLONASS:  slct.impl_select = select_GLONASS;  break;
         | 
| 290 | 
            -
                  case SYSTEM_LEO:      slct.impl_select = select_LEO;      break;
         | 
| 291 | 
            -
                  case SYSTEM_GALILEO:  slct.impl_select = select_GALILEO;  break;
         | 
| 292 | 
            -
                  case SYSTEM_BEIDOU:   slct.impl_select = select_BEIDOU;   break;
         | 
| 293 | 
            -
                  case SYSTEM_IRNSS:    slct.impl_select = select_IRNSS;    break;
         | 
| 294 | 
            -
                  default: return false;
         | 
| 295 | 
            -
                }
         | 
| 296 | 
            -
                slct.impl = this;
         | 
| 288 | 
            +
                if(sys >= NUM_OF_SYSTEMS){return false;}
         | 
| 289 | 
            +
                per_system[sys].product = this;
         | 
| 290 | 
            +
                per_system[sys].sys = sys;
         | 
| 291 | 
            +
                slct.impl_select = select;
         | 
| 292 | 
            +
                slct.impl = &per_system[sys];
         | 
| 297 293 | 
             
                return true;
         | 
| 298 294 | 
             
              }
         | 
| 299 295 |  | 
| @@ -305,19 +301,19 @@ static typename GPS_Solver_Base<FloatT>::satellite_t select_ ## sys( \ | |
| 305 301 | 
             
                for(typename satellites_t::const_iterator
         | 
| 306 302 | 
             
                      it(satellites.begin()), it_end(satellites.end());
         | 
| 307 303 | 
             
                    it != it_end; ++it){
         | 
| 308 | 
            -
                  switch(it->first  | 
| 309 | 
            -
                    case  | 
| 304 | 
            +
                  switch((char)(it->first >> 8)){
         | 
| 305 | 
            +
                    case '\0': {
         | 
| 310 306 | 
             
                      int id(it->first & 0xFF);
         | 
| 311 307 | 
             
                      if(id < 100){++res.gps;}
         | 
| 312 308 | 
             
                      else if(id < 192){++res.sbas;}
         | 
| 313 309 | 
             
                      else{++res.qzss;}
         | 
| 314 310 | 
             
                      break;
         | 
| 315 311 | 
             
                    }
         | 
| 316 | 
            -
                    case  | 
| 317 | 
            -
                    case  | 
| 318 | 
            -
                    case  | 
| 319 | 
            -
                    case  | 
| 320 | 
            -
                    case  | 
| 312 | 
            +
                    case 'R': ++res.glonass;  break;
         | 
| 313 | 
            +
                    case 'L': ++res.leo;      break;
         | 
| 314 | 
            +
                    case 'E': ++res.galileo;  break;
         | 
| 315 | 
            +
                    case 'C': ++res.beidou;   break;
         | 
| 316 | 
            +
                    case 'I': ++res.irnss;    break;
         | 
| 321 317 | 
             
                    default: ++res.unknown; break;
         | 
| 322 318 | 
             
                  }
         | 
| 323 319 | 
             
                }
         | 
| @@ -335,6 +331,17 @@ const typename SP3_Product<FloatT>::per_satellite_t::interpolate_cnd_t | |
| 335 331 | 
             
              60 * 60 * 2,
         | 
| 336 332 | 
             
            };
         | 
| 337 333 |  | 
| 334 | 
            +
            template <class FloatT>
         | 
| 335 | 
            +
            const int SP3_Product<FloatT>::offset_list[NUM_OF_SYSTEMS] = {
         | 
| 336 | 
            +
              0, 0, 0, // GPS, SBAS, QZSS
         | 
| 337 | 
            +
              ((int)'R' << 8), // GLONASS
         | 
| 338 | 
            +
              ((int)'L' << 8), // LEO
         | 
| 339 | 
            +
              ((int)'E' << 8), // GALILEO
         | 
| 340 | 
            +
              ((int)'C' << 8), // BEIDOU
         | 
| 341 | 
            +
              ((int)'I' << 8), // IRNSS
         | 
| 342 | 
            +
            };
         | 
| 343 | 
            +
             | 
| 344 | 
            +
             | 
| 338 345 | 
             
            template <class FloatT>
         | 
| 339 346 | 
             
            class SP3_Reader {
         | 
| 340 347 | 
             
              protected:
         | 
| @@ -130,7 +130,7 @@ class QuaternionData : public QuaternionDataProperty<FloatT> { | |
| 130 130 | 
             
                 * @param q �R�s�[��
         | 
| 131 131 | 
             
                 */
         | 
| 132 132 | 
             
                QuaternionData(const self_t &q){
         | 
| 133 | 
            -
                  if(storage = q.storage){(storage->ref)++;}
         | 
| 133 | 
            +
                  if((storage = q.storage)){(storage->ref)++;}
         | 
| 134 134 | 
             
                }
         | 
| 135 135 |  | 
| 136 136 | 
             
                /**
         | 
| @@ -143,7 +143,7 @@ class QuaternionData : public QuaternionDataProperty<FloatT> { | |
| 143 143 | 
             
                self_t &operator=(const self_t &q){
         | 
| 144 144 | 
             
                  if(this == &q){return *this;}
         | 
| 145 145 | 
             
                  if(storage && ((--(storage->ref)) <= 0)){delete storage;}
         | 
| 146 | 
            -
                  if(storage = q.storage){(storage->ref)++;}
         | 
| 146 | 
            +
                  if((storage = q.storage)){(storage->ref)++;}
         | 
| 147 147 | 
             
                  return *this;
         | 
| 148 148 | 
             
                }
         | 
| 149 149 |  | 
| @@ -133,7 +133,7 @@ class Vector3Data : public Vector3DataProperty<FloatT> { | |
| 133 133 | 
             
                 * @param v �R�s�[��
         | 
| 134 134 | 
             
                 */
         | 
| 135 135 | 
             
                Vector3Data(const self_t &v){
         | 
| 136 | 
            -
                  if(storage = v.storage){(storage->ref)++;}
         | 
| 136 | 
            +
                  if((storage = v.storage)){(storage->ref)++;}
         | 
| 137 137 | 
             
                }
         | 
| 138 138 |  | 
| 139 139 | 
             
                /**
         | 
| @@ -146,7 +146,7 @@ class Vector3Data : public Vector3DataProperty<FloatT> { | |
| 146 146 | 
             
                self_t &operator=(const self_t &v){
         | 
| 147 147 | 
             
                  if(this == &v){return *this;}
         | 
| 148 148 | 
             
                  if(storage && ((--(storage->ref)) <= 0)){delete storage;}
         | 
| 149 | 
            -
                  if(storage = v.storage){(storage->ref)++;}
         | 
| 149 | 
            +
                  if((storage = v.storage)){(storage->ref)++;}
         | 
| 150 150 | 
             
                  return *this;
         | 
| 151 151 | 
             
                }
         | 
| 152 152 |  |