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