pinocchio  3.9.0
A fast and flexible implementation of Rigid Body Dynamics algorithms and their analytical derivatives
Loading...
Searching...
No Matches
joint-ellipsoid.hpp
1//
2// Copyright (c) 2025 INRIA
3//
4
5#ifndef __pinocchio_multibody_joint_ellipsoid_hpp__
6#define __pinocchio_multibody_joint_ellipsoid_hpp__
7
8#include "pinocchio/macros.hpp"
9#include "pinocchio/multibody/joint/joint-base.hpp"
10#include "pinocchio/multibody/joint-motion-subspace-base.hpp"
11#include "pinocchio/math/sincos.hpp"
12#include "pinocchio/math/matrix.hpp"
13#include "pinocchio/spatial/spatial-axis.hpp"
14
15namespace pinocchio
16{
17 template<typename Scalar, int Options>
19
20 template<typename Scalar, int Options>
22
23 template<typename Scalar, int Options>
25 {
26 typedef Eigen::Matrix<Scalar, 6, 3, Options> ReturnType;
27 };
28
29 template<typename Scalar, int Options, typename MotionDerived>
31 {
32 typedef Eigen::Matrix<Scalar, 6, 3, Options> ReturnType;
33 };
34
35 template<typename Scalar, int Options, typename ForceDerived>
37 {
38 typedef Eigen::Matrix<Scalar, 3, 1, Options> ReturnType;
39 };
40
41 template<typename Scalar, int Options, typename ForceSet>
43 {
44 typedef typename traits<JointMotionSubspaceEllipsoidTpl<Scalar, Options>>::DenseBase DenseBase;
45 typedef
47 };
48
49 template<typename _Scalar, int _Options>
50 struct traits<JointMotionSubspaceEllipsoidTpl<_Scalar, _Options>>
51 {
52 typedef _Scalar Scalar;
53 enum
54 {
55 Options = _Options
56 };
57 enum
58 {
59 LINEAR = 0,
60 ANGULAR = 3
61 };
62
63 typedef MotionTpl<Scalar, Options> JointMotion;
64 typedef Eigen::Matrix<Scalar, 3, 1, Options> JointForce;
65 typedef Eigen::Matrix<Scalar, 6, 3, Options> DenseBase;
66 typedef Eigen::Matrix<Scalar, 3, 3, Options> ReducedSquaredMatrix;
67
68 typedef DenseBase MatrixReturnType;
69 typedef const DenseBase ConstMatrixReturnType;
70
71 typedef ReducedSquaredMatrix StDiagonalMatrixSOperationReturnType;
72 };
73
74 template<typename _Scalar, int _Options>
76 : JointMotionSubspaceBase<JointMotionSubspaceEllipsoidTpl<_Scalar, _Options>>
77 {
78 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
79
80 PINOCCHIO_CONSTRAINT_TYPEDEF_TPL(JointMotionSubspaceEllipsoidTpl)
81 enum
82 {
83 NV = 3
84 };
85
86 typedef SpatialAxis<5> AxisRotZ;
87
88 typedef Eigen::Matrix<Scalar, 6, 3, Options> Matrix63;
89 Matrix63 S;
90
91 template<typename Vector3Like>
92 JointMotion __mult__(const Eigen::MatrixBase<Vector3Like> & v) const
93 {
94 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Vector3Like, 3);
95 // Compute first 6 rows from first 2 columns
96 Eigen::Matrix<Scalar, 6, 1> result = S.template leftCols<2>() * v.template head<2>();
97
98 // Add contribution from last column (only row 5 is non-zero: S(5,2) = 1)
99 result[5] += v[2];
100
101 return JointMotion(result);
102 }
103
104 template<typename S1, int O1>
105 typename SE3GroupAction<JointMotionSubspaceEllipsoidTpl>::ReturnType
106 se3Action(const SE3Tpl<S1, O1> & m) const
107 {
108 typedef typename SE3GroupAction<JointMotionSubspaceEllipsoidTpl>::ReturnType ReturnType;
109 ReturnType res;
110 // Apply SE3 action to first two columns
111 motionSet::se3Action(m, S.template leftCols<2>(), res.template leftCols<2>());
112
113 res.template block<3, 1>(LINEAR, 2).noalias() = m.translation().cross(m.rotation().col(2));
114 res.template block<3, 1>(ANGULAR, 2) = m.rotation().col(2);
115
116 return res;
117 }
118
119 template<typename S1, int O1>
120 typename SE3GroupAction<JointMotionSubspaceEllipsoidTpl>::ReturnType
121 se3ActionInverse(const SE3Tpl<S1, O1> & m) const
122 {
123 typedef typename SE3GroupAction<JointMotionSubspaceEllipsoidTpl>::ReturnType ReturnType;
124 ReturnType res;
125 // Apply inverse SE3 action to first two columns
126 motionSet::se3ActionInverse(m, S.template leftCols<2>(), res.template leftCols<2>());
127
128 // Third column: inverse action on [0, 0, 0, 0, 0, 1]^T
129 res.template block<3, 1>(LINEAR, 2).noalias() =
130 m.rotation().transpose() * AxisRotZ::CartesianAxis3::cross(m.translation());
131 res.template block<3, 1>(ANGULAR, 2) = m.rotation().transpose().col(2);
132
133 return res;
134 }
135
136 int nv_impl() const
137 {
138 return NV;
139 }
140
141 struct TransposeConst : JointMotionSubspaceTransposeBase<JointMotionSubspaceEllipsoidTpl>
142 {
144 explicit TransposeConst(const JointMotionSubspaceEllipsoidTpl & ref)
145 : ref(ref)
146 {
147 }
148
149 template<typename ForceDerived>
150 typename ConstraintForceOp<JointMotionSubspaceEllipsoidTpl, ForceDerived>::ReturnType
151 operator*(const ForceDense<ForceDerived> & f) const
152 {
153 typedef
154 typename ConstraintForceOp<JointMotionSubspaceEllipsoidTpl, ForceDerived>::ReturnType
156 ReturnType res;
157
158 // First two rows: S[:, 0:2]^T * f
159 res.template head<2>().noalias() = ref.S.template leftCols<2>().transpose() * f.toVector();
160
161 // Third row: [0,0,0,0,0,1]^T · f = f.angular()[2]
162 res[2] = f.angular()[2];
163
164 return res;
165 }
166
167 template<typename ForceSet>
168 typename ConstraintForceSetOp<JointMotionSubspaceEllipsoidTpl, ForceSet>::ReturnType
169 operator*(const Eigen::MatrixBase<ForceSet> & F)
170 {
171 assert(F.rows() == 6);
172 return ref.S.transpose() * F.derived();
173 }
174 }; // struct TransposeConst
175
176 TransposeConst transpose() const
177 {
178 return TransposeConst(*this);
179 }
180
181 /* CRBA joint operators
182 * - ForceSet::Block = ForceSet
183 * - ForceSet operator* (Inertia Y,Constraint S)
184 * - MatrixBase operator* (Constraint::Transpose S, ForceSet::Block)
185 * - SE3::act(ForceSet::Block)
186 */
187 DenseBase matrix_impl() const
188 {
189 return S;
190 }
191
192 template<typename MotionDerived>
193 typename MotionAlgebraAction<JointMotionSubspaceEllipsoidTpl, MotionDerived>::ReturnType
194 motionAction(const MotionDense<MotionDerived> & m) const
195 {
196 typedef
197 typename MotionAlgebraAction<JointMotionSubspaceEllipsoidTpl, MotionDerived>::ReturnType
198 ReturnType;
199 ReturnType res;
200
201 // Motion action on first two columns
202 motionSet::motionAction(m, S.template leftCols<2>(), res.template leftCols<2>());
203
204 // We have to use a MotionRef to deal with the output of the cross product
205 MotionRef<typename ReturnType::ColXpr> v_col2(res.col(2));
206 v_col2 = m.cross(AxisRotZ());
207
208 return res;
209 }
210
211 bool isEqual(const JointMotionSubspaceEllipsoidTpl & other) const
212 {
213 return S == other.S;
214 }
215
216 }; // struct JointMotionSubspaceEllipsoidTpl
217
218 namespace details
219 {
220 template<typename Scalar, int Options>
222 {
225
226 static ReturnType run(const JointMotionSubspaceBase<Constraint> & S)
227 {
228 // Exploit sparse structure of last column: [0,0,0,0,0,1]^T
229 ReturnType res;
230 const auto & SMatrix = S.matrix();
231
232 // Upper-left dense 2x2 block: S^T * S
233 res.template topLeftCorner<2, 2>().noalias() =
234 SMatrix.template leftCols<2>().transpose() * SMatrix.template leftCols<2>();
235
236 // Third column/row: S(5, 0), S(5, 1), 1
237 res(0, 2) = SMatrix(5, 0);
238 res(1, 2) = SMatrix(5, 1);
239 res(2, 2) = Scalar(1);
240 res(2, 0) = res(0, 2);
241 res(2, 1) = res(1, 2);
242
243 return res;
244 }
245 };
246 } // namespace details
247
248 /* [CRBA] ForceSet operator* (Inertia Y, Constraint S) */
249 template<typename S1, int O1, typename S2, int O2>
250 Eigen::Matrix<S1, 6, 3, O1>
252 {
253 typedef Eigen::Matrix<S1, 6, 3, O1> ReturnType;
254 ReturnType res(6, S.nv());
255 motionSet::inertiaAction(Y, S.S, res);
256 return res;
257 }
258
259 /* [ABA] Y*S operator (Matrix6 Y, Constraint S) */
260 template<typename Matrix6Like, typename S2, int O2>
261 typename MatrixMatrixProduct<
262 Matrix6Like,
263 typename JointMotionSubspaceEllipsoidTpl<S2, O2>::DenseBase>::type
264 operator*(
265 const Eigen::MatrixBase<Matrix6Like> & Y, const JointMotionSubspaceEllipsoidTpl<S2, O2> & S)
266 {
267 EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix6Like, 6, 6);
268 return Y * S.S;
269 }
270
271 template<typename _Scalar, int _Options>
272 struct traits<JointEllipsoidTpl<_Scalar, _Options>>
273 {
274 enum
275 {
276 NQ = 3,
277 NV = 3,
278 NVExtended = 3
279 };
280 typedef _Scalar Scalar;
281 enum
282 {
283 Options = _Options
284 };
285 typedef JointDataEllipsoidTpl<Scalar, Options> JointDataDerived;
286 typedef JointModelEllipsoidTpl<Scalar, Options> JointModelDerived;
288
289 typedef SE3Tpl<Scalar, Options> Transformation_t;
290
291 typedef MotionTpl<Scalar, Options> Motion_t;
292 typedef MotionTpl<Scalar, Options> Bias_t;
293
294 // [ABA]
295 typedef Eigen::Matrix<Scalar, 6, NV, Options> U_t;
296 typedef Eigen::Matrix<Scalar, NV, NV, Options> D_t;
297 typedef Eigen::Matrix<Scalar, 6, NV, Options> UD_t;
298
299 typedef Eigen::Matrix<Scalar, NQ, 1, Options> ConfigVector_t;
300 typedef Eigen::Matrix<Scalar, NV, 1, Options> TangentVector_t;
301
302 typedef boost::mpl::false_ is_mimicable_t; // not mimicable
303
304 PINOCCHIO_JOINT_DATA_BASE_ACCESSOR_DEFAULT_RETURN_TYPE
305 };
306
307 template<typename _Scalar, int _Options>
308 struct traits<JointDataEllipsoidTpl<_Scalar, _Options>>
309 {
310 typedef JointEllipsoidTpl<_Scalar, _Options> JointDerived;
311 typedef _Scalar Scalar;
312 };
313
314 template<typename _Scalar, int _Options>
315 struct traits<JointModelEllipsoidTpl<_Scalar, _Options>>
316 {
317 typedef JointEllipsoidTpl<_Scalar, _Options> JointDerived;
318 typedef _Scalar Scalar;
319 };
320
321 template<typename _Scalar, int _Options>
322 struct JointDataEllipsoidTpl : public JointDataBase<JointDataEllipsoidTpl<_Scalar, _Options>>
323 {
324 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
325 typedef JointEllipsoidTpl<_Scalar, _Options> JointDerived;
326 PINOCCHIO_JOINT_DATA_TYPEDEF_TEMPLATE(JointDerived);
327 PINOCCHIO_JOINT_DATA_BASE_DEFAULT_ACCESSOR
328
329 ConfigVector_t joint_q;
330 TangentVector_t joint_v;
331
332 Constraint_t S;
333 Transformation_t M;
334 Motion_t v;
335 Bias_t c;
336
337 // [ABA] specific data
338 U_t U;
339 D_t Dinv;
340 UD_t UDinv;
341 D_t StU;
342
343 JointDataEllipsoidTpl()
344 : joint_q(ConfigVector_t::Zero())
345 , joint_v(TangentVector_t::Zero())
346 , S()
347 , M(Transformation_t::Identity())
348 , v(Motion_t::Zero())
349 , c(Bias_t::Zero())
350 , U(U_t::Zero())
351 , Dinv(D_t::Zero())
352 , UDinv(UD_t::Zero())
353 , StU(D_t::Zero())
354 {
355 }
356
357 static std::string classname()
358 {
359 return std::string("JointDataEllipsoid");
360 }
361 std::string shortname() const
362 {
363 return classname();
364 }
365
366 }; // struct JointDataEllipsoidTpl
367
368 PINOCCHIO_JOINT_CAST_TYPE_SPECIALIZATION(JointModelEllipsoidTpl);
388 template<typename _Scalar, int _Options>
389 struct JointModelEllipsoidTpl : public JointModelBase<JointModelEllipsoidTpl<_Scalar, _Options>>
390 {
391 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
392 typedef JointEllipsoidTpl<_Scalar, _Options> JointDerived;
393 PINOCCHIO_JOINT_TYPEDEF_TEMPLATE(JointDerived);
394
396 using Base::id;
397 using Base::idx_q;
398 using Base::idx_v;
399 using Base::idx_vExtended;
400 using Base::setIndexes;
401
402 typedef typename Transformation_t::Vector3 Vector3;
403
404 Scalar radius_x;
405 Scalar radius_y;
406 Scalar radius_z;
407
408 JointDataDerived createData() const
409 {
410 return JointDataDerived();
411 }
412
415 : radius_x(Scalar(0.0))
416 , radius_y(Scalar(0.0))
417 , radius_z(Scalar(0.0))
418 {
419 }
420
426 const Scalar & radius_x, const Scalar & radius_y, const Scalar & radius_z)
427 : radius_x(radius_x)
428 , radius_y(radius_y)
429 , radius_z(radius_z)
430 {
431 }
432
433 const std::vector<bool> hasConfigurationLimit() const
434 {
435 return {true, true, true};
436 }
437
438 const std::vector<bool> hasConfigurationLimitInTangent() const
439 {
440 return {true, true, true};
441 }
442
449 const Scalar & c0,
450 const Scalar & s0,
451 const Scalar & c1,
452 const Scalar & s1,
453 const Scalar & c2,
454 const Scalar & s2,
455 JointDataDerived & data) const
456 {
457 // clang-format off
458 data.M.rotation() << c1 * c2 , -c1 * s2 , s1 ,
459 c0 * s2 + c2 * s0 * s1 , c0 * c2 - s0 * s1 * s2 ,-c1 * s0 ,
460 -c0 * c2 * s1 + s0 * s2 , c0 * s1 * s2 + c2 * s0 , c0 * c1;
461 // clang-format on
462 Scalar nx, ny, nz;
463 nx = s1;
464 ny = -s0 * c1;
465 nz = c0 * c1;
466
467 data.M.translation() << radius_x * nx, radius_y * ny, radius_z * nz;
468 }
469
470 template<typename ConfigVector>
471 void calc(JointDataDerived & data, const typename Eigen::MatrixBase<ConfigVector> & qs) const
472 {
473 data.joint_q = qs.template segment<NQ>(idx_q());
474
475 Scalar c0, s0;
476 SINCOS(data.joint_q(0), &s0, &c0);
477 Scalar c1, s1;
478 SINCOS(data.joint_q(1), &s1, &c1);
479 Scalar c2, s2;
480 SINCOS(data.joint_q(2), &s2, &c2);
481
482 computeSpatialTransform(c0, s0, c1, s1, c2, s2, data);
483
484 computeMotionSubspace(s0, c0, s1, c1, s2, c2, data);
485 }
486
487 template<typename TangentVector>
488 void
489 calc(JointDataDerived & data, const Blank, const typename Eigen::MatrixBase<TangentVector> & vs)
490 const
491 {
492 data.joint_v = vs.template segment<NV>(idx_v());
493
494 // Compute S from already-set joint_q
495 Scalar c0, s0;
496 SINCOS(data.joint_q(0), &s0, &c0);
497 Scalar c1, s1;
498 SINCOS(data.joint_q(1), &s1, &c1);
499 Scalar c2, s2;
500 SINCOS(data.joint_q(2), &s2, &c2);
501
502 Scalar dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0, dndotz_dqdot1;
503 dndotx_dqdot1 = c1;
504 dndoty_dqdot0 = -c0 * c1;
505 dndoty_dqdot1 = s0 * s1;
506 dndotz_dqdot0 = -c1 * s0;
507 dndotz_dqdot1 = -c0 * s1;
508
509 computeMotionSubspace(
510 s0, c0, s1, c1, s2, c2, dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0,
511 dndotz_dqdot1, data);
512
513 // Velocity part
514 data.v.toVector().noalias() = data.S.matrix() * data.joint_v;
515
517 s0, c0, s1, c1, s2, c2, dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0,
518 dndotz_dqdot1, data);
519 }
520
521 template<typename ConfigVector, typename TangentVector>
522 void calc(
523 JointDataDerived & data,
524 const typename Eigen::MatrixBase<ConfigVector> & qs,
525 const typename Eigen::MatrixBase<TangentVector> & vs) const
526 {
527 data.joint_q = qs.template segment<NQ>(idx_q());
528
529 Scalar c0, s0;
530 SINCOS(data.joint_q(0), &s0, &c0);
531 Scalar c1, s1;
532 SINCOS(data.joint_q(1), &s1, &c1);
533 Scalar c2, s2;
534 SINCOS(data.joint_q(2), &s2, &c2);
535
536 computeSpatialTransform(c0, s0, c1, s1, c2, s2, data);
537
538 Scalar dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0, dndotz_dqdot1;
539 dndotx_dqdot1 = c1;
540 dndoty_dqdot0 = -c0 * c1;
541 dndoty_dqdot1 = s0 * s1;
542 dndotz_dqdot0 = -c1 * s0;
543 dndotz_dqdot1 = -c0 * s1;
544
545 computeMotionSubspace(
546 s0, c0, s1, c1, s2, c2, dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0,
547 dndotz_dqdot1, data);
548
549 // Velocity part
550 data.joint_v = vs.template segment<NV>(idx_v());
551 data.v.toVector().noalias() = data.S.matrix() * data.joint_v;
552
554 s0, c0, s1, c1, s2, c2, dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0,
555 dndotz_dqdot1, data);
556 }
557
558 template<typename VectorLike, typename Matrix6Like>
559 void calc_aba(
560 JointDataDerived & data,
561 const Eigen::MatrixBase<VectorLike> & armature,
562 const Eigen::MatrixBase<Matrix6Like> & I,
563 const bool update_I) const
564 {
565 data.U.noalias() = I * data.S.matrix();
566 data.StU.noalias() = data.S.transpose() * data.U;
567 data.StU.diagonal() += armature;
568 internal::PerformStYSInversion<Scalar>::run(data.StU, data.Dinv);
569
570 data.UDinv.noalias() = data.U * data.Dinv;
571
572 if (update_I)
573 PINOCCHIO_EIGEN_CONST_CAST(Matrix6Like, I).noalias() -= data.UDinv * data.U.transpose();
574 }
575
576 static std::string classname()
577 {
578 return std::string("JointModelEllipsoid");
579 }
580 std::string shortname() const
581 {
582 return classname();
583 }
584
586 template<typename NewScalar>
588 {
590 ReturnType res{
591 ScalarCast<NewScalar, Scalar>::cast(radius_x),
592 ScalarCast<NewScalar, Scalar>::cast(radius_y),
593 ScalarCast<NewScalar, Scalar>::cast(radius_z)};
594 res.setIndexes(id(), idx_q(), idx_v(), idx_vExtended());
595 return res;
596 }
597
598 void computeMotionSubspace(
599 const Scalar & s0,
600 const Scalar & c0,
601 const Scalar & s1,
602 const Scalar & c1,
603 const Scalar & s2,
604 const Scalar & c2,
605 JointDataDerived & data) const
606 {
607
608 Scalar dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0, dndotz_dqdot1;
609 dndotx_dqdot1 = c1;
610 dndoty_dqdot0 = -c0 * c1;
611 dndoty_dqdot1 = s0 * s1;
612 dndotz_dqdot0 = -c1 * s0;
613 dndotz_dqdot1 = -c0 * s1;
614
615 computeMotionSubspace(
616 s0, c0, s1, c1, s2, c2, dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0,
617 dndotz_dqdot1, data);
618 }
619 void computeMotionSubspace(
620 const Scalar & s0,
621 const Scalar & c0,
622 const Scalar & s1,
623 const Scalar & c1,
624 const Scalar & s2,
625 const Scalar & c2,
626 const Scalar & dndotx_dqdot1,
627 const Scalar & dndoty_dqdot0,
628 const Scalar & dndoty_dqdot1,
629 const Scalar & dndotz_dqdot0,
630 const Scalar & dndotz_dqdot1,
631 JointDataDerived & data) const
632 {
633 Scalar S_11, S_21, S_31, S_12, S_22, S_32;
634 // clang-format off
635 S_11 = dndoty_dqdot0 * radius_y * (c0 * s2 + c2 * s0 * s1)
636 + dndotz_dqdot0 * radius_z * (-c0 * c2 * s1 + s0 * s2);
637
638 S_21 = -dndoty_dqdot0 * radius_y * (-c0 * c2 + s0 * s1 * s2)
639 + dndotz_dqdot0 * radius_z * (c0 * s1 * s2 + c2 * s0);
640
641 S_31 = c1 * (-dndoty_dqdot0 * radius_y * s0 + dndotz_dqdot0 * radius_z * c0);
642
643 S_12 = dndotx_dqdot1 * radius_x * c1 * c2
644 + dndoty_dqdot1 * radius_y * (c0 * s2 + c2 * s0 * s1)
645 + dndotz_dqdot1 * radius_z * (-c0 * c2 * s1 + s0 * s2);
646
647 S_22 = -dndotx_dqdot1 * radius_x * c1 * s2
648 - dndoty_dqdot1 * radius_y * (-c0 * c2 + s0 * s1 * s2)
649 + dndotz_dqdot1 * radius_z * (c0 * s1 * s2 + c2 * s0);
650
651 S_32 = dndotx_dqdot1 * radius_x * s1 - dndoty_dqdot1 * radius_y * c1 * s0
652 + dndotz_dqdot1 * radius_z * c0 * c1;
653
654 // Write directly to the internal matrix S, not to matrix() which returns a copy
655 data.S.S << S_11 , S_12 , Scalar(0),
656 S_21 , S_22 , Scalar(0),
657 S_31 , S_32 , Scalar(0),
658 c1 * c2, s2 , Scalar(0),
659 -c1 * s2, c2 , Scalar(0),
660 s1 , Scalar(0), Scalar(1);
661 // clang-format on
662 }
663
665 template<typename ConfigVector, typename TangentVector>
667 JointDataDerived & data,
668 const Eigen::MatrixBase<ConfigVector> & qs,
669 const Eigen::MatrixBase<TangentVector> &) const
670 {
671 Scalar c0, s0;
672 SINCOS(qs(0), &s0, &c0);
673 Scalar c1, s1;
674 SINCOS(qs(1), &s1, &c1);
675 Scalar c2, s2;
676 SINCOS(qs(2), &s2, &c2);
677
678 Scalar dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0, dndotz_dqdot1;
679 dndotx_dqdot1 = c1;
680 dndoty_dqdot0 = -c0 * c1;
681 dndoty_dqdot1 = s0 * s1;
682 dndotz_dqdot0 = -c1 * s0;
683 dndotz_dqdot1 = -c0 * s1;
684
686 s0, c0, s1, c1, s2, c2, dndotx_dqdot1, dndoty_dqdot0, dndoty_dqdot1, dndotz_dqdot0,
687 dndotz_dqdot1, data);
688 }
689
690 void computeBiais(
691 const Scalar & s0,
692 const Scalar & c0,
693 const Scalar & s1,
694 const Scalar & c1,
695 const Scalar & s2,
696 const Scalar & c2,
697 const Scalar & dndotx_dqdot1,
698 const Scalar & dndoty_dqdot0,
699 const Scalar & dndoty_dqdot1,
700 const Scalar & dndotz_dqdot0,
701 const Scalar & dndotz_dqdot1,
702 JointDataDerived & data) const
703 {
704 // Compute Sdot for bias acceleration
705 Scalar qdot0, qdot1, qdot2;
706 qdot0 = data.joint_v(0);
707 qdot1 = data.joint_v(1);
708 qdot2 = data.joint_v(2);
709
710 // last columns and last element of the second column are zero,
711 // so we do not compute them
712 Scalar Sdot_11, Sdot_21, Sdot_31, Sdot_41, Sdot_51, Sdot_61;
713 Scalar Sdot_12, Sdot_22, Sdot_32, Sdot_42, Sdot_52;
714
715 // Derivative of dndotXX_dqdot0 with respect to q0 and q1
716 Scalar d_dndotx_dqdot1_dq1 = -s1;
717
718 Scalar d_dndoty_dqdot0_dq0 = s0 * c1;
719 Scalar d_dndoty_dqdot0_dq1 = c0 * s1;
720
721 Scalar d_dndoty_dqdot1_dq1 = s0 * c1;
722
723 Scalar d_dndotz_dqdot0_dq0 = -c1 * c0;
724 Scalar d_dndotz_dqdot0_dq1 = s0 * s1;
725
726 Scalar d_dndotz_dqdot1_dq1 = -c0 * c1;
727
728 // Upper part (translation)
729 // Row 1, Column 1
730 Sdot_11 =
731 qdot0
732 * (-dndoty_dqdot0 * radius_y * (-c0 * c2 * s1 + s0 * s2) + dndotz_dqdot0 * radius_z * (c0 * s2 + c2 * s0 * s1) + radius_y * (c0 * s2 + c2 * s0 * s1) * d_dndoty_dqdot0_dq0 + radius_z * (-c0 * c2 * s1 + s0 * s2) * d_dndotz_dqdot0_dq0)
733 + qdot1
734 * (dndoty_dqdot0 * radius_y * c1 * c2 * s0 - dndotz_dqdot0 * radius_z * c0 * c1 * c2 + radius_y * (c0 * s2 + c2 * s0 * s1) * d_dndoty_dqdot0_dq1 + radius_z * (-c0 * c2 * s1 + s0 * s2) * d_dndotz_dqdot0_dq1)
735 - qdot2
736 * (dndoty_dqdot0 * radius_y * (-c0 * c2 + s0 * s1 * s2) - dndotz_dqdot0 * radius_z * (c0 * s1 * s2 + c2 * s0));
737
738 // Row 1, Column 2
739 Sdot_12 =
740 qdot0
741 * (-dndoty_dqdot1 * radius_y * (-c0 * c2 * s1 + s0 * s2) + dndotz_dqdot1 * radius_z * (c0 * s2 + c2 * s0 * s1) + radius_y * (c0 * s2 + c2 * s0 * s1) * d_dndoty_dqdot0_dq1 + radius_z * (-c0 * c2 * s1 + s0 * s2) * d_dndotz_dqdot0_dq1)
742 + qdot1 * (-dndotx_dqdot1 * radius_x * c2 * s1 + dndoty_dqdot1 * radius_y * c1 * c2 * s0 - dndotz_dqdot1 * radius_z * c0 * c1 * c2 + radius_x * c1 * c2 * d_dndotx_dqdot1_dq1 + radius_y * (c0 * s2 + c2 * s0 * s1) * d_dndoty_dqdot1_dq1 + radius_z * (-c0 * c2 * s1 + s0 * s2) * d_dndotz_dqdot1_dq1) - qdot2 * (dndotx_dqdot1 * radius_x * c1 * s2 + dndoty_dqdot1 * radius_y * (-c0 * c2 + s0 * s1 * s2) - dndotz_dqdot1 * radius_z * (c0 * s1 * s2 + c2 * s0));
743
744 // Row 2, Column 1
745 Sdot_21 =
746 -qdot0
747 * (dndoty_dqdot0 * radius_y * (c0 * s1 * s2 + c2 * s0) + dndotz_dqdot0 * radius_z * (-c0 * c2 + s0 * s1 * s2) + radius_y * (-c0 * c2 + s0 * s1 * s2) * d_dndoty_dqdot0_dq0 - radius_z * (c0 * s1 * s2 + c2 * s0) * d_dndotz_dqdot0_dq0)
748 - qdot1
749 * (dndoty_dqdot0 * radius_y * c1 * s0 * s2 - dndotz_dqdot0 * radius_z * c0 * c1 * s2 + radius_y * (-c0 * c2 + s0 * s1 * s2) * d_dndoty_dqdot0_dq1 - radius_z * (c0 * s1 * s2 + c2 * s0) * d_dndotz_dqdot0_dq1)
750 - qdot2
751 * (dndoty_dqdot0 * radius_y * (c0 * s2 + c2 * s0 * s1) + dndotz_dqdot0 * radius_z * (-c0 * c2 * s1 + s0 * s2));
752
753 // Row 2, Column 2
754 Sdot_22 =
755 -qdot0
756 * (dndoty_dqdot1 * radius_y * (c0 * s1 * s2 + c2 * s0) + dndotz_dqdot1 * radius_z * (-c0 * c2 + s0 * s1 * s2) + radius_y * (-c0 * c2 + s0 * s1 * s2) * d_dndoty_dqdot0_dq1 - radius_z * (c0 * s1 * s2 + c2 * s0) * d_dndotz_dqdot0_dq1)
757 + qdot1 * (dndotx_dqdot1 * radius_x * s1 * s2 - dndoty_dqdot1 * radius_y * c1 * s0 * s2 + dndotz_dqdot1 * radius_z * c0 * c1 * s2 - radius_x * c1 * s2 * d_dndotx_dqdot1_dq1 - radius_y * (-c0 * c2 + s0 * s1 * s2) * d_dndoty_dqdot1_dq1 + radius_z * (c0 * s1 * s2 + c2 * s0) * d_dndotz_dqdot1_dq1) - qdot2 * (dndotx_dqdot1 * radius_x * c1 * c2 + dndoty_dqdot1 * radius_y * (c0 * s2 + c2 * s0 * s1) + dndotz_dqdot1 * radius_z * (-c0 * c2 * s1 + s0 * s2));
758
759 // Row 3, Column 1
760 Sdot_31 =
761 -qdot0 * c1
762 * (dndoty_dqdot0 * radius_y * c0 + dndotz_dqdot0 * radius_z * s0 + radius_y * s0 * d_dndoty_dqdot0_dq0 - radius_z * c0 * d_dndotz_dqdot0_dq0)
763 + qdot1
764 * (-c1 * (radius_y * s0 * d_dndoty_dqdot0_dq1 - radius_z * c0 * d_dndotz_dqdot0_dq1) + s1 * (dndoty_dqdot0 * radius_y * s0 - dndotz_dqdot0 * radius_z * c0));
765
766 // Row 3, Column 2
767 Sdot_32 =
768 -qdot0 * c1
769 * (dndoty_dqdot1 * radius_y * c0 + dndotz_dqdot1 * radius_z * s0 + radius_y * s0 * d_dndoty_dqdot0_dq1 - radius_z * c0 * d_dndotz_dqdot0_dq1)
770 + qdot1
771 * (dndotx_dqdot1 * radius_x * c1 + dndoty_dqdot1 * radius_y * s0 * s1 - dndotz_dqdot1 * radius_z * c0 * s1 + radius_x * s1 * d_dndotx_dqdot1_dq1 - radius_y * c1 * s0 * d_dndoty_dqdot1_dq1 + radius_z * c0 * c1 * d_dndotz_dqdot1_dq1);
772
773 // Angular part (rows 4-6)
774 Sdot_41 = -(qdot1 * c2 * s1 + qdot2 * c1 * s2);
775 Sdot_51 = qdot1 * s1 * s2 - qdot2 * c1 * c2;
776 Sdot_61 = qdot1 * c1;
777
778 Sdot_42 = qdot2 * c2;
779 Sdot_52 = -qdot2 * s2;
780
781 data.c.toVector() << Sdot_11 * qdot0 + Sdot_12 * qdot1, Sdot_21 * qdot0 + Sdot_22 * qdot1,
782 Sdot_31 * qdot0 + Sdot_32 * qdot1, Sdot_41 * qdot0 + Sdot_42 * qdot1,
783 Sdot_51 * qdot0 + Sdot_52 * qdot1, Sdot_61 * qdot0;
784 }
785 }; // struct JointModelEllipsoidTpl
786
787} // namespace pinocchio
788
789#include <boost/type_traits.hpp>
790
791namespace boost
792{
793 template<typename Scalar, int Options>
794 struct has_nothrow_constructor<::pinocchio::JointModelEllipsoidTpl<Scalar, Options>>
795 : public integral_constant<bool, true>
796 {
797 };
798
799 template<typename Scalar, int Options>
800 struct has_nothrow_copy<::pinocchio::JointModelEllipsoidTpl<Scalar, Options>>
801 : public integral_constant<bool, true>
802 {
803 };
804
805 template<typename Scalar, int Options>
806 struct has_nothrow_constructor<::pinocchio::JointDataEllipsoidTpl<Scalar, Options>>
807 : public integral_constant<bool, true>
808 {
809 };
810
811 template<typename Scalar, int Options>
812 struct has_nothrow_copy<::pinocchio::JointDataEllipsoidTpl<Scalar, Options>>
813 : public integral_constant<bool, true>
814 {
815 };
816} // namespace boost
817
818#endif // ifndef __pinocchio_multibody_joint_ellipsoid_hpp__
ToVectorConstReturnType toVector() const
Return the force as an Eigen vector.
ConstAngularType angular() const
Return the angular part of the force vector.
static void se3Action(const SE3Tpl< Scalar, Options > &m, const Eigen::MatrixBase< Mat > &iV, Eigen::MatrixBase< MatRet > const &jV)
SE3 action on a set of motions, represented by a 6xN matrix whose column represent a spatial motion.
static void se3ActionInverse(const SE3Tpl< Scalar, Options > &m, const Eigen::MatrixBase< Mat > &iV, Eigen::MatrixBase< MatRet > const &jV)
Inverse SE3 action on a set of motions, represented by a 6xN matrix whose column represent a spatial ...
static void motionAction(const MotionDense< MotionDerived > &v, const Eigen::MatrixBase< Mat > &iF, Eigen::MatrixBase< MatRet > const &jF)
Action of a motion on a set of motions, represented by a 6xN matrix whose columns represent a spatial...
static void inertiaAction(const InertiaTpl< Scalar, Options > &I, const Eigen::MatrixBase< Mat > &iF, Eigen::MatrixBase< MatRet > const &jF)
Action of an Inertia matrix on a set of motions, represented by a 6xN matrix whose columns represent ...
Main pinocchio namespace.
Definition treeview.dox:11
void SINCOS(const S1 &a, S2 *sa, S3 *ca)
Computes sin/cos values of a given input scalar.
Definition sincos.hpp:27
const std::vector< bool > hasConfigurationLimit(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointConfigurationLimitVisitor to get the configurations limits.
int idx_q(const JointModelTpl< Scalar, Options, JointCollectionTpl > &jmodel)
Visit a JointModelTpl through JointIdxQVisitor to get the index in the full model configuration space...
Return type of the Constraint::Transpose * Force operation.
Return type of the Constraint::Transpose * ForceSet operation.
Ellipsoid joint - constrains motion to ellipsoid surface with 3-DOF.
JointModelEllipsoidTpl(const Scalar &radius_x, const Scalar &radius_y, const Scalar &radius_z)
Constructor with specified radii.
JointModelEllipsoidTpl()
Default constructor. Creates a spherical joint with all radii equal to 0.
void computeSpatialTransform(const Scalar &c0, const Scalar &s0, const Scalar &c1, const Scalar &s1, const Scalar &c2, const Scalar &s2, JointDataDerived &data) const
Computes the spatial transformation M(q) from joint configuration.
JointModelEllipsoidTpl< NewScalar, Options > cast() const
void computeBiais(JointDataDerived &data, const Eigen::MatrixBase< ConfigVector > &qs, const Eigen::MatrixBase< TangentVector > &) const
Computes the bias acceleration c(q, v) = Sdot(q)·v.
Return type of the ation of a Motion onto an object of type D.
Definition motion.hpp:46