This post is meant as a follow-on for part 2 and documents some of the differences that I encountered trying to give control of simulation stepping to ROS-based code itself. Since ROS and Gazebo are technically separate, I was trying to find a way to create a ROS piece of code to communicate with the Gazebo plugin that I’d been using to step the simulation. After quite a bit of reading, it appears that it may not be possible, or simply prohibitively difficult. Therefore, this blog post documents an alternate solution that I plan to use in the blog posts and code going forward. Code for this blog post can be found here
General Approach:
Rather than employ the gazebo plugin from previous entries, all code now resides in one C++ file. We’ll declare both a ROS node to get the simulation time and report it to the terminal and also a gazebo node to actually handle the stepping of the simulation. Note: There are a few changes to the launch file in this example too so please use the accompanying world_step.launch rather than the version from previous posts.
Code Breakdown:
The primary file to look at is /src/world_step/ros_get_world_time.cpp:
#include <math.h> #include <boost/thread.hpp> #include <boost/algorithm/string.hpp> #include <gazebo/gazebo.hh> #include <gazebo/common/Plugin.hh> #include <gazebo/msgs/msgs.hh> #include <gazebo/transport/transport.hh> #include <ros/ros.h> #include <ros/subscribe_options.h> int main(int argc, char** argv) { gazebo::setupClient(argc,argv); ros::init(argc, argv, "get_world_time_test"); // Gazebo WorldControl Topic gazebo::transport::NodePtr node(new gazebo::transport::Node()); node->Init(); // Initialize the ROSNode ros::NodeHandle* rosnode = new ros::NodeHandle(); gazebo::transport::PublisherPtr pub = node->Advertise<gazebo::msgs::WorldControl>("~/world_control"); // Waits for simulation time update. ros::Time last_ros_time_; bool wait = true; while (wait) { last_ros_time_ = ros::Time::now(); std::cout << "\t\t\t Attempted getting sim time: " << last_ros_time_ << std::endl; if (last_ros_time_.toSec() > 0) //wait = false; std::cout << "Current Simulation Time: " << last_ros_time_ << std::endl; // Publish the step message for the simulation. gazebo::msgs::WorldControl msg; msg.set_step(1); pub->Publish(msg); // Wait for 1 second and allow ROS to complete as well. gazebo::common::Time::MSleep(1000); ros::spinOnce(); } gazebo::shutdown(); return 0; }
As you can see from the code, we initially setup the gazebo and ROS nodes in lines 19-26. Lines 28-38 are similar to those of previous examples simply getting the current simulation time and printing it to the terminal. The main change from previous examples are in lines 40-47. Instead of waiting on a Gazebo plugin, this code implements the world stepping code directly in the while loop. The next two lines then simply wait one second before proceeding with stepping.
Moving Forward:
With this setup, I now plan to use this loop to setup the basic framework for conducting simulations for a set amount of time.
Thanks for the post and the previous ones too!! They’ve been extremely useful