Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions UnitySDK/Assets/ML-Agents/Editor/BehaviorParametersEditor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using UnityEngine;
using UnityEditor;
using Barracuda;
using MLAgents.Sensor;

namespace MLAgents
{
Expand Down Expand Up @@ -56,15 +57,17 @@ void DisplayFailedModelChecks()
D.logEnabled = false;
Model barracudaModel = null;
var model = (NNModel)serializedObject.FindProperty("m_Model").objectReferenceValue;
var brainParameters = ((BehaviorParameters)target).brainParameters;
var behaviorParameters = (BehaviorParameters)target;
var sensorComponents = behaviorParameters.GetComponents<SensorComponent>();
var brainParameters = behaviorParameters.brainParameters;
if (model != null)
{
barracudaModel = ModelLoader.Load(model.Value);
}
if (brainParameters != null)
{
var failedChecks = InferenceBrain.BarracudaModelParamLoader.CheckModel(
barracudaModel, brainParameters);
barracudaModel, brainParameters, sensorComponents);
foreach (var check in failedChecks)
{
if (check != null)
Expand Down
2 changes: 0 additions & 2 deletions UnitySDK/Assets/ML-Agents/Editor/Tests/DemonstrationTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
using System.Collections.Generic;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleanup suggested by Rider.

using NUnit.Framework;
using UnityEngine;
using System.IO.Abstractions.TestingHelpers;
using System.Reflection;
using MLAgents.CommunicatorObjects;
using Google.Protobuf;

namespace MLAgents.Tests
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using NUnit.Framework;
using UnityEngine;
using MLAgents.Sensor;

namespace MLAgents.Tests
{
public class RayPerceptionSensorTests
{
[Test]
public void TestGetRayAngles()
{
var angles = RayPerceptionSensorComponent.GetRayAngles(3, 90f);
var expectedAngles = new [] { 90f, 60f, 120f, 30f, 150f, 0f, 180f };
Assert.AreEqual(expectedAngles.Length, angles.Length);
for (var i = 0; i < angles.Length; i++)
{
Assert.AreEqual(expectedAngles[i], angles[i], .01);
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

using Barracuda;
using MLAgents.InferenceBrain;
using MLAgents.InferenceBrain.Utils;


namespace MLAgents.Tests
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using UnityEngine;
using MLAgents;
using MLAgents.Sensor;

public class FoodCollectorAgent : Agent
{
Expand Down Expand Up @@ -150,7 +151,7 @@ public void MoveAgent(float[] act)
{
var myTransform = transform;
myLaser.transform.localScale = new Vector3(1f, 1f, m_LaserLength);
var position = myTransform.TransformDirection(RayPerception3D.PolarToCartesian(25f, 90f));
var position = myTransform.TransformDirection(RayPerceptionSensor.PolarToCartesian(25f, 90f));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be 3DRayPerceptionSensor to show this is 3D?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should PolarToCartesian live in some Utility class? Should the Debug.DrawRay be part of the sensor instead ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try to clean some of this up a bit. I'd lean towards not doing any trig functions at runtime, and either save a quaternion "base" and "increment", or storing the local space vectors on the sensor.

Copy link
Contributor Author

@chriselion chriselion Nov 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♂ This should just be "25.0 * transform.forwards" since the angle is hardcoded to 90

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned this part up. It had no need for any RayPerception* code here. Note this is "game logic" inside MoveAgent(), not actually related to observations.

Debug.DrawRay(myTransform.position, position, Color.red, 0f, true);
RaycastHit hit;
if (Physics.SphereCast(transform.position, 2f, position, out hit, 25f))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@

public abstract class RayPerception : MonoBehaviour
{
protected List<float> m_PerceptionBuffer = new List<float>();
protected float[] m_PerceptionBuffer;

abstract public List<float> Perceive(float rayDistance,
abstract public IList<float> Perceive(float rayDistance,
float[] rayAngles, string[] detectableObjects,
float startOffset=0.0f, float endOffset=0.0f);

/// <summary>
/// Converts degrees to radians.
/// </summary>
public static float DegreeToRadian(float degree)
{
return degree * Mathf.PI / 180f;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using UnityEngine;
using MLAgents.Sensor;

namespace MLAgents
{
Expand All @@ -9,7 +11,6 @@ namespace MLAgents
/// </summary>
public class RayPerception2D : RayPerception
{
Vector2 m_EndPosition;
RaycastHit2D m_Hit;

/// <summary>
Expand All @@ -30,55 +31,63 @@ public class RayPerception2D : RayPerception
/// <param name="detectableObjects">List of tags which correspond to object types agent can see</param>
/// <param name="startOffset">Unused</param>
/// <param name="endOffset">Unused</param>
public override List<float> Perceive(float rayDistance,
public override IList<float> Perceive(float rayDistance,
float[] rayAngles, string[] detectableObjects,
float startOffset=0.0f, float endOffset=0.0f)
{
m_PerceptionBuffer.Clear();

var perceptionSize = (detectableObjects.Length + 2) * rayAngles.Length;
if (m_PerceptionBuffer == null || m_PerceptionBuffer.Length != perceptionSize)
{
m_PerceptionBuffer = new float[perceptionSize];
}
Array.Clear(m_PerceptionBuffer, 0, m_PerceptionBuffer.Length);

// For each ray sublist stores categorical information on detected object
// along with object distance.
var bufferOffset = 0;
foreach (var angle in rayAngles)
{
m_EndPosition = transform.TransformDirection(
PolarToCartesian(rayDistance, angle));
Vector2 rayDirection = transform.TransformDirection(PolarToCartesian(rayDistance, angle));
if (Application.isEditor)
{
Debug.DrawRay(transform.position,
m_EndPosition, Color.black, 0.01f, true);
rayDirection, Color.black, 0.01f, true);
}

var subList = new float[detectableObjects.Length + 2];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got rid of this, and just wrote to the buffer with an offset instead.

m_Hit = Physics2D.CircleCast(transform.position, 0.5f, m_EndPosition, rayDistance);
m_Hit = Physics2D.CircleCast(transform.position, 0.5f, rayDirection, rayDistance);
if (m_Hit)
{
for (var i = 0; i < detectableObjects.Length; i++)
{
if (m_Hit.collider.gameObject.CompareTag(detectableObjects[i]))
{
subList[i] = 1;
subList[detectableObjects.Length + 1] = m_Hit.distance / rayDistance;
m_PerceptionBuffer[bufferOffset + i] = 1;
m_PerceptionBuffer[bufferOffset + detectableObjects.Length + 1] = m_Hit.distance / rayDistance;
break;
}
}
}
else
{
subList[detectableObjects.Length] = 1f;
m_PerceptionBuffer[bufferOffset + detectableObjects.Length] = 1f;
}

m_PerceptionBuffer.AddRange(subList);
bufferOffset += detectableObjects.Length + 2;
}

return m_PerceptionBuffer;
}



/// <summary>
/// Converts polar coordinate to cartesian coordinate.
/// </summary>
public static Vector2 PolarToCartesian(float radius, float angle)
{
var x = radius * Mathf.Cos(DegreeToRadian(angle));
var y = radius * Mathf.Sin(DegreeToRadian(angle));
var x = radius * Mathf.Cos(RayPerceptionSensor.DegreeToRadian(angle));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as in PolarToCartesian. Is there a better place to put these ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also made the PolarToCartesian methods private in their respective classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is folded into RayPerceptionSensor now.

var y = radius * Mathf.Sin(RayPerceptionSensor.DegreeToRadian(angle));
return new Vector2(x, y);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using MLAgents.Sensor;

namespace MLAgents
{
Expand All @@ -10,9 +11,6 @@ namespace MLAgents
/// </summary>
public class RayPerception3D : RayPerception
{
RaycastHit m_Hit;
float[] m_SubList;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. Also RayCast hit is a struct so we don't need to keep it around (I think, correct me if I'm wrong)


/// <summary>
/// Creates perception vector to be used as part of an observation of an agent.
/// Each ray in the rayAngles array adds a sublist of data to the observation.
Expand All @@ -31,66 +29,26 @@ public class RayPerception3D : RayPerception
/// <param name="detectableObjects">List of tags which correspond to object types agent can see</param>
/// <param name="startOffset">Starting height offset of ray from center of agent.</param>
/// <param name="endOffset">Ending height offset of ray from center of agent.</param>
public override List<float> Perceive(float rayDistance,
public override IList<float> Perceive(float rayDistance,
float[] rayAngles, string[] detectableObjects,
float startOffset=0.0f, float endOffset=0.0f)
{
if (m_SubList == null || m_SubList.Length != detectableObjects.Length + 2)
m_SubList = new float[detectableObjects.Length + 2];

m_PerceptionBuffer.Clear();
m_PerceptionBuffer.Capacity = m_SubList.Length * rayAngles.Length;

// For each ray sublist stores categorical information on detected object
// along with object distance.
foreach (var angle in rayAngles)
var perceptionSize = (detectableObjects.Length + 2) * rayAngles.Length;
if (m_PerceptionBuffer == null || m_PerceptionBuffer.Length != perceptionSize)
{
Vector3 startPositionLocal = new Vector3(0, startOffset, 0);
Vector3 endPositionLocal = PolarToCartesian(rayDistance, angle);
endPositionLocal.y += endOffset;

var startPositionWorld = transform.TransformPoint(startPositionLocal);
var endPositionWorld = transform.TransformPoint(endPositionLocal);

var rayDirection = endPositionWorld - startPositionWorld;
if (Application.isEditor)
{
Debug.DrawRay(startPositionWorld,rayDirection, Color.black, 0.01f, true);
}

Array.Clear(m_SubList, 0, m_SubList.Length);

if (Physics.SphereCast(startPositionWorld, 0.5f, rayDirection, out m_Hit, rayDistance))
{
for (var i = 0; i < detectableObjects.Length; i++)
{
if (m_Hit.collider.gameObject.CompareTag(detectableObjects[i]))
{
m_SubList[i] = 1;
m_SubList[detectableObjects.Length + 1] = m_Hit.distance / rayDistance;
break;
}
}
}
else
{
m_SubList[detectableObjects.Length] = 1f;
}

Utilities.AddRangeNoAlloc(m_PerceptionBuffer, m_SubList);
m_PerceptionBuffer = new float[perceptionSize];
}

const float castRadius = 0.5f;
const bool legacyHitFractionBehavior = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this adds complexity. It is fair to say, you need to retrain when updating. I don't think we should have legacy code in a beta project.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed it adds complexity. Disagree that we shouldn't support it, at least for one more release. The old code is marked as [Obsolete] and we can remove it after the next release ships.

RayPerceptionSensor.PerceiveStatic(
rayDistance, rayAngles, detectableObjects, startOffset, endOffset, castRadius,
transform, m_PerceptionBuffer, legacyHitFractionBehavior
);

return m_PerceptionBuffer;
}

/// <summary>
/// Converts polar coordinate to cartesian coordinate.
/// </summary>
public static Vector3 PolarToCartesian(float radius, float angle)
{
var x = radius * Mathf.Cos(DegreeToRadian(angle));
var z = radius * Mathf.Sin(DegreeToRadian(angle));
return new Vector3(x, 0f, z);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ GameObject:
- component: {fileID: 54678503543725326}
- component: {fileID: 114898893333200490}
- component: {fileID: 114925928594762506}
- component: {fileID: 114092229367912210}
- component: {fileID: 114560282875640470}
- component: {fileID: 114625671574740166}
m_Layer: 0
m_Name: Agent
m_TagString: agent
Expand Down Expand Up @@ -1052,17 +1053,52 @@ BoxCollider:
serializedVersion: 2
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!114 &114092229367912210
--- !u!114 &114560282875640470
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1195095783991828}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bb172294dbbcc408286b156a2c4b553c, type: 3}
m_Script: {fileID: 11500000, guid: 45243967d8c0419b953c02bccb7c2768, type: 3}
m_Name:
m_EditorClassIdentifier:
sensorName: RayPerceptionSensor
detectableTags:
- wall
- goal
- block
raysPerDirection: 3
maxRayDegrees: 90
startVerticalOffset: 0
endVerticalOffset: 0
sphereCastRadius: 0.5
rayLength: 20
observationStacks: 6
--- !u!114 &114625671574740166
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1195095783991828}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 45243967d8c0419b953c02bccb7c2768, type: 3}
m_Name:
m_EditorClassIdentifier:
sensorName: OffsetRayPerceptionSensor
detectableTags:
- wall
- goal
- block
raysPerDirection: 3
maxRayDegrees: 90
startVerticalOffset: 2.5
endVerticalOffset: 5
sphereCastRadius: 0.5
rayLength: 20
observationStacks: 6
--- !u!114 &114898893333200490
MonoBehaviour:
m_ObjectHideFlags: 1
Expand All @@ -1075,12 +1111,12 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_BrainParameters:
vectorObservationSize: 74
vectorObservationSize: 4
numStackedVectorObservations: 6
vectorActionSize: 03000000030000000300000002000000
vectorActionDescriptions: []
vectorActionSpaceType: 0
m_Model: {fileID: 11400000, guid: fb2ce36eb40b6480e94ea0b5d7573e47, type: 3}
m_Model: {fileID: 11400000, guid: 0468bf44b1efd4992b6bf22cadb50d89, type: 3}
m_InferenceDevice: 0
m_UseHeuristic: 0
m_BehaviorName: SmallWallJump
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44971442, g: 0.499779, b: 0.5756377, a: 1}
m_IndirectSpecularColor: {r: 0.44971484, g: 0.49977958, b: 0.5756385, a: 1}
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
Expand Down
Loading