Skip to main content

Crate linkage_blaze

Crate linkage_blaze 

Source
Expand description

§linkage-blaze

GitHub crates.io docs.rs

3D turtle graphics for animated jointed mechanisms and figures. Describe a figure with moves, turns, branches, links, joints, disks, and spheres, then animate parameters to bring it to life. Runs both no_std and std.

Armatron demo preview Ballet demo preview

§What is Linkage Blaze?

Linkage Blaze is a Rust-based domain-specific language (DSL) for making animated jointed drawings. It works like 3D turtle graphics: move forward, turn, branch, draw links, place joints, and add simple shapes such as disks and spheres. Animate a few parameters, and the drawing moves.

The demos include robot arms, clocks, and motion-controlled skeletons. The workspace targets microcontrollers through Device Envoy’s CYD (Cheap Yellow Display) APIs (ESP32 , RP, WASM).

The default crate configuration is no_std and allocation-free, so figures live in flash and animate on small microcontrollers. An opt-in alloc feature adds heap-based conveniences where an allocator is available.

The live gallery is the main showcase: carlkcarlk.github.io/linkage-blaze/demos/

It shows preview images of each demo and links to the live, interactive WASM versions.

Linkage Blaze demo gallery preview

§Articles

§Usage

linkage-blaze can run on embedded systems:

  • It does not require the Rust standard library (no_std).
  • It does not use heap allocation.
  • ESP and RP applications can use the LinkageFixed access generated by linkage_file!.

It can also run, with more features, in std runs:

  • alloc enables owned parsing.
  • bvh enables host-side APIs for reading Biovision Hierarchy (BVH) motion-capture files.
[dependencies]
linkage-blaze = "<latest version>"

Replace <latest version> with the current release shown on crates.io.

Install the Biovision Hierarchy (BVH) converter with:

cargo install linkage-blaze --features bvh --bin bvh-to-lb

§Platform Examples

  • Raspberry Pi Pico / RP - Pico 1 and Pico 2 examples, including Pico W variants.
  • ESP32 - Cheap Yellow Display examples across supported ESP32 families and boards.
  • Browser / WASM - Browser builds behind the live gallery.

The platform examples and browser adapter use the workspace version but are not separately published to crates.io. WASM applications provide their own cdylib and may depend on linkage-blaze with the alloc feature.

§Quick Start

The core workflow is: construct one or more linkages, combine them, obtain a borrowed LinkageView, and evaluate that view for geometry or a final pose.

§1. Construct a linkage from steps

LinkageFixed stores an allocation-free linkage in fixed-capacity arrays. Start at the origin, optionally define normalized parameters, and append movement and drawing steps with the fluent methods:

const ARM: LinkageFixed<1, 1, 8> = LinkageFixed::start()
    .define_param("shoulder", 0.5)
    .yaw_param("shoulder", -90.0, 90.0)
    .forward(3.0)
    .mark("hand");

The const generic arguments are the parameter count, mark-slot count, and step capacity. Unused step capacity is allowed.

§2. Combine linkages

LinkageFixed::combine appends another linkage without replaying its initial Start step:

const BASE: LinkageFixed<0, 0, 2> = LinkageFixed::start().forward(2.0);
const TIP: LinkageFixed<0, 0, 2> = LinkageFixed::start().left(1.0);
const FIGURE: LinkageFixed<0, 0, 4> = BASE.combine(TIP.view());

The output type states the combined parameter, mark, and step capacities.

§3. Evaluate the final pose

Call LinkageFixed::view to borrow a linkage, then pass one normalized value per parameter to LinkageView::final_pose:

const LINKAGE: LinkageFixed<1, 0, 4> = LinkageFixed::start()
    .define_param("reach", 0.5)
    .forward_param("reach", 1.0, 5.0);

let pose = LINKAGE.view().final_pose(&[0.5])?;
assert!(pose.position().is_close_to(&Vec3::from([3.0, 0.0, 0.0]), 1e-5));

§4. Evaluate for rendering

LinkageView::draw_items_3d evaluates strokes and shapes as an iterator of render::Item3d values. A platform renderer can project and draw each item without allocating:

const LINKAGE: LinkageFixed<0, 0, 3> = LinkageFixed::start()
    .forward(2.0)
    .left(1.0);

let stroke_count = LINKAGE
    .view()
    .draw_items_3d(&[])?
    .filter(|item| matches!(item, Item3d::Stroke(_)))
    .count();
assert_eq!(stroke_count, 2);

See the complete ESP32, RP, and WASM examples for display integration.

§5. Save and import a large linkage

Put a long fluent expression in a .lb.rs asset file. The file contains one linkage![...] expression with leading-dot methods:

linkage![
    .define_param("reach", 0.5)
    .forward_param("reach", 1.0, 5.0)
    .mark("tip")
];

Import it with linkage_file!. The macro measures the asset at compile time and creates a module containing its exact fixed type, value, and borrowed view. Choose view() for a borrowed, allocation-free handle, fixed() when you need the compile-time owner, or buf() under alloc when the linkage must be growable:

use linkage_blaze::linkage_file;

linkage_file! {
    figure {
        file: "assets/figure.lb.rs",
    }
}

type FigureFixed = figure::Fixed;
type FigureView = figure::View;
const FIGURE: FigureFixed = figure::fixed();
const FIGURE_VIEW: FigureView = figure::view();
#[cfg(feature = "alloc")]
let figure_buf: figure::Buf = figure::buf();

The import is a text excerpt because rustdoc cannot provide the external asset file at the macro call site. The repository’s linkage_file integration test compile-checks the complete external-file import path.

§6. Edit a large linkage

Open the interactive Linkage Blaze editor to edit and preview .lb.rs assets. Open an existing file or paste an expression, adjust its generated parameter controls while watching the 3D preview, and use Save or Save As to write the edited .lb.rs file.

Editor output uses the same syntax as the allocator-backed parser, so it can be checked before use:

use linkage_blaze::LinkageBuf;

let edited_source = r#"
linkage![
    .define_param("reach", 0.5)
    .forward_param("reach", 1.0, 5.0)
    .mark("tip")
]
"#;
let linkage = LinkageBuf::<1, 1>::from_lb_rs(edited_source)?;
assert_eq!(linkage.view().dof(), 1);

For motion-capture input, see the bvh module and its Biovision Hierarchy conversion APIs.

§Policy on AI-assisted development and contributions

The use of AI tools is permitted for development and contributions to this repository. AI may be used as a productivity aid for drafting, exploration, and refactoring.

All code and documentation contributed to this repository must be reviewed, edited, and validated by a human contributor. AI tools are not a substitute for design judgment, testing, or responsibility for correctness.

AGENTS.md contains the general instructions and constraints given to AI tools used during development of this repository.

§License

Licensed under either:

at your option.

§Coordinate System

Model-space axes:

  • +X = forward / along the link
  • +Y = left
  • +Z = up

Rotations:

  • yaw = rotate about local +Z
  • pitch = rotate about local +Y
  • roll = rotate about local +X

Modules§

bvh
Support for the Biovision Hierarchy (BVH) motion-capture file format.
examples
Platform-neutral example logic for the Linkage Blaze display examples.
render
Evaluated three-dimensional drawing geometry and projection helpers.

Macros§

linkage
Define a linkage expression inside a .lb.rs asset file.
linkage_file

Structs§

DrawItem3dIter
Iterator over Item3ds produced by evaluating a linkage.
LinkageBuf
An allocator-backed, growable linkage buffer for runtime construction or parsing.
LinkageFixed
An allocation-free linkage with compile-time-fixed capacities.
LinkageView
A borrowed linkage used to evaluate, compose, and render a linkage.
Mat3
Local-frame orientation matrix stored row-major: mat[row][col].
Param
A named linkage parameter with a normalized default value.
ParamArg
A linkage parameter reference and the operation-value range it controls.
Pose
A 3D position and local-frame orientation after evaluating a linkage step.
Rgb888
RGB color used by pen and shape operations in a linkage.
StyledPose
A Pose plus the pen state, color, and width active after a linkage step.
Vec3
3D position or vector [x, y, z].

Enums§

Error
Error returned by linkage evaluation and named-mark lookup.
PenState
Whether movement currently emits strokes.
Step
One movement, drawing, shape, mark, or restore operation in a linkage.
StepArg
A fixed operation value or a value interpolated from a normalized linkage parameter.

Traits§

RgbColor
Channel access and basic color constants for Rgb888. See the color and rendering example. RGB color.
WebColors
CSS named colors available as Rgb888::CSS_* constants in linkage assets. See the color and rendering example. Named colors as defined in the CSS specification.