Source code for vlcsim.scene.vled

"""VLed (Visible Light LED) access point class."""

import numpy as np
import math as m
from .access_point import AccessPoint


[docs] class VLed(AccessPoint): """Visible Light LED (VLed) access point for VLC communication. VLed represents a LED-based access point that transmits data using visible light. It extends AccessPoint with optical transmission parameters including LED array configuration, optical power, and beam characteristics. The class automatically calculates derived parameters such as total power and Lambertian emission order based on the LED configuration. Class Attributes: numberOfVLeds (int): Counter tracking total number of VLed instances created Properties: Inherited from AccessPoint: x, y, z, position, state, ID, B, sliceTime, slicesInFrame VLed-specific: nLedsX (int): Number of LEDs in X direction (rows) nLedsY (int): Number of LEDs in Y direction (columns) ledPower (float): Power per LED in milliwatts theta (float): Semi-angle at half illumination in degrees numberOfLeds (int): Total LEDs in array (read-only) totalPower (float): Total optical power in milliwatts ml (float): Lambertian emission order (read-only) Example: Creating a VLed access point:: # Create 2x2 LED array at ceiling center # Position: (5m, 5m, 3m) # Each LED: 20mW power # Beam angle: 60 degrees semi-angle vled = VLed(x=5.0, y=5.0, z=3.0, nLedsX=2, nLedsY=2, ledPower=20, theta=60) # Configure TDM parameters vled.sliceTime = 0.1 # 100ms per slice vled.slicesInFrame = 10 # 10 slices per frame vled.B = 5e5 # 500 kHz bandwidth # Total power is automatically calculated print(f\"Total power: {vled.totalPower}mW\") # 80mW (4 LEDs * 20mW) print(f\"Lambertian order: {vled.ml}\") Note: - ID is automatically assigned incrementally starting from 0 - Lambertian emission order ml is calculated as -log10(2)/log10(cos(theta)) - totalPower equals nLedsX * nLedsY * ledPower - Typical theta values range from 30-70 degrees for indoor VLC """ numberOfVLeds = 0
[docs] def __init__( self, x: float, y: float, z: float, nLedsX: int, nLedsY: int, ledPower: float, theta: float, ) -> None: """Initialize a VLed access point with optical parameters. Creates a VLed with specified position and LED array configuration. Automatically calculates total power and Lambertian emission order. Args: x: X-coordinate position in meters y: Y-coordinate position in meters z: Z-coordinate position in meters (typically ceiling height) nLedsX: Number of LEDs in X direction (rows in the array) nLedsY: Number of LEDs in Y direction (columns in the array) ledPower: Optical power per LED in milliwatts (mW) theta: Semi-angle at half illumination in degrees Example:: # Create 4x4 LED panel at room center ceiling vled = VLed(x=5.0, y=5.0, z=3.0, nLedsX=4, nLedsY=4, ledPower=50, theta=60) Note: - Total LEDs = nLedsX * nLedsY - Total power = numberOfLeds * ledPower - Lambertian order ml = -log10(2)/log10(cos(theta)) - VLed ID is auto-assigned from numberOfVLeds class counter """ AccessPoint.__init__(self, x, y, z) self.__nLedsX = nLedsX self.__nLedsY = nLedsY self.__ledPower = ledPower self.__theta = theta self._state = AccessPoint.stateap.IDLE self.__numberOfLeds = self.__nLedsX * self.__nLedsY self.__totalPower = self.__numberOfLeds * self.__ledPower self.__ml = -m.log10(2) / m.log10(m.cos(m.radians(theta))) self._ID = VLed.numberOfVLeds VLed.numberOfVLeds += 1 self._position = np.array([x, y, z])
@property def nLedsX(self) -> int: """Get the number of LEDs in X direction (rows). Returns: int: Number of LED rows in the array """ return self.__nLedsX @nLedsX.setter def nLedsX(self, value: int) -> None: """Set the number of LEDs in X direction (rows). Args: value: Number of LED rows """ self.__nLedsX = value @property def nLedsY(self) -> int: """Get the number of LEDs in Y direction (columns). Returns: int: Number of LED columns in the array """ return self.__nLedsY @nLedsY.setter def nLedsY(self, value: int) -> None: """Set the number of LEDs in Y direction (columns). Args: value: Number of LED columns """ self.__nLedsY = value @property def ledPower(self) -> float: """Get the optical power per individual LED. Returns: float: Power per LED in milliwatts (mW) """ return self.__ledPower @ledPower.setter def ledPower(self, value: float) -> None: """Set the optical power per individual LED. Args: value: Power per LED in milliwatts (mW) """ self.__ledPower = value @property def theta(self) -> float: """Get the semi-angle at half illumination. Theta defines the beam width of the LED. It is the angle from the optical axis at which the luminous intensity drops to half of its maximum value. Returns: float: Semi-angle in degrees Note: Typical values for indoor VLC range from 30-70 degrees. Smaller angles create more focused beams with higher intensity at center. """ return self.__theta @theta.setter def theta(self, value: float) -> None: """Set the semi-angle at half illumination. Args: value: Semi-angle in degrees """ self.__theta = value @property def numberOfLeds(self) -> int: """Get the total number of LEDs in this VLed array. Calculated as nLedsX * nLedsY. Returns: int: Total number of LEDs in the array """ return self.__numberOfLeds @property def totalPower(self) -> float: """Get the total optical power of this VLed array. Calculated as numberOfLeds * ledPower. Returns: float: Total optical power in milliwatts (mW) Example:: vled = VLed(5, 5, 3, nLedsX=4, nLedsY=4, ledPower=50, theta=60) # totalPower = 4 * 4 * 50 = 800 mW """ return self.__totalPower @totalPower.setter def totalPower(self, value: float): """Set the total optical power of this VLed array. Args: value: Total optical power in milliwatts (mW) """ self.__totalPower = value @property def ml(self) -> float: """Get the Lambertian emission order. The Lambertian order characterizes the directionality of the LED emission pattern. Higher values indicate more directional (focused) emission. The formula is: .. math:: ml = -\\frac{\\log_{10} 2}{\\log_{10} (\\cos(\\theta))} Returns: float: Lambertian emission order (dimensionless) Note: - theta=60° → ml ≈ 1 (wide beam) - theta=30° → ml ≈ 3.3 (narrow beam) - Higher ml means more concentrated light at center """ return self.__ml