phoxal
The Phoxal robot framework as one crate: a manifest-driven stack for production-oriented autonomous robots — a typed Zenoh bus, a derive-based runtime authoring model, and a single, dated API-version contract set.
Greenfield rewrite in progress (
tmp/framework-rewrite). The bus + runtime engine and the macros are new; the official runtime/simulator/tool crates are being re-ported onto this surface and are temporarily out of the workspace.
[]
= "0.11"
The authoring model
A runtime is one struct of typed handles + one annotated inherent impl. The struct declares the contracts it uses (as handle fields) and the one API version it runs against; the impl declares the lifecycle.
use y2026_1 as api;
use *;
Key rules the example shows:
- Import exactly one dated API module (
use phoxal::api::y2026_1 as api;) and declare it on the derive (#[phoxal(api = y2026_1)], mandatory). - Handle fields use version-local bodies:
Publisher<api::drive::State>,Latest<api::drive::Target>. The derive emits aContractBody<Api = R::Api>assertion, so a body from another API version is a compile error. - Topics are api-local:
api::topic::new().drive().state(). - The wire body is the plain payload;
api_version, family, and codec ride bus metadata. Normal runtimes never open Zenoh — the runner opens the bundle-selected bus profile before#[setup]. cargo run --example runtime_control_loop emit-apisprints the runtime's static metadata as one JSON document (theemit-apissubcommand) and exits.
Modules
| Module | What it is |
|---|---|
[phoxal::api] |
Dated API-version modules (y2026_1, …) generated by phoxal_api_tree!: the marker enum Api (ApiVersion), version-local wire bodies + their ContractBody impls, and the api-local topic builders. |
[phoxal::bus] |
The Zenoh-native bus_abi boundary: the key scheme <namespace>/robots/<robot-id>/<topic>, the MessagePack codec, the BusMetadata attachment, and the body-typed handles Publisher/Subscriber/Latest. |
[phoxal::runtime] |
The static metadata traits the macros target, SetupContext/StepContext, the clock (RealClock/TestClock) + scheduler, ParticipantLaunch, emit-apis, and the runner (run / tokio::run). |
[phoxal::model] |
Authored manifest schemas (robot.yaml, structure.urdf, …). |
Entrypoints
- Default (blocking):
fn main() -> phoxal::Result<()> { phoxal::run::<R>() }. - Advanced (async):
phoxal::tokio::run::<R>().awaitfor custom Tokio mains.
Status
Pre-1.0, building in public. One API version per robot graph (#[phoxal(api = y2026_1)]); the wire body is the plain payload and the version identity rides bus
metadata, never the key. Compatibility is checked at build/check time
(emit-apis + phoxal-cli check), never by introspecting a running binary.
License
AGPL-3.0-only. A commercial license is available — see the repository.