Raise error when binding to a removed element.
PiperOrigin-RevId: 774462737 Change-Id: I820c0e1c010ae9fbf6d9667c3364d4b65bf21002
This commit is contained in:
committed by
Copybara-Service
parent
419cdf1ff3
commit
a00bfa819c
@@ -3783,15 +3783,6 @@ Attachment
|
|||||||
|
|
||||||
Attach child to a parent, return the attached element if success or NULL otherwise.
|
Attach child to a parent, return the attached element if success or NULL otherwise.
|
||||||
|
|
||||||
.. _mjs_detach:
|
|
||||||
|
|
||||||
`mjs_detach <#mjs_detach>`__
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. mujoco-include:: mjs_detach
|
|
||||||
|
|
||||||
Detach but not delete object corresponding to the given element, return 0 on success.
|
|
||||||
|
|
||||||
.. _AddTreeElements:
|
.. _AddTreeElements:
|
||||||
|
|
||||||
Tree elements
|
Tree elements
|
||||||
|
|||||||
@@ -3411,7 +3411,6 @@ void mju_defaultTask(mjTask* task);
|
|||||||
void mju_taskJoin(mjTask* task);
|
void mju_taskJoin(mjTask* task);
|
||||||
mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
||||||
const char* prefix, const char* suffix);
|
const char* prefix, const char* suffix);
|
||||||
int mjs_detach(mjSpec* spec, mjsElement* element);
|
|
||||||
mjsBody* mjs_addBody(mjsBody* body, const mjsDefault* def);
|
mjsBody* mjs_addBody(mjsBody* body, const mjsDefault* def);
|
||||||
mjsSite* mjs_addSite(mjsBody* body, const mjsDefault* def);
|
mjsSite* mjs_addSite(mjsBody* body, const mjsDefault* def);
|
||||||
mjsJoint* mjs_addJoint(mjsBody* body, const mjsDefault* def);
|
mjsJoint* mjs_addJoint(mjsBody* body, const mjsDefault* def);
|
||||||
|
|||||||
@@ -1411,8 +1411,6 @@ MJAPI void mju_taskJoin(mjTask* task);
|
|||||||
MJAPI mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
MJAPI mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
||||||
const char* prefix, const char* suffix);
|
const char* prefix, const char* suffix);
|
||||||
|
|
||||||
// Detach but not delete object corresponding to the given element, return 0 on success.
|
|
||||||
MJAPI int mjs_detach(mjSpec* spec, mjsElement* element);
|
|
||||||
|
|
||||||
//---------------------------------- Tree elements -------------------------------------------------
|
//---------------------------------- Tree elements -------------------------------------------------
|
||||||
|
|
||||||
@@ -1440,7 +1438,7 @@ MJAPI mjsLight* mjs_addLight(mjsBody* body, const mjsDefault* def);
|
|||||||
// Add frame to body.
|
// Add frame to body.
|
||||||
MJAPI mjsFrame* mjs_addFrame(mjsBody* body, mjsFrame* parentframe);
|
MJAPI mjsFrame* mjs_addFrame(mjsBody* body, mjsFrame* parentframe);
|
||||||
|
|
||||||
// Delete object corresponding to the given element, return 0 on success.
|
// Detach but not delete object corresponding to the given element, return 0 on success.
|
||||||
MJAPI int mjs_delete(mjSpec* spec, mjsElement* element);
|
MJAPI int mjs_delete(mjSpec* spec, mjsElement* element);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -379,6 +379,19 @@ class SupportTest(parameterized.TestCase):
|
|||||||
' 15297169659434471387 != 2785811613804955188',
|
' 15297169659434471387 != 2785811613804955188',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# what happens when we bind to an actuator that was removed?
|
||||||
|
bygone_actuators = []
|
||||||
|
for act in s.actuators:
|
||||||
|
bygone_actuators.append(act)
|
||||||
|
s.delete(act)
|
||||||
|
m = s.compile()
|
||||||
|
d = mujoco.MjData(m)
|
||||||
|
mx = mjx.put_model(m)
|
||||||
|
dx = mjx.put_data(m, d)
|
||||||
|
dx = mjx.step(mx, dx)
|
||||||
|
with self.assertRaisesRegex(KeyError, 'invalid id: -1'):
|
||||||
|
dx.bind(mx, bygone_actuators)
|
||||||
|
|
||||||
_CONTACTS = """
|
_CONTACTS = """
|
||||||
<mujoco>
|
<mujoco>
|
||||||
<worldbody>
|
<worldbody>
|
||||||
|
|||||||
@@ -8987,26 +8987,6 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
|||||||
),
|
),
|
||||||
doc='Attach child to a parent, return the attached element if success or NULL otherwise.', # pylint: disable=line-too-long
|
doc='Attach child to a parent, return the attached element if success or NULL otherwise.', # pylint: disable=line-too-long
|
||||||
)),
|
)),
|
||||||
('mjs_detach',
|
|
||||||
FunctionDecl(
|
|
||||||
name='mjs_detach',
|
|
||||||
return_type=ValueType(name='int'),
|
|
||||||
parameters=(
|
|
||||||
FunctionParameterDecl(
|
|
||||||
name='spec',
|
|
||||||
type=PointerType(
|
|
||||||
inner_type=ValueType(name='mjSpec'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FunctionParameterDecl(
|
|
||||||
name='element',
|
|
||||||
type=PointerType(
|
|
||||||
inner_type=ValueType(name='mjsElement'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
doc='Detach but not delete object corresponding to the given element, return 0 on success.', # pylint: disable=line-too-long
|
|
||||||
)),
|
|
||||||
('mjs_addBody',
|
('mjs_addBody',
|
||||||
FunctionDecl(
|
FunctionDecl(
|
||||||
name='mjs_addBody',
|
name='mjs_addBody',
|
||||||
@@ -9195,7 +9175,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
doc='Delete object corresponding to the given element, return 0 on success.', # pylint: disable=line-too-long
|
doc='Detach but not delete object corresponding to the given element, return 0 on success.', # pylint: disable=line-too-long
|
||||||
)),
|
)),
|
||||||
('mjs_addActuator',
|
('mjs_addActuator',
|
||||||
FunctionDecl(
|
FunctionDecl(
|
||||||
|
|||||||
+2
-25
@@ -341,28 +341,6 @@ int mj_copyBack(mjSpec* s, const mjModel* m) {
|
|||||||
|
|
||||||
|
|
||||||
// detach body from mjSpec, return 0 on success
|
// detach body from mjSpec, return 0 on success
|
||||||
int mjs_detach(mjSpec* s, mjsElement* element) {
|
|
||||||
mjCModel* model = static_cast<mjCModel*>(s->element);
|
|
||||||
if (!element) {
|
|
||||||
model->SetError(mjCError(0, "Element is null."));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (element->elemtype == mjOBJ_DEFAULT) {
|
|
||||||
throw mjCError(0, "Detach is not implemented for defaults.");
|
|
||||||
} else {
|
|
||||||
*model -= element;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} catch (mjCError& e) {
|
|
||||||
model->SetError(e);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// delete object, return 0 on success
|
|
||||||
int mjs_delete(mjSpec* s, mjsElement* element) {
|
int mjs_delete(mjSpec* s, mjsElement* element) {
|
||||||
mjCModel* model = static_cast<mjCModel*>(s->element);
|
mjCModel* model = static_cast<mjCModel*>(s->element);
|
||||||
if (!element) {
|
if (!element) {
|
||||||
@@ -374,8 +352,7 @@ int mjs_delete(mjSpec* s, mjsElement* element) {
|
|||||||
mjCDef* def = static_cast<mjCDef*>(element);
|
mjCDef* def = static_cast<mjCDef*>(element);
|
||||||
*model -= *def;
|
*model -= *def;
|
||||||
} else {
|
} else {
|
||||||
mjs_detach(s, element);
|
*model -= element;
|
||||||
model->DeleteElement(element);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} catch (mjCError& e) {
|
} catch (mjCError& e) {
|
||||||
@@ -1031,7 +1008,7 @@ const char* mjs_resolveOrientation(double quat[4], mjtByte degree, const char* s
|
|||||||
mjsFrame* mjs_bodyToFrame(mjsBody** body) {
|
mjsFrame* mjs_bodyToFrame(mjsBody** body) {
|
||||||
mjCBody* bodyC = static_cast<mjCBody*>((*body)->element);
|
mjCBody* bodyC = static_cast<mjCBody*>((*body)->element);
|
||||||
mjCFrame* frameC = bodyC->ToFrame();
|
mjCFrame* frameC = bodyC->ToFrame();
|
||||||
bodyC->model->DeleteElement((*body)->element);
|
*bodyC->model -= (*body)->element;
|
||||||
*body = nullptr;
|
*body = nullptr;
|
||||||
return &frameC->spec;
|
return &frameC->spec;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -76,8 +76,6 @@ MJAPI int mj_copyBack(mjSpec* s, const mjModel* m);
|
|||||||
MJAPI mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
MJAPI mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
||||||
const char* prefix, const char* suffix);
|
const char* prefix, const char* suffix);
|
||||||
|
|
||||||
// Detach but not delete object corresponding to the given element, return 0 on success.
|
|
||||||
MJAPI int mjs_detach(mjSpec* s, mjsElement* element);
|
|
||||||
|
|
||||||
//---------------------------------- Add tree elements ---------------------------------------------
|
//---------------------------------- Add tree elements ---------------------------------------------
|
||||||
|
|
||||||
@@ -105,7 +103,7 @@ MJAPI mjsLight* mjs_addLight(mjsBody* body, const mjsDefault* def);
|
|||||||
// Add frame to body.
|
// Add frame to body.
|
||||||
MJAPI mjsFrame* mjs_addFrame(mjsBody* body, mjsFrame* parentframe);
|
MJAPI mjsFrame* mjs_addFrame(mjsBody* body, mjsFrame* parentframe);
|
||||||
|
|
||||||
// Delete object corresponding to the given element, return 0 on success.
|
// Detach but not delete object corresponding to the given element, return 0 on success.
|
||||||
MJAPI int mjs_delete(mjSpec* s, mjsElement* element);
|
MJAPI int mjs_delete(mjSpec* s, mjsElement* element);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-12
@@ -746,7 +746,6 @@ void mjCModel::DeleteSubtreePlugin(mjCBody* subtree) {
|
|||||||
mjsPlugin* plugin = &(subtree->spec.plugin);
|
mjsPlugin* plugin = &(subtree->spec.plugin);
|
||||||
if (plugin->active && plugin->name->empty()) {
|
if (plugin->active && plugin->name->empty()) {
|
||||||
*this -= plugin->element;
|
*this -= plugin->element;
|
||||||
detached_.push_back(static_cast<mjCBase*>(plugin->element));
|
|
||||||
}
|
}
|
||||||
for (auto* body : subtree->Bodies()) {
|
for (auto* body : subtree->Bodies()) {
|
||||||
DeleteSubtreePlugin(body);
|
DeleteSubtreePlugin(body);
|
||||||
@@ -755,13 +754,6 @@ void mjCModel::DeleteSubtreePlugin(mjCBody* subtree) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// delete an object from the model
|
|
||||||
void mjCModel::DeleteElement(mjsElement* el) {
|
|
||||||
static_cast<mjCBase*>(el)->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// remove the element from the model
|
// remove the element from the model
|
||||||
void mjCModel::operator-=(mjsElement* el) {
|
void mjCModel::operator-=(mjsElement* el) {
|
||||||
if (el->elemtype == mjOBJ_BODY) {
|
if (el->elemtype == mjOBJ_BODY) {
|
||||||
@@ -769,6 +761,7 @@ void mjCModel::operator-=(mjsElement* el) {
|
|||||||
*this -= *body;
|
*this -= *body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detached_.push_back(static_cast<mjCBase*>(el));
|
||||||
ResetTreeLists();
|
ResetTreeLists();
|
||||||
|
|
||||||
if (el->elemtype != mjOBJ_DEFAULT) {
|
if (el->elemtype != mjOBJ_DEFAULT) {
|
||||||
@@ -800,7 +793,6 @@ void mjCModel::operator-=(mjsElement* el) {
|
|||||||
mjCGeom* geom = static_cast<mjCGeom*>(el);
|
mjCGeom* geom = static_cast<mjCGeom*>(el);
|
||||||
if (geom->plugin.active && geom->plugin.name->empty()) {
|
if (geom->plugin.active && geom->plugin.name->empty()) {
|
||||||
*this -= geom->plugin.element;
|
*this -= geom->plugin.element;
|
||||||
detached_.push_back(static_cast<mjCBase*>(geom->plugin.element));
|
|
||||||
}
|
}
|
||||||
deletefromlist(&(geom->body->geoms), el);
|
deletefromlist(&(geom->body->geoms), el);
|
||||||
break;
|
break;
|
||||||
@@ -827,7 +819,6 @@ void mjCModel::operator-=(mjsElement* el) {
|
|||||||
mjCMesh* mesh = static_cast<mjCMesh*>(el);
|
mjCMesh* mesh = static_cast<mjCMesh*>(el);
|
||||||
if (mesh->plugin.active && mesh->plugin.name->empty()) {
|
if (mesh->plugin.active && mesh->plugin.name->empty()) {
|
||||||
*this -= mesh->plugin.element;
|
*this -= mesh->plugin.element;
|
||||||
detached_.push_back(static_cast<mjCBase*>(mesh->plugin.element));
|
|
||||||
}
|
}
|
||||||
deletefromlist(object_lists_[mjOBJ_MESH], el);
|
deletefromlist(object_lists_[mjOBJ_MESH], el);
|
||||||
break;
|
break;
|
||||||
@@ -838,7 +829,6 @@ void mjCModel::operator-=(mjsElement* el) {
|
|||||||
mjCActuator* actuator = static_cast<mjCActuator*>(el);
|
mjCActuator* actuator = static_cast<mjCActuator*>(el);
|
||||||
if (actuator->plugin.active && actuator->plugin.name->empty()) {
|
if (actuator->plugin.active && actuator->plugin.name->empty()) {
|
||||||
*this -= actuator->plugin.element;
|
*this -= actuator->plugin.element;
|
||||||
detached_.push_back(static_cast<mjCBase*>(actuator->plugin.element));
|
|
||||||
}
|
}
|
||||||
deletefromlist(object_lists_[mjOBJ_ACTUATOR], el);
|
deletefromlist(object_lists_[mjOBJ_ACTUATOR], el);
|
||||||
break;
|
break;
|
||||||
@@ -849,7 +839,6 @@ void mjCModel::operator-=(mjsElement* el) {
|
|||||||
mjCSensor* sensor = static_cast<mjCSensor*>(el);
|
mjCSensor* sensor = static_cast<mjCSensor*>(el);
|
||||||
if (sensor->plugin.active && sensor->plugin.name->empty()) {
|
if (sensor->plugin.active && sensor->plugin.name->empty()) {
|
||||||
*this -= sensor->plugin.element;
|
*this -= sensor->plugin.element;
|
||||||
detached_.push_back(static_cast<mjCBase*>(sensor->plugin.element));
|
|
||||||
}
|
}
|
||||||
deletefromlist(object_lists_[mjOBJ_SENSOR], el);
|
deletefromlist(object_lists_[mjOBJ_SENSOR], el);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -229,9 +229,6 @@ class mjCModel : public mjCModel_, private mjSpec {
|
|||||||
// delete object from the corresponding list
|
// delete object from the corresponding list
|
||||||
void operator-=(mjsElement* el);
|
void operator-=(mjsElement* el);
|
||||||
|
|
||||||
// delete object
|
|
||||||
void DeleteElement(mjsElement* el);
|
|
||||||
|
|
||||||
// delete default and all descendants
|
// delete default and all descendants
|
||||||
void RemoveDefault(mjCDef* def);
|
void RemoveDefault(mjCDef* def);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user