Skip to main content

VLCSim - Visible Light Communication Simulator

Python Version Poetry Coverage Tests License GitLab PyPI

VLCSim is an Event-Oriented simulator package for Visible Light Communication (VLC) systems. It provides a comprehensive framework for simulating dynamic VLC environments with support for resource allocation algorithms, RF fallback, and flexible room configurations.

Features

  • Dynamic Environment: Simulate real-time connections with arrivals and departures
  • Hybrid Communication: VLC with RF fallback support
  • Flexible Resource Allocation: Implement custom allocation algorithms
  • TDM Frame Management: Time-Division Multiplexing with configurable slices
  • Configurable Parameters: Customize VLC/room parameters for different scenarios
  • Event-Driven Simulation: Efficient discrete event simulation engine
  • Performance Metrics: Built-in SNR, capacity, blocking, waiting, and allocation metrics

Installation

# Install latest stable version
pip install vlcSim

# Or with Poetry
poetry add vlcSim

From Source (Development)

git clone https://gitlab.com/DaniloBorquez/simvlc.git
cd simvlc

# Using Poetry (recommended)
poetry install

# Or using pip
pip install -e .

Requirements

Runtime dependencies:

  • python >= 3.9
  • numpy >= 1.24.0: Numerical computations and random number generation

Development dependencies:

  • pytest >= 7.4.0: Testing framework
  • pytest-cov >= 4.1.0: Coverage reporting

See pyproject.toml for complete dependency specifications.

Paper Evaluation

The comprehensive paper evaluation script is in paper_evaluation/. Its versioned results are documented in paper_evaluation/README.md. New runs write to the ignored paper_evaluation/output/ directory by default. Install VLCSim from source before running the script so it can import the package:

python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -e .

Run the computational performance benchmarks sequentially when execution time is the measured response variable:

python paper_evaluation/comprehensive_evaluation.py \
  --evaluation performance \
  --replications 30 \
  --master-seed 20260903 \
  --performance-workers 1 \
  --warmup-runs 1

Run the case study with configurable parallelism for network metrics:

python paper_evaluation/comprehensive_evaluation.py \
  --evaluation case-study \
  --replications 30 \
  --master-seed 20260903 \
  --case-study-workers auto \
  --warmup-runs 1

Quick Start

Using the Built-in Default Algorithm

The simplest way to use VLCSim - no custom allocation code required:

from vlcsim import Simulator, VLed, RF

# Create a 10x10x3m room with 20 grids and 0.8 reflection coefficient
sim = Simulator(10.0, 10.0, 3.0, 20, 0.8)

# Add VLed access points
vled = VLed(5.0, 5.0, 3.0, 2, 2, 20, 60)  # x, y, z, nLedsX, nLedsY, power, theta
vled.sliceTime = 0.1
vled.slicesInFrame = 10
sim.scenario.addVLed(vled)

# Add RF access point as fallback
rf = RF(5.0, 5.0, 1.0)
rf.sliceTime = 0.1
rf.slicesInFrame = 10
sim.scenario.addRF(rf)

# Configure simulation parameters
sim.lambdaS = 3  # Mean inter-arrival time (exponential scale)
sim.goalConnections = 1000

# Initialize and run (default algorithm used automatically!)
sim.init()
sim.run()

# Get results
print(f"Blocking Probability: {sim.get_Blocking_Probability()}")
print(f"Waiting Probability: {sim.get_Waiting_Probability()}")
print(f"Attempted Connections: {sim.get_Attempted_Connections()}")
print(f"Allocated Connections: {sim.get_Allocated_Connections()}")
print(f"Waiting Connections: {sim.get_Waiting_Connections()}")
print(f"Blocked Connections: {sim.get_Blocked_Connections()}")

The built-in default algorithm (Controller.default_alloc):

  • ✅ Selects VLeds with best SNR (maximum 5 connections per VLed)
  • ✅ Falls back to RF if all VLeds are busy (maximum 12 connections per RF)
  • ✅ Automatically allocates TDM frame/slice positions
  • ✅ Works well for most VLC research scenarios

You only need a custom algorithm if you want different allocation behavior.

Core Concepts

Events

The simulator uses 5 types of events:

Event Description
ARRIVE New connection arrives to the system
RESUME Connection begins transmission
PAUSE Connection pauses transmission
DEPARTURE Connection ends transmission
RETRYING Unallocated connection attempts to reconnect

Scenario Components

  • VLed: Visible Light LED access points with configurable power and beam angle
  • RF: Radio Frequency access points for fallback communication
  • Receiver: Mobile devices with photodetector capabilities
  • Connection: Represents a data transmission session with capacity requirements

Resource Allocation

VLCSim includes a built-in default allocation algorithm that works for most scenarios. You can also implement custom allocation algorithms if you need different resource management strategies.

When to use the default algorithm:

  • General VLC network simulations
  • SNR-based allocation with RF fallback
  • Standard research scenarios

When to create a custom algorithm:

  • Testing novel allocation strategies
  • Implementing specific QoS policies
  • Research on resource optimization algorithms

Custom Allocation Example

from vlcsim import *

def custom_allocation_algorithm(receiver, connection: Connection, 
                                scenario: Scenario, controller: Controller):
    """Custom allocation: best VLed or RF fallback if overloaded"""
    candidates = []

    # Prefer feasible VLed links with available connection slots.
    for vled in scenario.vleds:
        if controller.numberOfActiveConnections(vled) >= Controller.MAX_ACTIVE_CONNECTIONS_PER_VLED:
            continue
        capacity = scenario.capacityVled(receiver, vled)
        snr = scenario.snrVled(receiver, vled)
        if Controller._is_feasible_link(capacity, snr):
            candidates.append((capacity, snr, vled))

    # Fall back to feasible RF links only when no VLed can serve the connection.
    if not candidates:
        for rf in scenario.rfs:
            if controller.numberOfActiveConnections(rf) >= Controller.MAX_ACTIVE_CONNECTIONS_PER_RF:
                continue
            capacity = scenario.capacityRf(receiver, rf)
            snr = scenario.snrRf(receiver, rf)
            if Controller._is_feasible_link(capacity, snr):
                candidates.append((capacity, snr, rf))

    if not candidates:
        return Controller.status.WAIT, connection

    capacity, snr, ap = max(candidates, key=lambda candidate: candidate[0])
    connection.AP = ap
    connection.receiver.capacityFromAP = capacity
    connection.snr = snr

    # Calculate required slices
    numberOfSlices = connection.numberOfSlicesNeeded(
        connection.capacityRequired, capacity
    )

    # Assign slices using the same scheduler as the built-in allocator.
    Controller._assign_frame_slices(connection, controller, numberOfSlices)
    
    return Controller.status.ALLOCATED, connection

# Setup simulation with 20x20x2.15m room
sim = Simulator(20.0, 20.0, 2.15, 10, 0.8)

# Add 4 VLeds in a grid pattern
for x, y in [(-7.5, -7.5), (-7.5, 7.5), (7.5, -7.5), (7.5, 7.5)]:
    vled = VLed(x, y, 2.15, 60, 60, 20, 70)
    vled.sliceTime = 0.2
    vled.slicesInFrame = 10
    vled.B = 0.5e5
    sim.scenario.addVLed(vled)

# Add RF fallback
rf = RF(0, 0, 0.85)
rf.sliceTime = 0.2
rf.slicesInFrame = 10
rf.B = 0.5e5
sim.scenario.addRF(rf)

# Configure simulation parameters
sim.set_allocation_algorithm(custom_allocation_algorithm)
sim.goalConnections = 60
sim.lambdaS = 1  # Mean inter-arrival time
sim.upper_random_wait = 20
sim.lower_random_wait = 2
sim.lower_capacity_required = 1e5
sim.upper_capacity_required = 5e5

# Run simulation
sim.init()
sim.run()

Testing

VLCSim has comprehensive test coverage (72%) with 166 tests.

Run Tests

# All tests
pytest tests/

# With coverage
pytest tests/ --cov=vlcsim --cov-report=term

# Specific module
pytest tests/test_controller.py -v
pytest tests/test_simulator.py -v
pytest tests/test_scenario.py -v

Coverage by Module

Module Coverage
vlcsim/__init__.py 100%
vlcsim/scene/__init__.py 100%
vlcsim/scene/access_point.py 88%
vlcsim/scene/vled.py 88%
vlcsim/scene/rf.py 88%
vlcsim/scene/receiver.py 88%
vlcsim/scene/scenario.py 88%
vlcsim/controller/__init__.py 100%
vlcsim/controller/connection.py 71%
vlcsim/controller/controller.py 71%
vlcsim/simulator.py 49%
Total 72%

API Reference

Simulator Class

Main simulation engine for event-driven VLC simulations.

sim = Simulator(length, width, height, nGrids, rho)
sim.init()              # Initialize simulation
sim.run()               # Execute simulation
sim.set_allocation_algorithm(func)  # Set custom allocator
sim.print_initial_info()  # Display scenario configuration

Key Parameters:

  • lambdaS: Mean inter-arrival time used as the exponential scale parameter
  • mu: Deprecated legacy service parameter retained for compatibility; the current simulator does not sample independent service times from it
  • goalConnections: Total connections to simulate
  • seedArrive: Random seed for inter-arrival time generation
  • seedX, seedY, seedZ: Random seeds for position generation
  • seedRandomWait: Random seed for retry wait generation
  • seedCapacityRequired: Random seed for capacity requirement generation
  • seedDeparture: Legacy seed retained for compatibility; departures are generated by capacity/TDM progress
  • upper_random_wait, lower_random_wait: Retry delay bounds (seconds)
  • upper_capacity_required, lower_capacity_required: Capacity bounds (bps)

Key Metrics:

  • get_Blocking_Probability(): Ratio of definitively blocked (NOT_ALLOCATED) connections to attempted connections
  • get_Waiting_Probability(): Ratio of currently waiting (WAIT) connections to attempted connections
  • get_Attempted_Connections(): Connection arrivals processed by the simulator
  • get_Allocated_Connections(): Connections assigned to an AP
  • get_Waiting_Connections(): Connections currently waiting for retry
  • get_Blocked_Connections(): Connections rejected with NOT_ALLOCATED
  • get_Response_Time(): Per-connection time from arrival to first service
  • get_Average_Response_Time(): Mean response time for connections that reached first service
  • get_Turnaround_Time(): Per-connection time from arrival to completion
  • get_Average_Turnaround_Time(): Mean turnaround time for completed connections
  • get_Waiting_Time(): Per-connection total waiting time, including TDM gaps between slots
  • get_Average_Waiting_Time(): Mean total waiting time for completed connections

Time Metrics:

VLCSim reports response time once a connection reaches first service. Turnaround and total waiting time are reported for completed connections:

response_time = first_service_time - arrival_time
turnaround_time = finish_time - arrival_time
waiting_time = turnaround_time - active_service_time

first_service_time is the first RESUME event for a connection. active_service_time is the effective transmission time accumulated by the receiver. In TDM simulations, waiting time includes the initial delay before first service and the idle gaps between assigned slots or frames, so it can be larger than response time.

By default, run() stops when the arrival target is reached. To calculate turnaround and total waiting time for every generated connection, ask the simulator to complete pending active connections without creating new arrivals:

sim.run(complete_active_connections=True)

avg_response_time = sim.get_Average_Response_Time()
avg_turnaround_time = sim.get_Average_Turnaround_Time()
avg_waiting_time = sim.get_Average_Waiting_Time()

Reproducibility:

VLCSim uses local NumPy random generators for simulator-owned random streams. Set the relevant seed parameters before calling init() and record sim.get_random_seeds() with your results. For independent statistical replications, create a fresh Simulator for each replication and use distinct stream seeds derived from a master seed. See examples/reproducible_replications.py for detailed and aggregated CSV output, including 95% confidence interval bounds when at least two replications are available.

Scenario Class

Room configuration with access points.

scenario.addVLed(vled)   # Add VLC access point
scenario.addRF(rf)       # Add RF access point
scenario.capacityVled(receiver, vled)  # Calculate VLC capacity
scenario.capacityRf(receiver, rf)      # Calculate RF capacity

Controller Class

Manages connections and resource allocation.

controller.assignConnection(connection, time)
controller.numberOfActiveConnections(ap)
controller.framesState(ap)
controller.APPosition(ap)
controller.init()  # Initialize controller with APs

Connection Class

Represents a data transmission session.

connection.assignFrameSlice(frame, slice)
connection.numberOfSlicesNeeded(capacity, rate)
connection.nextSliceInAPWhenArriving(ap)

Key Properties:

  • id: Connection identifier
  • receiver: Receiver object
  • AP: Assigned access point (VLed or RF)
  • allocated: Allocation status (boolean)
  • capacityRequired: Required data rate (bps)
  • frameSlice: Assigned TDM slices

Configuration Parameters

VLed Parameters

vled = VLed(x, y, z, nLedsX, nLedsY, ledPower, theta)
  • x, y, z: Position coordinates (meters)
  • nLedsX, nLedsY: LED array dimensions (rows x columns)
  • ledPower: LED power (mW)
  • theta: Semi-angle at half illumination (degrees)
  • sliceTime: Time slice duration (seconds)
  • slicesInFrame: Number of slices per frame
  • B: Bandwidth (Hz)

RF Parameters

rf = RF(x, y, z, bf=5e6, pf=40, BERf=10e-5)
  • x, y, z: Position coordinates (meters)
  • bf: Bandwidth (Hz)
  • pf: Transmission power (dBm)
  • BERf: Bit Error Rate target
  • sliceTime: Time slice duration (seconds)
  • slicesInFrame: Number of slices per frame

Receiver Parameters

receiver = Receiver(x, y, z, aDet, ts, index, fov)
  • x, y, z: Position coordinates (meters)
  • aDet: Detector area (m²)
  • ts: Optical filter transmittance
  • index: Refractive index
  • fov: Field of view (degrees)

Contributing

Contributions are welcome! We follow Git-Flow workflow and Conventional Commits standards.

Quick Start:

  1. Fork the repository on GitLab
  2. Clone your fork and set up development environment
    git clone https://gitlab.com/YOUR_USERNAME/simvlc.git
    cd simvlc
    poetry install
    
  3. Create a feature branch using Git-Flow
    git flow feature start feature-name
    
  4. Make your changes with tests
  5. Run tests and ensure they pass
    poetry run pytest tests/ --cov=vlcsim
    
  6. Commit changes with descriptive messages (use Conventional Commits)
    git commit -m 'feat: add new feature description'
    
  7. Finish the feature branch
    git flow feature finish feature-name
    
  8. Push to your fork and create a Merge Request

For detailed guidelines, see CONTRIBUTING.md

Also see:

Development

Project Structure

vlcsim/
├── vlcsim/
│   ├── __init__.py         # Package initialization
│   ├── controller/         # Connection management and allocation module (modular structure)
│   │   ├── __init__.py       # Controller package exports
│   │   ├── connection.py     # Connection class (transmission session)
│   │   └── controller.py     # Controller class (resource allocation)
│   ├── scene/              # Physical infrastructure module (modular structure)
│   │   ├── __init__.py       # Scene package exports
│   │   ├── access_point.py   # AccessPoint base class
│   │   ├── vled.py           # VLed (Visible Light LED) class
│   │   ├── rf.py             # RF (Radio Frequency) class
│   │   ├── receiver.py       # Receiver device class
│   │   └── scenario.py       # Scenario environment class
│   └── simulator.py        # Event-driven simulation engine
├── tests/
│   ├── test_controller.py   # Controller tests (42 tests)
│   ├── test_simulator.py    # Simulator tests (40 tests)
│   ├── test_connection.py   # Connection tests (29 tests)
│   ├── test_scenario.py     # Scenario tests
│   ├── test_vled.py         # VLed tests
│   ├── test_rf.py           # RF tests
│   └── test_receiver.py     # Receiver tests
├── docs/                # Sphinx documentation
├── CHANGELOG.md         # Version history
├── VERSIONING.md        # Release workflow guide
├── README.md            # This file
├── pyproject.toml       # Poetry configuration
└── requirements.txt     # Pip fallback dependencies

Setting Up Development Environment

# Clone repository
git clone https://gitlab.com/DaniloBorquez/simvlc.git
cd simvlc

# Install with Poetry (recommended)
poetry install

# Or with pip
pip install -e .

# Run tests
poetry run pytest tests/

# Run tests with coverage
poetry run pytest tests/ --cov=vlcsim --cov-report=html

# View coverage report
open htmlcov/index.html

# Build package (uses dynamic versioning from Git tags)
poetry build

Release Process

This project uses poetry-dynamic-versioning for automatic version management from Git tags. For detailed release instructions, see VERSIONING.md.

# Quick release workflow (Git-Flow)
git flow release start 0.5.0
# Update CHANGELOG.md
git flow release finish 0.5.0
git push origin --all && git push origin --tags

Releases to PyPI are automatically triggered when version tags are pushed to the main branch.

License

This project is licensed under the MIT License - see the LICENSE.md file for details.

Project Statistics

  • Lines of Code: ~2,500
  • Test Coverage: 72%
  • Number of Tests: 166 passing
  • Python Version: 3.9+
  • Modules: 3 main modules (controller, scene, simulator)
  • Package Manager: Poetry with dynamic versioning
  • Latest Release: See CHANGELOG.md

Acknowledgments

  • Based on research in Visible Light Communication systems
  • Event-driven simulation methodology
  • TDM resource allocation strategies
  • Hybrid VLC/RF communication systems

Contact

For questions, issues, or contributions, please:


Made with dedication for VLC research and simulation

Release files for vlcSim 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vlcSim 0.8.0
File Size Uploaded
vlcsim-0.8.0.tar.gz 46.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vlcSim 0.8.0
File Interpreter ABI Platform
vlcsim-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 94.6 kB

Release files / vlcsim-0.8.0.tar.gz

Download URL vlcsim-0.8.0.tar.gz
Size 46.9 kB
Tags Source
SHA-256 checksum
How to use checksums
2eb7597f21677897df2d509cddb83e9cbb3f48a9c689c311de412acca33555e1
BLAKE2b-256 checksum
How to use checksums
d53185beac38147a04a1a2a159e073f8bb482f16838fbe407253a74e59b52d68
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.10.21 Linux/5.15.154+

Release files / vlcsim-0.8.0-py3-none-any.whl

Download URL vlcsim-0.8.0-py3-none-any.whl
Size 47.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b39e3595746d63828da1ae8c8c4033ed3ee372129b3531dc67396871cdadd8b9
BLAKE2b-256 checksum
How to use checksums
71525e9a4a95841bca4ed3c8f5bd394975bc995c079ec3341d1fea7af1851fa8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.5.1 CPython/3.10.21 Linux/5.15.154+

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.4

1 release file

0.3.3

1 release file

0.3.2

1 release file

0.3.1

1 release file

0.3.0

1 release file

0.2.6

1 release file

0.2.5

1 release file

0.2.4

1 release file

0.2.3

1 release file

0.2.2

1 release file

0.2.1

1 release file

0.2.0

1 release file

0.0.11

1 release file

0.0.10

1 release file

0.0.9

1 release file

0.0.8

1 release file

0.0.7

1 release file

0.0.6

1 release file

0.0.4

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page