In this post, you will learn how to create Gazebo plugins by creating a more complex one integrated with ROS subscribers, to make an EarthQuake plugin. This is the second part of the response to the question posted on Gazebo Answers.
Before following this post, please ensure you have read and implemented the previous post, which created a simple plugin that merely printed “Hello World!” This post assumes you have read the first post. Let’s go!
Step 1: Add the source code for the new Gazebo plugin: EarthQuake
Create a new file in the src folder of the example_plugins_gazebo package.
cd ~/catkin_ws/src/example_plugins_gazebo/src
touch earthquake.cc
Now paste the following source code into the earthquake.cc file. Please read the explanations within the code.
#include <functional>
#include <gazebo/gazebo.hh>
#include <gazebo/physics/physics.hh>
#include <gazebo/common/common.hh>
#include <ignition/math/Vector3.hh>
#include <thread>
#include "ros/ros.h"
#include "ros/callback_queue.h"
#include "ros/subscribe_options.h"
#include "std_msgs/Float32.h"
#include <gazebo/transport/transport.hh>
#include <gazebo/msgs/msgs.hh>
namespace gazebo
{
class ModelQuake : public ModelPlugin
{
public: void Load(physics::ModelPtr _parent, sdf::ElementPtr /*_sdf*/)
{
// Store the pointer to the model
this->model = _parent;
// Listen to the update event. This event is broadcast every
// simulation iteration.
this->updateConnection = event::Events::ConnectWorldUpdateBegin(
std::bind(&ModelQuake::OnUpdate, this));
this->old_secs =ros::Time::now().toSec();
// Create a topic name
std::string earthquake_freq_topicName = "/earthquake_freq";
std::string earthquake_magnitud_topicName = "/earthquake_magnitud";
// Initialize ros, if it has not already bee initialized.
if (!ros::isInitialized())
{
int argc = 0;
char **argv = NULL;
ros::init(argc, argv, "earthquake_rosnode",
ros::init_options::NoSigintHandler);
}
// Create our ROS node. This acts in a similar manner to
// the Gazebo node
this->rosNode.reset(new ros::NodeHandle("earthquake_rosnode"));
// Freq
ros::SubscribeOptions so =
ros::SubscribeOptions::create<std_msgs::Float32>(
earthquake_freq_topicName,
1,
boost::bind(&ModelQuake::OnRosMsg, this, _1),
ros::VoidPtr(), &this->rosQueue);
this->rosSub = this->rosNode->subscribe(so);
// Spin up the queue helper thread.
this->rosQueueThread =
std::thread(std::bind(&ModelQuake::QueueThread, this));
// Magnitude
ros::SubscribeOptions so2 =
ros::SubscribeOptions::create<std_msgs::Float32>(
earthquake_magnitud_topicName,
1,
boost::bind(&ModelQuake::OnRosMsg_Magn, this, _1),
ros::VoidPtr(), &this->rosQueue2);
this->rosSub2 = this->rosNode->subscribe(so2);
// Spin up the queue helper thread.
this->rosQueueThread2 =
std::thread(std::bind(&ModelQuake::QueueThread2, this));
ROS_WARN("Loaded ModelQuake Plugin with parent...%s, only X Axis Freq Supported in this V-1.0", this->model->GetName().c_str());
}
// Called by the world update start event
public: void OnUpdate()
{
double new_secs =ros::Time::now().toSec();
double delta = new_secs - this->old_secs;
double max_delta = 0.0;
if (this->x_axis_freq != 0.0)
{
max_delta = 1.0 / this->x_axis_freq;
}
double magnitude_speed = this->x_axis_magn;
if (delta > max_delta && delta != 0.0)
{
// We change Direction
this->direction = this->direction * -1;
this->old_secs = new_secs;
ROS_DEBUG("Change Direction...");
}
double speed = magnitude_speed * this->direction;
// Apply a small linear velocity to the model.
this->model->SetLinearVel(ignition::math::Vector3d(speed, 0, 0));
this->model->SetAngularVel(ignition::math::Vector3d(0, 0, 0));
}
public: void SetFrequency(const double &_freq)
{
this->x_axis_freq = _freq;
ROS_WARN("x_axis_freq >> %f", this->x_axis_freq);
}
public: void SetMagnitude(const double &_magn)
{
this->x_axis_magn = _magn;
ROS_WARN("x_axis_magn >> %f", this->x_axis_magn);
}
public: void OnRosMsg(const std_msgs::Float32ConstPtr &_msg)
{
this->SetFrequency(_msg->data);
}
/// \brief ROS helper function that processes messages
private: void QueueThread()
{
static const double timeout = 0.01;
while (this->rosNode->ok())
{
this->rosQueue.callAvailable(ros::WallDuration(timeout));
}
}
public: void OnRosMsg_Magn(const std_msgs::Float32ConstPtr &_msg)
{
this->SetMagnitude(_msg->data);
}
/// \brief ROS helper function that processes messages
private: void QueueThread2()
{
static const double timeout = 0.01;
while (this->rosNode->ok())
{
this->rosQueue2.callAvailable(ros::WallDuration(timeout));
}
}
// Pointer to the model
private: physics::ModelPtr model;
// Pointer to the update event connection
private: event::ConnectionPtr updateConnection;
// Time Memory
double old_secs;
// Direction Value
int direction = 1;
// Frequency of earthquake
double x_axis_freq = 1.0;
// Magnitude of the Oscilations
double x_axis_magn = 1.0;
/// \brief A node use for ROS transport
private: std::unique_ptr<ros::NodeHandle> rosNode;
/// \brief A ROS subscriber
private: ros::Subscriber rosSub;
/// \brief A ROS callbackqueue that helps process messages
private: ros::CallbackQueue rosQueue;
/// \brief A thread the keeps running the rosQueue
private: std::thread rosQueueThread;
/// \brief A ROS subscriber
private: ros::Subscriber rosSub2;
/// \brief A ROS callbackqueue that helps process messages
private: ros::CallbackQueue rosQueue2;
/// \brief A thread the keeps running the rosQueue
private: std::thread rosQueueThread2;
};
// Register this plugin with the simulator
GZ_REGISTER_MODEL_PLUGIN(ModelQuake)
}
Add the new source to your CMakeLists.txt file so that it now looks like this:
cmake_minimum_required(VERSION 2.8.3)
project(example_plugins_gazebo)
## Add support for C++11, supported in ROS Kinetic and newer
add_definitions(-std=c++11)
# Load catkin and all dependencies required for this package
find_package(catkin REQUIRED COMPONENTS
roscpp
gazebo_ros
)
# Depend on system install of Gazebo
find_package(gazebo REQUIRED)
link_directories(${GAZEBO_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIR} ${catkin_INCLUDE_DIRS} ${GAZEBO_INCLUDE_DIRS})
# For tc_simple_world_plugin plugin
add_library(simple_world_plugin src/simple_world_plugin.cpp)
target_link_libraries(simple_world_plugin ${catkin_LIBRARIES} ${GAZEBO_LIBRARIES})
# For earthquake_plugin plugin
add_library(earthquake src/earthquake.cc)
target_link_libraries(earthquake ${catkin_LIBRARIES} ${GAZEBO_LIBRARIES})
catkin_package(
DEPENDS
roscpp
gazebo_ros
)
Step 2: Create a new world that will use the Gazebo plugin file we just created
Open a web shell and run the following commands to create the package. When creating Gazebo plugins, you need, at a minimum, the roscpp and gazebo_ros dependencies.
cd ~/catkin_ws/src/example_plugins_gazebo/worlds
touch earthquake.world
Now you should see some yellow warning printed in the terminal and a green plane with an ash-colored box on it. What – is the plane moving? Yes, it’s having an earthquake!
But that’s not all! Do you remember the two topics defined in the plugin code? We can publish to them and change the “course of history”. Try these on two new terminals and see what happens (keep the roslaunch command running).
cd ~/catkin_ws
source devel/setup.bash
rostopic pub /earthquake_freq std_msgs/Float32 "data: 2.0"
cd ~/catkin_ws
source devel/setup.bash
rostopic pub /earthquake_magnitud std_msgs/Float32 "data: 3.0"
What happened there? Can you save the situation and stop the earthquake?
Step 4: Check your learning
Do you understand how to create Gazebo plugins? If you don’t know it yet, please go over the post again, more carefully this time.
Here are the links to the resources used in this tutorial:
(Extra) Step 5: Watch the video to understand how to create Gazebo plugins
Here you go:
Feedback
Did you like this post? Do you have any questions about how to create Gazebo plugins? Please leave a comment in the comments section below, so we can interact and learn from each other.
If you want to learn about other ROS topics, please let us know in the comments area and we will do a video or post about it.
In this post, you will learn how to create Gazebo plugins by making the Gazebo plugin tutorial, Hello World, compile and work in a ROS package. This is a response to the question posted on Gazebo Answers.
Step 1: Fire up a system with ROS installation
“Hey, do you mean I have to install ros2 first?” Absolutely not! Just log in to The Construct to get access to virtual machines pre-installed with ROS.
Once logged in, click on My Rosjects, then Create a New Rosject, supply the information as shown in the image below, and click Create. Then RUN the rosject.
You might also want to try this on a local PC if you have ROS installed. However, please note that we cannot support local PCs and you will have to fix any errors you run into on your own. The rest of the instruction assumes that you are working on The Construct; please adapt them to your local PC and ROS installation.
PS: We are using ROS Kinetic here, but you should be able to use any ROS 1 distro.
Step 2: Create a new package that we’ll use to demonstrate creating Gazebo plugins
Open a web shell and run the following commands to create the package. When creating Gazebo plugins, you need, at a minimum, the roscpp and gazebo_ros dependencies.
cd catkin_ws/src
source /opt/ros/kinetic/setup.bash
catkin_create_pkg example_plugins_gazebo roscpp gazebo_ros
Create a new C++ file in the package you just created:
cd example_plugins_gazebo/src
touch simple_world_plugin.cpp
Now head over to the Code Editor to make changes to the C++ file. Check the image below for how to open the Code Editor.
Locate the C++ file in the code editor: catkin_ws > src > example_plugins_gazebo > src > simple_world_plugin.cpp and paste in the following code.
#include <gazebo/common/Plugin.hh>
#include <ros/ros.h>
namespace gazebo
{
class WorldPluginTutorial : public WorldPlugin
{
public:
WorldPluginTutorial() : WorldPlugin()
{
}
void Load(physics::WorldPtr _world, sdf::ElementPtr _sdf)
{
// Make sure the ROS node for Gazebo has already been initialized
if (!ros::isInitialized())
{
ROS_FATAL_STREAM("A ROS node for Gazebo has not been initialized, unable to load plugin. "
<< "Load the Gazebo system plugin 'libgazebo_ros_api_plugin.so' in the gazebo_ros package)");
return;
}
ROS_WARN("Hello World!");
}
};
GZ_REGISTER_WORLD_PLUGIN(WorldPluginTutorial)
}
Next, replace the package’s CMakeLists.txt with the following:
cmake_minimum_required(VERSION 2.8.3)
project(example_plugins_gazebo)
## Add support for C++11, supported in ROS Kinetic and newer
add_definitions(-std=c++11)
# Load catkin and all dependencies required for this package
find_package(catkin REQUIRED COMPONENTS
roscpp
gazebo_ros
)
# Depend on system install of Gazebo
find_package(gazebo REQUIRED)
link_directories(${GAZEBO_LIBRARY_DIRS})
include_directories(${Boost_INCLUDE_DIR} ${catkin_INCLUDE_DIRS} ${GAZEBO_INCLUDE_DIRS})
# For tc_simple_world_plugin plugin
add_library(simple_world_plugin src/simple_world_plugin.cpp)
target_link_libraries(simple_world_plugin ${catkin_LIBRARIES} ${GAZEBO_LIBRARIES})
catkin_package(
DEPENDS
roscpp
gazebo_ros
)
Also, replace the package.xml file content with the following:
But, wait…how did we know the right filename to use in the line highlighted in the world file? It is by convention named lib{name_of_cpp_executable}.so, and we should find it in ~/catkin_ws/src/devel/lib/
cd ~/catkin_ws/devel/lib/
ls
That covered, we move. Now we’ll create a launch file to launch our world with the Gazebo plugin.
cd ~/catkin_ws/src/example_plugins_gazebo
mkdir -p launch
cd launch
touch simple_world.launch
Open the simple_world.launch file in the code editor and paste in the following content.
(Extra) Step 5: Watch the video to understand how to create Gazebo plugins
Here you go:
Feedback
Did you like this post? Do you have any questions about how to create Gazebo plugins? Please leave a comment in the comments section below, so we can interact and learn from each other.
If you want to learn about other ROS topics, please let us know in the comments area and we will do a video or post about it.
In this video, we are going to see how can we launch multiple robots in a single Gazebo simulation.
We will be introduced to the concept of namespace and tf_prefix, which are essential to make sure that the robots will be able to work correctly. We will create a series of launch files that will enable us to easily add robots into our Gazebo simulation.
NOTICE: most of the code would be the same in the ROS Answer, however, we’ll make some change to make sure it is compatible with ROS kinetic. Please use the code below.
Step 1. Create a project in ROS Development Studio(ROSDS)
ROSDS helps you follow our tutorial in a fast pace without dealing without setting up an environment locally. If you haven’t had an account yet, you can create a free account here.
Step 2. Create a package
We’ll create a package to put our source code for the project with the following command
cd ~/catkin_ws/src
catkin_create_pkg multi_robot rospy gazebo_ros
Then we’ll create a folder called launch under the package directory and create 3 launch files that we need.
<launch>
<arg name="robot_name"/>
<arg name="init_pose"/>
<node name="spawn_minibot_model" pkg="gazebo_ros" type="spawn_model"
args="$(arg init_pose) -urdf -param /robot_description -model $(arg robot_name)"
respawn="false" output="screen" />
<node pkg="robot_state_publisher" type="state_publisher"
name="robot_state_publisher" output="screen"/>
<!-- The odometry estimator, throttling, fake laser etc. go here -->
<!-- All the stuff as from usual robot launch file -->
</launch>
This launch file will launch one robot in the simulation.
<launch>
<!-- No namespace here as we will share this description.
Access with slash at the beginning -->
<param name="robot_description"
command="$(find xacro)/xacro.py $(find turtlebot_description)/robots/kobuki_hexagons_asus_xtion_pro.urdf.xacro" />
<!-- BEGIN ROBOT 1-->
<group ns="robot1">
<param name="tf_prefix" value="robot1_tf" />
<include file="$(find multi_robot)/launch/one_robot.launch" >
<arg name="init_pose" value="-x 1 -y 1 -z 0" />
<arg name="robot_name" value="Robot1" />
</include>
</group>
<!-- BEGIN ROBOT 2-->
<group ns="robot2">
<param name="tf_prefix" value="robot2_tf" />
<include file="$(find multi_robot)/launch/one_robot.launch" >
<arg name="init_pose" value="-x -1 -y 1 -z 0" />
<arg name="robot_name" value="Robot2" />
</include>
</group>
</launch>
Please notice that it should have a different namespace and tf_prefix for each robot.
You can launch the simulation with the following command
roslaunch multi_robot main.launch
Then you have to open the gazebo window from Tools->Gazebo
You should see 2 robots are spawned in the simulation. You can spawn more by changing the robots.launch if you want.
Step 3. Move the robot
Open another terminal, if you type rostopic list , you’ll see there are 2 cmd_vel topics for the robots. The simplest way to control them is with the teleop_twist. We can run it and remap the cmd_vel with the robot you want to control. For example
—
Feedback
—
Did you like this video? Do you have questions about what is explained? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.
If you want to learn about other ROS topics, please let us know on the comments area and we will do a video about it.
In this ROS LIVE-Class we’re going to create a world in the Gazebo simulator for the previous differential drive manipulator we created in the previous class, so the robot can navigate around and interact with the objects.
The model of the robot was created using URDF. However, the model of the environment will be created using SDF.
We will see: ▸ How to create the world for the robot using SDF ▸ How to add models of any object you may think of ▸ How to spawn ROS based robots in the world
Part 1
Part 2
Every Wednesday at 18:00 CET/CEST.
This is a LIVE Class on how to develop with ROS. In Live Classes you practice with me at the same time that I explain, with the provided free ROS material.
IMPORTANT: Remember to be on time for the class because at the beginning of the class we will share the code with the attendants.
IMPORTANT 2: in order to start practicing quickly, we are using the ROS Development Studio for doing the practice. You will need a free account to attend the class. Go to http://rds.theconstructsim.com and create an account prior to the class.
Locomotion is one of the most challenging topics in robotics. Creating the hard-coded algorithms and the kinematics models is not an easy task. Therefore, its no surprise that AI has been used to try and make robots learn how to move by themselves. In this project you will learn step by step, how to create a Monopod robot simulation working in Gazebo and then set up everything to use OpenAI-Gym infrastructure. OpenAI-Gym allows you to separate learning algorithms from the physical/simulated robot, so that you can test different learning algorithms easily. It also allows you to compare your results with other people in the same conditions.
Part 1
In this first video of a new ROS Development Studio video series, you are going to learn step by step
how to create your own hopper simulation, and may be a real version if there is high support to this videos.
You will learn in this video how to create your ROS packages, modify a URDF given by Alexander W. Winkler, https://github.com/leggedrobotics/xpp to give it control and physics and add all the needed sensors like IMU, odometry and contact sensor.
Here are the steps to create the hopper robot as shown in the video:
Step 1
Head to Robot Development Studio and create a new project.
Provide a suitable project name and some useful description.
Open the project (this will take few seconds)
Once the project is loaded run the IDE from the tools menu. Also verify that the initial directory structure should look like following:
Note that we use simulation_ws to contain all the files related to simulations. Those files not related to simulations will go to catkin_ws (like python scripts, launch files etc)
Step 2
Now we create two catkin packages with names my_legged_robots_description and my_legged_robots_sims. We will add rospy as dependency for both of them.
Start a SHELL from tools menu and navigate to ~simulation_ws/src directory as follows
$ cd simulation_ws/src
Now we create the first catkin package with following command
Once the cloning is complete, we should have a new directory with name xpp inside the ~simulation_ws/src directory
This new directory contains the mesh models for various robots such as biped, quadruped etc. We only need the mesh for monoped so we will do following
copy the meshes folder from ~simulation_ws/src/xpp/robots/xpp_hyq/ to ~simulation_ws/src/my_legged_robots_description/ directory
copy the urdf folder from ~simulation_ws/src/xpp/robots/xpp_hyq/ to ~simulation_ws/src/my_legged_robots_sims/ directory
delete the files in ~simulation_ws/src/my_legged_robots_sims/urdf/ directory except the file monoped.urdf
Step 4
Lets analyze the urdf file for the monoped.
Open the monoped.urdf file in the IDE. The file contains 4links and 3joints. Moreover the links have only visual properties which means we can’t yet simulate it. However we can load it in rviz for display.
For simulation ability we need to define inertia and collision properties into the monoped.urdf file.
We will add these properties to the monoped.urdf file. Now before we make any changes, its a good idea that we create a copy of monoped.urdf with name monoped_controlled.urdf
Here is the monoped_controlled.urdf file content after editing
In addition to the inertia and collision tags we have added a few tags.
First is the gazebo tag, this tag is required to simulate the block in gazebo, it contains information about the material hardness (whether the material is easily deformable or not) and friction values (static and dynamic).
The Second tag that was added is a link tag with name lowerleg_contactsensor_link. This link will help us detect the contact with ground in later part of this project.
Another added tag is a joint tag by name lowerleg_contactsensor_link_joint, this combined with previous link tag completes the contact sensor positioning on the robot.
Note : In the above code the values used for various inertia is calculated using inertial_calculator tool ( it is a part of ROS). Moreover, to simplify calculation of inertia of different blocks with different shapes, a bounding box approximation is applied i.e. we compute the inertia with respect to the dimensions of the bounding box. Though such value might not be perfect, it is reasonably good to work with.
Step 5
Now we will simulate this robot.
To do so first we need to create a world file. Create a directory named worlds inside ~simulation_ws/src/my_legged_robots_sims/ directory.
Using the IDE create a file low_gravity.world inside worlds directory. This is our world file. Write the following content to it:
In this file the tag gravity helps us to manipulate the gravity inside the gazebo world.
Next, to launch the world we need to create a launch file main.launch. Before creating this file we create a launch directory inside ~simulation_ws/src/my_legged_robots_sims/ directory.
Using the IDE we add the following code to main.launch file
Notice in line 9 we have provided the name of our world file low_gravity.world.
This launch file will only launch an empty world in gazebo with zero gravity. To launch it click on the Simulation menu and select Select launch file option and choose the main.launch item.
To spawn the monoped we need to create another launch file inside the ~simulation_ws/src/my_legged_robots_sims/launch/ directory.
Use IDE to create a new file named spawn_monoped.launch and add following content:
You should see the monoped load in the gazebo world.
We can change the gravity settings in low_gravity.world file and relaunch the robot to see the effect of gravity. Since we have not actuated the robot the robot will fall under the influence of gravity, which is totally fine. This finishes the steps to create the hopper robot using Robot Development Studio as shown in the video.
Checkout the URDF robot creation course in RobotIgniteAcademy: https://goo.gl/NJHwq3
[irp posts=”8194″ name=”All about Gazebo 9 with ROS”]
Part 2
In this second video of a new ROS Development Studio video series, you are going to continue to learn step by step how to create your own hopper simulation, and may be a real version if there is high support to this videos.