Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 108 additions & 19 deletions app/GNSSStatus/Parsing/GNSSData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,32 @@
using System.Text;
using GNSSStatus.Configuration;
using GNSSStatus.Utils;
using YamlDotNet.Serialization;
Comment on lines 4 to +5

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not leave unused using statements


namespace GNSSStatus.Parsing;

public class GNSSData
{
public readonly List<double> DeltaZCache = new();
public readonly List<double> DeltaXCache = new();
public readonly List<double> DeltaYCache = new();
public readonly List<double> DeltaZCache = new();
public readonly List<double> RoverXCache = new();
public readonly List<double> RoverYCache = new();
public readonly List<double> RoverZCache = new();
public readonly List<GGAData.FixType> FixTypesCache = new();
public readonly List<string> RoverUtcTimeCache = new();
public readonly List<GGAData.FixType> RoverFixTypeCache = new();
public readonly List<int> RoverSatInUseCache = new();
public readonly List<float> RoverPDopCache = new();
public readonly List<float> RoverVDopCache = new();
public readonly List<float> RoverHDopCache = new();
public readonly List<float> RoverErrorLatitudeCache = new();
public readonly List<float> RoverErrorLongitudeCache = new();
public readonly List<float> RoverErrorAltitudeCache = new();
public readonly List<double> RoverBaselineCache = new();
Comment on lines +17 to +26

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to prefix everything with "rover"

Comment on lines +11 to +26

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If everything needs to be averaged/median calculated, wrap in struct member (GGA, GSA, GST...) field setters. It's not maintainable to store everything publicly accessible here.


//public readonly List<string> RoverFixCache = new();
//public readonly List<string> RoverSatInUseCache = new();
//public readonly List<GGAData.FixType> FixTypesCache = new();
Comment on lines +28 to +30

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(RSPEC-125) Sections of code should not be commented out.
Commented-out code distracts the focus from the actual executed code. It creates a noise that increases maintenance code. And because it is never executed, it quickly becomes out of date and invalid.
Commented-out code should be deleted and can be retrieved from source control history if required.

public double IonoPercentage { get; set; }

public GGAData GGA { get; set; }
Expand All @@ -26,7 +40,7 @@ public class GNSSData
public string GetPayloadJson()
{
JsonPayloadBuilder builder = new();

/*

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(RSPEC-125) Sections of code should not be commented out.

// Calculate averages and clear caches.
double deltaXAverage = DeltaXCache.Count > 0 ? DeltaXCache.Average() : 0;
double deltaYAverage = DeltaYCache.Count > 0 ? DeltaYCache.Average() : 0;
Expand All @@ -35,13 +49,49 @@ public string GetPayloadJson()
double roverXAverage = RoverXCache.Count > 0 ? RoverXCache.Average() : 0;
double roverYAverage = RoverYCache.Count > 0 ? RoverYCache.Average() : 0;
double roverZAverage = RoverZCache.Count > 0 ? RoverZCache.Average() : 0;
*/

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(RSPEC-125) Sections of code should not be commented out.


// Calculate median and clear caches.
int medianIndex = CalculateMedianIndex(RoverZCache).Item1;
int medianPdop = CalculateMedianIndex(RoverPDopCache).Item1;
int medianGstAltitudeError = CalculateMedianIndex(RoverErrorAltitudeCache).Item1;
int medianBaseline = CalculateMedianIndex(RoverBaselineCache).Item1;
double roverXMedian = RoverXCache[medianIndex];
double roverYMedian = RoverYCache[medianIndex];
double roverZMedian = RoverZCache[medianIndex];
double deltaXMedian = DeltaXCache[medianIndex];
double deltaYMedian = DeltaYCache[medianIndex];
double deltaXy = Math.Sqrt(deltaXMedian * deltaXMedian + deltaYMedian * deltaYMedian);
string roverUtCTime = RoverUtcTimeCache[medianIndex];
GGAData.FixType roverFixType = RoverFixTypeCache[medianIndex];

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FixTypes are no longer based on the worst in measure interval.

int roverSatInUse = RoverSatInUseCache[medianIndex];
double deltaZ = DeltaZCache[medianIndex];
float pDop = RoverPDopCache[medianPdop];
float hDop = RoverHDopCache[medianPdop];
float vDop = RoverVDopCache[medianPdop];
float errLat = RoverErrorLatitudeCache[medianGstAltitudeError];
float errLon = RoverErrorLongitudeCache[medianGstAltitudeError];
float errAlt = RoverErrorAltitudeCache[medianGstAltitudeError];
double baseline = RoverBaselineCache[medianBaseline];
Comment on lines +67 to +75

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same median index cannot be used to index into different data lists, as some lists may contain different amounts of data.


DeltaXCache.Clear();
DeltaYCache.Clear();
DeltaZCache.Clear();
RoverXCache.Clear();
RoverYCache.Clear();
RoverZCache.Clear();
RoverUtcTimeCache.Clear();
RoverFixTypeCache.Clear();
RoverSatInUseCache.Clear();
RoverPDopCache.Clear();
RoverHDopCache.Clear();
RoverVDopCache.Clear();
RoverErrorAltitudeCache.Clear();
RoverErrorLatitudeCache.Clear();
RoverErrorLongitudeCache.Clear();
RoverBaselineCache.Clear();

/*
// Determine the worst fix type.
GGAData.FixType worstFixType;
if (FixTypesCache.Count > 0)
Expand All @@ -52,50 +102,90 @@ public string GetPayloadJson()
worstFixType = GGAData.FixType.RTKFloat;
else
worstFixType = GGAData.FixType.RTKFixed;

}
else
worstFixType = GGAData.FixType.NoFix;
FixTypesCache.Clear();
*/

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(RSPEC-125) Sections of code should not be commented out.


// Manually serialize relevant properties.
builder.AddPayload(new
{
TimeUtc = GGA.UtcTime,
FixType = worstFixType,
SatellitesInUse = GGA.TotalSatellitesInUse,
RoverX = roverXAverage,
RoverY = roverYAverage,
RoverZ = roverZAverage,
TimeUtc = roverUtCTime,
//FixType = worstFixType,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(RSPEC-125) Sections of code should not be commented out.

FixType = roverFixType,
//SatellitesInUse = GGA.TotalSatellitesInUse,
SatellitesInUse = roverSatInUse,
//RoverX = roverXAverage,
RoverX = roverXMedian,
//RoverY = roverYAverage,
RoverY = roverYMedian,
//RoverZ = roverZAverage,
RoverZ = roverZMedian,
});

builder.AddPayload(new
{
DeltaXY = deltaXYAverage,
DeltaZ = deltaZAverage,
PDop = GSA.PDop,
HDop = GSA.HDop,
VDop = GSA.VDop
//DeltaXY = deltaXYAverage,
DeltaXY = deltaXy,
//DeltaZ = deltaZAverage,
DeltaZ = deltaZ,
//PDop = GSA.PDop,
PDop = pDop,
//HDop = GSA.HDop,
HDop = hDop,
//VDop = GSA.VDop
VDop = vDop,
});

builder.AddPayload(new
{
RoverId = ConfigManager.CurrentConfiguration.RoverIdentifier,
ErrorLatitude = GST.LatitudeError,
ErrorLongitude = GST.LongitudeError,
ErrorAltitude = GST.AltitudeError
//ErrorLatitude = GST.LatitudeError,
ErrorLatitude = errLat,
//ErrorLongitude = GST.LongitudeError,
ErrorLongitude = errLon,
//ErrorAltitude = GST.AltitudeError
ErrorAltitude = errAlt
});

builder.AddPayload(new
{
DifferentialDataAge = GGA.AgeOfDifferentialData,
ReferenceStationId = GGA.DifferentialReferenceStationID,
BaseRoverDistance = NTR.DistanceBetweenBaseAndRover,
//BaseRoverDistance = NTR.DistanceBetweenBaseAndRover,
BaseRoverDistance = baseline,
IonoPercentage = IonoPercentage
});

return builder.Build(true);
}

public (int, int) CalculateMedianIndex<T>(List<T> list)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CalculateMedianIndex does not need to return a tuple

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need for the method to be generic

{
// Luo kopio alkuperäisestä listasta ja liitä siihen alkuperäiset indeksit
var indexedNumbers = list

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer strong types where possible (maintainability)

.Select((value, index) => new { Value = value, Index = index })
.OrderBy(x => x.Value)
.ToArray();
Comment on lines +168 to +171

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allocates >3 IEnumerables, not ok in embedded systems


int count = indexedNumbers.Length;

if (count % 2 == 0)
{
// Jos määrä on parillinen, laske kahden keskimmäisen luvun indeksit
int mid1Index = indexedNumbers[count / 2 - 1].Index;
int mid2Index = indexedNumbers[count / 2].Index;
return (mid1Index, mid2Index);
}
else
{
// Jos määrä on pariton, valitse keskimmäisen luvun indeksi
int medianIndex = indexedNumbers[count / 2].Index;
return (medianIndex, -1); // -1 tarkoittaa, että vain yksi mediaani löytyy
}
Comment on lines +168 to +187

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not work as expected, and returns incorrect indices for generic types that do not implement IComparable.

}
Comment on lines +165 to +188

@japsuu japsuu Oct 21, 2024

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ChatGPT/AI generated code has no place in this project, because it is obviously logically incorrect. LLM has most likely no context of the embedded architecture we are building for, thus often outputting inefficient and often plain wrong code.


/// <summary>
/// NOTE: Should only be used for debugging purposes.
Expand All @@ -112,7 +202,6 @@ public override string ToString()
return sb.ToString();
}


private static void AppendPropertiesRecursive(StringBuilder sb, object? obj, int depth = 0)
{
if (obj == null)
Expand Down
11 changes: 10 additions & 1 deletion app/GNSSStatus/Parsing/SentenceParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public static void Parse(Nmea0183Sentence sentence)
ParsedData.RoverXCache.Add(ParsedData.GGA.RoverX);
ParsedData.RoverYCache.Add(ParsedData.GGA.RoverY);
ParsedData.RoverZCache.Add(ParsedData.GGA.RoverZ);
ParsedData.FixTypesCache.Add(ParsedData.GGA.Quality);
ParsedData.RoverUtcTimeCache.Add(ParsedData.GGA.UtcTime);
ParsedData.RoverFixTypeCache.Add(ParsedData.GGA.Quality);
ParsedData.RoverSatInUseCache.Add(ParsedData.GGA.TotalSatellitesInUse);
break;
}
case Nmea0183SentenceType.GSA:
Expand All @@ -42,6 +44,9 @@ public static void Parse(Nmea0183Sentence sentence)
}

ParsedData.GSA = new GSAData(sentence);
ParsedData.RoverPDopCache.Add(ParsedData.GSA.PDop);
ParsedData.RoverVDopCache.Add(ParsedData.GSA.VDop);
ParsedData.RoverHDopCache.Add(ParsedData.GSA.HDop);
break;
}
case Nmea0183SentenceType.GST:
Expand All @@ -53,6 +58,9 @@ public static void Parse(Nmea0183Sentence sentence)
}

ParsedData.GST = new GSTData(sentence);
ParsedData.RoverErrorAltitudeCache.Add(ParsedData.GST.AltitudeError);
ParsedData.RoverErrorLongitudeCache.Add(ParsedData.GST.LongitudeError);
ParsedData.RoverErrorLatitudeCache.Add(ParsedData.GST.LatitudeError);
break;
}
case Nmea0183SentenceType.GSV:
Expand All @@ -75,6 +83,7 @@ public static void Parse(Nmea0183Sentence sentence)
}

ParsedData.NTR = new NTRData(sentence);
ParsedData.RoverBaselineCache.Add(ParsedData.NTR.DistanceBetweenBaseAndRover);
break;
}
case Nmea0183SentenceType.GBS:
Expand Down