rosotacom-dev 2.5.dev39__tar.gz → 2.5.dev40__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 (353) hide show
  1. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/PKG-INFO +1 -1
  2. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/session-configuration.md +29 -2
  3. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/cli.py +5 -2
  4. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +5 -1
  5. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +71 -23
  6. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/PKG-INFO +1 -1
  7. rosotacom_dev-2.5.dev40/src/rosotacom_dev.egg-info/scm_version.json +8 -0
  8. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_session_pipeline.py +42 -3
  9. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_status_overview.py +84 -2
  10. rosotacom_dev-2.5.dev39/src/rosotacom_dev.egg-info/scm_version.json +0 -8
  11. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.devcontainer/devcontainer.json.template +0 -0
  12. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.devcontainer/re_generate_devcontainer_json.py +0 -0
  13. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/CODEOWNERS +0 -0
  14. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
  15. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
  16. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
  17. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
  18. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
  19. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
  20. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
  21. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
  22. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  23. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/actions/setup-just/action.yml +0 -0
  24. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/dependabot.yml +0 -0
  25. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/workflows/benchmark-calibrate.yml +0 -0
  26. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/workflows/benchmark-gate.yml +0 -0
  27. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/workflows/dev-release.yml +0 -0
  28. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/workflows/image-scan.yml +0 -0
  29. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/workflows/nightly-e2e.yml +0 -0
  30. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/workflows/pr-lightweight.yml +0 -0
  31. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/workflows/pr-merge-gate.yml +0 -0
  32. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.github/workflows/release.yml +0 -0
  33. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/.pre-commit-config.yaml +0 -0
  34. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/AGENTS.md +0 -0
  35. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/CONCURRENCY.md +0 -0
  36. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/CONTRIBUTING.md +0 -0
  37. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/DEVELOPMENT_PRINCIPLES.md +0 -0
  38. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/LICENSE.txt +0 -0
  39. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/MANIFEST.in +0 -0
  40. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/README.md +0 -0
  41. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/budgets.jsonl +0 -0
  42. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/calibration/README.md +0 -0
  43. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/calibration/capacity-size-tight-cyclone.json +0 -0
  44. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
  45. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-nominal-cyclone.json +0 -0
  46. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-tight-cyclone.json +0 -0
  47. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-tight-fastdds.json +0 -0
  48. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-tight-zenoh.json +0 -0
  49. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/codecov.yml +0 -0
  50. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/deployment-configuration.md +0 -0
  51. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/benchmark-ab.md +0 -0
  52. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/benchmark-bag-as-load.md +0 -0
  53. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/ci.md +0 -0
  54. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/ffmpeg-keyframes.md +0 -0
  55. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/findings/README.md +0 -0
  56. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
  57. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/findings/delay-alone-no-loss.md +0 -0
  58. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/findings/head-of-line-irregularity.md +0 -0
  59. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
  60. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/findings/lighter-message-loss.md +0 -0
  61. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
  62. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/forensics-report.md +0 -0
  63. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/geo-link-map.md +0 -0
  64. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/github-repository-settings.md +0 -0
  65. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/link-bandwidth.md +0 -0
  66. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/link-trace.md +0 -0
  67. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/owner-runbook.md +0 -0
  68. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/performance-bands.md +0 -0
  69. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/playbooks/README.md +0 -0
  70. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/quality-model.md +0 -0
  71. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/release-notes/TEMPLATE.md +0 -0
  72. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/release-notes/v2.1.md +0 -0
  73. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/release-notes/v2.2.md +0 -0
  74. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/release-notes/v2.3.md +0 -0
  75. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/release-notes/v2.4.md +0 -0
  76. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/release.md +0 -0
  77. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
  78. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/rfcs/0002-expectation-concepts.md +0 -0
  79. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/rfcs/0003-metric-backbone.md +0 -0
  80. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/rfcs/0004-network-profiles.md +0 -0
  81. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
  82. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/rfcs/0006-dynamic-qos.md +0 -0
  83. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/rfcs/0007-regression-gate.md +0 -0
  84. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/rfcs/README.md +0 -0
  85. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/testing.md +0 -0
  86. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/docs/work-items.md +0 -0
  87. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/install.sh +0 -0
  88. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/justfile +0 -0
  89. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/media/control_center.png +0 -0
  90. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/media/echo_test.png +0 -0
  91. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/media/forensics-report-example.png +0 -0
  92. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/media/host.png +0 -0
  93. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/media/vehicle.png +0 -0
  94. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/pyproject.toml +0 -0
  95. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/requirements.txt +0 -0
  96. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/rosotacom.yaml +0 -0
  97. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/setup.cfg +0 -0
  98. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/__init__.py +0 -0
  99. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/__main__.py +0 -0
  100. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/anonymize.py +0 -0
  101. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/bag_ground_truth.py +0 -0
  102. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/benched_set.py +0 -0
  103. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/benchmark.py +0 -0
  104. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/benchmark_delta.py +0 -0
  105. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/bundle_check.py +0 -0
  106. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/cli_benchmark.py +0 -0
  107. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/deployment.py +0 -0
  108. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/ffmpeg_packet.py +0 -0
  109. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/forensics.py +0 -0
  110. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/geomap.py +0 -0
  111. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/image_cache.py +0 -0
  112. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/network_profiles.py +0 -0
  113. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/network_shaper.py +0 -0
  114. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/plots.py +0 -0
  115. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/py.typed +0 -0
  116. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/benched-set.yaml +0 -0
  117. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/.gitignore +0 -0
  118. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/README.md +0 -0
  119. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/__init__.py +0 -0
  120. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
  121. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
  122. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/profiles.yaml +0 -0
  123. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/ros2docker.json +0 -0
  124. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
  125. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
  126. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
  127. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
  128. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
  129. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
  130. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
  131. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
  132. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
  133. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
  134. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
  135. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
  136. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
  137. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
  138. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
  139. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
  140. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
  141. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
  142. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
  143. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
  144. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
  145. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
  146. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
  147. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
  148. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
  149. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
  150. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
  151. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
  152. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
  153. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
  154. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
  155. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
  156. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
  157. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
  158. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
  159. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
  160. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
  161. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
  162. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
  163. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
  164. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
  165. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
  166. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
  167. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
  168. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
  169. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
  170. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
  171. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
  172. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
  173. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
  174. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
  175. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
  176. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
  177. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
  178. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
  179. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
  180. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
  181. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
  182. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
  183. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
  184. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
  185. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
  186. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
  187. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
  188. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
  189. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
  190. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
  191. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
  192. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
  193. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ros2docker.json.example +0 -0
  194. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
  195. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
  196. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
  197. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
  198. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
  199. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
  200. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
  201. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
  202. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
  203. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/cyclonedds_local_participants.xml.template +0 -0
  204. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
  205. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
  206. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
  207. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
  208. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
  209. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
  210. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
  211. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
  212. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
  213. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
  214. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
  215. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
  216. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
  217. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
  218. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
  219. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
  220. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
  221. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
  222. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
  223. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
  224. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
  225. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
  226. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
  227. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
  228. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
  229. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
  230. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
  231. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
  232. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
  233. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
  234. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
  235. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
  236. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
  237. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
  238. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
  239. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
  240. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
  241. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
  242. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
  243. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
  244. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
  245. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
  246. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
  247. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
  248. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
  249. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
  250. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
  251. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
  252. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
  253. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
  254. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
  255. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
  256. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
  257. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
  258. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
  259. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
  260. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
  261. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
  262. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
  263. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
  264. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
  265. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
  266. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
  267. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
  268. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
  269. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
  270. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
  271. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
  272. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
  273. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +0 -0
  274. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
  275. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
  276. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
  277. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
  278. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
  279. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
  280. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
  281. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
  282. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/status_eval.py +0 -0
  283. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/stream_stats.py +0 -0
  284. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/trace_profiles.py +0 -0
  285. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/transit.py +0 -0
  286. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom/video_quality.py +0 -0
  287. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/SOURCES.txt +0 -0
  288. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
  289. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
  290. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/requires.txt +0 -0
  291. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/scm_file_list.json +0 -0
  292. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
  293. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/terminology.md +0 -0
  294. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_benched_set_registry.py +0 -0
  295. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_findings.py +0 -0
  296. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_markdown_links.py +0 -0
  297. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_ota_source_bundle.py +0 -0
  298. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_package_metadata.py +0 -0
  299. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_packaged_resources.py +0 -0
  300. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_profile_covers_generated_commands.py +0 -0
  301. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_pytest_policy.py +0 -0
  302. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_readme_examples.py +0 -0
  303. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_security_maintenance_config.py +0 -0
  304. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_session_configuration_doc.py +0 -0
  305. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_session_template_substitution.py +0 -0
  306. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/contract/test_workflow_contracts.py +0 -0
  307. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/conftest.py +0 -0
  308. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/test_anonymize_e2e.py +0 -0
  309. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/test_benchmark_ab.py +0 -0
  310. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/test_benchmark_capacity.py +0 -0
  311. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/test_benchmark_replay.py +0 -0
  312. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/test_parallel_smoke.py +0 -0
  313. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/test_smoke.py +0 -0
  314. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/test_timeline_stepping.py +0 -0
  315. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/e2e/test_video_quality_e2e.py +0 -0
  316. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/sessions/generate_rmw_matrix.py +0 -0
  317. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
  318. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
  319. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
  320. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
  321. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
  322. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_anonymize.py +0 -0
  323. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_bag_ground_truth.py +0 -0
  324. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_benched_set.py +0 -0
  325. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_benchmark.py +0 -0
  326. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_benchmark_delta.py +0 -0
  327. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_bundle_check.py +0 -0
  328. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_catmux_pane_logging.py +0 -0
  329. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_cli.py +0 -0
  330. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_cli_benchmark.py +0 -0
  331. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_concurrency.py +0 -0
  332. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_deployment.py +0 -0
  333. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_ffmpeg_packet.py +0 -0
  334. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_forensics.py +0 -0
  335. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_geomap.py +0 -0
  336. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_image_cache.py +0 -0
  337. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_link_bytes.py +0 -0
  338. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_link_trace.py +0 -0
  339. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_network_profiles.py +0 -0
  340. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_network_shaper.py +0 -0
  341. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_ota_unwrapper.py +0 -0
  342. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_ota_wrapper.py +0 -0
  343. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_ota_xml.py +0 -0
  344. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_plots.py +0 -0
  345. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_qos_fallback_logging.py +0 -0
  346. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_relay_optional_parameters.py +0 -0
  347. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_stage_latency.py +0 -0
  348. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_status_eval.py +0 -0
  349. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_status_overview_observer.py +0 -0
  350. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_stream_stats.py +0 -0
  351. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_trace_profiles.py +0 -0
  352. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/tests/unit/test_transit.py +0 -0
  353. {rosotacom_dev-2.5.dev39 → rosotacom_dev-2.5.dev40}/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.dev39
3
+ Version: 2.5.dev40
4
4
  Summary: Host CLI for ROS OTA communication sessions.
5
5
  Author: develNor
6
6
  License-Expression: BSD-3-Clause
@@ -446,7 +446,8 @@ processing:
446
446
  pixel_cap_preset: "wsvga" # scalar, used as suffix only,
447
447
  transport:
448
448
  type: ffmpeg # ffmpeg | foxglove | compressed
449
- local_republish: false # default false
449
+ local_republish: raw # raw | compressed; omit for no sender-side decode
450
+ remote_republish: compressed # raw | compressed; omit for no receiver-side decode
450
451
  # plus type-specific params (see below)
451
452
  ```
452
453
 
@@ -507,11 +508,37 @@ The receiver undoes the chain in reverse, and every stage there is computed from
507
508
  the delivered topic rather than from the OTA topic:
508
509
 
509
510
  1) unwrap → republishes on the pre-wrap name (so wrapping renames nothing)
510
- 2) `local_republish: true` → reverse transport decodes into `+ /raw`
511
+ 2) `remote_republish: <transport>` → reverse transport decodes into `+ /<transport>`
511
512
  3) decompress → republishes on the pre-compress name
512
513
  4) framebridge `global_to_local` → the local base topic
513
514
  5) trickle → `+ /trickle`, the only receiver-side stage that adds a suffix
514
515
 
516
+ ##### The two reverse republishes
517
+
518
+ An encoded stream crosses the link as packets — `FFMPEGPacket`, `CompressedVideo`
519
+ — and something has to turn those back into an image. That decode can happen in
520
+ two places, and they answer different questions:
521
+
522
+ - **`remote_republish`** runs on the receiving peer and is the one that matters:
523
+ it produces the topic the receiving application subscribes to (`<encoded>/raw`
524
+ or `<encoded>/compressed`), and it is what `_delivered_topic` reports as the
525
+ delivered stage.
526
+ - **`local_republish`** runs on the *sending* peer, against the stream it just
527
+ encoded. Nothing crosses the link for it; it exists so the sending machine can
528
+ see approximately what the receiver will get.
529
+
530
+ Both name the image transport they publish in rather than being switched on:
531
+
532
+ | value | delivered type | cost |
533
+ |---|---|---|
534
+ | `raw` | `sensor_msgs/msg/Image` | the transport undone and nothing else, at full frame size — a 1280x800 stream is ~3 MB per frame |
535
+ | `compressed` | `sensor_msgs/msg/CompressedImage` | a JPEG encode per frame, roughly an order of magnitude less data on the wire and in a `record -a` |
536
+
537
+ Omitting a key means that side does not decode. There is deliberately **no
538
+ default**: `type: compressed` already delivers an image, so a decode that
539
+ switched itself on would produce exactly the full-size copy a session chose that
540
+ transport to avoid.
541
+
515
542
  #### Transport parameters
516
543
  `type: ffmpeg` supports:
517
544
  - `gop_size` (int)
@@ -6134,8 +6134,11 @@ def _smoke_postprocessed_topic(entry: Any, pipe: dict[str, Any]) -> str:
6134
6134
  if pipe.get("framebridge") == "global_to_local":
6135
6135
  return str(pipe["fb_g2l_base"])
6136
6136
  transport = pipe.get("transport")
6137
- if transport is not None and bool(getattr(transport, "local_republish", False)):
6138
- return str(pipe["final"]) + "/raw"
6137
+ remote_republish = getattr(transport, "remote_republish", None) if transport is not None else None
6138
+ if remote_republish:
6139
+ # The receiver's decode is what the smoke drives and asserts; the
6140
+ # sender's own preview (`local_republish`) never reaches this peer.
6141
+ return str(pipe["final"]) + f"/{remote_republish}"
6139
6142
  return str(pipe["final"])
6140
6143
 
6141
6144
 
@@ -49,7 +49,11 @@ topics:
49
49
  processing:
50
50
  transport:
51
51
  type: ffmpeg
52
- local_republish: true
52
+ # `raw` on both sides, because this example measures the codec: PSNR
53
+ # and SSIM compare pixels, and a JPEG twin would fold its own loss
54
+ # into the number the example exists to report.
55
+ local_republish: raw
56
+ remote_republish: raw
53
57
  gop_size: 4
54
58
  bit_rate: 2000000
55
59
  # Wrapping an encoded stream: the wrapper runs after the encoder, so the
@@ -64,18 +64,34 @@ HEARTBEAT_MSG_TYPE = "com_msgs/msg/EchoHeartbeat"
64
64
  COMPRESSED_MSG_TYPE = "com_msgs/msg/CompressedData"
65
65
  OTA_STAMPED_MSG_TYPE = "com_msgs/msg/OtaStamped"
66
66
  SENSOR_IMAGE_MSG_TYPE = "sensor_msgs/msg/Image"
67
+ SENSOR_COMPRESSED_IMAGE_MSG_TYPE = "sensor_msgs/msg/CompressedImage"
67
68
  TRANSPORT_OUTPUT_TYPES = {
68
69
  "compressed": "sensor_msgs/msg/CompressedImage",
69
70
  "ffmpeg": "ffmpeg_image_transport_msgs/msg/FFMPEGPacket",
70
71
  "foxglove": "foxglove_msgs/msg/CompressedVideo",
71
72
  }
73
+ #: The image transports a reverse republish may decode *into*, and the message
74
+ #: type each one delivers. `raw` is the neutral reconstruction -- the transport
75
+ #: undone and nothing else -- and `compressed` trades a JPEG encode for roughly
76
+ #: an order of magnitude less data on the wire and in a `record -a`.
77
+ REPUBLISH_OUTPUT_TYPES = {
78
+ "raw": SENSOR_IMAGE_MSG_TYPE,
79
+ "compressed": SENSOR_COMPRESSED_IMAGE_MSG_TYPE,
80
+ }
72
81
 
73
82
 
74
83
  @dataclass
75
84
  class TransportSpec:
76
85
  type: str
77
86
  params: Dict[str, Any]
78
- local_republish: bool = False
87
+ #: Reverse republish on the sending peer: decode the stream it just encoded,
88
+ #: so the machine that sends can see what the receiver will get. Optional.
89
+ local_republish: Optional[str] = None
90
+ #: Reverse republish on the receiving peer: the decode the receiving
91
+ #: application consumes. Optional too -- a consumer that subscribes through
92
+ #: image_transport itself, or one that only forwards or records packets,
93
+ #: does not want a second copy of every frame.
94
+ remote_republish: Optional[str] = None
79
95
 
80
96
 
81
97
  @dataclass
@@ -1288,11 +1304,14 @@ def _delivered_topic(pipe: Dict[str, Any], final: str) -> str:
1288
1304
  # renames nothing downstream of it.
1289
1305
  topic = str(pipe["ota_in"])
1290
1306
  transport = pipe.get("transport")
1291
- if isinstance(transport, TransportSpec) and transport.local_republish:
1292
- # image_transport reverse republish decodes the encoded topic into
1293
- # `<encoded>/raw`; PSNR/SSIM and application-level checks need that
1294
- # decoded sensor_msgs/Image stage, not the encoded packet.
1295
- topic = str(pipe["irt_in"]) + "/raw"
1307
+ if isinstance(transport, TransportSpec) and transport.remote_republish:
1308
+ # The receiver's reverse republish decodes the encoded topic into
1309
+ # `<encoded>/<transport>`, and that decoded image -- not the encoded
1310
+ # packet -- is what the receiving application subscribes to.
1311
+ # `local_republish` is deliberately not consulted here: it is the
1312
+ # *sender's* preview, on the sender's machine, and says nothing about
1313
+ # what the receiver ends up reading.
1314
+ topic = str(pipe["irt_in"]) + f"/{transport.remote_republish}"
1296
1315
  elif pipe.get("compress"):
1297
1316
  topic = str(pipe["comp_in"])
1298
1317
  if pipe.get("framebridge") == "global_to_local":
@@ -1544,8 +1563,8 @@ def _build_status_pipeline_spec(
1544
1563
  if postprocessed != final:
1545
1564
  native_in_type = base_type
1546
1565
  transport = p.get("transport")
1547
- if isinstance(transport, TransportSpec) and transport.local_republish:
1548
- native_in_type = SENSOR_IMAGE_MSG_TYPE
1566
+ if isinstance(transport, TransportSpec) and transport.remote_republish:
1567
+ native_in_type = REPUBLISH_OUTPUT_TYPES[transport.remote_republish]
1549
1568
  stages.append(
1550
1569
  {
1551
1570
  "stage": "native_in",
@@ -1659,9 +1678,27 @@ def _compute_pipeline(
1659
1678
  if not isinstance(t, dict) or "type" not in t:
1660
1679
  raise ValueError(f"transport must be dict with 'type' for topic '{entry.base}'")
1661
1680
  ttype = t["type"]
1662
- local_republish = bool(t.get("local_republish", False))
1663
- params = {k: v for k, v in t.items() if k not in ("type", "local_republish")}
1664
- transport = TransportSpec(type=ttype, params=params, local_republish=local_republish)
1681
+ republish_keys = ("local_republish", "remote_republish")
1682
+
1683
+ def _republish(key: str) -> Optional[str]:
1684
+ value = t.get(key)
1685
+ if value is None:
1686
+ return None
1687
+ if value not in REPUBLISH_OUTPUT_TYPES:
1688
+ raise ValueError(
1689
+ f"transport.{key} must name an image transport "
1690
+ f"({'|'.join(sorted(REPUBLISH_OUTPUT_TYPES))}) for topic '{entry.base}', got {value!r}. "
1691
+ "Omit the key for no reverse republish on that side."
1692
+ )
1693
+ return str(value)
1694
+
1695
+ params = {k: v for k, v in t.items() if k not in ("type", *republish_keys)}
1696
+ transport = TransportSpec(
1697
+ type=ttype,
1698
+ params=params,
1699
+ local_republish=_republish("local_republish"),
1700
+ remote_republish=_republish("remote_republish"),
1701
+ )
1665
1702
 
1666
1703
  topic = entry.base
1667
1704
 
@@ -1747,7 +1784,11 @@ def _compute_pipeline(
1747
1784
  if transport:
1748
1785
  it_in = topic
1749
1786
  topic = topic + f"/{transport.type}"
1750
- if transport.local_republish:
1787
+ if transport.local_republish or transport.remote_republish:
1788
+ # The encoded topic a reverse republish decodes *from*. One name for
1789
+ # both sides: each peer runs its own decoder against the copy it has
1790
+ # (the sender against what it just encoded, the receiver against what
1791
+ # arrived), and which of them exists is decided per side below.
1751
1792
  irt_in = topic
1752
1793
 
1753
1794
  # The wrapper is last, always. Its `seq` and send stamp describe whatever it
@@ -2607,7 +2648,11 @@ def func(
2607
2648
  thr_items = [(p["thr_in"], p["throttle"]) for p in out_pipes if p["thr_in"]]
2608
2649
  ipx_items = [(p["ipx_in"], p["pixel"]) for p in out_pipes if p["ipx_in"]]
2609
2650
  it_items = [(p["it_in"], p["transport"]) for p in out_pipes if p["it_in"]]
2610
- irt_items_local = [(p["irt_in"], p["transport"]) for p in out_pipes if p["irt_in"]]
2651
+ # Sender-side reverse transport: this peer decodes what it just encoded,
2652
+ # so the machine that sends can see what the receiver will get.
2653
+ irt_items_local = [
2654
+ (p["irt_in"], p["transport"]) for p in out_pipes if p["irt_in"] and p["transport"].local_republish
2655
+ ]
2611
2656
 
2612
2657
  # Compression happens on the sender side for topics marked with processing.compress
2613
2658
  comp_topics = _dedup_keep_order([p["comp_in"] for p in out_pipes if p["comp_in"]])
@@ -2660,15 +2705,15 @@ def func(
2660
2705
  _assert_max("it", it_items, 4)
2661
2706
  _assert_max("nor", nor_items, 4)
2662
2707
 
2663
- # Remote-side reverse transport is configured (if requested via local_republish) on the receiver, too.
2708
+ # Receiver-side reverse transport: this peer decodes what arrived, which
2709
+ # is the copy the receiving application reads (see `_delivered_topic`).
2664
2710
  irt_items_remote = []
2665
2711
  for e, p in zip(in_entries, in_pipes):
2666
- if not p["irt_in"]:
2667
- continue
2668
2712
  tspec = p["transport"]
2669
- assert tspec is not None
2713
+ if not p["irt_in"] or not (tspec and tspec.remote_republish):
2714
+ continue
2670
2715
  topic = _prefix_with_source_name_if_needed(local, remote, p["irt_in"])
2671
- irt_items_remote.append((topic, tspec.type))
2716
+ irt_items_remote.append((topic, tspec))
2672
2717
 
2673
2718
  # Build plugin.yaml blocks
2674
2719
  blocks: List[PluginBlock] = []
@@ -2953,9 +2998,9 @@ def func(
2953
2998
  if p.get("it_in")
2954
2999
  ]
2955
3000
  + [
2956
- f'{p["irt_in"]}/raw'
3001
+ f'{p["irt_in"]}/{p["transport"].local_republish}'
2957
3002
  for p in out_pipes
2958
- if p.get("irt_in")
3003
+ if p.get("irt_in") and p["transport"].local_republish
2959
3004
  ]
2960
3005
  )
2961
3006
  blocks.append(
@@ -3152,12 +3197,15 @@ def func(
3152
3197
  raise ValueError(f"Unsupported transport type '{tspec.type}'")
3153
3198
  blocks.append(PluginBlock("it", items2))
3154
3199
 
3155
- # Merge reverse-transport config for (a) local reconstruction and (b) inbound remote topics (if requested).
3200
+ # Merge reverse-transport config for (a) the sender's own preview of what
3201
+ # it encoded and (b) the decode of what arrived. Both run on *this* peer;
3202
+ # what differs is which copy they decode and which transport the session
3203
+ # asked each of them to publish in.
3156
3204
  irt_all: List[Tuple[str, str, str]] = []
3157
3205
  for t, tspec in irt_items_local:
3158
3206
  assert tspec is not None
3159
- irt_all.append((t, tspec.type, "raw"))
3160
- irt_all.extend((topic, ttype, "raw") for topic, ttype in irt_items_remote)
3207
+ irt_all.append((t, tspec.type, str(tspec.local_republish)))
3208
+ irt_all.extend((topic, tspec.type, str(tspec.remote_republish)) for topic, tspec in irt_items_remote)
3161
3209
  _assert_max("irt", irt_all, 4)
3162
3210
  if irt_all:
3163
3211
  items2 = [("irt", True)]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rosotacom-dev
3
- Version: 2.5.dev39
3
+ Version: 2.5.dev40
4
4
  Summary: Host CLI for ROS OTA communication sessions.
5
5
  Author: develNor
6
6
  License-Expression: BSD-3-Clause
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "2.4",
3
+ "distance": 40,
4
+ "node": "g679b8af8945b83eea3c582a4e0db6916592635bc",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-08-17"
8
+ }
@@ -57,9 +57,9 @@ def _pipeline(processing: dict, base: str = "/camera/image", msg_type: str = "se
57
57
 
58
58
 
59
59
  def _ffmpeg(**extra: object) -> dict:
60
- spec = {"type": "ffmpeg", "local_republish": True}
60
+ spec: dict = {"type": "ffmpeg", "local_republish": "raw", "remote_republish": "raw"}
61
61
  spec.update(extra)
62
- return {"transport": spec}
62
+ return {"transport": {k: v for k, v in spec.items() if v is not None}}
63
63
 
64
64
 
65
65
  # ---------------------------------------------------------------------------
@@ -88,12 +88,51 @@ def test_wrapping_a_transport_does_not_rename_the_delivered_topic() -> None:
88
88
 
89
89
 
90
90
  def test_transport_without_republish_delivers_the_unwrapped_packet() -> None:
91
- _, pipe = _pipeline({**_ffmpeg(local_republish=False), "use_ota_wrapper": True})
91
+ _, pipe = _pipeline(
92
+ {**_ffmpeg(local_republish=None, remote_republish=None), "use_ota_wrapper": True},
93
+ )
92
94
 
93
95
  assert pipe["irt_in"] is None
94
96
  assert generator._postprocessed_topic(pipe, pipe["final"]) == "/camera/image/ffmpeg"
95
97
 
96
98
 
99
+ # ---------------------------------------------------------------------------
100
+ # the two reverse republishes are separate decisions (#276)
101
+ # ---------------------------------------------------------------------------
102
+
103
+
104
+ def test_the_receiver_decode_names_the_delivered_topic_and_type() -> None:
105
+ """`remote_republish` decides what the receiving application subscribes to."""
106
+ entry, pipe = _pipeline(_ffmpeg(remote_republish="compressed"))
107
+
108
+ assert generator._postprocessed_topic(pipe, pipe["final"]) == "/camera/image/ffmpeg/compressed"
109
+ assert generator.REPUBLISH_OUTPUT_TYPES["compressed"] == "sensor_msgs/msg/CompressedImage"
110
+ # What crosses the link is still the encoded packet; only the decode changed.
111
+ assert generator._final_topic_type(entry, pipe) == generator.TRANSPORT_OUTPUT_TYPES["ffmpeg"]
112
+
113
+
114
+ def test_the_senders_preview_does_not_decide_the_delivered_topic() -> None:
115
+ """`local_republish` runs on the sending machine and never reaches the receiver."""
116
+ _, pipe = _pipeline(_ffmpeg(local_republish="raw", remote_republish="compressed"))
117
+
118
+ assert generator._postprocessed_topic(pipe, pipe["final"]) == "/camera/image/ffmpeg/compressed"
119
+
120
+
121
+ def test_a_sender_only_preview_delivers_the_packet() -> None:
122
+ """A preview on the sender leaves the receiver with what crossed the link."""
123
+ _, pipe = _pipeline(_ffmpeg(remote_republish=None))
124
+
125
+ # The encoded topic still exists -- the sender decodes it locally --
126
+ # but nothing decodes it on the receiving side.
127
+ assert pipe["irt_in"] == "/camera/image/ffmpeg"
128
+ assert generator._postprocessed_topic(pipe, pipe["final"]) == "/camera/image/ffmpeg"
129
+
130
+
131
+ def test_a_republish_must_name_a_known_image_transport() -> None:
132
+ with pytest.raises(ValueError, match="remote_republish"):
133
+ _pipeline(_ffmpeg(remote_republish="jpeg"))
134
+
135
+
97
136
  def test_trickle_republishes_the_unwrapped_topic() -> None:
98
137
  """#259: `<latched>/ota_stamped/trickle` is a name no application subscribes to."""
99
138
  _, pipe = _pipeline(
@@ -720,7 +720,8 @@ def test_pipeline_spec_exposes_decoded_reverse_transport_stage(tmp_path: Path) -
720
720
  "processing": {
721
721
  "transport": {
722
722
  "type": "ffmpeg",
723
- "local_republish": True,
723
+ "local_republish": "raw",
724
+ "remote_republish": "raw",
724
725
  "gop_size": 4,
725
726
  "bit_rate": 500000,
726
727
  }
@@ -744,6 +745,86 @@ def test_pipeline_spec_exposes_decoded_reverse_transport_stage(tmp_path: Path) -
744
745
  assert "metric_stage_topics: /com/in/b/camera/image/ffmpeg,/camera/image/ffmpeg,/camera/image/ffmpeg/raw" in plugin
745
746
 
746
747
 
748
+ def test_a_compressed_receiver_decode_names_the_stage_and_its_type(tmp_path: Path) -> None:
749
+ """#276: the decoded twin follows `remote_republish`, on the name and the type.
750
+
751
+ An uncompressed `sensor_msgs/Image` twin is ~3 MB per frame at 1280x800 and
752
+ dominates any `record -a` on the receiving machine; a session that asks for
753
+ `compressed` must get a `CompressedImage` under `.../ffmpeg/compressed`, and
754
+ the status overview has to report that stage, not the one it used to assume.
755
+ """
756
+ cfg = _heartbeat_cfg()
757
+ cfg["shared"]["use_heartbeat"] = False
758
+ cfg["topics"] = {
759
+ "b_to_a": [
760
+ {
761
+ "topic": "/camera/image",
762
+ "type": "sensor_msgs/msg/Image",
763
+ "processing": {
764
+ "transport": {
765
+ "type": "ffmpeg",
766
+ # Deliberately asymmetric: the sender keeps pixels for a
767
+ # local look, the receiver takes the small copy.
768
+ "local_republish": "raw",
769
+ "remote_republish": "compressed",
770
+ "gop_size": 4,
771
+ "bit_rate": 500000,
772
+ }
773
+ },
774
+ }
775
+ ]
776
+ }
777
+
778
+ _generate(cfg, tmp_path)
779
+
780
+ spec = yaml.safe_load((tmp_path / "a" / "pipeline_spec.yaml").read_text(encoding="utf-8"))
781
+ inbound = next(topic for topic in spec["topics"] if topic["base"] == "/camera/image")
782
+ stages = {stage["stage"]: stage for stage in inbound["stages"]}
783
+ assert stages["native_in"]["topic"] == "/camera/image/ffmpeg/compressed"
784
+ assert stages["native_in"]["type"] == "sensor_msgs/msg/CompressedImage"
785
+
786
+ receiver_plugin = (tmp_path / "a" / "plugin.yaml").read_text(encoding="utf-8")
787
+ assert "irt_1_out_transport: compressed" in receiver_plugin
788
+
789
+ # The sender's own preview is a separate decision and keeps its own format.
790
+ sender_plugin = (tmp_path / "b" / "plugin.yaml").read_text(encoding="utf-8")
791
+ assert "irt_1_out_transport: raw" in sender_plugin
792
+
793
+
794
+ def test_a_receiver_without_a_decode_gets_no_reverse_transport(tmp_path: Path) -> None:
795
+ """A sender-side preview must not put a decoder on the receiving peer."""
796
+ cfg = _heartbeat_cfg()
797
+ cfg["shared"]["use_heartbeat"] = False
798
+ cfg["topics"] = {
799
+ "b_to_a": [
800
+ {
801
+ "topic": "/camera/image",
802
+ "type": "sensor_msgs/msg/Image",
803
+ "processing": {
804
+ "transport": {
805
+ "type": "ffmpeg",
806
+ "local_republish": "raw",
807
+ "gop_size": 4,
808
+ "bit_rate": 500000,
809
+ }
810
+ },
811
+ }
812
+ ]
813
+ }
814
+
815
+ _generate(cfg, tmp_path)
816
+
817
+ receiver_plugin = (tmp_path / "a" / "plugin.yaml").read_text(encoding="utf-8")
818
+ assert "irt_1_topic" not in receiver_plugin
819
+ sender_plugin = (tmp_path / "b" / "plugin.yaml").read_text(encoding="utf-8")
820
+ assert "irt_1_out_transport: raw" in sender_plugin
821
+
822
+ spec = yaml.safe_load((tmp_path / "a" / "pipeline_spec.yaml").read_text(encoding="utf-8"))
823
+ inbound = next(topic for topic in spec["topics"] if topic["base"] == "/camera/image")
824
+ stages = {stage["stage"] for stage in inbound["stages"]}
825
+ assert "native_in" not in stages
826
+
827
+
747
828
  def test_reverse_transport_raw_stage_uses_sensor_image_type_for_compressed_source(tmp_path: Path) -> None:
748
829
  cfg = _heartbeat_cfg()
749
830
  cfg["shared"]["use_heartbeat"] = False
@@ -758,7 +839,8 @@ def test_reverse_transport_raw_stage_uses_sensor_image_type_for_compressed_sourc
758
839
  "drop": {"drop_count": 1, "window_size": 2},
759
840
  "transport": {
760
841
  "type": "ffmpeg",
761
- "local_republish": True,
842
+ "local_republish": "raw",
843
+ "remote_republish": "raw",
762
844
  "gop_size": 4,
763
845
  "bit_rate": 500000,
764
846
  },
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "2.4",
3
- "distance": 39,
4
- "node": "g17e7c753489cb153f8066e2911d37fdd85dcdb2f",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-08-14"
8
- }