anomaly-detection-material-parameters-calibration

Sionna param calibration (research proj)
git clone https://git.ea.contact/anomaly-detection-material-parameters-calibration
Log | Files | Refs | README

radio_device.py (6237B)


      1 #
      2 # SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
      3 # SPDX-License-Identifier: Apache-2.0
      4 #
      5 """
      6 Class implementing a radio device, which can be either a transmitter or a
      7 receiver.
      8 """
      9 
     10 import tensorflow as tf
     11 
     12 from .object import Object
     13 from .utils import normalize, theta_phi_from_unit_vec
     14 from sionna.constants import PI
     15 
     16 
     17 class RadioDevice(Object):
     18     # pylint: disable=line-too-long
     19     r"""RadioDevice(name, position, orientation=[0.,0.,0.], look_at=None, dtype=tf.complex64)
     20 
     21     Class defining a generic radio device.
     22 
     23     :class:`~sionna.rt.Transmitter`, :class:`~sionna.rt.Receiver`,
     24     and :class:`~sionna.rt.RIS`
     25 
     26     inherit from this class and should be used.
     27 
     28     Parameters
     29     ----------
     30     name : str
     31         Name
     32 
     33     position : [3], float
     34         Position :math:`(x,y,z)` as three-dimensional vector
     35 
     36     orientation : [3], float
     37         Orientation :math:`(\alpha, \beta, \gamma)` specified
     38         through three angles corresponding to a 3D rotation
     39         as defined in :eq:`rotation`.
     40         This parameter is ignored if ``look_at`` is not `None`.
     41         Defaults to [0,0,0].
     42 
     43     look_at : [3], float | :class:`~sionna.rt.Transmitter` | :class:`~sionna.rt.Receiver` | :class:`~sionna.rt.RIS` | :class:`~sionna.rt.Camera` | None
     44         A position or the instance of a :class:`~sionna.rt.Transmitter`,
     45         :class:`~sionna.rt.Receiver`, :class:`~sionna.rt.RIS`, or :class:`~sionna.rt.Camera` to look at.
     46         If set to `None`, then ``orientation`` is used to orientate the device.
     47 
     48     color : [3], float
     49         Defines the RGB (red, green, blue) ``color`` parameter for the device as displayed in the previewer and renderer.
     50         Each RGB component must have a value within the range :math:`\in [0,1]`.
     51 
     52     dtype : tf.complex
     53         Datatype to be used in internal calculations.
     54         Defaults to `tf.complex64`.
     55     """
     56 
     57     def __init__(self,
     58                  name,
     59                  position=None,
     60                  orientation=(0.,0.,0.),
     61                  look_at=None,
     62                  color=(0,0,0),
     63                  dtype=tf.complex64,
     64                  **kwargs):
     65 
     66         if dtype not in (tf.complex64, tf.complex128):
     67             raise ValueError("`dtype` must be tf.complex64 or tf.complex128`")
     68         self._dtype = dtype
     69         self._rdtype = dtype.real_dtype
     70         self.color = color
     71 
     72         # Position and orientation are set through this call
     73         super().__init__(name=name,
     74                          position=position,
     75                          orientation=orientation,
     76                          look_at=look_at,
     77                          **kwargs)
     78 
     79     @property
     80     def position(self):
     81         """
     82         [3], tf.float : Get/set the position
     83         """
     84         return self._position
     85 
     86     @position.setter
     87     def position(self, v):
     88         if isinstance(v, tf.Variable):
     89             if v.dtype != self._rdtype:
     90                 msg = f"`position` must have dtype={self._rdtype}"
     91                 raise TypeError(msg)
     92             else:
     93                 self._position = v
     94         else:
     95             self._position = tf.cast(v, dtype=self._rdtype)
     96 
     97     @property
     98     def orientation(self):
     99         """
    100         [3], tf.float : Get/set the orientation
    101         """
    102         return self._orientation
    103 
    104     @orientation.setter
    105     def orientation(self, v):
    106         if isinstance(v, tf.Variable):
    107             if v.dtype != self._rdtype:
    108                 msg = f"`orientation` must have dtype={self._rdtype}"
    109                 raise TypeError(msg)
    110             else:
    111                 self._orientation = v
    112         else:
    113             self._orientation = tf.cast(v, dtype=self._rdtype)
    114 
    115     def look_at(self, target):
    116         # pylint: disable=line-too-long
    117         r"""
    118         Sets the orientation so that the x-axis points toward a
    119         position, radio device, RIS, or camera.
    120 
    121         Given a point :math:`\mathbf{x}\in\mathbb{R}^3` with spherical angles
    122         :math:`\theta` and :math:`\varphi`, the orientation of the radio device
    123         will be set equal to :math:`(\varphi, \frac{\pi}{2}-\theta, 0.0)`.
    124 
    125         Input
    126         -----
    127         target : [3], float | :class:`~sionna.rt.Transmitter` | :class:`~sionna.rt.Receiver` | :class:`~sionna.rt.RIS` | :class:`~sionna.rt.Camera` | str
    128             A position or the name or instance of a
    129             :class:`~sionna.rt.Transmitter`, :class:`~sionna.rt.Receiver`,
    130             :class:`~sionna.rt.RIS`, or
    131             :class:`~sionna.rt.Camera` in the scene to look at.
    132         """
    133         # Get position to look at
    134         if isinstance(target, str):
    135             obj = self.scene.get(target)
    136             if not isinstance(obj, Object):
    137                 raise ValueError(f"No camera, device, or object named '{target}' found.")
    138             else:
    139                 target = obj.position
    140         elif isinstance(target, Object):
    141             target = target.position
    142         else:
    143             target = tf.cast(target, dtype=self._rdtype)
    144             if not target.shape[0]==3:
    145                 raise ValueError("`target` must be a three-element vector)")
    146 
    147         # Compute angles relative to LCS
    148         x = target - self.position
    149         x, _ = normalize(x)
    150         theta, phi = theta_phi_from_unit_vec(x)
    151         alpha = phi # Rotation around z-axis
    152         beta = theta-PI/2 # Rotation around y-axis
    153         gamma = 0.0 # Rotation around x-axis
    154         self.orientation = (alpha, beta, gamma)
    155 
    156     @property
    157     def color(self):
    158         r"""
    159         [3], float : Get/set the the RGB (red, green, blue) color for the device as displayed in the previewer and renderer.
    160         Each RGB component must have a value within the range :math:`\in [0,1]`.
    161         """
    162         return self._color
    163 
    164     @color.setter
    165     def color(self, new_color):
    166         new_color = tf.cast(new_color, dtype=self._rdtype)
    167         if not (tf.rank(new_color) == 1 and new_color.shape[0] == 3):
    168             msg = "Color must be shaped as [r,g,b] (rank=1 and shape=[3])"
    169             raise ValueError(msg)
    170         if tf.reduce_any(new_color < 0.) or tf.reduce_any(new_color > 1.):
    171             msg = "Color components must be in the range (0,1)"
    172             raise ValueError(msg)
    173         self._color = new_color