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

Publish one message without while infinite loop

asked 2020-12-10 10:39:04 -0500

mros gravatar image

Hi all, I am using ROS Noetic. I tried to publish one message without "while infinite loop" in the node that I created. In fact, I need just to publish one message from the topic to socketCAN but it doesn't work. I know that the node will be killed but it should publish one message?!! Anybody know why ? Thank you.

edit retag flag offensive close merge delete

Comments

2

We don't know what your code looks like and what message you are trying to publish and where. Please post your code, at least a snippet, so we can get context. Also, please be more detailed in your question. What have you tried so far and what errors you are facing (if any)!

Akhil Kurup gravatar image Akhil Kurup  ( 2020-12-10 11:44:51 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
0

answered 2020-12-10 17:33:59 -0500

danambrosio gravatar image

updated 2020-12-10 17:34:53 -0500

It most likely is the case that your publisher is publishing your message before any subscribers to that message have been connected. It takes a "non-zero" amount of time for the "hand-shaking" to occur through the ROS master and between the publisher/subscriber nodes. You can write a section of code that will wait for a subscriber, publish the message (to that subscriber) then shut down the node. If you immediately shutdown a node after calling publish on a publisher it is not guaranteed that the message was sent and received by the subscriber.

A convenient overload to the advertise function provided by the NodeHandle class allows a client to specify a SubscriberStatusCallback function pointer that gets called when a new subscriber connects to the publisher see the rosdocs.

Here is a simple code example with a std_msgs/String topic:

#include <std_msgs/String.h>

#include <ros/ros.h>

void subscriberConnectCallback(const ros::SingleSubscriberPublisher& publisher)
{
  ROS_INFO("Super cool I got a new subscriber [%s] on the %s topic!", publisher.getSubscriberName().c_str(),
           publisher.getTopic().c_str());

  // Build the message and publish
  std_msgs::String msg;
  msg.data = "super cool";
  publisher.publish(msg);

  // Signal shutdown
  ros::shutdown();
}

int main(int argc, char* argv[])
{
  ros::init(argc, argv, "test_node");

  // Create publisher with private node handle and bind callback to handle subscriber connection
  ros::NodeHandle pnh("~");
  ros::Publisher publisher =
      pnh.advertise<std_msgs::String>("chatter", 1, (ros::SubscriberStatusCallback)subscriberConnectCallback);

  // Spin this node until a shutdown is triggered
  ros::spin();

  return 0;
}
edit flag offensive delete link more

Comments

Hello, Thank you so much for your help, it works well but I had to remove ("~").

mros gravatar image mros  ( 2020-12-11 10:40:28 -0500 )edit
1

@mros If this is the correct answer and it solved your issue, please mark this answer as correct.

jarvisschultz gravatar image jarvisschultz  ( 2020-12-11 11:33:11 -0500 )edit
1

Just for your information, the private node handle is commonly used for publishers and would require a rosrunargument remap or launch remap.

The ability to remap topics/services/actions is useful to prevent hardcoded topics/service names in a node.

danambrosio gravatar image danambrosio  ( 2020-12-11 11:34:46 -0500 )edit
0

answered 2020-12-10 14:18:40 -0500

updated 2020-12-10 14:19:38 -0500

This is probably because the publisher will publish the msg asynchronously and forget about it. What the while loop does is keep publishing the msg again and again so the subscribers can listen in on these msgs and get most (if not all) of the msgs. You can circumvent this by asking the publisher to latch the msg. This will ensure the msg gets read in your case.

Your code will look something like this: (notice the '1' after the queue size in the publisher)

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

    ros::Publisher publishertocan = nh.advertise<can_msgs::Frame>("sent_messages", 100, 1);

    ros::Rate loop_rate(10);
    int count = 0;

    std::string can_device;
    nh.param<std::string>("can_device", can_device, "can0");

    // Form can msg
    can_msgs::Frame message;
    message.header.frame_id = "0";  // "0" for no frame.
    message.header.stamp = ros::Time::now();
    message.is_extended = false;
    message.is_rtr = false;
    message.is_error = false;
    message.id = 0x222;
    message.dlc = 8;
    for (uint8_t i=0; i < message.dlc; i++)
    {
      message.data[i] = i;
    }
    // send the can_frame::Frame message to the sent_messages topic.
    publishertocan.publish(message);
    ROS_INFO_STREAM("sent " << message.id );

    ros::spinOnce();
    loop_rate.sleep();
    count++;

return 0;
}
edit flag offensive delete link more

Comments

Thank you for your reply. By the way, I tried also to send the message 100 or 300 times... but it does not work. It works only with while infinite loop.

mros gravatar image mros  ( 2020-12-10 14:35:48 -0500 )edit

Please test the code I have posted above. It has worked in my tests.

Akhil Kurup gravatar image Akhil Kurup  ( 2020-12-10 14:38:36 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2020-12-10 10:39:04 -0500

Seen: 1,216 times

Last updated: Dec 10 '20