rosotacom-dev 2.5.dev62__tar.gz → 2.5.dev65__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 (388) hide show
  1. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/PKG-INFO +2 -2
  2. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/README.md +1 -1
  3. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/README.md +1 -0
  4. rosotacom_dev-2.5.dev65/docs/findings/cyclone-fragment-equal-to-max-drops-fragmented-samples.md +89 -0
  5. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/fastdds-datagram-cap-drops-large-samples.md +1 -1
  6. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/forensics-report.md +1 -1
  7. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/link-trace.md +10 -0
  8. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/cli.py +59 -0
  9. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +12 -1
  10. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +33 -3
  11. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom_dev.egg-info/PKG-INFO +2 -2
  12. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom_dev.egg-info/SOURCES.txt +1 -0
  13. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom_dev.egg-info/scm_file_list.json +1 -0
  14. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom_dev.egg-info/scm_version.json +2 -2
  15. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_cli.py +78 -0
  16. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_link_trace.py +72 -0
  17. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_ota_link_configs.py +12 -2
  18. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.devcontainer/devcontainer.json.template +0 -0
  19. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.devcontainer/re_generate_devcontainer_json.py +0 -0
  20. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/CODEOWNERS +0 -0
  21. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
  22. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
  23. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
  24. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
  25. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
  26. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
  27. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
  28. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
  29. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  30. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/actions/setup-just/action.yml +0 -0
  31. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/dependabot.yml +0 -0
  32. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/workflows/benchmark-calibrate.yml +0 -0
  33. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/workflows/benchmark-gate.yml +0 -0
  34. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/workflows/dev-release.yml +0 -0
  35. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/workflows/image-scan.yml +0 -0
  36. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/workflows/nightly-e2e.yml +0 -0
  37. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/workflows/pr-lightweight.yml +0 -0
  38. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/workflows/pr-merge-gate.yml +0 -0
  39. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.github/workflows/release.yml +0 -0
  40. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/.pre-commit-config.yaml +0 -0
  41. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/AGENTS.md +0 -0
  42. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/CONCURRENCY.md +0 -0
  43. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/CONTRIBUTING.md +0 -0
  44. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/DEVELOPMENT_PRINCIPLES.md +0 -0
  45. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/LICENSE.txt +0 -0
  46. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/MANIFEST.in +0 -0
  47. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/budgets.jsonl +0 -0
  48. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/calibration/README.md +0 -0
  49. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/calibration/capacity-size-tight-cyclone.json +0 -0
  50. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
  51. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/calibration/probe-loss-nominal-cyclone.json +0 -0
  52. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/calibration/probe-loss-tight-cyclone.json +0 -0
  53. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/calibration/probe-loss-tight-fastdds.json +0 -0
  54. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/calibration/probe-loss-tight-zenoh.json +0 -0
  55. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/codecov.yml +0 -0
  56. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/deployment-configuration.md +0 -0
  57. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/benchmark-ab.md +0 -0
  58. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/benchmark-bag-as-load.md +0 -0
  59. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/ci.md +0 -0
  60. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/ffmpeg-keyframes.md +0 -0
  61. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/a-transport-element-doubles-every-fastdds-sample.md +0 -0
  62. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
  63. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/delay-alone-no-loss.md +0 -0
  64. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/graph-derived-types-block-a-non-graph-transport.md +0 -0
  65. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/head-of-line-irregularity.md +0 -0
  66. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
  67. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/keyframe-loss-kills-the-next-deltas.md +0 -0
  68. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/lifespan-is-enforced-by-one-reader-and-not-the-other.md +0 -0
  69. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/lighter-message-loss.md +0 -0
  70. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/oversubscription-queues-not-losses.md +0 -0
  71. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/reorder-becomes-reader-loss.md +0 -0
  72. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/repro/decode_chain_repro.py +0 -0
  73. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/repro/reorder_drop_repro.py +0 -0
  74. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/sender-rows-make-a-dead-link-look-loss-free.md +0 -0
  75. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
  76. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/geo-link-map.md +0 -0
  77. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/github-repository-settings.md +0 -0
  78. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/link-bandwidth.md +0 -0
  79. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/owner-runbook.md +0 -0
  80. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/performance-bands.md +0 -0
  81. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/playbooks/README.md +0 -0
  82. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/quality-model.md +0 -0
  83. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/release-notes/TEMPLATE.md +0 -0
  84. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/release-notes/v2.1.md +0 -0
  85. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/release-notes/v2.2.md +0 -0
  86. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/release-notes/v2.3.md +0 -0
  87. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/release-notes/v2.4.md +0 -0
  88. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/release.md +0 -0
  89. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
  90. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/rfcs/0002-expectation-concepts.md +0 -0
  91. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/rfcs/0003-metric-backbone.md +0 -0
  92. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/rfcs/0004-network-profiles.md +0 -0
  93. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
  94. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/rfcs/0006-dynamic-qos.md +0 -0
  95. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/rfcs/0007-regression-gate.md +0 -0
  96. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/rfcs/README.md +0 -0
  97. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/testing.md +0 -0
  98. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/docs/work-items.md +0 -0
  99. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/install.sh +0 -0
  100. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/justfile +0 -0
  101. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/media/control_center.png +0 -0
  102. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/media/echo_test.png +0 -0
  103. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/media/forensics-report-example.png +0 -0
  104. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/media/host.png +0 -0
  105. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/media/vehicle.png +0 -0
  106. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/pyproject.toml +0 -0
  107. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/requirements.txt +0 -0
  108. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/rosotacom.yaml +0 -0
  109. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/session-configuration.md +0 -0
  110. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/setup.cfg +0 -0
  111. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/__init__.py +0 -0
  112. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/__main__.py +0 -0
  113. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/anonymize.py +0 -0
  114. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/bag_ground_truth.py +0 -0
  115. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/benched_set.py +0 -0
  116. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/benchmark.py +0 -0
  117. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/benchmark_delta.py +0 -0
  118. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/bundle_check.py +0 -0
  119. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/cli_benchmark.py +0 -0
  120. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/deployment.py +0 -0
  121. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/ffmpeg_packet.py +0 -0
  122. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/forensics.py +0 -0
  123. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/geomap.py +0 -0
  124. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/image_cache.py +0 -0
  125. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/netem_dist.py +0 -0
  126. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/network_preflight.py +0 -0
  127. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/network_profiles.py +0 -0
  128. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/network_shaper.py +0 -0
  129. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/plots.py +0 -0
  130. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/py.typed +0 -0
  131. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/benched-set.yaml +0 -0
  132. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/.gitignore +0 -0
  133. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/README.md +0 -0
  134. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/__init__.py +0 -0
  135. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
  136. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
  137. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/dist/field-20260817.dist +0 -0
  138. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/profiles.yaml +0 -0
  139. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/ros2docker.json +0 -0
  140. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/ros2docker.lyrical.json +0 -0
  141. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
  142. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
  143. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
  144. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
  145. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.lyrical.ros2docker.json +0 -0
  146. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
  147. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
  148. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
  149. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
  150. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.lyrical.ros2docker.json +0 -0
  151. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
  152. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
  153. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
  154. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
  155. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
  156. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
  157. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
  158. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
  159. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
  160. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
  161. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
  162. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
  163. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
  164. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
  165. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
  166. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
  167. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
  168. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
  169. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
  170. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
  171. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
  172. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
  173. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
  174. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
  175. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
  176. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
  177. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
  178. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
  179. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
  180. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
  181. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
  182. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
  183. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
  184. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
  185. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
  186. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
  187. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
  188. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
  189. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
  190. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
  191. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
  192. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
  193. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
  194. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
  195. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
  196. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
  197. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
  198. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
  199. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
  200. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
  201. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
  202. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
  203. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
  204. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
  205. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
  206. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
  207. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
  208. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
  209. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
  210. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
  211. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
  212. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
  213. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ros2docker.json.example +0 -0
  214. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ros2docker.lyrical.json.example +0 -0
  215. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
  216. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
  217. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
  218. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
  219. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
  220. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
  221. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
  222. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
  223. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
  224. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/cyclonedds_local_participants.xml.template +0 -0
  225. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
  226. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/fastdds_easy_mode.xml.template +0 -0
  227. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/fastdds_local.xml.template +0 -0
  228. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/fastdds_tuned.xml.template +0 -0
  229. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
  230. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
  231. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
  232. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
  233. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
  234. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
  235. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
  236. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
  237. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
  238. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
  239. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
  240. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
  241. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
  242. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
  243. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
  244. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
  245. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
  246. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
  247. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
  248. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
  249. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
  250. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
  251. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
  252. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
  253. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/ffmpeg_flags.py +0 -0
  254. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
  255. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
  256. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
  257. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
  258. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
  259. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
  260. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
  261. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
  262. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
  263. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
  264. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
  265. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
  266. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
  267. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
  268. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
  269. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
  270. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
  271. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/playout_pacer.py +0 -0
  272. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/playout_pacer_core.py +0 -0
  273. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
  274. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
  275. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
  276. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
  277. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
  278. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
  279. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
  280. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
  281. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
  282. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
  283. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
  284. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
  285. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
  286. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
  287. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
  288. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
  289. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
  290. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
  291. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
  292. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
  293. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
  294. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
  295. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
  296. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
  297. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
  298. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +0 -0
  299. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
  300. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
  301. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
  302. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
  303. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
  304. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +0 -0
  305. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
  306. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
  307. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
  308. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/status_eval.py +0 -0
  309. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/stream_stats.py +0 -0
  310. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/trace_profiles.py +0 -0
  311. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/transit.py +0 -0
  312. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom/video_quality.py +0 -0
  313. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
  314. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
  315. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom_dev.egg-info/requires.txt +0 -0
  316. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
  317. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/terminology.md +0 -0
  318. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_benched_set_registry.py +0 -0
  319. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_findings.py +0 -0
  320. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_generated_topics_have_a_producer.py +0 -0
  321. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_lyrical_runtime_compat.py +0 -0
  322. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_markdown_links.py +0 -0
  323. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_ota_source_bundle.py +0 -0
  324. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_package_metadata.py +0 -0
  325. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_packaged_resources.py +0 -0
  326. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_profile_covers_generated_commands.py +0 -0
  327. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_pytest_policy.py +0 -0
  328. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_readme_examples.py +0 -0
  329. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_security_maintenance_config.py +0 -0
  330. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_session_configuration_doc.py +0 -0
  331. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_session_template_substitution.py +0 -0
  332. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/contract/test_workflow_contracts.py +0 -0
  333. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/conftest.py +0 -0
  334. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/test_anonymize_e2e.py +0 -0
  335. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/test_benchmark_ab.py +0 -0
  336. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/test_benchmark_capacity.py +0 -0
  337. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/test_benchmark_replay.py +0 -0
  338. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/test_parallel_smoke.py +0 -0
  339. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/test_smoke.py +0 -0
  340. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/test_timeline_stepping.py +0 -0
  341. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/e2e/test_video_quality_e2e.py +0 -0
  342. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/sessions/generate_rmw_matrix.py +0 -0
  343. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
  344. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
  345. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
  346. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
  347. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/sessions/rmw_matrix/1_heartbeat_fastdds-default/session-definition.yaml +0 -0
  348. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
  349. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_anonymize.py +0 -0
  350. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_bag_ground_truth.py +0 -0
  351. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_benched_set.py +0 -0
  352. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_benchmark.py +0 -0
  353. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_benchmark_delta.py +0 -0
  354. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_bundle_check.py +0 -0
  355. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_catmux_pane_logging.py +0 -0
  356. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_cli_benchmark.py +0 -0
  357. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_concurrency.py +0 -0
  358. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_container_shaping.py +0 -0
  359. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_deployment.py +0 -0
  360. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_ffmpeg_flags.py +0 -0
  361. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_ffmpeg_packet.py +0 -0
  362. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_field_profiles.py +0 -0
  363. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_forensics.py +0 -0
  364. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_geomap.py +0 -0
  365. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_image_cache.py +0 -0
  366. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_link_bytes.py +0 -0
  367. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_netem_dist.py +0 -0
  368. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_network_preflight.py +0 -0
  369. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_network_profiles.py +0 -0
  370. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_network_shaper.py +0 -0
  371. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_ota_unwrapper.py +0 -0
  372. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_ota_wrapper.py +0 -0
  373. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_ota_xml.py +0 -0
  374. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_playout_pacer.py +0 -0
  375. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_plots.py +0 -0
  376. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_pub_sub_pair_types.py +0 -0
  377. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_qos_fallback_logging.py +0 -0
  378. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_relay_optional_parameters.py +0 -0
  379. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_ros_node_entity_ownership.py +0 -0
  380. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_session_pipeline.py +0 -0
  381. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_stage_latency.py +0 -0
  382. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_status_eval.py +0 -0
  383. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_status_overview.py +0 -0
  384. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_status_overview_observer.py +0 -0
  385. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_stream_stats.py +0 -0
  386. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_trace_profiles.py +0 -0
  387. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/tests/unit/test_transit.py +0 -0
  388. {rosotacom_dev-2.5.dev62 → rosotacom_dev-2.5.dev65}/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.dev62
3
+ Version: 2.5.dev65
4
4
  Summary: Host CLI for ROS OTA communication sessions.
5
5
  Author: develNor
6
6
  License-Expression: BSD-3-Clause
@@ -367,7 +367,7 @@ Peer reachability is opt-in because some valid networks block ICMP and peers may
367
367
  be started in either order. `rosotacom start` accepts the same
368
368
  `--require-peer-reachable` policy when a deployment does require it.
369
369
 
370
- `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/`.
370
+ `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`. The instance's `manifest.yaml` records what produced it: `rosotacom_version`, the effective config SHA, and `source_revision` — the commit, branch and tracked-dirtiness of the session source directory at creation time, so a recording stays attributable to a revision after the checkout has moved on (`null` when the source is not a git repository). Catmux pane output is logged under the same instance in `logs/<peer>/catmux/`.
371
371
 
372
372
  What else a run leaves under `logs/<peer>/`, and which file to open first when a
373
373
  peer looked healthy but did nothing:
@@ -322,7 +322,7 @@ Peer reachability is opt-in because some valid networks block ICMP and peers may
322
322
  be started in either order. `rosotacom start` accepts the same
323
323
  `--require-peer-reachable` policy when a deployment does require it.
324
324
 
325
- `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/`.
325
+ `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`. The instance's `manifest.yaml` records what produced it: `rosotacom_version`, the effective config SHA, and `source_revision` — the commit, branch and tracked-dirtiness of the session source directory at creation time, so a recording stays attributable to a revision after the checkout has moved on (`null` when the source is not a git repository). Catmux pane output is logged under the same instance in `logs/<peer>/catmux/`.
326
326
 
327
327
  What else a run leaves under `logs/<peer>/`, and which file to open first when a
328
328
  peer looked healthy but did nothing:
@@ -31,6 +31,7 @@ living verification hook.
31
31
  - [Sender-side transit rows made a dead link report zero loss](sender-rows-make-a-dead-link-look-loss-free.md) - `delivered = rows - lost` counted the sender's own `sent` rows as deliveries, so a topic the receiver never saw summarised as `delivered == expected` at 0.0% loss, with the publisher's timer reported as arrival spacing.
32
32
  - [A bridge that learns types from the graph cannot use a transport that does not carry the graph](graph-derived-types-block-a-non-graph-transport.md) - over `zenoh_ros2dds` the payload topic never arrived in either run: the bridge routes a topic once a local reader exists and the reader waited for the bridge, leaving only `Pending=1` in a log.
33
33
  - [A Fast DDS datagram cap stops every message larger than it](fastdds-datagram-cap-drops-large-samples.md) - copying CycloneDDS's 1200 B fragment size into the Fast DDS OTA profile makes every sample above the cap never arrive, at 1200 B and at 8192 B, sync and async — while the 84 B heartbeat keeps flowing at 10 Hz.
34
+ - [A fragment sized exactly like the datagram cap stops every fragmented sample](cyclone-fragment-equal-to-max-drops-fragmented-samples.md) - CycloneDDS 11.0.1 delivers nothing above one fragment when `FragmentSize` equals `MaxMessageSize`, where 0.10.5 delivers everything on the identical profile; a 40 B string still crosses, and discovery, endpoint announcement and proxy-writer matching all succeed while no sample arrives.
34
35
  - [A lost keyframe silences exactly the next gop_size−2 deltas](keyframe-loss-kills-the-next-deltas.md) - libavcodec emits nothing for them, the last delta decodes with artifacts, the next keyframe restores clean decode; a lost delta never blocks decode — so the display hole is gop_size × frame period, deterministically.
35
36
  - [Any transport element in a Fast DDS profile doubles every sample on the wire](a-transport-element-doubles-every-fastdds-sample.md) - 366 datagrams for 180 samples against 183 without it; `<builtinTransports>DEFAULT` is a no-op selection and doubles too, so the trigger is the element's presence — removing it takes the shipped OTA profile from 2.10x the payload to 1.04x at identical delivery.
36
37
  - [Lifespan is enforced by one DDS reader and not the other](lifespan-is-enforced-by-one-reader-and-not-the-other.md) - under the same 20% oversubscription both stacks queue alike (472 and 433 delivered at ~1.1-1.2 s); with `lifespan: 0.7` CycloneDDS is unchanged and delivers 9.1% inside the bound, while Fast DDS drops to 4 delivered and never exceeds 570 ms — the policy decides shown-vs-suppressed, not how long the wait is.
@@ -0,0 +1,89 @@
1
+ # A Fragment Sized Exactly Like the Datagram Cap Stops Every Fragmented Sample
2
+
3
+ ## Claim
4
+
5
+ Setting CycloneDDS's `FragmentSize` **equal to** `MaxMessageSize` makes every
6
+ sample large enough to fragment **never arrive** on CycloneDDS 11.0.1, while the
7
+ identical profile carries them on 0.10.5. Samples small enough to fit in one
8
+ fragment keep flowing on the same link, which is what makes it dangerous: the
9
+ endpoints match, neither side logs anything, and the reader simply never sees a
10
+ sample.
11
+
12
+ An RTPS message carries headers as well as the fragment, so a fragment of
13
+ exactly `MaxMessageSize` cannot be put into a message of `MaxMessageSize`.
14
+ 0.10.5 evidently coped with that arithmetic; 11.0.1 does not, and drops
15
+ silently.
16
+
17
+ This is the CycloneDDS sibling of
18
+ [the Fast DDS datagram cap](fastdds-datagram-cap-drops-large-samples.md), found
19
+ from the opposite direction: there the cap was a value copied *from* this
20
+ profile, here the profile's own two values were equal to each other.
21
+
22
+ ## Setup
23
+
24
+ - Host pair / topology: two hosts joined by a point-to-point VPN (`/24`,
25
+ 1.3 ms RTT, 0.0% loss measured with three probes each way), one container per
26
+ host from the packaged communication image, `--network host --ipc host`, one
27
+ ROS domain. Not the local smoke rig: on a single host nothing fragments far
28
+ enough to show it.
29
+ - Session: none. A bare `ros2 topic pub -r 1` of a 64 kB
30
+ `std_msgs/msg/String` against a subscriber given the type explicitly — with
31
+ `EnableTopicDiscoveryEndpoints false` a bare `ros2 topic echo <topic>`
32
+ resolves no type and reports nothing, in both versions, which is a trap worth
33
+ naming because it looks exactly like the failure under test.
34
+ - rosotacom SHA: measured on the packaged 2.5.dev61 images; re-runs record
35
+ theirs.
36
+ - Profile: none — no impairment. The failure needs none, which is what makes it
37
+ attributable to the configuration rather than to the link.
38
+ - Seed policy: deterministic (no netem, no random load), `n=1` per variant; the
39
+ effect is present/absent, not a distribution.
40
+ - Stacks: `ros-kilted-cyclonedds` 0.10.5-2noble against
41
+ `ros-lyrical-cyclonedds` 11.0.1-4resolute.
42
+
43
+ ## Evidence
44
+
45
+ | profile | 0.10.5 | 11.0.1 |
46
+ |---|---|---|
47
+ | `FragmentSize` 1200 B, `MaxMessageSize` 1200 B | arrives | **nothing** |
48
+ | no size limits at all | — | arrives |
49
+ | `FragmentSize` 1024 B, `MaxMessageSize` 1200 B | — | arrives |
50
+
51
+ - A 40 B string crosses on 11.0.1 with the 1200/1200 profile, so the trigger is
52
+ fragmentation and not the link.
53
+ - The discovery trace of a failing run rules out everything above the data path:
54
+ both participants discover each other across the hosts, both sides announce
55
+ their endpoints, the reading side builds proxy writers for the remote
56
+ participants, and neither side logs a QoS incompatibility or a rejection.
57
+
58
+ Verification: automated:
59
+ `pytest tests/unit/test_ota_link_configs.py::test_only_cyclone_caps_the_datagram_and_fast_dds_must_not`
60
+ asserts the fragment stays strictly below the datagram cap, which is the
61
+ invariant the two numbers exist for. Manual, for the effect itself: one
62
+ container per host from the communication image on one ROS domain, the shipped
63
+ OTA profile with only the three size elements varied, a 64 kB string at 1 Hz,
64
+ and `ros2 topic echo <topic> std_msgs/msg/String --once` on the other side.
65
+
66
+ ## Status
67
+
68
+ confirmed, 2026-08-20.
69
+
70
+ Fixed by making `FragmentSize` strictly smaller than `MaxMessageSize` (1024 B
71
+ against 1200 B) in `cyclonedds_tuned.xml.template`. The datagram stays inside
72
+ the same MTU budget the 1200 B was chosen for — only the header room is added —
73
+ and the value works on both versions, so it is one number rather than a branch
74
+ on the distribution.
75
+
76
+ ## Publication notes
77
+
78
+ A distribution bump silently changed what a profile *means*, and the profile
79
+ text did not move. That is the reportable part: measurements taken under one ROS
80
+ distribution cannot be presented as the other's on the strength of an identical
81
+ configuration file, because identical configuration is not identical behaviour
82
+ across a DDS major version. State the middleware version beside the profile
83
+ wherever OTA numbers are reported.
84
+
85
+ The second consequence is about what counts as evidence that a link works. A
86
+ heartbeat crossing at 10 Hz with 0.0% loss certified nothing here — the small
87
+ samples were exactly the ones that could not fail. A link check that does not
88
+ include a sample past the fragment threshold does not test the transport the
89
+ payload uses.
@@ -10,7 +10,7 @@ this dangerous: an 84 B heartbeat crossing at 10 Hz with 0.0% loss is a link
10
10
  that looks alive from every direction except the one that matters.
11
11
 
12
12
  The obvious reason to set it is symmetry with CycloneDDS, whose OTA profile
13
- carries this link at `FragmentSize`/`MaxMessageSize` 1200 B and works. The
13
+ carries this link at a 1024 B fragment inside a 1200 B datagram and works. The
14
14
  symmetry does not transfer: on ROS 2 Kilted with Fast DDS 3.2.4 the cap is the
15
15
  single knob that breaks the link, at 1200 B and at 8192 B, with a synchronous
16
16
  writer and with an asynchronous one.
@@ -37,7 +37,7 @@ gracefully when absent:
37
37
  |---|---|
38
38
  | `status.json` | declared topic types (FFMPEGPacket detection) |
39
39
  | `link_trace.jsonl` ([link trace recorder](link-trace.md)) | link state around each incident |
40
- | `manifest.yaml` | instance id + config SHA provenance |
40
+ | `manifest.yaml` | instance id, config SHA, and `source_revision` — the commit of the session source at instance creation |
41
41
  | `--profile NAME --profiles-file FILE` | RFC 0004 environment context (static params or timeline steps) |
42
42
  | `state_transition` rows in `events.jsonl` | pipeline diagnoses around each incident |
43
43
 
@@ -30,6 +30,16 @@ rosotacom ota-smoke 13_link_latency --link-trace
30
30
  `--link-trace-interval` and `--link-trace-modem-command` also enable the
31
31
  recorder and force `shared.use_status_overview: true` for the generated instance.
32
32
 
33
+ `interval_s` is the period between rows, and the status-overview node is ticked
34
+ at the same period when the trace is enabled. Those two being equal is what
35
+ makes the trace continuous: each row's `passive_counter_delta` covers one tick,
36
+ so consecutive rows meet rather than leaving traffic between them. The recorder
37
+ therefore schedules against an advancing deadline with a small tolerance instead
38
+ of a stopwatch since the last row — without that, a tick landing a hair early is
39
+ rejected and waits a whole further period, which halves the trace and leaves
40
+ every second interval described by no row at all (measured on a 5 h drive:
41
+ 1.984 s between rows carrying 1.002 s windows).
42
+
33
43
  ## Row Schema
34
44
 
35
45
  Each line is one JSON object:
@@ -882,6 +882,61 @@ def _append_log(path: Path, text: str) -> None:
882
882
  fp.write("\n")
883
883
 
884
884
 
885
+ #: A provenance read must never be what makes an instance fail to start.
886
+ _SOURCE_REVISION_TIMEOUT_S = 5.0
887
+
888
+
889
+ def _source_revision(path: Path | str) -> dict[str, Any] | None:
890
+ """The VCS revision of the directory this session was taken from.
891
+
892
+ `rosotacom_version` pins the tool. This pins its *input*: the session source
893
+ is normally a checkout of a deployment repository, and that checkout moves.
894
+ A consumer reading the manifest later cannot recover the revision by looking
895
+ at the machine, because looking at the machine answers a different question —
896
+ on one two-machine drive the vehicle had been synced by the time the
897
+ recording was consolidated the next morning, so the only commit anybody
898
+ could still read was not the commit that ran. The manifest is written once
899
+ at creation and never rewritten, which is exactly what such a fact needs.
900
+
901
+ `dirty` deliberately ignores untracked files: deployment checkouts routinely
902
+ carry recordings, logs and scratch files that are not the code, so counting
903
+ them would make every real deployment permanently dirty and the flag
904
+ meaningless. What it reports is tracked content differing from the commit.
905
+
906
+ Best effort throughout — not a directory, no git, not a repository, a git
907
+ that hangs: all yield None.
908
+ """
909
+ directory = Path(path)
910
+ if not directory.is_dir():
911
+ return None
912
+
913
+ def git(*args: str) -> str | None:
914
+ try:
915
+ result = subprocess.run(
916
+ ["git", "-C", str(directory), *args],
917
+ capture_output=True,
918
+ text=True,
919
+ check=False,
920
+ timeout=_SOURCE_REVISION_TIMEOUT_S,
921
+ )
922
+ except (OSError, subprocess.SubprocessError):
923
+ return None
924
+ return result.stdout.strip() if result.returncode == 0 else None
925
+
926
+ commit = git("rev-parse", "HEAD")
927
+ if not commit:
928
+ return None
929
+ branch = git("rev-parse", "--abbrev-ref", "HEAD")
930
+ tracked_changes = git("status", "--porcelain", "--untracked-files=no")
931
+ return {
932
+ "vcs": "git",
933
+ "commit": commit,
934
+ "branch": None if branch in (None, "HEAD") else branch,
935
+ "dirty": None if tracked_changes is None else bool(tracked_changes),
936
+ "root": git("rev-parse", "--show-toplevel"),
937
+ }
938
+
939
+
885
940
  def _effective_config_sha256(cfg: dict[str, Any]) -> str:
886
941
  text = yaml.safe_dump(cfg, sort_keys=True, default_flow_style=False, allow_unicode=True)
887
942
  return hashlib.sha256(text.encode("utf-8")).hexdigest()
@@ -908,6 +963,7 @@ def _write_instance_manifest(
908
963
  "instance_id": instance.instance_id,
909
964
  "rosotacom_version": __version__,
910
965
  "source_session_host_dir": str(session.host_dir),
966
+ "source_revision": _source_revision(session.host_dir),
911
967
  "source_session_container_dir": session.container_dir,
912
968
  "source": session.source,
913
969
  "config_dir": str(instance.config_host_dir),
@@ -962,6 +1018,7 @@ def _write_scenario_manifest(
962
1018
  "instance_id": instance.instance_id,
963
1019
  "rosotacom_version": __version__,
964
1020
  "source_session_host_dir": str(session.host_dir),
1021
+ "source_revision": _source_revision(session.host_dir),
965
1022
  "source_session_container_dir": session.container_dir,
966
1023
  "source": session.source,
967
1024
  "config_dir": str(instance.config_host_dir),
@@ -1028,6 +1085,7 @@ def _write_interactive_smoke_manifest(
1028
1085
  "instance_id": instance.instance_id,
1029
1086
  "rosotacom_version": __version__,
1030
1087
  "source_session_host_dir": str(target.session.host_dir),
1088
+ "source_revision": _source_revision(target.session.host_dir),
1031
1089
  "source_session_container_dir": target.session.container_dir,
1032
1090
  "source": target.session.source,
1033
1091
  "config_dir": str(instance.config_host_dir),
@@ -2445,6 +2503,7 @@ def _ota_write_manifest(
2445
2503
  "instance_id": instance.instance_id,
2446
2504
  "rosotacom_version": __version__,
2447
2505
  "source_session_host_dir": str(target.session.host_dir),
2506
+ "source_revision": _source_revision(target.session.host_dir),
2448
2507
  "source_session_container_dir": target.session.container_dir,
2449
2508
  "source": target.session.source,
2450
2509
  "config_dir": str(instance.config_host_dir),
@@ -6,7 +6,18 @@
6
6
  <NetworkInterface address="#host_ip"/>
7
7
  </Interfaces>
8
8
  <MulticastRecvNetworkInterfaceAddresses>none</MulticastRecvNetworkInterfaceAddresses>
9
- <FragmentSize>1200B</FragmentSize>
9
+ <!-- Strictly below MaxMessageSize, and that is the whole point: an RTPS
10
+ message carries headers as well as the fragment, so a fragment of
11
+ exactly MaxMessageSize cannot be sent at all. Both were 1200B, which
12
+ CycloneDDS 0.10.5 coped with and 11.0.1 does not — under Lyrical no
13
+ fragmented sample crossed, silently: the endpoints matched and the
14
+ reader never saw a sample, while a sample small enough not to
15
+ fragment arrived normally. Measured between two hosts with a 64 kB
16
+ sample: 1200/1200 delivers nothing on 11.0.1 and everything on
17
+ 0.10.5; 1024/1200 delivers on both. The datagram stays inside the
18
+ same MTU budget the 1200B was chosen for; only the header room is
19
+ added. -->
20
+ <FragmentSize>1024B</FragmentSize>
10
21
  <MaxMessageSize>1200B</MaxMessageSize>
11
22
  <MaxRexmitMessageSize>1200B</MaxRexmitMessageSize>
12
23
  </General>
@@ -152,6 +152,12 @@ def build_link_trace_sample(
152
152
  class LinkTraceRecorder:
153
153
  """Write link trace rows as append-only JSONL."""
154
154
 
155
+ #: How early a tick may be and still count as on time. The caller ticks at
156
+ #: the same nominal period, so its jitter is the whole question; a tenth of
157
+ #: the interval absorbs that without ever letting rows run at half the
158
+ #: configured period.
159
+ _TOLERANCE_FRACTION = 0.1
160
+
155
161
  def __init__(
156
162
  self,
157
163
  path: str,
@@ -166,13 +172,37 @@ class LinkTraceRecorder:
166
172
  self.modem_metrics_command = modem_metrics_command
167
173
  self.modem_metrics_timeout_s = modem_metrics_timeout_s
168
174
  self._clock = clock
169
- self._last_write: Optional[float] = None
175
+ self._due_at: Optional[float] = None
170
176
 
171
177
  def maybe_write(self, snapshot: Dict[str, Any], link_sample: Optional[Dict[str, Any]]) -> bool:
178
+ """Write one row if this tick is the one the schedule was waiting for.
179
+
180
+ The schedule is a *deadline that advances*, not a stopwatch since the
181
+ last row, and the tolerance is not cosmetic. The caller is deliberately
182
+ ticking at the same period as this one — `generate_session_files` sets
183
+ `status_write_interval_s` to the trace interval — so a plain
184
+ "never faster than interval_s" gate rejects every tick that lands a hair
185
+ early and, with no catch-up, makes it wait a whole further period.
186
+
187
+ That halves the trace, and it does not merely halve its resolution: the
188
+ passive counter delta in a row covers the caller's own tick, so with
189
+ rows twice as far apart every second of traffic is described by no row
190
+ at all. Measured on the 2026-08-19 drive before this fix: rows 1.984 s
191
+ apart carrying 1.002 s windows.
192
+ """
172
193
  now = self._clock()
173
- if self._last_write is not None and now - self._last_write < self.interval_s:
194
+ if self._due_at is None:
195
+ self._due_at = now
196
+ if now < self._due_at - self._TOLERANCE_FRACTION * self.interval_s:
174
197
  return False
175
- self._last_write = now
198
+ # Advance the deadline rather than restarting it from now, so the rows
199
+ # stay on one cadence instead of drifting by the jitter of every tick.
200
+ # After a stall long enough that the next deadline is already behind us,
201
+ # start a fresh interval from the present rather than bursting through
202
+ # the deadlines that were missed: the rows describe the link now, and a
203
+ # burst of them would describe nothing.
204
+ next_due = self._due_at + self.interval_s
205
+ self._due_at = next_due if next_due > now else now + self.interval_s
176
206
  modem = run_modem_metrics_hook(
177
207
  self.modem_metrics_command,
178
208
  timeout_s=self.modem_metrics_timeout_s,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rosotacom-dev
3
- Version: 2.5.dev62
3
+ Version: 2.5.dev65
4
4
  Summary: Host CLI for ROS OTA communication sessions.
5
5
  Author: develNor
6
6
  License-Expression: BSD-3-Clause
@@ -367,7 +367,7 @@ Peer reachability is opt-in because some valid networks block ICMP and peers may
367
367
  be started in either order. `rosotacom start` accepts the same
368
368
  `--require-peer-reachable` policy when a deployment does require it.
369
369
 
370
- `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/`.
370
+ `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`. The instance's `manifest.yaml` records what produced it: `rosotacom_version`, the effective config SHA, and `source_revision` — the commit, branch and tracked-dirtiness of the session source directory at creation time, so a recording stays attributable to a revision after the checkout has moved on (`null` when the source is not a git repository). Catmux pane output is logged under the same instance in `logs/<peer>/catmux/`.
371
371
 
372
372
  What else a run leaves under `logs/<peer>/`, and which file to open first when a
373
373
  peer looked healthy but did nothing:
@@ -62,6 +62,7 @@ docs/testing.md
62
62
  docs/work-items.md
63
63
  docs/findings/README.md
64
64
  docs/findings/a-transport-element-doubles-every-fastdds-sample.md
65
+ docs/findings/cyclone-fragment-equal-to-max-drops-fragmented-samples.md
65
66
  docs/findings/cyclone-spdp-discovery-bursts.md
66
67
  docs/findings/delay-alone-no-loss.md
67
68
  docs/findings/fastdds-datagram-cap-drops-large-samples.md
@@ -47,6 +47,7 @@
47
47
  "docs/ffmpeg-keyframes.md",
48
48
  "docs/findings/README.md",
49
49
  "docs/findings/a-transport-element-doubles-every-fastdds-sample.md",
50
+ "docs/findings/cyclone-fragment-equal-to-max-drops-fragmented-samples.md",
50
51
  "docs/findings/cyclone-spdp-discovery-bursts.md",
51
52
  "docs/findings/delay-alone-no-loss.md",
52
53
  "docs/findings/fastdds-datagram-cap-drops-large-samples.md",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "tag": "2.4",
3
- "distance": 62,
4
- "node": "gfec674ece7749d5ecb7bf4b65d12faa17e8f965e",
3
+ "distance": 65,
4
+ "node": "g10a4e383f32456a7740c259e780111c21ea071de",
5
5
  "dirty": false,
6
6
  "branch": "HEAD",
7
7
  "node_date": "2026-08-20"
@@ -3721,3 +3721,81 @@ def test_ota_cleanup_refuses_to_act_on_a_guessed_plan(capsys: pytest.CaptureFixt
3721
3721
 
3722
3722
  assert calls == []
3723
3723
  assert "no deployment state" in capsys.readouterr().out
3724
+
3725
+
3726
+ def _git_repo(path: Path) -> None:
3727
+ path.mkdir(parents=True, exist_ok=True)
3728
+ env = {
3729
+ **os.environ,
3730
+ "GIT_AUTHOR_NAME": "t",
3731
+ "GIT_AUTHOR_EMAIL": "t@example.invalid",
3732
+ "GIT_COMMITTER_NAME": "t",
3733
+ "GIT_COMMITTER_EMAIL": "t@example.invalid",
3734
+ }
3735
+ for args in (
3736
+ ["init", "--initial-branch", "main"],
3737
+ ["config", "commit.gpgsign", "false"],
3738
+ ):
3739
+ subprocess.run(["git", "-C", str(path), *args], check=True, capture_output=True, env=env)
3740
+ (path / "session-definition.yaml").write_text("shared: {}\n", encoding="utf-8")
3741
+ subprocess.run(["git", "-C", str(path), "add", "-A"], check=True, capture_output=True, env=env)
3742
+ subprocess.run(["git", "-C", str(path), "commit", "-m", "seed"], check=True, capture_output=True, env=env)
3743
+
3744
+
3745
+ def test_the_manifest_records_the_revision_of_the_session_it_was_built_from(
3746
+ tmp_path: Path,
3747
+ ) -> None:
3748
+ """rosotacom_version pins the tool; this pins its input.
3749
+
3750
+ Without it the only recoverable commit is whatever the machine holds when
3751
+ somebody looks, which is a different fact — and a wrong one as soon as the
3752
+ machine has been synced in between.
3753
+ """
3754
+ session = tmp_path / "sessions" / "demo"
3755
+ _git_repo(session)
3756
+
3757
+ revision = rosotacom._source_revision(session)
3758
+
3759
+ assert revision is not None
3760
+ assert revision["vcs"] == "git"
3761
+ assert re.fullmatch(r"[0-9a-f]{40}", revision["commit"])
3762
+ assert revision["branch"] == "main"
3763
+ assert revision["dirty"] is False
3764
+ assert Path(revision["root"]).resolve() == session.resolve()
3765
+
3766
+
3767
+ def test_a_session_source_that_differs_from_its_commit_says_so(tmp_path: Path) -> None:
3768
+ session = tmp_path / "sessions" / "demo"
3769
+ _git_repo(session)
3770
+ (session / "session-definition.yaml").write_text("shared: {changed: true}\n", encoding="utf-8")
3771
+
3772
+ assert rosotacom._source_revision(session)["dirty"] is True
3773
+
3774
+
3775
+ def test_untracked_files_beside_a_session_do_not_make_it_dirty(tmp_path: Path) -> None:
3776
+ """A deployment checkout carries recordings, logs and scratch files.
3777
+
3778
+ Counting those would leave every real deployment permanently dirty, which is
3779
+ the same as reporting nothing.
3780
+ """
3781
+ session = tmp_path / "sessions" / "demo"
3782
+ _git_repo(session)
3783
+ (session / "rosbag2_2026_01_01-00_00_00").mkdir()
3784
+ (session / "rosbag2_2026_01_01-00_00_00" / "metadata.yaml").write_text("x\n", encoding="utf-8")
3785
+
3786
+ assert rosotacom._source_revision(session)["dirty"] is False
3787
+
3788
+
3789
+ @pytest.mark.parametrize("case", ["not_a_repository", "not_a_directory", "missing"])
3790
+ def test_a_source_without_a_revision_is_null_and_not_an_error(tmp_path: Path, case: str) -> None:
3791
+ """An instance must never fail to start over a provenance read."""
3792
+ if case == "not_a_repository":
3793
+ target = tmp_path / "plain"
3794
+ target.mkdir()
3795
+ elif case == "not_a_directory":
3796
+ target = tmp_path / "file"
3797
+ target.write_text("x\n", encoding="utf-8")
3798
+ else:
3799
+ target = tmp_path / "gone"
3800
+
3801
+ assert rosotacom._source_revision(target) is None
@@ -129,3 +129,75 @@ def test_link_trace_recorder_appends_jsonl_on_interval(tmp_path: Path) -> None:
129
129
 
130
130
  rows = [json.loads(line) for line in trace_path.read_text(encoding="utf-8").splitlines()]
131
131
  assert [row["kind"] for row in rows] == ["link_trace", "link_trace"]
132
+
133
+
134
+ def _recorder(tmp_path: Path, ticks: list[float], interval_s: float = 1.0) -> tuple[LinkTraceRecorder, list[float]]:
135
+ remaining = iter(ticks)
136
+ path = tmp_path / "status" / "link_trace.jsonl"
137
+ return LinkTraceRecorder(str(path), interval_s=interval_s, clock=lambda: next(remaining)), ticks
138
+
139
+
140
+ SNAPSHOT = {"generated_at": "2026-08-19T13:52:11.000", "peer": "a", "remote": "b", "topics": []}
141
+
142
+
143
+ def test_a_caller_ticking_at_the_configured_period_gets_a_row_per_tick(tmp_path: Path) -> None:
144
+ """The caller ticks at exactly this period, so its jitter is the whole question.
145
+
146
+ `generate_session_files` sets `status_write_interval_s` to the trace
147
+ interval, so every tick lands one period after the last — sometimes a
148
+ millisecond early. A gate that rejects those outright makes each of them
149
+ wait a further full period, which is how the 2026-08-19 drive ended up with
150
+ rows 1.984 s apart at `interval_s: 1.0`.
151
+ """
152
+ ticks = [100.0, 100.999, 101.998, 102.997, 103.996]
153
+ recorder, _ = _recorder(tmp_path, ticks)
154
+
155
+ written = [recorder.maybe_write(SNAPSHOT, None) for _ in ticks]
156
+
157
+ assert written == [True] * len(ticks)
158
+
159
+
160
+ def test_half_the_traffic_is_not_left_between_two_rows(tmp_path: Path) -> None:
161
+ """Why the tick above matters more than resolution.
162
+
163
+ A row's passive counter delta covers the caller's own tick. With rows twice
164
+ as far apart as the ticks, every second interval is described by no row at
165
+ all — so the trace undercounts the bytes it exists to account for.
166
+ """
167
+ ticks = [0.0, 0.999, 1.998, 2.997]
168
+ recorder, _ = _recorder(tmp_path, ticks)
169
+ for _ in ticks:
170
+ recorder.maybe_write(SNAPSHOT, {"passive_counter_delta": {"window_s": 1.0}})
171
+
172
+ rows = [
173
+ json.loads(line) for line in (tmp_path / "status" / "link_trace.jsonl").read_text(encoding="utf-8").splitlines()
174
+ ]
175
+ stamps = [row["monotonic_s"] for row in rows]
176
+ gaps = [b - a for a, b in zip(stamps, stamps[1:], strict=False)]
177
+ assert gaps, "more than one row"
178
+ assert max(gaps) < 1.5, "no second of the drive falls between two rows"
179
+
180
+
181
+ def test_a_much_faster_caller_is_still_held_to_the_interval(tmp_path: Path) -> None:
182
+ """The tolerance must not turn the interval into a suggestion."""
183
+ ticks = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2]
184
+ recorder, _ = _recorder(tmp_path, ticks)
185
+
186
+ written = [recorder.maybe_write(SNAPSHOT, None) for _ in ticks]
187
+
188
+ assert written == [True, False, False, False, False, True, False]
189
+
190
+
191
+ def test_a_stall_resynchronises_instead_of_bursting(tmp_path: Path) -> None:
192
+ """After a gap, the rows describe the link now.
193
+
194
+ Emitting the deadlines that were missed would produce a burst of rows that
195
+ describe nothing, and would make the trace's own timestamps disagree with
196
+ the counters in it.
197
+ """
198
+ ticks = [0.0, 30.0, 30.2, 31.0]
199
+ recorder, _ = _recorder(tmp_path, ticks)
200
+
201
+ written = [recorder.maybe_write(SNAPSHOT, None) for _ in ticks]
202
+
203
+ assert written == [True, True, False, True]
@@ -28,7 +28,9 @@ PLUGIN_BASE = (
28
28
  REPO_ROOT / "src" / "rosotacom" / "resources" / "ws" / "session" / "content" / "base" / "session_plugin_base.yaml"
29
29
  )
30
30
 
31
- OTA_FRAGMENT_BYTES = 1200
31
+ OTA_FRAGMENT_BYTES = 1024
32
+ #: The datagram cap the fragment has to fit inside, headers included.
33
+ OTA_DATAGRAM_BYTES = 1200
32
34
 
33
35
 
34
36
  def _load(path: Path, name: str) -> ModuleType:
@@ -73,7 +75,15 @@ def test_only_cyclone_caps_the_datagram_and_fast_dds_must_not() -> None:
73
75
  cyclone = _resolved("cyclonedds_tuned.xml")
74
76
 
75
77
  assert f"<FragmentSize>{OTA_FRAGMENT_BYTES}B</FragmentSize>" in cyclone
76
- assert f"<MaxMessageSize>{OTA_FRAGMENT_BYTES}B</MaxMessageSize>" in cyclone
78
+ assert f"<MaxMessageSize>{OTA_DATAGRAM_BYTES}B</MaxMessageSize>" in cyclone
79
+
80
+ # Strictly smaller, not equal, and this is the assertion the numbers exist
81
+ # for: an RTPS message carries headers as well as the fragment, so a
82
+ # fragment of exactly MaxMessageSize cannot be sent. Both were 1200 B, which
83
+ # CycloneDDS 0.10.5 coped with and 11.0.1 does not — no fragmented sample
84
+ # arrived at all, silently, while a 40 B one kept crossing
85
+ # (docs/findings/cyclone-fragment-equal-to-max-drops-fragmented-samples.md).
86
+ assert OTA_FRAGMENT_BYTES < OTA_DATAGRAM_BYTES
77
87
 
78
88
  for config in ("fastdds_tuned.xml", "fastdds_easy_mode.xml"):
79
89
  resolved = _without_comments(_resolved(config))