-
Notifications
You must be signed in to change notification settings - Fork 10
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
Add fixed size vectors #26
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor comments, but otherwise looks good to me. Thanks for your contribution. Indeed it might be useful to add some matrix types in the future.
Isn't there any way to "hide" the fixed-sized vectors into regular orocos eigen_vectors ? |
I would not know how to generate a typekit that supports a dynamic number of types or variable template arguments. The type system of RTT is based on the idea that each type can be used to look up a What is possible is to expose the template declarations of typedef Eigen::Vector<double, 6, 1> Vector6d;
using namespace RTT::types;
if (!Types()->getTypeInfo<Vector6d>()) {
Types()->addType(new VectorTypeInfo<Vector6d>("eigen_vector6"));
} The extern template declarations and explicit instantiations are not required and only an optimization on compile time and code size. But the That reminds me that I once created a patch for RTT based on Boost's enable_if and operator type traits, that removed the need to specify explicitly whether streaming operators are defined for a certain type and also made the |
+ Vector6d/Matrix6d
Ok I took care of your comments, and also took the liberty of adding the Vector6d and Matrix6d to the set. import("eigen_typekit")
var eigen_vector2 a
var eigen_vector2 b = array(1.,2.)
var eigen_vector3 c
var eigen_vector3 d = array(1.,2.,3.)
c = array(5.,4.,3.,2.,1.,0.)
var eigen_vector4 e
var eigen_vector4 f = array(1.,2.,3.,4.)
var eigen_vector3 e1 = eigen_vector3(1,11)
var eigen_vector3 e2 = eigen_vector3(123,2)
var eigen_matrix m1 = eigen_matrix(10,11)
var eigen_matrix4 m2 = eigen_matrix4(123,2) Don't you think it'd be better to initialize the vectors/matrices to zero when resizing ? |
Indeed, this might be helpful. Normally Eigen does not initialize elements of vectors and matrices for performance reasons. But in all cases where the constructors provided by Orocos typekits are invoked performance is probably not the primary concern. Especially for variable-sized vectors and matrices it would be useful to initialize elements, or to provide alternative constructors that initialize all elements (like vector_index_value_constructor for Eigen vectors). Without an operator to access matrix elements (see #23, or at least an unary index in the default storage order column-major) and without the implementation of at least the common operators for addition and multiplication, Eigen types are not very useful in Orocos scripting anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Constructors with size arguments should be removed for fixed-size Eigen types.
- Constructors from an
array
should check input sizes before the assignment, issue a warning and default-initialize the remaining arguments. Initialization of any fixed-size vector or matrix from an emptyarray
could be used to default-initialize all elements without emitting a warning. - Add
matrix_size_value_constructor
(for variable-sized matrices) andmatrix_value_constructor
(for fixed-size matrices) to initialize all elements with the given value. - Rename
vector_index_array_constructor
tovector_array_constructor
(read: construct vector from array) - Rename
*_index_constructor
classes to*_size_constructor
(read: construct variable-sized vector/matrix by size)
eigen_typekit/eigen_typekit.cpp
Outdated
RTT::types::Types()->type("eigen_vector2")->addConstructor(types::newConstructor(vector_index_constructor<Vector2d>())); | ||
RTT::types::Types()->type("eigen_vector3")->addConstructor(types::newConstructor(vector_index_constructor<Vector3d>())); | ||
RTT::types::Types()->type("eigen_vector4")->addConstructor(types::newConstructor(vector_index_constructor<Vector4d>())); | ||
RTT::types::Types()->type("eigen_vector6")->addConstructor(types::newConstructor(vector_index_constructor<Vector6d>())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not make sense to add vector_index_constructor
s for fixed-size vectors. Actually the constructor functor should be called vector_size_constructor
: it takes a single argument and returns a new vector of the given size.
Using those constructors with an argument different than the fixed size triggers a failed assertion:
Deployer [S]> eigen_vector2(2)
= 6.90771e-310
1.54278e-316
Deployer [S]> eigen_vector2(3)
deployer-gnulinux: /usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:285: void Eigen::PlainObjectBase<Derived>::resize(Eigen::Index) [with Derived = Eigen::Matrix<double, 2, 1>; Eigen::Index = long int]: Assertion `((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0' failed.
Aborted
I addressed the issues, and added a fixed size vector value init : import("eigen_typekit")
var eigen_vector2 a
var eigen_vector2 b = array(1.,2.)
// Testing to copy from a bigger vector
var eigen_vector2 b2 = array(1.,2.,3.,4.,5.,6.)
// --> b2 is still copying the first 2 elements !!
var eigen_vector3 c
var eigen_vector3 d = array(1.,2.,3.)
var eigen_vector4 e
var eigen_vector4 f = array(1.,2.,3.,4.) What's bothering me is that
The array is copied anyway probably because it is trying to assing each value individualy with the "[]" operator (theory). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing my comments and sorry for the long delay since you opened this PR.
I suggest to return a well-defined fixed-size vector (e.g. all zeros) when constructing it from an array of the wrong size (see comment below).
eigen_typekit/eigen_typekit.cpp
Outdated
ptr( new VectorType ){} | ||
const VectorType& operator()(int size,double value ) const | ||
{ | ||
ptr->resize(size); | ||
ptr->conservativeResizeLike(VectorType::Zero(size)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line can be removed? The assignment below will implicitly resize the Eigen vector.
eigen_typekit/eigen_typekit.cpp
Outdated
if(ptr->size() != values.size() && VectorType::RowsAtCompileTime == Eigen::Dynamic) | ||
{ | ||
ptr->conservativeResize(values.size()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the dynamic-sized vector there is no need to resize explicitly. The assignment below will resize the vector as needed and all values will be overwritten anyway.
eigen_typekit/eigen_typekit.cpp
Outdated
log(Error) << "Cannot copy an std vector of size " << values.size() | ||
<< " into a fixed size vector of size " << ptr->size() | ||
<< endlog(); | ||
return *(ptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no way to let an Orocos operator fail. In any case it should return a well-defined value, e.g. VectorType::Constant(RTT::internal::NA<double&>::na())
. At the moment the instance ptr
owned by the constructor singleton is not overwritten, and therefore the result is either undefined or whatever fixed-size vector has been constructed before.
See also #34.
@@ -138,7 +138,7 @@ namespace Eigen{ | |||
if (arg->isAssignable()) { | |||
typedef typename RTT::internal::AssignableDataSource<VectorType >::shared_ptr sh_ptr; | |||
sh_ptr asarg = RTT::internal::AssignableDataSource<VectorType >::narrow( arg.get() ); | |||
asarg->set().resize( size ); | |||
asarg->set().conservativeResizeLike(VectorType::Zero(size)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
eigen_typekit/eigen_typekit.cpp
Outdated
@@ -375,7 +418,7 @@ namespace Eigen{ | |||
ptr( new VectorType() ){} | |||
const VectorType& operator()(int size ) const | |||
{ | |||
ptr->resize(size); | |||
ptr->conservativeResizeLike(VectorType::Zero(size)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*ptr = VectorType::Zero(size)
?
No need to keep the previous values in ptr
. Over its lifetime it will only be resized and copied, so all elements are already zero.
eigen_typekit/eigen_typekit.cpp
Outdated
@@ -402,11 +445,11 @@ namespace Eigen{ | |||
const MatrixType& operator()(int size1,int size2) const | |||
{ | |||
ptr->resize(size1,size2); | |||
ptr->setZero(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simpler:
*ptr = MatrixType::Zero(size1,size2);
I took care of the comments. Now I'm wondering how to set to zero all the elements of the fixed-size vectors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patch and for addressing review comments, even after more than one and a half years!
This PR adds
eigen_vector2
,eigen_vector3
andeigen_vector4
so we can use them in scripting.Implementation is a bit ugly, but I'd like also to do the same for matrix2d,3d,4d, the default in eigen.
To test it :
Gives :