[ロボ実験記録] ロボットアームDobot MG400をpythonで動かす(TCP-IP通信)

はじめに

ロボットアームDobot MG400をpythonで動かす試行錯誤のメモです。
以下の記事の続きです。

MG400を制御する手段

軽くネットを調べた感じ、23/12/15時点で4つほど選択肢がありました。

  • 公式のDobot Studio Proを使う

    • GUIまたはlua言語

  • ネットに転がっているROS2ライブラリを使う

    • Robot operation system (ROS)のセットアップが必要

  • 公式のSDKを読み解いて動かす

    • TCP-IPプロトコルで動くようです

  • TCP-IPプロトコルを動かすラッパーライブラリを使う

GUI/Lua言語では拡張性に課題があります。一方、ROSは下手に触ると火傷します。
そのため、Pythonだけで動かせるインターフェースを今回はつかいます。いろいろと探したところ、TCP-IPのラッパーライブラリがあったので、それを試すことにします。

dobotの設定変更

ラッパーライブラリを使う前に、dobotの設定の変更が必要でした。
(ここに詰まりました)
ソフトウェアの設定画面上で、「TCP/IP..」を選んで、適用後、このソフトからは接続解除しておく必要があります。
これをしないと、通信時の戻り値がすべて-1になり、何もうごきません。

ライブラリの使用

ライブラリのセットアップ

git cloneでOK

git clone https://github.com/Dobot-Arm/TCP-IP-4Axis-Python.git

dobot_api.pyが肝となるファイルです。適当に環境変数のパスなどに追加して、これを読み込める状態にしておきます。
実際のロボット操作の例はPythonExample.pyに記載があります。

dobotの初期化


from dobot_api import DobotApiDashboard, DobotApi, DobotApiMove, MyType
from time import sleep
import numpy as np

def connect_robot(ip="192.168.1.6"):
    try:
        dashboard_port = 29999
        move_port = 30003
        feedback_port = 30004
        print("Attempting to establish connection...")
        dashboard = DobotApiDashboard(ip, dashboard_port)
        move = DobotApiMove(ip, move_port)
        feed = DobotApi(ip, feedback_port)
        print("Connection successful!")
        return dashboard, move, feed
    except Exception as e:
        print("Connection failed :(")
        raise e

#初期化: dobotのipは環境に応じて変更
dashboard, move, feed = connect_robot(ip="192.168.11.40")

enable

dashboard.EnableRobot()
Enableの実行画面。
表示されるipがおかしいですが、実際は指定したipに接続されているので、無視して大丈夫でした。

うまく実行できると、'0,{},EnableRobot();'というレスポンスが帰ってきます。

終了するときは
dashboard.DisableRobot()
です。

アームを動かす

move.RelMovL(-10,0,0,0) #相対座標でx-=10とする例

アームを動かして、動かし終わるまで待つ

Sync系の関数を呼び出すと、動作が終わるまで(多分)待ってくれる模様です。

move.RelMovL(0,10,10,0)
#move.SyncAll()
print("fin")

現在の座標を取得する

dashboard.GetPose()

(ジョイント角の倍は、GetAngle)

現在の座標を取得して、そこから少し移動する

GetPoseとMovLをつかいます。
GetPoseの返り値がただの文字列なので、floatに変換するcodeも必要です。

def extract_values(response):
    # レスポンスから中括弧内の値を抽出する
    start = response.find('{') + 1
    end = response.find('}')
    values_str = response[start:end]

    # 文字列を数値のリストに変換
    values = [float(val) for val in values_str.split(',')]
    return values

response=dashboard.GetPose()
pose=extract_values(response)

#yを-10する例
move.MovL(pose[0],pose[1]-10,pose[2],pose[3])

移動スピードの変更

dashboard.SpeedL(1) #範囲は1-100の整数の模様

エラー番号の取得

dashboard.GetErrorID()

おかしな座標を設定すると17、接触センサが起動したときは-2でした。

エラーからの復旧

dashboard.ClearError()
dashboard.Continue()

動作の様子

1218追記: 状態の取得

feedインスタンスを使うと、アームの位置etcを高速で取得できます。
以下は、1 secごとにアームの状態を取得し、更新があったパラメータを表示するコードです。

from dobot_api import MyType
import time

def get_buffer():
    data = bytes()
    hasRead = 0
    while hasRead < 1440:
        temp = feed.socket_dobot.recv(1440 - hasRead)
        if len(temp) > 0:
            hasRead += len(temp)
            data += temp

        feedInfo = np.frombuffer(data, dtype=MyType)
        return feedInfo
    #if hex(feedInfo['test_value'][0]) == '0x123456789abcdef':
    #    print(feedInfo['EnableStatus'][0])  # 出力机器使能状态

previous_data=None
while True:
    data=feedInfo=get_buffer()
    current_data = np.frombuffer(data, dtype=MyType)

    # 前回のデータと比較して変更がある場合のみ表示
    print("---------------")
    if previous_data is not None:
        for field in MyType.names:
            #if current_data[field] != previous_data[field]:
            if not np.array_equal(current_data[field], previous_data[field]):
                print(f"Changed: {field} ")

    # 現在のデータを保存
    previous_data = current_data.copy()
    time.sleep(1)

力がかかったときに変化するパラメータを探したのですが、特に見つかりませんでした。まじめな触覚センサは、CRシリーズじゃないと難しい印象です。

いいなと思ったら応援しよう!