681 lines
23 KiB
C++
681 lines
23 KiB
C++
|
#include <UnitTest++.h>
|
||
|
|
||
|
#include <iostream>
|
||
|
|
||
|
#include "rbdl/rbdl_mathutils.h"
|
||
|
#include "rbdl/Logging.h"
|
||
|
|
||
|
#include "rbdl/Model.h"
|
||
|
#include "rbdl/Kinematics.h"
|
||
|
#include "rbdl/Dynamics.h"
|
||
|
|
||
|
#include "Human36Fixture.h"
|
||
|
|
||
|
using namespace std;
|
||
|
using namespace RigidBodyDynamics;
|
||
|
using namespace RigidBodyDynamics::Math;
|
||
|
|
||
|
const double TEST_PREC = 1.0e-12;
|
||
|
|
||
|
struct KinematicsFixture {
|
||
|
KinematicsFixture () {
|
||
|
ClearLogOutput();
|
||
|
model = new Model;
|
||
|
|
||
|
/* Basically a model like this, where X are the Center of Masses
|
||
|
* and the CoM of the last (3rd) body comes out of the Y=X=0 plane.
|
||
|
*
|
||
|
* X
|
||
|
* *
|
||
|
* _/
|
||
|
* _/ (-Z)
|
||
|
* Z /
|
||
|
* *---*
|
||
|
* |
|
||
|
* |
|
||
|
* Z |
|
||
|
* O---*
|
||
|
* Y
|
||
|
*/
|
||
|
|
||
|
body_a = Body (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
joint_a = Joint( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
body_a_id = model->AddBody(0, Xtrans(Vector3d(0., 0., 0.)), joint_a, body_a);
|
||
|
|
||
|
body_b = Body (1., Vector3d (0., 1., 0.), Vector3d (1., 1., 1.));
|
||
|
joint_b = Joint ( SpatialVector (0., 1., 0., 0., 0., 0.));
|
||
|
|
||
|
body_b_id = model->AddBody(body_a_id, Xtrans(Vector3d(1., 0., 0.)), joint_b, body_b);
|
||
|
|
||
|
body_c = Body (1., Vector3d (0., 0., 1.), Vector3d (1., 1., 1.));
|
||
|
joint_c = Joint ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
|
||
|
body_c_id = model->AddBody(body_b_id, Xtrans(Vector3d(0., 1., 0.)), joint_c, body_c);
|
||
|
|
||
|
body_d = Body (1., Vector3d (1., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
joint_c = Joint ( SpatialVector (1., 0., 0., 0., 0., 0.));
|
||
|
|
||
|
body_d_id = model->AddBody(body_c_id, Xtrans(Vector3d(0., 0., -1.)), joint_c, body_d);
|
||
|
|
||
|
Q = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
QDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
QDDot = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
Tau = VectorNd::Constant ((size_t) model->dof_count, 0.);
|
||
|
|
||
|
ClearLogOutput();
|
||
|
}
|
||
|
|
||
|
~KinematicsFixture () {
|
||
|
delete model;
|
||
|
}
|
||
|
Model *model;
|
||
|
|
||
|
unsigned int body_a_id, body_b_id, body_c_id, body_d_id;
|
||
|
Body body_a, body_b, body_c, body_d;
|
||
|
Joint joint_a, joint_b, joint_c, joint_d;
|
||
|
|
||
|
VectorNd Q;
|
||
|
VectorNd QDot;
|
||
|
VectorNd QDDot;
|
||
|
VectorNd Tau;
|
||
|
};
|
||
|
|
||
|
struct KinematicsFixture6DoF {
|
||
|
KinematicsFixture6DoF () {
|
||
|
ClearLogOutput();
|
||
|
model = new Model;
|
||
|
|
||
|
model->gravity = Vector3d (0., -9.81, 0.);
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
* X Contact point (ref child)
|
||
|
* |
|
||
|
* Base |
|
||
|
* / body |
|
||
|
* O-------*
|
||
|
* \
|
||
|
* Child body
|
||
|
*/
|
||
|
|
||
|
// base body (3 DoF)
|
||
|
base = Body (
|
||
|
1.,
|
||
|
Vector3d (0.5, 0., 0.),
|
||
|
Vector3d (1., 1., 1.)
|
||
|
);
|
||
|
joint_rotzyx = Joint (
|
||
|
SpatialVector (0., 0., 1., 0., 0., 0.),
|
||
|
SpatialVector (0., 1., 0., 0., 0., 0.),
|
||
|
SpatialVector (1., 0., 0., 0., 0., 0.)
|
||
|
);
|
||
|
base_id = model->AddBody (0, Xtrans (Vector3d (0., 0., 0.)), joint_rotzyx, base);
|
||
|
|
||
|
// child body (3 DoF)
|
||
|
child = Body (
|
||
|
1.,
|
||
|
Vector3d (0., 0.5, 0.),
|
||
|
Vector3d (1., 1., 1.)
|
||
|
);
|
||
|
child_id = model->AddBody (base_id, Xtrans (Vector3d (1., 0., 0.)), joint_rotzyx, child);
|
||
|
|
||
|
Q = VectorNd::Constant (model->mBodies.size() - 1, 0.);
|
||
|
QDot = VectorNd::Constant (model->mBodies.size() - 1, 0.);
|
||
|
QDDot = VectorNd::Constant (model->mBodies.size() - 1, 0.);
|
||
|
Tau = VectorNd::Constant (model->mBodies.size() - 1, 0.);
|
||
|
|
||
|
ClearLogOutput();
|
||
|
}
|
||
|
|
||
|
~KinematicsFixture6DoF () {
|
||
|
delete model;
|
||
|
}
|
||
|
Model *model;
|
||
|
|
||
|
unsigned int base_id, child_id;
|
||
|
Body base, child;
|
||
|
Joint joint_rotzyx;
|
||
|
|
||
|
VectorNd Q;
|
||
|
VectorNd QDot;
|
||
|
VectorNd QDDot;
|
||
|
VectorNd Tau;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture, TestPositionNeutral) {
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
Vector3d body_position;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0., 0., 0.), CalcBodyToBaseCoordinates(*model, Q, body_a_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 0., 0.), CalcBodyToBaseCoordinates(*model, Q, body_b_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 1., 0.), CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 1., -1.), CalcBodyToBaseCoordinates(*model, Q, body_d_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture, TestPositionBaseRotated90Deg) {
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
|
||
|
Q[0] = 0.5 * M_PI;
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
Vector3d body_position;
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0., 0., 0.), CalcBodyToBaseCoordinates(*model, Q, body_a_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0., 1., 0.), CalcBodyToBaseCoordinates(*model, Q, body_b_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (-1., 1., 0.),CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (-1., 1., -1.), CalcBodyToBaseCoordinates(*model, Q, body_d_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture, TestPositionBaseRotatedNeg45Deg) {
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
|
||
|
Q[0] = -0.25 * M_PI;
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
Vector3d body_position;
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0., 0., 0.), CalcBodyToBaseCoordinates(*model, Q, body_a_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0.707106781186547, -0.707106781186547, 0.), CalcBodyToBaseCoordinates(*model, Q, body_b_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (sqrt(2.0), 0., 0.),CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (sqrt(2.0), 0., -1.), CalcBodyToBaseCoordinates(*model, Q, body_d_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture, TestPositionBodyBRotated90Deg) {
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
Q[1] = 0.5 * M_PI;
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
Vector3d body_position;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0., 0., 0.), CalcBodyToBaseCoordinates(*model, Q, body_a_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 0., 0.), CalcBodyToBaseCoordinates(*model, Q, body_b_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 1., 0.),CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0., 1., 0.),CalcBodyToBaseCoordinates(*model, Q, body_d_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture, TestPositionBodyBRotatedNeg45Deg) {
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
Q[1] = -0.25 * M_PI;
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
Vector3d body_position;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0., 0., 0.), CalcBodyToBaseCoordinates(*model, Q, body_a_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 0., 0.), CalcBodyToBaseCoordinates(*model, Q, body_b_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 1., 0.),CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1 + 0.707106781186547, 1., -0.707106781186547), CalcBodyToBaseCoordinates(*model, Q, body_d_id, Vector3d (0., 0., 0.), true), 3, TEST_PREC );
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture, TestCalcBodyToBaseCoordinates) {
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (
|
||
|
Vector3d (1., 2., 0.),
|
||
|
CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 1., 0.)),
|
||
|
3, TEST_PREC
|
||
|
);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture, TestCalcBodyToBaseCoordinatesRotated) {
|
||
|
Q[2] = 0.5 * M_PI;
|
||
|
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (
|
||
|
Vector3d (1., 1., 0.).data(),
|
||
|
CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 0., 0.), false).data(),
|
||
|
3, TEST_PREC
|
||
|
);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (
|
||
|
Vector3d (0., 1., 0.).data(),
|
||
|
CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 1., 0.), false).data(),
|
||
|
3, TEST_PREC
|
||
|
);
|
||
|
|
||
|
// Rotate the other way round
|
||
|
Q[2] = -0.5 * M_PI;
|
||
|
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (
|
||
|
Vector3d (1., 1., 0.),
|
||
|
CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 0., 0.), false),
|
||
|
3, TEST_PREC
|
||
|
);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (
|
||
|
Vector3d (2., 1., 0.),
|
||
|
CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 1., 0.), false),
|
||
|
3, TEST_PREC
|
||
|
);
|
||
|
|
||
|
// Rotate around the base
|
||
|
Q[0] = 0.5 * M_PI;
|
||
|
Q[2] = 0.;
|
||
|
|
||
|
// We call ForwardDynamics() as it updates the spatial transformation
|
||
|
// matrices
|
||
|
ForwardDynamics(*model, Q, QDot, Tau, QDDot);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (
|
||
|
Vector3d (-1., 1., 0.),
|
||
|
CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 0., 0.), false),
|
||
|
3, TEST_PREC
|
||
|
);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (
|
||
|
Vector3d (-2., 1., 0.),
|
||
|
CalcBodyToBaseCoordinates(*model, Q, body_c_id, Vector3d (0., 1., 0.), false),
|
||
|
3, TEST_PREC
|
||
|
);
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
}
|
||
|
|
||
|
TEST(TestCalcPointJacobian) {
|
||
|
Model model;
|
||
|
Body base_body (1., Vector3d (0., 0., 0.), Vector3d (1., 1., 1.));
|
||
|
|
||
|
unsigned int base_body_id = 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);
|
||
|
|
||
|
VectorNd Q = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
VectorNd QDot = VectorNd::Constant ((size_t) model.dof_count, 0.);
|
||
|
MatrixNd G = MatrixNd::Constant (3, model.dof_count, 0.);
|
||
|
Vector3d point_position (1.1, 1.2, 2.1);
|
||
|
Vector3d point_velocity_ref;
|
||
|
Vector3d point_velocity;
|
||
|
|
||
|
Q[0] = 1.1;
|
||
|
Q[1] = 1.2;
|
||
|
Q[2] = 1.3;
|
||
|
Q[3] = 0.7;
|
||
|
Q[4] = 0.8;
|
||
|
Q[5] = 0.9;
|
||
|
|
||
|
QDot[0] = -1.1;
|
||
|
QDot[1] = 2.2;
|
||
|
QDot[2] = 1.3;
|
||
|
QDot[3] = -2.7;
|
||
|
QDot[4] = 1.8;
|
||
|
QDot[5] = -2.9;
|
||
|
|
||
|
// Compute the reference velocity
|
||
|
point_velocity_ref = CalcPointVelocity (model, Q, QDot, base_body_id, point_position);
|
||
|
|
||
|
G.setZero();
|
||
|
CalcPointJacobian (model, Q, base_body_id, point_position, G);
|
||
|
|
||
|
point_velocity = G * QDot;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (
|
||
|
point_velocity_ref.data(),
|
||
|
point_velocity.data(),
|
||
|
3, TEST_PREC
|
||
|
);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture, TestInverseKinematicSimple) {
|
||
|
std::vector<unsigned int> body_ids;
|
||
|
std::vector<Vector3d> body_points;
|
||
|
std::vector<Vector3d> target_pos;
|
||
|
|
||
|
Q[0] = 0.2;
|
||
|
Q[1] = 0.1;
|
||
|
Q[2] = 0.1;
|
||
|
|
||
|
VectorNd Qres = VectorNd::Zero ((size_t) model->dof_count);
|
||
|
|
||
|
unsigned int body_id = body_d_id;
|
||
|
Vector3d body_point = Vector3d (1., 0., 0.);
|
||
|
Vector3d target (1.3, 0., 0.);
|
||
|
|
||
|
body_ids.push_back (body_d_id);
|
||
|
body_points.push_back (body_point);
|
||
|
target_pos.push_back (target);
|
||
|
|
||
|
ClearLogOutput();
|
||
|
bool res = InverseKinematics (*model, Q, body_ids, body_points, target_pos, Qres);
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
CHECK_EQUAL (true, res);
|
||
|
|
||
|
UpdateKinematicsCustom (*model, &Qres, NULL, NULL);
|
||
|
|
||
|
Vector3d effector;
|
||
|
effector = CalcBodyToBaseCoordinates(*model, Qres, body_id, body_point, false);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (target.data(), effector.data(), 3, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture6DoF, TestInverseKinematicUnreachable) {
|
||
|
std::vector<unsigned int> body_ids;
|
||
|
std::vector<Vector3d> body_points;
|
||
|
std::vector<Vector3d> target_pos;
|
||
|
|
||
|
Q[0] = 0.2;
|
||
|
Q[1] = 0.1;
|
||
|
Q[2] = 0.1;
|
||
|
|
||
|
VectorNd Qres = VectorNd::Zero ((size_t) model->dof_count);
|
||
|
|
||
|
unsigned int body_id = child_id;
|
||
|
Vector3d body_point = Vector3d (1., 0., 0.);
|
||
|
Vector3d target (2.2, 0., 0.);
|
||
|
|
||
|
body_ids.push_back (body_id);
|
||
|
body_points.push_back (body_point);
|
||
|
target_pos.push_back (target);
|
||
|
|
||
|
ClearLogOutput();
|
||
|
bool res = InverseKinematics (*model, Q, body_ids, body_points, target_pos, Qres, 1.0e-8, 0.9, 1000);
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
CHECK_EQUAL (true, res);
|
||
|
|
||
|
UpdateKinematicsCustom (*model, &Qres, NULL, NULL);
|
||
|
|
||
|
Vector3d effector;
|
||
|
effector = CalcBodyToBaseCoordinates(*model, Qres, body_id, body_point, false);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (2.0, 0., 0.).data(), effector.data(), 3, 1.0e-7);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE(KinematicsFixture6DoF, TestInverseKinematicTwoPoints) {
|
||
|
std::vector<unsigned int> body_ids;
|
||
|
std::vector<Vector3d> body_points;
|
||
|
std::vector<Vector3d> target_pos;
|
||
|
|
||
|
Q[0] = 0.2;
|
||
|
Q[1] = 0.1;
|
||
|
Q[2] = 0.1;
|
||
|
|
||
|
VectorNd Qres = VectorNd::Zero ((size_t) model->dof_count);
|
||
|
|
||
|
unsigned int body_id = child_id;
|
||
|
Vector3d body_point = Vector3d (1., 0., 0.);
|
||
|
Vector3d target (2., 0., 0.);
|
||
|
|
||
|
body_ids.push_back (body_id);
|
||
|
body_points.push_back (body_point);
|
||
|
target_pos.push_back (target);
|
||
|
|
||
|
body_ids.push_back (base_id);
|
||
|
body_points.push_back (Vector3d (0.6, 1.0, 0.));
|
||
|
target_pos.push_back (Vector3d (0.5, 1.1, 0.));
|
||
|
|
||
|
ClearLogOutput();
|
||
|
bool res = InverseKinematics (*model, Q, body_ids, body_points, target_pos, Qres, 1.0e-3, 0.9, 200);
|
||
|
CHECK_EQUAL (true, res);
|
||
|
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
UpdateKinematicsCustom (*model, &Qres, NULL, NULL);
|
||
|
|
||
|
Vector3d effector;
|
||
|
|
||
|
// testing with very low precision
|
||
|
effector = CalcBodyToBaseCoordinates(*model, Qres, body_ids[0], body_points[0], false);
|
||
|
CHECK_ARRAY_CLOSE (target_pos[0].data(), effector.data(), 3, 1.0e-1);
|
||
|
|
||
|
effector = CalcBodyToBaseCoordinates(*model, Qres, body_ids[1], body_points[1], false);
|
||
|
CHECK_ARRAY_CLOSE (target_pos[1].data(), effector.data(), 3, 1.0e-1);
|
||
|
}
|
||
|
|
||
|
TEST ( FixedJointBodyCalcBodyToBase ) {
|
||
|
// the standard modeling using a null body
|
||
|
Body null_body;
|
||
|
Body body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
Body fixed_body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
|
||
|
Model model;
|
||
|
|
||
|
Joint joint_rot_z ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
model.AddBody (0, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, body);
|
||
|
unsigned int fixed_body_id = model.AppendBody (Xtrans(Vector3d(0., 1., 0.)), Joint(JointTypeFixed), fixed_body);
|
||
|
|
||
|
VectorNd Q_zero = VectorNd::Zero (model.dof_count);
|
||
|
Vector3d base_coords = CalcBodyToBaseCoordinates (model, Q_zero, fixed_body_id, Vector3d (1., 1., 0.1));
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 2., 0.1).data(), base_coords.data(), 3, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST ( FixedJointBodyCalcBodyToBaseRotated ) {
|
||
|
// the standard modeling using a null body
|
||
|
Body null_body;
|
||
|
Body body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
Body fixed_body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
|
||
|
Model model;
|
||
|
|
||
|
Joint joint_rot_z ( SpatialVector(0., 0., 1., 0., 0., 0.));
|
||
|
model.AddBody (0, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, body);
|
||
|
unsigned int fixed_body_id = model.AppendBody (Xtrans(Vector3d(1., 0., 0.)), Joint(JointTypeFixed), fixed_body);
|
||
|
|
||
|
VectorNd Q = VectorNd::Zero (model.dof_count);
|
||
|
|
||
|
ClearLogOutput();
|
||
|
Q[0] = M_PI * 0.5;
|
||
|
Vector3d base_coords = CalcBodyToBaseCoordinates (model, Q, fixed_body_id, Vector3d (1., 0., 0.));
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (0., 2., 0.).data(), base_coords.data(), 3, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST ( FixedJointBodyCalcBaseToBody ) {
|
||
|
// the standard modeling using a null body
|
||
|
Body null_body;
|
||
|
Body body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
Body fixed_body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
|
||
|
Model model;
|
||
|
|
||
|
Joint joint_rot_z ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
model.AddBody (0, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, body);
|
||
|
unsigned int fixed_body_id = model.AppendBody (Xtrans(Vector3d(0., 1., 0.)), Joint(JointTypeFixed), fixed_body);
|
||
|
|
||
|
VectorNd Q_zero = VectorNd::Zero (model.dof_count);
|
||
|
Vector3d base_coords = CalcBaseToBodyCoordinates (model, Q_zero, fixed_body_id, Vector3d (1., 2., 0.1));
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 1., 0.1).data(), base_coords.data(), 3, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST ( FixedJointBodyCalcBaseToBodyRotated ) {
|
||
|
// the standard modeling using a null body
|
||
|
Body null_body;
|
||
|
Body body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
Body fixed_body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
|
||
|
Model model;
|
||
|
|
||
|
Joint joint_rot_z ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
model.AddBody (0, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, body);
|
||
|
unsigned int fixed_body_id = model.AppendBody (Xtrans(Vector3d(1., 0., 0.)), Joint(JointTypeFixed), fixed_body);
|
||
|
|
||
|
VectorNd Q = VectorNd::Zero (model.dof_count);
|
||
|
|
||
|
ClearLogOutput();
|
||
|
Q[0] = M_PI * 0.5;
|
||
|
Vector3d base_coords = CalcBaseToBodyCoordinates (model, Q, fixed_body_id, Vector3d (0., 2., 0.));
|
||
|
// cout << LogOutput.str() << endl;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (Vector3d (1., 0., 0.).data(), base_coords.data(), 3, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST ( FixedJointBodyWorldOrientation ) {
|
||
|
// the standard modeling using a null body
|
||
|
Body null_body;
|
||
|
Body body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
Body fixed_body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
|
||
|
Model model;
|
||
|
|
||
|
Joint joint_rot_z ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
model.AddBody (0, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, body);
|
||
|
|
||
|
SpatialTransform transform = Xrotz(0.25) * Xtrans (Vector3d (1., 2., 3.));
|
||
|
unsigned int fixed_body_id = model.AppendBody (transform, Joint(JointTypeFixed), fixed_body);
|
||
|
|
||
|
VectorNd Q_zero = VectorNd::Zero (model.dof_count);
|
||
|
Matrix3d orientation = CalcBodyWorldOrientation (model, Q_zero, fixed_body_id);
|
||
|
|
||
|
Matrix3d reference = transform.E;
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (reference.data(), orientation.data(), 9, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST ( FixedJointCalcPointJacobian ) {
|
||
|
// the standard modeling using a null body
|
||
|
Body null_body;
|
||
|
Body body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
Body fixed_body(1., Vector3d (1., 0.4, 0.4), Vector3d (1., 1., 1.));
|
||
|
|
||
|
Model model;
|
||
|
|
||
|
Joint joint_rot_z ( SpatialVector (0., 0., 1., 0., 0., 0.));
|
||
|
model.AddBody (0, Xtrans(Vector3d(0., 0., 0.)), joint_rot_z, body);
|
||
|
|
||
|
SpatialTransform transform = Xrotz(0.25) * Xtrans (Vector3d (1., 2., 3.));
|
||
|
unsigned int fixed_body_id = model.AppendBody (transform, Joint(JointTypeFixed), fixed_body);
|
||
|
|
||
|
VectorNd Q = VectorNd::Zero (model.dof_count);
|
||
|
VectorNd QDot = VectorNd::Zero (model.dof_count);
|
||
|
|
||
|
Q[0] = 1.1;
|
||
|
QDot[0] = 1.2;
|
||
|
|
||
|
Vector3d point_position (1., 0., 0.);
|
||
|
|
||
|
MatrixNd G = MatrixNd::Zero (3, model.dof_count);
|
||
|
CalcPointJacobian (model, Q, fixed_body_id, point_position, G);
|
||
|
Vector3d point_velocity_jacobian = G * QDot;
|
||
|
Vector3d point_velocity_reference = CalcPointVelocity (model, Q, QDot, fixed_body_id, point_position);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (point_velocity_reference.data(), point_velocity_jacobian.data(), 3, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( Human36, SpatialJacobianSimple ) {
|
||
|
randomizeStates();
|
||
|
|
||
|
unsigned int foot_r_id = model->GetBodyId ("foot_r");
|
||
|
MatrixNd G (MatrixNd::Zero (6, model->dof_count));
|
||
|
|
||
|
CalcBodySpatialJacobian (*model, q, foot_r_id, G);
|
||
|
|
||
|
UpdateKinematicsCustom (*model, &q, &qdot, NULL);
|
||
|
SpatialVector v_body = SpatialVector(G * qdot);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (model->v[foot_r_id].data(), v_body.data(), 6, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( Human36, SpatialJacobianFixedBody ) {
|
||
|
randomizeStates();
|
||
|
|
||
|
unsigned int uppertrunk_id = model->GetBodyId ("uppertrunk");
|
||
|
MatrixNd G (MatrixNd::Zero (6, model->dof_count));
|
||
|
|
||
|
CalcBodySpatialJacobian (*model, q, uppertrunk_id, G);
|
||
|
|
||
|
unsigned int fixed_body_id = uppertrunk_id - model->fixed_body_discriminator;
|
||
|
unsigned int movable_parent = model->mFixedBodies[fixed_body_id].mMovableParent;
|
||
|
|
||
|
UpdateKinematicsCustom (*model, &q, &qdot, NULL);
|
||
|
SpatialVector v_body = SpatialVector(G * qdot);
|
||
|
|
||
|
SpatialVector v_fixed_body = model->mFixedBodies[fixed_body_id].mParentTransform.apply (model->v[movable_parent]);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (v_fixed_body.data(), v_body.data(), 6, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( Human36, CalcPointJacobian6D ) {
|
||
|
randomizeStates();
|
||
|
|
||
|
unsigned int foot_r_id = model->GetBodyId ("foot_r");
|
||
|
Vector3d point_local (1.1, 2.2, 3.3);
|
||
|
|
||
|
// Compute the 6-D velocity using the 6-D Jacobian
|
||
|
MatrixNd G (MatrixNd::Zero (6, model->dof_count));
|
||
|
CalcPointJacobian6D (*model, q, foot_r_id, point_local, G);
|
||
|
SpatialVector v_foot_0_jac = SpatialVector (G * qdot);
|
||
|
|
||
|
// Compute the 6-D velocity by transforming the body velocity to the
|
||
|
// reference point and aligning it with the base coordinate system
|
||
|
Vector3d r_point = CalcBodyToBaseCoordinates (*model, q, foot_r_id, point_local);
|
||
|
SpatialTransform X_foot (Matrix3d::Identity(), r_point);
|
||
|
UpdateKinematicsCustom (*model, &q, &qdot, NULL);
|
||
|
SpatialVector v_foot_0_ref = X_foot.apply(model->X_base[foot_r_id].inverse().apply(model->v[foot_r_id]));
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (v_foot_0_ref.data(), v_foot_0_jac.data(), 6, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( Human36, CalcPointVelocity6D ) {
|
||
|
randomizeStates();
|
||
|
|
||
|
unsigned int foot_r_id = model->GetBodyId ("foot_r");
|
||
|
Vector3d point_local (1.1, 2.2, 3.3);
|
||
|
|
||
|
// Compute the 6-D velocity
|
||
|
SpatialVector v_foot_0 = CalcPointVelocity6D (*model, q, qdot, foot_r_id, point_local);
|
||
|
|
||
|
// Compute the 6-D velocity by transforming the body velocity to the
|
||
|
// reference point and aligning it with the base coordinate system
|
||
|
Vector3d r_point = CalcBodyToBaseCoordinates (*model, q, foot_r_id, point_local);
|
||
|
SpatialTransform X_foot (Matrix3d::Identity(), r_point);
|
||
|
UpdateKinematicsCustom (*model, &q, &qdot, NULL);
|
||
|
SpatialVector v_foot_0_ref = X_foot.apply(model->X_base[foot_r_id].inverse().apply(model->v[foot_r_id]));
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (v_foot_0_ref.data(), v_foot_0.data(), 6, TEST_PREC);
|
||
|
}
|
||
|
|
||
|
TEST_FIXTURE ( Human36, CalcPointAcceleration6D ) {
|
||
|
randomizeStates();
|
||
|
|
||
|
unsigned int foot_r_id = model->GetBodyId ("foot_r");
|
||
|
Vector3d point_local (1.1, 2.2, 3.3);
|
||
|
|
||
|
// Compute the 6-D acceleration
|
||
|
SpatialVector a_foot_0 = CalcPointAcceleration6D (*model, q, qdot, qddot, foot_r_id, point_local);
|
||
|
|
||
|
// Compute the 6-D acceleration by adding the coriolis term to the
|
||
|
// acceleration of the body and transforming the result to the
|
||
|
// point and align it with the base coordinate system.
|
||
|
Vector3d r_point = CalcBodyToBaseCoordinates (*model, q, foot_r_id, point_local);
|
||
|
Vector3d v_foot_0 = CalcPointVelocity (*model, q, qdot, foot_r_id, point_local);
|
||
|
SpatialVector rdot (0., 0., 0., v_foot_0[0], v_foot_0[1], v_foot_0[2]);
|
||
|
|
||
|
SpatialTransform X_foot (Matrix3d::Identity(), r_point);
|
||
|
UpdateKinematicsCustom (*model, &q, &qdot, NULL);
|
||
|
SpatialVector a_foot_0_ref = X_foot.apply(
|
||
|
model->X_base[foot_r_id].inverse().apply(model->a[foot_r_id])
|
||
|
- crossm(rdot,
|
||
|
model->X_base[foot_r_id].inverse().apply(model->v[foot_r_id])
|
||
|
)
|
||
|
);
|
||
|
|
||
|
CHECK_ARRAY_CLOSE (a_foot_0_ref.data(), a_foot_0.data(), 6, TEST_PREC);
|
||
|
}
|