Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Satellites: Restore shadow circle at arbitrary altitude #3538

Merged
merged 4 commits into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 74 additions & 3 deletions plugins/Satellites/src/Satellite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,10 @@ QString Satellite::getInfoString(const StelCore *core, const InfoStringGroup& fl

QString Satellite::getCommLinkInfo(CommLink comm) const
{
QString commLinkData;
if (status==Satellite::StatusNonoperational)
return QString();

QString commLinkData;
if (!comm.modulation.isEmpty()) // OK, the signal modulation mode is exist
commLinkData = comm.modulation;

Expand Down Expand Up @@ -502,7 +504,6 @@ QString Satellite::getCommLinkInfo(CommLink comm) const
sign='+';

commLinkData.append(QString(": %1 %2 (%3%4 %5)<br />").arg(QString::number(comm.frequency, 'f', 3), qc_("MHz", "frequency"), sign, QString::number(ddop, 'f', 3), qc_("kHz", "frequency")));

return commLinkData;
}

Expand Down Expand Up @@ -827,7 +828,7 @@ void Satellite::update(double)
perigee = pa[0];
apogee = pa[1];
*/
if (height < 100) // below Kármán line: Satellite is certainly lost, at least TLE not applicable.
if (height < 80) // way below Kármán line: Satellite is certainly lost, at least TLE not applicable.
{
// The orbit is no longer valid. Causes include very out of date
// TLE, system date and time out of a reasonable range, and orbital
Expand Down Expand Up @@ -890,6 +891,7 @@ Vec4d Satellite::getUmbraData()
penumbraDistance=rhoE*cos(muP);
// radius of shadow circle
penumbraRadius=rhoE*sin(muP);
//// DBG out
//StelObjectMgr *om=GETSTELMODULE(StelObjectMgr);
//om->setExtraInfoString(StelObject::DebugAid, QString("&rho;<sub>E</sub> %1, r<sub>S</sub> %2, &theta;<sub>E</sub> %3°, &theta;<sub>S</sub> %4° <br/>")
// .arg(QString::number(rhoE, 'f', 3),
Expand Down Expand Up @@ -917,6 +919,75 @@ Vec4d Satellite::getUmbraData()
return Vec4d(umbraDistance, umbraRadius, penumbraDistance, penumbraRadius);
}

//! Get radii and geocentric distances of shadow circles in km for a hypothetical object in dist_km above the (spherical) Earth.
//! Vec4d(umbraDistance, umbraRadius, penumbraDistance, penumbraRadius);
Vec4d Satellite::getUmbraData(double dist_km)
{
static PlanetP earth=GETSTELMODULE(SolarSystem)->getEarth();
static PlanetP sun = GETSTELMODULE(SolarSystem)->getSun();

// Compute altitudes of umbra and penumbra circles. These should show where the satellite enters/exits umbra/penumbra.
// The computation follows ideas from https://celestrak.org/columns/v03n01/
// These sources mention ECI coordinates (Earth Centered Inertial). Presumably TEME (True Equator Mean Equinox) are equivalent, at least for our purposes.
const double rhoE=earth->getEquatorialRadius()*AU+dist_km; // geocentric Satellite distance, km
const double rS=earth->getHeliocentricEclipticPos().norm()*AU; // distance earth...sun
const double thetaE=asin((earth->getEquatorialRadius()*AU)/(rhoE));
// Accurate distance sat...sun from ECI sunpos
//Vec3d sunTEME=pSatWrapper->getSunECIPos() - pSatWrapper->getObserverECIPos(); // km
Vec3d sunEquinoxEqPos = sun->getEquinoxEquatorialPos(StelApp::getInstance().getCore());
Vec3d sunTEME=sunEquinoxEqPos*AU;
const double thetaS=asin((sun->getEquatorialRadius()*AU)/(sunTEME.norm()));
Q_ASSERT(thetaE>thetaS);
const double theta=thetaE-thetaS; // angle so that satellite dives into umbra
// angle at Sun:
const double sigma=asin(sin(theta)*rhoE/rS);
// angle in geocenter
const double eta=M_PI-sigma-theta;
// complement
const double mu=M_PI-eta;
// geocentric distance of shadow circle towards antisun
double umbraDistance=rhoE*cos(mu);
// radius of shadow circle
double umbraRadius=rhoE*sin(mu);
// Repeat for penumbra
const double thetaP=thetaE+thetaS; // angle so that satellite touches penumbra
// angle at Sun:
const double sigmaP=asin(sin(thetaP)*rhoE/rS);
// angle in geocenter
const double etaP=M_PI-sigmaP-thetaP;
// complement
const double muP=M_PI-etaP;
// geocentric distance of shadow circle towards antisun
double penumbraDistance=rhoE*cos(muP);
// radius of shadow circle
double penumbraRadius=rhoE*sin(muP);
//// DBG OUT
//StelObjectMgr *om=GETSTELMODULE(StelObjectMgr);
//om->setExtraInfoString(StelObject::DebugAid, QString("&rho;<sub>E</sub> %1, r<sub>S</sub> %2, &theta;<sub>E</sub> %3°, &theta;<sub>S</sub> %4° <br/>")
// .arg(QString::number(rhoE, 'f', 3),
// QString::number(rS, 'f', 3),
// QString::number(thetaE*M_180_PI, 'f', 3),
// QString::number(thetaS*M_180_PI, 'f', 3)
// )
// );
//om->addToExtraInfoString(StelObject::DebugAid, QString("&theta; %1°, &sigma; %2°, &eta; %3°, &mu; %4° <br/>")
// .arg(
// QString::number(theta*M_180_PI, 'f', 3),
// QString::number(sigma*M_180_PI, 'f', 3),
// QString::number(eta*M_180_PI, 'f', 3),
// QString::number(mu*M_180_PI, 'f', 3)
// )
// );
//om->addToExtraInfoString(StelObject::DebugAid, QString("&theta;<sub>P</sub> %1°, &sigma; %2°, &eta; %3°, &mu; %4° <br/>")
// .arg(
// QString::number(thetaP*M_180_PI, 'f', 3),
// QString::number(sigmaP*M_180_PI, 'f', 3),
// QString::number(etaP*M_180_PI, 'f', 3),
// QString::number(muP*M_180_PI, 'f', 3)
// )
// );
return Vec4d(umbraDistance, umbraRadius, penumbraDistance, penumbraRadius);
}

double Satellite::getDoppler(double freq) const
{
Expand Down
4 changes: 4 additions & 0 deletions plugins/Satellites/src/Satellite.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ class Satellite : public StelObject
//! Vec4d(umbraDistance, umbraRadius, penumbraDistance, penumbraRadius);
Vec4d getUmbraData();

//! Get radii and geocentric distances of shadow circles in km for a hypothetical object in dist_km above the (spherical) Earth.
//! Vec4d(umbraDistance, umbraRadius, penumbraDistance, penumbraRadius);
static Vec4d getUmbraData(double dist_km);

//! Get operational status of satellite
QString getOperationalStatus() const;

Expand Down
102 changes: 42 additions & 60 deletions plugins/Satellites/src/Satellites.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ Satellites::Satellites()
, autoRemoveEnabled(false)
, updateFrequencyHours(0)
, flagUmbraVisible(false)
, flagUmbraAtFixedDistance(false)
, flagUmbraAtFixedAltitude(false)
, umbraColor(1.0f, 0.0f, 0.0f)
, fixedUmbraDistance(1000.0)
, fixedUmbraAltitude(1000.0)
, flagPenumbraVisible(false)
, penumbraColor(1.0f, 0.0f, 0.0f)
, earthShadowEnlargementDanjon(false)
Expand Down Expand Up @@ -689,9 +689,9 @@ void Satellites::restoreDefaultSettings()
conf->setValue("hide_invisible_satellites", false);
conf->setValue("colored_invisible_satellites", true);
conf->setValue("umbra_flag", false);
conf->setValue("umbra_fixed_distance_flag", false);
conf->setValue("umbra_fixed_altitude_flag", false);
conf->setValue("umbra_color", "1.0,0.0,0.0");
conf->setValue("umbra_fixed_distance", 1000.0);
conf->setValue("umbra_fixed_altitude", 1000.0);
conf->setValue("penumbra_flag", false);
conf->setValue("penumbra_color", "1.0,0.0,0.0");
conf->setValue("cf_magnitude_flag", false);
Expand Down Expand Up @@ -834,11 +834,9 @@ void Satellites::loadSettings()

// umbra/penumbra
setFlagUmbraVisible(conf->value("umbra_flag", false).toBool());
// FIXME: Repair the functionality!
setFlagUmbraAtFixedDistance(false);
//setFlagUmbraAtFixedDistance(conf->value("umbra_fixed_distance_flag", false).toBool());
setFlagUmbraAtFixedAltitude(conf->value("umbra_fixed_altitude_flag", false).toBool());
setUmbraColor(Vec3f(conf->value("umbra_color", "1.0,0.0,0.0").toString()));
setUmbraDistance(conf->value("umbra_fixed_distance", 1000.0).toDouble());
setUmbraAltitude(conf->value("umbra_fixed_altitude", 1000.0).toDouble());
setFlagPenumbraVisible(conf->value("penumbra_flag", false).toBool());
setPenumbraColor(Vec3f(conf->value("penumbra_color", "1.0,0.0,0.0").toString()));

Expand Down Expand Up @@ -930,11 +928,9 @@ void Satellites::saveSettingsToConfig()

// umbra/penumbra
conf->setValue("umbra_flag", getFlagUmbraVisible());
// FIXME: Fix and re-enable this function
//conf->setValue("umbra_fixed_distance_flag", getFlagUmbraAtFixedDistance());
conf->setValue("umbra_fixed_distance_flag", false); // Preliminary
conf->setValue("umbra_fixed_altitude_flag", getFlagUmbraAtFixedAltitude());
conf->setValue("umbra_color", getUmbraColor().toStr());
conf->setValue("umbra_fixed_distance", getUmbraDistance());
conf->setValue("umbra_fixed_altitude", getUmbraAltitude());
conf->setValue("penumbra_flag", getFlagPenumbraVisible());
conf->setValue("penumbra_color", getPenumbraColor().toStr());

Expand Down Expand Up @@ -1911,18 +1907,14 @@ void Satellites::setFlagUmbraVisible(bool b)
}
}

void Satellites::setFlagUmbraAtFixedDistance(bool b)
void Satellites::setFlagUmbraAtFixedAltitude(bool b)
{
flagUmbraAtFixedDistance = false;
qDebug() << "setFlagUmbraAtFixedDistance() currently not possible";

// TO BE FIXED
//if (flagUmbraAtFixedDistance != b)
//{
// flagUmbraAtFixedDistance = b;
// emit settingsChanged(); // GZ IS THIS REQUIRED/USEFUL??
// emit flagUmbraAtFixedDistanceChanged(b);
//}
if (flagUmbraAtFixedAltitude != b)
{
flagUmbraAtFixedAltitude = b;
emit settingsChanged(); // GZ IS THIS REQUIRED/USEFUL??
emit flagUmbraAtFixedAltitudeChanged(b);
}
}

void Satellites::setUmbraColor(const Vec3f &c)
Expand All @@ -1931,10 +1923,10 @@ void Satellites::setUmbraColor(const Vec3f &c)
emit umbraColorChanged(c);
}

void Satellites::setUmbraDistance(double d)
void Satellites::setUmbraAltitude(double d)
{
fixedUmbraDistance = d;
emit umbraDistanceChanged(d);
fixedUmbraAltitude = d;
emit umbraAltitudeChanged(d);
}

void Satellites::setFlagPenumbraVisible(bool b)
Expand Down Expand Up @@ -2860,7 +2852,7 @@ void Satellites::drawCircles(StelCore* core, StelPainter &painter)
painter.setLineSmooth(true);
painter.setFont(labelFont);

double lambda, beta, umbraDistance_AU, umbraRadius_AU, penumbraDistance_AU, penumbraRadius_AU;
double lambda, beta;
const Vec3d pos = earth->getEclipticPos();
const Vec3d dir = - sun->getAberrationPush() + pos;
StelUtils::rectToSphe(&lambda, &beta, dir);
Expand All @@ -2871,47 +2863,35 @@ void Satellites::drawCircles(StelCore* core, StelPainter &painter)
if (!newSelected.empty())
sat = getById(newSelected[0].staticCast<Satellite>()->getCatalogNumberString());

if (flagUmbraAtFixedDistance)
Vec4d umbraData;
if (flagUmbraAtFixedAltitude)
{
umbraDistance_AU = penumbraDistance_AU = fixedUmbraDistance/AU+earth->getEquatorialRadius(); // geocentric circle distance [AU]
const double earthDistance=earth->getHeliocentricEclipticPos().norm(); // Earth distance [AU]
const double sunHP = asin(earth->getEquatorialRadius()/earthDistance) * (M_180_PI*3600.); // arcsec.
const double satHP = asin(earth->getEquatorialRadius()/umbraDistance_AU) * (M_180_PI*3600.); // arcsec.
const double sunSD = atan(sun->getEquatorialRadius()/earthDistance) * (M_180_PI*3600.); // arcsec.

//Classical Bessel elements
double f1, f2;
if (earthShadowEnlargementDanjon)
{
static const double danjonScale=1+1./85.-1./594.; // ~1.01, shadow magnification factor (see Espenak 5000 years Canon)
f1=danjonScale*satHP + sunHP + sunSD; // penumbra radius, arcsec
f2=danjonScale*satHP + sunHP - sunSD; // umbra radius, arcsec
}
else
{
const double mHP1=0.998340*satHP;
f1=1.02*(mHP1 + sunHP + sunSD); // penumbra radius, arcsec
f2=1.02*(mHP1 + sunHP - sunSD); // umbra radius, arcsec
}
penumbraRadius_AU=tan(f1/3600.*M_PI_180)*umbraDistance_AU;
umbraRadius_AU=tan(f2/3600.*M_PI_180)*umbraDistance_AU;
umbraData=Satellite::getUmbraData(fixedUmbraAltitude)/AU;
}
else if (!sat.isNull())
{
Vec4d umbraData=sat->getUmbraData();
umbraDistance_AU = umbraData[0]/AU;
umbraRadius_AU = umbraData[1]/AU;
penumbraDistance_AU = umbraData[2]/AU;
penumbraRadius_AU = umbraData[3]/AU;
umbraData=sat->getUmbraData()/AU;
}
else
return;


double shadowScale=1.02;
if (earthShadowEnlargementDanjon)
{
shadowScale = 1.+1./85.-1./594.; // ~1.01, shadow magnification factor (see Espenak 5000 years Canon)
}
// FIXME: Any shadow enlargement here contradicts visibility computations in the main model.
shadowScale = 1.;

const double umbraDistance_AU = umbraData[0];
const double umbraRadius_AU = umbraData[1] * shadowScale;
const double penumbraDistance_AU = umbraData[2];
const double penumbraRadius_AU = umbraData[3] * shadowScale;
StelVertexArray umbra(StelVertexArray::LineLoop);
for (int i=0; i<360; ++i)
for (int i=0; i<4*360; ++i)
{
Vec3d point(umbraDistance_AU, cos(i*M_PI_180)*umbraRadius_AU, sin(i*M_PI_180)*umbraRadius_AU);
Vec3d point(umbraDistance_AU, cos(i*M_PI_180*0.25)*umbraRadius_AU, sin(i*M_PI_180*0.25)*umbraRadius_AU);
rot.transfo(point);
umbra.vertex.append(pos+point);
}
Expand All @@ -2924,16 +2904,18 @@ void Satellites::drawCircles(StelCore* core, StelPainter &painter)
rot.transfo(point);
Vec3d coord = pos+point;
painter.drawSprite2dMode(coord, 5.f);
QString cuLabel = QString("%1 (h=%2 %3)").arg(q_("C.U."), QString::number(AU*(umbraDistance_AU - earth->getEquatorialRadius()), 'f', 1), qc_("km","distance"));
QString number = QString::number( (getFlagUmbraAtFixedAltitude() ? getUmbraAltitude() : sat->latLongSubPointPosition[2] ), 'f', 1);
//QString cuLabel = QString("%1 (h=%2 %3)").arg(q_("C.U."), QString::number(AU*(umbraDistance_AU - earth->getEquatorialRadius()), 'f', 1), qc_("km","distance"));
QString cuLabel = QString("%1 (h=%2 %3)").arg(q_("C.U."), number, qc_("km","distance"));
const float shift = 8.f;
painter.drawText(coord, cuLabel, 0, shift, shift, false);

if (getFlagPenumbraVisible())
{
StelVertexArray penumbra(StelVertexArray::LineLoop);
for (int i=0; i<360; ++i)
for (int i=0; i<4*360; ++i)
{
Vec3d point(penumbraDistance_AU, cos(i*M_PI_180)*penumbraRadius_AU, sin(i*M_PI_180)*penumbraRadius_AU);
Vec3d point(penumbraDistance_AU, cos(i*M_PI_180*0.25)*penumbraRadius_AU, sin(i*M_PI_180*0.25)*penumbraRadius_AU);
rot.transfo(point);
penumbra.vertex.append(pos+point);
}
Expand Down
26 changes: 12 additions & 14 deletions plugins/Satellites/src/Satellites.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ class Satellites : public StelObjectModule
Q_PROPERTY(Vec3f invisibleSatelliteColor READ getInvisibleSatelliteColor WRITE setInvisibleSatelliteColor NOTIFY invisibleSatelliteColorChanged)
Q_PROPERTY(Vec3f transitSatelliteColor READ getTransitSatelliteColor WRITE setTransitSatelliteColor NOTIFY transitSatelliteColorChanged)
Q_PROPERTY(bool flagUmbraVisible READ getFlagUmbraVisible WRITE setFlagUmbraVisible NOTIFY flagUmbraVisibleChanged)
Q_PROPERTY(bool flagUmbraAtFixedDistance READ getFlagUmbraAtFixedDistance WRITE setFlagUmbraAtFixedDistance NOTIFY flagUmbraAtFixedDistanceChanged)
Q_PROPERTY(double umbraDistance READ getUmbraDistance WRITE setUmbraDistance NOTIFY umbraDistanceChanged)
Q_PROPERTY(bool flagUmbraAtFixedAltitude READ getFlagUmbraAtFixedAltitude WRITE setFlagUmbraAtFixedAltitude NOTIFY flagUmbraAtFixedAltitudeChanged)
Q_PROPERTY(double umbraAltitude READ getUmbraAltitude WRITE setUmbraAltitude NOTIFY umbraAltitudeChanged)
Q_PROPERTY(Vec3f umbraColor READ getUmbraColor WRITE setUmbraColor NOTIFY umbraColorChanged)
Q_PROPERTY(bool flagPenumbraVisible READ getFlagPenumbraVisible WRITE setFlagPenumbraVisible NOTIFY flagPenumbraVisibleChanged)
Q_PROPERTY(Vec3f penumbraColor READ getPenumbraColor WRITE setPenumbraColor NOTIFY penumbraColorChanged)
Expand Down Expand Up @@ -435,9 +435,9 @@ class Satellites : public StelObjectModule
void invisibleSatelliteColorChanged(Vec3f);
void transitSatelliteColorChanged(Vec3f);
void flagUmbraVisibleChanged(bool b);
void flagUmbraAtFixedDistanceChanged(bool b);
void flagUmbraAtFixedAltitudeChanged(bool b);
void umbraColorChanged(Vec3f);
void umbraDistanceChanged(double d);
void umbraAltitudeChanged(double d);
void flagPenumbraVisibleChanged(bool b);
void penumbraColorChanged(Vec3f);
void flagCFKnownStdMagnitudeChanged(bool b);
Expand Down Expand Up @@ -611,11 +611,10 @@ public slots:
void setFlagUmbraVisible(bool b);
bool getFlagUmbraVisible() { return flagUmbraVisible; }

//! Set whether ring of Earth's umbra should be displayed at fixed distance.
//! Set whether ring of Earth's umbra should be displayed at given satellite altitude.
//! Emits settingsChanged() if the value changes.
//! V23.1: For now this had to be disabled/set to false.
void setFlagUmbraAtFixedDistance(bool b);
bool getFlagUmbraAtFixedDistance() { return flagUmbraAtFixedDistance; }
void setFlagUmbraAtFixedAltitude(bool b);
bool getFlagUmbraAtFixedAltitude() { return flagUmbraAtFixedAltitude; }

//! Get color for ring of Earth's umbra
//! @return color
Expand All @@ -625,9 +624,9 @@ public slots:

//! Get the fixed distance for center of visualized Earth's umbra
//! @return distance, km
double getUmbraDistance() { return fixedUmbraDistance; }
double getUmbraAltitude() { return fixedUmbraAltitude; }
//! Set the fixed distance for center of visualized Earth's umbra
void setUmbraDistance(double d);
void setUmbraAltitude(double d);

//! Set whether ring of Earth's penumbra should be displayed.
//! Emits settingsChanged() if the value changes.
Expand Down Expand Up @@ -916,12 +915,11 @@ private slots:
//@{
//! Flag enabling visualization the Earth's umbra.
bool flagUmbraVisible;
//! Flag enabling visualization the Earth's umbra at fixed distance
//! V23.1: This had to be disabled until computation will be implemented correctly.
bool flagUmbraAtFixedDistance; // MUST REMAIN false FOR NOW!
//! Flag enabling visualization the Earth's umbra at a given altitude above a spherical Earth
bool flagUmbraAtFixedAltitude;
Vec3f umbraColor;
//! The distance for center of visualized Earth's umbra in kilometers
double fixedUmbraDistance;
double fixedUmbraAltitude;
//! Flag enabling visualization the Earth's penumbra.
bool flagPenumbraVisible;
Vec3f penumbraColor;
Expand Down
Loading
Loading