[ANN] ModelPredictiveControl.jl

ModelPredictiveControl v1.5.0

An update to announce the migration to DifferentiationInterface.jl. Many thanks to @gdalle for all the help! :grinning_face_with_smiling_eyes:

In addition to a simpler and more maintainable codebase, it allows to switch the differentiation backend for gradients and Jacobians inside NonLinMPC, MovingHorizonEstimator, linearize and ExtendedKalmanFilter. Sparse Jacobians are also supported with AutoSparse. Dense ForwardDiff.jl computation are used everywhere by default, except for the MultipleShooting transcription that uses sparse computations. Note that for small problems like the inverted pendulum with H_p=20 and H_c=2, dense Jacobians may be slightly faster than sparse matrices, even with a MultipleShooting transcription. At least, that’s what I benchmarked for this case study.

Note that the implementation rely on the Cache feature of DI.jl to reduce the allocations, and some backend does not support it for now.

The change log since my last post is:

  • added: migration to DifferentiationInterface.jl
  • added: new gradient and jacobian keyword arguments for NonLinMPC
  • added: new gradient and jacobian keyword arguments for MovingHorizonEstimator
  • added: new jacobian keyword argument for NonLinModel (for linearization)
  • added: new jacobian keyword argument for ExtendedKalmanFilter
  • added: ExtendedKalmanFilter is now allocation-free at runtime
  • changed: deprecate preparestate!(::SimModel,_,_), replaced by preparestate!(::SimModel)
  • debug: nonlinear inequality constraint with MultipleShooting now work as expected (custom + output + terminal constraints)
  • debug: x_noise argument in sim! now works as expected
  • doc: now using DocumenterInterLinks.jl to ease the maintenance
  • test: many new test with AutoFiniteDiff backend
  • test: new test to cover nonlinear inequality constraint with MultipleShooting corner cases

I will release the update soon.

10 Likes

ModelPredictiveControl v1.7.0

A quick update on the new stuff in the package since my last post.

First, the newest release introduces the ManualEstimator to turn off built-in state estimation and provide your own estimate. A first use case is to implement a linear MPC (with an approximate plant model, for the speed) with a nonlinear state estimator (with a high fidelity plant model, for accuracy). A second use case is using the exclusive observers from LowLevelParticleFilters.jl to estimate the state of the plant model and its disturbances.

Also, a significant performance boost for NonLinMPC and MovingHorizonEstimator was introduced in v1.6.0 by the more efficient value_and_gradient! and value_and_jacobian! of DI.jl. This is equivalent of using DiffResults.jl, but agnostic of the differentiation backend. I benchmarked about a 1.25x speed boost on the pendulum example of the manual.

Lastly, the nint_u option for the MovingHorizonEstimator was not working well because of a bug when the observation window is not filled (at the beginning). The bug was corrected in v1.6.2 (with new unit tests).

The next release will introduce custom move blocking, which is a way of specifying long control horizon H_c without increasing the number of decision variables in the optimization problem.

The changelog since my last post is:

  • added: ManualEstimator to turn off built-in state estimation and provide your own estimate \mathbf{\hat{x}}_{k}(k) or \mathbf{\hat{x}}_{k-1}(k)
  • added: slightly improve NonLinMPC performances with specialized conversion and weight matrices
  • added: significant performance boost of NonLinMPC and MovingHorizonEstimator using value_and_gradient!/jacobian! of DifferentiationInterface.jl instead of individual calls
  • added: setstate! now allows manual modifications of the estimation error covariance \mathbf{\hat{P}} (if computed by the estimator)
  • changed: M_Hp, N_Hc and L_Hp keyword arguments now default to Diagonal instead of diagm matrices for all PredictiveController constructors
  • changed: moved lastu0 inside PredictiveController objects
  • removed: DiffCaches in RungeKutta solver
  • debug: force update of gradient/jacobian in MovingHorzionEstimator when window not filled
  • debug: remove .data in KalmanFilter matrix products
  • debug: do not call jacobian! if nd==0 in linearize
  • debug: no more noisy @warn about DiffCache chunk size
  • test: new tests for ManualEstimator
  • test: added allocations tests for types that are known to be allocation-free (SKIP THEM FOR NOW)
  • test: adapt tests for the new automatically balancing minreal function
7 Likes