Introduce private header engine_inline.h exploiting restrict and avoiding loops and copies in some commonly used utility functions.

PiperOrigin-RevId: 843635464
Change-Id: I3b0553eea98424ccc7def77e3769e2994f3e9014
This commit is contained in:
Yuval Tassa
2025-12-12 04:48:21 -08:00
committed by Copybara-Service
parent a0a56065e0
commit 600f0f20bc
11 changed files with 964 additions and 487 deletions
+113 -107
View File
@@ -23,6 +23,7 @@
#include "engine/engine_core_constraint.h"
#include "engine/engine_core_util.h"
#include "engine/engine_crossplatform.h"
#include "engine/engine_inline.h"
#include "engine/engine_macro.h"
#include "engine/engine_memory.h"
#include "engine/engine_sleep.h"
@@ -67,13 +68,13 @@ void mj_kinematics1(const mjModel* m, mjData* d) {
int qadr = m->jnt_qposadr[jntadr];
// copy pos and quat from qpos
mju_copy3(xpos, d->qpos+qadr);
mju_copy4(xquat, d->qpos+qadr+3);
mji_copy3(xpos, d->qpos+qadr);
mji_copy4(xquat, d->qpos+qadr+3);
mju_normalize4(xquat);
// assign xanchor and xaxis
mju_copy3(d->xanchor+3*jntadr, xpos);
mju_copy3(d->xaxis+3*jntadr, m->jnt_axis+3*jntadr);
mji_copy3(d->xanchor+3*jntadr, xpos);
mji_copy3(d->xaxis+3*jntadr, m->jnt_axis+3*jntadr);
}
// regular or no joint
@@ -84,7 +85,7 @@ void mj_kinematics1(const mjModel* m, mjData* d) {
mjtNum *bodypos, *bodyquat, quat[4];
if (m->body_mocapid[i] >= 0) {
bodypos = d->mocap_pos + 3*m->body_mocapid[i];
mju_copy4(quat, d->mocap_quat + 4*m->body_mocapid[i]);
mji_copy4(quat, d->mocap_quat + 4*m->body_mocapid[i]);
mju_normalize4(quat);
bodyquat = quat;
} else {
@@ -94,13 +95,13 @@ void mj_kinematics1(const mjModel* m, mjData* d) {
// apply fixed translation and rotation relative to parent
if (pid) {
mju_mulMatVec3(xpos, d->xmat+9*pid, bodypos);
mju_addTo3(xpos, d->xpos+3*pid);
mju_mulQuat(xquat, d->xquat+4*pid, bodyquat);
mji_mulMatVec3(xpos, d->xmat+9*pid, bodypos);
mji_addTo3(xpos, d->xpos+3*pid);
mji_mulQuat(xquat, d->xquat+4*pid, bodyquat);
} else {
// parent is the world
mju_copy3(xpos, bodypos);
mju_copy4(xquat, bodyquat);
mji_copy3(xpos, bodypos);
mji_copy4(xquat, bodyquat);
}
// accumulate joints, compute xpos and xquat for this body
@@ -112,16 +113,16 @@ void mj_kinematics1(const mjModel* m, mjData* d) {
mjtJoint jtype = m->jnt_type[jid];
// compute axis in global frame; ball jnt_axis is (0,0,1), set by compiler
mju_rotVecQuat(xaxis, m->jnt_axis+3*jid, xquat);
mji_rotVecQuat(xaxis, m->jnt_axis+3*jid, xquat);
// compute anchor in global frame
mju_rotVecQuat(xanchor, m->jnt_pos+3*jid, xquat);
mju_addTo3(xanchor, xpos);
mji_rotVecQuat(xanchor, m->jnt_pos+3*jid, xquat);
mji_addTo3(xanchor, xpos);
// apply joint transformation
switch (jtype) {
case mjJNT_SLIDE:
mju_addToScl3(xpos, xaxis, d->qpos[qadr] - m->qpos0[qadr]);
mji_addToScl3(xpos, xaxis, d->qpos[qadr] - m->qpos0[qadr]);
break;
case mjJNT_BALL:
@@ -130,10 +131,10 @@ void mj_kinematics1(const mjModel* m, mjData* d) {
// compute local quaternion rotation
mjtNum qloc[4];
if (jtype == mjJNT_BALL) {
mju_copy4(qloc, d->qpos+qadr);
mji_copy4(qloc, d->qpos+qadr);
mju_normalize4(qloc);
} else {
mju_axisAngle2Quat(qloc, m->jnt_axis+3*jid, d->qpos[qadr] - m->qpos0[qadr]);
mji_axisAngle2Quat(qloc, m->jnt_axis+3*jid, d->qpos[qadr] - m->qpos0[qadr]);
}
// apply rotation
@@ -141,8 +142,8 @@ void mj_kinematics1(const mjModel* m, mjData* d) {
// correct for off-center rotation
mjtNum vec[3];
mju_rotVecQuat(vec, m->jnt_pos+3*jid, xquat);
mju_sub3(xpos, xanchor, vec);
mji_rotVecQuat(vec, m->jnt_pos+3*jid, xquat);
mji_sub3(xpos, xanchor, vec);
}
break;
@@ -151,8 +152,8 @@ void mj_kinematics1(const mjModel* m, mjData* d) {
}
// assign xanchor and xaxis
mju_copy3(d->xanchor+3*jid, xanchor);
mju_copy3(d->xaxis+3*jid, xaxis);
mji_copy3(d->xanchor+3*jid, xanchor);
mji_copy3(d->xaxis+3*jid, xaxis);
}
}
@@ -179,8 +180,8 @@ void mj_kinematics1(const mjModel* m, mjData* d) {
}
// assign xquat and xpos, construct xmat
mju_copy4(d->xquat+4*i, xquat);
mju_copy3(d->xpos+3*i, xpos);
mji_copy4(d->xquat+4*i, xquat);
mji_copy3(d->xpos+3*i, xpos);
mju_quat2Mat(d->xmat+9*i, xquat);
}
}
@@ -251,7 +252,7 @@ void mj_comPos(const mjModel* m, mjData* d) {
for (int b=0; b < nbody; b++) {
int i = sleep_filter ? d->body_awake_ind[b] : b;
mju_scl3(d->subtree_com+3*i, d->xipos+3*i, m->body_mass[i]);
mji_scl3(d->subtree_com+3*i, d->xipos+3*i, m->body_mass[i]);
}
// subtree_com: accumulate to parent in backward pass
@@ -263,10 +264,10 @@ void mj_comPos(const mjModel* m, mjData* d) {
int parent = m->body_parentid[i];
if (sleep_filter && d->body_awake[i] == mjS_ASLEEP) {
mjtNum child_moment[3];
mju_scl3(child_moment, d->subtree_com+3*i, m->body_subtreemass[i]);
mju_addTo3(d->subtree_com+3*parent, child_moment);
mji_scl3(child_moment, d->subtree_com+3*i, m->body_subtreemass[i]);
mji_addTo3(d->subtree_com+3*parent, child_moment);
} else {
mju_addTo3(d->subtree_com+3*parent, d->subtree_com+3*i);
mji_addTo3(d->subtree_com+3*parent, d->subtree_com+3*i);
}
}
@@ -275,9 +276,10 @@ void mj_comPos(const mjModel* m, mjData* d) {
int i = sleep_filter ? d->body_awake_ind[b] : b;
if (m->body_subtreemass[i] < mjMINVAL) {
mju_copy3(d->subtree_com+3*i, d->xipos+3*i);
mji_copy3(d->subtree_com+3*i, d->xipos+3*i);
} else {
mju_scl3(d->subtree_com+3*i, d->subtree_com+3*i, 1.0/m->body_subtreemass[i]);
mju_scl3(d->subtree_com + 3 * i, d->subtree_com + 3 * i,
1.0 / m->body_subtreemass[i]);
}
}
@@ -289,7 +291,7 @@ void mj_comPos(const mjModel* m, mjData* d) {
int i = sleep_filter ? d->body_awake_ind[b] : b;
mjtNum offset[3];
mju_sub3(offset, d->xipos+3*i, d->subtree_com+3*m->body_rootid[i]);
mji_sub3(offset, d->xipos+3*i, d->subtree_com+3*m->body_rootid[i]);
mju_inertCom(d->cinert+10*i, m->body_inertia+3*i, d->ximat+9*i, offset, m->body_mass[i]);
}
@@ -308,7 +310,7 @@ void mj_comPos(const mjModel* m, mjData* d) {
// compute com-anchor vector
mjtNum offset[3], axis[3];
mju_sub3(offset, d->subtree_com+3*m->body_rootid[i], d->xanchor+3*j);
mji_sub3(offset, d->subtree_com+3*m->body_rootid[i], d->xanchor+3*j);
// create motion dof
int skip = 0;
@@ -377,16 +379,16 @@ void mj_camlight(const mjModel* m, mjData* d) {
case mjCAMLIGHT_TRACK:
case mjCAMLIGHT_TRACKCOM:
// fixed global orientation
mju_copy9(d->cam_xmat+9*i, m->cam_mat0+9*i);
mji_copy9(d->cam_xmat+9*i, m->cam_mat0+9*i);
// position: track camera body
if (m->cam_mode[i] == mjCAMLIGHT_TRACK) {
mju_add3(d->cam_xpos+3*i, d->xpos+3*id, m->cam_pos0+3*i);
mji_add3(d->cam_xpos+3*i, d->xpos+3*id, m->cam_pos0+3*i);
}
// position: track subtree com
else {
mju_add3(d->cam_xpos+3*i, d->subtree_com+3*id, m->cam_poscom0+3*i);
mji_add3(d->cam_xpos+3*i, d->subtree_com+3*id, m->cam_poscom0+3*i);
}
break;
@@ -397,25 +399,25 @@ void mj_camlight(const mjModel* m, mjData* d) {
mjtNum pos[3];
// get position to look at
if (m->cam_mode[i] == mjCAMLIGHT_TARGETBODY) {
mju_copy3(pos, d->xpos+3*id1);
mji_copy3(pos, d->xpos+3*id1);
} else {
mju_copy3(pos, d->subtree_com+3*id1);
mji_copy3(pos, d->subtree_com+3*id1);
}
// zaxis = -desired camera direction, in global frame
mjtNum matT[9];
mju_sub3(matT+6, d->cam_xpos+3*i, pos);
mji_sub3(matT+6, d->cam_xpos+3*i, pos);
mju_normalize3(matT+6);
// xaxis: orthogonal to zaxis and to (0,0,1)
matT[3] = 0;
matT[4] = 0;
matT[5] = 1;
mju_cross(matT, matT+3, matT+6);
mji_cross(matT, matT+3, matT+6);
mju_normalize3(matT);
// yaxis: orthogonal to xaxis and zaxis
mju_cross(matT+3, matT+6, matT);
mji_cross(matT+3, matT+6, matT);
mju_normalize3(matT+3);
// set camera frame
@@ -439,7 +441,7 @@ void mj_camlight(const mjModel* m, mjData* d) {
// default processing for fixed mode
mj_local2Global(d, d->light_xpos+3*i, 0, m->light_pos+3*i, 0, id, 0);
mju_rotVecQuat(d->light_xdir+3*i, m->light_dir+3*i, d->xquat+4*id);
mji_rotVecQuat(d->light_xdir+3*i, m->light_dir+3*i, d->xquat+4*id);
// adjust for mode
switch ((mjtCamLight) m->light_mode[i]) {
@@ -448,16 +450,16 @@ void mj_camlight(const mjModel* m, mjData* d) {
case mjCAMLIGHT_TRACK:
case mjCAMLIGHT_TRACKCOM:
// fixed global orientation
mju_copy3(d->light_xdir+3*i, m->light_dir0+3*i);
mji_copy3(d->light_xdir+3*i, m->light_dir0+3*i);
// position: track light body
if (m->light_mode[i] == mjCAMLIGHT_TRACK) {
mju_add3(d->light_xpos+3*i, d->xpos+3*id, m->light_pos0+3*i);
mji_add3(d->light_xpos+3*i, d->xpos+3*id, m->light_pos0+3*i);
}
// position: track subtree com
else {
mju_add3(d->light_xpos+3*i, d->subtree_com+3*id, m->light_poscom0+3*i);
mji_add3(d->light_xpos+3*i, d->subtree_com+3*id, m->light_poscom0+3*i);
}
break;
@@ -468,13 +470,13 @@ void mj_camlight(const mjModel* m, mjData* d) {
// get position to look at
mjtNum lookat[3];
if (m->light_mode[i] == mjCAMLIGHT_TARGETBODY) {
mju_copy3(lookat, d->xpos+3*id1);
mji_copy3(lookat, d->xpos+3*id1);
} else {
mju_copy3(lookat, d->subtree_com+3*id1);
mji_copy3(lookat, d->subtree_com+3*id1);
}
// set dir
mju_sub3(d->light_xdir+3*i, lookat, d->light_xpos+3*i);
mji_sub3(d->light_xdir+3*i, lookat, d->light_xpos+3*i);
}
}
@@ -554,15 +556,15 @@ void mj_flex(const mjModel* m, mjData* d) {
// centered: copy body position
if (m->flex_centered[f]) {
for (int i=vstart; i < vend; i++) {
mju_copy3(d->flexvert_xpos+3*i, d->xpos+3*m->flex_vertbodyid[i]);
mji_copy3(d->flexvert_xpos+3*i, d->xpos+3*m->flex_vertbodyid[i]);
}
}
// non-centered: map from local to global
else {
for (int i=vstart; i < vend; i++) {
mju_mulMatVec3(d->flexvert_xpos+3*i, d->xmat+9*m->flex_vertbodyid[i], m->flex_vert+3*i);
mju_addTo3(d->flexvert_xpos+3*i, d->xpos+3*m->flex_vertbodyid[i]);
mji_mulMatVec3(d->flexvert_xpos+3*i, d->xmat+9*m->flex_vertbodyid[i], m->flex_vert+3*i);
mji_addTo3(d->flexvert_xpos+3*i, d->xpos+3*m->flex_vertbodyid[i]);
}
}
}
@@ -572,13 +574,13 @@ void mj_flex(const mjModel* m, mjData* d) {
mjtNum nodexpos[3*mjMAXFLEXNODES];
if (m->flex_centered[f]) {
for (int i=nstart; i < nend; i++) {
mju_copy3(nodexpos + 3*(i-nstart), d->xpos + 3*m->flex_nodebodyid[i]);
mji_copy3(nodexpos + 3*(i-nstart), d->xpos + 3*m->flex_nodebodyid[i]);
}
} else {
for (int i=nstart; i < nend; i++) {
int j = i - nstart;
mju_mulMatVec3(nodexpos + 3*j, d->xmat + 9*m->flex_nodebodyid[i], m->flex_node + 3*i);
mju_addTo3(nodexpos + 3*j, d->xpos + 3*m->flex_nodebodyid[i]);
mji_mulMatVec3(nodexpos + 3*j, d->xmat + 9*m->flex_nodebodyid[i], m->flex_node + 3*i);
mji_addTo3(nodexpos + 3*j, d->xpos + 3*m->flex_nodebodyid[i]);
}
}
@@ -606,8 +608,8 @@ void mj_flex(const mjModel* m, mjData* d) {
// compute min and max along each global axis
mjtNum xmin[3], xmax[3];
mju_copy3(xmin, vert+3*edata[0]);
mju_copy3(xmax, vert+3*edata[0]);
mji_copy3(xmin, vert+3*edata[0]);
mji_copy3(xmax, vert+3*edata[0]);
for (int i=1; i <= dim; i++) {
for (int j=0; j < 3; j++) {
mjtNum value = vert[3*edata[i]+j];
@@ -637,8 +639,8 @@ void mj_flex(const mjModel* m, mjData* d) {
// copy element aabbs to bhv leaf aabbs
for (int i=flex_bvhadr; i < flex_bvhadr+flex_bvhnum; i++) {
if (m->bvh_nodeid[i] >= 0) {
mju_copy(d->bvh_aabb_dyn + 6*(i - m->nbvhstatic),
d->flexelem_aabb + 6*(m->flex_elemadr[f] + m->bvh_nodeid[i]), 6);
mji_copy6(d->bvh_aabb_dyn + 6*(i - m->nbvhstatic),
d->flexelem_aabb + 6*(m->flex_elemadr[f] + m->bvh_nodeid[i]));
}
}
@@ -689,7 +691,7 @@ void mj_flex(const mjModel* m, mjData* d) {
// vec = unit vector from v1 to v2, compute edge length
mjtNum vec[3];
mju_sub3(vec, pos2, pos1);
mji_sub3(vec, pos2, pos1);
d->flexedge_length[ebase+e] = mju_normalize3(vec);
// skip Jacobian if not needed
@@ -851,7 +853,7 @@ void mj_tendon(const mjModel* m, mjData* d) {
mjtNum wlen = -1;
int wrapid = -1;
mjtNum wpnt[12];
mju_copy3(wpnt, d->site_xpos+3*id0);
mji_copy3(wpnt, d->site_xpos+3*id0);
int wbody[4];
wbody[0] = m->site_bodyid[id0];
@@ -878,11 +880,11 @@ void mj_tendon(const mjModel* m, mjData* d) {
// complete sequence, accumulate lengths
if (wlen < 0) {
mju_copy3(wpnt+3, d->site_xpos+3*id1);
mji_copy3(wpnt+3, d->site_xpos+3*id1);
wbody[1] = m->site_bodyid[id1];
L[i] += mju_dist3(wpnt, wpnt+3) / divisor;
} else {
mju_copy3(wpnt+9, d->site_xpos+3*id1);
mji_copy3(wpnt+9, d->site_xpos+3*id1);
wbody[1] = wbody[2] = m->geom_bodyid[wrapid];
wbody[3] = m->site_bodyid[id1];
L[i] += (mju_dist3(wpnt, wpnt+3) + wlen + mju_dist3(wpnt+6, wpnt+9)) / divisor;
@@ -893,7 +895,7 @@ void mj_tendon(const mjModel* m, mjData* d) {
if (wbody[k] != wbody[k+1]) {
// get 3D position difference, normalize
mjtNum dif[3];
mju_sub3(dif, wpnt+3*k+3, wpnt+3*k);
mji_sub3(dif, wpnt+3*k+3, wpnt+3*k);
mju_normalize3(dif);
// sparse
@@ -934,7 +936,11 @@ void mj_tendon(const mjModel* m, mjData* d) {
}
// assign to wrap
mju_copy(d->wrap_xpos+wrapcount*3, wpnt, (wlen < 0 ? 3 : 9));
if (wlen < 0) {
mji_copy3(d->wrap_xpos+wrapcount*3, wpnt);
} else {
mji_copy9(d->wrap_xpos+wrapcount*3, wpnt);
}
d->wrap_obj[wrapcount] = -1;
if (wlen >= 0) {
d->wrap_obj[wrapcount+1] = d->wrap_obj[wrapcount+2] = wrapid;
@@ -947,7 +953,7 @@ void mj_tendon(const mjModel* m, mjData* d) {
// assign last site before pulley or tendon end
if (j == tendon_num-1 || m->wrap_type[adr+j+1] == mjWRAP_PULLEY) {
mju_copy3(d->wrap_xpos+wrapcount*3, d->site_xpos+3*id1);
mji_copy3(d->wrap_xpos+wrapcount*3, d->site_xpos+3*id1);
d->wrap_obj[wrapcount] = -1;
d->ten_wrapnum[i]++;
wrapcount++;
@@ -1009,7 +1015,7 @@ void mj_tendonDot(const mjModel* m, mjData* d, int id, mjtNum* Jdot) {
// init sequence; assume it starts with site
mjtNum wpnt[6];
mju_copy3(wpnt, d->site_xpos+3*id0);
mji_copy3(wpnt, d->site_xpos+3*id0);
mjtNum vel[6];
mj_objectVelocity(m, d, mjOBJ_SITE, id0, vel, /*flg_local=*/0);
mjtNum wvel[6] = {vel[3], vel[4], vel[5], 0, 0, 0};
@@ -1026,9 +1032,9 @@ void mj_tendonDot(const mjModel* m, mjData* d, int id, mjtNum* Jdot) {
// complete sequence
wbody[1] = m->site_bodyid[id1];
mju_copy3(wpnt+3, d->site_xpos+3*id1);
mji_copy3(wpnt+3, d->site_xpos+3*id1);
mj_objectVelocity(m, d, mjOBJ_SITE, id1, vel, /*flg_local=*/0);
mju_copy3(wvel+3, vel+3);
mji_copy3(wvel+3, vel+3);
// accumulate moments if consecutive points are in different bodies
if (wbody[0] != wbody[1]) {
@@ -1144,17 +1150,17 @@ void mj_transmission(const mjModel* m, mjData* d) {
else if (m->jnt_type[id] == mjJNT_BALL) {
// axis: expmap representation of quaternion
mjtNum axis[3], quat[4];
mju_copy4(quat, d->qpos+m->jnt_qposadr[id]);
mji_copy4(quat, d->qpos+m->jnt_qposadr[id]);
mju_normalize4(quat);
mju_quat2Vel(axis, quat, 1);
mji_quat2Vel(axis, quat, 1);
// gearAxis: rotate to parent frame if necessary
mjtNum gearAxis[3];
if (m->actuator_trntype[i] == mjTRN_JOINT) {
mju_copy3(gearAxis, gear);
mji_copy3(gearAxis, gear);
} else {
mju_negQuat(quat, quat);
mju_rotVecQuat(gearAxis, gear, quat);
mji_negQuat(quat, quat);
mji_rotVecQuat(gearAxis, gear, quat);
}
// length: axis*gearAxis
@@ -1170,7 +1176,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
rownnz[i] = 3;
// moment: gearAxis
mju_copy3(moment+adr, gearAxis);
mji_copy3(moment+adr, gearAxis);
}
// free joint: 6D wrench gear
@@ -1181,13 +1187,13 @@ void mj_transmission(const mjModel* m, mjData* d) {
// gearAxis: rotate to world frame if necessary
mjtNum gearAxis[3];
if (m->actuator_trntype[i] == mjTRN_JOINT) {
mju_copy3(gearAxis, gear+3);
mji_copy3(gearAxis, gear+3);
} else {
mjtNum quat[4];
mju_copy4(quat, d->qpos+m->jnt_qposadr[id]+3);
mji_copy4(quat, d->qpos+m->jnt_qposadr[id]+3);
mju_normalize4(quat);
mju_negQuat(quat, quat);
mju_rotVecQuat(gearAxis, gear+3, quat);
mji_rotVecQuat(gearAxis, gear+3, quat);
}
// dof start address
@@ -1200,8 +1206,8 @@ void mj_transmission(const mjModel* m, mjData* d) {
rownnz[i] = 6;
// moment: gear(tran), gearAxis
mju_copy3(moment+adr, gear);
mju_copy3(moment+adr+3, gearAxis);
mji_copy3(moment+adr, gear);
mji_copy3(moment+adr+3, gearAxis);
}
break;
@@ -1235,12 +1241,12 @@ void mj_transmission(const mjModel* m, mjData* d) {
if (ok) {
mju_scl3(dldv, axis, 1-av/sdet);
mju_scl3(dlda, vec, 1/sdet); // use dlda as temp
mju_addTo3(dldv, dlda);
mji_addTo3(dldv, dlda);
mju_scl3(dlda, vec, 1-av/sdet);
} else {
mju_copy3(dlda, vec);
mju_copy3(dldv, axis);
mji_copy3(dlda, vec);
mji_copy3(dldv, axis);
}
// get Jacobians of axis(jacA) and vec(jac)
@@ -1317,8 +1323,8 @@ void mj_transmission(const mjModel* m, mjData* d) {
if (m->actuator_trnid[2*i+1] == -1) {
// wrench: gear expressed in global frame
mjtNum wrench[6];
mju_mulMatVec3(wrench, d->site_xmat+9*id, gear); // translation
mju_mulMatVec3(wrench+3, d->site_xmat+9*id, gear+3); // rotation
mji_mulMatVec3(wrench, d->site_xmat+9*id, gear); // translation
mji_mulMatVec3(wrench+3, d->site_xmat+9*id, gear+3); // rotation
// moment: global Jacobian projected on wrench
mju_mulMatTVec(moment+adr, jac, wrench, 3, nv); // translation
@@ -1389,7 +1395,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
// wrench: translational gear expressed in global frame
mjtNum wrench[6];
mju_mulMatVec3(wrench, d->site_xmat+9*refid, gear);
mji_mulMatVec3(wrench, d->site_xmat+9*refid, gear);
// moment: global Jacobian projected on wrench
mju_mulMatTVec(moment+adr, jac, wrench, 3, nv);
@@ -1401,12 +1407,12 @@ void mj_transmission(const mjModel* m, mjData* d) {
// get site and refsite quats from parent bodies (avoiding mju_mat2Quat)
mjtNum quat[4];
mju_mulQuat(quat, m->site_quat+4*id, d->xquat+4*m->site_bodyid[id]);
mju_mulQuat(refquat, m->site_quat+4*refid, d->xquat+4*m->site_bodyid[refid]);
mji_mulQuat(quat, m->site_quat+4*id, d->xquat+4*m->site_bodyid[id]);
mji_mulQuat(refquat, m->site_quat+4*refid, d->xquat+4*m->site_bodyid[refid]);
// convert difference to expmap (axis-angle)
mjtNum vec[3];
mju_subQuat(vec, quat, refquat);
mji_subQuat(vec, quat, refquat);
// add length: dot product with gear
length[i] += mju_dot3(vec, gear+3);
@@ -1428,7 +1434,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
// wrench: rotational gear expressed in global frame
mjtNum wrench[6];
mju_mulMatVec3(wrench, d->site_xmat+9*refid, gear+3);
mji_mulMatVec3(wrench, d->site_xmat+9*refid, gear+3);
// moment_tmp: global Jacobian projected on wrench, add to moment
if (!moment_tmp) moment_tmp = mjSTACKALLOC(d, nv, mjtNum);
@@ -1711,7 +1717,7 @@ void mj_crb(const mjModel* m, mjData* d) {
// sparse backward pass over ancestors
for (int j=i; j >= 0; j = dof_parentid[j]) {
// M(i,j) += cdof_j * (crb_body_i * cdof_i)
M[Madr_ij--] += mju_dot(cdof+6*j, buf, 6);
M[Madr_ij--] += mji_dot6(cdof+6*j, buf);
}
}
}
@@ -2119,7 +2125,7 @@ void mj_comVel(const mjModel* m, mjData* d) {
// cvel = cvel_parent
mjtNum cvel[6];
mju_copy(cvel, d->cvel+6*m->body_parentid[i], 6);
mji_copy6(cvel, d->cvel+6*m->body_parentid[i]);
// cvel = cvel_parent + cdof * qvel, cdofdot = cvel x cdof
int dofnum = m->body_dofnum[i];
@@ -2144,9 +2150,9 @@ void mj_comVel(const mjModel* m, mjData* d) {
case mjJNT_BALL:
// compute all 3 cdofdots using parent velocity
mju_crossMotion(cdofdot+6*(j+0), cvel, d->cdof+6*(bda+j+0));
mju_crossMotion(cdofdot+6*(j+1), cvel, d->cdof+6*(bda+j+1));
mju_crossMotion(cdofdot+6*(j+2), cvel, d->cdof+6*(bda+j+2));
mji_crossMotion(cdofdot+6*(j+0), cvel, d->cdof+6*(bda+j+0));
mji_crossMotion(cdofdot+6*(j+1), cvel, d->cdof+6*(bda+j+1));
mji_crossMotion(cdofdot+6*(j+2), cvel, d->cdof+6*(bda+j+2));
// update velocity
mju_mulDofVec(tmp, d->cdof+6*(bda+j), d->qvel+bda+j, 3);
@@ -2160,7 +2166,7 @@ void mj_comVel(const mjModel* m, mjData* d) {
// in principle we should use the new velocity to compute cdofdot,
// but it makes no difference because crossMotion(cdof, cdof) = 0,
// and using the old velocity may be more accurate numerically
mju_crossMotion(cdofdot+6*j, cvel, d->cdof+6*(bda+j));
mji_crossMotion(cdofdot+6*j, cvel, d->cdof+6*(bda+j));
// update velocity
mju_mulDofVec(tmp, d->cdof+6*(bda+j), d->qvel+bda+j, 1);
@@ -2169,7 +2175,7 @@ void mj_comVel(const mjModel* m, mjData* d) {
}
// assign cvel, cdofdot
mju_copy(d->cvel+6*i, cvel, 6);
mji_copy6(d->cvel+6*i, cvel);
mju_copy(d->cdof_dot+6*bda, cdofdot, 6*dofnum);
}
}
@@ -2199,7 +2205,7 @@ void mj_subtreeVel(const mjModel* m, mjData* d) {
dv[0] *= m->body_inertia[3*i];
dv[1] *= m->body_inertia[3*i+1];
dv[2] *= m->body_inertia[3*i+2];
mju_mulMatVec3(d->subtree_angmom+3*i, d->ximat+9*i, dv);
mji_mulMatVec3(d->subtree_angmom+3*i, d->ximat+9*i, dv);
}
// subtree linear velocity
@@ -2208,7 +2214,7 @@ void mj_subtreeVel(const mjModel* m, mjData* d) {
// non-world: add linear momentum to parent
if (i) {
mju_addTo3(d->subtree_linvel+3*m->body_parentid[i], d->subtree_linvel+3*i);
mji_addTo3(d->subtree_linvel+3*m->body_parentid[i], d->subtree_linvel+3*i);
}
// convert linear momentum to linear velocity
@@ -2227,22 +2233,22 @@ void mj_subtreeVel(const mjModel* m, mjData* d) {
mju_sub3(dx, d->xipos+3*i, d->subtree_com+3*i);
mju_sub3(dv, body_vel+6*i+3, d->subtree_linvel+3*i);
mju_scl3(dp, dv, m->body_mass[i]);
mju_cross(dL, dx, dp);
mji_cross(dL, dx, dp);
// add to subtree i
mju_addTo3(d->subtree_angmom+3*i, dL);
mji_addTo3(d->subtree_angmom+3*i, dL);
// add to parent
mju_addTo3(d->subtree_angmom+3*parent, d->subtree_angmom+3*i);
mji_addTo3(d->subtree_angmom+3*parent, d->subtree_angmom+3*i);
// momentum wrt parent
mju_sub3(dx, d->subtree_com+3*i, d->subtree_com+3*parent);
mju_sub3(dv, d->subtree_linvel+3*i, d->subtree_linvel+3*parent);
mju_scl3(dv, dv, m->body_subtreemass[i]);
mju_cross(dL, dx, dv);
mji_cross(dL, dx, dv);
// add to parent
mju_addTo3(d->subtree_angmom+3*parent, dL);
mji_addTo3(d->subtree_angmom+3*parent, dL);
}
mj_freeStack(d);
@@ -2290,7 +2296,7 @@ void mj_rne(const mjModel* m, mjData* d, int flg_acc, mjtNum* result) {
mju_mulInertVec(loc_cfrc_body+6*i, d->cinert+10*i, loc_cacc+6*i);
mju_mulInertVec(tmp, d->cinert+10*i, d->cvel+6*i);
mjtNum tmp1[6];
mju_crossForce(tmp1, d->cvel+6*i, tmp);
mji_crossForce(tmp1, d->cvel+6*i, tmp);
mju_addTo(loc_cfrc_body+6*i, tmp1, 6);
}
@@ -2310,7 +2316,7 @@ void mj_rne(const mjModel* m, mjData* d, int flg_acc, mjtNum* result) {
// result = cdof * cfrc_body
for (int v=0; v < nv; v++) {
int i = sleep_filter ? d->dof_awake_ind[v] : v;
result[i] = mju_dot(d->cdof+6*i, loc_cfrc_body+6*m->dof_bodyid[i], 6);
result[i] = mji_dot6(d->cdof+6*i, loc_cfrc_body+6*m->dof_bodyid[i]);
}
mj_freeStack(d);
@@ -2334,8 +2340,8 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
for (int i=1; i < nbody; i++) {
if (!mju_isZero(d->xfrc_applied+6*i, 6)) {
// rearrange as torque:force
mju_copy3(cfrc, d->xfrc_applied+6*i+3);
mju_copy3(cfrc+3, d->xfrc_applied+6*i);
mji_copy3(cfrc, d->xfrc_applied+6*i+3);
mji_copy3(cfrc+3, d->xfrc_applied+6*i);
// map force from application point to com; both world-oriented
mju_transformSpatial(cfrc_com, cfrc, 1, d->subtree_com+3*m->body_rootid[i], d->xipos+3*i, 0);
@@ -2403,9 +2409,9 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
case mjEQ_CONNECT:
case mjEQ_WELD:
// cfrc = world-oriented torque:force vector
mju_copy3(cfrc + 3, d->efc_force + i);
mji_copy3(cfrc + 3, d->efc_force + i);
if (m->eq_type[id] == mjEQ_WELD) {
mju_copy3(cfrc, d->efc_force + i + 3);
mji_copy3(cfrc, d->efc_force + i + 3);
} else {
mju_zero3(cfrc); // no torque from connect
}
@@ -2490,7 +2496,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
// cfrc_body = cinert * cacc + cvel x (cinert * cvel)
mju_mulInertVec(cfrc_body, d->cinert+10*j, d->cacc+6*j);
mju_mulInertVec(cfrc_corr, d->cinert+10*j, d->cvel+6*j);
mju_crossForce(cfrc, d->cvel+6*j, cfrc_corr);
mji_crossForce(cfrc, d->cvel+6*j, cfrc_corr);
mju_addTo(cfrc_body, cfrc, 6);
// set cfrc_int = cfrc_body - cfrc_ext