Reputation: 425
I try to build my own point cloud with a gaussian distribution. The visualization with rviz doesn't work.
Here is how I create the pointcloud
int sizeOfCloud = 1000;
keypoints.points.resize(sizeOfCloud);
getRandomPointCloud(keypoints, 100, 100, sizeOfCloud);
keypoints.header.frame_id = "base_link";
keypoints.header.stamp = ros::Time::now();
keypoints_publisher.publish(keypoints);
and here is the function getRandomPointCloud:
void getRandomPointCloud(sensor_msgs::PointCloud& pc, int centerX, int centerY, int& sizeOfCloud) {
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<> distX(centerX, 10);
std::normal_distribution<> distY(centerY, 10);
for (int i = 0; i < pc.points.size(); i++) {
double xValue = distX(gen);
double yValue = distY(gen);
std::cout << std::round(xValue) << std::endl;
pc.points[i].x = std::round(xValue);
pc.points[i].y = std::round(yValue);
}
std::cout << "done" << std::endl;
}
As I said, it can't be displayed in rviz. I do select by topic, select the proper topic and then there is nothing on the screen. Topic is correct and if I set the grid to base_link then everything with the topic is okay. Maybe I have to set a special attribute in rviz or I don't build my pointcloud correctly.
Edit:
Here is a screenshot from rviz
Now I think the problem is more about the "base_link" tf topic which can't get resolved. If I try to map my tf tree then there is no entry. How do I set the base_link in my tf tree. Or is there another possibility for my purpose?
Upvotes: 3
Views: 6138
Reputation: 184
You might try zooming out a bit...
and of course ensure the Fixed Frame matches the frame in your message. You can see I also made the points larger (1.0 meter) and used a flat colour to ensure visibility over your enormous scale
Upvotes: 0
Reputation: 1043
The message sensor_msgs::PointCloud pc has an array of Point32 which in turn has x, y and z values. You are setting the x and y values of each point but you are missing the z value.
I'm not sure if the rviz visualizer also requires channel information. If the point cloud is still not visible despite the z value, then set the channel information. The channel is an array in sensor_msgs::PointCloud called channels
which is of type ChannelFloat32. If you have depth information you can use a single channel:
sensor_msgs::ChannelFloat32 depth_channel;
depth_channel.name = "distance";
for (int i = 0; i < pc.points.size(); i++) {
depth_channel.values.push_back(0.43242); // or set to a random value if you like
}
// add channel to point cloud
pc.channels.push_back(depth_channel);
It is also important to publish the message more than once in order to see it in rviz and often when dealing with TF you need to update the time stamp in the header.
Btw you are spreading the points around the point 100meter/10meter thats way out!
Here is the code that works for me
#include <ros/ros.h>
#include <sensor_msgs/PointCloud.h>
#include <string>
#include <random>
void getRandomPointCloud(sensor_msgs::PointCloud& pc,
double centerX,
double centerY,
int& sizeOfCloud) {
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<> distX(centerX, 2.);
std::normal_distribution<> distY(centerY, 2.);
for (int i = 0; i < pc.points.size(); i++) {
double xValue = distX(gen);
double yValue = distY(gen);
pc.points[i].x = xValue;
pc.points[i].y = yValue;
pc.points[i].z =
std::exp(-((xValue * xValue) + (yValue * yValue)) / 4.);
}
sensor_msgs::ChannelFloat32 depth_channel;
depth_channel.name = "distance";
for (int i = 0; i < pc.points.size(); i++) {
depth_channel.values.push_back(pc.points[i].z); // or set to a random value if you like
}
// add channel to point cloud
pc.channels.push_back(depth_channel);
}
int main(int argc, char** argv) {
ros::init(argc, argv, "point_cloud_test");
auto nh = ros::NodeHandle();
int sizeOfCloud = 100000;
sensor_msgs::PointCloud keypoints;
keypoints.points.resize(sizeOfCloud);
getRandomPointCloud(keypoints, 0.5, 0.5, sizeOfCloud);
keypoints.header.frame_id = "base_link";
keypoints.header.stamp = ros::Time::now();
auto keypoints_publisher =
nh.advertise<sensor_msgs::PointCloud>("point_cloud", 10);
ros::Rate rate(30);
while (ros::ok()) {
keypoints.header.stamp = ros::Time::now();
keypoints_publisher.publish(keypoints);
ros::spinOnce();
rate.sleep();
}
return 0;
}
Upvotes: 4