[choreonoid-users-ja 00223] Re: 即座にkinematicStateの変化を反映するには
Yuki Suga
ysuga @ ysuga.net
2017年 1月 13日 (金) 14:04:06 JST
小島様,中岡様:
菅です.お世話になります.
小島様:
やはりそうですね・・・描画イベントを起こしてしまうのが手っ取り早いとは思っていたのですが,必要な処理だけやる方法はないのかな・・・と.
中岡様:
なるほど.OSXで開発していると画面描画周りのスレッドに対する制約が強いので,
Qtは使ったことがありませんが,やはり制約があるのですね・・・
学生さんの環境だとモデルの見た目が壊れたりする不具合があったそうです.
flushを使い,callSynchronouslyで実装してみました.
今のところ改善したように見えます.
ありがとうございました.
ではでは
2017年1月12日(木) 22:31 中岡 慎一郎 <s.nakaoka @ aist.go.jp>:
> 産総研の中岡です。
>
> 小島さん解決方法の提示いただきありがとうございます。
>
>
> この解決方法については、ほぼ同じことをするAPIとして、MessageViewにflush()という関数があります。これを呼ぶと内部でイベントループを回して、即座にGUIの状態も更新されることになります。元々はMessageViewにメッセージを出力する際に、すぐにそのメッセージを表示させたいことがあるので、それを行うためにMessageViewの関数となっているのですが、内部的には小島さん提案の方法と同様の内容となっており、Qtのイベントループで処理されるGUI関連の処理は全てflushされることになります。Qtの内部的なところを気にしなくてよいという点で、こちらを使ったほうがよいかもしれません。
>
>
> ところで、菅さんの質問では、Choreonoid内部のスレッドとは別のスレッドで動いているとのことでした。この場合は対応方法が変わってくるかと思います。
>
>
> まず、Choreonoid内部スレッド(メインスレッド)以外のスレッドからは、基本的にGUIに関わる変数や関数に直接アクセスしてはいけません。ここではWorldItemやBodyItemにアクセスして、最終的にBodyItemのnotifyKinematicStateChangeを呼んでいるのだと思いますが、これは別スレッドでは行ってはいけない処理であり、タイミングによってはクラッシュする可能性があります。
>
> この場合、src/Base/LazyCaller.h で定義されている(インクルードするときは#include
> <cnoid/LazeCaller>
> )関数を使って、別スレッドからメインスレッドの関数を呼んで、そこで希望の処理を行う必要があります。
>
> 例えばこの例だと、
>
> void updatePose()
> {
> ... (ポーズ更新)
>
> bodyItem->notifyKinematicStateChange();
> }
>
> みたいな関数を定義しておきます。
>
> そしてサービスを実装している、別スレッドで動作する関数については、そこから上記ヘッダに定義されている
> callLater もしくは callSynchronously
> 関数を使って、updatePoseをメインスレッドから呼ぶよう要請します。
>
> これらの関数にはstd::function<void()> 型の関数オブジェクトを渡します。
>
> この例だと、
>
> callLater(updatePose);
>
> みたいな感じです。
> 何かのメンバ関数のときは、シグナルの時と同様に、ラムダ関数なりbindなりを使ってください。
>
>
> すると裏スレッドからはメインスレッドのイベントキューにこの関数を呼ぶイベントがポストされ、メインスレッド側でそのイベントが処理されることで、上記updatePose関数が「メインスレッドから」呼ばれます。
>
>
> callLaterだと非同期コールとなって呼び出し元にすぐ戻りますし、callSynchronouslyを使うと同期をとって上記関数の実行終了を待ってからこの関数も終了します。
>
>
> 後は、処理の実行自体は上記のように行いますが、裏スレッドと上記関数との間でデータのやりとりが必要な場合は、適切に同期(排他制御等)の処理をおこなってください。ただしcallSynchronouslyを使う場合は、他のスレッドからのアクセスがないのであれば、排他制御もいらなくなるかと思います。
>
>
> すみません、ちょっと複雑に見えるかもしれませんが、GUIのプログラムで別スレッドからGUIの処理を行う場合は、これが標準的なやり方になりますので、ご理解のほどよろしくお願いします。
>
> On 01/08/17 23:08, KUNIO KOJIMA wrote:
> > 東京大学の小島と申します
> >
> > 私も同じようなことを悩んだことがありまして,ひょっとしたら菅さんが求めているものと異なるかもしれませんが,自分の見つけた解決法を共有させて頂きます
> >
> > QEventLoop eventLoop;
> > で宣言したeventLoopに対して
> > bodyItem->notifyKinematicStateChange();
> > した直後に
> > eventLoop.processEvents();
> > を行うと,自分の環境ではシグナルが出されて貯まっているeventが全て消化されているように思います
> > 直後に,collision等を取得すると情報が更新されているはずです.
> >
> > 他により適した方法があるかもしれませんが,参考までに.
> >
> >
> > 2017年1月8日 18:14 Yuki Suga <ysuga @ ysuga.net>:
> >
> >> Choreonoid-MLの皆様:
> >> お世話になります.SSR/早大の菅です.
> >>
> >> もっとコードを読めば良いのですが・・・恥ずかしながらも質問です.
> >>
> >> Choreonoidで読み込んだモデルの姿勢を変えて干渉チェックをして干渉に関する情報を返すRTCのプラグインを作っています.
> >> サービスポートで受け取った関節角度を対象としているモデルに入れてから,
> >> WorldItemのcollisionsを使って干渉データを取り出すことができると考えているのですが,
> >> 関節角度を送ってからnotifyKinematicStateChangeを送っても即座には関節(ひいては干渉チェック)
> >> に反映されないようです(それが仕様だと思います)
> >>
> >> マニュアル通りにシグナルで受け取ってもいいのですが,サービスとして実装しているので,
> >> シグナルが送ってくるまで処理を待つという処理が必要になり無駄と感じています.
> >> この処理はサービスコール内で処理をしているので,Choreonoid内部のスレッドとは別のスレッドで動いています(動いているはずです)
> >>
> >> 無理矢理,関節角度の更新と干渉データのアップデートを促すには,
> >> プラグインの中でどのように処理をしたら良いのでしょうか?
> >>
> >> お教えください.よろしくお願いします.
> >>
> >>
> >> _______________________________________________
> >> choreonoid-users-ja mailing list
> >> choreonoid-users-ja @ choreonoid.org
> >> https://choreonoid.org/mailman/listinfo/choreonoid-users-ja
> >>
> >>
> >>
> >>
> >> _______________________________________________
> >> choreonoid-users-ja mailing list
> >> choreonoid-users-ja @ choreonoid.org
> >> https://choreonoid.org/mailman/listinfo/choreonoid-users-ja
>
> --
> 中岡 慎一郎 <s.nakaoka @ aist.go.jp>
> 産業技術総合研究所 知能システム研究部門
> ヒューマノイド研究グループ
>
> _______________________________________________
> choreonoid-users-ja mailing list
> choreonoid-users-ja @ choreonoid.org
> https://choreonoid.org/mailman/listinfo/choreonoid-users-ja
>
>
-------------- next part --------------
HTMLの添付ファイルを保管しました...
URL: <http://choreonoid.org/pipermail/choreonoid-users-ja/attachments/20170113/8d97bf0c/attachment.html>
choreonoid-users-ja メーリングリストの案内