Tag Archives: RTK

RTK基準局を設置~その2~

前回の作業で基準局用アンテナを設置し、その座標を求めました。
今回はRasberrypiを使って自宅用NTRIPサーバーを設置します。

構想

RTK基準局はアンテナで受信した電波の遅延等を補正データーとしてローバーに送ります。
テスト的に動かすならPCを基準局にしてローバーと1対1で接続するのでもOKですが、最終的には常時稼働にしたいし、また今後台数が増えてもいい様にもしたいです。

1対1の接続イメージ

その為に下図のイメージでローカルなNTRIPサーバーを稼働させようと思います。
NTRIPサーバーにはオープンソースのNtripcasterを使用します。
受信機のデーターを受け取ってNtripcasterに投げるのはRTKLIBに含まれるSTR2STRを使います。
受信機のデーターをSTR2STRがNtripcasterに送り、NtripcasterがGCSの要求に応じてデータを配信するイメージです。

自宅内にNtripcasterを動かすイメージ。今回はこれで行く。


ところでNTRIPは基準データをネットで配信するプロトコルで、これを利用したNTRIPサーバーが各地にあり多数の善意の基準局がデーターを配信されています(こんなところや、こんなところ参照)。
本当は自分の基準データーもこれらの公開されたNTRIPサーバーに上げれば近所の人まで使えてハッピーなのですが、今回立ち上げるのは自宅に設置したRTK基準局です。 会社や学校の設備ならともかく、今のご時世に自宅の座標をセンチメートルレベルで公開してしまうのは不安があるので当面これは止めときます。

公開されたNtripサーバーを使うイメージ。本当はこうしたいところだが当面やめておく。


なお最終的に常時稼働させたいので電力が少なくて済むRaspberryPiで構築します。
RaspberryPiには、ちょっと古いですがRaspberryPi2が手持ちにあったので、str2strもNtripcasterもこの中で動作させる事にします。

という事で今回やることは次の通りです。

  1. ZED-F9P受信機の設定
  2. RaspberryPiの準備(OSインストール他)
  3. Ntripサーバー(Ntripcaster)インストール
  4. STR2STR(RTKLIBに含まれる)インストール
  5. OS起動時に自動的に立上る設定とかシャットダウンボタンの設定

ZED-F9P受信機の設定

前回アンテナ座標を得るために受信機を設定しましたが、基準局として動作させるにはRTCMデータを出力させる必要があります。
参考にしたのはトラ技2019年10月号の第1部7章で、初期状態からの変更点は・・・

  • UBX-CFG-DGNSSの中で・・・
    Differential mode3=RTK fixed: Ambiguities are fixed whenever possible.に設定。
  • UBX-RXMの全て(RAWX,SFRBX等)を停止。
  • UBX-CFG-MSGの中で以下のメッセージにUSBへの出力を有効化(Message欄に下記を選んでUSBにチェック印を入れる)。
     01-35 NAV-SAT
     F5-05 1005 (基準極座標)
     F5-4D 1077 (GPS観測データ)
     F5-57 1087 (GLONASS観測データ)
     F5-61 1097 (Galileo観測データ)
     F5-4D 1127 (BeiDou観測データ)
     F5-4D 1230 (GLONAS補正データ)
     ※QZSS(みちびき)のRTCMデーター出力は今のところF9Pでは対応していない様です。
  • UBX-CFG-NAV5の中で・・・
     Dynamic Model = 2-Stationary
     Fix Mode = 3-Auto 2D/3D
     UTC Standard = 0-Automatic
  • UBX-CFG-PRTの中で・・・
     Target = 3-USB
     Protocol in = 0+1+5-UBX+NMEA+RTCM3
     Protocol out = 0+1+5-UBX+NMEA+RTCM3
  • UBX-CFG-TMODE3の中で・・・
     Mode = 2-Fixed Mode
     Lat,Long,Altを前回求めた座標値に設定。

・・・それぞれ忘れずに設定を書き込んでおく。

RasberryPiの準備

RaspberrypiOS(現行版のTrixie、GUIは不要なのでLite版)をインストールし、sshでログインできる様に設定しました。
そして下記の基本準備を実行しておきます・・・

 $ sudo apt update
 $ sudo apt install git

Ntripcasterをインストールする。

インストールは下記コマンドで特にエラーもなく終了しました。

$ git clone https://github.com/roice/ntripcaster
$ cd ntripcaster/ntripcaster0.1.5 # この時のバージョンは0.1.5だった。
$ ./configure
$ make
$ sudo make install
$ cd /usr/local/ntripcaster/conf
$ sudo cp -p ntripcaster.conf.dist ntripcaster.conf
$ sudo cp -p sourcetable.dat.dist sourcetable.dat

次にエディタでntripcaster.confを編集します。
不明な点やたぶんローカル使用だと不要お思われる点も多いですが、下記に記載の箇所を変して動作しています。

##################################
# NtripCaster configuration file #
################################################################################

############### Server Location and Resposible Person ##########################
# Server meta info with no fuctionality.

### 下記3行を変更したがローカル使用なので多分あまり影響しない。
location BKG                     →HOIHOIDOに変更
rp_email casteradmin@ifag.de     →自分のメールアドレスに変更
server_url http://caster.ifag.de →http://192.168.1.212に変更

########################### Server Limits ######################################
# Maximum number of simultaneous connections.

### 下記3行も気分的に変更した。
max_clients 100                  → 20
max_clients_per_source 100       → 20
max_sources 40                   → 8

######################### Server passwords #####################################
# The "encoder_password" is used from the sources to log in.

### パスワードを変更しておく。
encoder_password sesam01         → XXXXXXXX

#################### Server IP/port configuration ##############################
# The server_name specifies the hostname of the server and must not be set to
# an IP-adress. It is very important that server_name resolves to the IP-adress
# the server is running at.
# For every port, the server should listen to, a new port line can be added.

### 下記1行も変更したが、これもローカルだと意味なさそう。
server_name igs.ifag.de          →rtk.hoihoido.com
#port 80
port 2101

######################## Main Server Logfile ##################################
# logfile contains information about connections, warnings, errors etc.

logdir /usr/local/ntripcaster/logs
logfile ntripcaster.log

############################ Access Control ###################################
# Here you specify which users have access to which mountpoints,
# one line per mount.
#
# Syntax: /<MOUNTPOINT>:<USER1>:<PASSWORD1>,<USER2>:<PASSWORD2>,...,<USERn>:<PASSWORDn>
#
# /<MOUNTPOINT>: name of the mountpoint. Must start with a slash.
# <USERi>: name of the user that has access to <MOUNTPOINT>.
# <PASSWORDi>: password of <USERi>.
#

### たぶん、ここが一番大事
# example:
#/mount0:user0:pass0,user1:pass1,user2:pass2
#/BUCU0:user1:password1,user2:password2 → コメントアウト
#/PADO0                                 → コメントアウト
/HOIHOIDO                              → 追加

そしてエディタでsourcetable.datも編集します。
初期設定行を全部消して下記を記載しました。こちらもローカルサーバーなので適当なところもあります(もしかするとCASやNETの行は無くてもいいのかもしれません)。
きちんとした説明は公式のドキュメントを参照してください(doc形式なのでダウンロードする方が見やすいかも)。

CAS;192.168.1.212;2101;NtripInfoCaster;HOIHOIDO;0;JPN;32.87;130.76;http://192.168.1.212
NET;LOCAL;HOIHOIDO;N;N;192.168.1.212
STR;HOIHOIDO;Koshi;RTCM3.3;1005(1),1077(1),1087(1),1097(1),1127(1),1230(1);2;GPS+GLO+GAL+BDS;;JPN;32.87;130.76;0;0;u-bloxZED-F9P;none;N;N;;

STR2STR(RTKLIB)をインストール。

RTKLIB一式をインストールしてSTR2STRが使える状態にします。
これも下記コマンドで特に問題なくインストールできました。
設定する様なファイルはありません(実行時のコマンドラインオプションに色々書く方式)。

$ git clone https://github.com/tomojitakasu/RTKLIB.git
$ cd RTKLIB/app
$ chmod 755 makeall.sh
$ ./makeall.sh

動作確認

では手動で実行してテストしてみます。まずはNtripcaster。

$ cd /usr/local/ntripcaster/bin
$ sudo ./ntripcaster

次にstr2strを実行します。
こちらはコマンドラインに動作を色々と書いています。
やっている事を一言でいうと、「シリアルポートttyACM0から230400bpsで取ってきたデーターをntripプロトコルでlocalhostのポート2101に投げる。Ntripサーバーに投げる為のパスワードはXXXXXXXXで基準局の名前はHOIHOIDO」となります。

$ cd ~/RTKLIB/appstr2str/gcc
$ ./str2str -in serial://ttyACM0:230400 -out ntrips://:XXXXXXXX@localhost:2101/HOIHOIDO

この状態でRTK基準局として補正データーを配信してくれている筈なので、Ntripプロトコルで受信できるか試してみます。

まずWindows PC上でRTKNAVIを実行し、右上の[I]ボタンを押します。
(2)Base Stationだけにチェックを入れて、TypeをNTRIP Clientに、FormatをRTCM3に設定してOpt欄の「…」を押します。
そしてラズパイサーバーのIPアドレスとポート番号(2101)を入力して一旦[GetMountp]ボタンを押すと・・・

MountpointプルダウンにNTRIPサーバー内で管理している基準局一覧が出ます。
ここでは先程作ったHOIHOIDOのみが表示されるのでこれを選びます。

OK × 2回でメイン画面に戻り、[スタートボタン]を押すと・・・

基準局で受信した結果がグラフとして出てきますね。
でもよく見るとグラフ右上の表示が「GRE」となっています。これはGPS,GLONASS,Galileoを受信していることを示しますがBeidouが無いですね。
一旦「■Stop」で止めて「Options…」ボタンを押すと下記の通りBDSにチェックが入っていませんでした。
ここにチェックを入れて・・・

再びスタートすると受信衛星数が一気に増えて賑やかになりました。
グラフ右上の表示も「GREC」となり、「C」が増えています。

という事でBeidouも受信できていますね。
なお、この中にQZSS(みちびき)が含まれていないのは上にも書いた通り、F9PのRTCM出力にQZSSを含められないからです(実は方法があったりするのでしょうか?)。

ここまで来たら目的の動作は出来ているので、あとは使いやすい様に電源を入れたら即起動する設定と、電源を切るとき用にシャットダウンボタンを追加していきます。

RaspberryPi立上げ時に起動する設定

UNIX系OSの立上り時に自動的にプログラムを実行する設定は、古くは/etc/rc.localだったり、比較的最近まで/etc/rc*.dだったりしましたが、最近はまた新しくなっていてsystemdというのが標準で、これを使えば起動が早いそうです。という事でsystemdで設定してみます。

/etc/systemd/systemの下にntripcaster.serviceという名前でファイルを作って下記の内容を書きます。

[Unit]
Description=ntripcaster
After=syslog.target

[Service]
Type=simple
WorkingDirectory= /usr/local/ntripcaster/bin
ExecStart=/usr/local/ntripcaster/bin/ntripcaster
TimeoutStopSec=5
StandardOutput=null

[Install]
WantedBy = multi-user.target

同様にstr2str.serviceという名前で以下のファイルを作ります。

[Unit]
Description=str2str
After=ntripcaster.service

[Service]
Type=simple
WorkingDirectory= /usr/local/bin
ExecStart=/usr/local/bin/str2str -in serial://ttyACM0:230400 -out ntrips://:XXXXXXXX@localhost:2101/HOIHOIDO
TimeoutStopSec=5
StandardOutput=null

[Install]
WantedBy = multi-user.target

systemdを制御する主なコマンドは下の通りなので・・・

$ sudo systemctl start <サービス名> // 手動起動
$ sudo systemctl stop <サービス名> // 手動停止
$ sudo systemctl enable <サービス名> // 自動起動設定
$ sudo systemctl disable <サービス名> // 自動起動停止
$ journalctl -u <サービス名> // ログを見る

Ntripcasterとstr2strを手動で起動してみます。

$ sudo systemctl start Ntripcaster
$ sudo systemctl start str2str

この状態で上で試したのと同様にWindows PCからNtrip経由で情報を受け取れるはずです。
問題なければ下記コマンドで一旦停止し・・・

$ sudo systemctl stop Ntripcaster
$ sudo systemctl stop str2str

立ち上げ時の自動起動を有効にすると、再起動しても立ち上がっている筈です。

$ sudo systemctl enable Ntripcaster
$ sudo systemctl enable str2str

シャットダウンボタン。

常時起動にしてもシャットダウンする事はあります。その際sshでログインしてシャットダウンするのも面倒なのでシャットダウンボタンを付けておきます(これは色々な方法がありそうですが、自分の備忘録として書いときます・・・)

まずスイッチはGPIO3とGND間にタクトスイッチを付けました。

プログラムからGPIOをコントロールするライブラリとして以前はwiringPiを使っていましたが、もう古くてサポートされない様です。で、今風なのはlibgpiodだそうなので、まずこれをインストールしておきます。

$sudo apt install libgpiod3

そして下の内容でsdbuttond.cというファイルを作成し・・・

#include <stdio.h>
//#include <wiringPi.h>
#include <gpiod.h>
#include <stdlib.h>
#include <unistd.h>

//#define DBG

#define STARTTIME 10
#define STOPTIME 3
#define SDBUTTON 3

void DoShutdown() {
#ifdef DBG
  printf("Exec shutdown!!\n");
#endif
  system ("shutdown -h now");
}

int main() {
  int starttimer=STARTTIME;
  int stoptimer=STOPTIME;
  int enablef=0;
  int val;


  // libgpiod関係の準備ここから
  const char *chip_path = "/dev/gpiochip0";
  unsigned int offset = SDBUTTON;  // GPIO**
  struct gpiod_chip *chip;
  struct gpiod_line_config *line_cfg;
  struct gpiod_request_config *req_cfg;
  struct gpiod_line_request *request;
  struct gpiod_line_settings *settings;

  // チップを開く
  chip = gpiod_chip_open(chip_path);
  if (!chip) {
    perror("gpiod_chip_open");
    return 1;
  }

  // ライン設定作成
  settings = gpiod_line_settings_new();
  gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_INPUT);
  gpiod_line_settings_set_bias(settings, GPIOD_LINE_BIAS_PULL_UP);

  // ラインコンフィグ
  line_cfg = gpiod_line_config_new();
  gpiod_line_config_add_line_settings(line_cfg, &offset, 1, settings);

  // リクエスト設定
  req_cfg = gpiod_request_config_new();
  gpiod_request_config_set_consumer(req_cfg, "button");

  // リクエスト作成
  request = gpiod_chip_request_lines(chip, req_cfg, line_cfg);
  if (!request) {
    perror("gpiod_chip_request_lines");
    return 1;
  }
  // libgpiod関係の準備ここまで


  while(1) {
    val = gpiod_line_request_get_value(request, offset);
    if (enablef==0) {
      // まだイネーブルになっていない場合。
      if (val == 1) {
        starttimer--;
      } else {
        starttimer=STARTTIME;
      }
      if ( starttimer == 0) { enablef = 1;}
    } else {
      // イネーブルになった後。
      if (val == 0) {
        stoptimer--;
      } else {
        stoptimer=STOPTIME;
      }
      if ( stoptimer == 0 ) {
        DoShutdown();
        return 0;
      }
    }
#ifdef DBG
    printf("enablef:%d starttimer:%d stotimer:%d\n",
           enablef,starttimer,stoptimer);
#endif
    sleep(1);
  }
}

各#defineの意味は下記の通りです。

  • #define STARTTIME 10
    起動後この秒数はボタンを押してもシャットダウンしない。
  • #define STOPTIME 3
    この秒数押すとシャットダウンする(但しポーリングにつき1秒のばらつき有り)
  • #define SDBUTTON 3
    ボタンを接続するGPIO番号。3にしておくと再立ち上げにも使える。


次の様にコンパイルして実行ファイルsdbuttondを/usr/local/binの下にコピーします。

$ gcc sdbuttond.c -o sdbuttond -lgpiod
$ sudo cp sdbuttond /usr/local/bin
$ sudo chmod 755 /usr/local/bin/sdbuttond

先の2件と同様に/etc/systemd/system/sdbuttond.serviceを下の内容で作って・・・

[Unit]
Description=sdbuttond
After=syslog.target

[Service]
Type=simple
WorkingDirectory= /usr/local/bin
ExecStart=/usr/local/bin/sdbuttond
TimeoutStopSec=5
StandardOutput=null

[Install]
WantedBy = multi-user.target

お試し実行してみます。

$ sudo systemctl start sdbuttond

これでGPIO3に付けたタクトスイッチを数秒押すとシャットダウンする筈・・・試すと思惑通りシャットダウンしました。
ではもう一度立上げて恒久起動にします。

$ sudo systemctl enable sdbuttond

以上で一通りのインストールが終わったので・・・

写真の様なケースをThingiverseからダウンロードしてプリントし、壁に貼り付けていますが、本当に常時稼働させる様になったら防火対策のため金属製のケースに入れたいと思います。

RTK基準局を設置

Ublox ZED-F9P受信機を入手したので前から気になっていたRTKをやってみます。
最終的には庭で自動運転車を走らせて芝生を自動的に刈り込ませるのが目標です。

RTK

RTKというのはReal time kinematicの略でGPS(GNSS)衛星からの信号を高精度に解析してセンチメートル単位の測位を可能にする技術です。
※GNSSは測位システム全般を指す言葉でその内の一つがGPSですが、ここでは全てGPSと呼ぶ事にします。

センチメートル級測位というと日本の衛星「みちびき」のCLAS等もありますが、みちびきはまだ7機の完全体制になっていないし、精度的にもRTKの方が良い(らしい)のです。

RTKではGPS受信機を2つ使います。一方はアンテナの位置が既知である基準局で、衛星からの電波を受けて、その誤差を補正データとして出力します。もう一方は実際に測定する側(今回だと自動運転車、以下ROVERと呼びます)の受信機で、自分が受信した信号を基準局のデータで補正して自己位置を推定します。

GPSの誤差は近い距離内にある受信機間だとほぼ同じになるので基準局が近くにあるとROVERの位置が精度良く測定できる事になります。

基準局は必ずしも自分で用意する必要はなく、こんなところや、こんなところを見ると日本各地に基準データーを公開して頂けているサイトがあり、近い場所にあればそちらを利用するのが手っ取り早いです。
でも折角なので今回は自宅に基準局を設置して庭で測位してみようと思います。

受信機

入手した受信機はジオセンス社のF9PX1という機種で、Ublox社のZED-F9Pモジュールを搭載した基板です。
基板のままだと不安なので写真のケースを3Dプリントしました。
このケースの3DデータはThingiverseにアップしました

アンテナ

アンテナもUblox社製のANN-MB-00です。
基準局のアンテナは一旦設置したらあまり場所を動かしたくありません。cm単位で測位するための基準点なので1cm足りとも動かしたくないのです。 なので有り合わせの鉄板とアングルを溶接してアンテナ基台を作り、屋根に固定しました。
ここは屋根の一番高い所ではないので空を遮ってしまう部分が結構あります。本当はもっと高い位置に取り付けたいのですが、まずはこれでやってみます。

基準局のアンテナ位置を調べる。

基準局はアンテナの位置(座標)が正確に分かっている必要があります。
座標を知るには色々と方法がある様ですが、一番現実的な方法として暫く受信したデーターをファイルに書き出し、これを国土地理院の電子基準点のデーターから補正する方式でやってみます。
電子基準点のデーターは無料だとリアルタイムには提供されず、一時間毎に更新されるデーターをダウンロードする事になります。よって受信データーも一旦ファイルに落としておき、後付けで解析するのです。

手順としては以下の様に実施しました。
・ZED-F9P受信機を設定する。
・暫くの間データーを受信し、結果をファイルに落とす。
電子基準点のサイトから補正データーをダウンロードする。
rtklibに含まれる後付け解析ツールrtkpostを使って測位結果を算出する。
・測位結果はある程度ばらつきがあるので、その平均値を基準局の座標とする。

ZED-F9P受信機の設定

最初にZED-F9Pを設定します。
参考にしたのは下記書籍及びサイトです・・・

・トラ技2019年10月号 F9Pの設定詳細・RTKLIB・専用基準局製作
ZED-F9Pの設定方法
高精度衛星測位 RTK-GNSSチュートリアル

u-center(u-bloxの設定ツール)を開き、まずは上記資料の中で今回の座標特定に必要な内容だけを変更しました。

デフォルト設定値から変更した内容は・・・
・BaudRateを230400に設定
・受信衛星の選択画面(Viewメニューの「Generation 9 Advenced Configuration View」)を開いたが特に変更する箇所が見当たらなかったのでデフォルトのまま。
・ViewメニューのMessage Viewを開く。
・UBX-CFG-NAV5のMin SV Elevationをとりあえず15°程度に設定。
・UBX-CFG-RXMの中でRAWX,SFRBXを出力。
・NMEAではGxGGA,GxRMC,GxGSVを残してあとは停止する。
・UBX-CFG-NMEA内で、「High precision mode」にチェックを入れる。
・現段階ではRTCM出力は不要。
・変更を書込む。

なおデーターの更新レートを標準の1秒間隔から0.2秒間隔に変更できる様な事が色々なサイトに書いてありますが、私の所では0.2秒間隔だと受信中にRAWXデータが止まってしまうという現象が発生しました。色々試すと約0.7秒より長くすると安定したので、今回は1秒間隔(デフォルト通り)で使用しました。
(当面の用途ではRAWXはアンテナ座標を調べるとき以外は出力しなくて良いので大きな問題はない筈です)。

RTK-LIB

RTKを弄るにはrtklibをインストールしておくのが定番です。
私の環境ではrtklibのサイトを開くとブラウザから「この接続ではプライバシーが保護されません」というメッセージが出ますが、気にせず先に進みます。
そしてWindows版の最新2.4.3b34(ベータ版ですが)をダウンロードしてzipを解凍します(特にインストーラー等はなく解凍するだけ)。

まずはRTK-Naviで受信してみる。

その前にF9P基板とPCをUSBケーブルで接続し、デバイスマネージャーでCOM番号を調べておきます。

そしてRTK-LIBを解凍した階層下のbinディレクトリにある、rtknavi.exeを実行するとこんな画面が開きます。

右上の「I」というボタンを押すと次のダイアログが開きます(「I」は入力設定用ボタン)。

(1)Roverにチェックを入れ、TypeはSerialに設定してCmd列の「…」ボタンを押すと下のダイアログが出るので、PortのところにCOM番号、Bitrateのところに先程設定した230400bpsをセットして「OK」を押します。

そしてFormat列をu-blox UBXに設定してOKを押すとメイン画面に戻ります。

メイン画面の下の方の「Options…」を押すと次のダイアログが開くので、GPS,GLONASS,GAlileo,QZSSにチェックをいれて「OK」をクリック。

この時点で試しに受信してみましょう。
メイン画面左下の「▶Start」を押すと受信データがグラフで表示されます。

こんな感じで受信出来ていたら「■Stop」を押して一旦止めます。

受信ログを取得する。

ではログを取得する準備をします。
メイン画面右上の「L」を押してログ設定のダイアログを開きます。
(6)Roverにチェックを入れ、TypeにFileを設定し、LogFilePathsに適当なファイル名を設定します。
(ログファイル名には日付や時刻を含めておくと後で分かりやすいです。拡張子は.ubxにしておきます。)。

OKを押してMAIN画面で「▶Start」を押すと受信が始まるので、この状態でしばらく放置します(私は半日程置きました。長い方が良い筈ですが、どれくらいが適当かは不明。なお最初は短い時間で一度試してからが良いと思います。)。

取ったデータを解析する

データを解析するには上で落としたログをRINEX形式のファイルに変換します。
これにはRTKLIBに付属のRTKCONV.exeを実行します。
先頭の「RTCM,RCV RAW or RINEX OBX ?」に先程落としたログファイル名を指定すると出力ファイル名は自動的に設定されます。

「Options…」を押して出力形式が「RINEX Ver3.03」になっている事を確認します(違っていたら設定する)。

「OK」でMAIN画面に戻って「▶Convert」を押すと変換が始まり、XXX.obs(これがRINEX形式のファイル)が出来ていればOKです。

電子基準点からデータを取る。

受信したデータを解析する為に電子基準点の補正データを取得します。
まず下記にアクセスして・・・
https://terras.gsi.go.jp/
「観測データ取得」をクリック。なにやら「同意するか?」と聞かれたら「同意」をクリック・・

するとこんな地図が現れます。
各地の電子基準点で埋め尽くされていますね。。。

地図を拡大して最も近い基準点を選択し・・・

「ダウンロード」をクリック・・・

下の様に開始日時、終了日時には上記受信ログを落とした時間帯を含む範囲を指定します。
そして衛星はGRJE、RINEXverは3.02を指定。
「任意時間のデータダウンロード」をクリック。

するとこんな画面が開くので、「観測ファイル」、「衛星軌道情報ファイル」それぞれダウンロードします。

これでxxxx.o.gz , xxxx.tar.gzの2つのファイルがダウンロード出来ている筈です。
これらを解凍してxxxx.n,xxxx,g,xxxx,q,xxxx.l等に戻します。
(*.gzやtar.gzはUNIXでは一般的な圧縮/アーカイブ形式です。解凍方法が分からない場合は検索すると沢山出てきます。なおWindowsでも10あたりからtarコマンドが入っている様です。)
なお最近発見したのですが、xxxx.o.gzは解凍しなくても、そのまま指定すればRTKPOSTが読んで貰える様です。
またxxxx.tar.gzをそのまま指定するとエラーは出るものの解凍だけしてくれる様です。
 なので一旦エラー覚悟で実行して解凍されたファイルを改めて指定すればtarコマンドを実行せずに処理できます(今イチ良く分からん動作ですが)。

※素のままのファイル名だと後で分かりにくいので時刻範囲が分かるファイル名に変更しておいた方が良いと思います。

RTKPOSTで解析する。

以上により一通りのデータが揃ったので解析します。これにより自分のアンテナ位置の正確な位置(座標)を得るのです。

ではRTKLIBに付属のrtkpost.exeを実行すると下記の画面が開きます・・・


下の方の「Options…」ボタンを押して下記ダイアログを開き、Setting1タグにて・・・
・Positioning Mode をKinematicに。
・Filter Typeは一番厳密そうなCombinedを選び・・・。
・Elevation Mask(°) を30°程度に設定し(この辺りは適当)・・・。
・GPS,GLONASS,Galileo,QZSSにチェックを入れます。


PositionsタブのBaseStationをRINEX Header Positionに設定します。
その他にも細かなパラメーターが色々あって何がベストか分からないのもありますが、このあたりでOKを押してMAIN画面に戻ります。

後は処理するファイルを下記の様に設定していきます。
・RINEX OBS: Rover欄にはRTKNaviでダウンロードしてRTKConvで変換したRINEXファイル(XXX.obs)を指定。
・RINEX OBS: Base Stationには電子基準点からダウンロードして解凍したXXX.oファイルを指定。
・RINEX NAV/CLK,SP3,FCB,IONEX,SBS/EMS or RTCM欄にはXXX.n , XXX.g , XXX.l , XXX.qを指定。
・そして一番下の欄には出力ファイル名が自動的に入っているので・・・
「▶Execute」を押すと解析が始まります。

データー期間が長いと結構時間を要します。
終わったらPlotボタンを押すとこんな感じで分布が見えるはずです。

緑の点がRTKがFixしている(Cm級測位が出来ている)箇所で、黄色の点はFixしておらず精度が悪い点です。

取れたデータからアンテナ座標を求める。

アンテナ座標を求めるにはFixしているデーターだけ使いたいのでxxx.posファイルを以下の様にちょいといじります。

まずxxx.posファイルをテキストエディタで開くと下の様になっています。
この中でQと表示された列が1である行はFIXしたポイントで、その他の2や5になっている個所は精度が悪いのポイントなので、1の行を残して取り除きます。

これはテキストエディタで作業しても良いですが、面倒なのでこのページ末に記載したrubyスクリプトで処理しました。

Q=1の行以外を消してプロットし直すと次の様になりました。


同じスクリプトに-cオプションを指定して実行するとCSVファイルが出ます。
これをExcel等の表計算ソフトで開き、latitude,lognitude,height列を全部平均した座標をアンテナの位置としました(実はExcelは値段が高く持っていないのでLibreOfficeで実行した・・・)。
ついでに標準偏差を出してみるとLatitude≒9.2E-8, Lognitude≒1.67E-7, Hight≒35.07cmとなりました。 3σをmmになおすと30.9mm, 47.0mm, 105.2mmなので、まあセンチメートル単位で測位出来ていると思います。

そして・・・

以上でアンテナ座標を決める事が出来たので引き続き以下の作業を実施していきますが、長くなったので続きは後日投稿します。

・RaspberrypiでF9P受信器に接続してRTCM3データを取得し、同時にNTRIPcasterを実行して自宅内に配信。
・もう一つのF9P受信機をPixhawkに接続してRTK測位。
・ローバーを作成して庭で走らせる。

データー処理スクリプト

#!/usr/bin/env ruby
# coding: utf-8
#
# 2025.12.07 by https://www.hoihoido.com (konchi@hoihoido.com)
#
# rtkpost.exeが吐き出す*.posファイルからFIXしている行を取り出す。
# ※FIXしたらQ列(左から5ブロック目)が1になる。
#
# 引数:
# -c CSV出力(ヘッダなし)
# -q num Q列がnumで示す値である行だけ抜き出す。
# ※Q列はFIXやFLOAT等の状態を示す。1がデフォルトでFIX状態。
#

require 'optparse'

options = {}
opt = OptionParser.new
opt.on("-c", "--CSV", "CSV output") { |v| options[:CSV] = v }
opt.on("-q VAL", "--Q", Integer, "Q num (1=FIX:default)") { |v| options[:Q] = v }

opt.parse!(ARGV)

if ( options[:Q]) then
qval=options[:Q].to_s
else
qval="1"
end

n=0
while (l=gets()) do
if (options[:CSV] and l =~ /^% +GPST +/) then
title=l.split
print "DATA,"
print title[1..-1].join(','),"\n"
end

if l =~ /^\d{4}\/\d{2}\/\d{2} +\S+ +\S+ +\S+ +\S+ +(\d) / then
if $1 == qval then
if ( options[:CSV]) then
l.gsub!(/ +/,",")
end
puts l
n+=1
end
else
if (! options[:CSV]) then
puts l
end
end

end

print(",AVE,")
print("=average(C2:C",n+1,"),")
print("=average(D2:D",n+1,"),")
print("=average(E2:E",n+1,")\n")
print(",σ,")
print("=stdev(C2:C",n+1,"),")
print("=stdev(D2:D",n+1,"),")
print("=stdev(E2:E",n+1,")\n")
print(",3σ,")
print("=3*C",n+3,",")
print("=3*D",n+3,",")
print("=3*E",n+3,"\n")
print(",3σ[mm],")
print("=40000000/360*C",n+4,"*1000,")
print("=40000000/360*D",n+4,"*1000*cos(C",n+2,"/180*pi()),")
print("=E",n+4,"*1000\n")