wrenfold

wrenfold: Symbolic code generation for robotics - Published in JOSS (2025)

https://github.com/wrenfold/wrenfold

Science Score: 98.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 7 DOI reference(s) in README and JOSS metadata
  • Academic publication links
    Links to: arxiv.org, joss.theoj.org
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
    Published in Journal of Open Source Software

Keywords

code-generation computer-vision mathematics robotics symbolic-math

Scientific Fields

Mathematics Computer Science - 37% confidence
Last synced: 4 months ago · JSON representation ·

Repository

Toolkit for generating code from symbolic math expressions.

Basic Info
  • Host: GitHub
  • Owner: wrenfold
  • License: mit
  • Language: C++
  • Default Branch: main
  • Homepage:
  • Size: 3.15 MB
Statistics
  • Stars: 68
  • Watchers: 5
  • Forks: 1
  • Open Issues: 21
  • Releases: 14
Topics
code-generation computer-vision mathematics robotics symbolic-math
Created about 4 years ago · Last pushed 5 months ago
Metadata Files
Readme Contributing License Citation Support

README.md

wrenfold

wrenfold logo depicting a bird made from folded paper

CI Status Code Coverage Status Python versions badge conda-forge version badge crates.io C++17

Documentation


wrenfold is a framework for converting symbolic mathematical expressions (written in Python) into generated numerical code in other languages (C++, Rust, Python). It aims to bridge the gap between prototyping of functions in expressive symbolic form, and performant production code. wrenfold is particularly relevant to domains where numerical optimization is employed to solve differentiable objective functions, such as robotics or computer vision.

Using wrenfold, mathematical functions can be expressed and composed succinctly in python:

```python from wrenfold import codegeneration, sym from wrenfold.typeannotations import Vector3

def angulardistance(a: Vector3, b: Vector3): """ A simple example function: We compute the angle between two vectors. The angle is returned, and the Jacobian with respect to a is passed as an output argument. This might be a cost in an optimization, for instance. """ dot = (a.T * b)[0] costheta = dot / (a.norm() * b.norm()) theta = sym.acos(costheta) thetaD_a = sym.jacobian([theta], a)

# Our generated function will return `theta`, and pass `theta_D_a` as an output arg.
return (
    code_generation.ReturnValue(theta),
    code_generation.OutputArg(theta_D_a, "theta_D_a"),
)

```

And corresponding compilable code can be obtained easily:

```python

CppGenerator can be swapped out for RustGenerator to obtain Rust. You can implement your own

custom generator to target a new language - or override methods on the provided generators in

order to customize the output code to your liking.

cpp = codegeneration.generatefunction(angulardistance, codegeneration.CppGenerator()) print(cpp) cpp template Scalar angulardistance(const T0& a, const T1& b, T2&& thetaDa) { auto _a = wf::makeinputspan<3, 1>(a); auto _b = wf::makeinputspan<3, 1>(b); auto _thetaDa = wf::makeoutputspan<1, 3>(thetaD_a);

const Scalar v007 = _b(2, 0); const Scalar v006 = _a(2, 0); const Scalar v004 = _b(1, 0);

// ... Output code is truncated for brevity.

const Scalar v009 = v000 * v001 + v003 * v004 + v006 * v007; const Scalar v021 = v001 * v001 + v004 * v004 + v007 * v007;

// ...

thetaDa(0, 0) = (v000 * v072 + v001 * v017) * v073; _thetaDa(0, 1) = (v003 * v072 + v004 * v017) * v073; _thetaD_a(0, 2) = (v006 * v072 + v007 * v017) * v073; return std::acos(v009 * v017 * v023); } ```

wrenfold draws inspiration from SymForce, but differs in a few key ways:

  • Improved flexibility: Symbolic expressions can include conditional logic. This enables a broader range of functions to be generated.
  • Ease of integration: wrenfold aims to make it straightforward to customize the code-generation step to suit your project. For example, you can use existing types in your codebase in generated method signatures.
  • Faster code generation: Faster code generation translates to quicker iteration on experiments. The generation cost should ideally be negligible compared to compile time for the code itself.
  • Narrower scope: wrenfold does not implement a numerical optimizer. Rather we aim to make it simple to integrate generated code into your project's existing preferred optimizer (see the extended examples). It should be relatively straightforward to use wrenfold functions with GTSAM, Ceres, the SymForce optimizer, or your own custom implementation.

wrenfold is primarily written in C++, and exposes a python API via pybind11. It can presently generate code in C++17, Rust, and Python (NumPy, PyTorch, and JAX are all supported). <!--- intro_end --->

Motivation

Why use symbolic code generation for mathematical functions? The SymForce paper outlines some of the rationale. In our opinion, the two main arguments are:

  • Faster iteration:
    • Functions can be written quickly and expressively in python, enabling rapid prototyping. Over time, users acquire a library of composable expressions that can be combined easily to form new symbolic functions.
    • Derivatives are obtained automatically, without spending time debugging manually chain-ruled Jacobians.
  • Improved runtime performance:
    • The performance of generated methods is often competitive with handwritten implementations, and can meaningfully exceed results obtained with runtime auto-diff.
    • Generated methods are fast enough to deploy on a production robot, enabling a quicker pipeline from offline prototyping to real-world testing.
    • A prudent caveat for any performance related claim: Your mileage may vary depending on expression complexity and the degree of effort exerted in optimizing different implementations.

Getting started

Install wrenfold from PyPi:

bash pip install wrenfold

wrenfold is also available on conda-forge:

conda-forge platforms

bash conda install -c conda-forge wrenfold

To get started: - Refer to the quick start guide and user guide. - Take a look at some of the examples: - There are some examples of symbolic expressions in this repository. For instance, an implementation of imu integration or the dynamics of a cart-pole/double-pendulum system. - Each example includes a unit test that invokes the generated code. - The wrenfold-extra-examples repository includes examples of integrating generated code into existing optimizers like GTSAM and Ceres.

Building from source

See Building from source.

Project status

wrenfold was originally created by me after determining there were opportunities to push the symbolic code-generation concept further (see motivations section).

The project began as a part-time hobby for fun, and has evolved into a more full-featured framework over time. wrenfold is in the early stages of receiving feedback from a wider audience. There will be rough edges and undoubtedly some bugs. If you find something broken or missing, please consider filing a ticket. I aim to continue developing and expanding the framework. For details of upcoming work, see the planned features list.

If you are interested in collaboration opportunities or have general questions, please reach out.

License

wrenfold uses the MIT License.

Citation

DOI badge

wrenfold is published in the Journal of Open Source Software (JOSS). If you wish to cite this project, please use the following:

bibtex @article{Cross2025, doi = {10.21105/joss.07303}, url = {https://doi.org/10.21105/joss.07303}, year = {2025}, publisher = {The Open Journal}, volume = {10}, number = {105}, pages = {7303}, author = {Gareth Cross}, title = {wrenfold: Symbolic code generation for robotics}, journal = {Journal of Open Source Software} } <!--- citation_end --->

Owner

  • Name: wrenfold
  • Login: wrenfold
  • Kind: organization
  • Location: United States of America

Organization for the wrenfold symbolic code generator.

JOSS Publication

wrenfold: Symbolic code generation for robotics
Published
January 28, 2025
Volume 10, Issue 105, Page 7303
Authors
Gareth Cross ORCID
Independent Researcher, USA
Editor
Sébastien Boisgérault ORCID
Tags
symbolic math robotics computer vision code generation

Citation (CITATION.cff)

cff-version: "1.2.0"
authors:
- family-names: Cross
  given-names: Gareth
  orcid: "https://orcid.org/0009-0008-3110-0078"
doi: 10.5281/zenodo.14723141
message: If you use this software, please cite our article in the
  Journal of Open Source Software.
preferred-citation:
  authors:
  - family-names: Cross
    given-names: Gareth
    orcid: "https://orcid.org/0009-0008-3110-0078"
  date-published: 2025-01-28
  doi: 10.21105/joss.07303
  issn: 2475-9066
  issue: 105
  journal: Journal of Open Source Software
  publisher:
    name: Open Journals
  start: 7303
  title: "wrenfold: Symbolic code generation for robotics"
  type: article
  url: "https://joss.theoj.org/papers/10.21105/joss.07303"
  volume: 10
title: "wrenfold: Symbolic code generation for robotics"

GitHub Events

Total
  • Create event: 90
  • Issues event: 5
  • Release event: 5
  • Watch event: 36
  • Delete event: 74
  • Issue comment event: 25
  • Push event: 172
  • Pull request review comment event: 1
  • Pull request review event: 4
  • Pull request event: 92
  • Fork event: 1
Last Year
  • Create event: 90
  • Issues event: 5
  • Release event: 5
  • Watch event: 36
  • Delete event: 74
  • Issue comment event: 25
  • Push event: 172
  • Pull request review comment event: 1
  • Pull request review event: 4
  • Pull request event: 92
  • Fork event: 1

Committers

Last synced: 5 months ago

All Time
  • Total Commits: 316
  • Total Committers: 3
  • Avg Commits per committer: 105.333
  • Development Distribution Score (DDS): 0.006
Past Year
  • Commits: 69
  • Committers: 2
  • Avg Commits per committer: 34.5
  • Development Distribution Score (DDS): 0.014
Top Committers
Name Email Commits
Gareth g****e@i****m 314
Himel Mondal h****1@g****m 1
Anurag Makineni a****i 1

Issues and Pull Requests

Last synced: 4 months ago

All Time
  • Total issues: 12
  • Total pull requests: 100
  • Average time to close issues: about 1 month
  • Average time to close pull requests: 4 days
  • Total issue authors: 3
  • Total pull request authors: 2
  • Average comments per issue: 0.83
  • Average comments per pull request: 0.11
  • Merged pull requests: 95
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 4
  • Pull requests: 71
  • Average time to close issues: 10 days
  • Average time to close pull requests: about 12 hours
  • Issue authors: 2
  • Pull request authors: 2
  • Average comments per issue: 0.0
  • Average comments per pull request: 0.07
  • Merged pull requests: 66
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • gareth-cross (10)
  • rowoflo (1)
  • Galto2000 (1)
Pull Request Authors
  • gareth-cross (151)
  • anuragmakineni (2)
Top Labels
Issue Labels
feature (9) p0 (3) bug (2)
Pull Request Labels
feature (46) bug (17) cleanup (13) documentation (11) performance (4)

Packages

  • Total packages: 2
  • Total downloads:
    • pypi 543 last-month
    • cargo 7,586 total
  • Total dependent packages: 0
    (may contain duplicates)
  • Total dependent repositories: 0
    (may contain duplicates)
  • Total versions: 16
  • Total maintainers: 2
pypi.org: wrenfold

Tools for code-generating mathematical functions.

  • Versions: 11
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 543 Last month
Rankings
Dependent packages count: 9.5%
Average: 36.0%
Dependent repos count: 62.6%
Maintainers (1)
Last synced: 4 months ago
crates.io: wrenfold-traits

Runtime traits for the wrenfold symbolic code-generation library.

  • Versions: 5
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 7,586 Total
Rankings
Dependent repos count: 26.9%
Dependent packages count: 35.6%
Average: 53.0%
Downloads: 96.5%
Maintainers (1)
Last synced: 4 months ago

Dependencies

.github/workflows/build-wheels.yml actions
  • actions/checkout v4 composite
  • actions/download-artifact v4 composite
  • actions/setup-python v5 composite
  • actions/upload-artifact v4 composite
  • ilammy/msvc-dev-cmd v1 composite
  • maxim-lobanov/setup-xcode v1 composite
  • mikepenz/release-changelog-builder-action v4 composite
  • softprops/action-gh-release v2 composite
.github/workflows/ci.yml actions
  • Swatinem/rust-cache v2 composite
  • actions/cache v3 composite
  • actions/checkout v4 composite
  • conda-incubator/setup-miniconda 11b562958363ec5770fef326fe8ef0366f8cbf8a composite
  • ilammy/msvc-dev-cmd v1 composite
  • maxim-lobanov/setup-xcode v1 composite
Cargo.lock cargo
  • 326 dependencies
Cargo.toml cargo
components/core/tests/rust_generation_test/Cargo.lock cargo
  • approx 0.5.1
  • autocfg 1.1.0
  • bytemuck 1.14.0
  • matrixmultiply 0.3.8
  • nalgebra 0.32.3
  • nalgebra-macros 0.2.1
  • num-complex 0.4.4
  • num-integer 0.1.45
  • num-rational 0.4.1
  • num-traits 0.2.16
  • paste 1.0.14
  • proc-macro2 1.0.67
  • quote 1.0.33
  • rawpointer 0.2.1
  • safe_arch 0.7.1
  • simba 0.8.1
  • syn 1.0.109
  • typenum 1.17.0
  • unicode-ident 1.0.12
  • wide 0.7.11
components/core/tests/rust_generation_test/Cargo.toml cargo
components/core/tests/rust_generation_test_2/Cargo.toml cargo
components/rust/wrenfold-test-utils/Cargo.toml cargo
components/rust/wrenfold-traits/Cargo.toml cargo
docs/source/quick_start_files/rosenbrock_crate/Cargo.lock cargo
  • approx 0.5.1
  • autocfg 1.3.0
  • bytemuck 1.16.1
  • matrixmultiply 0.3.8
  • nalgebra 0.32.6
  • nalgebra-macros 0.2.2
  • num-complex 0.4.6
  • num-integer 0.1.46
  • num-rational 0.4.2
  • num-traits 0.2.19
  • paste 1.0.15
  • proc-macro2 1.0.86
  • quote 1.0.36
  • rawpointer 0.2.1
  • safe_arch 0.7.2
  • simba 0.8.1
  • syn 2.0.68
  • typenum 1.17.0
  • unicode-ident 1.0.12
  • wide 0.7.25
  • wrenfold-traits 0.0.3
docs/source/quick_start_files/rosenbrock_crate/Cargo.toml cargo
examples/bspline/bspline_demo/Cargo.toml cargo
examples/bspline/bspline_rust_test/Cargo.toml cargo
examples/custom_types/custom_types_rust_test/Cargo.toml cargo
examples/motion_planning/motion_planning_test/Cargo.toml cargo
pyproject.toml pypi
environment.yml conda
  • breathe 4.35.0
  • cmake >=3.20
  • doxygen
  • furo
  • mypy
  • myst-parser
  • ninja >=1.5
  • numpy
  • pre-commit
  • python 3.9.*
  • sphinx 6.2.1
  • sympy