diff --git a/newton/examples/assets/envs/ant_env.usda b/newton/examples/assets/envs/ant_env.usda new file mode 100644 index 0000000000..67f95defad --- /dev/null +++ b/newton/examples/assets/envs/ant_env.usda @@ -0,0 +1,1552 @@ +#usda 1.0 +( + customLayerData = { + dictionary cameraSettings = { + dictionary Front = { + double3 position = (50000.913137040225, -1.1102433003404901e-11, 0) + double radius = 500 + } + dictionary Perspective = { + double3 position = (5, 4.9999999999999964, 5.000000000000003) + double3 target = (0.06346260919888191, -0.1401416183386308, 0.07968062669460174) + } + dictionary Right = { + double3 position = (0, -50000.91313708642, -1.1102433003415162e-11) + double radius = 500 + } + dictionary Top = { + double3 position = (0, 0, 50000.25) + double radius = 500 + } + string boundCamera = "/OmniverseKit_Persp" + } + dictionary omni_layer = { + string authoring_layer = "./ant_prototype.usda" + dictionary locked = { + } + dictionary muteness = { + } + } + dictionary renderSettings = { + double "rtx:post:lensDistortion:cameraFocalLength" = 18.14756202697754 + } + } + doc = """Generated from Composed Stage of root layer https://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Isaac/4.5/Isaac/Robots/Ant/ant_instanceable.usd + + +Generated from Composed Stage of root layer /home/horde/Desktop/flattened_ant.usd +""" + endTimeCode = 0 + metersPerUnit = 1 + startTimeCode = -1 + timeCodesPerSecond = 60 + upAxis = "Z" +) + +over "Flattened_Prototype_19" +{ + def Capsule "right_leg_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_20" +{ + def Capsule "back_leg_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_21" +{ + def Capsule "fourth_ankle_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.20000000298023224, -0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_22" +{ + def Capsule "rightback_leg_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_23" +{ + def Sphere "torso_geom" + { + float3[] extent = [(-0.25, -0.25, -0.25), (0.25, 0.25, 0.25)] + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.25 + matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_1_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_2_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_3_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_4_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_24" +{ + def Capsule "left_leg_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_25" +{ + def Capsule "back_leg_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_26" +{ + def Capsule "rightback_leg_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_27" +{ + def Sphere "torso_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + float3[] extent = [(-0.25, -0.25, -0.25), (0.25, 0.25, 0.25)] + uniform token physics:approximation = "boundingSphere" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.25 + matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_1_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_2_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_3_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_4_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_28" +{ + def Capsule "third_ankle_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.20000000298023224, -0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_29" +{ + def Capsule "fourth_ankle_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.20000000298023224, -0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_30" +{ + def Capsule "right_ankle_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.20000000298023224, 0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_31" +{ + def Capsule "left_ankle_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.20000000298023224, 0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_32" +{ + def Capsule "left_leg_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_33" +{ + def Capsule "third_ankle_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.20000000298023224, -0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_34" +{ + def Capsule "left_ankle_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.20000000298023224, 0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_35" +{ + def Capsule "right_leg_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_36" +{ + def Capsule "right_ankle_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.20000000298023224, 0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_1" +{ + def Capsule "left_ankle_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.20000000298023224, 0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_2" +{ + def Capsule "left_leg_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_3" +{ + def Capsule "right_leg_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_4" +{ + def Capsule "back_leg_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_5" +{ + def Sphere "torso_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + float3[] extent = [(-0.25, -0.25, -0.25), (0.25, 0.25, 0.25)] + uniform token physics:approximation = "boundingSphere" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.25 + matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_1_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_2_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_3_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_4_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_6" +{ + def Capsule "left_leg_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_7" +{ + def Capsule "back_leg_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_8" +{ + def Capsule "third_ankle_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.20000000298023224, -0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_9" +{ + def Capsule "fourth_ankle_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.20000000298023224, -0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_10" +{ + def Capsule "right_ankle_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.20000000298023224, 0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_11" +{ + def Sphere "torso_geom" + { + float3[] extent = [(-0.25, -0.25, -0.25), (0.25, 0.25, 0.25)] + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.25 + matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_1_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_2_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_3_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } + + def Capsule "aux_4_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_12" +{ + def Capsule "left_ankle_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, 0.7071068030891894, 0, 0), (-0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.20000000298023224, 0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_13" +{ + def Capsule "rightback_leg_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_14" +{ + def Capsule "right_ankle_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.20000000298023224, 0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_15" +{ + def Capsule "fourth_ankle_geom" ( + apiSchemas = ["PhysicsCollisionAPI", "PhysicsMeshCollisionAPI"] + ) + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + uniform token physics:approximation = "convexHull" + float physxCollision:contactOffset = 0.02 + float physxCollision:restOffset = 0 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + uniform token purpose = "guide" + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.20000000298023224, -0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_16" +{ + def Capsule "right_leg_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, 0.7071067480216797, 0, 0), (-0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.10000000149011612, 0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_17" +{ + def Capsule "rightback_leg_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.22142136, -0.08, -0.08), (0.22142136, 0.08, 0.08)] + double height = 0.2828427255153656 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (0.7071067450934194, -0.7071068030891894, 0, 0), (0.7071068030891894, 0.7071067450934194, 0, 0), (0, 0, 1, 0), (0.10000000149011612, -0.10000000149011612, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Flattened_Prototype_18" +{ + def Capsule "third_ankle_geom" + { + uniform token axis = "X" + float3[] extent = [(-0.36284274, -0.08, -0.08), (0.36284274, 0.08, 0.08)] + double height = 0.5656854510307312 + color3f[] primvars:displayColor = [(0.97, 0.38, 0.06)] + double radius = 0.07999999821186066 + matrix4d xformOp:transform = ( (-0.7071066765757053, -0.7071067480216797, 0, 0), (0.7071067480216797, -0.7071066765757053, 0, 0), (0, 0, 1, 0), (-0.20000000298023224, -0.20000000298023224, 0, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] + } +} + +over "Render" ( + hide_in_stage_window = true +) +{ +} + +def Xform "World" +{ + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def Xform "envs" + { + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def Xform "env_0" + { + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def Xform "Robot" ( + apiSchemas = None + ) + { + float3 xformOp:rotateXYZ = (0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 1) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"] + + def Xform "torso" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI", "PhysicsArticulationRootAPI", "PhysxArticulationAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + + def Xform "front_left_leg" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + float3 xformOp:translate = (0.19999999, 0.2, 7.450581e-9) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + + def "joints" + { + def PhysicsRevoluteJoint "front_left_leg" ( + apiSchemas = ["PhysxLimitAPI:angular", "PhysxJointAPI"] + ) + { + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (0.2, 0.2, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.7071068, 0, -0.7071068, 0) + quatf physics:localRot1 = (0.7071068, 0, -0.7071068, 0) + float physics:lowerLimit = -40 + float physics:upperLimit = 40 + float physxJoint:armature = 0.01 + float physxLimit:angular:damping = 0.1 ( + allowedTokens = [] + ) + } + + def PhysicsRevoluteJoint "front_left_foot" ( + apiSchemas = ["PhysxLimitAPI:angular", "PhysxJointAPI"] + ) + { + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (0.2, 0.2, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.38268334, 0, 0, 0.9238796) + quatf physics:localRot1 = (0.38268334, 0, 0, 0.9238796) + float physics:lowerLimit = 30 + float physics:upperLimit = 100 + float physxJoint:armature = 0.01 + float physxLimit:angular:damping = 0.1 ( + allowedTokens = [] + ) + } + + def PhysicsRevoluteJoint "front_right_leg" ( + apiSchemas = ["PhysxLimitAPI:angular", "PhysxJointAPI"] + ) + { + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (-0.2, 0.2, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.7071068, 0, -0.7071068, 0) + quatf physics:localRot1 = (0.7071068, 0, -0.7071068, 0) + float physics:lowerLimit = -40 + float physics:upperLimit = 40 + float physxJoint:armature = 0.01 + float physxLimit:angular:damping = 0.1 ( + allowedTokens = [] + ) + } + + def PhysicsRevoluteJoint "front_right_foot" ( + apiSchemas = ["PhysxLimitAPI:angular", "PhysxJointAPI"] + ) + { + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (-0.2, 0.2, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.92387956, 0, 0, 0.38268346) + quatf physics:localRot1 = (0.92387956, 0, 0, 0.38268346) + float physics:lowerLimit = -100 + float physics:upperLimit = -30 + float physxJoint:armature = 0.01 + float physxLimit:angular:damping = 0.1 ( + allowedTokens = [] + ) + } + + def PhysicsRevoluteJoint "left_back_leg" ( + apiSchemas = ["PhysxLimitAPI:angular", "PhysxJointAPI"] + ) + { + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (-0.2, -0.2, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.7071068, 0, -0.7071068, 0) + quatf physics:localRot1 = (0.7071068, 0, -0.7071068, 0) + float physics:lowerLimit = -40 + float physics:upperLimit = 40 + float physxJoint:armature = 0.01 + float physxLimit:angular:damping = 0.1 ( + allowedTokens = [] + ) + } + + def PhysicsRevoluteJoint "left_back_foot" ( + apiSchemas = ["PhysxLimitAPI:angular", "PhysxJointAPI"] + ) + { + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (-0.2, -0.2, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.38268334, 0, 0, 0.9238796) + quatf physics:localRot1 = (0.38268334, 0, 0, 0.9238796) + float physics:lowerLimit = -100 + float physics:upperLimit = -30 + float physxJoint:armature = 0.01 + float physxLimit:angular:damping = 0.1 ( + allowedTokens = [] + ) + } + + def PhysicsRevoluteJoint "right_back_leg" ( + apiSchemas = ["PhysxLimitAPI:angular", "PhysxJointAPI"] + ) + { + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (0.2, -0.2, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.7071068, 0, -0.7071068, 0) + quatf physics:localRot1 = (0.7071068, 0, -0.7071068, 0) + float physics:lowerLimit = -40 + float physics:upperLimit = 40 + float physxJoint:armature = 0.01 + float physxLimit:angular:damping = 0.1 ( + allowedTokens = [] + ) + } + + def PhysicsRevoluteJoint "right_back_foot" ( + apiSchemas = ["PhysxLimitAPI:angular", "PhysxJointAPI"] + ) + { + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (0.2, -0.2, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.92387956, 0, 0, 0.38268346) + quatf physics:localRot1 = (0.92387956, 0, 0, 0.38268346) + float physics:lowerLimit = 30 + float physics:upperLimit = 100 + float physxJoint:armature = 0.01 + float physxLimit:angular:damping = 0.1 ( + allowedTokens = [] + ) + } + } + + def Xform "front_left_foot" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI", "PhysxArticulationForceSensorAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + float3 xformOp:translate = (0.39999995, 0.39999998, 4.4703484e-8) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + + def Xform "front_right_leg" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + float3 xformOp:translate = (-0.20000002, 0.20000002, 1.4901161e-8) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + + def Xform "front_right_foot" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI", "PhysxArticulationForceSensorAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + float3 xformOp:translate = (-0.39999998, 0.39999998, -4.4703484e-8) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + + def Xform "left_back_leg" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + float3 xformOp:translate = (-0.20000002, -0.20000002, 1.4901161e-8) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + + def Xform "left_back_foot" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI", "PhysxArticulationForceSensorAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + float3 xformOp:translate = (-0.39999998, -0.39999998, -4.4703484e-8) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + + def Xform "right_back_leg" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + float3 xformOp:translate = (0.19999999, -0.2, 7.450581e-9) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + + def Xform "right_back_foot" ( + apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsMassAPI", "PhysxArticulationForceSensorAPI"] + ) + { + vector3f physics:angularVelocity = (0, 0, 0) + float physics:density = 5 + vector3f physics:velocity = (0, 0, 0) + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + float3 xformOp:translate = (0.39999995, -0.39999998, 4.4703484e-8) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def "visuals" ( + instanceable = true + add references = + ) + { + } + } + } + } + } + + def Xform "ground" ( + kind = "component" + ) + { + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate"] + + def Scope "Looks" ( + kind = "" + ) + { + def Material "theGrid" + { + token outputs:mdl:displacement.connect = + token outputs:mdl:surface.connect = + token outputs:mdl:volume.connect = + + def Shader "Shader" + { + uniform token info:implementationSource = "sourceAsset" + uniform asset info:mdl:sourceAsset = @OmniPBR.mdl@ + uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR" + float inputs:albedo_add = 0 ( + customData = { + float default = 0 + dictionary soft_range = { + float max = 1 + float min = -1 + } + } + displayGroup = "Albedo" + displayName = "Albedo Add" + doc = "Adds a constant value to the diffuse color " + hidden = false + ) + color3f inputs:diffuse_color_constant = (0.2, 0.2, 0.2) ( + customData = { + float3 default = (0.2, 0.2, 0.2) + } + displayGroup = "Albedo" + displayName = "Albedo Color" + doc = "This is the albedo base color" + hidden = false + renderType = "color" + ) + asset inputs:diffuse_texture = @https://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Isaac/4.5/Isaac/Environments/Grid/Materials/Textures/Wireframe_blue.png@ ( + colorSpace = "auto" + customData = { + asset default = @@ + } + displayGroup = "Albedo" + displayName = "Albedo Map" + hidden = false + renderType = "texture_2d" + ) + color3f inputs:diffuse_tint = (1, 1, 1) ( + customData = { + float3 default = (1, 1, 1) + } + displayGroup = "Albedo" + displayName = "Color Tint" + doc = "When enabled, this color value is multiplied over the final albedo color" + hidden = false + renderType = "color" + ) + color3f inputs:emissive_color = (1, 1, 1) ( + customData = { + float3 default = (1, 0.1, 0.1) + } + displayGroup = "Emissive" + displayName = "Emissive Color" + doc = "The emission color" + hidden = false + renderType = "color" + ) + asset inputs:emissive_color_texture = @https://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Isaac/4.5/Isaac/Environments/Grid/Materials/Textures/WireframeBlur_basecolor.png@ ( + colorSpace = "auto" + customData = { + asset default = @@ + } + displayGroup = "Emissive" + displayName = "Emissive Color map" + doc = "The emissive color texture" + hidden = false + renderType = "texture_2d" + ) + float inputs:emissive_intensity = 1000 ( + customData = { + float default = 40 + } + displayGroup = "Emissive" + displayName = "Emissive Intensity" + doc = "Intensity of the emission" + hidden = false + ) + asset inputs:emissive_mask_texture = @https://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Isaac/4.5/Isaac/Environments/Grid/Materials/Textures/WireframeBlur_blue.png@ ( + colorSpace = "sRGB" + customData = { + asset default = @@ + } + displayGroup = "Emissive" + displayName = "Emissive Mask map" + doc = "The texture masking the emissive color" + hidden = false + renderType = "texture_2d" + ) + bool inputs:enable_emission = 1 ( + customData = { + bool default = 0 + } + displayGroup = "Emissive" + displayName = "Enable Emission" + doc = "Enables the emission of light from the material" + hidden = false + ) + bool inputs:project_uvw = 1 ( + customData = { + bool default = 0 + } + displayGroup = "UV" + displayName = "Enable Project UVW Coordinates" + doc = "When enabled, UV coordinates will be generated by projecting them from a coordinate system" + hidden = false + ) + float inputs:specular_level = 0.5 ( + customData = { + float default = 0.5 + dictionary soft_range = { + float max = 1 + float min = 0 + } + } + displayGroup = "Reflectivity" + displayName = "Specular" + doc = "The specular level (intensity) of the material" + hidden = false + ) + bool inputs:world_or_object = 1 ( + customData = { + bool default = 0 + } + displayGroup = "UV" + displayName = "Enable World Space" + doc = "When enabled, uses world space for projection, otherwise object space is used" + hidden = false + ) + token outputs:out ( + renderType = "material" + ) + } + } + } + + def Xform "GroundPlane" + { + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def Plane "CollisionPlane" ( + apiSchemas = ["PhysicsCollisionAPI"] + ) + { + uniform token axis = "Z" + uniform token purpose = "guide" + float3 xformOp:scale = (0.01, 0.01, 0.01) + uniform token[] xformOpOrder = ["xformOp:scale"] + } + } + + def SphereLight "SphereLight" ( + apiSchemas = ["ShapingAPI"] + ) + { + float inputs:intensity = 100000 + float inputs:radius = 0.25 + float inputs:shaping:cone:angle = 180 + float intensity = 100000 + float radius = 0.25 + float shaping:cone:angle = 180 + float shaping:cone:softness + float shaping:focus + color3f shaping:focusTint + asset shaping:ies:file + token visibility = "inherited" + quatd xformOp:orient = (0.5000000000000001, 0.5, 0.49999999999999994, 0.5) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 2.5) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } + + def Xform "Environment" ( + apiSchemas = ["MaterialBindingAPI"] + ) + { + rel material:binding = ( + bindMaterialAs = "weakerThanDescendants" + ) + token visibility = "inherited" + float3 xformOp:rotateZYX = (0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateZYX", "xformOp:scale"] + + def Mesh "Geometry" ( + apiSchemas = ["MaterialBindingAPI"] + ) + { + float3[] extent = [(-0.5, -0.5, 0), (0.5, 0.5, 0)] + int[] faceVertexCounts = [4] + int[] faceVertexIndices = [0, 1, 3, 2] + normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)] ( + interpolation = "faceVarying" + ) + point3f[] points = [(-0.5, -0.5, 0), (0.5, -0.5, 0), (-0.5, 0.5, 0), (0.5, 0.5, 0)] + texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1)] ( + interpolation = "faceVarying" + ) + uniform token subdivisionScheme = "none" + token visibility = "inherited" + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (100, 100, 1) + double3 xformOp:translate = (-0.425, 0.425, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } + } + } +} + diff --git a/newton/examples/assets/envs/anymal.usd b/newton/examples/assets/envs/anymal.usd new file mode 100644 index 0000000000..77ef283fac Binary files /dev/null and b/newton/examples/assets/envs/anymal.usd differ diff --git a/newton/examples/assets/envs/cartpole_env.usda b/newton/examples/assets/envs/cartpole_env.usda new file mode 100644 index 0000000000..4aa950a24b --- /dev/null +++ b/newton/examples/assets/envs/cartpole_env.usda @@ -0,0 +1,884 @@ +#usda 1.0 +( + customLayerData = { + dictionary omni_layer = { + dictionary locked = { + } + dictionary muteness = { + } + } + dictionary renderSettings = { + } + } + doc = """Generated from Composed Stage of root layer /work/src/newton/cartpole_prototype.usd +""" + endTimeCode = 100 + metersPerUnit = 1 + renderSettingsPrimPath = "/Render/OmniverseGlobalRenderSettings" + startTimeCode = 0 + timeCodesPerSecond = 60 + upAxis = "Z" +) + +over "Flattened_Prototype_1" +{ + def Cube "mesh_0" ( + apiSchemas = ["MaterialBindingAPI"] + ) + { + float3[] extent = [(-0.02, -0.03, -0.5), (0.02, 0.03, 0.5)] + rel material:binding = ( + bindMaterialAs = "weakerThanDescendants" + ) + double size = 1 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (0.03999999910593033, 0.05999999865889549, 1) + double3 xformOp:translate = (0, 0, 0.4699999988079071) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } + + def Scope "Looks" + { + def Material "material" + { + token outputs:mdl:displacement.connect = + token outputs:mdl:surface.connect = + token outputs:mdl:volume.connect = + + def Shader "Shader" + { + uniform token info:implementationSource = "sourceAsset" + uniform asset info:mdl:sourceAsset = @OmniPBR.mdl@ + uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR" + color3f inputs:diffuse_color_constant = (0.5232067, 0.52320147, 0.52320147) ( + customData = { + float3 default = (0.2, 0.2, 0.2) + } + displayGroup = "Albedo" + displayName = "Albedo Color" + doc = """This is the albedo base color + +""" + hidden = false + renderType = "color" + ) + color3f inputs:diffuse_tint = (0.12, 0.14, 0.29999998) ( + customData = { + float3 default = (1, 1, 1) + } + displayGroup = "Albedo" + displayName = "Color Tint" + doc = """When enabled, this color value is multiplied over the final albedo color + +""" + hidden = false + renderType = "color" + ) + token outputs:out ( + renderType = "material" + ) + } + } + } +} + +over "Flattened_Prototype_2" +{ + def Cube "mesh_0" ( + apiSchemas = ["PhysicsCollisionAPI"] + ) + { + float3[] extent = [(-0.015, -4, -0.015), (0.015, 4, 0.015)] + uniform token purpose = "guide" + double size = 1 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (0.029999999329447746, 8, 0.029999999329447746) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } +} + +over "Flattened_Prototype_3" +{ + def Cube "mesh_0" ( + apiSchemas = ["PhysicsCollisionAPI"] + ) + { + float3[] extent = [(-0.02, -0.03, -0.5), (0.02, 0.03, 0.5)] + uniform token purpose = "guide" + double size = 1 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (0.03999999910593033, 0.05999999865889549, 1) + double3 xformOp:translate = (0, 0, 0.4699999988079071) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } +} + +over "Flattened_Prototype_4" +{ + def Cube "mesh_0" ( + apiSchemas = ["PhysicsCollisionAPI"] + ) + { + float3[] extent = [(-0.1, -0.125, -0.1), (0.1, 0.125, 0.1)] + uniform token purpose = "guide" + double size = 1 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (0.20000000298023224, 0.25, 0.20000000298023224) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } +} + +over "Flattened_Prototype_5" +{ + def Cube "mesh_0" ( + apiSchemas = ["MaterialBindingAPI"] + ) + { + float3[] extent = [(-0.015, -4, -0.015), (0.015, 4, 0.015)] + rel material:binding = ( + bindMaterialAs = "weakerThanDescendants" + ) + double size = 1 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (0.029999999329447746, 8, 0.029999999329447746) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } + + def Scope "Looks" + { + def Material "material" + { + token outputs:mdl:displacement.connect = + token outputs:mdl:surface.connect = + token outputs:mdl:volume.connect = + + def Shader "Shader" + { + uniform token info:implementationSource = "sourceAsset" + uniform asset info:mdl:sourceAsset = @OmniPBR.mdl@ + uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR" + color3f inputs:diffuse_color_constant = (1, 0.99999, 0.99999) ( + customData = { + float3 default = (0.2, 0.2, 0.2) + } + displayGroup = "Albedo" + displayName = "Albedo Color" + doc = """This is the albedo base color + +""" + hidden = false + renderType = "color" + ) + color3f inputs:diffuse_tint = (0.91999996, 0.59, 0.19999999) ( + customData = { + float3 default = (1, 1, 1) + } + displayGroup = "Albedo" + displayName = "Color Tint" + doc = """When enabled, this color value is multiplied over the final albedo color + +""" + hidden = false + renderType = "color" + ) + token outputs:out ( + renderType = "material" + ) + } + } + } +} + +over "Flattened_Prototype_6" +{ + def Cube "mesh_0" ( + apiSchemas = ["MaterialBindingAPI"] + ) + { + float3[] extent = [(-0.1, -0.125, -0.1), (0.1, 0.125, 0.1)] + rel material:binding = ( + bindMaterialAs = "weakerThanDescendants" + ) + double size = 1 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (0.20000000298023224, 0.25, 0.20000000298023224) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } + + def Scope "Looks" + { + def Material "material" + { + token outputs:mdl:displacement.connect = + token outputs:mdl:surface.connect = + token outputs:mdl:volume.connect = + + def Shader "Shader" + { + uniform token info:implementationSource = "sourceAsset" + uniform asset info:mdl:sourceAsset = @OmniPBR.mdl@ + uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR" + color3f inputs:diffuse_color_constant = (0.47679323, 0.47678846, 0.47678846) ( + customData = { + float3 default = (0.2, 0.2, 0.2) + } + displayGroup = "Albedo" + displayName = "Albedo Color" + doc = """This is the albedo base color + +""" + hidden = false + renderType = "color" + ) + color3f inputs:diffuse_tint = (0.35037118, 0.5060563, 0.6919831) ( + customData = { + float3 default = (1, 1, 1) + } + displayGroup = "Albedo" + displayName = "Color Tint" + doc = """When enabled, this color value is multiplied over the final albedo color + +""" + hidden = false + renderType = "color" + ) + token outputs:out ( + renderType = "material" + ) + } + } + } +} + +def PhysicsScene "physicsScene" ( + apiSchemas = ["PhysxSceneAPI", "MaterialBindingAPI"] +) +{ + rel material:binding:physics = ( + bindMaterialAs = "strongerThanDescendants" + ) + vector3f physics:gravityDirection = (0, 0, -1) + float physics:gravityMagnitude = 9.81 + float physxScene:bounceThreshold = 0.5 + uniform token physxScene:broadphaseType = "GPU" + bool physxScene:enableCCD = 0 + bool physxScene:enableEnhancedDeterminism = 0 + bool physxScene:enableGPUDynamics = 1 + bool physxScene:enableSceneQuerySupport = 0 + bool physxScene:enableStabilization = 1 + float physxScene:frictionCorrelationDistance = 0.025 + float physxScene:frictionOffsetThreshold = 0.04 + uint physxScene:gpuCollisionStackSize = 67108864 + uint physxScene:gpuFoundLostAggregatePairsCapacity = 33554432 + uint physxScene:gpuFoundLostPairsCapacity = 2097152 + uint physxScene:gpuHeapCapacity = 67108864 + uint physxScene:gpuMaxNumPartitions = 8 + uint physxScene:gpuMaxParticleContacts = 1048576 + uint physxScene:gpuMaxRigidContactCount = 8388608 + uint physxScene:gpuMaxRigidPatchCount = 163840 + uint physxScene:gpuMaxSoftBodyContacts = 1048576 + uint64 physxScene:gpuTempBufferCapacity = 16777216 + uint physxScene:gpuTotalAggregatePairsCapacity = 2097152 + uniform uint physxScene:maxPositionIterationCount = 255 + uniform uint physxScene:maxVelocityIterationCount = 255 + uniform uint physxScene:minPositionIterationCount = 1 + uniform uint physxScene:minVelocityIterationCount = 0 + uniform token physxScene:solverType = "TGS" + uint physxScene:timeStepsPerSecond = 120 + + def Material "defaultMaterial" ( + apiSchemas = ["PhysicsMaterialAPI", "PhysxMaterialAPI"] + ) + { + float physics:dynamicFriction = 0.5 + float physics:restitution = 0 + float physics:staticFriction = 0.5 + float physxMaterial:compliantContactDamping = 0 + float physxMaterial:compliantContactStiffness = 0 + uniform token physxMaterial:frictionCombineMode = "average" + uniform token physxMaterial:restitutionCombineMode = "average" + } +} + +def "World" +{ + def Scope "envs" + { + def Xform "env_0" + { + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def Xform "Robot" ( + apiSchemas = ["PhysicsArticulationRootAPI", "PhysxArticulationAPI"] + ) + { + bool physxArticulation:enabledSelfCollisions = 0 + float physxArticulation:sleepThreshold = 0.005 + int physxArticulation:solverPositionIterationCount = 4 + int physxArticulation:solverVelocityIterationCount = 0 + float physxArticulation:stabilizationThreshold = 0.001 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 2) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def Xform "slider" ( + apiSchemas = ["PhysxRigidBodyAPI", "PhysicsRigidBodyAPI", "PhysicsMassAPI"] + ) + { + bool physics:rigidBodyEnabled = 1 + bool physxRigidBody:enableGyroscopicForces = 1 + float physxRigidBody:maxAngularVelocity = 1000 + float physxRigidBody:maxDepenetrationVelocity = 100 + float physxRigidBody:maxLinearVelocity = 1000 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "visuals" ( + instanceable = true + add references = + ) + { + } + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def PhysicsPrismaticJoint "slider_to_cart" ( + apiSchemas = ["PhysxJointAPI", "PhysicsJointStateAPI:linear", "PhysicsDriveAPI:linear"] + ) + { + float drive:linear:physics:damping = 0 + float drive:linear:physics:maxForce = 1000 + float drive:linear:physics:stiffness = 0 + uniform token drive:linear:physics:type = "force" + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (0, 0, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (0.70710677, 0, 0, 0.70710677) + quatf physics:localRot1 = (0.70710677, 0, 0, 0.70710677) + float physics:lowerLimit = -4 + float physics:upperLimit = 4 + float physxJoint:jointFriction = 0 + float physxJoint:maxJointVelocity = 100 + } + } + + def PhysicsFixedJoint "root_joint" + { + rel physics:body1 = + } + + def Xform "cart" ( + apiSchemas = ["PhysxRigidBodyAPI", "PhysicsRigidBodyAPI", "PhysicsMassAPI"] + ) + { + float physics:mass = 1 + bool physics:rigidBodyEnabled = 1 + bool physxRigidBody:enableGyroscopicForces = 1 + float physxRigidBody:maxAngularVelocity = 1000 + float physxRigidBody:maxDepenetrationVelocity = 100 + float physxRigidBody:maxLinearVelocity = 1000 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "visuals" ( + instanceable = true + add references = + ) + { + } + + def "collisions" ( + instanceable = true + add references = + ) + { + } + + def PhysicsRevoluteJoint "cart_to_pole" ( + apiSchemas = ["PhysxJointAPI", "PhysicsJointStateAPI:angular", "PhysicsDriveAPI:angular"] + ) + { + float drive:angular:physics:damping = 0 + float drive:angular:physics:maxForce = 1000 + float drive:angular:physics:stiffness = 0 + uniform token drive:angular:physics:type = "force" + uniform token physics:axis = "X" + rel physics:body0 = + rel physics:body1 = + float physics:breakForce = 3.4028235e38 + float physics:breakTorque = 3.4028235e38 + point3f physics:localPos0 = (0.12, 0, 0) + point3f physics:localPos1 = (0, 0, 0) + quatf physics:localRot0 = (1, 0, 0, 0) + quatf physics:localRot1 = (1, 0, 0, 0) + float physxJoint:jointFriction = 0 + float physxJoint:maxJointVelocity = 458.36624 + } + } + + def Xform "pole" ( + apiSchemas = ["PhysxRigidBodyAPI", "PhysicsRigidBodyAPI", "PhysicsMassAPI"] + ) + { + point3f physics:centerOfMass = (0, 0, 0.47) + float physics:mass = 1 + bool physics:rigidBodyEnabled = 1 + bool physxRigidBody:enableGyroscopicForces = 1 + float physxRigidBody:maxAngularVelocity = 1000 + float physxRigidBody:maxDepenetrationVelocity = 100 + float physxRigidBody:maxLinearVelocity = 1000 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0.11999999731779099, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def "visuals" ( + instanceable = true + add references = + ) + { + } + + def "collisions" ( + instanceable = true + add references = + ) + { + } + } + } + } + } + + def Xform "ground" ( + kind = "component" + ) + { + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def Scope "Looks" ( + kind = "" + ) + { + def Material "theGrid" + { + token outputs:mdl:displacement.connect = + token outputs:mdl:surface.connect = + token outputs:mdl:volume.connect = + + def Shader "Shader" + { + uniform token info:implementationSource = "sourceAsset" + uniform asset info:mdl:sourceAsset = @OmniPBR.mdl@ + uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR" + float inputs:albedo_add = 0 ( + customData = { + float default = 0 + dictionary soft_range = { + float max = 1 + float min = -1 + } + } + displayGroup = "Albedo" + displayName = "Albedo Add" + doc = "Adds a constant value to the diffuse color " + hidden = false + ) + color3f inputs:diffuse_color_constant = (0.2, 0.2, 0.2) ( + customData = { + float3 default = (0.2, 0.2, 0.2) + } + displayGroup = "Albedo" + displayName = "Albedo Color" + doc = "This is the albedo base color" + hidden = false + renderType = "color" + ) + asset inputs:diffuse_texture = @http://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Isaac/4.5/Isaac/Environments/Grid/Materials/Textures/Wireframe_blue.png@ ( + colorSpace = "auto" + customData = { + asset default = @@ + } + displayGroup = "Albedo" + displayName = "Albedo Map" + hidden = false + renderType = "texture_2d" + ) + color3f inputs:diffuse_tint = (0, 0, 0) ( + customData = { + float3 default = (1, 1, 1) + } + displayGroup = "Albedo" + displayName = "Color Tint" + doc = "When enabled, this color value is multiplied over the final albedo color" + hidden = false + renderType = "color" + ) + color3f inputs:emissive_color = (1, 1, 1) ( + customData = { + float3 default = (1, 0.1, 0.1) + } + displayGroup = "Emissive" + displayName = "Emissive Color" + doc = "The emission color" + hidden = false + renderType = "color" + ) + asset inputs:emissive_color_texture = @http://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Isaac/4.5/Isaac/Environments/Grid/Materials/Textures/WireframeBlur_basecolor.png@ ( + colorSpace = "auto" + customData = { + asset default = @@ + } + displayGroup = "Emissive" + displayName = "Emissive Color map" + doc = "The emissive color texture" + hidden = false + renderType = "texture_2d" + ) + float inputs:emissive_intensity = 1000 ( + customData = { + float default = 40 + } + displayGroup = "Emissive" + displayName = "Emissive Intensity" + doc = "Intensity of the emission" + hidden = false + ) + asset inputs:emissive_mask_texture = @http://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Isaac/4.5/Isaac/Environments/Grid/Materials/Textures/WireframeBlur_blue.png@ ( + colorSpace = "sRGB" + customData = { + asset default = @@ + } + displayGroup = "Emissive" + displayName = "Emissive Mask map" + doc = "The texture masking the emissive color" + hidden = false + renderType = "texture_2d" + ) + bool inputs:enable_emission = 1 ( + customData = { + bool default = 0 + } + displayGroup = "Emissive" + displayName = "Enable Emission" + doc = "Enables the emission of light from the material" + hidden = false + ) + bool inputs:project_uvw = 1 ( + customData = { + bool default = 0 + } + displayGroup = "UV" + displayName = "Enable Project UVW Coordinates" + doc = "When enabled, UV coordinates will be generated by projecting them from a coordinate system" + hidden = false + ) + float inputs:specular_level = 0.5 ( + customData = { + float default = 0.5 + dictionary soft_range = { + float max = 1 + float min = 0 + } + } + displayGroup = "Reflectivity" + displayName = "Specular" + doc = "The specular level (intensity) of the material" + hidden = false + ) + bool inputs:world_or_object = 1 ( + customData = { + bool default = 0 + } + displayGroup = "UV" + displayName = "Enable World Space" + doc = "When enabled, uses world space for projection, otherwise object space is used" + hidden = false + ) + token outputs:out ( + renderType = "material" + ) + } + } + } + + def Xform "GroundPlane" + { + quatf xformOp:orient = (1, 0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + + def Plane "CollisionPlane" ( + apiSchemas = ["MaterialBindingAPI", "PhysicsCollisionAPI"] + ) + { + uniform token axis = "Z" + rel material:binding:physics = ( + bindMaterialAs = "strongerThanDescendants" + ) + uniform token purpose = "guide" + float3 xformOp:scale = (0.01, 0.01, 0.01) + uniform token[] xformOpOrder = ["xformOp:scale"] + } + } + + def SphereLight "SphereLight" ( + apiSchemas = ["ShapingAPI"] + ) + { + float inputs:intensity = 100000 + float inputs:radius = 0.25 + float inputs:shaping:cone:angle = 180 + float intensity = 100000 + float radius = 0.25 + float shaping:cone:angle = 180 + float shaping:cone:softness + float shaping:focus + color3f shaping:focusTint + asset shaping:ies:file + token visibility = "invisible" + quatd xformOp:orient = (0.5000000000000001, 0.5, 0.49999999999999994, 0.5) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 2.5) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } + + def Xform "Environment" ( + apiSchemas = ["MaterialBindingAPI"] + ) + { + rel material:binding = ( + bindMaterialAs = "weakerThanDescendants" + ) + token visibility = "inherited" + float3 xformOp:rotateZYX = (0, 0, 0) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateZYX", "xformOp:scale"] + + def Mesh "Geometry" ( + apiSchemas = ["MaterialBindingAPI"] + ) + { + float3[] extent = [(-0.5, -0.5, 0), (0.5, 0.5, 0)] + int[] faceVertexCounts = [4] + int[] faceVertexIndices = [0, 1, 3, 2] + normal3f[] normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1)] ( + interpolation = "faceVarying" + ) + point3f[] points = [(-0.5, -0.5, 0), (0.5, -0.5, 0), (-0.5, 0.5, 0), (0.5, 0.5, 0)] + texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1)] ( + interpolation = "faceVarying" + ) + uniform token subdivisionScheme = "none" + token visibility = "inherited" + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (100, 100, 1) + double3 xformOp:translate = (-0.425, 0.425, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } + } + + def Material "physicsMaterial" ( + apiSchemas = ["PhysicsMaterialAPI", "PhysxMaterialAPI"] + ) + { + float physics:dynamicFriction = 0.5 + float physics:restitution = 0 + float physics:staticFriction = 0.5 + float physxMaterial:compliantContactDamping = 0 + float physxMaterial:compliantContactStiffness = 0 + uniform token physxMaterial:frictionCombineMode = "average" + uniform token physxMaterial:restitutionCombineMode = "average" + } + } + + def DomeLight "Light" + { + color3f inputs:color = (0.75, 0.75, 0.75) + float inputs:colorTemperature = 6500 + bool inputs:enableColorTemperature = 0 + float inputs:exposure = 0 + float inputs:intensity = 2000 + bool inputs:normalize = 0 + asset inputs:texture:file + token inputs:texture:format = "automatic" + bool visibleInPrimaryRay = 1 + quatd xformOp:orient = (1, 0, 0, 0) + double3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:orient", "xformOp:scale"] + } +} + +def Camera "OmniverseKit_Persp" ( + customData = { + dictionary omni = { + dictionary kit = { + bool hide_in_stage_window = 1 + bool no_delete = 1 + } + } + } + hide_in_stage_window = true + kind = "component" + no_delete = true +) +{ + float2 clippingRange = (1, 10000000) + float focalLength = 18.147562 + float focusDistance = 400 + custom uniform vector3d omni:kit:centerOfInterest = (0, 0, -96.46236999354045) + float3 xformOp:rotateXYZ = (54.73561, -6.3611094e-15, 135) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (55.74297572387726, 55.69257572553425, 58.162574395058954) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"] +} + +def Camera "OmniverseKit_Front" ( + customData = { + dictionary omni = { + dictionary kit = { + bool hide_in_stage_window = 1 + bool no_delete = 1 + } + } + } + hide_in_stage_window = true + kind = "component" + no_delete = true +) +{ + float2 clippingRange = (1, 10000000) + float horizontalAperture = 5000 + custom uniform vector3d omni:kit:centerOfInterest = (0, 0, -500) + token projection = "orthographic" + float verticalAperture = 5000 + float3 xformOp:rotateXYZ = (90, -1.2722219e-14, 90) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (500, 0, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"] +} + +def Camera "OmniverseKit_Top" ( + customData = { + dictionary omni = { + dictionary kit = { + bool hide_in_stage_window = 1 + bool no_delete = 1 + } + } + } + hide_in_stage_window = true + kind = "component" + no_delete = true +) +{ + float2 clippingRange = (1, 10000000) + float horizontalAperture = 5000 + custom uniform vector3d omni:kit:centerOfInterest = (0, 0, -500) + token projection = "orthographic" + float verticalAperture = 5000 + float3 xformOp:rotateXYZ = (-1.2722219e-14, -7.016709e-15, -90) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, 0, 500) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"] +} + +def Camera "OmniverseKit_Right" ( + customData = { + dictionary omni = { + dictionary kit = { + bool hide_in_stage_window = 1 + bool no_delete = 1 + } + } + } + hide_in_stage_window = true + kind = "component" + no_delete = true +) +{ + float2 clippingRange = (1, 10000000) + float horizontalAperture = 5000 + custom uniform vector3d omni:kit:centerOfInterest = (0, 0, -500) + token projection = "orthographic" + float verticalAperture = 5000 + float3 xformOp:rotateXYZ = (90, -1.41245e-30, 1.2722219e-14) + float3 xformOp:scale = (1, 1, 1) + double3 xformOp:translate = (0, -500, 0) + uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"] +} + +def "Render" ( + hide_in_stage_window = true + no_delete = true +) +{ + def "OmniverseKit" + { + def "HydraTextures" ( + hide_in_stage_window = true + no_delete = true + ) + { + def RenderProduct "omni_kit_widget_viewport_ViewportTexture_0" ( + hide_in_stage_window = true + no_delete = true + ) + { + rel camera = + rel orderedVars = + custom bool overrideClipRange = 0 + uniform int2 resolution = (1280, 720) + custom uint64 viewPickingId = 706153192698425 + custom int viewportHandle = 0 + } + } + } + + def RenderSettings "OmniverseGlobalRenderSettings" ( + hide_in_stage_window = true + no_delete = true + ) + { + rel products = + } + + def "Vars" + { + def RenderVar "LdrColor" ( + hide_in_stage_window = true + no_delete = true + ) + { + uniform string sourceName = "LdrColor" + } + } +} + diff --git a/newton/examples/assets/envs/humanoid_env.usd b/newton/examples/assets/envs/humanoid_env.usd new file mode 100644 index 0000000000..919d8ddb6f Binary files /dev/null and b/newton/examples/assets/envs/humanoid_env.usd differ diff --git a/newton/examples/example_selection_ant.py b/newton/examples/example_selection_ant.py new file mode 100644 index 0000000000..96c60dc6bd --- /dev/null +++ b/newton/examples/example_selection_ant.py @@ -0,0 +1,224 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 The Newton Developers +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math + +import torch +import warp as wp + +import newton +import newton.examples +import newton.utils +from newton.utils.isaaclab import replicate_environment +from newton.utils.selection import ArticulationView + + +class Example: + def __init__(self, stage_path=None, num_envs=8): + self.num_envs = num_envs + + builder, stage_info = replicate_environment( + newton.examples.get_asset("envs/ant_env.usda"), + "/World/envs/env_0", + "/World/envs/env_{}", + num_envs, + (5.0, 5.0, 0.0), + # USD importer args + collapse_fixed_joints=True, + joint_ordering="dfs", + ) + + up_axis = stage_info.get("up_axis") or newton.Axis.Z + + # finalize model + self.model = builder.finalize() + + self.solver = newton.solvers.MuJoCoSolver(self.model) + + self.renderer = None + if stage_path: + self.renderer = newton.utils.SimRendererOpenGL( + path=stage_path, + model=self.model, + scaling=2.0, + up_axis=str(up_axis), + screen_width=1280, + screen_height=720, + camera_pos=(0, 4, 30), + ) + + self.state_0 = self.model.state() + self.state_1 = self.model.state() + self.control = self.model.control() + + self.sim_time = 0.0 + fps = 60 + self.frame_dt = 1.0 / fps + + self.sim_substeps = 10 + self.sim_dt = self.frame_dt / self.sim_substeps + + self.next_reset = 0.0 + + # =========================================================== + # create articulation view + # =========================================================== + self.ants = ArticulationView(self.model, "/World/envs/*/Robot/torso", include_free_joint=True) + + print(f"articulation count: {self.ants.count}") + print(f"link_count: {self.ants.link_count}") + print(f"joint_count: {self.ants.joint_count}") + print(f"joint_axis_count: {self.ants.joint_axis_count}") + + print(f"joint_q shape: {self.ants.get_attribute('joint_q', self.model).shape}") + print(f"joint_qd shape: {self.ants.get_attribute('joint_qd', self.model).shape}") + print(f"joint_f shape: {self.ants.get_attribute('joint_f', self.model).shape}") + print(f"joint_target shape: {self.ants.get_attribute('joint_target', self.model).shape}") + print(f"body_q shape: {self.ants.get_attribute('body_q', self.model).shape}") + print(f"body_qd shape: {self.ants.get_attribute('body_qd', self.model).shape}") + + # set all dofs to the middle of their range by default + dof_limit_lower = wp.to_torch(self.ants.get_attribute("joint_limit_lower", self.model)) + dof_limit_upper = wp.to_torch(self.ants.get_attribute("joint_limit_upper", self.model)) + default_dof_transforms = 0.5 * (dof_limit_lower + dof_limit_upper) + + if self.ants.include_free_joint: + # combined root and dof transforms + self.default_transforms = wp.to_torch(self.ants.get_attribute("joint_q", self.model)).clone() + self.default_transforms[:, 2] = 0.8 # z-coordinate of articulation root + self.default_transforms[:, 7:] = default_dof_transforms + # combined root and dof velocities + self.default_velocities = wp.to_torch(self.ants.get_attribute("joint_qd", self.model)).clone() + self.default_velocities[:, 2] = 0.5 * math.pi # rotate about z-axis + self.default_velocities[:, 5] = 5.0 # move up z-axis + else: + # root transforms + self.default_root_transforms = wp.to_torch(self.ants.get_root_transforms(self.model)).clone() + self.default_root_transforms[:, 2] = 0.8 + # dof transforms + self.default_dof_transforms = default_dof_transforms + # root velocities + self.default_root_velocities = wp.to_torch(self.ants.get_root_velocities(self.model)).clone() + self.default_root_velocities[:, 2] = 0.5 * math.pi # rotate about z-axis + self.default_root_velocities[:, 5] = 5.0 # move up z-axis + # dof velocities + self.default_dof_velocities = wp.to_torch(self.ants.get_attribute("joint_qd", self.model)).clone() + + # create disjoint index groups to alternate between + all_indices = torch.arange(num_envs, dtype=torch.int32) + self.indices_0 = all_indices[::2] + self.indices_1 = all_indices[1::2] + + # reset all + self.reset() + self.next_reset = self.sim_time + 2.0 + + self.use_cuda_graph = wp.get_device().is_cuda + if self.use_cuda_graph: + with wp.ScopedCapture() as capture: + self.simulate() + self.graph = capture.graph + + def simulate(self): + for _ in range(self.sim_substeps): + self.state_0.clear_forces() + + # explicit collisions needed without MuJoCo solver + if not isinstance(self.solver, newton.solvers.MuJoCoSolver): + newton.collision.collide(self.model, self.state_0) + + self.solver.step(self.model, self.state_0, self.state_1, self.control, None, self.sim_dt) + self.state_0, self.state_1 = self.state_1, self.state_0 + + def step(self): + if self.sim_time >= self.next_reset: + self.reset(self.indices_0) + self.next_reset = self.sim_time + 2.0 + self.indices_0, self.indices_1 = self.indices_1, self.indices_0 + + # ========================= + # apply random controls + # ========================= + joint_forces = 300.0 - 600.0 * torch.rand((self.num_envs, 8)) + if self.ants.include_free_joint: + # include the leading root joint (pad with zeros) + joint_forces = torch.cat([torch.zeros((self.num_envs, 6)), joint_forces], axis=1) + self.ants.set_attribute("joint_f", self.control, joint_forces) + + with wp.ScopedTimer("step", active=False): + if self.use_cuda_graph: + wp.capture_launch(self.graph) + else: + self.simulate() + self.sim_time += self.frame_dt + + def reset(self, indices=None): + # ============================== + # set transforms and velocities + # ============================== + if self.ants.include_free_joint: + # set root and dof transforms together + self.ants.set_attribute("joint_q", self.state_0, self.default_transforms, indices=indices) + # set root and dof velocities together + self.ants.set_attribute("joint_qd", self.state_0, self.default_velocities, indices=indices) + else: + # set root and dof transforms separately + self.ants.set_root_transforms(self.state_0, self.default_root_transforms, indices=indices) + self.ants.set_attribute("joint_q", self.state_0, self.default_dof_transforms, indices=indices) + # set root and dof velocities separately + self.ants.set_root_velocities(self.state_0, self.default_root_velocities, indices=indices) + self.ants.set_attribute("joint_qd", self.state_0, self.default_dof_velocities, indices=indices) + + if not isinstance(self.solver, newton.solvers.MuJoCoSolver): + self.ants.eval_fk(self.state_0, indices=indices) + + def render(self): + if self.renderer is None: + return + + with wp.ScopedTimer("render", active=False): + self.renderer.begin_frame(self.sim_time) + self.renderer.render(self.state_0) + self.renderer.end_frame() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.") + parser.add_argument( + "--stage_path", + type=lambda x: None if x == "None" else str(x), + default="example_selection_ant.usd", + help="Path to the output USD file.", + ) + parser.add_argument("--num_frames", type=int, default=1200, help="Total number of frames.") + parser.add_argument("--num_envs", type=int, default=16, help="Total number of simulated environments.") + + args = parser.parse_known_args()[0] + + with wp.ScopedDevice(args.device): + example = Example(stage_path=args.stage_path, num_envs=args.num_envs) + + for _ in range(args.num_frames): + example.step() + example.render() + + # import time + # time.sleep(0.2) + + if example.renderer: + example.renderer.save() diff --git a/newton/examples/example_selection_anymal.py b/newton/examples/example_selection_anymal.py new file mode 100644 index 0000000000..6dbf21d573 --- /dev/null +++ b/newton/examples/example_selection_anymal.py @@ -0,0 +1,230 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 The Newton Developers +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# import math + +import torch +import warp as wp + +import newton +import newton.examples +import newton.utils +from newton.utils.isaaclab import replicate_environment +from newton.utils.selection import ArticulationView + + +class Example: + def __init__(self, stage_path=None, num_envs=8): + self.num_envs = num_envs + + builder, stage_info = replicate_environment( + newton.examples.get_asset("envs/anymal.usd"), + "/World/envs/env_0", + "/World/envs/env_{}", + num_envs, + (5.0, 5.0, 0.0), + # USD importer args + collapse_fixed_joints=True, + joint_ordering="dfs", + ) + + up_axis = stage_info.get("up_axis") or newton.Axis.Z + + # !!! asset has no ground plane + builder.add_ground_plane() + + # finalize model + self.model = builder.finalize() + + self.solver = newton.solvers.MuJoCoSolver(self.model) + + self.renderer = None + if stage_path: + self.renderer = newton.utils.SimRendererOpenGL( + path=stage_path, + model=self.model, + scaling=2.0, + up_axis=str(up_axis), + screen_width=1280, + screen_height=720, + camera_pos=(0, 4, 30), + ) + + self.state_0 = self.model.state() + self.state_1 = self.model.state() + self.control = self.model.control() + + self.sim_time = 0.0 + fps = 60 + self.frame_dt = 1.0 / fps + + self.sim_substeps = 10 + self.sim_dt = self.frame_dt / self.sim_substeps + + self.next_reset = 0.0 + + # =========================================================== + # create articulation view + # =========================================================== + self.anymals = ArticulationView(self.model, "/World/envs/*/Robot/base", include_free_joint=False) + + print(f"articulation count: {self.anymals.count}") + print(f"link_count: {self.anymals.link_count}") + print(f"joint_count: {self.anymals.joint_count}") + print(f"joint_axis_count: {self.anymals.joint_axis_count}") + print(f"joint_coord_count: {self.anymals.joint_coord_count}") + print(f"joint_dof_count: {self.anymals.joint_dof_count}") + + # print(f"joint_q shape: {self.anymals.get_attribute_shape('joint_q')}") + # print(f"joint_qd shape: {self.anymals.get_attribute_shape('joint_qd')}") + # print(f"joint_f shape: {self.anymals.get_attribute_shape('joint_f')}") + # print(f"joint_target shape: {self.anymals.get_attribute_shape('joint_target')}") + # print(f"body_q shape: {self.anymals.get_attribute_shape('body_q')}") + # print(f"body_qd shape: {self.anymals.get_attribute_shape('body_qd')}") + + # set all dofs to the middle of their range by default + # dof_limit_lower = wp.to_torch(self.anymals.get_attribute("joint_limit_lower", self.model)) + # dof_limit_upper = wp.to_torch(self.anymals.get_attribute("joint_limit_upper", self.model)) + # default_dof_transforms = 0.5 * (dof_limit_lower + dof_limit_upper) + + if self.anymals.include_free_joint: + # combined root and dof transforms + self.default_transforms = wp.to_torch(self.anymals.get_attribute("joint_q", self.model)).clone() + self.default_transforms[:, 2] = 1.5 # z-coordinate of articulation root + # self.default_transforms[:, 7:] = default_dof_transforms + # combined root and dof velocities + self.default_velocities = wp.to_torch(self.anymals.get_attribute("joint_qd", self.model)).clone() + # self.default_velocities[:, 2] = 1.0 * math.pi # rotate about z-axis + # self.default_velocities[:, 5] = 5.0 # move up z-axis + else: + # root transforms + self.default_root_transforms = wp.to_torch(self.anymals.get_root_transforms(self.model)).clone() + self.default_root_transforms[:, 2] = 1.5 + # dof transforms + # self.default_dof_transforms = default_dof_transforms + self.default_dof_transforms = wp.to_torch(self.anymals.get_attribute("joint_q", self.model)).clone() + # root velocities + self.default_root_velocities = wp.to_torch(self.anymals.get_root_velocities(self.model)).clone() + # self.default_root_velocities[:, 2] = 1.0 * math.pi # rotate about z-axis + # self.default_root_velocities[:, 5] = 5.0 # move up z-axis + # dof velocities + self.default_dof_velocities = wp.to_torch(self.anymals.get_attribute("joint_qd", self.model)).clone() + + # create disjoint index groups to alternate between + all_indices = torch.arange(num_envs, dtype=torch.int32) + self.indices_0 = all_indices[::2] + self.indices_1 = all_indices[1::2] + + # reset all + self.reset() + self.next_reset = self.sim_time + 2.0 + + self.use_cuda_graph = wp.get_device().is_cuda + if self.use_cuda_graph: + with wp.ScopedCapture() as capture: + self.simulate() + self.graph = capture.graph + + def simulate(self): + for _ in range(self.sim_substeps): + self.state_0.clear_forces() + + # explicit collisions needed without MuJoCo solver + if not isinstance(self.solver, newton.solvers.MuJoCoSolver): + newton.collision.collide(self.model, self.state_0) + + self.solver.step(self.model, self.state_0, self.state_1, self.control, None, self.sim_dt) + self.state_0, self.state_1 = self.state_1, self.state_0 + + def step(self): + if self.sim_time >= self.next_reset: + self.reset(self.indices_0) + self.next_reset = self.sim_time + 2.0 + self.indices_0, self.indices_1 = self.indices_1, self.indices_0 + + # # ========================= + # # apply random controls + # # ========================= + # joint_forces = 20.0 - 40.0 * torch.rand((self.num_envs, self.anymals.joint_dof_count)) + # if self.anymals.include_free_joint: + # # include the leading root joint (pad with zeros) + # joint_forces = torch.cat([torch.zeros((self.num_envs, 6)), joint_forces], axis=1) + # self.anymals.set_attribute("joint_f", self.control, joint_forces) + + with wp.ScopedTimer("step", active=False): + if self.use_cuda_graph: + wp.capture_launch(self.graph) + else: + self.simulate() + self.sim_time += self.frame_dt + + def reset(self, indices=None): + # ============================== + # set transforms and velocities + # ============================== + if self.anymals.include_free_joint: + # set root and dof transforms together + self.anymals.set_attribute("joint_q", self.state_0, self.default_transforms, indices=indices) + # set root and dof velocities together + self.anymals.set_attribute("joint_qd", self.state_0, self.default_velocities, indices=indices) + else: + # set root and dof transforms separately + self.anymals.set_root_transforms(self.state_0, self.default_root_transforms, indices=indices) + self.anymals.set_attribute("joint_q", self.state_0, self.default_dof_transforms, indices=indices) + # set root and dof velocities separately + self.anymals.set_root_velocities(self.state_0, self.default_root_velocities, indices=indices) + self.anymals.set_attribute("joint_qd", self.state_0, self.default_dof_velocities, indices=indices) + + if not isinstance(self.solver, newton.solvers.MuJoCoSolver): + self.anymals.eval_fk(self.state_0, indices=indices) + + def render(self): + if self.renderer is None: + return + + with wp.ScopedTimer("render", active=False): + self.renderer.begin_frame(self.sim_time) + self.renderer.render(self.state_0) + self.renderer.end_frame() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.") + parser.add_argument( + "--stage_path", + type=lambda x: None if x == "None" else str(x), + default="example_selection_humanoid.usd", + help="Path to the output USD file.", + ) + parser.add_argument("--num_frames", type=int, default=1200, help="Total number of frames.") + parser.add_argument("--num_envs", type=int, default=16, help="Total number of simulated environments.") + + args = parser.parse_known_args()[0] + + with wp.ScopedDevice(args.device): + example = Example(stage_path=args.stage_path, num_envs=args.num_envs) + + for _ in range(args.num_frames): + example.step() + example.render() + + # import time + # time.sleep(0.5) + + if example.renderer: + example.renderer.save() diff --git a/newton/examples/example_selection_cartpole.py b/newton/examples/example_selection_cartpole.py new file mode 100644 index 0000000000..5bc7c128b3 --- /dev/null +++ b/newton/examples/example_selection_cartpole.py @@ -0,0 +1,162 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 The Newton Developers +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import math + +import torch +import warp as wp + +import newton +import newton.examples +import newton.utils +from newton.utils.isaaclab import replicate_environment +from newton.utils.selection import ArticulationView + + +class Example: + def __init__(self, stage_path=None, num_envs=8): + self.num_envs = num_envs + + builder, stage_info = replicate_environment( + newton.examples.get_asset("envs/cartpole_env.usda"), + "/World/envs/env_0", + "/World/envs/env_{}", + num_envs, + (2.0, 3.0, 0.0), + # USD importer args + collapse_fixed_joints=True, + joint_ordering="dfs", + ) + + up_axis = stage_info.get("up_axis") or newton.Axis.Z + + # finalize model + self.model = builder.finalize() + + self.sim_time = 0.0 + fps = 60 + self.frame_dt = 1.0 / fps + + self.sim_substeps = 10 + self.sim_dt = self.frame_dt / self.sim_substeps + + self.solver = newton.solvers.MuJoCoSolver(self.model) + + self.state_0 = self.model.state() + self.state_1 = self.model.state() + self.control = self.model.control() + + # ======================= + # get cartpole view + # ======================= + self.cartpoles = ArticulationView(self.model, "/World/envs/*/Robot") + + # print(self.cartpoles.get_attribute("body_q", self.state_0)) + # print(self.cartpoles.get_attribute("body_qd", self.state_0)) + # print(self.cartpoles.get_attribute("joint_q", self.state_0)) + # print(self.cartpoles.get_attribute("joint_qd", self.state_0)) + # print(self.cartpoles.get_attribute("joint_f", self.control)) + + # ========================= + # randomize initial state + # ========================= + cart_positions = 2.0 - 4.0 * torch.rand(num_envs) + pole_angles = math.pi / 16.0 - math.pi / 8.0 * torch.rand(num_envs) + joint_states = torch.stack([cart_positions, pole_angles], dim=1) + self.cartpoles.set_attribute("joint_q", self.state_0, joint_states) + + if not isinstance(self.solver, newton.solvers.MuJoCoSolver): + self.cartpoles.eval_fk(self.state_0) + + self.renderer = None + if stage_path: + self.renderer = newton.utils.SimRendererOpenGL( + path=stage_path, + model=self.model, + scaling=1.0, + up_axis=str(up_axis), + screen_width=1280, + screen_height=720, + camera_pos=(0, 3, 10), + ) + + self.use_cuda_graph = wp.get_device().is_cuda + if self.use_cuda_graph: + with wp.ScopedCapture() as capture: + self.simulate() + self.graph = capture.graph + + def simulate(self): + for _ in range(self.sim_substeps): + self.state_0.clear_forces() + self.solver.step(self.model, self.state_0, self.state_1, self.control, None, self.sim_dt) + self.state_0, self.state_1 = self.state_1, self.state_0 + + def step(self): + # ========================= + # get observations + # ========================= + joint_states = wp.to_torch(self.cartpoles.get_attribute("joint_q", self.state_0)) + + # ========================= + # apply controls + # ========================= + joint_forces = torch.zeros((self.num_envs, 2)) + joint_forces[:, 0] = torch.where(joint_states[:, 0] > 0, -100, 100) + self.cartpoles.set_attribute("joint_f", self.control, joint_forces) + + # simulate + with wp.ScopedTimer("step", active=False): + if self.use_cuda_graph: + wp.capture_launch(self.graph) + else: + self.simulate() + self.sim_time += self.frame_dt + + def render(self): + if self.renderer is None: + return + + with wp.ScopedTimer("render", active=False): + self.renderer.begin_frame(self.sim_time) + self.renderer.render(self.state_0) + self.renderer.end_frame() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.") + parser.add_argument( + "--stage_path", + type=lambda x: None if x == "None" else str(x), + default="example_selection_cartpole.usd", + help="Path to the output USD file.", + ) + parser.add_argument("--num_frames", type=int, default=12000, help="Total number of frames.") + parser.add_argument("--num_envs", type=int, default=16, help="Total number of simulated environments.") + + args = parser.parse_known_args()[0] + + with wp.ScopedDevice(args.device): + example = Example(stage_path=args.stage_path, num_envs=args.num_envs) + + for _ in range(args.num_frames): + example.step() + example.render() + + if example.renderer: + example.renderer.save() diff --git a/newton/examples/example_selection_humanoid.py b/newton/examples/example_selection_humanoid.py new file mode 100644 index 0000000000..a4a7085622 --- /dev/null +++ b/newton/examples/example_selection_humanoid.py @@ -0,0 +1,227 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 The Newton Developers +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# import math + +import torch +import warp as wp + +import newton +import newton.examples +import newton.utils +from newton.utils.isaaclab import replicate_environment +from newton.utils.selection import ArticulationView + + +class Example: + def __init__(self, stage_path=None, num_envs=8): + self.num_envs = num_envs + + builder, stage_info = replicate_environment( + newton.examples.get_asset("envs/humanoid_env.usd"), + "/World/envs/env_0", + "/World/envs/env_{}", + num_envs, + (5.0, 5.0, 0.0), + # USD importer args + collapse_fixed_joints=True, + joint_ordering="dfs", + ) + + up_axis = stage_info.get("up_axis") or newton.Axis.Z + + # finalize model + self.model = builder.finalize() + + self.solver = newton.solvers.MuJoCoSolver(self.model) + + self.renderer = None + if stage_path: + self.renderer = newton.utils.SimRendererOpenGL( + path=stage_path, + model=self.model, + scaling=2.0, + up_axis=str(up_axis), + screen_width=1280, + screen_height=720, + camera_pos=(0, 4, 30), + ) + + self.state_0 = self.model.state() + self.state_1 = self.model.state() + self.control = self.model.control() + + self.sim_time = 0.0 + fps = 60 + self.frame_dt = 1.0 / fps + + self.sim_substeps = 10 + self.sim_dt = self.frame_dt / self.sim_substeps + + self.next_reset = 0.0 + + # =========================================================== + # create articulation view + # =========================================================== + self.humanoids = ArticulationView(self.model, "/World/envs/*/Robot/torso", include_free_joint=False) + + print(f"articulation count: {self.humanoids.count}") + print(f"link_count: {self.humanoids.link_count}") + print(f"joint_count: {self.humanoids.joint_count}") + print(f"joint_axis_count: {self.humanoids.joint_axis_count}") + print(f"joint_coord_count: {self.humanoids.joint_coord_count}") + print(f"joint_dof_count: {self.humanoids.joint_dof_count}") + + # print(f"joint_q shape: {self.humanoids.get_attribute_shape('joint_q')}") + # print(f"joint_qd shape: {self.humanoids.get_attribute_shape('joint_qd')}") + # print(f"joint_f shape: {self.humanoids.get_attribute_shape('joint_f')}") + # print(f"joint_target shape: {self.humanoids.get_attribute_shape('joint_target')}") + # print(f"body_q shape: {self.humanoids.get_attribute_shape('body_q')}") + # print(f"body_qd shape: {self.humanoids.get_attribute_shape('body_qd')}") + + # set all dofs to the middle of their range by default + # dof_limit_lower = wp.to_torch(self.humanoids.get_attribute("joint_limit_lower", self.model)) + # dof_limit_upper = wp.to_torch(self.humanoids.get_attribute("joint_limit_upper", self.model)) + # default_dof_transforms = 0.5 * (dof_limit_lower + dof_limit_upper) + + if self.humanoids.include_free_joint: + # combined root and dof transforms + self.default_transforms = wp.to_torch(self.humanoids.get_attribute("joint_q", self.model)).clone() + self.default_transforms[:, 2] = 1.5 # z-coordinate of articulation root + # self.default_transforms[:, 7:] = default_dof_transforms + # combined root and dof velocities + self.default_velocities = wp.to_torch(self.humanoids.get_attribute("joint_qd", self.model)).clone() + # self.default_velocities[:, 2] = 1.0 * math.pi # rotate about z-axis + # self.default_velocities[:, 5] = 5.0 # move up z-axis + else: + # root transforms + self.default_root_transforms = wp.to_torch(self.humanoids.get_root_transforms(self.model)).clone() + self.default_root_transforms[:, 2] = 1.5 + # dof transforms + # self.default_dof_transforms = default_dof_transforms + self.default_dof_transforms = wp.to_torch(self.humanoids.get_attribute("joint_q", self.model)).clone() + # root velocities + self.default_root_velocities = wp.to_torch(self.humanoids.get_root_velocities(self.model)).clone() + # self.default_root_velocities[:, 2] = 1.0 * math.pi # rotate about z-axis + # self.default_root_velocities[:, 5] = 5.0 # move up z-axis + # dof velocities + self.default_dof_velocities = wp.to_torch(self.humanoids.get_attribute("joint_qd", self.model)).clone() + + # create disjoint index groups to alternate between + all_indices = torch.arange(num_envs, dtype=torch.int32) + self.indices_0 = all_indices[::2] + self.indices_1 = all_indices[1::2] + + # reset all + self.reset() + self.next_reset = self.sim_time + 2.0 + + self.use_cuda_graph = wp.get_device().is_cuda + if self.use_cuda_graph: + with wp.ScopedCapture() as capture: + self.simulate() + self.graph = capture.graph + + def simulate(self): + for _ in range(self.sim_substeps): + self.state_0.clear_forces() + + # explicit collisions needed without MuJoCo solver + if not isinstance(self.solver, newton.solvers.MuJoCoSolver): + newton.collision.collide(self.model, self.state_0) + + self.solver.step(self.model, self.state_0, self.state_1, self.control, None, self.sim_dt) + self.state_0, self.state_1 = self.state_1, self.state_0 + + def step(self): + if self.sim_time >= self.next_reset: + self.reset(self.indices_0) + self.next_reset = self.sim_time + 2.0 + self.indices_0, self.indices_1 = self.indices_1, self.indices_0 + + # ========================= + # apply random controls + # ========================= + joint_forces = 20.0 - 40.0 * torch.rand((self.num_envs, self.humanoids.joint_dof_count)) + if self.humanoids.include_free_joint: + # include the leading root joint (pad with zeros) + joint_forces = torch.cat([torch.zeros((self.num_envs, 6)), joint_forces], axis=1) + self.humanoids.set_attribute("joint_f", self.control, joint_forces) + + with wp.ScopedTimer("step", active=False): + if self.use_cuda_graph: + wp.capture_launch(self.graph) + else: + self.simulate() + self.sim_time += self.frame_dt + + def reset(self, indices=None): + # ============================== + # set transforms and velocities + # ============================== + if self.humanoids.include_free_joint: + # set root and dof transforms together + self.humanoids.set_attribute("joint_q", self.state_0, self.default_transforms, indices=indices) + # set root and dof velocities together + self.humanoids.set_attribute("joint_qd", self.state_0, self.default_velocities, indices=indices) + else: + # set root and dof transforms separately + self.humanoids.set_root_transforms(self.state_0, self.default_root_transforms, indices=indices) + self.humanoids.set_attribute("joint_q", self.state_0, self.default_dof_transforms, indices=indices) + # set root and dof velocities separately + self.humanoids.set_root_velocities(self.state_0, self.default_root_velocities, indices=indices) + self.humanoids.set_attribute("joint_qd", self.state_0, self.default_dof_velocities, indices=indices) + + if not isinstance(self.solver, newton.solvers.MuJoCoSolver): + self.humanoids.eval_fk(self.state_0, indices=indices) + + def render(self): + if self.renderer is None: + return + + with wp.ScopedTimer("render", active=False): + self.renderer.begin_frame(self.sim_time) + self.renderer.render(self.state_0) + self.renderer.end_frame() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.") + parser.add_argument( + "--stage_path", + type=lambda x: None if x == "None" else str(x), + default="example_selection_humanoid.usd", + help="Path to the output USD file.", + ) + parser.add_argument("--num_frames", type=int, default=1200, help="Total number of frames.") + parser.add_argument("--num_envs", type=int, default=16, help="Total number of simulated environments.") + + args = parser.parse_known_args()[0] + + with wp.ScopedDevice(args.device): + example = Example(stage_path=args.stage_path, num_envs=args.num_envs) + + for _ in range(args.num_frames): + example.step() + example.render() + + # import time + # time.sleep(0.5) + + if example.renderer: + example.renderer.save() diff --git a/newton/utils/isaaclab.py b/newton/utils/isaaclab.py new file mode 100644 index 0000000000..037b779f1e --- /dev/null +++ b/newton/utils/isaaclab.py @@ -0,0 +1,113 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 The Newton Developers +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Any + +import warp as wp + +import newton +from newton.examples import compute_env_offsets + + +def replicate_environment( + source, + prototype_path: str, + path_pattern: str, + num_envs: int, + env_spacing: tuple[float], + up_axis: newton.AxisType = "Z", + **usd_kwargs, +) -> tuple[newton.ModelBuilder, dict[str:Any]]: + """ + Replicates a prototype USD environment in Newton. + + Args: + source (str | pxr.UsdStage): The file path to the USD file, or an existing USD stage instance. + prototype_path (str): The USD path where the prototype env is defined, e.g., "/World/envs/env_0". + path_pattern (str): The USD path pattern for replicated envs, e.g., "/World/envs/env_{}". + num_envs (int): Number of replicas to create. + env_spacing (tuple[float]): Environment spacing vector. + up_axis (AxisType): The desired up-vector (should match the USD stage). + **usd_kwargs: Keyword arguments to pass to the USD importer (see `newton.utils.parse_usd()`). + + Returns: + (ModelBuilder, dict): The resulting ModelBuilder containing all replicated environments and a dictionary with USD stage information. + """ + + builder = newton.ModelBuilder(up_axis=up_axis) + + # first, load everything except the prototype env + stage_info = newton.utils.parse_usd( + source, + builder, + ignore_paths=[prototype_path], + **usd_kwargs, + ) + + # up_axis sanity check + stage_up_axis = stage_info.get("up_axis") + if isinstance(stage_up_axis, str) and stage_up_axis.upper() != up_axis.upper(): + print(f"WARNING: up_axis '{up_axis}' does not match USD stage up_axis '{stage_up_axis}'") + + # load just the prototype env + prototype_builder = newton.ModelBuilder(up_axis=up_axis) + newton.utils.parse_usd( + source, + prototype_builder, + root_path=prototype_path, + **usd_kwargs, + ) + + env_offsets = compute_env_offsets(num_envs, env_offset=env_spacing, up_axis=up_axis) + + # clone the prototype env with updated paths + for i in range(num_envs): + body_start = builder.body_count + shape_start = builder.shape_count + joint_start = builder.joint_count + articulation_start = builder.articulation_count + + builder.add_builder(prototype_builder, xform=wp.transform(env_offsets[i], wp.quat_identity())) + + if i > 0: + update_paths( + builder, + prototype_path, + path_pattern.format(i), + body_start=body_start, + shape_start=shape_start, + joint_start=joint_start, + articulation_start=articulation_start, + ) + + return builder, stage_info + + +def update_paths( + builder, old_root, new_root, body_start=None, shape_start=None, joint_start=None, articulation_start=None +): + old_len = len(old_root) + if body_start is not None: + for i in range(body_start, builder.body_count): + builder.body_key[i] = f"{new_root}{builder.body_key[i][old_len:]}" + if shape_start is not None: + for i in range(shape_start, builder.shape_count): + builder.shape_key[i] = f"{new_root}{builder.shape_key[i][old_len:]}" + if joint_start is not None: + for i in range(joint_start, builder.joint_count): + builder.joint_key[i] = f"{new_root}{builder.joint_key[i][old_len:]}" + if articulation_start is not None: + for i in range(articulation_start, builder.articulation_count): + builder.articulation_key[i] = f"{new_root}{builder.articulation_key[i][old_len:]}" diff --git a/newton/utils/selection.py b/newton/utils/selection.py new file mode 100644 index 0000000000..0c9915d510 --- /dev/null +++ b/newton/utils/selection.py @@ -0,0 +1,536 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 The Newton Developers +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import functools +from fnmatch import fnmatch + +import numpy as np +import warp as wp +from warp.types import is_array + +import newton.sim +from newton import Control, Model, State + + +class AttributeRegistry: + def __init__(self): + # look up indexing mode for known attributes + self._indexing_mode: dict[str:str] = {} + + # addressable by joint id + self.register_attribute("joint_type", "joint") + self.register_attribute("joint_parent", "joint") + self.register_attribute("joint_child", "joint") + self.register_attribute("joint_ancestor", "joint") + self.register_attribute("joint_X_p", "joint") + self.register_attribute("joint_X_c", "joint") + self.register_attribute("joint_axis_start", "joint") + self.register_attribute("joint_axis_dim", "joint") + self.register_attribute("joint_enabled", "joint") + self.register_attribute("joint_twist_lower", "joint") + self.register_attribute("joint_twist_upper", "joint") + + # addressable by joint coord offset + self.register_attribute("joint_q", "joint_coord") + + # addressable by joint dof offset + self.register_attribute("joint_qd", "joint_dof") + self.register_attribute("joint_f", "joint_dof") + self.register_attribute("joint_armature", "joint_dof") + + # addressable by joint axis offset + self.register_attribute("joint_target", "joint_axis") + self.register_attribute("joint_axis", "joint_axis") + self.register_attribute("joint_target_ke", "joint_axis") + self.register_attribute("joint_target_kd", "joint_axis") + self.register_attribute("joint_axis_mode", "joint_axis") + self.register_attribute("joint_limit_lower", "joint_axis") + self.register_attribute("joint_limit_upper", "joint_axis") + self.register_attribute("joint_limit_ke", "joint_axis") + self.register_attribute("joint_limit_kd", "joint_axis") + + # addressable by body id + self.register_attribute("body_q", "body") + self.register_attribute("body_qd", "body") + self.register_attribute("body_com", "body") + self.register_attribute("body_inertia", "body") + self.register_attribute("body_inv_inertia", "body") + self.register_attribute("body_mass", "body") + self.register_attribute("body_inv_mass", "body") + self.register_attribute("body_f", "body") + + def register_attribute(self, name: str, mode: str): + self._indexing_mode[name] = mode + + def get_indexing_mode(self, attribute_name: str): + return self._indexing_mode[attribute_name] + + +attribute_registry = AttributeRegistry() + + +@wp.kernel +def set_mask_kernel(indices: wp.array(dtype=int), mask: wp.array(dtype=bool)): + tid = wp.tid() + mask[indices[tid]] = True + + +@wp.kernel +def set_mask_indexed_kernel( + indices: wp.array(dtype=int), indices_indices: wp.array(dtype=int), mask: wp.array(dtype=bool) +): + tid = wp.tid() + mask[indices[indices_indices[tid]]] = True + + +@wp.kernel +def set_articulation_root_transforms_kernel( + articulation_indices: wp.array(dtype=int), + articulation_start: wp.array(dtype=int), + joint_type: wp.array(dtype=int), + joint_q_start: wp.array(dtype=int), + root_transforms: wp.array(dtype=wp.transform), + env_indices: wp.array(dtype=int), + # outputs + joint_q: wp.array(dtype=float), + joint_X_p: wp.array(dtype=wp.transform), +): + tid = wp.tid() + idx = env_indices[tid] + root_pose = root_transforms[idx] + articulation = articulation_indices[idx] + joint_start = articulation_start[articulation] + q_start = joint_q_start[joint_start] + + if joint_type[joint_start] == newton.JOINT_FREE: + for i in range(7): + joint_q[q_start + i] = root_pose[i] + elif joint_type[joint_start] == newton.JOINT_FIXED: + joint_X_p[joint_start] = root_pose + + +@wp.kernel +def get_articulation_root_transforms_kernel( + articulation_indices: wp.array(dtype=int), + articulation_start: wp.array(dtype=int), + joint_parent: wp.array(dtype=int), + joint_child: wp.array(dtype=int), + body_q: wp.array(dtype=wp.transform), + # outputs + root_xforms: wp.array(dtype=wp.transform), +): + tid = wp.tid() + articulation = articulation_indices[tid] + joint_start = articulation_start[articulation] + + if joint_parent[joint_start] != -1: + root_body = joint_parent[joint_start] + else: + root_body = joint_child[joint_start] + + root_pose = body_q[root_body] + + root_xforms[tid] = root_pose + + +@wp.kernel +def set_articulation_root_velocities_kernel( + articulation_indices: wp.array(dtype=int), + articulation_start: wp.array(dtype=int), + joint_type: wp.array(dtype=int), + joint_qd_start: wp.array(dtype=int), + root_vels: wp.array(dtype=wp.spatial_vector), + env_indices: wp.array(dtype=int), + # outputs + joint_qd: wp.array(dtype=float), +): + tid = wp.tid() + idx = env_indices[tid] + articulation = articulation_indices[idx] + joint_start = articulation_start[articulation] + qd_start = joint_qd_start[joint_start] + root_vel = root_vels[idx] + + if joint_type[joint_start] == newton.JOINT_FREE: + for i in range(6): + joint_qd[qd_start + i] = root_vel[i] + + +@wp.kernel +def get_articulation_root_velocities_kernel( + articulation_indices: wp.array(dtype=int), + articulation_start: wp.array(dtype=int), + joint_parent: wp.array(dtype=int), + joint_child: wp.array(dtype=int), + body_qd: wp.array(dtype=wp.spatial_vector), + # outputs + root_vels: wp.array(dtype=wp.spatial_vector), +): + tid = wp.tid() + articulation = articulation_indices[tid] + joint_start = articulation_start[articulation] + + if joint_parent[joint_start] != -1: + root_body = joint_parent[joint_start] + else: + root_body = joint_child[joint_start] + + root_vels[tid] = body_qd[root_body] + + +class ArticulationView: + def __init__(self, model: Model, pattern: str, include_free_joint: bool = False, verbose: bool | None = None): + self.model = model + self.device = model.device + self.include_free_joint = include_free_joint + + if verbose is None: + verbose = wp.config.verbose + + articulation_ids = [] + for id, key in enumerate(model.articulation_key): + if fnmatch(key, pattern): + articulation_ids.append(id) + + count = len(articulation_ids) + if count == 0: + raise KeyError("No matching articulations") + + # FIXME: avoid this readback? + articulation_start = model.articulation_start.numpy() + joint_type = model.joint_type.numpy() + joint_parent = model.joint_parent.numpy() + joint_child = model.joint_child.numpy() + joint_axis_start = model.joint_axis_start.numpy() + joint_axis_dim = model.joint_axis_dim.numpy() + joint_q_start = model.joint_q_start.numpy() + joint_qd_start = model.joint_qd_start.numpy() + + # FIXME: + # - this assumes homogeneous envs with one selected articulation per env + # - we're going to have problems if there are any bodies or joints in the "global" env + + arti_0 = articulation_ids[0] + + joint_begin = articulation_start[arti_0] + joint_end = articulation_start[arti_0 + 1] # FIXME: is this always correct? + joint_last = joint_end - 1 + + links = {} + for joint_id in range(joint_begin, joint_end): + if joint_parent[joint_id] != -1: + links[int(joint_parent[joint_id])] = None + if joint_child[joint_id] != -1: + links[int(joint_child[joint_id])] = None + + links = sorted(links.keys()) + + # print stuff for debugging + if verbose: + print(f"num_joints: {joint_end - joint_begin}") + for joint_id in range(joint_begin, joint_end): + joint_name = model.joint_key[joint_id] + print(f" joint {joint_name}:") + print(f" bodies: {joint_parent[joint_id]} -> {joint_child[joint_id]}") + print(f" axis_start: {joint_axis_start[joint_id]}") + print(f" axis_dim: {joint_axis_dim[joint_id]}") + num_links = len(links) + print(f"num_links: {num_links}, {links}") + for body_id in links: + print(f" {model.body_key[body_id]}") + + # if the root joint is a free joint, skip it + if joint_type[joint_begin] == newton.JOINT_FREE and not include_free_joint: + joint_begin += 1 + + joint_coord_begin = joint_q_start[joint_begin] + joint_coord_end = joint_q_start[joint_end] + joint_dof_begin = joint_qd_start[joint_begin] + joint_dof_end = joint_qd_start[joint_end] + joint_axis_begin = joint_axis_start[joint_begin] + joint_axis_end = joint_axis_start[joint_last] + joint_axis_dim[joint_last][0] + joint_axis_dim[joint_last][1] + body_begin = links[0] + body_end = links[-1] + 1 + + self.articulation_indices = wp.array(articulation_ids, dtype=int, device=self.device) + + # create articulation mask + self.articulation_mask = wp.zeros(model.articulation_count, dtype=bool, device=self.device) + wp.launch( + set_mask_kernel, dim=count, inputs=[self.articulation_indices, self.articulation_mask], device=self.device + ) + + self.all_indices = wp.array(np.arange(count, dtype=np.int32), device=self.device) + + # set some counting properties + self.count = count + self.link_count = len(links) + self.joint_count = joint_end - joint_begin + self.joint_coord_count = joint_coord_end - joint_coord_begin + self.joint_dof_count = joint_dof_end - joint_dof_begin + self.joint_axis_count = joint_axis_end - joint_axis_begin + + self.joint_names = [] + self.joint_coord_names = [] + self.joint_dof_names = [] + self.joint_axis_names = [] + self.body_names = [] + + def get_name_from_key(key): + return key.split("/")[-1] + + for joint_id in range(joint_begin, joint_end): + joint_name = get_name_from_key(model.joint_key[joint_id]) + self.joint_names.append(joint_name) + num_coords = joint_q_start[joint_id + 1] - joint_q_start[joint_id] + if num_coords == 1: + self.joint_coord_names.append(joint_name) + elif num_coords > 1: + for coord in range(num_coords): + self.joint_coord_names.append(f"{joint_name}:{coord}") + num_dofs = joint_qd_start[joint_id + 1] - joint_qd_start[joint_id] + if num_dofs == 1: + self.joint_dof_names.append(joint_name) + elif num_dofs > 1: + for dof in range(num_dofs): + self.joint_dof_names.append(f"{joint_name}:{dof}") + num_axes = joint_axis_dim[joint_id][0] + joint_axis_dim[joint_id][1] + if num_axes == 1: + self.joint_axis_names.append(joint_name) + elif num_axes > 1: + for axis in range(num_axes): + self.joint_axis_names.append(f"{joint_name}:{axis}") + + for body_id in range(body_begin, body_end): + self.body_names.append(get_name_from_key(model.body_key[body_id])) + + print("Link names:") + print(self.body_names) + print("Joint names:") + print(self.joint_names) + print("Joint axis names:") + print(self.joint_axis_names) + # print("Joint coord names:") + # print(self.joint_coord_names) + # print("Joint dof names:") + # print(self.joint_dof_names) + + # slices by indexing mode + self._slices = { + "joint": slice(int(joint_begin), int(joint_end)), + "joint_coord": slice(int(joint_coord_begin), int(joint_coord_end)), + "joint_dof": slice(int(joint_dof_begin), int(joint_dof_end)), + "joint_axis": slice(int(joint_axis_begin), int(joint_axis_end)), + "body": slice(int(body_begin), int(body_end)), + } + + self._root_transforms = None + self._root_velocities = None + + @functools.lru_cache(maxsize=None) # noqa + def _get_cached_attribute(self, name: str, source: Model | State | Control): + # get the attribute array + attrib = getattr(source, name) + assert isinstance(attrib, wp.array) + + # reshape with batch dim at front + assert attrib.shape[0] % self.count == 0 + batched_shape = (self.count, attrib.shape[0] // self.count, *attrib.shape[1:]) + + # get attribute slice + indexing_mode = attribute_registry.get_indexing_mode(name) + attrib_slice = self._slices[indexing_mode] + + # create strided array + attrib = attrib.reshape(batched_shape) + attrib = attrib[:, attrib_slice] + + return attrib + + def get_attribute(self, name: str, source: Model | State | Control): + return self._get_cached_attribute(name, source) + + def set_attribute(self, name: str, target: Model | State | Control, values, indices=None): + attrib = self._get_cached_attribute(name, target) + if not is_array(values): + values = wp.array(values, dtype=attrib.dtype, shape=attrib.shape, device=self.device) + if indices is not None: + if not is_array(indices): + indices = wp.array(indices, dtype=int, device=self.device) + attrib = wp.indexedarray(attrib, [indices]) + values = wp.indexedarray(values, [indices]) + wp.copy(attrib, values) + + # convenience wrappers to align with legacy tensor API + # TODO: do we want this? + + # def get_link_transforms(self, source, copy=False): + # return self.get_attribute("body_q", source, copy=copy) + + # def get_link_velocities(self, source, copy=False): + # return self.get_attribute("body_qd", source, copy=copy) + + # ... + + def get_root_transforms(self, source: Model | State): + """ + Get the root transforms of the articulations. + + Args: + source (Model | State): Where to get the root transforms (Model or State). + + Returns: + array: The root transforms (dtype=wp.transform). + """ + if self._root_transforms is None: + self._root_transforms = wp.empty(self.count, dtype=wp.transform, device=self.device) + + wp.launch( + get_articulation_root_transforms_kernel, + self.count, + inputs=[ + self.articulation_indices, + self.model.articulation_start, + self.model.joint_parent, + self.model.joint_child, + source.body_q, + ], + outputs=[ + self._root_transforms, + ], + device=self.device, + ) + + return self._root_transforms + + def set_root_transforms(self, target: Model | State, root_transforms: wp.array, indices=None): + """ + Set the root transforms of the articulations. + Call `eval_fk()` to apply changes to all articulation links. + + Args: + target (Model | State): Where to set the root transforms (Model or State). + root_transforms (array): The root transforms to set (dtype=wp.transform). + """ + + if not is_array(root_transforms): + root_transforms = wp.array(root_transforms, dtype=wp.transform, device=self.device) + + assert len(root_transforms) == self.count, "Root poses should be provided for each articulation" + + if indices is not None: + if not is_array(indices): + indices = wp.array(indices, dtype=int, device=self.device) + else: + indices = self.all_indices + + wp.launch( + set_articulation_root_transforms_kernel, + indices.size, + inputs=[ + self.articulation_indices, + self.model.articulation_start, + self.model.joint_type, + self.model.joint_q_start, + root_transforms, + indices, + ], + outputs=[ + target.joint_q, + self.model.joint_X_p, # hmmm + ], + device=self.device, + ) + + def get_root_velocities(self, source: Model | State): + """ + Get the root velocities of the articulations. + + Args: + source (Model | State): Where to get the root velocities (Model or State). + + Returns: + array: The root velocities (dtype=wp.spatial_vector). + """ + if self._root_velocities is None: + self._root_velocities = wp.empty(self.count, dtype=wp.spatial_vector, device=self.device) + + wp.launch( + get_articulation_root_velocities_kernel, + self.count, + inputs=[ + self.articulation_indices, + self.model.articulation_start, + self.model.joint_parent, + self.model.joint_child, + source.body_qd, + ], + outputs=[ + self._root_velocities, + ], + device=self.device, + ) + + return self._root_velocities + + def set_root_velocities(self, target: Model | State, root_vels: wp.array, indices=None): + """ + Set the root velocities of the articulations. + + Args: + target (Model | State): Where to set the root velocities (Model or State). + root_vels (array): The root velocities to set (dtype=wp.spatial_vector). + """ + + if not is_array(root_vels): + root_vels = wp.array(root_vels, dtype=wp.spatial_vector, device=self.device) + + assert len(root_vels) == self.count, "Root velocities should be provided for each articulation" + + if indices is not None: + if not is_array(indices): + indices = wp.array(indices, dtype=int, device=self.device) + else: + indices = self.all_indices + + wp.launch( + set_articulation_root_velocities_kernel, + indices.size, + inputs=[ + self.articulation_indices, + self.model.articulation_start, + self.model.joint_type, + self.model.joint_qd_start, + root_vels, + indices, + ], + outputs=[ + target.joint_qd, + ], + device=self.device, + ) + + def eval_fk(self, target: Model | State, indices=None): + if indices is not None: + # create a custom mask for builtin eval_fk() + # TODO: something more efficient? + if not is_array(indices): + indices = wp.array(indices, dtype=int, device=self.device) + mask = wp.zeros(self.model.articulation_count, dtype=bool, device=self.device) + wp.launch(set_mask_indexed_kernel, dim=indices.size, inputs=[self.articulation_indices, indices, mask]) + else: + mask = self.articulation_mask + + newton.sim.eval_fk(self.model, target.joint_q, target.joint_qd, target, mask=mask)