Source code for sorts.radar.tx_rx

#!/usr/bin/env python

'''Defines an antenna's or entire radar system's radiation pattern, also defines physical antennas for RX and TX.

(c) 2016-2020 Juha Vierinen, Daniel Kastinen
'''

#Python standard import
import copy


#Third party import
import numpy as np


#Local import
from .. import frames


[docs]class Station(object): '''A radar station. :param float lat: Geographical latitude of radar station in decimal degrees (North+). :param float lon: Geographical longitude of radar station in decimal degrees (East+). :param float alt: Geographical altitude above geoid surface of radar station in meter. :param float min_elevation: Elevation threshold for the radar station in degrees, i.e. it cannot detect or point below this elevation. :param pyant.Beam beam: Radiation pattern for radar station. :ivar float lat: Geographical latitude of radar station in decimal degrees (North+). :ivar float lon: Geographical longitude of radar station in decimal degrees (East+). :ivar float alt: Geographical altitude above geoid surface of radar station in meter. :ivar float min_elevation: Elevation threshold for the radar station in degrees, i.e. it cannot detect or point below this elevation. :ivar numpy.array ecef: The ECEF coordinates of the radar station calculated using :func:`frames.geodetic_to_ITRS`. :ivar pyant.Beam beam: Radiation pattern for radar station. :ivar bool enabled: Indicates if this station is turned on or off. '''
[docs] def __init__(self, lat, lon, alt, min_elevation, beam): self.lat = lat self.lon = lon self.alt = alt self.min_elevation = min_elevation self.ecef = frames.geodetic_to_ITRS(lat, lon, alt, radians = False) self.beam = beam self.enabled = True self.pointing_range = None
[docs] def rebase(self, lat, lon, alt): '''Change geographical location of the station. ''' self.lat = lat self.lon = lon self.alt = alt self.ecef = frames.geodetic_to_ITRS(lat, lon, alt, radians = False)
[docs] def copy(self): st = Station( lat = self.lat, lon = self.lon, alt = self.alt, min_elevation = self.min_elevation, beam = self.beam.copy(), ) st.enabled = self.enabled return st
@property def frequency(self): return self.beam.frequency @property def wavelength(self): return self.beam.wavelength
[docs] def enu(self, ecefs): '''Converts a set of ECEF states to local ENU coordinates. ''' rel_ = ecefs.copy() rel_[:3,:] = rel_[:3,:] - self.ecef[:,None] rel_[:3,:] = frames.ecef_to_enu( self.lat, self.lon, self.alt, rel_[:3,:], radians=False, ) if ecefs.shape[0] > 3: rel_[3:,:] = frames.ecef_to_enu( self.lat, self.lon, self.alt, rel_[3:,:], radians=False, ) return rel_
[docs] def point(self, k): '''Point Station beam in local ENU coordinates. ''' self.beam.point(k)
[docs] def point_ecef(self, point): '''Point Station beam in location of ECEF coordinate. Returns local pointing direction. ''' k = frames.ecef_to_enu( self.lat, self.lon, self.alt, point, radians=False, ) k_norm = np.linalg.norm(k, axis=0) self.pointing_range = k_norm k = k/k_norm self.beam.point(k) return k
@property def pointing(self): '''Station beam pointing in local ENU coordinates. ''' return self.beam.pointing.copy() @property def pointing_ecef(self): '''Station beam pointing in local ENU coordinates. ''' return frames.enu_to_ecef( self.lat, self.lon, self.alt, self.beam.pointing, radians=False, ) def __str__(self): pass
[docs]class RX(Station): '''A radar receiving system. :param float noise: Receiver noise in Kelvin, i.e. system temperature. :ivar float noise: Receiver noise in Kelvin, i.e. system temperature. '''
[docs] def __init__(self, lat, lon, alt, min_elevation, beam, noise): super().__init__(lat, lon, alt, min_elevation, beam) self.noise = noise
[docs] def copy(self): st = RX( lat = self.lat, lon = self.lon, alt = self.alt, min_elevation = self.min_elevation, beam = self.beam.copy(), noise = self.noise, ) st.enabled = self.enabled return st
[docs]class TX(Station): '''A transmitting radar station :param float bandwidth: Transmissions bandwidth. :param float duty_cycle: Maximum duty cycle, i.e. fraction of time transmission can occur at maximum power. :param float power: Transmissions power in watts. :param float pulse_length: Length of transmission pulse. :param float ipp: Time between consecutive pulses. :param int n_ipp: Number of pulses to coherently integrate. :ivar float bandwidth: Transmissions bandwidth. :ivar float duty_cycle: Maximum duty cycle, i.e. fraction of time transmission can occur at maximum power. :ivar float power: Transmissions power in watts. :ivar float pulse_length: Length of transmission pulse. :ivar float ipp: Time between consecutive pulses. :ivar int n_ipp: Number of pulses to coherently integrate. :ivar float coh_int_bandwidth: Effective bandwidth of receiver noise after coherent integration. '''
[docs] def __init__(self, lat, lon, alt, min_elevation, beam, power, bandwidth, duty_cycle, pulse_length=1e-3, ipp=10e-3, n_ipp=20): super().__init__(lat, lon, alt, min_elevation, beam) self.bandwidth = bandwidth self.duty_cycle = duty_cycle self.power = power self.pulse_length = pulse_length self.ipp = ipp self.n_ipp = n_ipp self.coh_int_bandwidth = 1.0/(pulse_length*n_ipp)
[docs] def copy(self): st = TX( lat = self.lat, lon = self.lon, alt = self.alt, min_elevation = self.min_elevation, beam = self.beam.copy(), power = self.power, bandwidth = self.bandwidth, duty_cycle = self.duty_cycle, pulse_length = self.pulse_length, ipp = self.ipp, n_ipp = self.n_ipp, ) st.enabled = self.enabled return st