浏览代码

almost done now

/main
Mohsen Kamalzadeh 4 年前
当前提交
fb5da2c0
共有 14 个文件被更改,包括 347 次插入3 次删除
  1. 7
      com.unity.perception/Editor/Randomization/VisualElements/Sampler/SamplerElement.cs
  2. 22
      com.unity.perception/Runtime/Randomization/Parameters/Parameter.cs
  3. 21
      com.unity.perception/Runtime/Randomization/Randomizers/Randomizer.cs
  4. 10
      com.unity.perception/Runtime/Randomization/Samplers/ISampler.cs
  5. 10
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/ConstantSampler.cs
  6. 10
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/NormalSampler.cs
  7. 10
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/UniformSampler.cs
  8. 64
      com.unity.perception/Runtime/Randomization/Samplers/SamplerUtility.cs
  9. 10
      com.unity.perception/Runtime/Randomization/Scenarios/Scenario.cs
  10. 8
      com.unity.perception/Runtime/Randomization/Scenarios/ScenarioBase.cs
  11. 141
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/AnimationCurveSampler.cs
  12. 11
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/AnimationCurveSampler.cs.meta
  13. 15
      com.unity.perception/Tests/Runtime/Randomization/SamplerTests/AnimationCurveSamplerTests.cs
  14. 11
      com.unity.perception/Tests/Runtime/Randomization/SamplerTests/AnimationCurveSamplerTests.cs.meta

7
com.unity.perception/Editor/Randomization/VisualElements/Sampler/SamplerElement.cs


using System;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.Experimental.Perception.Randomization.Parameters;

{
var propertyField = new PropertyField(currentProperty.Copy());
propertyField.Bind(m_Property.serializedObject);
var originalField = m_Sampler.GetType().GetField(currentProperty.name);
var tooltipAttribute = originalField.GetCustomAttributes(true).ToList().Find(att => att.GetType() == typeof(TooltipAttribute));
if (tooltipAttribute != null)
{
propertyField.tooltip = (tooltipAttribute as TooltipAttribute)?.tooltip;
}
m_Properties.Add(propertyField);
}
}

22
com.unity.perception/Runtime/Randomization/Parameters/Parameter.cs


/// Validates parameter settings
/// </summary>
public virtual void Validate() { }
/// <summary>
/// Perform clean-up tasks for all samplers
/// </summary>
public virtual void CleanupSamplers()
{
foreach (var sampler in samplers)
{
sampler.Cleanup();
}
}
/// <summary>
/// Perform initialization tasks for all samplers
/// </summary>
public virtual void InitializeSamplers()
{
foreach (var sampler in samplers)
{
sampler.Initialize();
}
}
}
}

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


/// <summary>
/// OnScenarioComplete is called the after the entire scenario has completed
/// </summary>
protected virtual void OnScenarioComplete() { }
protected virtual void OnScenarioComplete()
{
CleanupSamplers();
}
/// <summary>
/// OnStartRunning is called on the first frame a Randomizer is enabled

{
m_PreviouslyEnabled = false;
OnStopRunning();
}
}
internal void CleanupSamplers()
{
foreach (var parameter in parameters)
{
parameter.CleanupSamplers();
}
}
internal void InitializeSamplers()
{
foreach (var parameter in parameters)
{
parameter.InitializeSamplers();
}
}
}

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


/// <param name="jobHandle">The handle of the scheduled job</param>
/// <returns>A NativeArray of generated samples</returns>
NativeArray<float> Samples(int sampleCount, out JobHandle jobHandle);
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
void Cleanup();
/// <summary>
/// Used for performing sampler specific initialization tasks.
/// </summary>
void Initialize();
}
}

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


samples[i] = value;
}
}
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
public void Cleanup() { }
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
public void Initialize() { }
}
}

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


}
}
}
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
public void Cleanup() { }
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
public void Initialize() { }
}
}

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


samples[i] = rng.NextFloat(min, max);
}
}
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
public void Cleanup() { }
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
public void Initialize() { }
}
}

64
com.unity.perception/Runtime/Randomization/Samplers/SamplerUtility.cs


using System;
using System.Runtime.CompilerServices;
using Unity.Collections;
using Unity.Mathematics;
namespace UnityEngine.Experimental.Perception.Randomization.Samplers

var stdTruncNorm = NormalCdfInverse(c);
return stdTruncNorm * stdDev + mean;
}
/// <summary>
/// Generate samples from probability distribution derived from a given AnimationCurve.
/// </summary>
/// <param name="integratedCurve">Numerical integration representing the AnimationCurve</param>
/// <param name="uniformSample">A sample value between 0 and 1 generated from a uniform distribution</param>
/// <param name="interval">The interval at which the original AnimationCurve was sampled in order to produce integratedCurve</param>
/// <param name="startTime">The time attribute of the first key of the original AnimationCurve</param>
/// <param name="endTime">The time attribute of the last key of the original AnimationCurve</param>
/// <returns></returns>
public static float AnimationCurveSample(NativeArray<float> integratedCurve, float uniformSample, float interval, float startTime, float endTime)
{
var scaledSample = uniformSample * integratedCurve[integratedCurve.Length - 1];
for (int i = 0; i < integratedCurve.Length - 1; i++)
{
if (scaledSample > integratedCurve[i] && scaledSample < integratedCurve[i + 1])
{
var valueDifference = integratedCurve[i + 1] - integratedCurve[i];
var upperWeight = (scaledSample - integratedCurve[i]) / valueDifference;
var lowerWeight = 1 - upperWeight;
var matchingIndex = (i * lowerWeight) + (i + 1 * upperWeight);
var matchingTimeStamp = startTime + matchingIndex * interval;
return matchingTimeStamp;
}
}
Debug.LogError("Could not find matching timestamp");
return -1;
}
/// <summary>
/// Numerically integrate a given AnimationCurve using the specified number of samples.
/// Based on https://en.wikipedia.org/wiki/Numerical_integration and http://blog.s-schoener.com/2018-05-05-animation-curves/
/// Using the trapezoidal rule for numerical interpolation
/// </summary>
public static void IntegrateCurve(NativeArray<float> array, AnimationCurve curve)
{
if (curve.length == 0)
{
throw new ArgumentException("The provided Animation Curve includes no keys.");
}
var startTime = curve.keys[0].time;
var endTime = curve.keys[curve.length - 1].time;
var interval = (endTime - startTime) / (array.Length - 1);
array[0] = 0;
var previousValue = curve.Evaluate(startTime);
for (int i = 1; i < array.Length; i++)
{
if (curve.length == 1)
{
array[i] = previousValue;
}
else
{
var currentTime = startTime + i * interval;
var currentValue = curve.Evaluate(currentTime);
array[i] = array[i-1] + (previousValue + currentValue) * interval / 2;
previousValue = currentValue;
}
}
}
}
}

10
com.unity.perception/Runtime/Randomization/Scenarios/Scenario.cs


using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine.Experimental.Perception.Randomization.Parameters;

var samplerObj = new JObject();
var fields = sampler.GetType().GetFields();
foreach (var field in fields)
samplerObj.Add(new JProperty(field.Name, field.GetValue(sampler)));
{
samplerObj.Add(new JProperty(field.Name, JToken.FromObject(field.GetValue(sampler))));
}
if (sampler.GetType() != typeof(ConstantSampler))
{
var rangeProperty = sampler.GetType().GetProperty("range");

{
var field = sampler.GetType().GetField(samplerFieldPair.Key);
if (field != null)
field.SetValue(sampler, ((JValue)samplerFieldPair.Value).Value);
{
field.SetValue(sampler, JsonConvert.DeserializeObject(samplerFieldPair.Value.ToString(), field.FieldType));
}
}
}
}

8
com.unity.perception/Runtime/Randomization/Scenarios/ScenarioBase.cs


}
}
}
void OnApplicationQuit()
{
foreach (var randomizer in m_Randomizers)
{
randomizer.CleanupSamplers();
}
}
}
}

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


using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine.Experimental.Perception.Randomization.Scenarios;
namespace UnityEngine.Experimental.Perception.Randomization.Samplers
{
/// <summary>
/// Returns random values according to a range and probability distribution denoted by a user provided AnimationCurve. The X axis of the AnimationCurve 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.
/// </summary>
[Serializable]
public class AnimationCurveSampler : ISampler
{
/// <summary>
/// The range field is not used by the AnimationCurve sampler.
/// </summary>
[field: NonSerialized]
public FloatRange range { get; set; }
/// <summary>
/// The Animation Curve associated with this sampler
/// </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;
NativeArray<float> m_IntegratedCurve;
bool m_CurveValid;
float m_StartTime;
float m_EndTime;
float m_Interval;
int m_NumOfSamples = 100;
/// <summary>
/// Constructs an Animation Curve Sampler
/// </summary>
public AnimationCurveSampler()
{
distributionCurve = new AnimationCurve();
distributionCurve.AddKey(0, 0);
distributionCurve.AddKey(0.5f, 1);
distributionCurve.AddKey(1, 0);
}
/// <summary>
/// Generates one sample
/// </summary>
/// <returns>The generated sample</returns>
public float Sample()
{
var rng = new Unity.Mathematics.Random(ScenarioBase.activeScenario.NextRandomState());
return SamplerUtility.AnimationCurveSample(m_IntegratedCurve, rng.NextFloat(), m_Interval, m_StartTime, m_EndTime);
}
/// <summary>
/// Schedules a job to generate an array of samples
/// </summary>
/// <param name="sampleCount">The number of samples to generate</param>
/// <param name="jobHandle">The handle of the scheduled job</param>
/// <returns>A NativeArray of generated samples</returns>
public NativeArray<float> Samples(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<float>(
sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
jobHandle = new SampleJob
{
integratedCurve = m_IntegratedCurve,
interval = m_Interval,
startTime = m_StartTime,
endTime = m_EndTime,
seed = ScenarioBase.activeScenario.NextRandomState(),
curveValid = m_CurveValid,
samples = samples
}.ScheduleBatch(sampleCount, SamplerUtility.samplingBatchSize);
return samples;
}
[BurstCompile]
struct SampleJob : IJobParallelForBatch
{
public NativeArray<float> integratedCurve;
public float interval;
public float startTime;
public float endTime;
public uint seed;
public NativeArray<float> samples;
public bool curveValid;
public void Execute(int startIndex, int count)
{
var endIndex = startIndex + count;
var batchIndex = startIndex / SamplerUtility.samplingBatchSize;
var rng = new Unity.Mathematics.Random(SamplerUtility.IterateSeed((uint)batchIndex, seed));
if (!curveValid)
{
Debug.LogError("The distribution curve provided for an Animation Curve sampler is empty.");
return;
}
for (var i = startIndex; i < endIndex; i++)
samples[i] = SamplerUtility.AnimationCurveSample(integratedCurve, rng.NextFloat(), interval, startTime, endTime);
}
}
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
public void Cleanup()
{
if (m_IntegratedCurve.IsCreated)
{
m_IntegratedCurve.Dispose();
}
}
/// <summary>
/// Used for performing sampler specific clean-up tasks (e.g. once the scenario is complete).
/// </summary>
public void Initialize()
{
m_CurveValid = false;
if (distributionCurve.length == 0)
{
Debug.LogError("The distribution curve provided for an Animation Curve sampler is empty.");
return;
}
m_CurveValid = true;
if (!m_IntegratedCurve.IsCreated)
{
m_IntegratedCurve = new NativeArray<float>(m_NumOfSamples, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
SamplerUtility.IntegrateCurve(m_IntegratedCurve, distributionCurve);
m_StartTime = distributionCurve.keys[0].time;
m_EndTime = distributionCurve.keys[distributionCurve.length - 1].time;
m_Interval = (m_EndTime - m_StartTime) / (m_NumOfSamples - 1);
}
}
}
}

11
com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/AnimationCurveSampler.cs.meta


fileFormatVersion: 2
guid: d4147226e4d134ac8b0c69c14db5d23b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

15
com.unity.perception/Tests/Runtime/Randomization/SamplerTests/AnimationCurveSamplerTests.cs


using NUnit.Framework;
using UnityEngine.Experimental.Perception.Randomization.Samplers;
namespace RandomizationTests.SamplerTests
{
[TestFixture]
public class AnimationCurveSamplerTests : RangedSamplerTests<AnimationCurveSampler>
{
public AnimationCurveSamplerTests()
{
m_BaseSampler = new AnimationCurveSampler();
m_BaseSampler.range = new FloatRange(m_BaseSampler.distributionCurve.keys[0].time, m_BaseSampler.distributionCurve.keys[m_BaseSampler.distributionCurve.length - 1].time);
}
}
}

11
com.unity.perception/Tests/Runtime/Randomization/SamplerTests/AnimationCurveSamplerTests.cs.meta


fileFormatVersion: 2
guid: 15fca3a26ddcf4459be02aea956806bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存