Skip to content

added: FOH discretization for RungeKutta in MPC/MHE and in updatestate!(::SimModel) - #495

Open
franckgaga wants to merge 56 commits into
mainfrom
foh_updatestate_modelonly
Open

franckgaga wants to merge 56 commits into
mainfrom
foh_updatestate_modelonly

Conversation

@franckgaga

@franckgaga franckgaga commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

FOH for disturbances d in MPC/MHE with ShootingMethods

The NonLinMPC and the MovingHorizonEstimator transcribed with SingleShooting and MultipleShooting et solved with RungeKutta now discretize the measured disturbances $\mathbf{d}$ with first-order hold (FOH, or piecewise linear), instead of the simpler zero-order hold (ZOH). It is more adapted for sampled continuous signal, which is usually the case for measured disturbances. The feedforward compensation can be therefore slightly improved by this.

FOH for inputs u in MPC/MHE with ShootingMethods

It is also possible to discretized the manipulated inputs $\mathbf{u}$ with FOH in MPC and MHE by using the SingleShooting(1) or MultipleShooting(1). The default is still ZOH for manipulated inputs.

FOH for updatestate!(::SimModel)

It's now possible to simulate a NonLinModel and NonLinModelDAE with FOH discretization on inputs $\mathbf{u}$ and $\mathbf{d}$, using the new unext and dnext keyword argument. Note that it's information about the future, so this is non-causal. It is still useful in practice since FOH measured disturbances is slightly more realistic that the default ZOH, even if it is non-causal (no discontinuities in the signal). Doing so also remove the annoying plant-model mistmatch between the MovingHorizonEstimator and NonLinMPC with a FOH discretization and the simulated plant.

Warning

FOH discretization for updatestate!(::StateEstimator) is not supported (there are no keyword arguments in this method). First, it leads to a non-causal filter, so not so useful in practice. Second, it significantly complexify the codebase, especially for MovingHorizonEstimator so I left this out of the scope for now. Still not sure if it is worth the effort.

Closes #469

This is truly the left limit at the next time step. If current and next values are identical, it's ZOH discretization, if they are different, it's FOH discretization.
It has the advantage that it creates an abstraction for `InternalModel`, in which the state vector is never augmented.
This is expected since now `d` are FOH discretized in MHE but not in EKF, so a small differences in the results. I may add the support for FOH in EKF later, but not super useful in practice since non-causal.
@codecov-commenter

codecov-commenter commented Oct 31, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.63462% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.13%. Comparing base (697d08b) to head (287433f).
⚠️ Report is 19 commits behind head on main.

Files with missing lines Patch % Lines
src/estimator/internal_model.jl 60.00% 4 Missing ⚠️
src/estimator/execute.jl 90.00% 1 Missing ⚠️
src/estimator/mhe/transcription.jl 96.29% 1 Missing ⚠️
src/model/nonlinmodel.jl 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #495      +/-   ##
==========================================
- Coverage   97.25%   97.13%   -0.12%     
==========================================
  Files          28       28              
  Lines        6995     7088      +93     
==========================================
+ Hits         6803     6885      +82     
- Misses        192      203      +11     
Flag Coverage Δ
unittests 97.13% <96.63%> (-0.12%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@franckgaga

franckgaga commented Nov 2, 2026 •

Copy link
Copy Markdown
Member Author

Okay, all the MPC/MHE benchmark with hessian=true are marginally slower. It's probably because the number of colors in one of the 3 Hessians increased. The root cause is likely new RungeKutta implementation that support both ZOH and FOH. I will see if I can improve this by creating a special path for the simpler ZOH in RungeKutta(1) and RungeKutta(4) solvers.

@franckgaga franckgaga changed the title added: FOH discretization for RungeKutta in MPC/MHE and updatestate!(::SimModel) added: FOH discretization for RungeKutta in MPC/MHE and in updatestate!(::SimModel) Nov 2, 2026
The buffer is used in the returned value of `updatestate!`. Using it in `getinfo` would mutate the output argument of `updatestate!` unexpectedly!
It allows tracking the allocations of `RungeKutta` on the benchmark suite. It should be 0 allocation.
@franckgaga

franckgaga commented Nov 2, 2026 •

Copy link
Copy Markdown
Member Author

I added a special path for ZOH in the two RungeKutta solvers. The benchmark are still slightly slower on CI and I'm not sure why. I'm not able to replicate this result locally on Win11... It's not related to the number of color since it affects the SingleShooting NMPC case on the pendulum, and there are no sparse Hessians in this case study. It maybe noise on the CI runner. Let's do one more run.

@franckgaga

franckgaga commented Nov 2, 2026 •

Copy link
Copy Markdown
Member Author

I'm not able to reproduce locally on fedora... Seems like noise.

edit: Let's try to remove the Ûi allocations at each call of the objective and constraint functions, this is something new compared to main. The are needed to compute the interpolated value of the manipulated input when h=1.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Assume piecewise linear measured disturbances for RungeKutta(4) in MPC/MHE ?

2 participants