Skip to content

Commit ebbf206

Browse files
DmitryNeverovCyrilWaechter
authored andcommitted
Fixed Transform extension type:
Vector3, Matrix3, Quaternion and Transform are now native Eigen objects in FCL, so helper functions were changed accordingly.
1 parent 6fa5416 commit ebbf206

2 files changed

Lines changed: 96 additions & 73 deletions

File tree

fcl/fcl.pyx

Lines changed: 84 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ cimport octomap_defs as octomap
1616
cimport std_defs as std
1717
from 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

297336
cdef 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

318355
cdef 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

711747
cdef defs.Quaterniond numpy_to_quaternion3d(a):
712748
return defs.Quaterniond(<double?> a[0], <double?> a[1], <double?> a[2], <double?> a[3])
713749

714750
cdef 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

720756
cdef 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

730764
cdef 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())

fcl/fcl_defs.pxd

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,41 +21,30 @@ cdef extern from "Python.h":
2121
cdef extern from "fcl/common/types.h" namespace "fcl":
2222
cdef cppclass Vector3d:
2323
Vector3d() except +
24-
Vector3d(double x, double y, double z) except +
24+
Vector3d(double *data) except +
2525
double& operator[](size_t i)
2626

2727
cdef cppclass Matrix3d:
2828
Matrix3d() except +
29-
# Matrix3d(double xx, double xy, double xz,
30-
# double yx, double yy, double yz,
31-
# double zx, double zy, double zz) except +
29+
Matrix3d(double *data)
3230
double operator()(size_t i, size_t j)
3331

3432
cdef cppclass Quaterniond:
3533
Quaterniond() except +
36-
Quaterniond(double a, double b,
37-
double c, double d) except +
38-
void fromRotation(Matrix3d& R)
39-
void fromAxisAngle(Vector3d& axis, double angle)
40-
# double& getW()
41-
# double& getX()
42-
# double& getY()
43-
# double& getZ()
34+
Quaterniond(double a, double b, double c, double d) except +
35+
Quaterniond(Matrix3d& R) except +
36+
double& w()
37+
double& x()
38+
double& y()
39+
double& z()
40+
Matrix3d& toRotationMatrix()
4441

4542
cdef cppclass Transform3d:
4643
Transform3d() except +
47-
# Transform3d(Matrix3d& R_, Vector3d& T_)
48-
# Transform3d(Quaterniond& q_, Vector3d& T_)
49-
# Transform3d(Matrix3d& R_)
50-
# Transform3d(Quaterniond& q_)
51-
# Transform3d(Vector3d& T_)
5244
Transform3d(Transform3d& tf_)
53-
# Matrix3d& getRotation()
54-
# Vector3d& getTranslation()
55-
# Quaterniond& getQuatRotation()
56-
# void setRotation(Matrix3d& R_)
57-
# void setTranslation(Vector3d& T_)
58-
# void setQuatRotation(Quaterniond & q_)
45+
void setIdentity()
46+
Matrix3d& linear()
47+
Vector3d& translation()
5948

6049
cdef extern from "fcl/narrowphase/continuous_collision_request.h" namespace "fcl":
6150
cdef enum CCDMotionType:

0 commit comments

Comments
 (0)