Directory: | ./ |
---|---|
File: | include/pinocchio/bindings/python/spatial/se3.hpp |
Date: | 2024-08-27 18:20:05 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 73 | 94 | 77.7% |
Branches: | 107 | 260 | 41.2% |
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_se3_hpp__ | ||
7 | #define __pinocchio_python_spatial_se3_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/motion.hpp" | ||
15 | #include "pinocchio/spatial/force.hpp" | ||
16 | #include "pinocchio/spatial/inertia.hpp" | ||
17 | #include "pinocchio/spatial/explog.hpp" | ||
18 | |||
19 | #include "pinocchio/utils/string.hpp" | ||
20 | |||
21 | #include "pinocchio/bindings/python/utils/cast.hpp" | ||
22 | #include "pinocchio/bindings/python/utils/copyable.hpp" | ||
23 | #include "pinocchio/bindings/python/utils/printable.hpp" | ||
24 | #include "pinocchio/bindings/python/utils/namespace.hpp" | ||
25 | |||
26 | #if EIGENPY_VERSION_AT_MOST(2, 8, 1) | ||
27 | EIGENPY_DEFINE_STRUCT_ALLOCATOR_SPECIALIZATION(pinocchio::SE3) | ||
28 | #endif | ||
29 | |||
30 | namespace pinocchio | ||
31 | { | ||
32 | namespace python | ||
33 | { | ||
34 | namespace bp = boost::python; | ||
35 | |||
36 | template<typename SE3> | ||
37 | struct SE3PythonVisitor : public boost::python::def_visitor<SE3PythonVisitor<SE3>> | ||
38 | { | ||
39 | typedef typename SE3::Scalar Scalar; | ||
40 | enum | ||
41 | { | ||
42 | Options = SE3::Options | ||
43 | }; | ||
44 | typedef typename SE3::Matrix3 Matrix3; | ||
45 | typedef typename SE3::Vector3 Vector3; | ||
46 | typedef typename SE3::Matrix4 Matrix4; | ||
47 | typedef typename SE3::Quaternion Quaternion; | ||
48 | typedef typename SE3::ActionMatrixType ActionMatrixType; | ||
49 | |||
50 | typedef MotionTpl<Scalar, Options> Motion; | ||
51 | typedef ForceTpl<Scalar, Options> Force; | ||
52 | typedef InertiaTpl<Scalar, Options> Inertia; | ||
53 | |||
54 | public: | ||
55 | template<class PyClass> | ||
56 | 20 | void visit(PyClass & cl) const | |
57 | { | ||
58 | static const Scalar dummy_precision = Eigen::NumTraits<Scalar>::dummy_precision(); | ||
59 | |||
60 |
4/8✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
|
40 | cl.def(bp::init<const Matrix3 &, const Vector3 &>( |
61 |
2/4✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
60 | (bp::arg("self"), bp::arg("rotation"), bp::arg("translation")), |
62 | "Initialize from a rotation matrix and a translation vector.")) | ||
63 |
4/8✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
|
40 | .def(bp::init<const Quaternion &, const Vector3 &>( |
64 |
3/6✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
|
60 | (bp::arg("self"), bp::arg("quat"), bp::arg("translation")), |
65 | "Initialize from a quaternion and a translation vector.")) | ||
66 |
5/10✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 20 times.
✗ Branch 14 not taken.
|
40 | .def(bp::init<int>((bp::arg("self"), bp::arg("int")), "Init to identity.")) |
67 |
3/6✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
|
20 | .def(bp::init<const Matrix4 &>( |
68 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | (bp::arg("self"), bp::arg("array")), "Initialize from an homogeneous matrix.")) |
69 |
5/10✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 20 times.
✗ Branch 14 not taken.
|
40 | .def(bp::init<const SE3 &>((bp::arg("self"), bp::arg("clone")), "Copy constructor")) |
70 | |||
71 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .add_property( |
72 | "rotation", | ||
73 | bp::make_function( | ||
74 | (typename SE3::AngularRef(SE3::*)()) & SE3::rotation, | ||
75 | 20 | bp::return_internal_reference<>()), | |
76 | (void(SE3::*)(const Matrix3 &)) & SE3::rotation, | ||
77 | "The rotation part of the transformation.") | ||
78 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .add_property( |
79 | "translation", | ||
80 | bp::make_function( | ||
81 | (typename SE3::LinearRef(SE3::*)()) & SE3::translation, | ||
82 | 20 | bp::return_internal_reference<>()), | |
83 | (void(SE3::*)(const Vector3 &)) & SE3::translation, | ||
84 | "The translation part of the transformation.") | ||
85 | |||
86 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .add_property( |
87 | "homogeneous", &SE3::toHomogeneousMatrix, | ||
88 | "Returns the equivalent homegeneous matrix (acting on SE3).") | ||
89 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .add_property( |
90 | "action", (ActionMatrixType(SE3::*)() const) & SE3::toActionMatrix, | ||
91 | "Returns the related action matrix (acting on Motion).") | ||
92 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def( |
93 | "toActionMatrix", (ActionMatrixType(SE3::*)() const) & SE3::toActionMatrix, | ||
94 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | bp::arg("self"), "Returns the related action matrix (acting on Motion).") |
95 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .add_property( |
96 | "actionInverse", (ActionMatrixType(SE3::*)() const) & SE3::toActionMatrixInverse, | ||
97 | "Returns the inverse of the action matrix (acting on Motion).\n" | ||
98 | "This is equivalent to do m.inverse().action") | ||
99 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def( |
100 | "toActionMatrixInverse", | ||
101 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | (ActionMatrixType(SE3::*)() const) & SE3::toActionMatrixInverse, bp::arg("self"), |
102 | "Returns the inverse of the action matrix (acting on Motion).\n" | ||
103 | "This is equivalent to do m.inverse().toActionMatrix()") | ||
104 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .add_property( |
105 | "dualAction", (ActionMatrixType(SE3::*)() const) & SE3::toDualActionMatrix, | ||
106 | "Returns the related dual action matrix (acting on Force).") | ||
107 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def( |
108 | "toDualActionMatrix", (ActionMatrixType(SE3::*)() const) & SE3::toDualActionMatrix, | ||
109 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | bp::arg("self"), "Returns the related dual action matrix (acting on Force).") |
110 | |||
111 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
112 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | "setIdentity", &SE3PythonVisitor::setIdentity, bp::arg("self"), |
113 | "Set *this to the identity placement.") | ||
114 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def( |
115 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | "setRandom", &SE3PythonVisitor::setRandom, bp::arg("self"), |
116 | "Set *this to a random placement.") | ||
117 | |||
118 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | .def("inverse", &SE3::inverse, bp::arg("self"), "Returns the inverse transform") |
119 | |||
120 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
121 | "act", (Vector3(SE3::*)(const Vector3 &) const) & SE3::act, bp::args("self", "point"), | ||
122 | "Returns a point which is the result of the entry point transforms by *this.") | ||
123 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
124 | "actInv", (Vector3(SE3::*)(const Vector3 &) const) & SE3::actInv, | ||
125 | bp::args("self", "point"), | ||
126 | "Returns a point which is the result of the entry point by the inverse of *this.") | ||
127 | |||
128 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
129 | "act", (SE3(SE3::*)(const SE3 & other) const) & SE3::act, bp::args("self", "M"), | ||
130 | "Returns the result of *this * M.") | ||
131 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
132 | "actInv", (SE3(SE3::*)(const SE3 & other) const) & SE3::actInv, bp::args("self", "M"), | ||
133 | "Returns the result of the inverse of *this times M.") | ||
134 | |||
135 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
136 | "act", (Motion(SE3::*)(const Motion &) const) & SE3::act, bp::args("self", "motion"), | ||
137 | "Returns the result action of *this onto a Motion.") | ||
138 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
139 | "actInv", (Motion(SE3::*)(const Motion &) const) & SE3::actInv, | ||
140 | bp::args("self", "motion"), "Returns the result of the inverse of *this onto a Motion.") | ||
141 | |||
142 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
143 | "act", (Force(SE3::*)(const Force &) const) & SE3::act, bp::args("self", "force"), | ||
144 | "Returns the result of *this onto a Force.") | ||
145 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
146 | "actInv", (Force(SE3::*)(const Force &) const) & SE3::actInv, bp::args("self", "force"), | ||
147 | "Returns the result of the inverse of *this onto an Inertia.") | ||
148 | |||
149 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
150 | "act", (Inertia(SE3::*)(const Inertia &) const) & SE3::act, bp::args("self", "inertia"), | ||
151 | "Returns the result of *this onto a Force.") | ||
152 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
153 | "actInv", (Inertia(SE3::*)(const Inertia &) const) & SE3::actInv, | ||
154 | bp::args("self", "inertia"), | ||
155 | "Returns the result of the inverse of *this onto an Inertia.") | ||
156 | |||
157 | #ifndef PINOCCHIO_PYTHON_SKIP_COMPARISON_OPERATIONS | ||
158 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
159 | "isApprox", &SE3::isApprox, | ||
160 |
5/10✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 20 times.
✗ Branch 14 not taken.
|
60 | (bp::arg("self"), bp::arg("other"), bp::arg("prec") = dummy_precision), |
161 | "Returns true if *this is approximately equal to other, within the precision given " | ||
162 | "by prec.") | ||
163 | |||
164 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def( |
165 |
4/8✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
|
40 | "isIdentity", &SE3::isIdentity, (bp::arg("self"), bp::arg("prec") = dummy_precision), |
166 | "Returns true if *this is approximately equal to the identity placement, within the " | ||
167 | "precision given by prec.") | ||
168 | #endif | ||
169 | |||
170 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def("__invert__", &SE3::inverse, "Returns the inverse of *this.") |
171 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
20 | .def(bp::self * bp::self) |
172 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def("__mul__", &__mul__<Motion>) |
173 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def("__mul__", &__mul__<Force>) |
174 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def("__mul__", &__mul__<Inertia>) |
175 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def("__mul__", &__mul__<Vector3>) |
176 | 40 | .add_property("np", &SE3::toHomogeneousMatrix) | |
177 | |||
178 | #ifndef PINOCCHIO_PYTHON_SKIP_COMPARISON_OPERATIONS | ||
179 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
|
20 | .def(bp::self == bp::self) |
180 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
20 | .def(bp::self != bp::self) |
181 | #endif | ||
182 | |||
183 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def("Identity", &SE3::Identity, "Returns the identity transformation.") |
184 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .staticmethod("Identity") |
185 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def("Random", &SE3::Random, "Returns a random transformation.") |
186 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .staticmethod("Random") |
187 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
40 | .def( |
188 | "Interpolate", &SE3::template Interpolate<Scalar>, bp::args("A", "B", "alpha"), | ||
189 | "Linear interpolation on the SE3 manifold.\n\n" | ||
190 | "This method computes the linear interpolation between A and B, such that the " | ||
191 | "result C = A + (B-A)*t if it would be applied on classic Euclidian space.\n" | ||
192 | "This operation is very similar to the SLERP operation on Rotations.\n" | ||
193 | "Parameters:\n" | ||
194 | "\tA: Initial transformation\n" | ||
195 | "\tB: Target transformation\n" | ||
196 | "\talpha: Interpolation factor") | ||
197 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .staticmethod("Interpolate") |
198 | |||
199 | 40 | .def("__array__", &SE3::toHomogeneousMatrix) | |
200 |
2/4✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
|
20 | .def("__array__", &__array__) |
201 | |||
202 | #ifndef PINOCCHIO_PYTHON_NO_SERIALIZATION | ||
203 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def_pickle(Pickle()) |
204 | #endif | ||
205 | ; | ||
206 | 20 | } | |
207 | |||
208 | static std::string scopeName() | ||
209 | { | ||
210 | static std::string scope_name; | ||
211 | return scope_name; | ||
212 | } | ||
213 | |||
214 | 20 | static void expose() | |
215 | { | ||
216 | #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 6 && EIGENPY_VERSION_AT_LEAST(2, 9, 0) | ||
217 | typedef PINOCCHIO_SHARED_PTR_HOLDER_TYPE(SE3) HolderType; | ||
218 | #else | ||
219 | typedef ::boost::python::detail::not_specified HolderType; | ||
220 | #endif | ||
221 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | bp::class_<SE3, HolderType>( |
222 | "SE3", "SE3 transformation defined by a 3d vector and a rotation matrix.", | ||
223 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
40 | bp::init<>(bp::arg("self"), "Default constructor.")) |
224 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def(SE3PythonVisitor<SE3>()) |
225 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def(CastVisitor<SE3>()) |
226 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def(ExposeConstructorByCastVisitor<SE3, ::pinocchio::SE3>()) |
227 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def(CopyableVisitor<SE3>()) |
228 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
40 | .def(bp::self_ns::str(bp::self_ns::self)) |
229 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | .def("__repr__", &repr); |
230 | 20 | } | |
231 | |||
232 | private: | ||
233 | ✗ | static Matrix4 __array__(const SE3 & self, bp::object) | |
234 | { | ||
235 | ✗ | return self.toHomogeneousMatrix(); | |
236 | } | ||
237 | |||
238 | struct Pickle : bp::pickle_suite | ||
239 | { | ||
240 | ✗ | static boost::python::tuple getinitargs(const SE3 & M) | |
241 | { | ||
242 | ✗ | return bp::make_tuple((Matrix3)M.rotation(), (Vector3)M.translation()); | |
243 | } | ||
244 | |||
245 | 20 | static bool getstate_manages_dict() | |
246 | { | ||
247 | 20 | return true; | |
248 | } | ||
249 | }; | ||
250 | |||
251 | ✗ | static void setIdentity(SE3 & self) | |
252 | { | ||
253 | ✗ | self.setIdentity(); | |
254 | } | ||
255 | ✗ | static void setRandom(SE3 & self) | |
256 | { | ||
257 | ✗ | self.setRandom(); | |
258 | } | ||
259 | |||
260 | template<typename Spatial> | ||
261 | ✗ | static Spatial __mul__(const SE3 & self, const Spatial & other) | |
262 | { | ||
263 | ✗ | return self.act(other); | |
264 | } | ||
265 | |||
266 | ✗ | static std::string repr(const SE3 & self) | |
267 | { | ||
268 | // bp::object | ||
269 | // py_rotation(bp::handle<>(eigenpy::EigenToPy<Matrix3,Scalar>::convert(self.rotation()))); | ||
270 | // std::string rotation_repr = | ||
271 | // bp::extract<std::string>(py_rotation.attr("__repr__")()); | ||
272 | // | ||
273 | // bp::object | ||
274 | // py_translation(bp::handle<>(eigenpy::EigenToPy<Vector3,Scalar>::convert(self.translation()))); | ||
275 | // std::string translation_repr = | ||
276 | // bp::extract<std::string>(py_translation.attr("__repr__")()); | ||
277 | |||
278 | ✗ | bp::object py_homogeneous( | |
279 | ✗ | bp::handle<>(eigenpy::EigenToPy<Matrix4, Scalar>::convert(self.toHomogeneousMatrix()))); | |
280 | ✗ | std::string homegeneous_repr = bp::extract<std::string>(py_homogeneous.attr("__repr__")()); | |
281 | ✗ | replace(homegeneous_repr, "\n", ""); | |
282 | ✗ | replace(homegeneous_repr, " ", ""); | |
283 | |||
284 | ✗ | std::stringstream ss_repr; | |
285 | ✗ | ss_repr << "SE3("; | |
286 | ✗ | ss_repr << homegeneous_repr; | |
287 | ✗ | ss_repr << ")"; | |
288 | |||
289 | ✗ | return ss_repr.str(); | |
290 | } | ||
291 | }; | ||
292 | |||
293 | } // namespace python | ||
294 | } // namespace pinocchio | ||
295 | |||
296 | #endif // ifndef __pinocchio_python_spatial_se3_hpp__ | ||
297 |