Add config drive controller. Single agent for both recording and training.

This commit is contained in:
Miguel Alonso Jr 2023-02-06 15:26:12 -05:00
Родитель bfebf91b35
Коммит 6e5fb6577e
32 изменённых файлов: 12878 добавлений и 10580 удалений

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 24e83aea37bed45529b03860c4d72ffd
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: d10d7ee1f589242e2960bf2658bdec93
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 5d27792c403d74622b43b77e59f53dc5
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 7d4484eee5cd8444cb3f7a6f5c4654f2
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: d62b3558b65b1472598c4561ea30afc1
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 79eba9672f24c473c859d9f6e1ab7a58
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 1bbff1433082c4721a3c893450c4ecf9
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: c450a6a249cbc40daa9492d00b26f0a6
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 05ddcac22763744c8a1f346e14fa8455
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: 0693b5247cb7845e1b085c6db82958bb
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: e7cd07d9d1da34e6680d25aaf7915459
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Двоичный файл не отображается.

Просмотреть файл

@ -1,10 +0,0 @@
fileFormatVersion: 2
guid: f1be46dd9c3db4e25801d54ef693fde0
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData: ' (Unity.MLAgents.Demonstrations.DemonstrationSummary)'
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 7bd65ce151aaa4a41a45312543c56be1, type: 3}

Просмотреть файл

@ -236,7 +236,7 @@ ModelImporter:
value: {x: 0, y: 0, z: 0}
length: 0
modified: 0
- boneName: chest
- boneName: spine1
humanName: Chest
limit:
min: {x: 0, y: 0, z: 0}
@ -284,6 +284,14 @@ ModelImporter:
value: {x: 0, y: 0, z: 0}
length: 0
modified: 0
- boneName: chest
humanName: UpperChest
limit:
min: {x: 0, y: 0, z: 0}
max: {x: 0, y: 0, z: 0}
value: {x: 0, y: 0, z: 0}
length: 0
modified: 0
skeleton:
- name: Walker(Clone)
parentName:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 4ab79b31fae4b4f62aec86188b2c0d02
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,296 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using UnityEngine;
[Serializable]
public struct CJControlSettings
{
public string name;
public Vector3 target;
public Range3D range;
public Vector3 originalPosition;
public Quaternion originalRotation;
}
[Serializable]
public class Range3D
{
public Range xRange;
public Range yRange;
public Range zRange;
public Range3D(float xLow, float xHigh, float yLow, float yHigh, float zLow, float zHigh)
{
xRange = new Range(xLow, xHigh);
yRange = new Range(xLow, xHigh);
zRange = new Range(xLow, xHigh);
}
}
[Serializable]
public class Range
{
public float low;
public float high;
public Range(float low, float high)
{
this.low = low;
this.high = high;
}
public float Scale(float input)
{
var t = (1.0f + input) / 2.0f;
return Mathf.Round(Mathf.Lerp(low, high, t));
// if (input >= 0f)
// {
// return Mathf.RoundToInt(Mathf.Lerp(0f, m_High, input));
// }
// else
// {
// return Mathf.RoundToInt(Mathf.Lerp(m_Low, 0f, 1.0f + input));
// }
}
public float InverseScale(float input)
{
var t = Mathf.InverseLerp(low, high, input);
return 2.0f * t - 1.0f;
// if (input >= 0f)
// {
// return Mathf.InverseLerp(0f, m_High, input);
// }
// else
// {
// return Mathf.InverseLerp(m_Low, 0f, input) - 1.0f;
// }
}
}
public class ConfigurableJointController : MonoBehaviour
{
public float spring = 1000;
public float damping = 250;
public float forceLimit = 500;
public bool kinematicRoot;
public float totalMass;
[SerializeField]
public CJControlSettings[] cjControlSettings;
[Header("Body Parts")]
public Transform hips;
public Transform spine;
public Transform head;
public Transform thighL;
public Transform shinL;
public Transform footL;
public Transform thighR;
public Transform shinR;
public Transform footR;
public Transform armL;
public Transform forearmL;
public Transform handL;
public Transform armR;
public Transform forearmR;
public Transform handR;
ConfigurableJoint[] m_ConfigurableJointChain;
Rigidbody[] m_RigidbodyChain;
Agent m_Agent;
bool m_IsAgentNull;
Vector3 m_RootOriginalPosition;
Quaternion m_RootOriginalRotation;
// Start is called before the first frame update
void Start()
{
m_Agent = GetComponent<Agent>();
m_IsAgentNull = m_Agent == null;
PopulateParameters();
m_ConfigurableJointChain[0].GetComponent<Rigidbody>().isKinematic = kinematicRoot;
m_RootOriginalPosition = hips.position;
m_RootOriginalRotation = hips.rotation;
StartCoroutine(ResetCJointTargetsAndPositions());
}
// Update is called once per frame
void FixedUpdate()
{
if (m_IsAgentNull)
{
SetCJointTargets();
}
}
#if UNITY_EDITOR
void OnValidate()
{
PopulateParameters();
}
#endif
void PopulateParameters(bool force = false)
{
if (m_ConfigurableJointChain == null || m_ConfigurableJointChain.Length == 0 || force)
{
m_ConfigurableJointChain = new[]
{
hips.GetComponent<ConfigurableJoint>(),
spine.GetComponent<ConfigurableJoint>(),
head.GetComponent<ConfigurableJoint>(),
thighL.GetComponent<ConfigurableJoint>(),
shinL.GetComponent<ConfigurableJoint>(),
footL.GetComponent<ConfigurableJoint>(),
thighR.GetComponent<ConfigurableJoint>(),
shinR.GetComponent<ConfigurableJoint>(),
footR.GetComponent<ConfigurableJoint>(),
armL.GetComponent<ConfigurableJoint>(),
forearmL.GetComponent<ConfigurableJoint>(),
handL.GetComponent<ConfigurableJoint>(),
armR.GetComponent<ConfigurableJoint>(),
forearmR.GetComponent<ConfigurableJoint>(),
handR.GetComponent<ConfigurableJoint>(),
};
}
if (m_RigidbodyChain == null || m_RigidbodyChain.Length == 0 || force)
{
m_RigidbodyChain = new[]
{
hips.GetComponent<Rigidbody>(),
spine.GetComponent<Rigidbody>(),
head.GetComponent<Rigidbody>(),
thighL.GetComponent<Rigidbody>(),
shinL.GetComponent<Rigidbody>(),
footL.GetComponent<Rigidbody>(),
thighR.GetComponent<Rigidbody>(),
shinR.GetComponent<Rigidbody>(),
footR.GetComponent<Rigidbody>(),
armL.GetComponent<Rigidbody>(),
forearmL.GetComponent<Rigidbody>(),
handL.GetComponent<Rigidbody>(),
armR.GetComponent<Rigidbody>(),
forearmR.GetComponent<Rigidbody>(),
handR.GetComponent<Rigidbody>(),
};
}
if (cjControlSettings == null || cjControlSettings.Length == 0 || force)
{
cjControlSettings = new CJControlSettings[m_ConfigurableJointChain.Length - 1];
for (int i = 0; i < cjControlSettings.Length; i++)
{
cjControlSettings[i].name = m_ConfigurableJointChain[i + 1].name;
cjControlSettings[i].target = m_ConfigurableJointChain[i + 1].targetRotation.eulerAngles;
cjControlSettings[i].range = new Range3D(
m_ConfigurableJointChain[i + 1].lowAngularXLimit.limit,
m_ConfigurableJointChain[i + 1].highAngularXLimit.limit,
-m_ConfigurableJointChain[i + 1].angularYLimit.limit,
m_ConfigurableJointChain[i + 1].angularYLimit.limit,
-m_ConfigurableJointChain[i + 1].angularZLimit.limit,
m_ConfigurableJointChain[i + 1].angularZLimit.limit
);
cjControlSettings[i].originalPosition = m_ConfigurableJointChain[i].transform.position;
cjControlSettings[i].originalRotation = m_ConfigurableJointChain[i].transform.rotation;
}
}
if (totalMass == 0)
{
foreach (var rb in m_RigidbodyChain)
{
totalMass += rb.mass;
}
}
}
public void SetCJointTargets(ActionSegment<float> angles)
{
for (int i = 0; i < cjControlSettings.Length; i++)
{
var subindex = 3 * i;
var xAngle = cjControlSettings[i].range.xRange.Scale(angles[subindex]);
var yAngle = cjControlSettings[i].range.yRange.Scale(angles[++subindex]);
var zAngle = cjControlSettings[i].range.zRange.Scale(angles[++subindex]);
var targetRotation = new Vector3(xAngle, yAngle, zAngle);
SetCJointTarget(m_ConfigurableJointChain[i + 1], targetRotation);
}
}
public void SetCJointTargets()
{
for (int i = 0; i < cjControlSettings.Length; i++)
{
SetCJointTarget(m_ConfigurableJointChain[i + 1], cjControlSettings[i].target);
}
}
public void SetCJointTarget(ConfigurableJoint joint, Vector3 target)
{
joint.targetRotation = Quaternion.Euler(target);
}
public void SetCJointPositionsAndRotations()
{
for (int i = 0; i < cjControlSettings.Length; i++)
{
m_RigidbodyChain[i + 1].transform.position = cjControlSettings[i].originalPosition;
m_RigidbodyChain[i + 1].transform.rotation = cjControlSettings[i].originalRotation;
}
}
public IEnumerator ResetCJointTargetsAndPositions()
{
m_ConfigurableJointChain[0].GetComponent<Rigidbody>().isKinematic = true;
ZeroCJointPhysics();
ZeroCJointPhysicsSettings();
// yield return new WaitForSeconds(1.0f / 50);
SetCJointPositionsAndRotations();
SetCJointTargets();
SetCJointPhysicsSettings();
yield return new WaitForSeconds(1.0f / 50);
m_ConfigurableJointChain[0].GetComponent<Rigidbody>().isKinematic = kinematicRoot;
}
void SetCJointPhysicsSettings()
{
for (int i = 1; i < m_ConfigurableJointChain.Length; i++)
{
m_ConfigurableJointChain[i].rotationDriveMode = RotationDriveMode.Slerp;
var drive = m_ConfigurableJointChain[i].slerpDrive;
drive.positionSpring = spring;
drive.positionDamper = damping;
drive.maximumForce = forceLimit;
m_ConfigurableJointChain[i].slerpDrive = drive;
}
}
public void ZeroCJointPhysics()
{
foreach (var rb in m_RigidbodyChain)
{
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
rb.Sleep();
}
}
public void ZeroCJointPhysicsSettings()
{
for (int i = 1; i < m_ConfigurableJointChain.Length; i++)
{
m_ConfigurableJointChain[i].rotationDriveMode = RotationDriveMode.Slerp;
var drive = m_ConfigurableJointChain[i].slerpDrive;
drive.positionSpring = 0f;
drive.positionDamper = 0f;
drive.maximumForce = forceLimit;
m_ConfigurableJointChain[i].slerpDrive = drive;
}
}
}

Просмотреть файл

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

Просмотреть файл

@ -1,12 +1,14 @@
using System.Collections;
using System.Collections.Generic;
using RootMotion.Dynamics;
using Unity.MLAgents;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Sensors;
using UnityEngine;
public class WalkerASEAgent : Agent
{
public bool RecordingMode;
public bool recordingMode;
public Transform root;
public Rigidbody rootRB;
@ -14,15 +16,33 @@ public class WalkerASEAgent : Agent
Vector3 m_OriginalPosition;
Quaternion m_OriginalRotation;
ConfigurableJointController m_Controller;
public override void Initialize()
{
m_OriginalPosition = root.position;
m_OriginalRotation = root.rotation;
m_Controller = GetComponent<ConfigurableJointController>();
if (!recordingMode)
{
var puppetMaster = GetComponentInChildren<PuppetMaster>();
var animator = GetComponentInChildren<Animator>();
Destroy(puppetMaster);
Destroy(animator.gameObject);
}
}
public override void OnEpisodeBegin()
{
ResetAgent();
if (recordingMode)
{
ResetAnimation();
}
}
void ResetAnimation()
{
// TODO reset animation on an episode reset (nice to have)
}
void ResetAgent()
@ -46,7 +66,29 @@ public class WalkerASEAgent : Agent
}
public float GetRootHeightFromGround()
public override void OnActionReceived(ActionBuffers actionBuffers)
{
var continuousActions = actionBuffers.ContinuousActions;
m_Controller.SetCJointTargets(continuousActions);
}
public override void Heuristic(in ActionBuffers actionsOut)
{
var continuousActionsOut = actionsOut.ContinuousActions;
// add control from editor component
for (int i = 0; i < m_Controller.cjControlSettings.Length; i++)
{
var target = m_Controller.cjControlSettings[i].target;
var subIndex = 3 * i;
continuousActionsOut[subIndex] = m_Controller.cjControlSettings[i].range.xRange.InverseScale(target.x);
continuousActionsOut[++subIndex] = m_Controller.cjControlSettings[i].range.yRange.InverseScale(target.y);
continuousActionsOut[++subIndex] = m_Controller.cjControlSettings[i].range.zRange.InverseScale(target.z);
}
}
float GetRootHeightFromGround()
{
int layerMask = 1 << 3;
layerMask = ~layerMask;
@ -54,18 +96,18 @@ public class WalkerASEAgent : Agent
return raycastHit.distance;
}
public float GetRootBalance()
float GetRootBalance()
{
var agentUp = root.transform.TransformDirection(Vector3.up);
return Vector3.Dot(agentUp, Vector3.up);
}
public Vector3 GetVelocity()
Vector3 GetVelocity()
{
return rootRB.velocity;
}
public Vector3 GetAngularVelocity()
Vector3 GetAngularVelocity()
{
return rootRB.angularVelocity;
}