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 post, you will learn how to use the Gazebo differential drive plugin in ros 2. This post answers the following question posted on ROS Answers.
Step 1: Copy a sample project with a ROS 2 Gazebo simulation using the differential drive plugin
“Hey, do I have to install ros2 first?” Absolutely not! We will be using The Construct to get access to virtual machines pre-installed with ROS.
Click here to copy the ROS2 TurtleBot3 sandbox project. Once copied, click the red RUN button to launch the project in a virtual machine. Please be patient while the environment loads.
PS: You will need to log in or create an account to copy the packages.
You might also want to try this on a local PC if you have ros2 and some executables 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 post assumes that you are working on The Construct; please adapt them to your local PC and ros2 installation.
Step 2: Find and explore the Gazebo model file containing the differential drive plugin
Now, we will find a Gazebo model file with the differential drive plugin. For this post, we’ll use the turtlebot3_ws/src/turtlebot3_simulations/turtlebot3_gazebo/models/turtlebot3_burger/model.sdf file. Sometimes it’s also defined as a .xacro file.
Head over to the Code Editor to explore this file as well as other files.
Let’s examine the differential drive section of this plugin file and compare it with the one on the ROS Answers post.
On lines 385 and 392, we see entries for the /cmd_vel (<command_topic>cmd_vel</command_topic>) and /odom (<odometry_topic>odom</odometry_topic>) topics respectively. However, these entries are missing in the file on ROS Answers.
Well, the topics are there, but are they working? Let’s publish to the /cmd_vel topic and see if the robot moves. We also echo the /odom in another terminal. Run the following in Terminal 2:
# Try to move the robot with teleop
ros2 run teleop_twist_keyboard teleop_twist_keyboard
Then in Terminal 3:
ros2 topic echo /odom
The robot didn’t move and nothing was echoing from /odom!
Now we need to confirm that it’s not working because of those tags. Let’s modify the launch command in Terminal 1. Press Ctrl + C to stop the simulation and run the following commands instead:
# note that we changed the Turtlebot3 model
export TURTLEBOT3_MODEL=waffle
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py
Now try to move the robot again and check the /odom eching…Poof, both working! Why? We modified the model file for “burger”; the one for “waffle” was intact!
Final confirmation: uncomment the lines in turtlebot3_ws/src/turtlebot3_simulations/turtlebot3_gazebo/models/turtlebot3_burger/model.sdf , stop the simulation in Terminal 1 and run the following commands.
# note that we changed the Turtlebot3 model back to burger
export TURTLEBOT3_MODEL=burger
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py
Done! Now everything should be working!
So we have confirmed that the command and odometry tags are necessary.
Step 4: Check your learning
Do you understand how to use the Gazebo differential drive plugin in ROS 2? If you don’t know it yet, please go over the post again, more carefully this time.
(Extra) Step 5: Watch the video to understand how to use the Gazebo differential drive plugin in ROS 2
Here you go:
Feedback
Did you like this post? Do you have any questions about how to use the Gazebo differential drive plugin in ROS 2? 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 ROS2 topics, please let us know in the comments area and we will do a video or post about it.
Learn how to launch an empty world in the gazebo simulator using ROS commands.
List of resources used in this post:
Robot Ignite Academy, the place to learn to program robots using only a web browser
ROS Development Studio (the environment used in the video), another powerful online tool for pushing your ROS learning in a practical way
Preparing the environment
In order to load gazebo using ROS, you need to have Gazebo and ROS installed. If you don’t want to install everything, we highly recommend using ROSDS (ROS Development Studio) which gives you access to an online environment with ROS already installed. Indeed, we are going to use that tool for easiness. You can follow the same steps on your computer as well if you don’t want to use ROSDS.
To use ROSDS, you can just create an account and start using it.
Once you have your account created, you have to create a ROSject by clicking on the New ROSject button:
Creating a new ROSject in ROSDS
Once you have the ROSject, you can open it by clicking Open:
Opening a ROSject in ROSDS
Creating the ROS Package
In order to run anything using ROS, we need a ROS package, so, let’s create one. For that, you are going to need a terminal/shell. In ROSDS, you can have a terminal by clicking Tools -> Shell.
Let’s first create the workspace. In this case, let’s call it ~/simulation_ws
mkdir ~/simulation_ws/src -p
Now let’s then compile our empty workspace
source /opt/ros/kinetic/setup.bash
source /usr/share/gazebo/setup.sh
cd ~/simulation_ws/
catkin_make
Now let’s create our ROS package. Let’s call it my_simulations:
source ~/simulation_ws/devel/setup.bash
cd ~/simulation_ws/src
catkin_create_pkg my_simulations
Now, let’s create a launch and a world folder inside the my_simulations package.
cd my_simulations
mkdir launch world
Now, inside the launch folder, let’s create a file named my_world.launch:
user:~/simulation_ws/src$ roslaunch my_simulations my_world.launch --screen
... logging to /home/user/.ros/log/1b7241b4-782c-11ea-a2f3-161ed25550cd/roslaunch-rosdscomputer-7087.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.
started roslaunch server http://rosdscomputer:40747/
SUMMARY
========
PARAMETERS
* /rosdistro: kinetic
* /rosversion: 1.12.14
* /use_sim_time: True
NODES
/
gazebo (gazebo_ros/gzserver)
gazebo_gui (gazebo_ros/gzclient)
auto-starting new master
process[master]: started with pid [7108]
ROS_MASTER_URI=http://master:11311
setting /run_id to 1b7241b4-782c-11ea-a2f3-161ed25550cd
process[rosout-1]: started with pid [7126]
started core service [/rosout]
process[gazebo-2]: started with pid [7140]
process[gazebo_gui-3]: started with pid [7158]
[ INFO] [1586194149.892774702]: Finished loading Gazebo ROS API Plugin.
[ INFO] [1586194149.894694146]: waitForService: Service [/gazebo/set_physics_properties] has not been advertised, waiting...
GZCLIENT disabled by The Construct
[ INFO] [1586194150.663164508, 0.021000000]: waitForService: Service [/gazebo/set_physics_properties] is now available.
[ INFO] [1586194150.694158392, 0.050000000]: Physics dynamic reconfigure ready.
If you are in ROSDS and chose to run the simulation manually, then you have to manually open the Gazebo Web (gzweb) by clicking on Tools -> Gazebo.
Congratulations. You have successfully launched your first Gazebo World using ROS.
Youtube video
If you didn’t understand all the steps explained here or needs more understanding of the files we created, remember that we have the live version of this post on YouTube. Also, if you liked the content, please consider subscribing to our youtube channel. We are publishing new content ~every day.
Welcome to the ROS Q&A series again. In this post, we are going to answer and solve a question from a user on Gazebo Answers which asks how to launch a Parrot Drone simulation locally. The question can be found here.
What will you learn in this post
How to spawn a drone simulation in your local computer
Before downloading the repositories, let’s first create a catkin workspace for the parrot drone, which we will call parrot_ws. Let’s do that with the commands below:
mkdir -p ~/parrot_ws/src
cd ~/parrot_ws/
Now we have the parrot_ws (parrot workspace). Let’s then download the required git repositories which contain the simulation:
cd ~/parrot_ws/src
git clone --branch kinetic-gazebo7 https://bitbucket.org/theconstructcore/parrot_ardrone.git
git clone https://bitbucket.org/theconstructcore/spawn_robot_tools.git
You should now have the folders parrot_ardrone and spawn_robot_tools on the ~/parrot_ws/src folder.
Installing ignition-math, used by sjtu_drone
Before compiling the packages we downloaded in the previous step, we will need to install the Ignition Math library, which is used by the sjtu_drone drone found on the parrot_ardrone repository we cloned previously.
We can install the Ignition Math library with the following commands:
Now that we have the Ignition Math library installed, we can proceed to compile the packages in our workspace.
Compiling the drone package
Now that we have everything in place, we can compile our packages we downloaded previously.
IMPORTANT: it may happen that when compiling the package, catkin_make can’t find the ignition library, so we need to export the CXXFLAGS accordingly. In my local computer, the ignition library is found at /usr/include/ignition/math4, so to compile we use the following commands:
cd ~/parrot_ws
export CXXFLAGS=-isystem\ /usr/include/ignition/math4
source /opt/ros/kinetic/setup.bash
catkin_make
If everything worked as expected, great. If not, try removing the devel and build first with cd ~/parrot_ws/; rm -rf build/ devel/ and compile it again with the commands exemplified above.
If everything went ok, you should have something like:
root@79e5b2505ede:~/parrot_ws# export CXXFLAGS=-isystem\ /usr/include/ignition/math4
root@79e5b2505ede:~/parrot_ws# source /opt/ros/kinetic/setup.bash; catkin_make
Base path: /root/parrot_ws
Source space: /root/parrot_ws/src
Build space: /root/parrot_ws/build
Devel space: /root/parrot_ws/devel
Install space: /root/parrot_ws/install
####
#### Running command: "cmake /root/parrot_ws/src -DCATKIN_DEVEL_PREFIX=/root/parrot_ws/devel -DCMAKE_INSTALL_PREFIX=/root/parrot_ws/install -G Unix Makefiles" in "/root/parrot_ws/build"
####
...
-- catkin 0.7.14
-- BUILD_SHARED_LIBS is on
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~ traversing 6 packages in topological order:
-- ~~ - custom_teleop
-- ~~ - drone_demo
-- ~~ - ardrone_as
-- ~~ - sjtu_drone
-- ~~ - spawn_robot_tools_pkg
-- ~~ - drone_construct
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'custom_teleop'
-- ==> add_subdirectory(parrot_ardrone/custom_teleop)
-- +++ processing catkin package: 'drone_demo'
-- ==> add_subdirectory(parrot_ardrone/drone_demo)
-- +++ processing catkin package: 'ardrone_as'
-- ==> add_subdirectory(parrot_ardrone/ardrone_as)
-- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy
-- Generating .msg files for action ardrone_as/Ardrone /root/parrot_ws/src/parrot_ardrone/ardrone_as/action/Ardrone.action
Generating for action Ardrone
-- ardrone_as: 7 messages, 0 services
-- +++ processing catkin package: 'sjtu_drone'
-- ==> add_subdirectory(parrot_ardrone/sjtu_drone)
-- Using these message generators: gencpp;geneus;genlisp;gennodejs;genpy
-- Boost version: 1.58.0
-- Found the following Boost libraries:
-- thread
-- signals
-- system
-- filesystem
-- program_options
-- regex
-- iostreams
-- date_time
-- chrono
-- atomic
-- Found Protobuf: /usr/lib/x86_64-linux-gnu/libprotobuf.so
...
-- Generating done
-- Build files have been written to: /root/parrot_ws/build
####
#### Running command: "make -j4 -l4" in "/root/parrot_ws/build"
####
Scanning dependencies of target _ardrone_as_generate_messages_check_deps_ArdroneActionFeedback
Scanning dependencies of target _ardrone_as_generate_messages_check_deps_ArdroneGoal
Scanning dependencies of target _ardrone_as_generate_messages_check_deps_ArdroneActionGoal
Scanning dependencies of target _ardrone_as_generate_messages_check_deps_ArdroneResult
[ 0%] Built target _ardrone_as_generate_messages_check_deps_ArdroneResult
...
Scanning dependencies of target plugin_drone
[ 1%] Building CXX object parrot_ardrone/sjtu_drone/CMakeFiles/plugin_ros_cam.dir/src/plugin_ros_cam.cpp.o
[ 3%] Building CXX object parrot_ardrone/sjtu_drone/CMakeFiles/plugin_ros_imu.dir/src/plugin_ros_imu_native.cpp.o
[ 5%] Building CXX object parrot_ardrone/sjtu_drone/CMakeFiles/plugin_drone.dir/src/plugin_drone.cpp.o
[ 7%] Building CXX object parrot_ardrone/sjtu_drone/CMakeFiles/plugin_ros_sonar.dir/src/plugin_ros_sonar.cpp.o
...
[ 9%] Linking CXX shared library /root/parrot_ws/src/parrot_ardrone/sjtu_drone/plugins/libplugin_ros_imu.so
[ 11%] Linking CXX shared library /root/parrot_ws/src/parrot_ardrone/sjtu_drone/plugins/libplugin_ros_sonar.so
[ 11%] Built target plugin_ros_sonar
[ 13%] Building CXX object parrot_ardrone/sjtu_drone/CMakeFiles/plugin_ros_cam.dir/src/util_ros_cam.cpp.o
[ 13%] Built target plugin_ros_imu
Scanning dependencies of target plugin_ros_init
[ 15%] Building CXX object parrot_ardrone/sjtu_drone/CMakeFiles/plugin_ros_init.dir/src/plugin_ros_init.cpp.o
[ 17%] Building CXX object parrot_ardrone/sjtu_drone/CMakeFiles/plugin_drone.dir/src/pid_controller.cpp.o
[ 19%] Linking CXX shared library /root/parrot_ws/src/parrot_ardrone/sjtu_drone/plugins/libplugin_drone.so
[ 19%] Built target plugin_drone
Scanning dependencies of target spawn_drone
[ 21%] Building CXX object parrot_ardrone/sjtu_drone/CMakeFiles/spawn_drone.dir/src/spawn_drone.cpp.o
...
[ 23%] Linking CXX executable /root/parrot_ws/src/parrot_ardrone/sjtu_drone/bin/spawn_drone
[ 23%] Built target spawn_drone
Scanning dependencies of target spawn_robot_tools_pkg_xacro_generated_to_devel_space_
[ 23%] Built target spawn_robot_tools_pkg_xacro_generated_to_devel_space_
Scanning dependencies of target ardrone_as_generate_messages_cpp
[ 25%] Generating C++ code from ardrone_as/ArdroneFeedback.msg
[ 27%] Generating C++ code from ardrone_as/ArdroneActionResult.msg
[ 29%] Generating C++ code from ardrone_as/ArdroneAction.msg
[ 31%] Generating C++ code from ardrone_as/ArdroneResult.msg
[ 33%] Generating C++ code from ardrone_as/ArdroneActionGoal.msg
[ 35%] Generating C++ code from ardrone_as/ArdroneGoal.msg
[ 37%] Generating C++ code from ardrone_as/ArdroneActionFeedback.msg
Scanning dependencies of target ardrone_as_generate_messages_py
[ 37%] Built target ardrone_as_generate_messages_cpp
[ 39%] Generating Python from MSG ardrone_as/ArdroneFeedback
Scanning dependencies of target ardrone_as_generate_messages_nodejs
[ 41%] Generating Javascript code from ardrone_as/ArdroneFeedback.msg
[ 43%] Generating Javascript code from ardrone_as/ArdroneActionResult.msg
[ 47%] Generating Javascript code from ardrone_as/ArdroneAction.msg
[ 47%] Generating Python from MSG ardrone_as/ArdroneActionResult
[ 49%] Generating Javascript code from ardrone_as/ArdroneResult.msg
[ 50%] Generating Javascript code from ardrone_as/ArdroneActionGoal.msg
[ 52%] Generating Python from MSG ardrone_as/ArdroneAction
[ 54%] Generating Javascript code from ardrone_as/ArdroneGoal.msg
[ 56%] Generating Javascript code from ardrone_as/ArdroneActionFeedback.msg
[ 58%] Generating Python from MSG ardrone_as/ArdroneResult
[ 58%] Built target ardrone_as_generate_messages_nodejs
Scanning dependencies of target ardrone_as_generate_messages_eus
[ 60%] Generating EusLisp code from ardrone_as/ArdroneFeedback.msg
[ 62%] Generating EusLisp code from ardrone_as/ArdroneActionResult.msg
[ 64%] Generating Python from MSG ardrone_as/ArdroneActionGoal
[ 66%] Generating EusLisp code from ardrone_as/ArdroneAction.msg
[ 68%] Generating Python from MSG ardrone_as/ArdroneGoal
[ 70%] Generating EusLisp code from ardrone_as/ArdroneResult.msg
[ 72%] Generating EusLisp code from ardrone_as/ArdroneActionGoal.msg
[ 74%] Generating Python from MSG ardrone_as/ArdroneActionFeedback
[ 76%] Generating EusLisp code from ardrone_as/ArdroneGoal.msg
[ 78%] Generating EusLisp code from ardrone_as/ArdroneActionFeedback.msg
[ 80%] Generating Python msg __init__.py for ardrone_as
[ 82%] Generating EusLisp manifest code for ardrone_as
[ 82%] Built target ardrone_as_generate_messages_py
Scanning dependencies of target ardrone_as_generate_messages_lisp
[ 84%] Generating Lisp code from ardrone_as/ArdroneFeedback.msg
[ 86%] Generating Lisp code from ardrone_as/ArdroneActionResult.msg
[ 88%] Generating Lisp code from ardrone_as/ArdroneAction.msg
[ 90%] Generating Lisp code from ardrone_as/ArdroneResult.msg
[ 92%] Generating Lisp code from ardrone_as/ArdroneActionGoal.msg
[ 94%] Generating Lisp code from ardrone_as/ArdroneGoal.msg
[ 96%] Generating Lisp code from ardrone_as/ArdroneActionFeedback.msg
[ 96%] Built target ardrone_as_generate_messages_lisp
[ 96%] Built target ardrone_as_generate_messages_eus
Scanning dependencies of target ardrone_as_generate_messages
[ 96%] Built target ardrone_as_generate_messages
...
[ 98%] Linking CXX shared library /root/parrot_ws/src/parrot_ardrone/sjtu_drone/plugins/libplugin_ros_cam.so
[ 98%] Built target plugin_ros_cam
[100%] Linking CXX shared library /root/parrot_ws/src/parrot_ardrone/sjtu_drone/plugins/libplugin_ros_init.so
[100%] Built target plugin_ros_init
Once the package is compiled, in every shell you need to source the parrot_ws so that ROS can find the compiled packages. In each shell you can run the commands below:
cd ~/parrot_ws/
source devel/setup.bash
rospack profile
Launching the simulation
Now that you have everything in place, you should be able to launch the simulation with the command below:
After running rosrun teleop_twist_keyboard teleop_twist_keyboard.py you can easily move the robot using the keyboard.
So that is the post for today. You can also find a live version of this post on our YouTube channel in the link below. Also, please consider subscribing to our channel if you liked the content and press the bell for a new video every day.