From ffc6df153a0329e3eafd5d96327b7f4f98eeabd5 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Tue, 4 Feb 2020 16:13:06 -0800 Subject: [PATCH 01/19] initial cleanup --- com.unity.ml-agents/Runtime/DemonstrationRecorder.cs | 1 - com.unity.ml-agents/Runtime/DemonstrationStore.cs | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index 313cdbe8b4..725609401d 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -16,7 +16,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; diff --git a/com.unity.ml-agents/Runtime/DemonstrationStore.cs b/com.unity.ml-agents/Runtime/DemonstrationStore.cs index de1f8b2c04..d2516e2083 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationStore.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationStore.cs @@ -16,7 +16,6 @@ public class DemonstrationStore const string k_DemoDirectory = "Assets/Demonstrations/"; const string k_ExtensionType = ".demo"; - string m_FilePath; DemonstrationMetaData m_MetaData; Stream m_Writer; float m_CumulativeReward; @@ -64,16 +63,16 @@ void CreateDemonstrationFile(string demonstrationName) { // Creates demonstration file. var literalName = demonstrationName; - m_FilePath = k_DemoDirectory + literalName + k_ExtensionType; + var filePath = k_DemoDirectory + literalName + k_ExtensionType; var uniqueNameCounter = 0; - while (m_FileSystem.File.Exists(m_FilePath)) + while (m_FileSystem.File.Exists(filePath)) { literalName = demonstrationName + "_" + uniqueNameCounter; - m_FilePath = k_DemoDirectory + literalName + k_ExtensionType; + filePath = k_DemoDirectory + literalName + k_ExtensionType; uniqueNameCounter++; } - m_Writer = m_FileSystem.File.Create(m_FilePath); + m_Writer = m_FileSystem.File.Create(filePath); m_MetaData = new DemonstrationMetaData { demonstrationName = demonstrationName }; var metaProto = m_MetaData.ToProto(); metaProto.WriteDelimitedTo(m_Writer); From b22e734e8e63cd98239725bfe8ca6824bb3829d9 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Tue, 4 Feb 2020 16:35:39 -0800 Subject: [PATCH 02/19] IExpWriter --- com.unity.ml-agents/Runtime/Agent.cs | 13 ++++++++++++- .../Runtime/DemonstrationStore.cs.meta | 3 --- com.unity.ml-agents/Runtime/Demonstrations.meta | 8 ++++++++ .../{ => Demonstrations}/Demonstration.cs | 0 .../{ => Demonstrations}/Demonstration.cs.meta | 2 +- .../DemonstrationRecorder.cs | 6 ++++++ .../DemonstrationRecorder.cs.meta | 2 +- .../{ => Demonstrations}/DemonstrationStore.cs | 8 +++++++- .../Demonstrations/DemonstrationStore.cs.meta | 11 +++++++++++ .../Runtime/Demonstrations/IExperienceWriter.cs | 17 +++++++++++++++++ .../Demonstrations/IExperienceWriter.cs.meta | 11 +++++++++++ 11 files changed, 74 insertions(+), 7 deletions(-) delete mode 100644 com.unity.ml-agents/Runtime/DemonstrationStore.cs.meta create mode 100644 com.unity.ml-agents/Runtime/Demonstrations.meta rename com.unity.ml-agents/Runtime/{ => Demonstrations}/Demonstration.cs (100%) rename com.unity.ml-agents/Runtime/{ => Demonstrations}/Demonstration.cs.meta (83%) rename com.unity.ml-agents/Runtime/{ => Demonstrations}/DemonstrationRecorder.cs (94%) rename com.unity.ml-agents/Runtime/{ => Demonstrations}/DemonstrationRecorder.cs.meta (83%) rename com.unity.ml-agents/Runtime/{ => Demonstrations}/DemonstrationStore.cs (94%) create mode 100644 com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs.meta create mode 100644 com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs create mode 100644 com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs.meta diff --git a/com.unity.ml-agents/Runtime/Agent.cs b/com.unity.ml-agents/Runtime/Agent.cs index fbd0cdc425..708f43d74d 100644 --- a/com.unity.ml-agents/Runtime/Agent.cs +++ b/com.unity.ml-agents/Runtime/Agent.cs @@ -493,9 +493,10 @@ void SendInfoToBrain() m_Brain.RequestDecision(m_Info, sensors); + // TODO simplify, only check if m_Recorder.GetExperienceWriter() exists if (m_Recorder != null && m_Recorder.record && Application.isEditor) { - m_Recorder.WriteExperience(m_Info, sensors); + WriteExperience(m_Recorder.GetExperienceWriter()); } } @@ -507,6 +508,16 @@ void UpdateSensors() } } + public void WriteExperience(IExperienceWriter writer) + { + ExperienceInfo expInfo = new ExperienceInfo + { + agentInfo = m_Info, + sensors = sensors + }; + writer.Record(expInfo); + } + /// /// Collects the (vector, visual) observations of the agent. /// The agent observation describes the current environment from the diff --git a/com.unity.ml-agents/Runtime/DemonstrationStore.cs.meta b/com.unity.ml-agents/Runtime/DemonstrationStore.cs.meta deleted file mode 100644 index 289d71f7d6..0000000000 --- a/com.unity.ml-agents/Runtime/DemonstrationStore.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: a79c7ccb2cd042b5b1e710b9588d921b -timeCreated: 1537388072 \ No newline at end of file diff --git a/com.unity.ml-agents/Runtime/Demonstrations.meta b/com.unity.ml-agents/Runtime/Demonstrations.meta new file mode 100644 index 0000000000..58b5700e49 --- /dev/null +++ b/com.unity.ml-agents/Runtime/Demonstrations.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d42515de33de041a5aca67c9c5043c91 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.ml-agents/Runtime/Demonstration.cs b/com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs similarity index 100% rename from com.unity.ml-agents/Runtime/Demonstration.cs rename to com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs diff --git a/com.unity.ml-agents/Runtime/Demonstration.cs.meta b/com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta similarity index 83% rename from com.unity.ml-agents/Runtime/Demonstration.cs.meta rename to com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta index be8bd24baf..86ec8ffda8 100644 --- a/com.unity.ml-agents/Runtime/Demonstration.cs.meta +++ b/com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: b651f66c75a1646c6ab48de06d0e13ef +guid: 8cb2be2647c864cbd886663a1646181a MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs similarity index 94% rename from com.unity.ml-agents/Runtime/DemonstrationRecorder.cs rename to com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs index 725609401d..54bdd37781 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs @@ -72,6 +72,7 @@ public static string SanitizeName(string demoName, int maxNameLength) /// public void WriteExperience(AgentInfo info, List sensors) { + // TODO remove, all writing goes through the IExperienceWriter m_DemoStore.Record(info, sensors); } @@ -94,5 +95,10 @@ void OnApplicationQuit() Close(); } } + + public IExperienceWriter GetExperienceWriter() + { + return m_DemoStore; + } } } diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs.meta b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta similarity index 83% rename from com.unity.ml-agents/Runtime/DemonstrationRecorder.cs.meta rename to com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta index efd60bab6a..891f608de5 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs.meta +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 50f710d360a49461cad67ff5e6bcefe1 +guid: 297c27f32f1254a0d8eb445bd9fd07c7 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.ml-agents/Runtime/DemonstrationStore.cs b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs similarity index 94% rename from com.unity.ml-agents/Runtime/DemonstrationStore.cs rename to com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs index d2516e2083..b8c6606ff6 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationStore.cs +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs @@ -9,7 +9,7 @@ namespace MLAgents /// /// Responsible for writing demonstration data to file. /// - public class DemonstrationStore + public class DemonstrationStore : IExperienceWriter { public const int MetaDataBytes = 32; // Number of bytes allocated to metadata in demo file. readonly IFileSystem m_FileSystem; @@ -23,6 +23,7 @@ public class DemonstrationStore public DemonstrationStore(IFileSystem fileSystem) { + // TODO move all file logic to component, only take a Stream here if (fileSystem != null) { m_FileSystem = fileSystem; @@ -112,6 +113,11 @@ public void Record(AgentInfo info, List sensors) agentProto.WriteDelimitedTo(m_Writer); } + public void Record(ExperienceInfo expInfo) + { + Record(expInfo.agentInfo, expInfo.sensors); + } + /// /// Performs all clean-up necessary /// diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs.meta b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs.meta new file mode 100644 index 0000000000..63466d74bb --- /dev/null +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2240b3886ad57476fa0ec68df1e56f05 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs b/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs new file mode 100644 index 0000000000..f077293bfb --- /dev/null +++ b/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using MLAgents.Sensor; + +namespace MLAgents +{ + public struct ExperienceInfo + { + public AgentInfo agentInfo; + public List sensors; + } + + public interface IExperienceWriter + { + // TODO Start() and Stop() + void Record(ExperienceInfo expInfo); + } +} diff --git a/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs.meta b/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs.meta new file mode 100644 index 0000000000..d007e34f55 --- /dev/null +++ b/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d38e34fe149994fdfb7c3b0c63455d83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 2a41bf498a2197bbabf4602638188af9f8662b82 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Tue, 4 Feb 2020 17:51:19 -0800 Subject: [PATCH 03/19] fs code to recorder, use dataPath, dont require editor --- com.unity.ml-agents/Runtime/Agent.cs | 2 +- .../Demonstrations/DemonstrationRecorder.cs | 89 ++++++++++++++++--- .../Demonstrations/DemonstrationStore.cs | 68 +++----------- .../Runtime/Policy/BehaviorParameters.cs | 1 + .../Tests/Editor/DemonstrationTests.cs | 34 ++++--- 5 files changed, 112 insertions(+), 82 deletions(-) diff --git a/com.unity.ml-agents/Runtime/Agent.cs b/com.unity.ml-agents/Runtime/Agent.cs index 708f43d74d..224a18d13a 100644 --- a/com.unity.ml-agents/Runtime/Agent.cs +++ b/com.unity.ml-agents/Runtime/Agent.cs @@ -494,7 +494,7 @@ void SendInfoToBrain() m_Brain.RequestDecision(m_Info, sensors); // TODO simplify, only check if m_Recorder.GetExperienceWriter() exists - if (m_Recorder != null && m_Recorder.record && Application.isEditor) + if (m_Recorder != null && m_Recorder.record) { WriteExperience(m_Recorder.GetExperienceWriter()); } diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs index 54bdd37781..9365321ca8 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs @@ -2,6 +2,7 @@ using System.Text.RegularExpressions; using UnityEngine; using System.Collections.Generic; +using System.IO; using MLAgents.Sensor; namespace MLAgents @@ -9,19 +10,28 @@ namespace MLAgents /// /// Demonstration Recorder Component. /// - [RequireComponent(typeof(Agent))] + //[RequireComponent(typeof(BehaviorParameters))] [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; - Agent m_RecordingAgent; + + [Tooltip("Base directory to write the demo files. If null, will use {Application.dataPath}/Demonstrations.")] + public string demoDirectory; + DemonstrationStore m_DemoStore; public const int MaxNameLength = 16; + const string k_ExtensionType = ".demo"; + IFileSystem m_FileSystem; + void Start() { - if (Application.isEditor && record) + if (record) { InitializeDemoStore(); } @@ -29,7 +39,7 @@ void Start() void Update() { - if (Application.isEditor && record && m_DemoStore == null) + if (record && m_DemoStore == null) { InitializeDemoStore(); } @@ -40,22 +50,45 @@ void Update() /// public void InitializeDemoStore(IFileSystem fileSystem = null) { - m_RecordingAgent = GetComponent(); - m_DemoStore = new DemonstrationStore(fileSystem); - var behaviorParams = GetComponent(); + if (m_DemoStore != null) + { + return; + } + + if (fileSystem != null) + { + m_FileSystem = fileSystem; + } + else + { + m_FileSystem = new FileSystem(); + } + + if (string.IsNullOrEmpty(demoDirectory)) + { + demoDirectory = Path.Combine(Application.dataPath, "Demonstrations"); + } + demonstrationName = SanitizeName(demonstrationName, MaxNameLength); + CreateDirectory(); + var stream = CreateDemonstrationFile(demonstrationName); + m_DemoStore = new DemonstrationStore(stream); + + var recordingAgent = GetComponent(); + var behaviorParams = GetComponent(); m_DemoStore.Initialize( demonstrationName, behaviorParams.brainParameters, - behaviorParams.fullyQualifiedBehaviorName); - Monitor.Log("Recording Demonstration of Agent: ", m_RecordingAgent.name); + behaviorParams.fullyQualifiedBehaviorName + ); + Monitor.Log("Recording Demonstration of Agent: ", recordingAgent?.name); } /// /// Removes all characters except alphanumerics from demonstration name. /// Shorten name if it is longer than the maxNameLength. /// - public static string SanitizeName(string demoName, int maxNameLength) + internal static string SanitizeName(string demoName, int maxNameLength) { var rgx = new Regex("[^a-zA-Z0-9 -]"); demoName = rgx.Replace(demoName, ""); @@ -67,6 +100,37 @@ public static string SanitizeName(string demoName, int maxNameLength) return demoName; } + /// + /// Checks for the existence of the Demonstrations directory + /// and creates it if it does not exist. + /// + void CreateDirectory() + { + if (!m_FileSystem.Directory.Exists(demoDirectory)) + { + m_FileSystem.Directory.CreateDirectory(demoDirectory); + } + } + + /// + /// Creates demonstration file and returns a Stream to it. + /// + Stream CreateDemonstrationFile(string demonstrationName) + { + // Creates demonstration file. + var literalName = demonstrationName; + var filePath = Path.Combine(demoDirectory, literalName + k_ExtensionType); + var uniqueNameCounter = 0; + while (m_FileSystem.File.Exists(filePath)) + { + literalName = demonstrationName + "_" + uniqueNameCounter; + filePath = Path.Combine(demoDirectory, literalName + k_ExtensionType); + uniqueNameCounter++; + } + + return m_FileSystem.File.Create(filePath); + } + /// /// Forwards AgentInfo to Demonstration Store. /// @@ -90,10 +154,7 @@ public void Close() /// void OnApplicationQuit() { - if (Application.isEditor && record) - { - Close(); - } + Close(); } public IExperienceWriter GetExperienceWriter() diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs index b8c6606ff6..7d91f70f90 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs @@ -12,26 +12,15 @@ namespace MLAgents public class DemonstrationStore : IExperienceWriter { public const int MetaDataBytes = 32; // Number of bytes allocated to metadata in demo file. - readonly IFileSystem m_FileSystem; - const string k_DemoDirectory = "Assets/Demonstrations/"; - const string k_ExtensionType = ".demo"; DemonstrationMetaData m_MetaData; Stream m_Writer; float m_CumulativeReward; WriteAdapter m_WriteAdapter = new WriteAdapter(); - public DemonstrationStore(IFileSystem fileSystem) + public DemonstrationStore(Stream stream) { - // TODO move all file logic to component, only take a Stream here - if (fileSystem != null) - { - m_FileSystem = fileSystem; - } - else - { - m_FileSystem = new FileSystem(); - } + m_Writer = stream; } /// @@ -40,42 +29,23 @@ public DemonstrationStore(IFileSystem fileSystem) public void Initialize( string demonstrationName, BrainParameters brainParameters, string brainName) { - CreateDirectory(); - CreateDemonstrationFile(demonstrationName); - WriteBrainParameters(brainName, brainParameters); - } + m_MetaData = new DemonstrationMetaData { demonstrationName = demonstrationName }; + var metaProto = m_MetaData.ToProto(); + metaProto.WriteDelimitedTo(m_Writer); - /// - /// Checks for the existence of the Demonstrations directory - /// and creates it if it does not exist. - /// - void CreateDirectory() - { - if (!m_FileSystem.Directory.Exists(k_DemoDirectory)) - { - m_FileSystem.Directory.CreateDirectory(k_DemoDirectory); - } + WriteBrainParameters(brainName, brainParameters); } /// - /// Creates demonstration file. + /// Writes meta-data. Note that this is called at the *end* of recording, but writes to the + /// beginning of the file. /// - void CreateDemonstrationFile(string demonstrationName) + void WriteMetadata() { - // Creates demonstration file. - var literalName = demonstrationName; - var filePath = k_DemoDirectory + literalName + k_ExtensionType; - var uniqueNameCounter = 0; - while (m_FileSystem.File.Exists(filePath)) - { - literalName = demonstrationName + "_" + uniqueNameCounter; - filePath = k_DemoDirectory + literalName + k_ExtensionType; - uniqueNameCounter++; - } - - m_Writer = m_FileSystem.File.Create(filePath); - m_MetaData = new DemonstrationMetaData { demonstrationName = demonstrationName }; var metaProto = m_MetaData.ToProto(); + var metaProtoBytes = metaProto.ToByteArray(); + m_Writer.Write(metaProtoBytes, 0, metaProtoBytes.Length); + m_Writer.Seek(0, 0); metaProto.WriteDelimitedTo(m_Writer); } @@ -93,7 +63,7 @@ void WriteBrainParameters(string brainName, BrainParameters brainParameters) /// /// Write AgentInfo experience to file. /// - public void Record(AgentInfo info, List sensors) + internal void Record(AgentInfo info, List sensors) { // Increment meta-data counters. m_MetaData.numberExperiences++; @@ -137,16 +107,6 @@ void EndEpisode() m_MetaData.numberEpisodes += 1; } - /// - /// Writes meta-data. - /// - void WriteMetadata() - { - var metaProto = m_MetaData.ToProto(); - var metaProtoBytes = metaProto.ToByteArray(); - m_Writer.Write(metaProtoBytes, 0, metaProtoBytes.Length); - m_Writer.Seek(0, 0); - metaProto.WriteDelimitedTo(m_Writer); - } + } } diff --git a/com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs b/com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs index e2619ef7f7..ade6fbcf22 100644 --- a/com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs +++ b/com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs @@ -56,6 +56,7 @@ public bool useChildSensors public string behaviorName { get { return m_BehaviorName; } + set { m_BehaviorName = value; } } /// diff --git a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs index df0bde9ac1..35320c293d 100644 --- a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs +++ b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs @@ -37,20 +37,23 @@ public void TestSanitization() public void TestStoreInitalize() { var fileSystem = new MockFileSystem(); - var demoStore = new DemonstrationStore(fileSystem); - Assert.IsFalse(fileSystem.Directory.Exists(k_DemoDirecory)); + var gameobj = new GameObject("gameObj"); - var brainParameters = new BrainParameters - { - vectorObservationSize = 3, - numStackedVectorObservations = 2, - vectorActionDescriptions = new[] { "TestActionA", "TestActionB" }, - vectorActionSize = new[] { 2, 2 }, - vectorActionSpaceType = SpaceType.Discrete - }; + var bp = gameobj.AddComponent(); + bp.brainParameters.vectorObservationSize = 3; + bp.brainParameters.numStackedVectorObservations = 2; + bp.brainParameters.vectorActionDescriptions = new[] { "TestActionA", "TestActionB" }; + bp.brainParameters.vectorActionSize = new[] { 2, 2 }; + bp.brainParameters.vectorActionSpaceType = SpaceType.Discrete; + bp.behaviorName = "TestBrain"; - demoStore.Initialize(k_DemoName, brainParameters, "TestBrain"); + Assert.IsFalse(fileSystem.Directory.Exists(k_DemoDirecory)); + + var demoRec = gameobj.AddComponent(); + demoRec.record = true; + demoRec.demonstrationName = k_DemoName; + demoRec.InitializeDemoStore(fileSystem); Assert.IsTrue(fileSystem.Directory.Exists(k_DemoDirecory)); Assert.IsTrue(fileSystem.FileExists(k_DemoDirecory + k_DemoName + k_ExtensionType)); @@ -65,8 +68,13 @@ public void TestStoreInitalize() storedVectorActions = new[] { 0f, 1f }, }; - demoStore.Record(agentInfo, new System.Collections.Generic.List()); - demoStore.Close(); + var expInfo = new ExperienceInfo + { + agentInfo = agentInfo, + sensors = new System.Collections.Generic.List() + }; + demoRec.GetExperienceWriter().Record(expInfo); + demoRec.Close(); } public class ObservationAgent : TestAgent From 9890f1607940e41bf28baa11200ae6b7bb5e83c4 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Tue, 4 Feb 2020 18:15:54 -0800 Subject: [PATCH 04/19] cleanup --- .../Runtime/Demonstrations/DemonstrationRecorder.cs | 2 +- .../Runtime/Demonstrations/DemonstrationStore.cs | 11 +++++++---- .../Runtime/Demonstrations/IExperienceWriter.cs | 4 +++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs index 9365321ca8..ca4f1db001 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs @@ -39,7 +39,7 @@ void Start() void Update() { - if (record && m_DemoStore == null) + if (record) { InitializeDemoStore(); } diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs index 7d91f70f90..09d1344cc6 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs @@ -7,7 +7,7 @@ namespace MLAgents { /// - /// Responsible for writing demonstration data to file. + /// Responsible for writing demonstration data to stream (usually a file stream). /// public class DemonstrationStore : IExperienceWriter { @@ -18,13 +18,18 @@ public class DemonstrationStore : IExperienceWriter float m_CumulativeReward; WriteAdapter m_WriteAdapter = new WriteAdapter(); + /// + /// Create a DemonstrationStore that will write to the specified stream. + /// The stream must support writes and seeking. + /// + /// public DemonstrationStore(Stream stream) { m_Writer = stream; } /// - /// Initializes the Demonstration Store, and writes initial data. + /// Writes the initial data to the stream. /// public void Initialize( string demonstrationName, BrainParameters brainParameters, string brainName) @@ -106,7 +111,5 @@ void EndEpisode() { m_MetaData.numberEpisodes += 1; } - - } } diff --git a/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs b/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs index f077293bfb..587b5340e1 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs +++ b/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs @@ -11,7 +11,9 @@ public struct ExperienceInfo public interface IExperienceWriter { - // TODO Start() and Stop() + void Initialize(string demonstrationName, BrainParameters brainParameters, string brainName); void Record(ExperienceInfo expInfo); + // TODO implement IDisposable and rename to Dispose? + void Close(); } } From df372775dbaf27a91c381957e31257bc7ead3f9c Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Tue, 4 Feb 2020 18:23:42 -0800 Subject: [PATCH 05/19] more cleanup --- .../Demonstrations/DemonstrationRecorder.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs index ca4f1db001..d591ce0395 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs @@ -10,7 +10,7 @@ namespace MLAgents /// /// Demonstration Recorder Component. /// - //[RequireComponent(typeof(BehaviorParameters))] + [RequireComponent(typeof(BehaviorParameters))] [AddComponentMenu("ML Agents/Demonstration Recorder", (int)MenuGroup.Default)] public class DemonstrationRecorder : MonoBehaviour { @@ -55,15 +55,12 @@ public void InitializeDemoStore(IFileSystem fileSystem = null) return; } - if (fileSystem != null) - { - m_FileSystem = fileSystem; - } - else + m_FileSystem = fileSystem ?? new FileSystem(); + var behaviorParams = GetComponent(); + if (string.IsNullOrEmpty(demonstrationName)) { - m_FileSystem = new FileSystem(); + demonstrationName = behaviorParams.behaviorName; } - if (string.IsNullOrEmpty(demoDirectory)) { demoDirectory = Path.Combine(Application.dataPath, "Demonstrations"); @@ -74,13 +71,12 @@ public void InitializeDemoStore(IFileSystem fileSystem = null) var stream = CreateDemonstrationFile(demonstrationName); m_DemoStore = new DemonstrationStore(stream); - var recordingAgent = GetComponent(); - var behaviorParams = GetComponent(); m_DemoStore.Initialize( demonstrationName, behaviorParams.brainParameters, behaviorParams.fullyQualifiedBehaviorName ); + var recordingAgent = GetComponent(); Monitor.Log("Recording Demonstration of Agent: ", recordingAgent?.name); } From cf113103b18ec91cabf990f648859936809dd1f3 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Tue, 11 Feb 2020 14:17:59 -0800 Subject: [PATCH 06/19] move out of subdir --- .../Runtime/{Demonstrations => }/Demonstration.cs | 0 .../Runtime/{Demonstrations => }/Demonstration.cs.meta | 2 +- .../Runtime/{Demonstrations => }/DemonstrationRecorder.cs | 0 .../Runtime/{Demonstrations => }/DemonstrationRecorder.cs.meta | 2 +- .../Runtime/{Demonstrations => }/DemonstrationStore.cs | 0 .../Runtime/{Demonstrations => }/DemonstrationStore.cs.meta | 2 +- .../Runtime/{Demonstrations => }/IExperienceWriter.cs | 0 .../Runtime/{Demonstrations => }/IExperienceWriter.cs.meta | 2 +- 8 files changed, 4 insertions(+), 4 deletions(-) rename com.unity.ml-agents/Runtime/{Demonstrations => }/Demonstration.cs (100%) rename com.unity.ml-agents/Runtime/{Demonstrations => }/Demonstration.cs.meta (83%) rename com.unity.ml-agents/Runtime/{Demonstrations => }/DemonstrationRecorder.cs (100%) rename com.unity.ml-agents/Runtime/{Demonstrations => }/DemonstrationRecorder.cs.meta (83%) rename com.unity.ml-agents/Runtime/{Demonstrations => }/DemonstrationStore.cs (100%) rename com.unity.ml-agents/Runtime/{Demonstrations => }/DemonstrationStore.cs.meta (83%) rename com.unity.ml-agents/Runtime/{Demonstrations => }/IExperienceWriter.cs (100%) rename com.unity.ml-agents/Runtime/{Demonstrations => }/IExperienceWriter.cs.meta (83%) diff --git a/com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs b/com.unity.ml-agents/Runtime/Demonstration.cs similarity index 100% rename from com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs rename to com.unity.ml-agents/Runtime/Demonstration.cs diff --git a/com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta b/com.unity.ml-agents/Runtime/Demonstration.cs.meta similarity index 83% rename from com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta rename to com.unity.ml-agents/Runtime/Demonstration.cs.meta index 86ec8ffda8..be8bd24baf 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/Demonstration.cs.meta +++ b/com.unity.ml-agents/Runtime/Demonstration.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8cb2be2647c864cbd886663a1646181a +guid: b651f66c75a1646c6ab48de06d0e13ef MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs similarity index 100% rename from com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs rename to com.unity.ml-agents/Runtime/DemonstrationRecorder.cs diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs.meta similarity index 83% rename from com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta rename to com.unity.ml-agents/Runtime/DemonstrationRecorder.cs.meta index 891f608de5..efd60bab6a 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationRecorder.cs.meta +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 297c27f32f1254a0d8eb445bd9fd07c7 +guid: 50f710d360a49461cad67ff5e6bcefe1 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs b/com.unity.ml-agents/Runtime/DemonstrationStore.cs similarity index 100% rename from com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs rename to com.unity.ml-agents/Runtime/DemonstrationStore.cs diff --git a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs.meta b/com.unity.ml-agents/Runtime/DemonstrationStore.cs.meta similarity index 83% rename from com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs.meta rename to com.unity.ml-agents/Runtime/DemonstrationStore.cs.meta index 63466d74bb..1e613fccf3 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/DemonstrationStore.cs.meta +++ b/com.unity.ml-agents/Runtime/DemonstrationStore.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2240b3886ad57476fa0ec68df1e56f05 +guid: a79c7ccb2cd042b5b1e710b9588d921b MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs b/com.unity.ml-agents/Runtime/IExperienceWriter.cs similarity index 100% rename from com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs rename to com.unity.ml-agents/Runtime/IExperienceWriter.cs diff --git a/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs.meta b/com.unity.ml-agents/Runtime/IExperienceWriter.cs.meta similarity index 83% rename from com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs.meta rename to com.unity.ml-agents/Runtime/IExperienceWriter.cs.meta index d007e34f55..cc73a8fa83 100644 --- a/com.unity.ml-agents/Runtime/Demonstrations/IExperienceWriter.cs.meta +++ b/com.unity.ml-agents/Runtime/IExperienceWriter.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d38e34fe149994fdfb7c3b0c63455d83 +guid: 3e9a1875ec9dc4d0fa654c774e1515ab MonoImporter: externalObjects: {} serializedVersion: 2 From 670ed47084470f20dc57673a381df68cdd59b3c9 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Wed, 12 Feb 2020 16:22:07 -0800 Subject: [PATCH 07/19] remove stray meta --- com.unity.ml-agents/Runtime/Demonstrations.meta | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 com.unity.ml-agents/Runtime/Demonstrations.meta diff --git a/com.unity.ml-agents/Runtime/Demonstrations.meta b/com.unity.ml-agents/Runtime/Demonstrations.meta deleted file mode 100644 index 58b5700e49..0000000000 --- a/com.unity.ml-agents/Runtime/Demonstrations.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d42515de33de041a5aca67c9c5043c91 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: From 1e13dcd004c44e183de9b928ae44f511a5d67152 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Wed, 12 Feb 2020 17:56:18 -0800 Subject: [PATCH 08/19] Agent keeps a set of DemoStores now --- .../ProjectSettings/GraphicsSettings.asset | 3 + .../UnityConnectSettings.asset | 2 +- com.unity.ml-agents/Runtime/Agent.cs | 30 ++++---- .../Runtime/DemonstrationRecorder.cs | 76 +++++++++---------- .../Runtime/DemonstrationStore.cs | 13 ++-- .../Runtime/IExperienceWriter.cs | 18 ----- .../Runtime/IExperienceWriter.cs.meta | 11 --- .../Runtime/Policy/BehaviorParameters.cs | 1 - .../Tests/Editor/DemonstrationTests.cs | 21 +++-- 9 files changed, 72 insertions(+), 103 deletions(-) delete mode 100644 com.unity.ml-agents/Runtime/IExperienceWriter.cs delete mode 100644 com.unity.ml-agents/Runtime/IExperienceWriter.cs.meta diff --git a/Project/ProjectSettings/GraphicsSettings.asset b/Project/ProjectSettings/GraphicsSettings.asset index b23b253ee8..4c3961c4ea 100644 --- a/Project/ProjectSettings/GraphicsSettings.asset +++ b/Project/ProjectSettings/GraphicsSettings.asset @@ -36,6 +36,9 @@ GraphicsSettings: - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} m_PreloadedShaders: [] m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} diff --git a/Project/ProjectSettings/UnityConnectSettings.asset b/Project/ProjectSettings/UnityConnectSettings.asset index fa0b146579..c3ae9a0208 100644 --- a/Project/ProjectSettings/UnityConnectSettings.asset +++ b/Project/ProjectSettings/UnityConnectSettings.asset @@ -4,7 +4,7 @@ UnityConnectSettings: m_ObjectHideFlags: 0 serializedVersion: 1 - m_Enabled: 0 + m_Enabled: 1 m_TestMode: 0 m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events m_EventUrl: https://cdp.cloud.unity3d.com/v1/events diff --git a/com.unity.ml-agents/Runtime/Agent.cs b/com.unity.ml-agents/Runtime/Agent.cs index f52aef2600..15f420111e 100644 --- a/com.unity.ml-agents/Runtime/Agent.cs +++ b/com.unity.ml-agents/Runtime/Agent.cs @@ -10,7 +10,7 @@ namespace MLAgents /// Struct that contains all the information for an Agent, including its /// observations, actions and current status, that is sent to the Brain. /// - public struct AgentInfo + internal struct AgentInfo { /// /// Keeps track of the last vector action taken by the Brain. @@ -145,7 +145,6 @@ public abstract class Agent : MonoBehaviour /// Whether or not the agent requests a decision. bool m_RequestDecision; - /// Keeps track of the number of steps taken by the agent in this episode. /// Note that this value is different for each agent, and may not overlap /// with the step counter in the Academy, since agents reset based on @@ -168,6 +167,14 @@ public abstract class Agent : MonoBehaviour /// DemonstrationRecorder m_Recorder; + /// + /// 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 DemonstrationStores; the Agent is not responsible for creating or closing the + /// stores, only opening them. + /// + public ISet DemonstrationStores = new HashSet(); + /// /// List of sensors used to generate observations. /// Currently generated from attached SensorComponents, and a legacy VectorSensor @@ -199,8 +206,6 @@ public void LazyInitialize() // Grab the "static" properties for the Agent. m_EpisodeId = EpisodeIdCounter.GetEpisodeId(); m_PolicyFactory = GetComponent(); - m_Recorder = GetComponent(); - m_Info = new AgentInfo(); m_Action = new AgentAction(); @@ -221,6 +226,8 @@ public void LazyInitialize() /// becomes disabled or inactive. void OnDisable() { + DemonstrationStores.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! if (Academy.IsInitialized) @@ -491,10 +498,10 @@ void SendInfoToBrain() m_Brain.RequestDecision(m_Info, sensors); - // TODO simplify, only check if m_Recorder.GetExperienceWriter() exists - if (m_Recorder != null && m_Recorder.record) + // If we have any DemonstrationStores, write the AgentInfo and sensors to them. + foreach(var demoWriter in DemonstrationStores) { - WriteExperience(m_Recorder.GetExperienceWriter()); + demoWriter.Record(m_Info, sensors); } } @@ -506,15 +513,6 @@ void UpdateSensors() } } - public void WriteExperience(IExperienceWriter writer) - { - ExperienceInfo expInfo = new ExperienceInfo - { - agentInfo = m_Info, - sensors = sensors - }; - writer.Record(expInfo); - } /// /// Collects the vector observations of the agent. diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index 997bd2df0f..a9ebb86051 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -9,7 +9,7 @@ namespace MLAgents /// /// Demonstration Recorder Component. /// - [RequireComponent(typeof(BehaviorParameters))] + [RequireComponent(typeof(Agent))] [AddComponentMenu("ML Agents/Demonstration Recorder", (int)MenuGroup.Default)] public class DemonstrationRecorder : MonoBehaviour { @@ -22,20 +22,12 @@ public class DemonstrationRecorder : MonoBehaviour [Tooltip("Base directory to write the demo files. If null, will use {Application.dataPath}/Demonstrations.")] public string demoDirectory; - DemonstrationStore m_DemoStore; - public const int MaxNameLength = 16; + internal DemonstrationStore m_DemoStore; + internal const int MaxNameLength = 16; const string k_ExtensionType = ".demo"; IFileSystem m_FileSystem; - void Start() - { - if (record) - { - InitializeDemoStore(); - } - } - void Update() { if (record) @@ -47,7 +39,7 @@ void Update() /// /// Creates demonstration store for use in recording. /// - public void InitializeDemoStore(IFileSystem fileSystem = null) + internal void InitializeDemoStore(IFileSystem fileSystem = null) { if (m_DemoStore != null) { @@ -66,8 +58,8 @@ public void InitializeDemoStore(IFileSystem fileSystem = null) } demonstrationName = SanitizeName(demonstrationName, MaxNameLength); - CreateDirectory(); - var stream = CreateDemonstrationFile(demonstrationName); + var filePath = MakeDemonstrationFilePath(m_FileSystem, demoDirectory, demonstrationName); + var stream = m_FileSystem.File.Create(filePath); m_DemoStore = new DemonstrationStore(stream); m_DemoStore.Initialize( @@ -75,6 +67,12 @@ public void InitializeDemoStore(IFileSystem fileSystem = null) behaviorParams.brainParameters, behaviorParams.fullyQualifiedBehaviorName ); + + var agent = GetComponent(); + if (agent != null) + { + agent.DemonstrationStores.Add(m_DemoStore); + } } /// @@ -94,65 +92,63 @@ internal static string SanitizeName(string demoName, int maxNameLength) } /// - /// Checks for the existence of the Demonstrations directory - /// and creates it if it does not exist. + /// Gets a unique path for the demonstrationName in the demoDirectory. /// - void CreateDirectory() + /// + /// + /// + /// + internal static string MakeDemonstrationFilePath( + IFileSystem fileSystem, string demoDirectory, string demonstrationName + ) { - if (!m_FileSystem.Directory.Exists(demoDirectory)) + // Create the directory if it doesn't already exist + if (!fileSystem.Directory.Exists(demoDirectory)) { - m_FileSystem.Directory.CreateDirectory(demoDirectory); + fileSystem.Directory.CreateDirectory(demoDirectory); } - } - /// - /// Creates demonstration file and returns a Stream to it. - /// - Stream CreateDemonstrationFile(string demonstrationName) - { - // Creates demonstration file. var literalName = demonstrationName; var filePath = Path.Combine(demoDirectory, literalName + k_ExtensionType); var uniqueNameCounter = 0; - while (m_FileSystem.File.Exists(filePath)) + 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(demoDirectory, literalName + k_ExtensionType); uniqueNameCounter++; } - return m_FileSystem.File.Create(filePath); + return filePath; } /// - /// Forwards AgentInfo to Demonstration Store. + /// Close the DemonstrationStore and remove it from the Agent. + /// Has no effect if the DemonstrationStore is already closed (or wasn't opened) /// - public void WriteExperience(AgentInfo info, List sensors) - { - // TODO remove, all writing goes through the IExperienceWriter - m_DemoStore.Record(info, sensors); - } - public void Close() { if (m_DemoStore != null) { + var agent = GetComponent(); + if (agent != null) + { + agent.DemonstrationStores.Remove(m_DemoStore); + } + m_DemoStore.Close(); m_DemoStore = null; } } /// - /// Closes Demonstration store. + /// Clean up the DemonstrationStore when shutting down. /// void OnApplicationQuit() { Close(); } - public IExperienceWriter GetExperienceWriter() - { - return m_DemoStore; - } } } diff --git a/com.unity.ml-agents/Runtime/DemonstrationStore.cs b/com.unity.ml-agents/Runtime/DemonstrationStore.cs index 19736c32c9..400b5871b6 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationStore.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationStore.cs @@ -8,7 +8,7 @@ namespace MLAgents /// /// Responsible for writing demonstration data to stream (usually a file stream). /// - public class DemonstrationStore : IExperienceWriter + public class DemonstrationStore { public const int MetaDataBytes = 32; // Number of bytes allocated to metadata in demo file. @@ -87,20 +87,23 @@ internal void Record(AgentInfo info, List sensors) agentProto.WriteDelimitedTo(m_Writer); } - public void Record(ExperienceInfo expInfo) - { - Record(expInfo.agentInfo, expInfo.sensors); - } /// /// Performs all clean-up necessary /// public void Close() { + if (m_Writer == null) + { + // Already closed + return; + } + EndEpisode(); m_MetaData.meanReward = m_CumulativeReward / m_MetaData.numberEpisodes; WriteMetadata(); m_Writer.Close(); + m_Writer = null; } /// diff --git a/com.unity.ml-agents/Runtime/IExperienceWriter.cs b/com.unity.ml-agents/Runtime/IExperienceWriter.cs deleted file mode 100644 index 08c824b55a..0000000000 --- a/com.unity.ml-agents/Runtime/IExperienceWriter.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; - -namespace MLAgents -{ - public struct ExperienceInfo - { - public AgentInfo agentInfo; - public List sensors; - } - - public interface IExperienceWriter - { - void Initialize(string demonstrationName, BrainParameters brainParameters, string brainName); - void Record(ExperienceInfo expInfo); - // TODO implement IDisposable and rename to Dispose? - void Close(); - } -} diff --git a/com.unity.ml-agents/Runtime/IExperienceWriter.cs.meta b/com.unity.ml-agents/Runtime/IExperienceWriter.cs.meta deleted file mode 100644 index cc73a8fa83..0000000000 --- a/com.unity.ml-agents/Runtime/IExperienceWriter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3e9a1875ec9dc4d0fa654c774e1515ab -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs b/com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs index 0633ba2b01..5e651be866 100644 --- a/com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs +++ b/com.unity.ml-agents/Runtime/Policy/BehaviorParameters.cs @@ -57,7 +57,6 @@ public bool useChildSensors public string behaviorName { get { return m_BehaviorName; } - set { m_BehaviorName = value; } } /// diff --git a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs index ffd51d3d52..0535e3c86c 100644 --- a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs +++ b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs @@ -9,7 +9,7 @@ namespace MLAgents.Tests [TestFixture] public class DemonstrationTests : MonoBehaviour { - const string k_DemoDirecory = "Assets/Demonstrations/"; + const string k_DemoDirectory = "Assets/Demonstrations/"; const string k_ExtensionType = ".demo"; const string k_DemoName = "Test"; @@ -45,17 +45,19 @@ public void TestStoreInitalize() bp.brainParameters.vectorActionDescriptions = new[] { "TestActionA", "TestActionB" }; bp.brainParameters.vectorActionSize = new[] { 2, 2 }; bp.brainParameters.vectorActionSpaceType = SpaceType.Discrete; - bp.behaviorName = "TestBrain"; - Assert.IsFalse(fileSystem.Directory.Exists(k_DemoDirecory)); + var agent = gameobj.AddComponent(); + + Assert.IsFalse(fileSystem.Directory.Exists(k_DemoDirectory)); var demoRec = gameobj.AddComponent(); demoRec.record = true; demoRec.demonstrationName = k_DemoName; + demoRec.demoDirectory = k_DemoDirectory; demoRec.InitializeDemoStore(fileSystem); - Assert.IsTrue(fileSystem.Directory.Exists(k_DemoDirecory)); - Assert.IsTrue(fileSystem.FileExists(k_DemoDirecory + k_DemoName + k_ExtensionType)); + Assert.IsTrue(fileSystem.Directory.Exists(k_DemoDirectory)); + Assert.IsTrue(fileSystem.FileExists(k_DemoDirectory + k_DemoName + k_ExtensionType)); var agentInfo = new AgentInfo { @@ -67,12 +69,8 @@ public void TestStoreInitalize() storedVectorActions = new[] { 0f, 1f }, }; - var expInfo = new ExperienceInfo - { - agentInfo = agentInfo, - sensors = new System.Collections.Generic.List() - }; - demoRec.GetExperienceWriter().Record(expInfo); + + demoRec.m_DemoStore.Record(agentInfo, new System.Collections.Generic.List()); demoRec.Close(); } @@ -104,6 +102,7 @@ public void TestAgentWrite() agentGo1.AddComponent(); var demoRecorder = agentGo1.GetComponent(); var fileSystem = new MockFileSystem(); + demoRecorder.demoDirectory = k_DemoDirectory; demoRecorder.demonstrationName = "TestBrain"; demoRecorder.record = true; demoRecorder.InitializeDemoStore(fileSystem); From 21a76312976c98ca663cb42d869f9525795960d9 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Thu, 13 Feb 2020 11:22:01 -0800 Subject: [PATCH 09/19] check for closed writer --- .../Runtime/DemonstrationStore.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/com.unity.ml-agents/Runtime/DemonstrationStore.cs b/com.unity.ml-agents/Runtime/DemonstrationStore.cs index 400b5871b6..e1974f8b14 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationStore.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationStore.cs @@ -33,6 +33,12 @@ public DemonstrationStore(Stream stream) public void Initialize( string demonstrationName, BrainParameters brainParameters, string brainName) { + if (m_Writer == null) + { + // Already closed + return; + } + m_MetaData = new DemonstrationMetaData { demonstrationName = demonstrationName }; var metaProto = m_MetaData.ToProto(); metaProto.WriteDelimitedTo(m_Writer); @@ -46,6 +52,12 @@ public void Initialize( /// void WriteMetadata() { + if (m_Writer == null) + { + // Already closed + return; + } + var metaProto = m_MetaData.ToProto(); var metaProtoBytes = metaProto.ToByteArray(); m_Writer.Write(metaProtoBytes, 0, metaProtoBytes.Length); @@ -58,6 +70,12 @@ void WriteMetadata() /// void WriteBrainParameters(string brainName, BrainParameters brainParameters) { + if (m_Writer == null) + { + // Already closed + return; + } + // Writes BrainParameters to file. m_Writer.Seek(MetaDataBytes + 1, 0); var brainProto = brainParameters.ToProto(brainName, false); @@ -69,6 +87,12 @@ void WriteBrainParameters(string brainName, BrainParameters brainParameters) /// internal void Record(AgentInfo info, List sensors) { + if (m_Writer == null) + { + // Already closed + return; + } + // Increment meta-data counters. m_MetaData.numberExperiences++; m_CumulativeReward += info.reward; From e66a3b83813965a16e770454752aef4ff3a56988 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Thu, 13 Feb 2020 11:22:53 -0800 Subject: [PATCH 10/19] undo settings changes --- Project/ProjectSettings/GraphicsSettings.asset | 3 --- Project/ProjectSettings/UnityConnectSettings.asset | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Project/ProjectSettings/GraphicsSettings.asset b/Project/ProjectSettings/GraphicsSettings.asset index 4c3961c4ea..b23b253ee8 100644 --- a/Project/ProjectSettings/GraphicsSettings.asset +++ b/Project/ProjectSettings/GraphicsSettings.asset @@ -36,9 +36,6 @@ GraphicsSettings: - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} m_PreloadedShaders: [] m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} diff --git a/Project/ProjectSettings/UnityConnectSettings.asset b/Project/ProjectSettings/UnityConnectSettings.asset index c3ae9a0208..fa0b146579 100644 --- a/Project/ProjectSettings/UnityConnectSettings.asset +++ b/Project/ProjectSettings/UnityConnectSettings.asset @@ -4,7 +4,7 @@ UnityConnectSettings: m_ObjectHideFlags: 0 serializedVersion: 1 - m_Enabled: 1 + m_Enabled: 0 m_TestMode: 0 m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events m_EventUrl: https://cdp.cloud.unity3d.com/v1/events From 2d2c995fe95d9941dc6c46c5f8307188f40ab54b Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Thu, 13 Feb 2020 11:34:49 -0800 Subject: [PATCH 11/19] rename demoDirectory --- .../Runtime/DemonstrationRecorder.cs | 22 +++++++++---------- .../Tests/Editor/DemonstrationTests.cs | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index a9ebb86051..50fab958cc 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -20,7 +20,7 @@ public class DemonstrationRecorder : MonoBehaviour public string demonstrationName; [Tooltip("Base directory to write the demo files. If null, will use {Application.dataPath}/Demonstrations.")] - public string demoDirectory; + public string demonstrationDirectory; internal DemonstrationStore m_DemoStore; internal const int MaxNameLength = 16; @@ -52,13 +52,13 @@ internal void InitializeDemoStore(IFileSystem fileSystem = null) { demonstrationName = behaviorParams.behaviorName; } - if (string.IsNullOrEmpty(demoDirectory)) + if (string.IsNullOrEmpty(demonstrationDirectory)) { - demoDirectory = Path.Combine(Application.dataPath, "Demonstrations"); + demonstrationDirectory = Path.Combine(Application.dataPath, "Demonstrations"); } demonstrationName = SanitizeName(demonstrationName, MaxNameLength); - var filePath = MakeDemonstrationFilePath(m_FileSystem, demoDirectory, demonstrationName); + var filePath = MakeDemonstrationFilePath(m_FileSystem, demonstrationDirectory, demonstrationName); var stream = m_FileSystem.File.Create(filePath); m_DemoStore = new DemonstrationStore(stream); @@ -92,31 +92,31 @@ internal static string SanitizeName(string demoName, int maxNameLength) } /// - /// Gets a unique path for the demonstrationName in the demoDirectory. + /// Gets a unique path for the demonstrationName in the demonstrationDirectory. /// /// - /// + /// /// /// internal static string MakeDemonstrationFilePath( - IFileSystem fileSystem, string demoDirectory, string demonstrationName + IFileSystem fileSystem, string demonstrationDirectory, string demonstrationName ) { // Create the directory if it doesn't already exist - if (!fileSystem.Directory.Exists(demoDirectory)) + if (!fileSystem.Directory.Exists(demonstrationDirectory)) { - fileSystem.Directory.CreateDirectory(demoDirectory); + fileSystem.Directory.CreateDirectory(demonstrationDirectory); } var literalName = demonstrationName; - var filePath = Path.Combine(demoDirectory, literalName + k_ExtensionType); + 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(demoDirectory, literalName + k_ExtensionType); + filePath = Path.Combine(demonstrationDirectory, literalName + k_ExtensionType); uniqueNameCounter++; } diff --git a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs index 0535e3c86c..2e15948894 100644 --- a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs +++ b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs @@ -53,7 +53,7 @@ public void TestStoreInitalize() var demoRec = gameobj.AddComponent(); demoRec.record = true; demoRec.demonstrationName = k_DemoName; - demoRec.demoDirectory = k_DemoDirectory; + demoRec.demonstrationDirectory = k_DemoDirectory; demoRec.InitializeDemoStore(fileSystem); Assert.IsTrue(fileSystem.Directory.Exists(k_DemoDirectory)); @@ -102,7 +102,7 @@ public void TestAgentWrite() agentGo1.AddComponent(); var demoRecorder = agentGo1.GetComponent(); var fileSystem = new MockFileSystem(); - demoRecorder.demoDirectory = k_DemoDirectory; + demoRecorder.demonstrationDirectory = k_DemoDirectory; demoRecorder.demonstrationName = "TestBrain"; demoRecorder.record = true; demoRecorder.InitializeDemoStore(fileSystem); From c59636f602a78a3dea343cc53a78f176d219d44d Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Thu, 13 Feb 2020 12:48:32 -0800 Subject: [PATCH 12/19] more cleanup and internal --- com.unity.ml-agents/Runtime/Demonstration.cs | 4 ++-- com.unity.ml-agents/Runtime/DemonstrationRecorder.cs | 9 +++++---- com.unity.ml-agents/Runtime/DemonstrationStore.cs | 1 - .../Tests/Editor/DemonstrationTests.cs | 11 +++++++++-- docs/Training-Imitation-Learning.md | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/com.unity.ml-agents/Runtime/Demonstration.cs b/com.unity.ml-agents/Runtime/Demonstration.cs index f6722451fb..d7cd7fa7a2 100644 --- a/com.unity.ml-agents/Runtime/Demonstration.cs +++ b/com.unity.ml-agents/Runtime/Demonstration.cs @@ -8,7 +8,7 @@ namespace MLAgents /// Used for imitation learning, or other forms of learning from data. /// [Serializable] - public class Demonstration : ScriptableObject + internal class Demonstration : ScriptableObject { public DemonstrationMetaData metaData; public BrainParameters brainParameters; @@ -26,7 +26,7 @@ public void Initialize(BrainParameters brainParams, /// Kept in a struct for easy serialization and deserialization. /// [Serializable] - public class DemonstrationMetaData + internal class DemonstrationMetaData { public int numberExperiences; public int numberEpisodes; diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index 50fab958cc..dacf6186d1 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -1,7 +1,6 @@ using System.IO.Abstractions; using System.Text.RegularExpressions; using UnityEngine; -using System.Collections.Generic; using System.IO; namespace MLAgents @@ -22,7 +21,7 @@ public class DemonstrationRecorder : MonoBehaviour [Tooltip("Base directory to write the demo files. If null, will use {Application.dataPath}/Demonstrations.")] public string demonstrationDirectory; - internal DemonstrationStore m_DemoStore; + DemonstrationStore m_DemoStore; internal const int MaxNameLength = 16; const string k_ExtensionType = ".demo"; @@ -39,11 +38,11 @@ void Update() /// /// Creates demonstration store for use in recording. /// - internal void InitializeDemoStore(IFileSystem fileSystem = null) + internal DemonstrationStore InitializeDemoStore(IFileSystem fileSystem = null) { if (m_DemoStore != null) { - return; + return m_DemoStore; } m_FileSystem = fileSystem ?? new FileSystem(); @@ -73,6 +72,8 @@ internal void InitializeDemoStore(IFileSystem fileSystem = null) { agent.DemonstrationStores.Add(m_DemoStore); } + + return m_DemoStore; } /// diff --git a/com.unity.ml-agents/Runtime/DemonstrationStore.cs b/com.unity.ml-agents/Runtime/DemonstrationStore.cs index e1974f8b14..d87d3df75f 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationStore.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationStore.cs @@ -1,5 +1,4 @@ using System.IO; -using System.IO.Abstractions; using Google.Protobuf; using System.Collections.Generic; diff --git a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs index 2e15948894..51c9995ff1 100644 --- a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs +++ b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs @@ -54,7 +54,7 @@ public void TestStoreInitalize() demoRec.record = true; demoRec.demonstrationName = k_DemoName; demoRec.demonstrationDirectory = k_DemoDirectory; - demoRec.InitializeDemoStore(fileSystem); + var demoStore = demoRec.InitializeDemoStore(fileSystem); Assert.IsTrue(fileSystem.Directory.Exists(k_DemoDirectory)); Assert.IsTrue(fileSystem.FileExists(k_DemoDirectory + k_DemoName + k_ExtensionType)); @@ -70,8 +70,15 @@ public void TestStoreInitalize() }; - demoRec.m_DemoStore.Record(agentInfo, new System.Collections.Generic.List()); + demoStore.Record(agentInfo, new System.Collections.Generic.List()); demoRec.Close(); + + // Make sure close can be called multiple times + demoStore.Close(); + demoRec.Close(); + + // Make sure trying to write after closing doesn't raise an error. + demoStore.Record(agentInfo, new System.Collections.Generic.List()); } public class ObservationAgent : TestAgent diff --git a/docs/Training-Imitation-Learning.md b/docs/Training-Imitation-Learning.md index b31c26541e..ac18c48cc0 100644 --- a/docs/Training-Imitation-Learning.md +++ b/docs/Training-Imitation-Learning.md @@ -76,7 +76,7 @@ is played from the Editor. Depending on the complexity of the task, anywhere from a few minutes or a few hours of demonstration data may be necessary to be useful for imitation learning. When you have recorded enough data, end the Editor play session, and a `.demo` file will be created in the -`Assets/Demonstrations` folder. This file contains the demonstrations. +`Assets/Demonstrations` folder (by default). This file contains the demonstrations. Clicking on the file will provide metadata about the demonstration in the inspector. From e275121820473e8ddc715e68e67ead86c30d3983 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Tue, 18 Feb 2020 15:35:15 -0800 Subject: [PATCH 13/19] write on Done too --- com.unity.ml-agents/Runtime/Agent.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/com.unity.ml-agents/Runtime/Agent.cs b/com.unity.ml-agents/Runtime/Agent.cs index e2e25dc1dd..b5a16f29d6 100644 --- a/com.unity.ml-agents/Runtime/Agent.cs +++ b/com.unity.ml-agents/Runtime/Agent.cs @@ -176,11 +176,6 @@ internal struct AgentParameters /// Keeps track of the actions that are masked at each step. ActionMasker m_ActionMasker; - /// - /// Demonstration recorder. - /// - DemonstrationRecorder m_Recorder; - /// /// Set of DemonstrationStores that the Agent will write its step information to. /// If you use a DemonstrationRecorder component, this will automatically register its DemonstrationStore. @@ -282,9 +277,10 @@ void NotifyAgentDone(bool maxStepReached = false) // We request a decision so Python knows the Agent is done immediately m_Brain?.RequestDecision(m_Info, sensors); - if (m_Recorder != null && m_Recorder.record && Application.isEditor) + // We also have to write any to any DemonstationStores so that they get the "done" flag. + foreach(var demoWriter in DemonstrationStores) { - m_Recorder.WriteExperience(m_Info, sensors); + demoWriter.Record(m_Info, sensors); } UpdateRewardStats(); From 29bd4be32530e256f870eaf95d5aeab86aa1aa62 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Tue, 18 Feb 2020 15:54:22 -0800 Subject: [PATCH 14/19] Close writer in OnDestroy instead --- com.unity.ml-agents/Runtime/DemonstrationRecorder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index dacf6186d1..1a98b06b6d 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -144,9 +144,9 @@ public void Close() } /// - /// Clean up the DemonstrationStore when shutting down. + /// Clean up the DemonstrationStore when shutting down or destroying the Agent. /// - void OnApplicationQuit() + void OnDestroy() { Close(); } From 9bd123d95274e74a0f0adc192f27239b0f867276 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Wed, 19 Feb 2020 14:18:13 -0800 Subject: [PATCH 15/19] LazyInitialize --- com.unity.ml-agents/Runtime/DemonstrationRecorder.cs | 5 +++-- com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index 1a98b06b6d..846bf3cdd2 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -31,14 +31,15 @@ void Update() { if (record) { - InitializeDemoStore(); + LazyInitialize(); } } /// /// Creates demonstration store for use in recording. + /// Has no effect if the demonstration store was already created. /// - internal DemonstrationStore InitializeDemoStore(IFileSystem fileSystem = null) + internal DemonstrationStore LazyInitialize(IFileSystem fileSystem = null) { if (m_DemoStore != null) { diff --git a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs index 51c9995ff1..f55d3829ff 100644 --- a/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs +++ b/com.unity.ml-agents/Tests/Editor/DemonstrationTests.cs @@ -54,7 +54,7 @@ public void TestStoreInitalize() demoRec.record = true; demoRec.demonstrationName = k_DemoName; demoRec.demonstrationDirectory = k_DemoDirectory; - var demoStore = demoRec.InitializeDemoStore(fileSystem); + var demoStore = demoRec.LazyInitialize(fileSystem); Assert.IsTrue(fileSystem.Directory.Exists(k_DemoDirectory)); Assert.IsTrue(fileSystem.FileExists(k_DemoDirectory + k_DemoName + k_ExtensionType)); @@ -112,7 +112,7 @@ public void TestAgentWrite() demoRecorder.demonstrationDirectory = k_DemoDirectory; demoRecorder.demonstrationName = "TestBrain"; demoRecorder.record = true; - demoRecorder.InitializeDemoStore(fileSystem); + demoRecorder.LazyInitialize(fileSystem); var agentEnableMethod = typeof(Agent).GetMethod("OnEnable", BindingFlags.Instance | BindingFlags.NonPublic); From a450de3bff0f8ddfc0edf1068632f4df6f9bcf09 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Wed, 19 Feb 2020 16:33:06 -0800 Subject: [PATCH 16/19] Agent set of stores is internal, add methods to DemoRecorder to add/remove --- com.unity.ml-agents/Runtime/Agent.cs | 5 +-- .../Runtime/DemonstrationRecorder.cs | 38 ++++++++++++++----- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/com.unity.ml-agents/Runtime/Agent.cs b/com.unity.ml-agents/Runtime/Agent.cs index 230df3d852..1da28e7c33 100644 --- a/com.unity.ml-agents/Runtime/Agent.cs +++ b/com.unity.ml-agents/Runtime/Agent.cs @@ -179,10 +179,9 @@ internal struct AgentParameters /// /// 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 DemonstrationStores; the Agent is not responsible for creating or closing the - /// stores, only opening them. + /// You can also add your own DemonstrationStore by calling DemonstrationRecorder.AddDemonstrationStoreToAgent() /// - public ISet DemonstrationStores = new HashSet(); + internal ISet DemonstrationStores = new HashSet(); /// /// List of sensors used to generate observations. diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index 846bf3cdd2..290b189f08 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -27,6 +27,13 @@ public class DemonstrationRecorder : MonoBehaviour const string k_ExtensionType = ".demo"; IFileSystem m_FileSystem; + Agent m_Agent; + + void OnEnable() + { + m_Agent = GetComponent(); + } + void Update() { if (record) @@ -68,11 +75,7 @@ internal DemonstrationStore LazyInitialize(IFileSystem fileSystem = null) behaviorParams.fullyQualifiedBehaviorName ); - var agent = GetComponent(); - if (agent != null) - { - agent.DemonstrationStores.Add(m_DemoStore); - } + m_Agent.DemonstrationStores.Add(m_DemoStore); return m_DemoStore; } @@ -133,11 +136,7 @@ public void Close() { if (m_DemoStore != null) { - var agent = GetComponent(); - if (agent != null) - { - agent.DemonstrationStores.Remove(m_DemoStore); - } + m_Agent.DemonstrationStores.Remove(m_DemoStore); m_DemoStore.Close(); m_DemoStore = null; @@ -152,5 +151,24 @@ void OnDestroy() Close(); } + /// + /// Add additional DemonstrationStore to the Agent. It is still up to the user to Close this + /// DemonstrationStores when recording is done. + /// + /// + void AddDemonstrationStoreToAgent(DemonstrationStore demoStore) + { + m_Agent.DemonstrationStores.Add(demoStore); + } + + /// + /// Remove additional DemonstrationStore to the Agent. It is still up to the user to Close this + /// DemonstrationStores when recording is done. + /// + /// + void RemoveDemonstrationStoreFromAgent(DemonstrationStore demoStore) + { + m_Agent.DemonstrationStores.Remove(demoStore); + } } } From dcac2890f1cd5eb98a89cecf7556c4c711192bb8 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Wed, 19 Feb 2020 16:34:10 -0800 Subject: [PATCH 17/19] actually make them public --- com.unity.ml-agents/Runtime/DemonstrationRecorder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index 290b189f08..ff8044f71b 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -156,7 +156,7 @@ void OnDestroy() /// DemonstrationStores when recording is done. /// /// - void AddDemonstrationStoreToAgent(DemonstrationStore demoStore) + public void AddDemonstrationStoreToAgent(DemonstrationStore demoStore) { m_Agent.DemonstrationStores.Add(demoStore); } @@ -166,7 +166,7 @@ void AddDemonstrationStoreToAgent(DemonstrationStore demoStore) /// DemonstrationStores when recording is done. /// /// - void RemoveDemonstrationStoreFromAgent(DemonstrationStore demoStore) + public void RemoveDemonstrationStoreFromAgent(DemonstrationStore demoStore) { m_Agent.DemonstrationStores.Remove(demoStore); } From 6da9433f4692ed31893f725962143f396927d523 Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Thu, 20 Feb 2020 11:24:48 -0800 Subject: [PATCH 18/19] make sure agent is initialized --- com.unity.ml-agents/Runtime/DemonstrationRecorder.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index ff8044f71b..2bc5368a6e 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -53,6 +53,11 @@ internal DemonstrationStore LazyInitialize(IFileSystem fileSystem = null) return m_DemoStore; } + if (m_Agent == null) + { + m_Agent = GetComponent(); + } + m_FileSystem = fileSystem ?? new FileSystem(); var behaviorParams = GetComponent(); if (string.IsNullOrEmpty(demonstrationName)) From c883ab0bc4ee39788f113391b9d28c292e232d7f Mon Sep 17 00:00:00 2001 From: Chris Elion Date: Sat, 22 Feb 2020 15:13:37 -0800 Subject: [PATCH 19/19] use AddDemonstrationStoreToAgent etc. --- com.unity.ml-agents/Runtime/DemonstrationRecorder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs index 2bc5368a6e..49f5aab065 100644 --- a/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs +++ b/com.unity.ml-agents/Runtime/DemonstrationRecorder.cs @@ -80,7 +80,7 @@ internal DemonstrationStore LazyInitialize(IFileSystem fileSystem = null) behaviorParams.fullyQualifiedBehaviorName ); - m_Agent.DemonstrationStores.Add(m_DemoStore); + AddDemonstrationStoreToAgent(m_DemoStore); return m_DemoStore; } @@ -141,7 +141,7 @@ public void Close() { if (m_DemoStore != null) { - m_Agent.DemonstrationStores.Remove(m_DemoStore); + RemoveDemonstrationStoreFromAgent(m_DemoStore); m_DemoStore.Close(); m_DemoStore = null;