Skip to main content

qpmpc

CI Documentation Coverage Conda version PyPI version

Model predictive control (MPC) in Python for optimal-control problems that are quadratic programs (QP). This includes linear time-invariant (LTI) and time-variant (LTV) systems with linear constraints. The corresponding QP has the form:

\begin{array}{rl}
\underset{x_k, u_k}{\min} \quad & w_{t} \|x_N - x_{\mathit{goal}}\|_2^2 + w_x \sum_{k=0}^{N-1} \| x_k - x^{\mathrm{ref}}_k \|_2^2  + w_u \sum_{k=0}^{N-1} \| u_k - u^{\mathrm{ref}}_k \|^2_2 \\
\mathrm{s.t.} \quad & x_{k+1} = A_k x_k + B_k u_k \\
& C_k x_k + D_k u_k \leq e_k \\
& x_0 = x_{\mathit{init}}
\end{array}

This module is designed for prototyping. If you need performance, check out the alternatives below.

Installation

pip install qpmpc

Usage

This module defines a one-stop shop function:

solve_mpc(problem: MPCProblem, solver: str) -> Plan

The MPCProblem defines the model predictive control problem (LTV system, LTV constraints, initial state and cost function to optimize) while the returned Plan holds the state and input trajectories that result from optimizing the problem (if a solution exists). The solver string is used to select the backend quadratic programming solver.

Example

Let us define a triple integrator:

    import numpy as np

    horizon_duration = 1.0  # [s]
    N = 16  # number of discretization steps
    T = horizon_duration / N
    A = np.array([[1.0, T, T ** 2 / 2.0], [0.0, 1.0, T], [0.0, 0.0, 1.0]])
    B = np.array([T ** 3 / 6.0, T ** 2 / 2.0, T]).reshape((3, 1))

Suppose for the sake of example that acceleration is the main constraint acting on our system. We thus define an acceleration constraint |acceleration| <= max_accel:

    max_accel = 3.0  # [m] / [s] / [s]
    accel_from_state = np.array([0.0, 0.0, 1.0])
    C = np.vstack([+accel_from_state, -accel_from_state])
    e = np.array([+max_accel, +max_accel])

This leads us to the following linear MPC problem:

    from qpmpc import MPCProblem

    x_init = np.array([0.0, 0.0, 0.0])
    x_goal = np.array([1.0, 0.0, 0.0])
    problem = MPCProblem(
        transition_state_matrix=A,
        transition_input_matrix=B,
        ineq_state_matrix=C,
        ineq_input_matrix=None,
        ineq_vector=e,
        initial_state=x_init,
        goal_state=x_goal,
        nb_timesteps=N,
        terminal_cost_weight=1.0,
        stage_state_cost_weight=None,
        stage_input_cost_weight=1e-6,
    )

We can solve it with:

    from qpmpc import solve_mpc

    solution = solve_mpc(problem, solver="proxqp")

The solution holds complete state and input trajectories as stacked vectors. For instance, we can plot positions, velocities and accelerations as follows:

    import matplotlib.pyplot as plt

    t = np.linspace(0.0, horizon_duration, N + 1)
    X = solution.states
    positions, velocities, accelerations = X[:, 0], X[:, 1], X[:, 2]
    plt.ion()
    plt.plot(t, positions)
    plt.plot(t, velocities)
    plt.plot(t, accelerations)
    plt.grid(True)
    plt.legend(("position", "velocity", "acceleration"))

This example produces the following trajectory:

2022-03-30-172206_1920x1080_scrot

The behavior is a weighted compromise between reaching the goal state (weight 1.0) and keeping reasonable finite jerk inputs (weight 1e-6). The latter mitigate bang-bang accelerations but prevent fully reaching the goal within the horizon. See the examples folder for more examples.

Areas of improvement

This module is incomplete with regards to the following points:

  • Cost functions: can be extended to general linear stage cost functions
  • Documentation: there are some undocumented functions
  • Test coverage: only one end-to-end test

Check out the contribution guidelines if you are interested in lending a hand.

Alternatives

You can also check out the following open-source libraries:

Linear model predictive control

Name Systems Languages License
Copra (LTV fork) Linear time-variant C++, Python BSD-2-Clause
Copra (original) Linear time-invariant C++, Python BSD-2-Clause
mpc-interface Linear time-variant C++, Python BSD-2-Clause
pyMPC Linear time-variant Python MIT

Nonlinear model predictive control

Name Systems Languages License
acados Nonlinear C++, Matlab, Python BSD-2-Clause
Aligator Nonlinear C++, Python BSD-2-Clause
Crocoddyl Nonlinear C++, Python BSD-3-Clause

Metadata

Release files for qpmpc 3.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qpmpc 3.3.0
File Size Uploaded Provenance Actions
qpmpc-3.3.0.tar.gz 195.2 kB Without provenance Details for qpmpc-3.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for qpmpc 3.3.0
File Interpreter ABI Platform Actions
qpmpc-3.3.0-py3-none-any.whl Python 3 none any Details for qpmpc-3.3.0-py3-none-any.whl

Total release size: 215.8 kB

Release files / qpmpc-3.3.0.tar.gz

Download URL qpmpc-3.3.0.tar.gz
Size 195.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c39db2adcaa5d1d84bf8ad7c9beb46fbfbcfb6bd985f2fedfac46a6144c33b2b
BLAKE2b-256 checksum
How to use checksums
c65902ceb4a033d4409df6109c23c7047b2e130d896e0681342ae1c46e275c36
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.4

Release files / qpmpc-3.3.0-py3-none-any.whl

Download URL qpmpc-3.3.0-py3-none-any.whl
Size 20.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ff7cdfec73a9e5acf12ae2a3b5b5a6172886a17b236f083902059106c83bd553
BLAKE2b-256 checksum
How to use checksums
20c81fc4ef45fdc02165615abca396a957d87a398884317e9fb49620180b0530
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.4

Security for qpmpc 3.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page