Skip to content

Commit

Permalink
Merge pull request #7 from adedolapoadegboye/maps
Browse files Browse the repository at this point in the history
Added maps to display fix positions
  • Loading branch information
adedolapoadegboye authored Jul 28, 2024
2 parents 7f5bb12 + 9602da7 commit b2018c6
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 138 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
# testing
/coverage

# private
.env

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
71 changes: 35 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,67 @@
# gnssmetrics.com
# GNSSMetrics.com

gnssmetrics.com is a web application designed to provide comprehensive metrics and analysis for GNSS (Global Navigation Satellite System) testing. It accepts Excel and CSV sheets containing latitude, longitude, and altitude data from a static GNSS test and calculates various metrics using both user-provided ground truth coordinates and the mean of the provided data.
GNSSMetrics.com is a web application designed to deliver comprehensive metrics and analysis for GNSS (Global Navigation Satellite System) testing. It processes Excel and CSV sheets containing latitude, longitude, and altitude data from static GNSS tests, calculating various metrics using both user-provided ground truth coordinates and the mean of the provided data.

## Features

### Metrics Calculated:

- **Maximum Fix Error**: Calculates the maximum distance to ground truth coordinates.
- **Minimum Fix Error**: Calculates the minimum distance to ground truth coordinates.
- **Average Fix Error**: Calculates the average distance to ground truth coordinates.
- **CEP 50%**: Provides 2D accuracy based on ground truth coordinates with a 50% confidence level.
- **CEP 90%**: Provides 2D accuracy based on ground truth coordinates with a 90% confidence level.
- **CEP 98%**: Provides 2D accuracy based on ground truth coordinates with a 98% confidence level.
- **Mean CEP 50%**: Provides 2D accuracy based on the mean of data coordinates with a 50% confidence level.
- **Mean CEP 90%**: Provides 2D accuracy based on the mean of data coordinates with a 90% confidence level.
- **Mean CEP 98%**: Provides 2D accuracy based on the mean of data coordinates with a 98% confidence level.
- **SEP 50%**: Provides 3D accuracy based on ground truth coordinates with a 50% confidence level.
- **SEP 90%**: Provides 3D accuracy based on ground truth coordinates with a 90% confidence level.
- **SEP 98%**: Provides 3D accuracy based on ground truth coordinates with a 98% confidence level.
- **Mean SEP 50%**: Provides 3D accuracy based on the mean of data coordinates with a 50% confidence level.
- **Mean SEP 90%**: Provides 3D accuracy based on the mean of data coordinates with a 90% confidence level.
- **Mean SEP 98%**: Provides 3D accuracy based on the mean of data coordinates with a 98% confidence level.
- **Maximum Fix Error**: \( \max \left( \text{distance}(\text{fix}, \text{ground truth}) \right) \)
- **Minimum Fix Error**: \( \min \left( \text{distance}(\text{fix}, \text{ground truth}) \right) \)
- **Average Fix Error**: \( \frac{1}{n} \sum\_{i=1}^{n} \text{distance}(\text{fix}\_i, \text{ground truth}) \)
- **CEP 50%**: 2D accuracy with 50% confidence level.
- **CEP 90%**: 2D accuracy with 90% confidence level.
- **CEP 98%**: 2D accuracy with 98% confidence level.
- **Mean CEP 50%**: 2D accuracy based on mean coordinates with 50% confidence level.
- **Mean CEP 90%**: 2D accuracy based on mean coordinates with 90% confidence level.
- **Mean CEP 98%**: 2D accuracy based on mean coordinates with 98% confidence level.
- **SEP 50%**: 3D accuracy with 50% confidence level.
- **SEP 90%**: 3D accuracy with 90% confidence level.
- **SEP 98%**: 3D accuracy with 98% confidence level.
- **Mean SEP 50%**: 3D accuracy based on mean coordinates with 50% confidence level.
- **Mean SEP 90%**: 3D accuracy based on mean coordinates with 90% confidence level.
- **Mean SEP 98%**: 3D accuracy based on mean coordinates with 98% confidence level.

## Usage

1. Visit [gnssmetrics.com](https://gnssmetrics.com) in your web browser.
2. Upload your Excel or CSV sheet containing latitude, longitude, and altitude data.
3. Enter your ground truth coordinates (latitude, longitude, and altitude).
4. Click on the "Calculate Metrics" button.
5. View the calculated metrics and analysis on the dashboard.
1. Visit [GNSSMetrics.com](https://gnssmetrics.com).
2. Upload your Excel or CSV file with latitude, longitude, and altitude data.
3. Enter your ground truth coordinates.
4. Click "Calculate Metrics."
5. View the metrics and analysis on the dashboard.

## Development
## Stack

### Technologies Used:

- React.js for the frontend.
- Node.js for the backend.
- Firebase for hosting.
- **Frontend**: React.js, Tailwind CSS, Framer Motion, React Icons, React Router DOM
- **Backend**: Node.js, Firebase
- **Data Processing**: Axios, Chart.js, PapaParse, xlsx, jszip, geodesy, spread-js
- **Mapping**: Google Maps, Mapbox

### Feature Roadmap

- Implement maps view on result dashboard
- Add data export of result in different formats (html, csv, xlsx, etc)
- Implement user sign in and data persistence
- Implement analysis of live tests
- Implement maps view on result dashboard.
- Add data export options (HTML, CSV, XLSX).
- Implement user sign-in and data persistence.
- Enable live test analysis.

### Setup Instructions:

1. Clone the repository: `git clone <repository-url>`
2. Navigate to the project directory: `cd gnssmetrics`
3. Install dependencies: `npm install`
4. Start the development server: `npm start`
5. Open your web browser and visit [http://localhost:3000](http://localhost:3000)
5. Visit [http://localhost:3000](http://localhost:3000) in your web browser.

## Contributing

Contributions are welcome! If you'd like to contribute to gnssmetrics.com, please follow these guidelines:
Contributions are welcome! Follow these steps:

1. Fork the repository.
2. Create a new branch: `git checkout -b feature-name`
3. Make your changes and commit them: `git commit -m 'Add new feature'`
3. Commit your changes: `git commit -m 'Add new feature'`
4. Push to the branch: `git push origin feature-name`
5. Submit a pull request.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gnssmetrics",
"version": "1.0.3",
"version": "1.0.4",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
Expand Down
2 changes: 0 additions & 2 deletions src/Dev/Components/Visualizers/AltDataPlot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import Chart from "chart.js/auto";
const LineChart = (data) => {
const chartRef = useRef(null);

console.log("3D errors: ", data);

useEffect(() => {
const ctx = chartRef.current.getContext("2d");

Expand Down
121 changes: 59 additions & 62 deletions src/Dev/Components/Visualizers/DataMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,97 +2,94 @@ import React, { useEffect, useState, useRef } from "react";
import GoogleMapReact from "google-map-react";
import { IoLocation } from "react-icons/io5";

// Component for rendering individual markers
const AnyReactComponent = ({ text }) => {
try {
return (
<div className="text-2 text-red-700">
<div className="text-xs text-red-700">
<IoLocation />
<p>{text}</p>
</div>
);
} catch (error) {
console.error("Error occurred while rendering marker component:", error);
// Handle the error gracefully, such as logging it or displaying a message to the user
return null; // Return null to render nothing in case of an error
// Handle the error gracefully
return null; // Render nothing in case of an error
}
};

const DataMap = (file) => {
const [markers, setMarkers] = useState([]);
const DataMap = ({ file, refLat, refLong }) => {
// API key for Google Maps, loaded from environment variables
const mapAPIKEYS = process.env.REACT_APP_GOOGLE_MAP_KEYS;

const mapRef = useRef();
// Define default map properties
const defaultProps = useRef({
center: { lat: 51.0447, lng: -114.0719 },
zoom: 10,
center: { lat: parseFloat(refLat), lng: parseFloat(refLong) },
zoom: 18,
});
console.log(defaultProps.current.center, defaultProps.current.zoom);

// State to store markers
const [markers, setMarkers] = useState([]);
const mapRef = useRef();

// Function to render markers on the map
const markerRender = () => {
try {
return (
<GoogleMapReact
bootstrapURLKeys={{ key: mapAPIKEYS }}
defaultCenter={defaultProps.current.center}
defaultZoom={defaultProps.current.zoom}
options={{
zoomControl: false,
fullscreenControl: false,
panControl: false,
draggable: false,
zoom: false,
}}
yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map }) => {
mapRef.current = map;
}}
>
{markers.map((marker) => (
<AnyReactComponent
key={marker.id}
lat={marker.lat}
lng={marker.lng}
text={marker.id.toString()}
/>
))}
</GoogleMapReact>
);
} catch (error) {
console.error(
"Error occurred while rendering markers on the map:",
error
);
return null; // Render nothing in case of an error
}
};

// Effect to process the file and set markers
useEffect(() => {
if (file.file) {
if (file && file.data) {
try {
// Map file data to markers
setMarkers(
file.file.data.map((item, index) => ({
file.data.map((item, index) => ({
id: index, // Unique identifier for each marker
lat: parseFloat(item.Latitude),
lng: parseFloat(item.Longitude),
}))
);
// setDefLat(file.file.data[0].Latitude);
// setDefLong(file.file.data[0].Longitude);
} catch (error) {
console.error("Error occurred while setting markers:", error);
// Handle the error gracefully, such as logging it or displaying a message to the user
}
}
}, [file.file, markers]);

// let defaultProps = {
// center: { lat: 51.0447, lng: -114.0719 },
// zoom: 10,
// };

const markerRender = () => {
if (markers.length > 0 && markers[0].lat) {
try {
return (
<div className="h-96 w-96 border border-gray-300 rounded-lg overflow-hidden text-xs">
<GoogleMapReact
bootstrapURLKeys={{
key: "",
}}
defaultCenter={defaultProps.current.center}
defaultZoom={defaultProps.current.zoom}
options={{
zoomControl: false,
fullscreenControl: false,
panControl: false,
draggable: false,
zoom: false,
}}
yesIWantToUseGoogleMapApiInternals
onGoogleApiLoaded={({ map, maps }) => {
mapRef.current = map;
}}
>
{markers.map((marker, index) => (
<AnyReactComponent
key={index}
lat={marker.lat}
lng={marker.lng}
text={marker.id}
/>
))}
</GoogleMapReact>
</div>
);
} catch (error) {
console.error("Error occurred while rendering Google Map:", error);
// Handle the error gracefully, such as logging it or displaying a message to the user
}
}
};
}, [file]);

return markerRender();
return <div className="w-full h-full rounded-xl">{markerRender()}</div>;
};

export default DataMap;
4 changes: 1 addition & 3 deletions src/Dev/Components/Visualizers/DataPlot.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import Chart from "chart.js/auto";
const LineChart = (data) => {
const chartRef = useRef(null);

console.log("2D errors: ", data);

useEffect(() => {
const ctx = chartRef.current.getContext("2d");

Expand Down Expand Up @@ -60,7 +58,7 @@ const LineChart = (data) => {
plugins: {
title: {
display: true,
text: "Plot of 2D Fix Error with respect to Reference 3D Coordinates",
text: "Plot of 2D Fix Error with respect to Reference 2D Coordinates",
},
},
},
Expand Down
4 changes: 4 additions & 0 deletions src/Dev/Functions/StatsAndPlotsRender.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import DataStats from "../Components/Visualizers/DataStats";
import DataPlot from "../Components/Visualizers/DataPlot";
import AltDataPlot from "../Components/Visualizers/AltDataPlot";
import DataMap from "../Components/Visualizers/DataMap";

const StatsAndPlotsRender = ({
startButton,
Expand Down Expand Up @@ -38,6 +39,9 @@ const StatsAndPlotsRender = ({
<AltDataPlot altPlotData={altPlotData} />
</div>
</div>
<div className="w-full h-[calc(75vh)] md:h-[calc(50vh)]">
<DataMap file={file} refLat={refLat} refLong={refLong} />
</div>
</div>
);
}
Expand Down
Loading

0 comments on commit b2018c6

Please sign in to comment.