organisation & splat changes

This commit is contained in:
2024-03-28 14:55:33 +00:00
parent d487af62b8
commit 0535f6df4c
347 changed files with 3579 additions and 1956 deletions

View File

@@ -0,0 +1,11 @@
using System;
using static BodyHelper002;
public class BodyConfig
{
public Func<string, BodyPartGroup> GetBodyPartGroup;
public Func<string, MuscleGroup> GetMuscleGroup;
public Func<BodyPartGroup> GetRootBodyPart;
public Func<MuscleGroup> GetRootMuscle;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03e1cab076cd94a488d1decc5d843de7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
public static class BodyHelper002
{
[System.Serializable]
public enum BodyPartGroup {
None,
Hips,
Torso,
Spine,
Head,
ArmUpper,
ArmLower,
Hand,
LegUpper,
LegLower,
Foot,
}
[System.Serializable]
public enum MuscleGroup {
None,
Hips,
Torso,
Spine,
Head,
ArmUpper,
ArmLower,
Hand,
LegUpper,
LegLower,
Foot,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bf75e597c351b12498957c0ec1d646fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,594 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
using System.Linq;
using static BodyHelper002;
using System;
using ManyWorlds;
public class BodyManager002 : MonoBehaviour, IOnSensorCollision
{
// Options / Configurables global properties
public Transform CameraTarget;
public float FixedDeltaTime = 0.005f;
public bool ShowMonitor = false;
public bool DebugDisableMotor;
public bool DebugShowWithOffset;
// Observations / Read only global properties
public List<Muscle002> Muscles;
public List<BodyPart002> BodyParts;
public List<float> SensorIsInTouch;
public List<float> Observations;
public int ObservationNormalizedErrors;
public int MaxObservationNormalizedErrors;
public List<GameObject> Sensors;
public float FrameReward;
public float AverageReward;
// private properties
Vector3 startPosition;
Dictionary<GameObject, Vector3> transformsPosition;
Dictionary<GameObject, Quaternion> transformsRotation;
Agent _agent;
SpawnableEnv _spawnableEnv;
TerrainGenerator _terrainGenerator;
DecisionRequester _decisionRequester;
static int _startCount;
float[] lastVectorAction;
float[] vectorDifference;
List <Vector3> mphBuffer;
[Tooltip("Max distance travelled across all episodes")]
/**< \brief Max distance travelled across all episodes*/
public float MaxDistanceTraveled;
[Tooltip("Distance travelled this episode")]
/**< \brief Distance travelled this episode*/
public float DistanceTraveled;
List<SphereCollider> sensorColliders;
static int _spawnCount;
// static ScoreHistogramData _scoreHistogramData;
// void FixedUpdate()
// {
// 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
// // }
// }
public BodyConfig BodyConfig;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void OnInitializeAgent()
{
_spawnableEnv = GetComponentInParent<SpawnableEnv>();
_terrainGenerator = GetComponentInParent<TerrainGenerator>();
SetupBody();
DistanceTraveled = float.MinValue;
}
public void OnAgentReset()
{
if (DistanceTraveled != float.MinValue)
{
var scorer = FindObjectOfType<Scorer>();
scorer?.ReportScore(DistanceTraveled, "Distance Traveled");
}
HandleModelReset();
Sensors = _agent.GetComponentsInChildren<SensorBehavior>()
.Select(x=>x.gameObject)
.ToList();
sensorColliders = Sensors
.Select(x=>x.GetComponent<SphereCollider>())
.ToList();
SensorIsInTouch = Enumerable.Range(0,Sensors.Count).Select(x=>0f).ToList();
// HACK first spawned agent should grab the camera
var smoothFollow = GameObject.FindObjectOfType<SmoothFollow>();
if (smoothFollow != null && smoothFollow.target == null) {
if (_spawnCount == 0) // HACK follow nth agent
{
smoothFollow.target = CameraTarget;
ShowMonitor = true;
}
else
_spawnCount++;
}
lastVectorAction = null;
vectorDifference = null;
mphBuffer = new List<Vector3>();
}
public void OnAgentAction(float[] vectorAction)
{
if (lastVectorAction == null){
lastVectorAction = vectorAction.Select(x=>0f).ToArray();
vectorDifference = vectorAction.Select(x=>0f).ToArray();
}
int i = 0;
foreach (var muscle in Muscles)
{
// if(muscle.Parent == null)
// continue;
if (muscle.ConfigurableJoint.angularXMotion != ConfigurableJointMotion.Locked){
vectorDifference[i] = Mathf.Abs(vectorAction[i]-lastVectorAction[i]);
muscle.TargetNormalizedRotationX = vectorAction[i++];
}
if (muscle.ConfigurableJoint.angularYMotion != ConfigurableJointMotion.Locked){
vectorDifference[i] = Mathf.Abs(vectorAction[i]-lastVectorAction[i]);
muscle.TargetNormalizedRotationY = vectorAction[i++];
}
if (muscle.ConfigurableJoint.angularZMotion != ConfigurableJointMotion.Locked){
vectorDifference[i] = Mathf.Abs(vectorAction[i]-lastVectorAction[i]);
muscle.TargetNormalizedRotationZ = vectorAction[i++];
}
if (!DebugDisableMotor)
muscle.UpdateMotor();
}
if (ShowMonitor)
{
// var hist = new[] {velocity, uprightBonus, heightPenality, effort}.ToList();
// Monitor.Log("rewardHist", hist.ToArray(), displayType: Monitor.DisplayType.Independent);
}
}
public BodyPart002 GetFirstBodyPart(BodyPartGroup bodyPartGroup)
{
var bodyPart = BodyParts.FirstOrDefault(x=>x.Group == bodyPartGroup);
return bodyPart;
}
public List<BodyPart002> GetBodyParts()
{
return BodyParts;
}
public List<BodyPart002> GetBodyParts(BodyPartGroup bodyPartGroup)
{
return BodyParts.Where(x=>x.Group == bodyPartGroup).ToList();
}
public float GetActionDifference()
{
float actionDifference = 1f - vectorDifference.Average();
actionDifference = Mathf.Clamp(actionDifference, 0, 1);
actionDifference = Mathf.Pow(actionDifference,2);
return actionDifference;
}
void SetupBody()
{
_agent = GetComponent<Agent>();
_decisionRequester = GetComponent<DecisionRequester>();
Time.fixedDeltaTime = FixedDeltaTime;
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;
maximumForce *= ragDoll.MotorScale;
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);
}
_startCount++;
}
void HandleModelReset()
{
Transform[] allChildren = _agent.GetComponentsInChildren<Transform>();
if (transformsPosition != null)
{
foreach (var child in allChildren)
{
child.position = transformsPosition[child.gameObject];
child.rotation = transformsRotation[child.gameObject];
var childRb = child.GetComponent<Rigidbody>();
if (childRb != null)
{
childRb.angularVelocity = Vector3.zero;
childRb.velocity = Vector3.zero;
}
}
}
else
{
startPosition = _agent.transform.position;
transformsPosition = new Dictionary<GameObject, Vector3>();
transformsRotation = new Dictionary<GameObject, Quaternion>();
foreach (Transform child in allChildren)
{
transformsPosition[child.gameObject] = child.position;
transformsRotation[child.gameObject] = child.rotation;
}
}
}
public float GetHeightNormalizedReward(float maxHeight)
{
var height = GetHeight();
var heightPenality = maxHeight - height;
heightPenality = Mathf.Clamp(heightPenality, 0f, maxHeight);
var reward = 1f - heightPenality;
reward = Mathf.Clamp(reward, 0f, 1f);
return reward;
}
internal float GetHeight()
{
var feetYpos = BodyParts
.Where(x => x.Group == BodyPartGroup.Foot)
.Select(x => x.Transform.position.y)
.OrderBy(x => x)
.ToList();
float lowestFoot = 0f;
if (feetYpos != null && feetYpos.Count != 0)
lowestFoot = feetYpos[0];
var height = GetFirstBodyPart(BodyPartGroup.Head).Transform.position.y - lowestFoot;
return height;
}
public float GetDirectionNormalizedReward(BodyPartGroup bodyPartGroup, Vector3 direction)
{
BodyPart002 bodyPart = GetFirstBodyPart(bodyPartGroup);
float maxBonus = 1f;
var toFocalAngle = bodyPart.ToFocalRoation * bodyPart.Transform.right;
var angle = Vector3.Angle(toFocalAngle, direction);
var qpos2 = (angle % 180) / 180;
var bonus = maxBonus * (2 - (Mathf.Abs(qpos2) * 2) - 1);
return bonus;
}
public float GetUprightNormalizedReward(BodyPartGroup bodyPartGroup)
{
BodyPart002 bodyPart = GetFirstBodyPart(bodyPartGroup);
float maxBonus = 1f;
var toFocalAngle = bodyPart.ToFocalRoation * -bodyPart.Transform.forward;
var angleFromUp = Vector3.Angle(toFocalAngle, Vector3.up);
var qpos2 = (angleFromUp % 180) / 180;
var uprightBonus = maxBonus * (2 - (Mathf.Abs(qpos2) * 2) - 1);
return uprightBonus;
}
public float GetEffortNormalized(string[] ignorJoints = null)
{
double effort = 0;
double jointEffort = 0;
double joints = 0;
foreach (var muscle in Muscles)
{
if(muscle.Parent == null)
continue;
var name = muscle.Name;
if (ignorJoints != null && ignorJoints.Contains(name))
continue;
if (muscle.ConfigurableJoint.angularXMotion != ConfigurableJointMotion.Locked) {
jointEffort = Mathf.Pow(Mathf.Abs(muscle.TargetNormalizedRotationX),2);
effort += jointEffort;
joints++;
}
if (muscle.ConfigurableJoint.angularYMotion != ConfigurableJointMotion.Locked) {
jointEffort = Mathf.Pow(Mathf.Abs(muscle.TargetNormalizedRotationY),2);
effort += jointEffort;
joints++;
}
if (muscle.ConfigurableJoint.angularZMotion != ConfigurableJointMotion.Locked) {
jointEffort = Mathf.Pow(Mathf.Abs(muscle.TargetNormalizedRotationZ),2);
effort += jointEffort;
joints++;
}
}
return (float) (effort / joints);
}
public void OnSensorCollisionEnter(Collider sensorCollider, GameObject other) {
// if (string.Compare(other.name, "Terrain", true) !=0)
if (other.GetComponent<Terrain>() == null)
return;
var sensor = Sensors
.FirstOrDefault(x=>x == sensorCollider.gameObject);
if (sensor != null) {
var idx = Sensors.IndexOf(sensor);
SensorIsInTouch[idx] = 1f;
}
}
public void OnSensorCollisionExit(Collider sensorCollider, GameObject other)
{
// if (string.Compare(other.gameObject.name, "Terrain", true) !=0)
if (other.GetComponent<Terrain>() == null)
return;
var sensor = Sensors
.FirstOrDefault(x=>x == sensorCollider.gameObject);
if (sensor != null) {
var idx = Sensors.IndexOf(sensor);
SensorIsInTouch[idx] = 0f;
}
}
public Vector3 GetLocalCenterOfMass()
{
var centerOfMass = GetCenterOfMass();
centerOfMass -= transform.position;
return centerOfMass;
}
public Vector3 GetCenterOfMass()
{
var centerOfMass = Vector3.zero;
float totalMass = 0f;
var bodies = BodyParts
.Select(x=>x.Rigidbody)
.Where(x=>x!=null)
.ToList();
foreach (Rigidbody rb in bodies)
{
centerOfMass += rb.worldCenterOfMass * rb.mass;
totalMass += rb.mass;
}
centerOfMass /= totalMass;
return centerOfMass;
}
public Vector3 GetNormalizedVelocity()
{
var pelvis = GetFirstBodyPart(BodyConfig.GetRootBodyPart());
Vector3 metersPerSecond = pelvis.Rigidbody.velocity;
var n = GetNormalizedVelocity(metersPerSecond);
return n;
}
public Vector3 GetNormalizedPosition()
{
// var position = GetCenterOfMass();
var pelvis = GetFirstBodyPart(BodyConfig.GetRootBodyPart());
var position = pelvis.Transform.position;
var normalizedPosition = GetNormalizedPosition(position - startPosition);
return normalizedPosition;
}
public void SetDebugFrameReward(float reward)
{
FrameReward = reward;
var stepCount = _agent.StepCount > 0 ? _agent.StepCount : 1;
if (_decisionRequester?.DecisionPeriod > 1)
stepCount /= _decisionRequester.DecisionPeriod;
AverageReward = _agent.GetCumulativeReward() / (float) stepCount;
}
public List<float> GetSensorIsInTouch()
{
return SensorIsInTouch;
}
// public List<float> GetBodyPartsObservations()
// {
// List<float> vectorObservation = new List<float>();
// foreach (var bodyPart in BodyParts)
// {
// bodyPart.UpdateObservations();
// // _agent.sensor.AddObservation(bodyPart.ObsRotation);
// vectorObservation.Add(bodyPart.ObsRotation.x);
// vectorObservation.Add(bodyPart.ObsRotation.y);
// vectorObservation.Add(bodyPart.ObsRotation.z);
// vectorObservation.Add(bodyPart.ObsRotation.w);
// // _agent.sensor.AddObservation(bodyPart.ObsRotationVelocity);
// vectorObservation.Add(bodyPart.ObsRotationVelocity.x);
// vectorObservation.Add(bodyPart.ObsRotationVelocity.y);
// vectorObservation.Add(bodyPart.ObsRotationVelocity.z);
// // _agent.sensor.AddObservation(GetNormalizedVelocity(bodyPart.ObsVelocity));
// var normalizedVelocity = GetNormalizedVelocity(bodyPart.ObsVelocity);
// vectorObservation.Add(normalizedVelocity.x);
// vectorObservation.Add(normalizedVelocity.y);
// vectorObservation.Add(normalizedVelocity.z);
// }
// return vectorObservation;
// }
public List<float> GetMusclesObservations()
{
List<float> vectorObservation = new List<float>();
foreach (var muscle in Muscles)
{
muscle.UpdateObservations();
if (muscle.ConfigurableJoint.angularXMotion != ConfigurableJointMotion.Locked)
vectorObservation.Add(muscle.TargetNormalizedRotationX);
if (muscle.ConfigurableJoint.angularYMotion != ConfigurableJointMotion.Locked)
vectorObservation.Add(muscle.TargetNormalizedRotationY);
if (muscle.ConfigurableJoint.angularZMotion != ConfigurableJointMotion.Locked)
vectorObservation.Add(muscle.TargetNormalizedRotationZ);
}
return vectorObservation;
}
[Obsolete("use GetSensorObservations()")]
public List<float> GetSensorYPositions()
{
var sensorYpositions = Sensors
.Select(x=> this.GetNormalizedPosition(x.transform.position - startPosition))
.Select(x=>x.y)
.ToList();
return sensorYpositions;
}
[Obsolete("use GetSensorObservations()")]
public List<float> GetSensorZPositions()
{
var sensorYpositions = Sensors
.Select(x=> this.GetNormalizedPosition(x.transform.position - startPosition))
.Select(x=>x.z)
.ToList();
return sensorYpositions;
}
public List<float> GetSensorObservations()
{
var localSensorsPos = new Vector3[Sensors.Count];
var globalSensorsPos = new Vector3[Sensors.Count];
for (int i = 0; i < Sensors.Count; i++) {
globalSensorsPos[i] = sensorColliders[i].transform.TransformPoint(sensorColliders[i].center);
localSensorsPos[i] = globalSensorsPos[i] - startPosition;
}
// get heights based on global senor position
var sensorsPos = Sensors
.Select(x=>x.transform.position).ToList();
var senorHeights = _terrainGenerator != null
? _terrainGenerator.GetDistances2d(globalSensorsPos)
: Enumerable.Range(0, globalSensorsPos.Length).Select(x=>0f).ToList();
for (int i = 0; i < Sensors.Count; i++) {
senorHeights[i] -= sensorColliders[i].radius;
if (senorHeights[i] >= 1f)
senorHeights[i] = 1f;
}
// get z positions based on local positions
var bounds = _spawnableEnv.bounds;
var normalizedZ = localSensorsPos
.Select(x=>x.z / (bounds.extents.z))
.ToList();
var observations = senorHeights
.Concat(normalizedZ)
.ToList();
return observations;
}
// public void OnCollectObservationsHandleDebug(AgentInfo info)
// {
// if (Observations?.Count != info.vectorObservation.Count)
// Observations = Enumerable.Range(0, info.vectorObservation.Count).Select(x => 0f).ToList();
// ObservationNormalizedErrors = 0;
// for (int i = 0; i < Observations.Count; i++)
// {
// Observations[i] = info.vectorObservation[i];
// var x = Mathf.Abs(Observations[i]);
// var e = Mathf.Epsilon;
// bool is1 = Mathf.Approximately(x, 1f);
// if ((x > 1f + e) && !is1)
// ObservationNormalizedErrors++;
// }
// if (ObservationNormalizedErrors > MaxObservationNormalizedErrors)
// MaxObservationNormalizedErrors = ObservationNormalizedErrors;
// var pelvis = GetFirstBodyPart(BodyPartGroup.Hips);
// DistanceTraveled = pelvis.Transform.position.x;
// MaxDistanceTraveled = Mathf.Max(MaxDistanceTraveled, DistanceTraveled);
// Vector3 metersPerSecond = pelvis.Rigidbody.velocity;
// Vector3 mph = metersPerSecond * 2.236936f;
// mphBuffer.Add(mph);
// if (mphBuffer.Count > 100)
// mphBuffer.RemoveAt(0);
// var aveMph = new Vector3(
// mphBuffer.Select(x=>x.x).Average(),
// mphBuffer.Select(x=>x.y).Average(),
// mphBuffer.Select(x=>x.z).Average()
// );
// if (ShowMonitor)
// {
// Monitor.Log("MaxDistance", MaxDistanceTraveled.ToString());
// Monitor.Log("NormalizedPos", GetNormalizedPosition().ToString());
// Monitor.Log("MPH: ", (aveMph).ToString());
// }
// }
float NextGaussian(float mu = 0, float sigma = 1)
{
var u1 = UnityEngine.Random.value;
var u2 = UnityEngine.Random.value;
var rand_std_normal = Mathf.Sqrt(-2.0f * Mathf.Log(u1)) *
Mathf.Sin(2.0f * Mathf.PI * u2);
var rand_normal = mu + sigma * rand_std_normal;
return rand_normal;
}
public Vector3 GetNormalizedVelocity(Vector3 metersPerSecond)
{
var maxMetersPerSecond = _spawnableEnv.bounds.size
/ _agent.MaxStep
/ Time.fixedDeltaTime;
var maxXZ = Mathf.Max(maxMetersPerSecond.x, maxMetersPerSecond.z);
maxMetersPerSecond.x = maxXZ;
maxMetersPerSecond.z = maxXZ;
maxMetersPerSecond.y = 53; // override with
float x = metersPerSecond.x / maxMetersPerSecond.x;
float y = metersPerSecond.y / maxMetersPerSecond.y;
float z = metersPerSecond.z / maxMetersPerSecond.z;
// clamp result
x = Mathf.Clamp(x, -1f, 1f);
y = Mathf.Clamp(y, -1f, 1f);
z = Mathf.Clamp(z, -1f, 1f);
Vector3 normalizedVelocity = new Vector3(x,y,z);
return normalizedVelocity;
}
public Vector3 GetNormalizedPosition(Vector3 pos)
{
var maxPos = _spawnableEnv.bounds.size;
float x = pos.x / maxPos.x;
float y = pos.y / maxPos.y;
float z = pos.z / maxPos.z;
// clamp result
x = Mathf.Clamp(x, -1f, 1f);
y = Mathf.Clamp(y, -1f, 1f);
z = Mathf.Clamp(z, -1f, 1f);
Vector3 normalizedPos = new Vector3(x,y,z);
return normalizedPos;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 776799f55314f4500bc35f859c94e2fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,239 @@
// A class that describes a body part of an Agent or an Animator. The object
// stores the rigid body associated with an Agent's body part. Along with some
// important data like root bone, i. e. 'butt' for a marathonMan. Implments methods
// to calculate distance to the characteristics of an animation being mimiced.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Unity.MLAgents;
[System.Serializable]
public class BodyPart002
{
public string Name;
public BodyHelper002.BodyPartGroup Group;
public Vector3 ObsLocalPosition;
public Quaternion ObsRotation;
public Quaternion ObsRotationFromBase;
public Vector3 ObsRotationVelocity;
public Vector3 ObsVelocity;
public float ObsAngleDeltaFromAnimationRotation;
public Vector3 ObsDeltaFromAnimationPosition;
public Vector3 ObsDeltaFromAnimationVelocity;
public Vector3 ObsDeltaFromAnimationAngularVelocity;
public Vector3 ObsDeltaFromAnimationAngularVelocityWorld;
public Vector3 DebugMaxRotationVelocity;
public Vector3 DebugMaxVelocity;
public Quaternion DefaultLocalRotation;
public Quaternion ToJointSpaceInverse;
public Quaternion ToJointSpaceDefault;
public Rigidbody Rigidbody;
public Transform Transform;
public BodyPart002 Root;
public Quaternion InitialRootRotation;
public Vector3 InitialRootPosition;
// base = from where to measure rotation and position from
public Quaternion BaseRotation;
public Vector3 BasePosition;
//
public Quaternion ToFocalRoation;
Quaternion _lastObsRotation;
Quaternion _lastWorldRotation;
Vector3 _lastLocalPosition;
Vector3 _lastWorldPosition;
Vector3 _animationAngularVelocity;
Vector3 _animationAngularVelocityWorld;
Vector3 _animationVelocityWorld;
DecisionRequester _decisionRequester;
float _lastUpdateObsTime;
bool _firstRunComplete;
bool _hasRanVeryFirstInit;
private Vector3 _animationPositionWorld;
private Quaternion _animationRotation;
static Vector3 Vector3Max (Vector3 a, Vector3 b)
{
var answer = new Vector3(
Mathf.Max(Mathf.Abs(a.x), Mathf.Abs(b.x)),
Mathf.Max(Mathf.Abs(a.y), Mathf.Abs(b.y)),
Mathf.Max(Mathf.Abs(a.z), Mathf.Abs(b.z)));
return answer;
}
// Initialize
public void Init()
{
_decisionRequester = GameObject.Find("MarathonMan").GetComponent<DecisionRequester>();
_firstRunComplete = false;
if (Rigidbody != null){
Rigidbody.angularVelocity = Vector3.zero;
Rigidbody.velocity = Vector3.zero;
}
if (!_hasRanVeryFirstInit) {
InitialRootRotation = Root.Transform.transform.rotation;
InitialRootPosition = Root.Transform.transform.position;
BaseRotation = Root.Transform.transform.rotation;
BasePosition = Root.Transform.transform.position;
DefaultLocalRotation = LocalRotation;
Vector3 forward = this.Transform.forward;
Vector3 up = this.Transform.up;
Quaternion toJointSpace = Quaternion.LookRotation(forward, up);
ToJointSpaceInverse = Quaternion.Inverse(toJointSpace);
ToJointSpaceDefault = DefaultLocalRotation * toJointSpace;
// set body part direction
Vector3 focalOffset = new Vector3(10,0,0);
if (Rigidbody != null){
var focalPoint = Rigidbody.position + focalOffset;
ToFocalRoation = Rigidbody.rotation;
ToFocalRoation.SetLookRotation(focalPoint - Rigidbody.position);
}
_hasRanVeryFirstInit = true;
}
}
// Update values like ObsLocalPosition, ObsRotation, ... that will be accessed
// by the agent as observations for the neural network. Also calculates distances
// to an animation being mimicked
public void UpdateObservations()
{
Quaternion rotation;
Vector3 position;
if (this == Root) {
rotation = Quaternion.Inverse(InitialRootRotation) * Transform.rotation;
position = Transform.position - InitialRootPosition;
}
else {
rotation = Quaternion.Inverse(Root.Transform.rotation) * Transform.rotation;
position = Transform.position - Root.Transform.position;
}
if (_firstRunComplete == false){
_lastUpdateObsTime = Time.time;
_lastLocalPosition = position;
_lastWorldPosition = Transform.position;
_lastObsRotation = rotation;
_lastWorldRotation = Transform.rotation;
}
var dt = Time.fixedDeltaTime * _decisionRequester.DecisionPeriod;
var velocity = (position - _lastLocalPosition)/dt;
var velocityWorld = (Transform.position - _lastWorldPosition)/dt;
var angularVelocity = JointHelper002.CalcDeltaRotationNormalizedEuler(_lastObsRotation, rotation)/dt;
var angularVelocityWorld = JointHelper002.CalcDeltaRotationNormalizedEuler(_lastWorldRotation, Transform.rotation)/dt;
// old calulation for observation vector
//angularVelocity = NormalizedEulerAngles(rotationVelocity.eulerAngles);
//angularVelocity /= 128f;
// old calculation end
_lastUpdateObsTime = Time.time;
_lastLocalPosition = position;
_lastWorldPosition = Transform.position;
_lastObsRotation = rotation;
_lastWorldRotation = Transform.rotation;
//if (Name == "right_right_foot") {
// Debug.Log("^^^^^^^^^^^^");
// Debug.Log("body part name: " + Name);
// Debug.Log("animation angular velocity:" + _animationAngularVelocity);
// Debug.Log("angular velocity:" + angularVelocity);
// Debug.Log("animation angular velocity world:" + _animationAngularVelocityWorld);
// Debug.Log("angular velocity world:" + angularVelocityWorld);
// Debug.Log("rotation local:" + rotation.eulerAngles);
// Debug.Log("animation rotation local: " + _animationRotation.eulerAngles);
// Debug.Log("velocity world: " + velocityWorld);
// Debug.Log("animation velocity world:" + _animationVelocityWorld);
// Debug.Log("transform position:" + Transform.position);
// Debug.Log("animation position world: " + _animationPositionWorld);
// Debug.Log("dt:" + dt);
//}
ObsLocalPosition = position;
ObsRotation = rotation;
ObsRotationVelocity = angularVelocity;
ObsVelocity = velocity;
ObsDeltaFromAnimationPosition = _animationPositionWorld - Transform.position;
ObsAngleDeltaFromAnimationRotation = Quaternion.Angle(_animationRotation, rotation);
ObsAngleDeltaFromAnimationRotation = JointHelper002.NormalizedAngle(ObsAngleDeltaFromAnimationRotation);
ObsDeltaFromAnimationVelocity = _animationVelocityWorld - velocityWorld;
ObsDeltaFromAnimationAngularVelocity = (_animationAngularVelocity - angularVelocity);
ObsDeltaFromAnimationAngularVelocityWorld = (_animationAngularVelocityWorld - angularVelocityWorld);
DebugMaxRotationVelocity = Vector3Max(DebugMaxRotationVelocity, angularVelocity);
DebugMaxVelocity = Vector3Max(DebugMaxVelocity, velocity);
_firstRunComplete = true;
}
// returns local rotation
public Quaternion LocalRotation {
get {
return Quaternion.Inverse(RootRotation) * Transform.rotation;
}
}
// retuns root rotation
public Quaternion RootRotation{
get {
return InitialRootRotation;
}
}
// Set the position, rotation of a body part to match animation's position and
// rotation. Also sets the rigid body's position and velocity, which is used
// in angular momentum calculation
public void MoveToAnim(Vector3 animPosition, Quaternion animRotation, Vector3 angularVelocity, Vector3 velocity)
{
Transform.position = animPosition;
Transform.rotation = animRotation;
if (Rigidbody != null){
foreach (var childRb in Rigidbody.GetComponentsInChildren<Rigidbody>())
{
if (childRb == Rigidbody)
continue;
childRb.transform.localPosition = Vector3.zero;
childRb.transform.localEulerAngles = Vector3.zero;
childRb.angularVelocity = Vector3.zero;
childRb.velocity = Vector3.zero;
}
Rigidbody.angularVelocity = angularVelocity;
Rigidbody.velocity = velocity;
}
}
// Set the position of the animation being mimicked
public void SetAnimationPosition(Vector3 animPositionWorld, Quaternion animRotationLocal, Vector3 animVelocityWorld, Vector3 animAngularVelocityLocal, Vector3 animAngularVelocityWorld)
{
_animationPositionWorld = animPositionWorld;
_animationRotation = animRotationLocal;
_animationVelocityWorld = animVelocityWorld;
_animationAngularVelocity = animAngularVelocityLocal;
_animationAngularVelocityWorld = animAngularVelocityWorld;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d6e9d3ad85936e6459222f0017b88b80
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using Unity.MLAgents;
using UnityEngine;
public class DomainRandomization : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e04e2081c5c5647a9993dcdc05765cd0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,107 @@
// Helper Utilities to work with agent's rigid bodies charateristics. Allows to
// calculate Angles between rotations in radians, find center of mass of an agent,
// and find Angular Momentum of an agent.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System;
public static class JointHelper002 {
// Return rotation from one rotation to another
public static Quaternion FromToRotation(Quaternion from, Quaternion to) {
if (to == from) return Quaternion.identity;
return to * Quaternion.Inverse(from);
}
// Calculate rotation between two rotations in radians. Adjusts the value to lie within [-pi, +pi].
public static Vector3 NormalizedEulerAngles(Vector3 eulerAngles) {
var x = eulerAngles.x < 180f ?
eulerAngles.x :
-360 + eulerAngles.x;
var y = eulerAngles.y < 180f ?
eulerAngles.y :
-360 + eulerAngles.y;
var z = eulerAngles.z < 180f ?
eulerAngles.z :
-360 + eulerAngles.z;
x = x * Mathf.Deg2Rad;
y = y * Mathf.Deg2Rad;
z = z * Mathf.Deg2Rad;
return new Vector3(x, y, z);
}
// Adjust the value of an angle to lie within [-pi, +pi].
public static float NormalizedAngle(float angle) {
if (angle < 180) {
return angle * Mathf.Deg2Rad;
}
return (angle - 360) * Mathf.Deg2Rad;
}
// Find rotation and convert to radians within [-pi, +pi].
public static Vector3 CalcDeltaRotationNormalizedEuler(Quaternion from, Quaternion to) {
var rotationVelocity = FromToRotation(from, to);
var angularVelocity = NormalizedEulerAngles(rotationVelocity.eulerAngles);
return angularVelocity;
}
// Find the center of mass of a list of Body Parts beloning to an agent. Relative to the root bone, i. e. "butt" for humanoid.
public static Vector3 GetCenterOfMassRelativeToRoot(List<BodyPart002> BodyParts) {
var centerOfMass = Vector3.zero;
float totalMass = 0f;
var bodies = BodyParts
.Select(x => x.Rigidbody)
.Where(x => x != null)
.ToList();
var rootBone = BodyParts[0];
foreach (Rigidbody rb in bodies) {
centerOfMass += rb.worldCenterOfMass * rb.mass;
totalMass += rb.mass;
}
centerOfMass /= totalMass;
centerOfMass -= rootBone.InitialRootPosition;
return centerOfMass;
}
// Find the center of mass of a List of Body Parts relative to the world coordinate system.
public static Vector3 GetCenterOfMassWorld(List<BodyPart002> BodyParts) {
var centerOfMass = GetCenterOfMassRelativeToRoot(BodyParts) + BodyParts[0].InitialRootPosition;
return centerOfMass;
}
// Calculate Angular Momentum of a List of Body Parts. In the world coordinate system about the center
// of mass of the Body Parts. Formulas at https://ocw.mit.edu/courses/aeronautics-and-astronautics/16-07-dynamics-fall-2009/lecture-notes/MIT16_07F09_Lec11.pdf
public static Vector3 GetAngularMoment(List<BodyPart002> BodyParts) {
var centerOfMass = GetCenterOfMassWorld(BodyParts);
var bodies = BodyParts
.Select(x => x.Rigidbody)
.Where(x => x != null)
.ToList();
Vector3 totalAngularMoment = Vector3.zero;
foreach (Rigidbody rb in bodies) {
var w_local = rb.transform.rotation * rb.angularVelocity;
var w_inertiaFrame = rb.inertiaTensorRotation * w_local;
Vector3 L_inertiaFrame = Vector3.zero;
L_inertiaFrame[0] = w_inertiaFrame[0] * rb.inertiaTensor[0];
L_inertiaFrame[1] = w_inertiaFrame[1] * rb.inertiaTensor[1];
L_inertiaFrame[2] = w_inertiaFrame[2] * rb.inertiaTensor[2];
Vector3 L_world = Quaternion.Inverse(rb.transform.rotation) * Quaternion.Inverse(rb.inertiaTensorRotation) * L_inertiaFrame;
Vector3 bodyPartCenterOfMassRelativeTobodyPartsCenterOfMass = rb.worldCenterOfMass - centerOfMass;
Vector3 LofBodyPartCenterOfMass = rb.mass * Vector3.Cross(bodyPartCenterOfMassRelativeTobodyPartsCenterOfMass, rb.velocity);
totalAngularMoment += L_world + LofBodyPartCenterOfMass;
}
return totalAngularMoment;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 168784be71eb147fd92601f19593c1b3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,195 @@
using System.Linq;
using UnityEngine;
namespace Unity.MLAgents
{
public static class MarathonHelper
{
static readonly bool FlipMarathonX = false;
public static Vector3 RightToLeft(Vector3 rightHanded, bool hackFlipZ = false)
{
if (FlipMarathonX)
return new Vector3(rightHanded.x, rightHanded.z,
rightHanded.y); // use if fliping marathon's X direction
return new Vector3(-rightHanded.x, rightHanded.z, -rightHanded.y); // use to maintain marathon's X direction
}
static char[] _delimiterChars = {' ', ',', ':', '\t'};
static string RemoveDuplicateWhitespace(string input)
{
while (input.Contains(" "))
input = input.Replace(" ", " ");
while (input.Contains("\t\t"))
input = input.Replace("\t\t", "\t");
return input;
}
static float Evaluate(string expression)
{
var doc = new System.Xml.XPath.XPathDocument(new System.IO.StringReader("<r/>"));
var nav = doc.CreateNavigator();
var newString = expression;
newString = (new System.Text.RegularExpressions.Regex(@"([\+\-\*])")).Replace(newString, " ${1} ");
newString = newString.Replace("/", " div ").Replace("%", " mod ");
var res = nav.Evaluate("number(" + newString + ")");
double d = (double) res;
return (float) d;
}
static public Vector3 ParseVector3NoFlipYZ(string str)
{
str = RemoveDuplicateWhitespace(str);
string[] words = str.Split(_delimiterChars);
float x = Evaluate(words[0]);
float y = Evaluate(words[1]);
float z = Evaluate(words[2]);
var vec3 = new Vector3(x, y, z);
return vec3;
}
static public Quaternion ParseQuaternion(string str)
{
str = RemoveDuplicateWhitespace(str);
string[] words = str.Split(_delimiterChars);
float w = Evaluate(words[0]);
float x = Evaluate(words[1]);
float y = Evaluate(words[2]);
float z = Evaluate(words[3]);
var q = new Quaternion(x, y, z, w);
return q;
}
static public Vector3 ParseAxis(string str)
{
var axis = MarathonHelper.ParseVector3NoFlipYZ(str);
if (FlipMarathonX)
axis = new Vector3(-axis.x, -axis.z, -axis.y); // use if fliping marathon's X direction
else
axis = new Vector3(axis.x, -axis.z, axis.y); // use to maintain marathon's X direction
return axis;
}
static public Vector3 JointParsePosition(string str, bool hackFlipZ)
{
str = RemoveDuplicateWhitespace(str);
string[] words = str.Split(_delimiterChars);
float x = Evaluate(words[0]);
float y = Evaluate(words[1]);
float z = Evaluate(words[2]);
Vector3 vec3 = new Vector3(x, y, z);
return RightToLeft(vec3, hackFlipZ);
}
public static Vector3 ParsePosition(string str)
{
str = RemoveDuplicateWhitespace(str);
string[] words = str.Split(_delimiterChars);
float x = Evaluate(words[0]);
float y = Evaluate(words[1]);
float z = Evaluate(words[2]);
Vector3 vec3 = new Vector3(x, y, z);
return RightToLeft(vec3);
}
public static Vector3 ParseFrom(string fromTo)
{
return ParseVector3NoFlipYZ(fromTo);
}
public static Vector3 ParseTo(string fromTo)
{
fromTo = RemoveDuplicateWhitespace(fromTo);
string[] words = fromTo.Split(_delimiterChars);
float x = Evaluate(words[3]);
float y = Evaluate(words[4]);
float z = Evaluate(words[5]);
Vector3 vec3 = new Vector3(x, y, z);
return vec3;
}
public static Vector2 ParseVector2(string str)
{
str = RemoveDuplicateWhitespace(str);
string[] words = str.Split(_delimiterChars);
float x = Evaluate(words[0]);
float y = Evaluate(words[1]);
var vec2 = new Vector2(x, y);
return vec2;
}
public static float ParseGetMin(string rangeAsText)
{
rangeAsText = RemoveDuplicateWhitespace(rangeAsText);
string[] words = rangeAsText.Split(_delimiterChars);
var range = words.Select(x => Evaluate(x));
return range.Min();
}
public static float ParseGetMax(string rangeAsText)
{
rangeAsText = RemoveDuplicateWhitespace(rangeAsText);
string[] words = rangeAsText.Split(_delimiterChars);
var range = words.Select(x => Evaluate(x));
return range.Max();
}
public static GameObject CreateBetweenPoints(this GameObject parent, Vector3 start, Vector3 end, float width,
bool useWorldSpace, GameObject root)
{
start = RightToLeft(start);
end = RightToLeft(end);
var instance = new GameObject();
var procCap = instance.AddComponent<ProceduralCapsule>();
var handleOverlap = instance.AddComponent<HandleOverlap>();
handleOverlap.Parent = root;
var collider = instance.AddComponent<CapsuleCollider>();
var offset = start - end;
var position = start - (offset / 2.0f);
var height = offset.magnitude;
collider.height = height + (width * 2) * .90f;
collider.radius = width * .90f;
procCap.height = height + (width);
procCap.radius = width;
procCap.CreateMesh();
instance.transform.parent = root.transform;
instance.transform.up = offset;
if (useWorldSpace)
{
instance.transform.position = position;
}
else
{
instance.transform.position = position + parent.transform.position;
instance.transform.rotation = instance.transform.rotation * parent.transform.rotation;
}
// UnityEngine.GameObject.Destroy(handleOverlap);
return instance;
}
public static GameObject CreateAtPoint(this GameObject parent, Vector3 position, float width,
bool useWorldSpace, GameObject root)
{
var scale = new Vector3(width, width, width);
var instance = GameObject.CreatePrimitive(PrimitiveType.Sphere);
instance.transform.parent = root.transform;
instance.transform.localScale = scale * 2;
if (useWorldSpace)
{
instance.transform.position = position;
}
else
{
instance.transform.position = position + parent.transform.position;
instance.transform.rotation = instance.transform.rotation * parent.transform.rotation;
}
return instance;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: badf427d082e546a0b2b91e0b251f39d
timeCreated: 1515352351
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using UnityEngine;
namespace Unity.MLAgents
{
[System.Serializable]
public class MarathonJoint
{
public Joint Joint;
public string Name;
public string JointName;
public Vector2 CtrlRange;
public bool? CtrlLimited;
public float? Gear;
public ConfigurableJoint TrueBase;
public Transform TrueTarget;
public float MaximumForce;
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 7e8c7f9aa73bc4a34bb844acd8d4dc68
timeCreated: 1515741765
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using UnityEngine;
namespace Unity.MLAgents
{
[System.Serializable]
public class MarathonSensor
{
public Collider SiteObject;
public string Name;
public string SiteName;
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: c363fa98af67a4ed8b4ce15b4baefc8d
timeCreated: 1520405313
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: a532e373957504411bd01901bf361ad3
timeCreated: 1515299486
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MarathonSupport : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3232628ca9c44e83973a20a6814ed33
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,206 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
[System.Serializable]
public class Muscle002
{
public string Name;
public BodyHelper002.MuscleGroup Group;
[Range(-1,1)]
public float TargetNormalizedRotationX;
[Range(-1,1)]
public float TargetNormalizedRotationY;
[Range(-1,1)]
public float TargetNormalizedRotationZ;
public Vector3 MaximumForce;
public Vector3 ObsLocalPosition;
public Quaternion ObsRotation;
public Vector3 ObsNormalizedRotation;
public Vector3 ObsNormalizedDeltaFromTargetRotation;
public Vector3 ObsRotationVelocity;
public Vector3 ObsVelocity;
public Vector3 DebugMaxRotationVelocity;
public Vector3 DebugMaxVelocity;
public Quaternion DefaultLocalRotation;
public Quaternion ToJointSpaceInverse;
public Quaternion ToJointSpaceDefault;
public Rigidbody Rigidbody;
public Transform Transform;
public ConfigurableJoint ConfigurableJoint;
public Rigidbody Parent;
public ConfigurableJoint RootConfigurableJoint;
public Quaternion InitialRootRotation;
public Vector3 InitialRootPosition;
Quaternion _lastObsRotation;
Vector3 _lastLocalPosition;
float _lastUpdateObsTime;
bool _firstRunComplete;
bool _hasRanVeryFirstInit;
public void UpdateMotor()
{
float powerMultiplier = 2.5f;
var t = ConfigurableJoint.targetAngularVelocity;
t.x = TargetNormalizedRotationX * MaximumForce.x;
t.y = TargetNormalizedRotationY * MaximumForce.y;
t.z = TargetNormalizedRotationZ * MaximumForce.z;
ConfigurableJoint.targetAngularVelocity = t;
var angX = ConfigurableJoint.angularXDrive;
angX.positionSpring = 1f;
var scale = MaximumForce.x * Mathf.Pow(Mathf.Abs(TargetNormalizedRotationX), 3);
angX.positionDamper = Mathf.Max(1f, scale);
angX.maximumForce = Mathf.Max(1f, MaximumForce.x * powerMultiplier);
ConfigurableJoint.angularXDrive = angX;
var maxForce = Mathf.Max(MaximumForce.y, MaximumForce.z);
var angYZ = ConfigurableJoint.angularYZDrive;
angYZ.positionSpring = 1f;
var maxAbsRotXY = Mathf.Max(Mathf.Abs(TargetNormalizedRotationY) + Mathf.Abs(TargetNormalizedRotationZ));
scale = maxForce * Mathf.Pow(maxAbsRotXY, 3);
angYZ.positionDamper = Mathf.Max(1f, scale);
angYZ.maximumForce = Mathf.Max(1f, maxForce * powerMultiplier);
ConfigurableJoint.angularYZDrive = angYZ;
}
static Vector3 NormalizedEulerAngles(Vector3 eulerAngles)
{
var x = eulerAngles.x < 180f ?
eulerAngles.x :
- 360 + eulerAngles.x;
var y = eulerAngles.y < 180f ?
eulerAngles.y :
- 360 + eulerAngles.y;
var z = eulerAngles.z < 180f ?
eulerAngles.z :
- 360 + eulerAngles.z;
x = x / 180f;
y = y / 180f;
z = z / 180f;
return new Vector3(x,y,z);
}
static Vector3 ScaleNormalizedByJoint(Vector3 normalizedRotation, ConfigurableJoint configurableJoint)
{
var x = normalizedRotation.x > 0f ?
(normalizedRotation.x * 180f) / configurableJoint.highAngularXLimit.limit :
(-normalizedRotation.x * 180f) / configurableJoint.lowAngularXLimit.limit;
var y = (normalizedRotation.y * 180f) / configurableJoint.angularYLimit.limit;
var z = (normalizedRotation.z * 180f) / configurableJoint.angularZLimit.limit;
var scaledNormalizedRotation = new Vector3(x,y,z);
return scaledNormalizedRotation;
}
static Vector3 Vector3Max (Vector3 a, Vector3 b)
{
var answer = new Vector3(
Mathf.Max(Mathf.Abs(a.x), Mathf.Abs(b.x)),
Mathf.Max(Mathf.Abs(a.y), Mathf.Abs(b.y)),
Mathf.Max(Mathf.Abs(a.z), Mathf.Abs(b.z)));
return answer;
}
public void Init()
{
_firstRunComplete = false;
Rigidbody.angularVelocity = Vector3.zero;
Rigidbody.velocity = Vector3.zero;
if (!_hasRanVeryFirstInit) {
Parent = ConfigurableJoint.connectedBody;
InitialRootRotation = RootConfigurableJoint.transform.rotation;
InitialRootPosition = RootConfigurableJoint.transform.position;
DefaultLocalRotation = LocalRotation;
// Vector3 forward = Vector3.Cross (ConfigurableJoint.axis, ConfigurableJoint.secondaryAxis).normalized;
//Vector3 up = Vector3.Cross (forward, ConfigurableJoint.axis).normalized;
Vector3 forward = this.Transform.forward;
Vector3 up = this.Transform.forward;
Quaternion toJointSpace = Quaternion.LookRotation(forward, up);
ToJointSpaceInverse = Quaternion.Inverse(toJointSpace);
ToJointSpaceDefault = DefaultLocalRotation * toJointSpace;
_hasRanVeryFirstInit = true;
}
}
public void UpdateObservations()
{
ObsRotation = this.LocalRotation;
ObsRotation = (ToJointSpaceInverse * UnityEngine.Quaternion.Inverse(this.LocalRotation) * this.ToJointSpaceDefault);
var r2 = (ToJointSpaceInverse * UnityEngine.Quaternion.Inverse(this.Transform.rotation) * this.ToJointSpaceDefault);
var s1 = ScaleNormalizedByJoint(NormalizedEulerAngles((this.LocalRotation * ToJointSpaceDefault).eulerAngles), ConfigurableJoint);
var s2 = ScaleNormalizedByJoint(NormalizedEulerAngles((Transform.localRotation * ToJointSpaceDefault).eulerAngles), ConfigurableJoint);
var s3 = ScaleNormalizedByJoint(NormalizedEulerAngles((this.LocalRotation * ToJointSpaceInverse).eulerAngles), ConfigurableJoint);
var s4 = ScaleNormalizedByJoint(NormalizedEulerAngles((Transform.localRotation * ToJointSpaceInverse).eulerAngles), ConfigurableJoint);
var s5 = ScaleNormalizedByJoint(NormalizedEulerAngles((UnityEngine.Quaternion.Inverse(this.LocalRotation) * ToJointSpaceDefault).eulerAngles), ConfigurableJoint);
var normalizedRotation = NormalizedEulerAngles(ObsRotation.eulerAngles);
// var normalizedRotation = NormalizedEulerAngles(this.LocalRotation.eulerAngles);
ObsNormalizedRotation = ScaleNormalizedByJoint(normalizedRotation, ConfigurableJoint);
ObsNormalizedDeltaFromTargetRotation =
new Vector3(TargetNormalizedRotationX, TargetNormalizedRotationY, TargetNormalizedRotationZ) - ObsNormalizedRotation;
// Debug code
// if (Group == BodyHelper002.MuscleGroup.Head){
// var debug = 1;
// }
if (_firstRunComplete == false){
_lastUpdateObsTime = Time.time;
_lastObsRotation = ObsRotation;
_lastLocalPosition = Transform.localPosition;
}
var dt = Time.time - _lastUpdateObsTime;
_lastUpdateObsTime = Time.time;
var rotationVelocity = ObsRotation.eulerAngles - _lastObsRotation.eulerAngles;
rotationVelocity = NormalizedEulerAngles(rotationVelocity);
rotationVelocity /= 128f;
if (dt > 0f)
rotationVelocity /= dt;
ObsRotationVelocity = rotationVelocity;
_lastObsRotation = ObsRotation;
var rootBone = RootConfigurableJoint.transform;
var toRootSpace = Quaternion.Inverse(RootConfigurableJoint.transform.rotation) * rootBone.rotation;
Quaternion rootRotation = Quaternion.Inverse(rootBone.rotation * toRootSpace) * Transform.rotation;
ObsLocalPosition = Transform.position - RootConfigurableJoint.transform.position;
var velocity = ObsLocalPosition - _lastLocalPosition;
ObsVelocity = velocity;
if (dt > 0f)
velocity /= dt;
_lastLocalPosition = ObsLocalPosition;
DebugMaxRotationVelocity = Vector3Max(DebugMaxRotationVelocity, rotationVelocity);
DebugMaxVelocity = Vector3Max(DebugMaxVelocity, velocity);
_firstRunComplete = true;
}
public Quaternion LocalRotation {
get {
// around root Rotation
return Quaternion.Inverse(RootRotation) * Transform.rotation;
// around parent space
// return Quaternion.Inverse(ParentRotation) * transform.rotation;
}
}
public Quaternion RootRotation {
get {
return InitialRootRotation;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c1a3e067c0e5a43b79cb9649ee706f12
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,158 @@
//------------------------------//
// ProceduralCapsule.cs //
// Written by Jay Kay //
// 2016/05/27 //
//------------------------------//
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class ProceduralCapsule : MonoBehaviour
{
#if UNITY_EDITOR
[ContextMenu("Generate Procedural Capsule")]
public void GenerateProceduralCapsule()
{
// GenerateMesh();
}
#endif
public float height = 2f;
public float radius = 0.5f;
public int segments = 24;
// void GenerateMesh()
void Start()
{
}
public void CreateMesh()
{
// make segments an even number
if (segments % 2 != 0)
segments++;
// extra vertex on the seam
int points = segments + 1;
// calculate points around a circle
float[] pX = new float[points];
float[] pZ = new float[points];
float[] pY = new float[points];
float[] pR = new float[points];
float calcH = 0f;
float calcV = 0f;
for (int i = 0; i < points; i++)
{
pX[i] = Mathf.Sin(calcH * Mathf.Deg2Rad);
pZ[i] = Mathf.Cos(calcH * Mathf.Deg2Rad);
pY[i] = Mathf.Cos(calcV * Mathf.Deg2Rad);
pR[i] = Mathf.Sin(calcV * Mathf.Deg2Rad);
calcH += 360f / (float) segments;
calcV += 180f / (float) segments;
}
// - Vertices and UVs -
Vector3[] vertices = new Vector3[points * (points + 1)];
Vector2[] uvs = new Vector2[vertices.Length];
int ind = 0;
// Y-offset is half the height minus the diameter
// float yOff = ( height - ( radius * 2f ) ) * 0.5f;
float yOff = (height - (radius)) * 0.5f;
if (yOff < 0)
yOff = 0;
// uv calculations
float stepX = 1f / ((float) (points - 1));
float uvX, uvY;
// Top Hemisphere
int top = Mathf.CeilToInt((float) points * 0.5f);
for (int y = 0; y < top; y++)
{
for (int x = 0; x < points; x++)
{
vertices[ind] = new Vector3(pX[x] * pR[y], pY[y], pZ[x] * pR[y]) * radius;
vertices[ind].y = yOff + vertices[ind].y;
uvX = 1f - (stepX * (float) x);
uvY = (vertices[ind].y + (height * 0.5f)) / height;
uvs[ind] = new Vector2(uvX, uvY);
ind++;
}
}
// Bottom Hemisphere
int btm = Mathf.FloorToInt((float) points * 0.5f);
for (int y = btm; y < points; y++)
{
for (int x = 0; x < points; x++)
{
vertices[ind] = new Vector3(pX[x] * pR[y], pY[y], pZ[x] * pR[y]) * radius;
vertices[ind].y = -yOff + vertices[ind].y;
uvX = 1f - (stepX * (float) x);
uvY = (vertices[ind].y + (height * 0.5f)) / height;
uvs[ind] = new Vector2(uvX, uvY);
ind++;
}
}
// - Triangles -
int[] triangles = new int[(segments * (segments + 1) * 2 * 3)];
for (int y = 0, t = 0; y < segments + 1; y++)
{
for (int x = 0; x < segments; x++, t += 6)
{
triangles[t + 0] = ((y + 0) * (segments + 1)) + x + 0;
triangles[t + 1] = ((y + 1) * (segments + 1)) + x + 0;
triangles[t + 2] = ((y + 1) * (segments + 1)) + x + 1;
triangles[t + 3] = ((y + 0) * (segments + 1)) + x + 1;
triangles[t + 4] = ((y + 0) * (segments + 1)) + x + 0;
triangles[t + 5] = ((y + 1) * (segments + 1)) + x + 1;
}
}
// - Assign Mesh -
MeshFilter mf = gameObject.GetComponent<MeshFilter>();
Mesh mesh = mf.sharedMesh;
if (!mesh)
{
mesh = new Mesh();
mf.sharedMesh = mesh;
}
mesh.Clear();
mesh.name = "ProceduralCapsule";
mesh.vertices = vertices;
mesh.uv = uvs;
mesh.triangles = triangles;
mesh.RecalculateBounds();
mesh.RecalculateNormals();
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 4d940240a49514996a7c1face83becce
timeCreated: 1515310310
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class RagDoll002 : MonoBehaviour {
[System.Serializable]
public class MusclePower
{
public string Muscle;
public Vector3 PowerVector;
}
public List<MusclePower> MusclePowers;
public float MotorScale = 1f;
// Use this for initialization
void Start () {
Setup();
}
// Update is called once per frame
void Update () {
}
void Setup () {
// handle collision overlaps
IgnoreCollision("torso", new []{"left_upper_arm", "right_upper_arm"});
IgnoreCollision("butt", new []{"left_thigh", "right_thigh"});
IgnoreCollision("left_larm", new []{"left_upper_arm"});
IgnoreCollision("right_larm", new []{"right_upper_arm"});
IgnoreCollision("left_shin", new []{"left_thigh"});
IgnoreCollision("right_shin", new []{"right_thigh"});
IgnoreCollision("right_shin", new []{"right_right_foot"});
IgnoreCollision("left_shin", new []{"left_left_foot"});
//
var joints = GetComponentsInChildren<Joint>().ToList();
foreach (var joint in joints)
joint.enablePreprocessing = false;
}
void IgnoreCollision(string first, string[] seconds)
{
foreach (var second in seconds)
{
IgnoreCollision(first, second);
}
}
void IgnoreCollision(string first, string second)
{
var rigidbodies = GetComponentsInChildren<Rigidbody>().ToList();
var colliderOnes = rigidbodies.FirstOrDefault(x=>x.name.Contains(first))?.GetComponents<Collider>();
var colliderTwos = rigidbodies.FirstOrDefault(x=>x.name.Contains(second))?.GetComponents<Collider>();
if (colliderOnes == null || colliderTwos == null)
return;
foreach (var c1 in colliderOnes)
foreach (var c2 in colliderTwos)
Physics.IgnoreCollision(c1, c2);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e788eb6109bb04aa1bd822f9fc98f4bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class ScoreHistogramData
{
int _columnCount;
int _historyDepth;
public List<List<double>> Items;
public ScoreHistogramData (int columnCount, int historyDepth)
{
_columnCount = columnCount;
_historyDepth = historyDepth;
ReCreateScoreHistogramData();
}
public void ReCreateScoreHistogramData ()
{
Items = new List<List<double>>();
for (int i = 0; i < _columnCount; i++)
{
// var item = Enumerable.Range(0,_historyDepth).Select(x=>default(T)).ToList();
var item = new List<double>();
Items.Add(item);
}
}
public void SetItem(int column, double value)
{
Items[column].Add(value);
if (Items[column].Count > _historyDepth)
Items[column].RemoveAt(0);
}
public double GetAverage(int column)
{
double average = Items[column].Average();
return average;
}
public List<double> GetAverages()
{
List<double> averages = Items.Select(x=>x.Count > 0 ? x.Average() : 0).ToList();
return averages;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5026d714f0bd4ce6bed38f75bd48588
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.MLAgents;
using UnityEngine;
using ManyWorlds;
public class Scorer : MonoBehaviour
{
public int TotalEpisodesToScore = 100;
public int EpisodesScored;
public float AverageScore;
public float StdDiv;
public string ScoreInfo;
public List<float> scores;
public List<string> scoreInfos;
[TextArea]
public string ScoreReport;
// Start is called before the first frame update
void Start()
{
scores = new List<float>(TotalEpisodesToScore);
scoreInfos = new List<string>(TotalEpisodesToScore);
}
// Update is called once per frame
void Update()
{
}
public void ReportScore(float score, string scoreInfo)
{
if (EpisodesScored >= TotalEpisodesToScore)
return;
scores.Add(score);
scoreInfos.Add(scoreInfo);
ScoreInfo = scoreInfo;
EpisodesScored = scores.Count;
AverageScore = scores.Average();
var sum = scores.Sum(d => (d - AverageScore) * (d - AverageScore));
StdDiv = Mathf.Sqrt(sum / EpisodesScored);
string name = string.Empty;
var spawnEnv = FindObjectOfType<SpawnableEnv>();
if (spawnEnv != null)
name = $"{spawnEnv.gameObject.name} ";
ScoreReport = $"{name}AveScore:{AverageScore}, StdDiv:{StdDiv} over {EpisodesScored} episodes using {scoreInfo}";
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 92cb079fa72494f018e7d3ebcc3851c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
using UnityEngine;
namespace Unity.MLAgents
{
public class SendOnCollisionTrigger : MonoBehaviour
{
void OnCollisionEnter(Collision other)
{
// Messenger.
var otherGameobject = other.gameObject;
var marathonAgent = otherGameobject.GetComponentInParent<MarathonAgent>();
if (marathonAgent != null)
marathonAgent.OnTerrainCollision(otherGameobject, this.gameObject);
var iOnTerrainCollision = otherGameobject.GetComponentInParent<IOnTerrainCollision>();
if (iOnTerrainCollision != null)
iOnTerrainCollision.OnTerrainCollision(otherGameobject, this.gameObject);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68231b96042614ce992397230a3bb5fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TerrainSetup : MonoBehaviour
{
public Vector3 TerrainSize;
// Start is called before the first frame update
void Start()
{
var terrain = GetComponent<Terrain>();
terrain.terrainData.size = TerrainSize;
}
// Update is called once per frame
void Update()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35dfb25d03f7744bc924a3a045e3c639
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: