DUCO 二次開発用SDKの使用方法

二次開発用のSDKはC++、C#、Pythonが準備されている

SDKで準備されている関数はマニュアルに記載されているが、モジュール自体はDUCOより入手する必要がある(代理店にお願いすれば入手可能)。
コントローラーのファームフェアのバージョンとSDKのバージョンが適合している必要があるため場合によってはファームウェアの更新が必要になる。

各種言語のSDKデータ

本SDKではRPC(Apache Thrift)を使用してコントローラーへ動作要求を実施、結果を受信している。接続するポートは7003

SDK(python)の構成

フォルダ内DucoCobotApi_py内は以下のファイル、フォルダが存在する。

  • フォルダ内データ
    • __init__.py … 中身は無し
    • DucoCobot.py … DUCOが準備した関数が記述されているファイル。基本は変更はせず、自作のクラス、関数から本モジュールを呼び出し使用。
    • demo.py … サンプルプログラム。ロボットコントローラーへの接続し、ロボット電源ON、イネーブル動作、ジョイント角(movej)動作、軌跡動作を実行するコードが記述されている。
    • lib … apache thriftのモジュールファイルが格納されている。
    • gen_py … thriftで自動生成されたファイル。変更しない。
SDKデータ構成

pythonサンプルプログラムの実行

以下のコードが記述されたファイルsample.pyDucoCobot.pyと同じフォルダに保存し、sample.pyを実行すると、ロボットの電源ON、イネーブル化、Movel(現在位置からZ軸+50mm)を行う。
今回動作確認したバージョンはpython 3.11.9、ロボットファームウェア V3.9、SDKバージョンV3.8.3。

ロボットステータス情報の取得は、DucoCobotモジュールの関数getRobotStatus()により取得しているが、TCP/IPでポート2001と接続する方法でも取得可能。

import sys
import time
import threading
import msvcrt

sys.path.append('lib')
from DucoCobot import DucoCobot
from thrift import Thrift
from gen_py.robot.ttypes import StateRobot, StateProgram, OperationMode, TaskState, Op, RealTimeControlData, PointOp, MoveJogTaskParam

class RobotControl:
    # 接続するLANポートのIPアドレス
    ip='192.168.1.10'
    # ポート名は固定
    port = 7003

    _stopheartthread = False
    _robot_status = None

    def __init__(self):
        pass

    # ハートビートスレッドの実行内容
    def _hearthread_fun(self):
        duco_heartbeat = DucoCobot(self.ip, self.port)
        duco_heartbeat.open()
        while not self._stopheartthread:
            duco_heartbeat.rpc_heartbeat()
            time.sleep(1)
    
        duco_heartbeat.stop(True)
        duco_heartbeat.close()

    # ステータス取得スレッドの実行内容
    def _get_status_thread_fun(self):
        duco_getstatus = DucoCobot(self.ip, self.port)
        duco_getstatus.open()
        
        while not self._stopheartthread:
            robot_status = duco_getstatus.getRobotStatus()
            if robot_status != None:
                self._robot_status = robot_status
            time.sleep(0.1)
    duco_getstatus.close()

  # ロボット動作指令実行関数
    def run(self):
        thd= threading.Thread(target=self._hearthread_fun)
        thd.start()
    
        self._duco_cobot = DucoCobot(self.ip, self.port)

        res = self._duco_cobot.open()
        if res == 0:
            print("Connect Success: DUCOとの接続に成功")
        else :
            print("Connect Fail: DUCOとの接続に失敗")
            return
        
        thd2= threading.Thread(target=self._get_status_thread_fun)
        thd2.daemon = True
        thd2.start()
    
        print(f"Robot Version: {self._duco_cobot.get_robot_version()}")

        res = self._duco_cobot.power_on(True)
        if res == TaskState.ST_Finished:
            print("Power On Success: 電源投入に成功")
        else:
            print("Power On Fail: 電源投入に失敗")
            return

        res = self._duco_cobot.enable(True)
        if res == TaskState.ST_Finished:
            print("Enable Success: イネーブルに成功")
        else:
            print("Enable Fail: イネーブルに失敗")
            return
    
        print(f"Z座標: {self._robot_status.cartActualPosition[2]:f}")
        pose1 = self._duco_cobot.get_tcp_pose()
        pose1[2] += 0.05
        # 現在の位置からTCPをZ方向に50mm移動 v=0.1 a=1.2
        res = self._duco_cobot.movel(pose1, 0.1, 1.2, 0, None, "", "", True)
        if res == TaskState.ST_Finished:
            print("Movel Success: ロボット動作指令成功")
        else:
            print("Movel Fail: ロボット動作指令失敗")

        time.sleep(0.5)

        print(f"Z座標: {self._robot_status.cartActualPosition[2]:f}")

        # 何かキー入力すると接続を解除して終了
        msvcrt.getch()
    
        self._stopheartthread = True
        time.sleep(1)

        res = self._duco_cobot.close()
        if res == 0:
            print("Disconnect Success: DUCOとの切断に成功")
        else :
            print("Disconnect Fail: DUCOとの切断に失敗")
            return

if __name__ == '__main__':
    robot = RobotControl()
    
    try:
        robot.run()
    except Thrift.TException as tx:
        print('%s' % tx.message)