handoverlab 2.4.2__tar.gz → 2.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- handoverlab-2.6.0/.zenodo.json +39 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/CHANGELOG.md +131 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/CITATION.cff +9 -4
- {handoverlab-2.4.2 → handoverlab-2.6.0}/PKG-INFO +51 -13
- {handoverlab-2.4.2 → handoverlab-2.6.0}/README.md +50 -12
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/calibration.md +208 -8
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/comparison.md +9 -9
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/ai-mobility.md +9 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/indoor-rural.md +5 -2
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/learning-rule.md +8 -0
- handoverlab-2.6.0/docs/guides/ns3-bridge.md +157 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/upper-mid-band.md +4 -1
- handoverlab-2.6.0/docs/images/dashboard-charts.png +0 -0
- handoverlab-2.6.0/docs/images/dashboard.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/index.md +1 -1
- handoverlab-2.6.0/docs/reference/api/ns3bridge.md +28 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/cli.md +83 -4
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/fr3-urban-15ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/highway-tr37885-30ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/highway-tr37885-4ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/hst-fr2-28ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/indoor-office-4ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/ns3-urban-3.5ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/open-area-10ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/rural-700mhz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/suburban-sma-7ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/urban-grid-10ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/urban-grid-28ghz-beams.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/urban-macro-tr37885-4ghz.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/stability.md +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/standard-compliance.md +2 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/user_guide.md +18 -7
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/verification.md +20 -2
- handoverlab-2.6.0/examples/ns3_study_v1.yaml +24 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/mkdocs.yml +2 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/pyproject.toml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/__init__.py +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/cli.py +101 -2
- handoverlab-2.6.0/src/handoverlab/ns3bridge/__init__.py +28 -0
- handoverlab-2.6.0/src/handoverlab/ns3bridge/compare.py +172 -0
- handoverlab-2.6.0/src/handoverlab/ns3bridge/export.py +102 -0
- handoverlab-2.6.0/src/handoverlab/ns3bridge/results.py +116 -0
- handoverlab-2.6.0/src/handoverlab/ns3bridge/study.py +270 -0
- handoverlab-2.6.0/src/handoverlab/ns3bridge/templates.py +192 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/fr3-urban-15ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/highway-tr37885-30ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/highway-tr37885-4ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/hst-fr2-28ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/indoor-office-4ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/ns3-urban-3.5ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/open-area-10ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/rural-700mhz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/suburban-sma-7ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/urban-grid-10ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/urban-grid-28ghz-beams.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/urban-macro-tr37885-4ghz.yaml +1 -1
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/stability.py +3 -2
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/__init__.py +6 -3
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/ns3.py +47 -15
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab.egg-info/PKG-INFO +51 -13
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab.egg-info/SOURCES.txt +11 -0
- handoverlab-2.6.0/tests/data/ns3bridge/v1_runs.json +86 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/data/public_api.json +21 -0
- handoverlab-2.6.0/tests/test_ns3bridge.py +262 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_verify.py +42 -0
- handoverlab-2.4.2/.zenodo.json +0 -39
- handoverlab-2.4.2/docs/images/dashboard-charts.png +0 -0
- handoverlab-2.4.2/docs/images/dashboard.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/CODE_OF_CONDUCT.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/CONTRIBUTING.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/LICENSE +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/MANIFEST.in +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/SECURITY.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/RELEASING.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/calibration-3gpp.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/add-scenario.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/beams-layers.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/buffers.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/daps-ltm.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/dashboard.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/dual-connectivity.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/export-event-logs.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/fading.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/high-speed-train.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/highway.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/many-cores.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/mro.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/ntn.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/radio-maps.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/reproduce.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/scheduler.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/suburban-o2i.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/guides/ue-beams.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/ai-mobility.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/buffers.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/calibration_38901.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/calibration_7ghz.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/dashboard-compare.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/dashboard-where.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/dual-connectivity.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/fading.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/mro.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/new-scenarios.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/ntn-beams.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/procedures.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/radio-map.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/report-comparison.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/report-tuning.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/scheduler.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/ssb-beams.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/traffic.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/images/ue-beams.png +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/migration-2.0.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/performance.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/config.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/engine.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/eventlog.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/gui.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/index.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/mapfile.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/ntn.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/rules.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/scenarios.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/simulate.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/stability.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/stats.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/studies.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/testing.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/api/verify.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference/metrics.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/reference-study.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/dense-urban-2layer.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/dense-urban-2layer.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/fr3-urban-15ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/highway-tr37885-30ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/highway-tr37885-4ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/hst-fr2-28ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/indoor-office-4ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/ns3-urban-3.5ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/ntn-leo600-2ghz.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/ntn-leo600-2ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/open-area-10ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/rural-700mhz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/smoke.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/smoke.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/suburban-sma-7ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/urban-grid-10ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/urban-grid-28ghz-beams.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/scenarios/urban-macro-tr37885-4ghz.svg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/time-step.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/tutorials/first-run.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/tutorials/own-rule.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/tutorials/reading-the-report.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/docs/tutorials/tuning-study.md +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/compare_a3_cho.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/open_area.toml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/radio_map.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/smoke.yaml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/speed_rule.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/street_grid.yaml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/study_reference.yaml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/study_reference_explore.yaml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/study_smoke.yaml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/examples/traffic_models.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/setup.cfg +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/__main__.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/__init__.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/antenna.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/extended.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/fading.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/l2s.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/ntn.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/pathloss.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/radiomap.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/channel/source.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/config.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/__init__.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/_kernels.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/batch.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/buffers.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/core.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/dual.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/extended.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/invariants.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/metrics.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/procedures.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/engine/scheduler.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/eventlog.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/gui/__init__.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/gui/app.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/gui/logic.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/io.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/layout.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/linklevel.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/mapfile.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/measurement.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/mobility.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/py.typed +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/requirements.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/rules/__init__.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/rules/base.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/rules/builtin.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/rules/dqn.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/rules/mro.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/rules/predict.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/__init__.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/dense-urban-2layer.yaml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/ntn-leo600-2ghz.yaml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/scenarios/cards/smoke.yaml +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/seeds.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/simulate.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/standard.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/stats.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/studies/__init__.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/studies/config.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/studies/report.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/studies/runner.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/studies/status.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/studies/store.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/studies/study.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/studies/tuning.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/testing.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/traffic.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/aimobility.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/calibration.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/data/golden.json +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/data/golden_1x.json +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/data/ns3_urban_a3.json +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/data/r1_165974.csv +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/data/r1_2506406.csv +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/engine_checks.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/extended.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/fading.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/golden.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/highway.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/learning.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/ntn.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/radio.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/report.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/scenarios.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/stored.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/verify/values.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab/world.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab.egg-info/dependency_links.txt +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab.egg-info/entry_points.txt +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab.egg-info/requires.txt +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/src/handoverlab.egg-info/top_level.txt +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/conftest.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/data/bh6_reference.json +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/data/bh6_wide.json +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/data/make_bh6_reference.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/data/make_bh6_wide.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/helpers.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_ai_mobility.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_batch.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_beams_layers.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_buffers.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_calibration.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_channel_detail.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_cltm.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_config_cli.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_contract.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_determinism.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_dqn.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_engine_triggers.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_eventlog.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_fading.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_gui.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_highway.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_highway_tr37885.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_hst_dc.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_indoor_rural.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_invariants.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_levels_status_extend.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_lm_model.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_mapfile.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_measurement.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_mro.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_ntn.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_pathloss.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_protocol_3gpp.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_readme_boundaries.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_regression_bh6.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_regression_bh6_wide.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_rrc_detail.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_rules_rc2.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_scenarios.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_scenarios_230.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_sched_kernel.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_scheduler.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_signalling_energy.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_stability.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_stats.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_study.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_tools.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_traffic.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_tuning.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_ue_beams.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tests/test_v111.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/compare_fingerprints.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_ai_mobility_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_beam_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_buffers_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_calibration_7ghz_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_calibration_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_dashboard_screenshots.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_dc_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_fading_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_mro_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_ntn_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_procedures_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_radiomap_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_readme_images.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_scenarios_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_scheduler_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_traffic_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/make_ue_beams_figure.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/mkdocs_hooks.py +0 -0
- {handoverlab-2.4.2 → handoverlab-2.6.0}/tools/release_check.py +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "HandoverLab: system-level handover simulator for 5G-Advanced and beyond-5G research",
|
|
3
|
+
"description": "HandoverLab is a reproducible system-level simulator for studying and comparing handover algorithms and procedures in 5G-Advanced, beyond-5G and some NTN scenarios, with explicit models, optional features and a documented validation scope. It is open source and simulates 3GPP mobility procedures (baseline handover with Event A3, Release-16 conditional and DAPS handover, Release-18 L1/L2-triggered mobility, conditional handover with the location events of Release 18, dual connectivity) for many users in dense 5G-Advanced and beyond-5G networks, on a street grid, in an open area, along a highway or a high-speed railway, in an indoor office, in suburban and rural macro cells or under the earth-moving beams of a LEO satellite. It provides a TR 38.901 received-power radio model (TR 38.811 for the satellite) with optional TDL fast fading, SSB and UE receive beams and several carriers, an optional slot scheduler with MCS, TBS and HARQ and user-plane buffers at handover, an L3-filtered measurement chain, a radio-link failure model, an outcome label for every handover attempt, a plug-in interface for handover rules (including a measurement-prediction rule after TR 38.744), equal-budget tuning studies with paired statistics, and verification against hand-computed values, golden event-log fingerprints, the 3GPP large-scale calibration and ns-3 / 5G-LENA.",
|
|
4
|
+
"upload_type": "software",
|
|
5
|
+
"access_right": "open",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"creators": [
|
|
8
|
+
{
|
|
9
|
+
"name": "Jalili Sanjarani, Mostafa"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "Elmi Sola, Yasser"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"handover",
|
|
17
|
+
"conditional handover",
|
|
18
|
+
"mobility",
|
|
19
|
+
"mobility robustness",
|
|
20
|
+
"radio-link failure",
|
|
21
|
+
"system-level simulation",
|
|
22
|
+
"5G",
|
|
23
|
+
"beyond 5G",
|
|
24
|
+
"3GPP",
|
|
25
|
+
"Python",
|
|
26
|
+
"dual connectivity",
|
|
27
|
+
"fast fading",
|
|
28
|
+
"beam management",
|
|
29
|
+
"NTN",
|
|
30
|
+
"AI/ML mobility"
|
|
31
|
+
],
|
|
32
|
+
"related_identifiers": [
|
|
33
|
+
{
|
|
34
|
+
"identifier": "https://github.com/mjs19971997/handoverlab",
|
|
35
|
+
"relation": "isSupplementTo",
|
|
36
|
+
"scheme": "url"
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
@@ -7,6 +7,134 @@ All notable changes to this project are documented in this file. The format foll
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.6.0] - 2026-10-25
|
|
11
|
+
|
|
12
|
+
No change of defaults or results: every golden fingerprint is unchanged. This release corrects a wrong
|
|
13
|
+
claim of 2.5.0 about the failure level (see "Corrected").
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- A bridge to ns-3 / 5G-LENA (`handoverlab.ns3bridge`, `handoverlab ns3 export|import|compare`;
|
|
18
|
+
[guide](docs/guides/ns3-bridge.md)). An ns-3 study file (`examples/ns3_study_v1.yaml`) defines conditions
|
|
19
|
+
(site distance, speed, time-to-trigger, A3 offset, traffic, fading), users, run length and seeds once.
|
|
20
|
+
`export` writes a ready-to-run package of the program `benchmarks/ns3/handoverlab-ns3-a3.cc`: the program,
|
|
21
|
+
`build.sh`, `run.py` (standard library only, resumable, parallel, zips the results), `run.ps1` and
|
|
22
|
+
`manifest.json` (study hash, HandoverLab version, every ns-3 command line). `import` reads the run JSONs
|
|
23
|
+
into a reference file in the format of `handoverlab.verify.ns3.load_reference`. `compare` runs HandoverLab
|
|
24
|
+
on the same cells and seeds (ideal execution, the in-car loss of ns-3; `--comparison` adds the comparison
|
|
25
|
+
setting of 2.5.0) and applies the checks of the studies N3 and V1 (F1 level, F2 order, F3 handover rate,
|
|
26
|
+
F4 time-to-trigger effect) with the limits as options. Options the program cannot simulate (other cards,
|
|
27
|
+
beams, NTN, CHO, DAPS, LTM, other site distances, unknown keys) are refused, naming the option, before any
|
|
28
|
+
file is written.
|
|
29
|
+
- `handoverlab.ns3bridge` is part of the public surface (`tests/data/public_api.json`).
|
|
30
|
+
|
|
31
|
+
### Validation
|
|
32
|
+
|
|
33
|
+
- Pre-registered acceptance of the bridge: exporting the V1 design gives the program options of the hand-made
|
|
34
|
+
V1 package run by run (40 command lines); importing the 40 V1 results and running `compare` with and
|
|
35
|
+
without the comparison setting gives the numbers of V1 (rows C and R) exactly, with
|
|
36
|
+
`handoverlab.run_length: card`, the HandoverLab run length registered for V1 (150 s with 60 s warm-up, so
|
|
37
|
+
90 s measured against 120 s in ns-3). With the same run length on both sides (`run_length: study`, the
|
|
38
|
+
default; not registered) the comparison setting gives level 1.31, rank correlation 0.62 (below the limit
|
|
39
|
+
0.8), handover-rate ratio 0.92 and the TTT sign in 4 of 4 pairs; the default link monitoring 0.32, 0.62,
|
|
40
|
+
0.94 and 4 of 4. This difference revealed the error corrected below.
|
|
41
|
+
|
|
42
|
+
### Corrected
|
|
43
|
+
|
|
44
|
+
- **The failure-level analyses of 2.5.0 compared unequal run lengths.** For the fresh ns-3 sets N3, V1 and
|
|
45
|
+
V3 the HandoverLab side ran the card's 150 s with 60 s warm-up (90 s measured), while ns-3 ran 180 s with
|
|
46
|
+
60 s discarded (120 s measured); the level (F1) and order (F2) checks compare failure counts summed over
|
|
47
|
+
the cells, so the HandoverLab counts covered three quarters of the ns-3 time. A corrected analysis was
|
|
48
|
+
registered (amendment E1) before any corrected result was seen and applied to all three sets: equal run
|
|
49
|
+
lengths (180 s, 60 s discarded on both sides), same ns-3 runs, seeds, rows and criteria.
|
|
50
|
+
- Corrected results (registered analysis with the wrong run length in brackets). The ns-3 comparison
|
|
51
|
+
setting: N3 level 0.52 (0.47), fails; V1 level 1.31 (0.97) but rank correlation 0.62 (0.88), fails; V3
|
|
52
|
+
level 0.64 (0.44), fails. So it passes F1-F3 on none of the three sets. The defaults (default link
|
|
53
|
+
monitoring, ideal execution) fail level and rank on all three: level 0.18 / 0.32 / 0.17 (0.16 / 0.33 /
|
|
54
|
+
0.095), rank 0.71 / 0.62 / 0.76. The handover-rate ratio (0.86-0.96) and the direction of the
|
|
55
|
+
time-to-trigger effect pass in every set and row. A rate-based level (failures per UE-minute, not affected
|
|
56
|
+
by the run length) equals the corrected count-based level in every set and row.
|
|
57
|
+
- Consequence: the 2.5.0 statement that the comparison setting passed the pre-registered checks on V1 is
|
|
58
|
+
withdrawn. The absolute failure level is **not calibrated**: the comparison setting gives 0.5-1.3 times
|
|
59
|
+
ns-3's failure level depending on the set, and its order of failures across cells is not
|
|
60
|
+
reliable. `COMPARISON_SETTING`, `comparison=True` and `verify --ns3-comparison` are kept (the stability
|
|
61
|
+
policy keeps them within 2.x) and documented as a setting that brings the level closer, not validated.
|
|
62
|
+
- Not affected: the comparisons of handover and unnecessary-handover rates (part A of the stored ns-3
|
|
63
|
+
reference, `handoverlab verify --ns3`, `verify.ns3.compare`) and N2, which use rates per UE-minute.
|
|
64
|
+
- V3 (registered 2026-10-25 before its runs: 40 fresh ns-3 runs, site distance 200 / 300 m, 10 / 28 m/s,
|
|
65
|
+
time-to-trigger 512 / 1024 ms, seeds 601-605, 1122 ns-3 failures): the comparison setting fails the level
|
|
66
|
+
in both analyses (0.44 registered, 0.64 corrected) with rank 0.87 / 0.88; the defaults 0.095 / 0.17. At
|
|
67
|
+
long time-to-trigger HandoverLab has fewer failures than ns-3, consistent with ns-3's slower out-of-sync
|
|
68
|
+
detection (0.65-0.83 s), which HandoverLab does not model.
|
|
69
|
+
- Planned, not in this release: an "ns-3-like" option (not a default) that imitates ns-3's slower
|
|
70
|
+
out-of-sync detection, built from the ns-3 data already seen and judged on a fresh set V4 (site distance
|
|
71
|
+
200 / 400 m, 14 / 22 m/s, time-to-trigger 128 / 1280 ms, seeds 701-705), collected and kept unopened until
|
|
72
|
+
the option and its settings are frozen.
|
|
73
|
+
- Corrected everywhere the 2.5.0 claim appeared: README ("Checked against ns-3", the boundary table, What's
|
|
74
|
+
new), `docs/calibration.md` (the summary and the 2.5.0 study, with the registered numbers kept next to the
|
|
75
|
+
corrected ones, and new sections on V3 and the correction), `docs/comparison.md`, `docs/verification.md`,
|
|
76
|
+
`docs/standard-compliance.md`, the user guide, the guides, the 12 scenario cards (scenario pages
|
|
77
|
+
regenerated), the docstrings of `handoverlab.verify.ns3`, the note of `verify --ns3 --ns3-comparison`, and
|
|
78
|
+
the help of `verify --ns3-comparison` and `ns3 compare --comparison` (command-line reference regenerated).
|
|
79
|
+
|
|
80
|
+
### Documentation
|
|
81
|
+
|
|
82
|
+
- Version 2.6.0 in the README, the user guide, the documentation home page and the citation metadata.
|
|
83
|
+
Dashboard screenshots retaken with this version.
|
|
84
|
+
|
|
85
|
+
## [2.5.0] - 2026-10-25
|
|
86
|
+
|
|
87
|
+
No change of defaults or results: every golden fingerprint is unchanged.
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
|
|
91
|
+
- The ns-3 comparison setting as code: `handoverlab.verify.ns3.COMPARISON_SETTING`
|
|
92
|
+
(`{"protocol.lm_load": 0.15, "protocol.exec_can_fail": False}`: interferer load 0.15 at link monitoring,
|
|
93
|
+
ideal execution), applied by `scenario_for(..., comparison=True)`, `compare(..., comparison=True)` and
|
|
94
|
+
`holdout(..., comparison=True)` (after the in-car loss, before `overrides`), by
|
|
95
|
+
`ns3_checks(..., comparison=True)` and `run_verify(..., ns3_comparison=True)` together with the in-car loss
|
|
96
|
+
of ns-3, and on the command line by `handoverlab verify --ns3 --ns3-comparison`. The summary of `compare`
|
|
97
|
+
records `car` and `comparison`. It is not a default.
|
|
98
|
+
|
|
99
|
+
### Validation
|
|
100
|
+
|
|
101
|
+
- An independent validation study, registered before any of its runs, with one amendment fixed before the runs
|
|
102
|
+
of its second part; nothing tuned on its data (`docs/calibration.md`, "Independent validation study (2.5.0)").
|
|
103
|
+
- **V1, failure rate against 40 fresh ns-3 / 5G-LENA runs** (site distance 200 / 300 m, 10 / 28 m/s,
|
|
104
|
+
time-to-trigger 80 / 320 ms, seeds 401-405). The N3 candidate, not re-tuned (`lm_load` 0.15, ideal
|
|
105
|
+
execution, in-car loss): failure level 0.97 of ns-3 (limit 0.67-1.5), rank correlation 0.88 over the 8 cells,
|
|
106
|
+
handover-rate ratio 0.965, TTT direction in 4 of 4: all pass, so it becomes the documented ns-3 comparison
|
|
107
|
+
setting (corrected in 2.6.0: with equal run lengths it fails the rank on V1, 0.62, and is not validated).
|
|
108
|
+
The 2.4.2 link monitoring with ideal execution: level 0.33 (fails), rank 0.84, ratio 0.973. V1 has
|
|
109
|
+
time-to-trigger 80 and 320 ms only; on the earlier fresh set N3 the same setting failed the level (0.47): its
|
|
110
|
+
TTT 100 ms cells matched, its TTT 640 ms cells had about half of ns-3's failures (matching at 100 ms was not a
|
|
111
|
+
registered criterion).
|
|
112
|
+
- **V2, generalisation of the adaptive and learning rules** (tuned and trained on `urban-grid-10ghz`, seeds
|
|
113
|
+
101-104; tested on `ns3-urban-3.5ghz`, `urban-macro-tr37885-4ghz`, `highway-tr37885-4ghz` and
|
|
114
|
+
`fr3-urban-15ghz`, seeds 501-505, against tuned A3). `a3_mro` and `dqn` generalise (fewer unnecessary
|
|
115
|
+
handovers on all four test cards, no cost flag). `a3_bandit` meets the registered criteria only formally: it
|
|
116
|
+
has more unnecessary handovers than tuned A3 on every card (+1.644 per UE-minute on the training card) and
|
|
117
|
+
1.65 to 4.15 times its ping-pong on three test cards. `a3_pred` does not generalise (the gain is lost on
|
|
118
|
+
`urban-macro-tr37885-4ghz`, and it cannot run at the 0.2 s measurement period of `ns3-urban-3.5ghz`). Limits
|
|
119
|
+
of the design: with 5 seeds the no-harm criterion cannot fail (smallest Wilcoxon p 0.0625), and
|
|
120
|
+
`fr3-urban-15ghz` is the least independent test card.
|
|
121
|
+
|
|
122
|
+
### Documentation
|
|
123
|
+
|
|
124
|
+
- The failure level is now stated precisely everywhere it was called "not calibrated" (README, scenario cards,
|
|
125
|
+
`docs/comparison.md`, `docs/verification.md`, the user guide and the guides): the ns-3
|
|
126
|
+
comparison setting passed the pre-registered checks on one fresh set of ns-3 runs (V1, TTT 80 and 320 ms:
|
|
127
|
+
level 0.97, rank 0.88) (withdrawn in 2.6.0: wrong run length; see Corrected)
|
|
128
|
+
and failed the level on another (N3: 0.47, because of its TTT 640 ms cells); the
|
|
129
|
+
default link-monitoring model gives a third to a sixth of ns-3's level (0.33 on V1, 0.16 on N3) (corrected
|
|
130
|
+
in 2.6.0). Scenario pages regenerated.
|
|
131
|
+
- The learning-rule and AI/ML-mobility guides: the generalisation results of V2.
|
|
132
|
+
- README, `CITATION.cff` and `.zenodo.json` describe HandoverLab as a reproducible system-level simulator for
|
|
133
|
+
studying and comparing handover algorithms and procedures in 5G-Advanced, beyond-5G and some NTN scenarios,
|
|
134
|
+
with explicit models, optional features and a documented validation scope.
|
|
135
|
+
- Citation with the DOI of 2.4.2 (10.5281/zenodo.23589215).
|
|
136
|
+
- Command-line reference: `verify --ns3-comparison`. Dashboard screenshots retaken with this version.
|
|
137
|
+
|
|
10
138
|
## [2.4.2] - 2026-10-23
|
|
11
139
|
|
|
12
140
|
No change of results.
|
|
@@ -1120,7 +1248,9 @@ First alpha release (stage 1: the core simulator).
|
|
|
1120
1248
|
- Documentation: README, user guide, contribution guide, citation file; CI on Linux, Windows and
|
|
1121
1249
|
macOS with Python 3.9-3.12.
|
|
1122
1250
|
|
|
1123
|
-
[Unreleased]: https://github.com/mjs19971997/handoverlab/compare/v2.
|
|
1251
|
+
[Unreleased]: https://github.com/mjs19971997/handoverlab/compare/v2.6.0...HEAD
|
|
1252
|
+
[2.6.0]: https://github.com/mjs19971997/handoverlab/compare/v2.5.0...v2.6.0
|
|
1253
|
+
[2.5.0]: https://github.com/mjs19971997/handoverlab/compare/v2.4.2...v2.5.0
|
|
1124
1254
|
[2.4.2]: https://github.com/mjs19971997/handoverlab/compare/v2.4.1...v2.4.2
|
|
1125
1255
|
[2.4.1]: https://github.com/mjs19971997/handoverlab/compare/v2.4.0...v2.4.1
|
|
1126
1256
|
[2.4.0]: https://github.com/mjs19971997/handoverlab/compare/v2.3.0...v2.4.0
|
|
@@ -2,8 +2,10 @@ cff-version: 1.2.0
|
|
|
2
2
|
message: "If you use this software, please cite it as below."
|
|
3
3
|
title: "HandoverLab: system-level handover simulator for 5G-Advanced and beyond-5G research"
|
|
4
4
|
abstract: >-
|
|
5
|
-
HandoverLab is
|
|
6
|
-
|
|
5
|
+
HandoverLab is a reproducible system-level simulator for studying and comparing handover
|
|
6
|
+
algorithms and procedures in 5G-Advanced, beyond-5G and some NTN scenarios, with explicit models,
|
|
7
|
+
optional features and a documented validation scope. It is open source and simulates 3GPP
|
|
8
|
+
mobility procedures (baseline handover with Event A3, Release-16 conditional and DAPS handover, Release-18 L1/L2-triggered
|
|
7
9
|
mobility, conditional handover with the location events of Release 18) for many users in dense
|
|
8
10
|
5G and beyond-5G networks, on a street grid, in an open area, along a highway, indoors, in rural
|
|
9
11
|
cells, along a high-speed railway or under the earth-moving beams of a LEO satellite. It provides a
|
|
@@ -14,7 +16,7 @@ abstract: >-
|
|
|
14
16
|
handover rules (including a measurement-prediction rule after TR 38.744), equal-budget tuning
|
|
15
17
|
studies with paired statistics, and verification against hand-computed values, golden event-log
|
|
16
18
|
fingerprints, the 3GPP large-scale calibration and ns-3 / 5G-LENA.
|
|
17
|
-
version: "2.
|
|
19
|
+
version: "2.6.0"
|
|
18
20
|
doi: 10.5281/zenodo.23409131
|
|
19
21
|
identifiers:
|
|
20
22
|
- type: doi
|
|
@@ -32,7 +34,10 @@ identifiers:
|
|
|
32
34
|
- type: doi
|
|
33
35
|
value: 10.5281/zenodo.23585308
|
|
34
36
|
description: "Version 2.4.1 on Zenodo"
|
|
35
|
-
|
|
37
|
+
- type: doi
|
|
38
|
+
value: 10.5281/zenodo.23589215
|
|
39
|
+
description: "Version 2.4.2 on Zenodo"
|
|
40
|
+
date-released: 2026-10-25
|
|
36
41
|
license: MIT
|
|
37
42
|
repository-code: "https://github.com/mjs19971997/handoverlab"
|
|
38
43
|
url: "https://mjs19971997.github.io/handoverlab/"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: handoverlab
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
4
4
|
Summary: System-level handover simulator for 5G-Advanced and beyond-5G research
|
|
5
5
|
Author: Mostafa Jalili Sanjarani, Yasser Elmi Sola
|
|
6
6
|
License-Expression: MIT
|
|
@@ -60,7 +60,7 @@ Dynamic: license-file
|
|
|
60
60
|
|
|
61
61
|
[](https://doi.org/10.5281/zenodo.23409131) [](https://pypi.org/project/handoverlab/)
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
HandoverLab is a reproducible system-level simulator for studying and comparing handover algorithms and procedures in 5G-Advanced, beyond-5G and some NTN scenarios, with explicit models, optional features and a documented validation scope. It is written in Python.
|
|
64
64
|
|
|
65
65
|
HandoverLab simulates 3GPP mobility procedures (baseline handover with Event A3, Release-16
|
|
66
66
|
conditional handover and DAPS handover, Release-18 L1/L2-triggered mobility, conditional handover with
|
|
@@ -70,7 +70,7 @@ received-power-level radio model from TR 38.901 (TR 38.811 for the satellite) (o
|
|
|
70
70
|
and several carriers), an L3-filtered measurement chain, a radio-link failure model, and an
|
|
71
71
|
outcome label for every handover attempt.
|
|
72
72
|
|
|
73
|
-
> **Status: 2.
|
|
73
|
+
> **Status: 2.6.0** (`python -m pip install handoverlab`). The public surface (configuration and
|
|
74
74
|
> result formats with a schema version, the rule interface, metric names, commands and the
|
|
75
75
|
> documented Python names) follows the [stability policy](https://github.com/mjs19971997/handoverlab/blob/main/docs/stability.md): within 2.x it only grows,
|
|
76
76
|
> and anything removed is deprecated first. 2.0.0 makes the 3GPP values the defaults (the protocol profile,
|
|
@@ -257,7 +257,7 @@ the clause-by-clause detail is in [standard compliance](https://github.com/mjs19
|
|
|
257
257
|
| Traffic and load | constant rates per 5QI, full buffer, periodic, FTP model 3; cell load drives interference; options: a slot scheduler (`protocol.scheduler`: round robin or proportional fair) with the MCS, TBS and HARQ of TS 38.214 (since 2.2.0), and user-plane buffers at handover (`protocol.buffers`: simplified PDCP / RLC in AM or UM with Xn data forwarding, since 2.3.0) | by default the rate from the SINR (Shannon-type mapping) without a scheduler; with the scheduler the channel is held for the 10 ms step and the MCS is chosen from the SINR of one measurement interval earlier (no CSI reports); buffers: downlink only, one bearer per user, the interruption quantised to the measurement interval; both options need the base engine (no beams, layers, NTN or TS 38.133 periods) | uplink data, CSI-based link adaptation, PDCP reordering and status reports at the UE, TCP and applications |
|
|
258
258
|
| Measurements | L1 samples with error, TS 38.331 L3 filter, TS 38.133 measurement periods and gaps (option) | wideband RSRP; SS-RSRP per resource element with beams/carriers | RSRQ, CSI reporting |
|
|
259
259
|
| Procedures | baseline (A3), CHO, DAPS, LTM, conditional LTM, CHO with D1/D2 for satellites, A3/A5 between carriers; rules `a3`, `a3a5`, `a3_mro`, `a3_bandit`, `dqn`, `a3_pred`, `cho`, `cho_d2`, `daps`, `ltm`, `cltm` | fixed preparation, command and execution delays; re-establishment always succeeds after a fixed outage | condEventT1, RACH-less NTN handover, Xn signalling in detail |
|
|
260
|
-
| Failure model | Qout/Qin with windows, N310/N311/T310, T304, command received during T310, re-establishment, link-monitoring restart | Qout/Qin as SINR thresholds (TR 36.839 values) instead of the BLER of a hypothetical PDCCH | BLER-based link monitoring; absolute failure
|
|
260
|
+
| Failure model | Qout/Qin with windows, N310/N311/T310, T304, command received during T310, re-establishment, link-monitoring restart | Qout/Qin as SINR thresholds (TR 36.839 values) instead of the BLER of a hypothetical PDCCH | BLER-based link monitoring; the absolute failure level is not calibrated: with equal run lengths the default gives 0.17-0.32 of ns-3's and the ns-3 comparison setting 0.5-1.3 depending on the set, passing the pre-registered checks on none of three fresh ns-3 sets (corrected in 2.6.0): compare rules with each other |
|
|
261
261
|
| Time | 10 ms step by default (`protocol.step_s`); the effect of the step is measured in [time step](https://github.com/mjs19971997/handoverlab/blob/main/docs/time-step.md) | events rounded to the step | sub-slot timing |
|
|
262
262
|
|
|
263
263
|
Built-in cards: `smoke`, `urban-grid-10ghz`, `fr3-urban-15ghz`, `urban-grid-28ghz-beams`, `dense-urban-2layer`,
|
|
@@ -326,9 +326,19 @@ The same 24 Event-A3 settings were simulated in HandoverLab and in the packet-le
|
|
|
326
326
|
ns-3 with 5G-LENA. Handover and unnecessary-handover rates agree (median ratios 0.95 and 1.06,
|
|
327
327
|
rank correlation 0.99; `handoverlab verify --ns3`, version 2.1.0). For failure rates, with the in-car loss of ns-3 and the restart of the link
|
|
328
328
|
monitoring switched on, the order of settings and conditions agrees too, also on ns-3 results
|
|
329
|
-
that were held back from any tuning (rank correlation 0.82-0.91). The absolute
|
|
330
|
-
|
|
331
|
-
|
|
329
|
+
that were held back from any tuning (rank correlation 0.82-0.91). **The absolute failure level is not
|
|
330
|
+
calibrated.** On three fresh, pre-registered sets of ns-3 runs (N3, V1, V3), compared over equal run
|
|
331
|
+
lengths, the default link-monitoring model gives 0.18, 0.32 and 0.17 of ns-3's failure level and fails
|
|
332
|
+
level and order on all three. The ns-3 comparison setting of 2.5.0
|
|
333
|
+
(`handoverlab.verify.ns3.COMPARISON_SETTING`: interferer load 0.15 at link monitoring and ideal execution,
|
|
334
|
+
with the in-car loss of ns-3; `handoverlab verify --ns3 --ns3-comparison`) brings the level closer but is
|
|
335
|
+
not validated: 0.52 (N3), 1.31 (V1, where the order of failures across cells fails, rank 0.62) and 0.64
|
|
336
|
+
(V3), so 0.5-1.3 times ns-3's level depending on the set, passing the checks on none of the
|
|
337
|
+
three sets. The handover-rate ratio (0.86-0.96) and the direction of the time-to-trigger effect agree in
|
|
338
|
+
every set. *Corrected in 2.6.0:* 2.5.0 reported that the setting passed on V1 (level 0.97, rank 0.88);
|
|
339
|
+
that analysis compared 90 s of HandoverLab with 120 s of ns-3. The setting is not a default, so
|
|
340
|
+
compare failure rates between rules within HandoverLab. The study and the causes of the differences are
|
|
341
|
+
in [docs/calibration.md](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration.md). On two of the causes HandoverLab follows the 3GPP texts more closely
|
|
332
342
|
than ns-3:
|
|
333
343
|
|
|
334
344
|
- **In-car penetration loss.** TR 38.901 clause 7.4.3.2 gives it to a user inside a car. ns-3 adds
|
|
@@ -343,8 +353,28 @@ HandoverLab has had this as an option since 1.3.0 (`protocol.rlm_holdoff_s`), on
|
|
|
343
353
|
covers baseline handover at 3.5 GHz only: 5G-LENA has no conditional handover, DAPS or
|
|
344
354
|
L1/L2-triggered mobility.
|
|
345
355
|
|
|
356
|
+
To run your own study in both simulators, `handoverlab ns3 export|import|compare` writes the ns-3 package, reads its results back and applies the same checks ([guide](https://github.com/mjs19971997/handoverlab/blob/main/docs/guides/ns3-bridge.md)).
|
|
357
|
+
|
|
346
358
|
## What's new
|
|
347
359
|
|
|
360
|
+
- **2.6.0**: a bridge to ns-3 / 5G-LENA (`handoverlab ns3 export|import|compare`) that writes a ready-to-run
|
|
361
|
+
ns-3 package for a study, reads its results back and applies the checks of the ns-3 studies
|
|
362
|
+
([guide](https://github.com/mjs19971997/handoverlab/blob/main/docs/guides/ns3-bridge.md)). It found an error in 2.5.0: the failure counts of
|
|
363
|
+
HandoverLab covered 90 s against 120 s of ns-3. Corrected, the ns-3 comparison setting passes the
|
|
364
|
+
pre-registered checks on none of the three fresh ns-3 sets (level 0.52, 1.31 with rank 0.62, 0.64): the
|
|
365
|
+
absolute failure level is not calibrated ([correction](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration.md#correction-in-260-equal-run-lengths)). Handover-rate comparisons were not
|
|
366
|
+
affected. No change of results.
|
|
367
|
+
- **2.5.0** (corrected in 2.6.0): an independent, pre-registered [validation study](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration.md#independent-validation-study-250). On 40
|
|
368
|
+
fresh ns-3 runs (V1, TTT 80 and 320 ms) the ns-3 comparison setting was reported to pass the
|
|
369
|
+
pre-registered checks (level 0.97, order 0.88); this compared 90 s of HandoverLab with 120 s of ns-3, and
|
|
370
|
+
with equal run lengths it fails the order on V1 (rank 0.62) and the level on N3 and V3 (0.52, 0.64), so it
|
|
371
|
+
is not validated. It is documented as code (`handoverlab.verify.ns3.COMPARISON_SETTING`,
|
|
372
|
+
`verify --ns3 --ns3-comparison`; not a default). Tuned on one card and tested on four unseen cards and
|
|
373
|
+
seeds, `a3_mro` and `dqn` kept fewer unnecessary handovers than tuned A3; `a3_bandit` met the criteria
|
|
374
|
+
only formally (more unnecessary handovers and ping-pong); `a3_pred` did not generalise. Limits of this
|
|
375
|
+
design: with 5 seeds the smallest two-sided Wilcoxon p is 0.0625, so the no-harm check could not fail, and
|
|
376
|
+
`fr3-urban-15ghz` is the training grid at another frequency, so it is the least independent test card
|
|
377
|
+
([V2](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration.md#v2-do-the-adaptive-and-learning-rules-generalise)). No change of results.
|
|
348
378
|
- **2.4.0**: UE receive beams (panels of TR 38.802, best beam or a sweep); a measurement-prediction rule after
|
|
349
379
|
TR 38.744 (`a3_pred`: predicted Event A3 or measurement skipping, sample and hold or a trained ridge
|
|
350
380
|
predictor); the slot scheduler as a compiled kernel (`run.backend: numba`, bit-identical; on the ns-3 card
|
|
@@ -569,9 +599,16 @@ the pages are plain Markdown in [docs/](https://github.com/mjs19971997/handoverl
|
|
|
569
599
|
scheduler, the 7 GHz calibration and the comparison with other simulators.
|
|
570
600
|
27. 2.4.1: pictures, citation and tutorials brought up to date; the example study
|
|
571
601
|
completes again; no change of results.
|
|
572
|
-
28.
|
|
602
|
+
28. 2.4.2: every option has a picture; the dashboard pictures show the current version;
|
|
573
603
|
guide and tutorial examples rerun; facts made consistent; no change of results.
|
|
574
|
-
29.
|
|
604
|
+
29. 2.5.0: an independent, pre-registered validation study: the ns-3 comparison setting for the
|
|
605
|
+
failure level (its pass on V1 was corrected in 2.6.0: not validated), and the generalisation of the
|
|
606
|
+
adaptive and learning rules to unseen cards and seeds; no change of results.
|
|
607
|
+
30. **2.6.0 (this release)**: the bridge to ns-3 / 5G-LENA (export, import, compare); the correction of the
|
|
608
|
+
2.5.0 failure-level comparison (equal run lengths: the absolute failure level is not calibrated); no
|
|
609
|
+
change of results.
|
|
610
|
+
31. Later (planned, not done), staying a handover simulator: an "ns-3-like" option imitating ns-3's slower
|
|
611
|
+
out-of-sync detection, judged on a fresh ns-3 set (V4) kept unopened until it is frozen; the effect of a handover on what the user
|
|
575
612
|
sees (simple TCP and application models on top of the buffers), MIMO as an SINR gain, hundreds of
|
|
576
613
|
users per run, and one scenario definition that also runs in ns-3; condEventT1 and earth-fixed beams.
|
|
577
614
|
|
|
@@ -581,9 +618,10 @@ If you use HandoverLab, please cite it as described in [CITATION.cff](https://gi
|
|
|
581
618
|
it under *Cite this repository*). Every release is archived on Zenodo:
|
|
582
619
|
[doi:10.5281/zenodo.23409131](https://doi.org/10.5281/zenodo.23409131) cites all versions (it resolves to
|
|
583
620
|
the latest). To cite the exact version you used, take its DOI from the version list on that page, where
|
|
584
|
-
the DOI of the latest version is listed; for example, version 2.4.
|
|
621
|
+
the DOI of the latest version is listed; for example, version 2.4.2 is
|
|
622
|
+
[doi:10.5281/zenodo.23589215](https://doi.org/10.5281/zenodo.23589215), version 2.4.1
|
|
585
623
|
[doi:10.5281/zenodo.23585308](https://doi.org/10.5281/zenodo.23585308) and version 2.4.0
|
|
586
|
-
[doi:10.5281/zenodo.23582521](https://doi.org/10.5281/zenodo.23582521). The BibTeX entry below cites 2.4.
|
|
624
|
+
[doi:10.5281/zenodo.23582521](https://doi.org/10.5281/zenodo.23582521). The BibTeX entry below cites 2.4.2;
|
|
587
625
|
replace version and DOI with those of the version you used.
|
|
588
626
|
|
|
589
627
|
```bibtex
|
|
@@ -592,8 +630,8 @@ replace version and DOI with those of the version you used.
|
|
|
592
630
|
title = {{HandoverLab}: system-level handover simulator for 5G-Advanced and beyond-5G research},
|
|
593
631
|
year = {2026},
|
|
594
632
|
publisher = {Zenodo},
|
|
595
|
-
version = {2.4.
|
|
596
|
-
doi = {10.5281/zenodo.
|
|
633
|
+
version = {2.4.2},
|
|
634
|
+
doi = {10.5281/zenodo.23589215},
|
|
597
635
|
url = {https://github.com/mjs19971997/handoverlab}
|
|
598
636
|
}
|
|
599
637
|
```
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://doi.org/10.5281/zenodo.23409131) [](https://pypi.org/project/handoverlab/)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
HandoverLab is a reproducible system-level simulator for studying and comparing handover algorithms and procedures in 5G-Advanced, beyond-5G and some NTN scenarios, with explicit models, optional features and a documented validation scope. It is written in Python.
|
|
6
6
|
|
|
7
7
|
HandoverLab simulates 3GPP mobility procedures (baseline handover with Event A3, Release-16
|
|
8
8
|
conditional handover and DAPS handover, Release-18 L1/L2-triggered mobility, conditional handover with
|
|
@@ -12,7 +12,7 @@ received-power-level radio model from TR 38.901 (TR 38.811 for the satellite) (o
|
|
|
12
12
|
and several carriers), an L3-filtered measurement chain, a radio-link failure model, and an
|
|
13
13
|
outcome label for every handover attempt.
|
|
14
14
|
|
|
15
|
-
> **Status: 2.
|
|
15
|
+
> **Status: 2.6.0** (`python -m pip install handoverlab`). The public surface (configuration and
|
|
16
16
|
> result formats with a schema version, the rule interface, metric names, commands and the
|
|
17
17
|
> documented Python names) follows the [stability policy](https://github.com/mjs19971997/handoverlab/blob/main/docs/stability.md): within 2.x it only grows,
|
|
18
18
|
> and anything removed is deprecated first. 2.0.0 makes the 3GPP values the defaults (the protocol profile,
|
|
@@ -199,7 +199,7 @@ the clause-by-clause detail is in [standard compliance](https://github.com/mjs19
|
|
|
199
199
|
| Traffic and load | constant rates per 5QI, full buffer, periodic, FTP model 3; cell load drives interference; options: a slot scheduler (`protocol.scheduler`: round robin or proportional fair) with the MCS, TBS and HARQ of TS 38.214 (since 2.2.0), and user-plane buffers at handover (`protocol.buffers`: simplified PDCP / RLC in AM or UM with Xn data forwarding, since 2.3.0) | by default the rate from the SINR (Shannon-type mapping) without a scheduler; with the scheduler the channel is held for the 10 ms step and the MCS is chosen from the SINR of one measurement interval earlier (no CSI reports); buffers: downlink only, one bearer per user, the interruption quantised to the measurement interval; both options need the base engine (no beams, layers, NTN or TS 38.133 periods) | uplink data, CSI-based link adaptation, PDCP reordering and status reports at the UE, TCP and applications |
|
|
200
200
|
| Measurements | L1 samples with error, TS 38.331 L3 filter, TS 38.133 measurement periods and gaps (option) | wideband RSRP; SS-RSRP per resource element with beams/carriers | RSRQ, CSI reporting |
|
|
201
201
|
| Procedures | baseline (A3), CHO, DAPS, LTM, conditional LTM, CHO with D1/D2 for satellites, A3/A5 between carriers; rules `a3`, `a3a5`, `a3_mro`, `a3_bandit`, `dqn`, `a3_pred`, `cho`, `cho_d2`, `daps`, `ltm`, `cltm` | fixed preparation, command and execution delays; re-establishment always succeeds after a fixed outage | condEventT1, RACH-less NTN handover, Xn signalling in detail |
|
|
202
|
-
| Failure model | Qout/Qin with windows, N310/N311/T310, T304, command received during T310, re-establishment, link-monitoring restart | Qout/Qin as SINR thresholds (TR 36.839 values) instead of the BLER of a hypothetical PDCCH | BLER-based link monitoring; absolute failure
|
|
202
|
+
| Failure model | Qout/Qin with windows, N310/N311/T310, T304, command received during T310, re-establishment, link-monitoring restart | Qout/Qin as SINR thresholds (TR 36.839 values) instead of the BLER of a hypothetical PDCCH | BLER-based link monitoring; the absolute failure level is not calibrated: with equal run lengths the default gives 0.17-0.32 of ns-3's and the ns-3 comparison setting 0.5-1.3 depending on the set, passing the pre-registered checks on none of three fresh ns-3 sets (corrected in 2.6.0): compare rules with each other |
|
|
203
203
|
| Time | 10 ms step by default (`protocol.step_s`); the effect of the step is measured in [time step](https://github.com/mjs19971997/handoverlab/blob/main/docs/time-step.md) | events rounded to the step | sub-slot timing |
|
|
204
204
|
|
|
205
205
|
Built-in cards: `smoke`, `urban-grid-10ghz`, `fr3-urban-15ghz`, `urban-grid-28ghz-beams`, `dense-urban-2layer`,
|
|
@@ -268,9 +268,19 @@ The same 24 Event-A3 settings were simulated in HandoverLab and in the packet-le
|
|
|
268
268
|
ns-3 with 5G-LENA. Handover and unnecessary-handover rates agree (median ratios 0.95 and 1.06,
|
|
269
269
|
rank correlation 0.99; `handoverlab verify --ns3`, version 2.1.0). For failure rates, with the in-car loss of ns-3 and the restart of the link
|
|
270
270
|
monitoring switched on, the order of settings and conditions agrees too, also on ns-3 results
|
|
271
|
-
that were held back from any tuning (rank correlation 0.82-0.91). The absolute
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
that were held back from any tuning (rank correlation 0.82-0.91). **The absolute failure level is not
|
|
272
|
+
calibrated.** On three fresh, pre-registered sets of ns-3 runs (N3, V1, V3), compared over equal run
|
|
273
|
+
lengths, the default link-monitoring model gives 0.18, 0.32 and 0.17 of ns-3's failure level and fails
|
|
274
|
+
level and order on all three. The ns-3 comparison setting of 2.5.0
|
|
275
|
+
(`handoverlab.verify.ns3.COMPARISON_SETTING`: interferer load 0.15 at link monitoring and ideal execution,
|
|
276
|
+
with the in-car loss of ns-3; `handoverlab verify --ns3 --ns3-comparison`) brings the level closer but is
|
|
277
|
+
not validated: 0.52 (N3), 1.31 (V1, where the order of failures across cells fails, rank 0.62) and 0.64
|
|
278
|
+
(V3), so 0.5-1.3 times ns-3's level depending on the set, passing the checks on none of the
|
|
279
|
+
three sets. The handover-rate ratio (0.86-0.96) and the direction of the time-to-trigger effect agree in
|
|
280
|
+
every set. *Corrected in 2.6.0:* 2.5.0 reported that the setting passed on V1 (level 0.97, rank 0.88);
|
|
281
|
+
that analysis compared 90 s of HandoverLab with 120 s of ns-3. The setting is not a default, so
|
|
282
|
+
compare failure rates between rules within HandoverLab. The study and the causes of the differences are
|
|
283
|
+
in [docs/calibration.md](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration.md). On two of the causes HandoverLab follows the 3GPP texts more closely
|
|
274
284
|
than ns-3:
|
|
275
285
|
|
|
276
286
|
- **In-car penetration loss.** TR 38.901 clause 7.4.3.2 gives it to a user inside a car. ns-3 adds
|
|
@@ -285,8 +295,28 @@ HandoverLab has had this as an option since 1.3.0 (`protocol.rlm_holdoff_s`), on
|
|
|
285
295
|
covers baseline handover at 3.5 GHz only: 5G-LENA has no conditional handover, DAPS or
|
|
286
296
|
L1/L2-triggered mobility.
|
|
287
297
|
|
|
298
|
+
To run your own study in both simulators, `handoverlab ns3 export|import|compare` writes the ns-3 package, reads its results back and applies the same checks ([guide](https://github.com/mjs19971997/handoverlab/blob/main/docs/guides/ns3-bridge.md)).
|
|
299
|
+
|
|
288
300
|
## What's new
|
|
289
301
|
|
|
302
|
+
- **2.6.0**: a bridge to ns-3 / 5G-LENA (`handoverlab ns3 export|import|compare`) that writes a ready-to-run
|
|
303
|
+
ns-3 package for a study, reads its results back and applies the checks of the ns-3 studies
|
|
304
|
+
([guide](https://github.com/mjs19971997/handoverlab/blob/main/docs/guides/ns3-bridge.md)). It found an error in 2.5.0: the failure counts of
|
|
305
|
+
HandoverLab covered 90 s against 120 s of ns-3. Corrected, the ns-3 comparison setting passes the
|
|
306
|
+
pre-registered checks on none of the three fresh ns-3 sets (level 0.52, 1.31 with rank 0.62, 0.64): the
|
|
307
|
+
absolute failure level is not calibrated ([correction](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration.md#correction-in-260-equal-run-lengths)). Handover-rate comparisons were not
|
|
308
|
+
affected. No change of results.
|
|
309
|
+
- **2.5.0** (corrected in 2.6.0): an independent, pre-registered [validation study](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration.md#independent-validation-study-250). On 40
|
|
310
|
+
fresh ns-3 runs (V1, TTT 80 and 320 ms) the ns-3 comparison setting was reported to pass the
|
|
311
|
+
pre-registered checks (level 0.97, order 0.88); this compared 90 s of HandoverLab with 120 s of ns-3, and
|
|
312
|
+
with equal run lengths it fails the order on V1 (rank 0.62) and the level on N3 and V3 (0.52, 0.64), so it
|
|
313
|
+
is not validated. It is documented as code (`handoverlab.verify.ns3.COMPARISON_SETTING`,
|
|
314
|
+
`verify --ns3 --ns3-comparison`; not a default). Tuned on one card and tested on four unseen cards and
|
|
315
|
+
seeds, `a3_mro` and `dqn` kept fewer unnecessary handovers than tuned A3; `a3_bandit` met the criteria
|
|
316
|
+
only formally (more unnecessary handovers and ping-pong); `a3_pred` did not generalise. Limits of this
|
|
317
|
+
design: with 5 seeds the smallest two-sided Wilcoxon p is 0.0625, so the no-harm check could not fail, and
|
|
318
|
+
`fr3-urban-15ghz` is the training grid at another frequency, so it is the least independent test card
|
|
319
|
+
([V2](https://github.com/mjs19971997/handoverlab/blob/main/docs/calibration.md#v2-do-the-adaptive-and-learning-rules-generalise)). No change of results.
|
|
290
320
|
- **2.4.0**: UE receive beams (panels of TR 38.802, best beam or a sweep); a measurement-prediction rule after
|
|
291
321
|
TR 38.744 (`a3_pred`: predicted Event A3 or measurement skipping, sample and hold or a trained ridge
|
|
292
322
|
predictor); the slot scheduler as a compiled kernel (`run.backend: numba`, bit-identical; on the ns-3 card
|
|
@@ -511,9 +541,16 @@ the pages are plain Markdown in [docs/](https://github.com/mjs19971997/handoverl
|
|
|
511
541
|
scheduler, the 7 GHz calibration and the comparison with other simulators.
|
|
512
542
|
27. 2.4.1: pictures, citation and tutorials brought up to date; the example study
|
|
513
543
|
completes again; no change of results.
|
|
514
|
-
28.
|
|
544
|
+
28. 2.4.2: every option has a picture; the dashboard pictures show the current version;
|
|
515
545
|
guide and tutorial examples rerun; facts made consistent; no change of results.
|
|
516
|
-
29.
|
|
546
|
+
29. 2.5.0: an independent, pre-registered validation study: the ns-3 comparison setting for the
|
|
547
|
+
failure level (its pass on V1 was corrected in 2.6.0: not validated), and the generalisation of the
|
|
548
|
+
adaptive and learning rules to unseen cards and seeds; no change of results.
|
|
549
|
+
30. **2.6.0 (this release)**: the bridge to ns-3 / 5G-LENA (export, import, compare); the correction of the
|
|
550
|
+
2.5.0 failure-level comparison (equal run lengths: the absolute failure level is not calibrated); no
|
|
551
|
+
change of results.
|
|
552
|
+
31. Later (planned, not done), staying a handover simulator: an "ns-3-like" option imitating ns-3's slower
|
|
553
|
+
out-of-sync detection, judged on a fresh ns-3 set (V4) kept unopened until it is frozen; the effect of a handover on what the user
|
|
517
554
|
sees (simple TCP and application models on top of the buffers), MIMO as an SINR gain, hundreds of
|
|
518
555
|
users per run, and one scenario definition that also runs in ns-3; condEventT1 and earth-fixed beams.
|
|
519
556
|
|
|
@@ -523,9 +560,10 @@ If you use HandoverLab, please cite it as described in [CITATION.cff](https://gi
|
|
|
523
560
|
it under *Cite this repository*). Every release is archived on Zenodo:
|
|
524
561
|
[doi:10.5281/zenodo.23409131](https://doi.org/10.5281/zenodo.23409131) cites all versions (it resolves to
|
|
525
562
|
the latest). To cite the exact version you used, take its DOI from the version list on that page, where
|
|
526
|
-
the DOI of the latest version is listed; for example, version 2.4.
|
|
563
|
+
the DOI of the latest version is listed; for example, version 2.4.2 is
|
|
564
|
+
[doi:10.5281/zenodo.23589215](https://doi.org/10.5281/zenodo.23589215), version 2.4.1
|
|
527
565
|
[doi:10.5281/zenodo.23585308](https://doi.org/10.5281/zenodo.23585308) and version 2.4.0
|
|
528
|
-
[doi:10.5281/zenodo.23582521](https://doi.org/10.5281/zenodo.23582521). The BibTeX entry below cites 2.4.
|
|
566
|
+
[doi:10.5281/zenodo.23582521](https://doi.org/10.5281/zenodo.23582521). The BibTeX entry below cites 2.4.2;
|
|
529
567
|
replace version and DOI with those of the version you used.
|
|
530
568
|
|
|
531
569
|
```bibtex
|
|
@@ -534,8 +572,8 @@ replace version and DOI with those of the version you used.
|
|
|
534
572
|
title = {{HandoverLab}: system-level handover simulator for 5G-Advanced and beyond-5G research},
|
|
535
573
|
year = {2026},
|
|
536
574
|
publisher = {Zenodo},
|
|
537
|
-
version = {2.4.
|
|
538
|
-
doi = {10.5281/zenodo.
|
|
575
|
+
version = {2.4.2},
|
|
576
|
+
doi = {10.5281/zenodo.23589215},
|
|
539
577
|
url = {https://github.com/mjs19971997/handoverlab}
|
|
540
578
|
}
|
|
541
579
|
```
|