Topocentric coordinate systems are local horizon-based reference frames centered on an observer, such as a ground station or radar site. These coordinate systems are essential for satellite tracking, visibility analysis, and determining where to point antennas or telescopes.
Unlike global coordinate systems (ECEF, ECI), topocentric systems define positions relative to a specific location on Earth, making it easy to determine whether a satellite is visible and where to look in the sky.
The SEZ system is sometimes used in radar and missile tracking applications. The main difference from ENZ is that the first two axes are rotated 180° around the zenith axis.
Info
Both ENZ and SEZ use a right-handed coordinate system with the zenith axis pointing up. The choice between them is typically driven by convention in your specific field or application.
To get the position of an object relative to a location, you need to convert the object's ECEF position to the local ENZ frame centered on the location:
importbraheasbhimportnumpyasnpbh.initialize_eop()# Define ground station location in geodetic coordinates# Stanford University: (lon=-122.17329°, lat=37.42692°, alt=32.0m)lon_deg=-122.17329lat_deg=37.42692alt_m=32.0print("Ground Station (Stanford):")print(f"Longitude: {lon_deg:.5f}° = {np.radians(lon_deg):.6f} rad")print(f"Latitude: {lat_deg:.5f}° = {np.radians(lat_deg):.6f} rad")print(f"Altitude: {alt_m:.1f} m\n")# Convert ground station to ECEFgeodetic_station=np.array([lon_deg,lat_deg,alt_m])station_ecef=bh.position_geodetic_to_ecef(geodetic_station,bh.AngleFormat.DEGREES)print("Ground Station ECEF:")print(f"x = {station_ecef[0]:.3f} m")print(f"y = {station_ecef[1]:.3f} m")print(f"z = {station_ecef[2]:.3f} m\n")# Define satellite in sun-synchronous orbit at 500 km altitude# SSO orbit passes over Stanford at approximately 10:30 AM local timeoe=np.array([bh.R_EARTH+500e3,0.001,97.8,240.0,0.0,90.0])# Define epoch when satellite passes near Stanford (Jan 1, 2024, 17:05 UTC)epoch=bh.Epoch.from_datetime(2024,1,1,17,5,0.0,0.0,bh.TimeSystem.UTC)# Convert orbital elements to ECI statesat_state_eci=bh.state_koe_to_eci(oe,bh.AngleFormat.DEGREES)# Convert ECI state to ECEF at the given epochsat_state_ecef=bh.state_eci_to_ecef(epoch,sat_state_eci)sat_ecef=sat_state_ecef[0:3]# Extract position onlyyear,month,day,hour,minute,second,ns=epoch.to_datetime()print(f"Epoch: {year}-{month:02d}-{day:02d}{hour:02d}:{minute:02d}:{second:06.3f} UTC")print("Satellite ECEF:")print(f"x = {sat_ecef[0]:.3f} m")print(f"y = {sat_ecef[1]:.3f} m")print(f"z = {sat_ecef[2]:.3f} m\n")# Convert satellite position to ENZ coordinates relative to ground stationenz=bh.relative_position_ecef_to_enz(station_ecef,sat_ecef,bh.EllipsoidalConversionType.GEODETIC)print("Satellite position in ENZ frame (relative to Stanford):")print(f"East: {enz[0]/1000:.3f} km")print(f"North: {enz[1]/1000:.3f} km")print(f"Zenith: {enz[2]/1000:.3f} km")print(f"Range: {np.linalg.norm(enz)/1000:.3f} km")
Ground Station (Stanford):
Longitude: -122.17329° = -2.132326 rad
Latitude: 37.42692° = 0.653223 rad
Altitude: 32.0 m
Ground Station ECEF:
x = -2700408.551 m
y = -4292612.600 m
z = 3855145.604 m
Epoch: 2024-01-01 17:05:00.000 UTC
Satellite ECEF:
x = -842800.791 m
y = 431996.779 m
z = 6812629.389 m
Satellite position in ENZ frame (relative to Stanford):
East: -943.412 km
North: 5380.227 km
Zenith: -2163.905 km
Range: 5875.317 km
Ground Station (Stanford):
Longitude: -122.17329° = -2.132326 rad
Latitude: 37.42692° = 0.653223 rad
Altitude: 32.0 m
Ground Station ECEF:
x = -2700408.551 m
y = -4292612.600 m
z = 3855145.604 m
Epoch: 2024-01-01 17:05:00.000 UTC
Satellite ECEF:
x = -842800.791 m
y = 431996.779 m
z = 6812629.389 m
Satellite position in ENZ frame (relative to Stanford):
East: -943.412 km
North: 5380.227 km
Zenith: -2163.905 km
Range: 5875.317 km
importbraheasbhimportnumpyasnpbh.initialize_eop()# Define ground station location in geodetic coordinates# Stanford University: (lon=-122.17329°, lat=37.42692°, alt=32.0m)lon_deg=-122.17329lat_deg=37.42692alt_m=32.0print("Ground Station (Stanford):")print(f"Longitude: {lon_deg:.5f}° = {np.radians(lon_deg):.6f} rad")print(f"Latitude: {lat_deg:.5f}° = {np.radians(lat_deg):.6f} rad")print(f"Altitude: {alt_m:.1f} m\n")# Convert ground station to ECEFgeodetic_station=np.array([lon_deg,lat_deg,alt_m])station_ecef=bh.position_geodetic_to_ecef(geodetic_station,bh.AngleFormat.DEGREES)print("Ground Station ECEF:")print(f"x = {station_ecef[0]:.3f} m")print(f"y = {station_ecef[1]:.3f} m")print(f"z = {station_ecef[2]:.3f} m\n")# Define relative position in ENZ coordinates# Example: 50 km East, 100 km North, 200 km Up from stationenz=np.array([50e3,100e3,200e3])print("Relative position in ENZ frame:")print(f"East: {enz[0]/1000:.1f} km")print(f"North: {enz[1]/1000:.1f} km")print(f"Zenith: {enz[2]/1000:.1f} km\n")# Convert ENZ relative position to absolute ECEF positiontarget_ecef=bh.relative_position_enz_to_ecef(station_ecef,enz,bh.EllipsoidalConversionType.GEODETIC)print("Target position in ECEF:")print(f"x = {target_ecef[0]:.3f} m")print(f"y = {target_ecef[1]:.3f} m")print(f"z = {target_ecef[2]:.3f} m")print(f"Distance from Earth center: {np.linalg.norm(target_ecef)/1000:.3f} km")
Ground Station (Stanford):
Longitude: -122.17329° = -2.132326 rad
Latitude: 37.42692° = 0.653223 rad
Altitude: 32.0 m
Ground Station ECEF:
x = -2700408.551 m
y = -4292612.600 m
z = 3855145.604 m
Relative position in ENZ frame:
East: 50.0 km
North: 100.0 km
Zenith: 200.0 km
Target position in ECEF:
x = -2710296.807 m
y = -4402231.062 m
z = 4056108.325 m
Distance from Earth center: 6570.948 km
Ground Station (Stanford):
Longitude: -122.17329° = -2.132326 rad
Latitude: 37.42692° = 0.653223 rad
Altitude: 32.0 m
Ground Station ECEF:
x = -2700408.551 m
y = -4292612.600 m
z = 3855145.604 m
Relative position in ENZ frame:
East: 50.0 km
North: 100.0 km
Zenith: 200.0 km
Target position in ECEF:
x = -2710296.807 m
y = -4402231.062 m
z = 4056108.325 m
Distance from Earth center: 6570.948 km
importbraheasbhimportnumpyasnpbh.initialize_eop()# Define ground station location in geodetic coordinates# Stanford University: (lon=-122.17329°, lat=37.42692°, alt=32.0m)lon_deg=-122.17329lat_deg=37.42692alt_m=32.0print("Ground Station (Stanford):")print(f"Longitude: {lon_deg:.5f}° = {np.radians(lon_deg):.6f} rad")print(f"Latitude: {lat_deg:.5f}° = {np.radians(lat_deg):.6f} rad")print(f"Altitude: {alt_m:.1f} m\n")# Convert ground station to ECEFgeodetic_station=np.array([lon_deg,lat_deg,alt_m])station_ecef=bh.position_geodetic_to_ecef(geodetic_station,bh.AngleFormat.DEGREES)print("Ground Station ECEF:")print(f"x = {station_ecef[0]:.3f} m")print(f"y = {station_ecef[1]:.3f} m")print(f"z = {station_ecef[2]:.3f} m\n")# Define satellite in sun-synchronous orbit at 500 km altitude# SSO orbit passes over Stanford at approximately 10:30 AM local timeoe=np.array([bh.R_EARTH+500e3,0.001,97.8,240.0,0.0,90.0])# Define epoch when satellite passes near Stanford (Jan 1, 2024, 17:05 UTC)epoch=bh.Epoch.from_datetime(2024,1,1,17,5,0.0,0.0,bh.TimeSystem.UTC)# Convert orbital elements to ECI statesat_state_eci=bh.state_koe_to_eci(oe,bh.AngleFormat.DEGREES)# Convert ECI state to ECEF at the given epochsat_state_ecef=bh.state_eci_to_ecef(epoch,sat_state_eci)sat_ecef=sat_state_ecef[0:3]# Extract position onlyyear,month,day,hour,minute,second,ns=epoch.to_datetime()print(f"Epoch: {year}-{month:02d}-{day:02d}{hour:02d}:{minute:02d}:{second:06.3f} UTC")print("Satellite ECEF:")print(f"x = {sat_ecef[0]:.3f} m")print(f"y = {sat_ecef[1]:.3f} m")print(f"z = {sat_ecef[2]:.3f} m\n")# Convert satellite position to SEZ coordinates relative to ground stationsez=bh.relative_position_ecef_to_sez(station_ecef,sat_ecef,bh.EllipsoidalConversionType.GEODETIC)print("Satellite position in SEZ frame (relative to Stanford):")print(f"South: {sez[0]/1000:.3f} km")print(f"East: {sez[1]/1000:.3f} km")print(f"Zenith: {sez[2]/1000:.3f} km")print(f"Range: {np.linalg.norm(sez)/1000:.3f} km")
Ground Station (Stanford):
Longitude: -122.17329° = -2.132326 rad
Latitude: 37.42692° = 0.653223 rad
Altitude: 32.0 m
Ground Station ECEF:
x = -2700408.551 m
y = -4292612.600 m
z = 3855145.604 m
Epoch: 2024-01-01 17:05:00.000 UTC
Satellite ECEF:
x = -842800.791 m
y = 431996.779 m
z = 6812629.389 m
Satellite position in SEZ frame (relative to Stanford):
South: -5380.227 km
East: -943.412 km
Zenith: -2163.905 km
Range: 5875.317 km
Ground Station (Stanford):
Longitude: -122.17329° = -2.132326 rad
Latitude: 37.42692° = 0.653223 rad
Altitude: 32.0 m
Ground Station ECEF:
x = -2700408.551 m
y = -4292612.600 m
z = 3855145.604 m
Epoch: 2024-01-01 17:05:00.000 UTC
Satellite ECEF:
x = -842800.791 m
y = 431996.779 m
z = 6812629.389 m
Satellite position in SEZ frame (relative to Stanford):
South: -5380.227 km
East: -943.412 km
Zenith: -2163.905 km
Range: 5875.317 km
importbraheasbhimportnumpyasnpbh.initialize_eop()# Define ground station location in geodetic coordinates# Stanford University: (lon=-122.17329°, lat=37.42692°, alt=32.0m)lon_deg=-122.17329lat_deg=37.42692alt_m=32.0print("Ground Station (Stanford):")print(f"Longitude: {lon_deg:.5f}° = {np.radians(lon_deg):.6f} rad")print(f"Latitude: {lat_deg:.5f}° = {np.radians(lat_deg):.6f} rad")print(f"Altitude: {alt_m:.1f} m\n")# Convert ground station to ECEFgeodetic_station=np.array([lon_deg,lat_deg,alt_m])station_ecef=bh.position_geodetic_to_ecef(geodetic_station,bh.AngleFormat.DEGREES)print("Ground Station ECEF:")print(f"x = {station_ecef[0]:.3f} m")print(f"y = {station_ecef[1]:.3f} m")print(f"z = {station_ecef[2]:.3f} m\n")# Define relative position in SEZ coordinates# Example: 30 km South, 50 km East, 100 km Up from stationsez=np.array([30e3,50e3,100e3])print("Relative position in SEZ frame:")print(f"South: {sez[0]/1000:.1f} km")print(f"East: {sez[1]/1000:.1f} km")print(f"Zenith: {sez[2]/1000:.1f} km\n")# Convert SEZ relative position to absolute ECEF positiontarget_ecef=bh.relative_position_sez_to_ecef(station_ecef,sez,bh.EllipsoidalConversionType.GEODETIC)print("Target position in ECEF:")print(f"x = {target_ecef[0]:.3f} m")print(f"y = {target_ecef[1]:.3f} m")print(f"z = {target_ecef[2]:.3f} m")print(f"Distance from Earth center: {np.linalg.norm(target_ecef)/1000:.3f} km")
Ground Station (Stanford):
Longitude: -122.17329° = -2.132326 rad
Latitude: 37.42692° = 0.653223 rad
Altitude: 32.0 m
Ground Station ECEF:
x = -2700408.551 m
y = -4292612.600 m
z = 3855145.604 m
Relative position in SEZ frame:
South: 30.0 km
East: 50.0 km
Zenith: 100.0 km
Target position in ECEF:
x = -2710080.862 m
y = -4401887.794 m
z = 3892096.631 m
Distance from Earth center: 6470.670 km
Ground Station (Stanford):
Longitude: -122.17329° = -2.132326 rad
Latitude: 37.42692° = 0.653223 rad
Altitude: 32.0 m
Ground Station ECEF:
x = -2700408.551 m
y = -4292612.600 m
z = 3855145.604 m
Relative position in SEZ frame:
South: 30.0 km
East: 50.0 km
Zenith: 100.0 km
Target position in ECEF:
x = -2710080.862 m
y = -4401887.794 m
z = 3892096.631 m
Distance from Earth center: 6470.670 km
Azimuth and Elevation from Topocentric Coordinates¶
For object tracking, it's often more intuitive to work with azimuth (compass direction) and elevation (angle above the horizon) rather than Cartesian ENZ or SEZ coordinates. Both ENZ and SEZ topocentric systems can be converted to azimuth-elevation-range format.
Both ENZ and SEZ produce identical azimuth-elevation-range results for the same physical position. The choice between them is purely a matter of intermediate representation.