Plan constrained control
Introduce predictive control, real-time logic, and explicit fallback behaviour. This module has 3 lessons and takes about 2h 25m. Each lesson has a practice exercise that runs real Python in your browser and a short quiz.
Start module 19 in the Learning LabFinite-horizon predictive control
Choose a feasible action by comparing predicted future cost.
Model predictive control predicts the plant over a horizon, chooses an input sequence to minimise cost under constraints, applies only its first input, then solves again using the next state estimate. This is receding-horizon control.
For x_next=0.8*x+0.2*u, use a stage cost (x_next-r)^2+0.05*u^2. A teaching controller can enumerate a small set of candidate commands. This is finite-set predictive control, not a general continuous quadratic-program solver.
Longer horizons increase computation and do not by themselves guarantee stability. Terminal conditions, feasibility, model error, estimator quality, and a defined fallback all matter. Keep the browser example small enough to inspect every candidate.
See it in action
from itertools import product
def cost(sequence,x,reference=0.5):
total=0.
for u in sequence:
x=0.8*x+0.2*u
total+=(x-reference)**2+0.05*u*u
return total
choices=list(product([0.,0.5,1.],repeat=3))
best=min(choices,key=lambda seq:cost(seq,0.))
print('Best sequence:',best,'Apply only:',best[0])
Constrained planning needs a model, a cost, a feasible set, and a fallback.
Real-time control logic and fault handling
Define what the controller does when data or timing are invalid.
A control tick should read a timestamped sensor value, validate it, update the estimator, compute a bounded command, send the command, and log the outcome. Keep slow file and network work outside the timing-critical loop.
Check finite values, plausible ranges, stale timestamps, and missed deadlines. A fallback must be chosen for the actual plant: zero command is appropriate for the simulated heater here but may be unsafe for another process. A watchdog and interlock should not depend only on the main control calculation.
For this software exercise, use a simulated heater command in [0,1], sensor temperature in [0,100] C, and maximum sample age 0.2 s. Invalid measurements or commands return zero with a fault flag. This is a learning policy, not a hardware safety certification.
See it in action
import math
temperature, age, requested = 26.,0.05,1.4
valid=math.isfinite(temperature) and 0<=temperature<=100 and 0<=age<=0.2
command=max(0.,min(1.,requested)) if valid else 0.
print('Command:',command,'Fault:',not valid)
Fault behaviour is part of the controller specification.
Practical: implement a constrained horizon
Enforce state and input limits in a small predictive controller.
Enumerate three-step sequences from actions [0,0.5,1]. Reject a sequence if any predicted next state exceeds 0.7 or falls below zero. Use the same model and stage cost as the previous lesson.
Return the first action of the cheapest feasible sequence. If none is feasible, return zero and an explicit False feasibility flag for this simulated system. Do not silently label the fallback as an optimal solution.
Hard model constraints do not guarantee the real plant respects them. Add model mismatch and check the actual state after each step. A practical constrained design needs margins and a plan for infeasible estimates or disturbances.
Your experiment plan
Use the browser editor or the downloadable notebook. All plant data are simulated. Keep a notebook with parameters, predictions, results, and units.
- Run the controller for 50 samples and log state, command, and feasibility.
- Compare horizons 1 and 3 using the same action set.
- Repeat with actual plant coefficient 0.9 instead of 0.8.
- Inject an infeasible initial state and verify that the failure flag is visible.
What to hand in
- A constrained response plot.
- A horizon comparison table.
- A tested infeasibility and fallback path.
Reflect on your results
Which assumption matters most? Describe one result that surprised you and one experiment that would test your explanation.
The automatic exercise checks the core code behaviour. Review observations and written deliverables yourself or with a mentor.
See it in action
from itertools import product
def choose_action(x,reference=0.5):
best=None; best_cost=float('inf')
for seq in product([0.,0.5,1.],repeat=3):
predicted=x; total=0.; feasible=True
for u in seq:
predicted=0.8*predicted+0.2*u
if not 0<=predicted<=0.7: feasible=False; break
total+=(predicted-reference)**2+0.05*u*u
if feasible and total<best_cost: best,best_cost=seq,total
return (best[0],True) if best is not None else (0.,False)
print('At zero:',choose_action(0.))
print('Outside feasible region:',choose_action(2.))
Make feasibility and fallback behaviour visible in both code and results.
Free, open and run by a nonprofit.
This page is part of Control Engineering, a free course of 20 modules and 60 lessons in the engineering.fit( ) Learning Lab. The Learning Lab is built and run by engineering.fit( ), a nonprofit founded by Abdullateef Opeyemi Bakare that helps African engineering students gain research experience. You do not need an account or pay a fee to learn.