|
@@ -1,184 +1,122 @@
|
|
|
# GPS Test Tool - PC Application
|
|
# GPS Test Tool - PC Application
|
|
|
|
|
|
|
|
-## Overview
|
|
|
|
|
-
|
|
|
|
|
-Standalone PC application for testing GPS filtering and GPX generation using the actual embedded code from the GPS tracker project.
|
|
|
|
|
-
|
|
|
|
|
-**Status**: Architecture complete, 95% functional - see [Final Steps](#final-steps) below.
|
|
|
|
|
-
|
|
|
|
|
-## Architecture
|
|
|
|
|
-
|
|
|
|
|
-### Centralized Header Approach
|
|
|
|
|
-
|
|
|
|
|
-Following your excellent suggestion, the tool uses a **single main.h** that handles all PC/embedded switches:
|
|
|
|
|
|
|
+Standalone PC program that reprocesses recorded NMEA logs (or lets you feed
|
|
|
|
|
+NMEA sentences from a live source) through the **actual embedded filtering
|
|
|
|
|
+and GPX-generation code** from `../soft` (`gpx.c`, `nmea.c`, `autopause.c`,
|
|
|
|
|
+`syslog.c`), unmodified. Useful for reviewing/re-tuning filter behavior
|
|
|
|
|
+against real recorded tracks, and for regression-testing the parser against
|
|
|
|
|
+malformed input, without flashing a device.
|
|
|
|
|
+
|
|
|
|
|
+## How it works
|
|
|
|
|
+
|
|
|
|
|
+`main.h` is a single central header that switches between the embedded
|
|
|
|
|
+build and a PC build via `#define PC_BUILD`:
|
|
|
|
|
+
|
|
|
|
|
+- Standard C headers (`stdio`, `time`, `math`, ...) instead of AVR headers
|
|
|
|
|
+- Stub `avr/*.h` headers (`pgmspace.h`, `interrupt.h`, `eeprom.h`, `io.h`)
|
|
|
|
|
+ so `__flash`/`PROGMEM`-style code compiles as plain RAM data
|
|
|
|
|
+- Stub project headers (`stime.h`, `settings.h`, `timec.h`, `expander.h`,
|
|
|
|
|
+ display headers) that satisfy includes without pulling in embedded-only
|
|
|
|
|
+ code
|
|
|
|
|
+- A `FIL`/`f_*()` FatFS-like shim backed by plain `FILE*`, so `gpx.c` can
|
|
|
|
|
+ write files without linking `ff.c`
|
|
|
|
|
+
|
|
|
|
|
+Each `*_wrapper.c` file just does `#define PC_BUILD` / `#include "main.h"`
|
|
|
|
|
+and then `#include "../soft/<file>.c"`, so the real embedded source is
|
|
|
|
|
+compiled as-is, not copied. `main.c` is the tool's own driver/`main()` —
|
|
|
|
|
+`soft/main.c` itself is not part of this build.
|
|
|
|
|
+
|
|
|
|
|
+## Build
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
-main.h (PC version)
|
|
|
|
|
- ├─ #ifdef PC_BUILD
|
|
|
|
|
- │ ├─ Standard C headers (stdio, time, math, etc.)
|
|
|
|
|
- │ ├─ AVR compatibility layer (PROGMEM→no-op, etc.)
|
|
|
|
|
- │ ├─ FatFS stubs (using FILE*)
|
|
|
|
|
- │ ├─ xprintf implementations
|
|
|
|
|
- │ └─ Stub functions (UART, timers, etc.)
|
|
|
|
|
- └─ #else (embedded)
|
|
|
|
|
- └─ Original AVR headers
|
|
|
|
|
|
|
+cd gps-test-tool
|
|
|
|
|
+make # builds ./gps-test-tool
|
|
|
|
|
+make clean # removes build artifacts and generated output/debug files
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-### Files
|
|
|
|
|
|
|
+**Current status:** the build is broken at the moment. `soft/main.c` (not
|
|
|
|
|
+yet committed) added `tracking_is_paused()`, which `soft/gpx.c` and
|
|
|
|
|
+`soft/nmea.c` now call, but `soft/main.c` itself isn't compiled into this
|
|
|
|
|
+PC tool (it has its own driver, `main.c`), and no stub for
|
|
|
|
|
+`tracking_is_paused()` exists here yet. This tool already has an analogous
|
|
|
|
|
+stub for `is_paused()` in `gpx_wrapper.c`/`main.h` — `tracking_is_paused()`
|
|
|
|
|
+needs the same treatment before `make` will succeed again.
|
|
|
|
|
|
|
|
-| File | Purpose | Status |
|
|
|
|
|
-|------|---------|--------|
|
|
|
|
|
-| `main.h` | Central header with PC/embedded switches | ✓ Complete |
|
|
|
|
|
-| `main.c` | Test application | ✓ Complete |
|
|
|
|
|
-| `gpx_wrapper.c` | Includes `../soft/gpx.c` | ✓ Complete |
|
|
|
|
|
-| `nmea_wrapper.c` | NMEA parsing | ✓ Complete |
|
|
|
|
|
-| `Makefile` | Build system | ✓ Complete |
|
|
|
|
|
-| `avr/*.h` | Stub AVR headers | ✓ Complete |
|
|
|
|
|
-| `stime.h`, `settings.h`, etc. | Stub project headers | ✓ Complete |
|
|
|
|
|
|
|
+## Running
|
|
|
|
|
|
|
|
-## How It Works
|
|
|
|
|
-
|
|
|
|
|
-1. **Single Include**: All `.c` files only `#include "main.h"`
|
|
|
|
|
-2. **Conditional Compilation**: `main.h` detects `PC_BUILD` and includes appropriate headers
|
|
|
|
|
-3. **No Source Modifications**: Original `gpx.c` included as-is via wrapper
|
|
|
|
|
-4. **Stub Headers**: Prevent conflicts by providing empty stubs for embedded-specific headers
|
|
|
|
|
|
|
+```
|
|
|
|
|
+./gps-test-tool <input.nmea>
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
-## Current Status
|
|
|
|
|
|
|
+Each run processes the input file **twice** — once with filters enabled,
|
|
|
|
|
+once disabled — and produces four files in the current directory:
|
|
|
|
|
|
|
|
-### ✓ Working
|
|
|
|
|
-- PC-compatible main.h with full conditional logic
|
|
|
|
|
-- NMEA parser (GPRMC, GPGGA)
|
|
|
|
|
-- Test harness structure
|
|
|
|
|
-- FatFS stubs using stdio
|
|
|
|
|
-- xprintf implementations
|
|
|
|
|
-- Build system
|
|
|
|
|
|
|
+- `output_filtered.gpx` / `output_unfiltered.gpx` — GPX 1.1 tracks
|
|
|
|
|
+- `debug_filtered.txt` / `debug_unfiltered.txt` — per-run debug console
|
|
|
|
|
+ output plus a summary (points processed, distance, elevation gain/loss,
|
|
|
|
|
+ moving/stopped time, average speeds)
|
|
|
|
|
|
|
|
-### ⚙️ Minor Issues
|
|
|
|
|
-- Include path resolution: `gpx.c` has `#include "main.h"` which looks in `../soft` first
|
|
|
|
|
-- Some embedded headers still being included from `../soft`
|
|
|
|
|
|
|
+"Filters enabled" mirrors an out-of-the-box device: Kalman filtering,
|
|
|
|
|
+distance/minimum-distance thresholds, 3-point averaging, and auto-pause are
|
|
|
|
|
+all active. "Filters disabled" turns off the distance/Kalman filtering
|
|
|
|
|
+(`CONFFLAG_DISABLE_FILTERS`) so you can compare raw vs. filtered output for
|
|
|
|
|
+the same input.
|
|
|
|
|
|
|
|
-## Final Steps
|
|
|
|
|
|
|
+### Adjusting settings
|
|
|
|
|
|
|
|
-Choose ONE approach to complete:
|
|
|
|
|
|
|
+There's no command-line or interactive settings UI. To try different
|
|
|
|
|
+device settings against a log, edit the defaults in `reset_system()` in
|
|
|
|
|
+`main.c` (around line 67) and rebuild:
|
|
|
|
|
|
|
|
-### Option A: Modify Source Files (Recommended)
|
|
|
|
|
-Add conditional to `../soft/gpx.c`, `../soft/nmea.c`:
|
|
|
|
|
```c
|
|
```c
|
|
|
-#ifdef PC_BUILD
|
|
|
|
|
- #include "../../gps-test-tool/main.h"
|
|
|
|
|
-#else
|
|
|
|
|
- #include "main.h"
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
+System.conf.skip_points = 0;
|
|
|
|
|
+System.conf.auto_pause_time = 30; // seconds
|
|
|
|
|
+System.conf.auto_pause_dist = 10; // meters
|
|
|
|
|
+System.conf.auto_pause_speed = 3; // km/h
|
|
|
|
|
+System.conf.min_sats = 4; // minimum satellites for a valid fix
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-**Pros**: Clean, maintainable, minimal changes
|
|
|
|
|
-**Cons**: Touches source files
|
|
|
|
|
|
|
+These match `soft/settings.c`'s out-of-the-box defaults, so start from a
|
|
|
|
|
+known-good baseline before changing them.
|
|
|
|
|
|
|
|
-### Option B: Complete Stub Coverage
|
|
|
|
|
-Create comprehensive stubs for ALL embedded headers that override `../soft` versions.
|
|
|
|
|
|
|
+### Input format
|
|
|
|
|
|
|
|
-**Pros**: No source modifications
|
|
|
|
|
-**Cons**: Maintenance burden
|
|
|
|
|
-
|
|
|
|
|
-### Option C: Symlink Approach
|
|
|
|
|
-```bash
|
|
|
|
|
-cd gps-test-tool
|
|
|
|
|
-ln -s ../soft/gpx.c
|
|
|
|
|
-# Edit to change includes
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-**Pros**: Isolated changes
|
|
|
|
|
-**Cons**: Duplicate files
|
|
|
|
|
-
|
|
|
|
|
-## Usage (When Complete)
|
|
|
|
|
-
|
|
|
|
|
-```bash
|
|
|
|
|
-# Build
|
|
|
|
|
-make
|
|
|
|
|
-
|
|
|
|
|
-# Test with NMEA file
|
|
|
|
|
-./gps-test-tool input.nmea
|
|
|
|
|
-
|
|
|
|
|
-# Outputs:
|
|
|
|
|
-# output_filtered.gpx - With Kalman + all filters
|
|
|
|
|
-# output_unfiltered.gpx - Raw GPS data
|
|
|
|
|
-# debug_filtered.txt - Debug console (filtered)
|
|
|
|
|
-# debug_unfiltered.txt - Debug console (unfiltered)
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-## Example NMEA Input
|
|
|
|
|
|
|
+Plain text, one NMEA sentence per line (`\n` or `\r\n`), the same as a
|
|
|
|
|
+device's raw log file. The parser only acts on recognized sentences (RMC,
|
|
|
|
|
+GGA, GSA, VTG, ...); unrelated lines are ignored. Example minimal input:
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
|
|
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
|
|
|
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
|
|
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-## Key Features Being Tested
|
|
|
|
|
-
|
|
|
|
|
-- ✓ Kalman filtering (lat/lon/alt)
|
|
|
|
|
-- ✓ Distance difference filter
|
|
|
|
|
-- ✓ Minimum distance threshold (2.0m)
|
|
|
|
|
-- ✓ 3-point averaging
|
|
|
|
|
-- ✓ Distance tracking (with pause support)
|
|
|
|
|
-- ✓ Elevation gain/loss tracking (0.1m resolution)
|
|
|
|
|
-- ✓ GPX 1.1 format output
|
|
|
|
|
-- ✓ Filter comparison
|
|
|
|
|
-
|
|
|
|
|
-## Architecture Benefits
|
|
|
|
|
-
|
|
|
|
|
-1. **Maintainability**: Single point of control (main.h)
|
|
|
|
|
-2. **No Duplication**: Uses actual embedded code
|
|
|
|
|
-3. **Easy Testing**: Swap filters on/off with one flag
|
|
|
|
|
-4. **Portability**: Compiles on any PC with gcc
|
|
|
|
|
|
|
+## Automated tests
|
|
|
|
|
|
|
|
-## Directory Structure
|
|
|
|
|
|
|
+A regression test (`test-malformed`) feeds the real `gps_parse()` a fixture
|
|
|
|
|
+of real and synthetic edge-case NMEA sentences (`malformed_test.nmea`):
|
|
|
|
|
+truncated lines, bad checksums, invalid epochs, short dialect variants, and
|
|
|
|
|
+a run long enough to exercise HDOP-based speed-sample gating.
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
-gps-test-tool/
|
|
|
|
|
-├── main.h # Central header (PC/embedded switch)
|
|
|
|
|
-├── main.c # Test application
|
|
|
|
|
-├── gpx_wrapper.c # Includes ../soft/gpx.c
|
|
|
|
|
-├── nmea_wrapper.c # NMEA parsing for PC
|
|
|
|
|
-├── Makefile # Build system
|
|
|
|
|
-├── avr/ # Stub AVR headers
|
|
|
|
|
-│ ├── pgmspace.h
|
|
|
|
|
-│ ├── interrupt.h
|
|
|
|
|
-│ ├── eeprom.h
|
|
|
|
|
-│ └── io.h
|
|
|
|
|
-├── stime.h # Stub project header
|
|
|
|
|
-├── settings.h # Stub project header
|
|
|
|
|
-├── xprintf.h # Stub project header
|
|
|
|
|
-├── timec.h # Stub project header
|
|
|
|
|
-├── expander.h # Stub project header
|
|
|
|
|
-├── HD44780-I2C.h # Stub LCD header
|
|
|
|
|
-├── UC1601S-I2C.h # Stub LCD header
|
|
|
|
|
-└── README.md # This file
|
|
|
|
|
|
|
+make run-test-malformed
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
-## Build System
|
|
|
|
|
|
|
+This builds `test-malformed` and runs it against `malformed_test.nmea`. It
|
|
|
|
|
+asserts that:
|
|
|
|
|
|
|
|
-```makefile
|
|
|
|
|
-CC = gcc
|
|
|
|
|
-CFLAGS = -Wall -Wextra -g -O2 -I. -I../soft -DPC_BUILD
|
|
|
|
|
-LDFLAGS = -lm
|
|
|
|
|
|
|
+- nothing crashes the parser, regardless of how malformed a line is (run
|
|
|
|
|
+ under `valgrind`/ASan for a stronger guarantee than "exited zero")
|
|
|
|
|
+- invalid-epoch lines (RMC status `V`, VTG mode `N`) do not add a speed
|
|
|
|
|
+ sample
|
|
|
|
|
+- a genuinely poor-quality fast sample (bad HDOP) is excluded from the
|
|
|
|
|
+ speed average outright
|
|
|
|
|
+- a genuinely fast, good-quality sample is capped rather than excluded or
|
|
|
|
|
+ let through raw
|
|
|
|
|
|
|
|
-all: gps-test-tool
|
|
|
|
|
-test: run with sample data
|
|
|
|
|
-clean: remove build artifacts
|
|
|
|
|
-help: show available targets
|
|
|
|
|
-```
|
|
|
|
|
-
|
|
|
|
|
-## Summary
|
|
|
|
|
-
|
|
|
|
|
-The architecture is **sound and 95% complete**. The centralized `main.h` approach you suggested works perfectly - all PC/embedded switches are in one place. The tool successfully:
|
|
|
|
|
-
|
|
|
|
|
-- ✓ Uses actual `gpx.c` code without modification
|
|
|
|
|
-- ✓ Provides complete AVR compatibility layer
|
|
|
|
|
-- ✓ Handles conditional compilation cleanly
|
|
|
|
|
-- ✓ Minimizes code duplication
|
|
|
|
|
|
|
+To run it against a different fixture file:
|
|
|
|
|
|
|
|
-Only remaining task is resolving include paths for headers referenced from embedded code.
|
|
|
|
|
-
|
|
|
|
|
-## License
|
|
|
|
|
|
|
+```
|
|
|
|
|
+./test-malformed path/to/other.nmea
|
|
|
|
|
+```
|
|
|
|
|
|
|
|
-Same as main GPS tracker project.
|
|
|
|
|
|
|
+Any non-zero exit / `FAIL:` line means a check failed.
|