シンプルコントローラ間の通信について

シミュレータ上にロボットの状態を示す独自のマーカー(具体的にはキャプチャーポイント)を表示したいと思っています。

このために、二つのシンプルコントローラを作成しました。
・ボール(対象物体)制御用 BallController
・マーカ制御用 MarkerController

GitHubにコード、実行用モデル・プロジェクトを置きました。

これはsample/WRS2018/controller以下にあるSpreaderControllerと
CarT3Controllerとの連携を参考に書いたものです。

ところが、どうにもMarkerControllerのインスタンスが取得できず、
実行時に symbol lookup error となってしまいます。
何がまずいか分かりますでしょうか?

なお、SimpleController読みこみ時に以下のエラーメッセージが出ています。

Error: SimpleControllerのコントローラモジュール "marker_control.so"はプロジェクトディレクトリからの相対パスで指定されていますが、プロジェクトディレクトリはまだ決まっていません

ただし、このエラーがあってもMarkeControllerのインスタンス取得をコメントアウトすれば、シミュレーションは正常動作します。

依然として問題は解決していませんが続報です。

実際のエラーメッセージは以下の通り。

$ choreonoid two_bodies.cnoid
choreonoid: symbol lookup error: /home/kajita/src/two_bodies/BallController.so: undefined symbol: _ZN5cnoid16MarkerController12get_instanceEv

実行時にBallControllerがMarkerControllerをどうしても参照してくれません。
しかし、BallController.cppは、MarkerController.hを読み込んでおりビルドはちゃんと通ります。

CMakeではなく、Makefileを使っており、コンパイルフラグは以下のとおりです。
なにか不足している設定があるのでしょうか?

CXXFLAGS += -fPIC -DQT_NO_KEYWORDS -DQT_SHARED -I$(CNOID_DIR)/include/choreonoid-1.8 -I/usr/include/eigen3 -std=c++11

$(PLUGINS) : %.so : %.o
g++ -shared -o $@ $^ -L$(CNOID_DIR)/lib -L/usr/local/lib -lCnoidUtil -lCnoidBase -lCnoidBody

WRS2018のコントローラでやっていることは、共有ライブラリに関するいくつかの条件を満たしているため実現できています。

具体的には、共有ライブラリ(DLL)を読み込んでリンクするにあたっては、通常以下の条件が必要となります。

  1. その共有ライブラリへのリンクをビルド時に行っておく
  2. 実行時にその共有ライブラリへのパスが通っている

1については、今回の例ではBallController.soのビルド時にMarkerController.soにもリンクをしておく必要があります。

2については、MarkerController.soが置かれているディレクトリに対して、環境変数LD_LIBRARY_PATHなどで共有ライブラリのパスを通しておく必要があります。

WRS2018のコントローラも、これらを満たす形でビルドされています。2については、コントローラが配置されるsimplecontrollerディレクトリにはパスが通っていないのですが、共有ライブラリに埋め込まれた相対パスでパスを通すという"RPATH"という仕組みでこれを実現しています。

これらはChoreonoid本体のCMakeの記述を共有して本体と同時にコントローラをビルドする場合は簡単に実現できますが、自前のMakefileで実現するとなると、少し面倒かもしれません。(1は対象共有ライブラリへのリンクを追加するだけですが、2はリンカのオプション記述が必要です。)

今回、上記の条件を満たしていなくても、Choreonoid上にコントローラが読み込まれてさえいれば実行時にリンクできるようにする機能を追加しました。

この改良により、シンプルコントローラアイテムに「シンボルのエクスポート」というプロパティが追加されます。これはデフォルトではfalseとなっていますが、これをtrueにすると、読み込んだコントローラ内のシンボルを実行時に他の部分からリンクできるよう、プロセス内部でエクスポートするようになります。これを有効にしておけば、リンクするコントローラが先に読み込まれていれば、そのコントローラ内の関数へのリンクが可能になります。

要はMarkerControllerに対してこのプロパティをtrueにしておけばOKです。

これで上記の条件を満たしていなくてもリンクができるようになります。梶田さん作成のプロジェクトでここだけ変更すれば、get_instance()も呼べるようになります。(いちおうこちらでも動かして確認しました。)

なお、今回の通信の仕方は、WRS2018で使った方法ではあるものの、あまりちゃんとしたやり方とは言えないので、表立ってはおすすめしにくいところがあります。本来はちゃんとした通信機能を利用して通信を行うのがよろしいかと思います。

確かに、ちょっとした実験などでちょこっと使いたい、といった用途には便利かもしれませんけどね。

「 プロジェクトディレクトリからの相対パスで指定されていますが、プロジェクトディレクトリはまだ決まっていません」というエラーメッセージについては、バグっぽいところがありますので、後程調査します。

なお、インストール先はプロジェクトディレクトリ内ではなく、Choreonoid本体のsimplecontrollerディレクトリに配置する方法もあります。梶田さんのMakefileでmake installをすると、これをやろうとしているように見えるのですが、実際にはプラグインディレクトリにインストールされています。プラグインディレクトリ内の"simplecontroller"というディレクトリが、本来インストールすべきディレクトリになります。

対応ありがとうございます!

早速Choreonoid開発版をアップデートしたのですが、Choreonoid が起動しなくなってしまいました。

$ choreonoid
Segmentation fault (core dumped)

システムはUbuntu 16.04LTS。coreをgdbで見るとこんな感じです。
何がまずいのでしょうか?

#0 0x00007f38b184ec10 in ?? ()
from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#1 0x00007f38b18857d7 in ?? ()
from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#2 0x00007f38b186f9c5 in ?? ()
from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#3 0x00007f38b16d5079 in ?? ()
from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#4 0x00007f38b16d6c90 in ?? ()
from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#5 0x00007f38b16c653c in ?? ()
from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#6 0x00007f38b1504c9e in ?? ()
from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#7 0x00007f38b14121f3 in ?? ()
from /usr/lib/x86_64-linux-gnu/dri/i965_dri.so
#8 0x00007f38d051bf36 in cnoid::GLSLProgram::link() ()
from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#9 0x00007f38d0524f39 in cnoid::BasicLightingProgram::initialize()
() from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#10 0x00007f38d0524f59 in cnoid::MaterialLightingProgram::initialize() () from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#11 0x00007f38d0525959 in cnoid::PhongShadowLightingProgram::initialize() () from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#12 0x00007f38d053efd5 in cnoid::GLSLSceneRendererImpl::initializeGL() () from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#13 0x00007f38d0554b16 in cnoid::SceneWidgetImpl::initializeGL() ()
from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#14 0x00007f38ce474cf8 in ?? ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#15 0x00007f38ce475dd2 in QOpenGLWidget::event(QEvent*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#16 0x00007f38ce41305c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#17 0x00007f38ce418516 in QApplication::notify(QObject*, QEvent*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#18 0x00007f38cfbdd38b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#19 0x00007f38ce4484a2 in ?? ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#20 0x00007f38ce448435 in ?? ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#21 0x00007f38ce448435 in ?? ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#22 0x00007f38ce45716a in QWidget::setParent(QWidget*, QFlagsQt::WindowType) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#23 0x00007f38ce457c6c in QWidget::setParent(QWidget*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#24 0x00007f38ce43306b in QLayout::addChildWidget(QWidget*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#25 0x00007f38ce4388bc in QStackedLayout::insertWidget(int, QWidget*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#26 0x00007f38ce5be7f6 in QTabWidget::insertTab(int, QWidget*, QIcon const&, QString const&) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#27 0x00007f38ce5be8c4 in QTabWidget::insertTab(int, QWidget*, QString const&) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#28 0x00007f38d046ae4d in cnoid::ViewAreaImpl::addView((anonymous namespace)::ViewPane*, cnoid::View*, bool) [clone .constprop.184] ()
from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#29 0x00007f38d046de3f in cnoid::ViewAreaImpl::addView(cnoid::View*)
() from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#30 0x00007f38d046e000 in cnoid::ViewAreaImpl::resetLayout() ()
from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#31 0x00007f38d0470573 in cnoid::ViewArea::restoreAllViewAreaLayouts(cnoid::ref_ptrcnoid::Archive) ()
from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#32 0x00007f38d046632c in cnoid::MainWindowImpl::restoreLayout(cnoid::ref_ptrcnoid::Archive&) ()
from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#33 0x00007f38d0466b59 in cnoid::MainWindow::resizeEvent(QResizeEvent*) () from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#34 0x00007f38ce45661e in QWidget::event(QEvent*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#35 0x00007f38ce56bdbb in QMainWindow::event(QEvent*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#36 0x00007f38ce41305c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#37 0x00007f38ce418516 in QApplication::notify(QObject*, QEvent*) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#38 0x00007f38cfbdd38b in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
#39 0x00007f38ce44ea41 in QWidgetPrivate::sendPendingMoveAndResizeEvents(bool, bool) () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#40 0x00007f38ce452833 in QWidgetPrivate::show_helper() ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#41 0x00007f38ce45563d in QWidget::setVisible(bool) ()
from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
#42 0x00007f38d0465eb6 in cnoid::MainWindow::show() ()
from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#43 0x00007f38d043bf3d in cnoid::AppImpl::exec() ()
from /usr/local/bin/…/lib/libCnoidBase.so.1.8
#44 0x00000000004068f2 in main ()
(gdb)

こちらの件と関係があるかもしれません。

まずは環境変数CNOID_USE_GLSLに0をセットして、描画エンジンを旧版にして、落ちなくなるか試してみていただけますでしょうか?

もしできれば参考にしたいので glxinfoコマンドの出力をアップしてください。

sudo apt install mesa-utils
glxinfo

を実行して出力されるテキストをお知らせいただけますでしょうか。

テキストをそのまま掲示板にはると長くなるので、ファイル添付の方がよいかもしれません。

お手数をおかけしますが、よろしくお願いします。

ちなみにファイルの添付は投稿用フォーム上部のツールバーにある「アップロード」ボタンでできるようです。

研究室のPC(同じくUbuntu 16.04LTS) ではコンパイル出来て、two_bodies.cnoidも問題なく動作する事を確認しました。有難うございました!

動いたようで、よかったです。

梶田さんが最初に試された、Choreonoidが落ちてしまう環境について気になるので、

  • CNOID_USE_GLSLを0にすると落ちなくなるか
  • glxinfoの出力結果

についてお知らせいただけないでしょうか。

お手数をおかけしますが、よろしくお願いします。

中岡様、

梶田です。
以下ご報告です。

  • CNOID_USE_GLSLを0にしたところ、クラッシュせず無事立ち上がりました。
  • two_bodies.cnoid も問題なく動作しました
  • glxinfoの出力結果を添付します。(.cnoid をつけていますが通常のテキストファイルです)
    glxinfo_txt.cnoid (26.8 KB)

ありがとうございます!
大変助かります。

この型番のGPUについて、デフォルトの挙動を変えるなどの対策を今後検討したいと思います。

Ubuntu 16.04でGPUがIntel HD Graphics 3000(Intel Core i7 Sandybridge に内蔵)の場合、デフォルトのGLSL描画エンジンだと落ちることを確認しました。対策として、このGPUの場合は影の描画を使わないようにしたところ、GLSL描画エンジンでも落ちなくなりました。

というわけで、CNOID_USE_GLSL=0 としなくても、大丈夫になったのではないかと思います。(影は描画されませんが。)

3 Likes