33void SolveLinearSystem (
40unsigned int GetMovableBodyId (Model& model,
unsigned int id);
50 const char *constraint_name,
51 unsigned int userDefinedId)
53 assert (
bound ==
false);
56 unsigned int insertAtRowInG =
size();
57 unsigned int rowsInG = insertAtRowInG+1;
60 if(constraint_name != NULL) {
61 nameStr = constraint_name;
72 bool constraintAppended =
false;
79#ifdef RBDL_USE_CASADI_MATH
82 if(pointErr.norm() < std::numeric_limits<double>::epsilon()*100 &&
85 constraintAppended =
true;
91 if(constraintAppended ==
false) {
94 std::shared_ptr<ContactConstraint>(
95 new ContactConstraint(body_id,body_point, world_normal, constraint_name,userDefinedId)));
103 name.push_back (nameStr);
107 err[insertAtRowInG] = 0.;
109 errd[insertAtRowInG] = 0.;
112 force[insertAtRowInG] = 0.;
118 v_plus[insertAtRowInG] = 0.;
121 Math::Vector3d::Zero());
124 if(nameStr.size() > 0) {
125 std::pair< std::map<std::string, unsigned int>::iterator,
bool > iter;
126 iter =
nameGroupMap.insert(std::pair<std::string, unsigned int>(
137 if(userDefinedId < std::numeric_limits<unsigned int>::max()) {
138 std::pair< std::map<unsigned int, unsigned int>::iterator,
bool > iter;
150 std::pair< std::map<unsigned int, unsigned int>::iterator,
bool > iter;
151 iter =
idGroupMap.insert(std::pair<unsigned int, unsigned int>(
154 if(iter.second ==
false) {
155 std::cerr <<
"Error: Constraint row entry in system is not unique."
156 <<
" (This should not be possible: contact the "
157 "maintainer of this code.)"
169 unsigned int idPredecessor,
170 unsigned int idSuccessor,
171 const Math::SpatialTransform &XPredecessor,
172 const Math::SpatialTransform &XSuccessor,
175 double stabilizationTimeConstant,
176 const char *constraintName,
177 unsigned int userDefinedId)
179 assert (
bound ==
false);
182 unsigned int insertAtRowInG = unsigned(
size());
183 unsigned int rowsInG = insertAtRowInG+1;
185 double tol = std::numeric_limits<double>::epsilon()*100.;
186 bool constraintAppended =
false;
194 bool framesNumericallyIdentical=
true;
195 SpatialTransform frameErrorPre, frameErrorSuc;
197 frameErrorPre.r=XPredecessor.r-
loopConstraints[idx]->getBodyFrames()[0].r;
198 frameErrorPre.E=XPredecessor.E-
loopConstraints[idx]->getBodyFrames()[0].E;
200 frameErrorSuc.r=XSuccessor.r -
loopConstraints[idx]->getBodyFrames()[1].r;
201 frameErrorSuc.E=XSuccessor.E -
loopConstraints[idx]->getBodyFrames()[1].E;
205#ifndef RBDL_USE_CASADI_MATH
206 for(
unsigned int i=0; i<frameErrorPre.r.size(); ++i) {
207 if(
fabs(frameErrorPre.r[i]) > tol ||
fabs(frameErrorSuc.r[i]) > tol) {
208 framesNumericallyIdentical=
false;
210 for(
unsigned int j=0; j<frameErrorPre.E.cols(); ++j) {
211 if(
fabs(frameErrorPre.E(i,j))>tol ||
fabs(frameErrorSuc.E(i,j))>tol) {
212 framesNumericallyIdentical=
false;
218 if(framesNumericallyIdentical
220 constraintAppended =
true;
221 loopConstraints[idx]->appendConstraintAxis(constraintAxisInPredecessor);
226 if(constraintAppended==
false) {
229 std::shared_ptr<LoopConstraint>(
231 idPredecessor, idSuccessor,XPredecessor, XSuccessor,
233 stabilizationTimeConstant,constraintName,userDefinedId)));
244 if (constraintName != NULL) {
245 nameStr = constraintName;
248 name.push_back (nameStr);
252 err[insertAtRowInG] = 0.;
254 errd[insertAtRowInG] = 0.;
257 force[insertAtRowInG] = 0.;
263 v_plus[insertAtRowInG] = 0.;
265 d_multdof3_u = std::vector<Math::Vector3d>(rowsInG, Math::Vector3d::Zero());
268 if(nameStr.size() > 0) {
269 std::pair< std::map<std::string, unsigned int>::iterator,
bool > iter;
270 iter =
nameGroupMap.insert(std::pair<std::string, unsigned int>(
282 if(userDefinedId < std::numeric_limits<unsigned int>::max()) {
283 std::pair< std::map<unsigned int, unsigned int>::iterator,
bool > iter;
295 std::pair< std::map<unsigned int, unsigned int>::iterator,
bool > iter;
296 iter =
idGroupMap.insert(std::pair<unsigned int, unsigned int>(
299 if(iter.second ==
false) {
300 std::stringstream errormsg;
301 errormsg <<
"Error: Constraint row entry in system is not unique."
302 <<
" (This should not be possible: contact the "
303 "maintainer of this code.)"
305 throw Errors::RBDLError(errormsg.str());
315 std::shared_ptr<Constraint> customConstraint)
317 unsigned int insertAtRowInG = unsigned(
size());
318 unsigned int rowsInG = insertAtRowInG+customConstraint->getConstraintSize();
322 constraints[cIndex]->addToConstraintSet(insertAtRowInG);
325 std::string nameStr(
"");
326 if(customConstraint->getName() != NULL) {
327 nameStr = customConstraint->getName();
335 d_multdof3_u = std::vector<Math::Vector3d>(rowsInG, Math::Vector3d::Zero());
337 for(
unsigned int i=0; i<customConstraint->getConstraintSize(); ++i) {
340 name.push_back (nameStr);
344 err[ insertAtRowInG+i ] = 0.;
345 errd[ insertAtRowInG+i ] = 0.;
346 force[ insertAtRowInG+i ] = 0.;
347 impulse[ insertAtRowInG+i ] = 0.;
348 v_plus[ insertAtRowInG+i ] = 0.;
352 if(nameStr.size() > 0) {
353 std::pair< std::map<std::string, unsigned int>::iterator,
bool > iter;
354 iter =
nameGroupMap.insert(std::pair<std::string, unsigned int>(
357 if(iter.second ==
false) {
358 throw Errors::RBDLError(
"Error: optional name is not unique.\n");
362 if(customConstraint->getUserDefinedId()
363 < std::numeric_limits<unsigned int>::max()) {
364 std::pair< std::map<unsigned int, unsigned int>::iterator,
bool > iter;
366 customConstraint->getUserDefinedId(),
368 if(iter.second ==
false) {
369 throw Errors::RBDLError(
"Error: optional userDefinedId is not unique.\n");
374 std::pair< std::map<unsigned int, unsigned int>::iterator,
bool > iter;
375 iter =
idGroupMap.insert(std::pair<unsigned int, unsigned int>(
378 if(iter.second ==
false) {
379 std::stringstream errormsg;
380 errormsg <<
"Error: Constraint row entry into system is not unique."
381 <<
" (This should not be possible: contact the "
382 "maintainer of this code.)"
384 throw Errors::RBDLError(errormsg.str());
395 assert (
bound ==
false);
398 throw Errors::RBDLError(
"Error: binding an already bound constraint set!\n");
421 unsigned int n_constr =
size();
442 W.
Identity(model.dof_count, model.dof_count);
445#ifndef RBDL_USE_CASADI_MATH
460 f_t.resize (n_constr, SpatialVector::Zero());
470 d_pA =std::vector<SpatialVector> (model.mBodies.size(),SpatialVector::Zero());
471 d_a = std::vector<SpatialVector> (model.mBodies.size(),SpatialVector::Zero());
474 d_IA = std::vector<SpatialMatrix> (model.mBodies.size()
475 , SpatialMatrix::Identity());
476 d_U = std::vector<SpatialVector> (model.mBodies.size(),SpatialVector::Zero());
479 d_multdof3_u = std::vector<Math::Vector3d> (model.mBodies.size()
480 , Math::Vector3d::Zero());
489 const std::vector<bool> &actuatedDofUpd)
492 assert(actuatedDofUpd.size() == model.dof_count);
494 unsigned int n = unsigned(
int( model.dof_count ));
495 unsigned int nc = unsigned(
int(
name.size() ));
499 for(
unsigned int i=0; i<actuatedDofUpd.size(); ++i) {
500 if(actuatedDofUpd[i]) {
522 for(
unsigned int i=0; i<model.dof_count; ++i) {
523 if(actuatedDofUpd[i]) {
532 unsigned int dim = n+n+nc+na;
627 for(
unsigned int i=0; i<
f_t.size(); ++i) {
634 for (i = 0; i <
f_t.size(); i++) {
646 for (i = 0; i <
d_pA.size(); i++) {
650 for (i = 0; i <
d_a.size(); i++) {
673 A.
block(0, 0, c.rows(), c.rows()) =
H;
680 b.
block(0, 0, c.rows(), 1) = c;
683 LOG <<
"A = " << std::endl <<
A << std::endl;
684 LOG <<
"b = " << std::endl <<
b << std::endl;
686#ifdef RBDL_USE_CASADI_MATH
687 auto linsol = casadi::Linsol(
"linear_solver",
"symbolicqr",
A.sparsity());
688 x = linsol.solve(
A,
b);
692 x =
A.partialPivLu().solve(
b);
695 x =
A.colPivHouseholderQr().solve(
b);
698 x =
A.householderQr().solve(
b);
701 LOG <<
"Error: Invalid linear solver: " <<
linear_solver << std::endl;
707 LOG <<
"x = " << std::endl <<
x << std::endl;
729 for (
unsigned int i = 0; i <
Y.
cols(); i++) {
741#ifdef RBDL_USE_CASADI_MATH
742 auto linsol = casadi::Linsol(
"linear_solver",
"symbolicqr",
K.sparsity());
743 lambda = linsol.solve(
K,
a);
745 lambda =
K.llt().solve(
a);
770#ifdef RBDL_USE_CASADI_MATH
772 auto linsol = casadi::Linsol(
"linear_solver",
"symbolicqr", GY.sparsity());
786 LOG <<
"Error: Invalid linear solver: " <<
linear_solver << std::endl;
792#ifdef RBDL_USE_CASADI_MATH
794 linsol = casadi::Linsol(
"linear_solver",
"symbolicqr", ZHZ.sparsity());
801#ifdef RBDL_USE_CASADI_MATH
803 linsol = casadi::Linsol(
"linear_solver",
"symbolicqr", GY.sparsity());
804 lambda = linsol.solve(GY,
Y.
transpose() * (
H * qddot - c));
808 lambda = (
G *
Y).partialPivLu().solve (
Y.
transpose() * (
H * qddot - c));
811 lambda = (
G*
Y).colPivHouseholderQr().solve (
Y.
transpose()*(
H*qddot - c));
814 lambda = (
G *
Y).householderQr().solve (
Y.
transpose() * (
H * qddot - c));
817 LOG <<
"Error: Invalid linear solver: " <<
linear_solver << std::endl;
832 bool update_kinematics
835 assert(
err.
size() == CS.size());
837 if(update_kinematics) {
841 for(
unsigned int i=0; i<CS.constraints.size(); ++i) {
842 CS.constraints[i]->calcPositionError(model,0,Q,
err, CS.cache,
854 bool update_kinematics
857 if (update_kinematics) {
861 for(
unsigned int i=0; i<CS.constraints.size(); ++i) {
862 CS.constraints[i]->calcConstraintJacobian(model,0,Q,CS.cache.vecNZeros,
G,
863 CS.cache,update_kinematics);
875 bool update_kinematics
882 for(
unsigned int i=0; i<CS.constraints.size(); ++i) {
883 CS.constraints[i]->calcVelocityError(model,0,Q,QDot,CS.G,
err,CS.cache,
897 bool update_kinematics,
898 std::vector<Math::SpatialVector> *f_ext
902 if(update_kinematics){
908 assert(CS.H.cols() == model.dof_count && CS.H.rows() == model.dof_count);
924 unsigned int prev_body_id = 0;
925 Vector3d prev_body_point = Vector3d::Zero();
926 Vector3d gamma_i = Vector3d::Zero();
928 CS.QDDot_0.setZero();
932 for(
unsigned int i=0; i<CS.constraints.size(); ++i) {
933 CS.constraints[i]->calcGamma(model,0,Q,QDot,CS.G,CS.gamma,CS.cache);
934 if(CS.constraints[i]->isBaumgarteStabilizationEnabled()) {
935 CS.constraints[i]->addInBaumgarteStabilizationForces(
936 CS.err,CS.errd,CS.gamma);
944#ifndef RBDL_USE_CASADI_MATH
953 unsigned int max_iter
957 if(Q.size() != model.q_size) {
958 throw Errors::RBDLDofMismatchError(
"Incorrect Q vector size.\n");
960 if(QInit.size() != model.q_size) {
961 throw Errors::RBDLDofMismatchError(
"Incorrect QInit vector size.\n");
963 if(weights.size() != model.dof_count) {
964 throw Errors::RBDLDofMismatchError(
"Incorrect weights vector size.\n");
968 MatrixNd constraintJac (cs.size(), model.dof_count);
977 for(
unsigned int i = 0; i < weights.size(); ++i) {
984 if (e.norm() < tolerance) {
991 for(
unsigned int it = 0; it < max_iter; ++it) {
993 constraintJac.setZero();
995 A.
block (model.dof_count, 0, cs.size(), model.dof_count) = constraintJac;
996 A.
block (0, model.dof_count, model.dof_count, cs.size())
997 = constraintJac.transpose();
998 b.
block (model.dof_count, 0, cs.size(), 1) = -e;
1001 SolveLinearSystem (
A,
b,
x, cs.linear_solver);
1004 d =
x.
block (0, 0, model.dof_count, 1);
1007 for (
size_t i = 0; i < model.mJoints.size(); ++i) {
1010 if (model.mJoints[i].mJointType == JointTypeSpherical) {
1011 Quaternion quat = model.GetQuaternion(i, QInit);
1012 Vector3d omega = d.block<3,1>(model.mJoints[i].q_index,0);
1015 quat += quat.omegaToQDot(omega);
1017 quat /= quat.norm();
1018 model.SetQuaternion(i, quat, QInit);
1023 unsigned int qIdx = model.mJoints[i].q_index;
1024 for(
size_t j = 0; j < model.mJoints[i].mDoFCount; ++j) {
1025 QInit[qIdx + j] += d[qIdx + j];
1034 if (e.norm() < tolerance && d.norm() < tolerance) {
1057 if(QDot.size() != model.dof_count) {
1058 throw Errors::RBDLDofMismatchError(
"Incorrect QDot vector size.\n");
1060 if(Q.size() != model.q_size) {
1061 throw Errors::RBDLDofMismatchError(
"Incorrect Q vector size.\n");
1063 if(QDotInit.size() != QDot.size()) {
1064 throw Errors::RBDLDofMismatchError(
"Incorrect QDotInit vector size.\n");
1066 if(weights.size() != QDot.size()) {
1067 throw Errors::RBDLDofMismatchError(
"Incorrect weight vector size.\n");
1078 for(
unsigned int i = 0; i < weights.size(); ++i) {
1079 A(i,i) = weights[i];
1080 b[i] = weights[i] * QDotInit[i];
1083 A.
block (model.dof_count, 0, cs.size(), model.dof_count) = constraintJac;
1084 A.
block (0, model.dof_count, model.dof_count, cs.size())
1085 = constraintJac.transpose();
1088 SolveLinearSystem (
A,
b,
x, cs.linear_solver);
1091 QDot =
x.
block (0, 0, model.dof_count, 1);
1103 bool update_kinematics,
1104 std::vector<Math::SpatialVector> *f_ext
1107 LOG <<
"-------- " << __func__ <<
" --------" << std::endl;
1113 , CS.force, CS.A, CS.b, CS.x, CS.linear_solver);
1116 for (
unsigned int i = 0; i < model.dof_count; i++) {
1121 for (
unsigned int i = 0; i < CS.size(); i++) {
1122 CS.force[i] = -CS.x[model.dof_count + i];
1135 bool update_kinematics,
1136 std::vector<Math::SpatialVector> *f_ext)
1143 , CS.gamma, QDDot, CS.force, CS.K, CS.a, CS.linear_solver);
1147#ifndef RBDL_USE_CASADI_MATH
1156 bool update_kinematics,
1157 std::vector<Math::SpatialVector> *f_ext
1161 LOG <<
"-------- " << __func__ <<
" --------" << std::endl;
1166 CS.GT_qr.compute (CS.G.transpose());
1167 CS.GT_qr.householderQ().evalTo (CS.GT_qr_Q);
1169 CS.Y = CS.GT_qr_Q.block (0,0,QDot.rows(), CS.G.rows());
1170 CS.Z = CS.GT_qr_Q.block (0,CS.G.rows(),QDot.rows(), QDot.rows() - CS.G.rows());
1173 , CS.force, CS.Y, CS.Z, CS.qddot_y, CS.qddot_z, CS.linear_solver);
1197 , CS.impulse, CS.A, CS.b, CS.x, CS.linear_solver);
1200 for (
unsigned int i = 0; i < model.dof_count; i++) {
1201 QDotPlus[i] = CS.x[i];
1205 for (
unsigned int i = 0; i < CS.size(); i++) {
1206 CS.impulse[i] = CS.x[model.dof_count + i];
1230 , CS.v_plus, QDotPlus, CS.impulse, CS.K, CS.a, CS.linear_solver);
1235#ifndef RBDL_USE_CASADI_MATH
1253 CS.GT_qr.compute(CS.G.transpose());
1254 CS.GT_qr_Q = CS.GT_qr.householderQ();
1256 CS.Y = CS.GT_qr_Q.block (0,0,QDotMinus.rows(), CS.G.rows());
1257 CS.Z = CS.GT_qr_Q.block (0,CS.G.rows(),QDotMinus.rows(), QDotMinus.rows()
1261 , QDotPlus, CS.impulse, CS.Y, CS.Z, CS.qddot_y, CS.qddot_z
1262 , CS.linear_solver);
1276void ForwardDynamicsApplyConstraintForces (
1283 LOG <<
"-------- " << __func__ <<
" --------" << std::endl;
1284 assert (QDDot.size() == model.dof_count);
1288 for (i = 1; i < model.mBodies.size(); i++) {
1289 model.IA[i] = model.I[i].toMatrix();;
1290 model.pA[i] =
crossf(model.v[i],model.I[i] * model.v[i]);
1292#ifdef RBDL_USE_CASADI_MATH
1295 if (CS.f_ext_constraints[i] != SpatialVector::Zero()) {
1297 LOG <<
"External force (" << i <<
") = "
1298 << model.X_base[i].toMatrixAdjoint() * CS.f_ext_constraints[i]
1300 model.pA[i] -= model.X_base[i].toMatrixAdjoint()*CS.f_ext_constraints[i];
1306 LOG <<
"--- first loop ---" << std::endl;
1308 for (i = model.mBodies.size() - 1; i > 0; i--) {
1309 unsigned int q_index = model.mJoints[i].q_index;
1311 if (model.mJoints[i].mDoFCount == 3
1312 && model.mJoints[i].mJointType != JointTypeCustom) {
1313 unsigned int lambda = model.lambda[i];
1314 model.multdof3_u[i] =
Vector3d (Tau[q_index],
1317 - model.multdof3_S[i].transpose() * model.pA[i];
1321 * model.multdof3_Dinv[i]
1322 * model.multdof3_U[i].transpose());
1325 + model.multdof3_U[i] * model.multdof3_Dinv[i] * model.multdof3_u[i];
1327#ifdef RBDL_USE_CASADI_MATH
1328 model.IA[lambda] += (model.X_lambda[i].toMatrixTranspose()
1329 * Ia * model.X_lambda[i].toMatrix());
1330 model.pA[lambda] += model.X_lambda[i].applyTranspose(pa);
1332 model.IA[lambda].noalias() += (model.X_lambda[i].toMatrixTranspose()
1333 * Ia * model.X_lambda[i].toMatrix());
1334 model.pA[lambda].noalias() += model.X_lambda[i].applyTranspose(pa);
1337 LOG <<
"pA[" << lambda <<
"] = " << model.pA[lambda].transpose()
1340 }
else if (model.mJoints[i].mDoFCount == 1
1341 && model.mJoints[i].mJointType != JointTypeCustom) {
1342 model.u[i] = Tau[q_index] - model.S[i].dot(model.pA[i]);
1344 unsigned int lambda = model.lambda[i];
1347 - model.U[i] * (model.U[i] / model.d[i]).transpose();
1349 + model.U[i] * model.u[i] / model.d[i];
1350#ifdef RBDL_USE_CASADI_MATH
1351 model.IA[lambda] += (model.X_lambda[i].toMatrixTranspose()
1352 * Ia * model.X_lambda[i].toMatrix());
1353 model.pA[lambda] += model.X_lambda[i].applyTranspose(pa);
1355 model.IA[lambda].noalias() += (model.X_lambda[i].toMatrixTranspose()
1356 * Ia * model.X_lambda[i].toMatrix());
1357 model.pA[lambda].noalias() += model.X_lambda[i].applyTranspose(pa);
1360 LOG <<
"pA[" << lambda <<
"] = "
1361 << model.pA[lambda].transpose() << std::endl;
1363 }
else if(model.mJoints[i].mJointType == JointTypeCustom) {
1365 unsigned int kI = model.mJoints[i].custom_joint_index;
1366 unsigned int dofI = model.mCustomJoints[kI]->mDoFCount;
1367 unsigned int lambda = model.lambda[i];
1370 for(
int z=0; z<dofI; ++z) {
1371 tau_temp[z] = Tau[q_index+z];
1374 model.mCustomJoints[kI]->u = tau_temp
1375 - (model.mCustomJoints[kI]->S.transpose()
1380 - ( model.mCustomJoints[kI]->U
1381 * model.mCustomJoints[kI]->Dinv
1382 * model.mCustomJoints[kI]->U.transpose());
1385 + ( model.mCustomJoints[kI]->U
1386 * model.mCustomJoints[kI]->Dinv
1387 * model.mCustomJoints[kI]->u );
1389#ifdef RBDL_USE_CASADI_MATH
1390 model.IA[lambda] += model.X_lambda[i].toMatrixTranspose()
1391 * Ia * model.X_lambda[i].toMatrix();
1393 model.pA[lambda] += model.X_lambda[i].applyTranspose(pa);
1395 model.IA[lambda].noalias() += model.X_lambda[i].toMatrixTranspose()
1396 * Ia * model.X_lambda[i].toMatrix();
1398 model.pA[lambda].noalias() += model.X_lambda[i].applyTranspose(pa);
1401 LOG <<
"pA[" << lambda <<
"] = " << model.pA[lambda].transpose()
1412 for (i = 1; i < model.mBodies.size(); i++) {
1413 unsigned int q_index = model.mJoints[i].q_index;
1414 unsigned int lambda = model.lambda[i];
1415 SpatialTransform X_lambda = model.X_lambda[i];
1417 model.a[i] = X_lambda.apply(model.a[lambda]) + model.c[i];
1418 LOG <<
"a'[" << i <<
"] = " << model.a[i].transpose() << std::endl;
1420 if (model.mJoints[i].mDoFCount == 3
1421 && model.mJoints[i].mJointType != JointTypeCustom) {
1422 Vector3d qdd_temp = model.multdof3_Dinv[i] *
1423 (model.multdof3_u[i]
1424 - model.multdof3_U[i].transpose() * model.a[i]);
1426 QDDot[q_index] = qdd_temp[0];
1427 QDDot[q_index + 1] = qdd_temp[1];
1428 QDDot[q_index + 2] = qdd_temp[2];
1429 model.a[i] = model.a[i] + model.multdof3_S[i] * qdd_temp;
1430 }
else if (model.mJoints[i].mDoFCount == 1
1431 && model.mJoints[i].mJointType != JointTypeCustom) {
1432 QDDot[q_index] = (1./model.d[i]) * (
1433 model.u[i] - model.U[i].dot(model.a[i]));
1434 model.a[i] = model.a[i] + model.S[i] * QDDot[q_index];
1435 }
else if (model.mJoints[i].mJointType == JointTypeCustom) {
1436 unsigned int kI = model.mJoints[i].custom_joint_index;
1437 unsigned int dofI = model.mCustomJoints[kI]->mDoFCount;
1440 qdd_temp = model.mCustomJoints[kI]->Dinv
1441 * (model.mCustomJoints[kI]->u
1442 - model.mCustomJoints[kI]->U.transpose()
1445 for(
int z=0; z<dofI; ++z) {
1446 QDDot[q_index+z] = qdd_temp[z];
1449 model.a[i] = model.a[i] + (model.mCustomJoints[kI]->S * qdd_temp);
1453 LOG <<
"QDDot = " << QDDot.transpose() << std::endl;
1465void ForwardDynamicsAccelerationDeltas (
1469 const unsigned int body_id,
1470 const std::vector<SpatialVector> &
f_t
1473 LOG <<
"-------- " << __func__ <<
" ------" << std::endl;
1475 assert (CS.d_pA.size() == model.mBodies.size());
1476 assert (CS.d_a.size() == model.mBodies.size());
1477 assert (CS.d_u.size() == model.mBodies.size());
1480 for (
unsigned int i = 0; i < model.mBodies.size(); i++) {
1481 CS.d_pA[i].setZero();
1482 CS.d_a[i].setZero();
1484 CS.d_multdof3_u[i].setZero();
1486 for(
unsigned int i=0; i<model.mCustomJoints.size(); i++) {
1487 model.mCustomJoints[i]->d_u.setZero();
1490 for (
unsigned int i = body_id; i > 0; i--) {
1492 CS.d_pA[i] = -model.X_base[i].applyAdjoint(
f_t[i]);
1495 if (model.mJoints[i].mDoFCount == 3
1496 && model.mJoints[i].mJointType != JointTypeCustom) {
1497 CS.d_multdof3_u[i] = - model.multdof3_S[i].transpose() * (CS.d_pA[i]);
1499 unsigned int lambda = model.lambda[i];
1501 CS.d_pA[lambda] = CS.d_pA[lambda]
1502 + model.X_lambda[i].applyTranspose (
1503 CS.d_pA[i] + (model.multdof3_U[i]
1504 * model.multdof3_Dinv[i]
1505 * CS.d_multdof3_u[i]));
1507 }
else if(model.mJoints[i].mDoFCount == 1
1508 && model.mJoints[i].mJointType != JointTypeCustom) {
1509 CS.d_u[i] = - model.S[i].dot(CS.d_pA[i]);
1510 unsigned int lambda = model.lambda[i];
1513 CS.d_pA[lambda] = CS.d_pA[lambda]
1514 + model.X_lambda[i].applyTranspose (
1515 CS.d_pA[i] + model.U[i] * CS.d_u[i] / model.d[i]);
1517 }
else if (model.mJoints[i].mJointType == JointTypeCustom) {
1519 unsigned int kI = model.mJoints[i].custom_joint_index;
1520 unsigned int dofI = model.mCustomJoints[kI]->mDoFCount;
1522 model.mCustomJoints[kI]->d_u =
1523 - model.mCustomJoints[kI]->S.transpose() * (CS.d_pA[i]);
1524 unsigned int lambda = model.lambda[i];
1528 + model.X_lambda[i].applyTranspose (
1529 CS.d_pA[i] + ( model.mCustomJoints[kI]->U
1530 * model.mCustomJoints[kI]->Dinv
1531 * model.mCustomJoints[kI]->d_u)
1537 for (
unsigned int i = 0; i <
f_t.size(); i++) {
1538 LOG <<
"f_t[" << i <<
"] = " <<
f_t[i].transpose() << std::endl;
1541 for (
unsigned int i = 0; i < model.mBodies.size(); i++) {
1542 LOG <<
"i = " << i <<
": d_pA[i] " << CS.d_pA[i].transpose() << std::endl;
1544 for (
unsigned int i = 0; i < model.mBodies.size(); i++) {
1545 LOG <<
"i = " << i <<
": d_u[i] = " << CS.d_u[i] << std::endl;
1549 CS.d_a[0] = model.a[0];
1551 for (
unsigned int i = 1; i < model.mBodies.size(); i++) {
1552 unsigned int q_index = model.mJoints[i].q_index;
1553 unsigned int lambda = model.lambda[i];
1557 if (model.mJoints[i].mDoFCount == 3
1558 && model.mJoints[i].mJointType != JointTypeCustom) {
1559 Vector3d qdd_temp = model.multdof3_Dinv[i]
1560 * (CS.d_multdof3_u[i] - model.multdof3_U[i].transpose() * Xa);
1562 QDDot_t[q_index] = qdd_temp[0];
1563 QDDot_t[q_index + 1] = qdd_temp[1];
1564 QDDot_t[q_index + 2] = qdd_temp[2];
1565 model.a[i] = model.a[i] + model.multdof3_S[i] * qdd_temp;
1566 CS.d_a[i] = Xa + model.multdof3_S[i] * qdd_temp;
1567 }
else if (model.mJoints[i].mDoFCount == 1
1568 && model.mJoints[i].mJointType != JointTypeCustom) {
1570 QDDot_t[q_index] = (CS.d_u[i] - model.U[i].dot(Xa) ) / model.d[i];
1571 CS.d_a[i] = Xa + model.S[i] *
QDDot_t[q_index];
1572 }
else if (model.mJoints[i].mJointType == JointTypeCustom) {
1573 unsigned int kI = model.mJoints[i].custom_joint_index;
1574 unsigned int dofI = model.mCustomJoints[kI]->mDoFCount;
1577 qdd_temp = model.mCustomJoints[kI]->Dinv
1578 * (model.mCustomJoints[kI]->d_u
1579 - model.mCustomJoints[kI]->U.transpose() * Xa);
1581 for(
int z=0; z<dofI; ++z) {
1582 QDDot_t[q_index+z] = qdd_temp[z];
1585 model.a[i] = model.a[i] + model.mCustomJoints[kI]->S * qdd_temp;
1586 CS.d_a[i] = Xa + model.mCustomJoints[kI]->S * qdd_temp;
1589 LOG <<
"QDDot_t[" << i - 1 <<
"] = " <<
QDDot_t[i - 1] << std::endl;
1590 LOG <<
"d_a[i] = " << CS.d_a[i].
transpose() << std::endl;
1594inline void set_zero (std::vector<SpatialVector> &spatial_values)
1596 for (
unsigned int i = 0; i < spatial_values.size(); i++) {
1612 LOG <<
"-------- " << __func__ <<
" ------" << std::endl;
1614 assert (CS.f_ext_constraints.size() == model.mBodies.size());
1615 assert (CS.QDDot_0.size() == model.dof_count);
1616 assert (CS.QDDot_t.size() == model.dof_count);
1617 assert (CS.f_t.size() == CS.size());
1618 assert (CS.point_accel_0.size() == CS.size());
1619 assert (CS.K.rows() == CS.size());
1620 assert (CS.K.cols() == CS.size());
1621 assert (CS.force.size() == CS.size());
1622 assert (CS.a.size() == CS.size());
1624 if(CS.constraints.size() != CS.contactConstraints.size()) {
1625 std::stringstream errormsg;
1626 errormsg <<
"Incompatible constraint types: all constraints"
1627 <<
" must be ContactConstraints for the Kokkevis method"
1629 throw Errors::RBDLError(errormsg.str());
1634 unsigned int ci = 0;
1643 LOG <<
"=== Initial Loop Start ===" << std::endl;
1646 unsigned int bi = 0;
1647 for(bi =0; bi < CS.contactConstraints.size(); ++bi) {
1654 << CS.contactConstraints[bi]->getBodyIds()[0]
1657 << CS.contactConstraints[bi]->getBodyFrames()[0].r
1659 LOG <<
"QDDot_0 = " << CS.QDDot_0.transpose() << std::endl;
1663 CS.contactConstraints[bi]->calcPointAccelerations(
1664 model,Q,QDot,CS.QDDot_0,CS.point_accel_0,
false);
1665 CS.contactConstraints[bi]->calcPointAccelerationError(
1666 CS.point_accel_0,CS.a);
1672 unsigned int movable_body_id = 0;
1675 for (bi = 0; bi < CS.contactConstraints.size(); bi++) {
1677 LOG <<
"=== Testforce Loop Start ===" << std::endl;
1679 ci = CS.contactConstraints[bi]->getConstraintIndex();
1681 movable_body_id = GetMovableBodyId(model,
1682 CS.contactConstraints[bi]->getBodyIds()[0]);
1685 LOG <<
"point_global = " << point_global.transpose() << std::endl;
1687 CS.contactConstraints[bi]->calcPointForceJacobian(
1688 model,Q,CS.cache,CS.f_t,
false);
1690 for(
unsigned int j = 0; j<CS.contactConstraints[bi]
1691 ->getConstraintNormalVectors().
size(); ++j) {
1693 CS.f_ext_constraints[movable_body_id] = CS.f_t[ci+j];
1695 LOG <<
"f_t[" << movable_body_id <<
"] = " << CS.f_t[ci+j].transpose()
1698 ForwardDynamicsAccelerationDeltas(model, CS, CS.QDDot_t
1699 , movable_body_id, CS.f_ext_constraints);
1701 LOG <<
"QDDot_0 = " << CS.QDDot_0.transpose() << std::endl;
1702 LOG <<
"QDDot_t = " << (CS.QDDot_t + CS.QDDot_0).transpose()
1704 LOG <<
"QDDot_t - QDDot_0 = " << (CS.QDDot_t).transpose() << std::endl;
1707 CS.f_ext_constraints[movable_body_id].setZero();
1709 CS.QDDot_t += CS.QDDot_0;
1716 for(
unsigned int dj = 0;
1717 dj < CS.contactConstraints.size(); dj++) {
1719 cj = CS.contactConstraints[dj]->getConstraintIndex();
1722 CS.contactConstraints[dj]->calcPointAccelerations(
1723 model,Q,QDot,CS.QDDot_t,point_accel_t,
false);
1726 LOG <<
"point_accel_0 = " << CS.point_accel_0[ci+j].transpose()
1728 LOG <<
"point_accel_t = " << point_accel_t.transpose() << std::endl;
1729 for(
unsigned int k=0;
1730 k < CS.contactConstraints[dj]
1731 ->getConstraintNormalVectors().
size(); ++k) {
1733 CS.K(ci+j,cj+k) = CS.contactConstraints[dj]
1734 ->getConstraintNormalVectors()[k].dot(
1735 point_accel_t - CS.point_accel_0[cj+k]);
1744 LOG <<
"K = " << std::endl << CS.K << std::endl;
1745 LOG <<
"a = " << std::endl << CS.a << std::endl;
1747#ifdef RBDL_USE_CASADI_MATH
1748 auto linsol = casadi::Linsol(
"linear_solver",
"symbolicqr", CS.K.sparsity());
1749 CS.force = linsol.solve(CS.K, CS.a);
1751 switch (CS.linear_solver) {
1753 CS.force = CS.K.partialPivLu().solve(CS.a);
1756 CS.force = CS.K.colPivHouseholderQr().solve(CS.a);
1759 CS.force = CS.K.householderQr().solve(CS.a);
1762 LOG <<
"Error: Invalid linear solver: " << CS.linear_solver << std::endl;
1768 LOG <<
"f = " << CS.force.transpose() << std::endl;
1771 for(bi=0; bi<CS.contactConstraints.size(); ++bi) {
1772 unsigned int body_id =
1773 CS.contactConstraints[bi]->getBodyIds()[0];
1774 unsigned int movable_body_id = body_id;
1776 if (model.IsFixedBodyId(body_id)) {
1777 unsigned int fbody_id = body_id - model.fixed_body_discriminator;
1778 movable_body_id = model.mFixedBodies[fbody_id].mMovableParent;
1780 ci = CS.contactConstraints[bi]->getConstraintIndex();
1782 for(
unsigned int k=0;
1783 k<CS.contactConstraints[bi]->getConstraintSize(); ++k) {
1784 CS.f_ext_constraints[movable_body_id] -= CS.f_t[ci+k] * CS.force[ci+k];
1785 LOG <<
"f_ext[" << movable_body_id <<
"] = "
1786 << CS.f_ext_constraints[movable_body_id].transpose() << std::endl;
1795 ForwardDynamicsApplyConstraintForces (model, Tau, CS, QDDot);
1798 LOG <<
"QDDot after applying f_ext: " << QDDot.transpose() << std::endl;
1803#ifndef RBDL_USE_CASADI_MATH
1810 bool update_kinematics,
1811 std::vector<Math::SpatialVector> *f_ext)
1814 LOG <<
"-------- " << __func__ <<
" ------" << std::endl;
1817 assert (CS.S.cols() == QDot.rows());
1819 unsigned int n = unsigned( CS.H.rows());
1820 unsigned int nc = unsigned( CS.name.size());
1821 unsigned int na = unsigned( CS.S.rows());
1822 unsigned int nu = n-na;
1826 update_kinematics, f_ext);
1828 CS.GPT = CS.G*CS.P.transpose();
1830 CS.GPT_full_qr.compute(CS.GPT);
1831 unsigned int r = unsigned(CS.GPT_full_qr.rank());
1833 bool isCompatible =
false;
1835 isCompatible =
true;
1837 isCompatible =
false;
1840 return isCompatible;
1854 bool update_kinematics,
1855 std::vector<Math::SpatialVector> *f_ext)
1858 LOG <<
"-------- " << __func__ <<
" ------" << std::endl;
1860 assert (QDot.size() == QDDotDesired.size());
1861 assert (QDDotDesired.size() == QDot.size());
1862 assert (QDDotOutput.size() == QDot.size());
1863 assert (TauOutput.size() == CS.H.rows());
1865 assert (CS.S.cols() == QDDotDesired.rows());
1867 unsigned int n = unsigned( CS.H.rows());
1868 unsigned int nc = unsigned( CS.name.size());
1869 unsigned int na = unsigned( CS.S.rows());
1870 unsigned int nu = n-na;
1872 TauOutput.setZero();
1885 CS.Ful = CS.S*CS.H*CS.S.transpose();
1886 CS.Fur = CS.S*CS.H*CS.P.transpose();
1887 CS.Fll = CS.P*CS.H*CS.S.transpose();
1888 CS.Flr = CS.P*CS.H*CS.P.transpose();
1890 CS.GTu = CS.S*(CS.G.transpose());
1891 CS.GTl = CS.P*(CS.G.transpose());
1896 CS.u = CS.S*QDDotDesired;
1902 SolveLinearSystem( CS.GTl.transpose(),
1903 CS.gamma - CS.GTu.transpose()*CS.u,
1904 CS.v, CS.linear_solver);
1907 SolveLinearSystem(CS.GTl,
1914 for(
unsigned int i=0; i<CS.force.rows(); ++i) {
1915 CS.force[i] *= -1.0;
1919 QDDotOutput = CS.S.transpose()*CS.u + CS.P.transpose()*CS.v;
1922 TauOutput = -CS.S.transpose()*( -CS.S*CS.C
1932#ifndef RBDL_USE_CASADI_MATH
1942 bool update_kinematics,
1943 std::vector<Math::SpatialVector> *f_ext)
1945 LOG <<
"-------- " << __func__ <<
" --------" << std::endl;
1948 assert(Q.size() == model.q_size);
1949 assert(QDot.size() == model.qdot_size);
1950 assert(QDDotControls.size() == model.dof_count);
1951 assert(CS.S.cols() == model.dof_count);
1952 assert(CS.W.rows() == CS.W.cols());
1953 assert(CS.W.rows() == CS.S.rows());
1954 assert(QDDotOutput.size() == model.dof_count);
1956 TauOutput.setZero();
1960 unsigned int n = unsigned( CS.H.rows());
1961 unsigned int nc = unsigned( CS.name.size());
1962 unsigned int na = unsigned( CS.S.rows());
1963 unsigned int nu = n-na;
1989 CS.W = 100.0*CS.S*CS.H*CS.S.transpose();
1990 CS.Winv = CS.W.inverse();
1991 CS.WinvSC = CS.Winv * CS.S * CS.C;
1995 CS.F.block( 0, 0, na, na) = CS.S*CS.H*CS.S.transpose() + CS.W;
1996 CS.F.block( 0, na, na, nu) = CS.S*CS.H*CS.P.transpose();
1997 CS.F.block( na, 0, nu, na) = CS.P*CS.H*CS.S.transpose();
1998 CS.F.block( na, na, nu, nu) = CS.P*CS.H*CS.P.transpose();
2000 CS.GT.block( 0, 0,na, nc) = CS.S*(CS.G.transpose());
2001 CS.GT.block( na, 0,nu, nc) = CS.P*(CS.G.transpose());
2003 CS.GT_qr.compute (CS.GT);
2004 CS.GT_qr.householderQ().evalTo (CS.GT_qr_Q);
2009 CS.R = CS.GT_qr_Q.transpose()*CS.GT;
2010 CS.Ru = CS.R.block(0,0,nc,nc);
2012 CS.Y = CS.GT_qr_Q.block( 0, 0, n, nc );
2013 CS.Z = CS.GT_qr_Q.block( 0, nc, n, (n-nc));
2027 CS.u = CS.S*CS.C - CS.W*(CS.S*(QDDotControls
2028 +(CS.S.transpose()*CS.WinvSC)));
2032 for(
unsigned int i=0; i<CS.S.rows(); ++i) {
2035 unsigned int j=CS.S.rows();
2036 for(
unsigned int i=0; i<CS.P.rows(); ++i) {
2042 SolveLinearSystem(CS.Ru.transpose(), CS.gamma, CS.py, CS.linear_solver);
2045 SolveLinearSystem(CS.Z.transpose()*CS.F*CS.Z,
2046 CS.Z.transpose()*(-CS.F*CS.Y*CS.py-CS.g),
2051 SolveLinearSystem(CS.Ru,
2052 CS.Y.transpose()*(CS.g + CS.F*CS.Y*CS.py + CS.F*CS.Z*CS.pz),
2053 CS.force, CS.linear_solver);
2058 QDDotOutput = CS.Y*CS.py + CS.Z*CS.pz;
2059 for(
unsigned int i=0; i<CS.S.rows(); ++i) {
2060 CS.u[i] = QDDotOutput[i];
2063 for(
unsigned int i=0; i<CS.P.rows(); ++i) {
2064 CS.v[i] = QDDotOutput[j];
2068 QDDotOutput = CS.S.transpose()*CS.u
2069 +CS.P.transpose()*CS.v;
2071 TauOutput = (CS.S.transpose()*CS.W*CS.S)*(
2072 QDDotControls+(CS.S.transpose()*CS.WinvSC)
2080void SolveLinearSystem (
2088 throw Errors::RBDLSizeMismatchError(
"Mismatching sizes.\n");
2091#ifdef RBDL_USE_CASADI_MATH
2092 auto linsol = casadi::Linsol(
"linear_solver",
"symbolicqr",
A.sparsity());
2093 x = linsol.solve(
A,
b);
2098 x =
A.partialPivLu().solve(
b);
2101 x =
A.colPivHouseholderQr().solve(
b);
2104 x =
A.householderQr().solve(
b);
2107 std::ostringstream errormsg;
2108 errormsg <<
"Error: Invalid linear solver: " << ls << std::endl;
2109 throw Errors::RBDLError(errormsg.str());
2116unsigned int GetMovableBodyId (Model& model,
unsigned int id)
2118 if(model.IsFixedBodyId(
id)) {
2119 unsigned int fbody_id =
id - model.fixed_body_discriminator;
2120 return model.mFixedBodies[fbody_id].mMovableParent;
2129 unsigned int groupIndex,
2133 std::vector< unsigned int > &constraintBodyIdsUpd,
2134 std::vector< Math::SpatialTransform > &constraintBodyFramesUpd,
2135 std::vector< Math::SpatialVector > &constraintForcesUpd,
2136 bool resolveAllInRootFrame,
2139 assert(groupIndex <=
unsigned(
constraints.size()-1));
2146 constraintBodyIdsUpd,
2147 constraintBodyFramesUpd,
2148 constraintForcesUpd,
2150 resolveAllInRootFrame,
2157 unsigned int groupIndex,
2161 std::vector< unsigned int > &constraintBodyIdsUpd,
2162 std::vector< Math::SpatialTransform > &constraintBodyFramesUpd,
2163 std::vector< Math::SpatialVector > &constraintImpulsesUpd,
2164 bool resolveAllInRootFrame,
2167 assert(groupIndex <=
unsigned(
constraints.size()-1));
2176 constraintBodyIdsUpd,
2177 constraintBodyFramesUpd,
2178 constraintImpulsesUpd,
2180 resolveAllInRootFrame,
2185 for(
unsigned int i=0; i<constraintImpulsesUpd.size(); ++i) {
2186 constraintImpulsesUpd[i] *= -1.0;
2193 unsigned int groupIndex,
2199 assert(groupIndex <=
unsigned(
constraints.size()-1));
2217 unsigned int groupIndex,
2224 assert(groupIndex <=
unsigned(
constraints.size()-1));
2246 unsigned int groupIndex,
2252 assert(groupIndex <=
unsigned(
constraints.size()-1));
2253 assert(positionError.rows() ==
constraints[groupIndex]->getConstraintSize());
2254 assert(velocityError.rows() ==
constraints[groupIndex]->getConstraintSize());
2256 constraints[groupIndex]->getBaumgarteStabilizationForces(positionError,
MX_Xd_dynamic transpose() const
unsigned int rows() const
MX_Xd_dynamic & setZero()
unsigned int cols() const
void resize(unsigned int newI, unsigned int newJ=1)
unsigned int size() const
static MX_Xd_dynamic Identity(unsigned int size, unsigned int ignoredSize=0)
void conservativeResize(unsigned int nrows, unsigned int ncols=1)
static MX_Xd_dynamic Zero(unsigned int nrows, unsigned int ncols=1)
MX_Xd_SubMatrix block(unsigned int row_start, unsigned int col_start)
std::map< unsigned int, unsigned int > userDefinedIdGroupMap
RBDL_DLLAPI void ComputeConstraintImpulsesNullSpace(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDotMinus, ConstraintSet &CS, Math::VectorNd &QDotPlusOutput)
Resolves contact gain using SolveContactSystemNullSpace()
void calcVelocityError(unsigned int groupIndex, Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, Math::VectorNd &velocityErrorOutput, bool updateKinematics=false)
calcVelocityError calculates the vector of position errors associated with this constraint....
void calcPositionError(unsigned int groupIndex, Model &model, const Math::VectorNd &Q, Math::VectorNd &positionErrorOutput, bool updateKinematics=false)
calcPositionError calculates the vector of position errors associated with this constraint....
Math::VectorNd b
Workspace for the Lagrangian right-hand-side.
Math::VectorNd QDDot_t
Workspace for the test accelerations.
std::vector< Math::SpatialVector > f_ext_constraints
Workspace for the actual spatial forces.
std::vector< Math::Vector3d > d_multdof3_u
std::vector< std::shared_ptr< LoopConstraint > > loopConstraints
Math::VectorNd impulse
Constraint impulses along the constraint directions.
size_t size() const
Returns the number of constraints.
void calcBaumgarteStabilizationForces(unsigned int groupIndex, Model &model, const Math::VectorNd &positionError, const Math::VectorNd &velocityError, Math::VectorNd &baumgarteForcesOutput)
std::vector< std::shared_ptr< ContactConstraint > > contactConstraints
Math::VectorNd QDDot_0
Workspace for the default accelerations.
RBDL_DLLAPI void CalcConstraintsPositionError(Model &model, const Math::VectorNd &Q, ConstraintSet &CS, Math::VectorNd &errOutput, bool update_kinematics=true)
Computes the position errors for the given ConstraintSet.
RBDL_DLLAPI void ForwardDynamicsConstraintsNullSpace(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS, Math::VectorNd &QDDotOutput, bool update_kinematics=true, std::vector< Math::SpatialVector > *f_ext=NULL)
RBDL_DLLAPI void CalcConstraintsVelocityError(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, ConstraintSet &CS, Math::VectorNd &errOutput, bool update_kinematics=true)
Computes the velocity errors for the given ConstraintSet.
Math::VectorNd a
Workspace for the accelerations of due to the test forces.
RBDL_DLLAPI void InverseDynamicsConstraintsRelaxed(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &QDDotControls, ConstraintSet &CS, Math::VectorNd &QDDotOutput, Math::VectorNd &TauOutput, bool update_kinematics=true, std::vector< Math::SpatialVector > *f_ext=NULL)
A relaxed inverse-dynamics operator that can be applied to under-actuated or fully-actuated constrain...
Math::VectorNd x
Workspace for the Lagrangian solution.
RBDL_DLLAPI void ForwardDynamicsConstraintsDirect(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS, Math::VectorNd &QDDotOutput, bool update_kinematics=true, std::vector< Math::SpatialVector > *f_ext=NULL)
Computes forward dynamics with contact by constructing and solving the full lagrangian equation.
Math::VectorNd d_d
Workspace when applying constraint forces.
std::vector< Math::SpatialVector > d_pA
Workspace for the bias force due to the test force.
Math::MatrixNd G
Workspace for the constraint Jacobian.
void SetActuationMap(const Model &model, const std::vector< bool > &actuatedDof)
Initializes and allocates memory needed for InverseDynamicsConstraints and InverseDynamicsConstraints...
RBDL_DLLAPI void SolveConstrainedSystemDirect(Math::MatrixNd &H, const Math::MatrixNd &G, const Math::VectorNd &c, const Math::VectorNd &gamma, 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...
std::vector< std::shared_ptr< Constraint > > constraints
RBDL_DLLAPI void CalcConstrainedSystemVariables(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CSOutput, bool update_kinematics=true, std::vector< Math::SpatialVector > *f_ext=NULL)
Computes the terms , , and of the constrained dynamic problem and stores them in the ConstraintSet.
RBDL_DLLAPI void InverseDynamicsConstraints(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &QDDotDesired, ConstraintSet &CS, Math::VectorNd &QDDotOutput, Math::VectorNd &TauOutput, bool update_kinematics=true, std::vector< Math::SpatialVector > *f_ext=NULL)
An inverse-dynamics operator that can be applied to fully-actuated constrained systems.
RBDL_DLLAPI bool CalcAssemblyQ(Model &model, Math::VectorNd QInit, ConstraintSet &CS, Math::VectorNd &QOutput, const Math::VectorNd &weights, double tolerance=1e-12, unsigned int max_iter=100)
Computes a feasible initial value of the generalized joint positions.
unsigned int AddLoopConstraint(unsigned int bodyIdPredecessor, unsigned int bodyIdSuccessor, const Math::SpatialTransform &XPredecessor, const Math::SpatialTransform &XSuccessor, const Math::SpatialVector &constraintAxisInPredecessor, bool enableBaumgarteStabilization=false, double stabilizationTimeConstant=0.1, const char *constraintName=NULL, unsigned int userDefinedId=std::numeric_limits< unsigned int >::max())
Adds a loop constraint to the constraint set.
std::vector< ConstraintType > constraintType
RBDL_DLLAPI void ComputeConstraintImpulsesDirect(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDotMinus, ConstraintSet &CS, Math::VectorNd &QDotPlusOutput)
Computes contact gain by constructing and solving the full lagrangian equation.
std::vector< Math::SpatialMatrix > d_IA
Workspace for the inertia when applying constraint forces.
std::vector< std::string > name
RBDL_DLLAPI void CalcAssemblyQDot(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDotInit, ConstraintSet &CS, Math::VectorNd &QDotOutput, const Math::VectorNd &weights)
Computes a feasible initial value of the generalized joint velocities.
unsigned int AddCustomConstraint(std::shared_ptr< Constraint > customConstraint)
Adds a custom constraint to the constraint set.
Math::MatrixNd H
Workspace for the joint space inertia matrix.
Math::VectorNd gamma
Workspace of the right hand side of the acceleration equation.
Math::MatrixNd P
Selection matrix for the non-actuated parts of the model.
std::vector< Math::SpatialVector > d_U
Workspace when applying constraint forces.
Math::VectorNd v_plus
The velocities we want to have along the constraint directions.
bool bound
Whether the constraint set was bound to a model (mandatory!).
Math::LinearSolver linear_solver
Method that should be used to solve internal linear systems.
std::vector< Math::SpatialVector > d_a
Workspace for the acceleration due to the test force.
RBDL_DLLAPI void SolveConstrainedSystemNullSpace(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...
void calcImpulses(unsigned int groupIndex, Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, std::vector< unsigned int > &constraintBodyIdsOutput, std::vector< Math::SpatialTransform > &constraintBodyFramesOutput, std::vector< Math::SpatialVector > &constraintImpulsesOutput, bool resolveAllInRootFrame=false, bool updateKinematics=false)
calcImpulses resolves the generalized impluses generated by this constraint into equivalent spatial i...
std::map< unsigned int, unsigned int > idGroupMap
unsigned int AddContactConstraint(unsigned int bodyId, const Math::Vector3d &bodyPoint, const Math::Vector3d &worldNormal, const char *constraintName=NULL, unsigned int userDefinedId=std::numeric_limits< unsigned int >::max())
Adds a single contact constraint (point-ground) to the constraint set.
Math::VectorNd C
Workspace for the coriolis forces.
RBDL_DLLAPI bool isConstrainedSystemFullyActuated(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, ConstraintSet &CS, bool update_kinematics=true, std::vector< Math::SpatialVector > *f_ext=NULL)
A method to evaluate if the constrained system is fully actuated.
RBDL_DLLAPI void CalcConstraintsJacobian(Model &model, const Math::VectorNd &Q, ConstraintSet &CS, Math::MatrixNd &GOutput, bool update_kinematics=true)
Computes the Jacobian for the given ConstraintSet.
void enableBaumgarteStabilization(unsigned int groupIndex)
RBDL_DLLAPI void SolveConstrainedSystemRangeSpaceSparse(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...
void clear()
Clears all variables in the constraint set.
std::vector< Math::SpatialVector > f_t
Workspace for the test forces.
RBDL_DLLAPI void ComputeConstraintImpulsesRangeSpaceSparse(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDotMinus, ConstraintSet &CS, Math::VectorNd &QDotPlusOutput)
Resolves contact gain using SolveContactSystemRangeSpaceSparse()
RBDL_DLLAPI void ForwardDynamicsConstraintsRangeSpaceSparse(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS, Math::VectorNd &QDDotOutput, bool update_kinematics=true, std::vector< Math::SpatialVector > *f_ext=NULL)
RBDL_DLLAPI void ForwardDynamicsContactsKokkevis(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, ConstraintSet &CS, Math::VectorNd &QDDotOutput)
Computes forward dynamics that accounts for active contacts in ConstraintSet.
Eigen::HouseholderQR< Math::MatrixNd > GT_qr
Workspace for the QR decomposition of the null-space method.
void calcForces(unsigned int groupIndex, Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, std::vector< unsigned int > &updConstraintBodyIdsOutput, std::vector< Math::SpatialTransform > &updConstraintBodyFramesOutput, std::vector< Math::SpatialVector > &updConstraintForcesOutput, bool resolveAllInRootFrame=false, bool updateKinematics=false)
calcForces resolves the generalized forces generated by this constraint into equivalent spatial force...
bool Bind(const Model &model)
Initializes and allocates memory for the constraint set.
std::vector< Math::Vector3d > point_accel_0
Workspace for the default point accelerations.
Math::MatrixNd K
Workspace for the Inverse Articulated-Body Inertia.
std::map< std::string, unsigned int > nameGroupMap
Math::MatrixNd A
Workspace for the Lagrangian left-hand-side matrix.
RBDL_DLLAPI void NonlinearEffects(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, Math::VectorNd &Tau, std::vector< Math::SpatialVector > *f_ext=NULL)
Computes the coriolis forces.
RBDL_DLLAPI void ForwardDynamics(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, Math::VectorNd &QDDot, std::vector< Math::SpatialVector > *f_ext=NULL)
Computes forward dynamics with the Articulated Body Algorithm.
RBDL_DLLAPI 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.
RBDL_DLLAPI void UpdateKinematicsCustom(Model &model, const VectorNd *Q, const VectorNd *QDot, const VectorNd *QDDot)
Selectively updates model internal states of body positions, velocities and/or accelerations.
SpatialMatrix_t SpatialMatrix
SpatialMatrix crossf(const SpatialVector &v)
SpatialVector_t SpatialVector
RBDL_DLLAPI void SparseFactorizeLTL(Model &model, Math::MatrixNd &H)
RBDL_DLLAPI void SparseSolveLx(Model &model, Math::MatrixNd &L, Math::VectorNd &x)
RBDL_DLLAPI void SparseSolveLTx(Model &model, Math::MatrixNd &L, Math::VectorNd &x)
MX_Xd_dynamic fabs(const MX_Xd_dynamic &m)
LinearSolverColPivHouseholderQR
LinearSolverHouseholderQR
Math::SpatialVector svecB
Math::SpatialVector svecA
Working SpatialVectors.
Math::SpatialTransform stB
Math::SpatialTransform stA
Working SpatialTransforms.
Math::VectorNd vecNA
Working vectors that are sized to match the length of qdot.
Math::SpatialVector svecD
Math::SpatialVector svecE
Math::SpatialVector svecF
Math::SpatialTransform stD
Math::VectorNd vecNZeros
Here N is taken to mean the number of elements in QDot.
Math::Vector3d vec3A
Working Vector3d entries.
Math::Matrix3d mat3A
Working Matrix3d entries.
Math::SpatialVector svecC
Math::SpatialTransform stC