一部、執筆しました。正直、高いよね。以上、宣伝でした。
Phantom4RTKのPPK処理
Phantom4RTKで撮影したデータをPPK(Post Processing Kinematic)するためのメモです。
処理の概要
- Phantom4RTKではGNSSの2周波の観測データを取得できます。対応しているGNSSは、GPS(米)、GLONASS(露)、BeiDou(中)、Galileo(欧)です(みちびき(日)は未対応)。
- 観測データおよび航行データは、0.2秒間隔(5Hz)で取得して、RTCM3.2 MSM5 形式のファイル「PPKRAW.bin」に保存されます。また、観測データをRINEX形式に変換したファイル「Rinex.obs」も保存されます。(PPKRAW.binを、FormatにRTCM3を指定しrtkconvで変換すると、Rinex.obsと同様の観測データのほかに、航行データが取得できます。)
- また、各画像の撮影時刻と、観測データを受信したアンテナの位置と画像を撮影したCMOSセンサーの位置の差は「Timestamp.MRK」に保存されます。
- 観測データをRTKLIBで処理することで正確な位置を算出し、CMOSセンサーとの位置の差を考慮して撮影画像に正確な位置を付与します。
- その際、観測データの位置情報は0.2秒間隔で、撮影位置とは一致していないので、観測データの取得時刻と撮影時刻の関係から線形補間します。
RTKLIBで正確な位置を算出
移動局(Rover)のデータにはRinex.obsを使用し、基準局(Base)と航行データ(.nav)は、近くの電子基準点のデータをダウンロードして使用します。RTKLIBの処理の詳細は、以下を参照してください。
ポイントとしては、次の処理のためにRTKLIBののOptionsのOutputの設定でHeaderをOFFにして、Time formatをww ssss GPST(1980年1月6日からの週数と週始めからの秒数)にして、Field separatorを「,」にしておきます。また、HeightはGeodeticにして出力を標高値にしておきます。(こうすることで、後述のMetashapeで処理した後のdemデータが、標高値になります(未実施なので要確認)。←おそらく問題ないと思いますが、楕円体高で処理した場合とで精度に違いが出ないか少し気になってます。)
Phantom 4 RTK - PPK Processing Workflow | Drone Data Processing
https://swest.toppers.jp/SWEST21/program/pdfs/s5a_public.pdf
https://www.naro.affrc.go.jp/publicity_report/publication/files/drone_gnss.pdf
撮影位置を補間
RTKLIBの処理で作成した.posファイル(0.2秒間隔の位置情報)と撮影時刻を記録した「Timestamp.MRK」から撮影位置を算出します。
算出には、以下からダウンロードできるEXCELファイルを利用します。
使用方法は、以下のサイトとファイルに書いてある通りですが、position fileの貼り付けは、別のシートで.posファイルをカンマ区切りで読み込んでおいて貼り付けると簡単です。(数式の列番号が間違っているところがあるので、自分で修正が必要です。)
Phantom 4 RTK - PPK Processing Workflow | Drone Data Processing
撮影位置を画像に付与
EXCELから出力されたcsvファイル(画像のファイル名と位置情報の対応情報)をMetashapeでインポートすれば、画像に位置情報を付与できます。
以下の資料にもあるように解の精度(Fix,Float,Single)によって位置精度を変更するように改造すると良いかもしれません。(以下資料のTimestamp Converterは公開されていない?ようです)
以下の12ページ目参照
Phantom4 RTKで、後処理キネマティック(PPK)をする方法
精度の目安は、fixで水平0.03m 垂直0.05m floatで水平、垂直0.5mにしようと思います。あと、画像がサブフォルダに分かれていて同じファイル名が複数あるとcsvと対応づけできないので、Metashapeに読み込む前にファイル名をフォルダ名+ファイル名に変換しておきます。
参考バッチファイル
フォルダ名をファイル名の頭に追加するバッチ| OKWAVE
RTKGPS+(カスタムバージョン)の更新
以前ビルドしたものがpixel3で起動できなくなってたので修正しました。
修正したapkはこちらからダウンロードできます。
コードはこちら
github.com
以下作業メモ
以前修正したコードを取ってくる。
git clone -b Customized https://github.com/tmizu23/RtkGps.git
RTKLIBの取得(最新版に変更)
cd RtkGps
git submodule deinit -f jni/RTKLIB
git rm -rf jni/RTKLIB
rmdir /s .git\modules\jni\RTKLIB
git submodule add -b rtklib_2.4.3 https://github.com/tomojitakasu/RTKLIB.git jni/RTKLIB
jni/RTKLIB-unixsocket.patchのパッチをあてる
android studioのVCS -> Apply patch... でファイルを指定する
以前の記事に従いソースを修正
simonlynen_android_libsの取得
git submodule update -i
以下のメッセージに従う
Minimum supported Gradle version is 6.1.1. Current version is 4.4.
Please fix the project's Gradle settings.
Fix Gradle wrapper and re-import project
基盤地図情報 標高DEMデータ変換ツールのコンパイル方法
基盤地図情報 標高DEMデータ変換ツール Version1.7.0のコンパイル方法です。
(QGIS3.10以降だと、以前のバージョンで変換したdemのCRSが不明となってしまったので、gdalとprojを更新して対応しました。ついでに32bit OS での動作は非対応にしました。その際の自分用メモです。
1. Visual Studio Community 2017をインストール
https://visualstudio.microsoft.com/ja/vs/older-downloads/
ここからダウンロードしてインストールして、x64 Native Tools コマンドプロンプトを起動します。
2. projをコンパイル
projのver6.3.2をダウンロードします。
https://proj.org/download.html
sqlite3をダウンロードします。
https://www.sqlite.org/2020/sqlite-amalgamation-3320300.zip
以下を参考にビルドします。
https://gist.github.com/pebbie/f5f0b1db7fc4039af89054c1b3fb532fbuilding proj6 on visual studio 2017 (windows) · GitHub
3.gdalをコンパイル
gdalの3.0.4をダウンロードします。
https://github.com/OSGeo/gdal/releases/download/v3.0.4/gdal-3.0.4.tar.gz
nmake.optを変更します。
・nmake.optのSETARGVを変更。
SETARGV = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64\setargv.obj"
・nmake.optのPROJを変更
PROJ_INCLUDE = -IC:\Users\mizutani\Desktop\proj-6.3.2\build\distro\include
PROJ_LIBRARY = "C:\Users\mizutani\Desktop\proj-6.3.2\build\distro\lib\proj.lib"
・nmake.optのssqlite3を変更
SQLITE_INC=-IC:\Users\mizutani\Desktop\proj-6.3.2\build\sqlite3
SQLITE_LIB=C:\Users\mizutani\Desktop\proj-6.3.2\build\sqlite3\sqlite3.lib
gdalを以下のコマンドでビルドします。
nmake -f makefile.vc MSVC_VER=1910 WIN64=yes
nmake -f makefile.vc devinstall MSVC_VER=1910 WIN64=yes
c:\warmerda 以下にgdal一式がインストールされます。
4. dem.cppをコンパイル
基盤地図情報 標高DEMデータ変換ツールの中に移動して以下を実行します。
cl -Ic:\warmerda\bld\include c:\warmerda\bld\lib\gdal_i.lib dem.cpp
5. gdalのexe、dll、dataをコピー
C:\warmerda\bld\binから基盤地図情報 標高DEMデータ変換ツールの中にコピーします。
・gdal300.dll
・gdalbuildvrt.exe
・gdalwarp.exe
・gdaldem.exe
C:\warmerda\bld\dataフォルダを基盤地図情報 標高DEMデータ変換ツールの中にコピーします。
6. projをコピー
C:\Users\mizutani\Desktop\proj-6.3.2\build\distro\share\projフォルダを基盤地図情報 標高DEMデータ変換ツールの中にコピーします。
以上です。
補足
変換結合.vbsの中でgdalを使用するための 環境変数を設定してあります。
tempEnv.Item("GDAL_DATA") = "data"
tempEnv.Item("GDAL_FILENAME_IS_UTF8") = "YES"
tempEnv.Item("PROJ_LIB") = "proj"
Rを用いたGIS
しばらく前に作った資料「Rを用いたGIS」のリンクです。
(google slideとgithub.ioに置いてあったけど、埋もれて探せなくなってきたのでこちらにスクラップ)
※資料を作成したときからsfパッケージのバージョンも上がってるので、今となっては動かないコードもあるかもしれません。
最初のバージョン
docs.google.com
応用編を一部変更
docs.google.com
上の資料のコードをRmarkdownで出力したもの
tmizu23.github.io
植生調査の凡例一覧をRSelemiumとrvestでスクレイピングしてxlsxデータにする
最新の凡例一覧をデータで公開してもらえれば済む話ですが、凡例Q&Aここのエクセルは更新されていないようなので、統一凡例一覧表をスクレイピングしてみます。
ただ、凡例のサイトは生データのtableでなくて、javascriptで生成されており、rvestだけではスクレイピングできないのでSelemiumも利用します。
※スクレイピングした凡例も、公開されているshpの属性中の凡例をすべては網羅していないのでご注意ください。
Selemiumの準備
以下のサイトを参考にしました。C:\seleniumに必要なファイルを入れてパスも通しておきます。javaが入っていない場合は、javaもインストールしておきます。
qiita.com
Rでスクレイピングする準備
RでRSeleniumとrvestとtydiverseのパッケージをインストールしておきます。
RTKGPS+をWindowsでビルド
(2020.8.12追記 apkを更新しました。http://tmizu23.hatenablog.com/entry/2020/08/09/100146 )
スマホ用のRTKアプリ「RTKGPS+」をカスタマイズしてビルドする方法です。
GNSSの後処理キネマティック (PPK) をするためには、受信機のRawデータを取得する必要があります。Pixcel3などのアンドロイドスマホとNeo-M8TなどのRTK対応の受信機をUSBで接続してRTKGPS+を使うと、Rawデータを簡単に取得できます。ただ、オリジナルのアプリだとQZSSのデータが表示されないのと、2周波対応のZED-F9Pの受信機に対応してなさそうなので、カスタマイズしてみます。ついでにマップに地理院地図も表示できるようにしてみます。
※オリジナルのものでもQZSSのRawデータは取得できてるっぽいのでPPKの処理は問題ないですが。
2周波表示とQZSS表示のポイントは、該当箇所のコメントアウトを外すことと、RTKGPS+用のパッチを当てればよかっただけなのですが...コードを理解してそれに気が付くまでが長かった...
RTKGPS+のコード取得
git で以下のコマンドで取得する。RTKLIBなど関連プロジェクトも含めて取得するため --recursive が必要なので注意!
git clone --recursive https://github.com/eltorio/RtkGps.git
Android StudioでRTKGPS+を開く
Android Studioで取得したRtkGpsフォルダを開くと、自動でSyncされて足りないライブラリなどをインストールするようにメッセージやらエラーがでるので従う。
必要なライブラリがそろうと、ビルドできるようになるがエラーで止まるので、以下のコードの修正をする。
環境変数を設定する
Windowsの環境変数のPathに以下を追加
C:\Users\mizutani\AppData\Local\Android\Sdk\ndk\20.0.559457
C:\Users\mizutani\AppData\Local\Android\Sdk\platform-tools
ビルドが通るようにコードの修正
- jni/Application.mkを修正
APP_STLをc++_staticから変更。APP_ABIを追加
APP_STL := c++_shared APP_ABI := armeabi-v7a
- build.gradleを修正
abiFiltersをarmeabi-v7a以外をコメントアウトする。(とりあえずデバッグするためにビルドを速くしたいから。リリース時は、要変更)
defaultConfigの packagingOptionsに pickFirstを追加する。
defaultConfig { applicationId "gpsplus.rtkgps" minSdkVersion 21 targetSdkVersion 26 multiDexEnabled true ndk { abiFilters = [] abiFilters.add('armeabi-v7a') //abiFilters.add('x86') //abiFilters.add('x86_64') //abiFilters.add('arm64-v8a') } packagingOptions { pickFirst 'lib/armeabi-v7a/libc++_shared.so' pickFirst 'lib/armeabi-v7a/libproj.so' pickFirst 'lib/armeabi-v7a/librtkgps.so' pickFirst 'lib/armeabi-v7a/libntripcaster.so' pickFirst 'lib/armeabi-v7a/libgdalalljni.so' pickFirst 'lib/x86_64/libc++_shared.so' //pickFirst 'lib/x86_64/libntripcaster.so' //pickFirst 'lib/x86_64/librtkgps.so' //pickFirst 'lib/x86_64/libproj.so' //pickFirst 'lib/x86_64/libgdalalljni.so' //pickFirst 'lib/x86/libc++_shared.so' //pickFirst 'lib/x86/librtkgps.so' //pickFirst 'lib/x86/libgdalalljni.so' //pickFirst 'lib/x86/libntripcaster.so' //pickFirst 'lib/x86/libproj.so' //pickFirst 'lib/arm64-v8a/libc++_shared.so' //pickFirst 'lib/arm64-v8a/libproj.so' //pickFirst 'lib/arm64-v8a/librtkgps.so' //pickFirst 'lib/arm64-v8a/libntripcaster.so' //pickFirst 'lib/arm64-v8a/libgdalalljni.so' } もともとあるコード }
- License.java.sampleの変更
src/gpsplus/rtkgps/geoportail/License.java.sampleのファイル名をLicense.javaに変更
QZSSを表示できるようにコードを修正
jni/rtklib.mkのRTKLIB_CFLAGSをコメントアウトしていあるものに変更(RtkGps+の作者はQZSSが関係ない地域の人だったのかな?)
RTKLIB_CFLAGS := -DENAGLO -DENAGAL -DENAQZS -DENACMP -DNFREQ=3 -DTRACE
ライブラリのビルド
Android StudioのTerminalでRtkGps/jniのフォルダに移動後、ndk-buildのコマンドでライブラリをビルド
cd RtkGps/jni ndk-build
アプリのビルド
Android Studioでビルドボタンを押す
アプリの起動テスト
Android StudioでBuild APKをするとbuild/outputs/debugフォルダにapkができるので、実際のスマホにコピーして、ファイルアプリから開いてインストールする。
デバッグ
https://okfoxy1990.com/android-apps-wifi-debug
Android Studioで開発したアプリを実機でテストする方法【初心者向け】 | TechAcademyマガジン
上記を参考にしてWIFI接続でデバッグできるようにする。USBは受信機を接続しているので。
開発者モードでUSBデバッグを有効にしてから、USB接続して、以下のコマンドを打つ adb.exe tcpip 5555 USB外して、以下のコマンドを打つ。ipはスマホのipアドレスを確認して指定 adb.exe connect 192.168.1.11
Android Studioで実機のデバイスを指定して実行すると、実機にアプリがインストールされて起動する。
デバッグモードとなっているのでAndroid StudioのLogcatタブにLogが出力される。
アプリのインストール
Android Studio : debugビルドとReleaseビルドの切替、releaseビルドの追加方法、署名付きapk作成方法 | 生活を良くします-怠惰なプログラミング
上記を参考にする
RTKLIBの更新
submoduleとなっているRTKLIBを更新する。
rtklibexplorerバージョンの場合
cd RtkGps git submodule deinit -f jni/RTKLIB git rm -rf jni/RTKLIB rmdir /s .git\modules\jni\RTKLIB git submodule add https://github.com/rtklibexplorer/RTKLIB.git jni/RTKLIB
jni/rtklib.mkの以下の行を削除
$(RTKLIB_PATH)/src/rcv/ss2.c \
jni/RTKLIB-unixsocket.patchのパッチをあてる
android studioのVCS -> Apply patch... でファイルを指定する
オリジナルの場合
android studioのterminalで以下を実行(コマンドプロンプトなのでフォルダ消すときはrmdir)
cd RtkGps git submodule deinit -f jni/RTKLIB git rm -rf jni/RTKLIB rmdir /s .git\modules\jni\RTKLIB git submodule add -b rtklib_2.4.3 https://github.com/tomojitakasu/RTKLIB.git jni/RTKLIB
jni/rtklib.mkの以下の行を削除
$(RTKLIB_PATH)/src/rcv/swiftnav.c \ $(RTKLIB_PATH)/src/rcv/comnav.c \
jni/prcopt.cを変更する(面倒なのでパッチの内容)
diff --git a/jni/prcopt.c b/jni/prcopt.c index 49d6884..7b88048 100644 --- a/jni/prcopt.c +++ b/jni/prcopt.c @@ -189,16 +189,16 @@ void processing_options2prcopt_t(JNIEnv* env, jobject thiz, prcopt_t *dst) GET_FIELD(modear, Int) GET_FIELD(glomodear, Int) - GET_FIELD(gpsmodear, Int) + //GET_FIELD(gpsmodear, Int) GET_FIELD(bdsmodear, Int) - GET_FIELD(arfilter, Int) - GET_FIELD(minfixsats, Int) - GET_FIELD(minholdsats, Int) - GET_FIELD(mindropsats, Int) - GET_FIELD(rcvstds, Int) + //GET_FIELD(arfilter, Int) + //GET_FIELD(minfixsats, Int) + //GET_FIELD(minholdsats, Int) + //GET_FIELD(mindropsats, Int) + //GET_FIELD(rcvstds, Int) GET_FIELD(armaxiter, Int) - GET_FIELD(varholdamb, Double) - GET_FIELD(gainholdamb, Double) + //GET_FIELD(varholdamb, Double) + //GET_FIELD(gainholdamb, Double) GET_FIELD(maxaveep, Int) GET_FIELD(initrst, Int) GET_FIELD(outsingle, Int) @@ -352,22 +352,21 @@ static void ProcessingOptions_load_defaults(JNIEnv* env, jobject thiz) SET_FIELD(modear, Int) SET_FIELD(glomodear, Int) - SET_FIELD(gpsmodear, Int) + //SET_FIELD(gpsmodear, Int) SET_FIELD(bdsmodear, Int) - SET_FIELD(arfilter, Int) - SET_FIELD(minfixsats, Int) - SET_FIELD(minholdsats, Int) - SET_FIELD(mindropsats, Int) - SET_FIELD(rcvstds, Int) + //SET_FIELD(arfilter, Int) + //SET_FIELD(minfixsats, Int) + //SET_FIELD(minholdsats, Int) + //SET_FIELD(mindropsats, Int) + //SET_FIELD(rcvstds, Int) SET_FIELD(armaxiter, Int) - SET_FIELD(varholdamb, Double) - SET_FIELD(gainholdamb, Double) - SET_FIELD(maxaveep, Int) - SET_FIELD(initrst, Int) - SET_FIELD(outsingle, Int) - SET_FIELD(syncsol, Int) - SET_FIELD(freqopt, Int) - + //SET_FIELD(varholdamb, Double) + //SET_FIELD(gainholdamb, Double) + //SET_FIELD(maxaveep, Int) + //SET_FIELD(initrst, Int) + //SET_FIELD(outsingle, Int) + //SET_FIELD(syncsol, Int) + //SET_FIELD(freqopt, Int) SET_FIELD(maxout, Int) SET_FIELD(minlock, Int) SET_FIELD(minfix, Int)
jni/RTKLIB-unixsocket.patchのパッチをあてる
android studioのVCS -> Apply patch... でファイルを指定する
osmdroidの更新と地理院地図の追加
build.gradleにosmdroidの最新バージョン追加。もともとのosmdroidのjarは削除する
dependencies { implementation 'org.osmdroid:osmdroid-android:6.1.2' もともとあったコード }
osmdroidのバージョンの違いによりエラーがでるのでMapFragment.javaまわりを修正。地理院地図を追加してgeoportailの地図を削除。
上記を変更したRtkGps+のコードはこちらにあります。
(2019.11.29 追記:apkも以下のreleaseの中にアップしておきました。)
github.com
あとがき
もともとの目的はドローン用対空標識の座標決めで、2周波RTKだったら3分ぐらいの受信と電子基準点との後処理でFixするかも?という期待でしたが、結果5km離れた電子基準点では、3分ではFixせず、最低5分は必要でした。あと、PPKしか試してないので、RTKGps+を使って2周波のRTK測位を試したいですが、Zed-F9Pは1台しかないので、安くなってからかな...