sot-core  4.11.8
Hierarchical task solver plug-in for dynamic-graph.
feature-pose.hxx
Go to the documentation of this file.
1 /*
2  * Copyright 2019
3  * Joseph Mirabel
4  *
5  * LAAS-CNRS
6  *
7  */
8 
9 /* --------------------------------------------------------------------- */
10 /* --- INCLUDE --------------------------------------------------------- */
11 /* --------------------------------------------------------------------- */
12 
13 /* --- SOT --- */
14 #include <dynamic-graph/command-bind.h>
15 #include <dynamic-graph/command-getter.h>
16 #include <dynamic-graph/command-setter.h>
17 #include <dynamic-graph/command.h>
18 
19 #include <Eigen/LU>
20 #include <boost/mpl/if.hpp>
21 #include <boost/type_traits/is_same.hpp>
22 #include <pinocchio/multibody/liegroup/liegroup.hpp>
23 #include <sot/core/debug.hh>
24 #include <sot/core/factory.hh>
25 #include <sot/core/feature-pose.hh>
26 
27 namespace dynamicgraph {
28 namespace sot {
29 
30 typedef pinocchio::CartesianProductOperation<
31  pinocchio::VectorSpaceOperationTpl<3, double>,
32  pinocchio::SpecialOrthogonalOperationTpl<3, double> >
34 typedef pinocchio::SpecialEuclideanOperationTpl<3, double> SE3_t;
35 
36 namespace internal {
37 template <Representation_t representation>
38 struct LG_t {
39  typedef typename boost::mpl::if_c<representation == SE3Representation, SE3_t,
41 };
42 } // namespace internal
43 
44 /* --------------------------------------------------------------------- */
45 /* --- CLASS ----------------------------------------------------------- */
46 /* --------------------------------------------------------------------- */
47 
48 static const MatrixHomogeneous Id(MatrixHomogeneous::Identity());
49 
50 template <Representation_t representation>
51 FeaturePose<representation>::FeaturePose(const std::string &pointName)
52  : FeatureAbstract(pointName),
53  oMja(NULL, CLASS_NAME + "(" + name + ")::input(matrixHomo)::oMja"),
54  jaMfa(NULL, CLASS_NAME + "(" + name + ")::input(matrixHomo)::jaMfa"),
55  oMjb(NULL, CLASS_NAME + "(" + name + ")::input(matrixHomo)::oMjb"),
56  jbMfb(NULL, CLASS_NAME + "(" + name + ")::input(matrixHomo)::jbMfb"),
57  jaJja(NULL, CLASS_NAME + "(" + name + ")::input(matrix)::jaJja"),
58  jbJjb(NULL, CLASS_NAME + "(" + name + ")::input(matrix)::jbJjb"),
59  faMfbDes(NULL,
60  CLASS_NAME + "(" + name + ")::input(matrixHomo)::faMfbDes"),
61  faNufafbDes(NULL,
62  CLASS_NAME + "(" + name + ")::input(vector)::faNufafbDes"),
63  faMfb(
64  boost::bind(&FeaturePose<representation>::computefaMfb, this, _1, _2),
65  oMja << jaMfa << oMjb << jbMfb,
66  CLASS_NAME + "(" + name + ")::output(matrixHomo)::faMfb"),
67  q_faMfb(boost::bind(&FeaturePose<representation>::computeQfaMfb, this, _1,
68  _2),
69  faMfb, CLASS_NAME + "(" + name + ")::output(vector7)::q_faMfb"),
70  q_faMfbDes(boost::bind(&FeaturePose<representation>::computeQfaMfbDes,
71  this, _1, _2),
72  faMfbDes,
73  CLASS_NAME + "(" + name + ")::output(vector7)::q_faMfbDes") {
74  oMja.setConstant(Id);
75  jaMfa.setConstant(Id);
76  jbMfb.setConstant(Id);
77  faMfbDes.setConstant(Id);
78  faNufafbDes.setConstant(Vector::Zero(6));
79 
80  jacobianSOUT.addDependencies(q_faMfbDes << q_faMfb << jaJja << jbJjb);
81 
82  errorSOUT.addDependencies(q_faMfbDes << q_faMfb);
83 
84  signalRegistration(oMja << jaMfa << oMjb << jbMfb << jaJja << jbJjb);
85  signalRegistration(faMfb << errordotSOUT << faMfbDes << faNufafbDes);
86 
87  errordotSOUT.setFunction(
88  boost::bind(&FeaturePose<representation>::computeErrorDot, this, _1, _2));
89  errordotSOUT.addDependencies(q_faMfbDes << q_faMfb << faNufafbDes);
90 
91  // Commands
92  //
93  {
94  using namespace dynamicgraph::command;
95  addCommand("keep",
96  makeCommandVoid1(
98  docCommandVoid1(
99  "modify the desired position to servo at current pos.",
100  "time")));
101  }
102 }
103 
104 template <Representation_t representation>
106 
107 /* --------------------------------------------------------------------- */
108 /* --------------------------------------------------------------------- */
109 /* --------------------------------------------------------------------- */
110 
111 template <Representation_t representation>
112 static inline void check(const FeaturePose<representation> &ft) {
113  (void)ft;
114  assert(ft.oMja.isPlugged());
115  assert(ft.jaMfa.isPlugged());
116  assert(ft.oMjb.isPlugged());
117  assert(ft.jbMfb.isPlugged());
118  assert(ft.faMfbDes.isPlugged());
119  assert(ft.faNufafbDes.isPlugged());
120 }
121 
122 template <Representation_t representation>
123 unsigned int &FeaturePose<representation>::getDimension(unsigned int &dim,
124  int time) {
125  sotDEBUG(25) << "# In {" << std::endl;
126 
127  const Flags &fl = selectionSIN.access(time);
128 
129  dim = 0;
130  for (int i = 0; i < 6; ++i)
131  if (fl(i)) dim++;
132 
133  sotDEBUG(25) << "# Out }" << std::endl;
134  return dim;
135 }
136 
137 void toVector(const MatrixHomogeneous &M, Vector7 &v) {
138  v.head<3>() = M.translation();
139  QuaternionMap(v.tail<4>().data()) = M.linear();
140 }
141 
143  Vector7 ret;
144  toVector(M, ret);
145  return ret;
146 }
147 
148 template <Representation_t representation>
149 Matrix &FeaturePose<representation>::computeJacobian(Matrix &J, int time) {
150  typedef typename internal::LG_t<representation>::type LieGroup_t;
151 
152  check(*this);
153 
154  q_faMfb.recompute(time);
155  q_faMfbDes.recompute(time);
156 
157  const unsigned int &dim = dimensionSOUT(time);
158  const Flags &fl = selectionSIN(time);
159 
160  const Matrix &_jbJjb = jbJjb(time);
161 
162  const MatrixHomogeneous &_jbMfb =
163  (jbMfb.isPlugged() ? jbMfb.accessCopy() : Id);
164 
165  const Matrix::Index cJ = _jbJjb.cols();
166  J.resize(dim, cJ);
167 
168  MatrixTwist X;
169  Eigen::Matrix<double, 6, 6, Eigen::RowMajor> Jminus;
170 
171  buildFrom(_jbMfb.inverse(Eigen::Affine), X);
172  MatrixRotation faRfb = jaMfa.access(time).rotation().transpose() *
173  oMja.access(time).rotation().transpose() *
174  oMjb.access(time).rotation() * _jbMfb.rotation();
175  if (boost::is_same<LieGroup_t, R3xSO3_t>::value)
176  X.topRows<3>().applyOnTheLeft(faRfb);
177  LieGroup_t().template dDifference<pinocchio::ARG1>(
178  q_faMfbDes.accessCopy(), q_faMfb.accessCopy(), Jminus);
179 
180  // Contribution of b:
181  // J = Jminus * X * jbJjb;
182  unsigned int rJ = 0;
183  for (unsigned int r = 0; r < 6; ++r)
184  if (fl((int)r)) J.row(rJ++) = (Jminus * X).row(r) * _jbJjb;
185 
186  if (jaJja.isPlugged()) {
187  const Matrix &_jaJja = jaJja(time);
188  const MatrixHomogeneous &_jaMfa =
189  (jaMfa.isPlugged() ? jaMfa.accessCopy() : Id),
190  _faMfb = faMfb.accessCopy();
191 
192  buildFrom((_jaMfa * _faMfb).inverse(Eigen::Affine), X);
193  if (boost::is_same<LieGroup_t, R3xSO3_t>::value)
194  X.topRows<3>().applyOnTheLeft(faRfb);
195 
196  // J -= (Jminus * X) * jaJja(time);
197  rJ = 0;
198  for (unsigned int r = 0; r < 6; ++r)
199  if (fl((int)r)) J.row(rJ++).noalias() -= (Jminus * X).row(r) * _jaJja;
200  }
201 
202  return J;
203 }
204 
205 template <Representation_t representation>
207  MatrixHomogeneous &res, int time) {
208  check(*this);
209 
210  res = (oMja(time) * jaMfa(time)).inverse(Eigen::Affine) * oMjb(time) *
211  jbMfb(time);
212  return res;
213 }
214 
215 template <Representation_t representation>
216 Vector7 &FeaturePose<representation>::computeQfaMfb(Vector7 &res, int time) {
217  check(*this);
218 
219  toVector(faMfb(time), res);
220  return res;
221 }
222 
223 template <Representation_t representation>
224 Vector7 &FeaturePose<representation>::computeQfaMfbDes(Vector7 &res, int time) {
225  check(*this);
226 
227  toVector(faMfbDes(time), res);
228  return res;
229 }
230 
231 template <Representation_t representation>
232 Vector &FeaturePose<representation>::computeError(Vector &error, int time) {
233  typedef typename internal::LG_t<representation>::type LieGroup_t;
234  check(*this);
235 
236  const Flags &fl = selectionSIN(time);
237 
238  Eigen::Matrix<double, 6, 1> v;
239  LieGroup_t().difference(q_faMfbDes(time), q_faMfb(time), v);
240 
241  error.resize(dimensionSOUT(time));
242  unsigned int cursor = 0;
243  for (unsigned int i = 0; i < 6; ++i)
244  if (fl((int)i)) error(cursor++) = v(i);
245 
246  return error;
247 }
248 
249 // This function is responsible of converting the input velocity expressed with
250 // SE(3) convention onto a velocity expressed with the convention of this
251 // feature (R^3xSO(3) or SE(3)), in the right frame.
252 template <>
254  const MatrixHomogeneous &Mdes,
255  const Vector &faNufafbDes) {
256  (void)M;
257  MatrixTwist X;
258  buildFrom(Mdes.inverse(Eigen::Affine), X);
259  return X * faNufafbDes;
260 }
261 template <>
263  const MatrixHomogeneous &Mdes,
264  const Vector &faNufafbDes) {
265  Vector6d nu;
266  nu.head<3>() =
267  faNufafbDes.head<3>() - M.translation().cross(faNufafbDes.tail<3>());
268  nu.tail<3>() = Mdes.rotation().transpose() * faNufafbDes.tail<3>();
269  return nu;
270 }
271 
272 template <Representation_t representation>
274  int time) {
275  typedef typename internal::LG_t<representation>::type LieGroup_t;
276  check(*this);
277 
278  errordot.resize(dimensionSOUT(time));
279  const Flags &fl = selectionSIN(time);
280  if (!faNufafbDes.isPlugged()) {
281  errordot.setZero();
282  return errordot;
283  }
284 
285  q_faMfb.recompute(time);
286  q_faMfbDes.recompute(time);
287  faNufafbDes.recompute(time);
288 
289  const MatrixHomogeneous &_faMfbDes = faMfbDes(time);
290 
291  Eigen::Matrix<double, 6, 6, Eigen::RowMajor> Jminus;
292 
293  LieGroup_t().template dDifference<pinocchio::ARG0>(
294  q_faMfbDes.accessCopy(), q_faMfb.accessCopy(), Jminus);
295  Vector6d nu = convertVelocity<LieGroup_t>(faMfb(time), _faMfbDes,
296  faNufafbDes.accessCopy());
297  unsigned int cursor = 0;
298  for (unsigned int i = 0; i < 6; ++i)
299  if (fl((int)i)) errordot(cursor++) = Jminus.row(i) * nu;
300 
301  return errordot;
302 }
303 
304 /* Modify the value of the reference (sdes) so that it corresponds
305  * to the current position. The effect on the servo is to maintain the
306  * current position and correct any drift. */
307 template <Representation_t representation>
309  check(*this);
310 
311  const MatrixHomogeneous &_oMja = (oMja.isPlugged() ? oMja.access(time) : Id),
312  _jaMfa =
313  (jaMfa.isPlugged() ? jaMfa.access(time) : Id),
314  _oMjb = oMjb.access(time),
315  _jbMfb =
316  (jbMfb.isPlugged() ? jbMfb.access(time) : Id);
317  faMfbDes = (_oMja * _jaMfa).inverse(Eigen::Affine) * _oMjb * _jbMfb;
318 }
319 
320 static const char *featureNames[] = {"X ", "Y ", "Z ", "RX", "RY", "RZ"};
321 template <Representation_t representation>
322 void FeaturePose<representation>::display(std::ostream &os) const {
323  os << CLASS_NAME << "<" << name << ">: (";
324 
325  try {
326  const Flags &fl = selectionSIN.accessCopy();
327  bool first = true;
328  for (int i = 0; i < 6; ++i)
329  if (fl(i)) {
330  if (first) {
331  first = false;
332  } else {
333  os << ",";
334  }
335  os << featureNames[i];
336  }
337  os << ") ";
338  } catch (ExceptionAbstract e) {
339  os << " selectSIN not set.";
340  }
341 }
342 
343 } // namespace sot
344 } // namespace dynamicgraph
Definition: exception-abstract.hh:36
This class gives the abstract definition of a feature.
Definition: feature-abstract.hh:76
unsigned int getDimension(void) const
Shortest method.
Definition: feature-abstract.hh:121
SignalTimeDependent< dynamicgraph::Vector, int > errordotSOUT
Derivative of the error with respect to time: .
Definition: feature-abstract.hh:189
SignalTimeDependent< unsigned int, int > dimensionSOUT
Returns the dimension of the feature as an output signal.
Definition: feature-abstract.hh:196
Feature that controls the relative (or absolute) pose between two frames A (or world) and B.
Definition: feature-pose.hh:62
dynamicgraph::SignalPtr< Matrix, int > jbJjb
Jacobian of the input Joint B, expressed in Joint B
Definition: feature-pose.hh:82
dynamicgraph::SignalPtr< Vector, int > faNufafbDes
Definition: feature-pose.hh:88
SignalTimeDependent< dynamicgraph::Matrix, int > jacobianSOUT
Jacobian of the error wrt the robot state: .
Definition: feature-abstract.hh:193
virtual dynamicgraph::Vector & computeError(dynamicgraph::Vector &res, int time)
Computes .
Definition: feature-pose.hxx:232
FeaturePose(const std::string &name)
Definition: feature-pose.hxx:51
dynamicgraph::SignalPtr< MatrixHomogeneous, int > faMfbDes
The desired pose of Frame B wrt to Frame A.
Definition: feature-pose.hh:85
SignalTimeDependent< Vector7, int > q_faMfbDes
Definition: feature-pose.hh:103
SignalTimeDependent< MatrixHomogeneous, int > faMfb
Pose of Frame B wrt to Frame A.
Definition: feature-pose.hh:95
SignalTimeDependent< dynamicgraph::Vector, int > errorSOUT
This signal returns the error between the desired value and the current value : .
Definition: feature-abstract.hh:185
virtual dynamicgraph::Matrix & computeJacobian(dynamicgraph::Matrix &res, int time)
Definition: feature-pose.hxx:149
virtual void display(std::ostream &os) const
Definition: feature-pose.hxx:322
dynamicgraph::SignalPtr< MatrixHomogeneous, int > oMjb
Input pose of Joint B wrt to world frame.
Definition: feature-pose.hh:76
dynamicgraph::SignalPtr< MatrixHomogeneous, int > jbMfb
Input pose of Frame B wrt to Joint B.
Definition: feature-pose.hh:78
virtual dynamicgraph::Vector & computeErrorDot(dynamicgraph::Vector &res, int time)
Definition: feature-pose.hxx:273
virtual ~FeaturePose(void)
Definition: feature-pose.hxx:105
void servoCurrentPosition(const int &time)
Definition: feature-pose.hxx:308
SignalPtr< Flags, int > selectionSIN
This vector specifies which dimension are used to perform the computation. For instance let us assume...
Definition: feature-abstract.hh:173
static const std::string CLASS_NAME
Definition: feature-pose.hh:64
dynamicgraph::SignalPtr< MatrixHomogeneous, int > oMja
Input pose of Joint A wrt to world frame.
Definition: feature-pose.hh:72
dynamicgraph::SignalPtr< Matrix, int > jaJja
Jacobian of the input Joint A, expressed in Joint A
Definition: feature-pose.hh:80
SignalTimeDependent< Vector7, int > q_faMfb
Definition: feature-pose.hh:99
dynamicgraph::SignalPtr< MatrixHomogeneous, int > jaMfa
Input pose of Frame A wrt to Joint A.
Definition: feature-pose.hh:74
Definition: flags.hh:33
#define sotDEBUG(level)
Definition: debug.hh:165
Eigen::VectorXd::Index Index
Definition: robot-utils.hh:39
@ SE3Representation
Definition: feature-pose.hh:29
Vector6d convertVelocity< R3xSO3_t >(const MatrixHomogeneous &M, const MatrixHomogeneous &Mdes, const Vector &faNufafbDes)
Definition: feature-pose.hxx:262
Eigen::Transform< double, 3, Eigen::Affine > SOT_CORE_EXPORT MatrixHomogeneous
Definition: matrix-geometry.hh:75
Eigen::Matrix< double, 7, 1 > SOT_CORE_EXPORT Vector7
Definition: matrix-geometry.hh:84
void buildFrom(const MatrixHomogeneous &MH, MatrixTwist &MT)
Definition: matrix-geometry.hh:88
pinocchio::SpecialEuclideanOperationTpl< 3, double > SE3_t
Definition: feature-pose.hxx:34
Eigen::Map< Quaternion > SOT_CORE_EXPORT QuaternionMap
Definition: matrix-geometry.hh:86
Vector6d convertVelocity< SE3_t >(const MatrixHomogeneous &M, const MatrixHomogeneous &Mdes, const Vector &faNufafbDes)
Definition: feature-pose.hxx:253
void toVector(const MatrixHomogeneous &M, Vector7 &v)
Definition: feature-pose.hxx:137
Eigen::Matrix< double, 3, 3 > SOT_CORE_EXPORT MatrixRotation
Definition: matrix-geometry.hh:76
Eigen::Matrix< double, 6, 6 > SOT_CORE_EXPORT MatrixTwist
Definition: matrix-geometry.hh:82
pinocchio::CartesianProductOperation< pinocchio::VectorSpaceOperationTpl< 3, double >, pinocchio::SpecialOrthogonalOperationTpl< 3, double > > R3xSO3_t
Definition: feature-pose.hxx:33
Definition: abstract-sot-external-interface.hh:17
Definition: feature-pose.hxx:38
boost::mpl::if_c< representation==SE3Representation, SE3_t, R3xSO3_t >::type type
Definition: feature-pose.hxx:40