浏览代码

first commit, tests to be added

/0.9.0.preview.1_staging
Mohsen Kamalzadeh 3 年前
当前提交
b1b39d5b
共有 10 个文件被更改,包括 315 次插入20 次删除
  1. 9
      com.unity.perception/Editor/Randomization/Utilities/UIElementsEditorUtilities.cs
  2. 8
      com.unity.perception/Runtime/Randomization/Randomizers/Randomizer.cs
  3. 20
      com.unity.perception/Runtime/Randomization/Samplers/ISampler.cs
  4. 20
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/AnimationCurveSampler.cs
  5. 42
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/ConstantSampler.cs
  6. 39
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/NormalSampler.cs
  7. 39
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/UniformSampler.cs
  8. 1
      com.unity.perception/Runtime/Randomization/Scenarios/Serialization/JsonConverters.cs
  9. 145
      com.unity.perception/Runtime/Randomization/Scenarios/Serialization/ScenarioSerializer.cs
  10. 12
      com.unity.perception/Runtime/Randomization/Scenarios/Serialization/SerializationStructures.cs

9
com.unity.perception/Editor/Randomization/Utilities/UIElementsEditorUtilities.cs


if (originalField == null)
return null;
var tooltipAttribute = originalField.GetCustomAttributes(true)
.ToList().Find(att => att.GetType() == typeof(TooltipAttribute));
var attributes = originalField.GetCustomAttributes(true).ToList();
var tooltipAttribute = attributes.Find(att => att.GetType() == typeof(TooltipAttribute));
var hideInspectorAttribute = attributes.Find(att => att.GetType() == typeof(TooltipAttribute));
if (hideInspectorAttribute != null)
propertyField.style.display = DisplayStyle.None;
return propertyField;
}
}

8
com.unity.perception/Runtime/Randomization/Randomizers/Randomizer.cs


}
/// <summary>
/// Some Randomizers should not be disabled by the user as they are critical to the project. E.g. We might want to mark this as false for a foreground objects placement randomizer in some projects
/// </summary>
#if !SCENARIO_CONFIG_POWER_USER
[HideInInspector]
#endif
public bool canBeDisabledByUser = true;
/// <summary>
/// Returns the scenario containing this Randomizer
/// </summary>
public ScenarioBase scenario => ScenarioBase.activeScenario;

20
com.unity.perception/Runtime/Randomization/Samplers/ISampler.cs


/// Validates that the sampler is configured properly
/// </summary>
void Validate();
/// <summary>
/// Check that the provided values adhere to the <see cref="minAllowed"/> and <see cref="maxAllowed"/> outputs for this sampler.
/// </summary>
public void CheckAgainstValidRange();
/// <summary>
/// Whether the provided <see cref="minAllowed"/> and <see cref="maxAllowed"/> values should be used to validate this sampler.
/// </summary>
public bool shouldCheckValidRange { get; set; }
/// <summary>
/// The smallest value this sampler should output
/// </summary>
public float minAllowed { get; set; }
/// <summary>
/// The largest value this sampler should output
/// </summary>
public float maxAllowed { get; set; }
}
}

20
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/AnimationCurveSampler.cs


using System;
using UnityEngine.Assertions;
namespace UnityEngine.Perception.Randomization.Samplers
{

/// </summary>
[Tooltip("Probability distribution curve used for this sampler. The X axis corresponds to the values this sampler will pick from, and the Y axis corresponds to the relative probability of the values. The relative probabilities (Y axis) do not need to max out at 1 as only the shape of the curve matters. The Y values cannot however be negative.")]
public AnimationCurve distributionCurve;
public void CheckAgainstValidRange()
{
throw new NotImplementedException();
//no range check currently performed for this sampler
}
///<inheritdoc/>
[field: HideInInspector]
[field: SerializeField]
public float minAllowed { get; set; }
///<inheritdoc/>
[field: HideInInspector]
[field: SerializeField]
public float maxAllowed { get; set; }
///<inheritdoc/>
[field: HideInInspector]
[field: SerializeField]
public bool shouldCheckValidRange { get; set; }
/// <summary>
/// Number of samples used for integrating over the provided AnimationCurve.

42
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/ConstantSampler.cs


using System;
using UnityEngine.Assertions;
namespace UnityEngine.Perception.Randomization.Samplers
{

/// </summary>
public float value;
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public float minAllowed { get; set; }
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public float maxAllowed { get; set; }
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public bool shouldCheckValidRange { get; set; }
/// <summary>
/// Constructs a ConstantSampler
/// </summary>

/// Constructs a new ConstantSampler
/// </summary>
/// <param name="value">The value from which samples will be generated</param>
public ConstantSampler(float value)
/// <param name="shouldCheckValidRange">Whether the provided <see cref="minAllowed"/> and <see cref="maxAllowed"/> values should be used to validate the <see cref="value"/> provided</param>
/// <param name="minAllowed">The smallest min value allowed for this range</param>
/// <param name="maxAllowed">The largest max value allowed for this range</param>
public ConstantSampler(float value, bool shouldCheckValidRange = false, float minAllowed = 0, float maxAllowed = 0)
this.shouldCheckValidRange = shouldCheckValidRange;
this.minAllowed = minAllowed;
this.maxAllowed = maxAllowed;
}
/// <summary>

/// <summary>
/// Validates that the sampler is configured properly
/// </summary>
public void Validate() {}
public void Validate()
{
Assert.IsTrue(!shouldCheckValidRange || value >= minAllowed && value <= maxAllowed);
}
public void CheckAgainstValidRange()
{
if (shouldCheckValidRange && (value < minAllowed || value > maxAllowed))
{
Debug.LogError($"The value a {GetType().Name} exceeds the allowed valid range. Clamping to valid range.");
value = Mathf.Clamp(value, minAllowed, maxAllowed);
}
}
}
}

39
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/NormalSampler.cs


using System;
using UnityEngine.Assertions;
namespace UnityEngine.Perception.Randomization.Samplers
{

mean = 0;
standardDeviation = 1;
}
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public float minAllowed { get; set; }
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public float maxAllowed { get; set; }
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public bool shouldCheckValidRange { get; set; }
/// <summary>
/// Constructs a normal distribution sampler

/// <param name="mean">The mean of the normal distribution to sample from</param>
/// <param name="standardDeviation">The standard deviation of the normal distribution to sample from</param>
/// <param name="shouldCheckValidRange">Whether the provided <see cref="minAllowed"/> and <see cref="maxAllowed"/> values should be used to validate the range provided with <see cref="minimum"/> and <see cref="maximum"/></param>
/// <param name="minAllowed">The smallest min value allowed for this range</param>
/// <param name="maxAllowed">The largest max value allowed for this range</param>
float min, float max, float mean, float standardDeviation)
float min, float max, float mean, float standardDeviation, bool shouldCheckValidRange = false, float minAllowed = 0, float maxAllowed = 0)
this.shouldCheckValidRange = shouldCheckValidRange;
this.minAllowed = minAllowed;
this.maxAllowed = maxAllowed;
}
/// <summary>

public void Validate()
{
range.Validate();
CheckAgainstValidRange();
}
public void CheckAgainstValidRange()
{
if (shouldCheckValidRange)
{
Debug.LogError($"The provided min and max values for a {GetType().Name} exceed the allowed valid range. Clamping to valid range.");
range.minimum = Mathf.Clamp(range.minimum, minAllowed, maxAllowed);
range.maximum = Mathf.Clamp(range.maximum, minAllowed, maxAllowed);
}
}
}
}

39
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/UniformSampler.cs


using System;
using UnityEngine.Assertions;
namespace UnityEngine.Perception.Randomization.Samplers
{

/// A range bounding the values generated by this sampler
/// </summary>
public FloatRange range;
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public float minAllowed { get; set; }
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public float maxAllowed { get; set; }
///<inheritdoc/>
#if !SCENARIO_CONFIG_POWER_USER
[field: HideInInspector]
#endif
[field: SerializeField]
public bool shouldCheckValidRange { get; set; }
/// <summary>
/// Constructs a UniformSampler

/// </summary>
/// <param name="min">The smallest value contained within the range</param>
/// <param name="max">The largest value contained within the range</param>
public UniformSampler(float min, float max)
/// <param name="shouldCheckValidRange">Whether the provided <see cref="minAllowed"/> and <see cref="maxAllowed"/> values should be used to validate the range provided with <see cref="minimum"/> and <see cref="maximum"/></param>
/// <param name="minAllowed">The smallest min value allowed for this range</param>
/// <param name="maxAllowed">The largest max value allowed for this range</param>
public UniformSampler(float min, float max, bool shouldCheckValidRange = false, float minAllowed = 0, float maxAllowed = 0)
this.shouldCheckValidRange = shouldCheckValidRange;
this.minAllowed = minAllowed;
this.maxAllowed = maxAllowed;
}
/// <summary>

public void Validate()
{
range.Validate();
CheckAgainstValidRange();
}
public void CheckAgainstValidRange()
{
if (shouldCheckValidRange && (range.minimum < minAllowed || range.maximum > maxAllowed))
{
Debug.LogError($"The provided min and max values for a {GetType().Name} exceed the allowed valid range. Clamping to valid range.");
range.minimum = Mathf.Clamp(range.minimum, minAllowed, maxAllowed);
range.maximum = Mathf.Clamp(range.maximum, minAllowed, maxAllowed);
}
}
}
}

1
com.unity.perception/Runtime/Randomization/Scenarios/Serialization/JsonConverters.cs


scalar.value = new BooleanScalarValue { boolean = value["bool"].Value<bool>() };
else
throw new KeyNotFoundException("No valid ScalarValue key type found");
return scalar;
}
}

145
com.unity.perception/Runtime/Randomization/Scenarios/Serialization/ScenarioSerializer.cs


randomizerData.items.Add(field.Name, new Scalar { value = scalarValue });
}
}
var properties = randomizer.GetType().GetProperties();
foreach (var property in properties)
{
if (property.PropertyType.IsSubclassOf(typeof(Randomization.Parameters.Parameter)))
{
if (!IsSubclassOfRawGeneric(typeof(NumericParameter<>), property.PropertyType))
continue;
var parameter = (Randomization.Parameters.Parameter)property.GetValue(randomizer);
var parameterData = SerializeParameter(parameter);
if (parameterData.items.Count == 0)
continue;
randomizerData.items.Add(property.Name, parameterData);
}
else
{
var scalarValue = ScalarFromProperty(property, randomizer);
if (scalarValue != null)
randomizerData.items.Add(property.Name, new Scalar { value = scalarValue });
}
}
return randomizerData;
}

if (sampler is Samplers.ConstantSampler constantSampler)
samplerData.defaultSampler = new ConstantSampler
{
value = constantSampler.value
value = constantSampler.value,
minAllowed = constantSampler.minAllowed,
maxAllowed = constantSampler.maxAllowed,
shouldCheckValidRange = constantSampler.shouldCheckValidRange
max = uniformSampler.range.maximum
max = uniformSampler.range.maximum,
minAllowed = uniformSampler.minAllowed,
maxAllowed = uniformSampler.maxAllowed,
shouldCheckValidRange = uniformSampler.shouldCheckValidRange
};
else if (sampler is Samplers.NormalSampler normalSampler)
samplerData.defaultSampler = new NormalSampler

mean = normalSampler.mean,
stddev = normalSampler.standardDeviation
stddev = normalSampler.standardDeviation,
minAllowed = normalSampler.minAllowed,
maxAllowed = normalSampler.maxAllowed,
shouldCheckValidRange = normalSampler.shouldCheckValidRange
};
else
throw new ArgumentException($"Invalid sampler type ({sampler.GetType()})");

if (field.FieldType == typeof(bool))
return new BooleanScalarValue { boolean = (bool)field.GetValue(obj) };
if (field.FieldType == typeof(float) || field.FieldType == typeof(double) || field.FieldType == typeof(int))
return new DoubleScalarValue { num = Convert.ToDouble(field.GetValue(obj)) };
{
var minAllowed = 0f;
var maxAllowed = 0f;
var shouldCheckValidRange = false;
var rangeAttributes = field.GetCustomAttributes(typeof(RangeAttribute));
if (rangeAttributes.Any())
{
var rangeAttribute = (RangeAttribute)rangeAttributes.First();
minAllowed = rangeAttribute.min;
maxAllowed = rangeAttribute.max;
shouldCheckValidRange = true;
}
return new DoubleScalarValue
{
num = Convert.ToDouble(field.GetValue(obj)),
minAllowed = minAllowed,
maxAllowed = maxAllowed,
shouldCheckValidRange = shouldCheckValidRange
};
}
return null;
}
static IScalarValue ScalarFromProperty(PropertyInfo property, object obj)
{
if (property.PropertyType == typeof(string))
return new StringScalarValue { str = (string)property.GetValue(obj) };
if (property.PropertyType == typeof(bool))
return new BooleanScalarValue { boolean = (bool)property.GetValue(obj) };
if (property.PropertyType == typeof(float) || property.PropertyType == typeof(double) || property.PropertyType == typeof(int))
return new DoubleScalarValue { num = Convert.ToDouble(property.GetValue(obj)) };
//Properties cannot have a Range attribute like fields so no need to check for it here (see function similar to this for fields)
return null;
}
#endregion

foreach (var pair in randomizerData.items)
{
var field = randomizer.GetType().GetField(pair.Key);
if (field == null)
if (field != null)
{
if (pair.Value is Parameter parameterData)
DeserializeParameter((Randomization.Parameters.Parameter)field.GetValue(randomizer), parameterData);
else
DeserializeScalarValue(randomizer, field, (Scalar)pair.Value);
if (pair.Value is Parameter parameterData)
DeserializeParameter((Randomization.Parameters.Parameter)field.GetValue(randomizer), parameterData);
else
DeserializeScalarValue(randomizer, field, (Scalar)pair.Value);
}
var property = randomizer.GetType().GetProperty(pair.Key);
if (property != null)
{
if (pair.Value is Parameter parameterData)
DeserializeParameter((Randomization.Parameters.Parameter)property.GetValue(randomizer), parameterData);
else
DeserializeScalarValue(randomizer, property, (Scalar)pair.Value);
}
}
}

if (samplerOption is ConstantSampler constantSampler)
return new Samplers.ConstantSampler
{
value = (float)constantSampler.value
value = (float)constantSampler.value,
minAllowed = (float)constantSampler.minAllowed,
maxAllowed = (float)constantSampler.maxAllowed,
shouldCheckValidRange = constantSampler.shouldCheckValidRange
};
if (samplerOption is UniformSampler uniformSampler)
return new Samplers.UniformSampler

minimum = (float)uniformSampler.min,
maximum = (float)uniformSampler.max
}
maximum = (float)uniformSampler.max,
},
minAllowed = (float)uniformSampler.minAllowed,
maxAllowed = (float)uniformSampler.maxAllowed,
shouldCheckValidRange = uniformSampler.shouldCheckValidRange
};
if (samplerOption is NormalSampler normalSampler)
return new Samplers.NormalSampler

maximum = (float)normalSampler.max
},
mean = (float)normalSampler.mean,
standardDeviation = (float)normalSampler.stddev
standardDeviation = (float)normalSampler.stddev,
minAllowed = (float)normalSampler.minAllowed,
maxAllowed = (float)normalSampler.maxAllowed,
shouldCheckValidRange = normalSampler.shouldCheckValidRange
};
throw new ArgumentException($"Cannot deserialize unsupported sampler type {samplerOption.GetType()}");
}

var rangeAttributes = field.GetCustomAttributes(typeof(RangeAttribute));
RangeAttribute rangeAttribute = null;
if (rangeAttributes.Any())
{
rangeAttribute = (RangeAttribute) rangeAttributes.First();
}
var value = ReadScalarValue(obj, scalar);
if (value is double num && rangeAttribute != null && (num < rangeAttribute.min || num > rangeAttribute.max))
{
Debug.LogError($"The provided value for the field \"{field.Name}\" of \"{obj.GetType().Name}\" exceeds the allowed valid range. Clamping to valid range.");
var clamped = Mathf.Clamp((float)num, rangeAttribute.min, rangeAttribute.max);
field.SetValue(obj, Convert.ChangeType(clamped, field.FieldType));
}
else
{
field.SetValue(obj, Convert.ChangeType(value, field.FieldType));
}
}
static void DeserializeScalarValue(object obj, PropertyInfo property, Scalar scalar)
{
//Properties cannot have a Range attribute like fields so no need to check for it here (see this function's overload for fields)
var value = ReadScalarValue(obj, scalar);
property.SetValue(obj, Convert.ChangeType(value, property.PropertyType));
}
static object ReadScalarValue(object obj, Scalar scalar)
{
object value;
if (scalar.value is StringScalarValue stringValue)
value = stringValue.str;

else
throw new ArgumentException(
$"Cannot deserialize unsupported scalar type {scalar.value.GetType()}");
field.SetValue(obj, Convert.ChangeType(value, field.FieldType));
return value;
}
#endregion

12
com.unity.perception/Runtime/Randomization/Scenarios/Serialization/SerializationStructures.cs


{
public double min;
public double max;
public double minAllowed;
public double maxAllowed;
public bool shouldCheckValidRange;
}
class NormalSampler : ISamplerOption

public double mean;
public double stddev;
public double minAllowed;
public double maxAllowed;
public bool shouldCheckValidRange;
public double minAllowed;
public double maxAllowed;
public bool shouldCheckValidRange;
}
#endregion

class DoubleScalarValue : IScalarValue
{
public double num;
public double minAllowed;
public double maxAllowed;
public bool shouldCheckValidRange;
}
class BooleanScalarValue : IScalarValue

正在加载...
取消
保存