rosotacom-dev 2.5.dev34__tar.gz → 2.5.dev36__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 (352) hide show
  1. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/PKG-INFO +29 -4
  2. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/README.md +28 -3
  3. rosotacom_dev-2.5.dev36/docs/link-bandwidth.md +73 -0
  4. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/rfcs/0003-metric-backbone.md +33 -3
  5. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/session-configuration.md +9 -0
  6. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/cli.py +20 -0
  7. rosotacom_dev-2.5.dev36/src/rosotacom/resources/ws/ota_configs/cyclonedds_local_participants.xml.template +37 -0
  8. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +47 -0
  9. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +20 -13
  10. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +275 -5
  11. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +31 -9
  12. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +17 -6
  13. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +44 -0
  14. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +7 -1
  15. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/transit.py +57 -17
  16. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom_dev.egg-info/PKG-INFO +29 -4
  17. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom_dev.egg-info/SOURCES.txt +4 -0
  18. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom_dev.egg-info/scm_file_list.json +4 -0
  19. rosotacom_dev-2.5.dev36/src/rosotacom_dev.egg-info/scm_version.json +8 -0
  20. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_packaged_resources.py +1 -0
  21. rosotacom_dev-2.5.dev36/tests/contract/test_session_template_substitution.py +75 -0
  22. rosotacom_dev-2.5.dev36/tests/unit/test_catmux_pane_logging.py +113 -0
  23. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_link_bytes.py +55 -0
  24. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_status_overview.py +323 -1
  25. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_status_overview_observer.py +5 -1
  26. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_transit.py +61 -0
  27. rosotacom_dev-2.5.dev34/src/rosotacom_dev.egg-info/scm_version.json +0 -8
  28. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.devcontainer/devcontainer.json.template +0 -0
  29. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.devcontainer/re_generate_devcontainer_json.py +0 -0
  30. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/CODEOWNERS +0 -0
  31. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
  32. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
  33. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
  34. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
  35. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
  36. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
  37. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
  38. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
  39. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  40. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/actions/setup-just/action.yml +0 -0
  41. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/dependabot.yml +0 -0
  42. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/workflows/benchmark-calibrate.yml +0 -0
  43. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/workflows/benchmark-gate.yml +0 -0
  44. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/workflows/dev-release.yml +0 -0
  45. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/workflows/image-scan.yml +0 -0
  46. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/workflows/nightly-e2e.yml +0 -0
  47. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/workflows/pr-lightweight.yml +0 -0
  48. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/workflows/pr-merge-gate.yml +0 -0
  49. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.github/workflows/release.yml +0 -0
  50. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/.pre-commit-config.yaml +0 -0
  51. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/AGENTS.md +0 -0
  52. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/CONCURRENCY.md +0 -0
  53. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/CONTRIBUTING.md +0 -0
  54. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/DEVELOPMENT_PRINCIPLES.md +0 -0
  55. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/LICENSE.txt +0 -0
  56. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/MANIFEST.in +0 -0
  57. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/budgets.jsonl +0 -0
  58. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/calibration/README.md +0 -0
  59. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/calibration/capacity-size-tight-cyclone.json +0 -0
  60. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
  61. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/calibration/probe-loss-nominal-cyclone.json +0 -0
  62. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/calibration/probe-loss-tight-cyclone.json +0 -0
  63. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/calibration/probe-loss-tight-fastdds.json +0 -0
  64. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/calibration/probe-loss-tight-zenoh.json +0 -0
  65. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/codecov.yml +0 -0
  66. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/deployment-configuration.md +0 -0
  67. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/benchmark-ab.md +0 -0
  68. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/benchmark-bag-as-load.md +0 -0
  69. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/ci.md +0 -0
  70. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/ffmpeg-keyframes.md +0 -0
  71. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/findings/README.md +0 -0
  72. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
  73. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/findings/delay-alone-no-loss.md +0 -0
  74. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/findings/head-of-line-irregularity.md +0 -0
  75. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
  76. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/findings/lighter-message-loss.md +0 -0
  77. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
  78. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/forensics-report.md +0 -0
  79. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/geo-link-map.md +0 -0
  80. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/github-repository-settings.md +0 -0
  81. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/link-trace.md +0 -0
  82. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/owner-runbook.md +0 -0
  83. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/performance-bands.md +0 -0
  84. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/playbooks/README.md +0 -0
  85. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/quality-model.md +0 -0
  86. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/release-notes/TEMPLATE.md +0 -0
  87. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/release-notes/v2.1.md +0 -0
  88. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/release-notes/v2.2.md +0 -0
  89. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/release-notes/v2.3.md +0 -0
  90. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/release-notes/v2.4.md +0 -0
  91. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/release.md +0 -0
  92. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
  93. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/rfcs/0002-expectation-concepts.md +0 -0
  94. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/rfcs/0004-network-profiles.md +0 -0
  95. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
  96. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/rfcs/0006-dynamic-qos.md +0 -0
  97. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/rfcs/0007-regression-gate.md +0 -0
  98. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/rfcs/README.md +0 -0
  99. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/testing.md +0 -0
  100. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/docs/work-items.md +0 -0
  101. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/install.sh +0 -0
  102. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/justfile +0 -0
  103. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/media/control_center.png +0 -0
  104. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/media/echo_test.png +0 -0
  105. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/media/forensics-report-example.png +0 -0
  106. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/media/host.png +0 -0
  107. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/media/vehicle.png +0 -0
  108. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/pyproject.toml +0 -0
  109. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/requirements.txt +0 -0
  110. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/rosotacom.yaml +0 -0
  111. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/run_session_in_container.py +0 -0
  112. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/setup.cfg +0 -0
  113. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/__init__.py +0 -0
  114. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/__main__.py +0 -0
  115. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/anonymize.py +0 -0
  116. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/bag_ground_truth.py +0 -0
  117. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/benched_set.py +0 -0
  118. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/benchmark.py +0 -0
  119. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/benchmark_delta.py +0 -0
  120. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/bundle_check.py +0 -0
  121. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/cli_benchmark.py +0 -0
  122. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/deployment.py +0 -0
  123. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/ffmpeg_packet.py +0 -0
  124. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/forensics.py +0 -0
  125. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/geomap.py +0 -0
  126. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/image_cache.py +0 -0
  127. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/network_profiles.py +0 -0
  128. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/network_shaper.py +0 -0
  129. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/plots.py +0 -0
  130. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/py.typed +0 -0
  131. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/benched-set.yaml +0 -0
  132. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/.gitignore +0 -0
  133. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/README.md +0 -0
  134. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/__init__.py +0 -0
  135. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
  136. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
  137. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/profiles.yaml +0 -0
  138. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/ros2docker.json +0 -0
  139. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
  140. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
  141. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
  142. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
  143. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
  144. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
  145. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
  146. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
  147. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
  148. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
  149. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
  150. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
  151. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
  152. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
  153. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
  154. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
  155. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
  156. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
  157. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
  158. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
  159. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
  160. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
  161. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
  162. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
  163. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
  164. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
  165. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
  166. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
  167. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
  168. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
  169. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
  170. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
  171. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
  172. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
  173. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
  174. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
  175. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
  176. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
  177. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
  178. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
  179. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
  180. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
  181. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
  182. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
  183. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
  184. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
  185. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
  186. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
  187. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
  188. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
  189. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
  190. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
  191. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
  192. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
  193. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
  194. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
  195. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
  196. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
  197. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
  198. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
  199. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
  200. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
  201. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
  202. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
  203. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
  204. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
  205. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
  206. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
  207. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
  208. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
  209. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ros2docker.json.example +0 -0
  210. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
  211. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
  212. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
  213. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
  214. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
  215. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
  216. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
  217. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
  218. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
  219. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
  220. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
  221. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
  222. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
  223. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
  224. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
  225. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
  226. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
  227. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
  228. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
  229. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
  230. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
  231. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
  232. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
  233. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
  234. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
  235. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
  236. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
  237. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
  238. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
  239. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
  240. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
  241. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
  242. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
  243. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
  244. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
  245. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
  246. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
  247. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
  248. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
  249. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
  250. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
  251. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
  252. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
  253. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
  254. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
  255. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
  256. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
  257. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
  258. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
  259. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
  260. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
  261. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
  262. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
  263. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
  264. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
  265. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
  266. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
  267. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
  268. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
  269. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
  270. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
  271. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
  272. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
  273. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
  274. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
  275. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
  276. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
  277. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
  278. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
  279. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
  280. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
  281. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
  282. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
  283. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
  284. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
  285. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
  286. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
  287. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
  288. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
  289. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
  290. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
  291. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/status_eval.py +0 -0
  292. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/stream_stats.py +0 -0
  293. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/trace_profiles.py +0 -0
  294. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom/video_quality.py +0 -0
  295. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
  296. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
  297. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom_dev.egg-info/requires.txt +0 -0
  298. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
  299. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/stop_session_in_container.py +0 -0
  300. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/terminology.md +0 -0
  301. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_benched_set_registry.py +0 -0
  302. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_findings.py +0 -0
  303. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_markdown_links.py +0 -0
  304. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_ota_source_bundle.py +0 -0
  305. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_package_metadata.py +0 -0
  306. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_profile_covers_generated_commands.py +0 -0
  307. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_pytest_policy.py +0 -0
  308. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_readme_examples.py +0 -0
  309. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_security_maintenance_config.py +0 -0
  310. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_session_configuration_doc.py +0 -0
  311. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/contract/test_workflow_contracts.py +0 -0
  312. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/conftest.py +0 -0
  313. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/test_anonymize_e2e.py +0 -0
  314. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/test_benchmark_ab.py +0 -0
  315. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/test_benchmark_capacity.py +0 -0
  316. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/test_benchmark_replay.py +0 -0
  317. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/test_parallel_smoke.py +0 -0
  318. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/test_smoke.py +0 -0
  319. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/test_timeline_stepping.py +0 -0
  320. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/e2e/test_video_quality_e2e.py +0 -0
  321. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/sessions/generate_rmw_matrix.py +0 -0
  322. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
  323. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
  324. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
  325. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
  326. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
  327. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_anonymize.py +0 -0
  328. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_bag_ground_truth.py +0 -0
  329. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_benched_set.py +0 -0
  330. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_benchmark.py +0 -0
  331. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_benchmark_delta.py +0 -0
  332. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_bundle_check.py +0 -0
  333. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_cli.py +0 -0
  334. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_cli_benchmark.py +0 -0
  335. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_concurrency.py +0 -0
  336. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_deployment.py +0 -0
  337. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_ffmpeg_packet.py +0 -0
  338. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_forensics.py +0 -0
  339. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_geomap.py +0 -0
  340. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_image_cache.py +0 -0
  341. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_link_trace.py +0 -0
  342. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_network_profiles.py +0 -0
  343. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_network_shaper.py +0 -0
  344. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_ota_wrapper.py +0 -0
  345. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_ota_xml.py +0 -0
  346. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_plots.py +0 -0
  347. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_session_pipeline.py +0 -0
  348. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_stage_latency.py +0 -0
  349. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_status_eval.py +0 -0
  350. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_stream_stats.py +0 -0
  351. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_trace_profiles.py +0 -0
  352. {rosotacom_dev-2.5.dev34 → rosotacom_dev-2.5.dev36}/tests/unit/test_video_quality.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rosotacom-dev
3
- Version: 2.5.dev34
3
+ Version: 2.5.dev36
4
4
  Summary: Host CLI for ROS OTA communication sessions.
5
5
  Author: develNor
6
6
  License-Expression: BSD-3-Clause
@@ -311,6 +311,25 @@ rosotacom start 1_heartbeat --identity b \
311
311
 
312
312
  `rosotacom` reads the static session input and creates generated files under `session-instances/<date>/<session>_<timestamp>_<id>/config/`, including per-peer plugin/session specs, topic lists, optional QoS, and optional `domain_bridge.yaml`. Catmux pane output is logged under the same instance in `logs/<peer>/catmux/`.
313
313
 
314
+ What else a run leaves under `logs/<peer>/`, and which file to open first when a
315
+ peer looked healthy but did nothing:
316
+
317
+ | File | Written by | Read it for |
318
+ |---|---|---|
319
+ | `catmux/<NN>-<WINDOW>/<pane>.log` | `catmux_log_setup.sh` (`tmux pipe-pane`) | everything a node printed, including the traceback it died with |
320
+ | `pane_failures.log` | the same script's prompt hook | one line per non-zero pane exit — **the file that answers "is any pane dead?"** |
321
+ | `status/startup_check.json` | `status_overview`, once, after `status_startup_grace_s` and one confirming look a grace later | the verdict: which outbound stages this peer produces and never published, plus the pane failures above |
322
+ | `status/status.{json,txt}` and `status/events.jsonl` | `status_overview`, continuously | live per-stage state and the transit records |
323
+ | `scenario/<component>.log` | `rosotacom start <scenario>` | each scenario application's own output |
324
+ | `launcher.log`, `docker.log` | `rosotacom start` | the exact command, and the container's own stdout where it has one |
325
+
326
+ A pane whose command exits drops back to a shell prompt and keeps looking alive
327
+ — `docker ps` shows a healthy container and the other panes keep working. That
328
+ is how a control centre ran for two hours on 2026-08-13 with no heartbeat
329
+ publisher, because Cyclone had no free participant index left on the local
330
+ domain and `heartbeat_echo` died two seconds after start. The last two rows of
331
+ that table exist so the next one announces itself.
332
+
314
333
  ### Complete use cases with scenarios
315
334
 
316
335
  A session intentionally describes only the communication contract. When a use
@@ -577,9 +596,15 @@ The running session writes, under
577
596
  - `status.json` — machine-readable snapshot (source of truth) for tools/agents,
578
597
  refreshed on a short interval and on every state transition,
579
598
  - `status.txt` — a human-rendered table, and
580
- - `events.jsonl` — state transitions plus per-`(topic, seq)` transit records for
581
- wrapped topics (delivered/lost/reordered, section latency, size, inter-arrival,
582
- and jitter).
599
+ - `events.jsonl` — state transitions plus per-`(topic, epoch, seq)` transit
600
+ records for wrapped topics (delivered/lost/reordered, section latency, size,
601
+ inter-arrival, and jitter). `epoch` counts the restarts of the sending peer's
602
+ wrapper: sequence numbers start at zero again after one, so it is what keeps
603
+ the numbering unique over an instance that outlived a restart.
604
+
605
+ Which of the bandwidth numbers a session publishes answers which question —
606
+ per-stream payload, whole-interface wire traffic, and the overhead ratio
607
+ between them — is in [link bandwidth](docs/link-bandwidth.md).
583
608
 
584
609
  For fixed-interval network-condition samples alongside the same session, enable
585
610
  the [link trace recorder](docs/link-trace.md). It writes
@@ -266,6 +266,25 @@ rosotacom start 1_heartbeat --identity b \
266
266
 
267
267
  `rosotacom` reads the static session input and creates generated files under `session-instances/<date>/<session>_<timestamp>_<id>/config/`, including per-peer plugin/session specs, topic lists, optional QoS, and optional `domain_bridge.yaml`. Catmux pane output is logged under the same instance in `logs/<peer>/catmux/`.
268
268
 
269
+ What else a run leaves under `logs/<peer>/`, and which file to open first when a
270
+ peer looked healthy but did nothing:
271
+
272
+ | File | Written by | Read it for |
273
+ |---|---|---|
274
+ | `catmux/<NN>-<WINDOW>/<pane>.log` | `catmux_log_setup.sh` (`tmux pipe-pane`) | everything a node printed, including the traceback it died with |
275
+ | `pane_failures.log` | the same script's prompt hook | one line per non-zero pane exit — **the file that answers "is any pane dead?"** |
276
+ | `status/startup_check.json` | `status_overview`, once, after `status_startup_grace_s` and one confirming look a grace later | the verdict: which outbound stages this peer produces and never published, plus the pane failures above |
277
+ | `status/status.{json,txt}` and `status/events.jsonl` | `status_overview`, continuously | live per-stage state and the transit records |
278
+ | `scenario/<component>.log` | `rosotacom start <scenario>` | each scenario application's own output |
279
+ | `launcher.log`, `docker.log` | `rosotacom start` | the exact command, and the container's own stdout where it has one |
280
+
281
+ A pane whose command exits drops back to a shell prompt and keeps looking alive
282
+ — `docker ps` shows a healthy container and the other panes keep working. That
283
+ is how a control centre ran for two hours on 2026-08-13 with no heartbeat
284
+ publisher, because Cyclone had no free participant index left on the local
285
+ domain and `heartbeat_echo` died two seconds after start. The last two rows of
286
+ that table exist so the next one announces itself.
287
+
269
288
  ### Complete use cases with scenarios
270
289
 
271
290
  A session intentionally describes only the communication contract. When a use
@@ -532,9 +551,15 @@ The running session writes, under
532
551
  - `status.json` — machine-readable snapshot (source of truth) for tools/agents,
533
552
  refreshed on a short interval and on every state transition,
534
553
  - `status.txt` — a human-rendered table, and
535
- - `events.jsonl` — state transitions plus per-`(topic, seq)` transit records for
536
- wrapped topics (delivered/lost/reordered, section latency, size, inter-arrival,
537
- and jitter).
554
+ - `events.jsonl` — state transitions plus per-`(topic, epoch, seq)` transit
555
+ records for wrapped topics (delivered/lost/reordered, section latency, size,
556
+ inter-arrival, and jitter). `epoch` counts the restarts of the sending peer's
557
+ wrapper: sequence numbers start at zero again after one, so it is what keeps
558
+ the numbering unique over an instance that outlived a restart.
559
+
560
+ Which of the bandwidth numbers a session publishes answers which question —
561
+ per-stream payload, whole-interface wire traffic, and the overhead ratio
562
+ between them — is in [link bandwidth](docs/link-bandwidth.md).
538
563
 
539
564
  For fixed-interval network-condition samples alongside the same session, enable
540
565
  the [link trace recorder](docs/link-trace.md). It writes
@@ -0,0 +1,73 @@
1
+ # Link bandwidth: what each number means
2
+
3
+ Three bandwidth numbers exist in a running session, and they answer three
4
+ different questions. Mixing them up is how a link that delivered ~6 Mbit/s was
5
+ reported at ~28 Gbit/s for a whole field run.
6
+
7
+ | Topic / field | Measured where | Counts | Scope |
8
+ |---|---|---|---|
9
+ | `/topic_monitor/<dir>/<name>[/to_<peer>]/ros_topic_bandwidth_kbps` | subscriber on the local domain | serialized ROS payload of every `/com/<dir>/<name>/…` stage topic | one peer, one direction, application payload only |
10
+ | `/topic_monitor/<dir>/<name>[/to_<peer>]/link_bandwidth_kbps` | `/proc/net/dev` counters of the OTA interface | every byte the kernel moved over that interface | the whole interface, all peers and all protocols on it |
11
+ | `status.json` → `link` | the same counters, plus the overview's own per-stage sizes and rates | both of the above, and their ratio | one peer, both directions |
12
+
13
+ `kbps` here is **Kibit/s** — bytes × 8 / 1024 / seconds. It has meant that
14
+ since the topic existed; the name is kept so old recordings keep their meaning.
15
+ The factor to Mbit/s is 1.024/1000, i.e. 6000 `kbps` ≈ 6.1 Mbit/s.
16
+
17
+ ## Which one answers "what does the camera cost the link"
18
+
19
+ Neither `link_bandwidth_kbps` alone. It is an *interface* number: it includes
20
+ DDS discovery, RTPS retransmits, ACKs, IP/UDP headers, and anything else
21
+ sharing the interface. That is what makes it useful — the overhead is exactly
22
+ what a payload sum cannot see — but it is not attributable to one stream.
23
+
24
+ The attributable number is the per-topic row in `topic_monitor`'s table (or the
25
+ per-stage `mean_size_bytes` × `hz` in `status.json`), and the honest way to
26
+ report the cost of a stream on the link is the pair: payload for the stream,
27
+ plus the session-level `overhead_ratio_out` / `overhead_ratio_in` from
28
+ `status.json`, which is `link / payload` at the OTA boundary. A ratio near 1
29
+ means the wire carries little beyond the payload; well above 1 means
30
+ retransmits, shadow connections, discovery chatter, or QoS that does not fit
31
+ the link. Small messages have a naturally higher ratio, because per-packet
32
+ headers are a larger share of them.
33
+
34
+ Per-remote-peer wire attribution is **not** available from these counters. On
35
+ the deployments this stack runs on, the OTA interface is a dedicated tunnel
36
+ carrying exactly one peer, so the interface number *is* the peer number. A
37
+ setup that multiplexes peers on one interface needs a per-peer filter (`iftop`
38
+ in the `NET` window, or packet accounting), and the `link` numbers should then
39
+ be read as an upper bound.
40
+
41
+ ## How the interface is found
42
+
43
+ From `ip_local` — the peer's own OTA address — by `find_interface_for_ip`,
44
+ inside the node. `topic_monitor` and `status_overview` share
45
+ `resolve_link_interface`, so they cannot disagree. An explicit `interface`
46
+ parameter overrides it for a setup an address cannot describe.
47
+
48
+ **A loopback interface is refused** when `ip_local` is not itself a loopback
49
+ address, because loopback carries this host's own intra-process ROS traffic.
50
+ `topic_monitor` fails to start; `status_overview` disables the `link` block and
51
+ warns. Both are better than the number that made this rule necessary.
52
+
53
+ ### What went wrong before (issue #267)
54
+
55
+ The interface used to be resolved in the session template:
56
+
57
+ ```yaml
58
+ - interface=$(ip -o addr | awk '/'${ip_local//./\\.}'\/[0-9]+/ {print $2; exit}')
59
+ ```
60
+
61
+ catmux substitutes `${name}` and nothing else — see
62
+ `tests/contract/test_session_template_substitution.py`. `${ip_local//./\\.}` is
63
+ not that form, so it reached the pane literally, bash expanded an unset shell
64
+ variable to the empty string, and the awk program became `/\/[0-9]+/` — "the
65
+ first address line with a prefix length", which is `lo` on every Linux host.
66
+
67
+ Both peers therefore reported loopback traffic as link bandwidth for the whole
68
+ 2026-08-13 field session. On the centre it read ~5–7 Mbit/s and looked
69
+ plausible. On the vehicle, which was also writing a 36 GB `-a` recording over
70
+ the same loopback, it read ~28 Gbit/s — near-constant, and identical in both
71
+ directions, which is the loopback signature (`rx_bytes` and `tx_bytes` are the
72
+ same bytes). `status_overview`, which already resolved the interface in the
73
+ node, reported `tun1` correctly in the same run.
@@ -46,7 +46,8 @@ It **feeds** the existing verdict layer (unlocks `expect.loss_pct`; sharpens
46
46
  Every metric on the wishlist is a projection of one recorded object per message:
47
47
 
48
48
  ```
49
- (topic, seq):
49
+ (topic, epoch, seq):
50
+ epoch (receiver-derived) — which run of the sender's wrapper this seq belongs to
50
51
  t_wrap (sender clock) — OtaStamped.header.stamp
51
52
  t_com_in (receiver clock) — arrival immediately after bridge_in
52
53
  status — delivered | lost | reordered [from seq gap]
@@ -55,6 +56,21 @@ Every metric on the wishlist is a projection of one recorded object per message:
55
56
  inter_arrival / jitter — receiver-local regularity
56
57
  ```
57
58
 
59
+ **Why `epoch` is part of the key.** `universal_ota_wrapper` counts per topic
60
+ from zero, so a peer that restarts inside an instance replays sequence numbers
61
+ the receiver has already seen. The receiver detects the restart from the
62
+ sequence stream itself (a backward jump larger than any reordering the
63
+ transport can produce — `is_sequence_epoch_reset`) and counts epochs from 0.
64
+ Without it, two things break at once and neither announces itself: live
65
+ accounting calls every arrival after the restart `reordered`, and the offline
66
+ join collapses the second run onto the first. On the 2026-08-13 field instance
67
+ that was 124,572 of 304,876 records misclassified and 123,253 dropped from the
68
+ joined output — 40% of the run, concentrated in the mission window.
69
+
70
+ Epochs are receiver-local numbering, not an identifier the peers agree on:
71
+ each side counts the restarts it observes on its own inbound stream. That is
72
+ enough for both consumers, because both key within one receiver's records.
73
+
58
74
  The envelope carries only what the cross-host **OTA hop** needs (`t_wrap` +
59
75
  `seq`). Local / per-stage latency — including the message's pre-OTA pipeline cost —
60
76
  is read uniformly from the `stage_latency` join (mechanism 3), **not** from an
@@ -210,6 +226,11 @@ in-order.
210
226
  restamp/latch/drop/throttle/pixel/frame transforms before compression and
211
227
  wrapping. Therefore `com_in` sequence gaps exclude intended pre-wrap shaping
212
228
  and measure failure after the wrap point.
229
+ - **A restart costs the epoch's head, not the run.** The receiver cannot know
230
+ how many messages the peer published before DDS discovery matched the reader,
231
+ so the messages before the first arrival of a new epoch are not counted as
232
+ lost. In the 2026-08-13 instance that head was 37 to 41 messages per restart.
233
+ Counting them would report a loss the link never caused.
213
234
  - **`θ` drifts.** Re-estimate continuously; fine for short runs, relevant for
214
235
  hour-long sessions.
215
236
  - **Head-of-line blocking is the real failure mode.** Field data: a heavy message
@@ -275,9 +296,18 @@ PR; the e2e row runs in the single-machine smoke matrix (`just test-e2e-smoke`);
275
296
  the cross-host rows are the operator OTA gate.
276
297
 
277
298
  - [x] **Sequence loss / reorder / burst / epoch reset** — host:
278
- `test_status_overview.py::test_sequence_loss_reorder_and_transit_records` and
279
- `::test_sequence_zero_starts_new_epoch_after_publisher_restart`. Live: the e2e
299
+ `test_status_overview.py::test_sequence_loss_reorder_and_transit_records`,
300
+ `::test_sequence_zero_starts_new_epoch_after_publisher_restart`,
301
+ `::test_restart_is_recognised_when_seq_zero_never_arrives` (the field shape:
302
+ the first arrival of a new epoch is seq 37, not 0),
303
+ `::test_a_small_backward_jump_is_still_reordering` and
304
+ `::test_transit_records_carry_the_epoch_they_were_counted_in`. Live: the e2e
280
305
  row asserts delivered transit records on a running pipeline.
306
+ - [x] **Epoch-keyed offline join** — host:
307
+ `test_transit.py::test_join_keeps_sequence_numbers_from_different_epochs_apart`,
308
+ `::test_records_without_an_epoch_are_one_epoch`,
309
+ `::test_lost_records_are_bounded_within_their_own_epoch` and
310
+ `::test_nominal_send_period_ignores_the_step_across_a_restart`.
281
311
  - [x] **`expect.loss_pct { max, stage? }` evaluation** — host:
282
312
  `test_status_eval.py::test_loss_pct_uses_first_sequence_aware_stage`,
283
313
  `::test_loss_pct_exceeded_fails`,
@@ -169,6 +169,15 @@ Per-side config blocks:
169
169
  - DDS implementations (`cyclone`, `fastdds`) accept:
170
170
  - `config: <template>` — template file under `ws/ota_configs/` (e.g. `fastdds_v1.xml`, `cyclonedds.xml`, `fastdds_easy_mode.xml`). Omit to use the RMW's built-in defaults.
171
171
  - `easy_mode_ip: <string>` — only honored by `fastdds_easy_mode.xml`; defaults to the first resolved peer address.
172
+
173
+ On the **local** side of a busy machine, set
174
+ `config: cyclonedds_local_participants.xml`. Cyclone allows 33 participants
175
+ per domain per host by default, and a control centre running its own
176
+ application next to the communication peer exceeds that: the processes that
177
+ start last fail with `Failed to find a free participant index for domain N`
178
+ and exit. That template raises the limit and changes nothing else — it pins no
179
+ interface and sets no peer list, because local discovery must keep working.
180
+ The OTA templates are not usable on the local side for exactly that reason.
172
181
  - `zenoh_connect_endpoints` (native, OTA side only; `zenoh` is still accepted as a legacy OTA alias) accepts:
173
182
  - `main_peer: <peer_key>` — the peer whose zenoh router listens. Defaults to the first peer declared under `peers:`.
174
183
  - `main_port: 7447` — listening port. Default `7447`.
@@ -1083,10 +1083,30 @@ def _mark_interactive_smoke_stopped(instance_dir: Path, target_type: str, target
1083
1083
 
1084
1084
 
1085
1085
  def _write_docker_log(container_name: str, instance: SessionInstance, identity: str) -> None:
1086
+ """Snapshot the peer container's own stdout into ``logs/<peer>/docker.log``.
1087
+
1088
+ In `attach` mode the container is `--rm` and already gone by the time this
1089
+ runs, so `docker logs` answers "No such container". That answer used to be
1090
+ written verbatim, which produced a 75-byte file that reads like the record
1091
+ of the run and says nothing -- it was the whole of `logs/<peer>/` besides
1092
+ `launcher.log` when a field session had to be diagnosed after the fact
1093
+ (#266). The catmux per-pane logs under `catmux/` are the actual record, so
1094
+ say that instead of pretending this file is one.
1095
+ """
1086
1096
  try:
1087
1097
  result = subprocess.run(["docker", "logs", container_name], text=True, capture_output=True, check=False)
1088
1098
  except Exception:
1089
1099
  return
1100
+ if result.returncode != 0:
1101
+ stderr = (result.stderr or "").strip()
1102
+ _append_log(
1103
+ _peer_docker_log(instance, identity),
1104
+ f"[rosotacom] docker logs {container_name}: {stderr or 'unavailable'}\n"
1105
+ "[rosotacom] The container is not (or no longer) present -- in attach mode it is\n"
1106
+ "[rosotacom] `--rm` and exits with the foreground command. What each pane inside\n"
1107
+ f"[rosotacom] it printed is under {_peer_docker_log(instance, identity).parent / 'catmux'}.",
1108
+ )
1109
+ return
1090
1110
  logs = (result.stdout or "") + (result.stderr or "")
1091
1111
  if logs:
1092
1112
  _append_log(_peer_docker_log(instance, identity), logs)
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ Local-domain CycloneDDS configuration: default discovery, more participants.
4
+
5
+ Set it as `shared.rmw.local.cyclone.config` (or a peer's `local_config_template`)
6
+ on a machine where many processes share the communication peer's local domain.
7
+
8
+ Why: Cyclone gives each process one participant index per domain, and its default
9
+ MaxAutoParticipantIndex is 32 - 33 slots per domain per host. A control centre
10
+ spends them faster than that sounds. The processes that start last then lose the
11
+ race, and the error names the domain rather than the cause:
12
+
13
+ [46] heartbeat_: Failed to find a free participant index for domain 46
14
+ [ERROR] [rmw_cyclonedds_cpp]: rmw_create_node: failed to create domain, error Error
15
+
16
+ On 2026-08-13 that killed the centre's `heartbeat_echo` and one `topic_monitor`
17
+ two seconds after start. catmux left both panes at a shell prompt, so the session
18
+ ran for two hours with no heartbeat publisher: no RTT, no clock-offset estimate,
19
+ and every EchoHeartbeat the far side received carried `echo_valid=false`.
20
+
21
+ 119, not higher: Cyclone's unicast discovery ports are
22
+ 7400 + 250*domain + 10 + 2*index, so 119 is the last index whose ports stay
23
+ inside this domain's 250-port block. Index 120 would answer on the next
24
+ domain's ports.
25
+
26
+ Nothing else is set. This is the *local* domain -- intra-host discovery must keep
27
+ working, so unlike the OTA templates it pins no interface, disables no multicast,
28
+ and sets no peer list.
29
+ -->
30
+ <CycloneDDS xmlns="https://cdds.io/config">
31
+ <Domain Id="any">
32
+ <Discovery>
33
+ <ParticipantIndex>auto</ParticipantIndex>
34
+ <MaxAutoParticipantIndex>119</MaxAutoParticipantIndex>
35
+ </Discovery>
36
+ </Domain>
37
+ </CycloneDDS>
@@ -78,6 +78,19 @@ def parse_ip_addr_for_ip(text: str, ip: str) -> Optional[str]:
78
78
  return None
79
79
 
80
80
 
81
+ #: Interface names that carry intra-host traffic only. Sampling one of these and
82
+ #: calling the result "link bandwidth" is the failure of issue #267: the number
83
+ #: is real, it is just not the link. On a machine that also runs a `-a` recorder
84
+ #: it reads ~28 Gbit/s next to a 6 Mbit/s OTA link.
85
+ LOOPBACK_INTERFACES = frozenset({"lo", "lo0"})
86
+
87
+
88
+ def is_loopback_address(ip: str) -> bool:
89
+ """Is ``ip`` a loopback address (so a loopback interface would be correct)?"""
90
+ ip = (ip or "").strip()
91
+ return ip.startswith("127.") or ip in {"::1", "0:0:0:0:0:0:0:1"}
92
+
93
+
81
94
  def find_interface_for_ip(ip: str) -> Optional[str]:
82
95
  """The interface owning ``ip``, via `ip -o addr show` (None if not found)."""
83
96
  if not ip:
@@ -91,6 +104,40 @@ def find_interface_for_ip(ip: str) -> Optional[str]:
91
104
  return parse_ip_addr_for_ip(out, ip)
92
105
 
93
106
 
107
+ def resolve_link_interface(
108
+ explicit: str,
109
+ host_ip: str,
110
+ finder=find_interface_for_ip,
111
+ ) -> Tuple[str, str]:
112
+ """The OTA link interface and where it came from, or raise.
113
+
114
+ ``explicit`` wins when given; otherwise the interface is the one owning
115
+ ``host_ip`` (the peer's own OTA address). A loopback interface for a
116
+ non-loopback address is refused rather than reported: loopback carries this
117
+ host's own ROS traffic, which on a machine running an ``-a`` recorder is
118
+ three orders of magnitude above the link and looks like a working
119
+ measurement. That mistake is issue #267; it survived a field session and an
120
+ offline analysis before anyone doubted the number.
121
+ """
122
+ interface = (explicit or "").strip()
123
+ provenance = "given explicitly"
124
+ if not interface:
125
+ interface = (finder(host_ip) or "").strip()
126
+ provenance = f"resolved from {host_ip}"
127
+ if not interface:
128
+ raise ValueError(
129
+ f"no interface owns the OTA address '{host_ip}'; "
130
+ "pass ip_local (preferred) or interface"
131
+ )
132
+ if interface in LOOPBACK_INTERFACES and not is_loopback_address(host_ip):
133
+ raise ValueError(
134
+ f"refusing to report loopback interface '{interface}' as the link for OTA "
135
+ f"address '{host_ip}' ({provenance}). Loopback carries this host's own ROS "
136
+ "traffic, not the link."
137
+ )
138
+ return interface, provenance
139
+
140
+
94
141
  def read_iface_counters(iface: str, proc_path: str = PROC_NET_DEV) -> Optional[Tuple[int, int]]:
95
142
  """Return (rx_bytes, tx_bytes) for ``iface`` now, or None if unavailable."""
96
143
  row = read_iface_counter_row(iface, proc_path)
@@ -67,9 +67,10 @@ from rclpy.qos import DurabilityPolicy, HistoryPolicy, QoSProfile, ReliabilityPo
67
67
  from rclpy.serialization import serialize_message
68
68
  from rosidl_runtime_py.utilities import get_message
69
69
 
70
- from com_py.link_bytes import LinkByteSampler, find_interface_for_ip
70
+ from com_py.link_bytes import LinkByteSampler, resolve_link_interface
71
71
  from com_py.link_trace import LinkTraceRecorder
72
72
  from com_py.status_overview_core import (
73
+ STARTUP_GRACE_S,
73
74
  ClockOffsetEstimator,
74
75
  StageObservation,
75
76
  StatusAggregator,
@@ -334,6 +335,8 @@ class StatusOverview(Node):
334
335
  self.declare_parameter("link_trace_interval_s", 1.0)
335
336
  self.declare_parameter("link_trace_modem_command", "")
336
337
  self.declare_parameter("link_trace_modem_timeout_s", 2.0)
338
+ # Grace before the one-shot startup verdict (#266). 0 disables it.
339
+ self.declare_parameter("startup_grace_s", STARTUP_GRACE_S)
337
340
 
338
341
  spec_file = str(self.get_parameter("status_spec_file").value or "").strip()
339
342
  output_dir = str(self.get_parameter("output_dir").value or "").strip()
@@ -410,20 +413,23 @@ class StatusOverview(Node):
410
413
 
411
414
  ota_interface = str(self.get_parameter("ota_interface").value or "").strip()
412
415
  ota_local_ip = str(self.get_parameter("ota_local_ip").value or "").strip()
413
- if not ota_interface and ota_local_ip:
414
- ota_interface = find_interface_for_ip(ota_local_ip) or ""
415
- if not ota_interface:
416
+ link_sampler = None
417
+ if ota_interface or ota_local_ip:
418
+ # Same resolution and the same loopback refusal as topic_monitor: a
419
+ # link number nobody can tell apart from loopback traffic is worse
420
+ # than no link number, so this reports nothing rather than that.
421
+ try:
422
+ ota_interface, provenance = resolve_link_interface(ota_interface, ota_local_ip)
423
+ except ValueError as exc:
424
+ self.get_logger().warning(
425
+ f"status_overview: {exc}; link-overhead measurement disabled"
426
+ )
427
+ else:
428
+ link_sampler = LinkByteSampler(ota_interface)
416
429
  self.get_logger().info(
417
- f"status_overview: no interface found for OTA address '{ota_local_ip}'; "
418
- "link-overhead measurement disabled"
430
+ f"status_overview: link-overhead sampling on interface "
431
+ f"'{ota_interface}' ({provenance})"
419
432
  )
420
- link_sampler = None
421
- if ota_interface:
422
- link_sampler = LinkByteSampler(ota_interface)
423
- self.get_logger().info(
424
- f"status_overview: link-overhead sampling on interface '{ota_interface}'"
425
- + (f" (resolved from {ota_local_ip})" if ota_local_ip else "")
426
- )
427
433
 
428
434
  link_trace_recorder = None
429
435
  if bool(self.get_parameter("link_trace").value):
@@ -450,6 +456,7 @@ class StatusOverview(Node):
450
456
  link_sampler=link_sampler,
451
457
  clock_estimator=clock_estimator,
452
458
  link_trace_recorder=link_trace_recorder,
459
+ startup_grace_s=float(self.get_parameter("startup_grace_s").value),
453
460
  )
454
461
 
455
462
  self.create_timer(self.write_interval_s, self._on_write)