예제 #1
0
        /// <summary>
        /// Returns a list of MTRansform
        /// </summary>
        /// <param name="pathConstraint"></param>
        /// <returns></returns>
        public static List <MTransform> GetMTransformList(this MPathConstraint pathConstraint)
        {
            //Create a list for storing the full trajectory
            List <MTransform> list = new List <MTransform>();

            foreach (MGeometryConstraint mg in pathConstraint.PolygonPoints)
            {
                MTransform t = null;

                if (mg.ParentToConstraint != null)
                {
                    t = new MTransform
                    {
                        ID       = "",
                        Position = mg.ParentToConstraint.Position,
                        Rotation = mg.ParentToConstraint.Rotation
                    };
                }

                else
                {
                    t = new MTransform
                    {
                        ID       = "",
                        Position = mg.TranslationConstraint.GetVector3(),
                        Rotation = MQuaternionExtensions.FromEuler(mg.TranslationConstraint.GetVector3())
                    };
                }


                list.Add(t);
            }

            return(list);
        }
예제 #2
0
        /// <summary>
        /// Method is repsonsible for modeling the actual carry for both handed objects
        /// </summary>
        /// <param name="result"></param>
        private void BothHandedCarry(ref MSimulationResult result)
        {
            //Create an empty transform representing the next object transform
            MTransform nextObjectTransform = new MTransform();


            //Update the desired object transform
            if (this.CarryTargetName != null && this.CarryTargetName.Length > 0)
            {
                MTransform targetTransform = SceneAccess.GetTransformByID(this.CarryTargetName);
                nextObjectTransform.Position = targetTransform.Position;
                nextObjectTransform.Rotation = targetTransform.Rotation;
            }
            else
            {
                MTransform refTransform = GetTransform(this.simulationState.Initial, bothHandedCarryReferenceJoint);
                MVector3   forward      = GetRootForwad(this.simulationState.Initial);
                //Determine the ref transform rotation
                refTransform.Rotation = MQuaternionExtensions.FromEuler(new MVector3(0, Extensions.SignedAngle(new MVector3(0, 0, 1), forward, new MVector3(0, 1, 0)), 0));

                nextObjectTransform.Position = refTransform.TransformPoint(this.internalCarryTransform.Position);
                nextObjectTransform.Rotation = refTransform.TransformRotation(this.internalCarryTransform.Rotation);
            }



            //Compute the object transform
            result.SceneManipulations.Add(new MSceneManipulation()
            {
                Transforms = new List <MTransformManipulation>()
                {
                    new MTransformManipulation()
                    {
                        Target   = instruction.Properties["TargetID"],
                        Position = nextObjectTransform.Position,
                        Rotation = nextObjectTransform.Rotation
                    }
                }
            });


            List <MIKProperty> ikProperties = new List <MIKProperty>();


            //Update the hands
            foreach (HandContainer hand in this.ActiveHands)
            {
                //Update the hands
                MTransform nextHandPose = new MTransform("", nextObjectTransform.TransformPoint(hand.HandOffset.Position), nextObjectTransform.TransformRotation(hand.HandOffset.Rotation));

                this.constraintManager.SetEndeffectorConstraint(hand.JointType, nextHandPose.Position, nextHandPose.Rotation, hand.ConstraintID);
            }
        }
예제 #3
0
        /// <summary>
        /// Rotates the current transform around the specific point and axis
        /// </summary>
        /// <param name="center">The rotation center</param>
        /// <param name="axis">The rotation axis</param>
        /// <param name="angle">The angle to rotate</param>
        private static MTransform RotateAround(MTransform transform, MVector3 center, MVector3 axis, float angle)
        {
            MTransform res = new MTransform()
            {
                ID = System.Guid.NewGuid().ToString()
            };

            MVector3 pos = transform.Position;

            MQuaternion rot = MQuaternionExtensions.FromEuler(axis.Multiply(angle)); // get the desired rotation
            MVector3    dir = pos.Subtract(center);                                  // find current direction relative to center

            dir = rot.Multiply(dir);                                                 // rotate the direction

            res.Position = center.Add(dir);                                          // define new position
            MQuaternion myRot = transform.Rotation;

            res.Rotation = transform.Rotation.Multiply(MQuaternionExtensions.Inverse(myRot).Multiply(rot).Multiply(myRot));


            return(res);
        }
예제 #4
0
        /// <summary>
        /// Method is responsible for modeling the positiong the object and hands which is the first part of the carry for both handed objects
        /// </summary>
        /// <param name="result"></param>
        /// <param name="time"></param>
        private void PositionObjectBothHanded(ref MSimulationResult result, double time)
        {
            double rootVelocity = this.ComputeRootVelocity(time);


            MAvatarPostureValues avatarPose             = this.simulationState.Initial;
            MTransform           currentObjectTransform = this.SceneAccess.GetTransformByID(this.instruction.Properties["TargetID"]);


            //Move the object to a central spot in front of the avatar
            //Create a new transform for the target object transform
            MTransform targetObjectTransform = new MTransform();


            if (this.CarryTargetName != null && this.CarryTargetName.Length > 0)
            {
                MTransform targetTransform = SceneAccess.GetTransformByID(this.CarryTargetName);
                targetObjectTransform.Position = targetTransform.Position;
                targetObjectTransform.Rotation = targetTransform.Rotation;
            }

            else
            {
                MTransform refTransform = GetTransform(this.simulationState.Initial, bothHandedCarryReferenceJoint);
                MVector3   forward      = GetRootForwad(this.simulationState.Initial);
                //Determine the ref transform rotation
                refTransform.Rotation = MQuaternionExtensions.FromEuler(new MVector3(0, Extensions.SignedAngle(new MVector3(0, 0, 1), forward, new MVector3(0, 1, 0)), 0));

                targetObjectTransform.Position = refTransform.TransformPoint(this.internalCarryTransform.Position);
                targetObjectTransform.Rotation = refTransform.TransformRotation(this.internalCarryTransform.Rotation);
            }

            MTransform nextObjectPose      = this.DoLocalMotionPlanning(rootVelocity + positionObjectVelocity, TimeSpan.FromSeconds(time), currentObjectTransform.Position, currentObjectTransform.Rotation, targetObjectTransform.Position, targetObjectTransform.Rotation);
            MTransform nextObjectTransform = new MTransform("", nextObjectPose.Position, nextObjectPose.Rotation);


            //Update the position of the object
            result.SceneManipulations.Add(new MSceneManipulation()
            {
                Transforms = new List <MTransformManipulation>()
                {
                    new MTransformManipulation()
                    {
                        Target   = instruction.Properties["TargetID"],
                        Position = nextObjectPose.Position,
                        Rotation = nextObjectPose.Rotation
                    }
                }
            });

            //Update the hands
            foreach (HandContainer hand in this.ActiveHands)
            {
                //Update the hands
                MTransform nextHandPose = new MTransform("", nextObjectTransform.TransformPoint(hand.HandOffset.Position), nextObjectTransform.TransformRotation(hand.HandOffset.Rotation));

                //Set a new endeffector constraint
                this.constraintManager.SetEndeffectorConstraint(hand.JointType, nextHandPose.Position, nextHandPose.Rotation, hand.ConstraintID);

                //Assign the hand pose to preserve finger rotations
                result.Posture = AssignHandPose(result.Posture, hand.HandPose, hand.Type);
            }



            //Check if position is finished
            if ((targetObjectTransform.Position.Subtract(nextObjectPose.Position)).Magnitude() < 0.01f && MQuaternionExtensions.Angle(targetObjectTransform.Rotation, nextObjectPose.Rotation) < 0.1f)
            {
                result.Events.Add(new MSimulationEvent("PositioningFinished", "PositioningFinished", instruction.ID));

                //Only consider the rotation around y axis
                double yRotation = this.GetRootRotation(this.simulationState.Initial).ToEuler().Y;

                MTransform rootTransform = new MTransform("", this.GetRootPosition(this.simulationState.Initial), MQuaternionExtensions.FromEuler(new MVector3(0, yRotation, 0)));

                //Update the new relative coordinates
                this.relativeObjectRotation = rootTransform.InverseTransformRotation(nextObjectTransform.Rotation);
                this.relativeObjectPosition = rootTransform.InverseTransformPoint(nextObjectTransform.Position);

                this.bothHandedState = CarryState.Carry;

                //Get the joint constraints
                List <MConstraint> jointConstraints = this.constraintManager.GetJointConstraints();

                //Solve using ik if constraints are defined
                if (jointConstraints.Count > 0)
                {
                    MIKServiceResult ikResult = this.ServiceAccess.IKService.CalculateIKPosture(result.Posture, jointConstraints, new Dictionary <string, string>());
                    result.Posture = ikResult.Posture;
                }
            }
        }
예제 #5
0
        public override MBoolResponse AssignInstruction(MInstruction instruction, MSimulationState simulationState)
        {
            //Reset the properties
            this.UseCarryIK      = false;
            this.bothHandedCarry = false;
            this.bothHandedState = CarryState.None;
            this.simulationState = simulationState;


            //Create a list which contains the hands which should be considered for carrying
            List <HandContainer> toPlan = new List <HandContainer>();

            if (instruction.Properties == null)
            {
                throw new Exception($"{this.Name}: No properties defined!");
            }

            //Extract the hand information
            if (instruction.Properties.ContainsKey("Hand"))
            {
                switch (instruction.Properties["Hand"])
                {
                case "Left":
                    toPlan.Add(this.SetupHand(HandType.Left, instruction));
                    this.bothHandedCarry = false;
                    break;

                case "Right":
                    toPlan.Add(this.SetupHand(HandType.Right, instruction));
                    this.bothHandedCarry = false;
                    break;

                case "Both":
                    //Set flag for both handed carry
                    this.bothHandedCarry = true;
                    toPlan.Add(this.SetupHand(HandType.Left, instruction));
                    toPlan.Add(this.SetupHand(HandType.Right, instruction));
                    break;
                }
            }
            else
            {
                toPlan.Add(this.SetupHand(HandType.Right, instruction));
            }


            //Use the carry target if defined
            if (!instruction.Properties.GetValue(out this.CarryTargetName, "CarryTarget"))
            {
                this.CarryTargetName = null;
            }

            //Use the carry target if defined
            if (!instruction.Properties.GetValue(out this.UseCarryIK, "UseCarryIK"))
            {
                UseCarryIK = false;
            }

            //Use carry distance if defined
            if (!instruction.Properties.GetValue(out this.carryDistanceBothHanded, "CarryDistance"))
            {
                carryDistanceBothHanded = 0.65f;
            }

            //Use carry distance if defined
            if (!instruction.Properties.GetValue(out this.carryHeightBothHanded, "CarryHeight"))
            {
                carryHeightBothHanded = 0.2f;
            }

            //Use carry distance if defined
            if (!instruction.Properties.GetValue(out this.positionObjectVelocity, "Velocity"))
            {
                this.positionObjectVelocity = 1.0f;
            }


            //Compute and plan the relevant aspects of each hand
            foreach (HandContainer hand in toPlan)
            {
                //Get the (initial) hand transform
                MTransform handTransform = this.GetTransform(simulationState.Initial, hand.Type);

                //Get the current transform of the scene object
                MTransform sceneObjectTransform = this.SceneAccess.GetTransformByID(hand.Instruction.Properties["TargetID"]);

                //Get the hand pose
                try
                {
                    hand.HandPose = GetTransform(simulationState.Initial, hand.Type);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Problem estimating hand pose: " + e.Message + e.StackTrace);
                }

                //Compute the relative transform of the hand (hand relative to object)
                hand.HandOffset = new MTransform("", sceneObjectTransform.InverseTransformPoint(handTransform.Position), sceneObjectTransform.InverseTransformRotation(handTransform.Rotation));

                //Compute the inverse offset (object relative to hand)
                hand.ObjectOffset = new MTransform("", handTransform.InverseTransformPoint(sceneObjectTransform.Position), handTransform.InverseTransformRotation(sceneObjectTransform.Rotation));

                //Set state to positioning
                hand.State = CarryState.Positioning;
            }


            //Do additional computations for both handed carry
            if (bothHandedCarry)
            {
                //Set the state to positioning
                this.bothHandedState = CarryState.Positioning;

                //Assign the instruction
                this.instruction = instruction;

                //Get the current object transorm
                MTransform currentObjectTransform = this.SceneAccess.GetTransformByID(this.instruction.Properties["TargetID"]);

                //Get the current root transform -> to do
                MTransform rootTransform = GetTransform(this.simulationState.Initial, MJointType.PelvisCentre);

                //Compute the relative object transform
                this.relativeObjectRotation = rootTransform.InverseTransformRotation(currentObjectTransform.Rotation);
                this.relativeObjectPosition = rootTransform.InverseTransformPoint(currentObjectTransform.Position);

                //Manually specify a carry target
                if (this.CarryTargetName == null || this.CarryTargetName.Length == 0)
                {
                    MTransform refTransform = GetTransform(this.simulationState.Initial, bothHandedCarryReferenceJoint);
                    MVector3   forward      = GetRootForwad(this.simulationState.Initial);

                    //Determine the ref transform rotation just consider the y axis rotation
                    refTransform.Rotation = MQuaternionExtensions.FromEuler(new MVector3(0, Extensions.SignedAngle(new MVector3(0, 0, 1), forward, new MVector3(0, 1, 0)), 0));

                    //Compute the delta
                    //MVector3 delta = currentObjectTransform.Position.Subtract(refTransform.Position);
                    //MVector3 direction = new MVector3(delta.X, 0, delta.Z).Normalize();

                    //The carry position i
                    MVector3 carryPosition = refTransform.Position.Add(forward.Multiply(this.carryDistanceBothHanded)).Add(new MVector3(0, carryHeightBothHanded, 0f));

                    //Forwad + offset
                    this.internalCarryTransform = new MTransform("CarryTarget", refTransform.InverseTransformPoint(carryPosition), refTransform.InverseTransformRotation(currentObjectTransform.Rotation));
                }
            }

            return(new MBoolResponse(true));
        }
 public static MQuaternion GetQuaternion(this MRotationConstraint rConstraint)
 {
     return(MQuaternionExtensions.FromEuler(rConstraint.GetVector3()));
 }
예제 #7
0
        /// <summary>
        /// Returns all ik constraints which are violated (avove specified threshold)
        /// </summary>
        /// <param name="constraints"></param>
        /// <param name="currentPosture"></param>
        /// <returns></returns>
        private List <MConstraint> GetViolatedIKConstraints(List <MConstraint> constraints, MAvatarPostureValues currentPosture)
        {
            List <MConstraint> violated = new List <MConstraint>();

            if (constraints != null)
            {
                // Apply result posture values to the skeleton
                skeletonAccess.SetChannelData(currentPosture);

                string avatarID = currentPosture.AvatarID;

                //Check each joint constraint
                foreach (MConstraint mconstraint in constraints)
                {
                    if (mconstraint.JointConstraint != null)
                    {
                        MJointConstraint endeffectorConstraint = mconstraint.JointConstraint;

                        //Skip if no gemometry constraint is defined
                        if (endeffectorConstraint.GeometryConstraint == null)
                        {
                            continue;
                        }


                        double distance        = 0f;
                        double angularDistance = 0f;


                        //Default (parent to constraint is set)
                        if (endeffectorConstraint.GeometryConstraint.ParentToConstraint != null)
                        {
                            MVector3    position = endeffectorConstraint.GeometryConstraint.ParentToConstraint.Position;
                            MQuaternion rotation = endeffectorConstraint.GeometryConstraint.ParentToConstraint.Rotation;

                            switch (endeffectorConstraint.JointType)
                            {
                            case MJointType.LeftWrist:
                                distance        = MVector3Extensions.Distance(position, this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.LeftWrist));
                                angularDistance = MQuaternionExtensions.Angle(rotation, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.LeftWrist));

                                break;

                            case MJointType.RightWrist:
                                distance        = MVector3Extensions.Distance(position, this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.RightWrist));
                                angularDistance = MQuaternionExtensions.Angle(rotation, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.RightWrist));

                                break;

                            case MJointType.LeftBall:
                                distance        = MVector3Extensions.Distance(position, this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.LeftAnkle));
                                angularDistance = MQuaternionExtensions.Angle(rotation, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.LeftAnkle));

                                break;

                            case MJointType.RightBall:
                                distance        = MVector3Extensions.Distance(position, this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.RightAnkle));
                                angularDistance = MQuaternionExtensions.Angle(rotation, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.RightAnkle));

                                break;

                            case MJointType.PelvisCentre:
                                distance        = MVector3Extensions.Distance(position, this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.PelvisCentre));
                                angularDistance = MQuaternionExtensions.Angle(rotation, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.PelvisCentre));

                                break;
                            }
                        }

                        //Legacy fallback mechanism -> Remove in future
                        else
                        {
                            MTranslationConstraint positionConstraint = endeffectorConstraint.GeometryConstraint.TranslationConstraint;


                            if (endeffectorConstraint.GeometryConstraint.TranslationConstraint != null)
                            {
                                switch (endeffectorConstraint.JointType)
                                {
                                case MJointType.LeftWrist:
                                    distance = MVector3Extensions.Distance(new MVector3(positionConstraint.X(), positionConstraint.Y(), positionConstraint.Z()), this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.LeftWrist));
                                    break;

                                case MJointType.RightWrist:
                                    distance = MVector3Extensions.Distance(new MVector3(positionConstraint.X(), positionConstraint.Y(), positionConstraint.Z()), this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.RightWrist));
                                    break;

                                case MJointType.LeftBall:
                                    distance = MVector3Extensions.Distance(new MVector3(positionConstraint.X(), positionConstraint.Y(), positionConstraint.Z()), this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.LeftAnkle));
                                    break;

                                case MJointType.RightBall:
                                    distance = MVector3Extensions.Distance(new MVector3(positionConstraint.X(), positionConstraint.Y(), positionConstraint.Z()), this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.RightAnkle));
                                    break;

                                case MJointType.PelvisCentre:
                                    distance = MVector3Extensions.Distance(new MVector3(positionConstraint.X(), positionConstraint.Y(), positionConstraint.Z()), this.skeletonAccess.GetGlobalJointPosition(avatarID, MJointType.PelvisCentre));
                                    break;
                                }
                            }

                            //Handle the rotation constraint
                            if (endeffectorConstraint.GeometryConstraint.RotationConstraint != null)
                            {
                                MRotationConstraint rotationConstraint = endeffectorConstraint.GeometryConstraint.RotationConstraint;

                                //Compute a quaternion based on the euler angles
                                MQuaternion quaternion = MQuaternionExtensions.FromEuler(new MVector3(rotationConstraint.X(), rotationConstraint.Y(), rotationConstraint.Z()));

                                if (endeffectorConstraint.GeometryConstraint.ParentObjectID == null || endeffectorConstraint.GeometryConstraint.ParentObjectID == "")
                                {
                                    switch (endeffectorConstraint.JointType)
                                    {
                                    case MJointType.LeftWrist:
                                        angularDistance = MQuaternionExtensions.Angle(quaternion, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.LeftWrist));
                                        break;

                                    case MJointType.RightWrist:
                                        angularDistance = MQuaternionExtensions.Angle(quaternion, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.RightWrist));
                                        break;

                                    case MJointType.LeftBall:
                                        angularDistance = MQuaternionExtensions.Angle(quaternion, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.LeftAnkle));
                                        break;

                                    case MJointType.RightBall:
                                        angularDistance = MQuaternionExtensions.Angle(quaternion, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.RightAnkle));
                                        break;

                                    case MJointType.PelvisCentre:
                                        angularDistance = MQuaternionExtensions.Angle(quaternion, this.skeletonAccess.GetGlobalJointRotation(avatarID, MJointType.PelvisCentre));
                                        break;
                                    }
                                }
                            }
                        }

                        //Check if solving is required
                        if (distance > this.PositionThreshold || angularDistance > this.RotationThreshold)
                        {
                            violated.Add(mconstraint);
                        }
                    }
                }
            }

            return(violated);
        }