|
Tech Note 03: NSBasicを使用してGPSデータ取得についての記述November 26, 2002 |
[英語版]
Contributed by Stan Armington.
自分の欲しい形でデータを収集できるので、PalmプラットホームはGPSデータ収集にはとても適しています。全てのコマーシャルGPSユニットは、特定のアプリケーションのニーズに適合する為にデザインされています - waypointへ操作するか、継続データ(tracks)を収集するか、不連続のポイントを収集するか、マップ上へプロットするなどです。私は自分の方法でデータを処理したいので(どのコマーシャルユニットも提供しない)、自分のシステムを書きました。
GPSで何ができるかの極め付けの例は、Robin Lovelock氏によって書かれたシステム www.gpss.co.ukをご覧下さい。このシステムは私に自信を持たせてくれ、自分のGPSデータ処理を開始する引き金になったものです。
私が見つけたPalmにアタッチできるユニットは、Rand McNally (RM)からので、一つのモデル(New ZealandのNavman製)はPalm 3用で、もう一つ(Magellan製)はPalm V用です。また、Handspringにアタッチできる韓国製のユニットに関する記事もみました。Magellan Palm Vユニットは試していませんが、Palm 3バージョンは組合せにかなりの時間が掛かります。したがって、テストおよび実際に私が使用しているのは、Garmin Etrex ($US119) で、ケーブル ($38) でPalmケーブル(hotsync cradle も使用できる)に接続しています。雄と雄のコネクターで接続しnullモデムが必要になります。これは複雑でやっかいなシステムになってしまいます。他のシステムでの試みの情報がありましたら感謝します。またこのサイトwww.celia.mehaffey.com/dale/pilotgps.htmもご覧になって下さい。
ほとんどのユニット(RMも含めて)はNMEA文を出力します。これらは「$」で始りキャリッジリターンで終る文字列です。これらの文に関する情報はwerple.net.au/~gnb/gps/nmea.htmlをご覧下さい。特に興味がある文は $GPGGA (Global Positioning System Fix Data) で、経度、緯度、高度、衛星の数、精度の見積もりを持っています。
Selective Availabilityが切られていても、GPSは誤差を出す傾向があることを忘れないで下さい。これはほぼ常に、少なくとも水平に10メートル、垂直に50メートルです。これはベース基地を使用した微分補正(differential correction)によって減少させることが出来ます。自分が集めたデータをどのように微分補正出来る形に変換するかは調査していません。正確な高度測定の為に、私はUS$3000のTrimble Geo Explorerを使用し、Trimbleソフトウエアを使用してデータを訂正しています。
また記録した位置の平均を出すことによって、精度を向上させることが出来ます。これは実際私がしていることですが、多少遅くなり、さらに複雑になります。私はバックグラウンドでデータを集めたいのですが(それによってGPSが平均を出している時に情報入力が可能になる)、Palm OSでは無理かもしれません。
NMEAデータは「度」+10進「分」の形式ですので、計算が必要になる時は10進「度」に変換しなくてはなりません。
NS Basic 問題:
1. データ取得
NSBasicを通してのシリアル入力は遅いです。文字を一つづつ集めようとしましたが、固まりを失いました。(serialreceiveファンクションのtimeoutを1秒以下にすることによって解決できるのかと思っているのですが?)最終的に以下のコードを書きました。動きます。幸いNMEA文は続けて来るので、一つ失っても大きな問題ではありません。全てのシリアル入力を取得することが重要な場合、どのように対処するかは私には分かりません。理想的にはバックグラウンドにおいてルーチンが動作して、データの取得と平均計算をしてくれることです。以下のルーチンはループの中にあり、ユーザがストップボタンを押すと終ります。NMEAデータは4800 (8-1-none)のボーレートで入ってきます。
err=serialreceive(Buffer,150,1) if err=0 then i=instr(1,Buffer,~$~,0) 'sentence start? j=instr(I+1,Buffer,&h0d,0) 'sentence end? if I>0 and j>0 then 'yes - then grab it line=mid(Buffer,I,j-I) term.text=line 'display the NMEA sentence if anydata=false then GPS_Status.text=~Receiving~ 'put up a flag saying we're finally receiving data anydata=true end if if left(Line,6)=~$GPGGA~ then showlocation(line) 'convert and save end if end if end if2. 自動オフ
George Henneは後継バージョンにてこれを処理すると言っていますが、現在では自動的にPalmを切る機能を外す事は出来ません。これをしないとユニットはシャットダウンし、データの取得を終らせます。(受けたものは保存します)私が見つけたこれを行う簡単な方法はAutooffプログラムを使用することです。これはAutooffを切ります。GPSが終了した時、Palm preferencesに戻りauto-off timeを1、2、3分のどれかにセットし直さなければなりません。Joe GrandがAutooffを提供しています。The Grand Design, http://www.mindspring.com/~jgrand
3. Checksum
NMEA 0183 Standard はオプションのchecksumを許容しています。checksumはアスタリスク文字 (*) で始り、最後のデータフィールドの後に置かれます。これは2文字のフィールドで、文の全ての文字バイトの排他的論理(XOR)によって得られるhex値と同じです。
これはNS Basicでは(すくなくとも単純な方法では)計算不可能です。回避として多くのエラーチェックとデータの確認が必要でした。George Henneはビット処理についても進めていると述べています。
4. UTM 変換
UTM座標をディスプレイできると、toeディスプレイをmap座標に関連させる事が簡単でしょう。残念ながら、Palm上でこの複雑な計算を行うと約5秒掛かります。以下はNSBasicコードです。
NS Basic routine to convert Latitude/Longitude to UTM "sub LLtoUTM(Lat as float, Long as float) ' results are global variables 'formula adapted from C code on url http://www.gpsy.com/gpsinfo/geotoutm/gantz/UTMConversions.cpp 'East Longitudes are positive, West longitudes are negative. 'North latitudes are positive, South latitudes are negative 'Lat and Long are in decimal degrees 'If input is in dddmm.mm then need to convert Dim LongOrigin as float Dim eccPrimeSquared as float Dim N as float Dim T as float Dim C as float Dim M as float Dim A as float Dim LatRad as float Dim LongRad as float Dim LongOriginRad as float Dim Longtemp as float Dim ZoneNumber as Integer Dim k0 as float Dim eradius as float Dim eccSquared as float Dim ECCcube as float k0 = 0.9996 eradius = 6378137 'WGS84 EquatorialRadius eccSquared = 0.00669438 'WGS84 eccentricitySquared ECCcube=pow(eccSquared,3) LongTemp = (Long+180)-int((Long+180)/360)*360-180 '-180.00 .. 179.9 LatRad = DegtoRadians(Lat) LongRad = DegtoRadians(LongTemp) ZoneNumber = int((LongTemp + 180)/6)+1 if (Lat >= 56.0) and (Lat < 64.0) and (LongTemp >= 3.0) and (LongTemp < 12.0 ) then ZoneNumber = 32 end if LongOrigin = (ZoneNumber - 1)*6 - 180 + 3 '+3 puts origin in middle of zone LongOriginRad = DegtoRadians(LongOrigin) UTMZone=ZoneNumber eccPrimeSquared = (eccSquared)/(1-eccSquared) N = eradius/sqrt(1-eccSquared*Pow(sin(LatRad),2)) T = pow(tan(LatRad),2) C = eccPrimeSquared*pow(cos(LatRad),2) A = cos(LatRad)*(LongRad-LongOriginRad) M = (1 - eccSquared/4 - 3*pow(eccSquared,2)/64 - 5*EccCube/256)*LatRad M=M - (3*eccSquared/8 + 3*pow(eccSquared,2)/32 + 45*EccCube/1024)*sin(2*LatRad) M=M + (15*pow(eccSquared,2)/256 + 45*EccCube/1024)*sin(4*LatRad) M=M - (35*pow(eccSquared,3)/3072)*sin(6*LatRad) M=eradius*M UTMEasting = A+(1-T+C)*pow(A,3)/6 UTMEasting=UTMEasting + (5-18*T+pow(T,2)+72*C-58*eccPrimeSquared)*pow(A,5)/120 UTMEasting=k0*N*UTMEasting+ 500000.0 UTMNorthing = M+N*tan(LatRad)*(pow(A,2)/2+(5-T+9*C+4*pow(C,2))*pow(A,4)/24) UTMNorthing = UTMNorthing + (61-58*T+pow(T,2)+600*C-330*eccPrimeSquared)*pow(A,6)/720 UTMNorthing = k0*UTMNorthing if Lat < 0 THEN UTMNorthing = UTMNorthing+10000000.0 '10000000 meter offset for southern hemisphere' end if end sub"
Revised 8 Sep 2000