// Prepares an animation step. Records the positions, rotations, velocities // of the rigid bodies forming an animation into the animation step structure. void UpdateAnimationStep(float timeStep) { // HACK deal with two of first frame if (NormalizedTime == 0f && AnimationSteps.FirstOrDefault(x => x.NormalizedTime == 0f) != null) { return; } // var c = _master.Muscles.Count; var c = BodyParts.Count; var animStep = new AnimationStep(); animStep.TimeStep = timeStep; animStep.NormalizedTime = NormalizedTime; animStep.Velocities = Enumerable.Repeat(Vector3.zero, c).ToList(); animStep.VelocitiesLocal = Enumerable.Repeat(Vector3.zero, c).ToList(); animStep.AngularVelocities = Enumerable.Repeat(Vector3.zero, c).ToList(); animStep.AngularVelocitiesLocal = Enumerable.Repeat(Vector3.zero, c).ToList(); animStep.Positions = Enumerable.Repeat(Vector3.zero, c).ToList(); animStep.Rotations = Enumerable.Repeat(Quaternion.identity, c).ToList(); animStep.CenterOfMass = JointHelper002.GetCenterOfMassRelativeToRoot(BodyParts); //animStep.CenterOfMass = GetCenterOfMass(); animStep.CenterOfMassVelocity = animStep.CenterOfMass - _lastCenterOfMass; animStep.Names = BodyParts.Select(x => x.Name).ToList(); animStep.SensorIsInTouch = new List <float>(SensorIsInTouch); _lastCenterOfMass = animStep.CenterOfMass; var rootBone = BodyParts[0]; foreach (var bodyPart in BodyParts) { var i = BodyParts.IndexOf(bodyPart); if (i == 0) { animStep.Rotations[i] = Quaternion.Inverse(bodyPart.InitialRootRotation) * bodyPart.Transform.rotation; animStep.Positions[i] = bodyPart.Transform.position - bodyPart.InitialRootPosition; } else { animStep.Rotations[i] = Quaternion.Inverse(rootBone.Transform.rotation) * bodyPart.Transform.rotation; animStep.Positions[i] = bodyPart.Transform.position - rootBone.Transform.position; } if (NormalizedTime != 0f) { animStep.Velocities[i] = (bodyPart.Transform.position - _lastPosition[i]) / (_decisionRequester.DecisionPeriod * Time.fixedDeltaTime);; animStep.AngularVelocities[i] = JointHelper002.CalcDeltaRotationNormalizedEuler(_lastRotation[i], bodyPart.Transform.rotation) / (_decisionRequester.DecisionPeriod * Time.fixedDeltaTime);; animStep.VelocitiesLocal[i] = (animStep.Positions[i] - _lastPositionLocal[i]) / (_decisionRequester.DecisionPeriod * Time.fixedDeltaTime);; animStep.AngularVelocitiesLocal[i] = JointHelper002.CalcDeltaRotationNormalizedEuler(_lastRotationLocal[i], animStep.Rotations[i]) / (_decisionRequester.DecisionPeriod * Time.fixedDeltaTime); } if (bodyPart.Rigidbody != null) { bodyPart.Rigidbody.angularVelocity = JointHelper002.CalcDeltaRotationNormalizedEuler(bodyPart.Transform.rotation, _lastRotation[i]) / (_decisionRequester.DecisionPeriod * Time.fixedDeltaTime); bodyPart.Rigidbody.velocity = (bodyPart.Transform.position - _lastPosition[i]) / (_decisionRequester.DecisionPeriod * Time.fixedDeltaTime); bodyPart.Rigidbody.transform.position = bodyPart.Transform.position; bodyPart.Rigidbody.transform.rotation = bodyPart.Transform.rotation; } _lastPosition[i] = bodyPart.Transform.position; _lastRotation[i] = bodyPart.Transform.rotation; _lastPositionLocal[i] = animStep.Positions[i]; _lastRotationLocal[i] = animStep.Rotations[i]; } animStep.TransformPosition = transform.position; animStep.TransformRotation = transform.rotation; animStep.AngularMoment = JointHelper002.GetAngularMoment(BodyParts); AnimationSteps.Add(animStep); }
// Calculate values like ObsCenterOfMass, ObsAngularMoment that will be used // as observations fed into the neural network for training and inference. Also // calculates the distance metrics between animation's and agents' body parts. // The distances are used by the Agent to calculate rewards. The max distances // can be used to manually tune the denominators in exp(-distance/denominator) // when forming reward function. StyleTransfer002Animator.AnimationStep UpdateObservations() { if (DebugMode) { AnimationIndex = 0; } var debugStepIdx = AnimationIndex; StyleTransfer002Animator.AnimationStep animStep = null; StyleTransfer002Animator.AnimationStep debugAnimStep = null; if (_phaseIsRunning) { debugStepIdx += DebugAnimOffset; if (DebugShowWithOffset) { debugStepIdx = Mathf.Clamp(debugStepIdx, 0, _muscleAnimator.AnimationSteps.Count); debugAnimStep = _muscleAnimator.AnimationSteps[debugStepIdx]; } animStep = _muscleAnimator.AnimationSteps[AnimationIndex]; } EndEffectorDistance = 0f; EndEffectorVelocityDistance = 0; JointAngularVelocityDistance = 0; JointAngularVelocityDistanceWorld = 0; RotationDistance = 0f; CenterOfMassVelocityDistance = 0f; CenterOfMassDistance = 0f; AngularMomentDistance = 0f; SensorDistance = 0f; if (_phaseIsRunning && DebugShowWithOffset) { MimicAnimationFrame(debugAnimStep); } else if (_phaseIsRunning) { CompareAnimationFrame(animStep); } foreach (var muscle in Muscles) { var i = Muscles.IndexOf(muscle); muscle.UpdateObservations(); if (!DebugShowWithOffset && !DebugDisableMotor) { muscle.UpdateMotor(); } if (!muscle.Rigidbody.useGravity) { continue; // skip sub joints } } foreach (var bodyPart in BodyParts) { if (_phaseIsRunning) { bodyPart.UpdateObservations(); var rotDistance = bodyPart.ObsAngleDeltaFromAnimationRotation; var squareRotDistance = Mathf.Pow(rotDistance, 2); RotationDistance += squareRotDistance; JointAngularVelocityDistance += bodyPart.ObsDeltaFromAnimationAngularVelocity.sqrMagnitude; JointAngularVelocityDistanceWorld += bodyPart.ObsDeltaFromAnimationAngularVelocityWorld.sqrMagnitude; if (bodyPart.Group == BodyHelper002.BodyPartGroup.Hand || bodyPart.Group == BodyHelper002.BodyPartGroup.Torso || bodyPart.Group == BodyHelper002.BodyPartGroup.Foot) { EndEffectorDistance += bodyPart.ObsDeltaFromAnimationPosition.sqrMagnitude; EndEffectorVelocityDistance += bodyPart.ObsDeltaFromAnimationVelocity.sqrMagnitude; } } } ObsCenterOfMass = JointHelper002.GetCenterOfMassRelativeToRoot(BodyParts); ObsAngularMoment = JointHelper002.GetAngularMoment(BodyParts); if (_phaseIsRunning) { CenterOfMassDistance = (animStep.CenterOfMass - ObsCenterOfMass).sqrMagnitude; AngularMomentDistance = (animStep.AngularMoment - ObsAngularMoment).sqrMagnitude; } ObsVelocity = ObsCenterOfMass - _lastCenterOfMass; if (_fakeVelocity) { ObsVelocity = animStep.CenterOfMassVelocity; } _lastCenterOfMass = ObsCenterOfMass; if (!_resetCenterOfMassOnLastUpdate) { _fakeVelocity = false; } if (_phaseIsRunning) { var animVelocity = animStep.CenterOfMassVelocity / (Time.fixedDeltaTime * _decisionRequester.DecisionPeriod); ObsVelocity /= (Time.fixedDeltaTime * _decisionRequester.DecisionPeriod); CenterOfMassVelocityDistance = (ObsVelocity - animVelocity).sqrMagnitude; SensorDistance = 0.0f; var sensorDistanceStep = 1.0f / _agent.SensorIsInTouch.Count; for (int i = 0; i < _agent.SensorIsInTouch.Count; i++) { if (animStep.SensorIsInTouch[i] != _agent.SensorIsInTouch[i]) { SensorDistance += sensorDistanceStep; } } } if (!IgnorRewardUntilObservation) { MaxEndEffectorDistance = Mathf.Max(MaxEndEffectorDistance, EndEffectorDistance); MaxEndEffectorVelocityDistance = Mathf.Max(MaxEndEffectorVelocityDistance, EndEffectorVelocityDistance); MaxRotationDistance = Mathf.Max(MaxRotationDistance, RotationDistance); MaxCenterOfMassVelocityDistance = Mathf.Max(MaxCenterOfMassVelocityDistance, CenterOfMassVelocityDistance); MaxEndEffectorVelocityDistance = Mathf.Max(MaxEndEffectorVelocityDistance, EndEffectorVelocityDistance); MaxJointAngularVelocityDistance = Mathf.Max(MaxJointAngularVelocityDistance, JointAngularVelocityDistance); MaxJointAngularVelocityDistanceWorld = Mathf.Max(MaxJointAngularVelocityDistanceWorld, JointAngularVelocityDistanceWorld); MaxCenterOfMassDistance = Mathf.Max(MaxCenterOfMassDistance, CenterOfMassDistance); MaxAngularMomentDistance = Mathf.Max(MaxAngularMomentDistance, AngularMomentDistance); MaxSensorDistance = Mathf.Max(MaxSensorDistance, SensorDistance); } if (IgnorRewardUntilObservation) { IgnorRewardUntilObservation = false; } ObsPhase = _muscleAnimator.AnimationSteps[AnimationIndex].NormalizedTime % 1f; return(animStep); }