rosotacom-dev 2.5.dev38__tar.gz → 2.5.dev40__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/PKG-INFO +1 -1
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/session-configuration.md +29 -2
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/cli.py +5 -2
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/17_synthetic_camera_quality/session-definition.yaml +5 -1
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/base_bridge_relay.py +32 -2
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/qos.py +8 -2
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/content/base/session_plugin_base.yaml +49 -36
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/generate_session_files.py +71 -23
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/PKG-INFO +1 -1
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/SOURCES.txt +2 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/scm_file_list.json +2 -0
- rosotacom_dev-2.5.dev40/src/rosotacom_dev.egg-info/scm_version.json +8 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_catmux_pane_logging.py +74 -0
- rosotacom_dev-2.5.dev40/tests/unit/test_qos_fallback_logging.py +139 -0
- rosotacom_dev-2.5.dev40/tests/unit/test_relay_optional_parameters.py +176 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_session_pipeline.py +42 -3
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_status_overview.py +84 -2
- rosotacom_dev-2.5.dev38/src/rosotacom_dev.egg-info/scm_version.json +0 -8
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.devcontainer/devcontainer.json.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.devcontainer/re_generate_devcontainer_json.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/CODEOWNERS +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/documentation-audit.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/implementation-cleanup.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/quality-workflow.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/redesign.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/release-process.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/repository-diagnosis.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/test-ci-audit.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/ISSUE_TEMPLATE/work-item.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/actions/setup-just/action.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/dependabot.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/workflows/benchmark-calibrate.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/workflows/benchmark-gate.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/workflows/dev-release.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/workflows/image-scan.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/workflows/nightly-e2e.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/workflows/pr-lightweight.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/workflows/pr-merge-gate.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.github/workflows/release.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/.pre-commit-config.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/AGENTS.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/CONCURRENCY.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/CONTRIBUTING.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/DEVELOPMENT_PRINCIPLES.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/MANIFEST.in +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/README.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/budgets.jsonl +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/calibration/README.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/calibration/capacity-size-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-gop-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-nominal-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-tight-cyclone.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-tight-fastdds.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/calibration/probe-loss-tight-zenoh.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/codecov.yml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/deployment-configuration.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/benchmark-ab.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/benchmark-bag-as-load.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/ci.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/ffmpeg-keyframes.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/findings/README.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/findings/cyclone-spdp-discovery-bursts.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/findings/delay-alone-no-loss.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/findings/head-of-line-irregularity.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/findings/jitter-loss-bandwidth-latency.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/findings/lighter-message-loss.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/findings/zero-loss-boundaries-18kb-20hz.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/forensics-report.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/geo-link-map.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/github-repository-settings.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/link-bandwidth.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/link-trace.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/owner-runbook.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/performance-bands.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/playbooks/README.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/quality-model.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/release-notes/TEMPLATE.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/release-notes/v2.1.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/release-notes/v2.2.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/release-notes/v2.3.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/release-notes/v2.4.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/release.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/rfcs/0001-expectation-driven-test-suite.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/rfcs/0002-expectation-concepts.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/rfcs/0003-metric-backbone.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/rfcs/0004-network-profiles.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/rfcs/0005-benchmark-genres-and-ci.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/rfcs/0006-dynamic-qos.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/rfcs/0007-regression-gate.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/rfcs/README.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/testing.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/docs/work-items.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/install.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/justfile +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/media/control_center.png +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/media/echo_test.png +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/media/forensics-report-example.png +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/media/host.png +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/media/vehicle.png +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/pyproject.toml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/requirements.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/__init__.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/__main__.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/anonymize.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/benched_set.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/benchmark.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/benchmark_delta.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/deployment.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/forensics.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/geomap.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/image_cache.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/plots.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/py.typed +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/benched-set.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/.gitignore +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/README.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/__init__.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/bags/8_drop_reference/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/deployment.example.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/profiles.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/rosotacom.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scenarios/2_native_chatter/scenario-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_a.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/1_heartbeat/run_machine_b.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_a/wait_for_echo_topic.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/2_native_chatter/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/3_comp_occ_grid/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/foxglove.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/costmap_1second_0.mcap +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/costmap_1second/metadata.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/4_comp_occ_grid_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/5_sized_payload/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_a/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external.ros2docker.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/external_session.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_communication.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/scripts/6_sized_payload_zen/machine_b/run_external.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/10_restamp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/11_trickle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/12_content_integrity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/13_link_latency/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/14_remote_assist_anonymized/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/15_remote_assist_anonymized_costmap/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/16_remote_assist_anonymized_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/1_heartbeat/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/1_heartbeat_status/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/2_native_chatter/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/3_comp_occ_grid/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/4_comp_occ_grid_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/5_sized_payload/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/6_sized_payload_zen/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/7_latched_static/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/8_drop/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/9_throttle/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_1_capacity/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_2_load_sweep/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_3_ramp/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_4_recovery/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/examples/sessions/bench_1_5_camera/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ros2docker.json.example +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/.vscode/c_cpp_properties.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/.vscode/settings.json +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_easy_mode.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_initial_peer_list.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v2.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v3.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v4.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/archive/fastdds_v5.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/create_zenoh_json5.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/cyclonedds_local_participants.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/cyclonedds_minimal.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/cyclonedds_tuned.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/fastdds_unicast.xml.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/get_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/utils.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ota_configs/zenoh.json5.template +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/.gitkeep +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/COLCON_IGNORE +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/package.xml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/src/hz_monitor.cpp +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_compressor.cpp +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_cpp/src/universal_decompressor.cpp +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/CMakeLists.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/CompressedData.msg +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/EchoHeartbeat.msg +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/OtaStamped.msg +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/msg/SizedPayload.msg +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_msgs/package.xml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/LICENSE.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/__init__.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_in.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/bridge_out.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/heartbeat_echo.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/hz_monitor.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_bandwidth_reducer.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/image_pixel_capper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/lanelet_saver.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/latch_relay.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/costmap_remapper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/marker_remapper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/speed_test.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/tf_remapper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/traffic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/legacy/wifi_network_analysis_1.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/link_trace.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/local_global_frame_bridge.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/localization_map_split_reduce_saver.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/msg_transform.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pair_management.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/pub_sub_pair.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_in.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/relay_out.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/restamp.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/sized_publisher.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/stage_latency_core.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/status_overview_core.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/tf_map_to_cart_saver.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_monitor.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/topic_resolution.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/trickle.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_compressor.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_decompressor.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/com_py/universal_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/package.xml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/resource/com_py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/setup.cfg +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/setup.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/test/test_copyright.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/test/test_flake8.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/ros2src/com_py/test/test_pep257.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/content/network/up_connectivity.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/content/network/wifi_network_analysis_2.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/anonymize_bag.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/catmux_log_setup.sh +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/create_session_yaml.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/run_session.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/run_session_in_external_terminal.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/resources/ws/session/creation/strip_ansi.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/status_eval.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/transit.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom/video_quality.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/dependency_links.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/entry_points.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/requires.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/top_level.txt +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/terminology.md +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_benched_set_registry.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_findings.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_markdown_links.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_ota_source_bundle.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_package_metadata.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_packaged_resources.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_profile_covers_generated_commands.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_pytest_policy.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_readme_examples.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_security_maintenance_config.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_session_configuration_doc.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_session_template_substitution.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/contract/test_workflow_contracts.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/conftest.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/test_anonymize_e2e.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/test_benchmark_ab.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/test_benchmark_capacity.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/test_benchmark_replay.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/test_parallel_smoke.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/test_smoke.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/test_timeline_stepping.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/e2e/test_video_quality_e2e.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/sessions/generate_rmw_matrix.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-local_zenoh-ros2dds-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_cyclone-ota-tuned/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_fastdds/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/sessions/rmw_matrix/1_heartbeat_zen-endpoints/session-definition.yaml +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_anonymize.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_bag_ground_truth.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_benched_set.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_benchmark_delta.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_bundle_check.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_cli.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_cli_benchmark.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_concurrency.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_deployment.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_ffmpeg_packet.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_forensics.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_geomap.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_image_cache.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_link_bytes.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_link_trace.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_network_profiles.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_network_shaper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_ota_unwrapper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_ota_wrapper.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_ota_xml.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_plots.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_stage_latency.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_status_eval.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_status_overview_observer.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_stream_stats.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_trace_profiles.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_transit.py +0 -0
- {rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/tests/unit/test_video_quality.py +0 -0
|
@@ -446,7 +446,8 @@ processing:
|
|
|
446
446
|
pixel_cap_preset: "wsvga" # scalar, used as suffix only,
|
|
447
447
|
transport:
|
|
448
448
|
type: ffmpeg # ffmpeg | foxglove | compressed
|
|
449
|
-
local_republish:
|
|
449
|
+
local_republish: raw # raw | compressed; omit for no sender-side decode
|
|
450
|
+
remote_republish: compressed # raw | compressed; omit for no receiver-side decode
|
|
450
451
|
# plus type-specific params (see below)
|
|
451
452
|
```
|
|
452
453
|
|
|
@@ -507,11 +508,37 @@ The receiver undoes the chain in reverse, and every stage there is computed from
|
|
|
507
508
|
the delivered topic rather than from the OTA topic:
|
|
508
509
|
|
|
509
510
|
1) unwrap → republishes on the pre-wrap name (so wrapping renames nothing)
|
|
510
|
-
2) `
|
|
511
|
+
2) `remote_republish: <transport>` → reverse transport decodes into `+ /<transport>`
|
|
511
512
|
3) decompress → republishes on the pre-compress name
|
|
512
513
|
4) framebridge `global_to_local` → the local base topic
|
|
513
514
|
5) trickle → `+ /trickle`, the only receiver-side stage that adds a suffix
|
|
514
515
|
|
|
516
|
+
##### The two reverse republishes
|
|
517
|
+
|
|
518
|
+
An encoded stream crosses the link as packets — `FFMPEGPacket`, `CompressedVideo`
|
|
519
|
+
— and something has to turn those back into an image. That decode can happen in
|
|
520
|
+
two places, and they answer different questions:
|
|
521
|
+
|
|
522
|
+
- **`remote_republish`** runs on the receiving peer and is the one that matters:
|
|
523
|
+
it produces the topic the receiving application subscribes to (`<encoded>/raw`
|
|
524
|
+
or `<encoded>/compressed`), and it is what `_delivered_topic` reports as the
|
|
525
|
+
delivered stage.
|
|
526
|
+
- **`local_republish`** runs on the *sending* peer, against the stream it just
|
|
527
|
+
encoded. Nothing crosses the link for it; it exists so the sending machine can
|
|
528
|
+
see approximately what the receiver will get.
|
|
529
|
+
|
|
530
|
+
Both name the image transport they publish in rather than being switched on:
|
|
531
|
+
|
|
532
|
+
| value | delivered type | cost |
|
|
533
|
+
|---|---|---|
|
|
534
|
+
| `raw` | `sensor_msgs/msg/Image` | the transport undone and nothing else, at full frame size — a 1280x800 stream is ~3 MB per frame |
|
|
535
|
+
| `compressed` | `sensor_msgs/msg/CompressedImage` | a JPEG encode per frame, roughly an order of magnitude less data on the wire and in a `record -a` |
|
|
536
|
+
|
|
537
|
+
Omitting a key means that side does not decode. There is deliberately **no
|
|
538
|
+
default**: `type: compressed` already delivers an image, so a decode that
|
|
539
|
+
switched itself on would produce exactly the full-size copy a session chose that
|
|
540
|
+
transport to avoid.
|
|
541
|
+
|
|
515
542
|
#### Transport parameters
|
|
516
543
|
`type: ffmpeg` supports:
|
|
517
544
|
- `gop_size` (int)
|
|
@@ -6134,8 +6134,11 @@ def _smoke_postprocessed_topic(entry: Any, pipe: dict[str, Any]) -> str:
|
|
|
6134
6134
|
if pipe.get("framebridge") == "global_to_local":
|
|
6135
6135
|
return str(pipe["fb_g2l_base"])
|
|
6136
6136
|
transport = pipe.get("transport")
|
|
6137
|
-
|
|
6138
|
-
|
|
6137
|
+
remote_republish = getattr(transport, "remote_republish", None) if transport is not None else None
|
|
6138
|
+
if remote_republish:
|
|
6139
|
+
# The receiver's decode is what the smoke drives and asserts; the
|
|
6140
|
+
# sender's own preview (`local_republish`) never reaches this peer.
|
|
6141
|
+
return str(pipe["final"]) + f"/{remote_republish}"
|
|
6139
6142
|
return str(pipe["final"])
|
|
6140
6143
|
|
|
6141
6144
|
|
|
@@ -49,7 +49,11 @@ topics:
|
|
|
49
49
|
processing:
|
|
50
50
|
transport:
|
|
51
51
|
type: ffmpeg
|
|
52
|
-
|
|
52
|
+
# `raw` on both sides, because this example measures the codec: PSNR
|
|
53
|
+
# and SSIM compare pixels, and a JPEG twin would fold its own loss
|
|
54
|
+
# into the number the example exists to report.
|
|
55
|
+
local_republish: raw
|
|
56
|
+
remote_republish: raw
|
|
53
57
|
gop_size: 4
|
|
54
58
|
bit_rate: 2000000
|
|
55
59
|
# Wrapping an encoded stream: the wrapper runs after the encoder, so the
|
|
@@ -61,8 +61,8 @@ class BaseBridgeRelay(Node, PairRefreshMixin):
|
|
|
61
61
|
self.qos_config_file = self.declare_parameter('qos_config_file', '').value
|
|
62
62
|
|
|
63
63
|
# Optional parameters with defaults
|
|
64
|
-
self.source_names = self.
|
|
65
|
-
self.target_names = self.
|
|
64
|
+
self.source_names = self.declare_optional_string_array('source_names')
|
|
65
|
+
self.target_names = self.declare_optional_string_array('target_names')
|
|
66
66
|
|
|
67
67
|
# Derived classes can declare additional parameters here (must happen before initialize_node()).
|
|
68
68
|
self.declare_additional_parameters()
|
|
@@ -73,6 +73,36 @@ class BaseBridgeRelay(Node, PairRefreshMixin):
|
|
|
73
73
|
# Create timer for periodic refresh of invalid pairs
|
|
74
74
|
self.init_pair_refresh(period_s=5.0, log_prefix=self.node_role)
|
|
75
75
|
|
|
76
|
+
def declare_optional_string_array(self, name: str) -> list:
|
|
77
|
+
"""Declare an optional STRING_ARRAY that reads as [] rather than as unset.
|
|
78
|
+
|
|
79
|
+
Declaring a type without a value leaves the parameter
|
|
80
|
+
PARAMETER_NOT_SET. This node never notices — it reads the value once,
|
|
81
|
+
here, and an unset parameter simply yields None. Everything *else*
|
|
82
|
+
notices: reading a not-set parameter raises, and rclpy's parameter
|
|
83
|
+
service logs one warning per read against this node,
|
|
84
|
+
|
|
85
|
+
[WARN] [ota_relay_out]: Failed to get parameters: The parameter
|
|
86
|
+
'source_names' is not initialized: source_names
|
|
87
|
+
|
|
88
|
+
which anything that enumerates parameters then produces on a timer. A
|
|
89
|
+
Foxglove bridge with a parameter panel open put 107 of those lines into
|
|
90
|
+
a single pane in one session — the kind of noise that hides the message
|
|
91
|
+
somebody actually needs to see.
|
|
92
|
+
|
|
93
|
+
A plain default cannot express this: `declare_parameter(name, [])`
|
|
94
|
+
infers the type from the value, and an empty list satisfies the
|
|
95
|
+
BYTE_ARRAY test first (`all(...)` is true for an empty sequence). The
|
|
96
|
+
parameter would be typed BYTE_ARRAY and the real string array refused
|
|
97
|
+
later with "Wrong parameter type, expected '5' got '9'". Declaring the
|
|
98
|
+
type and then setting the empty value keeps it STRING_ARRAY, so a wrong
|
|
99
|
+
type is still rejected and an override still wins.
|
|
100
|
+
"""
|
|
101
|
+
self.declare_parameter(name, rclpy.Parameter.Type.STRING_ARRAY)
|
|
102
|
+
if self.get_parameter_or(name).type_ == rclpy.Parameter.Type.NOT_SET:
|
|
103
|
+
self.set_parameters([rclpy.Parameter(name, rclpy.Parameter.Type.STRING_ARRAY, [])])
|
|
104
|
+
return self.get_parameter(name).value
|
|
105
|
+
|
|
76
106
|
def initialize_node(self):
|
|
77
107
|
"""Initialize node with resolved topics and QoS configuration."""
|
|
78
108
|
try:
|
|
@@ -139,7 +139,13 @@ def get_topic_qos(logger, qos_config: dict, topic_name: str, role_name: str):
|
|
|
139
139
|
Additionally supports a fallback lookup: if no exact match for topic_name exists
|
|
140
140
|
in qos_config['topics'], we look for the most specific configured base topic key
|
|
141
141
|
that matches as a path segment within topic_name (e.g. '/tf' for
|
|
142
|
-
'/shuttle_ella/tf/restamped').
|
|
142
|
+
'/shuttle_ella/tf/restamped'). Such a fallback is logged at debug level: it is
|
|
143
|
+
the designed path, not a degradation. Every processing stage appends a suffix,
|
|
144
|
+
so a session that uses framebridge, latching or a transport reaches it for most
|
|
145
|
+
of its topics, and a definition that declares QoS on the base topic and lets the
|
|
146
|
+
processed names inherit it is doing exactly what the schema intends. Logged as a
|
|
147
|
+
warning it was two lines per topic per peer at every start — enough noise around
|
|
148
|
+
a bring-up to bury an actual fault.
|
|
143
149
|
"""
|
|
144
150
|
default = qos_config.get('default', {})
|
|
145
151
|
|
|
@@ -151,7 +157,7 @@ def get_topic_qos(logger, qos_config: dict, topic_name: str, role_name: str):
|
|
|
151
157
|
if topic_name not in topics_cfg:
|
|
152
158
|
base_match = _find_best_base_topic_match(topics_cfg, topic_name)
|
|
153
159
|
if base_match is not None:
|
|
154
|
-
logger.
|
|
160
|
+
logger.debug(
|
|
155
161
|
f"[dds_qos] No exact QoS match for topic='{topic_name}'. "
|
|
156
162
|
f"Falling back to base topic='{base_match}'."
|
|
157
163
|
)
|
|
@@ -534,6 +534,19 @@ windows:
|
|
|
534
534
|
- commands:
|
|
535
535
|
- if [ '${ipx_4_topics}' = "None" ]; then exit; fi
|
|
536
536
|
- ros2 run com_py image_pixel_capper --ros-args -p topics:=[${ipx_4_topics}] -p max_pixels_preset:=${ipx_4_preset} -p qos_config_file:='${qos_config_file}'
|
|
537
|
+
# `if ...; then ...; fi`, never `[[ ... ]] && ...`, for the optional argument
|
|
538
|
+
# lines below. catmux sends every one of these to an interactive shell, and
|
|
539
|
+
# `catmux_log_setup.sh` hooks the pane-exit recorder into PROMPT_COMMAND — so
|
|
540
|
+
# it sees the status of each line, not just of the node the pane finally runs.
|
|
541
|
+
# `&&` short-circuits to status 1 whenever the option is unset, which is the
|
|
542
|
+
# normal case for every option a session does not override, so each of these
|
|
543
|
+
# lines wrote itself into `pane_failures.log` as a dead pane:
|
|
544
|
+
#
|
|
545
|
+
# pane=13-IT/0 exit=1 command=[[ "None" != "None" ]] && args+=(-p "ut.foxglove.bit_rate:=None")
|
|
546
|
+
#
|
|
547
|
+
# A peer then reported `STARTUP CHECK FAILED ... 4 pane(s) exited` on every
|
|
548
|
+
# start while nothing was wrong, which is the one thing that check must not
|
|
549
|
+
# do: it exists to make a genuinely dead pane visible in seconds.
|
|
537
550
|
- name: IT
|
|
538
551
|
if: it
|
|
539
552
|
layout: even-vertical
|
|
@@ -542,15 +555,15 @@ windows:
|
|
|
542
555
|
- if [ '${it_1_topic}' = "None" ]; then exit; fi
|
|
543
556
|
- if [[ "${it_1_topic}" == *"/compressed"* ]]; then it_in_transport="compressed"; else it_in_transport="raw"; fi
|
|
544
557
|
- args=(ros2 run image_transport republish --ros-args -r __node:=republish1 -p in_transport:=${it_in_transport})
|
|
545
|
-
- '[[ "${it_1_transport}" != "None" ]]
|
|
546
|
-
- '[[ "${it_1_compressed_jpeg_quality}" != "None" ]]
|
|
547
|
-
- '[[ "${it_1_ffmpeg_gop_size}" != "None" ]]
|
|
548
|
-
- '[[ "${it_1_ffmpeg_encoder_av_options}" != "None" ]]
|
|
549
|
-
- '[[ "${it_1_ffmpeg_bit_rate}" != "None" ]]
|
|
550
|
-
- '[[ "${it_1_foxglove_gop_size}" != "None" ]]
|
|
551
|
-
- '[[ "${it_1_foxglove_encoder_av_options}" != "None" ]]
|
|
552
|
-
- '[[ "${it_1_foxglove_bit_rate}" != "None" ]]
|
|
553
|
-
- '[[ "${it_1_foxglove_qmax}" != "None" ]]
|
|
558
|
+
- 'if [[ "${it_1_transport}" != "None" ]]; then args+=(-p "out_transport:=${it_1_transport}"); fi'
|
|
559
|
+
- 'if [[ "${it_1_compressed_jpeg_quality}" != "None" ]]; then args+=(-p "ut.compressed.jpeg_quality:=${it_1_compressed_jpeg_quality}"); fi'
|
|
560
|
+
- 'if [[ "${it_1_ffmpeg_gop_size}" != "None" ]]; then args+=(-p "ut.ffmpeg.gop_size:=${it_1_ffmpeg_gop_size}"); fi'
|
|
561
|
+
- 'if [[ "${it_1_ffmpeg_encoder_av_options}" != "None" ]]; then args+=(-p "ut.ffmpeg.encoder_av_options:=${it_1_ffmpeg_encoder_av_options}"); fi'
|
|
562
|
+
- 'if [[ "${it_1_ffmpeg_bit_rate}" != "None" ]]; then args+=(-p "ut.ffmpeg.bit_rate:=${it_1_ffmpeg_bit_rate}"); fi'
|
|
563
|
+
- 'if [[ "${it_1_foxglove_gop_size}" != "None" ]]; then args+=(-p "ut.foxglove.gop_size:=${it_1_foxglove_gop_size}"); fi'
|
|
564
|
+
- 'if [[ "${it_1_foxglove_encoder_av_options}" != "None" ]]; then args+=(-p "ut.foxglove.encoder_av_options:=${it_1_foxglove_encoder_av_options}"); fi'
|
|
565
|
+
- 'if [[ "${it_1_foxglove_bit_rate}" != "None" ]]; then args+=(-p "ut.foxglove.bit_rate:=${it_1_foxglove_bit_rate}"); fi'
|
|
566
|
+
- 'if [[ "${it_1_foxglove_qmax}" != "None" ]]; then args+=(-p "ut.foxglove.qmax:=${it_1_foxglove_qmax}"); fi'
|
|
554
567
|
- if [[ "${it_1_outgoing_suffix}" != "None" ]]; then outgoing_suffix="${it_1_outgoing_suffix}"; else outgoing_suffix="${it_1_transport}"; fi
|
|
555
568
|
- if [[ "${it_in_transport}" == "raw" ]]; then in_remap="in"; else in_remap="in/${it_in_transport}"; fi
|
|
556
569
|
- args+=(--remap "${in_remap}:=${it_1_topic}" --remap "out/${it_1_transport}:=${it_1_topic}/${outgoing_suffix}")
|
|
@@ -560,15 +573,15 @@ windows:
|
|
|
560
573
|
- if [ '${it_2_topic}' = "None" ]; then exit; fi
|
|
561
574
|
- if [[ "${it_2_topic}" == *"/compressed"* ]]; then it_in_transport="compressed"; else it_in_transport="raw"; fi
|
|
562
575
|
- args=(ros2 run image_transport republish --ros-args -r __node:=republish2 -p in_transport:=${it_in_transport})
|
|
563
|
-
- '[[ "${it_2_transport}" != "None" ]]
|
|
564
|
-
- '[[ "${it_2_compressed_jpeg_quality}" != "None" ]]
|
|
565
|
-
- '[[ "${it_2_ffmpeg_gop_size}" != "None" ]]
|
|
566
|
-
- '[[ "${it_2_ffmpeg_encoder_av_options}" != "None" ]]
|
|
567
|
-
- '[[ "${it_2_ffmpeg_bit_rate}" != "None" ]]
|
|
568
|
-
- '[[ "${it_2_foxglove_gop_size}" != "None" ]]
|
|
569
|
-
- '[[ "${it_2_foxglove_encoder_av_options}" != "None" ]]
|
|
570
|
-
- '[[ "${it_2_foxglove_bit_rate}" != "None" ]]
|
|
571
|
-
- '[[ "${it_2_foxglove_qmax}" != "None" ]]
|
|
576
|
+
- 'if [[ "${it_2_transport}" != "None" ]]; then args+=(-p "out_transport:=${it_2_transport}"); fi'
|
|
577
|
+
- 'if [[ "${it_2_compressed_jpeg_quality}" != "None" ]]; then args+=(-p "ut.compressed.jpeg_quality:=${it_2_compressed_jpeg_quality}"); fi'
|
|
578
|
+
- 'if [[ "${it_2_ffmpeg_gop_size}" != "None" ]]; then args+=(-p "ut.ffmpeg.gop_size:=${it_2_ffmpeg_gop_size}"); fi'
|
|
579
|
+
- 'if [[ "${it_2_ffmpeg_encoder_av_options}" != "None" ]]; then args+=(-p "ut.ffmpeg.encoder_av_options:=${it_2_ffmpeg_encoder_av_options}"); fi'
|
|
580
|
+
- 'if [[ "${it_2_ffmpeg_bit_rate}" != "None" ]]; then args+=(-p "ut.ffmpeg.bit_rate:=${it_2_ffmpeg_bit_rate}"); fi'
|
|
581
|
+
- 'if [[ "${it_2_foxglove_gop_size}" != "None" ]]; then args+=(-p "ut.foxglove.gop_size:=${it_2_foxglove_gop_size}"); fi'
|
|
582
|
+
- 'if [[ "${it_2_foxglove_encoder_av_options}" != "None" ]]; then args+=(-p "ut.foxglove.encoder_av_options:=${it_2_foxglove_encoder_av_options}"); fi'
|
|
583
|
+
- 'if [[ "${it_2_foxglove_bit_rate}" != "None" ]]; then args+=(-p "ut.foxglove.bit_rate:=${it_2_foxglove_bit_rate}"); fi'
|
|
584
|
+
- 'if [[ "${it_2_foxglove_qmax}" != "None" ]]; then args+=(-p "ut.foxglove.qmax:=${it_2_foxglove_qmax}"); fi'
|
|
572
585
|
- if [[ "${it_2_outgoing_suffix}" != "None" ]]; then outgoing_suffix="${it_2_outgoing_suffix}"; else outgoing_suffix="${it_2_transport}"; fi
|
|
573
586
|
- if [[ "${it_in_transport}" == "raw" ]]; then in_remap="in"; else in_remap="in/${it_in_transport}"; fi
|
|
574
587
|
- args+=(--remap "${in_remap}:=${it_2_topic}" --remap "out/${it_2_transport}:=${it_2_topic}/${outgoing_suffix}")
|
|
@@ -578,15 +591,15 @@ windows:
|
|
|
578
591
|
- if [ '${it_3_topic}' = "None" ]; then exit; fi
|
|
579
592
|
- if [[ "${it_3_topic}" == *"/compressed"* ]]; then it_in_transport="compressed"; else it_in_transport="raw"; fi
|
|
580
593
|
- args=(ros2 run image_transport republish --ros-args -r __node:=republish3 -p in_transport:=${it_in_transport})
|
|
581
|
-
- '[[ "${it_3_transport}" != "None" ]]
|
|
582
|
-
- '[[ "${it_3_compressed_jpeg_quality}" != "None" ]]
|
|
583
|
-
- '[[ "${it_3_ffmpeg_gop_size}" != "None" ]]
|
|
584
|
-
- '[[ "${it_3_ffmpeg_encoder_av_options}" != "None" ]]
|
|
585
|
-
- '[[ "${it_3_ffmpeg_bit_rate}" != "None" ]]
|
|
586
|
-
- '[[ "${it_3_foxglove_gop_size}" != "None" ]]
|
|
587
|
-
- '[[ "${it_3_foxglove_encoder_av_options}" != "None" ]]
|
|
588
|
-
- '[[ "${it_3_foxglove_bit_rate}" != "None" ]]
|
|
589
|
-
- '[[ "${it_3_foxglove_qmax}" != "None" ]]
|
|
594
|
+
- 'if [[ "${it_3_transport}" != "None" ]]; then args+=(-p "out_transport:=${it_3_transport}"); fi'
|
|
595
|
+
- 'if [[ "${it_3_compressed_jpeg_quality}" != "None" ]]; then args+=(-p "ut.compressed.jpeg_quality:=${it_3_compressed_jpeg_quality}"); fi'
|
|
596
|
+
- 'if [[ "${it_3_ffmpeg_gop_size}" != "None" ]]; then args+=(-p "ut.ffmpeg.gop_size:=${it_3_ffmpeg_gop_size}"); fi'
|
|
597
|
+
- 'if [[ "${it_3_ffmpeg_encoder_av_options}" != "None" ]]; then args+=(-p "ut.ffmpeg.encoder_av_options:=${it_3_ffmpeg_encoder_av_options}"); fi'
|
|
598
|
+
- 'if [[ "${it_3_ffmpeg_bit_rate}" != "None" ]]; then args+=(-p "ut.ffmpeg.bit_rate:=${it_3_ffmpeg_bit_rate}"); fi'
|
|
599
|
+
- 'if [[ "${it_3_foxglove_gop_size}" != "None" ]]; then args+=(-p "ut.foxglove.gop_size:=${it_3_foxglove_gop_size}"); fi'
|
|
600
|
+
- 'if [[ "${it_3_foxglove_encoder_av_options}" != "None" ]]; then args+=(-p "ut.foxglove.encoder_av_options:=${it_3_foxglove_encoder_av_options}"); fi'
|
|
601
|
+
- 'if [[ "${it_3_foxglove_bit_rate}" != "None" ]]; then args+=(-p "ut.foxglove.bit_rate:=${it_3_foxglove_bit_rate}"); fi'
|
|
602
|
+
- 'if [[ "${it_3_foxglove_qmax}" != "None" ]]; then args+=(-p "ut.foxglove.qmax:=${it_3_foxglove_qmax}"); fi'
|
|
590
603
|
- if [[ "${it_3_outgoing_suffix}" != "None" ]]; then outgoing_suffix="${it_3_outgoing_suffix}"; else outgoing_suffix="${it_3_transport}"; fi
|
|
591
604
|
- if [[ "${it_in_transport}" == "raw" ]]; then in_remap="in"; else in_remap="in/${it_in_transport}"; fi
|
|
592
605
|
- args+=(--remap "${in_remap}:=${it_3_topic}" --remap "out/${it_3_transport}:=${it_3_topic}/${outgoing_suffix}")
|
|
@@ -596,15 +609,15 @@ windows:
|
|
|
596
609
|
- if [ '${it_4_topic}' = "None" ]; then exit; fi
|
|
597
610
|
- if [[ "${it_4_topic}" == *"/compressed"* ]]; then it_in_transport="compressed"; else it_in_transport="raw"; fi
|
|
598
611
|
- args=(ros2 run image_transport republish --ros-args -r __node:=republish4 -p in_transport:=${it_in_transport})
|
|
599
|
-
- '[[ "${it_4_transport}" != "None" ]]
|
|
600
|
-
- '[[ "${it_4_compressed_jpeg_quality}" != "None" ]]
|
|
601
|
-
- '[[ "${it_4_ffmpeg_gop_size}" != "None" ]]
|
|
602
|
-
- '[[ "${it_4_ffmpeg_encoder_av_options}" != "None" ]]
|
|
603
|
-
- '[[ "${it_4_ffmpeg_bit_rate}" != "None" ]]
|
|
604
|
-
- '[[ "${it_4_foxglove_gop_size}" != "None" ]]
|
|
605
|
-
- '[[ "${it_4_foxglove_encoder_av_options}" != "None" ]]
|
|
606
|
-
- '[[ "${it_4_foxglove_bit_rate}" != "None" ]]
|
|
607
|
-
- '[[ "${it_4_foxglove_qmax}" != "None" ]]
|
|
612
|
+
- 'if [[ "${it_4_transport}" != "None" ]]; then args+=(-p "out_transport:=${it_4_transport}"); fi'
|
|
613
|
+
- 'if [[ "${it_4_compressed_jpeg_quality}" != "None" ]]; then args+=(-p "ut.compressed.jpeg_quality:=${it_4_compressed_jpeg_quality}"); fi'
|
|
614
|
+
- 'if [[ "${it_4_ffmpeg_gop_size}" != "None" ]]; then args+=(-p "ut.ffmpeg.gop_size:=${it_4_ffmpeg_gop_size}"); fi'
|
|
615
|
+
- 'if [[ "${it_4_ffmpeg_encoder_av_options}" != "None" ]]; then args+=(-p "ut.ffmpeg.encoder_av_options:=${it_4_ffmpeg_encoder_av_options}"); fi'
|
|
616
|
+
- 'if [[ "${it_4_ffmpeg_bit_rate}" != "None" ]]; then args+=(-p "ut.ffmpeg.bit_rate:=${it_4_ffmpeg_bit_rate}"); fi'
|
|
617
|
+
- 'if [[ "${it_4_foxglove_gop_size}" != "None" ]]; then args+=(-p "ut.foxglove.gop_size:=${it_4_foxglove_gop_size}"); fi'
|
|
618
|
+
- 'if [[ "${it_4_foxglove_encoder_av_options}" != "None" ]]; then args+=(-p "ut.foxglove.encoder_av_options:=${it_4_foxglove_encoder_av_options}"); fi'
|
|
619
|
+
- 'if [[ "${it_4_foxglove_bit_rate}" != "None" ]]; then args+=(-p "ut.foxglove.bit_rate:=${it_4_foxglove_bit_rate}"); fi'
|
|
620
|
+
- 'if [[ "${it_4_foxglove_qmax}" != "None" ]]; then args+=(-p "ut.foxglove.qmax:=${it_4_foxglove_qmax}"); fi'
|
|
608
621
|
- if [[ "${it_4_outgoing_suffix}" != "None" ]]; then outgoing_suffix="${it_4_outgoing_suffix}"; else outgoing_suffix="${it_4_transport}"; fi
|
|
609
622
|
- if [[ "${it_in_transport}" == "raw" ]]; then in_remap="in"; else in_remap="in/${it_in_transport}"; fi
|
|
610
623
|
- args+=(--remap "${in_remap}:=${it_4_topic}" --remap "out/${it_4_transport}:=${it_4_topic}/${outgoing_suffix}")
|
|
@@ -64,18 +64,34 @@ HEARTBEAT_MSG_TYPE = "com_msgs/msg/EchoHeartbeat"
|
|
|
64
64
|
COMPRESSED_MSG_TYPE = "com_msgs/msg/CompressedData"
|
|
65
65
|
OTA_STAMPED_MSG_TYPE = "com_msgs/msg/OtaStamped"
|
|
66
66
|
SENSOR_IMAGE_MSG_TYPE = "sensor_msgs/msg/Image"
|
|
67
|
+
SENSOR_COMPRESSED_IMAGE_MSG_TYPE = "sensor_msgs/msg/CompressedImage"
|
|
67
68
|
TRANSPORT_OUTPUT_TYPES = {
|
|
68
69
|
"compressed": "sensor_msgs/msg/CompressedImage",
|
|
69
70
|
"ffmpeg": "ffmpeg_image_transport_msgs/msg/FFMPEGPacket",
|
|
70
71
|
"foxglove": "foxglove_msgs/msg/CompressedVideo",
|
|
71
72
|
}
|
|
73
|
+
#: The image transports a reverse republish may decode *into*, and the message
|
|
74
|
+
#: type each one delivers. `raw` is the neutral reconstruction -- the transport
|
|
75
|
+
#: undone and nothing else -- and `compressed` trades a JPEG encode for roughly
|
|
76
|
+
#: an order of magnitude less data on the wire and in a `record -a`.
|
|
77
|
+
REPUBLISH_OUTPUT_TYPES = {
|
|
78
|
+
"raw": SENSOR_IMAGE_MSG_TYPE,
|
|
79
|
+
"compressed": SENSOR_COMPRESSED_IMAGE_MSG_TYPE,
|
|
80
|
+
}
|
|
72
81
|
|
|
73
82
|
|
|
74
83
|
@dataclass
|
|
75
84
|
class TransportSpec:
|
|
76
85
|
type: str
|
|
77
86
|
params: Dict[str, Any]
|
|
78
|
-
|
|
87
|
+
#: Reverse republish on the sending peer: decode the stream it just encoded,
|
|
88
|
+
#: so the machine that sends can see what the receiver will get. Optional.
|
|
89
|
+
local_republish: Optional[str] = None
|
|
90
|
+
#: Reverse republish on the receiving peer: the decode the receiving
|
|
91
|
+
#: application consumes. Optional too -- a consumer that subscribes through
|
|
92
|
+
#: image_transport itself, or one that only forwards or records packets,
|
|
93
|
+
#: does not want a second copy of every frame.
|
|
94
|
+
remote_republish: Optional[str] = None
|
|
79
95
|
|
|
80
96
|
|
|
81
97
|
@dataclass
|
|
@@ -1288,11 +1304,14 @@ def _delivered_topic(pipe: Dict[str, Any], final: str) -> str:
|
|
|
1288
1304
|
# renames nothing downstream of it.
|
|
1289
1305
|
topic = str(pipe["ota_in"])
|
|
1290
1306
|
transport = pipe.get("transport")
|
|
1291
|
-
if isinstance(transport, TransportSpec) and transport.
|
|
1292
|
-
#
|
|
1293
|
-
# `<encoded
|
|
1294
|
-
#
|
|
1295
|
-
|
|
1307
|
+
if isinstance(transport, TransportSpec) and transport.remote_republish:
|
|
1308
|
+
# The receiver's reverse republish decodes the encoded topic into
|
|
1309
|
+
# `<encoded>/<transport>`, and that decoded image -- not the encoded
|
|
1310
|
+
# packet -- is what the receiving application subscribes to.
|
|
1311
|
+
# `local_republish` is deliberately not consulted here: it is the
|
|
1312
|
+
# *sender's* preview, on the sender's machine, and says nothing about
|
|
1313
|
+
# what the receiver ends up reading.
|
|
1314
|
+
topic = str(pipe["irt_in"]) + f"/{transport.remote_republish}"
|
|
1296
1315
|
elif pipe.get("compress"):
|
|
1297
1316
|
topic = str(pipe["comp_in"])
|
|
1298
1317
|
if pipe.get("framebridge") == "global_to_local":
|
|
@@ -1544,8 +1563,8 @@ def _build_status_pipeline_spec(
|
|
|
1544
1563
|
if postprocessed != final:
|
|
1545
1564
|
native_in_type = base_type
|
|
1546
1565
|
transport = p.get("transport")
|
|
1547
|
-
if isinstance(transport, TransportSpec) and transport.
|
|
1548
|
-
native_in_type =
|
|
1566
|
+
if isinstance(transport, TransportSpec) and transport.remote_republish:
|
|
1567
|
+
native_in_type = REPUBLISH_OUTPUT_TYPES[transport.remote_republish]
|
|
1549
1568
|
stages.append(
|
|
1550
1569
|
{
|
|
1551
1570
|
"stage": "native_in",
|
|
@@ -1659,9 +1678,27 @@ def _compute_pipeline(
|
|
|
1659
1678
|
if not isinstance(t, dict) or "type" not in t:
|
|
1660
1679
|
raise ValueError(f"transport must be dict with 'type' for topic '{entry.base}'")
|
|
1661
1680
|
ttype = t["type"]
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1681
|
+
republish_keys = ("local_republish", "remote_republish")
|
|
1682
|
+
|
|
1683
|
+
def _republish(key: str) -> Optional[str]:
|
|
1684
|
+
value = t.get(key)
|
|
1685
|
+
if value is None:
|
|
1686
|
+
return None
|
|
1687
|
+
if value not in REPUBLISH_OUTPUT_TYPES:
|
|
1688
|
+
raise ValueError(
|
|
1689
|
+
f"transport.{key} must name an image transport "
|
|
1690
|
+
f"({'|'.join(sorted(REPUBLISH_OUTPUT_TYPES))}) for topic '{entry.base}', got {value!r}. "
|
|
1691
|
+
"Omit the key for no reverse republish on that side."
|
|
1692
|
+
)
|
|
1693
|
+
return str(value)
|
|
1694
|
+
|
|
1695
|
+
params = {k: v for k, v in t.items() if k not in ("type", *republish_keys)}
|
|
1696
|
+
transport = TransportSpec(
|
|
1697
|
+
type=ttype,
|
|
1698
|
+
params=params,
|
|
1699
|
+
local_republish=_republish("local_republish"),
|
|
1700
|
+
remote_republish=_republish("remote_republish"),
|
|
1701
|
+
)
|
|
1665
1702
|
|
|
1666
1703
|
topic = entry.base
|
|
1667
1704
|
|
|
@@ -1747,7 +1784,11 @@ def _compute_pipeline(
|
|
|
1747
1784
|
if transport:
|
|
1748
1785
|
it_in = topic
|
|
1749
1786
|
topic = topic + f"/{transport.type}"
|
|
1750
|
-
if transport.local_republish:
|
|
1787
|
+
if transport.local_republish or transport.remote_republish:
|
|
1788
|
+
# The encoded topic a reverse republish decodes *from*. One name for
|
|
1789
|
+
# both sides: each peer runs its own decoder against the copy it has
|
|
1790
|
+
# (the sender against what it just encoded, the receiver against what
|
|
1791
|
+
# arrived), and which of them exists is decided per side below.
|
|
1751
1792
|
irt_in = topic
|
|
1752
1793
|
|
|
1753
1794
|
# The wrapper is last, always. Its `seq` and send stamp describe whatever it
|
|
@@ -2607,7 +2648,11 @@ def func(
|
|
|
2607
2648
|
thr_items = [(p["thr_in"], p["throttle"]) for p in out_pipes if p["thr_in"]]
|
|
2608
2649
|
ipx_items = [(p["ipx_in"], p["pixel"]) for p in out_pipes if p["ipx_in"]]
|
|
2609
2650
|
it_items = [(p["it_in"], p["transport"]) for p in out_pipes if p["it_in"]]
|
|
2610
|
-
|
|
2651
|
+
# Sender-side reverse transport: this peer decodes what it just encoded,
|
|
2652
|
+
# so the machine that sends can see what the receiver will get.
|
|
2653
|
+
irt_items_local = [
|
|
2654
|
+
(p["irt_in"], p["transport"]) for p in out_pipes if p["irt_in"] and p["transport"].local_republish
|
|
2655
|
+
]
|
|
2611
2656
|
|
|
2612
2657
|
# Compression happens on the sender side for topics marked with processing.compress
|
|
2613
2658
|
comp_topics = _dedup_keep_order([p["comp_in"] for p in out_pipes if p["comp_in"]])
|
|
@@ -2660,15 +2705,15 @@ def func(
|
|
|
2660
2705
|
_assert_max("it", it_items, 4)
|
|
2661
2706
|
_assert_max("nor", nor_items, 4)
|
|
2662
2707
|
|
|
2663
|
-
#
|
|
2708
|
+
# Receiver-side reverse transport: this peer decodes what arrived, which
|
|
2709
|
+
# is the copy the receiving application reads (see `_delivered_topic`).
|
|
2664
2710
|
irt_items_remote = []
|
|
2665
2711
|
for e, p in zip(in_entries, in_pipes):
|
|
2666
|
-
if not p["irt_in"]:
|
|
2667
|
-
continue
|
|
2668
2712
|
tspec = p["transport"]
|
|
2669
|
-
|
|
2713
|
+
if not p["irt_in"] or not (tspec and tspec.remote_republish):
|
|
2714
|
+
continue
|
|
2670
2715
|
topic = _prefix_with_source_name_if_needed(local, remote, p["irt_in"])
|
|
2671
|
-
irt_items_remote.append((topic, tspec
|
|
2716
|
+
irt_items_remote.append((topic, tspec))
|
|
2672
2717
|
|
|
2673
2718
|
# Build plugin.yaml blocks
|
|
2674
2719
|
blocks: List[PluginBlock] = []
|
|
@@ -2953,9 +2998,9 @@ def func(
|
|
|
2953
2998
|
if p.get("it_in")
|
|
2954
2999
|
]
|
|
2955
3000
|
+ [
|
|
2956
|
-
f'{p["irt_in"]}/
|
|
3001
|
+
f'{p["irt_in"]}/{p["transport"].local_republish}'
|
|
2957
3002
|
for p in out_pipes
|
|
2958
|
-
if p.get("irt_in")
|
|
3003
|
+
if p.get("irt_in") and p["transport"].local_republish
|
|
2959
3004
|
]
|
|
2960
3005
|
)
|
|
2961
3006
|
blocks.append(
|
|
@@ -3152,12 +3197,15 @@ def func(
|
|
|
3152
3197
|
raise ValueError(f"Unsupported transport type '{tspec.type}'")
|
|
3153
3198
|
blocks.append(PluginBlock("it", items2))
|
|
3154
3199
|
|
|
3155
|
-
# Merge reverse-transport config for (a)
|
|
3200
|
+
# Merge reverse-transport config for (a) the sender's own preview of what
|
|
3201
|
+
# it encoded and (b) the decode of what arrived. Both run on *this* peer;
|
|
3202
|
+
# what differs is which copy they decode and which transport the session
|
|
3203
|
+
# asked each of them to publish in.
|
|
3156
3204
|
irt_all: List[Tuple[str, str, str]] = []
|
|
3157
3205
|
for t, tspec in irt_items_local:
|
|
3158
3206
|
assert tspec is not None
|
|
3159
|
-
irt_all.append((t, tspec.type,
|
|
3160
|
-
irt_all.extend((topic,
|
|
3207
|
+
irt_all.append((t, tspec.type, str(tspec.local_republish)))
|
|
3208
|
+
irt_all.extend((topic, tspec.type, str(tspec.remote_republish)) for topic, tspec in irt_items_remote)
|
|
3161
3209
|
_assert_max("irt", irt_all, 4)
|
|
3162
3210
|
if irt_all:
|
|
3163
3211
|
items2 = [("irt", True)]
|
|
@@ -337,6 +337,8 @@ tests/unit/test_ota_unwrapper.py
|
|
|
337
337
|
tests/unit/test_ota_wrapper.py
|
|
338
338
|
tests/unit/test_ota_xml.py
|
|
339
339
|
tests/unit/test_plots.py
|
|
340
|
+
tests/unit/test_qos_fallback_logging.py
|
|
341
|
+
tests/unit/test_relay_optional_parameters.py
|
|
340
342
|
tests/unit/test_session_pipeline.py
|
|
341
343
|
tests/unit/test_stage_latency.py
|
|
342
344
|
tests/unit/test_status_eval.py
|
{rosotacom_dev-2.5.dev38 → rosotacom_dev-2.5.dev40}/src/rosotacom_dev.egg-info/scm_file_list.json
RENAMED
|
@@ -332,6 +332,8 @@
|
|
|
332
332
|
"tests/unit/test_ota_wrapper.py",
|
|
333
333
|
"tests/unit/test_ota_xml.py",
|
|
334
334
|
"tests/unit/test_plots.py",
|
|
335
|
+
"tests/unit/test_qos_fallback_logging.py",
|
|
336
|
+
"tests/unit/test_relay_optional_parameters.py",
|
|
335
337
|
"tests/unit/test_session_pipeline.py",
|
|
336
338
|
"tests/unit/test_stage_latency.py",
|
|
337
339
|
"tests/unit/test_status_eval.py",
|
|
@@ -111,3 +111,77 @@ def test_the_hook_is_installed_once_even_if_sourced_twice(pane_env: tuple[Path,
|
|
|
111
111
|
|
|
112
112
|
(line,) = [ln for ln in result.stdout.splitlines() if ln.startswith("PC=")]
|
|
113
113
|
assert line.count("__rosotacom_note_exit") == 1
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# What the recorder cannot know, and why the session template has to care.
|
|
117
|
+
#
|
|
118
|
+
# The hook runs from PROMPT_COMMAND, so it sees every line a pane shell runs --
|
|
119
|
+
# including the lines that only assemble an argument list before the node
|
|
120
|
+
# starts. A line of the form `[[ cond ]] && args+=(...)` exits 1 whenever the
|
|
121
|
+
# condition is false, which is the normal case for every option a session leaves
|
|
122
|
+
# unset, so each one recorded itself as a dead pane. A peer then reported four
|
|
123
|
+
# exited panes at every start while nothing was wrong.
|
|
124
|
+
|
|
125
|
+
_UNSET_OPTION = '[[ "None" != "None" ]]'
|
|
126
|
+
_SET_OPTION = '[[ "22" != "None" ]]'
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _failure_log(catmux_dir: Path) -> Path:
|
|
130
|
+
return catmux_dir.parent / "pane_failures.log"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_the_short_circuit_form_records_a_false_failure(pane_env: tuple[Path, dict[str, str]]) -> None:
|
|
134
|
+
"""The shape that was in the template: correct behaviour, status 1."""
|
|
135
|
+
catmux_dir, env = pane_env
|
|
136
|
+
|
|
137
|
+
_run(f'args=(); {_UNSET_OPTION} && args+=(-p "bit_rate:=None")', env)
|
|
138
|
+
|
|
139
|
+
assert _failure_log(catmux_dir).is_file()
|
|
140
|
+
assert "exit=1" in _failure_log(catmux_dir).read_text(encoding="utf-8")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_the_if_form_leaves_an_unset_option_silent(pane_env: tuple[Path, dict[str, str]]) -> None:
|
|
144
|
+
"""The shape it was replaced with: same behaviour, status 0."""
|
|
145
|
+
catmux_dir, env = pane_env
|
|
146
|
+
|
|
147
|
+
_run(f'args=(); if {_UNSET_OPTION}; then args+=(-p "bit_rate:=None"); fi', env)
|
|
148
|
+
|
|
149
|
+
assert not _failure_log(catmux_dir).exists()
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def test_the_if_form_still_appends_a_set_option(pane_env: tuple[Path, dict[str, str]]) -> None:
|
|
153
|
+
"""Silencing the status must not silence the argument."""
|
|
154
|
+
catmux_dir, env = pane_env
|
|
155
|
+
|
|
156
|
+
result = _run(
|
|
157
|
+
f'args=(); if {_SET_OPTION}; then args+=(-p "bit_rate:=22"); fi\necho "ARGS=${{args[*]}}"',
|
|
158
|
+
env,
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
assert "ARGS=-p bit_rate:=22" in result.stdout
|
|
162
|
+
assert not _failure_log(catmux_dir).exists()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def test_no_session_template_line_uses_the_short_circuit_form() -> None:
|
|
166
|
+
"""The template is where this reaches a running session, so it is checked there."""
|
|
167
|
+
template = (
|
|
168
|
+
REPO_ROOT
|
|
169
|
+
/ "src"
|
|
170
|
+
/ "rosotacom"
|
|
171
|
+
/ "resources"
|
|
172
|
+
/ "ws"
|
|
173
|
+
/ "session"
|
|
174
|
+
/ "content"
|
|
175
|
+
/ "base"
|
|
176
|
+
/ "session_plugin_base.yaml"
|
|
177
|
+
)
|
|
178
|
+
offenders = [
|
|
179
|
+
line.strip()
|
|
180
|
+
for line in template.read_text(encoding="utf-8").splitlines()
|
|
181
|
+
if line.lstrip().startswith("- '[[") and "&&" in line
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
assert offenders == [], (
|
|
185
|
+
"these lines exit non-zero when their option is unset and land in "
|
|
186
|
+
f"pane_failures.log; use `if ...; then ...; fi`: {offenders}"
|
|
187
|
+
)
|