Giter VIP home page Giter VIP logo

libpredict's Introduction

libpredict

A satellite orbit prediction library.

Building

We recommend using out-of-source builds.

cd $SOURCEDIR
mkdir build
cd build
cmake ..
make

Installation

make install

The install location is defined by CMAKE_INSTALL_PREFIX, which defaults to /usr/local. To relocate the whole installation (to make usr/local etc. inside another directory, e.g., if you want to make a tarball or package it afterwards), use make DESTDIR=/foo/bar install.

Linking

The library comes with pkg-config information, so the include and library paths and flags can be found using the pkg-config command or by using the PKG_CHECK_MODULES autotools macro or CMake command.

Quickstart

We recommend to investigate the examples under examples/ and the API documentation in include/predict/predict.h.

A condensed version is that

predict_orbital_elements_t *orbital_elements = orbital_elements = predict_parse_tle(tle_line_1, tle_line_2);

parses a TLE in the form of two char arrays to orbital elements representing a satellite, and that

predict_observer_t *observer = predict_create_observer(name, latitude_radians, longitude_radians, altitude_meters);

defines a QTH for observation. For prediction,

struct predict_position orbit;
predict_orbit(orbital_elements, &orbit, prediction_time);

can be used to calculate properties that are independent of an observer (longitude, latitude, ...), while

struct predict_observation observation;
predict_observe_orbit(observer, &orbit, &observation);

will convert to properties that will be relative to our observer (azimuth, elevation, ...).

License

Copyright 1991-2006 John A. Magliacane (KD2BD)

Copyright 2013- Akademisk radioklubb (LA1K)

Copyright 2013-2015 Knut Magnus Kvamtrø (LA3DPA)

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

libpredict's People

Contributors

bjorgan avatar kvamtroe avatar nickoe avatar ryeng avatar thenorthcore avatar thomasing avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libpredict's Issues

predict_next_aos() is trapped in infinite loop for specific set of input

predict_next_aos() is trapped in an infinite loop at observer:c:429. Might have to do something about the robustness of the numerical approach.

Reproduce by:

TLE (AGILE):

1 31135U 07013A   16016.34541367  .00004770  00000-0  13362-3 0  9997
2 31135   2.4662 174.4370 0014287 235.3415 124.5292 15.27068958484334

Daynum:
13167.671296

Qth:
Latitude: 209 degrees north
Longitude: 10 degrees east
Altitude: 0

Prediction of maximum elevation

Being able to calculate the maximum elevation of a pass could be useful: la1k/flyby#47, la1k/flyby#46. Function proposal:

/**
 * Predict time of maximum elevation of the current or next pass after start_time.
 * 
 * \param observer QTH coordinates
 * \param orbital_elements Orbital elements of satellite
 * \param start_time Start time from which to search for/identify the next pass
 * \return Time of maximum elevation
 **/
predict_julian_date_t predict_max_elevation(const predict_observer_t *observer, const predict_orbital_elements_t *orbital_elements, predict_julian_date_t start_time);

The maximum is bracketed by the numbers obtained from predict_next_aos() and predict_next_los() if start_time is not during a pass. If we are during the middle of a pass, the maximum could be before start_time.

The elevation function is well-behaved unless the satellite is geostationary or decayed. Find some numerical method for finding the maximum. Could also be aided by the elevation_rate-property in struct predict_observation, but note that the first derivative in some cases can be discontinuous or near discontinuous at the peak (when max elevation approaches 90 degrees). Numerical accuracy can be tested in the test framework by checking the elevation rate and other parameters, and by moving to each side of the predicted maximum.

Might probably first be implemented in flyby for quick solving of the mentioned issues, and could then be moved over to libpredict.

Not sure if "predict_max_elevation" is a name that will be descriptive enough for its purpose.

Revisiting spacetrack report #3 and more recent version of SGP4

More recent, official version of SGP4 is available (https://celestrak.com/publications/AIAA/2006-6753/).

We should replace our internal FORTRAN-derived SGP4/SDP4-code with the code found above, as unmodified as possible. ~~~The C++-code seems to be C++ in name only, and is compilable using a C-compiler.~~~ The C++-code is very C-like, but not compilable using a C-compiler due to reference arguments.

The code seems to be reasonable (no global or static variables), and is public domain, so that we can remove the GPLv2-license for a large bulk of the code in libpredict.

Both input and output is contained in the same struct. We have clear separation between input in predict_orbital_elements and output in predict_orbit, so will need to do some massaging, but should not be a big deal.

Clean up basic example

Basic example is no longer compatible with latest development version, and probably also needs some general cleanup.

Should move from a Makefile to CMake.

Change in doppler shift arguments

Change from

double predict_doppler_shift(const predict_observer_t *observer, const struct predict_orbit *orbit, double downlink_frequency);

to

double predict_doppler_shift(const struct predict_observation *observation, double downlink_frequency);

It uses only the observation, we have often already calculated the observation, have to pass less arguments. Also makes more sense to get this from the observation.

SubString replacement

SubString (defined in unsorted.c/.h) outputs its results in a global variable temp[512], and makes predict_parse_tle() not threadsafe.

Deobfuscate and document constants in defs.h

Most important is to deobfuscate the constants that are (also) used outside SDP4/SGP4, since what happens only within SDP4/SGP4 might be total madness anyway. In any case, constants should at least be in upper-case.

Spacetrack report #3 might help in finding out what the different constants actually are.

Export only API symbols

Currently, all symbols are exported from the library. Restrict export to the symbols defined in the API spec.

Issues compiling for ARM

I'm unable to compile for ARM and getting following error. If I rename the s variable, I can workaround but I'm not sure what the deal is. All works fine when compiling for x86.

# dnf install arm-none-eabi-gcc-cs-c++
# dnf install arm-none-eabi-newlib
# git clone https://github.com/la1k/libpredict.git
# git clone https://github.com/vpetrigo/arm-cmake-toolchains.git
# mkdir libpredict/build
# cd libpredict/build
# cmake -DCMAKE_TOOLCHAIN_FILE=../../arm-cmake-toolchains/arm-gcc-toolchain.cmake -DCMAKE_BUILD_TYPE=Debug ../
...
-- Build files have been written to: /tmp/libpredict/build
# make 
Scanning dependencies of target predict_static
[  2%] Building C object src/CMakeFiles/predict_static.dir/orbit.c.obj
In file included from /tmp/libpredict/src/orbit.c:4:0:
/tmp/libpredict/src/defs.h:24:12: error: expected identifier or '(' before numeric constant
 #define s  1.012229
            ^
make[2]: *** [src/CMakeFiles/predict_static.dir/build.make:63: src/CMakeFiles/predict_static.dir/orbit.c.obj] Error 1
make[1]: *** [CMakeFiles/Makefile2:124: src/CMakeFiles/predict_static.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

Missing properties in moon/sun calculation

Moon calculation does not write anything to range_rate or range in struct predict_observation.

Predict/flyby also displays right ascension, declination and greenwhich hour angle, which are not output from libpredict. These are also observation-independent properties, which might cause some headache in which structs to use in the output. :-)

Accessing time

CurrentDayNum() is currently in unsorted.h and unavailable from outside the library.

Conversion functions to and from a more conventional time format would be nice.

Calculation of azimuth, elevation and range

As of now, orbit_t and orbit_predict() does not yield coordinates relative to point of observation. The user has to call Calculate_Obs manually after calling orbit_predict().

For any function dealing with relative coordinates, the QTH coordinates or (azimuth, elevation, range) must be supplied as additional function arguments. This seems to be a bit cumbersome. Can the QTH coordinates be supplied to orbit_create(), and orbit_predict() call Calculate_Obs(), so that (azimuth, elevation, range) can be extracted from orbit_t?

Define and implement an API

Currently, all symbols in the library are exported, and there's no symbol naming policy. The API must be defined and documented.

All symbols that are part of the API must start with a "predict_" prefix to avoid namespace conflicts with other libraries. The list of exported symbols must be restricted to those symbols to avoid internal symbols leaking out and cluttering the namespace.

When this is done, bump the ABI version to 1.0.0.

Satellites and daylight

It will be convenient to know whether a given satellite is currently in sunlight. Flyby does this in Sat_Eclipsed(). Depends on issue #7.

Clean up predict_orbit_t

Some values seem to be duplicated, or maybe even triplicated by pointers to structs/character strings with the same information.

A clean separation between predict_tle_t and predict_orbit_t would help a lot. Currently, predict_tle_t is only used deep down in the library. It makes sense to parse a TLE string into predict_tle_t and then give the predict_tle_t as parameter to predict_create_orbit() instead of the string array it currently takes.

Use of uninitialized value in sdp4()

In src/sdp4.c, line 326:

m->preep is used in a conditional statement before it is initialized. The same thing is present in original code from spacetrack report # 3. Not sure what it should be initialized to in advance, possibly 0.

Add Python bindings

Hej hej,
would it be possible to generate some python bindings for high level interfacing of the library?

Cheers,
Jens

Doppler shift calculation sign

After looking into #44 after some time, we figured out that the Doppler shift calculation of libpredic has the wrong sign. That effect is not seen by flyby as it appears that the sign there is again moved into the correct direction.

Looking at https://www.la1k.no/wp-content/uploads/2017/03/pass.png the Doppler is negative for an object moving towards the observer and positive after the object passed zenith.

  • Changing sign in calculations
  • Fixing test cases (not touching raw test case data)

Unit tests

Need tests for checking correctness of libpredict. Given specific TLE and a set of timestamps, generate file(s) with calculated properties from original predict. Write functions to test the developed library functions against the timestamps and properties in this file.

For AOS/LOS/moonrise/sunrise, can also run some kind of sanity check? Loop through the orbit, check if AOS and LOS actually happens, or passes are missed, and calculate how accurate the results are. Call AOS/LOS repeatedly at different times to see whether the results fall within a specified threshold.

Thresholds in predict_is_geostationary

... are probably "wrong". predict_is_geostationary() returns false on e.g. ELEKTRO-L 1 (37344) and INSAT-3A (27714), though they are geostationary. This results in weird behavior like a LOS or AOS occurring 180 days in the future, since the algorithms are allowed to step to a time so far away from the epoch that numerical inaccuracies allow AOS to happen.

Geostationary satellites never have mean motion set exactly to 1.002701 revolution per day (or do they), but the question is what is reasonably true and what is the correct definition. We have a list over geostationary TLEs, what is the threshold mean motion for these? What could it be true in the future? What satellites are reasonably geostationary over the period the TLE is valid? How exact is the mean motion-parameter?

EDIT: Could be related to geostationary vs geosynchronous, not sure. The value in the function corresponds to the strict definition of a geostationary satellite. Keeping the "bug" mark, but could be that we just need to extend with another function for checking whether a satellite is geosynchronous, need to check.

EDIT 2: Very strict definition of geostationary satellites also require something about the inclination and other parameters. ~~~I don't think we have any use for the strict definition. This function is used mainly for avoiding long iterations in predict_next_aos and similar, which was also its original purpose in Predict.~~~ Strict definition is required, since the satellite has to move with the direction of Earth's rotation. Could technically have a TLE with mean motion set to one rotation per sidereal day, but completely different direction.

double usage of predict_orbit

Hej hej,
I tried to work on an example for the python wrapped libpredict. I realised that the double usage of predict_orbit is breaking a simple interface.
predict_orbit is working as struct and as function at the moment. Further, the style changed from typedef struct { content } name_t; to struct name {content};. Not sure which implications that has in C.

Cheers,
Jens

[BUG] building tests fails

Hej,
unfortunately building some targets fails in my environment for:

  • moon-t
  • orbit-t
  • sun-t

The cmake output looks like:

Scanning dependencies of target moon-t
[ 77%] Building CXX object tests/CMakeFiles/moon-t.dir/moon-t.cpp.o
/export/scratch/jens/src/libpredict/tests/moon-t.cpp: In function ‘int runtest(const char*)’:
/export/scratch/jens/src/libpredict/tests/moon-t.cpp:60: error: expected initializer before ‘:’ token
/export/scratch/jens/src/libpredict/tests/moon-t.cpp:102: error: expected primary-expression at end of input
/export/scratch/jens/src/libpredict/tests/moon-t.cpp:102: error: expected ‘;’ at end of input
/export/scratch/jens/src/libpredict/tests/moon-t.cpp:102: error: expected primary-expression at end of input
/export/scratch/jens/src/libpredict/tests/moon-t.cpp:102: error: expected ‘)’ at end of input
/export/scratch/jens/src/libpredict/tests/moon-t.cpp:102: error: expected statement at end of input
/export/scratch/jens/src/libpredict/tests/moon-t.cpp:102: error: expected ‘}’ at end of input
make[2]: *** [tests/CMakeFiles/moon-t.dir/moon-t.cpp.o] Error 1
make[1]: *** [tests/CMakeFiles/moon-t.dir/all] Error 2
make: *** [all] Error 2

Environment:

  • CentOS 6
  • gcc stock Red Hat 4.4.7 or homemade 5.2.0

Cheers,
Jens

Prediction of sun and moon

Since solar and lunar positions cannot be estimated using TLEs, we have to have separate functions for predicting these. Would also need new structs, as it would not make sense to make use of the existing orbit_t interface for this, e.g. struct sun_t, sun_predict(sun_t *sun, double time), struct moon_t, moon_predict(moon_t *moon, double time).

Should have a clean-room implementation based on existing algorithms? ("Astronomical Algorithms", Jean Meeus). Relevant functions in flyby.c are PredictMoon, PredictSun, FindSun, FindMoon.

More usage examples

Add more examples. Ideas:

  • Very basic and short usage example to give brief overview over the API, put in the README or somewhere else in the documentation, in order to get the user started more quickly
  • AOS/LOS functions, with pass properties
  • TLE file reading, properties over several satellites
  • Moon/sun prediction (we have something in setrise, but I guess that's meant to eventually become a part of the API)
  • Something plot related, use predict_orbit to plot something nice we also can display on the web page or in README.md.

Phase and orbit number

libpredict is missing functions to calculate some properties which are displayed in predict (and will be displayed in flyby):

  • Modulo 256 phase (P-screen)
  • Phase (T-screen, does not seem to be the same as the one above)
  • Orbit (P-screen, seems to be variable with time)

Satellite footprint

Satellite footprint is currently not calculated within libpredict. Add a new field.

Sunrise, sunset, moonrise and moonset.

Proposed API functions:
time predict_sunrise(observer_, time, observation_)
time predict_sunset(observer_, time, observation_)
time predict_moonrise(observer_, time, observation_)
time predict_moonset(observer_, time, observation_)
All functions should use apparent elevation and correct for sun disk and moon disk diameter, such that sunrise happens at the moment the top of the sun disk is above the horizon. Functions should return the predicted time and fill observation pointer with observation data, if it is provided.

Missing functionality: Calculation of AOS and LOS

These are all calculations requiring azimuth and elevation of the satellite with respect to the point of observation. Proposed prototypes are given under the assumption that orbit_predict calculates azimuth, elevation and range, see issue #4.

double FindAOS() (line 4042 in flyby.c)
Proposed prototype: double orbit_get_aos(orbit_t* orbit, double time);
Start at time 'time' and search for first AOS for satellite. Returns time of first AOS.

double FindLOS() (line 4073 in flyby.c)
Proposed prototype: double orbit_get_los(orbit_t* orbit, double time)
Start at time 'time' and search for first LOS, after an AOS. Returns time of LOS.

Required by above functions:
char Decayed(x,time) (line 4007 in flyby.c)
Proposed prototype: bool orbit_decayed(orbit_t* orbit, double time);

Missing functionality: Calculation of Doppler shift

Proposed prototype: double orbit_get_doppler_shift(orbit_t* orbit, double frequency, double time);
See line 5123, 5148 and 5154 in flyby.c. Should output frequency shift, or corrected frequency? Does this belong in this library?

Requires satellite range, see issue #4.

Return predict_observation in predict_next_aos/los

predict_at_max_elevation will return a struct predict_observation and it makes sense that predict_next_aos/los should do the same, both for consistency's sake and that we sometimes need more than the time.

  • Return struct predict_observation for predict_next_aos and predict_next_los

Input to predict_parse_tle

This char*[2]-thing causes more trouble than I can see that it solves. We should find a better solution (e.g. splitting into two char arrays instead of having a char array array).

Add new satellite testcases in test generation script

Add new satellite testcases. @ryeng has provided a list of satellites with corresponding TLEs:

Elliptic orbit:
MOLNIYA 1-29 (SDP4)
1 07780U 75036A 15268.44024861 .00000357 00000-0 -30994-3 0 9998
2 07780 61.6281 228.0088 7320994 263.7628 16.5221 2.00561847296359

Geostationary:
THOR III (SDP4)
1 25358U 98035A 15268.24841071 -.00000057 00000-0 00000+0 0 9999
2 25358 4.3158 63.1329 0002182 131.4584 254.3027 1.00273084 63433

Sun-synchronous orbit:
HINODE (SOLAR-B)
1 29479U 06041A 15269.11672282 .00000318 00000-0 69027-4 0 9994
2 29479 98.1514 267.8479 0018201 43.1347 317.1278 14.64523079481168

Frozen orbit:
ERS-1
1 21574U 91050A 15268.99630557 .00000263 00000-0 10150-3 0 9991
2 21574 98.3773 218.1360 0034080 40.2399 0.7933 14.37359081267054

High Earth Orbit:
VELA-1
1 00692U 63039C 15270.70453905 -.00001516 00000-0 00000+0 0 9999
2 00692 35.8806 1.0617 5492959 190.0635 359.6944 0.22560069 41927

Medium Earth Orbit
GPS BIIA-10 (PRN 32) (SDP4)
1 20959U 90103A 15268.04814446 -.00000015 00000-0 00000+0 0 9997
2 20959 54.2521 190.2003 0113059 6.2850 353.8618 2.00562036181841

Tundra orbit:
SIRIUS-1
1 26390U 00035A 15263.05767392 .00000057 00000-0 00000+0 0 9995
2 26390 59.7673 235.4685 2643498 268.8985 140.1391 1.00280878 55759

Low Earth Orbit:
ISS (ZARYA)
1 25544U 98067A 15268.21313216 .00005785 00000-0 94507-4 0 9995
2 25544 51.6463 304.6860 0005196 319.3549 152.0018 15.54144244963604

Satellite database functions

Add functions to access a system wide (and maybe also user specified) satellite database. Currently, every application needs to maintain it's own database of satellites, updating them every so often.

API functions:

  • Load/access the entire database
  • Look up a satellite by name/catalog number
  • Add a satellite to the database (maybe, this requires write access)

It's not necessary to have update functions in the library, but if the user has write access, this could be a nice extra feature. Measures should be taken to avoid race conditions if a cron job is trying to update the database at the same time as an application reads/writes it.

If the same satellite occurs several times in one or more databases, which element set should be chosen? It's possible to identify the newest one. If it's possible to use the library functions to read different databases, applications could always maintain a separate database of overrides if necessary.

The TLE file format with the satellite name on a separate line (like the predict database) should be supported. Other, more efficient, formats could also be supported.

Separation of input/output in struct orbit

Split orbit parameters and time-dependent, predicted values into separate structs.

Most functions will mostly keep the same number of function arguments since they either use only the predicted values or the fixed orbit parameters.

Minimal header files

Make the header files used by client applications minimal, covering only the defined API. Internal symbols must be in private header files that aren't installed by make install.

Add doxygen docs

Add a doxygen config file and a make target for creating the docs.

Automatic travis build is broken

Travis has stopped working. Fails with "The command "openssl aes-256-cbc -K $encrypted_dee54b1f9803_key -iv $encrypted_dee54b1f9803_iv -in travis/travisci_rsa.enc -out travis/travisci_rsa -d" failed and exited with 1 during".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.