Skip to content

Commit a377a5b

Browse files
Add 3dbb tests (#267)
* Adding and updating 3d bb tests. * Adding more BB3D tests * Adding more tests for camera transforms and fixing labeler.
1 parent 8db5043 commit a377a5b

File tree

2 files changed

+247
-27
lines changed

2 files changed

+247
-27
lines changed

com.unity.perception/Runtime/GroundTruth/Labelers/BoundingBox3DLabeler.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,13 @@ void ProcessLabel(Labeling labeledEntity)
294294
combinedBounds.center = labelTransform.TransformPoint(combinedBounds.center);
295295
combinedBounds.extents = Vector3.Scale(combinedBounds.extents, labelTransform.lossyScale);
296296

297-
// Now convert all points into camera's space
298-
var cameraCenter = cameraTransform.InverseTransformPoint(combinedBounds.center);
299-
cameraCenter = Vector3.Scale(cameraTransform.localScale, cameraCenter);
297+
// Now adjust the center and rotation to camera space. Camera space transforms never rescale objects
298+
combinedBounds.center = combinedBounds.center - cameraTransform.position;
299+
combinedBounds.center = Quaternion.Inverse(cameraTransform.rotation) * combinedBounds.center;
300300

301-
// Rotation to go from label space to camera space
302301
var cameraRotation = Quaternion.Inverse(cameraTransform.rotation) * labelTransform.rotation;
303302

304-
var converted = ConvertToBoxData(labelEntry, labeledEntity.instanceId, cameraCenter, combinedBounds.extents, cameraRotation);
303+
var converted = ConvertToBoxData(labelEntry, labeledEntity.instanceId, combinedBounds.center, combinedBounds.extents, cameraRotation);
305304

306305
m_BoundingBoxValues[m_CurrentFrame][labeledEntity.instanceId] = converted;
307306
}
@@ -311,7 +310,7 @@ void ProcessLabel(Labeling labeledEntity)
311310
static Vector3 CalculateRotatedPoint(Camera cam, Vector3 start, Vector3 xDirection, Vector3 yDirection, Vector3 zDirection, float xScalar, float yScalar, float zScalar)
312311
{
313312
var rotatedPoint = start + xDirection * xScalar + yDirection * yScalar + zDirection * zScalar;
314-
var worldPoint = cam.transform.TransformPoint(rotatedPoint);
313+
var worldPoint = cam.transform.position + cam.transform.rotation * rotatedPoint;
315314
return VisualizationHelper.ConvertToScreenSpace(cam, worldPoint);
316315
}
317316

com.unity.perception/Tests/Runtime/GroundTruthTests/BoundingBox3dTests.cs

Lines changed: 242 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public IEnumerator CameraOffset_ProduceProperTranslationTest()
4242
labelId = 1,
4343
labelName = "label",
4444
position = new Vector3(0, 0, 10),
45-
scale = new Vector3(5, 5, 5),
45+
scale = new Vector3(10, 10, 10),
4646
rotation = Quaternion.identity
4747
}
4848
};
@@ -63,7 +63,7 @@ public IEnumerator CameraOffsetAndRotated_ProduceProperTranslationTest()
6363
labelId = 1,
6464
labelName = "label",
6565
position = new Vector3(0, 0, Mathf.Sqrt(200)),
66-
scale = new Vector3(5, 5, 5),
66+
scale = new Vector3(10, 10, 10),
6767
rotation = Quaternion.identity
6868
}
6969
};
@@ -84,7 +84,7 @@ public IEnumerator SimpleMultiMesh_ProduceProperTranslationTest()
8484
labelId = 1,
8585
labelName = "label",
8686
position = new Vector3(0, 0, 10),
87-
scale = new Vector3(6.5f, 2.5f, 2.5f),
87+
scale = new Vector3(13f, 5f, 5f),
8888
rotation = Quaternion.identity
8989
}
9090
};
@@ -95,6 +95,223 @@ public IEnumerator SimpleMultiMesh_ProduceProperTranslationTest()
9595
return ExecuteTest(target, cameraPosition, cameraRotation, expected);
9696
}
9797

98+
public class ParentedTestData
99+
{
100+
public string name;
101+
102+
public Vector3 expectedScale = Vector3.one;
103+
public Vector3 expectedPosition = new Vector3(0, 0, 10);
104+
public Quaternion expectedRotation = Quaternion.identity;
105+
106+
public Vector3 childScale = Vector3.one;
107+
public Vector3 childPosition = Vector3.zero;
108+
public Quaternion childRotation = Quaternion.identity;
109+
110+
public Vector3 grandchildScale = Vector3.one;
111+
public Vector3 grandchildPosition = Vector3.zero;
112+
public Quaternion grandchildRotation = Quaternion.identity;
113+
114+
public Vector3 parentScale = Vector3.one;
115+
public Vector3 parentPosition = Vector3.zero;
116+
public Quaternion parentRotation = Quaternion.identity;
117+
118+
public Vector3 grandparentScale = Vector3.one;
119+
public Vector3 grandparentPosition = Vector3.zero;
120+
public Quaternion grandparentRotation = Quaternion.identity;
121+
122+
public Vector3 cameraParentScale = Vector3.one;
123+
public Vector3 cameraParentPosition = Vector3.zero;
124+
public Quaternion cameraParentRotation = Quaternion.identity;
125+
126+
public Vector3 cameraScale = Vector3.one;
127+
public Vector3 cameraPosition = new Vector3(0, 0, -10);
128+
public Quaternion cameraRotation = Quaternion.identity;
129+
130+
public override string ToString()
131+
{
132+
return name;
133+
}
134+
}
135+
136+
static IEnumerable<ParentedTestData> ParentedObject_ProduceProperResults_Values()
137+
{
138+
yield return new ParentedTestData()
139+
{
140+
name = "ParentScale",
141+
expectedScale = new Vector3(1/5f, 1/5f, 1/5f),
142+
parentScale = new Vector3(1/5f, 1/5f, 1/5f),
143+
};
144+
yield return new ParentedTestData()
145+
{
146+
name = "GrandparentScale",
147+
expectedScale = new Vector3(1/5f, 1/5f, 1/5f),
148+
grandparentScale = new Vector3(1/5f, 1/5f, 1/5f),
149+
};
150+
yield return new ParentedTestData()
151+
{
152+
name = "ChildScale",
153+
expectedScale = new Vector3(1/5f, 1/5f, 1/5f),
154+
childScale = new Vector3(1/5f, 1/5f, 1/5f),
155+
};
156+
yield return new ParentedTestData()
157+
{
158+
name = "ChildAndParentScale",
159+
expectedScale = new Vector3(1f, 1f, 1f),
160+
childScale = new Vector3(5, 5, 5),
161+
parentScale = new Vector3(1/5f, 1/5f, 1/5f),
162+
};
163+
yield return new ParentedTestData()
164+
{
165+
name = "GrandchildScale",
166+
expectedScale = new Vector3(2, 2, 2),
167+
childScale = new Vector3(2, 2, 2),
168+
grandchildScale = new Vector3(5, 5, 5),
169+
parentScale = new Vector3(1/5f, 1/5f, 1/5f),
170+
};
171+
yield return new ParentedTestData()
172+
{
173+
name = "ParentRotation",
174+
expectedRotation = Quaternion.Euler(1f, 2f, 3f),
175+
parentRotation = Quaternion.Euler(1f, 2f, 3f),
176+
};
177+
yield return new ParentedTestData()
178+
{
179+
name = "ChildRotation",
180+
expectedRotation = Quaternion.Euler(1f, 2f, 3f),
181+
childRotation = Quaternion.Euler(1f, 2f, 3f),
182+
};
183+
yield return new ParentedTestData()
184+
{
185+
name = "ParentAndChildRotation",
186+
expectedRotation = Quaternion.identity,
187+
childRotation = Quaternion.Euler(20f, 0, 0),
188+
parentRotation = Quaternion.Euler(-20f, 0, 0),
189+
};
190+
var diagonalSize = Mathf.Sqrt(2 * 2 + 2 * 2); //A^2 + B^2 = C^2
191+
yield return new ParentedTestData()
192+
{
193+
name = "GrandchildRotation",
194+
expectedRotation = Quaternion.identity,
195+
expectedScale = new Vector3(diagonalSize / 2f, 1, diagonalSize / 2f),
196+
grandchildRotation = Quaternion.Euler(0, 45, 0),
197+
};
198+
yield return new ParentedTestData()
199+
{
200+
name = "GrandparentRotation",
201+
expectedRotation = Quaternion.Euler(-20f, 0, 0),
202+
grandparentRotation = Quaternion.Euler(-20f, 0, 0),
203+
};
204+
yield return new ParentedTestData()
205+
{
206+
name = "GrandchildTRS",
207+
expectedRotation = Quaternion.identity,
208+
expectedPosition = new Vector3(-5, 0, 10),
209+
expectedScale = new Vector3(.5f * diagonalSize / 2f, .5f, .5f * diagonalSize / 2f),
210+
grandchildRotation = Quaternion.Euler(0, -45, 0),
211+
grandchildPosition = new Vector3(-5, 0, 0),
212+
grandchildScale = new Vector3(.5f, .5f, .5f),
213+
};
214+
yield return new ParentedTestData()
215+
{
216+
name = "CamParentPositionAndScale",
217+
expectedRotation = Quaternion.identity,
218+
expectedPosition = new Vector3(2, 0, 6.5f),
219+
expectedScale = new Vector3(1, 1, 1),
220+
childPosition = new Vector3(0, 0, 4),
221+
cameraParentPosition = new Vector3(-2, 0, 0),
222+
cameraParentScale = new Vector3(1/2f, 1/3f, 1/4f),
223+
};
224+
//point at the left side of the box
225+
yield return new ParentedTestData()
226+
{
227+
name = "CamParentRotate",
228+
expectedRotation = Quaternion.Euler(0, -90, 0),
229+
expectedPosition = new Vector3(0, 0, 10),
230+
cameraParentRotation = Quaternion.Euler(0, 90, 0),
231+
};
232+
//point at the left side of the box
233+
yield return new ParentedTestData()
234+
{
235+
name = "CamParentScale",
236+
expectedPosition = new Vector3(0, 0, 2.5f),
237+
//Scale on the camera's hierarchy only affects the position of the camera. It does not affect the camera frustum
238+
cameraParentScale = new Vector3(1/2f, 1/3f, 1/4f),
239+
};
240+
yield return new ParentedTestData()
241+
{
242+
name = "CamRotationParentScale",
243+
expectedRotation = Quaternion.Euler(0, -90, 0),
244+
expectedPosition = new Vector3(0, 0, 5),
245+
cameraParentPosition = new Vector3(-5, 0, 0),
246+
cameraParentScale = new Vector3(.5f, 1, 1),
247+
cameraPosition = Vector3.zero,
248+
cameraRotation = Quaternion.Euler(0, 90, 0),
249+
};
250+
}
251+
[UnityTest]
252+
public IEnumerator ParentedObject_ProduceProperResults([ValueSource(nameof(ParentedObject_ProduceProperResults_Values))] ParentedTestData parentedTestData)
253+
{
254+
var expected = new[]
255+
{
256+
new ExpectedResult
257+
{
258+
instanceId = 1,
259+
labelId = 1,
260+
labelName = "label",
261+
position = parentedTestData.expectedPosition,
262+
scale = parentedTestData.expectedScale,
263+
rotation = parentedTestData.expectedRotation
264+
}
265+
};
266+
267+
var goGrandparent = new GameObject();
268+
goGrandparent.transform.localPosition = parentedTestData.grandparentPosition;
269+
goGrandparent.transform.localScale = parentedTestData.grandparentScale;
270+
goGrandparent.transform.localRotation = parentedTestData.grandparentRotation;
271+
272+
var goParent = new GameObject();
273+
goParent.transform.SetParent(goGrandparent.transform, false);
274+
goParent.transform.localPosition = parentedTestData.parentPosition;
275+
goParent.transform.localScale = parentedTestData.parentScale;
276+
goParent.transform.localRotation = parentedTestData.parentRotation;
277+
278+
var goChild = new GameObject();
279+
goChild.transform.SetParent(goParent.transform, false);
280+
281+
goChild.transform.localPosition = parentedTestData.childPosition;
282+
goChild.transform.localScale = parentedTestData.childScale;
283+
goChild.transform.localRotation = parentedTestData.childRotation;
284+
285+
var labeling = goChild.AddComponent<Labeling>();
286+
labeling.labels.Add("label");
287+
288+
var goGrandchild = GameObject.CreatePrimitive(PrimitiveType.Cube);
289+
goGrandchild.transform.SetParent(goChild.transform, false);
290+
291+
goGrandchild.transform.localPosition = parentedTestData.grandchildPosition;
292+
goGrandchild.transform.localScale = parentedTestData.grandchildScale;
293+
goGrandchild.transform.localRotation = parentedTestData.grandchildRotation;
294+
295+
var goCameraParent = new GameObject();
296+
goCameraParent.transform.localPosition = parentedTestData.cameraParentPosition;
297+
goCameraParent.transform.localScale = parentedTestData.cameraParentScale;
298+
goCameraParent.transform.localRotation = parentedTestData.cameraParentRotation;
299+
300+
var receivedResults = new List<(int, List<BoundingBox3DLabeler.BoxData>)>();
301+
var cameraObject = SetupCamera(SetupLabelConfig(), (frame, data) =>
302+
{
303+
receivedResults.Add((frame, data));
304+
});
305+
306+
cameraObject.transform.SetParent(goCameraParent.transform, false);
307+
cameraObject.transform.localPosition = parentedTestData.cameraPosition;
308+
cameraObject.transform.localScale = parentedTestData.cameraScale;
309+
cameraObject.transform.localRotation = parentedTestData.cameraRotation;
310+
cameraObject.SetActive(true);
311+
312+
return ExecuteTestOnCamera(goGrandparent, expected, goCameraParent, receivedResults);
313+
}
314+
98315
[UnityTest]
99316
public IEnumerator MultiInheritedMesh_ProduceProperTranslationTest()
100317
{
@@ -106,7 +323,7 @@ public IEnumerator MultiInheritedMesh_ProduceProperTranslationTest()
106323
labelId = 2,
107324
labelName = "car",
108325
position = new Vector3(0, 0.525f, 20),
109-
scale = new Vector3(2f, 0.875f, 2.4f),
326+
scale = new Vector3(4f, 1.75f, 4.8f),
110327
rotation = Quaternion.identity
111328
},
112329
};
@@ -121,7 +338,7 @@ public IEnumerator MultiInheritedMesh_ProduceProperTranslationTest()
121338
[UnityTest]
122339
public IEnumerator MultiInheritedMeshDifferentLabels_ProduceProperTranslationTest()
123340
{
124-
var wheelScale = new Vector3(0.35f, 1.0f, 0.35f);
341+
var wheelScale = new Vector3(0.7f, 2.0f, 0.7f);
125342
var wheelRot = Quaternion.Euler(0, 0, 90);
126343

127344
var expected = new[]
@@ -132,7 +349,7 @@ public IEnumerator MultiInheritedMeshDifferentLabels_ProduceProperTranslationTes
132349
labelId = 2,
133350
labelName = "car",
134351
position = new Vector3(0, 1.05f, 20),
135-
scale = new Vector3(1f, 0.7f, 2.4f),
352+
scale = new Vector3(2f, 1.4f, 4.8f),
136353
rotation = Quaternion.identity
137354
},
138355
new ExpectedResult
@@ -174,8 +391,8 @@ public IEnumerator TestOcclusion_Unseen()
174391
var target = TestHelper.CreateLabeledCube(scale: 15f, z: -50f);
175392
return ExecuteSeenUnseenTest(target, Vector3.zero, quaternion.identity, 0);
176393
}
177-
178-
394+
395+
179396
struct ExpectedResult
180397
{
181398
public int labelId;
@@ -205,13 +422,13 @@ IEnumerator ExecuteSeenUnseenTest(GameObject target, Vector3 cameraPos, Quaterni
205422

206423
yield return null;
207424
yield return null;
208-
425+
209426
Assert.AreEqual(expectedSeen, receivedResults[0].Item2.Count);
210427

211428
DestroyTestObject(gameObject);
212429
UnityEngine.Object.DestroyImmediate(target);
213430
}
214-
431+
215432
IEnumerator ExecuteTest(GameObject target, Vector3 cameraPos, Quaternion cameraRotation, IList<ExpectedResult> expectations)
216433
{
217434
var receivedResults = new List<(int, List<BoundingBox3DLabeler.BoxData>)>();
@@ -223,15 +440,22 @@ IEnumerator ExecuteTest(GameObject target, Vector3 cameraPos, Quaternion cameraR
223440
gameObject.transform.position = cameraPos;
224441
gameObject.transform.rotation = cameraRotation;
225442

226-
AddTestObjectForCleanup(gameObject);
443+
return ExecuteTestOnCamera(target, expectations, gameObject, receivedResults);
444+
}
227445

228-
gameObject.SetActive(false);
446+
private IEnumerator ExecuteTestOnCamera(GameObject target, IList<ExpectedResult> expectations, GameObject cameraObject,
447+
List<(int, List<BoundingBox3DLabeler.BoxData>)> receivedResults)
448+
{
449+
AddTestObjectForCleanup(cameraObject);
450+
AddTestObjectForCleanup(target);
451+
452+
cameraObject.SetActive(false);
229453
receivedResults.Clear();
230-
gameObject.SetActive(true);
454+
cameraObject.SetActive(true);
231455

232456
yield return null;
233457
yield return null;
234-
458+
235459
Assert.AreEqual(expectations.Count, receivedResults[0].Item2.Count);
236460

237461
for (var i = 0; i < receivedResults[0].Item2.Count; i++)
@@ -244,8 +468,7 @@ IEnumerator ExecuteTest(GameObject target, Vector3 cameraPos, Quaternion cameraR
244468
TestResults(b, expectations[i]);
245469
}
246470

247-
DestroyTestObject(gameObject);
248-
UnityEngine.Object.DestroyImmediate(target);
471+
DestroyTestObject(cameraObject);
249472
}
250473

251474
static IdLabelConfig SetupLabelConfig()
@@ -297,15 +520,13 @@ static GameObject SetupCamera(IdLabelConfig config, Action<int, List<BoundingBox
297520

298521
static void TestResults(BoundingBox3DLabeler.BoxData data, ExpectedResult e)
299522
{
300-
var scale = e.scale * 2;
301-
302523
Assert.IsNotNull(data);
303524
Assert.AreEqual(e.position[0], data.translation[0], k_Delta);
304525
Assert.AreEqual(e.position[1], data.translation[1], k_Delta);
305526
Assert.AreEqual(e.position[2], data.translation[2], k_Delta);
306-
Assert.AreEqual(scale[0], data.size[0], k_Delta);
307-
Assert.AreEqual(scale[1], data.size[1], k_Delta);
308-
Assert.AreEqual(scale[2], data.size[2], k_Delta);
527+
Assert.AreEqual(e.scale[0], data.size[0], k_Delta);
528+
Assert.AreEqual(e.scale[1], data.size[1], k_Delta);
529+
Assert.AreEqual(e.scale[2], data.size[2], k_Delta);
309530
Assert.AreEqual(e.rotation[0], data.rotation[0], k_Delta);
310531
Assert.AreEqual(e.rotation[1], data.rotation[1], k_Delta);
311532
Assert.AreEqual(e.rotation[2], data.rotation[2], k_Delta);

0 commit comments

Comments
 (0)