ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

Node service not publishing to topic

asked 2018-08-22 12:57:23 -0500

milosgajdos gravatar image

updated 2018-08-22 14:22:31 -0500

I have a problem with a simple node I wrote when it fails to publish any messages to a topic.

I'm using the following version of ROS:

SUMMARY
========

PARAMETERS
 * /rosdistro: melodic
 * /rosversion: 1.14.1

My subscriber node looks like this:

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <stdlib.h>
#include <iomanip>

void poseMessageReceived(const geometry_msgs::Twist& msg) {
        ROS_INFO_STREAM("Received velocity cmd:" << std::setprecision(4) << std::fixed
                << " SUB linear==" << msg.linear.x
                << " SUB angular==" << msg.linear.z);
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "subscribe_to_twist");
    ros::NodeHandle nh;

    ROS_INFO_STREAM("Subscribed to: subpose_node/cmd_vel");

    ros::Subscriber sub = nh.subscribe("subpose_node/cmd_vel", 1000, &poseMessageReceived);
    ros::spin();
}

There is nothing magical in the subscriber code.

My publisher node is a service node and it looks like this -- please ignore Foo.h srv for now:

#include <stdlib.h>
#include <iomanip>
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <svcsrv/Foo.h>

bool PubTwist(
  svcsrv::Foo::Request &req,
  svcsrv::Foo::Response &resp
) {
    ROS_INFO_STREAM("Received message: " << "linearX==" << req.linear.x << " linearZ" << req.linear.z);

    resp.linear.x = req.linear.x;
    resp.linear.z = req.linear.z;

    return true;
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "pub_twist");
    ros::NodeHandle nh;

    // register service with the master
    ros::ServiceServer server = nh.advertiseService("pub_twist", &PubTwist);

    ROS_INFO("Ready to receive and send messages!");

    ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("subpose_node/cmd_vel", 1000);
    geometry_msgs::Twist msg;
    msg.linear.x = 0.0;
    msg.linear.z = 0.0;
    pub.publish(msg);

    ros::spin();
    return 0;
}

The service client is also very simple:

#include <cstdlib>
#include <ros/ros.h>
#include <svcsrv/Foo.h>
int main(int argc, char **argv)
{
  ros::init(argc, argv, "send_twist_message");

  ros::NodeHandle n;
  ros::ServiceClient client = n.serviceClient<svcsrv::Foo>("pub_twist");

  svcsrv::Foo::Request req;
  svcsrv::Foo::Response resp;

  req.linear.x = 3.0;
  req.linear.z = 4.0;

  if (client.call(req, resp))
  {
    ROS_INFO_STREAM("Received pub_twist response: " << "linearX==" << resp.linear.x << " linearZ==" << resp.linear.z);
  }
  else
  {
    ROS_ERROR("Failed to call service pub_twist");
    return 1;
  }

  return 0;
}

When I run rosnode info it displays that the node should be able to publish to subpose_node/cmd_vel:

Connections:
 * topic: /rosout
    * to: /rosout
    * direction: outbound
    * transport: TCPROS
 * topic: /subpose_node/cmd_vel
    * to: /rostopic_15809_1534959147174
    * direction: outbound
    * transport: TCPROS
 * topic: /subpose_node/cmd_vel
    * to: /subscribe_to_twist
    * direction: outbound
    * transport: TCPROS

However subscriber NEVER receives any message. Any idea what I'm missing out here?

What's puzzling is that if I replace the service node code with the following code in works perfectly fine:

#include <stdlib.h>
#include <iomanip>
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <std_srvs/Empty.h>

bool toggle_pub = false;
bool togglePub(
  std_srvs::Empty::Request &req,
  std_srvs::Empty::Response &resp
) {
    toggle_pub = !toggle_pub;
    ROS_INFO_STREAM("Toggled send of a message:"
            << toggle_pub);
    return true;
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "toggle_pubsvc");
    ros::NodeHandle nh;

    // register service with the master
    ros::ServiceServer server = nh.advertiseService("toggle_pubsvc", &togglePub);

    // publisher
    ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("subpose_node/cmd_vel", 1000);
    ros::Rate rate(2);

    while(ros ...
(more)
edit retag flag offensive close merge delete

Comments

Sorry for being a beginner. Wow, this place can be really hostile. I'll try to avoid asking any more questions on this forum. As I said before thanks for your time and sorry for bothering anyone here.

milosgajdos gravatar image milosgajdos  ( 2018-08-22 15:14:51 -0500 )edit

My apologies if you found that comment too direct. You're completely welcome to ask questions.

I just wanted to highlight something I see a lot of people do: draw conclusions based on single / very few observations. It was not a critique on your question or your workflow.

gvdhoorn gravatar image gvdhoorn  ( 2018-08-22 15:17:58 -0500 )edit

@milosgajdos: I've restructured our comment-comment interaction a bit and summarised it into an actual answer.

I've left your expression of the sentiment that ROS Answers is a hostile place and my response as a comment under your question.

My apologies again if you feel that it was too direct.

gvdhoorn gravatar image gvdhoorn  ( 2018-08-23 06:04:54 -0500 )edit

Lets not generalise over all of ROS Answers based on a single interaction and give others a chance to prove you wrong.

gvdhoorn gravatar image gvdhoorn  ( 2018-08-23 06:10:54 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2018-08-22 14:19:11 -0500

gvdhoorn gravatar image

updated 2018-08-23 06:41:24 -0500

(this is a rewrite / summary / edit of the many comments that @milosgajdos and I exchanged)

However subscriber NEVER receives any message. Any idea what I'm missing out here?

As a direct answer: this is most likely caused by the fact that there is too little time between creating the Publisher instance (ie: advertise(..)ing it) and invoking publish(..) on it.

Even though the subscribing node is already around, the middleware doesn't have enough time to setup a connection between the publisher and subscriber, leading to the message being lost.

As there are no brokers in ROS that keep 'old' messages around (in a sort of node-independent global queue) like MQTT fi, a message published while there are no subscribers around to receive it will be dropped immediately.

What's puzzling is that if I replace the service node code with the following code in works perfectly fine

This is because the alternative code publishes messages in a loop: so even if the first one (or few) are lost, new ones are constantly being published. After the connection between publisher and subscriber has been setup, the new ones get delivered to the subscriber and it invokes the poseMessageReceived(..) callback.

Does message publishing ONLY work when sent continuously in a loop? In other words: single message publish is not possible in ROS?

Publishing single messages is perfectly supported, but because of the above, you'll have to take a little extra care to make sure that it works in all cases. For pub-sub connections that have been created earlier, publishing a single message does not need anything special. In the case you show here though -- with a publisher being created and a single message being published almost immediately -- it pays to check whether the connection process has completed. There is API for that: Publisher::getNumSubscribers(). The typical approach would be to wait in a while-loop (with a ros::Rate or a sleep(..) in the body) some appropriate time and only continue publish(..)ing if/when subscribers have connected.

I was working with an assumption that I'd start subscriber first and once it was running I could publish to the queue, then the messages eventually get delivered to the subscriber. My understanding was that the message is sent to the "local" queue from which it will eventually get sent to the remote host subscriber

Queues are local to the process that hosts the ROS node (ie: the program that calls ros::init(..) and instantiates Publisher objects). As @Reamees mentions, these queues are per-node, so two Publishers in the same node publishing to the same topic will share a queue. As there is no broker or other out-of-node infrastructure that handles the distribution of messages, subscibers that are not connected will not get any messages if they "join late".

is there anywhere I read more about how the whole model actually works?

I'm not sure it covers all of this in detail, but for more info on the ... (more)

edit flag offensive delete link more

Comments

I expect the subscriber successfully reading the message published in the original code? Does message publishing ONLY work when sent continuously in a loop? In other words: single message publish is not possible in ROS?

milosgajdos gravatar image milosgajdos  ( 2018-08-22 14:21:43 -0500 )edit

Thanks for clearing this up for me: I was working with an assumption that I'd start subscriber first and once it was running I could publish to the queue, then the messages eventually get delivered to the subscriber. My understanding was that the message is sent to the "local" queue...

milosgajdos gravatar image milosgajdos  ( 2018-08-22 14:35:53 -0500 )edit

from which it will eventually get sent to the remote host subscriber. Clearly my assumptions were wrong: is there anywhere I read more about how the whole model actually works? as for the example: it's a totally toy example -- no real life use case - I wanted to write a service that publishes a msg

milosgajdos gravatar image milosgajdos  ( 2018-08-22 14:37:24 -0500 )edit

Thanks, this clears up a lot of things in my head. Like I said I was clearly making incorrect assumptions about how the ROS pub/sub works - even when I keep the subscriber running for several minutes before I start the publisher the message doesnt get received. I'll have to check the code I guess

milosgajdos gravatar image milosgajdos  ( 2018-08-22 14:44:52 -0500 )edit

that is perfectly possible, but then I would have expected the call to publish(..) to appear in the body of the service callback. Not right after initialisation.

Yes originally the publish(..) code was in the body of the callback - I put it back to the main to test something else.

milosgajdos gravatar image milosgajdos  ( 2018-08-22 14:46:26 -0500 )edit

Thanks for clearing so many questions for me today @gvdhoorn -- I really appreciate it, and your patience.

milosgajdos gravatar image milosgajdos  ( 2018-08-22 14:47:48 -0500 )edit

One last thing: what is actually performing the message delivery? Is it roscore node? Or is it publisher itself? I mean the actual data transfer part...or is there some ROS thread which does that in the background?

milosgajdos gravatar image milosgajdos  ( 2018-08-22 14:51:16 -0500 )edit
1

Offtopic, something I happened upon recently. The queues are not per publisher as mentioned in the comments above, but are instead by topic. If you have two publishers to one topic the last specified que is used. ros_comm issue

Reamees gravatar image Reamees  ( 2018-08-23 03:12:46 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2018-08-22 12:56:12 -0500

Seen: 712 times

Last updated: Aug 23 '18