Add spaces around comparison operators in engine source files.
PiperOrigin-RevId: 535989348 Change-Id: I883f7e82351299933c49b35a31842b5d8d6aea04
This commit is contained in:
committed by
Copybara-Service
parent
d40c395917
commit
455b1cd2e2
@@ -21,11 +21,11 @@
|
|||||||
mjfGeneric mjcb_passive = 0;
|
mjfGeneric mjcb_passive = 0;
|
||||||
mjfGeneric mjcb_control = 0;
|
mjfGeneric mjcb_control = 0;
|
||||||
mjfConFilt mjcb_contactfilter = 0;
|
mjfConFilt mjcb_contactfilter = 0;
|
||||||
mjfSensor mjcb_sensor = 0;
|
mjfSensor mjcb_sensor = 0;
|
||||||
mjfTime mjcb_time = 0;
|
mjfTime mjcb_time = 0;
|
||||||
mjfAct mjcb_act_bias = 0;
|
mjfAct mjcb_act_bias = 0;
|
||||||
mjfAct mjcb_act_gain = 0;
|
mjfAct mjcb_act_gain = 0;
|
||||||
mjfAct mjcb_act_dyn = 0;
|
mjfAct mjcb_act_dyn = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -73,13 +73,13 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
|
|
||||||
case mjGEOM_ELLIPSOID:
|
case mjGEOM_ELLIPSOID:
|
||||||
// find support point on unit sphere: scale dir by ellipsoid sizes and renormalize
|
// find support point on unit sphere: scale dir by ellipsoid sizes and renormalize
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
res[i] = dir[i] * size[i];
|
res[i] = dir[i] * size[i];
|
||||||
}
|
}
|
||||||
mju_normalize3(res);
|
mju_normalize3(res);
|
||||||
|
|
||||||
// transform to ellipsoid
|
// transform to ellipsoid
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
res[i] *= size[i];
|
res[i] *= size[i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -87,7 +87,7 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
case mjGEOM_CYLINDER:
|
case mjGEOM_CYLINDER:
|
||||||
// set result in XY plane: support on circle
|
// set result in XY plane: support on circle
|
||||||
tmp = mju_sqrt(dir[0]*dir[0] + dir[1]*dir[1]);
|
tmp = mju_sqrt(dir[0]*dir[0] + dir[1]*dir[1]);
|
||||||
if (tmp>mjMINVAL) {
|
if (tmp > mjMINVAL) {
|
||||||
res[0] = dir[0]/tmp*size[0];
|
res[0] = dir[0]/tmp*size[0];
|
||||||
res[1] = dir[1]/tmp*size[0];
|
res[1] = dir[1]/tmp*size[0];
|
||||||
} else {
|
} else {
|
||||||
@@ -99,7 +99,7 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case mjGEOM_BOX:
|
case mjGEOM_BOX:
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
res[i] = mju_sign(dir[i]) * size[i];
|
res[i] = mju_sign(dir[i]) * size[i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -111,16 +111,16 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
ibest = -1;
|
ibest = -1;
|
||||||
|
|
||||||
// no graph data: exhaustive search
|
// no graph data: exhaustive search
|
||||||
if (m->mesh_graphadr[m->geom_dataid[g]]<0) {
|
if (m->mesh_graphadr[m->geom_dataid[g]] < 0) {
|
||||||
// search all vertices, find best
|
// search all vertices, find best
|
||||||
for (int i=0; i<m->mesh_vertnum[m->geom_dataid[g]]; i++) {
|
for (int i=0; i < m->mesh_vertnum[m->geom_dataid[g]]; i++) {
|
||||||
// vdot = dot(vertex, dir)
|
// vdot = dot(vertex, dir)
|
||||||
vdot = dir[0] * (mjtNum)vertdata[3*i] +
|
vdot = dir[0] * (mjtNum)vertdata[3*i] +
|
||||||
dir[1] * (mjtNum)vertdata[3*i+1] +
|
dir[1] * (mjtNum)vertdata[3*i+1] +
|
||||||
dir[2] * (mjtNum)vertdata[3*i+2];
|
dir[2] * (mjtNum)vertdata[3*i+2];
|
||||||
|
|
||||||
// update best
|
// update best
|
||||||
if (vdot>tmp) {
|
if (vdot > tmp) {
|
||||||
tmp = vdot;
|
tmp = vdot;
|
||||||
ibest = i;
|
ibest = i;
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
dir[2] * (mjtNum)vertdata[3*vert_globalid[locid]+2];
|
dir[2] * (mjtNum)vertdata[3*vert_globalid[locid]+2];
|
||||||
|
|
||||||
// update best
|
// update best
|
||||||
if (vdot>tmp) {
|
if (vdot > tmp) {
|
||||||
tmp = vdot;
|
tmp = vdot;
|
||||||
ibest = locid;
|
ibest = locid;
|
||||||
change = 1;
|
change = 1;
|
||||||
@@ -177,14 +177,14 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sanity check, SHOULD NOT OCCUR
|
// sanity check, SHOULD NOT OCCUR
|
||||||
if (ibest<0) {
|
if (ibest < 0) {
|
||||||
mju_warning("mesh_support could not find support vertex");
|
mju_warning("mesh_support could not find support vertex");
|
||||||
mju_zero3(res);
|
mju_zero3(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy best vertex
|
// copy best vertex
|
||||||
else {
|
else {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
res[i] = (mjtNum)vertdata[3*ibest + i];
|
res[i] = (mjtNum)vertdata[3*ibest + i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add dir*margin/2 to result
|
// add dir*margin/2 to result
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
res[i] += dir[i] * ccd->margin/2;
|
res[i] += dir[i] * ccd->margin/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +214,7 @@ static int mjc_MPRIteration(mjtCCD* obj1, mjtCCD* obj2, const ccd_t* ccd,
|
|||||||
mjContact* con, int g1, int g2, mjtNum margin) {
|
mjContact* con, int g1, int g2, mjtNum margin) {
|
||||||
ccd_vec3_t dir, pos;
|
ccd_vec3_t dir, pos;
|
||||||
ccd_real_t depth;
|
ccd_real_t depth;
|
||||||
if (ccdMPRPenetration(obj1, obj2, ccd, &depth, &dir, &pos)==0) {
|
if (ccdMPRPenetration(obj1, obj2, ccd, &depth, &dir, &pos) == 0) {
|
||||||
// contact is found but normal is undefined
|
// contact is found but normal is undefined
|
||||||
if (ccdVec3Eq(&dir, ccd_vec3_origin)) {
|
if (ccdVec3Eq(&dir, ccd_vec3_origin)) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -242,7 +242,7 @@ static int mjc_MPRIteration(mjtCCD* obj1, mjtCCD* obj2, const ccd_t* ccd,
|
|||||||
|
|
||||||
// compare new contact to previous contacts, return 1 if it is far from all of them
|
// compare new contact to previous contacts, return 1 if it is far from all of them
|
||||||
static int mjc_isDistinctContact(mjContact* con, int ncon, mjtNum tolerance) {
|
static int mjc_isDistinctContact(mjContact* con, int ncon, mjtNum tolerance) {
|
||||||
for (int i=0; i<ncon-1; i++) {
|
for (int i=0; i < ncon-1; i++) {
|
||||||
if (mju_dist3(con[i].pos, con[ncon - 1].pos) <= tolerance) {
|
if (mju_dist3(con[i].pos, con[ncon - 1].pos) <= tolerance) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -380,7 +380,7 @@ static int addplanemesh(mjContact* con, const float vertex[3],
|
|||||||
mju_addTo3(pnt, pos2);
|
mju_addTo3(pnt, pos2);
|
||||||
|
|
||||||
// skip if too close to first contact
|
// skip if too close to first contact
|
||||||
if (mju_dist3(pnt, first)<tolplanemesh*rbound) {
|
if (mju_dist3(pnt, first) < tolplanemesh*rbound) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,7 +419,7 @@ int mjc_PlaneConvex(const mjModel* m, const mjData* d,
|
|||||||
// compute normal distance, return if too far
|
// compute normal distance, return if too far
|
||||||
mju_sub3(dif, vec.v, pos1);
|
mju_sub3(dif, vec.v, pos1);
|
||||||
dist = mju_dot3(normal, dif);
|
dist = mju_dot3(normal, dif);
|
||||||
if (dist>margin) {
|
if (dist > margin) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,16 +454,16 @@ int mjc_PlaneConvex(const mjModel* m, const mjData* d,
|
|||||||
mjtNum threshold = mju_dot3(normal, dif) - margin;
|
mjtNum threshold = mju_dot3(normal, dif) - margin;
|
||||||
|
|
||||||
// no graph data: exhaustive search
|
// no graph data: exhaustive search
|
||||||
if (m->mesh_graphadr[m->geom_dataid[g]]<0) {
|
if (m->mesh_graphadr[m->geom_dataid[g]] < 0) {
|
||||||
// search all vertices, find best
|
// search all vertices, find best
|
||||||
for (int i=0; i<m->mesh_vertnum[m->geom_dataid[g]] && count<maxplanemesh; i++) {
|
for (int i=0; i < m->mesh_vertnum[m->geom_dataid[g]] && count < maxplanemesh; i++) {
|
||||||
// vdot = dot(vertex, dir)
|
// vdot = dot(vertex, dir)
|
||||||
vdot = locdir[0] * (mjtNum)vertdata[3*i] +
|
vdot = locdir[0] * (mjtNum)vertdata[3*i] +
|
||||||
locdir[1] * (mjtNum)vertdata[3*i+1] +
|
locdir[1] * (mjtNum)vertdata[3*i+1] +
|
||||||
locdir[2] * (mjtNum)vertdata[3*i+2];
|
locdir[2] * (mjtNum)vertdata[3*i+2];
|
||||||
|
|
||||||
// detect contact, skip best
|
// detect contact, skip best
|
||||||
if (vdot>threshold && i!=obj.meshindex) {
|
if (vdot > threshold && i != obj.meshindex) {
|
||||||
count += addplanemesh(con+count, vertdata+3*i,
|
count += addplanemesh(con+count, vertdata+3*i,
|
||||||
pos1, normal, pos2, mat2,
|
pos1, normal, pos2, mat2,
|
||||||
con->pos, m->geom_rbound[g2]);
|
con->pos, m->geom_rbound[g2]);
|
||||||
@@ -472,7 +472,7 @@ int mjc_PlaneConvex(const mjModel* m, const mjData* d,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use graph data
|
// use graph data
|
||||||
else if (obj.meshindex>=0) {
|
else if (obj.meshindex >= 0) {
|
||||||
// get info
|
// get info
|
||||||
graphadr = m->mesh_graphadr[m->geom_dataid[g]];
|
graphadr = m->mesh_graphadr[m->geom_dataid[g]];
|
||||||
numvert = m->mesh_graph[graphadr];
|
numvert = m->mesh_graph[graphadr];
|
||||||
@@ -482,14 +482,14 @@ int mjc_PlaneConvex(const mjModel* m, const mjData* d,
|
|||||||
|
|
||||||
// look for contacts in ibest neighborhood
|
// look for contacts in ibest neighborhood
|
||||||
int i = vert_edgeadr[obj.meshindex];
|
int i = vert_edgeadr[obj.meshindex];
|
||||||
while ((locid=edge_localid[i])>=0 && count<maxplanemesh) {
|
while ((locid=edge_localid[i]) >= 0 && count < maxplanemesh) {
|
||||||
// vdot = dot(vertex, dir)
|
// vdot = dot(vertex, dir)
|
||||||
vdot = locdir[0] * (mjtNum)vertdata[3*vert_globalid[locid]] +
|
vdot = locdir[0] * (mjtNum)vertdata[3*vert_globalid[locid]] +
|
||||||
locdir[1] * (mjtNum)vertdata[3*vert_globalid[locid]+1] +
|
locdir[1] * (mjtNum)vertdata[3*vert_globalid[locid]+1] +
|
||||||
locdir[2] * (mjtNum)vertdata[3*vert_globalid[locid]+2];
|
locdir[2] * (mjtNum)vertdata[3*vert_globalid[locid]+2];
|
||||||
|
|
||||||
// detect contact
|
// detect contact
|
||||||
if (vdot>threshold) {
|
if (vdot > threshold) {
|
||||||
count += addplanemesh(con+count, vertdata+3*vert_globalid[locid],
|
count += addplanemesh(con+count, vertdata+3*vert_globalid[locid],
|
||||||
pos1, normal, pos2, mat2,
|
pos1, normal, pos2, mat2,
|
||||||
con->pos, m->geom_rbound[g2]);
|
con->pos, m->geom_rbound[g2]);
|
||||||
@@ -522,10 +522,10 @@ static void prism_support(const void *obj, const ccd_vec3_t *dir, ccd_vec3_t *ve
|
|||||||
const mjtPrism* p = (const mjtPrism*)obj;
|
const mjtPrism* p = (const mjtPrism*)obj;
|
||||||
|
|
||||||
// find best vertex in halfspace determined by dir.z
|
// find best vertex in halfspace determined by dir.z
|
||||||
istart = dir->v[2]<0 ? 0 : 3;
|
istart = dir->v[2] < 0 ? 0 : 3;
|
||||||
ibest = istart;
|
ibest = istart;
|
||||||
best = mju_dot3(p->v[istart], dir->v);
|
best = mju_dot3(p->v[istart], dir->v);
|
||||||
for (int i=istart+1; i<istart+3; i++) {
|
for (int i=istart+1; i < istart+3; i++) {
|
||||||
if ((tmp = mju_dot3(p->v[i], dir->v)) > best) {
|
if ((tmp = mju_dot3(p->v[i], dir->v)) > best) {
|
||||||
ibest = i;
|
ibest = i;
|
||||||
best = tmp;
|
best = tmp;
|
||||||
@@ -543,7 +543,7 @@ static void prism_center(const void *obj, ccd_vec3_t *center) {
|
|||||||
|
|
||||||
// compute mean
|
// compute mean
|
||||||
mju_zero3(center->v);
|
mju_zero3(center->v);
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i < 6; i++) {
|
||||||
mju_addTo3(center->v, p->v[i]);
|
mju_addTo3(center->v, p->v[i]);
|
||||||
}
|
}
|
||||||
mju_scl3(center->v, center->v, 1.0/6.0);
|
mju_scl3(center->v, center->v, 1.0/6.0);
|
||||||
@@ -607,7 +607,7 @@ int mjc_ConvexHField(const mjModel* m, const mjData* d,
|
|||||||
r2 = m->geom_rbound[g2];
|
r2 = m->geom_rbound[g2];
|
||||||
|
|
||||||
// box-sphere test: horizontal plane
|
// box-sphere test: horizontal plane
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
if ((size1[i] < pos[i]-r2-margin) || (-size1[i] > pos[i]+r2+margin)) {
|
if ((size1[i] < pos[i]-r2-margin) || (-size1[i] > pos[i]+r2+margin)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -710,23 +710,23 @@ int mjc_ConvexHField(const mjModel* m, const mjData* d,
|
|||||||
|
|
||||||
// process all prisms in sub-grid
|
// process all prisms in sub-grid
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
for (int r=rmin; r<rmax; r++) {
|
for (int r=rmin; r < rmax; r++) {
|
||||||
nvert = 0;
|
nvert = 0;
|
||||||
for (int c=cmin; c<=cmax; c++) {
|
for (int c=cmin; c <= cmax; c++) {
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
// send vertex to prism constructor
|
// send vertex to prism constructor
|
||||||
addVert(&nvert, &prism, dx*c-size1[0], dy*(r+dr[i])-size1[1],
|
addVert(&nvert, &prism, dx*c-size1[0], dy*(r+dr[i])-size1[1],
|
||||||
data[(r+dr[i])*ncol+c]*size1[2]+margin);
|
data[(r+dr[i])*ncol+c]*size1[2]+margin);
|
||||||
|
|
||||||
// check for enough vertices
|
// check for enough vertices
|
||||||
if (nvert>2) {
|
if (nvert > 2) {
|
||||||
// prism height test
|
// prism height test
|
||||||
if (prism.v[3][2]<zmin && prism.v[4][2]<zmin && prism.v[5][2]<zmin) {
|
if (prism.v[3][2] < zmin && prism.v[4][2] < zmin && prism.v[5][2] < zmin) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// run MPR, save contact
|
// run MPR, save contact
|
||||||
if (ccdMPRPenetration(&prism, &obj, &ccd, &depth, &dirccd, &vecccd)==0 &&
|
if (ccdMPRPenetration(&prism, &obj, &ccd, &depth, &dirccd, &vecccd) == 0 &&
|
||||||
!ccdVec3Eq(&dirccd, ccd_vec3_origin)) {
|
!ccdVec3Eq(&dirccd, ccd_vec3_origin)) {
|
||||||
// fill in contact data, transform to global coordinates
|
// fill in contact data, transform to global coordinates
|
||||||
con[cnt].dist = -depth;
|
con[cnt].dist = -depth;
|
||||||
@@ -737,7 +737,7 @@ int mjc_ConvexHField(const mjModel* m, const mjData* d,
|
|||||||
|
|
||||||
// count, stop if max number reached
|
// count, stop if max number reached
|
||||||
cnt++;
|
cnt++;
|
||||||
if (cnt>=mjMAXCONPAIR) {
|
if (cnt >= mjMAXCONPAIR) {
|
||||||
r = rmax+1;
|
r = rmax+1;
|
||||||
c = cmax+1;
|
c = cmax+1;
|
||||||
i = 3;
|
i = 3;
|
||||||
@@ -754,7 +754,7 @@ int mjc_ConvexHField(const mjModel* m, const mjData* d,
|
|||||||
mju_copy3(pos2, savepos2);
|
mju_copy3(pos2, savepos2);
|
||||||
|
|
||||||
// fix contact normals
|
// fix contact normals
|
||||||
for (int i=0; i<cnt; i++) {
|
for (int i=0; i < cnt; i++) {
|
||||||
mjc_fixNormal(m, d, con+i, g1, g2);
|
mjc_fixNormal(m, d, con+i, g1, g2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,7 +774,7 @@ static int mjc_ellipsoidInside(mjtNum nrm[3], const mjtNum pos[3], const mjtNum
|
|||||||
// precompute quantities
|
// precompute quantities
|
||||||
mjtNum S2inv[3] = {1/(size[0]*size[0]), 1/(size[1]*size[1]), 1/(size[2]*size[2])};
|
mjtNum S2inv[3] = {1/(size[0]*size[0]), 1/(size[1]*size[1]), 1/(size[2]*size[2])};
|
||||||
mjtNum C = pos[0]*pos[0]*S2inv[0] + pos[1]*pos[1]*S2inv[1] + pos[2]*pos[2]*S2inv[2] - 1;
|
mjtNum C = pos[0]*pos[0]*S2inv[0] + pos[1]*pos[1]*S2inv[1] + pos[2]*pos[2]*S2inv[2] - 1;
|
||||||
if (C>0) {
|
if (C > 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,19 +783,19 @@ static int mjc_ellipsoidInside(mjtNum nrm[3], const mjtNum pos[3], const mjtNum
|
|||||||
|
|
||||||
// main iteration
|
// main iteration
|
||||||
int iter;
|
int iter;
|
||||||
for (iter=0; iter<maxiter; iter++) {
|
for (iter=0; iter < maxiter; iter++) {
|
||||||
// coefficients and determinant of quadratic
|
// coefficients and determinant of quadratic
|
||||||
mjtNum A = nrm[0]*nrm[0]*S2inv[0] + nrm[1]*nrm[1]*S2inv[1] + nrm[2]*nrm[2]*S2inv[2];
|
mjtNum A = nrm[0]*nrm[0]*S2inv[0] + nrm[1]*nrm[1]*S2inv[1] + nrm[2]*nrm[2]*S2inv[2];
|
||||||
mjtNum B = pos[0]*nrm[0]*S2inv[0] + pos[1]*nrm[1]*S2inv[1] + pos[2]*nrm[2]*S2inv[2];
|
mjtNum B = pos[0]*nrm[0]*S2inv[0] + pos[1]*nrm[1]*S2inv[1] + pos[2]*nrm[2]*S2inv[2];
|
||||||
mjtNum det = B*B - A*C;
|
mjtNum det = B*B - A*C;
|
||||||
if (det<mjMINVAL || A<mjMINVAL) {
|
if (det < mjMINVAL || A < mjMINVAL) {
|
||||||
return (iter>0);
|
return (iter > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ray intersection with ellipse: pos + x*nrm, x>=0
|
// ray intersection with ellipse: pos + x*nrm, x>=0
|
||||||
mjtNum x = (-B + mju_sqrt(det))/A;
|
mjtNum x = (-B + mju_sqrt(det))/A;
|
||||||
if (x<0) {
|
if (x < 0) {
|
||||||
return (iter>0);
|
return (iter > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// new point on ellipsoid
|
// new point on ellipsoid
|
||||||
@@ -811,7 +811,7 @@ static int mjc_ellipsoidInside(mjtNum nrm[3], const mjtNum pos[3], const mjtNum
|
|||||||
mju_copy3(nrm, newnrm);
|
mju_copy3(nrm, newnrm);
|
||||||
|
|
||||||
// terminate if converged
|
// terminate if converged
|
||||||
if (change<tolerance) {
|
if (change < tolerance) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -834,25 +834,25 @@ static int mjc_ellipsoidOutside(mjtNum nrm[3], const mjtNum pos[3], const mjtNum
|
|||||||
// main iteration
|
// main iteration
|
||||||
mjtNum la = 0;
|
mjtNum la = 0;
|
||||||
int iter;
|
int iter;
|
||||||
for (iter=0; iter<maxiter; iter++) {
|
for (iter=0; iter < maxiter; iter++) {
|
||||||
// precompute 1/(s^2+la)
|
// precompute 1/(s^2+la)
|
||||||
mjtNum R[3] = {1/(S2[0]+la), 1/(S2[1]+la), 1/(S2[2]+la)};
|
mjtNum R[3] = {1/(S2[0]+la), 1/(S2[1]+la), 1/(S2[2]+la)};
|
||||||
|
|
||||||
// value
|
// value
|
||||||
mjtNum val = PS2[0]*R[0]*R[0] + PS2[1]*R[1]*R[1] + PS2[2]*R[2]*R[2] - 1;
|
mjtNum val = PS2[0]*R[0]*R[0] + PS2[1]*R[1]*R[1] + PS2[2]*R[2]*R[2] - 1;
|
||||||
if (val<tolerance) {
|
if (val < tolerance) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// derivative
|
// derivative
|
||||||
mjtNum deriv = -2*(PS2[0]*R[0]*R[0]*R[0] + PS2[1]*R[1]*R[1]*R[1] + PS2[2]*R[2]*R[2]*R[2]);
|
mjtNum deriv = -2*(PS2[0]*R[0]*R[0]*R[0] + PS2[1]*R[1]*R[1]*R[1] + PS2[2]*R[2]*R[2]*R[2]);
|
||||||
if (deriv>-mjMINVAL) {
|
if (deriv > -mjMINVAL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// delta
|
// delta
|
||||||
mjtNum delta = -val/deriv;
|
mjtNum delta = -val/deriv;
|
||||||
if (delta<tolerance) {
|
if (delta < tolerance) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,20 +878,20 @@ void mjc_fixNormal(const mjModel* m, const mjData* d, mjContact* con, int g1, in
|
|||||||
// get geom ids and types
|
// get geom ids and types
|
||||||
int gid[2] = {g1, g2};
|
int gid[2] = {g1, g2};
|
||||||
int type[2];
|
int type[2];
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
type[i] = m->geom_type[gid[i]];
|
type[i] = m->geom_type[gid[i]];
|
||||||
|
|
||||||
// set to -1 if type cannot be processed
|
// set to -1 if type cannot be processed
|
||||||
if (type[i]!=mjGEOM_SPHERE &&
|
if (type[i] != mjGEOM_SPHERE &&
|
||||||
type[i]!=mjGEOM_CAPSULE &&
|
type[i] != mjGEOM_CAPSULE &&
|
||||||
type[i]!=mjGEOM_ELLIPSOID &&
|
type[i] != mjGEOM_ELLIPSOID &&
|
||||||
type[i]!=mjGEOM_CYLINDER) {
|
type[i] != mjGEOM_CYLINDER) {
|
||||||
type[i] = -1;
|
type[i] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// neither type can be processed: nothing to do
|
// neither type can be processed: nothing to do
|
||||||
if (type[0]<0 && type[1]<0) {
|
if (type[0] < 0 && type[1] < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -903,8 +903,8 @@ void mjc_fixNormal(const mjModel* m, const mjData* d, mjContact* con, int g1, in
|
|||||||
|
|
||||||
// process geoms in type range
|
// process geoms in type range
|
||||||
int processed[2] = {0, 0};
|
int processed[2] = {0, 0};
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
if (type[i]>=0) {
|
if (type[i] >= 0) {
|
||||||
// get geom mat and size
|
// get geom mat and size
|
||||||
mjtNum* mat = d->geom_xmat + 9*gid[i];
|
mjtNum* mat = d->geom_xmat + 9*gid[i];
|
||||||
mjtNum* size = m->geom_size + 3*gid[i];
|
mjtNum* size = m->geom_size + 3*gid[i];
|
||||||
@@ -924,12 +924,12 @@ void mjc_fixNormal(const mjModel* m, const mjData* d, mjContact* con, int g1, in
|
|||||||
|
|
||||||
case mjGEOM_CAPSULE:
|
case mjGEOM_CAPSULE:
|
||||||
// Z: bottom cap
|
// Z: bottom cap
|
||||||
if (pos[2]<-size[1]) {
|
if (pos[2] < -size[1]) {
|
||||||
nrm[2] = pos[2]+size[1];
|
nrm[2] = pos[2]+size[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Z: top cap
|
// Z: top cap
|
||||||
else if (pos[2]>size[1]) {
|
else if (pos[2] > size[1]) {
|
||||||
nrm[2] = pos[2]-size[1];
|
nrm[2] = pos[2]-size[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -946,7 +946,7 @@ void mjc_fixNormal(const mjModel* m, const mjData* d, mjContact* con, int g1, in
|
|||||||
|
|
||||||
case mjGEOM_ELLIPSOID:
|
case mjGEOM_ELLIPSOID:
|
||||||
// guard against invalid ellipsoid size (just in case)
|
// guard against invalid ellipsoid size (just in case)
|
||||||
if (size[0]<mjMINVAL || size[1]<mjMINVAL || size[2]<mjMINVAL) {
|
if (size[0] < mjMINVAL || size[1] < mjMINVAL || size[2] < mjMINVAL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -956,7 +956,7 @@ void mjc_fixNormal(const mjModel* m, const mjData* d, mjContact* con, int g1, in
|
|||||||
pos[2]*pos[2]/(size[2]*size[2]);
|
pos[2]*pos[2]/(size[2]*size[2]);
|
||||||
|
|
||||||
// dispatch to inside or outside solver
|
// dispatch to inside or outside solver
|
||||||
if (dst1<=1) {
|
if (dst1 <= 1) {
|
||||||
processed[i] = mjc_ellipsoidInside(nrm, pos, size);
|
processed[i] = mjc_ellipsoidInside(nrm, pos, size);
|
||||||
} else {
|
} else {
|
||||||
processed[i] = mjc_ellipsoidOutside(nrm, pos, size);
|
processed[i] = mjc_ellipsoidOutside(nrm, pos, size);
|
||||||
@@ -965,7 +965,7 @@ void mjc_fixNormal(const mjModel* m, const mjData* d, mjContact* con, int g1, in
|
|||||||
|
|
||||||
case mjGEOM_CYLINDER:
|
case mjGEOM_CYLINDER:
|
||||||
// skip if within 5% length of flat wall
|
// skip if within 5% length of flat wall
|
||||||
if (mju_abs(pos[2])>0.95*size[1]) {
|
if (mju_abs(pos[2]) > 0.95*size[1]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -974,7 +974,7 @@ void mjc_fixNormal(const mjModel* m, const mjData* d, mjContact* con, int g1, in
|
|||||||
dst2 = mju_abs(size[0]-mju_norm(pos, 2));
|
dst2 = mju_abs(size[0]-mju_norm(pos, 2));
|
||||||
|
|
||||||
// require 4x closer to round than flat wall
|
// require 4x closer to round than flat wall
|
||||||
if (dst1<0.25*dst2) {
|
if (dst1 < 0.25*dst2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ static inline mjtNum squaredDist3(const mjtNum pos1[3], const mjtNum pos2[3]) {
|
|||||||
// bounding-sphere collision
|
// bounding-sphere collision
|
||||||
static int mj_collideSphere(const mjModel* m, mjData* d, int g1, int g2, mjtNum margin) {
|
static int mj_collideSphere(const mjModel* m, mjData* d, int g1, int g2, mjtNum margin) {
|
||||||
// neither geom is a plane
|
// neither geom is a plane
|
||||||
if (m->geom_rbound[g1]>0 && m->geom_rbound[g2]>0) {
|
if (m->geom_rbound[g1] > 0 && m->geom_rbound[g2] > 0) {
|
||||||
mjtNum bound = m->geom_rbound[g1] + m->geom_rbound[g2] + margin;
|
mjtNum bound = m->geom_rbound[g1] + m->geom_rbound[g2] + margin;
|
||||||
if (squaredDist3(d->geom_xpos+3*g1, d->geom_xpos+3*g2) > bound*bound) {
|
if (squaredDist3(d->geom_xpos+3*g1, d->geom_xpos+3*g2) > bound*bound) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -76,13 +76,13 @@ static int mj_collideSphere(const mjModel* m, mjData* d, int g1, int g2, mjtNum
|
|||||||
}
|
}
|
||||||
|
|
||||||
// one geom is a plane
|
// one geom is a plane
|
||||||
if (m->geom_type[g1]==mjGEOM_PLANE && m->geom_rbound[g2]>0
|
if (m->geom_type[g1] == mjGEOM_PLANE && m->geom_rbound[g2] > 0
|
||||||
&& plane_geom(m, d, g1, g2) > margin+m->geom_rbound[g2]) {
|
&& plane_geom(m, d, g1, g2) > margin+m->geom_rbound[g2]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (m->geom_type[g2]==mjGEOM_PLANE && m->geom_rbound[g1]>0
|
if (m->geom_type[g2] == mjGEOM_PLANE && m->geom_rbound[g1] > 0
|
||||||
&& plane_geom(m, d, g2, g1) > margin+m->geom_rbound[g1]) {
|
&& plane_geom(m, d, g2, g1) > margin+m->geom_rbound[g1]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -97,9 +97,9 @@ void mj_collidePair(const mjModel* m, mjData* d, int g1, int g2, int merged,
|
|||||||
if (merged) {
|
if (merged) {
|
||||||
// find matching pair
|
// find matching pair
|
||||||
int found = 0;
|
int found = 0;
|
||||||
for (int k=startadr; k<pairadr; k++) {
|
for (int k=startadr; k < pairadr; k++) {
|
||||||
if ((m->pair_geom1[k]==g1 && m->pair_geom2[k]==g2) ||
|
if ((m->pair_geom1[k] == g1 && m->pair_geom2[k] == g2) ||
|
||||||
(m->pair_geom1[k]==g2 && m->pair_geom2[k]==g1)) {
|
(m->pair_geom1[k] == g2 && m->pair_geom2[k] == g1)) {
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -139,9 +139,9 @@ int mj_collideOBB(const mjtNum aabb1[6], const mjtNum aabb2[6],
|
|||||||
mjtByte infinite[2] = {inf1[0] || inf1[1] || inf1[2], inf2[0] || inf2[1] || inf2[2]};
|
mjtByte infinite[2] = {inf1[0] || inf1[1] || inf1[2], inf2[0] || inf2[1] || inf2[2]};
|
||||||
|
|
||||||
// compute centers in local coordinates
|
// compute centers in local coordinates
|
||||||
if (product==NULL) {
|
if (product == NULL) {
|
||||||
for (int i=0; i<2; i++) { // bounding boxes
|
for (int i=0; i < 2; i++) { // bounding boxes
|
||||||
for (int j=0; j<3; j++) { // axes
|
for (int j=0; j < 3; j++) { // axes
|
||||||
mju_rotVecMat(xcenter[i], aabb[i], xmat[i]);
|
mju_rotVecMat(xcenter[i], aabb[i], xmat[i]);
|
||||||
mju_addTo3(xcenter[i], xpos[i]);
|
mju_addTo3(xcenter[i], xpos[i]);
|
||||||
}
|
}
|
||||||
@@ -149,9 +149,9 @@ int mj_collideOBB(const mjtNum aabb1[6], const mjtNum aabb2[6],
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute normals in global coordinates
|
// compute normals in global coordinates
|
||||||
for (int i=0; i<2; i++) { // bounding boxes
|
for (int i=0; i < 2; i++) { // bounding boxes
|
||||||
for (int j=0; j<3; j++) { // faces
|
for (int j=0; j < 3; j++) { // faces
|
||||||
for (int k=0; k<3; k++) { // world axes
|
for (int k=0; k < 3; k++) { // world axes
|
||||||
normal[i][j][k] = xmat[i][3*k+j];
|
normal[i][j][k] = xmat[i][3*k+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,10 +159,10 @@ int mj_collideOBB(const mjtNum aabb1[6], const mjtNum aabb2[6],
|
|||||||
|
|
||||||
// precompute dot products
|
// precompute dot products
|
||||||
if (product && offset && *initialize) {
|
if (product && offset && *initialize) {
|
||||||
for (int i=0; i<2; i++) { // bodies
|
for (int i=0; i < 2; i++) { // bodies
|
||||||
for (int j=0; j<2; j++) { // bodies
|
for (int j=0; j < 2; j++) { // bodies
|
||||||
for (int k=0; k<3; k++) { // axes
|
for (int k=0; k < 3; k++) { // axes
|
||||||
for (int l=0; l<3; l++) { // axes
|
for (int l=0; l < 3; l++) { // axes
|
||||||
product[18*i + 9*j + 3*k + l] = mju_dot3(normal[i][l], normal[j][k]);
|
product[18*i + 9*j + 3*k + l] = mju_dot3(normal[i][l], normal[j][k]);
|
||||||
}
|
}
|
||||||
offset[6*i + 3*j + k] = mju_dot3(xpos[i], normal[j][k]);
|
offset[6*i + 3*j + k] = mju_dot3(xpos[i], normal[j][k]);
|
||||||
@@ -173,13 +173,13 @@ int mj_collideOBB(const mjtNum aabb1[6], const mjtNum aabb2[6],
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check intersections
|
// check intersections
|
||||||
for (int j=0; j<2; j++) { // bounding boxes
|
for (int j=0; j < 2; j++) { // bounding boxes
|
||||||
if (infinite[1-j]) {
|
if (infinite[1-j]) {
|
||||||
continue; // skip test against an infinite body
|
continue; // skip test against an infinite body
|
||||||
}
|
}
|
||||||
for (int k=0; k<3; k++) { // face
|
for (int k=0; k < 3; k++) { // face
|
||||||
for (int i=0; i<2; i++) { // bounding boxes
|
for (int i=0; i < 2; i++) { // bounding boxes
|
||||||
if (product==NULL) {
|
if (product == NULL) {
|
||||||
proj[i] = mju_dot3(xcenter[i], normal[j][k]);
|
proj[i] = mju_dot3(xcenter[i], normal[j][k]);
|
||||||
radius[i] = fabs(aabb[i][3]*mju_dot3(normal[i][0], normal[j][k])) +
|
radius[i] = fabs(aabb[i][3]*mju_dot3(normal[i][0], normal[j][k])) +
|
||||||
fabs(aabb[i][4]*mju_dot3(normal[i][1], normal[j][k])) +
|
fabs(aabb[i][4]*mju_dot3(normal[i][1], normal[j][k])) +
|
||||||
@@ -210,7 +210,7 @@ static mjCollisionTree* mj_stackAllocTree(mjData* d, int max_stack) {
|
|||||||
_Static_assert(sizeof(mjCollisionTree*) % sizeof(mjtNum) == 0,
|
_Static_assert(sizeof(mjCollisionTree*) % sizeof(mjtNum) == 0,
|
||||||
"mjCollisionTree has a different size from mjtNum");
|
"mjCollisionTree has a different size from mjtNum");
|
||||||
return (mjCollisionTree*)mj_stackAlloc(
|
return (mjCollisionTree*)mj_stackAlloc(
|
||||||
d, max_stack * sizeof(mjCollisionTree*) / sizeof(mjtNum));
|
d, max_stack * sizeof(mjCollisionTree*) / sizeof(mjtNum));
|
||||||
}
|
}
|
||||||
|
|
||||||
// binary search between two body trees
|
// binary search between two body trees
|
||||||
@@ -245,7 +245,7 @@ void mj_collideTree(const mjModel* m, mjData* d, int b1, int b2,
|
|||||||
int nodeid2 = m->bvh_geomid[bvhadr2 + node2];
|
int nodeid2 = m->bvh_geomid[bvhadr2 + node2];
|
||||||
|
|
||||||
// both are leaves
|
// both are leaves
|
||||||
if (isleaf1 && isleaf2 && nodeid1!=-1 && nodeid2!=-1) {
|
if (isleaf1 && isleaf2 && nodeid1 != -1 && nodeid2 != -1) {
|
||||||
if (mj_collideSphere(m, d, nodeid1, nodeid2, /*margin=*/ 0)) {
|
if (mj_collideSphere(m, d, nodeid1, nodeid2, /*margin=*/ 0)) {
|
||||||
if (mj_collideOBB(m->geom_aabb + 6*nodeid1, m->geom_aabb + 6*nodeid2,
|
if (mj_collideOBB(m->geom_aabb + 6*nodeid1, m->geom_aabb + 6*nodeid2,
|
||||||
d->geom_xpos + 3*nodeid1, d->geom_xmat + 9*nodeid1,
|
d->geom_xpos + 3*nodeid1, d->geom_xmat + 9*nodeid1,
|
||||||
@@ -272,7 +272,7 @@ void mj_collideTree(const mjModel* m, mjData* d, int b1, int b2,
|
|||||||
|
|
||||||
// keep traversing the tree
|
// keep traversing the tree
|
||||||
if (!isleaf1 && isleaf2) {
|
if (!isleaf1 && isleaf2) {
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
if (child1[2*node1+i] != -1) {
|
if (child1[2*node1+i] != -1) {
|
||||||
if (nstack >= max_stack) mju_error("BVH stack depth exceeded."); // SHOULD NOT OCCUR
|
if (nstack >= max_stack) mju_error("BVH stack depth exceeded."); // SHOULD NOT OCCUR
|
||||||
stack[nstack].node1 = child1[2*node1+i];
|
stack[nstack].node1 = child1[2*node1+i];
|
||||||
@@ -281,7 +281,7 @@ void mj_collideTree(const mjModel* m, mjData* d, int b1, int b2,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isleaf1 && !isleaf2) {
|
} else if (isleaf1 && !isleaf2) {
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
if (child2[2*node2+i] != -1) {
|
if (child2[2*node2+i] != -1) {
|
||||||
if (nstack >= max_stack) mju_error("BVH stack depth exceeded."); // SHOULD NOT OCCUR
|
if (nstack >= max_stack) mju_error("BVH stack depth exceeded."); // SHOULD NOT OCCUR
|
||||||
stack[nstack].node1 = node1;
|
stack[nstack].node1 = node1;
|
||||||
@@ -380,14 +380,14 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// return if disabled
|
// return if disabled
|
||||||
if (mjDISABLED(mjDSBL_CONSTRAINT) || mjDISABLED(mjDSBL_CONTACT)
|
if (mjDISABLED(mjDSBL_CONSTRAINT) || mjDISABLED(mjDSBL_CONTACT)
|
||||||
|| m->nconmax==0 || m->nbody < 2) {
|
|| m->nconmax == 0 || m->nbody < 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// predefined only; ignore exclude
|
// predefined only; ignore exclude
|
||||||
if (m->opt.collision==mjCOL_PAIR) {
|
if (m->opt.collision == mjCOL_PAIR) {
|
||||||
d->nbodypair_broad = npair;
|
d->nbodypair_broad = npair;
|
||||||
for (pairadr=0; pairadr<npair; pairadr++) {
|
for (pairadr=0; pairadr < npair; pairadr++) {
|
||||||
int ngeompair_narrow_before = d->ngeompair_narrow;
|
int ngeompair_narrow_before = d->ngeompair_narrow;
|
||||||
int ngeompair_mid_before = d->ngeompair_mid;
|
int ngeompair_mid_before = d->ngeompair_mid;
|
||||||
mj_collideGeoms(m, d, pairadr, -1, 0, 0);
|
mj_collideGeoms(m, d, pairadr, -1, 0, 0);
|
||||||
@@ -405,7 +405,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
unsigned int last_signature = -1;
|
unsigned int last_signature = -1;
|
||||||
|
|
||||||
// loop over body pairs (broadphase or all)
|
// loop over body pairs (broadphase or all)
|
||||||
for (int i=0; i<nbodypair; i++) {
|
for (int i=0; i < nbodypair; i++) {
|
||||||
// reconstruct body pair ids
|
// reconstruct body pair ids
|
||||||
b1 = (broadphasepair[i]>>16) & 0xFFFF;
|
b1 = (broadphasepair[i]>>16) & 0xFFFF;
|
||||||
b2 = broadphasepair[i] & 0xFFFF;
|
b2 = broadphasepair[i] & 0xFFFF;
|
||||||
@@ -422,10 +422,10 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
// merge predefined pairs
|
// merge predefined pairs
|
||||||
merged = 0;
|
merged = 0;
|
||||||
startadr = pairadr;
|
startadr = pairadr;
|
||||||
if (npair && m->opt.collision==mjCOL_ALL) {
|
if (npair && m->opt.collision == mjCOL_ALL) {
|
||||||
// test all predefined pairs for which pair_signature<=signature
|
// test all predefined pairs for which pair_signature<=signature
|
||||||
while (pairadr<npair && m->pair_signature[pairadr]<=signature) {
|
while (pairadr < npair && m->pair_signature[pairadr] <= signature) {
|
||||||
if (m->pair_signature[pairadr]==signature) {
|
if (m->pair_signature[pairadr] == signature) {
|
||||||
merged = 1;
|
merged = 1;
|
||||||
}
|
}
|
||||||
mj_collideGeoms(m, d, pairadr++, -1, 0, 0);
|
mj_collideGeoms(m, d, pairadr++, -1, 0, 0);
|
||||||
@@ -435,12 +435,12 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
// handle exclusion
|
// handle exclusion
|
||||||
if (nexclude) {
|
if (nexclude) {
|
||||||
// advance exadr while exclude_signature < signature
|
// advance exadr while exclude_signature < signature
|
||||||
while (exadr<nexclude && m->exclude_signature[exadr]<signature) {
|
while (exadr < nexclude && m->exclude_signature[exadr] < signature) {
|
||||||
exadr++;
|
exadr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip this body pair if its signature is found in exclude array
|
// skip this body pair if its signature is found in exclude array
|
||||||
if (exadr<nexclude && m->exclude_signature[exadr]==signature) {
|
if (exadr < nexclude && m->exclude_signature[exadr] == signature) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -450,7 +450,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// test all geom pairs within this body pair
|
// test all geom pairs within this body pair
|
||||||
if (m->body_geomnum[b1] && m->body_geomnum[b2]) {
|
if (m->body_geomnum[b1] && m->body_geomnum[b2]) {
|
||||||
if (!mjDISABLED(mjDSBL_MIDPHASE) && m->body_geomnum[b1]*m->body_geomnum[b2]>1) {
|
if (!mjDISABLED(mjDSBL_MIDPHASE) && m->body_geomnum[b1]*m->body_geomnum[b2] > 1) {
|
||||||
int ncon_before = d->ncon;
|
int ncon_before = d->ncon;
|
||||||
mj_collideTree(m, d, b1, b2, merged, startadr, pairadr);
|
mj_collideTree(m, d, b1, b2, merged, startadr, pairadr);
|
||||||
int ncon_after = d->ncon;
|
int ncon_after = d->ncon;
|
||||||
@@ -458,8 +458,8 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
mjQUICKSORT(d->contact + ncon_before, ncon_after - ncon_before,
|
mjQUICKSORT(d->contact + ncon_before, ncon_after - ncon_before,
|
||||||
sizeof(mjContact), contactcompare, context);
|
sizeof(mjContact), contactcompare, context);
|
||||||
} else {
|
} else {
|
||||||
for (g1=m->body_geomadr[b1]; g1<m->body_geomadr[b1]+m->body_geomnum[b1]; g1++) {
|
for (g1=m->body_geomadr[b1]; g1 < m->body_geomadr[b1]+m->body_geomnum[b1]; g1++) {
|
||||||
for (g2=m->body_geomadr[b2]; g2<m->body_geomadr[b2]+m->body_geomnum[b2]; g2++) {
|
for (g2=m->body_geomadr[b2]; g2 < m->body_geomadr[b2]+m->body_geomnum[b2]; g2++) {
|
||||||
mj_collidePair(m, d, g1, g2, merged, startadr, pairadr);
|
mj_collidePair(m, d, g1, g2, merged, startadr, pairadr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,8 +470,8 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// finish merging predefined pairs
|
// finish merging predefined pairs
|
||||||
if (npair && m->opt.collision==mjCOL_ALL) {
|
if (npair && m->opt.collision == mjCOL_ALL) {
|
||||||
while (pairadr<npair) {
|
while (pairadr < npair) {
|
||||||
mj_collideGeoms(m, d, pairadr++, -1, 0, 0);
|
mj_collideGeoms(m, d, pairadr++, -1, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,28 +498,28 @@ static void makeAABB(const mjModel* m, mjData* d, mjtNum* aabb, int body, const
|
|||||||
mjtNum _aabb[6], cen;
|
mjtNum _aabb[6], cen;
|
||||||
|
|
||||||
// no geoms attached to body: set to 0
|
// no geoms attached to body: set to 0
|
||||||
if (m->body_geomnum[body]==0) {
|
if (m->body_geomnum[body] == 0) {
|
||||||
mju_zero(aabb, 6);
|
mju_zero(aabb, 6);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process all body geoms
|
// process all body geoms
|
||||||
for (int i=0; i<m->body_geomnum[body]; i++) {
|
for (int i=0; i < m->body_geomnum[body]; i++) {
|
||||||
// get geom id
|
// get geom id
|
||||||
geom = m->body_geomadr[body]+i;
|
geom = m->body_geomadr[body]+i;
|
||||||
|
|
||||||
// set _aabb for this geom
|
// set _aabb for this geom
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
cen = mju_dot3(d->geom_xpos+3*geom, frame+3*j);
|
cen = mju_dot3(d->geom_xpos+3*geom, frame+3*j);
|
||||||
_aabb[2*j] = cen - m->geom_rbound[geom] - m->geom_margin[geom];
|
_aabb[2*j] = cen - m->geom_rbound[geom] - m->geom_margin[geom];
|
||||||
_aabb[2*j+1] = cen + m->geom_rbound[geom] + m->geom_margin[geom];
|
_aabb[2*j+1] = cen + m->geom_rbound[geom] + m->geom_margin[geom];
|
||||||
}
|
}
|
||||||
|
|
||||||
// update body aabb
|
// update body aabb
|
||||||
if (i==0) {
|
if (i == 0) {
|
||||||
mju_copy(aabb, _aabb, 6);
|
mju_copy(aabb, _aabb, 6);
|
||||||
} else {
|
} else {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
aabb[2*j] = mju_min(aabb[2*j], _aabb[2*j]);
|
aabb[2*j] = mju_min(aabb[2*j], _aabb[2*j]);
|
||||||
aabb[2*j+1] = mju_max(aabb[2*j+1], _aabb[2*j+1]);
|
aabb[2*j+1] = mju_max(aabb[2*j+1], _aabb[2*j+1]);
|
||||||
}
|
}
|
||||||
@@ -536,8 +536,8 @@ static int has_plane_or_hfield(const mjModel* m, int body) {
|
|||||||
|
|
||||||
// scan geoms belonging to body
|
// scan geoms belonging to body
|
||||||
int g;
|
int g;
|
||||||
for (g=start; g<end; g++) {
|
for (g=start; g < end; g++) {
|
||||||
if (m->geom_type[g]==mjGEOM_PLANE || m->geom_type[g]==mjGEOM_HFIELD) {
|
if (m->geom_type[g] == mjGEOM_PLANE || m->geom_type[g] == mjGEOM_HFIELD) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -549,7 +549,7 @@ static int has_plane_or_hfield(const mjModel* m, int body) {
|
|||||||
static int body_pair_filter(int weldbody1, int weldparent1, int weldbody2,
|
static int body_pair_filter(int weldbody1, int weldparent1, int weldbody2,
|
||||||
int weldparent2, int dsbl_filterparent) {
|
int weldparent2, int dsbl_filterparent) {
|
||||||
// same weldbody check
|
// same weldbody check
|
||||||
if (weldbody1==weldbody2) {
|
if (weldbody1 == weldbody2) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,9 +566,9 @@ static int body_pair_filter(int weldbody1, int weldparent1, int weldbody2,
|
|||||||
// add body pair in buffer
|
// add body pair in buffer
|
||||||
static void add_pair(const mjModel* m, int b1, int b2, int* npair, int* pair, int maxpair) {
|
static void add_pair(const mjModel* m, int b1, int b2, int* npair, int* pair, int maxpair) {
|
||||||
// add pair if there is room in buffer
|
// add pair if there is room in buffer
|
||||||
if ((*npair)<maxpair) {
|
if ((*npair) < maxpair) {
|
||||||
// exlude based on contype and conaffinity
|
// exlude based on contype and conaffinity
|
||||||
if (m && m->body_geomnum[b1]==1 && m->body_geomnum[b2]==1) {
|
if (m && m->body_geomnum[b1] == 1 && m->body_geomnum[b2] == 1) {
|
||||||
// get contypes and conaffinities
|
// get contypes and conaffinities
|
||||||
int contype1 = m->geom_contype[m->body_geomadr[b1]];
|
int contype1 = m->geom_contype[m->body_geomadr[b1]];
|
||||||
int conaffinity1 = m->geom_conaffinity[m->body_geomadr[b1]];
|
int conaffinity1 = m->geom_conaffinity[m->body_geomadr[b1]];
|
||||||
@@ -582,7 +582,7 @@ static void add_pair(const mjModel* m, int b1, int b2, int* npair, int* pair, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add pair
|
// add pair
|
||||||
if (b1<b2) {
|
if (b1 < b2) {
|
||||||
pair[*npair] = (b1<<16) + b2;
|
pair[*npair] = (b1<<16) + b2;
|
||||||
} else {
|
} else {
|
||||||
pair[*npair] = (b2<<16) + b1;
|
pair[*npair] = (b2<<16) + b1;
|
||||||
@@ -601,9 +601,9 @@ quicksortfunc(broadcompare, context, el1, el2) {
|
|||||||
mjtBroadphase* b1 = (mjtBroadphase*)el1;
|
mjtBroadphase* b1 = (mjtBroadphase*)el1;
|
||||||
mjtBroadphase* b2 = (mjtBroadphase*)el2;
|
mjtBroadphase* b2 = (mjtBroadphase*)el2;
|
||||||
|
|
||||||
if (b1->value<b2->value) {
|
if (b1->value < b2->value) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (b1->value==b2->value) {
|
} else if (b1->value == b2->value) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -617,9 +617,9 @@ quicksortfunc(paircompare, context, el1, el2) {
|
|||||||
int signature1 = *(int*)el1;
|
int signature1 = *(int*)el1;
|
||||||
int signature2 = *(int*)el2;
|
int signature2 = *(int*)el2;
|
||||||
|
|
||||||
if (signature1<signature2) {
|
if (signature1 < signature2) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (signature1==signature2) {
|
} else if (signature1 == signature2) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -633,7 +633,7 @@ static int can_collide(const mjModel* m, int b) {
|
|||||||
int g;
|
int g;
|
||||||
|
|
||||||
// scan geoms; return if collidable
|
// scan geoms; return if collidable
|
||||||
for (g=0; g<m->body_geomnum[b]; g++) {
|
for (g=0; g < m->body_geomnum[b]; g++) {
|
||||||
int ind = m->body_geomadr[b] + g;
|
int ind = m->body_geomadr[b] + g;
|
||||||
if (m->geom_contype[ind] || m->geom_conaffinity[ind]) {
|
if (m->geom_contype[ind] || m->geom_conaffinity[ind]) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -656,17 +656,18 @@ int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
|
|||||||
|
|
||||||
int dsbl_filterparent = mjDISABLED(mjDSBL_FILTERPARENT);
|
int dsbl_filterparent = mjDISABLED(mjDSBL_FILTERPARENT);
|
||||||
// world with geoms, and body with plane or hfield, can collide all bodies
|
// world with geoms, and body with plane or hfield, can collide all bodies
|
||||||
for (b1=0; b1<nbody; b1++) {
|
for (b1=0; b1 < nbody; b1++) {
|
||||||
// cannot colide
|
// cannot colide
|
||||||
if (!can_collide(m, b1)) {
|
if (!can_collide(m, b1)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// world with geoms, or welded body with plane or hfield
|
// world with geoms, or welded body with plane or hfield
|
||||||
if ((b1==0 && m->body_geomnum[b1]>0) || (m->body_weldid[b1]==0 && has_plane_or_hfield(m, b1))) {
|
if ((b1 == 0 && m->body_geomnum[b1] > 0) ||
|
||||||
|
(m->body_weldid[b1] == 0 && has_plane_or_hfield(m, b1))) {
|
||||||
int weld1 = 0;
|
int weld1 = 0;
|
||||||
int parent_weld1 = 0;
|
int parent_weld1 = 0;
|
||||||
for (b2=0; b2<nbody; b2++) {
|
for (b2=0; b2 < nbody; b2++) {
|
||||||
int weld2 = m->body_weldid[b2];
|
int weld2 = m->body_weldid[b2];
|
||||||
int parent_weld2 = m->body_weldid[m->body_parentid[weld2]];
|
int parent_weld2 = m->body_weldid[m->body_parentid[weld2]];
|
||||||
if (!body_pair_filter(weld1, parent_weld1, weld2, parent_weld2,
|
if (!body_pair_filter(weld1, parent_weld1, weld2, parent_weld2,
|
||||||
@@ -680,23 +681,23 @@ int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
|
|||||||
// find center of non-world geoms; return if none
|
// find center of non-world geoms; return if none
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
mju_zero3(cen);
|
mju_zero3(cen);
|
||||||
for (int i=0; i<ngeom; i++) {
|
for (int i=0; i < ngeom; i++) {
|
||||||
if (m->geom_bodyid[i]) {
|
if (m->geom_bodyid[i]) {
|
||||||
mju_addTo3(cen, d->geom_xpos+3*i);
|
mju_addTo3(cen, d->geom_xpos+3*i);
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cnt==0) {
|
if (cnt == 0) {
|
||||||
return npair;
|
return npair;
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
cen[i] /= cnt;
|
cen[i] /= cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute covariance
|
// compute covariance
|
||||||
mju_zero(cov, 9);
|
mju_zero(cov, 9);
|
||||||
for (int i=0; i<ngeom; i++) {
|
for (int i=0; i < ngeom; i++) {
|
||||||
if (m->geom_bodyid[i]) {
|
if (m->geom_bodyid[i]) {
|
||||||
mju_sub3(dif, d->geom_xpos+3*i, cen);
|
mju_sub3(dif, d->geom_xpos+3*i, cen);
|
||||||
mjtNum D00 = dif[0]*dif[0];
|
mjtNum D00 = dif[0]*dif[0];
|
||||||
@@ -716,7 +717,7 @@ int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
|
|||||||
cov[8] += D22;
|
cov[8] += D22;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<9; i++) {
|
for (int i=0; i < 9; i++) {
|
||||||
cov[i] /= cnt;
|
cov[i] /= cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,7 +730,7 @@ int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
|
|||||||
|
|
||||||
// construct body AABB for the aligned frame, count collidable
|
// construct body AABB for the aligned frame, count collidable
|
||||||
int bufcnt = 0;
|
int bufcnt = 0;
|
||||||
for (int i=1; i<nbody; i++) {
|
for (int i=1; i < nbody; i++) {
|
||||||
makeAABB(m, d, aabb+6*i, i, frame);
|
makeAABB(m, d, aabb+6*i, i, frame);
|
||||||
|
|
||||||
if (can_collide(m, i)) {
|
if (can_collide(m, i)) {
|
||||||
@@ -750,7 +751,7 @@ int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
|
|||||||
|
|
||||||
// init sortbuf with axis0
|
// init sortbuf with axis0
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (int i=1; i<nbody; i++) {
|
for (int i=1; i < nbody; i++) {
|
||||||
// cannot colide
|
// cannot colide
|
||||||
if (!can_collide(m, i)) {
|
if (!can_collide(m, i)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -765,7 +766,7 @@ int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sanity check; SHOULD NOT OCCUR
|
// sanity check; SHOULD NOT OCCUR
|
||||||
if (k!=bufcnt) {
|
if (k != bufcnt) {
|
||||||
mju_error("Internal error in broadphase: unexpected bufcnt");
|
mju_error("Internal error in broadphase: unexpected bufcnt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,10 +775,10 @@ int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
|
|||||||
|
|
||||||
// sweep and prune
|
// sweep and prune
|
||||||
cnt = 0; // size of active list
|
cnt = 0; // size of active list
|
||||||
for (int i=0; i<2*bufcnt; i++) {
|
for (int i=0; i < 2*bufcnt; i++) {
|
||||||
// min value: collide with all in list, add
|
// min value: collide with all in list, add
|
||||||
if (!(sortbuf[i].body_ismax & 0x10000)) {
|
if (!(sortbuf[i].body_ismax & 0x10000)) {
|
||||||
for (int j=0; j<cnt; j++) {
|
for (int j=0; j < cnt; j++) {
|
||||||
// get body ids: no need to mask ismax because activebuf entries never have the ismax bit,
|
// get body ids: no need to mask ismax because activebuf entries never have the ismax bit,
|
||||||
// and sortbuf[i].body_ismax is tested above
|
// and sortbuf[i].body_ismax is tested above
|
||||||
b1 = activebuf[j].body_ismax;
|
b1 = activebuf[j].body_ismax;
|
||||||
@@ -813,9 +814,9 @@ int mj_broadphase(const mjModel* m, mjData* d, int* pair, int maxpair) {
|
|||||||
// max value: remove corresponding min value from list
|
// max value: remove corresponding min value from list
|
||||||
else {
|
else {
|
||||||
toremove = sortbuf[i].body_ismax & 0xFFFF;
|
toremove = sortbuf[i].body_ismax & 0xFFFF;
|
||||||
for (int j=0; j<cnt; j++) {
|
for (int j=0; j < cnt; j++) {
|
||||||
if (activebuf[j].body_ismax==toremove) {
|
if (activebuf[j].body_ismax == toremove) {
|
||||||
if (j<cnt-1) {
|
if (j < cnt-1) {
|
||||||
memmove(activebuf+j, activebuf+j+1, sizeof(mjtBroadphase)*(cnt-1-j));
|
memmove(activebuf+j, activebuf+j+1, sizeof(mjtBroadphase)*(cnt-1-j));
|
||||||
}
|
}
|
||||||
cnt--;
|
cnt--;
|
||||||
@@ -847,10 +848,10 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
int num, type1, type2, condim;
|
int num, type1, type2, condim;
|
||||||
mjtNum margin, gap, mix, friction[5], solref[mjNREF], solimp[mjNIMP];
|
mjtNum margin, gap, mix, friction[5], solref[mjNREF], solimp[mjNIMP];
|
||||||
mjContact con[mjMAXCONPAIR];
|
mjContact con[mjMAXCONPAIR];
|
||||||
int ipair = (g2<0 ? g1 : -1);
|
int ipair = (g2 < 0 ? g1 : -1);
|
||||||
|
|
||||||
// get explicit geom ids from pair
|
// get explicit geom ids from pair
|
||||||
if (ipair>=0) {
|
if (ipair >= 0) {
|
||||||
g1 = m->pair_geom1[ipair];
|
g1 = m->pair_geom1[ipair];
|
||||||
g2 = m->pair_geom2[ipair];
|
g2 = m->pair_geom2[ipair];
|
||||||
}
|
}
|
||||||
@@ -872,7 +873,7 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// apply filters if not predefined pair and not flg_user
|
// apply filters if not predefined pair and not flg_user
|
||||||
if (ipair<0 && !flg_user) {
|
if (ipair < 0 && !flg_user) {
|
||||||
// user filter if defined
|
// user filter if defined
|
||||||
if (mjcb_contactfilter) {
|
if (mjcb_contactfilter) {
|
||||||
if (mjcb_contactfilter(m, d, g1, g2)) {
|
if (mjcb_contactfilter(m, d, g1, g2)) {
|
||||||
@@ -888,14 +889,14 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set margin, gap, condim: dynamic
|
// set margin, gap, condim: dynamic
|
||||||
if (ipair<0) {
|
if (ipair < 0) {
|
||||||
// margin and gap: max
|
// margin and gap: max
|
||||||
margin = mju_max(m->geom_margin[g1], m->geom_margin[g2]);
|
margin = mju_max(m->geom_margin[g1], m->geom_margin[g2]);
|
||||||
gap = mju_max(m->geom_gap[g1], m->geom_gap[g2]);
|
gap = mju_max(m->geom_gap[g1], m->geom_gap[g2]);
|
||||||
|
|
||||||
// condim: priority or max
|
// condim: priority or max
|
||||||
if (m->geom_priority[g1]!=m->geom_priority[g2]) {
|
if (m->geom_priority[g1] != m->geom_priority[g2]) {
|
||||||
int gp = (m->geom_priority[g1]>m->geom_priority[g2] ? g1 : g2);
|
int gp = (m->geom_priority[g1] > m->geom_priority[g2] ? g1 : g2);
|
||||||
condim = m->geom_condim[gp];
|
condim = m->geom_condim[gp];
|
||||||
} else {
|
} else {
|
||||||
condim = mjMAX(m->geom_condim[g1], m->geom_condim[g2]);
|
condim = mjMAX(m->geom_condim[g1], m->geom_condim[g2]);
|
||||||
@@ -936,23 +937,23 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
d->ngeompair_narrow++;
|
d->ngeompair_narrow++;
|
||||||
|
|
||||||
// check number of contacts, SHOULD NOT OCCUR
|
// check number of contacts, SHOULD NOT OCCUR
|
||||||
if (num>mjMAXCONPAIR) {
|
if (num > mjMAXCONPAIR) {
|
||||||
mju_error("Too many contacts returned by collision function");
|
mju_error("Too many contacts returned by collision function");
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove repeated contacts in box-box
|
// remove repeated contacts in box-box
|
||||||
if (type1==mjGEOM_BOX && type2==mjGEOM_BOX) {
|
if (type1 == mjGEOM_BOX && type2 == mjGEOM_BOX) {
|
||||||
// use dim field to mark: -1: bad, 0: good
|
// use dim field to mark: -1: bad, 0: good
|
||||||
for (int i=0; i<num; i++) {
|
for (int i=0; i < num; i++) {
|
||||||
con[i].dim = 0;
|
con[i].dim = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find bad
|
// find bad
|
||||||
for (int i=0; i<num-1; i++) {
|
for (int i=0; i < num-1; i++) {
|
||||||
for (int j=i+1; j<num; j++) {
|
for (int j=i+1; j < num; j++) {
|
||||||
if (con[i].pos[0]==con[j].pos[0] &&
|
if (con[i].pos[0] == con[j].pos[0] &&
|
||||||
con[i].pos[1]==con[j].pos[1] &&
|
con[i].pos[1] == con[j].pos[1] &&
|
||||||
con[i].pos[2]==con[j].pos[2]) {
|
con[i].pos[2] == con[j].pos[2]) {
|
||||||
con[i].dim = -1;
|
con[i].dim = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -961,10 +962,10 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
|
|
||||||
// consolidate good
|
// consolidate good
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (int j=0; j<num; j++) {
|
for (int j=0; j < num; j++) {
|
||||||
if (con[j].dim==0) {
|
if (con[j].dim == 0) {
|
||||||
// different: copy
|
// different: copy
|
||||||
if (i<j) {
|
if (i < j) {
|
||||||
con[i] = con[j];
|
con[i] = con[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,13 +979,13 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set friction, solref, solimp: dynamic
|
// set friction, solref, solimp: dynamic
|
||||||
if (ipair<0) {
|
if (ipair < 0) {
|
||||||
// different priority
|
// different priority
|
||||||
if (m->geom_priority[g1]!=m->geom_priority[g2]) {
|
if (m->geom_priority[g1] != m->geom_priority[g2]) {
|
||||||
int gp = (m->geom_priority[g1]>m->geom_priority[g2] ? g1 : g2);
|
int gp = (m->geom_priority[g1] > m->geom_priority[g2] ? g1 : g2);
|
||||||
|
|
||||||
// friction
|
// friction
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
friction[2*i] = m->geom_friction[3*gp+i];
|
friction[2*i] = m->geom_friction[3*gp+i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -998,31 +999,31 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
// same priority
|
// same priority
|
||||||
else {
|
else {
|
||||||
// friction: max
|
// friction: max
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
friction[2*i] = mju_max(m->geom_friction[3*g1+i], m->geom_friction[3*g2+i]);
|
friction[2*i] = mju_max(m->geom_friction[3*g1+i], m->geom_friction[3*g2+i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// solver mix factor
|
// solver mix factor
|
||||||
if (m->geom_solmix[g1]>=mjMINVAL && m->geom_solmix[g2]>=mjMINVAL) {
|
if (m->geom_solmix[g1] >= mjMINVAL && m->geom_solmix[g2] >= mjMINVAL) {
|
||||||
mix = m->geom_solmix[g1] / (m->geom_solmix[g1] + m->geom_solmix[g2]);
|
mix = m->geom_solmix[g1] / (m->geom_solmix[g1] + m->geom_solmix[g2]);
|
||||||
} else if (m->geom_solmix[g1]<mjMINVAL && m->geom_solmix[g2]<mjMINVAL) {
|
} else if (m->geom_solmix[g1] < mjMINVAL && m->geom_solmix[g2] < mjMINVAL) {
|
||||||
mix = 0.5;
|
mix = 0.5;
|
||||||
} else if (m->geom_solmix[g1]<mjMINVAL) {
|
} else if (m->geom_solmix[g1] < mjMINVAL) {
|
||||||
mix = 0.0;
|
mix = 0.0;
|
||||||
} else {
|
} else {
|
||||||
mix = 1.0;
|
mix = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reference standard: mix
|
// reference standard: mix
|
||||||
if (m->geom_solref[mjNREF*g1]>0 && m->geom_solref[mjNREF*g2]>0) {
|
if (m->geom_solref[mjNREF*g1] > 0 && m->geom_solref[mjNREF*g2] > 0) {
|
||||||
for (int i=0; i<mjNREF; i++) {
|
for (int i=0; i < mjNREF; i++) {
|
||||||
solref[i] = mix*m->geom_solref[mjNREF*g1+i] + (1-mix)*m->geom_solref[mjNREF*g2+i];
|
solref[i] = mix*m->geom_solref[mjNREF*g1+i] + (1-mix)*m->geom_solref[mjNREF*g2+i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reference direct: min
|
// reference direct: min
|
||||||
else {
|
else {
|
||||||
for (int i=0; i<mjNREF; i++) {
|
for (int i=0; i < mjNREF; i++) {
|
||||||
solref[i] = mju_min(m->geom_solref[mjNREF*g1+i], m->geom_solref[mjNREF*g2+i]);
|
solref[i] = mju_min(m->geom_solref[mjNREF*g1+i], m->geom_solref[mjNREF*g2+i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1040,7 +1041,7 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
// set friction, solref, solimp: pair
|
// set friction, solref, solimp: pair
|
||||||
else {
|
else {
|
||||||
// friction
|
// friction
|
||||||
for (int i=0; i<5; i++) {
|
for (int i=0; i < 5; i++) {
|
||||||
friction[i] = m->pair_friction[5*ipair+i];
|
friction[i] = m->pair_friction[5*ipair+i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,12 +1053,12 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clamp friction to mjMINMU
|
// clamp friction to mjMINMU
|
||||||
for (int i=0; i<5; i++) {
|
for (int i=0; i < 5; i++) {
|
||||||
friction[i] = mju_max(mjMINMU, friction[i]);
|
friction[i] = mju_max(mjMINMU, friction[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add contact returned by collision detector
|
// add contact returned by collision detector
|
||||||
for (int i=0; i<num; i++) {
|
for (int i=0; i < num; i++) {
|
||||||
// set contact data
|
// set contact data
|
||||||
if (condim > 6 || condim < 1) { // SHOULD NOT OCCUR
|
if (condim > 6 || condim < 1) { // SHOULD NOT OCCUR
|
||||||
mju_error("Invalid condim value: %d", i);
|
mju_error("Invalid condim value: %d", i);
|
||||||
@@ -1071,7 +1072,7 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
|||||||
mj_assignImp(m, con[i].solimp, solimp);
|
mj_assignImp(m, con[i].solimp, solimp);
|
||||||
|
|
||||||
// exclude in gap
|
// exclude in gap
|
||||||
if (con[i].dist<con[i].includemargin) {
|
if (con[i].dist < con[i].includemargin) {
|
||||||
con[i].exclude = 0;
|
con[i].exclude = 0;
|
||||||
} else {
|
} else {
|
||||||
con[i].exclude = 1;
|
con[i].exclude = 1;
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ int mjc_PlaneBox(const mjModel* m, const mjData* d,
|
|||||||
dist = mju_dot3(dif, norm);
|
dist = mju_dot3(dif, norm);
|
||||||
|
|
||||||
// test all corners, pick bottom 4
|
// test all corners, pick bottom 4
|
||||||
for (int i=0; i<8; i++) {
|
for (int i=0; i < 8; i++) {
|
||||||
// get corner in local coordinates
|
// get corner in local coordinates
|
||||||
vec[0] = (i&1 ? size2[0] : -size2[0]);
|
vec[0] = (i&1 ? size2[0] : -size2[0]);
|
||||||
vec[1] = (i&2 ? size2[1] : -size2[1]);
|
vec[1] = (i&2 ? size2[1] : -size2[1]);
|
||||||
@@ -298,7 +298,7 @@ static int _SphereSphere(mjContact* con, mjtNum margin,
|
|||||||
int mjc_SphereSphere(const mjModel* m, const mjData* d,
|
int mjc_SphereSphere(const mjModel* m, const mjData* d,
|
||||||
mjContact* con, int g1, int g2, mjtNum margin) {
|
mjContact* con, int g1, int g2, mjtNum margin) {
|
||||||
mjGETINFO
|
mjGETINFO
|
||||||
return _SphereSphere(con, margin, pos1, mat1, size1, pos2, mat2, size2);
|
return _SphereSphere(con, margin, pos1, mat1, size1, pos2, mat2, size2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -423,7 +423,7 @@ int mjc_CapsuleCapsule(const mjModel* m, const mjData* d,
|
|||||||
n2 = _SphereSphere(con+n1, margin, vec1, mat1, size1, vec2, mat2, size2);
|
n2 = _SphereSphere(con+n1, margin, vec1, mat1, size1, vec2, mat2, size2);
|
||||||
|
|
||||||
// return if two contacts already found
|
// return if two contacts already found
|
||||||
if (n1+n2>=2) {
|
if (n1+n2 >= 2) {
|
||||||
return n1+n2;
|
return n1+n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ int mjc_CapsuleCapsule(const mjModel* m, const mjData* d,
|
|||||||
n3 = _SphereSphere(con+n1+n2, margin, vec1, mat1, size1, vec2, mat2, size2);
|
n3 = _SphereSphere(con+n1+n2, margin, vec1, mat1, size1, vec2, mat2, size2);
|
||||||
|
|
||||||
// return if two contacts already found
|
// return if two contacts already found
|
||||||
if (n1+n2+n3>=2) {
|
if (n1+n2+n3 >= 2) {
|
||||||
return n1+n2+n3;
|
return n1+n2+n3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+189
-189
File diff suppressed because it is too large
Load Diff
+104
-104
@@ -50,14 +50,14 @@ void mj_kinematics(const mjModel* m, mjData* d) {
|
|||||||
mj_normalizeQuat(m, d->qpos);
|
mj_normalizeQuat(m, d->qpos);
|
||||||
|
|
||||||
// normalize mocap quaternions
|
// normalize mocap quaternions
|
||||||
for (int i=0; i<m->nmocap; i++) {
|
for (int i=0; i < m->nmocap; i++) {
|
||||||
mju_normalize4(d->mocap_quat+4*i);
|
mju_normalize4(d->mocap_quat+4*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute global cartesian positions and orientations of all bodies
|
// compute global cartesian positions and orientations of all bodies
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
// free joint
|
// free joint
|
||||||
if (m->body_jntnum[i]==1 && m->jnt_type[m->body_jntadr[i]]==mjJNT_FREE) {
|
if (m->body_jntnum[i] == 1 && m->jnt_type[m->body_jntadr[i]] == mjJNT_FREE) {
|
||||||
// get addresses
|
// get addresses
|
||||||
int jid = m->body_jntadr[i];
|
int jid = m->body_jntadr[i];
|
||||||
int qadr = m->jnt_qposadr[jid];
|
int qadr = m->jnt_qposadr[jid];
|
||||||
@@ -81,7 +81,7 @@ void mj_kinematics(const mjModel* m, mjData* d) {
|
|||||||
int pid = m->body_parentid[i];
|
int pid = m->body_parentid[i];
|
||||||
|
|
||||||
// get body pos and quat: from model or mocap
|
// get body pos and quat: from model or mocap
|
||||||
if (m->body_mocapid[i]>=0) {
|
if (m->body_mocapid[i] >= 0) {
|
||||||
bodypos = d->mocap_pos + 3*m->body_mocapid[i];
|
bodypos = d->mocap_pos + 3*m->body_mocapid[i];
|
||||||
bodyquat = d->mocap_quat + 4*m->body_mocapid[i];
|
bodyquat = d->mocap_quat + 4*m->body_mocapid[i];
|
||||||
} else {
|
} else {
|
||||||
@@ -95,7 +95,7 @@ void mj_kinematics(const mjModel* m, mjData* d) {
|
|||||||
mju_mulQuat(quat, d->xquat+4*pid, bodyquat);
|
mju_mulQuat(quat, d->xquat+4*pid, bodyquat);
|
||||||
|
|
||||||
// accumulate joints, compute pos and quat for this body
|
// accumulate joints, compute pos and quat for this body
|
||||||
for (int j=0; j<m->body_jntnum[i]; j++) {
|
for (int j=0; j < m->body_jntnum[i]; j++) {
|
||||||
// get joint id, qpos address, joint type
|
// get joint id, qpos address, joint type
|
||||||
int jid = m->body_jntadr[i] + j;
|
int jid = m->body_jntadr[i] + j;
|
||||||
int qadr = m->jnt_qposadr[jid];
|
int qadr = m->jnt_qposadr[jid];
|
||||||
@@ -117,7 +117,7 @@ void mj_kinematics(const mjModel* m, mjData* d) {
|
|||||||
case mjJNT_BALL:
|
case mjJNT_BALL:
|
||||||
case mjJNT_HINGE:
|
case mjJNT_HINGE:
|
||||||
// compute local quaternion rotation (qloc)
|
// compute local quaternion rotation (qloc)
|
||||||
if (jtype==mjJNT_BALL) {
|
if (jtype == mjJNT_BALL) {
|
||||||
mju_copy4(qloc, d->qpos+qadr);
|
mju_copy4(qloc, d->qpos+qadr);
|
||||||
} else {
|
} else {
|
||||||
mju_axisAngle2Quat(qloc, m->jnt_axis+3*jid, d->qpos[qadr] - m->qpos0[qadr]);
|
mju_axisAngle2Quat(qloc, m->jnt_axis+3*jid, d->qpos[qadr] - m->qpos0[qadr]);
|
||||||
@@ -152,21 +152,21 @@ void mj_kinematics(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute/copy Cartesian positions and orientations of body inertial frames
|
// compute/copy Cartesian positions and orientations of body inertial frames
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
mj_local2Global(d, d->xipos+3*i, d->ximat+9*i,
|
mj_local2Global(d, d->xipos+3*i, d->ximat+9*i,
|
||||||
m->body_ipos+3*i, m->body_iquat+4*i,
|
m->body_ipos+3*i, m->body_iquat+4*i,
|
||||||
i, m->body_sameframe[i]);
|
i, m->body_sameframe[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute/copy Cartesian positions and orientations of geoms
|
// compute/copy Cartesian positions and orientations of geoms
|
||||||
for (int i=0; i<m->ngeom; i++) {
|
for (int i=0; i < m->ngeom; i++) {
|
||||||
mj_local2Global(d, d->geom_xpos+3*i, d->geom_xmat+9*i,
|
mj_local2Global(d, d->geom_xpos+3*i, d->geom_xmat+9*i,
|
||||||
m->geom_pos+3*i, m->geom_quat+4*i,
|
m->geom_pos+3*i, m->geom_quat+4*i,
|
||||||
m->geom_bodyid[i], m->geom_sameframe[i]);
|
m->geom_bodyid[i], m->geom_sameframe[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute/copy Cartesian positions and orientations of sites
|
// compute/copy Cartesian positions and orientations of sites
|
||||||
for (int i=0; i<m->nsite; i++) {
|
for (int i=0; i < m->nsite; i++) {
|
||||||
mj_local2Global(d, d->site_xpos+3*i, d->site_xmat+9*i,
|
mj_local2Global(d, d->site_xpos+3*i, d->site_xmat+9*i,
|
||||||
m->site_pos+3*i, m->site_quat+4*i,
|
m->site_pos+3*i, m->site_quat+4*i,
|
||||||
m->site_bodyid[i], m->site_sameframe[i]);
|
m->site_bodyid[i], m->site_sameframe[i]);
|
||||||
@@ -186,7 +186,7 @@ void mj_comPos(const mjModel* m, mjData* d) {
|
|||||||
mju_zero(d->subtree_com, m->nbody*3);
|
mju_zero(d->subtree_com, m->nbody*3);
|
||||||
|
|
||||||
// backwards pass over bodies: compute subtree_com and mass_subtree
|
// backwards pass over bodies: compute subtree_com and mass_subtree
|
||||||
for (int i=m->nbody-1; i>=0; i--) {
|
for (int i=m->nbody-1; i >= 0; i--) {
|
||||||
// add local info
|
// add local info
|
||||||
mju_addToScl3(d->subtree_com+3*i, d->xipos+3*i, m->body_mass[i]);
|
mju_addToScl3(d->subtree_com+3*i, d->xipos+3*i, m->body_mass[i]);
|
||||||
mass_subtree[i] += m->body_mass[i];
|
mass_subtree[i] += m->body_mass[i];
|
||||||
@@ -199,7 +199,7 @@ void mj_comPos(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute local com
|
// compute local com
|
||||||
if (mass_subtree[i]<mjMINVAL) {
|
if (mass_subtree[i] < mjMINVAL) {
|
||||||
mju_copy3(d->subtree_com+3*i, d->xipos+3*i);
|
mju_copy3(d->subtree_com+3*i, d->xipos+3*i);
|
||||||
} else {
|
} else {
|
||||||
mju_scl3(d->subtree_com+3*i, d->subtree_com+3*i,
|
mju_scl3(d->subtree_com+3*i, d->subtree_com+3*i,
|
||||||
@@ -208,14 +208,14 @@ void mj_comPos(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map inertias to frame centered at subtree_com
|
// map inertias to frame centered at subtree_com
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
mju_sub3(offset, d->xipos+3*i, d->subtree_com+3*m->body_rootid[i]);
|
mju_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,
|
mju_inertCom(d->cinert+10*i, m->body_inertia+3*i, d->ximat+9*i,
|
||||||
offset, m->body_mass[i]);
|
offset, m->body_mass[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// map motion dofs to global frame centered at subtree_com
|
// map motion dofs to global frame centered at subtree_com
|
||||||
for (int j=0; j<m->njnt; j++) {
|
for (int j=0; j < m->njnt; j++) {
|
||||||
// get dof address, body index
|
// get dof address, body index
|
||||||
int da = 6*m->jnt_dofadr[j];
|
int da = 6*m->jnt_dofadr[j];
|
||||||
int bi = m->jnt_bodyid[j];
|
int bi = m->jnt_bodyid[j];
|
||||||
@@ -229,7 +229,7 @@ void mj_comPos(const mjModel* m, mjData* d) {
|
|||||||
case mjJNT_FREE:
|
case mjJNT_FREE:
|
||||||
// translation components: x, y, z in global frame
|
// translation components: x, y, z in global frame
|
||||||
mju_zero(d->cdof+da, 18);
|
mju_zero(d->cdof+da, 18);
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
d->cdof[da+3+7*i] = 1;
|
d->cdof[da+3+7*i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ void mj_comPos(const mjModel* m, mjData* d) {
|
|||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjJNT_BALL:
|
case mjJNT_BALL:
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
// I_3 rotation in child frame (assume no subsequent rotations)
|
// I_3 rotation in child frame (assume no subsequent rotations)
|
||||||
axis[0] = d->xmat[9*bi+i+0];
|
axis[0] = d->xmat[9*bi+i+0];
|
||||||
axis[1] = d->xmat[9*bi+i+3];
|
axis[1] = d->xmat[9*bi+i+3];
|
||||||
@@ -268,7 +268,7 @@ void mj_camlight(const mjModel* m, mjData* d) {
|
|||||||
mjtNum pos[3], matT[9];
|
mjtNum pos[3], matT[9];
|
||||||
|
|
||||||
// compute Cartesian positions and orientations of cameras
|
// compute Cartesian positions and orientations of cameras
|
||||||
for (int i=0; i<m->ncam; i++) {
|
for (int i=0; i < m->ncam; i++) {
|
||||||
// default processing for fixed mode
|
// default processing for fixed mode
|
||||||
mj_local2Global(d, d->cam_xpos+3*i, d->cam_xmat+9*i,
|
mj_local2Global(d, d->cam_xpos+3*i, d->cam_xmat+9*i,
|
||||||
m->cam_pos+3*i, m->cam_quat+4*i, m->cam_bodyid[i], 0);
|
m->cam_pos+3*i, m->cam_quat+4*i, m->cam_bodyid[i], 0);
|
||||||
@@ -285,7 +285,7 @@ void mj_camlight(const mjModel* m, mjData* d) {
|
|||||||
mju_copy(d->cam_xmat+9*i, m->cam_mat0+9*i, 9);
|
mju_copy(d->cam_xmat+9*i, m->cam_mat0+9*i, 9);
|
||||||
|
|
||||||
// position: track camera body
|
// position: track camera body
|
||||||
if (m->cam_mode[i]==mjCAMLIGHT_TRACK) {
|
if (m->cam_mode[i] == mjCAMLIGHT_TRACK) {
|
||||||
mju_add3(d->cam_xpos+3*i, d->xpos+3*id, m->cam_pos0+3*i);
|
mju_add3(d->cam_xpos+3*i, d->xpos+3*id, m->cam_pos0+3*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,9 +298,9 @@ void mj_camlight(const mjModel* m, mjData* d) {
|
|||||||
case mjCAMLIGHT_TARGETBODY:
|
case mjCAMLIGHT_TARGETBODY:
|
||||||
case mjCAMLIGHT_TARGETBODYCOM:
|
case mjCAMLIGHT_TARGETBODYCOM:
|
||||||
// only if target body is specified
|
// only if target body is specified
|
||||||
if (id1>=0) {
|
if (id1 >= 0) {
|
||||||
// get position to look at
|
// get position to look at
|
||||||
if (m->cam_mode[i]==mjCAMLIGHT_TARGETBODY) {
|
if (m->cam_mode[i] == mjCAMLIGHT_TARGETBODY) {
|
||||||
mju_copy3(pos, d->xpos+3*id1);
|
mju_copy3(pos, d->xpos+3*id1);
|
||||||
} else {
|
} else {
|
||||||
mju_copy3(pos, d->subtree_com+3*id1);
|
mju_copy3(pos, d->subtree_com+3*id1);
|
||||||
@@ -328,7 +328,7 @@ void mj_camlight(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute Cartesian positions and directions of lights
|
// compute Cartesian positions and directions of lights
|
||||||
for (int i=0; i<m->nlight; i++) {
|
for (int i=0; i < m->nlight; i++) {
|
||||||
// default processing for fixed mode
|
// default processing for fixed mode
|
||||||
mj_local2Global(d, d->light_xpos+3*i, 0, m->light_pos+3*i, 0, m->light_bodyid[i], 0);
|
mj_local2Global(d, d->light_xpos+3*i, 0, m->light_pos+3*i, 0, m->light_bodyid[i], 0);
|
||||||
mju_rotVecQuat(d->light_xdir+3*i, m->light_dir+3*i, d->xquat+4*m->light_bodyid[i]);
|
mju_rotVecQuat(d->light_xdir+3*i, m->light_dir+3*i, d->xquat+4*m->light_bodyid[i]);
|
||||||
@@ -345,7 +345,7 @@ void mj_camlight(const mjModel* m, mjData* d) {
|
|||||||
mju_copy3(d->light_xdir+3*i, m->light_dir0+3*i);
|
mju_copy3(d->light_xdir+3*i, m->light_dir0+3*i);
|
||||||
|
|
||||||
// position: track light body
|
// position: track light body
|
||||||
if (m->light_mode[i]==mjCAMLIGHT_TRACK) {
|
if (m->light_mode[i] == mjCAMLIGHT_TRACK) {
|
||||||
mju_add3(d->light_xpos+3*i, d->xpos+3*id, m->light_pos0+3*i);
|
mju_add3(d->light_xpos+3*i, d->xpos+3*id, m->light_pos0+3*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,9 +358,9 @@ void mj_camlight(const mjModel* m, mjData* d) {
|
|||||||
case mjCAMLIGHT_TARGETBODY:
|
case mjCAMLIGHT_TARGETBODY:
|
||||||
case mjCAMLIGHT_TARGETBODYCOM:
|
case mjCAMLIGHT_TARGETBODYCOM:
|
||||||
// only if target body is specified
|
// only if target body is specified
|
||||||
if (id1>=0) {
|
if (id1 >= 0) {
|
||||||
// get position to look at
|
// get position to look at
|
||||||
if (m->light_mode[i]==mjCAMLIGHT_TARGETBODY) {
|
if (m->light_mode[i] == mjCAMLIGHT_TARGETBODY) {
|
||||||
mju_copy3(pos, d->xpos+3*id1);
|
mju_copy3(pos, d->xpos+3*id1);
|
||||||
} else {
|
} else {
|
||||||
mju_copy3(pos, d->subtree_com+3*id1);
|
mju_copy3(pos, d->subtree_com+3*id1);
|
||||||
@@ -416,7 +416,7 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// loop over tendons
|
// loop over tendons
|
||||||
for (int i=0; i<nten; i++) {
|
for (int i=0; i < nten; i++) {
|
||||||
// initialize tendon path
|
// initialize tendon path
|
||||||
adr = m->tendon_adr[i];
|
adr = m->tendon_adr[i];
|
||||||
d->ten_wrapadr[i] = wcnt;
|
d->ten_wrapadr[i] = wcnt;
|
||||||
@@ -424,13 +424,13 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// sparse Jacobian row init
|
// sparse Jacobian row init
|
||||||
if (issparse) {
|
if (issparse) {
|
||||||
rowadr[i] = (i>0 ? rowadr[i-1] + rownnz[i-1] : 0);
|
rowadr[i] = (i > 0 ? rowadr[i-1] + rownnz[i-1] : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process joint tendon
|
// process joint tendon
|
||||||
if (m->wrap_type[adr]==mjWRAP_JOINT) {
|
if (m->wrap_type[adr] == mjWRAP_JOINT) {
|
||||||
// process all defined joints
|
// process all defined joints
|
||||||
for (int j=0; j<m->tendon_num[i]; j++) {
|
for (int j=0; j < m->tendon_num[i]; j++) {
|
||||||
// get joint id
|
// get joint id
|
||||||
int k = m->wrap_objid[adr+j];
|
int k = m->wrap_objid[adr+j];
|
||||||
|
|
||||||
@@ -455,11 +455,11 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
int x, *list = colind+rowadr[i];
|
int x, *list = colind+rowadr[i];
|
||||||
mjtNum y, *listy = J+rowadr[i];
|
mjtNum y, *listy = J+rowadr[i];
|
||||||
|
|
||||||
for (int k=1; k<rownnz[i]; k++) {
|
for (int k=1; k < rownnz[i]; k++) {
|
||||||
x = list[k];
|
x = list[k];
|
||||||
y = listy[k];
|
y = listy[k];
|
||||||
int j = k-1;
|
int j = k-1;
|
||||||
while (j>=0 && list[j]>x) {
|
while (j >= 0 && list[j] > x) {
|
||||||
list[j+1] = list[j];
|
list[j+1] = list[j];
|
||||||
listy[j+1] = listy[j];
|
listy[j+1] = listy[j];
|
||||||
j--;
|
j--;
|
||||||
@@ -475,7 +475,7 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
// process spatial tendon
|
// process spatial tendon
|
||||||
divisor = 1;
|
divisor = 1;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
while (j<m->tendon_num[i]-1) {
|
while (j < m->tendon_num[i]-1) {
|
||||||
// get 1st and 2nd object
|
// get 1st and 2nd object
|
||||||
tp0 = m->wrap_type[adr+j];
|
tp0 = m->wrap_type[adr+j];
|
||||||
id0 = m->wrap_objid[adr+j];
|
id0 = m->wrap_objid[adr+j];
|
||||||
@@ -483,9 +483,9 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
id1 = m->wrap_objid[adr+j+1];
|
id1 = m->wrap_objid[adr+j+1];
|
||||||
|
|
||||||
// pulley
|
// pulley
|
||||||
if (tp0==mjWRAP_PULLEY || tp1==mjWRAP_PULLEY) {
|
if (tp0 == mjWRAP_PULLEY || tp1 == mjWRAP_PULLEY) {
|
||||||
// get divisor, insert obj=-2
|
// get divisor, insert obj=-2
|
||||||
if (tp0==mjWRAP_PULLEY) {
|
if (tp0 == mjWRAP_PULLEY) {
|
||||||
divisor = m->wrap_prm[adr+j];
|
divisor = m->wrap_prm[adr+j];
|
||||||
mju_zero3(d->wrap_xpos+wcnt*3);
|
mju_zero3(d->wrap_xpos+wcnt*3);
|
||||||
d->wrap_obj[wcnt] = -2;
|
d->wrap_obj[wcnt] = -2;
|
||||||
@@ -504,7 +504,7 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
wbody[0] = m->site_bodyid[id0];
|
wbody[0] = m->site_bodyid[id0];
|
||||||
|
|
||||||
// second object is geom: process site-geom-site
|
// second object is geom: process site-geom-site
|
||||||
if (tp1==mjWRAP_SPHERE || tp1==mjWRAP_CYLINDER) {
|
if (tp1 == mjWRAP_SPHERE || tp1 == mjWRAP_CYLINDER) {
|
||||||
// reassign, get 2nd site info
|
// reassign, get 2nd site info
|
||||||
tpw = tp1;
|
tpw = tp1;
|
||||||
idw = id1;
|
idw = id1;
|
||||||
@@ -513,19 +513,19 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// do wrapping, possibly get 2 extra points (wlen>=0)
|
// do wrapping, possibly get 2 extra points (wlen>=0)
|
||||||
sideid = mju_round(m->wrap_prm[adr+j+1]);
|
sideid = mju_round(m->wrap_prm[adr+j+1]);
|
||||||
if (sideid<-1 || sideid>=m->nsite) {
|
if (sideid < -1 || sideid >= m->nsite) {
|
||||||
mju_error("Invalid sideid %d in wrap_prm", sideid); // SHOULD NOT OCCUR
|
mju_error("Invalid sideid %d in wrap_prm", sideid); // SHOULD NOT OCCUR
|
||||||
}
|
}
|
||||||
|
|
||||||
wlen = mju_wrap(wpnt+3, d->site_xpos+3*id0, d->site_xpos+3*id1,
|
wlen = mju_wrap(wpnt+3, d->site_xpos+3*id0, d->site_xpos+3*id1,
|
||||||
d->geom_xpos+3*idw, d->geom_xmat+9*idw, m->geom_size+3*idw, tpw,
|
d->geom_xpos+3*idw, d->geom_xmat+9*idw, m->geom_size+3*idw, tpw,
|
||||||
(sideid>=0 ? d->site_xpos+3*sideid : 0));
|
(sideid >= 0 ? d->site_xpos+3*sideid : 0));
|
||||||
} else {
|
} else {
|
||||||
tpw = mjWRAP_NONE;
|
tpw = mjWRAP_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete sequence, accumulate lengths
|
// complete sequence, accumulate lengths
|
||||||
if (wlen<0) {
|
if (wlen < 0) {
|
||||||
mju_copy3(wpnt+3, d->site_xpos+3*id1);
|
mju_copy3(wpnt+3, d->site_xpos+3*id1);
|
||||||
wbody[1] = m->site_bodyid[id1];
|
wbody[1] = m->site_bodyid[id1];
|
||||||
L[i] += mju_dist3(wpnt, wpnt+3)/divisor;
|
L[i] += mju_dist3(wpnt, wpnt+3)/divisor;
|
||||||
@@ -537,8 +537,8 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// accumulate moments if consequtive points are in different bodies
|
// accumulate moments if consequtive points are in different bodies
|
||||||
for (int k=0; k<(wlen<0 ? 1 : 3); k++) {
|
for (int k=0; k < (wlen < 0 ? 1 : 3); k++) {
|
||||||
if (wbody[k]!=wbody[k+1]) {
|
if (wbody[k] != wbody[k+1]) {
|
||||||
// get 3D position difference, normalize
|
// get 3D position difference, normalize
|
||||||
mju_sub3(dif, wpnt+3*k+3, wpnt+3*k);
|
mju_sub3(dif, wpnt+3*k+3, wpnt+3*k);
|
||||||
mju_normalize3(dif);
|
mju_normalize3(dif);
|
||||||
@@ -581,19 +581,19 @@ void mj_tendon(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// assign to wrap
|
// assign to wrap
|
||||||
mju_copy(d->wrap_xpos+wcnt*3, wpnt, (wlen<0 ? 3:9));
|
mju_copy(d->wrap_xpos+wcnt*3, wpnt, (wlen < 0 ? 3:9));
|
||||||
d->wrap_obj[wcnt] = -1;
|
d->wrap_obj[wcnt] = -1;
|
||||||
if (wlen>=0) {
|
if (wlen >= 0) {
|
||||||
d->wrap_obj[wcnt+1] = d->wrap_obj[wcnt+2] = idw;
|
d->wrap_obj[wcnt+1] = d->wrap_obj[wcnt+2] = idw;
|
||||||
}
|
}
|
||||||
d->ten_wrapnum[i] += (wlen<0 ? 1:3);
|
d->ten_wrapnum[i] += (wlen < 0 ? 1:3);
|
||||||
wcnt += (wlen<0 ? 1:3);
|
wcnt += (wlen < 0 ? 1:3);
|
||||||
|
|
||||||
// advance
|
// advance
|
||||||
j += (tpw!=mjWRAP_NONE ? 2 : 1);
|
j += (tpw != mjWRAP_NONE ? 2 : 1);
|
||||||
|
|
||||||
// assign last site before pulley or tendon end
|
// assign last site before pulley or tendon end
|
||||||
if (j==m->tendon_num[i]-1 || m->wrap_type[adr+j+1]==mjWRAP_PULLEY) {
|
if (j == m->tendon_num[i]-1 || m->wrap_type[adr+j+1] == mjWRAP_PULLEY) {
|
||||||
mju_copy3(d->wrap_xpos+wcnt*3, d->site_xpos+3*id1);
|
mju_copy3(d->wrap_xpos+wcnt*3, d->site_xpos+3*id1);
|
||||||
d->wrap_obj[wcnt] = -1;
|
d->wrap_obj[wcnt] = -1;
|
||||||
d->ten_wrapnum[i]++;
|
d->ten_wrapnum[i]++;
|
||||||
@@ -634,7 +634,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
int *chain;
|
int *chain;
|
||||||
|
|
||||||
// compute lengths and moments
|
// compute lengths and moments
|
||||||
for (int i=0; i<nu; i++) {
|
for (int i=0; i < nu; i++) {
|
||||||
// extract info
|
// extract info
|
||||||
id = m->actuator_trnid[2*i];
|
id = m->actuator_trnid[2*i];
|
||||||
idslider = m->actuator_trnid[2*i+1]; // for slider-crank only
|
idslider = m->actuator_trnid[2*i+1]; // for slider-crank only
|
||||||
@@ -645,13 +645,13 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
case mjTRN_JOINT: // joint
|
case mjTRN_JOINT: // joint
|
||||||
case mjTRN_JOINTINPARENT: // joint, force in parent frame
|
case mjTRN_JOINTINPARENT: // joint, force in parent frame
|
||||||
// slide and hinge joint: scalar gear
|
// slide and hinge joint: scalar gear
|
||||||
if (m->jnt_type[id]==mjJNT_SLIDE || m->jnt_type[id]==mjJNT_HINGE) {
|
if (m->jnt_type[id] == mjJNT_SLIDE || m->jnt_type[id] == mjJNT_HINGE) {
|
||||||
length[i] = d->qpos[m->jnt_qposadr[id]]*gear[0];
|
length[i] = d->qpos[m->jnt_qposadr[id]]*gear[0];
|
||||||
moment[i*nv + m->jnt_dofadr[id]] = gear[0];
|
moment[i*nv + m->jnt_dofadr[id]] = gear[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ball joint: 3D wrench gear
|
// ball joint: 3D wrench gear
|
||||||
else if (m->jnt_type[id]==mjJNT_BALL) {
|
else if (m->jnt_type[id] == mjJNT_BALL) {
|
||||||
// j: qpos start address
|
// j: qpos start address
|
||||||
int j = m->jnt_qposadr[id];
|
int j = m->jnt_qposadr[id];
|
||||||
|
|
||||||
@@ -659,7 +659,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
mju_quat2Vel(axis, d->qpos+j, 1);
|
mju_quat2Vel(axis, d->qpos+j, 1);
|
||||||
|
|
||||||
// gearAxis: rotate to parent frame if necessary
|
// gearAxis: rotate to parent frame if necessary
|
||||||
if (m->actuator_trntype[i]==mjTRN_JOINT) {
|
if (m->actuator_trntype[i] == mjTRN_JOINT) {
|
||||||
mju_copy3(gearAxis, gear);
|
mju_copy3(gearAxis, gear);
|
||||||
} else {
|
} else {
|
||||||
mju_negQuat(quat, d->qpos+j);
|
mju_negQuat(quat, d->qpos+j);
|
||||||
@@ -691,7 +691,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
mju_quat2Vel(axis, d->qpos+j+3, 1);
|
mju_quat2Vel(axis, d->qpos+j+3, 1);
|
||||||
|
|
||||||
// gearAxis: rotate to world frame if necessary
|
// gearAxis: rotate to world frame if necessary
|
||||||
if (m->actuator_trntype[i]==mjTRN_JOINT) {
|
if (m->actuator_trntype[i] == mjTRN_JOINT) {
|
||||||
mju_copy3(gearAxis, gear+3);
|
mju_copy3(gearAxis, gear+3);
|
||||||
} else {
|
} else {
|
||||||
mju_negQuat(quat, d->qpos+j+3);
|
mju_negQuat(quat, d->qpos+j+3);
|
||||||
@@ -720,7 +720,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
av = mju_dot3(vec, axis);
|
av = mju_dot3(vec, axis);
|
||||||
det = av*av + rod*rod - mju_dot3(vec, vec);
|
det = av*av + rod*rod - mju_dot3(vec, vec);
|
||||||
ok = 1;
|
ok = 1;
|
||||||
if (det<=0) {
|
if (det <= 0) {
|
||||||
ok = 0;
|
ok = 0;
|
||||||
sdet = 0;
|
sdet = 0;
|
||||||
length[i] = av;
|
length[i] = av;
|
||||||
@@ -748,15 +748,15 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
mju_subFrom(jac, jacS, 3*nv);
|
mju_subFrom(jac, jacS, 3*nv);
|
||||||
|
|
||||||
// apply chain rule
|
// apply chain rule
|
||||||
for (int j=0; j<nv; j++) {
|
for (int j=0; j < nv; j++) {
|
||||||
for (int k=0; k<3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
moment[i*nv+j] += dlda[k]*jacA[k*nv+j] + dldv[k]*jac[k*nv+j];
|
moment[i*nv+j] += dlda[k]*jacA[k*nv+j] + dldv[k]*jac[k*nv+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale by gear ratio
|
// scale by gear ratio
|
||||||
length[i] *= gear[0];
|
length[i] *= gear[0];
|
||||||
for (int j = 0; j<nv; j++) {
|
for (int j = 0; j < nv; j++) {
|
||||||
moment[i*nv + j] *= gear[0];
|
moment[i*nv + j] *= gear[0];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -767,7 +767,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
// moment: sparse or dense
|
// moment: sparse or dense
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
int end = d->ten_J_rowadr[id] + d->ten_J_rownnz[id];
|
int end = d->ten_J_rowadr[id] + d->ten_J_rownnz[id];
|
||||||
for (int j=d->ten_J_rowadr[id]; j<end; j++) {
|
for (int j=d->ten_J_rowadr[id]; j < end; j++) {
|
||||||
moment[i*nv + d->ten_J_colind[j]] = d->ten_J[j] * gear[0];
|
moment[i*nv + d->ten_J_colind[j]] = d->ten_J[j] * gear[0];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -878,7 +878,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// count all relevant contacts, accumulate Jacobians
|
// count all relevant contacts, accumulate Jacobians
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (int j=0; j<d->ncon; j++) {
|
for (int j=0; j < d->ncon; j++) {
|
||||||
const mjContact* con = d->contact+j;
|
const mjContact* con = d->contact+j;
|
||||||
int b1 = m->geom_bodyid[con->geom1];
|
int b1 = m->geom_bodyid[con->geom1];
|
||||||
int b2 = m->geom_bodyid[con->geom2];
|
int b2 = m->geom_bodyid[con->geom2];
|
||||||
@@ -893,14 +893,14 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
counter++;
|
counter++;
|
||||||
|
|
||||||
// condim 1 or elliptic cones: normal is in the first row
|
// condim 1 or elliptic cones: normal is in the first row
|
||||||
if (con->dim == 1 || m->opt.cone==mjCONE_ELLIPTIC) {
|
if (con->dim == 1 || m->opt.cone == mjCONE_ELLIPTIC) {
|
||||||
efc_force[con->efc_address] = 1;
|
efc_force[con->efc_address] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pyramidal cones: average all pyramid directions
|
// pyramidal cones: average all pyramid directions
|
||||||
else {
|
else {
|
||||||
int npyramid = con->dim-1; // number of frictional directions
|
int npyramid = con->dim-1; // number of frictional directions
|
||||||
for (int k=0; k<2*npyramid; k++) {
|
for (int k=0; k < 2*npyramid; k++) {
|
||||||
efc_force[con->efc_address+k] = 0.5/npyramid;
|
efc_force[con->efc_address+k] = 0.5/npyramid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -919,7 +919,7 @@ void mj_transmission(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// accumulate in moment_exclude
|
// accumulate in moment_exclude
|
||||||
if (issparse) {
|
if (issparse) {
|
||||||
for (int k=0; k<NV; k++) {
|
for (int k=0; k < NV; k++) {
|
||||||
moment_exclude[chain[k]] += jac[k];
|
moment_exclude[chain[k]] += jac[k];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -963,8 +963,8 @@ void mj_crbSkip(const mjModel* m, mjData* d, int skipsimple) {
|
|||||||
mju_copy(crb, d->cinert, 10*m->nbody);
|
mju_copy(crb, d->cinert, 10*m->nbody);
|
||||||
|
|
||||||
// backward pass over bodies, accumulate composite inertias
|
// backward pass over bodies, accumulate composite inertias
|
||||||
for (int i=m->nbody-1; i>0; i--) {
|
for (int i=m->nbody-1; i > 0; i--) {
|
||||||
if (m->body_parentid[i]>0) {
|
if (m->body_parentid[i] > 0) {
|
||||||
mju_addTo(crb+10*m->body_parentid[i], crb+10*i, 10);
|
mju_addTo(crb+10*m->body_parentid[i], crb+10*i, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -973,7 +973,7 @@ void mj_crbSkip(const mjModel* m, mjData* d, int skipsimple) {
|
|||||||
mju_zero(d->qM, m->nM);
|
mju_zero(d->qM, m->nM);
|
||||||
|
|
||||||
// dense backward pass over dofs
|
// dense backward pass over dofs
|
||||||
for (int i=m->nv-1; i>=0; i--) {
|
for (int i=m->nv-1; i >= 0; i--) {
|
||||||
// copy
|
// copy
|
||||||
if (skipsimple && m->dof_simplenum[i]) {
|
if (skipsimple && m->dof_simplenum[i]) {
|
||||||
d->qM[m->dof_Madr[i]] = m->dof_M0[i];
|
d->qM[m->dof_Madr[i]] = m->dof_M0[i];
|
||||||
@@ -990,7 +990,7 @@ void mj_crbSkip(const mjModel* m, mjData* d, int skipsimple) {
|
|||||||
|
|
||||||
// sparse backward pass over ancestors
|
// sparse backward pass over ancestors
|
||||||
int j = i;
|
int j = i;
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
// M(i,j) += cdof_j * crb_body(i) * cdof_i = cdof_j * tmp
|
// M(i,j) += cdof_j * crb_body(i) * cdof_i = cdof_j * tmp
|
||||||
d->qM[Madr_ij] += mju_dot(d->cdof+6*j, tmp, 6);
|
d->qM[Madr_ij] += mju_dot(d->cdof+6*j, tmp, 6);
|
||||||
|
|
||||||
@@ -1027,12 +1027,12 @@ void mj_factorI(const mjModel* m, mjData* d, const mjtNum* M, mjtNum* qLD, mjtNu
|
|||||||
mju_copy(qLD, M, m->nM);
|
mju_copy(qLD, M, m->nM);
|
||||||
|
|
||||||
// dense backward loop over dofs (regular only, simple diagonal already copied)
|
// dense backward loop over dofs (regular only, simple diagonal already copied)
|
||||||
for (int k=nv-1; k>=0; k--) {
|
for (int k=nv-1; k >= 0; k--) {
|
||||||
// get address of M(k,k)
|
// get address of M(k,k)
|
||||||
Madr_kk = dof_Madr[k];
|
Madr_kk = dof_Madr[k];
|
||||||
|
|
||||||
// check for small/negative numbers on diagonal
|
// check for small/negative numbers on diagonal
|
||||||
if (qLD[Madr_kk]<mjMINVAL) {
|
if (qLD[Madr_kk] < mjMINVAL) {
|
||||||
mj_warning(d, mjWARN_INERTIA, k);
|
mj_warning(d, mjWARN_INERTIA, k);
|
||||||
qLD[Madr_kk] = mjMINVAL;
|
qLD[Madr_kk] = mjMINVAL;
|
||||||
}
|
}
|
||||||
@@ -1045,11 +1045,11 @@ void mj_factorI(const mjModel* m, mjData* d, const mjtNum* M, mjtNum* qLD, mjtNu
|
|||||||
// sparse backward loop over ancestors of k (excluding k)
|
// sparse backward loop over ancestors of k (excluding k)
|
||||||
Madr_ki = Madr_kk + 1;
|
Madr_ki = Madr_kk + 1;
|
||||||
int i = dof_parentid[k];
|
int i = dof_parentid[k];
|
||||||
while (i>=0) {
|
while (i >= 0) {
|
||||||
tmp = qLD[Madr_ki] / qLD[Madr_kk]; // tmp = M(k,i) / M(k,k)
|
tmp = qLD[Madr_ki] / qLD[Madr_kk]; // tmp = M(k,i) / M(k,k)
|
||||||
|
|
||||||
// get number of ancestors of i (including i)
|
// get number of ancestors of i (including i)
|
||||||
if (i<nv-1) {
|
if (i < nv-1) {
|
||||||
cnt = dof_Madr[i+1] - dof_Madr[i];
|
cnt = dof_Madr[i+1] - dof_Madr[i];
|
||||||
} else {
|
} else {
|
||||||
cnt = m->nM - dof_Madr[i+1];
|
cnt = m->nM - dof_Madr[i+1];
|
||||||
@@ -1067,7 +1067,7 @@ void mj_factorI(const mjModel* m, mjData* d, const mjtNum* M, mjtNum* qLD, mjtNu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute 1/diag(D), 1/sqrt(diag(D))
|
// compute 1/diag(D), 1/sqrt(diag(D))
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
mjtNum qLDi = qLD[dof_Madr[i]];
|
mjtNum qLDi = qLD[dof_Madr[i]];
|
||||||
qLDiagInv[i] = 1.0/qLDi;
|
qLDiagInv[i] = 1.0/qLDi;
|
||||||
if (qLDiagSqrtInv) {
|
if (qLDiagSqrtInv) {
|
||||||
@@ -1096,9 +1096,9 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
|
|||||||
int nv = m->nv;
|
int nv = m->nv;
|
||||||
|
|
||||||
// single vector
|
// single vector
|
||||||
if (n==1) {
|
if (n == 1) {
|
||||||
// x <- inv(L') * x; skip simple, exploit sparsity of input vector
|
// x <- inv(L') * x; skip simple, exploit sparsity of input vector
|
||||||
for (int i=nv-1; i>=0; i--) {
|
for (int i=nv-1; i >= 0; i--) {
|
||||||
if (!m->dof_simplenum[i] && x[i]) {
|
if (!m->dof_simplenum[i] && x[i]) {
|
||||||
// init
|
// init
|
||||||
int Madr_ij = dof_Madr[i]+1;
|
int Madr_ij = dof_Madr[i]+1;
|
||||||
@@ -1106,7 +1106,7 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
|
|||||||
|
|
||||||
// traverse ancestors backwards
|
// traverse ancestors backwards
|
||||||
// read directly from x[i] since i cannot be a parent of itself
|
// read directly from x[i] since i cannot be a parent of itself
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
x[j] -= qLD[Madr_ij++]*x[i]; // x(j) -= L(i,j) * x(i)
|
x[j] -= qLD[Madr_ij++]*x[i]; // x(j) -= L(i,j) * x(i)
|
||||||
|
|
||||||
// advance to parent
|
// advance to parent
|
||||||
@@ -1116,12 +1116,12 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// x <- inv(D) * x
|
// x <- inv(D) * x
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
x[i] *= qLDiagInv[i]; // x(i) /= L(i,i)
|
x[i] *= qLDiagInv[i]; // x(i) /= L(i,i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// x <- inv(L) * x; skip simple
|
// x <- inv(L) * x; skip simple
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
if (!m->dof_simplenum[i]) {
|
if (!m->dof_simplenum[i]) {
|
||||||
// init
|
// init
|
||||||
int Madr_ij = dof_Madr[i]+1;
|
int Madr_ij = dof_Madr[i]+1;
|
||||||
@@ -1129,7 +1129,7 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
|
|||||||
|
|
||||||
// traverse ancestors backwards
|
// traverse ancestors backwards
|
||||||
// write directly in x[i] since i cannot be a parent of itself
|
// write directly in x[i] since i cannot be a parent of itself
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
x[i] -= qLD[Madr_ij++]*x[j]; // x(i) -= L(i,j) * x(j)
|
x[i] -= qLD[Madr_ij++]*x[j]; // x(i) -= L(i,j) * x(j)
|
||||||
|
|
||||||
// advance to parent
|
// advance to parent
|
||||||
@@ -1145,16 +1145,16 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
|
|||||||
mjtNum tmp;
|
mjtNum tmp;
|
||||||
|
|
||||||
// x <- inv(L') * x; skip simple
|
// x <- inv(L') * x; skip simple
|
||||||
for (int i=nv-1; i>=0; i--) {
|
for (int i=nv-1; i >= 0; i--) {
|
||||||
if (!m->dof_simplenum[i]) {
|
if (!m->dof_simplenum[i]) {
|
||||||
// init
|
// init
|
||||||
int Madr_ij = dof_Madr[i]+1;
|
int Madr_ij = dof_Madr[i]+1;
|
||||||
int j = dof_parentid[i];
|
int j = dof_parentid[i];
|
||||||
|
|
||||||
// traverse ancestors backwards
|
// traverse ancestors backwards
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
// process all vectors, exploit sparsity
|
// process all vectors, exploit sparsity
|
||||||
for (offset=0; offset<n*nv; offset+=nv)
|
for (offset=0; offset < n*nv; offset+=nv)
|
||||||
if ((tmp = x[i+offset])) {
|
if ((tmp = x[i+offset])) {
|
||||||
x[j+offset] -= qLD[Madr_ij]*tmp; // x(j) -= L(i,j) * x(i)
|
x[j+offset] -= qLD[Madr_ij]*tmp; // x(j) -= L(i,j) * x(i)
|
||||||
}
|
}
|
||||||
@@ -1167,14 +1167,14 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// x <- inv(D) * x
|
// x <- inv(D) * x
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
for (offset=0; offset<n*nv; offset+=nv) {
|
for (offset=0; offset < n*nv; offset+=nv) {
|
||||||
x[i+offset] *= qLDiagInv[i]; // x(i) /= L(i,i)
|
x[i+offset] *= qLDiagInv[i]; // x(i) /= L(i,i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// x <- inv(L) * x; skip simple
|
// x <- inv(L) * x; skip simple
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
if (!m->dof_simplenum[i]) {
|
if (!m->dof_simplenum[i]) {
|
||||||
// init
|
// init
|
||||||
int Madr_ij = dof_Madr[i]+1;
|
int Madr_ij = dof_Madr[i]+1;
|
||||||
@@ -1182,9 +1182,9 @@ void mj_solveLD(const mjModel* m, mjtNum* restrict x, int n,
|
|||||||
|
|
||||||
// traverse ancestors backwards
|
// traverse ancestors backwards
|
||||||
tmp = x[i+offset];
|
tmp = x[i+offset];
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
// process all vectors
|
// process all vectors
|
||||||
for (offset=0; offset<n*nv; offset+=nv) {
|
for (offset=0; offset < n*nv; offset+=nv) {
|
||||||
x[i+offset] -= qLD[Madr_ij]*x[j+offset]; // x(i) -= L(i,j) * x(j)
|
x[i+offset] -= qLD[Madr_ij]*x[j+offset]; // x(i) -= L(i,j) * x(j)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1222,11 +1222,11 @@ void mj_solveM2(const mjModel* m, mjData* d, mjtNum* x, const mjtNum* y, int n)
|
|||||||
mju_copy(x, y, n * nv);
|
mju_copy(x, y, n * nv);
|
||||||
|
|
||||||
// loop over the n input vectors
|
// loop over the n input vectors
|
||||||
for (int ivec=0; ivec<n; ivec++) {
|
for (int ivec=0; ivec < n; ivec++) {
|
||||||
int offset = ivec*nv;
|
int offset = ivec*nv;
|
||||||
|
|
||||||
// x <- inv(L') * x; skip simple, exploit sparsity of input vector
|
// x <- inv(L') * x; skip simple, exploit sparsity of input vector
|
||||||
for (int i=nv-1; i>=0; i--) {
|
for (int i=nv-1; i >= 0; i--) {
|
||||||
mjtNum tmp;
|
mjtNum tmp;
|
||||||
if (!m->dof_simplenum[i] && (tmp = x[i+offset])) {
|
if (!m->dof_simplenum[i] && (tmp = x[i+offset])) {
|
||||||
// init
|
// init
|
||||||
@@ -1234,7 +1234,7 @@ void mj_solveM2(const mjModel* m, mjData* d, mjtNum* x, const mjtNum* y, int n)
|
|||||||
int j = dof_parentid[i];
|
int j = dof_parentid[i];
|
||||||
|
|
||||||
// traverse ancestors backwards
|
// traverse ancestors backwards
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
x[j+offset] -= qLD[Madr_ij++] * tmp; // x(j) -= L(i,j) * x(i)
|
x[j+offset] -= qLD[Madr_ij++] * tmp; // x(j) -= L(i,j) * x(i)
|
||||||
|
|
||||||
// advance to parent
|
// advance to parent
|
||||||
@@ -1244,7 +1244,7 @@ void mj_solveM2(const mjModel* m, mjData* d, mjtNum* x, const mjtNum* y, int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// x <- sqrt(inv(D)) * x
|
// x <- sqrt(inv(D)) * x
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
x[i+offset] *= qLDiagSqrtInv[i]; // x(i) /= sqrt(L(i,i))
|
x[i+offset] *= qLDiagSqrtInv[i]; // x(i) /= sqrt(L(i,i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1262,7 +1262,7 @@ void mj_comVel(const mjModel* m, mjData* d) {
|
|||||||
mju_zero(d->cvel, 6);
|
mju_zero(d->cvel, 6);
|
||||||
|
|
||||||
// forward pass over bodies
|
// forward pass over bodies
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
// get body's first dof address
|
// get body's first dof address
|
||||||
int bda = m->body_dofadr[i];
|
int bda = m->body_dofadr[i];
|
||||||
|
|
||||||
@@ -1270,7 +1270,7 @@ void mj_comVel(const mjModel* m, mjData* d) {
|
|||||||
mju_copy(cvel, d->cvel+6*m->body_parentid[i], 6);
|
mju_copy(cvel, d->cvel+6*m->body_parentid[i], 6);
|
||||||
|
|
||||||
// cvel = cvel_parent + cdof * qvel, cdofdot = cvel x cdof
|
// cvel = cvel_parent + cdof * qvel, cdofdot = cvel x cdof
|
||||||
for (int j=0; j<m->body_dofnum[i]; j++) {
|
for (int j=0; j < m->body_dofnum[i]; j++) {
|
||||||
// compute cvel and cdofdot
|
// compute cvel and cdofdot
|
||||||
switch (m->jnt_type[m->dof_jntid[bda+j]]) {
|
switch (m->jnt_type[m->dof_jntid[bda+j]]) {
|
||||||
case mjJNT_FREE:
|
case mjJNT_FREE:
|
||||||
@@ -1287,7 +1287,7 @@ void mj_comVel(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
case mjJNT_BALL:
|
case mjJNT_BALL:
|
||||||
// compute all 3 cdofdots using parent velocity
|
// compute all 3 cdofdots using parent velocity
|
||||||
for (int k=0; k<3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
mju_crossMotion(cdofdot+6*(j+k), cvel, d->cdof+6*(bda+j+k));
|
mju_crossMotion(cdofdot+6*(j+k), cvel, d->cdof+6*(bda+j+k));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1326,7 +1326,7 @@ void mj_subtreeVel(const mjModel* m, mjData* d) {
|
|||||||
mjtNum* body_vel = mj_stackAlloc(d, 6*m->nbody);
|
mjtNum* body_vel = mj_stackAlloc(d, 6*m->nbody);
|
||||||
|
|
||||||
// bodywise quantities
|
// bodywise quantities
|
||||||
for (int i=0; i<m->nbody; i++) {
|
for (int i=0; i < m->nbody; i++) {
|
||||||
// compute and save body velocity
|
// compute and save body velocity
|
||||||
mj_objectVelocity(m, d, mjOBJ_BODY, i, body_vel+6*i, 0);
|
mj_objectVelocity(m, d, mjOBJ_BODY, i, body_vel+6*i, 0);
|
||||||
|
|
||||||
@@ -1342,7 +1342,7 @@ void mj_subtreeVel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// subtree linvel
|
// subtree linvel
|
||||||
for (int i=m->nbody-1; i>=0; i--) {
|
for (int i=m->nbody-1; i >= 0; i--) {
|
||||||
// non-world: add linear momentum to parent
|
// non-world: add linear momentum to parent
|
||||||
if (i) {
|
if (i) {
|
||||||
mju_addTo3(d->subtree_linvel+3*m->body_parentid[i], d->subtree_linvel+3*i);
|
mju_addTo3(d->subtree_linvel+3*m->body_parentid[i], d->subtree_linvel+3*i);
|
||||||
@@ -1354,7 +1354,7 @@ void mj_subtreeVel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// subtree angmom
|
// subtree angmom
|
||||||
for (int i=m->nbody-1; i>0; i--) {
|
for (int i=m->nbody-1; i > 0; i--) {
|
||||||
int parent = m->body_parentid[i];
|
int parent = m->body_parentid[i];
|
||||||
|
|
||||||
// momentum wrt body i
|
// momentum wrt body i
|
||||||
@@ -1399,7 +1399,7 @@ void mj_rne(const mjModel* m, mjData* d, int flg_acc, mjtNum* result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// forward pass over bodies: accumulate cacc, set cfrc_body
|
// forward pass over bodies: accumulate cacc, set cfrc_body
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
// get body's first dof address
|
// get body's first dof address
|
||||||
int bda = m->body_dofadr[i];
|
int bda = m->body_dofadr[i];
|
||||||
|
|
||||||
@@ -1424,13 +1424,13 @@ void mj_rne(const mjModel* m, mjData* d, int flg_acc, mjtNum* result) {
|
|||||||
mju_zero(loc_cfrc_body, 6);
|
mju_zero(loc_cfrc_body, 6);
|
||||||
|
|
||||||
// backward pass over bodies: accumulate cfrc_body from children
|
// backward pass over bodies: accumulate cfrc_body from children
|
||||||
for (int i=m->nbody-1; i>0; i--)
|
for (int i=m->nbody-1; i > 0; i--)
|
||||||
if (m->body_parentid[i]) {
|
if (m->body_parentid[i]) {
|
||||||
mju_addTo(loc_cfrc_body+6*m->body_parentid[i], loc_cfrc_body+6*i, 6);
|
mju_addTo(loc_cfrc_body+6*m->body_parentid[i], loc_cfrc_body+6*i, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
// result = cdof * cfrc_body
|
// result = cdof * cfrc_body
|
||||||
for (int i=0; i<m->nv; i++) {
|
for (int i=0; i < m->nv; i++) {
|
||||||
result[i] = mju_dot(d->cdof+6*i, loc_cfrc_body+6*m->dof_bodyid[i], 6);
|
result[i] = mju_dot(d->cdof+6*i, loc_cfrc_body+6*m->dof_bodyid[i], 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1453,7 +1453,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// cfrc_ext = perturb
|
// cfrc_ext = perturb
|
||||||
mju_zero(d->cfrc_ext, 6*nbody);
|
mju_zero(d->cfrc_ext, 6*nbody);
|
||||||
for (int i=1; i<nbody; i++)
|
for (int i=1; i < nbody; i++)
|
||||||
if (!mju_isZero(d->xfrc_applied+6*i, 6)) {
|
if (!mju_isZero(d->xfrc_applied+6*i, 6)) {
|
||||||
// rearrange as torque:force
|
// rearrange as torque:force
|
||||||
mju_copy3(cfrc, d->xfrc_applied+6*i+3);
|
mju_copy3(cfrc, d->xfrc_applied+6*i+3);
|
||||||
@@ -1467,8 +1467,8 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cfrc_ext += contacts
|
// cfrc_ext += contacts
|
||||||
for (int i=0; i<d->ncon; i++)
|
for (int i=0; i < d->ncon; i++)
|
||||||
if (d->contact[i].efc_address>=0) {
|
if (d->contact[i].efc_address >= 0) {
|
||||||
// get contact pointer
|
// get contact pointer
|
||||||
con = d->contact+i;
|
con = d->contact+i;
|
||||||
|
|
||||||
@@ -1502,7 +1502,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
// cfrc_ext += connect and weld constraints
|
// cfrc_ext += connect and weld constraints
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < d->ne) {
|
while (i < d->ne) {
|
||||||
if (d->efc_type[i]!=mjCNSTR_EQUALITY)
|
if (d->efc_type[i] != mjCNSTR_EQUALITY)
|
||||||
mju_error("Row %d of efc is not an equality constraint", i); // SHOULD NOT OCCUR
|
mju_error("Row %d of efc is not an equality constraint", i); // SHOULD NOT OCCUR
|
||||||
|
|
||||||
int id = d->efc_id[i];
|
int id = d->efc_id[i];
|
||||||
@@ -1514,7 +1514,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
case mjEQ_WELD:
|
case mjEQ_WELD:
|
||||||
// cfrc = world-oriented torque:force vector
|
// cfrc = world-oriented torque:force vector
|
||||||
mju_copy3(cfrc + 3, d->efc_force + i);
|
mju_copy3(cfrc + 3, d->efc_force + i);
|
||||||
if (m->eq_type[id]==mjEQ_WELD) {
|
if (m->eq_type[id] == mjEQ_WELD) {
|
||||||
mju_copy3(cfrc, d->efc_force + i + 3);
|
mju_copy3(cfrc, d->efc_force + i + 3);
|
||||||
} else {
|
} else {
|
||||||
mju_zero3(cfrc); // no torque from connect
|
mju_zero3(cfrc); // no torque from connect
|
||||||
@@ -1523,7 +1523,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
// body 1
|
// body 1
|
||||||
if ((k = m->eq_obj1id[id])) {
|
if ((k = m->eq_obj1id[id])) {
|
||||||
// transform point on body1: local -> global
|
// transform point on body1: local -> global
|
||||||
mj_local2Global(d, pos, 0, eq_data + 3*(m->eq_type[id]==mjEQ_WELD), 0, k, 0);
|
mj_local2Global(d, pos, 0, eq_data + 3*(m->eq_type[id] == mjEQ_WELD), 0, k, 0);
|
||||||
|
|
||||||
// tmp = subtree CoM-based torque_force vector
|
// tmp = subtree CoM-based torque_force vector
|
||||||
mju_transformSpatial(cfrc_com, cfrc, 1, d->subtree_com+3*m->body_rootid[k], pos, 0);
|
mju_transformSpatial(cfrc_com, cfrc, 1, d->subtree_com+3*m->body_rootid[k], pos, 0);
|
||||||
@@ -1535,7 +1535,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
// body 2
|
// body 2
|
||||||
if ((k = m->eq_obj2id[id])) {
|
if ((k = m->eq_obj2id[id])) {
|
||||||
// transform point on body2: local -> global
|
// transform point on body2: local -> global
|
||||||
mj_local2Global(d, pos, 0, eq_data + 3*(m->eq_type[id]==mjEQ_CONNECT), 0, k, 0);
|
mj_local2Global(d, pos, 0, eq_data + 3*(m->eq_type[id] == mjEQ_CONNECT), 0, k, 0);
|
||||||
|
|
||||||
// tmp = subtree CoM-based torque_force vector
|
// tmp = subtree CoM-based torque_force vector
|
||||||
mju_transformSpatial(cfrc_com, cfrc, 1, d->subtree_com+3*m->body_rootid[k], pos, 0);
|
mju_transformSpatial(cfrc_com, cfrc, 1, d->subtree_com+3*m->body_rootid[k], pos, 0);
|
||||||
@@ -1545,7 +1545,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// increment rows
|
// increment rows
|
||||||
i += m->eq_type[id]==mjEQ_WELD ? 6 : 3;
|
i += m->eq_type[id] == mjEQ_WELD ? 6 : 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjEQ_JOINT:
|
case mjEQ_JOINT:
|
||||||
@@ -1562,7 +1562,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
// forward pass over bodies: compute cacc, cfrc_int
|
// forward pass over bodies: compute cacc, cfrc_int
|
||||||
mjtNum cacc[6], cfrc_body[6], cfrc_corr[6];
|
mjtNum cacc[6], cfrc_body[6], cfrc_corr[6];
|
||||||
mju_zero(d->cfrc_int, 6);
|
mju_zero(d->cfrc_int, 6);
|
||||||
for (int j=1; j<m->nbody; j++) {
|
for (int j=1; j < m->nbody; j++) {
|
||||||
// get body's first dof address
|
// get body's first dof address
|
||||||
int bda = m->body_dofadr[j];
|
int bda = m->body_dofadr[j];
|
||||||
|
|
||||||
@@ -1583,7 +1583,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// backward pass over bodies: accumulate cfrc_int from children
|
// backward pass over bodies: accumulate cfrc_int from children
|
||||||
for (int j=m->nbody-1; j>0; j--) {
|
for (int j=m->nbody-1; j > 0; j--) {
|
||||||
mju_addTo(d->cfrc_int+6*m->body_parentid[j], d->cfrc_int+6*j, 6);
|
mju_addTo(d->cfrc_int+6*m->body_parentid[j], d->cfrc_int+6*j, 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -280,19 +280,19 @@ static void mjd_comVel_vel_dense(const mjModel* m, mjData* d, mjtNum* Dcvel, mjt
|
|||||||
mju_zero(Dcvel, nbody*6*nv);
|
mju_zero(Dcvel, nbody*6*nv);
|
||||||
|
|
||||||
// forward pass over bodies: accumulate Dcvel, set Dcdofdot
|
// forward pass over bodies: accumulate Dcvel, set Dcdofdot
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
// Dcvel = Dcvel_parent
|
// Dcvel = Dcvel_parent
|
||||||
mju_copy(Dcvel+i*6*nv, Dcvel+m->body_parentid[i]*6*nv, 6*nv);
|
mju_copy(Dcvel+i*6*nv, Dcvel+m->body_parentid[i]*6*nv, 6*nv);
|
||||||
|
|
||||||
// Dcvel += D(cdof * qvel), Dcdofdot = D(cvel x cdof)
|
// Dcvel += D(cdof * qvel), Dcdofdot = D(cvel x cdof)
|
||||||
for (int j=m->body_dofadr[i]; j<m->body_dofadr[i]+m->body_dofnum[i]; j++) {
|
for (int j=m->body_dofadr[i]; j < m->body_dofadr[i]+m->body_dofnum[i]; j++) {
|
||||||
switch (m->jnt_type[m->dof_jntid[j]]) {
|
switch (m->jnt_type[m->dof_jntid[j]]) {
|
||||||
case mjJNT_FREE:
|
case mjJNT_FREE:
|
||||||
// Dcdofdot = 0
|
// Dcdofdot = 0
|
||||||
mju_zero(Dcdofdot+j*6*nv, 18*nv);
|
mju_zero(Dcdofdot+j*6*nv, 18*nv);
|
||||||
|
|
||||||
// Dcvel += cdof * (D qvel)
|
// Dcvel += cdof * (D qvel)
|
||||||
for (int k=0; k<6; k++) {
|
for (int k=0; k < 6; k++) {
|
||||||
Dcvel[i*6*nv + k*nv + j+0] += d->cdof[(j+0)*6 + k];
|
Dcvel[i*6*nv + k*nv + j+0] += d->cdof[(j+0)*6 + k];
|
||||||
Dcvel[i*6*nv + k*nv + j+1] += d->cdof[(j+1)*6 + k];
|
Dcvel[i*6*nv + k*nv + j+1] += d->cdof[(j+1)*6 + k];
|
||||||
Dcvel[i*6*nv + k*nv + j+2] += d->cdof[(j+2)*6 + k];
|
Dcvel[i*6*nv + k*nv + j+2] += d->cdof[(j+2)*6 + k];
|
||||||
@@ -304,13 +304,13 @@ static void mjd_comVel_vel_dense(const mjModel* m, mjData* d, mjtNum* Dcvel, mjt
|
|||||||
|
|
||||||
case mjJNT_BALL:
|
case mjJNT_BALL:
|
||||||
// Dcdofdot = D crossMotion(cvel, cdof)
|
// Dcdofdot = D crossMotion(cvel, cdof)
|
||||||
for (int k=0; k<3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
mjd_crossMotion_vel(mat, d->cdof+6*(j+k));
|
mjd_crossMotion_vel(mat, d->cdof+6*(j+k));
|
||||||
mju_mulMatMat(Dcdofdot+(j+k)*6*nv, mat, Dcvel+i*6*nv, 6, 6, nv);
|
mju_mulMatMat(Dcdofdot+(j+k)*6*nv, mat, Dcvel+i*6*nv, 6, 6, nv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dcvel += cdof * (D qvel)
|
// Dcvel += cdof * (D qvel)
|
||||||
for (int k=0; k<6; k++) {
|
for (int k=0; k < 6; k++) {
|
||||||
Dcvel[i*6*nv + k*nv + j+0] += d->cdof[(j+0)*6 + k];
|
Dcvel[i*6*nv + k*nv + j+0] += d->cdof[(j+0)*6 + k];
|
||||||
Dcvel[i*6*nv + k*nv + j+1] += d->cdof[(j+1)*6 + k];
|
Dcvel[i*6*nv + k*nv + j+1] += d->cdof[(j+1)*6 + k];
|
||||||
Dcvel[i*6*nv + k*nv + j+2] += d->cdof[(j+2)*6 + k];
|
Dcvel[i*6*nv + k*nv + j+2] += d->cdof[(j+2)*6 + k];
|
||||||
@@ -326,7 +326,7 @@ static void mjd_comVel_vel_dense(const mjModel* m, mjData* d, mjtNum* Dcvel, mjt
|
|||||||
mju_mulMatMat(Dcdofdot+j*6*nv, mat, Dcvel+i*6*nv, 6, 6, nv);
|
mju_mulMatMat(Dcdofdot+j*6*nv, mat, Dcvel+i*6*nv, 6, 6, nv);
|
||||||
|
|
||||||
// Dcvel += cdof * (D qvel)
|
// Dcvel += cdof * (D qvel)
|
||||||
for (int k=0; k<6; k++) {
|
for (int k=0; k < 6; k++) {
|
||||||
Dcvel[i*6*nv + k*nv + j] += d->cdof[j*6 + k];
|
Dcvel[i*6*nv + k*nv + j] += d->cdof[j*6 + k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,14 +355,14 @@ void mjd_rne_vel_dense(const mjModel* m, mjData* d) {
|
|||||||
mju_zero(Dcacc, nbody*6*nv);
|
mju_zero(Dcacc, nbody*6*nv);
|
||||||
|
|
||||||
// forward pass over bodies: accumulate Dcacc, set Dcfrcbody
|
// forward pass over bodies: accumulate Dcacc, set Dcfrcbody
|
||||||
for (int i=1; i<nbody; i++) {
|
for (int i=1; i < nbody; i++) {
|
||||||
// Dcacc = Dcacc_parent
|
// Dcacc = Dcacc_parent
|
||||||
mju_copy(Dcacc + i*6*nv, Dcacc + m->body_parentid[i]*6*nv, 6*nv);
|
mju_copy(Dcacc + i*6*nv, Dcacc + m->body_parentid[i]*6*nv, 6*nv);
|
||||||
|
|
||||||
// Dcacc += D(cdofdot * qvel)
|
// Dcacc += D(cdofdot * qvel)
|
||||||
for (int j=m->body_dofadr[i]; j<m->body_dofadr[i]+m->body_dofnum[i]; j++) {
|
for (int j=m->body_dofadr[i]; j < m->body_dofadr[i]+m->body_dofnum[i]; j++) {
|
||||||
// Dcacc += cdofdot * (D qvel)
|
// Dcacc += cdofdot * (D qvel)
|
||||||
for (int k=0; k<6; k++) {
|
for (int k=0; k < 6; k++) {
|
||||||
Dcacc[i*6*nv + k*nv + j] += d->cdof_dot[j*6 + k];
|
Dcacc[i*6*nv + k*nv + j] += d->cdof_dot[j*6 + k];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,21 +392,21 @@ void mjd_rne_vel_dense(const mjModel* m, mjData* d) {
|
|||||||
mju_zero(Dcfrcbody, 6*nv);
|
mju_zero(Dcfrcbody, 6*nv);
|
||||||
|
|
||||||
// backward pass over bodies: accumulate Dcfrcbody
|
// backward pass over bodies: accumulate Dcfrcbody
|
||||||
for (int i=m->nbody-1; i>0; i--) {
|
for (int i=m->nbody-1; i > 0; i--) {
|
||||||
if (m->body_parentid[i]) {
|
if (m->body_parentid[i]) {
|
||||||
mju_addTo(Dcfrcbody+m->body_parentid[i]*6*nv, Dcfrcbody+i*6*nv, 6*nv);
|
mju_addTo(Dcfrcbody+m->body_parentid[i]*6*nv, Dcfrcbody+i*6*nv, 6*nv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// qDeriv -= D(cdof * cfrc_body)
|
// qDeriv -= D(cdof * cfrc_body)
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
for (int k=0; k<6; k++) {
|
for (int k=0; k < 6; k++) {
|
||||||
// compute D(cdof * cfrc_body), store in row
|
// compute D(cdof * cfrc_body), store in row
|
||||||
mju_scl(row, Dcfrcbody + (m->dof_bodyid[i]*6+k)*nv, d->cdof[i*6+k], nv);
|
mju_scl(row, Dcfrcbody + (m->dof_bodyid[i]*6+k)*nv, d->cdof[i*6+k], nv);
|
||||||
|
|
||||||
// dense to sparse: qDeriv -= row
|
// dense to sparse: qDeriv -= row
|
||||||
int end = d->D_rowadr[i] + d->D_rownnz[i];
|
int end = d->D_rowadr[i] + d->D_rownnz[i];
|
||||||
for (int adr=d->D_rowadr[i]; adr<end; adr++) {
|
for (int adr=d->D_rowadr[i]; adr < end; adr++) {
|
||||||
d->qDeriv[adr] -= row[d->D_colind[adr]];
|
d->qDeriv[adr] -= row[d->D_colind[adr]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,7 +430,7 @@ static void copyFromParent(const mjModel* m, mjData* d, mjtNum* mat, int n) {
|
|||||||
// count dofs in ancestors
|
// count dofs in ancestors
|
||||||
int ndof = 0;
|
int ndof = 0;
|
||||||
int np = m->body_weldid[m->body_parentid[n]];
|
int np = m->body_weldid[m->body_parentid[n]];
|
||||||
while (np>0) {
|
while (np > 0) {
|
||||||
// add self dofs
|
// add self dofs
|
||||||
ndof += m->body_dofnum[np];
|
ndof += m->body_dofnum[np];
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ static void addToParent(const mjModel* m, mjData* d, mjtNum* mat, int n) {
|
|||||||
// find matching nonzeros
|
// find matching nonzeros
|
||||||
int np = m->body_parentid[n];
|
int np = m->body_parentid[n];
|
||||||
int i = 0, ip = 0;
|
int i = 0, ip = 0;
|
||||||
while (i<d->B_rownnz[n] && ip<d->B_rownnz[np]) {
|
while (i < d->B_rownnz[n] && ip < d->B_rownnz[np]) {
|
||||||
// columns match
|
// columns match
|
||||||
if (d->B_colind[d->B_rowadr[n] + i] == d->B_colind[d->B_rowadr[np] + ip]) {
|
if (d->B_colind[d->B_rowadr[n] + i] == d->B_colind[d->B_rowadr[np] + ip]) {
|
||||||
mju_addTo(mat + 6*(d->B_rowadr[np] + ip), mat + 6*(d->B_rowadr[n] + i), 6);
|
mju_addTo(mat + 6*(d->B_rowadr[np] + ip), mat + 6*(d->B_rowadr[n] + i), 6);
|
||||||
@@ -485,15 +485,15 @@ static void mjd_comVel_vel(const mjModel* m, mjData* d, mjtNum* Dcvel, mjtNum* D
|
|||||||
mjtNum mat[36], matT[36]; // 6x6 matrices
|
mjtNum mat[36], matT[36]; // 6x6 matrices
|
||||||
|
|
||||||
// forward pass over bodies: accumulate Dcvel, set Dcdofdot
|
// forward pass over bodies: accumulate Dcvel, set Dcdofdot
|
||||||
for (int i = 1; i<nbody; i++) {
|
for (int i = 1; i < nbody; i++) {
|
||||||
// Dcvel = Dcvel_parent
|
// Dcvel = Dcvel_parent
|
||||||
copyFromParent(m, d, Dcvel, i);
|
copyFromParent(m, d, Dcvel, i);
|
||||||
|
|
||||||
// process all dofs of this body
|
// process all dofs of this body
|
||||||
int doflast = m->body_dofadr[i] + m->body_dofnum[i];
|
int doflast = m->body_dofadr[i] + m->body_dofnum[i];
|
||||||
for (int j = m->body_dofadr[i]; j<doflast; j++) {
|
for (int j = m->body_dofadr[i]; j < doflast; j++) {
|
||||||
// number of dof ancestors of dof j
|
// number of dof ancestors of dof j
|
||||||
int Jadr = (j<nv - 1 ? m->dof_Madr[j + 1] : m->nM) - (m->dof_Madr[j] + 1);
|
int Jadr = (j < nv - 1 ? m->dof_Madr[j + 1] : m->nM) - (m->dof_Madr[j] + 1);
|
||||||
|
|
||||||
// Dcvel += D(cdof * qvel), Dcdofdot = D(cvel x cdof)
|
// Dcvel += D(cdof * qvel), Dcdofdot = D(cvel x cdof)
|
||||||
switch (m->jnt_type[m->dof_jntid[j]]) {
|
switch (m->jnt_type[m->dof_jntid[j]]) {
|
||||||
@@ -512,7 +512,7 @@ static void mjd_comVel_vel(const mjModel* m, mjData* d, mjtNum* Dcvel, mjtNum* D
|
|||||||
|
|
||||||
case mjJNT_BALL:
|
case mjJNT_BALL:
|
||||||
// Dcdofdot = Dcvel * D crossMotion(cvel, cdof)
|
// Dcdofdot = Dcvel * D crossMotion(cvel, cdof)
|
||||||
for (int dj=0; dj<3; dj++) {
|
for (int dj=0; dj < 3; dj++) {
|
||||||
mjd_crossMotion_vel(mat, d->cdof + 6 * (j + dj));
|
mjd_crossMotion_vel(mat, d->cdof + 6 * (j + dj));
|
||||||
mju_transpose(matT, mat, 6, 6);
|
mju_transpose(matT, mat, 6, 6);
|
||||||
mju_mulMatMat(Dcdofdot + 6*Dadr[j + dj], Dcvel + 6*Badr[i], matT, Jadr + dj, 6, 6);
|
mju_mulMatMat(Dcdofdot + 6*Dadr[j + dj], Dcvel + 6*Badr[i], matT, Jadr + dj, 6, 6);
|
||||||
@@ -573,13 +573,13 @@ static void mjd_rne_vel(const mjModel* m, mjData* d) {
|
|||||||
mjd_comVel_vel(m, d, Dcvel, Dcdofdot);
|
mjd_comVel_vel(m, d, Dcvel, Dcdofdot);
|
||||||
|
|
||||||
// forward pass over bodies: accumulate Dcacc, set Dcfrcbody
|
// forward pass over bodies: accumulate Dcacc, set Dcfrcbody
|
||||||
for (int i=1; i<nbody; i++) {
|
for (int i=1; i < nbody; i++) {
|
||||||
// Dcacc = Dcacc_parent
|
// Dcacc = Dcacc_parent
|
||||||
copyFromParent(m, d, Dcacc, i);
|
copyFromParent(m, d, Dcacc, i);
|
||||||
|
|
||||||
// process all dofs of this body
|
// process all dofs of this body
|
||||||
int doflast = m->body_dofadr[i] + m->body_dofnum[i];
|
int doflast = m->body_dofadr[i] + m->body_dofnum[i];
|
||||||
for (int j=m->body_dofadr[i]; j<doflast; j++) {
|
for (int j=m->body_dofadr[i]; j < doflast; j++) {
|
||||||
// number of dof ancestors of dof j
|
// number of dof ancestors of dof j
|
||||||
int Jadr = (j < nv - 1 ? m->dof_Madr[j + 1] : m->nM) - (m->dof_Madr[j] + 1);
|
int Jadr = (j < nv - 1 ? m->dof_Madr[j + 1] : m->nM) - (m->dof_Madr[j] + 1);
|
||||||
|
|
||||||
@@ -615,12 +615,12 @@ static void mjd_rne_vel(const mjModel* m, mjData* d) {
|
|||||||
mju_zero(Dcfrcbody, 6*Bnnz[0]);
|
mju_zero(Dcfrcbody, 6*Bnnz[0]);
|
||||||
|
|
||||||
// backward pass over bodies: accumulate Dcfrcbody
|
// backward pass over bodies: accumulate Dcfrcbody
|
||||||
for (int i=m->nbody-1; i>0; i--) {
|
for (int i=m->nbody-1; i > 0; i--) {
|
||||||
addToParent(m, d, Dcfrcbody, i);
|
addToParent(m, d, Dcfrcbody, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process all dofs, update qDeriv
|
// process all dofs, update qDeriv
|
||||||
for (int j=0; j<nv; j++) {
|
for (int j=0; j < nv; j++) {
|
||||||
// get body index
|
// get body index
|
||||||
int i = m->dof_bodyid[j];
|
int i = m->dof_bodyid[j];
|
||||||
|
|
||||||
@@ -639,19 +639,19 @@ static void mjd_rne_vel(const mjModel* m, mjData* d) {
|
|||||||
// construct sparse Jacobian structure of body; return nnz
|
// construct sparse Jacobian structure of body; return nnz
|
||||||
static int bodyJacSparse(const mjModel* m, int body, int* ind) {
|
static int bodyJacSparse(const mjModel* m, int body, int* ind) {
|
||||||
// skip fixed bodies
|
// skip fixed bodies
|
||||||
while (body>0 && m->body_dofnum[body]==0) {
|
while (body > 0 && m->body_dofnum[body] == 0) {
|
||||||
body = m->body_parentid[body];
|
body = m->body_parentid[body];
|
||||||
}
|
}
|
||||||
|
|
||||||
// body is not movable: empty chain
|
// body is not movable: empty chain
|
||||||
if (body==0) {
|
if (body == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// count dofs
|
// count dofs
|
||||||
int nnz = 0;
|
int nnz = 0;
|
||||||
int dof = m->body_dofadr[body] + m->body_dofnum[body] - 1;
|
int dof = m->body_dofadr[body] + m->body_dofnum[body] - 1;
|
||||||
while (dof>=0) {
|
while (dof >= 0) {
|
||||||
nnz++;
|
nnz++;
|
||||||
dof = m->dof_parentid[dof];
|
dof = m->dof_parentid[dof];
|
||||||
}
|
}
|
||||||
@@ -659,7 +659,7 @@ static int bodyJacSparse(const mjModel* m, int body, int* ind) {
|
|||||||
// fill array in reverse (increasing dof)
|
// fill array in reverse (increasing dof)
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
dof = m->body_dofadr[body] + m->body_dofnum[body] - 1;
|
dof = m->body_dofadr[body] + m->body_dofnum[body] - 1;
|
||||||
while (dof>=0) {
|
while (dof >= 0) {
|
||||||
ind[nnz-cnt-1] = dof;
|
ind[nnz-cnt-1] = dof;
|
||||||
cnt++;
|
cnt++;
|
||||||
dof = m->dof_parentid[dof];
|
dof = m->dof_parentid[dof];
|
||||||
@@ -680,20 +680,20 @@ static void addJTBJ(const mjModel* m, mjData* d, const mjtNum* J, const mjtNum*
|
|||||||
mjtNum* row = mj_stackAlloc(d, nv);
|
mjtNum* row = mj_stackAlloc(d, nv);
|
||||||
|
|
||||||
// process non-zero elements of B
|
// process non-zero elements of B
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
for (int j=0; j<n; j++) {
|
for (int j=0; j < n; j++) {
|
||||||
if (!B[i*n+j]) {
|
if (!B[i*n+j]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// process non-zero elements of J(i,:)
|
// process non-zero elements of J(i,:)
|
||||||
for (int k=0; k<nv; k++) {
|
for (int k=0; k < nv; k++) {
|
||||||
if (J[i*nv+k]) {
|
if (J[i*nv+k]) {
|
||||||
// row = J(i,k)*B(i,j)*J(j,:)
|
// row = J(i,k)*B(i,j)*J(j,:)
|
||||||
mju_scl(row, J+j*nv, J[i*nv+k] * B[i*n+j], nv);
|
mju_scl(row, J+j*nv, J[i*nv+k] * B[i*n+j], nv);
|
||||||
|
|
||||||
// add row to qDeriv(k,:)
|
// add row to qDeriv(k,:)
|
||||||
int rownnz_k = d->D_rownnz[k];
|
int rownnz_k = d->D_rownnz[k];
|
||||||
for (int s=0; s<rownnz_k; s++) {
|
for (int s=0; s < rownnz_k; s++) {
|
||||||
int adr = d->D_rowadr[k] + s;
|
int adr = d->D_rowadr[k] + s;
|
||||||
d->qDeriv[adr] += row[d->D_colind[adr]];
|
d->qDeriv[adr] += row[d->D_colind[adr]];
|
||||||
}
|
}
|
||||||
@@ -709,9 +709,9 @@ static void addJTBJ(const mjModel* m, mjData* d, const mjtNum* J, const mjtNum*
|
|||||||
|
|
||||||
// add J'*B*J to qDeriv, sparse version
|
// add J'*B*J to qDeriv, sparse version
|
||||||
static void addJTBJSparse(
|
static void addJTBJSparse(
|
||||||
const mjModel* m, mjData* d, const mjtNum* J,
|
const mjModel* m, mjData* d, const mjtNum* J,
|
||||||
const mjtNum* B, int n, int offset,
|
const mjtNum* B, int n, int offset,
|
||||||
const int* J_rownnz, const int* J_rowadr, const int* J_colind) {
|
const int* J_rownnz, const int* J_rowadr, const int* J_colind) {
|
||||||
int nv = m->nv;
|
int nv = m->nv;
|
||||||
|
|
||||||
// allocate row
|
// allocate row
|
||||||
@@ -770,7 +770,7 @@ static mjtNum mjd_muscleGain_vel(mjtNum len, mjtNum vel, const mjtNum lengthrang
|
|||||||
mjtNum fvmax = prm[8];
|
mjtNum fvmax = prm[8];
|
||||||
|
|
||||||
// scale force if negative
|
// scale force if negative
|
||||||
if (force<0) {
|
if (force < 0) {
|
||||||
force = scale / mjMAX(mjMINVAL, acc0);
|
force = scale / mjMAX(mjMINVAL, acc0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -788,16 +788,16 @@ static mjtNum mjd_muscleGain_vel(mjtNum len, mjtNum vel, const mjtNum lengthrang
|
|||||||
|
|
||||||
// length curve
|
// length curve
|
||||||
mjtNum FL = 0;
|
mjtNum FL = 0;
|
||||||
if (L>=lmin && L<=a) {
|
if (L >= lmin && L <= a) {
|
||||||
x = (L-lmin) / mjMAX(mjMINVAL, a-lmin);
|
x = (L-lmin) / mjMAX(mjMINVAL, a-lmin);
|
||||||
FL = 0.5*x*x;
|
FL = 0.5*x*x;
|
||||||
} else if (L<=1) {
|
} else if (L <= 1) {
|
||||||
x = (1-L) / mjMAX(mjMINVAL, 1-a);
|
x = (1-L) / mjMAX(mjMINVAL, 1-a);
|
||||||
FL = 1 - 0.5*x*x;
|
FL = 1 - 0.5*x*x;
|
||||||
} else if (L<=b) {
|
} else if (L <= b) {
|
||||||
x = (L-1) / mjMAX(mjMINVAL, b-1);
|
x = (L-1) / mjMAX(mjMINVAL, b-1);
|
||||||
FL = 1 - 0.5*x*x;
|
FL = 1 - 0.5*x*x;
|
||||||
} else if (L<=lmax) {
|
} else if (L <= lmax) {
|
||||||
x = (lmax-L) / mjMAX(mjMINVAL, lmax-b);
|
x = (lmax-L) / mjMAX(mjMINVAL, lmax-b);
|
||||||
FL = 0.5*x*x;
|
FL = 0.5*x*x;
|
||||||
}
|
}
|
||||||
@@ -805,13 +805,13 @@ static mjtNum mjd_muscleGain_vel(mjtNum len, mjtNum vel, const mjtNum lengthrang
|
|||||||
// velocity curve
|
// velocity curve
|
||||||
mjtNum dFV;
|
mjtNum dFV;
|
||||||
mjtNum y = fvmax-1;
|
mjtNum y = fvmax-1;
|
||||||
if (V<=-1) {
|
if (V <= -1) {
|
||||||
// FV = 0
|
// FV = 0
|
||||||
dFV = 0;
|
dFV = 0;
|
||||||
} else if (V<=0) {
|
} else if (V <= 0) {
|
||||||
// FV = (V+1)*(V+1)
|
// FV = (V+1)*(V+1)
|
||||||
dFV = 2*V + 2;
|
dFV = 2*V + 2;
|
||||||
} else if (V<=y) {
|
} else if (V <= y) {
|
||||||
// FV = fvmax - (y-V)*(y-V) / mjMAX(mjMINVAL, y)
|
// FV = fvmax - (y-V)*(y-V) / mjMAX(mjMINVAL, y)
|
||||||
dFV = (-2*V + 2*y) / mjMAX(mjMINVAL, y);
|
dFV = (-2*V + 2*y) / mjMAX(mjMINVAL, y);
|
||||||
} else {
|
} else {
|
||||||
@@ -835,23 +835,23 @@ void mjd_actuator_vel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// process actuators
|
// process actuators
|
||||||
for (int i=0; i<m->nu; i++) {
|
for (int i=0; i < m->nu; i++) {
|
||||||
mjtNum bias_vel = 0, gain_vel = 0;
|
mjtNum bias_vel = 0, gain_vel = 0;
|
||||||
|
|
||||||
// affine bias
|
// affine bias
|
||||||
if (m->actuator_biastype[i]==mjBIAS_AFFINE) {
|
if (m->actuator_biastype[i] == mjBIAS_AFFINE) {
|
||||||
// extract bias info: prm = [const, kp, kv]
|
// extract bias info: prm = [const, kp, kv]
|
||||||
bias_vel = (m->actuator_biasprm + mjNBIAS*i)[2];
|
bias_vel = (m->actuator_biasprm + mjNBIAS*i)[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// affine gain
|
// affine gain
|
||||||
if (m->actuator_gaintype[i]==mjGAIN_AFFINE) {
|
if (m->actuator_gaintype[i] == mjGAIN_AFFINE) {
|
||||||
// extract bias info: prm = [const, kp, kv]
|
// extract bias info: prm = [const, kp, kv]
|
||||||
gain_vel = (m->actuator_gainprm + mjNGAIN*i)[2];
|
gain_vel = (m->actuator_gainprm + mjNGAIN*i)[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
// muscle gain
|
// muscle gain
|
||||||
else if (m->actuator_gaintype[i]==mjGAIN_MUSCLE) {
|
else if (m->actuator_gaintype[i] == mjGAIN_MUSCLE) {
|
||||||
gain_vel = mjd_muscleGain_vel(d->actuator_length[i],
|
gain_vel = mjd_muscleGain_vel(d->actuator_length[i],
|
||||||
d->actuator_velocity[i],
|
d->actuator_velocity[i],
|
||||||
m->actuator_lengthrange+2*i,
|
m->actuator_lengthrange+2*i,
|
||||||
@@ -860,8 +860,8 @@ void mjd_actuator_vel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// force = gain .* [ctrl/act]
|
// force = gain .* [ctrl/act]
|
||||||
if (gain_vel!=0) {
|
if (gain_vel != 0) {
|
||||||
if (m->actuator_dyntype[i]==mjDYN_NONE) {
|
if (m->actuator_dyntype[i] == mjDYN_NONE) {
|
||||||
bias_vel += gain_vel * d->ctrl[i];
|
bias_vel += gain_vel * d->ctrl[i];
|
||||||
} else {
|
} else {
|
||||||
bias_vel += gain_vel * d->act[i-(m->nu - m->na)];
|
bias_vel += gain_vel * d->act[i-(m->nu - m->na)];
|
||||||
@@ -869,7 +869,7 @@ void mjd_actuator_vel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add
|
// add
|
||||||
if (bias_vel!=0) {
|
if (bias_vel != 0) {
|
||||||
addJTBJ(m, d, d->actuator_moment+i*nv, &bias_vel, 1);
|
addJTBJ(m, d, d->actuator_moment+i*nv, &bias_vel, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -915,8 +915,8 @@ static void addToQuadrant(mjtNum* restrict B, const mjtNum D[9], int col_quad, i
|
|||||||
|
|
||||||
// forces due to fluid mass moving with the body, B is 6x6
|
// forces due to fluid mass moving with the body, B is 6x6
|
||||||
static void mjd_addedMassForces(
|
static void mjd_addedMassForces(
|
||||||
mjtNum* restrict B, const mjtNum local_vels[6], const mjtNum fluid_density,
|
mjtNum* restrict B, const mjtNum local_vels[6], const mjtNum fluid_density,
|
||||||
const mjtNum virtual_mass[3], const mjtNum virtual_inertia[3]) {
|
const mjtNum virtual_mass[3], const mjtNum virtual_inertia[3]) {
|
||||||
const mjtNum lin_vel[3] = {local_vels[3], local_vels[4], local_vels[5]};
|
const mjtNum lin_vel[3] = {local_vels[3], local_vels[4], local_vels[5]};
|
||||||
const mjtNum ang_vel[3] = {local_vels[0], local_vels[1], local_vels[2]};
|
const mjtNum ang_vel[3] = {local_vels[0], local_vels[1], local_vels[2]};
|
||||||
const mjtNum virtual_lin_mom[3] = {
|
const mjtNum virtual_lin_mom[3] = {
|
||||||
@@ -935,7 +935,7 @@ static void mjd_addedMassForces(
|
|||||||
// force[:3] += cross(virtual_ang_mom, ang_vel)
|
// force[:3] += cross(virtual_ang_mom, ang_vel)
|
||||||
mjd_cross(virtual_ang_mom, ang_vel, Da, Db);
|
mjd_cross(virtual_ang_mom, ang_vel, Da, Db);
|
||||||
addToQuadrant(B, Db, 0, 0);
|
addToQuadrant(B, Db, 0, 0);
|
||||||
for (int i=0; i<9; ++i) {
|
for (int i=0; i < 9; ++i) {
|
||||||
Da[i] *= fluid_density * virtual_inertia[i % 3];
|
Da[i] *= fluid_density * virtual_inertia[i % 3];
|
||||||
}
|
}
|
||||||
addToQuadrant(B, Da, 0, 0);
|
addToQuadrant(B, Da, 0, 0);
|
||||||
@@ -943,7 +943,7 @@ static void mjd_addedMassForces(
|
|||||||
// force[:3] += cross(virtual_lin_mom, lin_vel)
|
// force[:3] += cross(virtual_lin_mom, lin_vel)
|
||||||
mjd_cross(virtual_lin_mom, lin_vel, Da, Db);
|
mjd_cross(virtual_lin_mom, lin_vel, Da, Db);
|
||||||
addToQuadrant(B, Db, 0, 1);
|
addToQuadrant(B, Db, 0, 1);
|
||||||
for (int i=0; i<9; ++i) {
|
for (int i=0; i < 9; ++i) {
|
||||||
Da[i] *= fluid_density * virtual_mass[i % 3];
|
Da[i] *= fluid_density * virtual_mass[i % 3];
|
||||||
}
|
}
|
||||||
addToQuadrant(B, Da, 0, 1);
|
addToQuadrant(B, Da, 0, 1);
|
||||||
@@ -951,7 +951,7 @@ static void mjd_addedMassForces(
|
|||||||
// force[3:] += cross(virtual_lin_mom, ang_vel)
|
// force[3:] += cross(virtual_lin_mom, ang_vel)
|
||||||
mjd_cross(virtual_lin_mom, ang_vel, Da, Db);
|
mjd_cross(virtual_lin_mom, ang_vel, Da, Db);
|
||||||
addToQuadrant(B, Db, 1, 0);
|
addToQuadrant(B, Db, 1, 0);
|
||||||
for (int i=0; i<9; ++i) {
|
for (int i=0; i < 9; ++i) {
|
||||||
Da[i] *= fluid_density * virtual_mass[i % 3];
|
Da[i] *= fluid_density * virtual_mass[i % 3];
|
||||||
}
|
}
|
||||||
addToQuadrant(B, Da, 1, 1);
|
addToQuadrant(B, Da, 1, 1);
|
||||||
@@ -961,9 +961,9 @@ static void mjd_addedMassForces(
|
|||||||
|
|
||||||
// torque due to motion in the fluid, D is 3x3
|
// torque due to motion in the fluid, D is 3x3
|
||||||
static inline void mjd_viscous_torque(
|
static inline void mjd_viscous_torque(
|
||||||
mjtNum* restrict D, const mjtNum lvel[6], const mjtNum fluid_density,
|
mjtNum* restrict D, const mjtNum lvel[6], const mjtNum fluid_density,
|
||||||
const mjtNum fluid_viscosity, const mjtNum size[3],
|
const mjtNum fluid_viscosity, const mjtNum size[3],
|
||||||
const mjtNum slender_drag_coef, const mjtNum ang_drag_coef)
|
const mjtNum slender_drag_coef, const mjtNum ang_drag_coef)
|
||||||
{
|
{
|
||||||
const mjtNum d_max = mju_max(mju_max(size[0], size[1]), size[2]);
|
const mjtNum d_max = mju_max(mju_max(size[0], size[1]), size[2]);
|
||||||
const mjtNum d_min = mju_min(mju_min(size[0], size[1]), size[2]);
|
const mjtNum d_min = mju_min(mju_min(size[0], size[1]), size[2]);
|
||||||
@@ -1016,9 +1016,9 @@ static inline void mjd_viscous_torque(
|
|||||||
|
|
||||||
// drag due to motion in the fluid, D is 3x3
|
// drag due to motion in the fluid, D is 3x3
|
||||||
static inline void mjd_viscous_drag(
|
static inline void mjd_viscous_drag(
|
||||||
mjtNum* restrict D, const mjtNum lvel[6], const mjtNum fluid_density,
|
mjtNum* restrict D, const mjtNum lvel[6], const mjtNum fluid_density,
|
||||||
const mjtNum fluid_viscosity, const mjtNum size[3],
|
const mjtNum fluid_viscosity, const mjtNum size[3],
|
||||||
const mjtNum blunt_drag_coef, const mjtNum slender_drag_coef) {
|
const mjtNum blunt_drag_coef, const mjtNum slender_drag_coef) {
|
||||||
const mjtNum d_max = mju_max(mju_max(size[0], size[1]), size[2]);
|
const mjtNum d_max = mju_max(mju_max(size[0], size[1]), size[2]);
|
||||||
const mjtNum d_min = mju_min(mju_min(size[0], size[1]), size[2]);
|
const mjtNum d_min = mju_min(mju_min(size[0], size[1]), size[2]);
|
||||||
const mjtNum d_mid = size[0] + size[1] + size[2] - d_max - d_min;
|
const mjtNum d_mid = size[0] + size[1] + size[2] - d_max - d_min;
|
||||||
@@ -1046,7 +1046,7 @@ static inline void mjd_viscous_drag(
|
|||||||
|
|
||||||
const mjtNum lin_coef = fluid_viscosity * 3.0 * mjPI * eq_sphere_D;
|
const mjtNum lin_coef = fluid_viscosity * 3.0 * mjPI * eq_sphere_D;
|
||||||
const mjtNum quad_coef = fluid_density * (
|
const mjtNum quad_coef = fluid_density * (
|
||||||
A_proj*blunt_drag_coef + slender_drag_coef*(A_max - A_proj));
|
A_proj*blunt_drag_coef + slender_drag_coef*(A_max - A_proj));
|
||||||
const mjtNum Aproj_coef = fluid_density * norm * (blunt_drag_coef - slender_drag_coef);
|
const mjtNum Aproj_coef = fluid_density * norm * (blunt_drag_coef - slender_drag_coef);
|
||||||
|
|
||||||
const mjtNum dAproj_dv[3] = {
|
const mjtNum dAproj_dv[3] = {
|
||||||
@@ -1084,8 +1084,8 @@ static inline void mjd_viscous_drag(
|
|||||||
|
|
||||||
// Kutta lift due to motion in the fluid, D is 3x3
|
// Kutta lift due to motion in the fluid, D is 3x3
|
||||||
static inline void mjd_kutta_lift(
|
static inline void mjd_kutta_lift(
|
||||||
mjtNum* restrict D, const mjtNum lvel[6], const mjtNum fluid_density,
|
mjtNum* restrict D, const mjtNum lvel[6], const mjtNum fluid_density,
|
||||||
const mjtNum size[3], const mjtNum kutta_lift_coef) {
|
const mjtNum size[3], const mjtNum kutta_lift_coef) {
|
||||||
const mjtNum a = pow2(size[1] * size[2]);
|
const mjtNum a = pow2(size[1] * size[2]);
|
||||||
const mjtNum b = pow2(size[2] * size[0]);
|
const mjtNum b = pow2(size[2] * size[0]);
|
||||||
const mjtNum c = pow2(size[0] * size[1]);
|
const mjtNum c = pow2(size[0] * size[1]);
|
||||||
@@ -1097,7 +1097,7 @@ static inline void mjd_kutta_lift(
|
|||||||
const mjtNum proj_num = a * xx + b * yy + c * zz;
|
const mjtNum proj_num = a * xx + b * yy + c * zz;
|
||||||
const mjtNum norm2 = xx + yy + zz;
|
const mjtNum norm2 = xx + yy + zz;
|
||||||
const mjtNum df_denom = mjPI * kutta_lift_coef * fluid_density / mju_max(
|
const mjtNum df_denom = mjPI * kutta_lift_coef * fluid_density / mju_max(
|
||||||
mjMINVAL, mju_sqrt(proj_denom * proj_num * norm2));
|
mjMINVAL, mju_sqrt(proj_denom * proj_num * norm2));
|
||||||
|
|
||||||
const mjtNum dfx_coef = yy * (a - b) + zz * (a - c);
|
const mjtNum dfx_coef = yy * (a - b) + zz * (a - c);
|
||||||
const mjtNum dfy_coef = xx * (b - a) + zz * (b - c);
|
const mjtNum dfy_coef = xx * (b - a) + zz * (b - c);
|
||||||
@@ -1138,8 +1138,8 @@ static inline void mjd_kutta_lift(
|
|||||||
|
|
||||||
// Magnus force due to motion in the fluid, B is 6x6
|
// Magnus force due to motion in the fluid, B is 6x6
|
||||||
static inline void mjd_magnus_force(
|
static inline void mjd_magnus_force(
|
||||||
mjtNum* restrict B, const mjtNum lvel[6], const mjtNum fluid_density,
|
mjtNum* restrict B, const mjtNum lvel[6], const mjtNum fluid_density,
|
||||||
const mjtNum size[3], const mjtNum magnus_lift_coef) {
|
const mjtNum size[3], const mjtNum magnus_lift_coef) {
|
||||||
const mjtNum volume = 4.0/3.0 * mjPI * size[0] * size[1] * size[2];
|
const mjtNum volume = 4.0/3.0 * mjPI * size[0] * size[1] * size[2];
|
||||||
|
|
||||||
// magnus_coef = magnus_lift_coef * fluid_density * volume
|
// magnus_coef = magnus_lift_coef * fluid_density * volume
|
||||||
@@ -1149,9 +1149,11 @@ static inline void mjd_magnus_force(
|
|||||||
|
|
||||||
// premultiply by magnus_coef
|
// premultiply by magnus_coef
|
||||||
const mjtNum lin_vel[3] = {
|
const mjtNum lin_vel[3] = {
|
||||||
magnus_coef * lvel[3], magnus_coef * lvel[4], magnus_coef * lvel[5]};
|
magnus_coef * lvel[3], magnus_coef * lvel[4], magnus_coef * lvel[5]
|
||||||
|
};
|
||||||
const mjtNum ang_vel[3] = {
|
const mjtNum ang_vel[3] = {
|
||||||
magnus_coef * lvel[0], magnus_coef * lvel[1], magnus_coef * lvel[2]};
|
magnus_coef * lvel[0], magnus_coef * lvel[1], magnus_coef * lvel[2]
|
||||||
|
};
|
||||||
|
|
||||||
// force[3:] += magnus_coef * cross(ang_vel, lin_vel)
|
// force[3:] += magnus_coef * cross(ang_vel, lin_vel)
|
||||||
mjd_cross(ang_vel, lin_vel, D_ang, D_lin);
|
mjd_cross(ang_vel, lin_vel, D_ang, D_lin);
|
||||||
@@ -1186,25 +1188,25 @@ void mjd_ellipsoidFluid(const mjModel* m, mjData* d, int bodyid) {
|
|||||||
nnz = bodyJacSparse(m, bodyid, colind);
|
nnz = bodyJacSparse(m, bodyid, colind);
|
||||||
|
|
||||||
// prepare rownnz, rowadr, colind for all 6 rows
|
// prepare rownnz, rowadr, colind for all 6 rows
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i < 6; i++) {
|
||||||
rownnz[i] = nnz;
|
rownnz[i] = nnz;
|
||||||
rowadr[i] = i == 0 ? 0 : rowadr[i-1] + nnz;
|
rowadr[i] = i == 0 ? 0 : rowadr[i-1] + nnz;
|
||||||
for (int k=0; k<nnz; k++) {
|
for (int k=0; k < nnz; k++) {
|
||||||
colind_compressed[i*nnz+k] = colind[k];
|
colind_compressed[i*nnz+k] = colind[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j=0; j<m->body_geomnum[bodyid]; j++) {
|
for (int j=0; j < m->body_geomnum[bodyid]; j++) {
|
||||||
const int geomid = m->body_geomadr[bodyid] + j;
|
const int geomid = m->body_geomadr[bodyid] + j;
|
||||||
|
|
||||||
mju_geomSemiAxes(m, geomid, semiaxes);
|
mju_geomSemiAxes(m, geomid, semiaxes);
|
||||||
|
|
||||||
readFluidGeomInteraction(
|
readFluidGeomInteraction(
|
||||||
m->geom_fluid + mjNFLUID*geomid, &geom_interaction_coef,
|
m->geom_fluid + mjNFLUID*geomid, &geom_interaction_coef,
|
||||||
&blunt_drag_coef, &slender_drag_coef, &ang_drag_coef,
|
&blunt_drag_coef, &slender_drag_coef, &ang_drag_coef,
|
||||||
&kutta_lift_coef, &magnus_lift_coef,
|
&kutta_lift_coef, &magnus_lift_coef,
|
||||||
virtual_mass, virtual_inertia);
|
virtual_mass, virtual_inertia);
|
||||||
|
|
||||||
// scales all forces, read from MJCF as boolean (0.0 or 1.0)
|
// scales all forces, read from MJCF as boolean (0.0 or 1.0)
|
||||||
if (geom_interaction_coef == 0.0) {
|
if (geom_interaction_coef == 0.0) {
|
||||||
@@ -1228,8 +1230,8 @@ void mjd_ellipsoidFluid(const mjModel* m, mjData* d, int bodyid) {
|
|||||||
|
|
||||||
// compress geom Jacobian in-place
|
// compress geom Jacobian in-place
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i < 6; i++) {
|
||||||
for (int k=0; k<nnz; k++) {
|
for (int k=0; k < nnz; k++) {
|
||||||
J[i*nnz+k] = J[i*nv+colind[k]];
|
J[i*nnz+k] = J[i*nv+colind[k]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1291,11 +1293,11 @@ void mjd_inertiaBoxFluid(const mjModel* m, mjData* d, int i)
|
|||||||
|
|
||||||
// equivalent inertia box
|
// equivalent inertia box
|
||||||
box[0] = mju_sqrt(mju_max(mjMINVAL,
|
box[0] = mju_sqrt(mju_max(mjMINVAL,
|
||||||
(inertia[1] + inertia[2] - inertia[0])) / m->body_mass[i] * 6.0);
|
(inertia[1] + inertia[2] - inertia[0])) / m->body_mass[i] * 6.0);
|
||||||
box[1] = mju_sqrt(mju_max(mjMINVAL,
|
box[1] = mju_sqrt(mju_max(mjMINVAL,
|
||||||
(inertia[0] + inertia[2] - inertia[1])) / m->body_mass[i] * 6.0);
|
(inertia[0] + inertia[2] - inertia[1])) / m->body_mass[i] * 6.0);
|
||||||
box[2] = mju_sqrt(mju_max(mjMINVAL,
|
box[2] = mju_sqrt(mju_max(mjMINVAL,
|
||||||
(inertia[0] + inertia[1] - inertia[2])) / m->body_mass[i] * 6.0);
|
(inertia[0] + inertia[1] - inertia[2])) / m->body_mass[i] * 6.0);
|
||||||
|
|
||||||
// map from CoM-centered to local body-centered 6D velocity
|
// map from CoM-centered to local body-centered 6D velocity
|
||||||
mj_objectVelocity(m, d, mjOBJ_BODY, i, lvel, 1);
|
mj_objectVelocity(m, d, mjOBJ_BODY, i, lvel, 1);
|
||||||
@@ -1321,8 +1323,8 @@ void mjd_inertiaBoxFluid(const mjModel* m, mjData* d, int i)
|
|||||||
nnz = bodyJacSparse(m, i, colind);
|
nnz = bodyJacSparse(m, i, colind);
|
||||||
|
|
||||||
// compress body Jacobian in-place
|
// compress body Jacobian in-place
|
||||||
for (int j=0; j<6; j++) {
|
for (int j=0; j < 6; j++) {
|
||||||
for (int k=0; k<nnz; k++) {
|
for (int k=0; k < nnz; k++) {
|
||||||
J[j*nnz+k] = J[j*nv+colind[k]];
|
J[j*nnz+k] = J[j*nv+colind[k]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1330,10 +1332,10 @@ void mjd_inertiaBoxFluid(const mjModel* m, mjData* d, int i)
|
|||||||
// prepare rownnz, rowadr, colind for all 6 rows
|
// prepare rownnz, rowadr, colind for all 6 rows
|
||||||
rownnz[0] = nnz;
|
rownnz[0] = nnz;
|
||||||
rowadr[0] = 0;
|
rowadr[0] = 0;
|
||||||
for (int j=1; j<6; j++) {
|
for (int j=1; j < 6; j++) {
|
||||||
rownnz[j] = nnz;
|
rownnz[j] = nnz;
|
||||||
rowadr[j] = rowadr[j-1] + nnz;
|
rowadr[j] = rowadr[j-1] + nnz;
|
||||||
for (int k=0; k<nnz; k++) {
|
for (int k=0; k < nnz; k++) {
|
||||||
colind[j*nnz+k] = colind[k];
|
colind[j*nnz+k] = colind[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1346,13 +1348,13 @@ void mjd_inertiaBoxFluid(const mjModel* m, mjData* d, int i)
|
|||||||
mju_copy(J+3*nnz, tmp, 3*nnz);
|
mju_copy(J+3*nnz, tmp, 3*nnz);
|
||||||
|
|
||||||
// add viscous force and torque
|
// add viscous force and torque
|
||||||
if (m->opt.viscosity>0) {
|
if (m->opt.viscosity > 0) {
|
||||||
// diameter of sphere approximation
|
// diameter of sphere approximation
|
||||||
mjtNum diam = (box[0] + box[1] + box[2])/3.0;
|
mjtNum diam = (box[0] + box[1] + box[2])/3.0;
|
||||||
|
|
||||||
// mju_scl3(lfrc, lvel, -mjPI*diam*diam*diam*m->opt.viscosity)
|
// mju_scl3(lfrc, lvel, -mjPI*diam*diam*diam*m->opt.viscosity)
|
||||||
B = -mjPI*diam*diam*diam*m->opt.viscosity;
|
B = -mjPI*diam*diam*diam*m->opt.viscosity;
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
addJTBJSparse(m, d, J, &B, 1, j, rownnz, rowadr, colind);
|
addJTBJSparse(m, d, J, &B, 1, j, rownnz, rowadr, colind);
|
||||||
} else {
|
} else {
|
||||||
@@ -1362,7 +1364,7 @@ void mjd_inertiaBoxFluid(const mjModel* m, mjData* d, int i)
|
|||||||
|
|
||||||
// mju_scl3(lfrc+3, lvel+3, -3.0*mjPI*diam*m->opt.viscosity);
|
// mju_scl3(lfrc+3, lvel+3, -3.0*mjPI*diam*m->opt.viscosity);
|
||||||
B = -3.0*mjPI*diam*m->opt.viscosity;
|
B = -3.0*mjPI*diam*m->opt.viscosity;
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
addJTBJSparse(m, d, J, &B, 1, 3+j, rownnz, rowadr, colind);
|
addJTBJSparse(m, d, J, &B, 1, 3+j, rownnz, rowadr, colind);
|
||||||
} else {
|
} else {
|
||||||
@@ -1372,7 +1374,7 @@ void mjd_inertiaBoxFluid(const mjModel* m, mjData* d, int i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add lift and drag force and torque
|
// add lift and drag force and torque
|
||||||
if (m->opt.density>0) {
|
if (m->opt.density > 0) {
|
||||||
// lfrc[0] -= m->opt.density*box[0]*(box[1]*box[1]*box[1]*box[1]+box[2]*box[2]*box[2]*box[2])*
|
// lfrc[0] -= m->opt.density*box[0]*(box[1]*box[1]*box[1]*box[1]+box[2]*box[2]*box[2]*box[2])*
|
||||||
// mju_abs(lvel[0])*lvel[0]/64.0;
|
// mju_abs(lvel[0])*lvel[0]/64.0;
|
||||||
B = -m->opt.density*box[0]*(box[1]*box[1]*box[1]*box[1]+box[2]*box[2]*box[2]*box[2])*
|
B = -m->opt.density*box[0]*(box[1]*box[1]*box[1]*box[1]+box[2]*box[2]*box[2]*box[2])*
|
||||||
@@ -1445,9 +1447,9 @@ void mjd_passive_vel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dof damping
|
// dof damping
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
int nnz_i = d->D_rownnz[i];
|
int nnz_i = d->D_rownnz[i];
|
||||||
for (int j=0; j<nnz_i; j++) {
|
for (int j=0; j < nnz_i; j++) {
|
||||||
int ij = d->D_rowadr[i] + j;
|
int ij = d->D_rowadr[i] + j;
|
||||||
|
|
||||||
// identify diagonal element
|
// identify diagonal element
|
||||||
@@ -1459,8 +1461,8 @@ void mjd_passive_vel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tendon damping
|
// tendon damping
|
||||||
for (int i=0; i<m->ntendon; i++) {
|
for (int i=0; i < m->ntendon; i++) {
|
||||||
if (m->tendon_damping[i]>0) {
|
if (m->tendon_damping[i] > 0) {
|
||||||
mjtNum B = -m->tendon_damping[i];
|
mjtNum B = -m->tendon_damping[i];
|
||||||
|
|
||||||
// add sparse or dense
|
// add sparse or dense
|
||||||
@@ -1474,15 +1476,15 @@ void mjd_passive_vel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fluid drag model, either body-level (inertia box) or geom-level (ellipsoid)
|
// fluid drag model, either body-level (inertia box) or geom-level (ellipsoid)
|
||||||
if (m->opt.viscosity>0 || m->opt.density>0) {
|
if (m->opt.viscosity > 0 || m->opt.density > 0) {
|
||||||
for (int i=1; i<nbody; i++) {
|
for (int i=1; i < nbody; i++) {
|
||||||
if (m->body_mass[i]<mjMINVAL) {
|
if (m->body_mass[i] < mjMINVAL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int use_ellipsoid_model = 0;
|
int use_ellipsoid_model = 0;
|
||||||
// if any child geom uses the ellipsoid model, inertia-box model is disabled for parent body
|
// if any child geom uses the ellipsoid model, inertia-box model is disabled for parent body
|
||||||
for (int j=0; j<m->body_geomnum[i] && use_ellipsoid_model==0; j++) {
|
for (int j=0; j < m->body_geomnum[i] && use_ellipsoid_model == 0; j++) {
|
||||||
const int geomid = m->body_geomadr[i] + j;
|
const int geomid = m->body_geomadr[i] + j;
|
||||||
use_ellipsoid_model += (m->geom_fluid[mjNFLUID*geomid] > 0);
|
use_ellipsoid_model += (m->geom_fluid[mjNFLUID*geomid] > 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ static void setState(const mjModel* m, mjData* d, mjtNum time, const mjtNum* sta
|
|||||||
// dx = (x2 - x1) / h
|
// dx = (x2 - x1) / h
|
||||||
static void diff(mjtNum* restrict dx, const mjtNum* x1, const mjtNum* x2, mjtNum h, int n) {
|
static void diff(mjtNum* restrict dx, const mjtNum* x1, const mjtNum* x2, mjtNum h, int n) {
|
||||||
mjtNum inv_h = 1/h;
|
mjtNum inv_h = 1/h;
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
dx[i] = inv_h * (x2[i] - x1[i]);
|
dx[i] = inv_h * (x2[i] - x1[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,22 +154,22 @@ void mj_stepSkip(const mjModel* m, mjData* d, int skipstage, int skipsensor) {
|
|||||||
|
|
||||||
// use selected integrator
|
// use selected integrator
|
||||||
switch (m->opt.integrator) {
|
switch (m->opt.integrator) {
|
||||||
case mjINT_EULER:
|
case mjINT_EULER:
|
||||||
mj_EulerSkip(m, d, skipstage >= mjSTAGE_POS);
|
mj_EulerSkip(m, d, skipstage >= mjSTAGE_POS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjINT_RK4:
|
case mjINT_RK4:
|
||||||
// ignore skipstage
|
// ignore skipstage
|
||||||
mj_RungeKutta(m, d, 4);
|
mj_RungeKutta(m, d, 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjINT_IMPLICIT:
|
case mjINT_IMPLICIT:
|
||||||
case mjINT_IMPLICITFAST:
|
case mjINT_IMPLICITFAST:
|
||||||
mj_implicitSkip(m, d, skipstage >= mjSTAGE_VEL);
|
mj_implicitSkip(m, d, skipstage >= mjSTAGE_VEL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mju_error("Invalid integrator");
|
mju_error("Invalid integrator");
|
||||||
}
|
}
|
||||||
|
|
||||||
TM_END(mjTIMER_STEP);
|
TM_END(mjTIMER_STEP);
|
||||||
@@ -208,7 +208,7 @@ void mjd_passive_velFD(const mjModel* m, mjData* d, mjtNum eps) {
|
|||||||
mju_copy(qfrc_passive, d->qfrc_passive, nv);
|
mju_copy(qfrc_passive, d->qfrc_passive, nv);
|
||||||
|
|
||||||
// loop over dofs
|
// loop over dofs
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
// save qvel[i]
|
// save qvel[i]
|
||||||
mjtNum saveqvel = d->qvel[i];
|
mjtNum saveqvel = d->qvel[i];
|
||||||
|
|
||||||
@@ -224,9 +224,9 @@ void mjd_passive_velFD(const mjModel* m, mjData* d, mjtNum eps) {
|
|||||||
mju_scl(fd, fd, 1/eps, nv);
|
mju_scl(fd, fd, 1/eps, nv);
|
||||||
|
|
||||||
// copy to i-th column of qDeriv
|
// copy to i-th column of qDeriv
|
||||||
for (int j=0; j<nv; j++) {
|
for (int j=0; j < nv; j++) {
|
||||||
int adr = d->D_rowadr[j] + cnt[j];
|
int adr = d->D_rowadr[j] + cnt[j];
|
||||||
if (cnt[j]<d->D_rownnz[j] && d->D_colind[adr] == i) {
|
if (cnt[j] < d->D_rownnz[j] && d->D_colind[adr] == i) {
|
||||||
d->qDeriv[adr] = fd[j];
|
d->qDeriv[adr] = fd[j];
|
||||||
cnt[j]++;
|
cnt[j]++;
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ void mjd_smooth_velFD(const mjModel* m, mjData* d, mjtNum eps) {
|
|||||||
memset(cnt, 0, nv*sizeof(int));
|
memset(cnt, 0, nv*sizeof(int));
|
||||||
|
|
||||||
// loop over dofs
|
// loop over dofs
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
// save qvel[i]
|
// save qvel[i]
|
||||||
mjtNum saveqvel = d->qvel[i];
|
mjtNum saveqvel = d->qvel[i];
|
||||||
|
|
||||||
@@ -283,8 +283,8 @@ void mjd_smooth_velFD(const mjModel* m, mjData* d, mjtNum eps) {
|
|||||||
mju_scl(fd, fd, 0.5/eps, nv);
|
mju_scl(fd, fd, 0.5/eps, nv);
|
||||||
|
|
||||||
// copy to sparse qDeriv
|
// copy to sparse qDeriv
|
||||||
for (int j=0; j<nv; j++) {
|
for (int j=0; j < nv; j++) {
|
||||||
if (cnt[j]<d->D_rownnz[j] && d->D_colind[d->D_rowadr[j]+cnt[j]]==i) {
|
if (cnt[j] < d->D_rownnz[j] && d->D_colind[d->D_rowadr[j]+cnt[j]] == i) {
|
||||||
d->qDeriv[d->D_rowadr[j]+cnt[j]] = fd[j];
|
d->qDeriv[d->D_rowadr[j]+cnt[j]] = fd[j];
|
||||||
cnt[j]++;
|
cnt[j]++;
|
||||||
}
|
}
|
||||||
@@ -292,8 +292,8 @@ void mjd_smooth_velFD(const mjModel* m, mjData* d, mjtNum eps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make sure final row counters equal rownnz
|
// make sure final row counters equal rownnz
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
if (cnt[i]!=d->D_rownnz[i]) {
|
if (cnt[i] != d->D_rownnz[i]) {
|
||||||
mju_error("error in constructing FD sparse derivative");
|
mju_error("error in constructing FD sparse derivative");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,7 @@ void mjd_stepFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte flg_centered,
|
|||||||
|
|
||||||
// finite-difference controls: skip=mjSTAGE_VEL, handle ctrl at range limits
|
// finite-difference controls: skip=mjSTAGE_VEL, handle ctrl at range limits
|
||||||
if (DyDu || DsDu) {
|
if (DyDu || DsDu) {
|
||||||
for (int i=0; i<nu; i++) {
|
for (int i=0; i < nu; i++) {
|
||||||
int limited = m->actuator_ctrllimited[i];
|
int limited = m->actuator_ctrllimited[i];
|
||||||
// nudge forward, if possible given ctrlrange
|
// nudge forward, if possible given ctrlrange
|
||||||
int nudge_fwd = !limited || inRange(ctrl[i], ctrl[i]+eps, m->actuator_ctrlrange+2*i);
|
int nudge_fwd = !limited || inRange(ctrl[i], ctrl[i]+eps, m->actuator_ctrlrange+2*i);
|
||||||
@@ -415,7 +415,7 @@ void mjd_stepFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte flg_centered,
|
|||||||
|
|
||||||
// finite-difference activations: skip=mjSTAGE_VEL
|
// finite-difference activations: skip=mjSTAGE_VEL
|
||||||
if (DyDa || DsDa) {
|
if (DyDa || DsDa) {
|
||||||
for (int i=0; i<na; i++) {
|
for (int i=0; i < na; i++) {
|
||||||
// nudge forward
|
// nudge forward
|
||||||
d->act[i] += eps;
|
d->act[i] += eps;
|
||||||
|
|
||||||
@@ -462,7 +462,7 @@ void mjd_stepFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte flg_centered,
|
|||||||
|
|
||||||
// finite-difference velocities: skip=mjSTAGE_POS
|
// finite-difference velocities: skip=mjSTAGE_POS
|
||||||
if (DyDv || DsDv) {
|
if (DyDv || DsDv) {
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
// nudge forward
|
// nudge forward
|
||||||
d->qvel[i] += eps;
|
d->qvel[i] += eps;
|
||||||
|
|
||||||
@@ -509,7 +509,7 @@ void mjd_stepFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte flg_centered,
|
|||||||
// finite-difference positions: skip=mjSTAGE_NONE
|
// finite-difference positions: skip=mjSTAGE_NONE
|
||||||
if (DyDq || DsDq) {
|
if (DyDq || DsDq) {
|
||||||
mjtNum *dpos = mj_stackAlloc(d, nv); // allocate position perturbation
|
mjtNum *dpos = mj_stackAlloc(d, nv); // allocate position perturbation
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
// nudge forward
|
// nudge forward
|
||||||
mju_zero(dpos, nv);
|
mju_zero(dpos, nv);
|
||||||
dpos[i] = 1;
|
dpos[i] = 1;
|
||||||
|
|||||||
+42
-42
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
// check positions, reset if bad
|
// check positions, reset if bad
|
||||||
void mj_checkPos(const mjModel* m, mjData* d) {
|
void mj_checkPos(const mjModel* m, mjData* d) {
|
||||||
for (int i=0; i<m->nq; i++) {
|
for (int i=0; i < m->nq; i++) {
|
||||||
if (mju_isBad(d->qpos[i])) {
|
if (mju_isBad(d->qpos[i])) {
|
||||||
mj_warning(d, mjWARN_BADQPOS, i);
|
mj_warning(d, mjWARN_BADQPOS, i);
|
||||||
mj_resetData(m, d);
|
mj_resetData(m, d);
|
||||||
@@ -61,7 +61,7 @@ void mj_checkPos(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// check velocities, reset if bad
|
// check velocities, reset if bad
|
||||||
void mj_checkVel(const mjModel* m, mjData* d) {
|
void mj_checkVel(const mjModel* m, mjData* d) {
|
||||||
for (int i=0; i<m->nv; i++) {
|
for (int i=0; i < m->nv; i++) {
|
||||||
if (mju_isBad(d->qvel[i])) {
|
if (mju_isBad(d->qvel[i])) {
|
||||||
mj_warning(d, mjWARN_BADQVEL, i);
|
mj_warning(d, mjWARN_BADQVEL, i);
|
||||||
mj_resetData(m, d);
|
mj_resetData(m, d);
|
||||||
@@ -76,7 +76,7 @@ void mj_checkVel(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// check accelerations, reset if bad
|
// check accelerations, reset if bad
|
||||||
void mj_checkAcc(const mjModel* m, mjData* d) {
|
void mj_checkAcc(const mjModel* m, mjData* d) {
|
||||||
for (int i=0; i<m->nv; i++) {
|
for (int i=0; i < m->nv; i++) {
|
||||||
if (mju_isBad(d->qacc[i])) {
|
if (mju_isBad(d->qacc[i])) {
|
||||||
mj_warning(d, mjWARN_BADQACC, i);
|
mj_warning(d, mjWARN_BADQACC, i);
|
||||||
mj_resetData(m, d);
|
mj_resetData(m, d);
|
||||||
@@ -166,7 +166,7 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
|
|||||||
mju_zero(d->actuator_force, nu);
|
mju_zero(d->actuator_force, nu);
|
||||||
|
|
||||||
// disabled or no actuation: return
|
// disabled or no actuation: return
|
||||||
if (nu==0 || mjDISABLED(mjDSBL_ACTUATION)) {
|
if (nu == 0 || mjDISABLED(mjDSBL_ACTUATION)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
|
|||||||
if (mjDISABLED(mjDSBL_CLAMPCTRL)) {
|
if (mjDISABLED(mjDSBL_CLAMPCTRL)) {
|
||||||
mju_copy(ctrl, d->ctrl, nu);
|
mju_copy(ctrl, d->ctrl, nu);
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<nu; i++) {
|
for (int i=0; i < nu; i++) {
|
||||||
// clamp ctrl
|
// clamp ctrl
|
||||||
if (m->actuator_ctrllimited[i]) {
|
if (m->actuator_ctrllimited[i]) {
|
||||||
mjtNum *ctrlrange = m->actuator_ctrlrange + 2*i;
|
mjtNum *ctrlrange = m->actuator_ctrlrange + 2*i;
|
||||||
@@ -188,7 +188,7 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check controls, set all to 0 if any are bad
|
// check controls, set all to 0 if any are bad
|
||||||
for (int i=0; i<nu; i++) {
|
for (int i=0; i < nu; i++) {
|
||||||
if (mju_isBad(ctrl[i])) {
|
if (mju_isBad(ctrl[i])) {
|
||||||
mj_warning(d, mjWARN_BADCTRL, i);
|
mj_warning(d, mjWARN_BADCTRL, i);
|
||||||
mju_zero(ctrl, nu);
|
mju_zero(ctrl, nu);
|
||||||
@@ -197,7 +197,7 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// force = gain .* [ctrl/act] + bias
|
// force = gain .* [ctrl/act] + bias
|
||||||
for (int i=0; i<nu; i++) {
|
for (int i=0; i < nu; i++) {
|
||||||
// skip actuator plugins -- these are handled after builtin actuator types
|
// skip actuator plugins -- these are handled after builtin actuator types
|
||||||
if (m->actuator_plugin[i] >= 0) {
|
if (m->actuator_plugin[i] >= 0) {
|
||||||
continue;
|
continue;
|
||||||
@@ -275,7 +275,7 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
|
|||||||
// handle actuator plugins
|
// handle actuator plugins
|
||||||
if (m->nplugin) {
|
if (m->nplugin) {
|
||||||
const int nslot = mjp_pluginCount();
|
const int nslot = mjp_pluginCount();
|
||||||
for (int i=0; i<m->nplugin; i++) {
|
for (int i=0; i < m->nplugin; i++) {
|
||||||
const int slot = m->plugin[i];
|
const int slot = m->plugin[i];
|
||||||
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
@@ -291,7 +291,7 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clamp actuator_force
|
// clamp actuator_force
|
||||||
for (int i=0; i<nu; i++) {
|
for (int i=0; i < nu; i++) {
|
||||||
if (m->actuator_forcelimited[i]) {
|
if (m->actuator_forcelimited[i]) {
|
||||||
mjtNum *forcerange = m->actuator_forcerange + 2*i;
|
mjtNum *forcerange = m->actuator_forcerange + 2*i;
|
||||||
force[i] = mju_clip(force[i], forcerange[0], forcerange[1]);
|
force[i] = mju_clip(force[i], forcerange[0], forcerange[1]);
|
||||||
@@ -302,7 +302,7 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
|
|||||||
mju_mulMatTVec(d->qfrc_actuator, moment, force, nu, nv);
|
mju_mulMatTVec(d->qfrc_actuator, moment, force, nu, nv);
|
||||||
|
|
||||||
// act_dot for stateful actuators
|
// act_dot for stateful actuators
|
||||||
for (int i=0; i<nu; i++) {
|
for (int i=0; i < nu; i++) {
|
||||||
if (m->actuator_plugin[i] >= 0) {
|
if (m->actuator_plugin[i] >= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -392,7 +392,7 @@ static void warmstart(const mjModel* m, mjData* d) {
|
|||||||
mj_constraintUpdate(m, d, jar, &cost_warmstart, 0);
|
mj_constraintUpdate(m, d, jar, &cost_warmstart, 0);
|
||||||
|
|
||||||
// PGS
|
// PGS
|
||||||
if (m->opt.solver==mjSOL_PGS) {
|
if (m->opt.solver == mjSOL_PGS) {
|
||||||
// cost(force_warmstart)
|
// cost(force_warmstart)
|
||||||
mjtNum PGS_warmstart = mju_dot(d->efc_force, d->efc_b, nefc);
|
mjtNum PGS_warmstart = mju_dot(d->efc_force, d->efc_b, nefc);
|
||||||
mjtNum* ARf = mj_stackAlloc(d, nefc);
|
mjtNum* ARf = mj_stackAlloc(d, nefc);
|
||||||
@@ -406,7 +406,7 @@ static void warmstart(const mjModel* m, mjData* d) {
|
|||||||
PGS_warmstart += 0.5*mju_dot(d->efc_force, ARf, nefc);
|
PGS_warmstart += 0.5*mju_dot(d->efc_force, ARf, nefc);
|
||||||
|
|
||||||
// use zero if better
|
// use zero if better
|
||||||
if (PGS_warmstart>0) {
|
if (PGS_warmstart > 0) {
|
||||||
mju_zero(d->efc_force, nefc);
|
mju_zero(d->efc_force, nefc);
|
||||||
mju_zero(d->qfrc_constraint, nv);
|
mju_zero(d->qfrc_constraint, nv);
|
||||||
}
|
}
|
||||||
@@ -417,7 +417,7 @@ static void warmstart(const mjModel* m, mjData* d) {
|
|||||||
// add Gauss to cost(qacc_warmstart)
|
// add Gauss to cost(qacc_warmstart)
|
||||||
mjtNum* Ma = mj_stackAlloc(d, nv);
|
mjtNum* Ma = mj_stackAlloc(d, nv);
|
||||||
mj_mulM(m, d, Ma, d->qacc_warmstart);
|
mj_mulM(m, d, Ma, d->qacc_warmstart);
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
cost_warmstart += 0.5*(Ma[i]-d->qfrc_smooth[i])*(d->qacc_warmstart[i]-d->qacc_smooth[i]);
|
cost_warmstart += 0.5*(Ma[i]-d->qfrc_smooth[i])*(d->qacc_warmstart[i]-d->qacc_smooth[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,7 +426,7 @@ static void warmstart(const mjModel* m, mjData* d) {
|
|||||||
mj_constraintUpdate(m, d, d->efc_b, &cost_smooth, 0);
|
mj_constraintUpdate(m, d, d->efc_b, &cost_smooth, 0);
|
||||||
|
|
||||||
// use qacc_smooth if better
|
// use qacc_smooth if better
|
||||||
if (cost_warmstart>cost_smooth) {
|
if (cost_warmstart > cost_smooth) {
|
||||||
mju_copy(d->qacc, d->qacc_smooth, nv);
|
mju_copy(d->qacc, d->qacc_smooth, nv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -488,7 +488,7 @@ void mj_fwdConstraint(const mjModel* m, mjData* d) {
|
|||||||
mju_copy(d->qacc_warmstart, d->qacc, nv);
|
mju_copy(d->qacc_warmstart, d->qacc, nv);
|
||||||
|
|
||||||
// run noslip solver if enabled
|
// run noslip solver if enabled
|
||||||
if (m->opt.noslip_iterations>0) {
|
if (m->opt.noslip_iterations > 0) {
|
||||||
mj_solNoSlip(m, d, m->opt.noslip_iterations);
|
mj_solNoSlip(m, d, m->opt.noslip_iterations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,11 +507,11 @@ static void mj_advance(const mjModel* m, mjData* d,
|
|||||||
mju_addToScl(d->act, act_dot, m->opt.timestep, m->na);
|
mju_addToScl(d->act, act_dot, m->opt.timestep, m->na);
|
||||||
|
|
||||||
// clamp activations
|
// clamp activations
|
||||||
for (int i=0; i<m->nu; i++) {
|
for (int i=0; i < m->nu; i++) {
|
||||||
int j = m->actuator_actadr[i];
|
int j = m->actuator_actadr[i];
|
||||||
if (j > -1 && m->actuator_actlimited[i]) {
|
if (j > -1 && m->actuator_actlimited[i]) {
|
||||||
mjtNum* actrange = m->actuator_actrange + 2*i;
|
mjtNum* actrange = m->actuator_actrange + 2*i;
|
||||||
for (int k=0; k<m->actuator_actnum[i]; k++) {
|
for (int k=0; k < m->actuator_actnum[i]; k++) {
|
||||||
d->act[j+k] = mju_clip(d->act[j+k], actrange[0], actrange[1]);
|
d->act[j+k] = mju_clip(d->act[j+k], actrange[0], actrange[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,8 +552,8 @@ void mj_EulerSkip(const mjModel* m, mjData* d, int skipfactor) {
|
|||||||
|
|
||||||
// check for dof damping
|
// check for dof damping
|
||||||
int dof_damping = 0;
|
int dof_damping = 0;
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
if (m->dof_damping[i]>0) {
|
if (m->dof_damping[i] > 0) {
|
||||||
dof_damping = 1;
|
dof_damping = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -571,7 +571,7 @@ void mj_EulerSkip(const mjModel* m, mjData* d, int skipfactor) {
|
|||||||
|
|
||||||
// MhB = M + h*diag(B)
|
// MhB = M + h*diag(B)
|
||||||
mju_copy(MhB, d->qM, m->nM);
|
mju_copy(MhB, d->qM, m->nM);
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
MhB[m->dof_Madr[i]] += m->opt.timestep * m->dof_damping[i];
|
MhB[m->dof_Madr[i]] += m->opt.timestep * m->dof_damping[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,8 +618,8 @@ void mj_RungeKutta(const mjModel* m, mjData* d, int N) {
|
|||||||
int nv = m->nv, nq = m->nq, na = m->na;
|
int nv = m->nv, nq = m->nq, na = m->na;
|
||||||
mjtNum h = m->opt.timestep, time = d->time;
|
mjtNum h = m->opt.timestep, time = d->time;
|
||||||
mjtNum C[9], T[9], *X[10], *F[10], *dX;
|
mjtNum C[9], T[9], *X[10], *F[10], *dX;
|
||||||
const mjtNum* A = (N==4 ? RK4_A : 0);
|
const mjtNum* A = (N == 4 ? RK4_A : 0);
|
||||||
const mjtNum* B = (N==4 ? RK4_B : 0);
|
const mjtNum* B = (N == 4 ? RK4_B : 0);
|
||||||
mjMARKSTACK;
|
mjMARKSTACK;
|
||||||
|
|
||||||
// check order
|
// check order
|
||||||
@@ -629,16 +629,16 @@ void mj_RungeKutta(const mjModel* m, mjData* d, int N) {
|
|||||||
|
|
||||||
// allocate space for intermediate solutions
|
// allocate space for intermediate solutions
|
||||||
dX = mj_stackAlloc(d, 2*nv+na);
|
dX = mj_stackAlloc(d, 2*nv+na);
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i < N; i++) {
|
||||||
X[i] = mj_stackAlloc(d, nq+nv+na);
|
X[i] = mj_stackAlloc(d, nq+nv+na);
|
||||||
F[i] = mj_stackAlloc(d, nv+na);
|
F[i] = mj_stackAlloc(d, nv+na);
|
||||||
}
|
}
|
||||||
|
|
||||||
// precompute C and T; C,T,A have size (N-1)
|
// precompute C and T; C,T,A have size (N-1)
|
||||||
for (int i=1; i<N; i++) {
|
for (int i=1; i < N; i++) {
|
||||||
// C(i) = sum_j A(i,j)
|
// C(i) = sum_j A(i,j)
|
||||||
C[i-1] = 0;
|
C[i-1] = 0;
|
||||||
for (int j=0; j<i; j++) {
|
for (int j=0; j < i; j++) {
|
||||||
C[i-1] += A[(i-1)*(N-1)+j];
|
C[i-1] += A[(i-1)*(N-1)+j];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,10 +656,10 @@ void mj_RungeKutta(const mjModel* m, mjData* d, int N) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute the remaining X[i], F[i]
|
// compute the remaining X[i], F[i]
|
||||||
for (int i=1; i<N; i++) {
|
for (int i=1; i < N; i++) {
|
||||||
// compute dX
|
// compute dX
|
||||||
mju_zero(dX, 2*nv+na);
|
mju_zero(dX, 2*nv+na);
|
||||||
for (int j=0; j<i; j++) {
|
for (int j=0; j < i; j++) {
|
||||||
mju_addToScl(dX, X[j]+nq, A[(i-1)*(N-1)+j], nv);
|
mju_addToScl(dX, X[j]+nq, A[(i-1)*(N-1)+j], nv);
|
||||||
mju_addToScl(dX+nv, F[j], A[(i-1)*(N-1)+j], nv+na);
|
mju_addToScl(dX+nv, F[j], A[(i-1)*(N-1)+j], nv+na);
|
||||||
}
|
}
|
||||||
@@ -687,7 +687,7 @@ void mj_RungeKutta(const mjModel* m, mjData* d, int N) {
|
|||||||
|
|
||||||
// compute dX for final update (using B instead of A)
|
// compute dX for final update (using B instead of A)
|
||||||
mju_zero(dX, 2*nv+na);
|
mju_zero(dX, 2*nv+na);
|
||||||
for (int j=0; j<N; j++) {
|
for (int j=0; j < N; j++) {
|
||||||
mju_addToScl(dX, X[j]+nq, B[j], nv);
|
mju_addToScl(dX, X[j]+nq, B[j], nv);
|
||||||
mju_addToScl(dX+nv, F[j], B[j], nv+na);
|
mju_addToScl(dX+nv, F[j], B[j], nv+na);
|
||||||
}
|
}
|
||||||
@@ -783,7 +783,7 @@ void mj_forwardSkip(const mjModel* m, mjData* d, int skipstage, int skipsensor)
|
|||||||
TM_START;
|
TM_START;
|
||||||
|
|
||||||
// position-dependent
|
// position-dependent
|
||||||
if (skipstage<mjSTAGE_POS) {
|
if (skipstage < mjSTAGE_POS) {
|
||||||
mj_fwdPosition(m, d);
|
mj_fwdPosition(m, d);
|
||||||
if (!skipsensor) {
|
if (!skipsensor) {
|
||||||
mj_sensorPos(m, d);
|
mj_sensorPos(m, d);
|
||||||
@@ -794,7 +794,7 @@ void mj_forwardSkip(const mjModel* m, mjData* d, int skipstage, int skipsensor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// velocity-dependent
|
// velocity-dependent
|
||||||
if (skipstage<mjSTAGE_VEL) {
|
if (skipstage < mjSTAGE_VEL) {
|
||||||
mj_fwdVelocity(m, d);
|
mj_fwdVelocity(m, d);
|
||||||
if (!skipsensor) {
|
if (!skipsensor) {
|
||||||
mj_sensorVel(m, d);
|
mj_sensorVel(m, d);
|
||||||
@@ -845,21 +845,21 @@ void mj_step(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// use selected integrator
|
// use selected integrator
|
||||||
switch (m->opt.integrator) {
|
switch (m->opt.integrator) {
|
||||||
case mjINT_EULER:
|
case mjINT_EULER:
|
||||||
mj_Euler(m, d);
|
mj_Euler(m, d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjINT_RK4:
|
case mjINT_RK4:
|
||||||
mj_RungeKutta(m, d, 4);
|
mj_RungeKutta(m, d, 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjINT_IMPLICIT:
|
case mjINT_IMPLICIT:
|
||||||
case mjINT_IMPLICITFAST:
|
case mjINT_IMPLICITFAST:
|
||||||
mj_implicit(m, d);
|
mj_implicit(m, d);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mju_error("Invalid integrator");
|
mju_error("Invalid integrator");
|
||||||
}
|
}
|
||||||
|
|
||||||
TM_END(mjTIMER_STEP);
|
TM_END(mjTIMER_STEP);
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ void mj_inverseSkip(const mjModel* m, mjData* d,
|
|||||||
int nv = m->nv;
|
int nv = m->nv;
|
||||||
|
|
||||||
// position-dependent
|
// position-dependent
|
||||||
if (skipstage<mjSTAGE_POS) {
|
if (skipstage < mjSTAGE_POS) {
|
||||||
mj_invPosition(m, d);
|
mj_invPosition(m, d);
|
||||||
if (!skipsensor) {
|
if (!skipsensor) {
|
||||||
mj_sensorPos(m, d);
|
mj_sensorPos(m, d);
|
||||||
@@ -134,7 +134,7 @@ void mj_inverseSkip(const mjModel* m, mjData* d,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// velocity-dependent
|
// velocity-dependent
|
||||||
if (skipstage<mjSTAGE_VEL) {
|
if (skipstage < mjSTAGE_VEL) {
|
||||||
mj_invVelocity(m, d);
|
mj_invVelocity(m, d);
|
||||||
if (!skipsensor) {
|
if (!skipsensor) {
|
||||||
mj_sensorVel(m, d);
|
mj_sensorVel(m, d);
|
||||||
@@ -152,7 +152,7 @@ void mj_inverseSkip(const mjModel* m, mjData* d,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// qfrc_inverse += artmature*qacc - qfrc_passive - qfrc_constraint
|
// qfrc_inverse += artmature*qacc - qfrc_passive - qfrc_constraint
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
d->qfrc_inverse[i] += m->dof_armature[i]*d->qacc[i]
|
d->qfrc_inverse[i] += m->dof_armature[i]*d->qacc[i]
|
||||||
- d->qfrc_passive[i] - d->qfrc_constraint[i];
|
- d->qfrc_passive[i] - d->qfrc_constraint[i];
|
||||||
}
|
}
|
||||||
|
|||||||
+152
-152
@@ -285,7 +285,7 @@ static void bufwrite(const void* src, int num, int szbuf, void* buf, int* ptrbuf
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check size
|
// check size
|
||||||
if (*ptrbuf+num>szbuf) {
|
if (*ptrbuf+num > szbuf) {
|
||||||
mju_error("Attempting to write outside model buffer");
|
mju_error("Attempting to write outside model buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +304,7 @@ static void bufread(void* dest, int num, int szbuf, const void* buf, int* ptrbuf
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check size
|
// check size
|
||||||
if (*ptrbuf+num>szbuf) {
|
if (*ptrbuf+num > szbuf) {
|
||||||
mju_error("Attempting to read outside model buffer");
|
mju_error("Attempting to read outside model buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,7 +362,7 @@ static int safeAddToBufferSize(intptr_t* offset, int* nbuffer, size_t type_size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#if (__has_builtin(__builtin_add_overflow) && __has_builtin(__builtin_mul_overflow)) \
|
#if (__has_builtin(__builtin_add_overflow) && __has_builtin(__builtin_mul_overflow)) \
|
||||||
|| (defined(__GNUC__) && __GNUC__ >= 5)
|
|| (defined(__GNUC__) && __GNUC__ >= 5)
|
||||||
// supported by GCC and Clang
|
// supported by GCC and Clang
|
||||||
int to_add = 0;
|
int to_add = 0;
|
||||||
if (__builtin_mul_overflow(nc, nr, &to_add)) return 0;
|
if (__builtin_mul_overflow(nc, nr, &to_add)) return 0;
|
||||||
@@ -654,8 +654,8 @@ static mjModel* _mj_loadModel(const char* filename, int vfs_provider) {
|
|||||||
bufread(header, 4*sizeof(int), buffer_sz, buffer, &ptrbuf);
|
bufread(header, 4*sizeof(int), buffer_sz, buffer, &ptrbuf);
|
||||||
|
|
||||||
// check header
|
// check header
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i < 4; i++) {
|
||||||
if (header[i]!=expected_header[i]) {
|
if (header[i] != expected_header[i]) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
mju_warning("Model missing header ID");
|
mju_warning("Model missing header ID");
|
||||||
@@ -692,7 +692,7 @@ static mjModel* _mj_loadModel(const char* filename, int vfs_provider) {
|
|||||||
info[35], info[36], info[37], info[38], info[39], info[40], info[41],
|
info[35], info[36], info[37], info[38], info[39], info[40], info[41],
|
||||||
info[42], info[43], info[44], info[45], info[46], info[47], info[48],
|
info[42], info[43], info[44], info[45], info[46], info[47], info[48],
|
||||||
info[49], info[50], info[51], info[52]);
|
info[49], info[50], info[51], info[52]);
|
||||||
if (!m || m->nbuffer!=info[getnint()-1]) {
|
if (!m || m->nbuffer != info[getnint()-1]) {
|
||||||
mju_closeResource(r);
|
mju_closeResource(r);
|
||||||
mju_warning("Corrupted model, wrong size parameters");
|
mju_warning("Corrupted model, wrong size parameters");
|
||||||
mj_deleteModel(m);
|
mj_deleteModel(m);
|
||||||
@@ -775,7 +775,7 @@ int mj_sizeModel(const mjModel* m) {
|
|||||||
+ sizeof(mjVisual)
|
+ sizeof(mjVisual)
|
||||||
+ sizeof(mjStatistic));
|
+ sizeof(mjStatistic));
|
||||||
|
|
||||||
MJMODEL_POINTERS_PREAMBLE(m)
|
MJMODEL_POINTERS_PREAMBLE(m)
|
||||||
#define X(type, name, nr, nc) \
|
#define X(type, name, nr, nc) \
|
||||||
size += sizeof(type)*(m->nr)*(nc);
|
size += sizeof(type)*(m->nr)*(nc);
|
||||||
MJMODEL_POINTERS
|
MJMODEL_POINTERS
|
||||||
@@ -1367,16 +1367,16 @@ static void _resetData(const mjModel* m, mjData* d, unsigned char debug_value) {
|
|||||||
|
|
||||||
// set mocap_pos/quat = body_pos/quat for mocap bodies
|
// set mocap_pos/quat = body_pos/quat for mocap bodies
|
||||||
if (m->body_mocapid) {
|
if (m->body_mocapid) {
|
||||||
for (int i=0; i<m->nbody; i++) {
|
for (int i=0; i < m->nbody; i++) {
|
||||||
int id = m->body_mocapid[i];
|
int id = m->body_mocapid[i];
|
||||||
if (id>=0) {
|
if (id >= 0) {
|
||||||
mju_copy3(d->mocap_pos+3*id, m->body_pos+3*i);
|
mju_copy3(d->mocap_pos+3*id, m->body_pos+3*i);
|
||||||
mju_copy4(d->mocap_quat+4*id, m->body_quat+4*i);
|
mju_copy4(d->mocap_quat+4*id, m->body_quat+4*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// set the mocap_quats to {1, 0, 0, 0}
|
// set the mocap_quats to {1, 0, 0, 0}
|
||||||
for (int i=0; i<m->nmocap; i++) {
|
for (int i=0; i < m->nmocap; i++) {
|
||||||
d->mocap_quat[4*i] = 1.0;
|
d->mocap_quat[4*i] = 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1426,7 +1426,7 @@ void mj_resetDataKeyframe(const mjModel* m, mjData* d, int key) {
|
|||||||
_resetData(m, d, 0);
|
_resetData(m, d, 0);
|
||||||
|
|
||||||
// copy keyframe data if key is valid
|
// copy keyframe data if key is valid
|
||||||
if (key>=0 && key<m->nkey) {
|
if (key >= 0 && key < m->nkey) {
|
||||||
d->time = m->key_time[key];
|
d->time = m->key_time[key];
|
||||||
mju_copy(d->qpos, m->key_qpos+key*m->nq, m->nq);
|
mju_copy(d->qpos, m->key_qpos+key*m->nq, m->nq);
|
||||||
mju_copy(d->qvel, m->key_qvel+key*m->nv, m->nv);
|
mju_copy(d->qvel, m->key_qvel+key*m->nv, m->nv);
|
||||||
@@ -1510,7 +1510,7 @@ static int sensorSize(mjtSensor sensor_type, int sensor_dim) {
|
|||||||
case mjSENS_PLUGIN:
|
case mjSENS_PLUGIN:
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// don't use a 'default' case, so compiler warns about missing values
|
// don't use a 'default' case, so compiler warns about missing values
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1520,55 +1520,55 @@ static int sensorSize(mjtSensor sensor_type, int sensor_dim) {
|
|||||||
// -2: invalid objtype
|
// -2: invalid objtype
|
||||||
static int numObjects(const mjModel* m, mjtObj objtype) {
|
static int numObjects(const mjModel* m, mjtObj objtype) {
|
||||||
switch (objtype) {
|
switch (objtype) {
|
||||||
case mjOBJ_UNKNOWN:
|
case mjOBJ_UNKNOWN:
|
||||||
return -1;
|
return -1;
|
||||||
case mjOBJ_BODY:
|
case mjOBJ_BODY:
|
||||||
case mjOBJ_XBODY:
|
case mjOBJ_XBODY:
|
||||||
return m->nbody;
|
return m->nbody;
|
||||||
case mjOBJ_JOINT:
|
case mjOBJ_JOINT:
|
||||||
return m->njnt;
|
return m->njnt;
|
||||||
case mjOBJ_DOF:
|
case mjOBJ_DOF:
|
||||||
return m->nv;
|
return m->nv;
|
||||||
case mjOBJ_GEOM:
|
case mjOBJ_GEOM:
|
||||||
return m->ngeom;
|
return m->ngeom;
|
||||||
case mjOBJ_SITE:
|
case mjOBJ_SITE:
|
||||||
return m->nsite;
|
return m->nsite;
|
||||||
case mjOBJ_CAMERA:
|
case mjOBJ_CAMERA:
|
||||||
return m->ncam;
|
return m->ncam;
|
||||||
case mjOBJ_LIGHT:
|
case mjOBJ_LIGHT:
|
||||||
return m->nlight;
|
return m->nlight;
|
||||||
case mjOBJ_MESH:
|
case mjOBJ_MESH:
|
||||||
return m->nmesh;
|
return m->nmesh;
|
||||||
case mjOBJ_SKIN:
|
case mjOBJ_SKIN:
|
||||||
return m->nskin;
|
return m->nskin;
|
||||||
case mjOBJ_HFIELD:
|
case mjOBJ_HFIELD:
|
||||||
return m->nhfield;
|
return m->nhfield;
|
||||||
case mjOBJ_TEXTURE:
|
case mjOBJ_TEXTURE:
|
||||||
return m->ntex;
|
return m->ntex;
|
||||||
case mjOBJ_MATERIAL:
|
case mjOBJ_MATERIAL:
|
||||||
return m->nmat;
|
return m->nmat;
|
||||||
case mjOBJ_PAIR:
|
case mjOBJ_PAIR:
|
||||||
return m->npair;
|
return m->npair;
|
||||||
case mjOBJ_EXCLUDE:
|
case mjOBJ_EXCLUDE:
|
||||||
return m->nexclude;
|
return m->nexclude;
|
||||||
case mjOBJ_EQUALITY:
|
case mjOBJ_EQUALITY:
|
||||||
return m->neq;
|
return m->neq;
|
||||||
case mjOBJ_TENDON:
|
case mjOBJ_TENDON:
|
||||||
return m->ntendon;
|
return m->ntendon;
|
||||||
case mjOBJ_ACTUATOR:
|
case mjOBJ_ACTUATOR:
|
||||||
return m->nu;
|
return m->nu;
|
||||||
case mjOBJ_SENSOR:
|
case mjOBJ_SENSOR:
|
||||||
return m->nsensor;
|
return m->nsensor;
|
||||||
case mjOBJ_NUMERIC:
|
case mjOBJ_NUMERIC:
|
||||||
return m->nnumeric;
|
return m->nnumeric;
|
||||||
case mjOBJ_TEXT:
|
case mjOBJ_TEXT:
|
||||||
return m->ntext;
|
return m->ntext;
|
||||||
case mjOBJ_TUPLE:
|
case mjOBJ_TUPLE:
|
||||||
return m->ntuple;
|
return m->ntuple;
|
||||||
case mjOBJ_KEY:
|
case mjOBJ_KEY:
|
||||||
return m->nkey;
|
return m->nkey;
|
||||||
case mjOBJ_PLUGIN:
|
case mjOBJ_PLUGIN:
|
||||||
return m->nplugin;
|
return m->nplugin;
|
||||||
}
|
}
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
@@ -1675,7 +1675,7 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
#undef MJMODEL_REFERENCES
|
#undef MJMODEL_REFERENCES
|
||||||
|
|
||||||
// special logic that doesn't fit in the macro:
|
// special logic that doesn't fit in the macro:
|
||||||
for (int i=0; i<m->nbody; i++) {
|
for (int i=0; i < m->nbody; i++) {
|
||||||
if (i > 0 && m->body_parentid[i] >= i) {
|
if (i > 0 && m->body_parentid[i] >= i) {
|
||||||
return "Invalid model: bad body_parentid.";
|
return "Invalid model: bad body_parentid.";
|
||||||
}
|
}
|
||||||
@@ -1686,7 +1686,7 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
return "Invalid model: bad body_weldid.";
|
return "Invalid model: bad body_weldid.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
if (m->jnt_type[i] >= 4 || m->jnt_type[i] < 0) {
|
if (m->jnt_type[i] >= 4 || m->jnt_type[i] < 0) {
|
||||||
return "Invalid model: jnt_type out of bounds.";
|
return "Invalid model: jnt_type out of bounds.";
|
||||||
}
|
}
|
||||||
@@ -1699,12 +1699,12 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
return "Invalid model: jnt_dofadr out of bounds.";
|
return "Invalid model: jnt_dofadr out of bounds.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->nv; i++) {
|
for (int i=0; i < m->nv; i++) {
|
||||||
if (m->dof_parentid[i] >= i) {
|
if (m->dof_parentid[i] >= i) {
|
||||||
return "Invalid model: bad dof_parentid.";
|
return "Invalid model: bad dof_parentid.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->ngeom; i++) {
|
for (int i=0; i < m->ngeom; i++) {
|
||||||
if (m->geom_condim[i] > 6 || m->geom_condim[i] < 0) {
|
if (m->geom_condim[i] > 6 || m->geom_condim[i] < 0) {
|
||||||
return "Invalid model: geom_condim out of bounds.";
|
return "Invalid model: geom_condim out of bounds.";
|
||||||
}
|
}
|
||||||
@@ -1718,19 +1718,19 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->nhfield; i++) {
|
for (int i=0; i < m->nhfield; i++) {
|
||||||
int hfield_adr = m->hfield_adr[i] + m->hfield_nrow[i]*m->hfield_ncol[i];
|
int hfield_adr = m->hfield_adr[i] + m->hfield_nrow[i]*m->hfield_ncol[i];
|
||||||
if (hfield_adr > m->nhfielddata || m->hfield_adr[i] < 0) {
|
if (hfield_adr > m->nhfielddata || m->hfield_adr[i] < 0) {
|
||||||
return "Invalid model: hfield_adr out of bounds.";
|
return "Invalid model: hfield_adr out of bounds.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->ntex; i++) {
|
for (int i=0; i < m->ntex; i++) {
|
||||||
int tex_adr = m->tex_adr[i] + 3*m->tex_height[i]*m->tex_width[i];
|
int tex_adr = m->tex_adr[i] + 3*m->tex_height[i]*m->tex_width[i];
|
||||||
if (tex_adr > m->ntexdata || m->tex_adr[i] < 0) {
|
if (tex_adr > m->ntexdata || m->tex_adr[i] < 0) {
|
||||||
return "Invalid model: tex_adr out of bounds.";
|
return "Invalid model: tex_adr out of bounds.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->npair; i++) {
|
for (int i=0; i < m->npair; i++) {
|
||||||
int pair_body1 = (m->pair_signature[i] & 0xFFFF) - 1;
|
int pair_body1 = (m->pair_signature[i] & 0xFFFF) - 1;
|
||||||
if (pair_body1 >= m->nbody || pair_body1 < 0) {
|
if (pair_body1 >= m->nbody || pair_body1 < 0) {
|
||||||
return "Invalid model: pair_body1 out of bounds.";
|
return "Invalid model: pair_body1 out of bounds.";
|
||||||
@@ -1740,104 +1740,104 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
return "Invalid model: pair_body2 out of bounds.";
|
return "Invalid model: pair_body2 out of bounds.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->neq; i++) {
|
for (int i=0; i < m->neq; i++) {
|
||||||
int obj1id = m->eq_obj1id[i];
|
int obj1id = m->eq_obj1id[i];
|
||||||
int obj2id = m->eq_obj2id[i];
|
int obj2id = m->eq_obj2id[i];
|
||||||
switch (m->eq_type[i]) {
|
switch (m->eq_type[i]) {
|
||||||
case mjEQ_JOINT:
|
case mjEQ_JOINT:
|
||||||
if (obj1id >= m->njnt || obj1id < 0) {
|
if (obj1id >= m->njnt || obj1id < 0) {
|
||||||
return "Invalid model: eq_obj1id out of bounds.";
|
return "Invalid model: eq_obj1id out of bounds.";
|
||||||
}
|
}
|
||||||
// -1 is the value used if second object is omitted.
|
// -1 is the value used if second object is omitted.
|
||||||
if (obj2id >= m->njnt || obj2id < -1) {
|
if (obj2id >= m->njnt || obj2id < -1) {
|
||||||
return "Invalid model: eq_obj2id out of bounds.";
|
return "Invalid model: eq_obj2id out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjEQ_TENDON:
|
case mjEQ_TENDON:
|
||||||
if (obj1id >= m->ntendon || obj1id < 0) {
|
if (obj1id >= m->ntendon || obj1id < 0) {
|
||||||
return "Invalid model: eq_obj1id out of bounds.";
|
return "Invalid model: eq_obj1id out of bounds.";
|
||||||
}
|
}
|
||||||
// -1 is the value used if second object is omitted.
|
// -1 is the value used if second object is omitted.
|
||||||
if (obj2id >= m->ntendon || obj2id < -1) {
|
if (obj2id >= m->ntendon || obj2id < -1) {
|
||||||
return "Invalid model: eq_obj2id out of bounds.";
|
return "Invalid model: eq_obj2id out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjEQ_WELD:
|
case mjEQ_WELD:
|
||||||
case mjEQ_CONNECT:
|
case mjEQ_CONNECT:
|
||||||
if (obj1id >= m->nbody || obj1id < 0) {
|
if (obj1id >= m->nbody || obj1id < 0) {
|
||||||
return "Invalid model: eq_obj1id out of bounds.";
|
return "Invalid model: eq_obj1id out of bounds.";
|
||||||
}
|
}
|
||||||
if (obj2id >= m->nbody || obj2id < 0) {
|
if (obj2id >= m->nbody || obj2id < 0) {
|
||||||
return "Invalid model: eq_obj2id out of bounds.";
|
return "Invalid model: eq_obj2id out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mju_error("mj_validateReferences: unknown equality constraint type.");
|
mju_error("mj_validateReferences: unknown equality constraint type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->nwrap; i++) {
|
for (int i=0; i < m->nwrap; i++) {
|
||||||
int wrap_objid = m->wrap_objid[i];
|
int wrap_objid = m->wrap_objid[i];
|
||||||
switch (m->wrap_type[i]) {
|
switch (m->wrap_type[i]) {
|
||||||
case mjWRAP_NONE:
|
case mjWRAP_NONE:
|
||||||
case mjWRAP_PULLEY:
|
case mjWRAP_PULLEY:
|
||||||
// wrap_objid not used.
|
// wrap_objid not used.
|
||||||
break;
|
break;
|
||||||
case mjWRAP_JOINT:
|
case mjWRAP_JOINT:
|
||||||
if (wrap_objid >= m->njnt || wrap_objid < 0) {
|
if (wrap_objid >= m->njnt || wrap_objid < 0) {
|
||||||
return "Invalid model: wrap_objid out of bounds.";
|
return "Invalid model: wrap_objid out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjWRAP_SITE:
|
case mjWRAP_SITE:
|
||||||
if (wrap_objid >= m->nsite || wrap_objid < 0) {
|
if (wrap_objid >= m->nsite || wrap_objid < 0) {
|
||||||
return "Invalid model: wrap_objid out of bounds.";
|
return "Invalid model: wrap_objid out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjWRAP_SPHERE:
|
case mjWRAP_SPHERE:
|
||||||
case mjWRAP_CYLINDER:
|
case mjWRAP_CYLINDER:
|
||||||
if (wrap_objid >= m->ngeom || wrap_objid < 0) {
|
if (wrap_objid >= m->ngeom || wrap_objid < 0) {
|
||||||
return "Invalid model: wrap_objid out of bounds.";
|
return "Invalid model: wrap_objid out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->nu; i++) {
|
for (int i=0; i < m->nu; i++) {
|
||||||
int actuator_trntype = m->actuator_trntype[i];
|
int actuator_trntype = m->actuator_trntype[i];
|
||||||
int id = m->actuator_trnid[2*i];
|
int id = m->actuator_trnid[2*i];
|
||||||
int idslider = m->actuator_trnid[2*i+1];
|
int idslider = m->actuator_trnid[2*i+1];
|
||||||
switch (actuator_trntype) {
|
switch (actuator_trntype) {
|
||||||
case mjTRN_JOINT:
|
case mjTRN_JOINT:
|
||||||
case mjTRN_JOINTINPARENT:
|
case mjTRN_JOINTINPARENT:
|
||||||
if (id < 0 || id >= m->njnt) {
|
if (id < 0 || id >= m->njnt) {
|
||||||
return "Invalid model: actuator_trnid out of bounds.";
|
return "Invalid model: actuator_trnid out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjTRN_TENDON:
|
case mjTRN_TENDON:
|
||||||
if (id < 0 || id >= m->ntendon) {
|
if (id < 0 || id >= m->ntendon) {
|
||||||
return "Invalid model: actuator_trnid out of bounds.";
|
return "Invalid model: actuator_trnid out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjTRN_SITE:
|
case mjTRN_SITE:
|
||||||
if (id < 0 || id >= m->nsite) {
|
if (id < 0 || id >= m->nsite) {
|
||||||
return "Invalid model: actuator_trnid out of bounds.";
|
return "Invalid model: actuator_trnid out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjTRN_SLIDERCRANK:
|
case mjTRN_SLIDERCRANK:
|
||||||
if (id < 0 || id >= m->nsite) {
|
if (id < 0 || id >= m->nsite) {
|
||||||
return "Invalid model: actuator_trnid out of bounds.";
|
return "Invalid model: actuator_trnid out of bounds.";
|
||||||
}
|
}
|
||||||
if (idslider < 0 || idslider >= m->nsite) {
|
if (idslider < 0 || idslider >= m->nsite) {
|
||||||
return "Invalid model: actuator_trnid out of bounds.";
|
return "Invalid model: actuator_trnid out of bounds.";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case mjTRN_UNDEFINED:
|
case mjTRN_UNDEFINED:
|
||||||
// actuator_trnid not used.
|
// actuator_trnid not used.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->nsensor; i++) {
|
for (int i=0; i < m->nsensor; i++) {
|
||||||
mjtSensor sensor_type = m->sensor_type[i];
|
mjtSensor sensor_type = m->sensor_type[i];
|
||||||
int sensor_size;
|
int sensor_size;
|
||||||
if (sensor_type == mjSENS_PLUGIN) {
|
if (sensor_type == mjSENS_PLUGIN) {
|
||||||
@@ -1851,7 +1851,7 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
sensor_size = sensorSize(sensor_type, m->sensor_dim[i]);
|
sensor_size = sensorSize(sensor_type, m->sensor_dim[i]);
|
||||||
}
|
}
|
||||||
if (sensor_size < 0) {
|
if (sensor_size < 0) {
|
||||||
return "Invalid model: Bad sensor_type.";
|
return "Invalid model: Bad sensor_type.";
|
||||||
}
|
}
|
||||||
int sensor_adr = m->sensor_adr[i];
|
int sensor_adr = m->sensor_adr[i];
|
||||||
if (sensor_adr < 0 || sensor_adr + sensor_size > m->nsensordata) {
|
if (sensor_adr < 0 || sensor_adr + sensor_size > m->nsensordata) {
|
||||||
@@ -1872,7 +1872,7 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
return "Invalid model: invalid sensor_refid";
|
return "Invalid model: invalid sensor_refid";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->nexclude; i++) {
|
for (int i=0; i < m->nexclude; i++) {
|
||||||
int exclude_body1 = (m->exclude_signature[i] & 0xFFFF) - 1;
|
int exclude_body1 = (m->exclude_signature[i] & 0xFFFF) - 1;
|
||||||
if (exclude_body1 >= m->nbody || exclude_body1 < 0) {
|
if (exclude_body1 >= m->nbody || exclude_body1 < 0) {
|
||||||
return "Invalid model: exclude_body1 out of bounds.";
|
return "Invalid model: exclude_body1 out of bounds.";
|
||||||
@@ -1882,8 +1882,8 @@ const char* mj_validateReferences(const mjModel* m) {
|
|||||||
return "Invalid model: exclude_body2 out of bounds.";
|
return "Invalid model: exclude_body2 out of bounds.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->ntuple; i++) {
|
for (int i=0; i < m->ntuple; i++) {
|
||||||
for (int j=0; j<m->tuple_size[i]; j++) {
|
for (int j=0; j < m->tuple_size[i]; j++) {
|
||||||
int adr = m->tuple_adr[i] + j;
|
int adr = m->tuple_adr[i] + j;
|
||||||
int nobj = numObjects(m, m->tuple_objtype[adr]);
|
int nobj = numObjects(m, m->tuple_objtype[adr]);
|
||||||
if (nobj == -2) {
|
if (nobj == -2) {
|
||||||
|
|||||||
+27
-27
@@ -48,7 +48,7 @@ void mj_passive(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// joint-level springs
|
// joint-level springs
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
stiffness = m->jnt_stiffness[i];
|
stiffness = m->jnt_stiffness[i];
|
||||||
|
|
||||||
int padr = m->jnt_qposadr[i];
|
int padr = m->jnt_qposadr[i];
|
||||||
@@ -85,13 +85,13 @@ void mj_passive(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dof-level dampers
|
// dof-level dampers
|
||||||
for (int i=0; i<m->nv; i++) {
|
for (int i=0; i < m->nv; i++) {
|
||||||
damping = m->dof_damping[i];
|
damping = m->dof_damping[i];
|
||||||
d->qfrc_passive[i] -= damping*d->qvel[i];
|
d->qfrc_passive[i] -= damping*d->qvel[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// tendon-level spring-dampers
|
// tendon-level spring-dampers
|
||||||
for (int i=0; i<m->ntendon; i++) {
|
for (int i=0; i < m->ntendon; i++) {
|
||||||
stiffness = m->tendon_stiffness[i];
|
stiffness = m->tendon_stiffness[i];
|
||||||
damping = m->tendon_damping[i];
|
damping = m->tendon_damping[i];
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ void mj_passive(const mjModel* m, mjData* d) {
|
|||||||
// transform to joint torque, add to qfrc_passive: dense or sparse
|
// transform to joint torque, add to qfrc_passive: dense or sparse
|
||||||
if (issparse) {
|
if (issparse) {
|
||||||
int end = d->ten_J_rowadr[i] + d->ten_J_rownnz[i];
|
int end = d->ten_J_rowadr[i] + d->ten_J_rownnz[i];
|
||||||
for (int j=d->ten_J_rowadr[i]; j<end; j++) {
|
for (int j=d->ten_J_rowadr[i]; j < end; j++) {
|
||||||
d->qfrc_passive[d->ten_J_colind[j]] += d->ten_J[j] * frc;
|
d->qfrc_passive[d->ten_J_colind[j]] += d->ten_J[j] * frc;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -126,7 +126,7 @@ void mj_passive(const mjModel* m, mjData* d) {
|
|||||||
mjtNum force[3], torque[3]={0};
|
mjtNum force[3], torque[3]={0};
|
||||||
|
|
||||||
// apply per-body gravity compensation
|
// apply per-body gravity compensation
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
if (m->body_gravcomp[i]) {
|
if (m->body_gravcomp[i]) {
|
||||||
mju_scl3(force, m->opt.gravity, -(m->body_mass[i]*m->body_gravcomp[i]));
|
mju_scl3(force, m->opt.gravity, -(m->body_mass[i]*m->body_gravcomp[i]));
|
||||||
mj_applyFT(m, d, force, torque, d->xipos+3*i, i, d->qfrc_passive);
|
mj_applyFT(m, d, force, torque, d->xipos+3*i, i, d->qfrc_passive);
|
||||||
@@ -135,15 +135,15 @@ void mj_passive(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// body-level viscosity, lift and drag
|
// body-level viscosity, lift and drag
|
||||||
if (m->opt.viscosity>0 || m->opt.density>0) {
|
if (m->opt.viscosity > 0 || m->opt.density > 0) {
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
if (m->body_mass[i]<mjMINVAL) {
|
if (m->body_mass[i] < mjMINVAL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int use_ellipsoid_model = 0;
|
int use_ellipsoid_model = 0;
|
||||||
// if any child geom uses the ellipsoid model, inertia-box model is disabled for parent body
|
// if any child geom uses the ellipsoid model, inertia-box model is disabled for parent body
|
||||||
for (int j=0; j<m->body_geomnum[i] && use_ellipsoid_model==0; j++) {
|
for (int j=0; j < m->body_geomnum[i] && use_ellipsoid_model == 0; j++) {
|
||||||
const int geomid = m->body_geomadr[i] + j;
|
const int geomid = m->body_geomadr[i] + j;
|
||||||
use_ellipsoid_model += (m->geom_fluid[mjNFLUID*geomid] > 0);
|
use_ellipsoid_model += (m->geom_fluid[mjNFLUID*geomid] > 0);
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ void mj_passive(const mjModel* m, mjData* d) {
|
|||||||
if (m->nplugin) {
|
if (m->nplugin) {
|
||||||
const int nslot = mjp_pluginCount();
|
const int nslot = mjp_pluginCount();
|
||||||
// iterate over plugins, call compute if type is mjPLUGIN_PASSIVE
|
// iterate over plugins, call compute if type is mjPLUGIN_PASSIVE
|
||||||
for (int i=0; i<m->nplugin; i++) {
|
for (int i=0; i < m->nplugin; i++) {
|
||||||
const int slot = m->plugin[i];
|
const int slot = m->plugin[i];
|
||||||
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
@@ -209,7 +209,7 @@ void mj_inertiaBoxFluidModel(const mjModel* m, mjData* d, int i) {
|
|||||||
mju_zero(lfrc, 6);
|
mju_zero(lfrc, 6);
|
||||||
|
|
||||||
// set viscous force and torque
|
// set viscous force and torque
|
||||||
if (m->opt.viscosity>0) {
|
if (m->opt.viscosity > 0) {
|
||||||
// diameter of sphere approximation
|
// diameter of sphere approximation
|
||||||
diam = (box[0] + box[1] + box[2])/3.0;
|
diam = (box[0] + box[1] + box[2])/3.0;
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ void mj_inertiaBoxFluidModel(const mjModel* m, mjData* d, int i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add lift and drag force and torque
|
// add lift and drag force and torque
|
||||||
if (m->opt.density>0) {
|
if (m->opt.density > 0) {
|
||||||
// force
|
// force
|
||||||
lfrc[3] -= 0.5*m->opt.density*box[1]*box[2]*mju_abs(lvel[3])*lvel[3];
|
lfrc[3] -= 0.5*m->opt.density*box[1]*box[2]*mju_abs(lvel[3])*lvel[3];
|
||||||
lfrc[4] -= 0.5*m->opt.density*box[0]*box[2]*mju_abs(lvel[4])*lvel[4];
|
lfrc[4] -= 0.5*m->opt.density*box[0]*box[2]*mju_abs(lvel[4])*lvel[4];
|
||||||
@@ -252,16 +252,16 @@ void mj_ellipsoidFluidModel(const mjModel* m, mjData* d, int bodyid) {
|
|||||||
mjtNum semiaxes[3], virtual_mass[3], virtual_inertia[3];
|
mjtNum semiaxes[3], virtual_mass[3], virtual_inertia[3];
|
||||||
mjtNum blunt_drag_coef, slender_drag_coef, ang_drag_coef;
|
mjtNum blunt_drag_coef, slender_drag_coef, ang_drag_coef;
|
||||||
|
|
||||||
for (int j=0; j<m->body_geomnum[bodyid]; j++) {
|
for (int j=0; j < m->body_geomnum[bodyid]; j++) {
|
||||||
const int geomid = m->body_geomadr[bodyid] + j;
|
const int geomid = m->body_geomadr[bodyid] + j;
|
||||||
|
|
||||||
mju_geomSemiAxes(m, geomid, semiaxes);
|
mju_geomSemiAxes(m, geomid, semiaxes);
|
||||||
|
|
||||||
readFluidGeomInteraction(
|
readFluidGeomInteraction(
|
||||||
m->geom_fluid + mjNFLUID*geomid, &geom_interaction_coef,
|
m->geom_fluid + mjNFLUID*geomid, &geom_interaction_coef,
|
||||||
&blunt_drag_coef, &slender_drag_coef, &ang_drag_coef,
|
&blunt_drag_coef, &slender_drag_coef, &ang_drag_coef,
|
||||||
&kutta_lift_coef, &magnus_lift_coef,
|
&kutta_lift_coef, &magnus_lift_coef,
|
||||||
virtual_mass, virtual_inertia);
|
virtual_mass, virtual_inertia);
|
||||||
|
|
||||||
// scales all forces, read from MJCF as boolean (0.0 or 1.0)
|
// scales all forces, read from MJCF as boolean (0.0 or 1.0)
|
||||||
if (geom_interaction_coef == 0.0) {
|
if (geom_interaction_coef == 0.0) {
|
||||||
@@ -364,11 +364,11 @@ static inline mjtNum mji_ellipsoid_max_moment(const mjtNum size[3], const int di
|
|||||||
|
|
||||||
// lift and drag forces due to motion in the fluid
|
// lift and drag forces due to motion in the fluid
|
||||||
void mj_viscousForces(
|
void mj_viscousForces(
|
||||||
const mjtNum local_vels[6], const mjtNum fluid_density,
|
const mjtNum local_vels[6], const mjtNum fluid_density,
|
||||||
const mjtNum fluid_viscosity, const mjtNum size[3],
|
const mjtNum fluid_viscosity, const mjtNum size[3],
|
||||||
const mjtNum magnus_lift_coef, const mjtNum kutta_lift_coef,
|
const mjtNum magnus_lift_coef, const mjtNum kutta_lift_coef,
|
||||||
const mjtNum blunt_drag_coef, const mjtNum slender_drag_coef,
|
const mjtNum blunt_drag_coef, const mjtNum slender_drag_coef,
|
||||||
const mjtNum ang_drag_coef, mjtNum local_force[6])
|
const mjtNum ang_drag_coef, mjtNum local_force[6])
|
||||||
{
|
{
|
||||||
const mjtNum lin_vel[3] = {local_vels[3], local_vels[4], local_vels[5]};
|
const mjtNum lin_vel[3] = {local_vels[3], local_vels[4], local_vels[5]};
|
||||||
const mjtNum ang_vel[3] = {local_vels[0], local_vels[1], local_vels[2]};
|
const mjtNum ang_vel[3] = {local_vels[0], local_vels[1], local_vels[2]};
|
||||||
@@ -406,7 +406,7 @@ void mj_viscousForces(
|
|||||||
// cosine between velocity and normal to the surface
|
// cosine between velocity and normal to the surface
|
||||||
// divided by proj_denom instead of sqrt(proj_denom) to account for skipped normalization in norm
|
// divided by proj_denom instead of sqrt(proj_denom) to account for skipped normalization in norm
|
||||||
const mjtNum cos_alpha = proj_num / mju_max(
|
const mjtNum cos_alpha = proj_num / mju_max(
|
||||||
mjMINVAL, mju_norm3(lin_vel) * proj_denom);
|
mjMINVAL, mju_norm3(lin_vel) * proj_denom);
|
||||||
mjtNum kutta_circ[3];
|
mjtNum kutta_circ[3];
|
||||||
mju_cross(kutta_circ, norm, lin_vel);
|
mju_cross(kutta_circ, norm, lin_vel);
|
||||||
kutta_circ[0] *= kutta_lift_coef * fluid_density * cos_alpha * A_proj;
|
kutta_circ[0] *= kutta_lift_coef * fluid_density * cos_alpha * A_proj;
|
||||||
@@ -434,11 +434,11 @@ void mj_viscousForces(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const mjtNum drag_lin_coef = // linear plus quadratic
|
const mjtNum drag_lin_coef = // linear plus quadratic
|
||||||
fluid_viscosity*lin_visc_force_coef + fluid_density*mju_norm3(lin_vel)*(
|
fluid_viscosity*lin_visc_force_coef + fluid_density*mju_norm3(lin_vel)*(
|
||||||
A_proj*blunt_drag_coef + slender_drag_coef*(A_max - A_proj));
|
A_proj*blunt_drag_coef + slender_drag_coef*(A_max - A_proj));
|
||||||
const mjtNum drag_ang_coef = // linear plus quadratic
|
const mjtNum drag_ang_coef = // linear plus quadratic
|
||||||
fluid_viscosity * lin_visc_torq_coef +
|
fluid_viscosity * lin_visc_torq_coef +
|
||||||
fluid_density * mju_norm3(mom_visc);
|
fluid_density * mju_norm3(mom_visc);
|
||||||
|
|
||||||
local_force[0] -= drag_ang_coef * ang_vel[0];
|
local_force[0] -= drag_ang_coef * ang_vel[0];
|
||||||
local_force[1] -= drag_ang_coef * ang_vel[1];
|
local_force[1] -= drag_ang_coef * ang_vel[1];
|
||||||
|
|||||||
+76
-76
@@ -52,9 +52,9 @@ static void printArray(const char* str, int nr, int nc, const mjtNum* data, FILE
|
|||||||
}
|
}
|
||||||
if (nr && nc) {
|
if (nr && nc) {
|
||||||
fprintf(fp, "%s\n", str);
|
fprintf(fp, "%s\n", str);
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
for (int c=0; c<nc; c++) {
|
for (int c=0; c < nc; c++) {
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
fprintf(fp, float_format, data[c + r*nc]);
|
fprintf(fp, float_format, data[c + r*nc]);
|
||||||
}
|
}
|
||||||
@@ -72,9 +72,9 @@ static void printArrayInt(const char* str, int nr, int nc, const int* data, FILE
|
|||||||
}
|
}
|
||||||
if (nr && nc) {
|
if (nr && nc) {
|
||||||
fprintf(fp, "%s\n", str);
|
fprintf(fp, "%s\n", str);
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
for (int c=0; c<nc; c++) {
|
for (int c=0; c < nc; c++) {
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
fprintf(fp, "%d", data[c + r*nc]);
|
fprintf(fp, "%d", data[c + r*nc]);
|
||||||
}
|
}
|
||||||
@@ -95,9 +95,9 @@ static void printSparse(const char* str, const mjtNum* mat, int nr,
|
|||||||
}
|
}
|
||||||
fprintf(fp, "%s\n", str);
|
fprintf(fp, "%s\n", str);
|
||||||
|
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
for (int adr=rowadr[r]; adr<rowadr[r]+rownnz[r]; adr++) {
|
for (int adr=rowadr[r]; adr < rowadr[r]+rownnz[r]; adr++) {
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
fprintf(fp, "%d: ", colind[adr]);
|
fprintf(fp, "%d: ", colind[adr]);
|
||||||
fprintf(fp, float_format, mat[adr]);
|
fprintf(fp, float_format, mat[adr]);
|
||||||
@@ -119,7 +119,7 @@ static void printVector(const char* str, const mjtNum* data, int n, FILE* fp,
|
|||||||
fprintf(fp, "%s", str);
|
fprintf(fp, "%s", str);
|
||||||
|
|
||||||
// print data
|
// print data
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
fprintf(fp, float_format, data[i]);
|
fprintf(fp, float_format, data[i]);
|
||||||
}
|
}
|
||||||
@@ -199,11 +199,11 @@ static bool validateFloatFormat(const char* float_format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Clang sometimes goes OOM when the -Wuninitialized warning is enabled for this function
|
// Clang sometimes goes OOM when the -Wuninitialized warning is enabled for this function
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wuninitialized"
|
#pragma clang diagnostic ignored "-Wuninitialized"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// print mjModel to text file, specifying format. float_format must be a
|
// print mjModel to text file, specifying format. float_format must be a
|
||||||
@@ -231,7 +231,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
|
|
||||||
// compute total body mass
|
// compute total body mass
|
||||||
mjtNum totalmass = 0;
|
mjtNum totalmass = 0;
|
||||||
for (int i=0; i<m->nbody; i++) {
|
for (int i=0; i < m->nbody; i++) {
|
||||||
totalmass += m->body_mass[i];
|
totalmass += m->body_mass[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +305,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
|
|
||||||
// qpos0
|
// qpos0
|
||||||
fprintf(fp, NAME_FORMAT, "qpos0");
|
fprintf(fp, NAME_FORMAT, "qpos0");
|
||||||
for (int i=0; i<m->nq; i++) {
|
for (int i=0; i < m->nq; i++) {
|
||||||
fprintf(fp, float_format, m->qpos0[i]);
|
fprintf(fp, float_format, m->qpos0[i]);
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
|
|
||||||
// qpos_spring
|
// qpos_spring
|
||||||
fprintf(fp, NAME_FORMAT, "qpos_spring");
|
fprintf(fp, NAME_FORMAT, "qpos_spring");
|
||||||
for (int i=0; i<m->nq; i++) {
|
for (int i=0; i < m->nq; i++) {
|
||||||
fprintf(fp, float_format, m->qpos_spring[i]);
|
fprintf(fp, float_format, m->qpos_spring[i]);
|
||||||
fprintf(fp, " ");
|
fprintf(fp, " ");
|
||||||
}
|
}
|
||||||
@@ -347,7 +347,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bodies
|
// bodies
|
||||||
for (int i=0; i<m->nbody; i++) {
|
for (int i=0; i < m->nbody; i++) {
|
||||||
fprintf(fp, "\nBODY %d:\n", i);
|
fprintf(fp, "\nBODY %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_bodyadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_bodyadr[i]);
|
||||||
@@ -357,7 +357,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nbody) fprintf(fp, "\n");
|
if (m->nbody) fprintf(fp, "\n");
|
||||||
|
|
||||||
// joints
|
// joints
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
fprintf(fp, "\nJOINT %d:\n", i);
|
fprintf(fp, "\nJOINT %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_jntadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_jntadr[i]);
|
||||||
@@ -367,7 +367,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->njnt) fprintf(fp, "\n");
|
if (m->njnt) fprintf(fp, "\n");
|
||||||
|
|
||||||
// dofs
|
// dofs
|
||||||
for (int i=0; i<m->nv; i++) {
|
for (int i=0; i < m->nv; i++) {
|
||||||
fprintf(fp, "\nDOF %d:\n", i);
|
fprintf(fp, "\nDOF %d:\n", i);
|
||||||
object_class = &m->nv;
|
object_class = &m->nv;
|
||||||
MJMODEL_POINTERS
|
MJMODEL_POINTERS
|
||||||
@@ -375,7 +375,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nv) fprintf(fp, "\n");
|
if (m->nv) fprintf(fp, "\n");
|
||||||
|
|
||||||
// geoms
|
// geoms
|
||||||
for (int i=0; i<m->ngeom; i++) {
|
for (int i=0; i < m->ngeom; i++) {
|
||||||
fprintf(fp, "\nGEOM %d:\n", i);
|
fprintf(fp, "\nGEOM %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_geomadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_geomadr[i]);
|
||||||
@@ -385,7 +385,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->ngeom) fprintf(fp, "\n");
|
if (m->ngeom) fprintf(fp, "\n");
|
||||||
|
|
||||||
// sites
|
// sites
|
||||||
for (int i=0; i<m->nsite; i++) {
|
for (int i=0; i < m->nsite; i++) {
|
||||||
fprintf(fp, "\nSITE %d:\n", i);
|
fprintf(fp, "\nSITE %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_siteadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_siteadr[i]);
|
||||||
@@ -395,7 +395,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nsite) fprintf(fp, "\n");
|
if (m->nsite) fprintf(fp, "\n");
|
||||||
|
|
||||||
// cameras
|
// cameras
|
||||||
for (int i=0; i<m->ncam; i++) {
|
for (int i=0; i < m->ncam; i++) {
|
||||||
fprintf(fp, "\nCAMERA %d:\n", i);
|
fprintf(fp, "\nCAMERA %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_camadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_camadr[i]);
|
||||||
@@ -405,7 +405,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->ncam) fprintf(fp, "\n");
|
if (m->ncam) fprintf(fp, "\n");
|
||||||
|
|
||||||
// lights
|
// lights
|
||||||
for (int i=0; i<m->nlight; i++) {
|
for (int i=0; i < m->nlight; i++) {
|
||||||
fprintf(fp, "\nLIGHT %d:\n", i);
|
fprintf(fp, "\nLIGHT %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_lightadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_lightadr[i]);
|
||||||
@@ -415,13 +415,13 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nlight) fprintf(fp, "\n");
|
if (m->nlight) fprintf(fp, "\n");
|
||||||
|
|
||||||
// meshes
|
// meshes
|
||||||
for (int i=0; i<m->nmesh; i++) {
|
for (int i=0; i < m->nmesh; i++) {
|
||||||
fprintf(fp, "\nMESH %d:\n", i);
|
fprintf(fp, "\nMESH %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_meshadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_meshadr[i]);
|
||||||
object_class = &m->nmesh;
|
object_class = &m->nmesh;
|
||||||
MJMODEL_POINTERS
|
MJMODEL_POINTERS
|
||||||
if (m->mesh_graphadr[i]>=0) {
|
if (m->mesh_graphadr[i] >= 0) {
|
||||||
fprintf(fp, " " NAME_FORMAT, "qhull face");
|
fprintf(fp, " " NAME_FORMAT, "qhull face");
|
||||||
fprintf(fp, " %d\n", m->mesh_graph[m->mesh_graphadr[i]+1]);
|
fprintf(fp, " %d\n", m->mesh_graph[m->mesh_graphadr[i]+1]);
|
||||||
fprintf(fp, " " NAME_FORMAT, "qhull vert");
|
fprintf(fp, " " NAME_FORMAT, "qhull vert");
|
||||||
@@ -431,7 +431,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nmesh) fprintf(fp, "\n");
|
if (m->nmesh) fprintf(fp, "\n");
|
||||||
|
|
||||||
// skins
|
// skins
|
||||||
for (int i=0; i<m->nskin; i++) {
|
for (int i=0; i < m->nskin; i++) {
|
||||||
fprintf(fp, "\nSKIN %d:\n", i);
|
fprintf(fp, "\nSKIN %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_skinadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_skinadr[i]);
|
||||||
@@ -441,7 +441,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nskin) fprintf(fp, "\n");
|
if (m->nskin) fprintf(fp, "\n");
|
||||||
|
|
||||||
// hfields
|
// hfields
|
||||||
for (int i=0; i<m->nhfield; i++) {
|
for (int i=0; i < m->nhfield; i++) {
|
||||||
fprintf(fp, "\nHEIGHTFIELD %d:\n", i);
|
fprintf(fp, "\nHEIGHTFIELD %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_hfieldadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_hfieldadr[i]);
|
||||||
@@ -451,7 +451,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nhfield) fprintf(fp, "\n");
|
if (m->nhfield) fprintf(fp, "\n");
|
||||||
|
|
||||||
// textures
|
// textures
|
||||||
for (int i=0; i<m->ntex; i++) {
|
for (int i=0; i < m->ntex; i++) {
|
||||||
fprintf(fp, "\nTEXTURE %d:\n", i);
|
fprintf(fp, "\nTEXTURE %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_texadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_texadr[i]);
|
||||||
@@ -461,7 +461,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->ntex) fprintf(fp, "\n");
|
if (m->ntex) fprintf(fp, "\n");
|
||||||
|
|
||||||
// materials
|
// materials
|
||||||
for (int i=0; i<m->nmat; i++) {
|
for (int i=0; i < m->nmat; i++) {
|
||||||
fprintf(fp, "\nMATERIAL %d:\n", i);
|
fprintf(fp, "\nMATERIAL %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_matadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_matadr[i]);
|
||||||
@@ -471,7 +471,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nmat) fprintf(fp, "\n");
|
if (m->nmat) fprintf(fp, "\n");
|
||||||
|
|
||||||
// pairs
|
// pairs
|
||||||
for (int i=0; i<m->npair; i++) {
|
for (int i=0; i < m->npair; i++) {
|
||||||
fprintf(fp, "\nPAIR %d:\n", i);
|
fprintf(fp, "\nPAIR %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_pairadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_pairadr[i]);
|
||||||
@@ -481,7 +481,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->npair) fprintf(fp, "\n");
|
if (m->npair) fprintf(fp, "\n");
|
||||||
|
|
||||||
// excludes
|
// excludes
|
||||||
for (int i=0; i<m->nexclude; i++) {
|
for (int i=0; i < m->nexclude; i++) {
|
||||||
fprintf(fp, "\nEXCLUDE %d:\n", i);
|
fprintf(fp, "\nEXCLUDE %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_excludeadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_excludeadr[i]);
|
||||||
@@ -491,7 +491,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nexclude) fprintf(fp, "\n");
|
if (m->nexclude) fprintf(fp, "\n");
|
||||||
|
|
||||||
// equality constraints
|
// equality constraints
|
||||||
for (int i=0; i<m->neq; i++) {
|
for (int i=0; i < m->neq; i++) {
|
||||||
fprintf(fp, "\nEQUALITY %d:\n", i);
|
fprintf(fp, "\nEQUALITY %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_eqadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_eqadr[i]);
|
||||||
@@ -501,14 +501,14 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->neq) fprintf(fp, "\n");
|
if (m->neq) fprintf(fp, "\n");
|
||||||
|
|
||||||
// tendons
|
// tendons
|
||||||
for (int i=0; i<m->ntendon; i++) {
|
for (int i=0; i < m->ntendon; i++) {
|
||||||
fprintf(fp, "\nTENDON %d:\n", i);
|
fprintf(fp, "\nTENDON %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_tendonadr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_tendonadr[i]);
|
||||||
object_class = &m->ntendon;
|
object_class = &m->ntendon;
|
||||||
MJMODEL_POINTERS
|
MJMODEL_POINTERS
|
||||||
fprintf(fp, " path \n");
|
fprintf(fp, " path \n");
|
||||||
for (int j=0; j<m->tendon_num[i]; j++) {
|
for (int j=0; j < m->tendon_num[i]; j++) {
|
||||||
int k = m->tendon_adr[i]+j;
|
int k = m->tendon_adr[i]+j;
|
||||||
fprintf(fp, " %d %d ", m->wrap_type[k], m->wrap_objid[k]);
|
fprintf(fp, " %d %d ", m->wrap_type[k], m->wrap_objid[k]);
|
||||||
fprintf(fp, float_format, m->wrap_prm[k]);
|
fprintf(fp, float_format, m->wrap_prm[k]);
|
||||||
@@ -519,7 +519,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->ntendon) fprintf(fp, "\n");
|
if (m->ntendon) fprintf(fp, "\n");
|
||||||
|
|
||||||
// actuators
|
// actuators
|
||||||
for (int i=0; i<m->nu; i++) {
|
for (int i=0; i < m->nu; i++) {
|
||||||
fprintf(fp, "\nACTUATOR %d:\n", i);
|
fprintf(fp, "\nACTUATOR %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_actuatoradr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_actuatoradr[i]);
|
||||||
@@ -529,7 +529,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nu) fprintf(fp, "\n");
|
if (m->nu) fprintf(fp, "\n");
|
||||||
|
|
||||||
// sensors
|
// sensors
|
||||||
for (int i=0; i<m->nsensor; i++) {
|
for (int i=0; i < m->nsensor; i++) {
|
||||||
fprintf(fp, "\nSENSOR %d:\n", i);
|
fprintf(fp, "\nSENSOR %d:\n", i);
|
||||||
fprintf(fp, " " NAME_FORMAT, "name");
|
fprintf(fp, " " NAME_FORMAT, "name");
|
||||||
fprintf(fp, " %s\n", m->names + m->name_sensoradr[i]);
|
fprintf(fp, " %s\n", m->names + m->name_sensoradr[i]);
|
||||||
@@ -539,12 +539,12 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nsensor) fprintf(fp, "\n");
|
if (m->nsensor) fprintf(fp, "\n");
|
||||||
|
|
||||||
// custom numeric parameters
|
// custom numeric parameters
|
||||||
for (int i=0; i<m->nnumeric; i++) {
|
for (int i=0; i < m->nnumeric; i++) {
|
||||||
fprintf(fp, "\nNUMERIC %d:\n", i);
|
fprintf(fp, "\nNUMERIC %d:\n", i);
|
||||||
fprintf(fp, " name %s\n", m->names + m->name_numericadr[i]);
|
fprintf(fp, " name %s\n", m->names + m->name_numericadr[i]);
|
||||||
fprintf(fp, " size %d\n", m->numeric_size[i]);
|
fprintf(fp, " size %d\n", m->numeric_size[i]);
|
||||||
fprintf(fp, " value ");
|
fprintf(fp, " value ");
|
||||||
for (int j=0; j<m->numeric_size[i]; j++) {
|
for (int j=0; j < m->numeric_size[i]; j++) {
|
||||||
fprintf(fp, float_format, m->numeric_data[m->numeric_adr[i]+j]);
|
fprintf(fp, float_format, m->numeric_data[m->numeric_adr[i]+j]);
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
@@ -552,7 +552,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->nnumeric) fprintf(fp, "\n");
|
if (m->nnumeric) fprintf(fp, "\n");
|
||||||
|
|
||||||
// custom text parameters
|
// custom text parameters
|
||||||
for (int i=0; i<m->ntext; i++) {
|
for (int i=0; i < m->ntext; i++) {
|
||||||
fprintf(fp, "\nTEXT %d:\n", i);
|
fprintf(fp, "\nTEXT %d:\n", i);
|
||||||
fprintf(fp, " name %s\n", m->names + m->name_textadr[i]);
|
fprintf(fp, " name %s\n", m->names + m->name_textadr[i]);
|
||||||
fprintf(fp, " size %d\n", m->text_size[i]);
|
fprintf(fp, " size %d\n", m->text_size[i]);
|
||||||
@@ -561,12 +561,12 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->ntext) fprintf(fp, "\n");
|
if (m->ntext) fprintf(fp, "\n");
|
||||||
|
|
||||||
// custom tuple parameters
|
// custom tuple parameters
|
||||||
for (int i=0; i<m->ntuple; i++) {
|
for (int i=0; i < m->ntuple; i++) {
|
||||||
fprintf(fp, "\nTUPLE %d:\n", i);
|
fprintf(fp, "\nTUPLE %d:\n", i);
|
||||||
fprintf(fp, " name %s\n", m->names + m->name_tupleadr[i]);
|
fprintf(fp, " name %s\n", m->names + m->name_tupleadr[i]);
|
||||||
fprintf(fp, " size %d\n", m->tuple_size[i]);
|
fprintf(fp, " size %d\n", m->tuple_size[i]);
|
||||||
fprintf(fp, " elements\n");
|
fprintf(fp, " elements\n");
|
||||||
for (int j=m->tuple_adr[i]; j<m->tuple_adr[i]+m->tuple_size[i]; j++) {
|
for (int j=m->tuple_adr[i]; j < m->tuple_adr[i]+m->tuple_size[i]; j++) {
|
||||||
fprintf(fp, " %s %d, prm = ",
|
fprintf(fp, " %s %d, prm = ",
|
||||||
mju_type2Str(m->tuple_objtype[j]), m->tuple_objid[j]);
|
mju_type2Str(m->tuple_objtype[j]), m->tuple_objid[j]);
|
||||||
fprintf(fp, float_format, m->tuple_objprm[j]);
|
fprintf(fp, float_format, m->tuple_objprm[j]);
|
||||||
@@ -576,58 +576,58 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
if (m->ntuple) fprintf(fp, "\n");
|
if (m->ntuple) fprintf(fp, "\n");
|
||||||
|
|
||||||
// keyframes (only if different from default)
|
// keyframes (only if different from default)
|
||||||
for (int i=0; i<m->nkey; i++) {
|
for (int i=0; i < m->nkey; i++) {
|
||||||
// print name
|
// print name
|
||||||
if (m->names[m->name_keyadr[i]]) {
|
if (m->names[m->name_keyadr[i]]) {
|
||||||
fprintf(fp, "key_name%d %s\n", i, m->names + m->name_keyadr[i]);
|
fprintf(fp, "key_name%d %s\n", i, m->names + m->name_keyadr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// print time if non-0
|
// print time if non-0
|
||||||
if (m->key_time[i]!=0) {
|
if (m->key_time[i] != 0) {
|
||||||
fprintf(fp, "key_time%d %.4f\n", i, m->key_time[i]);
|
fprintf(fp, "key_time%d %.4f\n", i, m->key_time[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check qpos for difference
|
// check qpos for difference
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (int j=0; j<m->nq; j++)
|
for (int j=0; j < m->nq; j++)
|
||||||
if (m->qpos0[j] != m->key_qpos[i*m->nq + j]) {
|
if (m->qpos0[j] != m->key_qpos[i*m->nq + j]) {
|
||||||
k = 1;
|
k = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// print if different
|
// print if different
|
||||||
if (k==1) {
|
if (k == 1) {
|
||||||
fprintf(fp, "key_qpos%d ", i);
|
fprintf(fp, "key_qpos%d ", i);
|
||||||
for (int j=0; j<m->nq; j++) {
|
for (int j=0; j < m->nq; j++) {
|
||||||
fprintf(fp, float_format, m->key_qpos[i*m->nq + j]);
|
fprintf(fp, float_format, m->key_qpos[i*m->nq + j]);
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check qvel for nonzero
|
// check qvel for nonzero
|
||||||
for (int j=0; j<m->nv; j++)
|
for (int j=0; j < m->nv; j++)
|
||||||
if (m->key_qvel[i*m->nv + j]) {
|
if (m->key_qvel[i*m->nv + j]) {
|
||||||
k = 2;
|
k = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// print if nonzero
|
// print if nonzero
|
||||||
if (k==2) {
|
if (k == 2) {
|
||||||
fprintf(fp, "key_qvel%d ", i);
|
fprintf(fp, "key_qvel%d ", i);
|
||||||
for (int j=0; j<m->nv; j++) {
|
for (int j=0; j < m->nv; j++) {
|
||||||
fprintf(fp, float_format, m->key_qvel[i*m->nv + j]);
|
fprintf(fp, float_format, m->key_qvel[i*m->nv + j]);
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check act for nonzero
|
// check act for nonzero
|
||||||
for (int j=0; j<m->na; j++)
|
for (int j=0; j < m->na; j++)
|
||||||
if (m->key_act[i*m->na + j]) {
|
if (m->key_act[i*m->na + j]) {
|
||||||
k = 3;
|
k = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// print if nonzero
|
// print if nonzero
|
||||||
if (k==3) {
|
if (k == 3) {
|
||||||
fprintf(fp, "key_act%d ", i);
|
fprintf(fp, "key_act%d ", i);
|
||||||
for (int j=0; j<m->na; j++) {
|
for (int j=0; j < m->na; j++) {
|
||||||
fprintf(fp, float_format, m->key_act[i*m->na + j]);
|
fprintf(fp, float_format, m->key_act[i*m->na + j]);
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
@@ -635,10 +635,10 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
|
|
||||||
// check mpos for difference
|
// check mpos for difference
|
||||||
if (m->nmocap) {
|
if (m->nmocap) {
|
||||||
for (int j=0; j<m->nbody; j++) {
|
for (int j=0; j < m->nbody; j++) {
|
||||||
if (m->body_mocapid[j]>=0) {
|
if (m->body_mocapid[j] >= 0) {
|
||||||
int id = m->body_mocapid[j];
|
int id = m->body_mocapid[j];
|
||||||
if (m->body_pos[3*j] != m->key_mpos[i*3*m->nmocap + 3*id] ||
|
if (m->body_pos[3*j] != m->key_mpos[i*3*m->nmocap + 3*id] ||
|
||||||
m->body_pos[3*j+1] != m->key_mpos[i*3*m->nmocap + 3*id+1] ||
|
m->body_pos[3*j+1] != m->key_mpos[i*3*m->nmocap + 3*id+1] ||
|
||||||
m->body_pos[3*j+2] != m->key_mpos[i*3*m->nmocap + 3*id+2]) {
|
m->body_pos[3*j+2] != m->key_mpos[i*3*m->nmocap + 3*id+2]) {
|
||||||
k = 4;
|
k = 4;
|
||||||
@@ -649,9 +649,9 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print if nonzero
|
// print if nonzero
|
||||||
if (k==4) {
|
if (k == 4) {
|
||||||
fprintf(fp, "key_mpos%d ", i);
|
fprintf(fp, "key_mpos%d ", i);
|
||||||
for (int j=0; j<3*m->nmocap; j++) {
|
for (int j=0; j < 3*m->nmocap; j++) {
|
||||||
fprintf(fp, float_format, m->key_mpos[i*3*m->nmocap + j]);
|
fprintf(fp, float_format, m->key_mpos[i*3*m->nmocap + j]);
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
@@ -659,10 +659,10 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
|
|
||||||
// check mquat for difference
|
// check mquat for difference
|
||||||
if (m->nmocap) {
|
if (m->nmocap) {
|
||||||
for (int j=0; j<m->nbody; j++) {
|
for (int j=0; j < m->nbody; j++) {
|
||||||
if (m->body_mocapid[j]>=0) {
|
if (m->body_mocapid[j] >= 0) {
|
||||||
int id = m->body_mocapid[j];
|
int id = m->body_mocapid[j];
|
||||||
if (m->body_quat[4*j] != m->key_mquat[i*4*m->nmocap + 4*id] ||
|
if (m->body_quat[4*j] != m->key_mquat[i*4*m->nmocap + 4*id] ||
|
||||||
m->body_quat[4*j+1] != m->key_mquat[i*4*m->nmocap + 4*id+1] ||
|
m->body_quat[4*j+1] != m->key_mquat[i*4*m->nmocap + 4*id+1] ||
|
||||||
m->body_quat[4*j+2] != m->key_mquat[i*4*m->nmocap + 4*id+2] ||
|
m->body_quat[4*j+2] != m->key_mquat[i*4*m->nmocap + 4*id+2] ||
|
||||||
m->body_quat[4*j+3] != m->key_mquat[i*4*m->nmocap + 4*id+3]) {
|
m->body_quat[4*j+3] != m->key_mquat[i*4*m->nmocap + 4*id+3]) {
|
||||||
@@ -674,16 +674,16 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print if nonzero
|
// print if nonzero
|
||||||
if (k==5) {
|
if (k == 5) {
|
||||||
fprintf(fp, "key_mquat%d ", i);
|
fprintf(fp, "key_mquat%d ", i);
|
||||||
for (int j=0; j<4*m->nmocap; j++) {
|
for (int j=0; j < 4*m->nmocap; j++) {
|
||||||
fprintf(fp, float_format, m->key_mquat[i*4*m->nmocap + j]);
|
fprintf(fp, float_format, m->key_mquat[i*4*m->nmocap + j]);
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check ctrl for nonzero
|
// check ctrl for nonzero
|
||||||
for (int j=0; j<m->nu; j++) {
|
for (int j=0; j < m->nu; j++) {
|
||||||
if (m->key_ctrl[i*m->nu + j]) {
|
if (m->key_ctrl[i*m->nu + j]) {
|
||||||
k = 6;
|
k = 6;
|
||||||
break;
|
break;
|
||||||
@@ -691,9 +691,9 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// print if nonzero
|
// print if nonzero
|
||||||
if (k==6) {
|
if (k == 6) {
|
||||||
fprintf(fp, "key_ctrl%d ", i);
|
fprintf(fp, "key_ctrl%d ", i);
|
||||||
for (int j=0; j<m->nu; j++) {
|
for (int j=0; j < m->nu; j++) {
|
||||||
fprintf(fp, float_format, m->key_ctrl[i*m->nu + j]);
|
fprintf(fp, float_format, m->key_ctrl[i*m->nu + j]);
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
@@ -790,12 +790,12 @@ void mj_printFormattedData(const mjModel* m, mjData* d, const char* filename,
|
|||||||
|
|
||||||
// WARNING
|
// WARNING
|
||||||
int active_warnings = 0;
|
int active_warnings = 0;
|
||||||
for (int i=0; i<mjNWARNING; i++) {
|
for (int i=0; i < mjNWARNING; i++) {
|
||||||
active_warnings += d->warning[i].number;
|
active_warnings += d->warning[i].number;
|
||||||
}
|
}
|
||||||
if (active_warnings) {
|
if (active_warnings) {
|
||||||
fprintf(fp, "WARNING\n");
|
fprintf(fp, "WARNING\n");
|
||||||
for (int i=0; i<mjNWARNING; i++)
|
for (int i=0; i < mjNWARNING; i++)
|
||||||
if (d->warning[i].number)
|
if (d->warning[i].number)
|
||||||
fprintf(fp, " %d: lastinfo = %d number = %d\n",
|
fprintf(fp, " %d: lastinfo = %d number = %d\n",
|
||||||
i, d->warning[i].lastinfo, d->warning[i].number);
|
i, d->warning[i].lastinfo, d->warning[i].number);
|
||||||
@@ -804,12 +804,12 @@ void mj_printFormattedData(const mjModel* m, mjData* d, const char* filename,
|
|||||||
|
|
||||||
// TIMER
|
// TIMER
|
||||||
mjtNum active_timers = 0;
|
mjtNum active_timers = 0;
|
||||||
for (int i=0; i<mjNTIMER; i++) {
|
for (int i=0; i < mjNTIMER; i++) {
|
||||||
active_timers += d->timer[i].duration;
|
active_timers += d->timer[i].duration;
|
||||||
}
|
}
|
||||||
if (active_timers) {
|
if (active_timers) {
|
||||||
fprintf(fp, "TIMER\n");
|
fprintf(fp, "TIMER\n");
|
||||||
for (int i=0; i<mjNTIMER; i++) {
|
for (int i=0; i < mjNTIMER; i++) {
|
||||||
fprintf(fp, " %d: duration = ", i);
|
fprintf(fp, " %d: duration = ", i);
|
||||||
fprintf(fp, float_format, d->timer[i].duration);
|
fprintf(fp, float_format, d->timer[i].duration);
|
||||||
fprintf(fp, " number = %d\n", d->timer[i].number);
|
fprintf(fp, " number = %d\n", d->timer[i].number);
|
||||||
@@ -822,7 +822,7 @@ void mj_printFormattedData(const mjModel* m, mjData* d, const char* filename,
|
|||||||
fprintf(fp, "SOLVER STAT\n");
|
fprintf(fp, "SOLVER STAT\n");
|
||||||
fprintf(fp, " solver_iter = %d\n", d->solver_iter);
|
fprintf(fp, " solver_iter = %d\n", d->solver_iter);
|
||||||
fprintf(fp, " solver_nnz = %d\n", d->solver_nnz);
|
fprintf(fp, " solver_nnz = %d\n", d->solver_nnz);
|
||||||
for (int i=0; i<mjMIN(mjNSOLVER, d->solver_iter); i++) {
|
for (int i=0; i < mjMIN(mjNSOLVER, d->solver_iter); i++) {
|
||||||
fprintf(fp, " %d: improvement = ", i);
|
fprintf(fp, " %d: improvement = ", i);
|
||||||
fprintf(fp, float_format, d->solver[i].improvement);
|
fprintf(fp, float_format, d->solver[i].improvement);
|
||||||
fprintf(fp, " gradient = ");
|
fprintf(fp, " gradient = ");
|
||||||
@@ -886,11 +886,11 @@ void mj_printFormattedData(const mjModel* m, mjData* d, const char* filename,
|
|||||||
printArrayInt("TEN_J_ROWNNZ", m->ntendon, 1, d->ten_J_rownnz, fp);
|
printArrayInt("TEN_J_ROWNNZ", m->ntendon, 1, d->ten_J_rownnz, fp);
|
||||||
printArrayInt("TEN_J_ROWADR", m->ntendon, 1, d->ten_J_rowadr, fp);
|
printArrayInt("TEN_J_ROWADR", m->ntendon, 1, d->ten_J_rowadr, fp);
|
||||||
printSparse("TEN_J", d->ten_J, m->ntendon, d->ten_J_rownnz,
|
printSparse("TEN_J", d->ten_J, m->ntendon, d->ten_J_rownnz,
|
||||||
d->ten_J_rowadr, d->ten_J_colind, fp, float_format);
|
d->ten_J_rowadr, d->ten_J_colind, fp, float_format);
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->ntendon; i++) {
|
for (int i=0; i < m->ntendon; i++) {
|
||||||
fprintf(fp, "TENDON %d: %d wrap points\n", i, d->ten_wrapnum[i]);
|
fprintf(fp, "TENDON %d: %d wrap points\n", i, d->ten_wrapnum[i]);
|
||||||
for (int j=0; j<d->ten_wrapnum[i]; j++) {
|
for (int j=0; j < d->ten_wrapnum[i]; j++) {
|
||||||
fprintf(fp, " %d: ", d->wrap_obj[d->ten_wrapadr[i]+j]);
|
fprintf(fp, " %d: ", d->wrap_obj[d->ten_wrapadr[i]+j]);
|
||||||
printVector("", d->wrap_xpos+3*(d->ten_wrapadr[i]+j), 3, fp, float_format);
|
printVector("", d->wrap_xpos+3*(d->ten_wrapadr[i]+j), 3, fp, float_format);
|
||||||
}
|
}
|
||||||
@@ -965,7 +965,7 @@ void mj_printFormattedData(const mjModel* m, mjData* d, const char* filename,
|
|||||||
|
|
||||||
// contact
|
// contact
|
||||||
fprintf(fp, "CONTACT\n");
|
fprintf(fp, "CONTACT\n");
|
||||||
for (int i=0; i<d->ncon; i++) {
|
for (int i=0; i < d->ncon; i++) {
|
||||||
fprintf(fp, " %d:\n dim %d\n geom ", i, d->contact[i].dim);
|
fprintf(fp, " %d:\n dim %d\n geom ", i, d->contact[i].dim);
|
||||||
const char* geom1 = mj_id2name(m, mjOBJ_GEOM, d->contact[i].geom1);
|
const char* geom1 = mj_id2name(m, mjOBJ_GEOM, d->contact[i].geom1);
|
||||||
if (geom1) {
|
if (geom1) {
|
||||||
@@ -1066,9 +1066,9 @@ void mj_printFormattedData(const mjModel* m, mjData* d, const char* filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// print mjData to text file
|
// print mjData to text file
|
||||||
|
|||||||
+109
-109
@@ -67,22 +67,22 @@ static mjtNum latitude(const mjtNum vec[3]) {
|
|||||||
static int ray_eliminate(const mjModel* m, const mjData* d, int geomid,
|
static int ray_eliminate(const mjModel* m, const mjData* d, int geomid,
|
||||||
const mjtByte* geomgroup, mjtByte flg_static, int bodyexclude) {
|
const mjtByte* geomgroup, mjtByte flg_static, int bodyexclude) {
|
||||||
// body exclusion
|
// body exclusion
|
||||||
if (m->geom_bodyid[geomid]==bodyexclude) {
|
if (m->geom_bodyid[geomid] == bodyexclude) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// invisible geom exclusion
|
// invisible geom exclusion
|
||||||
if (m->geom_matid[geomid]<0 && m->geom_rgba[4*geomid+3]==0) {
|
if (m->geom_matid[geomid] < 0 && m->geom_rgba[4*geomid+3] == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// invisible material exclusion
|
// invisible material exclusion
|
||||||
if (m->geom_matid[geomid]>=0 && m->mat_rgba[4*m->geom_matid[geomid]+3]==0) {
|
if (m->geom_matid[geomid] >= 0 && m->mat_rgba[4*m->geom_matid[geomid]+3] == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static exclusion
|
// static exclusion
|
||||||
if (!flg_static && m->body_weldid[m->geom_bodyid[geomid]]==0) {
|
if (!flg_static && m->body_weldid[m->geom_bodyid[geomid]] == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ static int ray_eliminate(const mjModel* m, const mjData* d, int geomid,
|
|||||||
// group inclusion/exclusion
|
// group inclusion/exclusion
|
||||||
int groupid = mjMIN(mjNGROUP-1, mjMAX(0, m->geom_group[geomid]));
|
int groupid = mjMIN(mjNGROUP-1, mjMAX(0, m->geom_group[geomid]));
|
||||||
|
|
||||||
return (geomgroup[groupid]==0);
|
return (geomgroup[groupid] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ static int ray_eliminate(const mjModel* m, const mjData* d, int geomid,
|
|||||||
static mjtNum ray_quad(mjtNum a, mjtNum b, mjtNum c, mjtNum* x) {
|
static mjtNum ray_quad(mjtNum a, mjtNum b, mjtNum c, mjtNum* x) {
|
||||||
// compute determinant and check
|
// compute determinant and check
|
||||||
mjtNum det = b*b - a*c;
|
mjtNum det = b*b - a*c;
|
||||||
if (det<mjMINVAL) {
|
if (det < mjMINVAL) {
|
||||||
x[0] = -1;
|
x[0] = -1;
|
||||||
x[1] = -1;
|
x[1] = -1;
|
||||||
return -1;
|
return -1;
|
||||||
@@ -115,9 +115,9 @@ static mjtNum ray_quad(mjtNum a, mjtNum b, mjtNum c, mjtNum* x) {
|
|||||||
x[1] = (-b+det)/a;
|
x[1] = (-b+det)/a;
|
||||||
|
|
||||||
// finalize result
|
// finalize result
|
||||||
if (x[0]>=0) {
|
if (x[0] >= 0) {
|
||||||
return x[0];
|
return x[0];
|
||||||
} else if (x[1]>=0) {
|
} else if (x[1] >= 0) {
|
||||||
return x[1];
|
return x[1];
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -131,24 +131,24 @@ mjtNum ray_triangle(mjtNum v[][3], const mjtNum* lpnt, const mjtNum* lvec,
|
|||||||
const mjtNum* b0, const mjtNum* b1) {
|
const mjtNum* b0, const mjtNum* b1) {
|
||||||
// dif = v[i] - lpnt
|
// dif = v[i] - lpnt
|
||||||
mjtNum dif[3][3];
|
mjtNum dif[3][3];
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
dif[i][j] = v[i][j] - lpnt[j];
|
dif[i][j] = v[i][j] - lpnt[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// project difference vectors in normal plane
|
// project difference vectors in normal plane
|
||||||
mjtNum planar[3][2];
|
mjtNum planar[3][2];
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
planar[i][0] = mju_dot3(b0, dif[i]);
|
planar[i][0] = mju_dot3(b0, dif[i]);
|
||||||
planar[i][1] = mju_dot3(b1, dif[i]);
|
planar[i][1] = mju_dot3(b1, dif[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reject if on the same side of any coordinate axis
|
// reject if on the same side of any coordinate axis
|
||||||
if ((planar[0][0]>0 && planar[1][0]>0 && planar[2][0]>0) ||
|
if ((planar[0][0] > 0 && planar[1][0] > 0 && planar[2][0] > 0) ||
|
||||||
(planar[0][0]<0 && planar[1][0]<0 && planar[2][0]<0) ||
|
(planar[0][0] < 0 && planar[1][0] < 0 && planar[2][0] < 0) ||
|
||||||
(planar[0][1]>0 && planar[1][1]>0 && planar[2][1]>0) ||
|
(planar[0][1] > 0 && planar[1][1] > 0 && planar[2][1] > 0) ||
|
||||||
(planar[0][1]<0 && planar[1][1]<0 && planar[2][1]<0)) {
|
(planar[0][1] < 0 && planar[1][1] < 0 && planar[2][1] < 0)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,14 +158,14 @@ mjtNum ray_triangle(mjtNum v[][3], const mjtNum* lpnt, const mjtNum* lvec,
|
|||||||
planar[0][1]-planar[2][1], planar[1][1]-planar[2][1]};
|
planar[0][1]-planar[2][1], planar[1][1]-planar[2][1]};
|
||||||
mjtNum b[2] = {-planar[2][0], -planar[2][1]};
|
mjtNum b[2] = {-planar[2][0], -planar[2][1]};
|
||||||
mjtNum det = A[0]*A[3] - A[1]*A[2];
|
mjtNum det = A[0]*A[3] - A[1]*A[2];
|
||||||
if (mju_abs(det)<mjMINVAL) {
|
if (mju_abs(det) < mjMINVAL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mjtNum t0 = (A[3]*b[0] - A[1]*b[1]) / det;
|
mjtNum t0 = (A[3]*b[0] - A[1]*b[1]) / det;
|
||||||
mjtNum t1 = (-A[2]*b[0] + A[0]*b[1]) / det;
|
mjtNum t1 = (-A[2]*b[0] + A[0]*b[1]) / det;
|
||||||
|
|
||||||
// check if outside
|
// check if outside
|
||||||
if (t0<0 || t1<0|| t0+t1>1) {
|
if (t0 < 0 || t1 < 0|| t0+t1 > 1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ mjtNum ray_triangle(mjtNum v[][3], const mjtNum* lpnt, const mjtNum* lvec,
|
|||||||
mjtNum nrm[3];
|
mjtNum nrm[3];
|
||||||
mju_cross(nrm, dif[0], dif[1]); // normal to triangle plane
|
mju_cross(nrm, dif[0], dif[1]); // normal to triangle plane
|
||||||
mjtNum denom = mju_dot3(lvec, nrm);
|
mjtNum denom = mju_dot3(lvec, nrm);
|
||||||
if (mju_abs(denom)<mjMINVAL) {
|
if (mju_abs(denom) < mjMINVAL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,21 +193,21 @@ static mjtNum ray_plane(const mjtNum* pos, const mjtNum* mat, const mjtNum* size
|
|||||||
ray_map(pos, mat, pnt, vec, lpnt, lvec);
|
ray_map(pos, mat, pnt, vec, lpnt, lvec);
|
||||||
|
|
||||||
// z-vec not pointing towards front face: reject
|
// z-vec not pointing towards front face: reject
|
||||||
if (lvec[2]>-mjMINVAL) {
|
if (lvec[2] > -mjMINVAL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// intersection with plane
|
// intersection with plane
|
||||||
const mjtNum x = -lpnt[2]/lvec[2];
|
const mjtNum x = -lpnt[2]/lvec[2];
|
||||||
if (x<0) {
|
if (x < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mjtNum p0 = lpnt[0] + x*lvec[0];
|
mjtNum p0 = lpnt[0] + x*lvec[0];
|
||||||
mjtNum p1 = lpnt[1] + x*lvec[1];
|
mjtNum p1 = lpnt[1] + x*lvec[1];
|
||||||
|
|
||||||
// accept only within rendered rectangle
|
// accept only within rendered rectangle
|
||||||
if ((size[0]<=0 || mju_abs(p0)<=size[0]) &&
|
if ((size[0] <= 0 || mju_abs(p0) <= size[0]) &&
|
||||||
(size[1]<=0 || mju_abs(p1)<=size[1])) {
|
(size[1] <= 0 || mju_abs(p1) <= size[1])) {
|
||||||
return x;
|
return x;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -237,7 +237,7 @@ static mjtNum ray_capsule(const mjtNum* pos, const mjtNum* mat, const mjtNum* si
|
|||||||
const mjtNum* pnt, const mjtNum* vec) {
|
const mjtNum* pnt, const mjtNum* vec) {
|
||||||
// bounding sphere test
|
// bounding sphere test
|
||||||
mjtNum ssz = size[0] + size[1];
|
mjtNum ssz = size[0] + size[1];
|
||||||
if (ray_sphere(pos, NULL, ssz*ssz, pnt, vec)<0) {
|
if (ray_sphere(pos, NULL, ssz*ssz, pnt, vec) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,8 +257,8 @@ static mjtNum ray_capsule(const mjtNum* pos, const mjtNum* mat, const mjtNum* si
|
|||||||
sol = ray_quad(a, b, c, xx);
|
sol = ray_quad(a, b, c, xx);
|
||||||
|
|
||||||
// make sure round solution is between flat sides
|
// make sure round solution is between flat sides
|
||||||
if (sol>=0 && mju_abs(lpnt[2]+sol*lvec[2])<=size[1]) {
|
if (sol >= 0 && mju_abs(lpnt[2]+sol*lvec[2]) <= size[1]) {
|
||||||
if (x<0 || sol<x) {
|
if (x < 0 || sol < x) {
|
||||||
x = sol;
|
x = sol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,9 +271,9 @@ static mjtNum ray_capsule(const mjtNum* pos, const mjtNum* mat, const mjtNum* si
|
|||||||
ray_quad(a, b, c, xx);
|
ray_quad(a, b, c, xx);
|
||||||
|
|
||||||
// accept only top half of sphere
|
// accept only top half of sphere
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
if (xx[i]>=0 && lpnt[2]+xx[i]*lvec[2]>=size[1]) {
|
if (xx[i] >= 0 && lpnt[2]+xx[i]*lvec[2] >= size[1]) {
|
||||||
if (x<0 || xx[i]<x) {
|
if (x < 0 || xx[i] < x) {
|
||||||
x = xx[i];
|
x = xx[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,9 +286,9 @@ static mjtNum ray_capsule(const mjtNum* pos, const mjtNum* mat, const mjtNum* si
|
|||||||
ray_quad(a, b, c, xx);
|
ray_quad(a, b, c, xx);
|
||||||
|
|
||||||
// accept only bottom half of sphere
|
// accept only bottom half of sphere
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
if (xx[i]>=0 && lpnt[2]+xx[i]*lvec[2]<=-size[1]) {
|
if (xx[i] >= 0 && lpnt[2]+xx[i]*lvec[2] <= -size[1]) {
|
||||||
if (x<0 || xx[i]<x) {
|
if (x < 0 || xx[i] < x) {
|
||||||
x = xx[i];
|
x = xx[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,7 +326,7 @@ static mjtNum ray_cylinder(const mjtNum* pos, const mjtNum* mat, const mjtNum* s
|
|||||||
const mjtNum* pnt, const mjtNum* vec) {
|
const mjtNum* pnt, const mjtNum* vec) {
|
||||||
// bounding sphere test
|
// bounding sphere test
|
||||||
mjtNum ssz = size[0]*size[0] + size[1]*size[1];
|
mjtNum ssz = size[0]*size[0] + size[1]*size[1];
|
||||||
if (ray_sphere(pos, NULL, ssz, pnt, vec)<0) {
|
if (ray_sphere(pos, NULL, ssz, pnt, vec) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,20 +339,20 @@ static mjtNum ray_cylinder(const mjtNum* pos, const mjtNum* mat, const mjtNum* s
|
|||||||
|
|
||||||
// flat sides
|
// flat sides
|
||||||
int side;
|
int side;
|
||||||
if (mju_abs(lvec[2])>mjMINVAL) {
|
if (mju_abs(lvec[2]) > mjMINVAL) {
|
||||||
for (side=-1; side<=1; side+=2) {
|
for (side=-1; side <= 1; side+=2) {
|
||||||
// soludion of: lpnt[2] + x*lvec[2] = side*height_size
|
// soludion of: lpnt[2] + x*lvec[2] = side*height_size
|
||||||
sol = (side*size[1]-lpnt[2])/lvec[2];
|
sol = (side*size[1]-lpnt[2])/lvec[2];
|
||||||
|
|
||||||
// process if non-negative
|
// process if non-negative
|
||||||
if (sol>=0) {
|
if (sol >= 0) {
|
||||||
// intersection with horizontal face
|
// intersection with horizontal face
|
||||||
mjtNum p0 = lpnt[0] + sol*lvec[0];
|
mjtNum p0 = lpnt[0] + sol*lvec[0];
|
||||||
mjtNum p1 = lpnt[1] + sol*lvec[1];
|
mjtNum p1 = lpnt[1] + sol*lvec[1];
|
||||||
|
|
||||||
// accept within radius
|
// accept within radius
|
||||||
if (p0*p0 + p1*p1 <= size[0]*size[0]) {
|
if (p0*p0 + p1*p1 <= size[0]*size[0]) {
|
||||||
if (x<0 || sol<x) {
|
if (x < 0 || sol < x) {
|
||||||
x = sol;
|
x = sol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,8 +370,8 @@ static mjtNum ray_cylinder(const mjtNum* pos, const mjtNum* mat, const mjtNum* s
|
|||||||
sol = ray_quad(a, b, c, xx);
|
sol = ray_quad(a, b, c, xx);
|
||||||
|
|
||||||
// make sure round solution is between flat sides
|
// make sure round solution is between flat sides
|
||||||
if (sol>=0 && mju_abs(lpnt[2]+sol*lvec[2])<=size[1]) {
|
if (sol >= 0 && mju_abs(lpnt[2]+sol*lvec[2]) <= size[1]) {
|
||||||
if (x<0 || sol<x) {
|
if (x < 0 || sol < x) {
|
||||||
x = sol;
|
x = sol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,14 +386,14 @@ static mjtNum ray_box(const mjtNum* pos, const mjtNum* mat, const mjtNum* size,
|
|||||||
const mjtNum* pnt, const mjtNum* vec, mjtNum* all) {
|
const mjtNum* pnt, const mjtNum* vec, mjtNum* all) {
|
||||||
// clear all
|
// clear all
|
||||||
if (all) {
|
if (all) {
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i < 6; i++) {
|
||||||
all[i] = -1;
|
all[i] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bounding sphere test
|
// bounding sphere test
|
||||||
mjtNum ssz = size[0]*size[0] + size[1]*size[1] + size[2]*size[2];
|
mjtNum ssz = size[0]*size[0] + size[1]*size[1] + size[2]*size[2];
|
||||||
if (ray_sphere(pos, NULL, ssz, pnt, vec)<0) {
|
if (ray_sphere(pos, NULL, ssz, pnt, vec) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,23 +412,23 @@ static mjtNum ray_box(const mjtNum* pos, const mjtNum* mat, const mjtNum* size,
|
|||||||
mjtNum x = -1, sol;
|
mjtNum x = -1, sol;
|
||||||
|
|
||||||
// loop over axes with non-zero vec
|
// loop over axes with non-zero vec
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
if (mju_abs(lvec[i])>mjMINVAL) {
|
if (mju_abs(lvec[i]) > mjMINVAL) {
|
||||||
for (int side=-1; side<=1; side+=2) {
|
for (int side=-1; side <= 1; side+=2) {
|
||||||
// soludion of: lpnt[i] + x*lvec[i] = side*size[i]
|
// soludion of: lpnt[i] + x*lvec[i] = side*size[i]
|
||||||
sol = (side*size[i]-lpnt[i])/lvec[i];
|
sol = (side*size[i]-lpnt[i])/lvec[i];
|
||||||
|
|
||||||
// process if non-negative
|
// process if non-negative
|
||||||
if (sol>=0) {
|
if (sol >= 0) {
|
||||||
// intersection with face
|
// intersection with face
|
||||||
mjtNum p0 = lpnt[iface[i][0]] + sol*lvec[iface[i][0]];
|
mjtNum p0 = lpnt[iface[i][0]] + sol*lvec[iface[i][0]];
|
||||||
mjtNum p1 = lpnt[iface[i][1]] + sol*lvec[iface[i][1]];
|
mjtNum p1 = lpnt[iface[i][1]] + sol*lvec[iface[i][1]];
|
||||||
|
|
||||||
// accept within rectangle
|
// accept within rectangle
|
||||||
if (mju_abs(p0)<=size[iface[i][0]] &&
|
if (mju_abs(p0) <= size[iface[i][0]] &&
|
||||||
mju_abs(p1)<=size[iface[i][1]]) {
|
mju_abs(p1) <= size[iface[i][1]]) {
|
||||||
// update
|
// update
|
||||||
if (x<0 || sol<x) {
|
if (x < 0 || sol < x) {
|
||||||
x = sol;
|
x = sol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +451,7 @@ static mjtNum ray_box(const mjtNum* pos, const mjtNum* mat, const mjtNum* size,
|
|||||||
mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
||||||
const mjtNum* pnt, const mjtNum* vec) {
|
const mjtNum* pnt, const mjtNum* vec) {
|
||||||
// check geom type
|
// check geom type
|
||||||
if (m->geom_type[id]!=mjGEOM_HFIELD) {
|
if (m->geom_type[id] != mjGEOM_HFIELD) {
|
||||||
mju_error("mj_rayHfield: geom with hfield type expected");
|
mju_error("mj_rayHfield: geom with hfield type expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,7 +484,7 @@ mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
|||||||
// check top box: done if no intersection
|
// check top box: done if no intersection
|
||||||
mjtNum all[6];
|
mjtNum all[6];
|
||||||
mjtNum top_intersect = ray_box(top_pos, d->geom_xmat+9*id, top_size, pnt, vec, all);
|
mjtNum top_intersect = ray_box(top_pos, d->geom_xmat+9*id, top_size, pnt, vec, all);
|
||||||
if (top_intersect<0) {
|
if (top_intersect < 0) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,9 +494,9 @@ mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
|||||||
|
|
||||||
// construct basis vectors of normal plane
|
// construct basis vectors of normal plane
|
||||||
mjtNum b0[3] = {1, 1, 1}, b1[3];
|
mjtNum b0[3] = {1, 1, 1}, b1[3];
|
||||||
if (mju_abs(lvec[0])>=mju_abs(lvec[1]) && mju_abs(lvec[0])>=mju_abs(lvec[2])) {
|
if (mju_abs(lvec[0]) >= mju_abs(lvec[1]) && mju_abs(lvec[0]) >= mju_abs(lvec[2])) {
|
||||||
b0[0] = 0;
|
b0[0] = 0;
|
||||||
} else if (mju_abs(lvec[1])>=mju_abs(lvec[2])) {
|
} else if (mju_abs(lvec[1]) >= mju_abs(lvec[2])) {
|
||||||
b0[1] = 0;
|
b0[1] = 0;
|
||||||
} else {
|
} else {
|
||||||
b0[2] = 0;
|
b0[2] = 0;
|
||||||
@@ -508,8 +508,8 @@ mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
|||||||
|
|
||||||
// find ray segment intersecting top box
|
// find ray segment intersecting top box
|
||||||
mjtNum seg[2] = {0, top_intersect};
|
mjtNum seg[2] = {0, top_intersect};
|
||||||
for (int i=0; i<6; i++) {
|
for (int i=0; i < 6; i++) {
|
||||||
if (all[i]>seg[1]) {
|
if (all[i] > seg[1]) {
|
||||||
seg[0] = top_intersect;
|
seg[0] = top_intersect;
|
||||||
seg[1] = all[i];
|
seg[1] = all[i];
|
||||||
}
|
}
|
||||||
@@ -519,7 +519,7 @@ mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
|||||||
mjtNum dx = (2.0*size[0]) / (ncol-1);
|
mjtNum dx = (2.0*size[0]) / (ncol-1);
|
||||||
mjtNum dy = (2.0*size[1]) / (nrow-1);
|
mjtNum dy = (2.0*size[1]) / (nrow-1);
|
||||||
mjtNum SX[2], SY[2];
|
mjtNum SX[2], SY[2];
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
SX[i] = (lpnt[0] + seg[i]*lvec[0] + size[0]) / dx;
|
SX[i] = (lpnt[0] + seg[i]*lvec[0] + size[0]) / dx;
|
||||||
SY[i] = (lpnt[1] + seg[i]*lvec[1] + size[1]) / dy;
|
SY[i] = (lpnt[1] + seg[i]*lvec[1] + size[1]) / dy;
|
||||||
}
|
}
|
||||||
@@ -531,8 +531,8 @@ mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
|||||||
int rmax = mjMIN(nrow-1, (int)mju_ceil(mjMAX(SY[0], SY[1]))+1);
|
int rmax = mjMIN(nrow-1, (int)mju_ceil(mjMAX(SY[0], SY[1]))+1);
|
||||||
|
|
||||||
// check triangles within bounds
|
// check triangles within bounds
|
||||||
for (int r=rmin; r<rmax; r++) {
|
for (int r=rmin; r < rmax; r++) {
|
||||||
for (int c=cmin; c<cmax; c++) {
|
for (int c=cmin; c < cmax; c++) {
|
||||||
// first triangle
|
// first triangle
|
||||||
mjtNum va[3][3] = {
|
mjtNum va[3][3] = {
|
||||||
{dx*c-size[0], dy*r-size[1], data[r*ncol+c]*size[2]},
|
{dx*c-size[0], dy*r-size[1], data[r*ncol+c]*size[2]},
|
||||||
@@ -540,7 +540,7 @@ mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
|||||||
{dx*(c+1)-size[0], dy*r-size[1], data[r*ncol+(c+1)]*size[2]}
|
{dx*(c+1)-size[0], dy*r-size[1], data[r*ncol+(c+1)]*size[2]}
|
||||||
};
|
};
|
||||||
mjtNum sol = ray_triangle(va, lpnt, lvec, b0, b1);
|
mjtNum sol = ray_triangle(va, lpnt, lvec, b0, b1);
|
||||||
if (sol>=0 && (x<0 || sol<x)) {
|
if (sol >= 0 && (x < 0 || sol < x)) {
|
||||||
x = sol;
|
x = sol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,15 +551,15 @@ mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
|||||||
{dx*c-size[0], dy*(r+1)-size[1], data[(r+1)*ncol+c]*size[2]}
|
{dx*c-size[0], dy*(r+1)-size[1], data[(r+1)*ncol+c]*size[2]}
|
||||||
};
|
};
|
||||||
sol = ray_triangle(vb, lpnt, lvec, b0, b1);
|
sol = ray_triangle(vb, lpnt, lvec, b0, b1);
|
||||||
if (sol>=0 && (x<0 || sol<x)) {
|
if (sol >= 0 && (x < 0 || sol < x)) {
|
||||||
x = sol;
|
x = sol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check viable sides of top box
|
// check viable sides of top box
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i < 4; i++) {
|
||||||
if (all[i]>=0 && (all[i]<x || x<0)) {
|
if (all[i] >= 0 && (all[i] < x || x < 0)) {
|
||||||
// normalized height of intersection point
|
// normalized height of intersection point
|
||||||
mjtNum z = (lpnt[2] + all[i]*lvec[2]) / size[2];
|
mjtNum z = (lpnt[2] + all[i]*lvec[2]) / size[2];
|
||||||
|
|
||||||
@@ -567,19 +567,19 @@ mjtNum mj_rayHfield(const mjModel* m, const mjData* d, int id,
|
|||||||
mjtNum y, y0, z0, z1;
|
mjtNum y, y0, z0, z1;
|
||||||
|
|
||||||
// side normal to x-axis
|
// side normal to x-axis
|
||||||
if (i<2) {
|
if (i < 2) {
|
||||||
y = (lpnt[1] + all[i]*lvec[1] + size[1]) / dy;
|
y = (lpnt[1] + all[i]*lvec[1] + size[1]) / dy;
|
||||||
y0 = mjMAX(0, mjMIN(nrow-2, mju_floor(y)));
|
y0 = mjMAX(0, mjMIN(nrow-2, mju_floor(y)));
|
||||||
z0 = (mjtNum)data[mju_round(y0)*nrow + (i==1 ? ncol-1 : 0)];
|
z0 = (mjtNum)data[mju_round(y0)*nrow + (i == 1 ? ncol-1 : 0)];
|
||||||
z1 = (mjtNum)data[mju_round(y0+1)*nrow + (i==1 ? ncol-1 : 0)];
|
z1 = (mjtNum)data[mju_round(y0+1)*nrow + (i == 1 ? ncol-1 : 0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// side normal to y-axis
|
// side normal to y-axis
|
||||||
else {
|
else {
|
||||||
y = (lpnt[0] + all[i]*lvec[0] + size[0]) / dx;
|
y = (lpnt[0] + all[i]*lvec[0] + size[0]) / dx;
|
||||||
y0 = mjMAX(0, mjMIN(ncol-2, mju_floor(y)));
|
y0 = mjMAX(0, mjMIN(ncol-2, mju_floor(y)));
|
||||||
z0 = (mjtNum)data[mju_round(y0) + (i==3 ? (nrow-1)*ncol : 0)];
|
z0 = (mjtNum)data[mju_round(y0) + (i == 3 ? (nrow-1)*ncol : 0)];
|
||||||
z1 = (mjtNum)data[mju_round(y0+1) + (i==3 ? (nrow-1)*ncol : 0)];
|
z1 = (mjtNum)data[mju_round(y0+1) + (i == 3 ? (nrow-1)*ncol : 0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if point is below line segment
|
// check if point is below line segment
|
||||||
@@ -631,7 +631,7 @@ mjtNum mju_rayTree(const mjModel* m, const mjData* d, int id, const mjtNum* pnt,
|
|||||||
const mjtNum* bvh = m->bvh_aabb + 6*bvhadr;
|
const mjtNum* bvh = m->bvh_aabb + 6*bvhadr;
|
||||||
const int* child = m->bvh_child + 2*bvhadr;
|
const int* child = m->bvh_child + 2*bvhadr;
|
||||||
|
|
||||||
if (meshid==-1) {
|
if (meshid == -1) {
|
||||||
mju_error("mju_rayTree: mesh id of geom %d is -1", meshid); // SHOULD NOT OCCUR
|
mju_error("mju_rayTree: mesh id of geom %d is -1", meshid); // SHOULD NOT OCCUR
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,9 +647,9 @@ mjtNum mju_rayTree(const mjModel* m, const mjData* d, int id, const mjtNum* pnt,
|
|||||||
|
|
||||||
// construct basis vectors of normal plane
|
// construct basis vectors of normal plane
|
||||||
mjtNum b0[3] = {1, 1, 1}, b1[3];
|
mjtNum b0[3] = {1, 1, 1}, b1[3];
|
||||||
if (mju_abs(lvec[0])>=mju_abs(lvec[1]) && mju_abs(lvec[0])>=mju_abs(lvec[2])) {
|
if (mju_abs(lvec[0]) >= mju_abs(lvec[1]) && mju_abs(lvec[0]) >= mju_abs(lvec[2])) {
|
||||||
b0[0] = 0;
|
b0[0] = 0;
|
||||||
} else if (mju_abs(lvec[1])>=mju_abs(lvec[2])) {
|
} else if (mju_abs(lvec[1]) >= mju_abs(lvec[2])) {
|
||||||
b0[1] = 0;
|
b0[1] = 0;
|
||||||
} else {
|
} else {
|
||||||
b0[2] = 0;
|
b0[2] = 0;
|
||||||
@@ -687,8 +687,8 @@ mjtNum mju_rayTree(const mjModel* m, const mjData* d, int id, const mjtNum* pnt,
|
|||||||
|
|
||||||
// convert to mjtNum
|
// convert to mjtNum
|
||||||
mjtNum v[3][3];
|
mjtNum v[3][3];
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
v[i][j] = (mjtNum)vf[i][j];
|
v[i][j] = (mjtNum)vf[i][j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -697,7 +697,7 @@ mjtNum mju_rayTree(const mjModel* m, const mjData* d, int id, const mjtNum* pnt,
|
|||||||
sol = ray_triangle(v, lpnt, lvec, b0, b1);
|
sol = ray_triangle(v, lpnt, lvec, b0, b1);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
if (sol>=0 && (x<0 || sol<x)) {
|
if (sol >= 0 && (x < 0 || sol < x)) {
|
||||||
x = sol;
|
x = sol;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -707,7 +707,7 @@ mjtNum mju_rayTree(const mjModel* m, const mjData* d, int id, const mjtNum* pnt,
|
|||||||
d->bvh_active[node + bvhadr] = 1;
|
d->bvh_active[node + bvhadr] = 1;
|
||||||
|
|
||||||
// add children to the stack
|
// add children to the stack
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
if (child[2*node+i] != -1) {
|
if (child[2*node+i] != -1) {
|
||||||
if (nstack >= mjMAXTREEDEPTH) mju_error("BVH stack depth exceeded in geom %d.", id);
|
if (nstack >= mjMAXTREEDEPTH) mju_error("BVH stack depth exceeded in geom %d.", id);
|
||||||
stack[nstack] = child[2*node+i];
|
stack[nstack] = child[2*node+i];
|
||||||
@@ -723,12 +723,12 @@ mjtNum mju_rayTree(const mjModel* m, const mjData* d, int id, const mjtNum* pnt,
|
|||||||
mjtNum mj_rayMesh(const mjModel* m, const mjData* d, int id,
|
mjtNum mj_rayMesh(const mjModel* m, const mjData* d, int id,
|
||||||
const mjtNum* pnt, const mjtNum* vec) {
|
const mjtNum* pnt, const mjtNum* vec) {
|
||||||
// check geom type
|
// check geom type
|
||||||
if (m->geom_type[id]!=mjGEOM_MESH) {
|
if (m->geom_type[id] != mjGEOM_MESH) {
|
||||||
mju_error("mj_rayMesh: geom with mesh type expected");
|
mju_error("mj_rayMesh: geom with mesh type expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
// bounding box test
|
// bounding box test
|
||||||
if (ray_box(d->geom_xpos+3*id, d->geom_xmat+9*id, m->geom_size+3*id, pnt, vec, NULL)<0) {
|
if (ray_box(d->geom_xpos+3*id, d->geom_xmat+9*id, m->geom_size+3*id, pnt, vec, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,15 +772,15 @@ mjtNum mju_raySkin(int nface, int nvert, const int* face, const float* vert,
|
|||||||
const mjtNum* pnt, const mjtNum* vec, int vertid[1]) {
|
const mjtNum* pnt, const mjtNum* vec, int vertid[1]) {
|
||||||
// compute bounding box
|
// compute bounding box
|
||||||
mjtNum box[3][2] = {{0, 0}, {0, 0}, {0, 0}};
|
mjtNum box[3][2] = {{0, 0}, {0, 0}, {0, 0}};
|
||||||
for (int i=0; i<nvert; i++) {
|
for (int i=0; i < nvert; i++) {
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
// update minimum along side j
|
// update minimum along side j
|
||||||
if (box[j][0]>vert[3*i+j] || i==0) {
|
if (box[j][0] > vert[3*i+j] || i == 0) {
|
||||||
box[j][0] = vert[3*i+j];
|
box[j][0] = vert[3*i+j];
|
||||||
}
|
}
|
||||||
|
|
||||||
// update maximum along side j
|
// update maximum along side j
|
||||||
if (box[j][1]<vert[3*i+j] || i==0) {
|
if (box[j][1] < vert[3*i+j] || i == 0) {
|
||||||
box[j][1] = vert[3*i+j];
|
box[j][1] = vert[3*i+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -788,21 +788,21 @@ mjtNum mju_raySkin(int nface, int nvert, const int* face, const float* vert,
|
|||||||
|
|
||||||
// construct box geom
|
// construct box geom
|
||||||
mjtNum pos[3], size[3], mat[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
mjtNum pos[3], size[3], mat[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
pos[j] = 0.5*(box[j][0]+box[j][1]);
|
pos[j] = 0.5*(box[j][0]+box[j][1]);
|
||||||
size[j] = 0.5*(box[j][1]-box[j][0]);
|
size[j] = 0.5*(box[j][1]-box[j][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply bounding-box filter
|
// apply bounding-box filter
|
||||||
if (ray_box(pos, mat, size, pnt, vec, NULL)<0) {
|
if (ray_box(pos, mat, size, pnt, vec, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct basis vectors of normal plane
|
// construct basis vectors of normal plane
|
||||||
mjtNum b0[3] = {1, 1, 1}, b1[3];
|
mjtNum b0[3] = {1, 1, 1}, b1[3];
|
||||||
if (mju_abs(vec[0])>=mju_abs(vec[1]) && mju_abs(vec[0])>=mju_abs(vec[2])) {
|
if (mju_abs(vec[0]) >= mju_abs(vec[1]) && mju_abs(vec[0]) >= mju_abs(vec[2])) {
|
||||||
b0[0] = 0;
|
b0[0] = 0;
|
||||||
} else if (mju_abs(vec[1])>=mju_abs(vec[2])) {
|
} else if (mju_abs(vec[1]) >= mju_abs(vec[2])) {
|
||||||
b0[1] = 0;
|
b0[1] = 0;
|
||||||
} else {
|
} else {
|
||||||
b0[2] = 0;
|
b0[2] = 0;
|
||||||
@@ -816,7 +816,7 @@ mjtNum mju_raySkin(int nface, int nvert, const int* face, const float* vert,
|
|||||||
mjtNum x = -1, sol;
|
mjtNum x = -1, sol;
|
||||||
|
|
||||||
// process all faces
|
// process all faces
|
||||||
for (int i=0; i<nface; i++) {
|
for (int i=0; i < nface; i++) {
|
||||||
// get float vertices
|
// get float vertices
|
||||||
const float* vf[3];
|
const float* vf[3];
|
||||||
vf[0] = vert + 3*(face[3*i]);
|
vf[0] = vert + 3*(face[3*i]);
|
||||||
@@ -825,8 +825,8 @@ mjtNum mju_raySkin(int nface, int nvert, const int* face, const float* vert,
|
|||||||
|
|
||||||
// convert to mjtNum
|
// convert to mjtNum
|
||||||
mjtNum v[3][3];
|
mjtNum v[3][3];
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
for (int k=0; k<3; k++) {
|
for (int k=0; k < 3; k++) {
|
||||||
v[j][k] = (mjtNum)vf[j][k];
|
v[j][k] = (mjtNum)vf[j][k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -835,7 +835,7 @@ mjtNum mju_raySkin(int nface, int nvert, const int* face, const float* vert,
|
|||||||
sol = ray_triangle(v, pnt, vec, b0, b1);
|
sol = ray_triangle(v, pnt, vec, b0, b1);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
if (sol>=0 && (x<0 || sol<x)) {
|
if (sol >= 0 && (x < 0 || sol < x)) {
|
||||||
x = sol;
|
x = sol;
|
||||||
|
|
||||||
// construct intersection point
|
// construct intersection point
|
||||||
@@ -845,9 +845,9 @@ mjtNum mju_raySkin(int nface, int nvert, const int* face, const float* vert,
|
|||||||
// find nearest vertex
|
// find nearest vertex
|
||||||
mjtNum dist = mju_dist3(intersect, v[0]);
|
mjtNum dist = mju_dist3(intersect, v[0]);
|
||||||
*vertid = face[3*i];
|
*vertid = face[3*i];
|
||||||
for (int j=1; j<3; j++) {
|
for (int j=1; j < 3; j++) {
|
||||||
mjtNum newdist = mju_dist3(intersect, v[j]);
|
mjtNum newdist = mju_dist3(intersect, v[j]);
|
||||||
if (newdist<dist) {
|
if (newdist < dist) {
|
||||||
dist = newdist;
|
dist = newdist;
|
||||||
*vertid = face[3*i+j];
|
*vertid = face[3*i+j];
|
||||||
}
|
}
|
||||||
@@ -871,7 +871,7 @@ static int point_in_box(const mjtNum aabb[6], const mjtNum xpos[3],
|
|||||||
mju_subFrom3(point, aabb);
|
mju_subFrom3(point, aabb);
|
||||||
|
|
||||||
// check intersections
|
// check intersections
|
||||||
for (int j=0; j<3; j++) { // directions
|
for (int j=0; j < 3; j++) { // directions
|
||||||
if (mju_abs(point[j]) > aabb[3+j]) {
|
if (mju_abs(point[j]) > aabb[3+j]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -893,7 +893,7 @@ mjtNum mj_ray(const mjModel* m, const mjData* d, const mjtNum* pnt, const mjtNum
|
|||||||
mjtNum dist, newdist;
|
mjtNum dist, newdist;
|
||||||
|
|
||||||
// check vector length
|
// check vector length
|
||||||
if (mju_norm3(vec)<mjMINVAL) {
|
if (mju_norm3(vec) < mjMINVAL) {
|
||||||
mju_error("mj_ray: vector length is too small");
|
mju_error("mj_ray: vector length is too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,12 +902,12 @@ mjtNum mj_ray(const mjModel* m, const mjData* d, const mjtNum* pnt, const mjtNum
|
|||||||
*geomid = -1;
|
*geomid = -1;
|
||||||
|
|
||||||
// loop over geoms not eliminated by mask and bodyexclude
|
// loop over geoms not eliminated by mask and bodyexclude
|
||||||
for (int i=0; i<m->ngeom; i++) {
|
for (int i=0; i < m->ngeom; i++) {
|
||||||
if (!ray_eliminate(m, d, i, geomgroup, flg_static, bodyexclude)) {
|
if (!ray_eliminate(m, d, i, geomgroup, flg_static, bodyexclude)) {
|
||||||
// handle mesh and hfield separately
|
// handle mesh and hfield separately
|
||||||
if (m->geom_type[i]==mjGEOM_MESH) {
|
if (m->geom_type[i] == mjGEOM_MESH) {
|
||||||
newdist = mj_rayMesh(m, d, i, pnt, vec);
|
newdist = mj_rayMesh(m, d, i, pnt, vec);
|
||||||
} else if (m->geom_type[i]==mjGEOM_HFIELD) {
|
} else if (m->geom_type[i] == mjGEOM_HFIELD) {
|
||||||
newdist = mj_rayHfield(m, d, i, pnt, vec);
|
newdist = mj_rayHfield(m, d, i, pnt, vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -918,7 +918,7 @@ mjtNum mj_ray(const mjModel* m, const mjData* d, const mjtNum* pnt, const mjtNum
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update if closer intersection found
|
// update if closer intersection found
|
||||||
if (newdist>=0 && (newdist<dist || dist<0)) {
|
if (newdist >= 0 && (newdist < dist || dist < 0)) {
|
||||||
dist = newdist;
|
dist = newdist;
|
||||||
*geomid = i;
|
*geomid = i;
|
||||||
}
|
}
|
||||||
@@ -938,17 +938,17 @@ void mju_multiRayPrepare(const mjModel* m, const mjData* d, const mjtNum pnt[3],
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute eliminate flag for all geoms
|
// compute eliminate flag for all geoms
|
||||||
for (int geomid=0; geomid<m->ngeom; geomid++)
|
for (int geomid=0; geomid < m->ngeom; geomid++)
|
||||||
geom_eliminate[geomid] = ray_eliminate(m, d, geomid, geomgroup, flg_static, bodyexclude);
|
geom_eliminate[geomid] = ray_eliminate(m, d, geomid, geomgroup, flg_static, bodyexclude);
|
||||||
|
|
||||||
for (int b=0; b<m->nbody; b++) {
|
for (int b=0; b < m->nbody; b++) {
|
||||||
// skip precomputation if no bounding volume is available
|
// skip precomputation if no bounding volume is available
|
||||||
if (m->body_bvhadr[b] == -1) {
|
if (m->body_bvhadr[b] == -1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop over child geoms, compute bounding angles
|
// loop over child geoms, compute bounding angles
|
||||||
for (int i=0; i<m->body_geomnum[b]; i++) {
|
for (int i=0; i < m->body_geomnum[b]; i++) {
|
||||||
int g = i + m->body_geomadr[b];
|
int g = i + m->body_geomadr[b];
|
||||||
mjtNum AABB[4] = {mjMAXVAL, mjMAXVAL, -mjMAXVAL, -mjMAXVAL};
|
mjtNum AABB[4] = {mjMAXVAL, mjMAXVAL, -mjMAXVAL, -mjMAXVAL};
|
||||||
mjtNum* aabb = m->geom_aabb + 6*g;
|
mjtNum* aabb = m->geom_aabb + 6*g;
|
||||||
@@ -961,7 +961,7 @@ void mju_multiRayPrepare(const mjModel* m, const mjData* d, const mjtNum pnt[3],
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add to geom_eliminate if distance of bounding sphere is above cutoff
|
// add to geom_eliminate if distance of bounding sphere is above cutoff
|
||||||
if (mju_dist3(d->geom_xpos+3*g, pnt)>cutoff+m->geom_rbound[g]) {
|
if (mju_dist3(d->geom_xpos+3*g, pnt) > cutoff+m->geom_rbound[g]) {
|
||||||
geom_eliminate[g] = 1;
|
geom_eliminate[g] = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -975,7 +975,7 @@ void mju_multiRayPrepare(const mjModel* m, const mjData* d, const mjtNum pnt[3],
|
|||||||
}
|
}
|
||||||
|
|
||||||
// loop over box vertices, compute spherical aperture
|
// loop over box vertices, compute spherical aperture
|
||||||
for (int v=0; v<8; v++) {
|
for (int v=0; v < 8; v++) {
|
||||||
mjtNum vert[3], box[3];
|
mjtNum vert[3], box[3];
|
||||||
vert[0] = (v&1 ? aabb[0]+aabb[3] : aabb[0]-aabb[3]);
|
vert[0] = (v&1 ? aabb[0]+aabb[3] : aabb[0]-aabb[3]);
|
||||||
vert[1] = (v&2 ? aabb[1]+aabb[4] : aabb[1]-aabb[4]);
|
vert[1] = (v&2 ? aabb[1]+aabb[4] : aabb[1]-aabb[4]);
|
||||||
@@ -1020,7 +1020,7 @@ static mjtNum mju_singleRay(const mjModel* m, mjData* d, const mjtNum pnt[3], co
|
|||||||
mjtNum dist, newdist;
|
mjtNum dist, newdist;
|
||||||
|
|
||||||
// check vector length
|
// check vector length
|
||||||
if (mju_norm3(vec)<mjMINVAL) {
|
if (mju_norm3(vec) < mjMINVAL) {
|
||||||
mju_error("mj_ray: vector length is too small");
|
mju_error("mj_ray: vector length is too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1033,7 +1033,7 @@ static mjtNum mju_singleRay(const mjModel* m, mjData* d, const mjtNum pnt[3], co
|
|||||||
mjtNum elevation = latitude(vec);
|
mjtNum elevation = latitude(vec);
|
||||||
|
|
||||||
// loop over bodies not eliminated by bodyexclude
|
// loop over bodies not eliminated by bodyexclude
|
||||||
for (int b=0; b<m->nbody; b++) {
|
for (int b=0; b < m->nbody; b++) {
|
||||||
// exclude body using bounding sphere test
|
// exclude body using bounding sphere test
|
||||||
if (m->body_bvhadr[b] != -1) {
|
if (m->body_bvhadr[b] != -1) {
|
||||||
mjtNum* pos = m->bvh_aabb + 6*m->body_bvhadr[b];
|
mjtNum* pos = m->bvh_aabb + 6*m->body_bvhadr[b];
|
||||||
@@ -1041,13 +1041,13 @@ static mjtNum mju_singleRay(const mjModel* m, mjData* d, const mjtNum pnt[3], co
|
|||||||
mjtNum* size = pos + 3;
|
mjtNum* size = pos + 3;
|
||||||
mjtNum ssz = size[0]*size[0] + size[1]*size[1] + size[2]*size[2];
|
mjtNum ssz = size[0]*size[0] + size[1]*size[1] + size[2]*size[2];
|
||||||
mju_add3(center, pos, d->xipos+3*b);
|
mju_add3(center, pos, d->xipos+3*b);
|
||||||
if (ray_sphere(center, NULL, ssz, pnt, vec)<0) {
|
if (ray_sphere(center, NULL, ssz, pnt, vec) < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop over geoms if bounding sphere test fails
|
// loop over geoms if bounding sphere test fails
|
||||||
for (int g=0; g<m->body_geomnum[b]; g++) {
|
for (int g=0; g < m->body_geomnum[b]; g++) {
|
||||||
int i = m->body_geomadr[b] + g;
|
int i = m->body_geomadr[b] + g;
|
||||||
if (ray_eliminate[i]) {
|
if (ray_eliminate[i]) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1055,16 +1055,16 @@ static mjtNum mju_singleRay(const mjModel* m, mjData* d, const mjtNum pnt[3], co
|
|||||||
|
|
||||||
// exclude geom using bounding angles
|
// exclude geom using bounding angles
|
||||||
if (m->body_bvhadr[b] != -1) {
|
if (m->body_bvhadr[b] != -1) {
|
||||||
if (azimuth<(geom_ba+4*i)[0] || elevation<(geom_ba+4*i)[1] ||
|
if (azimuth < (geom_ba+4*i)[0] || elevation < (geom_ba+4*i)[1] ||
|
||||||
azimuth>(geom_ba+4*i)[2] || elevation>(geom_ba+4*i)[3]) {
|
azimuth > (geom_ba+4*i)[2] || elevation > (geom_ba+4*i)[3]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle mesh and hfield separately
|
// handle mesh and hfield separately
|
||||||
if (m->geom_type[i]==mjGEOM_MESH) {
|
if (m->geom_type[i] == mjGEOM_MESH) {
|
||||||
newdist = mj_rayMesh(m, d, i, pnt, vec);
|
newdist = mj_rayMesh(m, d, i, pnt, vec);
|
||||||
} else if (m->geom_type[i]==mjGEOM_HFIELD) {
|
} else if (m->geom_type[i] == mjGEOM_HFIELD) {
|
||||||
newdist = mj_rayHfield(m, d, i, pnt, vec);
|
newdist = mj_rayHfield(m, d, i, pnt, vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1075,7 +1075,7 @@ static mjtNum mju_singleRay(const mjModel* m, mjData* d, const mjtNum pnt[3], co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update if closer intersection found
|
// update if closer intersection found
|
||||||
if (newdist>=0 && (newdist<dist || dist<0)) {
|
if (newdist >= 0 && (newdist < dist || dist < 0)) {
|
||||||
dist = newdist;
|
dist = newdist;
|
||||||
*geomid = i;
|
*geomid = i;
|
||||||
}
|
}
|
||||||
@@ -1101,7 +1101,7 @@ void mj_multiRay(const mjModel* m, mjData* d, const mjtNum pnt[3], const mjtNum*
|
|||||||
cutoff, geom_ba, geom_eliminate);
|
cutoff, geom_ba, geom_eliminate);
|
||||||
|
|
||||||
// loop over rays
|
// loop over rays
|
||||||
for (int i=0; i<nray; i++) {
|
for (int i=0; i < nray; i++) {
|
||||||
dist[i] = mju_singleRay(m, d, pnt, vec+3*i, geom_eliminate, geom_ba, geomid+i);
|
dist[i] = mju_singleRay(m, d, pnt, vec+3*i, geom_eliminate, geom_ba, geomid+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+74
-74
@@ -41,24 +41,24 @@ static void add_noise(const mjModel* m, mjData* d, mjtStage stage) {
|
|||||||
mjtNum rnd[4], noise, quat[4], res[4];
|
mjtNum rnd[4], noise, quat[4], res[4];
|
||||||
|
|
||||||
// process sensors matching stage and having positive noise
|
// process sensors matching stage and having positive noise
|
||||||
for (int i=0; i<m->nsensor; i++) {
|
for (int i=0; i < m->nsensor; i++) {
|
||||||
if (m->sensor_needstage[i]==stage && m->sensor_noise[i]>0) {
|
if (m->sensor_needstage[i] == stage && m->sensor_noise[i] > 0) {
|
||||||
// get sensor info
|
// get sensor info
|
||||||
adr = m->sensor_adr[i];
|
adr = m->sensor_adr[i];
|
||||||
dim = m->sensor_dim[i];
|
dim = m->sensor_dim[i];
|
||||||
noise = m->sensor_noise[i];
|
noise = m->sensor_noise[i];
|
||||||
|
|
||||||
// real or positive: add noise directly, with clamp for positive
|
// real or positive: add noise directly, with clamp for positive
|
||||||
if (m->sensor_datatype[i]==mjDATATYPE_REAL ||
|
if (m->sensor_datatype[i] == mjDATATYPE_REAL ||
|
||||||
m->sensor_datatype[i]==mjDATATYPE_POSITIVE) {
|
m->sensor_datatype[i] == mjDATATYPE_POSITIVE) {
|
||||||
for (int j=0; j<dim; j++) {
|
for (int j=0; j < dim; j++) {
|
||||||
// get random numbers; use only the first one
|
// get random numbers; use only the first one
|
||||||
rnd[0] = mju_standardNormal(rnd+1);
|
rnd[0] = mju_standardNormal(rnd+1);
|
||||||
|
|
||||||
// positive
|
// positive
|
||||||
if (m->sensor_datatype[i]==mjDATATYPE_POSITIVE) {
|
if (m->sensor_datatype[i] == mjDATATYPE_POSITIVE) {
|
||||||
// add noise only if positive, keep it positive
|
// add noise only if positive, keep it positive
|
||||||
if (d->sensordata[adr+j]>0) {
|
if (d->sensordata[adr+j] > 0) {
|
||||||
d->sensordata[adr+j] = mjMAX(0, d->sensordata[adr+j]+rnd[0]*noise);
|
d->sensordata[adr+j] = mjMAX(0, d->sensordata[adr+j]+rnd[0]*noise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,14 +82,14 @@ static void add_noise(const mjModel* m, mjData* d, mjtStage stage) {
|
|||||||
mju_axisAngle2Quat(quat, rnd+1, rnd[0]);
|
mju_axisAngle2Quat(quat, rnd+1, rnd[0]);
|
||||||
|
|
||||||
// axis
|
// axis
|
||||||
if (m->sensor_datatype[i]==mjDATATYPE_AXIS) {
|
if (m->sensor_datatype[i] == mjDATATYPE_AXIS) {
|
||||||
// apply quaternion rotation to axis, assign
|
// apply quaternion rotation to axis, assign
|
||||||
mju_rotVecQuat(res, d->sensordata+adr, quat);
|
mju_rotVecQuat(res, d->sensordata+adr, quat);
|
||||||
mju_copy3(d->sensordata+adr, res);
|
mju_copy3(d->sensordata+adr, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// quaternion
|
// quaternion
|
||||||
else if (m->sensor_datatype[i]==mjDATATYPE_QUATERNION) {
|
else if (m->sensor_datatype[i] == mjDATATYPE_QUATERNION) {
|
||||||
// apply quaternion rotation to quaternion, assign
|
// apply quaternion rotation to quaternion, assign
|
||||||
mju_mulQuat(d->sensordata+adr, d->sensordata+adr, quat);
|
mju_mulQuat(d->sensordata+adr, d->sensordata+adr, quat);
|
||||||
}
|
}
|
||||||
@@ -108,22 +108,22 @@ static void add_noise(const mjModel* m, mjData* d, mjtStage stage) {
|
|||||||
// apply cutoff after each stage
|
// apply cutoff after each stage
|
||||||
static void apply_cutoff(const mjModel* m, mjData* d, mjtStage stage) {
|
static void apply_cutoff(const mjModel* m, mjData* d, mjtStage stage) {
|
||||||
// process sensors matching stage and having positive cutoff
|
// process sensors matching stage and having positive cutoff
|
||||||
for (int i=0; i<m->nsensor; i++) {
|
for (int i=0; i < m->nsensor; i++) {
|
||||||
if (m->sensor_needstage[i]==stage && m->sensor_cutoff[i]>0) {
|
if (m->sensor_needstage[i] == stage && m->sensor_cutoff[i] > 0) {
|
||||||
// get sensor info
|
// get sensor info
|
||||||
int adr = m->sensor_adr[i];
|
int adr = m->sensor_adr[i];
|
||||||
int dim = m->sensor_dim[i];
|
int dim = m->sensor_dim[i];
|
||||||
mjtNum cutoff = m->sensor_cutoff[i];
|
mjtNum cutoff = m->sensor_cutoff[i];
|
||||||
|
|
||||||
// process all dimensions
|
// process all dimensions
|
||||||
for (int j=0; j<dim; j++) {
|
for (int j=0; j < dim; j++) {
|
||||||
// real: apply on both sides
|
// real: apply on both sides
|
||||||
if (m->sensor_datatype[i]==mjDATATYPE_REAL) {
|
if (m->sensor_datatype[i] == mjDATATYPE_REAL) {
|
||||||
d->sensordata[adr+j] = mju_clip(d->sensordata[adr+j], -cutoff, cutoff);
|
d->sensordata[adr+j] = mju_clip(d->sensordata[adr+j], -cutoff, cutoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
// positive: apply on positive side only
|
// positive: apply on positive side only
|
||||||
else if (m->sensor_datatype[i]==mjDATATYPE_POSITIVE) {
|
else if (m->sensor_datatype[i] == mjDATATYPE_POSITIVE) {
|
||||||
d->sensordata[adr+j] = mju_min(cutoff, d->sensordata[adr+j]);
|
d->sensordata[adr+j] = mju_min(cutoff, d->sensordata[adr+j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,13 +201,13 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// process sensors matching stage
|
// process sensors matching stage
|
||||||
for (int i=0; i<m->nsensor; i++) {
|
for (int i=0; i < m->nsensor; i++) {
|
||||||
// skip sensor plugins -- these are handled after builtin sensor types
|
// skip sensor plugins -- these are handled after builtin sensor types
|
||||||
if (m->sensor_type[i] == mjSENS_PLUGIN) {
|
if (m->sensor_type[i] == mjSENS_PLUGIN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->sensor_needstage[i]==mjSTAGE_POS) {
|
if (m->sensor_needstage[i] == mjSTAGE_POS) {
|
||||||
// get sensor info
|
// get sensor info
|
||||||
objtype = m->sensor_objtype[i];
|
objtype = m->sensor_objtype[i];
|
||||||
objid = m->sensor_objid[i];
|
objid = m->sensor_objid[i];
|
||||||
@@ -247,8 +247,8 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
case mjSENS_JOINTLIMITPOS: // jointlimitpos
|
case mjSENS_JOINTLIMITPOS: // jointlimitpos
|
||||||
d->sensordata[adr] = 0;
|
d->sensordata[adr] = 0;
|
||||||
for (int j=ne+nf; j<nefc; j++) {
|
for (int j=ne+nf; j < nefc; j++) {
|
||||||
if (d->efc_type[j]==mjCNSTR_LIMIT_JOINT && d->efc_id[j]==objid) {
|
if (d->efc_type[j] == mjCNSTR_LIMIT_JOINT && d->efc_id[j] == objid) {
|
||||||
d->sensordata[adr] = d->efc_pos[j] - d->efc_margin[j];
|
d->sensordata[adr] = d->efc_pos[j] - d->efc_margin[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -257,8 +257,8 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
case mjSENS_TENDONLIMITPOS: // tendonlimitpos
|
case mjSENS_TENDONLIMITPOS: // tendonlimitpos
|
||||||
d->sensordata[adr] = 0;
|
d->sensordata[adr] = 0;
|
||||||
for (int j=ne+nf; j<nefc; j++) {
|
for (int j=ne+nf; j < nefc; j++) {
|
||||||
if (d->efc_type[j]==mjCNSTR_LIMIT_TENDON && d->efc_id[j]==objid) {
|
if (d->efc_type[j] == mjCNSTR_LIMIT_TENDON && d->efc_id[j] == objid) {
|
||||||
d->sensordata[adr] = d->efc_pos[j] - d->efc_margin[j];
|
d->sensordata[adr] = d->efc_pos[j] - d->efc_margin[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// reference frame unspecified: global frame
|
// reference frame unspecified: global frame
|
||||||
if (refid == -1) {
|
if (refid == -1) {
|
||||||
if (m->sensor_type[i]==mjSENS_FRAMEPOS) {
|
if (m->sensor_type[i] == mjSENS_FRAMEPOS) {
|
||||||
mju_copy3(d->sensordata+adr, xpos);
|
mju_copy3(d->sensordata+adr, xpos);
|
||||||
} else {
|
} else {
|
||||||
// offset = (0 or 1 or 2) for (x or y or z)-axis sensors, respectively
|
// offset = (0 or 1 or 2) for (x or y or z)-axis sensors, respectively
|
||||||
@@ -288,7 +288,7 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
|
|||||||
// reference frame specified
|
// reference frame specified
|
||||||
else {
|
else {
|
||||||
get_xpos_xmat(d, reftype, refid, i, &xpos_ref, &xmat_ref);
|
get_xpos_xmat(d, reftype, refid, i, &xpos_ref, &xmat_ref);
|
||||||
if (m->sensor_type[i]==mjSENS_FRAMEPOS) {
|
if (m->sensor_type[i] == mjSENS_FRAMEPOS) {
|
||||||
mju_sub3(rvec, xpos, xpos_ref);
|
mju_sub3(rvec, xpos, xpos_ref);
|
||||||
mju_rotVecMatT(d->sensordata+adr, rvec, xmat_ref);
|
mju_rotVecMatT(d->sensordata+adr, rvec, xmat_ref);
|
||||||
} else {
|
} else {
|
||||||
@@ -301,25 +301,25 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case mjSENS_FRAMEQUAT: // framequat
|
case mjSENS_FRAMEQUAT: // framequat
|
||||||
{
|
{
|
||||||
// get global object quaternion
|
// get global object quaternion
|
||||||
mjtNum objquat[4];
|
mjtNum objquat[4];
|
||||||
get_xquat(m, d, objtype, objid, i, objquat);
|
get_xquat(m, d, objtype, objid, i, objquat);
|
||||||
|
|
||||||
// reference frame unspecified: copy object quaternion
|
// reference frame unspecified: copy object quaternion
|
||||||
if (refid == -1) {
|
if (refid == -1) {
|
||||||
mju_copy4(d->sensordata+adr, objquat);
|
mju_copy4(d->sensordata+adr, objquat);
|
||||||
} else {
|
} else {
|
||||||
// reference frame specified, get global reference quaternion
|
// reference frame specified, get global reference quaternion
|
||||||
mjtNum refquat[4];
|
mjtNum refquat[4];
|
||||||
get_xquat(m, d, reftype, refid, i, refquat);
|
get_xquat(m, d, reftype, refid, i, refquat);
|
||||||
|
|
||||||
// relative quaternion
|
// relative quaternion
|
||||||
mju_negQuat(refquat, refquat);
|
mju_negQuat(refquat, refquat);
|
||||||
mju_mulQuat(d->sensordata+adr, refquat, objquat);
|
mju_mulQuat(d->sensordata+adr, refquat, objquat);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case mjSENS_SUBTREECOM: // subtreecom
|
case mjSENS_SUBTREECOM: // subtreecom
|
||||||
mju_copy3(d->sensordata+adr, d->subtree_com+3*objid);
|
mju_copy3(d->sensordata+adr, d->subtree_com+3*objid);
|
||||||
@@ -352,14 +352,14 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
|
|||||||
// compute plugin sensor values
|
// compute plugin sensor values
|
||||||
if (m->nplugin) {
|
if (m->nplugin) {
|
||||||
const int nslot = mjp_pluginCount();
|
const int nslot = mjp_pluginCount();
|
||||||
for (int i=0; i<m->nplugin; i++) {
|
for (int i=0; i < m->nplugin; i++) {
|
||||||
const int slot = m->plugin[i];
|
const int slot = m->plugin[i];
|
||||||
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
mju_error("invalid plugin slot: %d", slot);
|
mju_error("invalid plugin slot: %d", slot);
|
||||||
}
|
}
|
||||||
if ((plugin->capabilityflags & mjPLUGIN_SENSOR) &&
|
if ((plugin->capabilityflags & mjPLUGIN_SENSOR) &&
|
||||||
(plugin->needstage==mjSTAGE_POS || plugin->needstage==mjSTAGE_NONE)) {
|
(plugin->needstage == mjSTAGE_POS || plugin->needstage == mjSTAGE_NONE)) {
|
||||||
if (!plugin->compute) {
|
if (!plugin->compute) {
|
||||||
mju_error("`compute` is a null function pointer for plugin at slot %d", slot);
|
mju_error("`compute` is a null function pointer for plugin at slot %d", slot);
|
||||||
}
|
}
|
||||||
@@ -387,13 +387,13 @@ void mj_sensorVel(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// process sensors matching stage
|
// process sensors matching stage
|
||||||
int subtreeVel = 0;
|
int subtreeVel = 0;
|
||||||
for (int i=0; i<m->nsensor; i++) {
|
for (int i=0; i < m->nsensor; i++) {
|
||||||
// skip sensor plugins -- these are handled after builtin sensor types
|
// skip sensor plugins -- these are handled after builtin sensor types
|
||||||
if (m->sensor_type[i] == mjSENS_PLUGIN) {
|
if (m->sensor_type[i] == mjSENS_PLUGIN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->sensor_needstage[i]==mjSTAGE_VEL) {
|
if (m->sensor_needstage[i] == mjSTAGE_VEL) {
|
||||||
// get sensor info
|
// get sensor info
|
||||||
type = m->sensor_type[i];
|
type = m->sensor_type[i];
|
||||||
objtype = m->sensor_objtype[i];
|
objtype = m->sensor_objtype[i];
|
||||||
@@ -403,10 +403,10 @@ void mj_sensorVel(const mjModel* m, mjData* d) {
|
|||||||
adr = m->sensor_adr[i];
|
adr = m->sensor_adr[i];
|
||||||
|
|
||||||
// call mj_subtreeVel when first relevant sensor is encountered
|
// call mj_subtreeVel when first relevant sensor is encountered
|
||||||
if (subtreeVel==0 &&
|
if (subtreeVel == 0 &&
|
||||||
(type==mjSENS_SUBTREELINVEL ||
|
(type == mjSENS_SUBTREELINVEL ||
|
||||||
type==mjSENS_SUBTREEANGMOM ||
|
type == mjSENS_SUBTREEANGMOM ||
|
||||||
type==mjSENS_USER)) {
|
type == mjSENS_USER)) {
|
||||||
// compute subtree_linvel, subtree_angmom
|
// compute subtree_linvel, subtree_angmom
|
||||||
mj_subtreeVel(m, d);
|
mj_subtreeVel(m, d);
|
||||||
|
|
||||||
@@ -450,8 +450,8 @@ void mj_sensorVel(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
case mjSENS_JOINTLIMITVEL: // jointlimitvel
|
case mjSENS_JOINTLIMITVEL: // jointlimitvel
|
||||||
d->sensordata[adr] = 0;
|
d->sensordata[adr] = 0;
|
||||||
for (int j=ne+nf; j<nefc; j++) {
|
for (int j=ne+nf; j < nefc; j++) {
|
||||||
if (d->efc_type[j]==mjCNSTR_LIMIT_JOINT && d->efc_id[j]==objid) {
|
if (d->efc_type[j] == mjCNSTR_LIMIT_JOINT && d->efc_id[j] == objid) {
|
||||||
d->sensordata[adr] = d->efc_vel[j];
|
d->sensordata[adr] = d->efc_vel[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -460,8 +460,8 @@ void mj_sensorVel(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
case mjSENS_TENDONLIMITVEL: // tendonlimitvel
|
case mjSENS_TENDONLIMITVEL: // tendonlimitvel
|
||||||
d->sensordata[adr] = 0;
|
d->sensordata[adr] = 0;
|
||||||
for (int j=ne+nf; j<nefc; j++) {
|
for (int j=ne+nf; j < nefc; j++) {
|
||||||
if (d->efc_type[j]==mjCNSTR_LIMIT_TENDON && d->efc_id[j]==objid) {
|
if (d->efc_type[j] == mjCNSTR_LIMIT_TENDON && d->efc_id[j] == objid) {
|
||||||
d->sensordata[adr] = d->efc_vel[j];
|
d->sensordata[adr] = d->efc_vel[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -495,7 +495,7 @@ void mj_sensorVel(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copy linear or angular component
|
// copy linear or angular component
|
||||||
if (m->sensor_type[i]==mjSENS_FRAMELINVEL) {
|
if (m->sensor_type[i] == mjSENS_FRAMELINVEL) {
|
||||||
mju_copy3(d->sensordata+adr, xvel+3);
|
mju_copy3(d->sensordata+adr, xvel+3);
|
||||||
} else {
|
} else {
|
||||||
mju_copy3(d->sensordata+adr, xvel);
|
mju_copy3(d->sensordata+adr, xvel);
|
||||||
@@ -533,13 +533,13 @@ void mj_sensorVel(const mjModel* m, mjData* d) {
|
|||||||
// trigger computation of plugins
|
// trigger computation of plugins
|
||||||
if (m->nplugin) {
|
if (m->nplugin) {
|
||||||
const int nslot = mjp_pluginCount();
|
const int nslot = mjp_pluginCount();
|
||||||
for (int i=0; i<m->nplugin; i++) {
|
for (int i=0; i < m->nplugin; i++) {
|
||||||
const int slot = m->plugin[i];
|
const int slot = m->plugin[i];
|
||||||
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
mju_error("invalid plugin slot: %d", slot);
|
mju_error("invalid plugin slot: %d", slot);
|
||||||
}
|
}
|
||||||
if ((plugin->capabilityflags & mjPLUGIN_SENSOR) && plugin->needstage==mjSTAGE_VEL) {
|
if ((plugin->capabilityflags & mjPLUGIN_SENSOR) && plugin->needstage == mjSTAGE_VEL) {
|
||||||
if (!plugin->compute) {
|
if (!plugin->compute) {
|
||||||
mju_error("`compute` is null for plugin at slot %d", slot);
|
mju_error("`compute` is null for plugin at slot %d", slot);
|
||||||
}
|
}
|
||||||
@@ -576,13 +576,13 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// process sensors matching stage
|
// process sensors matching stage
|
||||||
int rnePost = 0;
|
int rnePost = 0;
|
||||||
for (int i=0; i<m->nsensor; i++) {
|
for (int i=0; i < m->nsensor; i++) {
|
||||||
// skip sensor plugins -- these are handled after builtin sensor types
|
// skip sensor plugins -- these are handled after builtin sensor types
|
||||||
if (m->sensor_type[i] == mjSENS_PLUGIN) {
|
if (m->sensor_type[i] == mjSENS_PLUGIN) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->sensor_needstage[i]==mjSTAGE_ACC) {
|
if (m->sensor_needstage[i] == mjSTAGE_ACC) {
|
||||||
// get sensor info
|
// get sensor info
|
||||||
type = m->sensor_type[i];
|
type = m->sensor_type[i];
|
||||||
objtype = m->sensor_objtype[i];
|
objtype = m->sensor_objtype[i];
|
||||||
@@ -590,11 +590,11 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
adr = m->sensor_adr[i];
|
adr = m->sensor_adr[i];
|
||||||
|
|
||||||
// call mj_rnePostConstraint when first relevant sensor is encountered
|
// call mj_rnePostConstraint when first relevant sensor is encountered
|
||||||
if (rnePost==0 &&
|
if (rnePost == 0 &&
|
||||||
type!=mjSENS_TOUCH &&
|
type != mjSENS_TOUCH &&
|
||||||
type!=mjSENS_ACTUATORFRC &&
|
type != mjSENS_ACTUATORFRC &&
|
||||||
type!=mjSENS_JOINTLIMITFRC &&
|
type != mjSENS_JOINTLIMITFRC &&
|
||||||
type!=mjSENS_TENDONLIMITFRC) {
|
type != mjSENS_TENDONLIMITFRC) {
|
||||||
// compute cacc, cfrc_int, cfrc_ext
|
// compute cacc, cfrc_int, cfrc_ext
|
||||||
mj_rnePostConstraint(m, d);
|
mj_rnePostConstraint(m, d);
|
||||||
|
|
||||||
@@ -613,19 +613,19 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
d->sensordata[adr] = 0;
|
d->sensordata[adr] = 0;
|
||||||
|
|
||||||
// find contacts in sensor zone, add normal forces
|
// find contacts in sensor zone, add normal forces
|
||||||
for (int j=0; j<d->ncon; j++) {
|
for (int j=0; j < d->ncon; j++) {
|
||||||
// contact pointer, contacting bodies
|
// contact pointer, contacting bodies
|
||||||
con = d->contact + j;
|
con = d->contact + j;
|
||||||
body1 = m->geom_bodyid[con->geom1];
|
body1 = m->geom_bodyid[con->geom1];
|
||||||
body2 = m->geom_bodyid[con->geom2];
|
body2 = m->geom_bodyid[con->geom2];
|
||||||
|
|
||||||
// select contacts involving sensorized body
|
// select contacts involving sensorized body
|
||||||
if (con->efc_address>=0 && (bodyid==body1 || bodyid==body2)) {
|
if (con->efc_address >= 0 && (bodyid == body1 || bodyid == body2)) {
|
||||||
// get contact force:torque in contact frame
|
// get contact force:torque in contact frame
|
||||||
mj_contactForce(m, d, j, conforce);
|
mj_contactForce(m, d, j, conforce);
|
||||||
|
|
||||||
// nothing to do if normal is zero
|
// nothing to do if normal is zero
|
||||||
if (conforce[0]<=0) {
|
if (conforce[0] <= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,7 +634,7 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
mju_normalize3(conray);
|
mju_normalize3(conray);
|
||||||
|
|
||||||
// flip ray direction if sensor is on body2
|
// flip ray direction if sensor is on body2
|
||||||
if (bodyid==body2) {
|
if (bodyid == body2) {
|
||||||
mju_scl3(conray, conray, -1);
|
mju_scl3(conray, conray, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,8 +688,8 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
case mjSENS_JOINTLIMITFRC: // jointlimitfrc
|
case mjSENS_JOINTLIMITFRC: // jointlimitfrc
|
||||||
d->sensordata[adr] = 0;
|
d->sensordata[adr] = 0;
|
||||||
for (int j=ne+nf; j<nefc; j++) {
|
for (int j=ne+nf; j < nefc; j++) {
|
||||||
if (d->efc_type[j]==mjCNSTR_LIMIT_JOINT && d->efc_id[j]==objid) {
|
if (d->efc_type[j] == mjCNSTR_LIMIT_JOINT && d->efc_id[j] == objid) {
|
||||||
d->sensordata[adr] = d->efc_force[j];
|
d->sensordata[adr] = d->efc_force[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -698,8 +698,8 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
case mjSENS_TENDONLIMITFRC: // tendonlimitfrc
|
case mjSENS_TENDONLIMITFRC: // tendonlimitfrc
|
||||||
d->sensordata[adr] = 0;
|
d->sensordata[adr] = 0;
|
||||||
for (int j=ne+nf; j<nefc; j++) {
|
for (int j=ne+nf; j < nefc; j++) {
|
||||||
if (d->efc_type[j]==mjCNSTR_LIMIT_TENDON && d->efc_id[j]==objid) {
|
if (d->efc_type[j] == mjCNSTR_LIMIT_TENDON && d->efc_id[j] == objid) {
|
||||||
d->sensordata[adr] = d->efc_force[j];
|
d->sensordata[adr] = d->efc_force[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -712,7 +712,7 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
mj_objectAcceleration(m, d, objtype, objid, tmp, 0);
|
mj_objectAcceleration(m, d, objtype, objid, tmp, 0);
|
||||||
|
|
||||||
// copy linear or angular component
|
// copy linear or angular component
|
||||||
if (m->sensor_type[i]==mjSENS_FRAMELINACC) {
|
if (m->sensor_type[i] == mjSENS_FRAMELINACC) {
|
||||||
mju_copy3(d->sensordata+adr, tmp+3);
|
mju_copy3(d->sensordata+adr, tmp+3);
|
||||||
} else {
|
} else {
|
||||||
mju_copy3(d->sensordata+adr, tmp);
|
mju_copy3(d->sensordata+adr, tmp);
|
||||||
@@ -742,13 +742,13 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
|
|||||||
// trigger computation of plugins
|
// trigger computation of plugins
|
||||||
if (m->nplugin) {
|
if (m->nplugin) {
|
||||||
const int nslot = mjp_pluginCount();
|
const int nslot = mjp_pluginCount();
|
||||||
for (int i=0; i<m->nplugin; i++) {
|
for (int i=0; i < m->nplugin; i++) {
|
||||||
const int slot = m->plugin[i];
|
const int slot = m->plugin[i];
|
||||||
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
mju_error("invalid plugin slot: %d", slot);
|
mju_error("invalid plugin slot: %d", slot);
|
||||||
}
|
}
|
||||||
if ((plugin->capabilityflags & mjPLUGIN_SENSOR) && plugin->needstage==mjSTAGE_ACC) {
|
if ((plugin->capabilityflags & mjPLUGIN_SENSOR) && plugin->needstage == mjSTAGE_ACC) {
|
||||||
if (!plugin->compute) {
|
if (!plugin->compute) {
|
||||||
mju_error("`compute` is null for plugin at slot %d", slot);
|
mju_error("`compute` is null for plugin at slot %d", slot);
|
||||||
}
|
}
|
||||||
@@ -787,14 +787,14 @@ void mj_energyPos(const mjModel* m, mjData* d) {
|
|||||||
// init potential energy: -sum_i body(i).mass * mju_dot(body(i).pos, gravity)
|
// init potential energy: -sum_i body(i).mass * mju_dot(body(i).pos, gravity)
|
||||||
d->energy[0] = 0;
|
d->energy[0] = 0;
|
||||||
if (!mjDISABLED(mjDSBL_GRAVITY)) {
|
if (!mjDISABLED(mjDSBL_GRAVITY)) {
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
d->energy[0] -= m->body_mass[i] * mju_dot3(m->opt.gravity, d->xipos+3*i);
|
d->energy[0] -= m->body_mass[i] * mju_dot3(m->opt.gravity, d->xipos+3*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add joint-level springs
|
// add joint-level springs
|
||||||
if (!mjDISABLED(mjDSBL_PASSIVE)) {
|
if (!mjDISABLED(mjDSBL_PASSIVE)) {
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
stiffness = m->jnt_stiffness[i];
|
stiffness = m->jnt_stiffness[i];
|
||||||
padr = m->jnt_qposadr[i];
|
padr = m->jnt_qposadr[i];
|
||||||
|
|
||||||
@@ -825,7 +825,7 @@ void mj_energyPos(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// add tendon-level springs
|
// add tendon-level springs
|
||||||
if (!mjDISABLED(mjDSBL_PASSIVE)) {
|
if (!mjDISABLED(mjDSBL_PASSIVE)) {
|
||||||
for (int i=0; i<m->ntendon; i++) {
|
for (int i=0; i < m->ntendon; i++) {
|
||||||
stiffness = m->tendon_stiffness[i];
|
stiffness = m->tendon_stiffness[i];
|
||||||
mjtNum length = d->ten_length[i];
|
mjtNum length = d->ten_length[i];
|
||||||
mjtNum displacement = 0;
|
mjtNum displacement = 0;
|
||||||
|
|||||||
@@ -42,14 +42,14 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
// save camera and light mode, set to fixed
|
// save camera and light mode, set to fixed
|
||||||
if (m->ncam) {
|
if (m->ncam) {
|
||||||
cammode = (int*) mj_stackAlloc(d, m->ncam);
|
cammode = (int*) mj_stackAlloc(d, m->ncam);
|
||||||
for (int i=0; i<m->ncam; i++) {
|
for (int i=0; i < m->ncam; i++) {
|
||||||
cammode[i] = m->cam_mode[i];
|
cammode[i] = m->cam_mode[i];
|
||||||
m->cam_mode[i] = mjCAMLIGHT_FIXED;
|
m->cam_mode[i] = mjCAMLIGHT_FIXED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m->nlight) {
|
if (m->nlight) {
|
||||||
lightmode = (int*) mj_stackAlloc(d, m->nlight);
|
lightmode = (int*) mj_stackAlloc(d, m->nlight);
|
||||||
for (int i=0; i<m->nlight; i++) {
|
for (int i=0; i < m->nlight; i++) {
|
||||||
lightmode[i] = m->light_mode[i];
|
lightmode[i] = m->light_mode[i];
|
||||||
m->light_mode[i] = mjCAMLIGHT_FIXED;
|
m->light_mode[i] = mjCAMLIGHT_FIXED;
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
mj_crbSkip(m, d, 0);
|
mj_crbSkip(m, d, 0);
|
||||||
|
|
||||||
// save dof_M0
|
// save dof_M0
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
m->dof_M0[i] = d->qM[m->dof_Madr[i]];
|
m->dof_M0[i] = d->qM[m->dof_Madr[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,10 +73,10 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
mj_transmission(m, d);
|
mj_transmission(m, d);
|
||||||
|
|
||||||
// restore camera and light mode
|
// restore camera and light mode
|
||||||
for (int i=0; i<m->ncam; i++) {
|
for (int i=0; i < m->ncam; i++) {
|
||||||
m->cam_mode[i] = cammode[i];
|
m->cam_mode[i] = cammode[i];
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->nlight; i++) {
|
for (int i=0; i < m->nlight; i++) {
|
||||||
m->light_mode[i] = lightmode[i];
|
m->light_mode[i] = lightmode[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// compute body_invweight0
|
// compute body_invweight0
|
||||||
m->body_invweight0[0] = m->body_invweight0[1] = 0.0;
|
m->body_invweight0[0] = m->body_invweight0[1] = 0.0;
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
if (nv) {
|
if (nv) {
|
||||||
// inverse spatial inertia: A = J*inv(M)*J'
|
// inverse spatial inertia: A = J*inv(M)*J'
|
||||||
mj_jacBodyCom(m, d, jac, jac+3*nv, i);
|
mj_jacBodyCom(m, d, jac, jac+3*nv, i);
|
||||||
@@ -100,13 +100,13 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute dof_invweight0
|
// compute dof_invweight0
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
id = m->jnt_dofadr[i];
|
id = m->jnt_dofadr[i];
|
||||||
|
|
||||||
// get number of components
|
// get number of components
|
||||||
if (m->jnt_type[i]==mjJNT_FREE) {
|
if (m->jnt_type[i] == mjJNT_FREE) {
|
||||||
dnum = 6;
|
dnum = 6;
|
||||||
} else if (m->jnt_type[i]==mjJNT_BALL) {
|
} else if (m->jnt_type[i] == mjJNT_BALL) {
|
||||||
dnum = 3;
|
dnum = 3;
|
||||||
} else {
|
} else {
|
||||||
dnum = 1;
|
dnum = 1;
|
||||||
@@ -115,7 +115,7 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
// inverse joint inertia: A = J*inv(M)*J'
|
// inverse joint inertia: A = J*inv(M)*J'
|
||||||
if (nv) {
|
if (nv) {
|
||||||
mju_zero(jac, dnum*nv);
|
mju_zero(jac, dnum*nv);
|
||||||
for (int j=0; j<dnum; j++) {
|
for (int j=0; j < dnum; j++) {
|
||||||
jac[j*(nv+1) + id] = 1;
|
jac[j*(nv+1) + id] = 1;
|
||||||
}
|
}
|
||||||
mj_solveM(m, d, tmp, jac, dnum);
|
mj_solveM(m, d, tmp, jac, dnum);
|
||||||
@@ -123,14 +123,14 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// average diagonal and assign
|
// average diagonal and assign
|
||||||
if (dnum==6) {
|
if (dnum == 6) {
|
||||||
m->dof_invweight0[id] = m->dof_invweight0[id+1] = m->dof_invweight0[id+2] =
|
m->dof_invweight0[id] = m->dof_invweight0[id+1] = m->dof_invweight0[id+2] =
|
||||||
(A[0] + A[7] + A[14])/3;
|
(A[0] + A[7] + A[14])/3;
|
||||||
m->dof_invweight0[id+3] = m->dof_invweight0[id+4] = m->dof_invweight0[id+5] =
|
m->dof_invweight0[id+3] = m->dof_invweight0[id+4] = m->dof_invweight0[id+5] =
|
||||||
(A[21] + A[28] + A[35])/3;
|
(A[21] + A[28] + A[35])/3;
|
||||||
} else if (dnum==3)
|
} else if (dnum == 3)
|
||||||
m->dof_invweight0[id] = m->dof_invweight0[id+1] = m->dof_invweight0[id+2] =
|
m->dof_invweight0[id] = m->dof_invweight0[id+1] = m->dof_invweight0[id+2] =
|
||||||
(A[0] + A[4] + A[8])/3;
|
(A[0] + A[4] + A[8])/3;
|
||||||
else {
|
else {
|
||||||
m->dof_invweight0[id] = A[0];
|
m->dof_invweight0[id] = A[0];
|
||||||
}
|
}
|
||||||
@@ -138,12 +138,12 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// compute tendon_invweight0
|
// compute tendon_invweight0
|
||||||
if (nv) {
|
if (nv) {
|
||||||
for (int i=0; i<m->ntendon; i++) {
|
for (int i=0; i < m->ntendon; i++) {
|
||||||
// make dense vector into tmp
|
// make dense vector into tmp
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
mju_zero(tmp, nv);
|
mju_zero(tmp, nv);
|
||||||
int end = d->ten_J_rowadr[i] + d->ten_J_rownnz[i];
|
int end = d->ten_J_rowadr[i] + d->ten_J_rownnz[i];
|
||||||
for (int j=d->ten_J_rowadr[i]; j<end; j++) {
|
for (int j=d->ten_J_rowadr[i]; j < end; j++) {
|
||||||
tmp[d->ten_J_colind[j]] = d->ten_J[j];
|
tmp[d->ten_J_colind[j]] = d->ten_J[j];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -156,24 +156,24 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute actuator_acc0
|
// compute actuator_acc0
|
||||||
for (int i=0; i<m->nu; i++) {
|
for (int i=0; i < m->nu; i++) {
|
||||||
mj_solveM(m, d, tmp, d->actuator_moment+i*nv, 1);
|
mj_solveM(m, d, tmp, d->actuator_moment+i*nv, 1);
|
||||||
m->actuator_acc0[i] = mju_norm(tmp, nv);
|
m->actuator_acc0[i] = mju_norm(tmp, nv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<m->nu; i++) {
|
for (int i=0; i < m->nu; i++) {
|
||||||
m->actuator_acc0[i] = 0;
|
m->actuator_acc0[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute missing eq_data for body constraints
|
// compute missing eq_data for body constraints
|
||||||
for (int i=0; i<m->neq; i++) {
|
for (int i=0; i < m->neq; i++) {
|
||||||
// get ids
|
// get ids
|
||||||
id1 = m->eq_obj1id[i];
|
id1 = m->eq_obj1id[i];
|
||||||
id2 = m->eq_obj2id[i];
|
id2 = m->eq_obj2id[i];
|
||||||
|
|
||||||
// connect constraint
|
// connect constraint
|
||||||
if (m->eq_type[i]==mjEQ_CONNECT) {
|
if (m->eq_type[i] == mjEQ_CONNECT) {
|
||||||
// pos = anchor position in global frame
|
// pos = anchor position in global frame
|
||||||
mj_local2Global(d, pos, 0, m->eq_data+mjNEQDATA*i, 0, id1, 0);
|
mj_local2Global(d, pos, 0, m->eq_data+mjNEQDATA*i, 0, id1, 0);
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// weld constraint
|
// weld constraint
|
||||||
else if (m->eq_type[i]==mjEQ_WELD) {
|
else if (m->eq_type[i] == mjEQ_WELD) {
|
||||||
// skip if user has set any quaternion data
|
// skip if user has set any quaternion data
|
||||||
if (m->eq_data[mjNEQDATA*i+6] ||
|
if (m->eq_data[mjNEQDATA*i+6] ||
|
||||||
m->eq_data[mjNEQDATA*i+7] ||
|
m->eq_data[mjNEQDATA*i+7] ||
|
||||||
@@ -208,28 +208,28 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// camera compos0, pos0, mat0
|
// camera compos0, pos0, mat0
|
||||||
for (int i=0; i<m->ncam; i++) {
|
for (int i=0; i < m->ncam; i++) {
|
||||||
// get body ids
|
// get body ids
|
||||||
id = m->cam_bodyid[i]; // camera body
|
id = m->cam_bodyid[i]; // camera body
|
||||||
id1 = m->cam_targetbodyid[i]; // target body
|
id1 = m->cam_targetbodyid[i]; // target body
|
||||||
|
|
||||||
// compute positional offsets
|
// compute positional offsets
|
||||||
mju_sub3(m->cam_pos0+3*i, d->cam_xpos+3*i, d->xpos+3*id);
|
mju_sub3(m->cam_pos0+3*i, d->cam_xpos+3*i, d->xpos+3*id);
|
||||||
mju_sub3(m->cam_poscom0+3*i, d->cam_xpos+3*i, d->subtree_com+ (id1>=0 ? 3*id1 : 3*id));
|
mju_sub3(m->cam_poscom0+3*i, d->cam_xpos+3*i, d->subtree_com+ (id1 >= 0 ? 3*id1 : 3*id));
|
||||||
|
|
||||||
// copy mat
|
// copy mat
|
||||||
mju_copy(m->cam_mat0+9*i, d->cam_xmat+9*i, 9);
|
mju_copy(m->cam_mat0+9*i, d->cam_xmat+9*i, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
// light compos0, pos0, dir0
|
// light compos0, pos0, dir0
|
||||||
for (int i=0; i<m->nlight; i++) {
|
for (int i=0; i < m->nlight; i++) {
|
||||||
// get body ids
|
// get body ids
|
||||||
id = m->light_bodyid[i]; // light body
|
id = m->light_bodyid[i]; // light body
|
||||||
id1 = m->light_targetbodyid[i]; // target body
|
id1 = m->light_targetbodyid[i]; // target body
|
||||||
|
|
||||||
// compute positional offsets
|
// compute positional offsets
|
||||||
mju_sub3(m->light_pos0+3*i, d->light_xpos+3*i, d->xpos+3*id);
|
mju_sub3(m->light_pos0+3*i, d->light_xpos+3*i, d->xpos+3*id);
|
||||||
mju_sub3(m->light_poscom0+3*i, d->light_xpos+3*i, d->subtree_com+ (id1>=0 ? 3*id1 : 3*id));
|
mju_sub3(m->light_poscom0+3*i, d->light_xpos+3*i, d->subtree_com+ (id1 >= 0 ? 3*id1 : 3*id));
|
||||||
|
|
||||||
// copy dir
|
// copy dir
|
||||||
mju_copy3(m->light_dir0+3*i, d->light_xdir+3*i);
|
mju_copy3(m->light_dir0+3*i, d->light_xdir+3*i);
|
||||||
@@ -242,7 +242,7 @@ static void set0(mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// accumulate bounding box
|
// accumulate bounding box
|
||||||
static void updateBox(mjtNum* xmin, mjtNum* xmax, mjtNum* pos, mjtNum radius) {
|
static void updateBox(mjtNum* xmin, mjtNum* xmax, mjtNum* pos, mjtNum radius) {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
xmin[i] = mjMIN(xmin[i], pos[i] - radius);
|
xmin[i] = mjMIN(xmin[i], pos[i] - radius);
|
||||||
xmax[i] = mjMAX(xmax[i], pos[i] + radius);
|
xmax[i] = mjMAX(xmax[i], pos[i] + radius);
|
||||||
}
|
}
|
||||||
@@ -258,22 +258,22 @@ static void setStat(mjModel* m, mjData* d) {
|
|||||||
mjtNum* body = mj_stackAlloc(d, m->nbody);
|
mjtNum* body = mj_stackAlloc(d, m->nbody);
|
||||||
|
|
||||||
// compute bounding box of bodies, joint centers, geoms and sites
|
// compute bounding box of bodies, joint centers, geoms and sites
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
updateBox(xmin, xmax, d->xpos+3*i, 0);
|
updateBox(xmin, xmax, d->xpos+3*i, 0);
|
||||||
updateBox(xmin, xmax, d->xipos+3*i, 0);
|
updateBox(xmin, xmax, d->xipos+3*i, 0);
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
updateBox(xmin, xmax, d->xanchor+3*i, 0);
|
updateBox(xmin, xmax, d->xanchor+3*i, 0);
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->nsite; i++) {
|
for (int i=0; i < m->nsite; i++) {
|
||||||
updateBox(xmin, xmax, d->site_xpos+3*i, 0);
|
updateBox(xmin, xmax, d->site_xpos+3*i, 0);
|
||||||
}
|
}
|
||||||
for (int i=0; i<m->ngeom; i++) {
|
for (int i=0; i < m->ngeom; i++) {
|
||||||
// set rbound: regular geom rbound, or 0.1 of plane or hfield max size
|
// set rbound: regular geom rbound, or 0.1 of plane or hfield max size
|
||||||
rbound = 0;
|
rbound = 0;
|
||||||
if (m->geom_rbound[i] > 0) {
|
if (m->geom_rbound[i] > 0) {
|
||||||
rbound = m->geom_rbound[i];
|
rbound = m->geom_rbound[i];
|
||||||
} else if (m->geom_type[i]==mjGEOM_PLANE) {
|
} else if (m->geom_type[i] == mjGEOM_PLANE) {
|
||||||
// finite in at least one direction
|
// finite in at least one direction
|
||||||
if (m->geom_size[3*i] || m->geom_size[3*i+1]) {
|
if (m->geom_size[3*i] || m->geom_size[3*i+1]) {
|
||||||
rbound = mjMAX(m->geom_size[3*i], m->geom_size[3*i+1]) * 0.1;
|
rbound = mjMAX(m->geom_size[3*i], m->geom_size[3*i+1]) * 0.1;
|
||||||
@@ -283,7 +283,7 @@ static void setStat(mjModel* m, mjData* d) {
|
|||||||
else {
|
else {
|
||||||
rbound = 1;
|
rbound = 1;
|
||||||
}
|
}
|
||||||
} else if (m->geom_type[i]==mjGEOM_HFIELD) {
|
} else if (m->geom_type[i] == mjGEOM_HFIELD) {
|
||||||
int j = m->geom_dataid[i];
|
int j = m->geom_dataid[i];
|
||||||
rbound = mjMAX(m->hfield_size[4*j],
|
rbound = mjMAX(m->hfield_size[4*j],
|
||||||
mjMAX(m->hfield_size[4*j+1],
|
mjMAX(m->hfield_size[4*j+1],
|
||||||
@@ -298,13 +298,13 @@ static void setStat(mjModel* m, mjData* d) {
|
|||||||
mju_scl3(m->stat.center, m->stat.center, 0.5);
|
mju_scl3(m->stat.center, m->stat.center, 0.5);
|
||||||
|
|
||||||
// compute bounding box size
|
// compute bounding box size
|
||||||
if (xmax[0]>xmin[0])
|
if (xmax[0] > xmin[0])
|
||||||
m->stat.extent = mju_max(1E-5,
|
m->stat.extent = mju_max(1E-5,
|
||||||
mju_max(xmax[0]-xmin[0], mju_max(xmax[1]-xmin[1], xmax[2]-xmin[2])));
|
mju_max(xmax[0]-xmin[0], mju_max(xmax[1]-xmin[1], xmax[2]-xmin[2])));
|
||||||
|
|
||||||
// set body size to max com-joint distance
|
// set body size to max com-joint distance
|
||||||
mju_zero(body, m->nbody);
|
mju_zero(body, m->nbody);
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
// handle this body
|
// handle this body
|
||||||
int id = m->jnt_bodyid[i];
|
int id = m->jnt_bodyid[i];
|
||||||
body[id] = mju_max(body[id], mju_dist3(d->xipos+3*id, d->xanchor+3*i));
|
body[id] = mju_max(body[id], mju_dist3(d->xipos+3*id, d->xanchor+3*i));
|
||||||
@@ -316,18 +316,18 @@ static void setStat(mjModel* m, mjData* d) {
|
|||||||
body[0] = 0;
|
body[0] = 0;
|
||||||
|
|
||||||
// set body size to max of old value, and geom rbound + com-geom dist
|
// set body size to max of old value, and geom rbound + com-geom dist
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
for (int id=m->body_geomadr[i]; id<m->body_geomadr[i]+m->body_geomnum[i]; id++) {
|
for (int id=m->body_geomadr[i]; id < m->body_geomadr[i]+m->body_geomnum[i]; id++) {
|
||||||
if (m->geom_rbound[id]>0) {
|
if (m->geom_rbound[id] > 0) {
|
||||||
body[i] = mju_max(body[i], m->geom_rbound[id] + mju_dist3(d->xipos+3*i, d->geom_xpos+3*id));
|
body[i] = mju_max(body[i], m->geom_rbound[id] + mju_dist3(d->xipos+3*i, d->geom_xpos+3*id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute meansize, make sure all sizes are above min
|
// compute meansize, make sure all sizes are above min
|
||||||
if (m->nbody>1) {
|
if (m->nbody > 1) {
|
||||||
m->stat.meansize = 0;
|
m->stat.meansize = 0;
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
body[i] = mju_max(body[i], 1E-5);
|
body[i] = mju_max(body[i], 1E-5);
|
||||||
m->stat.meansize += body[i]/(m->nbody-1);
|
m->stat.meansize += body[i]/(m->nbody-1);
|
||||||
}
|
}
|
||||||
@@ -337,9 +337,9 @@ static void setStat(mjModel* m, mjData* d) {
|
|||||||
m->stat.extent = mju_max(m->stat.extent, 2 * m->stat.meansize);
|
m->stat.extent = mju_max(m->stat.extent, 2 * m->stat.meansize);
|
||||||
|
|
||||||
// compute meanmass
|
// compute meanmass
|
||||||
if (m->nbody>1) {
|
if (m->nbody > 1) {
|
||||||
m->stat.meanmass = 0;
|
m->stat.meanmass = 0;
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
m->stat.meanmass += m->body_mass[i];
|
m->stat.meanmass += m->body_mass[i];
|
||||||
}
|
}
|
||||||
m->stat.meanmass /= (m->nbody-1);
|
m->stat.meanmass /= (m->nbody-1);
|
||||||
@@ -348,7 +348,7 @@ static void setStat(mjModel* m, mjData* d) {
|
|||||||
// compute meaninertia
|
// compute meaninertia
|
||||||
if (m->nv) {
|
if (m->nv) {
|
||||||
m->stat.meaninertia = 0;
|
m->stat.meaninertia = 0;
|
||||||
for (int i=0; i<m->nv; i++) {
|
for (int i=0; i < m->nv; i++) {
|
||||||
m->stat.meaninertia += d->qM[m->dof_Madr[i]];
|
m->stat.meaninertia += d->qM[m->dof_Madr[i]];
|
||||||
}
|
}
|
||||||
m->stat.meaninertia /= m->nv;
|
m->stat.meaninertia /= m->nv;
|
||||||
@@ -369,7 +369,7 @@ static void setSpring(mjModel* m, mjData* d) {
|
|||||||
mj_transmission(m, d);
|
mj_transmission(m, d);
|
||||||
|
|
||||||
// copy if model spring length is -1
|
// copy if model spring length is -1
|
||||||
for (int i=0; i<m->ntendon; i++) {
|
for (int i=0; i < m->ntendon; i++) {
|
||||||
if (m->tendon_lengthspring[2*i] == -1 && m->tendon_lengthspring[2*i+1] == -1) {
|
if (m->tendon_lengthspring[2*i] == -1 && m->tendon_lengthspring[2*i+1] == -1) {
|
||||||
// explicit springlength unused, set equal to ten_length
|
// explicit springlength unused, set equal to ten_length
|
||||||
m->tendon_lengthspring[2*i] = m->tendon_lengthspring[2*i+1] = d->ten_length[i];
|
m->tendon_lengthspring[2*i] = m->tendon_lengthspring[2*i+1] = d->ten_length[i];
|
||||||
@@ -382,10 +382,10 @@ static void setSpring(mjModel* m, mjData* d) {
|
|||||||
// entry point: set all constant fields of mjModel, except for lengthrange
|
// entry point: set all constant fields of mjModel, except for lengthrange
|
||||||
void mj_setConst(mjModel* m, mjData* d) {
|
void mj_setConst(mjModel* m, mjData* d) {
|
||||||
// compute subtreemass
|
// compute subtreemass
|
||||||
for (int i=0; i<m->nbody; i++) {
|
for (int i=0; i < m->nbody; i++) {
|
||||||
m->body_subtreemass[i] = m->body_mass[i];
|
m->body_subtreemass[i] = m->body_mass[i];
|
||||||
}
|
}
|
||||||
for (int i=m->nbody-1; i>0; i--) {
|
for (int i=m->nbody-1; i > 0; i--) {
|
||||||
m->body_subtreemass[m->body_parentid[i]] += m->body_subtreemass[i];
|
m->body_subtreemass[m->body_parentid[i]] += m->body_subtreemass[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,7 +418,7 @@ static mjtNum evalAct(const mjModel* m, mjData* d, int index, int side,
|
|||||||
|
|
||||||
// impose maxforce
|
// impose maxforce
|
||||||
nrm = mju_norm(d->qfrc_applied, nv);
|
nrm = mju_norm(d->qfrc_applied, nv);
|
||||||
if (opt->maxforce>0 && nrm>opt->maxforce) {
|
if (opt->maxforce > 0 && nrm > opt->maxforce) {
|
||||||
mju_scl(d->qfrc_applied, d->qfrc_applied, opt->maxforce/mjMAX(mjMINVAL, nrm), nv);
|
mju_scl(d->qfrc_applied, d->qfrc_applied, opt->maxforce/mjMAX(mjMINVAL, nrm), nv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,18 +435,18 @@ static mjtNum evalAct(const mjModel* m, mjData* d, int index, int side,
|
|||||||
int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
||||||
const mjLROpt* opt, char* error, int error_sz) {
|
const mjLROpt* opt, char* error, int error_sz) {
|
||||||
// check index
|
// check index
|
||||||
if (index<0 || index>=m->nu) {
|
if (index < 0 || index >= m->nu) {
|
||||||
mju_error("Invalid actuator index in mj_setLengthRange");
|
mju_error("Invalid actuator index in mj_setLengthRange");
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip depending on mode and type
|
// skip depending on mode and type
|
||||||
int ismuscle = (m->actuator_gaintype[index]==mjGAIN_MUSCLE ||
|
int ismuscle = (m->actuator_gaintype[index] == mjGAIN_MUSCLE ||
|
||||||
m->actuator_biastype[index]==mjBIAS_MUSCLE);
|
m->actuator_biastype[index] == mjBIAS_MUSCLE);
|
||||||
int isuser = (m->actuator_gaintype[index]==mjGAIN_USER ||
|
int isuser = (m->actuator_gaintype[index] == mjGAIN_USER ||
|
||||||
m->actuator_biastype[index]==mjBIAS_USER);
|
m->actuator_biastype[index] == mjBIAS_USER);
|
||||||
if ((opt->mode==mjLRMODE_NONE) ||
|
if ((opt->mode == mjLRMODE_NONE) ||
|
||||||
(opt->mode==mjLRMODE_MUSCLE && !ismuscle) ||
|
(opt->mode == mjLRMODE_MUSCLE && !ismuscle) ||
|
||||||
(opt->mode==mjLRMODE_MUSCLEUSER && !ismuscle && !isuser)) {
|
(opt->mode == mjLRMODE_MUSCLEUSER && !ismuscle && !isuser)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,8 +461,8 @@ int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
|||||||
// use joint and tendon limits if available
|
// use joint and tendon limits if available
|
||||||
if (opt->uselimit) {
|
if (opt->uselimit) {
|
||||||
// joint or jointinparent
|
// joint or jointinparent
|
||||||
if (m->actuator_trntype[index]==mjTRN_JOINT ||
|
if (m->actuator_trntype[index] == mjTRN_JOINT ||
|
||||||
m->actuator_trntype[index]==mjTRN_JOINTINPARENT) {
|
m->actuator_trntype[index] == mjTRN_JOINTINPARENT) {
|
||||||
// make sure joint is limited
|
// make sure joint is limited
|
||||||
if (m->jnt_limited[threadid]) {
|
if (m->jnt_limited[threadid]) {
|
||||||
// copy range
|
// copy range
|
||||||
@@ -475,7 +475,7 @@ int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tendon
|
// tendon
|
||||||
if (m->actuator_trntype[index]==mjTRN_TENDON) {
|
if (m->actuator_trntype[index] == mjTRN_TENDON) {
|
||||||
// make sure tendon is limited
|
// make sure tendon is limited
|
||||||
if (m->tendon_limited[threadid]) {
|
if (m->tendon_limited[threadid]) {
|
||||||
// copy range
|
// copy range
|
||||||
@@ -491,7 +491,7 @@ int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
|||||||
// optimize in both directions
|
// optimize in both directions
|
||||||
mjtNum lmin[2] = {0, 0}, lmax[2] = {0, 0};
|
mjtNum lmin[2] = {0, 0}, lmax[2] = {0, 0};
|
||||||
int side;
|
int side;
|
||||||
for (side=0; side<2; side++) {
|
for (side=0; side < 2; side++) {
|
||||||
// init at qpos0
|
// init at qpos0
|
||||||
mj_resetData(m, d);
|
mj_resetData(m, d);
|
||||||
|
|
||||||
@@ -502,17 +502,17 @@ int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
|||||||
mjtNum len = evalAct(m, d, index, side, opt);
|
mjtNum len = evalAct(m, d, index, side, opt);
|
||||||
|
|
||||||
// reset: cannot proceed
|
// reset: cannot proceed
|
||||||
if (d->time==0) {
|
if (d->time == 0) {
|
||||||
snprintf(error, error_sz, "Unstable lengthrange simulation in actuator %d", index);
|
snprintf(error, error_sz, "Unstable lengthrange simulation in actuator %d", index);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update limits
|
// update limits
|
||||||
if (d->time > opt->inttotal-opt->interval) {
|
if (d->time > opt->inttotal-opt->interval) {
|
||||||
if (len<lmin[side] || !updated) {
|
if (len < lmin[side] || !updated) {
|
||||||
lmin[side] = len;
|
lmin[side] = len;
|
||||||
}
|
}
|
||||||
if (len>lmax[side] || !updated) {
|
if (len > lmax[side] || !updated) {
|
||||||
lmax[side] = len;
|
lmax[side] = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,12 +521,12 @@ int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// assign
|
// assign
|
||||||
m->actuator_lengthrange[2*index+side] = (side==0 ? lmin[side] : lmax[side]);
|
m->actuator_lengthrange[2*index+side] = (side == 0 ? lmin[side] : lmax[side]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check range
|
// check range
|
||||||
mjtNum dif = m->actuator_lengthrange[2*index+1] - m->actuator_lengthrange[2*index];
|
mjtNum dif = m->actuator_lengthrange[2*index+1] - m->actuator_lengthrange[2*index];
|
||||||
if (dif<=0) {
|
if (dif <= 0) {
|
||||||
snprintf(error, error_sz,
|
snprintf(error, error_sz,
|
||||||
"Invalid lengthrange (%g, %g) in actuator %d",
|
"Invalid lengthrange (%g, %g) in actuator %d",
|
||||||
m->actuator_lengthrange[2*index],
|
m->actuator_lengthrange[2*index],
|
||||||
@@ -535,7 +535,7 @@ int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check convergence, side 0
|
// check convergence, side 0
|
||||||
if (lmax[0]-lmin[0]>opt->tolrange*dif) {
|
if (lmax[0]-lmin[0] > opt->tolrange*dif) {
|
||||||
snprintf(error, error_sz,
|
snprintf(error, error_sz,
|
||||||
"Lengthrange computation did not converge in actuator %d:\n"
|
"Lengthrange computation did not converge in actuator %d:\n"
|
||||||
" eval (%g, %g)\n range (%g, %g)",
|
" eval (%g, %g)\n range (%g, %g)",
|
||||||
@@ -546,7 +546,7 @@ int mj_setLengthRange(mjModel* m, mjData* d, int index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check convergence, side 1
|
// check convergence, side 1
|
||||||
if (lmax[1]-lmin[1]>opt->tolrange*dif) {
|
if (lmax[1]-lmin[1] > opt->tolrange*dif) {
|
||||||
snprintf(error, error_sz,
|
snprintf(error, error_sz,
|
||||||
"Lengthrange computation did not converge in actuator %d:\n"
|
"Lengthrange computation did not converge in actuator %d:\n"
|
||||||
" eval (%g, %g)\n range (%g, %g)",
|
" eval (%g, %g)\n range (%g, %g)",
|
||||||
|
|||||||
+165
-163
@@ -48,7 +48,7 @@ static void saveStats(const mjModel* m, mjData* d, int* piter,
|
|||||||
(*piter)++;
|
(*piter)++;
|
||||||
|
|
||||||
// save if within range
|
// save if within range
|
||||||
if (i<mjNSOLVER) {
|
if (i < mjNSOLVER) {
|
||||||
d->solver[i].improvement = improvement;
|
d->solver[i].improvement = improvement;
|
||||||
d->solver[i].gradient = gradient;
|
d->solver[i].gradient = gradient;
|
||||||
d->solver[i].lineslope = lineslope;
|
d->solver[i].lineslope = lineslope;
|
||||||
@@ -80,9 +80,9 @@ static void ARdiaginv(const mjModel* m, mjData* d, mjtNum* res, int flg_subR) {
|
|||||||
|
|
||||||
// sparse
|
// sparse
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
for (int j=0; j<d->efc_AR_rownnz[i]; j++) {
|
for (int j=0; j < d->efc_AR_rownnz[i]; j++) {
|
||||||
if (i==d->efc_AR_colind[rowadr[i]+j]) {
|
if (i == d->efc_AR_colind[rowadr[i]+j]) {
|
||||||
res[i] = 1/(flg_subR ? mju_max(mjMINVAL, d->efc_AR[rowadr[i]+j]-d->efc_R[i])
|
res[i] = 1/(flg_subR ? mju_max(mjMINVAL, d->efc_AR[rowadr[i]+j]-d->efc_R[i])
|
||||||
: d->efc_AR[rowadr[i]+j]);
|
: d->efc_AR[rowadr[i]+j]);
|
||||||
break;
|
break;
|
||||||
@@ -93,7 +93,7 @@ static void ARdiaginv(const mjModel* m, mjData* d, mjtNum* res, int flg_subR) {
|
|||||||
|
|
||||||
// dense
|
// dense
|
||||||
else {
|
else {
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
res[i] = 1/(flg_subR ? mju_max(mjMINVAL, d->efc_AR[i*(nefc+1)]-d->efc_R[i])
|
res[i] = 1/(flg_subR ? mju_max(mjMINVAL, d->efc_AR[i*(nefc+1)]-d->efc_R[i])
|
||||||
: d->efc_AR[i*(nefc+1)]);
|
: d->efc_AR[i*(nefc+1)]);
|
||||||
}
|
}
|
||||||
@@ -121,36 +121,36 @@ static void extractBlock(const mjModel* m, mjData* d, mjtNum* Ac,
|
|||||||
if( col>=start && col<start+n )
|
if( col>=start && col<start+n )
|
||||||
Ac[j*n+col-start] = AR[rowadr[start+j]+k];
|
Ac[j*n+col-start] = AR[rowadr[start+j]+k];
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// assume full sub-matrix, find starting k: same for all rows
|
// assume full sub-matrix, find starting k: same for all rows
|
||||||
int k;
|
int k;
|
||||||
for (k=0; k<rownnz[start]; k++) {
|
for (k=0; k < rownnz[start]; k++) {
|
||||||
if (colind[rowadr[start]+k]==start) {
|
if (colind[rowadr[start]+k] == start) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sanity check; SHOULD NOT OCCUR
|
// sanity check; SHOULD NOT OCCUR
|
||||||
if (k>=rownnz[start]) {
|
if (k >= rownnz[start]) {
|
||||||
mju_error("Internal error in extractComponent");
|
mju_error("Internal error in extractComponent");
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy rows
|
// copy rows
|
||||||
for (int j=0; j<n; j++) {
|
for (int j=0; j < n; j++) {
|
||||||
mju_copy(Ac+j*n, AR+rowadr[start+j]+k, n);
|
mju_copy(Ac+j*n, AR+rowadr[start+j]+k, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dense
|
// dense
|
||||||
else {
|
else {
|
||||||
for (int j=0; j<n; j++) {
|
for (int j=0; j < n; j++) {
|
||||||
mju_copy(Ac+j*n, AR+start+(start+j)*nefc, n);
|
mju_copy(Ac+j*n, AR+start+(start+j)*nefc, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// subtract R from diagonal, clamp to 1e-10 from below
|
// subtract R from diagonal, clamp to 1e-10 from below
|
||||||
if (flg_subR) {
|
if (flg_subR) {
|
||||||
for (int j=0; j<n; j++) {
|
for (int j=0; j < n; j++) {
|
||||||
Ac[j*(n+1)] -= d->efc_R[start+j];
|
Ac[j*(n+1)] -= d->efc_R[start+j];
|
||||||
Ac[j*(n+1)] = mjMAX(1e-10, Ac[j*(n+1)]);
|
Ac[j*(n+1)] = mjMAX(1e-10, Ac[j*(n+1)]);
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ static void residual(const mjModel* m, mjData* d, mjtNum* res, int i, int dim, i
|
|||||||
|
|
||||||
// sparse
|
// sparse
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
for (int j=0; j<dim; j++) {
|
for (int j=0; j < dim; j++) {
|
||||||
res[j] = d->efc_b[i+j] + mju_dotSparse(d->efc_AR + d->efc_AR_rowadr[i+j],
|
res[j] = d->efc_b[i+j] + mju_dotSparse(d->efc_AR + d->efc_AR_rowadr[i+j],
|
||||||
d->efc_force, d->efc_AR_rownnz[i+j],
|
d->efc_force, d->efc_AR_rownnz[i+j],
|
||||||
d->efc_AR_colind + d->efc_AR_rowadr[i+j]);
|
d->efc_AR_colind + d->efc_AR_rowadr[i+j]);
|
||||||
@@ -174,13 +174,13 @@ static void residual(const mjModel* m, mjData* d, mjtNum* res, int i, int dim, i
|
|||||||
|
|
||||||
// dense
|
// dense
|
||||||
else {
|
else {
|
||||||
for (int j=0; j<dim; j++) {
|
for (int j=0; j < dim; j++) {
|
||||||
res[j] = d->efc_b[i+j] + mju_dot(d->efc_AR+(i+j)*nefc, d->efc_force, nefc);
|
res[j] = d->efc_b[i+j] + mju_dot(d->efc_AR+(i+j)*nefc, d->efc_force, nefc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flg_subR) {
|
if (flg_subR) {
|
||||||
for (int j=0; j<dim; j++) {
|
for (int j=0; j < dim; j++) {
|
||||||
res[j] -= d->efc_R[i+j]*d->efc_force[i+j];
|
res[j] -= d->efc_R[i+j]*d->efc_force[i+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ static mjtNum costChange(const mjtNum* A, mjtNum* force, const mjtNum* oldforce,
|
|||||||
mjtNum delta[6], change;
|
mjtNum delta[6], change;
|
||||||
|
|
||||||
// compute change
|
// compute change
|
||||||
if (dim==1) {
|
if (dim == 1) {
|
||||||
delta[0] = force[0] - oldforce[0];
|
delta[0] = force[0] - oldforce[0];
|
||||||
change = 0.5*delta[0]*delta[0]*A[0] + delta[0]*res[0];
|
change = 0.5*delta[0]*delta[0]*A[0] + delta[0]*res[0];
|
||||||
} else {
|
} else {
|
||||||
@@ -203,7 +203,7 @@ static mjtNum costChange(const mjtNum* A, mjtNum* force, const mjtNum* oldforce,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// positive change: restore
|
// positive change: restore
|
||||||
if (change>1e-10) {
|
if (change > 1e-10) {
|
||||||
mju_copy(force, oldforce, dim);
|
mju_copy(force, oldforce, dim);
|
||||||
change = 0;
|
change = 0;
|
||||||
}
|
}
|
||||||
@@ -223,15 +223,15 @@ static int dualState(const mjModel* m, mjData* d) {
|
|||||||
nactive = ne + nf;
|
nactive = ne + nf;
|
||||||
|
|
||||||
// equality
|
// equality
|
||||||
for (int i=0; i<ne; i++) {
|
for (int i=0; i < ne; i++) {
|
||||||
state[i] = mjCNSTRSTATE_QUADRATIC;
|
state[i] = mjCNSTRSTATE_QUADRATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
// friction
|
// friction
|
||||||
for (int i=ne; i<ne+nf; i++) {
|
for (int i=ne; i < ne+nf; i++) {
|
||||||
if (force[i]<=-floss[i]) {
|
if (force[i] <= -floss[i]) {
|
||||||
state[i] = mjCNSTRSTATE_LINEARPOS; // opposite of primal
|
state[i] = mjCNSTRSTATE_LINEARPOS; // opposite of primal
|
||||||
} else if (force[i]>=floss[i]) {
|
} else if (force[i] >= floss[i]) {
|
||||||
state[i] = mjCNSTRSTATE_LINEARNEG;
|
state[i] = mjCNSTRSTATE_LINEARNEG;
|
||||||
} else {
|
} else {
|
||||||
state[i] = mjCNSTRSTATE_QUADRATIC;
|
state[i] = mjCNSTRSTATE_QUADRATIC;
|
||||||
@@ -239,10 +239,10 @@ static int dualState(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// limit and contact
|
// limit and contact
|
||||||
for (int i=ne+nf; i<nefc; i++) {
|
for (int i=ne+nf; i < nefc; i++) {
|
||||||
// non-negative
|
// non-negative
|
||||||
if (d->efc_type[i]!=mjCNSTR_CONTACT_ELLIPTIC) {
|
if (d->efc_type[i] != mjCNSTR_CONTACT_ELLIPTIC) {
|
||||||
if (force[i]<=0) {
|
if (force[i] <= 0) {
|
||||||
state[i] = mjCNSTRSTATE_SATISFIED;
|
state[i] = mjCNSTRSTATE_SATISFIED;
|
||||||
} else {
|
} else {
|
||||||
state[i] = mjCNSTRSTATE_QUADRATIC;
|
state[i] = mjCNSTRSTATE_QUADRATIC;
|
||||||
@@ -259,7 +259,7 @@ static int dualState(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// f = map force to regular-cone space
|
// f = map force to regular-cone space
|
||||||
f[0] = force[i]/mu;
|
f[0] = force[i]/mu;
|
||||||
for (int j=1; j<dim; j++) {
|
for (int j=1; j < dim; j++) {
|
||||||
f[j] = force[i+j]/con->friction[j-1];
|
f[j] = force[i+j]/con->friction[j-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,12 +268,12 @@ static int dualState(const mjModel* m, mjData* d) {
|
|||||||
mjtNum T = mju_norm(f+1, dim-1);
|
mjtNum T = mju_norm(f+1, dim-1);
|
||||||
|
|
||||||
// top zone
|
// top zone
|
||||||
if (mu*N>=T) {
|
if (mu*N >= T) {
|
||||||
result = mjCNSTRSTATE_SATISFIED;
|
result = mjCNSTRSTATE_SATISFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bottom zone
|
// bottom zone
|
||||||
else if (N+mu*T<=0) {
|
else if (N+mu*T <= 0) {
|
||||||
result = mjCNSTRSTATE_QUADRATIC;
|
result = mjCNSTRSTATE_QUADRATIC;
|
||||||
nactive += dim;
|
nactive += dim;
|
||||||
}
|
}
|
||||||
@@ -285,7 +285,7 @@ static int dualState(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// replicate state in all cone dimensions
|
// replicate state in all cone dimensions
|
||||||
for (int j=0; j<dim; j++) {
|
for (int j=0; j < dim; j++) {
|
||||||
state[i+j] = result;
|
state[i+j] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,14 +319,14 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
dualState(m, d);
|
dualState(m, d);
|
||||||
|
|
||||||
// main iteration
|
// main iteration
|
||||||
while (iter<maxiter) {
|
while (iter < maxiter) {
|
||||||
// clear improvement
|
// clear improvement
|
||||||
improvement = 0;
|
improvement = 0;
|
||||||
|
|
||||||
// perform one sweep
|
// perform one sweep
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
// get constraint dimensionality
|
// get constraint dimensionality
|
||||||
if (d->efc_type[i]==mjCNSTR_CONTACT_ELLIPTIC) {
|
if (d->efc_type[i] == mjCNSTR_CONTACT_ELLIPTIC) {
|
||||||
dim = d->contact[d->efc_id[i]].dim;
|
dim = d->contact[d->efc_id[i]].dim;
|
||||||
} else {
|
} else {
|
||||||
dim = 1;
|
dim = 1;
|
||||||
@@ -337,19 +337,19 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
mju_copy(oldforce, force+i, dim);
|
mju_copy(oldforce, force+i, dim);
|
||||||
|
|
||||||
// simple constraint
|
// simple constraint
|
||||||
if (d->efc_type[i]!=mjCNSTR_CONTACT_ELLIPTIC) {
|
if (d->efc_type[i] != mjCNSTR_CONTACT_ELLIPTIC) {
|
||||||
// unconstrained minimum
|
// unconstrained minimum
|
||||||
force[i] -= res[0]*ARinv[i];
|
force[i] -= res[0]*ARinv[i];
|
||||||
|
|
||||||
// impose interval and inequality constraints
|
// impose interval and inequality constraints
|
||||||
if (i>=ne && i<ne+nf) {
|
if (i >= ne && i < ne+nf) {
|
||||||
if (force[i]<-floss[i]) {
|
if (force[i] < -floss[i]) {
|
||||||
force[i] = -floss[i];
|
force[i] = -floss[i];
|
||||||
} else if (force[i]>floss[i]) {
|
} else if (force[i] > floss[i]) {
|
||||||
force[i] = floss[i];
|
force[i] = floss[i];
|
||||||
}
|
}
|
||||||
} else if (i>=ne+nf) {
|
} else if (i >= ne+nf) {
|
||||||
if (force[i]<0) {
|
if (force[i] < 0) {
|
||||||
force[i] = 0;
|
force[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,12 +368,12 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
extractBlock(m, d, Athis, i, dim, 0);
|
extractBlock(m, d, Athis, i, dim, 0);
|
||||||
|
|
||||||
// normal force too small: normal update
|
// normal force too small: normal update
|
||||||
if (force[i]<mjMINVAL) {
|
if (force[i] < mjMINVAL) {
|
||||||
// unconstrained minimum
|
// unconstrained minimum
|
||||||
force[i] -= res[0]*ARinv[i];
|
force[i] -= res[0]*ARinv[i];
|
||||||
|
|
||||||
// clamp
|
// clamp
|
||||||
if (force[i]<0) {
|
if (force[i] < 0) {
|
||||||
force[i] = 0;
|
force[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,17 +391,17 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
denom = mju_dot(v, v1, dim);
|
denom = mju_dot(v, v1, dim);
|
||||||
|
|
||||||
// avoid division by 0
|
// avoid division by 0
|
||||||
if (denom>=mjMINVAL) {
|
if (denom >= mjMINVAL) {
|
||||||
// x = v' * res / denom
|
// x = v' * res / denom
|
||||||
x = -mju_dot(v, res, dim) / denom;
|
x = -mju_dot(v, res, dim) / denom;
|
||||||
|
|
||||||
// make sure normal is non-negative
|
// make sure normal is non-negative
|
||||||
if (force[i]+x*v[0]<0) {
|
if (force[i]+x*v[0] < 0) {
|
||||||
x = -v[0]/force[i];
|
x = -v[0]/force[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// add x*v to f
|
// add x*v to f
|
||||||
for (int j=0; j<dim; j++) {
|
for (int j=0; j < dim; j++) {
|
||||||
force[i+j] += x*v[j];
|
force[i+j] += x*v[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -411,14 +411,14 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
|
|
||||||
// Ac = AR-submatrix; bc = b-subvector + Ac,rest * f_rest
|
// Ac = AR-submatrix; bc = b-subvector + Ac,rest * f_rest
|
||||||
mju_copy(bc, res+1, dim-1);
|
mju_copy(bc, res+1, dim-1);
|
||||||
for (int j=0; j<dim-1; j++) {
|
for (int j=0; j < dim-1; j++) {
|
||||||
mju_copy(Ac+j*(dim-1), Athis+(j+1)*dim+1, dim-1);
|
mju_copy(Ac+j*(dim-1), Athis+(j+1)*dim+1, dim-1);
|
||||||
bc[j] -= mju_dot(Ac+j*(dim-1), oldforce+1, dim-1);
|
bc[j] -= mju_dot(Ac+j*(dim-1), oldforce+1, dim-1);
|
||||||
bc[j] += Athis[(j+1)*dim]*(force[i]-oldforce[0]);
|
bc[j] += Athis[(j+1)*dim]*(force[i]-oldforce[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// guard for f_normal==0
|
// guard for f_normal==0
|
||||||
if (force[i]<mjMINVAL) {
|
if (force[i] < mjMINVAL) {
|
||||||
mju_zero(force+i+1, dim-1);
|
mju_zero(force+i+1, dim-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,9 +427,9 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
int flg_active;
|
int flg_active;
|
||||||
|
|
||||||
// solve
|
// solve
|
||||||
if (dim==3) {
|
if (dim == 3) {
|
||||||
flg_active = mju_QCQP2(v, Ac, bc, mu, force[i]);
|
flg_active = mju_QCQP2(v, Ac, bc, mu, force[i]);
|
||||||
} else if (dim==4) {
|
} else if (dim == 4) {
|
||||||
flg_active = mju_QCQP3(v, Ac, bc, mu, force[i]);
|
flg_active = mju_QCQP3(v, Ac, bc, mu, force[i]);
|
||||||
} else {
|
} else {
|
||||||
flg_active = mju_QCQP(v, Ac, bc, mu, force[i], dim-1);
|
flg_active = mju_QCQP(v, Ac, bc, mu, force[i], dim-1);
|
||||||
@@ -438,11 +438,11 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
// on constraint: put v on ellipsoid, in case QCQP is approximate
|
// on constraint: put v on ellipsoid, in case QCQP is approximate
|
||||||
if (flg_active) {
|
if (flg_active) {
|
||||||
mjtNum s = 0;
|
mjtNum s = 0;
|
||||||
for (int j=0; j<dim-1; j++) {
|
for (int j=0; j < dim-1; j++) {
|
||||||
s += v[j]*v[j] / (mu[j]*mu[j]);
|
s += v[j]*v[j] / (mu[j]*mu[j]);
|
||||||
}
|
}
|
||||||
s = mju_sqrt(force[i]*force[i] / mju_max(mjMINVAL, s));
|
s = mju_sqrt(force[i]*force[i] / mju_max(mjMINVAL, s));
|
||||||
for (int j=0; j<dim-1; j++) {
|
for (int j=0; j < dim-1; j++) {
|
||||||
v[j] *= s;
|
v[j] *= s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -453,7 +453,7 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// accumulate improvement
|
// accumulate improvement
|
||||||
if (dim==1) {
|
if (dim == 1) {
|
||||||
Athis[0] = 1/ARinv[i];
|
Athis[0] = 1/ARinv[i];
|
||||||
}
|
}
|
||||||
improvement -= costChange(Athis, force+i, oldforce, res, dim);
|
improvement -= costChange(Athis, force+i, oldforce, res, dim);
|
||||||
@@ -466,8 +466,8 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
memcpy(oldstate, d->efc_state, nefc*sizeof(int));
|
memcpy(oldstate, d->efc_state, nefc*sizeof(int));
|
||||||
int nactive = dualState(m, d);
|
int nactive = dualState(m, d);
|
||||||
int nchange = 0;
|
int nchange = 0;
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
nchange += (oldstate[i]!=d->efc_state[i]);
|
nchange += (oldstate[i] != d->efc_state[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale improvement, save stats, count
|
// scale improvement, save stats, count
|
||||||
@@ -475,7 +475,7 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
saveStats(m, d, &iter, improvement, 0, 0, nactive, nchange, 0, 0);
|
saveStats(m, d, &iter, improvement, 0, 0, nactive, nchange, 0, 0);
|
||||||
|
|
||||||
// terminate
|
// terminate
|
||||||
if (improvement<m->opt.tolerance) {
|
if (improvement < m->opt.tolerance) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,7 +486,7 @@ void mj_solPGS(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
// set nnz
|
// set nnz
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
d->solver_nnz = 0;
|
d->solver_nnz = 0;
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
d->solver_nnz += d->efc_AR_rownnz[i];
|
d->solver_nnz += d->efc_AR_rownnz[i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -521,19 +521,19 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
dualState(m, d);
|
dualState(m, d);
|
||||||
|
|
||||||
// main iteration
|
// main iteration
|
||||||
while (iter<maxiter) {
|
while (iter < maxiter) {
|
||||||
// clear improvement
|
// clear improvement
|
||||||
improvement = 0;
|
improvement = 0;
|
||||||
|
|
||||||
// correct for cost change at iter 0
|
// correct for cost change at iter 0
|
||||||
if (iter==0) {
|
if (iter == 0) {
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
improvement += 0.5*force[i]*force[i]*d->efc_R[i];
|
improvement += 0.5*force[i]*force[i]*d->efc_R[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform one sweep: dry friction
|
// perform one sweep: dry friction
|
||||||
for (int i=ne; i<ne+nf; i++) {
|
for (int i=ne; i < ne+nf; i++) {
|
||||||
// compute residual, save old
|
// compute residual, save old
|
||||||
residual(m, d, res, i, 1, 1);
|
residual(m, d, res, i, 1, 1);
|
||||||
oldforce[0] = force[i];
|
oldforce[0] = force[i];
|
||||||
@@ -542,9 +542,9 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
force[i] -= res[0]*ARinv[i];
|
force[i] -= res[0]*ARinv[i];
|
||||||
|
|
||||||
// impose interval constraints
|
// impose interval constraints
|
||||||
if (force[i]<-floss[i]) {
|
if (force[i] < -floss[i]) {
|
||||||
force[i] = -floss[i];
|
force[i] = -floss[i];
|
||||||
} else if (force[i]>floss[i]) {
|
} else if (force[i] > floss[i]) {
|
||||||
force[i] = floss[i];
|
force[i] = floss[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,16 +554,16 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perform one sweep: contact friction
|
// perform one sweep: contact friction
|
||||||
for (int i=ne+nf; i<nefc; i++) {
|
for (int i=ne+nf; i < nefc; i++) {
|
||||||
// pyramidal contact
|
// pyramidal contact
|
||||||
if (d->efc_type[i]==mjCNSTR_CONTACT_PYRAMIDAL) {
|
if (d->efc_type[i] == mjCNSTR_CONTACT_PYRAMIDAL) {
|
||||||
// get contact info
|
// get contact info
|
||||||
con = d->contact + d->efc_id[i];
|
con = d->contact + d->efc_id[i];
|
||||||
dim = con->dim;
|
dim = con->dim;
|
||||||
mu = con->friction;
|
mu = con->friction;
|
||||||
|
|
||||||
// loop over pairs of opposing pyramid edges
|
// loop over pairs of opposing pyramid edges
|
||||||
for (int j=i; j<i+2*(dim-1); j+=2) {
|
for (int j=i; j < i+2*(dim-1); j+=2) {
|
||||||
// compute residual, save old
|
// compute residual, save old
|
||||||
residual(m, d, res, j, 2, 1);
|
residual(m, d, res, j, 2, 1);
|
||||||
mju_copy(oldforce, force+j, 2);
|
mju_copy(oldforce, force+j, 2);
|
||||||
@@ -573,7 +573,7 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
|
|
||||||
// bc = b-subvector + Ac,rest * f_rest
|
// bc = b-subvector + Ac,rest * f_rest
|
||||||
mju_copy(bc, res, 2);
|
mju_copy(bc, res, 2);
|
||||||
for (int k=0; k<2; k++) {
|
for (int k=0; k < 2; k++) {
|
||||||
bc[k] -= mju_dot(Ac+k*2, oldforce, 2);
|
bc[k] -= mju_dot(Ac+k*2, oldforce, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,7 +586,7 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
K0 = mid*(Ac[0] - Ac[3]) + bc[0] - bc[1];
|
K0 = mid*(Ac[0] - Ac[3]) + bc[0] - bc[1];
|
||||||
|
|
||||||
// guard against Ac==0
|
// guard against Ac==0
|
||||||
if (K1<mjMINVAL) {
|
if (K1 < mjMINVAL) {
|
||||||
force[j] = force[j+1] = mid;
|
force[j] = force[j+1] = mid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,10 +596,10 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
y = -K0/K1;
|
y = -K0/K1;
|
||||||
|
|
||||||
// clamp and assign
|
// clamp and assign
|
||||||
if (y<-mid) {
|
if (y < -mid) {
|
||||||
force[j] = 0;
|
force[j] = 0;
|
||||||
force[j+1] = 2*mid;
|
force[j+1] = 2*mid;
|
||||||
} else if (y>mid) {
|
} else if (y > mid) {
|
||||||
force[j] = 2*mid;
|
force[j] = 2*mid;
|
||||||
force[j+1] = 0;
|
force[j+1] = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -617,7 +617,7 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// elliptic contact
|
// elliptic contact
|
||||||
else if (d->efc_type[i]==mjCNSTR_CONTACT_ELLIPTIC) {
|
else if (d->efc_type[i] == mjCNSTR_CONTACT_ELLIPTIC) {
|
||||||
// get contact info
|
// get contact info
|
||||||
con = d->contact + d->efc_id[i];
|
con = d->contact + d->efc_id[i];
|
||||||
dim = con->dim;
|
dim = con->dim;
|
||||||
@@ -632,12 +632,12 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
|
|
||||||
// bc = b-subvector + Ac,rest * f_rest
|
// bc = b-subvector + Ac,rest * f_rest
|
||||||
mju_copy(bc, res, dim-1);
|
mju_copy(bc, res, dim-1);
|
||||||
for (int j=0; j<dim-1; j++) {
|
for (int j=0; j < dim-1; j++) {
|
||||||
bc[j] -= mju_dot(Ac+j*(dim-1), oldforce, dim-1);
|
bc[j] -= mju_dot(Ac+j*(dim-1), oldforce, dim-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// guard for f_normal==0
|
// guard for f_normal==0
|
||||||
if (force[i]<mjMINVAL) {
|
if (force[i] < mjMINVAL) {
|
||||||
mju_zero(force+i+1, dim-1);
|
mju_zero(force+i+1, dim-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,9 +646,9 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
int flg_active = 0;
|
int flg_active = 0;
|
||||||
|
|
||||||
// solve
|
// solve
|
||||||
if (dim==3) {
|
if (dim == 3) {
|
||||||
flg_active = mju_QCQP2(v, Ac, bc, mu, force[i]);
|
flg_active = mju_QCQP2(v, Ac, bc, mu, force[i]);
|
||||||
} else if (dim==4) {
|
} else if (dim == 4) {
|
||||||
flg_active = mju_QCQP3(v, Ac, bc, mu, force[i]);
|
flg_active = mju_QCQP3(v, Ac, bc, mu, force[i]);
|
||||||
} else {
|
} else {
|
||||||
flg_active = mju_QCQP(v, Ac, bc, mu, force[i], dim-1);
|
flg_active = mju_QCQP(v, Ac, bc, mu, force[i], dim-1);
|
||||||
@@ -657,11 +657,11 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
// on constraint: put v on ellipsoid, in case QCQP is approximate
|
// on constraint: put v on ellipsoid, in case QCQP is approximate
|
||||||
if (flg_active) {
|
if (flg_active) {
|
||||||
mjtNum s = 0;
|
mjtNum s = 0;
|
||||||
for (int j=0; j<dim-1; j++) {
|
for (int j=0; j < dim-1; j++) {
|
||||||
s += v[j]*v[j]/(mu[j]*mu[j]);
|
s += v[j]*v[j]/(mu[j]*mu[j]);
|
||||||
}
|
}
|
||||||
s = mju_sqrt(force[i]*force[i] / mju_max(mjMINVAL, s));
|
s = mju_sqrt(force[i]*force[i] / mju_max(mjMINVAL, s));
|
||||||
for (int j=0; j<dim-1; j++) {
|
for (int j=0; j < dim-1; j++) {
|
||||||
v[j] *= s;
|
v[j] *= s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -682,8 +682,8 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
memcpy(oldstate, d->efc_state, nefc*sizeof(int));
|
memcpy(oldstate, d->efc_state, nefc*sizeof(int));
|
||||||
int nactive = dualState(m, d);
|
int nactive = dualState(m, d);
|
||||||
int nchange = 0;
|
int nchange = 0;
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
nchange += (oldstate[i]!=d->efc_state[i]);
|
nchange += (oldstate[i] != d->efc_state[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale improvement, save stats, count
|
// scale improvement, save stats, count
|
||||||
@@ -691,7 +691,7 @@ void mj_solNoSlip(const mjModel* m, mjData* d, int maxiter) {
|
|||||||
saveStats(m, d, &iter, improvement, 0, 0, nactive, nchange, 0, 0);
|
saveStats(m, d, &iter, improvement, 0, 0, nactive, nchange, 0, 0);
|
||||||
|
|
||||||
// terminate
|
// terminate
|
||||||
if (improvement<m->opt.noslip_tolerance) {
|
if (improvement < m->opt.noslip_tolerance) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -722,8 +722,8 @@ struct _mjCGContext {
|
|||||||
mjtNum* quad; // quadratic polynomials for constraint costs (nefc x 3)
|
mjtNum* quad; // quadratic polynomials for constraint costs (nefc x 3)
|
||||||
|
|
||||||
// Hessian (Newton only)
|
// Hessian (Newton only)
|
||||||
int flg_Newton; // 1: Newton, 0: CG (const)
|
int flg_Newton; // 1: Newton, 0: CG (const)
|
||||||
int nnz; // total number of non-zeros
|
int nnz; // total number of non-zeros
|
||||||
mjtNum* H; // Cholesky factorization of Hessian (nv x nv)
|
mjtNum* H; // Cholesky factorization of Hessian (nv x nv)
|
||||||
mjtNum* Hcone; // with cone contributions if present (nv x nv)
|
mjtNum* Hcone; // with cone contributions if present (nv x nv)
|
||||||
int* rownnz; // non-zeros in row (nv X 1)
|
int* rownnz; // non-zeros in row (nv X 1)
|
||||||
@@ -731,16 +731,16 @@ struct _mjCGContext {
|
|||||||
int* colind; // column indices (nv x nv)
|
int* colind; // column indices (nv x nv)
|
||||||
|
|
||||||
// globals
|
// globals
|
||||||
mjtNum cost; // constraint + Gauss cost
|
mjtNum cost; // constraint + Gauss cost
|
||||||
mjtNum quadGauss[3]; // quadratic polynomial for Gauss cost
|
mjtNum quadGauss[3]; // quadratic polynomial for Gauss cost
|
||||||
int nactive; // number of active constraints
|
int nactive; // number of active constraints
|
||||||
int ncone; // number of contacts in cone state
|
int ncone; // number of contacts in cone state
|
||||||
int nupdate; // number of Cholesky updates
|
int nupdate; // number of Cholesky updates
|
||||||
|
|
||||||
// linesearch diagnostics
|
// linesearch diagnostics
|
||||||
int LSiter; // number of linesearch iterations
|
int LSiter; // number of linesearch iterations
|
||||||
int LSresult; // linesearch result
|
int LSresult; // linesearch result
|
||||||
mjtNum LSslope; // linesearch slope at solution
|
mjtNum LSslope; // linesearch slope at solution
|
||||||
};
|
};
|
||||||
typedef struct _mjCGContext mjCGContext;
|
typedef struct _mjCGContext mjCGContext;
|
||||||
|
|
||||||
@@ -787,14 +787,14 @@ static void CGupdateConstraint(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
// count active and cone
|
// count active and cone
|
||||||
ctx->nactive = 0;
|
ctx->nactive = 0;
|
||||||
ctx->ncone = 0;
|
ctx->ncone = 0;
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
ctx->nactive += (d->efc_state[i]!=mjCNSTRSTATE_SATISFIED);
|
ctx->nactive += (d->efc_state[i] != mjCNSTRSTATE_SATISFIED);
|
||||||
ctx->ncone += (d->efc_state[i]==mjCNSTRSTATE_CONE);
|
ctx->ncone += (d->efc_state[i] == mjCNSTRSTATE_CONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add Gauss cost, set in quadratic[0]
|
// add Gauss cost, set in quadratic[0]
|
||||||
mjtNum Gauss = 0;
|
mjtNum Gauss = 0;
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
Gauss += 0.5*(ctx->Ma[i]-d->qfrc_smooth[i])*(d->qacc[i]-d->qacc_smooth[i]);
|
Gauss += 0.5*(ctx->Ma[i]-d->qfrc_smooth[i])*(d->qacc[i]-d->qacc_smooth[i]);
|
||||||
}
|
}
|
||||||
ctx->quadGauss[0] = Gauss;
|
ctx->quadGauss[0] = Gauss;
|
||||||
@@ -808,7 +808,7 @@ static void CGupdateGradient(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
int nv = m->nv;
|
int nv = m->nv;
|
||||||
|
|
||||||
// grad = M*qacc - qfrc_smooth - qfrc_constraint
|
// grad = M*qacc - qfrc_smooth - qfrc_constraint
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
ctx->grad[i] = ctx->Ma[i] - d->qfrc_smooth[i] - d->qfrc_constraint[i];
|
ctx->grad[i] = ctx->Ma[i] - d->qfrc_smooth[i] - d->qfrc_constraint[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -841,7 +841,7 @@ static void CGprepare(const mjModel* m, const mjData* d, mjCGContext* ctx) {
|
|||||||
ctx->quadGauss[2] = 0.5*mju_dot(v, ctx->Mv, nv);
|
ctx->quadGauss[2] = 0.5*mju_dot(v, ctx->Mv, nv);
|
||||||
|
|
||||||
// process constraints
|
// process constraints
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
// pointers to numeric data
|
// pointers to numeric data
|
||||||
mjtNum* Jv = ctx->Jv + i;
|
mjtNum* Jv = ctx->Jv + i;
|
||||||
mjtNum* Jaref = ctx->Jaref + i;
|
mjtNum* Jaref = ctx->Jaref + i;
|
||||||
@@ -857,7 +857,7 @@ static void CGprepare(const mjModel* m, const mjData* d, mjCGContext* ctx) {
|
|||||||
quad[2] = Jv[0]*D[0]*Jv[0];
|
quad[2] = Jv[0]*D[0]*Jv[0];
|
||||||
|
|
||||||
// elliptic cone: extra processing
|
// elliptic cone: extra processing
|
||||||
if (d->efc_type[i]==mjCNSTR_CONTACT_ELLIPTIC) {
|
if (d->efc_type[i] == mjCNSTR_CONTACT_ELLIPTIC) {
|
||||||
// extract contact info
|
// extract contact info
|
||||||
mjContact* con = d->contact + d->efc_id[i];
|
mjContact* con = d->contact + d->efc_id[i];
|
||||||
int dim = con->dim;
|
int dim = con->dim;
|
||||||
@@ -865,7 +865,7 @@ static void CGprepare(const mjModel* m, const mjData* d, mjCGContext* ctx) {
|
|||||||
mjtNum* friction = con->friction;
|
mjtNum* friction = con->friction;
|
||||||
|
|
||||||
// complete vector quadratic (for bottom zone)
|
// complete vector quadratic (for bottom zone)
|
||||||
for (int j=1; j<dim; j++) {
|
for (int j=1; j < dim; j++) {
|
||||||
mjtNum DJj = D[j]*Jaref[j];
|
mjtNum DJj = D[j]*Jaref[j];
|
||||||
quad[0] += Jaref[j]*DJj;
|
quad[0] += Jaref[j]*DJj;
|
||||||
quad[1] += Jv[j]*DJj;
|
quad[1] += Jv[j]*DJj;
|
||||||
@@ -875,13 +875,13 @@ static void CGprepare(const mjModel* m, const mjData* d, mjCGContext* ctx) {
|
|||||||
// rescale to make primal cone circular
|
// rescale to make primal cone circular
|
||||||
U[0] = Jaref[0]*mu;
|
U[0] = Jaref[0]*mu;
|
||||||
V[0] = Jv[0]*mu;
|
V[0] = Jv[0]*mu;
|
||||||
for (int j=1; j<dim; j++) {
|
for (int j=1; j < dim; j++) {
|
||||||
U[j] = Jaref[j]*friction[j-1];
|
U[j] = Jaref[j]*friction[j-1];
|
||||||
V[j] = Jv[j]*friction[j-1];
|
V[j] = Jv[j]*friction[j-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// accumulate sums of squares
|
// accumulate sums of squares
|
||||||
for (int j=1; j<dim; j++) {
|
for (int j=1; j < dim; j++) {
|
||||||
UU += U[j]*U[j];
|
UU += U[j]*U[j];
|
||||||
UV += U[j]*V[j];
|
UV += U[j]*V[j];
|
||||||
VV += V[j]*V[j];
|
VV += V[j]*V[j];
|
||||||
@@ -930,12 +930,12 @@ static void CGeval(const mjModel* m, mjData* d, mjCGContext* ctx, mjCGPnt* p) {
|
|||||||
mju_copy3(quadTotal, ctx->quadGauss);
|
mju_copy3(quadTotal, ctx->quadGauss);
|
||||||
|
|
||||||
// equality
|
// equality
|
||||||
for (int i=0; i<ne; i++) {
|
for (int i=0; i < ne; i++) {
|
||||||
mju_addTo3(quadTotal, ctx->quad+3*i);
|
mju_addTo3(quadTotal, ctx->quad+3*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// friction
|
// friction
|
||||||
for (int i=ne; i<ne+nf; i++) {
|
for (int i=ne; i < ne+nf; i++) {
|
||||||
// search point, friction loss, bound (Rf)
|
// search point, friction loss, bound (Rf)
|
||||||
mjtNum start = ctx->Jaref[i], dir = ctx->Jv[i];
|
mjtNum start = ctx->Jaref[i], dir = ctx->Jv[i];
|
||||||
mjtNum x = start + alpha*dir;
|
mjtNum x = start + alpha*dir;
|
||||||
@@ -943,12 +943,12 @@ static void CGeval(const mjModel* m, mjData* d, mjCGContext* ctx, mjCGPnt* p) {
|
|||||||
mjtNum Rf = d->efc_R[i]*f;
|
mjtNum Rf = d->efc_R[i]*f;
|
||||||
|
|
||||||
// -bound < x < bound : quadratic
|
// -bound < x < bound : quadratic
|
||||||
if (-Rf<x && x<Rf) {
|
if (-Rf < x && x < Rf) {
|
||||||
mju_addTo3(quadTotal, ctx->quad+3*i);
|
mju_addTo3(quadTotal, ctx->quad+3*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// x < -bound : linear negative
|
// x < -bound : linear negative
|
||||||
else if (x<=-Rf) {
|
else if (x <= -Rf) {
|
||||||
mjtNum qf[3] = {f*(-0.5*Rf-start), -f*dir, 0};
|
mjtNum qf[3] = {f*(-0.5*Rf-start), -f*dir, 0};
|
||||||
mju_addTo3(quadTotal, qf);
|
mju_addTo3(quadTotal, qf);
|
||||||
}
|
}
|
||||||
@@ -961,8 +961,8 @@ static void CGeval(const mjModel* m, mjData* d, mjCGContext* ctx, mjCGPnt* p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// limit and contact
|
// limit and contact
|
||||||
for (int i=ne+nf; i<nefc; i++) {
|
for (int i=ne+nf; i < nefc; i++) {
|
||||||
if (d->efc_type[i]==mjCNSTR_CONTACT_ELLIPTIC) { // elliptic cone
|
if (d->efc_type[i] == mjCNSTR_CONTACT_ELLIPTIC) { // elliptic cone
|
||||||
// extract contact info
|
// extract contact info
|
||||||
mjContact* con = d->contact + d->efc_id[i];
|
mjContact* con = d->contact + d->efc_id[i];
|
||||||
mjtNum* quad = ctx->quad + 3*i;
|
mjtNum* quad = ctx->quad + 3*i;
|
||||||
@@ -982,9 +982,9 @@ static void CGeval(const mjModel* m, mjData* d, mjCGContext* ctx, mjCGPnt* p) {
|
|||||||
mjtNum Tsqr = UU + alpha*(2*UV + alpha*VV);
|
mjtNum Tsqr = UU + alpha*(2*UV + alpha*VV);
|
||||||
|
|
||||||
// no tangential force : top or bottom zone
|
// no tangential force : top or bottom zone
|
||||||
if (Tsqr<=0) {
|
if (Tsqr <= 0) {
|
||||||
// bottom zone: quadratic cost
|
// bottom zone: quadratic cost
|
||||||
if (N<0) {
|
if (N < 0) {
|
||||||
mju_addTo3(quadTotal, quad);
|
mju_addTo3(quadTotal, quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -997,12 +997,12 @@ static void CGeval(const mjModel* m, mjData* d, mjCGContext* ctx, mjCGPnt* p) {
|
|||||||
mjtNum T = mju_sqrt(Tsqr);
|
mjtNum T = mju_sqrt(Tsqr);
|
||||||
|
|
||||||
// N>=mu*T : top zone
|
// N>=mu*T : top zone
|
||||||
if (N>=mu*T) {
|
if (N >= mu*T) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
// mu*N+T<=0 : bottom zone
|
// mu*N+T<=0 : bottom zone
|
||||||
else if (mu*N+T<=0) {
|
else if (mu*N+T <= 0) {
|
||||||
mju_addTo3(quadTotal, quad);
|
mju_addTo3(quadTotal, quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,7 +1027,7 @@ static void CGeval(const mjModel* m, mjData* d, mjCGContext* ctx, mjCGPnt* p) {
|
|||||||
mjtNum x = ctx->Jaref[i] + alpha*ctx->Jv[i];
|
mjtNum x = ctx->Jaref[i] + alpha*ctx->Jv[i];
|
||||||
|
|
||||||
// active
|
// active
|
||||||
if (x<0) {
|
if (x < 0) {
|
||||||
mju_addTo3(quadTotal, ctx->quad+3*i);
|
mju_addTo3(quadTotal, ctx->quad+3*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1039,7 +1039,7 @@ static void CGeval(const mjModel* m, mjData* d, mjCGContext* ctx, mjCGPnt* p) {
|
|||||||
deriv[1] += 2*quadTotal[2];
|
deriv[1] += 2*quadTotal[2];
|
||||||
|
|
||||||
// check for convexity; SHOULD NOT OCCUR
|
// check for convexity; SHOULD NOT OCCUR
|
||||||
if (deriv[1]<=0) {
|
if (deriv[1] <= 0) {
|
||||||
mju_warning("Linesearch objective is not convex");
|
mju_warning("Linesearch objective is not convex");
|
||||||
deriv[1] = mjMINVAL;
|
deriv[1] = mjMINVAL;
|
||||||
}
|
}
|
||||||
@@ -1057,15 +1057,17 @@ static void CGeval(const mjModel* m, mjData* d, mjCGContext* ctx, mjCGPnt* p) {
|
|||||||
static int updateBracket(const mjModel* m, mjData* d, mjCGContext* ctx,
|
static int updateBracket(const mjModel* m, mjData* d, mjCGContext* ctx,
|
||||||
mjCGPnt* p, mjCGPnt candidates[3], mjCGPnt* pnext) {
|
mjCGPnt* p, mjCGPnt candidates[3], mjCGPnt* pnext) {
|
||||||
int flag = 0;
|
int flag = 0;
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
// negative deriv
|
// negative deriv
|
||||||
if (p->deriv[0]<0 && candidates[i].deriv[0]<0 && p->deriv[0]<candidates[i].deriv[0]) {
|
if (p->deriv[0] < 0 && candidates[i].deriv[0] < 0 && p->deriv[0] < candidates[i].deriv[0]) {
|
||||||
*p = candidates[i];
|
*p = candidates[i];
|
||||||
flag = 1;
|
flag = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// positive deriv
|
// positive deriv
|
||||||
else if (p->deriv[0]>0 && candidates[i].deriv[0]>0 && p->deriv[0]>candidates[i].deriv[0]) {
|
else if (p->deriv[0] > 0 &&
|
||||||
|
candidates[i].deriv[0] > 0 &&
|
||||||
|
p->deriv[0] > candidates[i].deriv[0]) {
|
||||||
*p = candidates[i];
|
*p = candidates[i];
|
||||||
flag = 2;
|
flag = 2;
|
||||||
}
|
}
|
||||||
@@ -1096,7 +1098,7 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
|
|
||||||
// save search vector length, check
|
// save search vector length, check
|
||||||
mjtNum snorm = mju_norm(ctx->search, m->nv);
|
mjtNum snorm = mju_norm(ctx->search, m->nv);
|
||||||
if (snorm<mjMINVAL) {
|
if (snorm < mjMINVAL) {
|
||||||
ctx->LSresult = 1; // search vector too small
|
ctx->LSresult = 1; // search vector too small
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1119,13 +1121,13 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
// always attempt one Newton step
|
// always attempt one Newton step
|
||||||
p1.alpha = p0.alpha - p0.deriv[0]/p0.deriv[1];
|
p1.alpha = p0.alpha - p0.deriv[0]/p0.deriv[1];
|
||||||
CGeval(m, d, ctx, &p1);
|
CGeval(m, d, ctx, &p1);
|
||||||
if (p0.cost<p1.cost) {
|
if (p0.cost < p1.cost) {
|
||||||
p1 = p0;
|
p1 = p0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for initial convergence
|
// check for initial convergence
|
||||||
if (mju_abs(p1.deriv[0])<gtol) {
|
if (mju_abs(p1.deriv[0]) < gtol) {
|
||||||
if (p1.alpha==0) {
|
if (p1.alpha == 0) {
|
||||||
ctx->LSresult = 2; // no improvement, initial convergence
|
ctx->LSresult = 2; // no improvement, initial convergence
|
||||||
} else {
|
} else {
|
||||||
ctx->LSresult = 0; // SUCCESS
|
ctx->LSresult = 0; // SUCCESS
|
||||||
@@ -1135,32 +1137,32 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// save direction
|
// save direction
|
||||||
int dir = (p1.deriv[0]<0 ? +1 : -1);
|
int dir = (p1.deriv[0] < 0 ? +1 : -1);
|
||||||
|
|
||||||
// SANITY CHECKS
|
// SANITY CHECKS
|
||||||
/*
|
/*
|
||||||
// descent direction
|
// descent direction
|
||||||
if( mju_dot(ctx->grad, ctx->search, m->nv)>=0 )
|
if( mju_dot(ctx->grad, ctx->search, m->nv)>=0 )
|
||||||
printf("NOT A DESCENT: grad %g search %g dot %g\n",
|
printf("NOT A DESCENT: grad %g search %g dot %g\n",
|
||||||
mju_norm(ctx->grad, m->nv),
|
mju_norm(ctx->grad, m->nv),
|
||||||
mju_norm(ctx->search, m->nv),
|
mju_norm(ctx->search, m->nv),
|
||||||
mju_dot(ctx->grad, ctx->search, m->nv));
|
mju_dot(ctx->grad, ctx->search, m->nv));
|
||||||
|
|
||||||
// 2nd derivative for Newton cone
|
// 2nd derivative for Newton cone
|
||||||
if( ctx->flg_Newton && ctx->ncone )
|
if( ctx->flg_Newton && ctx->ncone )
|
||||||
{
|
{
|
||||||
mjtNum dd = -p0.deriv[0]/p0.deriv[1];
|
mjtNum dd = -p0.deriv[0]/p0.deriv[1];
|
||||||
|
|
||||||
if( mju_abs(dd-1)>1e-6 )
|
if( mju_abs(dd-1)>1e-6 )
|
||||||
printf("2nd DERIVATIVE FAIL: d0 %g d1 %g alpha %g\n",
|
printf("2nd DERIVATIVE FAIL: d0 %g d1 %g alpha %g\n",
|
||||||
p0.deriv[0], p0.deriv[1], dd);
|
p0.deriv[0], p0.deriv[1], dd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cost and gradient at 0: full-space vs. linesearch
|
// cost and gradient at 0: full-space vs. linesearch
|
||||||
mjtNum grd = mju_dot(ctx->grad, ctx->search, m->nv);
|
mjtNum grd = mju_dot(ctx->grad, ctx->search, m->nv);
|
||||||
if( mju_abs(p0.cost-ctx->cost)/mjMAX(mjMINVAL,mju_abs(p0.cost+ctx->cost)) > 1e-6 ||
|
if( mju_abs(p0.cost-ctx->cost)/mjMAX(mjMINVAL,mju_abs(p0.cost+ctx->cost)) > 1e-6 ||
|
||||||
mju_abs(p0.deriv[0]-grd)/mjMAX(mjMINVAL,mju_abs(p0.deriv[0]+grd)) > 1e-6 )
|
mju_abs(p0.deriv[0]-grd)/mjMAX(mjMINVAL,mju_abs(p0.deriv[0]+grd)) > 1e-6 )
|
||||||
{
|
{
|
||||||
printf("LSiter = %d:\n", ctx->LSiter);
|
printf("LSiter = %d:\n", ctx->LSiter);
|
||||||
printf("COST: %g %g %g\n",
|
printf("COST: %g %g %g\n",
|
||||||
p0.cost, ctx->cost,
|
p0.cost, ctx->cost,
|
||||||
@@ -1168,12 +1170,12 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
printf("GRAD: %g %g %g\n",
|
printf("GRAD: %g %g %g\n",
|
||||||
p0.deriv[0], grd,
|
p0.deriv[0], grd,
|
||||||
mju_abs(p0.deriv[0]-grd)/mjMAX(mjMINVAL,mju_abs(p0.deriv[0]+grd)));
|
mju_abs(p0.deriv[0]-grd)/mjMAX(mjMINVAL,mju_abs(p0.deriv[0]+grd)));
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// one-sided search
|
// one-sided search
|
||||||
int p2update = 0;
|
int p2update = 0;
|
||||||
while (p1.deriv[0]*dir<=-gtol && ctx->LSiter<LSmaxiter) {
|
while (p1.deriv[0]*dir <= -gtol && ctx->LSiter < LSmaxiter) {
|
||||||
// save current
|
// save current
|
||||||
p2 = p1;
|
p2 = p1;
|
||||||
p2update = 1;
|
p2update = 1;
|
||||||
@@ -1183,14 +1185,14 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
CGeval(m, d, ctx, &p1);
|
CGeval(m, d, ctx, &p1);
|
||||||
|
|
||||||
// check for convergence
|
// check for convergence
|
||||||
if (mju_abs(p1.deriv[0])<gtol) {
|
if (mju_abs(p1.deriv[0]) < gtol) {
|
||||||
ctx->LSslope = mju_abs(p1.deriv[0])*slopescl;
|
ctx->LSslope = mju_abs(p1.deriv[0])*slopescl;
|
||||||
return p1.alpha; // SUCCESS
|
return p1.alpha; // SUCCESS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for failure to bracket
|
// check for failure to bracket
|
||||||
if (ctx->LSiter>=LSmaxiter) {
|
if (ctx->LSiter >= LSmaxiter) {
|
||||||
ctx->LSresult = 3; // could not bracket
|
ctx->LSresult = 3; // could not bracket
|
||||||
ctx->LSslope = mju_abs(p1.deriv[0])*slopescl;
|
ctx->LSslope = mju_abs(p1.deriv[0])*slopescl;
|
||||||
return p1.alpha;
|
return p1.alpha;
|
||||||
@@ -1209,7 +1211,7 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
CGeval(m, d, ctx, &p1next);
|
CGeval(m, d, ctx, &p1next);
|
||||||
|
|
||||||
// bracketed search
|
// bracketed search
|
||||||
while (ctx->LSiter<LSmaxiter) {
|
while (ctx->LSiter < LSmaxiter) {
|
||||||
// evaluate at midpoint
|
// evaluate at midpoint
|
||||||
pmid.alpha = 0.5*(p1.alpha + p2.alpha);
|
pmid.alpha = 0.5*(p1.alpha + p2.alpha);
|
||||||
CGeval(m, d, ctx, &pmid);
|
CGeval(m, d, ctx, &pmid);
|
||||||
@@ -1220,14 +1222,14 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
// check candidates for convergence
|
// check candidates for convergence
|
||||||
mjtNum bestcost = 0;
|
mjtNum bestcost = 0;
|
||||||
int bestind = -1;
|
int bestind = -1;
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
if (mju_abs(candidates[i].deriv[0])<gtol &&
|
if (mju_abs(candidates[i].deriv[0]) < gtol &&
|
||||||
(bestind==-1 || candidates[i].cost<bestcost)) {
|
(bestind == -1 || candidates[i].cost < bestcost)) {
|
||||||
bestcost = candidates[i].cost;
|
bestcost = candidates[i].cost;
|
||||||
bestind = i;
|
bestind = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bestind>=0) {
|
if (bestind >= 0) {
|
||||||
ctx->LSslope = mju_abs(candidates[bestind].deriv[0])*slopescl;
|
ctx->LSslope = mju_abs(candidates[bestind].deriv[0])*slopescl;
|
||||||
return candidates[bestind].alpha; // SUCCESS
|
return candidates[bestind].alpha; // SUCCESS
|
||||||
}
|
}
|
||||||
@@ -1238,7 +1240,7 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
|
|
||||||
// no update possible: numerical accuracy reached, use midpoint
|
// no update possible: numerical accuracy reached, use midpoint
|
||||||
if (!b1 && !b2) {
|
if (!b1 && !b2) {
|
||||||
if (pmid.cost<p0.cost) {
|
if (pmid.cost < p0.cost) {
|
||||||
ctx->LSresult = 0; // SUCCESS
|
ctx->LSresult = 0; // SUCCESS
|
||||||
} else {
|
} else {
|
||||||
ctx->LSresult = 7; // no improvement, could not bracket
|
ctx->LSresult = 7; // no improvement, could not bracket
|
||||||
@@ -1250,11 +1252,11 @@ static mjtNum CGsearch(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// choose bracket with best cost
|
// choose bracket with best cost
|
||||||
if (p1.cost<=p2.cost && p1.cost<p0.cost) {
|
if (p1.cost <= p2.cost && p1.cost < p0.cost) {
|
||||||
ctx->LSresult = 4; // improvement but no convergence
|
ctx->LSresult = 4; // improvement but no convergence
|
||||||
ctx->LSslope = mju_abs(p1.deriv[0])*slopescl;
|
ctx->LSslope = mju_abs(p1.deriv[0])*slopescl;
|
||||||
return p1.alpha;
|
return p1.alpha;
|
||||||
} else if (p2.cost<=p1.cost && p2.cost<p0.cost) {
|
} else if (p2.cost <= p1.cost && p2.cost < p0.cost) {
|
||||||
ctx->LSresult = 4; // improvement but no convergence
|
ctx->LSresult = 4; // improvement but no convergence
|
||||||
ctx->LSslope = mju_abs(p2.deriv[0])*slopescl;
|
ctx->LSslope = mju_abs(p2.deriv[0])*slopescl;
|
||||||
return p2.alpha;
|
return p2.alpha;
|
||||||
@@ -1281,8 +1283,8 @@ static void HessianCone(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
mju_copy(ctx->Hcone, ctx->H, ctx->nnz);
|
mju_copy(ctx->Hcone, ctx->H, ctx->nnz);
|
||||||
|
|
||||||
// add contributions
|
// add contributions
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
if (d->efc_state[i]==mjCNSTRSTATE_CONE) {
|
if (d->efc_state[i] == mjCNSTRSTATE_CONE) {
|
||||||
mjContact* con = d->contact + d->efc_id[i];
|
mjContact* con = d->contact + d->efc_id[i];
|
||||||
int dim = con->dim;
|
int dim = con->dim;
|
||||||
|
|
||||||
@@ -1297,14 +1299,14 @@ static void HessianCone(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
|
|
||||||
// compute LTJ = L'*J for this contact
|
// compute LTJ = L'*J for this contact
|
||||||
mju_zero(LTJ, dim*nnz);
|
mju_zero(LTJ, dim*nnz);
|
||||||
for (int r=0; r<dim; r++) {
|
for (int r=0; r < dim; r++) {
|
||||||
for (int c=0; c<=r; c++) {
|
for (int c=0; c <= r; c++) {
|
||||||
mju_addToScl(LTJ+c*nnz, d->efc_J+d->efc_J_rowadr[i+r], local[r*dim+c], nnz);
|
mju_addToScl(LTJ+c*nnz, d->efc_J+d->efc_J_rowadr[i+r], local[r*dim+c], nnz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
for (int r=0; r<dim; r++) {
|
for (int r=0; r < dim; r++) {
|
||||||
// copy data for this row
|
// copy data for this row
|
||||||
mju_copy(LTJ_row, LTJ+r*nnz, nnz);
|
mju_copy(LTJ_row, LTJ+r*nnz, nnz);
|
||||||
memcpy(LTJ_ind, d->efc_J_colind+d->efc_J_rowadr[i+r], nnz*sizeof(int));
|
memcpy(LTJ_ind, d->efc_J_colind+d->efc_J_rowadr[i+r], nnz*sizeof(int));
|
||||||
@@ -1320,14 +1322,14 @@ static void HessianCone(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
else {
|
else {
|
||||||
// compute LTJ = L'*J for this contact row
|
// compute LTJ = L'*J for this contact row
|
||||||
mju_zero(LTJ, dim*nv);
|
mju_zero(LTJ, dim*nv);
|
||||||
for (int r=0; r<dim; r++) {
|
for (int r=0; r < dim; r++) {
|
||||||
for (int c=0; c<=r; c++) {
|
for (int c=0; c <= r; c++) {
|
||||||
mju_addToScl(LTJ+c*nv, d->efc_J+(i+r)*nv, local[r*dim+c], nv);
|
mju_addToScl(LTJ+c*nv, d->efc_J+(i+r)*nv, local[r*dim+c], nv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
for (int r=0; r<dim; r++) {
|
for (int r=0; r < dim; r++) {
|
||||||
mju_cholUpdate(ctx->Hcone, LTJ+r*nv, nv, 1);
|
mju_cholUpdate(ctx->Hcone, LTJ+r*nv, nv, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1352,8 +1354,8 @@ static void HessianDirect(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
|
|
||||||
// compute D corresponding to quad states
|
// compute D corresponding to quad states
|
||||||
mjtNum* D = mj_stackAlloc(d, nefc);
|
mjtNum* D = mj_stackAlloc(d, nefc);
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
if (d->efc_state[i]==mjCNSTRSTATE_QUADRATIC) {
|
if (d->efc_state[i] == mjCNSTRSTATE_QUADRATIC) {
|
||||||
D[i] = d->efc_D[i];
|
D[i] = d->efc_D[i];
|
||||||
} else {
|
} else {
|
||||||
D[i] = 0;
|
D[i] = 0;
|
||||||
@@ -1381,7 +1383,7 @@ static void HessianDirect(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
d);
|
d);
|
||||||
|
|
||||||
// rank-defficient, SHOULD NOT OCCUR
|
// rank-defficient, SHOULD NOT OCCUR
|
||||||
if (rank!=nv) {
|
if (rank != nv) {
|
||||||
mju_error("Rank-defficient Hessian in HessianDirect");
|
mju_error("Rank-defficient Hessian in HessianDirect");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1390,7 +1392,7 @@ static void HessianDirect(const mjModel* m, mjData* d, mjCGContext* ctx) {
|
|||||||
|
|
||||||
// count nnz
|
// count nnz
|
||||||
ctx->nnz = 0;
|
ctx->nnz = 0;
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
ctx->nnz += ctx->rownnz[i];
|
ctx->nnz += ctx->rownnz[i];
|
||||||
}
|
}
|
||||||
if (ctx->nnz > nv*nv) { // SHOULD NOT OCCUR
|
if (ctx->nnz > nv*nv) { // SHOULD NOT OCCUR
|
||||||
@@ -1438,21 +1440,21 @@ static void HessianIncremental(const mjModel* m, mjData* d,
|
|||||||
ctx->nupdate = 0;
|
ctx->nupdate = 0;
|
||||||
|
|
||||||
// update H factorization
|
// update H factorization
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
int flag_update = -1;
|
int flag_update = -1;
|
||||||
|
|
||||||
// add quad
|
// add quad
|
||||||
if (oldstate[i]!=mjCNSTRSTATE_QUADRATIC && d->efc_state[i]==mjCNSTRSTATE_QUADRATIC) {
|
if (oldstate[i] != mjCNSTRSTATE_QUADRATIC && d->efc_state[i] == mjCNSTRSTATE_QUADRATIC) {
|
||||||
flag_update = 1;
|
flag_update = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// subtract quad
|
// subtract quad
|
||||||
else if (oldstate[i]==mjCNSTRSTATE_QUADRATIC && d->efc_state[i]!=mjCNSTRSTATE_QUADRATIC) {
|
else if (oldstate[i] == mjCNSTRSTATE_QUADRATIC && d->efc_state[i] != mjCNSTRSTATE_QUADRATIC) {
|
||||||
flag_update = 0;
|
flag_update = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform update if flagged
|
// perform update if flagged
|
||||||
if (flag_update!=-1) {
|
if (flag_update != -1) {
|
||||||
// update with vec = J(i,:)*sqrt(D[i]))
|
// update with vec = J(i,:)*sqrt(D[i]))
|
||||||
if (mj_isSparse(m)) {
|
if (mj_isSparse(m)) {
|
||||||
// get nnz and adr of row i
|
// get nnz and adr of row i
|
||||||
@@ -1473,7 +1475,7 @@ static void HessianIncremental(const mjModel* m, mjData* d,
|
|||||||
ctx->nupdate++;
|
ctx->nupdate++;
|
||||||
|
|
||||||
// recompute H directly if accuracy lost
|
// recompute H directly if accuracy lost
|
||||||
if (rank<nv) {
|
if (rank < nv) {
|
||||||
mjFREESTACK;
|
mjFREESTACK;
|
||||||
HessianDirect(m, d, ctx);
|
HessianDirect(m, d, ctx);
|
||||||
|
|
||||||
@@ -1528,12 +1530,12 @@ static void mj_solCGNewton(const mjModel* m, mjData* d, int maxiter, int flg_New
|
|||||||
mju_scl(ctx.search, ctx.Mgrad, -1, nv);
|
mju_scl(ctx.search, ctx.Mgrad, -1, nv);
|
||||||
|
|
||||||
// main loop
|
// main loop
|
||||||
while (iter<maxiter) {
|
while (iter < maxiter) {
|
||||||
// perform linesearch
|
// perform linesearch
|
||||||
alpha = CGsearch(m, d, &ctx);
|
alpha = CGsearch(m, d, &ctx);
|
||||||
|
|
||||||
// no improvement: done
|
// no improvement: done
|
||||||
if (alpha==0) {
|
if (alpha == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1559,8 +1561,8 @@ static void mj_solCGNewton(const mjModel* m, mjData* d, int maxiter, int flg_New
|
|||||||
|
|
||||||
// count state changes
|
// count state changes
|
||||||
int nchange = 0;
|
int nchange = 0;
|
||||||
for (int i=0; i<nefc; i++) {
|
for (int i=0; i < nefc; i++) {
|
||||||
nchange += (d->efc_state[i]!=oldstate[i]);
|
nchange += (d->efc_state[i] != oldstate[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale improvement, save stats, count
|
// scale improvement, save stats, count
|
||||||
@@ -1570,7 +1572,7 @@ static void mj_solCGNewton(const mjModel* m, mjData* d, int maxiter, int flg_New
|
|||||||
ctx.nactive, nchange, ctx.LSiter, ctx.nupdate);
|
ctx.nactive, nchange, ctx.LSiter, ctx.nupdate);
|
||||||
|
|
||||||
// termination
|
// termination
|
||||||
if (improvement<m->opt.tolerance || gradient<m->opt.tolerance) {
|
if (improvement < m->opt.tolerance || gradient < m->opt.tolerance) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1584,12 +1586,12 @@ static void mj_solCGNewton(const mjModel* m, mjData* d, int maxiter, int flg_New
|
|||||||
mju_max(mjMINVAL, mju_dot(gradold, Mgradold, nv));
|
mju_max(mjMINVAL, mju_dot(gradold, Mgradold, nv));
|
||||||
|
|
||||||
// reset if negative
|
// reset if negative
|
||||||
if (beta<0) {
|
if (beta < 0) {
|
||||||
beta = 0;
|
beta = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
ctx.search[i] = -ctx.Mgrad[i] + beta*ctx.search[i];
|
ctx.search[i] = -ctx.Mgrad[i] + beta*ctx.search[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+221
-221
@@ -36,7 +36,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define mjVERSION 236
|
#define mjVERSION 236
|
||||||
#define mjVERSIONSTRING "2.3.6"
|
#define mjVERSIONSTRING "2.3.6"
|
||||||
|
|
||||||
// names of disable flags
|
// names of disable flags
|
||||||
@@ -120,7 +120,7 @@ void mj_jac(const mjModel* m, const mjData* d,
|
|||||||
da = m->body_dofadr[body] + m->body_dofnum[body] - 1;
|
da = m->body_dofadr[body] + m->body_dofnum[body] - 1;
|
||||||
|
|
||||||
// backward pass over dof ancestor chain
|
// backward pass over dof ancestor chain
|
||||||
while (da>=0) {
|
while (da >= 0) {
|
||||||
// construct rotation jacobian
|
// construct rotation jacobian
|
||||||
if (jacr) {
|
if (jacr) {
|
||||||
jacr[da] = cdof[6*da];
|
jacr[da] = cdof[6*da];
|
||||||
@@ -167,7 +167,7 @@ void mj_jacSubtreeCom(const mjModel* m, mjData* d, mjtNum* jacp, int body) {
|
|||||||
mju_zero(jacp, 3*nv);
|
mju_zero(jacp, 3*nv);
|
||||||
|
|
||||||
// forward pass starting from body
|
// forward pass starting from body
|
||||||
for (int b=body; b<m->nbody; b++) {
|
for (int b=body; b < m->nbody; b++) {
|
||||||
// end of body subtree, break from the loop
|
// end of body subtree, break from the loop
|
||||||
if (b > body && m->body_parentid[b] < body) {
|
if (b > body && m->body_parentid[b] < body) {
|
||||||
break;
|
break;
|
||||||
@@ -213,7 +213,7 @@ void mj_jacPointAxis(const mjModel* m, mjData* d, mjtNum* jacPoint, mjtNum* jacA
|
|||||||
|
|
||||||
// jacAxis_col = cross(jacr_col, axis)
|
// jacAxis_col = cross(jacr_col, axis)
|
||||||
if (jacAxis) {
|
if (jacAxis) {
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
jacAxis[ i] = jacr[ nv+i]*axis[2] - jacr[2*nv+i]*axis[1];
|
jacAxis[ i] = jacr[ nv+i]*axis[2] - jacr[2*nv+i]*axis[1];
|
||||||
jacAxis[ nv+i] = jacr[2*nv+i]*axis[0] - jacr[ i]*axis[2];
|
jacAxis[ nv+i] = jacr[2*nv+i]*axis[0] - jacr[ i]*axis[2];
|
||||||
jacAxis[2*nv+i] = jacr[ i]*axis[1] - jacr[ nv+i]*axis[0];
|
jacAxis[2*nv+i] = jacr[ i]*axis[1] - jacr[ nv+i]*axis[0];
|
||||||
@@ -260,14 +260,14 @@ void mj_jacSparse(const mjModel* m, const mjData* d,
|
|||||||
ci = NV-1;
|
ci = NV-1;
|
||||||
|
|
||||||
// backward pass over dof ancestor chain
|
// backward pass over dof ancestor chain
|
||||||
while (da>=0) {
|
while (da >= 0) {
|
||||||
// find chain index for this dof
|
// find chain index for this dof
|
||||||
while (ci>=0 && chain[ci]>da) {
|
while (ci >= 0 && chain[ci] > da) {
|
||||||
ci--;
|
ci--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we found it; SHOULD NOT OCCUR
|
// make sure we found it; SHOULD NOT OCCUR
|
||||||
if (chain[ci]!=da) {
|
if (chain[ci] != da) {
|
||||||
mju_error("dof index %d not found in chain", da);
|
mju_error("dof index %d not found in chain", da);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ void mj_jacSparseSimple(const mjModel* m, const mjData* d,
|
|||||||
// process dofs
|
// process dofs
|
||||||
int ci = start;
|
int ci = start;
|
||||||
int end = m->body_dofadr[body] + m->body_dofnum[body];
|
int end = m->body_dofadr[body] + m->body_dofnum[body];
|
||||||
for (int da=m->body_dofadr[body]; da<end; da++) {
|
for (int da=m->body_dofadr[body]; da < end; da++) {
|
||||||
// construct rotation jacobian
|
// construct rotation jacobian
|
||||||
if (jacdifr) {
|
if (jacdifr) {
|
||||||
// plus sign
|
// plus sign
|
||||||
@@ -389,11 +389,11 @@ int mj_jacDifPair(const mjModel* m, const mjData* d, int* chain,
|
|||||||
if (issimple) {
|
if (issimple) {
|
||||||
// first body
|
// first body
|
||||||
mj_jacSparseSimple(m, d, jacdifp, jacdifr, pos1, b1, 0, NV,
|
mj_jacSparseSimple(m, d, jacdifp, jacdifr, pos1, b1, 0, NV,
|
||||||
b1<b2 ? 0 : m->body_dofnum[b2]);
|
b1 < b2 ? 0 : m->body_dofnum[b2]);
|
||||||
|
|
||||||
// second body
|
// second body
|
||||||
mj_jacSparseSimple(m, d, jacdifp, jacdifr, pos2, b2, 1, NV,
|
mj_jacSparseSimple(m, d, jacdifp, jacdifr, pos2, b2, 1, NV,
|
||||||
b2<b1 ? 0 : m->body_dofnum[b1]);
|
b2 < b1 ? 0 : m->body_dofnum[b1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// regular processing
|
// regular processing
|
||||||
@@ -442,186 +442,186 @@ static int _getnumadr(const mjModel* m, mjtObj type, int** padr, int* mapadr) {
|
|||||||
|
|
||||||
// get address list and size for object type
|
// get address list and size for object type
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case mjOBJ_BODY:
|
case mjOBJ_BODY:
|
||||||
case mjOBJ_XBODY:
|
case mjOBJ_XBODY:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nbody;
|
*mapadr -= mjLOAD_MULTIPLE*m->nbody;
|
||||||
*padr = m->name_bodyadr;
|
*padr = m->name_bodyadr;
|
||||||
num = m->nbody;
|
num = m->nbody;
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_JOINT:
|
case mjOBJ_JOINT:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->njnt;
|
*mapadr -= mjLOAD_MULTIPLE*m->njnt;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_jntadr;
|
*padr = m->name_jntadr;
|
||||||
num = m->njnt;
|
num = m->njnt;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_GEOM:
|
case mjOBJ_GEOM:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->ngeom;
|
*mapadr -= mjLOAD_MULTIPLE*m->ngeom;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_geomadr;
|
*padr = m->name_geomadr;
|
||||||
num = m->ngeom;
|
num = m->ngeom;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_SITE:
|
case mjOBJ_SITE:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nsite;
|
*mapadr -= mjLOAD_MULTIPLE*m->nsite;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_siteadr;
|
*padr = m->name_siteadr;
|
||||||
num = m->nsite;
|
num = m->nsite;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_CAMERA:
|
case mjOBJ_CAMERA:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->ncam;
|
*mapadr -= mjLOAD_MULTIPLE*m->ncam;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_camadr;
|
*padr = m->name_camadr;
|
||||||
num = m->ncam;
|
num = m->ncam;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_LIGHT:
|
case mjOBJ_LIGHT:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nlight;
|
*mapadr -= mjLOAD_MULTIPLE*m->nlight;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_lightadr;
|
*padr = m->name_lightadr;
|
||||||
num = m->nlight;
|
num = m->nlight;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_MESH:
|
case mjOBJ_MESH:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nmesh;
|
*mapadr -= mjLOAD_MULTIPLE*m->nmesh;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_meshadr;
|
*padr = m->name_meshadr;
|
||||||
num = m->nmesh;
|
num = m->nmesh;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_SKIN:
|
case mjOBJ_SKIN:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nskin;
|
*mapadr -= mjLOAD_MULTIPLE*m->nskin;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_skinadr;
|
*padr = m->name_skinadr;
|
||||||
num = m->nskin;
|
num = m->nskin;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_HFIELD:
|
case mjOBJ_HFIELD:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nhfield;
|
*mapadr -= mjLOAD_MULTIPLE*m->nhfield;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_hfieldadr;
|
*padr = m->name_hfieldadr;
|
||||||
num = m->nhfield;
|
num = m->nhfield;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_TEXTURE:
|
case mjOBJ_TEXTURE:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->ntex;
|
*mapadr -= mjLOAD_MULTIPLE*m->ntex;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_texadr;
|
*padr = m->name_texadr;
|
||||||
num = m->ntex;
|
num = m->ntex;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_MATERIAL:
|
case mjOBJ_MATERIAL:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nmat;
|
*mapadr -= mjLOAD_MULTIPLE*m->nmat;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_matadr;
|
*padr = m->name_matadr;
|
||||||
num = m->nmat;
|
num = m->nmat;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_PAIR:
|
case mjOBJ_PAIR:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->npair;
|
*mapadr -= mjLOAD_MULTIPLE*m->npair;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_pairadr;
|
*padr = m->name_pairadr;
|
||||||
num = m->npair;
|
num = m->npair;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_EXCLUDE:
|
case mjOBJ_EXCLUDE:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nexclude;
|
*mapadr -= mjLOAD_MULTIPLE*m->nexclude;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_excludeadr;
|
*padr = m->name_excludeadr;
|
||||||
num = m->nexclude;
|
num = m->nexclude;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_EQUALITY:
|
case mjOBJ_EQUALITY:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->neq;
|
*mapadr -= mjLOAD_MULTIPLE*m->neq;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_eqadr;
|
*padr = m->name_eqadr;
|
||||||
num = m->neq;
|
num = m->neq;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_TENDON:
|
case mjOBJ_TENDON:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->ntendon;
|
*mapadr -= mjLOAD_MULTIPLE*m->ntendon;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_tendonadr;
|
*padr = m->name_tendonadr;
|
||||||
num = m->ntendon;
|
num = m->ntendon;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_ACTUATOR:
|
case mjOBJ_ACTUATOR:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nu;
|
*mapadr -= mjLOAD_MULTIPLE*m->nu;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_actuatoradr;
|
*padr = m->name_actuatoradr;
|
||||||
num = m->nu;
|
num = m->nu;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_SENSOR:
|
case mjOBJ_SENSOR:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nsensor;
|
*mapadr -= mjLOAD_MULTIPLE*m->nsensor;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_sensoradr;
|
*padr = m->name_sensoradr;
|
||||||
num = m->nsensor;
|
num = m->nsensor;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_NUMERIC:
|
case mjOBJ_NUMERIC:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nnumeric;
|
*mapadr -= mjLOAD_MULTIPLE*m->nnumeric;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_numericadr;
|
*padr = m->name_numericadr;
|
||||||
num = m->nnumeric;
|
num = m->nnumeric;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_TEXT:
|
case mjOBJ_TEXT:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->ntext;
|
*mapadr -= mjLOAD_MULTIPLE*m->ntext;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_textadr;
|
*padr = m->name_textadr;
|
||||||
num = m->ntext;
|
num = m->ntext;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_TUPLE:
|
case mjOBJ_TUPLE:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->ntuple;
|
*mapadr -= mjLOAD_MULTIPLE*m->ntuple;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_tupleadr;
|
*padr = m->name_tupleadr;
|
||||||
num = m->ntuple;
|
num = m->ntuple;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_KEY:
|
case mjOBJ_KEY:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nkey;
|
*mapadr -= mjLOAD_MULTIPLE*m->nkey;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_keyadr;
|
*padr = m->name_keyadr;
|
||||||
num = m->nkey;
|
num = m->nkey;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
case mjOBJ_PLUGIN:
|
case mjOBJ_PLUGIN:
|
||||||
*mapadr -= mjLOAD_MULTIPLE*m->nplugin;
|
*mapadr -= mjLOAD_MULTIPLE*m->nplugin;
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = m->name_pluginadr;
|
*padr = m->name_pluginadr;
|
||||||
num = m->nplugin;
|
num = m->nplugin;
|
||||||
}
|
}
|
||||||
mjFALLTHROUGH;
|
mjFALLTHROUGH;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
*padr = 0;
|
*padr = 0;
|
||||||
num = 0;
|
num = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return num;
|
return num;
|
||||||
@@ -653,15 +653,15 @@ int mj_name2id(const mjModel* m, int type, const char* name) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
int j = m->names_map[mapadr + i];
|
int j = m->names_map[mapadr + i];
|
||||||
if (j<0) {
|
if (j < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp(name, m->names+adr[j], m->nnames-adr[j])) {
|
if (!strncmp(name, m->names+adr[j], m->nnames-adr[j])) {
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
if ((++i)==num) i = 0;
|
if ((++i) == num)i = 0;
|
||||||
} while (i!=hash);
|
} while (i != hash);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -678,7 +678,7 @@ const char* mj_id2name(const mjModel* m, int type, int id) {
|
|||||||
int num = _getnumadr(m, type, &adr, &mapadr);
|
int num = _getnumadr(m, type, &adr, &mapadr);
|
||||||
|
|
||||||
// id is in [0, num) and the found name is not the empty string "\0"
|
// id is in [0, num) and the found name is not the empty string "\0"
|
||||||
if (id>=0 && id<num && m->names[adr[id]]) {
|
if (id >= 0 && id < num && m->names[adr[id]]) {
|
||||||
return m->names+adr[id];
|
return m->names+adr[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,9 +694,9 @@ void mj_fullM(const mjModel* m, mjtNum* dst, const mjtNum* M) {
|
|||||||
int adr = 0, nv = m->nv;
|
int adr = 0, nv = m->nv;
|
||||||
mju_zero(dst, nv*nv);
|
mju_zero(dst, nv*nv);
|
||||||
|
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
int j = i;
|
int j = i;
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
dst[i*nv+j] = M[adr];
|
dst[i*nv+j] = M[adr];
|
||||||
dst[j*nv+i] = M[adr];
|
dst[j*nv+i] = M[adr];
|
||||||
j = m->dof_parentid[j];
|
j = m->dof_parentid[j];
|
||||||
@@ -715,10 +715,10 @@ void mj_mulM(const mjModel* m, const mjData* d, mjtNum* res, const mjtNum* vec)
|
|||||||
|
|
||||||
mju_zero(res, nv);
|
mju_zero(res, nv);
|
||||||
|
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
#ifdef mjUSEAVX
|
#ifdef mjUSEAVX
|
||||||
// simple: diagonal division, AVX
|
// simple: diagonal division, AVX
|
||||||
if (m->dof_simplenum[i]>=4) {
|
if (m->dof_simplenum[i] >= 4) {
|
||||||
// init
|
// init
|
||||||
__m256d result, val1, val2;
|
__m256d result, val1, val2;
|
||||||
|
|
||||||
@@ -753,7 +753,7 @@ void mj_mulM(const mjModel* m, const mjData* d, mjtNum* res, const mjtNum* vec)
|
|||||||
// off-diagonal
|
// off-diagonal
|
||||||
int j = m->dof_parentid[i];
|
int j = m->dof_parentid[i];
|
||||||
adr++;
|
adr++;
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
res[i] += M[adr]*vec[j];
|
res[i] += M[adr]*vec[j];
|
||||||
res[j] += M[adr]*vec[i];
|
res[j] += M[adr]*vec[i];
|
||||||
|
|
||||||
@@ -776,10 +776,10 @@ void mj_mulM2(const mjModel* m, const mjData* d, mjtNum* res, const mjtNum* vec)
|
|||||||
|
|
||||||
mju_zero(res, nv);
|
mju_zero(res, nv);
|
||||||
|
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
#ifdef mjUSEAVX
|
#ifdef mjUSEAVX
|
||||||
// simple: diagonal division, AVX
|
// simple: diagonal division, AVX
|
||||||
if (m->dof_simplenum[i]>=4) {
|
if (m->dof_simplenum[i] >= 4) {
|
||||||
// init
|
// init
|
||||||
__m256d result, val1, val2;
|
__m256d result, val1, val2;
|
||||||
|
|
||||||
@@ -814,7 +814,7 @@ void mj_mulM2(const mjModel* m, const mjData* d, mjtNum* res, const mjtNum* vec)
|
|||||||
// off-diagonal
|
// off-diagonal
|
||||||
int j = m->dof_parentid[i];
|
int j = m->dof_parentid[i];
|
||||||
adr++;
|
adr++;
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
res[i] += qLD[adr]*vec[j];
|
res[i] += qLD[adr]*vec[j];
|
||||||
|
|
||||||
// advance to next element
|
// advance to next element
|
||||||
@@ -837,7 +837,7 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
if (rownnz && rowadr && colind) {
|
if (rownnz && rowadr && colind) {
|
||||||
// special processing of simple dofs
|
// special processing of simple dofs
|
||||||
int simplecnt = 0;
|
int simplecnt = 0;
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
if (m->dof_simplenum[i]) {
|
if (m->dof_simplenum[i]) {
|
||||||
// count simple
|
// count simple
|
||||||
simplecnt++;
|
simplecnt++;
|
||||||
@@ -854,8 +854,8 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
// find dof in row, add
|
// find dof in row, add
|
||||||
adr = rowadr[i];
|
adr = rowadr[i];
|
||||||
int end = adr + rownnz[i];
|
int end = adr + rownnz[i];
|
||||||
while (adr<end)
|
while (adr < end)
|
||||||
if (colind[adr]==i) {
|
if (colind[adr] == i) {
|
||||||
dst[adr] += d->qM[m->dof_Madr[i]];
|
dst[adr] += d->qM[m->dof_Madr[i]];
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -863,7 +863,7 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// not found: error
|
// not found: error
|
||||||
if (adr>=end) {
|
if (adr >= end) {
|
||||||
mju_error("mj_addM sparse: dst row expected to be empty");
|
mju_error("mj_addM sparse: dst row expected to be empty");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -871,7 +871,7 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// done if all simple
|
// done if all simple
|
||||||
if (simplecnt==nv) {
|
if (simplecnt == nv) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -885,13 +885,13 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
mjtNum* sparse_buf = mj_stackAlloc(d, nv);
|
mjtNum* sparse_buf = mj_stackAlloc(d, nv);
|
||||||
|
|
||||||
// convert M into sparse format, lower-triangular
|
// convert M into sparse format, lower-triangular
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
if (!m->dof_simplenum[i]) {
|
if (!m->dof_simplenum[i]) {
|
||||||
// backward pass over dofs: construct M_row(i) in reverse order
|
// backward pass over dofs: construct M_row(i) in reverse order
|
||||||
adr = m->dof_Madr[i];
|
adr = m->dof_Madr[i];
|
||||||
int j = i;
|
int j = i;
|
||||||
adr1 = 0;
|
adr1 = 0;
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
// assign
|
// assign
|
||||||
M[i*nv+adr1] = d->qM[adr];
|
M[i*nv+adr1] = d->qM[adr];
|
||||||
M_colind[i*nv+adr1] = j;
|
M_colind[i*nv+adr1] = j;
|
||||||
@@ -909,7 +909,7 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
M_rowadr[i] = i*nv;
|
M_rowadr[i] = i*nv;
|
||||||
|
|
||||||
// reverse order
|
// reverse order
|
||||||
for (int k=0; k<adr1/2; k++) {
|
for (int k=0; k < adr1/2; k++) {
|
||||||
mjtNum tmp = M[i*nv+k];
|
mjtNum tmp = M[i*nv+k];
|
||||||
M[i*nv+k] = M[i*nv+adr1-1-k];
|
M[i*nv+k] = M[i*nv+adr1-1-k];
|
||||||
M[i*nv+adr1-1-k] = tmp;
|
M[i*nv+adr1-1-k] = tmp;
|
||||||
@@ -922,9 +922,9 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make symmetric
|
// make symmetric
|
||||||
for (int i=1; i<nv; i++) {
|
for (int i=1; i < nv; i++) {
|
||||||
if (!m->dof_simplenum[i]) {
|
if (!m->dof_simplenum[i]) {
|
||||||
for (int k=nv*i; k<nv*i+M_rownnz[i]-1; k++) {
|
for (int k=nv*i; k < nv*i+M_rownnz[i]-1; k++) {
|
||||||
// add to row given by column index
|
// add to row given by column index
|
||||||
adr1 = nv*M_colind[k] + M_rownnz[M_colind[k]]++;
|
adr1 = nv*M_colind[k] + M_rownnz[M_colind[k]]++;
|
||||||
M[adr1] = M[k];
|
M[adr1] = M[k];
|
||||||
@@ -934,7 +934,7 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add to destination
|
// add to destination
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
if (!m->dof_simplenum[i]) {
|
if (!m->dof_simplenum[i]) {
|
||||||
int new_nnz =
|
int new_nnz =
|
||||||
mju_combineSparse(dst + rowadr[i], M + M_rowadr[i], nv, 1, 1,
|
mju_combineSparse(dst + rowadr[i], M + M_rowadr[i], nv, 1, 1,
|
||||||
@@ -951,13 +951,13 @@ void mj_addM(const mjModel* m, mjData* d, mjtNum* dst,
|
|||||||
|
|
||||||
// dense
|
// dense
|
||||||
else {
|
else {
|
||||||
for (int i=0; i<nv; i++) {
|
for (int i=0; i < nv; i++) {
|
||||||
adr = m->dof_Madr[i];
|
adr = m->dof_Madr[i];
|
||||||
int j = i;
|
int j = i;
|
||||||
while (j>=0) {
|
while (j >= 0) {
|
||||||
// add
|
// add
|
||||||
dst[i*nv+j] += d->qM[adr];
|
dst[i*nv+j] += d->qM[adr];
|
||||||
if (j<i) {
|
if (j < i) {
|
||||||
dst[j*nv+i] += d->qM[adr];
|
dst[j*nv+i] += d->qM[adr];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1052,7 +1052,7 @@ void mj_applyFT(const mjModel* m, mjData* d,
|
|||||||
mjtNum* qforce = mj_stackAlloc(d, nv);
|
mjtNum* qforce = mj_stackAlloc(d, nv);
|
||||||
|
|
||||||
// make sure body is in range
|
// make sure body is in range
|
||||||
if (body<0 || body>=m->nbody) {
|
if (body < 0 || body >= m->nbody) {
|
||||||
mju_error("Invalid body %d in applyFT", body);
|
mju_error("Invalid body %d in applyFT", body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1076,7 +1076,7 @@ void mj_applyFT(const mjModel* m, mjData* d,
|
|||||||
|
|
||||||
// accumulate xfrc_applied in qfrc
|
// accumulate xfrc_applied in qfrc
|
||||||
void mj_xfrcAccumulate(const mjModel* m, mjData* d, mjtNum* qfrc) {
|
void mj_xfrcAccumulate(const mjModel* m, mjData* d, mjtNum* qfrc) {
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
if (!mju_isZero(d->xfrc_applied+6*i, 6)) {
|
if (!mju_isZero(d->xfrc_applied+6*i, 6)) {
|
||||||
mj_applyFT(m, d, d->xfrc_applied+6*i, d->xfrc_applied+6*i+3, d->xipos+3*i, i, qfrc);
|
mj_applyFT(m, d, d->xfrc_applied+6*i, d->xfrc_applied+6*i+3, d->xipos+3*i, i, qfrc);
|
||||||
}
|
}
|
||||||
@@ -1092,35 +1092,35 @@ void mj_objectVelocity(const mjModel* m, const mjData* d,
|
|||||||
const mjtNum *pos = 0, *rot = 0;
|
const mjtNum *pos = 0, *rot = 0;
|
||||||
|
|
||||||
// body-inertial
|
// body-inertial
|
||||||
if (objtype==mjOBJ_BODY) {
|
if (objtype == mjOBJ_BODY) {
|
||||||
bodyid = objid;
|
bodyid = objid;
|
||||||
pos = d->xipos+3*objid;
|
pos = d->xipos+3*objid;
|
||||||
rot = (flg_local ? d->ximat+9*objid : 0);
|
rot = (flg_local ? d->ximat+9*objid : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// body-regular
|
// body-regular
|
||||||
else if (objtype==mjOBJ_XBODY) {
|
else if (objtype == mjOBJ_XBODY) {
|
||||||
bodyid = objid;
|
bodyid = objid;
|
||||||
pos = d->xpos+3*objid;
|
pos = d->xpos+3*objid;
|
||||||
rot = (flg_local ? d->xmat+9*objid : 0);
|
rot = (flg_local ? d->xmat+9*objid : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// geom
|
// geom
|
||||||
else if (objtype==mjOBJ_GEOM) {
|
else if (objtype == mjOBJ_GEOM) {
|
||||||
bodyid = m->geom_bodyid[objid];
|
bodyid = m->geom_bodyid[objid];
|
||||||
pos = d->geom_xpos+3*objid;
|
pos = d->geom_xpos+3*objid;
|
||||||
rot = (flg_local ? d->geom_xmat+9*objid : 0);
|
rot = (flg_local ? d->geom_xmat+9*objid : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// site
|
// site
|
||||||
else if (objtype==mjOBJ_SITE) {
|
else if (objtype == mjOBJ_SITE) {
|
||||||
bodyid = m->site_bodyid[objid];
|
bodyid = m->site_bodyid[objid];
|
||||||
pos = d->site_xpos+3*objid;
|
pos = d->site_xpos+3*objid;
|
||||||
rot = (flg_local ? d->site_xmat+9*objid : 0);
|
rot = (flg_local ? d->site_xmat+9*objid : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
else if (objtype==mjOBJ_CAMERA) {
|
else if (objtype == mjOBJ_CAMERA) {
|
||||||
bodyid = m->cam_bodyid[objid];
|
bodyid = m->cam_bodyid[objid];
|
||||||
pos = d->cam_xpos+3*objid;
|
pos = d->cam_xpos+3*objid;
|
||||||
rot = (flg_local ? d->cam_xmat+9*objid : 0);
|
rot = (flg_local ? d->cam_xmat+9*objid : 0);
|
||||||
@@ -1145,35 +1145,35 @@ void mj_objectAcceleration(const mjModel* m, const mjData* d,
|
|||||||
mjtNum correction[3], vel[6];
|
mjtNum correction[3], vel[6];
|
||||||
|
|
||||||
// body-inertial
|
// body-inertial
|
||||||
if (objtype==mjOBJ_BODY) {
|
if (objtype == mjOBJ_BODY) {
|
||||||
bodyid = objid;
|
bodyid = objid;
|
||||||
pos = d->xipos+3*objid;
|
pos = d->xipos+3*objid;
|
||||||
rot = (flg_local ? d->ximat+9*objid : 0);
|
rot = (flg_local ? d->ximat+9*objid : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// body-regular
|
// body-regular
|
||||||
else if (objtype==mjOBJ_XBODY) {
|
else if (objtype == mjOBJ_XBODY) {
|
||||||
bodyid = objid;
|
bodyid = objid;
|
||||||
pos = d->xpos+3*objid;
|
pos = d->xpos+3*objid;
|
||||||
rot = (flg_local ? d->xmat+9*objid : 0);
|
rot = (flg_local ? d->xmat+9*objid : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// geom
|
// geom
|
||||||
else if (objtype==mjOBJ_GEOM) {
|
else if (objtype == mjOBJ_GEOM) {
|
||||||
bodyid = m->geom_bodyid[objid];
|
bodyid = m->geom_bodyid[objid];
|
||||||
pos = d->geom_xpos+3*objid;
|
pos = d->geom_xpos+3*objid;
|
||||||
rot = (flg_local ? d->geom_xmat+9*objid : 0);
|
rot = (flg_local ? d->geom_xmat+9*objid : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// site
|
// site
|
||||||
else if (objtype==mjOBJ_SITE) {
|
else if (objtype == mjOBJ_SITE) {
|
||||||
bodyid = m->site_bodyid[objid];
|
bodyid = m->site_bodyid[objid];
|
||||||
pos = d->site_xpos+3*objid;
|
pos = d->site_xpos+3*objid;
|
||||||
rot = (flg_local ? d->site_xmat+9*objid : 0);
|
rot = (flg_local ? d->site_xmat+9*objid : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
else if (objtype==mjOBJ_CAMERA) {
|
else if (objtype == mjOBJ_CAMERA) {
|
||||||
bodyid = m->cam_bodyid[objid];
|
bodyid = m->cam_bodyid[objid];
|
||||||
pos = d->cam_xpos+3*objid;
|
pos = d->cam_xpos+3*objid;
|
||||||
rot = (flg_local ? d->cam_xmat+9*objid : 0);
|
rot = (flg_local ? d->cam_xmat+9*objid : 0);
|
||||||
@@ -1207,7 +1207,7 @@ void mj_contactForce(const mjModel* m, const mjData* d, int id, mjtNum result[6]
|
|||||||
mju_zero(result, 6);
|
mju_zero(result, 6);
|
||||||
|
|
||||||
// make sure contact is valid
|
// make sure contact is valid
|
||||||
if (id>=0 && id<d->ncon && d->contact[id].efc_address>=0) {
|
if (id >= 0 && id < d->ncon && d->contact[id].efc_address >= 0) {
|
||||||
// get contact pointer
|
// get contact pointer
|
||||||
con = d->contact + id;
|
con = d->contact + id;
|
||||||
|
|
||||||
@@ -1225,14 +1225,14 @@ void mj_contactForce(const mjModel* m, const mjData* d, int id, mjtNum result[6]
|
|||||||
void mj_differentiatePos(const mjModel* m, mjtNum* qvel, mjtNum dt,
|
void mj_differentiatePos(const mjModel* m, mjtNum* qvel, mjtNum dt,
|
||||||
const mjtNum* qpos1, const mjtNum* qpos2) {
|
const mjtNum* qpos1, const mjtNum* qpos2) {
|
||||||
// loop over joints
|
// loop over joints
|
||||||
for (int j=0; j<m->njnt; j++) {
|
for (int j=0; j < m->njnt; j++) {
|
||||||
// get addresses in qpos and qvel
|
// get addresses in qpos and qvel
|
||||||
int padr = m->jnt_qposadr[j];
|
int padr = m->jnt_qposadr[j];
|
||||||
int vadr = m->jnt_dofadr[j];
|
int vadr = m->jnt_dofadr[j];
|
||||||
|
|
||||||
switch (m->jnt_type[j]) {
|
switch (m->jnt_type[j]) {
|
||||||
case mjJNT_FREE:
|
case mjJNT_FREE:
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
qvel[vadr+i] = (qpos2[padr+i] - qpos1[padr+i]) / dt;
|
qvel[vadr+i] = (qpos2[padr+i] - qpos1[padr+i]) / dt;
|
||||||
}
|
}
|
||||||
vadr += 3;
|
vadr += 3;
|
||||||
@@ -1259,7 +1259,7 @@ void mj_differentiatePos(const mjModel* m, mjtNum* qvel, mjtNum dt,
|
|||||||
// integrate qpos with given qvel
|
// integrate qpos with given qvel
|
||||||
void mj_integratePos(const mjModel* m, mjtNum* qpos, const mjtNum* qvel, mjtNum dt) {
|
void mj_integratePos(const mjModel* m, mjtNum* qpos, const mjtNum* qvel, mjtNum dt) {
|
||||||
// loop over joints
|
// loop over joints
|
||||||
for (int j=0; j<m->njnt; j++) {
|
for (int j=0; j < m->njnt; j++) {
|
||||||
// get addresses in qpos and qvel
|
// get addresses in qpos and qvel
|
||||||
int padr = m->jnt_qposadr[j];
|
int padr = m->jnt_qposadr[j];
|
||||||
int vadr = m->jnt_dofadr[j];
|
int vadr = m->jnt_dofadr[j];
|
||||||
@@ -1267,7 +1267,7 @@ void mj_integratePos(const mjModel* m, mjtNum* qpos, const mjtNum* qvel, mjtNum
|
|||||||
switch (m->jnt_type[j]) {
|
switch (m->jnt_type[j]) {
|
||||||
case mjJNT_FREE:
|
case mjJNT_FREE:
|
||||||
// position update
|
// position update
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
qpos[padr+i] += dt * qvel[vadr+i];
|
qpos[padr+i] += dt * qvel[vadr+i];
|
||||||
}
|
}
|
||||||
padr += 3;
|
padr += 3;
|
||||||
@@ -1294,9 +1294,9 @@ void mj_integratePos(const mjModel* m, mjtNum* qpos, const mjtNum* qvel, mjtNum
|
|||||||
// normalize all quaternions in qpos-type vector
|
// normalize all quaternions in qpos-type vector
|
||||||
void mj_normalizeQuat(const mjModel* m, mjtNum* qpos) {
|
void mj_normalizeQuat(const mjModel* m, mjtNum* qpos) {
|
||||||
// find quaternion fields and normalize
|
// find quaternion fields and normalize
|
||||||
for (int i=0; i<m->njnt; i++) {
|
for (int i=0; i < m->njnt; i++) {
|
||||||
if (m->jnt_type[i]==mjJNT_BALL || m->jnt_type[i]==mjJNT_FREE) {
|
if (m->jnt_type[i] == mjJNT_BALL || m->jnt_type[i] == mjJNT_FREE) {
|
||||||
mju_normalize4(qpos+m->jnt_qposadr[i]+3*(m->jnt_type[i]==mjJNT_FREE));
|
mju_normalize4(qpos+m->jnt_qposadr[i]+3*(m->jnt_type[i] == mjJNT_FREE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1312,13 +1312,13 @@ void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9],
|
|||||||
// position
|
// position
|
||||||
if (xpos && pos) {
|
if (xpos && pos) {
|
||||||
// compute
|
// compute
|
||||||
if (sameframe==0) {
|
if (sameframe == 0) {
|
||||||
mju_rotVecMat(xpos, pos, d->xmat+9*body);
|
mju_rotVecMat(xpos, pos, d->xmat+9*body);
|
||||||
mju_addTo3(xpos, d->xpos+3*body);
|
mju_addTo3(xpos, d->xpos+3*body);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy body position
|
// copy body position
|
||||||
else if (sameframe==1) {
|
else if (sameframe == 1) {
|
||||||
mju_copy3(xpos, d->xpos+3*body);
|
mju_copy3(xpos, d->xpos+3*body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1331,13 +1331,13 @@ void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9],
|
|||||||
// orientation
|
// orientation
|
||||||
if (xmat && quat) {
|
if (xmat && quat) {
|
||||||
// compute
|
// compute
|
||||||
if (sameframe==0) {
|
if (sameframe == 0) {
|
||||||
mju_mulQuat(tmp, d->xquat+4*body, quat);
|
mju_mulQuat(tmp, d->xquat+4*body, quat);
|
||||||
mju_quat2Mat(xmat, tmp);
|
mju_quat2Mat(xmat, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy body orientation
|
// copy body orientation
|
||||||
else if (sameframe==1) {
|
else if (sameframe == 1) {
|
||||||
mju_copy(xmat, d->xmat+9*body, 9);
|
mju_copy(xmat, d->xmat+9*body, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1354,7 +1354,7 @@ void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9],
|
|||||||
mjtNum mj_getTotalmass(const mjModel* m) {
|
mjtNum mj_getTotalmass(const mjModel* m) {
|
||||||
mjtNum res = 0;
|
mjtNum res = 0;
|
||||||
|
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
res += m->body_mass[i];
|
res += m->body_mass[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1369,7 +1369,7 @@ void mj_setTotalmass(mjModel* m, mjtNum newmass) {
|
|||||||
mjtNum scale = mjMAX(mjMINVAL, newmass / mjMAX(mjMINVAL, mj_getTotalmass(m)));
|
mjtNum scale = mjMAX(mjMINVAL, newmass / mjMAX(mjMINVAL, mj_getTotalmass(m)));
|
||||||
|
|
||||||
// scale all masses and inertias
|
// scale all masses and inertias
|
||||||
for (int i=1; i<m->nbody; i++) {
|
for (int i=1; i < m->nbody; i++) {
|
||||||
m->body_mass[i] *= scale;
|
m->body_mass[i] *= scale;
|
||||||
m->body_inertia[3*i] *= scale;
|
m->body_inertia[3*i] *= scale;
|
||||||
m->body_inertia[3*i+1] *= scale;
|
m->body_inertia[3*i+1] *= scale;
|
||||||
@@ -1385,7 +1385,7 @@ void mj_setTotalmass(mjModel* m, mjtNum newmass) {
|
|||||||
void mj_warning(mjData* d, int warning, int info) {
|
void mj_warning(mjData* d, int warning, int info) {
|
||||||
|
|
||||||
// check type
|
// check type
|
||||||
if (warning<0 || warning>=mjNWARNING) {
|
if (warning < 0 || warning >= mjNWARNING) {
|
||||||
mju_error("Invalid warning type %d", warning);
|
mju_error("Invalid warning type %d", warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ void mju_addScl3(mjtNum res[3], const mjtNum vec1[3], const mjtNum vec2[3], mjtN
|
|||||||
mjtNum mju_normalize3(mjtNum vec[3]) {
|
mjtNum mju_normalize3(mjtNum vec[3]) {
|
||||||
mjtNum norm = mju_sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
|
mjtNum norm = mju_sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
|
||||||
|
|
||||||
if (norm<mjMINVAL) {
|
if (norm < mjMINVAL) {
|
||||||
vec[0] = 1;
|
vec[0] = 1;
|
||||||
vec[1] = 0;
|
vec[1] = 0;
|
||||||
vec[2] = 0;
|
vec[2] = 0;
|
||||||
@@ -216,7 +216,7 @@ void mju_copy4(mjtNum res[4], const mjtNum data[4]) {
|
|||||||
mjtNum mju_normalize4(mjtNum vec[4]) {
|
mjtNum mju_normalize4(mjtNum vec[4]) {
|
||||||
mjtNum norm = mju_sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2] + vec[3]*vec[3]);
|
mjtNum norm = mju_sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2] + vec[3]*vec[3]);
|
||||||
|
|
||||||
if (norm<mjMINVAL) {
|
if (norm < mjMINVAL) {
|
||||||
vec[0] = 1;
|
vec[0] = 1;
|
||||||
vec[1] = 0;
|
vec[1] = 0;
|
||||||
vec[2] = 0;
|
vec[2] = 0;
|
||||||
@@ -238,7 +238,7 @@ mjtNum mju_normalize4(mjtNum vec[4]) {
|
|||||||
|
|
||||||
// res = 0
|
// res = 0
|
||||||
void mju_zero(mjtNum* res, int n) {
|
void mju_zero(mjtNum* res, int n) {
|
||||||
if (n>0) {
|
if (n > 0) {
|
||||||
memset(res, 0, n*sizeof(mjtNum));
|
memset(res, 0, n*sizeof(mjtNum));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +247,7 @@ void mju_zero(mjtNum* res, int n) {
|
|||||||
|
|
||||||
// res = val
|
// res = val
|
||||||
void mju_fill(mjtNum* res, mjtNum val, int n) {
|
void mju_fill(mjtNum* res, mjtNum val, int n) {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i] = val;
|
res[i] = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,7 +256,7 @@ void mju_fill(mjtNum* res, mjtNum val, int n) {
|
|||||||
|
|
||||||
// res = vec
|
// res = vec
|
||||||
void mju_copy(mjtNum* res, const mjtNum* vec, int n) {
|
void mju_copy(mjtNum* res, const mjtNum* vec, int n) {
|
||||||
if (n>0) {
|
if (n > 0) {
|
||||||
memcpy(res, vec, n*sizeof(mjtNum));
|
memcpy(res, vec, n*sizeof(mjtNum));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,7 +267,7 @@ void mju_copy(mjtNum* res, const mjtNum* vec, int n) {
|
|||||||
mjtNum mju_sum(const mjtNum* vec, int n) {
|
mjtNum mju_sum(const mjtNum* vec, int n) {
|
||||||
mjtNum res = 0;
|
mjtNum res = 0;
|
||||||
|
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res += vec[i];
|
res += vec[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +280,7 @@ mjtNum mju_sum(const mjtNum* vec, int n) {
|
|||||||
mjtNum mju_L1(const mjtNum* vec, int n) {
|
mjtNum mju_L1(const mjtNum* vec, int n) {
|
||||||
mjtNum res = 0;
|
mjtNum res = 0;
|
||||||
|
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res += mju_abs(vec[i]);
|
res += mju_abs(vec[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,14 +297,14 @@ void mju_scl(mjtNum* res, const mjtNum* vec, mjtNum scl, int n) {
|
|||||||
int n_4 = n - 4;
|
int n_4 = n - 4;
|
||||||
|
|
||||||
// vector part
|
// vector part
|
||||||
if (n_4>=0) {
|
if (n_4 >= 0) {
|
||||||
__m256d sclpar, val1, val1scl;
|
__m256d sclpar, val1, val1scl;
|
||||||
|
|
||||||
// init
|
// init
|
||||||
sclpar = _mm256_set1_pd(scl);
|
sclpar = _mm256_set1_pd(scl);
|
||||||
|
|
||||||
// parallel computation
|
// parallel computation
|
||||||
while (i<=n_4) {
|
while (i <= n_4) {
|
||||||
val1 = _mm256_loadu_pd(vec+i);
|
val1 = _mm256_loadu_pd(vec+i);
|
||||||
val1scl = _mm256_mul_pd(val1, sclpar);
|
val1scl = _mm256_mul_pd(val1, sclpar);
|
||||||
_mm256_storeu_pd(res+i, val1scl);
|
_mm256_storeu_pd(res+i, val1scl);
|
||||||
@@ -314,19 +314,19 @@ void mju_scl(mjtNum* res, const mjtNum* vec, mjtNum scl, int n) {
|
|||||||
|
|
||||||
// process remaining
|
// process remaining
|
||||||
int n_i = n - i;
|
int n_i = n - i;
|
||||||
if (n_i==3) {
|
if (n_i == 3) {
|
||||||
res[i] = vec[i]*scl;
|
res[i] = vec[i]*scl;
|
||||||
res[i+1] = vec[i+1]*scl;
|
res[i+1] = vec[i+1]*scl;
|
||||||
res[i+2] = vec[i+2]*scl;
|
res[i+2] = vec[i+2]*scl;
|
||||||
} else if (n_i==2) {
|
} else if (n_i == 2) {
|
||||||
res[i] = vec[i]*scl;
|
res[i] = vec[i]*scl;
|
||||||
res[i+1] = vec[i+1]*scl;
|
res[i+1] = vec[i+1]*scl;
|
||||||
} else if (n_i==1) {
|
} else if (n_i == 1) {
|
||||||
res[i] = vec[i]*scl;
|
res[i] = vec[i]*scl;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
for (; i<n; i++) {
|
for (; i < n; i++) {
|
||||||
res[i] = vec[i]*scl;
|
res[i] = vec[i]*scl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -342,11 +342,11 @@ void mju_add(mjtNum* res, const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
int n_4 = n - 4;
|
int n_4 = n - 4;
|
||||||
|
|
||||||
// vector part
|
// vector part
|
||||||
if (n_4>=0) {
|
if (n_4 >= 0) {
|
||||||
__m256d sum, val1, val2;
|
__m256d sum, val1, val2;
|
||||||
|
|
||||||
// parallel computation
|
// parallel computation
|
||||||
while (i<=n_4) {
|
while (i <= n_4) {
|
||||||
val1 = _mm256_loadu_pd(vec1+i);
|
val1 = _mm256_loadu_pd(vec1+i);
|
||||||
val2 = _mm256_loadu_pd(vec2+i);
|
val2 = _mm256_loadu_pd(vec2+i);
|
||||||
sum = _mm256_add_pd(val1, val2);
|
sum = _mm256_add_pd(val1, val2);
|
||||||
@@ -357,19 +357,19 @@ void mju_add(mjtNum* res, const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
|
|
||||||
// process remaining
|
// process remaining
|
||||||
int n_i = n - i;
|
int n_i = n - i;
|
||||||
if (n_i==3) {
|
if (n_i == 3) {
|
||||||
res[i] = vec1[i] + vec2[i];
|
res[i] = vec1[i] + vec2[i];
|
||||||
res[i+1] = vec1[i+1] + vec2[i+1];
|
res[i+1] = vec1[i+1] + vec2[i+1];
|
||||||
res[i+2] = vec1[i+2] + vec2[i+2];
|
res[i+2] = vec1[i+2] + vec2[i+2];
|
||||||
} else if (n_i==2) {
|
} else if (n_i == 2) {
|
||||||
res[i] = vec1[i] + vec2[i];
|
res[i] = vec1[i] + vec2[i];
|
||||||
res[i+1] = vec1[i+1] + vec2[i+1];
|
res[i+1] = vec1[i+1] + vec2[i+1];
|
||||||
} else if (n_i==1) {
|
} else if (n_i == 1) {
|
||||||
res[i] = vec1[i] + vec2[i];
|
res[i] = vec1[i] + vec2[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
for (; i<n; i++) {
|
for (; i < n; i++) {
|
||||||
res[i] = vec1[i] + vec2[i];
|
res[i] = vec1[i] + vec2[i];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -385,11 +385,11 @@ void mju_sub(mjtNum* res, const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
int n_4 = n - 4;
|
int n_4 = n - 4;
|
||||||
|
|
||||||
// vector part
|
// vector part
|
||||||
if (n_4>=0) {
|
if (n_4 >= 0) {
|
||||||
__m256d dif, val1, val2;
|
__m256d dif, val1, val2;
|
||||||
|
|
||||||
// parallel computation
|
// parallel computation
|
||||||
while (i<=n_4) {
|
while (i <= n_4) {
|
||||||
val1 = _mm256_loadu_pd(vec1+i);
|
val1 = _mm256_loadu_pd(vec1+i);
|
||||||
val2 = _mm256_loadu_pd(vec2+i);
|
val2 = _mm256_loadu_pd(vec2+i);
|
||||||
dif = _mm256_sub_pd(val1, val2);
|
dif = _mm256_sub_pd(val1, val2);
|
||||||
@@ -400,19 +400,19 @@ void mju_sub(mjtNum* res, const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
|
|
||||||
// process remaining
|
// process remaining
|
||||||
int n_i = n - i;
|
int n_i = n - i;
|
||||||
if (n_i==3) {
|
if (n_i == 3) {
|
||||||
res[i] = vec1[i] - vec2[i];
|
res[i] = vec1[i] - vec2[i];
|
||||||
res[i+1] = vec1[i+1] - vec2[i+1];
|
res[i+1] = vec1[i+1] - vec2[i+1];
|
||||||
res[i+2] = vec1[i+2] - vec2[i+2];
|
res[i+2] = vec1[i+2] - vec2[i+2];
|
||||||
} else if (n_i==2) {
|
} else if (n_i == 2) {
|
||||||
res[i] = vec1[i] - vec2[i];
|
res[i] = vec1[i] - vec2[i];
|
||||||
res[i+1] = vec1[i+1] - vec2[i+1];
|
res[i+1] = vec1[i+1] - vec2[i+1];
|
||||||
} else if (n_i==1) {
|
} else if (n_i == 1) {
|
||||||
res[i] = vec1[i] - vec2[i];
|
res[i] = vec1[i] - vec2[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
for (; i<n; i++) {
|
for (; i < n; i++) {
|
||||||
res[i] = vec1[i] - vec2[i];
|
res[i] = vec1[i] - vec2[i];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -428,11 +428,11 @@ void mju_addTo(mjtNum* res, const mjtNum* vec, int n) {
|
|||||||
int n_4 = n - 4;
|
int n_4 = n - 4;
|
||||||
|
|
||||||
// vector part
|
// vector part
|
||||||
if (n_4>=0) {
|
if (n_4 >= 0) {
|
||||||
__m256d sum, val1, val2;
|
__m256d sum, val1, val2;
|
||||||
|
|
||||||
// parallel computation
|
// parallel computation
|
||||||
while (i<=n_4) {
|
while (i <= n_4) {
|
||||||
val1 = _mm256_loadu_pd(res+i);
|
val1 = _mm256_loadu_pd(res+i);
|
||||||
val2 = _mm256_loadu_pd(vec+i);
|
val2 = _mm256_loadu_pd(vec+i);
|
||||||
sum = _mm256_add_pd(val1, val2);
|
sum = _mm256_add_pd(val1, val2);
|
||||||
@@ -443,19 +443,19 @@ void mju_addTo(mjtNum* res, const mjtNum* vec, int n) {
|
|||||||
|
|
||||||
// process remaining
|
// process remaining
|
||||||
int n_i = n - i;
|
int n_i = n - i;
|
||||||
if (n_i==3) {
|
if (n_i == 3) {
|
||||||
res[i] += vec[i];
|
res[i] += vec[i];
|
||||||
res[i+1] += vec[i+1];
|
res[i+1] += vec[i+1];
|
||||||
res[i+2] += vec[i+2];
|
res[i+2] += vec[i+2];
|
||||||
} else if (n_i==2) {
|
} else if (n_i == 2) {
|
||||||
res[i] += vec[i];
|
res[i] += vec[i];
|
||||||
res[i+1] += vec[i+1];
|
res[i+1] += vec[i+1];
|
||||||
} else if (n_i==1) {
|
} else if (n_i == 1) {
|
||||||
res[i] += vec[i];
|
res[i] += vec[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
for (; i<n; i++) {
|
for (; i < n; i++) {
|
||||||
res[i] += vec[i];
|
res[i] += vec[i];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -471,11 +471,11 @@ void mju_subFrom(mjtNum* res, const mjtNum* vec, int n) {
|
|||||||
int n_4 = n - 4;
|
int n_4 = n - 4;
|
||||||
|
|
||||||
// vector part
|
// vector part
|
||||||
if (n_4>=0) {
|
if (n_4 >= 0) {
|
||||||
__m256d dif, val1, val2;
|
__m256d dif, val1, val2;
|
||||||
|
|
||||||
// parallel computation
|
// parallel computation
|
||||||
while (i<=n_4) {
|
while (i <= n_4) {
|
||||||
val1 = _mm256_loadu_pd(res+i);
|
val1 = _mm256_loadu_pd(res+i);
|
||||||
val2 = _mm256_loadu_pd(vec+i);
|
val2 = _mm256_loadu_pd(vec+i);
|
||||||
dif = _mm256_sub_pd(val1, val2);
|
dif = _mm256_sub_pd(val1, val2);
|
||||||
@@ -486,19 +486,19 @@ void mju_subFrom(mjtNum* res, const mjtNum* vec, int n) {
|
|||||||
|
|
||||||
// process remaining
|
// process remaining
|
||||||
int n_i = n - i;
|
int n_i = n - i;
|
||||||
if (n_i==3) {
|
if (n_i == 3) {
|
||||||
res[i] -= vec[i];
|
res[i] -= vec[i];
|
||||||
res[i+1] -= vec[i+1];
|
res[i+1] -= vec[i+1];
|
||||||
res[i+2] -= vec[i+2];
|
res[i+2] -= vec[i+2];
|
||||||
} else if (n_i==2) {
|
} else if (n_i == 2) {
|
||||||
res[i] -= vec[i];
|
res[i] -= vec[i];
|
||||||
res[i+1] -= vec[i+1];
|
res[i+1] -= vec[i+1];
|
||||||
} else if (n_i==1) {
|
} else if (n_i == 1) {
|
||||||
res[i] -= vec[i];
|
res[i] -= vec[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
for (; i<n; i++) {
|
for (; i < n; i++) {
|
||||||
res[i] -= vec[i];
|
res[i] -= vec[i];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -514,14 +514,14 @@ void mju_addToScl(mjtNum* res, const mjtNum* vec, mjtNum scl, int n) {
|
|||||||
int n_4 = n - 4;
|
int n_4 = n - 4;
|
||||||
|
|
||||||
// vector part
|
// vector part
|
||||||
if (n_4>=0) {
|
if (n_4 >= 0) {
|
||||||
__m256d sclpar, sum, val1, val2, val2scl;
|
__m256d sclpar, sum, val1, val2, val2scl;
|
||||||
|
|
||||||
// init
|
// init
|
||||||
sclpar = _mm256_set1_pd(scl);
|
sclpar = _mm256_set1_pd(scl);
|
||||||
|
|
||||||
// parallel computation
|
// parallel computation
|
||||||
while (i<=n_4) {
|
while (i <= n_4) {
|
||||||
val1 = _mm256_loadu_pd(res+i);
|
val1 = _mm256_loadu_pd(res+i);
|
||||||
val2 = _mm256_loadu_pd(vec+i);
|
val2 = _mm256_loadu_pd(vec+i);
|
||||||
val2scl = _mm256_mul_pd(val2, sclpar);
|
val2scl = _mm256_mul_pd(val2, sclpar);
|
||||||
@@ -533,19 +533,19 @@ void mju_addToScl(mjtNum* res, const mjtNum* vec, mjtNum scl, int n) {
|
|||||||
|
|
||||||
// process remaining
|
// process remaining
|
||||||
int n_i = n - i;
|
int n_i = n - i;
|
||||||
if (n_i==3) {
|
if (n_i == 3) {
|
||||||
res[i] += vec[i]*scl;
|
res[i] += vec[i]*scl;
|
||||||
res[i+1] += vec[i+1]*scl;
|
res[i+1] += vec[i+1]*scl;
|
||||||
res[i+2] += vec[i+2]*scl;
|
res[i+2] += vec[i+2]*scl;
|
||||||
} else if (n_i==2) {
|
} else if (n_i == 2) {
|
||||||
res[i] += vec[i]*scl;
|
res[i] += vec[i]*scl;
|
||||||
res[i+1] += vec[i+1]*scl;
|
res[i+1] += vec[i+1]*scl;
|
||||||
} else if (n_i==1) {
|
} else if (n_i == 1) {
|
||||||
res[i] += vec[i]*scl;
|
res[i] += vec[i]*scl;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
for (; i<n; i++) {
|
for (; i < n; i++) {
|
||||||
res[i] += vec[i]*scl;
|
res[i] += vec[i]*scl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -559,14 +559,14 @@ void mju_addScl(mjtNum* res, const mjtNum* vec1, const mjtNum* vec2, mjtNum scl,
|
|||||||
int n_4 = n - 4;
|
int n_4 = n - 4;
|
||||||
|
|
||||||
// vector part
|
// vector part
|
||||||
if (n_4>=0) {
|
if (n_4 >= 0) {
|
||||||
__m256d sclpar, sum, val1, val2, val2scl;
|
__m256d sclpar, sum, val1, val2, val2scl;
|
||||||
|
|
||||||
// init
|
// init
|
||||||
sclpar = _mm256_set1_pd(scl);
|
sclpar = _mm256_set1_pd(scl);
|
||||||
|
|
||||||
// parallel computation
|
// parallel computation
|
||||||
while (i<=n_4) {
|
while (i <= n_4) {
|
||||||
val1 = _mm256_loadu_pd(vec1+i);
|
val1 = _mm256_loadu_pd(vec1+i);
|
||||||
val2 = _mm256_loadu_pd(vec2+i);
|
val2 = _mm256_loadu_pd(vec2+i);
|
||||||
val2scl = _mm256_mul_pd(val2, sclpar);
|
val2scl = _mm256_mul_pd(val2, sclpar);
|
||||||
@@ -578,19 +578,19 @@ void mju_addScl(mjtNum* res, const mjtNum* vec1, const mjtNum* vec2, mjtNum scl,
|
|||||||
|
|
||||||
// process remaining
|
// process remaining
|
||||||
int n_i = n - i;
|
int n_i = n - i;
|
||||||
if (n_i==3) {
|
if (n_i == 3) {
|
||||||
res[i] = vec1[i] + vec2[i]*scl;
|
res[i] = vec1[i] + vec2[i]*scl;
|
||||||
res[i+1] = vec1[i+1] + vec2[i+1]*scl;
|
res[i+1] = vec1[i+1] + vec2[i+1]*scl;
|
||||||
res[i+2] = vec1[i+2] + vec2[i+2]*scl;
|
res[i+2] = vec1[i+2] + vec2[i+2]*scl;
|
||||||
} else if (n_i==2) {
|
} else if (n_i == 2) {
|
||||||
res[i] = vec1[i] + vec2[i]*scl;
|
res[i] = vec1[i] + vec2[i]*scl;
|
||||||
res[i+1] = vec1[i+1] + vec2[i+1]*scl;
|
res[i+1] = vec1[i+1] + vec2[i+1]*scl;
|
||||||
} else if (n_i==1) {
|
} else if (n_i == 1) {
|
||||||
res[i] = vec1[i] + vec2[i]*scl;
|
res[i] = vec1[i] + vec2[i]*scl;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
for (; i<n; i++) {
|
for (; i < n; i++) {
|
||||||
res[i] = vec1[i] + vec2[i]*scl;
|
res[i] = vec1[i] + vec2[i]*scl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -603,14 +603,14 @@ mjtNum mju_normalize(mjtNum* res, int n) {
|
|||||||
mjtNum norm = (mjtNum)mju_sqrt(mju_dot(res, res, n));
|
mjtNum norm = (mjtNum)mju_sqrt(mju_dot(res, res, n));
|
||||||
mjtNum normInv;
|
mjtNum normInv;
|
||||||
|
|
||||||
if (norm<mjMINVAL) {
|
if (norm < mjMINVAL) {
|
||||||
res[0] = 1;
|
res[0] = 1;
|
||||||
for (int i=1; i<n; i++) {
|
for (int i=1; i < n; i++) {
|
||||||
res[i] = 0;
|
res[i] = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
normInv = 1/norm;
|
normInv = 1/norm;
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i] *= normInv;
|
res[i] *= normInv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -635,7 +635,7 @@ mjtNum mju_dot(const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
#ifdef mjUSEAVX
|
#ifdef mjUSEAVX
|
||||||
|
|
||||||
// vector part
|
// vector part
|
||||||
if (n_4>=0) {
|
if (n_4 >= 0) {
|
||||||
__m256d sum, prod, val1, val2;
|
__m256d sum, prod, val1, val2;
|
||||||
__m128d vlow, vhigh, high64;
|
__m128d vlow, vhigh, high64;
|
||||||
|
|
||||||
@@ -646,7 +646,7 @@ mjtNum mju_dot(const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
i = 4;
|
i = 4;
|
||||||
|
|
||||||
// parallel computation
|
// parallel computation
|
||||||
while (i<=n_4) {
|
while (i <= n_4) {
|
||||||
val1 = _mm256_loadu_pd(vec1+i);
|
val1 = _mm256_loadu_pd(vec1+i);
|
||||||
val2 = _mm256_loadu_pd(vec2+i);
|
val2 = _mm256_loadu_pd(vec2+i);
|
||||||
prod = _mm256_mul_pd(val1, val2);
|
prod = _mm256_mul_pd(val1, val2);
|
||||||
@@ -671,7 +671,7 @@ mjtNum mju_dot(const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
mjtNum res2 = 0;
|
mjtNum res2 = 0;
|
||||||
mjtNum res3 = 0;
|
mjtNum res3 = 0;
|
||||||
|
|
||||||
for (; i<=n_4; i+=4) {
|
for (; i <= n_4; i+=4) {
|
||||||
res0 += vec1[i] * vec2[i];
|
res0 += vec1[i] * vec2[i];
|
||||||
res1 += vec1[i+1] * vec2[i+1];
|
res1 += vec1[i+1] * vec2[i+1];
|
||||||
res2 += vec1[i+2] * vec2[i+2];
|
res2 += vec1[i+2] * vec2[i+2];
|
||||||
@@ -682,11 +682,11 @@ mjtNum mju_dot(const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
|
|
||||||
// process remaining
|
// process remaining
|
||||||
int n_i = n - i;
|
int n_i = n - i;
|
||||||
if (n_i==3) {
|
if (n_i == 3) {
|
||||||
res += vec1[i]*vec2[i] + vec1[i+1]*vec2[i+1] + vec1[i+2]*vec2[i+2];
|
res += vec1[i]*vec2[i] + vec1[i+1]*vec2[i+1] + vec1[i+2]*vec2[i+2];
|
||||||
} else if (n_i==2) {
|
} else if (n_i == 2) {
|
||||||
res += vec1[i]*vec2[i] + vec1[i+1]*vec2[i+1];
|
res += vec1[i]*vec2[i] + vec1[i+1]*vec2[i+1];
|
||||||
} else if (n_i==1) {
|
} else if (n_i == 1) {
|
||||||
res += vec1[i]*vec2[i];
|
res += vec1[i]*vec2[i];
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@@ -696,7 +696,7 @@ mjtNum mju_dot(const mjtNum* vec1, const mjtNum* vec2, int n) {
|
|||||||
|
|
||||||
// multiply matrix and vector
|
// multiply matrix and vector
|
||||||
void mju_mulMatVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int nr, int nc) {
|
void mju_mulMatVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int nr, int nc) {
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
res[r] = mju_dot(mat + r*nc, vec, nc);
|
res[r] = mju_dot(mat + r*nc, vec, nc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -708,7 +708,7 @@ void mju_mulMatTVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int nr, i
|
|||||||
mjtNum tmp;
|
mjtNum tmp;
|
||||||
mju_zero(res, nc);
|
mju_zero(res, nc);
|
||||||
|
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
if ((tmp = vec[r])) {
|
if ((tmp = vec[r])) {
|
||||||
mju_addToScl(res, mat+r*nc, tmp, nc);
|
mju_addToScl(res, mat+r*nc, tmp, nc);
|
||||||
}
|
}
|
||||||
@@ -720,7 +720,7 @@ void mju_mulMatTVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int nr, i
|
|||||||
// multiply square matrix with vectors on both sides: return vec1'*mat*vec2
|
// multiply square matrix with vectors on both sides: return vec1'*mat*vec2
|
||||||
mjtNum mju_mulVecMatVec(const mjtNum* vec1, const mjtNum* mat, const mjtNum* vec2, int n) {
|
mjtNum mju_mulVecMatVec(const mjtNum* vec1, const mjtNum* mat, const mjtNum* vec2, int n) {
|
||||||
mjtNum res = 0;
|
mjtNum res = 0;
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res += vec1[i] * mju_dot(mat + i*n, vec2, n);
|
res += vec1[i] * mju_dot(mat + i*n, vec2, n);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@@ -732,8 +732,8 @@ mjtNum mju_mulVecMatVec(const mjtNum* vec1, const mjtNum* mat, const mjtNum* vec
|
|||||||
|
|
||||||
// transpose matrix
|
// transpose matrix
|
||||||
void mju_transpose(mjtNum* res, const mjtNum* mat, int nr, int nc) {
|
void mju_transpose(mjtNum* res, const mjtNum* mat, int nr, int nc) {
|
||||||
for (int i=0; i<nr; i++) {
|
for (int i=0; i < nr; i++) {
|
||||||
for (int j=0; j<nc; j++) {
|
for (int j=0; j < nc; j++) {
|
||||||
res[j*nr+i] = mat[i*nc+j];
|
res[j*nr+i] = mat[i*nc+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -743,9 +743,9 @@ void mju_transpose(mjtNum* res, const mjtNum* mat, int nr, int nc) {
|
|||||||
|
|
||||||
// symmetrize square matrix res = (mat + mat')/2
|
// symmetrize square matrix res = (mat + mat')/2
|
||||||
void mju_symmetrize(mjtNum* res, const mjtNum* mat, int n) {
|
void mju_symmetrize(mjtNum* res, const mjtNum* mat, int n) {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i*(n+1)] = mat[i*(n+1)];
|
res[i*(n+1)] = mat[i*(n+1)];
|
||||||
for (int j=0; j<i; j++) {
|
for (int j=0; j < i; j++) {
|
||||||
res[i*n+j] = res[j*n+i] = 0.5 * (mat[i*n+j] + mat[j*n+i]);
|
res[i*n+j] = res[j*n+i] = 0.5 * (mat[i*n+j] + mat[j*n+i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -756,7 +756,7 @@ void mju_symmetrize(mjtNum* res, const mjtNum* mat, int n) {
|
|||||||
// identity matrix
|
// identity matrix
|
||||||
void mju_eye(mjtNum* mat, int n) {
|
void mju_eye(mjtNum* mat, int n) {
|
||||||
mju_zero(mat, n*n);
|
mju_zero(mat, n*n);
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
mat[i*(n + 1)] = 1;
|
mat[i*(n + 1)] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -772,8 +772,8 @@ void mju_mulMatMat(mjtNum* res, const mjtNum* mat1, const mjtNum* mat2,
|
|||||||
|
|
||||||
mju_zero(res, r1*c2);
|
mju_zero(res, r1*c2);
|
||||||
|
|
||||||
for (int i=0; i<r1; i++) {
|
for (int i=0; i < r1; i++) {
|
||||||
for (int k=0; k<c1; k++) {
|
for (int k=0; k < c1; k++) {
|
||||||
if ((tmp = mat1[i*c1+k])) {
|
if ((tmp = mat1[i*c1+k])) {
|
||||||
mju_addToScl(res+i*c2, mat2+k*c2, tmp, c2);
|
mju_addToScl(res+i*c2, mat2+k*c2, tmp, c2);
|
||||||
}
|
}
|
||||||
@@ -786,8 +786,8 @@ void mju_mulMatMat(mjtNum* res, const mjtNum* mat1, const mjtNum* mat2,
|
|||||||
// multiply matrices, second argument transposed
|
// multiply matrices, second argument transposed
|
||||||
void mju_mulMatMatT(mjtNum* res, const mjtNum* mat1, const mjtNum* mat2,
|
void mju_mulMatMatT(mjtNum* res, const mjtNum* mat1, const mjtNum* mat2,
|
||||||
int r1, int c1, int r2) {
|
int r1, int c1, int r2) {
|
||||||
for (int i=0; i<r1; i++) {
|
for (int i=0; i < r1; i++) {
|
||||||
for (int j=0; j<r2; j++) {
|
for (int j=0; j < r2; j++) {
|
||||||
res[i*r2+j] = mju_dot(mat1+i*c1, mat2+j*c1, c1);
|
res[i*r2+j] = mju_dot(mat1+i*c1, mat2+j*c1, c1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -802,9 +802,9 @@ void mju_sqrMatTD(mjtNum* res, const mjtNum* mat, const mjtNum* diag, int nr, in
|
|||||||
// half of MatMat routine: only lower triangle
|
// half of MatMat routine: only lower triangle
|
||||||
mju_zero(res, nc*nc);
|
mju_zero(res, nc*nc);
|
||||||
if (diag) {
|
if (diag) {
|
||||||
for (int j=0; j<nr; j++) {
|
for (int j=0; j < nr; j++) {
|
||||||
if (diag[j]) {
|
if (diag[j]) {
|
||||||
for (int i=0; i<nc; i++) {
|
for (int i=0; i < nc; i++) {
|
||||||
if ((tmp = mat[j*nc+i])) {
|
if ((tmp = mat[j*nc+i])) {
|
||||||
mju_addToScl(res+i*nc, mat+j*nc, tmp*diag[j], i+1);
|
mju_addToScl(res+i*nc, mat+j*nc, tmp*diag[j], i+1);
|
||||||
}
|
}
|
||||||
@@ -812,8 +812,8 @@ void mju_sqrMatTD(mjtNum* res, const mjtNum* mat, const mjtNum* diag, int nr, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<nc; i++) {
|
for (int i=0; i < nc; i++) {
|
||||||
for (int j=0; j<nr; j++) {
|
for (int j=0; j < nr; j++) {
|
||||||
if ((tmp = mat[j*nc+i])) {
|
if ((tmp = mat[j*nc+i])) {
|
||||||
mju_addToScl(res+i*nc, mat+j*nc, tmp, i+1);
|
mju_addToScl(res+i*nc, mat+j*nc, tmp, i+1);
|
||||||
}
|
}
|
||||||
@@ -822,8 +822,8 @@ void mju_sqrMatTD(mjtNum* res, const mjtNum* mat, const mjtNum* diag, int nr, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make symmetric
|
// make symmetric
|
||||||
for (int i=0; i<nc; i++) {
|
for (int i=0; i < nc; i++) {
|
||||||
for (int j=i+1; j<nc; j++) {
|
for (int j=i+1; j < nc; j++) {
|
||||||
res[i*nc+j] = res[j*nc+i];
|
res[i*nc+j] = res[j*nc+i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -838,8 +838,8 @@ void mju_mulMatTMat(mjtNum* res, const mjtNum* mat1, const mjtNum* mat2,
|
|||||||
|
|
||||||
mju_zero(res, c1*c2);
|
mju_zero(res, c1*c2);
|
||||||
|
|
||||||
for (int i=0; i<r1; i++) {
|
for (int i=0; i < r1; i++) {
|
||||||
for (int j=0; j<c1; j++) {
|
for (int j=0; j < c1; j++) {
|
||||||
if ((tmp = mat1[i*c1+j])) {
|
if ((tmp = mat1[i*c1+j])) {
|
||||||
mju_addToScl(res+j*c2, mat2+i*c2, tmp, c2);
|
mju_addToScl(res+j*c2, mat2+i*c2, tmp, c2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ void mju_error(const char* msg, ...) {
|
|||||||
} else if (mju_user_error) {
|
} else if (mju_user_error) {
|
||||||
mju_user_error(errmsg);
|
mju_user_error(errmsg);
|
||||||
} else {
|
} else {
|
||||||
// write to log and console
|
// write to log and console
|
||||||
mju_writeLog("ERROR", errmsg);
|
mju_writeLog("ERROR", errmsg);
|
||||||
printf("ERROR: %s\n\nPress Enter to exit ...", errmsg);
|
printf("ERROR: %s\n\nPress Enter to exit ...", errmsg);
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ static mjtByte is_intersect(const mjtNum* p1, const mjtNum* p2,
|
|||||||
|
|
||||||
// compute determinant, check
|
// compute determinant, check
|
||||||
mjtNum det = (p4[1]-p3[1])*(p2[0]-p1[0]) - (p4[0]-p3[0])*(p2[1]-p1[1]);
|
mjtNum det = (p4[1]-p3[1])*(p2[0]-p1[0]) - (p4[0]-p3[0])*(p2[1]-p1[1]);
|
||||||
if (fabs(det)<mjMINVAL) {
|
if (fabs(det) < mjMINVAL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ static mjtByte is_intersect(const mjtNum* p1, const mjtNum* p2,
|
|||||||
a = ((p4[0]-p3[0])*(p1[1]-p3[1]) - (p4[1]-p3[1])*(p1[0]-p3[0])) / det;
|
a = ((p4[0]-p3[0])*(p1[1]-p3[1]) - (p4[1]-p3[1])*(p1[0]-p3[0])) / det;
|
||||||
b = ((p2[0]-p1[0])*(p1[1]-p3[1]) - (p2[1]-p1[1])*(p1[0]-p3[0])) / det;
|
b = ((p2[0]-p1[0])*(p1[1]-p3[1]) - (p2[1]-p1[1])*(p1[0]-p3[0])) / det;
|
||||||
|
|
||||||
return ((a>=0 && a<=1 && b>=0 && b<=1) ? 1 : 0);
|
return ((a >= 0 && a <= 1 && b >= 0 && b <= 1) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ static mjtNum length_circle(const mjtNum* p0, const mjtNum* p1, int ind, mjtNum
|
|||||||
|
|
||||||
// flip if necessary
|
// flip if necessary
|
||||||
cross = p0[1]*p1[0]-p0[0]*p1[1];
|
cross = p0[1]*p1[0]-p0[0]*p1[1];
|
||||||
if ((cross>0 && ind) || (cross<0 && !ind)) {
|
if ((cross > 0 && ind) || (cross < 0 && !ind)) {
|
||||||
angle = 2*mjPI - angle;
|
angle = 2*mjPI - angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,37 +85,37 @@ static mjtNum wrap_circle(mjtNum* pnt, const mjtNum* d, const mjtNum* sd, mjtNum
|
|||||||
int sgn;
|
int sgn;
|
||||||
|
|
||||||
// either point inside circle or circle too small: no wrap
|
// either point inside circle or circle too small: no wrap
|
||||||
if (sqlen0<sqrad || sqlen1<sqrad || rad<mjMINVAL) {
|
if (sqlen0 < sqrad || sqlen1 < sqrad || rad < mjMINVAL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// points too close: no wrap
|
// points too close: no wrap
|
||||||
dd = dif[0]*dif[0] + dif[1]*dif[1];
|
dd = dif[0]*dif[0] + dif[1]*dif[1];
|
||||||
if (dd<mjMINVAL) {
|
if (dd < mjMINVAL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find nearest point on line segment to origin: a*dif + d0
|
// find nearest point on line segment to origin: a*dif + d0
|
||||||
a = -(dif[0]*d[0]+dif[1]*d[1])/dd;
|
a = -(dif[0]*d[0]+dif[1]*d[1])/dd;
|
||||||
if (a<0) {
|
if (a < 0) {
|
||||||
a = 0;
|
a = 0;
|
||||||
} else if (a>1) {
|
} else if (a > 1) {
|
||||||
a = 1;
|
a = 1;
|
||||||
}
|
}
|
||||||
tmp[0] = a*dif[0] + d[0];
|
tmp[0] = a*dif[0] + d[0];
|
||||||
tmp[1] = a*dif[1] + d[1];
|
tmp[1] = a*dif[1] + d[1];
|
||||||
|
|
||||||
// check for intersection and side
|
// check for intersection and side
|
||||||
if (tmp[0]*tmp[0]+tmp[1]*tmp[1]>sqrad && (!sd || mju_dot(sd, tmp, 2)>=0)) {
|
if (tmp[0]*tmp[0]+tmp[1]*tmp[1] > sqrad && (!sd || mju_dot(sd, tmp, 2) >= 0)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct the two solutions, compute goodness
|
// construct the two solutions, compute goodness
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
sqrt0 = mju_sqrt(sqlen0 - sqrad);
|
sqrt0 = mju_sqrt(sqlen0 - sqrad);
|
||||||
sqrt1 = mju_sqrt(sqlen1 - sqrad);
|
sqrt1 = mju_sqrt(sqlen1 - sqrad);
|
||||||
|
|
||||||
sgn = (i==0 ? 1 : -1);
|
sgn = (i == 0 ? 1 : -1);
|
||||||
|
|
||||||
sol[i][0][0] = (d[0]*sqrad + sgn*rad*d[1]*sqrt0)/sqlen0;
|
sol[i][0][0] = (d[0]*sqrad + sgn*rad*d[1]*sqrt0)/sqlen0;
|
||||||
sol[i][0][1] = (d[1]*sqrad - sgn*rad*d[0]*sqrt0)/sqlen0;
|
sol[i][0][1] = (d[1]*sqrad - sgn*rad*d[0]*sqrt0)/sqlen0;
|
||||||
@@ -139,7 +139,7 @@ static mjtNum wrap_circle(mjtNum* pnt, const mjtNum* d, const mjtNum* sd, mjtNum
|
|||||||
}
|
}
|
||||||
|
|
||||||
// select the better solution
|
// select the better solution
|
||||||
int i = (good[0]>good[1] ? 0 : 1);
|
int i = (good[0] > good[1] ? 0 : 1);
|
||||||
pnt[0] = sol[i][0][0];
|
pnt[0] = sol[i][0][0];
|
||||||
pnt[1] = sol[i][0][1];
|
pnt[1] = sol[i][0][1];
|
||||||
pnt[2] = sol[i][1][0];
|
pnt[2] = sol[i][1][0];
|
||||||
@@ -173,20 +173,20 @@ static mjtNum wrap_inside(mjtNum* pnt, const mjtNum* d, mjtNum rad) {
|
|||||||
mjtNum dd = dif[0]*dif[0] + dif[1]*dif[1];
|
mjtNum dd = dif[0]*dif[0] + dif[1]*dif[1];
|
||||||
|
|
||||||
// either point inside circle or circle too small: no wrap
|
// either point inside circle or circle too small: no wrap
|
||||||
if (len0<=rad || len1<=rad || rad<mjMINVAL || len0<mjMINVAL || len1<mjMINVAL) {
|
if (len0 <= rad || len1 <= rad || rad < mjMINVAL || len0 < mjMINVAL || len1 < mjMINVAL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// segment-circle intersection: no wrap
|
// segment-circle intersection: no wrap
|
||||||
if (dd>mjMINVAL) {
|
if (dd > mjMINVAL) {
|
||||||
// find nearest point on line segment to origin: d0 + a*dif
|
// find nearest point on line segment to origin: d0 + a*dif
|
||||||
mjtNum a = -(dif[0]*d[0]+dif[1]*d[1])/dd;
|
mjtNum a = -(dif[0]*d[0]+dif[1]*d[1])/dd;
|
||||||
|
|
||||||
// in segment
|
// in segment
|
||||||
if (a>0 && a<1) {
|
if (a > 0 && a < 1) {
|
||||||
mjtNum tmp[2];
|
mjtNum tmp[2];
|
||||||
mju_addScl(tmp, d, dif, a, 2);
|
mju_addScl(tmp, d, dif, a, 2);
|
||||||
if (mju_norm(tmp, 2)<=rad) {
|
if (mju_norm(tmp, 2) <= rad) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,9 +204,9 @@ static mjtNum wrap_inside(mjtNum* pnt, const mjtNum* d, mjtNum rad) {
|
|||||||
mjtNum A = rad/len0;
|
mjtNum A = rad/len0;
|
||||||
mjtNum B = rad/len1;
|
mjtNum B = rad/len1;
|
||||||
mjtNum cosG = (len0*len0 + len1*len1 - dd) / (2*len0*len1);
|
mjtNum cosG = (len0*len0 + len1*len1 - dd) / (2*len0*len1);
|
||||||
if (cosG<-1+mjMINVAL) {
|
if (cosG < -1+mjMINVAL) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (cosG>1-mjMINVAL) {
|
} else if (cosG > 1-mjMINVAL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
mjtNum G = mju_acos(cosG);
|
mjtNum G = mju_acos(cosG);
|
||||||
@@ -216,20 +216,20 @@ static mjtNum wrap_inside(mjtNum* pnt, const mjtNum* d, mjtNum rad) {
|
|||||||
mjtNum f = mju_asin(A*z) + mju_asin(B*z) - 2*mju_asin(z) + G;
|
mjtNum f = mju_asin(A*z) + mju_asin(B*z) - 2*mju_asin(z) + G;
|
||||||
|
|
||||||
// make sure init is not on the other side
|
// make sure init is not on the other side
|
||||||
if (f>0) {
|
if (f > 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Newton method
|
// Newton method
|
||||||
int iter;
|
int iter;
|
||||||
for (iter=0; iter<maxiter && mju_abs(f)>tolerance; iter++) {
|
for (iter=0; iter < maxiter && mju_abs(f) > tolerance; iter++) {
|
||||||
// derivative
|
// derivative
|
||||||
mjtNum df = A/mju_max(mjMINVAL, mju_sqrt(1-z*z*A*A)) +
|
mjtNum df = A/mju_max(mjMINVAL, mju_sqrt(1-z*z*A*A)) +
|
||||||
B/mju_max(mjMINVAL, mju_sqrt(1-z*z*B*B)) -
|
B/mju_max(mjMINVAL, mju_sqrt(1-z*z*B*B)) -
|
||||||
2/mju_max(mjMINVAL, mju_sqrt(1-z*z));
|
2/mju_max(mjMINVAL, mju_sqrt(1-z*z));
|
||||||
|
|
||||||
// check sign; SHOULD NOT OCCUR
|
// check sign; SHOULD NOT OCCUR
|
||||||
if (df>-mjMINVAL) {
|
if (df > -mjMINVAL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ static mjtNum wrap_inside(mjtNum* pnt, const mjtNum* d, mjtNum rad) {
|
|||||||
mjtNum z1 = z - f/df;
|
mjtNum z1 = z - f/df;
|
||||||
|
|
||||||
// make sure we are moving to the left; SHOULD NOT OCCUR
|
// make sure we are moving to the left; SHOULD NOT OCCUR
|
||||||
if (z1>z) {
|
if (z1 > z) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,13 +246,13 @@ static mjtNum wrap_inside(mjtNum* pnt, const mjtNum* d, mjtNum rad) {
|
|||||||
f = mju_asin(A*z) + mju_asin(B*z) - 2*mju_asin(z) + G;
|
f = mju_asin(A*z) + mju_asin(B*z) - 2*mju_asin(z) + G;
|
||||||
|
|
||||||
// exit if positive; SHOULD NOT OCCUR
|
// exit if positive; SHOULD NOT OCCUR
|
||||||
if (f>tolerance) {
|
if (f > tolerance) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check convergence
|
// check convergence
|
||||||
if (iter>=maxiter) {
|
if (iter >= maxiter) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +286,7 @@ mjtNum mju_wrap(mjtNum* wpnt, const mjtNum* x0, const mjtNum* x1,
|
|||||||
mjtNum L0, L1;
|
mjtNum L0, L1;
|
||||||
|
|
||||||
// check object type; SHOULD NOT OCCUR
|
// check object type; SHOULD NOT OCCUR
|
||||||
if (type!=mjWRAP_SPHERE && type!=mjWRAP_CYLINDER) {
|
if (type != mjWRAP_SPHERE && type != mjWRAP_CYLINDER) {
|
||||||
mju_error("mju_wrap: unknown wrapping object type %d", type);
|
mju_error("mju_wrap: unknown wrapping object type %d", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,12 +297,12 @@ mjtNum mju_wrap(mjtNum* wpnt, const mjtNum* x0, const mjtNum* x1,
|
|||||||
mju_mulMatTVec(p[1], xmat, tmp, 3, 3);
|
mju_mulMatTVec(p[1], xmat, tmp, 3, 3);
|
||||||
|
|
||||||
// too close to origin: return
|
// too close to origin: return
|
||||||
if (mju_norm3(p[0])<mjMINVAL || mju_norm3(p[1])<mjMINVAL) {
|
if (mju_norm3(p[0]) < mjMINVAL || mju_norm3(p[1]) < mjMINVAL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct 2D frame for circle wrap
|
// construct 2D frame for circle wrap
|
||||||
if (type==mjWRAP_SPHERE) {
|
if (type == mjWRAP_SPHERE) {
|
||||||
// 1st axis = p0
|
// 1st axis = p0
|
||||||
mju_copy3(axis[0], p[0]);
|
mju_copy3(axis[0], p[0]);
|
||||||
mju_normalize3(axis[0]);
|
mju_normalize3(axis[0]);
|
||||||
@@ -312,15 +312,15 @@ mjtNum mju_wrap(mjtNum* wpnt, const mjtNum* x0, const mjtNum* x1,
|
|||||||
mjtNum nrm = mju_normalize3(normal);
|
mjtNum nrm = mju_normalize3(normal);
|
||||||
|
|
||||||
// if (p0, p1) parallel: different normal
|
// if (p0, p1) parallel: different normal
|
||||||
if (nrm<mjMINVAL) {
|
if (nrm < mjMINVAL) {
|
||||||
// find max component of axis0
|
// find max component of axis0
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (mju_abs(axis[0][1])>mju_abs(axis[0][0]) &&
|
if (mju_abs(axis[0][1]) > mju_abs(axis[0][0]) &&
|
||||||
mju_abs(axis[0][1])>mju_abs(axis[0][2])) {
|
mju_abs(axis[0][1]) > mju_abs(axis[0][2])) {
|
||||||
i = 1;
|
i = 1;
|
||||||
}
|
}
|
||||||
if (mju_abs(axis[0][2])>mju_abs(axis[0][0]) &&
|
if (mju_abs(axis[0][2]) > mju_abs(axis[0][0]) &&
|
||||||
mju_abs(axis[0][2])>mju_abs(axis[0][1])) {
|
mju_abs(axis[0][2]) > mju_abs(axis[0][1])) {
|
||||||
i = 2;
|
i = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +374,7 @@ mjtNum mju_wrap(mjtNum* wpnt, const mjtNum* x0, const mjtNum* x1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// apply inside wrap
|
// apply inside wrap
|
||||||
if (side && sd[0]==0 && sd[1]==0) {
|
if (side && sd[0] == 0 && sd[1] == 0) {
|
||||||
wlen = wrap_inside(pnt, d, size[0]);
|
wlen = wrap_inside(pnt, d, size[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,12 +384,12 @@ mjtNum mju_wrap(mjtNum* wpnt, const mjtNum* x0, const mjtNum* x1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no wrap
|
// no wrap
|
||||||
if (wlen<0) {
|
if (wlen < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reconstruct 3D points in local frame: res
|
// reconstruct 3D points in local frame: res
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i < 2; i++) {
|
||||||
// res = axis0*d0 + axis1*d1
|
// res = axis0*d0 + axis1*d1
|
||||||
mju_scl3(res+3*i, axis[0], pnt[2*i]);
|
mju_scl3(res+3*i, axis[0], pnt[2*i]);
|
||||||
mju_scl3(tmp, axis[1], pnt[2*i+1]);
|
mju_scl3(tmp, axis[1], pnt[2*i+1]);
|
||||||
@@ -397,7 +397,7 @@ mjtNum mju_wrap(mjtNum* wpnt, const mjtNum* x0, const mjtNum* x1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cylinder: correct along z
|
// cylinder: correct along z
|
||||||
if (type==mjWRAP_CYLINDER) {
|
if (type == mjWRAP_CYLINDER) {
|
||||||
// set vertical coordinates
|
// set vertical coordinates
|
||||||
L0 = mju_sqrt((p[0][0]-res[0])*(p[0][0]-res[0]) + (p[0][1]-res[1])*(p[0][1]-res[1]));
|
L0 = mju_sqrt((p[0][0]-res[0])*(p[0][0]-res[0]) + (p[0][1]-res[1])*(p[0][1]-res[1]));
|
||||||
L1 = mju_sqrt((p[1][0]-res[3])*(p[1][0]-res[3]) + (p[1][1]-res[4])*(p[1][1]-res[4]));
|
L1 = mju_sqrt((p[1][0]-res[3])*(p[1][0]-res[3]) + (p[1][1]-res[4])*(p[1][1]-res[4]));
|
||||||
@@ -466,7 +466,7 @@ mjtNum mju_muscleGain(mjtNum len, mjtNum vel, const mjtNum lengthrange[2],
|
|||||||
mjtNum fvmax = prm[8];
|
mjtNum fvmax = prm[8];
|
||||||
|
|
||||||
// scale force if negative
|
// scale force if negative
|
||||||
if (force<0) {
|
if (force < 0) {
|
||||||
force = scale / mjMAX(mjMINVAL, acc0);
|
force = scale / mjMAX(mjMINVAL, acc0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,16 +484,16 @@ mjtNum mju_muscleGain(mjtNum len, mjtNum vel, const mjtNum lengthrange[2],
|
|||||||
|
|
||||||
// length curve
|
// length curve
|
||||||
mjtNum FL = 0;
|
mjtNum FL = 0;
|
||||||
if (L>=lmin && L<=a) {
|
if (L >= lmin && L <= a) {
|
||||||
x = (L-lmin) / mjMAX(mjMINVAL, a-lmin);
|
x = (L-lmin) / mjMAX(mjMINVAL, a-lmin);
|
||||||
FL = 0.5*x*x;
|
FL = 0.5*x*x;
|
||||||
} else if (L<=1) {
|
} else if (L <= 1) {
|
||||||
x = (1-L) / mjMAX(mjMINVAL, 1-a);
|
x = (1-L) / mjMAX(mjMINVAL, 1-a);
|
||||||
FL = 1 - 0.5*x*x;
|
FL = 1 - 0.5*x*x;
|
||||||
} else if (L<=b) {
|
} else if (L <= b) {
|
||||||
x = (L-1) / mjMAX(mjMINVAL, b-1);
|
x = (L-1) / mjMAX(mjMINVAL, b-1);
|
||||||
FL = 1 - 0.5*x*x;
|
FL = 1 - 0.5*x*x;
|
||||||
} else if (L<=lmax) {
|
} else if (L <= lmax) {
|
||||||
x = (lmax-L) / mjMAX(mjMINVAL, lmax-b);
|
x = (lmax-L) / mjMAX(mjMINVAL, lmax-b);
|
||||||
FL = 0.5*x*x;
|
FL = 0.5*x*x;
|
||||||
}
|
}
|
||||||
@@ -501,11 +501,11 @@ mjtNum mju_muscleGain(mjtNum len, mjtNum vel, const mjtNum lengthrange[2],
|
|||||||
// velocity curve
|
// velocity curve
|
||||||
mjtNum FV;
|
mjtNum FV;
|
||||||
mjtNum y = fvmax-1;
|
mjtNum y = fvmax-1;
|
||||||
if (V<=-1) {
|
if (V <= -1) {
|
||||||
FV = 0;
|
FV = 0;
|
||||||
} else if (V<=0) {
|
} else if (V <= 0) {
|
||||||
FV = (V+1)*(V+1);
|
FV = (V+1)*(V+1);
|
||||||
} else if (V<=y) {
|
} else if (V <= y) {
|
||||||
FV = fvmax - (y-V)*(y-V) / mjMAX(mjMINVAL, y);
|
FV = fvmax - (y-V)*(y-V) / mjMAX(mjMINVAL, y);
|
||||||
} else {
|
} else {
|
||||||
FV = fvmax;
|
FV = fvmax;
|
||||||
@@ -528,7 +528,7 @@ mjtNum mju_muscleBias(mjtNum len, const mjtNum lengthrange[2],
|
|||||||
mjtNum fpmax = prm[7];
|
mjtNum fpmax = prm[7];
|
||||||
|
|
||||||
// scale force if negative
|
// scale force if negative
|
||||||
if (force<0) {
|
if (force < 0) {
|
||||||
force = scale / mjMAX(mjMINVAL, acc0);
|
force = scale / mjMAX(mjMINVAL, acc0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,9 +540,9 @@ mjtNum mju_muscleBias(mjtNum len, const mjtNum lengthrange[2],
|
|||||||
|
|
||||||
// half-quadratic to (L0+lmax)/2, linear beyond
|
// half-quadratic to (L0+lmax)/2, linear beyond
|
||||||
mjtNum b = 0.5*(1+lmax);
|
mjtNum b = 0.5*(1+lmax);
|
||||||
if (L<=1) {
|
if (L <= 1) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (L<=b) {
|
} else if (L <= b) {
|
||||||
mjtNum x = (L-1) / mjMAX(mjMINVAL, b-1);
|
mjtNum x = (L-1) / mjMAX(mjMINVAL, b-1);
|
||||||
return -force*fpmax*0.5*x*x;
|
return -force*fpmax*0.5*x*x;
|
||||||
} else {
|
} else {
|
||||||
@@ -606,7 +606,7 @@ void mju_encodePyramid(mjtNum* pyramid, const mjtNum* force, const mjtNum* mu, i
|
|||||||
// arbitary redundancy resolution:
|
// arbitary redundancy resolution:
|
||||||
// pyramid0_i + pyramid1_i = force_normal/(dim-1) = a
|
// pyramid0_i + pyramid1_i = force_normal/(dim-1) = a
|
||||||
// pyramid0_i - pyramid1_i = force_tangent_i/mu_i = b
|
// pyramid0_i - pyramid1_i = force_tangent_i/mu_i = b
|
||||||
for (int i=0; i<dim-1; i++) {
|
for (int i=0; i < dim-1; i++) {
|
||||||
b = mju_min(a, force[i+1]/mu[i]);
|
b = mju_min(a, force[i+1]/mu[i]);
|
||||||
pyramid[2*i] = 0.5*(a+b);
|
pyramid[2*i] = 0.5*(a+b);
|
||||||
pyramid[2*i+1] = 0.5*(a-b);
|
pyramid[2*i+1] = 0.5*(a-b);
|
||||||
@@ -618,19 +618,19 @@ void mju_encodePyramid(mjtNum* pyramid, const mjtNum* force, const mjtNum* mu, i
|
|||||||
// convert pyramid representation to contact force
|
// convert pyramid representation to contact force
|
||||||
void mju_decodePyramid(mjtNum* force, const mjtNum* pyramid, const mjtNum* mu, int dim) {
|
void mju_decodePyramid(mjtNum* force, const mjtNum* pyramid, const mjtNum* mu, int dim) {
|
||||||
// special handling of frictionless contacts
|
// special handling of frictionless contacts
|
||||||
if (dim==1) {
|
if (dim == 1) {
|
||||||
force[0] = pyramid[0];
|
force[0] = pyramid[0];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// force_normal = sum(pyramid0_i + pyramid1_i)
|
// force_normal = sum(pyramid0_i + pyramid1_i)
|
||||||
force[0] = 0;
|
force[0] = 0;
|
||||||
for (int i=0; i<2*(dim-1); i++) {
|
for (int i=0; i < 2*(dim-1); i++) {
|
||||||
force[0] += pyramid[i];
|
force[0] += pyramid[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// force_tangent_i = (pyramid0_i - pyramid1_i) * mu_i
|
// force_tangent_i = (pyramid0_i - pyramid1_i) * mu_i
|
||||||
for (int i=0; i<dim-1; i++) {
|
for (int i=0; i < dim-1; i++) {
|
||||||
force[i+1] = (pyramid[2*i] - pyramid[2*i+1]) * mu[i];
|
force[i+1] = (pyramid[2*i] - pyramid[2*i+1]) * mu[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -646,7 +646,7 @@ mjtNum mju_springDamper(mjtNum pos0, mjtNum vel0, mjtNum k, mjtNum b, mjtNum t)
|
|||||||
|
|
||||||
// overdamping
|
// overdamping
|
||||||
// pos(t) = c1*exp(r1*t) + c2*exp(r2*t); r12 = (-b +- sqrt(det))/2
|
// pos(t) = c1*exp(r1*t) + c2*exp(r2*t); r12 = (-b +- sqrt(det))/2
|
||||||
if (det>mjMINVAL) {
|
if (det > mjMINVAL) {
|
||||||
// compute w = sqrt(det)/2
|
// compute w = sqrt(det)/2
|
||||||
w = mju_sqrt(det)/2;
|
w = mju_sqrt(det)/2;
|
||||||
|
|
||||||
@@ -664,7 +664,7 @@ mjtNum mju_springDamper(mjtNum pos0, mjtNum vel0, mjtNum k, mjtNum b, mjtNum t)
|
|||||||
|
|
||||||
// critical damping
|
// critical damping
|
||||||
// pos(t) = exp(-b*t/2) * (c1 + c2*t)
|
// pos(t) = exp(-b*t/2) * (c1 + c2*t)
|
||||||
else if (det<=mjMINVAL && det>=-mjMINVAL) {
|
else if (det <= mjMINVAL && det >= -mjMINVAL) {
|
||||||
// compute coefficients
|
// compute coefficients
|
||||||
c1 = pos0;
|
c1 = pos0;
|
||||||
c2 = vel0 + b*c1/2;
|
c2 = vel0 + b*c1/2;
|
||||||
@@ -692,8 +692,8 @@ mjtNum mju_springDamper(mjtNum pos0, mjtNum vel0, mjtNum k, mjtNum b, mjtNum t)
|
|||||||
|
|
||||||
// print matrix to screen
|
// print matrix to screen
|
||||||
void mju_printMat(const mjtNum* mat, int nr, int nc) {
|
void mju_printMat(const mjtNum* mat, int nr, int nc) {
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
for (int c=0; c<nc; c++) {
|
for (int c=0; c < nc; c++) {
|
||||||
printf("%.8f ", mat[r*nc+c]);
|
printf("%.8f ", mat[r*nc+c]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -707,8 +707,8 @@ void mju_printMat(const mjtNum* mat, int nr, int nc) {
|
|||||||
void mju_printMatSparse(const mjtNum* mat, int nr,
|
void mju_printMatSparse(const mjtNum* mat, int nr,
|
||||||
const int* rownnz, const int* rowadr,
|
const int* rownnz, const int* rowadr,
|
||||||
const int* colind) {
|
const int* colind) {
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
for (int adr=rowadr[r]; adr<rowadr[r]+rownnz[r]; adr++) {
|
for (int adr=rowadr[r]; adr < rowadr[r]+rownnz[r]; adr++) {
|
||||||
printf("(%d %d): %9.6f ", r, colind[adr], mat[adr]);
|
printf("(%d %d): %9.6f ", r, colind[adr], mat[adr]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -742,9 +742,9 @@ mjtNum mju_max(mjtNum a, mjtNum b) {
|
|||||||
|
|
||||||
// clip x to the range [min, max]
|
// clip x to the range [min, max]
|
||||||
mjtNum mju_clip(mjtNum x, mjtNum min, mjtNum max) {
|
mjtNum mju_clip(mjtNum x, mjtNum min, mjtNum max) {
|
||||||
if (x<min) {
|
if (x < min) {
|
||||||
return min;
|
return min;
|
||||||
} else if (x>max) {
|
} else if (x > max) {
|
||||||
return max;
|
return max;
|
||||||
} else {
|
} else {
|
||||||
return x;
|
return x;
|
||||||
@@ -755,9 +755,9 @@ mjtNum mju_clip(mjtNum x, mjtNum min, mjtNum max) {
|
|||||||
|
|
||||||
// sign function
|
// sign function
|
||||||
mjtNum mju_sign(mjtNum x) {
|
mjtNum mju_sign(mjtNum x) {
|
||||||
if (x<0) {
|
if (x < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (x>0) {
|
} else if (x > 0) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -972,13 +972,13 @@ const char* mju_writeNumBytes(size_t nbytes) {
|
|||||||
int i;
|
int i;
|
||||||
static mjTHREADLOCAL char message[20];
|
static mjTHREADLOCAL char message[20];
|
||||||
static const char suffix[] = " KMGTPE";
|
static const char suffix[] = " KMGTPE";
|
||||||
for (i=0; i<6; i++) {
|
for (i=0; i < 6; i++) {
|
||||||
const size_t bits = (size_t)(1) << (10*(6-i));
|
const size_t bits = (size_t)(1) << (10*(6-i));
|
||||||
if (nbytes >= bits && !(nbytes & (bits - 1))) {
|
if (nbytes >= bits && !(nbytes & (bits - 1))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i<6) {
|
if (i < 6) {
|
||||||
mjSNPRINTF(message, "%zu%c", nbytes >> (10*(6-i)), suffix[6-i]);
|
mjSNPRINTF(message, "%zu%c", nbytes >> (10*(6-i)), suffix[6-i]);
|
||||||
} else {
|
} else {
|
||||||
mjSNPRINTF(message, "%zu", nbytes >> (10*(6-i)));
|
mjSNPRINTF(message, "%zu", nbytes >> (10*(6-i)));
|
||||||
@@ -1042,15 +1042,15 @@ const char* mju_warningText(int warning, size_t info) {
|
|||||||
|
|
||||||
// return 1 if nan or abs(x)>mjMAXVAL, 0 otherwise
|
// return 1 if nan or abs(x)>mjMAXVAL, 0 otherwise
|
||||||
int mju_isBad(mjtNum x) {
|
int mju_isBad(mjtNum x) {
|
||||||
return (x!=x || x>mjMAXVAL || x<-mjMAXVAL);
|
return (x != x || x > mjMAXVAL || x < -mjMAXVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// return 1 if all elements are 0
|
// return 1 if all elements are 0
|
||||||
int mju_isZero(mjtNum* vec, int n) {
|
int mju_isZero(mjtNum* vec, int n) {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
if (vec[i]!=0) {
|
if (vec[i] != 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1069,7 +1069,7 @@ mjtNum mju_standardNormal(mjtNum* num2) {
|
|||||||
x1 = scale * (mjtNum)rand() - 1.0;
|
x1 = scale * (mjtNum)rand() - 1.0;
|
||||||
x2 = scale * (mjtNum)rand() - 1.0;
|
x2 = scale * (mjtNum)rand() - 1.0;
|
||||||
w = x1 * x1 + x2 * x2;
|
w = x1 * x1 + x2 * x2;
|
||||||
} while (w>=1.0 || w==0);
|
} while (w >= 1.0 || w == 0);
|
||||||
|
|
||||||
w = mju_sqrt((-2.0 * mju_log(w)) / w);
|
w = mju_sqrt((-2.0 * mju_log(w)) / w);
|
||||||
if (num2) {
|
if (num2) {
|
||||||
@@ -1083,7 +1083,7 @@ mjtNum mju_standardNormal(mjtNum* num2) {
|
|||||||
|
|
||||||
// convert from float to mjtNum
|
// convert from float to mjtNum
|
||||||
void mju_f2n(mjtNum* res, const float* vec, int n) {
|
void mju_f2n(mjtNum* res, const float* vec, int n) {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i] = (mjtNum) vec[i];
|
res[i] = (mjtNum) vec[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1092,7 +1092,7 @@ void mju_f2n(mjtNum* res, const float* vec, int n) {
|
|||||||
|
|
||||||
// convert from mjtNum to float
|
// convert from mjtNum to float
|
||||||
void mju_n2f(float* res, const mjtNum* vec, int n) {
|
void mju_n2f(float* res, const mjtNum* vec, int n) {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i] = (float) vec[i];
|
res[i] = (float) vec[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1100,7 +1100,7 @@ void mju_n2f(float* res, const mjtNum* vec, int n) {
|
|||||||
|
|
||||||
// convert from double to mjtNum
|
// convert from double to mjtNum
|
||||||
void mju_d2n(mjtNum* res, const double* vec, int n) {
|
void mju_d2n(mjtNum* res, const double* vec, int n) {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i] = (mjtNum) vec[i];
|
res[i] = (mjtNum) vec[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1109,7 +1109,7 @@ void mju_d2n(mjtNum* res, const double* vec, int n) {
|
|||||||
|
|
||||||
// convert from mjtNum to double
|
// convert from mjtNum to double
|
||||||
void mju_n2d(double* res, const mjtNum* vec, int n) {
|
void mju_n2d(double* res, const mjtNum* vec, int n) {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i] = (double) vec[i];
|
res[i] = (double) vec[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1118,10 +1118,10 @@ void mju_n2d(double* res, const mjtNum* vec, int n) {
|
|||||||
|
|
||||||
// insertion sort, increasing order
|
// insertion sort, increasing order
|
||||||
void mju_insertionSort(mjtNum* list, int n) {
|
void mju_insertionSort(mjtNum* list, int n) {
|
||||||
for (int i=1; i<n; i++) {
|
for (int i=1; i < n; i++) {
|
||||||
mjtNum x = list[i];
|
mjtNum x = list[i];
|
||||||
int j = i-1;
|
int j = i-1;
|
||||||
while (j>=0 && list[j]>x) {
|
while (j >= 0 && list[j] > x) {
|
||||||
list[j+1] = list[j];
|
list[j+1] = list[j];
|
||||||
j--;
|
j--;
|
||||||
}
|
}
|
||||||
@@ -1133,10 +1133,10 @@ void mju_insertionSort(mjtNum* list, int n) {
|
|||||||
|
|
||||||
// integer insertion sort, increasing order
|
// integer insertion sort, increasing order
|
||||||
void mju_insertionSortInt(int* list, int n) {
|
void mju_insertionSortInt(int* list, int n) {
|
||||||
for (int i=1; i<n; i++) {
|
for (int i=1; i < n; i++) {
|
||||||
int x = list[i];
|
int x = list[i];
|
||||||
int j = i-1;
|
int j = i-1;
|
||||||
while (j>=0 && list[j]>x) {
|
while (j >= 0 && list[j] > x) {
|
||||||
list[j+1] = list[j];
|
list[j+1] = list[j];
|
||||||
j--;
|
j--;
|
||||||
}
|
}
|
||||||
@@ -1152,7 +1152,7 @@ mjtNum mju_Halton(int index, int base) {
|
|||||||
mjtNum b = (mjtNum)base;
|
mjtNum b = (mjtNum)base;
|
||||||
mjtNum f = 1/b, hn = 0;
|
mjtNum f = 1/b, hn = 0;
|
||||||
|
|
||||||
while (n0>0) {
|
while (n0 > 0) {
|
||||||
int n1 = n0/base;
|
int n1 = n0/base;
|
||||||
int r = n0 - n1*base;
|
int r = n0 - n1*base;
|
||||||
hn += f*r;
|
hn += f*r;
|
||||||
@@ -1167,7 +1167,7 @@ mjtNum mju_Halton(int index, int base) {
|
|||||||
|
|
||||||
// Call strncpy, then set dst[n-1] = 0.
|
// Call strncpy, then set dst[n-1] = 0.
|
||||||
char* mju_strncpy(char *dst, const char *src, int n) {
|
char* mju_strncpy(char *dst, const char *src, int n) {
|
||||||
if (dst && src && n>0) {
|
if (dst && src && n > 0) {
|
||||||
strncpy(dst, src, n);
|
strncpy(dst, src, n);
|
||||||
dst[n-1] = 0;
|
dst[n-1] = 0;
|
||||||
}
|
}
|
||||||
@@ -1180,10 +1180,10 @@ char* mju_strncpy(char *dst, const char *src, int n) {
|
|||||||
// sigmoid function over 0<=x<=1 using quintic polynomial
|
// sigmoid function over 0<=x<=1 using quintic polynomial
|
||||||
mjtNum mju_sigmoid(mjtNum x) {
|
mjtNum mju_sigmoid(mjtNum x) {
|
||||||
// fast return
|
// fast return
|
||||||
if (x<=0) {
|
if (x <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (x>=1) {
|
if (x >= 1) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+124
-124
@@ -35,7 +35,7 @@ int mju_cholFactor(mjtNum* mat, int n, mjtNum mindiag) {
|
|||||||
mjtNum tmp;
|
mjtNum tmp;
|
||||||
|
|
||||||
// in-place Cholesky factorization
|
// in-place Cholesky factorization
|
||||||
for (int j=0; j<n; j++) {
|
for (int j=0; j < n; j++) {
|
||||||
// compute new diagonal
|
// compute new diagonal
|
||||||
tmp = mat[j*(n+1)];
|
tmp = mat[j*(n+1)];
|
||||||
if (j) {
|
if (j) {
|
||||||
@@ -43,7 +43,7 @@ int mju_cholFactor(mjtNum* mat, int n, mjtNum mindiag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// correct diagonal values below threshold
|
// correct diagonal values below threshold
|
||||||
if (tmp<mindiag) {
|
if (tmp < mindiag) {
|
||||||
tmp = mindiag;
|
tmp = mindiag;
|
||||||
rank--;
|
rank--;
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ int mju_cholFactor(mjtNum* mat, int n, mjtNum mindiag) {
|
|||||||
|
|
||||||
// process off-diagonal entries
|
// process off-diagonal entries
|
||||||
tmp = 1/mat[j*(n+1)];
|
tmp = 1/mat[j*(n+1)];
|
||||||
for (int i=j+1; i<n; i++) {
|
for (int i=j+1; i < n; i++) {
|
||||||
mat[i*n+j] = (mat[i*n+j] - mju_dot(mat+i*n, mat+j*n, j)) * tmp;
|
mat[i*n+j] = (mat[i*n+j] - mju_dot(mat+i*n, mat+j*n, j)) * tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,12 +66,12 @@ int mju_cholFactor(mjtNum* mat, int n, mjtNum mindiag) {
|
|||||||
// Cholesky solve
|
// Cholesky solve
|
||||||
void mju_cholSolve(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int n) {
|
void mju_cholSolve(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int n) {
|
||||||
// copy if source and destination are different
|
// copy if source and destination are different
|
||||||
if (res!=vec) {
|
if (res != vec) {
|
||||||
mju_copy(res, vec, n);
|
mju_copy(res, vec, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// forward substitution: solve L*res = vec
|
// forward substitution: solve L*res = vec
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
if (i) {
|
if (i) {
|
||||||
res[i] -= mju_dot(mat+i*n, res, i);
|
res[i] -= mju_dot(mat+i*n, res, i);
|
||||||
}
|
}
|
||||||
@@ -81,9 +81,9 @@ void mju_cholSolve(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// backward substitution: solve L'*res = res
|
// backward substitution: solve L'*res = res
|
||||||
for (int i=n-1; i>=0; i--) {
|
for (int i=n-1; i >= 0; i--) {
|
||||||
if (i<n-1) {
|
if (i < n-1) {
|
||||||
for (int j=i+1; j<n; j++) {
|
for (int j=i+1; j < n; j++) {
|
||||||
res[i] -= mat[j*n+i] * res[j];
|
res[i] -= mat[j*n+i] * res[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,12 +99,12 @@ int mju_cholUpdate(mjtNum* mat, mjtNum* x, int n, int flg_plus) {
|
|||||||
int rank = n;
|
int rank = n;
|
||||||
mjtNum r, c, cinv, s, Lkk, tmp;
|
mjtNum r, c, cinv, s, Lkk, tmp;
|
||||||
|
|
||||||
for (int k=0; k<n; k++) {
|
for (int k=0; k < n; k++) {
|
||||||
if (x[k]) {
|
if (x[k]) {
|
||||||
// prepare constants
|
// prepare constants
|
||||||
Lkk = mat[k*(n+1)];
|
Lkk = mat[k*(n+1)];
|
||||||
tmp = Lkk*Lkk + (flg_plus ? x[k]*x[k] : -x[k]*x[k]);
|
tmp = Lkk*Lkk + (flg_plus ? x[k]*x[k] : -x[k]*x[k]);
|
||||||
if (tmp<mjMINVAL) {
|
if (tmp < mjMINVAL) {
|
||||||
tmp = mjMINVAL;
|
tmp = mjMINVAL;
|
||||||
rank--;
|
rank--;
|
||||||
}
|
}
|
||||||
@@ -118,17 +118,17 @@ int mju_cholUpdate(mjtNum* mat, mjtNum* x, int n, int flg_plus) {
|
|||||||
|
|
||||||
// update mat
|
// update mat
|
||||||
if (flg_plus) {
|
if (flg_plus) {
|
||||||
for (int i=k+1; i<n; i++) {
|
for (int i=k+1; i < n; i++) {
|
||||||
mat[i*n+k] = (mat[i*n+k] + s*x[i])*cinv;
|
mat[i*n+k] = (mat[i*n+k] + s*x[i])*cinv;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i=k+1; i<n; i++) {
|
for (int i=k+1; i < n; i++) {
|
||||||
mat[i*n+k] = (mat[i*n+k] - s*x[i])*cinv;
|
mat[i*n+k] = (mat[i*n+k] - s*x[i])*cinv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update x
|
// update x
|
||||||
for (int i=k+1; i<n; i++) {
|
for (int i=k+1; i < n; i++) {
|
||||||
x[i] = c*x[i] - s*mat[i*n+k];
|
x[i] = c*x[i] - s*mat[i*n+k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,26 +153,26 @@ int mju_cholFactorSparse(mjtNum* mat, int n, mjtNum mindiag,
|
|||||||
mjtNum* sparse_buf = mj_stackAlloc(d, n);
|
mjtNum* sparse_buf = mj_stackAlloc(d, n);
|
||||||
|
|
||||||
// shrink rows so that rownnz ends at diagonal
|
// shrink rows so that rownnz ends at diagonal
|
||||||
for (int r=0; r<n; r++) {
|
for (int r=0; r < n; r++) {
|
||||||
// shrink
|
// shrink
|
||||||
while (rownnz[r]>0 && colind[rowadr[r]+rownnz[r]-1]>r) {
|
while (rownnz[r] > 0 && colind[rowadr[r]+rownnz[r]-1] > r) {
|
||||||
rownnz[r]--;
|
rownnz[r]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check
|
// check
|
||||||
if (rownnz[r]==0 || colind[rowadr[r]+rownnz[r]-1]!=r) {
|
if (rownnz[r] == 0 || colind[rowadr[r]+rownnz[r]-1] != r) {
|
||||||
mju_error("Matrix must have non-zero diagonal in mju_cholFactorSparse");
|
mju_error("Matrix must have non-zero diagonal in mju_cholFactorSparse");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// backpass over rows
|
// backpass over rows
|
||||||
for (int r=n-1; r>=0; r--) {
|
for (int r=n-1; r >= 0; r--) {
|
||||||
// get rownnz and rowadr for row r
|
// get rownnz and rowadr for row r
|
||||||
int nnz = rownnz[r], adr = rowadr[r];
|
int nnz = rownnz[r], adr = rowadr[r];
|
||||||
|
|
||||||
// update row r diagonal
|
// update row r diagonal
|
||||||
mjtNum tmp = mat[adr+nnz-1];
|
mjtNum tmp = mat[adr+nnz-1];
|
||||||
if (tmp<mindiag) {
|
if (tmp < mindiag) {
|
||||||
tmp = mindiag;
|
tmp = mindiag;
|
||||||
rank--;
|
rank--;
|
||||||
}
|
}
|
||||||
@@ -180,12 +180,12 @@ int mju_cholFactorSparse(mjtNum* mat, int n, mjtNum mindiag,
|
|||||||
tmp = 1/mat[adr+nnz-1];
|
tmp = 1/mat[adr+nnz-1];
|
||||||
|
|
||||||
// update row r before diagonal
|
// update row r before diagonal
|
||||||
for (int i=0; i<nnz-1; i++) {
|
for (int i=0; i < nnz-1; i++) {
|
||||||
mat[adr+i] *= tmp;
|
mat[adr+i] *= tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update row c<r where mat(r,c)!=0
|
// update row c<r where mat(r,c)!=0
|
||||||
for (int i=0; i<nnz-1; i++) {
|
for (int i=0; i < nnz-1; i++) {
|
||||||
// get column index
|
// get column index
|
||||||
int c = colind[adr+i];
|
int c = colind[adr+i];
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ void mju_cholSolveSparse(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int
|
|||||||
mju_copy(res, vec, n);
|
mju_copy(res, vec, n);
|
||||||
|
|
||||||
// vec <- L^-T vec
|
// vec <- L^-T vec
|
||||||
for (int i=n-1; i>=0; i--) {
|
for (int i=n-1; i >= 0; i--) {
|
||||||
if (res[i]) {
|
if (res[i]) {
|
||||||
// get rowadr[i], rownnz[i]
|
// get rowadr[i], rownnz[i]
|
||||||
const int adr = rowadr[i], nnz = rownnz[i];
|
const int adr = rowadr[i], nnz = rownnz[i];
|
||||||
@@ -222,19 +222,19 @@ void mju_cholSolveSparse(mjtNum* res, const mjtNum* mat, const mjtNum* vec, int
|
|||||||
mjtNum tmp = res[i];
|
mjtNum tmp = res[i];
|
||||||
|
|
||||||
// x(j) -= L(i,j)*x(i), j=0:i-1
|
// x(j) -= L(i,j)*x(i), j=0:i-1
|
||||||
for (int j=0; j<nnz-1; j++) {
|
for (int j=0; j < nnz-1; j++) {
|
||||||
res[colind[adr+j]] -= mat[adr+j]*tmp;
|
res[colind[adr+j]] -= mat[adr+j]*tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// vec <- L^-1 vec
|
// vec <- L^-1 vec
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
// get rowadr[i], rownnz[i]
|
// get rowadr[i], rownnz[i]
|
||||||
const int adr = rowadr[i], nnz = rownnz[i];
|
const int adr = rowadr[i], nnz = rownnz[i];
|
||||||
|
|
||||||
// x(i) -= sum_j L(i,j)*x(j), j=0:i-1
|
// x(i) -= sum_j L(i,j)*x(j), j=0:i-1
|
||||||
if (nnz>1) {
|
if (nnz > 1) {
|
||||||
res[i] -= mju_dotSparse(mat+adr, res, nnz-1, colind+adr);
|
res[i] -= mju_dotSparse(mat+adr, res, nnz-1, colind+adr);
|
||||||
// modulo AVX, the above line does
|
// modulo AVX, the above line does
|
||||||
// for (int j=0; j<nnz-1; j++)
|
// for (int j=0; j<nnz-1; j++)
|
||||||
@@ -260,13 +260,13 @@ int mju_cholUpdateSparse(mjtNum* mat, mjtNum* x, int n, int flg_plus,
|
|||||||
|
|
||||||
// backpass over rows corresponding to non-zero x(r)
|
// backpass over rows corresponding to non-zero x(r)
|
||||||
int rank = n, i = x_nnz - 1;
|
int rank = n, i = x_nnz - 1;
|
||||||
while (i>=0) {
|
while (i >= 0) {
|
||||||
// get rownnz and rowadr for this row
|
// get rownnz and rowadr for this row
|
||||||
int nnz = rownnz[x_ind[i]], adr = rowadr[x_ind[i]];
|
int nnz = rownnz[x_ind[i]], adr = rowadr[x_ind[i]];
|
||||||
|
|
||||||
// compute quantities
|
// compute quantities
|
||||||
mjtNum tmp = mat[adr+nnz-1]*mat[adr+nnz-1] + (flg_plus ? x[i]*x[i] : -x[i]*x[i]);
|
mjtNum tmp = mat[adr+nnz-1]*mat[adr+nnz-1] + (flg_plus ? x[i]*x[i] : -x[i]*x[i]);
|
||||||
if (tmp<mjMINVAL) {
|
if (tmp < mjMINVAL) {
|
||||||
tmp = mjMINVAL;
|
tmp = mjMINVAL;
|
||||||
rank--;
|
rank--;
|
||||||
}
|
}
|
||||||
@@ -283,7 +283,7 @@ int mju_cholUpdateSparse(mjtNum* mat, mjtNum* x, int n, int flg_plus,
|
|||||||
sparse_buf, buf_ind);
|
sparse_buf, buf_ind);
|
||||||
|
|
||||||
// check for size change
|
// check for size change
|
||||||
if (new_nnz!=nnz-1) {
|
if (new_nnz != nnz-1) {
|
||||||
mju_error("Varying sparsity pattern in mju_cholUpdateSparse");
|
mju_error("Varying sparsity pattern in mju_cholUpdateSparse");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +314,7 @@ mjtNum mju_cholFactorBand(mjtNum* mat, int ntotal, int nband, int ndense,
|
|||||||
mjtNum mindiag = -1;
|
mjtNum mindiag = -1;
|
||||||
|
|
||||||
// sparse part, including sparse-sparse and sparse-dense
|
// sparse part, including sparse-sparse and sparse-dense
|
||||||
for (int j=0; j<nsparse; j++) {
|
for (int j=0; j < nsparse; j++) {
|
||||||
// number of non-zeros left of (j,j)
|
// number of non-zeros left of (j,j)
|
||||||
int width_jj = mjMIN(j, nband-1);
|
int width_jj = mjMIN(j, nband-1);
|
||||||
|
|
||||||
@@ -325,16 +325,16 @@ mjtNum mju_cholFactorBand(mjtNum* mat, int ntotal, int nband, int ndense,
|
|||||||
int adr_jj = (j+1)*nband-1;
|
int adr_jj = (j+1)*nband-1;
|
||||||
|
|
||||||
// compute L(j,j), before sqrt
|
// compute L(j,j), before sqrt
|
||||||
mjtNum left_ij = width_jj>0 ? mju_dot(mat+adr_jj-width_jj, mat+adr_jj-width_jj, width_jj) : 0;
|
mjtNum left_ij = width_jj > 0 ? mju_dot(mat+adr_jj-width_jj, mat+adr_jj-width_jj, width_jj) : 0;
|
||||||
mjtNum Ljj = diagadd + diagmul*mat[adr_jj] + mat[adr_jj] - left_ij;
|
mjtNum Ljj = diagadd + diagmul*mat[adr_jj] + mat[adr_jj] - left_ij;
|
||||||
|
|
||||||
// update mindiag
|
// update mindiag
|
||||||
if (Ljj<mindiag || mindiag<0) {
|
if (Ljj < mindiag || mindiag < 0) {
|
||||||
mindiag = Ljj;
|
mindiag = Ljj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop if rank-deficient
|
// stop if rank-deficient
|
||||||
if (Ljj<mjMINVAL) {
|
if (Ljj < mjMINVAL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +343,7 @@ mjtNum mju_cholFactorBand(mjtNum* mat, int ntotal, int nband, int ndense,
|
|||||||
mjtNum scale = 1/Ljj;
|
mjtNum scale = 1/Ljj;
|
||||||
|
|
||||||
// compute L(i,j) for i>j, sparse part
|
// compute L(i,j) for i>j, sparse part
|
||||||
for (int i=j+1; i<=j+height; i++) {
|
for (int i=j+1; i <= j+height; i++) {
|
||||||
// number of non-zeros left of (i,j)
|
// number of non-zeros left of (i,j)
|
||||||
int width_ij = mjMIN(j, nband-1-i+j);
|
int width_ij = mjMIN(j, nband-1-i+j);
|
||||||
|
|
||||||
@@ -351,18 +351,18 @@ mjtNum mju_cholFactorBand(mjtNum* mat, int ntotal, int nband, int ndense,
|
|||||||
int adr_ij = (i+1)*nband-1-i+j;
|
int adr_ij = (i+1)*nband-1-i+j;
|
||||||
|
|
||||||
// in-place computation of L(i,j)
|
// in-place computation of L(i,j)
|
||||||
left_ij = width_ij>0 ? mju_dot(mat+adr_jj-width_ij, mat+adr_ij-width_ij, width_ij) : 0;
|
left_ij = width_ij > 0 ? mju_dot(mat+adr_jj-width_ij, mat+adr_ij-width_ij, width_ij) : 0;
|
||||||
mat[adr_ij] = scale * (mat[adr_ij] - left_ij);
|
mat[adr_ij] = scale * (mat[adr_ij] - left_ij);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute L(i,j) for i>j, dense part
|
// compute L(i,j) for i>j, dense part
|
||||||
for (int i=nsparse; i<ntotal; i++) {
|
for (int i=nsparse; i < ntotal; i++) {
|
||||||
// address of (i,j)
|
// address of (i,j)
|
||||||
int adr_ij = nsparse*nband + (i-nsparse)*ntotal + j;
|
int adr_ij = nsparse*nband + (i-nsparse)*ntotal + j;
|
||||||
|
|
||||||
// in-place computation of L(i,j)
|
// in-place computation of L(i,j)
|
||||||
// number of non-zeros left of (i,j) now equals width_jj
|
// number of non-zeros left of (i,j) now equals width_jj
|
||||||
left_ij = width_jj>0 ? mju_dot(mat+adr_jj-width_jj, mat+adr_ij-width_jj, width_jj) : 0;
|
left_ij = width_jj > 0 ? mju_dot(mat+adr_jj-width_jj, mat+adr_ij-width_jj, width_jj) : 0;
|
||||||
mat[adr_ij] = scale * (mat[adr_ij] - left_ij);
|
mat[adr_ij] = scale * (mat[adr_ij] - left_ij);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,7 +371,7 @@ mjtNum mju_cholFactorBand(mjtNum* mat, int ntotal, int nband, int ndense,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dense part
|
// dense part
|
||||||
for (int j=nsparse; j<ntotal; j++) {
|
for (int j=nsparse; j < ntotal; j++) {
|
||||||
// address of (j,j)
|
// address of (j,j)
|
||||||
int adr_jj = nsparse*nband + (j-nsparse)*ntotal + j;
|
int adr_jj = nsparse*nband + (j-nsparse)*ntotal + j;
|
||||||
|
|
||||||
@@ -380,12 +380,12 @@ mjtNum mju_cholFactorBand(mjtNum* mat, int ntotal, int nband, int ndense,
|
|||||||
mju_dot(mat+adr_jj-j, mat+adr_jj-j, j);
|
mju_dot(mat+adr_jj-j, mat+adr_jj-j, j);
|
||||||
|
|
||||||
// update mindiag
|
// update mindiag
|
||||||
if (Ljj<mindiag || mindiag<0) {
|
if (Ljj < mindiag || mindiag < 0) {
|
||||||
mindiag = Ljj;
|
mindiag = Ljj;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop if rank-deficient
|
// stop if rank-deficient
|
||||||
if (Ljj<mjMINVAL) {
|
if (Ljj < mjMINVAL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +394,7 @@ mjtNum mju_cholFactorBand(mjtNum* mat, int ntotal, int nband, int ndense,
|
|||||||
mjtNum scale = 1/Ljj;
|
mjtNum scale = 1/Ljj;
|
||||||
|
|
||||||
// compute L(i,j) for i>j
|
// compute L(i,j) for i>j
|
||||||
for (int i=j+1; i<ntotal; i++) {
|
for (int i=j+1; i < ntotal; i++) {
|
||||||
// address of off-diagonal element
|
// address of off-diagonal element
|
||||||
int adr_ij = adr_jj + ntotal*(i-j);
|
int adr_ij = adr_jj + ntotal*(i-j);
|
||||||
|
|
||||||
@@ -417,14 +417,14 @@ void mju_cholSolveBand(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
|
|||||||
int width, height, nsparse = ntotal - ndense;
|
int width, height, nsparse = ntotal - ndense;
|
||||||
|
|
||||||
// copy into result if different
|
// copy into result if different
|
||||||
if (res!=vec) {
|
if (res != vec) {
|
||||||
mju_copy(res, vec, ntotal);
|
mju_copy(res, vec, ntotal);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------- forward substitution: solve L*res = vec
|
//------- forward substitution: solve L*res = vec
|
||||||
|
|
||||||
// sparse part
|
// sparse part
|
||||||
for (int i=0; i<nsparse; i++) {
|
for (int i=0; i < nsparse; i++) {
|
||||||
// number of non-zeros left of (i,i)
|
// number of non-zeros left of (i,i)
|
||||||
width = mjMIN(i, nband-1);
|
width = mjMIN(i, nband-1);
|
||||||
|
|
||||||
@@ -437,7 +437,7 @@ void mju_cholSolveBand(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dense part
|
// dense part
|
||||||
for (int i=nsparse; i<ntotal; i++) {
|
for (int i=nsparse; i < ntotal; i++) {
|
||||||
res[i] -= mju_dot(mat+nsparse*nband+(i-nsparse)*ntotal, res, i);
|
res[i] -= mju_dot(mat+nsparse*nband+(i-nsparse)*ntotal, res, i);
|
||||||
|
|
||||||
// diagonal
|
// diagonal
|
||||||
@@ -447,8 +447,8 @@ void mju_cholSolveBand(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
|
|||||||
//------- backward substitution: solve L'*res = res
|
//------- backward substitution: solve L'*res = res
|
||||||
|
|
||||||
// dense part
|
// dense part
|
||||||
for (int i=ntotal-1; i>=nsparse; i--) {
|
for (int i=ntotal-1; i >= nsparse; i--) {
|
||||||
for (int j=i+1; j<ntotal; j++) {
|
for (int j=i+1; j < ntotal; j++) {
|
||||||
res[i] -= mat[nsparse*nband+(j-nsparse)*ntotal+i] * res[j];
|
res[i] -= mat[nsparse*nband+(j-nsparse)*ntotal+i] * res[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,16 +457,16 @@ void mju_cholSolveBand(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sparse part
|
// sparse part
|
||||||
for (int i=nsparse-1; i>=0; i--) {
|
for (int i=nsparse-1; i >= 0; i--) {
|
||||||
// number of non-zeros below (i,i), sparse part
|
// number of non-zeros below (i,i), sparse part
|
||||||
height = mjMIN(nsparse-1-i, nband-1);
|
height = mjMIN(nsparse-1-i, nband-1);
|
||||||
|
|
||||||
// sparse rows
|
// sparse rows
|
||||||
for (int j=i+1; j<=i+height; j++)
|
for (int j=i+1; j <= i+height; j++)
|
||||||
res[i] -= mat[(j+1)*nband-1-(j-i)] * res[j];
|
res[i] -= mat[(j+1)*nband-1-(j-i)] * res[j];
|
||||||
|
|
||||||
// dense rows
|
// dense rows
|
||||||
for (int j=nsparse; j<ntotal; j++)
|
for (int j=nsparse; j < ntotal; j++)
|
||||||
res[i] -= mat[nsparse*nband+(j-nsparse)*ntotal+i] * res[j];
|
res[i] -= mat[nsparse*nband+(j-nsparse)*ntotal+i] * res[j];
|
||||||
|
|
||||||
// diagonal
|
// diagonal
|
||||||
@@ -481,7 +481,7 @@ int mju_bandDiag(int i, int ntotal, int nband, int ndense) {
|
|||||||
int nsparse = ntotal-ndense;
|
int nsparse = ntotal-ndense;
|
||||||
|
|
||||||
// sparse part
|
// sparse part
|
||||||
if (i<nsparse) {
|
if (i < nsparse) {
|
||||||
return i*nband + nband-1;
|
return i*nband + nband-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,7 +502,7 @@ void mju_band2Dense(mjtNum* res, const mjtNum* mat, int ntotal, int nband, int n
|
|||||||
mju_zero(res, ntotal*ntotal);
|
mju_zero(res, ntotal*ntotal);
|
||||||
|
|
||||||
// sparse part
|
// sparse part
|
||||||
for(int i=0; i<nsparse; i++) {
|
for(int i=0; i < nsparse; i++) {
|
||||||
// number of non-zeros left of (i,i)
|
// number of non-zeros left of (i,i)
|
||||||
int width = mjMIN(i, nband-1);
|
int width = mjMIN(i, nband-1);
|
||||||
|
|
||||||
@@ -511,14 +511,14 @@ void mju_band2Dense(mjtNum* res, const mjtNum* mat, int ntotal, int nband, int n
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dense part
|
// dense part
|
||||||
for(int i=nsparse; i<ntotal; i++) {
|
for(int i=nsparse; i < ntotal; i++) {
|
||||||
mju_copy(res + i*ntotal, mat + nsparse*nband + (i-nsparse)*ntotal, i+1);
|
mju_copy(res + i*ntotal, mat + nsparse*nband + (i-nsparse)*ntotal, i+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make symmetric
|
// make symmetric
|
||||||
if (flg_sym) {
|
if (flg_sym) {
|
||||||
for(int i=0; i<ntotal; i++) {
|
for(int i=0; i < ntotal; i++) {
|
||||||
for (int j=i+1; j<ntotal; j++) {
|
for (int j=i+1; j < ntotal; j++) {
|
||||||
res[i*ntotal + j] = res[j*ntotal + i];
|
res[i*ntotal + j] = res[j*ntotal + i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -532,7 +532,7 @@ void mju_dense2Band(mjtNum* res, const mjtNum* mat, int ntotal, int nband, int n
|
|||||||
int nsparse = ntotal-ndense;
|
int nsparse = ntotal-ndense;
|
||||||
|
|
||||||
// sparse part
|
// sparse part
|
||||||
for(int i=0; i<nsparse; i++) {
|
for(int i=0; i < nsparse; i++) {
|
||||||
// number of non-zeros left of (i,i)
|
// number of non-zeros left of (i,i)
|
||||||
int width = mjMIN(i, nband-1);
|
int width = mjMIN(i, nband-1);
|
||||||
|
|
||||||
@@ -541,7 +541,7 @@ void mju_dense2Band(mjtNum* res, const mjtNum* mat, int ntotal, int nband, int n
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dense part
|
// dense part
|
||||||
for(int i=nsparse; i<ntotal; i++) {
|
for(int i=nsparse; i < ntotal; i++) {
|
||||||
mju_copy(res + nsparse*nband + (i-nsparse)*ntotal, mat + i*ntotal, i+1);
|
mju_copy(res + nsparse*nband + (i-nsparse)*ntotal, mat + i*ntotal, i+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -554,13 +554,13 @@ void mju_bandMulMatVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
|
|||||||
int nsparse = ntotal-ndense;
|
int nsparse = ntotal-ndense;
|
||||||
|
|
||||||
// handle multiple vectors
|
// handle multiple vectors
|
||||||
for(int j=0; j<nvec; j++ ) {
|
for(int j=0; j < nvec; j++ ) {
|
||||||
// precompute pointer to corresponding vector in vec and res
|
// precompute pointer to corresponding vector in vec and res
|
||||||
const mjtNum* vec_j = vec + ntotal*j;
|
const mjtNum* vec_j = vec + ntotal*j;
|
||||||
mjtNum* res_j = res + ntotal*j;
|
mjtNum* res_j = res + ntotal*j;
|
||||||
|
|
||||||
// sparse part
|
// sparse part
|
||||||
for(int i=0; i<nsparse; i++) {
|
for(int i=0; i < nsparse; i++) {
|
||||||
int width = mjMIN(i+1, nband);
|
int width = mjMIN(i+1, nband);
|
||||||
int adr = i*nband + nband - width;
|
int adr = i*nband + nband - width;
|
||||||
int offset = mjMAX(0, i-nband+1);
|
int offset = mjMAX(0, i-nband+1);
|
||||||
@@ -572,7 +572,7 @@ void mju_bandMulMatVec(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dense part
|
// dense part
|
||||||
for(int i=nsparse; i<ntotal; i++) {
|
for(int i=nsparse; i < ntotal; i++) {
|
||||||
int adr = nsparse*nband + (i-nsparse)*ntotal;
|
int adr = nsparse*nband + (i-nsparse)*ntotal;
|
||||||
res_j[i] = mju_dot(mat+adr, vec_j, i+1);
|
res_j[i] = mju_dot(mat+adr, vec_j, i+1);
|
||||||
if (flg_sym) {
|
if (flg_sym) {
|
||||||
@@ -596,28 +596,28 @@ void mju_factorLUSparse(mjtNum* LU, int n, int* scratch,
|
|||||||
memcpy(remaining, rownnz, n*sizeof(int));
|
memcpy(remaining, rownnz, n*sizeof(int));
|
||||||
|
|
||||||
// diagonal elements (i,i)
|
// diagonal elements (i,i)
|
||||||
for (int i=n-1; i>=0; i--) {
|
for (int i=n-1; i >= 0; i--) {
|
||||||
// get address of last remaining element of row i, adjust remaining counter
|
// get address of last remaining element of row i, adjust remaining counter
|
||||||
int ii = rowadr[i] + remaining[i] - 1;
|
int ii = rowadr[i] + remaining[i] - 1;
|
||||||
remaining[i]--;
|
remaining[i]--;
|
||||||
|
|
||||||
// make sure ii is on diagonal
|
// make sure ii is on diagonal
|
||||||
if (colind[ii]!=i) {
|
if (colind[ii] != i) {
|
||||||
mju_error("missing diagonal element in mju_factorLUSparse");
|
mju_error("missing diagonal element in mju_factorLUSparse");
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure diagonal is not too small
|
// make sure diagonal is not too small
|
||||||
if (mju_abs(LU[ii])<mjMINVAL) {
|
if (mju_abs(LU[ii]) < mjMINVAL) {
|
||||||
mju_error("diagonal element too small in mju_factorLUSparse");
|
mju_error("diagonal element too small in mju_factorLUSparse");
|
||||||
}
|
}
|
||||||
|
|
||||||
// rows j above i
|
// rows j above i
|
||||||
for (int j=i-1; j>=0; j--) {
|
for (int j=i-1; j >= 0; j--) {
|
||||||
// get address of last remaining element of row j
|
// get address of last remaining element of row j
|
||||||
int ji = rowadr[j] + remaining[j] - 1;
|
int ji = rowadr[j] + remaining[j] - 1;
|
||||||
|
|
||||||
// process row j if (j,i) is non-zero
|
// process row j if (j,i) is non-zero
|
||||||
if (colind[ji]==i) {
|
if (colind[ji] == i) {
|
||||||
// adjust remaining counter
|
// adjust remaining counter
|
||||||
remaining[j]--;
|
remaining[j]--;
|
||||||
|
|
||||||
@@ -627,15 +627,15 @@ void mju_factorLUSparse(mjtNum* LU, int n, int* scratch,
|
|||||||
|
|
||||||
// (j,k) = (j,k) - (i,k) * (j,i) for k<i; handle incompatible sparsity
|
// (j,k) = (j,k) - (i,k) * (j,i) for k<i; handle incompatible sparsity
|
||||||
int icnt = rowadr[i], jcnt = rowadr[j];
|
int icnt = rowadr[i], jcnt = rowadr[j];
|
||||||
while (jcnt<rowadr[j]+remaining[j]) {
|
while (jcnt < rowadr[j]+remaining[j]) {
|
||||||
// both non-zero
|
// both non-zero
|
||||||
if (colind[icnt]==colind[jcnt]) {
|
if (colind[icnt] == colind[jcnt]) {
|
||||||
// update LU, advance counters
|
// update LU, advance counters
|
||||||
LU[jcnt++] -= LU[icnt++] * LUji;
|
LU[jcnt++] -= LU[icnt++] * LUji;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only (j,k) non-zero
|
// only (j,k) non-zero
|
||||||
else if (colind[icnt]>colind[jcnt]) {
|
else if (colind[icnt] > colind[jcnt]) {
|
||||||
// advance j counter
|
// advance j counter
|
||||||
jcnt++;
|
jcnt++;
|
||||||
}
|
}
|
||||||
@@ -647,7 +647,7 @@ void mju_factorLUSparse(mjtNum* LU, int n, int* scratch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make sure both rows fully processed
|
// make sure both rows fully processed
|
||||||
if (icnt!=rowadr[i]+remaining[i] || jcnt!=rowadr[j]+remaining[j]) {
|
if (icnt != rowadr[i]+remaining[i] || jcnt != rowadr[j]+remaining[j]) {
|
||||||
mju_error("row processing incomplete in mju_factorLUSparse");
|
mju_error("row processing incomplete in mju_factorLUSparse");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -655,8 +655,8 @@ void mju_factorLUSparse(mjtNum* LU, int n, int* scratch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make sure remaining points to diagonal
|
// make sure remaining points to diagonal
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
if (remaining[i]<0 || colind[rowadr[i]+remaining[i]]!=i) {
|
if (remaining[i] < 0 || colind[rowadr[i]+remaining[i]] != i) {
|
||||||
mju_error("unexpected sparse matrix structure in mju_factorLUSparse");
|
mju_error("unexpected sparse matrix structure in mju_factorLUSparse");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -668,28 +668,28 @@ void mju_factorLUSparse(mjtNum* LU, int n, int* scratch,
|
|||||||
void mju_solveLUSparse(mjtNum* res, const mjtNum* LU, const mjtNum* vec, int n,
|
void mju_solveLUSparse(mjtNum* res, const mjtNum* LU, const mjtNum* vec, int n,
|
||||||
const int* rownnz, const int* rowadr, const int* colind) {
|
const int* rownnz, const int* rowadr, const int* colind) {
|
||||||
//------------------ solve (U+I)*res = vec
|
//------------------ solve (U+I)*res = vec
|
||||||
for (int i=n-1; i>=0; i--) {
|
for (int i=n-1; i >= 0; i--) {
|
||||||
// init: diagonal of (U+I) is 1
|
// init: diagonal of (U+I) is 1
|
||||||
res[i] = vec[i];
|
res[i] = vec[i];
|
||||||
|
|
||||||
// res[i] -= sum_k>i res[k]*LU(i,k)
|
// res[i] -= sum_k>i res[k]*LU(i,k)
|
||||||
int j = rownnz[i] - 1;
|
int j = rownnz[i] - 1;
|
||||||
while (colind[rowadr[i]+j]>i) {
|
while (colind[rowadr[i]+j] > i) {
|
||||||
res[i] -= res[colind[rowadr[i]+j]] * LU[rowadr[i]+j];
|
res[i] -= res[colind[rowadr[i]+j]] * LU[rowadr[i]+j];
|
||||||
j--;
|
j--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure j points to diagonal
|
// make sure j points to diagonal
|
||||||
if (colind[rowadr[i]+j]!=i) {
|
if (colind[rowadr[i]+j] != i) {
|
||||||
mju_error("diagonal of U not reached in mju_factorLUSparse");
|
mju_error("diagonal of U not reached in mju_factorLUSparse");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------ solve L*res(new) = res
|
//------------------ solve L*res(new) = res
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
// res[i] -= sum_k<i res[k]*LU(i,k)
|
// res[i] -= sum_k<i res[k]*LU(i,k)
|
||||||
int j = 0;
|
int j = 0;
|
||||||
while (colind[rowadr[i]+j]<i) {
|
while (colind[rowadr[i]+j] < i) {
|
||||||
res[i] -= res[colind[rowadr[i]+j]] * LU[rowadr[i]+j];
|
res[i] -= res[colind[rowadr[i]+j]] * LU[rowadr[i]+j];
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
@@ -698,7 +698,7 @@ void mju_solveLUSparse(mjtNum* res, const mjtNum* LU, const mjtNum* vec, int n,
|
|||||||
res[i] /= LU[rowadr[i]+j];
|
res[i] /= LU[rowadr[i]+j];
|
||||||
|
|
||||||
// make sure j points to diagonal
|
// make sure j points to diagonal
|
||||||
if (colind[rowadr[i]+j]!=i) {
|
if (colind[rowadr[i]+j] != i) {
|
||||||
mju_error("diagonal of L not reached in mju_factorLUSparse");
|
mju_error("diagonal of L not reached in mju_factorLUSparse");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -720,7 +720,7 @@ int mju_eig3(mjtNum* eigval, mjtNum* eigvec, mjtNum quat[4], const mjtNum mat[9]
|
|||||||
quat[1] = quat[2] = quat[3] = 0;
|
quat[1] = quat[2] = quat[3] = 0;
|
||||||
|
|
||||||
// Jacobi iteration
|
// Jacobi iteration
|
||||||
for (iter=0; iter<500; iter++) {
|
for (iter=0; iter < 500; iter++) {
|
||||||
// make quaternion matrix eigvec, compute D = eigvec'*mat*eigvec
|
// make quaternion matrix eigvec, compute D = eigvec'*mat*eigvec
|
||||||
mju_quat2Mat(eigvec, quat);
|
mju_quat2Mat(eigvec, quat);
|
||||||
mju_mulMatTMat(tmp, eigvec, mat, 3, 3, 3);
|
mju_mulMatTMat(tmp, eigvec, mat, 3, 3, 3);
|
||||||
@@ -732,11 +732,11 @@ int mju_eig3(mjtNum* eigval, mjtNum* eigvec, mjtNum quat[4], const mjtNum mat[9]
|
|||||||
eigval[2] = D[8];
|
eigval[2] = D[8];
|
||||||
|
|
||||||
// find max off-diagonal element, set indices
|
// find max off-diagonal element, set indices
|
||||||
if (fabs(D[1])>fabs(D[2]) && fabs(D[1])>fabs(D[5])) {
|
if (fabs(D[1]) > fabs(D[2]) && fabs(D[1]) > fabs(D[5])) {
|
||||||
rk = 0; // row
|
rk = 0; // row
|
||||||
ck = 1; // column
|
ck = 1; // column
|
||||||
rotk = 2; // rotation axis
|
rotk = 2; // rotation axis
|
||||||
} else if (fabs(D[2])>fabs(D[5])) {
|
} else if (fabs(D[2]) > fabs(D[5])) {
|
||||||
rk = 0;
|
rk = 0;
|
||||||
ck = 2;
|
ck = 2;
|
||||||
rotk = 1;
|
rotk = 1;
|
||||||
@@ -747,13 +747,13 @@ int mju_eig3(mjtNum* eigval, mjtNum* eigvec, mjtNum quat[4], const mjtNum mat[9]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// terminate if max off-diagonal element too small
|
// terminate if max off-diagonal element too small
|
||||||
if (fabs(D[3*rk+ck])<eigEPS) {
|
if (fabs(D[3*rk+ck]) < eigEPS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2x2 symmetric Schur decomposition
|
// 2x2 symmetric Schur decomposition
|
||||||
tau = (D[4*ck]-D[4*rk])/(2*D[3*rk+ck]);
|
tau = (D[4*ck]-D[4*rk])/(2*D[3*rk+ck]);
|
||||||
if (tau>=0) {
|
if (tau >= 0) {
|
||||||
t = 1.0/(tau + mju_sqrt(1 + tau*tau));
|
t = 1.0/(tau + mju_sqrt(1 + tau*tau));
|
||||||
} else {
|
} else {
|
||||||
t = -1.0/(-tau + mju_sqrt(1 + tau*tau));
|
t = -1.0/(-tau + mju_sqrt(1 + tau*tau));
|
||||||
@@ -761,14 +761,14 @@ int mju_eig3(mjtNum* eigval, mjtNum* eigvec, mjtNum quat[4], const mjtNum mat[9]
|
|||||||
c = 1.0/mju_sqrt(1 + t*t);
|
c = 1.0/mju_sqrt(1 + t*t);
|
||||||
|
|
||||||
// terminate if cosine too close to 1
|
// terminate if cosine too close to 1
|
||||||
if (c>1.0-eigEPS) {
|
if (c > 1.0-eigEPS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// express rotation as quaternion
|
// express rotation as quaternion
|
||||||
tmp[1] = tmp[2] = tmp[3] = 0;
|
tmp[1] = tmp[2] = tmp[3] = 0;
|
||||||
tmp[rotk+1] = (tau>=0 ? -mju_sqrt(0.5-0.5*c) : mju_sqrt(0.5-0.5*c));
|
tmp[rotk+1] = (tau >= 0 ? -mju_sqrt(0.5-0.5*c) : mju_sqrt(0.5-0.5*c));
|
||||||
if (rotk==1) {
|
if (rotk == 1) {
|
||||||
tmp[rotk+1] = -tmp[rotk+1];
|
tmp[rotk+1] = -tmp[rotk+1];
|
||||||
}
|
}
|
||||||
tmp[0] = mju_sqrt(1.0 - tmp[rotk+1]*tmp[rotk+1]);
|
tmp[0] = mju_sqrt(1.0 - tmp[rotk+1]*tmp[rotk+1]);
|
||||||
@@ -780,7 +780,7 @@ int mju_eig3(mjtNum* eigval, mjtNum* eigvec, mjtNum quat[4], const mjtNum mat[9]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sort eigenvalues in decreasing order (bubblesort: 0, 1, 0)
|
// sort eigenvalues in decreasing order (bubblesort: 0, 1, 0)
|
||||||
for (int j=0; j<3; j++) {
|
for (int j=0; j < 3; j++) {
|
||||||
int j1 = j%2; // lead index
|
int j1 = j%2; // lead index
|
||||||
|
|
||||||
if (eigval[j1] < eigval[j1+1]) {
|
if (eigval[j1] < eigval[j1+1]) {
|
||||||
@@ -825,12 +825,12 @@ int mju_QCQP2(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
|
|
||||||
// Newton iteration
|
// Newton iteration
|
||||||
la = 0;
|
la = 0;
|
||||||
for (int iter=0; iter<20; iter++) {
|
for (int iter=0; iter < 20; iter++) {
|
||||||
// det(A+la)
|
// det(A+la)
|
||||||
det = (A11+la)*(A22+la) - A12*A12;
|
det = (A11+la)*(A22+la) - A12*A12;
|
||||||
|
|
||||||
// check SPD, with 1e-10 threshold
|
// check SPD, with 1e-10 threshold
|
||||||
if (det<1e-10) {
|
if (det < 1e-10) {
|
||||||
res[0] = 0;
|
res[0] = 0;
|
||||||
res[1] = 0;
|
res[1] = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -850,7 +850,7 @@ int mju_QCQP2(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
val = v1*v1 + v2*v2 - r*r;
|
val = v1*v1 + v2*v2 - r*r;
|
||||||
|
|
||||||
// check for convergence, or initial solution inside constraint set
|
// check for convergence, or initial solution inside constraint set
|
||||||
if (val<1e-10) {
|
if (val < 1e-10) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -859,7 +859,7 @@ int mju_QCQP2(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
|
|
||||||
// compute update, exit if too small
|
// compute update, exit if too small
|
||||||
mjtNum delta = -val/deriv;
|
mjtNum delta = -val/deriv;
|
||||||
if (delta<1e-10) {
|
if (delta < 1e-10) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,7 +871,7 @@ int mju_QCQP2(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
res[0] = v1*d[0];
|
res[0] = v1*d[0];
|
||||||
res[1] = v2*d[1];
|
res[1] = v2*d[1];
|
||||||
|
|
||||||
return (la!=0);
|
return (la != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -897,7 +897,7 @@ int mju_QCQP3(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
|
|
||||||
// Newton iteration
|
// Newton iteration
|
||||||
la = 0;
|
la = 0;
|
||||||
for (int iter=0; iter<20; iter++) {
|
for (int iter=0; iter < 20; iter++) {
|
||||||
// unscaled P
|
// unscaled P
|
||||||
P11 = (A22+la)*(A33+la) - A23*A23;
|
P11 = (A22+la)*(A33+la) - A23*A23;
|
||||||
P22 = (A11+la)*(A33+la) - A13*A13;
|
P22 = (A11+la)*(A33+la) - A13*A13;
|
||||||
@@ -910,7 +910,7 @@ int mju_QCQP3(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
det = (A11+la)*P11 + A12*P12 + A13*P13;
|
det = (A11+la)*P11 + A12*P12 + A13*P13;
|
||||||
|
|
||||||
// check SPD, with 1e-10 threshold
|
// check SPD, with 1e-10 threshold
|
||||||
if (det<1e-10) {
|
if (det < 1e-10) {
|
||||||
res[0] = 0;
|
res[0] = 0;
|
||||||
res[1] = 0;
|
res[1] = 0;
|
||||||
res[2] = 0;
|
res[2] = 0;
|
||||||
@@ -937,7 +937,7 @@ int mju_QCQP3(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
val = v1*v1 + v2*v2 + v3*v3 - r*r;
|
val = v1*v1 + v2*v2 + v3*v3 - r*r;
|
||||||
|
|
||||||
// check for convergence, or initial solution inside constraint set
|
// check for convergence, or initial solution inside constraint set
|
||||||
if (val<1e-10) {
|
if (val < 1e-10) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -947,7 +947,7 @@ int mju_QCQP3(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
|
|
||||||
// compute update, exit if too small
|
// compute update, exit if too small
|
||||||
mjtNum delta = -val/deriv;
|
mjtNum delta = -val/deriv;
|
||||||
if (delta<1e-10) {
|
if (delta < 1e-10) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,7 +960,7 @@ int mju_QCQP3(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
res[1] = v2*d[1];
|
res[1] = v2*d[1];
|
||||||
res[2] = v3*d[2];
|
res[2] = v3*d[2];
|
||||||
|
|
||||||
return (la!=0);
|
return (la != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -974,25 +974,25 @@ int mju_QCQP(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
mjtNum la, val, deriv, tmp[5];
|
mjtNum la, val, deriv, tmp[5];
|
||||||
|
|
||||||
// check size
|
// check size
|
||||||
if (n>5) {
|
if (n > 5) {
|
||||||
mju_error("mju_QCQP supports n up to 5");
|
mju_error("mju_QCQP supports n up to 5");
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale A,b so that constraint becomes x'*x <= r*r
|
// scale A,b so that constraint becomes x'*x <= r*r
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
b[i] = bin[i] * d[i];
|
b[i] = bin[i] * d[i];
|
||||||
|
|
||||||
for (int j=0; j<n; j++) {
|
for (int j=0; j < n; j++) {
|
||||||
A[j+i*n] = Ain[j+i*n] * d[i] * d[j];
|
A[j+i*n] = Ain[j+i*n] * d[i] * d[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Newton iteration
|
// Newton iteration
|
||||||
la = 0;
|
la = 0;
|
||||||
for (int iter=0; iter<20; iter++) {
|
for (int iter=0; iter < 20; iter++) {
|
||||||
// make A+la
|
// make A+la
|
||||||
mju_copy(Ala, A, n*n);
|
mju_copy(Ala, A, n*n);
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
Ala[i*(n+1)] += la;
|
Ala[i*(n+1)] += la;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1010,7 +1010,7 @@ int mju_QCQP(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
val = mju_dot(res, res, n) - r*r;
|
val = mju_dot(res, res, n) - r*r;
|
||||||
|
|
||||||
// check for convergence, or initial solution inside constraint set
|
// check for convergence, or initial solution inside constraint set
|
||||||
if (val<1e-10) {
|
if (val < 1e-10) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1020,7 +1020,7 @@ int mju_QCQP(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
|
|
||||||
// compute update, exit if too small
|
// compute update, exit if too small
|
||||||
mjtNum delta = -val/deriv;
|
mjtNum delta = -val/deriv;
|
||||||
if (delta<1e-10) {
|
if (delta < 1e-10) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1029,11 +1029,11 @@ int mju_QCQP(mjtNum* res, const mjtNum* Ain, const mjtNum* bin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// undo scaling
|
// undo scaling
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i] = res[i] * d[i];
|
res[i] = res[i] * d[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (la!=0);
|
return (la != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1119,7 +1119,7 @@ enum mjtStatusBoxQP {
|
|||||||
// assumes symmetry of mat, ignores upper triangle
|
// assumes symmetry of mat, ignores upper triangle
|
||||||
static mjtNum mulVecMatVecSym(const mjtNum* vec, const mjtNum* mat, int n) {
|
static mjtNum mulVecMatVecSym(const mjtNum* vec, const mjtNum* mat, int n) {
|
||||||
mjtNum res = 0;
|
mjtNum res = 0;
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res += vec[i] * mat[n*i+i] * vec[i]; // diagonal
|
res += vec[i] * mat[n*i+i] * vec[i]; // diagonal
|
||||||
res += 2 * vec[i] * mju_dot(mat+n*i, vec, i); // off-diagonal
|
res += 2 * vec[i] * mju_dot(mat+n*i, vec, i); // off-diagonal
|
||||||
}
|
}
|
||||||
@@ -1150,11 +1150,11 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
mjtNum sdotg, improvement=0, value=0, norm2=0;
|
mjtNum sdotg, improvement=0, value=0, norm2=0;
|
||||||
|
|
||||||
// basic checks
|
// basic checks
|
||||||
if (n<=0) {
|
if (n <= 0) {
|
||||||
mju_error("mju_boxQP: problem size n must be positive");
|
mju_error("mju_boxQP: problem size n must be positive");
|
||||||
}
|
}
|
||||||
if (upper && lower) {
|
if (upper && lower) {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
if (lower[i] >= upper[i]) {
|
if (lower[i] >= upper[i]) {
|
||||||
mju_error("mju_boxQP: upper bounds must be stricly larger than lower bounds");
|
mju_error("mju_boxQP: upper bounds must be stricly larger than lower bounds");
|
||||||
}
|
}
|
||||||
@@ -1200,14 +1200,14 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
}
|
}
|
||||||
|
|
||||||
// full index set (no clamping)
|
// full index set (no clamping)
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
index[i] = i;
|
index[i] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// have bounds: clamp res
|
// have bounds: clamp res
|
||||||
else {
|
else {
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
if (lower) {
|
if (lower) {
|
||||||
res[i] = mju_max(res[i], lower[i]);
|
res[i] = mju_max(res[i], lower[i]);
|
||||||
}
|
}
|
||||||
@@ -1220,7 +1220,7 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
// ------ main loop
|
// ------ main loop
|
||||||
int iter, logptr = 0;
|
int iter, logptr = 0;
|
||||||
mjtNum oldvalue;
|
mjtNum oldvalue;
|
||||||
for (iter=0; iter<maxiter; iter++) {
|
for (iter=0; iter < maxiter; iter++) {
|
||||||
if (status != mjBOXQP_NO_DESCENT) {
|
if (status != mjBOXQP_NO_DESCENT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1236,14 +1236,14 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
mju_addTo(grad, g, n);
|
mju_addTo(grad, g, n);
|
||||||
|
|
||||||
// find clamped dimensions
|
// find clamped dimensions
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
clamped[i] = ( lower && res[i] == lower[i] && grad[i] > 0 ) ||
|
clamped[i] = ( lower && res[i] == lower[i] && grad[i] > 0 ) ||
|
||||||
( upper && res[i] == upper[i] && grad[i] < 0 );
|
( upper && res[i] == upper[i] && grad[i] < 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// build index of free dimensions, count them
|
// build index of free dimensions, count them
|
||||||
nfree = 0;
|
nfree = 0;
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
if (!clamped[i]) {
|
if (!clamped[i]) {
|
||||||
index[nfree++] = i;
|
index[nfree++] = i;
|
||||||
}
|
}
|
||||||
@@ -1258,7 +1258,7 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
// re-factorize if clamped dimensions have changed
|
// re-factorize if clamped dimensions have changed
|
||||||
if (iter) {
|
if (iter) {
|
||||||
factorize = 0;
|
factorize = 0;
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
if (clamped[i] != oldclamped[i]) {
|
if (clamped[i] != oldclamped[i]) {
|
||||||
factorize = 1;
|
factorize = 1;
|
||||||
break;
|
break;
|
||||||
@@ -1267,26 +1267,26 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
}
|
}
|
||||||
|
|
||||||
// save last clamped
|
// save last clamped
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
oldclamped[i] = clamped[i];
|
oldclamped[i] = clamped[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// get search direction: search = g + H_all,clamped * res_clamped
|
// get search direction: search = g + H_all,clamped * res_clamped
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
temp[i] = clamped[i] ? res[i] : 0;
|
temp[i] = clamped[i] ? res[i] : 0;
|
||||||
}
|
}
|
||||||
mju_mulMatVec(search, H, temp, n, n);
|
mju_mulMatVec(search, H, temp, n, n);
|
||||||
mju_addTo(search, g, n);
|
mju_addTo(search, g, n);
|
||||||
|
|
||||||
// search = compress_free(search)
|
// search = compress_free(search)
|
||||||
for (int i=0; i<nfree; i++) {
|
for (int i=0; i < nfree; i++) {
|
||||||
search[i] = search[index[i]];
|
search[i] = search[index[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// R = compress_free(H)
|
// R = compress_free(H)
|
||||||
if (factorize) {
|
if (factorize) {
|
||||||
for (int i=0; i<nfree; i++) {
|
for (int i=0; i < nfree; i++) {
|
||||||
for (int j=0; j<i+1; j++) {
|
for (int j=0; j < i+1; j++) {
|
||||||
R[i*nfree+j] = H[index[i]*n+index[j]];
|
R[i*nfree+j] = H[index[i]*n+index[j]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1307,7 +1307,7 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
|
|
||||||
// search_free = expand_free(-temp) - x_free
|
// search_free = expand_free(-temp) - x_free
|
||||||
mju_zero(search, n);
|
mju_zero(search, n);
|
||||||
for (int i=0; i<nfree; i++) {
|
for (int i=0; i < nfree; i++) {
|
||||||
search[index[i]] = -temp[i] -res[index[i]];
|
search[index[i]] = -temp[i] -res[index[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1315,13 +1315,13 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
|
|
||||||
// squared norm of free gradient
|
// squared norm of free gradient
|
||||||
norm2 = 0;
|
norm2 = 0;
|
||||||
for (int i=0; i<nfree; i++) {
|
for (int i=0; i < nfree; i++) {
|
||||||
mjtNum grad_i = grad[index[i]];
|
mjtNum grad_i = grad[index[i]];
|
||||||
norm2 += grad_i*grad_i;
|
norm2 += grad_i*grad_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// small gradient: minimum found
|
// small gradient: minimum found
|
||||||
if (norm2<mingrad) {
|
if (norm2 < mingrad) {
|
||||||
status = nfree == n ? mjBOXQP_UNBOUNDED : mjBOXQP_TOL_GRAD;
|
status = nfree == n ? mjBOXQP_UNBOUNDED : mjBOXQP_TOL_GRAD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1338,10 +1338,10 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
// candidate = clamp(x + step*search)
|
// candidate = clamp(x + step*search)
|
||||||
mju_scl(candidate, search, step, n);
|
mju_scl(candidate, search, step, n);
|
||||||
mju_addTo(candidate, res, n);
|
mju_addTo(candidate, res, n);
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
if (lower && candidate[i]<lower[i]) {
|
if (lower && candidate[i] < lower[i]) {
|
||||||
candidate[i] = lower[i];
|
candidate[i] = lower[i];
|
||||||
} else if (upper && candidate[i]>upper[i]) {
|
} else if (upper && candidate[i] > upper[i]) {
|
||||||
candidate[i] = upper[i];
|
candidate[i] = upper[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1352,7 +1352,7 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
// increment and break if step is too small
|
// increment and break if step is too small
|
||||||
nstep++;
|
nstep++;
|
||||||
step = step*backtrack;
|
step = step*backtrack;
|
||||||
if (step<minstep) {
|
if (step < minstep) {
|
||||||
status = mjBOXQP_MAX_LS_ITER;
|
status = mjBOXQP_MAX_LS_ITER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1376,7 +1376,7 @@ int mju_boxQPoption(mjtNum* res, mjtNum* R, int* index, // outputs
|
|||||||
}
|
}
|
||||||
|
|
||||||
// max iterations exceeded
|
// max iterations exceeded
|
||||||
if (iter==maxiter) {
|
if (iter == maxiter) {
|
||||||
status = mjBOXQP_MAX_ITER;
|
status = mjBOXQP_MAX_ITER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ mjtNum mju_dotSparse(const mjtNum* vec1, const mjtNum* vec2,
|
|||||||
mjtNum res2 = 0;
|
mjtNum res2 = 0;
|
||||||
mjtNum res3 = 0;
|
mjtNum res3 = 0;
|
||||||
|
|
||||||
for (; i<=n_4; i+=4) {
|
for (; i <= n_4; i+=4) {
|
||||||
res0 += vec1[i+0] * vec2[ind1[i+0]];
|
res0 += vec1[i+0] * vec2[ind1[i+0]];
|
||||||
res1 += vec1[i+1] * vec2[ind1[i+1]];
|
res1 += vec1[i+1] * vec2[ind1[i+1]];
|
||||||
res2 += vec1[i+2] * vec2[ind1[i+2]];
|
res2 += vec1[i+2] * vec2[ind1[i+2]];
|
||||||
@@ -49,7 +49,7 @@ mjtNum mju_dotSparse(const mjtNum* vec1, const mjtNum* vec2,
|
|||||||
res = (res0 + res2) + (res1 + res3);
|
res = (res0 + res2) + (res1 + res3);
|
||||||
|
|
||||||
// scalar part
|
// scalar part
|
||||||
for (; i<nnz1; i++) {
|
for (; i < nnz1; i++) {
|
||||||
res += vec1[i] * vec2[ind1[i]];
|
res += vec1[i] * vec2[ind1[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ void mju_dotSparseX3(mjtNum* res0, mjtNum* res1, mjtNum* res2,
|
|||||||
mjtNum RES1 = 0;
|
mjtNum RES1 = 0;
|
||||||
mjtNum RES2 = 0;
|
mjtNum RES2 = 0;
|
||||||
|
|
||||||
for (; i<nnz1; i++) {
|
for (; i < nnz1; i++) {
|
||||||
mjtNum v2 = vec2[ind1[i]];
|
mjtNum v2 = vec2[ind1[i]];
|
||||||
|
|
||||||
RES0 += vec10[i] * v2;
|
RES0 += vec10[i] * v2;
|
||||||
@@ -102,17 +102,17 @@ mjtNum mju_dotSparse2(const mjtNum* vec1, const mjtNum* vec2,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i1<nnz1 && i2<nnz2) {
|
while (i1 < nnz1 && i2 < nnz2) {
|
||||||
// get current indices
|
// get current indices
|
||||||
int adr1 = ind1[i1], adr2 = ind2[i2];
|
int adr1 = ind1[i1], adr2 = ind2[i2];
|
||||||
|
|
||||||
// match: accumulate result, advance both
|
// match: accumulate result, advance both
|
||||||
if (adr1==adr2) {
|
if (adr1 == adr2) {
|
||||||
res += vec1[i1++] * vec2[i2++];
|
res += vec1[i1++] * vec2[i2++];
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise advance smaller
|
// otherwise advance smaller
|
||||||
else if (adr1<adr2) {
|
else if (adr1 < adr2) {
|
||||||
i1++;
|
i1++;
|
||||||
} else {
|
} else {
|
||||||
i2++;
|
i2++;
|
||||||
@@ -130,13 +130,13 @@ void mju_dense2sparse(mjtNum* res, const mjtNum* mat, int nr, int nc,
|
|||||||
int adr = 0;
|
int adr = 0;
|
||||||
|
|
||||||
// find non-zeros and construct sparse
|
// find non-zeros and construct sparse
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
// init row
|
// init row
|
||||||
rownnz[r] = 0;
|
rownnz[r] = 0;
|
||||||
rowadr[r] = adr;
|
rowadr[r] = adr;
|
||||||
|
|
||||||
// find non-zeros
|
// find non-zeros
|
||||||
for (int c=0; c<nc; c++) {
|
for (int c=0; c < nc; c++) {
|
||||||
if (mat[r*nc+c]) {
|
if (mat[r*nc+c]) {
|
||||||
// record index and count
|
// record index and count
|
||||||
colind[adr] = c;
|
colind[adr] = c;
|
||||||
@@ -158,8 +158,8 @@ void mju_sparse2dense(mjtNum* res, const mjtNum* mat, int nr, int nc,
|
|||||||
mju_zero(res, nr*nc);
|
mju_zero(res, nr*nc);
|
||||||
|
|
||||||
// copy non-zeros
|
// copy non-zeros
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
for (int i=0; i<rownnz[r]; i++) {
|
for (int i=0; i < rownnz[r]; i++) {
|
||||||
res[r*nc + colind[rowadr[r]+i]] = mat[rowadr[r]+i];
|
res[r*nc + colind[rowadr[r]+i]] = mat[rowadr[r]+i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,7 +175,7 @@ void mju_mulMatVecSparse(mjtNum* res, const mjtNum* mat, const mjtNum* vec,
|
|||||||
mju_mulMatVecSparse_avx(res, mat, vec, nr, rownnz, rowadr, colind, rowsuper);
|
mju_mulMatVecSparse_avx(res, mat, vec, nr, rownnz, rowadr, colind, rowsuper);
|
||||||
#else
|
#else
|
||||||
// regular sparse dot-product
|
// regular sparse dot-product
|
||||||
for (int r=0; r<nr; r++) {
|
for (int r=0; r < nr; r++) {
|
||||||
res[r] = mju_dotSparse(mat+rowadr[r], vec, rownnz[r], colind+rowadr[r]);
|
res[r] = mju_dotSparse(mat+rowadr[r], vec, rownnz[r], colind+rowadr[r]);
|
||||||
}
|
}
|
||||||
#endif // mjUSEAVX
|
#endif // mjUSEAVX
|
||||||
@@ -188,7 +188,7 @@ static void mju_addToSclScl(mjtNum* res, const mjtNum* vec, mjtNum scl1, mjtNum
|
|||||||
#ifdef mjUSEAVX
|
#ifdef mjUSEAVX
|
||||||
mju_addToSclScl_avx(res, vec, scl1, scl2, n);
|
mju_addToSclScl_avx(res, vec, scl1, scl2, n);
|
||||||
#else
|
#else
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
res[i] = res[i]*scl1 + vec[i]*scl2;
|
res[i] = res[i]*scl1 + vec[i]*scl2;
|
||||||
}
|
}
|
||||||
#endif // mjUSEAVX
|
#endif // mjUSEAVX
|
||||||
@@ -212,7 +212,7 @@ int mju_combineSparse(mjtNum* dst, const mjtNum* src, int n, mjtNum a, mjtNum b,
|
|||||||
int dst_nnz, int src_nnz, int* dst_ind, const int* src_ind,
|
int dst_nnz, int src_nnz, int* dst_ind, const int* src_ind,
|
||||||
mjtNum* buf, int* buf_ind) {
|
mjtNum* buf, int* buf_ind) {
|
||||||
// check for identical pattern
|
// check for identical pattern
|
||||||
if (dst_nnz==src_nnz) {
|
if (dst_nnz == src_nnz) {
|
||||||
if (mju_compare(dst_ind, src_ind, dst_nnz)) {
|
if (mju_compare(dst_ind, src_ind, dst_nnz)) {
|
||||||
// combine mjtNum data directly
|
// combine mjtNum data directly
|
||||||
mju_addToSclScl(dst, src, a, b, dst_nnz);
|
mju_addToSclScl(dst, src, a, b, dst_nnz);
|
||||||
@@ -229,26 +229,26 @@ int mju_combineSparse(mjtNum* dst, const mjtNum* src, int n, mjtNum a, mjtNum b,
|
|||||||
// prepare to merge buf and scr into dst
|
// prepare to merge buf and scr into dst
|
||||||
int bi = 0, si = 0, nnz = 0;
|
int bi = 0, si = 0, nnz = 0;
|
||||||
int buf_nnz = dst_nnz;
|
int buf_nnz = dst_nnz;
|
||||||
int badr = bi<buf_nnz ? buf_ind[bi] : n+1;
|
int badr = bi < buf_nnz ? buf_ind[bi] : n+1;
|
||||||
int sadr = si<src_nnz ? src_ind[si] : n+1;
|
int sadr = si < src_nnz ? src_ind[si] : n+1;
|
||||||
|
|
||||||
// merge vectors
|
// merge vectors
|
||||||
while (bi<buf_nnz || si<src_nnz) {
|
while (bi < buf_nnz || si < src_nnz) {
|
||||||
// both
|
// both
|
||||||
if (badr==sadr) {
|
if (badr == sadr) {
|
||||||
dst[nnz] = a*buf[bi++] + b*src[si++];
|
dst[nnz] = a*buf[bi++] + b*src[si++];
|
||||||
dst_ind[nnz++] = badr;
|
dst_ind[nnz++] = badr;
|
||||||
|
|
||||||
badr = bi<buf_nnz ? buf_ind[bi] : n+1;
|
badr = bi < buf_nnz ? buf_ind[bi] : n+1;
|
||||||
sadr = si<src_nnz ? src_ind[si] : n+1;
|
sadr = si < src_nnz ? src_ind[si] : n+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dst only
|
// dst only
|
||||||
else if (badr<sadr) {
|
else if (badr < sadr) {
|
||||||
dst[nnz] = a*buf[bi++];
|
dst[nnz] = a*buf[bi++];
|
||||||
dst_ind[nnz++] = badr;
|
dst_ind[nnz++] = badr;
|
||||||
|
|
||||||
badr = bi<buf_nnz ? buf_ind[bi] : n+1;
|
badr = bi < buf_nnz ? buf_ind[bi] : n+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// src only
|
// src only
|
||||||
@@ -256,7 +256,7 @@ int mju_combineSparse(mjtNum* dst, const mjtNum* src, int n, mjtNum a, mjtNum b,
|
|||||||
dst[nnz] = b*src[si++];
|
dst[nnz] = b*src[si++];
|
||||||
dst_ind[nnz++] = sadr;
|
dst_ind[nnz++] = sadr;
|
||||||
|
|
||||||
sadr = si<src_nnz ? src_ind[si] : n+1;
|
sadr = si < src_nnz ? src_ind[si] : n+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ int mju_combineSparse(mjtNum* dst, const mjtNum* src, int n, mjtNum a, mjtNum b,
|
|||||||
void mju_combineSparseInc(mjtNum* dst, const mjtNum* src, int n, mjtNum a, mjtNum b,
|
void mju_combineSparseInc(mjtNum* dst, const mjtNum* src, int n, mjtNum a, mjtNum b,
|
||||||
int dst_nnz, int src_nnz, int* dst_ind, const int* src_ind) {
|
int dst_nnz, int src_nnz, int* dst_ind, const int* src_ind) {
|
||||||
// check for identical pattern
|
// check for identical pattern
|
||||||
if (dst_nnz==src_nnz) {
|
if (dst_nnz == src_nnz) {
|
||||||
if (mju_compare(dst_ind, src_ind, dst_nnz)) {
|
if (mju_compare(dst_ind, src_ind, dst_nnz)) {
|
||||||
// combine mjtNum data directly
|
// combine mjtNum data directly
|
||||||
mju_addToSclScl(dst, src, a, b, dst_nnz);
|
mju_addToSclScl(dst, src, a, b, dst_nnz);
|
||||||
@@ -278,35 +278,35 @@ void mju_combineSparseInc(mjtNum* dst, const mjtNum* src, int n, mjtNum a, mjtNu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// scale dst by a
|
// scale dst by a
|
||||||
if (a!=1) {
|
if (a != 1) {
|
||||||
mju_scl(dst, dst, a, dst_nnz);
|
mju_scl(dst, dst, a, dst_nnz);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare to merge
|
// prepare to merge
|
||||||
int di = 0, si = 0;
|
int di = 0, si = 0;
|
||||||
int dadr = di<dst_nnz ? dst_ind[di] : n+1;
|
int dadr = di < dst_nnz ? dst_ind[di] : n+1;
|
||||||
int sadr = si<src_nnz ? src_ind[si] : n+1;
|
int sadr = si < src_nnz ? src_ind[si] : n+1;
|
||||||
|
|
||||||
// add src*b at common indices
|
// add src*b at common indices
|
||||||
while (di<dst_nnz) {
|
while (di < dst_nnz) {
|
||||||
// both
|
// both
|
||||||
if (dadr==sadr) {
|
if (dadr == sadr) {
|
||||||
dst[di++] += b*src[si++];
|
dst[di++] += b*src[si++];
|
||||||
|
|
||||||
dadr = di<dst_nnz ? dst_ind[di] : n+1;
|
dadr = di < dst_nnz ? dst_ind[di] : n+1;
|
||||||
sadr = si<src_nnz ? src_ind[si] : n+1;
|
sadr = si < src_nnz ? src_ind[si] : n+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dst only
|
// dst only
|
||||||
else if (dadr<sadr) {
|
else if (dadr < sadr) {
|
||||||
di++;
|
di++;
|
||||||
dadr = di<dst_nnz ? dst_ind[di] : n+1;
|
dadr = di < dst_nnz ? dst_ind[di] : n+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// src only
|
// src only
|
||||||
else {
|
else {
|
||||||
si++;
|
si++;
|
||||||
sadr = si<src_nnz ? src_ind[si] : n+1;
|
sadr = si < src_nnz ? src_ind[si] : n+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,13 +317,13 @@ void mju_combineSparseInc(mjtNum* dst, const mjtNum* src, int n, mjtNum a, mjtNu
|
|||||||
void mju_compressSparse(mjtNum* mat, int nr, int nc, int* rownnz, int* rowadr, int* colind) {
|
void mju_compressSparse(mjtNum* mat, int nr, int nc, int* rownnz, int* rowadr, int* colind) {
|
||||||
rowadr[0] = 0;
|
rowadr[0] = 0;
|
||||||
int adr = rownnz[0];
|
int adr = rownnz[0];
|
||||||
for (int r=1; r<nr; r++) {
|
for (int r=1; r < nr; r++) {
|
||||||
// save old rowadr, record new
|
// save old rowadr, record new
|
||||||
int rowadr1 = rowadr[r];
|
int rowadr1 = rowadr[r];
|
||||||
rowadr[r] = adr;
|
rowadr[r] = adr;
|
||||||
|
|
||||||
// shift mat and mat_colind
|
// shift mat and mat_colind
|
||||||
for (int adr1=rowadr1; adr1<rowadr1+rownnz[r]; adr1++) {
|
for (int adr1=rowadr1; adr1 < rowadr1+rownnz[r]; adr1++) {
|
||||||
mat[adr] = mat[adr1];
|
mat[adr] = mat[adr1];
|
||||||
colind[adr] = colind[adr1];
|
colind[adr] = colind[adr1];
|
||||||
adr++;
|
adr++;
|
||||||
@@ -344,13 +344,13 @@ void mju_transposeSparse(mjtNum* res, const mjtNum* mat, int nr, int nc,
|
|||||||
int nnz = rowadr[nr-1] + rownnz[nr-1];
|
int nnz = rowadr[nr-1] + rownnz[nr-1];
|
||||||
|
|
||||||
// count the number of non-zeros for each row of the transposed matrix
|
// count the number of non-zeros for each row of the transposed matrix
|
||||||
for (int i = 0; i<nnz; i++) {
|
for (int i = 0; i < nnz; i++) {
|
||||||
res_rownnz[colind[i]]++;
|
res_rownnz[colind[i]]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute the row addresses for the transposed matrix
|
// compute the row addresses for the transposed matrix
|
||||||
res_rowadr[0] = 0;
|
res_rowadr[0] = 0;
|
||||||
for (int i = 1; i<nc; i++) {
|
for (int i = 1; i < nc; i++) {
|
||||||
res_rowadr[i] = res_rowadr[i-1] + res_rownnz[i-1];
|
res_rowadr[i] = res_rowadr[i-1] + res_rownnz[i-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,7 +358,7 @@ void mju_transposeSparse(mjtNum* res, const mjtNum* mat, int nr, int nc,
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
// iterate through each non-zero entry of mat
|
// iterate through each non-zero entry of mat
|
||||||
for (int i = 0; i<nnz; i++) {
|
for (int i = 0; i < nnz; i++) {
|
||||||
// iterate to get to the current row (skipping rows with all zeros)
|
// iterate to get to the current row (skipping rows with all zeros)
|
||||||
while ((i-rowadr[r]) >= rownnz[r]) r++;
|
while ((i-rowadr[r]) >= rownnz[r]) r++;
|
||||||
|
|
||||||
@@ -369,7 +369,7 @@ void mju_transposeSparse(mjtNum* res, const mjtNum* mat, int nr, int nc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shift back row addresses
|
// shift back row addresses
|
||||||
for (int i = nc-1; i>0; i--) {
|
for (int i = nc-1; i > 0; i--) {
|
||||||
res_rowadr[i] = res_rowadr[i-1];
|
res_rowadr[i] = res_rowadr[i-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,9 +387,9 @@ void mju_superSparse(int nr, int* rowsuper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find match to child
|
// find match to child
|
||||||
for (int r=0; r<nr-1; r++) {
|
for (int r=0; r < nr-1; r++) {
|
||||||
// different number of nonzeros: cannot be a match
|
// different number of nonzeros: cannot be a match
|
||||||
if (rownnz[r]!=rownnz[r+1]) {
|
if (rownnz[r] != rownnz[r+1]) {
|
||||||
rowsuper[r] = 0;
|
rowsuper[r] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,7 +403,7 @@ void mju_superSparse(int nr, int* rowsuper,
|
|||||||
rowsuper[nr-1] = 0;
|
rowsuper[nr-1] = 0;
|
||||||
|
|
||||||
// accumulate in reverse
|
// accumulate in reverse
|
||||||
for (int r=nr-2; r>=0; r--) {
|
for (int r=nr-2; r >= 0; r--) {
|
||||||
if (rowsuper[r]) {
|
if (rowsuper[r]) {
|
||||||
rowsuper[r] += rowsuper[r+1];
|
rowsuper[r] += rowsuper[r+1];
|
||||||
}
|
}
|
||||||
@@ -424,14 +424,14 @@ void mju_sqrMatTDSparseInit(int* res_rownnz, int* res_rowadr,
|
|||||||
int nchain = 0;
|
int nchain = 0;
|
||||||
int* res_colind = NULL;
|
int* res_colind = NULL;
|
||||||
|
|
||||||
for (int r=0; r<nc; r++) {
|
for (int r=0; r < nc; r++) {
|
||||||
|
|
||||||
// supernode; copy everything to next row
|
// supernode; copy everything to next row
|
||||||
if (rowsuperT && r>0 && rowsuperT[r-1]>0) {
|
if (rowsuperT && r > 0 && rowsuperT[r-1] > 0) {
|
||||||
res_rownnz[r] = res_rownnz[r - 1];
|
res_rownnz[r] = res_rownnz[r - 1];
|
||||||
|
|
||||||
// fill in upper triangle
|
// fill in upper triangle
|
||||||
for (int j=0; j <nchain; j++) {
|
for (int j=0; j < nchain; j++) {
|
||||||
res_rownnz[res_colind[j]]++;
|
res_rownnz[res_colind[j]]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +444,7 @@ void mju_sqrMatTDSparseInit(int* res_rownnz, int* res_rowadr,
|
|||||||
int inew = 0, iold = nc;
|
int inew = 0, iold = nc;
|
||||||
nchain = 0;
|
nchain = 0;
|
||||||
|
|
||||||
for (int i=0; i<rownnzT[r]; i++) {
|
for (int i=0; i < rownnzT[r]; i++) {
|
||||||
int c = colindT[rowadrT[r] + i];
|
int c = colindT[rowadrT[r] + i];
|
||||||
|
|
||||||
int adr = inew;
|
int adr = inew;
|
||||||
@@ -454,15 +454,15 @@ void mju_sqrMatTDSparseInit(int* res_rownnz, int* res_rowadr,
|
|||||||
int nnewchain = 0;
|
int nnewchain = 0;
|
||||||
adr = 0;
|
adr = 0;
|
||||||
int end = rowadr[c] + rownnz[c];
|
int end = rowadr[c] + rownnz[c];
|
||||||
for (int adr1=rowadr[c]; adr1<end; adr1++) {
|
for (int adr1=rowadr[c]; adr1 < end; adr1++) {
|
||||||
int col_mat = colind[adr1];
|
int col_mat = colind[adr1];
|
||||||
while (adr<nchain && chain[iold + adr] < col_mat &&
|
while (adr < nchain && chain[iold + adr] < col_mat &&
|
||||||
chain[iold + adr]<=r) {
|
chain[iold + adr] <= r) {
|
||||||
chain[inew + nnewchain++] = chain[iold + adr++];
|
chain[inew + nnewchain++] = chain[iold + adr++];
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip upper triangle
|
// skip upper triangle
|
||||||
if (col_mat>r) {
|
if (col_mat > r) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,7 +472,7 @@ void mju_sqrMatTDSparseInit(int* res_rownnz, int* res_rowadr,
|
|||||||
chain[inew + nnewchain++] = col_mat;
|
chain[inew + nnewchain++] = col_mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (adr<nchain && chain[iold + adr]<=r) {
|
while (adr < nchain && chain[iold + adr] <= r) {
|
||||||
chain[inew + nnewchain++] = chain[iold + adr++];
|
chain[inew + nnewchain++] = chain[iold + adr++];
|
||||||
}
|
}
|
||||||
nchain = nnewchain;
|
nchain = nnewchain;
|
||||||
@@ -486,11 +486,11 @@ void mju_sqrMatTDSparseInit(int* res_rownnz, int* res_rowadr,
|
|||||||
int nchain_end = nchain;
|
int nchain_end = nchain;
|
||||||
|
|
||||||
// avoid double counting.
|
// avoid double counting.
|
||||||
if (nchain>0 && res_colind[nchain-1]==r) {
|
if (nchain > 0 && res_colind[nchain-1] == r) {
|
||||||
nchain_end = nchain - 1;
|
nchain_end = nchain - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j=0; j<nchain_end; j++) {
|
for (int j=0; j < nchain_end; j++) {
|
||||||
res_rownnz[res_colind[j]]++;
|
res_rownnz[res_colind[j]]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -507,7 +507,7 @@ void mju_sqrMatTDSparseInit(int* res_rownnz, int* res_rowadr,
|
|||||||
|
|
||||||
// precompute res_rowadr for mju_sqrMatTDSparse using uncompressed memory
|
// precompute res_rowadr for mju_sqrMatTDSparse using uncompressed memory
|
||||||
void mju_sqrMatTDUncompressedInit(int* res_rowadr, int nc) {
|
void mju_sqrMatTDUncompressedInit(int* res_rowadr, int nc) {
|
||||||
for (int r=0; r<nc; r++) {
|
for (int r=0; r < nc; r++) {
|
||||||
res_rowadr[r] = r*nc;
|
res_rowadr[r] = r*nc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -534,7 +534,7 @@ void mju_sqrMatTDSparse(mjtNum* res, const mjtNum* mat, const mjtNum* matT,
|
|||||||
// used for when creating the resulting sparse row
|
// used for when creating the resulting sparse row
|
||||||
int* markers = mj_stackAllocInt(d, nc);
|
int* markers = mj_stackAllocInt(d, nc);
|
||||||
|
|
||||||
for (int i=0; i<nc; i++) {
|
for (int i=0; i < nc; i++) {
|
||||||
int* cols = res_colind+res_rowadr[i];
|
int* cols = res_colind+res_rowadr[i];
|
||||||
|
|
||||||
res_rownnz[i] = 0;
|
res_rownnz[i] = 0;
|
||||||
@@ -542,20 +542,20 @@ void mju_sqrMatTDSparse(mjtNum* res, const mjtNum* mat, const mjtNum* matT,
|
|||||||
markers[i] = 0;
|
markers[i] = 0;
|
||||||
|
|
||||||
// if rowsuper, use the previous row sparsity structure
|
// if rowsuper, use the previous row sparsity structure
|
||||||
if (rowsuperT && i>0 && rowsuperT[i-1]) {
|
if (rowsuperT && i > 0 && rowsuperT[i-1]) {
|
||||||
res_rownnz[i] = res_rownnz[i-1];
|
res_rownnz[i] = res_rownnz[i-1];
|
||||||
memcpy(cols, res_colind+res_rowadr[i-1], res_rownnz[i]*sizeof(int));
|
memcpy(cols, res_colind+res_rowadr[i-1], res_rownnz[i]*sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate through each row of M'
|
// iterate through each row of M'
|
||||||
int end = rowadrT[i] + rownnzT[i];
|
int end = rowadrT[i] + rownnzT[i];
|
||||||
for (int r = rowadrT[i]; r<end; r++) {
|
for (int r = rowadrT[i]; r < end; r++) {
|
||||||
int t = colindT[r];
|
int t = colindT[r];
|
||||||
mjtNum v = diag ? matT[r] * diag[t] : matT[r];
|
mjtNum v = diag ? matT[r] * diag[t] : matT[r];
|
||||||
for (int c=rowadr[t]; c<rowadr[t]+rownnz[t]; c++) {
|
for (int c=rowadr[t]; c < rowadr[t]+rownnz[t]; c++) {
|
||||||
int cc = colind[c];
|
int cc = colind[c];
|
||||||
// ignore upper triangle
|
// ignore upper triangle
|
||||||
if (cc>i) {
|
if (cc > i) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,16 +566,16 @@ void mju_sqrMatTDSparse(mjtNum* res, const mjtNum* mat, const mjtNum* matT,
|
|||||||
markers[cc] = 1;
|
markers[cc] = 1;
|
||||||
|
|
||||||
// since i is the rightmost column, it can be inserted at the end
|
// since i is the rightmost column, it can be inserted at the end
|
||||||
if (cc==i) {
|
if (cc == i) {
|
||||||
cols[res_rownnz[i]++] = cc;
|
cols[res_rownnz[i]++] = cc;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert col in order via binary search
|
// insert col in order via binary search
|
||||||
int l = 0, h = res_rownnz[i];
|
int l = 0, h = res_rownnz[i];
|
||||||
while (l<h) {
|
while (l < h) {
|
||||||
int m = (l + h) >> 1;
|
int m = (l + h) >> 1;
|
||||||
if (cols[m]<cc) {
|
if (cols[m] < cc) {
|
||||||
l = m + 1;
|
l = m + 1;
|
||||||
} else {
|
} else {
|
||||||
h = m;
|
h = m;
|
||||||
@@ -583,7 +583,7 @@ void mju_sqrMatTDSparse(mjtNum* res, const mjtNum* mat, const mjtNum* matT,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cc is the rightmost column so far, it can be inserted at the end
|
// cc is the rightmost column so far, it can be inserted at the end
|
||||||
if (l==res_rownnz[i]) {
|
if (l == res_rownnz[i]) {
|
||||||
cols[l] = cc;
|
cols[l] = cc;
|
||||||
res_rownnz[i]++;
|
res_rownnz[i]++;
|
||||||
continue;
|
continue;
|
||||||
@@ -591,7 +591,7 @@ void mju_sqrMatTDSparse(mjtNum* res, const mjtNum* mat, const mjtNum* matT,
|
|||||||
|
|
||||||
// move the cols to the right
|
// move the cols to the right
|
||||||
h = res_rownnz[i];
|
h = res_rownnz[i];
|
||||||
while (l<h) {
|
while (l < h) {
|
||||||
cols[h] = cols[h-1];
|
cols[h] = cols[h-1];
|
||||||
h--;
|
h--;
|
||||||
}
|
}
|
||||||
@@ -607,13 +607,13 @@ void mju_sqrMatTDSparse(mjtNum* res, const mjtNum* mat, const mjtNum* matT,
|
|||||||
|
|
||||||
// rowsuperT: reuse sparsity, copy into res
|
// rowsuperT: reuse sparsity, copy into res
|
||||||
if (rowsuperT && rowsuperT[i]) {
|
if (rowsuperT && rowsuperT[i]) {
|
||||||
for (int r=0; r<end; r++) {
|
for (int r=0; r < end; r++) {
|
||||||
res[res_rowadr[i] + r] = buffer[cols[r]];
|
res[res_rowadr[i] + r] = buffer[cols[r]];
|
||||||
buffer[cols[r]] = 0;
|
buffer[cols[r]] = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// clear out buffers since sparsity cannot be reused
|
// clear out buffers since sparsity cannot be reused
|
||||||
for (int r=0; r<end; r++) {
|
for (int r=0; r < end; r++) {
|
||||||
int cc = cols[r];
|
int cc = cols[r];
|
||||||
res[res_rowadr[i] + r] = buffer[cc];
|
res[res_rowadr[i] + r] = buffer[cc];
|
||||||
res_colind[res_rowadr[i] + r] = cc;
|
res_colind[res_rowadr[i] + r] = cc;
|
||||||
@@ -625,9 +625,9 @@ void mju_sqrMatTDSparse(mjtNum* res, const mjtNum* mat, const mjtNum* matT,
|
|||||||
|
|
||||||
|
|
||||||
// fill upper triangle
|
// fill upper triangle
|
||||||
for (int i=0; i<nc; i++) {
|
for (int i=0; i < nc; i++) {
|
||||||
int end = res_rowadr[i] + res_rownnz[i] - 1;
|
int end = res_rowadr[i] + res_rownnz[i] - 1;
|
||||||
for (int j=res_rowadr[i]; j<end; j++) {
|
for (int j=res_rowadr[i]; j < end; j++) {
|
||||||
int adr = res_rowadr[res_colind[j]] + res_rownnz[res_colind[j]]++;
|
int adr = res_rowadr[res_colind[j]] + res_rownnz[res_colind[j]]++;
|
||||||
res[adr] = res[j];
|
res[adr] = res[j];
|
||||||
res_colind[adr] = i;
|
res_colind[adr] = i;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
// rotate vector by quaternion
|
// rotate vector by quaternion
|
||||||
void mju_rotVecQuat(mjtNum res[3], const mjtNum vec[3], const mjtNum quat[4]) {
|
void mju_rotVecQuat(mjtNum res[3], const mjtNum vec[3], const mjtNum quat[4]) {
|
||||||
// null quat: copy vec
|
// null quat: copy vec
|
||||||
if (quat[0]==1 && quat[1]==0 && quat[2]==0 && quat[3]==0) {
|
if (quat[0] == 1 && quat[1] == 0 && quat[2] == 0 && quat[3] == 0) {
|
||||||
mju_copy3(res, vec);
|
mju_copy3(res, vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ void mju_mulQuat(mjtNum res[4], const mjtNum qa[4], const mjtNum qb[4]) {
|
|||||||
// multiply quaternion and axis
|
// multiply quaternion and axis
|
||||||
void mju_mulQuatAxis(mjtNum res[4], const mjtNum quat[4], const mjtNum axis[3]) {
|
void mju_mulQuatAxis(mjtNum res[4], const mjtNum quat[4], const mjtNum axis[3]) {
|
||||||
mjtNum tmp[4] = {
|
mjtNum tmp[4] = {
|
||||||
-quat[1]*axis[0] - quat[2]*axis[1] - quat[3]*axis[2],
|
-quat[1]*axis[0] - quat[2]*axis[1] - quat[3]*axis[2],
|
||||||
quat[0]*axis[0] + quat[2]*axis[2] - quat[3]*axis[1],
|
quat[0]*axis[0] + quat[2]*axis[2] - quat[3]*axis[1],
|
||||||
quat[0]*axis[1] + quat[3]*axis[0] - quat[1]*axis[2],
|
quat[0]*axis[1] + quat[3]*axis[0] - quat[1]*axis[2],
|
||||||
quat[0]*axis[2] + quat[1]*axis[1] - quat[2]*axis[0]
|
quat[0]*axis[2] + quat[1]*axis[1] - quat[2]*axis[0]
|
||||||
@@ -91,7 +91,7 @@ void mju_mulQuatAxis(mjtNum res[4], const mjtNum quat[4], const mjtNum axis[3])
|
|||||||
// convert axisAngle to quaternion
|
// convert axisAngle to quaternion
|
||||||
void mju_axisAngle2Quat(mjtNum res[4], const mjtNum axis[3], mjtNum angle) {
|
void mju_axisAngle2Quat(mjtNum res[4], const mjtNum axis[3], mjtNum angle) {
|
||||||
// zero angle: null quat
|
// zero angle: null quat
|
||||||
if (angle==0) {
|
if (angle == 0) {
|
||||||
res[0] = 1;
|
res[0] = 1;
|
||||||
res[1] = 0;
|
res[1] = 0;
|
||||||
res[2] = 0;
|
res[2] = 0;
|
||||||
@@ -117,7 +117,7 @@ void mju_quat2Vel(mjtNum res[3], const mjtNum quat[4], mjtNum dt) {
|
|||||||
mjtNum speed = 2 * mju_atan2(sin_a_2, quat[0]);
|
mjtNum speed = 2 * mju_atan2(sin_a_2, quat[0]);
|
||||||
|
|
||||||
// when axis-angle is larger than pi, rotation is in the opposite direction
|
// when axis-angle is larger than pi, rotation is in the opposite direction
|
||||||
if (speed>mjPI) {
|
if (speed > mjPI) {
|
||||||
speed -= 2*mjPI;
|
speed -= 2*mjPI;
|
||||||
}
|
}
|
||||||
speed /= dt;
|
speed /= dt;
|
||||||
@@ -143,7 +143,7 @@ void mju_subQuat(mjtNum res[3], const mjtNum qa[4], const mjtNum qb[4]) {
|
|||||||
// convert quaternion to 3D rotation matrix
|
// convert quaternion to 3D rotation matrix
|
||||||
void mju_quat2Mat(mjtNum res[9], const mjtNum quat[4]) {
|
void mju_quat2Mat(mjtNum res[9], const mjtNum quat[4]) {
|
||||||
// null quat: identity
|
// null quat: identity
|
||||||
if (quat[0]==1 && quat[1]==0 && quat[2]==0 && quat[3]==0) {
|
if (quat[0] == 1 && quat[1] == 0 && quat[2] == 0 && quat[3] == 0) {
|
||||||
res[0] = 1;
|
res[0] = 1;
|
||||||
res[1] = 0;
|
res[1] = 0;
|
||||||
res[2] = 0;
|
res[2] = 0;
|
||||||
@@ -186,7 +186,7 @@ void mju_quat2Mat(mjtNum res[9], const mjtNum quat[4]) {
|
|||||||
// convert 3D rotation matrix to quaternion
|
// convert 3D rotation matrix to quaternion
|
||||||
void mju_mat2Quat(mjtNum quat[4], const mjtNum mat[9]) {
|
void mju_mat2Quat(mjtNum quat[4], const mjtNum mat[9]) {
|
||||||
// q0 largest
|
// q0 largest
|
||||||
if (mat[0]+mat[4]+mat[8]>0) {
|
if (mat[0]+mat[4]+mat[8] > 0) {
|
||||||
quat[0] = 0.5 * mju_sqrt(1 + mat[0] + mat[4] + mat[8]);
|
quat[0] = 0.5 * mju_sqrt(1 + mat[0] + mat[4] + mat[8]);
|
||||||
quat[1] = 0.25 * (mat[7] - mat[5]) / quat[0];
|
quat[1] = 0.25 * (mat[7] - mat[5]) / quat[0];
|
||||||
quat[2] = 0.25 * (mat[2] - mat[6]) / quat[0];
|
quat[2] = 0.25 * (mat[2] - mat[6]) / quat[0];
|
||||||
@@ -194,7 +194,7 @@ void mju_mat2Quat(mjtNum quat[4], const mjtNum mat[9]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// q1 largest
|
// q1 largest
|
||||||
else if (mat[0]>mat[4] && mat[0]>mat[8]) {
|
else if (mat[0] > mat[4] && mat[0] > mat[8]) {
|
||||||
quat[1] = 0.5 * mju_sqrt(1 + mat[0] - mat[4] - mat[8]);
|
quat[1] = 0.5 * mju_sqrt(1 + mat[0] - mat[4] - mat[8]);
|
||||||
quat[0] = 0.25 * (mat[7] - mat[5]) / quat[1];
|
quat[0] = 0.25 * (mat[7] - mat[5]) / quat[1];
|
||||||
quat[2] = 0.25 * (mat[1] + mat[3]) / quat[1];
|
quat[2] = 0.25 * (mat[1] + mat[3]) / quat[1];
|
||||||
@@ -202,7 +202,7 @@ void mju_mat2Quat(mjtNum quat[4], const mjtNum mat[9]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// q2 largest
|
// q2 largest
|
||||||
else if (mat[4]>mat[8]) {
|
else if (mat[4] > mat[8]) {
|
||||||
quat[2] = 0.5 * mju_sqrt(1 - mat[0] + mat[4] - mat[8]);
|
quat[2] = 0.5 * mju_sqrt(1 - mat[0] + mat[4] - mat[8]);
|
||||||
quat[0] = 0.25 * (mat[2] - mat[6]) / quat[2];
|
quat[0] = 0.25 * (mat[2] - mat[6]) / quat[2];
|
||||||
quat[1] = 0.25 * (mat[1] + mat[3]) / quat[2];
|
quat[1] = 0.25 * (mat[1] + mat[3]) / quat[2];
|
||||||
@@ -255,7 +255,7 @@ void mju_quatZ2Vec(mjtNum quat[4], const mjtNum vec[3]) {
|
|||||||
mju_zero3(quat+1);
|
mju_zero3(quat+1);
|
||||||
|
|
||||||
// normalize vector; if too small, no rotation
|
// normalize vector; if too small, no rotation
|
||||||
if (mju_normalize3(vn)<mjMINVAL) {
|
if (mju_normalize3(vn) < mjMINVAL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ void mju_quatZ2Vec(mjtNum quat[4], const mjtNum vec[3]) {
|
|||||||
a = mju_normalize3(axis);
|
a = mju_normalize3(axis);
|
||||||
|
|
||||||
// almost parallel
|
// almost parallel
|
||||||
if (fabs(a)<mjMINVAL) {
|
if (fabs(a) < mjMINVAL) {
|
||||||
// opposite: 180 deg rotation around x axis
|
// opposite: 180 deg rotation around x axis
|
||||||
if (mju_dot3(vn, z) < 0) {
|
if (mju_dot3(vn, z) < 0) {
|
||||||
quat[0] = 0;
|
quat[0] = 0;
|
||||||
@@ -368,8 +368,7 @@ void mju_inertCom(mjtNum res[10], const mjtNum inert[3], const mjtNum mat[9],
|
|||||||
// tmp = diag(inert) * mat' (mat is local-to-global rotation)
|
// tmp = diag(inert) * mat' (mat is local-to-global rotation)
|
||||||
mjtNum tmp[9] = {mat[0]*inert[0], mat[3]*inert[0], mat[6]*inert[0],
|
mjtNum tmp[9] = {mat[0]*inert[0], mat[3]*inert[0], mat[6]*inert[0],
|
||||||
mat[1]*inert[1], mat[4]*inert[1], mat[7]*inert[1],
|
mat[1]*inert[1], mat[4]*inert[1], mat[7]*inert[1],
|
||||||
mat[2]*inert[2], mat[5]*inert[2], mat[8]*inert[2]
|
mat[2]*inert[2], mat[5]*inert[2], mat[8]*inert[2]};
|
||||||
};
|
|
||||||
|
|
||||||
// res_rot = mat * diag(inert) * mat'
|
// res_rot = mat * diag(inert) * mat'
|
||||||
res[0] = mat[0]*tmp[0] + mat[1]*tmp[3] + mat[2]*tmp[6];
|
res[0] = mat[0]*tmp[0] + mat[1]*tmp[3] + mat[2]*tmp[6];
|
||||||
@@ -429,9 +428,9 @@ void mju_dofCom(mjtNum res[6], const mjtNum axis[3], const mjtNum offset[3]) {
|
|||||||
|
|
||||||
// multiply dof matrix (6-by-n, transposed) by vector (n-by-1)
|
// multiply dof matrix (6-by-n, transposed) by vector (n-by-1)
|
||||||
void mju_mulDofVec(mjtNum* res, const mjtNum* dof, const mjtNum* vec, int n) {
|
void mju_mulDofVec(mjtNum* res, const mjtNum* dof, const mjtNum* vec, int n) {
|
||||||
if (n==1) {
|
if (n == 1) {
|
||||||
mju_scl(res, dof, vec[0], 6);
|
mju_scl(res, dof, vec[0], 6);
|
||||||
} else if (n<=0) {
|
} else if (n <= 0) {
|
||||||
mju_zero(res, 6);
|
mju_zero(res, 6);
|
||||||
} else {
|
} else {
|
||||||
mju_mulMatTVec(res, dof, vec, n, 6);
|
mju_mulMatTVec(res, dof, vec, n, 6);
|
||||||
@@ -485,7 +484,7 @@ void mju_makeFrame(mjtNum frame[9]) {
|
|||||||
if (mju_norm3(frame+3) < 0.5) {
|
if (mju_norm3(frame+3) < 0.5) {
|
||||||
mju_zero3(frame+3);
|
mju_zero3(frame+3);
|
||||||
|
|
||||||
if (frame[1]<0.5 && frame[1]>-0.5) {
|
if (frame[1] < 0.5 && frame[1] > -0.5) {
|
||||||
frame[4] = 1;
|
frame[4] = 1;
|
||||||
} else {
|
} else {
|
||||||
frame[5] = 1;
|
frame[5] = 1;
|
||||||
|
|||||||
+19
-19
@@ -29,17 +29,17 @@ static void vfs_strippath(char* newname, const char* oldname) {
|
|||||||
|
|
||||||
// find last delimiter
|
// find last delimiter
|
||||||
int i;
|
int i;
|
||||||
for (i=sz-1; i>=0; i--) {
|
for (i=sz-1; i >= 0; i--) {
|
||||||
if (oldname[i]=='\\' || oldname[i]=='/') {
|
if (oldname[i] == '\\' || oldname[i] == '/') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check resulting length
|
// check resulting length
|
||||||
if (sz-(i+1)>=mjMAXVFSNAME) {
|
if (sz-(i+1) >= mjMAXVFSNAME) {
|
||||||
mju_error("Filename too long in VFS");
|
mju_error("Filename too long in VFS");
|
||||||
}
|
}
|
||||||
if (sz-(i+1)<=0) {
|
if (sz-(i+1) <= 0) {
|
||||||
mju_error("Empty filename in VFS");
|
mju_error("Empty filename in VFS");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,8 +47,8 @@ static void vfs_strippath(char* newname, const char* oldname) {
|
|||||||
mju_strncpy(newname, oldname+i+1, mjMAXVFSNAME);
|
mju_strncpy(newname, oldname+i+1, mjMAXVFSNAME);
|
||||||
|
|
||||||
// make lowercase
|
// make lowercase
|
||||||
for (int j=strlen(newname)-1; j>=0; j--) {
|
for (int j=strlen(newname)-1; j >= 0; j--) {
|
||||||
if (newname[j]>='A' && newname[j]<='Z') {
|
if (newname[j] >= 'A' && newname[j] <= 'Z') {
|
||||||
newname[j] = (char)(((int)newname[j]) +'a' - 'A');
|
newname[j] = (char)(((int)newname[j]) +'a' - 'A');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ void mj_defaultVFS(mjVFS* vfs) {
|
|||||||
// add file to VFS, return 0: success, 1: full, 2: repeated name, -1: failed to load
|
// add file to VFS, return 0: success, 1: full, 2: repeated name, -1: failed to load
|
||||||
int mj_addFileVFS(mjVFS* vfs, const char* directory, const char* filename) {
|
int mj_addFileVFS(mjVFS* vfs, const char* directory, const char* filename) {
|
||||||
// check vfs size
|
// check vfs size
|
||||||
if (vfs->nfile>=mjMAXVFS-1) {
|
if (vfs->nfile >= mjMAXVFS-1) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +84,8 @@ int mj_addFileVFS(mjVFS* vfs, const char* directory, const char* filename) {
|
|||||||
vfs_strippath(newname, filename);
|
vfs_strippath(newname, filename);
|
||||||
|
|
||||||
// check for repeated name
|
// check for repeated name
|
||||||
for (int i=0; i<vfs->nfile; i++) {
|
for (int i=0; i < vfs->nfile; i++) {
|
||||||
if (strncmp(newname, vfs->filename[i], mjMAXVFSNAME)==0) {
|
if (strncmp(newname, vfs->filename[i], mjMAXVFSNAME) == 0) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,12 +111,12 @@ int mj_addFileVFS(mjVFS* vfs, const char* directory, const char* filename) {
|
|||||||
// make empty file in VFS, return 0: success, 1: full, 2: repeated name
|
// make empty file in VFS, return 0: success, 1: full, 2: repeated name
|
||||||
int mj_makeEmptyFileVFS(mjVFS* vfs, const char* filename, int filesize) {
|
int mj_makeEmptyFileVFS(mjVFS* vfs, const char* filename, int filesize) {
|
||||||
// check vfs size
|
// check vfs size
|
||||||
if (vfs->nfile>=mjMAXVFS-1) {
|
if (vfs->nfile >= mjMAXVFS-1) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check filesize
|
// check filesize
|
||||||
if (filesize<=0) {
|
if (filesize <= 0) {
|
||||||
mju_error("mj_makeEmptyFileVFS expects positive filesize");
|
mju_error("mj_makeEmptyFileVFS expects positive filesize");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +125,8 @@ int mj_makeEmptyFileVFS(mjVFS* vfs, const char* filename, int filesize) {
|
|||||||
vfs_strippath(newname, filename);
|
vfs_strippath(newname, filename);
|
||||||
|
|
||||||
// check for repeated name
|
// check for repeated name
|
||||||
for (int i=0; i<vfs->nfile; i++) {
|
for (int i=0; i < vfs->nfile; i++) {
|
||||||
if (strncmp(newname, vfs->filename[i], mjMAXVFSNAME)==0) {
|
if (strncmp(newname, vfs->filename[i], mjMAXVFSNAME) == 0) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,8 +156,8 @@ int mj_findFileVFS(const mjVFS* vfs, const char* filename) {
|
|||||||
char newname[mjMAXVFSNAME];
|
char newname[mjMAXVFSNAME];
|
||||||
vfs_strippath(newname, filename);
|
vfs_strippath(newname, filename);
|
||||||
// find specific file
|
// find specific file
|
||||||
for (int i=0; i<vfs->nfile; i++) {
|
for (int i=0; i < vfs->nfile; i++) {
|
||||||
if (strncmp(newname, vfs->filename[i], mjMAXVFSNAME)==0) {
|
if (strncmp(newname, vfs->filename[i], mjMAXVFSNAME) == 0) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,13 +174,13 @@ int mj_deleteFileVFS(mjVFS* vfs, const char* filename) {
|
|||||||
vfs_strippath(newname, filename);
|
vfs_strippath(newname, filename);
|
||||||
|
|
||||||
// find specified file
|
// find specified file
|
||||||
for (int i=0; i<vfs->nfile; i++) {
|
for (int i=0; i < vfs->nfile; i++) {
|
||||||
if (strncmp(newname, vfs->filename[i], mjMAXVFSNAME)==0) {
|
if (strncmp(newname, vfs->filename[i], mjMAXVFSNAME) == 0) {
|
||||||
// free buffer
|
// free buffer
|
||||||
mju_free(vfs->filedata[i]);
|
mju_free(vfs->filedata[i]);
|
||||||
|
|
||||||
// scroll remaining files forward
|
// scroll remaining files forward
|
||||||
for (int j=i; j<vfs->nfile-1; j++) {
|
for (int j=i; j < vfs->nfile-1; j++) {
|
||||||
mjSTRNCPY(vfs->filename[j], vfs->filename[j+1]);
|
mjSTRNCPY(vfs->filename[j], vfs->filename[j+1]);
|
||||||
vfs->filesize[j] = vfs->filesize[j+1];
|
vfs->filesize[j] = vfs->filesize[j+1];
|
||||||
vfs->filedata[j] = vfs->filedata[j+1];
|
vfs->filedata[j] = vfs->filedata[j+1];
|
||||||
@@ -204,7 +204,7 @@ int mj_deleteFileVFS(mjVFS* vfs, const char* filename) {
|
|||||||
|
|
||||||
// delete all files from VFS
|
// delete all files from VFS
|
||||||
void mj_deleteVFS(mjVFS* vfs) {
|
void mj_deleteVFS(mjVFS* vfs) {
|
||||||
for (int i=0; i<vfs->nfile; i++) {
|
for (int i=0; i < vfs->nfile; i++) {
|
||||||
mju_free(vfs->filedata[i]);
|
mju_free(vfs->filedata[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ void mjv_makeScene(const mjModel* m, mjvScene* scn, int maxgeom) {
|
|||||||
mjv_freeScene(scn);
|
mjv_freeScene(scn);
|
||||||
|
|
||||||
// allocate geom buffers
|
// allocate geom buffers
|
||||||
if (maxgeom>0) {
|
if (maxgeom > 0) {
|
||||||
// allocate
|
// allocate
|
||||||
scn->maxgeom = maxgeom;
|
scn->maxgeom = maxgeom;
|
||||||
scn->geoms = (mjvGeom*) mju_malloc(maxgeom*sizeof(mjvGeom));
|
scn->geoms = (mjvGeom*) mju_malloc(maxgeom*sizeof(mjvGeom));
|
||||||
@@ -132,8 +132,8 @@ void mjv_makeScene(const mjModel* m, mjvScene* scn, int maxgeom) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set default OpenGL options
|
// set default OpenGL options
|
||||||
for (int i=0; i<mjNRNDFLAG; i++) {
|
for (int i=0; i < mjNRNDFLAG; i++) {
|
||||||
scn->flags[i] = (mjRNDSTRING[i][1][0]=='1');
|
scn->flags[i] = (mjRNDSTRING[i][1][0] == '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default model transformation
|
// set default model transformation
|
||||||
@@ -152,7 +152,7 @@ void mjv_makeScene(const mjModel* m, mjvScene* scn, int maxgeom) {
|
|||||||
// compute number of vertices in all skins
|
// compute number of vertices in all skins
|
||||||
int nskin = m->nskin;
|
int nskin = m->nskin;
|
||||||
int totvert = 0;
|
int totvert = 0;
|
||||||
for (int i=0; i<nskin; i++) {
|
for (int i=0; i < nskin; i++) {
|
||||||
totvert += m->skin_vertnum[i];
|
totvert += m->skin_vertnum[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ void mjv_makeScene(const mjModel* m, mjvScene* scn, int maxgeom) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copy constant data
|
// copy constant data
|
||||||
for (int i=0; i<nskin; i++) {
|
for (int i=0; i < nskin; i++) {
|
||||||
scn->skinfacenum[i] = m->skin_facenum[i];
|
scn->skinfacenum[i] = m->skin_facenum[i];
|
||||||
scn->skinvertadr[i] = m->skin_vertadr[i];
|
scn->skinvertadr[i] = m->skin_vertadr[i];
|
||||||
scn->skinvertnum[i] = m->skin_vertnum[i];
|
scn->skinvertnum[i] = m->skin_vertnum[i];
|
||||||
@@ -214,8 +214,8 @@ void mjv_defaultOption(mjvOption* vopt) {
|
|||||||
vopt->label = mjLABEL_NONE;
|
vopt->label = mjLABEL_NONE;
|
||||||
vopt->frame = mjFRAME_NONE;
|
vopt->frame = mjFRAME_NONE;
|
||||||
|
|
||||||
for (int i=0; i<mjNGROUP; i++) {
|
for (int i=0; i < mjNGROUP; i++) {
|
||||||
int state = (i<3 ? 1 : 0);
|
int state = (i < 3 ? 1 : 0);
|
||||||
vopt->geomgroup[i] = state;
|
vopt->geomgroup[i] = state;
|
||||||
vopt->sitegroup[i] = state;
|
vopt->sitegroup[i] = state;
|
||||||
vopt->jointgroup[i] = state;
|
vopt->jointgroup[i] = state;
|
||||||
@@ -224,8 +224,8 @@ void mjv_defaultOption(mjvOption* vopt) {
|
|||||||
vopt->skingroup[i] = state;
|
vopt->skingroup[i] = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<mjNVISFLAG; i++) {
|
for (int i=0; i < mjNVISFLAG; i++) {
|
||||||
vopt->flags[i] = (mjVISSTRING[i][1][0]=='1');
|
vopt->flags[i] = (mjVISSTRING[i][1][0] == '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
vopt->bvh_depth = 1;
|
vopt->bvh_depth = 1;
|
||||||
@@ -326,9 +326,9 @@ void mjv_defaultFigure(mjvFigure* fig) {
|
|||||||
mjSTRNCPY(fig->minwidth, "XXX");
|
mjSTRNCPY(fig->minwidth, "XXX");
|
||||||
|
|
||||||
// set line colors
|
// set line colors
|
||||||
for (int n=0; n<mjMAXLINE; n++) {
|
for (int n=0; n < mjMAXLINE; n++) {
|
||||||
// predefined colors
|
// predefined colors
|
||||||
if (n<8) {
|
if (n < 8) {
|
||||||
fig->linergb[n][0] = _linergb[n][0];
|
fig->linergb[n][0] = _linergb[n][0];
|
||||||
fig->linergb[n][1] = _linergb[n][1];
|
fig->linergb[n][1] = _linergb[n][1];
|
||||||
fig->linergb[n][2] = _linergb[n][2];
|
fig->linergb[n][2] = _linergb[n][2];
|
||||||
@@ -348,7 +348,7 @@ void mjv_defaultFigure(mjvFigure* fig) {
|
|||||||
// compute rbound for mjvGeom
|
// compute rbound for mjvGeom
|
||||||
float mjv_rbound(const mjvGeom* geom) {
|
float mjv_rbound(const mjvGeom* geom) {
|
||||||
// model geom: return
|
// model geom: return
|
||||||
if (geom->objtype==mjOBJ_GEOM) {
|
if (geom->objtype == mjOBJ_GEOM) {
|
||||||
return geom->modelrbound;
|
return geom->modelrbound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ void mjv_room2model(mjtNum* modelpos, mjtNum* modelquat, const mjtNum* roompos,
|
|||||||
mjtNum translate[3], rotate[4], invpos[3], invquat[4];
|
mjtNum translate[3], rotate[4], invpos[3], invquat[4];
|
||||||
|
|
||||||
// check scale
|
// check scale
|
||||||
if (scn->scale<mjMINVAL) {
|
if (scn->scale < mjMINVAL) {
|
||||||
mju_error("mjvScene scale too small in mjv_room2model");
|
mju_error("mjvScene scale too small in mjv_room2model");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ void mjv_model2room(mjtNum* roompos, mjtNum* roomquat, const mjtNum* modelpos,
|
|||||||
mjtNum translate[3], rotate[4];
|
mjtNum translate[3], rotate[4];
|
||||||
|
|
||||||
// check scale
|
// check scale
|
||||||
if (scn->scale<mjMINVAL) {
|
if (scn->scale < mjMINVAL) {
|
||||||
mju_error("mjvScene scale too small in mjv_model2room");
|
mju_error("mjvScene scale too small in mjv_model2room");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ void mjv_cameraInModel(mjtNum* headpos, mjtNum* forward, mjtNum* up, const mjvSc
|
|||||||
mjtNum modelpos[3], modelquat[4], modelmat[9];
|
mjtNum modelpos[3], modelquat[4], modelmat[9];
|
||||||
|
|
||||||
// check znear
|
// check znear
|
||||||
if (scn->camera[0].frustum_near<mjMINVAL || scn->camera[1].frustum_near<mjMINVAL) {
|
if (scn->camera[0].frustum_near < mjMINVAL || scn->camera[1].frustum_near < mjMINVAL) {
|
||||||
mju_error("mjvScene frustum_near too small in mjv_cameraInModel");
|
mju_error("mjvScene frustum_near too small in mjv_cameraInModel");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ void mjv_cameraInModel(mjtNum* headpos, mjtNum* forward, mjtNum* up, const mjvSc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// average over cameras
|
// average over cameras
|
||||||
for (int n=0; n<2; n++) {
|
for (int n=0; n < 2; n++) {
|
||||||
// convert pos, fwd, u
|
// convert pos, fwd, u
|
||||||
mju_f2n(pos, scn->camera[n].pos, 3);
|
mju_f2n(pos, scn->camera[n].pos, 3);
|
||||||
mju_f2n(fwd, scn->camera[n].forward, 3);
|
mju_f2n(fwd, scn->camera[n].forward, 3);
|
||||||
@@ -177,7 +177,7 @@ void mjv_cameraInRoom(mjtNum* headpos, mjtNum* forward, mjtNum* up, const mjvSce
|
|||||||
mjtNum pos[3], fwd[3], u[3];
|
mjtNum pos[3], fwd[3], u[3];
|
||||||
|
|
||||||
// check znear
|
// check znear
|
||||||
if (scn->camera[0].frustum_near<mjMINVAL || scn->camera[1].frustum_near<mjMINVAL) {
|
if (scn->camera[0].frustum_near < mjMINVAL || scn->camera[1].frustum_near < mjMINVAL) {
|
||||||
mju_error("mjvScene frustum_near too small in mjv_cameraInRoom");
|
mju_error("mjvScene frustum_near too small in mjv_cameraInRoom");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ void mjv_cameraInRoom(mjtNum* headpos, mjtNum* forward, mjtNum* up, const mjvSce
|
|||||||
}
|
}
|
||||||
|
|
||||||
// average over cameras
|
// average over cameras
|
||||||
for (int n=0; n<2; n++) {
|
for (int n=0; n < 2; n++) {
|
||||||
// convert pos, fwd, u
|
// convert pos, fwd, u
|
||||||
mju_f2n(pos, scn->camera[n].pos, 3);
|
mju_f2n(pos, scn->camera[n].pos, 3);
|
||||||
mju_f2n(fwd, scn->camera[n].forward, 3);
|
mju_f2n(fwd, scn->camera[n].forward, 3);
|
||||||
@@ -227,7 +227,7 @@ mjtNum mjv_frustumHeight(const mjvScene* scn) {
|
|||||||
mjtNum height;
|
mjtNum height;
|
||||||
|
|
||||||
// check znear
|
// check znear
|
||||||
if (scn->camera[0].frustum_near<mjMINVAL || scn->camera[1].frustum_near<mjMINVAL) {
|
if (scn->camera[0].frustum_near < mjMINVAL || scn->camera[1].frustum_near < mjMINVAL) {
|
||||||
mju_error("mjvScene frustum_near too small in mjv_frustumHeight");
|
mju_error("mjvScene frustum_near too small in mjv_frustumHeight");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ void mjv_moveCamera(const mjModel* m, int action, mjtNum reldx, mjtNum reldy,
|
|||||||
mjtNum vec[3], dif[3], scl;
|
mjtNum vec[3], dif[3], scl;
|
||||||
|
|
||||||
// fixed camera: nothing to do
|
// fixed camera: nothing to do
|
||||||
if (cam->type==mjCAMERA_FIXED) {
|
if (cam->type == mjCAMERA_FIXED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +326,7 @@ void mjv_moveCamera(const mjModel* m, int action, mjtNum reldx, mjtNum reldy,
|
|||||||
case mjMOUSE_MOVE_V:
|
case mjMOUSE_MOVE_V:
|
||||||
case mjMOUSE_MOVE_H:
|
case mjMOUSE_MOVE_H:
|
||||||
// do not move lookat point of tracking camera
|
// do not move lookat point of tracking camera
|
||||||
if (cam->type==mjCAMERA_TRACKING) {
|
if (cam->type == mjCAMERA_TRACKING) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,7 +405,7 @@ void mjv_movePerturb(const mjModel* m, const mjData* d, int action, mjtNum reldx
|
|||||||
mju_mulQuat(xiquat, d->xquat+4*sel, m->body_iquat+4*sel);
|
mju_mulQuat(xiquat, d->xquat+4*sel, m->body_iquat+4*sel);
|
||||||
|
|
||||||
// limit rotation relative to selected body
|
// limit rotation relative to selected body
|
||||||
if (sel>0 && sel<m->nbody) {
|
if (sel > 0 && sel < m->nbody) {
|
||||||
// q2 = neg(selbody) * refquat
|
// q2 = neg(selbody) * refquat
|
||||||
mjtNum q2[4];
|
mjtNum q2[4];
|
||||||
mju_negQuat(q1, xiquat);
|
mju_negQuat(q1, xiquat);
|
||||||
@@ -417,7 +417,7 @@ void mjv_movePerturb(const mjModel* m, const mjData* d, int action, mjtNum reldx
|
|||||||
scl = mju_normalize3(dif);
|
scl = mju_normalize3(dif);
|
||||||
|
|
||||||
// check limit: +/- 90 deg allowed
|
// check limit: +/- 90 deg allowed
|
||||||
if (scl<-mjPI*0.5 || scl>mjPI*0.5) {
|
if (scl < -mjPI*0.5 || scl > mjPI*0.5) {
|
||||||
// clamp angle
|
// clamp angle
|
||||||
scl = mju_max(-mjPI*0.5, mju_min(mjPI*0.5, scl));
|
scl = mju_max(-mjPI*0.5, mju_min(mjPI*0.5, scl));
|
||||||
|
|
||||||
@@ -467,8 +467,8 @@ void mjv_moveModel(const mjModel* m, int action, mjtNum reldx, mjtNum reldy,
|
|||||||
case mjMOUSE_ROTATE_V:
|
case mjMOUSE_ROTATE_V:
|
||||||
case mjMOUSE_ROTATE_H:
|
case mjMOUSE_ROTATE_H:
|
||||||
// construct rotation vector
|
// construct rotation vector
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
if (action==mjMOUSE_ROTATE_V) {
|
if (action == mjMOUSE_ROTATE_V) {
|
||||||
vec[i] = roomup[i]*reldx + roomright[i]*reldy;
|
vec[i] = roomup[i]*reldx + roomright[i]*reldy;
|
||||||
} else {
|
} else {
|
||||||
vec[i] = roomforward[i]*reldx + roomright[i]*reldy;
|
vec[i] = roomforward[i]*reldx + roomright[i]*reldy;
|
||||||
@@ -489,22 +489,22 @@ void mjv_moveModel(const mjModel* m, int action, mjtNum reldx, mjtNum reldy,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case mjMOUSE_MOVE_V:
|
case mjMOUSE_MOVE_V:
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
scn->translate[i] += (float)(roomright[i]*reldx - roomup[i]*reldy) * m->stat.extent;
|
scn->translate[i] += (float)(roomright[i]*reldx - roomup[i]*reldy) * m->stat.extent;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjMOUSE_MOVE_H:
|
case mjMOUSE_MOVE_H:
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i < 3; i++) {
|
||||||
scn->translate[i] += (float)(roomright[i]*reldx - roomforward[i]*reldy) * m->stat.extent;
|
scn->translate[i] += (float)(roomright[i]*reldx - roomforward[i]*reldy) * m->stat.extent;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjMOUSE_ZOOM:
|
case mjMOUSE_ZOOM:
|
||||||
scn->scale += (float)(mju_log(1 + scn->scale/3) * reldy * 3);
|
scn->scale += (float)(mju_log(1 + scn->scale/3) * reldy * 3);
|
||||||
if (scn->scale<0.01f) {
|
if (scn->scale < 0.01f) {
|
||||||
scn->scale = 0.01f;
|
scn->scale = 0.01f;
|
||||||
} else if (scn->scale>100.0f) {
|
} else if (scn->scale > 100.0f) {
|
||||||
scn->scale = 100.0f;
|
scn->scale = 100.0f;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -528,7 +528,7 @@ void mjv_initPerturb(const mjModel* m, mjData* d, const mjvScene* scn, mjvPertur
|
|||||||
mjtNum* jacM2 = mj_stackAlloc(d, 3*nv);
|
mjtNum* jacM2 = mj_stackAlloc(d, 3*nv);
|
||||||
|
|
||||||
// invalid selected body: return
|
// invalid selected body: return
|
||||||
if (sel<=0 || sel>=m->nbody) {
|
if (sel <= 0 || sel >= m->nbody) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +570,7 @@ void mjv_applyPerturbPose(const mjModel* m, mjData* d, const mjvPerturb* pert, i
|
|||||||
mjtNum *Rpos, *Rquat, *Cpos, *Cquat;
|
mjtNum *Rpos, *Rquat, *Cpos, *Cquat;
|
||||||
|
|
||||||
// exit if nothing to do
|
// exit if nothing to do
|
||||||
if (sel<=0 || sel>=m->nbody || !(pert->active | pert->active2)) {
|
if (sel <= 0 || sel >= m->nbody || !(pert->active | pert->active2)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,23 +582,23 @@ void mjv_applyPerturbPose(const mjModel* m, mjData* d, const mjvPerturb* pert, i
|
|||||||
mju_mulPose(refpos, refquat, pert->refpos, pert->refquat, pos1, quat1);
|
mju_mulPose(refpos, refquat, pert->refpos, pert->refquat, pos1, quat1);
|
||||||
|
|
||||||
// mocap body
|
// mocap body
|
||||||
if (m->body_mocapid[sel]>=0) {
|
if (m->body_mocapid[sel] >= 0) {
|
||||||
// copy ref pose into mocap pose
|
// copy ref pose into mocap pose
|
||||||
mju_copy3(d->mocap_pos + 3*m->body_mocapid[sel], refpos);
|
mju_copy3(d->mocap_pos + 3*m->body_mocapid[sel], refpos);
|
||||||
mju_copy4(d->mocap_quat + 4*m->body_mocapid[sel], refquat);
|
mju_copy4(d->mocap_quat + 4*m->body_mocapid[sel], refquat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// floating body, paused
|
// floating body, paused
|
||||||
else if (flg_paused && m->body_jntnum[sel]==1 &&
|
else if (flg_paused && m->body_jntnum[sel] == 1 &&
|
||||||
m->jnt_type[m->body_jntadr[sel]]==mjJNT_FREE) {
|
m->jnt_type[m->body_jntadr[sel]] == mjJNT_FREE) {
|
||||||
// copy ref pose into qpos
|
// copy ref pose into qpos
|
||||||
mju_copy3(d->qpos + m->jnt_qposadr[m->body_jntadr[sel]], refpos);
|
mju_copy3(d->qpos + m->jnt_qposadr[m->body_jntadr[sel]], refpos);
|
||||||
mju_copy4(d->qpos + m->jnt_qposadr[m->body_jntadr[sel]] + 3, refquat);
|
mju_copy4(d->qpos + m->jnt_qposadr[m->body_jntadr[sel]] + 3, refquat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// child of floating body, paused
|
// child of floating body, paused
|
||||||
else if (flg_paused && m->body_jntnum[rootid]==1 &&
|
else if (flg_paused && m->body_jntnum[rootid] == 1 &&
|
||||||
m->jnt_type[m->body_jntadr[rootid]]==mjJNT_FREE) {
|
m->jnt_type[m->body_jntadr[rootid]] == mjJNT_FREE) {
|
||||||
// get pointers to root
|
// get pointers to root
|
||||||
Rpos = d->qpos + m->jnt_qposadr[m->body_jntadr[rootid]];
|
Rpos = d->qpos + m->jnt_qposadr[m->body_jntadr[rootid]];
|
||||||
Rquat = Rpos + 3;
|
Rquat = Rpos + 3;
|
||||||
@@ -621,7 +621,7 @@ void mjv_applyPerturbForce(const mjModel* m, mjData* d, const mjvPerturb* pert)
|
|||||||
int sel = pert->select;
|
int sel = pert->select;
|
||||||
|
|
||||||
// exit if nothing to do
|
// exit if nothing to do
|
||||||
if (sel<0 || sel>=m->nbody || !(pert->active | pert->active2)) {
|
if (sel < 0 || sel >= m->nbody || !(pert->active | pert->active2)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -763,7 +763,7 @@ int mjv_select(const mjModel* m, const mjData* d, const mjvOption* vopt,
|
|||||||
mjtNum skindist = -1;
|
mjtNum skindist = -1;
|
||||||
*skinid = -1;
|
*skinid = -1;
|
||||||
if (vopt->flags[mjVIS_SKIN]) {
|
if (vopt->flags[mjVIS_SKIN]) {
|
||||||
for (int i=0; i<m->nskin; i++) {
|
for (int i=0; i < m->nskin; i++) {
|
||||||
// process one skin
|
// process one skin
|
||||||
int vertid;
|
int vertid;
|
||||||
mjtNum newdist = mju_raySkin(m->skin_facenum[i], m->skin_vertnum[i],
|
mjtNum newdist = mju_raySkin(m->skin_facenum[i], m->skin_vertnum[i],
|
||||||
@@ -772,24 +772,24 @@ int mjv_select(const mjModel* m, const mjData* d, const mjvOption* vopt,
|
|||||||
pos, ray, &vertid);
|
pos, ray, &vertid);
|
||||||
|
|
||||||
// update if closer intersection found
|
// update if closer intersection found
|
||||||
if (newdist>=0 && (newdist<skindist || skindist<0)) {
|
if (newdist >= 0 && (newdist < skindist || skindist < 0)) {
|
||||||
// assign result
|
// assign result
|
||||||
skindist = newdist;
|
skindist = newdist;
|
||||||
|
|
||||||
// find body with largest weight for this vertex
|
// find body with largest weight for this vertex
|
||||||
float bestweight = -1;
|
float bestweight = -1;
|
||||||
for (int j=m->skin_boneadr[i];
|
for (int j=m->skin_boneadr[i];
|
||||||
j<m->skin_boneadr[i]+m->skin_bonenum[i];
|
j < m->skin_boneadr[i]+m->skin_bonenum[i];
|
||||||
j++) {
|
j++) {
|
||||||
for (int k=m->skin_bonevertadr[j];
|
for (int k=m->skin_bonevertadr[j];
|
||||||
k<m->skin_bonevertadr[j]+m->skin_bonevertnum[j];
|
k < m->skin_bonevertadr[j]+m->skin_bonevertnum[j];
|
||||||
k++) {
|
k++) {
|
||||||
// get vertex id and weight
|
// get vertex id and weight
|
||||||
int vid = m->skin_bonevertid[k];
|
int vid = m->skin_bonevertid[k];
|
||||||
float vweight = m->skin_bonevertweight[k];
|
float vweight = m->skin_bonevertweight[k];
|
||||||
|
|
||||||
// update if matching id and bigger weight
|
// update if matching id and bigger weight
|
||||||
if (vid==vertid && vweight>bestweight) {
|
if (vid == vertid && vweight > bestweight) {
|
||||||
bestweight = vweight;
|
bestweight = vweight;
|
||||||
bodyid = m->skin_bonebodyid[j];
|
bodyid = m->skin_bonebodyid[j];
|
||||||
*skinid = i;
|
*skinid = i;
|
||||||
@@ -801,12 +801,12 @@ int mjv_select(const mjModel* m, const mjData* d, const mjvOption* vopt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no intersection
|
// no intersection
|
||||||
if (geomdist<0 && skindist<0) {
|
if (geomdist < 0 && skindist < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// geom only, or geom closer than skin
|
// geom only, or geom closer than skin
|
||||||
else if (geomdist>=0 && (skindist<0 || skindist>geomdist)) {
|
else if (geomdist >= 0 && (skindist < 0 || skindist > geomdist)) {
|
||||||
mju_addScl3(selpnt, pos, ray, geomdist);
|
mju_addScl3(selpnt, pos, ray, geomdist);
|
||||||
*skinid = -1;
|
*skinid = -1;
|
||||||
return m->geom_bodyid[*geomid];
|
return m->geom_bodyid[*geomid];
|
||||||
|
|||||||
@@ -141,8 +141,8 @@ void mjv_assignFromSceneState(const mjvSceneState* scnstate, mjModel* m, mjData*
|
|||||||
memset(m, 0, sizeof(mjModel));
|
memset(m, 0, sizeof(mjModel));
|
||||||
|
|
||||||
#ifdef MEMORY_SANITIZER
|
#ifdef MEMORY_SANITIZER
|
||||||
// Tell msan to treat the entire buffer as uninitialized
|
// Tell msan to treat the entire buffer as uninitialized
|
||||||
__msan_allocated_memory(m, sizeof(mjModel));
|
__msan_allocated_memory(m, sizeof(mjModel));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define X(var)
|
#define X(var)
|
||||||
@@ -166,8 +166,8 @@ void mjv_assignFromSceneState(const mjvSceneState* scnstate, mjModel* m, mjData*
|
|||||||
memset(d, 0, sizeof(mjData));
|
memset(d, 0, sizeof(mjData));
|
||||||
|
|
||||||
#ifdef MEMORY_SANITIZER
|
#ifdef MEMORY_SANITIZER
|
||||||
// Tell msan to treat the entire buffer as uninitialized
|
// Tell msan to treat the entire buffer as uninitialized
|
||||||
__msan_allocated_memory(d, sizeof(mjData));
|
__msan_allocated_memory(d, sizeof(mjData));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memcpy(d->warning, scnstate->data.warning, sizeof(d->warning));
|
memcpy(d->warning, scnstate->data.warning, sizeof(d->warning));
|
||||||
@@ -247,7 +247,7 @@ void mjv_updateSceneState(const mjModel* m, mjData* d, const mjvOption* opt,
|
|||||||
if (m->nplugin) {
|
if (m->nplugin) {
|
||||||
const int nslot = mjp_pluginCount();
|
const int nslot = mjp_pluginCount();
|
||||||
// iterate over plugins, call visualize if defined
|
// iterate over plugins, call visualize if defined
|
||||||
for (int i=0; i<m->nplugin; i++) {
|
for (int i=0; i < m->nplugin; i++) {
|
||||||
const int slot = m->plugin[i];
|
const int slot = m->plugin[i];
|
||||||
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot);
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
|
|||||||
+269
-268
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user