aligator  0.6.1
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(
74 aligator.StageConstraint(term_fun, constraints.EqualityConstraintSet())
75 )
76
77# Instantiate a solver separately
78mu_init = 1e-3 if args.bounds else 1e-6
79rho_init = 0.0
80verbose = aligator.VerboseLevel.VERBOSE
81tol = 1e-8
82solver = aligator.SolverProxDDP(tol, mu_init, rho_init, verbose=verbose)
83
84his_cb = aligator.HistoryCallback()
85solver.registerCallback("his", his_cb)
86solver.max_iters = 20
87solver.rollout_type = aligator.ROLLOUT_LINEAR
88
89u0 = np.zeros(nu)
90us_i = [u0] * nsteps
91xs_i = aligator.rollout(dynmodel, x0, us_i)
92prob_data = aligator.TrajOptData(problem)
93problem.evaluate(xs_i, us_i, prob_data)
94
95solver.setup(problem)
96solver.run(problem, xs_i, us_i)
97res = solver.results
98ws = solver.workspace
99print(res)
100
101plt.subplot(121)
102fig1: plt.Figure = plt.gcf()
103
104lstyle = {"lw": 0.9, "marker": ".", "markersize": 5}
105trange = np.arange(nsteps + 1)
106plt.plot(res.xs, ls="-", **lstyle)
107
108if args.term_cstr:
109 plt.hlines(
110 xtar2,
111 *trange[[0, -1]],
112 ls="-",
113 lw=1.0,
114 colors="k",
115 alpha=0.4,
116 label=r"$x_\mathrm{tar}$",
117 )
118plt.hlines(
119 0.0,
120 *trange[[0, -1]],
121 ls=":",
122 lw=0.6,
123 colors="k",
124 alpha=0.4,
125 label=r"$x=0$",
126)
127plt.title("State trajectory $x(t)$")
128plt.xlabel("Time $i$")
129plt.legend(frameon=False)
130
131plt.subplot(122)
132plt.plot(res.us, **lstyle)
133if args.bounds:
134 plt.hlines(
135 np.concatenate([u_min, u_max]),
136 *trange[[0, -1]],
137 ls="-",
138 colors="tab:red",
139 lw=1.8,
140 alpha=0.4,
141 label=r"$\bar{u}$",
142 )
143plt.xlabel("Time $i$")
144plt.title("Controls $u(t)$")
145plt.legend(frameon=False, loc="lower right")
146plt.tight_layout()
147
148
149fig2: plt.Figure = plt.figure()
150ax: plt.Axes = fig2.add_subplot()
151niter = res.num_iters
152ax.hlines(
153 tol,
154 0,
155 niter,
156 colors="k",
157 linestyles="-",
158 linewidth=2.0,
159)
160plot_convergence(his_cb, ax, res)
161ax.set_title("Convergence (constrained LQR)")
162ax.legend(
163 [
164 "Tolerance $\\epsilon_\\mathrm{tol}$",
165 "Primal error $p$",
166 "Dual error $d$",
167 ]
168)
169fig2.tight_layout()
170
171plt.show()
math_types< Scalar >::VectorOfVectors rollout(const std::vector< shared_ptr< 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:10