Skip to content

Sun, sat predictor inside ESP32 #4

@drom

Description

@drom

To compute the azimuth and elevation of a satellite from a specific point on Earth using Two-Line Element (TLE) sets, you typically need to follow these three steps:

  1. Propagate the Orbit: Use the SGP4 (Simplified General Perturbations 4) algorithm to convert TLE data into Cartesian coordinates (Position and Velocity) in an Inertial Frame (TEME/ECI).
  2. Coordinate Transformation: Convert the satellite's position from the Inertial Frame (ECI) to the Earth-Centered, Earth-Fixed (ECEF) frame, accounting for Earth's rotation.
  3. Topocentric Calculation: Convert the ECEF coordinates relative to your ground station's Latitude, Longitude, and Altitude to find the Look Angles (Azimuth, Elevation, and Range).

Recommended C Libraries

Writing SGP4 from scratch is complex due to the heavy orbital mechanics involved. It is standard practice to use a validated library:


C Code Example (using a simplified math approach)

If you already have the satellite's ECI position from an SGP4 propagator, here is how you calculate the Azimuth and Elevation in C.

#include <stdio.h>
#include <math.h>

#define PI 3.14159265358979323846
#define RAD_TO_DEG (180.0 / PI)
#define DEG_TO_RAD (PI / 180.0)

typedef struct {
    double x, y, z;
} Vector3;

// Computes Azimuth and Elevation from Satellite (ECI) and Observer (Geodetic)
void calculate_look_angles(Vector3 satECI, double obsLat, double obsLon, double obsAlt, double lst, double *az, double *el) {
    // 1. Convert Observer Geodetic to ECEF (Approximate spherical Earth for brevity)
    double earthRadius = 6378.137; // km
    double r = earthRadius + obsAlt;
    Vector3 obsECEF;
    obsECEF.x = r * cos(obsLat * DEG_TO_RAD) * cos(obsLon * DEG_TO_RAD);
    obsECEF.y = r * cos(obsLat * DEG_TO_RAD) * sin(obsLon * DEG_TO_RAD);
    obsECEF.z = r * sin(obsLat * DEG_TO_RAD);

    // 2. Convert Sat ECI to ECEF (Simplified: rotation by Local Sidereal Time)
    Vector3 satECEF;
    double theta = lst * DEG_TO_RAD; // LST is usually calculated from Julian Date
    satECEF.x = satECI.x * cos(theta) + satECI.y * sin(theta);
    satECEF.y = -satECI.x * sin(theta) + satECI.y * cos(theta);
    satECEF.z = satECI.z;

    // 3. Find Range Vector (Sat - Obs)
    double rx = satECEF.x - obsECEF.x;
    double ry = satECEF.y - obsECEF.y;
    double rz = satECEF.z - obsECEF.z;

    // 4. Transform to Topocentric (South-East-Zenith) frame
    double sinLat = sin(obsLat * DEG_TO_RAD);
    double cosLat = cos(obsLat * DEG_TO_RAD);
    double sinLon = sin(obsLon * DEG_TO_RAD);
    double cosLon = cos(obsLon * DEG_TO_RAD);

    double top_s = sinLat * cosLon * rx + sinLat * sinLon * ry - cosLat * rz;
    double top_e = -sinLon * rx + cosLon * ry;
    double top_z = cosLat * cosLon * rx + cosLat * sinLon * ry + sinLat * rz;

    // 5. Calculate Azimuth and Elevation
    double range = sqrt(top_s*top_s + top_e*top_e + top_z*top_z);
    *el = asin(top_z / range) * RAD_TO_DEG;
    *az = atan2(-top_e, top_s) * RAD_TO_DEG;
    
    if (*az < 0) *az += 360.0; // Standardize to 0-360
}

int main() {
    Vector3 satPos = {-4500.0, 1200.0, 5000.0}; // Example ECI coords in km
    double az, el;
    
    // Inputs: SatPos, ObsLat, ObsLon, ObsAlt (km), Local Sidereal Time (deg)
    calculate_look_angles(satPos, 34.05, -118.24, 0.1, 150.0, &az, &el);
    
    printf("Azimuth: %.2f°\nElevation: %.2f°\n", az, el);
    return 0;
}

Key Considerations

  1. SGP4 Implementation: For production, use the sgp4.c and sgp4.h files from the [Celestrak SGP4 software](https://celestrak.org/software/vallado-sw.php). It handles the complex perturbations (J2, J3, J4 gravity terms, atmospheric drag) required for TLEs.
  2. Time Handling: TLE accuracy depends heavily on the time of observation. You must convert your current UTC time to Julian Date (JD) and then to Local Sidereal Time (LST) to rotate the Earth correctly under the satellite.
  3. Coordinate Reference: SGP4 outputs in TEME (True Equator Mean Equinox). For high accuracy, you may need to apply precession and nutation corrections to move from TEME to a standard ECEF (WGS84) frame.

Would you like me to help you find the specific C header files for the SGP4 propagator or provide a Julian Date conversion function?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions