Skip to content

Commit 0f563ec

Browse files
yuvaltassacopybara-github
authored andcommitted
Switch mjData.{qH,qLD} from reduced ("C") to full ("M") inertia matrix structure. No performance impact of extra zeros because of existing "simple dof" skipping mechanism.
PiperOrigin-RevId: 733523931 Change-Id: Ic8d8a152dda5532331c239cb6b4ce7d8d09b7fff
1 parent 51f6aa8 commit 0f563ec

20 files changed

+95
-98
lines changed

doc/includes/references.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ struct mjData_ {
272272
mjtNum* qM; // total inertia (sparse) (nM x 1)
273273

274274
// computed by mj_fwdPosition/mj_factorM
275-
mjtNum* qLD; // L'*D*L factorization of M (sparse) (nC x 1)
275+
mjtNum* qLD; // L'*D*L factorization of M (sparse) (nM x 1)
276276
mjtNum* qLDiagInv; // 1/diag(D) (nv x 1)
277277

278278
// computed by mj_collisionTree
@@ -305,7 +305,7 @@ struct mjData_ {
305305
mjtNum* subtree_angmom; // angular momentum about subtree com (nbody x 3)
306306

307307
// computed by mj_Euler or mj_implicit
308-
mjtNum* qH; // L'*D*L factorization of modified M (nC x 1)
308+
mjtNum* qH; // L'*D*L factorization of modified M (nM x 1)
309309
mjtNum* qHDiagInv; // 1/diag(D) of modified M (nv x 1)
310310

311311
// computed by mj_resetData

include/mujoco/mjdata.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ struct mjData_ {
300300
mjtNum* qM; // total inertia (sparse) (nM x 1)
301301

302302
// computed by mj_fwdPosition/mj_factorM
303-
mjtNum* qLD; // L'*D*L factorization of M (sparse) (nC x 1)
303+
mjtNum* qLD; // L'*D*L factorization of M (sparse) (nM x 1)
304304
mjtNum* qLDiagInv; // 1/diag(D) (nv x 1)
305305

306306
// computed by mj_collisionTree
@@ -333,7 +333,7 @@ struct mjData_ {
333333
mjtNum* subtree_angmom; // angular momentum about subtree com (nbody x 3)
334334

335335
// computed by mj_Euler or mj_implicit
336-
mjtNum* qH; // L'*D*L factorization of modified M (nC x 1)
336+
mjtNum* qH; // L'*D*L factorization of modified M (nM x 1)
337337
mjtNum* qHDiagInv; // 1/diag(D) of modified M (nv x 1)
338338

339339
// computed by mj_resetData

include/mujoco/mjxmacro.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@
650650
X ( mjtNum, actuator_moment, nJmom, 1 ) \
651651
X ( mjtNum, crb, nbody, 10 ) \
652652
X ( mjtNum, qM, nM, 1 ) \
653-
X ( mjtNum, qLD, nC, 1 ) \
653+
X ( mjtNum, qLD, nM, 1 ) \
654654
X ( mjtNum, qLDiagInv, nv, 1 ) \
655655
XMJV( mjtNum, bvh_aabb_dyn, nbvhdynamic, 6 ) \
656656
XMJV( mjtByte, bvh_active, nbvh, 1 ) \
@@ -667,7 +667,7 @@
667667
X ( mjtNum, qfrc_passive, nv, 1 ) \
668668
X ( mjtNum, subtree_linvel, nbody, 3 ) \
669669
X ( mjtNum, subtree_angmom, nbody, 3 ) \
670-
X ( mjtNum, qH, nC, 1 ) \
670+
X ( mjtNum, qH, nM, 1 ) \
671671
X ( mjtNum, qHDiagInv, nv, 1 ) \
672672
X ( int, B_rownnz, nbody, 1 ) \
673673
X ( int, B_rowadr, nbody, 1 ) \

mjx/mujoco/mjx/_src/io.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ def make_data(
372372
'efc_aref': (nefc, float),
373373
'efc_force': (nefc, float),
374374
'_qM_sparse': (m.nM, float),
375-
'_qLD_sparse': (m.nC, float),
375+
'_qLD_sparse': (m.nM, float),
376376
'_qLDiagInv_sparse': (m.nv, float),
377377
}
378378

@@ -511,7 +511,7 @@ def get_data_into(
511511
value = value[dof_i, dof_j]
512512
elif field.name == 'qLD' and not support.is_sparse(m):
513513
# TODO(erikfrey): provide correct qLDs
514-
value = np.zeros(m.nC)
514+
value = np.zeros(m.nM)
515515
elif field.name == 'qLDiagInv' and not support.is_sparse(m):
516516
value = np.ones(m.nv)
517517

mjx/mujoco/mjx/_src/smooth_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ def test_smooth(self):
9292
# factor_m
9393
dx = jax.jit(mjx.factor_m)(mx, mjx.put_data(m, d))
9494
qLDLegacy = np.zeros(mx.nM) # pylint:disable=invalid-name
95-
for i in range(m.nC):
96-
qLDLegacy[d.mapM2C[i]] = d.qLD[i]
95+
for i in range(m.nM):
96+
qLDLegacy[d.mapM2M[i]] = d.qLD[i]
9797
_assert_eq(qLDLegacy, dx.qLD, 'qLD')
9898
_assert_attr_eq(d, dx, 'qLDiagInv')
9999
_assert_eq(dx._qLD_sparse, np.zeros(0), '_qLD_sparse')

mjx/mujoco/mjx/_src/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,7 @@ class Data(PyTreeNode):
13521352
efc_aref: reference pseudo-acceleration (nefc,)
13531353
efc_force: constraint force in constraint space (nefc,)
13541354
_qM_sparse: qM in sparse representation (nM,)
1355-
_qLD_sparse: qLD in sparse representation (nC,)
1355+
_qLD_sparse: qLD in sparse representation (nM,)
13561356
_qLDiagInv_sparse: qLDiagInv in sparse representation (nv,)
13571357
""" # fmt: skip
13581358
# constant sizes:

python/mujoco/introspect/structs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5356,7 +5356,7 @@
53565356
inner_type=ValueType(name='mjtNum'),
53575357
),
53585358
doc="L'*D*L factorization of M (sparse)",
5359-
array_extent=('nC',),
5359+
array_extent=('nM',),
53605360
),
53615361
StructFieldDecl(
53625362
name='qLDiagInv',
@@ -5492,7 +5492,7 @@
54925492
inner_type=ValueType(name='mjtNum'),
54935493
),
54945494
doc="L'*D*L factorization of modified M",
5495-
array_extent=('nC',),
5495+
array_extent=('nM',),
54965496
),
54975497
StructFieldDecl(
54985498
name='qHDiagInv',

src/engine/engine_core_constraint.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,7 +2131,7 @@ void mj_projectConstraint(const mjModel* m, mjData* d) {
21312131
// inverse square root of D from inertia LDL decomposition
21322132
mjtNum* sqrtInvD = mjSTACKALLOC(d, nv, mjtNum);
21332133
for (int i=0; i < nv; i++) {
2134-
int diag = d->C_rowadr[i] + d->C_rownnz[i] - 1;
2134+
int diag = d->M_rowadr[i] + d->M_rownnz[i] - 1;
21352135
sqrtInvD[i] = 1 / mju_sqrt(d->qLD[diag]);
21362136
}
21372137

@@ -2167,11 +2167,11 @@ void mj_projectConstraint(const mjModel* m, mjData* d) {
21672167
continue;
21682168
}
21692169

2170-
// traverse row j of C, marking new unique nonzeros
2171-
int nnzC = d->C_rownnz[j];
2172-
int adrC = d->C_rowadr[j];
2173-
for (int k=0; k < nnzC; k++) {
2174-
int c = d->C_colind[adrC + k];
2170+
// traverse row j of M, marking new unique nonzeros
2171+
int nnzM = d->M_rownnz[j];
2172+
int adrM = d->M_rowadr[j];
2173+
for (int k=0; k < nnzM; k++) {
2174+
int c = d->M_colind[adrM + k];
21752175
if (marker[c] != r) {
21762176
marker[c] = r;
21772177
nnz++;
@@ -2251,10 +2251,10 @@ void mj_projectConstraint(const mjModel* m, mjData* d) {
22512251
continue;
22522252
}
22532253
int j = B_colind[i];
2254-
int adrC = d->C_rowadr[j];
2255-
mju_addToSclSparseInc(B + adrB, d->qLD + adrC,
2254+
int adrM = d->M_rowadr[j];
2255+
mju_addToSclSparseInc(B + adrB, d->qLD + adrM,
22562256
nnzB, B_colind + adrB,
2257-
d->C_rownnz[j]-1, d->C_colind + adrC, -b);
2257+
d->M_rownnz[j]-1, d->M_colind + adrM, -b);
22582258
}
22592259

22602260
// B(r,:) <- sqrt(inv(D)) * B(r,:)

src/engine/engine_core_smooth.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,11 +1469,11 @@ void mj_factorI_legacy(const mjModel* m, mjData* d, const mjtNum* M, mjtNum* qLD
14691469
// sparse L'*D*L factorizaton of the inertia matrix M, assumed spd
14701470
void mj_factorM(const mjModel* m, mjData* d) {
14711471
TM_START;
1472-
int nC = m->nC;
1473-
for (int i=0; i < nC; i++) {
1474-
d->qLD[i] = d->qM[d->mapM2C[i]];
1472+
int nM = m->nM;
1473+
for (int i=0; i < nM; i++) {
1474+
d->qLD[i] = d->qM[d->mapM2M[i]];
14751475
}
1476-
mj_factorI(d->qLD, d->qLDiagInv, m->nv, d->C_rownnz, d->C_rowadr, m->dof_simplenum, d->C_colind);
1476+
mj_factorI(d->qLD, d->qLDiagInv, m->nv, d->M_rownnz, d->M_rowadr, m->dof_simplenum, d->M_colind);
14771477
TM_ADD(mjTIMER_POS_INERTIA);
14781478
}
14791479

@@ -1715,7 +1715,7 @@ void mj_solveM(const mjModel* m, mjData* d, mjtNum* x, const mjtNum* y, int n) {
17151715
mju_copy(x, y, n*m->nv);
17161716
}
17171717
mj_solveLD(x, d->qLD, d->qLDiagInv, m->nv, n,
1718-
d->C_rownnz, d->C_rowadr, m->dof_simplenum, d->C_colind);
1718+
d->M_rownnz, d->M_rowadr, m->dof_simplenum, d->M_colind);
17191719
}
17201720

17211721

@@ -1727,14 +1727,14 @@ void mj_solveM_island(const mjModel* m, const mjData* d, mjtNum* restrict x, int
17271727
const mjtNum* qLDiagInv = d->qLDiagInv;
17281728
if (island < 0) {
17291729
mj_solveLD(x, qLD, qLDiagInv, m->nv, 1,
1730-
d->C_rownnz, d->C_rowadr, m->dof_simplenum, d->C_colind);
1730+
d->M_rownnz, d->M_rowadr, m->dof_simplenum, d->M_colind);
17311731
return;
17321732
}
17331733

17341734
// local copies of key variables
1735-
const int* rownnz = d->C_rownnz;
1736-
const int* rowadr = d->C_rowadr;
1737-
const int* colind = d->C_colind;
1735+
const int* rownnz = d->M_rownnz;
1736+
const int* rowadr = d->M_rowadr;
1737+
const int* colind = d->M_colind;
17381738
const int* diagnum = m->dof_simplenum;
17391739

17401740
// local constants: island specific
@@ -1785,9 +1785,9 @@ void mj_solveM2(const mjModel* m, mjData* d, mjtNum* x, const mjtNum* y,
17851785
int nv = m->nv;
17861786

17871787
// local copies of key variables
1788-
const int* rownnz = d->C_rownnz;
1789-
const int* rowadr = d->C_rowadr;
1790-
const int* colind = d->C_colind;
1788+
const int* rownnz = d->M_rownnz;
1789+
const int* rowadr = d->M_rowadr;
1790+
const int* colind = d->M_colind;
17911791
const int* diagnum = m->dof_simplenum;
17921792
const mjtNum* qLD = d->qLD;
17931793

src/engine/engine_forward.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,7 @@ static void mj_advance(const mjModel* m, mjData* d,
770770
// Euler integrator, semi-implicit in velocity, possibly skipping factorisation
771771
void mj_EulerSkip(const mjModel* m, mjData* d, int skipfactor) {
772772
TM_START;
773-
int nv = m->nv, nC = m->nC;
773+
int nv = m->nv, nM = m->nM;
774774
mj_markStack(d);
775775
mjtNum* qfrc = mjSTACKALLOC(d, nv, mjtNum);
776776
mjtNum* qacc = mjSTACKALLOC(d, nv, mjtNum);
@@ -795,22 +795,22 @@ void mj_EulerSkip(const mjModel* m, mjData* d, int skipfactor) {
795795
else {
796796
if (!skipfactor) {
797797
// qH = M + h*diag(B)
798-
for (int i=0; i < nC; i++) {
799-
d->qH[i] = d->qM[d->mapM2C[i]];
798+
for (int i=0; i < nM; i++) {
799+
d->qH[i] = d->qM[d->mapM2M[i]];
800800
}
801801
for (int i=0; i < nv; i++) {
802-
d->qH[d->C_rowadr[i] + d->C_rownnz[i] - 1] += m->opt.timestep * m->dof_damping[i];
802+
d->qH[d->M_rowadr[i] + d->M_rownnz[i] - 1] += m->opt.timestep * m->dof_damping[i];
803803
}
804804

805805
// factorize in-place
806-
mj_factorI(d->qH, d->qHDiagInv, nv, d->C_rownnz, d->C_rowadr, m->dof_simplenum, d->C_colind);
806+
mj_factorI(d->qH, d->qHDiagInv, nv, d->M_rownnz, d->M_rowadr, m->dof_simplenum, d->M_colind);
807807
}
808808

809809
// solve
810810
mju_add(qfrc, d->qfrc_smooth, d->qfrc_constraint, nv);
811811
mju_copy(qacc, qfrc, m->nv);
812812
mj_solveLD(qacc, d->qH, d->qHDiagInv, nv, 1,
813-
d->C_rownnz, d->C_rowadr, m->dof_simplenum, d->C_colind);
813+
d->M_rownnz, d->M_rowadr, m->dof_simplenum, d->M_colind);
814814
}
815815

816816
// advance state and time
@@ -939,7 +939,7 @@ void mj_RungeKutta(const mjModel* m, mjData* d, int N) {
939939
// fully implicit in velocity, possibly skipping factorization
940940
void mj_implicitSkip(const mjModel* m, mjData* d, int skipfactor) {
941941
TM_START;
942-
int nv = m->nv, nM = m->nM, nD = m->nD, nC = m->nC;
942+
int nv = m->nv, nM = m->nM, nD = m->nD;
943943

944944
mj_markStack(d);
945945
mjtNum* qfrc = mjSTACKALLOC(d, nv, mjtNum);
@@ -987,18 +987,18 @@ void mj_implicitSkip(const mjModel* m, mjData* d, int skipfactor) {
987987
mju_addScl(MhB, d->qM, MhB, -m->opt.timestep, nM);
988988

989989
// copy into qH
990-
for (int i=0; i < nC; i++) {
991-
d->qH[i] = MhB[d->mapM2C[i]];
990+
for (int i=0; i < nM; i++) {
991+
d->qH[i] = MhB[d->mapM2M[i]];
992992
}
993993

994994
// factorize in-place
995-
mj_factorI(d->qH, d->qHDiagInv, nv, d->C_rownnz, d->C_rowadr, m->dof_simplenum, d->C_colind);
995+
mj_factorI(d->qH, d->qHDiagInv, nv, d->M_rownnz, d->M_rowadr, m->dof_simplenum, d->M_colind);
996996
}
997997

998998
// solve for qacc: (qM - dt*qDeriv) * qacc = qfrc
999999
mju_copy(qacc, qfrc, nv);
10001000
mj_solveLD(qacc, d->qH, d->qHDiagInv, nv, 1,
1001-
d->C_rownnz, d->C_rowadr, m->dof_simplenum, d->C_colind);
1001+
d->M_rownnz, d->M_rowadr, m->dof_simplenum, d->M_colind);
10021002

10031003
} else {
10041004
mjERROR("integrator must be implicit or implicitfast");

0 commit comments

Comments
 (0)