Recording object movements and forces using Python script

Hello,
I would like to record the positions of objects and also the forces acting on these objects. I am planning on using Matplotlib to visualize the recorded data.

To determine the object positions, I have written a small script:

import time

from pxr import Usd, UsdGeom, UsdPhysics, UsdShade, Sdf, Gf, Tf
from omni.physx.scripts.physicsUtils import *

gripperPath = ‘/World/o_ring_montage_asm_v4/MeshInstance_3’
gripperPrim = stage.GetPrimAtPath(gripperPath)

recording movement data for 30 seconds

start_time = time.time()
t = 0.0
while t < 30:
print(get_translation(gripperPrim))
time.sleep(0.1)
t = time.time() - start_time

However, as long as the script is executed in the script editor, the simulation freezes.

Since I am quite new to Omniverse, I am not sure which approach is suited to record such data.

Would it be best to write an extension for this?

I would also appreciate any tips on how to read out forces that are acting on Objects in Omniverse.

Many thanks in advance!

Hi,
yes you would have to create an extension here, you need to gather the data over time while allowing the application to step.
So in the extension you would have to register to the application update loop like this:
self._update_sub = omni.kit.app.get_app().get_update_event_stream().create_subscription_to_pop(
self._on_update, name=“my update”
)

Then in the update you can query the actual transformation for the given prim. However you can query only current position and velocity, you cant query the forces. If thats an articulation you can add articulation sensor to the rigid body and the articulation sensor would get you the forces. But for rigid bodies that do not belong to an articulation you wont get the forces.

1 Like

Thanks for the tip! Then I will write an extension for it.

Hi Ales,

thanks again for the tip.
I have experimented a bit with extensions and most of it works fine.

However, there are two things that are not clear to me:

First, how do I load external python packages, like matplotlib?
The documentation mentions that omni.kit.pipapi can be used to install pip packages in the extension, but not how to do it. I found an example in another extension were numpy is installed, but that doesn’t work for other packages, like matplotlib (see code for the .toml file below).

Secondly, how do I trigger code to run when the simulation starts and when it ends? “def on_startup(self, ext_id):” is triggered when the extension loads and “def on_shutdown(self):” is triggered when the extension closes. Are there equivalents to this that are triggered when the simulation starts and when it ends?

Many thanks in advance!

Hi Axel,
For the second part of the question, you can use something like this:

        # simulation events callback
        def on_simulation_event(event):
            if event.type == int(SimulationEvent.RESUMED):
                self._physx_simulation_started = True

            if event.type == int(SimulationEvent.PAUSED):

            if event.type == int(SimulationEvent.STOPPED):
                self._physx_simulation_started = False

        events = get_physx_interface().get_simulation_event_stream_v2()
        self._subs.append(events.create_subscription_to_pop(on_simulation_event))

For the first issue, I think the problem might be syntax, I think for multiple packages, you should write it like this:

[python.pipapi]
requirements = ["psutil", "pyperclip"]

Can you please try it out?

Ales

1 Like

Hi Ales,

thank you very much for your answer!

Regarding the first issue, it actually was the syntax. Now everything works fine!

As for the second problem, I’m not sure what to do with the line “self._subs.append(events.create_subscription_to_pop(on_simulation_event))”. When I put it directly into the “def init” function, I get an error stating, that _subs is not defined. Is “_subs” meant to be a list, containing all the functions that should get executed each update?

My code is below:
Subscribing to updates generally works fine. I have tested two different versions. The first one was the one you suggested (highlighted in blue). With this solution, I get an update on every step (probably on every new frame), regardless of whether the simulation is running or not.

With the second solution (highlighted in red), I get an update at every simulation step, so only while the simulation is running. But this remains active, even after the extension is deactivated.

Here is the actual python file:

test.py (1.9 KB)

Ah yes, because I send you a code that stores these in an array, you can just store the regular subscription:
events = get_physx_interface().get_simulation_event_stream_v2()
self._simulation_event_sub = events.create_subscription_to_pop(self._on_simulation_event)

Yes, you can subscribe to the step event too, this is called after each simulation step (there can be more steps per frame). So it really depends how you need to react to physics stepping.

Thanks a lot, now everything works!

Python didn’t know what to do with “SimulationEvent.Resume” etc, but when the respective integers are directly inserted, everything works as expected.

For reference, here is the working code:

and the matching Python file:
test.py (1.9 KB)

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