skyfielders / python-skyfield

Elegant astronomy for Python
MIT License
1.41k stars 211 forks source link

Unable to load TLE without name line #163

Closed Engineero closed 6 years ago

Engineero commented 6 years ago

When using load.tle(), it would be nice to add a check to either grab the first line as the satellite name (if three lines are provided per TLE), or just parse out the satellite ID and use that as the name if the list is only TLEs. For instance, if I download the latest TLE list from space-track.org (two-line elements, not three), to 'satcat.txt' and try to load.tle('./satcat.txt'), I get the following traceback:


AssertionError Traceback (most recent call last) /usr/local/lib/python3.6/site-packages/sgp4/io.py in twoline2rv(longstr1, longstr2, whichconst, afspc_mode) 130 try: --> 131 assert line.startswith('1 ') 132 satrec.satnum = int(line[2:7])

AssertionError:

During handling of the above exception, another exception occurred:

ValueError Traceback (most recent call last)

in () ----> 1 tles = load.tle('./satcat.txt') /usr/local/lib/python3.6/site-packages/skyfield/iokit.py in tle(self, url, reload) 195 """ 196 with self.open(url, reload=reload) as f: --> 197 return dict(parse_celestrak_tle(f)) 198 199 def open(self, url, mode='rb', reload=False): /usr/local/lib/python3.6/site-packages/skyfield/iokit.py in parse_celestrak_tle(fileobj) 336 line1 = next(lines).decode('ascii') 337 line2 = next(lines).decode('ascii') --> 338 sat = EarthSatellite(line1, line2, name) 339 yield name, sat 340 if ' (' in name: /usr/local/lib/python3.6/site-packages/skyfield/sgp4lib.py in __init__(self, line1, line2, name, ts) 79 def __init__(self, line1, line2, name=None, ts=None): 80 self.name = None if name is None else name.strip() ---> 81 sat = twoline2rv(line1, line2, whichconst=wgs72) 82 self.model = sat 83 if ts is None: /usr/local/lib/python3.6/site-packages/sgp4/io.py in twoline2rv(longstr1, longstr2, whichconst, afspc_mode) 151 # elnum = int(line[64:68]) 152 except (AssertionError, IndexError, ValueError): --> 153 raise ValueError(error_message.format(1, LINE1, line)) 154 155 line = longstr2.rstrip() ValueError: TLE format error The Two-Line Element (TLE) format was designed for punch cards and is therefore very strict about the position of every space and digit in a TLE line. Your line does not quite match. Here is the official format for line 1 followed by the line you provided: 1 NNNNNC NNNNNAAA NNNNN.NNNNNNNN +.NNNNNNNN +NNNNN-N +NNNNN-N N NNNNN 2 5 034.2535 260.6268 1847214 223.9179 119.9062 10.84801850115267

I know you can get the three-line elements from space-track.org, but sometimes I am working with TLE files that I have no control over and only use two lines per satellite (no ID).

If I have time I will try to implement this check and submit a pull request. Otherwise if somebody else gets to it first, I think it would be a nice improvement.

brandon-rhodes commented 6 years ago

It is expected that the link return "You must be logged in to complete this action" when I visit it?

Engineero commented 6 years ago

Yes, you need to create an account to view their data. The account is free if you want to check it out, but as an example, if you save the following two TLEs to a file and try to load it as shown, you will get that error:

1 29273U 06033B   18081.29838594 -.00000056 +00000-0 +00000-0 0  9993
2 29273 000.0189 154.5198 0004980 202.4902 284.9321 01.00271755042548
1 29274U 06033C   18081.39999693 +.00002637 +00000-0 +10299-2 0  9992
2 29274 005.9144 244.7152 6177908 248.3941 037.5897 03.74556424124616
brandon-rhodes commented 6 years ago

Thank you, that sample file will be perfect! I'll see what I can do.

brandon-rhodes commented 6 years ago

In the meantime, note that you can loop across the lines yourself and create Earth satellite objects with:

EarthSatellite(line1, line2)

In case that gets you moving again and not waiting for the next release!

Engineero commented 6 years ago

Thank you. I did get this direct implementation of the class constructor working for me, and just fed it the satellite ID for the name keyword argument. I would love to get the API solution working with 2-line and 3-line element sets though. I haven't had a chance to look at it yet, but I will try to look through the code and see if I can send you a pull request.

Engineero commented 6 years ago

See pull request #177

brandon-rhodes commented 6 years ago

Thanks, I'll go take a look at that pull request!

brandon-rhodes commented 6 years ago

(Fixed by #177.)