通过这个案例,将会学习到:

  1. 如何使用PCL创建多个不同的视口展现点云
  2. 如何生成梯形圆柱体形状的点云
  3. 如何将三维点云投影到不同的平面上
  4. 如何将三维点云进行旋转

PCL绘制圆柱体形状的点云

  1. PCL中绘制指定高度的梯形圆柱体形状的点云,参考代码如下:
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/common/common_headers.h>
#include <boost/thread/thread.hpp>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/common/transforms.h>

#include <vector>

typedef pcl::PointXYZRGB PointType;
using namespace std;


struct TrapezoidalCylinder {
private:
    float m_bottom_radius;      // 底部半径
    float m_top_radius;         // 顶部半径
    float m_height;             // 高度
    int m_r, m_g, m_b;          // 颜色

public:
    TrapezoidalCylinder(float bottom_radius, float top_radius, float height, int r, int g, int b) :
        m_bottom_radius(bottom_radius), m_top_radius(top_radius), m_height(height), m_r(r), m_g(g), m_b(b) {
        //cout << m_bottom_radius << m_top_radius << m_height << m_r << m_g << m_b << endl;
    }

    float get_bottom_radius()const { return m_bottom_radius; }
    float get_top_radius()const { return m_top_radius; }
    float get_height()const { return m_height; }
    int get_r()const { return m_r; }
    int get_g()const { return m_g; }
    int get_b()const { return m_b; }
};

//构造梯形圆柱体点云  
void create_cylinder_pointcloud(pcl::PointCloud<PointType>::Ptr& basic_cloud_ptr, const std::vector< TrapezoidalCylinder>& vec)
{
    int size = vec.size();

    for (int i = 0; i < size; ++i) {
        float height = vec[i].get_height();

        float slope = (vec[i].get_top_radius() - vec[i].get_bottom_radius()) / height;  // 斜率,控制半径的变化
        for (float z = 0; z <= height; z += 0.1)
        {
            // core
            float current_radius = vec[i].get_bottom_radius() + slope * z;
            for (float angle = 0.0; angle <= 360.0; angle += 5.0)
            {
                PointType basic_point;

                basic_point.x = current_radius * cosf(pcl::deg2rad(angle)); // r *cos(angle)
                basic_point.y = current_radius * sinf(pcl::deg2rad(angle)); // r *sin(angle)
                basic_point.z = z;
                uint32_t rgb = (static_cast<uint32_t>(vec[i].get_r()) << 16 |
                    static_cast<uint32_t>(vec[i].get_g()) << 8 | static_cast<uint32_t>(vec[i].get_b()));
                basic_point.rgb = *reinterpret_cast<float*>(&rgb);
                basic_cloud_ptr->points.push_back(basic_point);
            }

            basic_cloud_ptr->width = (int)basic_cloud_ptr->points.size();
            basic_cloud_ptr->height = 1;
        }
    }

}

int main(int argc, const char** argv) {
    pcl::PointCloud<PointType>::Ptr cloud(new pcl::PointCloud<PointType>);

    struct TrapezoidalCylinder cylinder_layer1 = { 1.6275, 1.805,   4.05, 63, 253, 63 };
    
    std::vector<TrapezoidalCylinder> vec;
    vec.push_back(cylinder_layer1);

    create_cylinder_pointcloud(cloud, vec);

    // 投影到xoy平面
    pcl::PointCloud<PointType>::Ptr cloud_down_projected(new pcl::PointCloud<PointType>);
    *cloud_down_projected = *cloud;
    int number_point = cloud_down_projected->points.size();
    for (int i = 0; i < number_point; ++i) {
        cloud_down_projected->points[i].z = 0;
    }

    // 绕x轴旋转90度
    // 定义一个4*4的单位阵
    Eigen::Matrix4f transform_matrix = Eigen::Matrix4f::Identity();
    // 旋转PI/2
    float theta = M_PI / 2;
    transform_matrix(1, 1) = cos(theta);
    transform_matrix(1, 2) = sin(theta);
    transform_matrix(2, 1) = -sin(theta);
    transform_matrix(2, 2) = cos(theta);

    pcl::PointCloud<PointType>::Ptr transformed_cloud(new pcl::PointCloud<PointType>());
    pcl::transformPointCloud(*cloud, *transformed_cloud, transform_matrix);

    // 投影到xoy平面
    pcl::PointCloud<PointType>::Ptr cloud_sideway_projected(new pcl::PointCloud<PointType>);
    *cloud_sideway_projected = *transformed_cloud;
    number_point = cloud_sideway_projected->points.size();
    for (int i = 0; i < number_point; ++i) {
        cloud_sideway_projected->points[i].z = 0;
    }

    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    int v1(0), v2(1), v3(2), v4(3);

    viewer->createViewPort(0.0, 0.5, 0.5, 1.0, v1);  // (xmin, ymin, xmax, ymax)
    viewer->createViewPort(0.5, 0.5, 1.0, 1.0, v2);
    viewer->createViewPort(0.0, 0.0, 0.5, 0.5, v3);
    viewer->createViewPort(0.5, 0.0, 1.0, 0.5, v4);
    viewer->addCoordinateSystem();

    viewer->addPointCloud<PointType>(cloud, "source point cloud", v1);
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "source point cloud"); // 设置点云大小

    viewer->addPointCloud<PointType>(transformed_cloud, "transform cloud", v2);

    viewer->addPointCloud<PointType>(cloud_down_projected, "down xoy cloud", v3);

    viewer->addPointCloud<PointType>(cloud_sideway_projected, "sideway xoy cloud", v4);

    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

    return 0;
}


结果

  1. 运行结果如下: