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

How to publish a vector of unknown length of structs in ROS?

asked 2013-04-13 11:13:21 -0600

joshualan gravatar image

I want to publish a vector of unknown length of structs that contain two integers and two strings. Is there a publisher and subscriber in ROS that can do this?

If not, I've been looking at the tutorial of how to create custom messages (which I cannot add a link to because I do not have enough karma) and I figure I can make one .msg file containing:

int32 upperLeft
int32 lowerRight
string color
string cameraID

and another .msg file containing an array of the previous messages. But the tutorial does not give an example of how to use arrays so I do not know what to put in the second .msg file. Furthermore, I am not sure how to even use this custom message in a C++ program.

Any tips on how to do this would be great!

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
45

answered 2013-04-14 18:16:16 -0600

You've got a good start. The right way to do this is to create custom ROS messages for both the "struct" and the "array of structs". In the ROS .msg format, an undefined-length array is defined using the int[] intArray syntax (with no size in the array-brackets).

The specifics of how arrays are handled in ROS messages are described on this wiki page. In particular, the "array handling" section shows that variable-length arrays are interpreted as std::vector in roscpp (C++).

As an example, see the Joint Trajectory Action tutorial. In the armExtensionTrajectory function, the example builds up the goal.trajectory message, which is of type JointTrajectory and contains a variable-length array of JointTrajectoryPoints. As you can see, the variable-length array is built using the usual C++ std::vector methods (push_back, resize, etc.).

Here's a more specific example to address your case above (it's untested, so forgive any typos):

---------------------------------------
imgData.msg
  int32 upperLeft
  int32 lowerRight
  string color
  string cameraID

---------------------------------------
imgDataArray.msg
  imgData[] images

---------------------------------------
demo_pub.cpp
  ros::Publisher pub = n.advertise<my_pkg::imgDataArray>("test", 1000);

  my_pkg::imgData data;
  my_pkg::imgDataArray msg;

  data.upperleft=0; data.lowerRight=100; data.color="red"; data.cameraID="one";
  msg.images.push_back(data);
  data.upperleft=1; data.lowerRight=101; data.color="blue"; data.cameraID="two";
  msg.images.push_back(data);

  pub.publish(msg);

---------------------------------------
demo_sub.cpp
  void subCB(const my_pkg::imgDataArray::ConstPtr& msg)
  {
    for (int i=0; i<msg->images.size; ++i)
    {
      const my_pkg::imgData &data = msg->images[i];
      ROS_INFO_STREAM("UL: " << data.upperleft << "UR: " << data.upperright <<
                      "color: " << data.color << "ID: " << data.cameraID);
    }
  }

  int main(int argc, char **argv)
  {
    ...
    ros::Subscriber sub = n.subscribe("test", 1000, subCB);
    ros::spin();
  }
edit flag offensive delete link more

Comments

1

Thanks, this is extremely helpful!

joshualan gravatar image joshualan  ( 2013-04-15 03:52:07 -0600 )edit

I am grateful to you for this answer. Thanks

Asfandyar Ashraf Malik gravatar image Asfandyar Ashraf Malik  ( 2013-07-01 03:23:39 -0600 )edit

Come to say thank you for this good answer

PaulYang gravatar image PaulYang  ( 2014-01-15 02:07:56 -0600 )edit

Jeremy, Thank you sir!

espkh4 gravatar image espkh4  ( 2014-09-10 02:15:43 -0600 )edit

Thank you for your patience!!!

sunsea_x gravatar image sunsea_x  ( 2014-11-24 07:15:02 -0600 )edit
2

@Jeremy Zoss I understood all of the above but I have one problem. How do I define in my CMakeLists.txt for one message to use a message from the same package? In this case, what do I write in my CMakeLists.txt so it knows to look for the imgData in the same package.

Metalzero2 gravatar image Metalzero2  ( 2015-08-25 07:48:27 -0600 )edit

Small nitpick: It should be images.size() instead of images.size? Also you might not need to create a new msg file just for array because ROS allows to declare individual fields in message as array.

sytelus gravatar image sytelus  ( 2016-05-15 16:46:30 -0600 )edit

@Metalzero2 did you find an answer?

gocarlos gravatar image gocarlos  ( 2016-10-26 15:50:40 -0600 )edit
2

answered 2016-06-15 16:57:15 -0600

Thanks for Jeremy's tips! And in my case I have to do something more to make it working (I'm using Indigo btw):

#include "package_name/msg_file_name.h"

Without the header file the following cannot be done:

const package_name::msg_file_name::ConstPtr &msg

Since it is declared in the header file, which is generated automatically when you customize the CMakeLists.txt file.

edit flag offensive delete link more

Question Tools

8 followers

Stats

Asked: 2013-04-13 11:13:21 -0600

Seen: 49,509 times

Last updated: Jun 15 '16