浏览代码

Modifications after peer review

- Removed native sampling (through jobs) capability from all samplers and parameters as no users have so far needed this, and it introduces additional complexity to the code
- Removed native sampling from the newly introduced AnimationCurveSampler.
- Removed the sampler initialization and cleanup functions based on feedback.
- Modified all randomization tests to not use native sampling
- Removed native sampling related sections from docs
/main
Mohsen Kamalzadeh 4 年前
当前提交
6a9a43d9
共有 23 个文件被更改,包括 39 次插入746 次删除
  1. 2
      com.unity.perception/CHANGELOG.md
  2. 8
      com.unity.perception/Documentation~/Randomization/Index.md
  3. 34
      com.unity.perception/Documentation~/Randomization/Parameters.md
  4. 9
      com.unity.perception/Runtime/Randomization/Parameters/NumericParameter.cs
  5. 22
      com.unity.perception/Runtime/Randomization/Parameters/Parameter.cs
  6. 33
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/BooleanParameter.cs
  7. 111
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorHsvaParameter.cs
  8. 52
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorRgbParameter.cs
  9. 11
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/FloatParameter.cs
  10. 31
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/IntegerParameter.cs
  11. 35
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector2Parameter.cs
  12. 38
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector3Parameter.cs
  13. 51
      com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector4Parameter.cs
  14. 26
      com.unity.perception/Runtime/Randomization/Randomizers/Randomizer.cs
  15. 18
      com.unity.perception/Runtime/Randomization/Samplers/ISampler.cs
  16. 82
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/AnimationCurveSampler.cs
  17. 41
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/ConstantSampler.cs
  18. 55
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/NormalSampler.cs
  19. 48
      com.unity.perception/Runtime/Randomization/Samplers/SamplerTypes/UniformSampler.cs
  20. 4
      com.unity.perception/Runtime/Randomization/Samplers/SamplerUtility.cs
  21. 8
      com.unity.perception/Runtime/Randomization/Scenarios/ScenarioBase.cs
  22. 19
      com.unity.perception/Tests/Runtime/Randomization/ParameterTests/StructParameterTests.cs
  23. 47
      com.unity.perception/Tests/Runtime/Randomization/SamplerTests/SamplerTestsBase.cs

2
com.unity.perception/CHANGELOG.md


Removed ScenarioBase.GenerateRandomSeedFromIndex()
Removed native sampling (through jobs) capability from all samplers and parameters as it introduced additional complexity to the code and was not a common usage pattern
### Fixed
Fixed an issue where the overlay panel would display a full screen semi-transparent image over the entire screen when the overlay panel is disabled in the UI

8
com.unity.perception/Documentation~/Randomization/Index.md


Randomizers encapsulate specific randomization activities to perform during the lifecycle of a randomized simulation. For example, randomizers exist for spawning objects, repositioning lights, varying the color of objects, etc. Randomizers expose random parameters to their inspector interface to further customize these variations.
To read more about how to create custom parameter types, navigate over to the [randomizers doc](Randomizers.md).
To read more about how to create custom parameter types, navigate over to the **[Randomizers doc](Randomizers.md)**.
## Randomizer Tags

To read more about how to use RandomizerTags, navigate over to the [RandomizerTags doc](RandomizerTags.md).
To read more about how to use RandomizerTags, navigate over to the **[RandomizerTags doc](RandomizerTags.md)**.
## Parameters

To read more about how to create custom parameter types, navigate over to the [parameters doc](Parameters.md).
To read more about how to create custom parameter types, navigate over to the **[Parameters doc](Parameters.md)**.
## Samplers

Take a look at the [samplers doc](Samplers.md) to learn more about implementing custom probability distributions and samplers that can integrate with the perception package.
Take a look at the **[Samplers doc](Samplers.md)** to learn more about implementing custom probability distributions and samplers that can integrate with the perception package.
## Getting Started

34
com.unity.perception/Documentation~/Randomization/Parameters.md


### Numeric Parameters
Numeric parameters use samplers to generate randomized structs. Take a look at the [ColorHsvaParameter]() class included in the perception package for an example on how to implement a numeric parameter.
## Improving Sampling Performance
For numeric parameters, it is recommended to use the JobHandle overload of the Samples() method when generating a large number of samples. The JobHandle overload will utilize the Unity Burst Compiler and Job System to automatically optimize and multithread parameter sampling jobs. The code block below is an example of how to use this overload to sample two parameters in parallel:
```
// Get a reference to the parameter configuration attached to this GameObject
var parameterConfiguration = GetComponent<ParameterConfiguration>();
// Lookup parameters
var cubeColorParameter = parameterConfiguration.GetParameter<HsvaColorParameter>("CubeColor");
var cubePositionParameter = parameterConfiguration.GetParameter<Vector3Parameter>("CubePosition");
// Schedule sampling jobs
var cubeColors = cubeColorParameter.Samples(constants.cubeCount, out var colorHandle);
var cubePositions = cubePositionParameter.Samples(constants.cubeCount, out var positionHandle);
// Combine job handles
var handles = JobHandle.CombineDependencies(colorHandle, positionHandle);
// Wait for the jobs to complete
handles.Complete();
// Use the created samples
for (var i = 0; i < constants.cubeCount; i++)
{
m_ObjectMaterials[i].SetColor(k_BaseColorProperty, cubeColors[i]);
m_Objects[i].transform.position = cubePositions[i];
}
// Dispose of the generated samples
cubeColors.Dispose();
cubePositions.Dispose();
```
Numeric parameters use samplers to generate randomized structs. Take a look at the [ColorHsvaParameter]() class included in the perception package for an example on how to implement a numeric parameter.

9
com.unity.perception/Runtime/Randomization/Parameters/NumericParameter.cs


public abstract T Sample();
/// <summary>
/// Schedules a job to generate an array of parameter samples.
/// Call Complete() on the JobHandle returned by this function to wait on the job generating the parameter samples.
/// </summary>
/// <param name="sampleCount">Number of parameter samples to generate</param>
/// <param name="jobHandle">The JobHandle returned from scheduling the sampling job</param>
/// <returns>A NativeArray containing generated samples</returns>
public abstract NativeArray<T> Samples(int sampleCount, out JobHandle jobHandle);
/// <summary>
/// Generates a generic sample
/// </summary>
/// <returns>The generated sample</returns>

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();
}
}
}
}

33
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/BooleanParameter.cs


{
return Sample(value.Sample());
}
/// <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 samples</returns>
public override NativeArray<bool> Samples(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<bool>(sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
var rngSamples = value.Samples(sampleCount, out jobHandle);
jobHandle = new SamplesJob
{
rngSamples = rngSamples,
samples = samples,
threshold = threshold
}.Schedule(jobHandle);
return samples;
}
[BurstCompile]
struct SamplesJob : IJob
{
[DeallocateOnJobCompletion] public NativeArray<float> rngSamples;
public NativeArray<bool> samples;
public float threshold;
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
samples[i] = rngSamples[i] >= threshold;
}
}
}
}

111
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorHsvaParameter.cs


{
return new ColorHsva(hue.Sample(), saturation.Sample(), value.Sample(), alpha.Sample());
}
/// <summary>
/// Schedules a job to generate an array of RGBA color 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 samples</returns>
public override NativeArray<Color> Samples(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<Color>(sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
var hueRng = hue.Samples(sampleCount, out var hueHandle);
var satRng = saturation.Samples(sampleCount, out var satHandle);
var valRng = value.Samples(sampleCount, out var valHandle);
var alphaRng = alpha.Samples(sampleCount, out var alphaHandle);
var handles = new NativeArray<JobHandle>(4, Allocator.TempJob)
{
[0] = hueHandle,
[1] = satHandle,
[2] = valHandle,
[3] = alphaHandle
};
var combinedJobHandles = JobHandle.CombineDependencies(handles);
jobHandle = new SamplesJob
{
hueRng = hueRng,
satRng = satRng,
valRng = valRng,
alphaRng = alphaRng,
samples = samples
}.Schedule(combinedJobHandles);
handles.Dispose(jobHandle);
return samples;
}
[BurstCompile]
struct SamplesJob : IJob
{
[DeallocateOnJobCompletion] public NativeArray<float> hueRng;
[DeallocateOnJobCompletion] public NativeArray<float> satRng;
[DeallocateOnJobCompletion] public NativeArray<float> valRng;
[DeallocateOnJobCompletion] public NativeArray<float> alphaRng;
public NativeArray<Color> samples;
static Color CreateColorHsva(float h, float s, float v, float a)
{
var color = Color.HSVToRGB(h, s, v);
color.a = a;
return color;
}
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
samples[i] = CreateColorHsva(hueRng[i], satRng[i], valRng[i], alphaRng[i]);
}
}
/// <summary>
/// Schedules a job to generate an array of HSVA color 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 samples</returns>
public NativeArray<ColorHsva> SamplesHsva(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<ColorHsva>(sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
var hueRng = hue.Samples(sampleCount, out var hueHandle);
var satRng = saturation.Samples(sampleCount, out var satHandle);
var valRng = value.Samples(sampleCount, out var valHandle);
var alphaRng = alpha.Samples(sampleCount, out var alphaHandle);
var handles = new NativeArray<JobHandle>(4, Allocator.TempJob)
{
[0] = hueHandle,
[1] = satHandle,
[2] = valHandle,
[3] = alphaHandle
};
var combinedJobHandles = JobHandle.CombineDependencies(handles);
jobHandle = new SamplesHsvaJob
{
hueRng = hueRng,
satRng = satRng,
valRng = valRng,
alphaRng = alphaRng,
samples = samples
}.Schedule(combinedJobHandles);
handles.Dispose(jobHandle);
return samples;
}
[BurstCompile]
struct SamplesHsvaJob : IJob
{
[DeallocateOnJobCompletion] public NativeArray<float> hueRng;
[DeallocateOnJobCompletion] public NativeArray<float> satRng;
[DeallocateOnJobCompletion] public NativeArray<float> valRng;
[DeallocateOnJobCompletion] public NativeArray<float> alphaRng;
public NativeArray<ColorHsva> samples;
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
samples[i] = new ColorHsva(hueRng[i], satRng[i], valRng[i], alphaRng[i]);
}
}
}
}

52
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/ColorParameters/ColorRgbParameter.cs


{
return new Color(red.Sample(), green.Sample(), blue.Sample(), alpha.Sample());
}
/// <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 samples</returns>
public override NativeArray<Color> Samples(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<Color>(sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
var redRng = red.Samples(sampleCount, out var redHandle);
var greenRng = green.Samples(sampleCount, out var greenHandle);
var blueRng = blue.Samples(sampleCount, out var blueHandle);
var alphaRng = alpha.Samples(sampleCount, out var alphaHandle);
var handles = new NativeArray<JobHandle>(4, Allocator.TempJob)
{
[0] = redHandle,
[1] = greenHandle,
[2] = blueHandle,
[3] = alphaHandle
};
var combinedJobHandles = JobHandle.CombineDependencies(handles);
jobHandle = new SamplesJob
{
redRng = redRng,
greenRng = greenRng,
blueRng = blueRng,
alphaRng = alphaRng,
samples = samples
}.Schedule(combinedJobHandles);
handles.Dispose(jobHandle);
return samples;
}
[BurstCompile]
struct SamplesJob : IJob
{
[DeallocateOnJobCompletion] public NativeArray<float> redRng;
[DeallocateOnJobCompletion] public NativeArray<float> greenRng;
[DeallocateOnJobCompletion] public NativeArray<float> blueRng;
[DeallocateOnJobCompletion] public NativeArray<float> alphaRng;
public NativeArray<Color> samples;
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
samples[i] = new Color(redRng[i], greenRng[i], blueRng[i], alphaRng[i]);
}
}
}
}

11
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/FloatParameter.cs


{
return value.Sample();
}
/// <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 samples</returns>
public override NativeArray<float> Samples(int sampleCount, out JobHandle jobHandle)
{
return value.Samples(sampleCount, out jobHandle);
}
}
}

31
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/IntegerParameter.cs


/// </summary>
/// <returns>The generated sample</returns>
public override int Sample() => (int)value.Sample();
/// <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 samples</returns>
public override NativeArray<int> Samples(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<int>(sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
var rngSamples = value.Samples(sampleCount, out jobHandle);
jobHandle = new SamplesJob
{
rngSamples = rngSamples,
samples = samples
}.Schedule(jobHandle);
return samples;
}
[BurstCompile]
struct SamplesJob : IJob
{
[DeallocateOnJobCompletion] public NativeArray<float> rngSamples;
public NativeArray<int> samples;
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
samples[i] = (int)rngSamples[i];
}
}
}
}

35
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector2Parameter.cs


{
return new Vector2(x.Sample(), y.Sample());
}
/// <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 samples</returns>
public override NativeArray<Vector2> Samples(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<Vector2>(sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
var xRng = x.Samples(sampleCount, out var xHandle);
var yRng = y.Samples(sampleCount, out var yHandle);
var combinedJobHandles = JobHandle.CombineDependencies(xHandle, yHandle);
jobHandle = new SamplesJob
{
xRng = xRng,
yRng = yRng,
samples = samples
}.Schedule(combinedJobHandles);
return samples;
}
[BurstCompile]
struct SamplesJob : IJob
{
[DeallocateOnJobCompletion] public NativeArray<float> xRng;
[DeallocateOnJobCompletion] public NativeArray<float> yRng;
public NativeArray<Vector2> samples;
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
samples[i] = new Vector2(xRng[i], yRng[i]);
}
}
}
}

38
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector3Parameter.cs


{
return new Vector3(x.Sample(), y.Sample(), z.Sample());
}
/// <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 samples</returns>
public override NativeArray<Vector3> Samples(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<Vector3>(sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
var xRng = x.Samples(sampleCount, out var xHandle);
var yRng = y.Samples(sampleCount, out var yHandle);
var zRng = z.Samples(sampleCount, out var zHandle);
var combinedJobHandles = JobHandle.CombineDependencies(xHandle, yHandle, zHandle);
jobHandle = new SamplesJob
{
xRng = xRng,
yRng = yRng,
zRng = zRng,
samples = samples
}.Schedule(combinedJobHandles);
return samples;
}
[BurstCompile]
struct SamplesJob : IJob
{
[DeallocateOnJobCompletion] public NativeArray<float> xRng;
[DeallocateOnJobCompletion] public NativeArray<float> yRng;
[DeallocateOnJobCompletion] public NativeArray<float> zRng;
public NativeArray<Vector3> samples;
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
samples[i] = new Vector3(xRng[i], yRng[i], zRng[i]);
}
}
}
}

51
com.unity.perception/Runtime/Randomization/Parameters/ParameterTypes/NumericParameters/Vector4Parameter.cs


{
return new Vector4(x.Sample(), y.Sample(), z.Sample(), w.Sample());
}
/// <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 samples</returns>
public override NativeArray<Vector4> Samples(int sampleCount, out JobHandle jobHandle)
{
var samples = new NativeArray<Vector4>(sampleCount, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
var xRng = x.Samples(sampleCount, out var xHandle);
var yRng = y.Samples(sampleCount, out var yHandle);
var zRng = z.Samples(sampleCount, out var zHandle);
var wRng = w.Samples(sampleCount, out var wHandle);
var handles = new NativeArray<JobHandle>(4, Allocator.Temp)
{
[0] = xHandle,
[1] = yHandle,
[2] = zHandle,
[3] = wHandle
};
var combinedJobHandles = JobHandle.CombineDependencies(handles);
handles.Dispose();
jobHandle = new SamplesJob
{
xRng = xRng,
yRng = yRng,
zRng = zRng,
wRng = wRng,
samples = samples
}.Schedule(combinedJobHandles);
return samples;
}
[BurstCompile]
struct SamplesJob : IJob
{
[DeallocateOnJobCompletion] public NativeArray<float> xRng;
[DeallocateOnJobCompletion] public NativeArray<float> yRng;
[DeallocateOnJobCompletion] public NativeArray<float> zRng;
[DeallocateOnJobCompletion] public NativeArray<float> wRng;
public NativeArray<Vector4> samples;
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
samples[i] = new Vector4(xRng[i], yRng[i], zRng[i], wRng[i]);
}
}
}
}

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


/// <summary>
/// OnCreate is called when the Randomizer is added or loaded to a scenario
/// </summary>
protected virtual void OnCreate()
{
InitializeSamplers();
}
protected virtual void OnCreate() { }
/// <summary>
/// OnIterationStart is called at the start of a new scenario iteration

/// <summary>
/// OnScenarioComplete is called the after the entire scenario has completed
/// </summary>
protected virtual void OnScenarioComplete()
{
CleanupSamplers();
}
protected virtual void OnScenarioComplete() { }
/// <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();
}
}
}

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


/// </summary>
/// <returns>The generated sample</returns>
float Sample();
/// <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>
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();
}
}

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


[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;
float[] m_IntegratedCurve;
bool m_CurveValid;
float m_StartTime;
float m_EndTime;

/// <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
{
[ReadOnly]
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)
Initialize();
if (!m_CurveValid)
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);
}
return 0;
var rng = new Unity.Mathematics.Random(ScenarioBase.activeScenario.NextRandomState());
return SamplerUtility.AnimationCurveSample(m_IntegratedCurve, rng.NextFloat(), m_Interval, m_StartTime, m_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()
void Initialize()
{
m_CurveValid = false;

m_CurveValid = true;
if (!m_IntegratedCurve.IsCreated)
if (m_IntegratedCurve == null)
m_IntegratedCurve = new NativeArray<float>(m_NumOfSamples, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
m_IntegratedCurve = new float[m_NumOfSamples];
SamplerUtility.IntegrateCurve(m_IntegratedCurve, distributionCurve);
m_StartTime = distributionCurve.keys[0].time;

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


{
return value;
}
/// <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
{
value = value,
samples = samples
}.Schedule();
return samples;
}
[BurstCompile]
struct SampleJob : IJob
{
public float value;
public NativeArray<float> samples;
public void Execute()
{
for (var i = 0; i < samples.Length; i++)
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() { }
}
}

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


return SamplerUtility.TruncatedNormalSample(
rng.NextFloat(), range.minimum, range.maximum, mean, standardDeviation);
}
/// <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
{
min = range.minimum,
max = range.maximum,
mean = mean,
standardDeviation = standardDeviation,
seed = ScenarioBase.activeScenario.NextRandomState(),
samples = samples
}.ScheduleBatch(sampleCount, SamplerUtility.samplingBatchSize);
return samples;
}
[BurstCompile]
struct SampleJob : IJobParallelForBatch
{
public float min;
public float max;
public float mean;
public float standardDeviation;
public uint seed;
public NativeArray<float> samples;
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));
for (var i = startIndex; i < endIndex; i++)
{
samples[i] = SamplerUtility.TruncatedNormalSample(
rng.NextFloat(), min, max, mean, standardDeviation);
}
}
}
/// <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() { }
}
}

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


var rng = new Unity.Mathematics.Random(ScenarioBase.activeScenario.NextRandomState());
return rng.NextFloat(range.minimum, range.maximum);
}
/// <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
{
min = range.minimum,
max = range.maximum,
seed = ScenarioBase.activeScenario.NextRandomState(),
samples = samples
}.ScheduleBatch(sampleCount, SamplerUtility.samplingBatchSize);
return samples;
}
[BurstCompile]
struct SampleJob : IJobParallelForBatch
{
public float min;
public float max;
public uint seed;
public NativeArray<float> samples;
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));
for (var i = startIndex; i < endIndex; i++)
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() { }
}
}

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


/// <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)
public static float AnimationCurveSample(float[] integratedCurve, float uniformSample, float interval, float startTime, float endTime)
{
var scaledSample = uniformSample * integratedCurve[integratedCurve.Length - 1];

/// 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)
public static void IntegrateCurve(float[] array, AnimationCurve curve)
{
if (curve.length == 0)
{

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


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

19
com.unity.perception/Tests/Runtime/Randomization/ParameterTests/StructParameterTests.cs


}
[Test]
public void CorrectNumberOfNativeSamplesAreGenerated()
public void CorrectNumberOfSamplesAreGenerated()
test.GeneratesNativeSamples();
test.GeneratesSamples();
public abstract void GeneratesNativeSamples();
public abstract void GeneratesSamples();
}
public class NumericParameterTest<T> : BaseStructParameterTest where T : struct

m_Parameter = parameter;
}
public override void GeneratesNativeSamples()
public override void GeneratesSamples()
var nativeSamples = m_Parameter.Samples(TestValues.TestSampleCount, out var handle);
handle.Complete();
Assert.AreEqual(nativeSamples.Length, TestValues.TestSampleCount);
nativeSamples.Dispose();
var samples = new T[TestValues.TestSampleCount];
for (var i = 0; i < samples.Length; i++)
{
samples[i] = m_Parameter.Sample();
}
Assert.AreEqual(samples.Length, TestValues.TestSampleCount);
}
}
}

47
com.unity.perception/Tests/Runtime/Randomization/SamplerTests/SamplerTestsBase.cs


public void Setup()
{
m_Sampler = m_BaseSampler;
m_BaseSampler.Initialize();
m_ScenarioObj = new GameObject("Scenario");
m_ScenarioObj.AddComponent<FixedLengthScenario>();
}

{
m_BaseSampler.Cleanup();
Object.DestroyImmediate(m_ScenarioObj);
}

var samples = m_Sampler.Samples(k_TestSampleCount, out var handle);
handle.Complete();
Assert.AreEqual(samples.Length, k_TestSampleCount);
foreach (var sample in samples)
var samples = new float[k_TestSampleCount];
for (var i = 0; i < samples.Length; i++)
Assert.GreaterOrEqual(sample, m_Sampler.range.minimum);
Assert.LessOrEqual(sample, m_Sampler.range.maximum);
samples[i] = m_Sampler.Sample();
samples.Dispose();
}
[Test]
public void NativeSamplesInRange()
{
var samples = m_Sampler.Samples(k_TestSampleCount, out var handle);
handle.Complete();
foreach (var sample in samples)
for (var i = 0; i < samples.Length; i++)
Assert.GreaterOrEqual(sample, m_Sampler.range.minimum);
Assert.LessOrEqual(sample, m_Sampler.range.maximum);
Assert.GreaterOrEqual(samples[i], m_Sampler.range.minimum);
Assert.LessOrEqual(samples[i], m_Sampler.range.maximum);
samples.Dispose();
}
[Test]

Assert.AreNotEqual(state0, state1);
Assert.AreNotEqual(state1, state2);
}
[Test]
public void ConsecutiveSampleBatchesChangesState()
{
var state0 = activeScenario.randomState;
var samples1 = m_Sampler.Samples(k_TestSampleCount, out var handle1);
var state1 = activeScenario.randomState;
var samples2 = m_Sampler.Samples(k_TestSampleCount, out var handle2);
var state2 = activeScenario.randomState;
JobHandle.CombineDependencies(handle1, handle2).Complete();
Assert.AreEqual(samples1.Length, samples2.Length);
Assert.AreNotEqual(state0, state1);
Assert.AreNotEqual(state1, state2);
Assert.AreNotEqual(samples1[0], samples2[0]);
samples1.Dispose();
samples2.Dispose();
}
}
}
正在加载...
取消
保存