Add error checking in mjs_setFrame.

Also raise error if the frame is not found in the mjCBody copy constructor.

Fixes #2543.

PiperOrigin-RevId: 742624013
Change-Id: I4999b3165c97f8d079412214d027ca7a8dae8cb3
This commit is contained in:
Alessio Quaglino
2025-04-01 03:33:54 -07:00
committed by Copybara-Service
parent ebd30493c8
commit 86c970bc23
11 changed files with 125 additions and 25 deletions
+9 -3
View File
@@ -758,13 +758,19 @@ mjsFrame* mjs_findFrame(mjSpec* s, const char* name) {
// set frame
void mjs_setFrame(mjsElement* dest, mjsFrame* frame) {
int mjs_setFrame(mjsElement* dest, mjsFrame* frame) {
if (!frame) {
return;
return -1;
}
mjCFrame* frameC = static_cast<mjCFrame*>(frame->element);
mjCBase* baseC = static_cast<mjCBase*>(dest);
baseC->SetFrame(frameC);
try {
baseC->SetFrame(frameC);
return 0;
} catch (mjCError& e) {
baseC->model->SetError(e);
return -1;
}
}
+2 -2
View File
@@ -370,8 +370,8 @@ MJAPI const double* mjs_getDouble(const mjDoubleVec* source, int* size);
// Set element's default.
MJAPI void mjs_setDefault(mjsElement* element, const mjsDefault* def);
// Set element's enlcosing frame.
MJAPI void mjs_setFrame(mjsElement* dest, mjsFrame* frame);
// Set element's enclosing frame, return 0 on success.
MJAPI int mjs_setFrame(mjsElement* dest, mjsFrame* frame);
// Resolve alternative orientations to quat, return error if any.
MJAPI const char* mjs_resolveOrientation(double quat[4], mjtByte degree, const char* sequence,
+15 -2
View File
@@ -773,6 +773,9 @@ void mjCBase::SetFrame(mjCFrame* _frame) {
if (!_frame) {
return;
}
if (_frame->body && GetParent() != _frame->body) {
throw mjCError(this, "Frame and body '%s' have mismatched parents", name.c_str());
}
frame = _frame;
}
@@ -891,8 +894,18 @@ mjCBody& mjCBody::operator+=(const mjCBody& other) {
for (int i=0; i < other.bodies.size(); i++) {
bodies.push_back(new mjCBody(*other.bodies[i], model)); // triggers recursive call
bodies.back()->parent = this;
bodies.back()->frame =
other.bodies[i]->frame ? frames[fmap[other.bodies[i]->frame]] : nullptr;
bodies.back()->frame = nullptr;
if (other.bodies[i]->frame) {
if (fmap.find(other.bodies[i]->frame) != fmap.end()) {
bodies.back()->frame = frames[fmap[other.bodies[i]->frame]];
} else {
throw mjCError(this, "Frame '%s' not found in other body",
other.bodies[i]->frame->name.c_str());
}
if (bodies.back()->frame && bodies.back()->frame->body != this) {
throw mjCError(this, "Frame and body '%s' have mismatched parents", name.c_str());
}
}
}
return *this;
+3
View File
@@ -254,6 +254,9 @@ class mjCBase : public mjCBase_ {
// Copy plugins instantiated in this object
virtual void CopyPlugin() {}
// Returns parent of this object
virtual mjCBase* GetParent() const { return nullptr; }
// Copy assignment
mjCBase& operator=(const mjCBase& other);
+3 -1
View File
@@ -3647,7 +3647,9 @@ void mjXReader::Body(XMLElement* section, mjsBody* body, mjsFrame* frame,
}
} else {
// only set frame to existing body
mjs_setFrame(child->element, pframe);
if (mjs_setFrame(child->element, pframe)) {
throw mjXError(elem, mjs_getError(spec));
}
}
}