implementation of drecon in unity 2022 lts forked from: https://github.com/joanllobera/marathon-envs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
14 KiB

9 months ago
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.MLAgents;
using UnityEngine;
using ManyWorlds;
using UnityEngine.Assertions;
public class Observations2Learn : MonoBehaviour
{
[Header("Observations")]
[Tooltip("Kinematic character center of mass velocity, Vector3")]
public Vector3 MocapCOMVelocity;
[Tooltip("RagDoll character center of mass velocity, Vector3")]
public Vector3 RagDollCOMVelocity;
[Tooltip("User-input desired horizontal CM velocity. Vector2")]
public Vector2 InputDesiredHorizontalVelocity;
[Tooltip("User-input requests jump, bool")]
public bool InputJump;
[Tooltip("User-input requests backflip, bool")]
public bool InputBackflip;
[Tooltip("Difference between RagDoll character horizontal CM velocity and user-input desired horizontal CM velocity. Vector2")]
public Vector2 HorizontalVelocityDifference;
[Tooltip("Positions and velocities for subset of bodies")]
public List<BodyPartDifferenceStats> BodyPartDifferenceStats;
public List<ObservationStats.Stat> MocapBodyStats;
public List<ObservationStats.Stat> RagDollBodyStats;
[Tooltip("Smoothed actions produced in the previous step of the policy are collected in t −1")]
public float[] PreviousActions;
//[Tooltip("RagDoll ArticulationBody joint positions in reduced space")]
//public float[] RagDollJointPositions;
// [Tooltip("RagDoll ArticulationBody joint velocity in reduced space")]
// public float[] RagDollJointVelocities;
// [Tooltip("RagDoll ArticulationBody joint accelerations in reduced space")]
// public float[] RagDollJointAccelerations;
[Tooltip("RagDoll ArticulationBody joint forces in reduced space")]
public float[] RagDollJointForces;
[Tooltip("Macap: ave of joint angular velocity")]
public float EnergyAngularMocap;
[Tooltip("RagDoll: ave of joint angular velocity")]
public float EnergyAngularRagDoll;
[Tooltip("RagDoll-Macap: ave of joint angular velocity")]
public float EnergyDifferenceAngular;
[Tooltip("Macap: ave of joint velocity in local space")]
public float EnergyPositionalMocap;
[Tooltip("RagDoll: ave of joint velocity in local space")]
public float EnergyPositionalRagDoll;
[Tooltip("RagDoll-Macap: ave of joint velocity in local space")]
public float EnergyDifferencePositional;
[Header("Gizmos")]
public bool VelocityInWorldSpace = true;
public bool PositionInWorldSpace = true;
public string targetedRootName = "articulation:Hips";
InputController _inputController;
SpawnableEnv _spawnableEnv;
ObservationStats _mocapBodyStats;
ObservationStats _ragDollBodyStats;
bool _hasLazyInitialized;
List<ArticulationBody> _motors;
public void OnAgentInitialize()
{
Assert.IsFalse(_hasLazyInitialized);
_hasLazyInitialized = true;
_spawnableEnv = GetComponentInParent<SpawnableEnv>();
_inputController = _spawnableEnv.GetComponentInChildren<InputController>();
_mocapBodyStats = new GameObject("MocapDReConObservationStats").AddComponent<ObservationStats>();
_mocapBodyStats.setRootName(targetedRootName);
_mocapBodyStats.ObjectToTrack = _spawnableEnv.GetComponentInChildren<MapAnim2Ragdoll>();
_mocapBodyStats.transform.SetParent(_spawnableEnv.transform);
_mocapBodyStats.OnAgentInitialize(_mocapBodyStats.ObjectToTrack.transform);
_ragDollBodyStats = new GameObject("RagDollDReConObservationStats").AddComponent<ObservationStats>();
_ragDollBodyStats.setRootName(targetedRootName);
_ragDollBodyStats.ObjectToTrack = this;
_ragDollBodyStats.transform.SetParent(_spawnableEnv.transform);
_ragDollBodyStats.OnAgentInitialize(transform);
BodyPartDifferenceStats = _mocapBodyStats.Stats
.Select(x => new BodyPartDifferenceStats { Name = x.Name })
.ToList();
int numJoints = 0;
_motors = GetComponentsInChildren<ArticulationBody>()
.Where(x => x.jointType == ArticulationJointType.SphericalJoint)
.Where(x => !x.isRoot)
.Distinct()
.ToList();
foreach (var m in _motors)
{
if (m.twistLock == ArticulationDofLock.LimitedMotion)
numJoints++;
if (m.swingYLock == ArticulationDofLock.LimitedMotion)
numJoints++;
if (m.swingZLock == ArticulationDofLock.LimitedMotion)
numJoints++;
}
PreviousActions = Enumerable.Range(0,numJoints).Select(x=>0f).ToArray();
//RagDollJointPositions = Enumerable.Range(0,numJoints).Select(x=>0f).ToArray();
// RagDollJointVelocities = Enumerable.Range(0,numJoints).Select(x=>0f).ToArray();
// RagDollJointAccelerations = Enumerable.Range(0,numJoints).Select(x=>0f).ToArray();
RagDollJointForces = Enumerable.Range(0,numJoints).Select(x=>0f).ToArray();
}
public List<Collider> EstimateBodyPartsForObservation()
{
var colliders = GetComponentsInChildren<Collider>()
.Where(x => x.enabled)
.Where(x => !x.isTrigger)
.Where(x=> {
var ignoreCollider = x.GetComponent<IgnoreColliderForObservation>();
if (ignoreCollider == null)
return true;
return !ignoreCollider.enabled;})
.Distinct()
.ToList();
return colliders;
}
public List<Collider> EstimateBodyPartsForReward()
{
var colliders = GetComponentsInChildren<Collider>()
.Where(x => x.enabled)
.Where(x => !x.isTrigger)
.Where(x=> {
var ignoreCollider = x.GetComponent<IgnoreColliderForReward>();
if (ignoreCollider == null)
return true;
return !ignoreCollider.enabled;})
.Distinct()
.ToList();
return colliders;
}
public void OnStep(float timeDelta)
{
Assert.IsTrue(_hasLazyInitialized);
_mocapBodyStats.SetStatusForStep(timeDelta);
_ragDollBodyStats.SetStatusForStep(timeDelta);
UpdateObservations(timeDelta);
}
public void OnReset()
{
Assert.IsTrue(_hasLazyInitialized);
_mocapBodyStats.OnReset();
_ragDollBodyStats.OnReset();
_ragDollBodyStats.transform.position = _mocapBodyStats.transform.position;
_ragDollBodyStats.transform.rotation = _mocapBodyStats.transform.rotation;
var timeDelta = float.MinValue;
UpdateObservations(timeDelta);
}
public void UpdateObservations(float timeDelta)
{
MocapCOMVelocity = _mocapBodyStats.CenterOfMassVelocity;
RagDollCOMVelocity = _ragDollBodyStats.CenterOfMassVelocity;
InputDesiredHorizontalVelocity = new Vector2(
_ragDollBodyStats.DesiredCenterOfMassVelocity.x,
_ragDollBodyStats.DesiredCenterOfMassVelocity.z);
if (_inputController != null)
{
InputJump = _inputController.Jump;
InputBackflip = _inputController.Backflip;
}
HorizontalVelocityDifference = new Vector2(
_ragDollBodyStats.CenterOfMassVelocityDifference.x,
_ragDollBodyStats.CenterOfMassVelocityDifference.z);
MocapBodyStats = _mocapBodyStats.Stats.ToList();
RagDollBodyStats = MocapBodyStats
.Select(x => _ragDollBodyStats.Stats.First(y => y.Name == x.Name))
.ToList();
// BodyPartStats =
foreach (var differenceStats in BodyPartDifferenceStats)
{
var mocapStats = _mocapBodyStats.Stats.First(x => x.Name == differenceStats.Name);
var ragDollStats = _ragDollBodyStats.Stats.First(x => x.Name == differenceStats.Name);
differenceStats.Position = mocapStats.Position - ragDollStats.Position;
differenceStats.Velocity = mocapStats.Velocity - ragDollStats.Velocity;
differenceStats.AngualrVelocity = mocapStats.AngularVelocity - ragDollStats.AngularVelocity;
differenceStats.Rotation = ObservationStats.GetAngularVelocity(mocapStats.Rotation, ragDollStats.Rotation, timeDelta);
}
int i = 0;
foreach (var m in _motors)
{
int j = 0;
if (m.twistLock == ArticulationDofLock.LimitedMotion)
{
//RagDollJointPositions[i] = m.jointPosition[j];
// RagDollJointVelocities[i] = m.jointVelocity[j];
// RagDollJointAccelerations[i] = m.jointAcceleration[j];
RagDollJointForces[i++] = m.jointForce[j++];
}
if (m.swingYLock == ArticulationDofLock.LimitedMotion)
{
// RagDollJointPositions[i] = m.jointPosition[j];
// RagDollJointVelocities[i] = m.jointVelocity[j];
// RagDollJointAccelerations[i] = m.jointAcceleration[j];
RagDollJointForces[i++] = m.jointForce[j++];
}
if (m.swingZLock == ArticulationDofLock.LimitedMotion)
{
// RagDollJointPositions[i] = m.jointPosition[j];
// RagDollJointVelocities[i] = m.jointVelocity[j];
// RagDollJointAccelerations[i] = m.jointAcceleration[j];
RagDollJointForces[i++] = m.jointForce[j++];
}
}
EnergyAngularMocap = MocapBodyStats
.Select(x=>x.AngularVelocity.magnitude)
.Average();
EnergyAngularRagDoll = RagDollBodyStats
.Select(x=>x.AngularVelocity.magnitude)
.Average();
EnergyDifferenceAngular = RagDollBodyStats
.Zip(MocapBodyStats, (x,y) => x.AngularVelocity.magnitude-y.AngularVelocity.magnitude)
.Average();
EnergyPositionalMocap = MocapBodyStats
.Select(x=>x.Velocity.magnitude)
.Average();
EnergyPositionalRagDoll = RagDollBodyStats
.Select(x=>x.Velocity.magnitude)
.Average();
EnergyDifferencePositional = RagDollBodyStats
.Zip(MocapBodyStats, (x,y) => x.Velocity.magnitude-y.Velocity.magnitude)
.Average();
}
public Transform GetRagDollCOM()
{
return _ragDollBodyStats.transform;
}
public Vector3 GetMocapCOMVelocityInWorldSpace()
{
var velocity = _mocapBodyStats.CenterOfMassVelocity;
var velocityInWorldSpace = _mocapBodyStats.transform.TransformVector(velocity);
return velocityInWorldSpace;
}
void OnDrawGizmos()
{
if (_mocapBodyStats == null)
return;
// MocapCOMVelocity
Vector3 pos = new Vector3(transform.position.x, .3f, transform.position.z);
Vector3 vector = MocapCOMVelocity;
if (VelocityInWorldSpace)
vector = _mocapBodyStats.transform.TransformVector(vector);
DrawArrow(pos, vector, Color.grey);
// RagDollCOMVelocity;
vector = RagDollCOMVelocity;
if (VelocityInWorldSpace)
vector = _ragDollBodyStats.transform.TransformVector(vector);
DrawArrow(pos, vector, Color.blue);
Vector3 actualPos = pos + vector;
// InputDesiredHorizontalVelocity;
vector = new Vector3(InputDesiredHorizontalVelocity.x, 0f, InputDesiredHorizontalVelocity.y);
if (VelocityInWorldSpace)
vector = _ragDollBodyStats.transform.TransformVector(vector);
DrawArrow(pos, vector, Color.green);
// HorizontalVelocityDifference;
vector = new Vector3(HorizontalVelocityDifference.x, 0f, HorizontalVelocityDifference.y);
if (VelocityInWorldSpace)
vector = _ragDollBodyStats.transform.TransformVector(vector);
DrawArrow(actualPos, vector, Color.red);
for (int i = 0; i < RagDollBodyStats.Count; i++)
{
var stat = RagDollBodyStats[i];
var differenceStat = BodyPartDifferenceStats[i];
pos = stat.Position;
vector = stat.Velocity;
if (PositionInWorldSpace)
pos = _ragDollBodyStats.transform.TransformPoint(pos);
if (VelocityInWorldSpace)
vector = _ragDollBodyStats.transform.TransformVector(vector);
DrawArrow(pos, vector, Color.cyan);
Vector3 velocityPos = pos + vector;
pos = stat.Position;
vector = differenceStat.Position;
if (PositionInWorldSpace)
pos = _ragDollBodyStats.transform.TransformPoint(pos);
if (VelocityInWorldSpace)
vector = _ragDollBodyStats.transform.TransformVector(vector);
Gizmos.color = Color.magenta;
Gizmos.DrawRay(pos, vector);
Vector3 differencePos = pos + vector;
vector = differenceStat.Velocity;
if (VelocityInWorldSpace)
vector = _ragDollBodyStats.transform.TransformVector(vector);
DrawArrow(velocityPos, vector, Color.red);
}
}
void DrawArrow(Vector3 start, Vector3 vector, Color color)
{
float headSize = 0.25f;
float headAngle = 20.0f;
Gizmos.color = color;
Gizmos.DrawRay(start, vector);
if (vector.magnitude > 0f)
{
Vector3 right = Quaternion.LookRotation(vector) * Quaternion.Euler(0, 180 + headAngle, 0) * new Vector3(0, 0, 1);
Vector3 left = Quaternion.LookRotation(vector) * Quaternion.Euler(0, 180 - headAngle, 0) * new Vector3(0, 0, 1);
Gizmos.DrawRay(start + vector, right * headSize);
Gizmos.DrawRay(start + vector, left * headSize);
}
}
}