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 *
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.
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?
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.
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.