浏览代码

UI for Ray stacks, rename WriteAdapter to ObservationWriter (#3834)

* UI for Ray stacks, rename WriteAdapter to ObservationWriter

* move test

* changelog and migration
/develop/dockerfile
GitHub 5 年前
当前提交
4399e29f
共有 31 个文件被更改,包括 87 次插入82 次删除
  1. 8
      Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/SensorBase.cs
  2. 2
      com.unity.ml-agents/CHANGELOG.md
  3. 2
      com.unity.ml-agents/Editor/RayPerceptionSensorComponentBaseEditor.cs
  4. 10
      com.unity.ml-agents/Runtime/Communicator/GrpcExtensions.cs
  5. 4
      com.unity.ml-agents/Runtime/Communicator/RpcCommunicator.cs
  6. 4
      com.unity.ml-agents/Runtime/Demonstrations/DemonstrationWriter.cs
  7. 12
      com.unity.ml-agents/Runtime/Inference/GeneratorImpl.cs
  8. 6
      com.unity.ml-agents/Runtime/Policies/HeuristicPolicy.cs
  9. 8
      com.unity.ml-agents/Runtime/Sensors/CameraSensor.cs
  10. 6
      com.unity.ml-agents/Runtime/Sensors/ISensor.cs
  11. 10
      com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensor.cs
  12. 2
      com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensorComponentBase.cs
  13. 4
      com.unity.ml-agents/Runtime/Sensors/RenderTextureSensor.cs
  14. 12
      com.unity.ml-agents/Runtime/Sensors/StackingSensor.cs
  15. 4
      com.unity.ml-agents/Runtime/Sensors/VectorSensor.cs
  16. 8
      com.unity.ml-agents/Runtime/Sensors/ObservationWriter.cs
  17. 16
      com.unity.ml-agents/Runtime/Utilities.cs
  18. 6
      com.unity.ml-agents/Tests/Editor/MLAgentsEditModeTest.cs
  19. 4
      com.unity.ml-agents/Tests/Editor/ParameterLoaderTest.cs
  20. 4
      com.unity.ml-agents/Tests/Editor/Sensor/CameraSensorTest.cs
  21. 6
      com.unity.ml-agents/Tests/Editor/Sensor/FloatVisualSensorTests.cs
  22. 10
      com.unity.ml-agents/Tests/Editor/Sensor/RayPerceptionSensorTests.cs
  23. 4
      com.unity.ml-agents/Tests/Editor/Sensor/RenderTextureSensorTests.cs
  24. 2
      com.unity.ml-agents/Tests/Editor/Sensor/SensorShapeValidatorTests.cs
  25. 4
      com.unity.ml-agents/Tests/Editor/Sensor/VectorSensorTests.cs
  26. 8
      com.unity.ml-agents/Tests/Editor/Sensor/ObservationWriterTests.cs
  27. 3
      docs/Migrating.md
  28. 0
      /com.unity.ml-agents/Runtime/Sensors/ObservationWriter.cs.meta
  29. 0
      /com.unity.ml-agents/Runtime/Sensors/ObservationWriter.cs
  30. 0
      /com.unity.ml-agents/Tests/Editor/Sensor/ObservationWriterTests.cs.meta
  31. 0
      /com.unity.ml-agents/Tests/Editor/Sensor/ObservationWriterTests.cs

8
Project/Assets/ML-Agents/Examples/SharedAssets/Scripts/SensorBase.cs


/// <summary>
/// Default implementation of Write interface. This creates a temporary array,
/// calls WriteObservation, and then writes the results to the WriteAdapter.
/// calls WriteObservation, and then writes the results to the ObservationWriter.
/// <param name="adapter"></param>
/// <param name="writer"></param>
public virtual int Write(WriteAdapter adapter)
public virtual int Write(ObservationWriter writer)
{
// TODO reuse buffer for similar agents, don't call GetObservationShape()
var numFloats = this.ObservationSize();

adapter.AddRange(buffer);
writer.AddRange(buffer);
return numFloats;
}

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


added in `CollectObservations()`. (#3825)
- Model updates can now happen asynchronously with environment steps for better performance. (#3690)
- `num_updates` and `train_interval` for SAC were replaced with `steps_per_update`. (#3690)
- `WriteAdapter` was renamed to `ObservationWriter`. If you have a custom `ISensor` implementation,
you will need to change the signature of its `Write()` method. (#3834)
### Bug Fixes

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


// it is not editable during play mode.
EditorGUI.BeginDisabledGroup(!EditorUtilities.CanUpdateModelProperties());
{
EditorGUILayout.PropertyField(so.FindProperty("m_ObservationStacks"), true);
EditorGUILayout.PropertyField(so.FindProperty("m_ObservationStacks"), new GUIContent("Stacked Raycasts"), true);
}
EditorGUI.EndDisabledGroup();

10
com.unity.ml-agents/Runtime/Communicator/GrpcExtensions.cs


}
/// <summary>
/// Generate an ObservationProto for the sensor using the provided WriteAdapter.
/// Generate an ObservationProto for the sensor using the provided ObservationWriter.
/// <param name="writeAdapter"></param>
/// <param name="observationWriter"></param>
public static ObservationProto GetObservationProto(this ISensor sensor, WriteAdapter writeAdapter)
public static ObservationProto GetObservationProto(this ISensor sensor, ObservationWriter observationWriter)
{
var shape = sensor.GetObservationShape();
ObservationProto observationProto = null;

floatDataProto.Data.Add(0.0f);
}
writeAdapter.SetTarget(floatDataProto.Data, sensor.GetObservationShape(), 0);
sensor.Write(writeAdapter);
observationWriter.SetTarget(floatDataProto.Data, sensor.GetObservationShape(), 0);
sensor.Write(observationWriter);
observationProto = new ObservationProto
{

4
com.unity.ml-agents/Runtime/Communicator/RpcCommunicator.cs


List<string> m_BehaviorNames = new List<string>();
bool m_NeedCommunicateThisStep;
WriteAdapter m_WriteAdapter = new WriteAdapter();
ObservationWriter m_ObservationWriter = new ObservationWriter();
Dictionary<string, SensorShapeValidator> m_SensorShapeValidators = new Dictionary<string, SensorShapeValidator>();
Dictionary<string, List<int>> m_OrderedAgentsRequestingDecisions = new Dictionary<string, List<int>>();

{
foreach (var sensor in sensors)
{
var obsProto = sensor.GetObservationProto(m_WriteAdapter);
var obsProto = sensor.GetObservationProto(m_ObservationWriter);
agentInfoProto.Observations.Add(obsProto);
}
}

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


DemonstrationMetaData m_MetaData;
Stream m_Writer;
float m_CumulativeReward;
WriteAdapter m_WriteAdapter = new WriteAdapter();
ObservationWriter m_ObservationWriter = new ObservationWriter();
/// <summary>
/// Create a DemonstrationWriter that will write to the specified stream.

var agentProto = info.ToInfoActionPairProto();
foreach (var sensor in sensors)
{
agentProto.AgentInfo.Observations.Add(sensor.GetObservationProto(m_WriteAdapter));
agentProto.AgentInfo.Observations.Add(sensor.GetObservationProto(m_ObservationWriter));
}
agentProto.WriteDelimitedTo(m_Writer);

12
com.unity.ml-agents/Runtime/Inference/GeneratorImpl.cs


{
readonly ITensorAllocator m_Allocator;
List<int> m_SensorIndices = new List<int>();
WriteAdapter m_WriteAdapter = new WriteAdapter();
ObservationWriter m_ObservationWriter = new ObservationWriter();
public VectorObservationGenerator(ITensorAllocator allocator)
{

foreach (var sensorIndex in m_SensorIndices)
{
var sensor = info.sensors[sensorIndex];
m_WriteAdapter.SetTarget(tensorProxy, agentIndex, tensorOffset);
var numWritten = sensor.Write(m_WriteAdapter);
m_ObservationWriter.SetTarget(tensorProxy, agentIndex, tensorOffset);
var numWritten = sensor.Write(m_ObservationWriter);
tensorOffset += numWritten;
}
Debug.AssertFormat(

{
readonly int m_SensorIndex;
readonly ITensorAllocator m_Allocator;
WriteAdapter m_WriteAdapter = new WriteAdapter();
ObservationWriter m_ObservationWriter = new ObservationWriter();
public VisualObservationInputGenerator(
int sensorIndex, ITensorAllocator allocator)

}
else
{
m_WriteAdapter.SetTarget(tensorProxy, agentIndex, 0);
sensor.Write(m_WriteAdapter);
m_ObservationWriter.SetTarget(tensorProxy, agentIndex, 0);
sensor.Write(m_ObservationWriter);
}
agentIndex++;
}

6
com.unity.ml-agents/Runtime/Policies/HeuristicPolicy.cs


bool m_Done;
bool m_DecisionRequested;
WriteAdapter m_WriteAdapter = new WriteAdapter();
ObservationWriter m_ObservationWriter = new ObservationWriter();
NullList m_NullList = new NullList();

{
if (sensor.GetCompressionType() == SensorCompressionType.None)
{
m_WriteAdapter.SetTarget(m_NullList, sensor.GetObservationShape(), 0);
sensor.Write(m_WriteAdapter);
m_ObservationWriter.SetTarget(m_NullList, sensor.GetObservationShape(), 0);
sensor.Write(m_ObservationWriter);
}
else
{

8
com.unity.ml-agents/Runtime/Sensors/CameraSensor.cs


}
/// <summary>
/// Writes out the generated, uncompressed image to the provided <see cref="WriteAdapter"/>.
/// Writes out the generated, uncompressed image to the provided <see cref="ObservationWriter"/>.
/// <param name="adapter">Where the observation is written to.</param>
/// <param name="writer">Where the observation is written to.</param>
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
var numWritten = Utilities.TextureToTensorProxy(texture, adapter, m_Grayscale);
var numWritten = Utilities.TextureToTensorProxy(texture, writer, m_Grayscale);
DestroyTexture(texture);
return numWritten;
}

6
com.unity.ml-agents/Runtime/Sensors/ISensor.cs


int[] GetObservationShape();
/// <summary>
/// Write the observation data directly to the <see cref="WriteAdapter"/>.
/// Write the observation data directly to the <see cref="ObservationWriter"/>.
/// <param name="adapter">Where the observations will be written to.</param>
/// <param name="writer">Where the observations will be written to.</param>
int Write(WriteAdapter adapter);
int Write(ObservationWriter writer);
/// <summary>
/// Return a compressed representation of the observation. For small observations,

10
com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensor.cs


/// <summary>
/// Computes the ray perception observations and saves them to the provided
/// <see cref="WriteAdapter"/>.
/// <see cref="ObservationWriter"/>.
/// <param name="adapter">Where the ray perception observations are written to.</param>
/// <param name="writer">Where the ray perception observations are written to.</param>
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
{
using (TimerStack.Instance.Scoped("RayPerceptionSensor.Perceive"))
{

rayOutput.ToFloatArray(numDetectableTags, rayIndex, m_Observations);
}
// Finally, add the observations to the WriteAdapter
adapter.AddRange(m_Observations);
// Finally, add the observations to the ObservationWriter
writer.AddRange(m_Observations);
}
return m_Observations.Length;
}

2
com.unity.ml-agents/Runtime/Sensors/RayPerceptionSensorComponentBase.cs


[HideInInspector, SerializeField, FormerlySerializedAs("observationStacks")]
[Range(1, 50)]
[Tooltip("Whether to stack previous observations. Using 1 means no previous observations.")]
[Tooltip("Number of raycast results that will be stacked before being fed to the neural network.")]
int m_ObservationStacks = 1;
/// <summary>

4
com.unity.ml-agents/Runtime/Sensors/RenderTextureSensor.cs


}
/// <inheritdoc/>
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
var numWritten = Utilities.TextureToTensorProxy(texture, adapter, m_Grayscale);
var numWritten = Utilities.TextureToTensorProxy(texture, writer, m_Grayscale);
DestroyTexture(texture);
return numWritten;
}

12
com.unity.ml-agents/Runtime/Sensors/StackingSensor.cs


float[][] m_StackedObservations;
int m_CurrentIndex;
WriteAdapter m_LocalAdapter = new WriteAdapter();
ObservationWriter m_LocalWriter = new ObservationWriter();
/// <summary>
/// Initializes the sensor.

}
/// <inheritdoc/>
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
// First, call the wrapped sensor's write method. Make sure to use our own adapter, not the passed one.
// First, call the wrapped sensor's write method. Make sure to use our own writer, not the passed one.
m_LocalAdapter.SetTarget(m_StackedObservations[m_CurrentIndex], wrappedShape, 0);
m_WrappedSensor.Write(m_LocalAdapter);
m_LocalWriter.SetTarget(m_StackedObservations[m_CurrentIndex], wrappedShape, 0);
m_WrappedSensor.Write(m_LocalWriter);
// Now write the saved observations (oldest first)
var numWritten = 0;

adapter.AddRange(m_StackedObservations[obsIndex], numWritten);
writer.AddRange(m_StackedObservations[obsIndex], numWritten);
numWritten += m_UnstackedObservationSize;
}

4
com.unity.ml-agents/Runtime/Sensors/VectorSensor.cs


}
/// <inheritdoc/>
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
{
var expectedObservations = m_Shape[0];
if (m_Observations.Count > expectedObservations)

m_Observations.Add(0);
}
}
adapter.AddRange(m_Observations);
writer.AddRange(m_Observations);
return expectedObservations;
}

8
com.unity.ml-agents/Runtime/Sensors/ObservationWriter.cs


/// <summary>
/// Allows sensors to write to both TensorProxy and float arrays/lists.
/// </summary>
public class WriteAdapter
public class ObservationWriter
{
IList<float> m_Data;
int m_Offset;

TensorShape m_TensorShape;
internal WriteAdapter() { }
internal ObservationWriter() { }
/// Set the adapter to write to an IList at the given channelOffset.
/// Set the writer to write to an IList at the given channelOffset.
/// </summary>
/// <param name="data">Float array or list that will be written to.</param>
/// <param name="shape">Shape of the observations to be written.</param>

}
/// <summary>
/// Set the adapter to write to a TensorProxy at the given batch and channel offset.
/// Set the writer to write to a TensorProxy at the given batch and channel offset.
/// </summary>
/// <param name="tensorProxy">Tensor proxy that will be written to.</param>
/// <param name="batchIndex">Batch index in the tensor proxy (i.e. the index of the Agent).</param>

16
com.unity.ml-agents/Runtime/Utilities.cs


internal static class Utilities
{
/// <summary>
/// Puts a Texture2D into a WriteAdapter.
/// Puts a Texture2D into a ObservationWriter.
/// <param name="adapter">
/// Adapter to fill with Texture data.
/// <param name="obsWriter">
/// Writer to fill with Texture data.
/// </param>
/// <param name="grayScale">
/// If set to <c>true</c> the textures will be converted to grayscale before

internal static int TextureToTensorProxy(
Texture2D texture,
WriteAdapter adapter,
ObservationWriter obsWriter,
bool grayScale)
{
var width = texture.width;

var currentPixel = texturePixels[(height - h - 1) * width + w];
if (grayScale)
{
adapter[h, w, 0] =
obsWriter[h, w, 0] =
adapter[h, w, 0] = currentPixel.r / 255.0f;
adapter[h, w, 1] = currentPixel.g / 255.0f;
adapter[h, w, 2] = currentPixel.b / 255.0f;
obsWriter[h, w, 0] = currentPixel.r / 255.0f;
obsWriter[h, w, 1] = currentPixel.g / 255.0f;
obsWriter[h, w, 2] = currentPixel.b / 255.0f;
}
}
}

6
com.unity.ml-agents/Tests/Editor/MLAgentsEditModeTest.cs


internal class TestPolicy : IPolicy
{
public Action OnRequestDecision;
private WriteAdapter m_Adapter = new WriteAdapter();
ObservationWriter m_ObsWriter = new ObservationWriter();
sensor.GetObservationProto(m_Adapter);
sensor.GetObservationProto(m_ObsWriter);
}
OnRequestDecision?.Invoke();
}

return new[] { 0 };
}
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
{
numWriteCalls++;
// No-op

4
com.unity.ml-agents/Tests/Editor/ParameterLoaderTest.cs


return new int[] {m_Height, m_Width, m_Channels };
}
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
adapter[i] = 0.0f;
writer[i] = 0.0f;
}
return m_Width * m_Height * m_Channels;
}

4
com.unity.ml-agents/Tests/Editor/Sensor/CameraSensorTest.cs


var camera = Camera.main;
var sensor = new CameraSensor(camera, width, height, grayscale, "TestCameraSensor", compression);
var writeAdapter = new WriteAdapter();
var obs = sensor.GetObservationProto(writeAdapter);
var obsWriter = new ObservationWriter();
var obs = sensor.GetObservationProto(obsWriter);
Assert.AreEqual((int) compression, (int) obs.CompressionType);
var expectedShape = new[] { height, width, grayscale ? 1 : 3 };

6
com.unity.ml-agents/Tests/Editor/Sensor/FloatVisualSensorTests.cs


return null;
}
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
{
using (TimerStack.Instance.Scoped("Float2DSensor.Write"))
{

{
adapter[h, w, 0] = floatData[h, w];
writer[h, w, 0] = floatData[h, w];
}
}
var numWritten = Height * Width;

}
var output = new float[12];
var writer = new WriteAdapter();
var writer = new ObservationWriter();
writer.SetTarget(output, sensor.GetObservationShape(), 0);
sensor.Write(writer);
for (var i = 0; i < 9; i++)

10
com.unity.ml-agents/Tests/Editor/Sensor/RayPerceptionSensorTests.cs


Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs);
var outputBuffer = new float[expectedObs];
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0);
var numWritten = sensor.Write(writer);

Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs);
var outputBuffer = new float[expectedObs];
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0);
var numWritten = sensor.Write(writer);

Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs);
var outputBuffer = new float[expectedObs];
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0);
var numWritten = sensor.Write(writer);

Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs);
var outputBuffer = new float[expectedObs];
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0);
var numWritten = sensor.Write(writer);

Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs);
var outputBuffer = new float[expectedObs];
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0);
var numWritten = sensor.Write(writer);

4
com.unity.ml-agents/Tests/Editor/Sensor/RenderTextureSensorTests.cs


var texture = new RenderTexture(width, height, 0);
var sensor = new RenderTextureSensor(texture, grayscale, "TestCameraSensor", compression);
var writeAdapter = new WriteAdapter();
var obs = sensor.GetObservationProto(writeAdapter);
var obsWriter = new ObservationWriter();
var obs = sensor.GetObservationProto(obsWriter);
Assert.AreEqual((int)compression, (int)obs.CompressionType);
var expectedShape = new[] { height, width, grayscale ? 1 : 3 };

2
com.unity.ml-agents/Tests/Editor/Sensor/SensorShapeValidatorTests.cs


return null;
}
public int Write(WriteAdapter adapter)
public int Write(ObservationWriter writer)
{
return this.ObservationSize();
}

4
com.unity.ml-agents/Tests/Editor/Sensor/VectorSensorTests.cs


}
Assert.AreEqual(fill, output[0]);
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
// Make sure WriteAdapter didn't touch anything
// Make sure ObservationWriter didn't touch anything
Assert.AreEqual(fill, output[0]);
sensor.Write(writer);

8
com.unity.ml-agents/Tests/Editor/Sensor/ObservationWriterTests.cs


namespace MLAgents.Tests
{
public class WriteAdapterTests
public class ObservationWriterTests
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
var buffer = new[] { 0f, 0f, 0f };
var shape = new[] { 3 };

[Test]
public void TestWritesToTensor()
{
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
var t = new TensorProxy
{
valueType = TensorProxy.TensorType.FloatingPoint,

[Test]
public void TestWritesToTensor3D()
{
WriteAdapter writer = new WriteAdapter();
ObservationWriter writer = new ObservationWriter();
var t = new TensorProxy
{
valueType = TensorProxy.TensorType.FloatingPoint,

3
docs/Migrating.md


C# style conventions. All public fields and properties now use "PascalCase"
instead of "camelCase"; for example, `Agent.maxStep` was renamed to
`Agent.MaxStep`. For a full list of changes, see the pull request. (#3828)
- `WriteAdapter` was renamed to `ObservationWriter`. (#3834)
### Steps to Migrate

no longer takes a file name as input but a fully constructed
`UnityEnvironment` instead.
- Update uses of "camelCase" fields and properties to "PascalCase".
- If you have a custom `ISensor` implementation, you will need to change the signature of
its `Write()` method to use `ObservationWriter` instead of `WriteAdapter`.
## Migrating from 0.14 to 0.15

/com.unity.ml-agents/Runtime/Sensors/WriteAdapter.cs.meta → /com.unity.ml-agents/Runtime/Sensors/ObservationWriter.cs.meta

/com.unity.ml-agents/Runtime/Sensors/WriteAdapter.cs → /com.unity.ml-agents/Runtime/Sensors/ObservationWriter.cs

/com.unity.ml-agents/Tests/Editor/Sensor/WriterAdapterTests.cs.meta → /com.unity.ml-agents/Tests/Editor/Sensor/ObservationWriterTests.cs.meta

/com.unity.ml-agents/Tests/Editor/Sensor/WriterAdapterTests.cs → /com.unity.ml-agents/Tests/Editor/Sensor/ObservationWriterTests.cs

正在加载...
取消
保存