Gazebo | Ignition | Community
Ask Your Question

Revision history [back]

Hello everyone,

I'm coming back with a solution to the problem mentioned in this post regarding the segmentation fault occurring randomly when calling the function physics::Joint::Detach().

After some investigation, I realized that the segmentation fault occurred when the call to the Detach function was done during an update of the physics engine. In this situation, a joint that was present in the beginning of the iteration of the physics engine is suddenly erased by the call to the Detach function, resulting in a segmentation fault.

To avoid this situation, you can use a workaround that consists in pushing the calls to the Detach function in a list and to execute effectively those Detach just before the physics engine is updated. This can be done using an event of type ConnectBeforePhysicsUpdate. We can hence link a callback function 'OnUpdate' that executes the Detach that are stored in a list, if any, just before the physics engine is updated. By doing so, we make sure that a call to Detach will no longer be executed during an update of the physics engine.

Code:

Add the following variables in the constructor of your class:

std::vector<fixedJoint> vect;
this->detach_vector = vect;
this->beforePhysicsUpdateConnection = Event::Events::ConnectBeforePhysicsUpdate(std::bind(&YourClass::OnUpdate, this));

In your function where you call Detach(), push back those calls in the detach_vector

bool YourClass::detach(std::string model1, std::string link1,
                                     std::string model2, std::string link2)
  {
      // search for the instance of joint and do detach
      fixedJoint j;
      if(this->getJoint(model1, link1, model2, link2, j)){
          this->detach_vector.push_back(j);
          ROS_INFO_STREAM("Detach joint request pushed in the detach vector");
          return true;
      }
    return false;
  }

(the function getJoint just returns the joint between the two links)

Create a callback function "OnUpdate" that will be executed each time just before the physics engine is updated, and where you effectively execute the call to Detach(), if there are any in the detach_vector:

void YourClass::OnUpdate()
  {
    if(!this->detach_vector.empty())
    {
      ROS_INFO_STREAM("Received before physics update callback... Detaching joints");
      std::vector<fixedJoint>::iterator it;
      it = this->detach_vector.begin();
      fixedJoint j;
      while (it != this->detach_vector.end())
      {
        j = *it;
        j.joint->Detach();
        ROS_INFO_STREAM("Joint detached !");
        ++it;
      }
      detach_vector.clear();
    }
  }

Hope this can help.

Best regards.