Add mjtSameFrame enum to specify frame alignment of bodies with their children.
PiperOrigin-RevId: 666303674 Change-Id: I53dc56e1ca52afa280ae5abaf4158edc465fb1e0
This commit is contained in:
committed by
Copybara-Service
parent
a2649d6cec
commit
8b03daa09b
@@ -346,6 +346,16 @@ These are the possible sensor data types, used in ``mjData.sensor_datatype``.
|
|||||||
.. mujoco-include:: mjtDataType
|
.. mujoco-include:: mjtDataType
|
||||||
|
|
||||||
|
|
||||||
|
.. _mjtSameFrame:
|
||||||
|
|
||||||
|
mjtSameFrame
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Types of frame alignment of elements with their parent bodies. Used as shortcuts during :ref:`mj_kinematics` in the
|
||||||
|
last argument to :ref:`mj_local2global`.
|
||||||
|
|
||||||
|
.. mujoco-include:: mjtSameFrame
|
||||||
|
|
||||||
|
|
||||||
.. _tyDataEnums:
|
.. _tyDataEnums:
|
||||||
|
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ mj_local2Global
|
|||||||
|
|
||||||
.. mujoco-include:: mj_local2Global
|
.. mujoco-include:: mj_local2Global
|
||||||
|
|
||||||
Map from body local to global Cartesian coordinates.
|
Map from body local to global Cartesian coordinates, sameframe takes values from mjtSameFrame.
|
||||||
|
|
||||||
.. _mj_getTotalmass:
|
.. _mj_getTotalmass:
|
||||||
|
|
||||||
|
|||||||
+14
-11
@@ -12,31 +12,34 @@ General
|
|||||||
early stages of testing.
|
early stages of testing.
|
||||||
2. Added :ref:`mjSpec` option for creating a texture from a buffer.
|
2. Added :ref:`mjSpec` option for creating a texture from a buffer.
|
||||||
3. :ref:`shellinertia <body-geom-shellinertia>` is now supported by all geom types.
|
3. :ref:`shellinertia <body-geom-shellinertia>` is now supported by all geom types.
|
||||||
4. Added support for :ref:`attaching<meAttachment>` keyframes.
|
4. When :ref:`attaching<meAttachment>` sub-models, :ref:`keyframes<keyframe>` will now be correctly merged into the
|
||||||
|
parent model, but only on the first attachment.
|
||||||
|
5. Added the :ref:`mjtSameFrame` enum which contains the possible frame alignments of bodies and their children. These
|
||||||
|
alignments are used as shortcuts in :ref:`mj_kinematics`.
|
||||||
|
|
||||||
MJX
|
MJX
|
||||||
^^^
|
^^^
|
||||||
5. Added ``efc_pos`` to ``mjx.Data`` (:github:issue:`1388`).
|
6. Added ``efc_pos`` to ``mjx.Data`` (:github:issue:`1388`).
|
||||||
6. Added position-dependent sensors: ``MAGNETOMETER``, ``CAMPROJECTION``, ``RANGEFINDER``, ``JOINTPOS``,
|
7. Added position-dependent sensors: ``MAGNETOMETER``, ``CAMPROJECTION``, ``RANGEFINDER``, ``JOINTPOS``,
|
||||||
``ACTUATORPOS``, ``BALLQUAT``, ``FRAMEPOS``, ``FRAMEXAXIS``, ``FRAMEYAXIS``, ``FRAMEZAXIS``, ``FRAMEQUAT``,
|
``ACTUATORPOS``, ``BALLQUAT``, ``FRAMEPOS``, ``FRAMEXAXIS``, ``FRAMEYAXIS``, ``FRAMEZAXIS``, ``FRAMEQUAT``,
|
||||||
``SUBTREECOM``, ``CLOCK``.
|
``SUBTREECOM``, ``CLOCK``.
|
||||||
7. Added velocity-dependent sensors: ``JOINTVEL``, ``ACTUATORVEL``, ``BALLANGVEL``.
|
8. Added velocity-dependent sensors: ``JOINTVEL``, ``ACTUATORVEL``, ``BALLANGVEL``.
|
||||||
8. Added acceleration/force-dependent sensors: ``ACTUATORFRC``, ``JOINTACTFRC``.
|
9. Added acceleration/force-dependent sensors: ``ACTUATORFRC``, ``JOINTACTFRC``.
|
||||||
9. Changed default policy to avoid placing unused (MuJoCo-only) arrays on device.
|
10. Changed default policy to avoid placing unused (MuJoCo-only) arrays on device.
|
||||||
10. Added ``device`` parameter to ``mjx.make_data`` to bring it to parity with ``mjx.put_model`` and ``mjx.put_data``.
|
11. Added ``device`` parameter to ``mjx.make_data`` to bring it to parity with ``mjx.put_model`` and ``mjx.put_data``.
|
||||||
11. Added support for :ref:`implicitfast integration<geIntegration>` for all cases except
|
12. Added support for :ref:`implicitfast integration<geIntegration>` for all cases except
|
||||||
:doc:`fluid drag <computation/fluid>`.
|
:doc:`fluid drag <computation/fluid>`.
|
||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
12. Fixed a performance regression introduced in 3.1.7 in mesh Bounding Volume Hierarchies (:github:issue:`1875`,
|
13. Fixed a performance regression introduced in 3.1.7 in mesh Bounding Volume Hierarchies (:github:issue:`1875`,
|
||||||
contribution by :github:user:`michael-ahn`).
|
contribution by :github:user:`michael-ahn`).
|
||||||
13. Fixed a bug wherein, for models that have both muscles and stateless actuators and used one of the implicit
|
14. Fixed a bug wherein, for models that have both muscles and stateless actuators and used one of the implicit
|
||||||
integrators, wrong derivatives would be computed.
|
integrators, wrong derivatives would be computed.
|
||||||
|
|
||||||
Python bindings
|
Python bindings
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
14. Added support for engine plugins in :ref:`mjSpec` (:github:issue:`1903`).
|
15. Added support for engine plugins in :ref:`mjSpec` (:github:issue:`1903`).
|
||||||
|
|
||||||
|
|
||||||
Version 3.2.2 (Aug 8, 2024)
|
Version 3.2.2 (Aug 8, 2024)
|
||||||
|
|||||||
@@ -684,6 +684,11 @@ typedef enum mjtDataType_ { // data type for sensors
|
|||||||
mjDATATYPE_AXIS, // 3D unit vector
|
mjDATATYPE_AXIS, // 3D unit vector
|
||||||
mjDATATYPE_QUATERNION // unit quaternion
|
mjDATATYPE_QUATERNION // unit quaternion
|
||||||
} mjtDataType;
|
} mjtDataType;
|
||||||
|
typedef enum mjtSameFrame_ { // frame alignment of bodies with their children
|
||||||
|
mjSAMEFRAME_NONE = 0, // no alignment
|
||||||
|
mjSAMEFRAME_BODY, // frame is same as body frame
|
||||||
|
mjSAMEFRAME_INERTIA, // frame is same as inertial frame
|
||||||
|
} mjtSameFrame;
|
||||||
typedef enum mjtLRMode_ { // mode for actuator length range computation
|
typedef enum mjtLRMode_ { // mode for actuator length range computation
|
||||||
mjLRMODE_NONE = 0, // do not process any actuators
|
mjLRMODE_NONE = 0, // do not process any actuators
|
||||||
mjLRMODE_MUSCLE, // process muscle actuators
|
mjLRMODE_MUSCLE, // process muscle actuators
|
||||||
@@ -978,7 +983,7 @@ struct mjModel_ {
|
|||||||
int* body_geomnum; // number of geoms (nbody x 1)
|
int* body_geomnum; // number of geoms (nbody x 1)
|
||||||
int* body_geomadr; // start addr of geoms; -1: no geoms (nbody x 1)
|
int* body_geomadr; // start addr of geoms; -1: no geoms (nbody x 1)
|
||||||
mjtByte* body_simple; // 1: diag M; 2: diag M, sliders only (nbody x 1)
|
mjtByte* body_simple; // 1: diag M; 2: diag M, sliders only (nbody x 1)
|
||||||
mjtByte* body_sameframe; // inertial frame is same as body frame (nbody x 1)
|
mjtByte* body_sameframe; // same frame as inertia (mjtSameframe) (nbody x 1)
|
||||||
mjtNum* body_pos; // position offset rel. to parent body (nbody x 3)
|
mjtNum* body_pos; // position offset rel. to parent body (nbody x 3)
|
||||||
mjtNum* body_quat; // orientation offset rel. to parent body (nbody x 4)
|
mjtNum* body_quat; // orientation offset rel. to parent body (nbody x 4)
|
||||||
mjtNum* body_ipos; // local position of center of mass (nbody x 3)
|
mjtNum* body_ipos; // local position of center of mass (nbody x 3)
|
||||||
@@ -1047,7 +1052,7 @@ struct mjModel_ {
|
|||||||
int* geom_group; // group for visibility (ngeom x 1)
|
int* geom_group; // group for visibility (ngeom x 1)
|
||||||
int* geom_priority; // geom contact priority (ngeom x 1)
|
int* geom_priority; // geom contact priority (ngeom x 1)
|
||||||
int* geom_plugin; // plugin instance id; -1: not in use (ngeom x 1)
|
int* geom_plugin; // plugin instance id; -1: not in use (ngeom x 1)
|
||||||
mjtByte* geom_sameframe; // same as body frame (1) or iframe (2) (ngeom x 1)
|
mjtByte* geom_sameframe; // same frame as body (mjtSameframe) (ngeom x 1)
|
||||||
mjtNum* geom_solmix; // mixing coef for solref/imp in geom pair (ngeom x 1)
|
mjtNum* geom_solmix; // mixing coef for solref/imp in geom pair (ngeom x 1)
|
||||||
mjtNum* geom_solref; // constraint solver reference: contact (ngeom x mjNREF)
|
mjtNum* geom_solref; // constraint solver reference: contact (ngeom x mjNREF)
|
||||||
mjtNum* geom_solimp; // constraint solver impedance: contact (ngeom x mjNIMP)
|
mjtNum* geom_solimp; // constraint solver impedance: contact (ngeom x mjNIMP)
|
||||||
@@ -1068,7 +1073,7 @@ struct mjModel_ {
|
|||||||
int* site_bodyid; // id of site's body (nsite x 1)
|
int* site_bodyid; // id of site's body (nsite x 1)
|
||||||
int* site_matid; // material id for rendering; -1: none (nsite x 1)
|
int* site_matid; // material id for rendering; -1: none (nsite x 1)
|
||||||
int* site_group; // group for visibility (nsite x 1)
|
int* site_group; // group for visibility (nsite x 1)
|
||||||
mjtByte* site_sameframe; // same as body frame (1) or iframe (2) (nsite x 1)
|
mjtByte* site_sameframe; // same frame as body (mjtSameframe) (nsite x 1)
|
||||||
mjtNum* site_size; // geom size for rendering (nsite x 3)
|
mjtNum* site_size; // geom size for rendering (nsite x 3)
|
||||||
mjtNum* site_pos; // local position offset rel. to body (nsite x 3)
|
mjtNum* site_pos; // local position offset rel. to body (nsite x 3)
|
||||||
mjtNum* site_quat; // local orientation offset rel. to body (nsite x 4)
|
mjtNum* site_quat; // local orientation offset rel. to body (nsite x 4)
|
||||||
|
|||||||
@@ -373,6 +373,13 @@ typedef enum mjtDataType_ { // data type for sensors
|
|||||||
} mjtDataType;
|
} mjtDataType;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum mjtSameFrame_ { // frame alignment of bodies with their children
|
||||||
|
mjSAMEFRAME_NONE = 0, // no alignment
|
||||||
|
mjSAMEFRAME_BODY, // frame is same as body frame
|
||||||
|
mjSAMEFRAME_INERTIA, // frame is same as inertial frame
|
||||||
|
} mjtSameFrame;
|
||||||
|
|
||||||
|
|
||||||
typedef enum mjtLRMode_ { // mode for actuator length range computation
|
typedef enum mjtLRMode_ { // mode for actuator length range computation
|
||||||
mjLRMODE_NONE = 0, // do not process any actuators
|
mjLRMODE_NONE = 0, // do not process any actuators
|
||||||
mjLRMODE_MUSCLE, // process muscle actuators
|
mjLRMODE_MUSCLE, // process muscle actuators
|
||||||
@@ -692,7 +699,7 @@ struct mjModel_ {
|
|||||||
int* body_geomnum; // number of geoms (nbody x 1)
|
int* body_geomnum; // number of geoms (nbody x 1)
|
||||||
int* body_geomadr; // start addr of geoms; -1: no geoms (nbody x 1)
|
int* body_geomadr; // start addr of geoms; -1: no geoms (nbody x 1)
|
||||||
mjtByte* body_simple; // 1: diag M; 2: diag M, sliders only (nbody x 1)
|
mjtByte* body_simple; // 1: diag M; 2: diag M, sliders only (nbody x 1)
|
||||||
mjtByte* body_sameframe; // inertial frame is same as body frame (nbody x 1)
|
mjtByte* body_sameframe; // same frame as inertia (mjtSameframe) (nbody x 1)
|
||||||
mjtNum* body_pos; // position offset rel. to parent body (nbody x 3)
|
mjtNum* body_pos; // position offset rel. to parent body (nbody x 3)
|
||||||
mjtNum* body_quat; // orientation offset rel. to parent body (nbody x 4)
|
mjtNum* body_quat; // orientation offset rel. to parent body (nbody x 4)
|
||||||
mjtNum* body_ipos; // local position of center of mass (nbody x 3)
|
mjtNum* body_ipos; // local position of center of mass (nbody x 3)
|
||||||
@@ -761,7 +768,7 @@ struct mjModel_ {
|
|||||||
int* geom_group; // group for visibility (ngeom x 1)
|
int* geom_group; // group for visibility (ngeom x 1)
|
||||||
int* geom_priority; // geom contact priority (ngeom x 1)
|
int* geom_priority; // geom contact priority (ngeom x 1)
|
||||||
int* geom_plugin; // plugin instance id; -1: not in use (ngeom x 1)
|
int* geom_plugin; // plugin instance id; -1: not in use (ngeom x 1)
|
||||||
mjtByte* geom_sameframe; // same as body frame (1) or iframe (2) (ngeom x 1)
|
mjtByte* geom_sameframe; // same frame as body (mjtSameframe) (ngeom x 1)
|
||||||
mjtNum* geom_solmix; // mixing coef for solref/imp in geom pair (ngeom x 1)
|
mjtNum* geom_solmix; // mixing coef for solref/imp in geom pair (ngeom x 1)
|
||||||
mjtNum* geom_solref; // constraint solver reference: contact (ngeom x mjNREF)
|
mjtNum* geom_solref; // constraint solver reference: contact (ngeom x mjNREF)
|
||||||
mjtNum* geom_solimp; // constraint solver impedance: contact (ngeom x mjNIMP)
|
mjtNum* geom_solimp; // constraint solver impedance: contact (ngeom x mjNIMP)
|
||||||
@@ -782,7 +789,7 @@ struct mjModel_ {
|
|||||||
int* site_bodyid; // id of site's body (nsite x 1)
|
int* site_bodyid; // id of site's body (nsite x 1)
|
||||||
int* site_matid; // material id for rendering; -1: none (nsite x 1)
|
int* site_matid; // material id for rendering; -1: none (nsite x 1)
|
||||||
int* site_group; // group for visibility (nsite x 1)
|
int* site_group; // group for visibility (nsite x 1)
|
||||||
mjtByte* site_sameframe; // same as body frame (1) or iframe (2) (nsite x 1)
|
mjtByte* site_sameframe; // same frame as body (mjtSameframe) (nsite x 1)
|
||||||
mjtNum* site_size; // geom size for rendering (nsite x 3)
|
mjtNum* site_size; // geom size for rendering (nsite x 3)
|
||||||
mjtNum* site_pos; // local position offset rel. to body (nsite x 3)
|
mjtNum* site_pos; // local position offset rel. to body (nsite x 3)
|
||||||
mjtNum* site_quat; // local orientation offset rel. to body (nsite x 4)
|
mjtNum* site_quat; // local orientation offset rel. to body (nsite x 4)
|
||||||
|
|||||||
@@ -507,7 +507,7 @@ MJAPI void mj_integratePos(const mjModel* m, mjtNum* qpos, const mjtNum* qvel, m
|
|||||||
// Normalize all quaternions in qpos-type vector.
|
// Normalize all quaternions in qpos-type vector.
|
||||||
MJAPI void mj_normalizeQuat(const mjModel* m, mjtNum* qpos);
|
MJAPI void mj_normalizeQuat(const mjModel* m, mjtNum* qpos);
|
||||||
|
|
||||||
// Map from body local to global Cartesian coordinates.
|
// Map from body local to global Cartesian coordinates, sameframe takes values from mjtSameFrame.
|
||||||
MJAPI void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9], const mjtNum pos[3],
|
MJAPI void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9], const mjtNum pos[3],
|
||||||
const mjtNum quat[4], int body, mjtByte sameframe);
|
const mjtNum quat[4], int body, mjtByte sameframe);
|
||||||
|
|
||||||
|
|||||||
@@ -388,6 +388,16 @@ ENUMS: Mapping[str, EnumDecl] = dict([
|
|||||||
('mjDATATYPE_QUATERNION', 3),
|
('mjDATATYPE_QUATERNION', 3),
|
||||||
]),
|
]),
|
||||||
)),
|
)),
|
||||||
|
('mjtSameFrame',
|
||||||
|
EnumDecl(
|
||||||
|
name='mjtSameFrame',
|
||||||
|
declname='enum mjtSameFrame_',
|
||||||
|
values=dict([
|
||||||
|
('mjSAMEFRAME_NONE', 0),
|
||||||
|
('mjSAMEFRAME_BODY', 1),
|
||||||
|
('mjSAMEFRAME_INERTIA', 2),
|
||||||
|
]),
|
||||||
|
)),
|
||||||
('mjtLRMode',
|
('mjtLRMode',
|
||||||
EnumDecl(
|
EnumDecl(
|
||||||
name='mjtLRMode',
|
name='mjtLRMode',
|
||||||
|
|||||||
@@ -3168,7 +3168,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
|||||||
type=ValueType(name='mjtByte'),
|
type=ValueType(name='mjtByte'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
doc='Map from body local to global Cartesian coordinates.',
|
doc='Map from body local to global Cartesian coordinates, sameframe takes values from mjtSameFrame.', # pylint: disable=line-too-long
|
||||||
)),
|
)),
|
||||||
('mj_getTotalmass',
|
('mj_getTotalmass',
|
||||||
FunctionDecl(
|
FunctionDecl(
|
||||||
|
|||||||
@@ -1343,7 +1343,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
|||||||
type=PointerType(
|
type=PointerType(
|
||||||
inner_type=ValueType(name='mjtByte'),
|
inner_type=ValueType(name='mjtByte'),
|
||||||
),
|
),
|
||||||
doc='inertial frame is same as body frame (nbody x 1)',
|
doc='same frame as inertia (mjtSameframe) (nbody x 1)',
|
||||||
),
|
),
|
||||||
StructFieldDecl(
|
StructFieldDecl(
|
||||||
name='body_pos',
|
name='body_pos',
|
||||||
@@ -1770,7 +1770,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
|||||||
type=PointerType(
|
type=PointerType(
|
||||||
inner_type=ValueType(name='mjtByte'),
|
inner_type=ValueType(name='mjtByte'),
|
||||||
),
|
),
|
||||||
doc='same as body frame (1) or iframe (2) (ngeom x 1)',
|
doc='same frame as body (mjtSameframe) (ngeom x 1)',
|
||||||
),
|
),
|
||||||
StructFieldDecl(
|
StructFieldDecl(
|
||||||
name='geom_solmix',
|
name='geom_solmix',
|
||||||
@@ -1903,7 +1903,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
|||||||
type=PointerType(
|
type=PointerType(
|
||||||
inner_type=ValueType(name='mjtByte'),
|
inner_type=ValueType(name='mjtByte'),
|
||||||
),
|
),
|
||||||
doc='same as body frame (1) or iframe (2) (nsite x 1)',
|
doc='same frame as body (mjtSameframe) (nsite x 1)',
|
||||||
),
|
),
|
||||||
StructFieldDecl(
|
StructFieldDecl(
|
||||||
name='site_size',
|
name='site_size',
|
||||||
|
|||||||
+16
-21
@@ -1614,43 +1614,38 @@ void mj_normalizeQuat(const mjModel* m, mjtNum* qpos) {
|
|||||||
void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9],
|
void mj_local2Global(mjData* d, mjtNum xpos[3], mjtNum xmat[9],
|
||||||
const mjtNum pos[3], const mjtNum quat[4],
|
const mjtNum pos[3], const mjtNum quat[4],
|
||||||
int body, mjtByte sameframe) {
|
int body, mjtByte sameframe) {
|
||||||
mjtNum tmp[4];
|
mjtSameFrame sf = sameframe;
|
||||||
|
|
||||||
// position
|
// position
|
||||||
if (xpos && pos) {
|
if (xpos && pos) {
|
||||||
// compute
|
switch (sf) {
|
||||||
if (sameframe == 0) {
|
case mjSAMEFRAME_NONE:
|
||||||
mju_mulMatVec3(xpos, d->xmat+9*body, pos);
|
mju_mulMatVec3(xpos, d->xmat+9*body, pos);
|
||||||
mju_addTo3(xpos, d->xpos+3*body);
|
mju_addTo3(xpos, d->xpos+3*body);
|
||||||
}
|
break;
|
||||||
|
case mjSAMEFRAME_BODY:
|
||||||
// copy body position
|
|
||||||
else if (sameframe == 1) {
|
|
||||||
mju_copy3(xpos, d->xpos+3*body);
|
mju_copy3(xpos, d->xpos+3*body);
|
||||||
}
|
break;
|
||||||
|
case mjSAMEFRAME_INERTIA:
|
||||||
// copy inertial body position
|
|
||||||
else {
|
|
||||||
mju_copy3(xpos, d->xipos+3*body);
|
mju_copy3(xpos, d->xipos+3*body);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// orientation
|
// orientation
|
||||||
if (xmat && quat) {
|
if (xmat && quat) {
|
||||||
// compute
|
mjtNum tmp[4];
|
||||||
if (sameframe == 0) {
|
switch (sf) {
|
||||||
|
case mjSAMEFRAME_NONE:
|
||||||
mju_mulQuat(tmp, d->xquat+4*body, quat);
|
mju_mulQuat(tmp, d->xquat+4*body, quat);
|
||||||
mju_quat2Mat(xmat, tmp);
|
mju_quat2Mat(xmat, tmp);
|
||||||
}
|
break;
|
||||||
|
case mjSAMEFRAME_BODY:
|
||||||
// copy body orientation
|
|
||||||
else if (sameframe == 1) {
|
|
||||||
mju_copy(xmat, d->xmat+9*body, 9);
|
mju_copy(xmat, d->xmat+9*body, 9);
|
||||||
}
|
break;
|
||||||
|
case mjSAMEFRAME_INERTIA:
|
||||||
// copy inertial body orientation
|
|
||||||
else {
|
|
||||||
mju_copy(xmat, d->ximat+9*body, 9);
|
mju_copy(xmat, d->ximat+9*body, 9);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+94
-64
@@ -19,7 +19,6 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <csetjmp>
|
#include <csetjmp>
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -56,6 +55,65 @@ namespace mju = ::mujoco::util;
|
|||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
constexpr int kMaxCompilerThreads = 16;
|
constexpr int kMaxCompilerThreads = 16;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------- LOCAL UTILITY FUNCTIONS ---------------------------------------
|
||||||
|
|
||||||
|
constexpr double kFrameEps = 1e-6; // difference below which frames are considered equal
|
||||||
|
|
||||||
|
// return true if two 3-vectors are element-wise less than kFrameEps apart
|
||||||
|
template <typename T>
|
||||||
|
bool IsSameVec(const T pos1[3], const T pos2[3]) {
|
||||||
|
static_assert(std::is_floating_point_v<T>);
|
||||||
|
return std::abs(pos1[0] - pos2[0]) < kFrameEps &&
|
||||||
|
std::abs(pos1[1] - pos2[1]) < kFrameEps &&
|
||||||
|
std::abs(pos1[2] - pos2[2]) < kFrameEps;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if two quaternions are element-wise less than kFrameEps apart, including double-cover
|
||||||
|
template <typename T>
|
||||||
|
bool IsSameQuat(const T quat1[4], const T quat2[4]) {
|
||||||
|
static_assert(std::is_floating_point_v<T>);
|
||||||
|
bool same_quat_minus = std::abs(quat1[0] - quat2[0]) < kFrameEps &&
|
||||||
|
std::abs(quat1[1] - quat2[1]) < kFrameEps &&
|
||||||
|
std::abs(quat1[2] - quat2[2]) < kFrameEps &&
|
||||||
|
std::abs(quat1[3] - quat2[3]) < kFrameEps;
|
||||||
|
|
||||||
|
bool same_quat_plus = std::abs(quat1[0] + quat2[0]) < kFrameEps &&
|
||||||
|
std::abs(quat1[1] + quat2[1]) < kFrameEps &&
|
||||||
|
std::abs(quat1[2] + quat2[2]) < kFrameEps &&
|
||||||
|
std::abs(quat1[3] + quat2[3]) < kFrameEps;
|
||||||
|
|
||||||
|
return same_quat_minus || same_quat_plus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// compare two poses
|
||||||
|
template <typename T>
|
||||||
|
bool IsSamePose(const T pos1[3], const T pos2[3], const T quat1[4], const T quat2[4]) {
|
||||||
|
// check position if given
|
||||||
|
if (pos1 && pos2 && !IsSameVec(pos1, pos2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check orientation if given
|
||||||
|
if (quat1 && quat2 && !IsSameQuat(quat1, quat2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// detect null pose
|
||||||
|
template <typename T>
|
||||||
|
bool IsNullPose(const T pos[3], const T quat[4]) {
|
||||||
|
T zero[3] = {0, 0, 0};
|
||||||
|
T qunit[4] = {1, 0, 0, 0};
|
||||||
|
return IsSamePose(pos, zero, quat, qunit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
//---------------------------------- CONSTRUCTOR AND DESTRUCTOR ------------------------------------
|
//---------------------------------- CONSTRUCTOR AND DESTRUCTOR ------------------------------------
|
||||||
@@ -429,7 +487,7 @@ void mjCModel::DeleteElement(mjsElement* el) {
|
|||||||
|
|
||||||
switch (el->elemtype) {
|
switch (el->elemtype) {
|
||||||
case mjOBJ_BODY:
|
case mjOBJ_BODY:
|
||||||
throw mjCError(NULL, "bodies cannot be deleted, use detach instead");
|
throw mjCError(nullptr, "bodies cannot be deleted, use detach instead");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case mjOBJ_GEOM:
|
case mjOBJ_GEOM:
|
||||||
@@ -825,12 +883,12 @@ static mjsElement* GetNext(std::vector<T*>& list, mjsElement* child) {
|
|||||||
mjsElement* mjCModel::NextObject(mjsElement* object, mjtObj type) {
|
mjsElement* mjCModel::NextObject(mjsElement* object, mjtObj type) {
|
||||||
if (type == mjOBJ_UNKNOWN) {
|
if (type == mjOBJ_UNKNOWN) {
|
||||||
if (!object) {
|
if (!object) {
|
||||||
throw mjCError(NULL, "type must be specified if no element is given");
|
throw mjCError(nullptr, "type must be specified if no element is given");
|
||||||
} else {
|
} else {
|
||||||
type = object->elemtype;
|
type = object->elemtype;
|
||||||
}
|
}
|
||||||
} else if (object && object->elemtype != type) {
|
} else if (object && object->elemtype != type) {
|
||||||
throw mjCError(NULL, "element is not of requested type");
|
throw mjCError(nullptr, "element is not of requested type");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -1022,29 +1080,6 @@ mjSpec* mjCModel::FindSpec(std::string name) const {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// detect null pose
|
|
||||||
bool mjCModel::IsNullPose(const mjtNum* pos, const mjtNum* quat) const {
|
|
||||||
bool result = true;
|
|
||||||
|
|
||||||
// check position if given
|
|
||||||
if (pos) {
|
|
||||||
if (pos[0] || pos[1] || pos[2]) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check orientation if given
|
|
||||||
if (quat) {
|
|
||||||
if (quat[0]!=1 || quat[1] || quat[2] || quat[3]) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------- COMPILER PHASES --------------------------------------------------
|
//------------------------------- COMPILER PHASES --------------------------------------------------
|
||||||
|
|
||||||
// make lists of objects in tree: bodies, geoms, joints, sites, cameras, lights
|
// make lists of objects in tree: bodies, geoms, joints, sites, cameras, lights
|
||||||
@@ -1640,12 +1675,12 @@ void* LRfunc(void* arg) {
|
|||||||
for (int i=larg->start; i<larg->start+larg->num; i++) {
|
for (int i=larg->start; i<larg->start+larg->num; i++) {
|
||||||
if (i<larg->m->nu) {
|
if (i<larg->m->nu) {
|
||||||
if (!mj_setLengthRange(larg->m, larg->data, i, larg->LRopt, larg->error, larg->error_sz)) {
|
if (!mj_setLengthRange(larg->m, larg->data, i, larg->LRopt, larg->error, larg->error_sz)) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1977,16 +2012,22 @@ void mjCModel::CopyTree(mjModel* m) {
|
|||||||
pb->lastdof = par->lastdof;
|
pb->lastdof = par->lastdof;
|
||||||
|
|
||||||
// set sameframe
|
// set sameframe
|
||||||
m->body_sameframe[i] = IsNullPose(m->body_ipos+3*i, m->body_iquat+4*i);
|
mjtSameFrame sameframe;
|
||||||
|
if (IsNullPose(m->body_ipos+3*i, m->body_iquat+4*i)) {
|
||||||
|
sameframe = mjSAMEFRAME_BODY;
|
||||||
|
} else {
|
||||||
|
sameframe = mjSAMEFRAME_NONE;
|
||||||
|
}
|
||||||
|
m->body_sameframe[i] = sameframe;
|
||||||
|
|
||||||
// init simple: sameframe, and (self-root, or parent is fixed child of world)
|
// init simple: sameframe, and (self-root, or parent is fixed child of world)
|
||||||
int j = m->body_parentid[i];
|
int parentid = m->body_parentid[i];
|
||||||
m->body_simple[i] = (m->body_sameframe[i] &&
|
m->body_simple[i] = (sameframe == mjSAMEFRAME_BODY &&
|
||||||
(m->body_rootid[i]==i ||
|
(m->body_rootid[i]==i ||
|
||||||
(m->body_parentid[j]==0 &&
|
(m->body_parentid[parentid]==0 &&
|
||||||
m->body_dofnum[j]==0)));
|
m->body_dofnum[parentid]==0)));
|
||||||
|
|
||||||
// parent is not simple (unless world)
|
// a parent body is never simple (unless world)
|
||||||
if (m->body_parentid[i]>0) {
|
if (m->body_parentid[i]>0) {
|
||||||
m->body_simple[m->body_parentid[i]] = 0;
|
m->body_simple[m->body_parentid[i]] = 0;
|
||||||
}
|
}
|
||||||
@@ -2020,12 +2061,11 @@ void mjCModel::CopyTree(mjModel* m) {
|
|||||||
mjuu_copyvec(m->jnt_user+nuser_jnt*jid, pj->get_userdata().data(), nuser_jnt);
|
mjuu_copyvec(m->jnt_user+nuser_jnt*jid, pj->get_userdata().data(), nuser_jnt);
|
||||||
|
|
||||||
// not simple if: rotation already found, or pos not zero, or mis-aligned axis
|
// not simple if: rotation already found, or pos not zero, or mis-aligned axis
|
||||||
if (rotfound ||
|
bool axis_aligned = ((std::abs(pj->axis[0]) > mjEPS) +
|
||||||
!IsNullPose(m->jnt_pos+3*jid, NULL) ||
|
(std::abs(pj->axis[1]) > mjEPS) +
|
||||||
((pj->type==mjJNT_HINGE || pj->type==mjJNT_SLIDE) &&
|
(std::abs(pj->axis[2]) > mjEPS)) == 1;
|
||||||
((std::abs(pj->axis[0])>mjEPS) +
|
if (rotfound || !IsNullPose(m->jnt_pos+3*jid, static_cast<mjtNum*>(nullptr)) ||
|
||||||
(std::abs(pj->axis[1])>mjEPS) +
|
((pj->type == mjJNT_HINGE || pj->type == mjJNT_SLIDE) && !axis_aligned)) {
|
||||||
(std::abs(pj->axis[2])>mjEPS)) > 1)) {
|
|
||||||
m->body_simple[i] = 0;
|
m->body_simple[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2133,18 +2173,13 @@ void mjCModel::CopyTree(mjModel* m) {
|
|||||||
|
|
||||||
// determine sameframe
|
// determine sameframe
|
||||||
if (IsNullPose(m->geom_pos+3*gid, m->geom_quat+4*gid)) {
|
if (IsNullPose(m->geom_pos+3*gid, m->geom_quat+4*gid)) {
|
||||||
m->geom_sameframe[gid] = 1;
|
sameframe = mjSAMEFRAME_BODY;
|
||||||
} else if (pg->pos[0]==pb->ipos[0] &&
|
} else if (IsSamePose(pg->pos, pb->ipos, pg->quat, pb->iquat)) {
|
||||||
pg->pos[1]==pb->ipos[1] &&
|
sameframe = mjSAMEFRAME_INERTIA;
|
||||||
pg->pos[2]==pb->ipos[2] &&
|
|
||||||
pg->quat[0]==pb->iquat[0] &&
|
|
||||||
pg->quat[1]==pb->iquat[1] &&
|
|
||||||
pg->quat[2]==pb->iquat[2] &&
|
|
||||||
pg->quat[3]==pb->iquat[3]) {
|
|
||||||
m->geom_sameframe[gid] = 2;
|
|
||||||
} else {
|
} else {
|
||||||
m->geom_sameframe[gid] = 0;
|
sameframe = mjSAMEFRAME_NONE;
|
||||||
}
|
}
|
||||||
|
m->geom_sameframe[gid] = sameframe;
|
||||||
|
|
||||||
// compute rbound
|
// compute rbound
|
||||||
m->geom_rbound[gid] = (mjtNum)pg->GetRBound();
|
m->geom_rbound[gid] = (mjtNum)pg->GetRBound();
|
||||||
@@ -2169,18 +2204,13 @@ void mjCModel::CopyTree(mjModel* m) {
|
|||||||
|
|
||||||
// determine sameframe
|
// determine sameframe
|
||||||
if (IsNullPose(m->site_pos+3*sid, m->site_quat+4*sid)) {
|
if (IsNullPose(m->site_pos+3*sid, m->site_quat+4*sid)) {
|
||||||
m->site_sameframe[sid] = 1;
|
sameframe = mjSAMEFRAME_BODY;
|
||||||
} else if (ps->pos[0]==pb->ipos[0] &&
|
} else if (IsSamePose(ps->pos, pb->ipos, ps->quat, pb->iquat)) {
|
||||||
ps->pos[1]==pb->ipos[1] &&
|
sameframe = mjSAMEFRAME_INERTIA;
|
||||||
ps->pos[2]==pb->ipos[2] &&
|
|
||||||
ps->quat[0]==pb->iquat[0] &&
|
|
||||||
ps->quat[1]==pb->iquat[1] &&
|
|
||||||
ps->quat[2]==pb->iquat[2] &&
|
|
||||||
ps->quat[3]==pb->iquat[3]) {
|
|
||||||
m->site_sameframe[sid] = 2;
|
|
||||||
} else {
|
} else {
|
||||||
m->site_sameframe[sid] = 0;
|
sameframe = mjSAMEFRAME_NONE;
|
||||||
}
|
}
|
||||||
|
m->site_sameframe[sid] = sameframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop over cameras for this body
|
// loop over cameras for this body
|
||||||
@@ -2887,7 +2917,7 @@ void mjCModel::SaveState(const std::string& state_name, const T* qpos, const T*
|
|||||||
const T* ctrl, const T* mpos, const T* mquat) {
|
const T* ctrl, const T* mpos, const T* mquat) {
|
||||||
for (auto joint : joints_) {
|
for (auto joint : joints_) {
|
||||||
if (joint->qposadr_ == -1 || joint->dofadr_ == -1) {
|
if (joint->qposadr_ == -1 || joint->dofadr_ == -1) {
|
||||||
throw mjCError(NULL, "SaveState: joint %s has no address", joint->name.c_str());
|
throw mjCError(nullptr, "SaveState: joint %s has no address", joint->name.c_str());
|
||||||
}
|
}
|
||||||
if (qpos) mjuu_copyvec(joint->qpos(state_name), qpos + joint->qposadr_, joint->nq());
|
if (qpos) mjuu_copyvec(joint->qpos(state_name), qpos + joint->qposadr_, joint->nq());
|
||||||
if (qvel) mjuu_copyvec(joint->qvel(state_name), qvel + joint->dofadr_, joint->nv());
|
if (qvel) mjuu_copyvec(joint->qvel(state_name), qvel + joint->dofadr_, joint->nv());
|
||||||
@@ -3170,7 +3200,7 @@ void mjCModel::FuseStatic(void) {
|
|||||||
mjuu_copyvec(par->fullinertia, toti, 6);
|
mjuu_copyvec(par->fullinertia, toti, 6);
|
||||||
const char* err1 = mjuu_fullInertia(par->iquat, par->inertia, par->fullinertia);
|
const char* err1 = mjuu_fullInertia(par->iquat, par->inertia, par->fullinertia);
|
||||||
if (err1) {
|
if (err1) {
|
||||||
throw mjCError(NULL, "error '%s' in fusing static body inertias", err1);
|
throw mjCError(nullptr, "error '%s' in fusing static body inertias", err1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3348,7 +3378,7 @@ static void processlist(mjListKeyMap& ids, vector<T*>& list,
|
|||||||
auto adjacent = std::adjacent_find(allnames.begin(), allnames.end());
|
auto adjacent = std::adjacent_find(allnames.begin(), allnames.end());
|
||||||
if (adjacent != allnames.end()) {
|
if (adjacent != allnames.end()) {
|
||||||
string msg = "repeated name '" + *adjacent + "' in " + mju_type2Str(type);
|
string msg = "repeated name '" + *adjacent + "' in " + mju_type2Str(type);
|
||||||
throw mjCError(NULL, "%s", msg.c_str());
|
throw mjCError(nullptr, "%s", msg.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,7 +232,6 @@ class mjCModel : public mjCModel_, private mjSpec {
|
|||||||
mjCBody* FindBody(mjCBody* body, std::string name); // find body given name
|
mjCBody* FindBody(mjCBody* body, std::string name); // find body given name
|
||||||
mjCFrame* FindFrame(mjCBody* body, std::string name) const; // find frame given name
|
mjCFrame* FindFrame(mjCBody* body, std::string name) const; // find frame given name
|
||||||
mjSpec* FindSpec(std::string name) const; // find spec given name
|
mjSpec* FindSpec(std::string name) const; // find spec given name
|
||||||
bool IsNullPose(const mjtNum* pos, const mjtNum* quat) const; // detect null pose
|
|
||||||
void SetActivePlugins(const std::vector<std::pair<const mjpPlugin*, int>>&& active_plugins) {
|
void SetActivePlugins(const std::vector<std::pair<const mjpPlugin*, int>>&& active_plugins) {
|
||||||
active_plugins_ = std::move(active_plugins);
|
active_plugins_ = std::move(active_plugins);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -392,6 +392,11 @@ public enum mjtDataType : int{
|
|||||||
mjDATATYPE_AXIS = 2,
|
mjDATATYPE_AXIS = 2,
|
||||||
mjDATATYPE_QUATERNION = 3,
|
mjDATATYPE_QUATERNION = 3,
|
||||||
}
|
}
|
||||||
|
public enum mjtSameFrame : int{
|
||||||
|
mjSAMEFRAME_NONE = 0,
|
||||||
|
mjSAMEFRAME_BODY = 1,
|
||||||
|
mjSAMEFRAME_INERTIA = 2,
|
||||||
|
}
|
||||||
public enum mjtLRMode : int{
|
public enum mjtLRMode : int{
|
||||||
mjLRMODE_NONE = 0,
|
mjLRMODE_NONE = 0,
|
||||||
mjLRMODE_MUSCLE = 1,
|
mjLRMODE_MUSCLE = 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user