Gazebo | Ignition | Community
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Hi Matthieu,

First I'm not an expert, I started to work with gazebo one month ago for the same reason as you. I need to run multiple simulations of an arm robot to use reinforcement learning. So basically I asked a similar question here some weeks ago.

I can't answer to your second question even if URDF and SDF look close enough such that you should be able to transform one to another (SDF is actually more complete than URDF). Then for your first question:

  • I made a SDF world file that contains a simple arm robot model and some basic objects. In this file I link the arm to a ModelPlugin and the world to a WorldPlugin. To do so, the tutorials of gazebo are clear and straight forward.

  • In the ModelController, which is a C++ class, I use a class called JointController, you can find the class reference but impossible to find any example on the web. To move a joint you can then use a PID, it would be something like this (in this case I make a pointer to the JointController as a property of the RobotControl class to be able to call it at each iteration):


#include <boost/bind.hpp>
#include <gazebo/gazebo.hh>
#include <gazebo/physics/physics.hh>
#include <gazebo/common/common.hh>
#include <stdio.h>
#include <math.h>

namespace gazebo
{
  class RobotControl : public ModelPlugin
  {
    // Pointer to the model
    private: physics::ModelPtr model;

    // Pointer to the world
    private: physics::WorldPtr world;

    // Pointer to the update event connection
    private: event::ConnectionPtr updateConnection;

    private: physics::JointControllerPtr jointsController;

    // When the simulation starts
    public: void Load(physics::ModelPtr _parent, sdf::ElementPtr /*_sdf*/)
    {
      // Store the pointer to the model
      this->model = _parent;
      // Store the world
      this->world = this->model->GetWorld();
      // Create the joint controller
      this->jointsController =  boost::shared_ptr<physics::jointcontroller>(new physics::JointController(this->model));
      // Create a PID
      common::PID PID = common::PID(100, 100, 100, 1, -1, 1000, -1000);         
      // Get all the joints of the model
      std::vector<physics::jointptr> joints = this->model->GetJoints();
      // For each one of these joints
      for (unsigned i=0; i < joints.size(); i++) 
      {
        // Add it to the joint controller
        this->jointsController->AddJoint(joints[i]);
        // Set its PID values
        this->jointsController->SetPositionPID(joints[i]->GetScopedName(),PID); 
      }
      // Listen to the update event. This event is broadcast every
      // simulation iteration.
      this->updateConnection = event::Events::ConnectWorldUpdateBegin(boost::bind(&ArmControl::OnUpdate, this, _1));
    }

    // Called at each update of the simulation
    public: void OnUpdate(const common::UpdateInfo & /*_info*/)
    {
       // Set an angle (here it is stupid since the angle doesn't change)
      float angle = 0.5 // gradient angle
      this->jointsController->SetPositionTarget(this->model->GetJoint("jointName")->GetScopedName(),angle);
    }
  };
  // Register this plugin with the simulator
  GZ_REGISTER_MODEL_PLUGIN(RobotControl)
}
  • The WorldPlugin is usefull to add/remove objects in your simulation, or access/change the properties of the simulation.

I hope this helps.

Cheers

Hi Matthieu,

First I'm not an expert, I started to work with gazebo one month ago for the same reason as you. I need to run multiple simulations of an arm robot to use reinforcement learning. So basically I asked a similar question here some weeks ago.

I can't answer to your second question even if URDF and SDF look close enough such that you should be able to transform one to another (SDF is actually more complete than URDF). Then for your first question:

  • I made a SDF world file that contains a simple arm robot model and some basic objects. In this file I link the arm to a ModelPlugin and the world to a WorldPlugin. To do so, the tutorials of gazebo are clear and straight forward.

  • In the ModelController, which is a C++ class, I use a class called JointController, you can find the class reference but impossible to find any example on the web. To move a joint you can then use a PID, it would be something like this (in this case I make a pointer to the JointController as a property of the RobotControl class to be able to call it at each iteration):


#include <boost/bind.hpp>
#include <gazebo/gazebo.hh>
#include <gazebo/physics/physics.hh>
#include <gazebo/common/common.hh>
#include <stdio.h>
#include <math.h>

namespace gazebo
{
  class RobotControl : public ModelPlugin
  {
    // Pointer to the model
    private: physics::ModelPtr model;

    // Pointer to the world
    private: physics::WorldPtr world;

    // Pointer to the update event connection
    private: event::ConnectionPtr updateConnection;

    private: physics::JointControllerPtr jointsController;

    // When the simulation starts
    public: void Load(physics::ModelPtr _parent, sdf::ElementPtr /*_sdf*/)
    {
      // Store the pointer to the model
      this->model = _parent;
      // Store the world
      this->world = this->model->GetWorld();
      // Create the joint controller
      this->jointsController =  boost::shared_ptr<physics::jointcontroller>(new physics::JointController(this->model));
      // Create a PID
      common::PID PID = common::PID(100, 100, 100, 1, -1, 1000, -1000);         
      // Get all the joints of the model
      std::vector<physics::jointptr> joints = this->model->GetJoints();
      // For each one of these joints
      for (unsigned i=0; i < joints.size(); i++) 
      {
        // Add it to the joint controller
        this->jointsController->AddJoint(joints[i]);
        // Set its PID values
        this->jointsController->SetPositionPID(joints[i]->GetScopedName(),PID); 
      }
      // Listen to the update event. This event is broadcast every
      // simulation iteration.
      this->updateConnection = event::Events::ConnectWorldUpdateBegin(boost::bind(&ArmControl::OnUpdate, this, _1));
    }

    // Called at each update of the simulation
    public: void OnUpdate(const common::UpdateInfo & /*_info*/)
    {
       // Set an angle (here it is stupid since the angle doesn't change)
      float angle = 0.5 // gradient angle
      this->jointsController->SetPositionTarget(this->model->GetJoint("jointName")->GetScopedName(),angle);
    }
  };
  // Register this plugin with the simulator
  GZ_REGISTER_MODEL_PLUGIN(RobotControl)
}
  • The WorldPlugin is usefull to add/remove objects in your simulation, or access/change the properties of the simulation.

I hope this helps.

Cheers

Hi Matthieu,

First I'm not an expert, I started to work with gazebo one month ago for the same reason as you. I need to run multiple simulations of an arm robot to use reinforcement learning. So basically I asked a similar question here some weeks ago.

I can't answer to your second question even if URDF and SDF look close enough such that you should be able to transform one to another (SDF is actually more complete than URDF). Then for your first question:

  • I made a SDF world file that contains a simple arm robot model and some basic objects. In this file I link the arm to a ModelPlugin and the world to a WorldPlugin. To do so, the tutorials of gazebo are clear and straight forward.

  • In the ModelController, which is a C++ class, I use a class called JointController, you can find the class reference but impossible to find any example on the web. To move a joint you can then use a PID, it would be something like this (in this case I make a pointer to the JointController as a property of the RobotControl class to be able to call it at each iteration):


#include <boost/bind.hpp>
#include <gazebo/gazebo.hh>
#include <gazebo/physics/physics.hh>
#include <gazebo/common/common.hh>
#include <stdio.h>
#include <math.h>

namespace gazebo
{
  class RobotControl : public ModelPlugin
  {
    // Pointer to the model
    private: physics::ModelPtr model;

    // Pointer to the world
    private: physics::WorldPtr world;

    // Pointer to the update event connection
    private: event::ConnectionPtr updateConnection;

    private: physics::JointControllerPtr jointsController;

    // When the simulation starts
    public: void Load(physics::ModelPtr _parent, sdf::ElementPtr /*_sdf*/)
    {
      // Store the pointer to the model
      this->model = _parent;
      // Store the world
      this->world = this->model->GetWorld();
      // Create the joint controller
      this->jointsController =  boost::shared_ptr<physics::jointcontroller>(new physics::JointController(this->model));
      // Create a PID
      common::PID PID = common::PID(100, 100, 100, 1, -1, 1000, -1000);         
      // Get all the joints of the model
      std::vector<physics::jointptr> joints = this->model->GetJoints();
      // For each one of these joints
      for (unsigned i=0; i < joints.size(); i++) 
      {
        // Add it to the joint controller
        this->jointsController->AddJoint(joints[i]);
        // Set its PID values
        this->jointsController->SetPositionPID(joints[i]->GetScopedName(),PID); 
      }
      // Listen to the update event. This event is broadcast every
      // simulation iteration.
      this->updateConnection = event::Events::ConnectWorldUpdateBegin(boost::bind(&ArmControl::OnUpdate, this, _1));
    }

    // Called at each update of the simulation
    public: void OnUpdate(const common::UpdateInfo & /*_info*/)
    {
       // Set an angle (here it is stupid since the angle doesn't change)
      float angle = 0.5 // gradient angle
      this->jointsController->SetPositionTarget(this->model->GetJoint("jointName")->GetScopedName(),angle);
    }
  };
  // Register this plugin with the simulator
  GZ_REGISTER_MODEL_PLUGIN(RobotControl)
}

The WorldPlugin is usefull useful to add/remove objects in your simulation, or access/change the properties of the simulation.

I hope this helps.

Cheers