0

ネタバレ注意: クォータニオンを正しい方法で使用しているかどうかはわかりません。

私はメソッドIntersectionPointPlaneModelPair pairを使用してから持っています。TangoSupport.fitPlaneModelNearClick(...)この平面が重力と一直線に並んでいるかどうか (多かれ少なかれ) を調べたいと思います。私のアプローチは、からQuaternion( Rajawali )を作成し、pair.planeModelからScenePoseCalculator.TANGO_WORLD_UPと の回転を作成し0.0、それらを乗算して、オリジナルと製品の間の角度を決定することでした。

IntersectionPointPlaneModelPair pair= TangoSupport.fitPlaneModelNearClick(...);
double x = 0.05; // subject to change
double[] p = pair.planeModel;
Quaternion plane = new Quaternion(p[0], p[1], p[2], p[3]);
plane.normalize();
Quaternion gravity = Quaternion(ScenePoseCalculator.TANGO_WORLD_UP.clone(), 0.0);
Quaternion product = plane.multiply(gravity);
if (plane.angleBetween(product) > x){
     ...   
}

productただし、が と同一であることが判明したため、これは機能しませんplane。前もって感謝します!

4

1 に答える 1

1

私はQuaternions について間違った理解をしていたことに気づきました。平面の角度を計算するためのこの公式も見つけました。したがって、実装を次のように変更しました。

編集:新しい回答(以下の古い回答)

private boolean isAlignedWithGravity(IntersectionPointPlaneModelPair candidate,
                                         TangoPoseData devicePose, double maxDeviation) {
    Matrix4 adfTdevice = ScenePoseCalculator.tangoPoseToMatrix(devicePose);
    Vector3 gravityVector = ScenePoseCalculator.TANGO_WORLD_UP.clone();
    adfTdevice.clone().multiply(mExtrinsics.getDeviceTDepthCamera()).inverse().
            rotateVector(gravityVector);

    double[] gravity = new double[]{gravityVector.x, gravityVector.y, gravityVector.z};
    double angle = VectorUtilities.getAngleBetweenVectors(candidate.planeModel, gravity);
    // vectors should be perpendicular => 90° => PI / 2 in radians
    double target = Math.PI / 2; 
    return (Math.abs(target - angle) <= maxDeviation);
}

そしてクラスでVectorUtilities

/**
 * Calculates the angle between two planes according to http://www.wolframalpha
 * .com/input/?i=dihedral+angle
 */
public static double getAngleBetweenVectors(double[] a, double[] b) {
    double numerator = 0;
    for (int i = 0; i < Math.min(a.length, b.length); i++){
        numerator += a[i] * b[i];
    }
    double denominator = getLength(a) * getLength(b);
    return Math.acos(numerator / denominator);
}


public static double getLength(double[] vector) {
    double sum = 0.0;
    for (double dimension : vector) {
        sum += (dimension * dimension);
    }
    return Math.sqrt(sum);
}


古い回答

private boolean isAlignedWithGravity(IntersectionPointPlaneModelPair pair,
                                     TangoPoseData devicePose) {
    Matrix4 adfTdevice = ScenePoseCalculator.tangoPoseToMatrix(devicePose);
    Vector3 gravityVector = ScenePoseCalculator.TANGO_WORLD_UP.clone();
    adfTdevice.clone().multiply(mExtrinsics.getDeviceTDepthCamera()).inverse().
            rotateVector(gravityVector);

    double[] gravity = new double[]{gravityVector.x, gravityVector.y, gravityVector.z};
    double angle = getAngleBetweenPlanes(pair.planeModel, gravity);
    Log.d(TAG, "angle: " + angle);
    if (angle < 0.1) {
        return false;
    }
    return true;
}

/**
 * Calculates the angle between two planes according to http://mathworld.wolfram
 * .com/DihedralAngle.html
 */
private double getAngleBetweenPlanes(double[] a, double[] b) {
    double numerator = Math.abs(a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
    double aFactor = Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
    double bFactor = Math.sqrt(b[0] * b[0] + b[1] * b[1] + b[2] * b[2]);
    double denumerator = aFactor * bFactor;
    double result = Math.acos(numerator / denumerator);
    return result;
}
于 2016-05-19T10:22:42.950 に答える