What exactly is qLD? #224
-
According to the API documentation I hope this is understandable, any help would be appreciated. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 1 reply
-
Both mj_fullM reconstructs the dense, // convert sparse inertia matrix M into full matrix
void mj_fullM(const mjModel* m, mjtNum* dst, const mjtNum* M) {
int i, j, adr = 0, nv = m->nv;
mju_zero(dst, nv*nv);
for (i=0; i<nv; i++) {
j = i;
while (j>=0) {
dst[i*nv+j] = M[adr];
dst[j*nv+i] = M[adr];
j = m->dof_parentid[j];
adr++;
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Yes, thank you. What I gather from this piece of code is that Maybe a little more concrete: how do qLD and qLDiagInv relate to qM (concerning dense nv x nv representations).
|
Beta Was this translation helpful? Give feedback.
-
Yes, M = np.zeros((nv, nv))
LD = np.zeros((nv, nv))
mujoco.mj_fullM(model, M, data.qM)
mujoco.mj_fullM(model, LD, data.qLD) Then for L = np.tril(LD, -1) + np.eye(nv)
D = np.diag(np.diag(LD)) we get L.T @ D @ L == M to numerical precision. The NB we have the upper triangle on the left and the lower triangle on the right, since this is zero-fill-in reverse Cholesky, what Featherstone calls "LTL", rather than the LDL you'll find in standard textbooks. |
Beta Was this translation helpful? Give feedback.
-
This is super informative, thanks @yuvaltassa ! |
Beta Was this translation helpful? Give feedback.
Yes,
LD
storage needs clarification. It is the lower triangle of the LDL factorisation with D replacing the unit diagonal.Using Python notation, if
Then for
we get
to numerical precision. The
qLDiagInv
andqLDiagSqrtInv
are there just to avoid taking roots and inverses during the solve, which is an important operation.NB we have the upper triangle on the left and the lower triangle on the right, since this is zero-fill-in reverse Cholesky, what Featherstone calls "LTL", rather than the LDL you'll…