Added support for msh2.2
Now we can load flex with format 2.2 binary and ASCII. There are two different parsing strategies. One for gmsh app and the other is for ftetwild. Used the shark model from Scanned Objects by Google Research: https://app.gazebosim.org/GoogleResearch/fuel/models/Weisshai_Great_White_Shark PiperOrigin-RevId: 619229499 Change-Id: I6eb876afcbc8a00631914b093c45bde10c0caaf6
This commit is contained in:
committed by
Copybara-Service
parent
4d2aa46e56
commit
4f0293c6cb
@@ -3808,8 +3808,12 @@ saving the XML:
|
|||||||
in MuJoCo can be used as a rigid geom attached to a single body. In contrast, the flex generated here corresponds to
|
in MuJoCo can be used as a rigid geom attached to a single body. In contrast, the flex generated here corresponds to
|
||||||
a soft mesh with the same initial shape, where each vertex is a separate moving body (unless pinned).
|
a soft mesh with the same initial shape, where each vertex is a separate moving body (unless pinned).
|
||||||
|
|
||||||
**gmsh** is similar to mesh, but it loads a `GMSH file <https://gmsh.info//doc/texinfo/gmsh.html#MSH-file-format>`__
|
.. _gmsh-file-docs:
|
||||||
in format 4.1 (ascii or binary). The file extension can be anything; the parser recognizes the format by examining
|
|
||||||
|
**gmsh** is similar to mesh, but it loads a GMSH file in
|
||||||
|
`format 4.1 <https://gmsh.info//doc/texinfo/gmsh.html#MSH-file-format>`__
|
||||||
|
and `format 2.2 <https://gmsh.info//doc/texinfo/gmsh.html#MSH-file-format-version-2-_0028Legacy_0029>`__
|
||||||
|
(ascii or binary). The file extension can be anything; the parser recognizes the format by examining
|
||||||
the file header. This is a very rich file format, allowing all kinds of elements with different dimensionality and
|
the file header. This is a very rich file format, allowing all kinds of elements with different dimensionality and
|
||||||
topology. MuJoCo only supports GMSH element types 1, 2, 4 which happen to correspond to our 1D, 2D and 3D flexes and
|
topology. MuJoCo only supports GMSH element types 1, 2, 4 which happen to correspond to our 1D, 2D and 3D flexes and
|
||||||
assumes that the nodes are specified in a single block. Only the Nodes and Elements sections of the GMHS file are
|
assumes that the nodes are specified in a single block. Only the Nodes and Elements sections of the GMHS file are
|
||||||
@@ -3817,7 +3821,7 @@ saving the XML:
|
|||||||
GMSH file contains meshes that are not supported by MuJoCo. :at:`dim` is automatically set to the dimensionality
|
GMSH file contains meshes that are not supported by MuJoCo. :at:`dim` is automatically set to the dimensionality
|
||||||
specified in the GMSH file. Presently this is the only mechanism to load a large tetrahedral mesh in MuJoCo and
|
specified in the GMSH file. Presently this is the only mechanism to load a large tetrahedral mesh in MuJoCo and
|
||||||
generate a corresponding soft entity. If such a mesh is available in a different file format, use the freely
|
generate a corresponding soft entity. If such a mesh is available in a different file format, use the freely
|
||||||
available `GMSH software <https://gmsh.info/>`__ to convert it to GMSH 4.1.
|
available `GMSH software <https://gmsh.info/>`__ to convert it to GMSH in one of the supported versions.
|
||||||
|
|
||||||
**direct** allows the user to specify the point and element data of the flexcomp directly in the XML. Note that
|
**direct** allows the user to specify the point and element data of the flexcomp directly in the XML. Note that
|
||||||
flexcomp will still generate moving bodies automatically, as well as automate other settings; so it still provides
|
flexcomp will still generate moving bodies automatically, as well as automate other settings; so it still provides
|
||||||
@@ -3873,7 +3877,7 @@ saving the XML:
|
|||||||
: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 **mesh** or a **gmsh** is loaded. For mesh, the file extentsion is used to
|
||||||
determine the file format. Supported formats are the same as in :ref:`mesh assets<asset-mesh>`. For gmsh, the file is
|
determine the file format. Supported formats are the same as in :ref:`mesh assets<asset-mesh>`. For gmsh, the file is
|
||||||
expected to be in GMSH format 4.1, ascii or binary.
|
expected to be in GMSH format 4.1 or 2.2, ascii or binary, see :ref:`here<gmsh-file-docs>`.
|
||||||
|
|
||||||
.. _body-flexcomp-rigid:
|
.. _body-flexcomp-rigid:
|
||||||
|
|
||||||
|
|||||||
+9
-5
@@ -5,16 +5,20 @@ Changelog
|
|||||||
Upcoming version (not yet released)
|
Upcoming version (not yet released)
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
|
General
|
||||||
|
^^^^^^^
|
||||||
|
1. Added support for gmsh format 2.2, as generated by e.g. `fTetwild <https://github.com/wildmeshing/fTetWild>`__.
|
||||||
|
|
||||||
MJX
|
MJX
|
||||||
^^^
|
^^^
|
||||||
|
|
||||||
1. Improved performance of SAT for convex collisions.
|
2. Improved performance of SAT for convex collisions.
|
||||||
2. Fixed bug for sphere/capsule-convex deep penetration.
|
3. Fixed bug for sphere/capsule-convex deep penetration.
|
||||||
3. Fixed bug where ``mjx.Data`` produced by ``mjx.put_data`` had different treedef than ``mjx.make_data``.
|
4. Fixed bug where ``mjx.Data`` produced by ``mjx.put_data`` had different treedef than ``mjx.make_data``.
|
||||||
4. Throw an error for margin/gap for convex mesh collisions, since they are not supported.
|
5. Throw an error for margin/gap for convex mesh collisions, since they are not supported.
|
||||||
|
|
||||||
Version 3.1.3 (March 5th, 2024)
|
Version 3.1.3 (March 5th, 2024)
|
||||||
-----------------------------------
|
-------------------------------
|
||||||
|
|
||||||
General
|
General
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
|||||||
+331
-71
@@ -12,16 +12,14 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "user/user_api.h"
|
#include <algorithm>
|
||||||
#include "user/user_flexcomp.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <mujoco/mjmacro.h>
|
#include <mujoco/mjmacro.h>
|
||||||
#include <mujoco/mjmodel.h>
|
#include <mujoco/mjmodel.h>
|
||||||
@@ -34,6 +32,7 @@
|
|||||||
#include "engine/engine_util_errmem.h"
|
#include "engine/engine_util_errmem.h"
|
||||||
#include "engine/engine_util_misc.h"
|
#include "engine/engine_util_misc.h"
|
||||||
#include "engine/engine_util_spatial.h"
|
#include "engine/engine_util_spatial.h"
|
||||||
|
#include "user/user_flexcomp.h"
|
||||||
#include "user/user_model.h"
|
#include "user/user_model.h"
|
||||||
#include "user/user_objects.h"
|
#include "user/user_objects.h"
|
||||||
#include "user/user_util.h"
|
#include "user/user_util.h"
|
||||||
@@ -58,6 +57,12 @@ static void ReadFromBuffer(T* dst, const char* src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ReadStrFromBuffer(char* dest, const char* src, int maxlen) {
|
||||||
|
std::strncpy(dest, src, maxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// constructor: set defaults outside mjCDef
|
// constructor: set defaults outside mjCDef
|
||||||
mjCFlexcomp::mjCFlexcomp(void) {
|
mjCFlexcomp::mjCFlexcomp(void) {
|
||||||
type = mjFCOMPTYPE_GRID;
|
type = mjFCOMPTYPE_GRID;
|
||||||
@@ -958,7 +963,6 @@ static int findstring(const char* buffer, int buffer_sz, const char* str) {
|
|||||||
|
|
||||||
// scan buffer
|
// scan buffer
|
||||||
for (int i=0; i < buffer_sz-len; i++) {
|
for (int i=0; i < buffer_sz-len; i++) {
|
||||||
|
|
||||||
// check for string at position i
|
// check for string at position i
|
||||||
bool found = true;
|
bool found = true;
|
||||||
for (int k=0; k < len; k++) {
|
for (int k=0; k < len; k++) {
|
||||||
@@ -1020,55 +1024,11 @@ bool mjCFlexcomp::MakeGMSH(mjCModel* model, char* error, int error_sz) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// load GMSH file from resource
|
// load GMSH format 4.1
|
||||||
void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
void mjCFlexcomp::LoadGMSH41(char* buffer, int binary, int nodeend,
|
||||||
// get buffer from resource
|
int nodebegin, int elemend, int elembegin){
|
||||||
char* buffer = 0;
|
// header size
|
||||||
int buffer_sz = mju_readResource(resource, (const void**) &buffer);
|
constexpr int kGmsh41HeaderSize = 52;
|
||||||
|
|
||||||
// check buffer
|
|
||||||
if (buffer_sz<0) {
|
|
||||||
throw mjCError(NULL, "Could not read GMSH file");
|
|
||||||
} else if (buffer_sz==0) {
|
|
||||||
throw mjCError(NULL, "Empty GMSH file");
|
|
||||||
} else if (buffer_sz<11 || strncmp(buffer, "$MeshFormat", 11)) {
|
|
||||||
throw mjCError(NULL, "GMSH file must begin with $MeshFormat");
|
|
||||||
}
|
|
||||||
|
|
||||||
// check version, determine ascii or binary
|
|
||||||
double version;
|
|
||||||
int binary;
|
|
||||||
if (sscanf(buffer+11, "%lf %d", &version, &binary) != 2) {
|
|
||||||
throw mjCError(NULL, "Could not read GMSH file header");
|
|
||||||
}
|
|
||||||
if (mju_round(100*version)!=410) {
|
|
||||||
throw mjCError(NULL, "Only GMSH file format 4.1 supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
// find section begin/end
|
|
||||||
int nodebegin = findstring(buffer, buffer_sz, "$Nodes");
|
|
||||||
int nodeend = findstring(buffer, buffer_sz, "$EndNodes");
|
|
||||||
int elembegin = findstring(buffer, buffer_sz, "$Elements");
|
|
||||||
int elemend = findstring(buffer, buffer_sz, "$EndElements");
|
|
||||||
|
|
||||||
// check sections
|
|
||||||
if (nodebegin<0) {
|
|
||||||
throw mjCError(NULL, "GMSH file missing $Nodes");
|
|
||||||
}
|
|
||||||
if (nodeend<nodebegin) {
|
|
||||||
throw mjCError(NULL, "GMSH file missing $EndNodes after $Nodes");
|
|
||||||
}
|
|
||||||
if (elembegin<0) {
|
|
||||||
throw mjCError(NULL, "GMSH file missing $Elements");
|
|
||||||
}
|
|
||||||
if (elemend<elembegin) {
|
|
||||||
throw mjCError(NULL, "GMSH file missing $EndElements after $Elements");
|
|
||||||
}
|
|
||||||
|
|
||||||
// correct begin for string size, +1 for LF in binary (CRLF in Win ascii works)
|
|
||||||
nodebegin += (int)strlen("$Nodes") + 1;
|
|
||||||
elembegin += (int)strlen("$Elements") + 1;
|
|
||||||
|
|
||||||
// base for node tags, to be subtracted from element data
|
// base for node tags, to be subtracted from element data
|
||||||
size_t minNodeTag, numEntityBlocks, numNodes, maxNodeTag, numNodesInBlock, tag;
|
size_t minNodeTag, numEntityBlocks, numNodes, maxNodeTag, numNodesInBlock, tag;
|
||||||
int entityDim, entityTag, parametric;
|
int entityDim, entityTag, parametric;
|
||||||
@@ -1076,8 +1036,7 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
|||||||
// ascii nodes
|
// ascii nodes
|
||||||
if (binary == 0) {
|
if (binary == 0) {
|
||||||
// convert node char buffer to stringstream
|
// convert node char buffer to stringstream
|
||||||
buffer[nodeend] = 0;
|
stringstream ss(string(buffer + nodebegin, nodeend - nodebegin));
|
||||||
stringstream ss(buffer+nodebegin);
|
|
||||||
|
|
||||||
// read header
|
// read header
|
||||||
ss >> numEntityBlocks >> numNodes >> minNodeTag >> maxNodeTag;
|
ss >> numEntityBlocks >> numNodes >> minNodeTag >> maxNodeTag;
|
||||||
@@ -1120,11 +1079,10 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
|||||||
point.push_back(x);
|
point.push_back(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// binary nodes
|
// binary nodes
|
||||||
else {
|
else {
|
||||||
// check header size: 5 size_t, 3 int
|
// check header size
|
||||||
if (nodeend-nodebegin < 52) {
|
if (nodeend-nodebegin < kGmsh41HeaderSize) {
|
||||||
throw mjCError(NULL, "Invalid nodes header");
|
throw mjCError(NULL, "Invalid nodes header");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1149,15 +1107,20 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
|||||||
}
|
}
|
||||||
def.spec.flex->dim = entityDim;
|
def.spec.flex->dim = entityDim;
|
||||||
|
|
||||||
|
// nodeData: node tag and 3 nodes
|
||||||
|
constexpr int numNodeComponents = 4;
|
||||||
|
constexpr int componentSize = 8;
|
||||||
|
int nodeDataSize = numNodeComponents*componentSize;
|
||||||
|
|
||||||
// check section byte size
|
// check section byte size
|
||||||
if (nodeend-nodebegin < 52+numNodes*4*8) {
|
if (nodeend-nodebegin < kGmsh41HeaderSize + numNodes*nodeDataSize) {
|
||||||
throw mjCError(NULL, "Insufficient byte size of Nodes");
|
throw mjCError(NULL, "Insufficient byte size of Nodes");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check node tags: must range from minNodeTag to maxNodeTag
|
// check node tags: must range from minNodeTag to maxNodeTag
|
||||||
const char* tagbuffer = buffer + nodebegin + 52;
|
const char* tagbuffer = buffer + nodebegin + kGmsh41HeaderSize;
|
||||||
for (size_t i=0; i < numNodes; i++) {
|
for (size_t i=0; i < numNodes; i++) {
|
||||||
ReadFromBuffer(&tag, tagbuffer+i*8);
|
ReadFromBuffer(&tag, tagbuffer + i*componentSize);
|
||||||
if (tag != i+minNodeTag) {
|
if (tag != i+minNodeTag) {
|
||||||
throw mjCError(NULL, "Node tags must be sequential");
|
throw mjCError(NULL, "Node tags must be sequential");
|
||||||
}
|
}
|
||||||
@@ -1166,9 +1129,9 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
|||||||
// read points
|
// read points
|
||||||
double x;
|
double x;
|
||||||
point.reserve(3*numNodes);
|
point.reserve(3*numNodes);
|
||||||
const char* pointbuffer = buffer + nodebegin + 52 + 8*numNodes;
|
const char* pointbuffer = buffer + nodebegin + kGmsh41HeaderSize + componentSize*numNodes;
|
||||||
for (size_t i=0; i < 3*numNodes; i++) {
|
for (size_t i=0; i < 3*numNodes; i++) {
|
||||||
ReadFromBuffer(&x, pointbuffer+i*8);
|
ReadFromBuffer(&x, pointbuffer + i*componentSize);
|
||||||
point.push_back(x);
|
point.push_back(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1223,8 +1186,8 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
|||||||
|
|
||||||
// binary elements
|
// binary elements
|
||||||
else {
|
else {
|
||||||
// check header size: 5 size_t, 3 int
|
// check header size
|
||||||
if (elemend-elembegin < 52) {
|
if (elemend-elembegin < kGmsh41HeaderSize) {
|
||||||
throw mjCError(NULL, "Invalid elements header");
|
throw mjCError(NULL, "Invalid elements header");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1255,17 +1218,22 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
|||||||
throw mjCError(NULL, "Element type inconsistent with dimensionality");
|
throw mjCError(NULL, "Element type inconsistent with dimensionality");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// elementData: element tag and n node tags
|
||||||
|
int numElementComponents = (entityDim+2);
|
||||||
|
constexpr int componentSize = 8;
|
||||||
|
int elementDataSize = numElementComponents*componentSize;
|
||||||
|
|
||||||
// check section byte size
|
// check section byte size
|
||||||
if (elemend-elembegin < 52+numElements*(entityDim+2)*8) {
|
if (elemend - elembegin < kGmsh41HeaderSize + numElements*elementDataSize) {
|
||||||
throw mjCError(NULL, "Insufficient byte size of Elements");
|
throw mjCError(NULL, "Insufficient byte size of Elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
// read elements, discard tags
|
// read elements, discard tags
|
||||||
element.reserve((entityDim+1)*numElements);
|
element.reserve((entityDim+1)*numElements);
|
||||||
const char* elembuffer = buffer + elembegin + 52;
|
const char* elembuffer = buffer + elembegin + kGmsh41HeaderSize;
|
||||||
for (size_t i=0; i < numElements; i++) {
|
for (size_t i=0; i < numElements; i++) {
|
||||||
// skip element tag
|
// skip element tag
|
||||||
elembuffer += 8;
|
elembuffer += componentSize;
|
||||||
|
|
||||||
// read vertex ids
|
// read vertex ids
|
||||||
size_t elemid;
|
size_t elemid;
|
||||||
@@ -1273,8 +1241,300 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
|||||||
ReadFromBuffer(&elemid, elembuffer);
|
ReadFromBuffer(&elemid, elembuffer);
|
||||||
int elementid = elemid - minNodeTag;
|
int elementid = elemid - minNodeTag;
|
||||||
element.push_back(elementid);
|
element.push_back(elementid);
|
||||||
elembuffer += 8;
|
elembuffer += componentSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// load GMSH format 2.2
|
||||||
|
void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
|
||||||
|
int nodebegin, int elemend, int elembegin) {
|
||||||
|
// ascii nodes
|
||||||
|
if (binary == 0) {
|
||||||
|
// convert node char buffer to stringstream
|
||||||
|
stringstream ss(string(buffer + nodebegin, nodeend - nodebegin));
|
||||||
|
|
||||||
|
// read header
|
||||||
|
size_t maxNodeTag = 0;
|
||||||
|
ss >> maxNodeTag;
|
||||||
|
if (!ss.good()) {
|
||||||
|
throw mjCError(NULL, "Error reading Nodes header");
|
||||||
|
}
|
||||||
|
size_t numNodes = maxNodeTag;
|
||||||
|
|
||||||
|
// read points, discard tag
|
||||||
|
point.reserve(3*numNodes);
|
||||||
|
for (size_t i=0; i < numNodes; i++) {
|
||||||
|
size_t tag;
|
||||||
|
double x;
|
||||||
|
ss >> tag;
|
||||||
|
if (!ss.good()) {
|
||||||
|
throw mjCError(NULL, "Error reading node tags");
|
||||||
|
}
|
||||||
|
// reading nodes
|
||||||
|
for (int k=0; k < 3; k++) {
|
||||||
|
ss >> x;
|
||||||
|
if (!ss.good()) {
|
||||||
|
throw mjCError(NULL, "Error reading node coordinates");
|
||||||
|
}
|
||||||
|
point.push_back(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary nodes
|
||||||
|
else {
|
||||||
|
// header size for gmshApp
|
||||||
|
constexpr int nodeHeaderSizeGmshApp = 5;
|
||||||
|
// header size compatible with both gmshApp and Ftetwild
|
||||||
|
constexpr int nodeHeaderSize = nodeHeaderSizeGmshApp - 1;
|
||||||
|
// check header size
|
||||||
|
if (nodeend-nodebegin < nodeHeaderSize) {
|
||||||
|
throw mjCError(NULL, "Invalid nodes header");
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse maxNodeTag and then cast it to int
|
||||||
|
char maxNodeTagChar[20];
|
||||||
|
ReadStrFromBuffer(maxNodeTagChar, buffer + nodebegin, std::min(10, nodeend - nodebegin));
|
||||||
|
size_t measuredHeaderSize = strnlen(maxNodeTagChar, 20) - 1;
|
||||||
|
size_t maxNodeTag = std::stoi(maxNodeTagChar);
|
||||||
|
size_t numNodes = maxNodeTag;
|
||||||
|
|
||||||
|
// node data: node tag and 3 nodes
|
||||||
|
int nodeSize = sizeof(double);
|
||||||
|
int indexSize = sizeof(int);
|
||||||
|
int nodeDataSize = indexSize + 3*nodeSize;
|
||||||
|
|
||||||
|
// check section byte size
|
||||||
|
if (nodeend - nodebegin < nodeHeaderSize + numNodes*nodeDataSize) {
|
||||||
|
throw mjCError(NULL, "Insufficient byte size of Nodes");
|
||||||
|
}
|
||||||
|
|
||||||
|
// read point, discard tag
|
||||||
|
point.reserve(3*numNodes);
|
||||||
|
// beginning of buffer containing node info
|
||||||
|
const char* tagBuffer = buffer + nodebegin + measuredHeaderSize;
|
||||||
|
for (int i=0; i < numNodes; i++) {
|
||||||
|
int tag;
|
||||||
|
int offset = i*(sizeof(int) + sizeof(double)*3);
|
||||||
|
ReadFromBuffer(&tag, tagBuffer + offset);
|
||||||
|
for (int k=0; k < 3; k++) {
|
||||||
|
double x;
|
||||||
|
const char* nodeBuffer = tagBuffer + sizeof(int) + sizeof(double)*k;
|
||||||
|
ReadFromBuffer(&x, nodeBuffer + offset);
|
||||||
|
point.push_back(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t entityDim = 3;
|
||||||
|
def.spec.flex->dim = entityDim;
|
||||||
|
|
||||||
|
// ascii elements
|
||||||
|
if (binary == 0) {
|
||||||
|
// convert element char buffer to stringstream
|
||||||
|
buffer[elemend] = 0;
|
||||||
|
stringstream ss(buffer + elembegin);
|
||||||
|
|
||||||
|
// read header
|
||||||
|
size_t maxElementTag = 0;
|
||||||
|
ss >> maxElementTag;
|
||||||
|
if (!ss.good()) {
|
||||||
|
throw mjCError(NULL, "Error reading Elements header");
|
||||||
|
}
|
||||||
|
size_t numElements = maxElementTag;
|
||||||
|
// read elements, discard all tags
|
||||||
|
element.reserve((entityDim+1)*numElements);
|
||||||
|
for (size_t i=0; i < numElements; i++) {
|
||||||
|
int tag = 0, type = 0, numTags = 0, nodeTag = 0, physicalEntityTag = 0,
|
||||||
|
elmentModelEntityTag = 0;
|
||||||
|
ss >> tag >> type >> numTags;
|
||||||
|
if (!ss.good()) {
|
||||||
|
throw mjCError(NULL, "Error reading Elements");
|
||||||
|
}
|
||||||
|
if (numTags > 0) {
|
||||||
|
ss >> physicalEntityTag >> elmentModelEntityTag;
|
||||||
|
if (!ss.good()) {
|
||||||
|
throw mjCError(NULL, "Error reading Elements");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int k=0; k <= entityDim; k++) {
|
||||||
|
ss >> nodeTag;
|
||||||
|
if (!ss.good()) {
|
||||||
|
throw mjCError(NULL, "Error reading Elements");
|
||||||
|
}
|
||||||
|
element.push_back((int)(nodeTag-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// binary elements
|
||||||
|
else {
|
||||||
|
// header size for gmshApp
|
||||||
|
constexpr int elementHeaderSizeGmshApp = 6;
|
||||||
|
// header size for Ftetwild
|
||||||
|
constexpr int elementHeaderSizeFtetwild = 17;
|
||||||
|
// check header size
|
||||||
|
if (elemend - elembegin < elementHeaderSizeGmshApp) {
|
||||||
|
throw mjCError(NULL, "Invalid elements header");
|
||||||
|
}
|
||||||
|
|
||||||
|
// reading elements
|
||||||
|
char maxElementTagChar[20];
|
||||||
|
ReadStrFromBuffer(maxElementTagChar, buffer + elembegin, std::min(10, elemend - elembegin));
|
||||||
|
int measuredHeaderSize = strnlen(maxElementTagChar, 20) - 1;
|
||||||
|
int maxElementTag = std::stoi(maxElementTagChar);
|
||||||
|
int numElements = maxElementTag;
|
||||||
|
int tag, numTags;
|
||||||
|
int nodeTag;
|
||||||
|
|
||||||
|
// size of single component in element data
|
||||||
|
int componentSize = sizeof(int);
|
||||||
|
// element buffer
|
||||||
|
const char* elementsBuffer = buffer + elembegin + measuredHeaderSize;
|
||||||
|
|
||||||
|
ReadFromBuffer(&numTags, elementsBuffer + componentSize*2);
|
||||||
|
ReadFromBuffer(&tag, elementsBuffer + componentSize*3);
|
||||||
|
|
||||||
|
// element data(Ftetwild): tag and 4 nodeTag
|
||||||
|
constexpr int numComponentsFtetwild = 5;
|
||||||
|
// element data(gmshApp): 4 Info components, 2 entity tag and 4 nodeTags
|
||||||
|
constexpr int numInfoComponents = 4;
|
||||||
|
constexpr int numEntityTagComponents = 2;
|
||||||
|
constexpr int numNodeTags = 4;
|
||||||
|
constexpr int numComponentsGmshApp = numInfoComponents +
|
||||||
|
numEntityTagComponents + numNodeTags;
|
||||||
|
|
||||||
|
// single element data size
|
||||||
|
int elementDataSizeFtetwild = numComponentsFtetwild*componentSize;
|
||||||
|
int elementDataSizeGmshApp = numComponentsGmshApp*componentSize;
|
||||||
|
|
||||||
|
// elements section buffer size
|
||||||
|
int elementsBufferSizeFtetwild = elementHeaderSizeFtetwild +
|
||||||
|
numElements*elementDataSizeFtetwild;
|
||||||
|
int elementsBufferSizeGmshApp = elementHeaderSizeGmshApp +
|
||||||
|
numElements*elementDataSizeGmshApp;
|
||||||
|
|
||||||
|
// check section byte size for ftetwild
|
||||||
|
if (elemend - elembegin < elementsBufferSizeFtetwild) {
|
||||||
|
throw mjCError(NULL, "Insufficient byte size of Elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handling elements produced by gmsh
|
||||||
|
if (numTags > 0) {
|
||||||
|
// check section byte size for gmsh
|
||||||
|
if (elemend - elembegin < elementsBufferSizeGmshApp) {
|
||||||
|
throw mjCError(NULL, "Insufficient byte size of Elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
// read first element
|
||||||
|
for (int k =0; k<numNodeTags; k++) {
|
||||||
|
ReadFromBuffer(&nodeTag, elementsBuffer + componentSize*(6+k));
|
||||||
|
element.push_back(nodeTag-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read every other element
|
||||||
|
for (int i=1; i < numElements; i++) {
|
||||||
|
const char* numTagsBuffer = elementsBuffer + componentSize*2;
|
||||||
|
const char* tagBuffer = elementsBuffer + componentSize*3;
|
||||||
|
int offset = i*elementDataSizeGmshApp;
|
||||||
|
ReadFromBuffer(&numTags, numTagsBuffer + offset);
|
||||||
|
ReadFromBuffer(&tag, tagBuffer+offset);
|
||||||
|
for (int k =0; k < numNodeTags; k++) {
|
||||||
|
const char* nodeTagBuffer = elementsBuffer + componentSize*(6+k);
|
||||||
|
ReadFromBuffer(&nodeTag, nodeTagBuffer + offset);
|
||||||
|
element.push_back(nodeTag-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handling elements produced by ftetwild
|
||||||
|
else {
|
||||||
|
// read first element
|
||||||
|
for (int k =0; k < numNodeTags; k++) {
|
||||||
|
const char* nodeTagBuffer = elementsBuffer + componentSize*(4+k);
|
||||||
|
ReadFromBuffer(&nodeTag, nodeTagBuffer);
|
||||||
|
element.push_back(nodeTag-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read every other element
|
||||||
|
for (int i=0; i<numElements-1; i++) {
|
||||||
|
int offset = componentSize*(4+2) + i*elementDataSizeFtetwild;
|
||||||
|
const char* tagBuffer = elementsBuffer + componentSize*2;
|
||||||
|
ReadFromBuffer(&tag, tagBuffer + offset);
|
||||||
|
for (int k=0; k < numNodeTags; k++) {
|
||||||
|
const char* nodeTagBuffer = elementsBuffer + componentSize*(3+k);
|
||||||
|
ReadFromBuffer(&nodeTag, nodeTagBuffer + offset);
|
||||||
|
element.push_back(nodeTag-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// load GMSH file from resource
|
||||||
|
void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
|
||||||
|
// get buffer from resource
|
||||||
|
char* buffer = 0;
|
||||||
|
int buffer_sz = mju_readResource(resource, (const void**) &buffer);
|
||||||
|
|
||||||
|
|
||||||
|
// check buffer
|
||||||
|
if (buffer_sz < 0) {
|
||||||
|
throw mjCError(NULL, "Could not read GMSH file");
|
||||||
|
} else if (buffer_sz == 0) {
|
||||||
|
throw mjCError(NULL, "Empty GMSH file");
|
||||||
|
} else if (buffer_sz < 11 || strncmp(buffer, "$MeshFormat", 11)) {
|
||||||
|
throw mjCError(NULL, "GMSH file must begin with $MeshFormat");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check version, determine ascii or binary
|
||||||
|
double version;
|
||||||
|
int binary;
|
||||||
|
if (sscanf(buffer + 11, "%lf %d", &version, &binary) != 2) {
|
||||||
|
throw mjCError(NULL, "Could not read GMSH file header");
|
||||||
|
}
|
||||||
|
if (mju_round(100*version) != 220 && mju_round(100*version) != 410) {
|
||||||
|
throw mjCError(NULL, "Only GMSH file format versions 4.1 and 2.2 are supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
// find section begin/end
|
||||||
|
int nodebegin = findstring(buffer, buffer_sz, "$Nodes");
|
||||||
|
int nodeend = findstring(buffer, buffer_sz, "$EndNodes");
|
||||||
|
int elembegin = findstring(buffer, buffer_sz, "$Elements");
|
||||||
|
int elemend = findstring(buffer, buffer_sz, "$EndElements");
|
||||||
|
|
||||||
|
|
||||||
|
// check sections
|
||||||
|
if (nodebegin < 0) {
|
||||||
|
throw mjCError(NULL, "GMSH file missing $Nodes");
|
||||||
|
}
|
||||||
|
if (nodeend < nodebegin) {
|
||||||
|
throw mjCError(NULL, "GMSH file missing $EndNodes after $Nodes");
|
||||||
|
}
|
||||||
|
if (elembegin < 0) {
|
||||||
|
throw mjCError(NULL, "GMSH file missing $Elements");
|
||||||
|
}
|
||||||
|
if (elemend < elembegin) {
|
||||||
|
throw mjCError(NULL, "GMSH file missing $EndElements after $Elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
// correct begin for string size, +1 for LF in binary (CRLF in Win ascii works)
|
||||||
|
nodebegin += (int)strlen("$Nodes") + 1;
|
||||||
|
elembegin += (int)strlen("$Elements") + 1;
|
||||||
|
|
||||||
|
|
||||||
|
// Support for 4.1
|
||||||
|
if (mju_round(100*version) == 410) {
|
||||||
|
LoadGMSH41(buffer, binary, nodeend, nodebegin, elemend, elembegin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for 2.2
|
||||||
|
else if (mju_round(100*version) == 220) {
|
||||||
|
LoadGMSH22(buffer, binary, nodeend, nodebegin, elemend, elembegin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ class mjCFlexcomp {
|
|||||||
bool MakeMesh(mjCModel* model, char* error, int error_sz);
|
bool MakeMesh(mjCModel* model, char* error, int error_sz);
|
||||||
bool MakeGMSH(mjCModel* model, char* error, int error_sz);
|
bool MakeGMSH(mjCModel* model, char* error, int error_sz);
|
||||||
void LoadGMSH(mjCModel* model, mjResource* resource);
|
void LoadGMSH(mjCModel* model, mjResource* resource);
|
||||||
|
void LoadGMSH41(char* buffer, int binary, int nodeend, int nodebegin,
|
||||||
|
int elemend, int elembegin);
|
||||||
|
void LoadGMSH22(char* buffer, int binary, int nodeend, int nodebegin,
|
||||||
|
int elemend, int elembegin);
|
||||||
|
|
||||||
|
|
||||||
int GridID(int ix, int iy);
|
int GridID(int ix, int iy);
|
||||||
int GridID(int ix, int iy, int iz);
|
int GridID(int ix, int iy, int iz);
|
||||||
|
|||||||
@@ -32,8 +32,14 @@ test_model() {
|
|||||||
# this test can take several minutes under ASAN
|
# this test can take several minutes under ASAN
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
if [[ "$model" == */benchmark/testdata/humanoid200.xml
|
if [[ "$model" == */benchmark/testdata/humanoid200.xml ||
|
||||||
|| "$model" == */engine/testdata/collision_convex/stacked_boxes.xml
|
"$model" == */engine/testdata/collision_convex/stacked_boxes.xml ||
|
||||||
|
"$model" == */user/testdata/shark_41_ascii_gmshApp.xml ||
|
||||||
|
"$model" == */user/testdata/shark_22_ascii_fTetWild.xml ||
|
||||||
|
"$model" == */user/testdata/shark_22_ascii_gmshApp.xml ||
|
||||||
|
"$model" == */user/testdata/shark_22_binary_fTetWild.xml ||
|
||||||
|
"$model" == */user/testdata/shark_41_binary_gmshApp.xml ||
|
||||||
|
"$model" == */user/testdata/shark_22_binary_gmshApp.xml
|
||||||
]]; then
|
]]; then
|
||||||
iterations=2
|
iterations=2
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<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="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"/>
|
||||||
|
<flexcomp name="shark" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4" mass="10" scale="1 1 1" file="shark_22_ascii_missing_element.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<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="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" />
|
||||||
|
<flexcomp name="shark" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4" mass="10"
|
||||||
|
scale="1 1 1" file="shark_22_ascii_missing_node.msh">
|
||||||
|
<edge equality="true" />
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<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="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" />
|
||||||
|
<flexcomp name="shark" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4" mass="10"
|
||||||
|
scale="1 1 1" file="shark_22_ascii_missing_num_elements.msh">
|
||||||
|
<edge equality="true" />
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<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="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" />
|
||||||
|
<flexcomp name="shark" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4" mass="10"
|
||||||
|
scale="1 1 1" file="shark_22_ascii_missing_num_nodes.msh">
|
||||||
|
<edge equality="true" />
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<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="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" />
|
||||||
|
<flexcomp name="shark binary 2.2" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4"
|
||||||
|
mass="10" scale="1 1 1" file="shark_41_ascii_missing_element.msh">
|
||||||
|
<edge equality="true" />
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<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="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" />
|
||||||
|
<flexcomp name="shark binary 2.2" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4"
|
||||||
|
mass="10" scale="1 1 1" file="shark_41_ascii_missing_element_header.msh">
|
||||||
|
<edge equality="true" />
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<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="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" />
|
||||||
|
<flexcomp name="shark binary 2.2" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 4"
|
||||||
|
mass="10" scale="1 1 1" file="shark_41_ascii_missing_node_header.msh">
|
||||||
|
<edge equality="true" />
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<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="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" />
|
||||||
|
<flexcomp name="shark binary 2.2" type="gmsh" 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">
|
||||||
|
<edge equality="true" />
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
+3979
File diff suppressed because it is too large
Load Diff
+25
@@ -0,0 +1,25 @@
|
|||||||
|
<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="shark" type="gmsh" dim="3" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 .3" mass="10" scale="1 1 1" file="shark_22_ascii_fTetWild.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
+2315
File diff suppressed because it is too large
Load Diff
+25
@@ -0,0 +1,25 @@
|
|||||||
|
<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="shark" type="gmsh" dim="3" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 0.3" mass="10" scale="1 1 1" file="shark_22_ascii_gmshApp.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
+3978
File diff suppressed because it is too large
Load Diff
+3978
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+3978
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
+25
@@ -0,0 +1,25 @@
|
|||||||
|
<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="shark" type="gmsh" dim="3" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 0.3" mass="10" scale="1 1 1" file="shark_22_binary_fTetWild.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
BIN
Binary file not shown.
+25
@@ -0,0 +1,25 @@
|
|||||||
|
<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="shark" type="gmsh" dim="3" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 0.3" mass="10" scale="1 1 1" file="shark_22_binary_gmshApp.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
+2973
File diff suppressed because it is too large
Load Diff
+25
@@ -0,0 +1,25 @@
|
|||||||
|
<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="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"/>
|
||||||
|
<flexcomp name="shark" 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_gmshApp.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
+2972
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
+25
@@ -0,0 +1,25 @@
|
|||||||
|
<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="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"/>
|
||||||
|
<flexcomp name="shark" 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_binary_gmshApp.msh">
|
||||||
|
<edge equality="true"/>
|
||||||
|
</flexcomp>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
@@ -227,5 +227,177 @@ TEST_F(UserFlexTest, CreateBVHSuccess) {
|
|||||||
mj_deleteData(d);
|
mj_deleteData(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHBinaryGMSH_41_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/shark_41_binary_gmshApp.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_THAT(m, NotNull()) << error.data();
|
||||||
|
EXPECT_EQ(m->nflexvert, 652);
|
||||||
|
EXPECT_EQ(m->nflexelem, 1654);
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHBinaryGMSH_22_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/shark_22_binary_gmshApp.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_THAT(m, NotNull()) << error.data();
|
||||||
|
EXPECT_EQ(m->nflexvert, 644);
|
||||||
|
EXPECT_EQ(m->nflexelem, 1635);
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHBinaryFTETWILD_22_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/shark_22_binary_fTetWild.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_THAT(m, NotNull()) << error.data();
|
||||||
|
EXPECT_EQ(m->nflexvert, 644);
|
||||||
|
EXPECT_EQ(m->nflexelem, 1635);
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCIIGMSH_41_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/shark_41_ascii_gmshApp.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_THAT(m, NotNull()) << error.data();
|
||||||
|
EXPECT_EQ(m->nflexvert, 652);
|
||||||
|
EXPECT_EQ(m->nflexelem, 1654);
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCIIGMSH_22_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/shark_22_ascii_gmshApp.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_THAT(m, NotNull()) << error.data();
|
||||||
|
EXPECT_EQ(m->nflexvert, 652);
|
||||||
|
EXPECT_EQ(m->nflexelem, 1654);
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCIIFTETWILD_22_Success) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath("user/testdata/shark_22_ascii_fTetWild.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
mjData* d = mj_makeData(m);
|
||||||
|
EXPECT_THAT(m, NotNull()) << error.data();
|
||||||
|
EXPECT_EQ(m->nflexvert, 652);
|
||||||
|
EXPECT_EQ(m->nflexelem, 1654);
|
||||||
|
mj_step(m, d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
mj_deleteData(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCII_41_MissingNodeHeader_Fail) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath(
|
||||||
|
"user/testdata/malformed_shark_41_ascii_missing_node_header.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
|
"XML Error: Error: All nodes must be in single block"));
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCII_41_MissingNodeIndex_Fail) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath(
|
||||||
|
"user/testdata/malformed_shark_41_ascii_missing_node_index.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
|
"XML Error: Element size must be a multiple of dim+1"));
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCII_41_MissingElementHeader_Fail) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath(
|
||||||
|
"user/testdata/malformed_shark_41_ascii_missing_element_header.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
|
"XML Error: Error: All elements must be in single block"));
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCII_41_MissingElement_Fail) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath(
|
||||||
|
"user/testdata/malformed_shark_41_ascii_missing_element.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
|
"XML Error: Error: Error reading Elements"));
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCII_22_MissingNumNodes_Fail) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath(
|
||||||
|
"user/testdata/malformed_shark_22_ascii_missing_num_nodes.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
|
"XML Error: Element size must be a multiple of dim+1"));
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCII_22_MissingNode_Fail) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath(
|
||||||
|
"user/testdata/malformed_shark_22_ascii_missing_node.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
|
"XML Error: Error: Error reading node tags"));
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCII_22_MissingNumElements_Fail) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath(
|
||||||
|
"user/testdata/malformed_shark_22_ascii_missing_num_elements.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
|
"XML Error: Element size must be a multiple of dim+1"));
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UserFlexTest, LoadMSHASCII_22_MissingElement_Fail) {
|
||||||
|
const std::string xml_path =
|
||||||
|
GetTestDataFilePath(
|
||||||
|
"user/testdata/malformed_shark_22_ascii_missing_element.xml");
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||||
|
EXPECT_THAT(error.data(), HasSubstr(
|
||||||
|
"XML Error: Error: Error reading Elements"));
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace mujoco
|
} // namespace mujoco
|
||||||
|
|||||||
@@ -1204,6 +1204,7 @@ TEST_F(XMLWriterTest, WriteReadCompare) {
|
|||||||
if (absl::StrContains(p.path().string(), "malformed_") ||
|
if (absl::StrContains(p.path().string(), "malformed_") ||
|
||||||
absl::StrContains(p.path().string(), "touch_grid") ||
|
absl::StrContains(p.path().string(), "touch_grid") ||
|
||||||
absl::StrContains(p.path().string(), "gmsh_") ||
|
absl::StrContains(p.path().string(), "gmsh_") ||
|
||||||
|
absl::StrContains(p.path().string(), "shark_") ||
|
||||||
absl::StrContains(p.path().string(), "cow")) {
|
absl::StrContains(p.path().string(), "cow")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user