Moving kinematic bodies every physx step

I have csv data of a real motion which I want to reproduce in omniverse with a kinematic rigidbody. The kinematic rigidbody shall interact/collide with other non-kinematic rigidbodies and particles.
My csv data has a very high temporal resolution of 5 microseconds and I want to reproduce the motion as accurately as possible. I thought about downsampling the data to 1 millisecond and running the physics simulation with 1000 steps per second as well.

Whenever I want to change the position attribute xformOp:translate via the attribute’s Set() method in the physics step, Omniverse freezes completely when I press play. I have to kill and re-launch the whole application.

   def on_init(self):
      self._physics_sub = physx.get_physx_interface().subscribe_physics_step_events(self.on_physics_update)

   def on_physics_update(self, delta_time):
      # I set the position attribute here.

I also tried to change a force value every physics step instead of position with the same result.

I tried working with AddTranslateOp() and setting all values once via translateOp.Set(time=_time, value=Vec3d(_x,_y,_z)). However it seems like these values are not set every physics step, but every frame or so even when tinkering with Metadata.TimeCodesPerSecond and such.

Thank you for your help!

Hi,
If you already have the data sampled I would recommend to indeed create an op with the sampled values, like you tried. This will read the values with every substep, did you marked the body as kinematic and are you sure the op is read right?
I mean if you just move with the timeline you should see the object to move (without pressing play).

How many objects do you need to move? With such a high simulation frequency its possible to achieve what you need, but using USD input/output would be quite an overkill. It could be possible to bypass this these days by using USDRT API. I could try to prepare a snippet for you for a try.

But I think using the timesampled values is a better solution then changing the values for kinematic bodies every frame. Since you just write once and then the interpolated value is read with every step.
Before each step omni.physx queries the new position based on current timeCode, which increases by each step size. The step size can be defined on a physics scene - num steps per second.

Thank you @AlesBorovicka for your support!

How many objects do you need to move?

I need to move 1 rigidbody only (a glass). It is filled with particles (water).

But I think using the timesampled values is a better solution then changing the values for kinematic bodies every frame.

I want to set the position exactly every physics step, not necessarily every frame. Whenever I want to set xformOp:translate during simulation - whether time-sampled, or interpolated, or the pure csv-data, my Omniverse App (Create & Isaac) freezes as soon as I press play.

It could be possible to bypass this these days by using USDRT API. I could try to prepare a snippet for you for a try.

I don’t know USDRT API. What is the difference? I am curious to give your sipplet a try.

Right, that was what I was thinking that before you start to simulate you would just feed in the data with your sampling rate.
What happens in omni.physx is that before each step I am asking for the value at the given time and the value is interpolated. So I am not getting the values every frame but every step, so this should work.

I don’t know USDRT API. What is the difference? I am curious to give your sipplet a try.

The difference is where the data live. Its really hard to tell what the problem is in your case, maybe you can send me some repro so that I can see why its deadlocking for you.
Anyway USDRT is API that is able to talk to both USD and Fabric/Flatcache data, that are designed for runtime but are not used by default.
You can enable omni.physx.flatcache extension that would output the simulation data into Fabric (new name for Flatcache). You can try to enable it if you get better perf.
Now once the data are in Fabric those are pretty much invisible to all UI, python etc.
So one can use USDRT API to access these data.
You would have to enable USDRT SCENEGRAPH API extension. Then you can play with it, for example create a Cube and try to move it through the API:

import usdrt
stage = usdrt.Usd.Stage.Attach(omni.usd.get_context().get_stage_id())

prim = stage.GetPrimAtPath("/World/Cube")

prim_pos_attr = prim.CreateAttribute("_worldPosition", usdrt.Sdf.ValueTypeNames.Double3, True)

prim_pos_attr.Set(usdrt.Gf.Vec3d(500.0, 0, 0))

pos = prim_pos_attr.Get()

print("pos: " + str(pos))

Documentation can be found:
http://omniverse-docs.s3-website-us-east-1.amazonaws.com/usdrt/4.0.5/docs/scenegraph_use.html

The move you do should be picked up by physics so you can do this move with every step, just make sure that ideally that glass object is a kinematic object.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.