Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate boxoverlap out of GridSensor #5238

Merged
merged 29 commits into from Apr 13, 2021
Merged

Conversation

dongruoping
Copy link
Contributor

Proposed change(s)

Separate BoxOverlap logic into separate class, and also make each encoding into a class derived from GridSensorBase.
The component holds a list of GridSensors, and the first one has the BoxOverlapChecker.
The component also has a dummy GridSensorBase which will not be passed to Agent, only for collecting debug gizmo data.

For each cell, the data collection process is as following:

  1. BoxOverlap: Detect all colliders within the cell
  2. ParseColliders: Iterate through all colliders and determine which ones will actually be used. Currently it either use the one closest to agent or use all.
  3. LoadObjectData: for each parsed collider, load the observation data for that game object. It calls GetObjectData which actually fills the data buffer.

Derived GridSensors share 1 and 2, and only overwrites 3.
1 only runs once for each cell.
2 runs once for each way of parsing colliders. This allows the parsed colliders being reused by different sensors. For example, there's a one-hot sensor and a continuous value sensor both using one collider per cell. Then ParseColliders only has to compute closest collider once.
3 runs once for each sensor and loads different data for different sensor.

Useful links (Github issues, JIRA tickets, ML-Agents forum threads etc.)

Types of change(s)

  • Bug fix
  • New feature
  • Code refactor
  • Breaking change
  • Documentation update
  • Other (please describe)

Checklist

  • Added tests that prove my fix is effective or that my feature works
  • Updated the changelog (if applicable)
  • Updated the documentation (if applicable)
  • Updated the migration guide (if applicable)

Other comments

/// Whether to use one-hot detected tag as observation.
/// Note that changing this after the sensor is created has no effect.
/// </summary>
public bool UseOneHotTag
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can make UseOneHotTag and CountColliders into a GridSensorObservationType enum if that's better.

);
// debug data is positive int value and will trigger data validation exception if SensorCompressionType is not None.
m_DebugSensor = new GridSensorBase("DebugGridSensor", m_CellScale, m_GridSize, new int[] { 1 }, m_DetectableObjects, SensorCompressionType.None);
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe lazily allocate this in OnDrawGizmos()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That will cause several issues. When there's any changes on component, the debug sensor has to be updated too. So if we turn on gizmo -> turn it off -> change some config -> and turn it back on, it will not be updated.

Also decoupling the creation of DebugSensor and BoxOverlapChecker cause errors in editor. m_DebugSensor will attach to the existing BoxOverlapChecker at creation time, but editor refresh will keep re-creating new BoxOverlapChecker and the debug sensor won't know about it.

I think in terms of performance it's not causing too much trouble since when showGizmo=false it doesn't trigger any unnecessary calls.

/// </summary>
/// <param name="currentColliderGo">The game object that was found colliding with a certain cell</param>
/// <param name="cellIndex">The index of the current cell</param>
protected internal void LoadObjectData(GameObject currentColliderGo, int cellIndex)
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename to ProcessCellOverlaps()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed to ProcessDetectedObject since it processes one object

{
if (!ReferenceEquals(currentColliderGo, null) && currentColliderGo.CompareTag(m_DetectableObjects[i]))
{
Array.Clear(m_CellDataBuffer, 0, m_CellDataBuffer.Length);
Copy link
Contributor

Choose a reason for hiding this comment

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

This feels like a a good usecase for an ArraySegment that's a "view' on the part of m_CellDataBuffer that we're able to write to. Now that we're on 2019.4, we might be able to use a new enough version of C# that we can write, otherwise we could roll our own small version

@dongruoping dongruoping marked this pull request as ready for review April 12, 2021 18:23

[HideInInspector, SerializeField]
internal string[] m_DetectableObjects;
internal string[] m_DetectableTags;
Copy link
Contributor

Choose a reason for hiding this comment

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

Good name change!

m_DebugSensor = new GridSensorBase("DebugGridSensor", m_CellScale, m_GridSize, m_DetectableTags, SensorCompressionType.None);
m_BoxOverlapChecker.RegisterDebugSensor(m_DebugSensor);

if (m_UseOneHotTag)
Copy link
Contributor

Choose a reason for hiding this comment

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

Move the creation of OneHotGridSensor and CountingGridSensor to the default impl of GetGridSensors?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can see how this make sense, but then when GetGridSensors is overridden the bool m_UseOneHotTag specified in UI will have no effect which is a bit confusing.

Copy link
Contributor

Choose a reason for hiding this comment

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

If you override GetGridSensors(), you can still call base.GetGridSensors() (or not)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, I moved it.

}
}
// Only one sensor needs to reference the boxOverlapChecker, so that it gets updated exactly once
((GridSensorBase)m_Sensors[0]).m_BoxOverlapChecker = m_BoxOverlapChecker;
Copy link
Contributor

Choose a reason for hiding this comment

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

m_Sensors will be empty if both m_UseOneHotTag and m_CountColliders are false, right? I think you need to check m_Sensors.Count first.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed it. Also added tests for this.


internal void RegisterSensor(GridSensorBase sensor)
{
if (sensor.ProcessAllCollidersInCell())
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: instead of bool ProcessAllCollidersInCell() and two separate registration methods, could you make the GridSensorBase return an enum (ProcessAllColliders, ProcessClosestCollider, DebugColliders) ? I think that would simplify this a bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I made two separate registration methods because I don't want to expose DebugColliders since user should never use that.
I can make enum for ProcessAllColliders and ProcessClosestCollider.

@dongruoping dongruoping merged commit 2564a1d into main Apr 13, 2021
@delete-merged-branch delete-merged-branch bot deleted the grid-sensor-separate-base branch April 13, 2021 20:38
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 14, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants