Skip to content

Commit 7c8d779

Browse files
authored
ManiSkill Scenic Integration (#400)
* Add interface to ManiSkill simulator * Add optional maniskill dependencies * Format with black
1 parent f0e3e60 commit 7c8d779

File tree

7 files changed

+601
-0
lines changed

7 files changed

+601
-0
lines changed

examples/maniskill/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# ManiSkill Examples
2+
3+
This directory contains example scenarios for the [ManiSkill](https://github.com/haosulab/ManiSkill) robotics simulator.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
model scenic.simulators.maniskill.model
2+
3+
import math
4+
pi = math.pi
5+
6+
# Create ground plane
7+
ground = new Ground with position (0, 0, -0.920)
8+
9+
# Create Panda robot arm with a neutral pose
10+
# Joint angles: [joint1, joint2, joint3, joint4, joint5, joint6, joint7, gripper_left, gripper_right]
11+
panda = new Robot,
12+
with uuid "panda",
13+
with jointAngles [0.0, pi/8, 0.0, -pi/2, 0.0, pi*5/8, pi/4, 0.04, 0.04]
14+
15+
# Create camera positioned to view the robot and cube
16+
camera = new Camera,
17+
at (-0.64, -0.4, 0.758),
18+
with name "base_camera",
19+
with img_width 640,
20+
with img_height 480,
21+
with fov 1.0
22+
23+
# Create a cube in front of the robot (within reach)
24+
cube = new ManiskillObject on ground,
25+
at (0.4, 0.0, 0.035),
26+
with name "target_cube",
27+
with shape BoxShape(),
28+
with width 0.05,
29+
with length 0.05,
30+
with height 0.05,
31+
with color [1.0, 0.5, 0.0, 1.0] # Orange cube
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
model scenic.simulators.maniskill.model
2+
3+
# Create ground plane
4+
ground = new Ground with position (0, 0, -0.920)
5+
6+
# Create three cubes stacked on top of each other
7+
# Bottom cube (red)
8+
cube1 = new ManiskillObject on ground,
9+
at (0, 0, 0.035),
10+
with name "cube1",
11+
with shape BoxShape(),
12+
with width 0.07,
13+
with length 0.07,
14+
with height 0.07,
15+
with color [0.9, 0.1, 0.1, 1.0]
16+
17+
# Middle cube (green)
18+
cube2 = new ManiskillObject on cube1,
19+
with name "cube2",
20+
with shape BoxShape(),
21+
with width 0.07,
22+
with length 0.07,
23+
with height 0.07,
24+
with color [0.1, 0.9, 0.1, 1.0]
25+
26+
# Top cube (blue)
27+
cube3 = new ManiskillObject on cube2,
28+
with name "cube3",
29+
with shape BoxShape(),
30+
with width 0.07,
31+
with length 0.07,
32+
with height 0.07,
33+
with color [0.1, 0.1, 0.9, 1.0]

pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ metadrive = [
5959
"metadrive-simulator@git+https://github.com/metadriverse/metadrive.git@85e5dadc6c7436d324348f6e3d8f8e680c06b4db",
6060
"sumolib >= 1.21.0",
6161
]
62+
maniskill = [
63+
"mani-skill >= 3.0.0b20",
64+
"torch >= 2.0.0",
65+
"sapien >= 3.0.0",
66+
"gymnasium >= 0.29.0",
67+
"coacd >= 1.0.0",
68+
]
6269
test = [ # minimum dependencies for running tests (used for tox virtualenvs)
6370
"pytest >= 7.0.0, <9",
6471
"pytest-cov >= 3.0.0",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""
2+
Interface to the ManiSkill robotics simulator.
3+
"""
4+
5+
# Check if mani_skill is installed and import ManiSkillSimulator only if it is
6+
mani_skill = None
7+
try:
8+
import mani_skill
9+
except ImportError:
10+
pass
11+
if mani_skill:
12+
from .simulator import ManiSkillSimulator
13+
del mani_skill
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""Scenic world model for robotic manipulation scenarios in ManiSkill.
2+
3+
Global Parameters:
4+
render (bool): Whether to render the simulation in a window. If True, it will open
5+
a window and display the simulation. If False (default), the simulation runs headless.
6+
stride (int): Number of simulation steps between action updates. Default is 1.
7+
"""
8+
9+
try:
10+
from scenic.simulators.maniskill.simulator import ManiSkillSimulator
11+
except ModuleNotFoundError:
12+
# for convenience when testing without the mani_skill package
13+
from scenic.core.simulators import SimulatorInterfaceWarning
14+
import warnings
15+
warnings.warn('The "mani-skill" package is not installed; '
16+
'will not be able to run dynamic simulations',
17+
SimulatorInterfaceWarning)
18+
19+
def ManiSkillSimulator(*args, **kwargs):
20+
"""Dummy simulator to allow compilation without the 'mani-skill' package.
21+
22+
:meta private:
23+
"""
24+
raise RuntimeError('the "mani-skill" package is required to run simulations '
25+
'from this scenario')
26+
27+
param render = False
28+
param stride = 1
29+
30+
simulator ManiSkillSimulator(
31+
render=bool(globalParameters.render),
32+
stride=int(globalParameters.stride),
33+
)
34+
35+
class ManiskillObject(Object):
36+
"""Base class for ManiSkill objects.
37+
38+
Properties:
39+
visualFilename (str or None): Path to a visual mesh file (e.g., .glb, .obj, .usdz).
40+
visualScale (tuple): Scale factor for the visual mesh as (x, y, z).
41+
visualOffset (tuple): Offset for the visual mesh as (x, y, z) to match visual and collision meshes.
42+
kinematic (bool): If True, the object is kinematic (fixed in place).
43+
"""
44+
visualFilename: None
45+
visualScale: (1, 1, 1)
46+
visualOffset: (0, 0, 0)
47+
width: 1
48+
length: 1
49+
height: 1
50+
color: [0.8, 0.8, 0.8, 1.0]
51+
kinematic: False
52+
53+
class Ground(ManiskillObject):
54+
"""The default ground plane from ManiSkill.
55+
56+
This creates a large flat ground plane using ManiSkill's built-in ground builder.
57+
The ground is always kinematic (fixed in place).
58+
"""
59+
name: "ground"
60+
shape: BoxShape()
61+
width: 100
62+
length: 100
63+
height: 0.001
64+
position: (0, 0, -0.0005)
65+
kinematic: True
66+
visualFilename: None
67+
isSimpleGround: True # Specify to ManiSkill that this is the ground plane
68+
69+
class Robot(Object):
70+
"""Robot object (Panda arm by default).
71+
72+
This class represents a robot in the scene. The robot is not physically generated
73+
in the scene (skipGeneration=True) but is used to configure the robot's initial state.
74+
75+
Properties:
76+
uuid (str): Robot type identifier. Default is "panda" for the Franka Emika Panda arm.
77+
jointAngles (list): Initial joint angles for the robot. If empty, uses a default configuration.
78+
"""
79+
position: (10, 0, 0) # Make scenic ignore it for collision checking for now
80+
name: "actor"
81+
uuid: "panda"
82+
jointAngles: []
83+
skipGeneration: True # Don't generate this object in the scene
84+
85+
class Camera(OrientedPoint):
86+
"""Camera configuration for the scene.
87+
88+
Cameras are not physical objects but define viewpoints for rendering and observation.
89+
90+
Properties:
91+
img_width (int): Image width in pixels. Default is 640.
92+
img_height (int): Image height in pixels. Default is 480.
93+
fov (float): Field of view in radians. Default is 1.0.
94+
near (float): Near clipping plane distance. Default is 0.01.
95+
far (float): Far clipping plane distance. Default is 100.0.
96+
shader_pack (str): Shader pack to use for rendering. Default is "rt" (ray tracing).
97+
"""
98+
name: "camera"
99+
img_width: 640
100+
img_height: 480
101+
fov: 1.0
102+
near: 0.01
103+
far: 100.0
104+
shader_pack: "rt"
105+
skipGeneration: True # Don't generate this as a physical object

0 commit comments

Comments
 (0)