Add nJmom, the number of non-zeros in sparse actuator_moment matrix, to mjModel.
PiperOrigin-RevId: 698343986 Change-Id: I3d4a4dea1ec095d4e7b231c2fffc0e6241cee39f
This commit is contained in:
committed by
Copybara-Service
parent
cd84011d7b
commit
aae5fd6906
@@ -263,8 +263,8 @@ struct mjData_ {
|
|||||||
mjtNum* actuator_length; // actuator lengths (nu x 1)
|
mjtNum* actuator_length; // actuator lengths (nu x 1)
|
||||||
int* moment_rownnz; // number of non-zeros in actuator_moment row (nu x 1)
|
int* moment_rownnz; // number of non-zeros in actuator_moment row (nu x 1)
|
||||||
int* moment_rowadr; // row start address in colind array (nu x 1)
|
int* moment_rowadr; // row start address in colind array (nu x 1)
|
||||||
int* moment_colind; // column indices in sparse Jacobian (nu x nv)
|
int* moment_colind; // column indices in sparse Jacobian (nJmom x 1)
|
||||||
mjtNum* actuator_moment; // actuator moments (nu x nv)
|
mjtNum* actuator_moment; // actuator moments (nJmom x 1)
|
||||||
|
|
||||||
// computed by mj_fwdPosition/mj_crb
|
// computed by mj_fwdPosition/mj_crb
|
||||||
mjtNum* crb; // com-based composite inertia and mass (nbody x 10)
|
mjtNum* crb; // com-based composite inertia and mass (nbody x 10)
|
||||||
@@ -956,6 +956,7 @@ struct mjModel_ {
|
|||||||
int nB; // number of non-zeros in sparse body-dof matrix
|
int nB; // number of non-zeros in sparse body-dof matrix
|
||||||
int nC; // number of non-zeros in sparse reduced dof-dof matrix
|
int nC; // number of non-zeros in sparse reduced dof-dof matrix
|
||||||
int nD; // number of non-zeros in sparse dof-dof matrix
|
int nD; // number of non-zeros in sparse dof-dof matrix
|
||||||
|
int nJmom; // number of non-zeros in sparse actuator_moment matrix
|
||||||
int ntree; // number of kinematic trees under world body
|
int ntree; // number of kinematic trees under world body
|
||||||
int ngravcomp; // number of bodies with nonzero gravcomp
|
int ngravcomp; // number of bodies with nonzero gravcomp
|
||||||
int nemax; // number of potential equality-constraint rows
|
int nemax; // number of potential equality-constraint rows
|
||||||
|
|||||||
@@ -291,8 +291,8 @@ struct mjData_ {
|
|||||||
mjtNum* actuator_length; // actuator lengths (nu x 1)
|
mjtNum* actuator_length; // actuator lengths (nu x 1)
|
||||||
int* moment_rownnz; // number of non-zeros in actuator_moment row (nu x 1)
|
int* moment_rownnz; // number of non-zeros in actuator_moment row (nu x 1)
|
||||||
int* moment_rowadr; // row start address in colind array (nu x 1)
|
int* moment_rowadr; // row start address in colind array (nu x 1)
|
||||||
int* moment_colind; // column indices in sparse Jacobian (nu x nv)
|
int* moment_colind; // column indices in sparse Jacobian (nJmom x 1)
|
||||||
mjtNum* actuator_moment; // actuator moments (nu x nv)
|
mjtNum* actuator_moment; // actuator moments (nJmom x 1)
|
||||||
|
|
||||||
// computed by mj_fwdPosition/mj_crb
|
// computed by mj_fwdPosition/mj_crb
|
||||||
mjtNum* crb; // com-based composite inertia and mass (nbody x 10)
|
mjtNum* crb; // com-based composite inertia and mass (nbody x 10)
|
||||||
|
|||||||
@@ -663,6 +663,7 @@ struct mjModel_ {
|
|||||||
int nB; // number of non-zeros in sparse body-dof matrix
|
int nB; // number of non-zeros in sparse body-dof matrix
|
||||||
int nC; // number of non-zeros in sparse reduced dof-dof matrix
|
int nC; // number of non-zeros in sparse reduced dof-dof matrix
|
||||||
int nD; // number of non-zeros in sparse dof-dof matrix
|
int nD; // number of non-zeros in sparse dof-dof matrix
|
||||||
|
int nJmom; // number of non-zeros in sparse actuator_moment matrix
|
||||||
int ntree; // number of kinematic trees under world body
|
int ntree; // number of kinematic trees under world body
|
||||||
int ngravcomp; // number of bodies with nonzero gravcomp
|
int ngravcomp; // number of bodies with nonzero gravcomp
|
||||||
int nemax; // number of potential equality-constraint rows
|
int nemax; // number of potential equality-constraint rows
|
||||||
|
|||||||
@@ -137,6 +137,7 @@
|
|||||||
X ( nB ) \
|
X ( nB ) \
|
||||||
X ( nC ) \
|
X ( nC ) \
|
||||||
X ( nD ) \
|
X ( nD ) \
|
||||||
|
X ( nJmom ) \
|
||||||
XMJV( ntree ) \
|
XMJV( ntree ) \
|
||||||
X ( ngravcomp ) \
|
X ( ngravcomp ) \
|
||||||
X ( nemax ) \
|
X ( nemax ) \
|
||||||
@@ -625,8 +626,8 @@
|
|||||||
X ( mjtNum, actuator_length, nu, 1 ) \
|
X ( mjtNum, actuator_length, nu, 1 ) \
|
||||||
X ( int, moment_rownnz, nu, 1 ) \
|
X ( int, moment_rownnz, nu, 1 ) \
|
||||||
X ( int, moment_rowadr, nu, 1 ) \
|
X ( int, moment_rowadr, nu, 1 ) \
|
||||||
X ( int, moment_colind, nu, MJ_M(nv) ) \
|
X ( int, moment_colind, nJmom, 1 ) \
|
||||||
X ( mjtNum, actuator_moment, nu, MJ_M(nv) ) \
|
X ( mjtNum, actuator_moment, nJmom, 1 ) \
|
||||||
X ( mjtNum, crb, nbody, 10 ) \
|
X ( mjtNum, crb, nbody, 10 ) \
|
||||||
X ( mjtNum, qM, nM, 1 ) \
|
X ( mjtNum, qM, nM, 1 ) \
|
||||||
X ( mjtNum, qLD, nM, 1 ) \
|
X ( mjtNum, qLD, nM, 1 ) \
|
||||||
|
|||||||
@@ -1178,6 +1178,11 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
|||||||
type=ValueType(name='int'),
|
type=ValueType(name='int'),
|
||||||
doc='number of non-zeros in sparse dof-dof matrix',
|
doc='number of non-zeros in sparse dof-dof matrix',
|
||||||
),
|
),
|
||||||
|
StructFieldDecl(
|
||||||
|
name='nJmom',
|
||||||
|
type=ValueType(name='int'),
|
||||||
|
doc='number of non-zeros in sparse actuator_moment matrix',
|
||||||
|
),
|
||||||
StructFieldDecl(
|
StructFieldDecl(
|
||||||
name='ntree',
|
name='ntree',
|
||||||
type=ValueType(name='int'),
|
type=ValueType(name='int'),
|
||||||
@@ -5166,7 +5171,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
|||||||
inner_type=ValueType(name='int'),
|
inner_type=ValueType(name='int'),
|
||||||
),
|
),
|
||||||
doc='column indices in sparse Jacobian',
|
doc='column indices in sparse Jacobian',
|
||||||
array_extent=('nu', 'nv'),
|
array_extent=('nJmom',),
|
||||||
),
|
),
|
||||||
StructFieldDecl(
|
StructFieldDecl(
|
||||||
name='actuator_moment',
|
name='actuator_moment',
|
||||||
@@ -5174,7 +5179,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
|||||||
inner_type=ValueType(name='mjtNum'),
|
inner_type=ValueType(name='mjtNum'),
|
||||||
),
|
),
|
||||||
doc='actuator moments',
|
doc='actuator moments',
|
||||||
array_extent=('nu', 'nv'),
|
array_extent=('nJmom',),
|
||||||
),
|
),
|
||||||
StructFieldDecl(
|
StructFieldDecl(
|
||||||
name='crb',
|
name='crb',
|
||||||
|
|||||||
+16
-15
@@ -276,7 +276,7 @@ def make_data(
|
|||||||
'actuator_length': (m.nu, float),
|
'actuator_length': (m.nu, float),
|
||||||
'moment_rownnz': (m.nu, jp.int32),
|
'moment_rownnz': (m.nu, jp.int32),
|
||||||
'moment_rowadr': (m.nu, jp.int32),
|
'moment_rowadr': (m.nu, jp.int32),
|
||||||
'moment_colind': (m.nu, m.nv, jp.int32),
|
'moment_colind': (m.nJmom, jp.int32),
|
||||||
'actuator_moment': (m.nu, m.nv, float),
|
'actuator_moment': (m.nu, m.nv, float),
|
||||||
'crb': (m.nbody, 10, float),
|
'crb': (m.nbody, 10, float),
|
||||||
'qM': (m.nM, float) if support.is_sparse(m) else (m.nv, m.nv, float),
|
'qM': (m.nM, float) if support.is_sparse(m) else (m.nv, m.nv, float),
|
||||||
@@ -431,22 +431,23 @@ def get_data_into(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# MuJoCo actuator_moment is sparse, MJX uses a dense representation.
|
# MuJoCo actuator_moment is sparse, MJX uses a dense representation.
|
||||||
if field.name == 'actuator_moment' and m.nu:
|
if field.name == 'actuator_moment':
|
||||||
moment_rownnz = np.zeros(m.nu, dtype=np.int32)
|
moment_rownnz = np.zeros(m.nu, dtype=np.int32)
|
||||||
moment_rowadr = np.zeros(m.nu, dtype=np.int32)
|
moment_rowadr = np.zeros(m.nu, dtype=np.int32)
|
||||||
moment_colind = np.zeros(m.nu * m.nv, dtype=np.int32)
|
moment_colind = np.zeros(m.nJmom, dtype=np.int32)
|
||||||
actuator_moment = np.zeros(m.nu * m.nv)
|
actuator_moment = np.zeros(m.nJmom)
|
||||||
mujoco.mju_dense2sparse(
|
if m.nu:
|
||||||
actuator_moment,
|
mujoco.mju_dense2sparse(
|
||||||
d.actuator_moment,
|
actuator_moment,
|
||||||
moment_rownnz,
|
d.actuator_moment,
|
||||||
moment_rowadr,
|
moment_rownnz,
|
||||||
moment_colind,
|
moment_rowadr,
|
||||||
)
|
moment_colind,
|
||||||
|
)
|
||||||
result_i.moment_rownnz[:] = moment_rownnz
|
result_i.moment_rownnz[:] = moment_rownnz
|
||||||
result_i.moment_rowadr[:] = moment_rowadr
|
result_i.moment_rowadr[:] = moment_rowadr
|
||||||
result_i.moment_colind[:] = moment_colind.reshape((m.nu, m.nv))
|
result_i.moment_colind[:] = moment_colind
|
||||||
result_i.actuator_moment[:] = actuator_moment.reshape((m.nu, m.nv))
|
result_i.actuator_moment[:] = actuator_moment
|
||||||
continue
|
continue
|
||||||
|
|
||||||
value = getattr(d_i, field.name)
|
value = getattr(d_i, field.name)
|
||||||
@@ -558,10 +559,10 @@ def put_data(
|
|||||||
moment = np.zeros((m.nu, m.nv))
|
moment = np.zeros((m.nu, m.nv))
|
||||||
mujoco.mju_sparse2dense(
|
mujoco.mju_sparse2dense(
|
||||||
moment,
|
moment,
|
||||||
d.actuator_moment.reshape(-1),
|
d.actuator_moment,
|
||||||
d.moment_rownnz,
|
d.moment_rownnz,
|
||||||
d.moment_rowadr,
|
d.moment_rowadr,
|
||||||
d.moment_colind.reshape(-1),
|
d.moment_colind,
|
||||||
)
|
)
|
||||||
fields['actuator_moment'] = moment
|
fields['actuator_moment'] = moment
|
||||||
|
|
||||||
|
|||||||
@@ -122,10 +122,10 @@ class SmoothTest(absltest.TestCase):
|
|||||||
moment = np.zeros((m.nu, m.nv))
|
moment = np.zeros((m.nu, m.nv))
|
||||||
mujoco.mju_sparse2dense(
|
mujoco.mju_sparse2dense(
|
||||||
moment,
|
moment,
|
||||||
d.actuator_moment.reshape(-1),
|
d.actuator_moment,
|
||||||
d.moment_rownnz,
|
d.moment_rownnz,
|
||||||
d.moment_rowadr,
|
d.moment_rowadr,
|
||||||
d.moment_colind.reshape(-1),
|
d.moment_colind,
|
||||||
)
|
)
|
||||||
_assert_eq(moment, dx.actuator_moment, 'actuator_moment')
|
_assert_eq(moment, dx.actuator_moment, 'actuator_moment')
|
||||||
|
|
||||||
@@ -193,10 +193,10 @@ class SmoothTest(absltest.TestCase):
|
|||||||
moment = np.zeros((m.nu, m.nv))
|
moment = np.zeros((m.nu, m.nv))
|
||||||
mujoco.mju_sparse2dense(
|
mujoco.mju_sparse2dense(
|
||||||
moment,
|
moment,
|
||||||
d.actuator_moment.reshape(-1),
|
d.actuator_moment,
|
||||||
d.moment_rownnz,
|
d.moment_rownnz,
|
||||||
d.moment_rowadr,
|
d.moment_rowadr,
|
||||||
d.moment_colind.reshape(-1),
|
d.moment_colind,
|
||||||
)
|
)
|
||||||
_assert_eq(moment, dx.actuator_moment, 'actuator_moment')
|
_assert_eq(moment, dx.actuator_moment, 'actuator_moment')
|
||||||
|
|
||||||
|
|||||||
@@ -536,6 +536,7 @@ class Model(PyTreeNode):
|
|||||||
nM: number of non-zeros in sparse inertia matrix
|
nM: number of non-zeros in sparse inertia matrix
|
||||||
nD: number of non-zeros in sparse dof-dof matrix
|
nD: number of non-zeros in sparse dof-dof matrix
|
||||||
nB: number of non-zeros in sparse body-dof matrix
|
nB: number of non-zeros in sparse body-dof matrix
|
||||||
|
nJmom: number of non-zeros in sparse actuator_moment matrix
|
||||||
ntree: number of kinematic trees under world body
|
ntree: number of kinematic trees under world body
|
||||||
ngravcomp: number of bodies with nonzero gravcomp
|
ngravcomp: number of bodies with nonzero gravcomp
|
||||||
nuserdata: size of userdata array
|
nuserdata: size of userdata array
|
||||||
@@ -855,6 +856,7 @@ class Model(PyTreeNode):
|
|||||||
nM: int # pylint:disable=invalid-name
|
nM: int # pylint:disable=invalid-name
|
||||||
nD: int # pylint:disable=invalid-name
|
nD: int # pylint:disable=invalid-name
|
||||||
nB: int # pylint:disable=invalid-name
|
nB: int # pylint:disable=invalid-name
|
||||||
|
nJmom: int
|
||||||
ntree: int = _restricted_to('mujoco')
|
ntree: int = _restricted_to('mujoco')
|
||||||
ngravcomp: int
|
ngravcomp: int
|
||||||
nuserdata: int
|
nuserdata: int
|
||||||
@@ -1236,8 +1238,8 @@ class Data(PyTreeNode):
|
|||||||
actuator_length: actuator lengths (nu,)
|
actuator_length: actuator lengths (nu,)
|
||||||
moment_rownnz: number of non-zeros in actuator_moment row (nu,)
|
moment_rownnz: number of non-zeros in actuator_moment row (nu,)
|
||||||
moment_rowadr: row start address in colind array (nu,)
|
moment_rowadr: row start address in colind array (nu,)
|
||||||
moment_colind: column indices in sparse Jacobian (nu, nv)
|
moment_colind: column indices in sparse Jacobian (nJmom,)
|
||||||
actuator_moment: actuator moments (nu, nv)
|
actuator_moment: actuator moments (nJmom,)
|
||||||
crb: com-based composite inertia and mass (nbody, 10)
|
crb: com-based composite inertia and mass (nbody, 10)
|
||||||
qM: total inertia if sparse: (nM,)
|
qM: total inertia if sparse: (nM,)
|
||||||
if dense: (nv, nv)
|
if dense: (nv, nv)
|
||||||
|
|||||||
@@ -76,10 +76,10 @@ class TransmissionIntegrationTest(parameterized.TestCase):
|
|||||||
moment = np.zeros((m.nu, m.nv))
|
moment = np.zeros((m.nu, m.nv))
|
||||||
mujoco.mju_sparse2dense(
|
mujoco.mju_sparse2dense(
|
||||||
moment,
|
moment,
|
||||||
d.actuator_moment.reshape(-1),
|
d.actuator_moment,
|
||||||
d.moment_rownnz,
|
d.moment_rownnz,
|
||||||
d.moment_rowadr,
|
d.moment_rowadr,
|
||||||
d.moment_colind.reshape(-1),
|
d.moment_colind,
|
||||||
)
|
)
|
||||||
_assert_eq(
|
_assert_eq(
|
||||||
moment,
|
moment,
|
||||||
|
|||||||
+10
-2
@@ -777,6 +777,7 @@ void mjCModel::Clear() {
|
|||||||
nM = 0;
|
nM = 0;
|
||||||
nD = 0;
|
nD = 0;
|
||||||
nB = 0;
|
nB = 0;
|
||||||
|
nJmom = 0;
|
||||||
njmax = -1;
|
njmax = -1;
|
||||||
nconmax = -1;
|
nconmax = -1;
|
||||||
nmocap = 0;
|
nmocap = 0;
|
||||||
@@ -2490,7 +2491,7 @@ void mjCModel::CopyTree(mjModel* m) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m->nC = nC = 2 * nOD + nv;
|
m->nC = nC = 2 * nOD + nv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy plugin data
|
// copy plugin data
|
||||||
@@ -4156,6 +4157,13 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
|
|||||||
// copy objects outsite kinematic tree (including keyframes)
|
// copy objects outsite kinematic tree (including keyframes)
|
||||||
CopyObjects(m);
|
CopyObjects(m);
|
||||||
|
|
||||||
|
// compute nJmom
|
||||||
|
for (int i = 0; i < nu; i++) {
|
||||||
|
// dense rows
|
||||||
|
nJmom += nv;
|
||||||
|
}
|
||||||
|
m->nJmom = nJmom;
|
||||||
|
|
||||||
// scale mass
|
// scale mass
|
||||||
if (compiler.settotalmass>0) {
|
if (compiler.settotalmass>0) {
|
||||||
mj_setTotalmass(m, compiler.settotalmass);
|
mj_setTotalmass(m, compiler.settotalmass);
|
||||||
@@ -4292,7 +4300,7 @@ bool mjCModel::CopyBack(const mjModel* m) {
|
|||||||
neq!=m->neq || ntendon!=m->ntendon || nwrap!=m->nwrap || nsensor!=m->nsensor ||
|
neq!=m->neq || ntendon!=m->ntendon || nwrap!=m->nwrap || nsensor!=m->nsensor ||
|
||||||
nnumeric!=m->nnumeric || nnumericdata!=m->nnumericdata || ntext!=m->ntext ||
|
nnumeric!=m->nnumeric || nnumericdata!=m->nnumericdata || ntext!=m->ntext ||
|
||||||
ntextdata!=m->ntextdata || nnames!=m->nnames || nM!=m->nM || nD!=m->nD || nC!=m->nC ||
|
ntextdata!=m->ntextdata || nnames!=m->nnames || nM!=m->nM || nD!=m->nD || nC!=m->nC ||
|
||||||
nB!=m->nB || nemax!=m->nemax || nconmax!=m->nconmax || njmax!=m->njmax ||
|
nB!=m->nB || nJmom!=m->nJmom ||nemax!=m->nemax || nconmax!=m->nconmax || njmax!=m->njmax ||
|
||||||
npaths!=m->npaths) {
|
npaths!=m->npaths) {
|
||||||
errInfo = mjCError(0, "incompatible models in CopyBack");
|
errInfo = mjCError(0, "incompatible models in CopyBack");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ class mjCModel_ : public mjsElement {
|
|||||||
int nB; // number of non-zeros in sparse body-dof matrix
|
int nB; // number of non-zeros in sparse body-dof matrix
|
||||||
int nC; // number of non-zeros in reduced sparse dof-dof matrix
|
int nC; // number of non-zeros in reduced sparse dof-dof matrix
|
||||||
int nD; // number of non-zeros in sparse dof-dof matrix
|
int nD; // number of non-zeros in sparse dof-dof matrix
|
||||||
|
int nJmom; // number of non-zeros in sparse actuator_moment matrix
|
||||||
|
|
||||||
// statistics, as computed by mj_setConst
|
// statistics, as computed by mj_setConst
|
||||||
double meaninertia_auto; // mean diagonal inertia, as computed by mj_setConst
|
double meaninertia_auto; // mean diagonal inertia, as computed by mj_setConst
|
||||||
|
|||||||
@@ -116,6 +116,30 @@ TEST_F(UserCModelTest, SameFrame) {
|
|||||||
mj_deleteModel(model);
|
mj_deleteModel(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UserCModelTest, ActuatorSparsity) {
|
||||||
|
static constexpr char xml[] = R"(
|
||||||
|
<mujoco>
|
||||||
|
<worldbody>
|
||||||
|
<body>
|
||||||
|
<geom size="1"/>
|
||||||
|
<joint name="a"/>
|
||||||
|
<body>
|
||||||
|
<geom size="1"/>
|
||||||
|
<joint name="b"/>
|
||||||
|
</body>
|
||||||
|
</body>
|
||||||
|
</worldbody>
|
||||||
|
<actuator>
|
||||||
|
<motor joint="a"/>
|
||||||
|
<motor joint="b"/>
|
||||||
|
</actuator>
|
||||||
|
</mujoco>
|
||||||
|
)";
|
||||||
|
mjModel* m = LoadModelFromString(xml);
|
||||||
|
ASSERT_EQ(m->nJmom, 4);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------- test automatic inference of nuser_xxx -------------------------
|
// ------------- test automatic inference of nuser_xxx -------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -5244,6 +5244,7 @@ public unsafe struct mjModel_ {
|
|||||||
public int nB;
|
public int nB;
|
||||||
public int nC;
|
public int nC;
|
||||||
public int nD;
|
public int nD;
|
||||||
|
public int nJmom;
|
||||||
public int ntree;
|
public int ntree;
|
||||||
public int ngravcomp;
|
public int ngravcomp;
|
||||||
public int nemax;
|
public int nemax;
|
||||||
|
|||||||
Reference in New Issue
Block a user