handoverlab 2.0.0__tar.gz → 2.2.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.2.0/.zenodo.json +34 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/CHANGELOG.md +148 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/CITATION.cff +3 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/PKG-INFO +56 -23
- {handoverlab-2.0.0 → handoverlab-2.2.0}/README.md +54 -21
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/calibration-3gpp.md +12 -2
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/calibration.md +22 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/beams-layers.md +5 -2
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/daps-ltm.md +8 -4
- handoverlab-2.2.0/docs/guides/fading.md +78 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/highway.md +20 -9
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/indoor-rural.md +10 -6
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/mro.md +4 -4
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/ntn.md +20 -8
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/radio-maps.md +7 -4
- handoverlab-2.2.0/docs/guides/scheduler.md +65 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/index.md +6 -5
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/migration-2.0.md +6 -4
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/cli.md +7 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/metrics.md +24 -13
- handoverlab-2.2.0/docs/reference-study.md +58 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/dense-urban-2layer.md +14 -17
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/fr3-urban-15ghz.md +14 -10
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/highway-tr37885-30ghz.md +28 -24
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/highway-tr37885-4ghz.md +24 -17
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/indoor-office-4ghz.md +18 -19
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/ns3-urban-3.5ghz.md +10 -8
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/ntn-leo600-2ghz.md +19 -33
- handoverlab-2.2.0/docs/scenarios/ntn-leo600-2ghz.svg +21 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/open-area-10ghz.md +11 -10
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/rural-700mhz.md +17 -18
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/smoke.md +14 -10
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/urban-grid-10ghz.md +14 -10
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/urban-grid-28ghz-beams.md +16 -12
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/stability.md +3 -1
- handoverlab-2.2.0/docs/standard-compliance.md +362 -0
- handoverlab-2.2.0/docs/time-step.md +55 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/tutorials/reading-the-report.md +7 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/user_guide.md +48 -27
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/verification.md +13 -2
- handoverlab-2.2.0/examples/study_reference.yaml +53 -0
- handoverlab-2.2.0/examples/study_reference_explore.yaml +55 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/mkdocs.yml +5 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/pyproject.toml +2 -2
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/__init__.py +1 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/extended.py +39 -5
- handoverlab-2.2.0/src/handoverlab/channel/fading.py +157 -0
- handoverlab-2.2.0/src/handoverlab/channel/l2s.py +51 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/ntn.py +58 -9
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/pathloss.py +106 -18
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/radiomap.py +131 -19
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/source.py +50 -11
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/cli.py +5 -2
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/config.py +157 -20
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/_kernels.py +21 -9
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/batch.py +35 -20
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/core.py +220 -48
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/extended.py +74 -28
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/invariants.py +2 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/metrics.py +16 -9
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/procedures.py +115 -21
- handoverlab-2.2.0/src/handoverlab/engine/scheduler.py +210 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/eventlog.py +1 -1
- handoverlab-2.2.0/src/handoverlab/linklevel.py +145 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/measurement.py +5 -2
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/mobility.py +10 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/requirements.py +8 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/base.py +6 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/builtin.py +31 -14
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/mro.py +14 -6
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/__init__.py +74 -12
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/dense-urban-2layer.yaml +5 -2
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/fr3-urban-15ghz.yaml +6 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/highway-tr37885-30ghz.yaml +6 -6
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/highway-tr37885-4ghz.yaml +5 -5
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/indoor-office-4ghz.yaml +12 -9
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/ns3-urban-3.5ghz.yaml +1 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/ntn-leo600-2ghz.yaml +13 -8
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/open-area-10ghz.yaml +2 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/rural-700mhz.yaml +9 -6
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/smoke.yaml +6 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/urban-grid-10ghz.yaml +7 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/urban-grid-28ghz-beams.yaml +6 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/seeds.py +3 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/stability.py +35 -1
- handoverlab-2.2.0/src/handoverlab/standard.py +231 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/stats.py +3 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/report.py +2 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/runner.py +1 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/study.py +15 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/tuning.py +23 -4
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/traffic.py +2 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/__init__.py +12 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/calibration.py +28 -9
- handoverlab-2.2.0/src/handoverlab/verify/data/golden.json +466 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/engine_checks.py +4 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/extended.py +3 -1
- handoverlab-2.2.0/src/handoverlab/verify/fading.py +61 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/golden.py +4 -2
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/highway.py +25 -13
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/ns3.py +16 -12
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/ntn.py +22 -11
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/radio.py +9 -4
- handoverlab-2.2.0/src/handoverlab/verify/values.py +38 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/PKG-INFO +56 -23
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/SOURCES.txt +18 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/public_api.json +21 -1
- handoverlab-2.2.0/tests/test_channel_detail.py +270 -0
- handoverlab-2.2.0/tests/test_fading.py +127 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_mro.py +2 -2
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_ntn.py +21 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_pathloss.py +1 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_protocol_3gpp.py +12 -4
- handoverlab-2.2.0/tests/test_readme_boundaries.py +33 -0
- handoverlab-2.2.0/tests/test_rrc_detail.py +167 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_rules_rc2.py +6 -1
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_scenarios.py +2 -1
- handoverlab-2.2.0/tests/test_scheduler.py +136 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_signalling_energy.py +13 -3
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_verify.py +32 -1
- handoverlab-2.0.0/.zenodo.json +0 -26
- handoverlab-2.0.0/docs/scenarios/ntn-leo600-2ghz.svg +0 -21
- handoverlab-2.0.0/docs/standard-compliance.md +0 -303
- handoverlab-2.0.0/src/handoverlab/verify/data/golden.json +0 -466
- {handoverlab-2.0.0 → handoverlab-2.2.0}/CODE_OF_CONDUCT.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/CONTRIBUTING.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/LICENSE +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/MANIFEST.in +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/SECURITY.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/RELEASING.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/add-scenario.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/dashboard.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/export-event-logs.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/learning-rule.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/many-cores.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/reproduce.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/upper-mid-band.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/calibration_38901.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/dashboard-charts.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/dashboard-compare.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/dashboard-where.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/dashboard.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/ntn-beams.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/radio-map.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/report-comparison.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/report-tuning.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/ssb-beams.png +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/performance.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/config.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/engine.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/eventlog.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/gui.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/index.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/mapfile.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/ntn.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/rules.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/scenarios.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/simulate.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/stability.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/stats.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/studies.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/testing.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/verify.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/dense-urban-2layer.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/fr3-urban-15ghz.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/highway-tr37885-30ghz.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/highway-tr37885-4ghz.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/indoor-office-4ghz.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/ns3-urban-3.5ghz.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/open-area-10ghz.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/rural-700mhz.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/smoke.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/urban-grid-10ghz.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/urban-grid-28ghz-beams.svg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/tutorials/first-run.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/tutorials/own-rule.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/tutorials/tuning-study.md +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/compare_a3_cho.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/open_area.toml +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/radio_map.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/smoke.yaml +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/speed_rule.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/street_grid.yaml +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/study_smoke.yaml +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/traffic_models.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/setup.cfg +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/__main__.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/__init__.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/antenna.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/__init__.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/gui/__init__.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/gui/app.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/gui/logic.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/io.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/layout.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/mapfile.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/py.typed +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/__init__.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/dqn.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/simulate.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/__init__.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/config.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/status.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/store.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/testing.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/data/golden_1x.json +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/data/ns3_urban_a3.json +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/data/r1_165974.csv +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/learning.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/report.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/stored.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/world.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/dependency_links.txt +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/entry_points.txt +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/requires.txt +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/top_level.txt +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/conftest.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/bh6_reference.json +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/bh6_wide.json +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/make_bh6_reference.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/make_bh6_wide.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/helpers.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_batch.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_beams_layers.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_calibration.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_cltm.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_config_cli.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_contract.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_determinism.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_dqn.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_engine_triggers.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_eventlog.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_gui.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_highway.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_highway_tr37885.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_indoor_rural.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_invariants.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_levels_status_extend.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_lm_model.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_mapfile.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_measurement.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_regression_bh6.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_regression_bh6_wide.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_stability.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_stats.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_study.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_tools.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_traffic.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_tuning.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_v111.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/compare_fingerprints.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_beam_figure.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_calibration_figure.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_ntn_figure.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_radiomap_figure.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_readme_images.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/mkdocs_hooks.py +0 -0
- {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/release_check.py +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "HandoverLab: system-level handover simulator for 5G-Advanced and beyond-5G research",
|
|
3
|
+
"description": "HandoverLab is an open-source, system-level simulator of 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) for many users in dense 5G-Advanced and beyond-5G networks, on a street grid, in an open area, along a highway, in an indoor office, in 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), an L3-filtered measurement chain, a radio-link failure model, an outcome label for every handover attempt, a plug-in interface for handover rules, equal-budget tuning studies with paired statistics, and verification against hand-computed values, golden event-log fingerprints 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
|
+
],
|
|
27
|
+
"related_identifiers": [
|
|
28
|
+
{
|
|
29
|
+
"identifier": "https://github.com/mjs19971997/handoverlab",
|
|
30
|
+
"relation": "isSupplementTo",
|
|
31
|
+
"scheme": "url"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
@@ -7,6 +7,151 @@ All notable changes to this project are documented in this file. The format foll
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.2.0] - 2026-10-22
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Fast fading as an option (`radio.fast_fading`: `tdl-a` .. `tdl-e`, off by default): the tapped delay line
|
|
15
|
+
models of TR 38.901 V19.5.0 clause 7.7.2 with the delay scaling of Eq. 7.7-1 (`radio.delay_spread_ns`, 100 ns
|
|
16
|
+
by default) and the K-factor change of clause 7.7.6 (`radio.fading_k_db`); each user-cell link fades on its own
|
|
17
|
+
with 32 sinusoids per Rayleigh tap (Jakes spectrum, f_D from the user's speed) and the LOS tap of TDL-D / -E at
|
|
18
|
+
0.7 f_D. Link-to-system mapping (`handoverlab.channel.l2s`): radio-link monitoring compares the MIESM effective
|
|
19
|
+
SINR of QPSK over the 24 PRBs of the hypothetical PDCCH (TS 38.133 Tables 8.1.2.1-1/-2) with Qout / Qin, and
|
|
20
|
+
the rate uses the capacity-equivalent SINR over the carrier. Base engine only in this version. With the option
|
|
21
|
+
off every result is unchanged. Guide: `docs/guides/fading.md`; `verify` group `fading` (criteria fixed before
|
|
22
|
+
the model was written; 32 sinusoids instead of 16 after the Rayleigh test failed with 16).
|
|
23
|
+
- Slot scheduler as an option (`protocol.scheduler`: `rr` or `pf`, off by default): every slot of the interval is
|
|
24
|
+
played (slot length of TS 38.211 Table 4.3.2-1), the free PRBs of a cell go to its users with data, the MCS is
|
|
25
|
+
the highest of TS 38.214 Table 5.1.3.1-1 with a block-error probability of at most 10 % at the reported SINR,
|
|
26
|
+
the TBS follows TS 38.214 clause 5.1.3.2, and HARQ runs with 8 processes per user, chase combining and at most
|
|
27
|
+
`protocol.harq_max_tx` transmissions after `protocol.harq_rtt_slots`. The block-error probability is the normal
|
|
28
|
+
approximation of the finite-blocklength error probability on the BICM bit channel of the modulation
|
|
29
|
+
(`handoverlab.linklevel`), with an implementation loss `protocol.l2s_loss_db`. Base engine only; about 45
|
|
30
|
+
times slower than the rate model. Guide: `docs/guides/scheduler.md`.
|
|
31
|
+
- `benchmarks/ns3/run_benchmark.py --fading`: the ns-3 runs with ns-3's TR 38.901 fast fading.
|
|
32
|
+
|
|
33
|
+
### Documentation
|
|
34
|
+
|
|
35
|
+
- Fast fading against ns-3 runs with fading (96 runs, criterion fixed before the runs): `tdl-c` passes
|
|
36
|
+
(handover ratio 1.04, unnecessary-handover ratio 1.24, ranks 0.97 / 0.98); `docs/guides/fading.md`.
|
|
37
|
+
- Held-out check of the failure-model parts on 40 new ns-3 runs, limits fixed before the runs: execution time
|
|
38
|
+
passes; the load effect on link monitoring and the time without connection after a failure fail; execution
|
|
39
|
+
failures are not measurable (none in ns-3). Reported as is in `docs/calibration.md`.
|
|
40
|
+
|
|
41
|
+
## [2.1.0] - 2026-10-21
|
|
42
|
+
|
|
43
|
+
A clause-by-clause audit of the protocol engine against TS 38.331 V18.11.0, TS 38.133, TS 38.300 V18.11.0 and
|
|
44
|
+
TS 38.321, of the value domains against the ASN.1 of TS 38.331, and of the large-scale channel and the scenario
|
|
45
|
+
cards against TR 38.901 V19.5.0, TR 37.885 V15.3.0, TR 38.811 V15.4.0, TR 38.821 V16.2.0 and ITU-R M.2412-0.
|
|
46
|
+
Every change that alters results sits behind a switch: `protocol.rrc_detail: simple` and
|
|
47
|
+
`radio.channel_detail: simple` (both now in `handoverlab.stability.LEGACY_1X`) and the card values of
|
|
48
|
+
`handoverlab.stability.LEGACY_CARDS` give the 2.0.0 model back, and the 1.x golden fingerprints are still
|
|
49
|
+
reproduced. Results of an unchanged configuration differ from 2.0.0 (`MODEL_VERSION` 3; new golden
|
|
50
|
+
fingerprints in `verify/data/golden.json`).
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
|
|
54
|
+
- `protocol.rrc_detail` (`3gpp`, the default, or `simple`, the engine of 2.0.0). With `3gpp`:
|
|
55
|
+
- out-of-sync and in-sync indications every max(10 ms, T_SSB) (TS 38.133 8.1.6); N310 counts consecutive
|
|
56
|
+
out-of-sync indications while T310 is stopped, N311 consecutive in-sync indications while it runs, each reset
|
|
57
|
+
by the other indication (TS 38.331 clause 7.2, 5.3.10.2), in all three engines and the compiled kernel;
|
|
58
|
+
- DAPS: T310 of the source keeps running at the reconfiguration with sync (5.3.5.5.2), the source link is
|
|
59
|
+
monitored during T304 and can fail (5.3.10.1, 5.3.10.3), and the UE falls back to the source only if no
|
|
60
|
+
source RLF was detected (5.3.5.8.3); no DAPS from FR2 to FR2 (TS 38.300 9.2.3.1) and none for NTN (refused,
|
|
61
|
+
16.14.3.2.1);
|
|
62
|
+
- LTM keeps its ltm-Config across a cell switch (5.3.5.18.6) and adds 20 ms of T_LTM-processing on a change of
|
|
63
|
+
frequency range (TS 38.133 6.3.1.3);
|
|
64
|
+
- CHO executes when the time-to-trigger of its condition expires, also between measurement instants, like the
|
|
65
|
+
report of 5.5.4.1 (5.3.5.13.4); CHO with condEventD2 and A3 keeps one state and time-to-trigger per event
|
|
66
|
+
(`ttt_d2_s`), updated at every measurement and reset on release; a recovery into a prepared cell is a
|
|
67
|
+
reconfiguration with sync and re-establishes if the cell cannot be joined before T304 expires (5.3.7.3);
|
|
68
|
+
- L3 filter with the intra-frequency L1 period of the frequency range as reference period (5.5.3.2),
|
|
69
|
+
Qout_LR = Qout + 4 dB for beam failure detection (TS 38.133 Tables 8.5.2.1-1 and 8.1.2.1-1), the RLM set
|
|
70
|
+
N_RLM, the BFD timer reset only after it expired, and L1-RSRP with N = 8 in FR2 (9.5.4.1);
|
|
71
|
+
- the RRC messages counted one by one: measurement reports, commands (an LTM cell switch is a MAC CE),
|
|
72
|
+
configurations once per user, Complete messages and releases.
|
|
73
|
+
- Outcome `coverage` and metric `coverage_failures_pm`: a failure after which the UE re-establishes in its
|
|
74
|
+
serving (or target) cell is neither too early nor too late. The outcome classes follow TS 38.300 15.5.2.2.2
|
|
75
|
+
(too early: re-establishment in the source; wrong cell: in a cell other than source and target; too late: a
|
|
76
|
+
failure before a handover, re-establishment elsewhere), one class per failure; `too_late_pm` counts the classes.
|
|
77
|
+
- `handoverlab.standard`: the value domains of TS 38.331 V18.11.0 (TimeToTrigger, Hysteresis,
|
|
78
|
+
MeasTriggerQuantityOffset, Q-OffsetRange, FilterCoefficient, ReportInterval, RLF timers and constants, t304,
|
|
79
|
+
SSB periodicity, RSRP-Range, maxNrofCondCells, the D2 distance steps) with the clause or page of each, and
|
|
80
|
+
`check_rule` / `check_scenario`; the `verify` group `values` checks every built-in card and rule default;
|
|
81
|
+
studies have a gate `standard_values` (blocking by default), and grid extensions stay on standard values.
|
|
82
|
+
- `radio.channel_detail` (`3gpp`, the default, or `simple`): with `3gpp` the place-tied shadowing and LOS
|
|
83
|
+
fields have the exponential autocorrelation exp(-d / d_cor) of TR 38.901 Eq. (7.4-5) (circulant embedding,
|
|
84
|
+
periodic with the highway wrap-around), the shadowing is uncorrelated between sites (clause 7.5 step 4),
|
|
85
|
+
UMa has C'(h_UT) in the LOS probability and the random effective environment height of Table 7.4.1-1
|
|
86
|
+
note 1 (h_UT >= 13 m), antenna heights outside the applicability ranges of Table 7.4.1-1 are refused,
|
|
87
|
+
links beyond the upper distance bound give a warning, and a co-sited layer must keep the LOS-state and
|
|
88
|
+
shadowing settings of the first layer (clause 7.6.5).
|
|
89
|
+
- `radio.pathloss: inh_office_open` (the open-office LOS probability); mobility profiles `p3`, `v30`, `v120`
|
|
90
|
+
(the fixed speeds of ITU-R M.2412-0 Tables 5a-5c) and `v140c`, `v70c` (TR 37.885 highway speeds on the lane
|
|
91
|
+
centre); `ntn.hpbw_deg` (unset: the tabled 3 dB beamwidth of TR 38.821 Tables 6.1.1.1-1/-2, from which the
|
|
92
|
+
beam spacing of Table 6.1.1.1-4 is computed) and `ntn.los_model` (`los`: the baseline "Clear Sky, Line of
|
|
93
|
+
sight" of TR 38.821 Table 6.1.1.1-5); `handoverlab.stability.LEGACY_CARDS`; the IRR-glass loss as a
|
|
94
|
+
parameter of the calibration module.
|
|
95
|
+
- `benchmarks/ns3/`: the ns-3 / 5G-LENA side of the comparison as a package anyone can rerun: the A3-only ns-3
|
|
96
|
+
program of the reference scenario (`handoverlab-ns3-a3.cc`, GPL-2.0-only like ns-3, outside the Python
|
|
97
|
+
package), `run_benchmark.py` for parts A, B and C (resumable, parallel) and the library state of the
|
|
98
|
+
reference runs; `handoverlab verify --ns3 --ns3-reference FILE` compares HandoverLab with such a file.
|
|
99
|
+
- "Model boundaries" and "Scope: 5G-Advanced and beyond 5G" in the README, with a test that keeps the table in
|
|
100
|
+
step with the registered rules, cards and layouts.
|
|
101
|
+
- The page "The 10 ms step" (`docs/time-step.md`): 10, 5, 2 and 1 ms on two scenarios and four procedures, with
|
|
102
|
+
criteria fixed before the runs; all 30 met, the metrics identical seed by seed.
|
|
103
|
+
- The reference study (`examples/study_reference.yaml`, `docs/reference-study.md`): CHO against A3 at an equal
|
|
104
|
+
failure budget. The confirmatory question is not answered: the study gates stopped it, as CHO meets the budget
|
|
105
|
+
at every setting up to 8 dB and 960 ms; an exploratory test stage shows the price (-90 % unnecessary
|
|
106
|
+
handovers, but 12 dB lower SINR and 25 % lower throughput).
|
|
107
|
+
|
|
108
|
+
### Changed
|
|
109
|
+
|
|
110
|
+
- `radio.shadow_site_corr` is unset by default (0 with `channel_detail: 3gpp`, 0.5 with `simple`).
|
|
111
|
+
- Cards: UE antenna 1.6 m (TR 37.885 vehicle type 2) on `smoke`, `urban-grid-10ghz`, `fr3-urban-15ghz`,
|
|
112
|
+
`urban-grid-28ghz-beams`; `indoor-office-4ghz` with `p3` and the open-office LOS probability;
|
|
113
|
+
`rural-700mhz` with `v120`; `dense-urban-2layer` with `v30`; highway cards with `v140c`; `ntn-leo600-2ghz`
|
|
114
|
+
with `ntn.los_model: los`. The card pages leave out keys that the layout and radio model do not read, keep
|
|
115
|
+
the card's own source for beam keys, and the cards state the remaining abstractions (one shadowing
|
|
116
|
+
decorrelation distance, LOS and NLOS on one shadowing realisation, LOS state on top of the buildings, user
|
|
117
|
+
numbers, scintillation as a link-budget margin, no wrap-around beam tiers).
|
|
118
|
+
- `verify`: radio statistics expect the exponential correlation and no correlation between sites; highway
|
|
119
|
+
check H3 uses the uncorrelated shadowing of TR 38.901 and simulates it along each vehicle's path (the
|
|
120
|
+
place-tied exponential field leaves too few independent samples per road), H2 accepts a jump at the
|
|
121
|
+
wrap-around up to the size of the ordinary steps (the radio map has a whole number of pixels per period);
|
|
122
|
+
NTN check N2 checks the tabled beamwidth (it passes now for both S-band apertures).
|
|
123
|
+
- `a3_mro`: `step_db` 1 dB by default (0.5 dB before), so that every offset is a Q-OffsetRange value; a
|
|
124
|
+
ping-pong must be strictly shorter than `pingpong_s`, and no ping-pong is counted across a re-establishment.
|
|
125
|
+
- Validation: `ssb_avg` at most min(`n_ssb`, 16) (maxNrofSS-BlocksToAverage); FR2-2 power classes 1 to 3;
|
|
126
|
+
T310, delays and the report interval must not be negative; with `rrc_detail: 3gpp` and TS 38.133 measurement
|
|
127
|
+
periods on several carriers, `protocol.gap_pattern` must be one of the per-UE gap ids that TS 38.133 Table
|
|
128
|
+
9.1.2-3 allows for the frequency ranges (FR1 present: 0-11, 24, 25; FR2 only: 12-25).
|
|
129
|
+
- Energy: each cell counts with the transmit power of its own layer (2.0.0: the base layer's power for every
|
|
130
|
+
cell), the metric is per cell, and the EARTH model has the number of transceivers of Auer et al. 2011 Eq. 1
|
|
131
|
+
(`radio.energy_ntrx`, 2 for the micro base station of Table 2; 1.x and 2.0.0: 1, now in `LEGACY_1X`).
|
|
132
|
+
- SS-RSRP per resource element with beams or layers: the power is spread over the 12 N_RB subcarriers of
|
|
133
|
+
TS 38.101-1 / TS 38.101-2 Table 5.3.2-1 (`radio.channel_detail: 3gpp`; 2.0.0: B / SCS, guard bands included).
|
|
134
|
+
- The title is "System-level handover simulator for 5G-Advanced and beyond-5G research" (README, PyPI, CITATION,
|
|
135
|
+
Zenodo, documentation site).
|
|
136
|
+
|
|
137
|
+
### Fixed
|
|
138
|
+
|
|
139
|
+
- Citations checked against the text of each document: FTP model 3 is defined in TR 36.872 Annex A.1 with the
|
|
140
|
+
0.5 Mbyte files of TR 38.802 Table A.2.1-1 and TR 38.821 Table 6.1.1.1-7 (TR 36.814 has models 1 and 2 only);
|
|
141
|
+
`protocol.reest_s` (1 s) is an assumption: TS 38.133 6.2.1.2.1 bounds the re-establishment delay by 50 ms +
|
|
142
|
+
cell identification (Table 6.2.1.2.1-1) + system information + PRACH, and TR 36.842 Table E.1-2 uses 250 ms;
|
|
143
|
+
MRO cites TS 28.313 clause 7.1.2; hand-calculated radio checks use c = 3e8 m/s; rows of
|
|
144
|
+
`docs/standard-compliance.md`, the user guide and the guides rewritten where the text said otherwise.
|
|
145
|
+
- Every citation of TS 38.133, TS 38.300, TS 38.321, TS 38.213 and TS 38.215 checked against the V19 texts (and
|
|
146
|
+
the versions named): no DAPS from FR2 to FR2 is TS 38.300 9.2.3.1 (not 9.2.3.2); recovery into a CHO candidate
|
|
147
|
+
9.2.3.1 and 9.2.7 (not 9.2.3.4); M_meas_period_w/o_gaps TS 38.133 9.2.5.1; the BFD threshold in the user
|
|
148
|
+
guide is Qout_LR; the restart of link monitoring on a new cell is called what it is, an interpretation of
|
|
149
|
+
TS 38.133 8.1.2.2; the SSB as BFD reference signal cites TS 38.133 8.5.1; conditional LTM cites TS 38.300
|
|
150
|
+
V19.4.0 9.2.3.7.
|
|
151
|
+
- The verify check of the configured LTM / DAPS interruption (V1e) runs with ideal random access, so that an
|
|
152
|
+
execution waiting for its target under T304 does not count against it; the README table of model boundaries is
|
|
153
|
+
checked against the built-in rules only.
|
|
154
|
+
|
|
10
155
|
## [2.0.0] - 2026-10-20
|
|
11
156
|
|
|
12
157
|
2.0.0 makes the 3GPP values the defaults. Results of an unchanged configuration therefore differ from 1.x;
|
|
@@ -789,7 +934,9 @@ First alpha release (stage 1: the core simulator).
|
|
|
789
934
|
- Documentation: README, user guide, contribution guide, citation file; CI on Linux, Windows and
|
|
790
935
|
macOS with Python 3.9-3.12.
|
|
791
936
|
|
|
792
|
-
[Unreleased]: https://github.com/mjs19971997/handoverlab/compare/v2.
|
|
937
|
+
[Unreleased]: https://github.com/mjs19971997/handoverlab/compare/v2.2.0...HEAD
|
|
938
|
+
[2.2.0]: https://github.com/mjs19971997/handoverlab/compare/v2.1.0...v2.2.0
|
|
939
|
+
[2.1.0]: https://github.com/mjs19971997/handoverlab/compare/v2.0.0...v2.1.0
|
|
793
940
|
[2.0.0]: https://github.com/mjs19971997/handoverlab/compare/v1.12.0...v2.0.0
|
|
794
941
|
[1.12.0]: https://github.com/mjs19971997/handoverlab/compare/v1.11.0...v1.12.0
|
|
795
942
|
[1.11.0]: https://github.com/mjs19971997/handoverlab/compare/v1.10.0...v1.11.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
cff-version: 1.2.0
|
|
2
2
|
message: "If you use this software, please cite it as below."
|
|
3
|
-
title: "HandoverLab: system-level
|
|
3
|
+
title: "HandoverLab: system-level handover simulator for 5G-Advanced and beyond-5G research"
|
|
4
4
|
abstract: >-
|
|
5
5
|
HandoverLab is an open-source, system-level simulator of 3GPP mobility procedures (baseline
|
|
6
6
|
handover with Event A3, Release-16 conditional and DAPS handover, Release-18 L1/L2-triggered
|
|
@@ -11,7 +11,7 @@ abstract: >-
|
|
|
11
11
|
measurement chain, a radio-link failure model, an outcome label for every handover attempt,
|
|
12
12
|
a plug-in interface for handover rules, equal-budget tuning studies with paired statistics,
|
|
13
13
|
and verification against hand-computed values, golden event-log fingerprints and ns-3 / 5G-LENA.
|
|
14
|
-
version: "2.
|
|
14
|
+
version: "2.2.0"
|
|
15
15
|
doi: 10.5281/zenodo.23409131
|
|
16
16
|
identifiers:
|
|
17
17
|
- type: doi
|
|
@@ -23,7 +23,7 @@ identifiers:
|
|
|
23
23
|
- type: doi
|
|
24
24
|
value: 10.5281/zenodo.23409402
|
|
25
25
|
description: "Version 1.0.1 on Zenodo"
|
|
26
|
-
date-released: 2026-10-
|
|
26
|
+
date-released: 2026-10-22
|
|
27
27
|
license: MIT
|
|
28
28
|
repository-code: "https://github.com/mjs19971997/handoverlab"
|
|
29
29
|
url: "https://mjs19971997.github.io/handoverlab/"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: handoverlab
|
|
3
|
-
Version: 2.
|
|
4
|
-
Summary: System-level
|
|
3
|
+
Version: 2.2.0
|
|
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
|
|
7
7
|
Project-URL: Homepage, https://github.com/mjs19971997/handoverlab
|
|
@@ -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
|
-
A system-level simulator for
|
|
63
|
+
A system-level handover simulator for 5G-Advanced and beyond-5G research, 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
|
|
@@ -75,7 +75,8 @@ outcome label for every handover attempt.
|
|
|
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,
|
|
77
77
|
> the urban vehicles of TR 37.885, the path-loss constants of TR 38.901), so results differ from 1.x;
|
|
78
|
-
> one switch, `LEGACY_1X`, gives every 1.x result back bit for bit
|
|
78
|
+
> one switch, `LEGACY_1X`, gives every 1.x result back bit for bit (for the cards changed since 2.1.0
|
|
79
|
+
> together with their old values in `LEGACY_CARDS`)
|
|
79
80
|
> ([moving from 1.x to 2.0](https://github.com/mjs19971997/handoverlab/blob/main/docs/migration-2.0.md)).
|
|
80
81
|
|
|
81
82
|
## See it
|
|
@@ -157,7 +158,7 @@ event D2 of Release 18:
|
|
|
157
158
|
pedestrian and vehicular speed profiles (by default the urban vehicles of TR 37.885: 60 km/h in one of
|
|
158
159
|
two lanes) or your own speed groups.
|
|
159
160
|
- **Traffic**: constant service rates per 5QI class, or a traffic model per user: full buffer,
|
|
160
|
-
periodic packets (as VoIP) or FTP model 3 of TR
|
|
161
|
+
periodic packets (as VoIP) or FTP model 3 (TR 38.802, the 0.5 Mbyte files of TR 38.821). The load of every cell, and so the
|
|
161
162
|
interference, follows the traffic of its users.
|
|
162
163
|
- **Measurements**: L1 samples, the TS 38.331 L3 filter, Event A3 with time-to-trigger, periodic
|
|
163
164
|
reporting for conditional handover.
|
|
@@ -169,9 +170,9 @@ event D2 of Release 18:
|
|
|
169
170
|
epsilon-greedy bandit (`a3_bandit`, checked against an exhaustive search) and a deep Q-network
|
|
170
171
|
(`dqn`, optional PyTorch).
|
|
171
172
|
- **Failure model**: Qout/Qin with windows, N310/N311/T310, T304, lost commands and configurations,
|
|
172
|
-
execution failures, re-establishment
|
|
173
|
-
during T310 and the restart of the link monitoring on a new cell as
|
|
174
|
-
(defaults since 2.0.0), with options for the link monitoring (own interferer load, ideal random access).
|
|
173
|
+
execution failures, re-establishment after a fixed outage (1 s, an assumption), the handover command
|
|
174
|
+
during T310 as TS 38.331 specifies and the restart of the link monitoring on a new cell as HandoverLab
|
|
175
|
+
reads TS 38.133 8.1.2.2 (defaults since 2.0.0), with options for the link monitoring (own interferer load, ideal random access).
|
|
175
176
|
- **Metrics**: outcome of every attempt (useful, unnecessary, too early, wrong cell, too late,
|
|
176
177
|
censored), failures by cause, ping-pong, preparation overhead, interruption, delivered rate,
|
|
177
178
|
signalling (RRC messages, commands), L1 measurements of the device and network energy (EARTH
|
|
@@ -180,17 +181,47 @@ event D2 of Release 18:
|
|
|
180
181
|
engine draws no random numbers; golden event-log fingerprints guard every change. An optional
|
|
181
182
|
compiled kernel (`run.backend: numba`) gives the same event logs bit for bit.
|
|
182
183
|
|
|
183
|
-
##
|
|
184
|
-
|
|
185
|
-
HandoverLab
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
184
|
+
## Model boundaries
|
|
185
|
+
|
|
186
|
+
What HandoverLab is for, at a glance: questions about handover and mobility procedures and the rules that
|
|
187
|
+
drive them, compared on the same worlds. What it abstracts or leaves out decides which conclusions it supports;
|
|
188
|
+
the clause-by-clause detail is in [standard compliance](https://github.com/mjs19971997/handoverlab/blob/main/docs/standard-compliance.md).
|
|
189
|
+
|
|
190
|
+
| Part | Modelled | Abstracted | Not modelled |
|
|
191
|
+
|---|---|---|---|
|
|
192
|
+
| Layouts | `street_grid` (TR 37.885 urban grid), `open_area`, `highway` (TR 37.885 / TR 36.885, wrap-around), `indoor` (TR 38.901 office), `ntn` (one LEO satellite, TR 38.821); explicit site lists | sites on the pavement with small cells (urban cards) | the 500 m macro grid of the TR 37.885 urban scenario, several satellites |
|
|
193
|
+
| Channel | TR 38.901 path loss and LOS (UMi, UMa, RMa, InH), LOS from buildings, spatially consistent LOS and shadowing, penetration loss, radio maps from a file (clause 8), TR 38.811 for the satellite | received power per site and step with a slow time-varying component; optional TDL fast fading with effective SINRs (clause 7.7.2, since 2.2.0) | CDL and the full fast-fading model of clause 7.5, MIMO |
|
|
194
|
+
| Beams and carriers | SSB beams per sector, cell quality from beams, beam failure detection and recovery, several carriers with gaps and Event A5 | the TR 38.901 antenna element and DFT beams; isotropic UE | UE-side beamforming, dual connectivity and PSCell change |
|
|
195
|
+
| Mobility | street-following vehicles (60 km/h, two lanes), highway lanes at 70/140 km/h, random waypoints, pedestrians | constant speed per user | handheld rotation and body blockage |
|
|
196
|
+
| Traffic and load | constant rates per 5QI, full buffer, periodic, FTP model 3; cell load drives interference | rate from SINR (Shannon-type mapping), no scheduler | slot scheduler, HARQ, RLC/PDCP, TCP and applications |
|
|
197
|
+
| 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 |
|
|
198
|
+
| 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`, `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 |
|
|
199
|
+
| 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 rates are not calibrated: compare rules with each other |
|
|
200
|
+
| 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 |
|
|
201
|
+
|
|
202
|
+
Built-in cards: `smoke`, `urban-grid-10ghz`, `fr3-urban-15ghz`, `urban-grid-28ghz-beams`, `dense-urban-2layer`,
|
|
203
|
+
`open-area-10ghz`, `ns3-urban-3.5ghz`, `highway-tr37885-4ghz`, `highway-tr37885-30ghz`, `indoor-office-4ghz`,
|
|
204
|
+
`rural-700mhz`, `ntn-leo600-2ghz`; each names the source of every value and its own limitations.
|
|
205
|
+
|
|
206
|
+
## Scope: 5G-Advanced and beyond 5G
|
|
207
|
+
|
|
208
|
+
HandoverLab is a system-level handover simulator for 5G-Advanced and beyond-5G research. It covers the
|
|
209
|
+
mobility procedures of Releases 16 to 19 (conditional handover, DAPS handover, L1/L2-triggered mobility,
|
|
210
|
+
conditional LTM, conditional handover with the location events of Release 18 for satellites) in dense
|
|
211
|
+
networks with small cells 50-300 m apart. Three paths lead beyond 5G:
|
|
212
|
+
|
|
213
|
+
- **The upper mid-band (FR3, 7-24 GHz)**, studied in TR 38.901 V19.5.0: the card `fr3-urban-15ghz` and every
|
|
214
|
+
layout at any carrier the path-loss models cover.
|
|
215
|
+
- **Non-terrestrial networks**: a LEO satellite with earth-moving beams (TR 38.811, TR 38.821) and conditional
|
|
216
|
+
handover with condEventD2 (TS 38.331 Release 18).
|
|
217
|
+
- **Learning-based mobility**: the rule interface gives a rule every measurement and the outcome of every
|
|
218
|
+
attempt; `a3_bandit` and `dqn` are examples, `a3_mro` the fair tuned baseline.
|
|
219
|
+
|
|
220
|
+
6G itself is at the stage of requirements: TR 38.914 V20.1.0 (Release 20, last changed at RAN #113 in September
|
|
221
|
+
2026) sets scenarios and key performance requirements but specifies no handover procedure, timer or measurement
|
|
222
|
+
rule yet. HandoverLab therefore claims no 6G procedure; the paths above are where 6G mobility work is expected
|
|
223
|
+
to build on 5G-Advanced. The cost of every procedure (signalling, prepared cells, interruption, energy) is
|
|
224
|
+
measured next to its benefit.
|
|
194
225
|
|
|
195
226
|
## Calibrated against 3GPP
|
|
196
227
|
|
|
@@ -211,7 +242,9 @@ Every rule of the handover procedure is listed clause by clause against the offi
|
|
|
211
242
|
[standard compliance](https://github.com/mjs19971997/handoverlab/blob/main/docs/standard-compliance.md),
|
|
212
243
|
with what is followed, what is abstracted and what is not modelled yet. The 3GPP protocol profile of
|
|
213
244
|
1.9.0 (`protocol: {cmd_during_t310: receive, t304_s: 1.0, rlm_holdoff_s: 0.2}`), the default since 2.0.0,
|
|
214
|
-
makes the handover command and its execution
|
|
245
|
+
makes the handover command and its execution follow TS 38.331; the audit of 2.1.0 checked every procedure,
|
|
246
|
+
requirement and value against TS 38.331 V18.11.0, TS 38.133, TS 38.300 and the TRs, and what remains an
|
|
247
|
+
abstraction is listed on that page. Against handover statistics
|
|
215
248
|
measured in commercial 5G networks (SIGCOMM, IMC and MobiCom measurement studies) the profile
|
|
216
249
|
brings the handover failure rate from about six times above the measured range to just above it;
|
|
217
250
|
ping-pong with the Verizon A3 setting and the handover distance in low-band rural cells match.
|
|
@@ -221,8 +254,8 @@ the DAPS and LTM interruptions are checked against TS 38.133 and published 3GPP
|
|
|
221
254
|
## Checked against ns-3
|
|
222
255
|
|
|
223
256
|
The same 24 Event-A3 settings were simulated in HandoverLab and in the packet-level simulator
|
|
224
|
-
ns-3 with 5G-LENA. Handover and unnecessary-handover rates agree (median
|
|
225
|
-
correlation 0.99). For failure rates, with the in-car loss of ns-3 and the restart of the link
|
|
257
|
+
ns-3 with 5G-LENA. Handover and unnecessary-handover rates agree (median ratios 0.95 and 1.06,
|
|
258
|
+
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
|
|
226
259
|
monitoring switched on, the order of settings and conditions agrees too, also on ns-3 results
|
|
227
260
|
that were held back from any tuning (rank correlation 0.82-0.91). The absolute values
|
|
228
261
|
differ, so compare failure rates between rules within HandoverLab. The causes are traced in
|
|
@@ -277,7 +310,7 @@ L1/L2-triggered mobility.
|
|
|
277
310
|
- **1.4.0**: traffic models per user (`traffic.model`: full buffer, periodic, FTP model 3); a
|
|
278
311
|
dashboard with confidence intervals, a map of where handovers and failures happen, and the status
|
|
279
312
|
of a running study; the ns-3 link-monitoring finding in the calibration report.
|
|
280
|
-
- **1.3.0**: optional restart of the link monitoring on a newly joined cell (TS 38.133).
|
|
313
|
+
- **1.3.0**: optional restart of the link monitoring on a newly joined cell (an interpretation of TS 38.133 8.1.2.2).
|
|
281
314
|
- **1.2.0**: optional penetration loss per user; the ns-3 comparison with the in-car loss of ns-3.
|
|
282
315
|
- **1.1.0 / 1.1.1**: optional link-monitoring model; held-back ns-3 results; issue forms, CI on
|
|
283
316
|
Windows for every test.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://doi.org/10.5281/zenodo.23409131) [](https://pypi.org/project/handoverlab/)
|
|
4
4
|
|
|
5
|
-
A system-level simulator for
|
|
5
|
+
A system-level handover simulator for 5G-Advanced and beyond-5G research, 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
|
|
@@ -17,7 +17,8 @@ outcome label for every handover attempt.
|
|
|
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,
|
|
19
19
|
> the urban vehicles of TR 37.885, the path-loss constants of TR 38.901), so results differ from 1.x;
|
|
20
|
-
> one switch, `LEGACY_1X`, gives every 1.x result back bit for bit
|
|
20
|
+
> one switch, `LEGACY_1X`, gives every 1.x result back bit for bit (for the cards changed since 2.1.0
|
|
21
|
+
> together with their old values in `LEGACY_CARDS`)
|
|
21
22
|
> ([moving from 1.x to 2.0](https://github.com/mjs19971997/handoverlab/blob/main/docs/migration-2.0.md)).
|
|
22
23
|
|
|
23
24
|
## See it
|
|
@@ -99,7 +100,7 @@ event D2 of Release 18:
|
|
|
99
100
|
pedestrian and vehicular speed profiles (by default the urban vehicles of TR 37.885: 60 km/h in one of
|
|
100
101
|
two lanes) or your own speed groups.
|
|
101
102
|
- **Traffic**: constant service rates per 5QI class, or a traffic model per user: full buffer,
|
|
102
|
-
periodic packets (as VoIP) or FTP model 3 of TR
|
|
103
|
+
periodic packets (as VoIP) or FTP model 3 (TR 38.802, the 0.5 Mbyte files of TR 38.821). The load of every cell, and so the
|
|
103
104
|
interference, follows the traffic of its users.
|
|
104
105
|
- **Measurements**: L1 samples, the TS 38.331 L3 filter, Event A3 with time-to-trigger, periodic
|
|
105
106
|
reporting for conditional handover.
|
|
@@ -111,9 +112,9 @@ event D2 of Release 18:
|
|
|
111
112
|
epsilon-greedy bandit (`a3_bandit`, checked against an exhaustive search) and a deep Q-network
|
|
112
113
|
(`dqn`, optional PyTorch).
|
|
113
114
|
- **Failure model**: Qout/Qin with windows, N310/N311/T310, T304, lost commands and configurations,
|
|
114
|
-
execution failures, re-establishment
|
|
115
|
-
during T310 and the restart of the link monitoring on a new cell as
|
|
116
|
-
(defaults since 2.0.0), with options for the link monitoring (own interferer load, ideal random access).
|
|
115
|
+
execution failures, re-establishment after a fixed outage (1 s, an assumption), the handover command
|
|
116
|
+
during T310 as TS 38.331 specifies and the restart of the link monitoring on a new cell as HandoverLab
|
|
117
|
+
reads TS 38.133 8.1.2.2 (defaults since 2.0.0), with options for the link monitoring (own interferer load, ideal random access).
|
|
117
118
|
- **Metrics**: outcome of every attempt (useful, unnecessary, too early, wrong cell, too late,
|
|
118
119
|
censored), failures by cause, ping-pong, preparation overhead, interruption, delivered rate,
|
|
119
120
|
signalling (RRC messages, commands), L1 measurements of the device and network energy (EARTH
|
|
@@ -122,17 +123,47 @@ event D2 of Release 18:
|
|
|
122
123
|
engine draws no random numbers; golden event-log fingerprints guard every change. An optional
|
|
123
124
|
compiled kernel (`run.backend: numba`) gives the same event logs bit for bit.
|
|
124
125
|
|
|
125
|
-
##
|
|
126
|
-
|
|
127
|
-
HandoverLab
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
## Model boundaries
|
|
127
|
+
|
|
128
|
+
What HandoverLab is for, at a glance: questions about handover and mobility procedures and the rules that
|
|
129
|
+
drive them, compared on the same worlds. What it abstracts or leaves out decides which conclusions it supports;
|
|
130
|
+
the clause-by-clause detail is in [standard compliance](https://github.com/mjs19971997/handoverlab/blob/main/docs/standard-compliance.md).
|
|
131
|
+
|
|
132
|
+
| Part | Modelled | Abstracted | Not modelled |
|
|
133
|
+
|---|---|---|---|
|
|
134
|
+
| Layouts | `street_grid` (TR 37.885 urban grid), `open_area`, `highway` (TR 37.885 / TR 36.885, wrap-around), `indoor` (TR 38.901 office), `ntn` (one LEO satellite, TR 38.821); explicit site lists | sites on the pavement with small cells (urban cards) | the 500 m macro grid of the TR 37.885 urban scenario, several satellites |
|
|
135
|
+
| Channel | TR 38.901 path loss and LOS (UMi, UMa, RMa, InH), LOS from buildings, spatially consistent LOS and shadowing, penetration loss, radio maps from a file (clause 8), TR 38.811 for the satellite | received power per site and step with a slow time-varying component; optional TDL fast fading with effective SINRs (clause 7.7.2, since 2.2.0) | CDL and the full fast-fading model of clause 7.5, MIMO |
|
|
136
|
+
| Beams and carriers | SSB beams per sector, cell quality from beams, beam failure detection and recovery, several carriers with gaps and Event A5 | the TR 38.901 antenna element and DFT beams; isotropic UE | UE-side beamforming, dual connectivity and PSCell change |
|
|
137
|
+
| Mobility | street-following vehicles (60 km/h, two lanes), highway lanes at 70/140 km/h, random waypoints, pedestrians | constant speed per user | handheld rotation and body blockage |
|
|
138
|
+
| Traffic and load | constant rates per 5QI, full buffer, periodic, FTP model 3; cell load drives interference | rate from SINR (Shannon-type mapping), no scheduler | slot scheduler, HARQ, RLC/PDCP, TCP and applications |
|
|
139
|
+
| 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 |
|
|
140
|
+
| 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`, `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 |
|
|
141
|
+
| 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 rates are not calibrated: compare rules with each other |
|
|
142
|
+
| 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 |
|
|
143
|
+
|
|
144
|
+
Built-in cards: `smoke`, `urban-grid-10ghz`, `fr3-urban-15ghz`, `urban-grid-28ghz-beams`, `dense-urban-2layer`,
|
|
145
|
+
`open-area-10ghz`, `ns3-urban-3.5ghz`, `highway-tr37885-4ghz`, `highway-tr37885-30ghz`, `indoor-office-4ghz`,
|
|
146
|
+
`rural-700mhz`, `ntn-leo600-2ghz`; each names the source of every value and its own limitations.
|
|
147
|
+
|
|
148
|
+
## Scope: 5G-Advanced and beyond 5G
|
|
149
|
+
|
|
150
|
+
HandoverLab is a system-level handover simulator for 5G-Advanced and beyond-5G research. It covers the
|
|
151
|
+
mobility procedures of Releases 16 to 19 (conditional handover, DAPS handover, L1/L2-triggered mobility,
|
|
152
|
+
conditional LTM, conditional handover with the location events of Release 18 for satellites) in dense
|
|
153
|
+
networks with small cells 50-300 m apart. Three paths lead beyond 5G:
|
|
154
|
+
|
|
155
|
+
- **The upper mid-band (FR3, 7-24 GHz)**, studied in TR 38.901 V19.5.0: the card `fr3-urban-15ghz` and every
|
|
156
|
+
layout at any carrier the path-loss models cover.
|
|
157
|
+
- **Non-terrestrial networks**: a LEO satellite with earth-moving beams (TR 38.811, TR 38.821) and conditional
|
|
158
|
+
handover with condEventD2 (TS 38.331 Release 18).
|
|
159
|
+
- **Learning-based mobility**: the rule interface gives a rule every measurement and the outcome of every
|
|
160
|
+
attempt; `a3_bandit` and `dqn` are examples, `a3_mro` the fair tuned baseline.
|
|
161
|
+
|
|
162
|
+
6G itself is at the stage of requirements: TR 38.914 V20.1.0 (Release 20, last changed at RAN #113 in September
|
|
163
|
+
2026) sets scenarios and key performance requirements but specifies no handover procedure, timer or measurement
|
|
164
|
+
rule yet. HandoverLab therefore claims no 6G procedure; the paths above are where 6G mobility work is expected
|
|
165
|
+
to build on 5G-Advanced. The cost of every procedure (signalling, prepared cells, interruption, energy) is
|
|
166
|
+
measured next to its benefit.
|
|
136
167
|
|
|
137
168
|
## Calibrated against 3GPP
|
|
138
169
|
|
|
@@ -153,7 +184,9 @@ Every rule of the handover procedure is listed clause by clause against the offi
|
|
|
153
184
|
[standard compliance](https://github.com/mjs19971997/handoverlab/blob/main/docs/standard-compliance.md),
|
|
154
185
|
with what is followed, what is abstracted and what is not modelled yet. The 3GPP protocol profile of
|
|
155
186
|
1.9.0 (`protocol: {cmd_during_t310: receive, t304_s: 1.0, rlm_holdoff_s: 0.2}`), the default since 2.0.0,
|
|
156
|
-
makes the handover command and its execution
|
|
187
|
+
makes the handover command and its execution follow TS 38.331; the audit of 2.1.0 checked every procedure,
|
|
188
|
+
requirement and value against TS 38.331 V18.11.0, TS 38.133, TS 38.300 and the TRs, and what remains an
|
|
189
|
+
abstraction is listed on that page. Against handover statistics
|
|
157
190
|
measured in commercial 5G networks (SIGCOMM, IMC and MobiCom measurement studies) the profile
|
|
158
191
|
brings the handover failure rate from about six times above the measured range to just above it;
|
|
159
192
|
ping-pong with the Verizon A3 setting and the handover distance in low-band rural cells match.
|
|
@@ -163,8 +196,8 @@ the DAPS and LTM interruptions are checked against TS 38.133 and published 3GPP
|
|
|
163
196
|
## Checked against ns-3
|
|
164
197
|
|
|
165
198
|
The same 24 Event-A3 settings were simulated in HandoverLab and in the packet-level simulator
|
|
166
|
-
ns-3 with 5G-LENA. Handover and unnecessary-handover rates agree (median
|
|
167
|
-
correlation 0.99). For failure rates, with the in-car loss of ns-3 and the restart of the link
|
|
199
|
+
ns-3 with 5G-LENA. Handover and unnecessary-handover rates agree (median ratios 0.95 and 1.06,
|
|
200
|
+
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
|
|
168
201
|
monitoring switched on, the order of settings and conditions agrees too, also on ns-3 results
|
|
169
202
|
that were held back from any tuning (rank correlation 0.82-0.91). The absolute values
|
|
170
203
|
differ, so compare failure rates between rules within HandoverLab. The causes are traced in
|
|
@@ -219,7 +252,7 @@ L1/L2-triggered mobility.
|
|
|
219
252
|
- **1.4.0**: traffic models per user (`traffic.model`: full buffer, periodic, FTP model 3); a
|
|
220
253
|
dashboard with confidence intervals, a map of where handovers and failures happen, and the status
|
|
221
254
|
of a running study; the ns-3 link-monitoring finding in the calibration report.
|
|
222
|
-
- **1.3.0**: optional restart of the link monitoring on a newly joined cell (TS 38.133).
|
|
255
|
+
- **1.3.0**: optional restart of the link monitoring on a newly joined cell (an interpretation of TS 38.133 8.1.2.2).
|
|
223
256
|
- **1.2.0**: optional penetration loss per user; the ns-3 comparison with the in-car loss of ns-3.
|
|
224
257
|
- **1.1.0 / 1.1.1**: optional link-monitoring model; held-back ns-3 results; issue forms, CI on
|
|
225
258
|
Windows for every test.
|
|
@@ -10,6 +10,16 @@ range, and none is more than about 1 dB from the industry mean. `handoverlab ver
|
|
|
10
10
|
check (group `calibration`). With c = 3.0e8 m/s in the breakpoint distances (2.0.0) every number of this
|
|
11
11
|
page is unchanged.
|
|
12
12
|
|
|
13
|
+
**Version.** The drop uses the formulas of TR 38.901 V19.5.0 with one exception: the IRR-glass loss of the
|
|
14
|
+
high-loss O2I model. V19.5.0 Table 7.4.3-1 gives 25.4 + 0.11 f dB (note 2: updated in the Release 19 study
|
|
15
|
+
on 7-24 GHz); the calibration keeps the earlier 23 + 0.3 f dB of TR 38.901 V17.0.0, because the companies of
|
|
16
|
+
R1-165974 worked before that change (`IRR_GLASS_R1_165974` in `handoverlab.verify.calibration`; pass
|
|
17
|
+
`irr_glass=IRR_GLASS_V19` to `simulate_drops` for the V19.5.0 value). With the V19.5.0 value (30 000 users,
|
|
18
|
+
seed 1) the 6 GHz cases stay inside the company range, but at 30 GHz the coupling loss and the SINR of UMa
|
|
19
|
+
and UMi leave it (coupling loss: UMa 15 of 19 percentiles inside, largest distance from the mean 3.30 dB;
|
|
20
|
+
UMi 11 of 19, 3.25 dB): the higher glass loss at 30 GHz is a change of the model, not an error of the
|
|
21
|
+
reproduction.
|
|
22
|
+
|
|
13
23
|

|
|
14
24
|
|
|
15
25
|
## The reference
|
|
@@ -34,10 +44,10 @@ of the simulator (a test checks that they give exactly the values of `handoverla
|
|
|
34
44
|
| Layout | UMa: 19 sites, ISD 500 m, BS 25 m; UMi: 19 sites, ISD 200 m, BS 10 m; geographical wrap-around | TR 38.901 Tables 7.2-1 and 7.8-1 |
|
|
35
45
|
| Indoor office | 12 ceiling sites, 20 m apart, in a 120 m x 50 m hall, BS 3 m, users 1 m | Table 7.2-2, Figure 7.2-1 |
|
|
36
46
|
| Sectors and antenna | 3 sectors per site (30, 150, 270 deg); element pattern of Table 7.3-1 (8 dBi); 10 vertical elements, d_V = lambda / 2, DFT tilt 102 deg (UMa, UMi), 110 deg (indoor) | Tables 7.3-1, 7.8-1; Eq. 7.3-1 |
|
|
37
|
-
| Users | uniform; UMa and UMi 80 % indoor at height 3 (n_fl - 1) + 1.5 m, n_fl ~ uniform(1, N_fl), N_fl ~ uniform(4, 8); minimum 2D distance 35 m (UMa), 10 m (UMi), applied to d2D-out | Table 7.2-1; TR 36.873
|
|
47
|
+
| Users | uniform; UMa and UMi 80 % indoor at height 3 (n_fl - 1) + 1.5 m, n_fl ~ uniform(1, N_fl), N_fl ~ uniform(4, 8); minimum 2D distance 35 m (UMa), 10 m (UMi), applied to d2D-out | Table 7.2-1 ("Same as 3D-UMa in TR36.873"); the formula as in ITU-R M.2412-0 Table 5b (TR 36.873 itself is not in the local sources) |
|
|
38
48
|
| Path loss and LOS | Table 7.4.1-1 (UMa with the random effective environment height of note 1), Table 7.4.2-1 (UMa with C'(h_UT), indoor open office) | TR 38.901 |
|
|
39
49
|
| Shadowing | LOS / NLOS of Table 7.4.1-1; 7 dB for indoor users of UMa and UMi; independent between sites, shared by the sectors of a site | Tables 7.4.1-1 and 7.5-6 |
|
|
40
|
-
| O2I loss | 50 % low loss, 50 % high loss; d2D-in = min of two uniform(0, 25 m) | clause 7.4.3.1,
|
|
50
|
+
| O2I loss | 50 % low loss, 50 % high loss; d2D-in = min of two uniform(0, 25 m); IRR glass 23 + 0.3 f dB (see Version above) | clause 7.4.3.1, Tables 7.4.3-1 (V17.0.0 value), 7.4.3-2 |
|
|
41
51
|
| Link budget | 49 dBm (UMa), 44 dBm (UMi) at 6 GHz with 20 MHz; 35 dBm at 30 GHz with 100 MHz; 24 dBm indoor; UT noise figure 9 dB; isotropic UT | Table 7.8-1 |
|
|
42
52
|
| Association | sector with the highest received power (handover margin 0 dB), no fast fading | Table 7.8-1 |
|
|
43
53
|
|
|
@@ -10,6 +10,24 @@ rates agree (median ratios 0.93 and 0.95, ranks 0.97), and the failure level agr
|
|
|
10
10
|
0.84, limit 0.67-1.5), but the order of the failure rates does not (rank 0.68, limit 0.8). See
|
|
11
11
|
[standard compliance](standard-compliance.md#fresh-ns-3-hold-out-190).
|
|
12
12
|
|
|
13
|
+
**Held-out check of the failure-model parts (2.2.0).** 40 new ns-3 runs (seeds 201-210, urban,
|
|
14
|
+
20 users, A3 3 dB / 300 ms, ISD 200 and 400 m at 16 m/s, light traffic and 12 Mbit/s full traffic)
|
|
15
|
+
tested each part of the failure model against limits fixed before the runs, with the 2.0.0 engine as
|
|
16
|
+
registered (2.1.0 defaults gave the same verdicts):
|
|
17
|
+
|
|
18
|
+
| Part | ns-3 | HandoverLab | Limit | Result |
|
|
19
|
+
|---|---|---|---|---|
|
|
20
|
+
| Load: link-monitoring SINR, light to full traffic | -2.1 / -1.8 dB | -13.3 / -13.4 dB | within 2 dB | fails |
|
|
21
|
+
| Execution: command to completion | median 4.1 ms | `exec_s` 10 ms | within 10 ms | passes |
|
|
22
|
+
| Recovery: time without connection per failure | 0.09 s | 1.0 s (`reest_s`) | ratio 0.67-1.5 | fails |
|
|
23
|
+
| Execution failures | none in any cell | 0-5 % | needs 10 in ns-3 | not measurable |
|
|
24
|
+
|
|
25
|
+
The two failing parts explain much of the failure gap: HandoverLab's full-buffer load always fills
|
|
26
|
+
every cell, so interference is far higher than with ns-3's offered traffic (ns-3 has fewer failures
|
|
27
|
+
at full traffic, 90 to 34 and 13 to 3; HandoverLab many more, 18 to 521 and 4 to 175), and a
|
|
28
|
+
re-establishment takes a fixed second. A traffic-driven load and a recovery time from the standard
|
|
29
|
+
texts are the next steps; they need new ns-3 runs to be judged, as these runs have now been seen.
|
|
30
|
+
|
|
13
31
|
**Summary (1.5.0).** Handover and unnecessary-handover rates of HandoverLab agree with ns-3 /
|
|
14
32
|
5G-LENA. For failure rates, the order of settings and conditions agrees on part A and on both
|
|
15
33
|
hold-out sets when the in-car loss of ns-3 and the restart of link monitoring are switched on
|
|
@@ -20,7 +38,7 @@ and diagnosis runs:
|
|
|
20
38
|
|---|---|---|---|
|
|
21
39
|
| In-car penetration loss | added only at 30-120 km/h | TR 38.901 7.4.3.2: a property of a user in a car | per user when configured, any speed (`radio.penetration_db`) |
|
|
22
40
|
| Time to detect out-of-sync | 20 frames of 10 control receptions; 0.65-0.83 s at light traffic | TS 38.133 8.1: about 200 ms | evaluated over time (`protocol.qout_window_s` 0.2 s) |
|
|
23
|
-
| Link monitoring on a new cell | restarts | TS 38.331: T310 stops at a handover; out-of-sync
|
|
41
|
+
| Link monitoring on a new cell | restarts | TS 38.331: T310 stops at a handover; out-of-sync evaluated anew (an interpretation of TS 38.133 8.1.2.2: quality over the last T_Evaluate_out) | option since 1.3.0 (`protocol.rlm_holdoff_s`) |
|
|
24
42
|
|
|
25
43
|
On the first two, HandoverLab is closer to the 3GPP texts; on the third, ns-3 was, and HandoverLab
|
|
26
44
|
now offers it. The sections below give the evidence in the order it was found.
|
|
@@ -268,8 +286,9 @@ reference includes this loss.
|
|
|
268
286
|
The remaining failures were compared with those of ns-3, failure by failure (A3 6 dB / 100 ms at
|
|
269
287
|
200 m). At 42 m/s, every HandoverLab failure came about 0.2 s after a handover, at an
|
|
270
288
|
intersection: T310 had started on the newly joined cell at once, and the next handover command
|
|
271
|
-
arrived while it was running. In ns-3
|
|
272
|
-
|
|
289
|
+
arrived while it was running. In ns-3 radio-link monitoring restarts on a new cell and needs a full evaluation period (200 ms)
|
|
290
|
+
before an out-of-sync indication; HandoverLab reads TS 38.133 8.1.2.2 (quality estimated over the last
|
|
291
|
+
T_Evaluate_out) the same way, an interpretation, as no clause defines a restart. Overall,
|
|
273
292
|
half of HandoverLab's failures came less than 2 s after the previous handover, against a quarter to
|
|
274
293
|
a third in ns-3.
|
|
275
294
|
|
|
@@ -35,7 +35,8 @@ What happens in a run:
|
|
|
35
35
|
periodic L1-RSRP reports (`report_s`, `switch_db`, `tci_delay_s`). In FR2 the L1-RSRP period of
|
|
36
36
|
TS 38.133 includes the receive-beam sweeping factor N = 8, so the beam follows a fast user late.
|
|
37
37
|
3. If the serving beam's quality, averaged over the beam-failure-detection period (FR2: 800 ms at a
|
|
38
|
-
20 ms SSB period), is below
|
|
38
|
+
20 ms SSB period), is below Qout_LR (since 2.1.0 4 dB above Qout, as TS 38.133 Tables 8.5.2.1-1 and
|
|
39
|
+
8.1.2.1-1 define the two hypothetical PDCCH at 0 dB and +4 dB), the UE counts beam failure instances; `bfi_max` of them within
|
|
39
40
|
the detection timer start beam failure recovery by random access on the best candidate beam.
|
|
40
41
|
A recovery whose random access fails `preamble_max` times is a radio-link failure.
|
|
41
42
|
4. The new metrics `beam_switches_pm`, `beam_failures_pm`, `beam_recoveries_pm`,
|
|
@@ -81,7 +82,9 @@ rules:
|
|
|
81
82
|
```
|
|
82
83
|
|
|
83
84
|
- Each layer has its own sites (or `cosited: true`: the sites, LOS states and shadowing of the
|
|
84
|
-
first layer, TR 38.901 7.6.5
|
|
85
|
+
first layer, TR 38.901 7.6.5; since 2.1.0 such a layer cannot set its own `pathloss`, `los_corr_m` or
|
|
86
|
+
`shadow_decorr_m` unless `radio.channel_detail` is `simple`). Only cells of one carrier interfere with
|
|
87
|
+
each other.
|
|
85
88
|
- With `meas_periods: ts38133` the UE measures the other carrier only in the measurement gaps
|
|
86
89
|
(`gap_pattern`, default 6 ms every 40 ms) with the inter-frequency periods of TS 38.133 9.3.5:
|
|
87
90
|
320 ms for an FR1 carrier and 1.6 s for an FR2 carrier. During a gap it receives no data
|