示例#1
0
        /// <summary>
        /// Creates the RayPerceptionSensor.
        /// </summary>
        /// <param name="name">The name of the sensor.</param>
        /// <param name="rayInput">The inputs for the sensor.</param>
        public RayPerceptionSensor(string name, RayPerceptionInput rayInput)
        {
            m_Name = name;
            m_RayPerceptionInput = rayInput;

            SetNumObservations(rayInput.OutputSize());

            m_DebugLastFrameCount = Time.frameCount;
            m_RayPerceptionOutput = new RayPerceptionOutput();
        }
示例#2
0
        /// <summary>
        /// Creates the RayPerceptionSensor.
        /// </summary>
        /// <param name="name">The name of the sensor.</param>
        /// <param name="rayInput">The inputs for the sensor.</param>
        public RayPerceptionSensor(string name, RayPerceptionInput rayInput)
        {
            m_Name = name;
            m_RayPerceptionInput = rayInput;

            SetNumObservations(rayInput.OutputSize());

            if (Application.isEditor)
            {
                m_DebugDisplayInfo = new DebugDisplayInfo();
            }
        }
示例#3
0
        /// <summary>
        /// Evaluates the raycasts to be used as part of an observation of an agent.
        /// </summary>
        /// <param name="input">Input defining the rays that will be cast.</param>
        /// <returns>Output struct containing the raycast results.</returns>
        public static RayPerceptionOutput Perceive(RayPerceptionInput input)
        {
            RayPerceptionOutput output = new RayPerceptionOutput();

            output.RayOutputs = new RayPerceptionOutput.RayOutput[input.Angles.Count];

            for (var rayIndex = 0; rayIndex < input.Angles.Count; rayIndex++)
            {
                output.RayOutputs[rayIndex] = PerceiveSingleRay(input, rayIndex);
            }

            return(output);
        }
示例#4
0
 internal void SetRayPerceptionInput(RayPerceptionInput rayInput)
 {
     // Note that change the number of rays or tags doesn't directly call this,
     // but changing them and then changing another field will.
     if (m_RayPerceptionInput.OutputSize() != rayInput.OutputSize())
     {
         Debug.Log(
             "Changing the number of tags or rays at runtime is not " +
             "supported and may cause errors in training or inference."
             );
         // Changing the shape will probably break things downstream, but we can at least
         // keep this consistent.
         SetNumObservations(rayInput.OutputSize());
     }
     m_RayPerceptionInput = rayInput;
 }
示例#5
0
        /// <summary>
        /// Evaluate the raycast results of a single ray from the RayPerceptionInput.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="rayIndex"></param>
        /// <param name="debugRayOut"></param>
        /// <returns></returns>
        internal static RayPerceptionOutput.RayOutput PerceiveSingleRay(
            RayPerceptionInput input,
            int rayIndex,
            out DebugDisplayInfo.RayInfo debugRayOut
            )
        {
            var unscaledRayLength  = input.RayLength;
            var unscaledCastRadius = input.CastRadius;

            var extents            = input.RayExtents(rayIndex);
            var startPositionWorld = extents.StartPositionWorld;
            var endPositionWorld   = extents.EndPositionWorld;

            var rayDirection = endPositionWorld - startPositionWorld;
            // If there is non-unity scale, |rayDirection| will be different from rayLength.
            // We want to use this transformed ray length for determining cast length, hit fraction etc.
            // We also it to scale up or down the sphere or circle radii
            var scaledRayLength = rayDirection.magnitude;
            // Avoid 0/0 if unscaledRayLength is 0
            var scaledCastRadius = unscaledRayLength > 0 ?
                                   unscaledCastRadius * scaledRayLength / unscaledRayLength :
                                   unscaledCastRadius;

            // Do the cast and assign the hit information for each detectable tag.
            bool       castHit;
            float      hitFraction;
            GameObject hitObject;

            if (input.CastType == RayPerceptionCastType.Cast3D)
            {
                RaycastHit rayHit;
                if (scaledCastRadius > 0f)
                {
                    castHit = Physics.SphereCast(startPositionWorld, scaledCastRadius, rayDirection, out rayHit,
                                                 scaledRayLength, input.LayerMask);
                }
                else
                {
                    castHit = Physics.Raycast(startPositionWorld, rayDirection, out rayHit,
                                              scaledRayLength, input.LayerMask);
                }

                // If scaledRayLength is 0, we still could have a hit with sphere casts (maybe?).
                // To avoid 0/0, set the fraction to 0.
                hitFraction = castHit ? (scaledRayLength > 0 ? rayHit.distance / scaledRayLength : 0.0f) : 1.0f;
                hitObject   = castHit ? rayHit.collider.gameObject : null;
            }
            else
            {
                RaycastHit2D rayHit;
                if (scaledCastRadius > 0f)
                {
                    rayHit = Physics2D.CircleCast(startPositionWorld, scaledCastRadius, rayDirection,
                                                  scaledRayLength, input.LayerMask);
                }
                else
                {
                    rayHit = Physics2D.Raycast(startPositionWorld, rayDirection, scaledRayLength, input.LayerMask);
                }

                castHit     = rayHit;
                hitFraction = castHit ? rayHit.fraction : 1.0f;
                hitObject   = castHit ? rayHit.collider.gameObject : null;
            }

            var rayOutput = new RayPerceptionOutput.RayOutput
            {
                HasHit          = castHit,
                HitFraction     = hitFraction,
                HitTaggedObject = false,
                HitTagIndex     = -1,
                HitGameObject   = hitObject
            };

            if (castHit)
            {
                // Find the index of the tag of the object that was hit.
                var numTags = input.DetectableTags?.Count ?? 0;
                for (var i = 0; i < numTags; i++)
                {
                    var tagsEqual = false;
                    try
                    {
                        var tag = input.DetectableTags[i];
                        if (!string.IsNullOrEmpty(tag))
                        {
                            tagsEqual = hitObject.CompareTag(tag);
                        }
                    }
                    catch (UnityException e)
                    {
                        // If the tag is null, empty, or not a valid tag, just ignore it.
                    }

                    if (tagsEqual)
                    {
                        rayOutput.HitTaggedObject = true;
                        rayOutput.HitTagIndex     = i;
                        break;
                    }
                }
            }

            debugRayOut.worldStart = startPositionWorld;
            debugRayOut.worldEnd   = endPositionWorld;
            debugRayOut.rayOutput  = rayOutput;
            debugRayOut.castRadius = scaledCastRadius;

            return(rayOutput);
        }
        /// <summary>
        /// Evaluate the raycast results of a single ray from the RayPerceptionInput.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="rayIndex"></param>
        /// <param name="debugRayOut"></param>
        /// <returns></returns>
        internal static RayPerceptionOutput.RayOutput PerceiveSingleRay(
            RayPerceptionInput input,
            int rayIndex,
            out DebugDisplayInfo.RayInfo debugRayOut
            )
        {
            var unscaledRayLength  = input.RayLength;
            var unscaledCastRadius = input.CastRadius;

            var extents            = input.RayExtents(rayIndex);
            var startPositionWorld = extents.StartPositionWorld;
            var endPositionWorld   = extents.EndPositionWorld;

            var rayDirection = endPositionWorld - startPositionWorld;
            // If there is non-unity scale, |rayDirection| will be different from rayLength.
            // We want to use this transformed ray length for determining cast length, hit fraction etc.
            // We also it to scale up or down the sphere or circle radii
            var scaledRayLength = rayDirection.magnitude;
            // Avoid 0/0 if unscaledRayLength is 0
            var scaledCastRadius = unscaledRayLength > 0 ?
                                   unscaledCastRadius * scaledRayLength / unscaledRayLength :
                                   unscaledCastRadius;

            // Do the cast and assign the hit information for each detectable tag.
            bool       castHit;
            float      hitFraction;
            GameObject hitObject;
            RaycastHit rayHit = new RaycastHit();;

            if (input.CastType == RayPerceptionCastType.Cast3D)
            {
                if (scaledCastRadius > 0f)
                {
                    // castHit = Physics.SphereCast(startPositionWorld, scaledCastRadius, rayDirection, out rayHit,
                    //     scaledRayLength, input.LayerMask);
                    System.Random rnd = new System.Random();
                    castHit = (rnd.Next(2) == 0);
                }
                else
                {
                    // castHit = Physics.Raycast(startPositionWorld, rayDirection, out rayHit,
                    //     scaledRayLength, input.LayerMask);
                    System.Random rnd = new System.Random();
                    castHit = (rnd.Next(2) == 0);
                }

                // If scaledRayLength is 0, we still could have a hit with sphere casts (maybe?).
                // To avoid 0/0, set the fraction to 0.
                hitFraction = castHit ? (scaledRayLength > 0 ? rayHit.distance / scaledRayLength : 0.0f) : 1.0f;
                // hitObject = castHit ? rayHit.collider.gameObject : null;
            }
            else
            {
                RaycastHit2D ray2Hit;
                if (scaledCastRadius > 0f)
                {
                    ray2Hit = Physics2D.CircleCast(startPositionWorld, scaledCastRadius, rayDirection,
                                                   scaledRayLength, input.LayerMask);
                }
                else
                {
                    ray2Hit = Physics2D.Raycast(startPositionWorld, rayDirection, scaledRayLength, input.LayerMask);
                }

                castHit     = ray2Hit;
                hitFraction = castHit ? ray2Hit.fraction : 1.0f;
                //  hitObject = castHit ? ray2Hit.collider.gameObject : null;
            }

            var rayOutput = new RayPerceptionOutput.RayOutput
            {
                HasHit          = castHit,
                HitFraction     = hitFraction,
                HitTaggedObject = false,
                HitTagIndex     = -1
            };

            if (castHit)
            {
                // Find the index of the tag of the object that was hit.
                for (var i = 0; i < input.DetectableTags.Count; i++)
                {
                    //   if (hitObject.CompareTag(input.DetectableTags[i]))
                    //   {
                    rayOutput.HitTaggedObject = true;
                    rayOutput.HitTagIndex     = i;
                    break;
                    //  }
                }
            }

            debugRayOut.worldStart = startPositionWorld;
            debugRayOut.worldEnd   = endPositionWorld;
            debugRayOut.rayOutput  = rayOutput;
            debugRayOut.castRadius = scaledCastRadius;

            return(rayOutput);
        }