Skip to content

Quick Start

Five queries that show what pg_orbit can do. Each builds on the previous — from a single planet observation to planning an interplanetary trajectory.

  1. Where is Jupiter right now?

    The observer type takes geodetic coordinates as a compact string. This observer is in Boulder, Colorado at 1655m elevation.

    SELECT topo_azimuth(t) AS az,
    topo_elevation(t) AS el,
    topo_range(t) / 149597870.7 AS distance_au
    FROM planet_observe(5, '40.0N 105.3W 1655m'::observer, now()) t;

    Body ID 5 is Jupiter (the VSOP87 convention: 1=Mercury through 8=Neptune). The result gives azimuth and elevation in degrees, plus range in AU.

  2. What’s the entire solar system doing?

    Use generate_series to loop over all 8 planets and compute their heliocentric positions:

    SELECT body_id,
    CASE body_id
    WHEN 1 THEN 'Mercury' WHEN 2 THEN 'Venus'
    WHEN 3 THEN 'Earth' WHEN 4 THEN 'Mars'
    WHEN 5 THEN 'Jupiter' WHEN 6 THEN 'Saturn'
    WHEN 7 THEN 'Uranus' WHEN 8 THEN 'Neptune'
    END AS name,
    round(helio_distance(planet_heliocentric(body_id, now()))::numeric, 4) AS distance_au
    FROM generate_series(1, 8) AS body_id;

    One query, eight planets, heliocentric distances in AU. No loops, no external libraries.

  3. Predict ISS passes over your location

    First, define a TLE and observer. Then predict all passes in the next 24 hours above 10 degrees elevation:

    WITH iss AS (
    SELECT '1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025
    2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle AS tle
    )
    SELECT pass_aos(p) AS rise_time,
    pass_max_el(p) AS max_elevation,
    pass_los(p) AS set_time
    FROM iss, predict_passes(tle, '40.0N 105.3W 1655m'::observer,
    now(), now() + interval '24 hours', 10.0) p;

    The 10.0 parameter is the minimum elevation filter in degrees. predict_passes returns a set of pass_event records with AOS, TCA, and LOS times plus azimuth data.

  4. When will Jupiter produce radio bursts tonight?

    Jupiter emits powerful decametric radio bursts when Io is in certain orbital positions relative to Jupiter’s Central Meridian Longitude. Predict the best windows:

    SELECT t,
    round(io_phase_angle(t)::numeric, 1) AS io_phase,
    round(jupiter_cml('40.0N 105.3W 1655m'::observer, t)::numeric, 1) AS cml,
    round(jupiter_burst_probability(
    io_phase_angle(t),
    jupiter_cml('40.0N 105.3W 1655m'::observer, t)
    )::numeric, 3) AS burst_prob
    FROM generate_series(
    now(),
    now() + interval '12 hours',
    interval '10 minutes'
    ) AS t
    WHERE jupiter_burst_probability(
    io_phase_angle(t),
    jupiter_cml('40.0N 105.3W 1655m'::observer, t)
    ) > 0.3;

    This scans the next 12 hours in 10-minute steps and filters for windows where burst probability exceeds 30%. The underlying model uses the Carr et al. (1983) source regions A, B, C, and D.

  5. Plan an Earth-Mars transfer

    Use the Lambert solver to find the transfer orbit for a given departure and arrival date:

    SELECT round(c3_departure::numeric, 2) AS c3_depart_km2s2,
    round(c3_arrival::numeric, 2) AS c3_arrive_km2s2,
    round(tof_days::numeric, 1) AS flight_days,
    round(transfer_sma::numeric, 4) AS sma_au
    FROM lambert_transfer(
    3, 4, -- Earth to Mars
    '2028-10-01'::timestamptz, -- departure
    '2029-06-15'::timestamptz -- arrival
    );

    Body IDs 3 (Earth) and 4 (Mars). The result gives departure C3 (the energy you need to leave Earth), arrival C3, time of flight, and the transfer orbit’s semi-major axis. For a full pork chop plot, wrap this in a CROSS JOIN of departure and arrival date ranges — see the Interplanetary Trajectories guide.

You’ve seen the five domains pg_orbit covers. For deeper dives: