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 all commits
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
4 changes: 2 additions & 2 deletions guide/ch_astronomical_phenomena.tex
Original file line number Diff line number Diff line change
Expand Up @@ -991,10 +991,10 @@ \subsection{Lunar Eclipses}
of the Solar disk is occulted by Earth, this spot on the Lunar surface
will receive less sunlight and will appear darker when observed from
Earth. A rule of thumb says that 70\% of the Moon must enter the
Earth's penumbra before a light defect can be noted by attentive human
Earth's \indexterm{penumbra} (partial shadow) before a light defect can be noted by attentive human
observers.

The Earth's deep shadow is then much darker. As soon as an observer on
The Earth's \indexterm{umbra} (deep shadow) is then much darker. As soon as an observer on
the Lunar edge experiences a Total Solar eclipse, observers on Earth
see the begin of the partial eclipse.

Expand Down
Binary file removed guide/pictures/bt_hint.png
Binary file not shown.
Binary file added guide/pictures/bt_satellites_off.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified guide/pictures/satellites_plugin_configuration.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions guide/plg_catalogs.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1205,9 +1205,9 @@ \section{Satellites Plugin}
\label{fig:plugins:Satellites:Configuration}
\end{figure}

If the plugin has been enabled (see
\noindent If the plugin has been enabled (see
section~\ref{sec:Plugins:EnablingPlugins}), just click on the
Satellite button \guibutton{0.6}{bt_hint.png} on the bottom
Satellite button \guibutton{0.6}{bt_satellites_off.png} on the bottom
toolbar to display markers for the satellites, or use right click to call the GUI.

You can search for artificial satellites using
Expand All @@ -1220,10 +1220,10 @@ \section{Satellites Plugin}
the huge number of satellites in orbit, most of which are invisible to
the unaided eye.

You can display \newFeature{0.22.2} circles representing the Earth's
You can display\newFeature{0.22.2} circles representing the Earth's
shadow (penumbra and umbra, defined just like for Lunar eclipses, see
section~\ref{sec:Eclipses:lunar}), at the distance of the currently
selected satellite, or at a fixed (configurable) distance from Earth's surface.
section~\ref{sec:Eclipses:lunar}), at the altitude of the currently
selected satellite, or at a fixed (configurable) altitude from Earth's surface.

\subsection{Satellite Properties}
\label{sec:plugins:Satellites:properties}
Expand Down Expand Up @@ -1309,7 +1309,7 @@ \subsection{Satellite Properties}
\label{fig:plugins:Satellites:Configuration:SatellitesFilter}
\end{figure}

You can display \newFeature{0.22.2} a list of satellites by specific
You can display\newFeature{0.22.2} a list of satellites by specific
selection of their properties, when the filter ``[custom filter]'' has
been selected (Fig.~\ref{fig:plugins:Satellites:Configuration:SatellitesFilter}). The
settings of this filter are available through the button
Expand Down
76 changes: 72 additions & 4 deletions plugins/Satellites/src/Satellite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ QString Satellite::getInfoString(const StelCore *core, const InfoStringGroup& fl
//Visibility: Full text
oss << q_(visibilityDescription.value(visibility, "")) << "<br />";

if (!comms.isEmpty())
if (!comms.isEmpty() && (status!=Satellite::StatusNonoperational))
{
oss << q_("Radio communication") << ":<br/>";
for (const auto& c : comms)
Expand All @@ -469,7 +469,6 @@ QString Satellite::getInfoString(const StelCore *core, const InfoStringGroup& fl
QString Satellite::getCommLinkInfo(CommLink comm) const
{
QString commLinkData;

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

Expand Down Expand Up @@ -502,7 +501,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 +825,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 +888,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 +916,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
96 changes: 33 additions & 63 deletions plugins/Satellites/src/Satellites.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,11 @@ 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)
, lastSelectedSatellite(QString())
#if(SATELLITES_PLUGIN_IRIDIUM == 1)
, iridiumFlaresPredictionDepth(7)
Expand Down Expand Up @@ -228,7 +227,6 @@ void Satellites::init()
connect(core, SIGNAL(locationChanged(StelLocation)), this, SLOT(updateObserverLocation(StelLocation)));
connect(core, SIGNAL(configurationDataSaved()), this, SLOT(saveSettings()));
connect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(translateData()));
connect(ssystem, SIGNAL(earthShadowEnlargementDanjonChanged(bool)), this, SLOT(updateEarthShadowEnlargementFlag(bool)));

connect(this, SIGNAL(satSelectionChanged(QString)), this, SLOT(changeSelectedSatellite(QString)));

Expand Down Expand Up @@ -689,9 +687,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 +832,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 +926,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 +1905,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 +1921,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 +2850,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 +2861,26 @@ 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;


const double umbraDistance_AU = umbraData[0];
const double umbraRadius_AU = umbraData[1];
const double penumbraDistance_AU = umbraData[2];
const double penumbraRadius_AU = umbraData[3];
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 +2893,17 @@ 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."), 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
Loading
Loading