RCMLでの産業用ロボットのランタイムプログラミング





この記事では、ランタイムプログラミングとは、外部コントローラーでロボットコントローラー(以下、単にロボット)の実行可能プログラムを作成するプロセスを指します。 この場合、作成されたプログラムのロボットによる実行プロセスは、最小限の実行可能なコマンドまたはコマンドのパッケージを送信することにより、反復的に発生します。 言い換えれば、実行時プログラミング中、実行可能プログラムはロボットに部分的に転送されますが、ロボットは実行可能プログラム全体を所有せず、保存せず、事前に知りません。 このアプローチにより、「外出中」の外部デバイスによって形成される、抽象的なパラメータ化された実行可能プログラムを作成できます。 ランタイム。



猫の下には、ランタイムプログラミングの仕組みの説明と実際の例があります。



通常、ロボットのプログラムは、ロボットマニピュレーターが到達する位置のシーケンスです。 これらの各位置は、マニピュレーターに取り付けられたツールの先端のポイントであるTCP(ツールセンターポイント)の位置によって特徴付けられます。 デフォルトでは、TCPはロボットフランジの中心にあります。下の図を参照してください。ただし、TCPがロボットアームに取り付けられたツールの先端と一致するように、その位置を再構成できます。 したがって、プログラミング時には、通常、空間内のTCPの位置が設定され、ロボットはマニピュレーター自体の関節の位置を決定します。 さらにこの記事では、「TCPポジション」という用語、つまりロボットが「来なければならない」ポイントを使用します。
ロボット用のプログラムには、プリミティブ制御ロジック(分岐、ループ)、単純な数学演算、および周辺制御コマンド(アナログおよびデジタル入力/出力)も含めることができます。 提案されているランタイムプログラミングのアプローチでは、通常のPCを外部コントローラーとして使用します。このコントローラーでは、必要な抽象化レベル(OOPおよびその他のパラダイム)を提供する強力なプログラミングツールと、複雑なロジック(高レベルプログラミング言語)の開発を迅速かつ容易にするツールを使用できます。 ロボットには、反応速度に重要なロジックのみが残ります。その実行には、産業用コントローラーの信頼性、例えば、緊急事態への操作可能で適切な対応が必要です。 ロボットに接続された周辺機器の制御は、PC上のロボット自体によって単に「プロキシ」され、PCのソフトウェアがロボット上の対応する信号をオンまたはオフにできるようにします。 これは、Arduinoの脚を制御するのと似ています。







前述のように、ランタイムプログラミングでは、プログラムをバッチでロボットに送信できます。 通常、出力信号の状態のセットと少数のポイント、または一度に1つのポイントだけが送信されます。 したがって、ロボットによって実行されるTCP移動の軌跡は動的に構築でき、その個々の部分は異なる技術プロセスに属し、またはロボットのグループが動作している場合(1つの外部コントローラーに接続されている)異なるロボットにさえ属します。 プロセスでロボットを動的に交換するための前提条件があります。



たとえば、作業エリア間でロボットを移動します。 各ゾーンで、彼は必要な操作を実行してから、次のゾーンに移動し、別のゾーンに移動してから、最初のゾーンに移動します。 さまざまな作業領域で、ロボットはさまざまな技術プロセスに必要な操作を実行します。そのプログラムの実行は、外部コントローラーで並列フローで行われ、ロボットを常に存在させる必要のないさまざまなプロセスに割り当てます。 このメカニズムは、OSがプロセッサコア(実行リソース)の時間をさまざまなスレッド(タスク)に割り当てる方法に似ていますが、同時に、プログラム実行期間全体を通じてさまざまなエグゼキュータがスレッドに結び付けられることはありません。



もう少し理論と実践に移ります。



産業用ロボットをプログラミングするための既存の方法の説明
この記事で紹介したランタイムプログラミングアプローチを考慮せずに、産業用ロボットをプログラミングする2つの方法を区別するのが一般的です。 オフラインおよびオンラインプログラミング。



オンラインプログラミングのプロセスは、 プログラマが使用場所でロボットと直接対話することで発生します。 コントロールパネルまたは物理的な動きを使用して、ツール(TCP)がロボットフランジの必要な空間のポイントに取り付けられます。



  • このプログラミング方法の利点は、ロボットのプログラミングへのアプローチが簡単であることです。 プログラミング自体を知る必要はなく、ロボットに一連の位置を示すだけです。
  • このアプローチの重大な欠点には、プログラムを少なくとも数十(数千は言うまでもなく)ポイントに増やし、その(プログラム)その後の変更に費やすかなりの時間が含まれます。 また、このようなトレーニング中のロボットは作業に関与できません。


オフラインプログラミングプロセスは、その名前が示すように、ロボットとそのコントローラーからリモートで発生します。 実行可能プログラムは、PCで産業用ロボットをプログラミングするための特別な環境で開発された後、ロボット全体にダウンロードされます。 ただし、このような開発用のソフトウェアツールはロボットの基本的な配信パッケージには含まれておらず、別途購入する追加オプションであり、全体として安価ではありません。



  • オフラインプログラミングの利点は、プログラムの開発中にロボットが生産と作業に関与できることです。 ロボットは、書かれたプログラムをデバッグするためにのみ必要です。 自動化オブジェクトに行き、直接ロボットプログラミングに従事する必要はありません。
  • 既存のオフラインプログラミング環境の大きな欠点は、コストが高いことです。 また、異なるロボット間で実行可能プログラムを動的に配布することはできません。


例として、マーカー付きの広告を作成する技術的プロセスを提供するランタイムモードでロボットプログラムを作成することを検討してください。



結果:




注意! ビデオは広告ではなく、空席は閉鎖されています。 この記事は、提案されたプログラミング手法を実証するために、ビデオの関連性が失われた後に書かれました。



書面:
こんにちは! 必要です

開発者。Webを作成するには

システムインターフェース

知識。 ピックできる

あなたからヒューマノイドを知っています。



そして最後にできること

GRABはこの世界を改善します



詳細:HTTP://ROBOTCT.COM/HI

スカイネットのみ= ^-^ =



このテキストを書くためには、ロボットに1700ポイント以上を転送する必要がありました。



例として、スポイラーは、正方形を描くロボットのリモートコントロールからのスクリーンショットを示しています。 その中には5つのポイントのみがあり(行4〜8)、各ポイントは基本的に完全な式(演算子)を表し、1行を占有します。 マニピュレータは4つのポイントのそれぞれをバイパスし、完了すると開始ポイントに戻ります。



実行可能プログラムを備えたリモートコントロールのスクリーンショット




この方法でプログラムを作成する場合、最低1700ステートメント、つまり、ポイントごとのステートメントごとのコード行になります。 しかし、後でテキストや文字の高さ、または文字間の距離を変更する必要が生じた場合はどうでしょうか? すべての1700ラインポイントを編集しますか? これは自動化の精神に反しています!



それでは、解決策に取り掛かりましょう...



R-30iシリーズBキャビネットコントローラーを備えたFANUC LR Mate 200iDロボットがあります。 ロボットは、マーカーの末尾にTCPとデスクトップの座標系が事前に構成されているため、テーブルの座標系からロボットの座標系に座標を変換することを直接心配せずに座標を送信できます。



特定の各ポイントの絶対値を計算するロボットに座標を送信するためのプログラムを実装するには、提案されたアプローチをサポートし、このロボットと通信するためのモジュールを備えたRCMLプログラミング言語を使用します。



各文字を点で記述しますが、空間の実際の座標ではなく、文字が入力されるフレーム内の相対で記述します。 各文字は、行内の文字のシリアル番号、行番号、および文字のサイズを入力パラメーターとして受け取り、計算された各点の絶対座標とともにロボットに一連の点を送信する別個の関数によって描画されます。



テキストを書くには、テキストで文字(文字)が示されているのと同じ順序で文字を描く一連の関数を呼び出す必要があります。 RCMLには文字列ツールが少ないため、RCMLプログラムを生成する外部Pythonスクリプトを作成しましょう。実際には、対応する文字シーケンスの一連の関数呼び出しのみを生成します。



すべてのコードはGitHubリポジトリで入手できます: rct_paint_words



出力ファイルをより詳細に検討すると、実行はmain()関数から始まります。



サンプルRCML出力ファイル
include "chars.rcml" function main(){ try { //  @fr = robot_fanuc; system.echo("Start move program\n"); //   ,  , ,  @fr->set_real_di("speed", SPEED); @fr->set_real_di("cnt", CNT); @fr->startProgram(UFRAME, UTOOL, PAYLOAD); system.echo("prepare\n"); @fr->prepare(); system.echo("start draw\n"); //,  Python,  @fr->draw_r_P(0, 0); @fr->draw_P(1, 0); @fr->draw_r_I(2, 0); @fr->draw_B(3, 0); @fr->draw_E(4, 0); @fr->draw_T(5, 0); @fr->draw_Comm(6, 0); @fr->draw_r_L(8, 0); @fr->draw_r_Yu(9, 0); @fr->draw_r_D(10, 0); @fr->draw_r_I(11, 0); @fr->draw_Exclamation(12, 0); @fr->draw_H(14, 0); @fr->draw_A(15, 0); @fr->draw_M(16, 0); @fr->draw_H(18, 0); @fr->draw_r_U(19, 0); @fr->draw_r_Je(20, 0); @fr->draw_E(21, 0); @fr->draw_H(22, 0); @fr->draw_P(0, 1); @fr->draw_A(1, 1); @fr->draw_r_Z(2, 1); @fr->draw_P(3, 1); @fr->draw_A(4, 1); @fr->draw_r_B(5, 1); @fr->draw_O(6, 1); @fr->draw_T(7, 1); @fr->draw_r_Che(8, 1); @fr->draw_r_I(9, 1); @fr->draw_K(10, 1); @fr->draw_Dot(11, 1); @fr->draw_r_D(12, 1); @fr->draw_r_L(13, 1); @fr->draw_r_Ya(14, 1); @fr->draw_C(16, 1); @fr->draw_O(17, 1); @fr->draw_r_Z(18, 1); @fr->draw_r_D(19, 1); @fr->draw_A(20, 1); @fr->draw_H(21, 1); @fr->draw_r_I(22, 1); @fr->draw_r_Ya(23, 1); @fr->draw_B(25, 1); @fr->draw_E(26, 1); @fr->draw_r_B(27, 1); @fr->draw_r_I(0, 2); @fr->draw_H(1, 2); @fr->draw_T(2, 2); @fr->draw_E(3, 2); @fr->draw_P(4, 2); @fr->draw_r_F(5, 2); @fr->draw_E(6, 2); @fr->draw_r_Ii(7, 2); @fr->draw_C(8, 2); @fr->draw_A(9, 2); @fr->draw_C(11, 2); @fr->draw_r_I(12, 2); @fr->draw_C(13, 2); @fr->draw_T(14, 2); @fr->draw_E(15, 2); @fr->draw_M(16, 2); @fr->draw_r_y(17, 2); @fr->draw_H(19, 2); @fr->draw_A(20, 2); @fr->draw_r_Sha(21, 2); @fr->draw_r_I(22, 2); @fr->draw_X(23, 2); @fr->draw_r_Z(0, 3); @fr->draw_H(1, 3); @fr->draw_A(2, 3); @fr->draw_H(3, 3); @fr->draw_r_I(4, 3); @fr->draw_r_Ii(5, 3); @fr->draw_Dot(6, 3); @fr->draw_T(8, 3); @fr->draw_A(9, 3); @fr->draw_K(10, 3); @fr->draw_M(12, 3); @fr->draw_r_y(13, 3); @fr->draw_C(15, 3); @fr->draw_M(16, 3); @fr->draw_O(17, 3); @fr->draw_r_Je(18, 3); @fr->draw_E(19, 3); @fr->draw_M(20, 3); @fr->draw_r_P(22, 3); @fr->draw_E(23, 3); @fr->draw_P(24, 3); @fr->draw_E(25, 3); @fr->draw_H(26, 3); @fr->draw_r_Ya(27, 3); @fr->draw_T(28, 3); @fr->draw_soft_sign(29, 3); @fr->draw_O(0, 4); @fr->draw_T(1, 4); @fr->draw_B(3, 4); @fr->draw_A(4, 4); @fr->draw_C(5, 4); @fr->draw_r_Ge(7, 4); @fr->draw_r_U(8, 4); @fr->draw_M(9, 4); @fr->draw_A(10, 4); @fr->draw_H(11, 4); @fr->draw_O(12, 4); @fr->draw_r_Ii(13, 4); @fr->draw_r_D(14, 4); @fr->draw_O(15, 4); @fr->draw_B(16, 4); @fr->draw_r_Z(18, 4); @fr->draw_H(19, 4); @fr->draw_A(20, 4); @fr->draw_H(21, 4); @fr->draw_r_I(22, 4); @fr->draw_r_Ya(23, 4); @fr->draw_Dot(24, 4); //  ,         @fr->set_real_di("speed", 10); @fr->rotateMarker(); @fr->set_real_di("speed", SPEED); @fr->draw_r_I(0, 6); @fr->draw_H(2, 6); @fr->draw_A(3, 6); @fr->draw_K(4, 6); @fr->draw_O(5, 6); @fr->draw_H(6, 6); @fr->draw_E(7, 6); @fr->draw_r_Ce(8, 6); @fr->draw_Minus(9, 6); @fr->draw_T(10, 6); @fr->draw_O(11, 6); @fr->draw_M(13, 6); @fr->draw_r_y(14, 6); @fr->draw_C(16, 6); @fr->draw_M(17, 6); @fr->draw_O(18, 6); @fr->draw_r_Je(19, 6); @fr->draw_E(20, 6); @fr->draw_M(21, 6); @fr->draw_r_Z(0, 7); @fr->draw_A(1, 7); @fr->draw_X(2, 7); @fr->draw_B(3, 7); @fr->draw_A(4, 7); @fr->draw_T(5, 7); @fr->draw_r_I(6, 7); @fr->draw_T(7, 7); @fr->draw_soft_sign(8, 7); @fr->draw_r_U(10, 7); @fr->draw_r_L(11, 7); @fr->draw_r_U(12, 7); @fr->draw_r_Che(13, 7); @fr->draw_r_Sha(14, 7); @fr->draw_r_I(15, 7); @fr->draw_T(16, 7); @fr->draw_soft_sign(17, 7); @fr->draw_r_aE(19, 7); @fr->draw_T(20, 7); @fr->draw_O(21, 7); @fr->draw_T(22, 7); @fr->draw_M(24, 7); @fr->draw_r_I(25, 7); @fr->draw_P(26, 7); @fr->draw_r_P(0, 9); @fr->draw_O(1, 9); @fr->draw_r_D(2, 9); @fr->draw_P(3, 9); @fr->draw_O(4, 9); @fr->draw_r_B(5, 9); @fr->draw_H(6, 9); @fr->draw_E(7, 9); @fr->draw_E(8, 9); @fr->draw_two_dots(9, 9); @fr->draw_H(11, 9); @fr->draw_T(12, 9); @fr->draw_T(13, 9); @fr->draw_P(14, 9); @fr->draw_two_dots(15, 9); @fr->draw_Slash(16, 9); @fr->draw_Slash(17, 9); @fr->draw_R(18, 9); @fr->draw_O(19, 9); @fr->draw_B(20, 9); @fr->draw_O(21, 9); @fr->draw_T(22, 9); @fr->draw_C(23, 9); @fr->draw_T(24, 9); @fr->draw_Dot(25, 9); @fr->draw_C(26, 9); @fr->draw_O(27, 9); @fr->draw_M(28, 9); @fr->draw_Slash(29, 9); @fr->draw_H(30, 9); @fr->draw_I(31, 9); @fr->draw_r_I(2, 10); @fr->draw_C(3, 10); @fr->draw_K(4, 10); @fr->draw_P(5, 10); @fr->draw_E(6, 10); @fr->draw_H(7, 10); @fr->draw_H(8, 10); @fr->draw_E(9, 10); @fr->draw_B(11, 10); @fr->draw_A(12, 10); @fr->draw_r_Sha(13, 10); @fr->draw_S(15, 10); @fr->draw_K(16, 10); @fr->draw_Y(17, 10); @fr->draw_N(18, 10); @fr->draw_E(19, 10); @fr->draw_T(20, 10); @fr->draw_Equal(22, 10); @fr->draw_Roof(23, 10); @fr->draw_Minus(24, 10); @fr->draw_Roof(25, 10); @fr->draw_Equal(26, 10); //    @fr->stopProgram(); @fr->go_home(); } catch(E){ system.echo("Exception catched!"); return E; } return 0; }
      
      







文字Aの例を使用して、文字をレンダリングするコードを検討してください。
 function robot_fanuc::draw_A(x_cell,y_cell){ //   ,   5%    95%  Y    robot->setPoint(x_cell, y_cell, 5, 95); //  robot->movePoint(x_cell, y_cell, 50, 5); //   robot->movePoint(x_cell, y_cell, 95, 95); // "" /\ //         robot->setPoint(x_cell, y_cell, 35, 50); //  robot->movePoint(x_cell, y_cell, 65, 50); //         robot->marker_up(); }
      
      







ブレークありまたはなしのポイントにマーカーを移動する機能も非常に簡単です。
 //            function robot_fanuc::setPoint(x_cell, y_cell, x_percent, y_precent){ //   x = calculate_absolute_coords_x(x_cell, x_percent); y = calculate_absolute_coords_y(y_cell, y_precent); robot->marker_up(); //     robot->marker_move(x,y); //  robot->marker_down(); //     } //     / function robot_fanuc::movePoint(x_cell, y_cell, x_percent, y_precent){ x = calculate_absolute_coords_x(x_cell, x_percent); y = calculate_absolute_coords_y(y_cell, y_precent); //    :) robot->marker_move(x,y); }
      
      







関数marker_up、marker_down、marker_moveには、TCPポイントの座標の変更部分(ZまたはXY)をロボットに送信するためのコードのみが含まれます。
 function robot_fanuc::marker_up(){ robot->set_real_di("z", SAFE_Z); er = robot->sendMoveSignal(); if (er != 0){ system.echo("error marker up\n"); throw er; } } function robot_fanuc::marker_down(){ robot->set_real_di("z", START_Z); er = robot->sendMoveSignal(); if (er != 0){ system.echo("error marker down\n"); throw er; } } function robot_fanuc::marker_move(x,y){ robot->set_real_di("x", x); robot->set_real_di("y", y); er = robot->sendMoveSignal(); if (er != 0){ system.echo("error marker move\n"); throw er; } }
      
      







文字のサイズ、行ごとの数などを含むすべての構成定数は、別のchars_config.rcmlファイルで取り出されました。



Chars_config.rcml構成ファイル
 define CHAR_HEIGHT_MM 50 //     define CHAR_WIDTH_PERCENT 60 //       define SAFE_Z -20 //       z define START_Z 0 //       z //    define BORDER_Y 120 define BORDER_X 75 //  ON/OFF define ON 1 define OFF 0 //      define _SIGNAL_PAUSE_MILLISEC 50 define _OFF_PAUSE_MILLISEC 200 //      –    define START_W -179.707 //  define START_P -2.500 //  define START_R 103.269 //  //      define SECOND_W -179.704 //  define SECOND_P -2.514 //  define SECOND_R -14.699 //  define CHAR_OFFSET_MM 4 //    define UFRAME 4 //   define UTOOL 2 //   define PAYLOAD 4 //   define SPEED 100 //  define CNT 0 //    define ROTATE_SPEED //    define HOME_PNS 4 //  PNS     
      
      







その結果、合計で約300行の高レベルコードが得られ、その設計と作成には2時間もかかりませんでした。



この問題がオンラインのポイントごとのプログラミングによって「額で」解決された場合、9時間以上かかります(1,700ポイント以上ある場合、1ポイントあたり約20〜25秒)。 この場合、開発者の苦しみを想像するのは難しいです:)、特に文字間のインデントを忘れた、または文字の高さと間違えたことが判明し、テキストが収まらなかった場合、最初からやり直す必要があります。



結論:



ランタイムプログラミングを使用すると、ロボットを一般的な方法で移動する問題を解決し、特定のパラメーターに応じてプライベートな移動プログラムを動的に構成できます。 さらに、一般的な問題を解決するプログラムは、ロボットを必要とせずに開発できます。これは、一方で産業用ロボットをプログラミングするためのオフラインアプローチに起因します。 一方、ロボット用の直接転送プログラムは、オンラインプログラミングのように、特定のインスタンスと特定のパラメーターに対してその場で問題を解決するために既に作成されています。



検討した例では、一般的なアルゴリズムはレタリングであり、そのサイズ、それらの間のインデント、1行の文字数などのパラメーターは、ロボットのあるサイトの特定の条件に依存していました。



前述のように、移動軌跡を動的に構築するこのようなアプローチでは、同時に発生する複数のタスク間で、実行リソースとして(イベントベースで)ロボット切り替えを実装するための前提条件が作成されます。



ただし、このアプローチは注意して使用する必要があります。
実証されたバリエーション(一度に1ポイントの転送)では、ランタイムアプローチに重大な制限があります-ロボットは移動平滑化(CNT)命令を正しく理解しないか、無視します。 常に1つの現在のポイントを送信する場合、ロボットは次のポイントについて何も知らず、現在のポイントを迂回する平滑化された軌道を計算できません。



CNTとは?



ロボットツールを移動する場合、2つのパラメーターに影響を与えることができます。



  • 移動速度-ツールの移動速度をmm /秒単位で設定します。
  • 平滑化レベル(CNT)-グループの極端なポイント間の最短距離でパスに沿ってポイントのグループを歩くことができます。


次の図に示すように、これらのパラメーターは両方とも最終的な結果の軌道に影響します。







最悪の場合、この命令をランタイムモードで使用する危険性は、ロボットが意図したスムージングポイントに到達したことを報告することですが、実際にはまだそこに行きます。 ロボットはこれを実行して、次のポイントを要求し、平滑化を計算します。 明らかに、そのような点を通過するとき、ロボットがどの位置にあるかを正確に知ることは不可能です。さらに、たとえばマニピュレータのツールをオンにする必要がある特定の点で。 ロボットは、ポイントに到達したというシグナルを出しますが、実際には到達しません。 この場合、ツールは必要以上に早くオンになります。



最良の場合、ロボットはCNT命令を単に無視します(モデルによって異なります)。



これは、CNTポイントが最後ではない2つ以上のポイントを一度に転送することで処理されますが、これによりプログラムの複雑さとプログラマーの負荷が増大します。



この記事がお役に立てば幸いです。



ご質問にお答えします。



All Articles