How publish\subscribe an array topic in c++(such as ros::publish pub[i])
Hi everyone, I am a new person to C++. Recently, I have notice another way to publish/subscribe a series of topics. Like:
std_msgs::Float64 msg[5];
ros::Publisher pub[5];
ros::Subscriber pub[5];
string name[5] = {"0", "1", "2", "3","4"}
int main(int argc, char **argv)
{
ros::init(argc, argv, "topic");
ros::NodeHandle nh;
for(int i=0; i<5 ;i++)
{
pub_cmd[i]=_n.advertise<std_msgs::Float64>(name[i], 1);
sub_js[i]=_n.subscribe(name[i], 1, callback);
}
.....
.....
This seems to make the code more simple.ROS WIKI don't seems to mention this method.It look quiet different from the example. How does this work?
In my reference learning routine, whatever how many pub has been subscribe, there is only one callback funtion for subscriber.
5 subscriber
for(int i=0; i<4; i++)
{
std::string joint_state_name="arm_joint_";
std::string joint_num=boost::lexical_cast<std::string>(i+1);
joint_state_name.append(joint_num);
joint_state_name.append("_controller/state");
sub_js[i]=_n.subscribe(joint_state_name, 1, &ArmHWInterface::read, this);
}
but 1 callback funtion
void ArmHWInterface::read(const dynamixel_msgs::JointStateConstPtr &msg)
{
......
}
Thank you!
Asked by Heho on 2020-06-06 09:20:31 UTC
Comments
Hi @Heho,
I was not able to understand you in this part: "If I want to assign another_msg[5] from msg[5] which was subscribe from the talker(value should obey the array index), how do I edit the callback funtion?"
What are you trying to achieve, 5 publisher that publish each msg position value and 5 subscriber with different calback processing functions?
Asked by Weasfas on 2020-06-07 08:26:13 UTC
@Weasfas I want to subscribe 5 topic with only one callback funtion(like the example I just update in question).And I don't know how to distinguish whether sub_js[1] or sub_js[3] triger the callback funtion. And I try to write such like
for(xxx;xxx;xxx)pos[i]=msg->data;
in callback to get the msg value but fail to compile.Asked by Heho on 2020-06-07 09:23:02 UTC
So, if you want to process 5 topic inputs with one callback you can just declare 5 subscriber with the same callback, however, since you want to distinguish between callback something tells me that you want to process data in different way thus you will need more than one callback signature. From this forum: "The usual ROS practice is to distinguish topics, but decouple subscribers from worrying about which node published each message". Hence, there is no way to differenciate the incoming msgs unless your msg data type contains a univocal key that tells you its origin (this can be done generating a custom msg or wraping a standard msg type with you custom source flag).
On the other hand, have you considered the message_filter approach?
Asked by Weasfas on 2020-06-07 09:46:49 UTC
While I agree it's not wise to implement nodes which depend on knowledge about the publishers of a message, it is actually technically possible to figure out which node published a message without the need for custom messages.
See wiki/roscpp/Overview/Publishers and Subscribers - MessageEvent.
Asked by gvdhoorn on 2020-06-07 09:58:34 UTC
Hi @Weasfas .I have succeed in the way to use msg data type contains a univocal key. But fail with the "message_filter" approach. It seems can not filter by only one type of message? My code doesn't even compile.
with
void subcallback(const geometry_msgs::Vector3::ConstPtr& msg0, const geometry_msgs::Vector3::ConstPtr& msg1, const geometry_msgs::Vector3::ConstPtr& msg2)
Asked by Heho on 2020-06-08 10:42:03 UTC
Hi @Heho, Of course you can use a
messsage_filter
with multiple topics with the same msg type. The main problem of the code you provided is that you have to declare theTimeSynchronizer
to accept every incoming msg. That is, if you have three different topics with the same message type:In addition, take into account that the
message_filter
only works if the message definition contains a stamp. That is because themessage_filter
implementation synchronizes incoming channels by the timestamps contained in their headers. So appart from changing theTimeSynchronizer
declaration you will need to add a stamp to those msgs.Asked by Weasfas on 2020-06-08 12:07:57 UTC
@Weasfas But how could I add a stamp to the msgs? I have seen there is no a type named "stamp" include the Message Definition of
geometry_msgs::Vector3
. Should I change the publish msgs type intogeometry_msgs/Vector3Stamped
? I thought maybe stamp can be set up in .header? However, I even don't understand what does the header do in msg........OrzBy the way , as @gvhoorn mention about
MessageEvent
.If all topics are publish from a same publisher, the method.getPublisherName()
may fail to distingish the msgs. So, it's the same idea to use.getConnectionHeader()
to distingish the msgs? Could you mind giving me a simple example about this?Thanks!Asked by Heho on 2020-06-09 09:26:01 UTC
@Heho, yes, when I mentioned stamp I was refering to the std_msgs/Header. And yes, in my case when I needed a stamped message I just wrap the standard message definition to add a
std_msgs/Header
type, like you saidgeometry_msgs/Vector3Stamped
, that is thegeometry_msgs/Vector3
definition but with a header. As for the second question I am sure @gvdhoorn knows more about the topic but I think he was thinkin about different nodes; there is a possibility to use the ConnectionHeader and decode the bytes, but since you are using the same topic and the same node to publish I think there is no way you can distinguish between callbacks.Asked by Weasfas on 2020-06-09 16:59:37 UTC
@Weasfas , my package can't work well. The callback funtion can not be trigger. My source core is here . Could you mind showing me a correct example as a answer? Thank you !
Asked by Heho on 2020-06-12 08:02:49 UTC
Hi @Heho
I have tested your code and you have several problems and bugs:
To avoid blocking the main process you should use
ros::ok()
NOTros::ok
. Publisher Node: You are not updating properly the messages stamps since you are only changing the values at the first lines not the main ROS loop. Change your publisher node main to:Subscriber Node: You may want to use the approximate time polocy instead of an exact one. You can check here how to implement that approach. I should look something like this: next comment.
Asked by Weasfas on 2020-06-12 17:40:26 UTC
This for the last comment:
Asked by Weasfas on 2020-06-12 17:41:21 UTC