Skip to content

Commit 3f247bc

Browse files
added names, changed logo, fixed math
1 parent 4d3b760 commit 3f247bc

File tree

8 files changed

+153
-61
lines changed

8 files changed

+153
-61
lines changed

docs/index.md

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ description: TinyMPC description and overview
66
# Welcome to TinyMPC's documentation!
77

88
<p align="center">
9-
<img width="50%" src="media/lightmode-banner.png#only-light" />
10-
<img width="50%" src="media/darkmode-banner.png#only-dark" />
9+
<img width="50%" src="media/tinympc-light-logo.png#only-light" />
10+
<img width="50%" src="media/tinympc-dark-logo.png#only-dark" />
1111
</p>
1212

1313
<p align="center" markdown>
1414
[Get Started :material-arrow-right-box:](get-started/installation.md){.md-button}
1515
</p>
1616

17-
TinyMPC is an open-source solver tailored for convex model-predictive control that delivers high speed computation with a small memory footprint. Implemented in C++ with minimal dependencies, TinyMPC is particularly suited for embedded control and robotics applications on resource-constrained platforms. TinyMPC can handle state and input bounds and second-order cone constraints. A Python interface is available to aid in generating code for embedded systems.
17+
TinyMPC is an open-source solver tailored for convex model-predictive control that delivers high speed computation with a small memory footprint. Implemented in C++ with minimal dependencies, TinyMPC is particularly suited for embedded control and robotics applications on resource-constrained platforms. TinyMPC can handle state and input bounds and second-order cone constraints. [Python](https://github.com/TinyMPC/tinympc-python), [MATLAB](https://github.com/TinyMPC/tinympc-matlab), and [Julia](https://github.com/TinyMPC/tinympc-julia) interfaces are available to aid in generating code for embedded systems.
1818

1919
!!! success ""
2020

@@ -75,11 +75,11 @@ TinyMPC outperforms state-of-the-art solvers in terms of speed and memory footpr
7575
</figure>
7676

7777
<figure markdown="span">
78-
![CDC24 MCU benchmarks](media/cdc_bench.png){ width=60% align=left}
78+
![ICRA26 benchmarks](media/icra_2026_benchmarks.png){ width=60% align=left}
7979
<div style="text-align: left;">
8080
<br>
8181
<br>
82-
TinyMPC is also capable of handling conic constraints. In (b), we benchmarked TinyMPC against two existing conic solvers with embedded support, [SCS](https://www.cvxgrp.org/scs/){:target="_blank"} and [ECOS](https://web.stanford.edu/~boyd/papers/ecos.html){:target="_blank"}, on the rocket soft-landing problem. TinyMPC achieves an average speed-up of 13x over SCS and 137x over ECOS.
82+
TinyMPC is also capable of handling conic constraints. Conic-TinyMPC outperforms [SCS](https://www.cvxgrp.org/scs/){:target="_blank"} and [ECOS](https://web.stanford.edu/~boyd/papers/ecos.html){:target="_blank"} in execution time and memory, achieving an average speed-up of 13.8x over SCS and 142.7x over ECOS.
8383
<!-- #gain, because of its lack of generality, TinyMPC is orders of magnitudes faster than SCS and ECOS. -->
8484
</div>
8585
</figure>
@@ -98,76 +98,79 @@ TinyMPC outperforms state-of-the-art solvers in terms of speed and memory footpr
9898

9999
## Made by
100100

101+
<!-- First row: Khai, Sam, Ishaan -->
101102
<div style="display: flex;">
102103
<div style="flex: 1;">
103104
<p align="center">
104-
<a href="https://www.linkedin.com/in/anoushka-alavilli-89586b178/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/anoushka_alavilli.jpg" /></a>
105+
<a href="https://xkhainguyen.github.io/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/khai_nguyen.jpg" /></a>
105106
</p>
106107
<h4 align="center">
107-
Anoushka Alavilli
108+
Khai Nguyen
108109
</h4>
109-
<!-- <h6 align="center">
110-
Main developer
111-
</h6> -->
112110
</div>
113111
<div style="flex: 1;">
114112
<p align="center">
115-
<a href="https://xkhainguyen.github.io/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/khai_nguyen.jpg" /></a>
113+
<a href="https://samschoedel.com/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/sam_schoedel.jpg" /></a>
116114
</p>
117115
<h4 align="center">
118-
Khai Nguyen
116+
Sam Schoedel
119117
</h4>
120-
<!-- <h6 align="center">
121-
Main developer
122-
</h6> -->
123118
</div>
124119
<div style="flex: 1;">
125120
<p align="center">
126-
<a href="https://samschoedel.com/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/sam_schoedel.jpg" /></a>
121+
<a href="https://ishaanmahajan.com/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/ishaan_mahajan.jpg" /></a>
127122
</p>
128123
<h4 align="center">
129-
Sam Schoedel
124+
Ishaan Mahajan
130125
</h4>
131-
<!-- <h6 align="center">
132-
Main developer
133-
</h6> -->
134126
</div>
135127
</div>
136128

137-
129+
<!-- Second row: Anoushka, Elakhya, Moises -->
138130
<div style="display: flex;">
131+
<div style="flex: 1;">
132+
<p align="center">
133+
<a href="https://www.linkedin.com/in/anoushka-alavilli-89586b178/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/anoushka_alavilli.jpg" /></a>
134+
</p>
135+
<h4 align="center">
136+
Anoushka Alavilli
137+
</h4>
138+
</div>
139139
<div style="flex: 1;">
140140
<p align="center">
141141
<a href="https://www.linkedin.com/in/elakhya-nedumaran/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/elakhya_nedumaran.png" /></a>
142142
</p>
143143
<h4 align="center">
144144
Elakhya Nedumaran
145145
</h4>
146-
<!-- <h6 align="center">
147-
Code generation and interfaces
148-
</h6> -->
149146
</div>
150147
<div style="flex: 1;">
148+
<p align="center">
149+
<a href="https://www.linkedin.com/in/moises-mata-cu/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/moises_mata.jpg" /></a>
150+
</p>
151+
<h4 align="center">
152+
Moises Mata
153+
</h4>
154+
</div>
155+
</div>
156+
157+
<!-- Third row: Brian and Zac (centered with proper sizing) -->
158+
<div style="display: flex; justify-content: center;">
159+
<div style="flex: 0 0 33.33%; max-width: 33.33%;">
151160
<p align="center">
152161
<a href="https://brianplancher.com/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/brian_plancher.jpg" /></a>
153162
</p>
154163
<h4 align="center">
155164
Prof. Brian Plancher
156165
</h4>
157-
<!-- <h6 align="center">
158-
Math and advice
159-
</h6> -->
160166
</div>
161-
<div style="flex: 1;">
167+
<div style="flex: 0 0 33.33%; max-width: 33.33%;">
162168
<p align="center">
163169
<a href="https://www.linkedin.com/in/zacmanchester/" target="_blank"><img style="border-radius: 0%;" width="60%" src="media/contributors/zac_manchester.jpg" /></a>
164170
</p>
165171
<h4 align="center">
166172
Prof. Zac Manchester
167173
</h4>
168-
<!-- <h6 align="center">
169-
Math and advice
170-
</h6> -->
171174
</div>
172175
</div>
173176

@@ -192,4 +195,13 @@ TinyMPC outperforms state-of-the-art solvers in terms of speed and memory footpr
192195
eprint={2403.18149},
193196
archivePrefix={arXiv},
194197
}
198+
```
199+
200+
```latex
201+
@article{mahajan2025robust,
202+
title={Robust and Efficient Embedded Convex Optimization through First-Order Adaptive Caching},
203+
author={Mahajan, Ishaan and Plancher, Brian},
204+
journal={arXiv preprint arXiv:2507.03231},
205+
year={2025}
206+
}
195207
```
3.71 MB
Loading
31.3 KB
Loading
243 KB
Loading

docs/media/tinympc-dark-logo.png

96.3 KB
Loading

docs/media/tinympc-light-logo.png

61.2 KB
Loading

docs/solver/background.md

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ The alternating direction method of multipliers algorithm was developed in the 1
1515
We want to solve optimization problems in which our cost function $f$ and set of valid states $\mathcal{C}$ are both convex:
1616

1717
$$
18-
\begin{alignat}{2}
19-
\min_x & \quad f(x) \\
20-
\text{subject to} & \quad x \in \mathcal{C}.
21-
\end{alignat}
18+
\begin{aligned}
19+
\min_x \quad & f(x) \\
20+
\text{subject to} \quad & x \in \mathcal{C}
21+
\end{aligned}
2222
$$
2323

2424
We define an indicator function for the set $\mathcal{C}$:
@@ -68,26 +68,25 @@ $$
6868
Our optimization problem has now been divided into two variables: the primal $x$ and slack $z$, and we can optimize over each one individually while holding all of the other variables constant. To get the ADMM algorithm, all we have to do is alternate between solving for the $x$ and then for the $z$ that minimizes our augmented Lagrangian. After each set of solves, we then update our dual variable $\lambda$ based on how much $x$ differs from $z$.
6969

7070
$$
71-
\begin{alignat}{3}
72-
\text{primal update: } & x^+ & ={} & \underset{x}{\arg \min} \hspace{2pt} \mathcal{L}_A(x,z,\lambda), \\
73-
\text{slack update: } & z^+ & ={} & \underset{z}{\arg \min} \hspace{2pt} \mathcal{L}_A(x^+,z,\lambda), \\
74-
\text{dual update: } & \lambda^+ & ={} & \lambda + \rho(x^+ - z^+),
75-
\end{alignat}
71+
\begin{aligned}
72+
\text{primal update: } x^+ &= \underset{x}{\arg \min} \, \mathcal{L}_A(x,z,\lambda), \\
73+
\text{slack update: } z^+ &= \underset{z}{\arg \min} \, \mathcal{L}_A(x^+,z,\lambda), \\
74+
\text{dual update: } \lambda^+ &= \lambda + \rho(x^+ - z^+)
75+
\end{aligned}
7676
$$
7777

7878
where $x^+$, $z^+$, and $\lambda^+$ refer to the primal, slack, and dual variables to be used in the next iteration.
7979

8080
Now all we have to do is solve a few unconstrained optimization problems!
8181

82-
<!-- ## TODO: primal and slack update and discrete algebraic riccati equation -->
8382
---
8483

8584
## Primal and slack update
8685

8786
The primal update in TinyMPC takes advantage of the special structure of Model Predictive Control (MPC) problems. The optimization problem can be written as:
8887

8988
$$
90-
\min_{x_{1:N}, u_{1:N-1}} J = \frac{1}{2}x_N^{\intercal}Q_fx_N + q_f^{\intercal}x_N + \sum_{k=1}^{N-1} \frac{1}{2}x_k^{\intercal}Qx_k + q_k^{\intercal}x_k + \frac{1}{2}u_k^{\intercal}Ru_k
89+
\min_{x_{1:N}, u_{1:N-1}} J = \frac{1}{2}x_N^\intercal Q_f x_N + q_f^\intercal x_N + \sum_{k=1}^{N-1} \frac{1}{2}x_k^\intercal Q x_k + q_k^\intercal x_k + \frac{1}{2}u_k^\intercal R u_k + r_k^\intercal u_k
9190
$$
9291

9392
$$
@@ -122,10 +121,10 @@ where $K_k$ is the feedback gain and $d_k$ is the feedforward term. These are co
122121

123122
$$
124123
\begin{aligned}
125-
K_k &= (R + B^{\intercal}P_{k+1}B)^{-1}(B^{\intercal}P_{k+1}A) \\
126-
d_k &= (R + B^{\intercal}P_{k+1}B)^{-1}(B^{\intercal}p_{k+1} + r_k) \\
127-
P_k &= Q + K_k^{\intercal}RK_k + (A - BK_k)^{\intercal}P_{k+1}(A - BK_k) \\
128-
p_k &= q_k + (A - BK_k)^{\intercal}(p_{k+1} - P_{k+1}Bd_k) + K_k^{\intercal}(Rd_k - r_k)
124+
K_k &= (R + B^\intercal P_{k+1} B)^{-1}(B^\intercal P_{k+1} A) \\
125+
d_k &= (R + B^\intercal P_{k+1} B)^{-1}(B^\intercal p_{k+1} + r_k) \\
126+
P_k &= Q + K_k^\intercal R K_k + (A - B K_k)^\intercal P_{k+1} (A - B K_k) \\
127+
p_k &= q_k + (A - B K_k)^\intercal (p_{k+1} - P_{k+1} B d_k) + K_k^\intercal (R d_k - r_k)
129128
\end{aligned}
130129
$$
131130

@@ -144,8 +143,8 @@ A key optimization in TinyMPC is the pre-computation of certain matrices that re
144143

145144
$$
146145
\begin{aligned}
147-
C_1 &= (R + B^{\intercal}P_{\text{inf}}B)^{-1} \\
148-
C_2 &= (A - BK_{\text{inf}})^{\intercal}
146+
C_1 &= (R + B^\intercal P_{\text{inf}} B)^{-1} \\
147+
C_2 &= (A - B K_{\text{inf}})^\intercal
149148
\end{aligned}
150149
$$
151150

@@ -158,13 +157,13 @@ This significantly reduces the online computational burden while maintaining the
158157
For long time horizons, the Riccati recursion converges to a steady-state solution given by the discrete algebraic Riccati equation:
159158

160159
$$
161-
P_{\text{inf}} = Q + A^{\intercal}P_{\text{inf}}A - A^{\intercal}P_{\text{inf}}B(R + B^{\intercal}P_{\text{inf}}B)^{-1}B^{\intercal}P_{\text{inf}}A
160+
P_{\text{inf}} = Q + A^\intercal P_{\text{inf}} A - A^\intercal P_{\text{inf}} B(R + B^\intercal P_{\text{inf}} B)^{-1} B^\intercal P_{\text{inf}} A
162161
$$
163162

164163
This steady-state solution $P_{\text{inf}}$ yields a constant feedback gain:
165164

166165
$$
167-
K_{\text{inf}} = (R + B^{\intercal}P_{\text{inf}}B)^{-1}B^{\intercal}P_{\text{inf}}A
166+
K_{\text{inf}} = (R + B^\intercal P_{\text{inf}} B)^{-1} B^\intercal P_{\text{inf}} A
168167
$$
169168

170169
TinyMPC leverages this property by pre-computing these steady-state matrices offline, significantly reducing the online computational burden. The only online updates needed are for the time-varying linear terms in the cost function.

docs/solver/solver.md

Lines changed: 92 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,112 @@ Our 2024 ICRA submission video provides a concise overview of the solver:
1414
TinyMPC solves convex quadratic model-predictive control programs of the form
1515

1616
$$
17-
\begin{array}{ll}
18-
\mbox{minimize} & \sum_{k=0}^{N-1} \frac{1}{2} (x_k - \bar{x}_k)^T Q (x_k - \bar{x}_k) + \frac{1}{2}(u_k - \bar{u}_k)^T R (u_k - \bar{u}_k) \\
19-
\mbox{subject to} & x_{0} = x_{\text{init}}, \\
20-
& x_{k+1} = A x_k + B u_k, \\
21-
& u_k^l \le u_k \le u_k^u, \\
22-
& x_k^l \le x_k \le x_k^u, \\
23-
& u_k \in \mathcal{K}_u, \\
24-
& x_k \in \mathcal{K}_x
25-
\end{array}
17+
\begin{aligned}
18+
\min_{x_{1:N}, u_{1:N-1}} \quad & J = \frac{1}{2} x_N^\intercal Q_f x_N + q_f^\intercal x_N + \sum_{k=1}^{N-1} \frac{1}{2} x_k^\intercal Q x_k + q_k^\intercal x_k + \frac{1}{2} u_k^\intercal R u_k + r_k^\intercal u_k \\
19+
\text{subject to} \quad & x_{k+1} = A x_k + B u_k \quad \forall k \in [1, N), \\
20+
& x_k \in \mathcal{X}, \quad u_k \in \mathcal{U}
21+
\end{aligned}
2622
$$
2723

28-
where $x_k \in \mathbb{R}^n$, $u_k \in \mathbb{R}^m$ are the state and control input at time step $k$, $N$ is the number of time steps (also referred to as the horizon), $A \in \mathbb{R}^{n \times n}$ and $B \in \mathbb{R}^{n \times m}$ define the system dynamics, $Q \succeq 0$, $R \succ 0$, and $Q_f \succeq 0$ are symmetric cost weight matrices and $\bar{x}_k$ and $\bar{u}_k$ are state and input reference trajectories. Constrains include state and input lower and upper bounds and second-order cones $\mathcal{K}$.
24+
where $x_k \in \mathbb{R}^n$, $u_k \in \mathbb{R}^m$ are the state and control input at time step $k$, $N$ is the number of time steps (also referred to as the horizon), $A \in \mathbb{R}^{n \times n}$ and $B \in \mathbb{R}^{n \times m}$ define the system dynamics, $Q \succeq 0$, $R \succ 0$, and $Q_f \succeq 0$ are symmetric cost weight matrices, and $q_k$, $r_k$, $q_f$ are linear cost vectors. The convex sets $\mathcal{X}$ and $\mathcal{U}$ represent state and input constraints respectively.
2925

3026
---
3127

3228
## Algorithm
3329

34-
Will be provided soon! Meanwhile, check out [our papers](../index.md) or [background](background.md) for more details.
30+
TinyMPC employs the **Alternating Direction Method of Multipliers (ADMM)** to efficiently solve convex quadratic MPC problems. The algorithm separates dynamics constraints from other convex constraints, enabling the use of specialized techniques for each type.
31+
32+
### ADMM Framework
33+
34+
The algorithm reformulates the MPC problem by introducing slack variables and solving three iterative update steps:
35+
36+
$$
37+
\begin{aligned}
38+
\text{primal update: } \quad & (x^+, u^+) = \underset{x,u}{\arg \min} \, \mathcal{L}_A(x,u,z_x,z_u,\lambda,\mu) \\
39+
\text{slack update: } \quad & (z_x^+, z_u^+) = \underset{z_x,z_u}{\arg \min} \, \mathcal{L}_A(x^+,u^+,z_x,z_u,\lambda,\mu) \\
40+
\text{dual update: } \quad & \lambda^+ = \lambda + \rho(x^+ - z_x^+), \quad \mu^+ = \mu + \rho(u^+ - z_u^+)
41+
\end{aligned}
42+
$$
43+
44+
### Key Innovation: LQR-Based Primal Update
45+
46+
The **primal update** step is reformulated as a Linear Quadratic Regulator (LQR) problem, which has a closed-form solution through the **discrete Riccati recursion**. This is the computational bottleneck that TinyMPC optimizes.
47+
48+
The modified cost matrices for the LQR problem become:
49+
50+
$$
51+
\begin{aligned}
52+
\tilde{Q}_f &= Q_f + \rho I, \quad \tilde{q}_f = q_f + \lambda_N - \rho z_N \\
53+
\tilde{Q} &= Q + \rho I, \quad \tilde{q}_k = q_k + \lambda_k - \rho z_k \\
54+
\tilde{R} &= R + \rho I, \quad \tilde{r}_k = r_k + \mu_k - \rho w_k
55+
\end{aligned}
56+
$$
57+
58+
The optimal control policy is computed via backward Riccati recursion:
59+
60+
$$
61+
\begin{aligned}
62+
K_k &= (R + B^\intercal P_{k+1} B)^{-1}(B^\intercal P_{k+1} A) \\
63+
d_k &= (R + B^\intercal P_{k+1} B)^{-1}(B^\intercal p_{k+1} + r_k) \\
64+
u_k^* &= -K_k x_k - d_k
65+
\end{aligned}
66+
$$
67+
68+
### Constraint Handling via Projection
69+
70+
The **slack update** step handles convex constraints through simple projection operations:
71+
72+
$$
73+
\begin{aligned}
74+
z_k^+ &= \text{proj}_{\mathcal{X}}(x_k^+ + y_k) \\
75+
w_k^+ &= \text{proj}_{\mathcal{U}}(u_k^+ + g_k)
76+
\end{aligned}
77+
$$
78+
79+
where $\mathcal{X}$ and $\mathcal{U}$ are the feasible sets for states and inputs respectively.
80+
81+
### Computational Optimization
82+
83+
For long horizons, TinyMPC pre-computes matrices that converge to steady-state values:
84+
85+
$$
86+
\begin{aligned}
87+
P_{\text{inf}} &= Q + A^\intercal P_{\text{inf}} A - A^\intercal P_{\text{inf}} B(R + B^\intercal P_{\text{inf}} B)^{-1} B^\intercal P_{\text{inf}} A \\
88+
K_{\text{inf}} &= (R + B^\intercal P_{\text{inf}} B)^{-1} B^\intercal P_{\text{inf}} A
89+
\end{aligned}
90+
$$
91+
92+
This significantly reduces online computation by caching expensive matrix operations.
93+
94+
### Algorithm Pseudocode
95+
96+
```
97+
Algorithm 1: TinyMPC
98+
function TINY_SOLVE(input)
99+
while not converged do
100+
// Primal update
101+
p_{1:N-1}, d_{1:N-1} ← Backward pass via Riccati recursion
102+
x_{1:N}, u_{1:N-1} ← Forward pass via feedback law
103+
104+
// Slack update
105+
z_{1:N}, w_{1:N-1} ← Project to feasible set
106+
107+
// Dual update
108+
y_{1:N}, g_{1:N-1} ← Gradient ascent update
109+
q_{1:N}, r_{1:N-1}, p_N ← Update linear cost terms
110+
end while
111+
return x_{1:N}, u_{1:N-1}
112+
end function
113+
```
35114

36115
---
37116

38117
## Implementations
39118

40119
The TinyMPC library offers a C++ implementation of the algorithm mentioned above, along with [interfaces to several high-level languages](../get-started/examples.md). This integration allows these languages to seamlessly solve optimal control problems using TinyMPC.
41120

121+
We have made available [Python](https://github.com/TinyMPC/tinympc-python), [MATLAB](https://github.com/TinyMPC/tinympc-matlab), and [Julia](https://github.com/TinyMPC/tinympc-julia) interfaces.
122+
42123
There are also several community-developed implementations of this algorithm: [Rust](https://github.com/peterkrull/tinympc-rs)
43124

44125
Numerical benchmarks against other solvers on microcontrollers are available at [this repository](https://github.com/RoboticExplorationLab/mcu-solver-benchmarks).

0 commit comments

Comments
 (0)