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

Push vector into `MultiArray`-Message and publish it

asked 2016-02-15 13:56:54 -0600

user23fj239 gravatar image

updated 2016-02-17 05:28:23 -0600

I simply try to push multiple vector<double> into the message format, but can not figure it out also I looked at this and this.

     std_msgs::Float64MultiArray msg;
    vector<double> vec1 = { 1.1, 2., 3.1};
    vector<double> vec2 = { 3., 4.1, 2., 3.1};

     vector<double>::const_iterator itr, end(vec.end());
    for(itr = vec.begin(); itr!= end; ++itr) {
            // how to use the pointer  *itr here? to push vec1 and vec2 into msg ?
    }

//I also want to specify the layout and tried to use some of these lines:

    msg.data.clear();
    msg.layout.dim.push_back(std_msgs::MultiArrayDimension());
    msg.layout.dim[0].size = *da;
    msg.layout.dim[0].stride = 1;
    msg.layout.dim[0].label = "typ i";


Edit: Solution
So as said below one cannot push multiple arrays(vector is basically 1D-array) into one message as originally thought. So it does not behave like a container object for multiple variables but only holds one i-D array.
To fix this I could sum up all vectors into one 2-D array and push it into the msg: The title MultiArray is quite misleading then, but once known its ok.
(I could not get to work with data.extend(..)

edit retag flag offensive close merge delete

Comments

sorry for the typo. updated my answer with the correct field name.

ahendrix gravatar image ahendrix  ( 2016-02-16 11:27:42 -0600 )edit

I confused the python extend() with the C++ vector's insert(). Answer updated and should work now. Note that insert() is faster than an element-by-element push, because it only expands the size of the vector once.

ahendrix gravatar image ahendrix  ( 2016-02-17 12:05:24 -0600 )edit

Explanations on insert() can be found here, furthermore this leads back to pushing multiple vectors inside the array: make all have same vec.size() and specify it in the .stride. So each row represents one vector.

user23fj239 gravatar image user23fj239  ( 2016-02-18 04:23:21 -0600 )edit

2 Answers

Sort by ยป oldest newest most voted
6

answered 2016-02-15 22:03:21 -0600

ahendrix gravatar image

updated 2016-02-17 12:03:11 -0600

MultiArray messages are for publishing multi-dimensional arrays; not for publishing multiple arrays within the same message.

For example, a vector or list is a one-dimensional array, and a matrix would be a two-dimensional array.

You need to set up the dim array with the dimensions of your array. For a 1-d array, one element with the length. For a 2-d array or matrix, your dim array would have two elements; one for the height of the matrix, and a second for the width of the matrix.

Once you have dim set up, you store your data in the data field in row-major order.

As an example, if you wanted to put your vec1 in a MultiArray, you would do:

vector<double> vec1 = { 1.1, 2., 3.1};
std_msgs::Float64MultiArray msg;

// set up dimensions
msg.layout.dim.push_back(std_msgs::MultiArrayDimension());
msg.layout.dim[0].size = vec1.size();
msg.layout.dim[0].stride = 1;
msg.layout.dim[0].label = "x"; // or whatever name you typically use to index vec1

// copy in the data
msg.data.clear();
msg.data.insert(msg.data.end(), vec1.begin(), vec1.end());
edit flag offensive delete link more

Comments

Why do you need the clear() call on msg.data?

2ROS0 gravatar image 2ROS0  ( 2017-03-28 10:48:52 -0600 )edit

It's not necessary in this example, but it's nice to clear the array if you're re-using the same message object.

ahendrix gravatar image ahendrix  ( 2017-03-28 17:15:10 -0600 )edit
3

answered 2016-02-17 05:23:31 -0600

user23fj239 gravatar image

updated 2016-08-14 12:56:06 -0600

Here is a complete example (please edit if any mistakes found)

vector<double> vec;
while (ros::ok()){
    int i = 0;
    std_msgs::Float64MultiArray msg;
    vec = c.getvec(typ); //function which initializes the vector

    msg.layout.dim.push_back(std_msgs::MultiArrayDimension());  
    msg.layout.dim[0].size = vec.size();
    msg.layout.dim[0].stride = 1;
    msg.layout.dim[0].label = strings[typ+4];


    //push data into data blob
    vector<double>::const_iterator itr, end(vec.end());
    for(itr = vec.begin(); itr!= end; ++itr) {
        //cout<<*itr<<endl;
        msg.data.push_back(*itr); 
    }/**/

    chatter_pub.publish(msg);
    ros::spinOnce();

    //clear stuff and sleep
    vec.clear();
    loop_rate.sleep();
}

The result on rostopic echo looks like:

layout: 
  dim: 
    - 
      label: /listener_socket/orient
      size: 6
      stride: 1
  data_offset: 0
data: [35589264796691.0, 3.0, 3.0, 167.94601, 1.6419868, 0.15967418]
---
edit flag offensive delete link more

Comments

how to assign data into defined indices for example a[2] = 12.

james P M gravatar image james P M  ( 2021-11-21 06:18:35 -0600 )edit

Question Tools

2 followers

Stats

Asked: 2016-02-15 13:56:54 -0600

Seen: 24,956 times

Last updated: Aug 14 '16