C-Functions instead of Casadi

Hello,

in examples/acados_matlab_octave/generic_external_cost it is demonstrated how to use C-functions for costs, gradient, and Hessian. This works fine in Matlab.

  1. Uncommenting the last line of code which should generate the templated C-code fails and the last part of the error message is

    gcc: error: pendulum_cost/pendulum_cost_ext_cost_fun.c: No such file or directory
    gcc: error: pendulum_cost/pendulum_cost_ext_cost_fun_jac.c: No such file or directory
    gcc: error: pendulum_cost/pendulum_cost_ext_cost_fun_jac_hess.c: No such file or directory
    gcc: error: pendulum_cost/pendulum_cost_ext_cost_e_fun.c: No such file or directory
    gcc: error: pendulum_cost/pendulum_cost_ext_cost_e_fun_jac.c: No such file or directory
    gcc: error: pendulum_cost/pendulum_cost_ext_cost_e_fun_jac_hess.c: No such file or directory
    make: *** [Makefile:101: example] Error 1
    
    
    Error in ocp_generate_c_code (line 226)
        acados_template_mex.compile_main()
    
    Error in acados_ocp/generate_c_code (line 181)
                ocp_generate_c_code(obj)
    
    Error in external_cost_example_ocp (line 172)
    ocp.generate_c_code;
    

    Is this a bug?

  2. Is there a possibility to use C-Functions for discrete-time dynamics as well (and generate templated C-code)?

BR
Martin

Hi Martin,

No, the template based interface never supported C Functions other than the standard CasADi ones.

Is there a possibility to use C-Functions for discrete-time dynamics as well (and generate templated C-code)?

Unfortunately not yet.
It would definitely be an interesting feature for several applications.
If I was to add this possibility, I would probably only do it from Python in the template based interface.

Best,
Jonathan

No, the template based interface never supported C Functions other than the standard CasADi ones.

Do you think it is a lot of effort to make this possible in Matlab? Could you give me a hint what has to be changed?

I guess implementing this feature for the discrete-time dynamics is more involving, right? Therefore, I would like to try it with the cost function first, in order to see if has a noticeable impact on the performance.

BR
Martin

I thought you are mainly using the Python interface. Or is that not true anymore?

In this case, it would actually be easier to add this feature there, since the Native MEX and template based MEX interface actually don’t share a lot of code.

I guess implementing this feature for the discrete-time dynamics is more involving, right?

I think it is similarly difficult actually.

No, I always did my ACADOS-related developments in Matlab. Maybe some other Martin in the forum uses Python :wink:

No, I always did my ACADOS-related developments in Matlab.

Ok, I must have confused something :smiley:

First, I noticed, that the example you are referring to has been broken with this PR, Interfaces: Add separate formulation for initial stage cost term. by FreyJo · Pull Request #684 · acados/acados · GitHub .
But I just fixed it on the acados/acados master branch with this commit: MEX: fix generic_external_cost example · acados/acados@74d3e69 · GitHub

I will try to outline what changes are required:

Hi Jonathan,

I am currently working on this topic and have a first running version in my acados fork. I successfully tested it with the example mentioned at the top of this thread. Now I have questions about the C-cost function of this example: void ext_cost(void **in, void **out, void *params)

  • Is it always the case that in is an array of two BLASFEO_DVEC_ARGS pointers and out contains pointers to a scalar (costs), a BLASFEO_DVEC, and a BLASFEO_DMAT? Why are the input types _ARGS and the outputs not?

  • From my debugging output in the cost-function it seems that params is simply a double array. Is that correct?

In case I wanted to extend that to enable C-functions for discrete-time dynamics:

I’ve looked at the example in examples/c/no_interface_examples/mass_spring_nmpc_example.c and there the signature for the dynamics is:
void disc_model(void *fun0, ext_fun_arg_t *type_in, void **in, ext_fun_arg_t *type_out, void **out)

There are additional arguments for input and output types. Why is this not necessary for the cost functions (there the type arguments are missing)?

BR
Martin

Hi Martin,

Nice!

I’ve looked at the example in examples/c/no_interface_examples/mass_spring_nmpc_example.c and there the signature for the dynamics is:
void disc_model(void *fun0, ext_fun_arg_t *type_in, void **in, ext_fun_arg_t *type_out, void **out)
There are additional arguments for input and output types. Why is this not necessary for the cost functions (there the type arguments are missing)?

In general they should be there, because the functions should have an evaluate function of this signature: https://github.com/acados/acados/blob/80b3461b49c39f92f98057bdc00734d268d6aa9e/acados/utils/external_function_generic.h#L97
I am wondering why the input arguments for the types are missing in this Matlab example.
Corrected external cost function signature · acados/acados@846b673 · GitHub

Is it always the case that in is an array of two BLASFEO_DVEC_ARGS pointers and out contains pointers to a scalar (costs), a BLASFEO_DVEC, and a BLASFEO_DMAT? Why are the input types _ARGS and the outputs not?

This is determined by the way the external function is called in acados. For the CasADi external functions there is this wrapper, that can handle these different types of in/output arguments: https://github.com/acados/acados/blob/80b3461b49c39f92f98057bdc00734d268d6aa9e/acados/utils/external_function_generic.c#L1131
For example for the external function you are looking at, it is called like this in acados: https://github.com/acados/acados/blob/80b3461b49c39f92f98057bdc00734d268d6aa9e/acados/ocp_nlp/ocp_nlp_cost_external.c#L611-L620

From my debugging output in the cost-function it seems that params is simply a double array. Is that correct?

Basically, yes, looking at this: https://github.com/acados/acados/blob/80b3461b49c39f92f98057bdc00734d268d6aa9e/acados/utils/external_function_generic.c#L153-L165

Best,
Jonathan