GPS etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
GPS etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

12 Mayıs 2016 Perşembe

National Maritime Electronics Association - NMEA

NMEA Formatı
Denizcilikte kullanılan bir çok cihaz NMEA 0183 formatında veri gönderir.

Bazı mesajlar NMEA dokümanında tanımlıdır, bazı cihazlarsa kendi özelleştirilmiş mesajlarını gönderirler.

NMEA Dokümanı Mesaj Alanları
Mesaj alanları için bazı karakterler kullanılıyor. 

Table 3 Character Symbol Table 
Bunları listeliyor. Noktalı virgül ile ayrılıyorsa A veya B olabilir demek
a: Alphabet character variable A through Z or a through z. Alfabe karakteri, c yani Valid character kümesinden küçüktir. Rakam ve bazı işaretleri içermez
c : Valid character;Calculating
h : Hours;HEX Number. Yani Hours veya HEX olaiblir.
m : Minutes;message
s : Seconds;Six bit numer
x : Numeric character variable

Table 6 Field Type Summary
aa : İki tane alfabe karakteri
c--c : Değişken uzunlukta string. Bazen string'in uzunluğu belirtiliyor.
hhmmss.ss : Time içindir. hhmmss alanı sabittir. Noktadan gelen ss alanı değişken sayıda basamaklıdır
x.x : Değişken uzunlukta integer veya floating sayı içindir. Başında 0 olabilir/olmayabilir

Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>net.sf.marineapi</groupId>
  <artifactId>marineapi<artifactId>
  <version>0.11.0</version>
</dependency>
Örnek - Mesaj Parse Etme
Şöyle yaparız
import net.sf.marineapi.nmea.parser.SentenceFactory;
import net.sf.marineapi.nmea.sentence.GSASentence;

String nmea = "$GPGSA,A,3,03,05,07,08,10,15,18,19,21,28,,,1.4,0.9,1.1*3A";
SentenceFactory sf = SentenceFactory.getInstance();
GSASentence gsa = (GSASentence) sf.createParser(nmea);
Örnek - Mesajı String'e Çevirme
Şöyle yaparız
import net.sf.marineapi.nmea.parser.SentenceFactory;
import net.sf.marineapi.nmea.sentence.MWVSentence;
import net.sf.marineapi.nmea.sentence.TalkerId;
import net.sf.marineapi.nmea.util.DataStatus;
import net.sf.marineapi.nmea.util.Units;

// Create a fresh MWV parser
SentenceFactory sf = SentenceFactory.getInstance();
MWVSentence mwv = (MWVSentence) sf.createParser(TalkerId.II, "MWV");
// should output "$IIMWV,,,,,V*36"
System.out.println(mwv.toSentence());
// Be sure to set all needed values correctly. For instance, in this
// example setAngle() and setTrue() have mutual dependency. Likewise,
// pay attention to set units correctly.
mwv.setAngle(43.7);
mwv.setTrue(true);
mwv.setSpeed(4.54);
mwv.setSpeedUnit(Units.METER);
mwv.setStatus(DataStatus.ACTIVE);
// should output "$IIMWV,043.7,T,4.5,M,A*39"
System.out.println(mwv.toSentence());
Örnek - SentenceReader + SentenceListener
Şöyle yaparız
import net.sf.marineapi.nmea.event.SentenceEvent;
import net.sf.marineapi.nmea.event.SentenceListener;
import net.sf.marineapi.nmea.io.SentenceReader;
import net.sf.marineapi.nmea.sentence.GGASentence;
import net.sf.marineapi.nmea.sentence.SentenceId;

public class SentenceListenerExample implements SentenceListener {

  @Override
  public void readingPaused() {...}
  @Override
  public void readingStarted() {...}
  @Override
  public void readingStopped() {...}
  @Override
  public void sentenceRead(SentenceEvent event) {
    // Safe to cast as we are registered only for GGA updates. Could
    // also cast to PositionSentence if interested only in position data.
    // When receiving all sentences without filtering, you should check the
    // sentence type before casting (e.g. with Sentence.getSentenceId()).
    GGASentence s = (GGASentence) event.getSentence();

    // Do something with sentence data..
    System.out.println(s.getPosition());
  }
}

// create sentence reader and provide input stream
InputStream stream = new FileInputStream(file);
SentenceReader reader = new SentenceReader(stream);

// register self as a listener for GGA sentences
reader.addSentenceListener(new SentenceListenerExample (), SentenceId.GGA);
reader.start();
Örnek 
Şöyle yaparız
class GGAListener extends AbstractSentenceListener<GGASentence> {
@Override public void sentenceRead(GGASentence gga) { Position pos = gga.getPosition(); // .. your code } } File file = new File("/var/log/nmea.log"); SentenceReader reader = new SentenceReader(new FileInputStream(file)); reader.addSentenceListener(new GGAListener()); reader.start();

1. TalkerID Alanı
Cümleler $ işareti ile başlar. Daha sonra hangi cihazdan geldiğini belirtmek için 2 harflik bir alan gelir. Bu 2 harfe TalkerID de deniliyor. Mesela  GPS alıcısından geldiğini belirtmek için GP harfi eklenir. 

2. SentenceID Alanı
Sonraki 3  harf ise cümlenin amacını belirtir. Buna da SentenceID deniliyor. Bazı örnekler şöyle
$GPVTG : Velocity
$GPGLL : Position
$GPZDA : Date Time
3. Veri Alanları
Alanlar virgül ayracı ile ayrılır. Her mesajına göre değişken sayıda olabilir.

4. Checksum Alanı
Mesajın sonundaki "*" karakterinden sonra gelen sayıdır. Açıklaması şöyle
The final part is an optional two-digit checksum - optional, but all good equipment will include this to help safe-guard the data in the sentence. The checksum is preceded by the ‘*’ character and is calculated by taking the 8-bit exclusive-OR of all characters in the sentence, including ‘,’ delimiters, between but not including the ‘$’ / ’!’ and ‘*’ delimiters.
National Maritime Electronics Association - NMEA ve Hızlı Arayüzler
NMEA çok yavaş bir mesajlaşma protokolü olduğu için hızlı arayüzler gerektiren cihazlarda kullanmak için uygun değil. Örneğin bir elektro-optik sistemin NMEA kullanması beklenemez.


GPS Mesajları
GPS Mesajları yazısına taşıdım


GN Mesajları
Bazı mesajlar şöyle
GNGGA
GNGSV
GNGST
GNGSA
Wind Instrument Mesajlar
Weather Instrument Mesajları yazısına taşıdım

Seyir Radarı (Navigation Radar) Mesajlar
Seyir Radarı Mesajları yazısına taşıdım

Echo Sounder (İskandil) Mesajlar
Echo Sounder Mesajları yazısına taşıdım

Magnetic Compass (Pusula)
Magnetic Compass Mesajları yazısına taşıdım

Speed Log (Parakete)
SpeedLog Mesajları yazısına taşıdım

GyroCompass
GyroCompass Mesajları yazısına taşıdım

Navtex
Navtex Mesajları yazısına taşıdım

5 Şubat 2016 Cuma

WGS84

Not : GPS sisteminin alternatifi olarak Rus GLONASS sistemi mevcuttur. Ayrıca Avrupa Birliği Galileo sistemi üzerinde çalışmaktadır.

WGS84 Nedir ?
WGS84 (World Geodetic System) Küresel Konumlama Sistemi (GPS) kullandığı koordinat sistemidir. 2004 senesinde, bu sistem tekrar gözden geçirildi. Artık sadece dünyamız için değil güneş sistemindeki diğer gezegenler için de koordinat sistemleri geliştiriliyor. Örneğin Mars gezegeni için Mars 2000 mevcut.

WGS84 koordinat sisteminin bileşenlerini gösteren bir şekli buradan aldım.



Burada dikkat edilmesi gereken nokta, koordinat sistemindeki (X,Y,Z eksenleri) dünyanın ağırlık merkezinde birleşiyorlar. WGS 84'ten önce WGS 60, WGS 66, WGS 72 sistemleri vardı.


Koordinat Sistemi ve Projeksiyon Arasındaki Fark Nedir ?
Koordinat sistemi, dünyadaki herhangi bir noktayı enlem ve boylamı olarak bildirir. Projeksiyon ise dünyadaki kara, deniz, göl gibi şekillerin iki boyutlu harita üzerine çizilmesidir. Örneğin WGS84 sistemi, farklı farklı projeksiyonlar kullanılarak kağıda/ekran çizilebilirler.

proj4 uygulamasının desteklediği elipsoidler
proj -le ile görülebilir.


Buradaki örnekte proj4 kullanılarak iki projeksiyon sistemi arasında çevrim gösteriliyor. Kullanılan metod isimleri. pj_init_plus ve pj_transform .



WGS84 ve Ellipsoid
WGS84 ile dünyanın şekli ellipsoid olarak kabul edilir. Dünyanın gerçek şekline ise geoid denilir. Aşağıdaki şekilde dünyanın gerçek şekli ile ellipsoid arasında farklılıklar olduğu görülüyor.

Datum Nedir?
Geoid datum defines the size and shape of the world. Geodetic datums also define the origin and orientation of the coordinate system to map the earth. Modern geodetic datums describe the size, shapei orientation, gravity field and angular velocity of the earth.

WGS84 ile kullanılan ellipsoid dışında başka ellipsoid tanımlamaları da yapılmış.

Tabloda kutupsal eksenin ekvatordaki eksenden dünyanın basıklığı sebebiyle daha kısa olduğu görülebiliyor. 

Geodetic Height (Jeodezik yükseklik)
Noktanın elipsoidden yüksekliği. Elipsoid ile nokta arasında dik bir çizgi (orthogonal - çekül doğrultusunda çizgi) çekilerek bulunur.  Aşağıdaki şekilde "h" ile belirtiliyor.


Geoid ve ellipsoid arasındaki farklılık, özellikle irtifanın bulunmasında sıkıntılara yol açıyor. Örneğin buradaki soruda Flori'danın ortalama yüksekliğinin deniz seviyesinden 30-40 metre yukarıda olduğu, dolayısıyla deniz kıyısında duran bir kişinin 0 yerine daha farklı bir yükseklik göreceğinden bahsedilmiş.

Ellipsoid yüksekliği, deniz seviyesi yüksekliğine çevirmek için aşağıdaki basit algoritmanın kullanıldığını gördüm. Bilinear interpolation ile ilgili buraya bakılabilir.

NWHeight = geoidHeight [index] ;
NEHeight  = geoidHeight [index+1] ;
index = //recalculate index
SWHeight = geoidHeight [index] ;
SEHeight  = geoidHeight [index+1] ;
//Do bi-linear interpolation to compute elevation difference
deltaX = //compute
deltaY = //compute

UpperY =  NWHeight + deltaX * (NEHeight   - NWHeight);
LowerY =  SWHeight + deltaX * (SEHeight   - SWHeight);
DeltaHeight = LowerY +  deltaY* (UpperY- LowerY);

WGS84 ve Flattening
semi-minor axis : Merkezden kutupa doğru giden çizgi. Küçük eksen olarak ta kullanılabiliyor.
semi-major axis : Merkezden ekvatora doğru giden çizgi.Büyük eksen olarak ta kullanılabiliyor.

Flattening WGS-84 için 1 - (semi-minor axis)/(semi-major axis) anlamına geliyor. Bu değer 0'a ne kadar yakınsa şekilin tam yuvarlağa o kadar yakın olması anlamına geliyor. Yani bir nevi basıklık ölçüsü.



WGS84 ve Meridyenler yani Boylam (Longitude)
WGS84'te Baş Meridyen (Prime Meridian) Greenwich'ten değil ona çok yakın olan bir noktadan geçiyor kabul ediliyor. Başlangıç Meridyeni gösteren bir şekli buradan aldım.


Ekvator
WGS-84 ekvatorun uzunluğunu 40,075.016686 kilometre olarak sabitlemiş durumda. Ekvatorda iki boylam arasındaki mesafe  40,000 / 360 =  yaklaşık 110 km. İki enlem arasındaki mesafe de aynı.

Ekvatordan uzaklaştıkça iki boylam arasındaki mesafe azalıyor. Buradaki soruya verilen cevapta mesafenin azaldığı görülebilir. Yanlız 42. enlemde neden aşağıdaki formul kullanıldı bilmiyorum.

cos(90-42) * 110 = 74 km

Başlangıç Meridyenindeki saate Greenwich Meridian Time (GMT) denilir.

Aşağıdaki resmi buradan aldım ve aradaki farkı gösteriyor. Başlangıç boylamının nerede olduğunun hesaplanması görevi International Earth Rotation and Reference Systems Service (IERS) kuruluşunun görevi ve yukarıdaki şekilde de bu durum görülebiliyor.



GPS ile konum bulma
Burada GPS ile konum bulma işlemi için en az 3 uydudan sinyal alınması gerektiği görülebiliyor.

Android ve GPS
Android ile GPS'i kullanarak konum değişiminden haberdar olmak için LocationListener arayüzünü gerçekleştirmek ve onLocationChanged (Location location) metodunu kullanmak gerekiyor.

İki Nokta Arasında En Kısa Mesafeyi Hesaplama
Yaklaşık Hesaplama
Konuyu Konum Hesaplama Formülleri başlıklı yazıya taşıdım.

Tam Olarak Hesaplama 
Konuyu Konum Hesaplama Formülleri başlıklı yazıya taşıdım.

GPS ve DM Formatı
Degree Minute Formatı şöyle olabiliyor. DDDMM.MMMM . Yani Degree Minutes ve saniye yerine küsuratlı dakikalar. Böyle bir formatı sayıy çevirmek için aşağıdak formül kullanılabilir.

GPS ve DMS Formatı

DMS (Degree Minutes Seconds) formatı GPS koordinatının Derece/Dakika/Saniye cinsinden gösterilmesi anlamına geliyor. Bazı hava kuvvetleri haritalarında DMS formatında gösterim kullanılabiliyor. DMS formatını GPS cihazının gösterdiği gibi küsuratlı bir sayıya çevirmek çok kolay.

1 derece   = 60' dakika - Derece aslında saat gibi düşünülebilir.
1 derece   = 3600'' saniye (60 dakika * 60 saniye)
90 derece = 5400' dakika

Dolayısıyla bu kodu kullanabiliyoruz.

Bir başka örnekte ise DMS gösteriminde 47°02'24''S, 73°28'48''W olan bir konum, GPS gösterimine aşağıdaki gibi çevirilir

enlem   = - (47 + 2/60 + 24/3600 ) =-47.04
boylam = - (73 + 28/60 + 48/3600)=-73.48


GPS ve NMEA Formatı
NMEA yazısına taşıdım.

NTP (Network Time Protocol) ve GPS
GPS'in bir diğer az bilinen faydası ise sistemler arasındaki saati ayarlamaya yarayan NTP protokolüne refererans saaat olarak kullanılabilmesidir. Aşağıda resimi buradan aldım ve bu durumu özetliyor.


İstemciler üzerinde ntpd kullanılması ile tüm sistemleri saati tutarlı hale geliyor. ntpd ve ntpdate komutlarını güzelce anlatan bir yazı için burayı okuyabilirsiniz.

ntpdate komutu ile bilgisayarın açılışında saati ayarlamak için aşağıdaki komut kullanılabilir.

/usr/bin/ntpdate -b -s -u pool.ntp.org

GPS ve UTM
UTM (Universal Transverse Mercator) harita üzerinde iki boyutlu pozisyon bulma sistemi. Bir çok NATO ülkesi tarafından kullanılan Military Grid Reference System UTM'nin biraz daha geliştirilmiş hali.
Buradan aldığım bir şekilde koordinat dönüştürücü başlığı altında görülebiliyor.