How can I raise the frame rate of physics simulations?

I want to run physics simulations with rigid or deformed objects at high speed.
Ideally, we would like to run physics simulations at 1000 fps (time step = 0.001s).
To achieve this, we need only minimal graphic settings such as ray tracing.
A rendering fps of about 60 fps is also sufficient.
I would like to know the settings related to the fps of the physics simulation and how to speed up the simulation.

Hi,
yes its possible to set the simulation frame rate, on the PhysicsScene you can set the Time Steps Per Second, this defines the fixed timestep for physics simulation. The simulation will to substepping with the given timestep on the Physics Scene:

To speedup the rigid body simulation, most of the time is usually spend in updating back the USD, you can enable omni.physx.flatcache extension to skip USD writes and write to Fabric, that will avoid the heavy writes.

The inverse of the time difference between frames was output to display pseudo fps, but the value displayed was different from the “Time Steps Per Second” setting.

Those are two different things, this is the time passed by Create update loop to physics, physics will then step with the given Time Step Per Seconds and do substepping if needed.

Sorry, I don’t understand much.
Is the time step at which the function described in the update loop in the script is executed different from the time step set in Time Step Per Second?
If the force function is used every frame, the update loop must be fast or the stability of the simulation may be unstable.

Yes, what you are printing is the Create main update loop time - this matches the FPS you see on the screeen, this is the UI /main thread update loop. This update loop asks physics to update with the given time (that you are printing), however physics will do substepping based on the Time Step Per Seconds, so physics wont do one step with this time, it will do a step with the size of the 1/Time Steps Per Second and will do substeps to match the time given.

If you need to apply the force before each step, its also possible to register to receive notification about each individual physics step.

I understood what was happening.
Perhaps what I want to know most is how to speed up the Create main update loop time. If possible, please tell me how to do it.

I would like to know more about this as well.

Lets start with the step callback:

        self._stepping_sub = get_physx_interface().subscribe_physics_step_events(self._on_physics_step)

       def _on_physics_step(self, dt):
            pass

This way you get a callback for each step done by physics simulation so that you can apply forces with a higher frequency matching the physics stepping.

Now to speedup the update loop, I am still a bit unsure what you are tying to achieve. If the update loop has to run and the rendering has to run you most likely wont get more then 100fps.
As mentioned you can enable omni.physx.flatcache extension, that would bypass USD writes and speed up significantly the write of the physics results for rendering.
So basically if you need the output to be rendered, then you can only increase the Time steps per second to let simulation run at a higher frequency, but still this time will be part of the main update loop.

Another possibility how to improve perf is to use async simulation, on a physics scene in advanced section you can enable asynchronous simulation. Now this is quite advanced setting because, simulation will run in a different order, once update is called for physics it would wait for previous simulation, update render, fire new simulation.
If you need to only update the forces through the separate API and dont touch USD then you could use the on_step callback to do that. But you cant write to USD from that callback.

Another thing, if you simulate with a high frequency and low number of objects, you can also try to change the simulation to run on CPU (Enable GPU dynamics) and change the number of threads to 0 (physics preferences). Running simulation on GPU (default) is targeted for larger scenes and does have some general overhead for launching the kernels.

It really depends on your scene, but if you manage to get just rendering to run around those 60fps, then for the simulation you also need to fit into that time (1/60)…

I didn’t explain enough about what I was trying to do.
I am trying to create a VR hand model using PhysX5.0 and FEM and do haptics related research.
First of all, I aim to read the position and pose of the hand using a tracking device, and connect it to the VR hand model with a spring to manipulate virtual objects.
In such a study, the visual rendering fps does not need to match the fps of the physical simulation, but the fps of the physical simulation needs to be as fast as possible to ensure accurate object-to-object interference detection.

The callback functions you presented seemed to be just what I needed.
However, I have been able to increase the Time Step Per Second to about 200 using the _on_physics_step function, but it does not work well beyond that.
In Unity, which also uses PhysX, I was able to run the loop at 1000 fps.
Also, when I enable omni.physx.flatcache extension, what I am trying to do does not work…

The left and right objects are connected by springs and are damping.
The right object is the rigidbody, and the force is applied so that it overlaps the left object.

Sorry for asking so many rudimentary questions…

However, I have been able to increase the Time Step Per Second to about 200 using the _on_physics_step function, but it does not work well beyond that.

Can you elaborate more what the problem is?

Also, when I enable omni.physx.flatcache extension, what I am trying to do does not work…

When you enable this extension, you cant anymore read from USD any positions, so if you in your code somewhere try to read the position of the body, it wont work. The data are not in USD anymore, for rigid bodies there is an API to get directly data from PhysX.

get_physx_interface().get_rigidbody_transformation(boxPathName)

Not sure if thats the problem, I but I suspect it is. This will give you world position of the rigid body on that path.

Now back to simulating at some given frequency. If you set the Time steps per second on a scene that will define the simulation step and the frequency for simulation. However this could lead to massive slowdown for the UI thread, so there is a safety in the Physics settings (window->simulation->physics settings) you have also Min Frame Rate. So this defines if some frames starts to be dropped. So if you want to make sure you get simulated exactly at your given Time Steps Per second set this please to 1.

Now to get some perf:

  1. Try to enable omni.physx.flatcache extension make sure your code works with that, read positions from physx interface, apply forces.
  2. For this kind of frequency you probably should not simulate on GPU as there will be a large latency in Create, on a PhysicsScene - disable GPU dynamics
  3. You might get some speedup if you run with 0 threads, in Edit->Preferences->Physics try to set the num worker threads to 0
  4. Check profiler where the time goes, enable extensions profiler window and tracy profiler. Press F5 then again F5, it should display a profile view in tracy

Hope some of the tips help. Though I am not quite sure that you can get desired perf using just python, since the python bindings are not for free and probably will cost a lot. Controlling this from C++ would give you better results and you would be able to skip USD completely, but that will be possible in next release. I am not sure if you can build C++ extensions with current release.