mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 15:23:04 +00:00 
			
		
		
		
	Added NMEA 2.1 protocol for PVT dump.
This is an experimental release that only supports FILE dump operations. git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@235 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
		| @@ -66,10 +66,19 @@ gps_l1_ca_pvt_cc::gps_l1_ca_pvt_cc(unsigned int nchannels, gr_msg_queue_sptr que | ||||
|     d_dump_filename = dump_filename; | ||||
|     std::string dump_ls_pvt_filename; | ||||
|     dump_ls_pvt_filename=dump_filename; | ||||
|  | ||||
|     //initialize kml_printer | ||||
|     std::string kml_dump_filename; | ||||
|     kml_dump_filename = d_dump_filename; | ||||
|     kml_dump_filename.append(".kml"); | ||||
|     d_kml_dump.set_headers(kml_dump_filename); | ||||
|  | ||||
|     //initialize nmea_printer | ||||
|     std::string nmea_dump_filename; | ||||
|     nmea_dump_filename = d_dump_filename; | ||||
|     nmea_dump_filename.append(".nmea"); | ||||
|     d_nmea_printer=new Nmea_Printer(nmea_dump_filename); | ||||
|  | ||||
|     d_dump_filename.append("_raw.dat"); | ||||
|     dump_ls_pvt_filename.append("_ls_pvt.dat"); | ||||
|     d_averaging_depth = averaging_depth; | ||||
| @@ -117,6 +126,7 @@ gps_l1_ca_pvt_cc::~gps_l1_ca_pvt_cc() | ||||
|     d_kml_dump.close_file(); | ||||
|     delete d_ls_pvt; | ||||
|     delete rp; | ||||
|     delete d_nmea_printer; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -204,6 +214,8 @@ int gps_l1_ca_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_ite | ||||
| 				if (d_ls_pvt->get_PVT(gnss_pseudoranges_map,d_tx_time,d_flag_averaging) == true) | ||||
| 				{ | ||||
| 					d_kml_dump.print_position(d_ls_pvt, d_flag_averaging); | ||||
| 					d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging); | ||||
|  | ||||
| 					if (!b_rinex_header_writen) //  & we have utc data in nav message! | ||||
| 					{ | ||||
| 						rp->rinex_nav_header(rp->navFile, d_last_nav_msg); | ||||
|   | ||||
| @@ -38,6 +38,7 @@ | ||||
| #include <boost/thread/thread.hpp> | ||||
| #include "concurrent_queue.h" | ||||
| #include "gps_navigation_message.h" | ||||
| #include "nmea_printer.h" | ||||
| #include "kml_printer.h" | ||||
| #include "rinex_printer.h" | ||||
| #include "gps_l1_ca_ls_pvt.h" | ||||
| @@ -81,6 +82,8 @@ private: | ||||
|  | ||||
|   Kml_Printer d_kml_dump; | ||||
|  | ||||
|   Nmea_Printer *d_nmea_printer; | ||||
|  | ||||
|   concurrent_queue<Gps_Navigation_Message> *d_nav_queue; // Navigation ephemeris queue | ||||
|   Gps_Navigation_Message d_last_nav_msg;                 // Last navigation message | ||||
|  | ||||
|   | ||||
| @@ -188,7 +188,10 @@ arma::vec gps_l1_ca_ls_pvt::leastSquarePos(arma::mat satpos, arma::vec obs, arma | ||||
|                             //--- Correct satellite position (do to earth rotation) -------- | ||||
|  | ||||
|                             Rot_X = e_r_corr(traveltime, X.col(i)); //armadillo | ||||
|                             //--- Find the elevation angel of the satellite ---------------- | ||||
|                             //--- Find the elevation angle of the satellite ---------------- | ||||
|  | ||||
|                             topocent(&d_visible_satellites_Az[i],&d_visible_satellites_El[i],&d_visible_satellites_Distance[i],pos.subvec(0,2), Rot_X - pos.subvec(0,2)); | ||||
|  | ||||
|                             //[az(i), el(i), dist] = topocent(pos(1:3, :), Rot_X - pos(1:3, :)); | ||||
|  | ||||
|                         } | ||||
| @@ -221,11 +224,13 @@ arma::vec gps_l1_ca_ls_pvt::leastSquarePos(arma::mat satpos, arma::vec obs, arma | ||||
|     //-- compute the Dilution Of Precision values | ||||
| 		arma::mat Q; | ||||
| 		Q       = arma::inv(arma::htrans(A)*A); | ||||
| 		//std::cout<<Q<<std::endl; | ||||
|  | ||||
| 		d_GDOP  = sqrt(arma::trace(Q));                 // GDOP | ||||
| 		d_PDOP  = sqrt(Q(1,1) + Q(2,2) + Q(3,3));       // PDOP | ||||
| 		d_HDOP  = sqrt(Q(1,1) + Q(2,2));                // HDOP | ||||
| 		d_VDOP  = sqrt(Q(3,3));                         // VDOP | ||||
| 		d_TDOP  = sqrt(Q(4,4));                         // TDOP | ||||
| 		d_PDOP  = sqrt(Q(0,0) + Q(1,1) + Q(2,2));       // PDOP | ||||
| 		d_HDOP  = sqrt(Q(0,0) + Q(1,1));                // HDOP | ||||
| 		d_VDOP  = sqrt(Q(2,2));                         // VDOP | ||||
| 		d_TDOP  = sqrt(Q(3,3));                         // TDOP | ||||
|     }catch(std::exception e) | ||||
|     { | ||||
|     	d_GDOP  = -1; | ||||
| @@ -250,6 +255,8 @@ bool gps_l1_ca_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, | ||||
|     double GPS_corrected_time = 0; | ||||
|     double utc = 0; | ||||
|  | ||||
|     d_flag_averaging=flag_averaging; | ||||
|  | ||||
|     int valid_obs=0; //valid observations counter | ||||
|     for (int i=0; i<d_nchannels; i++) | ||||
|         { | ||||
| @@ -280,6 +287,8 @@ bool gps_l1_ca_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, | ||||
|                             DLOG(INFO) << "ECEF satellite SV ID=" << d_ephemeris[i].i_satellite_PRN <<" X=" << d_ephemeris[i].d_satpos_X | ||||
|                                     << " [m] Y=" << d_ephemeris[i].d_satpos_Y << " [m] Z=" << d_ephemeris[i].d_satpos_Z << " [m]" << std::endl; | ||||
|                             obs(i) = gnss_pseudoranges_iter->second.Pseudorange_m + d_ephemeris[i].d_satClkCorr*GPS_C_m_s; | ||||
|                             d_visible_satellites_IDs[valid_obs]=d_ephemeris[i].i_satellite_PRN; | ||||
|                             d_visible_satellites_CN0_dB[valid_obs]=gnss_pseudoranges_iter->second.CN0_dB_hz; | ||||
|                             valid_obs++; | ||||
|                         } | ||||
|                     else | ||||
| @@ -296,7 +305,11 @@ bool gps_l1_ca_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, | ||||
|                     obs(i) = 1; // to avoid algorithm problems (divide by zero) | ||||
|                 } | ||||
|         } | ||||
|  | ||||
|     d_valid_observations = valid_obs; | ||||
|  | ||||
|     DLOG(INFO) <<"PVT: valid observations="<<valid_obs<<std::endl; | ||||
|  | ||||
|     if (valid_obs>=4) | ||||
|         { | ||||
|             arma::vec mypos; | ||||
| @@ -471,59 +484,230 @@ void gps_l1_ca_ls_pvt::cart2geo(double X, double Y, double Z, int elipsoid_selec | ||||
|     d_height_m = h; | ||||
| } | ||||
|  | ||||
| //void gps_l1_ca_ls_pvt::topocent(traveltime, X_sat) | ||||
| //{ | ||||
| /* | ||||
| %function [Az, El, D] = topocent(X, dx) | ||||
| %TOPOCENT  Transformation of vector dx into topocentric coordinate | ||||
| %          system with origin at X. | ||||
| %          Both parameters are 3 by 1 vectors. | ||||
| % | ||||
| %[Az, El, D] = topocent(X, dx); | ||||
| % | ||||
| %   Inputs: | ||||
| %       X           - vector origin corrdinates (in ECEF system [X; Y; Z;]) | ||||
| %       dx          - vector ([dX; dY; dZ;]). | ||||
| % | ||||
| %   Outputs: | ||||
| %       D           - vector length. Units like units of the input | ||||
| %       Az          - azimuth from north positive clockwise, degrees | ||||
| %       El          - elevation angle, degrees | ||||
| void gps_l1_ca_ls_pvt::togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z) | ||||
| { | ||||
| 	//function [dphi, dlambda, h] = togeod(a, finv, X, Y, Z) | ||||
| 	//%TOGEOD   Subroutine to calculate geodetic coordinates latitude, longitude, | ||||
| 	//%         height given Cartesian coordinates X,Y,Z, and reference ellipsoid | ||||
| 	//%         values semi-major axis (a) and the inverse of flattening (finv). | ||||
| 	//% | ||||
| 	//%[dphi, dlambda, h] = togeod(a, finv, X, Y, Z); | ||||
| 	//% | ||||
| 	//%  The units of linear parameters X,Y,Z,a must all agree (m,km,mi,ft,..etc) | ||||
| 	//%  The output units of angular quantities will be in decimal degrees | ||||
| 	//%  (15.5 degrees not 15 deg 30 min). The output units of h will be the | ||||
| 	//%  same as the units of X,Y,Z,a. | ||||
| 	//% | ||||
| 	//%   Inputs: | ||||
| 	//%       a           - semi-major axis of the reference ellipsoid | ||||
| 	//%       finv        - inverse of flattening of the reference ellipsoid | ||||
| 	//%       X,Y,Z       - Cartesian coordinates | ||||
| 	//% | ||||
| 	//%   Outputs: | ||||
| 	//%       dphi        - latitude | ||||
| 	//%       dlambda     - longitude | ||||
| 	//%       h           - height above reference ellipsoid | ||||
| 	// | ||||
| 	//%  Copyright (C) 1987 C. Goad, Columbus, Ohio | ||||
| 	//%  Reprinted with permission of author, 1996 | ||||
| 	//%  Fortran code translated into MATLAB | ||||
| 	//%  Kai Borre 03-30-96 | ||||
| 	//% | ||||
| 	//% CVS record: | ||||
| 	//% $Id: togeod.m,v 1.1.1.1.2.4 2006/08/22 13:45:59 dpl Exp $ | ||||
| 	//%========================================================================== | ||||
| 	// | ||||
| 	*h       = 0; | ||||
| 	double tolsq = 1.e-10; | ||||
| 	int maxit=10; | ||||
| 	// compute radians-to-degree factor | ||||
| 	double rtd; | ||||
| 	rtd     = 180/GPS_PI; | ||||
|  | ||||
| 	// compute square of eccentricity | ||||
| 	double esq; | ||||
| 	if (finv < 1.0E-20) | ||||
| 	{ | ||||
| 		esq = 0; | ||||
| 	}else | ||||
| 	{ | ||||
| 		esq = (2 - 1/finv) / finv; | ||||
| 	} | ||||
|  | ||||
| 	double oneesq; | ||||
|  | ||||
| 	oneesq  = 1 - esq; | ||||
|  | ||||
| 	// first guess | ||||
| 	// P is distance from spin axis | ||||
| 	double P; | ||||
| 	P = sqrt(X*X+Y*Y); | ||||
| 	//direct calculation of longitude | ||||
| 	// | ||||
| 	if (P > 1.0E-20) | ||||
| 	{ | ||||
| 		*dlambda = atan2(Y,X) * rtd; | ||||
| 	}else | ||||
| 	{ | ||||
| 		*dlambda = 0; | ||||
| 	} | ||||
|  | ||||
| 	if (*dlambda < 0) | ||||
| 	{ | ||||
| 		*dlambda = *dlambda + 360.0; | ||||
| 	} | ||||
|  | ||||
| 	// r is distance from origin (0,0,0) | ||||
| 	double r; | ||||
| 	r = sqrt(P*P + Z*Z); | ||||
|  | ||||
| 	double sinphi; | ||||
|  | ||||
| 	if (r > 1.0E-20) | ||||
| 	{ | ||||
| 		sinphi = Z/r; | ||||
| 	} else | ||||
| 	{ | ||||
| 		sinphi = 0; | ||||
| 	} | ||||
|  | ||||
| 	*dphi = asin(sinphi); | ||||
|  | ||||
| 	// initial value of height  =  distance from origin minus | ||||
| 	// approximate distance from origin to surface of ellipsoid | ||||
| 	if (r < 1.0E-20) | ||||
| 	{ | ||||
| 		*h = 0; | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	*h = r - a*(1-sinphi*sinphi/finv); | ||||
|  | ||||
|  | ||||
| dtr = pi/180; | ||||
| 	// iterate | ||||
| 	double cosphi; | ||||
| 	double N_phi; | ||||
| 	double dP; | ||||
| 	double dZ; | ||||
| 	for (int i=0; i<maxit; i++) | ||||
| 	{ | ||||
| 		sinphi  = sin(*dphi); | ||||
| 		cosphi  = cos(*dphi); | ||||
|  | ||||
| [phi, lambda, h] = togeod(6378137, 298.257223563, X(1), X(2), X(3)); | ||||
| 		//     compute radius of curvature in prime vertical direction | ||||
| 		N_phi   = a/sqrt(1-esq*sinphi*sinphi); | ||||
|  | ||||
| cl  = cos(lambda * dtr); | ||||
| sl  = sin(lambda * dtr); | ||||
| cb  = cos(phi * dtr); | ||||
| sb  = sin(phi * dtr); | ||||
| 		//    compute residuals in P and Z | ||||
| 		dP      = P - (N_phi + (*h)) * cosphi; | ||||
| 		dZ      = Z - (N_phi*oneesq + (*h)) * sinphi; | ||||
| 		// | ||||
| 		//    update height and latitude | ||||
| 		*h       = *h + (sinphi*dZ + cosphi*dP); | ||||
| 		*dphi    = *dphi + (cosphi*dZ - sinphi*dP)/(N_phi + (*h)); | ||||
|  | ||||
| F   = [-sl -sb*cl cb*cl; | ||||
|         cl -sb*sl cb*sl; | ||||
|         0    cb   sb]; | ||||
| 		//     test for convergence | ||||
| 		if ((dP*dP + dZ*dZ) < tolsq) | ||||
| 		{ | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| local_vector = F' * dx; | ||||
| E   = local_vector(1); | ||||
| N   = local_vector(2); | ||||
| U   = local_vector(3); | ||||
| 		//    Not Converged--Warn user | ||||
| 		//    if (i == (maxit-1)) | ||||
| 		//        fprintf([' Problem in TOGEOD, did not converge in %2.0f',... | ||||
| 		//            ' iterations\n'], i); | ||||
| 		//    end | ||||
| 	} | ||||
| 	// | ||||
| 	*dphi = (*dphi) * rtd; | ||||
|  | ||||
| hor_dis = sqrt(E^2 + N^2); | ||||
| } | ||||
| void gps_l1_ca_ls_pvt::topocent(double *Az, double *El, double *D, arma::vec x, arma::vec x_sat) | ||||
| { | ||||
|  | ||||
| if hor_dis < 1.e-20 | ||||
|     Az = 0; | ||||
|     El = 90; | ||||
| else | ||||
|     Az = atan2(E, N)/dtr; | ||||
|     El = atan2(U, hor_dis)/dtr; | ||||
| end | ||||
| 	//%function [Az, El, D] = topocent(X, dx) | ||||
| 	//%TOPOCENT  Transformation of vector dx into topocentric coordinate | ||||
| 	//%          system with origin at X. | ||||
| 	//%          Both parameters are 3 by 1 vectors. | ||||
| 	//% | ||||
| 	//%[Az, El, D] = topocent(X, dx); | ||||
| 	//% | ||||
| 	//%   Inputs: | ||||
| 	//%       X           - vector origin corrdinates (in ECEF system [X; Y; Z;]) | ||||
| 	//%       dx          - vector ([dX; dY; dZ;]). | ||||
| 	//% | ||||
| 	//%   Outputs: | ||||
| 	//%       D           - vector length. Units like units of the input | ||||
| 	//%       Az          - azimuth from north positive clockwise, degrees | ||||
| 	//%       El          - elevation angle, degrees | ||||
|  | ||||
| if Az < 0 | ||||
|     Az = Az + 360; | ||||
| end | ||||
| 	double dtr; | ||||
| 	double lambda; | ||||
| 	double phi; | ||||
| 	double cl; | ||||
| 	double sl; | ||||
| 	double cb; | ||||
| 	double sb; | ||||
|  | ||||
| D   = sqrt(dx(1)^2 + dx(2)^2 + dx(3)^2); | ||||
| %%%%%%%%% end topocent.m %%%%%%%%% | ||||
|  */ | ||||
| //} | ||||
| 	double h; | ||||
|  | ||||
| 	dtr = GPS_PI/180.0; | ||||
|  | ||||
| 	//[phi, lambda, h] = togeod(6378137, 298.257223563, X(1), X(2), X(3)); | ||||
|  | ||||
| 	togeod(&phi, &lambda, &h,6378137.0, 298.257223563, x(0), x(1), x(2)); | ||||
|  | ||||
| 	cl  = cos(lambda * dtr); | ||||
| 	sl  = sin(lambda * dtr); | ||||
| 	cb  = cos(phi * dtr); | ||||
| 	sb  = sin(phi * dtr); | ||||
|  | ||||
| 	arma::mat F=arma::zeros(3,3); | ||||
|  | ||||
| 	F(0,0)=-sl; | ||||
| 	F(0,1)=-sb*cl; | ||||
| 	F(0,2)=cb*cl; | ||||
|  | ||||
| 	F(1,0)=cl; | ||||
| 	F(1,1)=-sb*sl; | ||||
| 	F(1,2)=cb*sl; | ||||
|  | ||||
| 	F(2,0)=0; | ||||
| 	F(2,1)=cb; | ||||
| 	F(2,2)=sb; | ||||
|  | ||||
| 	arma::vec local_vector; | ||||
|  | ||||
| 	local_vector = arma::htrans(F) * x_sat; | ||||
|  | ||||
| 	double E; | ||||
| 	double N; | ||||
| 	double U; | ||||
|  | ||||
| 	E   = local_vector(0); | ||||
| 	N   = local_vector(1); | ||||
| 	U   = local_vector(2); | ||||
|  | ||||
| 	double hor_dis; | ||||
|  | ||||
| 	hor_dis = sqrt(E*E + N*N); | ||||
|  | ||||
| 	if (hor_dis < 1.0E-20) | ||||
| 	{ | ||||
| 		*Az = 0; | ||||
| 		*El = 90; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		*Az = atan2(E, N)/dtr; | ||||
| 		*El = atan2(U, hor_dis)/dtr; | ||||
| 	} | ||||
|  | ||||
| 	if (*Az < 0) | ||||
| 	{ | ||||
| 		*Az = *Az + 360.0; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	*D   = sqrt(x_sat(0)*x_sat(0) + x_sat(1)*x_sat(1) + x_sat(2)*x_sat(2)); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -48,6 +48,8 @@ | ||||
|  | ||||
| #include "gnss_synchro.h" | ||||
|  | ||||
| #define PVT_MAX_CHANNELS 24 | ||||
|  | ||||
| /*! | ||||
|  * \brief This class implements a simple PVT Least Squares solution | ||||
|  */ | ||||
| @@ -56,9 +58,17 @@ class gps_l1_ca_ls_pvt | ||||
| private: | ||||
|     arma::vec leastSquarePos(arma::mat satpos, arma::vec obs, arma::mat w); | ||||
|     arma::vec e_r_corr(double traveltime, arma::vec X_sat); | ||||
|     //void topocent(); | ||||
|     void topocent(double *Az, double *El, double *D, arma::vec x, arma::vec x_sat); | ||||
|     void togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z); | ||||
| public: | ||||
|     int d_nchannels;      //! Number of available channels for positioning | ||||
|     int d_valid_observations; //! Number of valid pseudorrange observations (valid satellites) | ||||
|     int d_visible_satellites_IDs[PVT_MAX_CHANNELS]; //! Array with the IDs of the valid satellites | ||||
| 	double d_visible_satellites_El[PVT_MAX_CHANNELS]; //! Array with the LOS Elevation of the valid satellites | ||||
| 	double d_visible_satellites_Az[PVT_MAX_CHANNELS]; //! Array with the LOS Azimuth of the valid satellites | ||||
| 	double d_visible_satellites_Distance[PVT_MAX_CHANNELS]; //! Array with the LOS Distance of the valid satellites | ||||
| 	double d_visible_satellites_CN0_dB[PVT_MAX_CHANNELS]; //! Array with the IDs of the valid satellites | ||||
|  | ||||
|     Gps_Navigation_Message* d_ephemeris; | ||||
|     double d_GPS_current_time; | ||||
|     boost::posix_time::ptime d_position_UTC_time; | ||||
| @@ -92,6 +102,8 @@ public: | ||||
|     double d_TDOP; | ||||
|  | ||||
|     bool d_flag_dump_enabled; | ||||
|     bool d_flag_averaging; | ||||
|  | ||||
|     std::string d_dump_filename; | ||||
|     std::ofstream d_dump_file; | ||||
|  | ||||
|   | ||||
| @@ -3,3 +3,4 @@ project : build-dir ../../../../build ; | ||||
| obj rinex_printer : rinex_printer.cc ; | ||||
| obj gps_l1_ca_ls_pvt : gps_l1_ca_ls_pvt.cc ; | ||||
| obj kml_printer : kml_printer.cc ; | ||||
| obj nmea_printer : nmea_printer.cc ; | ||||
							
								
								
									
										617
									
								
								src/algorithms/PVT/libs/nmea_printer.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										617
									
								
								src/algorithms/PVT/libs/nmea_printer.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,617 @@ | ||||
| /*! | ||||
|  * \file kml_printer.cc | ||||
|  * \brief Implementation of a NMEA 2.1 printer for GNSS-SDR | ||||
|  * This class provides a implementation of a subset of the NMEA-0183 standard for interfacing | ||||
|  * marine electronic devices as defined by the National Marine Electronics Association (NMEA). | ||||
|  * See http://www.nmea.org/ for the NMEA 183 standard | ||||
|  * | ||||
|  * \author Javier Arribas, 2012. jarribas(at)cttc.es | ||||
|  * | ||||
|  * | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * Copyright (C) 2010-2012  (see AUTHORS file for a list of contributors) | ||||
|  * | ||||
|  * GNSS-SDR is a software defined Global Navigation | ||||
|  *          Satellite Systems receiver | ||||
|  * | ||||
|  * This file is part of GNSS-SDR. | ||||
|  * | ||||
|  * GNSS-SDR 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. | ||||
|  * | ||||
|  * GNSS-SDR 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 GNSS-SDR. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * ------------------------------------------------------------------------- | ||||
|  */ | ||||
|  | ||||
| #include <glog/log_severity.h> | ||||
| #include <glog/logging.h> | ||||
| #include <gflags/gflags.h> | ||||
| #include "boost/date_time/posix_time/posix_time.hpp" | ||||
| #include "GPS_L1_CA.h" | ||||
| #include "nmea_printer.h" | ||||
|  | ||||
| using google::LogMessage; | ||||
|  | ||||
| //DEFINE_string(NMEA_version, "2.1", "Specifies the NMEA version (2.1)"); | ||||
|  | ||||
| Nmea_Printer::Nmea_Printer(std::string filename) | ||||
| { | ||||
| 	nmea_filename=filename; | ||||
| 	nmea_file_descriptor.open(nmea_filename.c_str(), std::ios::out); | ||||
|     if (nmea_file_descriptor.is_open()) | ||||
|         { | ||||
|             DLOG(INFO) << "NMEA printer writing on " << nmea_filename.c_str(); | ||||
|         } | ||||
| } | ||||
|  | ||||
| Nmea_Printer::~Nmea_Printer() | ||||
| { | ||||
|     if (nmea_file_descriptor.is_open()) | ||||
|         { | ||||
|     		nmea_file_descriptor.close(); | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| bool Nmea_Printer::Print_Nmea_Line(gps_l1_ca_ls_pvt* pvt_data, bool print_average_values) | ||||
| { | ||||
|  | ||||
| 	// set the new PVT data | ||||
| 	d_PVT_data=pvt_data; | ||||
|  | ||||
| 	try{ | ||||
| 		//GPRMC | ||||
| 		nmea_file_descriptor<<get_GPRMC(); | ||||
| 		//GPGGA (Global Positioning System Fixed Data) | ||||
| 		nmea_file_descriptor<<get_GPGGA(); | ||||
| 		//GPGSA | ||||
| 		nmea_file_descriptor<<get_GPGSA(); | ||||
| 		//GPGSV | ||||
| 		nmea_file_descriptor<<get_GPGSV(); | ||||
|  | ||||
| 	}catch(std::exception ex) | ||||
| 	{ | ||||
| 		 DLOG(INFO) << "NMEA printer can not write on output file" << nmea_filename.c_str();; | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| char Nmea_Printer::checkSum(std::string sentence) { | ||||
|   char check = 0; | ||||
|   // iterate over the string, XOR each byte with the total sum: | ||||
|   for (unsigned int c = 0; c < sentence.length(); c++) { | ||||
|     check = char(check ^ sentence.at(c)); | ||||
|   } | ||||
|   // return the result | ||||
|   return check; | ||||
| } | ||||
|  | ||||
| std::string Nmea_Printer::latitude_to_hm(double lat) | ||||
| { | ||||
| 	bool north; | ||||
|     if (lat < 0.0) | ||||
|     { | ||||
|     	north = false; | ||||
|     	lat = -lat ; | ||||
|     }else{ | ||||
|     	north = true; | ||||
|     } | ||||
|  | ||||
|     int deg = (int)lat; | ||||
|     double mins = lat - (double)deg; | ||||
|     mins *= 60.0 ; | ||||
|     std::ostringstream out_string; | ||||
|     out_string.setf(std::ios::fixed, std::ios::floatfield); | ||||
|     out_string.fill('0'); | ||||
|     out_string.width(2); | ||||
|     out_string << deg; | ||||
|     out_string.width(6); | ||||
|     out_string.precision(4); | ||||
|     out_string<<mins; | ||||
|  | ||||
|     if (north==true) | ||||
|     { | ||||
|     	out_string << ",N"; | ||||
|     }else{ | ||||
|     	out_string << ",S"; | ||||
|     } | ||||
|     return out_string.str(); | ||||
| } | ||||
|  | ||||
| std::string Nmea_Printer::longitude_to_hm(double longitude) | ||||
| { | ||||
| 	bool east; | ||||
|     if (longitude < 0.0) | ||||
|     { | ||||
|     	east = false; | ||||
|     	longitude = -longitude ; | ||||
|     }else{ | ||||
|     	east=true; | ||||
|     } | ||||
|  | ||||
|     int deg = (int)longitude; | ||||
|     double mins = longitude - (double)deg; | ||||
|     mins *= 60.0 ; | ||||
|     std::ostringstream out_string; | ||||
|     out_string.setf(std::ios::fixed, std::ios::floatfield); | ||||
|     out_string.width(3); | ||||
|     out_string.fill('0'); | ||||
|     out_string << deg; | ||||
|     out_string.width(6); | ||||
|     out_string.precision(4); | ||||
|     out_string<<mins; | ||||
|  | ||||
|     if (east==true) | ||||
|     { | ||||
|     	out_string << ",E"; | ||||
|     }else{ | ||||
|     	out_string << ",W"; | ||||
|     } | ||||
|  | ||||
|     return out_string.str(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| std::string Nmea_Printer::get_UTC_NMEA_time(boost::posix_time::ptime d_position_UTC_time) | ||||
| { | ||||
| 	//UTC Time: hhmmss.sss | ||||
| 	std::stringstream sentence_str; | ||||
|  | ||||
| 	boost::posix_time::time_duration td=d_position_UTC_time.time_of_day(); | ||||
| 	int utc_hours; | ||||
| 	int utc_mins; | ||||
| 	int utc_seconds; | ||||
| 	int utc_milliseconds; | ||||
|  | ||||
| 	utc_hours=td.hours(); | ||||
| 	utc_mins=td.minutes(); | ||||
| 	utc_seconds=td.seconds(); | ||||
| 	utc_milliseconds=td.total_milliseconds()-td.total_seconds()*1000; | ||||
|  | ||||
|     if (utc_hours < 10) sentence_str << "0"; //  two digits for hours | ||||
|     sentence_str << utc_hours; | ||||
|  | ||||
|     if (utc_mins < 10) sentence_str << "0"; //  two digits for minutes | ||||
|     sentence_str << utc_mins; | ||||
|  | ||||
|     if (utc_seconds < 10) sentence_str << "0"; //  two digits for seconds | ||||
|     sentence_str << utc_seconds; | ||||
|  | ||||
|     if (utc_milliseconds < 10) | ||||
|     	{ | ||||
|     		sentence_str << ".00"; //  three digits for ms | ||||
|     		sentence_str << utc_milliseconds; | ||||
|     	} | ||||
|     else if (utc_milliseconds < 100) | ||||
|     { | ||||
| 		sentence_str << ".0"; //   three digits for ms | ||||
| 		sentence_str << utc_milliseconds; | ||||
|     }else | ||||
|     { | ||||
|     	sentence_str << "."; //   three digits for ms | ||||
|     	sentence_str << utc_milliseconds; | ||||
|     } | ||||
|     return sentence_str.str(); | ||||
| } | ||||
| std::string Nmea_Printer::get_GPRMC() | ||||
| { | ||||
| 	// Sample -> $GPRMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598,*10 | ||||
|  | ||||
| 	bool valid_fix=d_PVT_data->b_valid_position; | ||||
|  | ||||
| 	// ToDo: Compute speed and course over ground | ||||
| 	double speed_over_ground_knots=0; | ||||
| 	double course_over_ground_deg=0; | ||||
|  | ||||
| 	//boost::posix_time::ptime d_position_UTC_time=boost::posix_time::microsec_clock::universal_time(); | ||||
|  | ||||
| 	std::stringstream sentence_str; | ||||
|  | ||||
| 	//GPRMC (RMC-Recommended,Minimum Specific GNSS Data) | ||||
| 	std::string sentence_header; | ||||
| 	sentence_header="$GPRMC,"; | ||||
| 	sentence_str<<sentence_header; | ||||
|  | ||||
| 	//UTC Time: hhmmss.sss | ||||
| 	sentence_str<<get_UTC_NMEA_time(d_PVT_data->d_position_UTC_time); | ||||
|  | ||||
| 	//Status: A: data valid, V: data NOT valid | ||||
|  | ||||
| 	if (valid_fix==true) | ||||
| 	{ | ||||
| 		sentence_str<<",A"; | ||||
| 	}else{ | ||||
| 		sentence_str<<",V"; | ||||
| 	}; | ||||
|  | ||||
| 	if (d_PVT_data->d_flag_averaging==true) | ||||
| 	{ | ||||
| 	    // Latitude ddmm.mmmm,(N or S) | ||||
|  | ||||
| 	    sentence_str<<","<<latitude_to_hm(d_PVT_data->d_avg_latitude_d); | ||||
|  | ||||
| 	    // longitude dddmm.mmmm,(E or W) | ||||
|  | ||||
| 	    sentence_str<<","<<longitude_to_hm(d_PVT_data->d_avg_longitude_d); | ||||
| 	}else{ | ||||
| 	    // Latitude ddmm.mmmm,(N or S) | ||||
|  | ||||
| 	    sentence_str<<","<<latitude_to_hm(d_PVT_data->d_latitude_d); | ||||
|  | ||||
| 	    // longitude dddmm.mmmm,(E or W) | ||||
|  | ||||
| 	    sentence_str<<","<<longitude_to_hm(d_PVT_data->d_longitude_d); | ||||
| 	} | ||||
|  | ||||
|     //Speed over ground (knots) | ||||
|     sentence_str<<","; | ||||
|     sentence_str.setf(std::ios::fixed, std::ios::floatfield); | ||||
|     sentence_str.precision(2); | ||||
|     sentence_str << speed_over_ground_knots; | ||||
|  | ||||
|     //course over ground (degrees) | ||||
|     sentence_str<<","; | ||||
|     sentence_str.setf(std::ios::fixed, std::ios::floatfield); | ||||
|     sentence_str.precision(2); | ||||
|     sentence_str << course_over_ground_deg; | ||||
|  | ||||
|     // Date ddmmyy | ||||
|  | ||||
|     boost::gregorian::date sentence_date = d_PVT_data->d_position_UTC_time.date(); | ||||
|     unsigned int year=sentence_date.year(); | ||||
|     unsigned int day=sentence_date.day(); | ||||
|     unsigned int month=sentence_date.month(); | ||||
|  | ||||
|     sentence_str<<","; | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str<<day; | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str<<month; | ||||
|  | ||||
|     std::stringstream year_strs; | ||||
|     year_strs<<std::dec<<year; | ||||
|     sentence_str<<std::dec<<year_strs.str().substr(2); | ||||
|  | ||||
|     //Magnetic Variation (degrees) | ||||
|     // ToDo: Implement magnetic compass | ||||
|     sentence_str<<","; | ||||
|  | ||||
|     //Magnetic Variation (E or W) | ||||
|     // ToDo: Implement magnetic compass | ||||
|     sentence_str<<","; | ||||
|  | ||||
|     // Checksum | ||||
|  | ||||
|     char checksum; | ||||
|     std::string tmpstr; | ||||
|     tmpstr=sentence_str.str(); | ||||
|  | ||||
|     checksum = checkSum(tmpstr.substr(1)); | ||||
|     sentence_str<<"*"; | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str<<std::hex<<(int)checksum; | ||||
|  | ||||
|     // end NMEA sentence | ||||
|     sentence_str<<"\r\n"; | ||||
|  | ||||
|     return sentence_str.str(); | ||||
|  | ||||
| } | ||||
|  | ||||
| std::string Nmea_Printer::get_GPGSA() | ||||
| { | ||||
| 	//$GPGSA,A,3,07,02,26,27,09,04,15, , , , , ,1.8,1.0,1.5*33 | ||||
| 	// GSA-GNSS DOP and Active Satellites | ||||
|  | ||||
| 	bool valid_fix=d_PVT_data->b_valid_position; | ||||
|  | ||||
| 	int n_sats_used=d_PVT_data->d_valid_observations; | ||||
|  | ||||
| 	double pdop=d_PVT_data->d_PDOP; | ||||
| 	double hdop=d_PVT_data->d_HDOP; | ||||
| 	double vdop=d_PVT_data->d_VDOP; | ||||
|  | ||||
|  | ||||
| 	std::stringstream sentence_str; | ||||
| 	std::string sentence_header; | ||||
| 	sentence_header="$GPGSA,"; | ||||
| 	sentence_str<<sentence_header; | ||||
|  | ||||
| 	// mode1: | ||||
| 	// (M) Manual-forced to operate in 2D or 3D mode | ||||
| 	// (A) Automatic-allowed to automatically switch 2D/3D | ||||
| 	std::string mode1="M"; | ||||
|  | ||||
| 	sentence_str<<mode1; | ||||
| 	// mode2: | ||||
| 	// 1 fix not available | ||||
| 	// 2 fix 2D | ||||
| 	// 3 fix 3D | ||||
| 	if (valid_fix==true) | ||||
| 	{ | ||||
| 		sentence_str<<",3"; | ||||
| 	}else{ | ||||
| 		sentence_str<<",1"; | ||||
| 	}; | ||||
|  | ||||
| 	// Used satellites | ||||
| 	for (int i=0; i<12;i++) | ||||
| 	{ | ||||
| 		sentence_str<<","; | ||||
| 	    if (i<n_sats_used) | ||||
| 	    { | ||||
| 		    sentence_str.width(2); | ||||
| 		    sentence_str.fill('0'); | ||||
| 	    	sentence_str<<d_PVT_data->d_visible_satellites_IDs[i]; | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
| 	// PDOP | ||||
|     sentence_str<<","; | ||||
|     sentence_str.setf(std::ios::fixed, std::ios::floatfield); | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.precision(1); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str << pdop; | ||||
| 	//HDOP | ||||
|     sentence_str<<","; | ||||
|     sentence_str.setf(std::ios::fixed, std::ios::floatfield); | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.precision(1); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str << hdop; | ||||
|  | ||||
| 	//VDOP | ||||
|     sentence_str<<","; | ||||
|     sentence_str.setf(std::ios::fixed, std::ios::floatfield); | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.precision(1); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str << vdop; | ||||
|  | ||||
|     // Checksum | ||||
|  | ||||
|     char checksum; | ||||
|     std::string tmpstr; | ||||
|     tmpstr=sentence_str.str(); | ||||
|  | ||||
|     checksum = checkSum(tmpstr.substr(1)); | ||||
|     sentence_str<<"*"; | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str<<std::hex<<(int)checksum; | ||||
|  | ||||
|     // end NMEA sentence | ||||
|     sentence_str<<"\r\n"; | ||||
|  | ||||
| 	return sentence_str.str(); | ||||
| } | ||||
|  | ||||
| std::string Nmea_Printer::get_GPGSV() | ||||
| { | ||||
| 	// GSV-GNSS Satellites in View | ||||
| 	// Notice that NMEA 2.1 only supports 12 channels | ||||
|  | ||||
| 	int n_sats_used=d_PVT_data->d_valid_observations; | ||||
|  | ||||
| 	std::stringstream sentence_str; | ||||
| 	std::stringstream frame_str; | ||||
| 	std::string sentence_header; | ||||
| 	sentence_header="$GPGSV,"; | ||||
|  | ||||
| 	char checksum; | ||||
| 	std::string tmpstr; | ||||
| 	// 1st step: How many GPGSV frames we need? (up to 3) | ||||
| 	// Each frame countains up to 4 satellites | ||||
| 	int n_frames; | ||||
| 	n_frames=std::ceil(((double)n_sats_used)/4.0); | ||||
|  | ||||
| 	// generate the frames | ||||
| 	int current_satellite=0; | ||||
| 	for (int i=1;i<(n_frames+1);i++) | ||||
| 	{ | ||||
|  | ||||
| 		frame_str.str(""); | ||||
|  | ||||
| 		frame_str<<sentence_header; | ||||
|  | ||||
| 		// number of messages | ||||
| 		frame_str<<n_frames; | ||||
|  | ||||
| 		// message number | ||||
| 		frame_str<<","; | ||||
| 		frame_str<<i; | ||||
|  | ||||
| 		// total number of satellites in view | ||||
| 		frame_str<<","; | ||||
| 		frame_str.width(2); | ||||
| 		frame_str.fill('0'); | ||||
| 		frame_str<<std::dec<<n_sats_used; | ||||
|  | ||||
| 		//satellites info | ||||
| 	    for (int j=0;j<4;j++) | ||||
| 	    { | ||||
| 	    	// write satellite info | ||||
| 	    	frame_str<<","; | ||||
| 	    	frame_str.width(2); | ||||
| 	    	frame_str.fill('0'); | ||||
| 	    	frame_str<<std::dec<<d_PVT_data->d_visible_satellites_IDs[current_satellite]; | ||||
|  | ||||
| 	    	frame_str<<","; | ||||
| 	    	frame_str.width(2); | ||||
| 	    	frame_str.fill('0'); | ||||
| 	    	frame_str<<std::dec<<(int)d_PVT_data->d_visible_satellites_El[current_satellite]; | ||||
|  | ||||
| 	    	frame_str<<","; | ||||
| 	    	frame_str.width(3); | ||||
| 	    	frame_str.fill('0'); | ||||
| 	    	frame_str<<std::dec<<(int)d_PVT_data->d_visible_satellites_Az[current_satellite]; | ||||
|  | ||||
| 	    	frame_str<<","; | ||||
| 	    	frame_str.width(2); | ||||
| 	    	frame_str.fill('0'); | ||||
| 	    	frame_str<<std::dec<<(int)d_PVT_data->d_visible_satellites_CN0_dB[current_satellite]; | ||||
|  | ||||
| 	    	current_satellite++; | ||||
|  | ||||
| 	    	if (current_satellite==n_sats_used) | ||||
| 	    	{ | ||||
| 	    		break; | ||||
| 	    	} | ||||
| 	    } | ||||
|  | ||||
| 	    // frame checksum | ||||
| 	    tmpstr=frame_str.str(); | ||||
| 	    checksum = checkSum(tmpstr.substr(1)); | ||||
| 	    frame_str<<"*"; | ||||
| 	    frame_str.width(2); | ||||
| 	    frame_str.fill('0'); | ||||
| 	    frame_str<<std::hex<<(int)checksum; | ||||
|  | ||||
| 	    // end NMEA sentence | ||||
| 	    frame_str<<"\r\n"; | ||||
|  | ||||
| 	    //add frame to sentence | ||||
| 	    sentence_str<<frame_str.str(); | ||||
| 	} | ||||
|  | ||||
| 	return sentence_str.str(); | ||||
|  | ||||
| 	//$GPGSV,2,1,07,07,79,048,42,02,51,062,43,26,36,256,42,27,27,138,42*71 | ||||
|  | ||||
| } | ||||
| std::string Nmea_Printer::get_GPGGA() | ||||
| { | ||||
| 	//boost::posix_time::ptime d_position_UTC_time=boost::posix_time::microsec_clock::universal_time(); | ||||
|  | ||||
| 	bool valid_fix=d_PVT_data->b_valid_position; | ||||
|  | ||||
| 	int n_channels=d_PVT_data->d_valid_observations;//d_nchannels | ||||
| 	double hdop=d_PVT_data->d_HDOP; | ||||
| 	double MSL_altitude; | ||||
|  | ||||
| 	if (d_PVT_data->d_flag_averaging==true) | ||||
| 	{ | ||||
| 		MSL_altitude=d_PVT_data->d_avg_height_m; | ||||
| 	}else{ | ||||
| 		MSL_altitude=d_PVT_data->d_height_m; | ||||
| 	} | ||||
|  | ||||
| 	std::stringstream sentence_str; | ||||
|  | ||||
| 	//GPGGA (Global Positioning System Fixed Data) | ||||
| 	std::string sentence_header; | ||||
| 	sentence_header="$GPGGA,"; | ||||
|  | ||||
| 	sentence_str<<sentence_header; | ||||
|  | ||||
| 	//UTC Time: hhmmss.sss | ||||
|  | ||||
| 	sentence_str<<get_UTC_NMEA_time(d_PVT_data->d_position_UTC_time); | ||||
|  | ||||
| 	if (d_PVT_data->d_flag_averaging==true) | ||||
| 	{ | ||||
| 	    // Latitude ddmm.mmmm,(N or S) | ||||
|  | ||||
| 	    sentence_str<<","<<latitude_to_hm(d_PVT_data->d_avg_latitude_d); | ||||
|  | ||||
| 	    // longitude dddmm.mmmm,(E or W) | ||||
|  | ||||
| 	    sentence_str<<","<<longitude_to_hm(d_PVT_data->d_avg_longitude_d); | ||||
| 	}else{ | ||||
| 	    // Latitude ddmm.mmmm,(N or S) | ||||
|  | ||||
| 	    sentence_str<<","<<latitude_to_hm(d_PVT_data->d_latitude_d); | ||||
|  | ||||
| 	    // longitude dddmm.mmmm,(E or W) | ||||
|  | ||||
| 	    sentence_str<<","<<longitude_to_hm(d_PVT_data->d_longitude_d); | ||||
| 	} | ||||
|  | ||||
|     // Position fix indicator | ||||
|     // 0 - Fix not available or invalid | ||||
|     // 1 - GPS SPS Mode, fix valid | ||||
|     // 2 - Differential GPS, SPS Mode, fix valid | ||||
|     // 3-5 - Not supported | ||||
|     // 6 - Dead Reckoning Mode, fix valid | ||||
|     // ToDo: Update PVT module to identify the fix mode | ||||
|  | ||||
|     if (valid_fix==true) | ||||
|     { | ||||
|     	sentence_str<<",1"; | ||||
|     }else{ | ||||
|     	sentence_str<<",0"; | ||||
|     } | ||||
|  | ||||
|     // Number of satellites used in PVT | ||||
|     sentence_str<<","; | ||||
|     if (n_channels<10) | ||||
|     { | ||||
|     	sentence_str<<'0'<<n_channels; | ||||
|     }else{ | ||||
|     	sentence_str<<n_channels; | ||||
|     } | ||||
|  | ||||
|     // HDOP | ||||
|     sentence_str<<","; | ||||
|     sentence_str.setf(std::ios::fixed, std::ios::floatfield); | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.precision(1); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str << hdop; | ||||
|  | ||||
|     // MSL Altitude | ||||
|     sentence_str<<","; | ||||
|     sentence_str.precision(1); | ||||
|     sentence_str<<MSL_altitude; | ||||
|     sentence_str<<",M"; | ||||
|  | ||||
|     // Geoid-to-ellipsoid separation. Ellipsoid altitude = MSL Altitude + Geoid Separation. | ||||
|     // ToDo: Compute this value | ||||
|     sentence_str<<","; | ||||
|     sentence_str<<"0.0"; | ||||
|     sentence_str<<",M"; | ||||
|  | ||||
|     // Age of Diff. Corr.  (Seconds) Null fields when DGPS is not used | ||||
|     // Diff. Ref. Station ID (0000) | ||||
|     // ToDo: Implement this fields for Differential GPS | ||||
|     sentence_str<<","; | ||||
|     sentence_str<<"0.0,0000"; | ||||
|  | ||||
|     // Checksum | ||||
|  | ||||
|     char checksum; | ||||
|     std::string tmpstr; | ||||
|     tmpstr=sentence_str.str(); | ||||
|  | ||||
|     checksum = checkSum(tmpstr.substr(1)); | ||||
|     sentence_str<<"*"; | ||||
|     sentence_str.width(2); | ||||
|     sentence_str.fill('0'); | ||||
|     sentence_str<<std::hex<<(int)checksum; | ||||
|  | ||||
|     // end NMEA sentence | ||||
|     sentence_str<<"\r\n"; | ||||
|  | ||||
|     return sentence_str.str(); | ||||
|  | ||||
|     //$GPGGA,104427.591,5920.7009,N,01803.2938,E,1,05,3.3,78.2,M,23.2,M,0.0,0000*4A | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										80
									
								
								src/algorithms/PVT/libs/nmea_printer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/algorithms/PVT/libs/nmea_printer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| /*! | ||||
|  * \file kml_printer.h | ||||
|  * \brief Implementation of a NMEA 2.1 printer for GNSS-SDR | ||||
|  * This class provides a implementation of a subset of the NMEA-0183 standard for interfacing | ||||
|  * marine electronic devices as defined by the National Marine Electronics Association (NMEA). | ||||
|  * See http://www.nmea.org/ for the NMEA 183 standard | ||||
|  * | ||||
|  * \author Javier Arribas, 2012. jarribas(at)cttc.es | ||||
|  * | ||||
|  * | ||||
|  * ------------------------------------------------------------------------- | ||||
|  * | ||||
|  * Copyright (C) 2010-2012  (see AUTHORS file for a list of contributors) | ||||
|  * | ||||
|  * GNSS-SDR is a software defined Global Navigation | ||||
|  *          Satellite Systems receiver | ||||
|  * | ||||
|  * This file is part of GNSS-SDR. | ||||
|  * | ||||
|  * GNSS-SDR 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. | ||||
|  * | ||||
|  * GNSS-SDR 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 GNSS-SDR. If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * ------------------------------------------------------------------------- | ||||
|  */ | ||||
|  | ||||
| #ifndef GNSS_SDR_NMEA_PRINTER_H_ | ||||
| #define	 GNSS_SDR_NMEA_PRINTER_H_ | ||||
|  | ||||
|  | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include "gps_l1_ca_ls_pvt.h" | ||||
|  | ||||
| class Nmea_Printer | ||||
| { | ||||
| public: | ||||
|     /*! | ||||
|      * \brief Default constructor. | ||||
|      */ | ||||
|     Nmea_Printer(std::string filename); | ||||
|  | ||||
|     /*! | ||||
|      * \brief Print NMEA PVT and satellite info to the initialized device | ||||
|      */ | ||||
|     bool Print_Nmea_Line(gps_l1_ca_ls_pvt* position, bool print_average_values); | ||||
|  | ||||
|     /*! | ||||
|      * \brief Default destructor. | ||||
|      */ | ||||
|     ~Nmea_Printer(); | ||||
|  | ||||
|  | ||||
| private: | ||||
|     std::string nmea_filename ; //<! String with the NMEA log filename | ||||
|     std::ofstream nmea_file_descriptor ; //<! Output file stream for NMEA log file | ||||
|  | ||||
|     gps_l1_ca_ls_pvt* d_PVT_data; | ||||
|  | ||||
|     std::string get_GPGGA(); | ||||
|     std::string get_GPGSV(); | ||||
|     std::string get_GPGSA(); | ||||
|     std::string get_GPRMC(); | ||||
|     std::string get_UTC_NMEA_time(boost::posix_time::ptime d_position_UTC_time); | ||||
|     std::string longitude_to_hm(double longitude); | ||||
|     std::string latitude_to_hm(double lat); | ||||
|     char checkSum(std::string sentence); | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -37,6 +37,7 @@ exe gnss-sdr : main.cc | ||||
| ../algorithms/observables/gnuradio_blocks//gps_l1_ca_observables_cc | ||||
| ../algorithms/PVT/libs//rinex_printer | ||||
| ../algorithms/PVT/libs//kml_printer | ||||
| ../algorithms/PVT/libs//nmea_printer | ||||
| ../algorithms/PVT/libs//gps_l1_ca_ls_pvt | ||||
| ../algorithms/output_filter/adapters//file_output_filter | ||||
| ../algorithms/output_filter/adapters//null_sink_output_filter | ||||
|   | ||||
| @@ -34,6 +34,7 @@ exe run_tests : test_main.cc | ||||
| ../algorithms/observables/gnuradio_blocks//gps_l1_ca_observables_cc | ||||
| ../algorithms/PVT/libs//rinex_printer | ||||
| ../algorithms/PVT/libs//kml_printer | ||||
| ../algorithms/PVT/libs//nmea_printer | ||||
| ../algorithms/PVT/libs//gps_l1_ca_ls_pvt | ||||
| ../algorithms/output_filter/adapters//file_output_filter | ||||
| ../algorithms/output_filter/adapters//null_sink_output_filter | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Javier Arribas
					Javier Arribas