using System; namespace Unity.MLAgents.Sensors { /// /// A Sensor that allows to observe a variable number of entities. /// public class BufferSensor : ISensor, IDimensionPropertiesSensor, IBuiltInSensor { private string m_Name; private int m_MaxNumObs; private int m_ObsSize; float[] m_ObservationBuffer; int m_CurrentNumObservables; static DimensionProperty[] s_DimensionProperties = new DimensionProperty[]{ DimensionProperty.VariableSize, DimensionProperty.None }; /// /// Creates the BufferSensor. /// /// The maximum number of observations to be appended to this BufferSensor. /// The size of each observation appended to the BufferSensor. /// The name of the sensor. public BufferSensor(int maxNumberObs, int obsSize, string name) { m_Name = name; m_MaxNumObs = maxNumberObs; m_ObsSize = obsSize; m_ObservationBuffer = new float[m_ObsSize * m_MaxNumObs]; m_CurrentNumObservables = 0; } /// public int[] GetObservationShape() { return new int[] { m_MaxNumObs, m_ObsSize }; } /// public DimensionProperty[] GetDimensionProperties() { return s_DimensionProperties; } /// /// Appends an observation to the buffer. If the buffer is full (maximum number /// of observation is reached) the observation will be ignored. the length of /// the provided observation array must be equal to the observation size of /// the buffer sensor. /// /// The float array observation public void AppendObservation(float[] obs) { if (obs.Length != m_ObsSize) { throw new UnityAgentsException( "The BufferSensor was expecting an observation of size " + $"{m_ObsSize} but received {obs.Length} observations instead." ); } if (m_CurrentNumObservables >= m_MaxNumObs) { return; } for (int i = 0; i < obs.Length; i++) { m_ObservationBuffer[m_CurrentNumObservables * m_ObsSize + i] = obs[i]; } m_CurrentNumObservables++; } /// public int Write(ObservationWriter writer) { for (int i = 0; i < m_ObsSize * m_MaxNumObs; i++) { writer[i] = m_ObservationBuffer[i]; } return m_ObsSize * m_MaxNumObs; } /// public virtual byte[] GetCompressedObservation() { return null; } /// public void Update() { Reset(); } /// public void Reset() { m_CurrentNumObservables = 0; Array.Clear(m_ObservationBuffer, 0, m_ObservationBuffer.Length); } /// public SensorCompressionType GetCompressionType() { return SensorCompressionType.None; } /// public string GetName() { return m_Name; } /// public BuiltInSensorType GetBuiltInSensorType() { return BuiltInSensorType.BufferSensor; } } }