Added support for GMSH22 surface loading
PiperOrigin-RevId: 629734063 Change-Id: I6a250b81de4e7c8f7520795bfe74a81d719dfb50
This commit is contained in:
committed by
Copybara-Service
parent
57b1dbac65
commit
131b1745db
@@ -3452,9 +3452,10 @@ saving the XML:
|
|||||||
.. _body-flexcomp-file:
|
.. _body-flexcomp-file:
|
||||||
|
|
||||||
:at:`file`: :at-val:`string, optional`
|
:at:`file`: :at-val:`string, optional`
|
||||||
The name of the file from which a **mesh** or a **gmsh** is loaded. For mesh, the file extentsion is used to
|
The name of the file from which a **surface** (triangular) or **volumetric** (tetrahedral) mesh is loaded. For
|
||||||
determine the file format. Supported formats are the same as in :ref:`mesh assets<asset-mesh>`. For gmsh, the file is
|
surface meshes, the file extension is used to determine the file format. Supported formats are the same as in
|
||||||
expected to be in GMSH format 4.1 or 2.2, ascii or binary, see :ref:`here<gmsh-file-docs>`.
|
:ref:`mesh assets<asset-mesh>` and also including GMSH. Volumetric meshes are supported only in GMSH format.
|
||||||
|
See :ref:`here<gmsh-file-docs>` for more information on GMSH files.
|
||||||
|
|
||||||
.. _body-flexcomp-rigid:
|
.. _body-flexcomp-rigid:
|
||||||
|
|
||||||
|
|||||||
+18
-17
@@ -24,39 +24,40 @@ General
|
|||||||
field.
|
field.
|
||||||
4. The type of the ``size`` argument of :ref:`mj_stackAllocNum` and :ref:`mj_stackAllocInt` was changed from ``int``
|
4. The type of the ``size`` argument of :ref:`mj_stackAllocNum` and :ref:`mj_stackAllocInt` was changed from ``int``
|
||||||
to ``size_t``.
|
to ``size_t``.
|
||||||
|
5. Added support for gmsh format version 2.2 surface meshes in :ref:`flexcomp<body-flexcomp-file>`.
|
||||||
|
|
||||||
MJX
|
MJX
|
||||||
^^^
|
^^^
|
||||||
.. admonition:: Breaking API changes
|
.. admonition:: Breaking API changes
|
||||||
:class: attention
|
:class: attention
|
||||||
|
|
||||||
5. Removed deprecated ``mjx.device_get_into`` and ``mjx.device_put`` functions as they lack critical new
|
6. Removed deprecated ``mjx.device_get_into`` and ``mjx.device_put`` functions as they lack critical new
|
||||||
functionality.
|
functionality.
|
||||||
|
|
||||||
**Migration:** Use ``mjx.get_data_into`` instead of ``mjx.device_get_into``, and ``mjx.put_data`` instead of
|
**Migration:** Use ``mjx.get_data_into`` instead of ``mjx.device_get_into``, and ``mjx.put_data`` instead of
|
||||||
``mjx.device_put``.
|
``mjx.device_put``.
|
||||||
|
|
||||||
6. Added cylinder plane collisions.
|
7. Added cylinder plane collisions.
|
||||||
7. Added ``efc_type`` to ``mjx.Data`` and ``dim``, ``efc_address`` to ``mjx.Contact``.
|
8. Added ``efc_type`` to ``mjx.Data`` and ``dim``, ``efc_address`` to ``mjx.Contact``.
|
||||||
8. Added ``geom`` to ``mjx.Contact`` and marked ``geom1``, ``geom2`` deprecated.
|
9. Added ``geom`` to ``mjx.Contact`` and marked ``geom1``, ``geom2`` deprecated.
|
||||||
9. Added ``ne``, ``nf``, ``nl``, ``nefc``, and ``ncon`` to ``mjx.Data`` to match ``mujoco.MjData``.
|
10. Added ``ne``, ``nf``, ``nl``, ``nefc``, and ``ncon`` to ``mjx.Data`` to match ``mujoco.MjData``.
|
||||||
10. Given the above added fields, removed ``mjx.get_params``, ``mjx.ncon``, and ``mjx.count_constraints``.
|
11. Given the above added fields, removed ``mjx.get_params``, ``mjx.ncon``, and ``mjx.count_constraints``.
|
||||||
11. Changed the way meshes are organized on device to speed up collision detection when a mesh is replicated for many
|
12. Changed the way meshes are organized on device to speed up collision detection when a mesh is replicated for many
|
||||||
geoms.
|
geoms.
|
||||||
12. Fixed a bug where capsules might be ignored in broadphase colliision checking.
|
13. Fixed a bug where capsules might be ignored in broadphase colliision checking.
|
||||||
13. Added cylinder collisions using SDFs.
|
14. Added cylinder collisions using SDFs.
|
||||||
14. Added support for all :ref:`condim <coContact>`: 1, 3, 4, 6.
|
15. Added support for all :ref:`condim <coContact>`: 1, 3, 4, 6.
|
||||||
15. Add support functions for ``id2name`` and ``name2id``, MJX versions of :ref:`mj_id2name` and :ref:`mj_name2id`.
|
16. Add support functions for ``id2name`` and ``name2id``, MJX versions of :ref:`mj_id2name` and :ref:`mj_name2id`.
|
||||||
16. Added support for :ref:`gravcomp<body-gravcomp>` and :ref:`actuatorgravcomp<body-joint-actuatorgravcomp>`.
|
17. Added support for :ref:`gravcomp<body-gravcomp>` and :ref:`actuatorgravcomp<body-joint-actuatorgravcomp>`.
|
||||||
17. Fixed a bug in ``mjx.ray`` for sometimes allowed negative distances for ray-mesh tests.
|
18. Fixed a bug in ``mjx.ray`` for sometimes allowed negative distances for ray-mesh tests.
|
||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
18. Defaults of lights were not being saved, now fixed.
|
19. Defaults of lights were not being saved, now fixed.
|
||||||
19. Prevent overwriting of frame names by body names when saving an XML. Bug introduced in 3.1.4.
|
20. Prevent overwriting of frame names by body names when saving an XML. Bug introduced in 3.1.4.
|
||||||
20. Fixed bug in Python binding of :ref:`mj_saveModel`: ``buffer`` argument was documented as optional but was actually
|
21. Fixed bug in Python binding of :ref:`mj_saveModel`: ``buffer`` argument was documented as optional but was actually
|
||||||
not optional.
|
not optional.
|
||||||
21. Fixed bug that prevented memory allocations larger than 2.15 GB.
|
22. Fixed bug that prevented memory allocations larger than 2.15 GB.
|
||||||
|
|
||||||
|
|
||||||
Version 3.1.4 (April 10th, 2024)
|
Version 3.1.4 (April 10th, 2024)
|
||||||
|
|||||||
+54
-17
@@ -62,7 +62,7 @@ static void ReadStrFromBuffer(char* dest, const char* src, int maxlen) {
|
|||||||
std::strncpy(dest, src, maxlen);
|
std::strncpy(dest, src, maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidElementHeader22(const std::string& line) {
|
bool IsValidElementOrNodeHeader22(const std::string& line) {
|
||||||
// making sure characters are numbers
|
// making sure characters are numbers
|
||||||
for (char c : line) {
|
for (char c : line) {
|
||||||
if (!std::isdigit(c)) {
|
if (!std::isdigit(c)) {
|
||||||
@@ -1296,10 +1296,21 @@ void mjCFlexcomp::LoadGMSH41(char* buffer, int binary, int nodeend,
|
|||||||
// load GMSH format 2.2
|
// load GMSH format 2.2
|
||||||
void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
||||||
int nodebegin, int elemend, int elembegin) {
|
int nodebegin, int elemend, int elembegin) {
|
||||||
|
// number of nodes
|
||||||
|
size_t numNodes = 0;
|
||||||
|
|
||||||
// ascii nodes
|
// ascii nodes
|
||||||
if (binary == 0) {
|
if (binary == 0) {
|
||||||
// convert node char buffer to stringstream
|
// convert node char buffer to stringstream
|
||||||
stringstream ss(std::string(buffer + nodebegin, nodeend - nodebegin));
|
stringstream ss(std::string(buffer + nodebegin, nodeend - nodebegin));
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
// checking header template
|
||||||
|
std::getline(ss, line);
|
||||||
|
if (!IsValidElementOrNodeHeader22(line)) {
|
||||||
|
throw mjCError(NULL, "Invalid node header");
|
||||||
|
}
|
||||||
|
ss.seekg(-(line.size()+1), std::ios::cur);
|
||||||
|
|
||||||
// read header
|
// read header
|
||||||
size_t maxNodeTag = 0;
|
size_t maxNodeTag = 0;
|
||||||
@@ -1307,7 +1318,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
if (!ss.good()) {
|
if (!ss.good()) {
|
||||||
throw mjCError(NULL, "Error reading Nodes header");
|
throw mjCError(NULL, "Error reading Nodes header");
|
||||||
}
|
}
|
||||||
size_t numNodes = maxNodeTag;
|
numNodes = maxNodeTag;
|
||||||
|
|
||||||
if (numNodes < 0 || numNodes >= INT_MAX / 3) {
|
if (numNodes < 0 || numNodes >= INT_MAX / 3) {
|
||||||
throw mjCError(NULL, "Invalid number of nodes.");
|
throw mjCError(NULL, "Invalid number of nodes.");
|
||||||
@@ -1349,7 +1360,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
ReadStrFromBuffer(maxNodeTagChar, buffer + nodebegin, std::min(10, nodeend - nodebegin));
|
ReadStrFromBuffer(maxNodeTagChar, buffer + nodebegin, std::min(10, nodeend - nodebegin));
|
||||||
size_t measuredHeaderSize = strnlen(maxNodeTagChar, 10) - 1;
|
size_t measuredHeaderSize = strnlen(maxNodeTagChar, 10) - 1;
|
||||||
size_t maxNodeTag = std::stoi(maxNodeTagChar);
|
size_t maxNodeTag = std::stoi(maxNodeTagChar);
|
||||||
size_t numNodes = maxNodeTag;
|
numNodes = maxNodeTag;
|
||||||
|
|
||||||
// check number of nodes is a positive number
|
// check number of nodes is a positive number
|
||||||
if (numNodes < 0) {
|
if (numNodes < 0) {
|
||||||
@@ -1396,7 +1407,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
|
|
||||||
// checking header template
|
// checking header template
|
||||||
std::getline(ss, line);
|
std::getline(ss, line);
|
||||||
if (!IsValidElementHeader22(line)) {
|
if (!IsValidElementOrNodeHeader22(line)) {
|
||||||
throw mjCError(NULL, "Invalid elements header");
|
throw mjCError(NULL, "Invalid elements header");
|
||||||
}
|
}
|
||||||
ss.seekg(-(line.size()+1), std::ios::cur);
|
ss.seekg(-(line.size()+1), std::ios::cur);
|
||||||
@@ -1404,7 +1415,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
size_t maxElementTag = 0;
|
size_t maxElementTag = 0;
|
||||||
ss >> maxElementTag;
|
ss >> maxElementTag;
|
||||||
if (!ss.good()) {
|
if (!ss.good()) {
|
||||||
throw mjCError(NULL, "GetMaxElementTag::Error reading Elements header");
|
throw mjCError(NULL, "Error reading Elements header");
|
||||||
}
|
}
|
||||||
size_t numElements = maxElementTag;
|
size_t numElements = maxElementTag;
|
||||||
|
|
||||||
@@ -1419,18 +1430,30 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reading first element's type
|
// reading first element's type
|
||||||
int tag = 0, type = 0, numTags = 0;
|
int tag = 0, elementType = 0, numTags = 0;
|
||||||
ss >> tag >> type >> numTags;
|
ss >> tag >> elementType >> numTags;
|
||||||
if (!ss.good()) {
|
if (!ss.good()) {
|
||||||
throw mjCError(NULL, "Error reading Elements");
|
throw mjCError(NULL, "Error reading Elements");
|
||||||
}
|
}
|
||||||
int numNodeTags = type;
|
|
||||||
|
size_t entityDim = 0;
|
||||||
|
int numNodeTags = 0;
|
||||||
|
// surface
|
||||||
|
if (elementType == 2) {
|
||||||
|
entityDim = 2;
|
||||||
|
numNodeTags = 3;
|
||||||
|
}
|
||||||
|
// tetrahedral
|
||||||
|
else if (elementType == 4) {
|
||||||
|
entityDim = 3;
|
||||||
|
numNodeTags = 4;
|
||||||
|
}
|
||||||
|
|
||||||
if (numNodeTags < 1 || numNodeTags >4) {
|
if (numNodeTags < 1 || numNodeTags >4) {
|
||||||
throw mjCError(NULL, "Invalid number of node tags");
|
throw mjCError(NULL, "Invalid number of node tags");
|
||||||
}
|
}
|
||||||
|
|
||||||
// setting entityDim
|
// setting entityDim
|
||||||
size_t entityDim = numNodeTags - 1;
|
|
||||||
def.spec.flex->dim = entityDim;
|
def.spec.flex->dim = entityDim;
|
||||||
|
|
||||||
// read elements, discard all tags
|
// read elements, discard all tags
|
||||||
@@ -1438,7 +1461,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
for (size_t i=0; i<numElements; i++) {
|
for (size_t i=0; i<numElements; i++) {
|
||||||
int nodeTag = 0, physicalEntityTag = 0, elmentModelEntityTag = 0;
|
int nodeTag = 0, physicalEntityTag = 0, elmentModelEntityTag = 0;
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
ss >> tag >> type >> numTags;
|
ss >> tag >> elementType >> numTags;
|
||||||
if (!ss.good()) {
|
if (!ss.good()) {
|
||||||
throw mjCError(NULL, "Error reading Elements");
|
throw mjCError(NULL, "Error reading Elements");
|
||||||
}
|
}
|
||||||
@@ -1454,7 +1477,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
if (!ss.good()) {
|
if (!ss.good()) {
|
||||||
throw mjCError(NULL, "Error reading Elements");
|
throw mjCError(NULL, "Error reading Elements");
|
||||||
}
|
}
|
||||||
if (nodeTag > numElements || nodeTag < 1) {
|
if (nodeTag > numNodes || nodeTag < 1) {
|
||||||
throw mjCError(NULL, "Invalid node tag");
|
throw mjCError(NULL, "Invalid node tag");
|
||||||
}
|
}
|
||||||
element.push_back((int)(nodeTag-1));
|
element.push_back((int)(nodeTag-1));
|
||||||
@@ -1464,7 +1487,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
// binary elements
|
// binary elements
|
||||||
else {
|
else {
|
||||||
// header size for gmshApp
|
// header size for gmshApp
|
||||||
constexpr int elementHeaderSizeGmshApp = 6;
|
constexpr int elementHeaderSizeGmshApp = 4;
|
||||||
// header size for Ftetwild
|
// header size for Ftetwild
|
||||||
constexpr int elementHeaderSizeFtetwild = 17;
|
constexpr int elementHeaderSizeFtetwild = 17;
|
||||||
// check header size
|
// check header size
|
||||||
@@ -1480,7 +1503,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
int numElements = maxElementTag;
|
int numElements = maxElementTag;
|
||||||
int tag, numTags;
|
int tag, numTags;
|
||||||
int nodeTag;
|
int nodeTag;
|
||||||
int numNodeTags;
|
int elementType;
|
||||||
|
|
||||||
// check number of elements is a positive number
|
// check number of elements is a positive number
|
||||||
if (numElements < 0) {
|
if (numElements < 0) {
|
||||||
@@ -1491,14 +1514,28 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
int componentSize = sizeof(int);
|
int componentSize = sizeof(int);
|
||||||
// element buffer
|
// element buffer
|
||||||
const char* elementsBuffer = buffer + elembegin + measuredHeaderSize;
|
const char* elementsBuffer = buffer + elembegin + measuredHeaderSize;
|
||||||
ReadFromBuffer(&numNodeTags, elementsBuffer);
|
ReadFromBuffer(&elementType, elementsBuffer);
|
||||||
ReadFromBuffer(&numTags, elementsBuffer + componentSize*2);
|
ReadFromBuffer(&numTags, elementsBuffer + componentSize*2);
|
||||||
ReadFromBuffer(&tag, elementsBuffer + componentSize*3);
|
ReadFromBuffer(&tag, elementsBuffer + componentSize*3);
|
||||||
|
|
||||||
|
// tetrahedral has 4 node tags and surface has 3
|
||||||
|
int numNodeTags = 0;
|
||||||
|
size_t entityDim = 0;
|
||||||
|
// surface
|
||||||
|
if (elementType == 2) {
|
||||||
|
entityDim = 2;
|
||||||
|
numNodeTags = 3;
|
||||||
|
}
|
||||||
|
// tetrahedral
|
||||||
|
else if (elementType == 4) {
|
||||||
|
entityDim = 3;
|
||||||
|
numNodeTags = 4;
|
||||||
|
}
|
||||||
|
|
||||||
if (numNodeTags < 1 || numNodeTags >4) {
|
if (numNodeTags < 1 || numNodeTags >4) {
|
||||||
throw mjCError(NULL, "Invalid number of node tags");
|
throw mjCError(NULL, "Invalid number of node tags");
|
||||||
}
|
}
|
||||||
size_t entityDim = numNodeTags - 1;
|
|
||||||
def.spec.flex->dim = entityDim;
|
def.spec.flex->dim = entityDim;
|
||||||
|
|
||||||
// element data(Ftetwild): tag and 4 nodeTag
|
// element data(Ftetwild): tag and 4 nodeTag
|
||||||
@@ -1534,7 +1571,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
// read first element
|
// read first element
|
||||||
for (int k =0; k<numNodeTags; k++) {
|
for (int k =0; k<numNodeTags; k++) {
|
||||||
ReadFromBuffer(&nodeTag, elementsBuffer + componentSize*(6+k));
|
ReadFromBuffer(&nodeTag, elementsBuffer + componentSize*(6+k));
|
||||||
if (nodeTag > numElements || nodeTag < 1) {
|
if (nodeTag > numNodes || nodeTag < 1) {
|
||||||
throw mjCError(NULL, "Invalid node tag");
|
throw mjCError(NULL, "Invalid node tag");
|
||||||
}
|
}
|
||||||
element.push_back(nodeTag-1);
|
element.push_back(nodeTag-1);
|
||||||
@@ -1564,7 +1601,7 @@ void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
|||||||
for (int k = 0; k < numNodeTags; k++) {
|
for (int k = 0; k < numNodeTags; k++) {
|
||||||
const char* nodeTagBuffer = elementsBuffer + componentSize*(4+k);
|
const char* nodeTagBuffer = elementsBuffer + componentSize*(4+k);
|
||||||
ReadFromBuffer(&nodeTag, nodeTagBuffer);
|
ReadFromBuffer(&nodeTag, nodeTagBuffer);
|
||||||
if (nodeTag > numElements || nodeTag < 1) {
|
if (nodeTag > numNodes || nodeTag < 1) {
|
||||||
throw mjCError(NULL, "Invalid node tag");
|
throw mjCError(NULL, "Invalid node tag");
|
||||||
}
|
}
|
||||||
element.push_back(nodeTag-1);
|
element.push_back(nodeTag-1);
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
$MeshFormat
|
||||||
|
2.2 0 8
|
||||||
|
$EndMeshFormat
|
||||||
|
$Nodes
|
||||||
|
14
|
||||||
|
1 -0.5 -0.5 0
|
||||||
|
2 0.5 -0.5 0
|
||||||
|
3 0.5 0.5 0
|
||||||
|
4 -0.5 0.5 0
|
||||||
|
5 -0.5 -0.5 1
|
||||||
|
6 0.5 -0.5 1
|
||||||
|
7 0.5 0.5 1
|
||||||
|
8 -0.5 0.5 1
|
||||||
|
9 0 0 0
|
||||||
|
10 0 -0.5 0.5
|
||||||
|
11 0.5 0 0.5
|
||||||
|
12 0 0.5 0.5
|
||||||
|
13 -0.5 0 0.5
|
||||||
|
14 0 0 1
|
||||||
|
$EndNodes
|
||||||
|
$Elements
|
||||||
|
24
|
||||||
|
1 2 2 0 1 9 4 3
|
||||||
|
2 2 2 0 1 9 3 2
|
||||||
|
3 2 2 0 1 9 1 4
|
||||||
|
4 2 2 0 1 9 2 1
|
||||||
|
5 2 2 0 1 2 10 1
|
||||||
|
6 2 2 0 1 1 10 5
|
||||||
|
7 2 2 0 1 6 10 2
|
||||||
|
8 2 2 0 1 5 10 6
|
||||||
|
9 2 2 0 1 3 11 2
|
||||||
|
10 2 2 0 1 2 11 6
|
||||||
|
11 2 2 0 1 7 11 3
|
||||||
|
12 2 2 0 1 6 11 7
|
||||||
|
13 2 2 0 1 4 12 3
|
||||||
|
14 2 2 0 1 3 12 7
|
||||||
|
15 2 2 0 1 8 12 4
|
||||||
|
16 2 2 0 1 7 12 8
|
||||||
|
17 2 2 0 1 1 13 4
|
||||||
|
18 2 2 0 1 5 13 1
|
||||||
|
19 2 2 0 1 4 13 8
|
||||||
|
20 2 2 0 1 8 13 5
|
||||||
|
21 2 2 0 1 5 6 14
|
||||||
|
22 2 2 0 1 8 5 14
|
||||||
|
23 2 2 0 1 6 7 14
|
||||||
|
24 2 2 0 1 7 8 14
|
||||||
|
$EndElements
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<mujoco model="gmsh">
|
||||||
|
<option timestep="0.01" integrator="implicitfast" solver="CG"/>
|
||||||
|
|
||||||
|
<asset>
|
||||||
|
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
|
||||||
|
<texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
|
||||||
|
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
|
||||||
|
</asset>
|
||||||
|
|
||||||
|
<visual>
|
||||||
|
<headlight diffuse="0.9 0.9 0.9" ambient="0.3 0.3 0.3" specular="0 0 0"/>
|
||||||
|
<map force="0.1" zfar="30"/>
|
||||||
|
<rgba haze="0.15 0.25 0.35 1"/>
|
||||||
|
<quality shadowsize="4096"/>
|
||||||
|
<global offwidth="800" offheight="800"/>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<worldbody>
|
||||||
|
<geom name="floor" size="1 1 .05" type="plane" material="grid" condim="3"/>
|
||||||
|
<light directional="false" diffuse=".2 .2 .2" specular="0 0 0" pos="0 0 5" dir="0 0 -1"/>
|
||||||
|
<flexcomp name="cube" type="gmsh" dim="2" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 0"
|
||||||
|
mass="10" scale="1 1 1" file="cube_22_ascii_surf_gmshApp.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
Binary file not shown.
@@ -0,0 +1,26 @@
|
|||||||
|
<mujoco model="gmsh">
|
||||||
|
<option timestep="0.01" integrator="implicitfast" solver="CG"/>
|
||||||
|
|
||||||
|
<asset>
|
||||||
|
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
|
||||||
|
<texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
|
||||||
|
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
|
||||||
|
</asset>
|
||||||
|
|
||||||
|
<visual>
|
||||||
|
<headlight diffuse="0.9 0.9 0.9" ambient="0.3 0.3 0.3" specular="0 0 0"/>
|
||||||
|
<map force="0.1" zfar="30"/>
|
||||||
|
<rgba haze="0.15 0.25 0.35 1"/>
|
||||||
|
<quality shadowsize="4096"/>
|
||||||
|
<global offwidth="800" offheight="800"/>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<worldbody>
|
||||||
|
<geom name="floor" size="1 1 .05" type="plane" material="grid" condim="3"/>
|
||||||
|
<light directional="false" diffuse=".2 .2 .2" specular="0 0 0" pos="0 0 5" dir="0 0 -1"/>
|
||||||
|
<flexcomp name="cube" type="gmsh" dim="2" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 0"
|
||||||
|
mass="10" scale="1 1 1" file="cube_22_binary_surf_gmshApp.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
$MeshFormat
|
||||||
|
4.1 0 8
|
||||||
|
$EndMeshFormat
|
||||||
|
$Entities
|
||||||
|
0 0 1 0
|
||||||
|
1 -0.5 -0.5 0 0.5 0.5 1 0 0
|
||||||
|
$EndEntities
|
||||||
|
$Nodes
|
||||||
|
1 14 1 14
|
||||||
|
2 1 0 14
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
|
9
|
||||||
|
10
|
||||||
|
11
|
||||||
|
12
|
||||||
|
13
|
||||||
|
14
|
||||||
|
-0.5 -0.5 0
|
||||||
|
0.5 -0.5 0
|
||||||
|
0.5 0.5 0
|
||||||
|
-0.5 0.5 0
|
||||||
|
-0.5 -0.5 1
|
||||||
|
0.5 -0.5 1
|
||||||
|
0.5 0.5 1
|
||||||
|
-0.5 0.5 1
|
||||||
|
0 0 0
|
||||||
|
0 -0.5 0.5
|
||||||
|
0.5 0 0.5
|
||||||
|
0 0.5 0.5
|
||||||
|
-0.5 0 0.5
|
||||||
|
0 0 1
|
||||||
|
$EndNodes
|
||||||
|
$Elements
|
||||||
|
1 24 1 24
|
||||||
|
2 1 2 24
|
||||||
|
1 9 4 3
|
||||||
|
2 9 3 2
|
||||||
|
3 9 1 4
|
||||||
|
4 9 2 1
|
||||||
|
5 2 10 1
|
||||||
|
6 1 10 5
|
||||||
|
7 6 10 2
|
||||||
|
8 5 10 6
|
||||||
|
9 3 11 2
|
||||||
|
10 2 11 6
|
||||||
|
11 7 11 3
|
||||||
|
12 6 11 7
|
||||||
|
13 4 12 3
|
||||||
|
14 3 12 7
|
||||||
|
15 8 12 4
|
||||||
|
16 7 12 8
|
||||||
|
17 1 13 4
|
||||||
|
18 5 13 1
|
||||||
|
19 4 13 8
|
||||||
|
20 8 13 5
|
||||||
|
21 5 6 14
|
||||||
|
22 8 5 14
|
||||||
|
23 6 7 14
|
||||||
|
24 7 8 14
|
||||||
|
$EndElements
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<mujoco model="gmsh">
|
||||||
|
<option timestep="0.01" integrator="implicitfast" solver="CG"/>
|
||||||
|
|
||||||
|
<asset>
|
||||||
|
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
|
||||||
|
<texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
|
||||||
|
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
|
||||||
|
</asset>
|
||||||
|
|
||||||
|
<visual>
|
||||||
|
<headlight diffuse="0.9 0.9 0.9" ambient="0.3 0.3 0.3" specular="0 0 0"/>
|
||||||
|
<map force="0.1" zfar="30"/>
|
||||||
|
<rgba haze="0.15 0.25 0.35 1"/>
|
||||||
|
<quality shadowsize="4096"/>
|
||||||
|
<global offwidth="800" offheight="800"/>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<worldbody>
|
||||||
|
<geom name="floor" size="1 1 .05" type="plane" material="grid" condim="3"/>
|
||||||
|
<light directional="false" diffuse=".2 .2 .2" specular="0 0 0" pos="0 0 5" dir="0 0 -1"/>
|
||||||
|
<flexcomp name="cube" type="gmsh" dim="2" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 0"
|
||||||
|
mass="10" scale="1 1 1" file="cube_41_ascii_surf_gmshApp.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
Binary file not shown.
@@ -0,0 +1,26 @@
|
|||||||
|
<mujoco model="gmsh">
|
||||||
|
<option timestep="0.01" integrator="implicitfast" solver="CG"/>
|
||||||
|
|
||||||
|
<asset>
|
||||||
|
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
|
||||||
|
<texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
|
||||||
|
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
|
||||||
|
</asset>
|
||||||
|
|
||||||
|
<visual>
|
||||||
|
<headlight diffuse="0.9 0.9 0.9" ambient="0.3 0.3 0.3" specular="0 0 0"/>
|
||||||
|
<map force="0.1" zfar="30"/>
|
||||||
|
<rgba haze="0.15 0.25 0.35 1"/>
|
||||||
|
<quality shadowsize="4096"/>
|
||||||
|
<global offwidth="800" offheight="800"/>
|
||||||
|
</visual>
|
||||||
|
|
||||||
|
<worldbody>
|
||||||
|
<geom name="floor" size="1 1 .05" type="plane" material="grid" condim="3"/>
|
||||||
|
<light directional="false" diffuse=".2 .2 .2" specular="0 0 0" pos="0 0 5" dir="0 0 -1"/>
|
||||||
|
<flexcomp name="cube" type="gmsh" dim="2" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 0"
|
||||||
|
mass="10" scale="1 1 1" file="cube_41_binary_surf_gmshApp.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<worldbody>
|
<worldbody>
|
||||||
<geom name="floor" size="20 20 .05" type="plane" material="grid" condim="3" />
|
<geom name="floor" size="20 20 .05" type="plane" material="grid" condim="3" />
|
||||||
<light directional="false" diffuse=".2 .2 .2" specular="0 0 0" pos="0 0 5" dir="0 0 -1" />
|
<light directional="false" diffuse=".2 .2 .2" specular="0 0 0" pos="0 0 5" dir="0 0 -1" />
|
||||||
<flexcomp name="shark binary 2.2" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4"
|
<flexcomp name="shark binary 2.2" type="gmsh" dim="3" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4"
|
||||||
mass="10" scale="1 1 1" file="shark_41_ascii_missing_node_index.msh">
|
mass="10" scale="1 1 1" file="shark_41_ascii_missing_node_index.msh">
|
||||||
<edge equality="true" />
|
<edge equality="true" />
|
||||||
</flexcomp>
|
</flexcomp>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ $EndEntities
|
|||||||
$Nodes
|
$Nodes
|
||||||
1 652 1 652
|
1 652 1 652
|
||||||
3 0 0 652
|
3 0 0 652
|
||||||
1
|
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
4
|
4
|
||||||
|
|||||||
+108
-3
@@ -23,6 +23,8 @@
|
|||||||
#include <mujoco/mujoco.h>
|
#include <mujoco/mujoco.h>
|
||||||
#include "test/fixture.h"
|
#include "test/fixture.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace mujoco {
|
namespace mujoco {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -32,6 +34,8 @@ using ::testing::HasSubstr;
|
|||||||
using UserFlexTest = MujocoTest;
|
using UserFlexTest = MujocoTest;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST_F(UserFlexTest, ParentMustHaveName) {
|
TEST_F(UserFlexTest, ParentMustHaveName) {
|
||||||
static constexpr char xml[] = R"(
|
static constexpr char xml[] = R"(
|
||||||
<mujoco>
|
<mujoco>
|
||||||
@@ -255,6 +259,56 @@ TEST_F(UserFlexTest, LoadMSHBinaryGMSH_22_Success) {
|
|||||||
mj_deleteData(d);
|
mj_deleteData(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHSurfaceBinaryGMSH_41_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/cube_41_binary_surf_gmshApp.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
ASSERT_THAT(m, NotNull()) << error.data();
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_EQ(m->nflexvert, 14);
|
||||||
|
EXPECT_EQ(m->nflexelem, 24);
|
||||||
|
|
||||||
|
// first node x y z
|
||||||
|
EXPECT_EQ(m->flex_xvert0[0], -0.5 );
|
||||||
|
EXPECT_EQ(m->flex_xvert0[1], -0.5 );
|
||||||
|
EXPECT_EQ(m->flex_xvert0[2], 0 );
|
||||||
|
|
||||||
|
// first element
|
||||||
|
EXPECT_EQ(m->flex_elem[0], 9-1 );
|
||||||
|
EXPECT_EQ(m->flex_elem[1], 4-1 );
|
||||||
|
EXPECT_EQ(m->flex_elem[2], 3-1 );
|
||||||
|
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHSurfaceBinaryGMSH_22_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/cube_22_binary_surf_gmshApp.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
ASSERT_THAT(m, NotNull()) << error.data();
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_EQ(m->nflexvert, 14);
|
||||||
|
EXPECT_EQ(m->nflexelem, 24);
|
||||||
|
|
||||||
|
// first node x y z
|
||||||
|
EXPECT_EQ(m->flex_xvert0[0], -0.5 );
|
||||||
|
EXPECT_EQ(m->flex_xvert0[1], -0.5 );
|
||||||
|
EXPECT_EQ(m->flex_xvert0[2], 0 );
|
||||||
|
|
||||||
|
// first element
|
||||||
|
EXPECT_EQ(m->flex_elem[0], 9-1 );
|
||||||
|
EXPECT_EQ(m->flex_elem[1], 4-1 );
|
||||||
|
EXPECT_EQ(m->flex_elem[2], 3-1 );
|
||||||
|
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(UserFlexTest, LoadMSHBinaryFTETWILD_22_Success) {
|
TEST_F(UserFlexTest, LoadMSHBinaryFTETWILD_22_Success) {
|
||||||
const std::string xml_path =
|
const std::string xml_path =
|
||||||
GetTestDataFilePath("user/testdata/shark_22_binary_fTetWild.xml");
|
GetTestDataFilePath("user/testdata/shark_22_binary_fTetWild.xml");
|
||||||
@@ -297,6 +351,56 @@ TEST_F(UserFlexTest, LoadMSHASCIIGMSH_22_Success) {
|
|||||||
mj_deleteData(d);
|
mj_deleteData(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHSurfaceASCIIGMSH_41_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/cube_41_ascii_surf_gmshApp.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
ASSERT_THAT(m, NotNull()) << error.data();
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_EQ(m->nflexvert, 14);
|
||||||
|
EXPECT_EQ(m->nflexelem, 24);
|
||||||
|
|
||||||
|
// first node x y z
|
||||||
|
EXPECT_EQ(m->flex_xvert0[0], -0.5 );
|
||||||
|
EXPECT_EQ(m->flex_xvert0[1], -0.5 );
|
||||||
|
EXPECT_EQ(m->flex_xvert0[2], 0 );
|
||||||
|
|
||||||
|
// first element
|
||||||
|
EXPECT_EQ(m->flex_elem[0], 9-1 );
|
||||||
|
EXPECT_EQ(m->flex_elem[1], 4-1 );
|
||||||
|
EXPECT_EQ(m->flex_elem[2], 3-1 );
|
||||||
|
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHSurfaceASCIIGMSH_22_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/cube_22_ascii_surf_gmshApp.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
ASSERT_THAT(m, NotNull()) << error.data();
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_EQ(m->nflexvert, 14);
|
||||||
|
EXPECT_EQ(m->nflexelem, 24);
|
||||||
|
|
||||||
|
// first node x y z
|
||||||
|
EXPECT_EQ(m->flex_xvert0[0], -0.5 );
|
||||||
|
EXPECT_EQ(m->flex_xvert0[1], -0.5 );
|
||||||
|
EXPECT_EQ(m->flex_xvert0[2], 0 );
|
||||||
|
|
||||||
|
// first element
|
||||||
|
EXPECT_EQ(m->flex_elem[0], 9-1 );
|
||||||
|
EXPECT_EQ(m->flex_elem[1], 4-1 );
|
||||||
|
EXPECT_EQ(m->flex_elem[2], 3-1 );
|
||||||
|
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(UserFlexTest, LoadMSHASCIIFTETWILD_22_Success) {
|
TEST_F(UserFlexTest, LoadMSHASCIIFTETWILD_22_Success) {
|
||||||
const std::string xml_path =
|
const std::string xml_path =
|
||||||
GetTestDataFilePath("user/testdata/shark_22_ascii_fTetWild.xml");
|
GetTestDataFilePath("user/testdata/shark_22_ascii_fTetWild.xml");
|
||||||
@@ -329,7 +433,7 @@ TEST_F(UserFlexTest, LoadMSHASCII_41_MissingNodeIndex_Fail) {
|
|||||||
std::array<char, 1024> error;
|
std::array<char, 1024> error;
|
||||||
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
EXPECT_THAT(error.data(), HasSubstr(
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
"XML Error: Element size must be a multiple of dim+1"));
|
"XML Error: Error: Node tags must be sequential"));
|
||||||
mj_deleteModel(m);
|
mj_deleteModel(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,8 +465,9 @@ TEST_F(UserFlexTest, LoadMSHASCII_22_MissingNumNodes_Fail) {
|
|||||||
"user/testdata/malformed_shark_22_ascii_missing_num_nodes.xml");
|
"user/testdata/malformed_shark_22_ascii_missing_num_nodes.xml");
|
||||||
std::array<char, 1024> error;
|
std::array<char, 1024> error;
|
||||||
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
EXPECT_THAT(error.data(), HasSubstr(
|
// TODO(mohammadhamid): Replace with an assertion about the error message. For
|
||||||
"XML Error: Element size must be a multiple of dim+1"));
|
// some reason, on Windows the error message is different on GH Actions
|
||||||
|
EXPECT_THAT(m, IsNull());
|
||||||
mj_deleteModel(m);
|
mj_deleteModel(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user