core package

Submodules

core.coordinates module

class core.coordinates.Coordinates

Bases: object

class core.coordinates.ECEF(x: float = 0.0, y: float = 0.0, z: float = 0.0, ellipsoid: ~toluene.core.ellipsoid.Ellipsoid = <toluene.core.ellipsoid.Ellipsoid object>, time: ~toluene.core.time.TerrestrialTimeJ2000 = <toluene.core.time.TerrestrialTimeJ2000 object>)

Bases: Coordinates

Defines a ECEF (Earth Centered Earth Fixed) vector. The ECEF vector is defined by the x, y, z coordinates in meters. Along with the ellipsoid if applicable which is used for conversion to LLA coordinates and time which is used for conversion to ECI coordinates.

Parameters:
  • x (float) – The x coordinate in meters.

  • y (float) – The y coordinate in meters.

  • z (float) – The z coordinate in meters.

  • ellipsoid (Ellipsoid, optional) – The ellipsoid the coordinates are in. Defaults to the WGS84 ellipsoid.

  • time (TerrestrialTimeJ2000, optional) – The time the coordinates are in. Defaults to time of ECEF vector initialization.

ellipsoid() core.ellipsoid.Ellipsoid

Getter for the ellipsoid in the ECEF class. The ellipsoid is used for conversion to LLA AKA geodetic coordinates. Otherwise, it is not used by ECEF directly.

Returns:

The ellipsoid object in the ECEF class.

Return type:

core.ellipsoid.Ellipsoid

magnitude() float

The magnitude of the ECEF vector. Simple Pythagorean theorem measurement of the displacement from the origin.

Returns:

The magnitude of the ECEF vector.

Return type:

float

time() core.time.TerrestrialTimeJ2000

Getter for the time in the ECEF class. The time is used for conversion to ECI AKA Earth

Returns:

The core.time.TerrestrialTimeJ2000 object in the ECEF class.

Return type:

core.time.TerrestrialTimeJ2000

to_ecef() LLA

This just returns self so you don’t have a bug if you try to get ECEF from ECEF. It’s not a bug, it’s a feature. :return: self :rtype: ECEF

to_eci() ECI

ECI is incredibly useful when talking about orbiting bodies. Geostationary orbits defined in ECI coordinates have velocity and acceleration while ECEF coordinates appear unmoving. This is because the Earth is moving in relation to the Sun, moon, other planets, and the stars. The conversion is done using the time since J2000.0 which is definied as exactly 11:58:55.816 UTC on January 1, 2000. Accounting for leap seconds the complication of time is handled in core.time.TerrestrialTimeJ2000. The conversion is done in 5 separate rotations. A simple quick not complete explanation of the formula.

\(x_{crs} = BPNTWx_{trs}\)

\(W\) being the rotation matrix from polar motion or the force applied by the solar system’s motion through the space.

\(T\) being the rotation matrix from the Earth’s rotation.

\(N\) being the rotation matrix from the nutation of the Earth’s axis. This is caused by gravitational forces applied to the bulge of the Earth at the equator.

\(P\) being the rotation matrix from the precession of the Earth’s axis. This is caused by the Earth’s axis wobbling like a top.

\(B\) being the rotation matrix from the bias of the Earth’s axis. This is caused by the Earth’s axis swaying from J2000.0 in an observalbe way.

More information and where the formulas were taken from can be found in Chapter 6 “Precession, Nutation, Polar Motion, and Earth Rotation” Explanatory Supplement to the Astronomical Almanac.

Returns:

The equivalent ECI vector with relation to x, y, z, and time displacement from J2000.0.

Return type:

ECI

to_lla() LLA

Converts the ECEF vector into the approximate LLA coordinates. The conversion is done using the ellipsoid and must be set appropriately to get the correct coordinates. The conversion is done using Ferrari’s solution to the inverse geodetic problem https://en.wikipedia.org/wiki/Geographic_coordinate_conversion. Being computation heavy in toluene all this is done in a C extension. These series of equations are used to convert the ECEF vector to the LLA coordinates.

\(a=\) semi-major axis

\(b=\) semi-minor axis

\(e^2 = \frac{a^2-b^2}{a^2}\)

\(e^{r2} = \frac{a^2-b^2}{b^2}\)

\(p = \sqrt{x^2+y^2}\)

\(F = 54b^2z^2\)

\(G = p^2+(1-e^2)z^2-e^2(a^2-b^2)\)

\(c = \frac{e^4Fp^2}{G^3}\)

\(s = (1+c+\sqrt{c^2+2c})^\frac{1}{3}\)

\(k = 1-s+\frac{1}{s}\)

\(P = \frac{F}{3k^2G^2}\)

\(Q = \sqrt{1+2e^4P}\)

\(r_0 = -\frac{Pep}{1+Q}+\) \(\sqrt{\frac{1}{2}a^2(1+\frac{1}{Q})-\frac{P(1-e^2)Z^2}{Q(1+Q)}-\frac{1}{2}Pp^2}\)

\(U = \sqrt{(p-e^2r_0)^2+z^2}\)

\(V = \sqrt{(p-e^2r_0)^2+(1-e^2)z^2}\)

\(z_0 = \frac{b^2z}{aV}\)

\(h = U(1-\frac{b^2}{aV}) =\) altitude over the ellipsoid

\(\phi = atan(\frac{z+e^{r2}z_0}{p}) =\) Latitude

\(\lambda = atan2[y,x] =\) Longitude

class core.coordinates.ECI(x, y, z, ellipsoid: ~toluene.core.ellipsoid.Ellipsoid = <toluene.core.ellipsoid.Ellipsoid object>, time: ~toluene.core.time.TerrestrialTimeJ2000 = <toluene.core.time.TerrestrialTimeJ2000 object>)

Bases: Coordinates

Defines a ECI (Earth Centered Inertial) vector. The ECI vector is defined by the x, y, z coordinates in meters and time in seconds since J2000.0 using TT. The time is used for conversion to ECEF coordinates. The ellipsoid is not used by ECI directly but used for conversion to LLA coordinates. ECI is incredibly useful when talking about orbiting bodies as geostationary orbits defined in ECI coordinates still have velocity and acceleration however appear unmoving in ECEF coordinates.

Parameters:
  • x (float) – The x coordinate in meters.

  • y (float) – The y coordinate in meters.

  • z (float) – The z coordinate in meters.

  • ellipsoid (Ellipsoid, optional) – The ellipsoid the coordinates are in. Defaults to the WGS84 ellipsoid.

  • time (TerrestrialTimeJ2000, optional) – The time the coordinates are in. Defaults to time of ECI vector initialization.

ellipsoid() core.ellipsoid.Ellipsoid

The ellipsoid the coordinates are in. Not used directly with ECI but is important if converting to LLA coordinates. Defaults to the WGS84 ellipsoid, however others can be used if needed. core.ellipsoid.Ellipsoid has more info on how to create a custom ellipsoid.

Returns:

The ellipsoid in the ECI class.

magnitude() float

The magnitude of the ECI vector. Simple Pythagorean theorem measurement of the displacement from the origin.

Returns:

The magnitude of the ECI vector.

Return type:

float

time() core.time.TerrestrialTimeJ2000

The time the coordinates are in. The time is used for conversion to ECEF coordinates. Defaults to time of ECI vector initialization. This NEEDS to be set appropriately using the UTC timezone. If using ECI you will probably need to convert to Earth Centered Earth Fixed coordinates at some point or geodetic coordinates to make sense as an observer on ground.

Returns:

The time in the ECI class.

Return type:

core.time.TerrestrialTimeJ2000

to_ecef() ECEF

Converts the ECI vector into the equivalent ECEF coordinates. The conversion is done using the inverse of the rotation matricies used to convert from ECEF to ECI. The conversion is done in 5 separate rotations just the same however we use the transpose as they’re orthaogonal matricies. Introduces some rounding error but is in the scale of micrometers so is negligible.

Returns:

The equivalent ECEF vector with relation to x, y, z, and time displacement from J2000.0.

Return type:

ECEF

to_eci() LLA

This just returns self so you don’t have a bug if you try to get ECI from ECI. It’s not a bug, it’s a feature. :return: self :rtype: ECI

to_lla() LLA

Converts the ECI vector into the equivalent LLA coordinates. The conversion is done using the ECEF as an intermediate step. Ensure that both time and ellipsoid are set appropriately to get the correct coordinates.

Returns:

The equivalent LLA vector with relation to latitude, longitude, altitude, and time displacement from J2000.0.

Return type:

LLA

class core.coordinates.LLA(latitude: float | None = None, longitude: float | None = None, altitude: float = 0.0, ellipsoid: ~toluene.core.ellipsoid.Ellipsoid = <toluene.core.ellipsoid.Ellipsoid object>, time: ~toluene.core.time.TerrestrialTimeJ2000 = <toluene.core.time.TerrestrialTimeJ2000 object>)

Bases: Coordinates

Defines geodetic coordinates, I.E. Latitude, Longitude, Altitude over an ellipsoid. These coordinates are defined by the ellipsoid they are on meaning unlike ECEF coordinates if you want to convert to any other coordinate frame, it is suggested that you ensure the ellipsoid is the proper one defaulting to the WGS84 ellipsoid. The time is also used when converting to ECI coordinates.

Parameters:
  • latitude (float) – The latitude of the point on the ellipsoid in degrees. Must be between -90 and 90 degrees. -90 is the South Pole and 90 is the North Pole and is just equal to the semi-minor axis. 0 is the equator and is equal to the semi-major axis. Represented in math as \(\phi\).

  • longitude (float) – The longitude of the point on the ellipsoid in degrees. Must be between -180 and 180 degrees. -180 is the International Date Line and 180 is the Prime Meridian. Represented in math as \(\lambda\).

  • altitude (float, optional) – The altitude of the point over the ellipsoid in meters. Represented in math as \(h\). Defaults to 0 meters.

  • ellipsoid (core.ellipsoid.Ellipsoid, optional) – The ellipsoid the coordinates are on. Defaults to the WGS84 ellipsoid.

  • time (core.time.TerrestrialTimeJ2000, optional) – The time the coordinates are in. Defaults to time of LLA coordinates initialization.

ellipsoid() core.ellipsoid.Ellipsoid

Getter for the ellipsoid in the LLA class. The ellipsoid is used for conversion to ECEF AKA Earth Centered Earth Fixed coordinates. It could also be used to measure the distance from one point to another in meters. It defines the shape of the Earth and how the radius changes with respect to latitude.

Returns:

The ellipsoid object in the LLA class.

Return type:

Ellipsoid

magnitude() float

The magnitude of the LLA vector. Measurement of the displacement from the center of the Earth. This is the same as the altitude over the ellipsoid plus the radius of the ellipsoid at the latitude of the point. Should be equal to the Pythagorean theorem of the corresponding ECEF vector.

Returns:

The magnitude of the LLA vector.

Return type:

float

time() core.time.TerrestrialTimeJ2000

Getter for the time in the LLA class. The time is used for conversion to ECI AKA Earth Centered Inertial coordinates. It could be used to store time when the coordinates were taken.

Returns:

The time object in the LLA class.

Return type:

core.time.TerrestrialTimeJ2000

to_ecef() ECEF

Converts the Geodetic coordinates to the equivalent ECEF coordinates. The conversion is done using the definied ellipsoid and must be set appropriately to get the correct coordinates. The conversion is much simpler than the other way around and could be computed with the equation. Still preformed in a C extension for speed.

\(x = (N(\phi)+h)cos(\phi)cos(\lambda)\)

\(y = (N(\phi)+h)cos(\phi)sin(\lambda)\)

\(z = (N(\phi)(1-e^2)+h)sin(\phi)\)

Where \(N(\phi) = \frac{a}{\sqrt{1-e^2sin^2(\phi)}}\)

\(a=\) semi-major axis

\(b=\) semi-minor axis

\(e^2 = \frac{a^2-b^2}{a^2}\)

to_eci() ECI

Converts the LLA coordinates to the equivalent ECI coordinates. The conversion is done using ECEF as an intermediate step. Ensure that both time and ellipsoid are set appropriately to get the correct coordinates.

Returns:

The equivalent ECI vector with relation to x, y, z, and time displacement from J2000.0.

Return type:

ECI

to_lla() LLA

This just returns self so you don’t have a bug if you try to get LLA from LLA. It’s not a bug, it’s a feature. :return: self :rtype: LLA

core.earth module

class core.earth.EarthModel

Bases: object

core.egm84 module

class core.egm84.EGM84(interpolation_grid_zip: str, spherical_harmonics_zip: str | None = None)

Bases: Geoid

The EGM84 geoid. The EGM84 geoid is a geoid model of the earth. It is based on the WGS84 ellipsoid and is defined by a grid of points and the spherical harmonics. The spherical harmonics are used to calculate gravity. The grid is used to interpolate the sea level at a point. Created by the National Geospatial-Intelligence Agency (NGA) and the data is available at https://earth-info.nga.mil/#wgs84-data. It does not come with toluene and must be downloaded to use the EGM84 geoid. Opens the interpolation grid zip file and sphereical harmonics zip file into the temp dir of this run. The file WWGRID can be found there after super().__init__.

Parameters:
  • interpolation_grid_zip (str) – The path to the interpolation grid zip file.

  • spherical_harmonics_zip (str, optional) – The path to the spherical harmonics zip file. Defaults to None.

height(position: Coordinates, interpolation: Literal['bilinear'] = 'bilinear') float

Calculates the height of the EGM84 geoid at a point. Uses interpolation to calculate the height. The method of interpolation is defined by the interpolation parameter.

Parameters:
  • position (Coordinates) – The position to calculate the height at.

  • interpolation (Literal['bilinear'], optional. Defaults to bilinear.) – The interpolation method to use for computing the value. Defaults to bilinear.

Returns:

The height of the EGM84 geoid at the point.

Return type:

float

core.ellipsoid module

class core.ellipsoid.Ellipsoid(semi_major_axis: float, inverse_flattening: float, epsg: int | None = None)

Bases: object

Defines an ellipsoid for toluene. The ellipsoid is defined by the semi-major axis and the inverse flattening factor. For too complicated reasons to explain here, the earth is not a sphere, but an ellipsoid. An Ellipsoid is close to a sphere but bulges at the equator and is flattened at the poles. The semi-major axis is the radius of the ellipsoid at the equator and the inverse flattening factor is the flattening factor inverted. The flattening factor defines how much the ellipsoid is flattened at the poles.

Parameters:
  • semi_major_axis (float) – The semi-major axis of the ellipsoid in meters. The semi-major axis is the radius of the ellipsoid at the equator.

  • inverse_flattening (float) – The inverse flattening factor of the ellipsoid. The inverse flattening factor is defined as the flattening factor inverted. \(\frac{1}{f} = \frac{a}{a-b}\) where \(a\) is the semi-major axis and \(b\) is the semi-minor axis. The semi-minor axis is the radius of the ellipsoid at the poles in meters.

  • epsg (int, optional) – The EPSG number of the ellipsoid. More ellipsoids can be found at https://epsg.io, Defaults to None

ellipsoid_radius(latitude: float | None = None) float

Calculates the radius of the ellipsoid at a given latitude. The latitude must be between -90 and 90 degrees. The solution is given in meters. The formula used is \(R = \sqrt{\frac{a^2}{1+(\frac{1}{(1-f)^2}-1)\cdot sin^2(\phi)}}\). Where \(a\) is the semi-major axis, \(f\) is the flattening factor and \(\phi\) is the latitude.

Parameters:

latitude (float) – The latitude of the point on the ellipsoid in degrees. Must be between -90 and 90 degrees. -90 is the South Pole and 90 is the North Pole and is just equal to the semi-minor axis. 0 is the equator and is equal to the semi-major axis.

Returns:

The radius of the ellipsoid at the given latitude in meters.

Return type:

float

epsg() int

EPSG number of the ellipsoid. More ellipsoids than the ones defined here can be found at https://epsg.io. There are plans to add more ellipsoids to this class, but for now, the user can define their own ellipsoid if the one’s supplied don’t fit their needs. The fact that the epsg number is saved in the class is just a for reference and has no effect on the calculations.

Returns:

The EPSG number of the ellipsoid.

Return type:

int

flattening() float

The flattening factor of the ellipsoid. The flattening factor is the relationship between the semi-major axis and the semi-minor axis. The mathematical symbol for the flattening factor is \(f\) in most cases. This is computed with the formula \(f = \frac{a}{a-b}\) where \(a\) is the semi-major axis and \(b\) is the semi-minor axis. The flattening factor isn’t saved in the class, but computed when the function is called with the formula \(f = \frac{1}{\frac{1}{f}}\).

Returns:

The flattening factor of the ellipsoid.

Return type:

float

semi_major_axis() float

The semi major axis of the ellipsoid. The semi-major axis is the radius of the ellipsoid at the equator. The mathematical symbol for the semi-major axis is \(a\) in most cases.

Returns:

The semi-major axis of the ellipsoid.

Return type:

float

semi_minor_axis() float

The semi minor axis of the ellipsoid. The semi-minor axis is the radius of the ellipsoid at the poles. The mathematical symbol for the semi-minor axis is \(b\) in most cases. This is computed at the class’ initialization using the formula \(b = a(1-f)\) where \(a\) is the semi-major axis and \(f\) is the flattening factor.

Returns:

The semi-minor axis of the ellipsoid.

Return type:

float

core.ellipsoid.grs_80_ellipsoid = <core.ellipsoid.Ellipsoid object>

GRS80/EPSG:7019 ellipsoid https://epsg.io/7019-ellipsoid Geodetic Reference System 1980. The semi-major axis is 6,378,137.0 meters and the inverse flattening is 298.257222101.

core.ellipsoid.wgs_66_ellipsoid = <core.ellipsoid.Ellipsoid object>

WGS66/EPSG:4890 ellipsoid https://epsg.io/4890 World Geodetic System 1966. The semi-major axis is 6,378,145.0 meters and the inverse flattening is 298.25.

core.ellipsoid.wgs_72_ellipsoid = <core.ellipsoid.Ellipsoid object>

WGS72/EPSG:4322 ellipsoid https://epsg.io/4322 World Geodetic System 1972. The semi-major axis is 6,378,135.0 meters and the inverse flattening is 298.26.

core.ellipsoid.wgs_84_ellipsoid = <core.ellipsoid.Ellipsoid object>

WGS84/EPSG:4326 ellipsoid https://epsg.io/4326 World Geodetic System 1984. The semi-major axis is 6,378,137.0 meters and the inverse flattening is 298.257223563. This is the most commonly used ellipsoid.

core.geoid module

class core.geoid.Geoid(interpolation_grid_zip: str, spherical_harmonics_zip: str | None = None)

Bases: object

The abstract base class for a Geoid. A geoid is a model of the earth’s surface. It is defined by a grid of points and the spherical harmonics. The spherical harmonics are used to calculate gravity. The grid is used to interpolate the sea level at a point. The geoid is based on an ellipsoid. The ellipsoid is used to calculate the height of a perfect ellipsoid to model the earth. The geoid is then used to calculate the difference between the ellipsoid and the theoretical sea level.

Parameters:
  • interpolation_grid_zip (str) – The path to the interpolation grid zip file.

  • spherical_harmonics_zip (str, optional) – The path to the spherical harmonics zip file. Defaults to None.

height(position: Coordinates, interpolation: Literal['bilinear'] = 'bilinear') float

Calculates the height of the geoid at a point. This method is pure virtual and must be implemented by the subclass.

Parameters:
  • position (Coordinates) – The position to calculate the height at.

  • interpolation (Literal['bilinear'], optional. Defaults to bilinear.) – The interpolation method to use for computing the value. Defaults to bilinear.

Returns:

The height of the geoid at the point.

Return type:

float

core.time module

class core.time.TerrestrialTimeJ2000(dt: datetime = datetime.datetime(2023, 11, 27, 2, 49, 29, 725326))

Bases: object

Terrestrial Time (TT) is the timescale used for most ephemerides of planets and other solar system bodies. It is dependent on the rotation of the earth and the gravitational potential of the earth. I define the timezone as UTC so when using a datetime object it is important to set the time as UTC and not local time.

Parameters:

dt (datetime, optional) – The datetime object to use for the time. Defaults to the current time.

centuries_since() float
seconds_since() float

Module contents