ROS/ROS2の環境変数管理
ROS/ROS2 環境変数あるある
1台のPCにROS/ROS2の複数のディストリビューションがインストールされていて, 環境変数を切り替えながら使っていませんか?
自分の場合,趣味のプロジェクトで使っているディストリビューションがバラバラで
melodic
dashing
eloquent
を使い分ける必要があります.
環境変数の切り替え,どうしてる?
以前,こんなツイートを見かけました.
よし。 pic.twitter.com/ae45uxPsXJ
— Namihei Adachi (@7oei) January 3, 2020
みんな環境変数切り替えで苦労してる. 考えることは一緒!
ちなみに自分は.bashrc
に下のように書いて一番上のexport
をコメントアウトで切り替えてました.
今思うと超ガバガバでウケる(ウケない)
export CHOOSE_ROS_DISTRO=dashing #export CHOOSE_ROS_DISTRO=melodic #export CHOOSE_ROS_DISTRO=eloquent if [ $CHOOSE_ROS_DISTRO = melodic ]; then source /opt/ros/melodic/setup.bash source ~/catkin_ws/devel/setup.bash elif [ $CHOOSE_ROS_DISTRO = dashing ]; then source /opt/ros/dashing/setup.bash source ~/ros2_dashing_ws/install/local_setup.bash elif [ $CHOOSE_ROS_DISTRO = eloquent ]; then source /opt/ros/eloquent/setup.bash source ~/ros2_eloquent_ws/install/local_setup.bash fi
神ツール現る
なんと,ROS2本の著者であるyoutalk氏がROS/ROS2の環境変数管理ツールを作っていたみたいです. github.com
ROSJPのLT大会でも発表されてたみたいですね
ROS / ROS 2開発生産性向上ツール - Speaker Deck
複数のディストリビューションだけでなく複数のワークスペースも考えられていて素晴らしい!
使い方は簡単で
chdistro dashing ~/ros2_ws
のようにchdistro
コマンドの後にディストリビューションとワークスペースを指定するだけです.
よく使うワークスペースにはエイリアスをかけておけば環境切り替えが爆速になりそうです.
神ツールに補完をつける
素晴らしいchdistro
ですが,入力補完がないのでディストリビューションやワークスペースのパスを全て入力する必要があります.
ということで補完スクリプトを作りました.
/etc/bash-completion
に配置すると勝手に読み込まれるはずです.
ディストリビューションは/opt/ros
にインストールされているものを補完し,
ワークスペースは$HOME
以下のディレクトリを補完してくれるようになっています.
本家の方にも補完を取り入れるようにはたらきかけているのでデフォルトで補完が出るようになるかも知れませんね.
Boost.GeometryでEigenを使う
Boost.Geometry?
皆さん,いきなりですが"Boost.Geometry"をご存知ですか?
一口で言うと「幾何計算をやってくれるC++のライブラリ」なんですが,特筆すべきはその華麗なる設計でC++のメタプログラミング大好きマンにとってはバイブルとでも言うべき存在です.そっち系の専門書とかでも良い具体例として引用されています.
具体的なクラス設計とかの話はBoostのドキュメントに書いてあるので興味がある人は読んでみましょう. www.boost.org 英語が苦手という人は日本語訳されている方がいらっしゃいましたのでそちらをどうぞ mmiyano.blogspot.com
Boost.Geometryの柔軟性
さて,そのBoost.Geometryはその"華麗なる設計"によって次の要素を任意に設定することができます.
- 次元
- 座標系
- データ型
例えば,「多倍長浮動小数点数の 4次元極座標系」なんかにも対応することが可能です.(もはやなんでもあり)
Eigen
への対応
さて,今回はみんな大好きEigenの2次元ベクトルをこのBoost.Geometryで使えるようにしていきたいと思います.
まず,今回扱う2次元ベクトル,Eigen::Vector2f
の基礎情報をチェックしていきますと
項目 | Eigen::Vector2fの場合 |
---|---|
次元 | 2 |
座標系 | 直交座標系 |
データ型 | float |
と言うような感じになります.この情報を元に対応させていきます.
各要素の対応
対応させるときはコードをboost::geometry::traits
名前空間に書かないといけないのですが,ここでは省略します.
次元
Eigen::Vecotr2f
が2次元であることをBoost.Geometryに教えてあげます.
template<> struct dimension<Eigen::Vector2f> : boost::mpl::int_<2> {};
座標系
直交座標系であることを教えてあげます.
当然ながら,有名な座標系は予め定義されているのでそれを使います.
頑張れば自己流のオレオレ座標系を作って指定することもできるっぽい!?
template<> struct coordinate_system<Eigen::Vector2f> { typedef cs::cartesian type; };
データ型
Eigen::Vecotr2f
がfloat
で成り立っていることをBoost.Geometryに教えます.
template<> struct coordinate_type<Eigen::Vector2f> { typedef float type; };
プリミティブ指定
Eigen::Vector2f
がポイント型,すなわち点を表すプリミティブであることを設定します.
点の他にも線やポリゴンなども利用可能です*1
template<> struct tag<Eigen::Vector2f> { typedef point_tag type; };
要素アクセス
Boost.Geometryの統一的なアクセス法に従って値を取得するgetterと値を設定するsetterを書きます.
これによって,Boost.Geometryが自在にEigen::Vector2f
を操ることができるようになります.
template<> struct access<Eigen::Vector2f, 0> { static float get(Eigen::Vector2f const &p) { return p.x(); } static void set(Eigen::Vector2f &p, float const &value) { p.x() = value; } }; template<> struct access<Eigen::Vector2f, 1> { static float get(Eigen::Vector2f const &p) { return p.y(); } static void set(Eigen::Vector2f &p, float const &value) { p.y() = value; } };
全体像
断片的に解説したのでここでコードの全体像を載せておきます.
#pragma once #include <boost/geometry.hpp> #include <Eigen/Core> namespace boost::geometry::traits { template<> struct tag<Eigen::Vector2f> { typedef point_tag type; }; template<> struct coordinate_type<Eigen::Vector2f> { typedef float type; }; template<> struct coordinate_system<Eigen::Vector2f> { typedef cs::cartesian type; }; template<> struct dimension<Eigen::Vector2f> : boost::mpl::int_<2> { }; template<> struct access<Eigen::zenntaiVector2f, 0> { static float get(Eigen::Vector2f const &p) { return p.x(); } static void set(Eigen::Vector2f &p, float const &value) { p.x() = value; } }; template<> struct access<Eigen::Vector2f, 1> { static float get(Eigen::Vector2f const &p) { return p.y(); } static void set(Eigen::Vector2f &p, float const &value) { p.y() = value; } }; }
GDBでEigenのデバッグをする
はじめに
GDB?Eigen?な人はお帰りください.
恐らくこの記事はあなたが欲しい情報を提供することができないでしょう.
これから書くことは↓に全て書いてあります.
つまずく人もいそうなので一応日本語情報を残す意味合いで書きました.
因みに筆者の環境はUbuntu18.04です.
GDBでEigenのデバッグができない問題
GDBでEigenのデータを取得しようとすると固まります.
私はCLionにバンドルされているGDBを使っているのですが,
CLionの画面では"Collecting Data..."と出たきりCLionの応答がなくなってしまいます.
これではデバッグどころかコーディングもできない!!
解決策
冒頭にも言った通り以下のStackOverFlowに書かれています. stackoverflow.com
実はEigenにGDBの拡張プラグインが含まれていてそれをインストールすることで解決できるというオチですw
拡張プラグインのダウンロード
Eigen本体に拡張プラグインが含まれているのでダウンロードします*1.
以下,/home/hans
ディレクトリにダウンロードした前提で話をすすめるので適宜置き換えて読んでください.
cd /home/hans/ git clone https://github.com/eigenteam/eigen-git-mirror.git
拡張プラグインの読み込み設定
gdbの設定ファイルを作ってプラグインの読み込み設定を記述します.
ホームディレクトリに.gdbinit
という名前のファイルを作成して次の内容をコピーしてください.
python import sys sys.path.insert(0, '/home/hans/eigen-git-mirror/debug/gdb') from printers import register_eigen_printers register_eigen_printers (None) end
GDBの再起動
設定ファイルの内容が反映するにはGDBの再起動が必要です.
GDBを起動しているなら一度落としてもう一度起動してください.
Eigenのベクトルや行列をデバッグした時に写真の用に中身が表示できていれば成功です.
*1:libeigen3-devパッケージには必要最低限のものしか含まれていないのでダウンロードする必要があります