mathematical calculation on 2D matrix(Implementation of 2 nested for loop )
Hi all; As I understand, the 2D matrix in the ROS in not available until now and for this reasn, a definition of a msg that its variable is a msg of 1D should be done. But, I would like to know how I can implement the following code: 1-define a 2D matrix named mat[m][n]; (m*n)
I write the following messages: array 2d.msg and array 1d.msg. Is it a problem in my definition?
array2d.msg
array 1d[] mat;
array 1d.msg
int8[] a;
2- Implementation of 2 nested for loop The one of simple code for do some mathematical calculation on matrix is presented in the following:
for (i=starti; i<m, i++)
for (j=starti; j<n, j++)
{mat[i][j]=mat[i+1][j]+2;}
Clearly, what I want to do is to do some mathematical functions on elements of matrix named mat. I write the simplest code of mathematical calculation in the previous lines. It is your kindness if you translate these lines to ROS code to give an idea to how to implement mathematical calculation with elements of 2D matrix.
Thanks for your help;
Fi
Asked by Fi on 2015-06-16 22:23:00 UTC
Answers
The multi-array messages in std_msgs are very useful for sending matrices. All of these message definitions include a MultiArrayLayout message and just a simple array. For example, check out the definition of the Float32MultiArray. The MultiArrayLayout
describes the size and shape of the matrix. This allows a node receiving one of these messages to properly unpack the array into a multidimensional array without requiring a priori knowledge of the matrix structure.
If you are trying to do mathematical calculations on those matrices in C++, it's probably worth checking into using a standard package for matrix math such as Eigen.
EDIT
As requested, I've written a few simple demos. The demo consists of a Python script that fills out a 3x3 matrix using random integers in [0,10) and publishes that matrix as a Float32MultiArray
on the /sent_matrix
topic. There is then a C++ receiver that listens to that topic. In the callback I first access a few elements of the message using the formula in the MultiArrayLayout documentation, and I then convert the entire message into an Eigen::MatrixXf
. Once I have that Eigen matrix I do a few simple matrix math operations and print them to the terminal. Finally I attempt to implement the nested for loop that was described in the original question. The entire ROS package is available at this gist: https://gist.github.com/jarvisschultz/7a886ed2714fac9f5226
The relevant Python code for filling out the matrix is below:
mat = Float32MultiArray()
mat.layout.dim.append(MultiArrayDimension())
mat.layout.dim.append(MultiArrayDimension())
mat.layout.dim[0].label = "height"
mat.layout.dim[1].label = "width"
mat.layout.dim[0].size = 3
mat.layout.dim[1].size = 3
mat.layout.dim[0].stride = 3*3
mat.layout.dim[1].stride = 3
mat.layout.data_offset = 0
mat.data = [0]*9
dstride1 = mat.layout.dim[1].stride
offset = mat.layout.data_offset
while not rospy.is_shutdown():
for i in range(3):
for j in range(3):
num = random.randrange(0,10)
mat.data[offset + i + dstride1*j] = num
The relevant C++ code for performing the original question could be boiled down to:
void matrixcb(const std_msgs::Float32MultiArray::ConstPtr& msg)
{
float h = msg->layout.dim[0].size;
float w = msg->layout.dim[1].size;
std::vector<float> data = msg->data;
Eigen::Map<Eigen::MatrixXf> mat(data.data(), h, w);
Eigen::MatrixXf newmat = mat;
for (int i=0; i<h-1; i++)
for (int j=0; j<w; j++)
newmat(i,j) = mat(i+1,j)+2;
std::cout << "newmat = " << std::endl << newmat << std::endl;
return;
}
Asked by jarvisschultz on 2015-06-17 08:02:42 UTC
Comments
Thanks Jarvi Would you please write the code for simple aboving example code by MultiArray to have a better understand of it?
Asked by Fi on 2015-06-17 13:38:30 UTC
Thanks Javri; Would you please give me an example of using Eigen to work with matrix?
Asked by Fi on 2015-06-18 14:42:00 UTC
Thanks Jarvi for sharing the code. I really appreciate it. However, i"m thinking if there is any solution that can run faster than this method. Running them in the for loop might take time esp in image pixel where the resolution is high. Again, thank you. If eventually, the data in std_msgs/Float32MultiArray Message will be in one dimensional data, i wonder what's the point of using Float32MultiArray. Appreciate it if you can enlighten me. Thanks
Asked by okkewei on 2023-05-23 00:14:24 UTC
@okkewei the Float32MultiArray
is a generic ROS message for arbitrarily-sized matrix data. If you are looking for a standardized, generic message then this might fit the bill. If you have a more specific use-case you can always create your own messages. If you are specifically working with images (as mentioned in the comment), you probably should be working with, for example, sensor_msgs/Image
(which also stores the rows/columns/channels of an image as a single one-dimensional array). Storing multidimensional arrays as "vectors" and then just keeping track of how to map the entries is a very common technique not just for serialization/transmission (like in the ROS messages), but also for working with the arrays in memory. For example, that's exactly how Eigen
or OpenCV
stores an Eigen::Matrix
or a cv::Mat
, respectively.
Asked by jarvisschultz on 2023-06-12 17:17:09 UTC
Comments