using System.Collections; using System.Collections.Generic; using System; using System.Linq; using UnityEngine; using Unity.MLAgents.Policies; using Unity.MLAgents; public class MapRangeOfMotion2Constraints : MonoBehaviour { /* [SerializeField] bool applyROMInGamePlay; public bool ApplyROMInGamePlay { set => applyROMInGamePlay = value; } */ public RangeOfMotionValues info2store; [Range(0, 359)] int MinROMNeededForJoint = 5; [SerializeField] bool debugWithLargestROM = false; [Tooltip("extra range for upper and lower angles of moving articulations ")] [SerializeField] float extraoffset = 10; public void ConfigureTrainingForRagdoll(int minROM) { MinROMNeededForJoint = minROM; int dof = ApplyRangeOfMotionToRagDoll(); if (dof == -1) { Debug.LogError("Problems applying the range of motion to the ragdoll"); } else { ApplyDoFOnBehaviorParameters(dof); } } int ApplyRangeOfMotionToRagDoll() { if (info2store == null || info2store.Values.Length == 0) return -1; ArticulationBody[] articulationBodies = GetComponentsInChildren(true) .Where(x=>x.name.StartsWith("articulation:")) .ToArray(); int DegreesOfFreedom = 0; foreach (ArticulationBody body in articulationBodies) { if (body.isRoot) continue; string keyword1 = "articulation:"; string keyword2 = "collider:"; string valuename = body.name.TrimStart(keyword1.ToArray()); valuename = valuename.TrimStart(keyword2.ToArray()); RangeOfMotionValue rom = info2store.Values.FirstOrDefault(x => x.name == valuename); if (rom == null) { Debug.LogError("Could not find a rangoe of motionvalue for articulation: " + body.name); return -1; } bool isLocked = true; body.twistLock = ArticulationDofLock.LockedMotion; body.swingYLock = ArticulationDofLock.LockedMotion; body.swingZLock = ArticulationDofLock.LockedMotion; body.jointType = ArticulationJointType.FixedJoint; body.anchorRotation = Quaternion.identity; //we make sure the anchor has no Rotation, otherwise the constraints do not make any sense if (rom.rangeOfMotion.x > (float)MinROMNeededForJoint) { DegreesOfFreedom++; isLocked = false; body.twistLock = ArticulationDofLock.LimitedMotion; var drive = body.xDrive; drive.lowerLimit = rom.lower.x - extraoffset; drive.upperLimit = rom.upper.x + extraoffset; body.xDrive = drive; if (debugWithLargestROM) { drive.lowerLimit = -170; drive.upperLimit = +170; } } if (rom.rangeOfMotion.y >= (float)MinROMNeededForJoint) { DegreesOfFreedom++; isLocked = false; body.swingYLock = ArticulationDofLock.LimitedMotion; var drive = body.yDrive; drive.lowerLimit = rom.lower.y - extraoffset; drive.upperLimit = rom.upper.y + extraoffset; body.yDrive = drive; if (debugWithLargestROM) { drive.lowerLimit = -170 - extraoffset; drive.upperLimit = +170 + extraoffset; } } if (rom.rangeOfMotion.z >= (float)MinROMNeededForJoint) { DegreesOfFreedom++; isLocked = false; body.swingZLock = ArticulationDofLock.LimitedMotion; var drive = body.zDrive; drive.lowerLimit = rom.lower.z - extraoffset; drive.upperLimit = rom.upper.z + extraoffset; body.zDrive = drive; if (debugWithLargestROM) { drive.lowerLimit = -170; drive.upperLimit = +170; } } if (!isLocked) { body.jointType = ArticulationJointType.SphericalJoint; } } return DegreesOfFreedom; } void ApplyDoFOnBehaviorParameters(int DegreesOfFreedom) { BehaviorParameters bp = GetComponent(); Unity.MLAgents.Actuators.ActionSpec myActionSpec = bp.BrainParameters.ActionSpec; myActionSpec.NumContinuousActions = DegreesOfFreedom; myActionSpec.BranchSizes = new List().ToArray(); bp.BrainParameters.ActionSpec = myActionSpec; Debug.Log("Space of actions calculated at:" + myActionSpec.NumContinuousActions + " continuous dimensions"); /* * To calculate the space of observations: */ int numsensors = GetComponentsInChildren().Length; int num_miscelaneous = GetComponent().calculateDreConObservationsize(); //apparently the number of sensors is already acocunted for in the degrees of freedom, so: // int ObservationDimensions = DegreesOfFreedom + numsensors + num_miscelaneous; int ObservationDimensions = DegreesOfFreedom + num_miscelaneous; bp.BrainParameters.VectorObservationSize = ObservationDimensions; Debug.Log("Space of perceptions calculated at:" + bp.BrainParameters.VectorObservationSize + " continuous dimensions, with: " + " sensors: " + numsensors + "and DreCon miscelaneous: " + num_miscelaneous); } }