Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# Amira Abdel-Rahman
# (c) Massachusetts Institute of Technology 2020
struct Vector3
x::Float64
y::Float64
z::Float64
function Vector3()
x=0.0
y=0.0
z=0.0
new(x,y,z)
end
function Vector3(x,y,z)
new(x,y,z)
end
end
struct Quaternion
x::Float64
y::Float64
z::Float64
w::Float64
function Quaternion()
x=0.0
y=0.0
z=0.0
w=1.0
new(x,y,z,w)
end
function Quaternion(x,y,z,w)
new(x,y,z,w)
end
end
struct RotationMatrix
te1::Float64
te2::Float64
te3::Float64
te4::Float64
te5::Float64
te6::Float64
te7::Float64
te8::Float64
te9::Float64
te10::Float64
te11::Float64
te12::Float64
te13::Float64
te14::Float64
te15::Float64
te16::Float64
function RotationMatrix()
te1 =0.0
te2 =0.0
te3 =0.0
te4 =0.0
te5 =0.0
te6 =0.0
te7 =0.0
te8 =0.0
te9 =0.0
te10=0.0
te11=0.0
te12=0.0
te13=0.0
te14=0.0
te15=0.0
te16=0.0
new(te1,te2,te3,te4,te5,te6,te7,te8,te9,te10,te11,te12,te13,te14,te15,te16)
end
function RotationMatrix(te1,te2,te3,te4,te5,te6,te7,te8,te9,te10,te11,te12,te13,te14,te15,te16)
new(te1,te2,te3,te4,te5,te6,te7,te8,te9,te10,te11,te12,te13,te14,te15,te16)
end
end
+(f::Vector3, g::Vector3)=Vector3(f.x+g.x , f.y+g.y,f.z+g.z )
-(f::Vector3, g::Vector3)=Vector3(f.x-g.x , f.y-g.y,f.z-g.z )
*(f::Vector3, g::Vector3)=Vector3(f.x*g.x , f.y*g.y,f.z*g.z )
+(f::Vector3, g::Number)=Vector3(f.x+g , f.y+g,f.z+g )
-(f::Vector3, g::Number)=Vector3(f.x-g , f.y-g,f.z-g )
*(f::Vector3, g::Number)=Vector3(f.x*g , f.y*g,f.z*g )
+(g::Vector3, f::Number)=Vector3(f.x+g , f.y+g,f.z+g )
-(g::Vector3, f::Number)=Vector3(g-f.x , g-f.y,g-f.z )
*(g::Vector3, f::Number)=Vector3(f.x*g , f.y*g,f.z*g )
addX(f::Vector3, g::Number)=Vector3(f.x+g , f.y,f.z)
addY(f::Vector3, g::Number)=Vector3(f.x , f.y+g,f.z )
addZ(f::Vector3, g::Number)=Vector3(f.x , f.y,f.z+g )
function normalizeVector3(f::Vector3)
leng=lengthVector3(f)
if(leng>0.0)
return Vector3(f.x/leng,f.y/leng,f.z/leng)
else
return Vector3(0.0,0.0,0.0)
end
end
function lengthVector3(f::Vector3)
leng=sqrt((f.x * f.x) + (f.y * f.y) + (f.z * f.z))
return convert(Float64,leng)
end
function crossVector3(vFrom::Vector3,vTo::Vector3)
x = vFrom.y * vTo.z - vFrom.z * vTo.y
y = vFrom.z * vTo.x - vFrom.x * vTo.z
z = vFrom.x * vTo.y - vFrom.y * vTo.x
return Vector3(x,y,z)
end
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
function normalizeQuaternion(f::Quaternion)
l = sqrt((f.x * f.x) + (f.y * f.y) + (f.z * f.z)+ (f.w * f.w))
if l === 0
qx = 0
qy = 0
qz = 0
qw = 1
else
l = 1 / l
qx = f.x * l
qy = f.y * l
qz = f.z * l
qw = f.w * l
end
return Quaternion(qx,qy,qz,qw)
end
function normalizeQuaternion1!(fx::Float64,fy::Float64,fz::Float64,fw::Float64)
l = sqrt((fx * fx) + (fy * fy) + (fz * fz)+ (fw * fw))
if l === 0
qx = 0.0
qy = 0.0
qz = 0.0
qw = 1.0
else
l = 1.0 / l
qx = fx * l
qy = fy * l
qz = fz * l
qw = fw * l
end
return qx,qy,qz,qw
end
function dotVector3(f::Vector3, g::Vector3)
return (f.x * g.x) + (f.y * g.y) + (f.z * g.z)
end
function Base.show(io::IO, v::Vector3)
print(io, "x:$(v.x), y:$(v.y), z:$(v.z)")
end
function Base.show(io::IO, v::Quaternion)
print(io, "x:$(v.x), y:$(v.y), z:$(v.z), w:$(v.z)")
end
Base.Broadcast.broadcastable(q::Vector3) = Ref(q)
######################utils##################################
function toAxisXVector3(pV::Vector3,axis::Vector3) #TODO CHANGE
xaxis=Vector3(1.0,0.0,0.0)
vector=normalizeVector3(axis)
q=setFromUnitVectors(vector,xaxis)
v=applyQuaternion1( pV ,q )
return Vector3(v.x,v.y,v.z)
end
function toAxisOriginalVector3(pV::Vector3,axis::Vector3)
xaxis=Vector3(1.0,0.0,0.0)
vector=normalizeVector3(axis)
q=setFromUnitVectors(xaxis,vector)
v=applyQuaternion1( pV ,q )
return Vector3(v.x,v.y,v.z)
end
function toAxisXQuat(pQ::Quaternion,axis::Vector3)
xaxis=Vector3(1.0,0.0,0.0)
vector=normalizeVector3(axis)
q=setFromUnitVectors(vector,xaxis)
pV=Vector3(pQ.x,pQ.y,pQ.z)
v=applyQuaternion1( pV ,q )
return Quaternion(v.x,v.y,v.z,pQ.w)
end
function toAxisOriginalQuat(pQ::Vector3,axis::Vector3)
xaxis=Vector3(1.0,0.0,0.0)
vector=normalizeVector3(axis)
q=setFromUnitVectors(xaxis,vector)
pV=Vector3(pQ.x,pQ.y,pQ.z)
v=applyQuaternion1( pV ,q )
return Quaternion(v.x,v.y,v.z,1.0)
end
function roundd(num,prec)
num = convert(Float64,num*prec)
num = floor(num+0.5)
num = convert(Float64,num)
num = num/prec
return num
end
###########################################
function setFromUnitVectors(vFrom::Vector3, vTo::Vector3)
# assumes direction vectors vFrom and vTo are normalized
EPS = 0.000000001;
r= dotVector3(vFrom,vTo)+1.0
# r = dot(vFrom,vTo)+1
if r < EPS
r = 0;
if abs( vFrom.x ) > abs( vFrom.z )
qx = - vFrom.y
qy = vFrom.x
qz = 0.0
qw = r
else
qx = 0.0
qy = -(vFrom.z)
qz = vFrom.y
qw = r
end
else
# crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3
qx = vFrom.y * vTo.z - vFrom.z * vTo.y
qy = vFrom.z * vTo.x - vFrom.x * vTo.z
qz = vFrom.x * vTo.y - vFrom.y * vTo.x
qw = r
end
# qx= (qx==-0.0) ? 0.0 : qx #just commented out 5 august 20202
# qy= (qy==-0.0) ? 0.0 : qy #just commented out 5 august 20202
# qz= (qz==-0.0) ? 0.0 : qz #just commented out 5 august 20202
# qw= (qw==-0.0) ? 0.0 : qw #just commented out 5 august 20202
mx=qx*qx
my=qy*qy
mz=qz*qz
mw=qw*qw
mm=mx+my
mm=mm+mz
mm=mm+mw
mm=convert(Float64,mm)#??????????????????? todo check later
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
#l = sqrt((qx * qx) + (qy * qy) + (qz * qz)+ (qw * qw))
if l === 0
qx = 0.0
qy = 0.0
qz = 0.0
qw = 1.0
else
l = 1.0 / l
qx = qx * l
qy = qy * l
qz = qz * l
qw = qw * l
end
return Quaternion(qx,qy,qz,qw)
end
function quatToMatrix( quaternion::Quaternion)
#te = RotationMatrix()
x = quaternion.x
y = quaternion.y
z = quaternion.z
w = quaternion.w
x2 = x + x
y2 = y + y
z2 = z + z
xx = x * x2
xy = x * y2
xz = x * z2
yy = y * y2
yz = y * z2
zz = z * z2
wx = w * x2
wy = w * y2
wz = w * z2
sx = 1.0
sy = 1.0
sz = 1.0
te1 = ( 1.0 - ( yy + zz ) ) * sx
te2 = ( xy + wz ) * sx
te3 = ( xz - wy ) * sx
te4 = 0.0
te5 = ( xy - wz ) * sy
te6 = ( 1.0 - ( xx + zz ) ) * sy
te7 = ( yz + wx ) * sy
te8 = 0.0
te9 = ( xz + wy ) * sz
te10 = ( yz - wx ) * sz
te11 = ( 1.0 - ( xx + yy ) ) * sz
te12 = 0.0
te13 = 0.0 #position.x;
te14 = 0.0 #position.y;
te15 = 0.0 #position.z;
te16 = 1.0
te= RotationMatrix(te1,te2,te3,te4,te5,te6,te7,te8,te9,te10,te11,te12,te13,te14,te15,te16)
return te
end
function setFromRotationMatrix(m::RotationMatrix)
m11 = convert(Float64,m.te1 )
m12 = convert(Float64,m.te5 )
m13 = convert(Float64,m.te9 )
m21 = convert(Float64,m.te2 )
m22 = convert(Float64,m.te6 )
m23 = convert(Float64,m.te10)
m31 = convert(Float64,m.te3 )
m32 = convert(Float64,m.te7 )
m33 = convert(Float64,m.te11)
y = CUDA.asin( clamp( m13, -1.0, 1.0 ) ) ##check if has to be changed to cuda
x = CUDA.atan2( - m23, m33 )
z = CUDA.atan2( - m12, m11 )#-m12, m11
z = 0.0;
end
return Vector3(x,y,z)
end
function setQuaternionFromEuler(euler::Vector3)
x=euler.x
y=euler.y
z=euler.z
c1 = CUDA.cos( x / 2.0 )
c2 = CUDA.cos( y / 2.0 )
c3 = CUDA.cos( z / 2.0 )
s1 = CUDA.sin( x / 2.0 )
s2 = CUDA.sin( y / 2.0 )
s3 = CUDA.sin( z / 2.0 )
x = s1 * c2 * c3 + c1 * s2 * s3
y = c1 * s2 * c3 - s1 * c2 * s3
z = c1 * c2 * s3 + s1 * s2 * c3
w = c1 * c2 * c3 - s1 * s2 * s3
return Quaternion(x,y,z,w)
end
function setQuaternionFromEuler1(euler::Vector3)
x=euler.x
y=euler.y
z=euler.z
c1 =cos( x / 2.0 )
c2 =cos( y / 2.0 )
c3 =cos( z / 2.0 )
s1 = sin( x / 2.0 )
s2 = sin( y / 2.0 )
s3 = sin( z / 2.0 )
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
x = s1 * c2 * c3 + c1 * s2 * s3
y = c1 * s2 * c3 - s1 * c2 * s3
z = c1 * c2 * s3 + s1 * s2 * c3
w = c1 * c2 * c3 - s1 * s2 * s3
return Quaternion(x,y,z,w)
end
function applyQuaternion1(e::Vector3,q2::Quaternion)
x = e.x
y = e.y
z = e.z
qx = q2.x
qy = q2.y
qz = q2.z
qw = q2.w
# calculate quat * vector
ix = qw * x + qy * z - qz * y
iy = qw * y + qz * x - qx * z
iz = qw * z + qx * y - qy * x
iw = - qx * x - qy * y - qz * z
# calculate result * inverse quat
xx = ix * qw + iw * - qx + iy * - qz - iz * - qy
yy = iy * qw + iw * - qy + iz * - qx - ix * - qz
zz = iz * qw + iw * - qz + ix * - qy - iy * - qx
d=15
return Vector3(xx,yy,zz)
end
##########################################
function conjugate(q::Quaternion)
x= (-q.x==-0) ? 0.0 : -q.x
y= (-q.y==-0) ? 0.0 : -q.y
z= (-q.z==-0) ? 0.0 : -q.z
w=q.w
x=-q.x
y=-q.y
z=-q.z
x=convert(Float64,x)
y=convert(Float64,y)
z=convert(Float64,z)
w=convert(Float64,w)
return Quaternion(x,y,z,w)
end
function RotateVec3D(a::Quaternion, f::Vector3)
fx= (f.x==-0) ? 0 : f.x
fy= (f.y==-0) ? 0 : f.y
fz= (f.z==-0) ? 0 : f.z
# fx= f.x
# fy= f.y
# fz= f.z
tw = fx*a.x + fy*a.y + fz*a.z
tx = fx*a.w - fy*a.z + fz*a.y
ty = fx*a.z + fy*a.w - fz*a.x
tz = -fx*a.y + fy*a.x + fz*a.w
return Vector3((a.w*tx+a.x*tw+a.y*tz-a.z*ty),(a.w*ty-a.x*tz+a.y*tw+a.z*tx),(a.w*tz+a.x*ty-a.y*tx+a.z*tw))
end
#!< Returns a vector representing the specified vector "f" rotated by this quaternion. @param[in] f The vector to transform.
function RotateVec3DInv(a::Quaternion, f::Vector3)
fx=f.x
fy=f.y
fz=f.z
tw = a.x*fx + a.y*fy + a.z*fz
tx = a.w*fx - a.y*fz + a.z*fy
ty = a.w*fy + a.x*fz - a.z*fx
tz = a.w*fz - a.x*fy + a.y*fx
return Vector3((tw*a.x + tx*a.w + ty*a.z - tz*a.y),(tw*a.y - tx*a.z + ty*a.w + tz*a.x),(tw*a.z + tx*a.y - ty*a.x + tz*a.w))
end
#!< Returns a vector representing the specified vector "f" rotated by the inverse of this quaternion. This is the opposite of RotateVec3D. @param[in] f The vector to transform.
function ToRotationVector(a::Quaternion)
x=convert(Float64,a.x)
y=convert(Float64,a.y)
z=convert(Float64,a.z)
w=convert(Float64,a.w)
if (w >= 1.0 || w <= -1.0)
return Vector3(0.0,0.0,0.0)
end
squareLength = 1.0-w*w; # because x*x + y*y + z*z + w*w = 1.0, but more susceptible to w noise (when
SLTHRESH_ACOS2SQRT= 2.4e-3; # SquareLength threshhold for when we can use square root optimization for acos. From SquareLength = 1-w*w. (calculate according to 1.0-W_THRESH_ACOS2SQRT*W_THRESH_ACOS2SQRT
if (squareLength < SLTHRESH_ACOS2SQRT) # ???????
# if (squareLength==0.0)
# w=1.0-1e-12
# squareLength = 1.0-w*w
# end
xx=x*(2.0*CUDA.sqrt((2.0-2.0*w)/squareLength))
yy=y*(2.0*CUDA.sqrt((2.0-2.0*w)/squareLength))
zz=z*(2.0*CUDA.sqrt((2.0-2.0*w)/squareLength))
xx=convert(Float64,xx)
yy=convert(Float64,yy)
zz=convert(Float64,zz)
return Vector3(xx,yy,zz) ; # acos(w) = sqrt(2*(1-x)) for w close to 1. for w=0.001, error is 1.317e-6
else
xx=x*(2.0*CUDA.acos(w)/CUDA.sqrt(squareLength))
yy=y*(2.0*CUDA.acos(w)/CUDA.sqrt(squareLength))
zz=z*(2.0*CUDA.acos(w)/CUDA.sqrt(squareLength))
xx=convert(Float64,xx)
yy=convert(Float64,yy)
zz=convert(Float64,zz)
return Vector3(xx,yy,zz)
end
# if (a.w >= 1.0 || a.w <= -1.0)
# return Vector3(0.0,0.0,0.0)
# end
# squareLength = 1.0-a.w*a.w; #because x*x + y*y + z*z + w*w = 1.0, but more susceptible to w noise (when
# if (squareLength < SLTHRESH_ACOS2SQRT)
# return Vec3D<T>(x, y, z)*2.0*sqrt((2-2*a.w)/squareLength); #acos(w) = sqrt(2*(1-x)) for w close to 1. for w=0.001, error is 1.317e-6
# else
# return Vec3D<T>(x, y, z)*2.0*acos(a.w)/sqrt(squareLength);
# end
end
# !< Returns a rotation vector representing this quaternion rotation. Adapted from http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/
function FromRotationVector(VecIn::Vector3)
theta=VecIn*Vector3(0.5,0.5,0.5)
ntheta=CUDA.sqrt((theta.x * theta.x) + (theta.y * theta.y) + (theta.z * theta.z))
thetaMag2=ntheta*ntheta
DBL_EPSILONx24 =5.328e-15
if thetaMag2*thetaMag2 < DBL_EPSILONx24
qw=1.0 - 0.5*thetaMag2
s=1.0 - thetaMag2 / 6.0
else
thetaMag = CUDA.sqrt(thetaMag2)
qw=CUDA.cos(thetaMag)
s=CUDA.sin(thetaMag) / thetaMag
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
end
qx=theta.x*s
qy=theta.y*s
qz=theta.z*s
qx=convert(Float64,qx)
qy=convert(Float64,qy)
qz=convert(Float64,qz)
qw=convert(Float64,qw)
return Quaternion(qx,qy,qz,qw)
end
function multiplyQuaternions(q::Quaternion,f::Quaternion)
x=convert(Float64,q.x)
y=convert(Float64,q.y)
z=convert(Float64,q.z)
w=convert(Float64,q.w)
x1=convert(Float64,w*convert(Float64,f.x) + x*convert(Float64,f.w) + y*convert(Float64,f.z) - z*convert(Float64,f.y))
y1=convert(Float64,w*convert(Float64,f.y) - x*convert(Float64,f.z) + y*convert(Float64,f.w) + z*convert(Float64,f.x))
z1=convert(Float64,w*convert(Float64,f.z) + x*convert(Float64,f.y) - y*convert(Float64,f.x) + z*convert(Float64,f.w))
w1=convert(Float64,w*convert(Float64,f.w) - x*convert(Float64,f.x) - y*convert(Float64,f.y) - z*convert(Float64,f.z))
# w1=convert(Float64,1.0*convert(Float64,f.w) - 1.0*convert(Float64,f.x) + 1.0*convert(Float64,f.y) - 1.0*convert(Float64,f.z)) #todo wrong fix
return Quaternion(x1,y1,z1,w1 ); #!< overload quaternion multiplication.
end
#####################################################
function FromAngleToPosX(angle::Quaternion,RotateFrom::Vector3) #highly optimized at the expense of readability
if (RotateFrom.x==0.0 && RotateFrom.y==0.0 && RotateFrom.z==0.0)
return Quaternion(angle.x,angle.y,angle.z,angle.w ) #leave off if it slows down too much!!
end
#Catch and handle small angle:
YoverX = RotateFrom.y/RotateFrom.x;
ZoverX = RotateFrom.z/RotateFrom.x;
SMALL_ANGLE_RAD= 1.732e-2 #/Angles less than this get small angle approximations. To get: Root solve atan(t)/t-1+MAX_ERROR_PERCENT. From: MAX_ERROR_PERCENT = (t-atan(t))/t
SMALL_ANGLE_W= 0.9999625 #//quaternion W value corresponding to a SMALL_ANGLE_RAD. To calculate, cos(SMALL_ANGLE_RAD*0.5).
PI=3.14159265358979
DISCARD_ANGLE_RAD=1e-7#define DISCARD_ANGLE_RAD 1e-7 //Anything less than this angle can be considered 0
if (YoverX<SMALL_ANGLE_RAD && YoverX>-SMALL_ANGLE_RAD && ZoverX<SMALL_ANGLE_RAD && ZoverX>-SMALL_ANGLE_RAD)#Intercept small angle and zero angle
x=0.0
y=0.5*ZoverX
z=-0.5*YoverX
w = 1.0+0.5*(-y*y-z*z) #w=sqrt(1-x*x-y*y), small angle sqrt(1+x) ~= 1+x/2 at x near zero.
return Quaternion(x,y,z,w )
end
#more accurate non-small angle:
RotFromNorm = Vector3(RotateFrom.x,RotateFrom.y,RotateFrom.z);
RotFromNorm=normalizeVector3(RotFromNorm); #Normalize the input...
theta = CUDA.acos(RotFromNorm.x); #because RotFromNorm is normalized, 1,0,0 is normalized, and A.B = |A||B|cos(theta) = cos(theta)
if (theta > PI-DISCARD_ANGLE_RAD)
w=0.0
x=0.0
y=1.0
z=0.0;
return Quaternion(x,y,z,w )
end #180 degree rotation (about y axis, since the vector must be pointing in -x direction
AxisMagInv = 1.0/CUDA.sqrt(RotFromNorm.z*RotFromNorm.z+RotFromNorm.y*RotFromNorm.y);
#Here theta is the angle, axis is RotFromNorm.Cross(Vec3D(1,0,0)) = Vec3D(0, RotFromNorm.z/AxisMagInv, -RotFromNorm.y/AxisMagInv), which is still normalized. (super rolled together)
a = 0.5*theta;
x=0;
y=RotFromNorm.z*AxisMagInv*s;
z = -RotFromNorm.y*AxisMagInv*s; #angle axis function, reduced
return Quaternion(x,y,z,w )
end
# //!< Overwrites this quaternion with the calculated rotation that would transform the specified RotateFrom vector to point in the positve X direction. Note: function changes this quaternion. @param[in] RotateFrom An arbitrary direction vector. Does not need to be normalized.