Unity
制御工学

ランダムディザ量子化器とPCゲームの車両操作

More than 1 year has passed since last update.

概要

こんにちは。私はPCゲームが大好きなのですが、どうにも『WASDで運転する車』で事故が多発するためオープンワールドでも徒歩とFTだけで移動しております。
この問題は代表的な量子化制御問題ですので、ランダムディザ量子化器を簡単に実装してみた結果をAdvent Calender 2017の16日目に寄稿します。

問題設定

WASDでの車両操作が困難な理由は、下図のようにフィードバックループ内にキーボードが存在することにより、車両へのステアリング入力が左いっぱい、中立、右いっぱいの3通りからしか選択できないことによります。
image.png
プレイヤーの指示したステアリングを$d\in[-1,1]$で表すと、キーボードを介した実際のステアリング入力は

\delta = \lfloor d\rceil_{Q}

となります。ここに、$\lfloor\cdot\rceil_{Q}$は量子化された入力空間

Q=\left\{-1,0,1\right\}

への最近傍丸め1を表す写像であり、このような量子化手法を単純量子化と呼びます。
image.png
今回はこの単純量子化器に代わり、よりよい量子化手法にトライしてみます。
image.png

ランダムディザ量子化器

「よりよい」量子化器の一例として、ランダムディザ量子化器を導入します。ランダムディザ量子化器は単純量子化器の入力に「ディザ」と呼ばれる雑音を意図的に加算するものです。すなわち、

\delta = \lceil d + w\rfloor_Q

なる量子化手法です。上式において$w$がディザであり、$w\in [-\Delta/2,\Delta/2)$なる一様乱数です。ただし$\Delta=2/3$は量子化間隔を表します。

外乱を印加したにも関わらずよりよい結果が得られる理由については各種文献をご参照頂きたいのですが、よく行われる定性的な説明は下図の歯車のようなものでしょう。上段がランダムディザ量子化器、下段が単純量子化器による動力伝達の様子です。歯車の回転周期よりも十分に速い速度で緑の歯車を振動させることで、歯車の"あそび"、すなわち量子化の影響が低減されていることがわかります。
output.gif

実装

本来であれば私が苦心しているあれやこれやのゲームで試してみるのがよいのでしょうが、ゲームアプリへキーボードイベントを中継するアプリを作るには時間がない(現在16日3:46)ので、UnityのStandard Assetsパッケージから車体運動モデルを拝借しました。あとはステアリング処理の部分に量子化を施すだけです。

public void Move(...
{
  // ...(略)...

  // 量子化なしならば[-1,1]へのクランプのみ
  if (isWoQuantize) {
    steering = Mathf.Clamp (steering, -1, 1);
  // 単純量子化処理
  } else if (isSimpleQuantize) {
    steering = SimpleQuantization (steering);
  // ランダムディザ量子化処理
  } else if (isRandomQuantize) {
    steering = RandomDitherQuantization (steering);
  }

  // ...(略)...
}

private float SimpleQuantization(float str){
  float outvar;
  if (str < -1/3.0f) {
    outvar = -1;
  } else if (str > 1/3.0f) {
    outvar = 1;
  }
  else {
    outvar = 0;
  }

  return outvar;
}
private float RandomDitherQuantization(float str){
  // Random.valueが[0,1]なのを忘れていたことに今気づいた
  float outvar = str + 2.0f * (UnityEngine.Random.value - 0.5f) / 3.0f;
  if (outvar < -1/3.0f) {
    outvar = -1;
  } else if (outvar > 1/3.0f) {
    outvar = 1;
  }
  else {
    outvar = 0;
  }

  return outvar;
}

完成品はこちらにおいておきます。
https://unityroom.com/games/rdq

画面中のマウスカーソルの位置に応じて左端から右端まで$d\in[-1,1]$の入力が得られます。Wキーで量子化なし、Qキーで単純量子化、Rキーでランダムディザ量子化をテストできます。
image.png

おわりに

いかがでしょうか?私はランダムディザ量子化器により多少運転しやすくなったと感じましたが、定量評価を行う十分な時間がないのと、ランダムディザ量子化器を使用したときの挙動が露骨すぎるため2結論は出さずにおきます。

おやすみなさい。


  1. ゲームにより最近傍でない(不均一な)量子化間隔を持つ可能性はある 

  2. 熱燗と冷酒の違いを盲検することは困難である