organisation & splat changes
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
// Implmentation of an Agent. Agent reads observations relevant to the reinforcement
|
||||
// learning task at hand, acts based on the observations, and receives a reward
|
||||
// based on its performance.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Unity.MLAgents;
|
||||
using Unity.MLAgents.Actuators;
|
||||
using Unity.MLAgents.Sensors;
|
||||
using System.Linq;
|
||||
using ManyWorlds;
|
||||
|
||||
public class StyleTransfer002Agent : Agent, IOnSensorCollision, IOnTerrainCollision {
|
||||
|
||||
public float FrameReward;
|
||||
public float AverageReward;
|
||||
public List<float> Rewards;
|
||||
public List<float> SensorIsInTouch;
|
||||
StyleTransfer002Master _master;
|
||||
StyleTransfer002Animator _localStyleAnimator;
|
||||
StyleTransfer002Animator _styleAnimator;
|
||||
DecisionRequester _decisionRequester;
|
||||
|
||||
List<GameObject> _sensors;
|
||||
|
||||
public bool ShowMonitor = false;
|
||||
|
||||
static int _startCount;
|
||||
static ScoreHistogramData _scoreHistogramData;
|
||||
int _totalAnimFrames;
|
||||
bool _ignorScoreForThisFrame;
|
||||
bool _isDone;
|
||||
bool _hasLazyInitialized;
|
||||
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
_master = GetComponent<StyleTransfer002Master>();
|
||||
_decisionRequester = GetComponent<DecisionRequester>();
|
||||
var spawnableEnv = GetComponentInParent<SpawnableEnv>();
|
||||
_localStyleAnimator = spawnableEnv.gameObject.GetComponentInChildren<StyleTransfer002Animator>();
|
||||
_styleAnimator = _localStyleAnimator.GetFirstOfThisAnim();
|
||||
_startCount++;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
}
|
||||
|
||||
// Collect observations that are used by the Neural Network for training and inference.
|
||||
override public void CollectObservations(VectorSensor sensor)
|
||||
{
|
||||
if (!_hasLazyInitialized)
|
||||
{
|
||||
OnEpisodeBegin();
|
||||
}
|
||||
|
||||
sensor.AddObservation(_master.ObsPhase);
|
||||
|
||||
foreach (var bodyPart in _master.BodyParts)
|
||||
{
|
||||
sensor.AddObservation(bodyPart.ObsLocalPosition);
|
||||
sensor.AddObservation(bodyPart.ObsRotation);
|
||||
sensor.AddObservation(bodyPart.ObsRotationVelocity);
|
||||
sensor.AddObservation(bodyPart.ObsVelocity);
|
||||
}
|
||||
foreach (var muscle in _master.Muscles)
|
||||
{
|
||||
if (muscle.ConfigurableJoint.angularXMotion != ConfigurableJointMotion.Locked)
|
||||
sensor.AddObservation(muscle.TargetNormalizedRotationX);
|
||||
if (muscle.ConfigurableJoint.angularYMotion != ConfigurableJointMotion.Locked)
|
||||
sensor.AddObservation(muscle.TargetNormalizedRotationY);
|
||||
if (muscle.ConfigurableJoint.angularZMotion != ConfigurableJointMotion.Locked)
|
||||
sensor.AddObservation(muscle.TargetNormalizedRotationZ);
|
||||
}
|
||||
|
||||
sensor.AddObservation(_master.ObsCenterOfMass);
|
||||
sensor.AddObservation(_master.ObsVelocity);
|
||||
sensor.AddObservation(_master.ObsAngularMoment);
|
||||
sensor.AddObservation(SensorIsInTouch);
|
||||
}
|
||||
|
||||
// A method that applies the vectorAction to the muscles, and calculates the rewards.
|
||||
public override void OnActionReceived(ActionBuffers actions)
|
||||
{
|
||||
float[] vectorAction = actions.ContinuousActions.Select(x=>x).ToArray();
|
||||
|
||||
if (!_hasLazyInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_isDone = false;
|
||||
if (_styleAnimator == _localStyleAnimator)
|
||||
_styleAnimator.OnAgentAction();
|
||||
_master.OnAgentAction();
|
||||
int i = 0;
|
||||
foreach (var muscle in _master.Muscles)
|
||||
{
|
||||
if (muscle.ConfigurableJoint.angularXMotion != ConfigurableJointMotion.Locked)
|
||||
muscle.TargetNormalizedRotationX = vectorAction[i++];
|
||||
if (muscle.ConfigurableJoint.angularYMotion != ConfigurableJointMotion.Locked)
|
||||
muscle.TargetNormalizedRotationY = vectorAction[i++];
|
||||
if (muscle.ConfigurableJoint.angularZMotion != ConfigurableJointMotion.Locked)
|
||||
muscle.TargetNormalizedRotationZ = vectorAction[i++];
|
||||
}
|
||||
|
||||
// the scaler factors are picked empirically by calculating the MaxRotationDistance, MaxVelocityDistance achieved for an untrained agent.
|
||||
var rotationDistance = _master.RotationDistance / 16f ;
|
||||
var centerOfMassvelocityDistance = _master.CenterOfMassVelocityDistance / 6f ;
|
||||
var endEffectorDistance = _master.EndEffectorDistance / 1f ;
|
||||
var endEffectorVelocityDistance = _master.EndEffectorVelocityDistance / 170f;
|
||||
var jointAngularVelocityDistance = _master.JointAngularVelocityDistance / 7000f;
|
||||
var jointAngularVelocityDistanceWorld = _master.JointAngularVelocityDistanceWorld / 7000f;
|
||||
var centerOfMassDistance = _master.CenterOfMassDistance / 0.3f;
|
||||
var angularMomentDistance = _master.AngularMomentDistance / 150.0f;
|
||||
var sensorDistance = _master.SensorDistance / 1f;
|
||||
|
||||
var rotationReward = 0.35f * Mathf.Exp(-rotationDistance);
|
||||
var centerOfMassVelocityReward = 0.1f * Mathf.Exp(-centerOfMassvelocityDistance);
|
||||
var endEffectorReward = 0.15f * Mathf.Exp(-endEffectorDistance);
|
||||
var endEffectorVelocityReward = 0.1f * Mathf.Exp(-endEffectorVelocityDistance);
|
||||
var jointAngularVelocityReward = 0.1f * Mathf.Exp(-jointAngularVelocityDistance);
|
||||
var jointAngularVelocityRewardWorld = 0.0f * Mathf.Exp(-jointAngularVelocityDistanceWorld);
|
||||
var centerMassReward = 0.05f * Mathf.Exp(-centerOfMassDistance);
|
||||
var angularMomentReward = 0.15f * Mathf.Exp(-angularMomentDistance);
|
||||
var sensorReward = 0.0f * Mathf.Exp(-sensorDistance);
|
||||
var jointsNotAtLimitReward = 0.0f * Mathf.Exp(-JointsAtLimit());
|
||||
|
||||
//Debug.Log("---------------");
|
||||
//Debug.Log("rotation reward: " + rotationReward);
|
||||
//Debug.Log("endEffectorReward: " + endEffectorReward);
|
||||
//Debug.Log("endEffectorVelocityReward: " + endEffectorVelocityReward);
|
||||
//Debug.Log("jointAngularVelocityReward: " + jointAngularVelocityReward);
|
||||
//Debug.Log("jointAngularVelocityRewardWorld: " + jointAngularVelocityRewardWorld);
|
||||
//Debug.Log("centerMassReward: " + centerMassReward);
|
||||
//Debug.Log("centerMassVelocityReward: " + centerOfMassVelocityReward);
|
||||
//Debug.Log("angularMomentReward: " + angularMomentReward);
|
||||
//Debug.Log("sensorReward: " + sensorReward);
|
||||
//Debug.Log("joints not at limit rewards:" + jointsNotAtLimitReward);
|
||||
|
||||
float reward = rotationReward +
|
||||
centerOfMassVelocityReward +
|
||||
endEffectorReward +
|
||||
endEffectorVelocityReward +
|
||||
jointAngularVelocityReward +
|
||||
jointAngularVelocityRewardWorld +
|
||||
centerMassReward +
|
||||
angularMomentReward +
|
||||
sensorReward +
|
||||
jointsNotAtLimitReward;
|
||||
|
||||
if (!_master.IgnorRewardUntilObservation)
|
||||
AddReward(reward);
|
||||
|
||||
if (reward < 0.5)
|
||||
EndEpisode();
|
||||
|
||||
if (!_isDone){
|
||||
if (_master.IsDone()){
|
||||
EndEpisode();
|
||||
if (_master.StartAnimationIndex > 0)
|
||||
_master.StartAnimationIndex--;
|
||||
}
|
||||
}
|
||||
FrameReward = reward;
|
||||
var stepCount = StepCount > 0 ? StepCount : 1;
|
||||
AverageReward = GetCumulativeReward() / (float) stepCount;
|
||||
}
|
||||
|
||||
// A helper function that calculates a fraction of joints at their limit positions
|
||||
float JointsAtLimit(string[] ignorJoints = null)
|
||||
{
|
||||
int atLimitCount = 0;
|
||||
int totalJoints = 0;
|
||||
foreach (var muscle in _master.Muscles)
|
||||
{
|
||||
if(muscle.Parent == null)
|
||||
continue;
|
||||
|
||||
var name = muscle.Name;
|
||||
if (ignorJoints != null && ignorJoints.Contains(name))
|
||||
continue;
|
||||
if (Mathf.Abs(muscle.TargetNormalizedRotationX) >= 1f)
|
||||
atLimitCount++;
|
||||
if (Mathf.Abs(muscle.TargetNormalizedRotationY) >= 1f)
|
||||
atLimitCount++;
|
||||
if (Mathf.Abs(muscle.TargetNormalizedRotationZ) >= 1f)
|
||||
atLimitCount++;
|
||||
totalJoints++;
|
||||
}
|
||||
float fractionOfJointsAtLimit = (float)atLimitCount / (float)totalJoints;
|
||||
return fractionOfJointsAtLimit;
|
||||
}
|
||||
|
||||
// Sets reward
|
||||
public void SetTotalAnimFrames(int totalAnimFrames)
|
||||
{
|
||||
_totalAnimFrames = totalAnimFrames;
|
||||
if (_scoreHistogramData == null) {
|
||||
var columns = _totalAnimFrames;
|
||||
if (_decisionRequester?.DecisionPeriod > 1)
|
||||
columns /= _decisionRequester.DecisionPeriod;
|
||||
_scoreHistogramData = new ScoreHistogramData(columns, 30);
|
||||
}
|
||||
Rewards = _scoreHistogramData.GetAverages().Select(x=>(float)x).ToList();
|
||||
}
|
||||
|
||||
// Resets the agent. Initialize the style animator and master if not initialized.
|
||||
public override void OnEpisodeBegin()
|
||||
{
|
||||
if (!_hasLazyInitialized)
|
||||
{
|
||||
_master = GetComponent<StyleTransfer002Master>();
|
||||
_master.BodyConfig = MarathonManAgent.BodyConfig;
|
||||
_decisionRequester = GetComponent<DecisionRequester>();
|
||||
var spawnableEnv = GetComponentInParent<SpawnableEnv>();
|
||||
_localStyleAnimator = spawnableEnv.gameObject.GetComponentInChildren<StyleTransfer002Animator>();
|
||||
_styleAnimator = _localStyleAnimator.GetFirstOfThisAnim();
|
||||
_styleAnimator.BodyConfig = MarathonManAgent.BodyConfig;
|
||||
|
||||
_styleAnimator.OnInitializeAgent();
|
||||
_master.OnInitializeAgent();
|
||||
|
||||
_hasLazyInitialized = true;
|
||||
_localStyleAnimator.DestoryIfNotFirstAnim();
|
||||
}
|
||||
_isDone = true;
|
||||
_ignorScoreForThisFrame = true;
|
||||
_master.ResetPhase();
|
||||
_sensors = GetComponentsInChildren<SensorBehavior>()
|
||||
.Select(x=>x.gameObject)
|
||||
.ToList();
|
||||
SensorIsInTouch = Enumerable.Range(0,_sensors.Count).Select(x=>0f).ToList();
|
||||
if (_scoreHistogramData != null) {
|
||||
var column = _master.StartAnimationIndex;
|
||||
if (_decisionRequester?.DecisionPeriod > 1)
|
||||
column /= _decisionRequester.DecisionPeriod;
|
||||
if (_ignorScoreForThisFrame)
|
||||
_ignorScoreForThisFrame = false;
|
||||
else
|
||||
_scoreHistogramData.SetItem(column, AverageReward);
|
||||
}
|
||||
}
|
||||
|
||||
// A method called on terrain collision. Used for early stopping an episode
|
||||
// on specific objects' collision with terrain.
|
||||
public virtual void OnTerrainCollision(GameObject other, GameObject terrain)
|
||||
{
|
||||
if (string.Compare(terrain.name, "Terrain", true) != 0)
|
||||
return;
|
||||
if (!_styleAnimator.AnimationStepsReady)
|
||||
return;
|
||||
var bodyPart = _master.BodyParts.FirstOrDefault(x=>x.Transform.gameObject == other);
|
||||
if (bodyPart == null)
|
||||
return;
|
||||
switch (bodyPart.Group)
|
||||
{
|
||||
case BodyHelper002.BodyPartGroup.None:
|
||||
case BodyHelper002.BodyPartGroup.Foot:
|
||||
case BodyHelper002.BodyPartGroup.LegUpper:
|
||||
case BodyHelper002.BodyPartGroup.LegLower:
|
||||
case BodyHelper002.BodyPartGroup.Hand:
|
||||
case BodyHelper002.BodyPartGroup.ArmLower:
|
||||
case BodyHelper002.BodyPartGroup.ArmUpper:
|
||||
break;
|
||||
default:
|
||||
EndEpisode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the a flag in Sensors In Touch array when an object enters collision with terrain
|
||||
public void OnSensorCollisionEnter(Collider sensorCollider, GameObject other)
|
||||
{
|
||||
if (string.Compare(other.name, "Terrain", true) !=0)
|
||||
return;
|
||||
if (_sensors == null || _sensors.Count == 0)
|
||||
return;
|
||||
var sensor = _sensors
|
||||
.FirstOrDefault(x=>x == sensorCollider.gameObject);
|
||||
if (sensor != null) {
|
||||
var idx = _sensors.IndexOf(sensor);
|
||||
SensorIsInTouch[idx] = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the a flag in Sensors In Touch array when an object stops colliding with terrain
|
||||
public void OnSensorCollisionExit(Collider sensorCollider, GameObject other)
|
||||
{
|
||||
if (string.Compare(other.gameObject.name, "Terrain", true) !=0)
|
||||
return;
|
||||
if (_sensors == null || _sensors.Count == 0)
|
||||
return;
|
||||
var sensor = _sensors
|
||||
.FirstOrDefault(x=>x == sensorCollider.gameObject);
|
||||
if (sensor != null) {
|
||||
var idx = _sensors.IndexOf(sensor);
|
||||
SensorIsInTouch[idx] = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/3_MarathonEnvs/Scripts/StyleTransfer/StyleTransfer002Agent.cs.meta
generated
Normal file
11
Assets/3_MarathonEnvs/Scripts/StyleTransfer/StyleTransfer002Agent.cs.meta
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec9cfe0db841e420283facda78fa8b61
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,443 @@
|
||||
// A class defining the Animator. The Animator is used as a reference for an
|
||||
// Agent that mimicks the animator behavior. Before training, the animator's
|
||||
// animation is run once and all the charateristics of it are stored as animSteps.
|
||||
// During training, the agent can simply acess the precomputed values and mimick
|
||||
// Animator's body Part' velocities, positions, rotations, angular velocities, etc.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Unity.MLAgents;
|
||||
using UnityEngine;
|
||||
|
||||
public class StyleTransfer002Animator : MonoBehaviour, IOnSensorCollision {
|
||||
|
||||
internal Animator anim;
|
||||
|
||||
public List<float> SensorIsInTouch;
|
||||
List<GameObject> _sensors;
|
||||
|
||||
public List<AnimationStep> AnimationSteps;
|
||||
public bool AnimationStepsReady;
|
||||
public bool IsLoopingAnimation;
|
||||
|
||||
[Range(0f,1f)]
|
||||
public float NormalizedTime;
|
||||
public float Lenght;
|
||||
|
||||
private List<Vector3> _lastPosition;
|
||||
private List<Quaternion> _lastRotation;
|
||||
private List<Vector3> _lastPositionLocal;
|
||||
private List<Quaternion> _lastRotationLocal;
|
||||
|
||||
List<Quaternion> _initialRotations;
|
||||
|
||||
public List<BodyPart002> BodyParts;
|
||||
|
||||
private Vector3 _lastCenterOfMass;
|
||||
|
||||
private List<Rigidbody> _rigidbodies;
|
||||
private List<Transform> _transforms;
|
||||
|
||||
private bool isFirstOfThisAnim;
|
||||
|
||||
[System.Serializable]
|
||||
public class AnimationStep
|
||||
{
|
||||
public float TimeStep;
|
||||
public float NormalizedTime;
|
||||
public List<Vector3> Velocities;
|
||||
public List<Vector3> VelocitiesLocal;
|
||||
public Vector3 CenterOfMassVelocity;
|
||||
public List<Vector3> AngularVelocities;
|
||||
public List<Vector3> AngularVelocitiesLocal;
|
||||
|
||||
public List<Vector3> Positions;
|
||||
public List<Quaternion> Rotations;
|
||||
public List<string> Names;
|
||||
public Vector3 CenterOfMass;
|
||||
public Vector3 AngularMoment;
|
||||
public Vector3 TransformPosition;
|
||||
public Quaternion TransformRotation;
|
||||
public List<float> SensorIsInTouch;
|
||||
|
||||
}
|
||||
|
||||
public BodyConfig BodyConfig;
|
||||
DecisionRequester _decisionRequester;
|
||||
|
||||
// Use this for initialization
|
||||
public void OnInitializeAgent()
|
||||
{
|
||||
|
||||
_decisionRequester = GameObject.Find("MarathonMan").GetComponent<DecisionRequester>();
|
||||
|
||||
anim = GetComponent<Animator>();
|
||||
anim.Play("Record",0, NormalizedTime);
|
||||
anim.Update(0f);
|
||||
AnimationSteps = new List<AnimationStep>();
|
||||
|
||||
if (_rigidbodies == null || _transforms == null)
|
||||
{
|
||||
_rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
|
||||
_transforms = GetComponentsInChildren<Transform>().ToList();
|
||||
}
|
||||
|
||||
SetupSensors();
|
||||
OnAgentAction();
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
SetupSensors();
|
||||
}
|
||||
|
||||
void SetupSensors()
|
||||
{
|
||||
_sensors = GetComponentsInChildren<SensorBehavior>()
|
||||
.Select(x=>x.gameObject)
|
||||
.ToList();
|
||||
SensorIsInTouch = Enumerable.Range(0,_sensors.Count).Select(x=>0f).ToList();
|
||||
}
|
||||
|
||||
// Reset the animator.
|
||||
void Reset()
|
||||
{
|
||||
BodyParts = new List<BodyPart002> ();
|
||||
BodyPart002 root = null;
|
||||
|
||||
if (_rigidbodies == null || _transforms == null)
|
||||
{
|
||||
_rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
|
||||
_transforms = GetComponentsInChildren<Transform>().ToList();
|
||||
}
|
||||
|
||||
foreach (var t in _transforms)
|
||||
{
|
||||
if (BodyConfig.GetBodyPartGroup(t.name) == BodyHelper002.BodyPartGroup.None)
|
||||
continue;
|
||||
|
||||
var bodyPart = new BodyPart002 {
|
||||
Rigidbody = t.GetComponent<Rigidbody>(),
|
||||
Transform = t,
|
||||
Name = t.name,
|
||||
Group = BodyConfig.GetBodyPartGroup(t.name),
|
||||
};
|
||||
if (bodyPart.Group == BodyConfig.GetRootBodyPart())
|
||||
root = bodyPart;
|
||||
bodyPart.Root = root;
|
||||
bodyPart.Init();
|
||||
BodyParts.Add(bodyPart);
|
||||
}
|
||||
var partCount = BodyParts.Count;
|
||||
SetupSensors();
|
||||
|
||||
_lastPosition = Enumerable.Repeat(Vector3.zero, partCount).ToList();
|
||||
_lastRotation = Enumerable.Repeat(Quaternion.identity, partCount).ToList();
|
||||
_lastPositionLocal = Enumerable.Repeat(Vector3.zero, partCount).ToList();
|
||||
_lastRotationLocal = Enumerable.Repeat(Quaternion.identity, partCount).ToList();
|
||||
_lastCenterOfMass = transform.position;
|
||||
_initialRotations = BodyParts
|
||||
.Select(x=> x.Transform.rotation)
|
||||
.ToList();
|
||||
BecomeAnimated();
|
||||
}
|
||||
|
||||
public StyleTransfer002Animator GetFirstOfThisAnim()
|
||||
{
|
||||
if (isFirstOfThisAnim)
|
||||
return this;
|
||||
var anim = GetComponent<Animator>();
|
||||
var styleAnimators = FindObjectsOfType<StyleTransfer002Animator>().ToList();
|
||||
var firstOfThisAnim = styleAnimators
|
||||
.Where(x=> x.GetComponent<Animator>().avatar == anim.avatar)
|
||||
.FirstOrDefault(x=> x.isFirstOfThisAnim);
|
||||
if (firstOfThisAnim != null)
|
||||
return firstOfThisAnim;
|
||||
isFirstOfThisAnim = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Mimics the positions of body parts of an animation. Computes AnimStep structure
|
||||
// for the step if it is not computed already.
|
||||
public void OnAgentAction() {
|
||||
|
||||
if (AnimationStepsReady){
|
||||
MimicAnimation();
|
||||
return;
|
||||
}
|
||||
if (_lastPosition == null)
|
||||
Reset();
|
||||
AnimatorStateInfo stateInfo = anim.GetCurrentAnimatorStateInfo(0);
|
||||
AnimatorClipInfo[] clipInfo = anim.GetCurrentAnimatorClipInfo(0);
|
||||
Lenght = stateInfo.length;
|
||||
NormalizedTime = stateInfo.normalizedTime;
|
||||
IsLoopingAnimation = stateInfo.loop;
|
||||
var timeStep = stateInfo.length * stateInfo.normalizedTime;
|
||||
|
||||
var endTime = 1f;
|
||||
if (IsLoopingAnimation)
|
||||
endTime = 3f;
|
||||
if (NormalizedTime <= endTime) {
|
||||
MimicAnimation();
|
||||
if (!AnimationStepsReady)
|
||||
UpdateAnimationStep(timeStep);
|
||||
}
|
||||
else {
|
||||
StopAnimation();
|
||||
// BecomeRagDoll();
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Sets kinematic flag for Animator's rigid bodies to true
|
||||
public void BecomeAnimated()
|
||||
{
|
||||
if (_rigidbodies == null || _transforms == null)
|
||||
{
|
||||
_rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
|
||||
_transforms = GetComponentsInChildren<Transform>().ToList();
|
||||
}
|
||||
foreach (var rb in _rigidbodies)
|
||||
{
|
||||
rb.isKinematic = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the kinematic flags for Animator's rigid bodies to false
|
||||
public void BecomeRagDoll()
|
||||
{
|
||||
if (_rigidbodies == null || _transforms == null)
|
||||
{
|
||||
_rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
|
||||
_transforms = GetComponentsInChildren<Transform>().ToList();
|
||||
}
|
||||
foreach (var rb in _rigidbodies)
|
||||
{
|
||||
rb.isKinematic = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the animation
|
||||
public void StopAnimation()
|
||||
{
|
||||
AnimationStepsReady = true;
|
||||
anim.enabled=false;
|
||||
}
|
||||
|
||||
public void DestoryIfNotFirstAnim()
|
||||
{
|
||||
if (!isFirstOfThisAnim){
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets positions and rotations of the Animator's body Rigid Bodies to match
|
||||
// the positions and rotations of the animation avatar. The rotatin and position
|
||||
// values passed as arguments to the MimicBone() calls are adjusted so that
|
||||
// the avatar's body parts' positions and rotations look identical to the
|
||||
// Animator's body parts
|
||||
public void MimicAnimation()
|
||||
{
|
||||
if (!anim.enabled)
|
||||
return;
|
||||
|
||||
MimicBone("butt", "mixamorig:Hips", new Vector3(.0f, -.055f, .0f), Quaternion.Euler(90, 0f, 0f));
|
||||
MimicBone("lower_waist", "mixamorig:Spine", new Vector3(.0f, .0153f, .0f), Quaternion.Euler(90, 0f, 0f));
|
||||
MimicBone("torso", "mixamorig:Spine2", new Vector3(.0f, .04f, .0f), Quaternion.Euler(90, 0f, 0f));
|
||||
|
||||
MimicBone("left_upper_arm", "mixamorig:LeftArm", "mixamorig:LeftForeArm", new Vector3(.0f, .0f, .0f), Quaternion.Euler(0, 45, 180));
|
||||
MimicBone("left_larm", "mixamorig:LeftForeArm", "mixamorig:LeftHand", new Vector3(.0f, .0f, .0f), Quaternion.Euler(0, -180-45, 180));
|
||||
|
||||
MimicBone("right_upper_arm", "mixamorig:RightArm", "mixamorig:RightForeArm", new Vector3(.0f, .0f, .0f), Quaternion.Euler(0, 180-45, 180));
|
||||
MimicBone("right_larm", "mixamorig:RightForeArm", "mixamorig:RightHand", new Vector3(.0f, .0f, .0f), Quaternion.Euler(0, 90-45, 180));
|
||||
|
||||
MimicBone("left_thigh", "mixamorig:LeftUpLeg", "mixamorig:LeftLeg", new Vector3(.0f, .0f, .0f), Quaternion.Euler(0, 0, 180));
|
||||
MimicBone("left_shin", "mixamorig:LeftLeg", "mixamorig:LeftFoot", new Vector3(.0f, .02f, .0f), Quaternion.Euler(0, 0, 180));
|
||||
|
||||
MimicBone("right_thigh", "mixamorig:RightUpLeg", "mixamorig:RightLeg", new Vector3(.0f, .0f, .0f), Quaternion.Euler(0, 0, 180));
|
||||
MimicBone("right_shin", "mixamorig:RightLeg", "mixamorig:RightFoot", new Vector3(.0f, .02f, .0f), Quaternion.Euler(0, 0, 180));
|
||||
|
||||
MimicRightFoot("right_right_foot", new Vector3(.0f, -.0f, -.0f), Quaternion.Euler(3, -90, 180));//3));
|
||||
MimicLeftFoot("left_left_foot", new Vector3(-.0f, -.0f, -.0f), Quaternion.Euler(-8, -90, 180));//3));
|
||||
}
|
||||
|
||||
// Set position and rotation of a rigid body to match avatar's rigid body
|
||||
void MimicBone(string name, string bodyPartName, Vector3 offset, Quaternion rotationOffset)
|
||||
{
|
||||
if (_rigidbodies == null || _transforms == null)
|
||||
{
|
||||
_rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
|
||||
_transforms = GetComponentsInChildren<Transform>().ToList();
|
||||
}
|
||||
|
||||
var bodyPart = _transforms.First(x=>x.name == bodyPartName);
|
||||
var target = _rigidbodies.First(x=>x.name == name);
|
||||
|
||||
target.transform.position = bodyPart.transform.position + offset;
|
||||
target.transform.rotation = bodyPart.transform.rotation * rotationOffset;
|
||||
}
|
||||
|
||||
// Set position and rotation of a rigid body to match avatar's rigid body
|
||||
void MimicBone(string name, string animStartName, string animEndtName, Vector3 offset, Quaternion rotationOffset)
|
||||
{
|
||||
if (_rigidbodies == null || _transforms == null)
|
||||
{
|
||||
_rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
|
||||
_transforms = GetComponentsInChildren<Transform>().ToList();
|
||||
}
|
||||
|
||||
|
||||
var animStartBone = _transforms.First(x=>x.name == animStartName);
|
||||
var animEndBone = _transforms.First(x=>x.name == animEndtName);
|
||||
var target = _rigidbodies.First(x=>x.name == name);
|
||||
|
||||
var pos = (animEndBone.transform.position - animStartBone.transform.position);
|
||||
target.transform.position = animStartBone.transform.position + pos/2 + offset;
|
||||
target.transform.rotation = animStartBone.transform.rotation * rotationOffset;
|
||||
}
|
||||
|
||||
[Range(0f,1f)]
|
||||
public float toePositionOffset = .3f;
|
||||
[Range(0f,1f)]
|
||||
public float toeRotationOffset = .7f;
|
||||
|
||||
// Set position and rotation of the left foot to match avatar's left foor
|
||||
void MimicLeftFoot(string name, Vector3 offset, Quaternion rotationOffset)
|
||||
{
|
||||
string animStartName = "mixamorig:LeftFoot";
|
||||
string animEndtName = "mixamorig:LeftToe_End";
|
||||
if (_rigidbodies == null || _transforms == null)
|
||||
{
|
||||
_rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
|
||||
_transforms = GetComponentsInChildren<Transform>().ToList();
|
||||
}
|
||||
|
||||
var animStartBone = _transforms.First(x=>x.name == animStartName);
|
||||
var animEndBone = _transforms.First(x=>x.name == animEndtName);
|
||||
var target = _rigidbodies.First(x=>x.name == name);
|
||||
|
||||
var rotation = Quaternion.Lerp(animStartBone.rotation, animEndBone.rotation, toeRotationOffset);
|
||||
var skinOffset = (animEndBone.transform.position - animStartBone.transform.position);
|
||||
target.transform.position = animStartBone.transform.position + (skinOffset * toePositionOffset) + offset;
|
||||
target.transform.rotation = rotation * rotationOffset;
|
||||
}
|
||||
|
||||
// Set position and rotation of the right foot to match avatar's right foot
|
||||
void MimicRightFoot(string name, Vector3 offset, Quaternion rotationOffset)
|
||||
{
|
||||
string animStartName = "mixamorig:RightFoot";
|
||||
string animEndtName = "mixamorig:RightToe_End";
|
||||
if (_rigidbodies == null || _transforms == null)
|
||||
{
|
||||
_rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
|
||||
_transforms = GetComponentsInChildren<Transform>().ToList();
|
||||
}
|
||||
|
||||
|
||||
var animStartBone = _transforms.First(x=>x.name == animStartName);
|
||||
var animEndBone = _transforms.First(x=>x.name == animEndtName);
|
||||
var target = _rigidbodies.First(x=>x.name == name);
|
||||
|
||||
var rotation = Quaternion.Lerp(animStartBone.rotation, animEndBone.rotation, toeRotationOffset);
|
||||
var skinOffset = (animEndBone.transform.position - animStartBone.transform.position);
|
||||
target.transform.position = animStartBone.transform.position + (skinOffset * toePositionOffset) + offset;
|
||||
target.transform.rotation = rotation * rotationOffset;
|
||||
|
||||
}
|
||||
|
||||
// Update the array of Sensors In Touch if an Animator's collider collides
|
||||
// with an object named "Terrain"
|
||||
public void OnSensorCollisionEnter(Collider sensorCollider, GameObject other)
|
||||
{
|
||||
if (string.Compare(other.name, "Terrain", true) !=0)
|
||||
return;
|
||||
var sensor = _sensors
|
||||
.FirstOrDefault(x=>x == sensorCollider.gameObject);
|
||||
if (sensor != null) {
|
||||
var idx = _sensors.IndexOf(sensor);
|
||||
SensorIsInTouch[idx] = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the array of Sensors In Touch if a sensor no more collides with terrain
|
||||
public void OnSensorCollisionExit(Collider sensorCollider, GameObject other)
|
||||
{
|
||||
if (string.Compare(other.gameObject.name, "Terrain", true) !=0)
|
||||
return;
|
||||
var sensor = _sensors
|
||||
.FirstOrDefault(x=>x == sensorCollider.gameObject);
|
||||
if (sensor != null) {
|
||||
var idx = _sensors.IndexOf(sensor);
|
||||
SensorIsInTouch[idx] = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/3_MarathonEnvs/Scripts/StyleTransfer/StyleTransfer002Animator.cs.meta
generated
Normal file
11
Assets/3_MarathonEnvs/Scripts/StyleTransfer/StyleTransfer002Animator.cs.meta
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3543848243544424b5503dcdc34970c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,437 @@
|
||||
// The Master script is attached to the Agent object. Calculates the distance metrics
|
||||
// used by the Agent to calculate rewards: distances between the rotations of agent's
|
||||
// body parts and Animator's body parts, the distance between the angular momentum, and
|
||||
// the center of masses.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Unity.MLAgents;
|
||||
using System;
|
||||
using ManyWorlds;
|
||||
|
||||
public class StyleTransfer002Master : MonoBehaviour {
|
||||
|
||||
public float FixedDeltaTime = 0.005f;
|
||||
public bool visualizeAnimator = true;
|
||||
|
||||
// general observations
|
||||
public List<Muscle002> Muscles;
|
||||
public List<BodyPart002> BodyParts;
|
||||
public float ObsPhase;
|
||||
public Vector3 ObsCenterOfMass;
|
||||
public Vector3 ObsAngularMoment;
|
||||
public Vector3 ObsVelocity;
|
||||
|
||||
// model observations
|
||||
// i.e. model = difference between mocap and actual)
|
||||
// ideally we dont want to generate model at inference
|
||||
public float EndEffectorDistance; // feet, hands, head
|
||||
public float EndEffectorVelocityDistance; // feet, hands, head
|
||||
public float JointAngularVelocityDistance;
|
||||
public float JointAngularVelocityDistanceWorld;
|
||||
public float RotationDistance;
|
||||
public float CenterOfMassVelocityDistance;
|
||||
public float CenterOfMassDistance;
|
||||
public float AngularMomentDistance;
|
||||
public float SensorDistance;
|
||||
|
||||
public float MaxEndEffectorDistance; // feet, hands, head
|
||||
public float MaxEndEffectorVelocityDistance; // feet, hands, head
|
||||
public float MaxJointAngularVelocityDistance;
|
||||
public float MaxJointAngularVelocityDistanceWorld;
|
||||
public float MaxRotationDistance;
|
||||
public float MaxCenterOfMassVelocityDistance;
|
||||
public float MaxCenterOfMassDistance;
|
||||
public float MaxAngularMomentDistance;
|
||||
public float MaxSensorDistance;
|
||||
|
||||
// debug variables
|
||||
public bool IgnorRewardUntilObservation;
|
||||
public float ErrorCutoff;
|
||||
public bool DebugShowWithOffset;
|
||||
public bool DebugMode;
|
||||
public bool DebugDisableMotor;
|
||||
[Range(-100,100)]
|
||||
public int DebugAnimOffset;
|
||||
|
||||
public float TimeStep;
|
||||
public int AnimationIndex;
|
||||
public int EpisodeAnimationIndex;
|
||||
public int StartAnimationIndex;
|
||||
public bool UseRandomIndexForTraining;
|
||||
public bool UseRandomIndexForInference;
|
||||
public bool CameraFollowMe;
|
||||
public Transform CameraTarget;
|
||||
|
||||
private bool _isDone;
|
||||
bool _resetCenterOfMassOnLastUpdate;
|
||||
bool _fakeVelocity;
|
||||
bool _waitingForAnimation;
|
||||
|
||||
private StyleTransfer002Animator _muscleAnimator;
|
||||
private StyleTransfer002Agent _agent;
|
||||
StyleTransfer002Animator _styleAnimator;
|
||||
StyleTransfer002Animator _localStyleAnimator;
|
||||
DecisionRequester _decisionRequester;
|
||||
|
||||
public bool IsInferenceMode;
|
||||
bool _phaseIsRunning;
|
||||
Vector3 _lastCenterOfMass;
|
||||
|
||||
public BodyConfig BodyConfig;
|
||||
|
||||
// Initialize the Agent. Sets up Body Parts, Muscles.
|
||||
public void OnInitializeAgent()
|
||||
{
|
||||
foreach (var rb in GetComponentsInChildren<Rigidbody>())
|
||||
{
|
||||
if (rb.useGravity == false)
|
||||
rb.solverVelocityIterations = 255;
|
||||
}
|
||||
var masters = FindObjectsOfType<StyleTransfer002Master>().ToList();
|
||||
if (masters.Count(x=>x.CameraFollowMe) < 1)
|
||||
CameraFollowMe = true;
|
||||
|
||||
Time.fixedDeltaTime = FixedDeltaTime;
|
||||
_waitingForAnimation = true;
|
||||
_decisionRequester = GetComponent<DecisionRequester>();
|
||||
|
||||
BodyParts = new List<BodyPart002> ();
|
||||
BodyPart002 root = null;
|
||||
foreach (var t in GetComponentsInChildren<Transform>())
|
||||
{
|
||||
if (BodyConfig.GetBodyPartGroup(t.name) == BodyHelper002.BodyPartGroup.None)
|
||||
continue;
|
||||
|
||||
var bodyPart = new BodyPart002{
|
||||
Rigidbody = t.GetComponent<Rigidbody>(),
|
||||
Transform = t,
|
||||
Name = t.name,
|
||||
Group = BodyConfig.GetBodyPartGroup(t.name),
|
||||
};
|
||||
if (bodyPart.Group == BodyConfig.GetRootBodyPart())
|
||||
root = bodyPart;
|
||||
bodyPart.Root = root;
|
||||
bodyPart.Init();
|
||||
BodyParts.Add(bodyPart);
|
||||
}
|
||||
var partCount = BodyParts.Count;
|
||||
|
||||
Muscles = new List<Muscle002> ();
|
||||
var muscles = GetComponentsInChildren<ConfigurableJoint>();
|
||||
ConfigurableJoint rootConfigurableJoint = null;
|
||||
var ragDoll = GetComponent<RagDoll002>();
|
||||
foreach (var m in muscles)
|
||||
{
|
||||
var maximumForce = ragDoll.MusclePowers.First(x=>x.Muscle == m.name).PowerVector;
|
||||
var muscle = new Muscle002{
|
||||
Rigidbody = m.GetComponent<Rigidbody>(),
|
||||
Transform = m.GetComponent<Transform>(),
|
||||
ConfigurableJoint = m,
|
||||
Name = m.name,
|
||||
Group = BodyConfig.GetMuscleGroup(m.name),
|
||||
MaximumForce = maximumForce
|
||||
};
|
||||
if (muscle.Group == BodyConfig.GetRootMuscle())
|
||||
rootConfigurableJoint = muscle.ConfigurableJoint;
|
||||
muscle.RootConfigurableJoint = rootConfigurableJoint;
|
||||
muscle.Init();
|
||||
|
||||
Muscles.Add(muscle);
|
||||
}
|
||||
var spawnableEnv = GetComponentInParent<SpawnableEnv>();
|
||||
_localStyleAnimator = spawnableEnv.gameObject.GetComponentInChildren<StyleTransfer002Animator>();
|
||||
_styleAnimator = _localStyleAnimator.GetFirstOfThisAnim();
|
||||
_muscleAnimator = _styleAnimator;
|
||||
_agent = GetComponent<StyleTransfer002Agent>();
|
||||
|
||||
IsInferenceMode = !Academy.Instance.IsCommunicatorOn;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
}
|
||||
|
||||
public void OnAgentAction()
|
||||
{
|
||||
if (_waitingForAnimation && _styleAnimator.AnimationStepsReady){
|
||||
_waitingForAnimation = false;
|
||||
ResetPhase();
|
||||
}
|
||||
var animStep = UpdateObservations();
|
||||
Step(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;
|
||||
}
|
||||
|
||||
// Increment animation index. The index is used to get the current AnimStep structure.
|
||||
void Step(StyleTransfer002Animator.AnimationStep animStep)
|
||||
{
|
||||
if (_phaseIsRunning){
|
||||
if (!DebugShowWithOffset)
|
||||
AnimationIndex++;
|
||||
if (AnimationIndex>=_muscleAnimator.AnimationSteps.Count) {
|
||||
EndEpisode();
|
||||
AnimationIndex--;
|
||||
}
|
||||
}
|
||||
if (_phaseIsRunning && IsInferenceMode && CameraFollowMe)
|
||||
{
|
||||
_muscleAnimator.anim.enabled = true;
|
||||
_muscleAnimator.anim.Play("Record",0, animStep.NormalizedTime);
|
||||
_muscleAnimator.anim.transform.position = animStep.TransformPosition;
|
||||
_muscleAnimator.anim.transform.rotation = animStep.TransformRotation;
|
||||
}
|
||||
}
|
||||
|
||||
void CompareAnimationFrame(StyleTransfer002Animator.AnimationStep animStep)
|
||||
{
|
||||
MimicAnimationFrame(animStep, true);
|
||||
}
|
||||
|
||||
// Moves Agent's body part to animation's position and rotation if onlySetAnimation = false.
|
||||
// Then sets the target animation for each Agent's body part. The animation's
|
||||
// positions and rotations are later on used by the Body Part object to calculate
|
||||
// distance metrics to the target animation.
|
||||
void MimicAnimationFrame(StyleTransfer002Animator.AnimationStep animStep, bool onlySetAnimation = false)
|
||||
{
|
||||
if (!onlySetAnimation)
|
||||
{
|
||||
foreach (var rb in GetComponentsInChildren<Rigidbody>())
|
||||
{
|
||||
rb.angularVelocity = Vector3.zero;
|
||||
rb.velocity = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var bodyPart in BodyParts)
|
||||
{
|
||||
var i = animStep.Names.IndexOf(bodyPart.Name);
|
||||
Vector3 animPosition = bodyPart.InitialRootPosition + animStep.Positions[0];
|
||||
Quaternion animRotation = bodyPart.InitialRootRotation * animStep.Rotations[0];
|
||||
if (i != 0) {
|
||||
animPosition += animStep.Positions[i];
|
||||
animRotation *= animStep.Rotations[i];
|
||||
}
|
||||
Vector3 angularVelocity = animStep.AngularVelocities[i];
|
||||
Vector3 velocity = animStep.Velocities[i];
|
||||
|
||||
Vector3 angularVelocityLocal = animStep.AngularVelocitiesLocal[i];
|
||||
Vector3 velocityLocal = animStep.VelocitiesLocal[i];
|
||||
|
||||
bool setAnim = !onlySetAnimation;
|
||||
if (bodyPart.Name.Contains("head") || bodyPart.Name.Contains("upper_waist"))
|
||||
setAnim = false;
|
||||
if (setAnim) {
|
||||
bodyPart.MoveToAnim(animPosition, animRotation, angularVelocity, velocity);
|
||||
}
|
||||
|
||||
bodyPart.SetAnimationPosition(animPosition, animStep.Rotations[i], velocity, angularVelocityLocal, angularVelocity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected virtual void LateUpdate() {
|
||||
if (_resetCenterOfMassOnLastUpdate){
|
||||
ObsCenterOfMass = JointHelper002.GetCenterOfMassRelativeToRoot(BodyParts);
|
||||
//ObsCenterOfMass = GetCenterOfMass();
|
||||
_lastCenterOfMass = ObsCenterOfMass;
|
||||
_resetCenterOfMassOnLastUpdate = false;
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
VisualizeTargetPose();
|
||||
#endif
|
||||
}
|
||||
|
||||
public bool IsDone()
|
||||
{
|
||||
return _isDone;
|
||||
}
|
||||
|
||||
void EndEpisode()
|
||||
{
|
||||
_isDone = true;
|
||||
}
|
||||
|
||||
public void ResetPhase()
|
||||
{
|
||||
if (_waitingForAnimation)
|
||||
return;
|
||||
_decisionRequester.enabled = true;
|
||||
_agent.SetTotalAnimFrames(_muscleAnimator.AnimationSteps.Count);
|
||||
SetStartIndex(0); // HACK for gym
|
||||
UpdateObservations();
|
||||
}
|
||||
|
||||
public void SetStartIndex(int startIdx)
|
||||
{
|
||||
_decisionRequester.enabled = false;
|
||||
|
||||
if (!_phaseIsRunning){
|
||||
StartAnimationIndex = _muscleAnimator.AnimationSteps.Count-1;
|
||||
EpisodeAnimationIndex = _muscleAnimator.AnimationSteps.Count-1;
|
||||
AnimationIndex = EpisodeAnimationIndex;
|
||||
if (CameraFollowMe){
|
||||
var camera = FindObjectOfType<Camera>();
|
||||
var follow = camera.GetComponent<SmoothFollow>();
|
||||
follow.target = CameraTarget;
|
||||
}
|
||||
}
|
||||
|
||||
AnimationIndex = startIdx;
|
||||
if (_decisionRequester?.DecisionPeriod > 1)
|
||||
AnimationIndex *= this._decisionRequester.DecisionPeriod;
|
||||
StartAnimationIndex = AnimationIndex;
|
||||
EpisodeAnimationIndex = AnimationIndex;
|
||||
_phaseIsRunning = true;
|
||||
_isDone = false;
|
||||
var animStep = _muscleAnimator.AnimationSteps[AnimationIndex];
|
||||
TimeStep = animStep.TimeStep;
|
||||
EndEffectorDistance = 0f;
|
||||
EndEffectorVelocityDistance = 0f;
|
||||
JointAngularVelocityDistance = 0;
|
||||
JointAngularVelocityDistanceWorld = 0;
|
||||
RotationDistance = 0f;
|
||||
CenterOfMassVelocityDistance = 0f;
|
||||
IgnorRewardUntilObservation = true;
|
||||
_resetCenterOfMassOnLastUpdate = true;
|
||||
_fakeVelocity = true;
|
||||
foreach (var muscle in Muscles)
|
||||
muscle.Init();
|
||||
foreach (var bodyPart in BodyParts)
|
||||
bodyPart.Init();
|
||||
MimicAnimationFrame(animStep);
|
||||
EpisodeAnimationIndex = AnimationIndex;
|
||||
}
|
||||
|
||||
private void VisualizeTargetPose() {
|
||||
if (!visualizeAnimator) return;
|
||||
if (!Application.isEditor) return;
|
||||
}
|
||||
|
||||
// Recursively visualizes a bone hierarchy
|
||||
private void VisualizeHierarchy(Transform t, Color color) {
|
||||
for (int i = 0; i < t.childCount; i++) {
|
||||
Debug.DrawLine(t.position, t.GetChild(i).position, color);
|
||||
VisualizeHierarchy(t.GetChild(i), color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
11
Assets/3_MarathonEnvs/Scripts/StyleTransfer/StyleTransfer002Master.cs.meta
generated
Normal file
11
Assets/3_MarathonEnvs/Scripts/StyleTransfer/StyleTransfer002Master.cs.meta
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbee4689469f148ca897ef6aabbab08d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user