0
$\begingroup$

Gazebo Answers logo

I used this tutorial to get me going http://gazebosim.org/tutorials?tut=guided_i5#TestthemessagepassingAPI.

It gave me enough information to create a gazebo model plugin, and a standalone gazebo node that would use a gazebo transport node to publish commands to a Gazebo topic.

My problem is that my gazebo model plugin is unable to see when a message is sent to the gazebo topic ("/topic/a") even though I have a gazebo subscriber callback function for "/topic/a". To confirm that I was publishing and subscribing to the gazebo topic I opened a terminal and used the command

"gz topic -i /topic/a" 

The response was

Type: gazebo.msgs.Vector3d Publishers: Same IP:43457 Subscribers: Same IP:45557 

They had the same IP but different ports. Is that normal? How do I get both gazebo nodes to look at the same Gazebo topic?

My code for my standalone is below

#include <gazebo/gazebo_client.hh> #include <gazebo/common/common.hh> #include <gazebo/gazebo_config.h> #include <gazebo/physics/physics.hh> #include <gazebo/transport/transport.hh> #include <gazebo/msgs/msgs.hh> void callback_from_gazebo(ConstVector3dPtr &_msg) { std::cout << "Callback received () \n"; } int main(int _argc, char **_argv) { std::cout << "Gazebo Initialization \n"; gazebo::transport::PublisherPtr pub1,pub2; gazebo::transport::SubscriberPtr sub1; gazebo::client::setup(_argc, _argv); gazebo::transport::init(); gazebo::transport::run(); gazebo::transport::NodePtr node(new gazebo::transport::Node()); node->Init("default"); std::cout << "End Gazebo Initialization \n"; std::cout << "Define Gazebo Publishers and Subscribers \n"; pub1 = node->Advertise<gazebo::msgs::Vector3d>("/topic/a"); pub2 = node->Advertise<gazebo::msgs::WorldControl>("/gazebo/torqueprofile/world_control"); sub1 = node->Subscribe("/topic/b", callback_from_gazebo); std::cout << "Waiting for connection\n"; pub1->WaitForConnection(); pub2->WaitForConnection(); std::cout << "Connections confirmed\n"; while(1) { gazebo::msgs::Vector3d cmd; cmd.set_x(1); cmd.set_y(2); cmd.set_z(3); pub1->WaitForConnection(); pub1->Publish(cmd); gazebo::msgs::WorldControl world_msg; world_msg.set_step(true); pub2->Publish(world_msg); gazebo::common::Time::MSleep(1000); } gazebo::transport::fini(); gazebo::client::shutdown(); return 0; } 

My code for my plugin is below

#include <boost/bind.hpp> #include <gazebo/transport/transport.hh> #include <gazebo/msgs/msgs.hh> #include <gazebo/physics/physics.hh> #include <gazebo/common/common.hh> #include <gazebo/math/Angle.hh> #include <gazebo/gazebo_client.hh> #include <gazebo/gazebo_config.h> #include <stdio.h> #include <fstream> namespace gazebo { /// \brief A plugin to control two cubes strictly in Gazebo class gazebo_simple_plugin : public ModelPlugin { /// \brief Constructor public: gazebo_simple_plugin() { } public: virtual void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf) { model = _model; if (model->GetJointCount() == 0) { std::cerr << "\n no joints \n"; return; } else std::cerr << "\n joints are there \n"; //set joint handle to joints in the _model joint1 = model->GetJoints()[0]; // Create the Gazebo node node = transport::NodePtr(new transport::Node()); node->Init(this->model->GetWorld()->GetName()); pub1 = node->Advertise<gazebo::msgs::Vector3d>("/topic/b"); sub1 = node->Subscribe("/topic/a", &gazebo_simple_plugin::callback_from_standalone, this); //Listen to the update event. This event is broadcast every updateConnection = event::Events::ConnectWorldUpdateBegin(boost::bind(&gazebo_simple_plugin::OnUpdate, this, _1)); } private: void callback_from_standalone(ConstVector3dPtr &_msg) { cmd=(_msg->x()); printf("cmd received %f \n",cmd); } // Called by the world update start event public: void OnUpdate(const common::UpdateInfo & /*_info*/) { //double force_1 = joint1_sy->GetForceTorque(0).body2Force.z; joint1->SetForce(2, cmd); gazebo::msgs::Vector3d feedback_msg; feedback_msg.set_x(joint1->GetAngle(2).Degree()); pub1->WaitForConnection(); pub1->Publish(feedback_msg); printf("ONUPDATE: Update occurred"); } // Pointer to the model private: physics::ModelPtr model; /// \brief Pointer to the joint. private: physics::JointPtr joint1; //shoulder yaw /// \brief A node used for transport public: transport::NodePtr node; public: transport::PublisherPtr pub1; public: transport::SubscriberPtr sub1; // Pointer to the update event connection private: event::ConnectionPtr updateConnection; private: double cmd; }; // Tell Gazebo about this plugin, so that Gazebo can call Load on this plugin. GZ_REGISTER_MODEL_PLUGIN(gazebo_simple_plugin) } 

Originally posted by Francis123 on Gazebo Answers with karma: 33 on 2017-01-25

Post score: 0


Original comments

Comment by hugomatic on 2017-01-26:
Make sure there is no typo in the topic name for your subscribe call. Can you provide code and what Gazebo version you are using?

Comment by Francis123 on 2017-01-27:
I made sure there was no typo in the topic name. Also i am able to see both the publisher and the subscriber to the topic so that confirms that the gazebo nodes are looking at the topic.

I did find this page to be helpful (http://gazebosim.org/tutorials?tut=custom_messages#CodeExplained13). It made it clear that in my gazebo node executable (that uses int main()) I needed to make a call to these two transport functions:

gazebo::transport::init(); gazebo::transport::run();

Comment by Francis123 on 2017-01-27:
I also added the call pub1->WaitForConnection(); before each message that I publish over the gazebo transport layer, before I just called it after defining the gazebo publisher handle. I am using Gazebo 7, and cannot show code due to employment restrictions.

Comment by nkoenig on 2017-01-27:
It is normal that the publisher and subscriber have different ports. The output of gz topic indicates that there is one publisher on /topic/a and one subscriber. If you are running a model plugin, then you shouldn't call gazebo::transport::init nor gazebo::transport::run. The documentation you referenced is for a standalone program. Can you post your code?

Comment by Francis123 on 2017-01-27:
I can show small portions though. Here is my subscriber for topic a in one gazebo node sub1 = node->Subscribe("/gazebo/torqueprofile/feedback", callback_from_gazebo);

Here is my code for the publisher for "topic a" in the gazebo control plugin pub1 = node->Advertisegazebo::msgs::Vector3d("/gazebo/torqueprofile/feedback");

They are identical name definition

Comment by nkoenig on 2017-01-27:
Can you create a simple plugin that demonstrates your problem, but doesn't violate your employment restrictions. Creating a simple plugin will also help you self-debug the problem.

Comment by Francis123 on 2017-01-27:
I added the code to the question now.

So basically what I see now is the stand alone can publish to topic a, but the gazebo plugin cannot publish to topic b, any ideas?

$\endgroup$

1 Answer 1

0
$\begingroup$

Gazebo Answers logo

I was able to figure out why my standalone gazebo program and gazebo plugin were having problems communicating with each other.

It was all on the the standalone gazebo program side, and I used this link to help me understand where I went wrong. http://gazebosim.org/tutorials?tut=custom_messages#CMakeListsforPluginandExecutable

For the problem of publishing messages to a gazebo topic Basically I was missing these two lines before initializing the gazebo transport node (something that is not used in another tutorial I used)

gazebo::transport::init(); gazebo::transport::run(); 

For the problem of subscribing to a gazebo topic through the standalone gazebo program, I had to create a shared boost ptr to the object that is passed as a parameter to the callback function

typedef const boost::shared_ptr<gazebo::msgs::Vector3d> ConstVector3dPtr; 

In the future it might be helpful if there were tutorials that are soley about creating standalone gazebo programs, I did find the answers but through a lot of assumptions.


Originally posted by Francis123 with karma: 33 on 2017-01-31

This answer was ACCEPTED on the original site

Post score: 1

$\endgroup$