Error status 1, what can I do to investigate this problem?

Hi,

I am getting the error status 1 from the ocp solver. The print_statistics prints:

iter res_stat res_eq res_ineq res_comp qp_stat qp_iter alpha
0 nan nan 1.000000e+15 0.000000e+00 0 0 0.000000e+00

What can I do to further investigate this error?

Thanks,
David

Hi David,

this means that you got an error, this one:

Already the residual evaluation resulted in NaNs.
Some of your problem functions are not defined for the initial guess.
More specifically, the stationarity residual is NaN, so your model equations are not well defined for the initial guess.
You probably need to initialize the solver more carefully.

Cheers,
Jonathan

Thanks Jonathan for the really quick reply!

I guessed that it has to do something with the initialization, but I do not see what I did wrong during the initialization. At least now I can be sure that it has something to do with the initialization. I will recheck and write again :slight_smile:

As a suggestion I would introduce more specific return values. Just an ACADOS_FAILURE is not really helpful for debugging.

Best wishes,
David

Hi Jonathan,

I now found out that it has something to do with the initialization of z. However, I can not see what might be the problem. Do you have a hint for me?

Here is a minimal example, which currently does not work. If you would write z-1 instead of 1 / z - 1 in the algebraic equation, it would work.

import casadi as cd
import numpy as np
from acados_template import AcadosModel, AcadosOcp, AcadosOcpSolver


def export_simple_inverse_model() -> AcadosModel:
    model_name = 'minimal_example'
    # set up states & controls
    x = cd.SX.sym('x')
    u = cd.SX.sym('u')
    p = cd.SX.sym('p')
    # xdot
    x_dot = cd.SX.sym('x_dot')
    # algebraic variables
    z = cd.SX.sym('z')
    # dynamics
    f_expl = 1 + z + 1 / p + 1 / u + 1 / x
    f_impl = x_dot - f_expl
    alg = 1 / z - 1
    # This would work:
    # alg = z - 1
    f_impl = cd.vertcat(f_impl, alg)

    model = AcadosModel()

    model.f_impl_expr = f_impl
    model.f_expl_expr = f_expl
    model.x = x
    model.xdot = x_dot
    model.z = z
    model.u = u
    model.p = p
    # set model_name
    model.name = model_name

    return model


def test_acados_initialization() -> None:
    # create ocp object to formulate the OCP
    ocp = AcadosOcp()

    # set model
    model = export_simple_inverse_model()
    ocp.model = model

    Tf = 1.0
    N = 20

    # set dimensions
    ocp.dims.N = N

    # the 'EXTERNAL' cost type can be used to define general cost terms
    # NOTE: This leads to additional (exact) hessian contributions when using GAUSS_NEWTON hessian.
    ocp.cost.cost_type = 'EXTERNAL'
    ocp.cost.cost_type_e = 'EXTERNAL'
    ocp.model.cost_expr_ext_cost = model.x**2 + model.u**2 + model.z**2
    ocp.model.cost_expr_ext_cost_e = model.x**2

    # set constraints
    ocp.constraints.x0 = np.array([0.0])

    # set options
    ocp.solver_options.qp_solver = 'PARTIAL_CONDENSING_HPIPM'
    ocp.solver_options.hessian_approx = 'EXACT'  # 'GAUSS_NEWTON', 'EXACT'
    ocp.solver_options.integrator_type = 'IRK'
    ocp.solver_options.nlp_solver_type = 'SQP'  # SQP_RTI, SQP

    # set prediction horizon
    ocp.solver_options.tf = Tf

    p_init = np.array([2])
    ocp.parameter_values = p_init
    ocp_solver = AcadosOcpSolver(ocp, json_file='acados_ocp.json')
    # Initial guess.
    x_init = 1
    z_init = 1
    u_init = 1
    p_init = 1
    for stage in range(0, ocp_solver.acados_ocp.dims.N + 1):
        ocp_solver.set(stage, 'x', x_init)
    for stage in range(0, ocp_solver.acados_ocp.dims.N):
        ocp_solver.set(stage, 'z', z_init)
    for stage in range(0, ocp_solver.acados_ocp.dims.N):
        ocp_solver.set(stage, 'u', u_init)
    for stage in range(0, ocp_solver.acados_ocp.dims.N + 1):
        ocp_solver.set(stage, 'p', p_init)
    status = ocp_solver.solve()
    assert status == 0, f'acados returned status {status}.'


if __name__ == '__main__':
    test_acados_initialization()

Thanks,
David

Hi David,

Thanks for providing this minimal example!
I just tried it, and mad a PR Initialize integrator z guess, when setting z, comments regarding algebraic variables. by FreyJo · Pull Request #902 · acados/acados · GitHub
with the following changes

  1. renamed the status as you requested to ACADOS_NAN_DETECTED
  2. set the guess for z in the integrator also when initializing z.
    The example now works!

I am honestly a bit though surprised that the other version works, i.e. solving an OCP with initial state 0.0, where you divide by x within your dynamic model equations.
I think one should really be a bit careful dividing by some numbers within a model used in SQP.

Cheers!
Jonathan

Hi Jonathan,

thanks for the quick bug fix :blush: How long does it normally take until the pull request is accepted?

Why do you think the initial state of x is 0? I also initialized x with 1 in the minimal example.

Cheers!
David

Hi,

good to have this solved!

Since all the tests passed and it is not controversial, I just merged it now.

you specified it here:

    ocp.constraints.x0 = np.array([0.0])

Perfect! Thanks for merging!

Ah that is true. That is weird. That should not work then, may that be a bug?
If I print the solution of the first stage of x I get: array([0.]). I am not sure if this number is rounded maybe it is just really small. Actually, this should cause an NaN in some matrices and thus result in an error.

I don’t think it is a bug.
In the implicit RK used the ODE is never evaluated at x0, so it is able to find a solution, but still the problem is not well defined formally.

Ah yeah, that is true.