0
$\begingroup$

Rosanswers logo

Not too much info on these (or any of the variants) on the wiki: what is the proper way to initialize these? I've tried:

const unsigned int data_sz = 10;
std_msgs::UInt8MultiArray m;

m.layout.dim.push_back(std_msgs::MultiArrayDimension());
m.layout.dim[0].size = data_sz;
m.layout.dim[0].stride = 1;
m.layout.dim[0].label = "bla";

// only needed if you don't want to use push_back
m.data.resize(data_sz);

for an array with 10, 1 byte elements, but I keep getting segfaults at the subscriber callback when accessing the data member (FIXED: see edit).

I couldn't find any examples anywhere, apart from http://alexsleat.co.uk/tag/multiarray/, but those snippets do not initialize any dimensions.

Is it programmers responsibility to keep the dimension objects in sync with the actual size of the data member, or is ROS doing some magic behind the scenes at serialization?


edit: as @Lorenz commented: reserve -> resize. I've left the bit about the segfaults in the question, even though that was fixed.


Originally posted by ipso on ROS Answers with karma: 1416 on 2012-06-25

Post score: 7


Original comments

Comment by Lorenz on 2012-06-25:
reserve might not do what you expect. It just causes the vector to allocate more memory but doesn't change its size, i.e. a call to vector's size method will still return 0. Instead, use the method resize.

Comment by ipso on 2012-06-25:
yes, just GDBed myself to that conclusion as well. Should've read the docs more carefully. Thanks for your reply. Point about the documentation on the whole MultiArray thing being really thin / non existent stands though (imho).

$\endgroup$

3 Answers 3

0
$\begingroup$

Rosanswers logo

Have a look at the definition of the messages. The file UInt8MultiArray contains a comment:

# Please look at the MultiArrayLayout message definition for
# documentation on all multiarrays.

The file MultiArrayLayout.msg contains the following:

# The multiarray declares a generic multi-dimensional array of a
# particular data type.  Dimensions are ordered from outer most
# to inner most.

MultiArrayDimension[] dim # Array of dimension properties
uint32 data_offset        # padding bytes at front of data

# Accessors should ALWAYS be written in terms of dimension stride
# and specified outer-most dimension first.
# 
# multiarray(i,j,k) = data[data_offset + dim_stride[1]*i + dim_stride[2]*j + k]
#
# A standard, 3-channel 640x480 image with interleaved color channels
# would be specified as:
#
# dim[0].label  = "height"
# dim[0].size   = 480
# dim[0].stride = 3*640*480 = 921600  (note dim[0] stride is just size of image)
# dim[1].label  = "width"
# dim[1].size   = 640
# dim[1].stride = 3*640 = 1920
# dim[2].label  = "channel"
# dim[2].size   = 3
# dim[2].stride = 3
#
# multiarray(i,j,k) refers to the ith row, jth column, and kth channel.

Originally posted by Lorenz with karma: 22731 on 2012-06-25

This answer was NOT ACCEPTED on the original site

Post score: 2


Original comments

Comment by ipso on 2012-06-25:
Thanks. I've actually read those comments in the msg def. I guess my question was more 'why are there so few (none) actual (C++) examples for this?' than 'what is the meaning of all these fields?'. Simultaneously programming in 3+ languages also doesn't help.

Comment by Lorenz on 2012-06-25:
I guess people just don't use this kind of really generic messages. It's always better to define a message with meaningful slot names instead of using generic message types for everything.

Comment by user23fj239 on 2016-02-15:
Could someone extend on how to create multiple arrays I dont get the dim[i]-stuff and where to put it ? Also why push an multiarray into the same multiarray, m.layout.dim.push_back(std_msgs::MultiArrayDimension());

$\endgroup$
0
$\begingroup$

Rosanswers logo

The snippet in my original post is basically how you initialize MultiArrays. Just push_back() a new std_msgs::MultiArrayDimension for each dimension and set it up according to the docs @Lorenz referenced.

Using resize(n, std_msgs::MultiArrayDimension()) should also work.


Originally posted by ipso with karma: 1416 on 2012-06-26

This answer was ACCEPTED on the original site

Post score: 0


Original comments

Comment by user23fj239 on 2016-02-15:
could you please extend on it via the push_back() approach?

$\endgroup$
0
$\begingroup$

Rosanswers logo

Hy, following a working code tried on an Arduino Mega and ROS Kinetic: Commands in ROS:

$ roscore

//New terminal

$ rosrun rosserial_python serial_node.py /dev/ttyACM0 _baud:=115200

//New terminal

$ rostopic echo /arr

Arduino Code for Publishing an array with 4 words:

#include <ros.h>
#include <std_msgs/UInt16MultiArray.h>

ros::NodeHandle nh;

std_msgs::UInt16MultiArray arr;
ros::Publisher pub_arr( "/arr", &arr);

void setup() {
  nh.getHardware()->setBaud(115200);
  nh.initNode();
  arr.layout.dim = (std_msgs::MultiArrayDimension *)
  malloc(sizeof(std_msgs::MultiArrayDimension)*2);
  arr.layout.dim[0].label = "height";
  arr.layout.dim[0].size = 4;
  arr.layout.dim[0].stride = 1;
  arr.layout.data_offset = 0;
  arr.data = (int *)malloc(sizeof(int)*8);
  arr.data_length = 4;
  nh.advertise(pub_arr);

}

void loop() {    
  arr.data[0] = 1;
  arr.data[1] = 2;
  arr.data[2] = 3;
  arr.data[3] = 4; 
  pub_arr.publish(&arr);
  nh.spinOnce();
}

Originally posted by mtROS with karma: 92 on 2017-04-26

This answer was NOT ACCEPTED on the original site

Post score: 3

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.