# Trouble with Nonliear Constraints on derivative of state, SQP_RTI: QP solver returned error status 3 QP iteration 15

Hi there,

I’m doing some nmpc things and trying to recurrent a controller based on centroidal-dynamics model of quadruped robot, which is similar to what is already done in OCS2. The state variables are the centroidal momentum, the 6 dimension posture of the center of mass and the angle of 12 joints on 4 legs. The control variables are ground reaction forces and velocity of 12 joints.

I’m just testing a standing case, which just set 4 feet on the ground to support. There’s 2 kinds of constraints the control variables should subject to. The first is the friction cone, which is linearized to square pyramid in advanced. The second one is that the support feet(4 feet in the standing case) shouldn’t move, which has a high non-linear correlation with the velocity of 12 joints and the posture of the center of mass because of forward kinematics of the robot. Actually this constraint is also a function of the derivative of state. Maybe is is infeasible in acados?

To formulate the model and constraints, I link pinocchio3(a Rigid Body Dynamics algorithms implementation) to casadi to do forward kinematics things. First of all I just simplified the second kind of constraints to let the velocity of 12 joints be 0, and everything went well on my simulation project based on MuJoCo, successfully keeping the robot standing without moving. But once I turned to the real constraints – compute feet velocity via pinocchio and let them be 0, the solver crashed and reported “SQP_RTI: QP solver returned error status 3 QP iteration 15”. It couldn’t be caused by pinocchio because the centroidal dynamics model is formulated via it and it runs well in my first attempt.

Here is my python code:

``````import numpy as np

import pinocchio as pin
from pinocchio import casadi as cpin
from pinocchio.robot_wrapper import RobotWrapper

def compute_centriodal_momentum_matrix(m, d, q):

v = ca.SX.zeros(18)

cpin.forwardKinematics(m, d, q)
cpin.updateFramePlacements(m, d)
cpin.ccrba(m, d, q, v)

return d.Ag

def compute_r_com_to_foot(m, d, q, id):

cpin.forwardKinematics(m, d, q)
cpin.updateFramePlacements(m, d)

r = ca.SX.sym("r", 12)
r[0:3] = d.oMf[id[0]].translation - q[0:3]
r[3:6] = d.oMf[id[1]].translation - q[0:3]
r[6:9] = d.oMf[id[2]].translation - q[0:3]
r[9:12] = d.oMf[id[3]].translation - q[0:3]

return r

def compute_end_vel(m, d, q, v, id):

cpin.forwardKinematics(m, d, q, v)
cpin.updateFramePlacements(m, d)

end_vel = ca.SX.sym("end_vel", 12)
for i in range(4):
end_vel[3 * i:3 * i + 3] = cpin.getFrameVelocity(
m, d, id[i], cpin.ReferenceFrame.LOCAL_WORLD_ALIGNED).linear

return end_vel

# 单刚体动力学Centriodal模型
class Centriodal_Model(object):

def __init__(self, ):
model.name = "centriodal"

h_com = ca.SX.sym("h_com", 6)
qb = ca.SX.sym("qb", 6)
qj = ca.SX.sym("qj", 12)
f = ca.SX.sym("f", 12)
qj_dot = ca.SX.sym("qj_dot", 12)

state_vars = ca.SX.sym("state_vars", 24)
state_vars = ca.vertcat(h_com, qb, qj)
control_vars = ca.SX.sym("control_vars", 24)
control_vars = ca.vertcat(f, qj_dot)

mass = 12.454
mg = ca.SX.zeros(3)
mg[2] = -9.81 * mass

jointComposite = pin.JointModelComposite(2)
robot = RobotWrapper.BuildFromURDF("../urdf/a1.urdf", "",
jointComposite)
cmodel = cpin.Model(robot.model)
cdata = cmodel.createData()

# need full config to compute A
full_config = ca.SX.sym("full_config", 18)
full_config[0:6] = qb
full_config[6:18] = qj

# centriodal_momentum_matrix
A_com = ca.SX.sym("centriodal_momentum_matrix", 6, 18)
A_com = compute_centriodal_momentum_matrix(cmodel, cdata, full_config)
A_b = ca.SX.sym("A_b", 6, 6)
A_b = A_com[0:6, 0:6]
A_j = ca.SX.sym("A_j", 6, 12)
A_j = A_com[0:6, 6:18]

qb_dot = ca.SX.sym("qb_dot", 6)
qb_dot = ca.inv(A_b) @ (h_com - A_j @ qj_dot)

full_config_dot = ca.SX.sym("full_config_dot", 18)
full_config_dot = ca.vertcat(qb_dot, qj_dot)

frame_id = [
cmodel.getFrameId("FL_foot"),
cmodel.getFrameId("FR_foot"),
cmodel.getFrameId("RL_foot"),
cmodel.getFrameId("RR_foot")
]

# r_com_to_foot
p_foot = ca.SX.sym("p_foot", 12)
r_com_to_foot = ca.SX.sym("r_com_to_foot", 12)
# r_com_to_foot = compute_r_com_to_foot(cmodel, cdata, full_config,
#                                       frame_id)
for i in range(4):
r_com_to_foot[3 * i:3 * i +
3] = p_foot[3 * i:3 * i + 3] - state_vars[6:9]
v_foot_world = ca.SX.sym("v_foot_world", 12)
v_foot_world = compute_end_vel(cmodel, cdata, full_config,
full_config_dot, frame_id)

# gait table
gait_data = ca.SX.sym("gait_data", 4)

# tau = r.cross * f
tau = (ca.cross(r_com_to_foot[0:3], f[0:3], -1) +
ca.cross(r_com_to_foot[3:6], f[3:6], -1) +
ca.cross(r_com_to_foot[6:9], f[6:9], -1) +
ca.cross(r_com_to_foot[9:12], f[9:12], -1))
f_sum = f[0:3] + f[3:6] + f[6:9] + f[9:12]

# 状态空间
state_space = ca.vertcat(f_sum + mg, tau, qb_dot, qj_dot)

state_vars_dot = ca.SX.sym("state_vars_dot", 24)
f_expl = state_space

model.f_expl_expr = f_expl
model.f_impl_expr = state_vars_dot - f_expl
model.x = state_vars
model.xdot = state_vars_dot
model.u = control_vars
# 参数由足端位置和步态信息构成
model.p = ca.vertcat(p_foot, gait_data)

mu = 0.4
nonlinear_constraint = ca.SX.sym("nonlinear_constraint", 32)
for i in range(4):
# 足底cone约束
nonlinear_constraint[i * 8 + 0] = (f[i * 3 + 0] -
mu * f[i * 3 + 2])
nonlinear_constraint[i * 8 + 1] = (f[i * 3 + 1] -
mu * f[i * 3 + 2])
nonlinear_constraint[i * 8 + 2] = (f[i * 3 + 0] +
mu * f[i * 3 + 2])
nonlinear_constraint[i * 8 + 3] = (f[i * 3 + 1] +
mu * f[i * 3 + 2])
nonlinear_constraint[i * 8 + 4] = f[i * 3 + 2]

#support foot with Zero vel
nonlinear_constraint[i * 8 + 5:i * 8 +
8] = v_foot_world[i * 3:i * 3 + 3]
# nonlinear_constraint[i * 8 + 5] = qj_dot[i * 3 + 0]
# nonlinear_constraint[i * 8 + 6] = qj_dot[i * 3 + 1]
# nonlinear_constraint[i * 8 + 7] = qj_dot[i * 3 + 2]

model.con_h_expr = nonlinear_constraint

constraint = ca.types.SimpleNamespace()
constraint.lower_bound = np.array([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
])
constraint.upper_bound = np.array([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
])

self.model = model
self.constraint = constraint

``````

I generated c code and called it in c++. The error is that:

``````SQP_RTI: QP solver returned error status 3 QP iteration 15
``````

Could anyone tell me what’s wrong? Is acados unable to solve high non-linear constraints with HPIPM(aka a solver for quadratic programs (QP) and quadratically-constrained quadratic programs (QCQP))? Or could I solve this by doing differentiation of the second constraints to linearize it via casadi’s AD in advance?