mardi 28 janvier 2020

Returning reference to Eigen Quaternion

I have a class with an Eigen::Quaterniond as a protected member variable. I want to access it through the method attitude(). There are three ways I can think to do this right now, and none of them seem to work.

This is a minimum working example in a google test format.


#include "gtest/gtest.h"
#include <Eigen/Geometry>

class MyClass{
public:
    MyClass( double w, double x, double y, double z ) : attitude_(w,x,y,z) {}

    Eigen::Quaterniond&       attitude1()       { return attitude_; }
    const Eigen::Quaterniond& attitude1() const { return attitude_; }

    // compilation fails with " error: 'IsVectorAtCompileTime' is not a member of 'Eigen::Quaternion<double>' "
    // Eigen::Ref<Eigen::Quaterniond>             attitude2()       { return attitude_; }
    // const Eigen::Ref<const Eigen::Quaterniond> attitude2() const { return attitude_; }

    Eigen::Map<Eigen::Quaterniond>             attitude3()       { return Eigen::Map<Eigen::Quaterniond>(attitude_.coeffs().data()); }
    const Eigen::Map<const Eigen::Quaterniond> attitude3() const { return Eigen::Map<const Eigen::Quaterniond>(attitude_.coeffs().data()); }

protected:
    Eigen::Quaterniond attitude_;
};

TEST(QuaternionTest, const_reference ){

    MyClass a(0.2,0.3,0.4,0.5);
    const MyClass& b(a);

    {
        const double& pt1 = a.attitude1().w();
        const double& pt2 = b.attitude1().w();
        EXPECT_EQ(&pt1, &pt2); // FAILS
    }

    // {
    //     const double& pt1 = a.attitude2().w();
    //     const double& pt2 = b.attitude2().w();
    //     EXPECT_EQ(&pt1, &pt2);
    // }

    {
        const double& pt1 = a.attitude3().w();
        const double& pt2 = b.attitude3().w();
        EXPECT_EQ(&pt1, &pt2); // FAILS
    }
}

The commented method is the way I typically return references to internally stored Eigen objects, which enables me to then decide on the actual data storage internally without it being known past the interface (i.e stacking some Vector3 into a contiguous piece of memory).

The compile error looks like a bug to me, as we definitely do know the length of the Quaternion at compile time, it's really just a dressed up Vector4d.

Am I doing something obviously wrong?

Aucun commentaire:

Enregistrer un commentaire