rosotacom-dev 2.5.dev51__tar.gz → 2.5.dev52__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.
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/workflows/nightly-e2e.yml +1 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/PKG-INFO +8 -1
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/README.md +7 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/README.md +3 -0
- rosotacom_dev-2.5.dev52/docs/findings/fastdds-datagram-cap-drops-large-samples.md +89 -0
- rosotacom_dev-2.5.dev52/docs/findings/graph-derived-types-block-a-non-graph-transport.md +79 -0
- rosotacom_dev-2.5.dev52/docs/findings/sender-rows-make-a-dead-link-look-loss-free.md +59 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/session-configuration.md +87 -3
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/benchmark.py +12 -2
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/cli.py +89 -40
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/cli_benchmark.py +80 -28
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +3 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +3 -0
- rosotacom_dev-2.5.dev52/src/rosotacom/resources/ws/ota_configs/fastdds_easy_mode.xml.template +49 -0
- rosotacom_dev-2.5.dev52/src/rosotacom/resources/ws/ota_configs/fastdds_tuned.xml.template +154 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +9 -2
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +19 -7
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +24 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +21 -3
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +84 -7
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/transit.py +20 -2
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom_dev.egg-info/PKG-INFO +8 -1
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom_dev.egg-info/SOURCES.txt +8 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom_dev.egg-info/scm_file_list.json +8 -0
- rosotacom_dev-2.5.dev52/src/rosotacom_dev.egg-info/scm_version.json +8 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_markdown_links.py +15 -1
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_packaged_resources.py +2 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_security_maintenance_config.py +4 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/conftest.py +1 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/sessions/generate_rmw_matrix.py +7 -0
- rosotacom_dev-2.5.dev52/tests/sessions/rmw_matrix/1_heartbeat_fastdds-default/session-definition.yaml +22 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_benchmark.py +15 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_cli_benchmark.py +76 -0
- rosotacom_dev-2.5.dev52/tests/unit/test_ota_link_configs.py +288 -0
- rosotacom_dev-2.5.dev52/tests/unit/test_pub_sub_pair_types.py +144 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_relay_optional_parameters.py +1 -1
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_transit.py +26 -2
- rosotacom_dev-2.5.dev51/src/rosotacom_dev.egg-info/scm_version.json +0 -8
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.devcontainer/devcontainer.json.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.devcontainer/re_generate_devcontainer_json.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/CODEOWNERS +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/actions/setup-just/action.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/dependabot.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/workflows/benchmark-calibrate.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/workflows/benchmark-gate.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/workflows/dev-release.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/workflows/image-scan.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/workflows/pr-lightweight.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/workflows/pr-merge-gate.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.github/workflows/release.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/.pre-commit-config.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/AGENTS.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/CONCURRENCY.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/CONTRIBUTING.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/DEVELOPMENT_PRINCIPLES.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/MANIFEST.in +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/budgets.jsonl +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/calibration/README.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/calibration/capacity-size-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/calibration/probe-loss-nominal-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/calibration/probe-loss-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/calibration/probe-loss-tight-fastdds.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/calibration/probe-loss-tight-zenoh.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/codecov.yml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/deployment-configuration.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/benchmark-ab.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/benchmark-bag-as-load.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/ci.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/ffmpeg-keyframes.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/delay-alone-no-loss.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/head-of-line-irregularity.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/keyframe-loss-kills-the-next-deltas.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/lighter-message-loss.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/oversubscription-queues-not-losses.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/reorder-becomes-reader-loss.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/repro/decode_chain_repro.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/repro/reorder_drop_repro.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/forensics-report.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/geo-link-map.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/github-repository-settings.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/link-bandwidth.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/link-trace.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/owner-runbook.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/performance-bands.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/playbooks/README.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/quality-model.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/release-notes/TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/release-notes/v2.1.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/release-notes/v2.2.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/release-notes/v2.3.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/release-notes/v2.4.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/release.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/rfcs/0002-expectation-concepts.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/rfcs/0003-metric-backbone.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/rfcs/0004-network-profiles.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/rfcs/0006-dynamic-qos.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/rfcs/0007-regression-gate.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/rfcs/README.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/testing.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/docs/work-items.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/install.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/justfile +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/media/control_center.png +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/media/echo_test.png +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/media/forensics-report-example.png +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/media/host.png +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/media/vehicle.png +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/pyproject.toml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/requirements.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/__init__.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/__main__.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/anonymize.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/benched_set.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/benchmark_delta.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/deployment.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/forensics.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/geomap.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/image_cache.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/netem_dist.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/plots.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/py.typed +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/benched-set.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/.gitignore +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/README.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/__init__.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/dist/field-20260817.dist +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/profiles.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ros2docker.json.example +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/cyclonedds_local_participants.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/ffmpeg_flags.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/playout_pacer.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/playout_pacer_core.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/status_eval.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom/video_quality.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom_dev.egg-info/requires.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/terminology.md +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_benched_set_registry.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_findings.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_ota_source_bundle.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_package_metadata.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_profile_covers_generated_commands.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_pytest_policy.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_readme_examples.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_session_configuration_doc.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_session_template_substitution.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/contract/test_workflow_contracts.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/test_anonymize_e2e.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/test_benchmark_ab.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/test_benchmark_capacity.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/test_benchmark_replay.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/test_parallel_smoke.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/test_smoke.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/test_timeline_stepping.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/e2e/test_video_quality_e2e.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_anonymize.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_benched_set.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_benchmark_delta.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_catmux_pane_logging.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_cli.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_concurrency.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_container_shaping.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_deployment.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_ffmpeg_flags.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_field_profiles.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_forensics.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_geomap.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_image_cache.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_link_trace.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_netem_dist.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_playout_pacer.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_plots.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_qos_fallback_logging.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_session_pipeline.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_status_eval.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_status_overview.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_status_overview_observer.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/tests/unit/test_trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev51 → rosotacom_dev-2.5.dev52}/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.
|
|
3
|
+
Version: 2.5.dev52
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -580,6 +580,13 @@ the ssh client's own argv apart, and a transport that promises no more than
|
|
|
580
580
|
`-t` and `-o BatchMode=yes` are dropped rather than forwarded. They are options
|
|
581
581
|
of one client, and a transport that is not ssh never agreed to understand them.
|
|
582
582
|
|
|
583
|
+
The same four options — `--peer-checkout`, `--peer-exec`, `--install-mode`,
|
|
584
|
+
`--install-pin` — are on every `ota-benchmark` genre, not just `ota-smoke`. A
|
|
585
|
+
measurement is the last thing that should require a shell on the peer: the
|
|
586
|
+
whole point of a narrower transport is that the runs which touch a machine
|
|
587
|
+
repeatedly can go through it, and a benchmark touches it far more often than a
|
|
588
|
+
smoke test does.
|
|
589
|
+
|
|
583
590
|
### Live status / debugging overview
|
|
584
591
|
|
|
585
592
|
Enable a continuously-updated, per-topic pipeline overview by setting
|
|
@@ -535,6 +535,13 @@ the ssh client's own argv apart, and a transport that promises no more than
|
|
|
535
535
|
`-t` and `-o BatchMode=yes` are dropped rather than forwarded. They are options
|
|
536
536
|
of one client, and a transport that is not ssh never agreed to understand them.
|
|
537
537
|
|
|
538
|
+
The same four options — `--peer-checkout`, `--peer-exec`, `--install-mode`,
|
|
539
|
+
`--install-pin` — are on every `ota-benchmark` genre, not just `ota-smoke`. A
|
|
540
|
+
measurement is the last thing that should require a shell on the peer: the
|
|
541
|
+
whole point of a narrower transport is that the runs which touch a machine
|
|
542
|
+
repeatedly can go through it, and a benchmark touches it far more often than a
|
|
543
|
+
smoke test does.
|
|
544
|
+
|
|
538
545
|
### Live status / debugging overview
|
|
539
546
|
|
|
540
547
|
Enable a continuously-updated, per-topic pipeline overview by setting
|
|
@@ -28,6 +28,9 @@ living verification hook.
|
|
|
28
28
|
|
|
29
29
|
## Findings
|
|
30
30
|
|
|
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
|
+
- [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
|
+
- [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.
|
|
31
34
|
- [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.
|
|
32
35
|
- [Oversubscription queues — it does not lose until the queue itself dies](oversubscription-queues-not-losses.md) - 16% over an emulated cap climbed one-way delay 340 → 3250 ms across twelve bins with zero loss in every one; the losses arrived only when the queue died, all at once.
|
|
33
36
|
- [Best-effort reordering becomes reader-side loss, independent of history depth](reorder-becomes-reader-loss.md) - under pure delay jitter a Cyclone best-effort reader discards every overtaken sample (57% at 100 Hz under 50+-45 ms), delivery stays strictly monotonic, and depth 50 loses the same as depth 1.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# A Fast DDS Datagram Cap Stops Every Message Larger Than It
|
|
2
|
+
|
|
3
|
+
## Claim
|
|
4
|
+
|
|
5
|
+
Setting `<maxMessageSize>` on a Fast DDS UDPv4 transport to a value below a
|
|
6
|
+
sample's serialized size makes that sample **never arrive** through the OTA
|
|
7
|
+
pipeline — not "arrive fragmented", not "arrive with loss". Messages that fit
|
|
8
|
+
inside the cap keep flowing at full rate on the same link, which is what makes
|
|
9
|
+
this dangerous: an 84 B heartbeat crossing at 10 Hz with 0.0% loss is a link
|
|
10
|
+
that looks alive from every direction except the one that matters.
|
|
11
|
+
|
|
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
|
|
14
|
+
symmetry does not transfer: on ROS 2 Kilted with Fast DDS 3.2.4 the cap is the
|
|
15
|
+
single knob that breaks the link, at 1200 B and at 8192 B, with a synchronous
|
|
16
|
+
writer and with an asynchronous one.
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
|
|
20
|
+
- Host pair / topology: one host, the packaged local smoke rig — two
|
|
21
|
+
communication containers on their own Docker network, split ROS domains
|
|
22
|
+
(peer 50, peer 51, OTA 52) with the stock `domain_bridge` between them. The
|
|
23
|
+
same failure was first seen across two machines over a VPN; one host
|
|
24
|
+
reproduces it, so nothing private is needed.
|
|
25
|
+
- Session: a two-peer session with a `com_msgs/msg/SizedPayload` stream at
|
|
26
|
+
12000 B and 10 Hz on the loaded direction plus the echo heartbeat, OTA QoS
|
|
27
|
+
best_effort / depth 1 / lifespan 0.7 (the deployed shape).
|
|
28
|
+
- rosotacom SHA: measured at `6e4b748`; re-runs record theirs.
|
|
29
|
+
- Profile: none for the bisect — the failure needs no impairment, which is what
|
|
30
|
+
makes it attributable to the configuration rather than to the link.
|
|
31
|
+
- Seed policy: deterministic (no netem, no random load), `n=1` per variant; the
|
|
32
|
+
effect is present/absent, not a distribution.
|
|
33
|
+
|
|
34
|
+
## Evidence
|
|
35
|
+
|
|
36
|
+
Evidence grade: single-host reproduction on packaged material, one variant per
|
|
37
|
+
run, read from the receiving peer's own `status.txt`.
|
|
38
|
+
|
|
39
|
+
Each knob of the tuned profile was added to the working `fastdds_unicast.xml`
|
|
40
|
+
one at a time (2026-08-19):
|
|
41
|
+
|
|
42
|
+
| added to fastdds_unicast.xml | 12 kB stream at the receiver |
|
|
43
|
+
|---|---|
|
|
44
|
+
| interface allowlist (127.0.0.1 + OTA address) | FLOWING 10.0 Hz, 0.0% loss |
|
|
45
|
+
| loopback locators (default / metatraffic / initial peers) | FLOWING 10.0 Hz |
|
|
46
|
+
| `maxInitialPeersRange` 10 | FLOWING 10.0 Hz |
|
|
47
|
+
| discovery lease / announcement | FLOWING 10.0 Hz |
|
|
48
|
+
| socket buffer sizes (1 MB / 4 MB) | FLOWING 10.0 Hz |
|
|
49
|
+
| `non_blocking_send` | FLOWING 10.0 Hz |
|
|
50
|
+
| `publishMode` ASYNCHRONOUS | FLOWING, degraded: 9.3 Hz at 285 ms |
|
|
51
|
+
| **`maxMessageSize` 1200** | **IDLE — nothing delivered** |
|
|
52
|
+
| **`maxMessageSize` 8192** | **IDLE — nothing delivered** |
|
|
53
|
+
| **`maxMessageSize` 1200 + ASYNCHRONOUS** | **IDLE — nothing delivered** |
|
|
54
|
+
|
|
55
|
+
The heartbeat crossed at 10 Hz with 0.0% loss in every one of those runs,
|
|
56
|
+
including the three that delivered no payload at all.
|
|
57
|
+
|
|
58
|
+
Two nearby observations, both of which cost time before the bisect narrowed it:
|
|
59
|
+
|
|
60
|
+
- Two Fast DDS participants in two containers, with the capped profile and
|
|
61
|
+
nothing else running, DO exchange 12 kB and 38 kB samples (57–59 of 60). The
|
|
62
|
+
cap only breaks the full pipeline, where the sample crosses a domain bridge
|
|
63
|
+
and an OTA bridge, so an isolated transport probe will report the cap as
|
|
64
|
+
harmless.
|
|
65
|
+
- Asynchronous publication does not rescue it, which rules out the documented
|
|
66
|
+
"a synchronous writer cannot fragment" explanation as the whole story.
|
|
67
|
+
|
|
68
|
+
Verification: manual: run the packaged smoke for a session whose OTA side names
|
|
69
|
+
`fastdds_tuned.xml`, then again for one that adds `<maxMessageSize>1200` to it,
|
|
70
|
+
and read `logs/<receiver>/status/status.txt`; the payload stage is FLOWING in
|
|
71
|
+
the first and IDLE in the second while the heartbeat is FLOWING in both. The
|
|
72
|
+
shipped profiles are pinned against the cap by
|
|
73
|
+
`tests/unit/test_ota_link_configs.py::test_only_cyclone_caps_the_datagram_and_fast_dds_must_not`.
|
|
74
|
+
|
|
75
|
+
## Status
|
|
76
|
+
|
|
77
|
+
confirmed, 2026-08-19.
|
|
78
|
+
|
|
79
|
+
## Publication notes
|
|
80
|
+
|
|
81
|
+
This is why "the OTA middleware is a configuration choice" needs measuring
|
|
82
|
+
rather than reasoning: the two profiles that look like translations of each
|
|
83
|
+
other are not, and the failure mode of the wrong translation is a link that
|
|
84
|
+
passes a heartbeat check. Consequence for the transport comparison: Fast DDS
|
|
85
|
+
lets IP fragment a large sample here where CycloneDDS sends RTPS fragments, so
|
|
86
|
+
the two differ in what a lost packet costs and in what the tunnel has to
|
|
87
|
+
reassemble — the measured OpenVPN barrier on the operator's path is around
|
|
88
|
+
110 kB per message. Report Fast DDS numbers with that difference stated, not as
|
|
89
|
+
a like-for-like transport swap.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# A Bridge That Learns Types From The Graph Cannot Use A Transport That Does Not Carry The Graph
|
|
2
|
+
|
|
3
|
+
## Claim
|
|
4
|
+
|
|
5
|
+
`PubSubPair` resolved a stage's message type from
|
|
6
|
+
`get_topic_names_and_types()`, so it could only create its endpoints once
|
|
7
|
+
somebody else had created the matching one. On a DDS OTA link that is invisible
|
|
8
|
+
— the remote writer is in the same domain, so the graph knows it. Over the
|
|
9
|
+
zenoh DDS bridge (`rmw.ota: zenoh_ros2dds`) it is a deadlock: the bridge
|
|
10
|
+
creates a subscriber route for a topic only once a **local DDS reader** exists,
|
|
11
|
+
and the reader was waiting for the bridge to route a publisher into the graph.
|
|
12
|
+
Neither ever happens, the payload topic never arrives, and the only trace is one
|
|
13
|
+
word in a log line — `Initialized 1 pair(s). Pending=1`.
|
|
14
|
+
|
|
15
|
+
The heartbeat escapes it because the receiving peer's bridge sees the remote
|
|
16
|
+
liveliness token for it early enough to create the route before the reader is
|
|
17
|
+
needed; the wrapped payload topic does not. So the observable is again a link
|
|
18
|
+
that carries the small topic and silently drops the big one.
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
- Host pair / topology: two machines over a VPN, `rmw.ota: zenoh_ros2dds`
|
|
23
|
+
(local cyclone), split ROS domains, one 12 kB `SizedPayload` stream at 10 Hz
|
|
24
|
+
plus the echo heartbeat.
|
|
25
|
+
- rosotacom SHA: observed at `6e4b748` (before the fix), fixed in `48d84dc`.
|
|
26
|
+
- Profile: the drive-derived loss process; the effect is not a loss effect and
|
|
27
|
+
reproduced identically in both runs under it.
|
|
28
|
+
- Seed policy: not applicable — present/absent, `n=2` runs, both failing the
|
|
29
|
+
same way.
|
|
30
|
+
|
|
31
|
+
## Evidence
|
|
32
|
+
|
|
33
|
+
Evidence grade: two live two-machine runs, read from the receiving peer's node
|
|
34
|
+
logs and from the zenoh bridge's own routing log.
|
|
35
|
+
|
|
36
|
+
Receiving peer, `bridge_in` (2026-08-19):
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
[PubSubPair] Created: sub='/ota/b/heartbeat_b' ...
|
|
40
|
+
[PubSubPair] Created: sub='/ota/b/cam_like/ota_stamped' ...
|
|
41
|
+
[PubSubPair] Initialized: sub='/ota/b/heartbeat_b' type='com_msgs/msg/EchoHeartbeat'
|
|
42
|
+
[bridge_in] Initialized 1 pair(s). Pending=1
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Receiving peer, `zenoh_bridge_ros2dds`, for the whole run:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
routes_mgr: Route Subscriber (Zenoh:ota/b/heartbeat_b -> ROS:/ota/b/heartbeat_b) created
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
— and no such line for `ota/b/cam_like/ota_stamped`, while the sending peer had
|
|
52
|
+
created its publisher route for exactly that key. Delivered payload messages in
|
|
53
|
+
both runs: 0 of ~810 sent.
|
|
54
|
+
|
|
55
|
+
The fix removes the dependency rather than the symptom: every session now writes
|
|
56
|
+
`<peer>/topic_types.yaml` (`<stage topic>: <message type>` for every stage that
|
|
57
|
+
peer takes part in, derived from the same pipeline description the status node
|
|
58
|
+
uses), the bridge and relay nodes read it, and the graph is consulted only for
|
|
59
|
+
what the file does not name.
|
|
60
|
+
|
|
61
|
+
Verification: `python -m pytest -q tests/unit/test_pub_sub_pair_types.py` — a
|
|
62
|
+
pair with a declared type creates its endpoints against an empty graph, a pair
|
|
63
|
+
without one still reads the graph, and a pair with neither stays pending.
|
|
64
|
+
`tests/unit/test_ota_link_configs.py::test_every_peer_gets_the_stage_types_its_bridges_need`
|
|
65
|
+
pins that the file is generated for every peer of every session.
|
|
66
|
+
|
|
67
|
+
## Status
|
|
68
|
+
|
|
69
|
+
confirmed, 2026-08-19.
|
|
70
|
+
|
|
71
|
+
## Publication notes
|
|
72
|
+
|
|
73
|
+
Worth stating in any "the transport is a configuration choice" claim: a
|
|
74
|
+
pipeline can depend on a transport property nobody wrote down — here, that the
|
|
75
|
+
transport propagates the ROS graph and not only the data. DDS does, the zenoh
|
|
76
|
+
DDS bridge does not, and the dependency only shows up as a topic that never
|
|
77
|
+
arrives. The general lesson is that a contract known at generation time should
|
|
78
|
+
be handed to the runtime rather than rediscovered from the runtime, which is
|
|
79
|
+
also what makes bring-up order-independent.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Sender-Side Transit Rows Made A Dead Link Report Zero Loss
|
|
2
|
+
|
|
3
|
+
## Claim
|
|
4
|
+
|
|
5
|
+
`summarize_transit_records` counted `delivered = rows − lost`. Sender-side
|
|
6
|
+
transit rows carry the status `sent` and are written whether or not anything
|
|
7
|
+
arrives, so a topic that the receiving peer never saw at all summarised as
|
|
8
|
+
`delivered == expected`, `loss_pct 0.0` — with the sender's own publication
|
|
9
|
+
cadence reported as the arrival spacing. The most dangerous shape a wrong number
|
|
10
|
+
can take: a link that delivered nothing scored better than one that delivered
|
|
11
|
+
96% of its messages.
|
|
12
|
+
|
|
13
|
+
Delivery is a receiver fact. Rows still `sent` after the join are `unconfirmed`;
|
|
14
|
+
`loss_pct` is `None` when no receiver accounted for the topic at all; and an
|
|
15
|
+
oracle reads that `None` as the worst case rather than as zero.
|
|
16
|
+
|
|
17
|
+
## Setup
|
|
18
|
+
|
|
19
|
+
- Host pair / topology: not a transport property — the summary is a pure
|
|
20
|
+
function of collected records, so the reproduction is a unit test over
|
|
21
|
+
synthetic rows. It was found on a two-machine run whose OTA transport
|
|
22
|
+
delivered nothing.
|
|
23
|
+
- rosotacom SHA: present up to `6e4b748`, fixed in `730ddf5`.
|
|
24
|
+
- Profile: none — the defect is in the accounting, not in the link.
|
|
25
|
+
- Seed policy: not applicable, deterministic.
|
|
26
|
+
|
|
27
|
+
## Evidence
|
|
28
|
+
|
|
29
|
+
Evidence grade: unit-level, deterministic, plus the live run that exposed it.
|
|
30
|
+
|
|
31
|
+
Live (2026-08-19, `rmw.ota: zenoh_ros2dds` over two machines): the sending peer
|
|
32
|
+
wrote 816 `outbound`/`sent` rows, the receiving peer wrote 5 rows and no
|
|
33
|
+
delivery at all. The run's `result.json` reported `delivered 807, expected 807,
|
|
34
|
+
loss_pct 0.0` for that topic, with inter-arrival p05/p95 of 102/104 ms — the
|
|
35
|
+
publisher's own timer, not an arrival distribution. The receiver's `status.txt`
|
|
36
|
+
for the same run said `ota_recv ABSENT/GRAPH pub=0` and `com_in IDLE`.
|
|
37
|
+
|
|
38
|
+
The window mattered as much as the number: this only became reachable when
|
|
39
|
+
sender-side transit rows landed (issue #294). Before that, a topic with no
|
|
40
|
+
receiver rows had no rows at all and simply did not appear.
|
|
41
|
+
|
|
42
|
+
Verification: `python -m pytest -q tests/unit/test_transit.py -k sender_rows`
|
|
43
|
+
— sender rows alone report `delivered 0`, `unconfirmed 3` and `loss_pct None`,
|
|
44
|
+
and a mixed set counts only the receiver's verdicts.
|
|
45
|
+
`tests/unit/test_benchmark.py::test_an_unknown_loss_figure_is_read_as_the_worst_case`
|
|
46
|
+
pins that an oracle does not pass on the `None`.
|
|
47
|
+
|
|
48
|
+
## Status
|
|
49
|
+
|
|
50
|
+
confirmed, 2026-08-19.
|
|
51
|
+
|
|
52
|
+
## Publication notes
|
|
53
|
+
|
|
54
|
+
A measurement pipeline that gains a second observer gains a way to be
|
|
55
|
+
confidently wrong: the new rows were real, the join was correct, and the
|
|
56
|
+
aggregate stopped meaning what its name said. Worth citing whenever a loss
|
|
57
|
+
figure is quoted from an automated run — state which side observed it. The
|
|
58
|
+
general rule the fix encodes: an aggregate over rows from two observers must say
|
|
59
|
+
which observer each row came from before it counts anything.
|
|
@@ -167,8 +167,49 @@ not override `RMW_IMPLEMENTATION` and relies on the ambient ROS 2 defaults — n
|
|
|
167
167
|
Per-side config blocks:
|
|
168
168
|
|
|
169
169
|
- DDS implementations (`cyclone`, `fastdds`) accept:
|
|
170
|
-
- `config: <template>` — template file under `ws/ota_configs/`
|
|
171
|
-
|
|
170
|
+
- `config: <template>` — template file under `ws/ota_configs/`
|
|
171
|
+
(`cyclonedds_tuned.xml`, `cyclonedds_minimal.xml`,
|
|
172
|
+
`cyclonedds_local_participants.xml`, `fastdds_tuned.xml`,
|
|
173
|
+
`fastdds_unicast.xml`, `fastdds_easy_mode.xml`).
|
|
174
|
+
- `easy_mode_ip: <string>` — resolved into a template's `#easy_mode_ip`
|
|
175
|
+
placeholder; defaults to the first resolved peer address. Only
|
|
176
|
+
`fastdds_easy_mode.xml` uses it.
|
|
177
|
+
|
|
178
|
+
`fastdds_easy_mode.xml` is the discovery alternative: Fast DDS 3.1 spawns or
|
|
179
|
+
reuses one Discovery Server per host and points the participant at the peer's
|
|
180
|
+
server too, so two hosts find each other with no multicast and no per-peer
|
|
181
|
+
locator list. It fails differently from `fastdds_tuned.xml` rather than
|
|
182
|
+
better — an explicit peer list cannot discover what it was not told about,
|
|
183
|
+
while easy mode depends on a server process being reachable on 11811 — which
|
|
184
|
+
is why both are packaged. Neither caps the datagram (see above); easy mode
|
|
185
|
+
expresses its transport settings as `<builtinTransports …>` attributes,
|
|
186
|
+
because replacing the transports outright would take its discovery path with
|
|
187
|
+
them.
|
|
188
|
+
|
|
189
|
+
**On the OTA side, omitting `config` is not "no configuration".** Each
|
|
190
|
+
implementation has a default template, and both defaults are the link-ready
|
|
191
|
+
one: `cyclone` → `cyclonedds_tuned.xml`, `fastdds` → `fastdds_tuned.xml`.
|
|
192
|
+
That is what makes `shared.rmw` an interchangeable choice — a session names a
|
|
193
|
+
middleware and gets unicast discovery with the OTA interface pinned either
|
|
194
|
+
way, rather than one middleware that survives a cellular tunnel and one that
|
|
195
|
+
has to be configured into surviving it. `fastdds_unicast.xml` is the earlier,
|
|
196
|
+
locator-only configuration, kept for a run that wants to measure the
|
|
197
|
+
difference.
|
|
198
|
+
|
|
199
|
+
The two defaults are **not** identical in what they put on the wire, and the
|
|
200
|
+
difference is deliberate. CycloneDDS fragments at the RTPS layer (1200 B);
|
|
201
|
+
Fast DDS hands a large sample to the kernel as one datagram and lets IP
|
|
202
|
+
fragment it. Writing the same cap into the Fast DDS profile is the obvious
|
|
203
|
+
move and it takes the link down: measured on the bench pair (2026-08-18/19,
|
|
204
|
+
ROS 2 Kilted, Fast DDS 3.2.4) a `maxMessageSize` below the sample size stops
|
|
205
|
+
the sample from ever arriving — at 1200 B and at 8192 B, synchronous writer
|
|
206
|
+
and asynchronous — while an 84 B heartbeat on the same link keeps flowing.
|
|
207
|
+
Plan the payload accordingly: the measured OpenVPN barrier on this path is
|
|
208
|
+
around 110 kB per message.
|
|
209
|
+
|
|
210
|
+
On the **local** side, omitting `config` really is no configuration: no
|
|
211
|
+
template is applied and no `CYCLONEDDS_URI` / `FASTDDS_DEFAULT_PROFILES_FILE`
|
|
212
|
+
is exported.
|
|
172
213
|
|
|
173
214
|
On the **local** side of a busy machine, set
|
|
174
215
|
`config: cyclonedds_local_participants.xml`. Cyclone allows 33 participants
|
|
@@ -179,10 +220,22 @@ Per-side config blocks:
|
|
|
179
220
|
interface and sets no peer list, because local discovery must keep working.
|
|
180
221
|
The OTA templates are not usable on the local side for exactly that reason.
|
|
181
222
|
- `zenoh_connect_endpoints` (native, OTA side only; `zenoh` is still accepted as a legacy OTA alias) accepts:
|
|
223
|
+
- `transport: tcp|udp` — the inter-host transport between the two routers.
|
|
224
|
+
Default `tcp`. On a lossy link TCP is the wrong choice for a best-effort
|
|
225
|
+
stream: one retransmit stalls everything queued behind it, which turns a
|
|
226
|
+
cellular dip into seconds of latency instead of one lost sample. The
|
|
227
|
+
listening router keeps `tcp/[::]:7447` whatever this is set to, because
|
|
228
|
+
every rmw_zenoh node on that host is a zenoh *client* of it over
|
|
229
|
+
`tcp/localhost:7447`.
|
|
182
230
|
- `main_peer: <peer_key>` — the peer whose zenoh router listens. Defaults to the first peer declared under `peers:`.
|
|
183
231
|
- `main_port: 7447` — listening port. Default `7447`.
|
|
184
232
|
- `zenoh_ros2dds` (bridge) accepts (OTA side only):
|
|
185
|
-
- `transport: udp|tcp` — default `
|
|
233
|
+
- `transport: udp|tcp` — default `tcp`, measured rather than assumed. On the
|
|
234
|
+
bench pair (2026-08-19, the 2026-08-17 drive's loss process, 12 kB at 10 Hz)
|
|
235
|
+
the UDP bridge delivered in one run of five and lost 66% of that one, while
|
|
236
|
+
the TCP bridge delivered in every run at ~1% loss with the lowest median
|
|
237
|
+
latency in the campaign. UDP stays available for a link where TCP's
|
|
238
|
+
head-of-line blocking costs more than its retransmission buys.
|
|
186
239
|
- `main_peer: <peer_key>` — defaults to the first peer.
|
|
187
240
|
- `main_port: 7447` — default `7447`.
|
|
188
241
|
|
|
@@ -227,6 +280,22 @@ topics to/from zenoh. The local graph still speaks DDS, so `rmw.local` must be
|
|
|
227
280
|
- `zen_pub_allow` / `zen_sub_allow` are derived from peer `com-name`s (`/ota/<com-name>/.*`).
|
|
228
281
|
- `zen_qos_pub` is derived from per-topic `zen_qos:` entries and baked into the generated `<peer>/plugin.yaml`.
|
|
229
282
|
|
|
283
|
+
#### Generated per peer: `topic_types.yaml`
|
|
284
|
+
|
|
285
|
+
Every session writes `<peer>/topic_types.yaml` — `<stage topic>: <message
|
|
286
|
+
type>` for every stage that peer takes part in — and the bridge and relay nodes
|
|
287
|
+
read it. It is generated whether or not `use_status_overview` is set, and is
|
|
288
|
+
derived from the same pipeline description the status node uses, so the two
|
|
289
|
+
cannot disagree about what a stage is called.
|
|
290
|
+
|
|
291
|
+
It exists because the alternative was the ROS graph, and the graph makes an
|
|
292
|
+
endpoint's creation depend on somebody else having created the matching one
|
|
293
|
+
first. Over a transport that carries data but not the graph — `rmw.ota:
|
|
294
|
+
zenoh_ros2dds`, where the bridge routes a topic only once a local DDS reader
|
|
295
|
+
exists — that is a deadlock, and a silent one: the receiving peer logs
|
|
296
|
+
`Initialized 1 pair(s). Pending=1` and the topic simply never arrives. The graph
|
|
297
|
+
is still consulted for anything the file does not name.
|
|
298
|
+
|
|
230
299
|
#### Domain bridging
|
|
231
300
|
|
|
232
301
|
If `shared.ota_domain_id` and `peer_settings.<peer>.domain_id` are both set and
|
|
@@ -421,6 +490,21 @@ Each entry is either:
|
|
|
421
490
|
- `expect` (optional mapping); `smoke_probe: false` keeps the topic in the
|
|
422
491
|
generated contract but excludes it from synthetic local-smoke probes
|
|
423
492
|
|
|
493
|
+
Two `expect` keys describe the *synthetic source* rather than the contract,
|
|
494
|
+
for the runs (local smoke, `ota-smoke`, OTA benchmark genres) that drive a
|
|
495
|
+
session with generated traffic instead of a replay:
|
|
496
|
+
|
|
497
|
+
- `smoke_native_hz` — publish the native topic at this rate instead of
|
|
498
|
+
deriving it from the `hz` bounds. Needed wherever the pipeline changes the
|
|
499
|
+
rate (`drop`, `throttle_hz`, `trickle_hz`), because the asserted rate is
|
|
500
|
+
the delivered one and the source has to run faster.
|
|
501
|
+
- `smoke_native_bytes` — the payload size for a
|
|
502
|
+
`com_msgs/msg/SizedPayload` topic (default 66000). The size belongs to the
|
|
503
|
+
load a session wants driven: comparing two OTA middlewares, or two
|
|
504
|
+
profiles, means holding the payload at a chosen size — a 38 kB camera
|
|
505
|
+
keyframe, say — rather than at whatever constant the driver carries. It is
|
|
506
|
+
also what the receiving side asserts, so both ends stay consistent.
|
|
507
|
+
|
|
424
508
|
In split-domain mode the generator must emit a standard ROS 2 `domain_bridge` YAML with explicit
|
|
425
509
|
message types for `/com/...` topics. For that reason, user-defined topic entries need `type:`.
|
|
426
510
|
The auto-generated heartbeat topic is the only exception because its type is known by the generator.
|
|
@@ -191,9 +191,19 @@ def oracle_passes(loss_pct: float, latency_ms: float | None, thresholds: OracleT
|
|
|
191
191
|
return loss_pct <= thresholds.max_loss_pct and latency_ms <= thresholds.max_latency_ms
|
|
192
192
|
|
|
193
193
|
|
|
194
|
+
def _oracle_loss_pct(value: Any) -> float:
|
|
195
|
+
"""A topic's loss for an oracle, with "unknown" read as the worst case.
|
|
196
|
+
|
|
197
|
+
`summarize_transit_records` reports `None` when no receiving peer accounted
|
|
198
|
+
for the topic at all. That is not zero loss; it is no evidence, and an
|
|
199
|
+
oracle that let it pass would turn a dead link into a green run.
|
|
200
|
+
"""
|
|
201
|
+
return 100.0 if value is None else float(value)
|
|
202
|
+
|
|
203
|
+
|
|
194
204
|
def oracle_passes_topic(topic_summary: dict[str, Any], thresholds: OracleThresholds) -> bool:
|
|
195
205
|
"""Apply the oracle to one topic of ``transit.summarize_transit_records`` output."""
|
|
196
|
-
loss_pct =
|
|
206
|
+
loss_pct = _oracle_loss_pct(topic_summary.get("loss_pct", 100.0))
|
|
197
207
|
latency = (topic_summary.get("ota_hop_ms") or {}).get(thresholds.latency_quantile)
|
|
198
208
|
return oracle_passes(loss_pct, None if latency is None else float(latency), thresholds)
|
|
199
209
|
|
|
@@ -323,7 +333,7 @@ def evaluate_bag_run(
|
|
|
323
333
|
lost = data.get("lost")
|
|
324
334
|
reordered = data.get("reordered")
|
|
325
335
|
run_expected = data.get("expected")
|
|
326
|
-
loss_pct =
|
|
336
|
+
loss_pct = _oracle_loss_pct(data.get("loss_pct", 100.0)) if data else 100.0
|
|
327
337
|
latency_p95 = (data.get("ota_hop_ms") or {}).get(quantile) if data else None
|
|
328
338
|
jitter_p95 = (data.get("jitter_ms") or {}).get("p95") if data else None
|
|
329
339
|
latency_val = None if latency_p95 is None else float(latency_p95)
|
|
@@ -3668,8 +3668,18 @@ def _ota_extract_peer_artifacts(instance: SessionInstance, peer: OtaSmokePeer, e
|
|
|
3668
3668
|
extracted = archive.extractfile(member)
|
|
3669
3669
|
if extracted is None:
|
|
3670
3670
|
continue
|
|
3671
|
+
# A peer's own `.session_readonly.yaml` is written 0400 on purpose
|
|
3672
|
+
# ("generated, do not edit"), and a peer that runs on the orchestrator
|
|
3673
|
+
# collects into the very directory it wrote. Replacing the file rather
|
|
3674
|
+
# than opening it for writing keeps both true: the copy lands, and the
|
|
3675
|
+
# mode the peer chose travels with it.
|
|
3676
|
+
if target.exists():
|
|
3677
|
+
target.unlink()
|
|
3671
3678
|
with extracted, target.open("wb") as handle:
|
|
3672
3679
|
shutil.copyfileobj(extracted, handle)
|
|
3680
|
+
mode = member.mode & 0o7777
|
|
3681
|
+
if mode:
|
|
3682
|
+
target.chmod(mode)
|
|
3673
3683
|
except tarfile.TarError:
|
|
3674
3684
|
print(f"OTA smoke: could not unpack collected artifacts from peer {peer.name}", file=sys.stderr)
|
|
3675
3685
|
|
|
@@ -6323,6 +6333,33 @@ def _smoke_publish_rate(expect: Any) -> float:
|
|
|
6323
6333
|
return 5.0
|
|
6324
6334
|
|
|
6325
6335
|
|
|
6336
|
+
#: What a `com_msgs/msg/SizedPayload` smoke stream carries when the session does
|
|
6337
|
+
#: not say. Big enough to fragment on any real link, which is what the packaged
|
|
6338
|
+
#: examples want to exercise.
|
|
6339
|
+
SMOKE_SIZED_PAYLOAD_BYTES = 66000
|
|
6340
|
+
|
|
6341
|
+
|
|
6342
|
+
def _smoke_native_payload_bytes(expect: Any, msg_type: str | None) -> int | None:
|
|
6343
|
+
"""How large the synthetic source's `SizedPayload` messages should be.
|
|
6344
|
+
|
|
6345
|
+
The size is a property of the load a session wants driven, not of the smoke
|
|
6346
|
+
driver, so a session may declare `expect.smoke_native_bytes` — the size
|
|
6347
|
+
sibling of `smoke_native_hz`. Comparing two OTA middlewares means holding
|
|
6348
|
+
the payload at a chosen size (a 38 kB camera keyframe, say) rather than at
|
|
6349
|
+
whatever constant the driver happens to carry.
|
|
6350
|
+
"""
|
|
6351
|
+
if msg_type != "com_msgs/msg/SizedPayload":
|
|
6352
|
+
return None
|
|
6353
|
+
if isinstance(expect, dict):
|
|
6354
|
+
declared = expect.get("smoke_native_bytes")
|
|
6355
|
+
if declared is not None:
|
|
6356
|
+
size = int(declared)
|
|
6357
|
+
if size <= 0:
|
|
6358
|
+
raise RuntimeError("expect.smoke_native_bytes must be a positive number of bytes.")
|
|
6359
|
+
return size
|
|
6360
|
+
return SMOKE_SIZED_PAYLOAD_BYTES
|
|
6361
|
+
|
|
6362
|
+
|
|
6326
6363
|
def _smoke_native_publish_rate(expect: Any) -> float:
|
|
6327
6364
|
"""The rate the synthetic source should publish the NATIVE topic at.
|
|
6328
6365
|
|
|
@@ -6529,7 +6566,7 @@ def _received_crossed_topics(cfg: dict[str, Any], receiver_peer_key: str) -> lis
|
|
|
6529
6566
|
hz_min=expect_hz_min,
|
|
6530
6567
|
hz_max=expect_hz_max,
|
|
6531
6568
|
max_delay_s=expect_max_delay_s,
|
|
6532
|
-
expected_size=
|
|
6569
|
+
expected_size=_smoke_native_payload_bytes(entry.expect, entry.msg_type),
|
|
6533
6570
|
publish_qos=_smoke_publish_qos(entry.qos),
|
|
6534
6571
|
),
|
|
6535
6572
|
]
|
|
@@ -6752,7 +6789,7 @@ def _smoke_topic_pub_qos_args(qos: dict[str, Any] | None) -> str:
|
|
|
6752
6789
|
def _smoke_publisher_command(spec: SmokeTopicSpec, ros_setup: str, duration: float) -> str:
|
|
6753
6790
|
assert spec.publish_topic is not None and spec.publish_type is not None
|
|
6754
6791
|
if spec.publish_type == "com_msgs/msg/SizedPayload":
|
|
6755
|
-
size = spec.expected_size or
|
|
6792
|
+
size = spec.expected_size or SMOKE_SIZED_PAYLOAD_BYTES
|
|
6756
6793
|
return (
|
|
6757
6794
|
f"{ros_setup} && timeout {duration} ros2 run com_py sized_publisher --ros-args "
|
|
6758
6795
|
f"-p topic:={shlex.quote(spec.publish_topic)} -p size:={size} -p rate:={spec.publish_rate}"
|
|
@@ -8550,6 +8587,55 @@ def _add_peer_arg(parser: argparse.ArgumentParser) -> None:
|
|
|
8550
8587
|
cast(Any, action).completer = _peer_host_completer
|
|
8551
8588
|
|
|
8552
8589
|
|
|
8590
|
+
def _add_ota_install_args(parser: argparse.ArgumentParser) -> None:
|
|
8591
|
+
"""How the peers get rosotacom, and how they are reached.
|
|
8592
|
+
|
|
8593
|
+
Shared by `ota-smoke` and every OTA benchmark genre. They were only on
|
|
8594
|
+
`ota-smoke` while the benchmarks were something an operator ran with an ssh
|
|
8595
|
+
key in hand; a run driven by a narrower transport needs the same four
|
|
8596
|
+
options wherever it starts, or the measurement is the one thing that still
|
|
8597
|
+
demands a shell on the peer.
|
|
8598
|
+
"""
|
|
8599
|
+
parser.add_argument(
|
|
8600
|
+
"--peer-checkout",
|
|
8601
|
+
action="append",
|
|
8602
|
+
default=[],
|
|
8603
|
+
metavar="PEER=PATH",
|
|
8604
|
+
help=(
|
|
8605
|
+
"Absolute path of a peer's project checkout, for --install-mode checkout. "
|
|
8606
|
+
"Required for every peer in that mode; the same repository is at a different path on each machine."
|
|
8607
|
+
),
|
|
8608
|
+
)
|
|
8609
|
+
parser.add_argument(
|
|
8610
|
+
"--peer-exec",
|
|
8611
|
+
action="append",
|
|
8612
|
+
default=[],
|
|
8613
|
+
metavar="PEER=COMMAND",
|
|
8614
|
+
help=(
|
|
8615
|
+
"Run this peer's commands through COMMAND instead of ssh; the script is appended as the final "
|
|
8616
|
+
"argument, the same contract ssh has. For --install-mode checkout only, and mutually exclusive "
|
|
8617
|
+
"with --peer-ssh for the same peer. Use it to put a peer behind a transport narrower than a "
|
|
8618
|
+
"shell, such as a forced command that accepts only this project's own commands."
|
|
8619
|
+
),
|
|
8620
|
+
)
|
|
8621
|
+
parser.add_argument(
|
|
8622
|
+
"--install-mode",
|
|
8623
|
+
choices=list(OTA_INSTALL_MODES),
|
|
8624
|
+
default="source",
|
|
8625
|
+
help=(
|
|
8626
|
+
"How the peers get rosotacom. 'source' (default) stages and installs what you are running — "
|
|
8627
|
+
"right while iterating on rosotacom. 'pin' installs a published release from the index, so the "
|
|
8628
|
+
"peers run the artefact that ships — right when rehearsing a deployment. 'checkout' stages and "
|
|
8629
|
+
"installs nothing: each peer uses its own installed rosotacom and its own project checkout "
|
|
8630
|
+
"(see --peer-checkout), so the run tests the machines as git left them."
|
|
8631
|
+
),
|
|
8632
|
+
)
|
|
8633
|
+
parser.add_argument(
|
|
8634
|
+
"--install-pin",
|
|
8635
|
+
help="Version for --install-mode pin (default: the version of the rosotacom you are running).",
|
|
8636
|
+
)
|
|
8637
|
+
|
|
8638
|
+
|
|
8553
8639
|
def _add_peer_ssh_arg(parser: argparse.ArgumentParser) -> None:
|
|
8554
8640
|
action = parser.add_argument(
|
|
8555
8641
|
"--peer-ssh",
|
|
@@ -9109,28 +9195,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
9109
9195
|
_add_peer_arg(ota_smoke_parser)
|
|
9110
9196
|
_add_peer_address_arg(ota_smoke_parser)
|
|
9111
9197
|
_add_peer_ssh_arg(ota_smoke_parser)
|
|
9112
|
-
ota_smoke_parser
|
|
9113
|
-
"--peer-checkout",
|
|
9114
|
-
action="append",
|
|
9115
|
-
default=[],
|
|
9116
|
-
metavar="PEER=PATH",
|
|
9117
|
-
help=(
|
|
9118
|
-
"Absolute path of a peer's project checkout, for --install-mode checkout. "
|
|
9119
|
-
"Required for every peer in that mode; the same repository is at a different path on each machine."
|
|
9120
|
-
),
|
|
9121
|
-
)
|
|
9122
|
-
ota_smoke_parser.add_argument(
|
|
9123
|
-
"--peer-exec",
|
|
9124
|
-
action="append",
|
|
9125
|
-
default=[],
|
|
9126
|
-
metavar="PEER=COMMAND",
|
|
9127
|
-
help=(
|
|
9128
|
-
"Run this peer's commands through COMMAND instead of ssh; the script is appended as the final "
|
|
9129
|
-
"argument, the same contract ssh has. For --install-mode checkout only, and mutually exclusive "
|
|
9130
|
-
"with --peer-ssh for the same peer. Use it to put a peer behind a transport narrower than a "
|
|
9131
|
-
"shell, such as a forced command that accepts only this project's own commands."
|
|
9132
|
-
),
|
|
9133
|
-
)
|
|
9198
|
+
_add_ota_install_args(ota_smoke_parser)
|
|
9134
9199
|
ota_smoke_parser.add_argument("--target-type", choices=["auto", "session", "scenario"], default="auto")
|
|
9135
9200
|
ota_smoke_parser.add_argument("--interactive", action="store_true", help="Open a local control tmux UI.")
|
|
9136
9201
|
ota_smoke_parser.add_argument("--stop", action="store_true", help="Stop an OTA smoke run.")
|
|
@@ -9147,22 +9212,6 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
9147
9212
|
action="store_true",
|
|
9148
9213
|
help="Reuse an already installed rosotacom source tree in the workdir.",
|
|
9149
9214
|
)
|
|
9150
|
-
ota_smoke_parser.add_argument(
|
|
9151
|
-
"--install-mode",
|
|
9152
|
-
choices=list(OTA_INSTALL_MODES),
|
|
9153
|
-
default="source",
|
|
9154
|
-
help=(
|
|
9155
|
-
"How the peers get rosotacom. 'source' (default) stages and installs what you are running — "
|
|
9156
|
-
"right while iterating on rosotacom. 'pin' installs a published release from the index, so the "
|
|
9157
|
-
"peers run the artefact that ships — right when rehearsing a deployment. 'checkout' stages and "
|
|
9158
|
-
"installs nothing: each peer uses its own installed rosotacom and its own project checkout "
|
|
9159
|
-
"(see --peer-checkout), so the run tests the machines as git left them."
|
|
9160
|
-
),
|
|
9161
|
-
)
|
|
9162
|
-
ota_smoke_parser.add_argument(
|
|
9163
|
-
"--install-pin",
|
|
9164
|
-
help="Version for --install-mode pin (default: the version of the rosotacom you are running).",
|
|
9165
|
-
)
|
|
9166
9215
|
ota_smoke_parser.add_argument(
|
|
9167
9216
|
"--keep-workdir",
|
|
9168
9217
|
action="store_true",
|