Help us understand the problem. What is going on with this article?

URScriptによるURロボットの外部制御

More than 1 year has passed since last update.

この記事を書く目的

最近は仕事でUniversal RobotsのURシリーズを使う機会が増えてきました。
外部制御なんかがすごくやりやすいので、外部制御のやり方をまとめていきます。

Universal RobotsのロボットUR3,UR5,UR10は共通のコントロールボックスCB3.1によりコントロールされます。(最近-eシリーズとかリリースされたので、そっちはまだ触ってないのですが。。。)
コントローラー内には小型のLinux PC(Debian)が入っているので、SSHからログインして中身をごにょごにょしたりできます。(通常ロボット使うときにはしませんが。。)

産業機械等でロボットを使うときはたいてい特定の条件が整ったら、プログラムを起動させるとか、ロボットの動きをあらかじめ作っておく使い方をします。もちろんURにもそういったジョブコールの仕組みはあるのですが(後日記事を書きます)、今回は特定の座標に直接ロボットの手先を移動させたりI/Oを使用したりといった、外部からプログラムを流し込む使い方についての解説をしていきます。

外部制御は、溶接などの分野でロボットに一定のパスをなぞらせたり、ジョイスティック等でロボットの手先座標を制御する場合などに用います。

誰に?

この記事は仕事でUniversalRobotsのロボットを使う必要が出てきたプログラマ向けに書いています。自分のメモ書き程度のつもりなので、詳しい解説など必要でしたらコメント欄にコメントいただけると助かります。
また、言語はpythonを使用していきます。pythonの解説に関しては他の記事や公式のドキュメント等を参照してください。

環境・前提条件

使用した
- コントロールボックス CB3.1 SW3.5
- ロボット UR5
- プログラム言語 python3.6

方法

ロボットコントローラの30002番ポートにTCPでコネクションを張って、スクリプトのテキストを送ります。
スクリプトの詳細はUR公式の外部制御マニュアルを参照してください。

最小のプログラム

以下にロボットが完全に腕を伸ばした状態へ持っていくスクリプトを記述します。

movejというのがロボットに動作をさせるためのスクリプトです。第一引数の配列に各関節の角度がラジアンで入っています。度で入力するわけではないので、注意してください。第二引数はロボットを動作させる際の加速度第三引数は速度です。
また、スクリプトの終端には改行を入れる必要があります。
(忘れやすいので強調しておきます)

ur_test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import socket
import time

HOST = "192.168.250.110"
PORT = 30002

def toBytes(str):
    return bytes(str.encode())

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    s.send(toBytes("movej([0,-1.57,0,0,-1.57,1.57], a=1.40, v=1.04)" + "\n"))
    # ラジアン
    time.sleep(3)
    data = s.recv(1024)
    s.close()
    print("Receved", repr(data))
    print("Program finish")

if __name__ == '__main__':
    main()

複数行のスクリプトの実行

複数行のプログラムを動かす場合、例えば、現在地から100mmだけ右へ動かす等の場合にはちょっと書き方が変わります。
スクリプトを1行ごと送っても同じようなことは実現できそうですが、変数はプログラムの1回の実行ごとに破棄されるので、変数を使って計算等をする場合には変数が破棄されない様に複数行まとめて実行させる必要があります。
複数行を実行させるには、送信する文字列を"def myProg():\n" ~ "end\n"で囲います。

以下は現在地を取得してx方向に100mm動かす際プログラムです。

multiline.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import time
import sys

HOST = "192.168.250.110"
PORT = 30002

def toBytes(str):
    return bytes(str.encode())

def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))

    s.send(toBytes(
        "def myProg():"+"\n" # 複数行で書く場合のおまじない
        +"begin_pos = get_actual_tcp_pose()" +"\n"  # 現在の手先座標取得
        +"pos_end = pose_add(begin_pos, p[0.100, 0.0, 0.0, 0.0, 0.0, 0.0])" +"\n"# 座標値の演算
        +"movel(pos_end , a=0.39, v=0.05)" + "\n"
        +"end" +"\n")) # ココもおまじない
if __name__ == '__main__':
    main()

まとめ

  • URへの外部制御スクリプトの送信方法をまとめた
  • URへの複数行のスクリプトの送信方法をまとめた

参考資料においた、スクリプトリファレンスを見ると、I/Oの制御や条件分岐で待ち続けたり、マルチスレッドでプログラムを動かす等、結構いろんなことができるので、皆さん遊んでみてください。

参考

UR公式のスクリプトリファレンス

Overview of client interfaces

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away