eigen 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|