rosotacom-dev 2.5.dev67__tar.gz → 2.5.dev69__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.dev67 → rosotacom_dev-2.5.dev69}/PKG-INFO +3 -2
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/README.md +2 -1
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/ota-pcap.md +19 -3
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/ota_pcap.py +66 -8
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +32 -1
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/PKG-INFO +3 -2
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/SOURCES.txt +1 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/scm_file_list.json +1 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/scm_version.json +2 -2
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/terminology.md +54 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_ota_pcap.py +49 -0
- rosotacom_dev-2.5.dev69/tests/unit/test_terminology_stage_ownership.py +103 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.devcontainer/devcontainer.json.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.devcontainer/re_generate_devcontainer_json.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/CODEOWNERS +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/actions/setup-just/action.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/dependabot.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/benchmark-calibrate.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/benchmark-gate.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/dev-release.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/image-scan.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/nightly-e2e.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/pr-lightweight.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/pr-merge-gate.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/release.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.pre-commit-config.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/AGENTS.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/CONCURRENCY.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/CONTRIBUTING.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/DEVELOPMENT_PRINCIPLES.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/MANIFEST.in +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/budgets.jsonl +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/README.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/capacity-size-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-nominal-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-tight-fastdds.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-tight-zenoh.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/codecov.yml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/deployment-configuration.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/benchmark-ab.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/benchmark-bag-as-load.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/ci.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/ffmpeg-keyframes.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/README.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/a-transport-element-doubles-every-fastdds-sample.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/cyclone-fragment-equal-to-max-drops-fragmented-samples.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/delay-alone-no-loss.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/fastdds-datagram-cap-drops-large-samples.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/graph-derived-types-block-a-non-graph-transport.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/head-of-line-irregularity.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/keyframe-loss-kills-the-next-deltas.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/lifespan-is-enforced-by-one-reader-and-not-the-other.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/lighter-message-loss.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/one-domain-two-cyclone-configs-stop-interoperating.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/oversubscription-queues-not-losses.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/reorder-becomes-reader-loss.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/repro/decode_chain_repro.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/repro/reorder_drop_repro.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/sender-rows-make-a-dead-link-look-loss-free.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/forensics-report.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/geo-link-map.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/github-repository-settings.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/link-bandwidth.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/link-trace.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/owner-runbook.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/performance-bands.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/playbooks/README.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/quality-model.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/release-notes/TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/release-notes/v2.1.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/release-notes/v2.2.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/release-notes/v2.3.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/release-notes/v2.4.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/release.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/rfcs/0002-expectation-concepts.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/rfcs/0003-metric-backbone.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/rfcs/0004-network-profiles.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/rfcs/0006-dynamic-qos.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/rfcs/0007-regression-gate.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/rfcs/README.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/testing.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/work-items.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/install.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/justfile +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/media/control_center.png +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/media/echo_test.png +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/media/forensics-report-example.png +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/media/host.png +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/media/vehicle.png +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/pyproject.toml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/requirements.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/session-configuration.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/__init__.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/__main__.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/anonymize.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/benched_set.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/benchmark.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/benchmark_delta.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/cli.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/deployment.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/forensics.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/geomap.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/image_cache.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/netem_dist.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/network_preflight.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/plots.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/py.typed +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/benched-set.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/.gitignore +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/README.md +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/__init__.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/dist/field-20260817.dist +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/profiles.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/ros2docker.lyrical.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.lyrical.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.lyrical.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ros2docker.json.example +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ros2docker.lyrical.json.example +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/cyclonedds_local_participants.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/cyclonedds_scoped.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/fastdds_easy_mode.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/fastdds_local.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/fastdds_tuned.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/ffmpeg_flags.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/playout_pacer.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/playout_pacer_core.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/status_eval.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/transit.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom/video_quality.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/requires.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_benched_set_registry.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_findings.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_generated_topics_have_a_producer.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_lyrical_runtime_compat.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_markdown_links.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_ota_source_bundle.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_package_metadata.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_packaged_resources.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_profile_covers_generated_commands.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_pytest_policy.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_readme_examples.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_security_maintenance_config.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_session_configuration_doc.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_session_template_substitution.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/contract/test_workflow_contracts.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/conftest.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/test_anonymize_e2e.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/test_benchmark_ab.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/test_benchmark_capacity.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/test_benchmark_replay.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/test_parallel_smoke.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/test_smoke.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/test_timeline_stepping.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/e2e/test_video_quality_e2e.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/sessions/generate_rmw_matrix.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/sessions/rmw_matrix/1_heartbeat_fastdds-default/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_anonymize.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_benched_set.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_benchmark_delta.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_catmux_pane_logging.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_cli.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_concurrency.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_container_shaping.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_deployment.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_ffmpeg_flags.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_field_profiles.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_forensics.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_geomap.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_image_cache.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_link_trace.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_netem_dist.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_network_preflight.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_ota_link_configs.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_playout_pacer.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_plots.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_pub_sub_pair_types.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_qos_fallback_logging.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_relay_optional_parameters.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_ros_node_entity_ownership.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_session_pipeline.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_status_eval.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_status_overview.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_status_overview_observer.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/tests/unit/test_transit.py +0 -0
- {rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/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.dev69
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -689,7 +689,8 @@ is which fragment was lost, whether a retransmit followed, or how one sample's
|
|
|
689
689
|
sub-messages were spaced, enable the [header-only OTA capture](docs/ota-pcap.md)
|
|
690
690
|
next to them — `shared.ota_pcap.enabled`, off by default, roughly 1 % of payload
|
|
691
691
|
volume, and every packet labelled uplink or downlink. It needs no capability,
|
|
692
|
-
no image change and no extra container
|
|
692
|
+
no image change and no extra container — only the passwordless sudo the
|
|
693
|
+
container already has, and only until its socket is open.
|
|
693
694
|
|
|
694
695
|
Convert a recorded link trace into a profiles-file entry when you want to replay
|
|
695
696
|
the same drive conditions in a repeatable benchmark:
|
|
@@ -644,7 +644,8 @@ is which fragment was lost, whether a retransmit followed, or how one sample's
|
|
|
644
644
|
sub-messages were spaced, enable the [header-only OTA capture](docs/ota-pcap.md)
|
|
645
645
|
next to them — `shared.ota_pcap.enabled`, off by default, roughly 1 % of payload
|
|
646
646
|
volume, and every packet labelled uplink or downlink. It needs no capability,
|
|
647
|
-
no image change and no extra container
|
|
647
|
+
no image change and no extra container — only the passwordless sudo the
|
|
648
|
+
container already has, and only until its socket is open.
|
|
648
649
|
|
|
649
650
|
Convert a recorded link trace into a profiles-file entry when you want to replay
|
|
650
651
|
the same drive conditions in a repeatable benchmark:
|
|
@@ -110,9 +110,25 @@ runs on. `shared.ota_pcap.enabled` therefore requires
|
|
|
110
110
|
|
|
111
111
|
## Privilege, containers, and what the option costs
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
`
|
|
115
|
-
|
|
113
|
+
No image change, no rebuild, no added capability and no extra container in
|
|
114
|
+
`docker ps`. What it does need is `sudo`, and only until the socket is open.
|
|
115
|
+
|
|
116
|
+
ros2docker's entrypoint runs this container's processes as `containeruser`,
|
|
117
|
+
whose `CapEff` is `0000000000000000`. A non-root process cannot open an
|
|
118
|
+
`AF_PACKET` socket however the container was started, so `--cap-add NET_RAW`
|
|
119
|
+
would buy nothing. `containeruser` does have passwordless sudo here — the NET
|
|
120
|
+
pane's `sudo iftop` already depends on it — so the capture is launched through
|
|
121
|
+
it, and `--drop-to` hands the process back to `containeruser` the moment the
|
|
122
|
+
socket exists. The pcap therefore belongs to the same user as
|
|
123
|
+
`link_trace.jsonl` beside it, rather than to root.
|
|
124
|
+
|
|
125
|
+
Two earlier attempts at this assumed root from a `docker run` that bypassed the
|
|
126
|
+
entrypoint, and were wrong in the same way both times. If you change this,
|
|
127
|
+
check the **running** container:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
docker exec <com-container> bash -lc 'id; grep CapEff /proc/self/status'
|
|
131
|
+
```
|
|
116
132
|
|
|
117
133
|
`CAP_NET_ADMIN` is *not* taken and is not needed: it buys promiscuous mode,
|
|
118
134
|
which this capture deliberately does not use. Everything of interest is
|
|
@@ -35,9 +35,22 @@ to a 6 Mbit/s link and survived a field session (#267). A capture that has to
|
|
|
35
35
|
re-derive link knowledge is in the wrong place; this one asks the same
|
|
36
36
|
resolution the status snapshot's own link block uses.
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
WHAT IT NEEDS, MEASURED RATHER THAN ASSUMED
|
|
39
|
+
-------------------------------------------
|
|
40
|
+
`sudo`, and only until the socket is open. ros2docker's entrypoint runs this
|
|
41
|
+
container's processes as `containeruser`, whose `CapEff` is
|
|
42
|
+
0000000000000000 — a non-root process cannot open an `AF_PACKET` socket
|
|
43
|
+
however the container was started, so `--cap-add` buys nothing. `containeruser`
|
|
44
|
+
does have passwordless sudo here, which the NET pane's `sudo iftop` already
|
|
45
|
+
relies on, so the capture is launched through it and `--drop-to` hands the
|
|
46
|
+
process back to `containeruser` the moment the socket exists. The pcap in
|
|
47
|
+
`logs/<peer>/status/` therefore belongs to the same user as `link_trace.jsonl`
|
|
48
|
+
beside it.
|
|
49
|
+
|
|
50
|
+
That is the whole cost: no image change, no rebuild, no added capability and no
|
|
51
|
+
extra container. Two earlier attempts at this assumed root from a `docker run`
|
|
52
|
+
that bypassed the entrypoint, and both were wrong in the same way — check the
|
|
53
|
+
*running* container, not the image.
|
|
41
54
|
|
|
42
55
|
THE FILE
|
|
43
56
|
--------
|
|
@@ -72,6 +85,7 @@ from __future__ import annotations
|
|
|
72
85
|
|
|
73
86
|
import argparse
|
|
74
87
|
import json
|
|
88
|
+
import os
|
|
75
89
|
import signal
|
|
76
90
|
import socket
|
|
77
91
|
import struct
|
|
@@ -240,6 +254,40 @@ def open_socket(iface: str) -> socket.socket:
|
|
|
240
254
|
return sock
|
|
241
255
|
|
|
242
256
|
|
|
257
|
+
def drop_privileges(spec: str | None) -> str | None:
|
|
258
|
+
"""Hand the process back to the user that started it.
|
|
259
|
+
|
|
260
|
+
The capture is launched through `sudo` — see the module header — because a
|
|
261
|
+
non-root process cannot open an `AF_PACKET` socket. Nothing after that call
|
|
262
|
+
needs root, and the artifacts in `logs/<peer>/status/` belong to
|
|
263
|
+
`containeruser` like `link_trace.jsonl` beside them: a root-owned file in
|
|
264
|
+
that directory is a `sudo rm` waiting to happen months later, and
|
|
265
|
+
`gather_drive.py` would copy it without noticing.
|
|
266
|
+
|
|
267
|
+
`spec` is "uid:gid". An argument rather than an environment variable
|
|
268
|
+
because sudo does not pass the environment through. Returns what it did, or
|
|
269
|
+
None when there was nothing to do.
|
|
270
|
+
"""
|
|
271
|
+
if not spec:
|
|
272
|
+
return None
|
|
273
|
+
try:
|
|
274
|
+
uid_text, _, gid_text = spec.partition(":")
|
|
275
|
+
uid, gid = int(uid_text), int(gid_text or uid_text)
|
|
276
|
+
except ValueError:
|
|
277
|
+
log(f"WARN --drop-to {spec!r} is not uid:gid — staying as I am")
|
|
278
|
+
return None
|
|
279
|
+
if os.geteuid() != 0:
|
|
280
|
+
return None
|
|
281
|
+
try:
|
|
282
|
+
os.setgroups([])
|
|
283
|
+
os.setgid(gid)
|
|
284
|
+
os.setuid(uid)
|
|
285
|
+
except OSError as error:
|
|
286
|
+
log(f"WARN could not drop to {uid}:{gid} ({error}) — the file will be root's")
|
|
287
|
+
return None
|
|
288
|
+
return f"{uid}:{gid}"
|
|
289
|
+
|
|
290
|
+
|
|
243
291
|
def kernel_timestamp(ancdata) -> tuple[int, int] | None:
|
|
244
292
|
"""(seconds, microseconds) out of SCM_TIMESTAMPNS, if the kernel sent it."""
|
|
245
293
|
for level, kind, data in ancdata:
|
|
@@ -264,7 +312,9 @@ class Capture:
|
|
|
264
312
|
"""One pcap file, and the counts needed to trust it."""
|
|
265
313
|
|
|
266
314
|
def __init__(self, iface: str, out: Path, *, snaplen: int = DEFAULT_SNAPLEN,
|
|
267
|
-
peer: str | None = None, max_bytes: int = DEFAULT_MAX_MB * 1000 * 1000
|
|
315
|
+
peer: str | None = None, max_bytes: int = DEFAULT_MAX_MB * 1000 * 1000,
|
|
316
|
+
drop_to: str | None = None):
|
|
317
|
+
self.drop_to = drop_to
|
|
268
318
|
self.iface = iface
|
|
269
319
|
self.out = out
|
|
270
320
|
self.snaplen = snaplen
|
|
@@ -300,6 +350,10 @@ class Capture:
|
|
|
300
350
|
|
|
301
351
|
def run(self, stop: list) -> None:
|
|
302
352
|
sock = open_socket(self.iface)
|
|
353
|
+
# Root was needed for that one call and for nothing after it.
|
|
354
|
+
dropped = drop_privileges(self.drop_to)
|
|
355
|
+
if dropped:
|
|
356
|
+
log(f"privileges dropped to {dropped}; the socket stays open")
|
|
303
357
|
packet_statistics(sock) # zero the counters; the run owns them from here
|
|
304
358
|
ancillary = socket.CMSG_SPACE(16)
|
|
305
359
|
self.out.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -365,10 +419,13 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
365
419
|
parser.add_argument("--peer", help="keep only packets to or from this address")
|
|
366
420
|
parser.add_argument("--max-mb", type=int, default=DEFAULT_MAX_MB,
|
|
367
421
|
help=f"stop after this many MB (default {DEFAULT_MAX_MB})")
|
|
422
|
+
parser.add_argument("--drop-to", metavar="UID:GID",
|
|
423
|
+
help="give root back once the socket is open, so the pcap "
|
|
424
|
+
"belongs to the user that started the session")
|
|
368
425
|
args = parser.parse_args(argv)
|
|
369
426
|
|
|
370
427
|
capture = Capture(args.iface, args.out, snaplen=args.snaplen, peer=args.peer,
|
|
371
|
-
max_bytes=args.max_mb * 1000 * 1000)
|
|
428
|
+
max_bytes=args.max_mb * 1000 * 1000, drop_to=args.drop_to)
|
|
372
429
|
|
|
373
430
|
stop: list = []
|
|
374
431
|
for name in (signal.SIGINT, signal.SIGTERM):
|
|
@@ -379,9 +436,10 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
379
436
|
try:
|
|
380
437
|
capture.run(stop)
|
|
381
438
|
except PermissionError:
|
|
382
|
-
log("FAIL no permission to open a packet socket.
|
|
383
|
-
"
|
|
384
|
-
"
|
|
439
|
+
log("FAIL no permission to open a packet socket. This is meant to run "
|
|
440
|
+
"through `sudo` from inside the communication container, where "
|
|
441
|
+
"containeruser has passwordless sudo; a non-root process cannot "
|
|
442
|
+
"open AF_PACKET whatever capabilities the container was given.")
|
|
385
443
|
return 3
|
|
386
444
|
except OSError as error:
|
|
387
445
|
log(f"FAIL {error}")
|
|
@@ -564,6 +564,9 @@ class StatusOverview(Node):
|
|
|
564
564
|
"--out", path,
|
|
565
565
|
"--snaplen", str(int(self.get_parameter("ota_pcap_snaplen").value)),
|
|
566
566
|
"--max-mb", str(int(self.get_parameter("ota_pcap_max_mb").value)),
|
|
567
|
+
# Root opens the socket; this hands it straight back, so the pcap
|
|
568
|
+
# belongs to the same user as link_trace.jsonl beside it.
|
|
569
|
+
"--drop-to", f"{os.getuid()}:{os.getgid()}",
|
|
567
570
|
]
|
|
568
571
|
# Narrowed to the remote peer by default. On a VPN tunnel the whole
|
|
569
572
|
# device is the link and the filter changes nothing; on a LAN port it
|
|
@@ -573,6 +576,16 @@ class StatusOverview(Node):
|
|
|
573
576
|
if bool(self.get_parameter("ota_pcap_peer_filter").value) and peer_ip:
|
|
574
577
|
argv += ["--peer", peer_ip]
|
|
575
578
|
|
|
579
|
+
# An `AF_PACKET` socket needs root, and this node is `containeruser`:
|
|
580
|
+
# its `CapEff` is zero, so no `--cap-add` on the container would help.
|
|
581
|
+
# `containeruser` has passwordless sudo here — the NET pane's
|
|
582
|
+
# `sudo iftop` already depends on it — so the capture goes through it
|
|
583
|
+
# and gives root back as soon as the socket exists. Where there is no
|
|
584
|
+
# sudo (this module run somewhere else, or already as root) the plain
|
|
585
|
+
# command is tried instead rather than refused.
|
|
586
|
+
if os.geteuid() != 0 and self._sudo_available():
|
|
587
|
+
argv = ["sudo", "-n", *argv]
|
|
588
|
+
|
|
576
589
|
try:
|
|
577
590
|
self._pcap = subprocess.Popen(argv, start_new_session=True)
|
|
578
591
|
except OSError as exc: # noqa: BLE001 - a sidecar may not stop a session
|
|
@@ -588,6 +601,16 @@ class StatusOverview(Node):
|
|
|
588
601
|
bool(self.get_parameter("ota_pcap_peer_filter").value) else "")
|
|
589
602
|
)
|
|
590
603
|
|
|
604
|
+
@staticmethod
|
|
605
|
+
def _sudo_available() -> bool:
|
|
606
|
+
"""Can this process become root without being asked for a password?"""
|
|
607
|
+
try:
|
|
608
|
+
return subprocess.run(
|
|
609
|
+
["sudo", "-n", "true"], capture_output=True, timeout=5.0
|
|
610
|
+
).returncode == 0
|
|
611
|
+
except (OSError, subprocess.SubprocessError):
|
|
612
|
+
return False
|
|
613
|
+
|
|
591
614
|
def _stop_ota_pcap(self) -> None:
|
|
592
615
|
"""SIGINT and wait, so the sidecar JSON and the drop counts are written.
|
|
593
616
|
|
|
@@ -599,7 +622,15 @@ class StatusOverview(Node):
|
|
|
599
622
|
if child is None or child.poll() is not None:
|
|
600
623
|
return
|
|
601
624
|
try:
|
|
602
|
-
child
|
|
625
|
+
# Through sudo the child is root, so an ordinary kill would be
|
|
626
|
+
# refused; `sudo -n kill` is how a non-root parent signals it.
|
|
627
|
+
# SIGINT and not SIGTERM, because SIGINT is what makes the capture
|
|
628
|
+
# write ota.json on the way out.
|
|
629
|
+
if os.geteuid() != 0:
|
|
630
|
+
subprocess.run(["sudo", "-n", "kill", "-INT", str(child.pid)],
|
|
631
|
+
capture_output=True, timeout=5.0)
|
|
632
|
+
else:
|
|
633
|
+
child.send_signal(signal.SIGINT)
|
|
603
634
|
child.wait(timeout=20.0)
|
|
604
635
|
except subprocess.TimeoutExpired:
|
|
605
636
|
child.kill()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rosotacom-dev
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.dev69
|
|
4
4
|
Summary: Host CLI for ROS OTA communication sessions.
|
|
5
5
|
Author: develNor
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -689,7 +689,8 @@ is which fragment was lost, whether a retransmit followed, or how one sample's
|
|
|
689
689
|
sub-messages were spaced, enable the [header-only OTA capture](docs/ota-pcap.md)
|
|
690
690
|
next to them — `shared.ota_pcap.enabled`, off by default, roughly 1 % of payload
|
|
691
691
|
volume, and every packet labelled uplink or downlink. It needs no capability,
|
|
692
|
-
no image change and no extra container
|
|
692
|
+
no image change and no extra container — only the passwordless sudo the
|
|
693
|
+
container already has, and only until its socket is open.
|
|
693
694
|
|
|
694
695
|
Convert a recorded link trace into a profiles-file entry when you want to replay
|
|
695
696
|
the same drive conditions in a repeatable benchmark:
|
|
@@ -386,6 +386,7 @@ tests/unit/test_status_eval.py
|
|
|
386
386
|
tests/unit/test_status_overview.py
|
|
387
387
|
tests/unit/test_status_overview_observer.py
|
|
388
388
|
tests/unit/test_stream_stats.py
|
|
389
|
+
tests/unit/test_terminology_stage_ownership.py
|
|
389
390
|
tests/unit/test_trace_profiles.py
|
|
390
391
|
tests/unit/test_transit.py
|
|
391
392
|
tests/unit/test_video_quality.py
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/src/rosotacom_dev.egg-info/scm_file_list.json
RENAMED
|
@@ -381,6 +381,7 @@
|
|
|
381
381
|
"tests/unit/test_status_overview.py",
|
|
382
382
|
"tests/unit/test_status_overview_observer.py",
|
|
383
383
|
"tests/unit/test_stream_stats.py",
|
|
384
|
+
"tests/unit/test_terminology_stage_ownership.py",
|
|
384
385
|
"tests/unit/test_trace_profiles.py",
|
|
385
386
|
"tests/unit/test_transit.py",
|
|
386
387
|
"tests/unit/test_video_quality.py"
|
|
@@ -305,6 +305,9 @@ Notes:
|
|
|
305
305
|
- Preprocessing/postprocessing are just processing stages applied at different points:
|
|
306
306
|
- outbound: native → processed (optional)
|
|
307
307
|
- inbound: processed → native (optional)
|
|
308
|
+
- Being postprocessing does **not** by itself make a transformation a processing
|
|
309
|
+
stage of this project. Which transformations belong here is decided by
|
|
310
|
+
§9.1, not by where or when they run.
|
|
308
311
|
|
|
309
312
|
---
|
|
310
313
|
|
|
@@ -323,6 +326,57 @@ Example: `/com/out/A/to_B/sensors/camera/image_raw/restamped/max20hz/bz2`
|
|
|
323
326
|
|
|
324
327
|
## 9. Module responsibilities
|
|
325
328
|
|
|
329
|
+
### 9.1 Stage ownership (which transformations belong to this project)
|
|
330
|
+
|
|
331
|
+
A **processing stage** (§7) belongs to this project when it either
|
|
332
|
+
|
|
333
|
+
1. **undoes a stage this project applied** — decompression undoes compression,
|
|
334
|
+
the OTA unwrapper undoes the OTA wrapper, `global_to_local` undoes
|
|
335
|
+
`local_to_global`, `trickle` undoes `latch`; or
|
|
336
|
+
2. **compensates for the medium** — the playout pacer against the arrival
|
|
337
|
+
jitter a link introduces.
|
|
338
|
+
|
|
339
|
+
Everything else that happens to a stream after the inbound native topic
|
|
340
|
+
belongs to whoever consumes it, and is that consumer's code in that
|
|
341
|
+
consumer's repository. The inbound native topic (§3) is where this project's
|
|
342
|
+
canonical lifecycle ends, and stage ownership ends with it.
|
|
343
|
+
|
|
344
|
+
**Two criteria that do not decide it**, because both are true of stages on
|
|
345
|
+
either side:
|
|
346
|
+
|
|
347
|
+
- *Where it runs.* Decompression, the unwrapper, `trickle` and the pacer all
|
|
348
|
+
run at the receiving peer. So does an application transform that has nothing
|
|
349
|
+
to do with the link.
|
|
350
|
+
- *That it is postprocessing.* §3 names inbound postprocessing as part of the
|
|
351
|
+
lifecycle, so the word describes a position, not an owner.
|
|
352
|
+
|
|
353
|
+
`trickle` is the stage that makes the boundary feel ambiguous, and rule 1
|
|
354
|
+
resolves it. It can be read as a fix for a consumer that expects a periodic
|
|
355
|
+
stream — but the question is not what it is good for, it is why the value was
|
|
356
|
+
latched in the first place: repeating a state at a fixed rate over a metered
|
|
357
|
+
link is waste, so latching is a link decision and `trickle` is its inverse.
|
|
358
|
+
Without the link there would be nothing to un-latch.
|
|
359
|
+
|
|
360
|
+
**The quick test is a counterfactual.** Change the *link* — other radio, other
|
|
361
|
+
route, other codec — and ask whether the stage has to change; then change the
|
|
362
|
+
*consumer* — other display, other viewer, an automated pipeline instead of a
|
|
363
|
+
person — and ask the same. A stage that survives every link change and breaks
|
|
364
|
+
on a consumer change is the consumer's.
|
|
365
|
+
|
|
366
|
+
**The falsifiable test, for cases the counterfactual leaves open.** A stage
|
|
367
|
+
here becomes part of the session contract, so it must carry an `expect:` the
|
|
368
|
+
harness can assert. If no `hz`, `loss_pct`, `latency_ms` or
|
|
369
|
+
`completeness.vs_bag_ratio` on that stage would mean anything, the contract
|
|
370
|
+
cannot check it — and a stage the contract cannot check does not belong in the
|
|
371
|
+
contract.
|
|
372
|
+
|
|
373
|
+
This is about **stages, not about code**. A generic operation — resampling an
|
|
374
|
+
image, filtering a point cloud — may live here as a reusable node the day a
|
|
375
|
+
second session needs it. What must not move here is the decision that a
|
|
376
|
+
particular consumer wants a particular result.
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
326
380
|
### App Relay
|
|
327
381
|
The **App Relay** (application relay) maps between application topics and com topics.
|
|
328
382
|
|
|
@@ -306,3 +306,52 @@ def test_the_node_is_handed_the_remote_peers_address_to_narrow_the_capture() ->
|
|
|
306
306
|
other conversation the machine is having."""
|
|
307
307
|
text = PLUGIN_BASE.read_text(encoding="utf-8")
|
|
308
308
|
assert "-p ota_pcap_peer_ip:=${ip_remote}" in text
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
# ---------------------------------------------------------------------------
|
|
312
|
+
# root for one system call
|
|
313
|
+
# ---------------------------------------------------------------------------
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def test_the_capture_gives_root_back_as_soon_as_the_socket_exists(monkeypatch) -> None:
|
|
317
|
+
"""Launched through sudo, dropped straight after — so the pcap belongs to
|
|
318
|
+
the same user as `link_trace.jsonl` beside it, not to root."""
|
|
319
|
+
calls = {}
|
|
320
|
+
monkeypatch.setattr(ota_pcap.os, "geteuid", lambda: 0)
|
|
321
|
+
monkeypatch.setattr(ota_pcap.os, "setgroups", lambda g: calls.setdefault("groups", g))
|
|
322
|
+
monkeypatch.setattr(ota_pcap.os, "setgid", lambda gid: calls.setdefault("gid", gid))
|
|
323
|
+
monkeypatch.setattr(ota_pcap.os, "setuid", lambda uid: calls.setdefault("uid", uid))
|
|
324
|
+
|
|
325
|
+
assert ota_pcap.drop_privileges("1000:1001") == "1000:1001"
|
|
326
|
+
assert calls == {"groups": [], "gid": 1001, "uid": 1000}
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def test_a_capture_that_is_not_root_leaves_the_ids_alone(monkeypatch) -> None:
|
|
330
|
+
monkeypatch.setattr(ota_pcap.os, "geteuid", lambda: 1000)
|
|
331
|
+
monkeypatch.setattr(ota_pcap.os, "setuid", lambda uid: pytest.fail("must not be called"))
|
|
332
|
+
assert ota_pcap.drop_privileges("1000:1000") is None
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@pytest.mark.parametrize("spec", [None, "", "root", "1000:nobody"])
|
|
336
|
+
def test_a_spec_that_is_not_uid_gid_never_changes_the_process(spec, monkeypatch) -> None:
|
|
337
|
+
monkeypatch.setattr(ota_pcap.os, "geteuid", lambda: 0)
|
|
338
|
+
monkeypatch.setattr(ota_pcap.os, "setuid", lambda uid: pytest.fail("must not be called"))
|
|
339
|
+
assert ota_pcap.drop_privileges(spec) is None
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def test_the_node_launches_it_through_sudo_and_hands_root_straight_back() -> None:
|
|
343
|
+
"""The node runs as `containeruser`, whose CapEff is zero, so no `--cap-add`
|
|
344
|
+
on the container would let it open an AF_PACKET socket. Asserted over the
|
|
345
|
+
source because the node needs rclpy, which the host suite does not have."""
|
|
346
|
+
source = (WS_PY / "com_py" / "status_overview.py").read_text(encoding="utf-8")
|
|
347
|
+
assert 'argv = ["sudo", "-n", *argv]' in source
|
|
348
|
+
assert '"--drop-to", f"{os.getuid()}:{os.getgid()}"' in source
|
|
349
|
+
# And the stop goes the same way: the child is root, so an ordinary kill
|
|
350
|
+
# would be refused — and it must be SIGINT, which is what writes ota.json.
|
|
351
|
+
assert '"sudo", "-n", "kill", "-INT"' in source
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def test_the_capture_is_a_process_not_a_thread_in_the_status_node() -> None:
|
|
355
|
+
"""A capture that misbehaves must not reach the snapshot an operator watches."""
|
|
356
|
+
source = (WS_PY / "com_py" / "status_overview.py").read_text(encoding="utf-8")
|
|
357
|
+
assert "subprocess.Popen(argv, start_new_session=True)" in source
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""The stage-ownership rule in `terminology.md` §9.1, against the code.
|
|
2
|
+
|
|
3
|
+
The rule is normative — it decides what may be added to this project — and it
|
|
4
|
+
argues from concrete pairs: decompression undoes compression, the unwrapper
|
|
5
|
+
undoes the wrapper, `global_to_local` undoes `local_to_global`, `trickle`
|
|
6
|
+
undoes `latch`, and the playout pacer compensates for the medium. A rule that
|
|
7
|
+
reasons from examples is only as good as the examples, and a renamed node
|
|
8
|
+
leaves it quietly arguing from things that are not there any more.
|
|
9
|
+
|
|
10
|
+
This is a documentation test, not a behaviour test: there is no behaviour to
|
|
11
|
+
run. What it pins is that every node the rule names still exists, that the two
|
|
12
|
+
tests it offers still name assertions the session schema accepts, and that the
|
|
13
|
+
section it belongs to is still where §7 sends the reader.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import re
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
22
|
+
TERMINOLOGY = REPO_ROOT / "terminology.md"
|
|
23
|
+
COM_PY = REPO_ROOT / "src" / "rosotacom" / "resources" / "ws" / "ros2src" / "com_py" / "com_py"
|
|
24
|
+
STATUS_EVAL = REPO_ROOT / "src" / "rosotacom" / "status_eval.py"
|
|
25
|
+
GENERATOR_PY = (
|
|
26
|
+
REPO_ROOT / "src" / "rosotacom" / "resources" / "ws" / "session" / "creation" / "generate_session_files.py"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
#: The nodes §9.1 argues from, as module names in `com_py`.
|
|
30
|
+
CITED_NODES = (
|
|
31
|
+
"universal_compressor",
|
|
32
|
+
"universal_decompressor",
|
|
33
|
+
"universal_ota_wrapper",
|
|
34
|
+
"universal_ota_unwrapper",
|
|
35
|
+
"local_global_frame_bridge",
|
|
36
|
+
"trickle",
|
|
37
|
+
"playout_pacer",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
#: The processing keys §9.1's inverse pairs are stated in. A session has to
|
|
41
|
+
#: still be able to declare each of them, or the pair argues from nothing.
|
|
42
|
+
CITED_STAGE_KEYS = ("latch", "local_to_global", "global_to_local")
|
|
43
|
+
|
|
44
|
+
#: The assertion keys §9.1 offers as its falsifiable test. They are only a
|
|
45
|
+
#: test if a session may actually declare them, so each is checked against the
|
|
46
|
+
#: evaluator that reads them. `vs_bag_ratio` sits under `completeness` and is
|
|
47
|
+
#: named that way in the text for the same reason.
|
|
48
|
+
CITED_EXPECTATIONS = ("hz", "loss_pct", "latency_ms", "completeness.vs_bag_ratio")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
#: `## 9.` and `### App Relay` are both headings, so a section has to run to
|
|
52
|
+
#: the next heading of its own level or higher, not to the next heading.
|
|
53
|
+
def section(title: str) -> str:
|
|
54
|
+
"""The text of one `terminology.md` section, up to the next peer heading."""
|
|
55
|
+
text = TERMINOLOGY.read_text(encoding="utf-8")
|
|
56
|
+
match = re.search(
|
|
57
|
+
rf"^(#+) {re.escape(title)}\s*$",
|
|
58
|
+
text,
|
|
59
|
+
re.MULTILINE,
|
|
60
|
+
)
|
|
61
|
+
assert match is not None, f"terminology.md has no section '{title}'"
|
|
62
|
+
depth = len(match.group(1))
|
|
63
|
+
rest = text[match.end() :]
|
|
64
|
+
end = re.search(rf"^#{{1,{depth}}} ", rest, re.MULTILINE)
|
|
65
|
+
return rest[: end.start()] if end else rest
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_the_rule_is_where_the_stage_definition_sends_the_reader():
|
|
69
|
+
# §7 defers the ownership question rather than answering it twice.
|
|
70
|
+
assert "§9.1" in section("7. Processing and transformations")
|
|
71
|
+
assert section("9.1 Stage ownership (which transformations belong to this project)")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_every_node_the_rule_argues_from_still_exists():
|
|
75
|
+
missing = [name for name in CITED_NODES if not (COM_PY / f"{name}.py").is_file()]
|
|
76
|
+
|
|
77
|
+
assert not missing, f"terminology.md §9.1 cites nodes that are gone: {missing}"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_the_stage_keywords_the_rule_argues_from_are_still_session_vocabulary():
|
|
81
|
+
# The rule reasons from inverse pairs, so it breaks quietly when a session
|
|
82
|
+
# key is renamed: the prose keeps arguing from a `latch` or a
|
|
83
|
+
# `local_to_global` that no definition can declare any more.
|
|
84
|
+
body = section("9.1 Stage ownership (which transformations belong to this project)")
|
|
85
|
+
generator = GENERATOR_PY.read_text(encoding="utf-8")
|
|
86
|
+
|
|
87
|
+
for key in CITED_STAGE_KEYS:
|
|
88
|
+
assert f"`{key}`" in body, f"§9.1 no longer argues from '{key}'"
|
|
89
|
+
assert f'"{key}"' in generator, (
|
|
90
|
+
f"§9.1 argues from '{key}', which the session generator no longer knows as a processing key"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_the_falsifiable_test_names_assertions_a_session_may_declare():
|
|
95
|
+
body = section("9.1 Stage ownership (which transformations belong to this project)")
|
|
96
|
+
evaluator = STATUS_EVAL.read_text(encoding="utf-8")
|
|
97
|
+
|
|
98
|
+
for key in CITED_EXPECTATIONS:
|
|
99
|
+
assert f"`{key}`" in body, f"§9.1 no longer offers '{key}'"
|
|
100
|
+
for part in key.split("."):
|
|
101
|
+
assert f'"{part}"' in evaluator, (
|
|
102
|
+
f"§9.1 offers '{key}' as an expectation, but status_eval does not know '{part}'"
|
|
103
|
+
)
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.devcontainer/devcontainer.json.template
RENAMED
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.devcontainer/re_generate_devcontainer_json.py
RENAMED
|
File without changes
|
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/documentation-audit.md
RENAMED
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/implementation-cleanup.md
RENAMED
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/quality-workflow.md
RENAMED
|
File without changes
|
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/release-process.md
RENAMED
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/ISSUE_TEMPLATE/repository-diagnosis.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/.github/workflows/benchmark-calibrate.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/capacity-size-tight-cyclone.json
RENAMED
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-gop-tight-cyclone.json
RENAMED
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-nominal-cyclone.json
RENAMED
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-tight-cyclone.json
RENAMED
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/calibration/probe-loss-tight-fastdds.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rosotacom_dev-2.5.dev67 → rosotacom_dev-2.5.dev69}/docs/findings/cyclone-spdp-discovery-bursts.md
RENAMED
|
File without changes
|