예제 #1
0
 public LowerThanBodyRestriction(JointType jointType, int angleThreshold)
     : base(
         body =>
 {
     double maxY = TrigonometryHelper.GetSine(angleThreshold);
     return(Z3.Context.MkLt(body.Joints[jointType].Y, Z3Math.Real(maxY)));
 },
         jointType)
 {
     this.JointType = jointType;
 }
예제 #2
0
        // Therapy restrictions
        public static IBodyRestriction StraightPostureRestriction(int angleThreshold = 15)
        {
            Z3Point3D up = new Z3Point3D(0, 1, 0);

            double distanceThreshold = TrigonometryHelper.GetSine(angleThreshold);

            var result = new SimpleBodyRestriction(body =>
            {
                BoolExpr expr = body.Joints[JointType.SpineMid].IsNearerThan(up, distanceThreshold);
                expr          = Z3.Context.MkAnd(expr, body.Joints[JointType.SpineShoulder].IsNearerThan(up, distanceThreshold));
                expr          = Z3.Context.MkAnd(expr, body.Joints[JointType.Neck].IsNearerThan(up, distanceThreshold));
                expr          = Z3.Context.MkAnd(expr, body.Joints[JointType.Head].IsNearerThan(up, distanceThreshold));
                return(expr);
            });

            return(result);
        }
예제 #3
0
        private void CalcPercentages(
            Z3Body body,
            int precision,
            out double transformsPercentage,
            out double restrictionsPercentage,
            out string mainRestriction)
        {
            transformsPercentage = 1.0;
            if (this.Target.TransformedJoints.Count > 0)
            {
                transformsPercentage = Math.Min(1.0,
                                                TrigonometryHelper.GetDistance(precision) /
                                                CalcMaxDistance(this.LastDistanceVectors, this.Target.TransformedJoints));
            }

            restrictionsPercentage =
                this.Gesture.Steps[CurrentStep].Pose.CalcMinPercentage(body, out mainRestriction);
        }
예제 #4
0
        public static IBodyRestriction ShouldersRelaxedRestriction(int angleThreshold = -5)
        {
            double maxY = TrigonometryHelper.GetSine(angleThreshold);

            var result = new SimpleBodyRestriction
                             (body =>
            {
                // Check if both shoulders have a lower Y than maxY
                BoolExpr expr1 = Z3.Context.MkLt(body.Joints[JointType.ShoulderLeft].Y, Z3Math.Real(maxY));
                BoolExpr expr2 = Z3.Context.MkLt(body.Joints[JointType.ShoulderRight].Y, Z3Math.Real(maxY));

                BoolExpr expr = Z3.Context.MkAnd(expr1, expr2);

                return(expr);
            });

            return(result);
        }
예제 #5
0
        public RotateJointTransform(int degrees, BodyPlaneType plane, RotationDirection rotationDirection = RotationDirection.Clockwise)
            : base(
                joint =>
        {
            double cosInput = TrigonometryHelper.GetCosine(degrees);
            double sinInput = TrigonometryHelper.GetSine(degrees);

            if (rotationDirection == RotationDirection.CounterClockwise)
            {
                sinInput = -sinInput;
            }

            var cos    = Z3Math.Real(cosInput);
            var sin    = Z3Math.Real(sinInput);
            var sinNeg = Z3Math.Real(-sinInput);

            Z3Point3D result = new Z3Point3D(joint.X, joint.Y, joint.Z);

            switch (plane)
            {
            case BodyPlaneType.Frontal:
                result.Y = Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.Z));
                result.Z = Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.Z));
                break;

            case BodyPlaneType.Sagittal:
                result.X = Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Y));
                result.Y = Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Y));
                break;

            case BodyPlaneType.Horizontal:
                result.X = Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Z));
                result.Z = Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Z));
                break;

            default:
                break;
            }

            return(result);
        })
        { }
예제 #6
0
        //public ArithExpr CalcApproximateDistanceBetweenNormalized(Z3Point3D that)
        //{
        //	Z3Point3D thisNormalized = this.GetApproximateNormalized();
        //	Z3Point3D thatNormalized = that.GetApproximateNormalized();

        //	ArithExpr result = thisNormalized.CalcApproximateDistance(thatNormalized);
        //	return result;
        //}

        // Assumes vectors are normalized
        public BoolExpr IsDegreesBetweenLessThan(Z3Point3D that, int degreesThreshold)
        {
            double    distanceThreshold = TrigonometryHelper.GetDistance(degreesThreshold);
            ArithExpr distance          = this.CalcApproximateDistance(that);

            BoolExpr result = Z3.Context.MkLt(distance, Z3Math.Real(distanceThreshold));

            //// TODO remove this, test code
            //SolverCheckResult checkResult = Z3AnalysisInterface.CheckStatus(result);
            //if (checkResult.Status == Status.SATISFIABLE)
            //{
            //    var joint = new Z3Point3D(
            //            checkResult.Model.Evaluate(this.X, true) as ArithExpr,
            //            checkResult.Model.Evaluate(this.Y, true) as ArithExpr,
            //            checkResult.Model.Evaluate(this.Z, true) as ArithExpr);

            //    var distanceSolvedExpr = checkResult.Model.Evaluate(distance, true) as ArithExpr;
            //    var distanceValue = Z3Math.GetRealValue(distanceSolvedExpr);
            //}
            //// end of test code

            return(result);
        }
예제 #7
0
        // the rotation towards a direction is limited to the directive vector of that direction
        public RotateJointTransform(int degrees, Direction direction)
            : base(
                joint =>
        {
            // define current degrees
            var currentDegrees = 0.0;
            switch (direction)
            {
            case Direction.Right:
            case Direction.Left:
                currentDegrees = Math.Asin(joint.GetXValue()) * 180.0 / Math.PI;
                break;

            case Direction.Up:
            case Direction.Down:
                currentDegrees = Math.Asin(joint.GetYValue()) * 180.0 / Math.PI;
                break;

            case Direction.Front:
            case Direction.Back:
                currentDegrees = Math.Asin(joint.GetZValue()) * 180.0 / Math.PI;
                break;
            }

            // check if current degrees + input degrees is an overflow
            // which means the rotation is going towards the opposite direction
            if (currentDegrees + degrees > 90 ||
                currentDegrees - degrees < -90)
            {
                // if so, set degrees as the complement to the limit value
                degrees = (int)(90.0 - currentDegrees);
            }


            double cosInput = TrigonometryHelper.GetCosine(degrees);
            double sinInput = TrigonometryHelper.GetSine(degrees);

            var cos    = Z3Math.Real(cosInput);
            var sin    = Z3Math.Real(sinInput);
            var sinNeg = Z3Math.Real(-sinInput);

            Z3Point3D result = new Z3Point3D(joint.X, joint.Y, joint.Z);

            // The performed rotation depends on current values of X, Y and Z
            // The rotation plane and direction changes depending on the relation between the coordinates
            switch (direction)
            {
            case Direction.Back:
                result.X =
                    // if Abs(X) >= Abs(Y)
                    // if X > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else return X
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.X), Z3Math.Abs(result.Y)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sinNeg, joint.Z))),
                                     joint.X) as ArithExpr;

                result.Y =
                    // if Abs(X) >= Abs(Y)
                    // then return Y
                    // else rotate Y
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Y)),
                                     joint.Y,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sinNeg, joint.Z)))) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Y)
                    // if X > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Y)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.X), Z3Math.Mul(cos, joint.Z))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Y), Z3Math.Mul(cos, joint.Z)))) as ArithExpr;
                break;

            case Direction.Front:
                result.X =
                    // if Abs(X) >= Abs(Y)
                    // if X > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    // else return X
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.X), Z3Math.Abs(result.Y)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sinNeg, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Z))),
                                     joint.X) as ArithExpr;

                result.Y =
                    // if Abs(X) >= Abs(Y)
                    // then return Y
                    // else rotate Y
                    // if Y > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Y)),
                                     joint.Y,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sinNeg, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.Z)))) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Y)
                    // if X > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    // else if Y > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Y)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.X), Z3Math.Mul(cos, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Z))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Y), Z3Math.Mul(cos, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.Z)))) as ArithExpr;
                break;

            case Direction.Down:
                result.X =
                    // if Abs(X) >= Abs(Z)
                    // if X > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else return X
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.X), Z3Math.Abs(result.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sinNeg, joint.Y))),
                                     joint.X) as ArithExpr;

                result.Y =
                    // if Abs(X) >= Abs(Z)
                    // if X > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.X), Z3Math.Mul(cos, joint.Y))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Z), Z3Math.Mul(cos, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Z), Z3Math.Mul(cos, joint.Y)))) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Z)
                    // then return Z
                    // else rotate Z
                    // if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Z)),
                                     joint.Z,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sin, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sinNeg, joint.Y)))) as ArithExpr;
                break;

            case Direction.Up:
                result.X =
                    // if Abs(X) >= Abs(Z)
                    // if X > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    // else return X
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.X), Z3Math.Abs(result.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sinNeg, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Y))),
                                     joint.X) as ArithExpr;

                result.Y =
                    // if Abs(X) >= Abs(Z)
                    // if X > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    // else if Z > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.X), Z3Math.Mul(cos, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Y))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Z), Z3Math.Mul(cos, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Z), Z3Math.Mul(cos, joint.Y)))) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Z)
                    // then return Z
                    // else rotate Z
                    // if Z > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Z)),
                                     joint.Z,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sinNeg, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sin, joint.Y)))) as ArithExpr;
                break;

            case Direction.Right:
                result.X =
                    // if Abs(Y) >= Abs(Z)
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.Y), Z3Math.Abs(joint.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Y), Z3Math.Mul(cos, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.X))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Z), Z3Math.Mul(cos, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Z), Z3Math.Mul(cos, joint.X)))) as ArithExpr;

                result.Y =
                    // if Abs(Y) >= Abs(Z)
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else return Y
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.Y), Z3Math.Abs(result.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sinNeg, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.X))),
                                     joint.Y) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Z)
                    // then return Z
                    // else rotate Z
                    // if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.Y), Z3Math.Abs(joint.Z)),
                                     joint.Z,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sinNeg, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sin, joint.X)))) as ArithExpr;
                break;

            case Direction.Left:
                result.X =
                    // if Abs(Y) >= Abs(Z)
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.Y), Z3Math.Abs(joint.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Y), Z3Math.Mul(cos, joint.X))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Z), Z3Math.Mul(cos, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Z), Z3Math.Mul(cos, joint.X)))) as ArithExpr;

                result.Y =
                    // if Abs(Y) >= Abs(Z)
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else return Y
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.Y), Z3Math.Abs(result.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sinNeg, joint.X))),
                                     joint.Y) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Z)
                    // then return Z
                    // else rotate Z
                    // if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.Y), Z3Math.Abs(joint.Z)),
                                     joint.Z,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sin, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sinNeg, joint.X)))) as ArithExpr;
                break;

            default:
                break;
            }

            return(result);
        })
        { }
예제 #8
0
        public RotateJointTransform(int angle, Direction direction)
            : base(
                joint =>
        {
            double cosInput = TrigonometryHelper.GetCosine(angle);
            double sinInput = TrigonometryHelper.GetSine(angle);

            var cos    = Z3Math.Real(cosInput);
            var sin    = Z3Math.Real(sinInput);
            var sinNeg = Z3Math.Real(-sinInput);

            Z3Point3D result = new Z3Point3D(joint.X, joint.Y, joint.Z);

            // The performed rotation depends on current values of X, Y and Z
            // The rotation plane and direction changes depending on the relation between the coordinates
            switch (direction)
            {
            case Direction.Back:
                result.X =
                    // if Abs(X) >= Abs(Y)
                    // if X > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else return X
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.X), Z3Math.Abs(result.Y)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sinNeg, joint.Z))),
                                     joint.X) as ArithExpr;

                result.Y =
                    // if Abs(X) >= Abs(Y)
                    // then return Y
                    // else rotate Y
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Y)),
                                     joint.Y,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sinNeg, joint.Z)))) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Y)
                    // if X > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Y)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.X), Z3Math.Mul(cos, joint.Z))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Y), Z3Math.Mul(cos, joint.Z)))) as ArithExpr;
                break;

            case Direction.Front:
                result.X =
                    // if Abs(X) >= Abs(Y)
                    // if X > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    // else return X
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.X), Z3Math.Abs(result.Y)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sinNeg, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Z))),
                                     joint.X) as ArithExpr;

                result.Y =
                    // if Abs(X) >= Abs(Y)
                    // then return Y
                    // else rotate Y
                    // if Y > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Y)),
                                     joint.Y,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sinNeg, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.Z)))) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Y)
                    // if X > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    // else if Y > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Y)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.X), Z3Math.Mul(cos, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Z))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Y), Z3Math.Mul(cos, joint.Z)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.Z)))) as ArithExpr;
                break;

            case Direction.Down:
                result.X =
                    // if Abs(X) >= Abs(Z)
                    // if X > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else return X
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.X), Z3Math.Abs(result.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sinNeg, joint.Y))),
                                     joint.X) as ArithExpr;

                result.Y =
                    // if Abs(X) >= Abs(Z)
                    // if X > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.X), Z3Math.Mul(cos, joint.Y))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Z), Z3Math.Mul(cos, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Z), Z3Math.Mul(cos, joint.Y)))) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Z)
                    // then return Z
                    // else rotate Z
                    // if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Z)),
                                     joint.Z,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sin, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sinNeg, joint.Y)))) as ArithExpr;
                break;

            case Direction.Up:
                result.X =
                    // if Abs(X) >= Abs(Z)
                    // if X > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    // else return X
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.X), Z3Math.Abs(result.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sinNeg, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.X), Z3Math.Mul(sin, joint.Y))),
                                     joint.X) as ArithExpr;

                result.Y =
                    // if Abs(X) >= Abs(Z)
                    // if X > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    // else if Z > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.X, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.X), Z3Math.Mul(cos, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.X), Z3Math.Mul(cos, joint.Y))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Z), Z3Math.Mul(cos, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Z), Z3Math.Mul(cos, joint.Y)))) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Z)
                    // then return Z
                    // else rotate Z
                    // if Z > 0
                    // rotate clockwise
                    // else rotate counter clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.X), Z3Math.Abs(joint.Z)),
                                     joint.Z,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sinNeg, joint.Y)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sin, joint.Y)))) as ArithExpr;
                break;

            case Direction.Right:
                result.X =
                    // if Abs(Y) >= Abs(Z)
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.Y), Z3Math.Abs(joint.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Y), Z3Math.Mul(cos, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.X))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Z), Z3Math.Mul(cos, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Z), Z3Math.Mul(cos, joint.X)))) as ArithExpr;

                result.Y =
                    // if Abs(Y) >= Abs(Z)
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else return Y
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.Y), Z3Math.Abs(result.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sinNeg, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.X))),
                                     joint.Y) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Z)
                    // then return Z
                    // else rotate Z
                    // if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.Y), Z3Math.Abs(joint.Z)),
                                     joint.Z,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sinNeg, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sin, joint.X)))) as ArithExpr;
                break;

            case Direction.Left:
                result.X =
                    // if Abs(Y) >= Abs(Z)
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.Y), Z3Math.Abs(joint.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Y), Z3Math.Mul(cos, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Y), Z3Math.Mul(cos, joint.X))),
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(sinNeg, joint.Z), Z3Math.Mul(cos, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(sin, joint.Z), Z3Math.Mul(cos, joint.X)))) as ArithExpr;

                result.Y =
                    // if Abs(Y) >= Abs(Z)
                    // if Y > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    // else return Y
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(result.Y), Z3Math.Abs(result.Z)),
                                     Z3.Context.MkITE(Z3.Context.MkGe(result.Y, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sin, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Y), Z3Math.Mul(sinNeg, joint.X))),
                                     joint.Y) as ArithExpr;

                result.Z =
                    // if Abs(X) >= Abs(Z)
                    // then return Z
                    // else rotate Z
                    // if Z > 0
                    // rotate counter clockwise
                    // else rotate clockwise
                    Z3.Context.MkITE(Z3.Context.MkGe(Z3Math.Abs(joint.Y), Z3Math.Abs(joint.Z)),
                                     joint.Z,
                                     Z3.Context.MkITE(Z3.Context.MkGe(joint.Z, Z3Math.Zero),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sin, joint.X)),
                                                      Z3Math.Add(Z3Math.Mul(cos, joint.Z), Z3Math.Mul(sinNeg, joint.X)))) as ArithExpr;
                break;

            default:
                break;
            }

            return(result);
        })
        { }
예제 #9
0
        public GestureStatus TestBody(Z3Body body, int precision, Context localContext)
        {
            StatisticsEntryMatch matchStat = new StatisticsEntryMatch();

            var stopwatch = new Stopwatch();

            stopwatch.Start();
            var time0 = stopwatch.ElapsedMilliseconds;


            var time1 = stopwatch.ElapsedMilliseconds - time0;

            // NOT THREAD SAFE XXX
            this.LastDistanceVectors = this.UpdateDistanceVectors(body, localContext);

            var time2 = stopwatch.ElapsedMilliseconds - time1;

            // Check distance to target transformed joints and if body satisfies restrictions
            var distance = 2.0;


            if (this.Target.TransformedJoints.Count > 0)
            {
                distance = CalcMaxDistance(this.LastDistanceVectors, this.Target.TransformedJoints);
            }


            this.AccumulatedError += distance - this.LastDistance;
            this.LastDistance      = distance;

            var time3 = stopwatch.ElapsedMilliseconds - time2;

            bool transformSucceeded = distance < TrigonometryHelper.GetDistance(precision);

            var time4 = stopwatch.ElapsedMilliseconds - time3;

            // NOT THREAD SAFE XXX
            bool restrictionSucceeded = this.Gesture.Steps[CurrentStep].Pose.IsBodyAccepted(body);

            var time5 = stopwatch.ElapsedMilliseconds - time4;

            matchStat.timeMs      = time5;
            matchStat.gestureName = this.Gesture.Name;
            matchStat.uid         = frameCount;
            matchStat.poseName    = this.Gesture.Steps[CurrentStep].Pose.Name;

            bool succeeded =
                (transformSucceeded || this.Target.TransformedJoints.Count == 0) &&
                (restrictionSucceeded || this.Target.RestrictedJoints.Count == 0);

            // Overall succeeded represents whether the entire gesture was matched on this test, not just a single pose
            bool overallSucceeded = false;

            // If body is accepted move to matching the next pose in sequence
            if (succeeded)
            {
                this.CurrentStep     += 1;
                this.AccumulatedError = 0;

                // Check if gesture is completed (all steps are finished)
                if (this.CurrentStep >= this.Gesture.Steps.Count)
                {
                    this.Reset(body);
                    this.CompletedCount += 1;
                    overallSucceeded     = true;
                }

                this.UpdateTargetBody(body);
            }
            // If body was not accepted then check if error is higher than threshold
            // If accumulated error is too high the gesture is broken
            else if (this.AccumulatedError > 1)
            {
                //gesture.Reset(body);
            }

            var result = this.GetStatus();

            // The VisualGestureBuilder API for DiscreteGestureResult cares about whole gestures,
            // not about individual poses. We need to check for this case explicitly.
            // We then expose succeededDetection in a DiscreteGestureResult .
            result.succeededDetection = overallSucceeded;

            // TODO: check the semantics of succeededDetectionFirstFrame in the VisualGestureBuilder API
            // We here are assuming that firstFrame means this is the first frame where we successfully detected the gesture
            // We are assuming that firstFrame does NOT mean this is the first frame where we started tracking the gesture
            if (CompletedCount == 1 & overallSucceeded)
            {
                result.succeededDetectionFirstFrame = true;
            }
            else
            {
                result.succeededDetectionFirstFrame = false;
            }

            // TODO: check the semantics of confidence in the VisualGestureBuilder API.
            // Here confidence is the same as distance from the target body.
            // That is NOT the same as if confidence were a probability that we are correct
            // We want to have as close semantics as possible to the VisualGestureBuilder API, so we need to double check this
            result.confidence = (float)distance;

            var time6 = stopwatch.ElapsedMilliseconds - time5;

            frameCount++;


            // Record the statistics entry here
            GestureStatistics.matchTimes.Add(matchStat);
            return(result);
        }