Add plugins list to mjSpec Python API.
Fixes #2061. PiperOrigin-RevId: 677762985 Change-Id: I8e407373e7b505d9b0f1c023e97c5ea92169bbf6
This commit is contained in:
committed by
Copybara-Service
parent
91cedfd65c
commit
0ba11b9623
@@ -4432,6 +4432,15 @@ mjs_asMaterial
|
||||
|
||||
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:
|
||||
|
||||
Attribute setters
|
||||
|
||||
@@ -1738,7 +1738,7 @@ typedef struct mjsOrientation_ { // alternative orientation specifiers
|
||||
double euler[3]; // Euler angles
|
||||
} mjsOrientation;
|
||||
typedef struct mjsPlugin_ { // plugin specification
|
||||
mjsElement* instance; // element type
|
||||
mjsElement* element; // element type
|
||||
mjString* name; // name
|
||||
mjString* instance_name; // instance name
|
||||
int plugin_slot; // global registered slot number of the plugin
|
||||
@@ -3622,6 +3622,7 @@ mjsHField* mjs_asHField(mjsElement* element);
|
||||
mjsSkin* mjs_asSkin(mjsElement* element);
|
||||
mjsTexture* mjs_asTexture(mjsElement* element);
|
||||
mjsMaterial* mjs_asMaterial(mjsElement* element);
|
||||
mjsPlugin* mjs_asPlugin(mjsElement* element);
|
||||
void mjs_setBuffer(mjByteVec* dest, const void* array, int size);
|
||||
void mjs_setString(mjString* dest, const char* text);
|
||||
void mjs_setStringVec(mjStringVec* dest, const char* text);
|
||||
|
||||
@@ -181,7 +181,7 @@ typedef struct mjsOrientation_ { // alternative orientation specifiers
|
||||
|
||||
|
||||
typedef struct mjsPlugin_ { // plugin specification
|
||||
mjsElement* instance; // element type
|
||||
mjsElement* element; // element type
|
||||
mjString* name; // name
|
||||
mjString* instance_name; // instance name
|
||||
int plugin_slot; // global registered slot number of the plugin
|
||||
|
||||
@@ -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.
|
||||
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 ---------------------------------------------
|
||||
|
||||
|
||||
@@ -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
|
||||
)),
|
||||
('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',
|
||||
FunctionDecl(
|
||||
name='mjs_setBuffer',
|
||||
|
||||
@@ -8565,7 +8565,7 @@ STRUCTS: Mapping[str, StructDecl] = dict([
|
||||
declname='struct mjsPlugin_',
|
||||
fields=(
|
||||
StructFieldDecl(
|
||||
name='instance',
|
||||
name='element',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsElement'),
|
||||
),
|
||||
|
||||
+15
-3
@@ -274,6 +274,18 @@ PYBIND11_MODULE(_specs, m) {
|
||||
mjSpec.def("detach_body", [](MjSpec& self, raw::MjsBody& 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(
|
||||
"actuators",
|
||||
[](MjSpec& self) -> py::list {
|
||||
@@ -900,12 +912,12 @@ PYBIND11_MODULE(_specs, m) {
|
||||
// ============================= MJSPLUGIN ===================================
|
||||
mjsPlugin.def_property(
|
||||
"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) {
|
||||
self.instance = other->instance;
|
||||
self.element = other->element;
|
||||
});
|
||||
mjsPlugin.def("delete",
|
||||
[](raw::MjsPlugin& self) { mjs_delete(self.instance); });
|
||||
[](raw::MjsPlugin& self) { mjs_delete(self.element); });
|
||||
|
||||
#include "specs.cc.inc"
|
||||
} // PYBIND11_MODULE // NOLINT
|
||||
|
||||
@@ -690,5 +690,32 @@ class SpecsTest(absltest.TestCase):
|
||||
):
|
||||
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__':
|
||||
absltest.main()
|
||||
|
||||
+12
-2
@@ -471,7 +471,7 @@ mjsKey* mjs_addKey(mjSpec* s) {
|
||||
mjsPlugin* mjs_addPlugin(mjSpec* s) {
|
||||
mjCModel* modelC = static_cast<mjCModel*>(s->element);
|
||||
mjCPlugin* plugin = modelC->AddPlugin();
|
||||
plugin->spec.instance = static_cast<mjsElement*>(plugin);
|
||||
plugin->spec.element = static_cast<mjsElement*>(plugin);
|
||||
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
|
||||
void mjs_setBuffer(mjByteVec* dest, const void* array, int size) {
|
||||
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
|
||||
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 =
|
||||
reinterpret_cast<std::map<std::string, std::string, std::less<>>*>(attributes);
|
||||
pluginC->config_attribs = std::move(*config_attribs);
|
||||
|
||||
@@ -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.
|
||||
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 ---------------------------------------------
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz)
|
||||
// overwrite plugin name
|
||||
if (plugin_instance_name.empty() && plugin.active) {
|
||||
plugin_instance_name = "composite" + prefix;
|
||||
(static_cast<mjCPlugin*>(plugin.instance))->name = plugin_instance_name;
|
||||
(static_cast<mjCPlugin*>(plugin.element))->name = plugin_instance_name;
|
||||
}
|
||||
|
||||
// dispatch
|
||||
@@ -714,7 +714,7 @@ mjsBody* mjCComposite::AddCableBody(mjCModel* model, mjsBody* body, int ix,
|
||||
if (plugin.active) {
|
||||
mjsPlugin* pplugin = &body->plugin;
|
||||
pplugin->active = true;
|
||||
pplugin->instance = plugin.instance;
|
||||
pplugin->element = plugin.element;
|
||||
mjs_setString(pplugin->name, mjs_getString(plugin.name));
|
||||
mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
|
||||
}
|
||||
|
||||
@@ -422,7 +422,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
|
||||
// overwrite plugin name
|
||||
if (plugin.active && plugin_instance_name.empty()) {
|
||||
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
|
||||
@@ -440,7 +440,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
|
||||
if (plugin.active) {
|
||||
mjsPlugin* pplugin = &body->plugin;
|
||||
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->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) {
|
||||
mjsPlugin* pplugin = &pb->plugin;
|
||||
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->instance_name, plugin_instance_name.c_str());
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ void mjCMesh::CopyFromSpec() {
|
||||
facetexcoord_ = spec_facetexcoord_;
|
||||
maxhullvert_ = spec.maxhullvert;
|
||||
plugin.active = spec.plugin.active;
|
||||
plugin.instance = spec.plugin.instance;
|
||||
plugin.element = spec.plugin.element;
|
||||
plugin.name = spec.plugin.name;
|
||||
plugin.instance_name = spec.plugin.instance_name;
|
||||
|
||||
@@ -270,7 +270,7 @@ mjCMesh::~mjCMesh() {
|
||||
if (center_) mju_free(center_);
|
||||
if (graph_) mju_free(graph_);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
plugin.instance = plugin_instance;
|
||||
plugin.element = plugin_instance;
|
||||
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
|
||||
if (!(pplugin->capabilityflags & mjPLUGIN_SDF)) {
|
||||
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_);
|
||||
|
||||
for (const auto& vbodyid : vertbodyid) {
|
||||
if (model->Bodies()[vbodyid]->plugin.instance) {
|
||||
if (model->Bodies()[vbodyid]->plugin.element) {
|
||||
mjCPlugin* plugin_instance =
|
||||
static_cast<mjCPlugin*>(model->Bodies()[vbodyid]->plugin.instance);
|
||||
static_cast<mjCPlugin*>(model->Bodies()[vbodyid]->plugin.element);
|
||||
if (damping > 0) {
|
||||
plugin_instance->config_attribs["damping"] = std::to_string(damping);
|
||||
}
|
||||
|
||||
@@ -938,6 +938,8 @@ mjsElement* mjCModel::NextObject(mjsElement* object, mjtObj type) {
|
||||
return GetNext(textures_, object);
|
||||
case mjOBJ_MATERIAL:
|
||||
return GetNext(materials_, object);
|
||||
case mjOBJ_PLUGIN:
|
||||
return GetNext(plugins_, object);
|
||||
default:
|
||||
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);
|
||||
for (int i = 0; i < nu; ++i) {
|
||||
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;
|
||||
plugin_to_actuators[actuator_plugin].push_back(i);
|
||||
} else {
|
||||
@@ -3942,7 +3944,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
|
||||
|
||||
for (int i = 0; i < nbody; ++i) {
|
||||
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 {
|
||||
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) {
|
||||
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 {
|
||||
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);
|
||||
for (int i = 0; i < nsensor; ++i) {
|
||||
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;
|
||||
plugin_to_sensors[sensor_plugin].push_back(i);
|
||||
} else {
|
||||
|
||||
+16
-16
@@ -959,7 +959,7 @@ void mjCBody::CopyFromSpec() {
|
||||
*static_cast<mjsBody*>(this) = spec;
|
||||
userdata_ = spec_userdata_;
|
||||
plugin.active = spec.plugin.active;
|
||||
plugin.instance = spec.plugin.instance;
|
||||
plugin.element = spec.plugin.element;
|
||||
plugin.name = spec.plugin.name;
|
||||
plugin.instance_name = spec.plugin.instance_name;
|
||||
}
|
||||
@@ -986,7 +986,7 @@ mjCBody::~mjCBody() {
|
||||
lights.clear();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
plugin.instance = plugin_instance;
|
||||
plugin.element = plugin_instance;
|
||||
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
|
||||
if (!(pplugin->capabilityflags & mjPLUGIN_PASSIVE)) {
|
||||
throw mjCError(this, "plugin '%s' does not support passive forces", pplugin->name);
|
||||
@@ -2132,7 +2132,7 @@ mjCGeom::mjCGeom(const mjCGeom& other) {
|
||||
|
||||
mjCGeom::~mjCGeom() {
|
||||
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_;
|
||||
material_ = spec_material_;
|
||||
plugin.active = spec.plugin.active;
|
||||
plugin.instance = spec.plugin.instance;
|
||||
plugin.element = spec.plugin.element;
|
||||
plugin.name = spec.plugin.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");
|
||||
}
|
||||
|
||||
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);
|
||||
plugin.instance = plugin_instance;
|
||||
plugin.element = plugin_instance;
|
||||
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
|
||||
if (!(pplugin->capabilityflags & mjPLUGIN_SDF)) {
|
||||
throw mjCError(this, "plugin '%s' does not support sign distance fields", pplugin->name);
|
||||
@@ -5554,7 +5554,7 @@ mjCActuator::mjCActuator(const mjCActuator& other) {
|
||||
|
||||
mjCActuator::~mjCActuator() {
|
||||
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_;
|
||||
slidersite_ = spec_slidersite_;
|
||||
plugin.active = spec.plugin.active;
|
||||
plugin.instance = spec.plugin.instance;
|
||||
plugin.element = spec.plugin.element;
|
||||
plugin.name = spec.plugin.name;
|
||||
plugin.instance_name = spec.plugin.instance_name;
|
||||
}
|
||||
@@ -5869,9 +5869,9 @@ void mjCActuator::Compile(void) {
|
||||
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);
|
||||
plugin.instance = plugin_instance;
|
||||
plugin.element = plugin_instance;
|
||||
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
|
||||
if (!(pplugin->capabilityflags & mjPLUGIN_ACTUATOR)) {
|
||||
throw mjCError(this, "plugin '%s' does not support actuators", pplugin->name);
|
||||
@@ -5916,7 +5916,7 @@ mjCSensor::mjCSensor(const mjCSensor& other) {
|
||||
|
||||
mjCSensor::~mjCSensor() {
|
||||
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_;
|
||||
refname_ = spec_refname_;
|
||||
plugin.active = spec.plugin.active;
|
||||
plugin.instance = spec.plugin.instance;
|
||||
plugin.element = spec.plugin.element;
|
||||
plugin.name = spec.plugin.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
|
||||
{
|
||||
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);
|
||||
plugin.instance = plugin_instance;
|
||||
plugin.element = plugin_instance;
|
||||
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
|
||||
if (!(pplugin->capabilityflags & mjPLUGIN_SENSOR)) {
|
||||
throw mjCError(this, "plugin '%s' does not support sensors", pplugin->name);
|
||||
|
||||
@@ -2767,7 +2767,7 @@ void mjXReader::OnePlugin(XMLElement* elem, mjsPlugin* plugin) {
|
||||
mjs_setString(plugin->name, name.c_str());
|
||||
mjs_setString(plugin->instance_name, instance_name.c_str());
|
||||
if (instance_name.empty()) {
|
||||
plugin->instance = mjs_addPlugin(spec)->instance;
|
||||
plugin->element = mjs_addPlugin(spec)->element;
|
||||
ReadPluginConfigs(elem, plugin);
|
||||
} else {
|
||||
spec->hasImplicitPluginElem = true;
|
||||
|
||||
@@ -827,8 +827,8 @@ void mjXWriter::OnePlugin(XMLElement* elem, const mjsPlugin* plugin) {
|
||||
} else {
|
||||
WriteAttrTxt(elem, "plugin", plugin_name);
|
||||
const mjpPlugin* pplugin = mjp_getPluginAtSlot(
|
||||
static_cast<mjCPlugin*>(plugin->instance)->spec.plugin_slot);
|
||||
const char* c = &(static_cast<mjCPlugin*>(plugin->instance)->flattened_attributes[0]);
|
||||
static_cast<mjCPlugin*>(plugin->element)->spec.plugin_slot);
|
||||
const char* c = &(static_cast<mjCPlugin*>(plugin->element)->flattened_attributes[0]);
|
||||
for (int i = 0; i < pplugin->nattribute; ++i) {
|
||||
string value(c);
|
||||
if (!value.empty()) {
|
||||
|
||||
@@ -147,7 +147,7 @@ TEST_F(PluginTest, ActivatePlugin) {
|
||||
// associate plugin to body
|
||||
mjsBody* body = mjs_addBody(mjs_findBody(spec, "world"), 0);
|
||||
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;
|
||||
mjsGeom* geom = mjs_addGeom(body, 0);
|
||||
geom->type = mjGEOM_BOX;
|
||||
@@ -191,7 +191,7 @@ TEST_F(PluginTest, DeletePlugin) {
|
||||
mjsActuator* actuator = mjs_addActuator(spec, 0);
|
||||
mjs_setString(actuator->target, "j1");
|
||||
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->trntype = mjTRN_JOINT;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user