#341 Stage 3 Gripper duplicates the model

open
stage (111)
5
2012-12-16
2010-08-12
Chris
No

In short this is an issue with the current gripper in stage, when it grips something it results in a duplicate of that model appearing in the world as the gripped object is both a child of the world and a child of the gripper.

My testing was done using playerv and everything.cfg, when the gripper is closed an additional model appears very near the origin of the map. This is because the gripper sets the relative pose of the model to (0,0,z-value,0), and it is still a child of the world so it is rendered at that position. This is obviously a reasonably bad error as we have suddenly duplicated the model. (The one at the origin is draggable as well and moving it will move the one within the gripper with respect to the gripper)

This issue arises as hit->SetParent(this) doesn't remove "hit" from the list of the children of the world. In this was SetParent and BecomeParentOf are very different:

int Model::SetParent( Model* newparent)
{
// remove the model from its old parent (if it has one)
if( parent )
EraseAll( this, parent->children );

if( newparent )
newparent->children.push_back( this );

// link from the model to its new parent
this->parent = newparent;

CallCallbacks\( CB\_PARENT \);

return 0; //ok
}

void Model::BecomeParentOf( Model* child )
{
if( child->parent )
child->parent->RemoveChild( child );
else
world->RemoveChild( child );

child->parent = this;

this->AddChild( child );

world->dirty = true;
}

Logically to me these two functions should do the same things (and one should really just call the other with child and parent swapped) however BecomeParentOf will remove the child from the world and set the world as dirty, but not call the callbacks function. There is additional different in the use of AddChild and RemoveChild rather than simply removing or adding the children, and so performing additional things (one of these additional things is very annoying, AddChild changes the token name of the model added to parent.model.x even if the token for that model was specified in the world file)

As a workaround to this for the gripper driver to stop the additional model from appearing when you pick it up adding the command "this->world->RemoveChild(hit);" before "hit->SetParent( this );" (line 457) will stop the model from appearing, and adding "this->world->AddModel(cfg.gripped);" after "cfg.gripped->SetParent( NULL );" (Line 265) will make it reappear - sorry for the lack of diff but I was actually working and testing this on a highly modified gripper like plugin model.

This seems like rather a hack given that the functions I am adding are RemoveChild and AddModel, not RemoveChild and AddChild. However in the WorldGui these are the two functions that call canvas->AddModel and canvas->RemoveModel so they need to be paired in this way I think.

I'm not sure what the fix for this should be (and so haven't actually submitted a patch) however it seems like BecomeParentOf and SetParent should either not both exist, or one should call the other (or if they are to have different functionality it should be commented). And the adding and removal from the world should be handled by that function.

~Chris

Discussion