Tomofiles Note

ドローンとインターネット、そして人との関係を考えるソフトウェアエンジニアのアウトプットブログ

座標系とCesiumJS

こんにちは。

最近、色々調べたり検証したりしていて、
せっかく勉強したことはブログにどんどん書いていきたいけど、
なかなか時間作れなくて困っています。
ちょっと油断すると、すぐに一週間が過ぎてしまいますからね。

今回は、前回のMAVSDKとCesiumJSの記事でトンチンカンなことを書いていた、
座標系について色々調べたり検証したので、それについてまとめたいと思います。

前回のおさらい

前回、MAVSDKから取得したクォータニオンをCesiumJSに表示するにあたり、
取得した値をそのままCesiumJSに流し込んでみたら、ドローンが変に傾いてしまいました。

tomofiles.hatenablog.com

このときは、ググって見つけたソースコードをコピペして解決していましたが、
何がどう解決したのか、ちゃんと理解できていませんでした。

なので、今回は、このコピペの意味をしっかりと理解することと、
調べたことを自分のために整理して残すために、記事を書きます。


2つの座標系

前回の時点で、座標系には少なくとも2つ存在することがわかっていました。
その2つをそのときは、ローカル軸と地球固定軸と呼びました。
クォータニオンは少なくとも、ローカル軸に縛られた表現であり、CesiumJSではそのまま使えませんでした。

これを踏まえ、座標系に関して体系立てて調べ、全体像から把握してみます。
※なお、以降記載する内容は、学術的な正しさを保証しません。
 製品等、何かしら使用する場合は、自己責任でお願いします。

ただ、いきなりですが、なかなかネット上に体系立った座標系に関するサイトは見つかりませんでした。
以下のWebサイトの連載記事とか、英語版Wikipediaを参考にしてみると、
まず座標系は、なんとなく2つに分類できそうです。

G空間データソリューションセンター
Coordinate system - Wikipedia

  • 天球座標系
  • 地理座標系

ただ、ややこしいことに、前回調べたローカル軸と地球固定軸とこれらは、別物です。(何
前回のことは一旦忘れて、まずはこれらの座標系の大枠を掴みましょう。
それでは、一つずつ見ていきます。

天球座標系

天球座標系 - Wikipedia

ひとつ目は、天球座標系です。
そもそも座標系は、何を軸とした位置を記述したいかによって、大きく分かれます。
大きい枠で見ると、まずそれは、地球自体なのか、地球外なのか、の2つです。

天球座標系は、後者の座標系であり、地球ではなく、衛星、惑星、銀河などの
広い範囲の位置を特定するために使用されます。
そのため、軸となるのは地球と限らず、太陽を軸にしたり、銀河を軸にしたりして、
広くその空間での位置を表現できるというのが、この座標系の特徴です。

天球座標系は、国際地球回転・基準系事業(IERS)という組織?により、標準化されており、
国際天文基準座標系(ICRS・ICRF)といいます。
この辺は深入りしなくても良いかなと、あまり調べてないですが、標準化の動きがあるということだけ理解しました。

ICRS・ICRFの地球重心版が、GCRS・GCRFというらしいです。
ベースとして宇宙空間の位置記述に目的を置いていて、ただ地球に関心のある位置記述もしたい、というような場合に利用するような座標系みたいです。

注目すべきは、地球重心を原点とした座標系だけど、地球の自転とともに座標も回転しないということです。
地球中心慣性(ECI)フレームとも言うそうですが、感覚的には、地球の地理的な面に依存する座標ではなく、重力的な面に依存する座標みたいな感じですかね。

Earth-centered inertial - Wikipedia

用途としては、人工衛星の運動に利用されるようですね。
ドローンの運動には直接利用されることは無い座標系だとは思いますが、衛星通信を利用したドローンの活用が実証実験されていたりして、
なんとなく知っておいても良いのかなと思って、今回挙げました。

NEDO:衛星ドローンによる山岳遭難者救助活動の実証実験に成功

地理座標系

地理座標系は、前述の通り、地球に関心のある座標系です。

地理座標系も、天球座標系と同様に国際標準があり、国際地球基準座標系(ITRS・ITRF)といいます。
これも同様に、地球中心のITRS・ITRFのことを、GTRS・GTRFと言います。

天球座標系は、ECIフレームにより、座標は地球の自転とともに回転しませんが、
地理座標系は、地球中心地球固定(ECEF)フレームといい、地球の自転とともに座標も回転します。
地球の動きと沿った座標であるため、地球上の位置記述に向いています。

ECIとECEFの違いは、以下のWebサイトにわかりやすい動画があって、おすすめです。

基礎知識 第二回 基準座標系|LSAS Tec 株式会社

ドローンなどの航空機の位置記述には地理座標系をベース考えれば大丈夫そうです。
天球座標系は前述の通り人工衛星などの宇宙機の位置記述に、主に利用されるので、一旦忘れても良いかもしれません。

地理座標系の重要なトピックを見ていきましょう。
以下の3つがあります。

  • 測地座標系
  • 三次元直交座標
  • 地平直交座標(ローカル接平面

おっと、やっと前回のトピックに似たワードが登場し始めました。

測地座標系

地理座標系は、通常は地球を回転楕円体と見なして、その表面上の位置を緯度、経度、高度で表現します。
回転楕円体とはなんぞや、と思うでしょうが、地球のシンプルなモデルと考えて大丈夫でしょう。
地球を楕円体に見立てて扱うと、楕円体表面上に緯度、経度などの地理座標を定義できるので、位置を記述するのに直感的で便利です。
地球は丸い、とは言うものの、完全な球体ではないので、このように回転楕円体として扱うことで、考え方をシンプルにしているのですね。

この回転楕円体も、前述のIERSによりGRS80準拠楕円体を国際標準(というか推奨しているだけ?)としています。

この辺の話は、以下のWebサイトが詳しいです。

G空間データソリューションセンター

GPSも緯度、経度、高度が取得できますが、GPSWGS84座標系が用いられています。
WGS84も、回転楕円体が定義されていて、衛星測位の際はこの回転楕円体を用いて座標計算しています。
WGS84とGRS80の回転楕円体は厳密には別物らしいですが、実用上の違いはほぼ無いそうです。
(国際標準のITRS・ITRFが定められてから、既存の座標系が標準に準拠するように修正が行われてきているそうです。GPS以外のGLONASSGalileoなど、各国のGNSSはそれぞれ別の座標系を用いていますが、その座標系がそれぞれ国際標準に準拠するようになっているため、各GNSSの測地に対する独自色は少なくなってきているようですね。)

GPSの測位の詳細に関しては、以下のWebサイト(の中のPDF)が詳しく記載されています。
なかなか数学知識が求められますが、イメージはなんとなく掴めそうですね。

GPS測位計算プログラム入門

三次元直交座標

回転楕円体の導入により計算がシンプルになると書きましたが、効果を発揮するのは直交座標に変換してからです。
回転楕円体により、地理座標を角度で表現できるようになりました。
この回転楕円体の中心を直交座標の原点と置くことで、緯度、経度、高度から(X, Y, Z)の三次元座標に変換出来ます。
直交座標は、多くの数学計算を簡素化します。

数学を忘れてしまって疎い私ですが、
複雑なシステム(地球)を、数値で記述可能なモデル(回転楕円体)と見なして、
楕円体表面上の座標(角度)で位置を表現し、
その座標を直交座標上の(x, y, z)に変換することで、
幾何学的に計算処理ができるというのが、とても便利であることは、
なんとなくわかります。
三角関数とかも、使えますしね。

前述のECEFは、地球の自転とともに回転する直交座標です。

測地座標系からECEFへの変換は、以下に詳しく記載されています。
やっぱり、三角関数多めですね。

Geographic coordinate conversion - Wikipedia

地平直交座標

最後に、地平直交座標です。
英語版Wikipediaには、ローカル接平面座標(ローカルタンジェントプレーン)と記載されていました。

地平直交座標は、これまでの地球規模の座標とは違います。
測地座標や三次元直交座標で定義された位置から、相対的な座標として扱います。
地平直交座標のイメージは、以下英語版Wikipediaに図が掲載されています。

Local tangent plane coordinates - Wikipedia

これを見ると、地球上のある位置に対して、新しい三次元の座標を配置しています。
このローカルな座標を、地球規模の座標の上に配置したときに、お互いがどのような関係性となるか、という規則を定めているのですね。

Wikipediaに掲載されている図には、ローカル座標に"east"、"north"、"up"と記載されています。
これがローカル座標における軸なのですが、eastがx、northがy、upがzと対応しています。
北がxじゃないんですよね。これがちょっと直感的じゃない印象を持ってしまいます。

座標系には、右手系と左手系があるそうです。
通常、右手系がメジャーに扱われる座標系らしく、左手系は非標準的な座標系であまり利用されません。
右手系というのは、右手の人差し指、中指、親指を立てたとき(フレミングの左手的なあれです)、人差し指がx、中指がy、親指がzに対応する座標系のことです。

右手系 - Wikipedia

北がxでもいいと思うんですけどね、ちょっとこれ以上のことは難しくて調べてないです。

上記、east、north、upの座標は、ENU座標と言います。
地上の車両や固定基地局など、下から上に対する関心のある場合に、ENU座標が利用されます。

ENU座標に対して、NED座標というものもあります。
NED座標は、"north"、"east"、"down"の座標です。
xが北、yが東、zが下に対応しています。(こっちは、北がxなんですよね。)
注目すべきは、z軸が下方向に対して正になっている点です。

NED座標を主に利用するのは、海上、航空の分野です。
これらの分野では、関心のあるオブジェクトは上ではなく下にあります。
そのため、下方向を正として扱ったほうが、何かと便利らしいです。

Axes conventions - Wikipedia

座標変換

ここまで、怒涛の勢いで座標系を一気に紹介しました。
本当はこれらの内容は、一つ一つが記事にできるくらい濃い内容なんですよね。
まぁ、細かい話は別に論じるつもりはなくて、全体感を掴みたいだけなので、全部ざっくりとした内容でまとめてしまいました。

さて、話はこれらの座標系の繋がりに入っていきます。

ここからは天球座標系を抜いて、

  • 測地座標
  • 三次元直交座標
  • 地平直交座標

に絞って、座標間の関係性について、まとめていきます。
そして、この内容が最終的にCesiumJSの座標変換ライブラリの話に繋がり、前回の記事の問題点を解決する流れとしていきます。

ゆーても、そこまで難しい話は書きません。
基本的に外部サイト参照、の形式を取っていきます。

まず、以下の座標系の変換は、数式による計算で変換可能です。

  • 測地座標(緯度、経度、高度) → 三次元直交座標(ECEFのx、y、z)
  • 三次元直交座標(ECEFのx、y、z) → 測地座標(緯度、経度、高度)
  • 三次元直交座標(ECEFのx、y、z) → 地平直交座標(ENUのeast、north、up)
  • 地平直交座標(ENUのeast、north、up) → 三次元直交座標(ECEFのx、y、z)

以下の英語版Wikipediaに、詳細な数式が記載されています。

Geographic coordinate conversion - Wikipedia

CesiumJSでは、測地座標と直交座標は、それぞれオブジェクトが用意されており、測地座標はCesium.Cartographic、直交座標はCesium.Cartesian3です。
これらのオブジェクトのメソッドを利用することで、それぞれのオブジェクト間の変換を実現出来ます。

また、直交座標とENU、NEDの変換は、Cesium.Transformsという変換関数セットが用意されています。
Cesium.Transformsは、これ以外の関数もよく見ると、ICRFとECEFとの変換など、天球座標系を含め、座標系変換の関数が色々含まれています。

これら座標系での姿勢の扱い

座標変換だけなら、そこまで難しい話題でもないです。
もちろん数学的な話だと、結構難しくて正直あまり理解できていませんが、大枠は捉えられたと思います。
それに計算ならコンピュータにやらせればいいですしね。

ちょっと厄介なのは、これら座標系での姿勢の計算です。
前回苦戦したクォータニオンは姿勢や回転を表現する方法の一つですが、このクォータニオンは地平直交座標での表現方法の一つです。

つまり、

  • 地平直交座標から三次元直交座標に変換してあげないと、CesiumJSではうまく表示出来ない
  • ENUとNEDのどちらに則したクォータニオンなのかが重要となる

ということです。

そもそもドローン等のセンサーを搭載した機体は、地球規模の座標を意識していません。
IMUのようなセンサーは、加速度センサーやジャイロセンサーなどを用いて、重力やコリオリ力を認識して姿勢の計算を行います。
以下のサイトにその辺が詳しく記載されています。

ロボットのための慣性計測装置(IMU)入門 - MyEnigma

CesiumJSでは、この姿勢の変換を回転行列で計算するようです。
回転行列が数学的にどのようなものなのかは、理解を諦めましたが、どのように利用するかだけは把握できるようにしました。
ということで、地球上のある位置における機体の姿勢を、(できるだけ)正しく扱う方法を整理していきたいと思います。

姿勢計算

まず、MAVSDKから取得できるクォータニオンがENUなのかNEDなのかを確認しましょう。

class Telemetry · MAVSDK Guide

クォータニオンのページ自体には、右手系であることしか記載されていないですが、他の項目の名称にNEDと記載されています。
ドローンも航空機の一種なので、NEDで座標を記述するということですね。

もう、この時点で前回のコピペの利用方法が誤っていたのがわかりますが、順を追って見ていきましょう。

三次元直交座標から地平直交座標に変換

Cesium.Transforms.eastNorthUpToFixedFrame、もしくは、northEastDownToFixedFrameを利用します。

Transforms - Cesium Documentation

三次元直交座標(x、y、z)は単純な地球上での位置ですが、その位置自体にも地球の中心に対する回転がかかっています。
つまり、その座標に存在するだけで、その対象物の姿勢は、ある原点から回転した姿勢となっているということです。

以下の画像は、だいたい赤道付近でゼロ回転のドローンをENUで表示したものです。

f:id:Tomofiles:20191103163252p:plain

地球に対して見たときに、ドローンの姿勢に違和感がないですが、仮に地球が見えないと仮定すると、ドローンは上部がこちらを向き、機首が右を向いています。
これが、地球の中心に対する回転です。
CesiumJSでは、このデフォルトの地球固定座標の回転に、機体から取得したローカル座標の回転を足し合わせ(足すというか掛ける?)、表示しないと正しい姿勢にならないということです。

試しに、ローカル座標として機体からオイラー角で以下のように取得できたとして、CesiumJSで表示してみます。

  • ヘディング:120度
  • ピッチ:0度
  • ロール:60度

f:id:Tomofiles:20191103164730p:plain

ちょっとわかりにくいですが、ENUの原点となる東から120度機首が回転し、60度機体が右に傾いています。正しそうですね。

さて、機体からテレメトリーとして取得できるクォータニオンは、NEDフレームとなっています。
なので、Cesium.Transforms.northEastDownToFixedFrameを使用して、ゼロ回転のクォータニオンでドローンの3Dモデルを表示してみます。

f:id:Tomofiles:20191103164147p:plain

あれま、3Dモデルがひっくり返りました。

同じように、オイラー角を指定して表示してみます。

f:id:Tomofiles:20191103170347p:plain

もう、よくわからん姿勢になっていますね。

これ、NEDフレームなので単純に北がx、東がy、下がzで表示しているのですが、3Dモデルの表示もNEDフレームに引っ張られているのです。
そのため、原点となる北に機首は向いていますが、z軸が下が正なので、3Dモデルの上下も下が正となってしまっているようです。
そう考えると、オイラー角で回転させたNEDフレームの画像は、向かって左に120度機首が回転し、60度機体が傾いているのがわかります。

航空機系の機体から取得できるフレームが標準的にNEDだと思うので、そうなるとCesiumJSの3Dモデル表示と簡単には噛み合わないということでしょうね。

NEDからENUへの変換

ということで、NEDからENUにフレームを変換して、ドローンを正しい向きに表示したいと思います。

NEDからENUへの変換は、あまり情報が出てきません。
色々調べて、以下の情報が計算式まで含めて出てきましたが、コメントがついていないのですよね。

https://stackoverflow.com/questions/53169107/quaternion-frame-conversions-ned-enu-eun

まぁでも、必要な理屈は理解できました。

ENUとNEDでまず大きく違うのは、x軸とy軸が逆ということです。
それから、z軸が正負逆になっています。
よって、x、y、zに対応する要素に対して、これらの変換をしてあげることで、フレームの変換ができるということです。そして、それが実現できるのがクォータニオンということですね。
最後の90度のクォータニオンを掛けているのは、ENUが東軸なので、NEDの北軸にするのに、90度回転させるということでしょう。

先程NEDフレームで変にひっくり返っていたサンプルに、上記フレーム変換を適用してみたところ、以下の画像のようになりました。

f:id:Tomofiles:20191103173148p:plain

北から120度右回りに回転し、機体が60度傾いています。
これがMAVSDKから取得できるクォータニオンの姿勢の正しい表示ということですね。

終わりに

長くなってしまったので、ここで今回は切り上げて、MAVSDKとCesiumJSの実際の解決編は別でまとめます。

座標変換は理解できればそれほど難しい概念ではないですね。
クォータニオンも基礎理論はおそらく難しい話なのでしょうが、(x, y, z, w)の要素自体はとても扱いやすく、計算もしやすく、CesiumJSでの関数も充実していて、結構柔軟にやりたいことを実現できるような気がします。

次は何を勉強・検証しましょうか。
題材を探しておきます。