A .NET 8.0 application that converts Ultra-Wideband (UWB) sensor network data into GPS coordinates using trilateration algorithms. Designed for real-time position tracking and emergency response scenarios.
This application processes UWB sensor network data received via MQTT, calculates positions of unknown nodes using trilateration from known beacon positions, and converts the results to WGS84 GPS coordinates. It includes iterative refinement algorithms to improve position accuracy.
- Real-time UWB Network Processing: Receives UWB node distance measurements via MQTT
- Trilateration Algorithm: Calculates 3D positions from distance measurements
- GPS Coordinate Conversion: Converts local coordinates to WGS84 lat/lon/alt
- Iterative Refinement: Gradient descent optimization for improved accuracy
- MQTT Integration: Bidirectional MQTT communication for network updates
- ARM64 Native Build: Optimized for embedded Linux ARM64 systems
- MQTTControl.cs: MQTT client for receiving/sending network data
- UWBManager.cs: Manages UWB network updates and conversion pipeline
- UWB2GPSConverter.cs: Core trilateration and position calculation logic
- WGS84Converter.cs: Geodetic coordinate conversion (ECEF, ENU transformations)
- VectorExtensions.cs: Vector math utilities
- UwbParser.py: Python script for preprocessing edge data into network format
For a detailed system architecture diagram, see PROJECT_CONTEXT.md.
- .NET 8.0 SDK or Runtime
- MQTT broker (default:
mqtt.dynamicdevices.co.uk:1883) - Linux ARM64 target platform (or compatible)
Install the .NET 8.0 SDK:
# On Ubuntu/Debian
wget https://dot.net/v1/dotnet-install.sh
chmod +x dotnet-install.sh
./dotnet-install.sh --version 8.0.121# Restore dependencies
dotnet restore
# Build Release version for ARM64
dotnet build -c Release -r linux-arm64
# Publish self-contained (includes runtime)
dotnet publish -c Release -r linux-arm64 --self-contained true
# Publish framework-dependent (requires .NET runtime)
dotnet publish -c Release -r linux-arm64 --self-contained falseOutput will be in: bin/Release/net8.0/linux-arm64/publish/
# Linux x64
dotnet publish -c Release -r linux-x64
# Windows x64
dotnet publish -c Release -r win-x64
# macOS ARM64
dotnet publish -c Release -r osx-arm64The application uses appsettings.json for configuration. A development override file appsettings.Development.json is also supported.
Location: src/appsettings.json
Configuration Sections:
- MQTT: Server address, port, topics, credentials, retry settings, auto-reconnect, TLS/SSL settings
- Application: Update interval, log level
- Algorithm: Max iterations, learning rate, refinement enabled/disabled
- Beacons: Optional beacon GPS coordinates (can be empty - beacons can be provided via MQTT data instead)
Environment Variables: All settings can be overridden via environment variables (e.g., MQTT__ServerAddress, Application__LogLevel).
Default MQTT configuration (from appsettings.json):
- Server:
mqtt.dynamicdevices.co.uk - Port:
1883 - Receive Topic:
DotnetMQTT/Test/in - Send Topic:
DotnetMQTT/Test/out - Client ID:
clientId-UwbManager-001 - Retry Attempts: 5 (with exponential backoff)
- Auto Reconnect: Enabled
To customize, edit appsettings.json or set environment variables.
The application expects JSON messages in the following format:
{
"uwbs": [
{
"id": "B5A4",
"triageStatus": 5,
"position": {"x": 0, "y": 0, "z": 0},
"latLonAlt": [53.485, -2.192, 0.0],
"positionKnown": true,
"lastPositionUpdateTime": 0.0,
"edges": [
{
"end0": "B5A4",
"end1": "B57A",
"distance": 49.83
}
],
"positionAccuracy": 0.0
}
]
}Requirements:
- At least 3 nodes must have
positionKnown: truewith validlatLonAltcoordinates (beacons)- Beacons can be provided via MQTT data (recommended) or pre-configured in
appsettings.json - If using MQTT data, set
positionKnown: trueand includelatLonAlt: [latitude, longitude, altitude]for each beacon
- Beacons can be provided via MQTT data (recommended) or pre-configured in
- Each node should have edges connecting to other nodes with distance measurements
- Distances are in meters
# Run the application (from project root)
./bin/Release/net8.0/linux-arm64/publish/InstDotNet
# Or with dotnet
dotnet run --project src/InstDotNet.csprojThe application will:
- Display version information (version, build date, git commit hash)
- Connect to the MQTT broker
- Subscribe to the receive topic
- Process incoming UWB network updates
- Calculate positions for unknown nodes
- Publish updated network with GPS coordinates
Press Ctrl+C to exit gracefully.
This project uses Semantic Versioning (MAJOR.MINOR.PATCH).
- Version: Defined in
InstDotNet.csprojandVERSIONfile - Build Date: Automatically set at build time (UTC)
- Git Commit Hash: Automatically extracted from git repository (short hash)
Version information is displayed when the application starts and is embedded in the assembly metadata. To update the version, modify the <Version> property in InstDotNet.csproj and the VERSION file.
The UwbParser.py script can preprocess edge data into the network format:
python3 UwbParser.pyThis reads edge data from test_uwbs.json and generates uwb_network.json.
The system uses 3D trilateration to calculate positions:
- Requires 3 known reference points (beacons) with GPS coordinates
- Beacons can be provided via MQTT data (set
positionKnown: truewithlatLonAltcoordinates) - Or pre-configured in
appsettings.json(optional)
- Beacons can be provided via MQTT data (set
- Uses distance measurements from unknown nodes to known nodes
- Calculates intersection of spheres to determine position
- Converts local 3D coordinates to GPS using WGS84 transformations
After initial trilateration, the system applies gradient descent optimization:
- Maximum 10 iterations
- Learning rate: 0.1
- Minimizes distance error between calculated and measured distances
.
├── bin/ # Build outputs (gitignored)
├── obj/ # Build artifacts (gitignored)
├── src/ # Source code
│ ├── Program.cs # Main entry point
│ ├── MQTTControl.cs # MQTT client implementation
│ ├── UWBManager.cs # UWB network management
│ ├── UWB2GPSConverter.cs # Trilateration and position calculation
│ ├── WGS84Converter.cs # Geodetic coordinate conversions
│ ├── VectorExtensions.cs # Vector math utilities
│ ├── Logger.cs # Logging framework
│ ├── VersionInfo.cs # Version information
│ ├── AppConfig.cs # Configuration model
│ ├── appsettings.json # Configuration file
│ ├── appsettings.Development.json # Development overrides
│ └── InstDotNet.csproj # Project file
├── tests/ # Unit tests
│ ├── VectorExtensionsTests.cs
│ ├── UWB2GPSConverterTests.cs
│ ├── WGS84ConverterTests.cs
│ ├── GlobalUsings.cs
│ └── InstDotNet.Tests.csproj
├── Directory.Build.props # Centralized build configuration
├── UwbParser.py # Python preprocessing script
├── TestNodes.json # Sample test data
├── InstDotNet.sln # Solution file
├── LICENSE # GPLv3 license
├── CONTRIBUTING.md # Contribution guidelines
└── README.md # This file
- Follow C# naming conventions
- Use async/await for I/O operations
- Include error handling for network operations
- Document public APIs
Unit Tests: Comprehensive test suite with 92 tests (all passing ✅)
- Vector math operations (11 tests)
- Trilateration algorithms (13 tests)
- Coordinate conversions (6 tests)
- Configuration loading (6 tests)
- Logging framework (7 tests)
- Version information (6 tests)
- Edge handling and error calculations (8 tests)
CI Integration: All tests run automatically in GitHub Actions for both linux-arm64 and linux-x64 platforms.
Run Tests Locally:
dotnet testFuture Improvements:
- Integration tests for MQTT communication
- Additional edge case coverage (see CODE_COVERAGE_IMPROVEMENTS.md)
- Verify MQTT broker is accessible
- Check firewall rules for port 1883
- Verify credentials if authentication is required
- Ensure at least 3 beacons have
positionKnown: truewith validlatLonAltcoordinates - Beacons can be provided via MQTT data or pre-configured in
appsettings.json - Verify beacon GPS coordinates are valid
- Check that distance measurements are reasonable
- Review console output for triangulation errors
- Ensure .NET 8.0 SDK is installed
- Run
dotnet restoreto fetch dependencies - Check that target runtime identifier is correct
This project is licensed under the GNU General Public License v3.0 (GPLv3). See the LICENSE file for details.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Important Notes:
- All contributions must be submitted via Pull Request (PR)
- Copyright must be assigned to the project maintainers
- Please ensure all tests pass and documentation is updated
- CGA (Initial development)
- Alex J Lennon (AI Wrangling)
- WGS84 conversion routines based on work by James R. Clynch (NPS, 2003)
- Adapted to C# by Jen Laing (2020)