propagate_many#
- cysgp4.propagate_many(mjds, tles, observers=None, do_eci_pos=True, do_eci_vel=True, do_geo=True, do_topo=True, do_obs_pos=False, do_sat_azel=False, do_sat_rotmat=False, sat_frame='zxy', on_error='raise', method='dwarner')[source]#
Calculate positions of many satellites at a various times at once.
This is an array interface to the sgp4 calculations, which allows to perform calculations for different satellite TLEs, observers and times in a parallelized manner.
numpy
broadcasting rules apply.With the Boolean parameters,
do_eci_pos
,do_eci_vel
,do_geo
,do_topo
,do_obs_pos
, anddo_sat_azel
the user can decide, which position frames are returned in the output dictionary.Satellite are defined via TLEs (see
PyTle
). Thepropagate_many
function works with a single (scalar) PyTle object or a list/array of them. The same is true for themjds
and optionalobservers
parameters, which must be a scalar (a double andPyObserver
instance, respectively) or a list/array of them.As in most use cases, a large number of positions is probably queried, the returned values do not use the
PyEci
orPyCoordTopocentric
classes, but pack everything in arrays. This is not only faster, but makes it easier to further process the results.For parallelization, OpenMP is utilized. To change the number of CPU cores that are used, one can either set the environment variable
OMP_NUM_THREADS
or useset_num_threads
.- Parameters:
- mjds
ndarray
,list
, or scalar offloat
Modified Julian Date.
- tles
ndarray
,list
, or scalar ofPyTle
TLE instance of the satellite of interest.
- observers
ndarray
,list
, or scalar ofPyObserver
orNone
(default:None
) Observer instance. If
None
then the observer location is set to (0 deg, 0 deg, 0 km).- do_eci_pos
Boolean
, optional (default:True
) Whether to include ECI cartesian positions in the result.
- do_eci_vel
Boolean
, optional (default:True
) Whether to include ECI cartesian velocity in the result.
- do_geo
Boolean
, optional (default:True
) Whether to include geographic/geodetic positions in the result.
- do_topo
Boolean
, optional (default:True
) Whether to include topocentric positions in the result.
- do_obs_pos
Boolean
, optional (default:True
) Whether to include the observer ECI position in the results.
- do_sat_azel
Boolean
, optional (default:True
) Whether to include the observer position as seen by the satellite (distance/azimuth/elevation) in the results.
- do_sat_rotmat
Boolean
, optional (default:False
) Whether to include the rotation matrix that converts the (moving and rotated) satellite frame (in cartesian) into cartesian ECI-aligned coordinates in the results. This can be useful for cases where the user needs to transform additional vectors between both frames (and is not only interested the observer position in the satellite frame as returned by
do_sat_azel
).- sat_frame‘zxy’ or ‘xyz’, optional (default: ‘zxy’)
How the moving satellite frame is defined. Two options are implemented, ‘zxy’ and ‘xyz’. If ‘zxy’ is chosen, the moving satellite frame is constructed such that the
z
axis is aligned with the satellite motion vector. They
axis is lies perpendicularly to the plane defined by the motion vector and the ECI zero point (aka the Earth centre). The resultingx
axis, which is orthogonal to they
andz
axes, is then approximately pointing towards nadir. Alternatively, if the frame is set asxyz
, thex
axis is the motion vector,y
has the same meaning (but points into the opposite direction) andz
is approximately pointing towards the nadir. The definition of the output polar angles is different for the two reference frames, see Returns.- on_error
str
, optional (either
‘raise’ or ‘coerce_to_nan’, default: ‘raise’) If the underlying SGP C++ library throws an error (which often happens if one works with times that are strongly deviating from the TLE epoch), a Python RuntimeError is usually thrown. For batch processing, this is not always desirable. If
on_error = 'coerce_to_nan'
then C++ errors will be suppressed and the resulting position vectors will be converted to NaN-values instead.Note: this option is only relevant for
method='dwarner'
!- method
str
, optional (either
‘dwarner’ or ‘vallado’) This option can be used to change from the default SGP C++ library (by Daniel Warner) to the Vallado model. For the latter, the external
python-sgp4
library is used. ‘vallado’ may be slower due to the additional boiler-plate code and differences in the model itself and implementation details.
- mjds
- Returns:
- result
dict
Resulting positions for each requested frame:
eci_pos
:ndarray
of floatSatellites ECI cartesian positions. Last dimension has length 3, one for each of
x
,y
, andz
.eci_vel
:ndarray
of floatSatellites ECI cartesian velicities. Last dimension has length 3, one for each of
v_x
,v_y
, andv_z
.geo
:ndarray
of floatSatellites Geodetic positions. Last dimension has length 3, one for each of
lon
,lat
, andalt
.topo
:ndarray
of floatSatellites Topocentric positions. Last dimension has length 4, one for each of
az
,el
,dist
, anddist_rate
.obs_pos
:ndarray
of floatObserver positions in ECI frame (Cartesian). Last dimension has length 3, one for each of
x
,y
, andz
.sat_azel
:ndarray
of floatIf
sat_frame
is ‘zxy’,z
lies in the direction of motion,y
perpendicular to the z-axis and the Earth center,x
is pointing approximately towards nadir, see alsosat_frame
parameter description. The Observer positions in the (co-moving) satellite frame are given as azimuth, elevation in the specified reference frame, and distance (az
,el
,dist
).az
is the angle between the projection of the vector towards the Observer onto the xy-plane and the x-axis. -180 deg <az
< 180 deg.el
is the angle between the normal vector and the xy-plane. -90 deg <el
< 90 deg.If
sat_frame
is ‘xyz’,x
lies in the direction of motion,y
is perpendicular toz
and the Earth center,z
is pointing approximately towards nadir, see alsosat_frame
parameter description. The Observer positions in the (moving) satellite frame are given as azimuth and polar angle in the specified reference frame, and distance (az
,theta
,dist
).az
is the angle between the projection of the vector towards the observer onto the xy-plane and the x-axis. -180 deg <az
< 180 deg.theta
is the angle between the normal vector and the z-axis. -90 deg <theta
< 90 deg.sat_rotmat
:ndarray
of floatRotation matrices which would transform a vector defined in the (moving and rotated) satellite frames (in cartesian) to the cartesian ECI-aligned basis frame. It is noted that the origin of this ECI-aligned frame is still at the satellite center.
This can be useful for cases where the user needs to transform additional vectors between both frames (and is not only interested the observer position in the satellite frame as returned by
do_sat_azel
).Likewise, the inverse of these rotation matrices (aka the transposed) can be used to rotate any vector from ECI-aligned satellite basis frame to the satellite frame.
In all cases the first dimensions are determined by the (broadcasted) shape of the inputs
mjd
,tles
, andobservers
.
- result
Examples
The following demonstrates how to use the
propagate_many
function:>>> import numpy as np >>> from cysgp4 import PyTle, PyObserver, propagate_many >>> from cysgp4 import get_example_tles, tles_from_text >>> tle_text = get_example_tles() >>> tles = np.array( ... tles_from_text(tle_text) ... )[np.newaxis, np.newaxis, :20] # use first 20 TLEs >>> observers = np.array([ ... PyObserver(6.88375, 50.525, 0.366), ... PyObserver(16.88375, 50.525, 0.366), ... ])[np.newaxis, :, np.newaxis] >>> mjds = np.linspace( ... 58805.5, 58806.5, 1000 # 1000 time steps ... )[:, np.newaxis, np.newaxis] >>> result = propagate_many(mjds, tles, observers) >>> print(sorted(result.keys())) ['eci_pos', 'eci_vel', 'geo', 'topo'] >>> # shapes are as follows >>> print(np.broadcast(mjds, tles, observers).shape) (1000, 2, 20) >>> print(result['eci_pos'].shape, result['topo'].shape) (1000, 2, 20, 3) (1000, 2, 20, 4) >>> result = propagate_many( ... mjds, tles, observers, ... do_eci_pos=False, do_eci_vel=False, do_geo=False, do_topo=True ... ) >>> print(sorted(result.keys())) ['topo']