This repository contains a collection of object models for simulation, along with helper scripts for downloading, generating and tidying the required files. In particular, they have been tuned and tested in pybullet.
The list of available objects includes:
- Primitive Objects
- Random Objects
- Superquadric Objects
- YCB Objects
- Google Scanned Objects
- Evolved Grasping Analysis Dataset (EGAD)
- Gibson Objects
- ShapeNetCore.v2
Each object has the following files:
-
Textured mesh for visualization (
.obj
). -
Simplified mesh for collision (
.obj
). These meshes can be basic shapes or a V-HACD decomposition of the textured mesh, depending on the complexity of the object shape. These are generally generated using the obj2urdf package. -
URDF file to load the object into the simulation.
-
TODO: add accurate mass and dynamics values to urdfs where possible.
The repo requires a python version >= 3. It can be installed with pip by doing:
$ git clone https://github.com/eleramp/pybullet-object-models.git
$ pip3 install -e pybullet-object-models/
It has been tested only on Ubuntu 18.04 LTS.
- A set of simple objects created in blender.
- Set of randomly generated objects from the pybullet repo.
-
Custom objects with a superquadric (superellipsoid) shape, generated using the pygalmesh tool.
-
Tools are provided for generating your own Superquadric object models. This requires using the pygalmesh tool which can be installed the tools by doing:
$ conda create -n env_pygalmesh python=3.8
$ conda activate env_pygalmesh
$ conda install -c conda-forge pygalmesh
$ pip install trimesh #this is used to interactively fix a bug in the generated meshes, related to the inverted surface normals
Using conda to install the tool is not probably the ideal option for some people but it is the best and easiest way at the moment, as pointed out in its github repo.
We provide information about how to generate custom objects by using the pygalmesh tool.
- Navigate to the
superquadric_objects
folder:
$ cd pybullet-object-models/pybullet_object_models/superquadric_objects/
- Activate the conda pygalmesh environment:
$ conda activate /path/to/env_pygalmesh
- Run the script to generate the meshes:
$ python generate_superquadric_mesh.py
The output meshes are saved according to the following tree:
sq_l1_l2_l3_l4_l5/
└── model.obj
- Run the script to generate the URDF model for each new superquadric object:
$ python generate_urdf_model.py
They are saved inside each superquadric object folder as follow:
sq_l1_l2_l3_l4_l5/
├── model.obj
└── model.urdf
The output meshes have a superquadric shape defined according to the inside-outside
function:
F = ( (x / λ1) ** (2/λ5) + (y / λ2) ** (2/λ5) ) ** (λ5/λ4) + (z / λ3) ** (2/λ4)
By default, the generate_superquadric_mesh.py
creates 100 superquadric meshes, with λ4, λ5
varying in the range (0.1, 1.9, step = 0.2)
You can of course modify the script to reduce the number of generated superquadric meshes as you like.
-
The near full set of YCB objects available for download here.
-
This is too large to store in this repo (approx 1Gb), a tool for dowloading these objects is available here, a very slightly modified version of this script with a function for removing numbers from the directory names is included in this repo.
-
The downloaded files can then be copied to the
ycb_objects
directory within this repo. This should contain the downloaded files, along with__init__.py
and_prototype.urdf
for generating the urdf files using obj2urdf. -
To generate urdf files from the downloaded .obj files run
build_object_urdfs.py
with the directoy name set correctly, this will also generate convex decompositions, more details are provided here. -
Additionally, there are 3 SDF files, each loading some YCB objects arranged according to a specific layout. The layouts reproduce the layouts of the GRASPA-benchmark. TODO: fix broken orientations on layouts.
-
Over 1000 "common" household objects that have been 3D scanned for use in robotic simulation and synthetic perception research from Google Research.
-
This is too large to store on this repo, the full set of objects can be downloaded using this repo.
-
I have limited expierience with Bazel but what worked for me was
git clone https://github.com/tommymchugh/gso_downloader.git
cd gso_downloader/
bazel build ...
./bazel-bin/src/download
-
This started downloading all the required files into my home directory. Warning, this is over 10GB.
-
The downloaded files can then be copied to the
google_scanned_objects
directory within this repo. This should contain the downloaded files (in the numbered directories), along with__init__.py
and_prototype.urdf
for generating the urdf files using obj2urdf. -
A script for renaming the directories, moving textures and clearing empty directories is provided in
tidy_google_objects.py
. Be careful when using as this will be removing/renaming a large number of files, I would reccomended commenting out any code that alters files and monitoring beforehand to make sure it is working as intended before use. -
This comes with sdf files that can directly be used in pybullet, however for consistency I find automatically generating urdf files using the obj2urdf package helpful. A script to do this is provided in
build_object_urdfs.py
(change directoy name), this will also generate convex decompositions, more details are provided in the linked repo. Warning, takes a while to run for the full google_scanned_objects set.
Evolved Grasping Analysis Dataset (EGAD), comprising over 2000 generated objects aimed at training and evaluating robotic visual grasp detection algorithms. See more details here and here.
To set up these objects:
-
Follow the steps to download the objects available on the project website (https://dougsm.github.io/egad/).
-
Place the extracted files in the egad directory under
egad/egad_train_set
andegad/egad_eval_set
. -
Run
python tidy_egad.py
to move all.obj
files into their own directories. -
Copy the
_protype.urdf
and__init__.py
files from/egad/
into theegad_eval_set
andegad_train_set
directories. -
Run
python build_object_urdfs.py
with the correct directories uncommented. Warning, this will take a while for the full 2000 object training set. -
Run
python demo_load_object.py -object_set=egad_eval
or-object_set=egad_train
to check things work correctly.
-
Sets of objects for visual and haptic shape perception (see here for more info).
-
Feelies: Artificial shapes for vision and haptic experiments.
-
Glavens: Shapes for haptic experiments of progressive complexity.
-
BellPeppers: Natural shapes for vision and haptic experiments
-
Some of the meshes have been simplified to reduce the number of triangles.
Please make sure to have the python library point-cloud-utils
and trimesh
installed. This ensures the etxraction of watertight meshes (if requires). Please read below for citation.
- The dataset is available on the ShapeNet website (https://shapenet.org/).
To extract .urdf
files from the ShapeNetCoreV2
dataset, please follow these instructions:
-
Download the
ShapeNetCoreV2
dataset and place it underpybullet_object_models/shapenet/
. This download defaults the dataset folder name asShapeNetCore.v2
. Please rename the folder asShapeNetCoreV2
. -
Copy the
_protype.urdf
and__init__.py
files from/egad/
under theShapeNetCoreV2
directory. -
Once the previous two steps are completed, you should have the following tree:
pybullet_object_models
├── shapenet
│ ├── ShapeNetCoreV2
│ │ ├── _prototype.urdf
│ │ ├── ... # example: 02942699
| | | ├── ... # example: 1ab3abb5c090d9b68e940c4e64a94e1e
- In the project root folder, run
python build_shapenet_urdfs.py
. This generates a new folder calledShapeNetCoreV2urdf
, which has the same structure as the original folderShapeNetCoreV2
. The script extracts.urdf
files from the ShapeNet.obj
files. The extracted files, renamedmodel.urdf
, can be found under each object ID directory in the new folder. In addition, the originalmodel_normalized.obj
is copied to the new folder. For example:
pybullet_object_models
├── shapenet
│ ├── ShapeNetCoreV2urdf <-- new folder
│ │ ├── _prototype.urdf
│ │ ├── 02942699
| | | ├── 1ab3abb5c090d9b68e940c4e64a94e1e
| | | | ├── model.urdf <-- EXTRACTED .URDF
| | | | ├── model.obj
- Some applications require watertight meshes. An example is DeepSDF. If a watertight mesh is required, please run
python build_shapenet_urdfs.py --watertight
. This first generates a watertight mesh and then extract its urdf. The generated dataset has the same structure as described above, butmodel.obj
andmodel.urdf
are watertight.
Example scripts for importing the objects into pybullet are provided in the examples folder. To run these cd into the examples
directory and run python demo_load_object.py
. Use the -object_set=
argument to load from a given object set, currently this can be selected from primitive
, random
, ycb
, superquadric
or google
if setup correctly.
We use the convention that the object name is the name of the directory, and the urdf file is titled model.urdf
. The function getDataPath()
and getModelList()
can be used to help load objects. Here is a code snippet for importing objects.
import os
import random
from pybullet_object_models import primitive_objects
from pybullet_object_models import random_objects
from pybullet_object_models import ycb_objects
from pybullet_object_models import superquadric_objects
from pybullet_object_models import google_scanned_objects
## Get the path to the objects inside each package
# data_path = primitive_objects.getDataPath()
# data_path = random_objects.getDataPath()
data_path = ycb_objects.getDataPath()
# data_path = superquadric_objects.getDataPath()
# data_path = google_scanned_objects.getDataPath()
## With this path you can access to the object files, e.g. its URDF model
obj_name = 'banana'
## or a full list of the available objects can be found with
# model_list = primitive_objects.getModelList()
# model_list = random_objects.getModelList()
model_list = ycb_objects.getModelList()
# model_list = superquadric_objects.getModelList()
# model_list = google_scanned_objects.getModelList()
## from which an object can be selected
object_name = random.choice(model_list)
## the full path is then
path_to_urdf = os.path.join(data_path, object_name, "model.urdf")
## Check by printing
print(path_to_urdf)
Here is a Python example to load the objects inside the pybullet simulation:
import os
import time
import pybullet as p
import pybullet_data
from pybullet_object_models import ycb_objects
## Open GUI and set pybullet_data in the path
p.connect(p.GUI)
p.resetDebugVisualizerCamera(3, 90, -30, [0.0, -0.0, -0.0])
p.setTimeStep(1 / 240.)
## Load plane contained in pybullet_data
planeId = p.loadURDF(os.path.join(pybullet_data.getDataPath(), "plane.urdf"))
## Load the object
obj_id = p.loadURDF(os.path.join(ycb_objects.getDataPath(), 'banana', "model.urdf"), [1., 0.0, 0.8])
## Start pybullet loop
p.setGravity(0, 0, -9.8)
while 1:
p.stepSimulation()
time.sleep(1./240)
If this library contributes to an academic publication, please consider citing the following resources:
@software{trimesh,
author = {{Dawson-Haggerty et al.}},
title = {trimesh},
url = {https://trimsh.org/},
version = {3.2.0},
date = {2019-12-8},
}
If you have used the Shapenet URDF extraction tool:
@misc{point-cloud-utils,
title = {Point Cloud Utils},
author = {Francis Williams},
note = {https://www.github.com/fwilliams/point-cloud-utils},
year = {2022}
}