Add plugins list to mjSpec Python API.

Fixes #2061.

PiperOrigin-RevId: 677762985
Change-Id: I8e407373e7b505d9b0f1c023e97c5ea92169bbf6
This commit is contained in:
Alessio Quaglino
2024-09-23 06:12:42 -07:00
committed by Copybara-Service
parent 91cedfd65c
commit 0ba11b9623
18 changed files with 127 additions and 44 deletions
+9
View File
@@ -4432,6 +4432,15 @@ mjs_asMaterial
Safely cast an element as mjsMaterial, or return NULL if the element is not an mjsMaterial. Safely cast an element as mjsMaterial, or return NULL if the element is not an mjsMaterial.
.. _mjs_asPlugin:
mjs_asPlugin
~~~~~~~~~~~~
.. mujoco-include:: mjs_asPlugin
Safely cast an element as mjsPlugin, or return NULL if the element is not an mjsPlugin.
.. _AttributeSetters: .. _AttributeSetters:
Attribute setters Attribute setters
+2 -1
View File
@@ -1738,7 +1738,7 @@ typedef struct mjsOrientation_ { // alternative orientation specifiers
double euler[3]; // Euler angles double euler[3]; // Euler angles
} mjsOrientation; } mjsOrientation;
typedef struct mjsPlugin_ { // plugin specification typedef struct mjsPlugin_ { // plugin specification
mjsElement* instance; // element type mjsElement* element; // element type
mjString* name; // name mjString* name; // name
mjString* instance_name; // instance name mjString* instance_name; // instance name
int plugin_slot; // global registered slot number of the plugin int plugin_slot; // global registered slot number of the plugin
@@ -3622,6 +3622,7 @@ mjsHField* mjs_asHField(mjsElement* element);
mjsSkin* mjs_asSkin(mjsElement* element); mjsSkin* mjs_asSkin(mjsElement* element);
mjsTexture* mjs_asTexture(mjsElement* element); mjsTexture* mjs_asTexture(mjsElement* element);
mjsMaterial* mjs_asMaterial(mjsElement* element); mjsMaterial* mjs_asMaterial(mjsElement* element);
mjsPlugin* mjs_asPlugin(mjsElement* element);
void mjs_setBuffer(mjByteVec* dest, const void* array, int size); void mjs_setBuffer(mjByteVec* dest, const void* array, int size);
void mjs_setString(mjString* dest, const char* text); void mjs_setString(mjString* dest, const char* text);
void mjs_setStringVec(mjStringVec* dest, const char* text); void mjs_setStringVec(mjStringVec* dest, const char* text);
+1 -1
View File
@@ -181,7 +181,7 @@ typedef struct mjsOrientation_ { // alternative orientation specifiers
typedef struct mjsPlugin_ { // plugin specification typedef struct mjsPlugin_ { // plugin specification
mjsElement* instance; // element type mjsElement* element; // element type
mjString* name; // name mjString* name; // name
mjString* instance_name; // instance name mjString* instance_name; // instance name
int plugin_slot; // global registered slot number of the plugin int plugin_slot; // global registered slot number of the plugin
+3
View File
@@ -1628,6 +1628,9 @@ MJAPI mjsTexture* mjs_asTexture(mjsElement* element);
// Safely cast an element as mjsMaterial, or return NULL if the element is not an mjsMaterial. // Safely cast an element as mjsMaterial, or return NULL if the element is not an mjsMaterial.
MJAPI mjsMaterial* mjs_asMaterial(mjsElement* element); MJAPI mjsMaterial* mjs_asMaterial(mjsElement* element);
// Safely cast an element as mjsPlugin, or return NULL if the element is not an mjsPlugin.
MJAPI mjsPlugin* mjs_asPlugin(mjsElement* element);
//---------------------------------- Attribute setters --------------------------------------------- //---------------------------------- Attribute setters ---------------------------------------------
+16
View File
@@ -10270,6 +10270,22 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
), ),
doc='Safely cast an element as mjsMaterial, or return NULL if the element is not an mjsMaterial.', # pylint: disable=line-too-long doc='Safely cast an element as mjsMaterial, or return NULL if the element is not an mjsMaterial.', # pylint: disable=line-too-long
)), )),
('mjs_asPlugin',
FunctionDecl(
name='mjs_asPlugin',
return_type=PointerType(
inner_type=ValueType(name='mjsPlugin'),
),
parameters=(
FunctionParameterDecl(
name='element',
type=PointerType(
inner_type=ValueType(name='mjsElement'),
),
),
),
doc='Safely cast an element as mjsPlugin, or return NULL if the element is not an mjsPlugin.', # pylint: disable=line-too-long
)),
('mjs_setBuffer', ('mjs_setBuffer',
FunctionDecl( FunctionDecl(
name='mjs_setBuffer', name='mjs_setBuffer',
+1 -1
View File
@@ -8565,7 +8565,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
declname='struct mjsPlugin_', declname='struct mjsPlugin_',
fields=( fields=(
StructFieldDecl( StructFieldDecl(
name='instance', name='element',
type=PointerType( type=PointerType(
inner_type=ValueType(name='mjsElement'), inner_type=ValueType(name='mjsElement'),
), ),
+15 -3
View File
@@ -274,6 +274,18 @@ PYBIND11_MODULE(_specs, m) {
mjSpec.def("detach_body", [](MjSpec& self, raw::MjsBody& body) { mjSpec.def("detach_body", [](MjSpec& self, raw::MjsBody& body) {
mjs_detachBody(self.ptr, &body); mjs_detachBody(self.ptr, &body);
}); });
mjSpec.def_property_readonly(
"plugins",
[](MjSpec& self) -> py::list {
py::list list;
raw::MjsElement* el = mjs_firstElement(self.ptr, mjOBJ_PLUGIN);
while (el) {
list.append(mjs_asPlugin(el));
el = mjs_nextElement(self.ptr, el);
}
return list;
},
py::return_value_policy::reference_internal);
mjSpec.def_property_readonly( mjSpec.def_property_readonly(
"actuators", "actuators",
[](MjSpec& self) -> py::list { [](MjSpec& self) -> py::list {
@@ -900,12 +912,12 @@ PYBIND11_MODULE(_specs, m) {
// ============================= MJSPLUGIN =================================== // ============================= MJSPLUGIN ===================================
mjsPlugin.def_property( mjsPlugin.def_property(
"id", "id",
[](raw::MjsPlugin& self) -> int { return mjs_getId(self.instance); }, [](raw::MjsPlugin& self) -> int { return mjs_getId(self.element); },
[](raw::MjsPlugin& self, raw::MjsPlugin* other) { [](raw::MjsPlugin& self, raw::MjsPlugin* other) {
self.instance = other->instance; self.element = other->element;
}); });
mjsPlugin.def("delete", mjsPlugin.def("delete",
[](raw::MjsPlugin& self) { mjs_delete(self.instance); }); [](raw::MjsPlugin& self) { mjs_delete(self.element); });
#include "specs.cc.inc" #include "specs.cc.inc"
} // PYBIND11_MODULE // NOLINT } // PYBIND11_MODULE // NOLINT
+27
View File
@@ -690,5 +690,32 @@ class SpecsTest(absltest.TestCase):
): ):
spec.recompile(model, data) spec.recompile(model, data)
def test_delete_unused_plugin(self):
spec = mujoco.MjSpec()
spec.from_string(textwrap.dedent("""
<mujoco model="MuJoCo Model">
<extension>
<plugin plugin="mujoco.pid">
<instance name="pid1">
<config key="kp" value="4.0"/>
</instance>
</plugin>
</extension>
<worldbody>
<body>
<geom size="1"/>
</body>
</worldbody>
</mujoco>
"""))
plugin = spec.plugins[0]
self.assertIsNotNone(plugin)
plugin.delete()
model = spec.compile()
self.assertIsNotNone(model)
self.assertEqual(model.nplugin, 0)
if __name__ == '__main__': if __name__ == '__main__':
absltest.main() absltest.main()
+12 -2
View File
@@ -471,7 +471,7 @@ mjsKey* mjs_addKey(mjSpec* s) {
mjsPlugin* mjs_addPlugin(mjSpec* s) { mjsPlugin* mjs_addPlugin(mjSpec* s) {
mjCModel* modelC = static_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCPlugin* plugin = modelC->AddPlugin(); mjCPlugin* plugin = modelC->AddPlugin();
plugin->spec.instance = static_cast<mjsElement*>(plugin); plugin->spec.element = static_cast<mjsElement*>(plugin);
return &plugin->spec; return &plugin->spec;
} }
@@ -887,6 +887,16 @@ mjsMaterial* mjs_asMaterial(mjsElement* element) {
// return plugin given mjsElement
mjsPlugin* mjs_asPlugin(mjsElement* element) {
if (element && element->elemtype == mjOBJ_PLUGIN) {
return &(static_cast<mjCPlugin*>(element)->spec);
}
return nullptr;
}
// copy buffer to destination buffer // copy buffer to destination buffer
void mjs_setBuffer(mjByteVec* dest, const void* array, int size) { void mjs_setBuffer(mjByteVec* dest, const void* array, int size) {
const std::byte* buffer = static_cast<const std::byte*>(array); const std::byte* buffer = static_cast<const std::byte*>(array);
@@ -995,7 +1005,7 @@ const double* mjs_getDouble(const mjDoubleVec* source, int* size) {
// set plugin attributes // set plugin attributes
void mjs_setPluginAttributes(mjsPlugin* plugin, void* attributes) { void mjs_setPluginAttributes(mjsPlugin* plugin, void* attributes) {
mjCPlugin* pluginC = static_cast<mjCPlugin*>(plugin->instance); mjCPlugin* pluginC = static_cast<mjCPlugin*>(plugin->element);
std::map<std::string, std::string, std::less<>>* config_attribs = std::map<std::string, std::string, std::less<>>* config_attribs =
reinterpret_cast<std::map<std::string, std::string, std::less<>>*>(attributes); reinterpret_cast<std::map<std::string, std::string, std::less<>>*>(attributes);
pluginC->config_attribs = std::move(*config_attribs); pluginC->config_attribs = std::move(*config_attribs);
+3
View File
@@ -296,6 +296,9 @@ MJAPI mjsTexture* mjs_asTexture(mjsElement* element);
// Safely cast an element as mjsMaterial, or return NULL if the element is not an mjsMaterial. // Safely cast an element as mjsMaterial, or return NULL if the element is not an mjsMaterial.
MJAPI mjsMaterial* mjs_asMaterial(mjsElement* element); MJAPI mjsMaterial* mjs_asMaterial(mjsElement* element);
// Safely cast an element as mjsPlugin, or return NULL if the element is not an mjsPlugin.
MJAPI mjsPlugin* mjs_asPlugin(mjsElement* element);
//---------------------------------- Attribute setters --------------------------------------------- //---------------------------------- Attribute setters ---------------------------------------------
+2 -2
View File
@@ -315,7 +315,7 @@ bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz)
// overwrite plugin name // overwrite plugin name
if (plugin_instance_name.empty() && plugin.active) { if (plugin_instance_name.empty() && plugin.active) {
plugin_instance_name = "composite" + prefix; plugin_instance_name = "composite" + prefix;
(static_cast<mjCPlugin*>(plugin.instance))->name = plugin_instance_name; (static_cast<mjCPlugin*>(plugin.element))->name = plugin_instance_name;
} }
// dispatch // dispatch
@@ -714,7 +714,7 @@ mjsBody* mjCComposite::AddCableBody(mjCModel* model, mjsBody* body, int ix,
if (plugin.active) { if (plugin.active) {
mjsPlugin* pplugin = &body->plugin; mjsPlugin* pplugin = &body->plugin;
pplugin->active = true; pplugin->active = true;
pplugin->instance = plugin.instance; pplugin->element = plugin.element;
mjs_setString(pplugin->name, mjs_getString(plugin.name)); mjs_setString(pplugin->name, mjs_getString(plugin.name));
mjs_setString(pplugin->instance_name, plugin_instance_name.c_str()); mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
} }
+3 -3
View File
@@ -422,7 +422,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
// overwrite plugin name // overwrite plugin name
if (plugin.active && plugin_instance_name.empty()) { if (plugin.active && plugin_instance_name.empty()) {
plugin_instance_name = "flexcomp_" + name; plugin_instance_name = "flexcomp_" + name;
static_cast<mjCPlugin*>(plugin.instance)->name = plugin_instance_name; static_cast<mjCPlugin*>(plugin.element)->name = plugin_instance_name;
} }
// create bodies, construct flex vert and vertbody // create bodies, construct flex vert and vertbody
@@ -440,7 +440,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
if (plugin.active) { if (plugin.active) {
mjsPlugin* pplugin = &body->plugin; mjsPlugin* pplugin = &body->plugin;
pplugin->active = true; pplugin->active = true;
pplugin->instance = static_cast<mjsElement*>(plugin.instance); pplugin->element = static_cast<mjsElement*>(plugin.element);
mjs_setString(pplugin->name, mjs_getString(plugin.name)); mjs_setString(pplugin->name, mjs_getString(plugin.name));
mjs_setString(pplugin->instance_name, plugin_instance_name.c_str()); mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
} }
@@ -504,7 +504,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
if (plugin.active) { if (plugin.active) {
mjsPlugin* pplugin = &pb->plugin; mjsPlugin* pplugin = &pb->plugin;
pplugin->active = true; pplugin->active = true;
pplugin->instance = static_cast<mjsElement*>(plugin.instance); pplugin->element = static_cast<mjsElement*>(plugin.element);
mjs_setString(pplugin->name, mjs_getString(plugin.name)); mjs_setString(pplugin->name, mjs_getString(plugin.name));
mjs_setString(pplugin->instance_name, plugin_instance_name.c_str()); mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
} }
+6 -6
View File
@@ -246,7 +246,7 @@ void mjCMesh::CopyFromSpec() {
facetexcoord_ = spec_facetexcoord_; facetexcoord_ = spec_facetexcoord_;
maxhullvert_ = spec.maxhullvert; maxhullvert_ = spec.maxhullvert;
plugin.active = spec.plugin.active; plugin.active = spec.plugin.active;
plugin.instance = spec.plugin.instance; plugin.element = spec.plugin.element;
plugin.name = spec.plugin.name; plugin.name = spec.plugin.name;
plugin.instance_name = spec.plugin.instance_name; plugin.instance_name = spec.plugin.instance_name;
@@ -270,7 +270,7 @@ mjCMesh::~mjCMesh() {
if (center_) mju_free(center_); if (center_) mju_free(center_);
if (graph_) mju_free(graph_); if (graph_) mju_free(graph_);
if (spec.plugin.active && spec.plugin.instance_name->empty()) { if (spec.plugin.active && spec.plugin.instance_name->empty()) {
model->DeleteElement(spec.plugin.instance); model->DeleteElement(spec.plugin.element);
} }
} }
@@ -289,9 +289,9 @@ void mjCMesh::LoadSDF() {
name.c_str(), id); name.c_str(), id);
} }
mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.instance); mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.element);
model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance); model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance);
plugin.instance = plugin_instance; plugin.element = plugin_instance;
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot); const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
if (!(pplugin->capabilityflags & mjPLUGIN_SDF)) { if (!(pplugin->capabilityflags & mjPLUGIN_SDF)) {
throw mjCError(this, "plugin '%s' does not support signed distance fields", pplugin->name); throw mjCError(this, "plugin '%s' does not support signed distance fields", pplugin->name);
@@ -2919,9 +2919,9 @@ void mjCFlex::Compile(const mjVFS* vfs) {
useredge = VectorToString(edgeidx_); useredge = VectorToString(edgeidx_);
for (const auto& vbodyid : vertbodyid) { for (const auto& vbodyid : vertbodyid) {
if (model->Bodies()[vbodyid]->plugin.instance) { if (model->Bodies()[vbodyid]->plugin.element) {
mjCPlugin* plugin_instance = mjCPlugin* plugin_instance =
static_cast<mjCPlugin*>(model->Bodies()[vbodyid]->plugin.instance); static_cast<mjCPlugin*>(model->Bodies()[vbodyid]->plugin.element);
if (damping > 0) { if (damping > 0) {
plugin_instance->config_attribs["damping"] = std::to_string(damping); plugin_instance->config_attribs["damping"] = std::to_string(damping);
} }
+6 -4
View File
@@ -938,6 +938,8 @@ mjsElement* mjCModel::NextObject(mjsElement* object, mjtObj type) {
return GetNext(textures_, object); return GetNext(textures_, object);
case mjOBJ_MATERIAL: case mjOBJ_MATERIAL:
return GetNext(materials_, object); return GetNext(materials_, object);
case mjOBJ_PLUGIN:
return GetNext(plugins_, object);
default: default:
return nullptr; return nullptr;
} }
@@ -3932,7 +3934,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
std::vector<std::vector<int>> plugin_to_actuators(nplugin); std::vector<std::vector<int>> plugin_to_actuators(nplugin);
for (int i = 0; i < nu; ++i) { for (int i = 0; i < nu; ++i) {
if (actuators_[i]->plugin.active) { if (actuators_[i]->plugin.active) {
int actuator_plugin = static_cast<mjCPlugin*>(actuators_[i]->plugin.instance)->id; int actuator_plugin = static_cast<mjCPlugin*>(actuators_[i]->plugin.element)->id;
m->actuator_plugin[i] = actuator_plugin; m->actuator_plugin[i] = actuator_plugin;
plugin_to_actuators[actuator_plugin].push_back(i); plugin_to_actuators[actuator_plugin].push_back(i);
} else { } else {
@@ -3942,7 +3944,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
for (int i = 0; i < nbody; ++i) { for (int i = 0; i < nbody; ++i) {
if (bodies_[i]->plugin.active) { if (bodies_[i]->plugin.active) {
m->body_plugin[i] = static_cast<mjCPlugin*>(bodies_[i]->plugin.instance)->id; m->body_plugin[i] = static_cast<mjCPlugin*>(bodies_[i]->plugin.element)->id;
} else { } else {
m->body_plugin[i] = -1; m->body_plugin[i] = -1;
} }
@@ -3950,7 +3952,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
for (int i = 0; i < ngeom; ++i) { for (int i = 0; i < ngeom; ++i) {
if (geoms_[i]->plugin.active) { if (geoms_[i]->plugin.active) {
m->geom_plugin[i] = static_cast<mjCPlugin*>(geoms_[i]->plugin.instance)->id; m->geom_plugin[i] = static_cast<mjCPlugin*>(geoms_[i]->plugin.element)->id;
} else { } else {
m->geom_plugin[i] = -1; m->geom_plugin[i] = -1;
} }
@@ -3959,7 +3961,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
std::vector<std::vector<int>> plugin_to_sensors(nplugin); std::vector<std::vector<int>> plugin_to_sensors(nplugin);
for (int i = 0; i < nsensor; ++i) { for (int i = 0; i < nsensor; ++i) {
if (sensors_[i]->type == mjSENS_PLUGIN) { if (sensors_[i]->type == mjSENS_PLUGIN) {
int sensor_plugin = static_cast<mjCPlugin*>(sensors_[i]->plugin.instance)->id; int sensor_plugin = static_cast<mjCPlugin*>(sensors_[i]->plugin.element)->id;
m->sensor_plugin[i] = sensor_plugin; m->sensor_plugin[i] = sensor_plugin;
plugin_to_sensors[sensor_plugin].push_back(i); plugin_to_sensors[sensor_plugin].push_back(i);
} else { } else {
+16 -16
View File
@@ -959,7 +959,7 @@ void mjCBody::CopyFromSpec() {
*static_cast<mjsBody*>(this) = spec; *static_cast<mjsBody*>(this) = spec;
userdata_ = spec_userdata_; userdata_ = spec_userdata_;
plugin.active = spec.plugin.active; plugin.active = spec.plugin.active;
plugin.instance = spec.plugin.instance; plugin.element = spec.plugin.element;
plugin.name = spec.plugin.name; plugin.name = spec.plugin.name;
plugin.instance_name = spec.plugin.instance_name; plugin.instance_name = spec.plugin.instance_name;
} }
@@ -986,7 +986,7 @@ mjCBody::~mjCBody() {
lights.clear(); lights.clear();
if (spec.plugin.active && spec.plugin.instance_name->empty()) { if (spec.plugin.active && spec.plugin.instance_name->empty()) {
model->DeleteElement(spec.plugin.instance); model->DeleteElement(spec.plugin.element);
} }
} }
@@ -1669,9 +1669,9 @@ void mjCBody::Compile(void) {
name.c_str(), id); name.c_str(), id);
} }
mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.instance); mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.element);
model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance); model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance);
plugin.instance = plugin_instance; plugin.element = plugin_instance;
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot); const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
if (!(pplugin->capabilityflags & mjPLUGIN_PASSIVE)) { if (!(pplugin->capabilityflags & mjPLUGIN_PASSIVE)) {
throw mjCError(this, "plugin '%s' does not support passive forces", pplugin->name); throw mjCError(this, "plugin '%s' does not support passive forces", pplugin->name);
@@ -2132,7 +2132,7 @@ mjCGeom::mjCGeom(const mjCGeom& other) {
mjCGeom::~mjCGeom() { mjCGeom::~mjCGeom() {
if (spec.plugin.active && spec.plugin.instance_name->empty()) { if (spec.plugin.active && spec.plugin.instance_name->empty()) {
model->DeleteElement(spec.plugin.instance); model->DeleteElement(spec.plugin.element);
} }
} }
@@ -2176,7 +2176,7 @@ void mjCGeom::CopyFromSpec() {
meshname_ = spec_meshname_; meshname_ = spec_meshname_;
material_ = spec_material_; material_ = spec_material_;
plugin.active = spec.plugin.active; plugin.active = spec.plugin.active;
plugin.instance = spec.plugin.instance; plugin.element = spec.plugin.element;
plugin.name = spec.plugin.name; plugin.name = spec.plugin.name;
plugin.instance_name = spec.plugin.instance_name; plugin.instance_name = spec.plugin.instance_name;
} }
@@ -2913,9 +2913,9 @@ void mjCGeom::Compile(void) {
this, "neither 'plugin' nor 'instance' is specified for geom"); this, "neither 'plugin' nor 'instance' is specified for geom");
} }
mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.instance); mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.element);
model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance); model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance);
plugin.instance = plugin_instance; plugin.element = plugin_instance;
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot); const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
if (!(pplugin->capabilityflags & mjPLUGIN_SDF)) { if (!(pplugin->capabilityflags & mjPLUGIN_SDF)) {
throw mjCError(this, "plugin '%s' does not support sign distance fields", pplugin->name); throw mjCError(this, "plugin '%s' does not support sign distance fields", pplugin->name);
@@ -5554,7 +5554,7 @@ mjCActuator::mjCActuator(const mjCActuator& other) {
mjCActuator::~mjCActuator() { mjCActuator::~mjCActuator() {
if (spec.plugin.active && spec.plugin.instance_name->empty()) { if (spec.plugin.active && spec.plugin.instance_name->empty()) {
model->DeleteElement(spec.plugin.instance); model->DeleteElement(spec.plugin.element);
} }
} }
@@ -5640,7 +5640,7 @@ void mjCActuator::CopyFromSpec() {
refsite_ = spec_refsite_; refsite_ = spec_refsite_;
slidersite_ = spec_slidersite_; slidersite_ = spec_slidersite_;
plugin.active = spec.plugin.active; plugin.active = spec.plugin.active;
plugin.instance = spec.plugin.instance; plugin.element = spec.plugin.element;
plugin.name = spec.plugin.name; plugin.name = spec.plugin.name;
plugin.instance_name = spec.plugin.instance_name; plugin.instance_name = spec.plugin.instance_name;
} }
@@ -5869,9 +5869,9 @@ void mjCActuator::Compile(void) {
name.c_str(), id); name.c_str(), id);
} }
mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.instance); mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.element);
model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance); model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance);
plugin.instance = plugin_instance; plugin.element = plugin_instance;
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot); const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
if (!(pplugin->capabilityflags & mjPLUGIN_ACTUATOR)) { if (!(pplugin->capabilityflags & mjPLUGIN_ACTUATOR)) {
throw mjCError(this, "plugin '%s' does not support actuators", pplugin->name); throw mjCError(this, "plugin '%s' does not support actuators", pplugin->name);
@@ -5916,7 +5916,7 @@ mjCSensor::mjCSensor(const mjCSensor& other) {
mjCSensor::~mjCSensor() { mjCSensor::~mjCSensor() {
if (spec.plugin.active && spec.plugin.instance_name->empty()) { if (spec.plugin.active && spec.plugin.instance_name->empty()) {
model->DeleteElement(spec.plugin.instance); model->DeleteElement(spec.plugin.element);
} }
} }
@@ -5968,7 +5968,7 @@ void mjCSensor::CopyFromSpec() {
objname_ = spec_objname_; objname_ = spec_objname_;
refname_ = spec_refname_; refname_ = spec_refname_;
plugin.active = spec.plugin.active; plugin.active = spec.plugin.active;
plugin.instance = spec.plugin.instance; plugin.element = spec.plugin.element;
plugin.name = spec.plugin.name; plugin.name = spec.plugin.name;
plugin.instance_name = spec.plugin.instance_name; plugin.instance_name = spec.plugin.instance_name;
} }
@@ -6373,9 +6373,9 @@ void mjCSensor::Compile(void) {
// resolve plugin instance, or create one if using the "plugin" attribute shortcut // resolve plugin instance, or create one if using the "plugin" attribute shortcut
{ {
mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.instance); mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.element);
model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance); model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance);
plugin.instance = plugin_instance; plugin.element = plugin_instance;
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot); const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
if (!(pplugin->capabilityflags & mjPLUGIN_SENSOR)) { if (!(pplugin->capabilityflags & mjPLUGIN_SENSOR)) {
throw mjCError(this, "plugin '%s' does not support sensors", pplugin->name); throw mjCError(this, "plugin '%s' does not support sensors", pplugin->name);
+1 -1
View File
@@ -2767,7 +2767,7 @@ void mjXReader::OnePlugin(XMLElement* elem, mjsPlugin* plugin) {
mjs_setString(plugin->name, name.c_str()); mjs_setString(plugin->name, name.c_str());
mjs_setString(plugin->instance_name, instance_name.c_str()); mjs_setString(plugin->instance_name, instance_name.c_str());
if (instance_name.empty()) { if (instance_name.empty()) {
plugin->instance = mjs_addPlugin(spec)->instance; plugin->element = mjs_addPlugin(spec)->element;
ReadPluginConfigs(elem, plugin); ReadPluginConfigs(elem, plugin);
} else { } else {
spec->hasImplicitPluginElem = true; spec->hasImplicitPluginElem = true;
+2 -2
View File
@@ -827,8 +827,8 @@ void mjXWriter::OnePlugin(XMLElement* elem, const mjsPlugin* plugin) {
} else { } else {
WriteAttrTxt(elem, "plugin", plugin_name); WriteAttrTxt(elem, "plugin", plugin_name);
const mjpPlugin* pplugin = mjp_getPluginAtSlot( const mjpPlugin* pplugin = mjp_getPluginAtSlot(
static_cast<mjCPlugin*>(plugin->instance)->spec.plugin_slot); static_cast<mjCPlugin*>(plugin->element)->spec.plugin_slot);
const char* c = &(static_cast<mjCPlugin*>(plugin->instance)->flattened_attributes[0]); const char* c = &(static_cast<mjCPlugin*>(plugin->element)->flattened_attributes[0]);
for (int i = 0; i < pplugin->nattribute; ++i) { for (int i = 0; i < pplugin->nattribute; ++i) {
string value(c); string value(c);
if (!value.empty()) { if (!value.empty()) {
+2 -2
View File
@@ -147,7 +147,7 @@ TEST_F(PluginTest, ActivatePlugin) {
// associate plugin to body // associate plugin to body
mjsBody* body = mjs_addBody(mjs_findBody(spec, "world"), 0); mjsBody* body = mjs_addBody(mjs_findBody(spec, "world"), 0);
mjs_setString(body->plugin.name, plugin_name.c_str()); mjs_setString(body->plugin.name, plugin_name.c_str());
body->plugin.instance = mjs_addPlugin(spec)->instance; body->plugin.element = mjs_addPlugin(spec)->element;
body->plugin.active = true; body->plugin.active = true;
mjsGeom* geom = mjs_addGeom(body, 0); mjsGeom* geom = mjs_addGeom(body, 0);
geom->type = mjGEOM_BOX; geom->type = mjGEOM_BOX;
@@ -191,7 +191,7 @@ TEST_F(PluginTest, DeletePlugin) {
mjsActuator* actuator = mjs_addActuator(spec, 0); mjsActuator* actuator = mjs_addActuator(spec, 0);
mjs_setString(actuator->target, "j1"); mjs_setString(actuator->target, "j1");
mjs_setString(actuator->plugin.name, plugin_name.c_str()); mjs_setString(actuator->plugin.name, plugin_name.c_str());
actuator->plugin.instance = mjs_addPlugin(spec)->instance; actuator->plugin.element = mjs_addPlugin(spec)->element;
actuator->plugin.active = true; actuator->plugin.active = true;
actuator->trntype = mjTRN_JOINT; actuator->trntype = mjTRN_JOINT;