Introducing the package SatelliteToolbox.jl


Hi guys!

Today, I finally made public the SatelliteToolbox.jl. This is a toolbox constructed at the Brazilian National Institute for Space Research (INPE) that contains a lot of useful algorithms for satellite simulations. Everything is very easy to use and this is the engine behind our Mission Concept Satellite Simulator. This is an on going work of almost 5 years (since the days of Julia 0.2).

I will submit to METADATA as soon as the new version of ReferenceFrameRotations is accepted (, because, otherwise, the tests will fail.

Unfortunately, a full documentation of the package is not available yet, but the source code is extensively documented using the Julia doc system. If you want to install and test right now, you can clone my repository and use the master version of ReferenceFrameRotations.

There are some interesting stuff in this package, such as:

Coordinate transformations

All the IAU-76/FK5 theory is implemented and you can compute the DCM or Quaternion that describes the rotations between ECEF and ECI. The supported coordinate frames are:

  • ITRF: International Terrestrial Reference Frame (ITRF).
  • PEF: Pseudo-Earth Fixed (PEF) reference frame.
  • MOD: Mean of Date (MOD) reference frame.
  • TOD: True of Date (TOD) reference frame.
  • J2000: J2000 reference frame.
  • GCRF: Geocentric Celestial Reference Frame (GCRF).
julia> eop_IAU1980 = get_iers_eop(:IAU1980)
julia> rECEFtoECI(DCM, ITRF(), GCRF(), DatetoJD(1986, 06, 19, 21, 35, 0), eop_IAU1980)
3×3 StaticArrays.SArray{Tuple{3,3},Float64,2,9}:
 -0.619267      0.78518     -0.00132979
 -0.78518      -0.619267     3.33483e-5
 -0.000797314   0.00106478   0.999999


There is a native Julia implementation of the IGRF v12.

julia> igrf12syn(0, 2017.12313, 1, 0.640, 40, 25)
(19685.59353648455, 2164.874709891016, 45708.25456382237, 49814.19286372505)

julia> igrf12(2017.12313, 640, 50*pi/180, 25*pi/180, Val{:geodetic})
3-element StaticArrays.SArray{Tuple{3},Float64,1,3}:

Orbit Propagators

There is a native Julia implementation of the SGP4 orbit propagator (without SDP4 bits for now). You can also find the Two Body and J2 orbit propagators.

julia> orbp = init_orbit_propagator(Val{:sgp4}, Orbit(0.0,7130982.0,0.001111,98.405*pi/180,pi/2,0.0,0.0))
julia> (o,r,v) = propagate!(orbp, collect(0:3:24)*60*60)
julia> r
9-element Array{Array{T,1} where T,1}:
 [-2159.7, 7.13166e6, -14607.2]
 [-1.00096e6, 2.1411e6, -6.73899e6]
 [-5.78906e5, -5.83897e6, -4.08451e6]
 [6.64614e5, -5.70129e6, 4.24735e6]
 [9.6287e5, 2.37768e6, 6.64987e6]
 [-1.12629e5, 7.12679e6, -2.45705e5]
 [-1.03066e6, 1.90639e6, -6.80469e6]
 [-4.86132e5, -5.97626e6, -3.89338e6]
 [7.5014e5, -5.54932e6, 4.42998e6]

EGM96 and 2008

There is a native Julia implementation of EGM96 and 2008.

julia> egm96 = read_egm_coefs(:EGM96)
julia> compute_g(egm96, GeodetictoECEF(-45*pi/180, -22*pi/180, 0), 360)
3-element Array{Float64,1}:

julia> egm2008 = read_egm_coefs(:EGM2008)
julia> compute_g(egm2008, GeodetictoECEF(-45*pi/180, -22*pi/180, 0), 360)
3-element Array{Float64,1}:

Much more

There is many other things such as beta angle computation, Sun synchronous orbit design, etc., that you can see in the package.


I can use some help if anyone have a little spare time :slight_smile: There are a lot of to do in this package. Some functions have been extensively tested, but others needs more work (as you can see in ./test). In the short time, I am expecting to do the following:

  • Add support for TEME (True Equator Mean Equinox) reference frame.
  • Add IAU-2000A model for coordinate transformations.
  • Add SDP4 bits to the orbit propagator.
  • Add a numerical propagator using EGM.


Nice work!
Did you rename the package Rotations.jl to ReferenceFrameRotations.jl ?
If so, why?



Yes, I had to rename it because that was already a package in METADATA named Rotations.jl. Hence, this was necessary to submit to the official package repository.


Cool stuff! Note that this may have some overlap with JuliaAstrodynamics by @helgee, so you may want to get in touch with him to coordinate the effort


Like @giordano says! I would be interested to collaborate.


Thanks! I will do this :slight_smile:

Nice! To help people to collaborate, I moved the package from my personal repository to the organziation SatelliteToolbox in Github ( In this case, I will start to break this big package into smaller ones as per @crbinz suggestion. Now, I have to figure out what is the correct way to move a registered package (ReferenceFrameRotations) to that organization.

What I will for sure need your help, is to guide me to integrate your JPLEphemeris package into my numerical propagator that I want to implement in the near future!

I think we have a lot very nice opportunities here!


As a counter viewpoint, I am strongly of the opinion that that is a bad idea. Big packages are awesome compared to the same package with the source code scattered around in a bunch of mini-packages. The advantages are clear: All documentation in one place, easier to get an overview of the source code, less overhead when loading the package, the tests test all of the source code, no need to tag a bunch of things all the time, issues condensed to one place etc etc. Unless the splitted package has a clear contained purpose on its own, it is very seldom beneficial to split it out.


Hi @kristoffer.carlsson,

I see your point! I think I will finish the implementations of some functions I have here that needs to be ported to Julia and analyze what I should do. Thanks for the advice.


@Ronis_BR, it would be awesome if you could evaluate AstroTime.jl and test whether you could use it instead of your code in the time folder. If there is anything missing that you have already it would also be great if you could contribute those functions to AstroTime.


I was about to say that to you! I analyzed your packages and found this overlapping :slight_smile: I will try to modify my code and will get in touch if I need any help!


I forgot to mention that the package was accepted. Then, you can now install it using:



Hi guys,

Some updates:

  1. TEME was added, now we can convert our TLEs :slight_smile:
julia> oe_teme = Orbit(0, 7130.982e3, 0.001111, 98.405*pi/180, 227.336*pi/180, 90*pi/180, 320*pi/180)

                  t =        0.0
    Semi-major axis =     7130.9820 km
       Eccentricity =        0.001111
        Inclination =       98.4050 ˚
               RAAN =      227.3360 ˚
    Arg. of Perigee =       90.0000 ˚
       True Anomaly =      320.0000 ˚

julia> oe_j2000 = change_oe_frame(oe_teme, TEME(), J2000(), DatetoJD(2016,06,01,11,00,00))

                  t =        0.0
    Semi-major axis =     7130.9820 km
       Eccentricity =        0.001111
        Inclination =       98.3365 ˚
               RAAN =      227.1345 ˚
    Arg. of Perigee =       90.0604 ˚
       True Anomaly =      320.0000 ˚
  1. Complete IAU-76/FK5 transformations. Using the functions rECEFtoECI, rECItoECEF, rECItoECI, and rECEFtoECEF, we can now covert between any of the supported reference frame (GCRF, J2000, TOD, MOD, TEME, PEF, ITRF). It is also possible to convert between two epochs like:
julia> eop = get_iers_eop(:IAU1980);

julia> oe_teme = Orbit(0, 7130.982e3, 0.001111, 98.405*pi/180, 227.336*pi/180, 90*pi/180, 320*pi/180)

                  t =        0.0
    Semi-major axis =     7130.9820 km
       Eccentricity =        0.001111
        Inclination =       98.4050 ˚
               RAAN =      227.3360 ˚
    Arg. of Perigee =       90.0000 ˚
       True Anomaly =      320.0000 ˚

julia> oe_teme2 = change_oe_frame(oe_teme, TEME(), DatetoJD(2016,06,01,11,00,00), TEME(), DatetoJD(2018,06,01,11,00,00), eop)

                  t =        0.0
    Semi-major axis =     7130.9820 km
       Eccentricity =        0.001111
        Inclination =       98.4118 ˚
               RAAN =      227.3605 ˚
    Arg. of Perigee =       89.9925 ˚
       True Anomaly =      320.0000 ˚