Clean up engine_derivative_test.cc
PiperOrigin-RevId: 730166629 Change-Id: I3418be9f7b289f4109ae43c221b89199d2ccf325
This commit is contained in:
committed by
Copybara-Service
parent
c52d1b3941
commit
81b1948b46
@@ -28,13 +28,12 @@
|
|||||||
#include "src/engine/engine_forward.h"
|
#include "src/engine/engine_forward.h"
|
||||||
#include "src/engine/engine_io.h"
|
#include "src/engine/engine_io.h"
|
||||||
#include "src/engine/engine_util_blas.h"
|
#include "src/engine/engine_util_blas.h"
|
||||||
#include "src/engine/engine_util_errmem.h"
|
|
||||||
#include "src/engine/engine_util_sparse.h"
|
|
||||||
#include "test/fixture.h"
|
#include "test/fixture.h"
|
||||||
|
|
||||||
namespace mujoco {
|
namespace mujoco {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using ::std::vector;
|
||||||
using ::testing::Pointwise;
|
using ::testing::Pointwise;
|
||||||
using ::testing::DoubleNear;
|
using ::testing::DoubleNear;
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
@@ -120,7 +119,7 @@ TEST_F(DerivativeTest, SmoothDvel) {
|
|||||||
|
|
||||||
// expect derivatives to be non-zero, make copy of qDeriv as a vector
|
// expect derivatives to be non-zero, make copy of qDeriv as a vector
|
||||||
EXPECT_GT(mju_norm(data->qDeriv, nD), 0);
|
EXPECT_GT(mju_norm(data->qDeriv, nD), 0);
|
||||||
std::vector<mjtNum> qDerivAnalytic = AsVector(data->qDeriv, nD);
|
vector<mjtNum> qDerivAnalytic = AsVector(data->qDeriv, nD);
|
||||||
|
|
||||||
// compute finite-difference derivatives
|
// compute finite-difference derivatives
|
||||||
mjtNum eps = 1e-7;
|
mjtNum eps = 1e-7;
|
||||||
@@ -364,13 +363,13 @@ TEST_F(DerivativeTest, StepSkip) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// save state
|
// save state
|
||||||
std::vector<mjtNum> qpos = AsVector(data->qpos, nq);
|
vector<mjtNum> qpos = AsVector(data->qpos, nq);
|
||||||
std::vector<mjtNum> qvel = AsVector(data->qvel, nv);
|
vector<mjtNum> qvel = AsVector(data->qvel, nv);
|
||||||
|
|
||||||
// take one more step, save next state
|
// take one more step, save next state
|
||||||
mj_step(model, data);
|
mj_step(model, data);
|
||||||
std::vector<mjtNum> qpos_next = AsVector(data->qpos, nq);
|
vector<mjtNum> qpos_next = AsVector(data->qpos, nq);
|
||||||
std::vector<mjtNum> qvel_next = AsVector(data->qvel, nv);
|
vector<mjtNum> qvel_next = AsVector(data->qvel, nv);
|
||||||
|
|
||||||
// reset state, take step again, compare (assert mj_step is deterministic)
|
// reset state, take step again, compare (assert mj_step is deterministic)
|
||||||
mju_copy(data->qpos, qpos.data(), nq);
|
mju_copy(data->qpos, qpos.data(), nq);
|
||||||
@@ -384,8 +383,8 @@ TEST_F(DerivativeTest, StepSkip) {
|
|||||||
mju_copy(data->qvel, qvel.data(), nv);
|
mju_copy(data->qvel, qvel.data(), nv);
|
||||||
data->ctrl[0] = 1;
|
data->ctrl[0] = 1;
|
||||||
mj_stepSkip(model, data, mjSTAGE_VEL, 0); // skipping both POS and VEL
|
mj_stepSkip(model, data, mjSTAGE_VEL, 0); // skipping both POS and VEL
|
||||||
std::vector<mjtNum> qpos_next_dctrl = AsVector(data->qpos, nq);
|
vector<mjtNum> qpos_next_dctrl = AsVector(data->qpos, nq);
|
||||||
std::vector<mjtNum> qvel_next_dctrl = AsVector(data->qvel, nv);
|
vector<mjtNum> qvel_next_dctrl = AsVector(data->qvel, nv);
|
||||||
|
|
||||||
// reset state (ctrl remains unchanged), call full mj_step, compare
|
// reset state (ctrl remains unchanged), call full mj_step, compare
|
||||||
mju_copy(data->qpos, qpos.data(), nq);
|
mju_copy(data->qpos, qpos.data(), nq);
|
||||||
@@ -399,8 +398,8 @@ TEST_F(DerivativeTest, StepSkip) {
|
|||||||
mju_copy(data->qvel, qvel.data(), nv);
|
mju_copy(data->qvel, qvel.data(), nv);
|
||||||
data->qvel[0] += 1;
|
data->qvel[0] += 1;
|
||||||
mj_stepSkip(model, data, mjSTAGE_POS, 0); // skipping POS
|
mj_stepSkip(model, data, mjSTAGE_POS, 0); // skipping POS
|
||||||
std::vector<mjtNum> qpos_next_dvel = AsVector(data->qpos, nq);
|
vector<mjtNum> qpos_next_dvel = AsVector(data->qpos, nq);
|
||||||
std::vector<mjtNum> qvel_next_dvel = AsVector(data->qvel, nv);
|
vector<mjtNum> qvel_next_dvel = AsVector(data->qvel, nv);
|
||||||
|
|
||||||
// reset state, change velocity, call full mj_step, compare
|
// reset state, change velocity, call full mj_step, compare
|
||||||
mju_copy(data->qpos, qpos.data(), nq);
|
mju_copy(data->qpos, qpos.data(), nq);
|
||||||
@@ -796,22 +795,17 @@ TEST_F(DerivativeTest, LinearSystemInverse) {
|
|||||||
mjModel* model = mj_loadXML(xml_path.c_str(), nullptr, nullptr, 0);
|
mjModel* model = mj_loadXML(xml_path.c_str(), nullptr, nullptr, 0);
|
||||||
mjData* data = mj_makeData(model);
|
mjData* data = mj_makeData(model);
|
||||||
|
|
||||||
static const int nv = 3;
|
int nv = model->nv;
|
||||||
EXPECT_EQ(nv, model->nv);
|
int ns = model->nsensordata;
|
||||||
static const int nu = 2;
|
int nM = model->nM;
|
||||||
EXPECT_EQ(nu, model->nu);
|
|
||||||
static const int ns = 5;
|
|
||||||
EXPECT_EQ(ns, model->nsensordata);
|
|
||||||
static const int nM = 6;
|
|
||||||
EXPECT_EQ(nM, model->nM);
|
|
||||||
|
|
||||||
mjtNum DfDq[nv*nv];
|
vector<mjtNum> DfDq(nv*nv);
|
||||||
mjtNum DfDv[nv*nv];
|
vector<mjtNum> DfDv(nv*nv);
|
||||||
mjtNum DfDa[nv*nv];
|
vector<mjtNum> DfDa(nv*nv);
|
||||||
mjtNum DsDq[nv*ns];
|
vector<mjtNum> DsDq(nv*ns);
|
||||||
mjtNum DsDv[nv*ns];
|
vector<mjtNum> DsDv(nv*ns);
|
||||||
mjtNum DsDa[nv*ns];
|
vector<mjtNum> DsDa(nv*ns);
|
||||||
mjtNum DmDq[nv*nM];
|
vector<mjtNum> DmDq(nv*nM);
|
||||||
|
|
||||||
// call mj_forward to get accelerations at initial state
|
// call mj_forward to get accelerations at initial state
|
||||||
mj_forward(model, data);
|
mj_forward(model, data);
|
||||||
@@ -820,61 +814,54 @@ TEST_F(DerivativeTest, LinearSystemInverse) {
|
|||||||
mjtNum eps = 1e-6;
|
mjtNum eps = 1e-6;
|
||||||
mjtByte flg_actuation = 0;
|
mjtByte flg_actuation = 0;
|
||||||
mjd_inverseFD(model, data, eps, flg_actuation,
|
mjd_inverseFD(model, data, eps, flg_actuation,
|
||||||
DfDq, DfDv, DfDa,
|
DfDq.data(), DfDv.data(), DfDa.data(),
|
||||||
DsDq, DsDv, DsDa,
|
DsDq.data(), DsDv.data(), DsDa.data(),
|
||||||
DmDq);
|
DmDq.data());
|
||||||
|
|
||||||
// expect that position derivatives are the stiffnesses
|
// expect that position derivatives are the stiffnesses
|
||||||
mjtNum DfDq_expect[3*3] = {model->jnt_stiffness[0], 0, 0,
|
vector<mjtNum> DfDq_expect = {model->jnt_stiffness[0], 0, 0,
|
||||||
0, model->jnt_stiffness[1], 0,
|
0, model->jnt_stiffness[1], 0,
|
||||||
0, 0, model->jnt_stiffness[2]};
|
0, 0, model->jnt_stiffness[2]};
|
||||||
EXPECT_THAT(AsVector(DfDq, nv*nv),
|
EXPECT_THAT(DfDq, Pointwise(DoubleNear(eps), DfDq_expect));
|
||||||
Pointwise(DoubleNear(eps), AsVector(DfDq_expect, nv*nv)));
|
|
||||||
|
|
||||||
// expect that velocity derivatives are the dampings
|
// expect that velocity derivatives are the dampings
|
||||||
mjtNum DfDv_expect[3*3] = {model->dof_damping[0], 0, 0,
|
vector<mjtNum> DfDv_expect = {model->dof_damping[0], 0, 0,
|
||||||
0, model->dof_damping[1], 0,
|
0, model->dof_damping[1], 0,
|
||||||
0, 0, model->dof_damping[2]};
|
0, 0, model->dof_damping[2]};
|
||||||
EXPECT_THAT(AsVector(DfDv, nv*nv),
|
EXPECT_THAT(DfDv, Pointwise(DoubleNear(eps), DfDv_expect));
|
||||||
Pointwise(DoubleNear(eps), AsVector(DfDv_expect, nv*nv)));
|
|
||||||
|
|
||||||
// expect that acceleration derivatives are the mass matrix
|
// expect that acceleration derivatives are the mass matrix
|
||||||
mjtNum DfDa_expect[3*3];
|
vector<mjtNum> DfDa_expect(nv*nv, 0);
|
||||||
mj_fullM(model, DfDa_expect, data->qM);
|
mj_fullM(model, DfDa_expect.data(), data->qM);
|
||||||
EXPECT_THAT(AsVector(DfDa, nv*nv),
|
EXPECT_THAT(DfDa, Pointwise(DoubleNear(eps), DfDa_expect));
|
||||||
Pointwise(DoubleNear(eps), AsVector(DfDa_expect, nv*nv)));
|
|
||||||
|
|
||||||
// expect that sensor derivatives w.r.t position only see sensor 1 at dof 0
|
// expect that sensor derivatives w.r.t position only see sensor 1 at dof 0
|
||||||
mjtNum DsDq_expect[3*5] = {0};
|
vector<mjtNum> DsDq_expect(nv*ns, 0);
|
||||||
int dof_index = 0;
|
int dof_index = 0;
|
||||||
int sensordata_index = model->sensor_adr[1];
|
int sensordata_index = model->sensor_adr[1];
|
||||||
DsDq_expect[dof_index*ns + sensordata_index] = 1;
|
DsDq_expect[dof_index*ns + sensordata_index] = 1;
|
||||||
EXPECT_THAT(AsVector(DsDq, nv*ns),
|
EXPECT_THAT(DsDq, Pointwise(DoubleNear(eps), DsDq_expect));
|
||||||
Pointwise(DoubleNear(eps), AsVector(DsDq_expect, nv*ns)));
|
|
||||||
|
|
||||||
// expect that sensor derivatives w.r.t velocity only see sensor 0 at dof 1
|
// expect that sensor derivatives w.r.t velocity only see sensor 0 at dof 1
|
||||||
mjtNum DsDv_expect[3*5] = {0};
|
vector<mjtNum> DsDv_expect(nv*ns, 0);
|
||||||
dof_index = 1;
|
dof_index = 1;
|
||||||
sensordata_index = model->sensor_adr[0];
|
sensordata_index = model->sensor_adr[0];
|
||||||
DsDv_expect[dof_index*ns + sensordata_index] = 1;
|
DsDv_expect[dof_index*ns + sensordata_index] = 1;
|
||||||
EXPECT_THAT(AsVector(DsDv, nv*ns),
|
EXPECT_THAT(DsDv, Pointwise(DoubleNear(eps), DsDv_expect));
|
||||||
Pointwise(DoubleNear(eps), AsVector(DsDv_expect, nv*ns)));
|
|
||||||
|
|
||||||
// expect that sensor derivatives w.r.t acceleration see the accelerometer
|
// expect that sensor derivatives w.r.t acceleration see the accelerometer
|
||||||
// in the y-axis, affected by both dof 0 and dof 1
|
// in the y-axis, affected by both dof 0 and dof 1
|
||||||
mjtNum DsDa_expect[3*5] = {0};
|
vector<mjtNum> DsDa_expect(nv*ns, 0);
|
||||||
dof_index = 0;
|
dof_index = 0;
|
||||||
sensordata_index = model->sensor_adr[2] + 1;
|
sensordata_index = model->sensor_adr[2] + 1;
|
||||||
DsDa_expect[dof_index*ns + sensordata_index] = 1;
|
DsDa_expect[dof_index*ns + sensordata_index] = 1;
|
||||||
dof_index = 1;
|
dof_index = 1;
|
||||||
DsDa_expect[dof_index*ns + sensordata_index] = 1;
|
DsDa_expect[dof_index*ns + sensordata_index] = 1;
|
||||||
EXPECT_THAT(AsVector(DsDa, nv*ns),
|
EXPECT_THAT(DsDa, Pointwise(DoubleNear(eps), DsDa_expect));
|
||||||
Pointwise(DoubleNear(eps), AsVector(DsDa_expect, nv*ns)));
|
|
||||||
|
|
||||||
// expect that mass matrix derivatives are zero
|
// expect that mass matrix derivatives are zero
|
||||||
mjtNum DmDq_expect[nv*nM] = {0};
|
vector<mjtNum> DmDq_expect(nv*nM, 0);
|
||||||
EXPECT_THAT(AsVector(DmDq, nv*nM),
|
EXPECT_THAT(DmDq, Pointwise(DoubleNear(eps), DmDq_expect));
|
||||||
Pointwise(DoubleNear(eps), AsVector(DmDq_expect, nv*nM)));
|
|
||||||
|
|
||||||
mj_deleteData(data);
|
mj_deleteData(data);
|
||||||
mj_deleteModel(model);
|
mj_deleteModel(model);
|
||||||
@@ -904,8 +891,8 @@ void randomQuatPair(mjtNum qa[4], mjtNum qb[4], mjtNum angle, int seed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// utility: finite-difference Jacobians of mju_subQuat
|
// utility: finite-difference Jacobians of mju_subQuat
|
||||||
void mjd_subQuatFD(mjtNum Da[9], mjtNum Db[9],
|
static void subQuatFD(mjtNum Da[9], mjtNum Db[9],
|
||||||
const mjtNum qa[4], const mjtNum qb[4], mjtNum eps) {
|
const mjtNum qa[4], const mjtNum qb[4], mjtNum eps) {
|
||||||
// subQuat
|
// subQuat
|
||||||
mjtNum y[3];
|
mjtNum y[3];
|
||||||
mju_subQuat(y, qa, qb);
|
mju_subQuat(y, qa, qb);
|
||||||
@@ -966,7 +953,7 @@ TEST_F(DerivativeTest, SubQuat) {
|
|||||||
// finite-differenced Jacobians
|
// finite-differenced Jacobians
|
||||||
mjtNum DaFD[9];
|
mjtNum DaFD[9];
|
||||||
mjtNum DbFD[9];
|
mjtNum DbFD[9];
|
||||||
mjd_subQuatFD(DaFD, DbFD, qa, qb, eps);
|
subQuatFD(DaFD, DbFD, qa, qb, eps);
|
||||||
|
|
||||||
// expect numerical equality
|
// expect numerical equality
|
||||||
EXPECT_THAT(AsVector(DaFD, 9),
|
EXPECT_THAT(AsVector(DaFD, 9),
|
||||||
@@ -978,7 +965,7 @@ TEST_F(DerivativeTest, SubQuat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// utility: random quaternion, 3D velocity
|
// utility: random quaternion, 3D velocity
|
||||||
void randomQuatVel(mjtNum quat[4], mjtNum vel[3], int seed) {
|
static void randomQuatVel(mjtNum quat[4], mjtNum vel[3], int seed) {
|
||||||
// make distribution using seed
|
// make distribution using seed
|
||||||
std::mt19937_64 rng;
|
std::mt19937_64 rng;
|
||||||
rng.seed(seed);
|
rng.seed(seed);
|
||||||
|
|||||||
Reference in New Issue
Block a user