public int Write(WriteAdapter adapter) { // First, call the wrapped sensor's write method. Make sure to use our own adapter, not the passed one. var wrappedShape = m_WrappedSensor.GetObservationShape(); m_LocalAdapter.SetTarget(m_StackedObservations[m_CurrentIndex], wrappedShape, 0); m_WrappedSensor.Write(m_LocalAdapter); // Now write the saved observations (oldest first) var numWritten = 0; for (var i = 0; i < m_NumStackedObservations; i++) { var obsIndex = (m_CurrentIndex + 1 + i) % m_NumStackedObservations; adapter.AddRange(m_StackedObservations[obsIndex], numWritten); numWritten += m_UnstackedObservationSize; } return(numWritten); }
public void TestFloat2DSensorWrite() { var sensor = new Float2DSensor(3, 4, "floatsensor"); for (var h = 0; h < 4; h++) { for (var w = 0; w < 3; w++) { sensor.floatData[h, w] = 3 * h + w; } } var output = new float[12]; var writer = new WriteAdapter(); writer.SetTarget(output, sensor.GetObservationShape(), 0); sensor.Write(writer); for (var i = 0; i < 9; i++) { Assert.AreEqual(i, output[i]); } }
public void TestRayZeroLength() { // Place the cube touching the origin var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.position = new Vector3(0, 0, .5f); cube.tag = k_CubeTag; Physics.SyncTransforms(); var obj = new GameObject("agent"); var perception = obj.AddComponent <RayPerceptionSensorComponent3D>(); perception.raysPerDirection = 0; perception.rayLength = 0.0f; perception.sphereCastRadius = .5f; perception.detectableTags = new List <string>(); perception.detectableTags.Add(k_CubeTag); { // Set the layer mask to either the default, or one that ignores the close cube's layer var sensor = perception.CreateSensor(); var expectedObs = (2 * perception.raysPerDirection + 1) * (perception.detectableTags.Count + 2); Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs); var outputBuffer = new float[expectedObs]; WriteAdapter writer = new WriteAdapter(); writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0); var numWritten = sensor.Write(writer); Assert.AreEqual(numWritten, expectedObs); // hit fraction is arbitrary but should be finite in [0,1] Assert.GreaterOrEqual(outputBuffer[2], 0.0f); Assert.LessOrEqual(outputBuffer[2], 1.0f); } }
public void Generate(TensorProxy tensorProxy, int batchSize, IEnumerable <AgentInfoSensorsPair> infos) { TensorUtils.ResizeTensor(tensorProxy, batchSize, m_Allocator); var agentIndex = 0; foreach (var infoSensorPair in infos) { var sensor = infoSensorPair.sensors[m_SensorIndex]; if (infoSensorPair.agentInfo.done) { // If the agent is done, we might have a stale reference to the sensors // e.g. a dependent object might have been disposed. // To avoid this, just fill observation with zeroes instead of calling sensor.Write. TensorUtils.FillTensorBatch(tensorProxy, agentIndex, 0.0f); } else { m_WriteAdapter.SetTarget(tensorProxy, agentIndex, 0); sensor.Write(m_WriteAdapter); } agentIndex++; } }
public void Generate(TensorProxy tensorProxy, int batchSize, IEnumerable <AgentInfoSensorsPair> infos) { TensorUtils.ResizeTensor(tensorProxy, batchSize, m_Allocator); var vecObsSizeT = tensorProxy.shape[tensorProxy.shape.Length - 1]; var agentIndex = 0; foreach (var info in infos) { if (info.agentInfo.done) { // If the agent is done, we might have a stale reference to the sensors // e.g. a dependent object might have been disposed. // To avoid this, just fill observation with zeroes instead of calling sensor.Write. TensorUtils.FillTensorBatch(tensorProxy, agentIndex, 0.0f); } else { var tensorOffset = 0; // Write each sensor consecutively to the tensor foreach (var sensorIndex in m_SensorIndices) { var sensor = info.sensors[sensorIndex]; m_WriteAdapter.SetTarget(tensorProxy, agentIndex, tensorOffset); var numWritten = sensor.Write(m_WriteAdapter); tensorOffset += numWritten; } Debug.AssertFormat( tensorOffset == vecObsSizeT, "mismatch between vector observation size ({0}) and number of observations written ({1})", vecObsSizeT, tensorOffset ); } agentIndex++; } }
public void TestRaycasts() { SetupScene(); var obj = new GameObject("agent"); var perception = obj.AddComponent <RayPerceptionSensorComponent3D>(); perception.raysPerDirection = 1; perception.maxRayDegrees = 45; perception.rayLength = 20; perception.detectableTags = new List <string>(); perception.detectableTags.Add(k_CubeTag); perception.detectableTags.Add(k_SphereTag); var radii = new[] { 0f, .5f }; foreach (var castRadius in radii) { perception.sphereCastRadius = castRadius; var sensor = perception.CreateSensor(); var expectedObs = (2 * perception.raysPerDirection + 1) * (perception.detectableTags.Count + 2); Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs); var outputBuffer = new float[expectedObs]; WriteAdapter writer = new WriteAdapter(); writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0); var numWritten = sensor.Write(writer); Assert.AreEqual(numWritten, expectedObs); // Expected hits: // ray 0 should hit the cube at roughly halfway // ray 1 should hit a sphere but no tag // ray 2 should hit a sphere with the k_SphereTag tag // The hit fraction should be the same for rays 1 and // Assert.AreEqual(1.0f, outputBuffer[0]); // hit cube Assert.AreEqual(0.0f, outputBuffer[1]); // missed sphere Assert.AreEqual(0.0f, outputBuffer[2]); // missed unknown tag // Hit is at z=9.0 in world space, ray length is 20 Assert.That( outputBuffer[3], Is.EqualTo((9.5f - castRadius) / perception.rayLength).Within(.0005f) ); // Spheres are at 5,0,5 and 5,0,-5, so 5*sqrt(2) units from origin // Minus 1.0 for the sphere radius to get the length of the hit. var expectedHitLengthWorldSpace = 5.0f * Mathf.Sqrt(2.0f) - 0.5f - castRadius; Assert.AreEqual(0.0f, outputBuffer[4]); // missed cube Assert.AreEqual(0.0f, outputBuffer[5]); // missed sphere Assert.AreEqual(0.0f, outputBuffer[6]); // hit unknown tag -> all 0 Assert.That( outputBuffer[7], Is.EqualTo(expectedHitLengthWorldSpace / perception.rayLength).Within(.0005f) ); Assert.AreEqual(0.0f, outputBuffer[8]); // missed cube Assert.AreEqual(1.0f, outputBuffer[9]); // hit sphere Assert.AreEqual(0.0f, outputBuffer[10]); // missed unknown tag Assert.That( outputBuffer[11], Is.EqualTo(expectedHitLengthWorldSpace / perception.rayLength).Within(.0005f) ); } }
public void TestRayFilter() { var cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.position = new Vector3(0, 0, 10); cube.tag = k_CubeTag; cube.name = "cubeFar"; var cubeFiltered = GameObject.CreatePrimitive(PrimitiveType.Cube); cubeFiltered.transform.position = new Vector3(0, 0, 5); cubeFiltered.tag = k_CubeTag; cubeFiltered.name = "cubeNear"; cubeFiltered.layer = 7; Physics.SyncTransforms(); var obj = new GameObject("agent"); var perception = obj.AddComponent <RayPerceptionSensorComponent3D>(); perception.raysPerDirection = 0; perception.rayLength = 20; perception.detectableTags = new List <string>(); var filterCubeLayers = new[] { false, true }; foreach (var filterCubeLayer in filterCubeLayers) { // Set the layer mask to either the default, or one that ignores the close cube's layer var layerMask = Physics.DefaultRaycastLayers; if (filterCubeLayer) { layerMask &= ~(1 << cubeFiltered.layer); } perception.rayLayerMask = layerMask; var sensor = perception.CreateSensor(); var expectedObs = (2 * perception.raysPerDirection + 1) * (perception.detectableTags.Count + 2); Assert.AreEqual(sensor.GetObservationShape()[0], expectedObs); var outputBuffer = new float[expectedObs]; WriteAdapter writer = new WriteAdapter(); writer.SetTarget(outputBuffer, sensor.GetObservationShape(), 0); var numWritten = sensor.Write(writer); Assert.AreEqual(numWritten, expectedObs); if (filterCubeLayer) { // Hit the far cube because close was filtered. Assert.That(outputBuffer[outputBuffer.Length - 1], Is.EqualTo((9.5f - perception.sphereCastRadius) / perception.rayLength).Within(.0005f) ); } else { // Hit the close cube because not filtered. Assert.That(outputBuffer[outputBuffer.Length - 1], Is.EqualTo((4.5f - perception.sphereCastRadius) / perception.rayLength).Within(.0005f) ); } } }