rosotacom-dev 2.5.dev15__tar.gz → 2.5.dev16__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.dev15 → rosotacom_dev-2.5.dev16}/PKG-INFO +21 -1
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/README.md +20 -0
- rosotacom_dev-2.5.dev16/src/rosotacom/benchmark_delta.py +279 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/cli_benchmark.py +62 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom_dev.egg-info/PKG-INFO +21 -1
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom_dev.egg-info/SOURCES.txt +2 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom_dev.egg-info/scm_file_list.json +2 -0
- rosotacom_dev-2.5.dev16/src/rosotacom_dev.egg-info/scm_version.json +8 -0
- rosotacom_dev-2.5.dev16/tests/unit/test_benchmark_delta.py +172 -0
- rosotacom_dev-2.5.dev15/src/rosotacom_dev.egg-info/scm_version.json +0 -8
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.devcontainer/devcontainer.json.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.devcontainer/re_generate_devcontainer_json.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/CODEOWNERS +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/dependabot.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/workflows/benchmark-calibrate.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/workflows/benchmark-gate.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/workflows/dev-release.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/workflows/image-scan.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/workflows/nightly-e2e.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/workflows/pr-lightweight.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/workflows/pr-merge-gate.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.github/workflows/release.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.pre-commit-config.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/AGENTS.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/CONCURRENCY.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/CONTRIBUTING.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/DEVELOPMENT_PRINCIPLES.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/MANIFEST.in +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/budgets.jsonl +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/calibration/README.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/calibration/capacity-size-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/calibration/probe-loss-nominal-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/calibration/probe-loss-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/calibration/probe-loss-tight-fastdds.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/calibration/probe-loss-tight-zenoh.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/codecov.yml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/deployment-configuration.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/benchmark-ab.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/benchmark-bag-as-load.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/ci.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/ffmpeg-keyframes.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/findings/README.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/findings/delay-alone-no-loss.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/findings/head-of-line-irregularity.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/findings/lighter-message-loss.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/forensics-report.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/geo-link-map.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/github-repository-settings.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/link-trace.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/owner-runbook.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/performance-bands.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/playbooks/README.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/quality-model.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/release-notes/TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/release-notes/v2.1.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/release-notes/v2.2.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/release-notes/v2.3.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/release-notes/v2.4.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/release.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/rfcs/0002-expectation-concepts.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/rfcs/0003-metric-backbone.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/rfcs/0004-network-profiles.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/rfcs/0006-dynamic-qos.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/rfcs/0007-regression-gate.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/rfcs/README.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/testing.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/docs/work-items.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/install.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/justfile +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/media/control_center.png +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/media/echo_test.png +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/media/forensics-report-example.png +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/media/host.png +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/media/vehicle.png +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/pyproject.toml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/requirements.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/run_session_in_container.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/session-configuration.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/__init__.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/__main__.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/anonymize.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/benched_set.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/benchmark.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/cli.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/deployment.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/forensics.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/geomap.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/plots.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/py.typed +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/benched-set.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/.gitignore +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/README.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/__init__.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/profiles.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ros2docker.json.example +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/status_eval.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/transit.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom/video_quality.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom_dev.egg-info/requires.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/stop_session_in_container.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/terminology.md +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_benched_set_registry.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_findings.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_markdown_links.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_ota_source_bundle.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_package_metadata.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_packaged_resources.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_profile_covers_generated_commands.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_pytest_policy.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_readme_examples.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_security_maintenance_config.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_session_configuration_doc.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/contract/test_workflow_contracts.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/conftest.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/test_anonymize_e2e.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/test_benchmark_ab.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/test_benchmark_capacity.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/test_benchmark_replay.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/test_parallel_smoke.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/test_smoke.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/test_timeline_stepping.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/e2e/test_video_quality_e2e.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/sessions/generate_rmw_matrix.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_anonymize.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_benched_set.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_cli.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_concurrency.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_deployment.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_forensics.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_geomap.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_link_trace.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_plots.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_status_eval.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_status_overview.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/tests/unit/test_transit.py +0 -0
- {rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/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.dev16
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -778,6 +778,26 @@ performance bands in `budgets.jsonl` via `rosotacom benchmark compare`, and
|
|
|
778
778
|
bands move only through `rosotacom benchmark ratchet` — see
|
|
779
779
|
[docs/performance-bands.md](docs/performance-bands.md) for the band schema,
|
|
780
780
|
verdicts, and the ratchet workflow (RFC 0007).
|
|
781
|
+
|
|
782
|
+
Two result sets taken in **different environments** — emulated versus a real
|
|
783
|
+
link, or shaped versus unshaped — are compared with `rosotacom benchmark delta`:
|
|
784
|
+
|
|
785
|
+
```bash
|
|
786
|
+
rosotacom benchmark delta emulated/ ota/ \
|
|
787
|
+
--label-reference emulated --label-measured ota \
|
|
788
|
+
--out delta.json --markdown delta.md
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
It pairs runs on genre, profile, RMW and session name, so a row that ran in one
|
|
792
|
+
environment and not the other is reported as unmatched rather than silently
|
|
793
|
+
dropped — "it got faster" and "it did not run" must not look the same. Every
|
|
794
|
+
report is labelled `monitor_only` and carries each side's command and profile
|
|
795
|
+
file, so a table pasted into a paper or an issue can be traced back without the
|
|
796
|
+
directory it came from.
|
|
797
|
+
|
|
798
|
+
It exits 0 whatever the numbers say, and non-zero only when the two sets share
|
|
799
|
+
no rows at all — a delta is an observation to explain, and an exit code would
|
|
800
|
+
turn "explain this" into "re-run until it is quiet".
|
|
781
801
|
For live benchmark probes, `--duration` is the shaped publish window; after that
|
|
782
802
|
rosotacom stops synthetic publishers and waits `--drain-s` seconds before
|
|
783
803
|
tearing down shaping, so delayed in-flight messages are not miscounted as loss.
|
|
@@ -733,6 +733,26 @@ performance bands in `budgets.jsonl` via `rosotacom benchmark compare`, and
|
|
|
733
733
|
bands move only through `rosotacom benchmark ratchet` — see
|
|
734
734
|
[docs/performance-bands.md](docs/performance-bands.md) for the band schema,
|
|
735
735
|
verdicts, and the ratchet workflow (RFC 0007).
|
|
736
|
+
|
|
737
|
+
Two result sets taken in **different environments** — emulated versus a real
|
|
738
|
+
link, or shaped versus unshaped — are compared with `rosotacom benchmark delta`:
|
|
739
|
+
|
|
740
|
+
```bash
|
|
741
|
+
rosotacom benchmark delta emulated/ ota/ \
|
|
742
|
+
--label-reference emulated --label-measured ota \
|
|
743
|
+
--out delta.json --markdown delta.md
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
It pairs runs on genre, profile, RMW and session name, so a row that ran in one
|
|
747
|
+
environment and not the other is reported as unmatched rather than silently
|
|
748
|
+
dropped — "it got faster" and "it did not run" must not look the same. Every
|
|
749
|
+
report is labelled `monitor_only` and carries each side's command and profile
|
|
750
|
+
file, so a table pasted into a paper or an issue can be traced back without the
|
|
751
|
+
directory it came from.
|
|
752
|
+
|
|
753
|
+
It exits 0 whatever the numbers say, and non-zero only when the two sets share
|
|
754
|
+
no rows at all — a delta is an observation to explain, and an exit code would
|
|
755
|
+
turn "explain this" into "re-run until it is quiet".
|
|
736
756
|
For live benchmark probes, `--duration` is the shaped publish window; after that
|
|
737
757
|
rosotacom stops synthetic publishers and waits `--drain-s` seconds before
|
|
738
758
|
tearing down shaping, so delayed in-flight messages are not miscounted as loss.
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Compare two benchmark result sets taken in different environments.
|
|
2
|
+
|
|
3
|
+
The local emulated lanes encode most of the performance truth cheaply and
|
|
4
|
+
deterministically. What they cannot show is **which effects exist only on the
|
|
5
|
+
real link** — cellular variability, VPN/MTU quirks, radio behaviour, real
|
|
6
|
+
cross-traffic — and which are emulation artifacts. Real links stay monitor-only
|
|
7
|
+
by the determinism rule, so the missing piece was never another measurement: it
|
|
8
|
+
was the *comparison* between two sets of the same rows.
|
|
9
|
+
|
|
10
|
+
This is that comparison. It reads two directories (or lists) of `result.json`
|
|
11
|
+
runs, pairs them by what makes a row a row, and reports per-row, per-metric
|
|
12
|
+
deltas as JSON plus a short Markdown summary.
|
|
13
|
+
|
|
14
|
+
Three properties are deliberate, because it is easy to produce numbers that lie:
|
|
15
|
+
|
|
16
|
+
* **Pairing is explicit and refuses to guess.** Rows are matched on genre,
|
|
17
|
+
profile, RMW and session name. A row present on one side only is reported as
|
|
18
|
+
unmatched rather than silently dropped, because "it got faster" and "it did
|
|
19
|
+
not run" must not look the same.
|
|
20
|
+
* **Every report says it is correlational.** The two sets differ in the
|
|
21
|
+
environment *and* in everything the environment drags along; a delta is an
|
|
22
|
+
observation, never a verdict. `monitor_only: true` is in the JSON and the
|
|
23
|
+
first line of the Markdown.
|
|
24
|
+
* **It is self-describing.** Each side carries its rosotacom SHA, profile file,
|
|
25
|
+
and the command that produced it, so a report pasted into a paper or an issue
|
|
26
|
+
can be traced back without the directory it came from.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import json
|
|
32
|
+
from dataclasses import dataclass, field
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
from typing import Any
|
|
35
|
+
|
|
36
|
+
SCHEMA_VERSION = 1
|
|
37
|
+
|
|
38
|
+
#: Numeric leaves under `result` that are worth comparing across environments.
|
|
39
|
+
#: A deny-list rather than an allow-list would drag in ids and counts whose
|
|
40
|
+
#: "delta" means nothing.
|
|
41
|
+
INTERESTING_SUFFIXES = (
|
|
42
|
+
"capacity",
|
|
43
|
+
"latency_ms",
|
|
44
|
+
"latency_p95_ms",
|
|
45
|
+
"loss_pct",
|
|
46
|
+
"rate_hz",
|
|
47
|
+
"mean_payload_bytes",
|
|
48
|
+
"offered_bandwidth_bps",
|
|
49
|
+
"jitter_ms",
|
|
50
|
+
"throughput_bps",
|
|
51
|
+
"delivered",
|
|
52
|
+
"received",
|
|
53
|
+
"published",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass(frozen=True)
|
|
58
|
+
class RowKey:
|
|
59
|
+
"""What makes two runs the same row in different environments."""
|
|
60
|
+
|
|
61
|
+
genre: str
|
|
62
|
+
profile: str
|
|
63
|
+
rmw: str
|
|
64
|
+
session: str
|
|
65
|
+
|
|
66
|
+
def label(self) -> str:
|
|
67
|
+
return f"{self.genre}/{self.profile}/{self.rmw}/{self.session}"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class Run:
|
|
72
|
+
key: RowKey
|
|
73
|
+
metrics: dict[str, float]
|
|
74
|
+
provenance: dict[str, Any] = field(default_factory=dict)
|
|
75
|
+
path: str = ""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _flatten_numbers(value: Any, prefix: str = "") -> dict[str, float]:
|
|
79
|
+
out: dict[str, float] = {}
|
|
80
|
+
if isinstance(value, dict):
|
|
81
|
+
for key, child in value.items():
|
|
82
|
+
out.update(_flatten_numbers(child, f"{prefix}.{key}" if prefix else str(key)))
|
|
83
|
+
elif isinstance(value, bool):
|
|
84
|
+
# Explicitly before the numeric branch: bool is an int in Python, and a
|
|
85
|
+
# "delta" between True and False is a category error dressed as -1.
|
|
86
|
+
return {}
|
|
87
|
+
elif isinstance(value, (int, float)):
|
|
88
|
+
return {prefix: float(value)}
|
|
89
|
+
return out
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def interesting_metrics(result: Any) -> dict[str, float]:
|
|
93
|
+
numbers = _flatten_numbers(result)
|
|
94
|
+
return {
|
|
95
|
+
name: value
|
|
96
|
+
for name, value in numbers.items()
|
|
97
|
+
if any(name == suffix or name.endswith("." + suffix) for suffix in INTERESTING_SUFFIXES)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def load_run(path: Path) -> Run | None:
|
|
102
|
+
"""Read one `result.json`. Returns None when it is not one."""
|
|
103
|
+
try:
|
|
104
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
105
|
+
except (OSError, json.JSONDecodeError):
|
|
106
|
+
return None
|
|
107
|
+
if not isinstance(data, dict) or "genre" not in data:
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
context = data.get("context") or {}
|
|
111
|
+
session = context.get("session") or {}
|
|
112
|
+
profile = context.get("profile") or {}
|
|
113
|
+
rmw = context.get("rmw") or {}
|
|
114
|
+
|
|
115
|
+
key = RowKey(
|
|
116
|
+
genre=str(data.get("genre") or ""),
|
|
117
|
+
profile=str(profile.get("name") or (data.get("configuration") or {}).get("profile") or ""),
|
|
118
|
+
rmw=str(rmw.get("requested") or session.get("rmw") or ""),
|
|
119
|
+
session=str(session.get("name") or ""),
|
|
120
|
+
)
|
|
121
|
+
return Run(
|
|
122
|
+
key=key,
|
|
123
|
+
metrics=interesting_metrics(data.get("result")),
|
|
124
|
+
provenance={
|
|
125
|
+
"created_at": data.get("created_at"),
|
|
126
|
+
"command": context.get("command"),
|
|
127
|
+
"profiles_file": (context.get("paths") or {}).get("profiles_file"),
|
|
128
|
+
"rosotacom_sha": (context.get("versions") or {}).get("rosotacom_sha"),
|
|
129
|
+
"verdict": (data.get("verdict") or {}).get("status"),
|
|
130
|
+
},
|
|
131
|
+
path=str(path),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def collect(paths: list[Path]) -> dict[RowKey, Run]:
|
|
136
|
+
"""Every `result.json` under the given files or directories, by row."""
|
|
137
|
+
found: dict[RowKey, Run] = {}
|
|
138
|
+
for path in paths:
|
|
139
|
+
candidates = [path] if path.is_file() else sorted(path.rglob("result.json"))
|
|
140
|
+
for candidate in candidates:
|
|
141
|
+
run = load_run(candidate)
|
|
142
|
+
if run is None:
|
|
143
|
+
continue
|
|
144
|
+
# Last one wins, and it is the newest by directory ordering — a
|
|
145
|
+
# re-run of a row supersedes it rather than doubling it.
|
|
146
|
+
found[run.key] = run
|
|
147
|
+
return found
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def compare(
|
|
151
|
+
reference: dict[RowKey, Run],
|
|
152
|
+
measured: dict[RowKey, Run],
|
|
153
|
+
*,
|
|
154
|
+
label_reference: str,
|
|
155
|
+
label_measured: str,
|
|
156
|
+
) -> dict[str, Any]:
|
|
157
|
+
rows: list[dict[str, Any]] = []
|
|
158
|
+
for key in sorted(set(reference) & set(measured), key=lambda k: k.label()):
|
|
159
|
+
a, b = reference[key], measured[key]
|
|
160
|
+
metrics = []
|
|
161
|
+
for name in sorted(set(a.metrics) | set(b.metrics)):
|
|
162
|
+
left = a.metrics.get(name)
|
|
163
|
+
right = b.metrics.get(name)
|
|
164
|
+
if left is None or right is None:
|
|
165
|
+
metrics.append(
|
|
166
|
+
{
|
|
167
|
+
"metric": name,
|
|
168
|
+
label_reference: left,
|
|
169
|
+
label_measured: right,
|
|
170
|
+
"delta": None,
|
|
171
|
+
"relative": None,
|
|
172
|
+
"note": "present on one side only",
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
continue
|
|
176
|
+
delta = right - left
|
|
177
|
+
metrics.append(
|
|
178
|
+
{
|
|
179
|
+
"metric": name,
|
|
180
|
+
label_reference: left,
|
|
181
|
+
label_measured: right,
|
|
182
|
+
"delta": delta,
|
|
183
|
+
"relative": (delta / left) if left else None,
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
rows.append(
|
|
187
|
+
{
|
|
188
|
+
"row": key.label(),
|
|
189
|
+
"genre": key.genre,
|
|
190
|
+
"profile": key.profile,
|
|
191
|
+
"rmw": key.rmw,
|
|
192
|
+
"session": key.session,
|
|
193
|
+
"metrics": metrics,
|
|
194
|
+
"provenance": {label_reference: a.provenance, label_measured: b.provenance},
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
"schema_version": SCHEMA_VERSION,
|
|
200
|
+
# First key, and repeated in the Markdown: a delta between two
|
|
201
|
+
# environments is correlational. The two sets differ in the environment
|
|
202
|
+
# and in everything it drags along.
|
|
203
|
+
"monitor_only": True,
|
|
204
|
+
"labels": {"reference": label_reference, "measured": label_measured},
|
|
205
|
+
"rows": rows,
|
|
206
|
+
"unmatched": {
|
|
207
|
+
label_reference: sorted(k.label() for k in set(reference) - set(measured)),
|
|
208
|
+
label_measured: sorted(k.label() for k in set(measured) - set(reference)),
|
|
209
|
+
},
|
|
210
|
+
"counts": {
|
|
211
|
+
"matched": len(rows),
|
|
212
|
+
f"only_{label_reference}": len(set(reference) - set(measured)),
|
|
213
|
+
f"only_{label_measured}": len(set(measured) - set(reference)),
|
|
214
|
+
},
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def render_markdown(report: dict[str, Any]) -> str:
|
|
219
|
+
ref = report["labels"]["reference"]
|
|
220
|
+
mea = report["labels"]["measured"]
|
|
221
|
+
lines = [
|
|
222
|
+
f"# Benchmark delta: {ref} vs {mea}",
|
|
223
|
+
"",
|
|
224
|
+
"**Monitor-only and correlational.** The two sets differ in the environment "
|
|
225
|
+
"and in everything the environment drags along; a delta here is an "
|
|
226
|
+
"observation to explain, never a verdict and never a gate.",
|
|
227
|
+
"",
|
|
228
|
+
f"{report['counts']['matched']} row(s) matched, "
|
|
229
|
+
f"{report['counts'][f'only_{ref}']} only in {ref}, "
|
|
230
|
+
f"{report['counts'][f'only_{mea}']} only in {mea}.",
|
|
231
|
+
"",
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
for row in report["rows"]:
|
|
235
|
+
lines.append(f"## `{row['row']}`")
|
|
236
|
+
lines.append("")
|
|
237
|
+
lines.append(f"| metric | {ref} | {mea} | Δ | Δ% |")
|
|
238
|
+
lines.append("|---|---:|---:|---:|---:|")
|
|
239
|
+
for metric in row["metrics"]:
|
|
240
|
+
left = metric[ref]
|
|
241
|
+
right = metric[mea]
|
|
242
|
+
delta = metric["delta"]
|
|
243
|
+
relative = metric["relative"]
|
|
244
|
+
lines.append(
|
|
245
|
+
f"| `{metric['metric']}` | {_fmt(left)} | {_fmt(right)} | {_fmt(delta, sign=True)} | {_pct(relative)} |"
|
|
246
|
+
)
|
|
247
|
+
lines.append("")
|
|
248
|
+
for side in (ref, mea):
|
|
249
|
+
provenance = row["provenance"][side]
|
|
250
|
+
command = provenance.get("command") or "-"
|
|
251
|
+
lines.append(f"- {side}: `{command}`")
|
|
252
|
+
lines.append("")
|
|
253
|
+
|
|
254
|
+
for side in (ref, mea):
|
|
255
|
+
missing = report["unmatched"][side]
|
|
256
|
+
if missing:
|
|
257
|
+
lines.append(f"## Only in {side}")
|
|
258
|
+
lines.append("")
|
|
259
|
+
lines.extend(f"- `{name}`" for name in missing)
|
|
260
|
+
lines.append("")
|
|
261
|
+
lines.append(
|
|
262
|
+
"A row on one side only is not a delta. It ran in one environment "
|
|
263
|
+
"and not the other, and treating that as an improvement is the "
|
|
264
|
+
"commonest way this kind of report lies."
|
|
265
|
+
)
|
|
266
|
+
lines.append("")
|
|
267
|
+
|
|
268
|
+
return "\n".join(lines)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def _fmt(value: float | None, *, sign: bool = False) -> str:
|
|
272
|
+
if value is None:
|
|
273
|
+
return "—"
|
|
274
|
+
formatted = f"{value:+.4g}" if sign else f"{value:.4g}"
|
|
275
|
+
return formatted
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _pct(value: float | None) -> str:
|
|
279
|
+
return "—" if value is None else f"{value * 100:+.1f}%"
|
|
@@ -4843,6 +4843,56 @@ def _parse_values(raw: str) -> list[float]:
|
|
|
4843
4843
|
# --------------------------------------------------------------------------- #
|
|
4844
4844
|
|
|
4845
4845
|
|
|
4846
|
+
def benchmark_delta(args: argparse.Namespace) -> int:
|
|
4847
|
+
"""`rosotacom benchmark delta` — the cross-environment comparison.
|
|
4848
|
+
|
|
4849
|
+
Exits 0 whenever the comparison itself succeeded, including when rows are
|
|
4850
|
+
unmatched or every metric moved. This is monitor-only by construction
|
|
4851
|
+
(`benchmark_delta.compare` puts `monitor_only: true` first in the report):
|
|
4852
|
+
the number is the deliverable, and an exit code would turn "explain this"
|
|
4853
|
+
into "re-run until it is quiet".
|
|
4854
|
+
|
|
4855
|
+
It exits non-zero for the one thing that is a failure — no rows in common,
|
|
4856
|
+
which means the two sides were not the same rows and the report would be
|
|
4857
|
+
an empty table with a confident heading.
|
|
4858
|
+
"""
|
|
4859
|
+
from . import benchmark_delta as delta_module
|
|
4860
|
+
|
|
4861
|
+
reference = delta_module.collect([Path(args.reference)])
|
|
4862
|
+
measured = delta_module.collect([Path(args.measured)])
|
|
4863
|
+
report = delta_module.compare(
|
|
4864
|
+
reference,
|
|
4865
|
+
measured,
|
|
4866
|
+
label_reference=args.label_reference,
|
|
4867
|
+
label_measured=args.label_measured,
|
|
4868
|
+
)
|
|
4869
|
+
|
|
4870
|
+
if args.out:
|
|
4871
|
+
Path(args.out).write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8")
|
|
4872
|
+
markdown = delta_module.render_markdown(report)
|
|
4873
|
+
if args.markdown:
|
|
4874
|
+
Path(args.markdown).write_text(markdown, encoding="utf-8")
|
|
4875
|
+
else:
|
|
4876
|
+
print(markdown)
|
|
4877
|
+
|
|
4878
|
+
counts = report["counts"]
|
|
4879
|
+
print(
|
|
4880
|
+
f"BENCHMARK DELTA: {counts['matched']} row(s) matched, "
|
|
4881
|
+
f"{counts[f'only_{args.label_reference}']} only in {args.label_reference}, "
|
|
4882
|
+
f"{counts[f'only_{args.label_measured}']} only in {args.label_measured} "
|
|
4883
|
+
"(monitor-only)"
|
|
4884
|
+
)
|
|
4885
|
+
if not report["rows"]:
|
|
4886
|
+
print(
|
|
4887
|
+
"rosotacom: error: the two sets share no rows, so there is nothing to "
|
|
4888
|
+
"compare. Check that both sides ran the same registry rows under the "
|
|
4889
|
+
"same profile and RMW.",
|
|
4890
|
+
file=sys.stderr,
|
|
4891
|
+
)
|
|
4892
|
+
return 1
|
|
4893
|
+
return 0
|
|
4894
|
+
|
|
4895
|
+
|
|
4846
4896
|
def _add_benchmark_common_args(parser: argparse.ArgumentParser, *, ota_benchmark: bool = False) -> None:
|
|
4847
4897
|
from .cli import (
|
|
4848
4898
|
OTA_DEFAULT_SUDO_MODE,
|
|
@@ -8068,6 +8118,18 @@ def _register_benchmark_band_parsers(benchmark_subparsers: Any) -> None:
|
|
|
8068
8118
|
)
|
|
8069
8119
|
compare_parser.set_defaults(func=benchmark_compare)
|
|
8070
8120
|
|
|
8121
|
+
delta_parser = benchmark_subparsers.add_parser(
|
|
8122
|
+
"delta",
|
|
8123
|
+
help="Compare two result.json sets taken in different environments (monitor-only).",
|
|
8124
|
+
)
|
|
8125
|
+
delta_parser.add_argument("reference", help="Directory or result.json for the reference environment.")
|
|
8126
|
+
delta_parser.add_argument("measured", help="Directory or result.json for the measured environment.")
|
|
8127
|
+
delta_parser.add_argument("--label-reference", default="emulated", help="Name for the reference side.")
|
|
8128
|
+
delta_parser.add_argument("--label-measured", default="ota", help="Name for the measured side.")
|
|
8129
|
+
delta_parser.add_argument("--out", default=None, help="Write the JSON report here.")
|
|
8130
|
+
delta_parser.add_argument("--markdown", default=None, help="Write the Markdown summary here.")
|
|
8131
|
+
delta_parser.set_defaults(func=benchmark_delta)
|
|
8132
|
+
|
|
8071
8133
|
ratchet_parser = benchmark_subparsers.add_parser(
|
|
8072
8134
|
"ratchet",
|
|
8073
8135
|
help="Rewrite committed bands from result.json run(s) — bands are never hand-edited.",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rosotacom-dev
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.dev16
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -778,6 +778,26 @@ performance bands in `budgets.jsonl` via `rosotacom benchmark compare`, and
|
|
|
778
778
|
bands move only through `rosotacom benchmark ratchet` — see
|
|
779
779
|
[docs/performance-bands.md](docs/performance-bands.md) for the band schema,
|
|
780
780
|
verdicts, and the ratchet workflow (RFC 0007).
|
|
781
|
+
|
|
782
|
+
Two result sets taken in **different environments** — emulated versus a real
|
|
783
|
+
link, or shaped versus unshaped — are compared with `rosotacom benchmark delta`:
|
|
784
|
+
|
|
785
|
+
```bash
|
|
786
|
+
rosotacom benchmark delta emulated/ ota/ \
|
|
787
|
+
--label-reference emulated --label-measured ota \
|
|
788
|
+
--out delta.json --markdown delta.md
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
It pairs runs on genre, profile, RMW and session name, so a row that ran in one
|
|
792
|
+
environment and not the other is reported as unmatched rather than silently
|
|
793
|
+
dropped — "it got faster" and "it did not run" must not look the same. Every
|
|
794
|
+
report is labelled `monitor_only` and carries each side's command and profile
|
|
795
|
+
file, so a table pasted into a paper or an issue can be traced back without the
|
|
796
|
+
directory it came from.
|
|
797
|
+
|
|
798
|
+
It exits 0 whatever the numbers say, and non-zero only when the two sets share
|
|
799
|
+
no rows at all — a delta is an observation to explain, and an exit code would
|
|
800
|
+
turn "explain this" into "re-run until it is quiet".
|
|
781
801
|
For live benchmark probes, `--duration` is the shaped publish window; after that
|
|
782
802
|
rosotacom stops synthetic publishers and waits `--drain-s` seconds before
|
|
783
803
|
tearing down shaping, so delayed in-flight messages are not miscounted as loss.
|
|
@@ -92,6 +92,7 @@ src/rosotacom/anonymize.py
|
|
|
92
92
|
src/rosotacom/bag_ground_truth.py
|
|
93
93
|
src/rosotacom/benched_set.py
|
|
94
94
|
src/rosotacom/benchmark.py
|
|
95
|
+
src/rosotacom/benchmark_delta.py
|
|
95
96
|
src/rosotacom/bundle_check.py
|
|
96
97
|
src/rosotacom/cli.py
|
|
97
98
|
src/rosotacom/cli_benchmark.py
|
|
@@ -314,6 +315,7 @@ tests/unit/test_anonymize.py
|
|
|
314
315
|
tests/unit/test_bag_ground_truth.py
|
|
315
316
|
tests/unit/test_benched_set.py
|
|
316
317
|
tests/unit/test_benchmark.py
|
|
318
|
+
tests/unit/test_benchmark_delta.py
|
|
317
319
|
tests/unit/test_bundle_check.py
|
|
318
320
|
tests/unit/test_cli.py
|
|
319
321
|
tests/unit/test_cli_benchmark.py
|
{rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/src/rosotacom_dev.egg-info/scm_file_list.json
RENAMED
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"src/rosotacom/bag_ground_truth.py",
|
|
94
94
|
"src/rosotacom/benched_set.py",
|
|
95
95
|
"src/rosotacom/benchmark.py",
|
|
96
|
+
"src/rosotacom/benchmark_delta.py",
|
|
96
97
|
"src/rosotacom/bundle_check.py",
|
|
97
98
|
"src/rosotacom/cli.py",
|
|
98
99
|
"src/rosotacom/cli_benchmark.py",
|
|
@@ -309,6 +310,7 @@
|
|
|
309
310
|
"tests/unit/test_bag_ground_truth.py",
|
|
310
311
|
"tests/unit/test_benched_set.py",
|
|
311
312
|
"tests/unit/test_benchmark.py",
|
|
313
|
+
"tests/unit/test_benchmark_delta.py",
|
|
312
314
|
"tests/unit/test_bundle_check.py",
|
|
313
315
|
"tests/unit/test_cli.py",
|
|
314
316
|
"tests/unit/test_cli_benchmark.py",
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Unit tests for the cross-environment benchmark delta (harness #36).
|
|
2
|
+
|
|
3
|
+
Fixtures, not runs. The point of the tool is what it says when two sets differ,
|
|
4
|
+
and a real pair of environments is the one input that cannot be made to differ
|
|
5
|
+
on purpose.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from rosotacom.benchmark_delta import collect, compare, interesting_metrics, render_markdown
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def write_result(
|
|
17
|
+
directory: Path,
|
|
18
|
+
*,
|
|
19
|
+
genre: str = "capacity",
|
|
20
|
+
profile: str = "cellular-4g-typical",
|
|
21
|
+
rmw: str = "cyclone",
|
|
22
|
+
session: str = "bench_1_1_capacity",
|
|
23
|
+
result: dict | None = None,
|
|
24
|
+
command: str = "rosotacom benchmark capacity",
|
|
25
|
+
) -> Path:
|
|
26
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
27
|
+
payload = {
|
|
28
|
+
"schema_version": 1,
|
|
29
|
+
"genre": genre,
|
|
30
|
+
"created_at": "2026-08-12T09:00:00",
|
|
31
|
+
"context": {
|
|
32
|
+
"command": command,
|
|
33
|
+
"profile": {"name": profile},
|
|
34
|
+
"rmw": {"requested": rmw},
|
|
35
|
+
"session": {"name": session, "rmw": rmw},
|
|
36
|
+
"paths": {"profiles_file": "profiles/benchmark-profiles.yaml"},
|
|
37
|
+
},
|
|
38
|
+
"result": result if result is not None else {"capacity": 43000, "slice": {"loss_pct": 0.5}},
|
|
39
|
+
"verdict": {"passed": True, "status": "capacity_found"},
|
|
40
|
+
}
|
|
41
|
+
path = directory / "result.json"
|
|
42
|
+
path.write_text(json.dumps(payload), encoding="utf-8")
|
|
43
|
+
return path
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_metrics_are_selected_not_swept_up() -> None:
|
|
47
|
+
metrics = interesting_metrics(
|
|
48
|
+
{
|
|
49
|
+
"capacity": 43000,
|
|
50
|
+
"slice": {"loss_pct": 0.5, "knob": "size"},
|
|
51
|
+
"run_id": 17,
|
|
52
|
+
"passed": True,
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
assert metrics == {"capacity": 43000.0, "slice.loss_pct": 0.5}
|
|
56
|
+
assert "run_id" not in metrics, "an id's delta means nothing"
|
|
57
|
+
assert "passed" not in metrics, "a bool delta is a category error dressed as -1"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_matching_rows_produce_a_delta(tmp_path: Path) -> None:
|
|
61
|
+
write_result(tmp_path / "emu" / "run1", result={"capacity": 43000, "slice": {"loss_pct": 0.5}})
|
|
62
|
+
write_result(tmp_path / "ota" / "run1", result={"capacity": 21000, "slice": {"loss_pct": 2.0}})
|
|
63
|
+
|
|
64
|
+
report = compare(
|
|
65
|
+
collect([tmp_path / "emu"]),
|
|
66
|
+
collect([tmp_path / "ota"]),
|
|
67
|
+
label_reference="emulated",
|
|
68
|
+
label_measured="ota",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
assert report["counts"]["matched"] == 1
|
|
72
|
+
metrics = {m["metric"]: m for m in report["rows"][0]["metrics"]}
|
|
73
|
+
assert metrics["capacity"]["delta"] == -22000
|
|
74
|
+
assert metrics["capacity"]["relative"] < 0
|
|
75
|
+
assert metrics["slice.loss_pct"]["delta"] == 1.5
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_a_row_on_one_side_only_is_never_a_delta(tmp_path: Path) -> None:
|
|
79
|
+
""" "It got faster" and "it did not run" must not look the same."""
|
|
80
|
+
write_result(tmp_path / "emu" / "a", session="row_a")
|
|
81
|
+
write_result(tmp_path / "emu" / "b", session="row_b")
|
|
82
|
+
write_result(tmp_path / "ota" / "a", session="row_a")
|
|
83
|
+
|
|
84
|
+
report = compare(
|
|
85
|
+
collect([tmp_path / "emu"]),
|
|
86
|
+
collect([tmp_path / "ota"]),
|
|
87
|
+
label_reference="emulated",
|
|
88
|
+
label_measured="ota",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
assert report["counts"]["matched"] == 1
|
|
92
|
+
assert report["counts"]["only_emulated"] == 1
|
|
93
|
+
assert any("row_b" in name for name in report["unmatched"]["emulated"])
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_rows_differing_only_in_profile_do_not_pair(tmp_path: Path) -> None:
|
|
97
|
+
"""A tight profile is not a delta against a nominal one."""
|
|
98
|
+
write_result(tmp_path / "emu" / "a", profile="cellular-4g-typical")
|
|
99
|
+
write_result(tmp_path / "ota" / "a", profile="cellular-4g-degraded")
|
|
100
|
+
|
|
101
|
+
report = compare(
|
|
102
|
+
collect([tmp_path / "emu"]),
|
|
103
|
+
collect([tmp_path / "ota"]),
|
|
104
|
+
label_reference="emulated",
|
|
105
|
+
label_measured="ota",
|
|
106
|
+
)
|
|
107
|
+
assert report["counts"]["matched"] == 0
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_rows_differing_only_in_rmw_do_not_pair(tmp_path: Path) -> None:
|
|
111
|
+
write_result(tmp_path / "emu" / "a", rmw="cyclone")
|
|
112
|
+
write_result(tmp_path / "ota" / "a", rmw="fastdds")
|
|
113
|
+
|
|
114
|
+
report = compare(
|
|
115
|
+
collect([tmp_path / "emu"]),
|
|
116
|
+
collect([tmp_path / "ota"]),
|
|
117
|
+
label_reference="emulated",
|
|
118
|
+
label_measured="ota",
|
|
119
|
+
)
|
|
120
|
+
assert report["counts"]["matched"] == 0
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_the_report_says_it_is_monitor_only(tmp_path: Path) -> None:
|
|
124
|
+
write_result(tmp_path / "emu" / "a")
|
|
125
|
+
write_result(tmp_path / "ota" / "a")
|
|
126
|
+
report = compare(
|
|
127
|
+
collect([tmp_path / "emu"]),
|
|
128
|
+
collect([tmp_path / "ota"]),
|
|
129
|
+
label_reference="emulated",
|
|
130
|
+
label_measured="ota",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
assert report["monitor_only"] is True
|
|
134
|
+
markdown = render_markdown(report)
|
|
135
|
+
assert "Monitor-only" in markdown.splitlines()[2]
|
|
136
|
+
assert "never a verdict" in markdown
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def test_the_report_carries_its_own_provenance(tmp_path: Path) -> None:
|
|
140
|
+
write_result(tmp_path / "emu" / "a", command="rosotacom benchmark capacity --profile nominal")
|
|
141
|
+
write_result(tmp_path / "ota" / "a", command="rosotacom ota-benchmark row --row s3")
|
|
142
|
+
report = compare(
|
|
143
|
+
collect([tmp_path / "emu"]),
|
|
144
|
+
collect([tmp_path / "ota"]),
|
|
145
|
+
label_reference="emulated",
|
|
146
|
+
label_measured="ota",
|
|
147
|
+
)
|
|
148
|
+
markdown = render_markdown(report)
|
|
149
|
+
assert "--profile nominal" in markdown
|
|
150
|
+
assert "ota-benchmark row --row s3" in markdown
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def test_a_metric_present_on_one_side_only_is_flagged(tmp_path: Path) -> None:
|
|
154
|
+
write_result(tmp_path / "emu" / "a", result={"capacity": 1000, "slice": {"loss_pct": 0.0}})
|
|
155
|
+
write_result(tmp_path / "ota" / "a", result={"capacity": 900})
|
|
156
|
+
report = compare(
|
|
157
|
+
collect([tmp_path / "emu"]),
|
|
158
|
+
collect([tmp_path / "ota"]),
|
|
159
|
+
label_reference="emulated",
|
|
160
|
+
label_measured="ota",
|
|
161
|
+
)
|
|
162
|
+
metrics = {m["metric"]: m for m in report["rows"][0]["metrics"]}
|
|
163
|
+
assert metrics["slice.loss_pct"]["delta"] is None
|
|
164
|
+
assert metrics["slice.loss_pct"]["note"] == "present on one side only"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_non_result_json_files_are_ignored(tmp_path: Path) -> None:
|
|
168
|
+
write_result(tmp_path / "emu" / "a")
|
|
169
|
+
(tmp_path / "emu" / "noise").mkdir()
|
|
170
|
+
(tmp_path / "emu" / "noise" / "result.json").write_text('{"not": "a benchmark"}', encoding="utf-8")
|
|
171
|
+
|
|
172
|
+
assert len(collect([tmp_path / "emu"])) == 1
|
{rosotacom_dev-2.5.dev15 → rosotacom_dev-2.5.dev16}/.devcontainer/devcontainer.json.template
RENAMED
|
File without changes
|