GitHub
4 年前
当前提交
0fb6043d
共有 36 个文件被更改,包括 1323 次插入 和 714 次删除
-
16com.unity.perception/CHANGELOG.md
-
8com.unity.perception/Documentation~/HPTutorial/TUTORIAL.md
-
1com.unity.perception/Editor/Randomization/Editors/PerceptionEditorAnalytics.cs
-
280com.unity.perception/Editor/Randomization/Editors/RunInUnitySimulationWindow.cs
-
54com.unity.perception/Editor/Randomization/Editors/ScenarioBaseEditor.cs
-
4com.unity.perception/Editor/Randomization/Uss/Styles.uss
-
48com.unity.perception/Editor/Randomization/Uxml/RunInUnitySimulationWindow.uxml
-
7com.unity.perception/Editor/Randomization/Uxml/ScenarioBaseElement.uxml
-
6com.unity.perception/Editor/Randomization/VisualElements/Parameter/CategoricalOptionElement.cs
-
14com.unity.perception/Editor/Randomization/VisualElements/Parameter/ParameterElement.cs
-
5com.unity.perception/Editor/Randomization/VisualElements/Randomizer/AddRandomizerMenu.cs
-
8com.unity.perception/Editor/Randomization/VisualElements/Randomizer/RandomizerList.cs
-
205com.unity.perception/Runtime/Randomization/Scenarios/Scenario.cs
-
337com.unity.perception/Runtime/Randomization/Scenarios/ScenarioBase.cs
-
24com.unity.perception/Runtime/Randomization/Scenarios/UnitySimulationScenario.cs
-
2com.unity.perception/Tests/Editor/RandomizerEditorTests.cs
-
10com.unity.perception/Tests/Runtime/Randomization/RandomizerTests/RandomizerTests.cs
-
18com.unity.perception/Editor/Randomization/Uss/RunInUnitySimulationWindowStyles.uss
-
3com.unity.perception/Editor/Randomization/Uss/RunInUnitySimulationWindowStyles.uss.meta
-
3com.unity.perception/Runtime/Randomization/Scenarios/Serialization.meta
-
3com.unity.perception/Tests/Runtime/Randomization/ScenarioTests.meta
-
188com.unity.perception/Runtime/Randomization/Scenarios/Serialization/JsonConverters.cs
-
3com.unity.perception/Runtime/Randomization/Scenarios/Serialization/JsonConverters.cs.meta
-
3com.unity.perception/Runtime/Randomization/Scenarios/Serialization/SerializationStructures.cs.meta
-
3com.unity.perception/Runtime/Randomization/Scenarios/Serialization/ScenarioSerializer.cs.meta
-
280com.unity.perception/Runtime/Randomization/Scenarios/Serialization/ScenarioSerializer.cs
-
95com.unity.perception/Runtime/Randomization/Scenarios/Serialization/SerializationStructures.cs
-
3com.unity.perception/Tests/Runtime/Randomization/ScenarioTests/Resources.meta
-
67com.unity.perception/Tests/Runtime/Randomization/ScenarioTests/Resources/SampleScenarioConfiguration.json
-
3com.unity.perception/Tests/Runtime/Randomization/ScenarioTests/Resources/SampleScenarioConfiguration.json.meta
-
159com.unity.perception/Tests/Runtime/Randomization/ScenarioTests/ScenarioTests.cs
-
177com.unity.perception/Tests/Runtime/Randomization/ScenarioTests.cs
-
0/com.unity.perception/Tests/Runtime/Randomization/ScenarioTests/ScenarioTests.cs.meta
|
|||
<UXML xmlns="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements"> |
|||
<TextField name="run-name" label="Run Name"/> |
|||
<editor:IntegerField name="total-iterations" label="Total Iterations"/> |
|||
<editor:IntegerField name="instance-count" label="Instance Count" max-value="10000"/> |
|||
<editor:ObjectField name="main-scene" label="Main Scene" allow-scene-objects="false"/> |
|||
<editor:ObjectField name="scenario" label="Scenario"/> |
|||
<VisualElement class="unity-base-field"> |
|||
<Label text="Sys-Param" class="unity-base-field__label"/> |
|||
<editor:ToolbarMenu name="sys-param" class="unity-base-field__input" style="border-width: 1px;"/> |
|||
</VisualElement> |
|||
<VisualElement style="align-items: center;"> |
|||
<Button name="run-button" text="Build and Run" style="margin: 10px; padding: 2 20; font-size: 13px;"/> |
|||
<VisualElement style="margin: 2 4 2 4;"> |
|||
<Style src="../Uss/RunInUnitySimulationWindowStyles.uss"/> |
|||
<VisualElement class="sim-window__container-outer"> |
|||
<Label text="Simulation Parameters" class="sim-window__header-1"/> |
|||
<TextField name="run-name" label="Run Name"/> |
|||
<editor:IntegerField name="total-iterations" label="Total Iterations" |
|||
tooltip="The number of scenario iterations to execute"/> |
|||
<editor:IntegerField name="instance-count" label="Instance Count" max-value="10000" |
|||
tooltip="The number of instances to distribute the work load across"/> |
|||
<VisualElement class="unity-base-field" |
|||
tooltip="The compute resources configuration to execute the simulation with"> |
|||
<Label text="Sys-Param" class="unity-base-field__label"/> |
|||
<editor:ToolbarMenu name="sys-param" class="unity-base-field__input" style="border-width: 1px;"/> |
|||
</VisualElement> |
|||
|
|||
<Label text="Optional Configuration" class="sim-window__header-1" style="margin-top: 18px;"/> |
|||
<editor:ObjectField name="scenario-config" label="Scenario JSON Config" allow-scene-object="false" |
|||
tooltip="Selects a scenario JSON configuration to load during the run. |
|||
You can leave this option blank to use the scenario settings currently configured in the editor."/> |
|||
|
|||
<VisualElement style="align-items: center; margin-top: 8px;"> |
|||
<Button name="run-button" text="Build and Run" style="margin: 10px; padding: 2 20; font-size: 13px;"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
|
|||
<VisualElement class="sim-window__container-outer"> |
|||
<Label text="Previous Run Information" class="sim-window__header-1"/> |
|||
|
|||
<Label name="prev-run-name" text="Run Name: " class="sim-window__label-prev-result"/> |
|||
<Label name="project-id" text="Project ID: " class="sim-window__label-prev-result"/> |
|||
<Label name="execution-id" text="Execution ID: " class="sim-window__label-prev-result"/> |
|||
|
|||
<VisualElement style="flex-direction: row; margin-top: 2px;"> |
|||
<Button name="copy-execution-id" text="Copy Execution ID" style="flex-grow: 1; flex-shrink: 0;"/> |
|||
<Button name="copy-project-id" text="Copy Project ID" style="flex-grow: 1; flex-shrink: 0;"/> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</VisualElement> |
|||
</UXML> |
|
|||
.sim-window__header-1 { |
|||
font-size: 14px; |
|||
-unity-font-style: bold; |
|||
margin-bottom: 1px; |
|||
margin-left: 2px; |
|||
} |
|||
|
|||
.sim-window__container-outer { |
|||
background-color: #2A2A2A; |
|||
margin-bottom: 8px; |
|||
margin-top: 2px; |
|||
padding: 2px; |
|||
} |
|||
|
|||
.sim-window__label-prev-result { |
|||
padding: 2 2 0 1; /*top, right, bottom, left*/ |
|||
margin: 1 3 1 3; |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 67ac54c923534486a149e4d1d85d9c83 |
|||
timeCreated: 1613109854 |
|
|||
fileFormatVersion: 2 |
|||
guid: 16628d9798ec4551b9648c56ef672ecc |
|||
timeCreated: 1612905161 |
|
|||
fileFormatVersion: 2 |
|||
guid: 60317fa8c31048249aef19666120f42d |
|||
timeCreated: 1613004387 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
|
|||
namespace UnityEngine.Perception.Randomization.Scenarios.Serialization |
|||
{ |
|||
class GroupItemsConverter : JsonConverter |
|||
{ |
|||
public override bool CanWrite => true; |
|||
|
|||
public override bool CanRead => true; |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(IGroupItem); |
|||
} |
|||
|
|||
public override void WriteJson( |
|||
JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
var output = new JObject(); |
|||
var groupItems = (Dictionary<string, IGroupItem>)value; |
|||
foreach (var itemKey in groupItems.Keys) |
|||
{ |
|||
var itemValue = groupItems[itemKey]; |
|||
var newObj = new JObject(); |
|||
if (itemValue is Parameter) |
|||
newObj["param"] = JObject.FromObject(itemValue); |
|||
else |
|||
newObj["scalar"] = JObject.FromObject(itemValue); |
|||
output[itemKey] = newObj; |
|||
} |
|||
output.WriteTo(writer); |
|||
} |
|||
|
|||
public override object ReadJson( |
|||
JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
var jsonObject = JObject.Load(reader); |
|||
var groupItems = new Dictionary<string, IGroupItem>(); |
|||
foreach (var property in jsonObject.Properties()) |
|||
{ |
|||
var value = (JObject)property.Value; |
|||
IGroupItem groupItem; |
|||
if (value.ContainsKey("param")) |
|||
groupItem = serializer.Deserialize<Parameter>(value["param"].CreateReader()); |
|||
else if (value.ContainsKey("scalar")) |
|||
groupItem = serializer.Deserialize<Scalar>(value["scalar"].CreateReader()); |
|||
else |
|||
throw new KeyNotFoundException("No GroupItem key found"); |
|||
groupItems.Add(property.Name, groupItem); |
|||
} |
|||
return groupItems; |
|||
} |
|||
} |
|||
|
|||
class ParameterItemsConverter : JsonConverter |
|||
{ |
|||
public override bool CanRead => true; |
|||
|
|||
public override bool CanWrite => true; |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(IParameterItem); |
|||
} |
|||
|
|||
public override void WriteJson( |
|||
JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
var output = new JObject(); |
|||
var parameterItems = (Dictionary<string, IParameterItem>)value; |
|||
foreach (var itemKey in parameterItems.Keys) |
|||
{ |
|||
var itemValue = parameterItems[itemKey]; |
|||
var newObj = new JObject(); |
|||
if (itemValue is SamplerOptions) |
|||
newObj["samplerOptions"] = JObject.FromObject(itemValue); |
|||
else |
|||
newObj["scalar"] = JObject.FromObject(itemValue); |
|||
output[itemKey] = newObj; |
|||
} |
|||
output.WriteTo(writer); |
|||
} |
|||
|
|||
public override object ReadJson( |
|||
JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
var jsonObject = JObject.Load(reader); |
|||
var parameterItems = new Dictionary<string, IParameterItem>(); |
|||
foreach (var property in jsonObject.Properties()) |
|||
{ |
|||
var value = (JObject)property.Value; |
|||
IParameterItem parameterItem; |
|||
if (value.ContainsKey("samplerOptions")) |
|||
parameterItem = serializer.Deserialize<SamplerOptions>(value["samplerOptions"].CreateReader()); |
|||
else if (value.ContainsKey("scalar")) |
|||
parameterItem = serializer.Deserialize<Scalar>(value["scalar"].CreateReader()); |
|||
else |
|||
throw new KeyNotFoundException("No ParameterItem key found"); |
|||
parameterItems.Add(property.Name, parameterItem); |
|||
} |
|||
return parameterItems; |
|||
} |
|||
} |
|||
|
|||
class SamplerOptionsConverter : JsonConverter |
|||
{ |
|||
public override bool CanRead => true; |
|||
|
|||
public override bool CanWrite => true; |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(SamplerOptions); |
|||
} |
|||
|
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
var options = (SamplerOptions)value; |
|||
var output = new JObject { ["metadata"] = JObject.FromObject(options.metadata) }; |
|||
|
|||
string key; |
|||
if (options.defaultSampler is ConstantSampler) |
|||
key = "constant"; |
|||
else if (options.defaultSampler is UniformSampler) |
|||
key = "uniform"; |
|||
else if (options.defaultSampler is NormalSampler) |
|||
key = "normal"; |
|||
else |
|||
throw new TypeAccessException($"Cannot serialize type ${options.defaultSampler.GetType()}"); |
|||
output[key] = JObject.FromObject(options.defaultSampler); |
|||
output.WriteTo(writer); |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
var jsonObject = JObject.Load(reader); |
|||
var samplerOption = new SamplerOptions { metadata = jsonObject["metadata"].ToObject<StandardMetadata>() }; |
|||
|
|||
if (jsonObject.ContainsKey("constant")) |
|||
samplerOption.defaultSampler = jsonObject["constant"].ToObject<ConstantSampler>(); |
|||
else if (jsonObject.ContainsKey("uniform")) |
|||
samplerOption.defaultSampler = jsonObject["uniform"].ToObject<UniformSampler>(); |
|||
else if (jsonObject.ContainsKey("normal")) |
|||
samplerOption.defaultSampler = jsonObject["normal"].ToObject<NormalSampler>(); |
|||
else |
|||
throw new KeyNotFoundException("No valid SamplerOption key type found"); |
|||
|
|||
return samplerOption; |
|||
} |
|||
} |
|||
|
|||
class ScalarConverter : JsonConverter |
|||
{ |
|||
public override bool CanRead => true; |
|||
|
|||
public override bool CanWrite => false; |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(Scalar); |
|||
} |
|||
|
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
throw new InvalidOperationException("Use default serialization."); |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
var jsonObject = JObject.Load(reader); |
|||
var value = (JObject)jsonObject["value"]; |
|||
var scalar = new Scalar { metadata = jsonObject["metadata"].ToObject<StandardMetadata>() }; |
|||
|
|||
if (value.ContainsKey("str")) |
|||
scalar.value = new StringScalarValue { str = value["str"].Value<string>() }; |
|||
else if (value.ContainsKey("num")) |
|||
scalar.value = new DoubleScalarValue { num = value["num"].Value<double>() }; |
|||
else if (value.ContainsKey("bool")) |
|||
scalar.value = new BooleanScalarValue { boolean = value["bool"].Value<bool>() }; |
|||
else |
|||
throw new KeyNotFoundException("No valid ScalarValue key type found"); |
|||
return scalar; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f2954e9f75904733971e6c6ab1f275d8 |
|||
timeCreated: 1612905182 |
|
|||
fileFormatVersion: 2 |
|||
guid: f1253a3d94bb468b93f80c2178652540 |
|||
timeCreated: 1612927921 |
|
|||
fileFormatVersion: 2 |
|||
guid: 39dfd341dac24b8fb2567380a105f770 |
|||
timeCreated: 1612461856 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Reflection; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using UnityEngine.Perception.Randomization.Parameters; |
|||
using UnityEngine.Perception.Randomization.Randomizers; |
|||
using UnityEngine.Perception.Randomization.Samplers; |
|||
|
|||
namespace UnityEngine.Perception.Randomization.Scenarios.Serialization |
|||
{ |
|||
static class ScenarioSerializer |
|||
{ |
|||
#region Serialization
|
|||
public static string SerializeToJsonString(ScenarioBase scenario) |
|||
{ |
|||
return JsonConvert.SerializeObject(SerializeToJsonObject(scenario), Formatting.Indented); |
|||
} |
|||
|
|||
public static void SerializeToFile(ScenarioBase scenario, string filePath) |
|||
{ |
|||
Directory.CreateDirectory(Application.dataPath + "/StreamingAssets/"); |
|||
using (var writer = new StreamWriter(filePath, false)) |
|||
{ |
|||
writer.Write(SerializeToJsonString(scenario)); |
|||
} |
|||
} |
|||
|
|||
public static JObject SerializeToJsonObject(ScenarioBase scenario) |
|||
{ |
|||
return new JObject |
|||
{ |
|||
["constants"] = SerializeConstants(scenario.genericConstants), |
|||
["randomizers"] = JObject.FromObject(SerializeScenarioToTemplate(scenario)) |
|||
}; |
|||
} |
|||
|
|||
static JObject SerializeConstants(ScenarioConstants constants) |
|||
{ |
|||
var constantsObj = new JObject(); |
|||
var constantsFields = constants.GetType().GetFields(); |
|||
foreach (var constantsField in constantsFields) |
|||
constantsObj.Add(new JProperty(constantsField.Name, constantsField.GetValue(constants))); |
|||
return constantsObj; |
|||
} |
|||
|
|||
static TemplateConfigurationOptions SerializeScenarioToTemplate(ScenarioBase scenario) |
|||
{ |
|||
return new TemplateConfigurationOptions |
|||
{ |
|||
groups = SerializeRandomizers(scenario.randomizers) |
|||
}; |
|||
} |
|||
|
|||
static Dictionary<string, Group> SerializeRandomizers(IEnumerable<Randomizer> randomizers) |
|||
{ |
|||
var serializedRandomizers = new Dictionary<string, Group>(); |
|||
foreach (var randomizer in randomizers) |
|||
{ |
|||
var randomizerData = SerializeRandomizer(randomizer); |
|||
if (randomizerData.items.Count == 0) |
|||
continue; |
|||
serializedRandomizers.Add(randomizer.GetType().Name, randomizerData); |
|||
} |
|||
return serializedRandomizers; |
|||
} |
|||
|
|||
static Group SerializeRandomizer(Randomizer randomizer) |
|||
{ |
|||
var randomizerData = new Group(); |
|||
var fields = randomizer.GetType().GetFields(); |
|||
foreach (var field in fields) |
|||
{ |
|||
if (field.FieldType.IsSubclassOf(typeof(Randomization.Parameters.Parameter))) |
|||
{ |
|||
if (!IsSubclassOfRawGeneric(typeof(NumericParameter<>), field.FieldType)) |
|||
continue; |
|||
var parameter = (Randomization.Parameters.Parameter)field.GetValue(randomizer); |
|||
var parameterData = SerializeParameter(parameter); |
|||
if (parameterData.items.Count == 0) |
|||
continue; |
|||
randomizerData.items.Add(field.Name, parameterData); |
|||
} |
|||
else |
|||
{ |
|||
var scalarValue = ScalarFromField(field, randomizer); |
|||
if (scalarValue != null) |
|||
randomizerData.items.Add(field.Name, new Scalar { value = scalarValue }); |
|||
} |
|||
} |
|||
return randomizerData; |
|||
} |
|||
|
|||
static Parameter SerializeParameter(Randomization.Parameters.Parameter parameter) |
|||
{ |
|||
var parameterData = new Parameter(); |
|||
var fields = parameter.GetType().GetFields(); |
|||
foreach (var field in fields) |
|||
{ |
|||
if (field.FieldType.IsAssignableFrom(typeof(ISampler))) |
|||
{ |
|||
var sampler = (ISampler)field.GetValue(parameter); |
|||
var samplerData = SerializeSampler(sampler); |
|||
if (samplerData.defaultSampler == null) |
|||
continue; |
|||
parameterData.items.Add(field.Name, samplerData); |
|||
} |
|||
else |
|||
{ |
|||
var scalarValue = ScalarFromField(field, parameter); |
|||
if (scalarValue != null) |
|||
parameterData.items.Add(field.Name, new Scalar { value = scalarValue }); |
|||
} |
|||
} |
|||
return parameterData; |
|||
} |
|||
|
|||
static SamplerOptions SerializeSampler(ISampler sampler) |
|||
{ |
|||
var samplerData = new SamplerOptions(); |
|||
if (sampler is Samplers.ConstantSampler constantSampler) |
|||
samplerData.defaultSampler = new ConstantSampler |
|||
{ |
|||
value = constantSampler.value |
|||
}; |
|||
else if (sampler is Samplers.UniformSampler uniformSampler) |
|||
samplerData.defaultSampler = new UniformSampler |
|||
{ |
|||
min = uniformSampler.range.minimum, |
|||
max = uniformSampler.range.maximum |
|||
}; |
|||
else if (sampler is Samplers.NormalSampler normalSampler) |
|||
samplerData.defaultSampler = new NormalSampler |
|||
{ |
|||
min = normalSampler.range.minimum, |
|||
max = normalSampler.range.maximum, |
|||
mean = normalSampler.mean, |
|||
standardDeviation = normalSampler.standardDeviation |
|||
}; |
|||
else |
|||
throw new ArgumentException($"Invalid sampler type ({sampler.GetType()})"); |
|||
return samplerData; |
|||
} |
|||
|
|||
static IScalarValue ScalarFromField(FieldInfo field, object obj) |
|||
{ |
|||
if (field.FieldType == typeof(string)) |
|||
return new StringScalarValue { str = (string)field.GetValue(obj) }; |
|||
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)) }; |
|||
return null; |
|||
} |
|||
#endregion
|
|||
|
|||
#region Deserialization
|
|||
public static void Deserialize(ScenarioBase scenario, string json) |
|||
{ |
|||
var jsonData = JObject.Parse(json); |
|||
if (jsonData.ContainsKey("constants")) |
|||
DeserializeConstants(scenario.genericConstants, (JObject)jsonData["constants"]); |
|||
if (jsonData.ContainsKey("randomizers")) |
|||
DeserializeTemplateIntoScenario( |
|||
scenario, jsonData["randomizers"].ToObject<TemplateConfigurationOptions>()); |
|||
} |
|||
|
|||
static void DeserializeConstants(ScenarioConstants constants, JObject constantsData) |
|||
{ |
|||
var serializer = new JsonSerializer(); |
|||
serializer.Populate(constantsData.CreateReader(), constants); |
|||
} |
|||
|
|||
static void DeserializeTemplateIntoScenario(ScenarioBase scenario, TemplateConfigurationOptions template) |
|||
{ |
|||
DeserializeRandomizers(scenario.randomizers, template.groups); |
|||
} |
|||
|
|||
static void DeserializeRandomizers(IEnumerable<Randomizer> randomizers, Dictionary<string, Group> groups) |
|||
{ |
|||
var randomizerTypeMap = new Dictionary<string, Randomizer>(); |
|||
foreach (var randomizer in randomizers) |
|||
randomizerTypeMap.Add(randomizer.GetType().Name, randomizer); |
|||
|
|||
foreach (var randomizerPair in groups) |
|||
{ |
|||
if (!randomizerTypeMap.ContainsKey(randomizerPair.Key)) |
|||
continue; |
|||
var randomizer = randomizerTypeMap[randomizerPair.Key]; |
|||
DeserializeRandomizer(randomizer, randomizerPair.Value); |
|||
} |
|||
} |
|||
|
|||
static void DeserializeRandomizer(Randomizer randomizer, Group randomizerData) |
|||
{ |
|||
foreach (var pair in randomizerData.items) |
|||
{ |
|||
var field = randomizer.GetType().GetField(pair.Key); |
|||
if (field == null) |
|||
continue; |
|||
if (pair.Value is Parameter parameterData) |
|||
DeserializeParameter((Randomization.Parameters.Parameter)field.GetValue(randomizer), parameterData); |
|||
else |
|||
DeserializeScalarValue(randomizer, field, (Scalar)pair.Value); |
|||
} |
|||
} |
|||
|
|||
static void DeserializeParameter(Randomization.Parameters.Parameter parameter, Parameter parameterData) |
|||
{ |
|||
foreach (var pair in parameterData.items) |
|||
{ |
|||
var field = parameter.GetType().GetField(pair.Key); |
|||
if (field == null) |
|||
continue; |
|||
if (pair.Value is SamplerOptions samplerOptions) |
|||
field.SetValue(parameter, DeserializeSampler(samplerOptions.defaultSampler)); |
|||
else |
|||
DeserializeScalarValue(parameter, field, (Scalar)pair.Value); |
|||
} |
|||
} |
|||
|
|||
static ISampler DeserializeSampler(ISamplerOption samplerOption) |
|||
{ |
|||
if (samplerOption is ConstantSampler constantSampler) |
|||
return new Samplers.ConstantSampler |
|||
{ |
|||
value = (float)constantSampler.value |
|||
}; |
|||
if (samplerOption is UniformSampler uniformSampler) |
|||
return new Samplers.UniformSampler |
|||
{ |
|||
range = new FloatRange |
|||
{ |
|||
minimum = (float)uniformSampler.min, |
|||
maximum = (float)uniformSampler.max |
|||
} |
|||
}; |
|||
if (samplerOption is NormalSampler normalSampler) |
|||
return new Samplers.NormalSampler |
|||
{ |
|||
range = new FloatRange |
|||
{ |
|||
minimum = (float)normalSampler.min, |
|||
maximum = (float)normalSampler.max |
|||
}, |
|||
mean = (float)normalSampler.mean, |
|||
standardDeviation = (float)normalSampler.standardDeviation |
|||
}; |
|||
throw new ArgumentException($"Cannot deserialize unsupported sampler type {samplerOption.GetType()}"); |
|||
} |
|||
|
|||
static void DeserializeScalarValue(object obj, FieldInfo field, Scalar scalar) |
|||
{ |
|||
object value; |
|||
if (scalar.value is StringScalarValue stringValue) |
|||
value = stringValue.str; |
|||
else if (scalar.value is BooleanScalarValue booleanValue) |
|||
value = booleanValue.boolean; |
|||
else if (scalar.value is DoubleScalarValue doubleValue) |
|||
value = doubleValue.num; |
|||
else |
|||
throw new ArgumentException( |
|||
$"Cannot deserialize unsupported scalar type {scalar.value.GetType()}"); |
|||
field.SetValue(obj, Convert.ChangeType(value, field.FieldType)); |
|||
} |
|||
#endregion
|
|||
|
|||
static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) { |
|||
while (toCheck != null && toCheck != typeof(object)) { |
|||
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; |
|||
if (generic == cur) { |
|||
return true; |
|||
} |
|||
toCheck = toCheck.BaseType; |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
} |
|
|||
using System.Collections.Generic; |
|||
using Newtonsoft.Json; |
|||
|
|||
namespace UnityEngine.Perception.Randomization.Scenarios.Serialization |
|||
{ |
|||
#region Interfaces
|
|||
interface IGroupItem { } |
|||
|
|||
interface IParameterItem { } |
|||
|
|||
interface ISamplerOption { } |
|||
|
|||
interface IScalarValue { } |
|||
#endregion
|
|||
|
|||
#region GroupedObjects
|
|||
class TemplateConfigurationOptions |
|||
{ |
|||
public Dictionary<string, Group> groups = new Dictionary<string, Group>(); |
|||
} |
|||
|
|||
class StandardMetadata |
|||
{ |
|||
public string name = string.Empty; |
|||
public string description = string.Empty; |
|||
} |
|||
|
|||
class Group |
|||
{ |
|||
public StandardMetadata metadata = new StandardMetadata(); |
|||
[JsonConverter(typeof(GroupItemsConverter))] |
|||
public Dictionary<string, IGroupItem> items = new Dictionary<string, IGroupItem>(); |
|||
} |
|||
|
|||
class Parameter : IGroupItem |
|||
{ |
|||
public StandardMetadata metadata = new StandardMetadata(); |
|||
[JsonConverter(typeof(ParameterItemsConverter))] |
|||
public Dictionary<string, IParameterItem> items = new Dictionary<string, IParameterItem>(); |
|||
} |
|||
#endregion
|
|||
|
|||
#region SamplerOptions
|
|||
[JsonConverter(typeof(SamplerOptionsConverter))] |
|||
class SamplerOptions : IParameterItem |
|||
{ |
|||
public StandardMetadata metadata = new StandardMetadata(); |
|||
public ISamplerOption defaultSampler; |
|||
} |
|||
|
|||
class UniformSampler : ISamplerOption |
|||
{ |
|||
public double min; |
|||
public double max; |
|||
} |
|||
|
|||
class NormalSampler : ISamplerOption |
|||
{ |
|||
public double min; |
|||
public double max; |
|||
public double mean; |
|||
public double standardDeviation; |
|||
} |
|||
|
|||
class ConstantSampler : ISamplerOption |
|||
{ |
|||
public double value; |
|||
} |
|||
#endregion
|
|||
|
|||
#region ScalarValues
|
|||
[JsonConverter(typeof(ScalarConverter))] |
|||
class Scalar : IGroupItem, IParameterItem |
|||
{ |
|||
public StandardMetadata metadata = new StandardMetadata(); |
|||
public IScalarValue value; |
|||
} |
|||
|
|||
class StringScalarValue : IScalarValue |
|||
{ |
|||
public string str; |
|||
} |
|||
|
|||
class DoubleScalarValue : IScalarValue |
|||
{ |
|||
public double num; |
|||
} |
|||
|
|||
class BooleanScalarValue : IScalarValue |
|||
{ |
|||
[JsonProperty("bool")] |
|||
public bool boolean; |
|||
} |
|||
#endregion
|
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 587e6f3ccc7d4d11beb10c2078c268f7 |
|||
timeCreated: 1613005737 |
|
|||
{ |
|||
"constants": { |
|||
"framesPerIteration": 1, |
|||
"totalIterations": 100, |
|||
"instanceCount": 1, |
|||
"instanceIndex": 0, |
|||
"randomSeed": 539662031 |
|||
}, |
|||
"randomizers": { |
|||
"groups": { |
|||
"RotationRandomizer": { |
|||
"metadata": { |
|||
"name": "", |
|||
"description": "" |
|||
}, |
|||
"items": { |
|||
"rotation": { |
|||
"param": { |
|||
"metadata": { |
|||
"name": "", |
|||
"description": "" |
|||
}, |
|||
"items": { |
|||
"x": { |
|||
"samplerOptions": { |
|||
"metadata": { |
|||
"name": "", |
|||
"description": "" |
|||
}, |
|||
"uniform": { |
|||
"min": 0.0, |
|||
"max": 360.0 |
|||
} |
|||
} |
|||
}, |
|||
"y": { |
|||
"samplerOptions": { |
|||
"metadata": { |
|||
"name": "", |
|||
"description": "" |
|||
}, |
|||
"uniform": { |
|||
"min": 0.0, |
|||
"max": 360.0 |
|||
} |
|||
} |
|||
}, |
|||
"z": { |
|||
"samplerOptions": { |
|||
"metadata": { |
|||
"name": "", |
|||
"description": "" |
|||
}, |
|||
"uniform": { |
|||
"min": 0.0, |
|||
"max": 360.0 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f8b765e3d9c34160bee64b2709a4edd8 |
|||
timeCreated: 1613005744 |
|
|||
using System; |
|||
using System.Collections; |
|||
using NUnit.Framework; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.Randomization.Randomizers.SampleRandomizers; |
|||
using UnityEngine.Perception.Randomization.Samplers; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using UnityEngine.Perception.Randomization.Scenarios; |
|||
using UnityEngine.TestTools; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace RandomizationTests |
|||
{ |
|||
[TestFixture] |
|||
public class ScenarioTests |
|||
{ |
|||
GameObject m_TestObject; |
|||
FixedLengthScenario m_Scenario; |
|||
|
|||
[SetUp] |
|||
public void Setup() |
|||
{ |
|||
m_TestObject = new GameObject(); |
|||
} |
|||
|
|||
[TearDown] |
|||
public void TearDown() |
|||
{ |
|||
Object.DestroyImmediate(m_TestObject); |
|||
} |
|||
|
|||
// TODO: update this function once the perception camera doesn't skip the first frame
|
|||
IEnumerator CreateNewScenario(int totalIterations, int framesPerIteration) |
|||
{ |
|||
m_Scenario = m_TestObject.AddComponent<FixedLengthScenario>(); |
|||
m_Scenario.constants.totalIterations = totalIterations; |
|||
m_Scenario.constants.framesPerIteration = framesPerIteration; |
|||
yield return null; // Skip Start() frame
|
|||
yield return null; // Skip first Update() frame
|
|||
} |
|||
|
|||
[Test] |
|||
public void ScenarioConfigurationSerializesProperly() |
|||
{ |
|||
m_TestObject = new GameObject(); |
|||
m_Scenario = m_TestObject.AddComponent<FixedLengthScenario>(); |
|||
m_Scenario.AddRandomizer(new RotationRandomizer()); |
|||
|
|||
string RemoveWhitespace(string str) => |
|||
string.Join("", str.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries)); |
|||
|
|||
var expectedConfigAsset = (TextAsset)Resources.Load("SampleScenarioConfiguration"); |
|||
var expectedText = RemoveWhitespace(expectedConfigAsset.text); |
|||
var scenarioJson = RemoveWhitespace(m_Scenario.SerializeToJson()); |
|||
Assert.AreEqual(expectedText, scenarioJson); |
|||
} |
|||
|
|||
[Test] |
|||
public void ScenarioConfigurationOverwrittenDuringDeserialization() |
|||
{ |
|||
m_TestObject = new GameObject(); |
|||
m_Scenario = m_TestObject.AddComponent<FixedLengthScenario>(); |
|||
|
|||
var constants = new FixedLengthScenario.Constants |
|||
{ |
|||
framesPerIteration = 2, |
|||
totalIterations = 2 |
|||
}; |
|||
|
|||
var changedConstants = new FixedLengthScenario.Constants |
|||
{ |
|||
framesPerIteration = 0, |
|||
totalIterations = 0 |
|||
}; |
|||
|
|||
// Serialize some values
|
|||
m_Scenario.constants = constants; |
|||
var serializedConfig = m_Scenario.SerializeToJson(); |
|||
|
|||
// Change the values
|
|||
m_Scenario.constants = changedConstants; |
|||
m_Scenario.DeserializeFromJson(serializedConfig); |
|||
|
|||
// Check if the values reverted correctly
|
|||
Assert.AreEqual(m_Scenario.constants.framesPerIteration, constants.framesPerIteration); |
|||
Assert.AreEqual(m_Scenario.constants.totalIterations, constants.totalIterations); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator IterationsCanLastMultipleFrames() |
|||
{ |
|||
const int frameCount = 5; |
|||
yield return CreateNewScenario(1, frameCount); |
|||
for (var i = 0; i < frameCount; i++) |
|||
{ |
|||
Assert.AreEqual(0, m_Scenario.currentIteration); |
|||
yield return null; |
|||
} |
|||
Assert.AreEqual(1, m_Scenario.currentIteration); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator FinishesWhenIsScenarioCompleteIsTrue() |
|||
{ |
|||
const int iterationCount = 5; |
|||
yield return CreateNewScenario(iterationCount, 1); |
|||
for (var i = 0; i < iterationCount; i++) |
|||
{ |
|||
Assert.False(m_Scenario.isScenarioComplete); |
|||
yield return null; |
|||
} |
|||
Assert.True(m_Scenario.isScenarioComplete); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator StartNewDatasetSequenceEveryIteration() |
|||
{ |
|||
var perceptionCamera = SetupPerceptionCamera(); |
|||
|
|||
yield return CreateNewScenario(2, 2); |
|||
Assert.AreEqual(DatasetCapture.SimulationState.SequenceTime, 0); |
|||
|
|||
// Second frame, first iteration
|
|||
yield return null; |
|||
Assert.AreEqual(DatasetCapture.SimulationState.SequenceTime, perceptionCamera.simulationDeltaTime); |
|||
|
|||
// Third frame, second iteration, SequenceTime has been reset
|
|||
yield return null; |
|||
Assert.AreEqual(DatasetCapture.SimulationState.SequenceTime, 0); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator GeneratedRandomSeedsChangeWithScenarioIteration() |
|||
{ |
|||
yield return CreateNewScenario(3, 1); |
|||
var seeds = new uint[3]; |
|||
for (var i = 0; i < 3; i++) |
|||
seeds[i] = SamplerState.NextRandomState(); |
|||
|
|||
yield return null; |
|||
for (var i = 0; i < 3; i++) |
|||
Assert.AreNotEqual(seeds[i], SamplerState.NextRandomState()); |
|||
} |
|||
|
|||
PerceptionCamera SetupPerceptionCamera() |
|||
{ |
|||
m_TestObject.SetActive(false); |
|||
var camera = m_TestObject.AddComponent<Camera>(); |
|||
camera.orthographic = true; |
|||
camera.orthographicSize = 1; |
|||
|
|||
var perceptionCamera = m_TestObject.AddComponent<PerceptionCamera>(); |
|||
perceptionCamera.captureRgbImages = false; |
|||
|
|||
m_TestObject.SetActive(true); |
|||
return perceptionCamera; |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using System.Collections; |
|||
using System.IO; |
|||
using NUnit.Framework; |
|||
using UnityEngine; |
|||
using UnityEngine.Perception.Randomization.Randomizers.SampleRandomizers; |
|||
using UnityEngine.Perception.Randomization.Samplers; |
|||
using UnityEngine.Perception.GroundTruth; |
|||
using UnityEngine.Perception.Randomization.Scenarios; |
|||
using UnityEngine.TestTools; |
|||
using Object = UnityEngine.Object; |
|||
|
|||
namespace RandomizationTests |
|||
{ |
|||
[TestFixture] |
|||
public class ScenarioTests |
|||
{ |
|||
GameObject m_TestObject; |
|||
FixedLengthScenario m_Scenario; |
|||
|
|||
[SetUp] |
|||
public void Setup() |
|||
{ |
|||
m_TestObject = new GameObject(); |
|||
} |
|||
|
|||
[TearDown] |
|||
public void TearDown() |
|||
{ |
|||
Object.DestroyImmediate(m_TestObject); |
|||
} |
|||
|
|||
// TODO: update this function once the perception camera doesn't skip the first frame
|
|||
IEnumerator CreateNewScenario(int totalIterations, int framesPerIteration) |
|||
{ |
|||
m_Scenario = m_TestObject.AddComponent<FixedLengthScenario>(); |
|||
m_Scenario.quitOnComplete = false; |
|||
m_Scenario.constants.totalIterations = totalIterations; |
|||
m_Scenario.constants.framesPerIteration = framesPerIteration; |
|||
yield return null; // Skip Start() frame
|
|||
yield return null; // Skip first Update() frame
|
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator ScenarioConfigurationSerializesProperly() |
|||
{ |
|||
yield return CreateNewScenario(10, 10); |
|||
var scenario = m_Scenario.GetComponent<FixedLengthScenario>(); |
|||
scenario.CreateRandomizer<HueOffsetRandomizer>(); |
|||
|
|||
const string expectedConfig = @"{
|
|||
""constants"": { |
|||
""framesPerIteration"": 10, |
|||
""totalIterations"": 10, |
|||
""instanceCount"": 1, |
|||
""instanceIndex"": 0, |
|||
""randomSeed"": 539662031 |
|||
}, |
|||
""randomizers"": { |
|||
""HueOffsetRandomizer"": { |
|||
""hueOffset"": { |
|||
""value"": { |
|||
""range"": { |
|||
""minimum"": -180.0, |
|||
""maximum"": 180.0 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}";
|
|||
Assert.AreEqual(expectedConfig, scenario.SerializeToJson()); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator ScenarioConfigurationOverwrittenDuringDeserialization() |
|||
{ |
|||
yield return CreateNewScenario(10, 10); |
|||
|
|||
var constants = new FixedLengthScenario.Constants |
|||
{ |
|||
framesPerIteration = 2, |
|||
totalIterations = 2 |
|||
}; |
|||
|
|||
var changedConstants = new FixedLengthScenario.Constants |
|||
{ |
|||
framesPerIteration = 0, |
|||
totalIterations = 0 |
|||
}; |
|||
|
|||
// Serialize some values
|
|||
m_Scenario.constants = constants; |
|||
var serializedConfig = m_Scenario.SerializeToJson(); |
|||
|
|||
// Change the values
|
|||
m_Scenario.constants = changedConstants; |
|||
m_Scenario.DeserializeFromJson(serializedConfig); |
|||
|
|||
// Check if the values reverted correctly
|
|||
Assert.AreEqual(m_Scenario.constants.framesPerIteration, constants.framesPerIteration); |
|||
Assert.AreEqual(m_Scenario.constants.totalIterations, constants.totalIterations); |
|||
|
|||
yield return null; |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator IterationsCanLastMultipleFrames() |
|||
{ |
|||
const int frameCount = 5; |
|||
yield return CreateNewScenario(1, frameCount); |
|||
for (var i = 0; i < frameCount; i++) |
|||
{ |
|||
Assert.AreEqual(0, m_Scenario.currentIteration); |
|||
yield return null; |
|||
} |
|||
Assert.AreEqual(1, m_Scenario.currentIteration); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator FinishesWhenIsScenarioCompleteIsTrue() |
|||
{ |
|||
const int iterationCount = 5; |
|||
yield return CreateNewScenario(iterationCount, 1); |
|||
for (var i = 0; i < iterationCount; i++) |
|||
{ |
|||
Assert.False(m_Scenario.isScenarioComplete); |
|||
yield return null; |
|||
} |
|||
Assert.True(m_Scenario.isScenarioComplete); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator StartNewDatasetSequenceEveryIteration() |
|||
{ |
|||
var perceptionCamera = SetupPerceptionCamera(); |
|||
|
|||
yield return CreateNewScenario(2, 2); |
|||
Assert.AreEqual(DatasetCapture.SimulationState.SequenceTime, 0); |
|||
|
|||
// Second frame, first iteration
|
|||
yield return null; |
|||
Assert.AreEqual(DatasetCapture.SimulationState.SequenceTime, perceptionCamera.simulationDeltaTime); |
|||
|
|||
// Third frame, second iteration, SequenceTime has been reset
|
|||
yield return null; |
|||
Assert.AreEqual(DatasetCapture.SimulationState.SequenceTime, 0); |
|||
} |
|||
|
|||
[UnityTest] |
|||
public IEnumerator GeneratedRandomSeedsChangeWithScenarioIteration() |
|||
{ |
|||
yield return CreateNewScenario(3, 1); |
|||
var seeds = new uint[3]; |
|||
for (var i = 0; i < 3; i++) |
|||
seeds[i] = SamplerState.NextRandomState(); |
|||
|
|||
yield return null; |
|||
for (var i = 0; i < 3; i++) |
|||
Assert.AreNotEqual(seeds[i], SamplerState.NextRandomState()); |
|||
} |
|||
|
|||
PerceptionCamera SetupPerceptionCamera() |
|||
{ |
|||
m_TestObject.SetActive(false); |
|||
var camera = m_TestObject.AddComponent<Camera>(); |
|||
camera.orthographic = true; |
|||
camera.orthographicSize = 1; |
|||
|
|||
var perceptionCamera = m_TestObject.AddComponent<PerceptionCamera>(); |
|||
perceptionCamera.captureRgbImages = false; |
|||
|
|||
m_TestObject.SetActive(true); |
|||
return perceptionCamera; |
|||
} |
|||
} |
|||
} |
撰写
预览
正在加载...
取消
保存
Reference in new issue