Add mjContact.solreffriction, mjModel.pair_solreffriction and related implementation, allowing contact reference acceleration to be different for normal and frictional contact directions. This is required for e.g. elastic frictional collisions.
PiperOrigin-RevId: 538513357 Change-Id: Id9eb910fe791cf898c712030cb2c0fc481389c91
This commit is contained in:
committed by
Copybara-Service
parent
83e70954d7
commit
d82f5ce5a4
@@ -1630,6 +1630,8 @@ if omitted.
|
||||
|
||||
.. _default-pair-solref:
|
||||
|
||||
.. _default-pair-solreffriction:
|
||||
|
||||
.. _default-pair-solimp:
|
||||
|
||||
.. _default-pair-gap:
|
||||
@@ -4299,6 +4301,20 @@ element.
|
||||
:at:`solref`, :at:`solimp`
|
||||
Constraint solver parameters for contact simulation. See :ref:`CSolver`.
|
||||
|
||||
.. _contact-pair-solreffriction:
|
||||
|
||||
:at:`solreffriction`: :at-val:`real, "0 0"`
|
||||
Contact reference acceleration, in the friction dimensions. This attribute has the same semantics as other
|
||||
:at:`solref` attributes (described in :ref:`CSolver`), with two important distictions:
|
||||
|
||||
- The default :at-val:`"0 0"` means "use the same values as :at:`solref`".
|
||||
- This attribute only takes effect for :ref:`elliptic friction cones<option-cone>`, since pyramidal cones mix normal
|
||||
and frictional forces.
|
||||
|
||||
Note that as with other :at:`solreffriction` attributes, the constraint violation is identically 0. Therefore, when
|
||||
using positive semantics :at:`solreffriction[1]` is ignored, while for negative semantics :at:`solreffriction[0]` is
|
||||
ignored. See :ref:`CSolver` for more details.
|
||||
|
||||
.. _contact-pair-margin:
|
||||
|
||||
:at:`margin`: :at-val:`real, "0"`
|
||||
|
||||
+5
-3
@@ -305,7 +305,9 @@
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`condim<default-pair-condim>` | :ref:`friction<default-pair-friction>` | :ref:`solref<default-pair-solref>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`solimp<default-pair-solimp>` | :ref:`gap<default-pair-gap>` | :ref:`margin<default-pair-margin>` | |
|
||||
| | | | :ref:`solreffriction<default-pair-solreffriction>` | :ref:`solimp<default-pair-solimp>` | :ref:`gap<default-pair-gap>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`margin<default-pair-margin>` | | | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| |_| default |br| |_| |L| | | .. table:: |
|
||||
@@ -827,9 +829,9 @@
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`geom2<contact-pair-geom2>` | :ref:`condim<contact-pair-condim>` | :ref:`friction<contact-pair-friction>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`solref<contact-pair-solref>` | :ref:`solimp<contact-pair-solimp>` | :ref:`gap<contact-pair-gap>` | |
|
||||
| | | | :ref:`solref<contact-pair-solref>` | :ref:`solreffriction<contact-pair-solreffriction>` | :ref:`solimp<contact-pair-solimp>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`margin<contact-pair-margin>` | | | |
|
||||
| | | | :ref:`gap<contact-pair-gap>` | :ref:`margin<contact-pair-margin>` | | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| |_| contact |br| |_| |L| | | .. table:: |
|
||||
|
||||
@@ -63,6 +63,13 @@ Simulate
|
||||
General
|
||||
^^^^^^^
|
||||
|
||||
- Added :ref:`mjContact.solreffriction<mjContact>`, allowing different :ref:`solref<CSolver>` parameters for the normal
|
||||
and frictional axes of contacts when using :ref:`elliptic friction cones<option-cone>`. This attribute is required
|
||||
for elastic frictional collisions, see associated
|
||||
`example model <https://github.com/deepmind/mujoco/blob/main/test/engine/testdata/bounce_recoil.xml>`__ mimicking the
|
||||
spin-bounce recoil behaviour of `elastic rubber balls <https://www.youtube.com/watch?v=uFLJcRegIVQ&t=3s>`__.
|
||||
This is an advanced option currently only supported by explicit :ref:`contact pairs<contact-pair>`, using the
|
||||
:ref:`solreffriction<contact-pair-solreffriction>` attribute.
|
||||
- Added :ref:`mjd_inverseFD` for finite-differenced inverse-dynamics derivatives.
|
||||
- Added functions for operations on banded-then-dense "arrowhead" matrices. Such matrices are common when doing direct
|
||||
trajectory optimization. See :ref:`mju_cholFactorBand` documentation for details.
|
||||
|
||||
+19
-17
@@ -50,32 +50,33 @@ typedef enum mjtTimer_ { // internal timers
|
||||
|
||||
mjNTIMER // number of timers
|
||||
} mjtTimer;
|
||||
struct mjContact_ { // result of collision detection functions
|
||||
struct mjContact_ { // result of collision detection functions
|
||||
// contact parameters set by geom-specific collision detector
|
||||
mjtNum dist; // distance between nearest points; neg: penetration
|
||||
mjtNum pos[3]; // position of contact point: midpoint between geoms
|
||||
mjtNum frame[9]; // normal is in [0-2]
|
||||
mjtNum dist; // distance between nearest points; neg: penetration
|
||||
mjtNum pos[3]; // position of contact point: midpoint between geoms
|
||||
mjtNum frame[9]; // normal is in [0-2]
|
||||
|
||||
// contact parameters set by mj_collideGeoms
|
||||
mjtNum includemargin; // include if dist<includemargin=margin-gap
|
||||
mjtNum friction[5]; // tangent1, 2, spin, roll1, 2
|
||||
mjtNum solref[mjNREF]; // constraint solver reference
|
||||
mjtNum solimp[mjNIMP]; // constraint solver impedance
|
||||
mjtNum includemargin; // include if dist<includemargin=margin-gap
|
||||
mjtNum friction[5]; // tangent1, 2, spin, roll1, 2
|
||||
mjtNum solref[mjNREF]; // constraint solver reference, normal direction
|
||||
mjtNum solreffriction[mjNREF]; // constraint solver reference, friction directions
|
||||
mjtNum solimp[mjNIMP]; // constraint solver impedance
|
||||
|
||||
// internal storage used by solver
|
||||
mjtNum mu; // friction of regularized cone, set by mj_makeConstraint
|
||||
mjtNum H[36]; // cone Hessian, set by mj_updateConstraint
|
||||
mjtNum mu; // friction of regularized cone, set by mj_makeConstraint
|
||||
mjtNum H[36]; // cone Hessian, set by mj_updateConstraint
|
||||
|
||||
// contact descriptors set by mj_collideGeoms
|
||||
int dim; // contact space dimensionality: 1, 3, 4 or 6
|
||||
int geom1; // id of geom 1
|
||||
int geom2; // id of geom 2
|
||||
int dim; // contact space dimensionality: 1, 3, 4 or 6
|
||||
int geom1; // id of geom 1
|
||||
int geom2; // id of geom 2
|
||||
|
||||
// flag set by mj_instantianteEquality
|
||||
int exclude; // 0: include, 1: in gap, 2: fused, 3: no dofs
|
||||
int exclude; // 0: include, 1: in gap, 2: fused, 3: no dofs
|
||||
|
||||
// address computed by mj_instantiateContact
|
||||
int efc_address; // address in efc; -1: not included
|
||||
int efc_address; // address in efc; -1: not included
|
||||
};
|
||||
typedef struct mjContact_ mjContact;
|
||||
struct mjWarningStat_ { // warning statistics
|
||||
@@ -1056,8 +1057,9 @@ struct mjModel_ {
|
||||
int* pair_geom1; // id of geom1 (npair x 1)
|
||||
int* pair_geom2; // id of geom2 (npair x 1)
|
||||
int* pair_signature; // (body1+1) << 16 + body2+1 (npair x 1)
|
||||
mjtNum* pair_solref; // constraint solver reference: contact (npair x mjNREF)
|
||||
mjtNum* pair_solimp; // constraint solver impedance: contact (npair x mjNIMP)
|
||||
mjtNum* pair_solref; // solver reference: contact normal (npair x mjNREF)
|
||||
mjtNum* pair_solreffriction; // solver reference: contact friction (npair x mjNREF)
|
||||
mjtNum* pair_solimp; // solver impedance: contact (npair x mjNIMP)
|
||||
mjtNum* pair_margin; // detect contact if dist<margin (npair x 1)
|
||||
mjtNum* pair_gap; // include in solver if dist<margin-gap (npair x 1)
|
||||
mjtNum* pair_friction; // tangent1, 2, spin, roll1, 2 (npair x 5)
|
||||
|
||||
+16
-15
@@ -63,32 +63,33 @@ typedef enum mjtTimer_ { // internal timers
|
||||
|
||||
//---------------------------------- mjContact -----------------------------------------------------
|
||||
|
||||
struct mjContact_ { // result of collision detection functions
|
||||
struct mjContact_ { // result of collision detection functions
|
||||
// contact parameters set by geom-specific collision detector
|
||||
mjtNum dist; // distance between nearest points; neg: penetration
|
||||
mjtNum pos[3]; // position of contact point: midpoint between geoms
|
||||
mjtNum frame[9]; // normal is in [0-2]
|
||||
mjtNum dist; // distance between nearest points; neg: penetration
|
||||
mjtNum pos[3]; // position of contact point: midpoint between geoms
|
||||
mjtNum frame[9]; // normal is in [0-2]
|
||||
|
||||
// contact parameters set by mj_collideGeoms
|
||||
mjtNum includemargin; // include if dist<includemargin=margin-gap
|
||||
mjtNum friction[5]; // tangent1, 2, spin, roll1, 2
|
||||
mjtNum solref[mjNREF]; // constraint solver reference
|
||||
mjtNum solimp[mjNIMP]; // constraint solver impedance
|
||||
mjtNum includemargin; // include if dist<includemargin=margin-gap
|
||||
mjtNum friction[5]; // tangent1, 2, spin, roll1, 2
|
||||
mjtNum solref[mjNREF]; // constraint solver reference, normal direction
|
||||
mjtNum solreffriction[mjNREF]; // constraint solver reference, friction directions
|
||||
mjtNum solimp[mjNIMP]; // constraint solver impedance
|
||||
|
||||
// internal storage used by solver
|
||||
mjtNum mu; // friction of regularized cone, set by mj_makeConstraint
|
||||
mjtNum H[36]; // cone Hessian, set by mj_updateConstraint
|
||||
mjtNum mu; // friction of regularized cone, set by mj_makeConstraint
|
||||
mjtNum H[36]; // cone Hessian, set by mj_updateConstraint
|
||||
|
||||
// contact descriptors set by mj_collideGeoms
|
||||
int dim; // contact space dimensionality: 1, 3, 4 or 6
|
||||
int geom1; // id of geom 1
|
||||
int geom2; // id of geom 2
|
||||
int dim; // contact space dimensionality: 1, 3, 4 or 6
|
||||
int geom1; // id of geom 1
|
||||
int geom2; // id of geom 2
|
||||
|
||||
// flag set by mj_instantianteEquality
|
||||
int exclude; // 0: include, 1: in gap, 2: fused, 3: no dofs
|
||||
int exclude; // 0: include, 1: in gap, 2: fused, 3: no dofs
|
||||
|
||||
// address computed by mj_instantiateContact
|
||||
int efc_address; // address in efc; -1: not included
|
||||
int efc_address; // address in efc; -1: not included
|
||||
};
|
||||
typedef struct mjContact_ mjContact;
|
||||
|
||||
|
||||
@@ -839,8 +839,9 @@ struct mjModel_ {
|
||||
int* pair_geom1; // id of geom1 (npair x 1)
|
||||
int* pair_geom2; // id of geom2 (npair x 1)
|
||||
int* pair_signature; // (body1+1) << 16 + body2+1 (npair x 1)
|
||||
mjtNum* pair_solref; // constraint solver reference: contact (npair x mjNREF)
|
||||
mjtNum* pair_solimp; // constraint solver impedance: contact (npair x mjNIMP)
|
||||
mjtNum* pair_solref; // solver reference: contact normal (npair x mjNREF)
|
||||
mjtNum* pair_solreffriction; // solver reference: contact friction (npair x mjNREF)
|
||||
mjtNum* pair_solimp; // solver impedance: contact (npair x mjNIMP)
|
||||
mjtNum* pair_margin; // detect contact if dist<margin (npair x 1)
|
||||
mjtNum* pair_gap; // include in solver if dist<margin-gap (npair x 1)
|
||||
mjtNum* pair_friction; // tangent1, 2, spin, roll1, 2 (npair x 5)
|
||||
|
||||
@@ -335,6 +335,7 @@
|
||||
X ( int, pair_geom2, npair, 1 ) \
|
||||
X ( int, pair_signature, npair, 1 ) \
|
||||
X ( mjtNum, pair_solref, npair, mjNREF ) \
|
||||
X ( mjtNum, pair_solreffriction, npair, mjNREF ) \
|
||||
X ( mjtNum, pair_solimp, npair, mjNIMP ) \
|
||||
X ( mjtNum, pair_margin, npair, 1 ) \
|
||||
X ( mjtNum, pair_gap, npair, 1 ) \
|
||||
|
||||
+18
-3
@@ -2397,14 +2397,21 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjtNum'),
|
||||
),
|
||||
doc='constraint solver reference: contact (npair x mjNREF)', # pylint: disable=line-too-long
|
||||
doc='solver reference: contact normal (npair x mjNREF)', # pylint: disable=line-too-long
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='pair_solreffriction',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjtNum'),
|
||||
),
|
||||
doc='solver reference: contact friction (npair x mjNREF)', # pylint: disable=line-too-long
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='pair_solimp',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjtNum'),
|
||||
),
|
||||
doc='constraint solver impedance: contact (npair x mjNIMP)', # pylint: disable=line-too-long
|
||||
doc='solver impedance: contact (npair x mjNIMP)', # pylint: disable=line-too-long
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='pair_margin',
|
||||
@@ -3279,7 +3286,15 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
inner_type=ValueType(name='mjtNum'),
|
||||
extents=(2,),
|
||||
),
|
||||
doc='constraint solver reference',
|
||||
doc='constraint solver reference, normal direction',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='solreffriction',
|
||||
type=ArrayType(
|
||||
inner_type=ValueType(name='mjtNum'),
|
||||
extents=(2,),
|
||||
),
|
||||
doc='constraint solver reference, friction directions',
|
||||
),
|
||||
StructFieldDecl(
|
||||
name='solimp',
|
||||
|
||||
@@ -486,6 +486,7 @@ MjContactWrapper::MjWrapper()
|
||||
X(frame),
|
||||
X(friction),
|
||||
X(solref),
|
||||
X(solreffriction),
|
||||
X(solimp),
|
||||
X(H) {}
|
||||
|
||||
@@ -495,6 +496,7 @@ MjContactWrapper::MjWrapper(raw::MjContact* ptr, py::handle owner)
|
||||
X(frame),
|
||||
X(friction),
|
||||
X(solref),
|
||||
X(solreffriction),
|
||||
X(solimp),
|
||||
X(H) {}
|
||||
#undef X
|
||||
@@ -1735,6 +1737,7 @@ This is useful for example when the MJB is not available as a file on disk.)"));
|
||||
X(frame);
|
||||
X(friction);
|
||||
X(solref);
|
||||
X(solreffriction);
|
||||
X(solimp);
|
||||
X(H);
|
||||
#undef X
|
||||
@@ -1766,6 +1769,7 @@ This is useful for example when the MJB is not available as a file on disk.)"));
|
||||
X(mjtNum, includemargin);
|
||||
XN(mjtNum, friction);
|
||||
XN(mjtNum, solref);
|
||||
XN(mjtNum, solreffriction);
|
||||
XN(mjtNum, solimp);
|
||||
X(mjtNum, mu);
|
||||
XN(mjtNum, H);
|
||||
|
||||
@@ -503,6 +503,7 @@ class MjWrapper<raw::MjContact> : public WrapperBase<raw::MjContact> {
|
||||
X(frame);
|
||||
X(friction);
|
||||
X(solref);
|
||||
X(solreffriction);
|
||||
X(solimp);
|
||||
X(H);
|
||||
#undef X
|
||||
|
||||
@@ -847,6 +847,7 @@ endbroad:
|
||||
void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user, mjtNum usermargin) {
|
||||
int num, type1, type2, condim;
|
||||
mjtNum margin, gap, mix, friction[5], solref[mjNREF], solimp[mjNIMP];
|
||||
mjtNum solreffriction[mjNREF] = {0};
|
||||
mjContact con[mjMAXCONPAIR];
|
||||
int ipair = (g2 < 0 ? g1 : -1);
|
||||
|
||||
@@ -1045,9 +1046,14 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
||||
friction[i] = m->pair_friction[5*ipair+i];
|
||||
}
|
||||
|
||||
// reference
|
||||
// reference, normal direction
|
||||
mju_copy(solref, m->pair_solref+mjNREF*ipair, mjNREF);
|
||||
|
||||
// reference, friction directions
|
||||
if (m->pair_solreffriction[mjNREF*ipair] || m->pair_solreffriction[mjNREF*ipair + 1]) {
|
||||
mju_copy(solreffriction, m->pair_solreffriction+mjNREF*ipair, mjNREF);
|
||||
}
|
||||
|
||||
// impedance
|
||||
mju_copy(solimp, m->pair_solimp+mjNIMP*ipair, mjNIMP);
|
||||
}
|
||||
@@ -1069,6 +1075,7 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
|
||||
con[i].includemargin = margin-gap;
|
||||
mju_copy(con[i].friction, friction, 5);
|
||||
mj_assignRef(m, con[i].solref, solref);
|
||||
mj_assignRef(m, con[i].solreffriction, solreffriction);
|
||||
mj_assignImp(m, con[i].solimp, solimp);
|
||||
|
||||
// exclude in gap
|
||||
|
||||
@@ -993,10 +993,14 @@ void mj_diagApprox(const mjModel* m, mjData* d) {
|
||||
|
||||
|
||||
// get solref, solimp for specified constraint
|
||||
static void getsolparam(const mjModel* m, const mjData* d, int i, mjtNum* solref, mjtNum* solimp) {
|
||||
static void getsolparam(const mjModel* m, const mjData* d, int i,
|
||||
mjtNum* solref, mjtNum* solreffriction, mjtNum* solimp) {
|
||||
// get constraint id
|
||||
int id = d->efc_id[i];
|
||||
|
||||
// clear solreffriction (applies only to contacts)
|
||||
mju_zero(solreffriction, mjNREF);
|
||||
|
||||
// extract solver parameters from corresponding model element
|
||||
switch (d->efc_type[i]) {
|
||||
case mjCNSTR_EQUALITY:
|
||||
@@ -1028,6 +1032,7 @@ static void getsolparam(const mjModel* m, const mjData* d, int i, mjtNum* solref
|
||||
case mjCNSTR_CONTACT_PYRAMIDAL:
|
||||
case mjCNSTR_CONTACT_ELLIPTIC:
|
||||
mju_copy(solref, d->contact[id].solref, mjNREF);
|
||||
mju_copy(solreffriction, d->contact[id].solreffriction, mjNREF);
|
||||
mju_copy(solimp, d->contact[id].solimp, mjNIMP);
|
||||
}
|
||||
|
||||
@@ -1042,6 +1047,17 @@ static void getsolparam(const mjModel* m, const mjData* d, int i, mjtNum* solref
|
||||
solref[0] = mju_max(solref[0], 2*m->opt.timestep);
|
||||
}
|
||||
|
||||
// check reference format: standard or direct, cannot be mixed
|
||||
if ((solreffriction[0] > 0) ^ (solreffriction[1] > 0)) {
|
||||
mju_warning("solreffriction values should have the same sign, replacing with default");
|
||||
mju_zero(solreffriction, mjNREF); // default solreffriction is (0, 0)
|
||||
}
|
||||
|
||||
// integrator safety: impose ref[0]>=2*timestep for standard format
|
||||
if (!mjDISABLED(mjDSBL_REFSAFE) && solreffriction[0] > 0) {
|
||||
solreffriction[0] = mju_max(solreffriction[0], 2*m->opt.timestep);
|
||||
}
|
||||
|
||||
// enforce constraints on solimp
|
||||
solimp[0] = mju_min(mjMAXIMP, mju_max(mjMINIMP, solimp[0]));
|
||||
solimp[1] = mju_min(mjMAXIMP, mju_max(mjMINIMP, solimp[1]));
|
||||
@@ -1149,12 +1165,12 @@ static void getimpedance(const mjtNum* solimp, mjtNum pos, mjtNum margin,
|
||||
void mj_makeImpedance(const mjModel* m, mjData* d) {
|
||||
int dim, nefc = d->nefc;
|
||||
mjtNum *R = d->efc_R, *KBIP = d->efc_KBIP;
|
||||
mjtNum pos, imp, impP, Rpy, solref[mjNREF], solimp[mjNIMP];
|
||||
mjtNum pos, imp, impP, Rpy, solref[mjNREF], solreffriction[mjNREF], solimp[mjNIMP];
|
||||
|
||||
// set efc_R, efc_KBIP
|
||||
for (int i=0; i < nefc; i++) {
|
||||
// get solref and solimp
|
||||
getsolparam(m, d, i, solref, solimp);
|
||||
getsolparam(m, d, i, solref, solreffriction, solimp);
|
||||
|
||||
// get pos and dim
|
||||
getposdim(m, d, i, &pos, &dim);
|
||||
@@ -1167,32 +1183,36 @@ void mj_makeImpedance(const mjModel* m, mjData* d) {
|
||||
// R = (1-imp)/imp * diagApprox
|
||||
R[i+j] = mju_max(mjMINVAL, (1-imp)*d->efc_diagApprox[i+j]/imp);
|
||||
|
||||
// friction: K = 0
|
||||
// constraint type
|
||||
int tp = d->efc_type[i+j];
|
||||
if (tp == mjCNSTR_FRICTION_DOF ||
|
||||
tp == mjCNSTR_FRICTION_TENDON ||
|
||||
(tp == mjCNSTR_CONTACT_ELLIPTIC && j > 0)) {
|
||||
|
||||
// elliptic contacts use solreffriction in non-normal directions, if non-zero
|
||||
int elliptic_friction = (tp == mjCNSTR_CONTACT_ELLIPTIC) && (j > 0);
|
||||
mjtNum* ref = elliptic_friction && (solreffriction[0] || solreffriction[1]) ?
|
||||
solreffriction : solref;
|
||||
|
||||
// friction: K = 0
|
||||
if (tp == mjCNSTR_FRICTION_DOF || tp == mjCNSTR_FRICTION_TENDON || elliptic_friction) {
|
||||
KBIP[4*(i+j)] = 0;
|
||||
}
|
||||
|
||||
// standard: K = 1 / (dmax^2 * timeconst^2 * dampratio^2)
|
||||
else if (solref[0] > 0)
|
||||
KBIP[4*(i+j)] = 1 / mju_max(mjMINVAL,
|
||||
solimp[1]*solimp[1] * solref[0]*solref[0] * solref[1]*solref[1]);
|
||||
else if (ref[0] > 0)
|
||||
KBIP[4*(i+j)] = 1 / mju_max(mjMINVAL, solimp[1]*solimp[1] * ref[0]*ref[0] * ref[1]*ref[1]);
|
||||
|
||||
// direct: K = -solref[0] / dmax^2
|
||||
else {
|
||||
KBIP[4*(i+j)] = -solref[0] / mju_max(mjMINVAL, solimp[1]*solimp[1]);
|
||||
KBIP[4*(i+j)] = -ref[0] / mju_max(mjMINVAL, solimp[1]*solimp[1]);
|
||||
}
|
||||
|
||||
// standard: B = 2 / (dmax*timeconst)
|
||||
if (solref[1] > 0) {
|
||||
KBIP[4*(i+j)+1] = 2 / mju_max(mjMINVAL, solimp[1]*solref[0]);
|
||||
if (ref[1] > 0) {
|
||||
KBIP[4*(i+j)+1] = 2 / mju_max(mjMINVAL, solimp[1]*ref[0]);
|
||||
}
|
||||
|
||||
// direct: B = -solref[1] / dmax
|
||||
else {
|
||||
KBIP[4*(i+j)+1] = -solref[1] / mju_max(mjMINVAL, solimp[1]);
|
||||
KBIP[4*(i+j)+1] = -ref[1] / mju_max(mjMINVAL, solimp[1]);
|
||||
}
|
||||
|
||||
// I = imp, P = imp'
|
||||
|
||||
@@ -1871,6 +1871,7 @@ void mjCModel::CopyObjects(mjModel* m) {
|
||||
m->pair_geom2[i] = pairs[i]->geom2;
|
||||
m->pair_signature[i] = pairs[i]->signature;
|
||||
copyvec(m->pair_solref+mjNREF*i, pairs[i]->solref, mjNREF);
|
||||
copyvec(m->pair_solreffriction+mjNREF*i, pairs[i]->solreffriction, mjNREF);
|
||||
copyvec(m->pair_solimp+mjNIMP*i, pairs[i]->solimp, mjNIMP);
|
||||
m->pair_margin[i] = (mjtNum)pairs[i]->margin;
|
||||
m->pair_gap[i] = (mjtNum)pairs[i]->gap;
|
||||
@@ -3037,6 +3038,7 @@ bool mjCModel::CopyBack(const mjModel* m) {
|
||||
// pairs
|
||||
for (int i=0; i<npair; i++) {
|
||||
copyvec(pairs[i]->solref, m->pair_solref+mjNREF*i, mjNREF);
|
||||
copyvec(pairs[i]->solreffriction, m->pair_solreffriction+mjNREF*i, mjNREF);
|
||||
copyvec(pairs[i]->solimp, m->pair_solimp+mjNIMP*i, mjNIMP);
|
||||
pairs[i]->margin = (double)m->pair_margin[i];
|
||||
pairs[i]->gap = (double)m->pair_gap[i];
|
||||
|
||||
@@ -2931,6 +2931,7 @@ mjCPair::mjCPair(mjCModel* _model, mjCDef* _def) {
|
||||
|
||||
condim = 3;
|
||||
mj_defaultSolRefImp(solref, solimp);
|
||||
mju_zero(solreffriction, mjNREF);
|
||||
margin = 0;
|
||||
gap = 0;
|
||||
friction[0] = 1;
|
||||
|
||||
@@ -772,7 +772,8 @@ class mjCPair : public mjCBase {
|
||||
|
||||
// optional parameters: computed from geoms if not set by user
|
||||
int condim; // contact dimensionality
|
||||
mjtNum solref[mjNREF]; // solver reference
|
||||
mjtNum solref[mjNREF]; // solver reference, normal direction
|
||||
mjtNum solreffriction[mjNREF]; // solver reference, frictional directions
|
||||
mjtNum solimp[mjNIMP]; // solver impedance
|
||||
double margin; // margin for contact detection
|
||||
double gap; // include in solver if dist<margin-gap
|
||||
|
||||
@@ -153,7 +153,8 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
|
||||
"axisangle", "xyaxes", "zaxis", "euler", "mode", "user"},
|
||||
{"light", "?", "12", "pos", "dir", "directional", "castshadow", "active",
|
||||
"attenuation", "cutoff", "exponent", "ambient", "diffuse", "specular", "mode"},
|
||||
{"pair", "?", "6", "condim", "friction", "solref", "solimp", "gap", "margin"},
|
||||
{"pair", "?", "7", "condim", "friction", "solref", "solreffriction", "solimp",
|
||||
"gap", "margin"},
|
||||
{"equality", "?", "3", "active", "solref", "solimp"},
|
||||
{"tendon", "?", "16", "group", "limited", "range",
|
||||
"solreflimit", "solimplimit", "solreffriction", "solimpfriction",
|
||||
@@ -283,8 +284,8 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
|
||||
|
||||
{"contact", "*", "0"},
|
||||
{"<"},
|
||||
{"pair", "*", "10", "name", "class", "geom1", "geom2", "condim", "friction",
|
||||
"solref", "solimp", "gap", "margin"},
|
||||
{"pair", "*", "11", "name", "class", "geom1", "geom2", "condim", "friction",
|
||||
"solref", "solreffriction", "solimp", "gap", "margin"},
|
||||
{"exclude", "*", "3", "name", "body1", "body2"},
|
||||
{">"},
|
||||
|
||||
@@ -1495,6 +1496,7 @@ void mjXReader::OnePair(XMLElement* elem, mjCPair* ppair) {
|
||||
ReadAttrTxt(elem, "name", ppair->name);
|
||||
ReadAttrInt(elem, "condim", &ppair->condim);
|
||||
ReadAttr(elem, "solref", mjNREF, ppair->solref, text, false, false);
|
||||
ReadAttr(elem, "solreffriction", mjNREF, ppair->solreffriction, text, false, false);
|
||||
ReadAttr(elem, "solimp", mjNIMP, ppair->solimp, text, false, false);
|
||||
ReadAttr(elem, "margin", 1, &ppair->margin, text);
|
||||
ReadAttr(elem, "gap", 1, &ppair->gap, text);
|
||||
|
||||
@@ -443,6 +443,7 @@ void mjXWriter::OnePair(XMLElement* elem, mjCPair* ppair, mjCDef* def) {
|
||||
WriteAttr(elem, "margin", 1, &ppair->margin, &def->pair.margin);
|
||||
WriteAttr(elem, "gap", 1, &ppair->gap, &def->pair.gap);
|
||||
WriteAttr(elem, "solref", mjNREF, ppair->solref, def->pair.solref);
|
||||
WriteAttr(elem, "solreffriction", mjNREF, ppair->solreffriction, def->pair.solreffriction);
|
||||
WriteAttr(elem, "solimp", mjNIMP, ppair->solimp, def->pair.solimp);
|
||||
WriteAttr(elem, "friction", 5, ppair->friction, def->pair.friction);
|
||||
}
|
||||
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
<mujoco>
|
||||
<option cone="elliptic" timestep="1e-4" integrator="implicitfast"/>
|
||||
|
||||
<visual>
|
||||
<global elevation="0"/>
|
||||
</visual>
|
||||
|
||||
<asset>
|
||||
<texture name="grid" type="2d" builtin="checker" rgb1=".1 .2 .3" rgb2=".2 .3 .4" width="300" height="300"/>
|
||||
<material name="grid" texture="grid" texrepeat="8 8" reflectance=".2"/>
|
||||
<texture name="ball" type="cube" builtin="checker" rgb1=".3 .3 .3" rgb2="1 1 1" width="300" height="300"/>
|
||||
<material name="ball" texture="ball" texrepeat="8 8"/>
|
||||
</asset>
|
||||
|
||||
<worldbody>
|
||||
<geom name="floor" size=".2 .2 .01" type="plane" material="grid"/>
|
||||
<geom name="wall" size=".2 .2 .01" type="plane" material="grid" pos=".2 0 .2" zaxis="-1 0 0"/>
|
||||
<light pos="0 0 .6"/>
|
||||
<light pos="-.6 0 .6" dir="1 0 -1"/>
|
||||
<body name="ball" pos="-.1 0 .2">
|
||||
<freejoint/>
|
||||
<geom name="ball" type="sphere" size=".02" material="ball" mass=".001"/>
|
||||
<body name="ballast">
|
||||
<joint type="ball" stiffness="0.1" damping=".0001"/>
|
||||
<geom name="ballast" type="sphere" size=".02" contype="0" conaffinity="0" mass=".01" group="3"/>
|
||||
</body>
|
||||
</body>
|
||||
</worldbody>
|
||||
|
||||
<default>
|
||||
<pair solref="-100000 0" solreffriction="0 -10000"/>
|
||||
</default>
|
||||
|
||||
<contact>
|
||||
<pair geom1="floor" geom2="ball"/>
|
||||
<pair geom1="wall" geom2="ball"/>
|
||||
</contact>
|
||||
|
||||
<keyframe>
|
||||
<key name="throw" qvel="1.3 0 0 0 0 0 0 0 0"/>
|
||||
</keyframe>
|
||||
</mujoco>
|
||||
@@ -524,6 +524,7 @@ public unsafe struct mjContact_ {
|
||||
public double includemargin;
|
||||
public fixed double friction[5];
|
||||
public fixed double solref[2];
|
||||
public fixed double solreffriction[2];
|
||||
public fixed double solimp[5];
|
||||
public double mu;
|
||||
public fixed double H[36];
|
||||
@@ -2130,6 +2131,7 @@ public unsafe struct mjModel_ {
|
||||
public int* pair_geom2;
|
||||
public int* pair_signature;
|
||||
public double* pair_solref;
|
||||
public double* pair_solreffriction;
|
||||
public double* pair_solimp;
|
||||
public double* pair_margin;
|
||||
public double* pair_gap;
|
||||
|
||||
Reference in New Issue
Block a user