Ubuntu14.04Choreonoid1.5で動くプログラムがU16.04C1.6で落ちる件について


#1

こんにちは

ロボットの強化学習のためにChoreonoid1.6を使わせていただいております。

Ubuntu14.04のPCにおいて動いているプロジェクトを
別のUbuntu16.04のPCにおいて動かしたいと思いましたが、
シミュレーションを開始した途端コアダンプで落ちてしまい、原因がわかりません。
ちなみに付属のサンプルプロジェクト(ContactForceExtractor)等は落ちずに動きます。
解決できるアドバイスなど、何かご教授いただけないかと存じ投稿いたしました。

エラーメッセージは以下のとおり

GtkDialog mapped without a transient parent. This is discouraged.
Segmentation fault (コアダンプ)

また、アイテムとしては以下のように配置しております。

World
DoubleARM_v7.yaml
シンプルコントローラ
AISTSimulator
ContactForceExtractor
Floor

気になったこととしては使っていたシンプルコントローラが
そのままでは16.04の環境ではビルドできなかったため、
14.04の環境では問題なかった以下の行を変更しました。

変更前
dt = timeStep();
変更後
dt = io->timeStep();

なぜ14.04では変更前でビルドできていたかも原因不明です。

どなたか何か気づいたことがありましたらコメントいただければ幸いです。
よろしくお願いいたします。


#2

choreonoidはQtベースなので、Gtkのエラーが出ているのがちょっと謎ですね(Qtから呼び出されているファイルオープン用のダイアログ?)。

コアダンプしているのであれば、gdbを使ってバックトレースを取得してみるとなにかわかるかもしれません。

まずはchoreonoidをデバッグシンボル付きでコンパイルして、

$ cmake -DCMAKE_BUILD_TYPE=Debug

コアダンプを出力できるように設定した上でchoreonoidを起動して、

$ ulimit -c unlimited
$ ./bin/choreonoid

コアダンプが得られたら以下のコマンドでgdbを起動してください。

$ gdb ./bin/choreonoid core

gdbが無事に起動してプロンプトが出てきたら「bt」コマンドを入力して、出てきた出力を教えてください。


#3

ご返信ありがとうございます。
おかげさまでコアダンプを出力できました。

gdbを起動したところ以下のように表示され、

Core was generated by `./bin/choreonoid’.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007f3085a907d0 in std::_Bit_reference::operato—

「bt」コマンドにより、以下の出力が出てきました。

#0 0x00007f3085a907d0 in std::_Bit_reference::operator=(bool) (this=0x7ffeffcf3680, __x=true)
at /usr/include/c++/7/bits/stl_bvector.h:87
#1 0x00007f3056198fbd in cnoid::SimpleControllerItemImpl::enableOutput(cnoid::Link*) (this=
0x55a503158210, link=0x55a5040a2920)
at /home/sugimoto-desktop-1/choreonoid-1.6.0/src/BodyPlugin/SimpleControllerItem.cpp:590
#2 0x00007f305619906d in cnoid::SimpleControllerItemImpl::setLinkOutput(cnoid::Link*, int) (this=0x55a503158210, link=0x55a5040a2920, stateTypes=8)
at /home/sugimoto-desktop-1/choreonoid-1.6.0/src/BodyPlugin/SimpleControllerItem.cpp:610
#3 0x00007f30561990d9 in cnoid::SimpleControllerItemImpl::setJointOutput(int) (this=0x55a503158210, stateTypes=8)
at /home/sugimoto-desktop-1/choreonoid-1.6.0/src/BodyPlugin/SimpleControllerItem.cpp:619
#4 0x00007f303f263529 in CrawlerQlearning_double_v7::initialize(cnoid::SimpleControllerIO*) (this=0x55a503253d60, io=0x55a503158210)
at /home/sugimoto-desktop-1/choreonoid-1.6.0/sample/SimpleController/CrawlerQL_double_Sugimo4.cpp:4

自分はよく分かっていないのですが、
コントローラの初期化処理においてリンクやジョイントのアウトプットに失敗しているということでしょうか。
どういう意味なのかお教えくださると幸いです。


#4

最終的にはこの代入命令でメモリアクセス違反が起こっているようですね、、、。

コードを見ると、indexに大きな値が入ってきた場合でも事前にresizeしているのでエラーは起こらないはずですが、indexにマイナス値が入ってきたりするとエラーになるかもしれません。

この処理がどこから呼び出されているかを遡っていくと、CrawlerQL_double_Sugimo4.cppの4行目でsetJointOutput関数を呼び出していると思うのですが、その部分で変な関節IDを与えていないでしょうか?または、使っているモデルファイルはうまく動く場合と同じになっているでしょうか?


#5

分かりやすく解説いただきありがとうございます。
自分なりに分かる範囲で辿って考えてみたのですが、
以下のようになり、やはりよく分からなくなってしまいました。
特にoutputLinkFlags[index] = true;に関して、
何かご存知でしたらご教授いただけると幸いです。

CrawlerQL_double_Sugimo4.cppでは以下のようにsetJointOutput(int stateTypes)の引数に
シンボルとしてJOINT_TORQUEを指定しております。

ioBody = io->body();
io->setJointInput(JOINT_ANGLE);
io->setJointOutput(JOINT_TORQUE);
io->setLinkInput(ioBody->rootLink(), LINK_POSITION);
for (int i=0;i<N_CTRL;i++){
io->setLinkInput(ioBody->link(JIDS[i]), LINK_POSITION);
}
io->setJointInput(JOINT_ACCELERATION|JOINT_VELOCITY|JOINT_ANGLE|LINK_POSITION);
io->setLinkOutput(ioBody->joint(CRL_LH_ID), JOINT_VELOCITY);
io->setLinkOutput(ioBody->joint(CRL_RH_ID), JOINT_VELOCITY);

setJointOutputは関節の指定なしにすべての全ての関節に対して一括で出力する関数だと存じます。
ioBody->numJoints()を取得して、次のようにsetLinkOutput(ioBody->joint(i), stateTypes)の引数にしております。
iは0からioBody->numJoints()までの値になるはずなのでマイナス値が入ることはないかと存じます。

void SimpleControllerItemImpl::setJointOutput(int stateTypes)
{
const int nj = ioBody->numJoints();
for(int i=0; i < nj; ++i){
setLinkOutput(ioBody->joint(i), stateTypes);
}
}

また、setLinkOutputは次のようにenableOutput(link)の引数として
与えられたioBody->joint(i)をそのまま入れております。

void SimpleControllerItemImpl::setLinkOutput(Link* link, int stateTypes)
{
Link::ActuationMode mode = Link::NO_ACTUATION;

if(stateTypes & SimpleControllerIO::LINK_POSITION){
    mode = Link::LINK_POSITION;
} else if(stateTypes & SimpleControllerIO::JOINT_DISPLACEMENT){
    mode = Link::JOINT_DISPLACEMENT;
} else if(stateTypes & SimpleControllerIO::JOINT_VELOCITY){
    mode = Link::JOINT_VELOCITY;
} else if(stateTypes & SimpleControllerIO::JOINT_EFFORT){
    mode = Link::JOINT_EFFORT;
}

if(mode != Link::NO_ACTUATION){
    link->setActuationMode(mode);
    enableOutput(link);
}

}

最後にenableOutputでindex = ioBody->joint(i)->index()となりますが、
これはおそらくiを参照しているのでしょうか。
そしてoutputLinkFlags[index] = true;として、ここでメモリアクセス違反とのことですが、
こちらの意味がよく分かりません。

void SimpleControllerItemImpl::enableOutput(Link* link)
{
int index = link->index();
if(static_cast(outputLinkFlags.size()) <= index){
outputLinkFlags.resize(index + 1, false);
}
outputLinkFlags[index] = true;
}

使ってるモデルファイルについては、14.04のPCからコピーしたファイル群(DoubleARM_v7.yamlとwrl)を使っており、
読み込みもできていて、リンクやジョイントも同様に表示されています。
そのため、問題ないかと思われるのですが、原因が分かりません。

ちなみにジョイントIDは以下の通りです。

//モデルのジョイントID
const int CRL_LH_ID = 0; //左クローラJoint ID
const int CRL_RH_ID = 1; //右クローラJoint ID
const int MSWG_ID = 2; //MFRAME中段旋回Joint ID
const int BLK_ID = 3; //BLOCKブームヨーJoint ID
const int BOM_ID = 4; //ブームJoint ID
const int ARM_ID = 5; //アームJoint ID
const int HAND_P_ID = 6; //バケットJoint ID
const int WTHUM_L1_ID = 7; //タフ左親指ベース1Joint ID
const int WTHUM_R1_ID = 8; //タフ右親指ベース2Joint ID
const int WFNG_L1_ID = 9; //タフ左指1Joint ID
const int WFNG_R1_ID = 10; //タフ右指2Joint ID
const int WTHUM_L2_ID = 11; //タフ左親指2Joint ID
const int WTHUM_L3_ID = 12; //タフ左親指3Joint ID
const int WTHUM_R2_ID = 13; //タフ右親指2Joint ID
const int WTHUM_R3_ID = 14; //タフ右親指3Joint ID
const int WFNG_L2_ID = 15; //タフ左指2Joint ID
const int WFNG_L3_ID = 16; //タフ左指3Joint ID
const int WFNG_R2_ID = 17; //タフ右指2Joint ID
const int WFNG_R3_ID = 18; //タフ右指3Joint ID
const int USWG_ID = 19; //UFRAME上段旋回Joint ID
const int MNPSWG_ID = 20; //マニピュレータSwing
const int MNPBOMC_ID = 36; //MブームシリンダJoint ID
const int MNPARMC_ID = 38; //MアームシリンダJoint ID
const int MNPELBC_ID = 40; //MエルボシリンダJoint ID
const int MNPBOM_ID = 21; //MブームJoint ID
const int MNPARM_ID = 22; //MアームJoint ID
const int MNPELB_ID = 23; //MエルボJoint ID
const int HAND_Y_ID = 24; //ハンドヨーJoint ID
const int HAND_R_ID = 25; //HANDBASEハンドロールJoint ID
const int FNGROD_ID = 26; //PUSHRODマニピュレータロッドJoint ID

const int HANDSLNK_I_ID=27;
const int HANDSLNK_O_ID=28;
const int MANIFNG_U_ID=29;
const int HANDTIP_U_ID=30;
const int HANDLNK_I_ID=31;
const int MANIFNG_L_ID=32;
const int HANDTIP_L_ID=33;
const int HANDLNK_O_ID=34;

以上がプログラムで定義しているジョイントIDで
以下は上記に加えてChoreonoid上で表示されるダミーの関節のようです。

41 IK_DUMMY_X0
42 IK_DUMMY_Y0
43 IK_DUMMY_X1
44 IK_DUMMY_Y1


#6

ダミーの関節があるため、Joint ID35〜40の指定がないのですが、
もしかしたらそれが原因でしょうか


#7

モデルファイルの中でJointIDを指定していないのは原因としてありえますね、、、。

SimpleControllerItemImpl::enableOutputの中でindex変数に何が入っているかprintfして見てみるというのも良いと思います。


#8

以下のようにsetJointOutputをやめて
enableOutputで34までの指定にしたところコアダンプで落ちることはなくなりました。

  // io->setJointOutput(JOINT_TORQUE);
     for(int i=0; i < 35; ++i){
         Link* joint = ioBody->joint(i);
         joint->setActuationMode(Link::JOINT_TORQUE);
         io->enableOutput(joint);
     }

最初、enableOutputやsetJointOutputにprintf挿入してみましたが、
なぜか出力されませんでした…
そこでofstreamで出力したところioBody->numJoints()は45となっていました。
コアダンプの原因としてはやはりモデルファイルで指定がないJoint ID35〜40があったからだと存じます。

ちなみにsetJointInputが通っていてsetJointOutputだけが通らなくなってしまったのは
Outputの仕様が変わったからでしょうか。

おそらく、Ubuntu14.04の方で動かしていたChoreonoidは1.6と表示されていましたが、
実際は1.5だったみたいで、
1.5まではOutputもImputと同じ仕組みでシンボルを設定してましたが、
1.6からは setActuationModeでの設定に変わったということですね。
少しだけ理解できてきました。

ただ、シミュレーションを開始してすぐにフリーズしてしまいました…
また、Gtkのエラー表示は残ったままです。
GtkDialog mapped without a transient parent. This is discouraged.
コアダンプとは別の原因がありそうです…

1.5をダウンロードすれば動くと思うのですが、
ダウンロードページから1.5をダウンロードしようとしても1.6になってしまいます…
もう1.5は手に入らないのでしょうか


#9

setJointOutputは1.6では非推奨になっているようですね、、、。

http://choreonoid.org/ja/manuals/latest/simulation/howto-implement-controller.html#id6

Choreonoid 1.5はここからダウンロードできます。

https://github.com/s-nakaoka/choreonoid/archive/release-1.5.zip

Ubuntu16.04とChoreonoid 1.6の組み合わせの場合、QT5を使うことが推奨されていたと思うので、もしQT4を使っていたら設定を変えてコンパイルすると、もしかしたらフリーズの症状が改善されるかもしれません。

http://choreonoid.org/ja/manuals/1.5/install/build-ubuntu.html#id5


#10

申し訳ございません。
非推奨になっていること,気づいておりませんでした。

Choreonoid1.5のリンクをいただき誠にありがとうございます。
Choreonoid1.5をダウンロードして試したところ、
今までのプログラムで問題なく動かすことができました。

QT5は最初から使っておりますので、結局フリーズの原因は分かりませんでしたが、
Choreonoid1.5で問題なく動くのでそのまま使ってみます。

大変親切にアドバイスいただき、本当に助かりました。
誠にありがとうございました。