"""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