-
Notifications
You must be signed in to change notification settings - Fork 356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using CasADi automatic differentiation is not possible #809
Comments
Nice to try with Casadi. From what I've seen from your log, the problem comes from there. |
I see at least two sources of the problem:
|
jmodel.jointVelocitySelector(data.ddq).noalias() =
jdata.Dinv() * jmodel.jointVelocitySelector(data.u) - jdata.UDinv().transpose() * data.a[i].toVector(); which produces the error message
I was unable to reproduce the same error with a simplified example so far. For example, the following code compiles without errors: Eigen::Matrix<casadi::SX, 3, 3> A, B;
Eigen::Matrix<casadi::SX, 3, 1> a, b;
Eigen::Matrix<casadi::SX, 3, 1> c = A * a - B.transpose() * b; |
Are you sure if this possible? So far I know, CasADi has its own algebra software. I think what you need is to pass derivatives from Pinocchio + CppAD to the interface of your solver. CasADi has several interfaces such as Ipopt. But some of them you can use without the CasADi framework |
@cmastalli what do you mean by "solver" here? You mentioned Ipopt -- yes, CasADi does provide interface to NLP solvers, but we are not speaking about optimization here. We are discussing automatic differentiation issues. And yes, CasADi does provide means for automatic differentiation:
See https://web.casadi.org/ for more details. |
Could you try: Eigen::Matrix<casadi::SX, 3, 3> A, B;
Eigen::Matrix<casadi::SX, -1, 1> a (4), c (4);
Eigen::Matrix<casadi::SX, 3, 1> b;
c.segment(1, 3) = A * a.segment(1, 3) - B.transpose() * b; @mkatliar, notice I edited the snippet. |
@jmirabel your (the edited and the original) snippet compiles without errors. |
@jmirabel can it have something to do with |
It could but my guesses are:
From the log you provided, I can see that the matrices in the expression are of type
|
Hello @jmirabel , #include <casadi/casadi.hpp>
#include <Eigen/Dense>
namespace Eigen
{
template<> struct NumTraits<casadi::SX>
{
using Real = casadi::SX;
using NonInteger = casadi::SX;
using Literal = casadi::SX;
using Nested = casadi::SX;
static bool constexpr IsComplex = false;
static bool constexpr IsInteger = false;
static int constexpr ReadCost = 1;
static int constexpr AddCost = 1;
static int constexpr MulCost = 1;
static bool constexpr IsSigned = true;
static bool constexpr RequireInitialization = true;
static double epsilon()
{
return std::numeric_limits<double>::epsilon();
}
static double dummy_precision()
{
return 1e-10;
}
static double hightest()
{
return std::numeric_limits<double>::max();
}
static double lowest()
{
return std::numeric_limits<double>::min();
}
static int digits10()
{
return std::numeric_limits<double>::digits10;
}
};
// A function working with Eigen::Matrix'es parameterized by the Scalar type
template <typename Scalar, typename T1, typename T2, typename T3, typename T4>
Eigen::Matrix<Scalar, Eigen::Dynamic, 1> eigenFun(
Eigen::MatrixBase<T1> const& A, Eigen::MatrixBase<T2> const& a, Eigen::MatrixBase<T3> const& B, Eigen::MatrixBase<T4> const& b)
{
Eigen::Matrix<Scalar, Eigen::Dynamic, 1> c(4);
c.segment(1, 3) = A * a.segment(1, 3) - B.transpose() * b;
c[0] = 0.;
return c;
}
}
int main(int, char **)
{
// Declare casadi symbolic matrix arguments
// casadi::SX cs_A = casadi::SX::sym("A", 3, 3);
// casadi::SX cs_B = casadi::SX::sym("B", 3, 3);
casadi::SX cs_a = casadi::SX::sym("a", 4);
casadi::SX cs_b = casadi::SX::sym("b", 3);
// Declare Eigen matrices
Eigen::Matrix<casadi::SX, 3, 3> A, B;
Eigen::Matrix<casadi::SX, -1, 1> a (4), c (4);
Eigen::Matrix<casadi::SX, 3, 1> b;
// Let A, B be some numeric matrices
for (Eigen::Index i = 0; i < A.rows(); ++i)
{
for (Eigen::Index j = 0; j < A.cols(); ++j)
{
A(i, j) = 10 * i + j;
B(i, j) = -10 * i - j;
}
b[i] = cs_b(i);
}
// Let a, b be symbolic arguments of a function
for (Eigen::Index i = 0; i < b.size(); ++i)
b[i] = cs_b(i);
for (Eigen::Index i = 0; i < a.size(); ++i)
a[i] = cs_a(i);
// Call the function taking Eigen matrices
c = eigenFun<casadi::SX>(A, a, B, b);
// Copy the result from Eigen matrices to casadi matrix
casadi::SX cs_c = casadi::SX(casadi::Sparsity::dense(c.rows(), 1));
for (Eigen::Index i = 0; i < c.rows(); ++i)
cs_c(i) = c[i];
// Display the resulting casadi matrix
std::cout << "c = " << cs_c << std::endl;
// Do some AD
casadi::SX dc_da = jacobian(cs_c, cs_a);
// Display the resulting jacobian
std::cout << "dc/da = " << dc_da << std::endl;
// Create a function which takes a, b and returns c and dc_da
casadi::Function fun("fun", casadi::SXVector {cs_a, cs_b}, casadi::SXVector {cs_c, dc_da});
std::cout << "fun = " << fun << std::endl;
// Evaluate the function
casadi::DMVector res = fun(casadi::DMVector {std::vector<double> {1., 2., 3., 4.}, std::vector<double> {-1., -2., -3.}});
std::cout << "fun(a, b)=" << res << std::endl;
} It outputs:
This is how I see CasADi can be used in combination with Eigen code parameterized by a scalar type. |
It does make sense to me, because |
Shouldn't you define |
Yes, indeed. I've done it in #813. |
@mkatliar |
@jmirabel |
fixed by #813. |
The paper says:
I tried to use
casadi::SX
type as a scalar type for Pinocchio algorithms, but the code does not compile. Here is a code snippet:Here is the relevant compiler output: make.log
The text was updated successfully, but these errors were encountered: