Skip to content

Commit 7174d33

Browse files
kbayescopybara-github
authored andcommitted
Introduce mjPreContact, a minimal struct passed into the collision functions.
PiperOrigin-RevId: 918533795 Change-Id: I2b5af05c1479b25d5c2cfdc690321a26fce6ede6
1 parent 53b3137 commit 7174d33

25 files changed

Lines changed: 709 additions & 406 deletions

doc/APIreference/APItypes.rst

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,15 @@ MJCF element :ref:`statistic <statistic>`. One instance of it is embedded in mjM
936936
.. mujoco-include:: mjStatistic
937937

938938

939+
.. _mjPreContact:
940+
941+
mjPreContact
942+
~~~~~~~~~~~~
943+
944+
This is the data structure holding information about one contact filled out by a narrowphase collision detector.
945+
946+
.. mujoco-include:: mjPreContact
947+
939948
.. _mjContact:
940949

941950
mjContact
@@ -1780,7 +1789,7 @@ mjfCollision
17801789
.. code-block:: C
17811790
17821791
typedef int (*mjfCollision)(const mjModel* m, const mjData* d,
1783-
mjContact* con, int g1, int g2, mjtNum margin);
1792+
mjPreContact* con, int g1, int g2, mjtNum margin);
17841793
17851794
This is the function type of the callbacks in the collision table :ref:`mjCOLLISIONFUNC`.
17861795

doc/changelog.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ General
7070
Negative ``margin`` values are now permitted (corresponding to ``gap > margin`` under the old semantics). The
7171
constraint ``margin + gap >= 0`` should be maintained to ensure valid collision detection.
7272

73+
- The :ref:`mjfCollision` functions now populate the :ref:`mjPreContact` struct instead of the :ref:`mjContact`
74+
struct. The :ref:`mjPreContact` only contains the necessary fields needed for the narrowphase collision detection.
75+
7376
- MJX: Removed the deprecated ``nconmax`` argument from ``mjx.make_data`` and ``mjx.put_data`` in favor of
7477
``naconmax``.
7578

doc/includes/references.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,15 @@ typedef enum mjtSleepState_ { // sleep state of an object
101101
mjS_ASLEEP = 0, // object is asleep
102102
mjS_AWAKE = 1 // object is awake
103103
} mjtSleepState;
104+
struct mjPreContact_ { // contact parameters set by narrowphase collision functions
105+
mjtNum dist;
106+
mjtNum pos[3];
107+
mjtNum normal[3]; // contact normal of the collision
108+
mjtNum tangent[3]; // first tangent direction
109+
};
110+
typedef struct mjPreContact_ mjPreContact;
104111
struct mjContact_ { // result of collision detection functions
105-
// contact parameters set by near-phase collision function
112+
// contact parameters set by narrowphase collision function
106113
mjtNum dist; // distance between nearest points; neg: penetration
107114
mjtNum pos[3]; // position of contact point: midpoint between geoms
108115
mjtNum frame[9]; // normal is in [0-2], points from geom[0] to geom[1]

include/mujoco/mjdata.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,18 @@ typedef enum mjtSleepState_ { // sleep state of an object
121121
} mjtSleepState;
122122

123123

124-
//---------------------------------- mjContact -----------------------------------------------------
124+
//------------------------------------- Contact ----------------------------------------------------
125+
126+
struct mjPreContact_ { // contact parameters set by narrowphase collision functions
127+
mjtNum dist;
128+
mjtNum pos[3];
129+
mjtNum normal[3]; // contact normal of the collision
130+
mjtNum tangent[3]; // first tangent direction
131+
};
132+
typedef struct mjPreContact_ mjPreContact;
125133

126134
struct mjContact_ { // result of collision detection functions
127-
// contact parameters set by near-phase collision function
135+
// contact parameters set by narrowphase collision function
128136
mjtNum dist; // distance between nearest points; neg: penetration
129137
mjtNum pos[3]; // position of contact point: midpoint between geoms
130138
mjtNum frame[9]; // normal is in [0-2], points from geom[0] to geom[1]
@@ -533,7 +541,7 @@ typedef mjtNum (*mjfTime)(void);
533541
typedef mjtNum (*mjfAct)(const mjModel* m, const mjData* d, int id);
534542

535543
// collision detection
536-
typedef int (*mjfCollision)(const mjModel* m, mjData* d, mjContact* con, int g1, int g2,
544+
typedef int (*mjfCollision)(const mjModel* m, mjData* d, mjPreContact* con, int g1, int g2,
537545
mjtNum margin);
538546

539547
#endif // MUJOCO_MJDATA_H_

python/mujoco/introspect/structs.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5140,6 +5140,42 @@
51405140
),
51415141
),
51425142
)),
5143+
('mjPreContact',
5144+
StructDecl(
5145+
name='mjPreContact',
5146+
declname='struct mjPreContact_',
5147+
fields=(
5148+
StructFieldDecl(
5149+
name='dist',
5150+
type=ValueType(name='mjtNum'),
5151+
doc='',
5152+
),
5153+
StructFieldDecl(
5154+
name='pos',
5155+
type=ArrayType(
5156+
inner_type=ValueType(name='mjtNum'),
5157+
extents=(3,),
5158+
),
5159+
doc='',
5160+
),
5161+
StructFieldDecl(
5162+
name='normal',
5163+
type=ArrayType(
5164+
inner_type=ValueType(name='mjtNum'),
5165+
extents=(3,),
5166+
),
5167+
doc='contact normal of the collision',
5168+
),
5169+
StructFieldDecl(
5170+
name='tangent',
5171+
type=ArrayType(
5172+
inner_type=ValueType(name='mjtNum'),
5173+
extents=(3,),
5174+
),
5175+
doc='first tangent direction',
5176+
),
5177+
),
5178+
)),
51435179
('mjContact',
51445180
StructDecl(
51455181
name='mjContact',

python/mujoco/raw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
// to them under the "raw" namespace.
2626
namespace mujoco::raw {
2727

28+
using MjPreContact = ::mjPreContact;
2829
using MjContact = ::mjContact;
2930
using MjData = ::mjData;
3031
using MjLROpt = ::mjLROpt;

python/mujoco/structs.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,32 @@ This is useful for example when the MJB is not available as a file on disk.)"));
615615
X(int, nupdate);
616616
#undef X
617617

618+
// ==================== MJPRECONTACT ==========================================
619+
py::class_<MjPreContactWrapper> mjPreContact(m, "MjPreContact");
620+
mjPreContact.def(py::init<>());
621+
mjPreContact.def("__copy__", [](const MjPreContactWrapper& self) {
622+
return MjPreContactWrapper(self);
623+
});
624+
mjPreContact.def("__deepcopy__", [](const MjPreContactWrapper& self, py::dict) {
625+
return MjPreContactWrapper(self);
626+
});
627+
DefineStructFunctions(mjPreContact);
628+
629+
#define X(var) \
630+
mjPreContact.def_property( \
631+
#var, [](const MjPreContactWrapper& c) { return c.get()->var; }, \
632+
[](MjPreContactWrapper& c, decltype(raw::MjPreContact::var) rhs) { \
633+
c.get()->var = rhs; \
634+
})
635+
X(dist);
636+
#undef X
637+
638+
#define X(var) DefinePyArray(mjPreContact, #var, &MjPreContactWrapper::var)
639+
X(pos);
640+
X(normal);
641+
X(tangent);
642+
#undef X
643+
618644
// ==================== MJCONTACT ============================================
619645
py::class_<MjContactWrapper> mjContact(m, "MjContact");
620646
mjContact.def(py::init<>());

python/mujoco/structs.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,27 @@ template <>
547547
struct enable_if_mj_struct<raw::MjModel> { using type = void; };
548548

549549
// ==================== MJCONTACT ==============================================
550+
template <>
551+
class MjWrapper<raw::MjPreContact> : public WrapperBase<raw::MjPreContact> {
552+
public:
553+
MjWrapper();
554+
MjWrapper(const MjWrapper&);
555+
MjWrapper(MjWrapper&&) = default;
556+
MjWrapper(raw::MjPreContact* ptr, pybind11::handle owner);
557+
~MjWrapper() = default;
558+
559+
#define X(var) \
560+
py_array_or_tuple_t< \
561+
std::remove_all_extents_t<decltype(raw::MjPreContact::var)>> \
562+
var
563+
X(pos);
564+
X(normal);
565+
X(tangent);
566+
#undef X
567+
};
568+
569+
using MjPreContactWrapper = MjWrapper<raw::MjPreContact>;
570+
550571
template <>
551572
class MjWrapper<raw::MjContact> : public WrapperBase<raw::MjContact> {
552573
public:
@@ -961,6 +982,7 @@ using _impl::MjSolverStatWrapper;
961982
using _impl::MjModelWrapper;
962983
using _impl::MjDataWrapper;
963984
using _impl::MjContactWrapper;
985+
using _impl::MjPreContactWrapper;
964986
using _impl::MjvPerturbWrapper;
965987
using _impl::MjvCameraWrapper;
966988
using _impl::MjvGLCameraWrapper;

python/mujoco/structs_wrappers.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,26 @@ std::unique_ptr<MjModelWrapper> MjModelWrapper::Deserialize(
535535
return std::unique_ptr<MjModelWrapper>(new MjModelWrapper(model));
536536
}
537537

538+
// ==================== MJPRECONTACT ==========================================
539+
#define X(var) var(InitPyArray(ptr_->var, owner_))
540+
MjPreContactWrapper::MjWrapper()
541+
: WrapperBase(new raw::MjPreContact{}),
542+
X(pos),
543+
X(normal),
544+
X(tangent) {}
545+
546+
MjPreContactWrapper::MjWrapper(raw::MjPreContact* ptr, py::handle owner)
547+
: WrapperBase(ptr, owner),
548+
X(pos),
549+
X(normal),
550+
X(tangent) {}
551+
#undef X
552+
553+
MjPreContactWrapper::MjWrapper(const MjPreContactWrapper& other)
554+
: MjPreContactWrapper() {
555+
*this->ptr_ = *other.ptr_;
556+
}
557+
538558
// ==================== MJCONTACT ==============================================
539559
#define X(var) var(InitPyArray(ptr_->var, owner_))
540560
MjContactWrapper::MjWrapper()

0 commit comments

Comments
 (0)