Getting cost and residuals values

Hi,

I am using c code generated files to solve nonlinear MPC problem in C++. After the problem is solved I obtain control and decision variables that look reasonable when I plot them. I wanted to analyse cost value and residuals and I use the following commands to store their values at each iteration of MPC:

ocp_nlp_get(nlp_config, nlp_solver, “cost_value”, &cost_data);
ocp_nlp_get(nlp_config, nlp_solver, “nlp_res”, &residual);

However I obtain 0 for both, cost and residual, at every iteration.

Can you suggest what might be going wrong?

Thanks in advance

Hi,

for the cost,
you need to call
ocp_nlp_eval_cost before the get.
See how it is done in the Python interface acados/acados_ocp_solver.py at master · acados/acados · GitHub

For the residuals, I guess it also makes sense to check what is done in the python interface.
See: acados/acados_ocp_solver.py at master · acados/acados · GitHub

Cheers!

Hi Jonathan,

Thank you for the reply.

I got an error when I tried using ocp_nlp_eval_cost(nlp_solver, nlp_in, nlp_out) before getter. The reason being that ocp_nlp_eval_cost() is not defined in the c files generated by using the command ocp.generate_c_code in MATLAB. On the other hand ocp_nlp_get() is defined in the generated c files.

Am I missing some argument setting in MATLAB so that the generated c files will contain ocp_nlp_eval_cost() ?

Thanks again!
Akash

Both ocp_nlp_get() and ocp_nlp_eval_cost() are defined here (interfaces/acados_c/ocp_nlp_interface.h), not in the generated C files.
See: acados/ocp_nlp_interface.h at f9bf3cc69f5253f887496d5650f719fb4ce1bffd · acados/acados · GitHub

Hi Jonathan,

You are right. The functions are defined in interfaces/acados_c/ocp_nlp_interface.h. I am able to calculate cost now, but strangely I get an error while making call to ocp_nlp_eval_residuals(). Unlike ocp_nlp_eval_cost(), ocp_nlp_eval_residuals() was not declared in interfaces/acados_c/ocp_nlp_interface.h, but even after manually declaring the function it does not work.

Thanks in advance,
Akash

I can confirm that ocp_nlp_eval_residuals was missing in the header file.
What kind of error do you get, when adding it there?

Hi Jonathan,

I declare ocp_nlp_eval_residuals in interfaces/acados_c/ocp_nlp_interface.h like void ocp_nlp_eval_residuals(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out);.
When I call this function from my main cpp file I get the compilation error error: ‘ocp_nlp_eval_residuals’ was not declared in this scope. I am including ocp_nlp_inteface.h in my program as I am getting cost value without any problem. Can you suggest what could be the issue here?

Thanks

That sounds right.
Did you reinstall acados to make sure the files in the include folder are updated?
Or did you add it to the file there directly?

Hi Jonathan,

Reinstalling acados solved the issue. Now I can print the relevant residuals. In my code the value of residuals are as follows:
Screenshot from 2021-12-13 11-39-36

As you can see that the residual for inequality constraint is quite high. To fix this issue changing the initial guess can be a solution. In my case I provide the solution of previous iteration from 2 to N (N is the horizon length of MPC) as initial guess for 1 to N-1 of next iteration (with N-th point given same initialization as of N-1). What else do you think can affect the Ineq residual.

Thank you in advance,
Akash

Hi,

Actually I observe a strange thing while printing residuals. The residuals printed are fixed and do not change over iterations of MPC. On tuning weights of cost function the solver sometimes find solution however the residuals again remain constant.
Can you please check it the residual function implementation is correct in the library?

Thanks in advance,
Akash

Did you rule out that there is some infeasible QP, by printing the solver statistics?
In that case it could be that the solver doesnt actually perform iterations and thus the residuals stay constant.

I just ran an example with it to verify that.

Cheers!

Hi Jonathan,

So I am printing stats using ocp_model_acados_print_stats(acados_ocp_capsule); which is defined in acados_solver_ocp_model.c which is code generated from MATLAB. Just to analyse I remove all inequality constraints except constraints on input variable u. This is the output of above function:


The inequality residual from residual->inf_norm_res_ineq is close to 2.165610e+01 for most of the iterations. The bounds set on input variable are very loose and they are in fact respected when I check the solution of the solver.

Now I don’t understand why inequality residual is high even after this. Please help me understand :slight_smile:

Thanks,
Akash

Hi Akash,

Your screenshot made me realize that the code generated print_stats function is not correct right now for SQP_RTI. I addressed this in this commit:

So what we see in your screenshot are the columns iter, qp_status and qp_iter.

Do you have nonlinear inequalities too?
It is hard to tell why the residual is so high without knowing the details…

Hi Jonathan,

Thank you for confirming.

Actually the original problem I am solving has one major nonlinear inequality constraint. However in order to reason about the residual issue I was getting I removed this inequality constraint. The screenshot is for the SQP_RTI solver with only constraints set on input (lower and upper bounds on u). Since the print_stats works correctly with SQP, I checked using SQP that residuals are high when the bounds are very loose ~1e+7. Ofcourse if the max number of iterations are set less for SQP the solver returns with status max iterations reached with such loosebounds.

I want to confirm that since I have to include the nonlinear inequality constraint in my formulation, is it better to use SQP over SQP_RTI?

Thanks,
Akash

Hi Akash,

Sometimes it can be problematic to set bounds to high to mimic unboundedness.
To large values can lead to numerical issues.
I am not sure in what magnitude your u is. But if 1e5 is also very loose, it might be better to use that.

I typically use SQP and sometimes ignore status 2.
There is just very little performance to be gained switching to SQP_RTI.
Plus, in the latter, you can split preparation and feedback phase.

Hi Jonatham,

I have now made the bounds little strict.

Thank you for the insight and suggestions.

Cheers,
Akash