From 6b9f5315de32dbac87da1dc28a89865bbd507a85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Badenes?= Date: Thu, 18 Dec 2025 16:25:14 -0300 Subject: [PATCH 1/4] Update documentation structure and build process for mintlify compatibility - Added new Sphinx documentation files and configuration for improved organization. - Updated `.gitignore` to exclude Sphinx build directories. - Modified `CONTRIBUTING.md` and GitHub Actions workflow to reflect new documentation paths. - Introduced new content files for configuration, getting started, usage, and specification sections. - Enhanced command handling documentation and added examples for single-robot and fleet connectors. - Included static assets such as logos and favicons for documentation branding. --- .github/workflows/docs.yaml | 4 +- .gitignore | 1 + CONTRIBUTING.md | 8 +- docs/{ => contents}/_static/favicon.ico | Bin .../_static/inorbit-logo-black.svg | 0 .../_static/inorbit-logo-white.svg | 0 docs/{ => contents}/_static/mark-github.svg | 0 docs/{ => contents}/configuration.md | 0 docs/{ => contents}/getting-started.md | 0 docs/{ => contents}/index.md | 21 +--- docs/{ => contents}/publishing.md | 0 docs/{ => contents}/specification/commands.md | 0 .../{ => contents}/specification/connector.md | 42 ++++---- docs/{ => contents}/specification/index.md | 91 +++++++++--------- docs/{ => contents}/specification/logging.md | 0 docs/{ => contents}/specification/models.md | 0 docs/{ => contents}/specification/utils.md | 0 .../{ => contents}/usage/commands-handling.md | 0 docs/{ => contents}/usage/fleet.md | 0 docs/contents/usage/index.md | 16 +++ docs/{ => contents}/usage/single-robot.md | 0 docs/{ => sphinx}/Makefile | 0 docs/{ => sphinx}/conf.py | 41 +++++--- docs/sphinx/configuration.md | 4 + docs/sphinx/getting-started.md | 4 + docs/sphinx/index.md | 21 ++++ docs/sphinx/publishing.md | 4 + docs/sphinx/specification/commands.md | 4 + docs/sphinx/specification/connector.md | 4 + docs/sphinx/specification/index.md | 15 +++ docs/sphinx/specification/logging.md | 4 + docs/sphinx/specification/models.md | 4 + docs/sphinx/specification/utils.md | 4 + docs/sphinx/usage/commands-handling.md | 4 + docs/sphinx/usage/fleet.md | 4 + docs/{ => sphinx}/usage/index.md | 6 +- docs/sphinx/usage/single-robot.md | 4 + 37 files changed, 204 insertions(+), 106 deletions(-) rename docs/{ => contents}/_static/favicon.ico (100%) rename docs/{ => contents}/_static/inorbit-logo-black.svg (100%) rename docs/{ => contents}/_static/inorbit-logo-white.svg (100%) rename docs/{ => contents}/_static/mark-github.svg (100%) rename docs/{ => contents}/configuration.md (100%) rename docs/{ => contents}/getting-started.md (100%) rename docs/{ => contents}/index.md (82%) rename docs/{ => contents}/publishing.md (100%) rename docs/{ => contents}/specification/commands.md (100%) rename docs/{ => contents}/specification/connector.md (81%) rename docs/{ => contents}/specification/index.md (55%) rename docs/{ => contents}/specification/logging.md (100%) rename docs/{ => contents}/specification/models.md (100%) rename docs/{ => contents}/specification/utils.md (100%) rename docs/{ => contents}/usage/commands-handling.md (100%) rename docs/{ => contents}/usage/fleet.md (100%) create mode 100644 docs/contents/usage/index.md rename docs/{ => contents}/usage/single-robot.md (100%) rename docs/{ => sphinx}/Makefile (100%) rename docs/{ => sphinx}/conf.py (59%) create mode 100644 docs/sphinx/configuration.md create mode 100644 docs/sphinx/getting-started.md create mode 100644 docs/sphinx/index.md create mode 100644 docs/sphinx/publishing.md create mode 100644 docs/sphinx/specification/commands.md create mode 100644 docs/sphinx/specification/connector.md create mode 100644 docs/sphinx/specification/index.md create mode 100644 docs/sphinx/specification/logging.md create mode 100644 docs/sphinx/specification/models.md create mode 100644 docs/sphinx/specification/utils.md create mode 100644 docs/sphinx/usage/commands-handling.md create mode 100644 docs/sphinx/usage/fleet.md rename docs/{ => sphinx}/usage/index.md (77%) create mode 100644 docs/sphinx/usage/single-robot.md diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 70f4b22..164178d 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -46,11 +46,11 @@ jobs: python -m pip install .[docs] - name: Build Sphinx site run: | - sphinx-build -b html docs/ docs/_build/html + sphinx-build -b html docs/sphinx docs/sphinx/_build/html - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: docs/_build/html + path: docs/sphinx/_build/html deploy: environment: diff --git a/.gitignore b/.gitignore index 97b2d3a..47ef6b9 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ instance/ # Sphinx documentation docs/_build/ +docs/sphinx/_build/ # PyBuilder .pybuilder/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 916b746..be0ca92 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -82,26 +82,26 @@ uv pip install .[docs] Using the Makefile generated by Sphinx: ```bash -make -C docs html +make -C docs/sphinx html ``` Or directly with sphinx-build: ```bash -sphinx-build -b html docs/ docs/_build/html +sphinx-build -b html docs/sphinx docs/sphinx/_build/html ``` Open the result in your browser: ```bash # Linux -xdg-open docs/_build/html/index.html +xdg-open docs/sphinx/_build/html/index.html ``` Clean build artifacts: ```bash -make -C docs clean +make -C docs/sphinx clean ``` ### Publishing (CI) diff --git a/docs/_static/favicon.ico b/docs/contents/_static/favicon.ico similarity index 100% rename from docs/_static/favicon.ico rename to docs/contents/_static/favicon.ico diff --git a/docs/_static/inorbit-logo-black.svg b/docs/contents/_static/inorbit-logo-black.svg similarity index 100% rename from docs/_static/inorbit-logo-black.svg rename to docs/contents/_static/inorbit-logo-black.svg diff --git a/docs/_static/inorbit-logo-white.svg b/docs/contents/_static/inorbit-logo-white.svg similarity index 100% rename from docs/_static/inorbit-logo-white.svg rename to docs/contents/_static/inorbit-logo-white.svg diff --git a/docs/_static/mark-github.svg b/docs/contents/_static/mark-github.svg similarity index 100% rename from docs/_static/mark-github.svg rename to docs/contents/_static/mark-github.svg diff --git a/docs/configuration.md b/docs/contents/configuration.md similarity index 100% rename from docs/configuration.md rename to docs/contents/configuration.md diff --git a/docs/getting-started.md b/docs/contents/getting-started.md similarity index 100% rename from docs/getting-started.md rename to docs/contents/getting-started.md diff --git a/docs/index.md b/docs/contents/index.md similarity index 82% rename from docs/index.md rename to docs/contents/index.md index 40b291b..80908fe 100644 --- a/docs/index.md +++ b/docs/contents/index.md @@ -31,21 +31,10 @@ Both connector types provide: - Python 3.10 or later - InOrbit account ([it's free to sign up!](https://control.inorbit.ai)) -```{toctree} -:maxdepth: 2 -:hidden: - -getting-started -specification/index -usage/index -configuration -publishing -``` - ## Documentation Sections -- **Getting Started**: Installation, environment setup, and running a connector -- **Specification**: Package-level specification of the connector API (what you can call and what you can override) -- **Usage**: Detailed guides for implementing single-robot and fleet connectors -- **Configuration**: Complete connector customization guide -- **Publishing**: How to publish data to InOrbit +- **Getting Started**: Installation, environment setup, and running a connector ([Getting Started](getting-started.md)) +- **Specification**: Package-level specification of the connector API ([Specification](specification/index.md)) +- **Usage**: Detailed guides for implementing single-robot and fleet connectors ([Usage](usage/index.md)) +- **Configuration**: Connector configuration models and file formats ([Configuration](configuration.md)) +- **Publishing**: How to publish data to InOrbit ([Publishing](publishing.md)) diff --git a/docs/publishing.md b/docs/contents/publishing.md similarity index 100% rename from docs/publishing.md rename to docs/contents/publishing.md diff --git a/docs/specification/commands.md b/docs/contents/specification/commands.md similarity index 100% rename from docs/specification/commands.md rename to docs/contents/specification/commands.md diff --git a/docs/specification/connector.md b/docs/contents/specification/connector.md similarity index 81% rename from docs/specification/connector.md rename to docs/contents/specification/connector.md index 2285541..40406a1 100644 --- a/docs/specification/connector.md +++ b/docs/contents/specification/connector.md @@ -12,7 +12,7 @@ This page specifies the connector base classes you subclass to build connectors. `inorbit_connector.connector.FleetConnector` is the base class for connectors that manage multiple robots. -(spec-connector-fleetconnector-connect)= + ### `_connect()` **Override.** @@ -25,7 +25,7 @@ Typical responsibilities: - Optionally fetch the fleet membership and call `update_fleet()` **before** sessions are created. - Start background polling tasks that keep fresh state for all robots. -(spec-connector-fleetconnector-execution-loop)= + ### `_execution_loop()` **Override.** @@ -37,14 +37,14 @@ Typical responsibilities: - For each robot in `self.robot_ids`, fetch the latest state (often from background polling state) and publish data via the `publish_robot_*` methods. - Handle exceptions inside the loop when possible (the framework logs and continues on exceptions). -(spec-connector-fleetconnector-disconnect)= + ### `_disconnect()` **Override.** Called once during shutdown, after Edge SDK sessions are disconnected. Use this to stop polling tasks, close sockets, and release resources. -(spec-connector-fleetconnector-command-handler)= + ### `_inorbit_robot_command_handler(robot_id, command_name, args, options)` **Override.** @@ -55,9 +55,9 @@ Contract: - `options["result_function"](...)` must be called to report success/failure, or you may raise `CommandFailure` for structured failure reporting. -See {doc}`../usage/commands-handling` for the full command result contract. +See [Commands Handling](../usage/commands-handling.md) for the full command result contract. -(spec-connector-fleetconnector-fetch-robot-map)= + ### `fetch_robot_map(robot_id, frame_id) -> MapConfigTemp | None` **Optional override.** @@ -70,14 +70,14 @@ If `publish_robot_pose()` references a `frame_id` that is not present in `config Return `None` if the map can’t be fetched. -(spec-connector-fleetconnector-is-online)= + ### `_is_fleet_robot_online(robot_id) -> bool` **Optional override.** The Edge SDK uses this callback to determine if a robot should be considered online. Default implementation returns `True`. -(spec-connector-fleetconnector-lifecycle)= + ### `start()` / `join()` / `stop()` **Callable.** @@ -86,7 +86,7 @@ The Edge SDK uses this callback to determine if a robot should be considered onl - `join()` blocks until the background thread exits. - `stop()` signals the event loop to stop and waits briefly for shutdown. -(spec-connector-fleetconnector-fleet-management)= + ### `robot_ids` / `update_fleet(fleet)` **Callable.** @@ -96,14 +96,14 @@ The Edge SDK uses this callback to determine if a robot should be considered onl This is designed to be used during `_connect()` when your fleet membership comes from an external system. -(spec-connector-fleetconnector-publish-robot-pose)= + ### `publish_robot_pose(robot_id, x, y, yaw, frame_id=None, **kwargs)` **Callable.** Publishes pose for one robot. If the `frame_id` differs from the last published `frame_id` for that robot, the framework triggers `publish_robot_map(..., is_update=True)`. -(spec-connector-fleetconnector-publish-robot-map)= + ### `publish_robot_map(robot_id, frame_id, is_update=False)` **Callable.** @@ -111,22 +111,22 @@ Publishes pose for one robot. If the `frame_id` differs from the last published - If `frame_id` exists in `config.maps`, publishes the configured map to InOrbit. - Otherwise schedules an async fetch via `fetch_robot_map()` (see above). -(spec-connector-fleetconnector-publish-robot-odometry)= + ### `publish_robot_odometry(robot_id, **kwargs)` **Callable.** Publishes odometry data for one robot. -(spec-connector-fleetconnector-publish-robot-key-values)= + ### `publish_robot_key_values(robot_id, **kwargs)` **Callable.** Publishes key-value telemetry for one robot. -(spec-connector-fleetconnector-publish-robot-system-stats)= + ### `publish_robot_system_stats(robot_id, **kwargs)` **Callable.** Publishes system stats for one robot. -(spec-connector-fleetconnector-get-robot-session)= + ### `_get_robot_session(robot_id) -> RobotSession` **Callable (advanced).** @@ -137,7 +137,7 @@ Returns the underlying Edge SDK session for `robot_id`. Use this if you need Edg `inorbit_connector.connector.Connector` is a single-robot specialization of `FleetConnector`. It selects a single robot out of the fleet config and provides convenience wrappers that omit `robot_id`. -(spec-connector-connector-lifecycle-hooks)= + ### Lifecycle hooks **Override.** Same intent as fleet: @@ -146,28 +146,28 @@ Returns the underlying Edge SDK session for `robot_id`. Use this if you need Edg - `_execution_loop()` - `_disconnect()` -(spec-connector-connector-command-handler)= + ### `_inorbit_command_handler(command_name, args, options)` **Override.** Single-robot command handler. It is called through the fleet-level handler internally, but without requiring you to accept `robot_id`. -(spec-connector-connector-fetch-map)= + ### `fetch_map(frame_id) -> MapConfigTemp | None` **Optional override.** Single-robot convenience for map fetching. The framework uses it by delegating `fetch_robot_map()` to `fetch_map()`. -(spec-connector-connector-is-online)= + ### `_is_robot_online() -> bool` **Optional override.** Single-robot convenience for online status. The fleet-level online check delegates to this method. -(spec-connector-connector-publishing)= + ### Publishing wrappers **Callable.** Single-robot wrappers over the fleet publishing methods: @@ -177,7 +177,7 @@ Single-robot convenience for online status. The fleet-level online check delegat - `publish_key_values(...)` - `publish_system_stats(...)` -(spec-connector-connector-get-session)= + ### `_get_session() -> RobotSession` **Callable (advanced).** diff --git a/docs/specification/index.md b/docs/contents/specification/index.md similarity index 55% rename from docs/specification/index.md rename to docs/contents/specification/index.md index abcd99e..bb09465 100644 --- a/docs/specification/index.md +++ b/docs/contents/specification/index.md @@ -38,11 +38,11 @@ For map handling, `publish_pose()` / `publish_robot_pose()` automatically trigge For narrative guides, see: -- Single robot: {doc}`../usage/single-robot` -- Fleet: {doc}`../usage/fleet` -- Commands: {doc}`../usage/commands-handling` -- Publishing: {doc}`../publishing` -- Configuration: {doc}`../configuration` +- Single robot: [Single-Robot Connector](../usage/single-robot.md) +- Fleet: [Fleet Connector](../usage/fleet.md) +- Commands: [Commands Handling](../usage/commands-handling.md) +- Publishing: [Publishing Data](../publishing.md) +- Configuration: [Configuration](../configuration.md) ## API surface (callable + overridable) @@ -50,47 +50,44 @@ The table below lists package-defined symbols meant for direct use (call) or ext | Kind | Symbol | Purpose | Details | | --- | --- | --- | --- | -| Override | `FleetConnector._connect()` | Connect to external services (fleet manager, robot backends) before sessions initialize. | {ref}`Details ` | -| Override | `FleetConnector._execution_loop()` | Periodic loop; publish telemetry for each robot. | {ref}`Details ` | -| Override | `FleetConnector._disconnect()` | Shutdown external services and release resources. | {ref}`Details ` | -| Override | `FleetConnector._inorbit_robot_command_handler()` | Handle commands for a specific `robot_id`. | {ref}`Details ` | -| Override (optional) | `FleetConnector.fetch_robot_map()` | Fetch a missing map (bytes + metadata) when publishing pose refers to an unknown `frame_id`. | {ref}`Details ` | -| Override (optional) | `FleetConnector._is_fleet_robot_online()` | Provide robot online status; used by Edge SDK callback. | {ref}`Details ` | -| Call | `FleetConnector.start()` / `join()` / `stop()` | Run and control the connector lifecycle. | {ref}`Details ` | -| Call | `FleetConnector.update_fleet()` / `FleetConnector.robot_ids` | Update fleet configuration (typically during `_connect()`) and access robot IDs. | {ref}`Details ` | -| Call | `FleetConnector.publish_robot_pose()` | Publish pose; triggers map publish when `frame_id` changes. | {ref}`Details ` | -| Call | `FleetConnector.publish_robot_map()` | Publish map metadata/image from configured maps (or after fetch). | {ref}`Details ` | -| Call | `FleetConnector.publish_robot_odometry()` | Publish odometry. | {ref}`Details ` | -| Call | `FleetConnector.publish_robot_key_values()` | Publish key-value telemetry. | {ref}`Details ` | -| Call | `FleetConnector.publish_robot_system_stats()` | Publish system stats telemetry. | {ref}`Details ` | -| Call (advanced) | `FleetConnector._get_robot_session()` | Access the underlying Edge SDK `RobotSession` for a specific robot. | {ref}`Details ` | -| Override | `Connector._connect()` / `_execution_loop()` / `_disconnect()` | Same lifecycle hooks as fleet, for a single robot. | {ref}`Details ` | -| Override | `Connector._inorbit_command_handler()` | Handle commands for the single robot. | {ref}`Details ` | -| Override (optional) | `Connector.fetch_map()` | Fetch a missing map for the current robot when pose references an unknown `frame_id`. | {ref}`Details ` | -| Override (optional) | `Connector._is_robot_online()` | Provide online status for the current robot. | {ref}`Details ` | -| Call | `Connector.publish_pose()` / `publish_map()` | Publish pose/map for the current robot (map handling included). | {ref}`Details ` | -| Call | `Connector.publish_odometry()` / `publish_key_values()` / `publish_system_stats()` | Publish telemetry for the current robot. | {ref}`Details ` | -| Call (advanced) | `Connector._get_session()` | Access the underlying Edge SDK `RobotSession` for the current robot. | {ref}`Details ` | -| Type | `ConnectorConfig` | Base configuration model for connectors. | {ref}`Details ` | -| Type | `RobotConfig` | Per-robot configuration (robot_id + cameras). | {ref}`Details ` | -| Type | `MapConfig` / `MapConfigTemp` | Map configuration (file-backed vs in-memory bytes) used by map publishing/fetching. | {ref}`Details ` | -| Type | `LoggingConfig` / `LogLevels` | Logging configuration and log-level enum. | {ref}`Details ` | -| Call | `read_yaml()` | Load YAML configuration data (with deprecated `robot_id` selection support). | {ref}`Details ` | -| Type / Call | `CommandResultCode` / `CommandFailure` | Standard command result code enum and structured failure exception. | {ref}`Details ` | -| Call | `parse_custom_command_args()` | Parse custom-command args (RunScript action payload) into `(script_name, params)`. | {ref}`Details ` | -| Type | `CommandModel` / `ExcludeUnsetMixin` | Pydantic-based command argument validation utilities. | {ref}`Details ` | -| Call | `setup_logger()` | Configure logging from `LoggingConfig`. | {ref}`Details ` | -| Type | `ConditionalColoredFormatter` | Optional `colorlog`-backed formatter used by the default logging config. | {ref}`Details ` | - -```{toctree} -:maxdepth: 2 -:hidden: - -connector -models -commands -utils -logging -``` +| Override | `FleetConnector._connect()` | Connect to external services (fleet manager, robot backends) before sessions initialize. | [Details](connector.md#spec-connector-fleetconnector-connect) | +| Override | `FleetConnector._execution_loop()` | Periodic loop; publish telemetry for each robot. | [Details](connector.md#spec-connector-fleetconnector-execution-loop) | +| Override | `FleetConnector._disconnect()` | Shutdown external services and release resources. | [Details](connector.md#spec-connector-fleetconnector-disconnect) | +| Override | `FleetConnector._inorbit_robot_command_handler()` | Handle commands for a specific `robot_id`. | [Details](connector.md#spec-connector-fleetconnector-command-handler) | +| Override (optional) | `FleetConnector.fetch_robot_map()` | Fetch a missing map (bytes + metadata) when publishing pose refers to an unknown `frame_id`. | [Details](connector.md#spec-connector-fleetconnector-fetch-robot-map) | +| Override (optional) | `FleetConnector._is_fleet_robot_online()` | Provide robot online status; used by Edge SDK callback. | [Details](connector.md#spec-connector-fleetconnector-is-online) | +| Call | `FleetConnector.start()` / `join()` / `stop()` | Run and control the connector lifecycle. | [Details](connector.md#spec-connector-fleetconnector-lifecycle) | +| Call | `FleetConnector.update_fleet()` / `FleetConnector.robot_ids` | Update fleet configuration (typically during `_connect()`) and access robot IDs. | [Details](connector.md#spec-connector-fleetconnector-fleet-management) | +| Call | `FleetConnector.publish_robot_pose()` | Publish pose; triggers map publish when `frame_id` changes. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-pose) | +| Call | `FleetConnector.publish_robot_map()` | Publish map metadata/image from configured maps (or after fetch). | [Details](connector.md#spec-connector-fleetconnector-publish-robot-map) | +| Call | `FleetConnector.publish_robot_odometry()` | Publish odometry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-odometry) | +| Call | `FleetConnector.publish_robot_key_values()` | Publish key-value telemetry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-key-values) | +| Call | `FleetConnector.publish_robot_system_stats()` | Publish system stats telemetry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-system-stats) | +| Call (advanced) | `FleetConnector._get_robot_session()` | Access the underlying Edge SDK `RobotSession` for a specific robot. | [Details](connector.md#spec-connector-fleetconnector-get-robot-session) | +| Override | `Connector._connect()` / `_execution_loop()` / `_disconnect()` | Same lifecycle hooks as fleet, for a single robot. | [Details](connector.md#spec-connector-connector-lifecycle-hooks) | +| Override | `Connector._inorbit_command_handler()` | Handle commands for the single robot. | [Details](connector.md#spec-connector-connector-command-handler) | +| Override (optional) | `Connector.fetch_map()` | Fetch a missing map for the current robot when pose references an unknown `frame_id`. | [Details](connector.md#spec-connector-connector-fetch-map) | +| Override (optional) | `Connector._is_robot_online()` | Provide online status for the current robot. | [Details](connector.md#spec-connector-connector-is-online) | +| Call | `Connector.publish_pose()` / `publish_map()` | Publish pose/map for the current robot (map handling included). | [Details](connector.md#spec-connector-connector-publishing) | +| Call | `Connector.publish_odometry()` / `publish_key_values()` / `publish_system_stats()` | Publish telemetry for the current robot. | [Details](connector.md#spec-connector-connector-publishing) | +| Call (advanced) | `Connector._get_session()` | Access the underlying Edge SDK `RobotSession` for the current robot. | [Details](connector.md#spec-connector-connector-get-session) | +| Type | `ConnectorConfig` | Base configuration model for connectors. | [Details](models.md#spec-models-connectorconfig) | +| Type | `RobotConfig` | Per-robot configuration (robot_id + cameras). | [Details](models.md#spec-models-robotconfig) | +| Type | `MapConfig` / `MapConfigTemp` | Map configuration (file-backed vs in-memory bytes) used by map publishing/fetching. | [Details](models.md#spec-models-mapconfig) | +| Type | `LoggingConfig` / `LogLevels` | Logging configuration and log-level enum. | [Details](logging.md#spec-logging-loggingconfig) | +| Call | `read_yaml()` | Load YAML configuration data (with deprecated `robot_id` selection support). | [Details](utils.md#spec-utils-readyaml) | +| Type / Call | `CommandResultCode` / `CommandFailure` | Standard command result code enum and structured failure exception. | [Details](commands.md#spec-commands-commandfailure) | +| Call | `parse_custom_command_args()` | Parse custom-command args (RunScript action payload) into `(script_name, params)`. | [Details](commands.md#spec-commands-parse-custom-command-args) | +| Type | `CommandModel` / `ExcludeUnsetMixin` | Pydantic-based command argument validation utilities. | [Details](commands.md#spec-commands-commandmodel) | +| Call | `setup_logger()` | Configure logging from `LoggingConfig`. | [Details](logging.md#spec-logging-setup-logger) | +| Type | `ConditionalColoredFormatter` | Optional `colorlog`-backed formatter used by the default logging config. | [Details](logging.md#spec-logging-conditional-colored-formatter) | + +## Pages + +- [Connector API](connector.md) +- [Models (configuration)](models.md) +- [Commands utilities](commands.md) +- [Utilities](utils.md) +- [Logging](logging.md) diff --git a/docs/specification/logging.md b/docs/contents/specification/logging.md similarity index 100% rename from docs/specification/logging.md rename to docs/contents/specification/logging.md diff --git a/docs/specification/models.md b/docs/contents/specification/models.md similarity index 100% rename from docs/specification/models.md rename to docs/contents/specification/models.md diff --git a/docs/specification/utils.md b/docs/contents/specification/utils.md similarity index 100% rename from docs/specification/utils.md rename to docs/contents/specification/utils.md diff --git a/docs/usage/commands-handling.md b/docs/contents/usage/commands-handling.md similarity index 100% rename from docs/usage/commands-handling.md rename to docs/contents/usage/commands-handling.md diff --git a/docs/usage/fleet.md b/docs/contents/usage/fleet.md similarity index 100% rename from docs/usage/fleet.md rename to docs/contents/usage/fleet.md diff --git a/docs/contents/usage/index.md b/docs/contents/usage/index.md new file mode 100644 index 0000000..5e90c91 --- /dev/null +++ b/docs/contents/usage/index.md @@ -0,0 +1,16 @@ + + +# Usage + +Guides for implementing connectors. + +## Guides + +- [Single-Robot Connector](single-robot.md) +- [Fleet Connector](fleet.md) +- [Commands Handling](commands-handling.md) + diff --git a/docs/usage/single-robot.md b/docs/contents/usage/single-robot.md similarity index 100% rename from docs/usage/single-robot.md rename to docs/contents/usage/single-robot.md diff --git a/docs/Makefile b/docs/sphinx/Makefile similarity index 100% rename from docs/Makefile rename to docs/sphinx/Makefile diff --git a/docs/conf.py b/docs/sphinx/conf.py similarity index 59% rename from docs/conf.py rename to docs/sphinx/conf.py index 7bacee7..f3e5394 100644 --- a/docs/conf.py +++ b/docs/sphinx/conf.py @@ -7,23 +7,31 @@ # For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -import os +import re from pathlib import Path -import sys -from inorbit_connector import __version__ -# Ensure the package can be imported so we can read its version -sys.path.insert(0, os.path.abspath("..")) +def _read_package_version() -> str: + """Read __version__ from the package without importing it. + + This keeps the docs build independent from the environment (no need to have the + package importable). + """ + repo_root = Path(__file__).resolve().parents[2] + init_py = repo_root / "inorbit_connector" / "__init__.py" + text = init_py.read_text(encoding="utf-8") + match = re.search(r'^__version__\s*=\s*"([^"]+)"\s*$', text, re.MULTILINE) + if not match: + raise RuntimeError("Could not determine package version from __init__.py") + return match.group(1) + project = "inorbit-connector" copyright = "2025, InOrbit, Inc." author = "InOrbit, Inc." -release = __version__ -version = __version__ +release = _read_package_version() +version = release # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration @@ -39,11 +47,18 @@ templates_path = ["_templates"] exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +root_doc = "index" + +# The portable docs use explicit HTML anchors (e.g. ) for deep +# linking compatibility across doc systems. MyST can't validate those anchors, +# and will emit "xref_missing" warnings for links that include a fragment. +suppress_warnings = ["myst.xref_missing"] + # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = "furo" -html_static_path = ["_static"] +html_static_path = ["../contents/_static"] # Support both Markdown (MyST) and reStructuredText sources source_suffix = { @@ -53,7 +68,7 @@ def _read_static_svg(filename: str) -> str: - static_dir = Path(__file__).resolve().parent / "_static" + static_dir = Path(__file__).resolve().parents[1] / "contents" / "_static" return (static_dir / filename).read_text(encoding="utf-8") @@ -63,7 +78,7 @@ def _read_static_svg(filename: str) -> str: "dark_logo": "inorbit-logo-white.svg", "source_repository": "https://github.com/inorbit-ai/inorbit-connector-python/", "source_branch": "main", - "source_directory": "docs/", + "source_directory": "docs/contents/", "top_of_page_buttons": ["view", "edit"], "footer_icons": [ { @@ -76,4 +91,4 @@ def _read_static_svg(filename: str) -> str: } # Favicon -html_favicon = "_static/favicon.ico" +html_favicon = "../contents/_static/favicon.ico" diff --git a/docs/sphinx/configuration.md b/docs/sphinx/configuration.md new file mode 100644 index 0000000..1d21e75 --- /dev/null +++ b/docs/sphinx/configuration.md @@ -0,0 +1,4 @@ +```{include} ../contents/configuration.md +``` + + diff --git a/docs/sphinx/getting-started.md b/docs/sphinx/getting-started.md new file mode 100644 index 0000000..fd9f277 --- /dev/null +++ b/docs/sphinx/getting-started.md @@ -0,0 +1,4 @@ +```{include} ../contents/getting-started.md +``` + + diff --git a/docs/sphinx/index.md b/docs/sphinx/index.md new file mode 100644 index 0000000..86499e5 --- /dev/null +++ b/docs/sphinx/index.md @@ -0,0 +1,21 @@ + + +```{include} ../contents/index.md +``` + +```{toctree} +:maxdepth: 2 +:hidden: + +getting-started +specification/index +usage/index +configuration +publishing +``` + + diff --git a/docs/sphinx/publishing.md b/docs/sphinx/publishing.md new file mode 100644 index 0000000..047c8a1 --- /dev/null +++ b/docs/sphinx/publishing.md @@ -0,0 +1,4 @@ +```{include} ../contents/publishing.md +``` + + diff --git a/docs/sphinx/specification/commands.md b/docs/sphinx/specification/commands.md new file mode 100644 index 0000000..371f806 --- /dev/null +++ b/docs/sphinx/specification/commands.md @@ -0,0 +1,4 @@ +```{include} ../../contents/specification/commands.md +``` + + diff --git a/docs/sphinx/specification/connector.md b/docs/sphinx/specification/connector.md new file mode 100644 index 0000000..a74ac14 --- /dev/null +++ b/docs/sphinx/specification/connector.md @@ -0,0 +1,4 @@ +```{include} ../../contents/specification/connector.md +``` + + diff --git a/docs/sphinx/specification/index.md b/docs/sphinx/specification/index.md new file mode 100644 index 0000000..ee7936b --- /dev/null +++ b/docs/sphinx/specification/index.md @@ -0,0 +1,15 @@ +```{include} ../../contents/specification/index.md +``` + +```{toctree} +:maxdepth: 2 +:hidden: + +connector +models +commands +utils +logging +``` + + diff --git a/docs/sphinx/specification/logging.md b/docs/sphinx/specification/logging.md new file mode 100644 index 0000000..61505ab --- /dev/null +++ b/docs/sphinx/specification/logging.md @@ -0,0 +1,4 @@ +```{include} ../../contents/specification/logging.md +``` + + diff --git a/docs/sphinx/specification/models.md b/docs/sphinx/specification/models.md new file mode 100644 index 0000000..ba31e8e --- /dev/null +++ b/docs/sphinx/specification/models.md @@ -0,0 +1,4 @@ +```{include} ../../contents/specification/models.md +``` + + diff --git a/docs/sphinx/specification/utils.md b/docs/sphinx/specification/utils.md new file mode 100644 index 0000000..456fbd4 --- /dev/null +++ b/docs/sphinx/specification/utils.md @@ -0,0 +1,4 @@ +```{include} ../../contents/specification/utils.md +``` + + diff --git a/docs/sphinx/usage/commands-handling.md b/docs/sphinx/usage/commands-handling.md new file mode 100644 index 0000000..f58b6c7 --- /dev/null +++ b/docs/sphinx/usage/commands-handling.md @@ -0,0 +1,4 @@ +```{include} ../../contents/usage/commands-handling.md +``` + + diff --git a/docs/sphinx/usage/fleet.md b/docs/sphinx/usage/fleet.md new file mode 100644 index 0000000..e52467e --- /dev/null +++ b/docs/sphinx/usage/fleet.md @@ -0,0 +1,4 @@ +```{include} ../../contents/usage/fleet.md +``` + + diff --git a/docs/usage/index.md b/docs/sphinx/usage/index.md similarity index 77% rename from docs/usage/index.md rename to docs/sphinx/usage/index.md index 2b2a6fc..8e5369c 100644 --- a/docs/usage/index.md +++ b/docs/sphinx/usage/index.md @@ -4,9 +4,8 @@ SPDX-FileCopyrightText: 2025 InOrbit, Inc. SPDX-License-Identifier: MIT --> -# Usage - -Guides for implementing connectors. +```{include} ../../contents/usage/index.md +``` ```{toctree} :maxdepth: 2 @@ -17,3 +16,4 @@ fleet commands-handling ``` + diff --git a/docs/sphinx/usage/single-robot.md b/docs/sphinx/usage/single-robot.md new file mode 100644 index 0000000..86bf359 --- /dev/null +++ b/docs/sphinx/usage/single-robot.md @@ -0,0 +1,4 @@ +```{include} ../../contents/usage/single-robot.md +``` + + From bb8d68a574eb4fa7450e06f5e8141f877750217c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Badenes?= Date: Thu, 18 Dec 2025 17:23:50 -0300 Subject: [PATCH 2/4] It works. At a great cost --- .github/workflows/docs.yaml | 12 ++- CONTRIBUTING.md | 9 +++ docs/contents/configuration.md | 13 ++-- docs/contents/docs.json | 48 ++++++++++++ docs/contents/getting-started.md | 19 ++--- docs/contents/index.md | 21 +++--- docs/contents/publishing.md | 11 +-- docs/contents/specification/commands.md | 13 ++-- docs/contents/specification/connector.md | 13 ++-- docs/contents/specification/index.md | 95 +++++++++++------------- docs/contents/specification/logging.md | 11 +-- docs/contents/specification/models.md | 13 ++-- docs/contents/specification/utils.md | 13 ++-- docs/contents/usage/commands-handling.md | 15 ++-- docs/contents/usage/fleet.md | 15 ++-- docs/contents/usage/index.md | 18 ++--- docs/contents/usage/single-robot.md | 17 ++--- docs/sphinx/Makefile | 26 ++++++- docs/sphinx/configuration.md | 5 +- docs/sphinx/fix_links.py | 80 ++++++++++++++++++++ docs/sphinx/getting-started.md | 6 +- docs/sphinx/index.md | 6 +- docs/sphinx/publishing.md | 5 +- docs/sphinx/specification/commands.md | 5 +- docs/sphinx/specification/connector.md | 5 +- docs/sphinx/specification/index.md | 6 +- docs/sphinx/specification/logging.md | 5 +- docs/sphinx/specification/models.md | 5 +- docs/sphinx/specification/utils.md | 5 +- docs/sphinx/usage/commands-handling.md | 5 +- docs/sphinx/usage/fleet.md | 5 +- docs/sphinx/usage/index.md | 11 +-- docs/sphinx/usage/single-robot.md | 5 +- 33 files changed, 338 insertions(+), 203 deletions(-) create mode 100644 docs/contents/docs.json create mode 100644 docs/sphinx/fix_links.py diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 164178d..fda1e5a 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -47,10 +47,20 @@ jobs: - name: Build Sphinx site run: | sphinx-build -b html docs/sphinx docs/sphinx/_build/html + - name: Fix absolute Mintlify-style links + run: | + # MyST converts absolute paths to anchors; rewrite them to relative paths + python docs/sphinx/fix_links.py docs/sphinx/_build/html + - name: Nest output under Mintlify-compatible path + run: | + mkdir -p docs/sphinx/_build/site/ground-control/robot-integration/connector-framework + cp -r docs/sphinx/_build/html/* docs/sphinx/_build/site/ground-control/robot-integration/connector-framework/ + # Add redirect from root to the nested path + echo 'Redirecting...

Redirecting to documentation...

' > docs/sphinx/_build/site/index.html - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: docs/sphinx/_build/html + path: docs/sphinx/_build/site deploy: environment: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index be0ca92..4d38088 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -98,6 +98,15 @@ Open the result in your browser: xdg-open docs/sphinx/_build/html/index.html ``` +**Note:** Internal links use absolute Mintlify-style paths (e.g., `/ground-control/robot-integration/connector-framework/...`) for compatibility with the main InOrbit docs site. To test link navigation locally, use the `serve` target: + +```bash +make -C docs/sphinx serve +# Opens at http://localhost:8000/ground-control/robot-integration/connector-framework/ +``` + +This builds the docs, nests them under the correct path prefix, and starts a local server. In CI, the docs are automatically deployed with this path structure so all links resolve correctly. + Clean build artifacts: ```bash diff --git a/docs/contents/configuration.md b/docs/contents/configuration.md index 7d08933..2f689cf 100644 --- a/docs/contents/configuration.md +++ b/docs/contents/configuration.md @@ -1,10 +1,7 @@ - - -# Configuration +--- +title: "Configuration" +description: "Configuration models and file formats for connectors" +--- The `inorbit-connector` framework uses Pydantic models for configuration, providing validation and type safety. @@ -12,7 +9,7 @@ The `inorbit-connector` framework uses Pydantic models for configuration, provid The main configuration class is `ConnectorConfig`, which contains all settings for your connector. It includes a `fleet` field containing a list of `RobotConfig` entries. -Connectors should subclass `inorbit_connector.models.ConnectorConfig` and define a `connector_config` field that contains the configuration for the connector. For more details see the {ref}`creating-a-custom-configuration` section below. +Connectors should subclass `inorbit_connector.models.ConnectorConfig` and define a `connector_config` field that contains the configuration for the connector. For more details see the [Creating a Custom Configuration](#creating-a-custom-configuration) section below. ### Key Fields diff --git a/docs/contents/docs.json b/docs/contents/docs.json new file mode 100644 index 0000000..d89530f --- /dev/null +++ b/docs/contents/docs.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "navigation": { + "products": [ + { + "product": "Ground Control", + "tabs": [ + { + "tab": "Connecting Devices", + "pages": [ + { + "group": "Connector Framework", + "pages": [ + "ground-control/robot-integration/connector-framework/index", + "ground-control/robot-integration/connector-framework/getting-started", + { + "group": "Usage", + "pages": [ + "ground-control/robot-integration/connector-framework/usage/index", + "ground-control/robot-integration/connector-framework/usage/single-robot", + "ground-control/robot-integration/connector-framework/usage/fleet", + "ground-control/robot-integration/connector-framework/usage/commands-handling" + ] + }, + "ground-control/robot-integration/connector-framework/configuration", + "ground-control/robot-integration/connector-framework/publishing", + { + "group": "Specification", + "pages": [ + "ground-control/robot-integration/connector-framework/specification/index", + "ground-control/robot-integration/connector-framework/specification/connector", + "ground-control/robot-integration/connector-framework/specification/models", + "ground-control/robot-integration/connector-framework/specification/commands", + "ground-control/robot-integration/connector-framework/specification/utils", + "ground-control/robot-integration/connector-framework/specification/logging" + ] + } + ] + } + ] + } + ] + } + ] + } +} + + diff --git a/docs/contents/getting-started.md b/docs/contents/getting-started.md index 021d7b0..4c318e1 100644 --- a/docs/contents/getting-started.md +++ b/docs/contents/getting-started.md @@ -1,10 +1,7 @@ - - -# Getting Started +--- +title: "Getting Started" +description: "Installation and setup for the InOrbit Connector Framework" +--- ## Installation @@ -80,7 +77,7 @@ python fleet-connector/main.py --config example.fleet.yaml ## Next Steps -- Review the [Specification](specification/index) to understand the public API of the package -- Read the [Usage Guide](usage/index) to learn how to implement your own connector -- Review the [Configuration Guide](configuration) to understand connector configuration -- Check the [Publishing Guide](publishing) to learn how to publish data to InOrbit +- Review the [Specification](/ground-control/robot-integration/connector-framework/specification/index) to understand the public API of the package +- Read the [Usage Guide](/ground-control/robot-integration/connector-framework/usage/index) to learn how to implement your own connector +- Review the [Configuration Guide](/ground-control/robot-integration/connector-framework/configuration) to understand connector configuration +- Check the [Publishing Guide](/ground-control/robot-integration/connector-framework/publishing) to learn how to publish data to InOrbit diff --git a/docs/contents/index.md b/docs/contents/index.md index 80908fe..ebabf6f 100644 --- a/docs/contents/index.md +++ b/docs/contents/index.md @@ -1,10 +1,7 @@ - - -# inorbit-connector +--- +title: "Connector Framework" +description: "Python framework for developing InOrbit robot connectors" +--- A Python framework for developing *connectors* for the [InOrbit](https://inorbit.ai/) RobOps ecosystem. @@ -33,8 +30,8 @@ Both connector types provide: ## Documentation Sections -- **Getting Started**: Installation, environment setup, and running a connector ([Getting Started](getting-started.md)) -- **Specification**: Package-level specification of the connector API ([Specification](specification/index.md)) -- **Usage**: Detailed guides for implementing single-robot and fleet connectors ([Usage](usage/index.md)) -- **Configuration**: Connector configuration models and file formats ([Configuration](configuration.md)) -- **Publishing**: How to publish data to InOrbit ([Publishing](publishing.md)) +- **Getting Started**: Installation, environment setup, and running a connector ([Getting Started](/ground-control/robot-integration/connector-framework/getting-started)) +- **Specification**: Package-level specification of the connector API ([Specification](/ground-control/robot-integration/connector-framework/specification/index)) +- **Usage**: Detailed guides for implementing single-robot and fleet connectors ([Usage](/ground-control/robot-integration/connector-framework/usage/index)) +- **Configuration**: Connector configuration models and file formats ([Configuration](/ground-control/robot-integration/connector-framework/configuration)) +- **Publishing**: How to publish data to InOrbit ([Publishing](/ground-control/robot-integration/connector-framework/publishing)) diff --git a/docs/contents/publishing.md b/docs/contents/publishing.md index 39960fb..09189aa 100644 --- a/docs/contents/publishing.md +++ b/docs/contents/publishing.md @@ -1,10 +1,7 @@ - - -# Publishing Data +--- +title: "Publishing Data" +description: "How to publish robot data to InOrbit" +--- The connector framework provides methods to publish various types of data to InOrbit. Both single-robot (`Connector`) and fleet (`FleetConnector`) connectors support publishing, with fleet connectors using methods prefixed with `publish_robot_*` that require a `robot_id` parameter. diff --git a/docs/contents/specification/commands.md b/docs/contents/specification/commands.md index 728df21..982e3e5 100644 --- a/docs/contents/specification/commands.md +++ b/docs/contents/specification/commands.md @@ -1,10 +1,7 @@ - - -# Commands utilities +--- +title: "Commands Utilities" +description: "Command handling utilities specification" +--- This page specifies command handling helpers from `inorbit_connector.commands`. @@ -46,7 +43,7 @@ These classes support type-safe parsing and validation of structured command par - `CommandModel` is a Pydantic `BaseModel` configured with `extra="forbid"`, and converts `ValidationError` into `CommandFailure`. - `ExcludeUnsetMixin` changes `model_dump()` default behavior to `exclude_unset=True` (useful when you want to emit only explicitly-provided fields). -See {doc}`../usage/commands-handling` for end-to-end usage patterns. +See [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) for end-to-end usage patterns. ## Note: re-exports via `inorbit_connector.connector` diff --git a/docs/contents/specification/connector.md b/docs/contents/specification/connector.md index 40406a1..8157627 100644 --- a/docs/contents/specification/connector.md +++ b/docs/contents/specification/connector.md @@ -1,10 +1,7 @@ - - -# Connector API +--- +title: "Connector API" +description: "Connector and FleetConnector class specifications" +--- This page specifies the connector base classes you subclass to build connectors. @@ -55,7 +52,7 @@ Contract: - `options["result_function"](...)` must be called to report success/failure, or you may raise `CommandFailure` for structured failure reporting. -See [Commands Handling](../usage/commands-handling.md) for the full command result contract. +See [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) for the full command result contract. ### `fetch_robot_map(robot_id, frame_id) -> MapConfigTemp | None` diff --git a/docs/contents/specification/index.md b/docs/contents/specification/index.md index bb09465..f362def 100644 --- a/docs/contents/specification/index.md +++ b/docs/contents/specification/index.md @@ -1,10 +1,7 @@ - - -# Specification +--- +title: "Specification" +description: "Public API specification for the inorbit-connector package" +--- This section specifies the public surface of the `inorbit-connector` package: what you are expected to **override** when implementing a connector, and what you can **call** at runtime. @@ -38,11 +35,11 @@ For map handling, `publish_pose()` / `publish_robot_pose()` automatically trigge For narrative guides, see: -- Single robot: [Single-Robot Connector](../usage/single-robot.md) -- Fleet: [Fleet Connector](../usage/fleet.md) -- Commands: [Commands Handling](../usage/commands-handling.md) -- Publishing: [Publishing Data](../publishing.md) -- Configuration: [Configuration](../configuration.md) +- Single robot: [Single-Robot Connector](/ground-control/robot-integration/connector-framework/usage/single-robot) +- Fleet: [Fleet Connector](/ground-control/robot-integration/connector-framework/usage/fleet) +- Commands: [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) +- Publishing: [Publishing Data](/ground-control/robot-integration/connector-framework/publishing) +- Configuration: [Configuration](/ground-control/robot-integration/connector-framework/configuration) ## API surface (callable + overridable) @@ -50,44 +47,42 @@ The table below lists package-defined symbols meant for direct use (call) or ext | Kind | Symbol | Purpose | Details | | --- | --- | --- | --- | -| Override | `FleetConnector._connect()` | Connect to external services (fleet manager, robot backends) before sessions initialize. | [Details](connector.md#spec-connector-fleetconnector-connect) | -| Override | `FleetConnector._execution_loop()` | Periodic loop; publish telemetry for each robot. | [Details](connector.md#spec-connector-fleetconnector-execution-loop) | -| Override | `FleetConnector._disconnect()` | Shutdown external services and release resources. | [Details](connector.md#spec-connector-fleetconnector-disconnect) | -| Override | `FleetConnector._inorbit_robot_command_handler()` | Handle commands for a specific `robot_id`. | [Details](connector.md#spec-connector-fleetconnector-command-handler) | -| Override (optional) | `FleetConnector.fetch_robot_map()` | Fetch a missing map (bytes + metadata) when publishing pose refers to an unknown `frame_id`. | [Details](connector.md#spec-connector-fleetconnector-fetch-robot-map) | -| Override (optional) | `FleetConnector._is_fleet_robot_online()` | Provide robot online status; used by Edge SDK callback. | [Details](connector.md#spec-connector-fleetconnector-is-online) | -| Call | `FleetConnector.start()` / `join()` / `stop()` | Run and control the connector lifecycle. | [Details](connector.md#spec-connector-fleetconnector-lifecycle) | -| Call | `FleetConnector.update_fleet()` / `FleetConnector.robot_ids` | Update fleet configuration (typically during `_connect()`) and access robot IDs. | [Details](connector.md#spec-connector-fleetconnector-fleet-management) | -| Call | `FleetConnector.publish_robot_pose()` | Publish pose; triggers map publish when `frame_id` changes. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-pose) | -| Call | `FleetConnector.publish_robot_map()` | Publish map metadata/image from configured maps (or after fetch). | [Details](connector.md#spec-connector-fleetconnector-publish-robot-map) | -| Call | `FleetConnector.publish_robot_odometry()` | Publish odometry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-odometry) | -| Call | `FleetConnector.publish_robot_key_values()` | Publish key-value telemetry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-key-values) | -| Call | `FleetConnector.publish_robot_system_stats()` | Publish system stats telemetry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-system-stats) | -| Call (advanced) | `FleetConnector._get_robot_session()` | Access the underlying Edge SDK `RobotSession` for a specific robot. | [Details](connector.md#spec-connector-fleetconnector-get-robot-session) | -| Override | `Connector._connect()` / `_execution_loop()` / `_disconnect()` | Same lifecycle hooks as fleet, for a single robot. | [Details](connector.md#spec-connector-connector-lifecycle-hooks) | -| Override | `Connector._inorbit_command_handler()` | Handle commands for the single robot. | [Details](connector.md#spec-connector-connector-command-handler) | -| Override (optional) | `Connector.fetch_map()` | Fetch a missing map for the current robot when pose references an unknown `frame_id`. | [Details](connector.md#spec-connector-connector-fetch-map) | -| Override (optional) | `Connector._is_robot_online()` | Provide online status for the current robot. | [Details](connector.md#spec-connector-connector-is-online) | -| Call | `Connector.publish_pose()` / `publish_map()` | Publish pose/map for the current robot (map handling included). | [Details](connector.md#spec-connector-connector-publishing) | -| Call | `Connector.publish_odometry()` / `publish_key_values()` / `publish_system_stats()` | Publish telemetry for the current robot. | [Details](connector.md#spec-connector-connector-publishing) | -| Call (advanced) | `Connector._get_session()` | Access the underlying Edge SDK `RobotSession` for the current robot. | [Details](connector.md#spec-connector-connector-get-session) | -| Type | `ConnectorConfig` | Base configuration model for connectors. | [Details](models.md#spec-models-connectorconfig) | -| Type | `RobotConfig` | Per-robot configuration (robot_id + cameras). | [Details](models.md#spec-models-robotconfig) | -| Type | `MapConfig` / `MapConfigTemp` | Map configuration (file-backed vs in-memory bytes) used by map publishing/fetching. | [Details](models.md#spec-models-mapconfig) | -| Type | `LoggingConfig` / `LogLevels` | Logging configuration and log-level enum. | [Details](logging.md#spec-logging-loggingconfig) | -| Call | `read_yaml()` | Load YAML configuration data (with deprecated `robot_id` selection support). | [Details](utils.md#spec-utils-readyaml) | -| Type / Call | `CommandResultCode` / `CommandFailure` | Standard command result code enum and structured failure exception. | [Details](commands.md#spec-commands-commandfailure) | -| Call | `parse_custom_command_args()` | Parse custom-command args (RunScript action payload) into `(script_name, params)`. | [Details](commands.md#spec-commands-parse-custom-command-args) | -| Type | `CommandModel` / `ExcludeUnsetMixin` | Pydantic-based command argument validation utilities. | [Details](commands.md#spec-commands-commandmodel) | -| Call | `setup_logger()` | Configure logging from `LoggingConfig`. | [Details](logging.md#spec-logging-setup-logger) | -| Type | `ConditionalColoredFormatter` | Optional `colorlog`-backed formatter used by the default logging config. | [Details](logging.md#spec-logging-conditional-colored-formatter) | +| Override | `FleetConnector._connect()` | Connect to external services (fleet manager, robot backends) before sessions initialize. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-connect) | +| Override | `FleetConnector._execution_loop()` | Periodic loop; publish telemetry for each robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-execution-loop) | +| Override | `FleetConnector._disconnect()` | Shutdown external services and release resources. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-disconnect) | +| Override | `FleetConnector._inorbit_robot_command_handler()` | Handle commands for a specific `robot_id`. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-command-handler) | +| Override (optional) | `FleetConnector.fetch_robot_map()` | Fetch a missing map (bytes + metadata) when publishing pose refers to an unknown `frame_id`. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-fetch-robot-map) | +| Override (optional) | `FleetConnector._is_fleet_robot_online()` | Provide robot online status; used by Edge SDK callback. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-is-online) | +| Call | `FleetConnector.start()` / `join()` / `stop()` | Run and control the connector lifecycle. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-lifecycle) | +| Call | `FleetConnector.update_fleet()` / `FleetConnector.robot_ids` | Update fleet configuration (typically during `_connect()`) and access robot IDs. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-fleet-management) | +| Call | `FleetConnector.publish_robot_pose()` | Publish pose; triggers map publish when `frame_id` changes. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-pose) | +| Call | `FleetConnector.publish_robot_map()` | Publish map metadata/image from configured maps (or after fetch). | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-map) | +| Call | `FleetConnector.publish_robot_odometry()` | Publish odometry. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-odometry) | +| Call | `FleetConnector.publish_robot_key_values()` | Publish key-value telemetry. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-key-values) | +| Call | `FleetConnector.publish_robot_system_stats()` | Publish system stats telemetry. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-system-stats) | +| Call (advanced) | `FleetConnector._get_robot_session()` | Access the underlying Edge SDK `RobotSession` for a specific robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-get-robot-session) | +| Override | `Connector._connect()` / `_execution_loop()` / `_disconnect()` | Same lifecycle hooks as fleet, for a single robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-lifecycle-hooks) | +| Override | `Connector._inorbit_command_handler()` | Handle commands for the single robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-command-handler) | +| Override (optional) | `Connector.fetch_map()` | Fetch a missing map for the current robot when pose references an unknown `frame_id`. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-fetch-map) | +| Override (optional) | `Connector._is_robot_online()` | Provide online status for the current robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-is-online) | +| Call | `Connector.publish_pose()` / `publish_map()` | Publish pose/map for the current robot (map handling included). | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-publishing) | +| Call | `Connector.publish_odometry()` / `publish_key_values()` / `publish_system_stats()` | Publish telemetry for the current robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-publishing) | +| Call (advanced) | `Connector._get_session()` | Access the underlying Edge SDK `RobotSession` for the current robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-get-session) | +| Type | `ConnectorConfig` | Base configuration model for connectors. | [Details](/ground-control/robot-integration/connector-framework/specification/models#spec-models-connectorconfig) | +| Type | `RobotConfig` | Per-robot configuration (robot_id + cameras). | [Details](/ground-control/robot-integration/connector-framework/specification/models#spec-models-robotconfig) | +| Type | `MapConfig` / `MapConfigTemp` | Map configuration (file-backed vs in-memory bytes) used by map publishing/fetching. | [Details](/ground-control/robot-integration/connector-framework/specification/models#spec-models-mapconfig) | +| Type | `LoggingConfig` / `LogLevels` | Logging configuration and log-level enum. | [Details](/ground-control/robot-integration/connector-framework/specification/logging#spec-logging-loggingconfig) | +| Call | `read_yaml()` | Load YAML configuration data (with deprecated `robot_id` selection support). | [Details](/ground-control/robot-integration/connector-framework/specification/utils#spec-utils-readyaml) | +| Type / Call | `CommandResultCode` / `CommandFailure` | Standard command result code enum and structured failure exception. | [Details](/ground-control/robot-integration/connector-framework/specification/commands#spec-commands-commandfailure) | +| Call | `parse_custom_command_args()` | Parse custom-command args (RunScript action payload) into `(script_name, params)`. | [Details](/ground-control/robot-integration/connector-framework/specification/commands#spec-commands-parse-custom-command-args) | +| Type | `CommandModel` / `ExcludeUnsetMixin` | Pydantic-based command argument validation utilities. | [Details](/ground-control/robot-integration/connector-framework/specification/commands#spec-commands-commandmodel) | +| Call | `setup_logger()` | Configure logging from `LoggingConfig`. | [Details](/ground-control/robot-integration/connector-framework/specification/logging#spec-logging-setup-logger) | +| Type | `ConditionalColoredFormatter` | Optional `colorlog`-backed formatter used by the default logging config. | [Details](/ground-control/robot-integration/connector-framework/specification/logging#spec-logging-conditional-colored-formatter) | ## Pages -- [Connector API](connector.md) -- [Models (configuration)](models.md) -- [Commands utilities](commands.md) -- [Utilities](utils.md) -- [Logging](logging.md) - - +- [Connector API](/ground-control/robot-integration/connector-framework/specification/connector) +- [Models (configuration)](/ground-control/robot-integration/connector-framework/specification/models) +- [Commands utilities](/ground-control/robot-integration/connector-framework/specification/commands) +- [Utilities](/ground-control/robot-integration/connector-framework/specification/utils) +- [Logging](/ground-control/robot-integration/connector-framework/specification/logging) diff --git a/docs/contents/specification/logging.md b/docs/contents/specification/logging.md index a075645..b6d3ae4 100644 --- a/docs/contents/specification/logging.md +++ b/docs/contents/specification/logging.md @@ -1,10 +1,7 @@ - - -# Logging +--- +title: "Logging" +description: "Logging configuration specification" +--- This page specifies logging-related helpers from `inorbit_connector.logging`. diff --git a/docs/contents/specification/models.md b/docs/contents/specification/models.md index 3e9878d..8d550bc 100644 --- a/docs/contents/specification/models.md +++ b/docs/contents/specification/models.md @@ -1,10 +1,7 @@ - - -# Models (configuration) +--- +title: "Models" +description: "Configuration models specification" +--- (configuration) This page specifies the configuration models defined by `inorbit_connector.models`. @@ -58,7 +55,7 @@ Logging configuration used by the connector at startup: - `log_level`: optional override for the root logger level. - `defaults`: dictionary passed to the logging config (e.g. `log_file`). -See {ref}`spec-logging-setup-logger` for how it is applied. +See [setup_logger()](/ground-control/robot-integration/connector-framework/specification/logging#spec-logging-setup-logger) for how it is applied. ## Deprecated: `InorbitConnectorConfig` diff --git a/docs/contents/specification/utils.md b/docs/contents/specification/utils.md index 1d556e6..5680f25 100644 --- a/docs/contents/specification/utils.md +++ b/docs/contents/specification/utils.md @@ -1,10 +1,7 @@ - - -# Utilities +--- +title: "Utilities" +description: "Utility functions specification" +--- This page specifies utilities from `inorbit_connector.utils`. @@ -22,7 +19,7 @@ Behavior: Notes: -- New configurations should follow the `ConnectorConfig` schema described in {doc}`../configuration`. +- New configurations should follow the `ConnectorConfig` schema described in [Configuration](/ground-control/robot-integration/connector-framework/configuration). ## Constants diff --git a/docs/contents/usage/commands-handling.md b/docs/contents/usage/commands-handling.md index 5a19131..3cffa52 100644 --- a/docs/contents/usage/commands-handling.md +++ b/docs/contents/usage/commands-handling.md @@ -1,10 +1,7 @@ - - -# Commands Handling +--- +title: "Commands Handling" +description: "How to handle commands from InOrbit" +--- Commands from InOrbit are automatically routed to your `_inorbit_robot_command_handler()` method in the case of a fleet connector, or to your `_inorbit_command_handler()` method in the case of a single-robot connector. @@ -145,7 +142,7 @@ async def _inorbit_robot_command_handler( ) ``` -It is recommended to complement its use with the `CommandModel` class (see {ref}`using-commandmodel-for-type-safe-argument-parsing`) for safe type validation and parsing. +It is recommended to complement its use with the `CommandModel` class (see [Using CommandModel for Type-Safe Argument Parsing](#using-commandmodel-for-type-safe-argument-parsing)) for safe type validation and parsing. (using-commandmodel-for-type-safe-argument-parsing)= ## Using `CommandModel` for Type-Safe Argument Parsing @@ -228,7 +225,7 @@ command = CommandQueueMission(**script_args) ``` The exception is automatically handled by the connector's command execution framework, so you don't need to catch `ValidationError` exceptions. -See the {ref}`reporting-failure` section for more details. +See the [Reporting Failure](#reporting-failure) section for more details. ### Excluding Unset Fields diff --git a/docs/contents/usage/fleet.md b/docs/contents/usage/fleet.md index 04075e7..75bf080 100644 --- a/docs/contents/usage/fleet.md +++ b/docs/contents/usage/fleet.md @@ -1,10 +1,7 @@ - - -# Fleet Connector +--- +title: "Fleet Connector" +description: "Guide for implementing a fleet connector" +--- Subclass `inorbit_connector.connector.FleetConnector` to manage multiple robots simultaneously. @@ -30,7 +27,7 @@ Subclasses must implement the same abstract methods as single-robot connectors, ### `_inorbit_robot_command_handler()` :::{hint} -See the [Commands Handling](commands-handling) chapter for more details. +See the [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) chapter for more details. ::: Handle commands for a specific robot. This method is automatically registered if `register_custom_command_handler` is True (default). @@ -93,7 +90,7 @@ The `update_fleet()` method updates the fleet configuration and initializes sess ## Publishing Methods -All publishing methods require a `robot_id` parameter. See the [Publishing Guide](../publishing) for detailed information. +All publishing methods require a `robot_id` parameter. See the [Publishing Guide](/ground-control/robot-integration/connector-framework/publishing) for detailed information. - `publish_robot_pose(robot_id, x, y, yaw, frame_id)`: Publish pose for a specific robot - `publish_robot_odometry(robot_id, **kwargs)`: Publish odometry for a specific robot diff --git a/docs/contents/usage/index.md b/docs/contents/usage/index.md index 5e90c91..8f7d244 100644 --- a/docs/contents/usage/index.md +++ b/docs/contents/usage/index.md @@ -1,16 +1,12 @@ - - -# Usage +--- +title: "Usage" +description: "Guides for implementing connectors" +--- Guides for implementing connectors. ## Guides -- [Single-Robot Connector](single-robot.md) -- [Fleet Connector](fleet.md) -- [Commands Handling](commands-handling.md) - +- [Single-Robot Connector](/ground-control/robot-integration/connector-framework/usage/single-robot) +- [Fleet Connector](/ground-control/robot-integration/connector-framework/usage/fleet) +- [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) diff --git a/docs/contents/usage/single-robot.md b/docs/contents/usage/single-robot.md index feac2e2..4a18989 100644 --- a/docs/contents/usage/single-robot.md +++ b/docs/contents/usage/single-robot.md @@ -1,10 +1,7 @@ - - -# Single-Robot Connector +--- +title: "Single-Robot Connector" +description: "Guide for implementing a single-robot connector" +--- Subclass `inorbit_connector.connector.Connector` to create a connector for a single robot. @@ -45,7 +42,7 @@ async def _connect(self) -> None: The main execution loop that runs periodically. This is where you fetch robot data and publish it to InOrbit. -Refer to the [publishing guide](../publishing) for more details on publishing data to InOrbit. +Refer to the [publishing guide](/ground-control/robot-integration/connector-framework/publishing) for more details on publishing data to InOrbit. With polling-based connectors, it is advisable to run polling loops concurrently with the execution loop to avoid long running `_execution_loop` calls. See the [robot-connector](https://github.com/inorbit-ai/inorbit-connector-python/blob/main/examples/robot-connector/connector.py) and [fleet-connector](https://github.com/inorbit-ai/inorbit-connector-python/blob/main/examples/simple-fleet-connector/connector.py) examples for more details. @@ -80,7 +77,7 @@ async def _disconnect(self) -> None: ### `_inorbit_command_handler()` :::{hint} -See the [Commands Handling](commands-handling) chapter for more details. +See the [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) chapter for more details. ::: Handle commands received from InOrbit. This method is automatically registered if `register_custom_command_handler` is True (default). @@ -135,7 +132,7 @@ connector.stop() ## Publishing Methods -See the [Publishing Guide](../publishing) for detailed information on publishing methods. +See the [Publishing Guide](/ground-control/robot-integration/connector-framework/publishing) for detailed information on publishing methods. ## Advanced Methods diff --git a/docs/sphinx/Makefile b/docs/sphinx/Makefile index e409574..f33e8df 100644 --- a/docs/sphinx/Makefile +++ b/docs/sphinx/Makefile @@ -12,11 +12,35 @@ SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build +# Path prefix matching Mintlify structure (for link compatibility) +SITE_PREFIX = ground-control/robot-integration/connector-framework + # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -.PHONY: help Makefile +.PHONY: help Makefile serve site clean-site + +# Fix absolute Mintlify-style links that MyST converts to anchors +fix-links: + @echo "Fixing absolute links in HTML..." + @python fix_links.py "$(BUILDDIR)/html" + +# Build and nest under Mintlify-compatible path for local testing +site: html fix-links + @mkdir -p "$(BUILDDIR)/site/$(SITE_PREFIX)" + @cp -r "$(BUILDDIR)/html/"* "$(BUILDDIR)/site/$(SITE_PREFIX)/" + @echo '' > "$(BUILDDIR)/site/index.html" + @echo "Site ready at $(BUILDDIR)/site/" + +# Serve locally with correct path structure +serve: site + @echo "Serving at http://localhost:8000/$(SITE_PREFIX)/" + @cd "$(BUILDDIR)/site" && python -m http.server 8000 + +# Clean the nested site directory +clean-site: + @rm -rf "$(BUILDDIR)/site" # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). diff --git a/docs/sphinx/configuration.md b/docs/sphinx/configuration.md index 1d21e75..34502bd 100644 --- a/docs/sphinx/configuration.md +++ b/docs/sphinx/configuration.md @@ -1,4 +1,5 @@ +# Configuration + ```{include} ../contents/configuration.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/fix_links.py b/docs/sphinx/fix_links.py new file mode 100644 index 0000000..968479e --- /dev/null +++ b/docs/sphinx/fix_links.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2025 InOrbit, Inc. +# SPDX-License-Identifier: MIT +"""Fix absolute Mintlify-style links in Sphinx HTML output. + +MyST converts absolute paths like /ground-control/robot-integration/connector-framework/X +to anchors like #/ground-control/robot-integration/connector-framework/X. + +This script rewrites them to proper relative paths based on the file's location. +""" + +import re +import sys +from pathlib import Path + +PREFIX = "/ground-control/robot-integration/connector-framework/" +ANCHOR_PATTERN = re.compile(r'href="#' + re.escape(PREFIX) + r'([^"]*)"') + + +def compute_relative_path(from_file: Path, to_path: str, html_root: Path) -> str: + """Compute relative path from one file to another.""" + # Get the directory containing the source file, relative to html_root + from_dir = from_file.parent.relative_to(html_root) + + # Compute how many levels up we need to go + depth = len(from_dir.parts) + prefix = "../" * depth + + # Build the relative path + # Handle fragment anchors (e.g., "specification/connector#some-anchor") + if "#" in to_path: + path_part, fragment = to_path.split("#", 1) + return f'{prefix}{path_part}.html#{fragment}' + else: + return f"{prefix}{to_path}.html" + + +def fix_file(html_file: Path, html_root: Path) -> int: + """Fix links in a single HTML file. Returns count of fixes.""" + content = html_file.read_text(encoding="utf-8") + fixes = 0 + + def replace_link(match: re.Match) -> str: + nonlocal fixes + target = match.group(1) + relative = compute_relative_path(html_file, target, html_root) + fixes += 1 + return f'href="{relative}"' + + new_content = ANCHOR_PATTERN.sub(replace_link, content) + + if fixes > 0: + html_file.write_text(new_content, encoding="utf-8") + + return fixes + + +def main(): + if len(sys.argv) < 2: + print("Usage: fix_links.py ", file=sys.stderr) + sys.exit(1) + + html_root = Path(sys.argv[1]) + if not html_root.is_dir(): + print(f"Error: {html_root} is not a directory", file=sys.stderr) + sys.exit(1) + + total_fixes = 0 + for html_file in html_root.rglob("*.html"): + fixes = fix_file(html_file, html_root) + if fixes > 0: + print(f" Fixed {fixes} links in {html_file.relative_to(html_root)}") + total_fixes += fixes + + print(f"Total: {total_fixes} links fixed") + + +if __name__ == "__main__": + main() + diff --git a/docs/sphinx/getting-started.md b/docs/sphinx/getting-started.md index fd9f277..e204688 100644 --- a/docs/sphinx/getting-started.md +++ b/docs/sphinx/getting-started.md @@ -1,4 +1,6 @@ +# Getting Started + ```{include} ../contents/getting-started.md +:start-line: 5 +:end-before: "## Next Steps" ``` - - diff --git a/docs/sphinx/index.md b/docs/sphinx/index.md index 86499e5..265e3a8 100644 --- a/docs/sphinx/index.md +++ b/docs/sphinx/index.md @@ -4,7 +4,11 @@ SPDX-FileCopyrightText: 2025 InOrbit, Inc. SPDX-License-Identifier: MIT --> +# Connector Framework + ```{include} ../contents/index.md +:start-line: 5 +:end-before: "## Documentation Sections" ``` ```{toctree} @@ -17,5 +21,3 @@ usage/index configuration publishing ``` - - diff --git a/docs/sphinx/publishing.md b/docs/sphinx/publishing.md index 047c8a1..d49c4c9 100644 --- a/docs/sphinx/publishing.md +++ b/docs/sphinx/publishing.md @@ -1,4 +1,5 @@ +# Publishing Data + ```{include} ../contents/publishing.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/specification/commands.md b/docs/sphinx/specification/commands.md index 371f806..18f4b21 100644 --- a/docs/sphinx/specification/commands.md +++ b/docs/sphinx/specification/commands.md @@ -1,4 +1,5 @@ +# Commands Utilities + ```{include} ../../contents/specification/commands.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/specification/connector.md b/docs/sphinx/specification/connector.md index a74ac14..73a92b3 100644 --- a/docs/sphinx/specification/connector.md +++ b/docs/sphinx/specification/connector.md @@ -1,4 +1,5 @@ +# Connector API + ```{include} ../../contents/specification/connector.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/specification/index.md b/docs/sphinx/specification/index.md index ee7936b..104b09e 100644 --- a/docs/sphinx/specification/index.md +++ b/docs/sphinx/specification/index.md @@ -1,4 +1,8 @@ +# Specification + ```{include} ../../contents/specification/index.md +:start-line: 5 +:end-before: "## Pages" ``` ```{toctree} @@ -11,5 +15,3 @@ commands utils logging ``` - - diff --git a/docs/sphinx/specification/logging.md b/docs/sphinx/specification/logging.md index 61505ab..b4372a3 100644 --- a/docs/sphinx/specification/logging.md +++ b/docs/sphinx/specification/logging.md @@ -1,4 +1,5 @@ +# Logging + ```{include} ../../contents/specification/logging.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/specification/models.md b/docs/sphinx/specification/models.md index ba31e8e..fef5fca 100644 --- a/docs/sphinx/specification/models.md +++ b/docs/sphinx/specification/models.md @@ -1,4 +1,5 @@ +# Models + ```{include} ../../contents/specification/models.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/specification/utils.md b/docs/sphinx/specification/utils.md index 456fbd4..2dde3af 100644 --- a/docs/sphinx/specification/utils.md +++ b/docs/sphinx/specification/utils.md @@ -1,4 +1,5 @@ +# Utilities + ```{include} ../../contents/specification/utils.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/usage/commands-handling.md b/docs/sphinx/usage/commands-handling.md index f58b6c7..f2add3c 100644 --- a/docs/sphinx/usage/commands-handling.md +++ b/docs/sphinx/usage/commands-handling.md @@ -1,4 +1,5 @@ +# Commands Handling + ```{include} ../../contents/usage/commands-handling.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/usage/fleet.md b/docs/sphinx/usage/fleet.md index e52467e..5e45656 100644 --- a/docs/sphinx/usage/fleet.md +++ b/docs/sphinx/usage/fleet.md @@ -1,4 +1,5 @@ +# Fleet Connector + ```{include} ../../contents/usage/fleet.md +:start-line: 5 ``` - - diff --git a/docs/sphinx/usage/index.md b/docs/sphinx/usage/index.md index 8e5369c..7110e09 100644 --- a/docs/sphinx/usage/index.md +++ b/docs/sphinx/usage/index.md @@ -1,11 +1,6 @@ - - -```{include} ../../contents/usage/index.md -``` +Guides for implementing connectors. ```{toctree} :maxdepth: 2 @@ -15,5 +10,3 @@ single-robot fleet commands-handling ``` - - diff --git a/docs/sphinx/usage/single-robot.md b/docs/sphinx/usage/single-robot.md index 86bf359..6a683cd 100644 --- a/docs/sphinx/usage/single-robot.md +++ b/docs/sphinx/usage/single-robot.md @@ -1,4 +1,5 @@ +# Single-Robot Connector + ```{include} ../../contents/usage/single-robot.md +:start-line: 5 ``` - - From de3943abda7a2068a5495ee19bc510c3c3670869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Badenes?= Date: Thu, 18 Dec 2025 17:41:11 -0300 Subject: [PATCH 3/4] Much better --- .github/workflows/docs.yaml | 12 +-- .gitignore | 3 +- CONTRIBUTING.md | 9 +- docs/contents/getting-started.md | 8 +- docs/contents/index.md | 10 +- docs/contents/specification/commands.md | 2 +- docs/contents/specification/connector.md | 2 +- docs/contents/specification/index.md | 82 +++++++-------- docs/contents/specification/models.md | 2 +- docs/contents/specification/utils.md | 2 +- docs/contents/usage/fleet.md | 4 +- docs/contents/usage/index.md | 8 +- docs/contents/usage/single-robot.md | 6 +- docs/mintlify/Makefile | 21 ++++ docs/mintlify/build.py | 127 +++++++++++++++++++++++ docs/sphinx/Makefile | 29 +----- docs/sphinx/fix_links.py | 80 -------------- 17 files changed, 219 insertions(+), 188 deletions(-) create mode 100644 docs/mintlify/Makefile create mode 100644 docs/mintlify/build.py delete mode 100644 docs/sphinx/fix_links.py diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index fda1e5a..164178d 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -47,20 +47,10 @@ jobs: - name: Build Sphinx site run: | sphinx-build -b html docs/sphinx docs/sphinx/_build/html - - name: Fix absolute Mintlify-style links - run: | - # MyST converts absolute paths to anchors; rewrite them to relative paths - python docs/sphinx/fix_links.py docs/sphinx/_build/html - - name: Nest output under Mintlify-compatible path - run: | - mkdir -p docs/sphinx/_build/site/ground-control/robot-integration/connector-framework - cp -r docs/sphinx/_build/html/* docs/sphinx/_build/site/ground-control/robot-integration/connector-framework/ - # Add redirect from root to the nested path - echo 'Redirecting...

Redirecting to documentation...

' > docs/sphinx/_build/site/index.html - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: docs/sphinx/_build/site + path: docs/sphinx/_build/html deploy: environment: diff --git a/.gitignore b/.gitignore index 47ef6b9..94ff718 100644 --- a/.gitignore +++ b/.gitignore @@ -73,8 +73,7 @@ instance/ .scrapy # Sphinx documentation -docs/_build/ -docs/sphinx/_build/ +docs/*/_build/ # PyBuilder .pybuilder/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d38088..500b97d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -96,17 +96,12 @@ Open the result in your browser: ```bash # Linux xdg-open docs/sphinx/_build/html/index.html -``` - -**Note:** Internal links use absolute Mintlify-style paths (e.g., `/ground-control/robot-integration/connector-framework/...`) for compatibility with the main InOrbit docs site. To test link navigation locally, use the `serve` target: -```bash +# Or serve locally make -C docs/sphinx serve -# Opens at http://localhost:8000/ground-control/robot-integration/connector-framework/ +# Opens at http://localhost:8000/ ``` -This builds the docs, nests them under the correct path prefix, and starts a local server. In CI, the docs are automatically deployed with this path structure so all links resolve correctly. - Clean build artifacts: ```bash diff --git a/docs/contents/getting-started.md b/docs/contents/getting-started.md index 4c318e1..90b35c4 100644 --- a/docs/contents/getting-started.md +++ b/docs/contents/getting-started.md @@ -77,7 +77,7 @@ python fleet-connector/main.py --config example.fleet.yaml ## Next Steps -- Review the [Specification](/ground-control/robot-integration/connector-framework/specification/index) to understand the public API of the package -- Read the [Usage Guide](/ground-control/robot-integration/connector-framework/usage/index) to learn how to implement your own connector -- Review the [Configuration Guide](/ground-control/robot-integration/connector-framework/configuration) to understand connector configuration -- Check the [Publishing Guide](/ground-control/robot-integration/connector-framework/publishing) to learn how to publish data to InOrbit +- Review the [Specification](specification/index) to understand the public API of the package +- Read the [Usage Guide](usage/index) to learn how to implement your own connector +- Review the [Configuration Guide](configuration) to understand connector configuration +- Check the [Publishing Guide](publishing) to learn how to publish data to InOrbit diff --git a/docs/contents/index.md b/docs/contents/index.md index ebabf6f..4ed5672 100644 --- a/docs/contents/index.md +++ b/docs/contents/index.md @@ -30,8 +30,8 @@ Both connector types provide: ## Documentation Sections -- **Getting Started**: Installation, environment setup, and running a connector ([Getting Started](/ground-control/robot-integration/connector-framework/getting-started)) -- **Specification**: Package-level specification of the connector API ([Specification](/ground-control/robot-integration/connector-framework/specification/index)) -- **Usage**: Detailed guides for implementing single-robot and fleet connectors ([Usage](/ground-control/robot-integration/connector-framework/usage/index)) -- **Configuration**: Connector configuration models and file formats ([Configuration](/ground-control/robot-integration/connector-framework/configuration)) -- **Publishing**: How to publish data to InOrbit ([Publishing](/ground-control/robot-integration/connector-framework/publishing)) +- **Getting Started**: Installation, environment setup, and running a connector ([Getting Started](getting-started)) +- **Specification**: Package-level specification of the connector API ([Specification](specification/index)) +- **Usage**: Detailed guides for implementing single-robot and fleet connectors ([Usage](usage/index)) +- **Configuration**: Connector configuration models and file formats ([Configuration](configuration)) +- **Publishing**: How to publish data to InOrbit ([Publishing](publishing)) diff --git a/docs/contents/specification/commands.md b/docs/contents/specification/commands.md index 982e3e5..148d395 100644 --- a/docs/contents/specification/commands.md +++ b/docs/contents/specification/commands.md @@ -43,7 +43,7 @@ These classes support type-safe parsing and validation of structured command par - `CommandModel` is a Pydantic `BaseModel` configured with `extra="forbid"`, and converts `ValidationError` into `CommandFailure`. - `ExcludeUnsetMixin` changes `model_dump()` default behavior to `exclude_unset=True` (useful when you want to emit only explicitly-provided fields). -See [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) for end-to-end usage patterns. +See [Commands Handling](../usage/commands-handling) for end-to-end usage patterns. ## Note: re-exports via `inorbit_connector.connector` diff --git a/docs/contents/specification/connector.md b/docs/contents/specification/connector.md index 8157627..813dafa 100644 --- a/docs/contents/specification/connector.md +++ b/docs/contents/specification/connector.md @@ -52,7 +52,7 @@ Contract: - `options["result_function"](...)` must be called to report success/failure, or you may raise `CommandFailure` for structured failure reporting. -See [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) for the full command result contract. +See [Commands Handling](../usage/commands-handling) for the full command result contract. ### `fetch_robot_map(robot_id, frame_id) -> MapConfigTemp | None` diff --git a/docs/contents/specification/index.md b/docs/contents/specification/index.md index f362def..6bd9449 100644 --- a/docs/contents/specification/index.md +++ b/docs/contents/specification/index.md @@ -35,11 +35,11 @@ For map handling, `publish_pose()` / `publish_robot_pose()` automatically trigge For narrative guides, see: -- Single robot: [Single-Robot Connector](/ground-control/robot-integration/connector-framework/usage/single-robot) -- Fleet: [Fleet Connector](/ground-control/robot-integration/connector-framework/usage/fleet) -- Commands: [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) -- Publishing: [Publishing Data](/ground-control/robot-integration/connector-framework/publishing) -- Configuration: [Configuration](/ground-control/robot-integration/connector-framework/configuration) +- Single robot: [Single-Robot Connector](../usage/single-robot) +- Fleet: [Fleet Connector](../usage/fleet) +- Commands: [Commands Handling](../usage/commands-handling) +- Publishing: [Publishing Data](../publishing) +- Configuration: [Configuration](../configuration) ## API surface (callable + overridable) @@ -47,42 +47,42 @@ The table below lists package-defined symbols meant for direct use (call) or ext | Kind | Symbol | Purpose | Details | | --- | --- | --- | --- | -| Override | `FleetConnector._connect()` | Connect to external services (fleet manager, robot backends) before sessions initialize. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-connect) | -| Override | `FleetConnector._execution_loop()` | Periodic loop; publish telemetry for each robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-execution-loop) | -| Override | `FleetConnector._disconnect()` | Shutdown external services and release resources. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-disconnect) | -| Override | `FleetConnector._inorbit_robot_command_handler()` | Handle commands for a specific `robot_id`. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-command-handler) | -| Override (optional) | `FleetConnector.fetch_robot_map()` | Fetch a missing map (bytes + metadata) when publishing pose refers to an unknown `frame_id`. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-fetch-robot-map) | -| Override (optional) | `FleetConnector._is_fleet_robot_online()` | Provide robot online status; used by Edge SDK callback. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-is-online) | -| Call | `FleetConnector.start()` / `join()` / `stop()` | Run and control the connector lifecycle. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-lifecycle) | -| Call | `FleetConnector.update_fleet()` / `FleetConnector.robot_ids` | Update fleet configuration (typically during `_connect()`) and access robot IDs. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-fleet-management) | -| Call | `FleetConnector.publish_robot_pose()` | Publish pose; triggers map publish when `frame_id` changes. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-pose) | -| Call | `FleetConnector.publish_robot_map()` | Publish map metadata/image from configured maps (or after fetch). | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-map) | -| Call | `FleetConnector.publish_robot_odometry()` | Publish odometry. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-odometry) | -| Call | `FleetConnector.publish_robot_key_values()` | Publish key-value telemetry. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-key-values) | -| Call | `FleetConnector.publish_robot_system_stats()` | Publish system stats telemetry. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-publish-robot-system-stats) | -| Call (advanced) | `FleetConnector._get_robot_session()` | Access the underlying Edge SDK `RobotSession` for a specific robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-fleetconnector-get-robot-session) | -| Override | `Connector._connect()` / `_execution_loop()` / `_disconnect()` | Same lifecycle hooks as fleet, for a single robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-lifecycle-hooks) | -| Override | `Connector._inorbit_command_handler()` | Handle commands for the single robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-command-handler) | -| Override (optional) | `Connector.fetch_map()` | Fetch a missing map for the current robot when pose references an unknown `frame_id`. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-fetch-map) | -| Override (optional) | `Connector._is_robot_online()` | Provide online status for the current robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-is-online) | -| Call | `Connector.publish_pose()` / `publish_map()` | Publish pose/map for the current robot (map handling included). | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-publishing) | -| Call | `Connector.publish_odometry()` / `publish_key_values()` / `publish_system_stats()` | Publish telemetry for the current robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-publishing) | -| Call (advanced) | `Connector._get_session()` | Access the underlying Edge SDK `RobotSession` for the current robot. | [Details](/ground-control/robot-integration/connector-framework/specification/connector#spec-connector-connector-get-session) | -| Type | `ConnectorConfig` | Base configuration model for connectors. | [Details](/ground-control/robot-integration/connector-framework/specification/models#spec-models-connectorconfig) | -| Type | `RobotConfig` | Per-robot configuration (robot_id + cameras). | [Details](/ground-control/robot-integration/connector-framework/specification/models#spec-models-robotconfig) | -| Type | `MapConfig` / `MapConfigTemp` | Map configuration (file-backed vs in-memory bytes) used by map publishing/fetching. | [Details](/ground-control/robot-integration/connector-framework/specification/models#spec-models-mapconfig) | -| Type | `LoggingConfig` / `LogLevels` | Logging configuration and log-level enum. | [Details](/ground-control/robot-integration/connector-framework/specification/logging#spec-logging-loggingconfig) | -| Call | `read_yaml()` | Load YAML configuration data (with deprecated `robot_id` selection support). | [Details](/ground-control/robot-integration/connector-framework/specification/utils#spec-utils-readyaml) | -| Type / Call | `CommandResultCode` / `CommandFailure` | Standard command result code enum and structured failure exception. | [Details](/ground-control/robot-integration/connector-framework/specification/commands#spec-commands-commandfailure) | -| Call | `parse_custom_command_args()` | Parse custom-command args (RunScript action payload) into `(script_name, params)`. | [Details](/ground-control/robot-integration/connector-framework/specification/commands#spec-commands-parse-custom-command-args) | -| Type | `CommandModel` / `ExcludeUnsetMixin` | Pydantic-based command argument validation utilities. | [Details](/ground-control/robot-integration/connector-framework/specification/commands#spec-commands-commandmodel) | -| Call | `setup_logger()` | Configure logging from `LoggingConfig`. | [Details](/ground-control/robot-integration/connector-framework/specification/logging#spec-logging-setup-logger) | -| Type | `ConditionalColoredFormatter` | Optional `colorlog`-backed formatter used by the default logging config. | [Details](/ground-control/robot-integration/connector-framework/specification/logging#spec-logging-conditional-colored-formatter) | +| Override | `FleetConnector._connect()` | Connect to external services (fleet manager, robot backends) before sessions initialize. | [Details](connector.md#spec-connector-fleetconnector-connect) | +| Override | `FleetConnector._execution_loop()` | Periodic loop; publish telemetry for each robot. | [Details](connector.md#spec-connector-fleetconnector-execution-loop) | +| Override | `FleetConnector._disconnect()` | Shutdown external services and release resources. | [Details](connector.md#spec-connector-fleetconnector-disconnect) | +| Override | `FleetConnector._inorbit_robot_command_handler()` | Handle commands for a specific `robot_id`. | [Details](connector.md#spec-connector-fleetconnector-command-handler) | +| Override (optional) | `FleetConnector.fetch_robot_map()` | Fetch a missing map (bytes + metadata) when publishing pose refers to an unknown `frame_id`. | [Details](connector.md#spec-connector-fleetconnector-fetch-robot-map) | +| Override (optional) | `FleetConnector._is_fleet_robot_online()` | Provide robot online status; used by Edge SDK callback. | [Details](connector.md#spec-connector-fleetconnector-is-online) | +| Call | `FleetConnector.start()` / `join()` / `stop()` | Run and control the connector lifecycle. | [Details](connector.md#spec-connector-fleetconnector-lifecycle) | +| Call | `FleetConnector.update_fleet()` / `FleetConnector.robot_ids` | Update fleet configuration (typically during `_connect()`) and access robot IDs. | [Details](connector.md#spec-connector-fleetconnector-fleet-management) | +| Call | `FleetConnector.publish_robot_pose()` | Publish pose; triggers map publish when `frame_id` changes. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-pose) | +| Call | `FleetConnector.publish_robot_map()` | Publish map metadata/image from configured maps (or after fetch). | [Details](connector.md#spec-connector-fleetconnector-publish-robot-map) | +| Call | `FleetConnector.publish_robot_odometry()` | Publish odometry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-odometry) | +| Call | `FleetConnector.publish_robot_key_values()` | Publish key-value telemetry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-key-values) | +| Call | `FleetConnector.publish_robot_system_stats()` | Publish system stats telemetry. | [Details](connector.md#spec-connector-fleetconnector-publish-robot-system-stats) | +| Call (advanced) | `FleetConnector._get_robot_session()` | Access the underlying Edge SDK `RobotSession` for a specific robot. | [Details](connector.md#spec-connector-fleetconnector-get-robot-session) | +| Override | `Connector._connect()` / `_execution_loop()` / `_disconnect()` | Same lifecycle hooks as fleet, for a single robot. | [Details](connector.md#spec-connector-connector-lifecycle-hooks) | +| Override | `Connector._inorbit_command_handler()` | Handle commands for the single robot. | [Details](connector.md#spec-connector-connector-command-handler) | +| Override (optional) | `Connector.fetch_map()` | Fetch a missing map for the current robot when pose references an unknown `frame_id`. | [Details](connector.md#spec-connector-connector-fetch-map) | +| Override (optional) | `Connector._is_robot_online()` | Provide online status for the current robot. | [Details](connector.md#spec-connector-connector-is-online) | +| Call | `Connector.publish_pose()` / `publish_map()` | Publish pose/map for the current robot (map handling included). | [Details](connector.md#spec-connector-connector-publishing) | +| Call | `Connector.publish_odometry()` / `publish_key_values()` / `publish_system_stats()` | Publish telemetry for the current robot. | [Details](connector.md#spec-connector-connector-publishing) | +| Call (advanced) | `Connector._get_session()` | Access the underlying Edge SDK `RobotSession` for the current robot. | [Details](connector.md#spec-connector-connector-get-session) | +| Type | `ConnectorConfig` | Base configuration model for connectors. | [Details](models.md#spec-models-connectorconfig) | +| Type | `RobotConfig` | Per-robot configuration (robot_id + cameras). | [Details](models.md#spec-models-robotconfig) | +| Type | `MapConfig` / `MapConfigTemp` | Map configuration (file-backed vs in-memory bytes) used by map publishing/fetching. | [Details](models.md#spec-models-mapconfig) | +| Type | `LoggingConfig` / `LogLevels` | Logging configuration and log-level enum. | [Details](logging.md#spec-logging-loggingconfig) | +| Call | `read_yaml()` | Load YAML configuration data (with deprecated `robot_id` selection support). | [Details](utils.md#spec-utils-readyaml) | +| Type / Call | `CommandResultCode` / `CommandFailure` | Standard command result code enum and structured failure exception. | [Details](commands.md#spec-commands-commandfailure) | +| Call | `parse_custom_command_args()` | Parse custom-command args (RunScript action payload) into `(script_name, params)`. | [Details](commands.md#spec-commands-parse-custom-command-args) | +| Type | `CommandModel` / `ExcludeUnsetMixin` | Pydantic-based command argument validation utilities. | [Details](commands.md#spec-commands-commandmodel) | +| Call | `setup_logger()` | Configure logging from `LoggingConfig`. | [Details](logging.md#spec-logging-setup-logger) | +| Type | `ConditionalColoredFormatter` | Optional `colorlog`-backed formatter used by the default logging config. | [Details](logging.md#spec-logging-conditional-colored-formatter) | ## Pages -- [Connector API](/ground-control/robot-integration/connector-framework/specification/connector) -- [Models (configuration)](/ground-control/robot-integration/connector-framework/specification/models) -- [Commands utilities](/ground-control/robot-integration/connector-framework/specification/commands) -- [Utilities](/ground-control/robot-integration/connector-framework/specification/utils) -- [Logging](/ground-control/robot-integration/connector-framework/specification/logging) +- [Connector API](connector) +- [Models (configuration)](models) +- [Commands utilities](commands) +- [Utilities](utils) +- [Logging](logging) diff --git a/docs/contents/specification/models.md b/docs/contents/specification/models.md index 8d550bc..3ded9e5 100644 --- a/docs/contents/specification/models.md +++ b/docs/contents/specification/models.md @@ -55,7 +55,7 @@ Logging configuration used by the connector at startup: - `log_level`: optional override for the root logger level. - `defaults`: dictionary passed to the logging config (e.g. `log_file`). -See [setup_logger()](/ground-control/robot-integration/connector-framework/specification/logging#spec-logging-setup-logger) for how it is applied. +See [setup_logger()](logging.md#spec-logging-setup-logger) for how it is applied. ## Deprecated: `InorbitConnectorConfig` diff --git a/docs/contents/specification/utils.md b/docs/contents/specification/utils.md index 5680f25..f9947b7 100644 --- a/docs/contents/specification/utils.md +++ b/docs/contents/specification/utils.md @@ -19,7 +19,7 @@ Behavior: Notes: -- New configurations should follow the `ConnectorConfig` schema described in [Configuration](/ground-control/robot-integration/connector-framework/configuration). +- New configurations should follow the `ConnectorConfig` schema described in [Configuration](../configuration). ## Constants diff --git a/docs/contents/usage/fleet.md b/docs/contents/usage/fleet.md index 75bf080..a9f933e 100644 --- a/docs/contents/usage/fleet.md +++ b/docs/contents/usage/fleet.md @@ -27,7 +27,7 @@ Subclasses must implement the same abstract methods as single-robot connectors, ### `_inorbit_robot_command_handler()` :::{hint} -See the [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) chapter for more details. +See the [Commands Handling](commands-handling) chapter for more details. ::: Handle commands for a specific robot. This method is automatically registered if `register_custom_command_handler` is True (default). @@ -90,7 +90,7 @@ The `update_fleet()` method updates the fleet configuration and initializes sess ## Publishing Methods -All publishing methods require a `robot_id` parameter. See the [Publishing Guide](/ground-control/robot-integration/connector-framework/publishing) for detailed information. +All publishing methods require a `robot_id` parameter. See the [Publishing Guide](../publishing) for detailed information. - `publish_robot_pose(robot_id, x, y, yaw, frame_id)`: Publish pose for a specific robot - `publish_robot_odometry(robot_id, **kwargs)`: Publish odometry for a specific robot diff --git a/docs/contents/usage/index.md b/docs/contents/usage/index.md index 8f7d244..da9d89c 100644 --- a/docs/contents/usage/index.md +++ b/docs/contents/usage/index.md @@ -3,10 +3,8 @@ title: "Usage" description: "Guides for implementing connectors" --- -Guides for implementing connectors. - ## Guides -- [Single-Robot Connector](/ground-control/robot-integration/connector-framework/usage/single-robot) -- [Fleet Connector](/ground-control/robot-integration/connector-framework/usage/fleet) -- [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) +- [Single-Robot Connector](single-robot) +- [Fleet Connector](fleet) +- [Commands Handling](commands-handling) diff --git a/docs/contents/usage/single-robot.md b/docs/contents/usage/single-robot.md index 4a18989..bcc6a7c 100644 --- a/docs/contents/usage/single-robot.md +++ b/docs/contents/usage/single-robot.md @@ -42,7 +42,7 @@ async def _connect(self) -> None: The main execution loop that runs periodically. This is where you fetch robot data and publish it to InOrbit. -Refer to the [publishing guide](/ground-control/robot-integration/connector-framework/publishing) for more details on publishing data to InOrbit. +Refer to the [publishing guide](../publishing) for more details on publishing data to InOrbit. With polling-based connectors, it is advisable to run polling loops concurrently with the execution loop to avoid long running `_execution_loop` calls. See the [robot-connector](https://github.com/inorbit-ai/inorbit-connector-python/blob/main/examples/robot-connector/connector.py) and [fleet-connector](https://github.com/inorbit-ai/inorbit-connector-python/blob/main/examples/simple-fleet-connector/connector.py) examples for more details. @@ -77,7 +77,7 @@ async def _disconnect(self) -> None: ### `_inorbit_command_handler()` :::{hint} -See the [Commands Handling](/ground-control/robot-integration/connector-framework/usage/commands-handling) chapter for more details. +See the [Commands Handling](commands-handling) chapter for more details. ::: Handle commands received from InOrbit. This method is automatically registered if `register_custom_command_handler` is True (default). @@ -132,7 +132,7 @@ connector.stop() ## Publishing Methods -See the [Publishing Guide](/ground-control/robot-integration/connector-framework/publishing) for detailed information on publishing methods. +See the [Publishing Guide](../publishing) for detailed information on publishing methods. ## Advanced Methods diff --git a/docs/mintlify/Makefile b/docs/mintlify/Makefile new file mode 100644 index 0000000..d9207be --- /dev/null +++ b/docs/mintlify/Makefile @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2025 InOrbit, Inc. +# SPDX-License-Identifier: MIT + +# Makefile for building Mintlify-compatible docs from shared content + +CONTENT_DIR = ../contents +BUILD_DIR = _build + +.PHONY: build clean + +# Build Mintlify-compatible docs with absolute links +build: + @echo "Building Mintlify-compatible docs..." + @python build.py "$(CONTENT_DIR)" "$(BUILD_DIR)" + @echo "Done. Output in $(BUILD_DIR)/" + +# Clean build artifacts +clean: + @rm -rf "$(BUILD_DIR)" + @echo "Cleaned $(BUILD_DIR)/" + diff --git a/docs/mintlify/build.py b/docs/mintlify/build.py new file mode 100644 index 0000000..c778f7f --- /dev/null +++ b/docs/mintlify/build.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2025 InOrbit, Inc. +# SPDX-License-Identifier: MIT +"""Build Mintlify-compatible docs from the shared content files. + +This script: +1. Copies content files to the build directory +2. Converts relative links to absolute Mintlify routes +3. Prepares the output for the multirepo action +""" + +import re +import shutil +import sys +from pathlib import Path + +# Mintlify route prefix for connector framework docs +PREFIX = "/ground-control/robot-integration/connector-framework" + +# Pattern to match markdown links: [text](path) or [text](path#anchor) +# Excludes: absolute URLs (http://, https://), absolute paths (/...), and pure anchors (#...) +LINK_PATTERN = re.compile(r"\[([^\]]+)\]\((?!https?://|mailto:|/|#)([^)]+)\)") + + +def convert_link(match: re.Match, file_path: Path, content_root: Path) -> str: + """Convert a relative link to an absolute Mintlify route.""" + text = match.group(1) + target = match.group(2) + + # Get the directory of the current file relative to content root + file_dir = file_path.parent.relative_to(content_root) + + # Resolve the relative path + if target.startswith("../"): + # Go up directories + resolved = (file_dir / target).as_posix() + # Normalize path (remove ../) + parts = [] + for part in resolved.split("/"): + if part == "..": + if parts: + parts.pop() + elif part and part != ".": + parts.append(part) + resolved = "/".join(parts) + else: + # Same directory or subdirectory + if str(file_dir) == ".": + resolved = target + else: + resolved = f"{file_dir}/{target}".replace("./", "") + + # Strip .md extension for Mintlify routes + if resolved.endswith(".md"): + resolved = resolved[:-3] + # Also handle .md before anchors (e.g., "file.md#anchor" -> "file#anchor") + resolved = re.sub(r"\.md(#)", r"\1", resolved) + + # Build absolute Mintlify route + absolute_path = f"{PREFIX}/{resolved}" + + return f"[{text}]({absolute_path})" + + +def process_file(src_file: Path, dst_file: Path, content_root: Path) -> int: + """Process a single file, converting links. Returns count of conversions.""" + content = src_file.read_text(encoding="utf-8") + count = 0 + + def replace_link(match: re.Match) -> str: + nonlocal count + count += 1 + return convert_link(match, src_file, content_root) + + new_content = LINK_PATTERN.sub(replace_link, content) + + dst_file.parent.mkdir(parents=True, exist_ok=True) + dst_file.write_text(new_content, encoding="utf-8") + + return count + + +def main(): + if len(sys.argv) < 3: + print("Usage: build.py ", file=sys.stderr) + sys.exit(1) + + content_dir = Path(sys.argv[1]) + output_dir = Path(sys.argv[2]) + + if not content_dir.is_dir(): + print(f"Error: {content_dir} is not a directory", file=sys.stderr) + sys.exit(1) + + # Clean output directory + if output_dir.exists(): + shutil.rmtree(output_dir) + output_dir.mkdir(parents=True) + + total_links = 0 + total_files = 0 + + # Process all markdown files + for src_file in content_dir.rglob("*.md"): + rel_path = src_file.relative_to(content_dir) + dst_file = output_dir / rel_path + + links = process_file(src_file, dst_file, content_dir) + if links > 0: + print(f" {rel_path}: {links} links converted") + total_links += links + total_files += 1 + + # Copy non-markdown files (images, etc.) + for src_file in content_dir.rglob("*"): + if src_file.is_file() and src_file.suffix != ".md": + rel_path = src_file.relative_to(content_dir) + dst_file = output_dir / rel_path + dst_file.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(src_file, dst_file) + + print(f"\nTotal: {total_files} files, {total_links} links converted") + print(f"Output: {output_dir}") + + +if __name__ == "__main__": + main() diff --git a/docs/sphinx/Makefile b/docs/sphinx/Makefile index f33e8df..a02f320 100644 --- a/docs/sphinx/Makefile +++ b/docs/sphinx/Makefile @@ -12,35 +12,16 @@ SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build -# Path prefix matching Mintlify structure (for link compatibility) -SITE_PREFIX = ground-control/robot-integration/connector-framework - # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -.PHONY: help Makefile serve site clean-site - -# Fix absolute Mintlify-style links that MyST converts to anchors -fix-links: - @echo "Fixing absolute links in HTML..." - @python fix_links.py "$(BUILDDIR)/html" - -# Build and nest under Mintlify-compatible path for local testing -site: html fix-links - @mkdir -p "$(BUILDDIR)/site/$(SITE_PREFIX)" - @cp -r "$(BUILDDIR)/html/"* "$(BUILDDIR)/site/$(SITE_PREFIX)/" - @echo '' > "$(BUILDDIR)/site/index.html" - @echo "Site ready at $(BUILDDIR)/site/" - -# Serve locally with correct path structure -serve: site - @echo "Serving at http://localhost:8000/$(SITE_PREFIX)/" - @cd "$(BUILDDIR)/site" && python -m http.server 8000 +.PHONY: help Makefile serve -# Clean the nested site directory -clean-site: - @rm -rf "$(BUILDDIR)/site" +# Serve locally for testing +serve: html + @echo "Serving at http://localhost:8000/" + @cd "$(BUILDDIR)/html" && python -m http.server 8000 # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). diff --git a/docs/sphinx/fix_links.py b/docs/sphinx/fix_links.py deleted file mode 100644 index 968479e..0000000 --- a/docs/sphinx/fix_links.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-FileCopyrightText: 2025 InOrbit, Inc. -# SPDX-License-Identifier: MIT -"""Fix absolute Mintlify-style links in Sphinx HTML output. - -MyST converts absolute paths like /ground-control/robot-integration/connector-framework/X -to anchors like #/ground-control/robot-integration/connector-framework/X. - -This script rewrites them to proper relative paths based on the file's location. -""" - -import re -import sys -from pathlib import Path - -PREFIX = "/ground-control/robot-integration/connector-framework/" -ANCHOR_PATTERN = re.compile(r'href="#' + re.escape(PREFIX) + r'([^"]*)"') - - -def compute_relative_path(from_file: Path, to_path: str, html_root: Path) -> str: - """Compute relative path from one file to another.""" - # Get the directory containing the source file, relative to html_root - from_dir = from_file.parent.relative_to(html_root) - - # Compute how many levels up we need to go - depth = len(from_dir.parts) - prefix = "../" * depth - - # Build the relative path - # Handle fragment anchors (e.g., "specification/connector#some-anchor") - if "#" in to_path: - path_part, fragment = to_path.split("#", 1) - return f'{prefix}{path_part}.html#{fragment}' - else: - return f"{prefix}{to_path}.html" - - -def fix_file(html_file: Path, html_root: Path) -> int: - """Fix links in a single HTML file. Returns count of fixes.""" - content = html_file.read_text(encoding="utf-8") - fixes = 0 - - def replace_link(match: re.Match) -> str: - nonlocal fixes - target = match.group(1) - relative = compute_relative_path(html_file, target, html_root) - fixes += 1 - return f'href="{relative}"' - - new_content = ANCHOR_PATTERN.sub(replace_link, content) - - if fixes > 0: - html_file.write_text(new_content, encoding="utf-8") - - return fixes - - -def main(): - if len(sys.argv) < 2: - print("Usage: fix_links.py ", file=sys.stderr) - sys.exit(1) - - html_root = Path(sys.argv[1]) - if not html_root.is_dir(): - print(f"Error: {html_root} is not a directory", file=sys.stderr) - sys.exit(1) - - total_fixes = 0 - for html_file in html_root.rglob("*.html"): - fixes = fix_file(html_file, html_root) - if fixes > 0: - print(f" Fixed {fixes} links in {html_file.relative_to(html_root)}") - total_fixes += fixes - - print(f"Total: {total_fixes} links fixed") - - -if __name__ == "__main__": - main() - From bd43c2d30520c017a0f50ad241b9279bbd3b6a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Badenes?= Date: Thu, 18 Dec 2025 17:46:22 -0300 Subject: [PATCH 4/4] Configure REUSE --- REUSE.toml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/REUSE.toml b/REUSE.toml index 83eaf08..bce00f8 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -45,3 +45,32 @@ path = "**/*.ico" SPDX-FileCopyrightText = "2025 InOrbit, Inc." SPDX-License-Identifier = "MIT" SPDX-FileComment = "ICO assets" + +# Documentation content files (portable between Sphinx and Mintlify) +# These use YAML frontmatter instead of HTML comments for Mintlify compatibility +[[annotations]] +path = "docs/contents/**/*.md" +SPDX-FileCopyrightText = "2025 InOrbit, Inc." +SPDX-License-Identifier = "MIT" +SPDX-FileComment = "Documentation content (Mintlify-compatible)" + +# Documentation JSON config +[[annotations]] +path = "docs/contents/docs.json" +SPDX-FileCopyrightText = "2025 InOrbit, Inc." +SPDX-License-Identifier = "MIT" +SPDX-FileComment = "Mintlify navigation configuration" + +# Mintlify build Makefile (has SPDX header but adding for completeness) +[[annotations]] +path = "docs/mintlify/Makefile" +SPDX-FileCopyrightText = "2025 InOrbit, Inc." +SPDX-License-Identifier = "MIT" +SPDX-FileComment = "Mintlify build configuration" + +# Sphinx wrapper files (use {include} directives, minimal content) +[[annotations]] +path = "docs/sphinx/**/*.md" +SPDX-FileCopyrightText = "2025 InOrbit, Inc." +SPDX-License-Identifier = "MIT" +SPDX-FileComment = "Sphinx documentation wrappers"