Source code for sionna.rt.radio_devices.radio_device

#
# SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#

"""Class implementing a radio device, i.e., a transmitter or a receiver"""

import mitsuba as mi
import drjit as dr
from typing_extensions import Tuple, Self

from sionna.rt.utils import theta_phi_from_unit_vec

[docs] class RadioDevice: # pylint: disable=line-too-long r"""Class defining a generic radio device The classes :class:`~sionna.rt.Transmitter` and :class:`~sionna.rt.Receiver` inherit from this class and should be used. :param name: Name :param position: Position :math:`(x,y,z)` [m] :param orientation: Orientation specified through three angles :math:`(\alpha, \beta, \gamma)` corresponding to a 3D rotation as defined in :eq:`rotation`. This parameter is ignored if ``look_at`` is not :py:class:`None`. :param look_at: A position or the instance of :class:`~sionna.rt.RadioDevices` to look at. If set to :py:class:`None`, then ``orientation`` is used to orientate the device. :param velocity: Velocity vector of the radio device [m/s] :param color: Defines the RGB (red, green, blue) ``color`` parameter for the device as displayed in the previewer and renderer. Each RGB component must have a value within the range :math:`\in [0,1]`. :param display_radius: Defines the radius, in meters, of the sphere that will represent this device when displayed in the previewer and renderer. If not specified, the radius will be chosen automatically using a heuristic. """ def __init__(self, name: str, position: mi.Point3f, orientation: mi.Point3f | None = None, look_at: mi.Point3f | Self | None = None, velocity : mi.Vector3f | None = None, color: Tuple[float, float, float] = (0, 0, 0), display_radius: float | None = None): self._name = name self.position = position self.color = color self.display_radius = display_radius assert (orientation is None) or (look_at is None), \ "Only one of `orientation` or `look_at` can be specified." if look_at is None: self.orientation = mi.Point3f(orientation) \ if orientation is not None \ else mi.Point3f(0) else: self.look_at(look_at) if velocity is None: self.velocity = mi.Vector3f(0., 0., 0.) else: self.velocity = velocity @property def name(self): """ Name :type: :py:class:`str` """ return self._name @property def position(self): """ Get/set the position :type: :py:class:`mi.Point3f` """ return self._position @position.setter def position(self, v): self._position = mi.Point3f(v) @property def orientation(self): """ Get/set the orientation :type: :py:class:`mi.Point3f` """ return self._orientation @orientation.setter def orientation(self, v): self._orientation = mi.Point3f(v) @property def velocity(self): """ Get/set the velocity :type: :py:class:`mi.Vector3f` """ return self._velocity @velocity.setter def velocity(self, v): self._velocity = mi.Vector3f(v)
[docs] def look_at(self, target: mi.Point3f | Self): # pylint: disable=line-too-long r""" Sets the orientation so that the x-axis points toward a position, or radio device. Given a point :math:`\mathbf{x}\in\mathbb{R}^3` with spherical angles :math:`\theta` and :math:`\varphi`, the orientation of the radio device will be set equal to :math:`(\varphi, \frac{\pi}{2}-\theta, 0.0)`. :param target: A position, or instance of a :class:`~sionna.rt.RadioDevice`, in the scene to look at """ # Get position to look at from sionna.rt import SceneObject # pylint: disable=import-outside-toplevel if isinstance(target, (SceneObject, RadioDevice)): target = target.position else: target = mi.Point3f(target) # Compute angles relative to LCS x = target - self.position x = dr.normalize(x) theta, phi = theta_phi_from_unit_vec(x) alpha = phi # Rotation around z-axis beta = theta - dr.pi/2. # Rotation around y-axis gamma = 0.0 # Rotation around x-axis self.orientation = mi.Point3f(alpha, beta, gamma)
@property def color(self): r""" Get/set the the RGB (red, green, blue) color for the device as displayed in the previewer and renderer. Each RGB component must have a value within the range :math:`\in [0,1]`. :type: :py:class:`Tuple[float, float, float]` """ return self._color @color.setter def color(self, new_color): if len(new_color) == 3: if min(new_color) < 0. or max(new_color) > 1.: raise ValueError("Color components must be in the range (0,1)") self._color = new_color @property def display_radius(self): r""" :py:class:`float | None` : Get/set the radius [m] of the sphere that represents this device when displayed in the previewer and renderer. If set to `None`, the radius will be chosen automatically using a heuristic. """ return self._display_radius @display_radius.setter def display_radius(self, radius): assert (radius is None) or (radius >= 0), \ "The display radius must be a float >= 0 or None." self._display_radius = radius