Cannot connect to gazebo API topics if i run a gazebo server using roslaunch.
Hello everybody. I have been stucked for a day on that and i do not find the solution to this problem.
I am just trying to do a mix between the clone simulation tutorial (http://gazebosim.org/tutorials?tut=clone_simulation&cat=) and a empty_world.launch simulation.
First of all, I am using ROS Kinetic and Gazebo 7.0
in clone.cpp I have commented the server run lines:
std::thread serverThread(RunServer);
and
serverThread.join();
Instead of running like this way the server, i just added the cpp code inside a launch copy of empty_world. adding the following line:
<node name="clone_node" pkg="ros_trial" type="cloner" output="screen" />
(just to be clear, CMakeLists.txt and package.xml are correctly configured
When I do a roslaunch, everyting seems to work, but the api message /gazebo/server/control is not published.
I have check if the channel exists with gz topic -l (and exists) but if i do gz topic -e /gazebo/server/control nothing appears.
The reason why i want to do this is because I want to clone a simulation several time and run them simoultaneously in order to reduce training time. The simulation which i want to run uses gazebomsgs topics like gazebomsgs::SpawnModel which does not exists woithout ROS (and I did not found any substitute).
I do not know if I have been clear, (sorry if not!) in which case just ask me. Any help will be appreciated.
Thanks!
EDIT: I add the code to be more clear.
cloner.cpp:
#include <cstdlib>
#include <iostream>
#include <memory>
#include <thread>
#include <gazebo/gazebo.hh>
#include <gazebo/msgs/msgs.hh>
#include <gazebo/transport/transport.hh>
#include <fstream>
#include <string>
#include <ros/ros.h>
#include <ros/package.h>
#include <geometry_msgs/Quaternion.h>
#include <geometry_msgs/PoseArray.h>
#include <geometry_msgs/Inertia.h>
#include <std_srvs/Empty.h>
#include <std_srvs/Trigger.h>
#include <urdf/model.h>
#include <urdf_parser/urdf_parser.h>
#include <collada_urdf/collada_urdf.h>
#include <gazebo_msgs/SpawnModel.h>
#include <gazebo_msgs/DeleteModel.h>
#include <gazebo_msgs/SetModelState.h>
#include <gazebo_msgs/GetModelState.h>
#include <actionlib/server/simple_action_server.h>
std::mutex feedback_mutex__;
std::vector<std::shared_ptr<std::thread>> clone_thread_ptr_vector__;
std::vector<char*> __environments;
/////////////////////////////////////////////////
void OnWorldModify(ConstWorldModifyPtr &_msg)
{
std::cout << "inside on world modify function" << std::endl;
if (_msg->has_cloned() && _msg->cloned() && _msg->has_cloned_uri())
{
std::cout << "World cloned. You can connect a client by typing\n"
<< "\tGAZEBO_MASTER_URI=" << _msg->cloned_uri()
<< " gzclient" << std::endl;
char uri = *_msg->cloned_uri().c_str();
__environments.push_back(&uri);
}
else{
std::cout << "ERROR 1" << std::endl;
}
}
/////////////////////////////////////////////////
void RunServer()
{
// Initialize gazebo server.
std::cout << "inside run server function" << std::endl;
std::unique_ptr<gazebo::Server> server(new gazebo::Server());
try
{
if (!server->ParseArgs(0, NULL))
return;
// Initialize the informational logger. This will log warnings, and errors.
gzLogInit("server-", "gzserver.log");
server->Run();
server->Fini();
}
catch(gazebo::common::Exception &_e)
{
std::cout << "ERROR 2" << std::endl;
_e.Print();
server->Fini();
}
}
int port_ = 11346;
char* __master = getenv("ROS_MASTER_URI");
void GenerateClone(gazebo::transport::PublisherPtr serverControlPub )
{
std::cout << "inside GenerateClone" << std::endl;
gazebo::msgs::ServerControl msg;
msg.set_save_world_name("");
msg.set_clone(true);
msg.set_new_port(port_);
std::cout << "publishing " << std::endl;
serverControlPub->Publish(msg);
std::cout << "published" << std::endl;
port_++;
return;
}
/////////////////////////////////////////////////
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker");
ros::NodeHandle n;
__environments.push_back(__master);
//std::thread serverThread(RunServer);
//setenv("GAZEBO_MASTER_URI", __master, 1);
// Create a node for communication.
gazebo::transport::NodePtr node(new gazebo::transport::Node());
node->Init();
// Publisher to the server control.
gazebo::transport::PublisherPtr serverControlPub =
node->Advertise<gazebo::msgs::ServerControl>("/gazebo/server/control");
// ros::Publisher serverControlPub = n.advertise<gazebo_msgs::ServerControl>("/gazebo/server/control", 1000);
// Subscriber to receive world updates (e.g.: a notification after a cloning).
gazebo::transport::SubscriberPtr worldModSub =
node->Subscribe("/gazebo/world/modify", &OnWorldModify);
std::cout << "master: "<< __master << std::endl;
std::cout << "\nPress [ENTER] to clone the current simulation\n" << std::endl;
getchar();
// Clone the server programmatically.
for (int i = 0; i<2 ; i++){
if (feedback_mutex__.try_lock()){
clone_thread_ptr_vector__.push_back(std::make_shared<std::thread>(GenerateClone, serverControlPub ) );
feedback_mutex__.unlock();
//sleep(5);
}
}
//__environments.push_back("http://localhost:11346");
//__environments.push_back("http://localhost:11347");
sleep(1);
// modify the different worlds
//master world
std::cout << "\nPress [ENTER] to send a 301 to the master world\n" << std::endl;
getchar();
{
//setenv("GAZEBO_MASTER_URI", __master, 1);
std::string package_path = ros::package::getPath("ros_trial");
std::string filename = package_path + "/urdf/part_301.urdf";
urdf::ModelInterfaceSharedPtr part_model_ptr = urdf::parseURDFFile(filename);
geometry_msgs::Inertia inertial__;
inertial__.m = 0.05;
inertial__.com.x = 0.0;
inertial__.com.y = 0.0;
inertial__.com.z = 0.014879;
inertial__.ixx = 0.0006158372000000;
inertial__.ixy = -0.0000000010145837;
inertial__.ixz = -0.0000000054554562;
inertial__.iyy = 0.0006157460000000;
inertial__.iyz = 0.0000000212208923;
inertial__.izz = 0.0003144807500000;
part_model_ptr->getRoot()->inertial->mass = inertial__.m;
part_model_ptr->getRoot()->inertial->origin.position.x = inertial__.com.x;
part_model_ptr->getRoot()->inertial->origin.position.y = inertial__.com.y;
part_model_ptr->getRoot()->inertial->origin.position.z = inertial__.com.z;
part_model_ptr->getRoot()->inertial->ixx = inertial__.ixx;
part_model_ptr->getRoot()->inertial->ixy = inertial__.ixy;
part_model_ptr->getRoot()->inertial->ixz = inertial__.ixz;
part_model_ptr->getRoot()->inertial->iyy = inertial__.iyy;
part_model_ptr->getRoot()->inertial->iyz = inertial__.iyz;
part_model_ptr->getRoot()->inertial->izz = inertial__.izz;
TiXmlDocument* urdf_doc_ptr;
urdf_doc_ptr = urdf::exportURDF( part_model_ptr );
TiXmlPrinter printer;
urdf_doc_ptr->Accept( &printer );
std::string urdf_str = printer.CStr();
sdf::ElementPtr __sdf;
ros::ServiceClient spawn_srv = n.serviceClient<gazebo_msgs::SpawnModel>("/gazebo/spawn_urdf_model");
gazebo_msgs::SpawnModel spawn_service;
spawn_service.request.initial_pose.position.x = 0.0;
spawn_service.request.initial_pose.position.y = 0.0;
spawn_service.request.initial_pose.position.z = 20.0;
spawn_service.request.initial_pose.orientation.w = 1.0;
spawn_service.request.model_name = "part";
spawn_service.request.model_xml = urdf_str;
spawn_srv.call(spawn_service);
}
//cloned 1
std::cout << "\nPress [ENTER] to send a 021 to the first cloned world\n" << std::endl;
getchar();
setenv("GAZEBO_MASTER_URI", __environments[1], 1);
{
std::string package_path = ros::package::getPath("ros_trial");
std::string filename = package_path + "/urdf/part_02.urdf";
urdf::ModelInterfaceSharedPtr part_model_ptr = urdf::parseURDFFile(filename);
geometry_msgs::Inertia inertial__;
inertial__.m = 0.05;
inertial__.com.x = 0.0;
inertial__.com.y = 0.0;
inertial__.com.z = 0.014879;
inertial__.ixx = 0.0006158372000000;
inertial__.ixy = -0.0000000010145837;
inertial__.ixz = -0.0000000054554562;
inertial__.iyy = 0.0006157460000000;
inertial__.iyz = 0.0000000212208923;
inertial__.izz = 0.0003144807500000;
part_model_ptr->getRoot()->inertial->mass = inertial__.m;
part_model_ptr->getRoot()->inertial->origin.position.x = inertial__.com.x;
part_model_ptr->getRoot()->inertial->origin.position.y = inertial__.com.y;
part_model_ptr->getRoot()->inertial->origin.position.z = inertial__.com.z;
part_model_ptr->getRoot()->inertial->ixx = inertial__.ixx;
part_model_ptr->getRoot()->inertial->ixy = inertial__.ixy;
part_model_ptr->getRoot()->inertial->ixz = inertial__.ixz;
part_model_ptr->getRoot()->inertial->iyy = inertial__.iyy;
part_model_ptr->getRoot()->inertial->iyz = inertial__.iyz;
part_model_ptr->getRoot()->inertial->izz = inertial__.izz;
TiXmlDocument* urdf_doc_ptr;
urdf_doc_ptr = urdf::exportURDF( part_model_ptr );
TiXmlPrinter printer;
urdf_doc_ptr->Accept( &printer );
std::string urdf_str = printer.CStr();
ros::ServiceClient spawn_srv = n.serviceClient<gazebo_msgs::SpawnModel>("/gazebo/spawn_urdf_model");
gazebo_msgs::SpawnModel spawn_service;
spawn_service.request.initial_pose.position.x = 0.0;
spawn_service.request.initial_pose.position.y = 0.0;
spawn_service.request.initial_pose.position.z = 20.0;
spawn_service.request.initial_pose.orientation.w = 1.0;
spawn_service.request.model_name = "part";
spawn_service.request.model_xml = urdf_str;
spawn_srv.call(spawn_service);
}
//cloned 2
std::cout << "\nPress [ENTER] to send a 301 to the second cloned world\n" << std::endl;
getchar();
setenv("GAZEBO_MASTER_URI", __environments[2], 1);
{
std::string package_path = ros::package::getPath("ros_trial");
std::string filename = package_path + "/urdf/part_301.urdf";
urdf::ModelInterfaceSharedPtr part_model_ptr = urdf::parseURDFFile(filename);
geometry_msgs::Inertia inertial__;
inertial__.m = 0.05;
inertial__.com.x = 0.0;
inertial__.com.y = 0.0;
inertial__.com.z = 0.014879;
inertial__.ixx = 0.0006158372000000;
inertial__.ixy = -0.0000000010145837;
inertial__.ixz = -0.0000000054554562;
inertial__.iyy = 0.0006157460000000;
inertial__.iyz = 0.0000000212208923;
inertial__.izz = 0.0003144807500000;
part_model_ptr->getRoot()->inertial->mass = inertial__.m;
part_model_ptr->getRoot()->inertial->origin.position.x = inertial__.com.x;
part_model_ptr->getRoot()->inertial->origin.position.y = inertial__.com.y;
part_model_ptr->getRoot()->inertial->origin.position.z = inertial__.com.z;
part_model_ptr->getRoot()->inertial->ixx = inertial__.ixx;
part_model_ptr->getRoot()->inertial->ixy = inertial__.ixy;
part_model_ptr->getRoot()->inertial->ixz = inertial__.ixz;
part_model_ptr->getRoot()->inertial->iyy = inertial__.iyy;
part_model_ptr->getRoot()->inertial->iyz = inertial__.iyz;
part_model_ptr->getRoot()->inertial->izz = inertial__.izz;
TiXmlDocument* urdf_doc_ptr;
urdf_doc_ptr = urdf::exportURDF( part_model_ptr );
TiXmlPrinter printer;
urdf_doc_ptr->Accept( &printer );
std::string urdf_str = printer.CStr();
ros::ServiceClient spawn_srv = n.serviceClient<gazebo_msgs::SpawnModel>("/gazebo/spawn_urdf_model");
gazebo_msgs::SpawnModel spawn_service;
spawn_service.request.initial_pose.position.x = 0.0;
spawn_service.request.initial_pose.position.y = 0.0;
spawn_service.request.initial_pose.position.z = 20.0;
spawn_service.request.initial_pose.orientation.w = 1.0;
spawn_service.request.model_name = "part";
spawn_service.request.model_xml = urdf_str;
spawn_srv.call(spawn_service);
}
// Wait for the simulation clone before showing the next message.
gazebo::common::Time::MSleep(200);
std::cout << "\nPress [ENTER] to exit and kill all the servers." << std::endl;
getchar();
// Make sure to shut everything down.
std::string cmd = "kill -15 `ps -A | grep -m1 gzserver | awk '{print $1}'`";
int ret = std::system(cmd.c_str());
if (ret != 0)
std::cerr << "kill gzserver returned a non zero value:" << ret << std::endl;
gazebo::shutdown();
//serverThread.join();
ros::spin();
return 0;
}
clone.launch:
<?xml version="1.0"?>
<launch>
<!-- these are the arguments you can pass this launch file, for example paused:=true -->
<arg name="paused" default="false"/>
<arg name="use_sim_time" default="true"/>
<arg name="extra_gazebo_args" default=""/>
<arg name="gui" default="true"/>
<arg name="recording" default="false"/>
<!-- Note that 'headless' is currently non-functional. See gazebo_ros_pkgs issue #491 (-r arg does not disable
rendering, but instead enables recording). The arg definition has been left here to prevent breaking downstream
launch files, but it does nothing. -->
<arg name="headless" default="false"/>
<arg name="debug" default="true"/>
<arg name="physics" default="ode"/>
<arg name="verbose" default="false"/>
<arg name="world_name" default="worlds/empty.world"/> <!-- Note: the world_name is with respect to GAZEBO_RESOURCE_PATH environmental variable -->
<arg name="respawn_gazebo" default="false"/>
<arg name="use_clock_frequency" default="false"/>
<arg name="pub_clock_frequency" default="100"/>
<arg name="required" default="false"/>
<!-- set use_sim_time flag -->
<group if="$(arg use_sim_time)">
<param name="/use_sim_time" value="true" />
</group>
<!-- set command arguments -->
<arg unless="$(arg paused)" name="command_arg1" value=""/>
<arg if="$(arg paused)" name="command_arg1" value="-u"/>
<arg unless="$(arg recording)" name="command_arg2" value=""/>
<arg if="$(arg recording)" name="command_arg2" value="-r"/>
<arg unless="$(arg verbose)" name="command_arg3" value=""/>
<arg if="$(arg verbose)" name="command_arg3" value="--verbose"/>
<arg unless="$(arg debug)" name="script_type" value="gzserver"/>
<arg if="$(arg debug)" name="script_type" value="debug"/>
<!-- start gazebo server-->
<group if="$(arg use_clock_frequency)">
<param name="gazebo/pub_clock_frequency" value="$(arg pub_clock_frequency)" />
</group>
<node name="clone_node" pkg="ros_trial" type="cloner" output="screen" />
<node name="gazebo" pkg="gazebo_ros" type="$(arg script_type)" respawn="$(arg respawn_gazebo)" output="screen"
args="$(arg command_arg1) $(arg command_arg2) $(arg command_arg3) -e $(arg physics) $(arg extra_gazebo_args) $(arg world_name)" />
<!-- start gazebo client -->
<group if="$(arg gui)">
<node name="gazebo_gui" pkg="gazebo_ros" type="gzclient" respawn="false" output="screen" required="$(arg required)"/>
</group>
</launch>
Asked by Solrac3589 on 2018-11-07 06:26:03 UTC
Comments
I am not going to post this as a solution, because it is not, but I am working through a workaround (if somebody has this problem). I am adapting the code to work only with the API topics from Gazebo (non-ROS ones). Disabling the gzserver generation from the launcher and generating it in the code.
Asked by Solrac3589 on 2018-11-08 03:11:37 UTC