浏览代码

Move Demonstration code to sub-folder (#3488)

/asymm-envs
GitHub 5 年前
当前提交
ecd13c8a
共有 17 个文件被更改,包括 211 次插入199 次删除
  1. 3
      com.unity.ml-agents/CHANGELOG.md
  2. 2
      com.unity.ml-agents/Editor/DemonstrationImporter.cs
  3. 17
      com.unity.ml-agents/Runtime/Agent.cs
  4. 10
      com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs
  5. 2
      com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta
  6. 2
      com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta
  7. 2
      com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs.meta
  8. 6
      com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs
  9. 8
      com.unity.ml-agents/Runtime/Demonstrations.meta
  10. 179
      com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs
  11. 179
      com.unity.ml-agents/Runtime/DemonstrationRecorder.cs
  12. 0
      /com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta
  13. 0
      /com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta
  14. 0
      /com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs.meta
  15. 0
      /com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs
  16. 0
      /com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs

3
com.unity.ml-agents/CHANGELOG.md


- The interface for `RayPerceptionSensor.PerceiveStatic()` was changed to take an input class and write to an output class.
- The checkpoint file suffix was changed from `.cptk` to `.ckpt` (#3470)
- The command-line argument used to determine the port that an environment will listen on was changed from `--port` to `--mlagents-port`.
- `DemonstrationRecorder` can now record observations outside of the editor.
- `DemonstrationRecorder` now has an optional path for the demonstrations. This will default to `Application.dataPath` if not set.
- `DemonstrationStore` was changed to accept a `Stream` for its constructor, and was renamed to `DemonstrationWriter`
- The method `GetStepCount()` on the Agent class has been replaced with the property getter `StepCount`
### Bugfixes

2
com.unity.ml-agents/Editor/DemonstrationImporter.cs


var metaDataProto = DemonstrationMetaProto.Parser.ParseDelimitedFrom(reader);
var metaData = metaDataProto.ToDemonstrationMetaData();
reader.Seek(DemonstrationStore.MetaDataBytes + 1, 0);
reader.Seek(DemonstrationWriter.MetaDataBytes + 1, 0);
var brainParamsProto = BrainParametersProto.Parser.ParseDelimitedFrom(reader);
var brainParameters = brainParamsProto.ToBrainParameters();

17
com.unity.ml-agents/Runtime/Agent.cs


ActionMasker m_ActionMasker;
/// <summary>
/// Set of DemonstrationStores that the Agent will write its step information to.
/// If you use a DemonstrationRecorder component, this will automatically register its DemonstrationStore.
/// You can also add your own DemonstrationStore by calling DemonstrationRecorder.AddDemonstrationStoreToAgent()
/// Set of DemonstrationWriters that the Agent will write its step information to.
/// If you use a DemonstrationRecorder component, this will automatically register its DemonstrationWriter.
/// You can also add your own DemonstrationWriter by calling
/// DemonstrationRecorder.AddDemonstrationWriterToAgent()
internal ISet<DemonstrationStore> DemonstrationStores = new HashSet<DemonstrationStore>();
internal ISet<DemonstrationWriter> DemonstrationWriters = new HashSet<DemonstrationWriter>();
/// <summary>
/// List of sensors used to generate observations.

void OnDisable()
{
DemonstrationStores.Clear();
DemonstrationWriters.Clear();
// If Academy.Dispose has already been called, we don't need to unregister with it.
// We don't want to even try, because this will lazily create a new Academy!

m_Brain?.RequestDecision(m_Info, sensors);
// We also have to write any to any DemonstationStores so that they get the "done" flag.
foreach(var demoWriter in DemonstrationStores)
foreach(var demoWriter in DemonstrationWriters)
{
demoWriter.Record(m_Info, sensors);
}

m_Brain.RequestDecision(m_Info, sensors);
// If we have any DemonstrationStores, write the AgentInfo and sensors to them.
foreach(var demoWriter in DemonstrationStores)
// If we have any DemonstrationWriters, write the AgentInfo and sensors to them.
foreach(var demoWriter in DemonstrationWriters)
{
demoWriter.Record(m_Info, sensors);
}

10
com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs


demoRec.record = true;
demoRec.demonstrationName = k_DemoName;
demoRec.demonstrationDirectory = k_DemoDirectory;
var demoStore = demoRec.LazyInitialize(fileSystem);
var demoWriter = demoRec.LazyInitialize(fileSystem);
Assert.IsTrue(fileSystem.Directory.Exists(k_DemoDirectory));
Assert.IsTrue(fileSystem.FileExists(k_DemoDirectory + k_DemoName + k_ExtensionType));

};
demoStore.Record(agentInfo, new System.Collections.Generic.List<ISensor>());
demoWriter.Record(agentInfo, new System.Collections.Generic.List<ISensor>());
demoStore.Close();
demoWriter.Close();
demoStore.Record(agentInfo, new System.Collections.Generic.List<ISensor>());
demoWriter.Record(agentInfo, new System.Collections.Generic.List<ISensor>());
}
public class ObservationAgent : TestAgent

// Read back the demo file and make sure observations were written
var reader = fileSystem.File.OpenRead("Assets/Demonstrations/TestBrain.demo");
reader.Seek(DemonstrationStore.MetaDataBytes + 1, 0);
reader.Seek(DemonstrationWriter.MetaDataBytes + 1, 0);
BrainParametersProto.Parser.ParseDelimitedFrom(reader);
var agentInfoProto = AgentInfoActionPairProto.Parser.ParseDelimitedFrom(reader).AgentInfo;

2
com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta


fileFormatVersion: 2
guid: b651f66c75a1646c6ab48de06d0e13ef
guid: a5e0cbcbc514b473399c262dd37541ea
MonoImporter:
externalObjects: {}
serializedVersion: 2

2
com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta


fileFormatVersion: 2
guid: 50f710d360a49461cad67ff5e6bcefe1
guid: f2902496c0120472b90269f94a0aec7e
MonoImporter:
externalObjects: {}
serializedVersion: 2

2
com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs.meta


fileFormatVersion: 2
guid: a79c7ccb2cd042b5b1e710b9588d921b
guid: ebaf7878a8cc74ee3aae07daf9e1b6f2
MonoImporter:
externalObjects: {}
serializedVersion: 2

6
com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs


/// <summary>
/// Responsible for writing demonstration data to stream (usually a file stream).
/// </summary>
public class DemonstrationStore
public class DemonstrationWriter
{
public const int MetaDataBytes = 32; // Number of bytes allocated to metadata in demo file.

WriteAdapter m_WriteAdapter = new WriteAdapter();
/// <summary>
/// Create a DemonstrationStore that will write to the specified stream.
/// Create a DemonstrationWriter that will write to the specified stream.
public DemonstrationStore(Stream stream)
public DemonstrationWriter(Stream stream)
{
m_Writer = stream;
}

8
com.unity.ml-agents/Runtime/Demonstrations.meta


fileFormatVersion: 2
guid: 85e02c21d231b4f5fa0c5f87e5f907a2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

179
com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs


using System.IO.Abstractions;
using System.Text.RegularExpressions;
using UnityEngine;
using System.IO;
namespace MLAgents
{
/// <summary>
/// Demonstration Recorder Component.
/// </summary>
[RequireComponent(typeof(Agent))]
[AddComponentMenu("ML Agents/Demonstration Recorder", (int)MenuGroup.Default)]
public class DemonstrationRecorder : MonoBehaviour
{
[Tooltip("Whether or not to record demonstrations.")]
public bool record;
[Tooltip("Base demonstration file name. Will have numbers appended to make unique.")]
public string demonstrationName;
[Tooltip("Base directory to write the demo files. If null, will use {Application.dataPath}/Demonstrations.")]
public string demonstrationDirectory;
DemonstrationWriter m_DemoWriter;
internal const int MaxNameLength = 16;
const string k_ExtensionType = ".demo";
IFileSystem m_FileSystem;
Agent m_Agent;
void OnEnable()
{
m_Agent = GetComponent<Agent>();
}
void Update()
{
if (record)
{
LazyInitialize();
}
}
/// <summary>
/// Creates demonstration store for use in recording.
/// Has no effect if the demonstration store was already created.
/// </summary>
internal DemonstrationWriter LazyInitialize(IFileSystem fileSystem = null)
{
if (m_DemoWriter != null)
{
return m_DemoWriter;
}
if (m_Agent == null)
{
m_Agent = GetComponent<Agent>();
}
m_FileSystem = fileSystem ?? new FileSystem();
var behaviorParams = GetComponent<BehaviorParameters>();
if (string.IsNullOrEmpty(demonstrationName))
{
demonstrationName = behaviorParams.behaviorName;
}
if (string.IsNullOrEmpty(demonstrationDirectory))
{
demonstrationDirectory = Path.Combine(Application.dataPath, "Demonstrations");
}
demonstrationName = SanitizeName(demonstrationName, MaxNameLength);
var filePath = MakeDemonstrationFilePath(m_FileSystem, demonstrationDirectory, demonstrationName);
var stream = m_FileSystem.File.Create(filePath);
m_DemoWriter = new DemonstrationWriter(stream);
m_DemoWriter.Initialize(
demonstrationName,
behaviorParams.brainParameters,
behaviorParams.fullyQualifiedBehaviorName
);
AddDemonstrationWriterToAgent(m_DemoWriter);
return m_DemoWriter;
}
/// <summary>
/// Removes all characters except alphanumerics from demonstration name.
/// Shorten name if it is longer than the maxNameLength.
/// </summary>
internal static string SanitizeName(string demoName, int maxNameLength)
{
var rgx = new Regex("[^a-zA-Z0-9 -]");
demoName = rgx.Replace(demoName, "");
// If the string is too long, it will overflow the metadata.
if (demoName.Length > maxNameLength)
{
demoName = demoName.Substring(0, maxNameLength);
}
return demoName;
}
/// <summary>
/// Gets a unique path for the demonstrationName in the demonstrationDirectory.
/// </summary>
/// <param name="fileSystem"></param>
/// <param name="demonstrationDirectory"></param>
/// <param name="demonstrationName"></param>
/// <returns></returns>
internal static string MakeDemonstrationFilePath(
IFileSystem fileSystem, string demonstrationDirectory, string demonstrationName
)
{
// Create the directory if it doesn't already exist
if (!fileSystem.Directory.Exists(demonstrationDirectory))
{
fileSystem.Directory.CreateDirectory(demonstrationDirectory);
}
var literalName = demonstrationName;
var filePath = Path.Combine(demonstrationDirectory, literalName + k_ExtensionType);
var uniqueNameCounter = 0;
while (fileSystem.File.Exists(filePath))
{
// TODO should we use a timestamp instead of a counter here? This loops an increasing number of times
// as the number of demos increases.
literalName = demonstrationName + "_" + uniqueNameCounter;
filePath = Path.Combine(demonstrationDirectory, literalName + k_ExtensionType);
uniqueNameCounter++;
}
return filePath;
}
/// <summary>
/// Close the DemonstrationWriter and remove it from the Agent.
/// Has no effect if the DemonstrationWriter is already closed (or wasn't opened)
/// </summary>
public void Close()
{
if (m_DemoWriter != null)
{
RemoveDemonstrationWriterFromAgent(m_DemoWriter);
m_DemoWriter.Close();
m_DemoWriter = null;
}
}
/// <summary>
/// Clean up the DemonstrationWriter when shutting down or destroying the Agent.
/// </summary>
void OnDestroy()
{
Close();
}
/// <summary>
/// Add additional DemonstrationWriter to the Agent. It is still up to the user to Close this
/// DemonstrationWriters when recording is done.
/// </summary>
/// <param name="demoWriter"></param>
public void AddDemonstrationWriterToAgent(DemonstrationWriter demoWriter)
{
m_Agent.DemonstrationWriters.Add(demoWriter);
}
/// <summary>
/// Remove additional DemonstrationWriter to the Agent. It is still up to the user to Close this
/// DemonstrationWriters when recording is done.
/// </summary>
/// <param name="demoWriter"></param>
public void RemoveDemonstrationWriterFromAgent(DemonstrationWriter demoWriter)
{
m_Agent.DemonstrationWriters.Remove(demoWriter);
}
}
}

179
com.unity.ml-agents/Runtime/DemonstrationRecorder.cs


using System.IO.Abstractions;
using System.Text.RegularExpressions;
using UnityEngine;
using System.IO;
namespace MLAgents
{
/// <summary>
/// Demonstration Recorder Component.
/// </summary>
[RequireComponent(typeof(Agent))]
[AddComponentMenu("ML Agents/Demonstration Recorder", (int)MenuGroup.Default)]
public class DemonstrationRecorder : MonoBehaviour
{
[Tooltip("Whether or not to record demonstrations.")]
public bool record;
[Tooltip("Base demonstration file name. Will have numbers appended to make unique.")]
public string demonstrationName;
[Tooltip("Base directory to write the demo files. If null, will use {Application.dataPath}/Demonstrations.")]
public string demonstrationDirectory;
DemonstrationStore m_DemoStore;
internal const int MaxNameLength = 16;
const string k_ExtensionType = ".demo";
IFileSystem m_FileSystem;
Agent m_Agent;
void OnEnable()
{
m_Agent = GetComponent<Agent>();
}
void Update()
{
if (record)
{
LazyInitialize();
}
}
/// <summary>
/// Creates demonstration store for use in recording.
/// Has no effect if the demonstration store was already created.
/// </summary>
internal DemonstrationStore LazyInitialize(IFileSystem fileSystem = null)
{
if (m_DemoStore != null)
{
return m_DemoStore;
}
if (m_Agent == null)
{
m_Agent = GetComponent<Agent>();
}
m_FileSystem = fileSystem ?? new FileSystem();
var behaviorParams = GetComponent<BehaviorParameters>();
if (string.IsNullOrEmpty(demonstrationName))
{
demonstrationName = behaviorParams.behaviorName;
}
if (string.IsNullOrEmpty(demonstrationDirectory))
{
demonstrationDirectory = Path.Combine(Application.dataPath, "Demonstrations");
}
demonstrationName = SanitizeName(demonstrationName, MaxNameLength);
var filePath = MakeDemonstrationFilePath(m_FileSystem, demonstrationDirectory, demonstrationName);
var stream = m_FileSystem.File.Create(filePath);
m_DemoStore = new DemonstrationStore(stream);
m_DemoStore.Initialize(
demonstrationName,
behaviorParams.brainParameters,
behaviorParams.fullyQualifiedBehaviorName
);
AddDemonstrationStoreToAgent(m_DemoStore);
return m_DemoStore;
}
/// <summary>
/// Removes all characters except alphanumerics from demonstration name.
/// Shorten name if it is longer than the maxNameLength.
/// </summary>
internal static string SanitizeName(string demoName, int maxNameLength)
{
var rgx = new Regex("[^a-zA-Z0-9 -]");
demoName = rgx.Replace(demoName, "");
// If the string is too long, it will overflow the metadata.
if (demoName.Length > maxNameLength)
{
demoName = demoName.Substring(0, maxNameLength);
}
return demoName;
}
/// <summary>
/// Gets a unique path for the demonstrationName in the demonstrationDirectory.
/// </summary>
/// <param name="fileSystem"></param>
/// <param name="demonstrationDirectory"></param>
/// <param name="demonstrationName"></param>
/// <returns></returns>
internal static string MakeDemonstrationFilePath(
IFileSystem fileSystem, string demonstrationDirectory, string demonstrationName
)
{
// Create the directory if it doesn't already exist
if (!fileSystem.Directory.Exists(demonstrationDirectory))
{
fileSystem.Directory.CreateDirectory(demonstrationDirectory);
}
var literalName = demonstrationName;
var filePath = Path.Combine(demonstrationDirectory, literalName + k_ExtensionType);
var uniqueNameCounter = 0;
while (fileSystem.File.Exists(filePath))
{
// TODO should we use a timestamp instead of a counter here? This loops an increasing number of times
// as the number of demos increases.
literalName = demonstrationName + "_" + uniqueNameCounter;
filePath = Path.Combine(demonstrationDirectory, literalName + k_ExtensionType);
uniqueNameCounter++;
}
return filePath;
}
/// <summary>
/// Close the DemonstrationStore and remove it from the Agent.
/// Has no effect if the DemonstrationStore is already closed (or wasn't opened)
/// </summary>
public void Close()
{
if (m_DemoStore != null)
{
RemoveDemonstrationStoreFromAgent(m_DemoStore);
m_DemoStore.Close();
m_DemoStore = null;
}
}
/// <summary>
/// Clean up the DemonstrationStore when shutting down or destroying the Agent.
/// </summary>
void OnDestroy()
{
Close();
}
/// <summary>
/// Add additional DemonstrationStore to the Agent. It is still up to the user to Close this
/// DemonstrationStores when recording is done.
/// </summary>
/// <param name="demoStore"></param>
public void AddDemonstrationStoreToAgent(DemonstrationStore demoStore)
{
m_Agent.DemonstrationStores.Add(demoStore);
}
/// <summary>
/// Remove additional DemonstrationStore to the Agent. It is still up to the user to Close this
/// DemonstrationStores when recording is done.
/// </summary>
/// <param name="demoStore"></param>
public void RemoveDemonstrationStoreFromAgent(DemonstrationStore demoStore)
{
m_Agent.DemonstrationStores.Remove(demoStore);
}
}
}

/com.unity.ml-agents/Runtime/Demonstration.cs.meta → /com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta

/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs.meta → /com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta

/com.unity.ml-agents/Runtime/DemonstrationStore.cs.meta → /com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs.meta

/com.unity.ml-agents/Runtime/DemonstrationStore.cs → /com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs

/com.unity.ml-agents/Runtime/Demonstration.cs → /com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs

正在加载...
取消
保存