Add elasticity plugins to xml_native_writer_test. Fixes #961.
PiperOrigin-RevId: 545454207 Change-Id: I4e93499eaa53e5bc8c8afa682986657cef3ac20f
This commit is contained in:
committed by
Copybara-Service
parent
2b38148d24
commit
46e06c4cac
@@ -1390,7 +1390,7 @@ void mjXWriter::Body(XMLElement* elem, mjCBody* body) {
|
||||
|
||||
// write plugin
|
||||
if (body->is_plugin) {
|
||||
OnePlugin(elem, body);
|
||||
OnePlugin(InsertEnd(elem, "plugin"), body);
|
||||
}
|
||||
|
||||
// write child bodies recursively
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <absl/strings/string_view.h>
|
||||
#include <mujoco/mjdata.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
|
||||
namespace mujoco {
|
||||
|
||||
@@ -65,5 +66,29 @@ const std::string SaveAndReadXml(const mjModel* model);
|
||||
std::vector<mjtNum> GetCtrlNoise(const mjModel* m, int nsteps,
|
||||
mjtNum ctrlnoise = 0.01);
|
||||
|
||||
// Installs elasticity plugins
|
||||
// TODO(quaglino): load all plugins with a macro
|
||||
class PluginTest : public MujocoTest {
|
||||
public:
|
||||
// load plugin library
|
||||
PluginTest() : MujocoTest() {
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
mj_loadPluginLibrary((
|
||||
std::string(std::getenv("MUJOCO_PLUGIN_DIR")) +
|
||||
std::string("\\elasticity.dll")).c_str());
|
||||
#else
|
||||
#if defined(__APPLE__)
|
||||
mj_loadPluginLibrary((
|
||||
std::string(std::getenv("MUJOCO_PLUGIN_DIR")) +
|
||||
std::string("/libelasticity.dylib")).c_str());
|
||||
#else
|
||||
mj_loadPluginLibrary((
|
||||
std::string(std::getenv("MUJOCO_PLUGIN_DIR")) +
|
||||
std::string("/libelasticity.so")).c_str());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mujoco
|
||||
#endif // MUJOCO_TEST_FIXTURE_H_
|
||||
|
||||
@@ -29,28 +29,6 @@
|
||||
namespace mujoco {
|
||||
namespace {
|
||||
|
||||
class PluginTest : public MujocoTest {
|
||||
public:
|
||||
// load plugin library
|
||||
PluginTest() : MujocoTest() {
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
mj_loadPluginLibrary((
|
||||
std::string(std::getenv("MUJOCO_PLUGIN_DIR")) +
|
||||
std::string("\\elasticity.dll")).c_str());
|
||||
#else
|
||||
#if defined(__APPLE__)
|
||||
mj_loadPluginLibrary((
|
||||
std::string(std::getenv("MUJOCO_PLUGIN_DIR")) +
|
||||
std::string("/libelasticity.dylib")).c_str());
|
||||
#else
|
||||
mj_loadPluginLibrary((
|
||||
std::string(std::getenv("MUJOCO_PLUGIN_DIR")) +
|
||||
std::string("/libelasticity.so")).c_str());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------- solid -----------------------------------
|
||||
TEST_F(PluginTest, ElasticEnergy) {
|
||||
static constexpr char cantilever_xml[] = R"(
|
||||
|
||||
@@ -18,7 +18,12 @@ target_link_libraries(xml_api_test fixture gmock)
|
||||
mujoco_test(xml_native_reader_test)
|
||||
target_link_libraries(xml_native_reader_test fixture gmock)
|
||||
|
||||
mujoco_test(xml_native_writer_test)
|
||||
mujoco_test(
|
||||
xml_native_writer_test
|
||||
PROPERTIES
|
||||
ENVIRONMENT
|
||||
"MUJOCO_PLUGIN_DIR=$<TARGET_FILE_DIR:elasticity>"
|
||||
)
|
||||
target_link_libraries(
|
||||
xml_native_writer_test
|
||||
fixture
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
// Tests for xml/xml_native_writer.cc.
|
||||
|
||||
#include <type_traits>
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@@ -959,17 +960,23 @@ static constexpr int kFieldSize = 500;
|
||||
// The maximum spacing between a normalised floating point number x and an
|
||||
// adjacent normalised number is 2 epsilon |x|; a factor 10 is added accounting
|
||||
// for losses during non-idempotent operations such as vector normalizations.
|
||||
template<typename T = mjtNum> T Compare(T val1, T val2) {
|
||||
T error;
|
||||
template <typename T>
|
||||
auto Compare(T val1, T val2) {
|
||||
using ReturnType =
|
||||
std::conditional_t<std::is_same_v<T, float>, float, double>;
|
||||
ReturnType error;
|
||||
if (mju_abs(val1) <= 1 || mju_abs(val2) <= 1) {
|
||||
// Asbolute precision for small numbers
|
||||
// Absolute precision for small numbers
|
||||
error = mju_abs(val1-val2);
|
||||
} else {
|
||||
// Relative precision for larger numbers
|
||||
T magnitude = mju_max(mju_abs(val1), mju_abs(val2));
|
||||
ReturnType magnitude = mju_abs(val1) + mju_abs(val2);
|
||||
error = mju_abs(val1/magnitude - val2/magnitude) / magnitude;
|
||||
}
|
||||
return error < 2*10*std::numeric_limits<T>::epsilon() ? 0 : error;
|
||||
ReturnType safety_factor = 10;
|
||||
return error < safety_factor * std::numeric_limits<ReturnType>::epsilon()
|
||||
? 0
|
||||
: error;
|
||||
}
|
||||
|
||||
mjtNum CompareModel(const mjModel* m1, const mjModel* m2,
|
||||
@@ -1015,7 +1022,7 @@ mjtNum CompareModel(const mjModel* m1, const mjModel* m2,
|
||||
return maxdif;
|
||||
}
|
||||
|
||||
TEST_F(XMLWriterTest, WriteReadCompare) {
|
||||
TEST_F(PluginTest, WriteReadCompare) {
|
||||
FullFloatPrecision increase_precision;
|
||||
// Loop over all xml files in data
|
||||
std::vector<std::string> paths = {GetTestDataFilePath("."),
|
||||
@@ -1028,7 +1035,7 @@ TEST_F(XMLWriterTest, WriteReadCompare) {
|
||||
|
||||
// if file is meant to fail, skip it
|
||||
if (absl::StrContains(p.path().string(), "malformed_") ||
|
||||
absl::StrContains(p.path().string(), "plugin")) {
|
||||
absl::StrContains(p.path().string(), "touch_grid")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1051,12 +1058,17 @@ TEST_F(XMLWriterTest, WriteReadCompare) {
|
||||
// if failing because assets are missing, accept the test
|
||||
ASSERT_THAT(error.data(), HasSubstr("file")) << error.data();
|
||||
} else {
|
||||
// for a particularly difficult example, relax the tolerance
|
||||
mjtNum tol =
|
||||
absl::StrContains(p.path().string(), "belt.xml") ? 1e-13 : 0;
|
||||
|
||||
// compare and delete
|
||||
char field[kFieldSize] = "";
|
||||
mjtNum result = CompareModel(m, mtemp, field);
|
||||
EXPECT_LE(result, 0) << "Loaded and saved models are different!\n"
|
||||
<< "Affected file " << p.path().string() << '\n'
|
||||
<< "Different field: " << field << '\n';
|
||||
char field[kFieldSize] = "";
|
||||
mjtNum result = CompareModel(m, mtemp, field);
|
||||
EXPECT_LE(result, tol)
|
||||
<< "Loaded and saved models are different!\n"
|
||||
<< "Affected file " << p.path().string() << '\n'
|
||||
<< "Different field: " << field << '\n';
|
||||
mj_deleteModel(mtemp);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user