In short, option #2 (i.e. using mpcmoveopt) is the right solution. Let me explain why it works and option #1 does not.
The key concept here is that: in the @mpcstate object that you pass to "mpcmove", the states are defined as x[k|k-1] and last MV is defined as uopt[k-1]. Note that x[k|k-1] = A*x[k-1|k-1] + B*uopt[k-1], computed in the previous control interval.
When you have actuator failure, the real MV "uMeas" would be different than expected uopt[k-1]. In other words, the true state should be x_true[k|k-1] = A*x[k-1|k-1] + B*uMeas, as you mentioned.
It is clear that x_true[k|k-1] = A*x[k-1|k-1] + B*uMeas = A*x[k-1|k-1] + B*(uopt[k-1]+deltaMV) = x[k|k-1] + B*deltaMV
So, when you pass in "uMeas" as "MVused" in "mpcmoveopt", we compute "deltaMV = MVused - uopt[k-1]" and update x[k|k-1] to x_true[k|k-1]. That is why option #2 works.
In option #1, because you don't specify "MVused", we always assume "MVused == uopt[k|k-1]". Therefore "deltaMV" is 0 and x_true[k|k-1] == x[k|k-1]. Even though you replace "uopt[k|k-1]" with "uMeas", the information is lost here. To use option #1 properly in our setup, you also need to replace x[k|k-1] with x_true[k|k-1] in the @mpcstate object before calling "mpcmove".
Hope it helps.
Best Answer