PCLの機能いろいろ

# 最小構成（point cloudを読み込んで，表示して，保存する）
色々調べて聞くと，一番初めの型の宣言方法が2種類あることが分かる．
```
pcl::PointCloud<pcl::PointXYZ> cloud;
pcl::PointCloud<pcl::PointXYZ> Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
```
どちらもビルドできるし，何が違うの？と思ったら，一つ目では使えない関数が多々あった．

その理由として，
```
pcl::PointCloud<pcl::PointXYZ> cloud;
```
これはスマートポインタを使わない方法であり
```
pcl::PointCloud<pcl::PointXYZ> Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
```
こちらはスマートポインタを利用した点群オブジェクトの宣言方法である，という違いがあげられる．

スマートポインタが何なのかちょっとよく分からないが，「点群はかなり大きいデータになるので、オブジェクトをディープコピーするとメモリを浪費してしまいます。 この問題を避けるのが、スマートポインタを用いた宣言の仕方です。 なので、PCLで扱う多くの関数の引数はスマートポインタを取るようになっています。」だそう．


https://tm-labo.hatenablog.com/entry/2019/09/19/193151


つまり，スマートポインタを使わなかったせいで，動くはずの関数が動かない事件が発生していた．

## スマートポインタなしだと動かない事例
* ポイントクラウドの表示
* ダウンサンプリング

## スマートポインタの有無によるコードの違い
<details>
<summary>スマートポインタありver.</summary>

```cpp:main.cpp
# include <ros/ros.h> //rosを使わないときはこの行のみ消す

#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/pcd_io.h>
#include <iostream>
#include <pcl/common/impl/io.hpp>

using namespace std;

// settings
void viewerOneOff(pcl::visualization::PCLVisualizer& viewer)
{
    // set back ground color 
    viewer.setBackgroundColor(1, 1, 1); //white
    cout << "viewerOneOff" << std::endl;
}

int main()
{   // set Type
    using CloudType = pcl::PointCloud<pcl::PointXYZRGB>;
    CloudType::Ptr cloud(new CloudType);

    // 作成したPointCloudを読み込む
    pcl::io::loadPCDFile("/home/file_path/PointCloud.pcd", *cloud);

    // get point cloud data
    double width = cloud->width;
    double height = cloud->height;
    // cloud->points.resize(cloud->width * cloud->height);

    //access each point
    for(int i = 0 ; i < cloud->points.size() ; i++)
    {
        double x, y, z, r, g, b;
        x = cloud->points[i].x;
        y = cloud->points[i].y;
        z = cloud->points[i].z;
        r = cloud->points[i].r;
        g = cloud->points[i].g;
        b = cloud->points[i].b;
        
    }

    // create veiwer
    pcl::visualization::CloudViewer viewer("PointCloudViewer");
    viewer.showCloud(cloud);
    
    // ビューワー起動時の一回だけ呼ばれる関数をセット
    viewer.runOnVisualizationThreadOnce(viewerOneOff);
    
    // ビューワー視聴用ループ
    while (!viewer.wasStopped())
    {
    
    }

    //PCDファイルの出力
    pcl::io::savePCDFile('/home/file_path/cloud',*cloud);
    return 0;
}  
```

</details>


<details>
<summary>スマートポインタなしver.</summary>

```cpp:main.cpp
# include <ros/ros.h> //rosを使わないときはこの行のみ消す

#include <pcl/visualization/cloud_viewer.h>
#include <pcl/io/pcd_io.h>
#include <iostream>
#include <pcl/common/impl/io.hpp>

using namespace std;

// settings
void viewerOneOff(pcl::visualization::PCLVisualizer& viewer)
{
    // set back ground color 
    viewer.setBackgroundColor(1, 1, 1); //white
    cout << "viewerOneOff" << std::endl;
}

int main()
{   // set Type
    using CloudType = pcl::PointCloud<pcl::PointXYZRGB>;
    CloudType cloud;

    // 作成したPointCloudを読み込む
    pcl::io::loadPCDFile("/home/file_path/PointCloud.pcd", cloud);

    // get point cloud data
    double width = cloud.width;
    double height = cloud.height;
    // cloud->points.resize(cloud.width * cloud.height);

    //access each point
    for(int i = 0 ; i < cloud.points.size() ; i++)
    {
        double x, y, z, r, g, b;
        x = cloud.points[i].x;
        y = cloud.points[i].y;
        z = cloud.points[i].z;
        r = cloud.points[i].r;
        g = cloud.points[i].g;
        b = cloud.points[i].b;
        
    }
    // スマートポインタでは，ポイントクラウドの表示はできない
    //// create veiwer
    //pcl::visualization::CloudViewer viewer("PointCloudViewer");
    //viewer.showCloud(cloud);
    
    //// ビューワー起動時の一回だけ呼ばれる関数をセット
    //viewer.runOnVisualizationThreadOnce(viewerOneOff);
    
    //// ビューワー視聴用ループ
    //while (!viewer.wasStopped())
    //{
    
    //}

    //PCDファイルの出力
    pcl::io::savePCDFile('/home/file_path/cloud', cloud);
    return 0;
}  
```

</details>


# PCL機能いろいろ

<details>
<summary>ダウンサンプリング</summary>

https://pcl.readthedocs.io/projects/tutorials/en/latest/voxel_grid.html
</details>

<details>
<summary>複数のポイントクラウドを合成，ポイントクラウドを作る</summary>

https://pcl.readthedocs.io/projects/tutorials/en/latest/pcl_visualizer.html#visualising-a-single-cloud
</details>

<details>
<summary>近傍店探索</summary>

https://ppdr.softether.net/ros-pointcloud-zatxy
https://pcl.readthedocs.io/projects/tutorials/en/latest/kdtree_search.html

</details>

<details>
<summary>pointcloudの型変換（pointcloud2<->pointcloud）</summary>
一部の機能は型がpointcloud型でないといけない場合がある．その時はこれを使って変換する．

https://ros-developer.com/2017/08/03/converting-pclpclpointcloud2-to-pclpointcloud-and-reverse/
</details>

<details>
<summary>内外判定</summary>
https://kunassy.com/python-polygon-inside-outside-judgment/#toc3
</details>

<details>
<summary>外れ値除去</summary>
https://pcl.readthedocs.io/projects/tutorials/en/latest/statistical_outlier.html
</details>

<details>
<summary>回帰直線</summary>
https://ytake2.github.io/Rsite/_site/lec3.html
</details>

<details>
<summary>球体の挿入</summary>
https://pcl.readthedocs.io/projects/tutorials/en/latest/cloud_viewer.html
</details>

<details>
<summary>その他物体の挿入</summary>
https://pcl.readthedocs.io/projects/tutorials/en/latest/pcl_visualizer.html#drawing-shapes
</details>

<details>
<summary>点群の最大・最小値の取得</summary>
https://qiita.com/hoshianaaa/items/b930874110efe7135d8e
</details>

<details>
<summary>点群の平均値（重心）の取得</summary>
https://whitewell.sakura.ne.jp/PCL/OpenNI_tutorial_2_Cloud_processing_basic.html
</details>