/*
* This file is part of JGrasstools (http://www.jgrasstools.org)
* (C) HydroloGIS - www.hydrologis.com
*
* JGrasstools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jgrasstools.gears.io.nmea;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
/**
* Representation of a complete gps point info.
*
* <pre>
* RMC - NMEA has its own version of essential gps pvt (position, velocity, time) data. It is called RMC, The Recommended Minimum, which will look similar to:
* $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
* Where:
* RMC Recommended Minimum sentence C
* 123519 Fix taken at 12:35:19 UTC
* A Status A=active or V=Void.
* 4807.038,N Latitude 48 deg 07.038' N
* 01131.000,E Longitude 11 deg 31.000' E
* 022.4 Speed over the ground in knots
* 084.4 Track angle in degrees True
* 230394 Date - 23rd of March 1994
* 003.1,W Magnetic Variation
* *6A The checksum data, always begins with *
*
* GGA - essential fix data which provide 3D location and accuracy data.
* $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
* Where:
* GGA Global Positioning System Fix Data
* 123519 Fix taken at 12:35:19 UTC
* 4807.038,N Latitude 48 deg 07.038' N
* 01131.000,E Longitude 11 deg 31.000' E
* 1 Fix quality: 0 = invalid
* 1 = GPS fix (SPS)
* 2 = DGPS fix
* 3 = PPS fix
* 4 = Real Time Kinematic
* 5 = Float RTK
* 6 = estimated (dead reckoning) (2.3 feature)
* 7 = Manual input mode
* 8 = Simulation mode
* 08 Number of satellites being tracked
* 0.9 Horizontal dilution of position
* 545.4,M Altitude, Meters, above mean sea level
* 46.9,M Height of geoid (mean sea level) above WGS84
* ellipsoid
* (empty field) time in seconds since last DGPS update
* (empty field) DGPS station ID number
* *47 the checksum data, always begins with *
* </pre>
*
* @author Andrea Antonello (www.hydrologis.com)
*/
public class NmeaGpsPoint {
public static final String GPGGA = "$GPGGA";
public static final String GPRMC = "$GPRMC";
public final static String strLatitude = "northing";
public final static String strLongitude = "easting";
public final static String strLat = "lat";
public final static String strLon = "lon";
public final static String strSpeed = "speed";
public final static String strAltitude = "elev";
public final static String strQuality = "quality";
public final static String strSat = "satnum";
public final static String strHdop = "hdop";
public final static String strMsl = "dif_ell_msl";
public final static String strUtctime = "utctime";
public final static String strMag_var = "mag_var";
public final static String strAngle = "angle";
public final static String strValidity1 = "THIS POINT IS NOT VALID"; // "Validity";
public final static String strValidity2 = "";
public double latitude = -1.0;
public double longitude = -1.0;
public double speed = -1.0;
public double altitude = -1.0;
public double quality = -1.0;
public double sat = -1.0;
public double hdop = -1.0;
public double ellipsoidVsMsl = -1.0;
public DateTime utcDateTime = null;
public double mag_var = -1.0;
public double angle = -1.0;
public String altitudeUnit = "M";
public String ellipsoidVsMslUnit = "M";
public boolean isValid = false;
private static DateTimeFormatter nmeaDateFormatter = DateTimeFormat.forPattern("ddMMyyHHmmss.SSS"); //$NON-NLS-1$
private static DateTimeFormatter dateFormatter = DateTimeFormat.forPattern("ddMMyyHHmmss"); //$NON-NLS-1$
public NmeaGpsPoint() {
}
// public NmeaGpsPoint( double latitude, double longitude, double altitude ) {
// this.originalLatitude = latitude;
// this.originalLongitude = longitude;
// this.altitude = altitude;
// }
public NmeaGpsPoint( NmeaGpsPoint gpsPoint ) {
this.latitude = gpsPoint.latitude;
this.longitude = gpsPoint.longitude;
this.speed = gpsPoint.speed;
this.quality = gpsPoint.quality;
this.altitude = gpsPoint.altitude;
this.sat = gpsPoint.sat;
this.hdop = gpsPoint.hdop;
this.ellipsoidVsMsl = gpsPoint.ellipsoidVsMsl;
this.utcDateTime = gpsPoint.utcDateTime;
this.mag_var = gpsPoint.mag_var;
this.angle = gpsPoint.angle;
this.altitudeUnit = gpsPoint.altitudeUnit;
this.ellipsoidVsMslUnit = gpsPoint.ellipsoidVsMslUnit;
this.isValid = gpsPoint.isValid;
}
/**
* Creates a {@link NmeaGpsPoint} from the data strings.
*
* @param currentGPGGAsentence the GPGGA Nmea sentence. If null it is discarded.
* @param currentGPRMCsentence the GPRMC Nmea sentence. If null it is discarded.
*/
public NmeaGpsPoint( String currentGPGGAsentence, String currentGPRMCsentence ) {
// $GPGGA,173416.033,2500.0001,N,12159.9999,E,0,0,,80.9,M,16.1,M,,*7A
if (currentGPGGAsentence != null && currentGPGGAsentence.startsWith(GPGGA)) {
String[] dataBlocks = currentGPGGAsentence.split(","); //$NON-NLS-1$
if (dataBlocks[6].length() > 0)
quality = Double.parseDouble(dataBlocks[6]);
if (dataBlocks[7].length() > 0)
sat = Double.parseDouble(dataBlocks[7]);
if (dataBlocks[8].length() > 0)
hdop = Double.parseDouble(dataBlocks[8]);
if (dataBlocks[9].length() > 0) {
altitude = Double.parseDouble(dataBlocks[9]);
altitudeUnit = dataBlocks[10].toLowerCase();
}
if (dataBlocks[11].length() > 0) {
ellipsoidVsMsl = Double.parseDouble(dataBlocks[11]);
ellipsoidVsMslUnit = dataBlocks[12].toLowerCase();
}
}
if (currentGPRMCsentence != null && currentGPRMCsentence.startsWith(GPRMC)) {
String[] dataBlocks = currentGPRMCsentence.split(","); //$NON-NLS-1$
if (dataBlocks[1].length() > 0 && dataBlocks[9].length() > 0) {
utcDateTime = nmeaDateFormatter.parseDateTime(dataBlocks[9] + dataBlocks[1]);
}
if (dataBlocks[2].length() > 0 && dataBlocks[2].trim().equals("A")) //$NON-NLS-1$
isValid = true;
double latitude_in = 0.0;
if (dataBlocks[3].length() > 0)
latitude_in = Double.parseDouble(dataBlocks[3]);
double longitude_in = 0.0;
if (dataBlocks[5].length() > 0)
longitude_in = Double.parseDouble(dataBlocks[5]);
if (dataBlocks[10].length() > 0)
mag_var = Double.parseDouble(dataBlocks[10]);
double speed_in = 0.0;
if (dataBlocks[7].length() > 0)
speed_in = Double.parseDouble(dataBlocks[7]);
if (dataBlocks[8].length() > 0)
angle = Double.parseDouble(dataBlocks[8]);
double latitude_degrees = Math.floor(latitude_in / 100.0);
double latitude_minutes = latitude_in - latitude_degrees * 100.0;
double longitude_degrees = Math.floor(longitude_in / 100.0);
double longitude_minutes = longitude_in - longitude_degrees * 100;
latitude = latitude_degrees + (latitude_minutes / 60.0);
longitude = longitude_degrees + (longitude_minutes / 60.0);
if (dataBlocks[4].equals("S")) //$NON-NLS-1$
latitude = -latitude;
if (dataBlocks[6].equals("W")) //$NON-NLS-1$
longitude = -longitude;
speed = (int) (speed_in * 1.852);
}
}
@SuppressWarnings("nls")
public String toString() {
final String TAB = "/";
String retValue = "";
retValue = "GpsPoint ( " + "latitude = " + this.latitude + TAB + "longitude = " + this.longitude + TAB + "speed = "
+ this.speed + TAB + "altitude = " + this.altitude + TAB + "quality = " + this.quality + TAB + "sat = "
+ this.sat + TAB + "hdop = " + this.hdop + TAB + "msl = " + this.ellipsoidVsMsl + TAB + "utctime = "
+ this.utcDateTime.toString(dateFormatter) + TAB + "mag_var = " + this.mag_var + TAB + "angle = " + this.angle
+ TAB + " )";
return retValue;
}
}