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

Revision history [back]

I can help clear up the questions about ROS MultiArray messages, but first as has been suggested I can show you how to define a custom message specifically for your ground penetrating RADAR sensor. The language of ROS message files is described here, as well as a description how to update your CMakeLists.txt file so that they will be built correctly.

The idea here is to define a message type which represents a sample and another message type which contains an array of these samples along with any additional data. Keeping in mind that ROS uses SI units by convention. First the sample message:

GPRSample.msg

# Ground Penetrating Radar Sample Message
float32 delay_secs
float amplitude

I'm not sure if your sensor produces an amplitude metric in units at all or if you get an un-quantified integer value. This could be an example where we don't use SI units in ROS, the laser_scan message for example uses a float32 of no unit to describe reflected pulse intensity because none of the LIDAR manufacturers I know of publish the units of the intensity data their sensors produce.

GPREcho.msg

# Ground Penetrating Radar Echo Message
Header header

# power emitted by Radar (just a guess, don't know if this is relevant)
float emitter_power_watts

# variable length array of gpr samples
GPRSample[] samples

When these two message are built you can then use in python as below

from <your_package_name>.msg import GPRSample
from <your_package_name>.msg import GPREcho
def make_message():
    gpr_msg = GPREcho()
    for i in range(10):
        gpr_sample = GPRSample()
        gpr_sample.delay_secs = i / 1000000000.0
        gpr_sample.amplitude = 10 * sin(i)
        gpr_msg.samples += [gpr_sample]

    gpr_msg.emitter_power_watts = 10
    gpr_msg.header.frame_id = "sensor_frame"
    gpr_msg.header.stamp = rospy.get_rostime()
    return gpr_msg

Using custom messages in this way means that there is useful meta-data along with your raw values, so that other developers and parts of the ROS system can know exactly what the data is. This is not possible with a simple matrix of values, the solution above is how we would recommend you solve this problem. However I will also address your questions about ROS MultiArrays because you're not the first and won't be the last person to be confused by them.

All of the MultiArray messages specify a 1 dimensional flat array which contains the actual data within the array. As well as this it also defines the structure of an n dimensional array which maps onto this 1 dimensional data, this allows it to represent a 3D cube of data, a 2D matrix, a 4D tensor, anything you want. However this power also makes it quite complicated to use in simple cases.

Taking your use case you want to define a 2D matrix of size 2x4096, and we'll use row-major ordering. Create a FloatMultiArray message and put the data into first as a flat array of 8192 elements.

msg = Float32MultiArray()
msg.data = my_data.reshape([8196])

Now we need to define the layout so that ROS knows this data is actually a 2x4096 matrix:

# This is almost always zero there is no empty padding at the start of your data
msg.layout.data_offset = 0 

# create two dimensions in the dim array
msg.layout.dim = [MultiArrayDimension(), MultiArrayDimension()]

# dim[0] is the vertical dimension of your matrix
msg.layout.dim[0].label = "channels"
msg.layout.dim[0].size = 2
msg.layout.dim[0].stride = 8196
# dim[1] is the horizontal dimension of your matrix
msg.layout.dim[1].label = "samples"
msg.layout.dim[1].size = 4096
msg.layout.dim[1].stride = 4096

The stride in these dimensions refers to how many samples along the next higher dimension is. So in the case of the samples, there is a stride of 4096 to the next sample. In the case of dimension zero there is no higher dimension so the stride is the overall size of the message data.

I hope this clears some of this up for you. I do recommend defining custom messages though, it's a bit of a pain at first but when you get used to it you'll never look back.