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.
Files changed (258) hide show
  1. handoverlab-2.2.0/.zenodo.json +34 -0
  2. {handoverlab-2.0.0 → handoverlab-2.2.0}/CHANGELOG.md +148 -1
  3. {handoverlab-2.0.0 → handoverlab-2.2.0}/CITATION.cff +3 -3
  4. {handoverlab-2.0.0 → handoverlab-2.2.0}/PKG-INFO +56 -23
  5. {handoverlab-2.0.0 → handoverlab-2.2.0}/README.md +54 -21
  6. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/calibration-3gpp.md +12 -2
  7. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/calibration.md +22 -3
  8. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/beams-layers.md +5 -2
  9. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/daps-ltm.md +8 -4
  10. handoverlab-2.2.0/docs/guides/fading.md +78 -0
  11. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/highway.md +20 -9
  12. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/indoor-rural.md +10 -6
  13. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/mro.md +4 -4
  14. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/ntn.md +20 -8
  15. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/radio-maps.md +7 -4
  16. handoverlab-2.2.0/docs/guides/scheduler.md +65 -0
  17. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/index.md +6 -5
  18. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/migration-2.0.md +6 -4
  19. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/cli.md +7 -3
  20. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/metrics.md +24 -13
  21. handoverlab-2.2.0/docs/reference-study.md +58 -0
  22. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/dense-urban-2layer.md +14 -17
  23. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/fr3-urban-15ghz.md +14 -10
  24. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/highway-tr37885-30ghz.md +28 -24
  25. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/highway-tr37885-4ghz.md +24 -17
  26. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/indoor-office-4ghz.md +18 -19
  27. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/ns3-urban-3.5ghz.md +10 -8
  28. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/ntn-leo600-2ghz.md +19 -33
  29. handoverlab-2.2.0/docs/scenarios/ntn-leo600-2ghz.svg +21 -0
  30. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/open-area-10ghz.md +11 -10
  31. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/rural-700mhz.md +17 -18
  32. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/smoke.md +14 -10
  33. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/urban-grid-10ghz.md +14 -10
  34. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/urban-grid-28ghz-beams.md +16 -12
  35. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/stability.md +3 -1
  36. handoverlab-2.2.0/docs/standard-compliance.md +362 -0
  37. handoverlab-2.2.0/docs/time-step.md +55 -0
  38. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/tutorials/reading-the-report.md +7 -3
  39. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/user_guide.md +48 -27
  40. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/verification.md +13 -2
  41. handoverlab-2.2.0/examples/study_reference.yaml +53 -0
  42. handoverlab-2.2.0/examples/study_reference_explore.yaml +55 -0
  43. {handoverlab-2.0.0 → handoverlab-2.2.0}/mkdocs.yml +5 -1
  44. {handoverlab-2.0.0 → handoverlab-2.2.0}/pyproject.toml +2 -2
  45. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/__init__.py +1 -1
  46. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/extended.py +39 -5
  47. handoverlab-2.2.0/src/handoverlab/channel/fading.py +157 -0
  48. handoverlab-2.2.0/src/handoverlab/channel/l2s.py +51 -0
  49. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/ntn.py +58 -9
  50. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/pathloss.py +106 -18
  51. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/radiomap.py +131 -19
  52. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/source.py +50 -11
  53. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/cli.py +5 -2
  54. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/config.py +157 -20
  55. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/_kernels.py +21 -9
  56. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/batch.py +35 -20
  57. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/core.py +220 -48
  58. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/extended.py +74 -28
  59. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/invariants.py +2 -0
  60. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/metrics.py +16 -9
  61. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/procedures.py +115 -21
  62. handoverlab-2.2.0/src/handoverlab/engine/scheduler.py +210 -0
  63. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/eventlog.py +1 -1
  64. handoverlab-2.2.0/src/handoverlab/linklevel.py +145 -0
  65. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/measurement.py +5 -2
  66. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/mobility.py +10 -0
  67. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/requirements.py +8 -3
  68. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/base.py +6 -1
  69. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/builtin.py +31 -14
  70. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/mro.py +14 -6
  71. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/__init__.py +74 -12
  72. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/dense-urban-2layer.yaml +5 -2
  73. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/fr3-urban-15ghz.yaml +6 -1
  74. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/highway-tr37885-30ghz.yaml +6 -6
  75. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/highway-tr37885-4ghz.yaml +5 -5
  76. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/indoor-office-4ghz.yaml +12 -9
  77. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/ns3-urban-3.5ghz.yaml +1 -0
  78. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/ntn-leo600-2ghz.yaml +13 -8
  79. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/open-area-10ghz.yaml +2 -0
  80. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/rural-700mhz.yaml +9 -6
  81. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/smoke.yaml +6 -1
  82. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/urban-grid-10ghz.yaml +7 -1
  83. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/scenarios/cards/urban-grid-28ghz-beams.yaml +6 -0
  84. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/seeds.py +3 -1
  85. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/stability.py +35 -1
  86. handoverlab-2.2.0/src/handoverlab/standard.py +231 -0
  87. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/stats.py +3 -1
  88. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/report.py +2 -1
  89. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/runner.py +1 -1
  90. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/study.py +15 -3
  91. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/tuning.py +23 -4
  92. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/traffic.py +2 -1
  93. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/__init__.py +12 -3
  94. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/calibration.py +28 -9
  95. handoverlab-2.2.0/src/handoverlab/verify/data/golden.json +466 -0
  96. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/engine_checks.py +4 -3
  97. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/extended.py +3 -1
  98. handoverlab-2.2.0/src/handoverlab/verify/fading.py +61 -0
  99. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/golden.py +4 -2
  100. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/highway.py +25 -13
  101. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/ns3.py +16 -12
  102. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/ntn.py +22 -11
  103. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/radio.py +9 -4
  104. handoverlab-2.2.0/src/handoverlab/verify/values.py +38 -0
  105. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/PKG-INFO +56 -23
  106. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/SOURCES.txt +18 -0
  107. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/public_api.json +21 -1
  108. handoverlab-2.2.0/tests/test_channel_detail.py +270 -0
  109. handoverlab-2.2.0/tests/test_fading.py +127 -0
  110. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_mro.py +2 -2
  111. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_ntn.py +21 -3
  112. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_pathloss.py +1 -1
  113. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_protocol_3gpp.py +12 -4
  114. handoverlab-2.2.0/tests/test_readme_boundaries.py +33 -0
  115. handoverlab-2.2.0/tests/test_rrc_detail.py +167 -0
  116. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_rules_rc2.py +6 -1
  117. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_scenarios.py +2 -1
  118. handoverlab-2.2.0/tests/test_scheduler.py +136 -0
  119. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_signalling_energy.py +13 -3
  120. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_verify.py +32 -1
  121. handoverlab-2.0.0/.zenodo.json +0 -26
  122. handoverlab-2.0.0/docs/scenarios/ntn-leo600-2ghz.svg +0 -21
  123. handoverlab-2.0.0/docs/standard-compliance.md +0 -303
  124. handoverlab-2.0.0/src/handoverlab/verify/data/golden.json +0 -466
  125. {handoverlab-2.0.0 → handoverlab-2.2.0}/CODE_OF_CONDUCT.md +0 -0
  126. {handoverlab-2.0.0 → handoverlab-2.2.0}/CONTRIBUTING.md +0 -0
  127. {handoverlab-2.0.0 → handoverlab-2.2.0}/LICENSE +0 -0
  128. {handoverlab-2.0.0 → handoverlab-2.2.0}/MANIFEST.in +0 -0
  129. {handoverlab-2.0.0 → handoverlab-2.2.0}/SECURITY.md +0 -0
  130. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/RELEASING.md +0 -0
  131. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/add-scenario.md +0 -0
  132. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/dashboard.md +0 -0
  133. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/export-event-logs.md +0 -0
  134. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/learning-rule.md +0 -0
  135. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/many-cores.md +0 -0
  136. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/reproduce.md +0 -0
  137. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/guides/upper-mid-band.md +0 -0
  138. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/calibration_38901.png +0 -0
  139. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/dashboard-charts.png +0 -0
  140. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/dashboard-compare.png +0 -0
  141. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/dashboard-where.png +0 -0
  142. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/dashboard.png +0 -0
  143. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/ntn-beams.png +0 -0
  144. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/radio-map.png +0 -0
  145. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/report-comparison.png +0 -0
  146. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/report-tuning.png +0 -0
  147. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/images/ssb-beams.png +0 -0
  148. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/performance.md +0 -0
  149. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/config.md +0 -0
  150. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/engine.md +0 -0
  151. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/eventlog.md +0 -0
  152. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/gui.md +0 -0
  153. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/index.md +0 -0
  154. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/mapfile.md +0 -0
  155. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/ntn.md +0 -0
  156. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/rules.md +0 -0
  157. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/scenarios.md +0 -0
  158. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/simulate.md +0 -0
  159. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/stability.md +0 -0
  160. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/stats.md +0 -0
  161. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/studies.md +0 -0
  162. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/testing.md +0 -0
  163. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/reference/api/verify.md +0 -0
  164. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/dense-urban-2layer.svg +0 -0
  165. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/fr3-urban-15ghz.svg +0 -0
  166. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/highway-tr37885-30ghz.svg +0 -0
  167. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/highway-tr37885-4ghz.svg +0 -0
  168. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/indoor-office-4ghz.svg +0 -0
  169. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/ns3-urban-3.5ghz.svg +0 -0
  170. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/open-area-10ghz.svg +0 -0
  171. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/rural-700mhz.svg +0 -0
  172. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/smoke.svg +0 -0
  173. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/urban-grid-10ghz.svg +0 -0
  174. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/scenarios/urban-grid-28ghz-beams.svg +0 -0
  175. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/tutorials/first-run.md +0 -0
  176. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/tutorials/own-rule.md +0 -0
  177. {handoverlab-2.0.0 → handoverlab-2.2.0}/docs/tutorials/tuning-study.md +0 -0
  178. {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/compare_a3_cho.py +0 -0
  179. {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/open_area.toml +0 -0
  180. {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/radio_map.py +0 -0
  181. {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/smoke.yaml +0 -0
  182. {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/speed_rule.py +0 -0
  183. {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/street_grid.yaml +0 -0
  184. {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/study_smoke.yaml +0 -0
  185. {handoverlab-2.0.0 → handoverlab-2.2.0}/examples/traffic_models.py +0 -0
  186. {handoverlab-2.0.0 → handoverlab-2.2.0}/setup.cfg +0 -0
  187. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/__main__.py +0 -0
  188. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/__init__.py +0 -0
  189. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/channel/antenna.py +0 -0
  190. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/engine/__init__.py +0 -0
  191. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/gui/__init__.py +0 -0
  192. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/gui/app.py +0 -0
  193. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/gui/logic.py +0 -0
  194. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/io.py +0 -0
  195. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/layout.py +0 -0
  196. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/mapfile.py +0 -0
  197. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/py.typed +0 -0
  198. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/__init__.py +0 -0
  199. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/rules/dqn.py +0 -0
  200. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/simulate.py +0 -0
  201. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/__init__.py +0 -0
  202. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/config.py +0 -0
  203. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/status.py +0 -0
  204. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/studies/store.py +0 -0
  205. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/testing.py +0 -0
  206. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/data/golden_1x.json +0 -0
  207. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/data/ns3_urban_a3.json +0 -0
  208. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/data/r1_165974.csv +0 -0
  209. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/learning.py +0 -0
  210. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/report.py +0 -0
  211. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/verify/stored.py +0 -0
  212. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab/world.py +0 -0
  213. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/dependency_links.txt +0 -0
  214. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/entry_points.txt +0 -0
  215. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/requires.txt +0 -0
  216. {handoverlab-2.0.0 → handoverlab-2.2.0}/src/handoverlab.egg-info/top_level.txt +0 -0
  217. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/conftest.py +0 -0
  218. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/bh6_reference.json +0 -0
  219. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/bh6_wide.json +0 -0
  220. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/make_bh6_reference.py +0 -0
  221. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/data/make_bh6_wide.py +0 -0
  222. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/helpers.py +0 -0
  223. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_batch.py +0 -0
  224. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_beams_layers.py +0 -0
  225. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_calibration.py +0 -0
  226. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_cltm.py +0 -0
  227. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_config_cli.py +0 -0
  228. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_contract.py +0 -0
  229. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_determinism.py +0 -0
  230. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_dqn.py +0 -0
  231. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_engine_triggers.py +0 -0
  232. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_eventlog.py +0 -0
  233. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_gui.py +0 -0
  234. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_highway.py +0 -0
  235. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_highway_tr37885.py +0 -0
  236. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_indoor_rural.py +0 -0
  237. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_invariants.py +0 -0
  238. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_levels_status_extend.py +0 -0
  239. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_lm_model.py +0 -0
  240. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_mapfile.py +0 -0
  241. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_measurement.py +0 -0
  242. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_regression_bh6.py +0 -0
  243. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_regression_bh6_wide.py +0 -0
  244. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_stability.py +0 -0
  245. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_stats.py +0 -0
  246. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_study.py +0 -0
  247. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_tools.py +0 -0
  248. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_traffic.py +0 -0
  249. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_tuning.py +0 -0
  250. {handoverlab-2.0.0 → handoverlab-2.2.0}/tests/test_v111.py +0 -0
  251. {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/compare_fingerprints.py +0 -0
  252. {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_beam_figure.py +0 -0
  253. {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_calibration_figure.py +0 -0
  254. {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_ntn_figure.py +0 -0
  255. {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_radiomap_figure.py +0 -0
  256. {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/make_readme_images.py +0 -0
  257. {handoverlab-2.0.0 → handoverlab-2.2.0}/tools/mkdocs_hooks.py +0 -0
  258. {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.0.0...HEAD
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 simulation of handover and mobility beyond 5G"
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.0.0"
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-20
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.0.0
4
- Summary: System-level simulator of handover and mobility procedures in dense 5G and beyond-5G networks
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
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23409131.svg)](https://doi.org/10.5281/zenodo.23409131) [![PyPI](https://img.shields.io/pypi/v/handoverlab.svg)](https://pypi.org/project/handoverlab/)
62
62
 
63
- A system-level simulator for studying handover in dense 5G and beyond-5G networks, written in Python.
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 36.814. The load of every cell, and so the
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 (TR 36.839 / TR 36.842 values by default), the handover command
173
- during T310 and the restart of the link monitoring on a new cell as TS 38.331 and TS 38.133 specify
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
- ## Built for beyond-5G
184
-
185
- HandoverLab targets the questions of dense beyond-5G networks: small cells 50-300 m apart, the
186
- upper mid-band (FR3, 7-24 GHz; the scenario `fr3-urban-15ghz`, 10 GHz by default), and the
187
- mobility procedures beyond baseline handover: conditional handover, DAPS handover,
188
- L1/L2-triggered mobility of Release 18 and conditional LTM from the Release 19 work, satellite access
189
- with the conditional handover events of Release 18 (non-terrestrial networks, since 2.0.0), next to rules
190
- that learn from handover outcomes and
191
- A3 tuned by mobility robustness optimisation, the fair baseline for a new rule. The cost
192
- of each procedure (signalling, prepared cells, interruption, energy) is measured next to its
193
- benefit.
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 behave as TS 38.331 specifies. Against handover statistics
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 ratio 0.92, rank
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
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23409131.svg)](https://doi.org/10.5281/zenodo.23409131) [![PyPI](https://img.shields.io/pypi/v/handoverlab.svg)](https://pypi.org/project/handoverlab/)
4
4
 
5
- A system-level simulator for studying handover in dense 5G and beyond-5G networks, written in Python.
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 36.814. The load of every cell, and so the
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 (TR 36.839 / TR 36.842 values by default), the handover command
115
- during T310 and the restart of the link monitoring on a new cell as TS 38.331 and TS 38.133 specify
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
- ## Built for beyond-5G
126
-
127
- HandoverLab targets the questions of dense beyond-5G networks: small cells 50-300 m apart, the
128
- upper mid-band (FR3, 7-24 GHz; the scenario `fr3-urban-15ghz`, 10 GHz by default), and the
129
- mobility procedures beyond baseline handover: conditional handover, DAPS handover,
130
- L1/L2-triggered mobility of Release 18 and conditional LTM from the Release 19 work, satellite access
131
- with the conditional handover events of Release 18 (non-terrestrial networks, since 2.0.0), next to rules
132
- that learn from handover outcomes and
133
- A3 tuned by mobility robustness optimisation, the fair baseline for a new rule. The cost
134
- of each procedure (signalling, prepared cells, interruption, energy) is measured next to its
135
- benefit.
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 behave as TS 38.331 specifies. Against handover statistics
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 ratio 0.92, rank
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
  ![HandoverLab against the 21 companies of 3GPP R1-165974](images/calibration_38901.png)
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 Table 6-1 |
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, Table 7.4.3-2 |
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 is evaluated anew (TS 38.133 8.1) | option since 1.3.0 (`protocol.rlm_holdoff_s`) |
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, as in TS 38.133 clause 8.1, radio-link monitoring restarts
272
- on a new cell and needs a full evaluation period (200 ms) before an out-of-sync indication. Overall,
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 Qout, the UE counts beam failure instances; `bfi_max` of them within
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). Only cells of one carrier interfere with each other.
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