1 //==============================================================================
2 //
3 // This file is part of GPSTk, the GPS Toolkit.
4 //
5 // The GPSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GPSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GPSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2020, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38
39 /**
40 * @file PhaseWindup.cpp
41 * Implement computations of phase windup, solar ephemeris, satellite attitude
42 * and eclipse at the satellite.
43 */
44
45 // -----------------------------------------------------------------------------------
46 // GPSTk includes
47 #include "Matrix.hpp"
48 #include "GNSSconstants.hpp" // DEG_TO_RAD
49 // geomatics
50 #include "PhaseWindup.hpp"
51 #include "SunEarthSatGeometry.hpp"
52 #include "SolarPosition.hpp"
53 #include <math.h>
54
55 using namespace std;
56
57 namespace gpstk
58 {
59
60 // -----------------------------------------------------------------------------------
61 // Compute the phase windup, in cycles, given the time, the unit vector from receiver
62 // to transmitter, and the west and north unit vectors at the receiver, all in ECEF.
63 // YR is the West unit vector, XR is the North unit vector, at the receiver.
64 // shadow is the fraction of the sun's area not visible at the satellite.
65 // Previous value is needed to ensure continuity and prevent 1-cycle ambiguities.
PhaseWindup(double & prev,CommonTime & tt,Position & SV,Position & Rx2Tx,Position & YR,Position & XR,SolarSystem & SSEph,EarthOrientation & EO,double & shadow,bool isBlockR)66 double PhaseWindup(double& prev, // previous return value
67 CommonTime& tt, // epoch of interest
68 Position& SV, // satellite position
69 Position& Rx2Tx, // unit vector from receiver to satellite
70 Position& YR, // west unit vector at receiver
71 Position& XR, // north unit vector at receiver
72 SolarSystem& SSEph, // solar system ephemeris
73 EarthOrientation& EO, // earth orientation at tt
74 double& shadow, // fraction of sun not visible at satellite
75 bool isBlockR) // true for Block IIR satellites
76 {
77 try {
78 double d,windup;
79 Position DR,DT;
80 Position TR = -1.0 * Rx2Tx; // transmitter to receiver
81
82 // get satellite attitude
83 Position XT,YT,ZT;
84 Matrix<double> Att = SSEph.SatelliteAttitude(tt, SV);
85 XT = Position(Att(0,0),Att(0,1),Att(0,2)); // Cartesian is default
86 YT = Position(Att(1,0),Att(1,1),Att(1,2));
87 ZT = Position(Att(2,0),Att(2,1),Att(2,2));
88
89 // NB. Block IIR has X (ie the effective dipole orientation) in the -XT direction.
90 // Ref. Kouba(2009) GPS Solutions 13, pp1-12.
91 // In fact it should be a rotation by pi about Z, producing a constant offset.
92 //if(isBlockR)
93 //{
94 // XT = Position(-Att(0,0),-Att(0,1),-Att(0,2));
95 // YT = Position(-Att(1,0),-Att(1,1),-Att(1,2));
96 //}
97
98 // compute effective dipoles at receiver and transmitter
99 // Ref Kouba(2009) Using IGS Products; note sign diff. <=> East(ref) West(here)
100 // NB. switching second sign between the two eqns <=> overall sign windup
101 DR = XR - TR * TR.dot(XR) + Position(TR.cross(YR));
102 DT = XT - TR * TR.dot(XT) - Position(TR.cross(YT));
103
104 // normalize
105 d = 1.0/DR.mag();
106 DR = d * DR;
107 d = 1.0/DT.mag();
108 DT = d * DT;
109
110 windup = ::acos(DT.dot(DR)) / TWO_PI; // cycles
111 if (TR.dot(DR.cross(DT)) < 0.) windup *= -1.0;
112
113 // adjust by 2pi if necessary
114 d = windup-prev;
115 windup -= int(d + (d < 0.0 ? -0.5 : 0.5));
116
117 return windup;
118 }
119 catch(Exception& e) { GPSTK_RETHROW(e); }
120 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
121 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
122 }
123
124 // -----------------------------------------------------------------------------------
125 // Version without JPL solar system ephemeris - uses a lower quality solar position.
126 // Compute the phase windup, in cycles, given the time, the unit vector from receiver
127 // to transmitter, and the west and north unit vectors at the receiver, all in ECEF.
128 // YR is the West unit vector, XR is the North unit vector, at the receiver.
129 // shadow is the fraction of the sun's area not visible at the satellite.
PhaseWindup(double & prev,CommonTime & tt,Position & SV,Position & Rx2Tx,Position & YR,Position & XR,double & shadow,bool isBlockR)130 double PhaseWindup(double& prev, // previous return value
131 CommonTime& tt, // epoch of interest
132 Position& SV, // satellite position
133 Position& Rx2Tx, // unit vector from receiver to satellite
134 Position& YR, // west unit vector at receiver
135 Position& XR, // north unit vector at receiver
136 double& shadow, // fraction of sun not visible at satellite
137 bool isBlockR) // true for Block IIR satellites
138 {
139 try {
140 double d,windup=0.0;
141 Position DR,DT;
142 Position TR = -1.0 * Rx2Tx; // transmitter to receiver
143
144 // get satellite attitude
145 Position XT,YT,ZT,Sun;
146 double AR;
147 Sun = SolarPosition(tt,AR);
148 Matrix<double> Att = SatelliteAttitude(SV,Sun);
149 XT = Position(Att(0,0),Att(0,1),Att(0,2)); // Cartesian is default
150 YT = Position(Att(1,0),Att(1,1),Att(1,2));
151 ZT = Position(Att(2,0),Att(2,1),Att(2,2));
152
153 // NB. Block IIR has X (ie the effective dipole orientation) in the -XT direction.
154 // Ref. Kouba(2009) GPS Solutions 13, pp1-12.
155 if(isBlockR) XT = Position(-Att(0,0),-Att(0,1),-Att(0,2));
156
157 // compute effective dipoles at receiver and transmitter
158 // Ref Kouba(2009) Using IGS Products; note sign diff. <=> East(ref) West(here)
159 // NB. switching second sign between the two eqns <=> overall sign windup
160 DR = XR - TR * TR.dot(XR) + Position(TR.cross(YR));
161 DT = XT - TR * TR.dot(XT) - Position(TR.cross(YT));
162
163 // normalize
164 d = 1.0/DR.mag();
165 DR = d * DR;
166 d = 1.0/DT.mag();
167 DT = d * DT;
168
169 windup = ::acos(DT.dot(DR)) / TWO_PI;
170 if (TR.dot(DR.cross(DT)) < 0.) windup *= -1.0;
171
172 // adjust by 2pi if necessary
173 d = windup-prev;
174 windup -= int(d + (d < 0.0 ? -0.5 : 0.5));
175
176 return windup;
177 }
178 catch(Exception& e) { GPSTK_RETHROW(e); }
179 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
180 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
181 }
182
183
184 } // end namespace gpstk
185 //------------------------------------------------------------------------------------
186 //------------------------------------------------------------------------------------
187