Model Predictive Control
The Model Predictive Control (MPC) module computes optimal control commands (acceleration and steering) to follow a reference trajectory while respecting vehicle constraints. The MPC predicts future vehicle behavior over a receding horizon and solves a constrained optimization problem at each time step to minimize tracking error.
Overview
MPC is an advanced control technique that:
Predicts future vehicle states over a finite horizon using a dynamics model
Optimizes control inputs to minimize trajectory tracking error
Enforces physical constraints (speed limits, steering limits, acceleration limits)
Applies the first control input and repeats the process at the next time step
This approach is particularly well-suited for autonomous racing because it can explicitly handle vehicle limits while maximizing performance.
Key Features
Real-time capable: Achieves 1-5ms solve times with C code generation
Nonlinear dynamics: Uses bicycle kinematic model with numerical integration
Hard constraints: Enforces velocity, acceleration, and steering rate limits
Warm-starting: Leverages previous solutions for faster convergence
Structure-exploiting solver: Uses FATROP for efficient optimization
Flexible tuning: Adjustable cost weights for different driving styles
System Integration
The MPC controller integrates with the autonomy stack as follows:
Inputs:
Vehicle state from SLAM module (position, heading, velocity)
Reference trajectory from global or local path planner
Previous control inputs for warm-starting
Outputs:
Acceleration commands (m/s²)
Steering angle rate commands (rad/s)
Predicted trajectory for visualization
Control Loop:
Runs at 100 Hz (10ms period)
MPC horizon: 10 time steps × 100ms = 1 second lookahead
Typical lookahead distance: ~10m at 10 m/s
MPC Documentation
Published Topics
Topic |
Type |
Description |
---|---|---|
|
ackermann_msgs/AckermannDriveStamped |
Control commands (acceleration, steering) |
|
std_msgs/Float64 |
Acceleration command only |
|
std_msgs/Float64 |
Steering angle command only |
|
geometry_msgs/PoseArray |
Predicted and reference trajectories for visualization |
Subscribed Topics
Topic |
Type |
Description |
---|---|---|
|
feb_msgs/State |
Current vehicle state (x, y, heading, velocity) |
|
feb_msgs/FebPath |
Reference trajectory from global planner (after first lap) |
|
feb_msgs/FebPath |
Reference trajectory from local planner (exploration lap) |
|
eufs_msgs/WheelSpeedsStamped |
Current steering angle feedback |
|
std_msgs/Bool |
Emergency stop signal (triggers maximum braking) |
Performance Characteristics
Typical Operating Conditions
Prediction horizon: 1 second (10 steps × 100ms)
Control frequency: 100 Hz
Solve time: 1-5 ms with compiled solver, 10-20 ms without
Tracking accuracy: <0.1m RMS lateral error on smooth paths
Maximum speed: 10 m/s (configurable up to 15+ m/s)
Computational Requirements
CPU: ~5-10% of one core at 100 Hz (with compiled solver)
Memory: ~50 MB (including Python runtime and dependencies)
Dependencies: CasADi, NumPy, SciPy, FATROP or IPOPT
API Reference
- class mpc.mpc_controller.MPCPathFollower(N, DT, L_F, L_R, V_MIN, V_MAX, A_MIN, A_MAX, A_DOT_MIN, A_DOT_MAX, DF_MIN, DF_MAX, DF_DOT_MIN, DF_DOT_MAX, Q, R, RUNTIME_FREQUENCY, ivpsolver, **kwargs)[source]
Bases:
object
- construct_solver(generate_c=False, compile_c=False, use_c=False, gcc_opt_flag='-Ofast')[source]
handles codegeneration and loading.
- Parameters
generate_c (bool, optional) – whether or not to generate new C code. Defaults to False.
compile_c (bool, optional) – whether or not to look for and compile the C code. Defaults to False.
use_c (bool, optional) – whether or not to load the compiled C code. Defaults to False.
gcc_opt_flag (str, optional) – optimization flags to pass to GCC. can be -O1, -O2, -O3, or -Ofast depending on how long you’re willing to wait. Defaults to ‘-Ofast’.
- solve(x0, u_prev, trajectory, P=None)[source]
crunch the numbers; solve the problem.
- Parameters
x0 – length 4 vector of the current car state.
u_prev – length 2 vector of the previous control command
trajectory – shape (6, N) trajectory of target states and controls.
P (optional) – terminal cost matrix. If not passed, use default from 10 m/s fwd driving.
- Returns
control result. [[acc], [theta]]
- Return type
array of shape (2, 1)
- make_dynamics(n, method='rk4')[source]
construct functions for the dynamics of the car. uses bicycle model.
- Parameters
n (int) – number of steps the integrator should take.
method (str, optional) – integration method to use. one of (‘midpoint’, ‘rk4’). Defaults to ‘rk4’ for a 4th order explicit runge-kutta method
- Returns
discrete dynamics w/ augmented state, continuous dynamics, jac(f, x), jac(f, u). All casadi.Function objects.
- Return type
(F, f, A, B)
- class mpc.main.MPC(*args, **kwargs)[source]
Bases:
rclpy.node.Node
- steer_callback(msg)[source]
Return Steering Angle from steering angle sensor on car
- Parameters
msg (eufs_msgs.msg.WheelSpeedsStamped) –
- acc_callback(msg)[source]
Set curr_acc to value recieved from
- Parameters
msg (std_msgs.msg.Float64) –
- global_path_callback(msg)[source]
Input: msg.PathState -> List of State (from State.msg) vectors Returns: List of numpy state vectors (len 4: x, y, velocity, heading) Description: Takes in a local or global path depending on what lap we’re in and converts to np.array of state vectors
- Parameters
msg (feb_msgs.msg.FebPath) –
- local_path_callback(msg)[source]
Input: msg.PathState -> List of State (from State.msg) vectors Returns: List of numpy state vectors (len 4: x, y, velocity, heading) Description: Takes in a local or global path depending on what lap we’re in and converts to np.array of state vectors
- Parameters
msg (feb_msgs.msg.FebPath) –
- state_callback(carstate)[source]
Input: Float64[4] Description: Converts State msg to numpy vector,
updates variables initalized in __init__ (e.g. self.z_ref, self.z_curr, etc.) with get_update_dict and self.update, and solves mpc problem -> stores result in self.prev_soln
- Parameters
carstate (feb_msgs.msg.State) –