RealSence D435iのセットアップ
はじめに
最近、RealSence D435iを扱う必要が出てきたので、セットアップで行ったことをまとめていきたいと思います。 今回、MacとUbuntu16.04の両方でセットアップしました。 さらにUbuntuの方ではROSで使用できるようにしました。
目次
セットアップ(Mac編)
まず初めに必要なものを一通りインストールします。 引用した記事だと
$ brew install libusb pkg-config $ brew install homebrew/versions/glfw3 $ brew install cmake
と書いてあるのですが、glfw3が非推奨というエラーが出てしまいます。 なので、以下のようにglfw3のインストールの部分を変更します。
$ brew install glfw3
GitHubからソースコードを自分のワークスペースに持ってきます。
$ git clone https://github.com/IntelRealSense/librealsense
チュートリアルの通りにサンプルプログラムをビルドし、XCodeを立ち上げます。
$ cd librealsense $ mkdir build && cd build $ cmake .. -DBUILD_EXAMPLES=true -DBUILD_WITH_OPENMP=false -DHWM_OVER_XU=false -G Xcode $ open librealsense2.xcodeproj
最後にXCodeのターゲットをrealsence-viewerに変更し、ビルドすれば完了です。 実行後にViewerが立ち上がります。
セットアップ(Ubuntu16.04編)
Viewerの起動
以下の公式のReadmeを参考に進めていきました。 github.com
まず初めにサーバーに公開鍵を登録し、リポジトリのリストに追加します。 自分の環境では以下のものだけ登録しました。
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE $ sudo add-apt-repository "deb http://realsense-hw-public.s3.amazonaws.com/Debian/apt-repo xenial main" -u
次に必要なものを一通りインストールします。
$ sudo apt-get update $ sudo apt-get install librealsense2-dkms librealsense2-utils librealsense2-dev librealsense2-dbg
以下のコマンドを実行するとViewerが起動します。
$ realsense-viewer
ROSで動かす
以下の記事を参考に進めていきました。 naonaorange.hatenablog.com
まず初めにGitHubからソースコードを自分のワークスペースに持ってきます。
$ cd ~/catkin_ws/src/ $ git clone https://github.com/IntelRealSense/realsense-ros.git
記事の通りに'catkin_make'するとエラーが表示されます。
公式のドキュメントを確認するとddynamic_reconfigure
が必要と書いてあるのでインストールします。
github.com
$ sudo apt-get install ros-kinetic-ddynamic-reconfigure
あとは引用した記事通りに進めていきます。
$ cd ~/catkin_ws/ $ catkin_make
最後にRealSenceを接続して、以下のコマンドを実行し、ノードを立ち上げます。
$ roslaunch realsense2_camera rs_camera.launch
あとはRvizからRealSenceで取得した情報を見ることができます。
最後に
せっかく手元にRealSenceがあり、セットアップもしたのでこれから色々遊んでいきたいと思います。
PCL(Point Cloud Library)のまとめ
はじめに
最近、3次元点群を扱うことが増えてきました。
今までまったく使ったことないので結構、苦戦しました。
なので、忘れないようにまとめていこうと思います。
使用環境はUbuntu16.04、使用言語はC++です。
目次
点群オブジェクトの宣言
型の種類
点群を扱うために変数を宣言する必要があります。 今回は例として、cloudという変数を宣言します。
pcl::PointCloud<pcl::PointXYZ> cloud; pcl::PointCloud<pcl::PointXYZRGB> cloud; pcl::PointCloud<pcl::PointXYZI> cloud;
上記のように様々な型の宣言があり、扱う点群の種類よって変える必要があります。
<pcl::PointXYZ>型は、点群の位置情報(XYZ)。
<pcl::PointXYZRGB>型は、点群の位置情報(XYZ)と色の情報(RGB)。
<pcl::PointXYZI>型は、点群の位置情報(XYZ)と輝度値。
宣言の種類
色々調べているとサンプルによっては宣言の仕方が、
pcl::PointCloud<pcl::PointXYZ> cloud; pcl::PointCloud<pcl::PointXYZ> Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
など様々あり、どれが正しいのかわからなくなりました。
実際はどっちを使ってもコンパイルは通りますが、要素のアクセスの仕方や関数の引数の記述方法が異なります。
じゃあ、どっちを使えば良いのかという疑問がありますよね。
pcl::PointCloud<pcl::PointXYZ> Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
上記はスマートポインタを使用した点群オブジェクトの宣言方法になります。
点群はかなり大きいデータになるので、オブジェクトをディープコピーするとメモリを浪費してしまいます。
この問題を避けるのが、スマートポインタを用いた宣言の仕方です。
なので、PCLで扱う多くの関数の引数はスマートポインタを取るようになっています。
pcl::PointCloud<pcl::PointXYZ> cloud;
上記はスマートポインタを使用してない生の点群オブジェクトを宣言しています。 使えないわけでもないですが、関数の引数でこの宣言方法だと使えないものがいくつかあったので注意が必要です。
サンプルコード
今回は長方形の点群を生成し、PCDファイルを保存します。 上記で述べた2通りの宣言方法で記述します。
- スマートポインタを使用しない宣言
#include <pcl_conversions/pcl_conversions.h> #include <iostream> using namespace std; int main(int argc, char **argv){ double x; double y; //型の宣言 pcl::PointCloud<pcl::PointXYZ> cloud; //点群の大きさを指定 cloud.width = 5000; cloud.height = 1; cloud.points.resize(cloud.width * cloud.height); //点群の生成 for(int i = 0 ; i < cloud.points.size() ; i++) { x = 3.0*rand() / (RAND_MAX + 1.0f); y = 1.0*rand() / (RAND_MAX + 1.0f); cloud.points[i].x = x; cloud.points[i].y = y; cloud.points[i].z = 1.0*rand() / (RAND_MAX + 1.0f); } //PCDファイルの出力 pcl::io::savePCDFile('cloud',cloud); return 0; }
- スマートポインタを使用する宣言
#include <pcl_conversions/pcl_conversions.h> #include <iostream> using namespace std; int main(int argc, char **argv){ double x; double y; //型の宣言 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); //点群の大きさを指定 cloud->width = 5000; cloud->height = 1; cloud->points.resize(cloud->width * cloud->height); //点群の生成 for(int i = 0 ; i < cloud->points.size() ; i++) { x = 3.0*rand() / (RAND_MAX + 1.0f); y = 1.0*rand() / (RAND_MAX + 1.0f); cloud->points[i].x = x; cloud->points[i].y = y; cloud->points[i].z = 1.0*rand() / (RAND_MAX + 1.0f); } //PCDファイルの出力 pcl::io::savePCDFile('cloud',*cloud_pcl); return 0; }