From 5dc37f85fb6b079471b7f006e3b2422c6ac0ec6e Mon Sep 17 00:00:00 2001 From: vincentpierre Date: Thu, 6 Feb 2020 10:56:06 -0800 Subject: [PATCH 1/4] Removing the monitor --- .../Scripts/FoodCollectorAgent.cs | 1 - .../Scripts/ProjectSettingsOverrides.cs | 8 +- .../Runtime/DemonstrationRecorder.cs | 3 - com.unity.ml-agents/Runtime/Monitor.cs | 564 ------------------ com.unity.ml-agents/Runtime/Monitor.cs.meta | 12 - 5 files changed, 1 insertion(+), 587 deletions(-) delete mode 100644 com.unity.ml-agents/Runtime/Monitor.cs delete mode 100644 com.unity.ml-agents/Runtime/Monitor.cs.meta diff --git a/Project/Assets/ML-Agents/Examples/FoodCollector/Scripts/FoodCollectorAgent.cs b/Project/Assets/ML-Agents/Examples/FoodCollector/Scripts/FoodCollectorAgent.cs index c4f304124a..cad3cb9757 100644 --- a/Project/Assets/ML-Agents/Examples/FoodCollector/Scripts/FoodCollectorAgent.cs +++ b/Project/Assets/ML-Agents/Examples/FoodCollector/Scripts/FoodCollectorAgent.cs @@ -32,7 +32,6 @@ public override void InitializeAgent() { base.InitializeAgent(); m_AgentRb = GetComponent(); - Monitor.verticalOffset = 1f; m_MyArea = area.GetComponent(); m_FoodCollecterSettings = FindObjectOfType(); diff --git a/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/ProjectSettingsOverrides.cs b/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/ProjectSettingsOverrides.cs index 1d98050617..7f529cd3de 100644 --- a/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/ProjectSettingsOverrides.cs +++ b/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/ProjectSettingsOverrides.cs @@ -6,7 +6,7 @@ namespace MLAgentsExamples public class ProjectSettingsOverrides : MonoBehaviour { // Original values - float m_OriginalMonitorVerticalOffset; + Vector3 m_OriginalGravity; float m_OriginalFixedDeltaTime; float m_OriginalMaximumDeltaTime; @@ -16,9 +16,6 @@ public class ProjectSettingsOverrides : MonoBehaviour [Tooltip("Increase or decrease the scene gravity. Use ~3x to make things less floaty")] public float gravityMultiplier = 1.0f; - [Header("Display Settings")] - public float monitorVerticalOffset; - [Header("Advanced physics settings")] [Tooltip("The interval in seconds at which physics and other fixed frame rate updates (like MonoBehaviour's FixedUpdate) are performed.")] public float fixedDeltaTime = .02f; @@ -32,7 +29,6 @@ public class ProjectSettingsOverrides : MonoBehaviour public void Awake() { // Save the original values - m_OriginalMonitorVerticalOffset = Monitor.verticalOffset; m_OriginalGravity = Physics.gravity; m_OriginalFixedDeltaTime = Time.fixedDeltaTime; m_OriginalMaximumDeltaTime = Time.maximumDeltaTime; @@ -40,7 +36,6 @@ public void Awake() m_OriginalSolverVelocityIterations = Physics.defaultSolverVelocityIterations; // Override - Monitor.verticalOffset = monitorVerticalOffset; Physics.gravity *= gravityMultiplier; Time.fixedDeltaTime = fixedDeltaTime; Time.maximumDeltaTime = maximumDeltaTime; @@ -52,7 +47,6 @@ public void Awake() public void OnDestroy() { - Monitor.verticalOffset = m_OriginalMonitorVerticalOffset; Physics.gravity = m_OriginalGravity; Time.fixedDeltaTime = m_OriginalFixedDeltaTime; Time.maximumDeltaTime = m_OriginalMaximumDeltaTime; diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index 313cdbe8b4..62c28be592 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -15,7 +15,6 @@ public class DemonstrationRecorder : MonoBehaviour { public bool record; public string demonstrationName; - Agent m_RecordingAgent; string m_FilePath; DemonstrationStore m_DemoStore; public const int MaxNameLength = 16; @@ -41,7 +40,6 @@ void Update() /// public void InitializeDemoStore(IFileSystem fileSystem = null) { - m_RecordingAgent = GetComponent(); m_DemoStore = new DemonstrationStore(fileSystem); var behaviorParams = GetComponent(); demonstrationName = SanitizeName(demonstrationName, MaxNameLength); @@ -49,7 +47,6 @@ public void InitializeDemoStore(IFileSystem fileSystem = null) demonstrationName, behaviorParams.brainParameters, behaviorParams.fullyQualifiedBehaviorName); - Monitor.Log("Recording Demonstration of Agent: ", m_RecordingAgent.name); } /// diff --git a/com.unity.ml-agents/Runtime/Monitor.cs b/com.unity.ml-agents/Runtime/Monitor.cs deleted file mode 100644 index e6ff5991a8..0000000000 --- a/com.unity.ml-agents/Runtime/Monitor.cs +++ /dev/null @@ -1,564 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace MLAgents -{ - /// - /// Monitor is used to display information about the Agent within the Unity - /// scene. Use the log function to add information to your monitor. - /// - public class Monitor : MonoBehaviour - { - /// - /// The type of monitor the information must be displayed in. - /// corresponds to a single rectangle whose width is given - /// by a float between -1 and 1. (green is positive, red is negative) - /// - /// corresponds to n vertical sliders. - /// is a text field. - /// is a rectangle of fixed length to represent the proportions - /// of a list of floats. - /// - public enum DisplayType - { - Independent, - Proportion - } - - /// - /// Represents how high above the target the monitors will be. - /// - public static float verticalOffset = 3f; - - static bool s_IsInstantiated; - static GameObject s_Canvas; - static Dictionary> s_DisplayTransformValues; - - /// - /// Camera used to calculate GUI screen position relative to the target - /// transform. - /// - static Dictionary s_TransformCamera; - - static Color[] s_BarColors; - - struct DisplayValue - { - public float time; - public string stringValue; - public float floatValue; - public float[] floatArrayValues; - - public enum ValueType - { - Float, - FloatarrayIndependent, - FloatarrayProportion, - String - } - - public ValueType valueType; - } - - static GUIStyle s_KeyStyle; - static GUIStyle s_ValueStyle; - static GUIStyle s_GreenStyle; - static GUIStyle s_RedStyle; - static GUIStyle[] s_ColorStyle; - static bool s_Initialized; - - /// - /// Use the Monitor.Log static function to attach information to a transform. - /// - /// The log. - /// The name of the information you wish to Log. - /// The string value you want to display. - /// The transform you want to attach the information to. - /// - /// Camera used to calculate GUI position relative to - /// the target. If null, `Camera.main` will be used. - public static void Log( - string key, - string value, - Transform target = null, - Camera camera = null) - { - if (!s_IsInstantiated) - { - InstantiateCanvas(); - s_IsInstantiated = true; - } - if (s_Canvas == null) - { - return; - } - - if (target == null) - { - target = s_Canvas.transform; - } - - s_TransformCamera[target] = camera; - - if (!s_DisplayTransformValues.Keys.Contains(target)) - { - s_DisplayTransformValues[target] = - new Dictionary(); - } - - var displayValues = - s_DisplayTransformValues[target]; - - if (value == null) - { - RemoveValue(target, key); - return; - } - - if (!displayValues.ContainsKey(key)) - { - var dv = new DisplayValue(); - dv.time = Time.timeSinceLevelLoad; - dv.stringValue = value; - dv.valueType = DisplayValue.ValueType.String; - displayValues[key] = dv; - while (displayValues.Count > 20) - { - var max = ( - displayValues - .Aggregate((l, r) => l.Value.time < r.Value.time ? l : r) - .Key - ); - RemoveValue(target, max); - } - } - else - { - var dv = displayValues[key]; - dv.stringValue = value; - dv.valueType = DisplayValue.ValueType.String; - displayValues[key] = dv; - } - } - - /// - /// Use the Monitor.Log static function to attach information to a transform. - /// - /// The log. - /// The name of the information you wish to Log. - /// The float value you want to display. - /// The transform you want to attach the information to. - /// - /// Camera used to calculate GUI position relative to - /// the target. If null, `Camera.main` will be used. - public static void Log( - string key, - float value, - Transform target = null, - Camera camera = null) - { - if (!s_IsInstantiated) - { - InstantiateCanvas(); - s_IsInstantiated = true; - } - - if (target == null) - { - target = s_Canvas.transform; - } - - s_TransformCamera[target] = camera; - - if (!s_DisplayTransformValues.Keys.Contains(target)) - { - s_DisplayTransformValues[target] = new Dictionary(); - } - - var displayValues = s_DisplayTransformValues[target]; - - if (!displayValues.ContainsKey(key)) - { - var dv = new DisplayValue(); - dv.time = Time.timeSinceLevelLoad; - dv.floatValue = value; - dv.valueType = DisplayValue.ValueType.Float; - displayValues[key] = dv; - while (displayValues.Count > 20) - { - var max = ( - displayValues.Aggregate((l, r) => l.Value.time < r.Value.time ? l : r).Key); - RemoveValue(target, max); - } - } - else - { - var dv = displayValues[key]; - dv.floatValue = value; - dv.valueType = DisplayValue.ValueType.Float; - displayValues[key] = dv; - } - } - - /// - /// Use the Monitor.Log static function to attach information to a transform. - /// - /// The log. - /// The name of the information you wish to Log. - /// The array of float you want to display. - /// The type of display. - /// The transform you want to attach the information to. - /// - /// Camera used to calculate GUI position relative to - /// the target. If null, `Camera.main` will be used. - public static void Log( - string key, - float[] value, - Transform target = null, - DisplayType displayType = DisplayType.Independent, - Camera camera = null - ) - { - if (!s_IsInstantiated) - { - InstantiateCanvas(); - s_IsInstantiated = true; - } - - if (target == null) - { - target = s_Canvas.transform; - } - - s_TransformCamera[target] = camera; - - if (!s_DisplayTransformValues.Keys.Contains(target)) - { - s_DisplayTransformValues[target] = new Dictionary(); - } - - var displayValues = s_DisplayTransformValues[target]; - - if (!displayValues.ContainsKey(key)) - { - var dv = new DisplayValue(); - dv.time = Time.timeSinceLevelLoad; - dv.floatArrayValues = value; - if (displayType == DisplayType.Independent) - { - dv.valueType = DisplayValue.ValueType.FloatarrayIndependent; - } - else - { - dv.valueType = DisplayValue.ValueType.FloatarrayProportion; - } - - displayValues[key] = dv; - while (displayValues.Count > 20) - { - var max = ( - displayValues.Aggregate((l, r) => l.Value.time < r.Value.time ? l : r).Key); - RemoveValue(target, max); - } - } - else - { - var dv = displayValues[key]; - dv.floatArrayValues = value; - if (displayType == DisplayType.Independent) - { - dv.valueType = DisplayValue.ValueType.FloatarrayIndependent; - } - else - { - dv.valueType = DisplayValue.ValueType.FloatarrayProportion; - } - - displayValues[key] = dv; - } - } - - /// - /// Remove a value from a monitor. - /// - /// - /// The transform to which the information is attached. - /// - /// The key of the information you want to remove. - public static void RemoveValue(Transform target, string key) - { - if (target == null) - { - target = s_Canvas.transform; - } - - if (s_DisplayTransformValues.Keys.Contains(target)) - { - if (s_DisplayTransformValues[target].ContainsKey(key)) - { - s_DisplayTransformValues[target].Remove(key); - if (s_DisplayTransformValues[target].Keys.Count == 0) - { - s_DisplayTransformValues.Remove(target); - } - } - } - } - - /// - /// Remove all information from a monitor. - /// - /// - /// The transform to which the information is attached. - /// - public static void RemoveAllValues(Transform target) - { - if (target == null) - { - target = s_Canvas.transform; - } - - if (s_DisplayTransformValues.Keys.Contains(target)) - { - s_DisplayTransformValues.Remove(target); - } - } - - /// - /// Use SetActive to enable or disable the Monitor via script - /// - /// Value to set the Monitor's status to. - public static void SetActive(bool active) - { - if (!s_IsInstantiated) - { - InstantiateCanvas(); - s_IsInstantiated = true; - } - - if (s_Canvas != null) - { - s_Canvas.SetActive(active); - } - } - - /// Initializes the canvas. - static void InstantiateCanvas() - { - s_Canvas = GameObject.Find("AgentMonitorCanvas"); - if (s_Canvas == null) - { - s_Canvas = new GameObject(); - s_Canvas.name = "AgentMonitorCanvas"; - s_Canvas.AddComponent(); - } - - s_DisplayTransformValues = new Dictionary>(); - - s_TransformCamera = new Dictionary(); - } - - /// - void OnGUI() - { - if (!s_Initialized) - { - Initialize(); - s_Initialized = true; - } - - var toIterate = s_DisplayTransformValues.Keys.ToList(); - foreach (var target in toIterate) - { - if (target == null) - { - s_DisplayTransformValues.Remove(target); - continue; - } - - // get camera - var cam = s_TransformCamera[target]; - if (cam == null) - { - cam = Camera.main; - } - - var widthScaler = (Screen.width / 1000f); - var keyPixelWidth = 100 * widthScaler; - var keyPixelHeight = 20 * widthScaler; - var paddingWidth = 10 * widthScaler; - - var scale = 1f; - var origin = new Vector3( - Screen.width / 2.0f - keyPixelWidth, Screen.height); - if (!(target == s_Canvas.transform)) - { - var camTransform = cam.transform; - var position = target.position; - var cam2Obj = position - camTransform.position; - scale = Mathf.Min( - 1, - 20f / (Vector3.Dot(cam2Obj, camTransform.forward))); - var worldPosition = cam.WorldToScreenPoint( - position + new Vector3(0, verticalOffset, 0)); - origin = new Vector3( - worldPosition.x - keyPixelWidth * scale, Screen.height - worldPosition.y); - } - - keyPixelWidth *= scale; - keyPixelHeight *= scale; - paddingWidth *= scale; - s_KeyStyle.fontSize = (int)(keyPixelHeight * 0.8f); - if (s_KeyStyle.fontSize < 2) - { - continue; - } - - - var displayValues = s_DisplayTransformValues[target]; - - var index = 0; - var orderedKeys = displayValues.Keys.OrderBy(x => - displayValues[x].time); - foreach (var key in orderedKeys) - { - s_KeyStyle.alignment = TextAnchor.MiddleRight; - GUI.Label( - new Rect( - origin.x, origin.y - (index + 1) * keyPixelHeight, - keyPixelWidth, keyPixelHeight), - key, - s_KeyStyle); - float[] vals; - GUIStyle s; - switch (displayValues[key].valueType) - { - case DisplayValue.ValueType.String: - s_ValueStyle.alignment = TextAnchor.MiddleLeft; - GUI.Label( - new Rect( - origin.x + paddingWidth + keyPixelWidth, - origin.y - (index + 1) * keyPixelHeight, - keyPixelWidth, keyPixelHeight), - displayValues[key].stringValue, - s_ValueStyle); - break; - case DisplayValue.ValueType.Float: - var sliderValue = displayValues[key].floatValue; - sliderValue = Mathf.Min(1f, sliderValue); - s = s_GreenStyle; - if (sliderValue < 0) - { - sliderValue = Mathf.Min(1f, -sliderValue); - s = s_RedStyle; - } - - GUI.Box( - new Rect( - origin.x + paddingWidth + keyPixelWidth, - origin.y - (index + 0.9f) * keyPixelHeight, - keyPixelWidth * sliderValue, keyPixelHeight * 0.8f), - GUIContent.none, - s); - break; - - case DisplayValue.ValueType.FloatarrayIndependent: - const float histWidth = 0.15f; - vals = displayValues[key].floatArrayValues; - for (var i = 0; i < vals.Length; i++) - { - var value = Mathf.Min(vals[i], 1); - s = s_GreenStyle; - if (value < 0) - { - value = Mathf.Min(1f, -value); - s = s_RedStyle; - } - - GUI.Box( - new Rect( - origin.x + paddingWidth + keyPixelWidth + - (keyPixelWidth * histWidth + paddingWidth / 2) * i, - origin.y - (index + 0.1f) * keyPixelHeight, - keyPixelWidth * histWidth, -keyPixelHeight * value), - GUIContent.none, - s); - } - - break; - - case DisplayValue.ValueType.FloatarrayProportion: - var valsSum = 0f; - var valsCum = 0f; - vals = displayValues[key].floatArrayValues; - foreach (var f in vals) - { - valsSum += Mathf.Max(f, 0); - } - - if (valsSum < float.Epsilon) - { - Debug.LogError( - $"The Monitor value for key {key} " + - "must be a list or array of " + - "positive values and cannot " + - "be empty."); - } - else - { - for (var i = 0; i < vals.Length; i++) - { - var value = Mathf.Max(vals[i], 0) / valsSum; - GUI.Box( - new Rect( - origin.x + paddingWidth + - keyPixelWidth + keyPixelWidth * valsCum, - origin.y - (index + 0.9f) * keyPixelHeight, - keyPixelWidth * value, keyPixelHeight * 0.8f), - GUIContent.none, - s_ColorStyle[i % s_ColorStyle.Length]); - valsCum += value; - } - } - - break; - } - - index++; - } - } - } - - /// Helper method used to initialize the GUI. Called once. - void Initialize() - { - s_KeyStyle = GUI.skin.label; - s_ValueStyle = GUI.skin.label; - s_ValueStyle.clipping = TextClipping.Overflow; - s_ValueStyle.wordWrap = false; - s_BarColors = new[] - { - Color.magenta, - Color.blue, - Color.cyan, - Color.green, - Color.yellow, - Color.red - }; - s_ColorStyle = new GUIStyle[s_BarColors.Length]; - for (var i = 0; i < s_BarColors.Length; i++) - { - var texture = new Texture2D(1, 1, TextureFormat.ARGB32, false); - texture.SetPixel(0, 0, s_BarColors[i]); - texture.Apply(); - var staticRectStyle = new GUIStyle(); - staticRectStyle.normal.background = texture; - s_ColorStyle[i] = staticRectStyle; - } - - s_GreenStyle = s_ColorStyle[3]; - s_RedStyle = s_ColorStyle[5]; - } - } -} diff --git a/com.unity.ml-agents/Runtime/Monitor.cs.meta b/com.unity.ml-agents/Runtime/Monitor.cs.meta deleted file mode 100644 index 74c210c11f..0000000000 --- a/com.unity.ml-agents/Runtime/Monitor.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: e59a31a1cc2f5464d9a61bef0bc9a53b -timeCreated: 1508031727 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: From 80f9f291918fc6de2704e9cae9a4f72c55c18723 Mon Sep 17 00:00:00 2001 From: vincentpierre Date: Thu, 6 Feb 2020 10:59:31 -0800 Subject: [PATCH 2/4] Editing the migrating docs --- docs/Migrating.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/Migrating.md b/docs/Migrating.md index af61faf334..94404aef27 100644 --- a/docs/Migrating.md +++ b/docs/Migrating.md @@ -7,8 +7,15 @@ The versions can be found in # Migrating +## Migrating from 0.14 to latest -## Migrating from 0.13 to latest +### Important changes +* The `Monitor` class has been removed. (It was prone to errors during testing) + +### Steps to Migrate + + +## Migrating from 0.13 to 0.14 ### Important changes * The `UnitySDK` folder has been split into a Unity Package (`com.unity.ml-agents`) and an examples project (`Project`). Please follow the [Installation Guide](Installation.md) to get up and running with this new repo structure. From fbe7005af692dceda9f09a46d2b9f3ef73ec756d Mon Sep 17 00:00:00 2001 From: vincentpierre Date: Thu, 6 Feb 2020 13:00:23 -0800 Subject: [PATCH 3/4] Readding the Monitor in the examples folder --- .../Examples/SharedAssets/Scripts/Monitor.cs | 564 ++++++++++++++++++ .../SharedAssets/Scripts/Monitor.cs.meta | 11 + 2 files changed, 575 insertions(+) create mode 100644 Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/Monitor.cs create mode 100644 Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/Monitor.cs.meta diff --git a/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/Monitor.cs b/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/Monitor.cs new file mode 100644 index 0000000000..eedeb57a82 --- /dev/null +++ b/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/Monitor.cs @@ -0,0 +1,564 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace MLAgents +{ + /// + /// Monitor is used to display information about the Agent within the Unity + /// scene. Use the log function to add information to your monitor. + /// + public class Monitor : MonoBehaviour + { + /// + /// The type of monitor the information must be displayed in. + /// corresponds to a single rectangle whose width is given + /// by a float between -1 and 1. (green is positive, red is negative) + /// + /// corresponds to n vertical sliders. + /// is a text field. + /// is a rectangle of fixed length to represent the proportions + /// of a list of floats. + /// + public enum DisplayType + { + Independent, + Proportion + } + + /// + /// Represents how high above the target the monitors will be. + /// + public static float verticalOffset = 3f; + + static bool s_IsInstantiated; + static GameObject s_Canvas; + static Dictionary> s_DisplayTransformValues; + + /// + /// Camera used to calculate GUI screen position relative to the target + /// transform. + /// + static Dictionary s_TransformCamera; + + static Color[] s_BarColors; + + struct DisplayValue + { + public float time; + public string stringValue; + public float floatValue; + public float[] floatArrayValues; + + public enum ValueType + { + Float, + FloatarrayIndependent, + FloatarrayProportion, + String + } + + public ValueType valueType; + } + + static GUIStyle s_KeyStyle; + static GUIStyle s_ValueStyle; + static GUIStyle s_GreenStyle; + static GUIStyle s_RedStyle; + static GUIStyle[] s_ColorStyle; + static bool s_Initialized; + + /// + /// Use the Monitor.Log static function to attach information to a transform. + /// + /// The log. + /// The name of the information you wish to Log. + /// The string value you want to display. + /// The transform you want to attach the information to. + /// + /// Camera used to calculate GUI position relative to + /// the target. If null, `Camera.main` will be used. + public static void Log( + string key, + string value, + Transform target = null, + Camera camera = null) + { + if (!s_IsInstantiated) + { + InstantiateCanvas(); + s_IsInstantiated = true; + } + if (s_Canvas == null) + { + return; + } + + if (target == null) + { + target = s_Canvas.transform; + } + + s_TransformCamera[target] = camera; + + if (!s_DisplayTransformValues.Keys.Contains(target)) + { + s_DisplayTransformValues[target] = + new Dictionary(); + } + + var displayValues = + s_DisplayTransformValues[target]; + + if (value == null) + { + RemoveValue(target, key); + return; + } + + if (!displayValues.ContainsKey(key)) + { + var dv = new DisplayValue(); + dv.time = Time.timeSinceLevelLoad; + dv.stringValue = value; + dv.valueType = DisplayValue.ValueType.String; + displayValues[key] = dv; + while (displayValues.Count > 20) + { + var max = ( + displayValues + .Aggregate((l, r) => l.Value.time < r.Value.time ? l : r) + .Key + ); + RemoveValue(target, max); + } + } + else + { + var dv = displayValues[key]; + dv.stringValue = value; + dv.valueType = DisplayValue.ValueType.String; + displayValues[key] = dv; + } + } + + /// + /// Use the Monitor.Log static function to attach information to a transform. + /// + /// The log. + /// The name of the information you wish to Log. + /// The float value you want to display. + /// The transform you want to attach the information to. + /// + /// Camera used to calculate GUI position relative to + /// the target. If null, `Camera.main` will be used. + public static void Log( + string key, + float value, + Transform target = null, + Camera camera = null) + { + if (!s_IsInstantiated) + { + InstantiateCanvas(); + s_IsInstantiated = true; + } + + if (target == null) + { + target = s_Canvas.transform; + } + + s_TransformCamera[target] = camera; + + if (!s_DisplayTransformValues.Keys.Contains(target)) + { + s_DisplayTransformValues[target] = new Dictionary(); + } + + var displayValues = s_DisplayTransformValues[target]; + + if (!displayValues.ContainsKey(key)) + { + var dv = new DisplayValue(); + dv.time = Time.timeSinceLevelLoad; + dv.floatValue = value; + dv.valueType = DisplayValue.ValueType.Float; + displayValues[key] = dv; + while (displayValues.Count > 20) + { + var max = ( + displayValues.Aggregate((l, r) => l.Value.time < r.Value.time ? l : r).Key); + RemoveValue(target, max); + } + } + else + { + var dv = displayValues[key]; + dv.floatValue = value; + dv.valueType = DisplayValue.ValueType.Float; + displayValues[key] = dv; + } + } + + /// + /// Use the Monitor.Log static function to attach information to a transform. + /// + /// The log. + /// The name of the information you wish to Log. + /// The array of float you want to display. + /// The type of display. + /// The transform you want to attach the information to. + /// + /// Camera used to calculate GUI position relative to + /// the target. If null, `Camera.main` will be used. + public static void Log( + string key, + float[] value, + Transform target = null, + DisplayType displayType = DisplayType.Independent, + Camera camera = null + ) + { + if (!s_IsInstantiated) + { + InstantiateCanvas(); + s_IsInstantiated = true; + } + + if (target == null) + { + target = s_Canvas.transform; + } + + s_TransformCamera[target] = camera; + + if (!s_DisplayTransformValues.Keys.Contains(target)) + { + s_DisplayTransformValues[target] = new Dictionary(); + } + + var displayValues = s_DisplayTransformValues[target]; + + if (!displayValues.ContainsKey(key)) + { + var dv = new DisplayValue(); + dv.time = Time.timeSinceLevelLoad; + dv.floatArrayValues = value; + if (displayType == DisplayType.Independent) + { + dv.valueType = DisplayValue.ValueType.FloatarrayIndependent; + } + else + { + dv.valueType = DisplayValue.ValueType.FloatarrayProportion; + } + + displayValues[key] = dv; + while (displayValues.Count > 20) + { + var max = ( + displayValues.Aggregate((l, r) => l.Value.time < r.Value.time ? l : r).Key); + RemoveValue(target, max); + } + } + else + { + var dv = displayValues[key]; + dv.floatArrayValues = value; + if (displayType == DisplayType.Independent) + { + dv.valueType = DisplayValue.ValueType.FloatarrayIndependent; + } + else + { + dv.valueType = DisplayValue.ValueType.FloatarrayProportion; + } + + displayValues[key] = dv; + } + } + + /// + /// Remove a value from a monitor. + /// + /// + /// The transform to which the information is attached. + /// + /// The key of the information you want to remove. + public static void RemoveValue(Transform target, string key) + { + if (target == null) + { + target = s_Canvas.transform; + } + + if (s_DisplayTransformValues.Keys.Contains(target)) + { + if (s_DisplayTransformValues[target].ContainsKey(key)) + { + s_DisplayTransformValues[target].Remove(key); + if (s_DisplayTransformValues[target].Keys.Count == 0) + { + s_DisplayTransformValues.Remove(target); + } + } + } + } + + /// + /// Remove all information from a monitor. + /// + /// + /// The transform to which the information is attached. + /// + public static void RemoveAllValues(Transform target) + { + if (target == null) + { + target = s_Canvas.transform; + } + + if (s_DisplayTransformValues.Keys.Contains(target)) + { + s_DisplayTransformValues.Remove(target); + } + } + + /// + /// Use SetActive to enable or disable the Monitor via script + /// + /// Value to set the Monitor's status to. + public static void SetActive(bool active) + { + if (!s_IsInstantiated) + { + InstantiateCanvas(); + s_IsInstantiated = true; + } + + if (s_Canvas != null) + { + s_Canvas.SetActive(active); + } + } + + /// Initializes the canvas. + static void InstantiateCanvas() + { + s_Canvas = GameObject.Find("AgentMonitorCanvas"); + if (s_Canvas == null) + { + s_Canvas = new GameObject(); + s_Canvas.name = "AgentMonitorCanvas"; + s_Canvas.AddComponent(); + } + + s_DisplayTransformValues = new Dictionary>(); + + s_TransformCamera = new Dictionary(); + } + + /// + void OnGUI() + { + if (!s_Initialized) + { + Initialize(); + s_Initialized = true; + } + + var toIterate = s_DisplayTransformValues.Keys.ToList(); + foreach (var target in toIterate) + { + if (target == null) + { + s_DisplayTransformValues.Remove(target); + continue; + } + + // get camera + var cam = s_TransformCamera[target]; + if (cam == null) + { + cam = Camera.main; + } + + var widthScaler = (Screen.width / 1000f); + var keyPixelWidth = 100 * widthScaler; + var keyPixelHeight = 20 * widthScaler; + var paddingWidth = 10 * widthScaler; + + var scale = 1f; + var origin = new Vector3( + Screen.width / 2.0f - keyPixelWidth, Screen.height); + if (!(target == s_Canvas.transform)) + { + var camTransform = cam.transform; + var position = target.position; + var cam2Obj = position - camTransform.position; + scale = Mathf.Min( + 1, + 20f / (Vector3.Dot(cam2Obj, camTransform.forward))); + var worldPosition = cam.WorldToScreenPoint( + position + new Vector3(0, verticalOffset, 0)); + origin = new Vector3( + worldPosition.x - keyPixelWidth * scale, Screen.height - worldPosition.y); + } + + keyPixelWidth *= scale; + keyPixelHeight *= scale; + paddingWidth *= scale; + s_KeyStyle.fontSize = (int)(keyPixelHeight * 0.8f); + if (s_KeyStyle.fontSize < 2) + { + continue; + } + + + var displayValues = s_DisplayTransformValues[target]; + + var index = 0; + var orderedKeys = displayValues.Keys.OrderBy(x => - displayValues[x].time); + foreach (var key in orderedKeys) + { + s_KeyStyle.alignment = TextAnchor.MiddleRight; + GUI.Label( + new Rect( + origin.x, origin.y - (index + 1) * keyPixelHeight, + keyPixelWidth, keyPixelHeight), + key, + s_KeyStyle); + float[] vals; + GUIStyle s; + switch (displayValues[key].valueType) + { + case DisplayValue.ValueType.String: + s_ValueStyle.alignment = TextAnchor.MiddleLeft; + GUI.Label( + new Rect( + origin.x + paddingWidth + keyPixelWidth, + origin.y - (index + 1) * keyPixelHeight, + keyPixelWidth, keyPixelHeight), + displayValues[key].stringValue, + s_ValueStyle); + break; + case DisplayValue.ValueType.Float: + var sliderValue = displayValues[key].floatValue; + sliderValue = Mathf.Min(1f, sliderValue); + s = s_GreenStyle; + if (sliderValue < 0) + { + sliderValue = Mathf.Min(1f, -sliderValue); + s = s_RedStyle; + } + + GUI.Box( + new Rect( + origin.x + paddingWidth + keyPixelWidth, + origin.y - (index + 0.9f) * keyPixelHeight, + keyPixelWidth * sliderValue, keyPixelHeight * 0.8f), + GUIContent.none, + s); + break; + + case DisplayValue.ValueType.FloatarrayIndependent: + const float histWidth = 0.15f; + vals = displayValues[key].floatArrayValues; + for (var i = 0; i < vals.Length; i++) + { + var value = Mathf.Min(vals[i], 1); + s = s_GreenStyle; + if (value < 0) + { + value = Mathf.Min(1f, -value); + s = s_RedStyle; + } + + GUI.Box( + new Rect( + origin.x + paddingWidth + keyPixelWidth + + (keyPixelWidth * histWidth + paddingWidth / 2) * i, + origin.y - (index + 0.1f) * keyPixelHeight, + keyPixelWidth * histWidth, -keyPixelHeight * value), + GUIContent.none, + s); + } + + break; + + case DisplayValue.ValueType.FloatarrayProportion: + var valsSum = 0f; + var valsCum = 0f; + vals = displayValues[key].floatArrayValues; + foreach (var f in vals) + { + valsSum += Mathf.Max(f, 0); + } + + if (valsSum < float.Epsilon) + { + Debug.LogError( + $"The Monitor value for key {key} " + + "must be a list or array of " + + "positive values and cannot " + + "be empty."); + } + else + { + for (var i = 0; i < vals.Length; i++) + { + var value = Mathf.Max(vals[i], 0) / valsSum; + GUI.Box( + new Rect( + origin.x + paddingWidth + + keyPixelWidth + keyPixelWidth * valsCum, + origin.y - (index + 0.9f) * keyPixelHeight, + keyPixelWidth * value, keyPixelHeight * 0.8f), + GUIContent.none, + s_ColorStyle[i % s_ColorStyle.Length]); + valsCum += value; + } + } + + break; + } + + index++; + } + } + } + + /// Helper method used to initialize the GUI. Called once. + void Initialize() + { + s_KeyStyle = GUI.skin.label; + s_ValueStyle = GUI.skin.label; + s_ValueStyle.clipping = TextClipping.Overflow; + s_ValueStyle.wordWrap = false; + s_BarColors = new[] + { + Color.magenta, + Color.blue, + Color.cyan, + Color.green, + Color.yellow, + Color.red + }; + s_ColorStyle = new GUIStyle[s_BarColors.Length]; + for (var i = 0; i < s_BarColors.Length; i++) + { + var texture = new Texture2D(1, 1, TextureFormat.ARGB32, false); + texture.SetPixel(0, 0, s_BarColors[i]); + texture.Apply(); + var staticRectStyle = new GUIStyle(); + staticRectStyle.normal.background = texture; + s_ColorStyle[i] = staticRectStyle; + } + + s_GreenStyle = s_ColorStyle[3]; + s_RedStyle = s_ColorStyle[5]; + } + } +} \ No newline at end of file diff --git a/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/Monitor.cs.meta b/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/Monitor.cs.meta new file mode 100644 index 0000000000..e10bd36d98 --- /dev/null +++ b/Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/Monitor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eca114d0a5b45439384024291ba7d40a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 42150601dbe8c9265de577911c25378961f564c4 Mon Sep 17 00:00:00 2001 From: vincentpierre Date: Thu, 6 Feb 2020 13:01:58 -0800 Subject: [PATCH 4/4] Editing the Migrating doc --- docs/Migrating.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Migrating.md b/docs/Migrating.md index 94404aef27..0fcba40451 100644 --- a/docs/Migrating.md +++ b/docs/Migrating.md @@ -10,7 +10,7 @@ The versions can be found in ## Migrating from 0.14 to latest ### Important changes -* The `Monitor` class has been removed. (It was prone to errors during testing) +* The `Monitor` class has been moved to the Examples Project. (It was prone to errors during testing) ### Steps to Migrate