aligator 0.18.0
A versatile and efficient C++ library for real-time constrained trajectory optimization.
Loading...
Searching...
No Matches
dense-kernel.hpp
Go to the documentation of this file.
1
3#pragma once
4
8#include "lqr-problem.hpp"
9
10namespace aligator::gar {
11
13template <typename _Scalar> struct DenseKernel {
14 using Scalar = _Scalar;
17
18 struct Data {
22
28
29 Data(uint nx, uint nu, uint nc, uint nx2, uint nth)
30 : kktMat({nu, nc, nx2, nx2}, {nu, nc, nx2, nx2})
31 , fb({nu, nc, nx2, nx2}, {nx})
32 , ft({nu, nc, nx2, nx2}, {nth})
33 , ff({nu, nc, nx2, nx2})
34 , ldl{nu + nc + 2 * nx2} {
35 setZero();
36 }
37
38 void setZero() {
39 kktMat.setZero();
40 fb.setZero();
41 ft.setZero();
42 ff.setZero();
43 }
44 };
45
46 // simple struct, can be copied
47 struct value {
48 MatrixRef Pxx;
49 MatrixRef Pxt;
50 MatrixRef Ptt;
51 VectorRef px;
52 VectorRef pt;
53 };
54
55 inline static void terminalSolve(const KnotType &knot, Data &d, value v,
56 Scalar mueq) {
57 d.kktMat.setZero();
58
59 // assemble last-stage kkt matrix - includes input 'u'
60 d.kktMat(0, 0) = knot.R;
61 d.kktMat(0, 1) = knot.D.transpose();
62 d.kktMat(1, 0) = knot.D;
63 d.kktMat(1, 1).diagonal().array() = -mueq;
64
65 VectorRef kff = d.ff[0] = -knot.r;
66 VectorRef zff = d.ff[1] = -knot.d;
67 RowMatrixRef K = d.fb.blockRow(0) = -knot.S.transpose();
68 RowMatrixRef Z = d.fb.blockRow(1) = -knot.C;
69
70 d.ldl.compute(d.kktMat.matrix());
71 d.ldl.solveInPlace(d.ff.matrix());
72 d.ldl.solveInPlace(d.fb.matrix());
73
74 RowMatrixRef Kth = d.ft.blockRow(0) = -knot.Gu;
75 RowMatrixRef Zth = d.ft.blockRow(1) = -knot.Gv;
76 d.ldl.solveInPlace(d.ft.matrix());
77
78 Eigen::Transpose Ct = knot.C.transpose();
79
80 v.Pxx.noalias() = knot.Q + knot.S * K;
81 v.Pxx.noalias() += Ct * Z;
82
83 v.Pxt.noalias() = knot.Gx + K.transpose() * knot.Gu;
84 v.Pxt.noalias() += Z.transpose() * knot.Gv;
85
86 v.Ptt.noalias() = knot.Gth + knot.Gu.transpose() * Kth;
87 v.Ptt.noalias() += knot.Gv.transpose() * Zth;
88
89 v.px.noalias() = knot.q + knot.S * kff;
90 v.px.noalias() += Ct * zff;
91
92 v.pt.noalias() = knot.gamma + knot.Gu.transpose() * kff;
93 v.pt.noalias() += knot.Gv.transpose() * zff;
94 }
95
96 inline static void stageKernelSolve(const KnotType &knot, Data &d, value v,
97 const value *vn, Scalar mueq) {
98 d.kktMat.setZero();
99 d.kktMat(0, 0) = knot.R;
100 d.kktMat(1, 0) = knot.D;
101 d.kktMat(0, 1) = knot.D.transpose();
102 d.kktMat(1, 1).diagonal().setConstant(-mueq);
103
104 d.kktMat(2, 0) = knot.B;
105 d.kktMat(0, 2) = knot.B.transpose();
106 // d.kktMat(2, 2).setZero();
107 d.kktMat(2, 3).setIdentity() *= -1;
108 d.kktMat(3, 2).setIdentity() *= -1;
109 if (vn)
110 d.kktMat(3, 3) = vn->Pxx;
111
112 // 1. factorize
113 d.ldl.compute(d.kktMat.matrix());
114
115 // 2. rhs
116 // feedforward
117 VectorRef kff = d.ff[0] = -knot.r;
118 VectorRef zff = d.ff[1] = -knot.d;
119 VectorRef lff = d.ff[2] = -knot.f;
120 VectorRef yff = d.ff[3];
121 if (vn)
122 yff = -vn->px;
123
124 // feedback
125 RowMatrixRef K = d.fb.blockRow(0) = -knot.S.transpose();
126 RowMatrixRef Z = d.fb.blockRow(1) = -knot.C;
127 RowMatrixRef L = d.fb.blockRow(2) = -knot.A;
128 RowMatrixRef Y = d.fb.blockRow(3).setZero();
129
130 // parametric
131 RowMatrixRef Kth = d.ft.blockRow(0) = -knot.Gu;
132 RowMatrixRef Zth = d.ft.blockRow(1) = -knot.Gv;
133 d.ft.blockRow(2).setZero();
134 RowMatrixRef Yth = d.ft.blockRow(3);
135 if (vn)
136 Yth = -vn->Pxt;
137
138 d.ldl.solveInPlace(d.ff.matrix());
139 d.ldl.solveInPlace(d.fb.matrix());
140 d.ldl.solveInPlace(d.ft.matrix());
141
142 // 3. update value function
143 Eigen::Transpose At = knot.A.transpose();
144 Eigen::Transpose Ct = knot.C.transpose();
145
146 v.Pxx.noalias() = knot.Q + knot.S * K;
147 v.Pxx.noalias() += Ct * Z;
148 v.Pxx.noalias() += At * L;
149
150 v.Pxt = knot.Gx;
151 v.Pxt.noalias() += K.transpose() * knot.Gu;
152 v.Pxt.noalias() += Z.transpose() * knot.Gv;
153 if (vn)
154 v.Pxt.noalias() += Y.transpose() * vn->Pxt;
155
156 v.Ptt = knot.Gth;
157 v.Ptt.noalias() += Kth.transpose() * knot.Gu;
158 v.Ptt.noalias() += Zth.transpose() * knot.Gv;
159 if (vn)
160 v.Ptt.noalias() += Yth.transpose() * vn->Pxt;
161
162 v.px.noalias() = knot.q + knot.S * kff;
163 v.px.noalias() += Ct * zff;
164 v.px.noalias() += At * lff;
165
166 v.pt.noalias() = knot.gamma + knot.Gu.transpose() * kff;
167 v.pt.noalias() += knot.Gv.transpose() * zff;
168 if (vn)
169 v.pt.noalias() += vn->Pxt.transpose() * yff;
170 }
171
172 static bool forwardStep(size_t i, bool isTerminal, const KnotType &knot,
173 const Data &d, boost::span<VectorXs> xs,
174 boost::span<VectorXs> us, boost::span<VectorXs> vs,
175 boost::span<VectorXs> lbdas,
176 const std::optional<ConstVectorRef> &theta_) {
177 ConstVectorRef kff = d.ff[0];
178 ConstVectorRef zff = d.ff[1];
179 ConstVectorRef lff = d.ff[2];
180 ConstVectorRef yff = d.ff[3];
181
182 ConstRowMatrixRef K = d.fb.blockRow(0);
183 ConstRowMatrixRef Z = d.fb.blockRow(1);
184 ConstRowMatrixRef L = d.fb.blockRow(2);
185 ConstRowMatrixRef Y = d.fb.blockRow(3);
186
187 ConstRowMatrixRef Kth = d.ft.blockRow(0);
188 ConstRowMatrixRef Zth = d.ft.blockRow(1);
189 ConstRowMatrixRef Lth = d.ft.blockRow(2);
190 ConstRowMatrixRef Yth = d.ft.blockRow(3);
191
192 if (knot.nu > 0)
193 us[i].noalias() = kff + K * xs[i];
194 vs[i].noalias() = zff + Z * xs[i];
195 if (theta_.has_value()) {
196 if (knot.nu > 0)
197 us[i].noalias() += Kth * theta_.value();
198 vs[i].noalias() += Zth * theta_.value();
199 }
200
201 if (isTerminal)
202 return true;
203 lbdas[i + 1].noalias() = lff + L * xs[i];
204 xs[i + 1].noalias() = yff + Y * xs[i];
205 if (theta_.has_value()) {
206 lbdas[i + 1].noalias() += Lth * theta_.value();
207 xs[i + 1].noalias() += Yth * theta_.value();
208 }
209 return true;
210 }
211};
212
213#ifdef ALIGATOR_ENABLE_TEMPLATE_INSTANTIATION
214extern template struct DenseKernel<context::Scalar>;
215#endif
216} // namespace aligator::gar
Block matrix class, with a fixed or dynamic-size number of row and column blocks.
auto blockRow(size_t i)
MatrixType & matrix()
unsigned int uint
Definition logger.hpp:11
BlkMatrix< VectorXs, 4, 1 > BlkVec4
BlkMatrix< MatrixXs, 4, 4 > BlkMat44
BlkMatrix< RowMatrixXs, 4, 1 > BlkRowMat41
Data(uint nx, uint nu, uint nc, uint nx2, uint nth)
BunchKaufman< MatrixXs > ldl
A dense Bunch-Kaufman based kernel.
static bool forwardStep(size_t i, bool isTerminal, const KnotType &knot, const Data &d, boost::span< VectorXs > xs, boost::span< VectorXs > us, boost::span< VectorXs > vs, boost::span< VectorXs > lbdas, const std::optional< ConstVectorRef > &theta_)
LqrKnotTpl< Scalar > KnotType
static void terminalSolve(const KnotType &knot, Data &d, value v, Scalar mueq)
ALIGATOR_DYNAMIC_TYPEDEFS_WITH_ROW_TYPES(Scalar)
static void stageKernelSolve(const KnotType &knot, Data &d, value v, const value *vn, Scalar mueq)
Struct describing a stage of a constrained LQ problem.
ArenaMatrix< MatrixXs > Gv
ArenaMatrix< MatrixXs > A
ArenaMatrix< MatrixXs > D
ArenaMatrix< MatrixXs > Q
ArenaMatrix< VectorXs > q
ArenaMatrix< MatrixXs > Gx
ArenaMatrix< MatrixXs > Gth
ArenaMatrix< MatrixXs > B
ArenaMatrix< MatrixXs > R
ArenaMatrix< MatrixXs > S
ArenaMatrix< VectorXs > d
ArenaMatrix< VectorXs > gamma
ArenaMatrix< MatrixXs > Gu
ArenaMatrix< MatrixXs > C
ArenaMatrix< VectorXs > r
ArenaMatrix< VectorXs > f