Contacts.cc
Go to the documentation of this file.
1 /*
2  * Original Copyright (c) 2011-2016 Martin Felis <martin.felis@iwr.uni-heidelberg.de>
3  *
4  *
5  * RDL - Robot Dynamics Library
6  * Modifications Copyright (c) 2017 Jordan Lack <jlack1987@gmail.com>
7  *
8  * Licensed under the zlib license. See LICENSE for more details.
9  */
10 
11 #include <iostream>
12 #include <limits>
13 #include <assert.h>
14 
15 #include "rdl_dynamics/Contacts.h"
16 #include "rdl_dynamics/Dynamics.h"
19 #include "rdl_dynamics/Model.h"
22 
23 namespace RobotDynamics
24 {
25 using namespace Math;
26 
27 unsigned int ConstraintSet::addConstraint(unsigned int body_id, const Vector3d& body_point, const Vector3d& world_normal, const char* constraint_name,
28  double normal_acceleration)
29 {
30  assert(bound == false);
31 
32  std::string name_str;
33  if (constraint_name != NULL)
34  {
35  name_str = constraint_name;
36  }
37 
38  name.push_back(name_str);
39  body.push_back(body_id);
40  point.push_back(body_point);
41  normal.push_back(world_normal);
42 
43  unsigned int n_constr = acceleration.size() + 1;
44 
45  acceleration.conservativeResize(n_constr);
46  acceleration[n_constr - 1] = normal_acceleration;
47 
48  force.conservativeResize(n_constr);
49  force[n_constr - 1] = 0.;
50 
51  impulse.conservativeResize(n_constr);
52  impulse[n_constr - 1] = 0.;
53 
54  v_plus.conservativeResize(n_constr);
55  v_plus[n_constr - 1] = 0.;
56 
57  d_multdof3_u = std::vector<Math::Vector3d>(n_constr, Math::Vector3d::Zero());
58 
59  return n_constr - 1;
60 }
61 
62 bool ConstraintSet::bind(const Model& model)
63 {
64  assert(bound == false);
65 
66  if (bound)
67  {
68  std::cerr << "Error: binding an already bound constraint set!" << std::endl;
69  abort();
70  }
71  unsigned int n_constr = size();
72 
73  H = model.ndof0_mat;
74 
75  C = model.ndof0_vec;
76 
77  gamma.conservativeResize(n_constr);
78  gamma.setZero();
79  G.conservativeResize(n_constr, model.dof_count);
80  G.setZero();
81  A.conservativeResize(model.dof_count + n_constr, model.dof_count + n_constr);
82  A.setZero();
83  b.conservativeResize(model.dof_count + n_constr);
84  b.setZero();
85  x.conservativeResize(model.dof_count + n_constr);
86  x.setZero();
87 
88  GT_qr = Eigen::HouseholderQR<Math::MatrixNd>(G.transpose());
89  GT_qr_Q = model.ndof0_mat;
90  Y = MatrixNd::Zero(model.dof_count, G.rows());
91  Z = MatrixNd::Zero(model.dof_count, model.dof_count - G.rows());
92  qddot_y = model.ndof0_vec;
93  qddot_z = model.ndof0_vec;
94 
95  K.conservativeResize(n_constr, n_constr);
96  K.setZero();
97  a.conservativeResize(n_constr);
98  a.setZero();
99  QDDot_t = model.ndof0_vec;
100  QDDot_0 = model.ndof0_vec;
101 
102  f_t.resize(n_constr);
103  f_ext_constraints.resize(model.mBodies.size());
104 
105  for(unsigned int i = 0; i < model.mBodies.size(); i++)
106  {
107  f_ext_constraints[i].setIncludingFrame(model.bodyFrames[i], 0., 0., 0., 0., 0., 0.);
108  }
109 
110  point_accel_0.resize(n_constr, Vector3d::Zero());
111 
112  d_pA.resize(model.mBodies.size());
113  d_a = std::vector<SpatialVector>(model.mBodies.size(), SpatialVectorZero);
114  d_u = model.nbodies0_vec;
115 
116  d_IA = std::vector<SpatialMatrix>(model.mBodies.size(), SpatialMatrixIdentity);
117  d_U = std::vector<SpatialVector>(model.mBodies.size(), SpatialVectorZero);
118  d_d = model.nbodies0_vec;
119 
120  d_multdof3_u = std::vector<Math::Vector3d>(model.mBodies.size(), Math::Vector3d::Zero());
121 
122  bound = true;
123 
124  return bound;
125 }
126 
128 {
129  acceleration.setZero();
130  force.setZero();
131  impulse.setZero();
132 
133  H.setZero();
134  C.setZero();
135  gamma.setZero();
136  G.setZero();
137  A.setZero();
138  b.setZero();
139  x.setZero();
140 
141  K.setZero();
142  a.setZero();
143  QDDot_t.setZero();
144  QDDot_0.setZero();
145 
146  unsigned int i;
147  for (i = 0; i < f_t.size(); i++)
148  {
149  f_t[i].setZero();
150  }
151 
152  for (i = 0; i < f_ext_constraints.size(); i++)
153  {
154  f_ext_constraints[i].setZero();
155  }
156 
157  for (i = 0; i < point_accel_0.size(); i++)
158  {
159  point_accel_0[i].setZero();
160  }
161 
162  for (i = 0; i < d_pA.size(); i++)
163  {
164  d_pA[i].setZero();
165  }
166 
167  for (i = 0; i < d_a.size(); i++)
168  {
169  d_a[i].setZero();
170  }
171 
172  d_u.setZero();
173 }
174 
177 {
178  // Build the system: Copy H
179  A.block(0, 0, c.rows(), c.rows()) = H;
180 
181  // Copy G and G^T
182  A.block(0, c.rows(), c.rows(), gamma.rows()) = G.transpose();
183  A.block(c.rows(), 0, gamma.rows(), c.rows()) = G;
184 
185  // Build the system: Copy -C + \tau
186  b.block(0, 0, c.rows(), 1) = c;
187  b.block(c.rows(), 0, gamma.rows(), 1) = gamma;
188 
189  switch (linear_solver)
190  {
192  x = A.partialPivLu().solve(b);
193  break;
195  x = A.colPivHouseholderQr().solve(b);
196  break;
198  x = A.householderQr().solve(b);
199  break;
200  default:
201  assert(0);
202  break;
203  }
204 }
205 
207  Math::VectorNd& qddot, Math::VectorNd& lambda, Math::MatrixNd& K, Math::VectorNd& a, Math::LinearSolver linear_solver)
208 {
209  SparseFactorizeLTL(model, H);
210 
211  MatrixNd Y(G.transpose());
212 
213  for (unsigned int i = 0; i < Y.cols(); i++)
214  {
215  VectorNd Y_col = Y.block(0, i, Y.rows(), 1);
216  SparseSolveLTx(model, H, Y_col);
217  Y.block(0, i, Y.rows(), 1) = Y_col;
218  }
219 
220  VectorNd z(c);
221  SparseSolveLTx(model, H, z);
222 
223  K = Y.transpose() * Y;
224 
225  a = gamma - Y.transpose() * z;
226 
227  lambda = K.llt().solve(a);
228 
229  qddot = c + G.transpose() * lambda;
230  SparseSolveLTx(model, H, qddot);
231  SparseSolveLx(model, H, qddot);
232 }
233 
235  Math::VectorNd& lambda, Math::MatrixNd& Y, Math::MatrixNd& Z, Math::VectorNd& qddot_y, Math::VectorNd& qddot_z,
236  Math::LinearSolver& linear_solver)
237 {
238  switch (linear_solver)
239  {
241  qddot_y = (G * Y).partialPivLu().solve(gamma);
242  break;
244  qddot_y = (G * Y).colPivHouseholderQr().solve(gamma);
245  break;
247  qddot_y = (G * Y).householderQr().solve(gamma);
248  break;
249  default:
250  assert(0);
251  break;
252  }
253 
254  qddot_z = (Z.transpose() * H * Z).llt().solve(Z.transpose() * (c - H * Y * qddot_y));
255 
256  qddot = Y * qddot_y + Z * qddot_z;
257 
258  switch (linear_solver)
259  {
261  lambda = (G * Y).partialPivLu().solve(Y.transpose() * (H * qddot - c));
262  break;
264  lambda = (G * Y).colPivHouseholderQr().solve(Y.transpose() * (H * qddot - c));
265  break;
267  lambda = (G * Y).householderQr().solve(Y.transpose() * (H * qddot - c));
268  break;
269  default:
270  assert(0);
271  break;
272  }
273 }
274 
275 void calcContactJacobian(Model& model, const Math::VectorNd& Q, const ConstraintSet& CS, Math::MatrixNd& G, bool update_kinematics)
276 {
277  if (update_kinematics)
278  {
279  updateKinematicsCustom(model, &Q, NULL, NULL);
280  }
281 
282  unsigned int i, j;
283 
284  // variables to check whether we need to recompute G
285  unsigned int prev_body_id = 0;
286  Vector3d prev_body_point = Vector3d::Zero();
287  MatrixNd Gi(3, model.dof_count);
288 
289  for (i = 0; i < CS.size(); i++)
290  {
291  // only compute the matrix Gi if actually needed
292  if (prev_body_id != CS.body[i] || prev_body_point != CS.point[i])
293  {
294  Gi.setZero();
295  calcPointJacobian(model, Q, CS.body[i], CS.point[i], Gi, false);
296  prev_body_id = CS.body[i];
297  prev_body_point = CS.point[i];
298  }
299 
300  for (j = 0; j < model.dof_count; j++)
301  {
302  Vector3d gaxis(Gi(0, j), Gi(1, j), Gi(2, j));
303  G(i, j) = gaxis.transpose() * CS.normal[i];
304  }
305  }
306 }
307 
309 {
310  // Compute C
311  nonlinearEffects(model, Q, QDot, CS.C);
312  assert(CS.H.cols() == model.dof_count && CS.H.rows() == model.dof_count);
313 
314  // Compute H
315  compositeRigidBodyAlgorithm(model, Q, CS.H, false);
316 
317  calcContactJacobian(model, Q, CS, CS.G, false);
318 
319  // Compute gamma
320  unsigned int prev_body_id = 0;
321  Vector3d prev_body_point = Vector3d::Zero();
322  Vector3d gamma_i = Vector3d::Zero();
323 
324  CS.QDDot_0.setZero();
325  updateAccelerations(model, CS.QDDot_0);
326 
327  for (unsigned int i = 0; i < CS.size(); i++)
328  {
329  // only compute point accelerations when necessary
330  if (prev_body_id != CS.body[i] || prev_body_point != CS.point[i])
331  {
332  gamma_i = calcPointAcceleration(model, Q, QDot, CS.QDDot_0, CS.body[i], CS.point[i], false);
333  prev_body_id = CS.body[i];
334  prev_body_point = CS.point[i];
335  }
336 
337  // we also substract ContactData[i].acceleration such that the contact
338  // point will have the desired acceleration
339  CS.gamma[i] = CS.acceleration[i] - CS.normal[i].dot(gamma_i);
340  }
341 }
342 
344 {
345  calcContactSystemVariables(model, Q, QDot, Tau, CS);
346 
347  solveContactSystemDirect(CS.H, CS.G, Tau - CS.C, CS.gamma, QDDot, CS.force, CS.A, CS.b, CS.x, CS.linear_solver);
348 
349  // Copy back QDDot
350  for (unsigned int i = 0; i < model.dof_count; i++)
351  {
352  QDDot[i] = CS.x[i];
353  }
354 
355  // Copy back contact forces
356  for (unsigned int i = 0; i < CS.size(); i++)
357  {
358  CS.force[i] = -CS.x[model.dof_count + i];
359  }
360 }
361 
364 {
365  calcContactSystemVariables(model, Q, QDot, Tau, CS);
366 
367  solveContactSystemRangeSpaceSparse(model, CS.H, CS.G, Tau - CS.C, CS.gamma, QDDot, CS.force, CS.K, CS.a, CS.linear_solver);
368 }
369 
371 {
372  calcContactSystemVariables(model, Q, QDot, Tau, CS);
373 
374  CS.GT_qr.compute(CS.G.transpose());
375  CS.GT_qr.householderQ().evalTo(CS.GT_qr_Q);
376 
377  CS.Y = CS.GT_qr_Q.block(0, 0, QDot.rows(), CS.G.rows());
378  CS.Z = CS.GT_qr_Q.block(0, CS.G.rows(), QDot.rows(), QDot.rows() - CS.G.rows());
379 
380  solveContactSystemNullSpace(CS.H, CS.G, Tau - CS.C, CS.gamma, QDDot, CS.force, CS.Y, CS.Z, CS.qddot_y, CS.qddot_z, CS.linear_solver);
381 }
382 
383 void computeContactImpulsesDirect(Model& model, const Math::VectorNd& Q, const Math::VectorNd& QDotMinus, ConstraintSet& CS, Math::VectorNd& QDotPlus)
384 {
385  // Compute H
386  updateKinematicsCustom(model, &Q, NULL, NULL);
387  compositeRigidBodyAlgorithm(model, Q, CS.H, false);
388 
389  // Compute G
390  calcContactJacobian(model, Q, CS, CS.G, false);
391 
392  solveContactSystemDirect(CS.H, CS.G, CS.H * QDotMinus, CS.v_plus, QDotPlus, CS.impulse, CS.A, CS.b, CS.x, CS.linear_solver);
393 
394  // Copy back QDotPlus
395  for (unsigned int i = 0; i < model.dof_count; i++)
396  {
397  QDotPlus[i] = CS.x[i];
398  }
399 
400  // Copy back constraint impulses
401  for (unsigned int i = 0; i < CS.size(); i++)
402  {
403  CS.impulse[i] = CS.x[model.dof_count + i];
404  }
405 }
406 
408 {
409  // Compute H
410  updateKinematicsCustom(model, &Q, NULL, NULL);
411  compositeRigidBodyAlgorithm(model, Q, CS.H, false);
412 
413  // Compute G
414  calcContactJacobian(model, Q, CS, CS.G, false);
415 
416  solveContactSystemRangeSpaceSparse(model, CS.H, CS.G, CS.H * QDotMinus, CS.v_plus, QDotPlus, CS.impulse, CS.K, CS.a, CS.linear_solver);
417 }
418 
420 {
421  // Compute H
422  updateKinematicsCustom(model, &Q, NULL, NULL);
423  compositeRigidBodyAlgorithm(model, Q, CS.H, false);
424 
425  // Compute G
426  calcContactJacobian(model, Q, CS, CS.G, false);
427 
428  CS.GT_qr.compute(CS.G.transpose());
429  CS.GT_qr_Q = CS.GT_qr.householderQ();
430 
431  CS.Y = CS.GT_qr_Q.block(0, 0, QDotMinus.rows(), CS.G.rows());
432  CS.Z = CS.GT_qr_Q.block(0, CS.G.rows(), QDotMinus.rows(), QDotMinus.rows() - CS.G.rows());
433 
434  solveContactSystemNullSpace(CS.H, CS.G, CS.H * QDotMinus, CS.v_plus, QDotPlus, CS.impulse, CS.Y, CS.Z, CS.qddot_y, CS.qddot_z, CS.linear_solver);
435 }
436 
446 {
447  assert(QDDot.size() == model.dof_count);
448 
449  unsigned int i = 0;
450 
451  for (i = 1; i < model.mBodies.size(); i++)
452  {
453  model.I[i].setSpatialMatrix(model.IA[i]);
454  model.pA[i] = RobotDynamics::Math::SpatialForce(model.bodyFrames[i], model.v[i] % (model.I[i] * model.v[i])) -
455  CS.f_ext_constraints[i].changeFrameAndCopy(model.bodyFrames[i]);
456  }
457  for (i = model.mBodies.size() - 1; i > 0; i--)
458  {
459  unsigned int q_index = model.mJoints[i].q_index;
460  ReferenceFramePtr bodyFrame = model.bodyFrames[i];
461 
462  if (model.mJoints[i].mDoFCount == 3 && model.mJoints[i].mJointType != JointTypeCustom)
463  {
464  unsigned int lambda = model.lambda[i];
465  model.multdof3_u[i] = Vector3d(Tau[q_index], Tau[q_index + 1], Tau[q_index + 2]) - model.multdof3_S[i].transpose() * model.pA[i];
466 
467  if (lambda != 0)
468  {
469  SpatialMatrix Ia = model.IA[i] - (model.multdof3_U[i] * model.multdof3_Dinv[i] * model.multdof3_U[i].transpose());
470 
472  bodyFrame,
473  model.pA[i] + RobotDynamics::Math::SpatialForce(bodyFrame, Ia * model.c[i] + model.multdof3_U[i] * model.multdof3_Dinv[i] * model.multdof3_u[i]));
474 
475  model.IA[lambda].noalias() += (bodyFrame->getTransformFromParent().toMatrixTranspose() * Ia * bodyFrame->getTransformFromParent().toMatrix());
476  model.pA[lambda].noalias() += pa.changeFrameAndCopy(model.bodyFrames[model.lambda[i]]);
477  }
478  }
479  else if (model.mJoints[i].mDoFCount == 1 && model.mJoints[i].mJointType != JointTypeCustom)
480  {
481  model.u[i] = Tau[q_index] - model.S[i].dot(model.pA[i]);
482 
483  unsigned int lambda = model.lambda[i];
484  if (lambda != 0)
485  {
486  SpatialMatrix Ia = model.IA[i] - model.U[i] * (model.U[i] / model.d[i]).transpose();
488  model.pA[i] + RobotDynamics::Math::SpatialForce(bodyFrame, Ia * model.c[i] + model.U[i] * model.u[i] / model.d[i]));
489 
490  model.IA[lambda].noalias() += (bodyFrame->getTransformFromParent().toMatrixTranspose() * Ia * bodyFrame->getTransformFromParent().toMatrix());
491  model.pA[lambda].noalias() += pa.changeFrameAndCopy(model.bodyFrames[model.lambda[i]]);
492  }
493  }
494  else if (model.mJoints[i].mJointType == JointTypeCustom)
495  {
496  unsigned int kI = model.mJoints[i].custom_joint_index;
497  unsigned int dofI = model.mCustomJoints[kI]->mDoFCount;
498  unsigned int lambda = model.lambda[i];
499  VectorNd tau_temp = VectorNd::Zero(dofI);
500 
501  for (unsigned int z = 0; z < dofI; ++z)
502  {
503  tau_temp[z] = Tau[q_index + z];
504  }
505 
506  model.mCustomJoints[kI]->u = tau_temp - (model.mCustomJoints[kI]->S.transpose() * model.pA[i]);
507 
508  if (lambda != 0)
509  {
510  SpatialMatrix Ia = model.IA[i] - (model.mCustomJoints[kI]->U * model.mCustomJoints[kI]->Dinv * model.mCustomJoints[kI]->U.transpose());
511  SpatialForce pa(bodyFrame,
512  model.pA[i] + RobotDynamics::Math::SpatialForce(bodyFrame, Ia * model.c[i] + (model.mCustomJoints[kI]->U * model.mCustomJoints[kI]->Dinv *
513  model.mCustomJoints[kI]->u)));
514 
515  model.IA[lambda].noalias() += bodyFrame->getTransformFromParent().toMatrixTranspose() * Ia * bodyFrame->getTransformFromParent().toMatrix();
516  model.pA[lambda].noalias() += pa.changeFrameAndCopy(model.bodyFrames[model.lambda[i]]);
517  }
518  }
519  }
520 
521  model.a[0].set(SpatialVector(-model.gravity));
522 
523  for (i = 1; i < model.mBodies.size(); i++)
524  {
525  unsigned int q_index = model.mJoints[i].q_index;
526  unsigned int lambda = model.lambda[i];
527 
528  model.a[i].set(model.a[lambda].transform_copy(model.bodyFrames[i]->getTransformFromParent()) + model.c[i]);
529 
530  if (model.mJoints[i].mDoFCount == 3 && model.mJoints[i].mJointType != JointTypeCustom)
531  {
532  Vector3d qdd_temp = model.multdof3_Dinv[i] * (model.multdof3_u[i] - model.multdof3_U[i].transpose() * model.a[i]);
533 
534  QDDot[q_index] = qdd_temp[0];
535  QDDot[q_index + 1] = qdd_temp[1];
536  QDDot[q_index + 2] = qdd_temp[2];
537  model.a[i].set(model.a[i] + model.multdof3_S[i] * qdd_temp);
538  }
539  else if (model.mJoints[i].mDoFCount == 1 && model.mJoints[i].mJointType != JointTypeCustom)
540  {
541  QDDot[q_index] = (1. / model.d[i]) * (model.u[i] - model.U[i].dot(model.a[i]));
542  model.a[i].set(model.a[i] + model.S[i] * QDDot[q_index]);
543  }
544  else if (model.mJoints[i].mJointType == JointTypeCustom)
545  {
546  unsigned int kI = model.mJoints[i].custom_joint_index;
547  unsigned int dofI = model.mCustomJoints[kI]->mDoFCount;
548 
549  VectorNd qdd_temp = model.mCustomJoints[kI]->Dinv * (model.mCustomJoints[kI]->u - model.mCustomJoints[kI]->U.transpose() * model.a[i]);
550 
551  for (unsigned int z = 0; z < dofI; ++z)
552  {
553  QDDot[q_index + z] = qdd_temp[z];
554  }
555 
556  model.a[i].set(model.a[i] + (model.mCustomJoints[kI]->S * qdd_temp));
557  }
558  }
559 }
560 
568 void forwardDynamicsAccelerationDeltas(Model& model, ConstraintSet& CS, VectorNd& QDDot_t, const unsigned int body_id, const SpatialForceV& f_t)
569 {
570  assert(CS.d_pA.size() == model.mBodies.size());
571  assert(CS.d_a.size() == model.mBodies.size());
572  assert(CS.d_u.size() == model.mBodies.size());
573 
574  // TODO reset all values (debug)
575  for (unsigned int i = 0; i < model.mBodies.size(); i++)
576  {
577  CS.d_pA[i].setIncludingFrame(model.bodyFrames[i], 0., 0., 0., 0., 0., 0.);
578  CS.d_a[i].setZero();
579  CS.d_u[i] = 0.;
580  CS.d_multdof3_u[i].setZero();
581  }
582  for (unsigned int i = 0; i < model.mCustomJoints.size(); i++)
583  {
584  model.mCustomJoints[i]->d_u.setZero();
585  }
586 
587  for (unsigned int i = body_id; i > 0; i--)
588  {
589  if (i == body_id)
590  {
591  CS.d_pA[i].setIncludingFrame(model.bodyFrames[i], -f_t[i].changeFrameAndCopy(model.bodyFrames[i]));
592  }
593 
594  if (model.mJoints[i].mDoFCount == 3 && model.mJoints[i].mJointType != JointTypeCustom)
595  {
596  CS.d_multdof3_u[i] = -model.multdof3_S[i].transpose() * (CS.d_pA[i]);
597 
598  unsigned int lambda = model.lambda[i];
599  if (lambda != 0)
600  {
601  RobotDynamics::Math::SpatialForce f(model.bodyFrames[i], CS.d_pA[i] + model.multdof3_U[i] * model.multdof3_Dinv[i] * CS.d_multdof3_u[i]);
602  CS.d_pA[lambda] += f.changeFrameAndCopy(model.bodyFrames[model.lambda[i]]);
603  }
604  }
605  else if (model.mJoints[i].mDoFCount == 1 && model.mJoints[i].mJointType != JointTypeCustom)
606  {
607  CS.d_u[i] = -model.S[i].dot(CS.d_pA[i]);
608  unsigned int lambda = model.lambda[i];
609 
610  if (lambda != 0)
611  {
612  RobotDynamics::Math::SpatialForce f(model.bodyFrames[i], CS.d_pA[i] + model.U[i] * CS.d_u[i] / model.d[i]);
613  CS.d_pA[lambda] += f.changeFrameAndCopy(model.bodyFrames[model.lambda[i]]);
614  }
615  }
616  else if (model.mJoints[i].mJointType == JointTypeCustom)
617  {
618  unsigned int kI = model.mJoints[i].custom_joint_index;
619  // CS.
620  model.mCustomJoints[kI]->d_u = -model.mCustomJoints[kI]->S.transpose() * (CS.d_pA[i]);
621  unsigned int lambda = model.lambda[i];
622  if (lambda != 0)
623  {
625  CS.d_pA[i] + (model.mCustomJoints[kI]->U * model.mCustomJoints[kI]->Dinv * model.mCustomJoints[kI]->d_u));
626  CS.d_pA[lambda] += f.changeFrameAndCopy(model.bodyFrames[model.lambda[i]]);
627  }
628  }
629  }
630 
631  QDDot_t[0] = 0.;
632  CS.d_a[0] = model.a[0];
633 
634  for (unsigned int i = 1; i < model.mBodies.size(); i++)
635  {
636  unsigned int q_index = model.mJoints[i].q_index;
637  unsigned int lambda = model.lambda[i];
638 
639  SpatialVector Xa = model.bodyFrames[i]->getTransformFromParent().apply(CS.d_a[lambda]);
640 
641  if (model.mJoints[i].mDoFCount == 3 && model.mJoints[i].mJointType != JointTypeCustom)
642  {
643  Vector3d qdd_temp = model.multdof3_Dinv[i] * (CS.d_multdof3_u[i] - model.multdof3_U[i].transpose() * Xa);
644 
645  QDDot_t[q_index] = qdd_temp[0];
646  QDDot_t[q_index + 1] = qdd_temp[1];
647  QDDot_t[q_index + 2] = qdd_temp[2];
648  model.a[i].set(model.a[i] + model.multdof3_S[i] * qdd_temp);
649  CS.d_a[i] = Xa + model.multdof3_S[i] * qdd_temp;
650  }
651  else if (model.mJoints[i].mDoFCount == 1 && model.mJoints[i].mJointType != JointTypeCustom)
652  {
653  QDDot_t[q_index] = (CS.d_u[i] - model.U[i].dot(Xa)) / model.d[i];
654  CS.d_a[i] = Xa + model.S[i] * QDDot_t[q_index];
655  }
656  else if (model.mJoints[i].mJointType == JointTypeCustom)
657  {
658  unsigned int kI = model.mJoints[i].custom_joint_index;
659  unsigned int dofI = model.mCustomJoints[kI]->mDoFCount;
660 
661  VectorNd qdd_temp = model.mCustomJoints[kI]->Dinv * (model.mCustomJoints[kI]->d_u - model.mCustomJoints[kI]->U.transpose() * Xa);
662 
663  for (unsigned int z = 0; z < dofI; ++z)
664  {
665  QDDot_t[q_index + z] = qdd_temp[z];
666  }
667 
668  model.a[i].set(model.a[i] + model.mCustomJoints[kI]->S * qdd_temp);
669  CS.d_a[i] = Xa + model.mCustomJoints[kI]->S * qdd_temp;
670  }
671  }
672 }
673 
674 inline void set_zero(std::vector<SpatialVector>& spatial_values)
675 {
676  for (unsigned int i = 0; i < spatial_values.size(); i++)
677  {
678  spatial_values[i].setZero();
679  }
680 }
681 
683 {
684  assert(CS.f_ext_constraints.size() == model.mBodies.size());
685  assert(CS.QDDot_0.size() == model.dof_count);
686  assert(CS.QDDot_t.size() == model.dof_count);
687  assert(CS.f_t.size() == CS.size());
688  assert(CS.point_accel_0.size() == CS.size());
689  assert(CS.K.rows() == CS.size());
690  assert(CS.K.cols() == CS.size());
691  assert(CS.force.size() == CS.size());
692  assert(CS.a.size() == CS.size());
693 
694  Vector3d point_accel_t;
695 
696  unsigned int ci = 0;
697 
698  // The default acceleration only needs to be computed once
699  forwardDynamics(model, Q, QDot, Tau, CS.QDDot_0);
700 
701  // we have to compute the standard accelerations first as we use them to
702  // compute the effects of each test force
703  for (ci = 0; ci < CS.size(); ci++)
704  {
705  unsigned int body_id = CS.body[ci];
706  Vector3d point = CS.point[ci];
707  Vector3d normal = CS.normal[ci];
708  double acceleration = CS.acceleration[ci];
709 
710  updateAccelerations(model, CS.QDDot_0);
711  CS.point_accel_0[ci] = calcPointAcceleration(model, Q, QDot, CS.QDDot_0, body_id, point, false);
712 
713  CS.a[ci] = -acceleration + normal.dot(CS.point_accel_0[ci]);
714  }
715 
716  // Now we can compute and apply the test forces and use their net effect
717  // to compute the inverse articlated inertia to fill K.
719  for (ci = 0; ci < CS.size(); ci++)
720  {
721  unsigned int body_id = CS.body[ci];
722  Vector3d point = CS.point[ci];
723  Vector3d normal = CS.normal[ci];
724 
725  unsigned int movable_body_id = body_id;
726  if (model.IsFixedBodyId(body_id))
727  {
728  unsigned int fbody_id = body_id - model.fixed_body_discriminator;
729  movable_body_id = model.mFixedBodies[fbody_id].mMovableParent;
730  p.setIncludingFrame(point, model.fixedBodyFrames[fbody_id]);
731  p.changeFrame(model.worldFrame);
732  }
733  else
734  {
735  p.setIncludingFrame(point, model.bodyFrames[body_id]);
736  p.changeFrame(model.worldFrame);
737  }
738 
739  // Review this frame xform, might not be right
740  CS.f_t[ci].setIncludingFrame(model.worldFrame, p.vec().cross(-normal), -normal);
741  CS.f_ext_constraints[movable_body_id] = CS.f_t[ci];
742 
743  forwardDynamicsAccelerationDeltas(model, CS, CS.QDDot_t, movable_body_id, CS.f_ext_constraints);
744 
745  CS.f_ext_constraints[movable_body_id].setIncludingFrame(model.worldFrame, 0., 0., 0., 0., 0., 0.);
746 
747  CS.QDDot_t += CS.QDDot_0;
748 
749  // compute the resulting acceleration
750  updateAccelerations(model, CS.QDDot_t);
751 
752  for (unsigned int cj = 0; cj < CS.size(); cj++)
753  {
754  point_accel_t = calcPointAcceleration(model, Q, QDot, CS.QDDot_t, CS.body[cj], CS.point[cj], false);
755 
756  CS.K(ci, cj) = CS.normal[cj].dot(point_accel_t - CS.point_accel_0[cj]);
757  }
758  }
759 
760  bool solve_successful = linSolveGaussElimPivot(CS.K, CS.a, CS.force);
761  assert(solve_successful);
762  for (ci = 0; ci < CS.size(); ci++)
763  {
764  unsigned int body_id = CS.body[ci];
765  unsigned int movable_body_id = body_id;
766 
767  if (model.IsFixedBodyId(body_id))
768  {
769  unsigned int fbody_id = body_id - model.fixed_body_discriminator;
770  movable_body_id = model.mFixedBodies[fbody_id].mMovableParent;
771  }
772  CS.f_ext_constraints[movable_body_id] -= CS.f_t[ci] * CS.force[ci];
773  }
774 
775  forwardDynamicsApplyConstraintForces(model, Tau, CS, QDDot);
776 }
777 
778 } /* namespace RobotDynamics */
Math::VectorNd C
Workspace for the coriolis forces.
Definition: Contacts.h:260
Math::SpatialForceV f_t
Workspace for the test forces.
Definition: Contacts.h:299
std::vector< Math::SpatialMatrix > IA
The spatial inertia of the bodies.
Definition: Model.h:251
void compositeRigidBodyAlgorithm(Model &model, const Math::VectorNd &Q, Math::MatrixNd &H, bool update_kinematics=true)
Computes the joint space inertia matrix by using the Composite Rigid Body Algorithm.
Definition: Dynamics.cc:302
Math::SpatialForceV f_ext_constraints
Workspace for the actual spatial forces.
Definition: Contacts.h:302
void computeContactImpulsesDirect(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDotMinus, ConstraintSet &CS, Math::VectorNd &QDotPlus)
Computes contact gain by constructing and solving the full lagrangian equation.
Definition: Contacts.cc:383
bool IsFixedBodyId(unsigned int body_id) const
Checks whether the body is rigidly attached to another body.
Definition: Model.h:483
std::vector< SpatialForce, Eigen::aligned_allocator< SpatialForce > > SpatialForceV
File containing the FramePoint<T> object definition.
void calcPointJacobian(Model &model, const Math::VectorNd &Q, unsigned int body_id, const Math::Vector3d &point_position, Math::MatrixNd &G, bool update_kinematics=true)
Computes the 3D point jacobian for a point on a body.
Definition: Kinematics.cc:510
Math::VectorNd b
Workspace for the Lagrangian right-hand-side.
Definition: Contacts.h:270
std::vector< Joint > mJoints
All joints.
Definition: Model.h:209
Math::VectorNd impulse
Definition: Contacts.h:248
SpatialVector SpatialVectorZero
A FramePoint is a 3D point that is expressed in a ReferenceFrame. To change the ReferenceFrame a Fram...
Definition: FramePoint.hpp:40
Math::VectorNd u
Temporary variable u (RBDA p. 130)
Definition: Model.h:263
VectorNd Tau
void calcContactJacobian(Model &model, const Math::VectorNd &Q, const ConstraintSet &CS, Math::MatrixNd &G, bool update_kinematics=true)
Computes the Jacobian for the given ConstraintSet.
Definition: Contacts.cc:275
void calcContactSystemVariables(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS)
Definition: Contacts.cc:308
User defined joints of varying size.
Definition: Joint.h:213
void clear()
Clears all variables in the constraint set.
Definition: Contacts.cc:127
Math::VectorNd a
Workspace for the accelerations of due to the test forces.
Definition: Contacts.h:290
VectorNd QDDot
std::vector< Math::Matrix63 > multdof3_U
Definition: Model.h:237
Math::MatrixNd GT_qr_Q
Definition: Contacts.h:278
std::vector< FixedBody > mFixedBodies
All bodies that are attached to a body via a fixed joint.
Definition: Model.h:298
std::vector< unsigned int > lambda
Definition: Model.h:156
bool linSolveGaussElimPivot(MatrixNd A, VectorNd b, VectorNd &x)
Solves a linear system using gaussian elimination with pivoting.
VectorNd QDot
void set_zero(std::vector< SpatialVector > &spatial_values)
Definition: Contacts.cc:674
Math::VectorNd ndof0_vec
Definition: Model.h:284
VectorNd Q
Math::SpatialForceV d_pA
Workspace for the bias force due to the test force.
Definition: Contacts.h:308
unsigned int addConstraint(unsigned int body_id, const Math::Vector3d &body_point, const Math::Vector3d &world_normal, const char *constraint_name=NULL, double normal_acceleration=0.)
Adds a constraint to the constraint set.
Definition: Contacts.cc:27
std::vector< Math::Vector3d > point
Definition: Contacts.h:237
Math::MatrixNd A
Workspace for the Lagrangian left-hand-side matrix.
Definition: Contacts.h:267
Math::FrameVector calcPointAcceleration(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &QDDot, unsigned int body_id, const Math::Vector3d &point_position, bool update_kinematics=true)
Computes the linear acceleration of a point on a body.
Definition: Kinematics.cc:1593
Math::MotionVector gravity
the cartesian vector of the gravity
Definition: Model.h:196
Math::VectorNd acceleration
Definition: Contacts.h:242
std::vector< ReferenceFramePtr > bodyFrames
Definition: Model.h:145
Math::VectorNd nbodies0_vec
Definition: Model.h:285
ReferenceFramePtr worldFrame
Definition: Model.h:141
void computeContactImpulsesRangeSpaceSparse(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDotMinus, ConstraintSet &CS, Math::VectorNd &QDotPlus)
Resolves contact gain using solveContactSystemRangeSpaceSparse()
Definition: Contacts.cc:407
void forwardDynamicsContactsRangeSpaceSparse(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS, Math::VectorNd &QDDot)
Definition: Contacts.cc:362
Math::VectorNd QDDot_t
Workspace for the test accelerations.
Definition: Contacts.h:293
std::vector< Math::Vector3d > d_multdof3_u
Definition: Contacts.h:323
EIGEN_STRONG_INLINE void setIncludingFrame(const Math::Vector3d &v, ReferenceFramePtr referenceFrame)
Set both the ReferenceFrame this object is expressed in as well as the (x,y,z) coordinates of the poi...
Definition: FramePoint.hpp:138
LinearSolver
Available solver methods for the linear systems.
Definition: rdl_mathutils.h:34
EIGEN_STRONG_INLINE Math::Vector3d vec() const
Definition: Point3.hpp:269
Math::SpatialMotionV v
Definition: Model.h:202
std::shared_ptr< ReferenceFrame > ReferenceFramePtr
void forwardDynamicsContactsDirect(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS, Math::VectorNd &QDDot)
Computes forward dynamics with contact by constructing and solving the full lagrangian equation...
Definition: Contacts.cc:343
Structure that contains both constraint information and workspace memory.
Definition: Contacts.h:168
Math::MatrixNd ndof0_mat
Definition: Model.h:281
virtual void changeFrame(ReferenceFramePtr desiredFrame)
Change the ReferenceFrame this FrameObject is expressed in.
Definition: FrameObject.cpp:12
Math::SpatialForceV pA
The spatial bias force.
Definition: Model.h:254
std::vector< Body > mBodies
All bodies 0 ... N_B, including the base.
Definition: Model.h:321
Math::VectorNd gamma
Workspace of the lower part of b.
Definition: Contacts.h:263
void solveContactSystemRangeSpaceSparse(Model &model, Math::MatrixNd &H, const Math::MatrixNd &G, const Math::VectorNd &c, const Math::VectorNd &gamma, Math::VectorNd &qddot, Math::VectorNd &lambda, Math::MatrixNd &K, Math::VectorNd &a, Math::LinearSolver linear_solver)
Solves the contact system by first solving for the the joint accelerations and then the contact force...
Definition: Contacts.cc:206
std::vector< unsigned int > body
Definition: Contacts.h:236
std::vector< Math::Vector3d > point_accel_0
Workspace for the default point accelerations.
Definition: Contacts.h:305
Math::VectorNd d
Temporary variable D_i (RBDA p. 130)
Definition: Model.h:260
Eigen::VectorXd VectorNd
Definition: rdl_eigenmath.h:25
void forwardDynamicsContactsNullSpace(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS, Math::VectorNd &QDDot)
Definition: Contacts.cc:370
Math::VectorNd QDDot_0
Workspace for the default accelerations.
Definition: Contacts.h:296
Math::SpatialAccelerationV a
The spatial velocity of the bodies.
Definition: Model.h:200
std::vector< CustomJoint * > mCustomJoints
Definition: Model.h:242
std::vector< Math::Matrix3d > multdof3_Dinv
Definition: Model.h:238
Contains all information about the rigid body model.
Definition: Model.h:121
void updateKinematicsCustom(Model &model, const Math::VectorNd *Q, const Math::VectorNd *QDot=nullptr, const Math::VectorNd *QDDot=nullptr)
Selectively updates model internal states of body positions, velocities and/or accelerations.
Definition: Kinematics.cc:72
bool bind(const Model &model)
Initializes and allocates memory for the constraint set.
Definition: Contacts.cc:62
void computeContactImpulsesNullSpace(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDotMinus, ConstraintSet &CS, Math::VectorNd &QDotPlus)
Resolves contact gain using solveContactSystemNullSpace()
Definition: Contacts.cc:419
std::vector< Math::SpatialVector > U
Temporary variable U_i (RBDA p. 130)
Definition: Model.h:257
Math::SpatialInertiaV I
Definition: Model.h:269
void SparseFactorizeLTL(Model &model, Math::MatrixNd &H)
Eigen::MatrixXd MatrixNd
Definition: rdl_eigenmath.h:26
std::vector< Math::SpatialVector > c
The velocity dependent spatial acceleration.
Definition: Model.h:248
Math::VectorNd qddot_y
Definition: Contacts.h:281
unsigned int fixed_body_discriminator
Value that is used to discriminate between fixed and movable bodies.
Definition: Model.h:312
Eigen::HouseholderQR< Math::MatrixNd > GT_qr
Workspace for the QR decomposition of the null-space method.
Definition: Contacts.h:276
SpatialMatrix SpatialMatrixIdentity
Math::MatrixNd K
Workspace for the Inverse Articulated-Body Inertia.
Definition: Contacts.h:287
A SpatialForce is a spatial vector with the angular part being three moments and the linear part bein...
std::vector< Math::SpatialVector > d_a
Workspace for the acceleration due to the test force.
Definition: Contacts.h:311
void SparseSolveLTx(Model &model, Math::MatrixNd &L, Math::VectorNd &x)
Math::LinearSolver linear_solver
Method that should be used to solve internal linear systems.
Definition: Contacts.h:230
std::vector< Math::Matrix63 > multdof3_S
Motion subspace for joints with 3 degrees of freedom.
Definition: Model.h:235
void updateAccelerations(Model &model, const Math::VectorNd &QDDot)
Computes only the accelerations of the bodies.
Definition: Kinematics.cc:152
std::vector< ReferenceFramePtr > fixedBodyFrames
Definition: Model.h:154
void SparseSolveLx(Model &model, Math::MatrixNd &L, Math::VectorNd &x)
void forwardDynamics(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, Math::VectorNd &QDDot, Math::SpatialForceV *f_ext=nullptr, bool update_kinematics=true)
Computes forward dynamics with the Articulated Body Algorithm.
Definition: Dynamics.cc:455
void forwardDynamicsAccelerationDeltas(Model &model, ConstraintSet &CS, VectorNd &QDDot_t, const unsigned int body_id, const SpatialForceV &f_t)
Computes the effect of external forces on the generalized accelerations.
Definition: Contacts.cc:568
std::vector< Math::Vector3d > multdof3_u
Definition: Model.h:239
void solveContactSystemNullSpace(Math::MatrixNd &H, const Math::MatrixNd &G, const Math::VectorNd &c, const Math::VectorNd &gamma, Math::VectorNd &qddot, Math::VectorNd &lambda, Math::MatrixNd &Y, Math::MatrixNd &Z, Math::VectorNd &qddot_y, Math::VectorNd &qddot_z, Math::LinearSolver &linear_solver)
Solves the contact system by first solving for the joint accelerations and then for the constraint fo...
Definition: Contacts.cc:234
SpatialForce changeFrameAndCopy(ReferenceFramePtr referenceFrame) const
Copy and change frame.
void solveContactSystemDirect(Math::MatrixNd &H, const Math::MatrixNd &G, const Math::VectorNd &c, const Math::VectorNd &gamma, Math::VectorNd &qddot, Math::VectorNd &lambda, Math::MatrixNd &A, Math::VectorNd &b, Math::VectorNd &x, Math::LinearSolver &linear_solver)
Solves the full contact system directly, i.e. simultaneously for contact forces and joint acceleratio...
Definition: Contacts.cc:175
void forwardDynamicsApplyConstraintForces(Model &model, const VectorNd &Tau, ConstraintSet &CS, VectorNd &QDDot)
Compute only the effects of external forces on the generalized accelerations.
Definition: Contacts.cc:445
void nonlinearEffects(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, Math::VectorNd &Tau, bool update_kinematics=true)
Computes the coriolis forces.
Definition: Dynamics.cc:236
unsigned int dof_count
number of degrees of freedoms of the model
Definition: Model.h:169
Math::VectorNd qddot_z
Definition: Contacts.h:282
Namespace for all structures of the RobotDynamics library.
Definition: Body.h:21
Math::VectorNd x
Workspace for the Lagrangian solution.
Definition: Contacts.h:273
Math::MatrixNd H
Workspace for the joint space inertia matrix.
Definition: Contacts.h:257
Math::MotionVectorV S
Definition: Model.h:211
std::vector< Math::Vector3d > normal
Definition: Contacts.h:238
void forwardDynamicsContactsKokkevis(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS, Math::VectorNd &QDDot)
Computes forward dynamics that accounts for active contacts in ConstraintSet.
Definition: Contacts.cc:682
size_t size() const
Returns the number of constraints.
Definition: Contacts.h:221


rdl_dynamics
Author(s):
autogenerated on Tue Apr 20 2021 02:25:27