s-nakaoka / choreonoid

An integrated graphical robotics application framework
http://choreonoid.org
Other
94 stars 58 forks source link

pythonのtime.sleep()を呼ぶとシミュレーションが止まる #209

Closed shintarokkk closed 6 years ago

shintarokkk commented 6 years ago

ロボットに対して時系列的に変化する外力(時間幅tm毎にf0,f1,f2,..と変化していく外力)を与えるために、BodyPluginのsetExternalForceを用いて、pythonで

setExternalForce(bodyItem, link, point, f0, tm) sleep(tm) setExternalForce(bodyItem, link, point, f1, tm) sleep(tm) setExternalForce(bodyItem, link, point, f2, tm) .....

というようなプログラムを実行したいのですが、pythonコンソールでsleep(tm)を実行するとシミュレーションの再生が時間tmだけ停止してしまい、またtmに長めの時間を入れるとchoreonoidがフリーズしてしまいます。 sleep関数使用時の停止を回避する方法、もしくはsleep関数を使わずに変化する外力を与える方法があれば教えていただけないでしょうか。

s-nakaoka commented 6 years ago

バックグラウンドで実行するか、タイマーを使います。

バックグラウンドで実行する場合は、例えば以下のようなスクリプトを用意して、これをPythonスクリプトアイテムとして読み込み、そのプロパティで「バックグラウンド実行」をtrueにしておきます。

from cnoid.Base import *
from time import sleep

def doSomething(i):
  print("do something %d" % i)

for i in range(10):
    callLater(lambda : doSomething(i))
    sleep(1.0)

これを実行しても、バックグラウンドでの実行になるので、シミュレーションは止まらないはずです。doSomethingのところに実行したい処理を記述します。

ここではcallLaterを使ってdoSomethingだけメインスレッドから実行するようにしています。メインスレッドから実行する必要がある処理はこのようにします。そうでない場合はcallLaterを使わずに直接実行すればOKです。

タイマーを使う場合は、例えば以下のようなスクリプトを用意します。

from cnoid.Base import *

class TimerSample:
    def __init__(self):
        self.timer = Timer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.doSomething)
        self.timer.start()
        self.counter = 0

    def doSomething(self):
        print("do something %d" % self.counter)
        self.counter += 1
        if self.counter == 10:
            self.timer.stop()

timerSample = TimerSample()

これについてはバックグラウンド実行はfalseとしておきます。これを実行すると、タイマーによって周期的にdoSomethingが呼ばれます。その間やはりシミュレーションは止まらないはずです。

これらのサンプルをsample/pythonに追加しておきました。それぞれDispatchSample.py、TimerSample.py としています。

s-nakaoka commented 6 years ago

ちなみに上記のスクリプトはChoreonodi開発版の最新版で試して下さい。

shintarokkk commented 6 years ago

@s-nakaoka さん、ありがとうございます。 二つの方法どちらも正常に動作することを確認しました。 (この際プロパティの「読み込み時に実行」をTrueにしてchoreonoid画面下部の「メッセージ」のところに"do something 0,..."のprint文が流れるのを確認しました。)