Help us understand the problem. What is going on with this article?

PCLVisualizerのラッパー的なものを作った話

3D Sensor Advent Calendar 2019の11日目の記事です.

概要

Point Cloud LibraryのPCLVisualizerが叩きにくいので4年くらい前からラッパーを書いていたのを公開します.ヘッダオンリーです.
プロトタイプ用途で点群可視化・保存・読み込み周りの実装を書き散らかすのに便利な設計を目指したつもりです.
GitHubリポジトリ: https://github.com/naoya-chiba/RabVisualizer

実装力が無い時代からの遺産なので汚いのですが,今後ちゃんと整理することもなさそうですのでそのまま公開ということでお許しください.

なりゆき

3D Sensor Advent Calendar 2019になにか書きたかったのですが,多忙で新ネタがちょっとできなさそうなので見送っていました.
今見たら枠が空いてたようですので,一応3D Sensor周りということで点群可視化しやすくしましたということで紹介させてもらおうかと思います.

できること

  • 点群の描画
  • 点群法線の描画
  • 座標系(原点での各軸方向)の描画
  • 点ペアの対応関係の描画(点群位置合わせを想定)
  • 線の描画
  • 2D/3D文字列の描画
  • Cubeの描画
  • 上記で描画されるデータの保存・読み込み

image.png
こんな感じの諸々を描画・保存・読み込みできます.

依存ライブラリ等

  • PCL (Point Cloud Library) 1.9.1
  • Boost 1.70.0
  • VTK 8.2.0 バージョンは動作確認した時点のものです.PCLがBoostとVTKに依存しますので,PCLが(Visualization込みで)入っていればOKです.

使い方

以下で一通り紹介しますが, sample_main.cpp を読んでもらうのが良いです.

基本的な使い方

ヘッダオンリーなのでrabv.hppをインクルードしたら使えます.

描画するデータはすべてRabクラスのインスタンスとして取り扱います.PCLに合わせてboost::shared_ptrで管理することを前提にしています.
自分でnewしても良いですが,create()で作成,make_shared()で複製できます.

auto rab = rabv::Rab::create();

各種可視化対象の追加

rabネームスペースにあるLines, Text, Text3D, FlatText3D, Cloud, Normal, Correspondence, CoordinateSystemあたりを生成してrabに加えていくことができます.メンバ関数のaddほげほげが対応します.削除時にはremoveほげほげです.
追加時には第一引数として名前,第二引数で可視化対象データを渡します.個々で指定する名前で管理しますので,同種の可視化対象にはユニークな名前を与えてください.
第二引数に可視化対象データのインスタンスの代わりに,可視化対象データのコンストラクタの引数を渡すことができます.こちらのほうが使いやすいので推奨,以下の例でもこちらを使用します.

// 点群を可視化
rab->addCloud(
    "sample1",   // ユニークな名前
    sample_cloud // pcl::PointCloud<pcl::PointXYZ>::Ptrな点群データ
);

// 点群を可視化,色々と同時に設定
rab->addCloud(
    "sample2",                    // ユニークな名前
    sample_cloud,                 // pcl::PointCloud<pcl::PointXYZ>::Ptrな点群データ
    1,                            // 点の大きさ
    rabv::Color(255, 255, 128),   // 点群の色 (r, g, b)
    rabv::Point(2.0, 0.0, 0.0),   // 並進オフセット (x, y, z)
    rabv::Rotation(0.5, 0.0, 0.0) // 回転 (X-axis, Y-axis, Z-axis)
);

// 点群と法線の可視化
rab->addCloudNormal(
    "sample3",                  // ユニークな名前
    sample_point_normal,        // pcl::PointCloud<pcl::PointNormal>::Ptrな点群+法線データ
    1,                          // 点の大きさ
    rabv::Color(255, 0, 128),   // 点群の色 (r, g, b)
    rabv::Point(3.0, 0.0, 0.0), // 並進オフセット (x, y, z)
    rabv::Rotation(),           // 回転 (X-axis, Y-axis, Z-axis)
    1,                          // 法線の表示密度
    0.05,                       // 法線の長さ
    1,                          // 法線の太さ
    rabv::Color(0, 255, 255)    // 法線の色
);

// 点群を追加した後に法線を追加
rab->addNormal(
    "sample1",                  // 法線を追加する対象の点群名
    sample_normal,              // pcl::PointCloud<pcl::Normal>::Ptrな法線データ
    1,                          // 法線の表示密度
    0.05,                       // 法線の長さ
    2,                          // 法線の太さ
    rabv::Color(255, 0, 128)    // 法線の色
);

// ワールド座標系の表示
rab->addCoordinateSystem(
    "world", // 座標系名,"world"を指定するとワールド座標系
    0.3      // 矢印のスケール
);

// 点群座標系の表示
rab->addCoordinateSystem(
    "sample2", // 座標系名,ここでは"sample2"の座標系を表示
    0.2        // 矢印のスケール
);

// 2つの点群に含まれる点の対応を線で結んで可視化
rab->addCorrespondence(
    "corr1",   // 対応名
    "sample1", // 対応元の点群名
    "sample2", // 対応先の点群名
    corrs1     // pcl::Correspondencesかpcl::CorrespondencesPtrかstd::vector<std::pair<int, int>>な対応関係データ
);

// 2つの点群に含まれる点の対応を線で結んで可視化,色々と同時に設定
rab->addCorrespondence(
    "corr2",                   // 対応名
    "sample1",                 // 対応元の点群名
    "sample2",                 // 対応先の点群名
    corrs2,                    // pcl::Correspondencesかpcl::CorrespondencesPtrかstd::vector<std::pair<int, int>>な対応関係データ
    2,                         // 線の太さ
    rabv::Color(255, 255, 128) // 線の色 (r, g, b)
);

Line, Text, Text3D, FlatText3D, Cubeは煩雑で面白くないので省略,sample_main.cpp を見てください...

可視化

rab::Viewerを使います.コンストラクタにboost::shared_ptr<rabv::Rab>を渡してあげるとそのまま可視化できます.
メンバ関数spinLoop()でウインドウを閉じるまで表示していてくれます.ブロッキングして欲しくない場合はメンバ関数spinOnce(time[ミリ秒])で指定した時間で返ってきてくれます.
Shiftキーを押しながら点群の点をクリックすると,その点に関する情報(インデックス,座標,原点からの距離,前に選択した点からの距離)がコンソールに出力されます.

const auto& viewer1 = rabv::Viewer::create(
        "Viewer1",  // ビューアーのウインドウ名
        rab     // boost::shared_ptr<rabv::Rab>なrabデータ
    );

viewer1->spinLoop();

保存と読み込み

rabデータはまるごと保存と読み込みができます(多分).
保存先パスに指定したファイル名の拡張子の前までと同名のディレクトリが作られ,点群などのデータが保存されます.
rabファイル自体はxmlですので修正などが容易です.特にvisibleというタグがあり,これをtrue/falseで切り替えることで可視化のオンオフができます.
main.cppをコンパイルするとrabファイルを読み込んで表示するビューアーとなっています.

// 保存
rabv::Writer::saveRabFile(
    "./test1.rab", // 保存先パス
    rab            // 保存するboost::shared_ptr<rabv::Rab>なrabデータ
);

// 読み込み
auto load_rab = rabv::Reader::loadRabFile("./test1.rab");

その他

  • 3D Sensorの話じゃないのでは?
    • ごめんなさい,他に数時間でかけるようなネタがなかったのですがどうしても何か書きたかったので...ダメであれば消しますのでお知らせください..
  • rabって何?
    • 当時Stanford Bunnyばかり見る日々で心が疲れていたのですが,Is the Order a Rabbit?に救われたので.Rabbit Visualizerです.

最後ですが,当時実装を手伝ってくれた研究室元同期の友人,使ってくれた先輩・後輩諸氏に感謝します.ありがとうございます.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした