[TASK] Initial commit with basic product setup

This commit is contained in:
2019-08-18 13:50:14 +02:00
commit 01a66a8e1f
2548 changed files with 167528 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
namespace Mapbox.Unity.Location
{
using Mapbox.Utils;
using System;
using UnityEngine;
/// <summary>
/// Base class for implementing different smoothing strategies
/// </summary>
public abstract class AngleSmoothingAbstractBase : MonoBehaviour, IAngleSmoothing
{
[SerializeField]
[Tooltip("Number of measurements used for smoothing. Keep that number as low as feasible as collection of measurements depends on update time of location provider (minimum 500ms). eg 6 smoothes over the last 3 seconds.")]
[Range(5, 20)]
public int _measurements = 5;
public AngleSmoothingAbstractBase()
{
_angles = new CircularBuffer<double>(_measurements);
}
/// <summary>
/// Internal storage for latest 'n' values. Latest value at [0], <see cref="Mapbox.Utils.CircularBuffer{T}"/>
/// </summary>
protected CircularBuffer<double> _angles;
/// <summary>
/// For conversions from degrees to radians needed for Math functions.
/// </summary>
protected readonly double DEG2RAD = Math.PI / 180.0d;
/// <summary>
/// For conversions from radians to degrees.
/// </summary>
protected readonly double RAD2DEG = 180.0d / Math.PI;
/// <summary>
/// Add angle to list of angles used for calculation.
/// </summary>
/// <param name="angle"></param>
public void Add(double angle)
{
// safe measures to stay within [0..<360]
angle = angle < 0 ? angle + 360 : angle >= 360 ? angle - 360 : angle;
_angles.Add(angle);
}
/// <summary>
/// Calculate smoothed angle from previously added angles.
/// </summary>
/// <returns>Smoothed angle</returns>
public abstract double Calculate();
[System.Diagnostics.Conditional("UNITY_EDITOR")]
protected void debugLogAngle(double raw, double smoothed)
{
double debugAngle = Math.Atan2(Math.Sin(smoothed * DEG2RAD), Math.Cos(smoothed * DEG2RAD)) * RAD2DEG;
debugAngle = debugAngle < 0 ? debugAngle + 360 : debugAngle >= 360 ? debugAngle - 360 : debugAngle;
Debug.Log(string.Format("{0:0.000} => {1:0.000}", raw, smoothed));
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 96b2e341a57b7f44a965174f6d88c67a
timeCreated: 1527175159
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
namespace Mapbox.Unity.Location
{
using System;
using System.Linq;
/// <summary>
/// Simple averaging latest 'n' values.
/// </summary>
public class AngleSmoothingAverage : AngleSmoothingAbstractBase
{
public override double Calculate()
{
// calc mean heading taking into account that eg 355° and 5° should result in 0° and not 180°
// refs:
// https://en.wikipedia.org/wiki/Mean_of_circular_quantities
// https://rosettacode.org/wiki/Averages/Mean_angle
// https://rosettacode.org/wiki/Averages/Mean_angle#C.23
double cos = _angles.Sum(a => Math.Cos(a * DEG2RAD)) / _angles.Count;
double sin = _angles.Sum(a => Math.Sin(a * DEG2RAD)) / _angles.Count;
// round as we don't need super high precision
double finalAngle = Math.Round(Math.Atan2(sin, cos) * RAD2DEG, 2);
debugLogAngle(finalAngle, finalAngle);
// stay within [0..<360]
finalAngle = finalAngle < 0 ? finalAngle + 360 : finalAngle >= 360 ? finalAngle - 360 : finalAngle;
debugLogAngle(finalAngle, finalAngle);
return finalAngle;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 6843ccbf70c208645a89b4c8c37a4ecf
timeCreated: 1527174926
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
namespace Mapbox.Unity.Location
{
using System;
using System.Linq;
/// <summary>
/// <para>Smooths angles via a exponential moving average (EMA).</para>
/// <para>https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average</para>
/// <para>https://stackoverflow.com/questions/8450020/calculate-exponential-moving-average-on-a-queue-in-c-sharp</para>
/// </summary>
public class AngleSmoothingEMA : AngleSmoothingAbstractBase
{
public AngleSmoothingEMA() : base()
{
_alpha = 2.0d / (double)(_measurements + 1);
}
private double _alpha;
public override double Calculate()
{
// reverse order, _angles[0] is latest
double[] angles = _angles.Reverse().ToArray();
// since we cannot work directly on the angles (eg think about 355 and 5)
// we convert to cartesian coordinates and apply filtering there
// aproximation should be good enough for the use case of compass filtering
// differences occur only at the 2nd or 3rd digit after the decimal point
double sin = Math.Sin(angles[0] * DEG2RAD);
double cos = Math.Cos(angles[0] * DEG2RAD);
debugLogAngle(angles[0], Math.Atan2(sin, cos) * RAD2DEG);
for (int i = 1; i < angles.Length; i++)
{
sin = (Math.Sin(angles[i] * DEG2RAD) - sin) * _alpha + sin;
cos = (Math.Cos(angles[i] * DEG2RAD) - cos) * _alpha + cos;
debugLogAngle(angles[i], Math.Atan2(sin, cos) * RAD2DEG);
}
// round, don't need crazy precision
double finalAngle = Math.Round(Math.Atan2(sin, cos) * RAD2DEG, 2);
debugLogAngle(finalAngle, finalAngle);
// stay within [0..<360]
finalAngle = finalAngle < 0 ? finalAngle + 360 : finalAngle >= 360 ? finalAngle - 360 : finalAngle;
debugLogAngle(finalAngle, finalAngle);
return finalAngle;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 26ab886ba5422c248b693e60311088c7
timeCreated: 1527174401
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
namespace Mapbox.Unity.Location
{
using System;
using System.Linq;
using UnityEngine;
/// <summary>
/// Smoothing via low pass filter
/// </summary>
public class AngleSmoothingLowPass : AngleSmoothingAbstractBase
{
[SerializeField]
[Tooltip("Factor to change smoothing. The lower the factor the slower the angle changes. '1' would be no smoothing")]
[Range(0.01f, 0.9f)]
private double _smoothingFactor = 0.5;
public AngleSmoothingLowPass() : base() { }
public AngleSmoothingLowPass(double smoothingFactor) : base()
{
_smoothingFactor = smoothingFactor;
}
public override double Calculate()
{
// reverse order, latest in _angles is at [0]
double[] angles = _angles.Reverse().ToArray();
// since we cannot work directly on the angles (eg think about 355 and 5)
// we convert to cartesian coordinates and apply filtering there
// aproximation should be good enough for the use case of compass filtering
// differences occur only at the 2nd or 3rd digit after the decimal point
double lastSin = Math.Sin(angles[0] * DEG2RAD);
double lastCos = Math.Cos(angles[0] * DEG2RAD);
debugLogAngle(angles[0], Math.Atan2(lastSin, lastCos) * RAD2DEG);
for (int i = 1; i < angles.Length; i++)
{
double angle = angles[i];
lastSin = _smoothingFactor * Math.Sin(angle * DEG2RAD) + (1 - _smoothingFactor) * lastSin;
lastCos = _smoothingFactor * Math.Cos(angle * DEG2RAD) + (1 - _smoothingFactor) * lastCos;
debugLogAngle(angles[i], Math.Atan2(lastSin, lastCos) * RAD2DEG);
}
// round, don't need crazy precision
double finalAngle = Math.Round(Math.Atan2(lastSin, lastCos) * RAD2DEG, 2);
debugLogAngle(finalAngle, finalAngle);
// stay within [0..<360]
finalAngle = finalAngle < 0 ? finalAngle + 360 : finalAngle >= 360 ? finalAngle - 360 : finalAngle;
debugLogAngle(finalAngle, finalAngle);
return finalAngle;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 5bc20e719eeb82d448d4698d29d526c0
timeCreated: 1527174376
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
namespace Mapbox.Unity.Location
{
/// <summary>
/// Doesn't do any calculations. Just passes latest value through.
/// </summary>
public class AngleSmoothingNoOp : AngleSmoothingAbstractBase
{
public override double Calculate() { return _angles[0]; }
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 1ea49ff9cb53e9b44b5fa981d0009588
timeCreated: 1527179489
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
namespace Mapbox.Unity.Location
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IAngleSmoothing
{
void Add(double angle);
double Calculate();
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 0e44baa04db660e4a953a1c006235c94
timeCreated: 1527174166
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: