Support nested frames in mjs_attachFrame.

PiperOrigin-RevId: 626001651
Change-Id: I3dc52baa6aad875504dd4c7d969a4091f52c4c16
This commit is contained in:
Alessio Quaglino
2024-04-18 05:35:54 -07:00
committed by Copybara-Service
parent d2392efe6c
commit c331d18a6e
3 changed files with 40 additions and 17 deletions
+20 -3
View File
@@ -739,13 +739,15 @@ mjCBody& mjCBody::operator+=(const mjCFrame& other) {
frames.back()->body = this; frames.back()->body = this;
frames.back()->model = model; frames.back()->model = model;
frames.back()->frame = other.frame; frames.back()->frame = other.frame;
int i = frames.size();
// map input frames to index in this->frames // map input frames to index in this->frames
std::map<mjCFrame*, int> fmap; std::map<mjCFrame*, int> fmap;
for (auto frame : subtree->frames) { for (auto frame : subtree->frames) {
if (frame == static_cast<const mjCFrame*>(&other)) { if (frame == static_cast<const mjCFrame*>(&other)) {
fmap[frame] = frames.size() - 1; fmap[frame] = frames.size() - 1;
break; } else if (other.IsAncestor(frame)) {
fmap[frame] = i++;
} }
} }
@@ -758,7 +760,7 @@ mjCBody& mjCBody::operator+=(const mjCFrame& other) {
CopyList(lights, subtree->lights, fmap, &other); CopyList(lights, subtree->lights, fmap, &other);
for (int i=0; i<subtree->bodies.size(); i++) { for (int i=0; i<subtree->bodies.size(); i++) {
if (subtree->bodies[i]->frame != &other) { if (!other.IsAncestor(subtree->bodies[i]->frame)) {
continue; continue;
} }
bodies.push_back(new mjCBody(*subtree->bodies[i], model)); // triggers recursive call bodies.push_back(new mjCBody(*subtree->bodies[i], model)); // triggers recursive call
@@ -786,7 +788,7 @@ void mjCBody::CopyList(std::vector<T*>& dst, const std::vector<T*>& src,
std::map<mjCFrame*, int>& fmap, const mjCFrame* pframe) { std::map<mjCFrame*, int>& fmap, const mjCFrame* pframe) {
int nsrc = (int)src.size(); int nsrc = (int)src.size();
for (int i=0; i<nsrc; i++) { for (int i=0; i<nsrc; i++) {
if (pframe && src[i]->frame != pframe) { if (pframe && !pframe->IsAncestor(src[i]->frame)) {
continue; // skip if the element is not inside pframe continue; // skip if the element is not inside pframe
} }
dst.push_back(new T(*src[i])); dst.push_back(new T(*src[i]));
@@ -1473,6 +1475,21 @@ mjCFrame& mjCFrame::operator+=(const mjCBody& other) {
// return true if child is descendent of this frame
bool mjCFrame::IsAncestor(const mjCFrame* child) const {
if (!child) {
return false;
}
if (child == this) {
return true;
}
return IsAncestor(child->frame);
}
void mjCFrame::SetParent(mjCBody* _body) { void mjCFrame::SetParent(mjCBody* _body) {
body = _body; body = _body;
} }
+2
View File
@@ -362,6 +362,8 @@ class mjCFrame : public mjCFrame_, private mjsFrame {
mjCFrame& operator+=(const mjCBody& other); mjCFrame& operator+=(const mjCBody& other);
bool IsAncestor(const mjCFrame* child) const; // true if child is contained in this frame
private: private:
mjCFrame(mjCModel* = 0, mjCFrame* = 0); // constructor mjCFrame(mjCModel* = 0, mjCFrame* = 0); // constructor
mjCFrame(const mjCFrame& other); // copy constructor mjCFrame(const mjCFrame& other); // copy constructor
+18 -14
View File
@@ -200,13 +200,15 @@ static constexpr char xml_child[] = R"(
<mujoco> <mujoco>
<worldbody> <worldbody>
<frame name="pframe"> <frame name="pframe">
<body name="body"> <frame name="cframe">
<joint type="hinge" name="hinge"/> <body name="body">
<geom type="cylinder" size=".1 1 0"/> <joint type="hinge" name="hinge"/>
<light mode="targetbody" target="targetbody"/> <geom type="cylinder" size=".1 1 0"/>
<body name="targetbody"/> <light mode="targetbody" target="targetbody"/>
<body/> <body name="targetbody"/>
</body> <body/>
</body>
</frame>
</frame> </frame>
<body name="ignore"/> <body name="ignore"/>
<frame name="frame" pos=".1 0 0" euler="0 90 0"/> <frame name="frame" pos=".1 0 0" euler="0 90 0"/>
@@ -437,13 +439,15 @@ TEST_F(MujocoTest, AttachFrame) {
<geom size=".1"/> <geom size=".1"/>
<frame name="frame" pos=".1 0 0" euler="0 90 0"/> <frame name="frame" pos=".1 0 0" euler="0 90 0"/>
<frame name="pframe"> <frame name="pframe">
<body name="attached-body-1"> <frame name="cframe">
<joint type="hinge" name="attached-hinge-1"/> <body name="attached-body-1">
<geom type="cylinder" size=".1 1 0"/> <joint type="hinge" name="attached-hinge-1"/>
<light mode="targetbody" target="attached-targetbody-1"/> <geom type="cylinder" size=".1 1 0"/>
<body name="attached-targetbody-1"/> <light mode="targetbody" target="attached-targetbody-1"/>
<body/> <body name="attached-targetbody-1"/>
</body> <body/>
</body>
</frame>
</frame> </frame>
</body> </body>
</worldbody> </worldbody>