eigen 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +14 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +45 -0
- data/Rakefile +18 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/eigen.gemspec +27 -0
- data/ext/eigen/eigen.cpp +1170 -0
- data/ext/eigen/extconf.rb +10 -0
- data/lib/eigen.rb +15 -0
- data/lib/eigen/affine3.rb +35 -0
- data/lib/eigen/angle_axis.rb +90 -0
- data/lib/eigen/isometry3.rb +36 -0
- data/lib/eigen/matrix4.rb +96 -0
- data/lib/eigen/matrixx.rb +105 -0
- data/lib/eigen/quaternion.rb +253 -0
- data/lib/eigen/vector3.rb +178 -0
- data/lib/eigen/vectorx.rb +54 -0
- data/lib/eigen/version.rb +3 -0
- metadata +144 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
require "mkmf-rice"
|
2
|
+
|
3
|
+
RbConfig::CONFIG['CXXFLAGS'].gsub! "-Wdeclaration-after-statement", ''
|
4
|
+
RbConfig::CONFIG['CXXFLAGS'].gsub! "-Wimplicit-function-declaration", ''
|
5
|
+
|
6
|
+
if !pkg_config('eigen3')
|
7
|
+
raise "cannot find the eigen3 pkg-config package in #{ENV['PKG_CONFIG_PATH']}"
|
8
|
+
end
|
9
|
+
|
10
|
+
create_makefile("eigen/eigen")
|
data/lib/eigen.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Ruby bindings for the Eigen C++ linear algebra library
|
2
|
+
module Eigen
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'eigen/eigen'
|
6
|
+
|
7
|
+
require 'eigen/affine3'
|
8
|
+
require 'eigen/angle_axis'
|
9
|
+
require 'eigen/isometry3'
|
10
|
+
require 'eigen/matrix4'
|
11
|
+
require 'eigen/matrixx'
|
12
|
+
require 'eigen/quaternion'
|
13
|
+
require 'eigen/vector3'
|
14
|
+
require 'eigen/vectorx'
|
15
|
+
require 'eigen/version'
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Eigen
|
2
|
+
class Affine3
|
3
|
+
def self.Identity
|
4
|
+
Affine3.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.from_position_orientation( v, q )
|
8
|
+
i = Affine3.Identity
|
9
|
+
i.prerotate( q )
|
10
|
+
i.pretranslate( v )
|
11
|
+
i
|
12
|
+
end
|
13
|
+
|
14
|
+
def dup
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(q)
|
19
|
+
q.kind_of?(self.class) &&
|
20
|
+
__equal__(q)
|
21
|
+
end
|
22
|
+
|
23
|
+
def *(obj)
|
24
|
+
if obj.kind_of?(Affine3)
|
25
|
+
concatenate(obj)
|
26
|
+
else
|
27
|
+
transform(obj)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
matrix.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Eigen
|
2
|
+
# Representation and manipulation of an angle axis
|
3
|
+
class AngleAxis
|
4
|
+
def dup
|
5
|
+
AngleAxis.new(angle, axis)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns the angle axis as [angle, x, y, z]
|
9
|
+
def to_a; [angle, axis.to_a] end
|
10
|
+
|
11
|
+
def from_a (array)
|
12
|
+
aa = AngleAxis.new(array[0], Eigen::Vector3.new(array[1][0], array[1][1], array[1][2]))
|
13
|
+
aa
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the identity unit quaternion (identity rotation)
|
17
|
+
def self.Identity
|
18
|
+
AngleAxis.new(0, Eigen::Vector3.new(1, 0, 0))
|
19
|
+
end
|
20
|
+
|
21
|
+
# Creates a angle axis from a quaternion
|
22
|
+
def self.from_quaternion(*args)
|
23
|
+
aa = new(0, Eigen::Vector3.new(1, 0, 0))
|
24
|
+
aa.from_quaternion(*args)
|
25
|
+
aa
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates a quaternion from a set of euler angles.
|
29
|
+
#
|
30
|
+
# See Quaternion#from_euler for details
|
31
|
+
def self.from_euler(*args)
|
32
|
+
aa = new(0, Eigen::Vector3.new(1, 0, 0))
|
33
|
+
aa.from_euler(*args)
|
34
|
+
aa
|
35
|
+
end
|
36
|
+
|
37
|
+
# Creates a quaternion from a rotation matrix
|
38
|
+
def self.from_matrix(m)
|
39
|
+
aa = new(0, Eigen::Vector3.new(1, 0, 0))
|
40
|
+
aa.from_matrix(m)
|
41
|
+
aa
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns a scaled axis representation that is equivalent to this
|
45
|
+
# quaternion
|
46
|
+
#
|
47
|
+
# @param [Float] eps see {#to_angle_axis}
|
48
|
+
# @return [Vector3]
|
49
|
+
def to_scaled_axis(eps = 1e-12)
|
50
|
+
return axis * angle
|
51
|
+
end
|
52
|
+
|
53
|
+
# Concatenates with another angle axis or transforms a vector
|
54
|
+
def *(obj)
|
55
|
+
if obj.kind_of?(AngleAxis)
|
56
|
+
concatenate(obj)
|
57
|
+
else
|
58
|
+
transform(obj)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def _dump(level) # :nodoc:
|
63
|
+
Marshal.dump(to_a)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self._load(coordinates) # :nodoc:
|
67
|
+
aa = new(0, Eigen::Vector3.new(1, 0, 0))
|
68
|
+
aa.from_a(Marshal.load(coordinates))
|
69
|
+
aa
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_s # :nodoc:
|
73
|
+
"AngleAxis( angle #{angle}, axis(#{axis.x}, #{axis.y}, #{axis.z}))"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Tests for equality
|
77
|
+
#
|
78
|
+
# Since Quaternion stores the coordinates as floating-point values, this is
|
79
|
+
# a bad test. Use
|
80
|
+
#
|
81
|
+
# (v - other_v).norm < threshold
|
82
|
+
#
|
83
|
+
# instead
|
84
|
+
def ==(q)
|
85
|
+
q.kind_of?(self.class) &&
|
86
|
+
__equal__(q)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Eigen
|
2
|
+
class Isometry3
|
3
|
+
def self.Identity
|
4
|
+
Isometry3.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.from_position_orientation( v, q )
|
8
|
+
i = Isometry3.Identity
|
9
|
+
i.prerotate( q )
|
10
|
+
i.pretranslate( v )
|
11
|
+
i
|
12
|
+
end
|
13
|
+
|
14
|
+
def dup
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(q)
|
19
|
+
q.kind_of?(self.class) &&
|
20
|
+
__equal__(q)
|
21
|
+
end
|
22
|
+
|
23
|
+
def *(obj)
|
24
|
+
if obj.kind_of?(Isometry3)
|
25
|
+
concatenate(obj)
|
26
|
+
else
|
27
|
+
transform(obj)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
matrix.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Eigen
|
2
|
+
# Matrix 4x4
|
3
|
+
class Matrix4
|
4
|
+
# @!method [](row, col)
|
5
|
+
# @param [Integer] row the row index
|
6
|
+
# @param [Integer] col the column index
|
7
|
+
|
8
|
+
# Create a new matrix from the content of an array
|
9
|
+
#
|
10
|
+
# @param [Array<Numeric>] the values. It must be of size at most 16.
|
11
|
+
# If smaller than 16, the rest is filled with zeroes
|
12
|
+
#
|
13
|
+
# @return [Matrix4]
|
14
|
+
def self.from_a(*args)
|
15
|
+
m = new
|
16
|
+
m.from_a(*args)
|
17
|
+
m
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the values flattened in a ruby array
|
21
|
+
#
|
22
|
+
# @param [Boolean] column_major if true, the values of a column will be
|
23
|
+
# adjacent in the resulting array, if not the values of a row will
|
24
|
+
# @return [Array<Numeric>]
|
25
|
+
#
|
26
|
+
# @example column-major ordering
|
27
|
+
# matrix.to_s => Matrix4(1 2 3 4
|
28
|
+
# 5 6 7 8
|
29
|
+
# 9 10 11 12
|
30
|
+
# 13 14 15 16)
|
31
|
+
# matrix.to_a(true) => [1 5 9 13 2 6 10 14 ...]
|
32
|
+
def to_a(column_major=true)
|
33
|
+
a = []
|
34
|
+
if column_major
|
35
|
+
for j in 0..3
|
36
|
+
for i in 0..3
|
37
|
+
a << self[i,j]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
for i in 0..3
|
42
|
+
for j in 0..3
|
43
|
+
a << self[i,j]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
a
|
48
|
+
end
|
49
|
+
|
50
|
+
# sets matrix from a 1d array
|
51
|
+
def from_a(array, column_major=true)
|
52
|
+
if array.size > 16
|
53
|
+
raise ArgumentError, "array should be of size maximum 16"
|
54
|
+
end
|
55
|
+
|
56
|
+
16.times do |i|
|
57
|
+
v = array[i] || 0
|
58
|
+
if column_major
|
59
|
+
self[i%4,i/4] = v
|
60
|
+
else
|
61
|
+
self[i/4,i%4] = v
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def ==(m)
|
67
|
+
m.kind_of?(self.class) &&
|
68
|
+
__equal__(m)
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_s(line_format = "%g %g %g %g") # :nodoc:
|
72
|
+
lines = to_a.each_slice(3).to_s
|
73
|
+
<<-EOSTRING
|
74
|
+
Matrix4(#{line_format % lines[0]}"
|
75
|
+
#{line_format % lines[1]}"
|
76
|
+
#{line_format % lines[2]}"
|
77
|
+
#{line_format % lines[3]})"
|
78
|
+
EOSTRING
|
79
|
+
end
|
80
|
+
|
81
|
+
def _dump(level)
|
82
|
+
to_a.pack("E*")
|
83
|
+
end
|
84
|
+
|
85
|
+
def self._load(elements) # :nodoc:
|
86
|
+
m = new
|
87
|
+
if elements.size == 8 * 16
|
88
|
+
m.from_a(elements.unpack("E*"))
|
89
|
+
else
|
90
|
+
m.from_a(Marshal.load(elements)['data'])
|
91
|
+
end
|
92
|
+
m
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Eigen
|
2
|
+
# Abritary size vector
|
3
|
+
class MatrixX
|
4
|
+
def dup
|
5
|
+
MatrixX.from_a(to_a, rows, cols)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.Zero(rows, cols)
|
9
|
+
m = new(rows, cols)
|
10
|
+
rows.times do |r|
|
11
|
+
cols.times do |c|
|
12
|
+
m[r, c] = 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
m
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.from_a(*args)
|
19
|
+
m = new
|
20
|
+
m.from_a(*args)
|
21
|
+
m
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the array value in a vector
|
25
|
+
def to_a(column_major=true)
|
26
|
+
a = []
|
27
|
+
if column_major
|
28
|
+
for j in 0..cols()-1
|
29
|
+
for i in 0..rows()-1
|
30
|
+
a << self[i,j]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
else
|
34
|
+
for i in 0..rows()-1
|
35
|
+
for j in 0..cols()-1
|
36
|
+
a << self[i,j]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
a
|
41
|
+
end
|
42
|
+
|
43
|
+
# sets matrix from a 1d array
|
44
|
+
def from_a(array,nrows=-1,ncols=-1,column_major=true)
|
45
|
+
if nrows == -1 && ncols == -1
|
46
|
+
nrows = rows
|
47
|
+
ncols = cols
|
48
|
+
elsif nrows == -1
|
49
|
+
nrows = array.size / ncols
|
50
|
+
elsif ncols == -1
|
51
|
+
ncols = array.size / nrows
|
52
|
+
end
|
53
|
+
resize(nrows,ncols)
|
54
|
+
array.each_index do |i|
|
55
|
+
v = array[i]
|
56
|
+
if !v
|
57
|
+
v = 0.0
|
58
|
+
end
|
59
|
+
if column_major
|
60
|
+
self[i%nrows,i/nrows] = v
|
61
|
+
else
|
62
|
+
self[i/ncols,i%ncols] = v
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def pretty_print(pp)
|
68
|
+
for i in 0..rows()-1
|
69
|
+
for j in 0..cols()-1
|
70
|
+
pp.text " #{self[i,j]}"
|
71
|
+
end
|
72
|
+
pp.text "\n"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def ==(m)
|
77
|
+
m.kind_of?(self.class) &&
|
78
|
+
__equal__(m)
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_s # :nodoc:
|
82
|
+
str = "MatrixX(\n"
|
83
|
+
for i in 0..rows()-1
|
84
|
+
for j in 0..cols()-1
|
85
|
+
str += "#{self[i,j]} "
|
86
|
+
end
|
87
|
+
str[-1] = "\n"
|
88
|
+
end
|
89
|
+
str += ")"
|
90
|
+
str
|
91
|
+
end
|
92
|
+
|
93
|
+
def _dump(level) # :nodoc:
|
94
|
+
Marshal.dump({'rows' => rows, 'cols' => cols, 'data' => to_a})
|
95
|
+
end
|
96
|
+
|
97
|
+
def self._load(coordinates) # :nodoc:
|
98
|
+
o = Marshal.load(coordinates)
|
99
|
+
m = new(o['rows'],o['cols'])
|
100
|
+
m.from_a(o['data'],o['rows'],o['cols'])
|
101
|
+
m
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -0,0 +1,253 @@
|
|
1
|
+
module Eigen
|
2
|
+
# Representation and manipulation of a quaternion
|
3
|
+
class Quaternion
|
4
|
+
def dup
|
5
|
+
Quaternion.new(w, x, y, z)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns the quaternion as [w, x, y, z]
|
9
|
+
def to_a; [w, x, y, z] end
|
10
|
+
|
11
|
+
# Returns the identity unit quaternion (identity rotation)
|
12
|
+
def self.Identity
|
13
|
+
Quaternion.new(1, 0, 0, 0)
|
14
|
+
end
|
15
|
+
|
16
|
+
# DEPRECATED: please use identity instead. Returns the unit quaternion (identity rotation)
|
17
|
+
def self.Unit
|
18
|
+
warn "[DEPRECATED] Quaternion.unit, please use Quaternion.identity."
|
19
|
+
self.Identity
|
20
|
+
end
|
21
|
+
|
22
|
+
# Creates a quaternion from an angle and axis description
|
23
|
+
def self.from_angle_axis(*args)
|
24
|
+
q = new(1, 0, 0, 0)
|
25
|
+
q.from_angle_axis(*args)
|
26
|
+
q
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns an angle,axis representation equivalent to this quaternion
|
30
|
+
#
|
31
|
+
# If the angle turns out to be PI, there are two solutions and the one
|
32
|
+
# with positive Z component is chosen.
|
33
|
+
#
|
34
|
+
# @param [Float] eps if the angle turns out to be closer to zero than eps, the
|
35
|
+
# rotation axis is undefined and chosen to be the Z axis.
|
36
|
+
#
|
37
|
+
# @return [(Float,Vector3)] the angle and axis. The angle is in [0, PI]
|
38
|
+
def to_angle_axis(eps = 1e-12)
|
39
|
+
w, x, y, z = to_a
|
40
|
+
norm = Math.sqrt(x*x+y*y+z*z);
|
41
|
+
if norm < eps
|
42
|
+
return 0, Eigen::Vector3.new(0,0,1);
|
43
|
+
end
|
44
|
+
|
45
|
+
angle = 2.0 * Math.atan2(norm, w);
|
46
|
+
axis = Eigen::Vector3.new(x, y, z) / norm
|
47
|
+
return angle, axis
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns a scaled axis representation that is equivalent to this
|
51
|
+
# quaternion
|
52
|
+
#
|
53
|
+
# @param [Float] eps see {#to_angle_axis}
|
54
|
+
# @return [Vector3]
|
55
|
+
def to_scaled_axis(eps = 1e-12)
|
56
|
+
angle, axis = to_angle_axis(eps)
|
57
|
+
return axis * angle
|
58
|
+
end
|
59
|
+
|
60
|
+
# Creates a quaternion from a set of euler angles.
|
61
|
+
#
|
62
|
+
# See Quaternion#from_euler for details
|
63
|
+
def self.from_euler(*args)
|
64
|
+
q = new(1, 0, 0, 0)
|
65
|
+
q.from_euler(*args)
|
66
|
+
q
|
67
|
+
end
|
68
|
+
|
69
|
+
# Creates a quaternion from a rotation matrix
|
70
|
+
def self.from_matrix(m)
|
71
|
+
q = new(1, 0, 0, 0)
|
72
|
+
q.from_matrix(m)
|
73
|
+
q
|
74
|
+
end
|
75
|
+
|
76
|
+
# Extracts the yaw angle from this quaternion
|
77
|
+
#
|
78
|
+
# It decomposes the quaternion in euler angles using to_euler
|
79
|
+
# and returns the first element. See #to_euler for details.
|
80
|
+
def yaw
|
81
|
+
to_euler[0]
|
82
|
+
end
|
83
|
+
|
84
|
+
def pitch
|
85
|
+
to_euler[1]
|
86
|
+
end
|
87
|
+
|
88
|
+
def roll
|
89
|
+
to_euler[2]
|
90
|
+
end
|
91
|
+
|
92
|
+
# The inverse of #yaw
|
93
|
+
def self.from_yaw(yaw)
|
94
|
+
from_euler(Eigen::Vector3.new(yaw, 0, 0), 2, 1, 0)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Concatenates with another quaternion or transforms a vector
|
98
|
+
def *(obj)
|
99
|
+
if obj.kind_of?(Quaternion)
|
100
|
+
concatenate(obj)
|
101
|
+
else
|
102
|
+
transform(obj)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def _dump(level) # :nodoc:
|
107
|
+
Marshal.dump(to_a)
|
108
|
+
end
|
109
|
+
|
110
|
+
def self._load(coordinates) # :nodoc:
|
111
|
+
new(*Marshal.load(coordinates))
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_s # :nodoc:
|
115
|
+
"Quaternion(#{w}, (#{x}, #{y}, #{z}))"
|
116
|
+
end
|
117
|
+
|
118
|
+
# Tests for equality
|
119
|
+
#
|
120
|
+
# Since Quaternion stores the coordinates as floating-point values, this is
|
121
|
+
# a bad test. Use
|
122
|
+
#
|
123
|
+
# (v - other_v).norm < threshold
|
124
|
+
#
|
125
|
+
# instead
|
126
|
+
def ==(q)
|
127
|
+
q.kind_of?(self.class) &&
|
128
|
+
__equal__(q)
|
129
|
+
end
|
130
|
+
|
131
|
+
def re
|
132
|
+
w
|
133
|
+
end
|
134
|
+
|
135
|
+
def re=(value)
|
136
|
+
self.w = value
|
137
|
+
end
|
138
|
+
|
139
|
+
def im
|
140
|
+
[x,y,z]
|
141
|
+
end
|
142
|
+
|
143
|
+
def im=(value)
|
144
|
+
self.x, self.y, self.z = *value
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# :method: w
|
149
|
+
|
150
|
+
##
|
151
|
+
# :method: x
|
152
|
+
|
153
|
+
##
|
154
|
+
# :method: y
|
155
|
+
|
156
|
+
##
|
157
|
+
# :method: z
|
158
|
+
|
159
|
+
##
|
160
|
+
# :method: w=
|
161
|
+
|
162
|
+
##
|
163
|
+
# :method: x=
|
164
|
+
|
165
|
+
##
|
166
|
+
# :method: y=
|
167
|
+
|
168
|
+
##
|
169
|
+
# :method: z=
|
170
|
+
|
171
|
+
##
|
172
|
+
# :method: concatenate
|
173
|
+
# :call-seq:
|
174
|
+
# concatenate(q)
|
175
|
+
#
|
176
|
+
# Returns the rotation in which +q+ is applied first and +self+ second
|
177
|
+
|
178
|
+
##
|
179
|
+
# :method: transform
|
180
|
+
# :call-seq:
|
181
|
+
# transform(v)
|
182
|
+
#
|
183
|
+
# Transforms the given Eigen::Vector3 by the rotation represented with
|
184
|
+
# this quaternion
|
185
|
+
|
186
|
+
##
|
187
|
+
# :method: normalize!
|
188
|
+
#
|
189
|
+
# Normalizes this quaternion
|
190
|
+
|
191
|
+
##
|
192
|
+
# :method: normalize
|
193
|
+
#
|
194
|
+
# Returns a quaternion that is a normalized version of +self+
|
195
|
+
|
196
|
+
##
|
197
|
+
# :method: approx?
|
198
|
+
# :call-seq:
|
199
|
+
# approx?(q, tolerance)
|
200
|
+
#
|
201
|
+
# Returns true if +self+ and +q+ do not differ from more than
|
202
|
+
# +tolerance+. The comparison is done on a coordinate basis.
|
203
|
+
|
204
|
+
##
|
205
|
+
# :method: to_euler
|
206
|
+
# :call-seq:
|
207
|
+
# to_euler => Eigen::Vector3(a0, a1, a2)
|
208
|
+
#
|
209
|
+
# Decomposes this quaternion in euler angles so that +self+ can be
|
210
|
+
# obtained by applying the following rotations in order:
|
211
|
+
#
|
212
|
+
# rotation of a2 around x-axis
|
213
|
+
# rotation of a1 around y-axis
|
214
|
+
# rotation of a0 around z-axis
|
215
|
+
#
|
216
|
+
# assuming angles in range of: a0:(-pi,pi), a1:(-pi/2,pi/2), a2:(-pi/2,pi/2)
|
217
|
+
#
|
218
|
+
# note that
|
219
|
+
#
|
220
|
+
# self == Quaternion.from_euler(to_euler, axis0, axis1, axis2)
|
221
|
+
|
222
|
+
##
|
223
|
+
# :method: from_euler
|
224
|
+
# :call-seq:
|
225
|
+
# from_euler(Eigen::Vector3(a0, a1, a2), axis0, axis1, axis2)
|
226
|
+
#
|
227
|
+
# Resets this quaternion so that it represents the rotation obtained by
|
228
|
+
# applying the following rotations in order:
|
229
|
+
#
|
230
|
+
# rotation of a2 around axis2
|
231
|
+
# rotation of a1 around axis1
|
232
|
+
# rotation of a0 around axis0
|
233
|
+
#
|
234
|
+
# note that
|
235
|
+
#
|
236
|
+
# self == Quaternion.from_euler(to_euler, axis0, axis1, axis2)
|
237
|
+
|
238
|
+
##
|
239
|
+
# :method: inverse
|
240
|
+
# :call-seq:
|
241
|
+
# inverse => quaternion
|
242
|
+
#
|
243
|
+
# Computes the quaternion that is inverse of this one
|
244
|
+
|
245
|
+
|
246
|
+
# @return [Qt::Quaternion] the Qt quaternion that is identical to this
|
247
|
+
# one
|
248
|
+
def to_qt
|
249
|
+
Qt::Quaternion.new(w, x, y, z)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|