Refactor numerical parsing in XML.
PiperOrigin-RevId: 653979240 Change-Id: I4d39f4041b88396193eb35f0cc393141d64f6fc0
This commit is contained in:
committed by
Copybara-Service
parent
e92af73cbf
commit
8a8a44a4db
@@ -27,7 +27,12 @@
|
||||
#include "user/user_model.h"
|
||||
#include "user/user_objects.h"
|
||||
#include "user/user_cache.h"
|
||||
#include "xml/xml_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using mujoco::user::StringToVector;
|
||||
|
||||
} // namespace
|
||||
|
||||
// global cache size in bytes (default 500MB)
|
||||
static constexpr std::size_t kGlobalCacheSize = 500 * (1 << 20);
|
||||
@@ -892,7 +897,7 @@ mjtByte mjs_setInStringVec(mjStringVec* dest, int i, const char* text) {
|
||||
// split text and copy into string array
|
||||
void mjs_setStringVec(mjStringVec* dest, const char* text) {
|
||||
std::vector<std::string>* v = static_cast<std::vector<std::string>*>(dest);
|
||||
*v = mjXUtil::String2Vector<std::string>(text);
|
||||
*v = StringToVector<std::string>(text);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+20
-20
@@ -36,12 +36,11 @@
|
||||
#include "user/user_model.h"
|
||||
#include "user/user_objects.h"
|
||||
#include "user/user_util.h"
|
||||
#include "xml/xml_util.h"
|
||||
|
||||
namespace {
|
||||
namespace mju = ::mujoco::util;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using mujoco::user::VectorToString;
|
||||
using mujoco::user::StringToVector;
|
||||
} // namespace
|
||||
|
||||
// strncpy with 0, return false
|
||||
@@ -418,12 +417,12 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjsBody* body, char* error, int
|
||||
}
|
||||
}
|
||||
}
|
||||
mjXUtil::Vector2String(userface, face);
|
||||
userface = VectorToString(face);
|
||||
} else {
|
||||
dim = 2; // can only load a surface for now
|
||||
face = mjXUtil::String2Vector<int>(userface);
|
||||
face = StringToVector<int>(userface);
|
||||
for (int i=0; i<face.size(); face[i++]--) {};
|
||||
mjXUtil::Vector2String(userface, face);
|
||||
userface = VectorToString(face);
|
||||
}
|
||||
|
||||
// compute volume
|
||||
@@ -438,7 +437,7 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjsBody* body, char* error, int
|
||||
}
|
||||
}
|
||||
if (!userface.empty()) {
|
||||
face = mjXUtil::String2Vector<int>(userface);
|
||||
face = StringToVector<int>(userface);
|
||||
for (int j=0; j<face.size()/3; j++) {
|
||||
double area[3];
|
||||
double edge1[3];
|
||||
@@ -1307,7 +1306,7 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
|
||||
// copy skin from existing mesh
|
||||
if (type==mjCOMPTYPE_PARTICLE && username.empty()) {
|
||||
std::vector<int> skinface;
|
||||
skinface = mjXUtil::String2Vector<int>(userface);
|
||||
skinface = StringToVector<int>(userface);
|
||||
int nvert = uservert.size()/3;
|
||||
|
||||
for (int j=0; j<2; j++) {
|
||||
@@ -2034,9 +2033,9 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
|
||||
// add skin to 3D
|
||||
void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
int vcnt = 0;
|
||||
std::map<string, int> vmap;
|
||||
std::map<std::string, int> vmap;
|
||||
char txt[100], cnt0[10], cnt1[10], cnt2[10];
|
||||
string fmt;
|
||||
std::string fmt;
|
||||
|
||||
// string counts
|
||||
mju::sprintf_arr(cnt0, "%d", count[0]-1);
|
||||
@@ -2056,17 +2055,17 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
if (type==mjCOMPTYPE_BOX || type==mjCOMPTYPE_PARTICLE) {
|
||||
// z-faces
|
||||
MakeSkin3Box(skin, count[0], count[1], 1, vcnt, "%sB%d_%d_0");
|
||||
fmt = "%sB%d_%d_" + string(cnt2);
|
||||
fmt = "%sB%d_%d_" + std::string(cnt2);
|
||||
MakeSkin3Box(skin, count[0], count[1], 0, vcnt, fmt.c_str());
|
||||
|
||||
// y-faces
|
||||
MakeSkin3Box(skin, count[0], count[2], 0, vcnt, "%sB%d_0_%d");
|
||||
fmt = "%sB%d_" + string(cnt1) + "_%d";
|
||||
fmt = "%sB%d_" + std::string(cnt1) + "_%d";
|
||||
MakeSkin3Box(skin, count[0], count[2], 1, vcnt, fmt.c_str());
|
||||
|
||||
// x-faces
|
||||
MakeSkin3Box(skin, count[1], count[2], 1, vcnt, "%sB0_%d_%d");
|
||||
fmt = "%sB" + string(cnt0) + "_%d_%d";
|
||||
fmt = "%sB" + std::string(cnt0) + "_%d_%d";
|
||||
MakeSkin3Box(skin, count[1], count[2], 0, vcnt, fmt.c_str());
|
||||
}
|
||||
|
||||
@@ -2112,17 +2111,17 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
|
||||
// y-faces
|
||||
MakeSkin3Smooth(skin, count[0], count[2], 0, vmap, "%sB%d_0_%d");
|
||||
fmt = "%sB%d_" + string(cnt1) + "_%d";
|
||||
fmt = "%sB%d_" + std::string(cnt1) + "_%d";
|
||||
MakeSkin3Smooth(skin, count[0], count[2], 1, vmap, fmt.c_str());
|
||||
|
||||
// x-faces
|
||||
MakeSkin3Smooth(skin, count[1], count[2], 1, vmap, "%sB0_%d_%d");
|
||||
fmt = "%sB" + string(cnt0) + "_%d_%d";
|
||||
fmt = "%sB" + std::string(cnt0) + "_%d_%d";
|
||||
MakeSkin3Smooth(skin, count[1], count[2], 0, vmap, fmt.c_str());
|
||||
|
||||
// z-faces, boxy-type
|
||||
MakeSkin3Box(skin, count[0], count[1], 1, vcnt, "%sB%d_%d_0");
|
||||
fmt = "%sB%d_%d_" + string(cnt2);
|
||||
fmt = "%sB%d_%d_" + std::string(cnt2);
|
||||
MakeSkin3Box(skin, count[0], count[1], 0, vcnt, fmt.c_str());
|
||||
}
|
||||
|
||||
@@ -2172,17 +2171,17 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
||||
|
||||
// z-faces
|
||||
MakeSkin3Smooth(skin, count[0], count[1], 1, vmap, "%sB%d_%d_0");
|
||||
fmt = "%sB%d_%d_" + string(cnt2);
|
||||
fmt = "%sB%d_%d_" + std::string(cnt2);
|
||||
MakeSkin3Smooth(skin, count[0], count[1], 0, vmap, fmt.c_str());
|
||||
|
||||
// y-faces
|
||||
MakeSkin3Smooth(skin, count[0], count[2], 0, vmap, "%sB%d_0_%d");
|
||||
fmt = "%sB%d_" + string(cnt1) + "_%d";
|
||||
fmt = "%sB%d_" + std::string(cnt1) + "_%d";
|
||||
MakeSkin3Smooth(skin, count[0], count[2], 1, vmap, fmt.c_str());
|
||||
|
||||
// x-faces
|
||||
MakeSkin3Smooth(skin, count[1], count[2], 1, vmap, "%sB0_%d_%d");
|
||||
fmt = "%sB" + string(cnt0) + "_%d_%d";
|
||||
fmt = "%sB" + std::string(cnt0) + "_%d_%d";
|
||||
MakeSkin3Smooth(skin, count[1], count[2], 0, vmap, fmt.c_str());
|
||||
}
|
||||
|
||||
@@ -2248,7 +2247,8 @@ void mjCComposite::MakeSkin3Box(mjsSkin* skin, int c0, int c1, int side,
|
||||
|
||||
// make one face of 3D skin, smooth
|
||||
void mjCComposite::MakeSkin3Smooth(mjsSkin* skin, int c0, int c1, int side,
|
||||
const std::map<string, int>& vmap, const char* format) {
|
||||
const std::map<std::string, int>& vmap,
|
||||
const char* format) {
|
||||
char txt00[100], txt01[100], txt10[100], txt11[100];
|
||||
|
||||
// loop over bodies/vertices of specified face
|
||||
|
||||
@@ -62,13 +62,16 @@
|
||||
#include "user/user_objects.h"
|
||||
#include "user/user_resource.h"
|
||||
#include "user/user_util.h"
|
||||
#include "xml/xml_util.h"
|
||||
#include <tiny_obj_loader.h>
|
||||
|
||||
extern "C" {
|
||||
#include "qhull_ra.h"
|
||||
}
|
||||
|
||||
namespace {
|
||||
using mujoco::user::VectorToString;
|
||||
} // namespace
|
||||
|
||||
// compute triangle area, surface normal, center
|
||||
static double _triangle(double* normal, double* center,
|
||||
const float* v1, const float* v2, const float* v3) {
|
||||
@@ -2627,8 +2630,8 @@ void mjCFlex::Compile(const mjVFS* vfs) {
|
||||
|
||||
// add plugins
|
||||
std::string userface, useredge;
|
||||
mjXUtil::Vector2String(userface, elem_);
|
||||
mjXUtil::Vector2String(useredge, edgeidx);
|
||||
userface = VectorToString(elem_);
|
||||
useredge = VectorToString(edgeidx);
|
||||
|
||||
for (const auto& vbodyid : vertbodyid) {
|
||||
if (model->Bodies()[vbodyid]->plugin.instance) {
|
||||
|
||||
+117
-1
@@ -16,11 +16,13 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
@@ -32,6 +34,16 @@
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "engine/engine_crossplatform.h"
|
||||
|
||||
|
||||
// workaround with locale bug on some MacOS machines
|
||||
#if defined (__APPLE__) && defined (__MACH__)
|
||||
#include <xlocale.h>
|
||||
#include <locale.h>
|
||||
|
||||
#define strtof(X, Y) strtof_l((X), (Y), _c_locale)
|
||||
#define strtod(X, Y) strtod_l((X), (Y), _c_locale)
|
||||
#endif
|
||||
|
||||
// check if numeric variable is defined
|
||||
bool mjuu_defined(double num) {
|
||||
return !std::isnan(num);
|
||||
@@ -1137,5 +1149,109 @@ std::vector<uint8_t> FileToMemory(const char* filename) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace mujoco::user
|
||||
// convert vector to string separating elements by whitespace
|
||||
template<typename T> std::string VectorToString(const std::vector<T>& v) {
|
||||
std::stringstream ss;
|
||||
|
||||
for (const T& t : v) {
|
||||
ss << t << " ";
|
||||
}
|
||||
|
||||
std::string s = ss.str();
|
||||
if (!s.empty()) s.pop_back(); // remove trailing space
|
||||
return s;
|
||||
}
|
||||
|
||||
template std::string VectorToString(const std::vector<int>& v);
|
||||
template std::string VectorToString(const std::vector<float>& v);
|
||||
template std::string VectorToString(const std::vector<double>& v);
|
||||
template std::string VectorToString(const std::vector<std::string>& v);
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename T> T StrToNum(char* str, char** c);
|
||||
|
||||
template<> int StrToNum(char* str, char** c) {
|
||||
long n = std::strtol(str, c, 10);
|
||||
if (n < INT_MIN || n > INT_MAX) errno = ERANGE;
|
||||
return n;
|
||||
}
|
||||
|
||||
template<> float StrToNum(char* str, char** c) {
|
||||
float f = strtof(str, c);
|
||||
if (std::isnan(f)) errno = EDOM;
|
||||
return f;
|
||||
}
|
||||
|
||||
template<> double StrToNum(char* str, char** c) {
|
||||
double d = strtod(str, c);
|
||||
if (std::isnan(d)) errno = EDOM;
|
||||
return d;
|
||||
}
|
||||
|
||||
template<> unsigned char StrToNum(char* str, char** c) {
|
||||
long n = std::strtol(str, c, 10);
|
||||
if (n < 0 || n > UCHAR_MAX) errno = ERANGE;
|
||||
return n;
|
||||
}
|
||||
|
||||
inline bool IsNullOrSpace(char* c) {
|
||||
return std::isspace(static_cast<unsigned char>(*c)) || *c == '\0';
|
||||
}
|
||||
|
||||
inline char* SkipSpace(char* c) {
|
||||
for (; *c != '\0'; c++) {
|
||||
if (!IsNullOrSpace(c)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename T> std::vector<T> StringToVector(char* cs) {
|
||||
std::vector<T> v;
|
||||
char* ch = cs;
|
||||
|
||||
errno = 0;
|
||||
// reserve worst case
|
||||
v.reserve((std::strlen(cs) >> 1) + 1);
|
||||
|
||||
for (;;) {
|
||||
cs = SkipSpace(ch); // skip leading spaces
|
||||
if (*cs == '\0') break; // end of string
|
||||
T num = StrToNum<T>(cs, &ch); // parse number
|
||||
if (!IsNullOrSpace(ch)) errno = EINVAL; // invalid separator
|
||||
if (cs == ch) errno = EINVAL; // failed to parse number
|
||||
if (errno && errno != EDOM) break; // NaNs are quietly ignored
|
||||
v.push_back(num);
|
||||
}
|
||||
|
||||
v.shrink_to_fit();
|
||||
return v;
|
||||
}
|
||||
|
||||
template<> std::vector<std::string> StringToVector(const std::string& s) {
|
||||
std::vector<std::string> v;
|
||||
std::stringstream ss(s);
|
||||
std::string word;
|
||||
while (ss >> word) {
|
||||
v.push_back(word);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template std::vector<int> StringToVector(char* cs);
|
||||
template std::vector<float> StringToVector(char* cs);
|
||||
template std::vector<double> StringToVector(char* cs);
|
||||
|
||||
|
||||
template <typename T> std::vector<T> StringToVector(const std::string& s) {
|
||||
return StringToVector<T>(const_cast<char*>(s.c_str()));
|
||||
}
|
||||
template std::vector<int> StringToVector(const std::string& s);
|
||||
template std::vector<float> StringToVector(const std::string& s);
|
||||
template std::vector<double> StringToVector(const std::string& s);
|
||||
template std::vector<unsigned char> StringToVector(const std::string& s);
|
||||
|
||||
} // namespace mujoco::user
|
||||
|
||||
@@ -235,6 +235,13 @@ class FilePath {
|
||||
// read file into memory buffer
|
||||
std::vector<uint8_t> FileToMemory(const char* filename);
|
||||
|
||||
// convert vector to string separating elements by whitespace
|
||||
template<typename T> std::string VectorToString(const std::vector<T>& v);
|
||||
|
||||
// convert string to vector
|
||||
template<typename T> std::vector<T> StringToVector(char *cs);
|
||||
template<typename T> std::vector<T> StringToVector(const std::string& s);
|
||||
|
||||
} // namespace mujoco::user
|
||||
|
||||
// strip path from filename
|
||||
|
||||
Reference in New Issue
Block a user