stack-of-tasks / pinocchio

A fast and flexible implementation of Rigid Body Dynamics algorithms and their analytical derivatives
http://stack-of-tasks.github.io/pinocchio/
BSD 2-Clause "Simplified" License
1.89k stars 392 forks source link

GreaterThanZero cannot be called for non-parameters for eigen determinant #1584

Closed chrisFlexiv closed 2 years ago

chrisFlexiv commented 2 years ago

Hi,

I am trying to use CppADCG with pinocchio to compute the gradient of the manipulability determinant index. However, it gives the "GreaterThanZero cannot be called for non-parameters" when the codes are generated. For sure, it's not a problem of pinocchio, but just curious did you encounter similar issues by any chance before? My code snippet is listed below:

`void RigidBodyDynamicsPinocchio::CreateManipulabilityAutoDiff(const ADDataStruct& arguments) { bodyid = robot_admodel.getFrameId(arguments.bodyname); auto func = [&, this](const ad_vector_t& x, ad_vector_t& y) { ad_matrix_t J(6, robot_admodel.nq); pinocchio::computeFrameJacobian( robot_admodel, robot_addata, x, bodyid, pinocchio::LOCAL_WORLD_ALIGNED, J); y.resize(1); y[0] = (J * J.eval().transpose()).determinant(); }; manipulability_derivptr.reset( new CppAdInterface(func, robot_admodel.nq, arguments.modelname, arguments.modelfolder));

CreateAutoDiffFunc(arguments, manipulability_derivptr); }`

After some search online, it seems that the error is due to "if else" branching inside Eigen determinant function with regards to the intermediate variable rather than the independent variable X. Besides re-writing the determinant function of Eigen with CppAD::CondExpLt overloading the switches, are there easier routes/ways to make it be able to generate the auto diff codes succuessfully at run-time? Thank you very much!

Best regards, Chris.

chrisFlexiv commented 2 years ago

Close this issue. For me, I separate the manipulability into two parts, linear and rotation, this can make sure J*J^T is 3x3 which is a small matrix with closed form determinant. Eigen library uses this to calculate small matrix determinant instead of LU decomposition for large matrix. The inequality if/else branches happens in the LU decomposition method. Otherwise, we have to wrap if/else around with CppAD::CondExpLt.