Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • cli_segfault_test
  • commands-dev
  • commands-dev-backend
  • commands-to-make-andy-happy
  • groundStation-dev-cli
  • groundStation-dev-cli-setpoint
  • groundStation-dev-frontend-pid
  • groundStation-dev-getpid
  • groundStation-dev-quad-response
  • groundstation-datalog-vrpn
  • groundstation-dev-cliCommandHelpMessages
  • master
  • new-commands
  • new-uart
  • new-uart-circ
  • quad-auto-height
  • update-commands
17 results

Target

Select target project
  • danc/MicroCART
  • snawerdt/MicroCART_17-18
  • bbartels/MicroCART_17-18
  • jonahu/MicroCART
4 results
Select Git revision
  • develop
  • master
  • 2020-team-final-state
  • Lab_Part_1_tag
  • Lab_Part_2_tag
  • sdmay25-32-final
  • team_17-16_demo
  • team_17-16_v1
  • team_17-16_v2
  • team_18-17
10 results
Show changes
Showing
with 0 additions and 34646 deletions
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]
# - Build the OpenHaptics utility libraries as a part of your solution.
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file ../../LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(WIN32)
# Work around bug in library at least <= 3.10
add_definitions(-DWIN32)
endif()
include_directories("${HDAPI_HDU_INCLUDE_DIR}"
"${HDAPI_INCLUDE_DIR}"
"${HLAPI_HLU_INCLUDE_DIR}"
"${HLAPI_INCLUDE_DIR}")
if(HDAPI_HDU_LIBRARY STREQUAL "openhaptics_hdu_nested_target")
add_library(openhaptics_hdu_nested_target
STATIC
EXCLUDE_FROM_ALL
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduBoundBox.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduError.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduGenericMatrix.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hdu.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduHapticDevice.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduLine.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduLineSegment.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduMath.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduMatrix.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduPlane.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduQuaternion.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduRecord.h"
"${HDAPI_HDU_INCLUDE_DIR}/HDU/hduVector.h"
"${HDAPI_HDU_SOURCE_DIR}/hdu.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduAfx.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduAfx.h"
"${HDAPI_HDU_SOURCE_DIR}/hduDecompose.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduDecompose.h"
"${HDAPI_HDU_SOURCE_DIR}/hduError.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduHapticDevice.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduLine.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduLineSegment.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduMatrix.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduPlane.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduQuaternion.cpp"
"${HDAPI_HDU_SOURCE_DIR}/hduRecord.cpp")
target_link_libraries(openhaptics_hdu_nested_target ${HDAPI_LIBRARY})
set_property(TARGET
openhaptics_hdu_nested_target
PROPERTY
PROJECT_LABEL
"OpenHaptics HDU Library")
if(MSVC)
# Disable warnings - no sense in warning about Sensable's potential bugs.
set_property(TARGET
openhaptics_hdu_nested_target
PROPERTY
COMPILE_FLAGS
"/wd4189 /wd4701")
endif()
endif()
if(HLAPI_HLU_LIBRARY STREQUAL "openhaptics_hlu_nested_target")
add_library(openhaptics_hlu_nested_target
STATIC
EXCLUDE_FROM_ALL
"${HLAPI_HLU_INCLUDE_DIR}/HLU/hlu.h"
"${HLAPI_HLU_SOURCE_DIR}/hlu.cpp"
"${HLAPI_HLU_SOURCE_DIR}/hluAfx.cpp"
"${HLAPI_HLU_SOURCE_DIR}/hluAfx.h")
target_link_libraries(openhaptics_hlu_nested_target ${HLAPI_LIBRARY} ${HDAPI_LIBRARY})
set_property(TARGET
openhaptics_hlu_nested_target
PROPERTY
PROJECT_LABEL
"OpenHaptics HLU Library")
if(MSVC)
# Disable warnings - no sense in warning about Sensable's potential bugs.
set_property(TARGET
openhaptics_hlu_nested_target
APPEND
PROPERTY
COMPILE_FLAGS
/wd4189)
endif()
endif()
Source diff could not be displayed: it is too large. Options to address this: view the blob.
#!/usr/bin/tclsh
# $Id$
display distance -2.000000
display projection Perspective
display nearclip set 0.000100
display farclip set 30.000000
display depthcue off
display backgroundgradiend on
if {0} {
display rendermode GLSL
} else {
display rendermode Normal
}
set thismol [ mol new afm-plus.psf type psf first 0 last -1 step 1 filebonds 1 autobonds 1 waitfor all ]
mol delrep 0 top
mol representation VDW 0.500000 16.000000
mol color Name
mol selection {name SU NS CS OS HS}
mol material Glossy
mol addrep top
mol selection {name ZN PS}
mol material AOEdgy
mol addrep top
mol rename top {Simulated AFM Experiment}
draw delete all
draw material Glass3
#draw material Chalky
draw color white
draw triangle {-26.0 -26.0 -26.0} { 26.0 -26.0 -26.0} { 26.0 0.0 -26.0}
draw triangle {-26.0 -26.0 -26.0} {-26.0 0.0 -26.0} { 26.0 0.0 -26.0}
draw triangle {-26.0 -26.0 26.0} { 26.0 -26.0 26.0} { 26.0 0.0 26.0}
draw triangle {-26.0 -26.0 26.0} {-26.0 0.0 26.0} { 26.0 0.0 26.0}
draw triangle { 26.0 -26.0 -26.0} { 26.0 -26.0 26.0} { 26.0 0.0 26.0}
draw triangle { 26.0 -26.0 -26.0} { 26.0 0.0 -26.0} { 26.0 0.0 26.0}
imd connect localhost 6789
display resize 1024 768
rotate y by 90
translate by 0.0 -0.5 0.0
after idle {
play falcon.tcl
}
Source diff could not be displayed: it is too large. Options to address this: view the blob.
#!/usr/bin/tclsh
# $Id$
menu tool on
tool create tug falcon0 fbuttons0 ffeedback0
tool scale 30.0 0
tool scaleforce 20.0 0
tool scalespring 25.0
if {1} {
# attach effector to second representation (AFM tip).
tool rep 0 0 1
} else {
# effector grabs atoms.
tool rep 0 -1 -1
}
# virtual atomic force microscope demo
# $Id $
dimension 3
units lj
atom_style molecular
bond_style harmonic
angle_style harmonic
boundary s s s
newton on off # apply newton's 3rd law only for nonbonded.
special_bonds lj/coul 0.0 0.0 1.0
# override original processor grid for maximum performance.
# since there are few atoms in y direction we don't want
# to do domain decomposition in that direction. so optimally
# is should be set to that the middle number is always 1.
# use this for 6 CPUs
#processors 3 1 2
# use this for 7 CPUs
processors 1 1 7
# we are pushing the limits with the time step,
# make sure we don't miss neighbor list updates.
neighbor 0.45 bin
neigh_modify delay 2 every 1 check yes
# an fcc lattice will be our base lattice
# not really needed with a data file, but...
lattice fcc 0.9
# system definition
read_data data.afm-plus
# atom masses.
mass 1 1.0 # substrate, doesn't move so mass doesn't matter.
mass 2 1.0 # light, soft atoms => liquid.
mass 3 5.0 # medium weight, medium hard atoms => soft solid.
mass 4 25.0 # heavy, hard atoms => hard solid.
mass 5 0.005 # tip atoms. have to be very light, so we can "feel" something.
mass 6 1.0 # buckyballs.
# surface and buckballs are integrated normally.
group mobile type 2 3 4 6
velocity mobile create 0.6 46659 mom yes rot yes dist gaussian
# temperature is based on mobile atoms only
compute mobtemp mobile temp
# contain mobile atoms within the original simulation cell
fix bounds all wall/lj93 xlo -16.0 1.0 1.7 1.36 xhi 16.0 1.0 1.7 1.36 &
ylo -16.0 1.0 1.7 1.36 yhi 10.0 1.0 1.7 1.36 &
zlo -16.0 1.0 1.7 1.36 zhi 16.0 1.0 1.7 1.36 &
units lattice
# make probe rigid and keep it from rotating.
group afm type 5
fix afmtip afm rigid group 1 afm torque * off off off
velocity afm set 0.0 0.0 0.0
# damping through friction makes the probe much easier
# to control and keeps it in place if not grabbed.
fix dampen afm viscous 0.02
# with bouncing walls we need to slow down regular atoms, too
fix frict mobile viscous 0.05
pair_style lj/cut 2.5
# GPU version dies in cell list.
#pair_style lj/cut/gpu one/node 1 3.0
pair_coeff * * 1.0 1.05
pair_coeff 3 3 2.0 1.05
pair_coeff 4 4 3.0 1.05
pair_coeff 6 6 0.2 1.05
# reset parameters for interactions with the tip
# and make tip atoms a bit hard and large and
# mostly repulsive so that they are more "feely"
# (not physically correct, but much nicer).
pair_coeff 1 5 3.0 1.30 1.50
pair_coeff 2 5 3.0 1.30 1.50
pair_coeff 3 5 3.0 1.30 1.50
pair_coeff 4 5 3.0 1.30 1.50
pair_coeff 5 6 3.0 1.30 1.50
# buckballs are purely repulsive with
# type 2 atoms to make them float on top.
pair_coeff 2 6 0.6 1.05 1.178
# buckball bonded parameters, adapted from CHARMM benzene.
bond_coeff 1 340.0 0.72
angle_coeff 1 570.0 120.00
#
run_style respa 2 3 bond 1 angle 1 dihedral 1 pair 2
timestep 0.015
# use verlet for smoother interactions through higher TimeS/S,
# but slower progress
#run_style verlet
#timestep 0.005
fix integrate mobile nve
fix thermostat mobile langevin 0.5 0.5 10.0 699483
thermo_style custom step pe ke evdwl emol c_mobtemp tpt tps
thermo 1000
thermo_modify norm yes
thermo_modify temp mobtemp
#write_restart afm-plus.restart
#dump traj all atom 100 afm-plus.lammpstrj
fix comm all imd 6789 unwrap off trate 10
#run 10000
# XXX: need to correct fix imd to handle multiple runs.
run 5000000000
# vrpn.cfg.SAMPLE for VRPN version 07.18
################################################################################
################################################################################
# This file provides comments and examples for the vrpn.cfg file that is read
# by the vrpn_server application when it starts up. This is a generic server
# application that can start up many but maybe not all servers.
#
# This has sample lines for a vrpn.cfg file. If you get a new device working,
# add a line for it here. DO NOT remove lines from this file (unless
# devices are declared obsolete) - just change the actual vrpn.cfg to match
# your application.
#
# All examples in the file are preceded by comment characters (#). To actually
# use one of these examples, remove that character from the beginning of all the
# examples that you want to use, and edit those lines to suit your environment.
################################################################################
################################################################################
# NULL Tracker. This is a "device" that reports the Identity transformation for
# each of its sensors at the specified rate. It can be used to verify connections
# are working and for other tests of VRPN. There are three arguments:
# char name_of_this_device[]
# int number_of_sensors
# float rate_at_which_to_report_updates
#
# vrpn_Tracker_NULL Tracker0 2 2.0
################################################################################
# Novint Falcon attached to USB.
# Arguments:
# char name_of_this_device[]
# int device index (starts at 0)
# char name_of_grip (optional, default= "4-button")
# char kinematic_model (optional, default="stamper")
vrpn_Tracker_NovintFalcon Tracker0 0 4-button
html
latex
man
# Changes made by:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
include(DoxygenTargets)
#-----------------------------------------------------------------------------
# Create documentation
add_doxygen(Doxyfile
INSTALL_DESTINATION
share/doc/vrpn-${BRIEF_VERSION}/source-docs
NO_PDF
INSTALL_COMPONENT
doc) # For some reason, LaTeX bails with a nesting-too-deep error
# The PROJECT_NAME tag is a single word (or sequence of words) that should
# identify the project. Note that if you do not use Doxywizard you need
# to put quotes around the project name if it contains spaces.
# For config item PROJECT_NAME, default is My Project
PROJECT_NAME = vrpn
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
# a quick idea about the purpose of the project. Keep the description short.
# For config item PROJECT_BRIEF, default is
PROJECT_BRIEF = "Virtual Reality Peripheral Network"
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
# For config item FULL_PATH_NAMES, default is 1
FULL_PATH_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like regular Qt-style comments
# (thus requiring an explicit @brief command for a brief description.)
# For config item JAVADOC_AUTOBRIEF, default is 0
JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
# interpret the first line (until the first dot) of a Qt-style
# comment as the brief description. If set to NO, the comments
# will behave just like regular Qt-style comments (thus requiring
# an explicit \brief command for a brief description.)
# For config item QT_AUTOBRIEF, default is 0
QT_AUTOBRIEF = YES
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
# comments) as a brief description. This used to be the default behaviour.
# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.
# For config item MULTILINE_CPP_IS_BRIEF, default is 0
MULTILINE_CPP_IS_BRIEF = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
# func(std::string) {}). This also makes the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# For config item BUILTIN_STL_SUPPORT, default is 0
BUILTIN_STL_SUPPORT = YES
# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
# is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically
# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# For config item TYPEDEF_HIDES_STRUCT, default is 0
TYPEDEF_HIDES_STRUCT = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
# For config item EXTRACT_ALL, default is 0
EXTRACT_ALL = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.
# For config item EXTRACT_LOCAL_CLASSES, default is 1
EXTRACT_LOCAL_CLASSES = NO
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
# For config item INPUT, default is
INPUT = ..
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
# *.f90 *.f *.for *.vhd *.vhdl
# For config item FILE_PATTERNS, default is
FILE_PATTERNS = *.h \
*.C
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
# For config item SOURCE_BROWSER, default is 0
SOURCE_BROWSER = YES
# If the REFERENCED_BY_RELATION tag is set to YES
# then for each documented function all documented
# functions referencing it will be listed.
# For config item REFERENCED_BY_RELATION, default is 0
REFERENCED_BY_RELATION = YES
# If the REFERENCES_RELATION tag is set to YES
# then for each documented function all documented entities
# called/used by that function will be listed.
# For config item REFERENCES_RELATION, default is 0
REFERENCES_RELATION = YES
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to YES, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
# Windows users are probably better off using the HTML help feature.
# Since the tree basically has the same information as the tab index you
# could consider to set DISABLE_INDEX to NO when enabling this option.
# For config item GENERATE_TREEVIEW, default is 0
GENERATE_TREEVIEW = YES
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, letter, legal and
# executive. If left blank a4wide will be used.
# For config item PAPER_TYPE, default is a4
PAPER_TYPE = letter
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
# For config item GENERATE_MAN, default is 0
GENERATE_MAN = YES
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
# For config item PREDEFINED, default is
PREDEFINED = VRPN_USE_PHANTOM_SERVER \
VRPN_USE_DIRECTINPUT \
VRPN_USE_DIRECTSHOW \
VRPN_INCLUDE_INTERSENSE \
VRPN_USE_NATIONAL_INSTRUMENTS \
VRPN_USE_NATIONAL_INSTRUMENTS_MX \
VRPN_USE_USDIGITAL \
VRPN_USE_MICROSCRIBE \
VRPN_INCLUDE_PHASESPACE \
VRPN_USE_GPM_MOUSE \
VRPN_USE_MOTIONNODE \
VRPN_USE_WIIUSE \
VRPN_USE_FREESPACE \
VRPN_USE_TRIVISIOCOLIBRI \
VRPN_USE_HID \
VRPN_USE_LIBUSB_1_0
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
# For config item HAVE_DOT, default is 0
HAVE_DOT = YES
# If the CALL_GRAPH and HAVE_DOT options are set to YES then
# doxygen will generate a call dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.
# For config item CALL_GRAPH, default is 0
CALL_GRAPH = YES
# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.
# For config item CALLER_GRAPH, default is 0
CALLER_GRAPH = NO
android_widgets/example_app/.classpath
android_widgets/example_app/default.properties
android_widgets/example_app/proguard.cfg
android_widgets/example_app/res/drawable-hdpi/icon.png
android_widgets/example_app/res/drawable-mdpi/icon.png
android_widgets/example_app/res/drawable-ldpi/icon.png
android_widgets/example_app/res/layout/main.xml
android_widgets/example_app/res/values/vrpn.xml
android_widgets/example_app/res/values/strings.xml
android_widgets/example_app/res/values/arrays.xml
android_widgets/example_app/src/test/app1/MainActivity.java
android_widgets/example_app/.project
android_widgets/example_app/AndroidManifest.xml
android_widgets/README.txt
android_widgets/vrpn_library/.classpath
android_widgets/vrpn_library/doc/allclasses-noframe.html
android_widgets/vrpn_library/doc/deprecated-list.html
android_widgets/vrpn_library/doc/allclasses-frame.html
android_widgets/vrpn_library/doc/help-doc.html
android_widgets/vrpn_library/doc/index.html
android_widgets/vrpn_library/doc/package-list
android_widgets/vrpn_library/doc/constant-values.html
android_widgets/vrpn_library/doc/stylesheet.css
android_widgets/vrpn_library/doc/index-files/index-1.html
android_widgets/vrpn_library/doc/index-files/index-4.html
android_widgets/vrpn_library/doc/index-files/index-3.html
android_widgets/vrpn_library/doc/index-files/index-2.html
android_widgets/vrpn_library/doc/index-files/index-5.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/package-frame.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/VrpnToggleButton.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/package-use.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/VrpnSpinner.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/class-use/VrpnToggleButton.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/class-use/VrpnSpinner.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/class-use/VrpnClient.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/class-use/VrpnApplication.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/class-use/VrpnSeekBar.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/class-use/VrpnPressButton.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/class-use/VrpnRadioButton.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/class-use/VrpnSurface.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/VrpnClient.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/VrpnApplication.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/VrpnSeekBar.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/package-summary.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/package-tree.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/VrpnPressButton.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/VrpnRadioButton.html
android_widgets/vrpn_library/doc/eu/ensam/ii/vrpn/VrpnSurface.html
android_widgets/vrpn_library/doc/overview-tree.html
android_widgets/vrpn_library/doc/resources/inherit.gif
android_widgets/vrpn_library/default.properties
android_widgets/vrpn_library/proguard.cfg
android_widgets/vrpn_library/res/drawable-hdpi/ic_menu_manage.png
android_widgets/vrpn_library/res/drawable-hdpi/ic_menu_rotate_right.png
android_widgets/vrpn_library/res/drawable-hdpi/ic_menu_rotate_left.png
android_widgets/vrpn_library/res/drawable-hdpi/ic_menu_preferences.png
android_widgets/vrpn_library/res/drawable-hdpi/ic_lock_silent_mode_vibrate.png
android_widgets/vrpn_library/res/drawable-hdpi/icon.png
android_widgets/vrpn_library/res/drawable-hdpi/ic_menu_refresh.png
android_widgets/vrpn_library/res/drawable-mdpi/ic_menu_rotate_right.png
android_widgets/vrpn_library/res/drawable-mdpi/ic_menu_rotate_left.png
android_widgets/vrpn_library/res/drawable-mdpi/ic_lock_silent_mode_vibrate.png
android_widgets/vrpn_library/res/drawable-mdpi/icon.png
android_widgets/vrpn_library/res/drawable-ldpi/icon.png
android_widgets/vrpn_library/res/layout/vrpn_seekbar.xml
android_widgets/vrpn_library/res/layout/tab_debug_sensors.xml
android_widgets/vrpn_library/res/values/strings.xml
android_widgets/vrpn_library/res/values/attrs.xml
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/VrpnSpinner.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/VrpnSeekBar.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/Quat.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/VrpnClient.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/package-info.html
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/Vec3f.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/VrpnPressButton.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/package-info.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/VrpnRadioButton.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/VrpnSurface.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/VrpnToggleButton.java
android_widgets/vrpn_library/src/eu/ensam/ii/vrpn/VrpnApplication.java
android_widgets/vrpn_library/.project
android_widgets/vrpn_library/AndroidManifest.xml
cmake/FindJsonCpp.cmake
gpsnmealib/typedCoord.h
gpsnmealib/utmCoord.h
gpsnmealib/gpsnmealib.vcproj
gpsnmealib/typedCoord.C
gpsnmealib/nmeaParser.h
gpsnmealib/latLonCoord.C
gpsnmealib/utmCoord.C
gpsnmealib/nmeaParser.C
gpsnmealib/.cvsignore
gpsnmealib/latLonCoord.h
server_src/vrpn.cfg
util/cleanupBeforeCommit.sh
vrpn_android/index_files/vrpn48.png
vrpn_android/cpp_doc.htm
vrpn_android/manuals/functionalspec.pdf
vrpn_android/manuals/designdoc.pdf
vrpn_android/manuals/manual.pdf
vrpn_android/comp523android/.classpath
vrpn_android/comp523android/default.properties
vrpn_android/comp523android/res/drawable-hdpi/icon.png
vrpn_android/comp523android/res/menu/controller_menu.xml
vrpn_android/comp523android/res/drawable-mdpi/icon.png
vrpn_android/comp523android/res/drawable/vrpn48.png
vrpn_android/comp523android/res/drawable/gradient.xml
vrpn_android/comp523android/res/drawable-ldpi/icon.png
vrpn_android/comp523android/res/layout/main.xml
vrpn_android/comp523android/res/values/strings.xml
vrpn_android/comp523android/jniInfo.txt
vrpn_android/comp523android/todo.txt
vrpn_android/comp523android/debugging.txt
vrpn_android/comp523android/src/edu/unc/cs/vrpn/VrpnSeekBarChangeListener.java
vrpn_android/comp523android/src/edu/unc/cs/vrpn/Main.java
vrpn_android/comp523android/src/edu/unc/cs/vrpn/JniBuilder.java
vrpn_android/comp523android/src/edu/unc/cs/vrpn/AccelerometerListener.java
vrpn_android/comp523android/src/edu/unc/cs/vrpn/ButtonListener.java
vrpn_android/comp523android/src/jni/JniLayer.java
vrpn_android/comp523android/.project
vrpn_android/comp523android/AndroidManifest.xml
vrpn_android/README.txt
vrpn_android/index.htm
vrpn_Qt_GUI_server/vrpn_Qt.h
vrpn_Qt_GUI_server/vrpn_Qt.C
vrpn_Qt_GUI_server/vrpn_Qt_AppExample/CMakeLists.txt
vrpn_Qt_GUI_server/vrpn_Qt_AppExample/vrpn_Qt_AppExample.cpp
vrpn_Qt_GUI_server/vrpn_Qt_AppExample/MainWindow.cpp
vrpn_Qt_GUI_server/vrpn_Qt_AppExample/MainWindow.h
vrpn_Qt_GUI_server/vrpn_Qt_AppExample/vrpn_Qt_AppExample.bat
vrpn_Qt_GUI_server/vrpn_Qt_AppExample/MainWindow.ui
vrpn_Qt_GUI_server/README.txt
vrpn_Qt_GUI_server/cmake/FindVRPN.cmake
vrpn_Qt_GUI_server/cmake/Findquatlib.cmake
vrpn_Qt_GUI_server/CMakeLists.txt
#!/bin/sh
function SourceFile()
{
cat <<EOS
<File
RelativePath="${1}"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
EOS
}
function HeaderFile()
{
cat <<EOS
<File
RelativePath="${1}"
>
</File>
EOS
}
function CleanFileList()
{
sort -f | grep --invert-match "Android" | grep --invert-match "Atmel"
}
function GenerateFilesSection()
{
cat << EOS
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
>
EOS
for src in $(ls vrpn_*.C vrpn_*.cpp | CleanFileList)
do
SourceFile $src
done
cat <<EOS
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl"
>
EOS
for header in $(ls vrpn_*.h | CleanFileList)
do
HeaderFile $header
done
cat <<EOS
</Filter>
</Files>
EOS
}
function GenerateVrpnVCPROJ()
{
cat <<'EOS'
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="vrpn"
ProjectGUID="{7EE1DB03-16A5-4465-9164-061BE0C88B8C}"
RootNamespace="vrpn"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Release|Win32"
OutputDirectory=".\pc_win32/Release"
IntermediateDirectory=".\pc_win32/Release"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="&quot;$(SYSTEMDRIVE)\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&quot;;../dtrack;quat;../isense;../Dtrack;../libfreespace/include;&quot;$(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include&quot;;&quot;$(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\Include&quot;;&quot;$(SYSTEMDRIVE)\sdk\cpp&quot;;&quot;$(SYSTEMDRIVE)\Program Files\boost\boost_1_34_1&quot;;./submodules/hidapi/hidapi;&quot;$(SYSTEMDRIVE)\Program Files\libusb-1.0\libusb&quot;"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS,VRPNDLL_NOEXPORTS"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\pc_win32/Release/vrpn.pch"
AssemblerListingLocation=".\pc_win32/Release/"
ObjectFile=".\pc_win32/Release/"
ProgramDataBaseFileName=".\pc_win32/Release/"
BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\pc_win32/Release\vrpn.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\pc_win32/Release/vrpn.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\pc_win32/Debug"
IntermediateDirectory=".\pc_win32/Debug"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(SYSTEMDRIVE)\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&quot;;../dtrack;quat;../isense;../Dtrack;../libfreespace/include;&quot;$(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include&quot;;&quot;$(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\Include&quot;;&quot;$(SYSTEMDRIVE)\sdk\cpp&quot;;&quot;$(SYSTEMDRIVE)\Program Files\boost\boost_1_34_1&quot;;./submodules/hidapi/hidapi;&quot;$(SYSTEMDRIVE)\Program Files\libusb-1.0\libusb&quot;"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS,VRPNDLL_NOEXPORTS"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\pc_win32/Debug/vrpn.pch"
AssemblerListingLocation=".\pc_win32/Debug/"
ObjectFile=".\pc_win32/Debug/"
ProgramDataBaseFileName=".\pc_win32/Debug/"
BrowseInformation="1"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile=".\pc_win32/Debug\vrpn.lib"
SuppressStartupBanner="true"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\pc_win32/Debug/vrpn.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
EOS
GenerateFilesSection
cat <<EOS
<Globals>
</Globals>
</VisualStudioProject>
EOS
}
function GenerateVrpnDLLVCPROJ()
{
cat <<'EOS'
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="vrpndll"
ProjectGUID="{5F38B32E-B5AE-4316-B15E-9E21D033B1BE}"
RootNamespace="vrpndll"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\pc_win32/DLL/Debug"
IntermediateDirectory=".\pc_win32/DLL/Debug"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\pc_win32/DLL/Debug/vrpndll.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;$(SYSTEMDRIVE)\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&quot;;quat;../isense;../Dtrack;../libfreespace/include;&quot;$(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include&quot;;&quot;$(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\Include&quot;;&quot;$(SYSTEMDRIVE)\sdk\cpp&quot;;&quot;$(SYSTEMDRIVE)\Program Files\boost\boost_1_34_1&quot;;./submodules/hidapi/hidapi;&quot;$(SYSTEMDRIVE)\Program Files\libusb-1.0\libusb&quot;"
PreprocessorDefinitions="VRPNDLL_EXPORTS,_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
PrecompiledHeaderFile=".\pc_win32/DLL/Debug/vrpndll.pch"
AssemblerListingLocation=".\pc_win32/DLL/Debug/"
ObjectFile=".\pc_win32/DLL/Debug/"
ProgramDataBaseFileName=".\pc_win32/DLL/Debug/"
WarningLevel="3"
SuppressStartupBanner="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
IgnoreImportLibrary="true"
OutputFile=".\pc_win32/DLL/Debug/vrpndll.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="$(SYSTEMDRIVE)\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib,$(SYSTEMDRIVE)\sdk\cpp,$(SYSTEMDRIVE)\Program Files\boost\boost_1_34_1\lib"
GenerateDebugInformation="true"
ProgramDatabaseFile=".\pc_win32/DLL/Debug/vrpndll.pdb"
ImportLibrary=".\pc_win32\DLL\Debug\vrpndll.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\pc_win32/DLL/Debug/vrpndll.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\pc_win32/DLL/Release"
IntermediateDirectory=".\pc_win32/DLL/Release"
ConfigurationType="2"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="1"
TypeLibraryName=".\pc_win32/DLL/Release/vrpndll.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="&quot;$(SYSTEMDRIVE)\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&quot;;quat;../isense;../Dtrack;../libfreespace/include;&quot;$(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include&quot;;&quot;$(SYSTEMDRIVE)\Program Files\National Instruments\NI-DAQ\Include&quot;;&quot;$(SYSTEMDRIVE)\sdk\cpp&quot;;&quot;$(SYSTEMDRIVE)\Program Files\boost\boost_1_34_1&quot;;./submodules/hidapi/hidapi;&quot;$(SYSTEMDRIVE)\Program Files\libusb-1.0\libusb&quot;"
PreprocessorDefinitions="VRPNDLL_EXPORTS,_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
PrecompiledHeaderFile=".\pc_win32/DLL/Release/vrpndll.pch"
AssemblerListingLocation=".\pc_win32/DLL/Release/"
ObjectFile=".\pc_win32/DLL/Release/"
ProgramDataBaseFileName=".\pc_win32/DLL/Release/"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
IgnoreImportLibrary="true"
OutputFile=".\pc_win32/DLL/Release/vrpndll.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="$(SYSTEMDRIVE)\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib,$(SYSTEMDRIVE)\sdk\cpp,$(SYSTEMDRIVE)\Program Files\boost\boost_1_34_1\lib"
ProgramDatabaseFile=".\pc_win32/DLL/Release/vrpndll.pdb"
ImportLibrary=".\pc_win32\DLL\Release\vrpndll.lib"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
SuppressStartupBanner="true"
OutputFile=".\pc_win32/DLL/Release/vrpndll.bsc"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
EOS
GenerateFilesSection
cat <<EOS
<Globals>
</Globals>
</VisualStudioProject>
EOS
}
GenerateVrpnVCPROJ > vrpn.vcproj
dos2unix --u2d vrpn.vcproj
GenerateVrpnDLLVCPROJ > vrpndll.vcproj
dos2unix --u2d vrpndll.vcproj
# | sed 's|^\(.*\)$|<File RelativePath="\1"></File>|'
Debug
*.ncb
*.suo
if(WIN32)
ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
endif()
set(GPSNMEALIB_PUBLIC_HEADERS
nmeaParser.h
utmCoord.h
latLonCoord.h)
set(GPSNMEALIB_SOURCES
latLonCoord.C
nmeaParser.C
typedCoord.h
typedCoord.C
utmCoord.C)
add_library(gpsnmea ${GPSNMEALIB_PUBLIC_HEADERS} ${GPSNMEALIB_SOURCES})
set_property(TARGET
gpsnmea
PROPERTY
PUBLIC_HEADER
${GPSNMEALIB_PUBLIC_HEADERS})
set_property(TARGET gpsnmea PROPERTY FOLDER "Library")
if(VRPN_INSTALL)
install(TARGETS
gpsnmea
ARCHIVE
DESTINATION
lib
COMPONENT
serversdk
PUBLIC_HEADER
DESTINATION
include
COMPONENT
serversdk)
endif()
\ No newline at end of file
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="gpsnmealib"
ProjectGUID="{D60E311B-657F-444E-9A0E-5218B37D5551}"
RootNamespace="gpsnmealib"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../"
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\latLonCoord.C"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\nmeaParser.C"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\typedCoord.C"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\utmCoord.C"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\latLonCoord.h"
>
</File>
<File
RelativePath=".\nmeaParser.h"
>
</File>
<File
RelativePath=".\typedCoord.h"
>
</File>
<File
RelativePath=".\utmCoord.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
// LatLonCoord.cpp: Implementation of the CLatLonCoord class.
//
// Written by Jason Bevins in 1998. File is in the public domain.
//
#include "gpsnmealib/typedCoord.h" // for TypedCoord
#include "latLonCoord.h"
#ifdef sgi
#include <assert.h>
#include <math.h>
#include <stdio.h>
#else
#include <cassert> // for assert
#include <cmath> // for fabs
#include <cstdio> // for sprintf
#endif
// Format strings for the degree-to-string conversion functions.
// Note that east/west (EW) has a different set of format strings as north/
// south (NS), as integer degrees in east/west can have up to three digits
// instead of two.
static const char formatD_NS[] = "%c %02d.%05d*";
static const char formatDM_NS[] = "%c %02d*%02d.%03d'";
static const char formatDMS_NS[] = "%c %02d*%02d'%02d.%01d\x22";
static const char formatD_EW[] = "%c %03d.%05d*";
static const char formatDM_EW[] = "%c %03d*%02d.%03d'";
static const char formatDMS_EW[] = "%c %03d*%02d'%02d.%01d\x22";
/////////////////////////////////////////////////////////////////////////////
// LatLonCoord construction/destruction
LatLonCoord::LatLonCoord (): TypedCoord ()
{
// Set the default output coordinate format to decimal degrees.
m_latLonFormat = FORMAT_D;
}
LatLonCoord::LatLonCoord (double lat, double lon)
{
m_lat = lat;
m_lon = lon;
// Set the default output coordinate format to decimal degrees.
m_latLonFormat = FORMAT_D;
}
LatLonCoord::LatLonCoord (const LatLonCoord& other)
{
copyLatLonCoord (other);
}
LatLonCoord::LatLonCoord (const TypedCoord& other)
{
m_latLonFormat = FORMAT_D;
copyOtherCoord (other);
}
/////////////////////////////////////////////////////////////////////////////
// LatLonCoord operators
LatLonCoord& LatLonCoord::operator= (const LatLonCoord& other)
{
copyLatLonCoord (other);
return *this;
}
LatLonCoord& LatLonCoord::operator= (const TypedCoord& other)
{
copyOtherCoord (other);
return *this;
}
/////////////////////////////////////////////////////////////////////////////
// LatLonCoord members
void LatLonCoord::copyLatLonCoord (const LatLonCoord& other)
// Purpose:
// This function copies the lat/lon coordinate of the specified object and
// assigns that coordinate to this object.
{
m_lat = other.m_lat;
m_lon = other.m_lon;
}
void LatLonCoord::copyOtherCoord (const TypedCoord& other)
// Purpose:
// This function copies the coordinate of the specified object, converts
// the coordinate to the coordinate type of this object, then assigns the
// converted coordinate to this object.
{
// Convert the right hand side coordinate to lat/lon; then store these
// lat/lon values in this coordinate.
other.getLatLonCoord (m_lat, m_lon);
}
const std::string& LatLonCoord::createCoordString(std::string& coordString) const
// Purpose:
// This function creates a formatted coordinate string containing this
// object's coordinate value.
// Parameters:
// std::string& coordString:
// Upon exit, this parameter will contain the generated coordinate
// string
// Returns:
// A reference to the generated coordinate string.
// Notes:
// The string can be in one of three different formats (degrees, degrees and
// decimal minutes, or degrees, minutes, and decimal seconds.) Set the
// format by calling the SetCurrentLatLonFormat() member function.
{
std::string latString;
std::string lonString;
// Create the formatted lat/lon strings; the format is specified by the
// m_currentLatLonFormat member variable
degreeToString (latString, m_lat, HEMISPHERE_NS);
degreeToString (lonString, m_lon, HEMISPHERE_EW);
coordString = latString + ", " + lonString;
return coordString;
}
void LatLonCoord::createDisplayStrings (std::string& topLeftString,
std::string& topRightString, std::string& bottomLeftString,
std::string& bottomRightString) const
// Purpose:
// This function creates four strings that can be used for display; these
// strings contain coordinate data. The four strings are for the top left,
// top right, bottom left, and bottom right text of a display; each string
// is specified as follows:
// - top left: North/south hemisphere character
// - top right: Latitude
// - bottom left: East/west hemisphere character
// - bottom right: Longitude
// Notes:
// It is up to the calling function to write these strings to the display.
{
std::string coordString;
createCoordString (coordString);
#if 0
// Extract the elements of the coordinate string.
switch (getLatLonFormat ()) {
case FORMAT_D:
topLeftString = coordString.Mid (LAT_D_HPPEMISPHERE_POS,
LAT_D_HPPEMISPHERE_LEN);
topRightString = coordString.Mid (LAT_D_DEGREE_POS,
LAT_D_DEGREE_LEN);
bottomLeftString = coordString.Mid (LON_D_HPPEMISPHERE_POS,
LON_D_HPPEMISPHERE_LEN);
bottomRightString = coordString.Mid (LON_D_DEGREE_POS,
LON_D_DEGREE_LEN);
break;
case FORMAT_DM:
topLeftString = coordString.Mid (LAT_DM_HPPEMISPHERE_POS,
LAT_DM_HPPEMISPHERE_LEN);
topRightString = coordString.Mid (LAT_DM_DEGREE_POS,
LAT_DM_DEGREE_LEN);
bottomLeftString = coordString.Mid (LON_DM_HPPEMISPHERE_POS,
LON_DM_HPPEMISPHERE_LEN);
bottomRightString = coordString.Mid (LON_DM_DEGREE_POS,
LON_DM_DEGREE_LEN);
break;
case FORMAT_DMS:
topLeftString = coordString.Mid (LAT_DMS_HPPEMISPHERE_POS,
LAT_DMS_HPPEMISPHERE_LEN);
topRightString = coordString.Mid (LAT_DMS_DEGREE_POS,
LAT_DMS_DEGREE_LEN);
bottomLeftString = coordString.Mid (LON_DMS_HPPEMISPHERE_POS,
LON_DMS_HPPEMISPHERE_LEN);
bottomRightString = coordString.Mid (LON_DMS_DEGREE_POS,
LON_DMS_DEGREE_LEN);
break;
default:
ASSERT (FALSE);
}
#endif
}
void LatLonCoord::createXYCoordStrings (std::string& xString, std::string& yString)
const
// Purpose:
// This function generates two strings: a string containing the longitude
// (stored in the parameter xString), and a string containing the latitude
// (stored in the parameter yString.)
// Notes:
// The string can be in one of three different formats (degrees, degrees and
// decimal minutes, or degrees, minutes, and decimal seconds); Set the
// format by calling the SetCurrentLatLonFormat() member function.
{
degreeToString (xString, m_lon, HEMISPHERE_EW);
degreeToString (yString, m_lat, HEMISPHERE_NS);
}
const std::string& LatLonCoord::degreeToD (std::string& output, double degree,
HEMISPHERE_DIRECTION direction) const
// Purpose:
// This function converts a value specified in decimal degrees to a string
// formatted as H DDD.DDDDD*.
// Pre:
// -180.0 <= degree <= 180.0
// Parameters:
// std::string& output:
// Upon exit, this parameter contains the converted string.
// double degree:
// The degree value to convert.
// HEMISPHERE_DIRECTION direction:
// The direction of the hemisphere, either north/south or east/west.
// This value determines the hemisphere character in the converted
// string.
// Returns:
// The converted string.
{
char hemisphereChar = getHemisphereChar (degree, direction);
double positiveDegrees = fabs (degree);
// A "unit" is measured in 1/100000ths of a degree; this is the smallest
// possible unit when coordinates are expressed as DDD.DDDDD.
// (Calculating the degree and the 1/100000th degree parts as integers
// avoid rounding errors in the final result.)
int units = (int)((positiveDegrees * 100000.0) + 0.5);
int intDegrees = units / 100000;
int int100ThousandthDegrees = units % 100000;
const char* pFormatString;
char tempString[1000];
if (direction == HEMISPHERE_NS) {
pFormatString = formatD_NS;
} else {
pFormatString = formatD_EW;
}
sprintf(tempString, pFormatString, hemisphereChar, intDegrees,
int100ThousandthDegrees);
output = tempString;
return output;
}
const std::string& LatLonCoord::degreeToDM (std::string& output, double degree,
HEMISPHERE_DIRECTION direction) const
// Purpose:
// Same as DegreeToD, except the string is formatted as H DDD*MM.MMM'.
// Pre:
// -180.0 <= degree <= 180.0
{
char hemisphereChar = getHemisphereChar (degree, direction);
double positiveDegrees = fabs (degree);
// A "unit" is measured in 1/1000ths of a minute (or 1/60000 of a degree);
// this is the smallest possible unit when coordinates are expressed as
// DDD MM.MMM. (Calculating the degree, minute, and the 1/1000th minute
// parts as integers avoid rounding errors in the final result.)
int units = (int)((positiveDegrees * 60000.0) + 0.5);
int intDegrees = units / 60000;
int intDegreesInUnits = intDegrees * 60000;
int intMinutes = (units - intDegreesInUnits) / 1000;
int intThousandthMinutes = (units - intDegreesInUnits) % 1000;
const char* pFormatString;
char tempString[1000];
if (direction == HEMISPHERE_NS) {
pFormatString = formatDM_NS;
} else {
pFormatString = formatDM_EW;
}
sprintf(tempString, pFormatString, hemisphereChar,
intDegrees, intMinutes, intThousandthMinutes);
output = tempString;
return output;
}
const std::string& LatLonCoord::degreeToDMS (std::string& output, double degree,
HEMISPHERE_DIRECTION direction) const
// Purpose:
// Same as DegreeToD, except the string is formatted as H DDD*MM'SS.S".
// Pre:
// -180.0 <= degree <= 180.0
{
char hemisphereChar = getHemisphereChar (degree, direction);
double positiveDegrees = fabs (degree);
// A "unit" is measured in 1/10ths of a second (or 1/36000 of a degree);
// this is the smallest possible unit when coordinates are expressed as
// DDD MM SS.S. (Calculating the degree, minute, second, and the 1/10th
// second parts as integers will avoid rounding errors in the final
// result.)
int units = (int)((positiveDegrees * 36000.0) + 0.5);
int intDegrees = units / 36000;
int intDegreesInUnits = intDegrees * 36000;
int intMinutes = (units - intDegreesInUnits) / 600;
int intMinutesInUnits = intMinutes * 600;
int intSeconds = (units - intDegreesInUnits - intMinutesInUnits) / 10;
int intTenthSeconds = (units - intDegreesInUnits - intMinutesInUnits) % 10;
const char* pFormatString;
char tempString[1000];
if (direction == HEMISPHERE_NS) {
pFormatString = formatDMS_NS;
} else {
pFormatString = formatDMS_EW;
}
sprintf(tempString, pFormatString, hemisphereChar,
intDegrees, intMinutes, intSeconds, intTenthSeconds);
output = tempString;
return output;
}
const std::string& LatLonCoord::degreeToString (std::string& output, double degree,
HEMISPHERE_DIRECTION direction) const
// Purpose:
// This function converts a value specified in decimal degrees to a formatted
// string.
// Pre:
// -180.0 <= degree <= 180.0
// Parameters:
// std::string& output:
// Upon exit, this parameter contains the converted string.
// double degree:
// The degree value to convert.
// HEMISPHERE_DIRECTION direction:
// The direction of the hemisphere, either north/south or east/west.
// This value determines the hemisphere character in the converted
// string.
// Returns:
// The converted string.
// Notes:
// If formatType is FORMAT_D, the returned string format is H DDD.DDDDD*.
// If formatType is FORMAT_DM, the returned string format is H DDD*MM.MMM'.
// If formatType is FORMAT_DMS, the returned string format is H DDD*MM'SS.S".
{
switch (m_latLonFormat) {
case FORMAT_DMS:
return degreeToDMS (output, degree, direction);
break;
case FORMAT_DM:
return degreeToDM (output, degree, direction);
break;
case FORMAT_D:
return degreeToD (output, degree, direction);
break;
default:
assert(false);
return output; // needed to stop compiler warning.
}
}
void LatLonCoord::getXYCoord (double& x, double& y) const
// Purpose:
// This function returns the (x, y) coordinate stored within this object.
// In this class, the x coordinate is the longitude and the y coordinate is
// the latitude.
{
x = m_lon;
y = m_lat;
}
char LatLonCoord::getHemisphereChar (double degree,
HEMISPHERE_DIRECTION direction) const
// Purpose:
// This function determine the appropriate hemisphere character ('N', 'S',
// 'E', 'W') given the degree value and the hemisphere direction (north/south
// or east/west).
// Returns:
// 'N' if direction is HEMISPHERE_NS and degree is positive.
// 'S' if direction is HEMISPHERE_NS and degree is negative.
// 'E' if direction is HEMISPHERE_EW and degree is positive.
// 'W' if direction is HEMISPHERE_EW and degree is negative.
{
if (direction == HEMISPHERE_NS) {
if (degree >= 0.0) {
return 'N';
} else {
return 'S';
}
} else {
if (degree >= 0.0) {
return 'E';
} else {
return 'W';
}
}
}
// LatLonCoord.h: Definition of the CLatLonCoord class.
//
// The CLatLonCoord class, derived from the CTypedCoord class, represents a
// lat/lon coordinate. Since this class contains an internal lat/lon
// coordinate from CTypedCoord, no conversion functions are necessary.
//
// The formatted coordinate string generated by the CreateCoordString() member
// function can be in one of the three following formats:
// - Degrees (H DD.DDDDD*, H DDD.DDDDD*); this is the default.
// - Degrees, and decimal minutes (H DD*MM.MMM'. H DDD* MM.MMM')
// - Degrees, minutes, and decimal seconds (H DD*MM'SS.S", H DDD*MM'SS.S")
//
// The coordinate string format is set by calling the SetCurrentLatLonFormat()
// member function.
//
// Written by Jason Bevins in 1998. File is in the public domain.
//
#ifndef __LAT_LON_CPPOORD_HPP
#define __LAT_LON_CPPOORD_HPP
#include <string> // for string
#include "typedCoord.h" // for COORD_TYPE, etc
enum HEMISPHERE_DIRECTION
{
HEMISPHERE_NS = 0,
HEMISPHERE_EW = 1
};
enum COORD_LATLON_FORMAT
{
FORMAT_D = 0,
FORMAT_DM = 1,
FORMAT_DMS = 2
};
// These constants are used by the CreateDisplayStrings() and the
// CreateXYCoordStrings() functions to parse the string generated by the
// CreateCoordString() function. Modify these constants when you modify the
// code that generates the string. These constants do not affect the code
// that generate these strings, but you may write parsing functions that
// require the positions of the individual elements in the strings.
const int LAT_D_HPPEMISPHERE_POS = 0;
const int LAT_D_HPPEMISPHERE_LEN = 1;
const int LON_D_HPPEMISPHERE_POS = 13;
const int LON_D_HPPEMISPHERE_LEN = 1;
const int LAT_D_DEGREE_POS = 2;
const int LAT_D_DEGREE_LEN = 9;
const int LON_D_DEGREE_POS = 15;
const int LON_D_DEGREE_LEN = 10;
const int LAT_DM_HPPEMISPHERE_POS = 0;
const int LAT_DM_HPPEMISPHERE_LEN = 1;
const int LON_DM_HPPEMISPHERE_POS = 14;
const int LON_DM_HPPEMISPHERE_LEN = 1;
const int LAT_DM_DEGREE_POS = 2;
const int LAT_DM_DEGREE_LEN = 10;
const int LON_DM_DEGREE_POS = 16;
const int LON_DM_DEGREE_LEN = 11;
const int LAT_DMS_HPPEMISPHERE_POS = 0;
const int LAT_DMS_HPPEMISPHERE_LEN = 1;
const int LON_DMS_HPPEMISPHERE_POS = 15;
const int LON_DMS_HPPEMISPHERE_LEN = 1;
const int LAT_DMS_DEGREE_POS = 2;
const int LAT_DMS_DEGREE_LEN = 11;
const int LON_DMS_DEGREE_POS = 17;
const int LON_DMS_DEGREE_LEN = 12;
const char DEGREE_CHAR = '*';
class LatLonCoord: public TypedCoord
{
public:
LatLonCoord ();
LatLonCoord (double lat, double lon);
LatLonCoord (const TypedCoord& other);
LatLonCoord (const LatLonCoord& other);
LatLonCoord& operator= (const LatLonCoord& other);
LatLonCoord& operator= (const TypedCoord& other);
void copyLatLonCoord (const LatLonCoord& other);
void copyOtherCoord (const TypedCoord& other);
virtual const std::string& createCoordString (std::string& coordString) const;
virtual void createDisplayStrings (std::string& topLeftString,
std::string& topRightString, std::string& bottomLeftString,
std::string& bottomRightString) const;
virtual void createXYCoordStrings (std::string& xString, std::string& yString)
const;
virtual COORD_TYPE getCoordType () const {return COORD_LATLON;}
COORD_LATLON_FORMAT getLatLonFormat () const
{return m_latLonFormat;}
virtual void getXYCoord (double& x, double& y) const;
void setLatLonFormat (COORD_LATLON_FORMAT latLonFormat)
{m_latLonFormat = latLonFormat;}
protected:
// Conversion functions for each of the three lat/lon formats.
const std::string& degreeToD (std::string& output, double degree,
HEMISPHERE_DIRECTION direction) const;
const std::string& degreeToDM (std::string& output, double degree,
HEMISPHERE_DIRECTION direction) const;
const std::string& degreeToDMS (std::string& output, double degree,
HEMISPHERE_DIRECTION direction) const;
const std::string& degreeToString (std::string& output, double degree,
HEMISPHERE_DIRECTION formatType) const;
char getHemisphereChar (double degree, HEMISPHERE_DIRECTION direction)
const;
// Current lat/lon format in one of three format types.
COORD_LATLON_FORMAT m_latLonFormat;
};
#endif
// NmeaParser.cpp: Implementation of the NMEA-0183 2.0 parser class.
//
// Written by Jason Bevins in 1998. File is in the public domain.
//
#ifdef sgi
#include <stdlib.h>
#include <string.h>
#else
#include <cstdlib> // for atof, atoi, atol
#endif
#include "nmeaParser.h"
// This constant define the length of the date string in a sentence.
const int DATE_LEN = 6;
/////////////////////////////////////////////////////////////////////////////
// NMEAData construction/destruction
NMEAData::NMEAData ()
{
// The constructor for the NMEAData object clears all data and resets the
// times of last acquisition to 0.
reset ();
// No coordinate has ever been valid since this object was created.
hasCoordEverBeenValid = false;
}
/////////////////////////////////////////////////////////////////////////////
// NMEAData methods
void NMEAData::reset()
// Purpose:
// This function resets all the data in this object to its defaults.
{
// Reset the data.
lat = 0.0;
lon = 0.0;
altitude = 0.0;
speed = 0.0;
UTCYear = 94;
UTCMonth = 6;
UTCDay = 1;
UTCHour = 0;
UTCMinute = 0;
UTCSecond = 0;
track = 0.0;
magVariation = 0.0;
hdop = 1.0;
eStd = 1.0;
nStd = 1.0;
numSats = 0;
// All data stored by this object is currently invalid.
isValidLat = false;
isValidLon = false;
isValidAltitude = false;
isValidSpeed = false;
isValidDate = false;
isValidTime = false;
isValidTrack = false;
isValidMagVariation = false;
isValidHdop = false;
isValidNStd = false;
isValidEStd = false;
isValidZStd = false;
isValidHStd = false;
isValidSatData = false;
isValidRangeResidualData = false;
isValidFixQuality = false;
// Last fix was invalid.
lastFixQuality = FIX_AUTONOMOUS;
// Still waiting for the frame to start...
waitingForStart = true;
// Clear what messages have been seen
seenZDA = false;
seenGGA = false;
seenGLL = false;
seenRMC = false;
seenGSV = false;
seenGST = false;
seenVTG = false;
seenRRE = false;
}
/////////////////////////////////////////////////////////////////////////////
// NMEAParser construction/destruction
NMEAParser::NMEAParser () //sj: log4cpp::Category& l) : logger(l)
{
m_data = new NMEAData();
// by default, we'll look for "RMC" message to signify a new sequence of messages
strcpy(startSentence, "RMC");
// Defaults for the GSV sentence parser.
m_lastSentenceNumber = 1;
m_numSentences = 1;
m_numSatsExpected = 0;
m_numSatsLeft = 0;
m_satArrayPos = 0;
}
NMEAParser::NMEAParser (NMEAData* data)//sj: log4cpp::Category& l, NMEAData* data) : logger(l)
{
m_data = data;
// Defaults for the GSV sentence parser.
m_lastSentenceNumber = 1;
m_numSentences = 1;
m_numSatsExpected = 0;
m_numSatsLeft = 0;
m_satArrayPos = 0;
}
NMEAParser::~NMEAParser ()
{
delete m_data;
m_data = 0;
}
void NMEAParser::parseZDA(const char* sentence)
{
m_data->seenZDA=true;
char field[255];
uint_ currentPos = 0;
bool isMore = true; // More strings to parse?
// Skip past the '$xxZDA'
if ((isMore = getNextField (field, sentence, currentPos)) == false)
{
return;
}
// UTC time.
isMore = getNextField (field, sentence, currentPos);
parseAndValidateTime (field);
}
void NMEAParser::parseGGA (const char* sentence)
// Purpose:
// This function parses a GGA sentence; all data will be stored in the
// NMEAData object within this class. This function will correctly parse
// a partial GGA sentence.
// Pre:
// The string to parse must be a valid GGA sentence.
{
m_data->seenGGA=true;
char field[255];
char hemisphereField[32];
char hemisphereChar;
char unitField[32];
char unitChar;
uint_ currentPos = 0;
bool isMore = true; // More strings to parse?
// Skip past the '$xxGGA'
if ((isMore = getNextField (field, sentence, currentPos)) == false)
{
return;
}
// UTC time.
isMore = getNextField (field, sentence, currentPos);
parseAndValidateTime (field);
if (isMore == false) return;
// Latitude.
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
isMore = getNextField (hemisphereField, sentence, currentPos);
if (strlen (hemisphereField) != 0) {
hemisphereChar = hemisphereField[0];
} else {
hemisphereChar = ' ';
}
parseAndValidateLat (field, hemisphereChar);
if (isMore == false) return;
// Longitude.
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
isMore = getNextField (hemisphereField, sentence, currentPos);
if (strlen (hemisphereField) != 0) {
hemisphereChar = hemisphereField[0];
} else {
hemisphereChar = ' ';
}
parseAndValidateLon (field, hemisphereChar);
if (isMore == false) return;
// Quality of GPS fix.
isMore = getNextField (field, sentence, currentPos);
parseAndValidateFixQuality (field);
if (isMore == false) return;
// Skip number of sats tracked for now.
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Horizontal dilution of precision (HDOP).
isMore = getNextField (field, sentence, currentPos);
parseAndValidateHdop (field);
if (isMore == false) return;
// Altitude.
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
isMore = getNextField (unitField, sentence, currentPos);
if (strlen (unitField) != 0) {
unitChar = unitField[0];
} else {
unitChar = ' ';
}
parseAndValidateAltitude (field, unitChar);
if (isMore == false) return;
// Everything else (geoid height and DGPS info) is ignored for now.
return;
}
void NMEAParser::parseGLL (const char* sentence)
// Purpose:
// This function parses a GLL sentence; all data will be stored in the
// NMEAData object within this class. This function will correctly parse
// a partial GLL sentence.
// Pre:
// The string to parse must be a valid GLL sentence.
{
m_data->seenGLL=true;
char field[255];
char hemisphereField[32];
char hemisphereChar;
uint_ currentPos = 0;
bool isMore = true; // More strings to parse?
// Count commas in this sentence to see if it's valid.
if (countChars (sentence, ',', SENTENCE_GLL_COMMAS) < 0) return;
// Skip past the '$xxGLL'
if ((isMore = getNextField (field, sentence, currentPos)) == false) {
return;
}
// Latitude
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
isMore = getNextField (hemisphereField, sentence, currentPos);
if (strlen (hemisphereField) != 0) {
hemisphereChar = hemisphereField[0];
} else {
hemisphereChar = ' ';
}
parseAndValidateLat (field, hemisphereChar);
if (isMore == false) return;
// Longitude
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
isMore = getNextField (hemisphereField, sentence, currentPos);
if (strlen (hemisphereField) != 0) {
hemisphereChar = hemisphereField[0];
} else {
hemisphereChar = ' ';
}
parseAndValidateLon (field, hemisphereChar);
if (isMore == false) return;
// UTC time
isMore = getNextField (field, sentence, currentPos);
parseAndValidateTime (field);
if (isMore == false) return;
}
void NMEAParser::parseGSV (const char* sentence)
// Purpose:
// This function parses a GSV sentence; all data will be stored in the
// NMEAData object within this class. This function will correctly parse
// a partial GSV sentence.
// Pre:
// The string to parse must be a valid GSV sentence.
// Notes:
// All GSV sentences from a single packet (a collection of NMEA sentences
// sent from the GPS) must be processed before satellite information in the
// NMEAData object is updated. There is data for only four satellites
// in each GSV sentence, so multiple sentences must be processed. For
// example, if your GPS was tracking eight satellites, two GSV sentences is
// sent from your GPS in each packet; both sentences must be parsed before
// the NMEAData object is updated with the satellite information.
{
m_data->seenGSV=true;
char field[255];
uint_ numSats;
int numSentences;
int sentenceNumber;
uint_ currentPos = 0;
bool isMore = true; // More strings to parse?
// Count commas in this sentence to see if it's valid.
if (countChars (sentence, ',', SENTENCE_GSV_COMMAS) < 0) return;
// Skip past the '$xxGSV'
if ((isMore = getNextField (field, sentence, currentPos)) == false) {
return;
}
// Determine the number of sentences that will make up the satellite data.
isMore = getNextField (field, sentence, currentPos);
numSentences = atoi (field);
if (isMore == false) return;
// Which sentence is this?.
isMore = getNextField (field, sentence, currentPos);
sentenceNumber = atoi (field);
if (isMore == false) return;
// How many satellites are in total?
isMore = getNextField (field, sentence, currentPos);
numSats = atoi (field);
if (isMore == false) return;
// Is this the first sentence? If so, reset the satellite information.
if (sentenceNumber == 1) {
m_lastSentenceNumber = 1;
m_numSentences = numSentences;
m_numSatsExpected = numSats;
m_numSatsLeft = numSats;
m_satArrayPos = 0;
} else {
// Make sure the satellite strings are being sent in order. If not,
// then you're screwed.
if (sentenceNumber != m_lastSentenceNumber + 1) return;
// BUGFIX:
// Added by Clarke Brunt 20001112
m_lastSentenceNumber = sentenceNumber;
}
// parse the satellite string. There are four satellite info fields per
// sentence.
int i;
for (i = 0; i < 4; i++) {
getNextField (field, sentence, currentPos);
if (strlen (field) != 0) {
m_tempSatData[m_satArrayPos].prn = atoi (field);
getNextField (field, sentence, currentPos);
if (strlen (field) != 0) {
m_tempSatData[m_satArrayPos].elevation = atoi (field);
}
getNextField (field, sentence, currentPos);
if (strlen (field) != 0) {
m_tempSatData[m_satArrayPos].azimuth = atoi (field);
}
getNextField (field, sentence, currentPos);
if (strlen (field) != 0) {
m_tempSatData[m_satArrayPos].strength = atoi (field);
}
--m_numSatsLeft;
++m_satArrayPos;
} else {
// Jump past the next three fields.
for (int j = 0; j < 3; j++)
getNextField (field, sentence, currentPos);
}
}
// If all the satellite information has been received, then update the
// NMEAData object with the new satellite data.
if (m_numSatsLeft == 0) {
for (i = 0; i < m_numSatsExpected; i++) {
m_data->satData[i] = m_tempSatData[i];
}
m_data->numSats = m_numSatsExpected;
m_data->isValidSatData = true;
}
}
void NMEAParser::parseRRE (const char* sentence)
{
m_data->seenRRE=true;
bool isMore;
char field[255];
uint_ currentPos = 0;
// Skip past the '$xxRMC'
if ((isMore = getNextField (field, sentence, currentPos)) == false)
{
return;
}
isMore = getNextField (field, sentence, currentPos);
// I assume the RRE numSats is the same as the RRE numSats!
m_data->numSats = atoi(field);
// Skip the intermediate stuff
for (uint_ i = 0; i < m_data->numSats; i++)
{
isMore = getNextField (field, sentence, currentPos);
if (isMore == false)
{
//sj: logger.error("only read %d out of %d entries", m_data->numSats, i);
return;
}
m_data->rrData[i].prn = atoi(field);
isMore = getNextField (field, sentence, currentPos);
if (isMore == false)
{
//sj: logger.error("only read %d out of %d entries", m_data->numSats, i);
return;
}
m_data->rrData[i].residual = atof(field);
}
m_data->isValidRangeResidualData = true;
// Now read the horizontal
isMore = getNextField (field, sentence, currentPos);
if (isMore == false)
{
// sj: logger.error("no fields left to read hStd");
return;
}
m_data->hStd = atof(field);
m_data->isValidHStd = true;
// Now read the vertical
isMore = getNextField (field, sentence, currentPos);
m_data->zStd = atof(field);
m_data->isValidZStd = true;
//sj: logger.debug("isValidRangeResidualData=%d",
//sj: m_data->isValidRangeResidualData);
//sj: logger.debug("isValidHStd=%d", m_data->isValidHStd);
//sj: logger.debug("isValidZStd=%d", m_data->isValidZStd);
}
void NMEAParser::parseRMC (const char* sentence)
// Purpose:
// This function parses an RMC sentence; all data will be stored in the
// NMEAData object within this class. This function will correctly parse
// a partial RMC sentence.
// Pre:
// The string to parse must be a valid RMC sentence.
{
m_data->seenRMC=true;
char field[255];
char hemisphereField[32];
char hemisphereChar;
char directionField[32];
char directionChar;
uint_ currentPos = 0;
bool isMore = true; // More strings to parse?
// Count commas in this sentence to see if it's valid.
if (countChars (sentence, ',', SENTENCE_RMC_COMMAS) < 0) return;
// Skip past the '$xxRMC'
if ((isMore = getNextField (field, sentence, currentPos)) == false) {
return;
}
// UTC time
isMore = getNextField (field, sentence, currentPos);
parseAndValidateTime (field);
if (isMore == false) return;
// Skip past the navigation warning indicator for now.
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Latitude
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
isMore = getNextField (hemisphereField, sentence, currentPos);
if (strlen (hemisphereField) != 0) {
hemisphereChar = hemisphereField[0];
} else {
hemisphereChar = ' ';
}
parseAndValidateLat (field, hemisphereChar);
if (isMore == false) return;
// Longitude
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
isMore = getNextField (hemisphereField, sentence, currentPos);
if (strlen (hemisphereField) != 0) {
hemisphereChar = hemisphereField[0];
} else {
hemisphereChar = ' ';
}
parseAndValidateLon (field, hemisphereChar);
if (isMore == false) return;
// Current speed, in knots.
isMore = getNextField (field, sentence, currentPos);
parseAndValidateSpeed (field);
if (isMore == false) return;
// Current track, in degrees.
isMore = getNextField (field, sentence, currentPos);
parseAndValidateTrack (field);
if (isMore == false) return;
// Current date
isMore = getNextField (field, sentence, currentPos);
parseAndValidateDate (field);
if (isMore == false) return;
// Magnetic variation (degrees from true north)
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
isMore = getNextField (directionField, sentence, currentPos);
if (strlen (directionField) != 0) {
directionChar = directionField[0];
} else {
directionChar = ' ';
}
parseAndValidateMagVariation (field, directionChar);
if (isMore == false) return;
}
void NMEAParser::parseGST (const char* sentence)
{
m_data->seenGST=true;
char field[255];
uint_ currentPos = 0;
bool isMore = true; // More strings to parse?
// Count commas in this sentence to see if it's valid.
if (countChars (sentence, ',', SENTENCE_GST_COMMAS) < 0) return;
// Skip past '$GPGST'
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Get the UTC time
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
parseAndValidateTime(field);
// This field is the RMS value of the standard deviations to the range inputs
// to the navigation process
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Skip unimplemented fields
currentPos += 3;
// Standard deviation of latitude
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Parse the north standard deviation
parseAndValidateNStd(field);
// Standard deviation of longitude
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
parseAndValidateEStd(field);
// Standard deviation of altitude
isMore = getNextField (field, sentence, currentPos);
parseAndValidateZStd(field);
}
void NMEAParser::parseVTG (const char* sentence)
{
m_data->seenVTG=true;
char field[255];
char reference[256];
uint_ currentPos = 0;
bool isMore = true; // More strings to parse?
// Count commas in this sentence to see if it's valid.
if (countChars (sentence, ',', SENTENCE_VTG_COMMAS) < 0) return;
// Skip past '$GPVTG'
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Get the COG wrt to true north
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Get the reference
isMore = getNextField (reference, sentence, currentPos);
if (isMore == false) return;
// Reference should be a 'T' to denote true north
if (reference[0] != 'T')
{
// sj: logger.warn("parseVTG: the reference should be T but it's ",
// sj: reference);
return;
}
// Get the track
parseAndValidateTrack(field);
// Get the COG wrt to magnetic north
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Get the reference
isMore = getNextField (reference, sentence, currentPos);
if (isMore == false) return;
// Reference should be a 'M' to denote wrt magnetic north
if (reference[0] != 'M')
{
// sj: logger.warn("parseVTG: the reference should be M but it's ",
// sj: reference);
return;
}
// Speed, should be in miles per hour
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Get the reference
isMore = getNextField (reference, sentence, currentPos);
if (isMore == false) return;
// Reference should be a 'N' to denote knots per hour
if (reference[0] != 'N')
{
// sj: logger.warn("parseVTG: the reference should be N but it's ",
// sj: reference);
return;
}
// Speed, should be in kilometres per hour
isMore = getNextField (field, sentence, currentPos);
if (isMore == false) return;
// Get the reference
isMore = getNextField (reference, sentence, currentPos);
// Reference should be a 'K' to denote kilometers per hour
if (reference[0] != 'K')
{
// sj: logger.warn("parseVTG: the reference should be K but it's ",
// sj: reference);
return;
}
parseAndValidateSpeed(field);
}
SENTENCE_STATUS NMEAParser::parseSentence (const char* sentence)
// Purpose:
// This function parses a given NMEA sentence. All valid information will be
// stored within the NMEAData object in this class; call the GetData()
// member function to retrieve the data.
// Parameters:
// const char* sentence:
// The sentence to parse.
// Returns:
// SENTENCE_VALID if the sentence passed is a valid NMEA sentence.
// SENTENCE_INVALID if the sentence passed is not a valid NMEA sentence, or
// the sentence type is unsupported (see NMEAParser.h for a list of
// supported sentences.)
// SENTENCE_BAD_CHECKSUM if the sentence has an invalid checksum.
{
#if 0 // sj
if (logger.isDebugEnabled())
{
logger.debug("parsing sentence %s", sentence);
}
#endif
if (isCorrectChecksum (sentence) == false)
{
// sj: logger.debug("SENTENCE_BAD_CHECKSUM");
return SENTENCE_BAD_CHECKSUM;
}
if (isKnownSentenceType (sentence) == false)
{
// sj: logger.debug("SENTENCE_UNKNOWN");
return SENTENCE_UNKNOWN;
}
return parseValidSentence(sentence);
}
SENTENCE_STATUS NMEAParser::parseValidSentence (const char* sentence)
{
#if 0 // sj
if (logger.isDebugEnabled())
{
logger.debug("NMEAParser: parsing %s", sentence);
}
#endif
// Start the parsing 3 spaces past start to get past the initial
// '$xx', where xx is the device type sending the sentences (GP =
// GPS, etc.)
uint_ currentPos = 3;
char sentenceType[4];
if (getNextField (sentenceType, sentence, currentPos) == false)
{
return SENTENCE_INVALID;
}
if (strcmp (sentenceType, startSentence) == 0)
{
// this message is the first in the sequence
m_data->waitingForStart = false;
}
// If we are waiting for the start message to appear, don't bother
// processing any other message type
if (m_data->waitingForStart == true)
{
return SENTENCE_VALID;
}
// Parse the sentence. Make sure the sentence has the correct
// number of commas in it, otherwise the sentence is invalid.
if (strcmp (sentenceType, "GGA") == 0)
{
if (countChars (sentence, ',', SENTENCE_GGA_COMMAS) < 0)
{
return SENTENCE_INVALID;
}
parseGGA (sentence);
}
else if (strcmp (sentenceType, "GLL") == 0)
{
if (countChars (sentence, ',', SENTENCE_GLL_COMMAS) < 0)
{
return SENTENCE_INVALID;
}
parseGLL (sentence);
}
else if (strcmp (sentenceType, "RMC") == 0)
{
if (countChars (sentence, ',', SENTENCE_RMC_COMMAS) < 0)
{
return SENTENCE_INVALID;
}
parseRMC (sentence);
}
else if (strcmp (sentenceType, "GSV") == 0)
{
if (countChars (sentence, ',', SENTENCE_GSV_COMMAS) < 0)
{
return SENTENCE_INVALID;
}
parseGSV (sentence);
}
else if (strcmp (sentenceType, "RRE") == 0)
{
// if (countChars (sentence, ',', SENTENCE_RRE_COMMAS) < 0)
//{
// return SENTENCE_INVALID;
//}
parseRRE (sentence);
}
else if (strcmp (sentenceType, "VTG") == 0)
{
if (countChars (sentence, ',', SENTENCE_VTG_COMMAS) < 0)
{
return SENTENCE_INVALID;
}
parseVTG (sentence);
}
else if (strcmp (sentenceType, "GST") == 0)
{
if (countChars (sentence, ',', SENTENCE_GST_COMMAS) < 0)
{
return SENTENCE_INVALID;
}
parseGST (sentence);
}
else if (strcmp (sentenceType, "ZDA") == 0)
{
if (countChars (sentence, ',', SENTENCE_ZDA_COMMAS) < 0)
{
return SENTENCE_INVALID;
}
parseZDA (sentence);
}
else
{
return SENTENCE_INVALID;
}
return SENTENCE_VALID;
}
/////////////////////////////////////////////////////////////////////////////
// Member functions for individual element parsing of sentences.
bool NMEAParser::parseDate (int& year, int& month, int& day,
const char* dateString) const
// Purpose:
// This function parses a date string from an NMEA sentence in DDMMYY format
// and returns the year, month, and day values.
// Parameters:
// int& year, int& month, int& year:
// Upon exit, these variables will contain the year, month, and day
// values specified in dateString, respectively.
// const char* dateString:
// The NMEA date string to parse.
// Returns:
// true if the date string is in a valid format, false if not.
// Notes:
// - NMEA sentences are *not* "Year 2000-compliant"{tm}; the software must
// correctly determine the year's century.
// - If this function returns false, then the variables year, month, and day
// are unaffected.
{
// Date must be six characters.
if (strlen (dateString) < unsigned (DATE_LEN))
{
return false;
}
long tempDate = atol (dateString);
int tempYear, tempMonth, tempDay;
tempYear = tempDate - ((tempDate / 100) * 100);
tempMonth = (tempDate - ((tempDate / 10000) * 10000)) / 100;
tempDay = tempDate / 10000;
// Check to see if the date is valid. (This function will accept
// Feb 31 as a valid date; no check is made for how many days are in
// each month of our whacked calendar.)
if ((tempYear >= 0 && tempYear <= 99)
&& (tempMonth >= 1 && tempMonth <= 12)
&& (tempDay >= 1 && tempDay <= 31))
{
year = tempYear;
month = tempMonth;
day = tempDay;
return true;
}
return false;
}
bool NMEAParser::parseDegrees (double& degrees, const char* degString) const
// Purpose:
// This function converts a lat/lon string returned from an NMEA string into
// a numeric representation of that string, in degrees. (A lat/lon string
// must be in the format DDMM.M(...) where D = degrees and M = minutes.)
// Pre:
// The string degString must contain a number in the format DDMM.M(...).
// Parameters:
// double& degrees:
// Upon exit, degrees will contain the numeric representation of the
// string passed to this function, in decimal degrees.
// const char* degString:
// Contains the string to convert.
// Returns:
// - true if the conversion was successful. If false is returned, either
// degString was not in one of those required formats, or the string data
// itself is invalid. (For example, the string 23809.666 would not be
// valid, as the 238th degree does not exist.)
// - If this function returns false, then the parameter 'degrees' is
// unaffected.
{
if (strlen (degString) == 0)
{
return false;
}
double tempPosition = atof (degString);
double tempDegrees = (double)((int)(tempPosition / 100.0));
double tempMinutes = (tempPosition - (tempDegrees * 100.0));
tempPosition = tempDegrees + (tempMinutes / 60.0);
if (tempPosition >= 0.0 && tempPosition <= 180.0)
{
degrees = tempPosition;
return true;
}
return false;
}
bool NMEAParser::parseTime (int& hour, int& minute, int& second,
const char* timeString) const
// Purpose:
// This function parses a time string from an NMEA sentence in HHMMSS.S(...)
// format and returns the hour, minute, and second values.
// Parameters:
// int& hour, int& minute, int& second:
// Upon exit, these variables will contain the hour, minute, and second
// values specified in timeString, respectively.
// const char* timeString:
// The NMEA time string to parse.
// Returns:
// true if the time string is in a valid format, false if not.
// Notes:
// - Decimal second values are truncated.
// - If this function returns false, then the variables hour, minute, and
// second are unaffected.
{
if (strlen (timeString) == 0)
{
return false;
}
long tempTime = atol (timeString);
int tempHour = tempTime / 10000;
int tempMinute = (tempTime - ((tempTime / 10000) * 10000)) / 100;
int tempSecond = tempTime - ((tempTime / 100) * 100);
// Check to see if the time is valid.
if ((tempHour >= 0 && tempHour <= 23)
&& (tempMinute >= 0 && tempMinute <= 59)
&& (tempSecond >= 0 && tempSecond <= 61))
{ // leap seconds
hour = tempHour;
minute = tempMinute;
second = tempSecond;
return true;
}
return false;
}
/////////////////////////////////////////////////////////////////////////////
// parse And Validate member functions for NMEAParser.
//
// Each of these member functions parse a specified field from a sentence and
// updates the appropriate member variables in the NMEAData object. If the
// data parsed is valid, the validation member variable associated the parsed
// value is set to true, otherwise it is set to false.
void NMEAParser::parseAndValidateAltitude (const char* field, const char unit)
// Purpose:
// This function parses the altitude field of a sentence.
// Parameters:
// const char* field:
// The altitude field of the sentence to parse.
// const char unit:
// The unit of altitude. Valid values are 'f' (feet) and 'm' (meters).
// Notes:
// The resulting altitude data is specified in feet.
{
// Initially assume data is invalid.
m_data->isValidAltitude = false;
if (strlen (field) != 0) {
if (unit == 'f' || unit == 'F') {
// Altitude is in feet.
m_data->altitude = atof (field) * FEET_TO_METERS;
m_data->isValidAltitude = true;
} else if (unit == 'm' || unit == 'M') {
// Altitude is in meters. Convert to feet.
m_data->altitude = atof (field);
m_data->isValidAltitude = true;
}
}
// sj: logger.debug("isValidAltitude=%d; altitude=%f",
// sj: m_data->isValidAltitude, m_data->altitude);
}
void NMEAParser::parseAndValidateDate (const char* field)
// Purpose:
// This function parses the date field of a sentence, in the format DDMMYY.
{
// Initially assume data is invalid.
m_data->isValidDate = false;
if (strlen (field) != 0) {
int year, month, day;
if (parseDate (year, month, day, field) == true) {
m_data->UTCYear = year;
m_data->UTCMonth = month;
m_data->UTCDay = day;
m_data->isValidDate = true;
}
}
// sj: logger.debug("isValidDate=%d; year=%d; month=%d; day=%d",
// sj: m_data->isValidDate, m_data->UTCYear, m_data->UTCMonth,
// sj: m_data->UTCDay);
}
void NMEAParser::parseAndValidateFixQuality (const char* field)
// Purpose:
// This function parses the GPS fix quality field of a sentence.
{
if (strlen (field) != 0) {
m_data->isValidFixQuality = true;
int fixQuality = atoi (field);
if (fixQuality == 0) m_data->lastFixQuality = FIX_AUTONOMOUS;
else if (fixQuality == 1) m_data->lastFixQuality = FIX_RTCM;
else if (fixQuality == 2) m_data->lastFixQuality = FIX_CPD_FLOAT;
else if (fixQuality == 3) m_data->lastFixQuality = FIX_CPD_FIXED;
else if (fixQuality == 9) m_data->lastFixQuality = FIX_ALMANAC;
else
{
// sj: logger.notice("unknown fix quality %d", fixQuality);
m_data->lastFixQuality = FIX_AUTONOMOUS;
}
}
// sj: logger.debug("lastFixQuality=%d", m_data->lastFixQuality);
}
void NMEAParser::parseAndValidateHdop (const char* field)
// Purpose:
// This function parses the HDOP (horizontal dilution of precision) field of
// a sentence.
{
if (strlen (field) != 0) {
m_data->hdop = atof (field);
m_data->isValidHdop = true;
} else {
m_data->isValidHdop = false;
}
// sj: logger.debug("isValidHdop=%d; hdop=%f", m_data->isValidHdop, m_data->hdop);
}
void NMEAParser::parseAndValidateNStd (const char* field)
// Purpose:
// This function parses the NSTD (1 standard deviation of position estimate in northern
// direction)
{
if (strlen (field) != 0) {
m_data->nStd = atof (field);
m_data->isValidNStd = true;
} else {
m_data->isValidNStd = false;
}
// sj: logger.debug("isValidNStd=%d; nStd=%f", m_data->isValidNStd, m_data->nStd);
}
void NMEAParser::parseAndValidateEStd (const char* field)
// Purpose:
// This function parses the ESTD (1 standard deviation of position estimate in eastern
// direction)
{
if (strlen (field) != 0) {
m_data->eStd = atof (field);
m_data->isValidEStd = true;
} else {
m_data->isValidEStd = false;
}
}
void NMEAParser::parseAndValidateZStd (const char* field)
// Purpose:
// This function parses the ZSTD (1 standard deviation of position estimate in altitude)
{
if (strlen (field) != 0) {
m_data->zStd = atof (field);
m_data->isValidZStd = true;
} else {
m_data->isValidZStd = false;
}
// sj: logger.debug("isValidEStd=%d; eStd=%f", m_data->isValidEStd, m_data->eStd);
}
void NMEAParser::parseAndValidateLat (const char* field, const char hem)
// Purpose:
// This function parses the latitude field of a sentence in the format
// DDMM.M(...).
// Parameters:
// const char* field:
// The latitude field of the sentence to parse.
// const char hem:
// The hemisphere that contains the location. Valid values are 'N' and
// 'S'.
// Notes:
// - If the latitude is in the southern hemisphere, the latitude member
// variable will be negative. (e.g., 4000.000 S will be stored as -40.0.)
// - If the latitude field does not exist within a sentence, the fix
// quality variable, m_data->lastFixQuality, is set to FIX_AUTONOMOUS.
{
// Initially assume data is invalid.
m_data->isValidLat = false;
if (strlen (field) != 0) {
// GPS lat/lon data has been received.
// Set the fix quality to "GPS navigation." This is because some
// GPS's may not send GGA sentences; therefore the last fix quality
// would never get set.
if (m_data->lastFixQuality == FIX_AUTONOMOUS) {
m_data->lastFixQuality = FIX_RTCM;
}
m_data->hasCoordEverBeenValid = true;
double degree;
if (parseDegrees (degree, field) == true) {
if (hem == 'N') {
// Northern hemisphere.
m_data->lat = degree;
m_data->isValidLat = true;
} else if (hem == 'S') {
// Southern hemisphere, so make latitude negative.
m_data->lat = -degree;
m_data->isValidLat = true;
}
}
} else {
m_data->lastFixQuality = FIX_AUTONOMOUS;
}
// sj: logger.debug("isValidLat=%d; lat=%f", m_data->isValidLat, m_data->lat);
}
void NMEAParser::parseAndValidateLon (const char* field, const char hem)
// Purpose:
// Same as parseAndValidateLat(), but the longitude is in the format
// DDDMM.M(...).
// Notes:
// - The valid values for the hem parameter are 'E' and 'W'.
// - If the longitude is in the western hemisphere, the longitude member
// variable will be negative. (e.g., 4000.000 W will be stored as -40.0.)
// - If the latitude field does not exist within a sentence, the last fix
// quality variable, m_data->lastFixQuality, is set to FIX_AUTONOMOUS.
{
// Initially assume data is invalid.
m_data->isValidLon = false;
if (strlen (field) != 0) {
// GPS lat/lon data has been received.
// Set the fix quality to "GPS navigation." This is because some
// GPS's may not send GGA sentences; therefore the last fix quality
// would never get set.
if (m_data->lastFixQuality == FIX_AUTONOMOUS) {
m_data->lastFixQuality = FIX_RTCM;
m_data->hasCoordEverBeenValid = true;
}
double degree;
if (parseDegrees (degree, field) == true) {
if (hem == 'E') {
// Eastern hemisphere.
m_data->lon = degree;
m_data->isValidLon = true;
} else if (hem == 'W') {
// Western hemisphere, so make longitude negative.
m_data->lon = -degree;
m_data->isValidLon = true;
}
}
} else {
m_data->lastFixQuality = FIX_AUTONOMOUS;
}
// sj: logger.debug("isValidLon=%d; lon=%f", m_data->isValidLon, m_data->lon);
}
void NMEAParser::parseAndValidateMagVariation (const char* field,
const char direction)
// Purpose:
// This function parses the magnetic variation field of a sentence, in
// relation to true north.
// Parameters:
// const char* field:
// The magnetic variation field of the sentence to parse, in degrees.
// const char direction:
// The direction of the field in relation to true north. Valid values
// are 'E' and 'W'.
// Notes:
// If the magnetic variation points west of true north, the magnetic
// variation variable will be negative. (e.g., 020.3 W will be stored as
// -20.3.)
{
// Initially assume data is invalid.
m_data->isValidMagVariation = false;
if (strlen (field) != 0) {
double degree = atof (field);
if (degree >= 0.0 && degree <= 360.0) {
if (direction == 'E') {
m_data->magVariation = degree;
m_data->isValidMagVariation = true;
} else if (direction == 'W') {
m_data->magVariation = -degree;
m_data->isValidMagVariation = true;
}
}
}
// sj: logger.debug("isValidMagVariation=%d; magVariation=%f",
// sj: m_data->isValidMagVariation, m_data->magVariation);
}
void NMEAParser::parseAndValidateSpeed (const char* field)
// Purpose:
// This function parses the speed field of a sentence.
{
if (strlen (field) != 0) {
m_data->speed = atof (field);
m_data->isValidSpeed = true;
} else {
m_data->isValidSpeed = false;
}
// sj: logger.debug("isValidSpeed=%d; speed=%f",
// sj: m_data->isValidSpeed, m_data->speed);
}
void NMEAParser::parseAndValidateTime (const char* field)
// Purpose:
// This function parses the date field of a sentence, in the format
// HHMMSS.S(...), except the decimal second values are truncated.
{
// Initially assume data is invalid.
m_data->isValidTime = false;
if (strlen (field) != 0) {
int hour, minute, second;
if (parseTime (hour, minute, second, field) == true) {
m_data->UTCHour = hour;
m_data->UTCMinute = minute;
m_data->UTCSecond = second;
m_data->isValidTime = true;
}
}
// sj: logger.debug("isValidTime=%d; hour=%d; minute=%d; second=%d",
// sj: m_data->isValidTime, m_data->UTCHour, m_data->UTCMinute,
// sj: m_data->UTCSecond);
}
void NMEAParser::parseAndValidateTrack (const char* field)
// Purpose:
// This function parses the track field of a sentence.
{
// Initially assume data is invalid.
m_data->isValidTrack = false;
if (strlen (field) != 0) {
double track = atof (field);
if (track >= 0.0 && track <= 360.0) {
m_data->track = track;
m_data->isValidTrack = true;
}
}
// sj: logger.debug("isValidTrack=%d; track=%f", m_data->isValidTrack, m_data->track);
}
/////////////////////////////////////////////////////////////////////////////
// Miscellaneous member functions
bool NMEAParser::getNextField (char* data, const char* sentence,
uint_& currentPos) const
// Purpose:
// This function retrieves the next field in the NMEA sentence. A field is
// defined as the text between two delimiters (in this case of NMEA
// sentences, a delimiter is a comma character.)
// Pre:
// The specified sentence is valid. (Before calling this function, call the
// member functions IsCorrectChecksum() and ValidSentenceType(), passing the
// sentence to those functions.)
// Parameters:
// char* data:
// Upon exit, this string will contain the contents of the next field
// in the sentence.
// const char* sentence:
// The NMEA sentence to parse.
// uint_& currentPos:
// Determines the initial position within the NMEA sentence in which to
// parse. This function will grab all of the characters from
// currentPos all the way to the character before the comma delimiter.
// Upon exit, currentPosition will point to the next field in the string.
// Note that the comma is not included in the field data.
// Returns:
// true if there are more fields to parse, false if not.
// Notes:
// To grab all of the fields, you can iteratively call GetNextData()
// using the same variable that is passed as currentPosition, until
// GetNextData() returns false.
{
int srcPos = currentPos;
int dstPos = 0;
char currentChar = sentence[srcPos];
// The delimiter character is the comma.
while ((currentChar != '\0' ) && (currentChar != ',')
&& (currentChar != '\x0d') && (currentChar != '*')) {
data[dstPos++] = currentChar;
currentChar = sentence[++srcPos];
}
data[dstPos] = '\0';
if (currentChar == ',') {
// Next data field to parse will be past the comma.
currentPos = srcPos + 1;
return true;
} else {
// No more characters in the string to parse; this function has
// arrived at the end of the string.
return false;
}
}
bool NMEAParser::isCorrectChecksum (const char* sentence) const
// Purpose:
// This function calculates the sentence's checksum and compares it with the
// checksum in the sentence.
// Pre:
// The NMEA sentence is valid (ValidSentenceStructure() must be called with
// this sentence before calling this function; that function must return
// true.)
// Returns:
// true if the checksum is valid or there is no checksum in the sentence.
// (It is not necessary to have a device append a checksum to a sentence.)
// Otherwise this function returns false.
// Notes:
// The checksum in the sentence occurs after the * character.
{
// Check all characters between the initial '$' and the last "*" in the
// sentence and XOR them together.
int charPos = 1; // start past the initial '$'.
char currentChar = sentence[charPos];
uint8_ checksum = 0;
while (currentChar != '*' && currentChar != '\0') {
checksum ^= (uint8_)currentChar;
currentChar = sentence[++charPos];
}
// If no checksum exists (this function has reached the end of the string
// without finding one), the sentence is good.
if (sentence[charPos + 1] == '\0') return true;
// Convert last two hex characters (the checksum) in the sentence with
// the checksum this function has generated.
char firstDigit = sentence[charPos + 1];
char lastDigit = sentence[charPos + 2];
if ( (firstDigit <= '9' ? firstDigit - '0': (firstDigit - 'A') + 10) * 16
+ (lastDigit <= '9' ? lastDigit - '0': (lastDigit - 'A') + 10)
== checksum) {
return true;
} else {
return false;
}
return true;
}
bool NMEAParser::isValidSentenceType (const char* sentence) const
{
if (strlen (sentence) < 6)
{
return false;
}
if (sentence[0] != '$')
{
return false;
}
return isKnownSentenceType(sentence);
}
bool NMEAParser::isKnownSentenceType (const char* sentence) const
// Purpose:
// This function determines whether this is a valid NMEA sentence that this
// class can support.
// Notes:
// See the header file for a list of sentences supported by this class.
{
// Get the three letters after the '$xx'; this is the type of
// sentence. (Note the xx is the type of device which is sending
// the string. For example, GP = GPS, etc.)
char sentenceType[4];
memcpy (sentenceType, &(sentence[3]), 3);
sentenceType[3] = '\0';
return ((strcmp (sentenceType, "ZDA") == 0)
|| (strcmp (sentenceType, "GGA") == 0)
|| (strcmp (sentenceType, "GLL") == 0)
|| (strcmp (sentenceType, "RMC") == 0)
|| (strcmp (sentenceType, "GSV") == 0)
|| (strcmp (sentenceType, "GST") == 0)
|| (strcmp (sentenceType, "VTG") == 0)
|| (strcmp (sentenceType, "RRE") == 0));
}
int NMEAParser::countChars (const char* string, char charToCount, uint_ charCount) const
// Purpose:
// This function counts the number of specified occurrences of the
// specified characters and compares to the number of characters that is
// expected.
// Parameters:
// const char* string:
// The string to check.
// char charToCount:
// The character to count.
// uint_ charCount:
// The number of the characters specified by charToCount that is expected
// to be contained within that string.
// Returns:
// 0 if the number of specified characters in the sentence matches charCount.
// 1 if the number of specified characters in the sentence is less than
// charCount.
// -1 if the number of specified characters in the sentence is greater than
// charCount.
{
size_t stringSize = strlen (string);
size_t currentCharCount = 0;
const char* currentChar = string;
for (size_t i = 0; i < stringSize; i++) {
if (*currentChar++ == charToCount) ++currentCharCount;
}
if (currentCharCount > charCount) {
return 1;
} else if (currentCharCount < charCount) {
return -1;
} else {
return 0;
}
}
/*
* This class was adapted from the GPSThing CNmeaParser class.
* Originally written by Jason Bevins
*/
#ifndef __NMEAPARSER_HPP
#define __NMEAPARSER_HPP
#if 1
typedef unsigned char uint8_;
typedef unsigned short uint16_;
typedef unsigned int uint32_;
typedef unsigned int uint_;
#else
// Get standard types (uint8_, etc.)
#include <cc++/config.h>
#endif
#include <string.h>
// sj: #include <log4cpp/Category.hh>
struct SatData
{
SatData ()
{
prn = 0;
elevation = 0;
azimuth = 0;
strength = 0;
}
SatData (uint8_ prn_, uint16_ elevation_, uint16_ azimuth_,
uint16_ strength_)
{
prn = prn_;
elevation = elevation_;
azimuth = azimuth_;
strength = strength_;
}
uint16_ prn; // Satellite's ID.
uint16_ elevation; // Elevation of satellite, in degrees.
uint16_ azimuth; // Azimuth of satellite, in degrees.
uint16_ strength; // Signal strength of satellite.
};
struct RangeResidualData
{
RangeResidualData()
{
prn = 0;
residual = 0;
}
RangeResidualData(uint8_ prn_, double residual_)
{
prn = prn_;
residual = residual_;
}
uint8_ prn;
double residual;
};
const double METERS_TO_FEET = 3.280839895013;
const double FEET_TO_METERS = 1 / METERS_TO_FEET;
const double KM_TO_NM = 1.853;
const double NM_TO_KM = 1 / KM_TO_NM;
const double KM_TO_MI = FEET_TO_METERS * 5.28;
const double MI_TO_KM = 1 / KM_TO_MI;
// GPS coordinate fix quality.
enum GPS_FIX_QUALITY
{
FIX_AUTONOMOUS = 0,
FIX_RTCM = 1,
FIX_CPD_FLOAT = 2,
FIX_CPD_FIXED = 3,
FIX_ALMANAC = 9
};
// Sentence parsing status.
enum SENTENCE_STATUS
{
SENTENCE_VALID=0, // Sentence parsed is valid.
SENTENCE_INVALID, // Sentence parsed has invalid data.
SENTENCE_BAD_CHECKSUM, // Sentence parsed has a bad checksum.
SENTENCE_UNKNOWN // Sentence is of unknown type
};
// Number of commas in each sentence. In order for a sentence to be valid,
// it must have a specified number of commas.
enum SENTENCE_COMMA_SIZES
{
SENTENCE_ZDA_COMMAS = 6,
SENTENCE_GGA_COMMAS = 14,
SENTENCE_GLL_COMMAS = 6,
SENTENCE_RMC_COMMAS = 11,
SENTENCE_GSV_COMMAS = 19,
SENTENCE_VTG_COMMAS = 7,
SENTENCE_GST_COMMAS = 8,
SENTENCE_RRE_COMMAS = 4
};
// Maximum size of an NMEA sentence (plus the NULL character.)
const int MAX_SENTENCE_SIZE = 1024;
// No GPS I'm aware of can track more than 12 satellites.
const uint8_ MAX_SATS = 12;
// Data class stored with the parser. To extract the data parsed from the
// parser, pass an object of this class to the parser.
// NOTE! NMEA sentences are not "Year 2000-compliant"{tm}
struct NMEAData
{
NMEAData ();
virtual ~NMEAData()
{
}
virtual void reset ();
// Data retrieved from the NMEA sentences.
double lat; // Latitude, in degrees (positive=N, negative=S)
double lon; // Longitude, in degrees (positive=E, negative=W)
double altitude; // Altitude, in feet
double speed; // Speed, in knots
double track; // Current track, in degrees.
double magVariation; // Magnetic variation, in degrees.
double hdop; // Horizontal dilution of precision.
double nStd; // North standard deviation.
double eStd; // East standard deviation.
double zStd; // Altitude standard deviation.
double hStd; // Horizonal standard deviation.
uint_ numSats; // Number of satellites in the sky.
int UTCYear; // GPS Date (UTC), year part
int UTCMonth; // GPS Date (UTC), month part
int UTCDay; // GPS Date (UTC), day part
int UTCHour; // GPS Time (UTC), hour part.
int UTCMinute; // GPS Time (UTC), minute part
int UTCSecond; // GPS Time (UTC), second part
SatData satData[MAX_SATS];
RangeResidualData rrData[MAX_SATS];
// Quality of last fix:
// 0 = invalid, 1 = GPS fix, 2 = DGPS fix.
GPS_FIX_QUALITY lastFixQuality;
// Validity of data parsed.
bool isValidLat; // Latitude
bool isValidLon; // Longitude
bool isValidAltitude; // Altitude
bool isValidSpeed; // Speed
bool isValidDate; // Date
bool isValidTime; // Time
bool isValidTrack; // Track
bool isValidMagVariation; // Magnetic variation
bool isValidHdop; // Horizontal dilution of precision
bool isValidNStd;
bool isValidEStd;
bool isValidZStd;
bool isValidSatData; // Satellite data
bool isValidRangeResidualData; // Satellite data
bool isValidHStd;
bool isValidFixQuality;
// Has a valid coordinate ever been sent over the serial port?
bool hasCoordEverBeenValid;
// Flag indicates if we are waiting for the frame to start
bool waitingForStart;
// Whether we have seen a particular message since the data was
// reset
bool seenZDA;
bool seenGGA;
bool seenGLL;
bool seenRMC;
bool seenGSV;
bool seenGST;
bool seenVTG;
bool seenRRE;
};
class NMEAParser
{
public:
NMEAParser (/* sj: log4cpp::Category& l*/);
virtual ~NMEAParser ();
SENTENCE_STATUS parseSentence (const char* sentence);
void setStartSentence(char *sentence)
{
strcpy(startSentence, sentence);
}
void getData (NMEAData& data) const
{
data = *m_data;
}
NMEAData& getData()
{
return *m_data;
}
void reset ()
{
m_data->reset ();
}
bool isValidSentenceType (const char* sentence) const;
bool isCorrectChecksum (const char* sentence) const;
protected:
NMEAParser (/* sj: log4cpp::Category& l,*/ NMEAData* data);
bool parseDegrees (double& degrees, const char* degString) const;
bool parseDate (int& year, int& month, int& day,
const char* dateString) const;
bool parseTime (int& hour, int& minute, int& second,
const char* timeString) const;
void parseAndValidateAltitude (const char* field, const char unit);
void parseAndValidateDate (const char* field);
void parseAndValidateFixQuality (const char* field);
void parseAndValidateLat (const char* field, const char hem);
void parseAndValidateLon (const char* field, const char hem);
void parseAndValidateHdop (const char* field);
void parseAndValidateSpeed (const char* field);
void parseAndValidateNStd (const char* field);
void parseAndValidateEStd (const char* field);
void parseAndValidateZStd (const char* field);
void parseAndValidateMagVariation(const char* field,
const char direction);
void parseAndValidateTime (const char* field);
void parseAndValidateTrack (const char* field);
bool getNextField(char* data, const char* sentence,
uint_& currentPosition) const;
int countChars(const char* sentence, char charToCount,
uint_ charCount) const;
virtual bool isKnownSentenceType (const char* sentence) const;
virtual SENTENCE_STATUS parseValidSentence (const char* sentence);
NMEAData* m_data;
// the sentence that marks the beginning of the set of packets
char startSentence[16];
// Needed for parsing the GSV sentence.
int m_lastSentenceNumber;// Which sentence number was the last one?
int m_numSentences; // Number of sentences to process.
int m_numSatsExpected; // Number of satellites expected to parse.
int m_numSatsLeft; // Number of satellites left to parse.
int m_satArrayPos; // Array position of the next sat entry.
SatData m_tempSatData[MAX_SATS];
// The logging category
// sj: log4cpp::Category& logger;
private:
void parseZDA(const char* sentence);
void parseGGA (const char* sentence);
void parseGLL (const char* sentence);
void parseRMC (const char* sentence);
void parseGSV (const char* sentence);
void parseGST (const char* sentence);
void parseVTG (const char* sentence);
void parseRRE (const char* sentence);
};
#endif