/* * 作成日: 2008/07/01 */ package jp.ac.fit.asura.nao.misc; import javax.vecmath.AxisAngle4f; import javax.vecmath.Matrix3f; import javax.vecmath.SingularMatrixException; import javax.vecmath.Vector3f; import jp.ac.fit.asura.nao.sensation.FrameState; import jp.ac.fit.asura.vecmathx.GfMatrix; import jp.ac.fit.asura.vecmathx.GfVector; /** * @author sey * * @version $Id: MatrixUtils.java 717 2008-12-31 18:16:20Z sey $ * */ public class MatrixUtils { public static Matrix3f rotationMatrix(AxisAngle4f axisAngle) { Matrix3f mat = new Matrix3f(); mat.set(axisAngle); return mat; } /** * 回転行列rotからZYXオイラー角(Roll-Pitch-Yaw, ロール-ピッチ-ヨー)を求めpyrに格納します. * * ただしzをRoll, yをYaw, xをPitchとします. * * @param rot * @param ypr */ public static void rot2pyr(Matrix3f rot, Vector3f ypr) { // // Roll // rpy.x = (float) Math.atan2(rot.m21, rot.m22); // // // Pitch // // rpy.y = (float) Math.atan2(rot.m12 * sYaw + rot.m02 * cYaw, // rot.m01 // // * sYaw + rot.m00 * cYaw); // rpy.y = (float) Math.atan2(rot.m12 * sYaw + rot.m02 * cYaw, rot.m22); // // // Yaw // rpy.z = (float) yaw; // ZYXオイラー角の場合 // Z軸上の回転角度 double yaw = Math.atan2(rot.m10, rot.m00); float cosYaw = (float) Math.cos(yaw); float sinYaw = (float) Math.sin(yaw); // Roll ypr.x = (float) Math.atan2(rot.m02 * sinYaw - rot.m12 * cosYaw, -rot.m01 * sinYaw + rot.m11 * cosYaw); // Pitch ypr.y = (float) Math.atan2(-rot.m20, rot.m00 * cosYaw + rot.m10 * sinYaw); // Yaw ypr.z = (float) yaw; } /** * ZYXオイラー角(Roll-Pitch-Yaw, ロール-ピッチ-ヨー) pyrから回転行列を求め、rotに格納します. * * ただしzをRoll, yをYaw, xをPitchとします. * * @param ypr * @param rot */ public static void pyr2rot(Vector3f ypr, Matrix3f rot) { float sRoll = (float) Math.sin(ypr.x); // ロール(yaw) float cRoll = (float) Math.cos(ypr.x); float sPitch = (float) Math.sin(ypr.y); float cPitch = (float) Math.cos(ypr.y); float sYaw = (float) Math.sin(ypr.z); float cYaw = (float) Math.cos(ypr.z); rot.m00 = cYaw * cPitch; rot.m01 = -sYaw * cRoll + cYaw * sPitch * sRoll; rot.m02 = sYaw * sRoll + cYaw * sPitch * cRoll; rot.m10 = sYaw * cPitch; rot.m11 = cYaw * cRoll + sYaw * sPitch * sRoll; rot.m12 = -cYaw * sRoll + sYaw * sPitch * cRoll; rot.m20 = -sPitch; rot.m21 = cPitch * sRoll; rot.m22 = cPitch * cRoll; } /** * 回転行列から角速度ベクトルへの変換. ヒューマノイドロボット p35より. * * @param rotation * 変換する回転行列 * @param omega * 角速度ベクトルの書き込み先 */ public static void rot2omega(Matrix3f rot, Vector3f omega) { double theta = Math.acos(MathUtils.clipAbs( (rot.m00 + rot.m11 + rot.m22 - 1) / 2.0, 1)); if (MathUtils.epsEquals(Math.sin(theta), 0) || MatrixUtils.isIdentity(rot)) { // System.out.println(Math.sin(theta)); omega.set(0, 0, 0); return; } assert !Double.isNaN(theta) && Math.sin(theta) != 0; omega.setX(rot.m21 - rot.m12); omega.setY(rot.m02 - rot.m20); omega.setZ(rot.m10 - rot.m01); omega.scale((float) theta / (float) (2 * Math.sin(theta))); } /** * vectorで表される位置ベクトルに,frameによる座標変換を行います. <br> * frameの関節角度にはradが使用されます. 変換結果はvectorに上書きされます. * * @param vector * 変換する位置ベクトル * @param frame * @param rad */ public static void transform(Vector3f vector, FrameState frame) { Matrix3f mat = new Matrix3f(); mat.set(frame.getAxisAngle()); mat.transform(vector); vector.add(frame.getPosition()); } public static void inverseTransform(Vector3f vector, FrameState frame) { vector.sub(frame.getPosition()); Matrix3f mat = new Matrix3f(); mat.set(frame.getAxisAngle()); mat.transpose(); mat.transform(vector); } /** * 連立一次方程式mat*x=bを解きます. * * 行列matの中身は保持されないことに注意してください. * * @param mat * @param b * @param x * @throws SingularMatrixException */ public static void solve(GfMatrix mat, GfVector b, GfVector x) throws SingularMatrixException { // LU分解その1 GfVector perm = new GfVector(mat.getNumRow()); mat.LUD(mat, perm); x.LUDBackSolve(mat, b, perm); // 逆行列(中身はLU分解) // jacobi.invert(); // x.mul(mat, b); } /** * 連立一次方程式mat*x=bを解きます. その2. */ public static int solve2(GfMatrix mat, GfVector b, GfVector x) throws SingularMatrixException { int rows = mat.getNumRow(); int cols = mat.getNumCol(); GfMatrix u = new GfMatrix(rows, rows); GfMatrix w = new GfMatrix(rows, cols); GfMatrix v = new GfMatrix(cols, cols); int rank = mat.SVD(u, w, v); x.SVDBackSolve(u, w, v, b); return rank; } /** * この行列が単位行列であるかを調べます. * * @param matrix * @return */ private static final Matrix3f E3f = new Matrix3f(1, 0, 0, 0, 1, 0, 0, 0, 1); public static boolean isIdentity(Matrix3f matrix) { return matrix.epsilonEquals(E3f, 1e-6f); } public static void setAxis(AxisAngle4f axisAngle, Vector3f axis) { axis.x = axisAngle.x; axis.y = axisAngle.y; axis.z = axisAngle.z; } }