Thomas Sharpless
Thomas Sharpless

Reputation: 1133

Puzzled by "You mixed matrices of different sizes"

Trying to fit a plane normal to a vector of 3d points, with the following code

typedef Eigen::MatrixX3f mat3f;
typedef Eigen::Map<mat3f> map3f;
int npts = points.size();
map3f matA((float*)points.data(), npts, 3);
Eigen::MatrixX3f matB = Eigen::MatrixX3f::Constant(npts, 3, -1.f);
Eigen::Vector3f normal = matA.colPivHouseholderQr().solve(matB);

I get this compile error for the last line:

static_assert failed: 'YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES'

Evidently the compiler (MSVCC 17) thinks the output of solve() is not compatible with Vector3f.

However its template instantiation messages seem to indicate that it is looking for a Matrix of that type; here is the last one:

>       D:\opensource\vcpkg\installed\x64-windows\include\Eigen\src\Core\PlainObjectBase.h(797,17):
1>        see reference to function template instantiation 'void Eigen::internal::call_assignment_no_alias<Derived,Eigen::Solve<Eigen::ColPivHouseholderQR<Eigen::Matrix<float,-1,3,0,-1,3>>,Eigen::Matrix<float,-1,3,0,-1,3>>,Eigen::internal::assign_op<float,float>>(Dst &,const Src &,const Func &)' being compiled
1>        with
1>        [
1>            Derived=Eigen::Matrix<float,1,3,1,1,3>,
1>            Dst=Eigen::Matrix<float,1,3,1,1,3>,
1>            Src=Eigen::Solve<Eigen::ColPivHouseholderQR<Eigen::Matrix<float,-1,3,0,-1,3>>,Eigen::Matrix<float,-1,3,0,-1,3>>,
1>            Func=Eigen::internal::assign_op<float,float>
1> 
    

How can I declare the output vector properly?

Upvotes: -1

Views: 97

Answers (2)

chtz
chtz

Reputation: 18827

Generally, if you multiply a (m,k) with a (k,n)-matrix, you get a (m,n) result. The pseudo-inverse of a (m,k) matrix has dimensions (k,m). "Solving" with a (decomposed) (m,k) matrix and a (m,n) right-hand-side (rhs) therefore results in a (k,n) matrix.

In your example, m==npts, k==3 and n==3, therefore you get a (3,3) matrix as result, but since all columns of your rhs are identical, all columns of your solution are identical. If you just want a (3,1) result, just use a (npts,1) rhs:

Eigen::Vector3f normal = matA.colPivHouseholderQr().solve(Eigen::VectorXf::Constant(npts, -1.f));

Upvotes: 0

Thomas Sharpless
Thomas Sharpless

Reputation: 1133

Turns out the correct declaration for the solve result is Matrix3f. It gets 3 columns, each equal to the 3-component solution.

Upvotes: 0

Related Questions