"""Isolated pusher diagnostic: place one item right at the blade, sweep it, log velocity every step. Determines push (item picks up tangential speed) vs teleport (item barely moves, gets a depenetration nudge, stops) - probe_push_physics.py's own distinction. Reuses the CURRENTLY prepared stage (belts/plow/pusher/rails already configured by the last full run) rather than reopening. """ import sys REPO = "/home/dasha/robozon-sorter" if REPO not in sys.path: sys.path.insert(0, REPO) for _m in [k for k in list(sys.modules) if k.startswith("robozon_sorter")]: del sys.modules[_m] import importlib importlib.invalidate_caches() import omni.usd, omni.timeline from pxr import Gf, UsdGeom, UsdPhysics, PhysxSchema import isaacsim.core.experimental.utils.app as app_utils from isaacsim.core.experimental.prims import RigidPrim from robozon_sorter import config as C from robozon_sorter.sim import scene as _scene stage = omni.usd.get_context().get_stage() tl = omni.timeline.get_timeline_interface() if tl.is_playing(): tl.stop() await app_utils.update_app_async(steps=10) print("=== blade geometry now ===") geom = stage.GetPrimAtPath("/World/Diverters/DiverterY_Split/Pusher/Geom") bbc = UsdGeom.BBoxCache(0, ["default", "render"]) r = bbc.ComputeWorldBound(geom).ComputeAlignedRange() print(f" blade bbox x[{r.GetMin()[0]:+.3f}..{r.GetMax()[0]:+.3f}] " f"y[{r.GetMin()[1]:+.3f}..{r.GetMax()[1]:+.3f}] z[{r.GetMin()[2]:+.3f}..{r.GetMax()[2]:+.3f}]") print(f" BLADE_HOME_Y={C.BLADE_HOME_Y} BLADE_OUT_Y={C.BLADE_OUT_Y} PUSH_X={C.PUSH_X} BELT_Z={C.BELT_Z}") blade_prim = stage.GetPrimAtPath(_scene.BLADE) print(" blade kinematic:", UsdPhysics.RigidBodyAPI(blade_prim).GetKinematicEnabledAttr().Get()) print(" blade collision enabled (self):", blade_prim.GetAttribute("physics:collisionEnabled").Get()) for c in blade_prim.GetChildren(): print(" child", c.GetPath(), "collisionEnabled:", c.GetAttribute("physics:collisionEnabled").Get()) # reset blade to home def blade_op(): for op in UsdGeom.Xformable(blade_prim).GetOrderedXformOps(): if op.GetOpType() == UsdGeom.XformOp.TypeTranslate: return op blade_base = blade_op().Get() def blade_to(y): b = blade_base blade_op().Set(Gf.Vec3d(b[0], y - _scene.BLADE_PARENT_Y, b[2])) blade_to(C.BLADE_HOME_Y) # place a fresh item just upstream of the blade, in its path name = "probe_item" items_dir = C.ROOT / "assets" / "items" prim = UsdGeom.Xform.Define(stage, f"/World/Items/{name}").GetPrim() prim.GetReferences().ClearReferences() prim.GetReferences().AddReference(str(items_dir / "box_300x200x200.usd")) xf = UsdGeom.Xformable(prim) xf.ClearXformOpOrder() xf.AddTranslateOp(precision=UsdGeom.XformOp.PrecisionDouble).Set(Gf.Vec3d(C.PUSH_X + 0.05, 0.0, C.BELT_Z + 0.10)) UsdPhysics.RigidBodyAPI.Apply(prim) UsdPhysics.RigidBodyAPI(prim).CreateKinematicEnabledAttr().Set(False) UsdPhysics.MassAPI.Apply(prim).CreateMassAttr().Set(0.6) px = PhysxSchema.PhysxRigidBodyAPI.Apply(prim) px.CreateEnableCCDAttr().Set(True) px.CreateSolverPositionIterationCountAttr().Set(24) px.CreateSleepThresholdAttr().Set(0.0) UsdGeom.Imageable(prim).MakeVisible() rp = RigidPrim(paths=[f"/World/Items/{name}"]) tl.play() await app_utils.update_app_async(steps=40) p0 = rp.get_world_poses()[0].numpy()[0] print(f"\n--- settled at x={p0[0]:+.3f} y={p0[1]:+.3f} z={p0[2]:+.3f} ---") print("\n--- sweeping blade out at PUSHER_MAX_SAFE, logging item state ---") speed = C.PUSHER_MAX_SAFE a, b = C.BLADE_HOME_Y, C.BLADE_OUT_Y duration = abs(b - a) / speed t0 = float(tl.get_current_time()) i = 0 print(f"{'i':>3} {'t':>6} {'blade_y':>8} {'item_x':>8} {'item_y':>8} {'item_z':>8} {'vx':>7} {'vy':>7}") while True: u = min(1.0, (float(tl.get_current_time()) - t0) / duration) blade_to(a + (b - a) * u) await app_utils.update_app_async(steps=1) p = rp.get_world_poses()[0].numpy()[0] v = rp.get_velocities()[0].numpy()[0] if i % 3 == 0 or u >= 1.0: print(f"{i:3d} {float(tl.get_current_time())-t0:6.3f} {a+(b-a)*u:8.3f} " f"{p[0]:8.3f} {p[1]:8.3f} {p[2]:8.3f} {v[0]:7.3f} {v[1]:7.3f}") i += 1 if u >= 1.0: break p_final = rp.get_world_poses()[0].numpy()[0] print(f"\n--- after stroke: x={p_final[0]:+.3f} y={p_final[1]:+.3f} (started y={p0[1]:+.3f}, moved {p_final[1]-p0[1]:+.3f}) ---") tl.stop()