軌道の計算と追従用のチャネル

チャネルは、NavMesh 内のある場所から別の場所へのパスの周囲の移動可能なスペースを簡易表示したものです。道路のような、幅の広いパスの一種とみなすことができます。

チャネルの構造は単純で、移動可能なスペースを簡単な方法で表します。チャネル内の情報は近づきつつある曲がり角を予測するために、Bot の旋回能力に制限をつける軌道を計算するために簡単にアクセスできます。

チャネルはゲートの配列です。隣接する 2 つのゲート間の四角形または三角形は、チャネル セクションと呼ばれます。各セクションは、NavMesh 障害物の影響を一切受けません。次の図を参照してください。

NavGraph を通過するパスは複数のチャネルに関連付けられています。パスの周囲に十分なスペース(幅)がなく有効なチャネルを持つことができない場合、チャネルは NavMesh 上で分割されます。そのため、パスの NavMesh に配置された各パーツは複数のチャネルを持つことができます。これらのチャネルはすべて、パス内に集約される ChannelArray 内に集められます。次の図を参照してください。

チャネルには、プリチャネル セクションとポストチャネル セクションがあります。プリチャネル セクションとポストチャネル セクションは反時計回りの開いたポリラインで区切られています。反時計回りの開いたポリラインは、最初のゲートまたは最後のゲートを使用して閉じられます。プリチャネル セクションとポストチャネル セクションは、それぞれ最初のセクションと最後のセクションの延長です。これらのセクションは NavMesh の境界から抽出された簡素化されたポリラインであり、プリチャネル セクションまたはポストチャネル セクションの各位置は閉じたゲート上に自身の直角投影を確認することができます。次の図を参照してください。

チャネルのないパスでは、 NavMesh の動的な変更に従ってパスのナビゲート可能な部分を区切るために下限と上限が計算されます。下限と上限の間のすべてのセクションに障害物がないことを確認するために、下限と上限はゲート位置に配置されます。障害物がセクションと衝突した場合は、すべてのセクションが無効になります。障害物がプリチャネル セクションまたはポストチャネル セクションと衝突した場合、最初のセクションまたは最後のセクションがそれぞれ無効になります。

チャネルを計算する

パス ファインディング クエリ内でチャネルを作成できます。Kaim::Bot::ComputeNewPathToDestinationKaim::Bot::InitAStarQueryForBot などの Kaim::Bot の関数を使用してパス ファインディング クエリを起動すると、Bot の軌道モードが Kaim::TrajectoryMode_Spline の場合にはチャネルが自動的に計算されます。パス ファインディング クエリを初期化して起動する場合、SetComputeChannelMode 関数を使用してチャネルの計算を有効にすることができます。クエリは ChannelArray を計算するステージに移行します。このステージでは、NavMesh 上の各リファインしたパスの部分の周りに新しいチャネルを構築します。その後で、元のパスは、チャネルを集約したものと、そのまま残された NavGraph ベースの元のパスの部分に置き換えられます。

チャネルは、元のリファイン済みパス周囲のフリー スペースを集めることで計算されます。使用可能なフリー スペースが見つかると、必須の曲がり角にある最大のフリー スペースを考慮して、半径適合アルゴリズムによってこのような曲がり角が検出されます。これによって、チャネルが曲がる部分のゲートが決まります。その後、曲がり角と曲がり角の間の距離が長い場合は、利用可能なスペースをできる限り大きくするために中間ゲートが追加され、軌道の中でより幅の広い曲がり角を検出するために使用されます。

チャネルの CircleArcSpline と軌道

SDK には、チャネルにフィットする円弧ベースのスプラインを保持および追従する SplineTrajectory コンポーネントが用意されています。この CircleArcSpline は、円弧(マゼンダ)とセグメント(シアン)で構成されます。次の図を参照してください。

スプラインは、各側のコーナーへの距離を任意に設定し、任意の半径の円上に配置されるように最適化されます。ただし、チャネルの制限が大きい場合は、これらはリリースされ、これらの場所でスプラインは変更されないままになります(次善策)。

スプラインが低モード(SplineComputation_Degraded)の場合には再計算されます。スプラインが再計算されない場合、チャネルの軌道を更新するときに現在のスプラインの末尾が指定された距離(デフォルトでは 5 m)を超えて修正されることはありません。これにより、近づきつつある曲がり角を予測する、安定した軌道がフレーム間で提供されます。Bot のアニメーションで駆動される移動用のアニメーション システムに入力するためには、SplineTrajectory で正確かつ安定した情報を取得します。

CircleArcSpline にアクセスする

スプラインにアクセスして現在のスプライン上の Bot の位置とスプラインの計算方法を把握することができます。次の例を参照してください。

Kaim::ITrajectory* trajectory = m_bot->GetTrajectory(); //The bot has no trajectory, if it does not have a path.
Kaim::FollowedCircleArcSpline* followedSpline = trajectory-> GetFollowedCircleArcSpline(); // Give the following information.
followedSpline->m_spline;// Previously, trajectory->GetSpline()
followedSpline->m_positionOnSpline; //Previously, trajectory->GetPositionOnSpline()
followedSpline->m_computationMode

スプラインの計算モードは次のとおりです。

  • SplineComputation_Optimal: チャネルでスプラインを計算するときにすべてのコンストレイントが考慮されます。
  • SplineComputation_SubOptimal: チャネルでスプラインを計算するときにすべてのコンストレイントが考慮されません。
  • SplineComputation_Degraded: スプラインは正確には計算されず、ShortcutTrajectory から生成されます。
  • SplineComputation_Frozen: スプラインは再計算されませんが、BotConfig::m_trajectoryFailureModeTrajectoryFailureMode_Safe の場合、NavMesh の外に出たときにカットできます。TrajectoryFailureMode_Unsafe に設定すると、以前に計算されたスプラインがそのまま追従されます。この場合、Bot が NavMesh の外に出たり、除外された NavTag に進入することがあります。
    注:パスの上限はスプラインの安定距離にあります。新しいパスへの移行時のジッターやBot の開始動作および停止動作を避けるため、パス上に上限が移動した際にはスプラインは更新されません。
  • SplineComputation_OutOfNavMesh: Bot が NavMesh の外に出ます。スプラインは ShortcutTrajectory から生成されます。
  • SplineComputation_Failure: スプラインの計算が失敗しました。ショートカットがパスに到達できず、Bot が停止します。

パスを再計算する必要があるかを知るためにスプラインの計算モードを確認する必要はありません。m_bot->IsPathRecomputationNeeded() を呼び出してパスを再計算する必要があるかを確認することができます。

注:IsPathRecomputationNeeded() が true を返した場合でも軌道は速度を返すことができます。たとえば、計算モードが SplineComputation_Frozen のスプラインについて考えます。パスを再計算する必要がありますが、パスが計算される間も、軌道はまだスプラインを追従します。さらに、軌道が TrajectoryMode_Shortcut の場合には IsPathRecomputationNeeded() は true を返すこともあります。

狭いチャネルの内側のコーナーからのスプラインの最小距離

狭いチャネルの回転の内側のコーナーからのスプラインの最小距離を DistanceToInnerCorner() 関数を使用して定義することができます。

これまでは、境界からの距離の計算に浮動小数点パラメータ(distToBorder)が使用されていました。channelWidth が小さすぎる(distToBorder の 2 倍未満の)場合、この距離は、スプラインが狭いチャネルの中央を通過するようにリラックスされていました。スプラインと回転の内側のコーナーの間の距離を指定する区分的連続アフィン関数を channelWidth の関数として定義することでこのリラックスをカスタマイズできるようになりました。この関数表現は(0,0)で開始し、いくつかのポイントを通過し、最後のポイントの後で一定となるポリラインです。ポリラインのポイント[p0 ~ pn]を指定することでパラメータ化します。最初のセグメントは p0 に対して、(0,0)から自動的に取得されるため、(0,0)のポイントは指定されていません。デフォルト値は1点(0.4, 0.2)のみで、0.2 のデフォルト値が設定されたシングル フロートの distToBorder パラメータのように機能します。channelWidth が[0, 0.4]の場合には線形係数 0.5 の線形で、channelWidth が 0.4m より大きい場合には 0.2m で一定です。

注:channelWidth 内で位置を見つけることができるように、すべてのポイントが y<=x/2 を考慮する必要があります。内側のコーナーまでの距離が channelWidth/2 より大きい場合には、channelWidth 内に位置を見つけることができません。

通常は、小さい channelWidth 値の低線形係数(y=x/10 など)セクションの定義に使用され、最大距離のどこかで y=x/2 に再び接続します。次の図を参照してください。

  • デフォルト ケース: 1 点(0.4, 0.2)。channelWidth = 0.4m までは係数 0.5 の線形で、そのポイントの後は 0.2m で一定です。
  • カスタム ケース: 1 点(1.0, 0.2)。channelWidth = 1.0m までは係数 0.2 の線形で、そのポイントの後は 0.2m で一定です。
  • カスタム ケース: 2 点(0.3, 0.03)および(0.4, 0.2)。非常に低い係数 0.1 の線形で、その後急上昇して channelWidth > 0.4m の場合に 0.2m の一定の値に接続します。

対応する内側のコーナーまでの距離でチャネルの境界がオフセットされることで赤と緑のポリラインが取得されます。