Refactor mjXUtil::WriteAttr using templates.
PiperOrigin-RevId: 453848941 Change-Id: I1f87f0c20f0c89caab89ea4891aee7583a92534e
This commit is contained in:
committed by
Copybara-Service
parent
066367fcc8
commit
c7c765b6eb
@@ -17,14 +17,14 @@
|
|||||||
namespace mujoco {
|
namespace mujoco {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
thread_local const char* precision = "%g";
|
thread_local int precision = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _mjPRIVATE__get_xml_precision() {
|
int _mjPRIVATE__get_xml_precision() {
|
||||||
return precision;
|
return precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _mjPRIVATE__set_xml_precision(const char* new_precision) {
|
void _mjPRIVATE__set_xml_precision(const int new_precision) {
|
||||||
precision = new_precision;
|
precision = new_precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,15 +20,15 @@
|
|||||||
namespace mujoco {
|
namespace mujoco {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
MJAPI const char* _mjPRIVATE__get_xml_precision();
|
MJAPI int _mjPRIVATE__get_xml_precision();
|
||||||
MJAPI void _mjPRIVATE__set_xml_precision(const char* precision);
|
MJAPI void _mjPRIVATE__set_xml_precision(const int precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Full precision printing of floating point numbers in saved XMLs, useful for testing
|
// Full precision printing of floating point numbers in saved XMLs, useful for testing
|
||||||
class FullFloatPrecision {
|
class FullFloatPrecision {
|
||||||
public:
|
public:
|
||||||
FullFloatPrecision() { _mjPRIVATE__set_xml_precision("%.17g");}
|
FullFloatPrecision() { _mjPRIVATE__set_xml_precision(17);}
|
||||||
~FullFloatPrecision() { _mjPRIVATE__set_xml_precision("%g");}
|
~FullFloatPrecision() { _mjPRIVATE__set_xml_precision(6);}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mujoco
|
} // namespace mujoco
|
||||||
|
|||||||
+45
-159
@@ -19,8 +19,10 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "cc/array_safety.h"
|
#include "cc/array_safety.h"
|
||||||
@@ -483,33 +485,16 @@ XMLElement* mjXSchema::Check(XMLElement* elem, int level) {
|
|||||||
|
|
||||||
//---------------------------------- class mjXUtil implementation ----------------------------------
|
//---------------------------------- class mjXUtil implementation ----------------------------------
|
||||||
|
|
||||||
// compare two vectors: double
|
// compare two vectors
|
||||||
bool mjXUtil::SameVector(const double* vec1, const double* vec2, int n) {
|
template<typename T>
|
||||||
|
bool mjXUtil::SameVector(const T* vec1, const T* vec2, int n) {
|
||||||
if (!vec1 || !vec2) {
|
if (!vec1 || !vec2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool same = true;
|
bool same = true;
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i<n; i++) {
|
||||||
if (fabs(vec1[i] - vec2[i]) > 1E-10) {
|
if (fabs(vec1[i] - vec2[i]) > std::numeric_limits<T>::epsilon()) {
|
||||||
same = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return same;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// compare two vectors: double
|
|
||||||
bool mjXUtil::SameVector(const float* vec1, const float* vec2, int n) {
|
|
||||||
if (!vec1 || !vec2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool same = true;
|
|
||||||
for (int i=0; i<n; i++) {
|
|
||||||
if (fabs(vec1[i] - vec2[i]) > 1E-7) {
|
|
||||||
same = false;
|
same = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -517,6 +502,10 @@ bool mjXUtil::SameVector(const float* vec1, const float* vec2, int n) {
|
|||||||
return same;
|
return same;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template bool mjXUtil::SameVector(const double* vec1, const double* vec2, int n);
|
||||||
|
template bool mjXUtil::SameVector(const float* vec1, const float* vec2, int n);
|
||||||
|
template bool mjXUtil::SameVector(const int* vec1, const int* vec2, int n);
|
||||||
|
template bool mjXUtil::SameVector(const mjtByte* vec1, const mjtByte* vec2, int n);
|
||||||
|
|
||||||
|
|
||||||
// find string in map, return corresponding integer (-1: not found)
|
// find string in map, return corresponding integer (-1: not found)
|
||||||
@@ -808,163 +797,60 @@ static int Round(double x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// write attribute- double
|
// write attribute
|
||||||
void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, double* data,
|
template<typename T>
|
||||||
const double* def) {
|
void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, T* data, const T* def) {
|
||||||
char buf[100];
|
|
||||||
string value;
|
|
||||||
value.clear();
|
|
||||||
|
|
||||||
// make sure all are defined
|
// make sure all are defined
|
||||||
for (int i=0; i<n; i++) {
|
if constexpr (std::is_floating_point_v<T>) {
|
||||||
if (std::isnan(data[i])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip default attributes
|
|
||||||
if (SameVector(data, def, n)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// process all numbers
|
|
||||||
for (int i=0; i<n; i++) {
|
|
||||||
// add space between numbers
|
|
||||||
if (i>0) {
|
|
||||||
value = value + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// write integer or float
|
|
||||||
if (isint(data[i])) {
|
|
||||||
mju::sprintf_arr(buf, "%d", Round(data[i]));
|
|
||||||
} else {
|
|
||||||
mju::sprintf_arr(buf, mujoco::_mjPRIVATE__get_xml_precision(), data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// append number
|
|
||||||
value = value + buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set attribute as string
|
|
||||||
WriteAttrTxt(elem, name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// write attribute- float
|
|
||||||
void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, float* data,
|
|
||||||
const float* def) {
|
|
||||||
char buf[100];
|
|
||||||
string value;
|
|
||||||
value.clear();
|
|
||||||
|
|
||||||
// skip default attributes
|
|
||||||
if (SameVector(data, def, n)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// process all numbers
|
|
||||||
for (int i=0; i<n; i++) {
|
|
||||||
// add space between numbers
|
|
||||||
if (i>0) {
|
|
||||||
value = value + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// write integer or float
|
|
||||||
if (isint(data[i])) {
|
|
||||||
mju::sprintf_arr(buf, "%d", Round(data[i]));
|
|
||||||
} else {
|
|
||||||
mju::sprintf_arr(buf, "%g", data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// append number
|
|
||||||
value = value + buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set attribute as string
|
|
||||||
WriteAttrTxt(elem, name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// write attribute- byte
|
|
||||||
void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, mjtByte* data,
|
|
||||||
const mjtByte* def) {
|
|
||||||
char buf[100];
|
|
||||||
string value;
|
|
||||||
value.clear();
|
|
||||||
|
|
||||||
// skip default attributes
|
|
||||||
if (def) {
|
|
||||||
bool skip = true;
|
|
||||||
for (int i=0; i<n; i++)
|
|
||||||
if (data[i] != def[i]) {
|
|
||||||
skip = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skip) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process all numbers
|
|
||||||
for (int i=0; i<n; i++) {
|
|
||||||
// add space between numbers
|
|
||||||
if (i>0) {
|
|
||||||
value = value + " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// write integer
|
|
||||||
mju::sprintf_arr(buf, "%d", data[i]);
|
|
||||||
|
|
||||||
// append number
|
|
||||||
value = value + buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set attribute as string
|
|
||||||
WriteAttrTxt(elem, name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// write attribute- int
|
|
||||||
void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, int* data,
|
|
||||||
const int* def) {
|
|
||||||
char buf[100];
|
|
||||||
string value;
|
|
||||||
value.clear();
|
|
||||||
|
|
||||||
// skip default attributes
|
|
||||||
if (def) {
|
|
||||||
bool skip = true;
|
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i<n; i++) {
|
||||||
if (data[i] != def[i]) {
|
if (std::isnan(data[i])) {
|
||||||
skip = false;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (skip) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip default attributes
|
||||||
|
if (SameVector(data, def, n)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// increase precision for testing
|
||||||
|
stringstream stream;
|
||||||
|
stream.precision(mujoco::_mjPRIVATE__get_xml_precision());
|
||||||
|
|
||||||
// process all numbers
|
// process all numbers
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i<n; i++) {
|
||||||
// add space between numbers
|
// add space between numbers
|
||||||
if (i>0) {
|
if (i>0) {
|
||||||
value = value + " ";
|
stream << " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
// write integer
|
|
||||||
mju::sprintf_arr(buf, "%d", data[i]);
|
|
||||||
|
|
||||||
// append number
|
// append number
|
||||||
value = value + buf;
|
if (isint(data[i])) {
|
||||||
|
stream << Round(data[i]);
|
||||||
|
} else {
|
||||||
|
stream << data[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set attribute as string
|
// set attribute as string
|
||||||
WriteAttrTxt(elem, name, value);
|
WriteAttrTxt(elem, name, stream.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
||||||
|
double* data, const double* def);
|
||||||
|
|
||||||
|
template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
||||||
|
float* data, const float* def);
|
||||||
|
|
||||||
|
template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
||||||
|
int* data, const int* def);
|
||||||
|
|
||||||
|
template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
||||||
|
mjtByte* data, const mjtByte* def);
|
||||||
|
|
||||||
|
|
||||||
// write vector<double> attribute, default = zero array
|
// write vector<double> attribute, default = zero array
|
||||||
void mjXUtil::WriteVector(XMLElement* elem, string name, vector<double>& vec) {
|
void mjXUtil::WriteVector(XMLElement* elem, string name, vector<double>& vec) {
|
||||||
// proceed only if non-zero found
|
// proceed only if non-zero found
|
||||||
|
|||||||
+6
-17
@@ -89,8 +89,8 @@ class mjXUtil {
|
|||||||
virtual ~mjXUtil() = default;
|
virtual ~mjXUtil() = default;
|
||||||
|
|
||||||
// compare two vectors
|
// compare two vectors
|
||||||
static bool SameVector(const double* vec1, const double* vec2, int n);
|
template<typename T>
|
||||||
static bool SameVector(const float* vec1, const float* vec2, int n);
|
static bool SameVector(const T* vec1, const T* vec2, int n);
|
||||||
|
|
||||||
// find key in map, return value (-1: not found)
|
// find key in map, return value (-1: not found)
|
||||||
static int FindKey(const mjMap* map, int mapsz, std::string key);
|
static int FindKey(const mjMap* map, int mapsz, std::string key);
|
||||||
@@ -136,21 +136,10 @@ class mjXUtil {
|
|||||||
static bool MapValue(tinyxml2::XMLElement* elem, const char* attr, int* data,
|
static bool MapValue(tinyxml2::XMLElement* elem, const char* attr, int* data,
|
||||||
const mjMap* map, int mapSz, bool required = false);
|
const mjMap* map, int mapSz, bool required = false);
|
||||||
|
|
||||||
// write attribute- double
|
// write attribute- any type
|
||||||
static void WriteAttr(tinyxml2::XMLElement* elem, std::string name, int n, double* data,
|
template<typename T>
|
||||||
const double* def = 0);
|
static void WriteAttr(tinyxml2::XMLElement* elem, std::string name, int n, T* data,
|
||||||
|
const T* def = 0);
|
||||||
// write attribute- float
|
|
||||||
static void WriteAttr(tinyxml2::XMLElement* elem, std::string name, int n, float* data,
|
|
||||||
const float* def = 0);
|
|
||||||
|
|
||||||
// write attribute- byte
|
|
||||||
static void WriteAttr(tinyxml2::XMLElement* elem, std::string name, int n, mjtByte* data,
|
|
||||||
const mjtByte* def = 0);
|
|
||||||
|
|
||||||
// write attribute- int
|
|
||||||
static void WriteAttr(tinyxml2::XMLElement* elem, std::string name, int n, int* data,
|
|
||||||
const int* def = 0);
|
|
||||||
|
|
||||||
// write vector<double> attribute, with and without default
|
// write vector<double> attribute, with and without default
|
||||||
static void WriteVector(tinyxml2::XMLElement* elem, std::string name, std::vector<double>& vec);
|
static void WriteVector(tinyxml2::XMLElement* elem, std::string name, std::vector<double>& vec);
|
||||||
|
|||||||
Reference in New Issue
Block a user