Add compiler C API for mjmSite.
PiperOrigin-RevId: 604573450 Change-Id: I6ba7fcece0942ddc0d109413ba5684b2df3fab96
This commit is contained in:
committed by
Copybara-Service
parent
f763254a00
commit
3b2dd06c54
@@ -13,6 +13,8 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
set(MUJOCO_USER_SRCS
|
set(MUJOCO_USER_SRCS
|
||||||
|
user_api.cc
|
||||||
|
user_api.h
|
||||||
user_composite.cc
|
user_composite.cc
|
||||||
user_composite.h
|
user_composite.h
|
||||||
user_flexcomp.cc
|
user_flexcomp.cc
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2021 DeepMind Technologies Limited
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "user/user_api.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <mujoco/mujoco.h>
|
||||||
|
#include "user/user_model.h"
|
||||||
|
#include "user/user_objects.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// create model
|
||||||
|
void* mjm_createModel() {
|
||||||
|
mjCModel* modelC = new mjCModel();
|
||||||
|
return modelC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// delete model
|
||||||
|
void mjm_deleteModel(void* model) {
|
||||||
|
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||||
|
delete modelC;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// add body to body
|
||||||
|
void* mjm_addBody(void* body, void* def) {
|
||||||
|
mjCDef* defC = static_cast<mjCDef*>(def);
|
||||||
|
mjCBody* bodyC = static_cast<mjCBody*>(body);
|
||||||
|
return bodyC->AddBody(defC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// add site to body
|
||||||
|
mjmSite* mjm_addSite(void* body, void* def) {
|
||||||
|
mjCDef* defC = static_cast<mjCDef*>(def);
|
||||||
|
mjCSite* siteC = static_cast<mjCBody*>(body)->AddSite(defC);
|
||||||
|
return &siteC->spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// get object of given type
|
||||||
|
void* mjm_findObject(void* model, mjtObj type, const char* name) {
|
||||||
|
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||||
|
return modelC->FindObject(type, std::string(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// set parent frame of dest
|
||||||
|
void mjm_setFrame(void* dest, void* frame) {
|
||||||
|
mjCFrame* frameC = static_cast<mjCFrame*>(frame);
|
||||||
|
mjCBase* baseC = static_cast<mjCBase*>(dest);
|
||||||
|
baseC->SetFrame(frameC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// set string
|
||||||
|
void mjm_setString(mjString dest, const char* text) {
|
||||||
|
std::string* str = reinterpret_cast<std::string*>(dest);
|
||||||
|
*str = std::string(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// set double array
|
||||||
|
void mjm_setDouble(mjDouble dest, const double* array, int size) {
|
||||||
|
std::vector<double>* v = reinterpret_cast<std::vector<double>*>(dest);
|
||||||
|
v->assign(size, 0.0);
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
(*v)[i] = array[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// get string
|
||||||
|
const char* mjm_getString(const mjString source) {
|
||||||
|
std::string* str = reinterpret_cast<std::string*>(source);
|
||||||
|
return str->c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// get double array
|
||||||
|
const double* mjm_getDouble(const mjDouble source, int* size) {
|
||||||
|
std::vector<double>* v = reinterpret_cast<std::vector<double>*>(source);
|
||||||
|
if (size) {
|
||||||
|
*size = v->size();
|
||||||
|
}
|
||||||
|
return v->data();
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
// Copyright 2021 DeepMind Technologies Limited
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef MUJOCO_SRC_USER_USER_API_H_
|
||||||
|
#define MUJOCO_SRC_USER_USER_API_H_
|
||||||
|
|
||||||
|
#include <mujoco/mjexport.h>
|
||||||
|
#include <mujoco/mjmodel.h>
|
||||||
|
|
||||||
|
typedef struct _mjString* mjString;
|
||||||
|
typedef struct _mjDouble* mjDouble;
|
||||||
|
typedef struct _mjElement* mjElement;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------- Public structs ------------------------------------------------
|
||||||
|
typedef struct _mjmOrientation {
|
||||||
|
double axisangle[4]; // rotation axis and angle
|
||||||
|
double xyaxes[6]; // x and y axes
|
||||||
|
double zaxis[3]; // z axis (use minimal rotation)
|
||||||
|
double euler[3]; // euler rotations
|
||||||
|
double fullinertia[6]; // non-axis-aligned inertia matrix
|
||||||
|
} mjmOrientation;
|
||||||
|
|
||||||
|
typedef struct _mjmSite {
|
||||||
|
mjElement element; // only used internally, do not modify
|
||||||
|
mjString name; // name
|
||||||
|
mjString classname; // class name
|
||||||
|
mjString info; // message appended to errors
|
||||||
|
mjtGeom type; // geom type for rendering
|
||||||
|
int group; // group id, used for visualization
|
||||||
|
double size[3]; // geom size for rendering
|
||||||
|
double pos[3]; // position
|
||||||
|
double quat[4]; // orientation
|
||||||
|
mjString material; // name of material for rendering
|
||||||
|
mjDouble userdata; // user data
|
||||||
|
float rgba[4]; // rgba when material is omitted
|
||||||
|
double fromto[6]; // alternative for capsule, cylinder, box, ellipsoid
|
||||||
|
mjmOrientation alt; // alternative orientation specification
|
||||||
|
} mjmSite;
|
||||||
|
|
||||||
|
//---------------------------------- Public API ----------------------------------------------------
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Create model.
|
||||||
|
MJAPI void* mjm_createModel();
|
||||||
|
|
||||||
|
// Delete model.
|
||||||
|
MJAPI void mjm_deleteModel(void* model);
|
||||||
|
|
||||||
|
// Add body to body.
|
||||||
|
MJAPI void* mjm_addBody(void* body, void* def);
|
||||||
|
|
||||||
|
// Add site to body.
|
||||||
|
MJAPI mjmSite* mjm_addSite(void* body, void* def);
|
||||||
|
|
||||||
|
// Find object of given type.
|
||||||
|
MJAPI void* mjm_findObject(void* model, mjtObj type, const char* name);
|
||||||
|
|
||||||
|
// Copy input text to destination string.
|
||||||
|
MJAPI void mjm_setString(mjString dest, const char* text);
|
||||||
|
|
||||||
|
// Copy input array to destination vector.
|
||||||
|
MJAPI void mjm_setDouble(mjDouble dest, const double* array, int size);
|
||||||
|
|
||||||
|
// Get const pointer to mjString data.
|
||||||
|
MJAPI const char* mjm_getString(mjString source);
|
||||||
|
|
||||||
|
// Get const pointer to mjDouble data and its size.
|
||||||
|
MJAPI const double* mjm_getDouble(mjDouble source, int* size);
|
||||||
|
|
||||||
|
// Set frame.
|
||||||
|
MJAPI void mjm_setFrame(void* dest, void* frame);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // MUJOCO_SRC_USER_USER_API_H_
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
#include "engine/engine_util_solve.h"
|
#include "engine/engine_util_solve.h"
|
||||||
#include "engine/engine_util_spatial.h"
|
#include "engine/engine_util_spatial.h"
|
||||||
#include "engine/engine_vfs.h"
|
#include "engine/engine_vfs.h"
|
||||||
|
#include "user/user_api.h"
|
||||||
#include "user/user_model.h"
|
#include "user/user_model.h"
|
||||||
#include "user/user_util.h"
|
#include "user/user_util.h"
|
||||||
|
|
||||||
@@ -1931,25 +1932,35 @@ mjCSite::mjCSite(mjCModel* _model, mjCDef* _def) {
|
|||||||
spec.group = 0;
|
spec.group = 0;
|
||||||
mjuu_setvec(spec.quat, 1, 0, 0, 0);
|
mjuu_setvec(spec.quat, 1, 0, 0, 0);
|
||||||
mjuu_setvec(spec.pos, 0, 0, 0);
|
mjuu_setvec(spec.pos, 0, 0, 0);
|
||||||
spec.material = nullptr;
|
spec_material_.clear();
|
||||||
spec.rgba[0] = spec.rgba[1] = spec.rgba[2] = 0.5f;
|
spec.rgba[0] = spec.rgba[1] = spec.rgba[2] = 0.5f;
|
||||||
spec.rgba[3] = 1.0f;
|
spec.rgba[3] = 1.0f;
|
||||||
spec.fromto[0] = mjNAN;
|
spec.fromto[0] = mjNAN;
|
||||||
spec.userdata = nullptr;
|
spec_userdata_.clear();
|
||||||
|
spec.alt.axisangle[0] = spec.alt.xyaxes[0] = spec.alt.zaxis[0] =
|
||||||
|
spec.alt.euler[0] = spec.alt.fullinertia[0] = mjNAN;
|
||||||
|
|
||||||
// clear internal variables
|
// clear internal variables
|
||||||
body = 0;
|
body = 0;
|
||||||
matid = -1;
|
matid = -1;
|
||||||
|
|
||||||
// initialize private attributes
|
|
||||||
CopyFromSpec();
|
|
||||||
|
|
||||||
// reset to default if given
|
// reset to default if given
|
||||||
if (_def) {
|
if (_def) {
|
||||||
_def->site.CopyFromSpec();
|
_def->site.CopyFromSpec();
|
||||||
*this = _def->site;
|
*this = _def->site;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// point to local, not to default
|
||||||
|
spec.element = (mjElement)this;
|
||||||
|
spec.name = (mjString)&name;
|
||||||
|
spec.info = (mjString)&info;
|
||||||
|
spec.classname = (mjString)&classname;
|
||||||
|
spec.material = (mjString)&spec_material_;
|
||||||
|
spec.userdata = (mjDouble)&spec_userdata_;
|
||||||
|
|
||||||
|
// initialize private attributes in case object won't be compiled
|
||||||
|
CopyFromSpec();
|
||||||
|
|
||||||
// set model, def
|
// set model, def
|
||||||
model = _model;
|
model = _model;
|
||||||
def = (_def ? _def : (_model ? _model->defaults[0] : 0));
|
def = (_def ? _def : (_model ? _model->defaults[0] : 0));
|
||||||
@@ -1961,8 +1972,13 @@ void mjCSite::CopyFromSpec() {
|
|||||||
*static_cast<mjmSite*>(this) = spec;
|
*static_cast<mjmSite*>(this) = spec;
|
||||||
userdata_ = spec_userdata_;
|
userdata_ = spec_userdata_;
|
||||||
material_ = spec_material_;
|
material_ = spec_material_;
|
||||||
userdata = userdata_.data();
|
userdata = (mjDouble)&userdata_;
|
||||||
material = material_.data();
|
material = (mjString)&material_;
|
||||||
|
mju_copy4(alt_.axisangle, alt.axisangle);
|
||||||
|
mju_copy(alt_.xyaxes, alt.xyaxes, 6);
|
||||||
|
mju_copy3(alt_.zaxis, alt.zaxis);
|
||||||
|
mju_copy3(alt_.euler, alt.euler);
|
||||||
|
mju_copy(alt_.fullinertia, alt.fullinertia, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2034,7 +2050,7 @@ void mjCSite::Compile(void) {
|
|||||||
|
|
||||||
// alternative orientation
|
// alternative orientation
|
||||||
else {
|
else {
|
||||||
const char* err = alt.Set(quat, 0, model->degree, model->euler);
|
const char* err = alt_.Set(quat, 0, model->degree, model->euler);
|
||||||
if (err) {
|
if (err) {
|
||||||
throw mjCError(this, "orientation specification error '%s' in site %d", err, id);
|
throw mjCError(this, "orientation specification error '%s' in site %d", err, id);
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-34
@@ -24,11 +24,10 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "lodepng.h"
|
|
||||||
|
|
||||||
#include <mujoco/mjtnum.h>
|
#include <mujoco/mjtnum.h>
|
||||||
#include <mujoco/mjmodel.h>
|
#include <mujoco/mjmodel.h>
|
||||||
#include <mujoco/mjplugin.h>
|
#include <mujoco/mjplugin.h>
|
||||||
|
#include "user/user_api.h"
|
||||||
|
|
||||||
// forward declarations of all mjC/X classes
|
// forward declarations of all mjC/X classes
|
||||||
class mjCError;
|
class mjCError;
|
||||||
@@ -109,18 +108,12 @@ class [[nodiscard]] mjCError {
|
|||||||
|
|
||||||
|
|
||||||
// alternative specifications of frame orientation
|
// alternative specifications of frame orientation
|
||||||
class mjCAlternative {
|
class mjCAlternative : public mjmOrientation {
|
||||||
public:
|
public:
|
||||||
mjCAlternative(); // constuctor
|
mjCAlternative(); // constuctor
|
||||||
const char* Set(double* quat, double* inertia, // set frame quat and diag. inertia
|
const char* Set(double* quat, double* inertia, // set frame quat and diag. inertia
|
||||||
bool degree, // angle format: degree/radian
|
bool degree, // angle format: degree/radian
|
||||||
const char* sequence); // euler sequence format: "xyz"
|
const char* sequence); // euler sequence format: "xyz"
|
||||||
|
|
||||||
double axisangle[4]; // rotation axis and angle
|
|
||||||
double xyaxes[6]; // x and y axes
|
|
||||||
double zaxis[3]; // z axis (use minimal rotation)
|
|
||||||
double euler[3]; // euler rotations
|
|
||||||
double fullinertia[6]; // non-axis-aligned inertia matrix
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -458,19 +451,6 @@ class mjCGeom : public mjCBase {
|
|||||||
//------------------------- class mjCSite ----------------------------------------------------------
|
//------------------------- class mjCSite ----------------------------------------------------------
|
||||||
// Describes a site on a body
|
// Describes a site on a body
|
||||||
|
|
||||||
typedef struct _mjmSite {
|
|
||||||
mjtGeom type; // geom type for rendering
|
|
||||||
int group; // group id, used for visualization
|
|
||||||
double size[3]; // geom size for rendering
|
|
||||||
double pos[3]; // position
|
|
||||||
double quat[4]; // orientation
|
|
||||||
char* material; // name of material for rendering
|
|
||||||
double* userdata; // user data
|
|
||||||
float rgba[4]; // rgba when material is omitted
|
|
||||||
double fromto[6]; // alternative for capsule, cylinder, box, ellipsoid
|
|
||||||
mjCAlternative alt; // alternative orientation specification
|
|
||||||
} mjmSite;
|
|
||||||
|
|
||||||
class mjCSite : public mjCBase, private mjmSite {
|
class mjCSite : public mjCBase, private mjmSite {
|
||||||
friend class mjCDef;
|
friend class mjCDef;
|
||||||
friend class mjCBody;
|
friend class mjCBody;
|
||||||
@@ -481,30 +461,30 @@ class mjCSite : public mjCBase, private mjmSite {
|
|||||||
public:
|
public:
|
||||||
mjmSite spec; // variables set by user
|
mjmSite spec; // variables set by user
|
||||||
|
|
||||||
void set_material(std::string _material) {
|
// use strings from mjCBase rather than mjStrings from mjmSite
|
||||||
spec_material_ = _material;
|
using mjCBase::name;
|
||||||
spec.material = spec_material_.data();
|
using mjCBase::classname;
|
||||||
}
|
using mjCBase::info;
|
||||||
void set_userdata(std::vector<double> _userdata) {
|
|
||||||
spec_userdata_ = _userdata;
|
// used by mjXWriter and mjCModel
|
||||||
spec.userdata = spec_userdata_.data();
|
const std::vector<double>& get_userdata() { return userdata_; }
|
||||||
}
|
const std::string& get_material() { return material_; }
|
||||||
std::vector<double>& get_userdata() { return userdata_; }
|
|
||||||
std::string& get_material() { return material_; }
|
|
||||||
|
|
||||||
// variables computed by 'compile' and 'mjCBody::addSite'
|
|
||||||
private:
|
private:
|
||||||
mjCSite(mjCModel* = 0, mjCDef* = 0); // constructor
|
mjCSite(mjCModel* = 0, mjCDef* = 0); // constructor
|
||||||
void Compile(void); // compiler
|
void Compile(void); // compiler
|
||||||
void CopyFromSpec(); // copy spec into attributes
|
void CopyFromSpec(); // copy spec into attributes
|
||||||
|
|
||||||
|
mjCAlternative alt_;
|
||||||
|
mjCAlternative spec_alt_;
|
||||||
|
|
||||||
// variable-size data
|
// variable-size data
|
||||||
std::string material_;
|
std::string material_;
|
||||||
std::vector<double> userdata_;
|
std::vector<double> userdata_;
|
||||||
|
|
||||||
std::string spec_material_;
|
std::string spec_material_;
|
||||||
std::vector<double> spec_userdata_;
|
std::vector<double> spec_userdata_;
|
||||||
|
|
||||||
|
// variables computed by 'compile' and 'mjCBody::addSite'
|
||||||
mjCBody* body; // site's body
|
mjCBody* body; // site's body
|
||||||
int matid; // material id for rendering
|
int matid; // material id for rendering
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-1
@@ -21,6 +21,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "user/user_api.h"
|
||||||
#include "user/user_model.h"
|
#include "user/user_model.h"
|
||||||
#include "user/user_objects.h"
|
#include "user/user_objects.h"
|
||||||
#include "tinyxml2.h"
|
#include "tinyxml2.h"
|
||||||
@@ -50,7 +51,7 @@ void mjXBase::SetModel(mjCModel* _model) {
|
|||||||
|
|
||||||
|
|
||||||
// read alternative orientation specification
|
// read alternative orientation specification
|
||||||
void mjXBase::ReadAlternative(XMLElement* elem, mjCAlternative& alt) {
|
void mjXBase::ReadAlternative(XMLElement* elem, mjmOrientation& alt) {
|
||||||
string text;
|
string text;
|
||||||
int read = (int)(elem->Attribute("quat") != 0) +
|
int read = (int)(elem->Attribute("quat") != 0) +
|
||||||
(ReadAttr(elem, "axisangle", 4, alt.axisangle, text) ? 1 : 0) +
|
(ReadAttr(elem, "axisangle", 4, alt.axisangle, text) ? 1 : 0) +
|
||||||
|
|||||||
+1
-1
@@ -92,7 +92,7 @@ class mjXBase : public mjXUtil {
|
|||||||
void SetModel(mjCModel*);
|
void SetModel(mjCModel*);
|
||||||
|
|
||||||
// read alternative orientation specification
|
// read alternative orientation specification
|
||||||
static void ReadAlternative(tinyxml2::XMLElement* elem, mjCAlternative& alt);
|
static void ReadAlternative(tinyxml2::XMLElement* elem, mjmOrientation& alt);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mjCModel* model; // internally-allocated mjCModel object
|
mjCModel* model; // internally-allocated mjCModel object
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "engine/engine_plugin.h"
|
#include "engine/engine_plugin.h"
|
||||||
#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 "user/user_api.h"
|
||||||
#include "user/user_composite.h"
|
#include "user/user_composite.h"
|
||||||
#include "user/user_flexcomp.h"
|
#include "user/user_flexcomp.h"
|
||||||
#include "user/user_model.h"
|
#include "user/user_model.h"
|
||||||
@@ -1563,34 +1564,39 @@ void mjXReader::OneGeom(XMLElement* elem, mjCGeom* pgeom) {
|
|||||||
|
|
||||||
|
|
||||||
// site element parser
|
// site element parser
|
||||||
void mjXReader::OneSite(XMLElement* elem, mjCSite* site) {
|
void mjXReader::OneSite(XMLElement* elem, mjmSite& site) {
|
||||||
int n;
|
int n;
|
||||||
string text;
|
string text, name, classname;
|
||||||
mjmSite* psite = &site->spec;
|
|
||||||
std::vector<double> userdata;
|
std::vector<double> userdata;
|
||||||
std::string material;
|
std::string material;
|
||||||
|
|
||||||
// read attributes
|
// read attributes
|
||||||
ReadAttrTxt(elem, "name", site->name);
|
ReadAttrTxt(elem, "name", name);
|
||||||
ReadAttrTxt(elem, "class", site->classname);
|
ReadAttrTxt(elem, "class", classname);
|
||||||
if (MapValue(elem, "type", &n, geom_map, mjNGEOMTYPES)) {
|
if (MapValue(elem, "type", &n, geom_map, mjNGEOMTYPES)) {
|
||||||
psite->type = (mjtGeom)n;
|
site.type = (mjtGeom)n;
|
||||||
}
|
}
|
||||||
ReadAttr(elem, "size", 3, psite->size, text, false, false);
|
ReadAttr(elem, "size", 3, site.size, text, false, false);
|
||||||
ReadAttrInt(elem, "group", &psite->group);
|
ReadAttrInt(elem, "group", &site.group);
|
||||||
ReadAttr(elem, "pos", 3, psite->pos, text);
|
ReadAttr(elem, "pos", 3, site.pos, text);
|
||||||
ReadQuat(elem, "quat", psite->quat, text);
|
ReadQuat(elem, "quat", site.quat, text);
|
||||||
ReadAttrTxt(elem, "material", material);
|
ReadAttrTxt(elem, "material", material);
|
||||||
ReadAttr(elem, "rgba", 4, psite->rgba, text);
|
ReadAttr(elem, "rgba", 4, site.rgba, text);
|
||||||
ReadAttr(elem, "fromto", 6, psite->fromto, text);
|
ReadAttr(elem, "fromto", 6, site.fromto, text);
|
||||||
ReadAlternative(elem, psite->alt);
|
ReadAlternative(elem, site.alt);
|
||||||
ReadVector(elem, "user", userdata, text);
|
ReadVector(elem, "user", userdata, text);
|
||||||
|
|
||||||
// set variable-size attributes
|
// set strings
|
||||||
site->set_userdata(userdata);
|
mjm_setString(site.name, name.c_str());
|
||||||
site->set_material(material);
|
mjm_setString(site.classname, classname.c_str());
|
||||||
|
mjm_setString(site.material, material.c_str());
|
||||||
|
|
||||||
GetXMLPos(elem, site);
|
// set pointers
|
||||||
|
mjm_setDouble(site.userdata, userdata.data(), userdata.size());
|
||||||
|
|
||||||
|
// set info
|
||||||
|
mjm_setString(site.info,
|
||||||
|
std::string("line = " + std::to_string(elem->GetLineNum()) + ", column = -1").c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2177,7 +2183,7 @@ void mjXReader::OneComposite(XMLElement* elem, mjCBody* pbody, mjCDef* def) {
|
|||||||
ReadAttrInt(esite, "group", &dsite.group);
|
ReadAttrInt(esite, "group", &dsite.group);
|
||||||
ReadAttrTxt(esite, "material", material);
|
ReadAttrTxt(esite, "material", material);
|
||||||
ReadAttr(esite, "rgba", 4, dsite.rgba, text);
|
ReadAttr(esite, "rgba", 4, dsite.rgba, text);
|
||||||
comp.def[0].site.set_material(material);
|
mjm_setString(dsite.material, material.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// joint
|
// joint
|
||||||
@@ -2487,7 +2493,7 @@ void mjXReader::Default(XMLElement* section, int parentid) {
|
|||||||
else if (name=="geom") OneGeom(elem, &def->geom);
|
else if (name=="geom") OneGeom(elem, &def->geom);
|
||||||
|
|
||||||
// read site
|
// read site
|
||||||
else if (name=="site") OneSite(elem, &def->site);
|
else if (name=="site") OneSite(elem, def->site.spec);
|
||||||
|
|
||||||
// read camera
|
// read camera
|
||||||
else if (name=="camera") OneCamera(elem, &def->camera);
|
else if (name=="camera") OneCamera(elem, &def->camera);
|
||||||
@@ -3061,9 +3067,9 @@ void mjXReader::Body(XMLElement* section, mjCBody* pbody, mjCFrame* frame) {
|
|||||||
// site sub-element
|
// site sub-element
|
||||||
else if (name=="site") {
|
else if (name=="site") {
|
||||||
// create site and parse
|
// create site and parse
|
||||||
mjCSite* psite = pbody->AddSite(def);
|
mjmSite* site = mjm_addSite(pbody, def);
|
||||||
OneSite(elem, psite);
|
OneSite(elem, *site);
|
||||||
psite->SetFrame(frame);
|
mjm_setFrame(site, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
// camera sub-element
|
// camera sub-element
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class mjXReader : public mjXBase {
|
|||||||
void OneMaterial(tinyxml2::XMLElement* elem, mjCMaterial* pmaterial);
|
void OneMaterial(tinyxml2::XMLElement* elem, mjCMaterial* pmaterial);
|
||||||
void OneJoint(tinyxml2::XMLElement* elem, mjCJoint* pjoint);
|
void OneJoint(tinyxml2::XMLElement* elem, mjCJoint* pjoint);
|
||||||
void OneGeom(tinyxml2::XMLElement* elem, mjCGeom* pgeom);
|
void OneGeom(tinyxml2::XMLElement* elem, mjCGeom* pgeom);
|
||||||
void OneSite(tinyxml2::XMLElement* elem, mjCSite* psite);
|
void OneSite(tinyxml2::XMLElement* elem, mjmSite& site);
|
||||||
void OneCamera(tinyxml2::XMLElement* elem, mjCCamera* pcamera);
|
void OneCamera(tinyxml2::XMLElement* elem, mjCCamera* pcamera);
|
||||||
void OneLight(tinyxml2::XMLElement* elem, mjCLight* plight);
|
void OneLight(tinyxml2::XMLElement* elem, mjCLight* plight);
|
||||||
void OnePair(tinyxml2::XMLElement* elem, mjCPair* ppair);
|
void OnePair(tinyxml2::XMLElement* elem, mjCPair* ppair);
|
||||||
|
|||||||
+3
-3
@@ -1034,7 +1034,7 @@ template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
|||||||
|
|
||||||
|
|
||||||
// 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, const vector<double>& vec) {
|
||||||
// proceed only if non-zero found
|
// proceed only if non-zero found
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
for (size_t i=0; i<vec.size(); i++) {
|
for (size_t i=0; i<vec.size(); i++) {
|
||||||
@@ -1053,8 +1053,8 @@ void mjXUtil::WriteVector(XMLElement* elem, string name, vector<double>& vec) {
|
|||||||
|
|
||||||
|
|
||||||
// write vector<double> attribute, default with same size
|
// write vector<double> attribute, default with same size
|
||||||
void mjXUtil::WriteVector(XMLElement* elem, string name, vector<double>& vec,
|
void mjXUtil::WriteVector(XMLElement* elem, string name, const vector<double>& vec,
|
||||||
vector<double>& def) {
|
const vector<double>& def) {
|
||||||
// proceed only if non-zero found
|
// proceed only if non-zero found
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
for (size_t i=0; i<vec.size(); i++) {
|
for (size_t i=0; i<vec.size(); i++) {
|
||||||
|
|||||||
+4
-3
@@ -198,9 +198,10 @@ class mjXUtil {
|
|||||||
const T* def = 0);
|
const T* 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,
|
||||||
static void WriteVector(tinyxml2::XMLElement* elem, std::string name, std::vector<double>& vec,
|
const std::vector<double>& vec);
|
||||||
std::vector<double>& def);
|
static void WriteVector(tinyxml2::XMLElement* elem, std::string name,
|
||||||
|
const std::vector<double>& vec, const std::vector<double>& def);
|
||||||
|
|
||||||
// write attribute- string
|
// write attribute- string
|
||||||
static void WriteAttrTxt(tinyxml2::XMLElement* elem, std::string name, std::string value);
|
static void WriteAttrTxt(tinyxml2::XMLElement* elem, std::string name, std::string value);
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ target_link_libraries(user_model_test fixture gmock absl::str_format)
|
|||||||
mujoco_test(user_objects_test)
|
mujoco_test(user_objects_test)
|
||||||
target_link_libraries(user_objects_test fixture gmock)
|
target_link_libraries(user_objects_test fixture gmock)
|
||||||
|
|
||||||
|
mujoco_test(user_api_test)
|
||||||
|
target_link_libraries(user_api_test fixture gmock)
|
||||||
|
|
||||||
mujoco_test(user_flex_test)
|
mujoco_test(user_flex_test)
|
||||||
target_link_libraries(user_flex_test fixture gmock)
|
target_link_libraries(user_flex_test fixture gmock)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2021 DeepMind Technologies Limited
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// Tests for user/user_api.cc.
|
||||||
|
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include "src/user/user_api.h"
|
||||||
|
#include <mujoco/mjmodel.h>
|
||||||
|
#include "test/fixture.h"
|
||||||
|
|
||||||
|
namespace mujoco {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::HasSubstr;
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------- test set/get --------------------------------
|
||||||
|
|
||||||
|
TEST_F(MujocoTest, ReadWriteData) {
|
||||||
|
void* model = mjm_createModel();
|
||||||
|
void* world = mjm_findObject(model, mjOBJ_BODY, "world");
|
||||||
|
void* body = mjm_addBody(world, 0);
|
||||||
|
mjmSite* site = mjm_addSite(body, 0);
|
||||||
|
|
||||||
|
{
|
||||||
|
double vec[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||||
|
const char* str = "sitename";
|
||||||
|
|
||||||
|
mjm_setString(site->name, str);
|
||||||
|
mjm_setDouble(site->userdata, vec, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_THAT(mjm_getString(site->name), HasSubstr("sitename"));
|
||||||
|
|
||||||
|
int nsize;
|
||||||
|
const double* vec = mjm_getDouble(site->userdata, &nsize);
|
||||||
|
for (int i = 0; i < nsize; ++i) {
|
||||||
|
EXPECT_EQ(vec[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
mjm_deleteModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace mujoco
|
||||||
Reference in New Issue
Block a user