浏览代码

new Monitor

/develop-generalizationTraining-TrainerController
vincentpierre 7 年前
当前提交
2d5d735f
共有 6 个文件被更改,包括 392 次插入204 次删除
  1. 380
      unity-environment/Assets/ML-Agents/Scripts/Monitor.cs
  2. 12
      unity-environment/Assets/ML-Agents/Scripts/Monitor.cs.meta
  3. 183
      unity-environment/Assets/ML-Agents/Scripts/AgentMonitor.cs
  4. 12
      unity-environment/Assets/ML-Agents/Scripts/AgentMonitor.cs.meta
  5. 9
      unity-environment/Assets/ML-Agents/Resources.meta

380
unity-environment/Assets/ML-Agents/Scripts/Monitor.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Newtonsoft.Json;
using System.Linq;
/** The type of monitor the information must be displayed in.
* <slider> corresponds to a slingle rectangle which width is given
* by a float between -1 and 1. (green is positive, red is negative)
* <hist> corresponds to n vertical sliders.
* <text> is a text field.
* <bar> is a rectangle of fixed length to represent the proportions
* of a list of floats.
*/
public enum MonitorType
{
slider,
hist,
text,
bar
}
/** Monitor is used to display information. Use the log function to add
* information to your monitor.
*/
public class Monitor : MonoBehaviour
{
static bool isInstanciated;
static GameObject canvas;
private struct DisplayValue
{
public float time;
public object value;
public MonitorType monitorDisplayType;
}
static Dictionary<Transform, Dictionary<string, DisplayValue>> displayTransformValues;
static private Color[] barColors;
[HideInInspector]
static public float verticalOffset = 3f;
/**< \brief This float represents how high above the target the monitors will be. */
static GUIStyle keyStyle;
static GUIStyle valueStyle;
static GUIStyle greenStyle;
static GUIStyle redStyle;
static GUIStyle[] colorStyle;
static bool initialized;
/** Use the Monitor.Log static function to attach information to a transform.
* If displayType is <text>, value can be any object.
* If sidplayType is <slider>, value must be a float.
* If sidplayType is <hist>, value must be a List or Array of floats.
* If sidplayType is <bar>, value must be a list or Array of positive floats.
* Note that <slider> and <hist> caps values between -1 and 1.
* @param key The name of the information you wish to Log.
* @param value The value you want to display.
* @param displayType The type of display.
* @param target The transform you want to attach the information to.
*/
public static void Log(
string key,
object value,
MonitorType displayType = MonitorType.text,
Transform target = null)
{
if (!isInstanciated)
{
InstanciateCanvas();
isInstanciated = true;
}
if (target == null)
{
target = canvas.transform;
}
if (!displayTransformValues.Keys.Contains(target))
{
displayTransformValues[target] = new Dictionary<string, DisplayValue>();
}
Dictionary<string, DisplayValue> displayValues = displayTransformValues[target];
if (value == null)
{
RemoveValue(target, key);
return;
}
if (!displayValues.ContainsKey(key))
{
DisplayValue dv = new DisplayValue();
dv.time = Time.timeSinceLevelLoad;
dv.value = value;
dv.monitorDisplayType = displayType;
displayValues[key] = dv;
while (displayValues.Count > 20)
{
string max = displayValues.Aggregate((l, r) => l.Value.time < r.Value.time ? l : r).Key;
RemoveValue(target, max);
}
}
else
{
DisplayValue dv = displayValues[key];
dv.value = value;
displayValues[key] = dv;
}
}
/** Remove a value from a monitor
* @param target The transform to which the information is attached
* @param key The key of the information you want to remove
*/
public static void RemoveValue(Transform target, string key)
{
if (target == null)
{
target = canvas.transform;
}
if (displayTransformValues.Keys.Contains(target))
{
if (displayTransformValues[target].ContainsKey(key))
{
displayTransformValues[target].Remove(key);
if (displayTransformValues[target].Keys.Count == 0)
{
displayTransformValues.Remove(target);
}
}
}
}
/** Remove all information from a monitor
* @param target The transform to which the information is attached
*/
public static void RemoveAllValues(Transform target)
{
if (target == null)
{
target = canvas.transform;
}
if (displayTransformValues.Keys.Contains(target))
{
displayTransformValues.Remove(target);
}
}
/** Use SetActive to enable or disable the Monitor via script
* @param active Set the Monitor's status to the value of active
*/
public static void SetActive(bool active){
if (!isInstanciated)
{
InstanciateCanvas();
isInstanciated = true;
}
canvas.SetActive(active);
}
private static void InstanciateCanvas()
{
canvas = GameObject.Find("AgentMonitorCanvas");
if (canvas == null)
{
canvas = new GameObject();
canvas.name = "AgentMonitorCanvas";
canvas.AddComponent<Monitor>();
}
displayTransformValues = new Dictionary<Transform, Dictionary< string , DisplayValue>>();
}
private float[] ToFloatArray(object input)
{
try
{
return JsonConvert.DeserializeObject<float[]>(
JsonConvert.SerializeObject(input, Formatting.None));
}
catch
{
}
try
{
return new float[1]
{JsonConvert.DeserializeObject<float>(
JsonConvert.SerializeObject(input, Formatting.None))
};
}
catch
{
}
return new float[0];
}
void OnGUI()
{
if (!initialized)
{
Initialize();
initialized = true;
}
var toIterate = displayTransformValues.Keys.ToList();
foreach (Transform target in toIterate)
{
if (target == null)
{
displayTransformValues.Remove(target);
continue;
}
float widthScaler = (Screen.width / 1000f);
float keyPixelWidth = 100 * widthScaler;
float keyPixelHeight = 20 * widthScaler;
float paddingwidth = 10 * widthScaler;
float scale = 1f;
Vector2 origin = new Vector3(0, Screen.height);
if (!(target == canvas.transform))
{
Vector3 cam2obj = target.position - Camera.main.transform.position;
scale = Mathf.Min(1, 20f / (Vector3.Dot(cam2obj, Camera.main.transform.forward)));
Vector3 worldPosition = Camera.main.WorldToScreenPoint(target.position + new Vector3(0, verticalOffset, 0));
origin = new Vector3(worldPosition.x - keyPixelWidth * scale, Screen.height - worldPosition.y);
}
keyPixelWidth *= scale;
keyPixelHeight *= scale;
paddingwidth *= scale;
keyStyle.fontSize = (int)(keyPixelHeight * 0.8f);
if (keyStyle.fontSize < 2)
{
continue;
}
Dictionary<string, DisplayValue> displayValues = displayTransformValues[target];
int index = 0;
foreach (string key in displayValues.Keys.OrderBy(x => -displayValues[x].time))
{
keyStyle.alignment = TextAnchor.MiddleRight;
GUI.Label(new Rect(origin.x, origin.y - (index + 1) * keyPixelHeight, keyPixelWidth, keyPixelHeight), key, keyStyle);
if (displayValues[key].monitorDisplayType == MonitorType.text)
{
valueStyle.alignment = TextAnchor.MiddleLeft;
GUI.Label(new Rect(
origin.x + paddingwidth + keyPixelWidth,
origin.y - (index + 1) * keyPixelHeight,
keyPixelWidth, keyPixelHeight),
JsonConvert.SerializeObject(displayValues[key].value, Formatting.None), valueStyle);
}
else if (displayValues[key].monitorDisplayType == MonitorType.slider)
{
float sliderValue = 0f;
if (displayValues[key].value.GetType() == typeof(float))
{
sliderValue = (float)displayValues[key].value;
}
else
{
Debug.LogError(string.Format("The value for {0} could not be displayed as " +
"a slider because it is not a number.", key));
}
sliderValue = Mathf.Min(1f, sliderValue);
GUIStyle s = greenStyle;
if (sliderValue < 0)
{
sliderValue = Mathf.Min(1f, -sliderValue);
s = redStyle;
}
GUI.Box(new Rect(
origin.x + paddingwidth + keyPixelWidth,
origin.y - (index + 0.9f) * keyPixelHeight,
keyPixelWidth * sliderValue, keyPixelHeight * 0.8f),
GUIContent.none, s);
}
else if (displayValues[key].monitorDisplayType == MonitorType.hist)
{
float histWidth = 0.15f;
float[] vals = ToFloatArray(displayValues[key].value);
for (int i = 0; i < vals.Length; i++)
{
float value = Mathf.Min(vals[i], 1);
GUIStyle s = greenStyle;
if (value < 0)
{
value = Mathf.Min(1f, -value);
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);
}
}
else if (displayValues[key].monitorDisplayType == MonitorType.bar)
{
float[] vals = ToFloatArray(displayValues[key].value);
float valsSum = 0f;
float valsCum = 0f;
foreach (float f in vals)
{
valsSum += Mathf.Max(f, 0);
}
if (valsSum == 0)
{
Debug.LogError(string.Format("The value for key {0} must be "
+ "a list or array of positive values and cannot be empty.", key));
}
else
{
for (int i = 0; i < vals.Length; i++)
{
float 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, colorStyle[i % colorStyle.Length]);
valsCum += value;
}
}
}
index++;
}
}
}
private void Initialize()
{
keyStyle = GUI.skin.label;
valueStyle = GUI.skin.label;
valueStyle.clipping = TextClipping.Overflow;
valueStyle.wordWrap = false;
barColors = new Color[6]{ Color.magenta, Color.blue, Color.cyan, Color.green, Color.yellow, Color.red };
colorStyle = new GUIStyle[barColors.Length];
for (int i = 0; i < barColors.Length; i++)
{
Texture2D texture = new Texture2D(1, 1, TextureFormat.ARGB32, false);
texture.SetPixel(0, 0, barColors[i]);
texture.Apply();
GUIStyle staticRectStyle = new GUIStyle();
staticRectStyle.normal.background = texture;
colorStyle[i] = staticRectStyle;
}
greenStyle = colorStyle[3];
redStyle = colorStyle[5];
}
}

12
unity-environment/Assets/ML-Agents/Scripts/Monitor.cs.meta


fileFormatVersion: 2
guid: e59a31a1cc2f5464d9a61bef0bc9a53b
timeCreated: 1508031727
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

183
unity-environment/Assets/ML-Agents/Scripts/AgentMonitor.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/**
* Attach this component to a game object with an Agent component in order to
* visulaize relevant information about your agent.
*/
public class AgentMonitor : MonoBehaviour
{
public bool fixedPosition;
/**< \brief If true, the monitor will be fixed in the top left corner of
* the screen. If false, it will move with the position of the agent*/
public float verticalOffset = 10f;
/**< \brief If fixedPosition is false, defines how high above the agent
* the monitor is */
[Header("Displayed Values")]
public bool DisplayBrainName = true;
/**< \brief If true, the name of the brain will be displayed in the monitor */
public bool DisplayBrainType = true;
/**< \brief If true, the type of the brain will be displayed in the monitor */
public bool DisplayFrameCount = true;
/**< \brief If true, the number of steps since the agent was reset will be displayed in the monitor */
public bool DisplayCurrentReward = true;
/**< \brief If true, the current reward of the agent will be displayed in the monitor */
public bool DisplayMaxReward = true;
/**< \brief If true, the maximum reward accros episodes will be displayed in the monitor */
public bool DisplayState = false;
/**< \brief If true, the current state of the agetn will be displayed in the monitor */
public bool DisplayAction = false;
/**< \brief If true, the current action of the agetn will be displayed in the monitor */
private Agent agent;
private Text texts;
private GameObject monitor;
private Slider slider;
private Image fill;
private float maxReward;
void Start()
{
agent = gameObject.GetComponent<Agent>();
GameObject canvas = GameObject.Find("AgentMonitorCanvas");
if (canvas == null)
{
canvas = new GameObject();
canvas.name = "AgentMonitorCanvas";
}
if (canvas.GetComponent<Canvas>() == null)
{
Canvas c = canvas.AddComponent<Canvas>();
c.renderMode = RenderMode.ScreenSpaceOverlay;
c.pixelPerfect = true;
}
if (canvas.GetComponent<CanvasScaler>() == null)
{
CanvasScaler cs = canvas.AddComponent<CanvasScaler>() as CanvasScaler;
cs.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
}
if (canvas.GetComponent<GraphicRaycaster>() == null)
{
canvas.AddComponent<GraphicRaycaster>();
}
monitor = Instantiate(Resources.Load("AgentMonitor") as GameObject);
monitor.transform.SetParent(canvas.transform, false);
slider = monitor.GetComponentInChildren<Slider>();
fill = slider.GetComponentInChildren<Image>();
texts = monitor.GetComponent<Text>();
if (fixedPosition)
{
monitor.GetComponent<RectTransform>().anchorMin = new Vector2(0, 1);
monitor.GetComponent<RectTransform>().anchorMax = new Vector2(0, 1);
monitor.GetComponent<RectTransform>().pivot = new Vector2(0, 1);
monitor.GetComponent<RectTransform>().position = new Vector3(0, monitor.GetComponent<RectTransform>().position.y, 0);
}
}
void Update()
{
if (maxReward < agent.CummulativeReward)
{
maxReward = agent.CummulativeReward;
}
texts.text = "";
if (DisplayBrainName)
{
texts.text += "Brain name : " + agent.brain.gameObject.name + "\n";
}
if (DisplayBrainType)
{
texts.text += "Mode : " + agent.brain.brainType + "\n";
}
if (DisplayFrameCount)
{
texts.text += "Frame Count :" + agent.stepCounter + "\n";
}
if (DisplayCurrentReward)
{
texts.text += "Reward : " + agent.CummulativeReward.ToString("F2") + "\n";
}
if (DisplayMaxReward)
{
texts.text += "Maximum Reward : " + maxReward.ToString("F2") + "\n";
}
if (DisplayState)
{
if (agent.brain.brainParameters.stateSpaceType == StateType.continuous)
{
texts.text += "State : ";
foreach (float f in agent.CollectState())
{
texts.text += f.ToString("F2") + " ";
}
texts.text += "\n";
}
else
{
texts.text += "State : " + ((int)agent.CollectState()[0]).ToString() + "\n";
}
}
if (DisplayAction)
{
if (agent.brain.brainParameters.actionSpaceType == StateType.continuous)
{
texts.text += "Action : ";
foreach (float f in agent.agentStoredAction)
{
texts.text += f.ToString("F2") + " ";
}
texts.text += "\n";
}
else
{
texts.text += "State : " + ((int)agent.agentStoredAction[0]).ToString() + "\n";
}
}
if (Mathf.Abs(agent.value) > slider.maxValue)
{
slider.maxValue = Mathf.Abs(agent.value);
}
slider.value = Mathf.Abs(agent.value);
if (agent.value > 0)
{
fill.color = Color.green;
}
else
{
fill.color = Color.red;
}
if (!fixedPosition)
{
Vector3 cam2obj = gameObject.transform.position - Camera.main.transform.position;
if (Vector3.Dot(cam2obj, Camera.main.transform.forward) < 0)
{
monitor.SetActive(false);
}
else
{
monitor.SetActive(true);
monitor.transform.position = Camera.main.WorldToScreenPoint(agent.transform.position + new Vector3(0, verticalOffset, 0));
monitor.transform.localScale = 20f * Mathf.Min(1, 1f / (Vector3.Dot(cam2obj, Camera.main.transform.forward))) * new Vector3(1, 1, 1);
}
}
}
void OnDestroy()
{
Destroy(monitor);
}
}

12
unity-environment/Assets/ML-Agents/Scripts/AgentMonitor.cs.meta


fileFormatVersion: 2
guid: e040eaa8759024abbbb14994dc4c55ee
timeCreated: 1502056030
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
unity-environment/Assets/ML-Agents/Resources.meta


fileFormatVersion: 2
guid: 10f3eff160a3b46fcb86042594151eae
folderAsset: yes
timeCreated: 1501551323
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存