チトセロボティクスの「クルーボ」で産業用ロボットのビジュアルフィードバック制御を試してみた（１）

### クルーボについて
チトセロボティクス社の製品「クルーボ」を使って、産業用として利用されている6軸アームを動かすロボットのビジュアルフィードバック制御を試す機会があったので紹介します。製品の詳細は下記のチトセロボティクス社のサイトで見ることができます。

https://chitose-robotics.com/product

#### 「クルーボ」のベースキット
クルーボはロボット制御ソフトウェアライブラリを含んだミニPCとして提供されており、Ubuntu上でC++を使った開発が進めやすいように構成されています。ベースキットにはチュートリアルの内容を試すためのカメラやハンド類が付属しています。（内容物の写真やソフトウェアの部分的な掲載はチトセロボティクス社から了解を得ています。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/57482618-770d-9824-8996-88485203a1e4.png)

#### 主な仕組み
通常、今回使用するような協働ロボットは「アーム部」と「コントローラ」で構成されており、リモート動作でPCからの制御もできるようになっています。クルーボは、このリモート制御用のPCとして動作します。ロボットの設定や起動にはロボットメーカーの提供するソフトウェアも必要となりますので、その場合はもう１台のPCを併用します。クルーボは多くのロボットの品種に対応していますが、今回はその中から三菱製の協働ロボットMelfa RV-5AS-Dという6軸アームロボットを使用します。基本的には次のような構成となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/c8341f38-e65c-c516-a5f7-eb37172b2b68.png)

:::note alert
実際に設置する場合は非常停止ボタンなど適切な安全対策を施してください。
:::

クルーボにはスタートアップガイドが含まれていますので、これに沿ってロボット側の設定を行い、チュートリアルの内容を進めていきます。
スタートアップガイドの表紙にはカンブリア紀の古生物、「オパビニア・レガリス」が描かれています。目が5つとハサミのような吻を持ちます。かつてこんな不思議な生き物がいたのですね。:open_mouth:

<img width="200" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/c87af712-677a-bc02-29cf-3d0b29c1ab92.png>

### ロボット側の設定
　三菱MELFAのソフトウェア「RT ToolBox3」をインストールしたPCから、スタートアップガイドの内容に沿ってロボット側の設定をおこないます。基本的にはクルーボとの通信でロボットを動作させる「CMXT」という名称のプログラムを作成して実行することでリモート制御ができるようになります。そのほか、IPアドレスやポートの設定などもここで設定しておきます。
 
　ロボットの起動時には「RT ToolBox3」を使用してロボットの「サーボON」とプログラム「CMXT」の開始を行います。そのあとはクルーボのミニPCからC++のプログラムを作成してロボットを動かしていきます。
 <img width="200" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/cef52708-326c-2a04-23dc-12218a2db9c8.png>
### クルーボのプロジェクトの作成
クルーボに用意されている`crewbo create`コマンドでプロジェクトを作成します。ここでは例として`crewbo-projects`フォルダを作成し、そこに移動して`tutorial`プロジェクトを作ります。
<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/74083290-0f53-8e5e-f0cb-bddcecc5891e.png>

続いて、VS Codeでこのフォルダを開きます。
 <img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/957acaf1-599f-2dfa-9dc6-d7e47364e192.png>

すると、以下のようにセットアップされたプロジェクトフォルダの中を見ることができます。
<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/cf28008e-b7ed-458b-556f-717607f07930.png>

ここに含まれるsrcフォルダのmain.cppを編集していくことになります。あらかじめmain関数の基本構造に、「hello!」と表示するコードが含まれています。（このままビルドして実行すると、コンソールに「hello!」が表示されます。）
<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/e840bbfd-975d-3c81-ec70-55102f004dca.png>

### コードの準備
チュートリアル用のサンプルコードはexamples内のtutorialフォルダにロボットの機種ごとに格納されています。今回は三菱製Melfaを使用しますので、melfaフォルダの中のサンプルコードを使用します。
<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/98e29c72-3992-78f5-8db3-b4c1baadcf14.png>

付属するスタートアップガイドではtutorialの手順として細かくステップを踏んで解説されていますので、順を追って進めるのが良いと思います。ここでは少し間を飛ばしてtutorial 4-4を使用し、ロボットアームに設置した「マーカー」をカメラでリアルタイムに検出し、カメラ画像上のマウスでクリックしたポジションに移動するプログラムを動かしてみます。
<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/d5897232-fed8-156b-bd33-17c572481e90.png>

tutorialの`melfa_4_4_vf_2dof_to_marker.cpp`を開いて、全選択してコピーします。そして、`src`フォルダの`main.cpp`の中身をこれに置き換えます。
<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/3cc67aff-346b-1a7c-5886-32b2e90b07b7.png>

### カメラとロボットの設定
次に、コピペしたコードの中で、接続したカメラとロボットの設定を行います。カメラはクルーボ付属のカメラのほかUVC接続のできるWebカメラなら使用できます。`main.cpp`の71行目に次のコードがあります。
```
crewbo::camera::UsbCamera camera(0, image_width, image_height);
```
ここでカメラID(上記では"0"の部分)でカメラを選択しています。接続されているカメラが1台の場合はカメラIDには`0`または`-1`を設定します。2台以上接続されているときは2台目のカメラは`2`、3台目は`4`という具合に2づつ加算されます。カメラがうまく接続できない場合はターミナルから`lsusb`を使うなどしてPCがカメラを認識しているか確認してみてください。

ロボットの設定は`main.cpp`の89行目に次のコードがあります。
```
crewbo::robot::melfa::base_kit::MelfaRv4frl robot;
```
デフォルトではMelfaのRV-4FR-Lが設定されていますので、今回使用するRV-5ASに修正します。この時、実際に接続するロボットではIPアドレスを変更しているのでIPアドレスも指定しておきます。
```
crewbo::robot::melfa::base_kit::MelfaRv5as robot(1.f, "192.168.15.20", 10000U);
```

そのすぐ下、91行目にあるのは起動時に移動する初期位置のポジションです。もしもロボットをこのポジションに移動したとき他の設備と干渉するような場合は別のポジションに設定しておく必要があります。データはJ1~J6の各ジョイントの角度(deg)と、速度です。0.1fでは比較的低速で動作する設定ですが、安全な動作が確認できるまでは速度をむやみに上げないようにします。
```
robot.moveJointByAbsJoint_({0_deg, 0_deg, 120_deg, 0_deg, 60_deg, 0_deg}, 0.1f);
```

### マーカーの設置
ソフトウェアの準備ができたので、ロボットアームのポジションをカメラで認識するためのマーカーを設置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/9a444607-1112-8302-92b7-ab039b5a34c7.png)

### ソフトウェアのビルドと実行
マーカーの設置ができたら先ほど作成したソフトウェアをビルドして実行します。

実行の前に、ロボットのサーボがONになっていてロボットのプログラム「CMXT」が開始していることを確認しておきます。

VS Codeの「ターミナル」メニューから「ビルドタスクの実行」を選択するか、キーボードからctrl-shift-"B"を押すとウインドウ上部にメニューが表示されます。「このソースファイルをビルドして実行する」を選択します。

<img width="500" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/fb420914-9689-10c6-088a-6cdcb8bd4cf3.png>

コンソールでビルド状況が表示され、実行されるとまずロボットが初期位置に移動し、そしてWebカメラの映像が表示されます。この画像で、黄色のドットはカメラで撮影した画像から検出したマーカーの中心を示します。緑色のドットは目標位置ですが、一度マウスをクリックするまで動作はスタートしません。
<img width="400" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/0368cbb0-882b-0765-ff05-804d1a063f52.png>

画面上をクリックすると、緑のドットが移動し、その画面上のポジションにロボットハンドのマーカーの黄色のドットが一致するようにロボットが動作を始めます。マウスで次々とポジションを変更していくと、ロボットはその緑ドットを追いかけるように動きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3012948/88171dad-a29b-033c-afca-f6e0ea3411ef.png)

　ー　動画　ー
ロボットアームの動作中に、マウスで目標位置を変更しています。
<iframe width="500" height="320" src="https://www.youtube.com/embed/_JWk8RAwq5g" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

このケースでは下記の2点の間の偏差を抽出し、カメラ画像内の上下方向と左右方向でどの方向に動かせば偏差が最小になるかをリアルタイムでフィードバックしながらロボットアームを動作させています。

1) ロボットアームに取り付けたマーカーをカメラで認識したポジション
2) カメラから取得した画像上でマウスクリックしたポジション

今回は目標点をカメラ画像内でマウスクリックによって与えていますが、カメラ画像から目標の物体を検出して目標点を設定すれば、そのカメラ画像内で見つけた物体に向かってアームを動かすことも可能です。
（これは改めてPart2として記事を書ければ...と思います。）

### ポイント
今回の例ではロボットアームにマーカーを取り付けて、マーカーのカメラの画像上でのポジションと、同じ画像の上でマウスでクリックしたポジションを一致させる動きを行いました。つまり、これはカメラ画像内で設定した2つの制御点の情報だけを元にロボットを制御しています。

普通のロボット作業の現場で使われているような「位置決め」や「キャリブレーション」を使用していない点が最も重要なポイントです。カメラの位置が変わっても、ロボットの台座が動いても「視覚的に検知した2点を一致させる」という動作は安定して行うことができます。これはちょうど人間が目で目視して鉛筆に鉛筆キャップを被せるようなイメージです。

この技術では「2つの制御点の偏差」さえ検出できれば位置決め精度に関わらず高精度な制御が可能なので、チトセロボティクス社のデモ画像にあるような「縫い針に糸を通す」といったデモも可能になっています。

このリアルタイムビジュアルフィードバック技術を使ってどんなことができようになるか、今後の展開が楽しみです。

### おまけ
産業用ロボットの制御方式について主なものを簡単に挙げてみます。
詳細についてはそれぞれの専門文献を参照してみてください。

##### 1. 教示再生方式（ティーチング・プレイバック方式）
工場などの現場でロボットが稼働している場合、ほとんどがこの方式で動作しています。対象物は厳密に位置決めされ、ロボットアーム先端のツールは、この位置決めされた対象物の作業ポイントにティーチングされたデータだけを元に移動し作業を進めます。量産品の生産などで決められた作業を繰り返し行う場合に適しています。

##### 2. ワンショット・ビジュアルフィードバック方式
教示再生方式で動作するロボットを元に、動作開始前に一度だけカメラで撮影した画像から対象物の作業ポイントを設定するようにした方式です。この方式の場合、ロボット座標系とカメラ座標系が異なることから座標変換が必要ですが、この際に多くの誤差が混入し、精度を上げることが困難です。ヒトに例えると作業前に一瞬だけ目に見えた情報を元に、後は目をつぶって作業をしているような状態です。
- 位置精度を出すのが難しい
- キャリブレーションの手間がかかる
という点が課題になります。

##### 3. リアルタイム・ビジュアルフィードバック方式
カメラでリアルタイムで連続的に撮影し、都度環境を認識しながらロボットを動作させるので、ワークの変形や移動、ロボットの姿勢変化なども含めた変動を吸収しながら制御することが可能です。そのため、位置決めやキャリブレーションをしなくてもリアルタイムで得られるカメラからのビジュアル情報を元に高精度な制御が可能です。今回の「クルーボ」で実現している方式です。

### 今後の予定
今後もTutorialの中で特徴的なものや、Node-REDと連動してネットワーク経由で動作した事例、Node-RED MCUで周辺機器制御をやった事例などを紹介できればと思います。

クルーボやビジュアルフィードバックにご興味ある方、Node-RED、Node-RED MCUと組み合わせている方、コメント等いただけますと嬉しいです。

#### 関連記事

この記事の関連記事は以下の通りです。

・ビジュアルフィードバック制御によるインサートタスクの事例

https://qiita.com/mshioji/items/01443911f0903d300205