diff --git a/src/pycyphal2/__init__.py b/src/pycyphal2/__init__.py
index 88043d9b..43dc40b0 100644
--- a/src/pycyphal2/__init__.py
+++ b/src/pycyphal2/__init__.py
@@ -5,7 +5,7 @@
Supports various transports such as Ethernet (UDP) and CAN FD with optional redundancy.
-## Installation
+# Installation
Optional features inside the brackets can be removed if not needed; see `pyproject.toml` for the full list:
@@ -13,7 +13,7 @@
pip install 'pycyphal2[udp,pythoncan]'
```
-## Usage
+# Usage
Set up a transport, make a node, publish and subscribe:
@@ -40,9 +40,144 @@ async def main():
Transport modules (`pycyphal2.udp`, `pycyphal2.can`) are imported separately
so that only the needed dependencies are pulled in.
-### Name resolution
+## Name resolution
+
+The topic naming system shares many similarities with [ROS Names](https://wiki.ros.org/Names).
+
+Name resolution is the process by which a topic name passed to `node.advertise()` or `node.subscribe()` is resolved to a topic name as used on the Cyphal network.
+There exist 4 kinds of topic names in Cyphal:
+
+
+Relative Name
+
+A relative name is a name that does not start with `/` or `~/`.
+
+```
+sensor/temperature
+cmd_vel
+camera/image_raw
+```
+
+Its resolved name is prefixed with the node namespace.
+
+| Input name | Namespace | Home | Resolved name |
+| ----------------- | --------- | ---- | --------------------- |
+| `foo` | `ns` | `me` | `ns/foo` |
+| `foo/bar` | `ns` | `me` | `ns/foo/bar` |
+
+*Use case:* Use relative names for topics that are specific to a node, but might be reused across multiple nodes.
+
+*Example:* A robot contains 4 motor controllers of the same type, each has its own namespace (`motor_1`, `motor_2`, `motor_3`, `motor_4`).
+Using relative names, the application code is the same for all 4 motor controllers, however the topics are resolved differently based on the node namespace.
+
+| Input name | Namespace | Home | Resolved name |
+| ----------------- | --------- | ------- | ---------------------------- |
+| `speed` | `motor_1` | `robot` | `motor_1/speed` |
+| `speed` | `motor_2` | `robot` | `motor_2/speed` |
+| `speed` | `motor_3` | `robot` | `motor_3/speed` |
+| `speed` | `motor_4` | `robot` | `motor_4/speed` |
+
+
+
+
+Absolute Name
+
+An absolute name starts with `/`.
+
+```
+/temperature
+/diagnostics/status
+```
+
+Its resolved name is simply the same as the input name, ignoring both the node namespace and home.
+
+| Input name | Namespace | Home | Resolved name |
+| ----------------- | --------- | ---- | ------------------ |
+| `foo` | `ns` | `me` | `foo` |
+| `foo/bar` | `ns` | `me` | `foo/bar` |
+
+Use case: Use absolute names for topics that are *not* specific to a node and might be reused across multiple nodes.
+
+Example: Shared system topics like `/log`, since multiple nodes may publish to the same topic.
+Conversely, topics like `/battery_voltage` that might be sourced from multiple nodes but need one single source of truth for other nodes like the motor controllers to subscribe to.
+
+| Input name | Namespace | Home | Resolved name |
+| --------------------- | --------------- | ------- | ------------------ |
+| `/log` | `cpu` | `robot` | `/log` |
+| `/battery_voltage` | `battery_1` | `robot` | `/battery_voltage` |
+
+
+
+
+Homeful Name
+
+A homeful name starts with `~` of `~/`.
+
+```
+~/config
+```
+
+Its resolved name consists of the home and the input name, with the node namespace ignored. Note that `~foo` is not homeful and resolves as relative name to `ns/~foo` (this is confusing so don't use this).
+
+Proposal: both `~` and `~foo` should not be allowed.
+
+| Input name | Namespace | Home | Resolved name |
+| --------------------- | --------------- | ------- | ------------------ |
+| `~` | `ns` | `me` | `me` |
+| `~/config` | `ns` | `me` | `me/config` |
+| `~config` | `ns` | `me` | `ns/~config` |
+
+Use case: For topics tied to specific nodes. The most common use case is configuring a node's parameters or settings.
+
+Example: We want to configure an antenna to transmit at a specific frequency. The antenna node has a `~/config/frequency` topic that we can publish to.
+
+
+
+
+Pattern Name (only for subscribing)
+
+A pattern name contains wildcard `*` (matches any _single_ name segment)
+
+```
+*/speed # matches any topic under `speed` (e.g. `motor_1/speed`, `motor_2/speed/`, `motor_3/value`, ...)
+```
+
+or `>` (matches _zero or more_ trailing segments)
+
+```
+sensor/> # matches any topic under `sensor` (e.g. `sensor/`, `sensor/temperature`, `sensor/pressure/`, ...)
+```
+
+Use case: Use `*` to subscribe to a _specific_ topic coming from a undetermined number of nodes.
+Use `>` to subscribe to _multiple_ topics under a given namespace.
+
+Example: `*/battery_pct` to subscribe to all nodes publishing battery data, of which there may be multiple per vehicle.
+'logs/>' to subscribe to all topics publishing under '/logs' which may contain 'log_info', 'log_warning', 'log_error' topics.
+
+
+
+Used effectively they allow to split up complex systems into smaller sub-systems simplifying development and debugging.
+
+### Extra functions
+
+*Topping* is the process by which a unique subject ID is assigned upon initialization.
+For some applications that require a high level of reliability, determinism is required and can be achieved by using `#` to pin a topic to a specific subject ID.
+
+```
+motor/speed#1234
+```
+
+The resolved topic name is 'motor/speed' and the subject ID is fixed to 1234.
+
+*Remapping* lets a node replace one name with another before final resolution.
+This can be useful when trying to match the expected topic name from one node to another (when integrating multiple subsystems).
+
+```
+node.remap({"sensor/temperature": "temp"})
+```
+
+Now any topic name matching `sensor/temperature` will be remapped to `temp` before final resolution.
-The topic naming system shares many similarities with ROS.
A valid name contains printable ASCII characters except space (ASCII codes [33, 126]).
Normalized names do not have leading or trailing segment separators `/` and do not have consecutive separators.
Every node should have a unique name, which is called its *home*; home substitution is done via `~/`.
@@ -66,7 +201,7 @@ async def main():
See also :meth:`Node.remap`.
-### Publish
+## Publish
Publication is best-effort by default. Pass `reliable=True` when publishing to retry delivery until
acknowledged by every known subscriber or until the deadline; if the remote side does not acknowledge in time,
@@ -77,7 +212,7 @@ async def main():
await pub(Instant.now() + 1.0, b"payload", reliable=True)
```
-### Subscribe
+## Subscribe
Subscriptions normally yield messages as soon as they arrive. Set `reordering_window` [seconds] on
:meth:`Node.subscribe` to allow delaying out-of-order messages to reconstruct the original publication order.
@@ -99,7 +234,7 @@ async def main():
print(topic.name, captures) # [('engine', 1)], where 1 is the pattern segment index
```
-### RPC & streaming
+## RPC & streaming
RPC is layered directly on top of pub/sub. Use :meth:`Publisher.request` to publish a message that expects
responses, and use :attr:`Arrival.breadcrumb` on the subscriber side to send a unicast reply back to the requester.
@@ -119,7 +254,7 @@ async def main():
await arrival.breadcrumb(Instant.now() + 1.0, b"chunk-2", reliable=True)
```
-### Topic pinning
+## Topic pinning
Topics may be pinned to a specific subject-ID using `name#1234` to bypass automatic assignment.
This is useful for applications where a high degree of determinism is required and for Cyphal/CAN v1.0 interoperability.
@@ -135,7 +270,7 @@ async def main():
Old Cyphal/CAN v1.0 nodes do not participate in the topic discovery protocol,
so topics joined only by such nodes are not discoverable by pattern subscribers.
-## Remarks
+# Remarks
Cyphal does not define a serialization format. Previous versions used to define the DSDL format but it has been
extracted into an independent project, and Cyphal was made serialization-agnostic in v1.1+.