@@ -16,6 +16,21 @@ cimport octomap_defs as octomap
1616cimport std_defs as std
1717from collision_data import Contact, CostSource, CollisionRequest, ContinuousCollisionRequest, CollisionResult, ContinuousCollisionResult, DistanceRequest, DistanceResult
1818
19+ """
20+ Eigen::Transform linear and translation parts are returned as Eigen::Block
21+ It can be an rvalue and an lvalue, so in C++ you could assign something to translation() like:
22+ `tf.translation() = (Vector3d (0., 0., 50));`
23+ In python and cython however, a function call is never an lvalue, so we workaround with the following macro
24+ """
25+ cdef extern from * :
26+ """
27+ /* Verbatim C as a workaround for assingment to lvalue-returning functions*/
28+ #define ASSIGN(a, b) a = b
29+ """
30+ void ASSIGN(defs.Vector3d& , defs.Vector3d)
31+ void ASSIGN(defs.Matrix3d& , defs.Matrix3d)
32+ # void ASSIGN[T](T&, T) # This doesn't work somehow
33+
1934# ##############################################################################
2035# Transforms
2136# ##############################################################################
@@ -25,55 +40,79 @@ cdef class Transform:
2540 def __cinit__ (self , *args ):
2641 if len (args) == 0 :
2742 self .thisptr = new defs.Transform3d()
43+ self .thisptr.setIdentity()
2844 elif len (args) == 1 :
2945 if isinstance (args[0 ], Transform):
3046 self .thisptr = new defs.Transform3d(deref((< Transform> args[0 ]).thisptr))
31- # else:
32- # data = numpy.array(args[0])
33- # if data.shape == (3,3):
34- # self.thisptr = new defs.Transform3d(numpy_to_mat3d(data))
35- # elif data.shape == (4,):
36- # self.thisptr = new defs.Transform3d(numpy_to_quaternion3d(data))
37- # elif data.shape == (3,):
38- # self.thisptr = new defs.Transform3d(numpy_to_vec3d(data))
39- # else:
40- # raise ValueError('Invalid input to Transform().')
47+ else :
48+ data = numpy.array(args[0 ])
49+ if data.shape == (3 ,3 ):
50+ self .thisptr = new defs.Transform3d()
51+ self .thisptr.setIdentity()
52+ ASSIGN(self .thisptr.linear(),
53+ numpy_to_mat3d(data))
54+ elif data.shape == (4 ,):
55+ self .thisptr = new defs.Transform3d()
56+ self .thisptr.setIdentity()
57+ ASSIGN(self .thisptr.linear(),
58+ numpy_to_quaternion3d(data).toRotationMatrix())
59+ elif data.shape == (3 ,):
60+ self .thisptr = new defs.Transform3d()
61+ self .thisptr.setIdentity()
62+ ASSIGN(self .thisptr.translation(),
63+ numpy_to_vec3d(data))
64+ else :
65+ raise ValueError (' Invalid input to Transform().' )
4166 elif len (args) == 2 :
4267 rot = numpy.array(args[0 ])
4368 trans = numpy.array(args[1 ]).squeeze()
4469 if not trans.shape == (3 ,):
4570 raise ValueError (' Translation must be (3,).' )
4671
47- # if rot.shape == (3,3):
48- # self.thisptr = new defs.Transform3d(numpy_to_mat3d(rot), numpy_to_vec3d(trans))
49- # elif rot.shape == (4,):
50- # self.thisptr = new defs.Transform3d(numpy_to_quaternion3d(rot), numpy_to_vec3d(trans))
51- # else:
52- # raise ValueError('Invalid input to Transform().')
72+ if rot.shape == (3 ,3 ):
73+ self .thisptr = new defs.Transform3d()
74+ self .thisptr.setIdentity()
75+ ASSIGN(self .thisptr.linear(),
76+ numpy_to_mat3d(rot))
77+ ASSIGN(self .thisptr.translation(),
78+ numpy_to_vec3d(trans))
79+ elif rot.shape == (4 ,):
80+ self .thisptr = new defs.Transform3d()
81+ self .thisptr.setIdentity()
82+ ASSIGN(self .thisptr.linear(),
83+ numpy_to_quaternion3d(rot).toRotationMatrix())
84+ ASSIGN(self .thisptr.translation(),
85+ numpy_to_vec3d(trans))
86+ else :
87+ raise ValueError (' Invalid input to Transform().' )
5388 else :
5489 raise ValueError (' Too many arguments to Transform().' )
5590
5691 def __dealloc__ (self ):
5792 if self .thisptr:
5893 free(self .thisptr)
5994
60- # def getRotation(self):
61- # return mat3d_to_numpy(self.thisptr.getRotation ())
95+ def getRotation (self ):
96+ return mat3d_to_numpy(self .thisptr.linear ())
6297
63- # def getTranslation(self):
64- # return vec3d_to_numpy(self.thisptr.getTranslation ())
98+ def getTranslation (self ):
99+ return vec3d_to_numpy(self .thisptr.translation ())
65100
66- # def getQuatRotation(self):
67- # return quaternion3d_to_numpy(self.thisptr.getQuatRotation())
101+ def getQuatRotation (self ):
102+ cdef defs.Quaterniond quaternion = defs.Quaterniond(self .thisptr.linear())
103+ return quaternion3d_to_numpy(quaternion)
68104
69- # def setRotation(self, R):
70- # self.thisptr.setRotation(numpy_to_mat3d(R))
105+ def setRotation (self , R ):
106+ ASSIGN(self .thisptr.linear(),
107+ numpy_to_mat3d(R))
71108
72- # def setTranslation(self, T):
73- # self.thisptr.setTranslation(numpy_to_vec3d(T))
109+ def setTranslation (self , T ):
110+ ASSIGN(self .thisptr.translation(),
111+ numpy_to_vec3d(T))
74112
75- # def setQuatRotation(self, q):
76- # self.thisptr.setQuatRotation(numpy_to_quaternion3d(q))
113+ def setQuatRotation (self , q ):
114+ ASSIGN(self .thisptr.linear(),
115+ numpy_to_quaternion3d(q).toRotationMatrix())
77116
78117# ##############################################################################
79118# Collision objects and geometries
@@ -121,12 +160,12 @@ cdef class CollisionObject:
121160 def getRotation (self ):
122161 return mat3d_to_numpy(self .thisptr.getRotation())
123162
124- # def setRotation(self, mat):
125- # self.thisptr.setRotation(numpy_to_mat3d(mat))
126- # self.thisptr.computeAABB()
163+ def setRotation (self , mat ):
164+ self .thisptr.setRotation(numpy_to_mat3d(mat))
165+ self .thisptr.computeAABB()
127166
128- # def getQuatRotation(self):
129- # return quaternion3d_to_numpy(self.thisptr.getQuatRotation())
167+ def getQuatRotation (self ):
168+ return quaternion3d_to_numpy(self .thisptr.getQuatRotation())
130169
131170 def setQuatRotation (self , q ):
132171 self .thisptr.setQuatRotation(numpy_to_quaternion3d(q))
@@ -295,10 +334,8 @@ cdef class Cylinder(CollisionGeometry):
295334 (< defs.Cylinderd* > self .thisptr).lz = < double ?> value
296335
297336cdef class Halfspace(CollisionGeometry):
298- def __cinit__ (self , n , d ):
299- self .thisptr = new defs.Halfspaced(defs.Vector3d(< double ?> n[0 ],
300- < double ?> n[1 ],
301- < double ?> n[2 ]),
337+ def __cinit__ (self , np.ndarray[double , ndim = 1 , mode = " c" ] n, d ):
338+ self .thisptr = new defs.Halfspaced(defs.Vector3d(& n[0 ]),
302339 < double ?> d)
303340
304341 property n :
@@ -316,10 +353,8 @@ cdef class Halfspace(CollisionGeometry):
316353 (< defs.Halfspaced* > self .thisptr).d = < double ?> value
317354
318355cdef class Plane(CollisionGeometry):
319- def __cinit__ (self , n , d ):
320- self .thisptr = new defs.Planed(defs.Vector3d(< double ?> n[0 ],
321- < double ?> n[1 ],
322- < double ?> n[2 ]),
356+ def __cinit__ (self , np.ndarray[double , ndim = 1 , mode = " c" ] n, d ):
357+ self .thisptr = new defs.Planed(defs.Vector3d(& n[0 ]),
323358 < double ?> d)
324359
325360 property n :
@@ -355,7 +390,8 @@ cdef class BVHModel(CollisionGeometry):
355390 return n
356391
357392 def addVertex (self , x , y , z ):
358- n = (< defs.BVHModel* > self .thisptr).addVertex(defs.Vector3d(< double ?> x, < double ?> y, < double ?> z))
393+ cdef np.ndarray[double , ndim= 1 , mode= " c" ] n = numpy.array([x, y, z])
394+ n = (< defs.BVHModel* > self .thisptr).addVertex(defs.Vector3d(& n[0 ]))
359395 return self ._check_ret_value(n)
360396
361397 def addTriangle (self , v1 , v2 , v3 ):
@@ -705,27 +741,25 @@ cdef inline bool DistanceCallBack(defs.CollisionObjectd*o1, defs.CollisionObject
705741# Helper Functions
706742# ##############################################################################
707743
708- # cdef quaternion3d_to_numpy(defs.Quaterniond q):
709- # return numpy.array([q.getW (), q.getX (), q.getY (), q.getZ ()])
744+ cdef quaternion3d_to_numpy(defs.Quaterniond q):
745+ return numpy.array([q.w (), q.x (), q.y (), q.z ()])
710746
711747cdef defs.Quaterniond numpy_to_quaternion3d(a):
712748 return defs.Quaterniond(< double ?> a[0 ], < double ?> a[1 ], < double ?> a[2 ], < double ?> a[3 ])
713749
714750cdef vec3d_to_numpy(defs.Vector3d vec):
715751 return numpy.array([vec[0 ], vec[1 ], vec[2 ]])
716752
717- cdef defs.Vector3d numpy_to_vec3d(a):
718- return defs.Vector3d(< double ? > a[0 ], < double ? > a[ 1 ], < double ? > a[ 2 ])
753+ cdef defs.Vector3d numpy_to_vec3d(np.ndarray[ double , ndim = 1 , mode = " c " ] a):
754+ return defs.Vector3d(& a[0 ])
719755
720756cdef mat3d_to_numpy(defs.Matrix3d m):
721757 return numpy.array([[m(0 ,0 ), m(0 ,1 ), m(0 ,2 )],
722758 [m(1 ,0 ), m(1 ,1 ), m(1 ,2 )],
723759 [m(2 ,0 ), m(2 ,1 ), m(2 ,2 )]])
724760
725- # cdef defs.Matrix3d numpy_to_mat3d(a):
726- # return defs.Matrix3d(<double?> a[0][0], <double?> a[0][1], <double?> a[0][2],
727- # <double?> a[1][0], <double?> a[1][1], <double?> a[1][2],
728- # <double?> a[2][0], <double?> a[2][1], <double?> a[2][2])
761+ cdef defs.Matrix3d numpy_to_mat3d(np.ndarray[double , ndim= 2 , mode= " c" ] a):
762+ return defs.Matrix3d(& a[0 , 0 ])
729763
730764cdef c_to_python_collision_geometry(defs.const_CollisionGeometryd* geom, CollisionObject o1, CollisionObject o2):
731765 cdef CollisionGeometry o1_py_geom = < CollisionGeometry> ((< defs.CollisionObjectd* > o1.thisptr).getUserData())
0 commit comments