Use mj_parseXMLString instead of a test-specific LoadFromModelString.
This removes the need for a custom mjResourceProvider, but does require reimplementing part of mj_loadXML in the fixture. PiperOrigin-RevId: 854170820 Change-Id: Ib455cc5cdb5138213eb7e996dc32ac156f22a859
This commit is contained in:
committed by
Copybara-Service
parent
2c4f710cf4
commit
398e3dcf15
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <mujoco/mujoco.h>
|
#include <mujoco/mujoco.h>
|
||||||
|
|
||||||
void SetGlobalXmlSpec(mjSpec* spec = nullptr);
|
MJAPI void SetGlobalXmlSpec(mjSpec* spec = nullptr);
|
||||||
|
|
||||||
std::string GetGlobalXmlSpec(const mjModel* m, char* error, int error_sz);
|
std::string GetGlobalXmlSpec(const mjModel* m, char* error, int error_sz);
|
||||||
|
|
||||||
|
|||||||
+21
-19
@@ -41,6 +41,7 @@
|
|||||||
#include <mujoco/mjmodel.h>
|
#include <mujoco/mjmodel.h>
|
||||||
#include <mujoco/mjxmacro.h>
|
#include <mujoco/mjxmacro.h>
|
||||||
#include <mujoco/mujoco.h>
|
#include <mujoco/mujoco.h>
|
||||||
|
#include "src/xml/xml_global.h"
|
||||||
|
|
||||||
namespace mujoco {
|
namespace mujoco {
|
||||||
namespace {
|
namespace {
|
||||||
@@ -85,26 +86,27 @@ const std::string GetModelPath(std::string_view path) { // NOLINT
|
|||||||
|
|
||||||
mjModel* LoadModelFromString(std::string_view xml, char* error,
|
mjModel* LoadModelFromString(std::string_view xml, char* error,
|
||||||
int error_size, mjVFS* vfs) {
|
int error_size, mjVFS* vfs) {
|
||||||
// register string resource provider if not registered before
|
if (error) {
|
||||||
if (mjp_getResourceProvider("LoadModelFromString:") == nullptr) {
|
error[0] = '\0';
|
||||||
mjpResourceProvider resourceProvider;
|
|
||||||
mjp_defaultResourceProvider(&resourceProvider);
|
|
||||||
resourceProvider.prefix = "LoadModelFromString";
|
|
||||||
resourceProvider.open = +[](mjResource* resource) {
|
|
||||||
resource->data = &(resource->name[strlen("LoadModelFromString:")]);
|
|
||||||
return 1;
|
|
||||||
};
|
|
||||||
resourceProvider.read =
|
|
||||||
+[](mjResource* resource, const void** buffer) {
|
|
||||||
*buffer = resource->data;
|
|
||||||
return (int) strlen((const char*) resource->data);
|
|
||||||
};
|
|
||||||
resourceProvider.close = +[](mjResource* resource) {};
|
|
||||||
mjp_registerResourceProvider(&resourceProvider);
|
|
||||||
}
|
}
|
||||||
std::string xml2 = {xml.begin(), xml.end()};
|
|
||||||
std::string str = "LoadModelFromString:" + xml2;
|
// This duplicates the logic in mj_loadXML, but allows us to use a string
|
||||||
return mj_loadXML(str.c_str(), vfs, error, error_size);
|
// directly rather than having to write the contents to a file. Most
|
||||||
|
// importantly, we "save" the spec to global storage so that subsequent calls
|
||||||
|
// to mj_saveLastXML will be done using the parsed mjSpec.
|
||||||
|
mjSpec* spec = mj_parseXMLString(xml.data(), vfs, error, error_size);
|
||||||
|
|
||||||
|
mjModel* model = nullptr;
|
||||||
|
if (spec) {
|
||||||
|
model = mj_compile(spec, vfs);
|
||||||
|
|
||||||
|
if (error && (!model || mjs_isWarning(spec))) {
|
||||||
|
strncpy(error, mjs_getError(spec), error_size);
|
||||||
|
error[error_size - 1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetGlobalXmlSpec(spec);
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AssertModelNotNull(mjModel* model,
|
static void AssertModelNotNull(mjModel* model,
|
||||||
|
|||||||
Reference in New Issue
Block a user