Exemple #1
0
def _check_sat2earth_input(azimuth_time, range_times,
                           frequency_doppler_centroid, wavelength):
    if not isinstance(azimuth_time, PreciseDateTime):
        raise RuntimeError("Azimuth should be a single absolute time")

    range_times = _utils.input_data_to_numpy_array_with_checks(range_times,
                                                               dtype=float)

    if (frequency_doppler_centroid is not None and wavelength is None) or (
            wavelength is not None and frequency_doppler_centroid is None):
        raise RuntimeError(
            "Frequency doppler centroid and wavelength should be both specified"
        )

    if frequency_doppler_centroid is not None:
        frequency_doppler_centroid = _utils.input_data_to_numpy_array_with_checks(
            frequency_doppler_centroid, dtype=float, ndim=1)

    if frequency_doppler_centroid is not None and (
            frequency_doppler_centroid.ndim != 1
            or frequency_doppler_centroid.shape != range_times.shape):
        if frequency_doppler_centroid.size == 1:
            frequency_doppler_centroid = np.full(range_times.shape,
                                                 frequency_doppler_centroid[0])
        else:
            raise RuntimeError(
                "Frequency doppler centroid vector should have the same shape of the range times vector: "
                + "{} != {}".format(frequency_doppler_centroid.shape,
                                    range_times.shape))

    return range_times, frequency_doppler_centroid
def direct_geocoding_bistatic(sensor_position_rx: np.ndarray,
                              sensor_velocity_rx: np.ndarray,
                              sensor_positions_tx: np.ndarray,
                              sensor_velocities_tx: np.ndarray,
                              range_times: np.ndarray,
                              look_direction: str,
                              geodetic_altitude: float,
                              frequency_doppler_centroid: np.ndarray,
                              wavelength: float,
                              initial_guess: np.ndarray = None) -> np.ndarray:
    """Perform bistatic direct geocoding

    :param sensor_position_rx: position of the sensor rx
    :param sensor_velocity_rx: velocity of the sensor rx
    :param sensor_positions_tx: positions of the sensor tx (one for each range time (3, N))
    :param sensor_velocities_tx: velocities of the sensor tx (one for each range time (3, N))
    :param range_times: range axis (N, 1) vector
    :param look_direction: either RIGHT or LEFT
    :param geodetic_altitude: the altitude over wgs84
    :param frequency_doppler_centroid: array with frequency doppler centroid values (N,1) vector
    :param wavelength: the wavelength
    :param initial_guess: initial guess for newton iterations. If not provided a guess will be computed [optional]

    :return: a matrix 3xN with the xyz coordinate of the points
    """
    # input validation
    _utils.check_type(wavelength, float)
    _utils.check_type(geodetic_altitude, float)
    sensor_position_rx = _utils.input_data_to_numpy_array_with_checks(
        sensor_position_rx, dtype=float, shape=(3, ))
    sensor_velocity_rx = _utils.input_data_to_numpy_array_with_checks(
        sensor_velocity_rx, dtype=float, shape=(3, ))
    sensor_positions_tx = _utils.input_data_to_numpy_array_with_checks(
        sensor_positions_tx, dtype=float, first_axis_size=3)
    sensor_velocities_tx = _utils.input_data_to_numpy_array_with_checks(
        sensor_velocities_tx, dtype=float, first_axis_size=3)

    # Optional initial guess
    if initial_guess is None:
        initial_guess = _direct_geocoding_monostatic_init(
            sensor_position_rx, sensor_velocity_rx,
            _mid_range_distance(range_times), _LOOK_SIGN[look_direction])

    output = np.zeros((3, range_times.size))
    for i_rg, (rg_time, pos_tx, vel_tx, f_dc) in enumerate(
            zip(range_times, sensor_positions_tx.T, sensor_velocities_tx.T,
                frequency_doppler_centroid)):
        output[:, i_rg] = _direct_geocoding_bistatic_core(
            initial_guess, sensor_position_rx, sensor_velocity_rx, pos_tx,
            vel_tx, rg_time, wavelength, f_dc, geodetic_altitude)
        initial_guess = output[:, i_rg].copy()
    return output
Exemple #3
0
def _get_interval_id_not_regular_real_axis(array: np.ndarray, increasing: bool,
                                           values: np.ndarray) -> np.ndarray:
    """
    The interval id is intended as the interval starting at the returned position, containing the point.
    If the point is exactly an edge of the interval, the interval starting at the point should be returned.

    :param array
    :param values: the values to be located in the array
    :return: np.ndarray of the same size as values
    """

    values = _utils.input_data_to_numpy_array_with_checks(values, ndim=1)
    out = np.empty((values.size, ))
    for k, v in enumerate(values):
        closest_pos = np.argmin(np.abs((array - v)))
        if increasing:
            if array[closest_pos] > v:
                out[k] = closest_pos - 1
            else:
                out[k] = closest_pos
        else:
            if array[closest_pos] < v:
                out[k] = closest_pos - 1
            else:
                out[k] = closest_pos
    return np.clip(out.astype(int), 0, array.size - 1)
Exemple #4
0
def llh2xyz(coordinates: Union[list, np.ndarray]) -> np.ndarray:
    """
    Conversion from llh coordinates to xyz.

    :param coordinates: a numpy ndarray of shape (3,), (3, 1) or (3, N) or a list.
    :return: a two dimensional numpy array of shape (3, N) with xyz coordinates
    """
    coordinates = _utils.input_data_to_numpy_array_with_checks(
        coordinates, dtype=float, first_axis_size=3, name="coordinates")
    if coordinates.ndim == 1:
        coordinates = coordinates.copy()
        coordinates.shape = (3, 1)

    lat = coordinates[0, :]
    lon = coordinates[1, :]
    h = coordinates[2, :]

    big_n = WGS84.semi_major_axis / np.sqrt(1 - WGS84.eccentricity_square *
                                            np.sin(lat)**2)
    r = (big_n + h) * np.cos(lat)

    x = r * np.cos(lon)
    y = r * np.sin(lon)
    z = (big_n * WGS84.semi_axes_ratio_min_max**2 + h) * np.sin(lat)

    return np.vstack((x, y, z)).astype(float)
Exemple #5
0
def xyz2llh(coordinates: Union[list, np.ndarray]) -> np.ndarray:
    """
    Conversion from xyz coordinates to llh.

    :param coordinates: a numpy ndarray of shape (3,), (3, 1) or (3, N) or a list.
    :return: a two dimensional numpy array of shape (3, N) with llh coordinates
    """
    coordinates = _utils.input_data_to_numpy_array_with_checks(
        coordinates, dtype=float, first_axis_size=3, name="coordinates")
    if coordinates.ndim == 1:
        coordinates = coordinates.copy()
        coordinates.shape = (3, 1)

    x = coordinates[0, :]
    y = coordinates[1, :]
    z = coordinates[2, :]

    lon = np.arctan2(y, x)

    k = np.maximum(np.absolute(x), np.absolute(y))
    k[np.where(k == 0)] = 1.

    c1 = x / k
    c2 = y / k

    r = k * np.sqrt(c1**2 + c2**2)

    beta = np.arctan2(z, r * WGS84.semi_axes_ratio_min_max)
    sin_beta, cos_beta = np.sin(beta), np.cos(beta)

    lat = np.arctan2(
        z + _A_MIN_TIMES_EP2 * sin_beta**3,
        r - _A_MAX_SQUARE_MINUS_A_MIN_SQUARE_DIVIDED_BY_A_MAX * cos_beta**3)
    beta_new = np.arctan2(WGS84.semi_axes_ratio_min_max * np.sin(lat),
                          np.cos(lat))

    for _ in range(_NUMBER_OF_ITERATIONS):
        if np.array_equal(beta, beta_new):
            break

        beta = beta_new
        sin_beta, cos_beta = np.sin(beta), np.cos(beta)

        lat = np.arctan2(
            z + _A_MIN_TIMES_EP2 * sin_beta**3, r -
            _A_MAX_SQUARE_MINUS_A_MIN_SQUARE_DIVIDED_BY_A_MAX * cos_beta**3)
        beta_new = np.arctan2(WGS84.semi_axes_ratio_min_max * np.sin(lat),
                              np.cos(lat))

    # Compute height
    sin_phi = np.sin(lat)
    big_n = WGS84.semi_major_axis / np.sqrt(1 - sin_phi**2 *
                                            WGS84.eccentricity_square)
    h = r * np.cos(lat) + (
        z + WGS84.eccentricity_square * big_n * sin_phi) * sin_phi - big_n

    return np.vstack((lat, lon, h)).astype(float)
Exemple #6
0
 def decorated_fun(self, *args_f, **kwargs_f):
     interpolation_axis = _utils.input_data_to_numpy_array_with_checks(
         args_f[0], ndim=1, name='Interpolation axis')
     return f(self, interpolation_axis, *args_f[1:], **kwargs_f)