736 lines
24 KiB
C++
736 lines
24 KiB
C++
|
#include <UnitTest++.h>
|
||
|
|
||
|
#include <iostream>
|
||
|
#include <limits>
|
||
|
|
||
|
#include "rbdl/Logging.h"
|
||
|
|
||
|
#include "rbdl/Model.h"
|
||
|
#include "rbdl/Kinematics.h"
|
||
|
#include "rbdl/Dynamics.h"
|
||
|
#include "rbdl/Constraints.h"
|
||
|
|
||
|
#include "Fixtures.h"
|
||
|
|
||
|
using namespace std;
|
||
|
using namespace RigidBodyDynamics;
|
||
|
using namespace RigidBodyDynamics::Math;
|
||
|
|
||
|
const double TEST_PREC = 1.0e-13;
|
||
|
|
||
|
struct DynamicsFixture {
|
||
|
DynamicsFixture () {
|
||
|
ClearLogOutput();
|
||
|
model = new Model;
|
||
|
model->gravity = Vector3d (0., -9.81, 0.);
|
||
|
}
|
||
|
~DynamicsFixture () {
|
||
|
delete model;
|
||
|
}
|
||
|
Model *model;
|
||
|
};
|
||
|
|
||
|
TEST_FIXTURE(DynamicsFixture, TestCalcDynamicSingleChain) {
|
||
|
Body body(1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(0, Xtrans(Vector3d(0., 0., 0.)), joint, body);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd Tau = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < QDDot.size(); i++) {
|
||
|
LOG << "QDDot[" << i << "] = " << QDDot[i] << endl;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < model->a.size(); i++) {
|
||
|
LOG << "a[" << i << "] = " << model->a[i] << endl;
|
||
|
}
|
||
|
|
||
|
CHECK_EQUAL (-4.905, QDDot[0]);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(DynamicsFixture, TestCalcDynamicSpatialInertiaSingleChain) {
|
||
|
// This function checks the value for a non-trivial spatial inertia
|
||
|
Body body(1., Vector3d (1.5, 1., 1.), Vector3d (1., 2., 3.));
|
||
|
|
||
|
Joint joint ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(0, Xtrans(Vector3d(0., 0., 0.)), joint, body);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd Tau = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < QDDot.size(); i++) {
|
||
|
LOG << "QDDot[" << i << "] = " << QDDot[i] << endl;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < model->a.size(); i++) {
|
||
|
LOG << "a[" << i << "] = " << model->a[i] << endl;
|
||
|
}
|
||
|
|
||
|
CHECK_EQUAL (-2.3544, QDDot[0]);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(DynamicsFixture, TestCalcDynamicDoubleChain) {
|
||
|
Body body_a (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_a ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
|
||
|
|
||
|
Body body_b (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_b ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(1, Xtrans(Vector3d(1., 0., 0.)), joint_b, body_b);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd Tau = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
|
||
|
// cout << "--- Double Chain ---" << endl;
|
||
|
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < QDDot.size(); i++) {
|
||
|
LOG << "QDDot[" << i << "] = " << QDDot[i] << endl;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < model->a.size(); i++) {
|
||
|
LOG << "a[" << i << "] = " << model->a[i] << endl;
|
||
|
}
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
CHECK_CLOSE (-5.88600000000000E+00, QDDot[0], TEST_PREC);
|
||
|
CHECK_CLOSE ( 3.92400000000000E+00, QDDot[1], TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(DynamicsFixture, TestCalcDynamicTripleChain) {
|
||
|
Body body_a (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_a ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
|
||
|
|
||
|
Body body_b (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_b ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(1, Xtrans(Vector3d(1., 0., 0.)), joint_b, body_b);
|
||
|
|
||
|
Body body_c (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_c ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(2, Xtrans(Vector3d(1., 0., 0.)), joint_c, body_c);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd Tau = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
|
||
|
// cout << "--- Triple Chain ---" << endl;
|
||
|
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < QDDot.size(); i++) {
|
||
|
LOG << "QDDot[" << i << "] = " << QDDot[i] << endl;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < model->a.size(); i++) {
|
||
|
LOG << "a[" << i << "] = " << model->a[i] << endl;
|
||
|
}
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
CHECK_CLOSE (-6.03692307692308E+00, QDDot[0], TEST_PREC);
|
||
|
CHECK_CLOSE ( 3.77307692307692E+00, QDDot[1], TEST_PREC);
|
||
|
CHECK_CLOSE ( 1.50923076923077E+00, QDDot[2], TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(DynamicsFixture, TestCalcDynamicDoubleChain3D) {
|
||
|
Body body_a (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_a ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
|
||
|
|
||
|
Body body_b (1., Vector3d (0., 1., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_b ( SpatialVector (0., 1., 0., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(1, Xtrans(Vector3d(1., 0., 0.)), joint_b, body_b);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd Tau = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
|
||
|
// cout << "--- Double Chain 3D ---" << endl;
|
||
|
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < QDDot.size(); i++) {
|
||
|
LOG << "QDDot[" << i << "] = " << QDDot[i] << endl;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < model->a.size(); i++) {
|
||
|
LOG << "a[" << i << "] = " << model->a[i] << endl;
|
||
|
}
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
CHECK_CLOSE (-3.92400000000000E+00, QDDot[0], TEST_PREC);
|
||
|
CHECK_CLOSE ( 0.00000000000000E+00, QDDot[1], TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(DynamicsFixture, TestCalcDynamicSimpleTree3D) {
|
||
|
Body body_a (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_a ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
|
||
|
|
||
|
Body body_b1 (1., Vector3d (0., 1., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_b1 ( SpatialVector (0., 1., 0., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(1, Xtrans(Vector3d(1., 0., 0.)), joint_b1, body_b1);
|
||
|
|
||
|
Body body_c1 (1., Vector3d (0., 0., 1.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_c1 ( SpatialVector (1., 0., 0., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(2, Xtrans(Vector3d(0., 1., 0.)), joint_c1, body_c1);
|
||
|
|
||
|
Body body_b2 (1., Vector3d (0., 1., 0.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_b2 ( SpatialVector (0., 1., 0., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(1, Xtrans(Vector3d(-0.5, 0., 0.)), joint_b2, body_b2);
|
||
|
|
||
|
Body body_c2 (1., Vector3d (0., 0., 1.), Vector3d (1., 1., 1.));
|
||
|
Joint joint_c2 ( SpatialVector (1., 0., 0., 0., 0., 0.));
|
||
|
|
||
|
model->AddBody(4, Xtrans(Vector3d(0., -0.5, 0.)), joint_c2, body_c2);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd QDDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
VectorNd Tau = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
|
||
|
// cout << "--- SimpleTree ---" << endl;
|
||
|
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < QDDot.size(); i++) {
|
||
|
LOG << "QDDot[" << i << "] = " << QDDot[i] << endl;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < model->a.size(); i++) {
|
||
|
LOG << "a[" << i << "] = " << model->a[i] << endl;
|
||
|
}
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
CHECK_CLOSE (-1.60319066147860E+00, QDDot[0], TEST_PREC);
|
||
|
CHECK_CLOSE (-5.34396887159533E-01, QDDot[1], TEST_PREC);
|
||
|
CHECK_CLOSE ( 4.10340466926070E+00, QDDot[2], TEST_PREC);
|
||
|
CHECK_CLOSE ( 2.67198443579767E-01, QDDot[3], TEST_PREC);
|
||
|
CHECK_CLOSE ( 5.30579766536965E+00, QDDot[4], TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST (TestForwardDynamicsLagrangian) {
|
||
|
Model model;
|
||
|
Body base_body(1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
|
||
|
model.AddBody (0, SpatialTransform(),
|
||
|
Joint (
|
||
|
SpatialVector (0., 0., 0., 1., 0., 0.),
|
||
|
SpatialVector (0., 0., 0., 0., 1., 0.),
|
||
|
SpatialVector (0., 0., 0., 0., 0., 1.),
|
||
|
SpatialVector (0., 0., 1., 0., 0., 0.),
|
||
|
SpatialVector (0., 1., 0., 0., 0., 0.),
|
||
|
SpatialVector (1., 0., 0., 0., 0., 0.)
|
||
|
),
|
||
|
base_body);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Zero (model.dof_count);
|
||
|
VectorNd QDot = VectorNd::Zero (model.dof_count);
|
||
|
VectorNd Tau = VectorNd::Zero (model.dof_count);
|
||
|
|
||
|
VectorNd QDDot_aba = VectorNd::Zero (model.dof_count);
|
||
|
VectorNd QDDot_lagrangian = VectorNd::Zero (model.dof_count);
|
||
|
|
||
|
Q[0] = 1.1;
|
||
|
Q[1] = 1.2;
|
||
|
Q[2] = 1.3;
|
||
|
Q[3] = 0.1;
|
||
|
Q[4] = 0.2;
|
||
|
Q[5] = 0.3;
|
||
|
|
||
|
QDot[0] = 1.1;
|
||
|
QDot[1] = -1.2;
|
||
|
QDot[2] = 1.3;
|
||
|
QDot[3] = -0.1;
|
||
|
QDot[4] = 0.2;
|
||
|
QDot[5] = -0.3;
|
||
|
|
||
|
Tau[0] = 2.1;
|
||
|
Tau[1] = 2.2;
|
||
|
Tau[2] = 2.3;
|
||
|
Tau[3] = 1.1;
|
||
|
Tau[4] = 1.2;
|
||
|
Tau[5] = 1.3;
|
||
|
|
||
|
ForwardDynamics(model, Q, QDot, Tau, QDDot_aba);
|
||
|
ForwardDynamicsLagrangian(model, Q, QDot, Tau, QDDot_lagrangian);
|
||
|
|
||
|
CHECK_EQUAL (QDDot_aba.size(), QDDot_lagrangian.size());
|
||
|
CHECK_ARRAY_CLOSE (QDDot_aba.data(), QDDot_lagrangian.data(), QDDot_aba.size(), TEST_PREC);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* A simple test for a model with 3 rotational dof. The reference value was
|
||
|
* computed with Featherstones spatial_v1 code. This test was written
|
||
|
* because my benchmark tool showed up inconsistencies, however this was
|
||
|
* due to the missing gravity term. But as the test now works, I just leave
|
||
|
* it here.
|
||
|
*/
|
||
|
TEST (TestForwardDynamics3DoFModel) {
|
||
|
Model model;
|
||
|
|
||
|
model.gravity = Vector3d (0., -9.81, 0.);
|
||
|
|
||
|
Body null_body (0., Vector3d(0., 0., 0.), Vector3d (0., 0., 0.));
|
||
|
Body base_body (1., Vector3d(0., 0.5, 0.), Vector3d (1., 1., 1.));
|
||
|
|
||
|
Joint joint_rot_z ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
Joint joint_rot_y ( SpatialVector (0., 1., 0., 0., 0., 0.));
|
||
|
Joint joint_rot_x ( SpatialVector (1., 0., 0., 0., 0., 0.));
|
||
|
|
||
|
unsigned int base_id_rot_z, base_id_rot_y;
|
||
|
|
||
|
// we can reuse both bodies and joints as they are copied
|
||
|
base_id_rot_z = model.AddBody (0, Xtrans (Vector3d(0., 0., 0.)), joint_rot_z, null_body);
|
||
|
base_id_rot_y = model.AddBody (base_id_rot_z, Xtrans (Vector3d(0., 0., 0.)), joint_rot_y, null_body);
|
||
|
model.AddBody (base_id_rot_y, Xtrans (Vector3d(0., 0., 0.)), joint_rot_x, base_body);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
VectorNd Tau = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
|
||
|
VectorNd QDDot = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
VectorNd QDDot_ref = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
|
||
|
Q[0] = 1.;
|
||
|
|
||
|
ClearLogOutput();
|
||
|
|
||
|
ForwardDynamics (model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
QDDot_ref[0] = 3.301932144386186;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (QDDot_ref.data(), QDDot.data(), QDDot.size(), TEST_PREC);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Another simple 3 dof model test which showed some problems when
|
||
|
* computing forward dynamics with the Lagrangian formulation. A proplem
|
||
|
* occured as the CRBA does not update the kinematics of the model, hence
|
||
|
* invalid body transformations and joint axis were used in the CRBA.
|
||
|
* Running the CRBA after the InverseDynamics calculation fixes this. This
|
||
|
* test ensures that the error does not happen when calling ForwardLagrangian.
|
||
|
*/
|
||
|
TEST (TestForwardDynamics3DoFModelLagrangian) {
|
||
|
Model model;
|
||
|
|
||
|
model.gravity = Vector3d (0., -9.81, 0.);
|
||
|
|
||
|
Body null_body (0., Vector3d(0., 0., 0.), Vector3d (0., 0., 0.));
|
||
|
Body base_body (1., Vector3d(0., 0.5, 0.), Vector3d (1., 1., 1.));
|
||
|
|
||
|
Joint joint_rot_z ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
Joint joint_rot_y ( SpatialVector (0., 1., 0., 0., 0., 0.));
|
||
|
Joint joint_rot_x ( SpatialVector (1., 0., 0., 0., 0., 0.));
|
||
|
|
||
|
unsigned int base_id_rot_z, base_id_rot_y;
|
||
|
|
||
|
// we can reuse both bodies and joints as they are copied
|
||
|
base_id_rot_z = model.AddBody (0, Xtrans (Vector3d(0., 0., 0.)), joint_rot_z, null_body);
|
||
|
base_id_rot_y = model.AddBody (base_id_rot_z, Xtrans (Vector3d(0., 0., 0.)), joint_rot_y, null_body);
|
||
|
model.AddBody (base_id_rot_y, Xtrans (Vector3d(0., 0., 0.)), joint_rot_x, base_body);
|
||
|
|
||
|
// Initialization of the input vectors
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
VectorNd Tau = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
|
||
|
VectorNd QDDot_ab = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
VectorNd QDDot_lagrangian = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
|
||
|
Q[1] = 1.;
|
||
|
ClearLogOutput();
|
||
|
|
||
|
Q[0] = 0.;
|
||
|
Q[1] = 1.;
|
||
|
Q[2] = 0.;
|
||
|
ForwardDynamicsLagrangian (model, Q, QDot, Tau, QDDot_lagrangian);
|
||
|
Q[0] = 0.;
|
||
|
Q[1] = 0.;
|
||
|
Q[2] = 1.;
|
||
|
ForwardDynamicsLagrangian (model, Q, QDot, Tau, QDDot_lagrangian);
|
||
|
ForwardDynamics (model, Q, QDot, Tau, QDDot_ab);
|
||
|
|
||
|
// cout << QDDot_lagrangian << endl;
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (QDDot_ab.data(), QDDot_lagrangian.data(), QDDot_ab.size(), TEST_PREC);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This is a test for a model where I detected incosistencies between the
|
||
|
* Lagragian method and the ABA.
|
||
|
*/
|
||
|
TEST (TestForwardDynamicsTwoLegModelLagrangian) {
|
||
|
Model *model = NULL;
|
||
|
|
||
|
unsigned int hip_id,
|
||
|
// upper_leg_right_id,
|
||
|
// lower_leg_right_id,
|
||
|
foot_right_id,
|
||
|
// upper_leg_left_id,
|
||
|
// lower_leg_left_id,
|
||
|
foot_left_id;
|
||
|
Body hip_body,
|
||
|
upper_leg_right_body,
|
||
|
lower_leg_right_body,
|
||
|
foot_right_body,
|
||
|
upper_leg_left_body,
|
||
|
lower_leg_left_body,
|
||
|
foot_left_body;
|
||
|
|
||
|
Joint joint_rot_z, joint_rot_y, joint_rot_x;
|
||
|
Joint joint_trans_z, joint_trans_y, joint_trans_x;
|
||
|
|
||
|
ConstraintSet CS_right;
|
||
|
ConstraintSet CS_left;
|
||
|
ConstraintSet CS_both;
|
||
|
|
||
|
model = new Model();
|
||
|
|
||
|
model->gravity = Vector3d (0., -9.81, 0.);
|
||
|
|
||
|
joint_rot_z = Joint ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
joint_rot_y = Joint ( SpatialVector (0., 1., 0., 0., 0., 0.));
|
||
|
joint_rot_x = Joint ( SpatialVector (1., 0., 0., 0., 0., 0.));
|
||
|
|
||
|
joint_trans_z = Joint ( SpatialVector (0., 0., 0., 0., 0., 1.));
|
||
|
joint_trans_y = Joint ( SpatialVector (0., 0., 0., 0., 1., 0.));
|
||
|
joint_trans_x = Joint ( SpatialVector (0., 0., 0., 1., 0., 0.));
|
||
|
|
||
|
Body null_body (0., Vector3d (0., 0., 0.), Vector3d (0., 0., 0.));
|
||
|
|
||
|
// hip
|
||
|
hip_body = Body (1., Vector3d (0., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
|
||
|
// lateral right
|
||
|
upper_leg_right_body = Body (1., Vector3d (0., -0.25, 0.), Vector3d (1., 1., 1.));
|
||
|
lower_leg_right_body = Body (1., Vector3d (0., -0.25, 0.), Vector3d (1., 1., 1.));
|
||
|
foot_right_body = Body (1., Vector3d (0.15, -0.1, 0.), Vector3d (1., 1., 1.));
|
||
|
|
||
|
// lateral left
|
||
|
upper_leg_left_body = Body (1., Vector3d (0., -0.25, 0.), Vector3d (1., 1., 1.));
|
||
|
lower_leg_left_body = Body (1., Vector3d (0., -0.25, 0.), Vector3d (1., 1., 1.));
|
||
|
foot_left_body = Body (1., Vector3d (0.15, -0.1, 0.), Vector3d (1., 1., 1.));
|
||
|
|
||
|
// temporary value to store most recent body id
|
||
|
unsigned int temp_id;
|
||
|
|
||
|
// add hip to the model (planar, 3 DOF)
|
||
|
temp_id = model->AddBody (0, Xtrans (Vector3d (0., 0., 0.)), joint_trans_x, null_body);
|
||
|
temp_id = model->AddBody (temp_id, Xtrans (Vector3d (0., 0., 0.)), joint_trans_y, null_body);
|
||
|
hip_id = model->AddBody (temp_id, Xtrans (Vector3d (0., 0., 0.)), joint_rot_z, hip_body);
|
||
|
|
||
|
//
|
||
|
// right leg
|
||
|
//
|
||
|
|
||
|
// add right upper leg
|
||
|
temp_id = model->AddBody (hip_id, Xtrans (Vector3d(0., 0., 0.)), joint_rot_z, upper_leg_right_body);
|
||
|
// upper_leg_right_id = temp_id;
|
||
|
|
||
|
// add the right lower leg (only one DOF)
|
||
|
temp_id = model->AddBody (temp_id, Xtrans (Vector3d(0., -0.5, 0.)), joint_rot_z, lower_leg_right_body);
|
||
|
// lower_leg_right_id = temp_id;
|
||
|
|
||
|
// add the right foot (1 DOF)
|
||
|
temp_id = model->AddBody (temp_id, Xtrans (Vector3d(0., -0.5, 0.)), joint_rot_z, foot_right_body);
|
||
|
foot_right_id = temp_id;
|
||
|
|
||
|
//
|
||
|
// left leg
|
||
|
//
|
||
|
|
||
|
// add left upper leg
|
||
|
temp_id = model->AddBody (hip_id, Xtrans (Vector3d(0., 0., 0.)), joint_rot_z, upper_leg_left_body);
|
||
|
// upper_leg_left_id = temp_id;
|
||
|
|
||
|
// add the left lower leg (only one DOF)
|
||
|
temp_id = model->AddBody (temp_id, Xtrans (Vector3d(0., -0.5, 0.)), joint_rot_z, lower_leg_left_body);
|
||
|
// lower_leg_left_id = temp_id;
|
||
|
|
||
|
// add the left foot (1 DOF)
|
||
|
temp_id = model->AddBody (temp_id, Xtrans (Vector3d(0., -0.5, 0.)), joint_rot_z, foot_left_body);
|
||
|
foot_left_id = temp_id;
|
||
|
|
||
|
LOG << "--- model created (" << model->dof_count << " DOF) ---" << endl;
|
||
|
|
||
|
// contact data
|
||
|
CS_right.AddContactConstraint(foot_right_id, Vector3d (0., 0., 0.), Vector3d (1., 0., 0.), "foot_right_x");
|
||
|
CS_right.AddContactConstraint(foot_right_id, Vector3d (0., 0., 0.), Vector3d (0., 1., 0.), "foot_right_y");
|
||
|
CS_right.AddContactConstraint(foot_right_id, Vector3d (0., 0., 0.), Vector3d (0., 0., 1.), "foot_right_z");
|
||
|
|
||
|
CS_left.AddContactConstraint(foot_left_id, Vector3d (0., 0., 0.), Vector3d (1., 0., 0.), "foot_left_x");
|
||
|
CS_left.AddContactConstraint(foot_left_id, Vector3d (0., 0., 0.), Vector3d (0., 1., 0.), "foot_left_y");
|
||
|
CS_left.AddContactConstraint(foot_left_id, Vector3d (0., 0., 0.), Vector3d (0., 0., 1.), "foot_left_z");
|
||
|
|
||
|
CS_both.AddContactConstraint(foot_right_id, Vector3d (0., 0., 0.), Vector3d (1., 0., 0.), "foot_right_x");
|
||
|
CS_both.AddContactConstraint(foot_right_id, Vector3d (0., 0., 0.), Vector3d (0., 1., 0.), "foot_right_y");
|
||
|
CS_both.AddContactConstraint(foot_right_id, Vector3d (0., 0., 0.), Vector3d (0., 0., 1.), "foot_right_z");
|
||
|
CS_both.AddContactConstraint(foot_left_id, Vector3d (0., 0., 0.), Vector3d (1., 0., 0.), "foot_left_x");
|
||
|
CS_both.AddContactConstraint(foot_left_id, Vector3d (0., 0., 0.), Vector3d (0., 1., 0.), "foot_left_y");
|
||
|
CS_both.AddContactConstraint(foot_left_id, Vector3d (0., 0., 0.), Vector3d (0., 0., 1.), "foot_left_z");
|
||
|
|
||
|
CS_right.Bind(*model);
|
||
|
CS_left.Bind(*model);
|
||
|
CS_both.Bind(*model);
|
||
|
|
||
|
VectorNd Q(model->dof_count);
|
||
|
VectorNd QDot(model->dof_count);
|
||
|
VectorNd Tau(model->dof_count);
|
||
|
VectorNd QDDot(model->dof_count);
|
||
|
VectorNd QDDotABA(model->dof_count);
|
||
|
|
||
|
Q[0] = 0.8;
|
||
|
Q[1] = -7.76326e-06;
|
||
|
Q[2] = -1.58205e-07;
|
||
|
Q[3] = 1.57391e-07;
|
||
|
Q[4] = -1.03029e-09;
|
||
|
Q[5] = 7.92143e-08;
|
||
|
Q[6] = 1.57391e-07;
|
||
|
Q[7] = -1.03029e-09;
|
||
|
Q[8] = 7.92143e-08;
|
||
|
|
||
|
QDot[0] = -1.77845e-06;
|
||
|
QDot[1] = -0.00905283;
|
||
|
QDot[2] = -0.000184484;
|
||
|
QDot[3] = 0.000183536;
|
||
|
QDot[4] = -1.20144e-06;
|
||
|
QDot[5] = 9.23727e-05;
|
||
|
QDot[6] = 0.000183536;
|
||
|
QDot[7] = -1.20144e-06;
|
||
|
QDot[8] = 9.23727e-05;
|
||
|
|
||
|
Tau[0] = 0;
|
||
|
Tau[1] = 0;
|
||
|
Tau[2] = 0;
|
||
|
Tau[3] = 0.1;
|
||
|
Tau[4] = 0.1;
|
||
|
Tau[5] = 0.1;
|
||
|
Tau[6] = 0.1;
|
||
|
Tau[7] = 0.1;
|
||
|
Tau[8] = 0.1;
|
||
|
|
||
|
// QDDot = 6.31843e-07 -6.12442e-07 9.22595e-14 3.3712e-07 4.27368e-07 -7.91795e-07 3.3712e-07 4.27368e-07 -7.91795e-07
|
||
|
// QDDAB = -0.00192794 -9.81419 -0.2 0.198972 -0.00130243 0.100141 0.198972 -0.00130243 0.100141
|
||
|
|
||
|
ForwardDynamics (*model, Q, QDot, Tau, QDDotABA);
|
||
|
ClearLogOutput();
|
||
|
ForwardDynamicsLagrangian (*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
// run it again to make sure the calculations give the same results and
|
||
|
// no invalid state information lingering in the model structure is being used
|
||
|
ForwardDynamics (*model, Q, QDot, Tau, QDDotABA);
|
||
|
ClearLogOutput();
|
||
|
ForwardDynamicsLagrangian (*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (QDDotABA.data(), QDDot.data(), QDDotABA.size(), TEST_PREC);
|
||
|
|
||
|
delete model;
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(FixedAndMovableJoint, TestForwardDynamicsFixedJoint) {
|
||
|
Q_fixed[0] = 1.1;
|
||
|
Q_fixed[1] = 2.2;
|
||
|
|
||
|
QDot_fixed[0] = -3.2;
|
||
|
QDot_fixed[1] = -2.3;
|
||
|
|
||
|
Tau_fixed[0] = 1.2;
|
||
|
Tau_fixed[1] = 2.1;
|
||
|
|
||
|
Q = CreateDofVectorFromReducedVector (Q_fixed);
|
||
|
QDot = CreateDofVectorFromReducedVector (QDot_fixed);
|
||
|
|
||
|
QDDot.setZero();
|
||
|
|
||
|
InverseDynamics (*model_movable, Q, QDot, QDDot, C_movable);
|
||
|
CompositeRigidBodyAlgorithm (*model_movable, Q, H_movable);
|
||
|
|
||
|
H_fixed = CreateReducedInertiaMatrix (H_movable);
|
||
|
|
||
|
C_fixed[0] = C_movable[0];
|
||
|
C_fixed[1] = C_movable[2];
|
||
|
|
||
|
VectorNd QDDot_fixed_emulate(2);
|
||
|
CHECK (LinSolveGaussElimPivot (H_fixed, C_fixed * -1. + Tau_fixed, QDDot_fixed_emulate));
|
||
|
|
||
|
ForwardDynamics (*model_fixed, Q_fixed, QDot_fixed, Tau_fixed, QDDot_fixed);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (QDDot_fixed_emulate.data(), QDDot_fixed.data(), 2, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(FixedAndMovableJoint, TestInverseDynamicsFixedJoint) {
|
||
|
Q_fixed[0] = 1.1;
|
||
|
Q_fixed[1] = 2.2;
|
||
|
|
||
|
QDot_fixed[0] = -3.2;
|
||
|
QDot_fixed[1] = -2.3;
|
||
|
|
||
|
QDDot_fixed[0] = 1.2;
|
||
|
QDDot_fixed[1] = 2.1;
|
||
|
|
||
|
Q = CreateDofVectorFromReducedVector (Q_fixed);
|
||
|
QDot = CreateDofVectorFromReducedVector (QDot_fixed);
|
||
|
QDDot = CreateDofVectorFromReducedVector (QDDot_fixed);
|
||
|
|
||
|
InverseDynamics (*model_movable, Q, QDot, QDDot, Tau);
|
||
|
InverseDynamics (*model_fixed, Q_fixed, QDot_fixed, QDDot_fixed, Tau_fixed);
|
||
|
|
||
|
VectorNd Tau_2dof (2);
|
||
|
Tau_2dof[0] = Tau[0];
|
||
|
Tau_2dof[1] = Tau[2];
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Tau_2dof.data(), Tau_fixed.data(), 2, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( FloatingBase12DoF, TestForwardDynamicsLagrangianPrealloc ) {
|
||
|
for (unsigned int i = 0; i < model->dof_count; i++) {
|
||
|
Q[i] = static_cast<double>(i + 1) * 0.1;
|
||
|
QDot[i] = static_cast<double>(i + 1) * 1.1;
|
||
|
Tau[i] = static_cast<double>(i + 1) * -1.2;
|
||
|
}
|
||
|
|
||
|
ForwardDynamicsLagrangian (*model,
|
||
|
Q,
|
||
|
QDot,
|
||
|
Tau,
|
||
|
QDDot,
|
||
|
Math::LinearSolverPartialPivLU,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
MatrixNd H (MatrixNd::Zero(model->dof_count, model->dof_count));
|
||
|
VectorNd C (VectorNd::Zero(model->dof_count));
|
||
|
VectorNd QDDot_prealloc (VectorNd::Zero (model->dof_count));
|
||
|
ForwardDynamicsLagrangian (*model,
|
||
|
Q,
|
||
|
QDot,
|
||
|
Tau,
|
||
|
QDDot_prealloc,
|
||
|
Math::LinearSolverPartialPivLU,
|
||
|
NULL,
|
||
|
&H,
|
||
|
&C
|
||
|
);
|
||
|
|
||
|
CHECK_ARRAY_EQUAL (QDDot.data(), QDDot_prealloc.data(), model->dof_count);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( FixedBase3DoF, SolveMInvTimesTau) {
|
||
|
for (unsigned int i = 0; i < model->dof_count; i++) {
|
||
|
Q[i] = rand() / static_cast<double>(RAND_MAX);
|
||
|
Tau[i] = rand() / static_cast<double>(RAND_MAX);
|
||
|
}
|
||
|
|
||
|
MatrixNd M (MatrixNd::Zero(model->dof_count, model->dof_count));
|
||
|
CompositeRigidBodyAlgorithm (*model, Q, M);
|
||
|
|
||
|
VectorNd qddot_solve_llt = M.llt().solve(Tau);
|
||
|
|
||
|
VectorNd qddot_minv (Q);
|
||
|
CalcMInvTimesTau (*model, Q, Tau, qddot_minv);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (qddot_solve_llt.data(), qddot_minv.data(), model->dof_count, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( FixedBase3DoF, SolveMInvTimesTauReuse) {
|
||
|
for (unsigned int i = 0; i < model->dof_count; i++) {
|
||
|
Q[i] = rand() / static_cast<double>(RAND_MAX);
|
||
|
Tau[i] = rand() / static_cast<double>(RAND_MAX);
|
||
|
}
|
||
|
|
||
|
MatrixNd M (MatrixNd::Zero(model->dof_count, model->dof_count));
|
||
|
CompositeRigidBodyAlgorithm (*model, Q, M);
|
||
|
|
||
|
VectorNd qddot_solve_llt = M.llt().solve(Tau);
|
||
|
|
||
|
VectorNd qddot_minv (Q);
|
||
|
CalcMInvTimesTau (*model, Q, Tau, qddot_minv);
|
||
|
|
||
|
for (unsigned int j = 0; j < 1; j++) {
|
||
|
for (unsigned int i = 0; i < model->dof_count; i++) {
|
||
|
Tau[i] = rand() / static_cast<double>(RAND_MAX);
|
||
|
}
|
||
|
|
||
|
CompositeRigidBodyAlgorithm (*model, Q, M);
|
||
|
qddot_solve_llt = M.llt().solve(Tau);
|
||
|
|
||
|
CalcMInvTimesTau (*model, Q, Tau, qddot_minv, false);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (qddot_solve_llt.data(), qddot_minv.data(), model->dof_count, TEST_PREC);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( FixedBase3DoF, SolveMInvTimesNonZeroQDotKinematicsUpdate) {
|
||
|
for (unsigned int i = 0; i < model->dof_count; i++) {
|
||
|
Q[i] = rand() / static_cast<double>(RAND_MAX);
|
||
|
QDot[i] = rand() / static_cast<double>(RAND_MAX);
|
||
|
Tau[i] = rand() / static_cast<double>(RAND_MAX);
|
||
|
}
|
||
|
|
||
|
UpdateKinematicsCustom(*model, &Q, &QDot, NULL);
|
||
|
|
||
|
MatrixNd M (MatrixNd::Zero(model->dof_count, model->dof_count));
|
||
|
CompositeRigidBodyAlgorithm (*model, Q, M);
|
||
|
|
||
|
VectorNd qddot_solve_llt = M.llt().solve(Tau);
|
||
|
|
||
|
VectorNd qddot_minv (Q);
|
||
|
CalcMInvTimesTau (*model, Q, Tau, qddot_minv);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (qddot_solve_llt.data(), qddot_minv.data(), model->dof_count, TEST_PREC);
|
||
|
}
|