浏览代码

Ray perception sensor tests (#3297)

* tests WIP

* add test for misses, remove obsolete test

* add filtering test

* cleanup

* 2d default, remove constants test

* use built in tags

* copy old physics settings

* manually sync physics transforms
/asymm-envs
GitHub 5 年前
当前提交
01b29cec
共有 6 个文件被更改,包括 213 次插入57 次删除
  1. 14
      Project/ProjectSettings/DynamicsManager.asset
  2. 12
      com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensor.cs
  3. 6
      com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensorComponent2D.cs
  4. 195
      com.unity.ml-agents/Tests/Editor/Sensor/RayPerceptionSensorTests.cs
  5. 40
      Project/Assets/ML-Agents/Editor/Tests/RayPerceptionTests.cs
  6. 3
      Project/Assets/ML-Agents/Editor/Tests/RayPerceptionTests.cs.meta

14
Project/ProjectSettings/DynamicsManager.asset


--- !u!55 &1
PhysicsManager:
m_ObjectHideFlags: 0
serializedVersion: 10
serializedVersion: 7
m_DefaultSolverIterations: 6
m_DefaultSolverVelocityIterations: 1
m_DefaultSolverIterations: 12
m_DefaultSolverVelocityIterations: 12
m_QueriesHitBackfaces: 0
m_QueriesHitTriggers: 1
m_EnableAdaptiveForce: 0

m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebffffffddffffffeffffffff5fffffffbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
m_AutoSyncTransforms: 0
m_ReuseCollisionCallbacks: 0
m_AutoSyncTransforms: 1
m_ClothInterCollisionSettingsToggle: 0
m_ContactPairsMode: 0
m_BroadphaseType: 0

m_WorldSubdivisions: 8
m_FrictionType: 0
m_EnableEnhancedDeterminism: 0
m_EnableUnifiedHeightmaps: 1

12
com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensor.cs


if (castHit)
{
bool hitTaggedObject = false;
for (var i = 0; i < detectableObjects.Count; i++)
{
if (hitObject.CompareTag(detectableObjects[i]))

hitTaggedObject = true;
}
if (!legacyHitFractionBehavior)
{
// Something was hit but not on the list. Still set the hit fraction.
perceptionBuffer[bufferOffset + detectableObjects.Count + 1] = hitFraction;
}
if (!hitTaggedObject && !legacyHitFractionBehavior)
{
// Something was hit but not on the list. Still set the hit fraction.
perceptionBuffer[bufferOffset + detectableObjects.Count + 1] = hitFraction;
}
}
else

6
com.unity.ml-agents/Runtime/Sensor/RayPerceptionSensorComponent2D.cs


[AddComponentMenu("ML Agents/Ray Perception Sensor 2D", (int) MenuGroup.Sensors)]
public class RayPerceptionSensorComponent2D : RayPerceptionSensorComponentBase
{
public RayPerceptionSensorComponent2D()
{
// Set to the 2D defaults (just in case they ever diverge).
rayLayerMask = Physics2D.DefaultRaycastLayers;
}
public override RayPerceptionSensor.CastType GetCastType()
{
return RayPerceptionSensor.CastType.Cast2D;

195
com.unity.ml-agents/Tests/Editor/Sensor/RayPerceptionSensorTests.cs


using System;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using MLAgents.Sensor;

for (var i = 0; i < angles.Length; i++)
{
Assert.AreEqual(expectedAngles[i], angles[i], .01);
}
}
}
public class RayPerception3DTests
{
// Use built-in tags
const string k_CubeTag = "Player";
const string k_SphereTag = "Respawn";
void SetupScene()
{
/* Creates game objects in the world for testing.
* C is a cube
* S are spheres
* @ is the agent (at the origin)
* Each space or line is 5 world units, +x is right, +z is up
*
* C
* S S
* @
*
* S
*/
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = new Vector3(0, 0, 10);
cube.tag = k_CubeTag;
var sphere1 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere1.transform.position = new Vector3(-5, 0, 5);
sphere1.tag = k_SphereTag;
var sphere2 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere2.transform.position = new Vector3(5, 0, 5);
// No tag for sphere2
var sphere3 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere3.transform.position = new Vector3(0, 0, -10);
sphere3.tag = k_SphereTag;
Physics.SyncTransforms();
}
[Test]
public void TestRaycasts()
{
SetupScene();
var obj = new GameObject("agent");
var perception = obj.AddComponent<RayPerceptionSensorComponent3D>();
perception.raysPerDirection = 1;
perception.maxRayDegrees = 45;
perception.rayLength = 20;
perception.detectableTags = new List<string>();
perception.detectableTags.Add(k_CubeTag);
perception.detectableTags.Add(k_SphereTag);
var radii = new [] { 0f, .5f };
foreach (var castRadius in radii)
{
perception.sphereCastRadius = castRadius;
var sensor = perception.CreateSensor();
var expectedObs = (2 * perception.raysPerDirection + 1) * (perception.detectableTags.Count + 2);
Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs);
var outputBuffer = new float[expectedObs];
WriteAdapter writer = new WriteAdapter();
writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0);
var numWritten = sensor.Write(writer);
Assert.AreEqual(numWritten, expectedObs);
// Expected hits:
// ray 0 should hit the cube at roughly halfway
// ray 1 should hit a sphere but no tag
// ray 2 should hit a sphere with the k_SphereTag tag
// The hit fraction should be the same for rays 1 and
//
Assert.AreEqual(1.0f, outputBuffer[0]); // hit cube
Assert.AreEqual(0.0f, outputBuffer[1]); // missed sphere
Assert.AreEqual(0.0f, outputBuffer[2]); // missed unknown tag
// Hit is at z=9.0 in world space, ray length is 20
Assert.That(
outputBuffer[3], Is.EqualTo((9.5f - castRadius) / perception.rayLength).Within(.0005f)
);
// Spheres are at 5,0,5 and 5,0,-5, so 5*sqrt(2) units from origin
// Minus 1.0 for the sphere radius to get the length of the hit.
var expectedHitLengthWorldSpace = 5.0f * Mathf.Sqrt(2.0f) - 0.5f - castRadius;
Assert.AreEqual(0.0f, outputBuffer[4]); // missed cube
Assert.AreEqual(0.0f, outputBuffer[5]); // missed sphere
Assert.AreEqual(0.0f, outputBuffer[6]); // hit unknown tag -> all 0
Assert.That(
outputBuffer[7], Is.EqualTo(expectedHitLengthWorldSpace / perception.rayLength).Within(.0005f)
);
Assert.AreEqual(0.0f, outputBuffer[8]); // missed cube
Assert.AreEqual(1.0f, outputBuffer[9]); // hit sphere
Assert.AreEqual(0.0f, outputBuffer[10]); // missed unknown tag
Assert.That(
outputBuffer[11], Is.EqualTo(expectedHitLengthWorldSpace / perception.rayLength).Within(.0005f)
);
}
}
[Test]
public void TestRaycastMiss()
{
var obj = new GameObject("agent");
var perception = obj.AddComponent<RayPerceptionSensorComponent3D>();
perception.raysPerDirection = 0;
perception.maxRayDegrees = 45;
perception.rayLength = 20;
perception.detectableTags = new List<string>();
perception.detectableTags.Add(k_CubeTag);
perception.detectableTags.Add(k_SphereTag);
var sensor = perception.CreateSensor();
var expectedObs = (2 * perception.raysPerDirection + 1) * (perception.detectableTags.Count + 2);
Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs);
var outputBuffer = new float[expectedObs];
WriteAdapter writer = new WriteAdapter();
writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0);
var numWritten = sensor.Write(writer);
Assert.AreEqual(numWritten, expectedObs);
// Everything missed
Assert.AreEqual(new float[] { 0, 0, 1, 1 }, outputBuffer);
}
[Test]
public void TestRayFilter()
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = new Vector3(0, 0, 10);
cube.tag = k_CubeTag;
cube.name = "cubeFar";
var cubeFiltered = GameObject.CreatePrimitive(PrimitiveType.Cube);
cubeFiltered.transform.position = new Vector3(0, 0, 5);
cubeFiltered.tag = k_CubeTag;
cubeFiltered.name = "cubeNear";
cubeFiltered.layer = 7;
Physics.SyncTransforms();
var obj = new GameObject("agent");
var perception = obj.AddComponent<RayPerceptionSensorComponent3D>();
perception.raysPerDirection = 0;
perception.rayLength = 20;
perception.detectableTags = new List<string>();
var filterCubeLayers = new[] { false, true };
foreach (var filterCubeLayer in filterCubeLayers)
{
// Set the layer mask to either the default, or one that ignores the close cube's layer
var layerMask = Physics.DefaultRaycastLayers;
if (filterCubeLayer)
{
layerMask &= ~(1 << cubeFiltered.layer);
}
perception.rayLayerMask = layerMask;
var sensor = perception.CreateSensor();
var expectedObs = (2 * perception.raysPerDirection + 1) * (perception.detectableTags.Count + 2);
Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs);
var outputBuffer = new float[expectedObs];
WriteAdapter writer = new WriteAdapter();
writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0);
var numWritten = sensor.Write(writer);
Assert.AreEqual(numWritten, expectedObs);
if (filterCubeLayer)
{
// Hit the far cube because close was filtered.
Assert.That(outputBuffer[outputBuffer.Length - 1],
Is.EqualTo((9.5f - perception.sphereCastRadius) / perception.rayLength).Within(.0005f)
);
}
else
{
// Hit the close cube because not filtered.
Assert.That(outputBuffer[outputBuffer.Length - 1],
Is.EqualTo((4.5f - perception.sphereCastRadius) / perception.rayLength).Within(.0005f)
);
}
}
}
}

40
Project/Assets/ML-Agents/Editor/Tests/RayPerceptionTests.cs


using UnityEngine;
using NUnit.Framework;
namespace MLAgents.Tests
{
public class RayPerceptionTests : MonoBehaviour
{
[Test]
public void TestPerception3D()
{
var angles = new[] {0f, 90f, 180f};
var tags = new[] {"test", "test_1"};
var go = new GameObject("MyGameObject");
var rayPer3D = go.AddComponent<RayPerception3D>();
var result = rayPer3D.Perceive(1f, angles, tags);
Assert.IsTrue(result.Count == angles.Length * (tags.Length + 2));
}
[Test]
public void TestPerception2D()
{
var angles = new[] {0f, 90f, 180f};
var tags = new[] {"test", "test_1"};
var go = new GameObject("MyGameObject");
var rayPer2D = go.AddComponent<RayPerception2D>();
var result = rayPer2D.Perceive(1f, angles,
tags);
Assert.IsTrue(result.Count == angles.Length * (tags.Length + 2));
}
[Test]
public void TestConstants()
{
Assert.AreEqual(Physics.DefaultRaycastLayers, Physics2D.DefaultRaycastLayers);
}
}
}

3
Project/Assets/ML-Agents/Editor/Tests/RayPerceptionTests.cs.meta


fileFormatVersion: 2
guid: 29010426d01b4569830a85795f4f345b
timeCreated: 1552498773
正在加载...
取消
保存