using System.Linq; namespace Unity.MLAgents.Sensors { /// /// The compression setting for visual/camera observations. /// public enum SensorCompressionType { /// /// No compression. Data is preserved as float arrays. /// None, /// /// PNG format. Data will be stored in binary format. /// PNG } /// /// A description of the compression used for observations. /// /// /// Most ISensor implementations can't take advantage of compression, /// and should return CompressionSpec.Default() from their ISensor.GetCompressionSpec() methods. /// Visual observations, or mulitdimensional categorical observations (for example, image segmentation /// or the piece types in a match-3 game board) can use PNG compression reduce the amount of /// data transferred between Unity and the trainer. /// public struct CompressionSpec { internal SensorCompressionType m_SensorCompressionType; /// /// The compression type that the sensor will use for its observations. /// public SensorCompressionType SensorCompressionType { get => m_SensorCompressionType; } internal int[] m_CompressedChannelMapping; /// /// The mapping of the channels in compressed data to the actual channel after decompression. /// /// /// The mapping is a list of integer index with the same length as /// the number of output observation layers (channels), including padding if there's any. /// Each index indicates the actual channel the layer will go into. /// Layers with the same index will be averaged, and layers with negative index will be dropped. /// For example, mapping for CameraSensor using grayscale and stacking of two: [0, 0, 0, 1, 1, 1] /// Mapping for GridSensor of 4 channels and stacking of two: [0, 1, 2, 3, -1, -1, 4, 5, 6, 7, -1, -1] /// public int[] CompressedChannelMapping { get => m_CompressedChannelMapping; } /// /// Return a CompressionSpec indicating possible compression. /// /// The compression type to use. /// Optional mapping mapping of the channels in compressed data to the /// actual channel after decompression. public CompressionSpec(SensorCompressionType sensorCompressionType, int[] compressedChannelMapping = null) { m_SensorCompressionType = sensorCompressionType; m_CompressedChannelMapping = compressedChannelMapping; } /// /// Return a CompressionSpec indicating no compression. This is recommended for most sensors. /// /// public static CompressionSpec Default() { return new CompressionSpec { m_SensorCompressionType = SensorCompressionType.None, m_CompressedChannelMapping = null }; } /// /// Return whether the compressed channel mapping is "trivial"; if so it doesn't need to be sent to the /// trainer. /// /// internal bool IsTrivialMapping() { var mapping = CompressedChannelMapping; if (mapping == null) { return true; } // check if mapping equals zero mapping if (mapping.Length == 3 && mapping.All(m => m == 0)) { return true; } // check if mapping equals identity mapping for (var i = 0; i < mapping.Length; i++) { if (mapping[i] != i) { return false; } } return true; } } }