topicforge 0.2.0__tar.gz → 0.3.0__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.
- {topicforge-0.2.0 → topicforge-0.3.0}/.gitignore +5 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/CHANGELOG.md +47 -5
- {topicforge-0.2.0 → topicforge-0.3.0}/PKG-INFO +41 -13
- {topicforge-0.2.0 → topicforge-0.3.0}/README.md +34 -12
- topicforge-0.3.0/docs/DDS_QUICKSTART.md +156 -0
- topicforge-0.3.0/docs/MIGRATION_v0.2_to_v0.3.md +153 -0
- topicforge-0.3.0/docs/dds-interop-matrix.md +50 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/docs/product-plan.md +3 -3
- {topicforge-0.2.0 → topicforge-0.3.0}/pyproject.toml +16 -3
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/__init__.py +1 -1
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/base.py +3 -1
- topicforge-0.3.0/src/topicforge/adapters/common/__init__.py +17 -0
- topicforge-0.3.0/src/topicforge/adapters/common/dds_helpers.py +111 -0
- topicforge-0.3.0/src/topicforge/adapters/dds_cyclone/adapter.py +384 -0
- topicforge-0.3.0/src/topicforge/adapters/dds_fast/__init__.py +11 -0
- topicforge-0.3.0/src/topicforge/adapters/dds_fast/adapter.py +493 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_live/adapter.py +6 -3
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_mock/fixtures.py +10 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/config/settings.py +19 -8
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/models/schemas.py +16 -7
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/services/factory.py +51 -17
- topicforge-0.3.0/src/topicforge/services/health.py +65 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/services/inspector.py +32 -6
- topicforge-0.3.0/tests/test_config.py +170 -0
- topicforge-0.3.0/tests/test_cyclone_adapter.py +117 -0
- topicforge-0.3.0/tests/test_dds_cross_vendor.py +136 -0
- topicforge-0.3.0/tests/test_dds_helpers.py +117 -0
- topicforge-0.3.0/tests/test_fast_adapter.py +146 -0
- topicforge-0.3.0/tests/test_health.py +126 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_qos_analyzer.py +108 -1
- topicforge-0.2.0/docs/DDS_QUICKSTART.md +0 -111
- topicforge-0.2.0/docs/v0.1.2-action-plan.md +0 -356
- topicforge-0.2.0/src/topicforge/adapters/common/__init__.py +0 -5
- topicforge-0.2.0/src/topicforge/adapters/dds_cyclone/adapter.py +0 -110
- topicforge-0.2.0/src/topicforge/services/health.py +0 -32
- topicforge-0.2.0/tests/test_config.py +0 -58
- topicforge-0.2.0/tests/test_cyclone_adapter.py +0 -56
- topicforge-0.2.0/tests/test_health.py +0 -56
- {topicforge-0.2.0 → topicforge-0.3.0}/LICENSE +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/docs/MIGRATION_v0.1_to_v0.2.md +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/docs/TESTING.md +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/docs/pro.md +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/__main__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/common/qos_analyzer.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/dds_cyclone/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_live/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_mock/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/adapters/ros2_mock/adapter.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/config/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/models/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/server/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/server/app.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/services/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/services/constants.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/telemetry/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/telemetry/client.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/tools/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/src/topicforge/tools/handlers.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/__init__.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/conftest.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/fixtures/csv_echo_imu.txt +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/fixtures/csv_echo_pose_multi.txt +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_dds_schemas.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_inspector.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_live_adapter_parse.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_live_adapter_subprocess.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_mock_adapter.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_telemetry.py +0 -0
- {topicforge-0.2.0 → topicforge-0.3.0}/tests/test_tools_integration.py +0 -0
|
@@ -212,6 +212,11 @@ CLAUDE*.md
|
|
|
212
212
|
# decisions are bisectable per release.
|
|
213
213
|
!/docs/projet-file/*-audit-*.md
|
|
214
214
|
!/docs/projet-file/audit-*.md
|
|
215
|
+
# External reference material (OMG interop reports, third-party specs
|
|
216
|
+
# snapshots) the maintainer wants pinned in git so strategy decisions
|
|
217
|
+
# remain reproducible. Tracked, not part of sdist.
|
|
218
|
+
!/docs/projet-file/references/
|
|
219
|
+
!/docs/projet-file/references/**
|
|
215
220
|
/docs/assets/screencast-raw/
|
|
216
221
|
|
|
217
222
|
|
|
@@ -7,11 +7,52 @@ and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-05-14
|
|
11
|
+
|
|
12
|
+
### Strategic
|
|
13
|
+
|
|
14
|
+
- **OMG DDS-RTPS multi-vendor positioning.** TopicForge is now framed as a read-only DDS-RTPS observer that joins the bus via one of two OSS Python participants — Eclipse CycloneDDS or eProsima Fast DDS — and observes every conformant vendor on the domain (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, etc.) regardless of host language. See `docs/dds-interop-matrix.md` for the canonical statement and `docs/projet-file/references/omg-dds-interop-2025-05-08.xlsx` for the OMG May 2025 interop reference. The earlier v0.2.0/v0.3.0 phasing (Cyclone-only at v0.3.0, RTI at v0.3.0+) is collapsed: multi-vendor OSS lands together at v0.3.0 ; RTI Pro defers to v0.4.0+.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Real `CycloneDdsAdapter`** — replaces the v0.2.0 stub with actual CycloneDDS discovery via `cyclonedds.builtin.BuiltinDataReader` on the DCPS participant/subscription/publication builtin topics. QoS extracted via `Policy.*` class-name introspection. `take_iter(timeout=...)` for bounded discovery. Lazy-imported via `services.factory`.
|
|
19
|
+
- **`FastDdsAdapter`** (`adapters/dds_fast/`) — new parallel OSS adapter built on the `fastdds` Python bindings (BSD-licensed, eProsima). Duck-typed listener subclass aggregates discovery callbacks under an RLock. Bounded `discovery_wait_ms=1500` warm-up after participant creation. `close()` releases the participant via `factory.delete_participant`.
|
|
20
|
+
- **`adapters/common/dds_helpers.py`** — vendor-neutral helpers: `canonicalize_vendor_id` (OMG vendor_id → canonical tag), `format_guid` (16-byte GUID → `xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx` canonical text), `DDS_ONLY_ERROR_MSG` (shared remediation message). Pure functions, no DDS dependency.
|
|
21
|
+
- **Pyproject extras refactor**: `[dds-cyclone]` (Cyclone only), `[dds-fast]` (Fast only), `[dds]` (both — union of v0.2.0 `[dds]` behavior plus fastdds).
|
|
22
|
+
- **`TOPICFORGE_DDS_BACKEND=fast`** — new accepted value alongside `mock | cyclone | rti | auto`.
|
|
23
|
+
- **3rd mock participant** with `vendor="fast"` exercises the multi-vendor positioning in mock mode.
|
|
24
|
+
- **New pytest marker** `requires_fastdds` — auto-skips without the binding.
|
|
25
|
+
- **35+ new tests**: `tests/test_dds_helpers.py`, `tests/test_fast_adapter.py`, `tests/test_dds_cross_vendor.py` (parametrized on both adapters), 6 analyzer edge cases in `tests/test_qos_analyzer.py`, 4 new health tests for DDS field population.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **`ParticipantInfo.vendor` Literal widened** to include `"fast"`. **Strict JSON-schema clients pinned to v0.2.0 will reject `vendor:fast` unless their schema is regenerated.** Standard MCP clients reading tool descriptions dynamically are unaffected.
|
|
30
|
+
- **`HealthReport.dds_backend` Literal widened** to include `"fast"`. Same soft-breaking caveat.
|
|
31
|
+
- **`AdapterName` Literal widened** to include `"fast"` (internal type — no wire impact).
|
|
32
|
+
- **`DdsBackend` / `ResolvedDdsBackend`** widened to include `"fast"`.
|
|
33
|
+
- **`Settings.effective_dds_backend` auto resolution** now prefers Fast DDS > Cyclone DDS > Mock (was Cyclone > Mock in v0.2.0). v0.2.0 users with only `cyclonedds` installed see no change — Fast is unimportable on their host. Users with both SDKs installed will see Fast selected. Reflects the OMG May 2025 interop matrix.
|
|
34
|
+
- **`HealthService.report()`** now populates `dds_backend`, `dds_domain_id`, `middleware_available` — previously returned schema defaults regardless of configuration (v0.2.0 latent bug). `middleware_available` is checked via `importlib.util.find_spec` on the active backend's Python module.
|
|
35
|
+
- **`Ros2CliAdapter._DDS_MODULE_INACTIVE_MSG`** updated to mention both `pip install topicforge[dds-cyclone]` and `pip install topicforge[dds-fast]` remediation paths.
|
|
36
|
+
- **`Inspector` DDS topic validator relaxed** — `detect_qos_mismatches` and `peek_dds_samples` now accept DDS-native topic names (no leading `/` required, `::` separators allowed) via a new `_validate_topic_name_dds`. The strict ROS2 validator stays in place for the 5 ROS2 graph methods. Resolves audit-2026-05-14 "Refactor opportunities" #5.
|
|
37
|
+
|
|
38
|
+
### Removed
|
|
39
|
+
|
|
40
|
+
- **`CycloneDdsAdapter` v0.2.0 stub** — `_NOT_IMPLEMENTED_MSG` and the corresponding `test_dds_surface_raises_stub_error_in_v020` test removed. The 3 DDS methods now serve real results when cyclonedds is installed.
|
|
41
|
+
|
|
42
|
+
### Notes
|
|
43
|
+
|
|
44
|
+
- **OMG-DDS-RTPS interoperability** is the protocol guarantee that makes multi-vendor observation work — see `docs/dds-interop-matrix.md` and `docs/projet-file/references/omg-dds-interop-2025-05-08.xlsx`.
|
|
45
|
+
- **v0.3.0 `peek_dds_samples` limitation** — full-fidelity on the 4 builtin DCPS topics (`DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`) ; arbitrary user topics raise an `AdapterError` with a v0.3.x roadmap pointer (XTypes/IDL discovery is the missing piece, both for Cyclone via `cyclonedds.dynamic.get_types_for_typeid` and for Fast DDS via XTypes remote type lookup).
|
|
46
|
+
- **`pip install topicforge[dds]` in v0.3.0** now pulls BOTH `cyclonedds` and `fastdds` (was Cyclone only in v0.2.0). Use `[dds-cyclone]` or `[dds-fast]` for single-vendor installs. See `docs/MIGRATION_v0.2_to_v0.3.md`.
|
|
47
|
+
- **Fast DDS pin**: `fastdds>=2.6.1,<3` — Fast DDS 3.x binding wheels for Python 3.11+ on Windows / Linux are not yet stable. Bump when upstream cuts stable 3.x wheels.
|
|
48
|
+
- **No code change to the 5 ROS2 tools** — `health_check`, `list_topics`, `get_topic_info`, `sample_messages`, `analyze_bag` behave identically to v0.2.0. The `mode_effective` wire contract is unchanged ; `health_check` now populates DDS fields correctly.
|
|
49
|
+
- **Full migration guide**: `docs/MIGRATION_v0.2_to_v0.3.md`.
|
|
50
|
+
|
|
10
51
|
## [0.2.0] - 2026-05-14
|
|
11
52
|
|
|
12
53
|
### Strategic
|
|
13
54
|
|
|
14
|
-
- **Mono-MCP pivot (2026-05-14).** The 3-to-5-MCP pack draft is collapsed into a 2-product strategy: TopicForge umbrella (this product — covers ROS2 today and grows a DDS observability module starting with v0.2.0), and **DatasetForge** (Vision Dataset Inspector, the standalone second product).
|
|
55
|
+
- **Mono-MCP pivot (2026-05-14).** The 3-to-5-MCP pack draft is collapsed into a 2-product strategy: TopicForge umbrella (this product — covers ROS2 today and grows a DDS observability module starting with v0.2.0), and **DatasetForge** (Vision Dataset Inspector, the standalone second product). The previously-planned standalone DDS-MCP product is cancelled — its spec is reframed as the TopicForge DDS module spec at `docs/projet-file/mcp-02-spec.md`. Motif: solo-maintenance cost of two parallel repos was the binding constraint, and ROS2 / DDS are the same problem shape (typed pub/sub graph introspection) under the same `MiddlewareAdapter` superset.
|
|
15
56
|
|
|
16
57
|
### Added
|
|
17
58
|
|
|
@@ -54,12 +95,12 @@ and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/
|
|
|
54
95
|
### Added
|
|
55
96
|
|
|
56
97
|
- **`mode_effective` on every tool response (schema, soft-breaking additive).** `TopicInfo`, `SampleResult`, and `BagAnalysis` now carry a required `mode_effective: Literal["mock", "live"]` field. A new `effective_mode` property on the `RosAdapter` protocol is the single source of truth; `Ros2CliAdapter` returns `"live"`, `MockAdapter` returns `"mock"`, services thread it through at result construction time. **Producer side**: Python code constructing these models directly must now supply `mode_effective` — models are `frozen=True, extra="forbid"` with no default. **Client side (over MCP)**: additive — an MCP client consuming JSON sees one extra key per response and is unaffected unless it strictly validates against the v0.1.1 schema with a no-extra-keys assumption.
|
|
57
|
-
- **
|
|
58
|
-
- **DatasetForge spec** (`docs/projet-file/mcp-03-spec.md`). Vision Dataset Inspector spec, re-slotted to MCP 03 after competitive-landscape audit that surfaced zero non-ROS DDS-MCP projects and made
|
|
98
|
+
- **DDS-MCP spec** (`docs/projet-file/mcp-02-spec.md`). Strategic draft for MCP 02 at the time: safety-first read-only DDS observability across middleware vendors (CycloneDDS OSS, RTI Connext Pro tier). Five tools, `MiddlewareAdapter` protocol, mock + cyclone + rti + auto modes. Reviewer notes appended (2026-05-13): wrong cross-reference in §11 flagged. (Reframed the next day as a TopicForge module after the mono-MCP pivot — see [0.2.0] Strategic section.)
|
|
99
|
+
- **DatasetForge spec** (`docs/projet-file/mcp-03-spec.md`). Vision Dataset Inspector spec, re-slotted to MCP 03 after competitive-landscape audit that surfaced zero non-ROS DDS-MCP projects and made a standalone DDS-MCP the stronger MCP 02 candidate. Reviewer notes appended (2026-05-13): contradictory §11 phrasing and two implicitly-resolved open questions flagged.
|
|
59
100
|
|
|
60
101
|
### Changed
|
|
61
102
|
|
|
62
|
-
- **Safety-first read-only repositioning.** README and `docs/product-plan.md §1` now lead with "read-only by architecture, not by configuration" as the primary identity. Pack candidate list updated: MCP 02
|
|
103
|
+
- **Safety-first read-only repositioning.** README and `docs/product-plan.md §1` now lead with "read-only by architecture, not by configuration" as the primary identity. Pack candidate list updated: MCP 02 reframed to a non-ROS DDS observability MCP (later folded into TopicForge itself by the 2026-05-14 multi-vendor reframe — see v0.3.0 entry); DatasetForge slides to MCP 03. Strategic context in `docs/product-plan.md §4` and §8 (DDS-complete horizon).
|
|
63
104
|
- **Internal API.** `Inspector.sample_messages` now returns a `SampleResult` envelope (previously a `list[MessageSample]`). The MCP-facing tool handler is reduced to a thin pass-through. No effect on the tool's wire-level response shape (handlers already wrapped the list into `SampleResult`), but flagged here for anyone importing `Inspector` directly outside this repo.
|
|
64
105
|
|
|
65
106
|
### Internal
|
|
@@ -105,7 +146,8 @@ Initial MVP release of TopicForge — ROS Topic Inspector & Bag Analyzer MCP ser
|
|
|
105
146
|
- The write path (publishing, commanding robots) is intentionally out of scope for the MVP.
|
|
106
147
|
- `analyze_bag` in live mode parses `ros2 bag info` text output; deeper anomaly detection remains mock-only for now.
|
|
107
148
|
|
|
108
|
-
[Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.
|
|
149
|
+
[Unreleased]: https://github.com/yaniswav/TopicForge/compare/v0.3.0...HEAD
|
|
150
|
+
[0.3.0]: https://github.com/yaniswav/TopicForge/compare/v0.2.0...v0.3.0
|
|
109
151
|
[0.2.0]: https://github.com/yaniswav/TopicForge/compare/v0.1.2...v0.2.0
|
|
110
152
|
[0.1.2]: https://github.com/yaniswav/TopicForge/compare/v0.1.1...v0.1.2
|
|
111
153
|
[0.1.1]: https://github.com/yaniswav/TopicForge/compare/v0.1.0...v0.1.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: topicforge
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: ROS Topic Inspector & Bag Analyzer MCP server for AI agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/yaniswav/TopicForge
|
|
6
6
|
Project-URL: Repository, https://github.com/yaniswav/TopicForge
|
|
@@ -42,8 +42,14 @@ Requires-Dist: mcp>=1.0.0
|
|
|
42
42
|
Requires-Dist: pydantic>=2.6
|
|
43
43
|
Provides-Extra: all
|
|
44
44
|
Requires-Dist: cyclonedds>=0.10; extra == 'all'
|
|
45
|
+
Requires-Dist: fastdds<3,>=2.6.1; extra == 'all'
|
|
45
46
|
Provides-Extra: dds
|
|
46
47
|
Requires-Dist: cyclonedds>=0.10; extra == 'dds'
|
|
48
|
+
Requires-Dist: fastdds<3,>=2.6.1; extra == 'dds'
|
|
49
|
+
Provides-Extra: dds-cyclone
|
|
50
|
+
Requires-Dist: cyclonedds>=0.10; extra == 'dds-cyclone'
|
|
51
|
+
Provides-Extra: dds-fast
|
|
52
|
+
Requires-Dist: fastdds<3,>=2.6.1; extra == 'dds-fast'
|
|
47
53
|
Provides-Extra: dev
|
|
48
54
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
49
55
|
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
@@ -56,7 +62,7 @@ Description-Content-Type: text/markdown
|
|
|
56
62
|
[](https://github.com/yaniswav/TopicForge/blob/main/LICENSE)
|
|
57
63
|
[](https://github.com/yaniswav/TopicForge#security-model)
|
|
58
64
|
|
|
59
|
-
> **The safety-first read-only MCP for ROS2 robotics — now with
|
|
65
|
+
> **The safety-first read-only MCP for ROS2 robotics — now with multi-vendor OMG DDS-RTPS observability (v0.3.0).** TopicForge lets AI agents inspect your ROS2 graph, ROS bag files, and (since v0.2.0) the raw DDS layer beneath ROS, without ever publishing back to the bus. v0.3.0 ships two OSS Python adapters — Eclipse CycloneDDS and eProsima Fast DDS — each joining the bus as a read-only DDS-RTPS participant that observes **every conformant vendor on the wire** (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, etc.) via the OMG protocol guarantee. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md) for the canonical multi-vendor positioning and the OMG May 2025 interop reference.
|
|
60
66
|
|
|
61
67
|
TopicForge is a production-minded MCP (Model Context Protocol) server that lets AI agents — such as Claude — inspect ROS2 topics, analyze ROS bag files, and (since v0.2.0) observe the raw DDS layer through a clean, structured tool interface. It is read-only by **architecture**, not by configuration: there is no write path to misconfigure, no permission system to audit, no liability conversation to have. The MCP client can see the robot stack; it cannot touch it.
|
|
62
68
|
|
|
@@ -188,15 +194,29 @@ TOPICFORGE_MODE=live python -m topicforge
|
|
|
188
194
|
|
|
189
195
|
TopicForge invokes the `ros2` CLI under the hood, so it does **not** require `rclpy` to be importable. This keeps the live adapter portable across ROS2 distros.
|
|
190
196
|
|
|
191
|
-
### DDS support (v0.
|
|
197
|
+
### Multi-vendor DDS support (v0.3.0+)
|
|
192
198
|
|
|
193
|
-
Beyond ROS2 graph introspection, TopicForge
|
|
199
|
+
Beyond ROS2 graph introspection, TopicForge observes the raw DDS bus directly via one of two OSS Python adapters — Eclipse CycloneDDS or eProsima Fast DDS — each joining as a **read-only DDS-RTPS participant**. By the OMG-DDS-RTPS protocol guarantee, both adapters see every conformant participant on the domain (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, InterCOM, etc.) regardless of host language. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md) for the canonical multi-vendor positioning and the [OMG May 2025 interop reference](docs/projet-file/references/omg-dds-interop-2025-05-08.xlsx).
|
|
194
200
|
|
|
195
|
-
|
|
201
|
+
Useful for non-ROS DDS stacks (defense, aerospace, automotive AUTOSAR Adaptive, industrial integration) and for diagnosing why a ROS2 subscriber isn't receiving when the graph says it should. Same safety-first contract : read-only by **architecture** — the `MiddlewareAdapter` protocol does not expose a write method on any backend.
|
|
202
|
+
|
|
203
|
+
Install one or both OSS backends :
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Single vendor — install only what you need
|
|
207
|
+
pip install topicforge[dds-cyclone] # Eclipse CycloneDDS only
|
|
208
|
+
pip install topicforge[dds-fast] # eProsima Fast DDS only
|
|
209
|
+
pip install topicforge[dds] # both OSS backends (union)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Then select a backend :
|
|
196
213
|
|
|
197
214
|
```bash
|
|
198
|
-
pip install topicforge[dds]
|
|
199
215
|
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
|
|
216
|
+
# or:
|
|
217
|
+
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=fast python -m topicforge
|
|
218
|
+
# or, auto-select Fast > Cyclone > Mock:
|
|
219
|
+
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=auto python -m topicforge
|
|
200
220
|
```
|
|
201
221
|
|
|
202
222
|
Three new MCP tools (in addition to the five ROS2 tools above) :
|
|
@@ -207,11 +227,13 @@ Three new MCP tools (in addition to the five ROS2 tools above) :
|
|
|
207
227
|
| `detect_qos_mismatches` | Reader/writer QoS incompatibilities preventing communication on a topic |
|
|
208
228
|
| `peek_dds_samples` | Recent samples on a raw DDS topic (distinct from `sample_messages` on ROS2 graph)|
|
|
209
229
|
|
|
210
|
-
**v0.
|
|
230
|
+
**v0.3.0 limitation — single adapter at a time.** TopicForge selects one adapter per server run. With `TOPICFORGE_DDS_BACKEND=cyclone` (or `fast`), the 3 DDS tools work and the 5 ROS2 tools raise a clear `AdapterError` ; vice versa with the default `TOPICFORGE_DDS_BACKEND=mock`. The mock backend exposes all 8 tools against deterministic fixtures (incl. a `vendor="fast"` participant) for local development. A composite adapter delegating per-tool category is a v0.3.x roadmap item.
|
|
231
|
+
|
|
232
|
+
**v0.3.0 limitation — `peek_dds_samples` scope.** Full-fidelity on the 4 builtin DCPS topics (`DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`) ; arbitrary user topics raise an `AdapterError` pointing at the v0.3.x XTypes/IDL roadmap. The other two DDS tools (`list_participants`, `detect_qos_mismatches`) work end-to-end on any user-topic deployment.
|
|
211
233
|
|
|
212
|
-
|
|
234
|
+
**`RTI Connext`** is v0.4.0+ Pro tier (BYO license — see `docs/pro.md`).
|
|
213
235
|
|
|
214
|
-
**Full 5-minute walkthrough** —
|
|
236
|
+
**Full 5-minute walkthrough** — backend selection, the canonical QoS-mismatch debugging scenario, troubleshooting — lives in [`docs/DDS_QUICKSTART.md`](docs/DDS_QUICKSTART.md). Migration from v0.2.0 in [`docs/MIGRATION_v0.2_to_v0.3.md`](docs/MIGRATION_v0.2_to_v0.3.md).
|
|
215
237
|
|
|
216
238
|
### Configure with Claude Desktop
|
|
217
239
|
|
|
@@ -266,7 +288,7 @@ make check # both, plus tests (CI bundle)
|
|
|
266
288
|
| `TOPICFORGE_LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
|
|
267
289
|
| `TOPICFORGE_ROS2_BIN` | `ros2` | Name (or path) of the ROS2 CLI binary |
|
|
268
290
|
| `TOPICFORGE_TELEMETRY` | `off` | Opt-in anonymous usage telemetry. See [Telemetry](#telemetry). |
|
|
269
|
-
| `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `rti`, or `auto`. See [DDS support](#dds-support-
|
|
291
|
+
| `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `fast`, `rti`, or `auto`. `auto` resolves to Fast > Cyclone > Mock. See [Multi-vendor DDS support](#multi-vendor-dds-support-v030). |
|
|
270
292
|
| `TOPICFORGE_DDS_DOMAIN_ID` | `0` | DDS domain id observed (0..232) when a DDS backend is active. |
|
|
271
293
|
|
|
272
294
|
See [`.env.example`](.env.example).
|
|
@@ -341,7 +363,10 @@ See [`docs/product-plan.md`](docs/product-plan.md) for the full product trajecto
|
|
|
341
363
|
Near-term additions on the bench:
|
|
342
364
|
|
|
343
365
|
- `rclpy`-backed live adapter for faster & richer sampling
|
|
344
|
-
-
|
|
366
|
+
- XTypes/IDL discovery to extend `peek_dds_samples` to arbitrary user topics (today: 4 builtin DCPS topics only) — v0.3.x patch
|
|
367
|
+
- Extended QoS coverage (Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget) — v0.3.x patch
|
|
368
|
+
- Composite adapter delegating per-tool category, so ROS2 + DDS surfaces work simultaneously — v0.3.x patch
|
|
369
|
+
- `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`) — v0.4.0+
|
|
345
370
|
- URDF inspector / validator MCP tools
|
|
346
371
|
- Bag anomaly detection (clock jumps, gaps, dropped frames, TF tree health)
|
|
347
372
|
- Dataset export helpers (rosbag → COCO / HF Datasets)
|
|
@@ -365,10 +390,13 @@ topicforge-mcp/
|
|
|
365
390
|
│ ├── services/ # Domain orchestration
|
|
366
391
|
│ ├── adapters/
|
|
367
392
|
│ │ ├── ros2_live/ # `ros2` CLI wrappers
|
|
368
|
-
│ │
|
|
393
|
+
│ │ ├── ros2_mock/ # Deterministic fixtures (incl. DDS)
|
|
394
|
+
│ │ ├── dds_cyclone/ # Eclipse CycloneDDS adapter (lazy import)
|
|
395
|
+
│ │ ├── dds_fast/ # eProsima Fast DDS adapter (lazy import)
|
|
396
|
+
│ │ └── common/ # Vendor-neutral helpers + pure QoS analyzer
|
|
369
397
|
│ ├── models/ # Pydantic schemas
|
|
370
398
|
│ └── config/ # Settings & mode resolution
|
|
371
|
-
└── tests/ # Pytest suite (mock-only, no ROS2 required)
|
|
399
|
+
└── tests/ # Pytest suite (mock-only, no ROS2/DDS required)
|
|
372
400
|
```
|
|
373
401
|
|
|
374
402
|
## License
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/yaniswav/TopicForge/blob/main/LICENSE)
|
|
6
6
|
[](https://github.com/yaniswav/TopicForge#security-model)
|
|
7
7
|
|
|
8
|
-
> **The safety-first read-only MCP for ROS2 robotics — now with
|
|
8
|
+
> **The safety-first read-only MCP for ROS2 robotics — now with multi-vendor OMG DDS-RTPS observability (v0.3.0).** TopicForge lets AI agents inspect your ROS2 graph, ROS bag files, and (since v0.2.0) the raw DDS layer beneath ROS, without ever publishing back to the bus. v0.3.0 ships two OSS Python adapters — Eclipse CycloneDDS and eProsima Fast DDS — each joining the bus as a read-only DDS-RTPS participant that observes **every conformant vendor on the wire** (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, etc.) via the OMG protocol guarantee. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md) for the canonical multi-vendor positioning and the OMG May 2025 interop reference.
|
|
9
9
|
|
|
10
10
|
TopicForge is a production-minded MCP (Model Context Protocol) server that lets AI agents — such as Claude — inspect ROS2 topics, analyze ROS bag files, and (since v0.2.0) observe the raw DDS layer through a clean, structured tool interface. It is read-only by **architecture**, not by configuration: there is no write path to misconfigure, no permission system to audit, no liability conversation to have. The MCP client can see the robot stack; it cannot touch it.
|
|
11
11
|
|
|
@@ -137,15 +137,29 @@ TOPICFORGE_MODE=live python -m topicforge
|
|
|
137
137
|
|
|
138
138
|
TopicForge invokes the `ros2` CLI under the hood, so it does **not** require `rclpy` to be importable. This keeps the live adapter portable across ROS2 distros.
|
|
139
139
|
|
|
140
|
-
### DDS support (v0.
|
|
140
|
+
### Multi-vendor DDS support (v0.3.0+)
|
|
141
141
|
|
|
142
|
-
Beyond ROS2 graph introspection, TopicForge
|
|
142
|
+
Beyond ROS2 graph introspection, TopicForge observes the raw DDS bus directly via one of two OSS Python adapters — Eclipse CycloneDDS or eProsima Fast DDS — each joining as a **read-only DDS-RTPS participant**. By the OMG-DDS-RTPS protocol guarantee, both adapters see every conformant participant on the domain (RTI Connext, OpenDDS, CoreDX, Dust DDS in Rust, InterCOM, etc.) regardless of host language. See [`docs/dds-interop-matrix.md`](docs/dds-interop-matrix.md) for the canonical multi-vendor positioning and the [OMG May 2025 interop reference](docs/projet-file/references/omg-dds-interop-2025-05-08.xlsx).
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
Useful for non-ROS DDS stacks (defense, aerospace, automotive AUTOSAR Adaptive, industrial integration) and for diagnosing why a ROS2 subscriber isn't receiving when the graph says it should. Same safety-first contract : read-only by **architecture** — the `MiddlewareAdapter` protocol does not expose a write method on any backend.
|
|
145
|
+
|
|
146
|
+
Install one or both OSS backends :
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Single vendor — install only what you need
|
|
150
|
+
pip install topicforge[dds-cyclone] # Eclipse CycloneDDS only
|
|
151
|
+
pip install topicforge[dds-fast] # eProsima Fast DDS only
|
|
152
|
+
pip install topicforge[dds] # both OSS backends (union)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Then select a backend :
|
|
145
156
|
|
|
146
157
|
```bash
|
|
147
|
-
pip install topicforge[dds]
|
|
148
158
|
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
|
|
159
|
+
# or:
|
|
160
|
+
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=fast python -m topicforge
|
|
161
|
+
# or, auto-select Fast > Cyclone > Mock:
|
|
162
|
+
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=auto python -m topicforge
|
|
149
163
|
```
|
|
150
164
|
|
|
151
165
|
Three new MCP tools (in addition to the five ROS2 tools above) :
|
|
@@ -156,11 +170,13 @@ Three new MCP tools (in addition to the five ROS2 tools above) :
|
|
|
156
170
|
| `detect_qos_mismatches` | Reader/writer QoS incompatibilities preventing communication on a topic |
|
|
157
171
|
| `peek_dds_samples` | Recent samples on a raw DDS topic (distinct from `sample_messages` on ROS2 graph)|
|
|
158
172
|
|
|
159
|
-
**v0.
|
|
173
|
+
**v0.3.0 limitation — single adapter at a time.** TopicForge selects one adapter per server run. With `TOPICFORGE_DDS_BACKEND=cyclone` (or `fast`), the 3 DDS tools work and the 5 ROS2 tools raise a clear `AdapterError` ; vice versa with the default `TOPICFORGE_DDS_BACKEND=mock`. The mock backend exposes all 8 tools against deterministic fixtures (incl. a `vendor="fast"` participant) for local development. A composite adapter delegating per-tool category is a v0.3.x roadmap item.
|
|
174
|
+
|
|
175
|
+
**v0.3.0 limitation — `peek_dds_samples` scope.** Full-fidelity on the 4 builtin DCPS topics (`DCPSParticipant`, `DCPSSubscription`, `DCPSPublication`) ; arbitrary user topics raise an `AdapterError` pointing at the v0.3.x XTypes/IDL roadmap. The other two DDS tools (`list_participants`, `detect_qos_mismatches`) work end-to-end on any user-topic deployment.
|
|
160
176
|
|
|
161
|
-
|
|
177
|
+
**`RTI Connext`** is v0.4.0+ Pro tier (BYO license — see `docs/pro.md`).
|
|
162
178
|
|
|
163
|
-
**Full 5-minute walkthrough** —
|
|
179
|
+
**Full 5-minute walkthrough** — backend selection, the canonical QoS-mismatch debugging scenario, troubleshooting — lives in [`docs/DDS_QUICKSTART.md`](docs/DDS_QUICKSTART.md). Migration from v0.2.0 in [`docs/MIGRATION_v0.2_to_v0.3.md`](docs/MIGRATION_v0.2_to_v0.3.md).
|
|
164
180
|
|
|
165
181
|
### Configure with Claude Desktop
|
|
166
182
|
|
|
@@ -215,7 +231,7 @@ make check # both, plus tests (CI bundle)
|
|
|
215
231
|
| `TOPICFORGE_LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |
|
|
216
232
|
| `TOPICFORGE_ROS2_BIN` | `ros2` | Name (or path) of the ROS2 CLI binary |
|
|
217
233
|
| `TOPICFORGE_TELEMETRY` | `off` | Opt-in anonymous usage telemetry. See [Telemetry](#telemetry). |
|
|
218
|
-
| `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `rti`, or `auto`. See [DDS support](#dds-support-
|
|
234
|
+
| `TOPICFORGE_DDS_BACKEND` | `mock` | DDS module backend: `mock`, `cyclone`, `fast`, `rti`, or `auto`. `auto` resolves to Fast > Cyclone > Mock. See [Multi-vendor DDS support](#multi-vendor-dds-support-v030). |
|
|
219
235
|
| `TOPICFORGE_DDS_DOMAIN_ID` | `0` | DDS domain id observed (0..232) when a DDS backend is active. |
|
|
220
236
|
|
|
221
237
|
See [`.env.example`](.env.example).
|
|
@@ -290,7 +306,10 @@ See [`docs/product-plan.md`](docs/product-plan.md) for the full product trajecto
|
|
|
290
306
|
Near-term additions on the bench:
|
|
291
307
|
|
|
292
308
|
- `rclpy`-backed live adapter for faster & richer sampling
|
|
293
|
-
-
|
|
309
|
+
- XTypes/IDL discovery to extend `peek_dds_samples` to arbitrary user topics (today: 4 builtin DCPS topics only) — v0.3.x patch
|
|
310
|
+
- Extended QoS coverage (Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget) — v0.3.x patch
|
|
311
|
+
- Composite adapter delegating per-tool category, so ROS2 + DDS surfaces work simultaneously — v0.3.x patch
|
|
312
|
+
- `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`) — v0.4.0+
|
|
294
313
|
- URDF inspector / validator MCP tools
|
|
295
314
|
- Bag anomaly detection (clock jumps, gaps, dropped frames, TF tree health)
|
|
296
315
|
- Dataset export helpers (rosbag → COCO / HF Datasets)
|
|
@@ -314,10 +333,13 @@ topicforge-mcp/
|
|
|
314
333
|
│ ├── services/ # Domain orchestration
|
|
315
334
|
│ ├── adapters/
|
|
316
335
|
│ │ ├── ros2_live/ # `ros2` CLI wrappers
|
|
317
|
-
│ │
|
|
336
|
+
│ │ ├── ros2_mock/ # Deterministic fixtures (incl. DDS)
|
|
337
|
+
│ │ ├── dds_cyclone/ # Eclipse CycloneDDS adapter (lazy import)
|
|
338
|
+
│ │ ├── dds_fast/ # eProsima Fast DDS adapter (lazy import)
|
|
339
|
+
│ │ └── common/ # Vendor-neutral helpers + pure QoS analyzer
|
|
318
340
|
│ ├── models/ # Pydantic schemas
|
|
319
341
|
│ └── config/ # Settings & mode resolution
|
|
320
|
-
└── tests/ # Pytest suite (mock-only, no ROS2 required)
|
|
342
|
+
└── tests/ # Pytest suite (mock-only, no ROS2/DDS required)
|
|
321
343
|
```
|
|
322
344
|
|
|
323
345
|
## License
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# DDS quickstart — TopicForge v0.3.0+
|
|
2
|
+
|
|
3
|
+
A 5-minute tour of TopicForge's multi-vendor DDS observability module. Both backends — Eclipse CycloneDDS and eProsima Fast DDS — join the bus as **read-only DDS-RTPS participants** and observe every conformant vendor on the wire via the OMG protocol guarantee. The `MiddlewareAdapter` protocol does not expose a write method, so the MCP client cannot publish back to the bus on any backend.
|
|
4
|
+
|
|
5
|
+
See [`docs/dds-interop-matrix.md`](dds-interop-matrix.md) for the canonical multi-vendor positioning and the [OMG May 2025 interop reference](projet-file/references/omg-dds-interop-2025-05-08.xlsx).
|
|
6
|
+
|
|
7
|
+
This guide does **not** assume you have ROS2 installed.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 1. Mock mode — 30-second demo
|
|
12
|
+
|
|
13
|
+
The deterministic mock fixtures expose the full DDS tool surface without any DDS SDK or middleware. Useful for evaluating the tools before pulling in a real broker.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install topicforge
|
|
17
|
+
TOPICFORGE_MODE=mock python -m topicforge
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
In the spawned MCP client (Claude Desktop, Claude Code, Cursor, ...), the 3 DDS tools are now available alongside the 5 ROS2 tools:
|
|
21
|
+
|
|
22
|
+
- `list_participants(domain_id=0)` → returns 3 mock participants on domain 0 — two CycloneDDS (`mock-robot`, `mock-laptop`) and one Fast DDS (`mock-aerospace-node`). The multi-vendor mock exercises the canonical vendor enum (`cyclone`, `fast`, `rti`, `mock`, `unknown`).
|
|
23
|
+
- `detect_qos_mismatches(topic=None)` → returns 1 `MismatchReport` for `/dds/qos_mismatch` (deliberate Reliability incompatibility — RELIABLE reader vs BEST_EFFORT writer).
|
|
24
|
+
- `peek_dds_samples(topic="/dds/well_matched", count=3)` → returns 3 deterministic samples ; `peek_dds_samples(topic="/dds/qos_mismatch", count=1)` returns 1 sample with a `qos_note` field annotating the mismatch.
|
|
25
|
+
|
|
26
|
+
Mock fixtures are stable across runs — you can write integration tests against them.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. Live mode — choose your backend
|
|
31
|
+
|
|
32
|
+
v0.3.0 ships two OSS Python adapters. Pick one (or install both) :
|
|
33
|
+
|
|
34
|
+
### 2.a Eclipse CycloneDDS
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install topicforge[dds-cyclone]
|
|
38
|
+
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=cyclone python -m topicforge
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The CycloneDDS adapter uses `cyclonedds.builtin.BuiltinDataReader` for polling-style discovery on the DCPS builtin topics. QoS policies are introspected via `Policy.*` class names. Bounded `take_iter` timeouts keep tool calls under 2 seconds.
|
|
42
|
+
|
|
43
|
+
### 2.b eProsima Fast DDS
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install topicforge[dds-fast]
|
|
47
|
+
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=fast python -m topicforge
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The Fast DDS adapter attaches a `DomainParticipantListener`-shaped object to a freshly created participant and accumulates discovery callbacks under an RLock. A bounded `discovery_wait_ms=1500` warm-up after participant creation gives the listener time to populate before the first tool call.
|
|
51
|
+
|
|
52
|
+
### 2.c Both backends + auto resolution
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install topicforge[dds] # both Cyclone and Fast
|
|
56
|
+
TOPICFORGE_MODE=live TOPICFORGE_DDS_BACKEND=auto python -m topicforge
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`auto` resolves to the first available OSS backend in this order: `fast` > `cyclone` > `mock`. The order reflects the OMG May 2025 interop matrix where Fast DDS is validated against all five other vendors on 47/47 pairs. v0.2.0 users with only `cyclonedds` installed remain unchanged — Fast is unimportable on their host so the chain falls through to Cyclone.
|
|
60
|
+
|
|
61
|
+
### Domain selection
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
TOPICFORGE_DDS_DOMAIN_ID=42 python -m topicforge
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Accepts `0..232` (DDS spec range). Default is `0` — the same default used by most ROS2 setups.
|
|
68
|
+
|
|
69
|
+
### Pro tier — RTI Connext
|
|
70
|
+
|
|
71
|
+
`TOPICFORGE_DDS_BACKEND=rti` is reserved for the v0.4.0+ Pro tier (BYO RTI Connext license). Selecting it in the OSS core falls back to the ROS2 CLI adapter with a logged warning.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 3. The QoS mismatch scenario
|
|
76
|
+
|
|
77
|
+
Both real backends and the mock fixtures encode the canonical "subscriber doesn't receive" debugging case. From an MCP client:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
> Detect QoS mismatches on the current bus.
|
|
81
|
+
|
|
82
|
+
[tool call: detect_qos_mismatches]
|
|
83
|
+
[result]
|
|
84
|
+
[
|
|
85
|
+
{
|
|
86
|
+
"topic": "/dds/qos_mismatch",
|
|
87
|
+
"reader_guid": "010f1c2a.3b4c5d6e.7f800000.00000001",
|
|
88
|
+
"writer_guid": "010f1c2a.3b4c5d6e.7f800000.00000002",
|
|
89
|
+
"incompatible_policies": ["Reliability"],
|
|
90
|
+
"severity": "incompatible",
|
|
91
|
+
"mode_effective": "mock"
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
An LLM reading this output has enough information to suggest a concrete fix ("the writer is BEST_EFFORT but the reader requires RELIABLE — either relax the reader or upgrade the writer"). That is the diagnostic loop the DDS module is designed to support — and it works identically regardless of which backend produced the discovery samples, because the vendor-neutral pure analyzer at `src/topicforge/adapters/common/qos_analyzer.py` operates on canonical `QosProfile` Pydantic models.
|
|
97
|
+
|
|
98
|
+
The analyzer covers the four MVP policies — **Reliability**, **Durability**, **History**, **Deadline** — that explain the bulk of real-world mismatch cases. Liveliness, Ownership, Partition, TimeBasedFilter, and LatencyBudget are v0.3.x patches.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 4. Single-adapter limitation (v0.3.0)
|
|
103
|
+
|
|
104
|
+
TopicForge v0.3.0 still selects **one adapter at a time** based on `TOPICFORGE_MODE` + `TOPICFORGE_DDS_BACKEND` :
|
|
105
|
+
|
|
106
|
+
| `TOPICFORGE_MODE` | `TOPICFORGE_DDS_BACKEND` | Active adapter | ROS2 tools | DDS tools |
|
|
107
|
+
| ----------------- | ------------------------ | -------------------------- | ------------------------- | -------------------------- |
|
|
108
|
+
| `mock` | (any) | `MockAdapter` | work (fixtures) | work (fixtures) |
|
|
109
|
+
| `live` / `auto` | `mock` (default) | `Ros2CliAdapter` | work | raise with remediation |
|
|
110
|
+
| `live` / `auto` | `cyclone` | `CycloneDdsAdapter` | raise (DDS-only adapter) | work (real CycloneDDS) |
|
|
111
|
+
| `live` / `auto` | `fast` | `FastDdsAdapter` | raise (DDS-only adapter) | work (real Fast DDS) |
|
|
112
|
+
| `live` / `auto` | `rti` | falls back to ROS2 CLI | work (CLI) | raise (v0.4.0+ Pro tier) |
|
|
113
|
+
|
|
114
|
+
A composite adapter that delegates per-tool category (ROS2 graph vs DDS layer) is on the v0.3.x roadmap. For now, restart the server with a different `TOPICFORGE_DDS_BACKEND` to switch sides.
|
|
115
|
+
|
|
116
|
+
Error messages on the unselected side are explicit and point at the remediation path — no silent failures.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 5. v0.3.0 scope of `peek_dds_samples`
|
|
121
|
+
|
|
122
|
+
`peek_dds_samples` is full-fidelity on the 4 builtin DCPS topics with both backends :
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
peek_dds_samples(topic="DCPSParticipant", count=5)
|
|
126
|
+
peek_dds_samples(topic="DCPSSubscription", count=10)
|
|
127
|
+
peek_dds_samples(topic="DCPSPublication", count=10)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Arbitrary user topics raise an `AdapterError` pointing at the v0.3.x roadmap — XTypes/IDL discovery (`cyclonedds.dynamic.get_types_for_typeid` on Cyclone, XTypes remote-type lookup on Fast DDS) is the missing piece for arbitrary user-topic peek.
|
|
131
|
+
|
|
132
|
+
The other two DDS tools — `list_participants` and `detect_qos_mismatches` — work end-to-end on any user-topic deployment ; they don't depend on payload deserialization.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 6. What's next
|
|
137
|
+
|
|
138
|
+
- **v0.3.x patch** — XTypes/IDL discovery to extend `peek_dds_samples` to arbitrary user topics on both backends.
|
|
139
|
+
- **v0.3.x patch** — Extended QoS coverage : Liveliness, Ownership, Partition, TimeBasedFilter, LatencyBudget.
|
|
140
|
+
- **v0.3.x patch** — Composite adapter routing ROS2 graph tools to `Ros2CliAdapter` and DDS tools to the selected DDS adapter, so both surfaces are usable simultaneously.
|
|
141
|
+
- **v0.4.0+** — `RtiConnextAdapter` in the Pro tier (BYO RTI Connext license, gated by `TOPICFORGE_LICENSE_KEY`).
|
|
142
|
+
|
|
143
|
+
Full strategic roadmap lives in [`docs/product-plan.md`](product-plan.md) and the DDS module spec at [`docs/projet-file/mcp-02-spec.md`](projet-file/mcp-02-spec.md).
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 7. Troubleshooting
|
|
148
|
+
|
|
149
|
+
- **`pip install topicforge[dds-cyclone]` fails on Windows / macOS Python 3.13+** — `cyclonedds` wheels are typically published for Python 3.8 to 3.12. Pin Python 3.11 or 3.12 for the install host.
|
|
150
|
+
- **`pip install topicforge[dds-cyclone]` fails with `CYCLONEDDS_HOME`** — pip is trying to build `cyclonedds` from source because no wheel matches your platform/Python combination. Either switch to a supported Python (3.11/3.12) or install the native CycloneDDS C library first (see Eclipse CycloneDDS releases).
|
|
151
|
+
- **`pip install topicforge[dds-fast]` fails** — eProsima Fast DDS Python bindings (`fastdds>=2.6.1,<3`) currently ship wheels for Linux first. Windows wheels lag ; consult fast-dds.docs.eprosima.com for the current matrix.
|
|
152
|
+
- **DDS tool returns "v0.3.x roadmap" error** — you called `peek_dds_samples` on an arbitrary user topic. The 4 builtin DCPS topics work today ; arbitrary user-topic peek is a v0.3.x patch (XTypes/IDL discovery).
|
|
153
|
+
- **DDS tool returns "DDS module is not active" error** — your `TOPICFORGE_DDS_BACKEND` is `mock` while `TOPICFORGE_MODE` is `live` (the ROS2 CLI adapter is selected). Set `TOPICFORGE_DDS_BACKEND=cyclone` or `=fast` explicitly to enable the DDS adapters.
|
|
154
|
+
- **`auto` selects the wrong backend** — `auto` prefers Fast > Cyclone > Mock. If you want Cyclone explicitly, set `TOPICFORGE_DDS_BACKEND=cyclone` rather than relying on `auto`.
|
|
155
|
+
|
|
156
|
+
Report issues at https://github.com/yaniswav/TopicForge/issues.
|