PositionCalculator.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. using Assets.StreetLight.Interfaces;
  2. using Assets.StreetLight.Poco;
  3. using MathNet.Numerics.LinearAlgebra;
  4. using MathNet.Numerics.LinearAlgebra.Double;
  5. using System;
  6. using System.Collections.Generic;
  7. using UnityEngine;
  8. namespace Assets.StreetLight.Scripts
  9. {
  10. public class PositionCalculator
  11. {
  12. private List<CalibrationPoint> calibrationVectors;
  13. private Matrix<double> homography;
  14. public PositionCalculator(List<CalibrationPoint> calibrationVectors)
  15. {
  16. this.calibrationVectors = calibrationVectors;
  17. CalculateHomographyRansac();
  18. }
  19. private void CalculateHomographyRansac()
  20. {
  21. if (!(calibrationVectors?.Count >= 4))
  22. {
  23. throw new InvalidOperationException("Must have at least 4 correspondences to calculate a homography.");
  24. }
  25. var iterations = RansacIterations(0.35f, 4, 0.99f);
  26. for (int i = 0; i < iterations; i++)
  27. {
  28. }
  29. }
  30. private int RansacIterations(float inlierProbability, int samplesPerIteration, float successProbability)
  31. {
  32. return (int)Math.Ceiling(Math.Log(1 - successProbability, 1 - Math.Pow(inlierProbability, samplesPerIteration)));
  33. }
  34. private void CalculateHomographySimple()
  35. {
  36. if (!(calibrationVectors?.Count >= 4))
  37. {
  38. throw new InvalidOperationException("Must have at least 4 correspondences to calculate a homography.");
  39. }
  40. var cv = calibrationVectors;
  41. Matrix<double> matrixA = DenseMatrix.OfArray(new double[,]
  42. {
  43. {cv[0].WorldPosition.x, cv[0].WorldPosition.z, 1, 0, 0, 0, -cv[0].UnityPosition.x*cv[0].WorldPosition.x, -cv[0].UnityPosition.x*cv[0].WorldPosition.z},
  44. {0, 0, 0, cv[0].WorldPosition.x, cv[0].WorldPosition.z, 1, -cv[0].UnityPosition.z*cv[0].WorldPosition.x, -cv[0].UnityPosition.z*cv[0].WorldPosition.z},
  45. {cv[1].WorldPosition.x, cv[1].WorldPosition.z, 1, 0, 0, 0, -cv[1].UnityPosition.x*cv[1].WorldPosition.x, -cv[1].UnityPosition.x*cv[1].WorldPosition.z},
  46. {0, 0, 0, cv[1].WorldPosition.x, cv[1].WorldPosition.z, 1, -cv[1].UnityPosition.z*cv[1].WorldPosition.x, -cv[1].UnityPosition.z*cv[1].WorldPosition.z},
  47. {cv[2].WorldPosition.x, cv[2].WorldPosition.z, 1, 0, 0, 0, -cv[2].UnityPosition.x*cv[2].WorldPosition.x, -cv[2].UnityPosition.x*cv[2].WorldPosition.z},
  48. {0, 0, 0, cv[2].WorldPosition.x, cv[2].WorldPosition.z, 1, -cv[2].UnityPosition.z*cv[2].WorldPosition.x, -cv[2].UnityPosition.z*cv[2].WorldPosition.z},
  49. {cv[3].WorldPosition.x, cv[3].WorldPosition.z, 1, 0, 0, 0, -cv[3].UnityPosition.x*cv[3].WorldPosition.x, -cv[3].UnityPosition.x*cv[3].WorldPosition.z},
  50. {0, 0, 0, cv[3].WorldPosition.x, cv[3].WorldPosition.z, 1, -cv[3].UnityPosition.z*cv[3].WorldPosition.x, -cv[3].UnityPosition.z*cv[3].WorldPosition.z}
  51. });
  52. Matrix<double> matrixB = DenseMatrix.OfArray(new double[,]
  53. {
  54. {cv[0].UnityPosition.x},
  55. {cv[0].UnityPosition.z},
  56. {cv[1].UnityPosition.x},
  57. {cv[1].UnityPosition.z},
  58. {cv[2].UnityPosition.x},
  59. {cv[2].UnityPosition.z},
  60. {cv[3].UnityPosition.x},
  61. {cv[3].UnityPosition.z}
  62. });
  63. var lambda = (matrixA.Transpose() * matrixA).Inverse() * matrixA.Transpose() * matrixB;
  64. homography = DenseMatrix.OfArray(new double[,]
  65. {
  66. { lambda[0,0], lambda[1,0], lambda[2,0]},
  67. { lambda[3,0], lambda[4,0], lambda[5,0]},
  68. { lambda[6,0], lambda[7,0], 1}
  69. });
  70. testCalibration();
  71. }
  72. public Vector3 CalculateUnityPosition(Person person)
  73. {
  74. return WorldPositionToUnityPosition(person.WorldPosition);
  75. }
  76. private Vector3 WorldPositionToUnityPosition(Vector3 worldPosition)
  77. {
  78. var vector = DenseVector.OfArray(new double[] { worldPosition.x, worldPosition.z, 1 });
  79. var output = homography * vector;
  80. var scaledOutput = output / output[2];
  81. var resultVector = new Vector3((float)scaledOutput[0], 0, (float)scaledOutput[1]);
  82. return resultVector;
  83. }
  84. /// <summary>
  85. /// For internal debugging only.
  86. /// </summary>
  87. private void testCalibration()
  88. {
  89. foreach (var c in calibrationVectors)
  90. {
  91. var test = DenseVector.OfArray(new double[] { c.WorldPosition.x, c.WorldPosition.z, 1 });
  92. var testOutput = homography * test;
  93. var scaledTestOutput = testOutput / testOutput[2];
  94. }
  95. }
  96. }
  97. }