Gazebo | Ignition | Community
Ask Your Question
3

Insert model programmatically and get its model pointer

asked 2014-12-10 12:53:47 -0500

NickDP gravatar image

When running Gazebo as a library, I want to insert a robot model. I have the model as an SDF string (which I converted from a URDF file).

I want to be able to insert this model and get the corresponding ModelPtr. I am able to do this if the world is not running when inserting the model, as follows:

// Assume the world is not running at this point.
std::string modelString; // this contains a valid SDF model
gazebo::physics::ModelPtr insertedModel;

int modelCountBefore = world->GetModelCount();
world->InsertModelString(modelString);
// need to advange the physics engine in order for the model count to increase
world->RunBlocking(1);
if(world->GetModelCount() == modelCountBefore+1)
{
    // sucess
    insertedModel = world->GetModel(modelCountBefore);
}
else
{    
    // failure
}

This works, but it's not necessarily very pretty.

I would like to be able to insert a model into a running world. If the world is already running, the above won't work. The code below inserts a model when the world is already running.

// Assume the world is running at this point.
std::string modelString; // this contains a valid SDF model
gazebo::physics::ModelPtr insertedModel;

world->InsertModelString(result);
// need to wait several iterations until models are loaded into Gazebo
int timer = 0;
while(world->GetModelCount() == modelCountBefore)
{
    gazebo::common::Time::MSleep(100);
    timer++;
    if(timer > 1000)
    {
        break;
    }
}
if(world->GetModelCount() == modelCountBefore+1)
{
    // sucess
    insertedModel = world->GetModel(modelCountBefore);
}
else
{    
    // failure
}

This is even more cumbersome. In addition, I have some severe problems when I insert the model with the second method. The model does not behave as it should at all when I use my controller on it. Sometimes the joints just move around arbitrarily, sometimes the joints appear to be fixed to some wrong locations, which causes the robot's links to fly apart when moving the joints. Sometimes it behaves fine. This behavior is not deterministic, something different happens every time I execute the same identical code.

What is the best way to reliably insert a model into a running simulation and get the corresponding ModelPtr?

edit retag flag offensive close merge delete

Comments

hi, I just want to know if you figured out why you have the non deterministic behavior, because I have the same issue

djou07 gravatar imagedjou07 ( 2015-06-17 13:58:04 -0500 )edit

Unfortunately I no longer have access to the code. But I believe I followed nkoenigs advice below and paused the simulation, then proceeded as in the first code snippet in the OP and then unpaused.

NickDP gravatar imageNickDP ( 2015-06-18 14:29:25 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
1

answered 2014-12-11 12:51:26 -0500

nkoenig gravatar image

Models are inserted into simulation asynchronously. This is done to make Gazebo thread safe. The consequence is that your code will be ugly.

You can subscribe to the ~/model/info topic, which receives msgs::Model messages when models are inserted. This would take advantage of the asynchronous nature of gazebo.

You may want to pause simulation, insert a model, wait for the model to appear, then start simulation again. This would give you more control over the model.

edit flag offensive delete link more

Comments

Thanks. Right now I stop the simulation with gazebo::physics::World::Stop() before inserting the model. Is there an advantage to using SetPaused()?

NickDP gravatar imageNickDP ( 2014-12-11 14:04:44 -0500 )edit
1

Stop actually stops the RunLoop thread, and is usually used when ending simulation. SetPaused is a bit better if you intend to start simulation again.

nkoenig gravatar imagenkoenig ( 2014-12-11 14:11:36 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2014-12-10 12:53:47 -0500

Seen: 2,434 times

Last updated: Dec 11 '14