brandon-rhodes / pyephem

Scientific-grade astronomy routines for Python
Other
783 stars 121 forks source link

ephem.Observer.next_pass ignores the horizon parameter #247

Closed lpmrfentazis closed 1 year ago

lpmrfentazis commented 2 years ago

Hi! I am writing a shell for pyephem, making it look like pyorbital, and I ran into such a problem that for some reason the Horizon parameter does not work for me, no matter what I equate it to, when I run next_pass, I will get spans from a height of ~ 0 deg. I probably misunderstand something, but I can't figure out what it is.

Code: ` class Orbital: """ A class simulating an orbital one.orbital.Orbital, but based on Piefem. Solves the problem of "Calculations in deep space are not supported" when calculating high orbits, such as the ARKTIKA M1

    The *satellite* parameter is the name of the satellite to work on and is
    used to retrieve the right TLE data for internet or from *tle_file* in case
    it is provided.

    In:
        satellite: str
        tle_file: str
        line1: str
        line2: str
"""

def __init__(self, satellite: str, tle_file: str = None, line1: str = None, line2: str = None) -> None:
    self.satelliteName: str = satellite.upper()
    self._line1: str = None
    self._line2: str = None

    if line1 is not None and line2 is not None:
        self._line1 = line1.strip()
        self._line2 = line2.strip()
        self.tle =  ephem.readtle(self.satelliteName, self._line1, self._line2)

    else:
        if tle_file:
            with open(tle_file, 'r') as f:
                lines = f.readlines()
                for i in range(len(lines)):
                    # if Satellite founded in tle file and line1 and line2 exist
                    if self.satelliteName in lines[i] and (len(lines) - i >= 2):
                        self._line1 = lines[i+1].strip()
                        self._line2 = lines[i+2].strip()

                        self.tle =  ephem.readtle(self.satelliteName, self._line1, self._line2)

                        break

        if not self.tle:
            raise KeyError(f"Found no TLE entry for {satellite}")

    self._checksum()

def _checksum(self):
    """Calculate checksum for the current TLE."""
    for line in [self._line1, self._line2]:
        check = 0
        for char in line[:-1]:
            if char.isdigit():
                check += int(char)
            if char == "-":
                check += 1

        if (check % 10) != int(line[-1]):
            raise ChecksumError(self.satelliteName + " " + line)

def get_observer_look(self, utc_time: datetime, lon: float, lat: float, alt: float) -> Tuple[float, float]:
    """
        Calculate observers look angle to a satellite.

        In:
            utc_time: datetime Observation time
            lon: float Longitude of observer position on ground in degrees east
            lat: float Latitude of observer position on ground in degrees north
            alt: float Altitude above sea-level (geoid) of observer position on ground in km
        Out:
            Azimuth: float
            Elevation: float
    """

    obs = ephem.Observer()
    obs.lat = str(lat)
    obs.lon = str(lon)
    obs.date = utc_time.strftime("%Y/%m/%d %H:%M:%S")

    self.tle.compute(obs)

    azimuth: float = self.tle.az
    elevation: float = self.tle.alt

    return azimuth / pi * 180.0 , elevation / pi * 180.0

def get_next_passes(self, utc_time: datetime, length: int, lon: float, lat: float, alt: float, tol: float=0.001, horizon: int=0):
    """
        Calculate passes for the next hours for a given start time and a
        given observer.

        Original by Martin.
        In:
            utc_time: datetime Observation time
            length: int Number of hours to find passes
            lon: float Longitude of observer position on ground
            lat: float Latitude of observer position on ground
            alt: float Altitude above sea-level (geoid) of observer position on ground
            tol: float precision of the result in seconds
            horizon: int the elevation of horizon to compute risetime and falltime.

        Out:
            [(rise-time, fall-time, max-elevation-time), ...]
    """

    obs = ephem.Observer()
    obs.lat = ephem.degrees(str(lat))
    obs.lon = ephem.degrees(str(lon))
    obs.elevation = 1000*alt
    obs.horizon = ephem.degrees(horizon)
    obs.date = ephem.Date(utc_time.strftime("%Y/%m/%d %H:%M:%S"))

    ... 

    return obs.next_pass(self.tle)

def get_lonlatalt(self, utc_time: datetime) -> Tuple[float, float, float]:
    self.tle.compute(utc_time.strftime("%Y/%m/%d %H:%M:%S"))
    return self.tle.sublong / pi * 180.0, self.tle.sublat / pi * 180.0, self.tle.elevation

def __str__(self) -> str:
    return self.satelliteName + " " + str(self.tle)

if name == "main": orb = Orbital("NOAA 19", "./lorettOrbital/tle/tle.txt")

porb = OldOrbital("NOAA 19", "./lorettOrbital/tle/tle.txt")

t = orb.get_next_passes(datetime.utcnow(), length=24, lat=55.671226, lon=37.625304, alt=0.16, horizon=55)[0::2]

for i in t:
    print(ephem.Date(i), end=" ")

    time = datetime.strptime(str(ephem.Date(i)), "%Y/%m/%d %H:%M:%S")
    print(orb.get_observer_look(time, lat=55.671226, lon=37.625304, alt=0.16), end=" ")

    print()

print(t)`

Result: ` 2022/11/17 16:51:03 (166.82481598681184, -0.010533880925298653)

2022/11/17 16:59:04 (254.87394570960512, 73.19512118379468)

2022/11/17 17:07:06 (342.685425830417, -0.005461666304415813)

(44881.20212112983, 44881.207682768945, 44881.213262047066) `