Differences in behavior between acados v0.4.0 and v0.4.1

Hello,

I am using acados through its MATLAB interface, running closed loop simulations in Simulink. I am using SQP_RTI.

I have recently moved form acados v0.4.0 to v0.4.1 and noticed that controller behaves differently with a more recent version of acados:

  • In certain instances the new controller performs shorter steps in the globalization algorithm.
  • Generally, the globalization algorithm takes longer to compute with the newer version, even when performing a full step.

I need to elaborate on how I measure the globalization algorithm execution time. In version v0.4.0 there is an option to expose time_glob output from the Simulink sfunction. In version v0.4.1 time_glob is always zero, so some custom code was added for getting the timing information, see the code screenshot below.

The timeseries plot below was obtained from a closed loop simulation with MPC controller. In addition to timing information, it also shows the step size in the globalization algorithm.

v0.4.0 behaves somewhat predictably: globalization time is relatively constant, and only spikes then performing backtracking steps.

v0.4.1 is a bit less predictable: we occasionally see spikes in the execution time, even when the globalization algorithm performs full steps.

In this simulation I limited the smallest step size to 0.49. This was done to make the timing comparison more consistent. If this had not been done, v0.4.1 would keep making backtracking steps further, while v0.4.0 would only go down to 0.49.

This experiment was repeated on a Windows machine and on dSpace, so this is unlikely to be compiler-specific.

Going through the release notes, I understand the globalization algorithm has been refactored. My understanding is that functionality has not been changed.

Please let me know if I missed something. Ideally, I would expect v0.4.1 to behave the same as v0.4.0 when two versions are parameterized identically.

Hi :wave:

thanks for reporting this issue! Could you give some more information on your solver settings in particular regarding globalization (or provide the generated .json file)?

Best, Katrin

Hi,

In general, it is not recommended to use RTI with globalization.
Typical globalization strategies compare different iterates in terms of cost and constraint violation.
However, in RTI, the problem typically always changes (at least due to a change in the initial state constraint) and the algorithm only performs a SQP single iteration.

If you naively combine RTI and globalization, typically your initial state constraint is not satisfied, if the step length is not 1.
Additionally, globalization techniques ensure that the infeasibility decreases over the iterations. But since the problem formulation typicaly changes between subsequent iterations, this cannot be guarenteed.

Regarding the timings: The globalization timings are fixed for RTI in acados PR 1376..

Secondly, if there is some unexpected difference in behavior such as different iterations after the globalization refactoring, we could look into it if you provide an example.
Please double check if this issue is related to your other post, Globalization not being parametrised correctly through legacy functions when using new MATLAB interface - #2 by FreyJo

Best,
Jonathan

Hi Katrin,

Many thanks for getting back.
The attached screenshot is a comparison between generated json files for acados v0.4.0 and v0.4.1. When I looked at it for the first time, it stood out to me that alpha_min and full_step_dual are different, despite being parameterised in the same way from MATLAB. At the time I manually changed the rendered C code, so that we have the same parametrisation in alpha_min and full_step_dual. This bug was later fixed by Jonathan.

There are a couple of other small differences in the screenshot, but not sure if they can explain the difference in the controller behavior and execution time.

Best regards,
Bulat

Hi Jonathan,

Thanks for your response and sharing your experience about RTI and globalization.

I understand that with the setup that I have (RTI + merit backtracking), there is a risk of violating the initial condition constraint. Interestingly, for the considered problem, the controller performs better (in terms of closed loop performance) with globalization enabled. I suspect this is something to do with the dynamics model. There are certain operating points in the state space, where the nonlinear problem becomes ill conditioned, i.e. tiny changes in control inputs result in big changes in system response. In such cases, I typically see the globalization algorithm kicking in and preventing the controller from making aggressive input changes, which is often beneficial. This is likely to be something about the dynamics model formulation, which, should be reformulated in a more robust way in order to be able to perform full step at every solve.

Thanks for linking this thread to my previous post about globalization parametrization in MATLAB. I accounted for this when running profiling experiments, but still seeing different behavior between acados versions.

Best wishes,
Bulat

Hi Bulat,

Thanks for your post!
I think that it might indeed make sense to combine RTI and globalization as you are doing.

I looked a bit into your issue.
It is really not so easy without having a test example.
So, I ended up mainly looking through the diffs of acados PR 1254.
My main finding is that in RTI, the second order correction was not implemented yet before this PR. So there was a discrepancy between MERIT_BACKTRACKING with SQP and SQP_RTI.
This could be the difference that results in longer runtimes for you.
You can disable this by setting globalization_use_SOC = 0.

How do you assess the step length in SQP_RTI? I don’t think there is a dedicated getter and the value does not even seem to be stored in memory.

If you could provide a small example showcasing the difference in behavior between the two version, it would enable us to investigate this further.

Best,
Jonathan

Hi Jonathan,

Thanks for getting back.

You suggestion to set globalization_use_SOC = 0 did the job - now I have v0.4.0 and v0.4.1 giving nearly identical results, both the controller response and execution time. In fact, I was able to move to v0.4.3 retaining the same controller behavior.

Regarding your comment about step length: indeed there is no dedicated getter for this. I added a couple of lines of code in ocp_nlp_sqp_rti.c to expose the step length in a dirty way, without a dedicated getter. You will find the code screenshot in the first message in this thread.

Many thanks for your help!

Best regards,
Bulat