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