Skip to content

Commit 73e452b

Browse files
committed
chore: New release 2.10.1
1 parent 4aff9c9 commit 73e452b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+6884
-146
lines changed

exts/wandelbots.omni/config/extension.toml

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ reloadable = true
33
order = 1000 # Make sure all .dlls are loaded before this extension
44

55
[package]
6-
version = "2.7.1"
6+
version = "2.10.1"
77
category = "Simulation"
88
title = "Wandelbots NOVA"
99
description = "Simulate your robotics cell running on Wandelbots NOVA."
@@ -31,20 +31,28 @@ icon = "data/icon.png"
3131

3232

3333
[dependencies]
34-
"omni.isaac.core" = {}
35-
"omni.isaac.conveyor" = {}
34+
"wandelbots.usd" = { version = "1.1.3" }
35+
"isaacsim.core.api" = {}
36+
"isaacsim.core.prims" = {}
37+
"isaacsim.core.utils" = {}
38+
"isaacsim.gui.components"= {}
39+
"isaacsim.asset.gen.conveyor" = {}
3640
'omni.services.core' = {}
37-
"omni.isaac.cloner" = {}
41+
"isaacsim.core.cloner" = {}
3842
'omni.services.client' = {}
3943
'omni.services.usd' = {}
4044
"omni.services.transport.server.base" = {}
4145
"omni.services.transport.server.http" = {}
4246
"omni.services.transport.client.http_async" = {}
4347
"omni.kit.test" = {}
4448
"omni.graph" = {}
45-
"wandelbots.usd" = { version = "1.1.3" }
4649
"omni.kit.clipboard" = {}
47-
50+
"omni.ui" = {}
51+
"omni.kit.menu.utils" = {}
52+
"omni.replicator.core" = {}
53+
"isaacsim.sensors.camera" = {}
54+
"omni.isaac.ml_archive" = {}
55+
"omni.kit.property.usd" = {}
4856

4957
[settings]
5058
exts."omni.services.transport.server.http".https.enabled = false
@@ -65,3 +73,9 @@ exclude = ["Ogn*Database.py"]
6573

6674
[[python.module]]
6775
name = "wandelbots.omni"
76+
77+
[[test]]
78+
name = "startup"
79+
pythonTests.include = []
80+
_startup_only_test = true
81+
timeout = 3600
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
httpx==0.28.1
22
scikit-learn==1.6.1
3-
wandelbots-api-client==25.8.0.dev71
3+
wandelbots-api-client==25.9.0rc3
44
python-decouple==3.8
55
tenacity==9.1.2

exts/wandelbots.omni/docs/CHANGELOG.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,47 @@
11
# Changelog - Wandelbots NOVA x Nvidia Isaac Sim
22

3+
## 2.10.1 (2025-10-22)
4+
5+
### Bug Fixes
6+
7+
* Fixed fetch of rigid body pose
8+
9+
## 2.10.0 (2025-10-22)
10+
11+
### Features
12+
13+
* **CSI-2113:** Added context menu for nova tcp creation
14+
15+
## 2.9.0 (2025-10-22)
16+
17+
### Features
18+
19+
* **CSI-2110:** Added collision export and action planner ui (beta)
20+
21+
## 2.8.1 (2025-10-21)
22+
23+
### Bug Fixes
24+
25+
* Copy examples to new location.
26+
27+
## 2.8.0 (2025-10-20)
28+
29+
### Features
30+
31+
* Remove deprecated dependencies from omni.isaac and drop support for 4.2.0
32+
33+
## 2.7.3 (2025-10-14)
34+
35+
### Bug Fixes
36+
37+
* Fixed version check for minimal nova version
38+
39+
## 2.7.2 (2025-10-13)
40+
41+
### Bug Fixes
42+
43+
* Fixed blocking extension ref on shutdown (warning)
44+
345
## 2.7.1 (2025-09-18)
446

547
### Bug Fixes

exts/wandelbots.omni/premake5.lua

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- Use folder name to build extension name and tag. Version is specified explicitly.
2+
local ext = get_current_extension_info()
3+
4+
project_ext (ext)
5+
6+
-- Link only those files and folders into the extension target directory
7+
repo_build.prebuild_link {
8+
{ "data", ext.target_dir.."/data" },
9+
{ "docs", ext.target_dir.."/docs" },
10+
{ "wandelbots", ext.target_dir.."/wandelbots" },
11+
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

exts/wandelbots.omni/wandelbots/omni/core/collision/collision_export_service.py

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from typing import Literal, cast
1+
from typing import Callable, Literal, cast
2+
import asyncio
23

34
import carb
45
import omni.physx.bindings._physx as physx_bindings
@@ -9,6 +10,13 @@
910
from pxr import Sdf
1011
import wandelbots.omni.core.collision.shapes as collision_shapes
1112
from wandelbots.omni.utils.prims import Pose, PrimUtils, WSPose
13+
import wandelbots_api_client.v2 as wb
14+
import wandelbots_api_client.v2.models as wb_models
15+
from wandelbots.omni.utils.api import get_api_client_from_config
16+
from wandelbots.omni.utils.auth import get_auth_token
17+
from wandelbots.omni.utils.scene import SceneUtils
18+
from wandelbots.omni.manipulators import get_motion_group_configuration_from_prim
19+
from .utils import to_nova_collider
1220

1321

1422
class SphereSweepParameters(pydantic.BaseModel):
@@ -217,6 +225,107 @@ def on_sweep_hit(hit: physx_bindings.SweepHit) -> bool:
217225
if collider is not None
218226
}
219227

228+
async def export_collision_sweep_to_nova(
229+
self,
230+
reference_prim: Usd.Prim,
231+
motion_group_prim: Usd.Prim,
232+
sweep_parameters: SweepParameters,
233+
collision_setup_id: str,
234+
tcp_id: str,
235+
tcp_sphere_radius: float,
236+
progress_callback_fn: Callable[[float], None],
237+
self_collision: bool = True,
238+
) -> dict[str, wb_models.Collider]:
239+
reference_pose = PrimUtils.get_prim_pose(
240+
reference_prim.GetPath().pathString, coordinate_system="world"
241+
)
242+
243+
motion_group = get_motion_group_configuration_from_prim(motion_group_prim)
244+
if progress_callback_fn:
245+
progress_callback_fn(0.1)
246+
247+
timeline, _ = SceneUtils.check_simulation()
248+
if not timeline.is_playing():
249+
timeline.play()
250+
251+
while timeline.is_stopped():
252+
# waiting for the timeline to start
253+
await asyncio.sleep(0.1)
254+
255+
colliders = get_collision_export_service().collision_sweep(
256+
stage=motion_group_prim.GetStage(),
257+
sweep_args=sweep_parameters,
258+
reference_prim_pose=reference_pose,
259+
)
260+
colliders = {
261+
shape_id: to_nova_collider(shape) for shape_id, shape in colliders.items()
262+
}
263+
carb.log_info(f"Found {len(colliders)} colliders.")
264+
if progress_callback_fn:
265+
progress_callback_fn(0.5)
266+
267+
stream_config = motion_group.motion_stream_configuration
268+
async with get_api_client_from_config(
269+
stream_config.get_api_configuration(token=get_auth_token(), version="v2")
270+
) as api:
271+
collision_setup_api = wb.StoreCollisionSetupsApi(api)
272+
273+
motion_group_description: wb_models.MotionGroupDescription = (
274+
await wb.MotionGroupApi(api).get_motion_group_description(
275+
cell=stream_config.cell,
276+
controller=stream_config.controller,
277+
motion_group=stream_config.motion_group,
278+
)
279+
)
280+
281+
link_chain = await wb.MotionGroupModelsApi(
282+
api
283+
).get_motion_group_collision_model(
284+
motion_group_model=motion_group_description.motion_group_model,
285+
)
286+
287+
tcps = await wb.VirtualControllerApi(api).list_virtual_controller_tcps(
288+
cell=stream_config.cell,
289+
controller=stream_config.controller,
290+
motion_group=stream_config.motion_group,
291+
)
292+
293+
tcp: wb_models.RobotTcp = None
294+
for virtual_tcp in tcps:
295+
if virtual_tcp.id == tcp_id:
296+
tcp = virtual_tcp
297+
break
298+
299+
await collision_setup_api.store_collision_setup(
300+
cell=stream_config.cell,
301+
setup=collision_setup_id,
302+
collision_setup=wb_models.CollisionSetup(
303+
colliders=colliders,
304+
link_chain=link_chain,
305+
tool={
306+
"TCPSphere": wb_models.Collider(
307+
shape=wb_models.ColliderShape(
308+
wb_models.Sphere(
309+
radius=SceneUtils.value_to_millimeters(
310+
tcp_sphere_radius
311+
),
312+
shape_type="sphere",
313+
)
314+
),
315+
pose=wb_models.Pose(
316+
position=tcp.position,
317+
orientation=tcp.orientation,
318+
),
319+
),
320+
},
321+
self_collision_detection=self_collision,
322+
),
323+
)
324+
325+
if progress_callback_fn:
326+
progress_callback_fn(1.0)
327+
return colliders
328+
220329

221330
_collision_export_service = CollisionExportService()
222331

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import wandelbots_api_client.v2 as nova_api
2+
from typing import cast
3+
import wandelbots.omni.core.collision.shapes as collision_shapes
4+
5+
6+
def to_nova_collider(
7+
shape: collision_shapes.Collider,
8+
) -> nova_api.models.Collider:
9+
pose = nova_api.models.Pose(
10+
position=[
11+
shape.pose.position[0],
12+
shape.pose.position[1],
13+
shape.pose.position[2],
14+
],
15+
orientation=[
16+
shape.pose.orientation[0],
17+
shape.pose.orientation[1],
18+
shape.pose.orientation[2],
19+
],
20+
)
21+
22+
if isinstance(shape.shape, collision_shapes.Sphere):
23+
return nova_api.models.Collider(
24+
shape=nova_api.models.ColliderShape(
25+
nova_api.models.Sphere(
26+
radius=shape.shape.radius,
27+
shape_type="sphere",
28+
)
29+
),
30+
pose=pose,
31+
)
32+
elif isinstance(shape.shape, collision_shapes.Box):
33+
return nova_api.models.Collider(
34+
shape=nova_api.models.ColliderShape(
35+
nova_api.models.Box(
36+
size_x=shape.shape.size_x,
37+
size_y=shape.shape.size_y,
38+
size_z=shape.shape.size_z,
39+
shape_type="box",
40+
box_type="FULL",
41+
)
42+
),
43+
pose=pose,
44+
)
45+
elif isinstance(shape.shape, collision_shapes.Capsule):
46+
return nova_api.models.Collider(
47+
shape=nova_api.models.ColliderShape(
48+
nova_api.models.Capsule(
49+
cylinder_height=shape.shape.height,
50+
radius=shape.shape.radius,
51+
shape_type="capsule",
52+
)
53+
),
54+
pose=pose,
55+
)
56+
elif isinstance(shape.shape, collision_shapes.Cylinder):
57+
return nova_api.models.Collider(
58+
shape=nova_api.models.ColliderShape(
59+
nova_api.models.Cylinder(
60+
height=shape.shape.height,
61+
radius=shape.shape.radius,
62+
shape_type="cylinder",
63+
)
64+
),
65+
pose=pose,
66+
)
67+
elif isinstance(shape.shape, collision_shapes.Plane):
68+
return nova_api.models.Collider(
69+
shape=nova_api.models.ColliderShape(
70+
nova_api.models.Plane(shape_type="plane")
71+
),
72+
pose=pose,
73+
)
74+
elif isinstance(shape.shape, collision_shapes.ConvexHull):
75+
return nova_api.models.Collider(
76+
shape=nova_api.models.ColliderShape(
77+
nova_api.models.ConvexHull(
78+
shape_type="convex_hull",
79+
vertices=cast(
80+
collision_shapes.ConvexHull,
81+
shape.shape,
82+
).vertices,
83+
)
84+
),
85+
pose=pose,
86+
)
87+
return None

exts/wandelbots.omni/wandelbots/omni/datatypes.py

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -58,44 +58,6 @@ class RelativePoseMode(str, Enum):
5858
INVERSE_BOTH = "inverse_both"
5959

6060

61-
class ArticulationChainState(BaseModel):
62-
mode: str
63-
signals_mapping: dict[str, Union[bool, float]]
64-
joint_positions: list[float]
65-
joint_velocities: list[float]
66-
67-
class Config:
68-
title = "Articulation Chain State"
69-
70-
71-
class ConveyorState(BaseModel):
72-
mode: str
73-
signals_mapping: dict[str, Union[bool, float]]
74-
velocity: float
75-
direction: Optional[list[float]]
76-
77-
class Config:
78-
title = "Conveyor State"
79-
80-
81-
class SurfaceGripperState(BaseModel):
82-
mode: Literal["open", "close"]
83-
signals_mapping: dict[str, Union[bool, float]]
84-
85-
class Config:
86-
title = "Surface Gripper State"
87-
88-
89-
class AnalogSignal(BaseModel):
90-
id: str
91-
range: list[float]
92-
93-
94-
class MockAnalogSignal(BaseModel):
95-
io: str = Field(example="analog_out[0]")
96-
io_value: Union[bool, float] = Field(example=0.2)
97-
98-
9961
class GhostObjectSource(BaseModel):
10062
name: str
10163
prim_path: str

0 commit comments

Comments
 (0)