@@ -257,25 +257,79 @@ def test_staticconstructors(self):
257257 UnitQuaternion .Rz (theta , "deg" ).R , rotz (theta , "deg" )
258258 )
259259
260+ def test_constructor_RPY (self ):
260261 # 3 angle
262+ q = UnitQuaternion .RPY ([0.1 , 0.2 , 0.3 ])
263+ self .assertIsInstance (q , UnitQuaternion )
264+ self .assertEqual (len (q ), 1 )
265+ nt .assert_array_almost_equal (q .R , rpy2r (0.1 , 0.2 , 0.3 ))
266+ q = UnitQuaternion .RPY (0.1 , 0.2 , 0.3 )
267+ self .assertIsInstance (q , UnitQuaternion )
268+ self .assertEqual (len (q ), 1 )
269+ nt .assert_array_almost_equal (q .R , rpy2r (0.1 , 0.2 , 0.3 ))
270+ q = UnitQuaternion .RPY (np .r_ [0.1 , 0.2 , 0.3 ])
271+ self .assertIsInstance (q , UnitQuaternion )
272+ self .assertEqual (len (q ), 1 )
273+ nt .assert_array_almost_equal (q .R , rpy2r (0.1 , 0.2 , 0.3 ))
274+
261275 nt .assert_array_almost_equal (
262- UnitQuaternion .RPY ([0.1 , 0.2 , 0.3 ]).R , rpy2r (0.1 , 0.2 , 0.3 )
276+ UnitQuaternion .RPY ([10 , 20 , 30 ], unit = "deg" ).R ,
277+ rpy2r (10 , 20 , 30 , unit = "deg" ),
263278 )
264-
265279 nt .assert_array_almost_equal (
266- UnitQuaternion .Eul ([0.1 , 0.2 , 0.3 ]).R , eul2r (0.1 , 0.2 , 0.3 )
280+ UnitQuaternion .RPY ([0.1 , 0.2 , 0.3 ], order = "xyz" ).R ,
281+ rpy2r (0.1 , 0.2 , 0.3 , order = "xyz" ),
282+ )
283+
284+ angles = np .array (
285+ [[0.1 , 0.2 , 0.3 ], [0.2 , 0.3 , 0.4 ], [0.3 , 0.4 , 0.5 ], [0.4 , 0.5 , 0.6 ]]
267286 )
287+ q = UnitQuaternion .RPY (angles )
288+ self .assertIsInstance (q , UnitQuaternion )
289+ self .assertEqual (len (q ), 4 )
290+ for i in range (4 ):
291+ nt .assert_array_almost_equal (q [i ].R , rpy2r (angles [i , :]))
292+
293+ q = UnitQuaternion .RPY (angles , order = "xyz" )
294+ self .assertIsInstance (q , UnitQuaternion )
295+ self .assertEqual (len (q ), 4 )
296+ for i in range (4 ):
297+ nt .assert_array_almost_equal (q [i ].R , rpy2r (angles [i , :], order = "xyz" ))
268298
299+ angles *= 10
300+ q = UnitQuaternion .RPY (angles , unit = "deg" )
301+ self .assertIsInstance (q , UnitQuaternion )
302+ self .assertEqual (len (q ), 4 )
303+ for i in range (4 ):
304+ nt .assert_array_almost_equal (q [i ].R , rpy2r (angles [i , :], unit = "deg" ))
305+
306+ def test_constructor_Eul (self ):
269307 nt .assert_array_almost_equal (
270- UnitQuaternion .RPY ([10 , 20 , 30 ], unit = "deg" ).R ,
271- rpy2r (10 , 20 , 30 , unit = "deg" ),
308+ UnitQuaternion .Eul ([0.1 , 0.2 , 0.3 ]).R , eul2r (0.1 , 0.2 , 0.3 )
272309 )
273310
274311 nt .assert_array_almost_equal (
275312 UnitQuaternion .Eul ([10 , 20 , 30 ], unit = "deg" ).R ,
276313 eul2r (10 , 20 , 30 , unit = "deg" ),
277314 )
278315
316+ angles = np .array (
317+ [[0.1 , 0.2 , 0.3 ], [0.2 , 0.3 , 0.4 ], [0.3 , 0.4 , 0.5 ], [0.4 , 0.5 , 0.6 ]]
318+ )
319+ q = UnitQuaternion .Eul (angles )
320+ self .assertIsInstance (q , UnitQuaternion )
321+ self .assertEqual (len (q ), 4 )
322+ for i in range (4 ):
323+ nt .assert_array_almost_equal (q [i ].R , eul2r (angles [i , :]))
324+
325+ angles *= 10
326+ q = UnitQuaternion .Eul (angles , unit = "deg" )
327+ self .assertIsInstance (q , UnitQuaternion )
328+ self .assertEqual (len (q ), 4 )
329+ for i in range (4 ):
330+ nt .assert_array_almost_equal (q [i ].R , eul2r (angles [i , :], unit = "deg" ))
331+
332+ def test_constructor_AngVec (self ):
279333 # (theta, v)
280334 th = 0.2
281335 v = unitvec ([1 , 2 , 3 ])
@@ -286,6 +340,7 @@ def test_staticconstructors(self):
286340 )
287341 nt .assert_array_almost_equal (UnitQuaternion .AngVec (th , - v ).R , angvec2r (th , - v ))
288342
343+ def test_constructor_EulerVec (self ):
289344 # (theta, v)
290345 th = 0.2
291346 v = unitvec ([1 , 2 , 3 ])
@@ -830,6 +885,20 @@ def test_log(self):
830885 nt .assert_array_almost_equal (q1 .log ().exp (), q1 )
831886 nt .assert_array_almost_equal (q2 .log ().exp (), q2 )
832887
888+ q = Quaternion ([q1 , q2 , q1 , q2 ])
889+ qlog = q .log ()
890+ nt .assert_array_almost_equal (qlog [0 ].exp (), q1 )
891+ nt .assert_array_almost_equal (qlog [1 ].exp (), q2 )
892+ nt .assert_array_almost_equal (qlog [2 ].exp (), q1 )
893+ nt .assert_array_almost_equal (qlog [3 ].exp (), q2 )
894+
895+ q = UnitQuaternion () # identity
896+ qlog = q .log ()
897+ nt .assert_array_almost_equal (qlog .vec , np .zeros (4 ))
898+ qq = qlog .exp ()
899+ self .assertIsInstance (qq , UnitQuaternion )
900+ nt .assert_array_almost_equal (qq .vec , np .r_ [1 , 0 , 0 , 0 ])
901+
833902 def test_concat (self ):
834903 u = Quaternion ()
835904 uu = Quaternion ([u , u , u , u ])
@@ -1018,6 +1087,27 @@ def test_miscellany(self):
10181087 nt .assert_equal (q .inner (q ), q .norm () ** 2 )
10191088 nt .assert_equal (q .inner (u ), np .dot (q .vec , u .vec ))
10201089
1090+ # def test_mean(self):
1091+ # rpy = np.ones((100, 1)) @ np.c_[0.1, 0.2, 0.3]
1092+ # q = UnitQuaternion.RPY(rpy)
1093+ # self.assertEqual(len(q), 100)
1094+ # m = q.mean()
1095+ # self.assertIsInstance(m, UnitQuaternion)
1096+ # nt.assert_array_almost_equal(m.vec, q[0].vec)
1097+
1098+ # # range of angles, mean should be the middle one, index=25
1099+ # q = UnitQuaternion.Rz(np.linspace(start=0.3, stop=0.7, num=51))
1100+ # m = q.mean()
1101+ # self.assertIsInstance(m, UnitQuaternion)
1102+ # nt.assert_array_almost_equal(m.vec, q[25].vec)
1103+
1104+ # # now add noise
1105+ # rng = np.random.default_rng(0) # reproducible random numbers
1106+ # rpy += rng.normal(scale=0.1, size=(100, 3))
1107+ # q = UnitQuaternion.RPY(rpy)
1108+ # m = q.mean()
1109+ # nt.assert_array_almost_equal(m.vec, q.RPY(0.1, 0.2, 0.3).vec)
1110+
10211111
10221112# ---------------------------------------------------------------------------------------#
10231113if __name__ == "__main__" :
0 commit comments