Add mj_maxContact API function.

PiperOrigin-RevId: 903135055
Change-Id: I5f103c7d51f97e327c923bc567002ace835f5517
This commit is contained in:
Kyle Bayes
2026-04-21 04:02:34 -07:00
committed by Copybara-Service
parent bc5883e82f
commit 3325971840
13 changed files with 448 additions and 21 deletions
+12
View File
@@ -1179,6 +1179,18 @@ It is also triggered for :ref:`user sensors<sensor-user>` of :ref:`stage<sensor-
The computed force arrays ``cfrc_int`` and ``cfrc_ext`` currently suffer from a know bug, they do not take into account
the effect of spatial tendons, see :issue:`832`.
.. _mj_maxContact:
`mj_maxContact <#mj_maxContact>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mj_maxContact
Return the maximum number of contacts that can be generated between two geoms.
If has_margin is -1, then the margin is pulled from the model, otherwise if has_margin > 0
indicates that the geoms have a positive margin.
.. _mj_collision:
`mj_collision <#mj_collision>`__
+2 -1
View File
@@ -7,7 +7,8 @@ Upcoming version (not yet released)
General
^^^^^^^
- Added new :ref:`mj_maxContact<mj_maxContact>` function to get the maximum number of possible contacts returned by
two geoms.
- Added :ref:`multi-cell support<body-flexcomp-cellnum>` for trilinear and quadratic flexes. Note that the implicit
integrator uses a dense solver for the flex degrees of freedom, which can be slow for multi-cell flexes.
- Refactored ``flexstrain`` equality constraints to be instantiated per cell instead of per flex object, reducing the
+127 -18
View File
@@ -1718,9 +1718,36 @@ work, but it pays off at runtime and yields both faster and more stable simulati
Pair-wise colliders
^^^^^^^^^^^^^^^^^^^
The table below provides information about the colliders used for different geom pairs. The second row in each cell
lists the maximum number of contacts generated, possibly with ``multiccd`` enabled. For example, ``Mesh`` / ``Mesh``
will generate up to 1 contact or with ``multiccd`` up to 4 contacts.
The table below provides information about the colliders used for different geom pairs. These values can be computed
dynamically by the :ref:`mj_maxContact` function. Use the toggles to see the max number of contacts returned with the
parameters :ref:`nativeccd<option-flag-nativeccd>`, :ref:`multiccd<option-flag-multiccd>`, and
:ref:`margin<body-geom-margin>`.
.. raw:: html
<div class="pairwise-toggles">
<div class="pairwise-toggle-item">
<label class="pairwise-switch">
<input type="checkbox" id="nativeccd-checkbox" checked>
<span class="pairwise-slider"></span>
</label>
<span>nativeccd</span>
</div>
<div class="pairwise-toggle-item">
<label class="pairwise-switch">
<input type="checkbox" id="multiccd-checkbox">
<span class="pairwise-slider"></span>
</label>
<span>multiccd</span>
</div>
<div class="pairwise-toggle-item">
<label class="pairwise-switch">
<input type="checkbox" id="margin-checkbox">
<span class="pairwise-slider"></span>
</label>
<span>with margin</span>
</div>
</div>
.. list-table::
:header-rows: 1
@@ -1744,7 +1771,7 @@ will generate up to 1 contact or with ``multiccd`` up to 4 contacts.
- | primitive
| **1**
- | primitive
| **2**
| **4**
- | primitive
| **4**
- | primitive
@@ -1787,12 +1814,28 @@ will generate up to 1 contact or with ``multiccd`` up to 4 contacts.
| **2**
- | CCD
| **1**
- | CCD
| **1**, **4**
-
.. raw:: html
<div class="line">CCD</div>
<div class="line">
<div class="multiccd-off"><strong>1</strong></div>
<div class="multiccd-native"><strong>5</strong></div>
<div class="multiccd-legacy"><strong>5</strong></div>
</div>
- | primitive
| **2**
- | CCD
| **1**, **4**
-
.. raw:: html
<div class="line">CCD</div>
<div class="line">
<div class="multiccd-off"><strong>1</strong></div>
<div class="multiccd-native"><strong>5</strong></div>
<div class="multiccd-legacy"><strong>5</strong></div>
</div>
- | SDF
| :ref:`sdf_initpoints <option-sdf_initpoints>`
* - Ellipsoid
@@ -1812,12 +1855,36 @@ will generate up to 1 contact or with ``multiccd`` up to 4 contacts.
-
-
-
- | CCD
| **1**, **4**
- | CCD
| **1**, **4**
- | CCD
| **1**, **4**
-
.. raw:: html
<div class="line">CCD</div>
<div class="line">
<div class="multiccd-off"><strong>1</strong></div>
<div class="multiccd-native"><strong>5</strong></div>
<div class="multiccd-legacy"><strong>5</strong></div>
</div>
-
.. raw:: html
<div class="line">CCD</div>
<div class="line">
<div class="multiccd-off"><strong>1</strong></div>
<div class="multiccd-native"><strong>5</strong></div>
<div class="multiccd-legacy"><strong>5</strong></div>
</div>
-
.. raw:: html
<div class="line">CCD</div>
<div class="line">
<div class="multiccd-off"><strong>1</strong></div>
<div class="multiccd-native"><strong>5</strong></div>
<div class="multiccd-legacy"><strong>5</strong></div>
</div>
- | SDF
| :ref:`sdf_initpoints <option-sdf_initpoints>`
* - Box
@@ -1827,8 +1894,16 @@ will generate up to 1 contact or with ``multiccd`` up to 4 contacts.
-
- | primitive
| **8**
- | CCD
| **1**, **4**
-
.. raw:: html
<div class="line">CCD</div>
<div class="line">
<div class="multiccd-off"><strong>1</strong></div>
<div class="multiccd-native"><strong>4</strong></div>
<div class="multiccd-legacy"><strong>5</strong></div>
</div>
- | SDF
| :ref:`sdf_initpoints <option-sdf_initpoints>`
* - Mesh
@@ -1837,8 +1912,16 @@ will generate up to 1 contact or with ``multiccd`` up to 4 contacts.
-
-
-
- | CCD
| **1**, **4**
-
.. raw:: html
<div class="line">CCD</div>
<div class="line">
<div class="multiccd-off"><strong>1</strong></div>
<div class="multiccd-native"><strong>4</strong></div>
<div class="multiccd-legacy"><strong>5</strong></div>
</div>
- | MeshSDF
| :ref:`sdf_initpoints <option-sdf_initpoints>`
* - SDF
@@ -1851,6 +1934,32 @@ will generate up to 1 contact or with ``multiccd`` up to 4 contacts.
- | SDF
| :ref:`sdf_initpoints <option-sdf_initpoints>`
.. raw:: html
<script>
const pairwiseToggles = () => {
const table = document.querySelector('.table-pairwise');
const toggles = [
{id: 'nativeccd-checkbox', cls: 'nativeccd-enabled'},
{id: 'multiccd-checkbox', cls: 'multiccd-enabled'},
{id: 'margin-checkbox', cls: 'margin-enabled'}
];
toggles.forEach(toggle => {
const cb = document.getElementById(toggle.id);
if (cb.checked) {
table.classList.add(toggle.cls);
}
cb.addEventListener('change', () => {
table.classList.toggle(toggle.cls, this.checked);
});
});
};
pairwiseToggles();
</script>
.. _Sleeping:
Sleeping islands
+92
View File
@@ -54,6 +54,98 @@ body[data-theme="dark"] table.docutils:not(.mjcf-attributes) {
font-size: 85%;
}
.pairwise-toggles {
display: flex;
align-items: center;
gap: 1.5em;
margin-bottom: 0.75em;
}
.pairwise-toggle-item {
display: flex;
align-items: center;
gap: 0.5em;
}
.pairwise-switch {
position: relative;
display: inline-block;
width: 36px;
height: 20px;
}
.pairwise-switch input {
opacity: 0;
width: 0;
height: 0;
}
.pairwise-slider {
position: absolute;
cursor: pointer;
inset: 0;
background-color: #ccc;
transition: 0.3s;
border-radius: 20px;
}
.pairwise-slider:before {
content: "";
position: absolute;
height: 14px;
width: 14px;
left: 3px;
bottom: 3px;
background-color: white;
transition: 0.3s;
border-radius: 50%;
}
.pairwise-switch input:checked + .pairwise-slider {
background-color: var(--secondary-header-color, #123693);
}
.pairwise-switch input:checked + .pairwise-slider:before {
transform: translateX(16px);
}
.multiccd-off,
.multiccd-native,
.multiccd-legacy {
display: none;
margin: 0;
}
.multiccd-off {
display: inline;
}
.multiccd-enabled .multiccd-off {
display: none;
}
.multiccd-enabled.nativeccd-enabled:not(.margin-enabled) .multiccd-native {
display: inline;
}
.multiccd-enabled:not(.nativeccd-enabled) .multiccd-legacy,
.multiccd-enabled.nativeccd-enabled.margin-enabled .multiccd-legacy {
display: inline;
}
.margin-show {
display: none;
}
.margin-enabled .margin-hide {
display: none;
}
.margin-enabled .margin-show {
display: inline;
}
.small-centered td, .small-centered th,
.table-pairwise td, .table-pairwise th {
text-align: center !important;
+1
View File
@@ -3272,6 +3272,7 @@ void mj_passive(const mjModel* m, mjData* d);
void mj_subtreeVel(const mjModel* m, mjData* d);
void mj_rne(const mjModel* m, mjData* d, int flg_acc, mjtNum* result);
void mj_rnePostConstraint(const mjModel* m, mjData* d);
int mj_maxContact(const mjModel* m, int g1, int g2, int has_margin);
void mj_collision(const mjModel* m, mjData* d);
void mj_makeConstraint(const mjModel* m, mjData* d);
void mj_island(const mjModel* m, mjData* d);