GCC Code Coverage Report


Directory: ./
File: include/pinocchio/bindings/python/spatial/motion.hpp
Date: 2025-02-12 21:03:38
Exec Total Coverage
Lines: 90 96 93.8%
Branches: 102 211 48.3%

Line Branch Exec Source
1 //
2 // Copyright (c) 2015-2024 CNRS INRIA
3 // Copyright (c) 2016 Wandercraft, 86 rue de Paris 91400 Orsay, France.
4 //
5
6 #ifndef __pinocchio_python_spatial_motion_hpp__
7 #define __pinocchio_python_spatial_motion_hpp__
8
9 #include <eigenpy/eigenpy.hpp>
10 #include <eigenpy/memory.hpp>
11 #include <boost/python/tuple.hpp>
12 #include <boost/python/implicit.hpp>
13
14 #include "pinocchio/spatial/se3.hpp"
15 #include "pinocchio/spatial/motion.hpp"
16 #include "pinocchio/spatial/force.hpp"
17
18 #include "pinocchio/bindings/python/utils/cast.hpp"
19 #include "pinocchio/bindings/python/utils/copyable.hpp"
20 #include "pinocchio/bindings/python/utils/printable.hpp"
21
22 #if EIGENPY_VERSION_AT_MOST(2, 8, 1)
23 EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(pinocchio::Motion)
24 #endif
25
26 namespace pinocchio
27 {
28 namespace python
29 {
30 namespace bp = boost::python;
31
32 template<typename T>
33 struct call;
34
35 template<typename Scalar, int Options>
36 struct call<MotionTpl<Scalar, Options>>
37 {
38 typedef MotionTpl<Scalar, Options> Motion;
39
40 static bool isApprox(
41 const Motion & self,
42 const Motion & other,
43 const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision())
44 {
45 return self.isApprox(other, prec);
46 }
47
48 static bool
49 isZero(const Motion & self, const Scalar & prec = Eigen::NumTraits<Scalar>::dummy_precision())
50 {
51 return self.isZero(prec);
52 }
53 };
54
55 template<typename Motion>
56 struct MotionPythonVisitor : public boost::python::def_visitor<MotionPythonVisitor<Motion>>
57 {
58 enum
59 {
60 Options = traits<Motion>::Options
61 };
62
63 typedef typename Motion::Scalar Scalar;
64 typedef ForceTpl<Scalar, Options> Force;
65 typedef typename Motion::Vector6 Vector6;
66 typedef typename Motion::Vector3 Vector3;
67
68 typedef typename Eigen::Map<Vector3> MapVector3;
69 typedef typename Eigen::Ref<Vector3> RefVector3;
70
71 public:
72 template<class PyClass>
73 69 void visit(PyClass & cl) const
74 {
75
3/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
4 static const Scalar dummy_precision = Eigen::NumTraits<Scalar>::dummy_precision();
76 PINOCCHIO_COMPILER_DIAGNOSTIC_PUSH
77 PINOCCHIO_COMPILER_DIAGNOSTIC_IGNORED_SELF_ASSIGN_OVERLOADED
78
2/4
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 69 times.
✗ Branch 6 not taken.
69 cl.def(bp::init<>(bp::arg("self"), "Default constructor"))
79
4/8
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 69 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 69 times.
✗ Branch 11 not taken.
138 .def(bp::init<const Vector3 &, const Vector3 &>(
80
3/6
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 69 times.
✗ Branch 8 not taken.
207 (bp::arg("self"), bp::arg("linear"), bp::arg("angular")),
81 "Initialize from linear and angular components of a Motion vector (don't mix the "
82 "order)."))
83
3/6
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 69 times.
✗ Branch 8 not taken.
69 .def(bp::init<const Vector6 &>(
84
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
138 (bp::arg("self"), bp::arg("array")),
85 "Init from a vector 6 [linear velocity, angular velocity]"))
86
5/10
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 69 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 69 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 69 times.
✗ Branch 14 not taken.
138 .def(bp::init<const Motion &>((bp::arg("self"), bp::arg("clone")), "Copy constructor"))
87
88
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
69 .add_property(
89 "linear",
90 bp::make_function(
91 69 &MotionPythonVisitor::getLinear, bp::with_custodian_and_ward_postcall<0, 1>()),
92 &MotionPythonVisitor::setLinear,
93 "Linear part of a *this, corresponding to the linear velocity in case of a "
94 "Spatial velocity.")
95
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
69 .add_property(
96 "angular",
97 bp::make_function(
98 69 &MotionPythonVisitor::getAngular, bp::with_custodian_and_ward_postcall<0, 1>()),
99 &MotionPythonVisitor::setAngular,
100 "Angular part of a *this, corresponding to the angular velocity in case of "
101 "a Spatial velocity.")
102
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
69 .add_property(
103 "vector",
104 bp::make_function(
105 (typename Motion::ToVectorReturnType(Motion::*)()) & Motion::toVector,
106 69 bp::return_internal_reference<>()),
107 &MotionPythonVisitor::setVector, "Returns the components of *this as a 6d vector.")
108
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
69 .add_property(
109 "np", bp::make_function(
110 (typename Motion::ToVectorReturnType(Motion::*)()) & Motion::toVector,
111 69 bp::return_internal_reference<>()))
112
113
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
138 .def(
114 "se3Action", &Motion::template se3Action<Scalar, Options>, bp::args("self", "M"),
115 "Returns the result of the action of M on *this.")
116
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
138 .def(
117 "se3ActionInverse", &Motion::template se3ActionInverse<Scalar, Options>,
118 bp::args("self", "M"), "Returns the result of the action of the inverse of M on *this.")
119
120
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .add_property(
121 "action", &Motion::toActionMatrix,
122 "Returns the action matrix of *this (acting on Motion).")
123
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .add_property(
124 "dualAction", &Motion::toDualActionMatrix,
125 "Returns the dual action matrix of *this (acting on Force).")
126
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .add_property(
127 "homogeneous", &Motion::toHomogeneousMatrix,
128 "Equivalent homogeneous representation of the Motion vector")
129
130
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
138 .def(
131
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
138 "setZero", &MotionPythonVisitor::setZero, bp::arg("self"),
132 "Set the linear and angular components of *this to zero.")
133
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def(
134
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
138 "setRandom", &MotionPythonVisitor::setRandom, bp::arg("self"),
135 "Set the linear and angular components of *this to random values.")
136
137
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
138 .def(
138 "dot", (Scalar(Motion::*)(const ForceBase<Force> &) const)&Motion::dot,
139 bp::args("self", "f"), "Dot product between *this and a Force f.")
140
141
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
138 .def(
142 "cross", (Motion(Motion::*)(const Motion &) const)&Motion::cross, bp::args("self", "m"),
143 "Action of *this onto another Motion m. Returns ¨*this x m.")
144
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
138 .def(
145 "cross", (Force(Motion::*)(const Force &) const)&Motion::cross, bp::args("self", "f"),
146 "Dual action of *this onto a Force f. Returns *this x* f.")
147
148
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 69 times.
✗ Branch 6 not taken.
69 .def(bp::self + bp::self)
149
1/2
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
69 .def(bp::self += bp::self)
150
1/2
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
69 .def(bp::self - bp::self)
151
1/2
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
69 .def(bp::self -= bp::self)
152
1/2
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
69 .def(-bp::self)
153
1/2
✓ Branch 2 taken 69 times.
✗ Branch 3 not taken.
69 .def(bp::self ^ bp::self)
154
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 69 times.
✗ Branch 6 not taken.
73 .def(bp::self ^ Force())
155
156 #ifndef PINOCCHIO_PYTHON_SKIP_COMPARISON_OPERATIONS
157
1/2
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
65 .def(bp::self == bp::self)
158
1/2
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
65 .def(bp::self != bp::self)
159 #endif
160
161
3/5
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
73 .def(bp::self * Scalar())
162
3/5
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
73 .def(Scalar() * bp::self)
163
3/5
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
73 .def(bp::self / Scalar())
164
165 #ifndef PINOCCHIO_PYTHON_SKIP_COMPARISON_OPERATIONS
166
2/4
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
130 .def(
167 "isApprox", &call<Motion>::isApprox,
168
5/10
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 65 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 65 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 65 times.
✗ Branch 14 not taken.
195 (bp::arg("self"), bp::arg("other"), bp::arg("prec") = dummy_precision),
169 "Returns true if *this is approximately equal to other, within the precision given "
170 "by prec.")
171
172
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 .def(
173
4/8
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 65 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 65 times.
✗ Branch 11 not taken.
130 "isZero", &call<Motion>::isZero, (bp::arg("self"), bp::arg("prec") = dummy_precision),
174 "Returns true if *this is approximately equal to the zero Motion, within the "
175 "precision given by prec.")
176 #endif
177
178
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def("Random", &Motion::Random, "Returns a random Motion.")
179
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .staticmethod("Random")
180
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def("Zero", &Motion::Zero, "Returns a zero Motion.")
181
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .staticmethod("Zero")
182
183
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
69 .def(
184 "__array__", bp::make_function(
185 (typename Motion::ToVectorReturnType(Motion::*)()) & Motion::toVector,
186 69 bp::return_internal_reference<>()))
187
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def(
188 "__array__", &__array__,
189
9/18
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 69 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 69 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 69 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 69 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 69 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 69 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 69 times.
✗ Branch 26 not taken.
138 (bp::arg("self"), bp::arg("dtype") = bp::object(), bp::arg("copy") = bp::object()),
190 69 bp::return_internal_reference<>())
191 #ifndef PINOCCHIO_PYTHON_NO_SERIALIZATION
192
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 .def_pickle(Pickle())
193 #endif
194 ;
195 PINOCCHIO_COMPILER_DIAGNOSTIC_POP
196 69 }
197
198 69 static void expose()
199 {
200 typedef pinocchio::MotionBase<Motion> MotionBase;
201 69 bp::objects::register_dynamic_id<MotionBase>();
202 69 bp::objects::register_conversion<Motion, MotionBase>(false);
203
204 typedef pinocchio::MotionDense<Motion> MotionDense;
205 69 bp::objects::register_dynamic_id<MotionDense>();
206 69 bp::objects::register_conversion<Motion, MotionDense>(false);
207
208 #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 6 && EIGENPY_VERSION_AT_LEAST(2, 9, 0)
209 typedef PINOCCHIO_SHARED_PTR_HOLDER_TYPE(Motion) HolderType;
210 #else
211 typedef ::boost::python::detail::not_specified HolderType;
212 #endif
213 69 bp::class_<Motion, HolderType>(
214 "Motion",
215 "Motion vectors, in se3 == M^6.\n\n"
216 "Supported operations ...",
217 bp::no_init)
218
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def(MotionPythonVisitor<Motion>())
219
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def(CastVisitor<Motion>())
220
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def(ExposeConstructorByCastVisitor<Motion, ::pinocchio::Motion>())
221
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def(CopyableVisitor<Motion>())
222
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 .def(PrintableVisitor<Motion>());
223 69 }
224
225 private:
226 static typename Motion::ToVectorConstReturnType
227 3 __array__(const Motion & self, bp::object, bp::object)
228 {
229 3 return self.toVector();
230 }
231
232 struct Pickle : bp::pickle_suite
233 {
234 static boost::python::tuple getinitargs(const Motion & m)
235 {
236 return bp::make_tuple((Vector3)m.linear(), (Vector3)m.angular());
237 }
238
239 65 static bool getstate_manages_dict()
240 {
241 65 return true;
242 }
243 };
244
245 7 static RefVector3 getLinear(Motion & self)
246 {
247
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
14 return self.linear();
248 }
249 1 static void setLinear(Motion & self, const Vector3 & v)
250 {
251 1 self.linear(v);
252 1 }
253 7 static RefVector3 getAngular(Motion & self)
254 {
255
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
14 return self.angular();
256 }
257 1 static void setAngular(Motion & self, const Vector3 & w)
258 {
259 1 self.angular(w);
260 1 }
261
262 1 static void setVector(Motion & self, const Vector6 & v)
263 {
264 1 self = v;
265 1 }
266
267 1 static void setZero(Motion & self)
268 {
269 1 self.setZero();
270 1 }
271 2 static void setRandom(Motion & self)
272 {
273 2 self.setRandom();
274 2 }
275 };
276
277 } // namespace python
278 } // namespace pinocchio
279
280 #endif // ifndef __pinocchio_python_spatial_motion_hpp__
281