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.
numpybroadcasting rules apply.With the Boolean parameters,
do_eci_pos,do_eci_vel,do_geo,do_topo,do_obs_pos, anddo_sat_azelthe user can decide, which position frames are returned in the output dictionary.Satellite are defined via TLEs (see
PyTle). Thepropagate_manyfunction works with a single (scalar) PyTle object or a list/array of them. The same is true for themjdsand optionalobserversparameters, which must be a scalar (a double andPyObserverinstance, 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
PyEciorPyCoordTopocentricclasses, 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_THREADSor 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 ofPyObserverorNone(default:None) Observer instance. If
Nonethen 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
zaxis is aligned with the satellite motion vector. Theyaxis is lies perpendicularly to the plane defined by the motion vector and the ECI zero point (aka the Earth centre). The resultingxaxis, which is orthogonal to theyandzaxes, is then approximately pointing towards nadir. Alternatively, if the frame is set asxyz, thexaxis is the motion vector,yhas the same meaning (but points into the opposite direction) andzis 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-sgp4library 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:ndarrayof floatSatellites ECI cartesian positions. Last dimension has length 3, one for each of
x,y, andz.eci_vel:ndarrayof floatSatellites ECI cartesian velicities. Last dimension has length 3, one for each of
v_x,v_y, andv_z.geo:ndarrayof floatSatellites Geodetic positions. Last dimension has length 3, one for each of
lon,lat, andalt.topo:ndarrayof floatSatellites Topocentric positions. Last dimension has length 4, one for each of
az,el,dist, anddist_rate.obs_pos:ndarrayof floatObserver positions in ECI frame (Cartesian). Last dimension has length 3, one for each of
x,y, andz.sat_azel:ndarrayof floatIf
sat_frameis ‘zxy’,zlies in the direction of motion,yperpendicular to the z-axis and the Earth center,xis pointing approximately towards nadir, see alsosat_frameparameter 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).azis the angle between the projection of the vector towards the Observer onto the xy-plane and the x-axis. -180 deg <az< 180 deg.elis the angle between the normal vector and the xy-plane. -90 deg <el< 90 deg.If
sat_frameis ‘xyz’,xlies in the direction of motion,yis perpendicular tozand the Earth center,zis pointing approximately towards nadir, see alsosat_frameparameter 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).azis the angle between the projection of the vector towards the observer onto the xy-plane and the x-axis. -180 deg <az< 180 deg.thetais the angle between the normal vector and the z-axis. -90 deg <theta< 90 deg.sat_rotmat:ndarrayof 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_manyfunction:>>> 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']