1 #include "MathUtil.h"
2 #include <time.h>
3 #define _USE_MATH_DEFINES
4 #include <math.h>
5 
6 
Clamp(int val,int min,int max)7 int cMathUtil::Clamp(int val, int min, int max)
8 {
9 	return std::max(min, std::min(val, max));
10 }
11 
Clamp(const Eigen::VectorXd & min,const Eigen::VectorXd & max,Eigen::VectorXd & out_vec)12 void cMathUtil::Clamp(const Eigen::VectorXd& min, const Eigen::VectorXd& max, Eigen::VectorXd& out_vec)
13 {
14 	out_vec = out_vec.cwiseMin(max).cwiseMax(min);
15 }
16 
Clamp(double val,double min,double max)17 double cMathUtil::Clamp(double val, double min, double max)
18 {
19 	return std::max(min, std::min(val, max));
20 }
21 
Saturate(double val)22 double cMathUtil::Saturate(double val)
23 {
24 	return Clamp(val, 0.0, 1.0);
25 }
26 
Lerp(double t,double val0,double val1)27 double cMathUtil::Lerp(double t, double val0, double val1)
28 {
29 	return (1 - t) * val0 + t * val1;
30 }
31 
NormalizeAngle(double theta)32 double cMathUtil::NormalizeAngle(double theta)
33 {
34 	// normalizes theta to be between [-pi, pi]
35 	double norm_theta = fmod(theta, 2 * M_PI);
36 	if (norm_theta > M_PI)
37 	{
38 		norm_theta = -2 * M_PI + norm_theta;
39 	}
40 	else if (norm_theta < -M_PI)
41 	{
42 		norm_theta = 2 * M_PI + norm_theta;
43 	}
44 	return norm_theta;
45 }
46 
47 
SmoothStep(double t)48 double cMathUtil::SmoothStep(double t)
49 {
50 	double val = t * t * t * (t * (t * 6 - 15) + 10);
51 	return val;
52 }
53 
54 
TranslateMat(const tVector & trans)55 tMatrix cMathUtil::TranslateMat(const tVector& trans)
56 {
57 	tMatrix mat = tMatrix::Identity();
58 	mat(0, 3) = trans[0];
59 	mat(1, 3) = trans[1];
60 	mat(2, 3) = trans[2];
61 	return mat;
62 }
63 
ScaleMat(double scale)64 tMatrix cMathUtil::ScaleMat(double scale)
65 {
66 	return ScaleMat(tVector::Ones() * scale);
67 }
68 
ScaleMat(const tVector & scale)69 tMatrix cMathUtil::ScaleMat(const tVector& scale)
70 {
71 	tMatrix mat = tMatrix::Identity();
72 	mat(0, 0) = scale[0];
73 	mat(1, 1) = scale[1];
74 	mat(2, 2) = scale[2];
75 	return mat;
76 }
77 
RotateMat(const tVector & euler)78 tMatrix cMathUtil::RotateMat(const tVector& euler)
79 {
80 	double x = euler[0];
81 	double y = euler[1];
82 	double z = euler[2];
83 
84 	double x_s = std::sin(x);
85 	double x_c = std::cos(x);
86 	double y_s = std::sin(y);
87 	double y_c = std::cos(y);
88 	double z_s = std::sin(z);
89 	double z_c = std::cos(z);
90 
91 	tMatrix mat = tMatrix::Identity();
92 	mat(0, 0) = y_c * z_c;
93 	mat(1, 0) = y_c * z_s;
94 	mat(2, 0) = -y_s;
95 
96 	mat(0, 1) = x_s * y_s * z_c - x_c * z_s;
97 	mat(1, 1) = x_s * y_s * z_s + x_c * z_c;
98 	mat(2, 1) = x_s * y_c;
99 
100 	mat(0, 2) = x_c * y_s * z_c + x_s * z_s;
101 	mat(1, 2) = x_c * y_s * z_s - x_s * z_c;
102 	mat(2, 2) = x_c * y_c;
103 
104 	return mat;
105 }
106 
RotateMat(const tVector & axis,double theta)107 tMatrix cMathUtil::RotateMat(const tVector& axis, double theta)
108 {
109 	assert(std::abs(axis.squaredNorm() - 1) < 0.0001);
110 
111 	double c = std::cos(theta);
112 	double s = std::sin(theta);
113 	double x = axis[0];
114 	double y = axis[1];
115 	double z = axis[2];
116 
117 	tMatrix mat;
118 	mat <<	c + x * x * (1 - c),		x * y * (1 - c) - z * s,	x * z * (1 - c) + y * s,	0,
119 			y * x * (1 - c) + z * s,	c + y * y * (1 - c),		y * z * (1 - c) - x * s,	0,
120 			z * x * (1 - c) - y * s,	z * y * (1 - c) + x * s,	c + z * z * (1 - c),		0,
121 			0,							0,							0,							1;
122 
123 	return mat;
124 }
125 
RotateMat(const tQuaternion & q)126 tMatrix cMathUtil::RotateMat(const tQuaternion& q)
127 {
128 	tMatrix mat = tMatrix::Identity();
129 
130 	double sqw = q.w() * q.w();
131 	double sqx = q.x()*  q.x();
132 	double sqy = q.y() * q.y();
133 	double sqz = q.z() * q.z();
134 	double invs = 1 / (sqx + sqy + sqz + sqw);
135 
136 	mat(0, 0) = (sqx - sqy - sqz + sqw) * invs;
137 	mat(1, 1) = (-sqx + sqy - sqz + sqw) * invs;
138 	mat(2, 2) = (-sqx - sqy + sqz + sqw) * invs;
139 
140 	double tmp1 = q.x()*q.y();
141 	double tmp2 = q.z()*q.w();
142 	mat(1, 0) = 2.0 * (tmp1 + tmp2) * invs;
143 	mat(0, 1) = 2.0 * (tmp1 - tmp2) * invs;
144 
145 	tmp1 = q.x()*q.z();
146 	tmp2 = q.y()*q.w();
147 	mat(2, 0) = 2.0 * (tmp1 - tmp2) * invs;
148 	mat(0, 2) = 2.0 * (tmp1 + tmp2) * invs;
149 
150 	tmp1 = q.y()*q.z();
151 	tmp2 = q.x()*q.w();
152 	mat(2, 1) = 2.0 * (tmp1 + tmp2) * invs;
153 	mat(1, 2) = 2.0 * (tmp1 - tmp2) * invs;
154 
155 	return mat;
156 }
157 
CrossMat(const tVector & a)158 tMatrix cMathUtil::CrossMat(const tVector& a)
159 {
160 	tMatrix m;
161 	m << 0,		-a[2],	a[1],	0,
162 		 a[2],	0,		-a[0],	0,
163 		 -a[1],	a[0],	0,		0,
164 		 0,		0,		0,		1;
165 	return m;
166 }
167 
InvRigidMat(const tMatrix & mat)168 tMatrix cMathUtil::InvRigidMat(const tMatrix& mat)
169 {
170 	tMatrix inv_mat = tMatrix::Zero();
171 	inv_mat.block(0, 0, 3, 3) = mat.block(0, 0, 3, 3).transpose();
172 	inv_mat.col(3) = -inv_mat * mat.col(3);
173 	inv_mat(3, 3) = 1;
174 	return inv_mat;
175 }
176 
GetRigidTrans(const tMatrix & mat)177 tVector cMathUtil::GetRigidTrans(const tMatrix& mat)
178 {
179 	return tVector(mat(0, 3), mat(1, 3), mat(2, 3), 0);
180 }
181 
InvEuler(const tVector & euler)182 tVector cMathUtil::InvEuler(const tVector& euler)
183 {
184 	tMatrix inv_mat = cMathUtil::RotateMat(tVector(1, 0, 0, 0), -euler[0])
185 					* cMathUtil::RotateMat(tVector(0, 1, 0, 0), -euler[1])
186 					* cMathUtil::RotateMat(tVector(0, 0, 1, 0), -euler[2]);
187 	tVector inv_euler = cMathUtil::RotMatToEuler(inv_mat);
188 	return inv_euler;
189 }
190 
RotMatToAxisAngle(const tMatrix & mat,tVector & out_axis,double & out_theta)191 void cMathUtil::RotMatToAxisAngle(const tMatrix& mat, tVector& out_axis, double& out_theta)
192 {
193 	double c = (mat(0, 0) + mat(1, 1) + mat(2, 2) - 1) * 0.5;
194 	c = cMathUtil::Clamp(c, -1.0, 1.0);
195 
196 	out_theta = std::acos(c);
197 	if (std::abs(out_theta) < 0.00001)
198 	{
199 		out_axis = tVector(0, 0, 1, 0);
200 	}
201 	else
202 	{
203 		double m21 = mat(2, 1) - mat(1, 2);
204 		double m02 = mat(0, 2) - mat(2, 0);
205 		double m10 = mat(1, 0) - mat(0, 1);
206 		double denom = std::sqrt(m21 * m21 + m02 * m02 + m10 * m10);
207 		out_axis[0] = m21 / denom;
208 		out_axis[1] = m02 / denom;
209 		out_axis[2] = m10 / denom;
210 		out_axis[3] = 0;
211 	}
212 }
213 
RotMatToEuler(const tMatrix & mat)214 tVector cMathUtil::RotMatToEuler(const tMatrix& mat)
215 {
216 	tVector euler;
217 	euler[0] = std::atan2(mat(2, 1), mat(2, 2));
218 	euler[1] = std::atan2(-mat(2, 0), std::sqrt(mat(2, 1) * mat(2, 1) + mat(2, 2) * mat(2, 2)));
219 	euler[2] = std::atan2(mat(1, 0), mat(0, 0));
220 	euler[3] = 0;
221 	return euler;
222 }
223 
RotMatToQuaternion(const tMatrix & mat)224 tQuaternion cMathUtil::RotMatToQuaternion(const tMatrix& mat)
225 {
226 	double tr = mat(0, 0) + mat(1, 1) + mat(2, 2);
227 	tQuaternion q;
228 
229 	if (tr > 0) {
230 		double S = sqrt(tr + 1.0) * 2; // S=4*qw
231 		q.w() = 0.25 * S;
232 		q.x() = (mat(2, 1) - mat(1, 2)) / S;
233 		q.y() = (mat(0, 2) - mat(2, 0)) / S;
234 		q.z() = (mat(1, 0) - mat(0, 1)) / S;
235 	}
236 	else if ((mat(0, 0) > mat(1, 1) && (mat(0, 0) > mat(2, 2)))) {
237 		double S = sqrt(1.0 + mat(0, 0) - mat(1, 1) - mat(2, 2)) * 2; // S=4*qx
238 		q.w() = (mat(2, 1) - mat(1, 2)) / S;
239 		q.x() = 0.25 * S;
240 		q.y() = (mat(0, 1) + mat(1, 0)) / S;
241 		q.z() = (mat(0, 2) + mat(2, 0)) / S;
242 	}
243 	else if (mat(1, 1) > mat(2, 2)) {
244 		double S = sqrt(1.0 + mat(1, 1) - mat(0, 0) - mat(2, 2)) * 2; // S=4*qy
245 		q.w() = (mat(0, 2) - mat(2, 0)) / S;
246 		q.x() = (mat(0, 1) + mat(1, 0)) / S;
247 		q.y() = 0.25 * S;
248 		q.z() = (mat(1, 2) + mat(2, 1)) / S;
249 	}
250 	else {
251 		double S = sqrt(1.0 + mat(2, 2) - mat(0, 0) - mat(1, 1)) * 2; // S=4*qz
252 		q.w() = (mat(1, 0) - mat(0, 1)) / S;
253 		q.x() = (mat(0, 2) + mat(2, 0)) / S;
254 		q.y() = (mat(1, 2) + mat(2, 1)) / S;
255 		q.z() = 0.25 * S;
256 	}
257 
258 	return q;
259 }
260 
EulerToAxisAngle(const tVector & euler,tVector & out_axis,double & out_theta)261 void cMathUtil::EulerToAxisAngle(const tVector& euler, tVector& out_axis, double& out_theta)
262 {
263 	double x = euler[0];
264 	double y = euler[1];
265 	double z = euler[2];
266 
267 	double x_s = std::sin(x);
268 	double x_c = std::cos(x);
269 	double y_s = std::sin(y);
270 	double y_c = std::cos(y);
271 	double z_s = std::sin(z);
272 	double z_c = std::cos(z);
273 
274 	double c = (y_c * z_c + x_s * y_s * z_s + x_c * z_c + x_c * y_c - 1) * 0.5;
275 	c = Clamp(c, -1.0, 1.0);
276 
277 	out_theta = std::acos(c);
278 	if (std::abs(out_theta) < 0.00001)
279 	{
280 		out_axis = tVector(0, 0, 1, 0);
281 	}
282 	else
283 	{
284 		double m21 = x_s * y_c - x_c * y_s * z_s + x_s * z_c;
285 		double m02 = x_c * y_s * z_c + x_s * z_s + y_s;
286 		double m10 = y_c * z_s - x_s * y_s * z_c + x_c * z_s;
287 		double denom = std::sqrt(m21 * m21 + m02 * m02 + m10 * m10);
288 		out_axis[0] = m21 / denom;
289 		out_axis[1] = m02 / denom;
290 		out_axis[2] = m10 / denom;
291 		out_axis[3] = 0;
292 	}
293 }
294 
295 
DirToRotMat(const tVector & dir,const tVector & up)296 tMatrix cMathUtil::DirToRotMat(const tVector& dir, const tVector& up)
297 {
298 	tVector x = up.cross3(dir);
299 	double x_norm = x.norm();
300 	if (x_norm == 0)
301 	{
302 		x_norm = 1;
303 		x = (dir.dot(up) >= 0) ? tVector(1, 0, 0, 0) : tVector(-1, 0, 0, 0);
304 	}
305 	x /= x_norm;
306 
307 	tVector y = dir.cross3(x).normalized();
308 	tVector z = dir;
309 
310 	tMatrix mat = tMatrix::Identity();
311 	mat.block(0, 0, 3, 1) = x.segment(0, 3);
312 	mat.block(0, 1, 3, 1) = y.segment(0, 3);
313 	mat.block(0, 2, 3, 1) = z.segment(0, 3);
314 
315 	return mat;
316 }
317 
DeltaRot(const tVector & axis0,double theta0,const tVector & axis1,double theta1,tVector & out_axis,double & out_theta)318 void cMathUtil::DeltaRot(const tVector& axis0, double theta0, const tVector& axis1, double theta1,
319 							tVector& out_axis, double& out_theta)
320 {
321 	tMatrix R0 = RotateMat(axis0, theta0);
322 	tMatrix R1 = RotateMat(axis1, theta1);
323 	tMatrix M = DeltaRot(R0, R1);
324 	RotMatToAxisAngle(M, out_axis, out_theta);
325 }
326 
DeltaRot(const tMatrix & R0,const tMatrix & R1)327 tMatrix cMathUtil::DeltaRot(const tMatrix& R0, const tMatrix& R1)
328 {
329 	return R1 * R0.transpose();
330 }
331 
EulerToQuaternion(const tVector & euler)332 tQuaternion cMathUtil::EulerToQuaternion(const tVector& euler)
333 {
334 	tVector axis;
335 	double theta;
336 	EulerToAxisAngle(euler, axis, theta);
337 	return AxisAngleToQuaternion(axis, theta);
338 }
339 
340 
AxisAngleToQuaternion(const tVector & axis,double theta)341 tQuaternion cMathUtil::AxisAngleToQuaternion(const tVector& axis, double theta)
342 {
343 	// axis must be normalized
344 	double c = std::cos(theta / 2);
345 	double s = std::sin(theta / 2);
346 	tQuaternion q;
347 	q.w() = c;
348 	q.x() = s * axis[0];
349 	q.y() = s * axis[1];
350 	q.z() = s * axis[2];
351 	return q;
352 }
353 
QuaternionToAxisAngle(const tQuaternion & q,tVector & out_axis,double & out_theta)354 void cMathUtil::QuaternionToAxisAngle(const tQuaternion& q, tVector& out_axis, double& out_theta)
355 {
356 	out_theta = 0;
357 	out_axis = tVector(0, 0, 1, 0);
358 
359 	tQuaternion q1 = q;
360 	if (q1.w() > 1)
361 	{
362 		q1.normalize();
363 	}
364 
365 	double sin_theta = std::sqrt(1 - q1.w() * q1.w());
366 	if (sin_theta > 0.000001)
367 	{
368 		out_theta = 2 * std::acos(q1.w());
369 		out_theta = cMathUtil::NormalizeAngle(out_theta);
370 		out_axis = tVector(q1.x(), q1.y(), q1.z(), 0) / sin_theta;
371 	}
372 }
373 
BuildQuaternionDiffMat(const tQuaternion & q)374 tMatrix cMathUtil::BuildQuaternionDiffMat(const tQuaternion& q)
375 {
376 	tMatrix mat;
377 	mat << -0.5 * q.x(), -0.5 * q.y(), -0.5 * q.z(), 0,
378 		0.5 * q.w(), -0.5 * q.z(), 0.5 * q.y(), 0,
379 		0.5 * q.z(), 0.5 * q.w(), -0.5 * q.x(), 0,
380 		-0.5 * q.y(), 0.5 * q.x(), 0.5 * q.w(), 0;
381 	return mat;
382 }
383 
CalcQuaternionVel(const tQuaternion & q0,const tQuaternion & q1,double dt)384 tVector cMathUtil::CalcQuaternionVel(const tQuaternion& q0, const tQuaternion& q1, double dt)
385 {
386 	tQuaternion q_diff = cMathUtil::QuatDiff(q0, q1);
387 	tVector axis;
388 	double theta;
389 	QuaternionToAxisAngle(q_diff, axis, theta);
390 	return (theta / dt) * axis;
391 }
392 
CalcQuaternionVelRel(const tQuaternion & q0,const tQuaternion & q1,double dt)393 tVector cMathUtil::CalcQuaternionVelRel(const tQuaternion& q0, const tQuaternion& q1, double dt)
394 {
395 	// calculate relative rotational velocity in the coordinate frame of q0
396 	tQuaternion q_diff = q0.conjugate() * q1;
397 	tVector axis;
398 	double theta;
399 	QuaternionToAxisAngle(q_diff, axis, theta);
400 	return (theta / dt) * axis;
401 }
402 
VecToQuat(const tVector & v)403 tQuaternion cMathUtil::VecToQuat(const tVector& v)
404 {
405 	return tQuaternion(v[0], v[1], v[2], v[3]);
406 }
407 
QuatToVec(const tQuaternion & q)408 tVector cMathUtil::QuatToVec(const tQuaternion& q)
409 {
410 	return tVector(q.w(), q.x(), q.y(), q.z());
411 }
412 
QuatDiff(const tQuaternion & q0,const tQuaternion & q1)413 tQuaternion cMathUtil::QuatDiff(const tQuaternion& q0, const tQuaternion& q1)
414 {
415 	return q1 * q0.conjugate();
416 }
417 
QuatDiffTheta(const tQuaternion & q0,const tQuaternion & q1)418 double cMathUtil::QuatDiffTheta(const tQuaternion& q0, const tQuaternion& q1)
419 {
420 	tQuaternion dq = QuatDiff(q0, q1);
421 	return QuatTheta(dq);
422 }
423 
QuatTheta(const tQuaternion & dq)424 double cMathUtil::QuatTheta(const tQuaternion& dq)
425 {
426 	double theta = 0;
427 	tQuaternion q1 = dq;
428 	if (q1.w() > 1)
429 	{
430 		q1.normalize();
431 	}
432 
433 	double sin_theta = std::sqrt(1 - q1.w() * q1.w());
434 	if (sin_theta > 0.0001)
435 	{
436 		theta = 2 * std::acos(q1.w());
437 		theta = cMathUtil::NormalizeAngle(theta);
438 	}
439 	return theta;
440 }
441 
VecDiffQuat(const tVector & v0,const tVector & v1)442 tQuaternion cMathUtil::VecDiffQuat(const tVector& v0, const tVector& v1)
443 {
444 	return tQuaternion::FromTwoVectors(v0.segment(0, 3), v1.segment(0, 3));
445 }
446 
QuatRotVec(const tQuaternion & q,const tVector & dir)447 tVector cMathUtil::QuatRotVec(const tQuaternion& q, const tVector& dir)
448 {
449 	tVector rot_dir = tVector::Zero();
450 	rot_dir.segment(0, 3)  = q * dir.segment(0, 3);
451 	return rot_dir;
452 }
453 
MirrorQuaternion(const tQuaternion & q,eAxis axis)454 tQuaternion cMathUtil::MirrorQuaternion(const tQuaternion& q, eAxis axis)
455 {
456 	tQuaternion mirror_q;
457 	mirror_q.w() = q.w();
458 	mirror_q.x() = (axis == eAxisX) ? q.x() : -q.x();
459 	mirror_q.y() = (axis == eAxisY) ? q.y() : -q.y();
460 	mirror_q.z() = (axis == eAxisZ) ? q.z() : -q.z();
461 	return mirror_q;
462 }
463 
Sign(double val)464 double cMathUtil::Sign(double val)
465 {
466 	return SignAux<double>(val);
467 }
468 
Sign(int val)469 int cMathUtil::Sign(int val)
470 {
471 	return SignAux<int>(val);
472 }
473 
AddAverage(double avg0,int count0,double avg1,int count1)474 double cMathUtil::AddAverage(double avg0, int count0, double avg1, int count1)
475 {
476 	double total = count0 + count1;
477 	return (count0 / total) * avg0 + (count1 / total) * avg1;
478 }
479 
AddAverage(const tVector & avg0,int count0,const tVector & avg1,int count1)480 tVector cMathUtil::AddAverage(const tVector& avg0, int count0, const tVector& avg1, int count1)
481 {
482 	double total = count0 + count1;
483 	return (count0 / total) * avg0 + (count1 / total) * avg1 ;
484 }
485 
AddAverage(const Eigen::VectorXd & avg0,int count0,const Eigen::VectorXd & avg1,int count1,Eigen::VectorXd & out_result)486 void cMathUtil::AddAverage(const Eigen::VectorXd& avg0, int count0, const Eigen::VectorXd& avg1, int count1, Eigen::VectorXd& out_result)
487 {
488 	double total = count0 + count1;
489 	out_result = (count0 / total) * avg0 + (count1 / total) * avg1;
490 }
491 
CalcSoftmax(const Eigen::VectorXd & vals,double temp,Eigen::VectorXd & out_prob)492 void cMathUtil::CalcSoftmax(const Eigen::VectorXd& vals, double temp, Eigen::VectorXd& out_prob)
493 {
494 	assert(out_prob.size() == vals.size());
495 	int num_vals = static_cast<int>(vals.size());
496 	double sum = 0;
497 	double max_val = vals.maxCoeff();
498 	for (int i = 0; i < num_vals; ++i)
499 	{
500 		double val = vals[i];
501 		val = std::exp((val - max_val) / temp);
502 		out_prob[i] = val;
503 		sum += val;
504 	}
505 
506 	out_prob /= sum;
507 }
508 
EvalGaussian(const Eigen::VectorXd & mean,const Eigen::VectorXd & covar,const Eigen::VectorXd & sample)509 double cMathUtil::EvalGaussian(const Eigen::VectorXd& mean, const Eigen::VectorXd& covar, const Eigen::VectorXd& sample)
510 {
511 	assert(mean.size() == covar.size());
512 	assert(sample.size() == covar.size());
513 
514 	Eigen::VectorXd diff = sample - mean;
515 	double exp_val = diff.dot(diff.cwiseQuotient(covar));
516 	double likelihood = std::exp(-0.5 * exp_val);
517 
518 	double partition = CalcGaussianPartition(covar);
519 	likelihood /= partition;
520 	return likelihood;
521 }
522 
EvalGaussian(double mean,double covar,double sample)523 double cMathUtil::EvalGaussian(double mean, double covar, double sample)
524 {
525 	double diff = sample - mean;
526 	double exp_val = diff * diff / covar;
527 	double norm = 1 / std::sqrt(2 * M_PI * covar);
528 	double likelihood = norm * std::exp(-0.5 * exp_val);
529 	return likelihood;
530 }
531 
CalcGaussianPartition(const Eigen::VectorXd & covar)532 double cMathUtil::CalcGaussianPartition(const Eigen::VectorXd& covar)
533 {
534 	int data_size = static_cast<int>(covar.size());
535 	double det = covar.prod();
536 	double partition = std::sqrt(std::pow(2 * M_PI, data_size) * det);
537 	return partition;
538 }
539 
EvalGaussianLogp(const Eigen::VectorXd & mean,const Eigen::VectorXd & covar,const Eigen::VectorXd & sample)540 double cMathUtil::EvalGaussianLogp(const Eigen::VectorXd& mean, const Eigen::VectorXd& covar, const Eigen::VectorXd& sample)
541 {
542 	int data_size = static_cast<int>(covar.size());
543 
544 	Eigen::VectorXd diff = sample - mean;
545 	double logp = -0.5 * diff.dot(diff.cwiseQuotient(covar));
546 	double det = covar.prod();
547 	logp += -0.5 * (data_size * std::log(2 * M_PI) + std::log(det));
548 
549 	return logp;
550 }
551 
EvalGaussianLogp(double mean,double covar,double sample)552 double cMathUtil::EvalGaussianLogp(double mean, double covar, double sample)
553 {
554 	double diff = sample - mean;
555 	double logp = -0.5 * diff * diff / covar;
556 	logp += -0.5 * (std::log(2 * M_PI) + std::log(covar));
557 	return logp;
558 }
559 
Sigmoid(double x)560 double cMathUtil::Sigmoid(double x)
561 {
562 	return Sigmoid(x, 1, 0);
563 }
564 
Sigmoid(double x,double gamma,double bias)565 double cMathUtil::Sigmoid(double x, double gamma, double bias)
566 {
567 	double exp = -gamma * (x + bias);
568 	double val = 1 / (1 + std::exp(exp));
569 	return val;
570 }
571 
572 
CalcBarycentric(const tVector & p,const tVector & a,const tVector & b,const tVector & c)573 tVector cMathUtil::CalcBarycentric(const tVector& p, const tVector& a, const tVector& b, const tVector& c)
574 {
575 	tVector v0 = b - a;
576 	tVector v1 = c - a;
577 	tVector v2 = p - a;
578 
579 	double d00 = v0.dot(v0);
580 	double d01 = v0.dot(v1);
581 	double d11 = v1.dot(v1);
582 	double d20 = v2.dot(v0);
583 	double d21 = v2.dot(v1);
584 	double denom = d00 * d11 - d01 * d01;
585 	double v = (d11 * d20 - d01 * d21) / denom;
586 	double w = (d00 * d21 - d01 * d20) / denom;
587 	double u = 1.0f - v - w;
588 
589 	return tVector(u, v, w, 0);
590 }
591 
ContainsAABB(const tVector & pt,const tVector & aabb_min,const tVector & aabb_max)592 bool cMathUtil::ContainsAABB(const tVector& pt, const tVector& aabb_min, const tVector& aabb_max)
593 {
594 	bool contains = pt[0] >= aabb_min[0] && pt[1] >= aabb_min[1] && pt[2] >= aabb_min[2]
595 					&& pt[0] <= aabb_max[0] && pt[1] <= aabb_max[1] && pt[2] <= aabb_max[2];
596 	return contains;
597 }
598 
ContainsAABB(const tVector & aabb_min0,const tVector & aabb_max0,const tVector & aabb_min1,const tVector & aabb_max1)599 bool cMathUtil::ContainsAABB(const tVector& aabb_min0, const tVector& aabb_max0, const tVector& aabb_min1, const tVector& aabb_max1)
600 {
601 	return ContainsAABB(aabb_min0, aabb_min1, aabb_max1) && ContainsAABB(aabb_max0, aabb_min1, aabb_max1);
602 }
603 
ContainsAABBXZ(const tVector & pt,const tVector & aabb_min,const tVector & aabb_max)604 bool cMathUtil::ContainsAABBXZ(const tVector& pt, const tVector& aabb_min, const tVector& aabb_max)
605 {
606 	bool contains = pt[0] >= aabb_min[0] && pt[2] >= aabb_min[2]
607 		&& pt[0] <= aabb_max[0] && pt[2] <= aabb_max[2];
608 	return contains;
609 }
610 
ContainsAABBXZ(const tVector & aabb_min0,const tVector & aabb_max0,const tVector & aabb_min1,const tVector & aabb_max1)611 bool cMathUtil::ContainsAABBXZ(const tVector& aabb_min0, const tVector& aabb_max0, const tVector& aabb_min1, const tVector& aabb_max1)
612 {
613 	return ContainsAABBXZ(aabb_min0, aabb_min1, aabb_max1) && ContainsAABBXZ(aabb_max0, aabb_min1, aabb_max1);
614 }
615 
CalcAABBIntersection(const tVector & aabb_min0,const tVector & aabb_max0,const tVector & aabb_min1,const tVector & aabb_max1,tVector & out_min,tVector & out_max)616 void cMathUtil::CalcAABBIntersection(const tVector& aabb_min0, const tVector& aabb_max0, const tVector& aabb_min1, const tVector& aabb_max1,
617 									tVector& out_min, tVector& out_max)
618 {
619 	out_min = aabb_min0.cwiseMax(aabb_min1);
620 	out_max = aabb_max0.cwiseMin(aabb_max1);
621 	if (out_min[0] > out_max[0])
622 	{
623 		out_min[0] = 0;
624 		out_max[0] = 0;
625 	}
626 	if (out_min[1] > out_max[1])
627 	{
628 		out_min[1] = 0;
629 		out_max[1] = 0;
630 	}
631 	if (out_min[2] > out_max[2])
632 	{
633 		out_min[2] = 0;
634 		out_max[2] = 0;
635 	}
636 }
637 
CalcAABBUnion(const tVector & aabb_min0,const tVector & aabb_max0,const tVector & aabb_min1,const tVector & aabb_max1,tVector & out_min,tVector & out_max)638 void cMathUtil::CalcAABBUnion(const tVector& aabb_min0, const tVector& aabb_max0, const tVector& aabb_min1, const tVector& aabb_max1,
639 								tVector& out_min, tVector& out_max)
640 {
641 	out_min = aabb_min0.cwiseMin(aabb_min1);
642 	out_max = aabb_max0.cwiseMax(aabb_max1);
643 }
644 
IntersectAABB(const tVector & aabb_min0,const tVector & aabb_max0,const tVector & aabb_min1,const tVector & aabb_max1)645 bool cMathUtil::IntersectAABB(const tVector& aabb_min0, const tVector& aabb_max0, const tVector& aabb_min1, const tVector& aabb_max1)
646 {
647 	tVector center0 = 0.5 * (aabb_max0 + aabb_min0);
648 	tVector center1 = 0.5 * (aabb_max1 + aabb_min1);
649 	tVector size0 = aabb_max0 - aabb_min0;
650 	tVector size1 = aabb_max1 - aabb_min1;
651 	tVector test_len = 0.5 * (size0 + size1);
652 	tVector delta = center1 - center0;
653 	bool overlap = (std::abs(delta[0]) <= test_len[0]) && (std::abs(delta[1]) <= test_len[1]) && (std::abs(delta[2]) <= test_len[2]);
654 	return overlap;
655 }
656 
IntersectAABBXZ(const tVector & aabb_min0,const tVector & aabb_max0,const tVector & aabb_min1,const tVector & aabb_max1)657 bool cMathUtil::IntersectAABBXZ(const tVector& aabb_min0, const tVector& aabb_max0, const tVector& aabb_min1, const tVector& aabb_max1)
658 {
659 	tVector center0 = 0.5 * (aabb_max0 + aabb_min0);
660 	tVector center1 = 0.5 * (aabb_max1 + aabb_min1);
661 	tVector size0 = aabb_max0 - aabb_min0;
662 	tVector size1 = aabb_max1 - aabb_min1;
663 	tVector test_len = 0.5 * (size0 + size1);
664 	tVector delta = center1 - center0;
665 	bool overlap = (std::abs(delta[0]) <= test_len[0]) && (std::abs(delta[2]) <= test_len[2]);
666 	return overlap;
667 }
668 
CheckNextInterval(double delta,double curr_val,double int_size)669 bool cMathUtil::CheckNextInterval(double delta, double curr_val, double int_size)
670 {
671 	double pad = 0.001 * delta;
672 	int curr_count = static_cast<int>(std::floor((curr_val + pad) / int_size));
673 	int prev_count = static_cast<int>(std::floor((curr_val + pad - delta) / int_size));
674 	bool new_action = (curr_count != prev_count);
675 	return new_action;
676 }
677 
678 
679 
QuatSwingTwistDecomposition(const tQuaternion & q,const tVector & dir,tQuaternion & out_swing,tQuaternion & out_twist)680 void cMathUtil::QuatSwingTwistDecomposition(const tQuaternion& q, const tVector& dir, tQuaternion& out_swing, tQuaternion& out_twist)
681 {
682 	assert(std::abs(dir.norm() - 1) < 0.000001);
683 	assert(std::abs(q.norm() - 1) < 0.000001);
684 
685 	tVector q_axis = tVector(q.x(), q.y(), q.z(), 0);
686 	double p = q_axis.dot(dir);
687 	tVector twist_axis = p * dir;
688 	out_twist = tQuaternion(q.w(), twist_axis[0], twist_axis[1], twist_axis[2]);
689 	out_twist.normalize();
690 	out_swing = q * out_twist.conjugate();
691 }
692 
ProjectQuat(const tQuaternion & q,const tVector & dir)693 tQuaternion cMathUtil::ProjectQuat(const tQuaternion& q, const tVector& dir)
694 {
695 	assert(std::abs(dir.norm() - 1) < 0.00001);
696 	tVector ref_axis = tVector::Zero();
697 	int min_idx = 0;
698 	dir.cwiseAbs().minCoeff(&min_idx);
699 	ref_axis[min_idx] = 1;
700 
701 	tVector rot_dir0 = dir.cross3(ref_axis);
702 	tVector rot_dir1 = cMathUtil::QuatRotVec(q, rot_dir0);
703 	rot_dir1 -= rot_dir1.dot(dir) * dir;
704 
705 	double dir1_norm = rot_dir1.norm();
706 	tQuaternion p_rot = tQuaternion::Identity();
707 	if (dir1_norm > 0.0001)
708 	{
709 		rot_dir1 /= dir1_norm;
710 		p_rot = cMathUtil::VecDiffQuat(rot_dir0, rot_dir1);
711 	}
712 	return p_rot;
713 }
714 
ButterworthFilter(double dt,double cutoff,Eigen::VectorXd & out_x)715 void cMathUtil::ButterworthFilter(double dt, double cutoff, Eigen::VectorXd& out_x)
716 {
717 	double sampling_rate = 1 / dt;
718 	int n = static_cast<int>(out_x.size());
719 
720 	double wc = std::tan(cutoff * M_PI / sampling_rate);
721 	double k1 = std::sqrt(2.0) * wc;
722 	double k2 = wc * wc;
723 	double a = k2 / (1 + k1 + k2);
724 	double b = 2 * a;
725 	double c = a;
726 	double k3 = b / k2;
727 	double d = -2 * a + k3;
728 	double e = 1 - (2 * a) - k3;
729 
730 	double xm2 = out_x[0];
731 	double xm1 = out_x[0];
732 	double ym2 = out_x[0];
733 	double ym1 = out_x[0];
734 
735 	for (int s = 0; s < n; ++s)
736 	{
737 		double x = out_x[s];
738 		double y = a * x + b * xm1 + c * xm2 + d * ym1 + e * ym2;
739 
740 		out_x[s] = y;
741 		xm2 = xm1;
742 		xm1 = x;
743 		ym2 = ym1;
744 		ym1 = y;
745 	}
746 
747 	double yp2 = out_x[n - 1];
748 	double yp1 = out_x[n - 1];
749 	double zp2 = out_x[n - 1];
750 	double zp1 = out_x[n - 1];
751 
752 	for (int t = n - 1; t >= 0; --t)
753 	{
754 		double y = out_x[t];
755 		double z = a * y + b * yp1 + c * yp2 + d * zp1 + e * zp2;
756 
757 		out_x[t] = z;
758 		yp2 = yp1;
759 		yp1 = y;
760 		zp2 = zp1;
761 		zp1 = z;
762 	}
763 }