Skip to content

Home

Scaly is a modelling and code-generation library for optimal control. You describe dynamics, costs and constraints once, and use the same description from prototyping in Python to deployment using generated C code.

Early release

Scaly is still in development and the public API can still change between minor versions. See versioning policy for more details.

import numpy as np
import scaly as sc

N = 20  # the decision vector w stacks N + 1 states of size 2, then N controls

@sc.function(sc.G(sc.L("z", 2), sc.L("u", 1), sc.L("znext", 2)), sc.L("defect", ...))
def defect(inputs):
    z, u, znext = inputs
    return z + 0.1 * sc.concat([z[1:], u]) - znext

@sc.problem(vars=sc.L("w", 3 * N + 2), params=sc.L("z0", 2))
def multiple_shooting(w, z0):
    zs, us = w[: 2 * N + 2], w[2 * N + 2 :]
    defects = sc.vmap(defect, N, {"z": zs[:-2], "u": us, "znext": zs[2:]})  # one loop, not N copies
    return sc.ProblemSpec(minimize=sc.sumsqr(zs) + 0.1 * sc.sumsqr(us), eq=(zs[:2] - z0, defects))

solve = sc.solver(multiple_shooting, "ipopt")
w_opt, *_ = solve(np.array([1.0, 0.0]))

Behind the scenes, scaly traces the costs, constraints and their derivatives, generates and compiles on the fly C code to call them within the solver. You can also generate the same C code in a specific directory so you can embed it into an external application, either from Python:

from pathlib import Path
from scaly.codegen import write_module

write_module(solve, Path("generated/"))  # generated/multiple_shooting_ipopt.h and .c

or from the command line, naming the module and the function in it:

uv run scaly_codegen mymodule:solve -o generated/

Where to start

Acknowledgements

Scaly is developed by:

  • Tudor A. Oancea (main developer)
  • Colin N. Jones (methods and math)

All contributors are part of the Predictive control lab from EPFL. This project is funded by the Swiss National Science Foundation through the NCCR Automation (grant agreement 51NF40_180545).