aligator  0.9.0
A primal-dual augmented Lagrangian-type solver for nonlinear trajectory optimization.
Loading...
Searching...
No Matches
Trajectory optimization problems

Trajectory optimization

The objective of this library is to model and solve optimal control problems (OCPs) of the form

\begin{align} \min_{x,u}~& \int_0^T \ell(x, u)\, dt + \ell_\mathrm{f}(x(T)) \\ \subjectto & \dot x (t) = f(x(t), u(t)) \\ & g(x(t), u(t)) = 0 \\ & h(x(t), u(t)) \leq 0 \end{align}

Transcription

A transcription translates the continuous-time OCP to a discrete-time, finite-dimensional nonlinear program. Aligator allows us to consider transcriptions with implicit discrete dynamics: \begin{aligned} \min_{\bmx,\bmu}~& J(\bmx, \bmu) = \sum_{i=0}^{N-1} \ell_i(x_i, u_i) + \ell_N(x_N) \\ \subjectto & f(x_i, u_i, x_{i+1}) = 0 \\ & g(x_i, u_i) = 0 \\ & h(x_i, u_i) \leq 0 \end{aligned}

In aligator, trajectory optimization problems are described using the class TrajOptProblemTpl. Each TrajOptProblemTpl is described by a succession of stages (StageModelTpl) which encompass the set of constraints and the cost function (class CostAbstractTpl) for this stage.

Additionally, a TrajOptProblemTpl must provide an initial condition \( x_0 = \bar{x} \), a terminal cost $$ \ell_{\mathrm{f}}(x_N) $$ on the terminal state \(x_N \); optionally, a terminal constraint \(g(x_N) = 0, h(x_N) \leq 0 \) on this state may be added.

Stage models

A stage model (StageModelTpl) describes a node in the discrete-time optimal control problem: it consists in a running cost function, and a vector of constraints (StageConstraintTpl), the first of which must describe system dynamics (through a DynamicsModelTpl).

Example

Define and solve an LQR (Python API):

1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# SPDX-License-Identifier: BSD-2-Clause
5# Copyright 2023 Inria
6
7"""Formulating and solving a linear quadratic regulator with Aligator."""
8
9import matplotlib.pyplot as plt
10import numpy as np
11import tap
12
13import aligator
14from aligator import constraints, dynamics, manifolds
15from aligator.utils.plotting import plot_convergence
16
17
18class Args(tap.Tap):
19 term_cstr: bool = False
20 bounds: bool = False
21
22
23args = Args().parse_args()
24np.random.seed(42)
25
26nx = 3 # dimension of the state manifold
27nu = 3 # dimension of the input
28space = manifolds.VectorSpace(nx)
29x0 = space.neutral() + (0.2, 0.3, -0.1)
30
31# Linear discrete dynamics: x[t+1] = A x[t] + B u[t] + c
32A = np.eye(nx)
33A[0, 1] = -0.2
34A[1, 0] = 0.2
35B = np.eye(nx)[:, :nu]
36B[2, :] = 0.4
37c = np.zeros(nx)
38c[:] = (0.0, 0.0, 0.1)
39
40# Quadratic cost: ½ x^T Q x + ½ u^T R u + x^T N u
41Q = 1e-2 * np.eye(nx)
42R = 1e-2 * np.eye(nu)
43N = 1e-5 * np.eye(nx, nu)
44
45Qf = np.eye(nx)
46if args.term_cstr: # <-- TODO: should it be `not term_cstr`?
47 Qf[:, :] = 0.0
48
49
50# These matrices define the costs and constraints that apply at each stage
51# (a.k.a. node) of our trajectory optimization problem
52rcost0 = aligator.QuadraticCost(Q, R, N)
53term_cost = aligator.QuadraticCost(Qf, R)
54dynmodel = dynamics.LinearDiscreteDynamics(A, B, c)
55stage = aligator.StageModel(rcost0, dynmodel)
56if args.bounds:
57 u_min = -0.18 * np.ones(nu)
58 u_max = +0.18 * np.ones(nu)
59 ctrl_fn = aligator.ControlErrorResidual(nx, np.zeros(nu))
60 stage.addConstraint(ctrl_fn, constraints.BoxConstraint(u_min, u_max))
61
62
63# Build our problem by appending stages and the optional terminal constraint
64nsteps = 20
65problem = aligator.TrajOptProblem(x0, nu, space, term_cost)
66
67for i in range(nsteps):
68 problem.addStage(stage)
69
70xtar2 = 0.1 * np.ones(nx)
71if args.term_cstr:
72 term_fun = aligator.StateErrorResidual(space, nu, xtar2)
73 problem.addTerminalConstraint(term_fun, constraints.EqualityConstraintSet())
74
75# Instantiate a solver separately
76mu_init = 1e-1 if args.bounds else 1e-4
77verbose = aligator.VerboseLevel.VERBOSE
78tol = 1e-8
79solver = aligator.SolverProxDDP(tol, mu_init, verbose=verbose)
80
81his_cb = aligator.HistoryCallback()
82solver.registerCallback("his", his_cb)
83print("Registered callbacks:", solver.getCallbackNames().tolist())
84solver.max_iters = 20
85solver.rollout_type = aligator.ROLLOUT_LINEAR
86
87u0 = np.zeros(nu)
88us_i = [u0] * nsteps
89xs_i = aligator.rollout(dynmodel, x0, us_i)
90prob_data = aligator.TrajOptData(problem)
91problem.evaluate(xs_i, us_i, prob_data)
92
93solver.setup(problem)
94solver.run(problem, xs_i, us_i)
95res = solver.results
96ws = solver.workspace
97print(res)
98
99plt.subplot(121)
100fig1: plt.Figure = plt.gcf()
101
102lstyle = {"lw": 0.9, "marker": ".", "markersize": 5}
103trange = np.arange(nsteps + 1)
104plt.plot(res.xs, ls="-", **lstyle)
105
106if args.term_cstr:
107 plt.hlines(
108 xtar2,
109 *trange[[0, -1]],
110 ls="-",
111 lw=1.0,
112 colors="k",
113 alpha=0.4,
114 label=r"$x_\mathrm{tar}$",
115 )
116plt.hlines(
117 0.0,
118 *trange[[0, -1]],
119 ls=":",
120 lw=0.6,
121 colors="k",
122 alpha=0.4,
123 label=r"$x=0$",
124)
125plt.title("State trajectory $x(t)$")
126plt.xlabel("Time $i$")
127plt.legend(frameon=False)
128
129plt.subplot(122)
130plt.plot(res.us, **lstyle)
131if args.bounds:
132 plt.hlines(
133 np.concatenate([u_min, u_max]),
134 *trange[[0, -1]],
135 ls="-",
136 colors="tab:red",
137 lw=1.8,
138 alpha=0.4,
139 label=r"$\bar{u}$",
140 )
141plt.xlabel("Time $i$")
142plt.title("Controls $u(t)$")
143plt.legend(frameon=False, loc="lower right")
144plt.tight_layout()
145
146
147fig2: plt.Figure = plt.figure()
148ax: plt.Axes = fig2.add_subplot()
149niter = res.num_iters
150ax.hlines(
151 tol,
152 0,
153 niter,
154 colors="k",
155 linestyles="-",
156 linewidth=2.0,
157)
158plot_convergence(his_cb, ax, res)
159ax.set_title("Convergence (constrained LQR)")
160ax.legend(
161 [
162 "Tolerance $\\epsilon_\\mathrm{tol}$",
163 "Primal error $p$",
164 "Dual error $d$",
165 ]
166)
167fig2.tight_layout()
168
169plt.show()
math_types< Scalar >::VectorOfVectors rollout(const std::vector< xyz::polymorphic< DynamicsModelTpl< Scalar > > > &dyn_models, const typename math_types< Scalar >::VectorXs &x0, const typename math_types< Scalar >::VectorOfVectors &us, typename math_types< Scalar >::VectorOfVectors &xout)
Perform a rollout of the supplied dynamical models.
Definition rollout.hpp:9