Skip to content

Commit c55625b

Browse files
committed
Addressed first round of review comments
1 parent db0f70f commit c55625b

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

com.unity.perception/Documentation~/FAQ/FAQ.md

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -150,33 +150,35 @@ This Randomizer takes a list of `PrefabCluster` assets, then, on each Iteration,
150150

151151
The provided `ForegroundObjectPlacementRandomizer` uses Poisson Disk sampling to find randomly positioned points in the space denoted by the provided `Width` and `Height` values. The lower bound on the distance between the sampled points will be `Separation Distance`. The number of sampled points will be the maximum number of points in the given area that match these criteria.
152152

153-
Thus, to limit the number of spawned objects, you can simply introduce a hard limit in the `for` loop that iterates over the Poisson Disk samples, to break out of the loop if the limit is reached. For example:
154-
153+
Thus, to limit the number of spawned objects, you can simply introduce a hard limit in the `for` loop that iterates over the Poisson Disk samples, to break out of the loop if the limit is reached. Additionally, we will need to shuffle the list of points retrieved from the Poisson Disk sampling in order to remove any selection bias when building our subset of points. This is because Poisson Disk points are sampled in sequence and relative to the points already sampled, therefore, the initial points in the list are likely to be closer to each other. We will use a `FloatParameter` to perform this shuffle, so that we can guarantee that our simulation is deterministic and reproducible.
155154
```C#
155+
FloatParameter m_IndexShuffleParameter = new FloatParameter { value = new UniformSampler(0, 1) };
156+
156157
protected override void OnIterationStart()
157158
{
158159
var seed = SamplerState.NextRandomState();
159-
160-
//retrieve points using Poisson Disk sampling
161160
var placementSamples = PoissonDiskSampling.GenerateSamples(
162161
placementArea.x, placementArea.y, separationDistance, seed);
163-
164162
var offset = new Vector3(placementArea.x, placementArea.y, 0f) * -0.5f;
165163

166-
var limit = 50;
164+
//shuffle retrieved points
165+
var indexes = Enumerable.Range(0, placementSamples.Length).ToList();
166+
indexes = indexes.OrderBy(item => m_IndexShuffleParameter.Sample()).ToList();
167+
167168
//maximum number of objects to place
169+
var limit = 50;
168170

169171
var instantiatedCount = 0;
170172
//iterate over all points
171-
foreach (var sample in placementSamples)
173+
foreach (var index in indexes)
172174
{
175+
instantiatedCount ++;
176+
173177
if (instantiatedCount == limit)
174178
break;
175179

176-
instantiatedCount ++;
177-
178180
var instance = m_GameObjectOneWayCache.GetOrInstantiate(prefabs.Sample());
179-
instance.transform.position = new Vector3(sample.x, sample.y, depth) + offset;
181+
instance.transform.position = new Vector3(placementSamples[index].x, placementSamples[index].y, depth) + offset;
180182
}
181183
placementSamples.Dispose();
182184
}
@@ -348,6 +350,8 @@ protected override void OnIterationStart()
348350
}
349351
}
350352
```
353+
Additionally, keep in mind that you can use Perception Samplers (and therefore Parameters) to generate constant values, not just random ones. The `ConstantSampler` class provides this functionality.
354+
351355
---
352356
</details>
353357

@@ -358,7 +362,28 @@ The objects instantiated by the sample foreground Randomizer are all parented to
358362

359363
Alternatively, you could also place `Foreground Objects` inside another GameObject in the Scene using the `Transform.SetParent()` method, and then modify the local position and rotation of `Foreground Objects` in such a way that makes the objects appear on the surface of the parent GameObject.
360364

361-
To achieve more natural placement, you could also use Unity's physics engine to drop the objects on a surface, let them settle, and then capture an image. To achieve this, you would just need to have sufficient frames in each Iteration of the Scenario (instead of the default 1 frame per iteration), and set your Perception Camera's capture interval to a large enough number that would make it capture each Iteration once after the objects have settled. This example is explained in more detail in the [Perception Camera](#perception-camera) section of this FAQ.
365+
In addition, if you'd like to have horizontal placement without touching the parent object, you can modify the Randomizer's code to place objects horizontally instead of vertically. The lines responsible for placement are:
366+
```C#
367+
var offset = new Vector3(placementArea.x, placementArea.y, 0) * -0.5f;
368+
```
369+
```C#
370+
instance.transform.position = new Vector3(sample.x, sample.y, depth) + offset;
371+
```
372+
373+
The first line builds an offset vector that is later used to center the points retrieved from Poisson Disk sampling around the center of the coordinate system. The second line is executed in a loop, and each time, places one object at one of the sampled points at the depth (along Z axis) provided by the user.
374+
375+
To make this placement horizontal, you would just need to change these two lines to swap Y for Z. The resulting lines would be:
376+
377+
```C#
378+
var offset = new Vector3(placementArea.x, 0, placementArea.y) * -0.5f;
379+
```
380+
```C#
381+
instance.transform.position = new Vector3(sample.x, depth, sample.y) + offset;
382+
```
383+
384+
Note that the variable `depth` is in fact playing the role of a height variable now.
385+
386+
Finally, to achieve more natural placement, you could also use Unity's physics engine to drop the objects on a surface, let them settle, and then capture an image. To achieve this, you would just need to have sufficient frames in each Iteration of the Scenario (instead of the default 1 frame per iteration), and set your Perception Camera's capture interval to a large enough number that would make it capture each Iteration once after the objects have settled. This example is explained in more detail in the [Perception Camera](#perception-camera) section of this FAQ.
362387

363388
---
364389
</details>
@@ -388,9 +413,9 @@ Each Iteration of the Scenario resets the Perception Camera's timing variables.
388413
<details>
389414
<summary><strong>Q: I want to simulate physics (or other accumulative behaviors such as auto-exposure) for a number of frames and let things settle before capturing the Scene. Is this possible with the Perception package?</strong></summary><br>
390415

391-
The Perception Camera can be set to capture at specific frame intervals, rather than every frame. The `Frames Between Captures` value is set to 0 by default, which causes the camera to capture all frames; however, you can change this to 1 to capture every other frame, or larger numbers to allow more time between captures. You can also have the camera start capturing at a certain frame rather the first frame, by setting the `Start at Frame` value to a value other than 0. All of this timing happens within each Iteration of the Scenario, and gets reset when you advance to the next Iteration. Therefore, the combination of these properties and the Scenario's `Frames Per Iteration` property allows you to randomize the state of your Scene at the start of each Iteration, let things run for a number of frames, and then capture the Scene at the end of the Iteration.
416+
Yes. The Perception Camera can be set to capture at specific frame intervals, rather than every frame. The `Frames Between Captures` value is set to 0 by default, which causes the camera to capture all frames; however, you can change this to 1 to capture every other frame, or larger numbers to allow more time between captures. You can also have the camera start capturing at a certain frame rather the first frame, by setting the `Start at Frame` value to a value other than 0. All of this timing happens within each Iteration of the Scenario, and gets reset when you advance to the next Iteration. Therefore, the combination of these properties and the Scenario's `Frames Per Iteration` property allows you to randomize the state of your Scene at the start of each Iteration, let things run for a number of frames, and then capture the Scene at the end of the Iteration.
392417

393-
Suppose we need to drop a few objects into the Scene, let them interact physically and settle after a number of frames, and then capture their final state once. Afterwards, we want to repeat this cycle by randomizing the initial positions of the objects, dropping them, and capturing the final state again. We will set the Scenario's `Frames Per Iteration` to 300, which should be sufficient for the objects to get close to a settled position (this depends on the value you use for `Simulation Delta Time` in Perception Camera and the physical properties of the engine and objects, and can be found through experimentation). We also set the `Start at Frame` value of the Perception Camera to 290, and the `Frames Between Captures` to a sufficiently large number (like 100), so that we only get one capture per Iteration of the Scenario. The results look like below. Note how the bounding boxes only update after the objects are fairly settled. These are the timestamps at which captures are happening.
418+
Suppose we need to drop a few objects into the Scene, let them interact physically and settle after a number of frames, and then capture their final state once. Afterwards, we want to repeat this cycle by randomizing the initial positions of the objects, dropping them, and capturing the final state again. We will set the Scenario's `Frames Per Iteration` to 300, which should be sufficient for the objects to get close to a settled position (this depends on the value you use for `Simulation Delta Time` in Perception Camera and the physical properties of the engine and objects, and can be found through experimentation). We also set the `Start at Frame` value of the Perception Camera to 290, and the `Frames Between Captures` to a sufficiently large number (like 100), so that we only get one capture per Iteration of the Scenario. The results look like below. Note how the bounding boxes only appear after the objects are fairly settled. These are the timestamps at which captures are happening.
394419

395420

396421
<p align="center">
@@ -412,9 +437,9 @@ Yes. The Perception Camera offers two trigger modes, `Scheduled` and `Manual`, a
412437
<details>
413438
<summary><strong>Q: Can I have multiple Perception Cameras active in my Scene simultaneously?</strong></summary><br>
414439

415-
We currently do not support multiple active Perception Cameras, but you may be able to get things working partially if you clone the repository and modify parts of the code to fix some of the more easy-to-fix issues such as file sharing errors. You would also need to use render textures on all cameras. That said, there are still issues with the render pipeline that may prevent you from using Labelers of the same kind with different Label Configs on these cameras.
440+
No, at this time the Perception package only supports one active Perception Camera. This is something that is on our roadmap and we hope to support soon.
416441

417-
However, you can have more than one Perception Camera in the Scene, if only one is active when the simulation starts. Therefore, one possible workaround, if your simulation is fully deterministic from one run to the next, would be to run the simulation more than once, each time with one of the cameras active. While not ideal, this will at least let you generate matching datasets.
442+
However, the package does support having more than one Perception Camera in the Scene, as long as only one is active when the simulation starts. Therefore, one possible workaround, if your simulation is fully deterministic from one run to the next, would be to run the simulation more than once, each time with one of the cameras active. While not ideal, this will at least let you generate matching datasets.
418443

419444
---
420445
</details>
1.98 MB
Loading

0 commit comments

Comments
 (0)