public override ISensor CreateSensor()
        {
            var rayAngles = GetRayAngles(raysPerDirection, maxRayDegrees);

            var rayPerceptionInput = new RayPerceptionInput();

            rayPerceptionInput.rayLength      = rayLength;
            rayPerceptionInput.detectableTags = detectableTags;
            rayPerceptionInput.angles         = rayAngles;
            rayPerceptionInput.startOffset    = GetStartVerticalOffset();
            rayPerceptionInput.endOffset      = GetEndVerticalOffset();
            rayPerceptionInput.castRadius     = sphereCastRadius;
            rayPerceptionInput.transform      = transform;
            rayPerceptionInput.castType       = GetCastType();
            rayPerceptionInput.layerMask      = rayLayerMask;

            m_RaySensor = new RayPerceptionSensor(sensorName, rayPerceptionInput);

            if (observationStacks != 1)
            {
                var stackingSensor = new StackingSensor(m_RaySensor, observationStacks);
                return(stackingSensor);
            }

            return(m_RaySensor);
        }
예제 #2
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>
        /// <param name="output">Output class that will be written to with raycast results.</param>
        ///
        public static RayPerceptionOutput PerceiveStatic(RayPerceptionInput input)
        {
            RayPerceptionOutput output = new RayPerceptionOutput();

            output.rayOutputs = new RayPerceptionOutput.RayOutput[input.angles.Count];

            for (var rayIndex = 0; rayIndex < input.angles.Count; rayIndex++)
            {
                DebugDisplayInfo.RayInfo debugRay;
                output.rayOutputs[rayIndex] = PerceiveSingleRay(input, rayIndex, out debugRay);
            }

            return(output);
        }
예제 #3
0
        public RayPerceptionSensor(string name, RayPerceptionInput rayInput)
        {
            var numObservations = rayInput.OutputSize();

            m_Shape = new[] { numObservations };
            m_Name  = name;
            m_RayPerceptionInput = rayInput;

            m_Observations = new float[numObservations];

            if (Application.isEditor)
            {
                m_DebugDisplayInfo = new DebugDisplayInfo();
            }
        }
예제 #4
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>
        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
            };

            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);
        }
예제 #5
0
 internal void SetRayPerceptionInput(RayPerceptionInput input)
 {
     // TODO make sure that number of rays and tags don't change
     m_RayPerceptionInput = input;
 }