place-camera-aim-at
GitHub在 Isaac Sim 中围绕目标对象自动放置多个无遮挡相机,用于多视角产品或机器人检测。
Trigger Scenarios
Install
npx skills add isaac-sim/IsaacSim --skill place-camera-aim-at -g -y
SKILL.md
Frontmatter
{
"name": "place-camera-aim-at",
"license": "Apache-2.0",
"metadata": {
"author": "NVIDIA Isaac Sim <isaac-sim@nvidia.com>"
},
"description": "Occlusion-aware CircularCameraPlacement around one target prim or world point. Use for multi-angle product or robot inspection shots that must keep the subject visible."
}
Place Cameras Aimed At a Target
Purpose
Ring a single object with N cameras that each have a clear, unoccluded view of it, using the CircularCameraPlacement API of isaacsim.sensors.rtx.placement.
Prerequisites
- Running Isaac Sim 6 / Kit 110 with python_server (port 8226); see
isaac-sim-remote. - Extension
isaacsim.sensors.rtx.placementenabled (action_and_event_data_generation app, or--enable). - Stage contains the target object and a baked navmesh (or pass
scopewithon_navmesh=false). - Shell env:
$ISAAC_SIM_DIR,$ISAAC_LAB_DIR,$WORKSPACE_DIR(isaac-sim-orchestrator).
Limitations
- Does not build
isaacsim.sensors.rtx.placement— consume the pin fromsource/apps/isaacsim.exp.action_and_event_data_generation.base.kit. - Live Kit only (raycast + navmesh); no offline substitute.
- Occlusion uses target bounding boxes, not per-triangle visibility.
- Sampling is stochastic;
random_seed/ density / geometry change results. - For floor-area coverage ratios (not single-object aim), use
place-camera-max-coverage.
Troubleshooting
| Error / symptom | Cause | Solution |
|---|---|---|
AIM_AT_PREFLIGHT: ext=unavailable |
App does not resolve the extension | Launch isaacsim.exp.action_and_event_data_generation.base.sh, or add --enable isaacsim.sensors.rtx.placement |
ValueError: not enough values to unpack (expected 2, got 1) |
Upstream defect — zero surviving directions crashes inside select_sparse_vectors instead of returning None |
The script translates this into remedies: widen distance_range/height_range/yaw_ranges, raise occlusion_threshold (-1 disables), or set on_navmesh=false |
| Script raises "returned no poses" | Validation failed and logged via carb.log_error |
Read the Isaac Sim console; usually height_range below the target, an invisible target, or inverted min/max ranges |
| "Fail to place N cameras from different directions" | Surviving directions non-zero but fewer than num_cameras |
Raise occlusion_threshold, widen distance_range/yaw_ranges, or lower num_cameras |
| "camera height should not be lower than object" | Target sits above height_range[1] |
Raise the height range above the target's Z |
| "target object is invisible" | Target prim already hidden | Make it visible; the API hides it itself during the sweep |
| Cameras appear but views are blocked | Occlusion filtering was silently disabled | Confirm target_prim has Mesh descendants and occlusion_threshold != -1 |
When to use this skill
| You want | Skill |
|---|---|
| N views of this pallet / shelf / robot, each unobstructed | this skill |
| Cover this whole floor area to a coverage ratio | place-camera-max-coverage |
| Author a single camera's intrinsics, AOVs, distortion | isaac-camera |
How the algorithm works
- Hide the target prim, then raycast a sweep of candidate observation directions around it, constrained by
height_range,distance_range,look_down_angle_range, andyaw_ranges. - Restore the target's visibility, then walk each direction outward in
camera_distance_step_sizeincrements, keeping positions that are on the navmesh (and insidescope, when given). - Reject any pose whose occlusion ratio for the target is at or above
occlusion_threshold. - From the surviving directions, pick the
num_camerasmost widely separated (math_util.select_sparse_vectors) so the views are not redundant, and author aCameraprim per pick.
Full parameter semantics and the non-obvious validation behavior live in
references/aim-at-api.md; occlusion internals and
the destructive refresh flag are in
references/aim-at-runtime-notes.md.
Available Scripts
| Script | Purpose | Arguments |
|---|---|---|
scripts/place_camera_aim_at.py |
Place cameras aimed at a target object using isaacsim.sensors.rtx.placement | injected key=value args (see script docstring) |
Running scripts
The script is a python_server payload, not a standalone program. From agent
runtimes that expose skill execution helpers, invoke it with run_script():
run_script("scripts/place_camera_aim_at.py", args=["action=preflight"])
From a built tree, send it through the isaac-sim-remote client:
python skills/isaac-sim-remote/scripts/isaacsim_send.py \
--file skills/place-camera-aim-at/scripts/place_camera_aim_at.py \
--arg action=place --arg target_prim=/World/Pallet --arg num_cameras=3
Workflow
-
Preflight.
action=preflight(the default) reports extension, stage, target, mesh count, and navmesh state without touching the stage. It never raises, so it is safe to run first.run_script("scripts/place_camera_aim_at.py", args=["action=preflight", "target_prim=/World/Pallet"])Expect:
AIM_AT_PREFLIGHT: ext=enabled stage=ok target=ok meshes=12 navmesh=ok. Resolve anything that is notokbefore continuing — the remedy lines say how. -
Place. Give either
target_prim(preferred — enables occlusion filtering) ortarget_point.run_script( "scripts/place_camera_aim_at.py", args=["action=place", "target_prim=/World/Pallet", "num_cameras=3", "height_range=2,4"], )Expect
AIM_AT_RESULT: placed=3 ...plus onecamera[i] position=... focus=...line each. Fewer cameras than requested is a hard error, not a warning. -
Verify. Cameras land under the parent prim path (default
/World/Cameras). Confirm the count and eyeball one render before trusting the placement — the occlusion test is bbox-based. -
Iterate. Vary
random_seedfor a different arrangement with identical constraints; loosenocclusion_thresholdor widendistance_rangewhen placement fails for lack of surviving directions.
Calling the API directly
When you need the poses without authoring prims (spawn_camera defaults to
False):
from isaacsim.sensors.rtx.placement import CircularCameraPlacement
poses = CircularCameraPlacement.circular_camera_placement(
target_object_path="/World/Pallet",
number_of_camera_to_select=3,
camera_height_range=(2.0, 4.0),
camera_distance_range=(6.0, 18.0),
occlusion_threshold=0.4,
spawn_camera=False,
)
if not poses:
raise RuntimeError("placement failed; see the carb log for the reason")
for pose in poses:
print(pose.camera_position, pose.focus_point)
poses is a list of CameraPose dataclasses with camera_position,
camera_direction, and focus_point as np.ndarray. The API returns None
on every failure path rather than raising — always null-check.
Related skills
isaac-sim-remote— the transport this skill's script rides on.place-camera-max-coverage— the area-coverage sibling.isaac-camera— per-camera intrinsics, render products, AOVs, distortion.isaac-sim-sensor— attaching annotators and writers once cameras exist.
Version History
- 2469084 Current 2026-09-22 15:46


