5.1.0 NOTE: We are currently in the process of recreating this behavior on 5.1.0
4.5.0
Operating System
Ubuntu 24.04x
GPU Information
Model: Can provide if needed
Driver Version: Can provide if needed
Topic Description
Detailed Description
We are using the running some calculations to determine a new-position and orientation of multiple vehicles outside of the IsaacSim loop. This is simply because the motion model of our vehicles is currently better represented this way. We are then trying to update the position and orientation of each prim in IsaacSim using the set_local_poses function of a GeometryPrimView wrapping the vehicles.
We are on the order of ~5000 vehicles, and the biggest bottleneck is the amount of time the set_local_poses step takes for all 5000 vehicles. Right now it is 70+% of the loop time. Is there a faster way to batch this update or speed up this implementation?
Thank you!!
Example Code Snippet
# Initialize GeometryPrimView of vehicles
for i in range(0, NUM_VEHICLES):
add_reference_to_stage(
usd_path=VEHICLE_USD_PATH, # Any USD may suffice here
prim_path=f"/World/Drone_{i}",
)
vehicles = GeometryPrimView(
prim_paths_expr="/World/Drone_*",
name="drone_prim_view",
collisions=[False] * vehicle_cnt,
)
pm = calculate_new_poses(pm)
vehicles.set_local_poses(
translations=torch.stack([pm.X.x, pm.X.y, -1 * pm.X.z]).T,
orientations=euler2quat(torch.stack([pm.X.phi, -1 * pm.X.theta, pm.X.psi]).T),
)
Screenshots
Below is an plot of what we’re seeing when timing the vehicles.set_local_poses() call above. While I can provide context for the other calls below, the significant piece is how much of the total loop time setting the poses using the set_local_poses function is costing us.
Hi, GeometryPrimView inherits its pose setters from XFormPrim, which writes USD attributes one prim at a time in a Python loop. Each set_local_poses() call ends up doing ~2N USD attribute writes (one for xformOp:translate, one for xformOp:orient) plus a GetPropertyNames() check per prim.
To speed things up, here’re some options:
Use RigidPrimView (or the SingleRigidPrim/Articulation tensor APIs) if your vehicles can be physics prims. Once physics is initialized, RigidPrimView.set_local_poses() / set_world_poses() dispatch to self._physics_view.set_transforms(...), which is a single batched call backed by a Warp kernel — no per-prim USD churn. If your vehicles are kinematic (you compute the poses externally), make them kinematic rigid bodies (PhysicsRigidBodyAPI + kinematicEnabled=true); they won’t be simulated by PhysX but you still get the tensor-API fast path. This is by far the largest speedup at your scale.
Use the Fabric path via set_world_poses(..., usd=False) if you must stick with non-physics prims. That branch in XFormPrim.set_world_poses() writes through the USDRT fabric hierarchy fabric_hierarchy.set_world_xform(...)) instead of touching USD attributes directly, which is significantly cheaper for rendering-only updates. It still has a Python loop but the per-iteration cost is much lower than a USD attribute set, and Hydra/RTX consumes the fabric data directly. Note: this writes world poses, so you’ll need to compose your local poses with the parent transform yourself.
Hi, We noticed that this topic hasn’t received any recent responses, so we are closing it for now to help keep the forum organized.
If you’re still experiencing this issue or have additional questions, please feel free to create a new topic with updated details. When doing so, we recommend mentioning or linking to this original topic in your new post—this helps provide context and makes it easier for others to assist you.
Thank you for being part of the NVIDIA Isaac Sim community.