shashwatak / satellite-js

Modular set of functions for SGP4 and SDP4 propagation of TLEs.
MIT License
911 stars 145 forks source link

What is a good way to determine if satellite is in sunlight? #58

Closed pkrasicki closed 9 months ago

pkrasicki commented 5 years ago

I need to know if a satellite is illuminated by the sun and possibly be able to estimate its brightness. I read that I would need to calculate phase angle between the satellite, observer and the sun. Does anyone know how to do that?

davidcalhoun commented 4 years ago

You can get part of this with a helper like https://github.com/Triggertrap/sun-js, though the times would be slightly different for a satellite because of its altitude. It may help to peek at some of the math there at least.

Not sure about how to determine brightness. Here's a list of the brightest satellites maintained by Celestrak: https://celestrak.com/NORAD/elements/visual.txt

The surface of the satellite is definitely a factor as well - the Iridium satellites have really reflective sufaces that lead to bright momentary flares: https://en.wikipedia.org/wiki/Satellite_flare#Iridium_flares (thought I guess this is different than overall brightness)

pkrasicki commented 4 years ago

Thanks for the answer! I've been stuck on this problem for a while. I'm making a free app for spotting the ISS https://github.com/pkrasicki/issviewer. Being able to know if ISS is illuminated is the key to make it usable for observations. It would be nice if satellite.js provided such feature. I'm using SunCalc https://github.com/mourner/suncalc library for getting sunrise/sunset times and position of the sun on the sky.

I haven't thought of doing it the way you are proposing :). I will try your idea and see if it works!

thkruz commented 4 years ago

Deleted my old comments that were not helpful. Here is the answer you are looking for:

Satellite in Sun Math: https://www.celestrak.com/columns/v03n01/

Angle Math in 3D: https://www.geeksforgeeks.org/find-all-angles-of-a-triangle-in-3d/

Dot Math in JS might be useful too: https://mathjs.org/docs/reference/functions/dot.html

pkrasicki commented 4 years ago

That's very helpful! I like this solution, but the problem is that it requires ECI coordinates. I can get them for a satellite from satellite.js. The Earth would be the center I assume? So (0, 0, 0)? The problem is getting ECI coordinates for the sun. SunCalc and sun.js don't seem to give those. SunCalc only gives azimuth and elevation.

thkruz commented 4 years ago

I calculated the az/el of the sun from lat 0 lon 0 height 0 and then converted it from RAE to ECI. The one gotcha is that you need to do the equations on CelesTrak using the satellite's position as 0,0,0. I just kept everything in ECI and subtracted the satellites position. Take a look at:

satellite.isInSun() in https://github.com/thkruz/keeptrack.space/blob/master/js/lookangles.js and sun.getXYZ() in https://github.com/thkruz/keeptrack.space/blob/master/js/sun.js

I am using https://github.com/Fabiz/MeeusJs to get the az/el of the sun because it seems more accurate than sunCalc, but you can convert from ra/dec too using sunCalc.

So far it works perfectly for me. I am sure someone with a degree in this stuff can show you a more efficient way, but its good enough for my purposes.

pkrasicki commented 4 years ago

For now I went with @davidcalhoun's idea, because it's easier to implement. It might be less accurate, but so far it's been working pretty well for ISS.

// this requires SunCalc from Git master branch. Version 1.8.0 doesn't let you provide the height
function isSunlit(date, lon, lat, heightMeters)
{
    const lonDeg = satellite.radiansToDegrees(lon);
    const latDeg = satellite.radiansToDegrees(lat);
    const sunTimes = SunCalc.getTimes(date, latDeg, lonDeg, heightMeters);

    // get time between sunset start and golden hour. When satellite height is used this time seems to work best
    let sunlightEnd = new Date((sunTimes.sunsetStart.getTime() + sunTimes.goldenHour.getTime()) / 2);
    if (date > sunTimes.dawn && date < sunlightEnd)
        return true;
    else
        return false;
}
thkruz commented 2 years ago

@ezze Recommend closing this since it has been answered.

louisjmorgan commented 2 years ago

this is how I do it using some THREE.js vector methods to simplify the maths:

const THREE = require('three');

const earthPosition = new THREE.Vector3(0, 0, 0);
const sunPosition = new THREE.Vector3();
const satPosition = new THREE.Vector3();
const sunEarth = new THREE.Vector3();
const sunSat = new THREE.Vector3();

function isEclipsed(satellite, sun) {
  sunPosition.fromArray([sun.x, sun.y, sun.z]);
  satPosition.fromArray([satellite.x, satellite.y, satellite.z]);

  sunEarth.subVectors(earthPosition, sunPosition);
  sunSat.subVectors(satPosition, earthPosition);

  const angle = sunEarth.angleTo(sunSat);

  const sunEarthDistance = sunPosition.distanceTo(earthPosition);
  const sunSatDistance = sunPosition.distanceTo(satPosition);
  const limbAngle = Math.atan2(earthRadius, sunEarthDistance);

  if (angle > limbAngle || sunSatDistance < sunEarthDistance) {
    return false;
  }
  return true;
}
thkruz commented 9 months ago

I will refer anyone still looking for this to:

https://github.com/thkruz/ootk-core/blob/87529d8326ddc475b51a0e42c61d7ba916ce3fd5/src/body/Sun.ts#L364C3-L388C4 and https://github.com/thkruz/ootk-core/blob/87529d8326ddc475b51a0e42c61d7ba916ce3fd5/src/body/Sun.ts#L493C1-L510C4

Sun calculations are outside the scope of satellite.js, so I am going to close this.