PythonでAPIバッファ(リアルタイム動作)

コーディング

遅いPythonでもモーションとモーションの間の処理が遅くならない方法があります。WMXのAPIバッファー機能を使ってください。

APIバッファの使い方

ApiBufferクラスを作成して、「記録開始」「モーションの登録」「記録終了」「モーション動作開始」の流れになります。 ApiBufferは複数存在できますので、バッファを動作中にほかのバッファーに記録する事もできます。

検証コード

1つの軸で、3つの位置を移動するコードになります。モーションはリアルタイムスレッドで動作します。移動ポイント1に移動後、時間待ち。その後ポイント2を経由でポイント3に移動します。

# WMXに必要なコード
from WMX3ApiPython import *
from time import *

INFINITE = int(0xFFFFFFFF)

def main():

    # 制御する軸番号(0から始まります。)
    AXIS_NO = 0
    print('WMXプログラムスタート ディバイスを作成します')

    # WMXを使用するおまじない
    Wmx3Lib = WMX3Api()
    Wmx3Lib.CreateDevice('C:\\Program Files\\SoftServo\\WMX3\\', DeviceType.DeviceTypeNormal, INFINITE)
    Wmx3Lib.SetDeviceName('devicePython')
    Wmx3Lib_cm = CoreMotion(Wmx3Lib)

    #スレーブとの通信開始
    ret = Wmx3Lib.StartCommunication(INFINITE)
    
    #ここでユーザーの処理を記述します。
    print('WMXサーボオン')
    Wmx3Lib_cm.axisControl.SetServoOn(AXIS_NO, 1)
    
    # サーボがONするまで待機
    while True:
        ret, CmStatus = Wmx3Lib_cm.GetStatus()
        if (CmStatus.GetAxesStatus(AXIS_NO).servoOn):
            break
        sleep(0.1)

    # 原点復帰
    homeParam          = Config_HomeParam()
    ret, homeParam = Wmx3Lib_cm.config.GetHomeParam(0)
    homeParam.homeType = Config_HomeType.CurrentPos
    Wmx3Lib_cm.config.SetHomeParam(0, homeParam)
    Wmx3Lib_cm.home.StartHome(0)
    Wmx3Lib_cm.motion.Wait(0)
    

    API_NO = 0                          # APIバッファーは複数定義することができます
    api = ApiBuffer(Wmx3Lib)
    api.Clear(API_NO)
    api.CreateApiBuffer(API_NO)         # チャネルを開く

    print('待機中1。何かキーを押すとAPIバッファーの記録を開始します。')
    input()                                             # 1個目の待ち

    # 記録開始
    api.StartRecordBufferChannel(API_NO)

    posCommand                          = Motion_PosCommand()
    posCommand.profile.type             = ProfileType.Trapezoidal
    posCommand.axis                     = AXIS_NO       #制御したい軸番号の設定
    posCommand.profile.velocity         = 100000        #スピード設定
    posCommand.profile.acc              = 100000
    posCommand.profile.dec              = 100000
    

    #移動ポイント1
    posCommand.target                   = 10000         #移動先の座標設定
    Wmx3Lib_cm.motion.StartPos(posCommand)
    Wmx3Lib_cm.motion.Wait(0)                           #移動命令の完了待ち(サーボの位置決め完了ではありません)
    api.Sleep(100)                                      # リアルタイムスレッドでの時間待ち(正確です)

    #移動ポイント2
    posCommand.target                   = 20000         #移動先の座標設定
    Wmx3Lib_cm.motion.StartPos(posCommand)
    Wmx3Lib_cm.motion.Wait(0)                           #移動命令の完了待ち(サーボの位置決め完了ではありません)

    #移動ポイント3
    posCommand.target                   = -1340         #移動先の座標設定
    Wmx3Lib_cm.motion.StartPos(posCommand)
    Wmx3Lib_cm.motion.Wait(0)                           #移動命令の完了待ち(サーボの位置決め完了ではありません)

    # 記録終了
    api.EndRecordBufferChannel()

    print('待機中2。APIバッファーの記録を終了しました。何かキーを押すとAPIバッファーで動作します。')
    input()                                             # 2個目の待ち
    #リアルタイム動作開始
    api.Execute(API_NO)  

    print('待機中3。何かキーを押すと終了します。')
    input()
    api.Halt(API_NO)                                        #APIバッファの実行を停止。この命令を行わないと、新しく記録した瞬間にモーションが実行されてしまいます(同じAPIチャンネルの場合)
    # stopOnLastBlockオプションが有効の時は、Haltは不要です。
    api.Clear(API_NO)                                       # WMX3を開いているとAPIがクリアされません
    
    print('WMXサーボオフ')
    Wmx3Lib_cm.axisControl.SetServoOn(AXIS_NO, 0)

    # サーボがOFFするまで待機
    while True:
        ret, CmStatus = Wmx3Lib_cm.GetStatus()
        if (not CmStatus.GetAxesStatus(0).servoOn):
            break
        sleep(0.1)


    #スレーブとの通信終了
    Wmx3Lib.StopCommunication(INFINITE)
    #WMXの終了
    Wmx3Lib.CloseDevice()
    print('WMXプログラム終了')
    
    sleep(3)
    return 0
    
if __name__ == '__main__':
    main()

C#コードの記事はこちらです

上手く動かない場合はこちらの環境設定記事を参照してください。

動かしてみる

サンプルコードが正しく動いているかを確認するためにWMX3コンソールTOOLを起動します。

今回は、C:\WorkPython\PythonTest\のフォルダーにPythonTest_AIPバッファー.pyというファイルを作成して実行しました。

ANACONDAのコンソールを出し、ディレクトリを移動して”python PythonTest_AIPバッファー.py”で実行されます。

下図の状態で、コンソールが1個目の入力待ちの状態になっています。WMXが起動して、サーボONして、原点復帰が完了しています。動かす準備ができた状態です。

キーを押すと、次のコードが処理されます。

StartPos処理を実行しても、軸は動きません。モーションを記録するのみです。

キーを押すと、api.Execute関数が処理され、軸がリアルタイムスレッドで動き始めます。

APIバッファーコーディングの注意 APIバッファーを止めること

APIバッファーはデフォルトで動き続けます。(リアルタイムスレッドで指示待ち状態となっています) そのため、APIを記録しているつもりでStartPos()を行うと、即実行されます。

    # 記録終了
    api.EndRecordBufferChannel()

の命令を行っていても、APIバッファーに記録&即実行されてしまいますので注意してください。

APIバッファーを止める方法は2つあります。アプリケーションにより使い分けてください。

・Halt()命令をでAPIを止める

・stopOnLastBlockオプションを有効にしてAPIバッファーを起動する。(記録されたAPIを処理したら自動終了)

【調査中】PythonでstopOnLastBlockパラメータを変更したかった

作成したAPIバッファーに対して、GetOptions()でクラス値を取得して、SetOptions()でWMXに書き込みたいのですが、stopOnLastBlockパラメータに参照する方法がよくわかりませんでした。(詳しい人、コメントで教えてください。)

api = ApiBuffer(Wmx3Lib)
apiOptions = api.GetOptions(API_NO)
apiOptions.__setattr__("stopOnLastBlock",True)   # true=バッファの最後のAPIが実行されたときに、Halt

【調査中】APIバッファーが止まったことを検知したい

APIバッファーが終わった(モーションが終わった)のを確認して、次の処理を行いたい時があります。

GetStatus()でtuple(タプル)で値が戻ってきていそう。 要素にアクセスするのにapiStatus[0]で参照してもエラーとなる。(詳しい人、コメントで教えてください。)(ググてもやり方がよくわかりませんでした)

#APIバッファーが終了するまで待機(stopOnLastBlockがtrueが前提のコード)
while(True):
    apiStatus = api.GetStatus(API_NO)
    if(apiStatus["state"] == ApiBufferState.Stop):
        break;                                      # APIバッファーが完了した
    time.sleep(3)

あとがき

結構前からPythonでAPIバッファにチャレンジしていましたが、やっと動きました。よかったよかった。 APIバッファーがない場合、装置の制御は絶望的ですので、道が開けました。

コメント

タイトルとURLをコピーしました