Source code for vlcsim.scene.receiver

"""Receiver device class for VLC simulation."""

import numpy as np
import math as m
from typing import Optional, Any


[docs] class Receiver: """Represents a receiver device in the VLC scenario. The Receiver class models a photodetector device with all physical and electrical parameters required for VLC simulation, including optical and electrical properties, timing information, and connection state. Attributes: receiversCreated: Class variable tracking the total number of receivers created. Properties: - Position: x, y, z coordinates and position vector - Optical: aDet (detector area), ts (symbol period), index (refractive index), fov (field of view), gCon (concentrator gain) - Electrical: q (electronic charge), s (photodetector responsivity), b (bandwidth), ibg (background current), cb (Boltzmann constant), tk (temperature), gv (voltage gain), n (capacitance), fr (noise factor), gm (transconductance) - Experimental: i1, i2 (calibration constants) - Connection: capacityFromAP, timeFirstConnected, goalTime, timeActive, timeFinished Example: >>> receiver = Receiver( ... x=2.5, y=3.0, z=0.85, ... aDet=1e-4, ts=0.1, index=1.5, fov=60.0 ... ) >>> receiver.ID 0 """ receiversCreated = 0 """Class variable tracking the total number of receivers created."""
[docs] def __init__( self, x: float, y: float, z: float, aDet: float, ts: float, index: float, fov: float, q: float = 1.6e-19, s: float = 0.54, b: float = 10e6, ibg: float = 5.1e-3, cb: float = 1.380649e-23, tk: float = 298.0, a: float = 1.0, gv: float = 10.0, n: float = 1.12e-6, fr: float = 1.5, gm: float = 3e-2, i1: float = 0.562, i2: float = 0.0868, ) -> None: """Initialize a receiver device with physical and electrical properties. Args: x: X coordinate of the receiver position in meters y: Y coordinate of the receiver position in meters z: Z coordinate of the receiver position in meters aDet: Photodetector active area in m² ts: Symbol period in seconds index: Refractive index of the optical concentrator fov: Field of view half-angle in degrees q: Electronic charge in coulombs (default: 1.6e-19 C) s: Photodetector responsivity in A/W (default: 0.54 A/W) b: Receiver bandwidth in Hz (default: 10 MHz) ibg: Background current in amperes (default: 5.1e-3 A) cb: Boltzmann constant in J/K (default: 1.380649e-23 J/K) tk: Absolute temperature in Kelvin (default: 298.0 K) a: Optical filter gain (default: 1.0) gv: Open-loop voltage gain (default: 10.0) n: Photodetector capacitance per unit area in F/m² (default: 1.12e-6 F/m²) fr: FET channel noise factor (default: 1.5) gm: FET transconductance in S (default: 3e-2 S) i1: Experimental calibration constant (default: 0.562) i2: Experimental calibration constant (default: 0.0868) Note: The receiver is automatically assigned a unique ID upon creation. The concentrator gain (gCon) is calculated from the index and FOV. """ self.__x = x self.__y = y self.__z = z self.__aDet = aDet self.__ts = ts self.__index = index self.__fov = fov self.__q = q self.__s = s self.__b = b self.__ibg = ibg self.__cb = cb self.__tk = tk self.__a = a self.__gv = gv self.__n = n self.__fr = fr self.__gm = gm self.__i1 = i1 self.__i2 = i2 self.__timeFirstConnected: Optional[float] = None self.__goalTime: Optional[float] = None self.__timeActive: float = 0.0 self.__timeFinished: Optional[float] = None self.__capacityFromAP: Optional[float] = None self.__gCon = (index**2) / (m.sin(m.radians(fov)) ** 2) self.__position = np.array([x, y, z]) self.__ID = Receiver.receiversCreated Receiver.receiversCreated += 1
@property def capacityFromAP(self) -> Optional[float]: """Get the capacity allocated from the access point. Returns: Optional[float]: Capacity from AP in bits/s, or None if not connected """ return self.__capacityFromAP @capacityFromAP.setter def capacityFromAP(self, value: float) -> None: """Set the capacity allocated from the access point. Args: value: Capacity value in bits/s """ self.__capacityFromAP = value @property def ID(self) -> int: """Get the unique identifier of this receiver. Returns: int: Unique receiver ID assigned at creation """ return self.__ID @ID.setter def ID(self, value: int) -> None: """Set the unique identifier of this receiver. Args: value: The ID value to set """ self.__ID = value @property def x(self) -> float: """Get the X coordinate of the receiver. Returns: float: X coordinate in meters """ return self.__x @x.setter def x(self, value: float) -> None: """Set the X coordinate of the receiver. Args: value: X coordinate in meters """ self.__x = value @property def y(self) -> float: """Get the Y coordinate of the receiver. Returns: float: Y coordinate in meters """ return self.__y @y.setter def y(self, value: float) -> None: """Set the Y coordinate of the receiver. Args: value: Y coordinate in meters """ self.__y = value @property def z(self) -> float: """Get the Z coordinate of the receiver. Returns: float: Z coordinate in meters """ return self.__z @z.setter def z(self, value: float) -> None: """Set the Z coordinate of the receiver. Args: value: Z coordinate in meters """ self.__z = value @property def aDet(self) -> float: """Get the photodetector active area. Returns: float: Photodetector active area in m² """ return self.__aDet @aDet.setter def aDet(self, value: float) -> None: """Set the photodetector active area. Args: value: Photodetector active area in m² """ self.__aDet = value @property def ts(self) -> float: """Get the symbol period. Returns: float: Symbol period in seconds """ return self.__ts @ts.setter def ts(self, value: float) -> None: """Set the symbol period. Args: value: Symbol period in seconds """ self.__ts = value @property def index(self) -> float: """Get the refractive index of the optical concentrator. Returns: float: Refractive index (dimensionless) """ return self.__index @index.setter def index(self, value: float) -> None: """Set the refractive index of the optical concentrator. Args: value: Refractive index value """ self.__index = value @property def fov(self) -> float: """Get the field of view half-angle. Returns: float: Field of view half-angle in degrees """ return self.__fov @fov.setter def fov(self, value: float) -> None: """Set the field of view half-angle. Args: value: Field of view half-angle in degrees """ self.__fov = value @property def gCon(self) -> float: """Get the concentrator gain. This is a read-only property calculated from the refractive index and FOV. Returns: float: Concentrator gain (dimensionless) """ return self.__gCon @property def position(self) -> np.ndarray[Any, np.dtype[np.float64]]: """Get the position vector of the receiver. Returns: np.ndarray[Any, np.dtype[np.float64]]: Position as numpy array [x, y, z] """ return self.__position @property def q(self) -> float: """Get the electronic charge. Returns: float: Electronic charge in coulombs (default: 1.6e-19 C) """ return self.__q @q.setter def q(self, value: float) -> None: """Set the electronic charge. Args: value: Electronic charge in coulombs """ self.__q = value @property def s(self) -> float: """Get the photodetector responsivity. Returns: float: Photodetector responsivity in A/W (default: 0.54 A/W) """ return self.__s @s.setter def s(self, value: float) -> None: """Set the photodetector responsivity. Args: value: Photodetector responsivity in A/W """ self.__s = value @property def b(self) -> float: """Get the receiver bandwidth. Returns: float: Receiver bandwidth in Hz (default: 10 MHz) """ return self.__b @b.setter def b(self, value: float) -> None: """Set the receiver bandwidth. Args: value: Receiver bandwidth in Hz """ self.__b = value @property def ibg(self) -> float: """Get the background current. Returns: float: Background current in amperes (default: 5.1e-3 A) """ return self.__ibg @ibg.setter def ibg(self, value: float) -> None: """Set the background current. Args: value: Background current in amperes """ self.__ibg = value @property def cb(self) -> float: """Get the Boltzmann constant. Returns: float: Boltzmann constant in J/K (default: 1.380649e-23 J/K) """ return self.__cb @cb.setter def cb(self, value: float) -> None: """Set the Boltzmann constant. Args: value: Boltzmann constant in J/K """ self.__cb = value @property def tk(self) -> float: """Get the absolute temperature. Returns: float: Temperature in Kelvin (default: 298.0 K) """ return self.__tk @tk.setter def tk(self, value: float) -> None: """Set the absolute temperature. Args: value: Temperature in Kelvin """ self.__tk = value @property def a(self) -> float: """Get the optical filter gain. Returns: float: Optical filter gain (dimensionless, default: 1.0) """ return self.__a @a.setter def a(self, value: float) -> None: """Set the optical filter gain. Args: value: Optical filter gain value """ self.__a = value @property def gv(self) -> float: """Get the open-loop voltage gain. Returns: float: Open-loop voltage gain (dimensionless, default: 10.0) """ return self.__gv @gv.setter def gv(self, value: float) -> None: """Set the open-loop voltage gain. Args: value: Open-loop voltage gain value """ self.__gv = value @property def n(self) -> float: """Get the photodetector capacitance per unit area. Returns: float: Capacitance in F/m² (default: 1.12e-6 F/m²) """ return self.__n @n.setter def n(self, value: float) -> None: """Set the photodetector capacitance per unit area. Args: value: Capacitance in F/m² """ self.__n = value @property def fr(self) -> float: """Get the FET channel noise factor. Returns: float: FET noise factor (dimensionless, default: 1.5) """ return self.__fr @fr.setter def fr(self, value: float) -> None: """Set the FET channel noise factor. Args: value: FET noise factor value """ self.__fr = value @property def gm(self) -> float: """Get the FET transconductance. Returns: float: FET transconductance in siemens (default: 3e-2 S) """ return self.__gm @gm.setter def gm(self, value: float) -> None: """Set the FET transconductance. Args: value: FET transconductance in siemens """ self.__gm = value @property def i1(self) -> float: """Get the first experimental calibration constant. Returns: float: Calibration constant (default: 0.562) """ return self.__i1 @i1.setter def i1(self, value: float) -> None: """Set the first experimental calibration constant. Args: value: Calibration constant value """ self.__i1 = value @property def i2(self) -> float: """Get the second experimental calibration constant. Returns: float: Calibration constant (default: 0.0868) """ return self.__i2 @i2.setter def i2(self, value: float) -> None: """Set the second experimental calibration constant. Args: value: Calibration constant value """ self.__i2 = value @property def timeFirstConnected(self) -> Optional[float]: """Get the time when the receiver was first connected. Returns: Optional[float]: Connection time in seconds, or None if not connected yet """ return self.__timeFirstConnected @timeFirstConnected.setter def timeFirstConnected(self, value: float) -> None: """Set the time when the receiver was first connected. Args: value: Connection time in seconds """ self.__timeFirstConnected = value @property def goalTime(self) -> Optional[float]: """Get the goal connection time for this receiver. The goal time represents the required connection duration based on SNR and capacity requirements. Returns: Optional[float]: Goal time in seconds, or None if not set """ return self.__goalTime @goalTime.setter def goalTime(self, value: float) -> None: """Set the goal connection time for this receiver. Args: value: Goal time in seconds """ self.__goalTime = value @property def timeActive(self) -> float: """Get the effective time the receiver has been connected. Returns: float: Active connection time in seconds """ return self.__timeActive @timeActive.setter def timeActive(self, value: float) -> None: """Set the effective time the receiver has been connected. Args: value: Active time in seconds """ self.__timeActive = value @property def timeFinished(self) -> Optional[float]: """Get the time when the receiver finished its connection. Returns: Optional[float]: Disconnection time in seconds, or None if still active """ return self.__timeFinished @timeFinished.setter def timeFinished(self, value: float) -> None: """Set the time when the receiver finished its connection. Args: value: Disconnection time in seconds """ self.__timeFinished = value