How would I publish a 2D float Array through a ROS message?
I am currently working on a circle detection app. Using OpenCV
, I get a std::vector<std::vector<float>>
named v
. Now I want to send this to a different executable node. So I made a simple Circles.msg which is:
float32[][] circles
However, I get a bunch of errors, mostly which are:
'const class std::vector<std::vector<float> >' has no member named '__getMD5Sum'
From the line:
circle_pub_.publish(v);
which I get from:
ros::Publisher circle_pub_;
circle_pub_ = node.advertise("/circles", 1);
So therefore, I don't know how to approach this problem.
I also do not understand how to subscribe to this topic. Currently I got:
circles_in = node.subscribe("/circles", 1, organizer_callback);
void organizer_callback( const std::vector< std::vector<float> >& circles) {
....
}
Is this okay? Please let me know if you know any more information!
The Code
Here is the most important parts of my program as of now:
class ImageConverter {
ros::NodeHandle nh_;
image_transport::ImageTransport it_;
image_transport::Subscriber image_sub_;
image_transport::Publisher image_pub_;
ros::Publisher circle_pub_;
public:
ImageConverter()
: it_(nh_)
{
// Subscribe to the Bottom Raw Image
image_sub_ = it_.subscribe("/ardrone/bottom/image_raw", 1,
&ImageConverter::imageCb, this);
// Advertisng the Circles being detected from this
circle_pub_ = nh_.advertise<zlab_drone::Circles>("/circles", 1);
}
void imageCb(const sensor_msgs::ImageConstPtr& msg)
{
// Find the circles from a particular video
cv::vector<cv::Vec3f> circles;
cv::HoughCircles(img_bin, circles, CV_HOUGH_GRADIENT, 1, 70, 140, 15,
20, 400);
std::vector<zlab_drone::Circle> v;
for(int i = 0; i < circles.size(); ++i) {
const cv::Vec3f& c = circles[i];
v[i][0] = c[0];
v[i][1] = c[1];
v[i][2] = c[2];
}
circle_pub_.publish(v);
}
};
Subscriber
Here's the code from my subscriber:
// Gathering Data from the messages
for (std::vector<zlab_drone::Circles>::const_iterator gp =
msg->circles.begin(); gp!= msg->circles.end(), ++gp) {
for (std::vector<float>::const_iterator dp =
gp->circle.begin(); dp != gp->circle.end(); ++dp) {
circles[gp][dp] = gp->circle(dp);
}
}
Just a general comment: you can't publish/subscribe arbitrary datatypes, as you are trying to do, only messages (ie: specially crafted containers that are declaratively described in
.msg
files). @suforeman's answer shows how you could nest two such msgs to get a 2d array.@gvdhoorn Makes sense. However, when I implemented @suforeman's answer, I retained all the same errors.
Well without seeing what you did exactly, it's hard to know what could be wrong, but I know from experience that what @suforeman suggests works.
@gvdhoorn I have added the most relavant bits of code in the question now. I have also implemented what @suforeman has implemented.
Your latest edit suggests you're still not using message definitions / classes, but
std::vector<std::vector<float>>
.@gvdhoorn I still haven't understood how the publisher would be? I have edited the code to the most correct versions right now.
You still appear to be trying to defining your topic subscriber without using your message definition. Compare your callback with the one in my answer's example. Try to get your subscriber working first. You can test your subscriber from the command line using
rostopic
.@ suforeman I have made the subscriber work exactly as you specified within your answer.