Joint.h
Go to the documentation of this file.
1 /*
2  * Copyright 2012-2019 CNRS-UM LIRMM, CNRS-AIST JRL
3  */
4 
5 #pragma once
6 
7 // includes
8 // std
9 #include <cmath>
10 #include <sstream>
11 #include <stdexcept>
12 #include <string>
13 #include <vector>
14 
15 // SpaceVecAlg
16 #include <SpaceVecAlg/SpaceVecAlg>
17 
18 namespace rbd
19 {
20 
26 template<typename T>
27 Eigen::Matrix3<T> QuatToE(const std::vector<T> & q);
28 
35 class Joint
36 {
37 public:
39  enum Type
40  {
41  Rev,
46  Free,
48  };
49 
51  enum OldType
52  {
53  RevX,
54  RevY,
55  RevZ,
59  };
60 
61 public:
62  Joint();
63 
70  Joint(OldType type, bool forward, std::string name);
71 
78  Joint(Type type, const Eigen::Vector3d & axis, bool forward, std::string name);
79 
85  Joint(Type type, bool forward, std::string name);
86 
91  Joint(std::string name);
92 
102  void makeMimic(const std::string & name, double multiplier, double offset);
103 
105  Type type() const
106  {
107  return type_;
108  }
109 
111  double direction() const
112  {
113  return dir_;
114  }
115 
117  bool forward() const
118  {
119  return dir_ == 1.;
120  }
121 
123  void forward(bool forward)
124  {
125  if(forward != this->forward()) S_ *= -1;
126  dir_ = forward ? 1. : -1;
127  }
128 
133  int params() const
134  {
135  return params_;
136  }
137 
142  int dof() const
143  {
144  return dof_;
145  }
146 
148  const std::string & name() const
149  {
150  return name_;
151  }
152 
154  bool isMimic() const
155  {
156  return isMimic_;
157  }
158 
160  const std::string & mimicName() const
161  {
162  return mimicName_;
163  }
164 
166  double mimicMultiplier() const
167  {
168  return mimicMultiplier_;
169  }
170 
172  double mimicOffset() const
173  {
174  return mimicOffset_;
175  }
176 
178  const Eigen::Matrix<double, 6, Eigen::Dynamic> & motionSubspace() const
179  {
180  return S_;
181  }
182 
188  template<typename T>
189  sva::PTransform<T> pose(const std::vector<T> & q) const;
190 
196  sva::MotionVecd motion(const std::vector<double> & alpha) const;
197 
203  sva::MotionVecd tanAccel(const std::vector<double> & alphaD) const;
204 
208  std::vector<double> zeroParam() const;
209 
213  std::vector<double> zeroDof() const;
214 
221  sva::PTransformd sPose(const std::vector<double> & q) const;
222 
229  sva::MotionVecd sMotion(const std::vector<double> & alpha) const;
230 
237  sva::MotionVecd sTanAccel(const std::vector<double> & alphaD) const;
238 
239  bool operator==(const Joint & b) const
240  {
241  return name_ == b.name_;
242  }
243 
244  bool operator!=(const Joint & b) const
245  {
246  return name_ != b.name_;
247  }
248 
249 public:
253  static std::vector<double> ZeroParam(Type type);
254 
258  static std::vector<double> ZeroDof(Type type);
259 
260 private:
261  void constructJoint(Type t, const Eigen::Vector3d & a);
262 
263 private:
264  Type type_;
265  Eigen::Matrix<double, 6, Eigen::Dynamic> S_;
266  double dir_;
267 
268  int params_;
269  int dof_;
270 
271  std::string name_;
272 
273  bool isMimic_ = false;
274  std::string mimicName_ = "";
275  double mimicMultiplier_ = 1.0;
276  double mimicOffset_ = 0.0;
277 };
278 
279 inline std::ostream & operator<<(std::ostream & out, const Joint & b)
280 {
281  out << "Joint: " << b.name();
282  return out;
283 }
284 
285 inline Joint::Joint() : dir_(0.0), params_(0), dof_(0), name_("") {}
286 
287 inline Joint::Joint(OldType type, bool forward, std::string name)
288 : dir_(forward ? 1. : -1), params_(0), dof_(0), name_(name)
289 {
290  switch(type)
291  {
292  case RevX:
293  constructJoint(Rev, Eigen::Vector3d::UnitX());
294  break;
295  case RevY:
296  constructJoint(Rev, Eigen::Vector3d::UnitY());
297  break;
298  case RevZ:
299  constructJoint(Rev, Eigen::Vector3d::UnitZ());
300  break;
301  case PrismX:
302  constructJoint(Prism, Eigen::Vector3d::UnitX());
303  break;
304  case PrismY:
305  constructJoint(Prism, Eigen::Vector3d::UnitY());
306  break;
307  case PrismZ:
308  constructJoint(Prism, Eigen::Vector3d::UnitZ());
309  break;
310  default:
311  constructJoint(Fixed, Eigen::Vector3d::Zero());
312  break;
313  }
314 }
315 
316 inline Joint::Joint(Type type, const Eigen::Vector3d & axis, bool forward, std::string name)
317 : dir_(forward ? 1. : -1), params_(0), dof_(0), name_(name)
318 {
319  constructJoint(type, axis);
320 }
321 
322 inline Joint::Joint(Type type, bool forward, std::string name)
323 : dir_(forward ? 1. : -1), params_(0), dof_(0), name_(name)
324 {
325  constructJoint(type, Eigen::Vector3d::UnitZ());
326 }
327 
328 inline Joint::Joint(std::string name) : dir_(1), params_(0), dof_(0), name_(name)
329 {
330  constructJoint(Joint::Type::Fixed, Eigen::Vector3d::UnitZ());
331 }
332 
333 inline void Joint::makeMimic(const std::string & name, double multiplier, double offset)
334 {
335  isMimic_ = true;
336  mimicName_ = name;
337  mimicMultiplier_ = multiplier;
338  mimicOffset_ = offset;
339 }
340 
341 template<typename T>
342 inline sva::PTransform<T> Joint::pose(const std::vector<T> & q) const
343 {
344  Eigen::Matrix3<T> rot;
345  switch(type_)
346  {
347  case Rev:
348  // minus S because rotation is anti trigonometric
349  return sva::PTransform<T>(Eigen::AngleAxis<T>(-q[0], S_.block<3, 1>(0, 0).cast<T>()).matrix());
350  case Prism:
351  return sva::PTransform<T>(Eigen::Vector3<T>(S_.block<3, 1>(3, 0).cast<T>() * q[0]));
352  case Spherical:
353  return sva::PTransform<T>(Eigen::Quaternion<T>(q[0], dir_ * q[1], dir_ * q[2], dir_ * q[3]).inverse());
354  case Planar:
355  rot = sva::RotZ(q[0]);
356  if(dir_ == 1.)
357  {
358  return sva::PTransform<T>(rot, rot.transpose() * Eigen::Vector3<T>(q[1], q[2], 0.));
359  }
360  else
361  {
362  return sva::PTransform<T>(rot, rot.transpose() * Eigen::Vector3<T>(q[1], q[2], 0.)).inv();
363  }
364  case Cylindrical:
365  return sva::PTransform<T>(Eigen::AngleAxis<T>(-q[0], S_.col(0).head<3>().cast<T>()).matrix(),
366  S_.col(1).tail<3>().cast<T>() * q[1]);
367  case Free:
368  rot = QuatToE(q);
369  if(dir_ == 1.)
370  {
371  return sva::PTransform<T>(rot, Eigen::Vector3<T>(q[4], q[5], q[6]));
372  }
373  else
374  {
375  return sva::PTransform<T>(rot, Eigen::Vector3<T>(q[4], q[5], q[6])).inv();
376  }
377  case Fixed:
378  default:
379  return sva::PTransform<T>::Identity();
380  }
381 }
382 
383 inline sva::MotionVecd Joint::motion(const std::vector<double> & alpha) const
384 {
385  switch(type_)
386  {
387  case Rev:
388  return sva::MotionVecd(
389  (Eigen::Vector6d() << S_.block<3, 1>(0, 0) * alpha[0], Eigen::Vector3d::Zero()).finished());
390  case Prism:
391  return sva::MotionVecd(
392  (Eigen::Vector6d() << Eigen::Vector3d::Zero(), S_.block<3, 1>(3, 0) * alpha[0]).finished());
393  case Spherical:
394  return sva::MotionVecd(S_ * Eigen::Vector3d(alpha[0], alpha[1], alpha[2]));
395  case Planar:
396  return sva::MotionVecd(S_ * Eigen::Vector3d(alpha[0], alpha[1], alpha[2]));
397  case Cylindrical:
398  return sva::MotionVecd(S_ * Eigen::Vector2d(alpha[0], alpha[1]));
399  case Free:
400  return sva::MotionVecd(
401  S_ * (Eigen::Vector6d() << alpha[0], alpha[1], alpha[2], alpha[3], alpha[4], alpha[5]).finished());
402  case Fixed:
403  default:
404  return sva::MotionVecd(Eigen::Vector6d::Zero());
405  }
406 }
407 
408 inline sva::MotionVecd Joint::tanAccel(const std::vector<double> & alphaD) const
409 {
410  switch(type_)
411  {
412  case Rev:
413  return sva::MotionVecd(
414  (Eigen::Vector6d() << S_.block<3, 1>(0, 0) * alphaD[0], Eigen::Vector3d::Zero()).finished());
415  case Prism:
416  return sva::MotionVecd(
417  (Eigen::Vector6d() << Eigen::Vector3d::Zero(), S_.block<3, 1>(3, 0) * alphaD[0]).finished());
418  case Spherical:
419  return sva::MotionVecd(S_ * Eigen::Vector3d(alphaD[0], alphaD[1], alphaD[2]));
420  case Planar:
421  return sva::MotionVecd(S_ * Eigen::Vector3d(alphaD[0], alphaD[1], alphaD[2]));
422  case Cylindrical:
423  return sva::MotionVecd(S_ * Eigen::Vector2d(alphaD[0], alphaD[1]));
424  case Free:
425  return sva::MotionVecd(
426  S_ * (Eigen::Vector6d() << alphaD[0], alphaD[1], alphaD[2], alphaD[3], alphaD[4], alphaD[5]).finished());
427  case Fixed:
428  default:
429  return sva::MotionVecd(Eigen::Vector6d::Zero());
430  }
431 }
432 
433 inline std::vector<double> Joint::zeroParam() const
434 {
435  auto q = ZeroParam(type_);
436  if(isMimic_)
437  {
438  for(auto & qi : q)
439  {
440  qi += mimicOffset_;
441  }
442  }
443  return q;
444 }
445 
446 inline std::vector<double> Joint::zeroDof() const
447 {
448  return ZeroDof(type_);
449 }
450 
451 inline sva::PTransformd Joint::sPose(const std::vector<double> & q) const
452 {
453  if(q.size() != static_cast<unsigned int>(params_))
454  {
455  std::ostringstream str;
456  str << "Wrong number of generalized position variable: expected " << params_ << " gived " << q.size();
457  throw std::domain_error(str.str());
458  }
459  return pose(q);
460 }
461 
462 inline sva::MotionVecd Joint::sMotion(const std::vector<double> & alpha) const
463 {
464  if(alpha.size() != static_cast<unsigned int>(dof_))
465  {
466  std::ostringstream str;
467  str << "Wrong number of generalized speed variable: expected " << params_ << " gived " << alpha.size();
468  throw std::domain_error(str.str());
469  }
470  return motion(alpha);
471 }
472 
473 inline sva::MotionVecd Joint::sTanAccel(const std::vector<double> & alphaD) const
474 {
475  if(alphaD.size() != static_cast<unsigned int>(dof_))
476  {
477  std::ostringstream str;
478  str << "Wrong number of generalized acceleration variable: expected " << params_ << " gived " << alphaD.size();
479  throw std::domain_error(str.str());
480  }
481  return tanAccel(alphaD);
482 }
483 
484 inline std::vector<double> Joint::ZeroParam(Type type)
485 {
486  switch(type)
487  {
488  case Rev:
489  case Prism:
490  return {0.};
491  case Spherical:
492  return {1., 0., 0., 0.};
493  case Planar:
494  return {0., 0., 0.};
495  case Cylindrical:
496  return {0., 0.};
497  case Free:
498  return {1., 0., 0., 0., 0., 0., 0.};
499  case Fixed:
500  default:
501  return {};
502  }
503 }
504 
505 inline std::vector<double> Joint::ZeroDof(Type type)
506 {
507  switch(type)
508  {
509  case Rev:
510  case Prism:
511  return {0.};
512  case Spherical:
513  return {0., 0., 0.};
514  case Planar:
515  return {0., 0., 0.};
516  case Cylindrical:
517  return {0., 0.};
518  case Free:
519  return {0., 0., 0., 0., 0., 0.};
520  case Fixed:
521  default:
522  return {};
523  }
524 }
525 
526 inline void Joint::constructJoint(Type t, const Eigen::Vector3d & a)
527 {
528  type_ = t;
529 
530  switch(t)
531  {
532  case Rev:
533  S_ = dir_ * (Eigen::Vector6d() << a, Eigen::Vector3d::Zero()).finished();
534  params_ = 1;
535  dof_ = 1;
536  break;
537  case Prism:
538  S_ = dir_ * (Eigen::Vector6d() << Eigen::Vector3d::Zero(), a).finished();
539  params_ = 1;
540  dof_ = 1;
541  break;
542  case Spherical:
543  S_ = Eigen::Matrix<double, 6, 3>::Zero();
544  S_.block<3, 3>(0, 0).setIdentity();
545  S_ *= dir_;
546  params_ = 4;
547  dof_ = 3;
548  break;
549  case Planar:
550  S_ = Eigen::Matrix<double, 6, 3>::Zero();
551  S_.block<3, 3>(2, 0).setIdentity();
552  S_ *= dir_;
553  params_ = 3;
554  dof_ = 3;
555  break;
556  case Cylindrical:
557  S_ = Eigen::Matrix<double, 6, 2>::Zero();
558  S_.col(0).head<3>() = a;
559  S_.col(1).tail<3>() = a;
560  S_ *= dir_;
561  params_ = 2;
562  dof_ = 2;
563  break;
564  case Free:
565  S_ = dir_ * Eigen::Matrix6d::Identity();
566  params_ = 7;
567  dof_ = 6;
568  break;
569  case Fixed:
570  default:
571  S_ = Eigen::Matrix<double, 6, 0>::Zero();
572  params_ = 0;
573  dof_ = 0;
574  break;
575  }
576 }
577 
578 template<typename T>
579 inline Eigen::Matrix3<T> QuatToE(const std::vector<T> & q)
580 {
581  T p0 = q[0];
582  T p1 = q[1];
583  T p2 = q[2];
584  T p3 = q[3];
585 
586  T p0p1 = p0 * p1;
587  T p0p2 = p0 * p2;
588  T p0p3 = p0 * p3;
589 
590  T p1p2 = p1 * p2;
591  T p1p3 = p1 * p3;
592 
593  T p2p3 = p2 * p3;
594 
595  T p0s = std::pow(p0, 2);
596  T p1s = std::pow(p1, 2);
597  T p2s = std::pow(p2, 2);
598  T p3s = std::pow(p3, 2);
599 
600  return 2.
601  * (Eigen::Matrix3<T>() << p0s + p1s - 0.5, p1p2 + p0p3, p1p3 - p0p2, p1p2 - p0p3, p0s + p2s - 0.5, p2p3 + p0p1,
602  p1p3 + p0p2, p2p3 - p0p1, p0s + p3s - 0.5)
603  .finished();
604 }
605 
606 } // namespace rbd
rbd::Joint::PrismZ
@ PrismZ
Prismatique joint about Z axis.
Definition: Joint.h:58
rbd::Joint::sMotion
sva::MotionVecd sMotion(const std::vector< double > &alpha) const
Definition: Joint.h:462
rbd::Joint::Cylindrical
@ Cylindrical
Cylindrical joint (Z prismatic, Z revolute).
Definition: Joint.h:45
rbd::Joint::Type
Type
Joint type.
Definition: Joint.h:39
rbd::Joint::Free
@ Free
Free joint, represented by a quaternion.
Definition: Joint.h:46
rbd::Joint::PrismX
@ PrismX
Prismatique joint about X axis.
Definition: Joint.h:56
rbd::Joint::Spherical
@ Spherical
Spherical joint, represented by a quaternion.
Definition: Joint.h:43
rbd::Joint::Prism
@ Prism
Prismatic joint about an user specified axis.
Definition: Joint.h:42
rbd::Joint::RevY
@ RevY
Revolute joint about Y axis.
Definition: Joint.h:54
rbd::Joint::dof
int dof() const
Definition: Joint.h:142
rbd::Joint::motionSubspace
const Eigen::Matrix< double, 6, Eigen::Dynamic > & motionSubspace() const
Definition: Joint.h:178
rbd::Joint::Joint
Joint()
Definition: Joint.h:285
rbd::Joint::Planar
@ Planar
Planar joint (2 prismatic(X, Y) and 1 revolute(Z)).
Definition: Joint.h:44
rbd::Joint::type
Type type() const
Definition: Joint.h:105
rbd::Joint::mimicMultiplier
double mimicMultiplier() const
Definition: Joint.h:166
rbd::Joint::ZeroDof
static std::vector< double > ZeroDof(Type type)
Definition: Joint.h:505
rbd::Joint::forward
void forward(bool forward)
Definition: Joint.h:123
rbd::Joint
Definition: Joint.h:35
rbd::Joint::zeroParam
std::vector< double > zeroParam() const
Definition: Joint.h:433
rbd::Joint::tanAccel
sva::MotionVecd tanAccel(const std::vector< double > &alphaD) const
Definition: Joint.h:408
rbd::Joint::makeMimic
void makeMimic(const std::string &name, double multiplier, double offset)
Definition: Joint.h:333
rbd::Joint::OldType
OldType
Old joint type for Api compatibility.
Definition: Joint.h:51
rbd::Joint::params
int params() const
Definition: Joint.h:133
rbd::Joint::operator==
bool operator==(const Joint &b) const
Definition: Joint.h:239
rbd::Joint::operator!=
bool operator!=(const Joint &b) const
Definition: Joint.h:244
rbd::operator<<
std::ostream & operator<<(std::ostream &out, const Body &b)
Definition: Body.h:69
rbd::Joint::motion
sva::MotionVecd motion(const std::vector< double > &alpha) const
Definition: Joint.h:383
rbd::Joint::ZeroParam
static std::vector< double > ZeroParam(Type type)
Definition: Joint.h:484
rbd::Joint::PrismY
@ PrismY
Prismatique joint about Y axis.
Definition: Joint.h:57
rbd::Joint::Fixed
@ Fixed
Fixed joint.
Definition: Joint.h:47
rbd::Joint::sTanAccel
sva::MotionVecd sTanAccel(const std::vector< double > &alphaD) const
Definition: Joint.h:473
rbd::Joint::sPose
sva::PTransformd sPose(const std::vector< double > &q) const
Definition: Joint.h:451
rbd::Joint::pose
sva::PTransform< T > pose(const std::vector< T > &q) const
Definition: Joint.h:342
rbd::Joint::mimicOffset
double mimicOffset() const
Definition: Joint.h:172
rbd
Definition: common.h:20
rbd::Joint::zeroDof
std::vector< double > zeroDof() const
Definition: Joint.h:446
rbd::QuatToE
Eigen::Matrix3< T > QuatToE(const std::vector< T > &q)
Definition: Joint.h:579
rbd::Joint::RevX
@ RevX
Revolute joint about X axis.
Definition: Joint.h:53
rbd::Joint::mimicName
const std::string & mimicName() const
Definition: Joint.h:160
rbd::Joint::name
const std::string & name() const
Definition: Joint.h:148
rbd::Joint::RevZ
@ RevZ
Revolute joint about Z axis.
Definition: Joint.h:55
rbd::Joint::isMimic
bool isMimic() const
Definition: Joint.h:154
rbd::Joint::Rev
@ Rev
Revolute joint about an user specified axis.
Definition: Joint.h:41
rbd::Joint::direction
double direction() const
Definition: Joint.h:111
rbd::Joint::forward
bool forward() const
Definition: Joint.h:117