Jaxonomy — hybrid dynamical systems on JAX

io.github.machinavitalisPublished by GitHub account machinavitalisv3.4.1Updated Oct 27, 2026

Build, simulate and calibrate JAX block-diagram models of hybrid dynamical systems.

VerifiedSTDIODesktop onlyDeveloper ToolsData & Analytics

Overview

AI-generated overview

Exposes the Jaxonomy JAX simulation engine as tools so an assistant can build, validate, simulate, fit and linearize hybrid dynamical system models.

What you can do
  • Enumerate the built-in library blocks available for building models
  • Build and validate block-diagram models of hybrid dynamical systems
  • Run simulations and return the resulting signals for reasoning
  • Fit model parameters to data and linearize a system
  • Report results back so the assistant can reason over actual simulation output
When to use it
Use it when you drive Jaxonomy from an AI agent such as Claude Desktop, Claude Code or Cursor and want the agent to construct and run models itself. If you are writing Python by hand, the plain package install is enough and this server can be skipped.
Requirements
Runs as a local stdio process on the user's machine (desktop only). Requires Python 3.10+ with the jaxonomy package including its MCP extra installed, launched via the module entry point or the jaxonomy-mcp entry point using the interpreter where it is installed. No authentication, environment variables or headers are declared.
Before you install
The server runs local code and simulations on your machine; the README notes that full tool reference and limitations are documented separately, so check those before relying on it. Optional extras may require external solvers on PATH. No credentials or payments are involved.

Installation

In SourceWeft

  1. Open Jaxonomy — hybrid dynamical systems on JAX in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

[Jaxonomy — compose, simulate, control]

Jaxonomy

Differentiable simulation of hybrid dynamical systems — powered by JAX.

[PyPI] [Python 3.10+] [License: MIT] [Docs]

Block diagrams meet automatic differentiation. Model physical systems, close the loop with LQR/MPC/Kalman, and differentiate through everything.

Why JAX? · Install · Quick Start · Gallery · Examples · Docs

Every panel above is produced by jaxonomy.simulate on a model built from the library.


What is Jaxonomy?

Jaxonomy is a Python framework for modeling, simulating, and optimizing hybrid dynamical systems — systems that combine continuous physics, discrete control laws, and event-driven logic in a single model. Every simulation runs on JAX, so it is JIT-compilable, batchable with vmap, and fully differentiable from end to end.

python
import jax.numpy as jnpimport jaxonomy as jx
# Double integrator: A, B, C, D define the plant; Q, R weight the LQR cost.A, B = jnp.array([[0., 1.], [0., 0.]]), jnp.array([[0.], [1.]])C, D = jnp.eye(2), jnp.zeros((2, 1))Q, R = jnp.eye(2), jnp.array([[1.]])
builder = jx.DiagramBuilder()# Start displaced from the origin, so the regulator has something to do.plant      = builder.add(jx.library.LTISystem(A, B, C, D,                                              initialize_states=jnp.array([1.0, 0.0])))controller = builder.add(jx.library.LinearQuadraticRegulator(A, B, Q, R))builder.connect(plant.output_ports[0],      controller.input_ports[0])builder.connect(controller.output_ports[0], plant.input_ports[0])
diagram = builder.build()results = jx.simulate(    diagram,    diagram.create_context(),    (0.0, 10.0),    # Nothing is stored unless you name it here: without recorded_signals,    # results.time and results.outputs come back as None.    recorded_signals={"x": plant.output_ports[0],                      "u": controller.output_ports[0]},)
results.outputs["x"]    # (T, 2) — position and velocity, driven back to zero

🔥 Why JAX?

Choosing JAX as the compute backbone unlocks capabilities that are impractical with NumPy-based simulators:

Traditional simulator          Jaxonomy / JAX──────────────────────         ─────────────────────────────────────────simulate(params)          →    jit(simulate)(params)          10–100× fasterfor p in param_grid: …    →    vmap(simulate)(param_grid)     embarrassingly parallelfinite_diff_gradient(…)   →    grad(simulate)(params)         exact gradients, free
FeatureSciPy / NumPyJulia / DiffEqModelicaMathWorks¹Jaxonomy
Python-native✓✗✗✗✓
JIT / code generation✗✓✓ (C++)✓ (C/C++)✓
Full autodiff through ODE✗Partial✗Partial²✓
Hybrid events & zero-crossingPartial✓✓✓✓
Acausal / equation-based✗✗✓✓ (Simscape)✓
Block-diagram composition✗PartialPartial✓ (Simulink)✓
State-machine modeling✗✗✗✓ (Stateflow)✓
LQR / MPC / Kalman built-in✗PartialVia libs✓ (Toolboxes)✓
Neural ODE / SINDy✗✓✗✗✓
Reduced-order modeling (balred / POD-DEIM / DMD / Koopman)✗Partial✗✓ (Toolboxes)✓
Batch / ensemble (vmap)✗✗✗✗✓
Open-source (MIT)✓✓Partial✗✓

¹ Simulink + Simscape + Stateflow + Control System Toolbox  ·  ² Via Simulink Design Optimization, no end-to-end AD


⚡ Key Capabilities

CapabilityWhat it enables
⚡ JAX-native engineJIT-compile simulations, run ensembles with vmap, differentiate through ODE solvers including event handling
🔀 Hybrid dynamics + state machinesContinuous ODEs, periodic discrete updates, zero-crossing events, and StateMachineBuilder-authored finite state machines composed in one model. jax.grad flows through event times for hybrid trajectory optimisation.
🔌 Acausal modelingModelica-inspired multi-domain components (electrical, mechanical, thermal, fluid, battery) with Pantelides index reduction and a BDF mass-matrix DAE solver
🎯 Control & estimationLQR (continuous, discrete, finite-horizon, LQG), linear MPC (native + OSQP), nonlinear MPC (shooting / transcription / Hermite-Simpson), Kalman / EKF / UKF / RLS / Luenberger, 2-DOF PID with classical tuning helpers
🧮 Unit-aware wiringOptional BusUnit annotations on ports and signals; the diagram compiler catches dimensional mismatches at build time instead of as silent runtime bugs
🧠 Data-driven modelingNeural ODEs, Universal Differential Equations, SINDy symbolic regression, neural-network blocks (MLP / PyTorch / TensorFlow / ONNX), differentiable lookup-table fitting, and statistical surrogates (Gaussian process, polynomial chaos, RBF)
📉 Reduced-order modelingjaxonomy.library.rom: linear MOR (balanced truncation, minreal, modal / residualization), POD–Galerkin with DEIM hyper-reduction, and data-driven operator ROM (DMD / DMDc / ERA, Koopman / eDMD lifted-linear predictors). One reduce(...) front door; every reduced model is a differentiable, simulatable block
🎲 Uncertainty & sensitivityFirst-class jaxonomy.uq workflow: Monte Carlo with parameter distributions, Latin Hypercube + quasi-Monte Carlo sampling, Sobol sensitivity decomposition, Morris screening
🤝 FMI 2.0 / 3.0 interopImport FMI co-simulation FMUs (ModelicaFMU, mixed-type and array I/O) or model-exchange FMUs (ModelicaFMUME, integrated by Jaxonomy's own solver with FMI event indicators as zero-crossings); export a diagram as a binary .fmu via build_fmu. Verified against the Reference FMUs, OpenModelica, and the fmusim reference simulator in CI
🧩 150+ library blocksIntegrators, filters, state machines, look-up tables, coordinate transforms, container blocks, bus / mux family, stochastic sources, and more

📦 Installation

Requires Python 3.10+.

bash
# Create and activate a virtual environment (recommended)python -m venv .venvsource .venv/bin/activate        # Windows: .venv\Scripts\activate
# Installpip install jaxonomy             # corepip install jaxonomy[safe]       # + SciPy, Matplotlib, control, jaxoptpip install jaxonomy[nmpc]       # + nonlinear MPC (requires IPOPT on PATH)pip install jaxonomy[all]        # + everything

From source:

bash
git clone https://github.com/machinavitalis/jaxonomycd jaxonomypip install -e .

CLI runner:

bash
jaxonomy_cli run --model path/to/model.json

🚀 Quick Start

A first simulation in a few lines — a custom block, built into a diagram, integrated through its ODE:

python
import jaxonomy as jximport jax.numpy as jnp
# Van der Pol oscillator as a custom blockclass VanDerPol(jx.LeafSystem):    def __init__(self, mu=1.0, **kwargs):        super().__init__(**kwargs)        self.declare_dynamic_parameter("mu", mu)        self.declare_continuous_state(            default_value=jnp.array([0.0, 2.0]), ode=self._ode        )        self.declare_continuous_state_output(name="x")
    def _ode(self, time, state, *inputs, **params):        x, mu = state.continuous_state, params["mu"]        return jnp.array([x[1],  mu * (1 - x[0]**2) * x[1] - x[0]])
builder = jx.DiagramBuilder()vdp = builder.add(VanDerPol(mu=2.0, name="vdp"))diagram = builder.build()
results = jx.simulate(    diagram, diagram.create_context(), (0.0, 20.0),    options=jx.SimulatorOptions(buffer_length=4000),  # room for adaptive steps    recorded_signals={"x": vdp.output_ports[0]},)# results.outputs["x"] → time-series of shape (T, 2)

📚 Documentation

  • Online docs & tutorials: py.jaxonomy.com
  • Local docs:
    bash
    pip install -r requirements.docs.txtmkdocs serve   # → http://127.0.0.1:8000
  • Example notebooks: docs/examples/
  • Scope notes: PINNs & PDE surrogates — classical PDE PINNs are out of scope; physics-informed dynamics learning (UDE / Neural DAE / Neural ODE / SINDy) is core.

🤖 Driving Jaxonomy from an AI agent (MCP)

Jaxonomy ships an MCP server that exposes the engine as tools an AI agent can call directly — it can enumerate library blocks, build and validate a model, run a simulation, fit parameters to data, and linearize a system, then reason over the actual results. This is worth wiring up if you drive Jaxonomy from an agent (Claude Desktop/Code, Cursor, …); if you're writing Python by hand, the pip install above is all you need and you can skip this.

bash
pip install jaxonomy[mcp]

Then register the server with your agent client. For Claude Desktop, add to claude_desktop_config.json:

json
{  "mcpServers": {    "jaxonomy": {      "command": "python",      "args": ["-m", "jaxonomy.mcp.server"]    }  }}

Use the interpreter where jaxonomy[mcp] is installed (or the jaxonomy-mcp entry point). The server is listed in the MCP Registry as io.github.machinavitalis/jaxonomy; full tool reference, client configuration and limitations are at py.jaxonomy.com/mcp.

If you'd rather just point an agent at the documentation, start it on SKILL.md — when to use Jaxonomy, when to reach for something else, the core API, and the pitfalls that most often break a first script. The docs site also publishes llms.txt views: py.jaxonomy.com/llms.txt for an index of every page, and py.jaxonomy.com/llms-full.txt for the whole documentation set as one Markdown file.


📖 Examples

1 · Hybrid Dynamics: The Bouncing Ball

Jaxonomy is designed for hybrid systems — models where continuous physics interacts with instantaneous discrete resets. The bouncing ball is the canonical example: free-fall ODE interrupted by a collision event that reverses velocity.

Governing equations

The dynamics between bounces follow:

$$ \dot{x} = v, \qquad \dot{v} = -g $$

When the ball hits the ground ($x = 0$, $v < 0$) a zero-crossing event fires and the state resets:

$$ x^+ = 0, \qquad v^+ = -e \cdot v \quad (e \in [0, 1] \text{ — coefficient of restitution}) $$

python
import jaxonomy as jximport jax.numpy as jnp
class BouncingBall(jx.LeafSystem):    def __init__(self, g=9.81, e=0.8, **kwargs):        super().__init__(**kwargs)        self.declare_dynamic_parameter("g", g)        self.declare_dynamic_parameter("e", e)        # [height, velocity]        self.declare_continuous_state(            default_value=jnp.array([5.0, 0.0]), ode=self._ode        )        self.declare_continuous_state_output(name="state")
        # Zero-crossing: fires as height crosses zero from above        self.declare_zero_crossing(            guard=self._hit_ground,            reset_map=self._bounce,            direction="positive_then_non_positive",        )
    def _ode(self, time, state, *inputs, **params):        v = state.continuous_state[1]        return jnp.array([v, -params["g"]])
    def _hit_ground(self, time, state, *inputs, **params):        return state.continuous_state[0]  # guard on height
    def _bounce(self, time, state, *inputs, **params):        x, v = state.continuous_state        new_state = jnp.array([0.0, -params["e"] * v])        return state.with_continuous_state(new_state)
builder = jx.DiagramBuilder()ball = builder.add(BouncingBall(g=9.81, e=0.85, name="ball"))diagram  = builder.build()results  = jx.simulate(    diagram, diagram.create_context(), (0.0, 8.0),    recorded_signals={"state": ball.output_ports[0]},)

Zero-crossing events are located with 40-step bisection on the solver's dense output polynomial — giving sub-microsecond temporal accuracy without user-specified tolerances.


2 · Optimal Control: LQR Pendulum

For a linearized pendulum with state $x = [\theta, \dot\theta]^\top$:

$$ \dot{x} = Ax + Bu, \qquad A = \begin{bmatrix} 0 & 1 \ g/L & 0 \end{bmatrix}, \quad B = \begin{bmatrix} 0 \ 1/mL^2 \end{bmatrix} $$

The Linear Quadratic Regulator minimizes infinite-horizon cost:

$$ J = \int_0^\infty \bigl( x^\top Q, x + u^\top R, u \bigr), dt $$

by solving the algebraic Riccati equation $A^\top P + PA - PBR^{-1}B^\top P + Q = 0$ for the optimal gain $K = R^{-1}B^\top P$, so $u^* = -Kx$.

python
import jaxonomy as jxfrom jaxonomy.library import LTISystem, LinearQuadraticRegulatorimport jax.numpy as jnp
g, L, m = 9.81, 1.0, 1.0A = jnp.array([[0, 1], [g/L, 0]])B = jnp.array([[0], [1 / (m * L**2)]])C, D = jnp.eye(2), jnp.zeros((2, 1))
Q = jnp.diag(jnp.array([10.0, 1.0]))  # penalise angle more than rateR = jnp.array([[0.1]])                 # control effort cost
builder    = jx.DiagramBuilder()plant      = builder.add(LTISystem(A, B, C, D, name="pendulum"))controller = builder.add(LinearQuadraticRegulator(A, B, Q, R, name="lqr"))
builder.connect(plant.output_ports[0],      controller.input_ports[0])builder.connect(controller.output_ports[0], plant.input_ports[0])
diagram = builder.build()context = diagram.create_context()
# Perturb the pendulum's initial angle by 15° (set one block's sub-state)context = context.with_subcontext(    plant.system_id,    context[plant.system_id].with_continuous_state(jnp.array([jnp.pi / 12, 0.0])),)
results = jx.simulate(    diagram, context, (0.0, 5.0),    recorded_signals={"x": plant.output_ports[0]},)

3 · Differentiable Parameter Identification

Jaxonomy can differentiate through complete simulations to fit model parameters to data — no finite-difference approximations, no hand-written adjoint code. Here we recover a spring–damper's stiffness and damping by differentiating the whole rollout and descending with Optax:

python
import jaximport jax.numpy as jnpimport optaximport jaxonomy as jx
class SpringDamper(jx.LeafSystem):    def __init__(self, k=1.0, c=0.3, **kwargs):        super().__init__(**kwargs)        self.declare_dynamic_parameter("k", k)        self.declare_dynamic_parameter("c", c)        self.declare_continuous_state(            default_value=jnp.array([1.0, 0.0]), ode=self._ode        )
    def _ode(self, time, state, *inputs, **params):        x, v = state.continuous_state        return jnp.array([v, -params["k"] * x - params["c"] * v])
sd   = SpringDamper(name="sd")opts = jx.SimulatorOptions(enable_autodiff=True, max_major_steps=200)
def final_state(theta):                       # theta = {"k": ..., "c": ...}    ctx = sd.create_context()    ctx.parameters["k"], ctx.parameters["c"] = theta["k"], theta["c"]    res = jx.simulate(sd, ctx, (0.0, 1.5), options=opts)    return res.context.continuous_state       # differentiable final [x, v]
target = jax.lax.stop_gradient(final_state({"k": 4.0, "c": 0.5}))  # "measured"loss   = lambda theta: jnp.sum((final_state(theta) - target) ** 2)
theta   = {"k": 1.0, "c": 0.1}opt     = optax.adam(2e-1)state   = opt.init(theta)grad_fn = jax.jit(jax.grad(loss))             # gradient through the ODE solverfor _ in range(300):    updates, state = opt.update(grad_fn(theta), state)    theta = optax.apply_updates(theta, updates)# theta → {"k": 4.00, "c": 0.50}

jax.grad(loss) flows back through every ODE step automatically, so the same recipe scales to battery ECMs (above), powertrains, or any parametric model — and jaxonomy.optimization wraps it in a higher-level Optimizable API when you want bounds, transforms, and constraints.


4 · Acausal Physical Modeling

Jaxonomy includes a Modelica-inspired acausal modeling layer for multi-domain physical systems. You describe component connections symbolically; the compiler automatically derives the governing DAE, reduces its index, and emits a LeafSystem ready to drop into any diagram.

RC circuit with initial conditions:

$$ C,\dot{V}C = I, \qquad V_C(0) = 0,\text{V}, \qquad V{\text{src}} = 1,\text{V} $$

python
import jaxonomy as jxfrom jaxonomy.acausal import AcausalCompiler, AcausalDiagram, EqnEnvfrom jaxonomy.acausal import electrical as elec
ev = EqnEnv()ad = AcausalDiagram()
vs  = elec.VoltageSource(ev, name="vs", v=1.0)r   = elec.Resistor(ev,      name="r",  R=1.0)c   = elec.Capacitor(ev,     name="c",  C=1.0,                              initial_voltage=0.0, initial_voltage_fixed=True)gnd = elec.Ground(ev,        name="gnd")
ad.connect(vs, "p", r,  "n")ad.connect(r,  "p", c,  "p")ad.connect(c,  "n", vs, "n")ad.connect(vs, "n", gnd, "p")
compiler = AcausalCompiler(ev, ad)rc_block = compiler()         # → LeafSystem, JIT-compiled ODE
builder = jx.DiagramBuilder()rc = builder.add(rc_block)diagram = builder.build()results = jx.simulate(    diagram,    diagram.create_context(),    (0.0, 5.0),    recorded_signals={"rc": rc.output_ports[0]},)
results.outputs["rc"]   # capacitor charges 0 → 0.993 V over 5 τ (R = C = 1)

The same pipeline handles multi-domain systems — an electro-mechanical actuator connecting electrical, rotational, and translational domains compiles to a single optimized system.

Available acausal domains: electrical · rotational · translational · thermal · fluid


5 · Differentiable Sensitivity & Batch Simulation

Because jax.grad, jax.jit, and jax.vmap all compose with simulate, you get powerful workflows with minimal boilerplate:

python
import jaximport jax.numpy as jnpimport jaxonomy as jx
class SpringMass(jx.LeafSystem):    def __init__(self, mass=1.0, damping=0.1, stiffness=10.0, **kwargs):        super().__init__(**kwargs)        self.declare_dynamic_parameter("mass", mass)        self.declare_dynamic_parameter("damping", damping)        self.declare_dynamic_parameter("stiffness", stiffness)        self.declare_continuous_state(            default_value=jnp.array([1.0, 0.0]), ode=self._ode        )        self.declare_continuous_state_output(name="x")
    def _ode(self, time, state, *inputs, **params):        x, v = state.continuous_state        a = -(params["stiffness"] * x + params["damping"] * v) / params["mass"]        return jnp.array([v, a])
# ── Sensitivity: ∂(final position)/∂(all parameters) in one reverse pass ─────plant = SpringMass(name="plant")grad_opts = jx.SimulatorOptions(enable_autodiff=True, max_major_steps=200)
def final_position(theta):    ctx = plant.create_context()    for name, value in theta.items():        ctx.parameters[name] = value    res = jx.simulate(plant, ctx, (0.0, 5.0), options=grad_opts)    return res.context.continuous_state[0]
grads = jax.grad(final_position)({"mass": 1.0, "damping": 0.1, "stiffness": 10.0})
# ── Monte Carlo ensemble: 1000 trajectories over a mass sweep (vmap) ─────────builder = jx.DiagramBuilder()plant_b = builder.add(SpringMass(name="plant"))diagram = builder.build()
results = jx.simulate_batch(    diagram, t_span=(0.0, 5.0),    param_batches={"plant.mass": jnp.linspace(0.5, 2.0, 1000)},    options=jx.SimulatorOptions(math_backend="jax", max_major_steps=200),    recorded_signals={"x": plant_b.output_ports[0]},)# results.outputs["x"] shape: (1000, T, 2)

🧩 Library Overview

Over 150 built-in blocks covering the full signal-processing and control toolkit. A representative slice — not exhaustive:

CategoryBlocks
SourcesConstant, Step, Ramp, Chirp, Pulse, Sawtooth, Clock, DataSource
StochasticRandomNumber, UniformRandomNumber, WhiteNoise, BandLimitedNoise, PRBS, RandomSource — all support with_key for independent noise streams under vmap
Arithmetic & nonlinearitiesAdder, Gain, Product, Abs, Power, Trigonometric, Saturate / SoftSaturate, DeadZone, RateLimiter / SoftRateLimiter, Quantizer, Backlash
Continuous dynamicsIntegrator, Derivative, TransferFunction, LTISystem, PID / PIDContinuous
Discrete dynamicsIntegratorDiscrete, UnitDelay, FilterDiscrete, LowPassDiscrete, LeadLag, Notch, PIDDiscrete, PIDController2DOF, Decimator, RateTransition
Routing, buses, matrixMux / Demux, BusCreator / BusSelector / BusUpdate (with BusUnit annotations), Slice, Stack, Switch / MultiPortSwitch, IfThenElse, MatrixMultiplication, MatrixInversion, DotProduct, CrossProduct
Logic & state machinesTruthTable, LogicalOperator, Comparator, Relay, EdgeDetection, StateMachine (authored via StateMachineBuilder DSL)
Lookup tablesLookupTable1d / LookupTable2d / LookupTableND, Prelookup / InterpolationUsingPrelookup, TableSearch — all differentiable and fittable from data via fit_lookup_table_*
Delays & containersTransportDelay, VariableTransportDelay, EnabledSubsystem, TriggeredSubsystem, ForEach, Conditional
ControlLinearQuadraticRegulator / DiscreteTimeLinearQuadraticRegulator / FiniteHorizonLinearQuadraticRegulator / LinearQuadraticGaussian, LinearDiscreteTimeMPC (native + LinearDiscreteTimeMPC_OSQP), DirectShootingNMPC / DirectTranscriptionNMPC / HermiteSimpsonNMPC
EstimationKalmanFilter, ExtendedKalmanFilter, UnscentedKalmanFilter, InfiniteHorizonKalmanFilter, RecursiveLeastSquares, AugmentedStateEKF, Luenberger
Physics & coordinatesCoordinateRotation, RigidBody, BatteryCell
ML / DataMLP (Equinox), Sindy, PyTorch, TensorFlow, ONNX / ONNXJax
ROM & surrogatesreduce(...) → ReducedOrderModel; linear MOR (balred / minreal / modal_truncation / residualize), galerkin_reduce + deim (POD–DEIM), dmd / dmdc / era, DMDForecaster / KoopmanPredictor, and surrogate blocks GaussianProcess / PolynomialChaos / RadialBasisSurrogate
InteropModelicaFMU / ModelicaFMUME (FMI 2.0 / 3.0 co-simulation and model-exchange import) + FMU export via build_fmu; MuJoCo / MJX; Ros2Publisher / Ros2Subscriber; QuanserHAL; PyTwin
CustomCustomPythonBlock, CustomJaxBlock for user-authored algorithms with persistent per-instance state

Custom blocks are first-class beyond the wrappers above: subclass LeafSystem, declare ports and states, and your block integrates with the full framework including JIT, autodiff, and event detection.


🏗️ System Architecture

A Jaxonomy model is a Diagram — a directed graph of interconnected blocks. Blocks (LeafSystem) declare ports, continuous/discrete states, and event guards. The simulator orchestrates ODE integration, discrete updates, and event detection automatically.

mermaid
graph LR    subgraph Diagram["DiagramBuilder.build()"]        direction LR        r[/"r(t)\nReference"/] --> sum(("Σ"))        sum -->|"e(t)"| ctrl["Controller\nLQR · MPC · PID"]        ctrl -->|"u(t)"| plant["Plant\nLTI · Nonlinear · Acausal"]        plant -->|"x(t)"| obs["State Estimator\nKalman · EKF · UKF"]        obs --> sum        plant -->|"y(t)"| out[/"y(t)\nOutput"/]    end
    style Diagram fill:#f5f8ff,stroke:#4a6fa5,stroke-width:2px    style ctrl fill:#dbeafe,stroke:#2563eb    style plant fill:#dcfce7,stroke:#16a34a    style obs fill:#fef9c3,stroke:#ca8a04

The JAX backend sits underneath every simulation, giving you a clean Python API backed by XLA compilation:

mermaid
graph TD    A["Python API\nDiagram · LeafSystem · simulate()"] --> B["JAX Backend\nJIT · vmap · grad"]    B --> C1["Dopri5\nAdaptive RK45\nnon-stiff ODEs"]    B --> C2["BDF\nImplicit solver\nstiff systems"]    B --> C3["Event Handler\nZero-crossing\nbisection"]
    style A fill:#e0f2fe,stroke:#0284c7    style B fill:#fdf4ff,stroke:#9333ea    style C1 fill:#f0fdf4,stroke:#16a34a    style C2 fill:#f0fdf4,stroke:#16a34a    style C3 fill:#f0fdf4,stroke:#16a34a

The Jaxonomy stack

Jaxonomy is the engine at the base of a three-package stack. Each package is its own repository, MIT-licensed, and depends only on the package(s) above it:

  • Jaxonomy — this package. The general-purpose, JAX-native simulation engine for hybrid dynamical systems. Not robotics-specific; depends on nothing else in the stack.
  • Jaxterity — the robotics layer built on top of Jaxonomy: URDF/MJCF import, MJX-backed articulated dynamics, calibrated actuators/sensors, system identification, and whole-body control. Imports Jaxonomy; never re-implements its primitives.
  • Jaxility — the deployment artifact factory: compiles a calibrated robot to embedded C for Arm SoCs (Cortex-A / Cortex-M) with a signed attestation manifest. Consumes Jaxterity.

The boundary rule: anything useful to controls engineers outside robotics (HVAC, battery, aerospace, energy) belongs in Jaxonomy; anything specific to joints, actuators, contacts, and kinematic chains belongs in Jaxterity; embedded codegen, targets, and attestation belong in Jaxility.

What Jaxonomy does not yet do (or does only partially) is tracked in KNOWN_GAPS.md — the public inverse of the internal evidence ledger in CLAIMS.md.

License

Released under the MIT License from version 2.2.0 onward.

Derived from the MIT-licensed open-source package pycollimator by Collimator, Inc.

Source: README.md at commit f615a73

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

1
  1. v3.4.1LatestSep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts