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

writing first node, have some questions about the Subscriber

asked 2012-12-28 08:42:19 -0600

joe.s gravatar image

updated 2012-12-28 08:51:51 -0600

I'm writing my first node and there are a few things that I don't quite understand and am looking for some clarification. (This node will read Float64 messages from the /phidgets_ros/interface_kit node and then publish a cmd_vel)

I've read through the http://www.ros.org/wiki/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29 (Writing a Simple Publisher and Subscriber (C++)) and still have some questions, specifically about the Subscriber.

I've defined my publisher and subscriber as

youbot_flexiforce_sensor_touch::youbot_flexiforce_sensor_touch()
{
   cmd_vel_ = nh.advertise<youbot::Velocity>("cmd_vel", 1);
   sens_sub_ = nh.subscribe<std_msgs::Float64>("/phidgets_ros/interface_kit/116807/sensor/1", 1, &flexiCallback, this);
}

where "/phidgets_ros/interface_kit/116807/sensor/1" is where the messages are being sent from (of type Float64)

My question then is regarding how that message is stored for use later in my node.

void youbot_flexiforce_sensor_touch::flexiCallback(const std_msgs::Float64::ConstPtr& msg)
{
stuff
}

I'm not understanding how the tutorial is explaining where the data is stored. In the tutorial, "msg" is the data (a string) and has a pointer pointing to it... am I misunderstanding that? Why not just keep it in a variable that is updated?

I'm a bit confused and could use a point in the right direction... thank you

EDIT: bad spilling

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
2

answered 2012-12-28 10:47:12 -0600

Mac gravatar image

Two things are happening here.

First, there's some behind-the-scenes stuff ROS does. Specifically, when you subscribe to something, your node communicates with the ROS master to figure out who's publishing on that topic. Then, your node sets up a peer-to-peer connection with every publisher, and gets ready to receive messages. When a message comes in, it deserializes it and then calls your callback with the message as the argument.

Second, your callback runs, and you do whatever you want.

So, the message is in the msg argument of the callback you defined above. To avoid an extraneous copy, it's actually in a const boost::shared_ptr (typedef'd to message_type::ConstPtr). You can then do with this message whatever you'd like; copy it, just copy the pointer, process it, or whatever.

There are myriad reasons not to just keep it in a variable: the simplest is that that would require you to implement polling yourself, rather than just a callback function that's called whenever a message arrives. The race conditions &c that polling introduces are fairly painful; the callback technique is much simpler.

Something to keep in mind: every time your callback is called, it's with a different message: if you want to save older versions (say, to average over so that your cmd_vel results are smooth), you'll have to do that yourself.

edit flag offensive delete link more

Comments

Ok. I'm trying to translate in to terms I understand... so, it's easier to use the msg stored in a pointer because it's easier to pass that to other functions in your node? Here I mean functions in the mathematical sense... not separate functions like in code.

joe.s gravatar image joe.s  ( 2012-12-29 06:06:22 -0600 )edit
1

IIRC (and it's been awhile), you can, in fact, have your callback take the message by value, not by pointer, and the right thing will happen; you'll get a deep copy. But if you're dealing with large objects, why pay for the copy?

Mac gravatar image Mac  ( 2012-12-29 09:05:38 -0600 )edit

Question Tools

Stats

Asked: 2012-12-28 08:42:19 -0600

Seen: 458 times

Last updated: Dec 28 '12