using Unity.Barracuda; namespace Unity.MLAgents.Sensors { /// /// This is the simplest approach, but there's possible user error if Shape.Length != DimensionProperties.Length /// public struct ObservationSpec { public ObservationType ObservationType; public int[] Shape; public DimensionProperty[] DimensionProperties; /// /// Create an Observation spec with default DimensionProperties and ObservationType from the shape. /// /// /// public static ObservationSpec FromShape(params int[] shape) { DimensionProperty[] dimProps = null; if (shape.Length == 1) { dimProps = new[] { DimensionProperty.None }; } else if (shape.Length == 2) { // NOTE: not sure if I like this - might leave Unspecified and make BufferSensor set it dimProps = new[] { DimensionProperty.VariableSize, DimensionProperty.None }; } else if (shape.Length == 3) { dimProps = new[] { DimensionProperty.TranslationalEquivariance, DimensionProperty.TranslationalEquivariance, DimensionProperty.None }; } else { dimProps = new DimensionProperty[shape.Length]; for (var i = 0; i < dimProps.Length; i++) { dimProps[i] = DimensionProperty.Unspecified; } } return new ObservationSpec { ObservationType = ObservationType.Default, Shape = shape, DimensionProperties = dimProps }; } public ObservationSpec Clone() { return new ObservationSpec { Shape = (int[])Shape.Clone(), DimensionProperties = (DimensionProperty[])DimensionProperties.Clone(), ObservationType = ObservationType }; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Information about a single dimension. Future per-dimension properties can go here. /// This is nicer because it ensures the shape and dimension properties that the same size /// public struct DimensionInfo { public int Rank; public DimensionProperty DimensionProperty; } public struct ObservationSpecAlternativeOne { public ObservationType ObservationType; public DimensionInfo[] DimensionInfos; // Similar ObservationSpec.FromShape() as above } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// Uses Barracuda's TensorShape struct instead of an int[] for the shape. /// This doesn't fully avoid allocations because of DimensionProperty, so we'd need more supporting code. /// I don't like explicitly depending on Barracuda in one of our central interfaces, but listing as an alternative. /// public struct ObservationSpecAlternativeTwo { public ObservationType ObservationType; public TensorShape Shape; public DimensionProperty[] DimensionProperties; } }