// ----------------------------------------------------------------------------------- // Compute the satellite attitude, given the time and the satellite position SV. // Return a 3x3 Matrix which contains, as rows, the unit (ECEF) vectors X,Y,Z in the // body frame of the satellite, namely // Z = along the boresight (i.e. towards Earth center), // Y = perpendicular to both Z and the satellite-sun direction, and // X completing the orthonormal triad. X will generally point toward the sun. // Also return the shadow factor = fraction of sun's area not visible to satellite. Matrix<double> SatelliteAttitude(DayTime& tt, Position& SV, double& sf) { try { int i; double d,svrange,lat,lon,DistSun,Radsun,Radearth,dES; Position X,Y,Z,T; Matrix<double> R(3,3); // Z points from satellite to Earth center - along the antenna boresight Z = SV; Z.transformTo(Position::Cartesian); svrange = Z.mag(); d = -1.0/Z.mag(); Z = d * Z; // reverse and normalize Z // T points from satellite to sun SolarPosition(tt, lat, lon, DistSun, Radsun); Radsun *= DEG_TO_RAD; // angular radius of sun at satellite Radearth = ::asin(6378137.0/svrange); // angular radius of earth at sat T.setGeocentric(lat,lon,DistSun); // vector earth to sun T.transformTo(Position::Cartesian); T = T - SV; // sat to sun=(E to sun)-(E to sat) d = 1.0/T.mag(); T = d * T; // normalize T dES = ::acos(Z.dot(T)); // apparent angular distance, earth // to sun, as seen at satellite sf = shadowFactor(Radearth, Radsun, dES); // is satellite in eclipse? //if(sf > 0.999) { ; // total eclipse } //else if(sf > 0.0) { ; // partial eclipse } //else { ; // no eclipse } // Y is perpendicular to Z and T, such that ... Y = Z.cross(T); d = 1.0/Y.mag(); Y = d * Y; // normalize Y // ... X points generally in the direction of the sun X = Y.cross(Z); // X will be unit vector if(X.dot(T) < 0) { // need to reverse X, hence Y also X = -1.0 * X; Y = -1.0 * Y; } // fill the matrix and return it for(i=0; i<3; i++) { R(0,i) = X[i]; R(1,i) = Y[i]; R(2,i) = Z[i]; } return R; } catch(Exception& e) { GPSTK_RETHROW(e); } catch(exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); } catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); } }
// ----------------------------------------------------------------------------------- // Compute the satellite attitude, given the time and the satellite position SV. // If the SolarSystem is valid, use it; otherwise use SolarPosition. // See two versions of SatelliteAttitude() for the user interface. // Return a 3x3 Matrix which contains, as rows, the unit (ECEF) vectors X,Y,Z in the // body frame of the satellite, namely // Z = along the boresight (i.e. towards Earth center), // Y = perpendicular to both Z and the satellite-sun direction, and // X = completing the orthonormal triad. X will generally point toward the sun. // Thus this rotation matrix R * (ECEF XYZ vector) = components in body frame, and // R.transpose() * (sat. body. frame vector) = ECEF XYZ components. // Also return the shadow factor = fraction of sun's area not visible to satellite. Matrix<double> doSatAtt(const CommonTime& tt, const Position& SV, const SolarSystem& SSEph, const EarthOrientation& EO, double& sf) throw(Exception) { try { int i; double d,svrange,DistSun,AngRadSun,AngRadEarth,AngSeparation; Position X,Y,Z,T,S,Sun; Matrix<double> R(3,3); // Z points from satellite to Earth center - along the antenna boresight Z = SV; Z.transformTo(Position::Cartesian); svrange = Z.mag(); d = -1.0/Z.mag(); Z = d * Z; // reverse and normalize Z // get the Sun's position if(SSEph.JPLNumber() > -1) { //SolarSystem& mySSEph=const_cast<SolarSystem&>(SSEph); Sun = const_cast<SolarSystem&>(SSEph).WGS84Position(SolarSystem::Sun,tt,EO); } else { double AR; Sun = SolarPosition(tt, AR); } DistSun = Sun.radius(); // apparent angular radius of sun = 0.2666/distance in AU (deg) AngRadSun = 0.2666/(DistSun/149598.0e6); AngRadSun *= DEG_TO_RAD; // angular radius of earth at sat AngRadEarth = ::asin(6378137.0/svrange); // T points from satellite to sun T = Sun; // vector earth to sun T.transformTo(Position::Cartesian); S = SV; S.transformTo(Position::Cartesian); T = T - S; // sat to sun=(E to sun)-(E to sat) d = 1.0/T.mag(); T = d * T; // normalize T AngSeparation = ::acos(Z.dot(T)); // apparent angular distance, earth // to sun, as seen at satellite // is satellite in eclipse? try { sf = ShadowFactor(AngRadEarth, AngRadSun, AngSeparation); } catch(Exception& e) { GPSTK_RETHROW(e); } // Y is perpendicular to Z and T, such that ... Y = Z.cross(T); d = 1.0/Y.mag(); Y = d * Y; // normalize Y // ... X points generally in the direction of the sun X = Y.cross(Z); // X will be unit vector if(X.dot(T) < 0) { // need to reverse X, hence Y also X = -1.0 * X; Y = -1.0 * Y; } // fill the matrix and return it for(i=0; i<3; i++) { R(0,i) = X[i]; R(1,i) = Y[i]; R(2,i) = Z[i]; } return R; } catch(Exception& e) { GPSTK_RETHROW(e); } catch(exception& e) {Exception E("std except: "+string(e.what())); GPSTK_THROW(E);} catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); } }