Typecasting Eigen::Vectorxd to Std::Vector

typecasting Eigen::VectorXd to std::vector

vector<int> vec(mat.data(), mat.data() + mat.rows() * mat.cols());

Converting an Eigen::VectorXd to an std::vector<double>

You are using a constructor syntax for the std::vector vec although the vector was already declared. That doesn't work.

There are two efficient possibilities to copy the content of an Eigen::VectorXd into a std::vector<double>. You can either construct a new std::vector vec2, like this:

vector<double> vec2(firstEvector.data(), firstEvector.data() + firstEvector.size());

or use the previously declared vector vec and transfer the data from the Eigen::VectorXd by using Eigen::Map. But in that case the std::vector first needs to be resized:

vec.resize(firstEvector.size());
Map<VectorXd>(vec.data(), vec.size()) = firstEvector;

Convert every column of an Eigen::Matrix to an std::vector?

I think the most elegant Solution would be to use Eigen::Map. In your case you would do it like this:

 Eigen::MatrixXf mat(3, 4);
mat << 1.1, 2, 3, 50,
2.2, 2, 3, 50,
3.1, 2, 3, 50;

std::vector<float> vec;
vec.resize(mat.rows());
for(int col=0; col<mat.cols(); col++){
Eigen::Map<Eigen::MatrixXf>(vec.data(), mat.rows(), 1 ) = mat.col(col); }

How to get an Eigen vector from an Eigen matrix column/row?

Eigen Slicing and Indexing is of much use here.

To retrieve an i-th row vector:

VectorXd V = M(i, all);

To retrieve an i-th column vector:

VectorXd V = M(all, i);

Initialise Eigen::vector with std::vector

According to Eigen Doc, Vector is a typedef for Matrix, and the Matrix has a constructor with the following signature:

Matrix (const Scalar *data)

Constructs a fixed-sized matrix initialized with coefficients starting at data.

And vector reference defines the std::vector::data as:

std::vector::data

T* data();
const T* data() const;

Returns pointer to the underlying array serving as element storage.
The pointer is such that range [data(); data() + size()) is always a
valid range, even if the container is empty.

So, you could just pass the vector's data as a Vector3d constructor parameter:

Eigen::Vector3d v2(v1.data());

Also, as of Eigen 3.2.8, the constructor mentioned above defined as:

template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
::Matrix(const Scalar *data)
{
this->_set_noalias(Eigen::Map<const Matrix>(data));
}

As you can see, it also uses Eigen::Map, as noted by @ggael and @gongzhitaao.

merging a collection of `Eigen::VectorXd`s into one large `Eigen::VectorXd`

The comma initializer does not work like that. You have to fully initialize the matrix from that. Instead, allocate a large enough vector and iterate and assign the blocks.

#include <iostream>
#include <vector>

#include <Eigen/Dense>

// http://eigen.tuxfamily.org/dox/group__TopicStlContainers.html
#include <Eigen/StdVector>
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::VectorXd)

int main()
{
// make some random VectorXds
std::vector<Eigen::VectorXd> vOfV;
Eigen::VectorXd first(3);
Eigen::VectorXd second(4);
first << 1,2,3;
second << 4,5,6,7;
vOfV.push_back(first);
vOfV.push_back(second);

int len = 0;
for (auto const &v : vOfV)
len += v.size();

Eigen::VectorXd flattened(len);

int offset = 0;
for (auto const &v : vOfV)
{
flattened.middleRows(offset,v.size()) = v;
offset += v.size();
}

std::cout << flattened << "\n";
}

Fill a std::vector from a row of an Eigen Array / Matrix

Figured it out. The problem is related to storage order, the way how Eigen lays out a two dimensional array in memory. There are two possible layouts: RowMajor and ColumnMajor. The default layout is ColumnMajor, which stores the 2D array elements column-wise.

Knowing this, the weird result I get makes sense. The .row(0).data() returns the pointer to the first element of the first row. The .row(0).size() is 4 and .row(0).data() + 4 takes the first 4 elements column-wise: [-1, 0, 0, 0]. Same argument for the second column which starts at (1, 0) element, and counting 4 elements column-wise leads to [0, 0, 0, 30.57].

There are two solutions:

  • Make the Array/Matrix layout row-major:
Array<double, 2, Dynamic, RowMajor> arr(2, 6);
arr << 1, 2, 3, 4
5, 6, 7, 8;

vector<double> row1_vec(arr.row(0).data(), arr.row(0).data() + arr.cols());

// row1_vec: 1, 2, 3, 4

  • or use Eigen's Map class:
Array2Xd arr(2, 4);
arr << 1, 2, 3, 4,
5, 6, 7, 8;

vector<double> row1_vec(arr.cols());
Map<RowVectorXd>(&row1_vec[0], 1, arr.cols()) = arr.row(0);

// row1_vec: 1, 2, 3, 4


Related Topics



Leave a reply



Submit