test_rotmat.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #!/usr/bin/env python
  2. """
  3. Unit tests for the rotmat library
  4. """
  5. from __future__ import absolute_import, division, print_function
  6. from math import radians, degrees
  7. import unittest
  8. import random
  9. import numpy as np
  10. from pymavlink.rotmat import Vector3, Matrix3, Plane, Line
  11. class VectorTest(unittest.TestCase):
  12. """
  13. Class to test Vector3
  14. """
  15. def __init__(self, *args, **kwargs):
  16. """Constructor, set up some data that is reused in many tests"""
  17. super(VectorTest, self).__init__(*args, **kwargs)
  18. def test_constructor(self):
  19. """Test the constructor functionality"""
  20. v1 = Vector3(1, 0.2, -3)
  21. v2 = Vector3([1, 0.2, -3])
  22. v3 = Vector3([1, 0.3, -3])
  23. assert v1 == v2
  24. assert v1 != v3
  25. assert str(v1) == "Vector3(1.00, 0.20, -3.00)"
  26. def test_maths(self):
  27. """Test simple maths"""
  28. v1 = Vector3(1, 2, -3)
  29. v2 = Vector3(1, 3, 3)
  30. assert v1 + v2 == Vector3(2, 5, 0)
  31. assert v1 - v2 == Vector3(0, -1, -6)
  32. assert (v1 * 3) == Vector3(3, 6, -9)
  33. assert v1 * v2 == -2
  34. assert v1 % v2 == Vector3(15.00, -6.00, 1.00)
  35. np.testing.assert_almost_equal(v2.length(), 4.358898943540674)
  36. assert v2.normalized().close(Vector3(0.23, 0.69, 0.69), tol=1e-2)
  37. np.testing.assert_almost_equal(v1.angle(v2), 1.693733631245806)
  38. class MatrixTest(unittest.TestCase):
  39. """
  40. Class to test Matrix3
  41. """
  42. def __init__(self, *args, **kwargs):
  43. """Constructor, set up some data that is reused in many tests"""
  44. super(MatrixTest, self).__init__(*args, **kwargs)
  45. def test_constructor(self):
  46. """Test the constructor functionality"""
  47. m1 = Matrix3(Vector3(1, 0, 0), Vector3(1, 5, 0), Vector3(1, 0, -7))
  48. m2 = Matrix3()
  49. assert str(m1) == 'Matrix3((1.00, 0.00, 0.00), (1.00, 5.00, 0.00), (1.00, 0.00, -7.00))'
  50. assert str(m2) == 'Matrix3((1.00, 0.00, 0.00), (0.00, 1.00, 0.00), (0.00, 0.00, 1.00))'
  51. def test_maths(self):
  52. m1 = Matrix3(Vector3(1, 0, 0), Vector3(1, 5, 0), Vector3(1, 0, -7))
  53. m2 = Matrix3()
  54. assert m1 + m2 == Matrix3(Vector3(2, 0, 0), Vector3(1, 6, 0), Vector3(1, 0, -6))
  55. assert m1 - m2 == Matrix3(Vector3(0, 0, 0), Vector3(1, 4, 0), Vector3(1, 0, -8))
  56. assert m1 * 3 == Matrix3(Vector3(3, 0, 0), Vector3(3, 15, 0), Vector3(3, 0, -21))
  57. assert m1 * m1 == Matrix3(Vector3(1, 0, 0), Vector3(6, 25, 0), Vector3(-6, 0, 49))
  58. assert m1.transposed() == Matrix3(Vector3(1, 1, 1), Vector3(0, 5, 0), Vector3(0, 0, -7))
  59. def test_euler(self):
  60. '''check that from_euler() and to_euler() are consistent'''
  61. m = Matrix3()
  62. for r in range(-179, 179, 10):
  63. for p in range(-89, 89, 10):
  64. for y in range(-179, 179, 10):
  65. m.from_euler(radians(r), radians(p), radians(y))
  66. (r2, p2, y2) = m.to_euler()
  67. v1 = Vector3(r, p, y)
  68. v2 = Vector3(degrees(r2), degrees(p2), degrees(y2))
  69. diff = v1 - v2
  70. assert diff.length() < 1.0e-12
  71. def test_euler312(self):
  72. '''check that from_euler312() and to_euler312() are consistent'''
  73. m = Matrix3()
  74. for r in range(-89, 89, 10):
  75. for p in range(-179, 179, 10):
  76. for y in range(-179, 179, 10):
  77. m.from_euler312(radians(r), radians(p), radians(y))
  78. (r2, p2, y2) = m.to_euler312()
  79. v1 = Vector3(r, p, y)
  80. v2 = Vector3(degrees(r2), degrees(p2), degrees(y2))
  81. diff = v1 - v2
  82. assert diff.length() < 1.0e-12
  83. def test_matrixops(self):
  84. m1 = Matrix3(Vector3(1, 0, 0), Vector3(1, 5, 0), Vector3(1, 0, -7))
  85. m1.normalize()
  86. print(m1)
  87. assert m1.close(Matrix3(Vector3(0.2, -0.98, 0), Vector3(0.1, 1, 0), Vector3(0, 0, 1)), tol=1e-2)
  88. np.testing.assert_almost_equal(m1.trace(), 2.19115332535)
  89. m1.rotate(Vector3(0.2,-0.98,0))
  90. assert m1.close(Matrix3(Vector3(0.2,-0.98,0), Vector3(0.1,1,-0.3), Vector3(0.98,0.2,1)), tol=1e-2)
  91. def test_axisangle(self):
  92. axis = Vector3(0, 1, 0)
  93. angle = radians(45)
  94. m1 = Matrix3()
  95. m1.from_axis_angle(axis, angle)
  96. #print(m1)
  97. assert m1.close(Matrix3(Vector3(0.71, 0.00, 0.71),
  98. Vector3(0.00, 1.00, 0.00),
  99. Vector3(-0.71, 0.00, 0.71)), tol=1e-2)
  100. def test_two_vectors(self):
  101. '''test the from_two_vectors() method'''
  102. for i in range(100):
  103. v1 = Vector3(1, 0.2, -3)
  104. v2 = Vector3(random.uniform(-5, 5), random.uniform(-5, 5), random.uniform(-5, 5))
  105. m = Matrix3()
  106. m.from_two_vectors(v1, v2)
  107. v3 = m * v1
  108. diff = v3.normalized() - v2.normalized()
  109. (r, p, y) = m.to_euler()
  110. assert diff.length() < 0.001
  111. class LinePlaneTest(unittest.TestCase):
  112. """
  113. Class to test Line and Plane classes
  114. """
  115. def __init__(self, *args, **kwargs):
  116. """Constructor, set up some data that is reused in many tests"""
  117. super(LinePlaneTest, self).__init__(*args, **kwargs)
  118. def test_plane(self):
  119. '''testing line/plane intersection'''
  120. plane = Plane(Vector3(0, 0, 0), Vector3(0, 0, 1))
  121. line = Line(Vector3(0, 0, 100), Vector3(10, 10, -90))
  122. p = line.plane_intersection(plane)
  123. assert p.close(Vector3(11.11, 11.11, 0.00), tol=1e-2)
  124. if __name__ == '__main__':
  125. unittest.main()