Exemplo n.º 1
0
def gnss_earth_rotation_drift(dset: "Dataset") -> np.ndarray:
    """Determine earth rotation drift based on precise or broadcast satellite clock information

    The correction is caluclated after the description in Section 6.2.9 in :cite:`zhang2007`.

    Args:
        dset (Dataset):   Model data.

    Returns:
        numpy.ndarray:    GNSS earth rotation drift for each observation

    """
    correction = np.zeros(dset.num_obs)

    if "site_vel" not in dset.fields:
        # TODO: This should be replaced by dset.site_posvel
        dset.add_float("site_vel",
                       val=np.zeros([dset.num_obs, 3]),
                       unit="meter/second")

    for sys in dset.unique("system"):
        idx = dset.filter(system=sys)
        omega = constant.get("omega",
                             source=enums.gnss_id_to_reference_system[sys])
        correction[idx] = (
            omega / constant.c *
            (dset.site_vel[:, 0][idx] * dset.sat_posvel.trs.y[idx] -
             dset.site_vel[:, 1][idx] * dset.sat_posvel.trs.x[idx] +
             dset.site_pos.trs.x[idx] * dset.sat_posvel.trs.vy[idx] -
             dset.site_pos.trs.y[idx] * dset.sat_posvel.trs.vx[idx]))

    return correction
Exemplo n.º 2
0
def slr_relativistic(dset):
    """Calculate relativistic delay for all observations

    Args:
        dset:     Dataset containing the data

    Returns:
        Numpy array:  Correction in meters for each observation
    """
    eph = apriori.get("ephemerides")
    GM = constant.get("GM", source="egm_2008")
    site_norm = np.linalg.norm(dset.site_pos.gcrs, axis=1)
    sat_norm = np.linalg.norm(dset.sat_pos.gcrs, axis=1)
    geocenter_movement = eph.pos_bcrs(
        "earth", time=dset.time + TimeDelta(
            dset.up_leg, format="sec")) - eph.pos_bcrs("earth", time=dset.time)
    sta_sat_norm = np.linalg.norm(dset.sat_pos.gcrs - dset.site_pos.gcrs +
                                  geocenter_movement,
                                  axis=1)
    numerator = site_norm + sat_norm + sta_sat_norm
    denominator = site_norm + sat_norm - sta_sat_norm
    correction = np.array([
        math.log(numerator[i] / denominator[i])
        for i in range(0, len(numerator))
    ])

    return 2 * GM / constant.c**2 * correction
Exemplo n.º 3
0
def gnss_relativistic_clock_rate(dset):
    """Determine relativistic clock rate correction due to orbit eccentricity

    The correction is caluclated for precise and broadcast orbits after Eq. 6-19 in :cite:`zhang2007`.

    Args:
        dset (Dataset):   Model data.

    Returns:
        numpy.ndarray:    Relativistic clock rate correction due to orbit eccentricity corrections for each observation

    """

    gm = constant.get("GM", source="iers_2010")

    orbit = apriori.get(
        "orbit",
        apriori_orbit=dset.vars["orbit"],
        rundate=dset.analysis["rundate"],
        system=tuple(dset.unique("system")),
        station=dset.vars["station"],
    )

    a = np.power(orbit.get_ephemeris_field("sqrt_a", dset), 2)

    correction = 2 * gm / constant.c * (1 / a -
                                        1 / dset.sat_posvel.trs.pos.length)

    return correction
Exemplo n.º 4
0
 def parse_flux(self, line, cache):
     if not line["day"]:
         return
     day = int(line.pop("day"))
     for month in line:
         if not line[month]:
             continue
         time = None
         try:
             time = datetime(cache["year"], int(month), day)
             self.data[time] = int(line[month])
         except ValueError:  # Todo: Can we use __missing__ instead? Makes it possible to add warning
             if time is not None:
                 self.data[time] = constant.get("S", source="book")
Exemplo n.º 5
0
def slr_relativistic(dset):
    """Calculate relativistic delay for all observations

    Args:
        dset:     Dataset containing the data

    Returns:
        Numpy array:  Correction in meters for each observation
    """
    GM = constant.get("GM", source="egm_2008")
    site_norm = np.linalg.norm(dset.site_pos.gcrs, axis=1)
    sat_norm = np.linalg.norm(dset.sat_pos.gcrs, axis=1)
    sta_sat_norm = np.linalg.norm(dset.sat_pos.gcrs.pos - dset.site_pos.gcrs, axis=1)
    numerator = site_norm + sat_norm + sta_sat_norm
    denominator = site_norm + sat_norm - sta_sat_norm
    correction = np.array([math.log(numerator[i] / denominator[i]) for i in range(0, len(numerator))])

    return 2 * GM / constant.c ** 2 * correction
Exemplo n.º 6
0
# External imports
import scipy.constants as scp
from scipy import stats
from scipy.optimize import lsq_linear
import numpy as np

#  Midgard imports
from midgard.data.position import Position  # Import Position class
from midgard.collections import enums
from midgard.math.constant import constant

# define constants
# wavelength for E1 (D1X) - lambda_E1
lambda_E1 = constant.c / enums.gnss_freq_E.E1  # eller constant.c /enums.gnss_freq_E.E1.value
E_OMGA = constant.get(
    "omega", source="wgs84")  # Earth Angular Velocity (IS-GPS) (rad/s)
logger = print


# =================================================
#  class definition of Single Point Velocity (SPV)
# =================================================
class spvDoppler(object):

    # =========================================
    #    METHOD 1: Constructor/Initializer
    # =========================================
    def __init__(self, z, H, x, dx, Qx):
        """Initialize the single point velocity estimation by Doppler

        Args:
Exemplo n.º 7
0
def vlbi_grav_delay(dset):
    """Calculate the gravitational delay

    The implementation is described in IERS Conventions [1]_, section 11.1, in particular equation (11.9).

    Args:
        dset:     A Dataset containing model data.

    Returns:
        Numpy array: Gravitational delay in meters for each observation.
    """
    eph = apriori.get("ephemerides", time=dset.time)
    grav_delay = np.zeros(dset.num_obs)

    # List of celestial bodies. Major moons are also recommended, like Titan, Ganymedes, ...
    bodies = [
        "mercury barycenter",
        "venus barycenter",
        "earth",
        "moon",
        "mars barycenter",
        "jupiter barycenter",
        "saturn barycenter",
        "uranus barycenter",
        "neptune barycenter",
        "pluto barycenter",
        "sun",
    ]

    bcrs_vel_earth = eph.vel_bcrs("earth")

    baseline_gcrs = dset.site_pos_2.gcrs.pos - dset.site_pos_1.gcrs.pos
    src_dot_baseline = (dset.src_dir.unit_vector[:, None, :] @ baseline_gcrs.mat)[:, 0, 0]

    # Equation 11.6
    bcrs_site1 = eph.pos_bcrs("earth") + dset.site_pos_1.gcrs.pos.val
    bcrs_site2 = eph.pos_bcrs("earth") + dset.site_pos_2.gcrs.pos.val

    for body in bodies:
        try:
            GM_name = "GM" if body == "earth" else f"GM_{body.split()[0]}"
            GM_body = constant.get(GM_name, source=eph.ephemerides)
        except KeyError:
            log.warn(
                f"The GM value of {body.split()[0].title()} is not defined for {eph.ephemerides}. "
                f"Correction set to zero."
            )
            continue
        bcrs_body_t1 = eph.pos_bcrs(body)

        # Equation 11.3
        delta_t = TimeDelta(
            np.maximum(0, dset.src_dir.unit_vector[:, None, :] @ (bcrs_body_t1 - bcrs_site1)[:, :, None])[:, 0, 0]
            * Unit.second2day
            / constant.c,
            fmt="jd",
            scale="tdb",
        )
        time_1J = dset.time.tdb - delta_t

        # Equation 11.4
        bcrs_body_t1J = eph.pos_bcrs(body, time=time_1J)
        vector_body_site1 = bcrs_site1 - bcrs_body_t1J

        # Equation 11.5
        vector_body_site2 = bcrs_site2 - bcrs_body_t1J - bcrs_vel_earth / constant.c * src_dot_baseline[:, None]

        # Needed for equation 11.1
        norm_body_site1 = np.linalg.norm(vector_body_site1, axis=1)
        src_dot_vector_body_site1 = (dset.src_dir.unit_vector[:, None, :] @ vector_body_site1[:, :, None])[:, 0, 0]
        nomJ = norm_body_site1 + src_dot_vector_body_site1
        denomJ = (
            np.linalg.norm(vector_body_site2, axis=1)
            + (dset.src_dir.unit_vector[:, None, :] @ vector_body_site2[:, :, None])[:, 0, 0]
        )

        # Main correction (equation 11.1)
        grav_delay += 2 * GM_body / constant.c ** 2 * np.log(nomJ / denomJ)

        # Higher order correction  (equation 11.14)
        baseline_dot_vector_body_site1 = (baseline_gcrs.val[:, None, :] @ vector_body_site1[:, :, None])[:, 0, 0]
        grav_delay += (
            4
            * GM_body ** 2
            / constant.c ** 4
            * (baseline_dot_vector_body_site1 / norm_body_site1 + src_dot_baseline)
            / (norm_body_site1 + src_dot_vector_body_site1) ** 2
        )

    # Denominator (equation 11.9)
    denominator = (
        1
        + (
            (bcrs_vel_earth + dset.site_pos_2.gcrs.vel.val)[:, None, :]
            @ dset.src_dir.unit_vector[:, :, None]
            / constant.c
        )[:, 0, 0]
    )

    return grav_delay / denominator
Exemplo n.º 8
0
    def _get_pco_sat(self, sat, sys_freq, used_date):
        """Get satellite PCO in satellite reference system

        If two frequencies are given over the 'sys_freq' argument, then the PCOs are determined as an ionospheric linear
        combination.

        Args:
            sat (str):                      Satellite identifier.
            sys_freq (dict):                Dictionary with frequency or frequency combination given for GNSS
                                            identifier:
                                                sys_freq = { <sys_id>: <freq> }
                                                (e.g. sys_freq = {'E': 'E1',  'G': 'L1_L2'} )
            used_date (datetime.datetime):  Correct date for use of satellite antenna corrections

        Returns:
            numpy.ndarray: Satellite PCO in satellite reference system
        """
        # GNSS          GNSS freq        ANTEX freq
        # ___________________________________________
        # C (BeiDou):   B1               'C02'
        #               B2               'C07'
        #               B3               'C06'
        # G (GPS):      L1               'G01'
        #               L2               'G02'
        #               L5               'G05'
        # R (GLONASS):  G1               'R01'
        #               G2               'R02'
        # E (Galileo):  E1               'E01'
        #               E5 (E5a+E5b)     'E08'
        #               E5a              'E05'
        #               E5b              'E07'
        #               E6               'E06'
        # I (IRNSS):    L5               'I05'
        #               S                'I09'
        # J (QZSS):     L1               'J01'
        #               L2               'J02'
        #               L5               'J05'
        #               LEX              'J06'
        # S (SBAS):     L1               'S01'
        #               L5               'S05'
        gnss_to_antex_freq = {
            "C": {"B1": "C02", "B2": "C07", "B3": "C06"},
            "E": {"E1": "E01", "E5": "E08", "E5a": "E05", "E5b": "E07", "E6": "E06"},
            "G": {"L1": "G01", "L2": "G02", "L5": "G05"},
            "I": {"L5": "I05", "S": "I09"},
            "J": {"L1": "J01", "L2": "J02", "L5": "J05", "LEX": "J06"},
            "R": {"G1": "R01", "G2": "R02", "G3": "R03"},
            "S": {"L1": "S01", "L5": "S05"},
        }

        # Get GNSS and frequency/frequencies
        sys = sat[0]  # GNSS identifier
        freq = sys_freq[sys]
        if "_" in freq:
            freq = freq.split("_")
        else:
            freq = [freq]

        # Get satellite PCO for one frequency
        if len(freq) == 1:

            # Get satellite phase center offset (PCO) given in satellite reference system
            pco_sat = np.array([self.data[sat][used_date][gnss_to_antex_freq[sys][freq[0]]]["neu"]])

            log.debug(f"PCO of satellite {sat} for frequency {sys}:{sys_freq[sys]}: {pco_sat.tolist()[0]}.")

        # Get satellite PCO for ionospheric-free linear combination based on two-frequencies
        elif len(freq) == 2:

            # Coefficient of ionospheric-free linear combination
            f1 = constant.get("gnss_freq_" + sys, source=freq[0])  # Frequency of 1st band
            f2 = constant.get("gnss_freq_" + sys, source=freq[1])  # Frequency of 2nd band
            n = f1 ** 2 / (f1 ** 2 - f2 ** 2)
            m = -f2 ** 2 / (f1 ** 2 - f2 ** 2)

            # Get satellite phase center offset (PCO) given in satellite reference system
            pco_sat_f1 = np.array([self.data[sat][used_date][gnss_to_antex_freq[sys][freq[0]]]["neu"]])
            pco_sat_f2 = np.array([self.data[sat][used_date][gnss_to_antex_freq[sys][freq[1]]]["neu"]])

            # Generate ionospheric-free linear combination
            pco_sat = n * pco_sat_f1 + m * pco_sat_f2

            log.debug(
                f"Ionospheric-free linear combination PCOs of satellite {sat} for"
                f" frequency combination {sys}:{sys_freq[sys]}:  {pco_sat.tolist()[0]}."
            )

        else:
            log.fatal(
                f"Wrong frequency type '{sys}:{'_'.join(freq)}'. Note: 'signals' configuration option"
                f" should represent one- or two-frequencies (e.g. E:E1 or E:E1_E5a)."
            )

        return pco_sat
Exemplo n.º 9
0
from midgard.math.constant import constant

# Where imports
from where import data
from where import cleaners
from where import parsers
from where.apriori import orbit
from where.lib import config
from where.lib import log
from where.lib import plugins
from where.lib import rotation
from where.lib.unit import Unit

# Earth's gravitational constant
GM = {
    "C": constant.get("GM", source="cgcs2000"),
    "E": constant.get("GM", source="gtrf"),
    "G": constant.get("GM", source="wgs84"),
    "I": constant.get("GM", source="wgs84"),
    "J": constant.get("GM", source="jgs"),
}

# Earth's rotation rate
OMEGA = {
    "C": constant.get("omega", source="cgcs2000"),
    "E": constant.get("omega", source="gtrf"),
    "G": constant.get("omega", source="wgs84"),
    "I": constant.get("omega", source="wgs84"),
    "J": constant.get("omega", source="jgs"),
}