AGVネットワーク
概要と主要な概念
AGVネットワークは、自動誘導車両(AGV)や他のタスク実行者をシミュレートしながら移動経路を作成するのに役立ちます。
AGVモジュールは、自身のAGVオブジェクトタイプをライブラリに追加しません。代わりに、AGVネットワーク上のコントロールポイントにタスク実行者(タスクエグゼキューター、オペレーター、トランスポーターなど)を接続でき、そのタスク実行者はAGV定義のロジックを使用して移動します。
[AGVタイプ]タブ
[AGVタイプ]タブについては、「AGVタイプ」を参照してください。
[コントロールポイントの接続]タブ
[コントロールポイントの接続]タブについては、「コントロールポイントの接続」を参照してください。
[集積タイプ]タブ
[集積タイプ]タブについては、「集積タイプ」を参照してください。
[割り当て解除タイプ]タブ
[割り当て解除タイプ]タブについては、「割り当て解除タイプ」を参照してください。
[条件付きのルール]タブ
[条件付きのルール]タブを使用すれば、さまざまなパス上のルーティングに関するブール条件を定義することができます。たとえば、AGVの特定のタイプ専用のパスもあります。特定のラベル値を持つAGVのみがパスを辿ることができるようにするために、AGVのラベル値が一致するかどうかをチェックする条件付きルールを定義できます。その後で、そのルールを参照するパスの[条件付きのルール]プロパティを設定します。設定したら、ラベル値が一致するAGVのみがそのパス上を移動します。
AGVが移動タスクを開始するたびに、それぞれの条件付きルールを評価し、必要な目的地へのルートのキャッシュされたマップへのキーとして機能するタプルを作成します。AGVネットワークは、速度上の理由でそのキャッシュを維持するため、AGVが移動する必要があるたびにルートを計算し直す必要がありません。シミュレーション実行中に必要に応じてルーティングテーブルが構築され、キャッシュされます。
AGVは、移動オペレーションの開始時点にしか条件付きルールを評価しないことに注意することが重要です。これは、移動オペレーションの途中で条件付きルールの値が変化した場合は、ユーザーがAGVをプリエンプトして、AGVが移動オペレーションを再起動し、条件付きルールと後続ルートを再評価するようにする必要があることを意味します。
[一般]タブ
[一般]タブには、次のプロパティがあります。
パスまたはコントロールポイントを右クリックし、[AGVネットワークプロパティ]を選択すると、[一般]ページが表示されます。
デッドロックを確認
チェックボックスをオンにすると、コントロールポイント/コントロールエリアの割り当てロジックはデッドロックサイクルがないか継続的に確認します。見つかった場合は、モデルを停止し、問題を通知します。デッドロック検出には追加の計算が必要であり、シミュレーションが遅くなる可能性があることに注意してください。そのため、デバッグ中にオンにして、デッドロック問題がすべて解決したら、オフに戻してください。
移動終了速度0は最高速度を意味する
チェックボックスをオンにすると、AGVでは、終了速度0の移動タスクが「AGVの最高速度で終了」と解釈されます。この動作は、ネットワークノードを使用する標準的なトラベルネットワークなど、他のFlexSim移動メカニズムではデフォルトです。しかしながら、AGVの場合、これはいつも望ましい動作であるとは限らないため、ここでこの設定を明示的に定義します。詳細については、「AGV 移動タスクのカスタマイズ」を参照してください。
内部目的地エラーを無視
オンにすると、輸送列本体内部の目的地としてAGV.BodyOffset.TrainLeadingEdgeまたはAGV.BodyOffset.TrainTrailingEdgeを使用しているときに発生した移動目的地エラーがシステムコンソールに出力されません。代わりに、AGVはすぐに移動タスクを終了します。
このエラーは、非常に特殊なケースで発生します。AGV輸送列の「前縁」をAGV輸送列の内部のAGVパスネットワーク上の目的地に移動させたい場合は、技術的にはその操作を正常に実行する方法はありません。これは、その目的地への輸送列移動の縁が何であっても「前縁」ではなく「後縁」になるためです。つまり、AGVを前提とすると、このようなタスクは技術的にエラーです。ただし、モデルによっては、このエラーを検出して回避するのは困難な場合があります。そのため、このボックスをオンにすることはできますが、AGVは全く移動せずに移動タスクを終了するだけです。
交差位置で転送を作成
交差する複数の直線パスを配置するときに転送を作成するかどうかを定義します。デフォルト(オフ)の場合、少なくともどちらか一方のパスの端に交差点がある場合に限り、転送が作成されます。オンの場合、交差するパスの途中に交差点がある場合でも転送が作成されます。
線幅
基準となる幅をピクセルで定義します。モデル内のパスとコントロールポイントがこの幅で描画されます。
描画スケール
基準となするサイズを定義します。コントロールポイントとパスの方向矢印の描画をこのサイズで縮小拡大します。
スナップしきい値
ユーザーインターフェイスでオブジェクトをまとめてスナップする距離。
パス描画、コントロールポイントの描画、コントロールエリアの描画
モデル内で個々のオブジェクトをどのように操作できるかを定義します。モデルの特定の部分を完了したとき、その中のオブジェクトに関して変更できるところを制限することがあります。オプションは次のとおりです。
- 完全操作 - 必要に応じてこれらのオブジェクトをクリックし、動かすことができます。
- クリックのみ可能 - これらのオブジェクトをクリックできますが、動かすことはできません。
- クリック不可 - 3Dビューでオブジェクトを表示できますが、クリックできません。
- 描画しない - 3Dビューでオブジェクトを表示できません。
コントロールポイント/エリアの割り当てを表示
主に、デバッグに使用されます。オンにすると、AGVネットワークが各AGVの現在の割り当てと要求された割り当てを3Dビューに描画します。これには、コントロールポイント、コントロールエリア、およびパス転送の割り当てが含まれます。現在の割り当てはオレンジ色で描画されますが、要求された割り当ては赤色で描画されます。
集積の関連付けを表示
主に、デバッグに使用されます。オンにすると、AGVネットワークが現在集積パス上を移動しているAGV間に線を描画します。各AGVからその前のAGVとその後ろのAGVまで青色の線を描画します。
ルートコスト
このコントロールのグループを使用すれば、AGVパスネットワークに沿ったルートを解析するときの移動コストの計算方法をカスタマイズすることができます。AGVネットワークでは、最適な移動ルートを決定するためにダイクストラ法が使用されます。このアルゴリズムは、ネットワークを走査するときに、パスの各セクションでの移動に関連付けられた「コスト」を計算します。その後で、AGVが合計コストが最小のルートを辿って目的地に到着します。
デフォルトで、パスの1セクションの移動コストはそのセクションの距離と一致します。または、[速度で分配]を選択した場合は、その距離を、指定されたAGVがそのパスに沿って移動する速度で除算します。その結果、AGVは、最も短いルートではなく、最も速いルートを移動することになります。
また、[カスタムパスコストで乗算]を選択して、パス依存の式を入力することもできます。その後で、アルゴリズムが、コストを式の結果で乗算します。この最も一般的な用途は、ネットワーク内のさまざまなパスにラベルを貼ってパスごとに優先度を付けることです。そうすれば、アルゴリズムが特定のパス上の移動を優先します。ここで、式の結果が1の場合は、標準コストが使用され、式の結果が3の場合は、コストが3倍になるという具合です。式の結果が0の場合は、標準コストが使用されることに注意してください。さらに、A*モードを使用する場合、パスの乗数を常に1以上にする必要があります。これは、A*ヒューリスティックがアルゴリズムを目的地に正しく導くために必要です。
パスベースのコスト計算は静的であることが前提です。システムが目的地までのルーティングテーブルを必要としている場合は、それを1回だけ構築してキャッシュオフします。以降のルーティングではキャッシュされたテーブルが使用されます。これは、シミュレーションの実行中にパス依存のコストを単純に変更するだけでは、それらのコストが機能すると想定できないことを意味します。このとき、テーブルが初めて構築されたときのパスベースのコストが使用され、以降の変更は無視されます。ただし、パス依存のコスト計算を条件付きルールと組み合わせて使用して、この目的を達成することができます。
システムは、移動タスクの開始時点で各条件付きルールを評価することによってタプルを作成します。このタプルは、ルーティングテーブルのマップへのキーになります。指定されたタプルキーのテーブルがすでに存在する場合は、システムがキャッシュされたテーブルを使用します。テーブルが存在しなかった場合は、システムが新しいルートを構築してキャッシュします。そのため、パスコストを動的にしたい場合は、特定のパスコスト構成を条件付きルールに関連付けることができます。このような構成を使用するには、すべてのパスコスト値を構成に設定してから、条件付きルールをオンにします。その後で、ルーティングテーブルの計算が完了したら、パスコストをデフォルト値にリセットして、条件ルールをオフにします。
ルートコストのデバッグ
AGVシステムは、ダイクストラ法による結果に関する情報を取得するためのツールも提供しています。目的地のコントロールポイントを右クリックして、[AGVルーティングの近接性を表示]を選択できます。その後で、モデル内の他のコントロールポイントとパス転送の上にカーソルを移動します。カーソルを移動したポイントから目的地までの移動に関連付けられたさまざまなコストが表示されます。
詳細については、「AGVルーティングアクセシビリティの表示」を参照してください。
ウェイポイント
ウェイポイントは、AGVがコントロールポイントを通過するときに発生するAGVコントロールロジックを定義するために使用されます。しかしながら、今後は、AGVコントロールについてはウェイポイントの代わりに処理フローを使用することをお勧めします。FlexSimはテンプレートAGVコントロール処理フローを提供します。これは、AGVコントロールロジックを定義するための出発点として使用できます。
[ウェイポイント]タブには次のプロパティがあります。
パスまたはコントロールポイントを右クリックし、[AGVネットワークプロパティ]を選択すると、[ウェイポイント]ページが表示されます。
ウェイポイントリスト
ここでは、各ウェイポイントを追加、削除、並べ替え、名前変更できます。
トリガーポイント
ウェイポイントロジックを起動するタイミングがこれで定義されます。オプションは次のとおりです。
- 到着前 - ウェイポイントロジックは、AGVが減速を開始し、ウェイポイントで停止するタイミングで起動します。
- 到着時 - AGVがウェイポイントに到着したときにウェイポイントロジックが起動します。トリガー要件が満たされ、このトリガーポイントが選択されている場合、ウェイポイントがAGVの最終宛先ではない場合でも、AGVは減速してこのウェイポイントで停止し、ウェイポイントを起動します。したがって、AGVを停止まで減速させない場合、[到着前]を使用してください。
トリガー要件
ウェイポイントを起動する場合は1を返し、起動しない場合は0を返すフィールド。
ウェイポイントロジック
ウェイポイントのコード。
ウェイポイントのメンバー
このウェイポイントの一部であるコントロールポイントのリスト。ここでは、メンバーリストを追加、削除、並べ替えできます。
AGVカスタマイズデリゲート
FlexSimのユーザーインターフェイスに用意された標準機能以外に、AGVモジュールには、AGVの移動をより細かくカスタマイズできる上級ユーザー向けメカニズムが用意されています。AGVネットワークは、AGVナビゲーションロジックの特定のポイントにフックを配置できる「AGVカスタマイズデリゲート(AGV Customization Delegate)」を使用します。AGVネットワークは、内部的に定義されたデフォルトのカスタマイズデリゲート(customization delegate)を使用しますが、このデフォルトのデリゲートのロジックはオーバーライドすることができます。オーバーライドするには、専用のノードであるMODEL:/AGVNetwork>variables/customizationDelegateを次のように追加し、設定します。
- ツリーのMODEL:/AGVNetwork>variables/customizationDelegateに移動します。
- このノードを右クリックし、[編集]>[このノードを指定(so)]を選択します。
- スクリプトウィンドウで、スクリプト「nodeadddata(so(), DATATYPE_SIMPLE)」を実行します。
- このノードに、sdt::attributetreeというサブノードを追加し、「AGV::UserAGVCustomizationDelegate」というテキストを指定します。
- このノードをコピーし、このノード自体に貼り付けます。「UserAGVCustomizationDelegate」クラスがインスタンス化されます。このクラスには、FlexScriptでカスタマイズを実装できるフックが含まれています。
各種カスタマイズフックについては、わかりやすくするために、AGVの移動オペレーション全般と併せて説明します。AGVは、移動タスクの設定から完了までの一環として、いくつかの連続したオペレーションを実行します。それらを以下に示します。
- ルーティングの解決
- 移動パスの構築
- 移動パスの速度プロファイルの設定
- 先読みの割り当て/キネマティクス
AGVシステムは「怠惰」なダイクストラ法を使用して、ルーティングテーブルを目的地別にキャッシュします。AGVパスネットワークに変更が加えられるたびに、キャッシュされたルーティングテーブルはすべてクリアされます。ある目的地に移動しなければならないAGVは、その目的地がキャッシュ済みのルーティングテーブルを持たない場合、ダイクストラ法を使用してその場でテーブルを作成し、後で再利用できるようにテーブルを格納します。このテーブルには、AGVパスネットワーク内のすべての地点からその目的地に到達するための「コスト」と「次」のルーティング値が定義されています。目的地は実際に複数のルーティングテーブルを持つ可能性があり、各テーブルは条件付きのルールに基づくタプルキーによって独自にアドレス指定されます。
AGVシステムでは、より動的にテーブルを構築することもできます。その場合、目的地へのルートはA*アルゴリズムによって求められ、移動オペレーションのたびに完全に再計算されます。このモードは、shouldBuildCustomRouteフックが1を返す場合か、ユーザーがシステムで動的なルーティング制約を定義した場合に有効になります。
ダイクストラ法とA*モードのどちらでも、AGVは特定のパスセクションの移動「コスト」を求めるためにgetPathTravelWeightフックを呼び出します。
このステップでは、AGVはルーティングテーブルを使用して、ローカルに格納された、目的地への移動パスを構築します。この段階でAGVは、ルートの各パスセクションを移動する際のAGVの向きなどを求め、さらに、パスを移動する際にAGVが取得しなければならない先読みの割り当てポイントのリストも構築します。
このステップでは、AGVが移動パスを進み、移動パスセクションごとに最高移動速度、加速度、減速度の値を設定します。まず移動パスを順方向に通過し、カスタマイズデリゲートのsetSpeedProfileフックを呼び出します。次に逆方向に通過し、パスセクションの速度要件を満たすために減速を開始しなければならない地点を求めます。
このステップでは、AGVは次の割り当てポイントの事前割り当てを繰り返します。そのために、addKinematicsフックとaddRotationフックを呼び出して、次の割り当てポイントまでの移動パスセクションを通過するキネマティクスを追加します。AGVは、次の先読みポイントの事前割り当てをすぐに行わないかのようにキネマティクスを追加し、事前割り当てを必要とする次のポイントの到着前イベントをスケジューリングします。その際、すぐに事前割り当てができない場合は、キネマティクスを終了させ、先読みポイントで停止するだけです。一方、すぐに事前割り当てを行う場合は、キネマティクスをリセットして現在の位置から出発して加速します。そして処理を再度繰り返し、次の先読みポイントまで移動するキネマティクスを追加します。
カスタマイズフック
ユーザーカスタマイズデリゲート(user customization delegate)を追加すると、ユーザーが実装できるように空のフックノードが作成されます。このフックを未実装のままにすると、そのフックについてはデフォルトロジックが実行されます。フックを実装するには、該当するノードにテキストデータを追加し、そのノードをFlexScriptとしてトグルした後、正しいカスタマイズコードを実装し、その関数から必要な値を返します。
カスタマイズデリゲートフックは次のとおりです。
shouldBuildCustomRoute
このフックは、AGVのルート解決ステップの最初に実行されます。カスタマイズした移動ルートの使用を希望する場合は1を、そうでない場合は0を返す必要があります。1を返す場合、カスタムのgetPathTravelWeightフックの実装も必要です。なお、FlexSimの比較的新しいバージョンには、AGVのルートキャッシュメカニズムを使用するルートコスト機能がユーザーインターフェイスに追加されています。これらの新しい機能により、このフックとgetPathTravelWeightフックは廃止されたに等しく、ルーティングのカスタマイズにはこのフックの代わりにこれらの新しい機能を使用することをお勧めします。
このフックのコードヘッダーは、次のようにする必要があります。
AGV agv = param(1); // the traveling AGV
AGV.AllocatableObject currentCP; // the Control Point (if any) that the AGV is currently at
Object destination; // the destination object (if any)
getPathTravelWeight
このフックは、AGVのルート解決ステップの一環として繰り返し実行されます。AGVは、パスネットワーク内の通過中にパスセクションを検知すると、このフックを呼び出してこのセクションの移動「コスト」を確認します。一般にこのフックはパスセクションの距離またはパスセクションの移動時間を返しますが、必要に応じてこれをカスタマイズできます。なお、FlexSimの比較的新しいバージョンには、AGVのルートキャッシュメカニズムを使用するルートコスト機能がユーザーインターフェイスに追加されています。これらの新しい機能により、このフックとshouldBuildCustomRouteフックは廃止されたに等しく、ルーティングのカスタマイズにはこのフックの代わりにこれらの新しい機能を使用することをお勧めします。
このフックのコードヘッダーは、次のようにする必要があります。
AGV agv = param(1); // the traveling AGV
Object path = param(2); // the path whose travel weight is being queried
double fromDist = param(3); // the 'start distance' on the path
double toDist = param(4); // the 'end distance' on the path
setSpeedProfile
このフックは、速度プロファイルの設定ステップの一環として呼び出されます。このフックでは、移動パスセクションの最高速度、加速度、減速度の各属性を定義できます。このフックを実装する場合、1を返す必要があります。
このフックのコードヘッダーは、次のようにする必要があります。
AGV agv = param(1); // the traveling AGV
Object path = param(2); // the path whose travel weight is being queried
double fromDist = param(3); // the 'start distance' on the path
double toDist = param(4); // the 'end distance' on the path
残念ながら、バージョン22.2現在、FlexScript APIには、移動パスセクションにこれらの属性を直接設定するメカニズムはありません(今後のリリースでこの点が変更されたかどうかは、おそらくAPIを直接確認する必要があります)。とはいえ、移動パスセクションに対してsetsdtvalue()を呼び出し、「peakSpeed」、「acc」、「dec」の値を指定すれば、これらの属性を設定できます。
addKinematics
このフックは、先読みの割り当て/キネマティクスステップの一環として繰り返し呼び出されます。次の先読みポイントまでの移動パスセクションごとに1回、呼び出されます。
このフックのコードヘッダーは、次のようにする必要があります。
treenode kinematics = param(1); // the kinematics node to add kinematics to
AGV.TravelPathSection section = param(2); // the travel path section the AGV is to travel on
double atTravelDist = param(3); // the travel distance at which this kinematic will start
double dist = param(4); // the total distance that should be added to the kinematics, i.e. the distance to travel on that section
double startTime = param(5); // the start time for adding the kinematics
double startSpeed = param(6); // the speed the AGV will be traveling at startTime
double endSpeed = param(7); // the target end speed, i.e. the speed the AGV should be at when finished traveling the distance on the section
int reason = param(8); // 0: OnBuildKinematics, 1: OnAbort/OnPreempt, 2: OnProximityInterrupt
treenode endSpeedOut = param(9); // set the value of this node if the resulting endSpeed != original endSpeed
double peakSpeed = param(10); // the peak speed of the section
double acc = param(11); // the acceleration for the section
double dec = param(12); // the deceleration for the section
AGV agv = section.agv;
このフックのデフォルトの実装は次のとおりです。
return addkinematic(kinematics, dist, 0, 0, peakSpeed, acc, dec, startSpeed, endSpeed, startTime, KINEMATIC_TRAVEL);
このフックを実装する場合、コードは次の条件を満たす必要があります。
- KINEMATIC_TRAVELを使用したaddkinematic()コマンドでキネマティクスを追加する。
- addkinematic()で定義された距離は、X軸上で排他的に定義される。つまり、addkinematic()の第3、第4のパラメータは常に0にする必要があります。
- すべてのaddkinematic()呼び出しのxパラメータの累積距離は、dist(param(4))と同じである。
- どのaddkinematic()呼び出しも、最も早い開始時間がstartTime(param(5))より早い時間であってはならない。
- addkinematic()で複数のキネマティクスを追加する場合、これらのキネマティクスの時間は重なっていてはならない。
- 最終の終了速度は、渡されたendSpeed(param(7))以下でなければならない。キネマティクスの結果、終了速度が渡されたendSpeedを下回る場合、endSpeedOut->valueに結果の最終速度を設定する必要があります。
- AGVがすべての距離を移動し終えた最終の終了時間をこのフックから返す。
addRotation
このフックは、先読みの割り当て/キネマティクスステップの一環として呼び出されます。AGVが停止し、回転しきい値に基づいて新しい方向に転換しなければならない場合にのみ呼び出されます。
このフックのコードヘッダーは、次のようにする必要があります。
treenode kinematics = param(1); // the kinematics node to add kinematics to
double rotation = param(2); // the angle, in degrees, that the AGV must rotate
double rotSpeed = param(3); // the AGV's rotation speed
double startTime = param(4); // the time at which the AGV has come to a stop and can start rotating
AGV.TravelPathSection fromSection = param(5); // the path section that the AGV is transitioning from
AGV.TravelPathSection toSection = param(6); // the path section that the AGV is transitioning to
このフックのデフォルトの実装は次のとおりです。
return addkinematic(kinematics, 0, 0, rotation, rotSpeed, 0, 0, 0, 0, startTime, KINEMATIC_ROTATE);
このフックを実装する場合、コードは次の条件を満たす必要があります。
- KINEMATIC_ROTATEを使用したaddkinematic()コマンドでキネマティクスを追加する。
- addkinematic()で定義された距離は、Z軸上で排他的に定義される。つまり、addkinematic()の第2、第3のパラメータは常に0にする必要があります。
- すべてのaddkinematic()呼び出しのzパラメータの累積距離は、rotation(param(2))と同じである。
- どのaddkinematic()呼び出しも、最も早い開始時間がstartTime(param(4))より早い時間であってはならない。
- AGVがすべての回転を終えた最終の終了時間をこのフックから返す。