Model Predictive Control (MPC) - CSU083 | Shoolini University

Model Predictive Control (MPC)

1. Prerequisites of Model Predictive Control (MPC)

Before diving into Model Predictive Control, one must understand the following foundational concepts:

1.1 Control Systems

1.2 Optimization

1.3 Linear Algebra

1.4 System Dynamics

2. What is Model Predictive Control (MPC)?

Model Predictive Control (MPC) is an advanced control algorithm that optimizes control inputs by predicting the system's future behavior over a finite time horizon.

2.1 Core Principles

2.2 Mathematical Representation

At each time step, MPC solves:

$$ \min_{u} \sum_{k=0}^{N} (x_k^T Q x_k + u_k^T R u_k) $$

Subject to:

3. Why Does Model Predictive Control Exist?

MPC was developed to handle multivariable systems with constraints efficiently. It is widely used in:

3.1 Industrial Process Control

3.2 Autonomous Vehicles

3.3 Robotics

3.4 Smart Grids

4. When Should You Use Model Predictive Control?

MPC is best suited when:

4.1 Systems Have Constraints

4.2 Multivariable Control is Needed

4.3 Future Predictions Improve Performance

4.4 System Dynamics Are Well Understood

5. How Does Model Predictive Control Compare to Alternatives?

5.1 Strengths of MPC

5.2 Weaknesses of MPC

5.3 Comparison with Other Controllers

Control Method Handles Constraints Predictive Capability Computational Complexity
PID (Proportional-Integral-Derivative) No No Low
State Feedback (LQR) No No Moderate
MPC Yes Yes High

6. Basic Implementation of Model Predictive Control (MPC)

The following Python implementation demonstrates a simple linear MPC for controlling a system represented by the equation:

$$ x_{k+1} = Ax_k + Bu_k $$

We use Quadratic Programming (QP) to optimize the control input over a prediction horizon.


import numpy as np
import cvxpy as cp

# System dynamics: x_{k+1} = Ax_k + Bu_k
A = np.array([[1, 1], [0, 1]])  # State transition matrix
B = np.array([[0], [1]])        # Control matrix
Q = np.eye(2)                    # State cost matrix
R = np.eye(1) * 0.1              # Control effort cost matrix

# Horizon
N = 5

# Constraints
x_min = np.array([-10, -10])  # State constraints
x_max = np.array([10, 10])
u_min = np.array([-2])  # Control constraints
u_max = np.array([2])

# MPC optimization function
def mpc_controller(x0):
    x = cp.Variable((2, N + 1))
    u = cp.Variable((1, N))
    cost = 0
    constraints = [x[:, 0] == x0]

    for k in range(N):
        cost += cp.quad_form(x[:, k], Q) + cp.quad_form(u[:, k], R)
        constraints += [x[:, k + 1] == A @ x[:, k] + B @ u[:, k]]
        constraints += [x_min <= x[:, k], x[:, k] <= x_max]
        constraints += [u_min <= u[:, k], u[:, k] <= u_max]

    problem = cp.Problem(cp.Minimize(cost), constraints)
    problem.solve()

    return u[:, 0].value  # Apply only the first control action

# Initial state
x0 = np.array([5, 0])

# Compute control action
u_optimal = mpc_controller(x0)
print("Optimal Control Action:", u_optimal)

This implementation:

7. Dry Run of Model Predictive Control

Let's analyze step by step how the variables change when the initial state is \( x_0 = [5, 0] \).

7.1 Initial Conditions

7.2 Step-by-Step Execution

Step State \( x \) Control \( u \) Next State Calculation
0 \([5, 0]\) To be optimized \( x_1 = A x_0 + B u_0 \)
1 Computed \( x_1 \) based on \( u_0 \) New \( u_1 \) optimized \( x_2 = A x_1 + B u_1 \)
2 Computed \( x_2 \) New \( u_2 \) optimized \( x_3 = A x_2 + B u_2 \)
3 Computed \( x_3 \) New \( u_3 \) optimized \( x_4 = A x_3 + B u_3 \)
4 Computed \( x_4 \) New \( u_4 \) optimized \( x_5 = A x_4 + B u_4 \)

7.3 Observations

8. Time & Space Complexity Analysis of Model Predictive Control

8.1 Time Complexity

MPC solves a Quadratic Programming (QP) problem at each time step, which determines its complexity.

8.1.1 Worst-case Complexity
8.1.2 Best-case Complexity
8.1.3 Average-case Complexity

9. Space Complexity Analysis

9.1 Memory Consumption

10. Trade-offs in Model Predictive Control

10.1 Accuracy vs. Computation Time

10.2 Constraint Handling vs. Simplicity

10.3 Explicit vs. Implicit MPC

10.4 Comparisons with Alternative Controllers

Controller Computation Cost Memory Usage Constraint Handling Predictive Capability
PID O(1) O(1) No No
LQR O(n^3) O(n^2) No No
MPC O(N(n+m)^3) O(N(n+m)^2) Yes Yes

11. Optimizations & Variants of Model Predictive Control (MPC)

11.1 Common Optimizations

Since MPC is computationally expensive, several optimizations improve efficiency:

11.1.1 Warm-starting Optimization
11.1.2 Explicit MPC
11.1.3 Sparse Matrix Representation
11.1.4 Parallel Processing
11.1.5 Constraint Relaxation

11.2 Variants of MPC

Different MPC formulations are used based on application requirements:

11.2.1 Linear MPC
11.2.2 Nonlinear MPC (NMPC)
11.2.3 Robust MPC
11.2.4 Economic MPC

12. Iterative vs. Recursive Implementations of MPC

12.1 Iterative MPC

12.2 Recursive MPC

12.3 Efficiency Comparison

Implementation Computation Time Memory Usage Suitability
Iterative MPC High (O(N(n+m)^3)) Moderate Simple problems, offline optimization
Recursive MPC Lower (O(N(n+m)^2.5)) Higher (stores past solutions) Real-time control, robotics, autonomous driving

12.4 When to Use Which?

13. Edge Cases & Failure Handling in Model Predictive Control (MPC)

13.1 Common Pitfalls & Edge Cases

13.1.1 Constraint Violations
13.1.2 Poor Model Accuracy
13.1.3 Computational Delays
13.1.4 Numerical Instabilities
13.1.5 Actuator Saturation

14. Writing Test Cases for Model Predictive Control

14.1 Basic Test Cases


import numpy as np

def test_mpc_constraints():
    """Test if MPC respects control constraints."""
    x0 = np.array([5, 0])  # Initial state
    u_optimal = mpc_controller(x0)
    assert np.all(u_optimal >= -2) and np.all(u_optimal <= 2), "Control input out of bounds"

def test_mpc_stability():
    """Test if MPC drives the system towards zero."""
    x0 = np.array([5, 0])  # Initial state
    for _ in range(10):  # Simulate multiple steps
        u_optimal = mpc_controller(x0)
        x0 = np.dot(A, x0) + np.dot(B, u_optimal)  # Apply control
    assert np.all(np.abs(x0) < 0.1), "MPC failed to stabilize system"

def test_mpc_solver():
    """Test if solver successfully finds a solution."""
    x0 = np.array([5, 0])
    try:
        u_optimal = mpc_controller(x0)
        assert u_optimal is not None, "Solver failed"
    except:
        assert False, "MPC solver crashed"

14.2 Edge Case Test Scenarios

15. Real-World Failure Scenarios in MPC

15.1 Autonomous Vehicle Control

15.2 Industrial Process Control

15.3 Robotics & Drone Navigation

16. Real-World Applications & Industry Use Cases of Model Predictive Control (MPC)

MPC is widely used across various industries due to its ability to handle constraints and optimize control decisions.

16.1 Autonomous Vehicles

16.2 Industrial Process Control

16.3 Robotics & Drone Navigation

16.4 Finance & Economic Systems

16.5 Medical & Biomedical Applications

17. Open-Source Implementations of MPC

17.1 Python Libraries

17.2 MATLAB & Simulink

17.3 ROS (Robot Operating System) Integration

17.4 GitHub Repositories

18. Practical Project: Implementing MPC for Drone Path Planning

This Python script simulates an MPC-based drone trajectory controller.


import numpy as np
import cvxpy as cp
import matplotlib.pyplot as plt

# System dynamics: x_{k+1} = Ax_k + Bu_k
A = np.array([[1, 1], [0, 1]])  # Position & velocity
B = np.array([[0], [1]])        # Control influence
Q = np.eye(2)                    # State cost matrix
R = np.eye(1) * 0.1              # Control effort cost matrix
N = 10  # Prediction Horizon

# Constraints
x_min = np.array([-10, -10])  # State constraints
x_max = np.array([10, 10])
u_min = np.array([-2])  # Control constraints
u_max = np.array([2])

def mpc_drone_controller(x0, target):
    x = cp.Variable((2, N + 1))
    u = cp.Variable((1, N))
    cost = 0
    constraints = [x[:, 0] == x0]

    for k in range(N):
        cost += cp.quad_form(x[:, k] - target, Q) + cp.quad_form(u[:, k], R)
        constraints += [x[:, k + 1] == A @ x[:, k] + B @ u[:, k]]
        constraints += [x_min <= x[:, k], x[:, k] <= x_max]
        constraints += [u_min <= u[:, k], u[:, k] <= u_max]

    problem = cp.Problem(cp.Minimize(cost), constraints)
    problem.solve()

    return u[:, 0].value  # Apply only the first control action

# Initial state (position, velocity)
x0 = np.array([5, 0])
target = np.array([0, 0])  # Target landing position

# Simulating control actions over time
positions = []
for _ in range(15):
    u_optimal = mpc_drone_controller(x0, target)
    x0 = np.dot(A, x0) + np.dot(B, u_optimal)  # Apply control
    positions.append(x0[0])

# Plot results
plt.plot(positions, label="Drone Path")
plt.axhline(y=0, color='r', linestyle='--', label="Target")
plt.legend()
plt.xlabel("Time Step")
plt.ylabel("Position")
plt.title("MPC Drone Landing Optimization")
plt.show()

18.1 Explanation

18.2 Possible Extensions

19. Model Predictive Control (MPC) in Competitive Programming & System Design

19.1 Using MPC in Competitive Programming

While MPC is mainly used in real-time control systems, it can be adapted for competitive programming problems that involve:

19.1.1 Example Problem (Path Planning)

Problem: Given a grid where some cells have penalties, find the optimal path from (0,0) to (n,m) such that the cumulative penalty is minimized.

Approach:

19.1.2 Implementation (Python)

import numpy as np
import cvxpy as cp

# Define grid cost matrix (higher values = penalty)
grid = np.array([[0, 2, 3], [1, 5, 1], [4, 1, 0]])

# State-space representation
A = np.eye(2)
B = np.eye(2)
N = 3  # Prediction horizon

def mpc_path_planner(start, target):
    x = cp.Variable((2, N + 1), integer=True)
    u = cp.Variable((2, N))
    cost = 0
    constraints = [x[:, 0] == start]

    for k in range(N):
        cost += grid[int(x[0, k]), int(x[1, k])]
        constraints += [x[:, k + 1] == x[:, k] + u[:, k]]  # Movement model
        constraints += [0 <= x[:, k], x[:, k] < grid.shape[0]]  # Stay within bounds

    problem = cp.Problem(cp.Minimize(cost), constraints)
    problem.solve()

    return x.value[:, 1]  # Return next best move

# Simulate movement
start = np.array([0, 0])
target = np.array([2, 2])
for _ in range(5):
    move = mpc_path_planner(start, target)
    print("Next Move:", move)
    start = move

19.2 Using MPC in System Design

MPC is often used in large-scale system designs for:

19.2.1 Example: Cloud Server Auto-Scaling

20. Assignments: Practical MPC Challenges

20.1 Solve at least 10 problems using MPC

  1. Path planning with obstacles: Find an optimal path avoiding obstacles.
  2. Resource allocation: Distribute limited resources across multiple agents.
  3. Warehouse robot navigation: Plan the best path for a robot collecting items.
  4. Stock trading optimization: Maximize profit while managing risk.
  5. Autonomous car lane switching: Decide the best lane-changing strategy.
  6. Dynamic pricing strategy: Adjust product pricing based on demand forecasts.
  7. Manufacturing scheduling: Optimize machine usage with time constraints.
  8. Traffic signal control: Minimize congestion with adaptive timing.
  9. Multi-agent decision making: Coordinate actions of multiple autonomous agents.
  10. Drone delivery optimization: Find the fastest delivery route considering wind disturbances.

20.2 Implement MPC in a system design problem

Choose one of the following:

20.3 Practice implementing MPC under time constraints